[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:
Sanjoy Das 2016-07-28 23:43:38 +00:00
parent b17a45cae0
commit 1c20b71db8
5 changed files with 111 additions and 0 deletions

View File

@ -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 ``:``

View File

@ -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.

View File

@ -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);

View File

@ -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()) {

View 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
}