summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/docs/LangRef.rst24
-rw-r--r--llvm/include/llvm/IR/DataLayout.h18
-rw-r--r--llvm/lib/IR/DataLayout.cpp14
-rw-r--r--llvm/lib/IR/Verifier.cpp10
-rw-r--r--llvm/test/Verifier/non-integral-pointers.ll45
5 files changed, 111 insertions, 0 deletions
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index d4d0ee325c9..7f69d693294 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -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 ``:``
diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h
index 173121b72ff..2b481fb6607 100644
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -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.
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index 20a15fb8831..d7ed73015ee 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -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);
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 659a22428e2..7815207fd9f 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -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()) {
diff --git a/llvm/test/Verifier/non-integral-pointers.ll b/llvm/test/Verifier/non-integral-pointers.ll
new file mode 100644
index 00000000000..221dd350522
--- /dev/null
+++ b/llvm/test/Verifier/non-integral-pointers.ll
@@ -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
+}
OpenPOWER on IntegriCloud