10f5676f4SDimitry Andric //===- DataLayout.cpp - Data size & alignment routines ---------------------==//
2139f7f9bSDimitry Andric //
3139f7f9bSDimitry Andric // The LLVM Compiler Infrastructure
4139f7f9bSDimitry Andric //
5139f7f9bSDimitry Andric // This file is distributed under the University of Illinois Open Source
6139f7f9bSDimitry Andric // License. See LICENSE.TXT for details.
7139f7f9bSDimitry Andric //
8139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
9139f7f9bSDimitry Andric //
10139f7f9bSDimitry Andric // This file defines layout properties related to datatype size/offset/alignment
11139f7f9bSDimitry Andric // information.
12139f7f9bSDimitry Andric //
13139f7f9bSDimitry Andric // This structure should be created once, filled in if the defaults are not
14139f7f9bSDimitry Andric // correct and then passed around by const&. None of the members functions
15139f7f9bSDimitry Andric // require modification to the object.
16139f7f9bSDimitry Andric //
17139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
18139f7f9bSDimitry Andric
19db17bf38SDimitry Andric #include "llvm/IR/DataLayout.h"
20139f7f9bSDimitry Andric #include "llvm/ADT/DenseMap.h"
210f5676f4SDimitry Andric #include "llvm/ADT/StringRef.h"
2291bc56edSDimitry Andric #include "llvm/ADT/Triple.h"
23139f7f9bSDimitry Andric #include "llvm/IR/Constants.h"
24139f7f9bSDimitry Andric #include "llvm/IR/DerivedTypes.h"
2591bc56edSDimitry Andric #include "llvm/IR/GetElementPtrTypeIterator.h"
260f5676f4SDimitry Andric #include "llvm/IR/GlobalVariable.h"
27139f7f9bSDimitry Andric #include "llvm/IR/Module.h"
280f5676f4SDimitry Andric #include "llvm/IR/Type.h"
290f5676f4SDimitry Andric #include "llvm/IR/Value.h"
300f5676f4SDimitry Andric #include "llvm/Support/Casting.h"
31139f7f9bSDimitry Andric #include "llvm/Support/ErrorHandling.h"
32139f7f9bSDimitry Andric #include "llvm/Support/MathExtras.h"
33139f7f9bSDimitry Andric #include <algorithm>
340f5676f4SDimitry Andric #include <cassert>
350f5676f4SDimitry Andric #include <cstdint>
36139f7f9bSDimitry Andric #include <cstdlib>
370f5676f4SDimitry Andric #include <tuple>
380f5676f4SDimitry Andric #include <utility>
390f5676f4SDimitry Andric
40139f7f9bSDimitry Andric using namespace llvm;
41139f7f9bSDimitry Andric
42139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
43139f7f9bSDimitry Andric // Support for StructLayout
44139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
45139f7f9bSDimitry Andric
StructLayout(StructType * ST,const DataLayout & DL)46284c1978SDimitry Andric StructLayout::StructLayout(StructType *ST, const DataLayout &DL) {
47139f7f9bSDimitry Andric assert(!ST->isOpaque() && "Cannot get layout of opaque structs");
48139f7f9bSDimitry Andric StructAlignment = 0;
49139f7f9bSDimitry Andric StructSize = 0;
507d523365SDimitry Andric IsPadded = false;
51139f7f9bSDimitry Andric NumElements = ST->getNumElements();
52139f7f9bSDimitry Andric
53139f7f9bSDimitry Andric // Loop over each of the elements, placing them in memory.
54139f7f9bSDimitry Andric for (unsigned i = 0, e = NumElements; i != e; ++i) {
55139f7f9bSDimitry Andric Type *Ty = ST->getElementType(i);
56284c1978SDimitry Andric unsigned TyAlign = ST->isPacked() ? 1 : DL.getABITypeAlignment(Ty);
57139f7f9bSDimitry Andric
58139f7f9bSDimitry Andric // Add padding if necessary to align the data element properly.
597d523365SDimitry Andric if ((StructSize & (TyAlign-1)) != 0) {
607d523365SDimitry Andric IsPadded = true;
613ca95b02SDimitry Andric StructSize = alignTo(StructSize, TyAlign);
627d523365SDimitry Andric }
63139f7f9bSDimitry Andric
64139f7f9bSDimitry Andric // Keep track of maximum alignment constraint.
65139f7f9bSDimitry Andric StructAlignment = std::max(TyAlign, StructAlignment);
66139f7f9bSDimitry Andric
67139f7f9bSDimitry Andric MemberOffsets[i] = StructSize;
68284c1978SDimitry Andric StructSize += DL.getTypeAllocSize(Ty); // Consume space for this data item
69139f7f9bSDimitry Andric }
70139f7f9bSDimitry Andric
71139f7f9bSDimitry Andric // Empty structures have alignment of 1 byte.
72139f7f9bSDimitry Andric if (StructAlignment == 0) StructAlignment = 1;
73139f7f9bSDimitry Andric
74139f7f9bSDimitry Andric // Add padding to the end of the struct so that it could be put in an array
75139f7f9bSDimitry Andric // and all array elements would be aligned correctly.
767d523365SDimitry Andric if ((StructSize & (StructAlignment-1)) != 0) {
777d523365SDimitry Andric IsPadded = true;
783ca95b02SDimitry Andric StructSize = alignTo(StructSize, StructAlignment);
79139f7f9bSDimitry Andric }
807d523365SDimitry Andric }
81139f7f9bSDimitry Andric
82139f7f9bSDimitry Andric /// getElementContainingOffset - Given a valid offset into the structure,
83139f7f9bSDimitry Andric /// return the structure index that contains it.
getElementContainingOffset(uint64_t Offset) const84139f7f9bSDimitry Andric unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const {
85139f7f9bSDimitry Andric const uint64_t *SI =
86139f7f9bSDimitry Andric std::upper_bound(&MemberOffsets[0], &MemberOffsets[NumElements], Offset);
87139f7f9bSDimitry Andric assert(SI != &MemberOffsets[0] && "Offset not in structure type!");
88139f7f9bSDimitry Andric --SI;
89139f7f9bSDimitry Andric assert(*SI <= Offset && "upper_bound didn't work");
90139f7f9bSDimitry Andric assert((SI == &MemberOffsets[0] || *(SI-1) <= Offset) &&
91139f7f9bSDimitry Andric (SI+1 == &MemberOffsets[NumElements] || *(SI+1) > Offset) &&
92139f7f9bSDimitry Andric "Upper bound didn't work!");
93139f7f9bSDimitry Andric
94139f7f9bSDimitry Andric // Multiple fields can have the same offset if any of them are zero sized.
95139f7f9bSDimitry Andric // For example, in { i32, [0 x i32], i32 }, searching for offset 4 will stop
96139f7f9bSDimitry Andric // at the i32 element, because it is the last element at that offset. This is
97139f7f9bSDimitry Andric // the right one to return, because anything after it will have a higher
98139f7f9bSDimitry Andric // offset, implying that this element is non-empty.
99139f7f9bSDimitry Andric return SI-&MemberOffsets[0];
100139f7f9bSDimitry Andric }
101139f7f9bSDimitry Andric
102139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
103139f7f9bSDimitry Andric // LayoutAlignElem, LayoutAlign support
104139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
105139f7f9bSDimitry Andric
106139f7f9bSDimitry Andric LayoutAlignElem
get(AlignTypeEnum align_type,unsigned abi_align,unsigned pref_align,uint32_t bit_width)107139f7f9bSDimitry Andric LayoutAlignElem::get(AlignTypeEnum align_type, unsigned abi_align,
108139f7f9bSDimitry Andric unsigned pref_align, uint32_t bit_width) {
109139f7f9bSDimitry Andric assert(abi_align <= pref_align && "Preferred alignment worse than ABI!");
110139f7f9bSDimitry Andric LayoutAlignElem retval;
111139f7f9bSDimitry Andric retval.AlignType = align_type;
112139f7f9bSDimitry Andric retval.ABIAlign = abi_align;
113139f7f9bSDimitry Andric retval.PrefAlign = pref_align;
114139f7f9bSDimitry Andric retval.TypeBitWidth = bit_width;
115139f7f9bSDimitry Andric return retval;
116139f7f9bSDimitry Andric }
117139f7f9bSDimitry Andric
118139f7f9bSDimitry Andric bool
operator ==(const LayoutAlignElem & rhs) const119139f7f9bSDimitry Andric LayoutAlignElem::operator==(const LayoutAlignElem &rhs) const {
120139f7f9bSDimitry Andric return (AlignType == rhs.AlignType
121139f7f9bSDimitry Andric && ABIAlign == rhs.ABIAlign
122139f7f9bSDimitry Andric && PrefAlign == rhs.PrefAlign
123139f7f9bSDimitry Andric && TypeBitWidth == rhs.TypeBitWidth);
124139f7f9bSDimitry Andric }
125139f7f9bSDimitry Andric
126139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
127139f7f9bSDimitry Andric // PointerAlignElem, PointerAlign support
128139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
129139f7f9bSDimitry Andric
130139f7f9bSDimitry Andric PointerAlignElem
get(uint32_t AddressSpace,unsigned ABIAlign,unsigned PrefAlign,uint32_t TypeByteWidth,uint32_t IndexWidth)13191bc56edSDimitry Andric PointerAlignElem::get(uint32_t AddressSpace, unsigned ABIAlign,
1324ba319b5SDimitry Andric unsigned PrefAlign, uint32_t TypeByteWidth,
1334ba319b5SDimitry Andric uint32_t IndexWidth) {
13491bc56edSDimitry Andric assert(ABIAlign <= PrefAlign && "Preferred alignment worse than ABI!");
135139f7f9bSDimitry Andric PointerAlignElem retval;
13691bc56edSDimitry Andric retval.AddressSpace = AddressSpace;
13791bc56edSDimitry Andric retval.ABIAlign = ABIAlign;
13891bc56edSDimitry Andric retval.PrefAlign = PrefAlign;
13991bc56edSDimitry Andric retval.TypeByteWidth = TypeByteWidth;
1404ba319b5SDimitry Andric retval.IndexWidth = IndexWidth;
141139f7f9bSDimitry Andric return retval;
142139f7f9bSDimitry Andric }
143139f7f9bSDimitry Andric
144139f7f9bSDimitry Andric bool
operator ==(const PointerAlignElem & rhs) const145139f7f9bSDimitry Andric PointerAlignElem::operator==(const PointerAlignElem &rhs) const {
146139f7f9bSDimitry Andric return (ABIAlign == rhs.ABIAlign
147139f7f9bSDimitry Andric && AddressSpace == rhs.AddressSpace
148139f7f9bSDimitry Andric && PrefAlign == rhs.PrefAlign
1494ba319b5SDimitry Andric && TypeByteWidth == rhs.TypeByteWidth
1504ba319b5SDimitry Andric && IndexWidth == rhs.IndexWidth);
151139f7f9bSDimitry Andric }
152139f7f9bSDimitry Andric
153139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
154139f7f9bSDimitry Andric // DataLayout Class Implementation
155139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
156139f7f9bSDimitry Andric
getManglingComponent(const Triple & T)15791bc56edSDimitry Andric const char *DataLayout::getManglingComponent(const Triple &T) {
15891bc56edSDimitry Andric if (T.isOSBinFormatMachO())
15991bc56edSDimitry Andric return "-m:o";
160ff0cc061SDimitry Andric if (T.isOSWindows() && T.isOSBinFormatCOFF())
161ff0cc061SDimitry Andric return T.getArch() == Triple::x86 ? "-m:x" : "-m:w";
16291bc56edSDimitry Andric return "-m:e";
16391bc56edSDimitry Andric }
164139f7f9bSDimitry Andric
16591bc56edSDimitry Andric static const LayoutAlignElem DefaultAlignments[] = {
16691bc56edSDimitry Andric { INTEGER_ALIGN, 1, 1, 1 }, // i1
16791bc56edSDimitry Andric { INTEGER_ALIGN, 8, 1, 1 }, // i8
16891bc56edSDimitry Andric { INTEGER_ALIGN, 16, 2, 2 }, // i16
16991bc56edSDimitry Andric { INTEGER_ALIGN, 32, 4, 4 }, // i32
17091bc56edSDimitry Andric { INTEGER_ALIGN, 64, 4, 8 }, // i64
17191bc56edSDimitry Andric { FLOAT_ALIGN, 16, 2, 2 }, // half
17291bc56edSDimitry Andric { FLOAT_ALIGN, 32, 4, 4 }, // float
17391bc56edSDimitry Andric { FLOAT_ALIGN, 64, 8, 8 }, // double
17491bc56edSDimitry Andric { FLOAT_ALIGN, 128, 16, 16 }, // ppcf128, quad, ...
17591bc56edSDimitry Andric { VECTOR_ALIGN, 64, 8, 8 }, // v2i32, v1i64, ...
17691bc56edSDimitry Andric { VECTOR_ALIGN, 128, 16, 16 }, // v16i8, v8i16, v4i32, ...
17791bc56edSDimitry Andric { AGGREGATE_ALIGN, 0, 0, 8 } // struct
17891bc56edSDimitry Andric };
17991bc56edSDimitry Andric
reset(StringRef Desc)18091bc56edSDimitry Andric void DataLayout::reset(StringRef Desc) {
18191bc56edSDimitry Andric clear();
18291bc56edSDimitry Andric
18391bc56edSDimitry Andric LayoutMap = nullptr;
18439d628a0SDimitry Andric BigEndian = false;
1857a7e6055SDimitry Andric AllocaAddrSpace = 0;
186139f7f9bSDimitry Andric StackNaturalAlign = 0;
1874ba319b5SDimitry Andric ProgramAddrSpace = 0;
18891bc56edSDimitry Andric ManglingMode = MM_None;
189d88c1a5aSDimitry Andric NonIntegralAddressSpaces.clear();
190139f7f9bSDimitry Andric
191139f7f9bSDimitry Andric // Default alignments
19291bc56edSDimitry Andric for (const LayoutAlignElem &E : DefaultAlignments) {
19391bc56edSDimitry Andric setAlignment((AlignTypeEnum)E.AlignType, E.ABIAlign, E.PrefAlign,
19491bc56edSDimitry Andric E.TypeBitWidth);
19591bc56edSDimitry Andric }
1964ba319b5SDimitry Andric setPointerAlignment(0, 8, 8, 8, 8);
197139f7f9bSDimitry Andric
198139f7f9bSDimitry Andric parseSpecifier(Desc);
199139f7f9bSDimitry Andric }
200139f7f9bSDimitry Andric
201139f7f9bSDimitry Andric /// Checked version of split, to ensure mandatory subparts.
split(StringRef Str,char Separator)202139f7f9bSDimitry Andric static std::pair<StringRef, StringRef> split(StringRef Str, char Separator) {
203139f7f9bSDimitry Andric assert(!Str.empty() && "parse error, string can't be empty here");
204139f7f9bSDimitry Andric std::pair<StringRef, StringRef> Split = Str.split(Separator);
20539d628a0SDimitry Andric if (Split.second.empty() && Split.first != Str)
20639d628a0SDimitry Andric report_fatal_error("Trailing separator in datalayout string");
20739d628a0SDimitry Andric if (!Split.second.empty() && Split.first.empty())
20839d628a0SDimitry Andric report_fatal_error("Expected token before separator in datalayout string");
209139f7f9bSDimitry Andric return Split;
210139f7f9bSDimitry Andric }
211139f7f9bSDimitry Andric
21291bc56edSDimitry Andric /// Get an unsigned integer, including error checks.
getInt(StringRef R)213139f7f9bSDimitry Andric static unsigned getInt(StringRef R) {
214139f7f9bSDimitry Andric unsigned Result;
215139f7f9bSDimitry Andric bool error = R.getAsInteger(10, Result); (void)error;
21691bc56edSDimitry Andric if (error)
21791bc56edSDimitry Andric report_fatal_error("not a number, or does not fit in an unsigned int");
218139f7f9bSDimitry Andric return Result;
219139f7f9bSDimitry Andric }
220139f7f9bSDimitry Andric
221139f7f9bSDimitry Andric /// Convert bits into bytes. Assert if not a byte width multiple.
inBytes(unsigned Bits)222139f7f9bSDimitry Andric static unsigned inBytes(unsigned Bits) {
22339d628a0SDimitry Andric if (Bits % 8)
22439d628a0SDimitry Andric report_fatal_error("number of bits must be a byte width multiple");
225139f7f9bSDimitry Andric return Bits / 8;
226139f7f9bSDimitry Andric }
227139f7f9bSDimitry Andric
getAddrSpace(StringRef R)2284ba319b5SDimitry Andric static unsigned getAddrSpace(StringRef R) {
2294ba319b5SDimitry Andric unsigned AddrSpace = getInt(R);
2304ba319b5SDimitry Andric if (!isUInt<24>(AddrSpace))
2314ba319b5SDimitry Andric report_fatal_error("Invalid address space, must be a 24-bit integer");
2324ba319b5SDimitry Andric return AddrSpace;
2334ba319b5SDimitry Andric }
2344ba319b5SDimitry Andric
parseSpecifier(StringRef Desc)235139f7f9bSDimitry Andric void DataLayout::parseSpecifier(StringRef Desc) {
236ff0cc061SDimitry Andric StringRepresentation = Desc;
237139f7f9bSDimitry Andric while (!Desc.empty()) {
238139f7f9bSDimitry Andric // Split at '-'.
239139f7f9bSDimitry Andric std::pair<StringRef, StringRef> Split = split(Desc, '-');
240139f7f9bSDimitry Andric Desc = Split.second;
241139f7f9bSDimitry Andric
242139f7f9bSDimitry Andric // Split at ':'.
243139f7f9bSDimitry Andric Split = split(Split.first, ':');
244139f7f9bSDimitry Andric
245139f7f9bSDimitry Andric // Aliases used below.
246139f7f9bSDimitry Andric StringRef &Tok = Split.first; // Current token.
247139f7f9bSDimitry Andric StringRef &Rest = Split.second; // The rest of the string.
248139f7f9bSDimitry Andric
249d88c1a5aSDimitry Andric if (Tok == "ni") {
250d88c1a5aSDimitry Andric do {
251d88c1a5aSDimitry Andric Split = split(Rest, ':');
252d88c1a5aSDimitry Andric Rest = Split.second;
253d88c1a5aSDimitry Andric unsigned AS = getInt(Split.first);
254d88c1a5aSDimitry Andric if (AS == 0)
255d88c1a5aSDimitry Andric report_fatal_error("Address space 0 can never be non-integral");
256d88c1a5aSDimitry Andric NonIntegralAddressSpaces.push_back(AS);
257d88c1a5aSDimitry Andric } while (!Rest.empty());
258d88c1a5aSDimitry Andric
259d88c1a5aSDimitry Andric continue;
260d88c1a5aSDimitry Andric }
261d88c1a5aSDimitry Andric
262139f7f9bSDimitry Andric char Specifier = Tok.front();
263139f7f9bSDimitry Andric Tok = Tok.substr(1);
264139f7f9bSDimitry Andric
265139f7f9bSDimitry Andric switch (Specifier) {
26691bc56edSDimitry Andric case 's':
26791bc56edSDimitry Andric // Ignored for backward compatibility.
26891bc56edSDimitry Andric // FIXME: remove this on LLVM 4.0.
26991bc56edSDimitry Andric break;
270139f7f9bSDimitry Andric case 'E':
27139d628a0SDimitry Andric BigEndian = true;
272139f7f9bSDimitry Andric break;
273139f7f9bSDimitry Andric case 'e':
27439d628a0SDimitry Andric BigEndian = false;
275139f7f9bSDimitry Andric break;
276139f7f9bSDimitry Andric case 'p': {
277139f7f9bSDimitry Andric // Address space.
278139f7f9bSDimitry Andric unsigned AddrSpace = Tok.empty() ? 0 : getInt(Tok);
27939d628a0SDimitry Andric if (!isUInt<24>(AddrSpace))
28039d628a0SDimitry Andric report_fatal_error("Invalid address space, must be a 24bit integer");
281139f7f9bSDimitry Andric
282139f7f9bSDimitry Andric // Size.
28339d628a0SDimitry Andric if (Rest.empty())
28439d628a0SDimitry Andric report_fatal_error(
28539d628a0SDimitry Andric "Missing size specification for pointer in datalayout string");
286139f7f9bSDimitry Andric Split = split(Rest, ':');
287139f7f9bSDimitry Andric unsigned PointerMemSize = inBytes(getInt(Tok));
288ff0cc061SDimitry Andric if (!PointerMemSize)
289ff0cc061SDimitry Andric report_fatal_error("Invalid pointer size of 0 bytes");
290139f7f9bSDimitry Andric
291139f7f9bSDimitry Andric // ABI alignment.
29239d628a0SDimitry Andric if (Rest.empty())
29339d628a0SDimitry Andric report_fatal_error(
29439d628a0SDimitry Andric "Missing alignment specification for pointer in datalayout string");
295139f7f9bSDimitry Andric Split = split(Rest, ':');
296139f7f9bSDimitry Andric unsigned PointerABIAlign = inBytes(getInt(Tok));
297ff0cc061SDimitry Andric if (!isPowerOf2_64(PointerABIAlign))
298ff0cc061SDimitry Andric report_fatal_error(
299ff0cc061SDimitry Andric "Pointer ABI alignment must be a power of 2");
300139f7f9bSDimitry Andric
3014ba319b5SDimitry Andric // Size of index used in GEP for address calculation.
3024ba319b5SDimitry Andric // The parameter is optional. By default it is equal to size of pointer.
3034ba319b5SDimitry Andric unsigned IndexSize = PointerMemSize;
3044ba319b5SDimitry Andric
305139f7f9bSDimitry Andric // Preferred alignment.
306139f7f9bSDimitry Andric unsigned PointerPrefAlign = PointerABIAlign;
307139f7f9bSDimitry Andric if (!Rest.empty()) {
308139f7f9bSDimitry Andric Split = split(Rest, ':');
309139f7f9bSDimitry Andric PointerPrefAlign = inBytes(getInt(Tok));
310ff0cc061SDimitry Andric if (!isPowerOf2_64(PointerPrefAlign))
311ff0cc061SDimitry Andric report_fatal_error(
312ff0cc061SDimitry Andric "Pointer preferred alignment must be a power of 2");
313139f7f9bSDimitry Andric
3144ba319b5SDimitry Andric // Now read the index. It is the second optional parameter here.
3154ba319b5SDimitry Andric if (!Rest.empty()) {
3164ba319b5SDimitry Andric Split = split(Rest, ':');
3174ba319b5SDimitry Andric IndexSize = inBytes(getInt(Tok));
3184ba319b5SDimitry Andric if (!IndexSize)
3194ba319b5SDimitry Andric report_fatal_error("Invalid index size of 0 bytes");
3204ba319b5SDimitry Andric }
3214ba319b5SDimitry Andric }
322139f7f9bSDimitry Andric setPointerAlignment(AddrSpace, PointerABIAlign, PointerPrefAlign,
3234ba319b5SDimitry Andric PointerMemSize, IndexSize);
324139f7f9bSDimitry Andric break;
325139f7f9bSDimitry Andric }
326139f7f9bSDimitry Andric case 'i':
327139f7f9bSDimitry Andric case 'v':
328139f7f9bSDimitry Andric case 'f':
32991bc56edSDimitry Andric case 'a': {
330139f7f9bSDimitry Andric AlignTypeEnum AlignType;
331139f7f9bSDimitry Andric switch (Specifier) {
332d8866befSDimitry Andric default: llvm_unreachable("Unexpected specifier!");
333139f7f9bSDimitry Andric case 'i': AlignType = INTEGER_ALIGN; break;
334139f7f9bSDimitry Andric case 'v': AlignType = VECTOR_ALIGN; break;
335139f7f9bSDimitry Andric case 'f': AlignType = FLOAT_ALIGN; break;
336139f7f9bSDimitry Andric case 'a': AlignType = AGGREGATE_ALIGN; break;
337139f7f9bSDimitry Andric }
338139f7f9bSDimitry Andric
339139f7f9bSDimitry Andric // Bit size.
340139f7f9bSDimitry Andric unsigned Size = Tok.empty() ? 0 : getInt(Tok);
341139f7f9bSDimitry Andric
34239d628a0SDimitry Andric if (AlignType == AGGREGATE_ALIGN && Size != 0)
34339d628a0SDimitry Andric report_fatal_error(
34439d628a0SDimitry Andric "Sized aggregate specification in datalayout string");
34591bc56edSDimitry Andric
346139f7f9bSDimitry Andric // ABI alignment.
34739d628a0SDimitry Andric if (Rest.empty())
34839d628a0SDimitry Andric report_fatal_error(
34939d628a0SDimitry Andric "Missing alignment specification in datalayout string");
350139f7f9bSDimitry Andric Split = split(Rest, ':');
351139f7f9bSDimitry Andric unsigned ABIAlign = inBytes(getInt(Tok));
352ff0cc061SDimitry Andric if (AlignType != AGGREGATE_ALIGN && !ABIAlign)
353ff0cc061SDimitry Andric report_fatal_error(
354ff0cc061SDimitry Andric "ABI alignment specification must be >0 for non-aggregate types");
355139f7f9bSDimitry Andric
356139f7f9bSDimitry Andric // Preferred alignment.
357139f7f9bSDimitry Andric unsigned PrefAlign = ABIAlign;
358139f7f9bSDimitry Andric if (!Rest.empty()) {
359139f7f9bSDimitry Andric Split = split(Rest, ':');
360139f7f9bSDimitry Andric PrefAlign = inBytes(getInt(Tok));
361139f7f9bSDimitry Andric }
362139f7f9bSDimitry Andric
363139f7f9bSDimitry Andric setAlignment(AlignType, ABIAlign, PrefAlign, Size);
364139f7f9bSDimitry Andric
365139f7f9bSDimitry Andric break;
366139f7f9bSDimitry Andric }
367139f7f9bSDimitry Andric case 'n': // Native integer types.
3680f5676f4SDimitry Andric while (true) {
369139f7f9bSDimitry Andric unsigned Width = getInt(Tok);
37039d628a0SDimitry Andric if (Width == 0)
37139d628a0SDimitry Andric report_fatal_error(
37239d628a0SDimitry Andric "Zero width native integer type in datalayout string");
373139f7f9bSDimitry Andric LegalIntWidths.push_back(Width);
374139f7f9bSDimitry Andric if (Rest.empty())
375139f7f9bSDimitry Andric break;
376139f7f9bSDimitry Andric Split = split(Rest, ':');
377139f7f9bSDimitry Andric }
378139f7f9bSDimitry Andric break;
379139f7f9bSDimitry Andric case 'S': { // Stack natural alignment.
380139f7f9bSDimitry Andric StackNaturalAlign = inBytes(getInt(Tok));
381139f7f9bSDimitry Andric break;
382139f7f9bSDimitry Andric }
3834ba319b5SDimitry Andric case 'P': { // Function address space.
3844ba319b5SDimitry Andric ProgramAddrSpace = getAddrSpace(Tok);
3854ba319b5SDimitry Andric break;
3864ba319b5SDimitry Andric }
3877a7e6055SDimitry Andric case 'A': { // Default stack/alloca address space.
3884ba319b5SDimitry Andric AllocaAddrSpace = getAddrSpace(Tok);
3897a7e6055SDimitry Andric break;
3907a7e6055SDimitry Andric }
39191bc56edSDimitry Andric case 'm':
39239d628a0SDimitry Andric if (!Tok.empty())
39339d628a0SDimitry Andric report_fatal_error("Unexpected trailing characters after mangling specifier in datalayout string");
39439d628a0SDimitry Andric if (Rest.empty())
39539d628a0SDimitry Andric report_fatal_error("Expected mangling specifier in datalayout string");
39639d628a0SDimitry Andric if (Rest.size() > 1)
39739d628a0SDimitry Andric report_fatal_error("Unknown mangling specifier in datalayout string");
39891bc56edSDimitry Andric switch(Rest[0]) {
39991bc56edSDimitry Andric default:
40039d628a0SDimitry Andric report_fatal_error("Unknown mangling in datalayout string");
40191bc56edSDimitry Andric case 'e':
40291bc56edSDimitry Andric ManglingMode = MM_ELF;
40391bc56edSDimitry Andric break;
40491bc56edSDimitry Andric case 'o':
40591bc56edSDimitry Andric ManglingMode = MM_MachO;
40691bc56edSDimitry Andric break;
40791bc56edSDimitry Andric case 'm':
40891bc56edSDimitry Andric ManglingMode = MM_Mips;
40991bc56edSDimitry Andric break;
41091bc56edSDimitry Andric case 'w':
411ff0cc061SDimitry Andric ManglingMode = MM_WinCOFF;
412ff0cc061SDimitry Andric break;
413ff0cc061SDimitry Andric case 'x':
414ff0cc061SDimitry Andric ManglingMode = MM_WinCOFFX86;
41591bc56edSDimitry Andric break;
41691bc56edSDimitry Andric }
41791bc56edSDimitry Andric break;
418139f7f9bSDimitry Andric default:
41939d628a0SDimitry Andric report_fatal_error("Unknown specifier in datalayout string");
420139f7f9bSDimitry Andric break;
421139f7f9bSDimitry Andric }
422139f7f9bSDimitry Andric }
423139f7f9bSDimitry Andric }
424139f7f9bSDimitry Andric
DataLayout(const Module * M)4250f5676f4SDimitry Andric DataLayout::DataLayout(const Module *M) {
42639d628a0SDimitry Andric init(M);
42739d628a0SDimitry Andric }
42839d628a0SDimitry Andric
init(const Module * M)429ff0cc061SDimitry Andric void DataLayout::init(const Module *M) { *this = M->getDataLayout(); }
430139f7f9bSDimitry Andric
operator ==(const DataLayout & Other) const43191bc56edSDimitry Andric bool DataLayout::operator==(const DataLayout &Other) const {
43239d628a0SDimitry Andric bool Ret = BigEndian == Other.BigEndian &&
4337a7e6055SDimitry Andric AllocaAddrSpace == Other.AllocaAddrSpace &&
43491bc56edSDimitry Andric StackNaturalAlign == Other.StackNaturalAlign &&
4354ba319b5SDimitry Andric ProgramAddrSpace == Other.ProgramAddrSpace &&
43691bc56edSDimitry Andric ManglingMode == Other.ManglingMode &&
43791bc56edSDimitry Andric LegalIntWidths == Other.LegalIntWidths &&
43891bc56edSDimitry Andric Alignments == Other.Alignments && Pointers == Other.Pointers;
439ff0cc061SDimitry Andric // Note: getStringRepresentation() might differs, it is not canonicalized
44091bc56edSDimitry Andric return Ret;
441139f7f9bSDimitry Andric }
442139f7f9bSDimitry Andric
4437a7e6055SDimitry Andric DataLayout::AlignmentsTy::iterator
findAlignmentLowerBound(AlignTypeEnum AlignType,uint32_t BitWidth)4447a7e6055SDimitry Andric DataLayout::findAlignmentLowerBound(AlignTypeEnum AlignType,
4457a7e6055SDimitry Andric uint32_t BitWidth) {
4467a7e6055SDimitry Andric auto Pair = std::make_pair((unsigned)AlignType, BitWidth);
4477a7e6055SDimitry Andric return std::lower_bound(Alignments.begin(), Alignments.end(), Pair,
4487a7e6055SDimitry Andric [](const LayoutAlignElem &LHS,
4497a7e6055SDimitry Andric const std::pair<unsigned, uint32_t> &RHS) {
4507a7e6055SDimitry Andric return std::tie(LHS.AlignType, LHS.TypeBitWidth) <
4517a7e6055SDimitry Andric std::tie(RHS.first, RHS.second);
4527a7e6055SDimitry Andric });
4537a7e6055SDimitry Andric }
4547a7e6055SDimitry Andric
455139f7f9bSDimitry Andric void
setAlignment(AlignTypeEnum align_type,unsigned abi_align,unsigned pref_align,uint32_t bit_width)456139f7f9bSDimitry Andric DataLayout::setAlignment(AlignTypeEnum align_type, unsigned abi_align,
457139f7f9bSDimitry Andric unsigned pref_align, uint32_t bit_width) {
458ff0cc061SDimitry Andric if (!isUInt<24>(bit_width))
459ff0cc061SDimitry Andric report_fatal_error("Invalid bit width, must be a 24bit integer");
460ff0cc061SDimitry Andric if (!isUInt<16>(abi_align))
461ff0cc061SDimitry Andric report_fatal_error("Invalid ABI alignment, must be a 16bit integer");
462ff0cc061SDimitry Andric if (!isUInt<16>(pref_align))
463ff0cc061SDimitry Andric report_fatal_error("Invalid preferred alignment, must be a 16bit integer");
464ff0cc061SDimitry Andric if (abi_align != 0 && !isPowerOf2_64(abi_align))
465ff0cc061SDimitry Andric report_fatal_error("Invalid ABI alignment, must be a power of 2");
466ff0cc061SDimitry Andric if (pref_align != 0 && !isPowerOf2_64(pref_align))
467ff0cc061SDimitry Andric report_fatal_error("Invalid preferred alignment, must be a power of 2");
468ff0cc061SDimitry Andric
469ff0cc061SDimitry Andric if (pref_align < abi_align)
470ff0cc061SDimitry Andric report_fatal_error(
471ff0cc061SDimitry Andric "Preferred alignment cannot be less than the ABI alignment");
472ff0cc061SDimitry Andric
4737a7e6055SDimitry Andric AlignmentsTy::iterator I = findAlignmentLowerBound(align_type, bit_width);
4747a7e6055SDimitry Andric if (I != Alignments.end() &&
4757a7e6055SDimitry Andric I->AlignType == (unsigned)align_type && I->TypeBitWidth == bit_width) {
476139f7f9bSDimitry Andric // Update the abi, preferred alignments.
4777a7e6055SDimitry Andric I->ABIAlign = abi_align;
4787a7e6055SDimitry Andric I->PrefAlign = pref_align;
4797a7e6055SDimitry Andric } else {
4807a7e6055SDimitry Andric // Insert before I to keep the vector sorted.
4817a7e6055SDimitry Andric Alignments.insert(I, LayoutAlignElem::get(align_type, abi_align,
482139f7f9bSDimitry Andric pref_align, bit_width));
483139f7f9bSDimitry Andric }
4847a7e6055SDimitry Andric }
485139f7f9bSDimitry Andric
48691bc56edSDimitry Andric DataLayout::PointersTy::iterator
findPointerLowerBound(uint32_t AddressSpace)48791bc56edSDimitry Andric DataLayout::findPointerLowerBound(uint32_t AddressSpace) {
48891bc56edSDimitry Andric return std::lower_bound(Pointers.begin(), Pointers.end(), AddressSpace,
48991bc56edSDimitry Andric [](const PointerAlignElem &A, uint32_t AddressSpace) {
49091bc56edSDimitry Andric return A.AddressSpace < AddressSpace;
49191bc56edSDimitry Andric });
49291bc56edSDimitry Andric }
49391bc56edSDimitry Andric
setPointerAlignment(uint32_t AddrSpace,unsigned ABIAlign,unsigned PrefAlign,uint32_t TypeByteWidth,uint32_t IndexWidth)49491bc56edSDimitry Andric void DataLayout::setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign,
4954ba319b5SDimitry Andric unsigned PrefAlign, uint32_t TypeByteWidth,
4964ba319b5SDimitry Andric uint32_t IndexWidth) {
497ff0cc061SDimitry Andric if (PrefAlign < ABIAlign)
498ff0cc061SDimitry Andric report_fatal_error(
499ff0cc061SDimitry Andric "Preferred alignment cannot be less than the ABI alignment");
500ff0cc061SDimitry Andric
50191bc56edSDimitry Andric PointersTy::iterator I = findPointerLowerBound(AddrSpace);
50291bc56edSDimitry Andric if (I == Pointers.end() || I->AddressSpace != AddrSpace) {
50391bc56edSDimitry Andric Pointers.insert(I, PointerAlignElem::get(AddrSpace, ABIAlign, PrefAlign,
5044ba319b5SDimitry Andric TypeByteWidth, IndexWidth));
505139f7f9bSDimitry Andric } else {
50691bc56edSDimitry Andric I->ABIAlign = ABIAlign;
50791bc56edSDimitry Andric I->PrefAlign = PrefAlign;
50891bc56edSDimitry Andric I->TypeByteWidth = TypeByteWidth;
5094ba319b5SDimitry Andric I->IndexWidth = IndexWidth;
510139f7f9bSDimitry Andric }
511139f7f9bSDimitry Andric }
512139f7f9bSDimitry Andric
513139f7f9bSDimitry Andric /// getAlignmentInfo - Return the alignment (either ABI if ABIInfo = true or
514139f7f9bSDimitry Andric /// preferred if ABIInfo = false) the layout wants for the specified datatype.
getAlignmentInfo(AlignTypeEnum AlignType,uint32_t BitWidth,bool ABIInfo,Type * Ty) const515139f7f9bSDimitry Andric unsigned DataLayout::getAlignmentInfo(AlignTypeEnum AlignType,
516139f7f9bSDimitry Andric uint32_t BitWidth, bool ABIInfo,
517139f7f9bSDimitry Andric Type *Ty) const {
5187a7e6055SDimitry Andric AlignmentsTy::const_iterator I = findAlignmentLowerBound(AlignType, BitWidth);
5197a7e6055SDimitry Andric // See if we found an exact match. Of if we are looking for an integer type,
5207a7e6055SDimitry Andric // but don't have an exact match take the next largest integer. This is where
5217a7e6055SDimitry Andric // the lower_bound will point to when it fails an exact match.
5227a7e6055SDimitry Andric if (I != Alignments.end() && I->AlignType == (unsigned)AlignType &&
5237a7e6055SDimitry Andric (I->TypeBitWidth == BitWidth || AlignType == INTEGER_ALIGN))
5247a7e6055SDimitry Andric return ABIInfo ? I->ABIAlign : I->PrefAlign;
525139f7f9bSDimitry Andric
526139f7f9bSDimitry Andric if (AlignType == INTEGER_ALIGN) {
5277a7e6055SDimitry Andric // If we didn't have a larger value try the largest value we have.
5287a7e6055SDimitry Andric if (I != Alignments.begin()) {
5297a7e6055SDimitry Andric --I; // Go to the previous entry and see if its an integer.
5307a7e6055SDimitry Andric if (I->AlignType == INTEGER_ALIGN)
5317a7e6055SDimitry Andric return ABIInfo ? I->ABIAlign : I->PrefAlign;
5327a7e6055SDimitry Andric }
533ff0cc061SDimitry Andric } else if (AlignType == VECTOR_ALIGN) {
534139f7f9bSDimitry Andric // By default, use natural alignment for vector types. This is consistent
535139f7f9bSDimitry Andric // with what clang and llvm-gcc do.
536139f7f9bSDimitry Andric unsigned Align = getTypeAllocSize(cast<VectorType>(Ty)->getElementType());
537139f7f9bSDimitry Andric Align *= cast<VectorType>(Ty)->getNumElements();
538d88c1a5aSDimitry Andric Align = PowerOf2Ceil(Align);
539139f7f9bSDimitry Andric return Align;
540139f7f9bSDimitry Andric }
541139f7f9bSDimitry Andric
542ff0cc061SDimitry Andric // If we still couldn't find a reasonable default alignment, fall back
543ff0cc061SDimitry Andric // to a simple heuristic that the alignment is the first power of two
544ff0cc061SDimitry Andric // greater-or-equal to the store size of the type. This is a reasonable
545ff0cc061SDimitry Andric // approximation of reality, and if the user wanted something less
546ff0cc061SDimitry Andric // less conservative, they should have specified it explicitly in the data
547ff0cc061SDimitry Andric // layout.
548ff0cc061SDimitry Andric unsigned Align = getTypeStoreSize(Ty);
549d88c1a5aSDimitry Andric Align = PowerOf2Ceil(Align);
550ff0cc061SDimitry Andric return Align;
551ff0cc061SDimitry Andric }
552ff0cc061SDimitry Andric
553139f7f9bSDimitry Andric namespace {
554139f7f9bSDimitry Andric
555139f7f9bSDimitry Andric class StructLayoutMap {
5560f5676f4SDimitry Andric using LayoutInfoTy = DenseMap<StructType*, StructLayout*>;
557139f7f9bSDimitry Andric LayoutInfoTy LayoutInfo;
558139f7f9bSDimitry Andric
559139f7f9bSDimitry Andric public:
~StructLayoutMap()56091bc56edSDimitry Andric ~StructLayoutMap() {
561139f7f9bSDimitry Andric // Remove any layouts.
56291bc56edSDimitry Andric for (const auto &I : LayoutInfo) {
56391bc56edSDimitry Andric StructLayout *Value = I.second;
564139f7f9bSDimitry Andric Value->~StructLayout();
565139f7f9bSDimitry Andric free(Value);
566139f7f9bSDimitry Andric }
567139f7f9bSDimitry Andric }
568139f7f9bSDimitry Andric
operator [](StructType * STy)569139f7f9bSDimitry Andric StructLayout *&operator[](StructType *STy) {
570139f7f9bSDimitry Andric return LayoutInfo[STy];
571139f7f9bSDimitry Andric }
572139f7f9bSDimitry Andric };
573139f7f9bSDimitry Andric
574139f7f9bSDimitry Andric } // end anonymous namespace
575139f7f9bSDimitry Andric
clear()57691bc56edSDimitry Andric void DataLayout::clear() {
57791bc56edSDimitry Andric LegalIntWidths.clear();
57891bc56edSDimitry Andric Alignments.clear();
57991bc56edSDimitry Andric Pointers.clear();
580139f7f9bSDimitry Andric delete static_cast<StructLayoutMap *>(LayoutMap);
58191bc56edSDimitry Andric LayoutMap = nullptr;
582139f7f9bSDimitry Andric }
583139f7f9bSDimitry Andric
~DataLayout()58491bc56edSDimitry Andric DataLayout::~DataLayout() {
58591bc56edSDimitry Andric clear();
586139f7f9bSDimitry Andric }
587139f7f9bSDimitry Andric
getStructLayout(StructType * Ty) const588139f7f9bSDimitry Andric const StructLayout *DataLayout::getStructLayout(StructType *Ty) const {
589139f7f9bSDimitry Andric if (!LayoutMap)
590139f7f9bSDimitry Andric LayoutMap = new StructLayoutMap();
591139f7f9bSDimitry Andric
592139f7f9bSDimitry Andric StructLayoutMap *STM = static_cast<StructLayoutMap*>(LayoutMap);
593139f7f9bSDimitry Andric StructLayout *&SL = (*STM)[Ty];
594139f7f9bSDimitry Andric if (SL) return SL;
595139f7f9bSDimitry Andric
596139f7f9bSDimitry Andric // Otherwise, create the struct layout. Because it is variable length, we
597139f7f9bSDimitry Andric // malloc it, then use placement new.
598139f7f9bSDimitry Andric int NumElts = Ty->getNumElements();
5994ba319b5SDimitry Andric StructLayout *L = (StructLayout *)
6004ba319b5SDimitry Andric safe_malloc(sizeof(StructLayout)+(NumElts-1) * sizeof(uint64_t));
601139f7f9bSDimitry Andric
602139f7f9bSDimitry Andric // Set SL before calling StructLayout's ctor. The ctor could cause other
603139f7f9bSDimitry Andric // entries to be added to TheMap, invalidating our reference.
604139f7f9bSDimitry Andric SL = L;
605139f7f9bSDimitry Andric
606139f7f9bSDimitry Andric new (L) StructLayout(Ty, *this);
607139f7f9bSDimitry Andric
608139f7f9bSDimitry Andric return L;
609139f7f9bSDimitry Andric }
610139f7f9bSDimitry Andric
getPointerABIAlignment(unsigned AS) const61191bc56edSDimitry Andric unsigned DataLayout::getPointerABIAlignment(unsigned AS) const {
61291bc56edSDimitry Andric PointersTy::const_iterator I = findPointerLowerBound(AS);
61391bc56edSDimitry Andric if (I == Pointers.end() || I->AddressSpace != AS) {
61491bc56edSDimitry Andric I = findPointerLowerBound(0);
61591bc56edSDimitry Andric assert(I->AddressSpace == 0);
61691bc56edSDimitry Andric }
61791bc56edSDimitry Andric return I->ABIAlign;
61891bc56edSDimitry Andric }
61991bc56edSDimitry Andric
getPointerPrefAlignment(unsigned AS) const62091bc56edSDimitry Andric unsigned DataLayout::getPointerPrefAlignment(unsigned AS) const {
62191bc56edSDimitry Andric PointersTy::const_iterator I = findPointerLowerBound(AS);
62291bc56edSDimitry Andric if (I == Pointers.end() || I->AddressSpace != AS) {
62391bc56edSDimitry Andric I = findPointerLowerBound(0);
62491bc56edSDimitry Andric assert(I->AddressSpace == 0);
62591bc56edSDimitry Andric }
62691bc56edSDimitry Andric return I->PrefAlign;
62791bc56edSDimitry Andric }
62891bc56edSDimitry Andric
getPointerSize(unsigned AS) const62991bc56edSDimitry Andric unsigned DataLayout::getPointerSize(unsigned AS) const {
63091bc56edSDimitry Andric PointersTy::const_iterator I = findPointerLowerBound(AS);
63191bc56edSDimitry Andric if (I == Pointers.end() || I->AddressSpace != AS) {
63291bc56edSDimitry Andric I = findPointerLowerBound(0);
63391bc56edSDimitry Andric assert(I->AddressSpace == 0);
63491bc56edSDimitry Andric }
63591bc56edSDimitry Andric return I->TypeByteWidth;
63691bc56edSDimitry Andric }
63791bc56edSDimitry Andric
getMaxPointerSize() const638*b5893f02SDimitry Andric unsigned DataLayout::getMaxPointerSize() const {
639*b5893f02SDimitry Andric unsigned MaxPointerSize = 0;
640*b5893f02SDimitry Andric for (auto &P : Pointers)
641*b5893f02SDimitry Andric MaxPointerSize = std::max(MaxPointerSize, P.TypeByteWidth);
642*b5893f02SDimitry Andric
643*b5893f02SDimitry Andric return MaxPointerSize;
644*b5893f02SDimitry Andric }
645*b5893f02SDimitry Andric
getPointerTypeSizeInBits(Type * Ty) const646f785676fSDimitry Andric unsigned DataLayout::getPointerTypeSizeInBits(Type *Ty) const {
647f785676fSDimitry Andric assert(Ty->isPtrOrPtrVectorTy() &&
648f785676fSDimitry Andric "This should only be called with a pointer or pointer vector type");
6496bc11b14SDimitry Andric Ty = Ty->getScalarType();
6506bc11b14SDimitry Andric return getPointerSizeInBits(cast<PointerType>(Ty)->getAddressSpace());
651f785676fSDimitry Andric }
652139f7f9bSDimitry Andric
getIndexSize(unsigned AS) const6534ba319b5SDimitry Andric unsigned DataLayout::getIndexSize(unsigned AS) const {
6544ba319b5SDimitry Andric PointersTy::const_iterator I = findPointerLowerBound(AS);
6554ba319b5SDimitry Andric if (I == Pointers.end() || I->AddressSpace != AS) {
6564ba319b5SDimitry Andric I = findPointerLowerBound(0);
6574ba319b5SDimitry Andric assert(I->AddressSpace == 0);
6584ba319b5SDimitry Andric }
6594ba319b5SDimitry Andric return I->IndexWidth;
6604ba319b5SDimitry Andric }
6614ba319b5SDimitry Andric
getIndexTypeSizeInBits(Type * Ty) const6624ba319b5SDimitry Andric unsigned DataLayout::getIndexTypeSizeInBits(Type *Ty) const {
6634ba319b5SDimitry Andric assert(Ty->isPtrOrPtrVectorTy() &&
6644ba319b5SDimitry Andric "This should only be called with a pointer or pointer vector type");
6654ba319b5SDimitry Andric Ty = Ty->getScalarType();
6664ba319b5SDimitry Andric return getIndexSizeInBits(cast<PointerType>(Ty)->getAddressSpace());
6674ba319b5SDimitry Andric }
6684ba319b5SDimitry Andric
669139f7f9bSDimitry Andric /*!
670139f7f9bSDimitry Andric \param abi_or_pref Flag that determines which alignment is returned. true
671139f7f9bSDimitry Andric returns the ABI alignment, false returns the preferred alignment.
672139f7f9bSDimitry Andric \param Ty The underlying type for which alignment is determined.
673139f7f9bSDimitry Andric
674139f7f9bSDimitry Andric Get the ABI (\a abi_or_pref == true) or preferred alignment (\a abi_or_pref
675139f7f9bSDimitry Andric == false) for the requested type \a Ty.
676139f7f9bSDimitry Andric */
getAlignment(Type * Ty,bool abi_or_pref) const677139f7f9bSDimitry Andric unsigned DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const {
6786bc11b14SDimitry Andric AlignTypeEnum AlignType;
679139f7f9bSDimitry Andric
680139f7f9bSDimitry Andric assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
681139f7f9bSDimitry Andric switch (Ty->getTypeID()) {
682139f7f9bSDimitry Andric // Early escape for the non-numeric types.
683139f7f9bSDimitry Andric case Type::LabelTyID:
684139f7f9bSDimitry Andric return (abi_or_pref
685139f7f9bSDimitry Andric ? getPointerABIAlignment(0)
686139f7f9bSDimitry Andric : getPointerPrefAlignment(0));
687139f7f9bSDimitry Andric case Type::PointerTyID: {
68839d628a0SDimitry Andric unsigned AS = cast<PointerType>(Ty)->getAddressSpace();
689139f7f9bSDimitry Andric return (abi_or_pref
690139f7f9bSDimitry Andric ? getPointerABIAlignment(AS)
691139f7f9bSDimitry Andric : getPointerPrefAlignment(AS));
692139f7f9bSDimitry Andric }
693139f7f9bSDimitry Andric case Type::ArrayTyID:
694139f7f9bSDimitry Andric return getAlignment(cast<ArrayType>(Ty)->getElementType(), abi_or_pref);
695139f7f9bSDimitry Andric
696139f7f9bSDimitry Andric case Type::StructTyID: {
697139f7f9bSDimitry Andric // Packed structure types always have an ABI alignment of one.
698139f7f9bSDimitry Andric if (cast<StructType>(Ty)->isPacked() && abi_or_pref)
699139f7f9bSDimitry Andric return 1;
700139f7f9bSDimitry Andric
701139f7f9bSDimitry Andric // Get the layout annotation... which is lazily created on demand.
702139f7f9bSDimitry Andric const StructLayout *Layout = getStructLayout(cast<StructType>(Ty));
703139f7f9bSDimitry Andric unsigned Align = getAlignmentInfo(AGGREGATE_ALIGN, 0, abi_or_pref, Ty);
704139f7f9bSDimitry Andric return std::max(Align, Layout->getAlignment());
705139f7f9bSDimitry Andric }
706139f7f9bSDimitry Andric case Type::IntegerTyID:
707139f7f9bSDimitry Andric AlignType = INTEGER_ALIGN;
708139f7f9bSDimitry Andric break;
709139f7f9bSDimitry Andric case Type::HalfTyID:
710139f7f9bSDimitry Andric case Type::FloatTyID:
711139f7f9bSDimitry Andric case Type::DoubleTyID:
712139f7f9bSDimitry Andric // PPC_FP128TyID and FP128TyID have different data contents, but the
713139f7f9bSDimitry Andric // same size and alignment, so they look the same here.
714139f7f9bSDimitry Andric case Type::PPC_FP128TyID:
715139f7f9bSDimitry Andric case Type::FP128TyID:
716139f7f9bSDimitry Andric case Type::X86_FP80TyID:
717139f7f9bSDimitry Andric AlignType = FLOAT_ALIGN;
718139f7f9bSDimitry Andric break;
719139f7f9bSDimitry Andric case Type::X86_MMXTyID:
720139f7f9bSDimitry Andric case Type::VectorTyID:
721139f7f9bSDimitry Andric AlignType = VECTOR_ALIGN;
722139f7f9bSDimitry Andric break;
723139f7f9bSDimitry Andric default:
724139f7f9bSDimitry Andric llvm_unreachable("Bad type for getAlignment!!!");
725139f7f9bSDimitry Andric }
726139f7f9bSDimitry Andric
7276bc11b14SDimitry Andric return getAlignmentInfo(AlignType, getTypeSizeInBits(Ty), abi_or_pref, Ty);
728139f7f9bSDimitry Andric }
729139f7f9bSDimitry Andric
getABITypeAlignment(Type * Ty) const730139f7f9bSDimitry Andric unsigned DataLayout::getABITypeAlignment(Type *Ty) const {
731139f7f9bSDimitry Andric return getAlignment(Ty, true);
732139f7f9bSDimitry Andric }
733139f7f9bSDimitry Andric
734139f7f9bSDimitry Andric /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for
735139f7f9bSDimitry Andric /// an integer type of the specified bitwidth.
getABIIntegerTypeAlignment(unsigned BitWidth) const736139f7f9bSDimitry Andric unsigned DataLayout::getABIIntegerTypeAlignment(unsigned BitWidth) const {
73791bc56edSDimitry Andric return getAlignmentInfo(INTEGER_ALIGN, BitWidth, true, nullptr);
738139f7f9bSDimitry Andric }
739139f7f9bSDimitry Andric
getPrefTypeAlignment(Type * Ty) const740139f7f9bSDimitry Andric unsigned DataLayout::getPrefTypeAlignment(Type *Ty) const {
741139f7f9bSDimitry Andric return getAlignment(Ty, false);
742139f7f9bSDimitry Andric }
743139f7f9bSDimitry Andric
getPreferredTypeAlignmentShift(Type * Ty) const744139f7f9bSDimitry Andric unsigned DataLayout::getPreferredTypeAlignmentShift(Type *Ty) const {
745139f7f9bSDimitry Andric unsigned Align = getPrefTypeAlignment(Ty);
746139f7f9bSDimitry Andric assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
747139f7f9bSDimitry Andric return Log2_32(Align);
748139f7f9bSDimitry Andric }
749139f7f9bSDimitry Andric
getIntPtrType(LLVMContext & C,unsigned AddressSpace) const750139f7f9bSDimitry Andric IntegerType *DataLayout::getIntPtrType(LLVMContext &C,
751139f7f9bSDimitry Andric unsigned AddressSpace) const {
7524ba319b5SDimitry Andric return IntegerType::get(C, getIndexSizeInBits(AddressSpace));
753139f7f9bSDimitry Andric }
754139f7f9bSDimitry Andric
getIntPtrType(Type * Ty) const755139f7f9bSDimitry Andric Type *DataLayout::getIntPtrType(Type *Ty) const {
756139f7f9bSDimitry Andric assert(Ty->isPtrOrPtrVectorTy() &&
757139f7f9bSDimitry Andric "Expected a pointer or pointer vector type.");
7584ba319b5SDimitry Andric unsigned NumBits = getIndexTypeSizeInBits(Ty);
759139f7f9bSDimitry Andric IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits);
760139f7f9bSDimitry Andric if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
761139f7f9bSDimitry Andric return VectorType::get(IntTy, VecTy->getNumElements());
762139f7f9bSDimitry Andric return IntTy;
763139f7f9bSDimitry Andric }
764139f7f9bSDimitry Andric
getSmallestLegalIntType(LLVMContext & C,unsigned Width) const765139f7f9bSDimitry Andric Type *DataLayout::getSmallestLegalIntType(LLVMContext &C, unsigned Width) const {
76691bc56edSDimitry Andric for (unsigned LegalIntWidth : LegalIntWidths)
76791bc56edSDimitry Andric if (Width <= LegalIntWidth)
76891bc56edSDimitry Andric return Type::getIntNTy(C, LegalIntWidth);
76991bc56edSDimitry Andric return nullptr;
770139f7f9bSDimitry Andric }
771139f7f9bSDimitry Andric
getLargestLegalIntTypeSizeInBits() const7723ca95b02SDimitry Andric unsigned DataLayout::getLargestLegalIntTypeSizeInBits() const {
77391bc56edSDimitry Andric auto Max = std::max_element(LegalIntWidths.begin(), LegalIntWidths.end());
77491bc56edSDimitry Andric return Max != LegalIntWidths.end() ? *Max : 0;
775f785676fSDimitry Andric }
776f785676fSDimitry Andric
getIndexType(Type * Ty) const7774ba319b5SDimitry Andric Type *DataLayout::getIndexType(Type *Ty) const {
7784ba319b5SDimitry Andric assert(Ty->isPtrOrPtrVectorTy() &&
7794ba319b5SDimitry Andric "Expected a pointer or pointer vector type.");
7804ba319b5SDimitry Andric unsigned NumBits = getIndexTypeSizeInBits(Ty);
7814ba319b5SDimitry Andric IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits);
7824ba319b5SDimitry Andric if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
7834ba319b5SDimitry Andric return VectorType::get(IntTy, VecTy->getNumElements());
7844ba319b5SDimitry Andric return IntTy;
7854ba319b5SDimitry Andric }
7864ba319b5SDimitry Andric
getIndexedOffsetInType(Type * ElemTy,ArrayRef<Value * > Indices) const7873ca95b02SDimitry Andric int64_t DataLayout::getIndexedOffsetInType(Type *ElemTy,
788139f7f9bSDimitry Andric ArrayRef<Value *> Indices) const {
7893ca95b02SDimitry Andric int64_t Result = 0;
790139f7f9bSDimitry Andric
791139f7f9bSDimitry Andric generic_gep_type_iterator<Value* const*>
792d88c1a5aSDimitry Andric GTI = gep_type_begin(ElemTy, Indices),
793d88c1a5aSDimitry Andric GTE = gep_type_end(ElemTy, Indices);
7943ca95b02SDimitry Andric for (; GTI != GTE; ++GTI) {
7953ca95b02SDimitry Andric Value *Idx = GTI.getOperand();
796d88c1a5aSDimitry Andric if (StructType *STy = GTI.getStructTypeOrNull()) {
7973ca95b02SDimitry Andric assert(Idx->getType()->isIntegerTy(32) && "Illegal struct idx");
7983ca95b02SDimitry Andric unsigned FieldNo = cast<ConstantInt>(Idx)->getZExtValue();
799139f7f9bSDimitry Andric
800139f7f9bSDimitry Andric // Get structure layout information...
801139f7f9bSDimitry Andric const StructLayout *Layout = getStructLayout(STy);
802139f7f9bSDimitry Andric
803139f7f9bSDimitry Andric // Add in the offset, as calculated by the structure layout info...
804139f7f9bSDimitry Andric Result += Layout->getElementOffset(FieldNo);
805139f7f9bSDimitry Andric } else {
806139f7f9bSDimitry Andric // Get the array index and the size of each array element.
8073ca95b02SDimitry Andric if (int64_t arrayIdx = cast<ConstantInt>(Idx)->getSExtValue())
8083ca95b02SDimitry Andric Result += arrayIdx * getTypeAllocSize(GTI.getIndexedType());
809139f7f9bSDimitry Andric }
810139f7f9bSDimitry Andric }
811139f7f9bSDimitry Andric
812139f7f9bSDimitry Andric return Result;
813139f7f9bSDimitry Andric }
814139f7f9bSDimitry Andric
815139f7f9bSDimitry Andric /// getPreferredAlignment - Return the preferred alignment of the specified
816139f7f9bSDimitry Andric /// global. This includes an explicitly requested alignment (if the global
817139f7f9bSDimitry Andric /// has one).
getPreferredAlignment(const GlobalVariable * GV) const818139f7f9bSDimitry Andric unsigned DataLayout::getPreferredAlignment(const GlobalVariable *GV) const {
819*b5893f02SDimitry Andric unsigned GVAlignment = GV->getAlignment();
820*b5893f02SDimitry Andric // If a section is specified, always precisely honor explicit alignment,
821*b5893f02SDimitry Andric // so we don't insert padding into a section we don't control.
822*b5893f02SDimitry Andric if (GVAlignment && GV->hasSection())
823*b5893f02SDimitry Andric return GVAlignment;
824*b5893f02SDimitry Andric
825*b5893f02SDimitry Andric // If no explicit alignment is specified, compute the alignment based on
826*b5893f02SDimitry Andric // the IR type. If an alignment is specified, increase it to match the ABI
827*b5893f02SDimitry Andric // alignment of the IR type.
828*b5893f02SDimitry Andric //
829*b5893f02SDimitry Andric // FIXME: Not sure it makes sense to use the alignment of the type if
830*b5893f02SDimitry Andric // there's already an explicit alignment specification.
8313ca95b02SDimitry Andric Type *ElemType = GV->getValueType();
832139f7f9bSDimitry Andric unsigned Alignment = getPrefTypeAlignment(ElemType);
833139f7f9bSDimitry Andric if (GVAlignment >= Alignment) {
834139f7f9bSDimitry Andric Alignment = GVAlignment;
835139f7f9bSDimitry Andric } else if (GVAlignment != 0) {
836139f7f9bSDimitry Andric Alignment = std::max(GVAlignment, getABITypeAlignment(ElemType));
837139f7f9bSDimitry Andric }
838139f7f9bSDimitry Andric
839*b5893f02SDimitry Andric // If no explicit alignment is specified, and the global is large, increase
840*b5893f02SDimitry Andric // the alignment to 16.
841*b5893f02SDimitry Andric // FIXME: Why 16, specifically?
842139f7f9bSDimitry Andric if (GV->hasInitializer() && GVAlignment == 0) {
843139f7f9bSDimitry Andric if (Alignment < 16) {
844139f7f9bSDimitry Andric // If the global is not external, see if it is large. If so, give it a
845139f7f9bSDimitry Andric // larger alignment.
846139f7f9bSDimitry Andric if (getTypeSizeInBits(ElemType) > 128)
847139f7f9bSDimitry Andric Alignment = 16; // 16-byte alignment.
848139f7f9bSDimitry Andric }
849139f7f9bSDimitry Andric }
850139f7f9bSDimitry Andric return Alignment;
851139f7f9bSDimitry Andric }
852139f7f9bSDimitry Andric
853139f7f9bSDimitry Andric /// getPreferredAlignmentLog - Return the preferred alignment of the
854139f7f9bSDimitry Andric /// specified global, returned in log form. This includes an explicitly
855139f7f9bSDimitry Andric /// requested alignment (if the global has one).
getPreferredAlignmentLog(const GlobalVariable * GV) const856139f7f9bSDimitry Andric unsigned DataLayout::getPreferredAlignmentLog(const GlobalVariable *GV) const {
857139f7f9bSDimitry Andric return Log2_32(getPreferredAlignment(GV));
858139f7f9bSDimitry Andric }
859