#include "llvm/IR/DataLayout.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <tuple>
#include <utility>
using namespace llvm;
StructLayout::StructLayout(StructType *ST, const DataLayout &DL) {
assert(!ST->isOpaque() && "Cannot get layout of opaque structs");
StructAlignment = 0;
StructSize = 0;
IsPadded = false;
NumElements = ST->getNumElements();
for (unsigned i = 0, e = NumElements; i != e; ++i) {
Type *Ty = ST->getElementType(i);
unsigned TyAlign = ST->isPacked() ? 1 : DL.getABITypeAlignment(Ty);
if ((StructSize & (TyAlign-1)) != 0) {
IsPadded = true;
StructSize = alignTo(StructSize, TyAlign);
}
StructAlignment = std::max(TyAlign, StructAlignment);
MemberOffsets[i] = StructSize;
StructSize += DL.getTypeAllocSize(Ty);
}
if (StructAlignment == 0) StructAlignment = 1;
if ((StructSize & (StructAlignment-1)) != 0) {
IsPadded = true;
StructSize = alignTo(StructSize, StructAlignment);
}
}
unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const {
const uint64_t *SI =
std::upper_bound(&MemberOffsets[0], &MemberOffsets[NumElements], Offset);
assert(SI != &MemberOffsets[0] && "Offset not in structure type!");
--SI;
assert(*SI <= Offset && "upper_bound didn't work");
assert((SI == &MemberOffsets[0] || *(SI-1) <= Offset) &&
(SI+1 == &MemberOffsets[NumElements] || *(SI+1) > Offset) &&
"Upper bound didn't work!");
return SI-&MemberOffsets[0];
}
LayoutAlignElem
LayoutAlignElem::get(AlignTypeEnum align_type, unsigned abi_align,
unsigned 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
PointerAlignElem::get(uint32_t AddressSpace, unsigned ABIAlign,
unsigned 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);
}
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";
return "-m:e";
}
static const LayoutAlignElem DefaultAlignments[] = {
{ INTEGER_ALIGN, 1, 1, 1 },
{ INTEGER_ALIGN, 8, 1, 1 },
{ INTEGER_ALIGN, 16, 2, 2 },
{ INTEGER_ALIGN, 32, 4, 4 },
{ INTEGER_ALIGN, 64, 4, 8 },
{ FLOAT_ALIGN, 16, 2, 2 },
{ FLOAT_ALIGN, 32, 4, 4 },
{ FLOAT_ALIGN, 64, 8, 8 },
{ FLOAT_ALIGN, 128, 16, 16 },
{ VECTOR_ALIGN, 64, 8, 8 },
{ VECTOR_ALIGN, 128, 16, 16 },
{ AGGREGATE_ALIGN, 0, 0, 8 }
};
void DataLayout::reset(StringRef Desc) {
clear();
LayoutMap = nullptr;
BigEndian = false;
AllocaAddrSpace = 0;
StackNaturalAlign = 0;
ProgramAddrSpace = 0;
ManglingMode = MM_None;
NonIntegralAddressSpaces.clear();
for (const LayoutAlignElem &E : DefaultAlignments) {
setAlignment((AlignTypeEnum)E.AlignType, E.ABIAlign, E.PrefAlign,
E.TypeBitWidth);
}
setPointerAlignment(0, 8, 8, 8, 8);
parseSpecifier(Desc);
}
static std::pair<StringRef, StringRef> split(StringRef Str, char Separator) {
assert(!Str.empty() && "parse error, string can't be empty here");
std::pair<StringRef, StringRef> Split = Str.split(Separator);
if (Split.second.empty() && Split.first != Str)
report_fatal_error("Trailing separator in datalayout string");
if (!Split.second.empty() && Split.first.empty())
report_fatal_error("Expected token before separator in datalayout string");
return Split;
}
static unsigned getInt(StringRef R) {
unsigned Result;
bool error = R.getAsInteger(10, Result); (void)error;
if (error)
report_fatal_error("not a number, or does not fit in an unsigned int");
return Result;
}
static unsigned inBytes(unsigned Bits) {
if (Bits % 8)
report_fatal_error("number of bits must be a byte width multiple");
return Bits / 8;
}
static unsigned getAddrSpace(StringRef R) {
unsigned AddrSpace = getInt(R);
if (!isUInt<24>(AddrSpace))
report_fatal_error("Invalid address space, must be a 24-bit integer");
return AddrSpace;
}
void DataLayout::parseSpecifier(StringRef Desc) {
StringRepresentation = Desc;
while (!Desc.empty()) {
std::pair<StringRef, StringRef> Split = split(Desc, '-');
Desc = Split.second;
Split = split(Split.first, ':');
StringRef &Tok = Split.first;
StringRef &Rest = Split.second;
if (Tok == "ni") {
do {
Split = split(Rest, ':');
Rest = Split.second;
unsigned AS = getInt(Split.first);
if (AS == 0)
report_fatal_error("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':
break;
case 'E':
BigEndian = true;
break;
case 'e':
BigEndian = false;
break;
case 'p': {
unsigned AddrSpace = Tok.empty() ? 0 : getInt(Tok);
if (!isUInt<24>(AddrSpace))
report_fatal_error("Invalid address space, must be a 24bit integer");
if (Rest.empty())
report_fatal_error(
"Missing size specification for pointer in datalayout string");
Split = split(Rest, ':');
unsigned PointerMemSize = inBytes(getInt(Tok));
if (!PointerMemSize)
report_fatal_error("Invalid pointer size of 0 bytes");
if (Rest.empty())
report_fatal_error(
"Missing alignment specification for pointer in datalayout string");
Split = split(Rest, ':');
unsigned PointerABIAlign = inBytes(getInt(Tok));
if (!isPowerOf2_64(PointerABIAlign))
report_fatal_error(
"Pointer ABI alignment must be a power of 2");
unsigned IndexSize = PointerMemSize;
unsigned PointerPrefAlign = PointerABIAlign;
if (!Rest.empty()) {
Split = split(Rest, ':');
PointerPrefAlign = inBytes(getInt(Tok));
if (!isPowerOf2_64(PointerPrefAlign))
report_fatal_error(
"Pointer preferred alignment must be a power of 2");
if (!Rest.empty()) {
Split = split(Rest, ':');
IndexSize = inBytes(getInt(Tok));
if (!IndexSize)
report_fatal_error("Invalid index size of 0 bytes");
}
}
setPointerAlignment(AddrSpace, PointerABIAlign, PointerPrefAlign,
PointerMemSize, IndexSize);
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;
}
unsigned Size = Tok.empty() ? 0 : getInt(Tok);
if (AlignType == AGGREGATE_ALIGN && Size != 0)
report_fatal_error(
"Sized aggregate specification in datalayout string");
if (Rest.empty())
report_fatal_error(
"Missing alignment specification in datalayout string");
Split = split(Rest, ':');
unsigned ABIAlign = inBytes(getInt(Tok));
if (AlignType != AGGREGATE_ALIGN && !ABIAlign)
report_fatal_error(
"ABI alignment specification must be >0 for non-aggregate types");
unsigned PrefAlign = ABIAlign;
if (!Rest.empty()) {
Split = split(Rest, ':');
PrefAlign = inBytes(getInt(Tok));
}
setAlignment(AlignType, ABIAlign, PrefAlign, Size);
break;
}
case 'n':
while (true) {
unsigned Width = getInt(Tok);
if (Width == 0)
report_fatal_error(
"Zero width native integer type in datalayout string");
LegalIntWidths.push_back(Width);
if (Rest.empty())
break;
Split = split(Rest, ':');
}
break;
case 'S': {
StackNaturalAlign = inBytes(getInt(Tok));
break;
}
case 'P': {
ProgramAddrSpace = getAddrSpace(Tok);
break;
}
case 'A': {
AllocaAddrSpace = getAddrSpace(Tok);
break;
}
case 'm':
if (!Tok.empty())
report_fatal_error("Unexpected trailing characters after mangling specifier in datalayout string");
if (Rest.empty())
report_fatal_error("Expected mangling specifier in datalayout string");
if (Rest.size() > 1)
report_fatal_error("Unknown mangling specifier in datalayout string");
switch(Rest[0]) {
default:
report_fatal_error("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;
}
break;
default:
report_fatal_error("Unknown specifier in datalayout string");
break;
}
}
}
DataLayout::DataLayout(const Module *M) {
init(M);
}
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 &&
ManglingMode == Other.ManglingMode &&
LegalIntWidths == Other.LegalIntWidths &&
Alignments == Other.Alignments && Pointers == Other.Pointers;
return Ret;
}
DataLayout::AlignmentsTy::iterator
DataLayout::findAlignmentLowerBound(AlignTypeEnum AlignType,
uint32_t BitWidth) {
auto Pair = std::make_pair((unsigned)AlignType, BitWidth);
return std::lower_bound(Alignments.begin(), Alignments.end(), Pair,
[](const LayoutAlignElem &LHS,
const std::pair<unsigned, uint32_t> &RHS) {
return std::tie(LHS.AlignType, LHS.TypeBitWidth) <
std::tie(RHS.first, RHS.second);
});
}
void
DataLayout::setAlignment(AlignTypeEnum align_type, unsigned abi_align,
unsigned pref_align, uint32_t bit_width) {
if (!isUInt<24>(bit_width))
report_fatal_error("Invalid bit width, must be a 24bit integer");
if (!isUInt<16>(abi_align))
report_fatal_error("Invalid ABI alignment, must be a 16bit integer");
if (!isUInt<16>(pref_align))
report_fatal_error("Invalid preferred alignment, must be a 16bit integer");
if (abi_align != 0 && !isPowerOf2_64(abi_align))
report_fatal_error("Invalid ABI alignment, must be a power of 2");
if (pref_align != 0 && !isPowerOf2_64(pref_align))
report_fatal_error("Invalid preferred alignment, must be a power of 2");
if (pref_align < abi_align)
report_fatal_error(
"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) {
I->ABIAlign = abi_align;
I->PrefAlign = pref_align;
} else {
Alignments.insert(I, LayoutAlignElem::get(align_type, abi_align,
pref_align, bit_width));
}
}
DataLayout::PointersTy::iterator
DataLayout::findPointerLowerBound(uint32_t AddressSpace) {
return std::lower_bound(Pointers.begin(), Pointers.end(), AddressSpace,
[](const PointerAlignElem &A, uint32_t AddressSpace) {
return A.AddressSpace < AddressSpace;
});
}
void DataLayout::setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign,
unsigned PrefAlign, uint32_t TypeByteWidth,
uint32_t IndexWidth) {
if (PrefAlign < ABIAlign)
report_fatal_error(
"Preferred alignment cannot be less than the ABI alignment");
PointersTy::iterator I = findPointerLowerBound(AddrSpace);
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;
}
}
unsigned DataLayout::getAlignmentInfo(AlignTypeEnum AlignType,
uint32_t BitWidth, bool ABIInfo,
Type *Ty) const {
AlignmentsTy::const_iterator I = findAlignmentLowerBound(AlignType, BitWidth);
if (I != Alignments.end() && I->AlignType == (unsigned)AlignType &&
(I->TypeBitWidth == BitWidth || AlignType == INTEGER_ALIGN))
return ABIInfo ? I->ABIAlign : I->PrefAlign;
if (AlignType == INTEGER_ALIGN) {
if (I != Alignments.begin()) {
--I;
if (I->AlignType == INTEGER_ALIGN)
return ABIInfo ? I->ABIAlign : I->PrefAlign;
}
} else if (AlignType == VECTOR_ALIGN) {
unsigned Align = getTypeAllocSize(cast<VectorType>(Ty)->getElementType());
Align *= cast<VectorType>(Ty)->getNumElements();
Align = PowerOf2Ceil(Align);
return Align;
}
unsigned Align = getTypeStoreSize(Ty);
Align = PowerOf2Ceil(Align);
return Align;
}
namespace {
class StructLayoutMap {
using LayoutInfoTy = DenseMap<StructType*, StructLayout*>;
LayoutInfoTy LayoutInfo;
public:
~StructLayoutMap() {
for (const auto &I : LayoutInfo) {
StructLayout *Value = I.second;
Value->~StructLayout();
free(Value);
}
}
StructLayout *&operator[](StructType *STy) {
return LayoutInfo[STy];
}
};
}
void DataLayout::clear() {
LegalIntWidths.clear();
Alignments.clear();
Pointers.clear();
delete static_cast<StructLayoutMap *>(LayoutMap);
LayoutMap = nullptr;
}
DataLayout::~DataLayout() {
clear();
}
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;
int NumElts = Ty->getNumElements();
StructLayout *L = (StructLayout *)
safe_malloc(sizeof(StructLayout)+(NumElts-1) * sizeof(uint64_t));
SL = L;
new (L) StructLayout(Ty, *this);
return L;
}
unsigned DataLayout::getPointerABIAlignment(unsigned AS) const {
PointersTy::const_iterator I = findPointerLowerBound(AS);
if (I == Pointers.end() || I->AddressSpace != AS) {
I = findPointerLowerBound(0);
assert(I->AddressSpace == 0);
}
return I->ABIAlign;
}
unsigned DataLayout::getPointerPrefAlignment(unsigned AS) const {
PointersTy::const_iterator I = findPointerLowerBound(AS);
if (I == Pointers.end() || I->AddressSpace != AS) {
I = findPointerLowerBound(0);
assert(I->AddressSpace == 0);
}
return I->PrefAlign;
}
unsigned DataLayout::getPointerSize(unsigned AS) const {
PointersTy::const_iterator I = findPointerLowerBound(AS);
if (I == Pointers.end() || I->AddressSpace != AS) {
I = findPointerLowerBound(0);
assert(I->AddressSpace == 0);
}
return I->TypeByteWidth;
}
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 {
PointersTy::const_iterator I = findPointerLowerBound(AS);
if (I == Pointers.end() || I->AddressSpace != AS) {
I = findPointerLowerBound(0);
assert(I->AddressSpace == 0);
}
return I->IndexWidth;
}
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.
*/
unsigned DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const {
AlignTypeEnum AlignType;
assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
switch (Ty->getTypeID()) {
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: {
if (cast<StructType>(Ty)->isPacked() && abi_or_pref)
return 1;
const StructLayout *Layout = getStructLayout(cast<StructType>(Ty));
unsigned Align = getAlignmentInfo(AGGREGATE_ALIGN, 0, abi_or_pref, Ty);
return std::max(Align, Layout->getAlignment());
}
case Type::IntegerTyID:
AlignType = INTEGER_ALIGN;
break;
case Type::HalfTyID:
case Type::FloatTyID:
case Type::DoubleTyID:
case Type::PPC_FP128TyID:
case Type::FP128TyID:
case Type::X86_FP80TyID:
AlignType = FLOAT_ALIGN;
break;
case Type::X86_MMXTyID:
case Type::VectorTyID:
AlignType = VECTOR_ALIGN;
break;
default:
llvm_unreachable("Bad type for getAlignment!!!");
}
return getAlignmentInfo(AlignType, getTypeSizeInBits(Ty), abi_or_pref, Ty);
}
unsigned DataLayout::getABITypeAlignment(Type *Ty) const {
return getAlignment(Ty, true);
}
unsigned DataLayout::getABIIntegerTypeAlignment(unsigned BitWidth) const {
return getAlignmentInfo(INTEGER_ALIGN, BitWidth, true, nullptr);
}
unsigned DataLayout::getPrefTypeAlignment(Type *Ty) const {
return getAlignment(Ty, false);
}
unsigned DataLayout::getPreferredTypeAlignmentShift(Type *Ty) const {
unsigned Align = getPrefTypeAlignment(Ty);
assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
return Log2_32(Align);
}
IntegerType *DataLayout::getIntPtrType(LLVMContext &C,
unsigned AddressSpace) const {
return IntegerType::get(C, getIndexSizeInBits(AddressSpace));
}
Type *DataLayout::getIntPtrType(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->getNumElements());
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 = std::max_element(LegalIntWidths.begin(), LegalIntWidths.end());
return Max != LegalIntWidths.end() ? *Max : 0;
}
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->getNumElements());
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();
const StructLayout *Layout = getStructLayout(STy);
Result += Layout->getElementOffset(FieldNo);
} else {
if (int64_t arrayIdx = cast<ConstantInt>(Idx)->getSExtValue())
Result += arrayIdx * getTypeAllocSize(GTI.getIndexedType());
}
}
return Result;
}
unsigned DataLayout::getPreferredAlignment(const GlobalVariable *GV) const {
Type *ElemType = GV->getValueType();
unsigned Alignment = getPrefTypeAlignment(ElemType);
unsigned GVAlignment = GV->getAlignment();
if (GVAlignment >= Alignment) {
Alignment = GVAlignment;
} else if (GVAlignment != 0) {
Alignment = std::max(GVAlignment, getABITypeAlignment(ElemType));
}
if (GV->hasInitializer() && GVAlignment == 0) {
if (Alignment < 16) {
if (getTypeSizeInBits(ElemType) > 128)
Alignment = 16;
}
}
return Alignment;
}
unsigned DataLayout::getPreferredAlignmentLog(const GlobalVariable *GV) const {
return Log2_32(getPreferredAlignment(GV));
}