mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-01 07:30:33 +00:00
[IR] Introduce a non-integral pointer type
Summary: This change adds a `ni` specifier in the `datalayout` string to denote pointers in some given address spaces as "non-integral", and adds some typing rules around these special pointers. Reviewers: majnemer, chandlerc, atrick, dberlin, eli.friedman, tstellarAMD, arsenm Subscribers: arsenm, mcrosier, llvm-commits Differential Revision: https://reviews.llvm.org/D22488 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277085 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b17a45cae0
commit
1c20b71db8
@ -546,6 +546,26 @@ An example of an identified structure specification is:
|
||||
Prior to the LLVM 3.0 release, identified types were structurally uniqued. Only
|
||||
literal types are uniqued in recent versions of LLVM.
|
||||
|
||||
.. _nointptrtype:
|
||||
|
||||
Non-Integral Pointer Type
|
||||
-------------------------
|
||||
|
||||
Note: non-integral pointer types are a work in progress, and they should be
|
||||
considered experimental at this time.
|
||||
|
||||
LLVM IR optionally allows the frontend to denote pointers in certain address
|
||||
spaces as "non-integral" via the :ref:```datalayout``
|
||||
string<langref_datalayout>`. Non-integral pointer types represent pointers that
|
||||
have an *unspecified* bitwise representation; that is, the integral
|
||||
representation may be target dependent or unstable (not backed by a fixed
|
||||
integer).
|
||||
|
||||
``inttoptr`` instructions converting integers to non-integral pointer types are
|
||||
ill-typed, and so are ``ptrtoint`` instructions converting values of
|
||||
non-integral pointer types to integers. Vector versions of said instructions
|
||||
are ill-typed as well.
|
||||
|
||||
.. _globalvars:
|
||||
|
||||
Global Variables
|
||||
@ -1831,6 +1851,10 @@ as follows:
|
||||
``n32:64`` for PowerPC 64, or ``n8:16:32:64`` for X86-64. Elements of
|
||||
this set are considered to support most general arithmetic operations
|
||||
efficiently.
|
||||
``ni:<address space0>:<address space1>:<address space2>...``
|
||||
This specifies pointer types with the specified address spaces
|
||||
as :ref:`Non-Integral Pointer Type <nointptrtype>` s. The ``0``
|
||||
address space cannot be specified as non-integral.
|
||||
|
||||
On every specification that takes a ``<abi>:<pref>``, specifying the
|
||||
``<pref>`` alignment is optional. If omitted, the preceding ``:``
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define LLVM_IR_DATALAYOUT_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Pass.h"
|
||||
@ -144,6 +145,10 @@ private:
|
||||
// The StructType -> StructLayout map.
|
||||
mutable void *LayoutMap;
|
||||
|
||||
/// Pointers in these address spaces are non-integral, and don't have a
|
||||
/// well-defined bitwise representation.
|
||||
SmallVector<unsigned, 8> NonIntegralAddressSpaces;
|
||||
|
||||
void setAlignment(AlignTypeEnum align_type, unsigned abi_align,
|
||||
unsigned pref_align, uint32_t bit_width);
|
||||
unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width,
|
||||
@ -199,6 +204,7 @@ public:
|
||||
LegalIntWidths = DL.LegalIntWidths;
|
||||
Alignments = DL.Alignments;
|
||||
Pointers = DL.Pointers;
|
||||
NonIntegralAddressSpaces = DL.NonIntegralAddressSpaces;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -320,6 +326,18 @@ public:
|
||||
/// the backends/clients are updated.
|
||||
unsigned getPointerSize(unsigned AS = 0) const;
|
||||
|
||||
/// Return the address spaces containing non-integral pointers. Pointers in
|
||||
/// this address space don't have a well-defined bitwise representation.
|
||||
ArrayRef<unsigned> getNonIntegralAddressSpaces() const {
|
||||
return NonIntegralAddressSpaces;
|
||||
}
|
||||
|
||||
bool isNonIntegralPointerType(PointerType *PT) const {
|
||||
ArrayRef<unsigned> NonIntegralSpaces = getNonIntegralAddressSpaces();
|
||||
return find(NonIntegralSpaces, PT->getAddressSpace()) !=
|
||||
NonIntegralSpaces.end();
|
||||
}
|
||||
|
||||
/// Layout pointer size, in bits
|
||||
/// FIXME: The defaults need to be removed once all of
|
||||
/// the backends/clients are updated.
|
||||
|
@ -182,6 +182,7 @@ void DataLayout::reset(StringRef Desc) {
|
||||
BigEndian = false;
|
||||
StackNaturalAlign = 0;
|
||||
ManglingMode = MM_None;
|
||||
NonIntegralAddressSpaces.clear();
|
||||
|
||||
// Default alignments
|
||||
for (const LayoutAlignElem &E : DefaultAlignments) {
|
||||
@ -234,6 +235,19 @@ void DataLayout::parseSpecifier(StringRef Desc) {
|
||||
StringRef &Tok = Split.first; // Current token.
|
||||
StringRef &Rest = Split.second; // The rest of the string.
|
||||
|
||||
if (Tok == "ni") {
|
||||
do {
|
||||
Split = split(Rest, ':');
|
||||
Rest = Split.second;
|
||||
unsigned AS = getInt(Split.first);
|
||||
if (AS == 0)
|
||||
report_fatal_error("Address space 0 can never be non-integral");
|
||||
NonIntegralAddressSpaces.push_back(AS);
|
||||
} while (!Rest.empty());
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
char Specifier = Tok.front();
|
||||
Tok = Tok.substr(1);
|
||||
|
||||
|
@ -2409,6 +2409,11 @@ void Verifier::visitPtrToIntInst(PtrToIntInst &I) {
|
||||
|
||||
Assert(SrcTy->getScalarType()->isPointerTy(),
|
||||
"PtrToInt source must be pointer", &I);
|
||||
|
||||
if (auto *PTy = dyn_cast<PointerType>(SrcTy->getScalarType()))
|
||||
Assert(!M->getDataLayout().isNonIntegralPointerType(PTy),
|
||||
"ptrtoint not supported for non-integral pointers");
|
||||
|
||||
Assert(DestTy->getScalarType()->isIntegerTy(),
|
||||
"PtrToInt result must be integral", &I);
|
||||
Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "PtrToInt type mismatch",
|
||||
@ -2433,6 +2438,11 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) {
|
||||
"IntToPtr source must be an integral", &I);
|
||||
Assert(DestTy->getScalarType()->isPointerTy(),
|
||||
"IntToPtr result must be a pointer", &I);
|
||||
|
||||
if (auto *PTy = dyn_cast<PointerType>(DestTy->getScalarType()))
|
||||
Assert(!M->getDataLayout().isNonIntegralPointerType(PTy),
|
||||
"inttoptr not supported for non-integral pointers");
|
||||
|
||||
Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "IntToPtr type mismatch",
|
||||
&I);
|
||||
if (SrcTy->isVectorTy()) {
|
||||
|
45
test/Verifier/non-integral-pointers.ll
Normal file
45
test/Verifier/non-integral-pointers.ll
Normal file
@ -0,0 +1,45 @@
|
||||
; RUN: not opt -verify < %s 2>&1 | FileCheck %s
|
||||
|
||||
target datalayout = "e-ni:4:6"
|
||||
|
||||
define i64 @f_0(i8 addrspace(4)* %ptr) {
|
||||
; CHECK: ptrtoint not supported for non-integral pointers
|
||||
%val = ptrtoint i8 addrspace(4)* %ptr to i64
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define <4 x i64> @f_1(<4 x i8 addrspace(4)*> %ptr) {
|
||||
; CHECK: ptrtoint not supported for non-integral pointers
|
||||
%val = ptrtoint <4 x i8 addrspace(4)*> %ptr to <4 x i64>
|
||||
ret <4 x i64> %val
|
||||
}
|
||||
|
||||
define i64 @f_2(i8 addrspace(3)* %ptr) {
|
||||
; Negative test
|
||||
%val = ptrtoint i8 addrspace(3)* %ptr to i64
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i8 addrspace(4)* @f_3(i64 %integer) {
|
||||
; CHECK: inttoptr not supported for non-integral pointers
|
||||
%val = inttoptr i64 %integer to i8 addrspace(4)*
|
||||
ret i8 addrspace(4)* %val
|
||||
}
|
||||
|
||||
define <4 x i8 addrspace(4)*> @f_4(<4 x i64> %integer) {
|
||||
; CHECK: inttoptr not supported for non-integral pointers
|
||||
%val = inttoptr <4 x i64> %integer to <4 x i8 addrspace(4)*>
|
||||
ret <4 x i8 addrspace(4)*> %val
|
||||
}
|
||||
|
||||
define i8 addrspace(3)* @f_5(i64 %integer) {
|
||||
; Negative test
|
||||
%val = inttoptr i64 %integer to i8 addrspace(3)*
|
||||
ret i8 addrspace(3)* %val
|
||||
}
|
||||
|
||||
define i64 @f_6(i8 addrspace(6)* %ptr) {
|
||||
; CHECK: ptrtoint not supported for non-integral pointers
|
||||
%val = ptrtoint i8 addrspace(6)* %ptr to i64
|
||||
ret i64 %val
|
||||
}
|
Loading…
Reference in New Issue
Block a user