Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -546,6 +546,24 @@ 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 specify a non-integral pointer type +via the :ref:```datalayout`` string`. Values of the +non-integral pointer type represent pointers that don't have a *stable* bitwise +representation; that is at runtime they may not be backed by a fixed unchanging +pointer-width integer. + +``inttoptr`` instructions converting integers to the non-integral pointer type +are ill-typed, and so are ``ptrtoint`` instructions converting values of the +non-integral pointer type to integers. + .. _globalvars: Global Variables @@ -1831,6 +1849,9 @@ ``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:
`` + This specifies the pointer type with the address space ``
`` + as a :ref:`Non-Integral Pointer Type `. On every specification that takes a ``:``, specifying the ```` alignment is optional. If omitted, the preceding ``:`` Index: include/llvm/IR/DataLayout.h =================================================================== --- include/llvm/IR/DataLayout.h +++ include/llvm/IR/DataLayout.h @@ -144,6 +144,10 @@ // The StructType -> StructLayout map. mutable void *LayoutMap; + /// Pointers in this address space are non-integral, and don't have a stable + /// bitwise representation. + unsigned NonIntegralAddressSpace; + 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 +203,7 @@ LegalIntWidths = DL.LegalIntWidths; Alignments = DL.Alignments; Pointers = DL.Pointers; + NonIntegralAddressSpace = DL.NonIntegralAddressSpace; return *this; } @@ -320,6 +325,19 @@ /// the backends/clients are updated. unsigned getPointerSize(unsigned AS = 0) const; + /// Return the address space of non-integral pointers. Pointers in this + /// address space don't have a stable bitwise representation. Returns \c 0 if + /// no address space is designated as non-integral (the \c 0 address space + /// never non-integral). + unsigned getNonIntegralAddressSpace() const { + return NonIntegralAddressSpace; + } + + bool isNonIntegralPointerType(PointerType *PT) const { + unsigned AS = getNonIntegralAddressSpace(); + return AS && PT->getAddressSpace() == AS; + } + /// Layout pointer size, in bits /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. Index: lib/IR/DataLayout.cpp =================================================================== --- lib/IR/DataLayout.cpp +++ lib/IR/DataLayout.cpp @@ -182,6 +182,7 @@ BigEndian = false; StackNaturalAlign = 0; ManglingMode = MM_None; + NonIntegralAddressSpace = 0; // Default alignments for (const LayoutAlignElem &E : DefaultAlignments) { @@ -222,6 +223,7 @@ void DataLayout::parseSpecifier(StringRef Desc) { StringRepresentation = Desc; + bool SeenNonIntegralAddrspace = false; while (!Desc.empty()) { // Split at '-'. std::pair Split = split(Desc, '-'); @@ -234,6 +236,19 @@ StringRef &Tok = Split.first; // Current token. StringRef &Rest = Split.second; // The rest of the string. + if (Tok == "ni") { + if (SeenNonIntegralAddrspace) + report_fatal_error( + "Only one non-integral addrspace specification is allowed"); + if (Rest.getAsInteger(10, NonIntegralAddressSpace)) + report_fatal_error("Unexpected non-integral address space"); + if (NonIntegralAddressSpace == 0) + report_fatal_error("Address space 0 can never be non-integral"); + + SeenNonIntegralAddrspace = true; + continue; + } + char Specifier = Tok.front(); Tok = Tok.substr(1); Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -2409,6 +2409,11 @@ Assert(SrcTy->getScalarType()->isPointerTy(), "PtrToInt source must be pointer", &I); + + if (auto *PTy = dyn_cast(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 @@ "IntToPtr source must be an integral", &I); Assert(DestTy->getScalarType()->isPointerTy(), "IntToPtr result must be a pointer", &I); + + if (auto *PTy = dyn_cast(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()) { Index: test/Verifier/gc-references.ll =================================================================== --- /dev/null +++ test/Verifier/gc-references.ll @@ -0,0 +1,27 @@ +; RUN: not opt -verify < %s 2>&1 | FileCheck %s + +target datalayout = "e-ni:4" + +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 i64 @f_1(i8 addrspace(3)* %ptr) { +; Negative test + %val = ptrtoint i8 addrspace(3)* %ptr to i64 + ret i64 %val +} + +define i8 addrspace(4)* @f_2(i64 %integer) { +; CHECK: inttoptr not supported for non-integral pointers + %val = inttoptr i64 %integer to i8 addrspace(4)* + ret i8 addrspace(4)* %val +} + +define i8 addrspace(3)* @f_3(i64 %integer) { +; Negative test + %val = inttoptr i64 %integer to i8 addrspace(3)* + ret i8 addrspace(3)* %val +}