diff --git a/llvm/include/llvm/MC/MCSymbol.h b/llvm/include/llvm/MC/MCSymbol.h --- a/llvm/include/llvm/MC/MCSymbol.h +++ b/llvm/include/llvm/MC/MCSymbol.h @@ -113,11 +113,16 @@ /// extension and achieve better bitpacking with MSVC. unsigned SymbolContents : 3; - /// The alignment of the symbol, if it is 'common', or -1. + /// The alignment of the symbol if it is 'common'. /// - /// The alignment is stored as log2(align) + 1. This allows all values from - /// 0 to 2^31 to be stored which is every power of 2 representable by an - /// unsigned. + /// Internally, this is stored as log2(align) + 1. + /// We reserve 5 bits to encode this value which allows the following values + /// 0b00000 -> unset + /// 0b00001 -> 1ULL << 0 = 1 + /// 0b00010 -> 1ULL << 1 = 2 + /// 0b00011 -> 1ULL << 2 = 4 + /// ... + /// 0b11111 -> 1ULL << 30 = 1 GiB enum : unsigned { NumCommonAlignmentBits = 5 }; unsigned CommonAlignLog2 : NumCommonAlignmentBits; @@ -354,9 +359,9 @@ } /// Return the alignment of a 'common' symbol. - unsigned getCommonAlignment() const { + MaybeAlign getCommonAlignment() const { assert(isCommon() && "Not a 'common' symbol!"); - return CommonAlignLog2 ? (1U << (CommonAlignLog2 - 1)) : 0; + return decodeMaybeAlign(CommonAlignLog2); } /// Declare this symbol as being 'common'. @@ -368,7 +373,7 @@ bool declareCommon(uint64_t Size, unsigned Alignment, bool Target = false) { assert(isCommon() || getOffset() == 0); if(isCommon()) { - if (CommonSize != Size || getCommonAlignment() != Alignment || + if (CommonSize != Size || getCommonAlignment() != Align(Alignment) || isTargetCommon() != Target) return true; } else diff --git a/llvm/include/llvm/MC/MCSymbolMachO.h b/llvm/include/llvm/MC/MCSymbolMachO.h --- a/llvm/include/llvm/MC/MCSymbolMachO.h +++ b/llvm/include/llvm/MC/MCSymbolMachO.h @@ -115,12 +115,13 @@ // Common alignment is packed into the 'desc' bits. if (isCommon()) { - if (unsigned Align = getCommonAlignment()) { - unsigned Log2Size = Log2_32(Align); - assert((1U << Log2Size) == Align && "Invalid 'common' alignment!"); + if (MaybeAlign MaybeAlignment = getCommonAlignment()) { + Align Alignment = *MaybeAlignment; + unsigned Log2Size = Log2(Alignment); if (Log2Size > 15) report_fatal_error("invalid 'common' alignment '" + - Twine(Align) + "' for '" + getName() + "'", + Twine(Alignment.value()) + "' for '" + + getName() + "'", false); Flags = (Flags & SF_CommonAlignmentMask) | (Log2Size << SF_CommonAlignmentShift); diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -454,7 +454,7 @@ uint64_t ELFWriter::SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout) { if (Sym.isCommon()) - return Sym.getCommonAlignment(); + return Sym.getCommonAlignment()->value(); uint64_t Res; if (!Layout.getSymbolOffset(Sym, Res))