Index: clang/include/clang/AST/ASTContext.h =================================================================== --- clang/include/clang/AST/ASTContext.h +++ clang/include/clang/AST/ASTContext.h @@ -76,6 +76,7 @@ namespace llvm { class APFixedPoint; +class DataLayout; class FixedPointSemantics; struct fltSemantics; template class SmallPtrSet; @@ -599,6 +600,7 @@ bool AddrSpaceMapMangling; const TargetInfo *Target = nullptr; + std::unique_ptr TargetDataLayout; const TargetInfo *AuxTarget = nullptr; clang::PrintingPolicy PrintingPolicy; std::unique_ptr InterpContext; @@ -690,6 +692,9 @@ } const TargetInfo &getTargetInfo() const { return *Target; } + const llvm::DataLayout &getTargetDataLayout() const { + return *TargetDataLayout; + } const TargetInfo *getAuxTargetInfo() const { return AuxTarget; } /// getIntTypeForBitwidth - Index: clang/include/clang/Basic/TargetInfo.h =================================================================== --- clang/include/clang/Basic/TargetInfo.h +++ clang/include/clang/Basic/TargetInfo.h @@ -40,7 +40,7 @@ namespace llvm { struct fltSemantics; -class DataLayout; +class DataLayoutString; } namespace clang { @@ -205,7 +205,7 @@ unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth; unsigned short SimdDefaultAlign; - std::unique_ptr DataLayout; + std::unique_ptr DataLayout; const char *MCountName; unsigned char RegParmMax, SSERegParmMax; TargetCXXABI TheCXXABI; @@ -1096,7 +1096,7 @@ /// Returns the target ID if supported. virtual llvm::Optional getTargetID() const { return llvm::None; } - const llvm::DataLayout &getDataLayout() const { + const llvm::DataLayoutString &getDataLayout() const { assert(DataLayout && "Uninitialized DataLayout!"); return *DataLayout; } Index: clang/include/clang/CodeGen/BackendUtil.h =================================================================== --- clang/include/clang/CodeGen/BackendUtil.h +++ clang/include/clang/CodeGen/BackendUtil.h @@ -39,7 +39,7 @@ void EmitBackendOutput(DiagnosticsEngine &Diags, const HeaderSearchOptions &, const CodeGenOptions &CGOpts, const TargetOptions &TOpts, const LangOptions &LOpts, - const llvm::DataLayout &TDesc, llvm::Module *M, + const llvm::DataLayoutString &TDesc, llvm::Module *M, BackendAction Action, std::unique_ptr OS); Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -80,6 +80,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" +#include "llvm/IR/DataLayout.h" #include "llvm/Support/Capacity.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" @@ -1260,6 +1261,8 @@ assert(VoidTy.isNull() && "Context reinitialized?"); this->Target = &Target; + TargetDataLayout = std::make_unique( + Target.getDataLayout().getStringRepresentation()); this->AuxTarget = AuxTarget; ABI.reset(createCXXABI(Target)); Index: clang/lib/AST/Mangle.cpp =================================================================== --- clang/lib/AST/Mangle.cpp +++ clang/lib/AST/Mangle.cpp @@ -383,8 +383,7 @@ public: explicit Implementation(ASTContext &Ctx) - : MC(Ctx.createMangleContext()), DL(Ctx.getTargetInfo().getDataLayout()) { - } + : MC(Ctx.createMangleContext()), DL(Ctx.getTargetDataLayout()) {} bool writeName(const Decl *D, raw_ostream &OS) { // First apply frontend mangling. Index: clang/lib/Basic/CMakeLists.txt =================================================================== --- clang/lib/Basic/CMakeLists.txt +++ clang/lib/Basic/CMakeLists.txt @@ -1,5 +1,4 @@ set(LLVM_LINK_COMPONENTS - Core MC Support ) Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -1595,14 +1595,11 @@ } } -void clang::EmitBackendOutput(DiagnosticsEngine &Diags, - const HeaderSearchOptions &HeaderOpts, - const CodeGenOptions &CGOpts, - const clang::TargetOptions &TOpts, - const LangOptions &LOpts, - const llvm::DataLayout &TDesc, Module *M, - BackendAction Action, - std::unique_ptr OS) { +void clang::EmitBackendOutput( + DiagnosticsEngine &Diags, const HeaderSearchOptions &HeaderOpts, + const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, + const LangOptions &LOpts, const llvm::DataLayoutString &TDesc, Module *M, + BackendAction Action, std::unique_ptr OS) { llvm::TimeTraceScope TimeScope("Backend"); Index: clang/lib/CodeGen/ModuleBuilder.cpp =================================================================== --- clang/lib/CodeGen/ModuleBuilder.cpp +++ clang/lib/CodeGen/ModuleBuilder.cpp @@ -138,7 +138,7 @@ Ctx = &Context; M->setTargetTriple(Ctx->getTargetInfo().getTriple().getTriple()); - M->setDataLayout(Ctx->getTargetInfo().getDataLayout()); + M->setDataLayout(Ctx->getTargetDataLayout()); const auto &SDKVersion = Ctx->getTargetInfo().getSDKVersion(); if (!SDKVersion.empty()) M->setSDKVersion(SDKVersion); Index: clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp =================================================================== --- clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp +++ clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp @@ -166,7 +166,7 @@ Ctx = &Context; VMContext.reset(new llvm::LLVMContext()); M.reset(new llvm::Module(MainFileName, *VMContext)); - M->setDataLayout(Ctx->getTargetInfo().getDataLayout()); + M->setDataLayout(Ctx->getTargetDataLayout()); Builder.reset(new CodeGen::CodeGenModule( *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags)); @@ -245,7 +245,7 @@ return; M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple()); - M->setDataLayout(Ctx.getTargetInfo().getDataLayout()); + M->setDataLayout(Ctx.getTargetDataLayout()); // PCH files don't have a signature field in the control block, // but LLVM detects DWO CUs by looking for a non-zero DWO id. Index: llvm/include/llvm/IR/DataLayout.h =================================================================== --- llvm/include/llvm/IR/DataLayout.h +++ llvm/include/llvm/IR/DataLayout.h @@ -26,6 +26,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Type.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/DataLayoutString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Alignment.h" @@ -48,347 +49,37 @@ class Triple; class Value; -/// Enum used to categorize the alignment types stored by LayoutAlignElem -enum AlignTypeEnum { - INVALID_ALIGN = 0, - INTEGER_ALIGN = 'i', - VECTOR_ALIGN = 'v', - FLOAT_ALIGN = 'f', - AGGREGATE_ALIGN = 'a' -}; - -// FIXME: Currently the DataLayout string carries a "preferred alignment" -// for types. As the DataLayout is module/global, this should likely be -// sunk down to an FTTI element that is queried rather than a global -// preference. - -/// Layout alignment element. -/// -/// Stores the alignment data associated with a given alignment type (integer, -/// vector, float) and type bit width. -/// -/// \note The unusual order of elements in the structure attempts to reduce -/// padding and make the structure slightly more cache friendly. -struct LayoutAlignElem { - /// Alignment type from \c AlignTypeEnum - unsigned AlignType : 8; - unsigned TypeBitWidth : 24; - Align ABIAlign; - Align PrefAlign; - - static LayoutAlignElem get(AlignTypeEnum align_type, Align abi_align, - Align pref_align, uint32_t bit_width); - - bool operator==(const LayoutAlignElem &rhs) const; -}; - -/// Layout pointer alignment element. -/// -/// Stores the alignment data associated with a given pointer and address space. -/// -/// \note The unusual order of elements in the structure attempts to reduce -/// padding and make the structure slightly more cache friendly. -struct PointerAlignElem { - Align ABIAlign; - Align PrefAlign; - uint32_t TypeByteWidth; - uint32_t AddressSpace; - uint32_t IndexWidth; - - /// Initializer - static PointerAlignElem get(uint32_t AddressSpace, Align ABIAlign, - Align PrefAlign, uint32_t TypeByteWidth, - uint32_t IndexWidth); - - bool operator==(const PointerAlignElem &rhs) const; -}; - -/// A parsed version of the target data layout string in and methods for -/// querying it. -/// -/// The target data layout string is specified *by the target* - a frontend -/// generating LLVM IR is required to generate the right target data for the -/// target being codegen'd to. -class DataLayout { -public: - enum class FunctionPtrAlignType { - /// The function pointer alignment is independent of the function alignment. - Independent, - /// The function pointer alignment is a multiple of the function alignment. - MultipleOfFunctionAlign, - }; -private: - /// Defaults to false. - bool BigEndian; - - unsigned AllocaAddrSpace; - MaybeAlign StackNaturalAlign; - unsigned ProgramAddrSpace; - unsigned DefaultGlobalsAddrSpace; - - MaybeAlign FunctionPtrAlign; - FunctionPtrAlignType TheFunctionPtrAlignType; - - enum ManglingModeT { - MM_None, - MM_ELF, - MM_MachO, - MM_WinCOFF, - MM_WinCOFFX86, - MM_Mips, - MM_XCOFF - }; - ManglingModeT ManglingMode; - - SmallVector LegalIntWidths; - - /// Primitive type alignment data. This is sorted by type and bit - /// width during construction. - using AlignmentsTy = SmallVector; - AlignmentsTy Alignments; - - AlignmentsTy::const_iterator - findAlignmentLowerBound(AlignTypeEnum AlignType, uint32_t BitWidth) const { - return const_cast(this)->findAlignmentLowerBound(AlignType, - BitWidth); - } - - AlignmentsTy::iterator - findAlignmentLowerBound(AlignTypeEnum AlignType, uint32_t BitWidth); - - /// The string representation used to create this DataLayout - std::string StringRepresentation; - - using PointersTy = SmallVector; - PointersTy Pointers; - - const PointerAlignElem &getPointerAlignElem(uint32_t AddressSpace) const; +/// Extends DataLayoutString with convenience methods taking IR Types. +class DataLayout final : public DataLayoutString { // 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; - - /// Attempts to set the alignment of the given type. Returns an error - /// description on failure. - Error setAlignment(AlignTypeEnum align_type, Align abi_align, - Align pref_align, uint32_t bit_width); - - /// Attempts to set the alignment of a pointer in the given address space. - /// Returns an error description on failure. - Error setPointerAlignment(uint32_t AddrSpace, Align ABIAlign, Align PrefAlign, - uint32_t TypeByteWidth, uint32_t IndexWidth); - - /// Internal helper to get alignment for integer of given bitwidth. - Align getIntegerAlignment(uint32_t BitWidth, bool abi_or_pref) const; - /// Internal helper method that returns requested alignment for type. Align getAlignment(Type *Ty, bool abi_or_pref) const; - /// Attempts to parse a target data specification string and reports an error - /// if the string is malformed. - Error parseSpecifier(StringRef Desc); - // Free all internal data structures. void clear(); public: - /// Constructs a DataLayout from a specification string. See reset(). - explicit DataLayout(StringRef LayoutDescription) { - reset(LayoutDescription); - } + explicit DataLayout(StringRef LayoutDescription) + : DataLayoutString(LayoutDescription) {} /// Initialize target data from properties stored in the module. explicit DataLayout(const Module *M); - DataLayout(const DataLayout &DL) { *this = DL; } - - ~DataLayout(); // Not virtual, do not subclass this class + DataLayout(const DataLayout &DL) : DataLayoutString(DL) { *this = DL; } DataLayout &operator=(const DataLayout &DL) { - clear(); - StringRepresentation = DL.StringRepresentation; - BigEndian = DL.isBigEndian(); - AllocaAddrSpace = DL.AllocaAddrSpace; - StackNaturalAlign = DL.StackNaturalAlign; - FunctionPtrAlign = DL.FunctionPtrAlign; - TheFunctionPtrAlignType = DL.TheFunctionPtrAlignType; - ProgramAddrSpace = DL.ProgramAddrSpace; - DefaultGlobalsAddrSpace = DL.DefaultGlobalsAddrSpace; - ManglingMode = DL.ManglingMode; - LegalIntWidths = DL.LegalIntWidths; - Alignments = DL.Alignments; - Pointers = DL.Pointers; - NonIntegralAddressSpaces = DL.NonIntegralAddressSpaces; + DataLayoutString::operator=(DL); return *this; } - bool operator==(const DataLayout &Other) const; + bool operator==(const DataLayout &Other) const { return DataLayoutString::operator==(Other); } bool operator!=(const DataLayout &Other) const { return !(*this == Other); } void init(const Module *M); - /// Parse a data layout string (with fallback to default values). - void reset(StringRef LayoutDescription); - - /// Parse a data layout string and return the layout. Return an error - /// description on failure. - static Expected parse(StringRef LayoutDescription); - - /// Layout endianness... - bool isLittleEndian() const { return !BigEndian; } - bool isBigEndian() const { return BigEndian; } - - /// Returns the string representation of the DataLayout. - /// - /// This representation is in the same format accepted by the string - /// constructor above. This should not be used to compare two DataLayout as - /// different string can represent the same layout. - const std::string &getStringRepresentation() const { - return StringRepresentation; - } - - /// Test if the DataLayout was constructed from an empty string. - bool isDefault() const { return StringRepresentation.empty(); } - - /// Returns true if the specified type is known to be a native integer - /// type supported by the CPU. - /// - /// For example, i64 is not native on most 32-bit CPUs and i37 is not native - /// on any known one. This returns false if the integer width is not legal. - /// - /// The width is specified in bits. - bool isLegalInteger(uint64_t Width) const { - return llvm::is_contained(LegalIntWidths, Width); - } - - bool isIllegalInteger(uint64_t Width) const { return !isLegalInteger(Width); } - - /// Returns true if the given alignment exceeds the natural stack alignment. - bool exceedsNaturalStackAlignment(Align Alignment) const { - return StackNaturalAlign && (Alignment > *StackNaturalAlign); - } - - Align getStackAlignment() const { - assert(StackNaturalAlign && "StackNaturalAlign must be defined"); - return *StackNaturalAlign; - } - - unsigned getAllocaAddrSpace() const { return AllocaAddrSpace; } - - /// Returns the alignment of function pointers, which may or may not be - /// related to the alignment of functions. - /// \see getFunctionPtrAlignType - MaybeAlign getFunctionPtrAlign() const { return FunctionPtrAlign; } - - /// Return the type of function pointer alignment. - /// \see getFunctionPtrAlign - FunctionPtrAlignType getFunctionPtrAlignType() const { - return TheFunctionPtrAlignType; - } - - unsigned getProgramAddressSpace() const { return ProgramAddrSpace; } - unsigned getDefaultGlobalsAddressSpace() const { - return DefaultGlobalsAddrSpace; - } - - bool hasMicrosoftFastStdCallMangling() const { - return ManglingMode == MM_WinCOFFX86; - } - - /// Returns true if symbols with leading question marks should not receive IR - /// mangling. True for Windows mangling modes. - bool doNotMangleLeadingQuestionMark() const { - return ManglingMode == MM_WinCOFF || ManglingMode == MM_WinCOFFX86; - } - - bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; } - - StringRef getLinkerPrivateGlobalPrefix() const { - if (ManglingMode == MM_MachO) - return "l"; - return ""; - } - - char getGlobalPrefix() const { - switch (ManglingMode) { - case MM_None: - case MM_ELF: - case MM_Mips: - case MM_WinCOFF: - case MM_XCOFF: - return '\0'; - case MM_MachO: - case MM_WinCOFFX86: - return '_'; - } - llvm_unreachable("invalid mangling mode"); - } - - StringRef getPrivateGlobalPrefix() const { - switch (ManglingMode) { - case MM_None: - return ""; - case MM_ELF: - case MM_WinCOFF: - return ".L"; - case MM_Mips: - return "$"; - case MM_MachO: - case MM_WinCOFFX86: - return "L"; - case MM_XCOFF: - return "L.."; - } - llvm_unreachable("invalid mangling mode"); - } - - static const char *getManglingComponent(const Triple &T); - - /// Returns true if the specified type fits in a native integer type - /// supported by the CPU. - /// - /// For example, if the CPU only supports i32 as a native integer type, then - /// i27 fits in a legal integer type but i45 does not. - bool fitsInLegalInteger(unsigned Width) const { - for (unsigned LegalIntWidth : LegalIntWidths) - if (Width <= LegalIntWidth) - return true; - return false; - } - - /// Layout pointer alignment - Align getPointerABIAlignment(unsigned AS) const; - - /// Return target's alignment for stack-based pointers - /// FIXME: The defaults need to be removed once all of - /// the backends/clients are updated. - Align getPointerPrefAlignment(unsigned AS = 0) const; - - /// Layout pointer size - /// FIXME: The defaults need to be removed once all of - /// the backends/clients are updated. - unsigned getPointerSize(unsigned AS = 0) const; - - /// Returns the maximum pointer size over all address spaces. - unsigned getMaxPointerSize() const; - - // Index size used for address calculation. - unsigned getIndexSize(unsigned AS) const; - - /// 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; - } - - bool isNonIntegralAddressSpace(unsigned AddrSpace) const { - ArrayRef NonIntegralSpaces = getNonIntegralAddressSpaces(); - return is_contained(NonIntegralSpaces, AddrSpace); - } - bool isNonIntegralPointerType(PointerType *PT) const { return isNonIntegralAddressSpace(PT->getAddressSpace()); } @@ -398,23 +89,6 @@ return PTy && isNonIntegralPointerType(PTy); } - /// Layout pointer size, in bits - /// FIXME: The defaults need to be removed once all of - /// the backends/clients are updated. - unsigned getPointerSizeInBits(unsigned AS = 0) const { - return getPointerSize(AS) * 8; - } - - /// Returns the maximum pointer size over all address spaces. - unsigned getMaxPointerSizeInBits() const { - return getMaxPointerSize() * 8; - } - - /// Size in bits of index used for address calculation in getelementptr. - unsigned getIndexSizeInBits(unsigned AS) const { - return getIndexSize(AS) * 8; - } - /// Layout pointer size, in bits, based on the type. If this function is /// called with a pointer type, then the type size of the pointer is returned. /// If this function is called with a vector of pointers, then the type size @@ -526,12 +200,6 @@ return Alignment ? *Alignment : getABITypeAlign(Ty); } - /// Returns the minimum ABI-required alignment for an integer type of - /// the specified bitwidth. - Align getABIIntegerTypeAlignment(unsigned BitWidth) const { - return getIntegerAlignment(BitWidth, /* abi_or_pref */ true); - } - /// Returns the preferred stack/global alignment for the specified /// type. /// Index: llvm/include/llvm/Support/DataLayoutString.h =================================================================== --- /dev/null +++ llvm/include/llvm/Support/DataLayoutString.h @@ -0,0 +1,398 @@ +//===- llvm/DataLayoutString.h - Data size & alignment info -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines layout properties related to datatype size/offset/alignment +// information. It uses lazy annotations to cache information about how +// structure types are laid out and used. +// +// This structure should be created once, filled in if the defaults are not +// correct and then passed around by const&. None of the members functions +// require modification to the object. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DATALAYOUT_STRING_H +#define LLVM_SUPPORT_DATALAYOUT_STRING_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Alignment.h" +#include "llvm/Support/TrailingObjects.h" +#include "llvm/Support/TypeSize.h" +#include +#include +#include + +namespace llvm { + +class Triple; +class Value; + +/// Enum used to categorize the alignment types stored by LayoutAlignElem +enum AlignTypeEnum { + INVALID_ALIGN = 0, + INTEGER_ALIGN = 'i', + VECTOR_ALIGN = 'v', + FLOAT_ALIGN = 'f', + AGGREGATE_ALIGN = 'a' +}; + +// FIXME: Currently the DataLayoutString carries a "preferred alignment" +// for types. As the DataLayoutString is module/global, this should likely be +// sunk down to an FTTI element that is queried rather than a global +// preference. + +/// Layout alignment element. +/// +/// Stores the alignment data associated with a given alignment type (integer, +/// vector, float) and type bit width. +/// +/// \note The unusual order of elements in the structure attempts to reduce +/// padding and make the structure slightly more cache friendly. +struct LayoutAlignElem { + /// Alignment type from \c AlignTypeEnum + unsigned AlignType : 8; + unsigned TypeBitWidth : 24; + Align ABIAlign; + Align PrefAlign; + + static LayoutAlignElem get(AlignTypeEnum align_type, Align abi_align, + Align pref_align, uint32_t bit_width); + + bool operator==(const LayoutAlignElem &rhs) const; +}; + +/// Layout pointer alignment element. +/// +/// Stores the alignment data associated with a given pointer and address space. +/// +/// \note The unusual order of elements in the structure attempts to reduce +/// padding and make the structure slightly more cache friendly. +struct PointerAlignElem { + Align ABIAlign; + Align PrefAlign; + uint32_t TypeByteWidth; + uint32_t AddressSpace; + uint32_t IndexWidth; + + /// Initializer + static PointerAlignElem get(uint32_t AddressSpace, Align ABIAlign, + Align PrefAlign, uint32_t TypeByteWidth, + uint32_t IndexWidth); + + bool operator==(const PointerAlignElem &rhs) const; +}; + +/// A parsed version of the target data layout string in and methods for +/// querying it. +/// +/// The target data layout string is specified *by the target* - a frontend +/// generating LLVM IR is required to generate the right target data for the +/// target being codegen'd to. +class DataLayoutString { +public: + enum class FunctionPtrAlignType { + /// The function pointer alignment is independent of the function alignment. + Independent, + /// The function pointer alignment is a multiple of the function alignment. + MultipleOfFunctionAlign, + }; +protected: + /// Defaults to false. + bool BigEndian; + + unsigned AllocaAddrSpace; + MaybeAlign StackNaturalAlign; + unsigned ProgramAddrSpace; + unsigned DefaultGlobalsAddrSpace; + + MaybeAlign FunctionPtrAlign; + FunctionPtrAlignType TheFunctionPtrAlignType; + + enum ManglingModeT { + MM_None, + MM_ELF, + MM_MachO, + MM_WinCOFF, + MM_WinCOFFX86, + MM_Mips, + MM_XCOFF + }; + ManglingModeT ManglingMode; + + SmallVector LegalIntWidths; + + /// Primitive type alignment data. This is sorted by type and bit + /// width during construction. + using AlignmentsTy = SmallVector; + AlignmentsTy Alignments; + + AlignmentsTy::const_iterator + findAlignmentLowerBound(AlignTypeEnum AlignType, uint32_t BitWidth) const { + return const_cast(this)->findAlignmentLowerBound( + AlignType, BitWidth); + } + + AlignmentsTy::iterator + findAlignmentLowerBound(AlignTypeEnum AlignType, uint32_t BitWidth); + + /// The string representation used to create this DataLayoutString + std::string StringRepresentation; + + using PointersTy = SmallVector; + PointersTy Pointers; + + const PointerAlignElem &getPointerAlignElem(uint32_t AddressSpace) const; + + /// Pointers in these address spaces are non-integral, and don't have a + /// well-defined bitwise representation. + SmallVector NonIntegralAddressSpaces; + + /// Attempts to set the alignment of the given type. Returns an error + /// description on failure. + Error setAlignment(AlignTypeEnum align_type, Align abi_align, + Align pref_align, uint32_t bit_width); + + /// Attempts to set the alignment of a pointer in the given address space. + /// Returns an error description on failure. + Error setPointerAlignment(uint32_t AddrSpace, Align ABIAlign, Align PrefAlign, + uint32_t TypeByteWidth, uint32_t IndexWidth); + + /// Internal helper to get alignment for integer of given bitwidth. + Align getIntegerAlignment(uint32_t BitWidth, bool abi_or_pref) const; + + /// Attempts to parse a target data specification string and reports an error + /// if the string is malformed. + Error parseSpecifier(StringRef Desc); + + // Free all internal data structures. + void clear(); + +public: + /// Constructs a DataLayoutString from a specification string. See reset(). + explicit DataLayoutString(StringRef LayoutDescription) { + reset(LayoutDescription); + } + + DataLayoutString(const DataLayoutString &DL) { *this = DL; } + + // Not virtual, do not delete instances of this class polymorphically + ~DataLayoutString(); + + DataLayoutString &operator=(const DataLayoutString &DL) { + clear(); + StringRepresentation = DL.StringRepresentation; + BigEndian = DL.isBigEndian(); + AllocaAddrSpace = DL.AllocaAddrSpace; + StackNaturalAlign = DL.StackNaturalAlign; + FunctionPtrAlign = DL.FunctionPtrAlign; + TheFunctionPtrAlignType = DL.TheFunctionPtrAlignType; + ProgramAddrSpace = DL.ProgramAddrSpace; + DefaultGlobalsAddrSpace = DL.DefaultGlobalsAddrSpace; + ManglingMode = DL.ManglingMode; + LegalIntWidths = DL.LegalIntWidths; + Alignments = DL.Alignments; + Pointers = DL.Pointers; + NonIntegralAddressSpaces = DL.NonIntegralAddressSpaces; + return *this; + } + + bool operator==(const DataLayoutString &Other) const; + bool operator!=(const DataLayoutString &Other) const { return !(*this == Other); } + + /// Parse a data layout string (with fallback to default values). + void reset(StringRef LayoutDescription); + + /// Parse a data layout string and return the layout. Return an error + /// description on failure. + static Expected parse(StringRef LayoutDescription); + + /// Layout endianness... + bool isLittleEndian() const { return !BigEndian; } + bool isBigEndian() const { return BigEndian; } + + /// Returns the string representation of the DataLayoutString. + /// + /// This representation is in the same format accepted by the string + /// constructor above. This should not be used to compare two DataLayoutString as + /// different string can represent the same layout. + const std::string &getStringRepresentation() const { + return StringRepresentation; + } + + /// Test if the DataLayoutString was constructed from an empty string. + bool isDefault() const { return StringRepresentation.empty(); } + + /// Returns true if the specified type is known to be a native integer + /// type supported by the CPU. + /// + /// For example, i64 is not native on most 32-bit CPUs and i37 is not native + /// on any known one. This returns false if the integer width is not legal. + /// + /// The width is specified in bits. + bool isLegalInteger(uint64_t Width) const { + return llvm::is_contained(LegalIntWidths, Width); + } + + bool isIllegalInteger(uint64_t Width) const { return !isLegalInteger(Width); } + + /// Returns true if the given alignment exceeds the natural stack alignment. + bool exceedsNaturalStackAlignment(Align Alignment) const { + return StackNaturalAlign && (Alignment > *StackNaturalAlign); + } + + Align getStackAlignment() const { + assert(StackNaturalAlign && "StackNaturalAlign must be defined"); + return *StackNaturalAlign; + } + + unsigned getAllocaAddrSpace() const { return AllocaAddrSpace; } + + /// Returns the alignment of function pointers, which may or may not be + /// related to the alignment of functions. + /// \see getFunctionPtrAlignType + MaybeAlign getFunctionPtrAlign() const { return FunctionPtrAlign; } + + /// Return the type of function pointer alignment. + /// \see getFunctionPtrAlign + FunctionPtrAlignType getFunctionPtrAlignType() const { + return TheFunctionPtrAlignType; + } + + unsigned getProgramAddressSpace() const { return ProgramAddrSpace; } + unsigned getDefaultGlobalsAddressSpace() const { + return DefaultGlobalsAddrSpace; + } + + bool hasMicrosoftFastStdCallMangling() const { + return ManglingMode == MM_WinCOFFX86; + } + + /// Returns true if symbols with leading question marks should not receive IR + /// mangling. True for Windows mangling modes. + bool doNotMangleLeadingQuestionMark() const { + return ManglingMode == MM_WinCOFF || ManglingMode == MM_WinCOFFX86; + } + + bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; } + + StringRef getLinkerPrivateGlobalPrefix() const { + if (ManglingMode == MM_MachO) + return "l"; + return ""; + } + + char getGlobalPrefix() const { + switch (ManglingMode) { + case MM_None: + case MM_ELF: + case MM_Mips: + case MM_WinCOFF: + case MM_XCOFF: + return '\0'; + case MM_MachO: + case MM_WinCOFFX86: + return '_'; + } + llvm_unreachable("invalid mangling mode"); + } + + StringRef getPrivateGlobalPrefix() const { + switch (ManglingMode) { + case MM_None: + return ""; + case MM_ELF: + case MM_WinCOFF: + return ".L"; + case MM_Mips: + return "$"; + case MM_MachO: + case MM_WinCOFFX86: + return "L"; + case MM_XCOFF: + return "L.."; + } + llvm_unreachable("invalid mangling mode"); + } + + static const char *getManglingComponent(const Triple &T); + + /// Returns true if the specified type fits in a native integer type + /// supported by the CPU. + /// + /// For example, if the CPU only supports i32 as a native integer type, then + /// i27 fits in a legal integer type but i45 does not. + bool fitsInLegalInteger(unsigned Width) const { + for (unsigned LegalIntWidth : LegalIntWidths) + if (Width <= LegalIntWidth) + return true; + return false; + } + + /// Layout pointer alignment + Align getPointerABIAlignment(unsigned AS) const; + + /// Return target's alignment for stack-based pointers + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + Align getPointerPrefAlignment(unsigned AS = 0) const; + + /// Layout pointer size + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + unsigned getPointerSize(unsigned AS = 0) const; + + /// Returns the maximum pointer size over all address spaces. + unsigned getMaxPointerSize() const; + + // Index size used for address calculation. + unsigned getIndexSize(unsigned AS) const; + + /// 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; + } + + bool isNonIntegralAddressSpace(unsigned AddrSpace) const { + ArrayRef NonIntegralSpaces = getNonIntegralAddressSpaces(); + return is_contained(NonIntegralSpaces, AddrSpace); + } + + /// Layout pointer size, in bits + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + unsigned getPointerSizeInBits(unsigned AS = 0) const { + return getPointerSize(AS) * 8; + } + + /// Returns the maximum pointer size over all address spaces. + unsigned getMaxPointerSizeInBits() const { + return getMaxPointerSize() * 8; + } + + /// Size in bits of index used for address calculation in getelementptr. + unsigned getIndexSizeInBits(unsigned AS) const { + return getIndexSize(AS) * 8; + } + + /// Returns the minimum ABI-required alignment for an integer type of + /// the specified bitwidth. + Align getABIIntegerTypeAlignment(unsigned BitWidth) const { + return getIntegerAlignment(BitWidth, /* abi_or_pref */ true); + } +}; + +} // end namespace llvm + +#endif // LLVM_SUPPORT_DATALAYOUT_STRING_H Index: llvm/lib/IR/DataLayout.cpp =================================================================== --- llvm/lib/IR/DataLayout.cpp +++ llvm/lib/IR/DataLayout.cpp @@ -97,542 +97,15 @@ return SI - MemberOffsets.begin(); } -//===----------------------------------------------------------------------===// -// LayoutAlignElem, LayoutAlign support -//===----------------------------------------------------------------------===// - -LayoutAlignElem LayoutAlignElem::get(AlignTypeEnum align_type, Align abi_align, - Align pref_align, uint32_t bit_width) { - assert(abi_align <= pref_align && "Preferred alignment worse than ABI!"); - LayoutAlignElem retval; - retval.AlignType = align_type; - retval.ABIAlign = abi_align; - retval.PrefAlign = pref_align; - retval.TypeBitWidth = bit_width; - return retval; -} - -bool -LayoutAlignElem::operator==(const LayoutAlignElem &rhs) const { - return (AlignType == rhs.AlignType - && ABIAlign == rhs.ABIAlign - && PrefAlign == rhs.PrefAlign - && TypeBitWidth == rhs.TypeBitWidth); -} - -//===----------------------------------------------------------------------===// -// PointerAlignElem, PointerAlign support -//===----------------------------------------------------------------------===// - -PointerAlignElem PointerAlignElem::get(uint32_t AddressSpace, Align ABIAlign, - Align PrefAlign, uint32_t TypeByteWidth, - uint32_t IndexWidth) { - assert(ABIAlign <= PrefAlign && "Preferred alignment worse than ABI!"); - PointerAlignElem retval; - retval.AddressSpace = AddressSpace; - retval.ABIAlign = ABIAlign; - retval.PrefAlign = PrefAlign; - retval.TypeByteWidth = TypeByteWidth; - retval.IndexWidth = IndexWidth; - return retval; -} - -bool -PointerAlignElem::operator==(const PointerAlignElem &rhs) const { - return (ABIAlign == rhs.ABIAlign - && AddressSpace == rhs.AddressSpace - && PrefAlign == rhs.PrefAlign - && TypeByteWidth == rhs.TypeByteWidth - && IndexWidth == rhs.IndexWidth); -} - //===----------------------------------------------------------------------===// // DataLayout Class Implementation //===----------------------------------------------------------------------===// -const char *DataLayout::getManglingComponent(const Triple &T) { - if (T.isOSBinFormatMachO()) - return "-m:o"; - if (T.isOSWindows() && T.isOSBinFormatCOFF()) - return T.getArch() == Triple::x86 ? "-m:x" : "-m:w"; - if (T.isOSBinFormatXCOFF()) - return "-m:a"; - return "-m:e"; -} - -static const LayoutAlignElem DefaultAlignments[] = { - {INTEGER_ALIGN, 1, Align(1), Align(1)}, // i1 - {INTEGER_ALIGN, 8, Align(1), Align(1)}, // i8 - {INTEGER_ALIGN, 16, Align(2), Align(2)}, // i16 - {INTEGER_ALIGN, 32, Align(4), Align(4)}, // i32 - {INTEGER_ALIGN, 64, Align(4), Align(8)}, // i64 - {FLOAT_ALIGN, 16, Align(2), Align(2)}, // half, bfloat - {FLOAT_ALIGN, 32, Align(4), Align(4)}, // float - {FLOAT_ALIGN, 64, Align(8), Align(8)}, // double - {FLOAT_ALIGN, 128, Align(16), Align(16)}, // ppcf128, quad, ... - {VECTOR_ALIGN, 64, Align(8), Align(8)}, // v2i32, v1i64, ... - {VECTOR_ALIGN, 128, Align(16), Align(16)}, // v16i8, v8i16, v4i32, ... - {AGGREGATE_ALIGN, 0, Align(1), Align(8)} // struct -}; - -void DataLayout::reset(StringRef Desc) { - clear(); - - LayoutMap = nullptr; - BigEndian = false; - AllocaAddrSpace = 0; - StackNaturalAlign.reset(); - ProgramAddrSpace = 0; - DefaultGlobalsAddrSpace = 0; - FunctionPtrAlign.reset(); - TheFunctionPtrAlignType = FunctionPtrAlignType::Independent; - ManglingMode = MM_None; - NonIntegralAddressSpaces.clear(); - - // Default alignments - for (const LayoutAlignElem &E : DefaultAlignments) { - if (Error Err = setAlignment((AlignTypeEnum)E.AlignType, E.ABIAlign, - E.PrefAlign, E.TypeBitWidth)) - return report_fatal_error(std::move(Err)); - } - if (Error Err = setPointerAlignment(0, Align(8), Align(8), 8, 8)) - return report_fatal_error(std::move(Err)); - - if (Error Err = parseSpecifier(Desc)) - return report_fatal_error(std::move(Err)); -} - -Expected DataLayout::parse(StringRef LayoutDescription) { - DataLayout Layout(""); - if (Error Err = Layout.parseSpecifier(LayoutDescription)) - return std::move(Err); - return Layout; -} - -static Error reportError(const Twine &Message) { - return createStringError(inconvertibleErrorCode(), Message); -} - -/// Checked version of split, to ensure mandatory subparts. -static Error split(StringRef Str, char Separator, - std::pair &Split) { - assert(!Str.empty() && "parse error, string can't be empty here"); - Split = Str.split(Separator); - if (Split.second.empty() && Split.first != Str) - return reportError("Trailing separator in datalayout string"); - if (!Split.second.empty() && Split.first.empty()) - return reportError("Expected token before separator in datalayout string"); - return Error::success(); -} - -/// Get an unsigned integer, including error checks. -template static Error getInt(StringRef R, IntTy &Result) { - bool error = R.getAsInteger(10, Result); (void)error; - if (error) - return reportError("not a number, or does not fit in an unsigned int"); - return Error::success(); -} - -/// Get an unsigned integer representing the number of bits and convert it into -/// bytes. Error out of not a byte width multiple. -template -static Error getIntInBytes(StringRef R, IntTy &Result) { - if (Error Err = getInt(R, Result)) - return Err; - if (Result % 8) - return reportError("number of bits must be a byte width multiple"); - Result /= 8; - return Error::success(); -} - -static Error getAddrSpace(StringRef R, unsigned &AddrSpace) { - if (Error Err = getInt(R, AddrSpace)) - return Err; - if (!isUInt<24>(AddrSpace)) - return reportError("Invalid address space, must be a 24-bit integer"); - return Error::success(); -} - -Error DataLayout::parseSpecifier(StringRef Desc) { - StringRepresentation = std::string(Desc); - while (!Desc.empty()) { - // Split at '-'. - std::pair Split; - if (Error Err = split(Desc, '-', Split)) - return Err; - Desc = Split.second; - - // Split at ':'. - if (Error Err = split(Split.first, ':', Split)) - return Err; - - // Aliases used below. - StringRef &Tok = Split.first; // Current token. - StringRef &Rest = Split.second; // The rest of the string. - - if (Tok == "ni") { - do { - if (Error Err = split(Rest, ':', Split)) - return Err; - Rest = Split.second; - unsigned AS; - if (Error Err = getInt(Split.first, AS)) - return Err; - if (AS == 0) - return reportError("Address space 0 can never be non-integral"); - NonIntegralAddressSpaces.push_back(AS); - } while (!Rest.empty()); - - continue; - } - - char Specifier = Tok.front(); - Tok = Tok.substr(1); - - switch (Specifier) { - case 's': - // Deprecated, but ignoring here to preserve loading older textual llvm - // ASM file - break; - case 'E': - BigEndian = true; - break; - case 'e': - BigEndian = false; - break; - case 'p': { - // Address space. - unsigned AddrSpace = 0; - if (!Tok.empty()) - if (Error Err = getInt(Tok, AddrSpace)) - return Err; - if (!isUInt<24>(AddrSpace)) - return reportError("Invalid address space, must be a 24bit integer"); - - // Size. - if (Rest.empty()) - return reportError( - "Missing size specification for pointer in datalayout string"); - if (Error Err = split(Rest, ':', Split)) - return Err; - unsigned PointerMemSize; - if (Error Err = getIntInBytes(Tok, PointerMemSize)) - return Err; - if (!PointerMemSize) - return reportError("Invalid pointer size of 0 bytes"); - - // ABI alignment. - if (Rest.empty()) - return reportError( - "Missing alignment specification for pointer in datalayout string"); - if (Error Err = split(Rest, ':', Split)) - return Err; - unsigned PointerABIAlign; - if (Error Err = getIntInBytes(Tok, PointerABIAlign)) - return Err; - if (!isPowerOf2_64(PointerABIAlign)) - return reportError("Pointer ABI alignment must be a power of 2"); - - // Size of index used in GEP for address calculation. - // The parameter is optional. By default it is equal to size of pointer. - unsigned IndexSize = PointerMemSize; - - // Preferred alignment. - unsigned PointerPrefAlign = PointerABIAlign; - if (!Rest.empty()) { - if (Error Err = split(Rest, ':', Split)) - return Err; - if (Error Err = getIntInBytes(Tok, PointerPrefAlign)) - return Err; - if (!isPowerOf2_64(PointerPrefAlign)) - return reportError( - "Pointer preferred alignment must be a power of 2"); - - // Now read the index. It is the second optional parameter here. - if (!Rest.empty()) { - if (Error Err = split(Rest, ':', Split)) - return Err; - if (Error Err = getIntInBytes(Tok, IndexSize)) - return Err; - if (!IndexSize) - return reportError("Invalid index size of 0 bytes"); - } - } - if (Error Err = setPointerAlignment( - AddrSpace, assumeAligned(PointerABIAlign), - assumeAligned(PointerPrefAlign), PointerMemSize, IndexSize)) - return Err; - break; - } - case 'i': - case 'v': - case 'f': - case 'a': { - AlignTypeEnum AlignType; - switch (Specifier) { - default: llvm_unreachable("Unexpected specifier!"); - case 'i': AlignType = INTEGER_ALIGN; break; - case 'v': AlignType = VECTOR_ALIGN; break; - case 'f': AlignType = FLOAT_ALIGN; break; - case 'a': AlignType = AGGREGATE_ALIGN; break; - } - - // Bit size. - unsigned Size = 0; - if (!Tok.empty()) - if (Error Err = getInt(Tok, Size)) - return Err; - - if (AlignType == AGGREGATE_ALIGN && Size != 0) - return reportError( - "Sized aggregate specification in datalayout string"); - - // ABI alignment. - if (Rest.empty()) - return reportError( - "Missing alignment specification in datalayout string"); - if (Error Err = split(Rest, ':', Split)) - return Err; - unsigned ABIAlign; - if (Error Err = getIntInBytes(Tok, ABIAlign)) - return Err; - if (AlignType != AGGREGATE_ALIGN && !ABIAlign) - return reportError( - "ABI alignment specification must be >0 for non-aggregate types"); - - if (!isUInt<16>(ABIAlign)) - return reportError("Invalid ABI alignment, must be a 16bit integer"); - if (ABIAlign != 0 && !isPowerOf2_64(ABIAlign)) - return reportError("Invalid ABI alignment, must be a power of 2"); - - // Preferred alignment. - unsigned PrefAlign = ABIAlign; - if (!Rest.empty()) { - if (Error Err = split(Rest, ':', Split)) - return Err; - if (Error Err = getIntInBytes(Tok, PrefAlign)) - return Err; - } - - if (!isUInt<16>(PrefAlign)) - return reportError( - "Invalid preferred alignment, must be a 16bit integer"); - if (PrefAlign != 0 && !isPowerOf2_64(PrefAlign)) - return reportError("Invalid preferred alignment, must be a power of 2"); - - if (Error Err = setAlignment(AlignType, assumeAligned(ABIAlign), - assumeAligned(PrefAlign), Size)) - return Err; - - break; - } - case 'n': // Native integer types. - while (true) { - unsigned Width; - if (Error Err = getInt(Tok, Width)) - return Err; - if (Width == 0) - return reportError( - "Zero width native integer type in datalayout string"); - LegalIntWidths.push_back(Width); - if (Rest.empty()) - break; - if (Error Err = split(Rest, ':', Split)) - return Err; - } - break; - case 'S': { // Stack natural alignment. - uint64_t Alignment; - if (Error Err = getIntInBytes(Tok, Alignment)) - return Err; - if (Alignment != 0 && !llvm::isPowerOf2_64(Alignment)) - return reportError("Alignment is neither 0 nor a power of 2"); - StackNaturalAlign = MaybeAlign(Alignment); - break; - } - case 'F': { - switch (Tok.front()) { - case 'i': - TheFunctionPtrAlignType = FunctionPtrAlignType::Independent; - break; - case 'n': - TheFunctionPtrAlignType = FunctionPtrAlignType::MultipleOfFunctionAlign; - break; - default: - return reportError("Unknown function pointer alignment type in " - "datalayout string"); - } - Tok = Tok.substr(1); - uint64_t Alignment; - if (Error Err = getIntInBytes(Tok, Alignment)) - return Err; - if (Alignment != 0 && !llvm::isPowerOf2_64(Alignment)) - return reportError("Alignment is neither 0 nor a power of 2"); - FunctionPtrAlign = MaybeAlign(Alignment); - break; - } - case 'P': { // Function address space. - if (Error Err = getAddrSpace(Tok, ProgramAddrSpace)) - return Err; - break; - } - case 'A': { // Default stack/alloca address space. - if (Error Err = getAddrSpace(Tok, AllocaAddrSpace)) - return Err; - break; - } - case 'G': { // Default address space for global variables. - if (Error Err = getAddrSpace(Tok, DefaultGlobalsAddrSpace)) - return Err; - break; - } - case 'm': - if (!Tok.empty()) - return reportError("Unexpected trailing characters after mangling " - "specifier in datalayout string"); - if (Rest.empty()) - return reportError("Expected mangling specifier in datalayout string"); - if (Rest.size() > 1) - return reportError("Unknown mangling specifier in datalayout string"); - switch(Rest[0]) { - default: - return reportError("Unknown mangling in datalayout string"); - case 'e': - ManglingMode = MM_ELF; - break; - case 'o': - ManglingMode = MM_MachO; - break; - case 'm': - ManglingMode = MM_Mips; - break; - case 'w': - ManglingMode = MM_WinCOFF; - break; - case 'x': - ManglingMode = MM_WinCOFFX86; - break; - case 'a': - ManglingMode = MM_XCOFF; - break; - } - break; - default: - return reportError("Unknown specifier in datalayout string"); - break; - } - } - - return Error::success(); -} - -DataLayout::DataLayout(const Module *M) { - init(M); -} +DataLayout::DataLayout(const Module *M) + : DataLayoutString(M->getDataLayout()) {} void DataLayout::init(const Module *M) { *this = M->getDataLayout(); } -bool DataLayout::operator==(const DataLayout &Other) const { - bool Ret = BigEndian == Other.BigEndian && - AllocaAddrSpace == Other.AllocaAddrSpace && - StackNaturalAlign == Other.StackNaturalAlign && - ProgramAddrSpace == Other.ProgramAddrSpace && - DefaultGlobalsAddrSpace == Other.DefaultGlobalsAddrSpace && - FunctionPtrAlign == Other.FunctionPtrAlign && - TheFunctionPtrAlignType == Other.TheFunctionPtrAlignType && - ManglingMode == Other.ManglingMode && - LegalIntWidths == Other.LegalIntWidths && - Alignments == Other.Alignments && Pointers == Other.Pointers; - // Note: getStringRepresentation() might differs, it is not canonicalized - return Ret; -} - -DataLayout::AlignmentsTy::iterator -DataLayout::findAlignmentLowerBound(AlignTypeEnum AlignType, - uint32_t BitWidth) { - auto Pair = std::make_pair((unsigned)AlignType, BitWidth); - return partition_point(Alignments, [=](const LayoutAlignElem &E) { - return std::make_pair(E.AlignType, E.TypeBitWidth) < Pair; - }); -} - -Error DataLayout::setAlignment(AlignTypeEnum align_type, Align abi_align, - Align pref_align, uint32_t bit_width) { - // AlignmentsTy::ABIAlign and AlignmentsTy::PrefAlign were once stored as - // uint16_t, it is unclear if there are requirements for alignment to be less - // than 2^16 other than storage. In the meantime we leave the restriction as - // an assert. See D67400 for context. - assert(Log2(abi_align) < 16 && Log2(pref_align) < 16 && "Alignment too big"); - if (!isUInt<24>(bit_width)) - return reportError("Invalid bit width, must be a 24bit integer"); - if (pref_align < abi_align) - return reportError( - "Preferred alignment cannot be less than the ABI alignment"); - - AlignmentsTy::iterator I = findAlignmentLowerBound(align_type, bit_width); - if (I != Alignments.end() && - I->AlignType == (unsigned)align_type && I->TypeBitWidth == bit_width) { - // Update the abi, preferred alignments. - I->ABIAlign = abi_align; - I->PrefAlign = pref_align; - } else { - // Insert before I to keep the vector sorted. - Alignments.insert(I, LayoutAlignElem::get(align_type, abi_align, - pref_align, bit_width)); - } - return Error::success(); -} - -const PointerAlignElem & -DataLayout::getPointerAlignElem(uint32_t AddressSpace) const { - if (AddressSpace != 0) { - auto I = lower_bound(Pointers, AddressSpace, - [](const PointerAlignElem &A, uint32_t AddressSpace) { - return A.AddressSpace < AddressSpace; - }); - if (I != Pointers.end() && I->AddressSpace == AddressSpace) - return *I; - } - - assert(Pointers[0].AddressSpace == 0); - return Pointers[0]; -} - -Error DataLayout::setPointerAlignment(uint32_t AddrSpace, Align ABIAlign, - Align PrefAlign, uint32_t TypeByteWidth, - uint32_t IndexWidth) { - if (PrefAlign < ABIAlign) - return reportError( - "Preferred alignment cannot be less than the ABI alignment"); - - auto I = lower_bound(Pointers, AddrSpace, - [](const PointerAlignElem &A, uint32_t AddressSpace) { - return A.AddressSpace < AddressSpace; - }); - if (I == Pointers.end() || I->AddressSpace != AddrSpace) { - Pointers.insert(I, PointerAlignElem::get(AddrSpace, ABIAlign, PrefAlign, - TypeByteWidth, IndexWidth)); - } else { - I->ABIAlign = ABIAlign; - I->PrefAlign = PrefAlign; - I->TypeByteWidth = TypeByteWidth; - I->IndexWidth = IndexWidth; - } - return Error::success(); -} - -Align DataLayout::getIntegerAlignment(uint32_t BitWidth, - bool abi_or_pref) const { - auto I = findAlignmentLowerBound(INTEGER_ALIGN, BitWidth); - // If we don't have an exact match, use alignment of next larger integer - // type. If there is none, use alignment of largest integer type by going - // back one element. - if (I == Alignments.end() || I->AlignType != INTEGER_ALIGN) - --I; - assert(I->AlignType == INTEGER_ALIGN && "Must be integer alignment"); - return abi_or_pref ? I->ABIAlign : I->PrefAlign; -} - namespace { class StructLayoutMap { @@ -657,17 +130,11 @@ } // end anonymous namespace void DataLayout::clear() { - LegalIntWidths.clear(); - Alignments.clear(); - Pointers.clear(); + DataLayoutString::clear(); delete static_cast(LayoutMap); LayoutMap = nullptr; } -DataLayout::~DataLayout() { - clear(); -} - const StructLayout *DataLayout::getStructLayout(StructType *Ty) const { if (!LayoutMap) LayoutMap = new StructLayoutMap(); @@ -690,26 +157,6 @@ return L; } -Align DataLayout::getPointerABIAlignment(unsigned AS) const { - return getPointerAlignElem(AS).ABIAlign; -} - -Align DataLayout::getPointerPrefAlignment(unsigned AS) const { - return getPointerAlignElem(AS).PrefAlign; -} - -unsigned DataLayout::getPointerSize(unsigned AS) const { - return getPointerAlignElem(AS).TypeByteWidth; -} - -unsigned DataLayout::getMaxPointerSize() const { - unsigned MaxPointerSize = 0; - for (auto &P : Pointers) - MaxPointerSize = std::max(MaxPointerSize, P.TypeByteWidth); - - return MaxPointerSize; -} - unsigned DataLayout::getPointerTypeSizeInBits(Type *Ty) const { assert(Ty->isPtrOrPtrVectorTy() && "This should only be called with a pointer or pointer vector type"); @@ -717,10 +164,6 @@ return getPointerSizeInBits(cast(Ty)->getAddressSpace()); } -unsigned DataLayout::getIndexSize(unsigned AS) const { - return getPointerAlignElem(AS).IndexWidth; -} - unsigned DataLayout::getIndexTypeSizeInBits(Type *Ty) const { assert(Ty->isPtrOrPtrVectorTy() && "This should only be called with a pointer or pointer vector type"); Index: llvm/lib/Support/CMakeLists.txt =================================================================== --- llvm/lib/Support/CMakeLists.txt +++ llvm/lib/Support/CMakeLists.txt @@ -112,6 +112,7 @@ ConvertUTFWrapper.cpp CrashRecoveryContext.cpp DataExtractor.cpp + DataLayoutString.cpp Debug.cpp DebugCounter.cpp DeltaAlgorithm.cpp Index: llvm/lib/Support/DataLayoutString.cpp =================================================================== --- /dev/null +++ llvm/lib/Support/DataLayoutString.cpp @@ -0,0 +1,597 @@ +//===- DataLayoutString.cpp - Data size & alignment routines ---------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines layout properties related to datatype size/offset/alignment +// information. +// +// This structure should be created once, filled in if the defaults are not +// correct and then passed around by const&. None of the members functions +// require modification to the object. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/DataLayoutString.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/TypeSize.h" +#include +#include +#include +#include +#include +#include + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// LayoutAlignElem, LayoutAlign support +//===----------------------------------------------------------------------===// + +LayoutAlignElem LayoutAlignElem::get(AlignTypeEnum align_type, Align abi_align, + Align pref_align, uint32_t bit_width) { + assert(abi_align <= pref_align && "Preferred alignment worse than ABI!"); + LayoutAlignElem retval; + retval.AlignType = align_type; + retval.ABIAlign = abi_align; + retval.PrefAlign = pref_align; + retval.TypeBitWidth = bit_width; + return retval; +} + +bool +LayoutAlignElem::operator==(const LayoutAlignElem &rhs) const { + return (AlignType == rhs.AlignType + && ABIAlign == rhs.ABIAlign + && PrefAlign == rhs.PrefAlign + && TypeBitWidth == rhs.TypeBitWidth); +} + +//===----------------------------------------------------------------------===// +// PointerAlignElem, PointerAlign support +//===----------------------------------------------------------------------===// + +PointerAlignElem PointerAlignElem::get(uint32_t AddressSpace, Align ABIAlign, + Align PrefAlign, uint32_t TypeByteWidth, + uint32_t IndexWidth) { + assert(ABIAlign <= PrefAlign && "Preferred alignment worse than ABI!"); + PointerAlignElem retval; + retval.AddressSpace = AddressSpace; + retval.ABIAlign = ABIAlign; + retval.PrefAlign = PrefAlign; + retval.TypeByteWidth = TypeByteWidth; + retval.IndexWidth = IndexWidth; + return retval; +} + +bool +PointerAlignElem::operator==(const PointerAlignElem &rhs) const { + return (ABIAlign == rhs.ABIAlign + && AddressSpace == rhs.AddressSpace + && PrefAlign == rhs.PrefAlign + && TypeByteWidth == rhs.TypeByteWidth + && IndexWidth == rhs.IndexWidth); +} + +//===----------------------------------------------------------------------===// +// DataLayoutString Class Implementation +//===----------------------------------------------------------------------===// + +const char *DataLayoutString::getManglingComponent(const Triple &T) { + if (T.isOSBinFormatMachO()) + return "-m:o"; + if (T.isOSWindows() && T.isOSBinFormatCOFF()) + return T.getArch() == Triple::x86 ? "-m:x" : "-m:w"; + if (T.isOSBinFormatXCOFF()) + return "-m:a"; + return "-m:e"; +} + +static const LayoutAlignElem DefaultAlignments[] = { + {INTEGER_ALIGN, 1, Align(1), Align(1)}, // i1 + {INTEGER_ALIGN, 8, Align(1), Align(1)}, // i8 + {INTEGER_ALIGN, 16, Align(2), Align(2)}, // i16 + {INTEGER_ALIGN, 32, Align(4), Align(4)}, // i32 + {INTEGER_ALIGN, 64, Align(4), Align(8)}, // i64 + {FLOAT_ALIGN, 16, Align(2), Align(2)}, // half, bfloat + {FLOAT_ALIGN, 32, Align(4), Align(4)}, // float + {FLOAT_ALIGN, 64, Align(8), Align(8)}, // double + {FLOAT_ALIGN, 128, Align(16), Align(16)}, // ppcf128, quad, ... + {VECTOR_ALIGN, 64, Align(8), Align(8)}, // v2i32, v1i64, ... + {VECTOR_ALIGN, 128, Align(16), Align(16)}, // v16i8, v8i16, v4i32, ... + {AGGREGATE_ALIGN, 0, Align(1), Align(8)} // struct +}; + +void DataLayoutString::reset(StringRef Desc) { + clear(); + + BigEndian = false; + AllocaAddrSpace = 0; + StackNaturalAlign.reset(); + ProgramAddrSpace = 0; + DefaultGlobalsAddrSpace = 0; + FunctionPtrAlign.reset(); + TheFunctionPtrAlignType = FunctionPtrAlignType::Independent; + ManglingMode = MM_None; + NonIntegralAddressSpaces.clear(); + + // Default alignments + for (const LayoutAlignElem &E : DefaultAlignments) { + if (Error Err = setAlignment((AlignTypeEnum)E.AlignType, E.ABIAlign, + E.PrefAlign, E.TypeBitWidth)) + return report_fatal_error(std::move(Err)); + } + if (Error Err = setPointerAlignment(0, Align(8), Align(8), 8, 8)) + return report_fatal_error(std::move(Err)); + + if (Error Err = parseSpecifier(Desc)) + return report_fatal_error(std::move(Err)); +} + +Expected DataLayoutString::parse(StringRef LayoutDescription) { + DataLayoutString Layout(""); + if (Error Err = Layout.parseSpecifier(LayoutDescription)) + return std::move(Err); + return Layout; +} + +static Error reportError(const Twine &Message) { + return createStringError(inconvertibleErrorCode(), Message); +} + +/// Checked version of split, to ensure mandatory subparts. +static Error split(StringRef Str, char Separator, + std::pair &Split) { + assert(!Str.empty() && "parse error, string can't be empty here"); + Split = Str.split(Separator); + if (Split.second.empty() && Split.first != Str) + return reportError("Trailing separator in datalayout string"); + if (!Split.second.empty() && Split.first.empty()) + return reportError("Expected token before separator in datalayout string"); + return Error::success(); +} + +/// Get an unsigned integer, including error checks. +template static Error getInt(StringRef R, IntTy &Result) { + bool error = R.getAsInteger(10, Result); (void)error; + if (error) + return reportError("not a number, or does not fit in an unsigned int"); + return Error::success(); +} + +/// Get an unsigned integer representing the number of bits and convert it into +/// bytes. Error out of not a byte width multiple. +template +static Error getIntInBytes(StringRef R, IntTy &Result) { + if (Error Err = getInt(R, Result)) + return Err; + if (Result % 8) + return reportError("number of bits must be a byte width multiple"); + Result /= 8; + return Error::success(); +} + +static Error getAddrSpace(StringRef R, unsigned &AddrSpace) { + if (Error Err = getInt(R, AddrSpace)) + return Err; + if (!isUInt<24>(AddrSpace)) + return reportError("Invalid address space, must be a 24-bit integer"); + return Error::success(); +} + +Error DataLayoutString::parseSpecifier(StringRef Desc) { + StringRepresentation = std::string(Desc); + while (!Desc.empty()) { + // Split at '-'. + std::pair Split; + if (Error Err = split(Desc, '-', Split)) + return Err; + Desc = Split.second; + + // Split at ':'. + if (Error Err = split(Split.first, ':', Split)) + return Err; + + // Aliases used below. + StringRef &Tok = Split.first; // Current token. + StringRef &Rest = Split.second; // The rest of the string. + + if (Tok == "ni") { + do { + if (Error Err = split(Rest, ':', Split)) + return Err; + Rest = Split.second; + unsigned AS; + if (Error Err = getInt(Split.first, AS)) + return Err; + if (AS == 0) + return reportError("Address space 0 can never be non-integral"); + NonIntegralAddressSpaces.push_back(AS); + } while (!Rest.empty()); + + continue; + } + + char Specifier = Tok.front(); + Tok = Tok.substr(1); + + switch (Specifier) { + case 's': + // Deprecated, but ignoring here to preserve loading older textual llvm + // ASM file + break; + case 'E': + BigEndian = true; + break; + case 'e': + BigEndian = false; + break; + case 'p': { + // Address space. + unsigned AddrSpace = 0; + if (!Tok.empty()) + if (Error Err = getInt(Tok, AddrSpace)) + return Err; + if (!isUInt<24>(AddrSpace)) + return reportError("Invalid address space, must be a 24bit integer"); + + // Size. + if (Rest.empty()) + return reportError( + "Missing size specification for pointer in datalayout string"); + if (Error Err = split(Rest, ':', Split)) + return Err; + unsigned PointerMemSize; + if (Error Err = getIntInBytes(Tok, PointerMemSize)) + return Err; + if (!PointerMemSize) + return reportError("Invalid pointer size of 0 bytes"); + + // ABI alignment. + if (Rest.empty()) + return reportError( + "Missing alignment specification for pointer in datalayout string"); + if (Error Err = split(Rest, ':', Split)) + return Err; + unsigned PointerABIAlign; + if (Error Err = getIntInBytes(Tok, PointerABIAlign)) + return Err; + if (!isPowerOf2_64(PointerABIAlign)) + return reportError("Pointer ABI alignment must be a power of 2"); + + // Size of index used in GEP for address calculation. + // The parameter is optional. By default it is equal to size of pointer. + unsigned IndexSize = PointerMemSize; + + // Preferred alignment. + unsigned PointerPrefAlign = PointerABIAlign; + if (!Rest.empty()) { + if (Error Err = split(Rest, ':', Split)) + return Err; + if (Error Err = getIntInBytes(Tok, PointerPrefAlign)) + return Err; + if (!isPowerOf2_64(PointerPrefAlign)) + return reportError( + "Pointer preferred alignment must be a power of 2"); + + // Now read the index. It is the second optional parameter here. + if (!Rest.empty()) { + if (Error Err = split(Rest, ':', Split)) + return Err; + if (Error Err = getIntInBytes(Tok, IndexSize)) + return Err; + if (!IndexSize) + return reportError("Invalid index size of 0 bytes"); + } + } + if (Error Err = setPointerAlignment( + AddrSpace, assumeAligned(PointerABIAlign), + assumeAligned(PointerPrefAlign), PointerMemSize, IndexSize)) + return Err; + break; + } + case 'i': + case 'v': + case 'f': + case 'a': { + AlignTypeEnum AlignType; + switch (Specifier) { + default: llvm_unreachable("Unexpected specifier!"); + case 'i': AlignType = INTEGER_ALIGN; break; + case 'v': AlignType = VECTOR_ALIGN; break; + case 'f': AlignType = FLOAT_ALIGN; break; + case 'a': AlignType = AGGREGATE_ALIGN; break; + } + + // Bit size. + unsigned Size = 0; + if (!Tok.empty()) + if (Error Err = getInt(Tok, Size)) + return Err; + + if (AlignType == AGGREGATE_ALIGN && Size != 0) + return reportError( + "Sized aggregate specification in datalayout string"); + + // ABI alignment. + if (Rest.empty()) + return reportError( + "Missing alignment specification in datalayout string"); + if (Error Err = split(Rest, ':', Split)) + return Err; + unsigned ABIAlign; + if (Error Err = getIntInBytes(Tok, ABIAlign)) + return Err; + if (AlignType != AGGREGATE_ALIGN && !ABIAlign) + return reportError( + "ABI alignment specification must be >0 for non-aggregate types"); + + if (!isUInt<16>(ABIAlign)) + return reportError("Invalid ABI alignment, must be a 16bit integer"); + if (ABIAlign != 0 && !isPowerOf2_64(ABIAlign)) + return reportError("Invalid ABI alignment, must be a power of 2"); + + // Preferred alignment. + unsigned PrefAlign = ABIAlign; + if (!Rest.empty()) { + if (Error Err = split(Rest, ':', Split)) + return Err; + if (Error Err = getIntInBytes(Tok, PrefAlign)) + return Err; + } + + if (!isUInt<16>(PrefAlign)) + return reportError( + "Invalid preferred alignment, must be a 16bit integer"); + if (PrefAlign != 0 && !isPowerOf2_64(PrefAlign)) + return reportError("Invalid preferred alignment, must be a power of 2"); + + if (Error Err = setAlignment(AlignType, assumeAligned(ABIAlign), + assumeAligned(PrefAlign), Size)) + return Err; + + break; + } + case 'n': // Native integer types. + while (true) { + unsigned Width; + if (Error Err = getInt(Tok, Width)) + return Err; + if (Width == 0) + return reportError( + "Zero width native integer type in datalayout string"); + LegalIntWidths.push_back(Width); + if (Rest.empty()) + break; + if (Error Err = split(Rest, ':', Split)) + return Err; + } + break; + case 'S': { // Stack natural alignment. + uint64_t Alignment; + if (Error Err = getIntInBytes(Tok, Alignment)) + return Err; + if (Alignment != 0 && !llvm::isPowerOf2_64(Alignment)) + return reportError("Alignment is neither 0 nor a power of 2"); + StackNaturalAlign = MaybeAlign(Alignment); + break; + } + case 'F': { + switch (Tok.front()) { + case 'i': + TheFunctionPtrAlignType = FunctionPtrAlignType::Independent; + break; + case 'n': + TheFunctionPtrAlignType = FunctionPtrAlignType::MultipleOfFunctionAlign; + break; + default: + return reportError("Unknown function pointer alignment type in " + "datalayout string"); + } + Tok = Tok.substr(1); + uint64_t Alignment; + if (Error Err = getIntInBytes(Tok, Alignment)) + return Err; + if (Alignment != 0 && !llvm::isPowerOf2_64(Alignment)) + return reportError("Alignment is neither 0 nor a power of 2"); + FunctionPtrAlign = MaybeAlign(Alignment); + break; + } + case 'P': { // Function address space. + if (Error Err = getAddrSpace(Tok, ProgramAddrSpace)) + return Err; + break; + } + case 'A': { // Default stack/alloca address space. + if (Error Err = getAddrSpace(Tok, AllocaAddrSpace)) + return Err; + break; + } + case 'G': { // Default address space for global variables. + if (Error Err = getAddrSpace(Tok, DefaultGlobalsAddrSpace)) + return Err; + break; + } + case 'm': + if (!Tok.empty()) + return reportError("Unexpected trailing characters after mangling " + "specifier in datalayout string"); + if (Rest.empty()) + return reportError("Expected mangling specifier in datalayout string"); + if (Rest.size() > 1) + return reportError("Unknown mangling specifier in datalayout string"); + switch(Rest[0]) { + default: + return reportError("Unknown mangling in datalayout string"); + case 'e': + ManglingMode = MM_ELF; + break; + case 'o': + ManglingMode = MM_MachO; + break; + case 'm': + ManglingMode = MM_Mips; + break; + case 'w': + ManglingMode = MM_WinCOFF; + break; + case 'x': + ManglingMode = MM_WinCOFFX86; + break; + case 'a': + ManglingMode = MM_XCOFF; + break; + } + break; + default: + return reportError("Unknown specifier in datalayout string"); + break; + } + } + + return Error::success(); +} + +bool DataLayoutString::operator==(const DataLayoutString &Other) const { + bool Ret = BigEndian == Other.BigEndian && + AllocaAddrSpace == Other.AllocaAddrSpace && + StackNaturalAlign == Other.StackNaturalAlign && + ProgramAddrSpace == Other.ProgramAddrSpace && + DefaultGlobalsAddrSpace == Other.DefaultGlobalsAddrSpace && + FunctionPtrAlign == Other.FunctionPtrAlign && + TheFunctionPtrAlignType == Other.TheFunctionPtrAlignType && + ManglingMode == Other.ManglingMode && + LegalIntWidths == Other.LegalIntWidths && + Alignments == Other.Alignments && Pointers == Other.Pointers; + // Note: getStringRepresentation() might differs, it is not canonicalized + return Ret; +} + +DataLayoutString::AlignmentsTy::iterator +DataLayoutString::findAlignmentLowerBound(AlignTypeEnum AlignType, + uint32_t BitWidth) { + auto Pair = std::make_pair((unsigned)AlignType, BitWidth); + return partition_point(Alignments, [=](const LayoutAlignElem &E) { + return std::make_pair(E.AlignType, E.TypeBitWidth) < Pair; + }); +} + +Error DataLayoutString::setAlignment(AlignTypeEnum align_type, Align abi_align, + Align pref_align, uint32_t bit_width) { + // AlignmentsTy::ABIAlign and AlignmentsTy::PrefAlign were once stored as + // uint16_t, it is unclear if there are requirements for alignment to be less + // than 2^16 other than storage. In the meantime we leave the restriction as + // an assert. See D67400 for context. + assert(Log2(abi_align) < 16 && Log2(pref_align) < 16 && "Alignment too big"); + if (!isUInt<24>(bit_width)) + return reportError("Invalid bit width, must be a 24bit integer"); + if (pref_align < abi_align) + return reportError( + "Preferred alignment cannot be less than the ABI alignment"); + + AlignmentsTy::iterator I = findAlignmentLowerBound(align_type, bit_width); + if (I != Alignments.end() && + I->AlignType == (unsigned)align_type && I->TypeBitWidth == bit_width) { + // Update the abi, preferred alignments. + I->ABIAlign = abi_align; + I->PrefAlign = pref_align; + } else { + // Insert before I to keep the vector sorted. + Alignments.insert(I, LayoutAlignElem::get(align_type, abi_align, + pref_align, bit_width)); + } + return Error::success(); +} + +const PointerAlignElem & +DataLayoutString::getPointerAlignElem(uint32_t AddressSpace) const { + if (AddressSpace != 0) { + auto I = lower_bound(Pointers, AddressSpace, + [](const PointerAlignElem &A, uint32_t AddressSpace) { + return A.AddressSpace < AddressSpace; + }); + if (I != Pointers.end() && I->AddressSpace == AddressSpace) + return *I; + } + + assert(Pointers[0].AddressSpace == 0); + return Pointers[0]; +} + +Error DataLayoutString::setPointerAlignment(uint32_t AddrSpace, Align ABIAlign, + Align PrefAlign, uint32_t TypeByteWidth, + uint32_t IndexWidth) { + if (PrefAlign < ABIAlign) + return reportError( + "Preferred alignment cannot be less than the ABI alignment"); + + auto I = lower_bound(Pointers, AddrSpace, + [](const PointerAlignElem &A, uint32_t AddressSpace) { + return A.AddressSpace < AddressSpace; + }); + if (I == Pointers.end() || I->AddressSpace != AddrSpace) { + Pointers.insert(I, PointerAlignElem::get(AddrSpace, ABIAlign, PrefAlign, + TypeByteWidth, IndexWidth)); + } else { + I->ABIAlign = ABIAlign; + I->PrefAlign = PrefAlign; + I->TypeByteWidth = TypeByteWidth; + I->IndexWidth = IndexWidth; + } + return Error::success(); +} + +Align DataLayoutString::getIntegerAlignment(uint32_t BitWidth, + bool abi_or_pref) const { + auto I = findAlignmentLowerBound(INTEGER_ALIGN, BitWidth); + // If we don't have an exact match, use alignment of next larger integer + // type. If there is none, use alignment of largest integer type by going + // back one element. + if (I == Alignments.end() || I->AlignType != INTEGER_ALIGN) + --I; + assert(I->AlignType == INTEGER_ALIGN && "Must be integer alignment"); + return abi_or_pref ? I->ABIAlign : I->PrefAlign; +} + +void DataLayoutString::clear() { + LegalIntWidths.clear(); + Alignments.clear(); + Pointers.clear(); +} + +DataLayoutString::~DataLayoutString() { + clear(); +} + +Align DataLayoutString::getPointerABIAlignment(unsigned AS) const { + return getPointerAlignElem(AS).ABIAlign; +} + +Align DataLayoutString::getPointerPrefAlignment(unsigned AS) const { + return getPointerAlignElem(AS).PrefAlign; +} + +unsigned DataLayoutString::getPointerSize(unsigned AS) const { + return getPointerAlignElem(AS).TypeByteWidth; +} + +unsigned DataLayoutString::getMaxPointerSize() const { + unsigned MaxPointerSize = 0; + for (auto &P : Pointers) + MaxPointerSize = std::max(MaxPointerSize, P.TypeByteWidth); + + return MaxPointerSize; +} + +unsigned DataLayoutString::getIndexSize(unsigned AS) const { + return getPointerAlignElem(AS).IndexWidth; +} Index: llvm/utils/gn/secondary/clang/lib/Basic/BUILD.gn =================================================================== --- llvm/utils/gn/secondary/clang/lib/Basic/BUILD.gn +++ llvm/utils/gn/secondary/clang/lib/Basic/BUILD.gn @@ -45,10 +45,10 @@ "//clang/include/clang/Sema:AttrParsedAttrKinds", "//clang/include/clang/Sema:AttrSpellingListIndex", "//llvm/include/llvm/Config:llvm-config", - "//llvm/lib/IR", "//llvm/lib/MC", "//llvm/lib/Support", ] + assert_no_deps = [ "//llvm/lib/IR" ] include_dirs = [ "." ] sources = [ "Attributes.cpp", Index: llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn =================================================================== --- llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn +++ llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn @@ -63,6 +63,7 @@ "DAGDeltaAlgorithm.cpp", "DJB.cpp", "DataExtractor.cpp", + "DataLayoutString.cpp", "Debug.cpp", "DebugCounter.cpp", "DeltaAlgorithm.cpp",