mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 19:47:05 +00:00

The check for `isOSWindows() || isUEFI()` is used in several places across the codebase. Introducing `isOSWindowsOrUEFI()` in Triple.h to simplify these checks.
1023 lines
36 KiB
C++
1023 lines
36 KiB
C++
//===- DataLayout.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/IR/DataLayout.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
#include "llvm/IR/GetElementPtrTypeIterator.h"
|
|
#include "llvm/IR/GlobalVariable.h"
|
|
#include "llvm/IR/Type.h"
|
|
#include "llvm/IR/Value.h"
|
|
#include "llvm/Support/Casting.h"
|
|
#include "llvm/Support/Error.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/MathExtras.h"
|
|
#include "llvm/Support/MemAlloc.h"
|
|
#include "llvm/Support/TypeSize.h"
|
|
#include "llvm/TargetParser/Triple.h"
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <new>
|
|
#include <utility>
|
|
|
|
using namespace llvm;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Support for StructLayout
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
StructLayout::StructLayout(StructType *ST, const DataLayout &DL)
|
|
: StructSize(TypeSize::getFixed(0)) {
|
|
assert(!ST->isOpaque() && "Cannot get layout of opaque structs");
|
|
IsPadded = false;
|
|
NumElements = ST->getNumElements();
|
|
|
|
// Loop over each of the elements, placing them in memory.
|
|
for (unsigned i = 0, e = NumElements; i != e; ++i) {
|
|
Type *Ty = ST->getElementType(i);
|
|
if (i == 0 && Ty->isScalableTy())
|
|
StructSize = TypeSize::getScalable(0);
|
|
|
|
const Align TyAlign = ST->isPacked() ? Align(1) : DL.getABITypeAlign(Ty);
|
|
|
|
// Add padding if necessary to align the data element properly.
|
|
// Currently the only structure with scalable size will be the homogeneous
|
|
// scalable vector types. Homogeneous scalable vector types have members of
|
|
// the same data type so no alignment issue will happen. The condition here
|
|
// assumes so and needs to be adjusted if this assumption changes (e.g. we
|
|
// support structures with arbitrary scalable data type, or structure that
|
|
// contains both fixed size and scalable size data type members).
|
|
if (!StructSize.isScalable() && !isAligned(TyAlign, StructSize)) {
|
|
IsPadded = true;
|
|
StructSize = TypeSize::getFixed(alignTo(StructSize, TyAlign));
|
|
}
|
|
|
|
// Keep track of maximum alignment constraint.
|
|
StructAlignment = std::max(TyAlign, StructAlignment);
|
|
|
|
getMemberOffsets()[i] = StructSize;
|
|
// Consume space for this data item
|
|
StructSize += DL.getTypeAllocSize(Ty);
|
|
}
|
|
|
|
// Add padding to the end of the struct so that it could be put in an array
|
|
// and all array elements would be aligned correctly.
|
|
if (!StructSize.isScalable() && !isAligned(StructAlignment, StructSize)) {
|
|
IsPadded = true;
|
|
StructSize = TypeSize::getFixed(alignTo(StructSize, StructAlignment));
|
|
}
|
|
}
|
|
|
|
/// getElementContainingOffset - Given a valid offset into the structure,
|
|
/// return the structure index that contains it.
|
|
unsigned StructLayout::getElementContainingOffset(uint64_t FixedOffset) const {
|
|
assert(!StructSize.isScalable() &&
|
|
"Cannot get element at offset for structure containing scalable "
|
|
"vector types");
|
|
TypeSize Offset = TypeSize::getFixed(FixedOffset);
|
|
ArrayRef<TypeSize> MemberOffsets = getMemberOffsets();
|
|
|
|
const auto *SI =
|
|
std::upper_bound(MemberOffsets.begin(), MemberOffsets.end(), Offset,
|
|
[](TypeSize LHS, TypeSize RHS) -> bool {
|
|
return TypeSize::isKnownLT(LHS, RHS);
|
|
});
|
|
assert(SI != MemberOffsets.begin() && "Offset not in structure type!");
|
|
--SI;
|
|
assert(TypeSize::isKnownLE(*SI, Offset) && "upper_bound didn't work");
|
|
assert(
|
|
(SI == MemberOffsets.begin() || TypeSize::isKnownLE(*(SI - 1), Offset)) &&
|
|
(SI + 1 == MemberOffsets.end() ||
|
|
TypeSize::isKnownGT(*(SI + 1), Offset)) &&
|
|
"Upper bound didn't work!");
|
|
|
|
// Multiple fields can have the same offset if any of them are zero sized.
|
|
// For example, in { i32, [0 x i32], i32 }, searching for offset 4 will stop
|
|
// at the i32 element, because it is the last element at that offset. This is
|
|
// the right one to return, because anything after it will have a higher
|
|
// offset, implying that this element is non-empty.
|
|
return SI - MemberOffsets.begin();
|
|
}
|
|
|
|
namespace {
|
|
|
|
class StructLayoutMap {
|
|
using LayoutInfoTy = DenseMap<StructType *, StructLayout *>;
|
|
LayoutInfoTy LayoutInfo;
|
|
|
|
public:
|
|
~StructLayoutMap() {
|
|
// Remove any layouts.
|
|
for (const auto &I : LayoutInfo) {
|
|
StructLayout *Value = I.second;
|
|
Value->~StructLayout();
|
|
free(Value);
|
|
}
|
|
}
|
|
|
|
StructLayout *&operator[](StructType *STy) { return LayoutInfo[STy]; }
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// DataLayout Class Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool DataLayout::PrimitiveSpec::operator==(const PrimitiveSpec &Other) const {
|
|
return BitWidth == Other.BitWidth && ABIAlign == Other.ABIAlign &&
|
|
PrefAlign == Other.PrefAlign;
|
|
}
|
|
|
|
bool DataLayout::PointerSpec::operator==(const PointerSpec &Other) const {
|
|
return AddrSpace == Other.AddrSpace && BitWidth == Other.BitWidth &&
|
|
ABIAlign == Other.ABIAlign && PrefAlign == Other.PrefAlign &&
|
|
IndexBitWidth == Other.IndexBitWidth &&
|
|
IsNonIntegral == Other.IsNonIntegral;
|
|
}
|
|
|
|
namespace {
|
|
/// Predicate to sort primitive specs by bit width.
|
|
struct LessPrimitiveBitWidth {
|
|
bool operator()(const DataLayout::PrimitiveSpec &LHS,
|
|
unsigned RHSBitWidth) const {
|
|
return LHS.BitWidth < RHSBitWidth;
|
|
}
|
|
};
|
|
|
|
/// Predicate to sort pointer specs by address space number.
|
|
struct LessPointerAddrSpace {
|
|
bool operator()(const DataLayout::PointerSpec &LHS,
|
|
unsigned RHSAddrSpace) const {
|
|
return LHS.AddrSpace < RHSAddrSpace;
|
|
}
|
|
};
|
|
} // namespace
|
|
|
|
const char *DataLayout::getManglingComponent(const Triple &T) {
|
|
if (T.isOSBinFormatGOFF())
|
|
return "-m:l";
|
|
if (T.isOSBinFormatMachO())
|
|
return "-m:o";
|
|
if (T.isOSWindowsOrUEFI() && T.isOSBinFormatCOFF())
|
|
return T.getArch() == Triple::x86 ? "-m:x" : "-m:w";
|
|
if (T.isOSBinFormatXCOFF())
|
|
return "-m:a";
|
|
return "-m:e";
|
|
}
|
|
|
|
// Default primitive type specifications.
|
|
// NOTE: These arrays must be sorted by type bit width.
|
|
constexpr DataLayout::PrimitiveSpec DefaultIntSpecs[] = {
|
|
{1, Align::Constant<1>(), Align::Constant<1>()}, // i1:8:8
|
|
{8, Align::Constant<1>(), Align::Constant<1>()}, // i8:8:8
|
|
{16, Align::Constant<2>(), Align::Constant<2>()}, // i16:16:16
|
|
{32, Align::Constant<4>(), Align::Constant<4>()}, // i32:32:32
|
|
{64, Align::Constant<4>(), Align::Constant<8>()}, // i64:32:64
|
|
};
|
|
constexpr DataLayout::PrimitiveSpec DefaultFloatSpecs[] = {
|
|
{16, Align::Constant<2>(), Align::Constant<2>()}, // f16:16:16
|
|
{32, Align::Constant<4>(), Align::Constant<4>()}, // f32:32:32
|
|
{64, Align::Constant<8>(), Align::Constant<8>()}, // f64:64:64
|
|
{128, Align::Constant<16>(), Align::Constant<16>()}, // f128:128:128
|
|
};
|
|
constexpr DataLayout::PrimitiveSpec DefaultVectorSpecs[] = {
|
|
{64, Align::Constant<8>(), Align::Constant<8>()}, // v64:64:64
|
|
{128, Align::Constant<16>(), Align::Constant<16>()}, // v128:128:128
|
|
};
|
|
|
|
// Default pointer type specifications.
|
|
constexpr DataLayout::PointerSpec DefaultPointerSpecs[] = {
|
|
// p0:64:64:64:64
|
|
{0, 64, Align::Constant<8>(), Align::Constant<8>(), 64, false},
|
|
};
|
|
|
|
DataLayout::DataLayout()
|
|
: IntSpecs(ArrayRef(DefaultIntSpecs)),
|
|
FloatSpecs(ArrayRef(DefaultFloatSpecs)),
|
|
VectorSpecs(ArrayRef(DefaultVectorSpecs)),
|
|
PointerSpecs(ArrayRef(DefaultPointerSpecs)) {}
|
|
|
|
DataLayout::DataLayout(StringRef LayoutString) : DataLayout() {
|
|
if (Error Err = parseLayoutString(LayoutString))
|
|
report_fatal_error(std::move(Err));
|
|
}
|
|
|
|
DataLayout &DataLayout::operator=(const DataLayout &Other) {
|
|
delete static_cast<StructLayoutMap *>(LayoutMap);
|
|
LayoutMap = nullptr;
|
|
StringRepresentation = Other.StringRepresentation;
|
|
BigEndian = Other.BigEndian;
|
|
AllocaAddrSpace = Other.AllocaAddrSpace;
|
|
ProgramAddrSpace = Other.ProgramAddrSpace;
|
|
DefaultGlobalsAddrSpace = Other.DefaultGlobalsAddrSpace;
|
|
StackNaturalAlign = Other.StackNaturalAlign;
|
|
FunctionPtrAlign = Other.FunctionPtrAlign;
|
|
TheFunctionPtrAlignType = Other.TheFunctionPtrAlignType;
|
|
ManglingMode = Other.ManglingMode;
|
|
LegalIntWidths = Other.LegalIntWidths;
|
|
IntSpecs = Other.IntSpecs;
|
|
FloatSpecs = Other.FloatSpecs;
|
|
VectorSpecs = Other.VectorSpecs;
|
|
PointerSpecs = Other.PointerSpecs;
|
|
StructABIAlignment = Other.StructABIAlignment;
|
|
StructPrefAlignment = Other.StructPrefAlignment;
|
|
return *this;
|
|
}
|
|
|
|
bool DataLayout::operator==(const DataLayout &Other) const {
|
|
// NOTE: StringRepresentation might differ, it is not canonicalized.
|
|
return BigEndian == Other.BigEndian &&
|
|
AllocaAddrSpace == Other.AllocaAddrSpace &&
|
|
ProgramAddrSpace == Other.ProgramAddrSpace &&
|
|
DefaultGlobalsAddrSpace == Other.DefaultGlobalsAddrSpace &&
|
|
StackNaturalAlign == Other.StackNaturalAlign &&
|
|
FunctionPtrAlign == Other.FunctionPtrAlign &&
|
|
TheFunctionPtrAlignType == Other.TheFunctionPtrAlignType &&
|
|
ManglingMode == Other.ManglingMode &&
|
|
LegalIntWidths == Other.LegalIntWidths && IntSpecs == Other.IntSpecs &&
|
|
FloatSpecs == Other.FloatSpecs && VectorSpecs == Other.VectorSpecs &&
|
|
PointerSpecs == Other.PointerSpecs &&
|
|
StructABIAlignment == Other.StructABIAlignment &&
|
|
StructPrefAlignment == Other.StructPrefAlignment;
|
|
}
|
|
|
|
Expected<DataLayout> DataLayout::parse(StringRef LayoutString) {
|
|
DataLayout Layout;
|
|
if (Error Err = Layout.parseLayoutString(LayoutString))
|
|
return std::move(Err);
|
|
return Layout;
|
|
}
|
|
|
|
static Error createSpecFormatError(Twine Format) {
|
|
return createStringError("malformed specification, must be of the form \"" +
|
|
Format + "\"");
|
|
}
|
|
|
|
/// Attempts to parse an address space component of a specification.
|
|
static Error parseAddrSpace(StringRef Str, unsigned &AddrSpace) {
|
|
if (Str.empty())
|
|
return createStringError("address space component cannot be empty");
|
|
|
|
if (!to_integer(Str, AddrSpace, 10) || !isUInt<24>(AddrSpace))
|
|
return createStringError("address space must be a 24-bit integer");
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
/// Attempts to parse a size component of a specification.
|
|
static Error parseSize(StringRef Str, unsigned &BitWidth,
|
|
StringRef Name = "size") {
|
|
if (Str.empty())
|
|
return createStringError(Name + " component cannot be empty");
|
|
|
|
if (!to_integer(Str, BitWidth, 10) || BitWidth == 0 || !isUInt<24>(BitWidth))
|
|
return createStringError(Name + " must be a non-zero 24-bit integer");
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
/// Attempts to parse an alignment component of a specification.
|
|
///
|
|
/// On success, returns the value converted to byte amount in \p Alignment.
|
|
/// If the value is zero and \p AllowZero is true, \p Alignment is set to one.
|
|
///
|
|
/// Return an error in a number of cases:
|
|
/// - \p Str is empty or contains characters other than decimal digits;
|
|
/// - the value is zero and \p AllowZero is false;
|
|
/// - the value is too large;
|
|
/// - the value is not a multiple of the byte width;
|
|
/// - the value converted to byte amount is not not a power of two.
|
|
static Error parseAlignment(StringRef Str, Align &Alignment, StringRef Name,
|
|
bool AllowZero = false) {
|
|
if (Str.empty())
|
|
return createStringError(Name + " alignment component cannot be empty");
|
|
|
|
unsigned Value;
|
|
if (!to_integer(Str, Value, 10) || !isUInt<16>(Value))
|
|
return createStringError(Name + " alignment must be a 16-bit integer");
|
|
|
|
if (Value == 0) {
|
|
if (!AllowZero)
|
|
return createStringError(Name + " alignment must be non-zero");
|
|
Alignment = Align(1);
|
|
return Error::success();
|
|
}
|
|
|
|
constexpr unsigned ByteWidth = 8;
|
|
if (Value % ByteWidth || !isPowerOf2_32(Value / ByteWidth))
|
|
return createStringError(
|
|
Name + " alignment must be a power of two times the byte width");
|
|
|
|
Alignment = Align(Value / ByteWidth);
|
|
return Error::success();
|
|
}
|
|
|
|
Error DataLayout::parsePrimitiveSpec(StringRef Spec) {
|
|
// [ifv]<size>:<abi>[:<pref>]
|
|
SmallVector<StringRef, 3> Components;
|
|
char Specifier = Spec.front();
|
|
assert(Specifier == 'i' || Specifier == 'f' || Specifier == 'v');
|
|
Spec.drop_front().split(Components, ':');
|
|
|
|
if (Components.size() < 2 || Components.size() > 3)
|
|
return createSpecFormatError(Twine(Specifier) + "<size>:<abi>[:<pref>]");
|
|
|
|
// Size. Required, cannot be zero.
|
|
unsigned BitWidth;
|
|
if (Error Err = parseSize(Components[0], BitWidth))
|
|
return Err;
|
|
|
|
// ABI alignment.
|
|
Align ABIAlign;
|
|
if (Error Err = parseAlignment(Components[1], ABIAlign, "ABI"))
|
|
return Err;
|
|
|
|
if (Specifier == 'i' && BitWidth == 8 && ABIAlign != 1)
|
|
return createStringError("i8 must be 8-bit aligned");
|
|
|
|
// Preferred alignment. Optional, defaults to the ABI alignment.
|
|
Align PrefAlign = ABIAlign;
|
|
if (Components.size() > 2)
|
|
if (Error Err = parseAlignment(Components[2], PrefAlign, "preferred"))
|
|
return Err;
|
|
|
|
if (PrefAlign < ABIAlign)
|
|
return createStringError(
|
|
"preferred alignment cannot be less than the ABI alignment");
|
|
|
|
setPrimitiveSpec(Specifier, BitWidth, ABIAlign, PrefAlign);
|
|
return Error::success();
|
|
}
|
|
|
|
Error DataLayout::parseAggregateSpec(StringRef Spec) {
|
|
// a<size>:<abi>[:<pref>]
|
|
SmallVector<StringRef, 3> Components;
|
|
assert(Spec.front() == 'a');
|
|
Spec.drop_front().split(Components, ':');
|
|
|
|
if (Components.size() < 2 || Components.size() > 3)
|
|
return createSpecFormatError("a:<abi>[:<pref>]");
|
|
|
|
// According to LangRef, <size> component must be absent altogether.
|
|
// For backward compatibility, allow it to be specified, but require
|
|
// it to be zero.
|
|
if (!Components[0].empty()) {
|
|
unsigned BitWidth;
|
|
if (!to_integer(Components[0], BitWidth, 10) || BitWidth != 0)
|
|
return createStringError("size must be zero");
|
|
}
|
|
|
|
// ABI alignment. Required. Can be zero, meaning use one byte alignment.
|
|
Align ABIAlign;
|
|
if (Error Err =
|
|
parseAlignment(Components[1], ABIAlign, "ABI", /*AllowZero=*/true))
|
|
return Err;
|
|
|
|
// Preferred alignment. Optional, defaults to the ABI alignment.
|
|
Align PrefAlign = ABIAlign;
|
|
if (Components.size() > 2)
|
|
if (Error Err = parseAlignment(Components[2], PrefAlign, "preferred"))
|
|
return Err;
|
|
|
|
if (PrefAlign < ABIAlign)
|
|
return createStringError(
|
|
"preferred alignment cannot be less than the ABI alignment");
|
|
|
|
StructABIAlignment = ABIAlign;
|
|
StructPrefAlignment = PrefAlign;
|
|
return Error::success();
|
|
}
|
|
|
|
Error DataLayout::parsePointerSpec(StringRef Spec) {
|
|
// p[<n>]:<size>:<abi>[:<pref>[:<idx>]]
|
|
SmallVector<StringRef, 5> Components;
|
|
assert(Spec.front() == 'p');
|
|
Spec.drop_front().split(Components, ':');
|
|
|
|
if (Components.size() < 3 || Components.size() > 5)
|
|
return createSpecFormatError("p[<n>]:<size>:<abi>[:<pref>[:<idx>]]");
|
|
|
|
// Address space. Optional, defaults to 0.
|
|
unsigned AddrSpace = 0;
|
|
if (!Components[0].empty())
|
|
if (Error Err = parseAddrSpace(Components[0], AddrSpace))
|
|
return Err;
|
|
|
|
// Size. Required, cannot be zero.
|
|
unsigned BitWidth;
|
|
if (Error Err = parseSize(Components[1], BitWidth, "pointer size"))
|
|
return Err;
|
|
|
|
// ABI alignment. Required, cannot be zero.
|
|
Align ABIAlign;
|
|
if (Error Err = parseAlignment(Components[2], ABIAlign, "ABI"))
|
|
return Err;
|
|
|
|
// Preferred alignment. Optional, defaults to the ABI alignment.
|
|
// Cannot be zero.
|
|
Align PrefAlign = ABIAlign;
|
|
if (Components.size() > 3)
|
|
if (Error Err = parseAlignment(Components[3], PrefAlign, "preferred"))
|
|
return Err;
|
|
|
|
if (PrefAlign < ABIAlign)
|
|
return createStringError(
|
|
"preferred alignment cannot be less than the ABI alignment");
|
|
|
|
// Index size. Optional, defaults to pointer size. Cannot be zero.
|
|
unsigned IndexBitWidth = BitWidth;
|
|
if (Components.size() > 4)
|
|
if (Error Err = parseSize(Components[4], IndexBitWidth, "index size"))
|
|
return Err;
|
|
|
|
if (IndexBitWidth > BitWidth)
|
|
return createStringError(
|
|
"index size cannot be larger than the pointer size");
|
|
|
|
setPointerSpec(AddrSpace, BitWidth, ABIAlign, PrefAlign, IndexBitWidth,
|
|
false);
|
|
return Error::success();
|
|
}
|
|
|
|
Error DataLayout::parseSpecification(
|
|
StringRef Spec, SmallVectorImpl<unsigned> &NonIntegralAddressSpaces) {
|
|
// The "ni" specifier is the only two-character specifier. Handle it first.
|
|
if (Spec.starts_with("ni")) {
|
|
// ni:<address space>[:<address space>]...
|
|
StringRef Rest = Spec.drop_front(2);
|
|
|
|
// Drop the first ':', then split the rest of the string the usual way.
|
|
if (!Rest.consume_front(":"))
|
|
return createSpecFormatError("ni:<address space>[:<address space>]...");
|
|
|
|
for (StringRef Str : split(Rest, ':')) {
|
|
unsigned AddrSpace;
|
|
if (Error Err = parseAddrSpace(Str, AddrSpace))
|
|
return Err;
|
|
if (AddrSpace == 0)
|
|
return createStringError("address space 0 cannot be non-integral");
|
|
NonIntegralAddressSpaces.push_back(AddrSpace);
|
|
}
|
|
return Error::success();
|
|
}
|
|
|
|
// The rest of the specifiers are single-character.
|
|
assert(!Spec.empty() && "Empty specification is handled by the caller");
|
|
char Specifier = Spec.front();
|
|
|
|
if (Specifier == 'i' || Specifier == 'f' || Specifier == 'v')
|
|
return parsePrimitiveSpec(Spec);
|
|
|
|
if (Specifier == 'a')
|
|
return parseAggregateSpec(Spec);
|
|
|
|
if (Specifier == 'p')
|
|
return parsePointerSpec(Spec);
|
|
|
|
StringRef Rest = Spec.drop_front();
|
|
switch (Specifier) {
|
|
case 's':
|
|
// Deprecated, but ignoring here to preserve loading older textual llvm
|
|
// ASM file
|
|
break;
|
|
case 'e':
|
|
case 'E':
|
|
if (!Rest.empty())
|
|
return createStringError(
|
|
"malformed specification, must be just 'e' or 'E'");
|
|
BigEndian = Specifier == 'E';
|
|
break;
|
|
case 'n': // Native integer types.
|
|
// n<size>[:<size>]...
|
|
for (StringRef Str : split(Rest, ':')) {
|
|
unsigned BitWidth;
|
|
if (Error Err = parseSize(Str, BitWidth))
|
|
return Err;
|
|
LegalIntWidths.push_back(BitWidth);
|
|
}
|
|
break;
|
|
case 'S': { // Stack natural alignment.
|
|
// S<size>
|
|
if (Rest.empty())
|
|
return createSpecFormatError("S<size>");
|
|
Align Alignment;
|
|
if (Error Err = parseAlignment(Rest, Alignment, "stack natural"))
|
|
return Err;
|
|
StackNaturalAlign = Alignment;
|
|
break;
|
|
}
|
|
case 'F': {
|
|
// F<type><abi>
|
|
if (Rest.empty())
|
|
return createSpecFormatError("F<type><abi>");
|
|
char Type = Rest.front();
|
|
Rest = Rest.drop_front();
|
|
switch (Type) {
|
|
case 'i':
|
|
TheFunctionPtrAlignType = FunctionPtrAlignType::Independent;
|
|
break;
|
|
case 'n':
|
|
TheFunctionPtrAlignType = FunctionPtrAlignType::MultipleOfFunctionAlign;
|
|
break;
|
|
default:
|
|
return createStringError("unknown function pointer alignment type '" +
|
|
Twine(Type) + "'");
|
|
}
|
|
Align Alignment;
|
|
if (Error Err = parseAlignment(Rest, Alignment, "ABI"))
|
|
return Err;
|
|
FunctionPtrAlign = Alignment;
|
|
break;
|
|
}
|
|
case 'P': { // Function address space.
|
|
if (Rest.empty())
|
|
return createSpecFormatError("P<address space>");
|
|
if (Error Err = parseAddrSpace(Rest, ProgramAddrSpace))
|
|
return Err;
|
|
break;
|
|
}
|
|
case 'A': { // Default stack/alloca address space.
|
|
if (Rest.empty())
|
|
return createSpecFormatError("A<address space>");
|
|
if (Error Err = parseAddrSpace(Rest, AllocaAddrSpace))
|
|
return Err;
|
|
break;
|
|
}
|
|
case 'G': { // Default address space for global variables.
|
|
if (Rest.empty())
|
|
return createSpecFormatError("G<address space>");
|
|
if (Error Err = parseAddrSpace(Rest, DefaultGlobalsAddrSpace))
|
|
return Err;
|
|
break;
|
|
}
|
|
case 'm':
|
|
if (!Rest.consume_front(":") || Rest.empty())
|
|
return createSpecFormatError("m:<mangling>");
|
|
if (Rest.size() > 1)
|
|
return createStringError("unknown mangling mode");
|
|
switch (Rest[0]) {
|
|
default:
|
|
return createStringError("unknown mangling mode");
|
|
case 'e':
|
|
ManglingMode = MM_ELF;
|
|
break;
|
|
case 'l':
|
|
ManglingMode = MM_GOFF;
|
|
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 createStringError("unknown specifier '" + Twine(Specifier) + "'");
|
|
}
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
Error DataLayout::parseLayoutString(StringRef LayoutString) {
|
|
StringRepresentation = std::string(LayoutString);
|
|
|
|
if (LayoutString.empty())
|
|
return Error::success();
|
|
|
|
// Split the data layout string into specifications separated by '-' and
|
|
// parse each specification individually, updating internal data structures.
|
|
SmallVector<unsigned, 8> NonIntegralAddressSpaces;
|
|
for (StringRef Spec : split(LayoutString, '-')) {
|
|
if (Spec.empty())
|
|
return createStringError("empty specification is not allowed");
|
|
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();
|
|
}
|
|
|
|
void DataLayout::setPrimitiveSpec(char Specifier, uint32_t BitWidth,
|
|
Align ABIAlign, Align PrefAlign) {
|
|
SmallVectorImpl<PrimitiveSpec> *Specs;
|
|
switch (Specifier) {
|
|
default:
|
|
llvm_unreachable("Unexpected specifier");
|
|
case 'i':
|
|
Specs = &IntSpecs;
|
|
break;
|
|
case 'f':
|
|
Specs = &FloatSpecs;
|
|
break;
|
|
case 'v':
|
|
Specs = &VectorSpecs;
|
|
break;
|
|
}
|
|
|
|
auto I = lower_bound(*Specs, BitWidth, LessPrimitiveBitWidth());
|
|
if (I != Specs->end() && I->BitWidth == BitWidth) {
|
|
// Update the abi, preferred alignments.
|
|
I->ABIAlign = ABIAlign;
|
|
I->PrefAlign = PrefAlign;
|
|
} else {
|
|
// Insert before I to keep the vector sorted.
|
|
Specs->insert(I, PrimitiveSpec{BitWidth, ABIAlign, PrefAlign});
|
|
}
|
|
}
|
|
|
|
const DataLayout::PointerSpec &
|
|
DataLayout::getPointerSpec(uint32_t AddrSpace) const {
|
|
if (AddrSpace != 0) {
|
|
auto I = lower_bound(PointerSpecs, AddrSpace, LessPointerAddrSpace());
|
|
if (I != PointerSpecs.end() && I->AddrSpace == AddrSpace)
|
|
return *I;
|
|
}
|
|
|
|
assert(PointerSpecs[0].AddrSpace == 0);
|
|
return PointerSpecs[0];
|
|
}
|
|
|
|
void DataLayout::setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth,
|
|
Align ABIAlign, Align PrefAlign,
|
|
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, IsNonIntegral});
|
|
} else {
|
|
I->BitWidth = BitWidth;
|
|
I->ABIAlign = ABIAlign;
|
|
I->PrefAlign = PrefAlign;
|
|
I->IndexBitWidth = IndexBitWidth;
|
|
I->IsNonIntegral = IsNonIntegral;
|
|
}
|
|
}
|
|
|
|
Align DataLayout::getIntegerAlignment(uint32_t BitWidth,
|
|
bool abi_or_pref) const {
|
|
auto I = lower_bound(IntSpecs, BitWidth, LessPrimitiveBitWidth());
|
|
// 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 == IntSpecs.end())
|
|
--I;
|
|
return abi_or_pref ? I->ABIAlign : I->PrefAlign;
|
|
}
|
|
|
|
DataLayout::~DataLayout() { delete static_cast<StructLayoutMap *>(LayoutMap); }
|
|
|
|
const StructLayout *DataLayout::getStructLayout(StructType *Ty) const {
|
|
if (!LayoutMap)
|
|
LayoutMap = new StructLayoutMap();
|
|
|
|
StructLayoutMap *STM = static_cast<StructLayoutMap*>(LayoutMap);
|
|
StructLayout *&SL = (*STM)[Ty];
|
|
if (SL) return SL;
|
|
|
|
// Otherwise, create the struct layout. Because it is variable length, we
|
|
// malloc it, then use placement new.
|
|
StructLayout *L = (StructLayout *)safe_malloc(
|
|
StructLayout::totalSizeToAlloc<TypeSize>(Ty->getNumElements()));
|
|
|
|
// Set SL before calling StructLayout's ctor. The ctor could cause other
|
|
// entries to be added to TheMap, invalidating our reference.
|
|
SL = L;
|
|
|
|
new (L) StructLayout(Ty, *this);
|
|
|
|
return L;
|
|
}
|
|
|
|
Align DataLayout::getPointerABIAlignment(unsigned AS) const {
|
|
return getPointerSpec(AS).ABIAlign;
|
|
}
|
|
|
|
Align DataLayout::getPointerPrefAlignment(unsigned AS) const {
|
|
return getPointerSpec(AS).PrefAlign;
|
|
}
|
|
|
|
unsigned DataLayout::getPointerSize(unsigned AS) const {
|
|
return divideCeil(getPointerSpec(AS).BitWidth, 8);
|
|
}
|
|
|
|
unsigned DataLayout::getPointerTypeSizeInBits(Type *Ty) const {
|
|
assert(Ty->isPtrOrPtrVectorTy() &&
|
|
"This should only be called with a pointer or pointer vector type");
|
|
Ty = Ty->getScalarType();
|
|
return getPointerSizeInBits(cast<PointerType>(Ty)->getAddressSpace());
|
|
}
|
|
|
|
unsigned DataLayout::getIndexSize(unsigned AS) const {
|
|
return divideCeil(getPointerSpec(AS).IndexBitWidth, 8);
|
|
}
|
|
|
|
unsigned DataLayout::getIndexTypeSizeInBits(Type *Ty) const {
|
|
assert(Ty->isPtrOrPtrVectorTy() &&
|
|
"This should only be called with a pointer or pointer vector type");
|
|
Ty = Ty->getScalarType();
|
|
return getIndexSizeInBits(cast<PointerType>(Ty)->getAddressSpace());
|
|
}
|
|
|
|
/*!
|
|
\param abi_or_pref Flag that determines which alignment is returned. true
|
|
returns the ABI alignment, false returns the preferred alignment.
|
|
\param Ty The underlying type for which alignment is determined.
|
|
|
|
Get the ABI (\a abi_or_pref == true) or preferred alignment (\a abi_or_pref
|
|
== false) for the requested type \a Ty.
|
|
*/
|
|
Align DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const {
|
|
assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
|
|
switch (Ty->getTypeID()) {
|
|
// Early escape for the non-numeric types.
|
|
case Type::LabelTyID:
|
|
return abi_or_pref ? getPointerABIAlignment(0) : getPointerPrefAlignment(0);
|
|
case Type::PointerTyID: {
|
|
unsigned AS = cast<PointerType>(Ty)->getAddressSpace();
|
|
return abi_or_pref ? getPointerABIAlignment(AS)
|
|
: getPointerPrefAlignment(AS);
|
|
}
|
|
case Type::ArrayTyID:
|
|
return getAlignment(cast<ArrayType>(Ty)->getElementType(), abi_or_pref);
|
|
|
|
case Type::StructTyID: {
|
|
// Packed structure types always have an ABI alignment of one.
|
|
if (cast<StructType>(Ty)->isPacked() && abi_or_pref)
|
|
return Align(1);
|
|
|
|
// Get the layout annotation... which is lazily created on demand.
|
|
const StructLayout *Layout = getStructLayout(cast<StructType>(Ty));
|
|
const Align Align = abi_or_pref ? StructABIAlignment : StructPrefAlignment;
|
|
return std::max(Align, Layout->getAlignment());
|
|
}
|
|
case Type::IntegerTyID:
|
|
return getIntegerAlignment(Ty->getIntegerBitWidth(), abi_or_pref);
|
|
case Type::HalfTyID:
|
|
case Type::BFloatTyID:
|
|
case Type::FloatTyID:
|
|
case Type::DoubleTyID:
|
|
// PPC_FP128TyID and FP128TyID have different data contents, but the
|
|
// same size and alignment, so they look the same here.
|
|
case Type::PPC_FP128TyID:
|
|
case Type::FP128TyID:
|
|
case Type::X86_FP80TyID: {
|
|
unsigned BitWidth = getTypeSizeInBits(Ty).getFixedValue();
|
|
auto I = lower_bound(FloatSpecs, BitWidth, LessPrimitiveBitWidth());
|
|
if (I != FloatSpecs.end() && I->BitWidth == BitWidth)
|
|
return abi_or_pref ? I->ABIAlign : I->PrefAlign;
|
|
|
|
// If we still couldn't find a reasonable default alignment, fall back
|
|
// to a simple heuristic that the alignment is the first power of two
|
|
// greater-or-equal to the store size of the type. This is a reasonable
|
|
// approximation of reality, and if the user wanted something less
|
|
// less conservative, they should have specified it explicitly in the data
|
|
// layout.
|
|
return Align(PowerOf2Ceil(BitWidth / 8));
|
|
}
|
|
case Type::FixedVectorTyID:
|
|
case Type::ScalableVectorTyID: {
|
|
unsigned BitWidth = getTypeSizeInBits(Ty).getKnownMinValue();
|
|
auto I = lower_bound(VectorSpecs, BitWidth, LessPrimitiveBitWidth());
|
|
if (I != VectorSpecs.end() && I->BitWidth == BitWidth)
|
|
return abi_or_pref ? I->ABIAlign : I->PrefAlign;
|
|
|
|
// By default, use natural alignment for vector types. This is consistent
|
|
// with what clang and llvm-gcc do.
|
|
//
|
|
// We're only calculating a natural alignment, so it doesn't have to be
|
|
// based on the full size for scalable vectors. Using the minimum element
|
|
// count should be enough here.
|
|
return Align(PowerOf2Ceil(getTypeStoreSize(Ty).getKnownMinValue()));
|
|
}
|
|
case Type::X86_AMXTyID:
|
|
return Align(64);
|
|
case Type::TargetExtTyID: {
|
|
Type *LayoutTy = cast<TargetExtType>(Ty)->getLayoutType();
|
|
return getAlignment(LayoutTy, abi_or_pref);
|
|
}
|
|
default:
|
|
llvm_unreachable("Bad type for getAlignment!!!");
|
|
}
|
|
}
|
|
|
|
Align DataLayout::getABITypeAlign(Type *Ty) const {
|
|
return getAlignment(Ty, true);
|
|
}
|
|
|
|
Align DataLayout::getPrefTypeAlign(Type *Ty) const {
|
|
return getAlignment(Ty, false);
|
|
}
|
|
|
|
IntegerType *DataLayout::getIntPtrType(LLVMContext &C,
|
|
unsigned AddressSpace) const {
|
|
return IntegerType::get(C, getPointerSizeInBits(AddressSpace));
|
|
}
|
|
|
|
Type *DataLayout::getIntPtrType(Type *Ty) const {
|
|
assert(Ty->isPtrOrPtrVectorTy() &&
|
|
"Expected a pointer or pointer vector type.");
|
|
unsigned NumBits = getPointerTypeSizeInBits(Ty);
|
|
IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits);
|
|
if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
|
|
return VectorType::get(IntTy, VecTy);
|
|
return IntTy;
|
|
}
|
|
|
|
Type *DataLayout::getSmallestLegalIntType(LLVMContext &C, unsigned Width) const {
|
|
for (unsigned LegalIntWidth : LegalIntWidths)
|
|
if (Width <= LegalIntWidth)
|
|
return Type::getIntNTy(C, LegalIntWidth);
|
|
return nullptr;
|
|
}
|
|
|
|
unsigned DataLayout::getLargestLegalIntTypeSizeInBits() const {
|
|
auto Max = llvm::max_element(LegalIntWidths);
|
|
return Max != LegalIntWidths.end() ? *Max : 0;
|
|
}
|
|
|
|
IntegerType *DataLayout::getIndexType(LLVMContext &C,
|
|
unsigned AddressSpace) const {
|
|
return IntegerType::get(C, getIndexSizeInBits(AddressSpace));
|
|
}
|
|
|
|
Type *DataLayout::getIndexType(Type *Ty) const {
|
|
assert(Ty->isPtrOrPtrVectorTy() &&
|
|
"Expected a pointer or pointer vector type.");
|
|
unsigned NumBits = getIndexTypeSizeInBits(Ty);
|
|
IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits);
|
|
if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
|
|
return VectorType::get(IntTy, VecTy);
|
|
return IntTy;
|
|
}
|
|
|
|
int64_t DataLayout::getIndexedOffsetInType(Type *ElemTy,
|
|
ArrayRef<Value *> Indices) const {
|
|
int64_t Result = 0;
|
|
|
|
generic_gep_type_iterator<Value* const*>
|
|
GTI = gep_type_begin(ElemTy, Indices),
|
|
GTE = gep_type_end(ElemTy, Indices);
|
|
for (; GTI != GTE; ++GTI) {
|
|
Value *Idx = GTI.getOperand();
|
|
if (StructType *STy = GTI.getStructTypeOrNull()) {
|
|
assert(Idx->getType()->isIntegerTy(32) && "Illegal struct idx");
|
|
unsigned FieldNo = cast<ConstantInt>(Idx)->getZExtValue();
|
|
|
|
// Get structure layout information...
|
|
const StructLayout *Layout = getStructLayout(STy);
|
|
|
|
// Add in the offset, as calculated by the structure layout info...
|
|
Result += Layout->getElementOffset(FieldNo);
|
|
} else {
|
|
if (int64_t ArrayIdx = cast<ConstantInt>(Idx)->getSExtValue())
|
|
Result += ArrayIdx * GTI.getSequentialElementStride(*this);
|
|
}
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
static APInt getElementIndex(TypeSize ElemSize, APInt &Offset) {
|
|
// Skip over scalable or zero size elements. Also skip element sizes larger
|
|
// than the positive index space, because the arithmetic below may not be
|
|
// correct in that case.
|
|
unsigned BitWidth = Offset.getBitWidth();
|
|
if (ElemSize.isScalable() || ElemSize == 0 ||
|
|
!isUIntN(BitWidth - 1, ElemSize)) {
|
|
return APInt::getZero(BitWidth);
|
|
}
|
|
|
|
APInt Index = Offset.sdiv(ElemSize);
|
|
Offset -= Index * ElemSize;
|
|
if (Offset.isNegative()) {
|
|
// Prefer a positive remaining offset to allow struct indexing.
|
|
--Index;
|
|
Offset += ElemSize;
|
|
assert(Offset.isNonNegative() && "Remaining offset shouldn't be negative");
|
|
}
|
|
return Index;
|
|
}
|
|
|
|
std::optional<APInt> DataLayout::getGEPIndexForOffset(Type *&ElemTy,
|
|
APInt &Offset) const {
|
|
if (auto *ArrTy = dyn_cast<ArrayType>(ElemTy)) {
|
|
ElemTy = ArrTy->getElementType();
|
|
return getElementIndex(getTypeAllocSize(ElemTy), Offset);
|
|
}
|
|
|
|
if (isa<VectorType>(ElemTy)) {
|
|
// Vector GEPs are partially broken (e.g. for overaligned element types),
|
|
// and may be forbidden in the future, so avoid generating GEPs into
|
|
// vectors. See https://discourse.llvm.org/t/67497
|
|
return std::nullopt;
|
|
}
|
|
|
|
if (auto *STy = dyn_cast<StructType>(ElemTy)) {
|
|
const StructLayout *SL = getStructLayout(STy);
|
|
uint64_t IntOffset = Offset.getZExtValue();
|
|
if (IntOffset >= SL->getSizeInBytes())
|
|
return std::nullopt;
|
|
|
|
unsigned Index = SL->getElementContainingOffset(IntOffset);
|
|
Offset -= SL->getElementOffset(Index);
|
|
ElemTy = STy->getElementType(Index);
|
|
return APInt(32, Index);
|
|
}
|
|
|
|
// Non-aggregate type.
|
|
return std::nullopt;
|
|
}
|
|
|
|
SmallVector<APInt> DataLayout::getGEPIndicesForOffset(Type *&ElemTy,
|
|
APInt &Offset) const {
|
|
assert(ElemTy->isSized() && "Element type must be sized");
|
|
SmallVector<APInt> Indices;
|
|
Indices.push_back(getElementIndex(getTypeAllocSize(ElemTy), Offset));
|
|
while (Offset != 0) {
|
|
std::optional<APInt> Index = getGEPIndexForOffset(ElemTy, Offset);
|
|
if (!Index)
|
|
break;
|
|
Indices.push_back(*Index);
|
|
}
|
|
|
|
return Indices;
|
|
}
|
|
|
|
/// getPreferredAlign - Return the preferred alignment of the specified global.
|
|
/// This includes an explicitly requested alignment (if the global has one).
|
|
Align DataLayout::getPreferredAlign(const GlobalVariable *GV) const {
|
|
MaybeAlign GVAlignment = GV->getAlign();
|
|
// If a section is specified, always precisely honor explicit alignment,
|
|
// so we don't insert padding into a section we don't control.
|
|
if (GVAlignment && GV->hasSection())
|
|
return *GVAlignment;
|
|
|
|
// If no explicit alignment is specified, compute the alignment based on
|
|
// the IR type. If an alignment is specified, increase it to match the ABI
|
|
// alignment of the IR type.
|
|
//
|
|
// FIXME: Not sure it makes sense to use the alignment of the type if
|
|
// there's already an explicit alignment specification.
|
|
Type *ElemType = GV->getValueType();
|
|
Align Alignment = getPrefTypeAlign(ElemType);
|
|
if (GVAlignment) {
|
|
if (*GVAlignment >= Alignment)
|
|
Alignment = *GVAlignment;
|
|
else
|
|
Alignment = std::max(*GVAlignment, getABITypeAlign(ElemType));
|
|
}
|
|
|
|
// If no explicit alignment is specified, and the global is large, increase
|
|
// the alignment to 16.
|
|
// FIXME: Why 16, specifically?
|
|
if (GV->hasInitializer() && !GVAlignment) {
|
|
if (Alignment < Align(16)) {
|
|
// If the global is not external, see if it is large. If so, give it a
|
|
// larger alignment.
|
|
if (getTypeSizeInBits(ElemType) > 128)
|
|
Alignment = Align(16); // 16-byte alignment.
|
|
}
|
|
}
|
|
return Alignment;
|
|
}
|