diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h index 8f7ab2f9df389..93bd519f5727d 100644 --- a/llvm/include/llvm/IR/DataLayout.h +++ b/llvm/include/llvm/IR/DataLayout.h @@ -78,7 +78,11 @@ class DataLayout { Align ABIAlign; Align PrefAlign; uint32_t IndexBitWidth; - + /// Pointers in this address space don't have a well-defined bitwise + /// representation (e.g. may be relocated by a copying garbage collector). + /// Additionally, they may also be non-integral (i.e. containing additional + /// metadata such as bounds information/permissions). + bool IsNonIntegral; bool operator==(const PointerSpec &Other) const; }; @@ -133,10 +137,6 @@ class DataLayout { // The StructType -> StructLayout map. mutable void *LayoutMap = nullptr; - /// Pointers in these address spaces are non-integral, and don't have a - /// well-defined bitwise representation. - SmallVector NonIntegralAddressSpaces; - /// Sets or updates the specification for the given primitive type. void setPrimitiveSpec(char Specifier, uint32_t BitWidth, Align ABIAlign, Align PrefAlign); @@ -147,7 +147,8 @@ class DataLayout { /// Sets or updates the specification for pointer in the given address space. void setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth, Align ABIAlign, - Align PrefAlign, uint32_t IndexBitWidth); + Align PrefAlign, uint32_t IndexBitWidth, + bool IsNonIntegral); /// Internal helper to get alignment for integer of given bitwidth. Align getIntegerAlignment(uint32_t BitWidth, bool abi_or_pref) const; @@ -165,7 +166,8 @@ class DataLayout { Error parsePointerSpec(StringRef Spec); /// Attempts to parse a single specification. - Error parseSpecification(StringRef Spec); + Error parseSpecification(StringRef Spec, + SmallVectorImpl &NonIntegralAddressSpaces); /// Attempts to parse a data layout string. Error parseLayoutString(StringRef LayoutString); @@ -337,13 +339,17 @@ class DataLayout { /// Return the address spaces containing non-integral pointers. Pointers in /// this address space don't have a well-defined bitwise representation. - ArrayRef getNonIntegralAddressSpaces() const { - return NonIntegralAddressSpaces; + SmallVector getNonIntegralAddressSpaces() const { + SmallVector AddrSpaces; + for (const PointerSpec &PS : PointerSpecs) { + if (PS.IsNonIntegral) + AddrSpaces.push_back(PS.AddrSpace); + } + return AddrSpaces; } bool isNonIntegralAddressSpace(unsigned AddrSpace) const { - ArrayRef NonIntegralSpaces = getNonIntegralAddressSpaces(); - return is_contained(NonIntegralSpaces, AddrSpace); + return getPointerSpec(AddrSpace).IsNonIntegral; } bool isNonIntegralPointerType(PointerType *PT) const { diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp index d295d1f5785eb..a4af0ead07cf6 100644 --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -151,7 +151,8 @@ bool DataLayout::PrimitiveSpec::operator==(const PrimitiveSpec &Other) const { bool DataLayout::PointerSpec::operator==(const PointerSpec &Other) const { return AddrSpace == Other.AddrSpace && BitWidth == Other.BitWidth && ABIAlign == Other.ABIAlign && PrefAlign == Other.PrefAlign && - IndexBitWidth == Other.IndexBitWidth; + IndexBitWidth == Other.IndexBitWidth && + IsNonIntegral == Other.IsNonIntegral; } namespace { @@ -206,7 +207,8 @@ constexpr DataLayout::PrimitiveSpec DefaultVectorSpecs[] = { // Default pointer type specifications. constexpr DataLayout::PointerSpec DefaultPointerSpecs[] = { - {0, 64, Align::Constant<8>(), Align::Constant<8>(), 64} // p0:64:64:64:64 + // p0:64:64:64:64 + {0, 64, Align::Constant<8>(), Align::Constant<8>(), 64, false}, }; DataLayout::DataLayout() @@ -239,13 +241,11 @@ DataLayout &DataLayout::operator=(const DataLayout &Other) { PointerSpecs = Other.PointerSpecs; StructABIAlignment = Other.StructABIAlignment; StructPrefAlignment = Other.StructPrefAlignment; - NonIntegralAddressSpaces = Other.NonIntegralAddressSpaces; return *this; } bool DataLayout::operator==(const DataLayout &Other) const { // NOTE: StringRepresentation might differ, it is not canonicalized. - // FIXME: NonIntegralAddressSpaces isn't compared. return BigEndian == Other.BigEndian && AllocaAddrSpace == Other.AllocaAddrSpace && ProgramAddrSpace == Other.ProgramAddrSpace && @@ -454,11 +454,13 @@ Error DataLayout::parsePointerSpec(StringRef Spec) { return createStringError( "index size cannot be larger than the pointer size"); - setPointerSpec(AddrSpace, BitWidth, ABIAlign, PrefAlign, IndexBitWidth); + setPointerSpec(AddrSpace, BitWidth, ABIAlign, PrefAlign, IndexBitWidth, + false); return Error::success(); } -Error DataLayout::parseSpecification(StringRef Spec) { +Error DataLayout::parseSpecification( + StringRef Spec, SmallVectorImpl &NonIntegralAddressSpaces) { // The "ni" specifier is the only two-character specifier. Handle it first. if (Spec.starts_with("ni")) { // ni:
[:
]... @@ -614,12 +616,23 @@ Error DataLayout::parseLayoutString(StringRef LayoutString) { // Split the data layout string into specifications separated by '-' and // parse each specification individually, updating internal data structures. + SmallVector NonIntegralAddressSpaces; for (StringRef Spec : split(LayoutString, '-')) { if (Spec.empty()) return createStringError("empty specification is not allowed"); - if (Error Err = parseSpecification(Spec)) + if (Error Err = parseSpecification(Spec, NonIntegralAddressSpaces)) return Err; } + // Mark all address spaces that were qualified as non-integral now. This has + // to be done later since the non-integral property is not part of the data + // layout pointer specification. + for (unsigned AS : NonIntegralAddressSpaces) { + // If there is no special spec for a given AS, getPointerSpec(AS) returns + // the spec for AS0, and we then update that to mark it non-integral. + const PointerSpec &PS = getPointerSpec(AS); + setPointerSpec(AS, PS.BitWidth, PS.ABIAlign, PS.PrefAlign, PS.IndexBitWidth, + true); + } return Error::success(); } @@ -666,16 +679,17 @@ DataLayout::getPointerSpec(uint32_t AddrSpace) const { void DataLayout::setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth, Align ABIAlign, Align PrefAlign, - uint32_t IndexBitWidth) { + uint32_t IndexBitWidth, bool IsNonIntegral) { auto I = lower_bound(PointerSpecs, AddrSpace, LessPointerAddrSpace()); if (I == PointerSpecs.end() || I->AddrSpace != AddrSpace) { PointerSpecs.insert(I, PointerSpec{AddrSpace, BitWidth, ABIAlign, PrefAlign, - IndexBitWidth}); + IndexBitWidth, IsNonIntegral}); } else { I->BitWidth = BitWidth; I->ABIAlign = ABIAlign; I->PrefAlign = PrefAlign; I->IndexBitWidth = IndexBitWidth; + I->IsNonIntegral = IsNonIntegral; } }