123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606 |
- //===-- TargetData.cpp - Data size & alignment routines --------------------==//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file defines target 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/Target/TargetData.h"
- #include "llvm/Module.h"
- #include "llvm/DerivedTypes.h"
- #include "llvm/Constants.h"
- #include "llvm/Support/GetElementPtrTypeIterator.h"
- #include "llvm/Support/MathExtras.h"
- #include "llvm/Support/ManagedStatic.h"
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/ADT/StringExtras.h"
- #include <algorithm>
- #include <cstdlib>
- using namespace llvm;
- // Handle the Pass registration stuff necessary to use TargetData's.
- // Register the default SparcV9 implementation...
- static RegisterPass<TargetData> X("targetdata", "Target Data Layout", false,
- true);
- char TargetData::ID = 0;
- //===----------------------------------------------------------------------===//
- // Support for StructLayout
- //===----------------------------------------------------------------------===//
- StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
- StructAlignment = 0;
- StructSize = 0;
- NumElements = ST->getNumElements();
- // Loop over each of the elements, placing them in memory...
- for (unsigned i = 0, e = NumElements; i != e; ++i) {
- const Type *Ty = ST->getElementType(i);
- unsigned TyAlign = ST->isPacked() ? 1 : TD.getABITypeAlignment(Ty);
- // Add padding if necessary to align the data element properly...
- StructSize = (StructSize + TyAlign - 1)/TyAlign * TyAlign;
- // Keep track of maximum alignment constraint
- StructAlignment = std::max(TyAlign, StructAlignment);
- MemberOffsets[i] = StructSize;
- StructSize += TD.getABITypeSize(Ty); // Consume space for this data item
- }
- // Empty structures have alignment of 1 byte.
- if (StructAlignment == 0) StructAlignment = 1;
- // 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 % StructAlignment != 0)
- StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
- }
- /// getElementContainingOffset - Given a valid offset into the structure,
- /// return the structure index that contains it.
- 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!");
-
- // 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[0];
- }
- //===----------------------------------------------------------------------===//
- // TargetAlignElem, TargetAlign support
- //===----------------------------------------------------------------------===//
- TargetAlignElem
- TargetAlignElem::get(AlignTypeEnum align_type, unsigned char abi_align,
- unsigned char pref_align, uint32_t bit_width) {
- assert(abi_align <= pref_align && "Preferred alignment worse than ABI!");
- TargetAlignElem retval;
- retval.AlignType = align_type;
- retval.ABIAlign = abi_align;
- retval.PrefAlign = pref_align;
- retval.TypeBitWidth = bit_width;
- return retval;
- }
- bool
- TargetAlignElem::operator==(const TargetAlignElem &rhs) const {
- return (AlignType == rhs.AlignType
- && ABIAlign == rhs.ABIAlign
- && PrefAlign == rhs.PrefAlign
- && TypeBitWidth == rhs.TypeBitWidth);
- }
- std::ostream &
- TargetAlignElem::dump(std::ostream &os) const {
- return os << AlignType
- << TypeBitWidth
- << ":" << (int) (ABIAlign * 8)
- << ":" << (int) (PrefAlign * 8);
- }
- const TargetAlignElem TargetData::InvalidAlignmentElem =
- TargetAlignElem::get((AlignTypeEnum) -1, 0, 0, 0);
- //===----------------------------------------------------------------------===//
- // TargetData Class Implementation
- //===----------------------------------------------------------------------===//
- /*!
- A TargetDescription string consists of a sequence of hyphen-delimited
- specifiers for target endianness, pointer size and alignments, and various
- primitive type sizes and alignments. A typical string looks something like:
- <br><br>
- "E-p:32:32:32-i1:8:8-i8:8:8-i32:32:32-i64:32:64-f32:32:32-f64:32:64"
- <br><br>
- (note: this string is not fully specified and is only an example.)
- \p
- Alignments come in two flavors: ABI and preferred. ABI alignment (abi_align,
- below) dictates how a type will be aligned within an aggregate and when used
- as an argument. Preferred alignment (pref_align, below) determines a type's
- alignment when emitted as a global.
- \p
- Specifier string details:
- <br><br>
- <i>[E|e]</i>: Endianness. "E" specifies a big-endian target data model, "e"
- specifies a little-endian target data model.
- <br><br>
- <i>p:@verbatim<size>:<abi_align>:<pref_align>@endverbatim</i>: Pointer size,
- ABI and preferred alignment.
- <br><br>
- <i>@verbatim<type><size>:<abi_align>:<pref_align>@endverbatim</i>: Numeric type
- alignment. Type is
- one of <i>i|f|v|a</i>, corresponding to integer, floating point, vector (aka
- packed) or aggregate. Size indicates the size, e.g., 32 or 64 bits.
- \p
- The default string, fully specified is:
- <br><br>
- "E-p:64:64:64-a0:0:0-f32:32:32-f64:0:64"
- "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:0:64"
- "-v64:64:64-v128:128:128"
- <br><br>
- Note that in the case of aggregates, 0 is the default ABI and preferred
- alignment. This is a special case, where the aggregate's computed worst-case
- alignment will be used.
- */
- void TargetData::init(const std::string &TargetDescription) {
- std::string temp = TargetDescription;
-
- LittleEndian = false;
- PointerMemSize = 8;
- PointerABIAlign = 8;
- PointerPrefAlign = PointerABIAlign;
- // Default alignments
- setAlignment(INTEGER_ALIGN, 1, 1, 1); // Bool
- setAlignment(INTEGER_ALIGN, 1, 1, 8); // Byte
- setAlignment(INTEGER_ALIGN, 2, 2, 16); // short
- setAlignment(INTEGER_ALIGN, 4, 4, 32); // int
- setAlignment(INTEGER_ALIGN, 4, 8, 64); // long
- setAlignment(FLOAT_ALIGN, 4, 4, 32); // float
- setAlignment(FLOAT_ALIGN, 8, 8, 64); // double
- setAlignment(VECTOR_ALIGN, 8, 8, 64); // v2i32
- setAlignment(VECTOR_ALIGN, 16, 16, 128); // v16i8, v8i16, v4i32, ...
- setAlignment(AGGREGATE_ALIGN, 0, 8, 0); // struct, union, class, ...
- while (!temp.empty()) {
- std::string token = getToken(temp, "-");
- std::string arg0 = getToken(token, ":");
- const char *p = arg0.c_str();
- switch(*p) {
- case 'E':
- LittleEndian = false;
- break;
- case 'e':
- LittleEndian = true;
- break;
- case 'p':
- PointerMemSize = atoi(getToken(token,":").c_str()) / 8;
- PointerABIAlign = atoi(getToken(token,":").c_str()) / 8;
- PointerPrefAlign = atoi(getToken(token,":").c_str()) / 8;
- if (PointerPrefAlign == 0)
- PointerPrefAlign = PointerABIAlign;
- break;
- case 'i':
- case 'v':
- case 'f':
- case 'a':
- case 's': {
- AlignTypeEnum align_type = STACK_ALIGN; // Dummy init, silence warning
- switch(*p) {
- case 'i': align_type = INTEGER_ALIGN; break;
- case 'v': align_type = VECTOR_ALIGN; break;
- case 'f': align_type = FLOAT_ALIGN; break;
- case 'a': align_type = AGGREGATE_ALIGN; break;
- case 's': align_type = STACK_ALIGN; break;
- }
- uint32_t size = (uint32_t) atoi(++p);
- unsigned char abi_align = atoi(getToken(token, ":").c_str()) / 8;
- unsigned char pref_align = atoi(getToken(token, ":").c_str()) / 8;
- if (pref_align == 0)
- pref_align = abi_align;
- setAlignment(align_type, abi_align, pref_align, size);
- break;
- }
- default:
- break;
- }
- }
- }
- TargetData::TargetData(const Module *M)
- : ImmutablePass(&ID) {
- init(M->getDataLayout());
- }
- void
- TargetData::setAlignment(AlignTypeEnum align_type, unsigned char abi_align,
- unsigned char pref_align, uint32_t bit_width) {
- assert(abi_align <= pref_align && "Preferred alignment worse than ABI!");
- for (unsigned i = 0, e = Alignments.size(); i != e; ++i) {
- if (Alignments[i].AlignType == align_type &&
- Alignments[i].TypeBitWidth == bit_width) {
- // Update the abi, preferred alignments.
- Alignments[i].ABIAlign = abi_align;
- Alignments[i].PrefAlign = pref_align;
- return;
- }
- }
-
- Alignments.push_back(TargetAlignElem::get(align_type, abi_align,
- pref_align, bit_width));
- }
- /// getAlignmentInfo - Return the alignment (either ABI if ABIInfo = true or
- /// preferred if ABIInfo = false) the target wants for the specified datatype.
- unsigned TargetData::getAlignmentInfo(AlignTypeEnum AlignType,
- uint32_t BitWidth, bool ABIInfo,
- const Type *Ty) const {
- // Check to see if we have an exact match and remember the best match we see.
- int BestMatchIdx = -1;
- int LargestInt = -1;
- for (unsigned i = 0, e = Alignments.size(); i != e; ++i) {
- if (Alignments[i].AlignType == AlignType &&
- Alignments[i].TypeBitWidth == BitWidth)
- return ABIInfo ? Alignments[i].ABIAlign : Alignments[i].PrefAlign;
-
- // The best match so far depends on what we're looking for.
- if (AlignType == VECTOR_ALIGN && Alignments[i].AlignType == VECTOR_ALIGN) {
- // If this is a specification for a smaller vector type, we will fall back
- // to it. This happens because <128 x double> can be implemented in terms
- // of 64 <2 x double>.
- if (Alignments[i].TypeBitWidth < BitWidth) {
- // Verify that we pick the biggest of the fallbacks.
- if (BestMatchIdx == -1 ||
- Alignments[BestMatchIdx].TypeBitWidth < Alignments[i].TypeBitWidth)
- BestMatchIdx = i;
- }
- } else if (AlignType == INTEGER_ALIGN &&
- Alignments[i].AlignType == INTEGER_ALIGN) {
- // The "best match" for integers is the smallest size that is larger than
- // the BitWidth requested.
- if (Alignments[i].TypeBitWidth > BitWidth && (BestMatchIdx == -1 ||
- Alignments[i].TypeBitWidth < Alignments[BestMatchIdx].TypeBitWidth))
- BestMatchIdx = i;
- // However, if there isn't one that's larger, then we must use the
- // largest one we have (see below)
- if (LargestInt == -1 ||
- Alignments[i].TypeBitWidth > Alignments[LargestInt].TypeBitWidth)
- LargestInt = i;
- }
- }
- // Okay, we didn't find an exact solution. Fall back here depending on what
- // is being looked for.
- if (BestMatchIdx == -1) {
- // If we didn't find an integer alignment, fall back on most conservative.
- if (AlignType == INTEGER_ALIGN) {
- BestMatchIdx = LargestInt;
- } else {
- assert(AlignType == VECTOR_ALIGN && "Unknown alignment type!");
-
- // If we didn't find a vector size that is smaller or equal to this type,
- // then we will end up scalarizing this to its element type. Just return
- // the alignment of the element.
- return getAlignment(cast<VectorType>(Ty)->getElementType(), ABIInfo);
- }
- }
-
- // Since we got a "best match" index, just return it.
- return ABIInfo ? Alignments[BestMatchIdx].ABIAlign
- : Alignments[BestMatchIdx].PrefAlign;
- }
- namespace {
- /// LayoutInfo - The lazy cache of structure layout information maintained by
- /// TargetData. Note that the struct types must have been free'd before
- /// llvm_shutdown is called (and thus this is deallocated) because all the
- /// targets with cached elements should have been destroyed.
- ///
- typedef std::pair<const TargetData*,const StructType*> LayoutKey;
- struct DenseMapLayoutKeyInfo {
- static inline LayoutKey getEmptyKey() { return LayoutKey(0, 0); }
- static inline LayoutKey getTombstoneKey() {
- return LayoutKey((TargetData*)(intptr_t)-1, 0);
- }
- static unsigned getHashValue(const LayoutKey &Val) {
- return DenseMapInfo<void*>::getHashValue(Val.first) ^
- DenseMapInfo<void*>::getHashValue(Val.second);
- }
- static bool isEqual(const LayoutKey &LHS, const LayoutKey &RHS) {
- return LHS == RHS;
- }
- static bool isPod() { return true; }
- };
- typedef DenseMap<LayoutKey, StructLayout*, DenseMapLayoutKeyInfo> LayoutInfoTy;
- }
- static ManagedStatic<LayoutInfoTy> LayoutInfo;
- TargetData::~TargetData() {
- if (LayoutInfo.isConstructed()) {
- // Remove any layouts for this TD.
- LayoutInfoTy &TheMap = *LayoutInfo;
- for (LayoutInfoTy::iterator I = TheMap.begin(), E = TheMap.end();
- I != E; ) {
- if (I->first.first == this) {
- I->second->~StructLayout();
- free(I->second);
- TheMap.erase(I++);
- } else {
- ++I;
- }
- }
- }
- }
- const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
- LayoutInfoTy &TheMap = *LayoutInfo;
-
- StructLayout *&SL = TheMap[LayoutKey(this, Ty)];
- if (SL) return SL;
- // Otherwise, create the struct layout. Because it is variable length, we
- // malloc it, then use placement new.
- int NumElts = Ty->getNumElements();
- StructLayout *L =
- (StructLayout *)malloc(sizeof(StructLayout)+(NumElts-1)*sizeof(uint64_t));
-
- // 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;
- }
- /// InvalidateStructLayoutInfo - TargetData speculatively caches StructLayout
- /// objects. If a TargetData object is alive when types are being refined and
- /// removed, this method must be called whenever a StructType is removed to
- /// avoid a dangling pointer in this cache.
- void TargetData::InvalidateStructLayoutInfo(const StructType *Ty) const {
- if (!LayoutInfo.isConstructed()) return; // No cache.
-
- LayoutInfoTy::iterator I = LayoutInfo->find(LayoutKey(this, Ty));
- if (I != LayoutInfo->end()) {
- I->second->~StructLayout();
- free(I->second);
- LayoutInfo->erase(I);
- }
- }
- std::string TargetData::getStringRepresentation() const {
- std::string repr;
- repr.append(LittleEndian ? "e" : "E");
- repr.append("-p:").append(itostr((int64_t) (PointerMemSize * 8))).
- append(":").append(itostr((int64_t) (PointerABIAlign * 8))).
- append(":").append(itostr((int64_t) (PointerPrefAlign * 8)));
- for (align_const_iterator I = Alignments.begin();
- I != Alignments.end();
- ++I) {
- repr.append("-").append(1, (char) I->AlignType).
- append(utostr((int64_t) I->TypeBitWidth)).
- append(":").append(utostr((uint64_t) (I->ABIAlign * 8))).
- append(":").append(utostr((uint64_t) (I->PrefAlign * 8)));
- }
- return repr;
- }
- uint64_t TargetData::getTypeSizeInBits(const Type *Ty) const {
- assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
- switch (Ty->getTypeID()) {
- case Type::LabelTyID:
- case Type::PointerTyID:
- return getPointerSizeInBits();
- case Type::ArrayTyID: {
- const ArrayType *ATy = cast<ArrayType>(Ty);
- return getABITypeSizeInBits(ATy->getElementType())*ATy->getNumElements();
- }
- case Type::StructTyID: {
- // Get the layout annotation... which is lazily created on demand.
- const StructLayout *Layout = getStructLayout(cast<StructType>(Ty));
- return Layout->getSizeInBits();
- }
- case Type::IntegerTyID:
- return cast<IntegerType>(Ty)->getBitWidth();
- case Type::VoidTyID:
- return 8;
- case Type::FloatTyID:
- return 32;
- case Type::DoubleTyID:
- return 64;
- case Type::PPC_FP128TyID:
- case Type::FP128TyID:
- return 128;
- // In memory objects this is always aligned to a higher boundary, but
- // only 80 bits contain information.
- case Type::X86_FP80TyID:
- return 80;
- case Type::VectorTyID: {
- const VectorType *PTy = cast<VectorType>(Ty);
- return PTy->getBitWidth();
- }
- default:
- assert(0 && "TargetData::getTypeSizeInBits(): Unsupported type");
- break;
- }
- return 0;
- }
- /*!
- \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 char TargetData::getAlignment(const Type *Ty, bool abi_or_pref) const {
- int AlignType = -1;
- assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
- switch (Ty->getTypeID()) {
- /* Early escape for the non-numeric types */
- case Type::LabelTyID:
- case Type::PointerTyID:
- return (abi_or_pref
- ? getPointerABIAlignment()
- : getPointerPrefAlignment());
- 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 1;
-
- // Get the layout annotation... which is lazily created on demand.
- const StructLayout *Layout = getStructLayout(cast<StructType>(Ty));
- unsigned Align = getAlignmentInfo(AGGREGATE_ALIGN, 0, abi_or_pref, Ty);
- return std::max(Align, (unsigned)Layout->getAlignment());
- }
- case Type::IntegerTyID:
- case Type::VoidTyID:
- AlignType = INTEGER_ALIGN;
- break;
- 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:
- AlignType = FLOAT_ALIGN;
- break;
- case Type::VectorTyID:
- AlignType = VECTOR_ALIGN;
- break;
- default:
- assert(0 && "Bad type for getAlignment!!!");
- break;
- }
- return getAlignmentInfo((AlignTypeEnum)AlignType, getTypeSizeInBits(Ty),
- abi_or_pref, Ty);
- }
- unsigned char TargetData::getABITypeAlignment(const Type *Ty) const {
- return getAlignment(Ty, true);
- }
- unsigned char TargetData::getCallFrameTypeAlignment(const 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 char TargetData::getPrefTypeAlignment(const Type *Ty) const {
- return getAlignment(Ty, false);
- }
- unsigned char TargetData::getPreferredTypeAlignmentShift(const Type *Ty) const {
- unsigned Align = (unsigned) getPrefTypeAlignment(Ty);
- assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
- return Log2_32(Align);
- }
- /// getIntPtrType - Return an unsigned integer type that is the same size or
- /// greater to the host pointer size.
- const Type *TargetData::getIntPtrType() const {
- return IntegerType::get(getPointerSizeInBits());
- }
- uint64_t TargetData::getIndexedOffset(const Type *ptrTy, Value* const* Indices,
- unsigned NumIndices) const {
- const Type *Ty = ptrTy;
- assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
- uint64_t Result = 0;
- generic_gep_type_iterator<Value* const*>
- TI = gep_type_begin(ptrTy, Indices, Indices+NumIndices);
- for (unsigned CurIDX = 0; CurIDX != NumIndices; ++CurIDX, ++TI) {
- if (const StructType *STy = dyn_cast<StructType>(*TI)) {
- assert(Indices[CurIDX]->getType() == Type::Int32Ty &&
- "Illegal struct idx");
- unsigned FieldNo = cast<ConstantInt>(Indices[CurIDX])->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);
- // Update Ty to refer to current element
- Ty = STy->getElementType(FieldNo);
- } else {
- // Update Ty to refer to current element
- Ty = cast<SequentialType>(Ty)->getElementType();
- // Get the array index and the size of each array element.
- int64_t arrayIdx = cast<ConstantInt>(Indices[CurIDX])->getSExtValue();
- Result += arrayIdx * (int64_t)getABITypeSize(Ty);
- }
- }
- return Result;
- }
- /// getPreferredAlignment - Return the preferred alignment of the specified
- /// global. This includes an explicitly requested alignment (if the global
- /// has one).
- unsigned TargetData::getPreferredAlignment(const GlobalVariable *GV) const {
- const Type *ElemType = GV->getType()->getElementType();
- unsigned Alignment = getPrefTypeAlignment(ElemType);
- if (GV->getAlignment() > Alignment)
- Alignment = GV->getAlignment();
- if (GV->hasInitializer()) {
- if (Alignment < 16) {
- // If the global is not external, see if it is large. If so, give it a
- // larger alignment.
- if (getTypeSizeInBits(ElemType) > 128)
- Alignment = 16; // 16-byte alignment.
- }
- }
- return Alignment;
- }
- /// getPreferredAlignmentLog - Return the preferred alignment of the
- /// specified global, returned in log form. This includes an explicitly
- /// requested alignment (if the global has one).
- unsigned TargetData::getPreferredAlignmentLog(const GlobalVariable *GV) const {
- return Log2_32(getPreferredAlignment(GV));
- }
|