Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -546,6 +546,21 @@ Prior to the LLVM 3.0 release, identified types were structurally uniqued. Only literal types are uniqued in recent versions of LLVM. +.. _gcreftype: + +GC Reference Type +----------------- + +Note: GC reference types are a work in progress, and they should be +considered experimental at this time. + +LLVM IR optionally allows the frontend to specify a GC reference type via the +:ref:```datalayout`` string`. Values of the GC reference type +represent pointers into a heap managed by a compacting garbage collector, and don't have +have a well defined bitwise representation. ``inttoptr`` converting integers to the GC +reference type is ill-typed, and so is ``ptrtoint`` converting values of the GC reference +type to integers. + .. _globalvars: Global Variables @@ -1831,6 +1846,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. +``gc:
`` + This specifies the pointer type with the address space ``
`` + as a :ref:`GC Reference 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 count as GC references, and have some + /// special properties. + unsigned GCReferenceAddressSpace; + 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; + GCReferenceAddressSpace = DL.GCReferenceAddressSpace; return *this; } @@ -320,6 +325,19 @@ /// the backends/clients are updated. unsigned getPointerSize(unsigned AS = 0) const; + /// Return the address space of GC references. Pointers in this address space + /// are GC references, and have some special properties. Returns \c 0 if no + /// address space is designated for GC references (the \c 0 address space + /// never denotes GC references). + unsigned getGCReferenceAddressSpace() const { + return GCReferenceAddressSpace; + } + + bool isGCReferenceType(PointerType *PT) const { + unsigned AS = getGCReferenceAddressSpace(); + 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; + GCReferenceAddressSpace = 0; // Default alignments for (const LayoutAlignElem &E : DefaultAlignments) { @@ -222,6 +223,7 @@ void DataLayout::parseSpecifier(StringRef Desc) { StringRepresentation = Desc; + bool SeenGCRefAddrspace = false; while (!Desc.empty()) { // Split at '-'. std::pair Split = split(Desc, '-'); @@ -371,6 +373,14 @@ break; } break; + case 'g': + if (SeenGCRefAddrspace) + report_fatal_error( + "Only one GC reference addrspace specification is allowed"); + if (Rest.getAsInteger(10, GCReferenceAddressSpace)) + report_fatal_error("Unexpected GC reference address space"); + SeenGCRefAddrspace = true; + break; default: report_fatal_error("Unknown specifier in datalayout string"); break; 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().isGCReferenceType(PTy), + "ptrtoint not supported for GC references"); + 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().isGCReferenceType(PTy), + "inttoptr not supported for GC references"); + 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-gc:4" + +define i64 @f_0(i8 addrspace(4)* %ptr) { +; CHECK: ptrtoint not supported for GC references + %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 GC references + %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 +}