#include "llvm/IR/DataLayout.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
}
const LayoutAlignElem
-DataLayout::InvalidAlignmentElem = LayoutAlignElem::get(INVALID_ALIGN, 0, 0, 0);
+DataLayout::InvalidAlignmentElem = { INVALID_ALIGN, 0, 0, 0 };
//===----------------------------------------------------------------------===//
// PointerAlignElem, PointerAlign support
//===----------------------------------------------------------------------===//
PointerAlignElem
-PointerAlignElem::get(uint32_t addr_space, unsigned abi_align,
- unsigned pref_align, uint32_t bit_width) {
- assert(abi_align <= pref_align && "Preferred alignment worse than ABI!");
+PointerAlignElem::get(uint32_t AddressSpace, unsigned ABIAlign,
+ unsigned PrefAlign, uint32_t TypeByteWidth) {
+ assert(ABIAlign <= PrefAlign && "Preferred alignment worse than ABI!");
PointerAlignElem retval;
- retval.AddressSpace = addr_space;
- retval.ABIAlign = abi_align;
- retval.PrefAlign = pref_align;
- retval.TypeBitWidth = bit_width;
+ retval.AddressSpace = AddressSpace;
+ retval.ABIAlign = ABIAlign;
+ retval.PrefAlign = PrefAlign;
+ retval.TypeByteWidth = TypeByteWidth;
return retval;
}
return (ABIAlign == rhs.ABIAlign
&& AddressSpace == rhs.AddressSpace
&& PrefAlign == rhs.PrefAlign
- && TypeBitWidth == rhs.TypeBitWidth);
+ && TypeByteWidth == rhs.TypeByteWidth);
}
const PointerAlignElem
-DataLayout::InvalidPointerElem = PointerAlignElem::get(~0U, 0U, 0U, 0U);
+DataLayout::InvalidPointerElem = { 0U, 0U, 0U, ~0U };
//===----------------------------------------------------------------------===//
// DataLayout Class Implementation
//===----------------------------------------------------------------------===//
+const char *DataLayout::getManglingComponent(const Triple &T) {
+ if (T.isOSBinFormatMachO())
+ return "-m:o";
+ if (T.isOSBinFormatELF() || T.isArch64Bit())
+ return "-m:e";
+ assert(T.isOSBinFormatCOFF());
+ return "-m:c";
+}
+
+static const LayoutAlignElem DefaultAlignments[] = {
+ { INTEGER_ALIGN, 1, 1, 1 }, // i1
+ { INTEGER_ALIGN, 8, 1, 1 }, // i8
+ { INTEGER_ALIGN, 16, 2, 2 }, // i16
+ { INTEGER_ALIGN, 32, 4, 4 }, // i32
+ { INTEGER_ALIGN, 64, 4, 8 }, // i64
+ { FLOAT_ALIGN, 16, 2, 2 }, // half
+ { FLOAT_ALIGN, 32, 4, 4 }, // float
+ { FLOAT_ALIGN, 64, 8, 8 }, // double
+ { FLOAT_ALIGN, 128, 16, 16 }, // ppcf128, quad, ...
+ { VECTOR_ALIGN, 64, 8, 8 }, // v2i32, v1i64, ...
+ { VECTOR_ALIGN, 128, 16, 16 }, // v16i8, v8i16, v4i32, ...
+ { AGGREGATE_ALIGN, 0, 0, 8 } // struct
+};
+
void DataLayout::init(StringRef Desc) {
initializeDataLayoutPass(*PassRegistry::getPassRegistry());
LayoutMap = 0;
LittleEndian = false;
StackNaturalAlign = 0;
+ ManglingMode = MM_None;
// Default alignments
- setAlignment(INTEGER_ALIGN, 1, 1, 1); // i1
- setAlignment(INTEGER_ALIGN, 1, 1, 8); // i8
- setAlignment(INTEGER_ALIGN, 2, 2, 16); // i16
- setAlignment(INTEGER_ALIGN, 4, 4, 32); // i32
- setAlignment(INTEGER_ALIGN, 4, 8, 64); // i64
- setAlignment(FLOAT_ALIGN, 2, 2, 16); // half
- setAlignment(FLOAT_ALIGN, 4, 4, 32); // float
- setAlignment(FLOAT_ALIGN, 8, 8, 64); // double
- setAlignment(FLOAT_ALIGN, 16, 16, 128); // ppcf128, quad, ...
- setAlignment(VECTOR_ALIGN, 8, 8, 64); // v2i32, v1i64, ...
- setAlignment(VECTOR_ALIGN, 16, 16, 128); // v16i8, v8i16, v4i32, ...
- setAlignment(AGGREGATE_ALIGN, 0, 8, 0); // struct
+ for (int I = 0, N = array_lengthof(DefaultAlignments); I < N; ++I) {
+ const LayoutAlignElem &E = DefaultAlignments[I];
+ setAlignment((AlignTypeEnum)E.AlignType, E.ABIAlign, E.PrefAlign,
+ E.TypeBitWidth);
+ }
setPointerAlignment(0, 8, 8, 8);
parseSpecifier(Desc);
}
void DataLayout::parseSpecifier(StringRef Desc) {
-
while (!Desc.empty()) {
-
// Split at '-'.
std::pair<StringRef, StringRef> Split = split(Desc, '-');
Desc = Split.second;
Tok = Tok.substr(1);
switch (Specifier) {
+ case 's':
+ // Ignored for backward compatibility.
+ // FIXME: remove this on LLVM 4.0.
+ break;
case 'E':
LittleEndian = false;
break;
case 'i':
case 'v':
case 'f':
- case 'a':
- case 's': {
+ case 'a': {
AlignTypeEnum AlignType;
switch (Specifier) {
default:
case 'v': AlignType = VECTOR_ALIGN; break;
case 'f': AlignType = FLOAT_ALIGN; break;
case 'a': AlignType = AGGREGATE_ALIGN; break;
- case 's': AlignType = STACK_ALIGN; break;
}
// Bit size.
unsigned Size = Tok.empty() ? 0 : getInt(Tok);
+ assert((AlignType != AGGREGATE_ALIGN || Size == 0) &&
+ "These specifications don't have a size");
+
// ABI alignment.
Split = split(Rest, ':');
unsigned ABIAlign = inBytes(getInt(Tok));
StackNaturalAlign = inBytes(getInt(Tok));
break;
}
+ case 'm':
+ assert(Tok.empty());
+ assert(Rest.size() == 1);
+ switch(Rest[0]) {
+ default:
+ llvm_unreachable("Unknown mangling in datalayout string");
+ case 'e':
+ ManglingMode = MM_ELF;
+ break;
+ case 'o':
+ ManglingMode = MM_MachO;
+ break;
+ case 'm':
+ ManglingMode = MM_Mips;
+ break;
+ case 'c':
+ ManglingMode = MM_COFF;
+ break;
+ }
+ break;
default:
llvm_unreachable("Unknown specifier in datalayout string");
break;
pref_align, bit_width));
}
-void
-DataLayout::setPointerAlignment(uint32_t addr_space, unsigned abi_align,
- unsigned pref_align, uint32_t bit_width) {
- assert(abi_align <= pref_align && "Preferred alignment worse than ABI!");
- DenseMap<unsigned,PointerAlignElem>::iterator val = Pointers.find(addr_space);
+void DataLayout::setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign,
+ unsigned PrefAlign,
+ uint32_t TypeByteWidth) {
+ assert(ABIAlign <= PrefAlign && "Preferred alignment worse than ABI!");
+ DenseMap<unsigned,PointerAlignElem>::iterator val = Pointers.find(AddrSpace);
if (val == Pointers.end()) {
- Pointers[addr_space] = PointerAlignElem::get(addr_space,
- abi_align, pref_align, bit_width);
+ Pointers[AddrSpace] =
+ PointerAlignElem::get(AddrSpace, ABIAlign, PrefAlign, TypeByteWidth);
} else {
- val->second.ABIAlign = abi_align;
- val->second.PrefAlign = pref_align;
- val->second.TypeBitWidth = bit_width;
+ val->second.ABIAlign = ABIAlign;
+ val->second.PrefAlign = PrefAlign;
+ val->second.TypeByteWidth = TypeByteWidth;
}
}
raw_string_ostream OS(Result);
OS << (LittleEndian ? "e" : "E");
+
+ switch (ManglingMode) {
+ case MM_None:
+ break;
+ case MM_ELF:
+ OS << "-m:e";
+ break;
+ case MM_MachO:
+ OS << "-m:o";
+ break;
+ case MM_COFF:
+ OS << "-m:c";
+ break;
+ case MM_Mips:
+ OS << "-m:m";
+ break;
+ }
+
SmallVector<unsigned, 8> addrSpaces;
// Lets get all of the known address spaces and sort them
// into increasing order so that we can emit the string
addrSpaces.push_back(pib->first);
}
std::sort(addrSpaces.begin(), addrSpaces.end());
- for (SmallVector<unsigned, 8>::iterator asb = addrSpaces.begin(),
+ for (SmallVectorImpl<unsigned>::iterator asb = addrSpaces.begin(),
ase = addrSpaces.end(); asb != ase; ++asb) {
const PointerAlignElem &PI = Pointers.find(*asb)->second;
+
+ // Skip default.
+ if (PI.AddressSpace == 0 && PI.ABIAlign == 8 && PI.PrefAlign == 8 &&
+ PI.TypeByteWidth == 8)
+ continue;
+
OS << "-p";
if (PI.AddressSpace) {
OS << PI.AddressSpace;
}
- OS << ":" << PI.TypeBitWidth*8 << ':' << PI.ABIAlign*8
- << ':' << PI.PrefAlign*8;
+ OS << ":" << PI.TypeByteWidth*8 << ':' << PI.ABIAlign*8;
+ if (PI.PrefAlign != PI.ABIAlign)
+ OS << ':' << PI.PrefAlign*8;
}
- OS << "-S" << StackNaturalAlign*8;
+ const LayoutAlignElem *DefaultStart = DefaultAlignments;
+ const LayoutAlignElem *DefaultEnd =
+ DefaultStart + array_lengthof(DefaultAlignments);
for (unsigned i = 0, e = Alignments.size(); i != e; ++i) {
const LayoutAlignElem &AI = Alignments[i];
- OS << '-' << (char)AI.AlignType << AI.TypeBitWidth << ':'
- << AI.ABIAlign*8 << ':' << AI.PrefAlign*8;
+ if (std::find(DefaultStart, DefaultEnd, AI) != DefaultEnd)
+ continue;
+ OS << '-' << (char)AI.AlignType;
+ if (AI.TypeBitWidth)
+ OS << AI.TypeBitWidth;
+ OS << ':' << AI.ABIAlign*8;
+ if (AI.ABIAlign != AI.PrefAlign)
+ OS << ':' << AI.PrefAlign*8;
}
if (!LegalIntWidths.empty()) {
for (unsigned i = 1, e = LegalIntWidths.size(); i != e; ++i)
OS << ':' << (unsigned)LegalIntWidths[i];
}
+
+ if (StackNaturalAlign)
+ OS << "-S" << StackNaturalAlign*8;
+
return OS.str();
}
+unsigned DataLayout::getPointerTypeSizeInBits(Type *Ty) const {
+ assert(Ty->isPtrOrPtrVectorTy() &&
+ "This should only be called with a pointer or pointer vector type");
+
+ if (Ty->isPointerTy())
+ return getTypeSizeInBits(Ty);
+
+ return getTypeSizeInBits(Ty->getScalarType());
+}
/*!
\param abi_or_pref Flag that determines which alignment is returned. true
return getAlignmentInfo(INTEGER_ALIGN, BitWidth, true, 0);
}
-
-unsigned DataLayout::getCallFrameTypeAlignment(Type *Ty) const {
- for (unsigned i = 0, e = Alignments.size(); i != e; ++i)
- if (Alignments[i].AlignType == STACK_ALIGN)
- return Alignments[i].ABIAlign;
-
- return getABITypeAlignment(Ty);
-}
-
unsigned DataLayout::getPrefTypeAlignment(Type *Ty) const {
return getAlignment(Ty, false);
}
return Log2_32(Align);
}
-/// getIntPtrType - Return an integer type with size at least as big as that
-/// of a pointer in the given address space.
IntegerType *DataLayout::getIntPtrType(LLVMContext &C,
unsigned AddressSpace) const {
return IntegerType::get(C, getPointerSizeInBits(AddressSpace));
}
-/// getIntPtrType - Return an integer (vector of integer) type with size at
-/// least as big as that of a pointer of the given pointer (vector of pointer)
-/// type.
Type *DataLayout::getIntPtrType(Type *Ty) const {
assert(Ty->isPtrOrPtrVectorTy() &&
"Expected a pointer or pointer vector type.");
return 0;
}
+unsigned DataLayout::getLargestLegalIntTypeSize() const {
+ unsigned MaxWidth = 0;
+ for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i)
+ MaxWidth = std::max<unsigned>(MaxWidth, LegalIntWidths[i]);
+ return MaxWidth;
+}
+
uint64_t DataLayout::getIndexedOffset(Type *ptrTy,
ArrayRef<Value *> Indices) const {
Type *Ty = ptrTy;