llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-mc Author: Peter Collingbourne (pcc) <details> <summary>Changes</summary> The new ``SHT_LLVM_MIN_ADDRALIGN`` section is used to specify the minimum alignment of a section where that differs from its preferred alignment. Its ``sh_link`` field identifies the section whose alignment is being specified, its ``sh_addralign`` field specifies the linked section's minimum alignment and the ``sh_addralign`` field of the linked section's section header specifies its preferred alignment. This section has the ``SHF_EXCLUDE`` flag so that it is stripped from the final executable or shared library, and the ``SHF_LINK_ORDER`` flag so that the ``sh_link`` field is updated by tools such as ``ld -r`` and ``objcopy``. The contents of the section must be empty. The new asm directive: .prefalign n specifies that the preferred alignment of the current section is determined by taking the maximum of ``n`` and the section's minimum alignment, and causes an ``SHT_LLVM_MIN_ADDRALIGN`` section to be emitted if necessary. --- Full diff: https://github.com/llvm/llvm-project/pull/150151.diff 13 Files Affected: - (modified) llvm/docs/Extensions.rst (+22) - (modified) llvm/include/llvm/BinaryFormat/ELF.h (+1) - (modified) llvm/include/llvm/MC/MCObjectStreamer.h (+1) - (modified) llvm/include/llvm/MC/MCSection.h (+12) - (modified) llvm/include/llvm/MC/MCStreamer.h (+2) - (modified) llvm/lib/MC/ELFObjectWriter.cpp (+13-4) - (modified) llvm/lib/MC/MCAsmStreamer.cpp (+6) - (modified) llvm/lib/MC/MCObjectStreamer.cpp (+4) - (modified) llvm/lib/MC/MCParser/AsmParser.cpp (+20) - (modified) llvm/lib/MC/MCStreamer.cpp (+1) - (modified) llvm/lib/Object/ELF.cpp (+1) - (added) llvm/test/MC/ELF/prefalign-errors.s (+5) - (added) llvm/test/MC/ELF/prefalign.s (+47) ``````````diff diff --git a/llvm/docs/Extensions.rst b/llvm/docs/Extensions.rst index d8fb87b6998ad..e6b2db0745623 100644 --- a/llvm/docs/Extensions.rst +++ b/llvm/docs/Extensions.rst @@ -601,6 +601,28 @@ sees fit (generally the section that would provide the best locality). .. _CFI jump table: https://clang.llvm.org/docs/ControlFlowIntegrityDesign.html#forward-edge-cfi-for-indirect-function-calls +``SHT_LLVM_MIN_ADDRALIGN`` Section (minimum section alignment) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +This section is used to specify the minimum alignment of a section +where that differs from its preferred alignment. Its ``sh_link`` +field identifies the section whose alignment is being specified, its +``sh_addralign`` field specifies the linked section's minimum alignment +and the ``sh_addralign`` field of the linked section's section header +specifies its preferred alignment. This section has the ``SHF_EXCLUDE`` +flag so that it is stripped from the final executable or shared library, +and the ``SHF_LINK_ORDER`` flag so that the ``sh_link`` field is updated +by tools such as ``ld -r`` and ``objcopy``. The contents of the section +must be empty. + +.. code-block:: gas + + .prefalign n + +Specifies that the preferred alignment of the current section is +determined by taking the maximum of ``n`` and the section's minimum +alignment, and causes an ``SHT_LLVM_MIN_ADDRALIGN`` section to be emitted +if necessary. + CodeView-Dependent ------------------ diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index e4f82ad96a084..95600f39153d4 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1160,6 +1160,7 @@ enum : unsigned { SHT_LLVM_LTO = 0x6fff4c0c, // .llvm.lto for fat LTO. SHT_LLVM_JT_SIZES = 0x6fff4c0d, // LLVM jump tables sizes. SHT_LLVM_CFI_JUMP_TABLE = 0x6fff4c0e, // LLVM CFI jump table. + SHT_LLVM_MIN_ADDRALIGN = 0x6fff4c0f, // Minimum alignment specification. // Android's experimental support for SHT_RELR sections. // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512 SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets. diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index 319e131999d48..27de57f2ccd91 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -113,6 +113,7 @@ class MCObjectStreamer : public MCStreamer { unsigned MaxBytesToEmit = 0) override; void emitCodeAlignment(Align ByteAlignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit = 0) override; + void emitPrefAlign(Align Alignment) override; void emitValueToOffset(const MCExpr *Offset, unsigned char Value, SMLoc Loc) override; void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 313071ec75033..61ae6dff4d146 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -82,6 +82,7 @@ class LLVM_ABI MCSection { MCSymbol *End = nullptr; /// The alignment requirement of this section. Align Alignment; + MaybeAlign PreferredAlignment; /// The section index in the assemblers section list. unsigned Ordinal = 0; @@ -147,6 +148,17 @@ class LLVM_ABI MCSection { Alignment = MinAlignment; } + Align getPreferredAlignment() const { + if (!PreferredAlignment || Alignment > *PreferredAlignment) + return Alignment; + return *PreferredAlignment; + } + + void ensurePreferredAlignment(Align PrefAlign) { + if (!PreferredAlignment || PrefAlign > *PreferredAlignment) + PreferredAlignment = PrefAlign; + } + unsigned getOrdinal() const { return Ordinal; } void setOrdinal(unsigned Value) { Ordinal = Value; } diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 4b91dbc794682..e7947657e1356 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -832,6 +832,8 @@ class LLVM_ABI MCStreamer { virtual void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit = 0); + virtual void emitPrefAlign(Align A); + /// Emit some number of copies of \p Value until the byte offset \p /// Offset is reached. /// diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 9f52b3e3e85c0..7709cf56ffd32 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -926,10 +926,10 @@ void ELFWriter::writeSectionHeader(uint32_t GroupSymbolIndex, uint64_t Offset, sh_link = Sym->getSection().getOrdinal(); } - writeSectionHeaderEntry(StrTabBuilder.getOffset(Section.getName()), - Section.getType(), Section.getFlags(), 0, Offset, - Size, sh_link, sh_info, Section.getAlign(), - Section.getEntrySize()); + writeSectionHeaderEntry( + StrTabBuilder.getOffset(Section.getName()), Section.getType(), + Section.getFlags(), 0, Offset, Size, sh_link, sh_info, + Section.getPreferredAlignment(), Section.getEntrySize()); } void ELFWriter::writeSectionHeaders() { @@ -1062,6 +1062,15 @@ uint64_t ELFWriter::writeObject() { Relocations.push_back(RelSection); } + if (Sec.getPreferredAlignment() != Sec.getAlign()) { + MCSectionELF *MinAlign = Ctx.getELFSection( + ".llvm.minalign", ELF::SHT_LLVM_MIN_ADDRALIGN, + ELF::SHF_EXCLUDE | ELF::SHF_LINK_ORDER, 0, "", false, 0, + cast<MCSymbolELF>(Section.getBeginSymbol())); + MinAlign->setOrdinal(addToSectionTable(MinAlign)); + MinAlign->setAlignment(Sec.getAlign()); + } + if (GroupIdxEntry) { auto &Members = Groups[GroupMap[*GroupIdxEntry]]; Members.second.push_back(Section.getOrdinal()); diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 67c53e01a6111..4d53607400a27 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -275,6 +275,7 @@ class MCAsmStreamer final : public MCStreamer { void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit = 0) override; + void emitPrefAlign(Align Alignment) override; void emitValueToOffset(const MCExpr *Offset, unsigned char Value, @@ -1540,6 +1541,11 @@ void MCAsmStreamer::emitCodeAlignment(Align Alignment, emitAlignmentDirective(Alignment.value(), std::nullopt, 1, MaxBytesToEmit); } +void MCAsmStreamer::emitPrefAlign(Align Alignment) { + OS << ".prefalign " << Alignment.value(); + EmitEOL(); +} + void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value, SMLoc Loc) { diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index d5b8f22463894..e860f6c61c5f7 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -567,6 +567,10 @@ void MCObjectStreamer::emitCodeAlignment(Align Alignment, } } +void MCObjectStreamer::emitPrefAlign(Align Alignment) { + getCurrentSectionOnly()->ensurePreferredAlignment(Alignment); +} + void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value, SMLoc Loc) { diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 77bf84364c5a3..2e85c08852c15 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -418,6 +418,7 @@ class AsmParser : public MCAsmParser { DK_P2ALIGN, DK_P2ALIGNW, DK_P2ALIGNL, + DK_PREFALIGN, DK_ORG, DK_FILL, DK_ENDR, @@ -565,6 +566,7 @@ class AsmParser : public MCAsmParser { bool parseDirectiveOrg(); // ".org" // ".align{,32}", ".p2align{,w,l}" bool parseDirectiveAlign(bool IsPow2, uint8_t ValueSize); + bool parseDirectivePrefAlign(); // ".file", ".line", ".loc", ".loc_label", ".stabs" bool parseDirectiveFile(SMLoc DirectiveLoc); @@ -2000,6 +2002,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2); case DK_P2ALIGNL: return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); + case DK_PREFALIGN: + return parseDirectivePrefAlign(); case DK_ORG: return parseDirectiveOrg(); case DK_FILL: @@ -3426,6 +3430,21 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, uint8_t ValueSize) { return ReturnVal; } +bool AsmParser::parseDirectivePrefAlign() { + SMLoc AlignmentLoc = getLexer().getLoc(); + int64_t Alignment; + if (checkForValidSection() || parseAbsoluteExpression(Alignment)) + return true; + if (parseEOL()) + return true; + + if (!isPowerOf2_64(Alignment)) + return Error(AlignmentLoc, "alignment must be a power of 2"); + getStreamer().emitPrefAlign(Align(Alignment)); + + return false; +} + /// parseDirectiveFile /// ::= .file filename /// ::= .file number [directory] filename [md5 checksum] [source source-text] @@ -5377,6 +5396,7 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".p2align"] = DK_P2ALIGN; DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW; DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL; + DirectiveKindMap[".prefalign"] = DK_PREFALIGN; DirectiveKindMap[".org"] = DK_ORG; DirectiveKindMap[".fill"] = DK_FILL; DirectiveKindMap[".zero"] = DK_ZERO; diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index c3ecf8fc717f5..eeca414da580d 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -1329,6 +1329,7 @@ void MCStreamer::emitFill(const MCExpr &NumBytes, uint64_t Value, SMLoc Loc) {} void MCStreamer::emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, SMLoc Loc) {} void MCStreamer::emitValueToAlignment(Align, int64_t, uint8_t, unsigned) {} +void MCStreamer::emitPrefAlign(Align A) {} void MCStreamer::emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit) {} void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value, diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp index 788c6020a7f99..ab23a0b1f25b9 100644 --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -322,6 +322,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_LTO); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_JT_SIZES) STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_CFI_JUMP_TABLE) + STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_MIN_ADDRALIGN) STRINGIFY_ENUM_CASE(ELF, SHT_GNU_SFRAME); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH); diff --git a/llvm/test/MC/ELF/prefalign-errors.s b/llvm/test/MC/ELF/prefalign-errors.s new file mode 100644 index 0000000000000..363638f9bcb1e --- /dev/null +++ b/llvm/test/MC/ELF/prefalign-errors.s @@ -0,0 +1,5 @@ +// RUN: not llvm-mc -filetype=asm -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s + +.section .text.f1,"ax",@progbits +// CHECK: error: alignment must be a power of 2 +.prefalign 3 diff --git a/llvm/test/MC/ELF/prefalign.s b/llvm/test/MC/ELF/prefalign.s new file mode 100644 index 0000000000000..f3537029b23c1 --- /dev/null +++ b/llvm/test/MC/ELF/prefalign.s @@ -0,0 +1,47 @@ +// RUN: llvm-mc -filetype=asm -triple x86_64-pc-linux-gnu %s -o - | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readelf -SW - | FileCheck --check-prefix=OBJ %s + +// Minimum alignment = preferred alignment, no SHT_LLVM_MIN_ADDRALIGN needed. +// ASM: .section .text.f1 +// ASM: .p2align 2 +// ASM: .prefalign 4 +// OBJ: .text.f1 +// OBJ-NOT: .llvm.minalign +.section .text.f1,"ax",@progbits +.p2align 2 +.prefalign 4 + +// Minimum alignment < preferred alignment, SHT_LLVM_MIN_ADDRALIGN emitted. +// ASM: .section .text.f2 +// ASM: .p2align 2 +// ASM: .prefalign 8 +// OBJ: [ 4] .text.f2 PROGBITS 0000000000000000 000040 000000 00 AX 0 0 8 +// OBJ: [ 5] .llvm.minalign LLVM_MIN_ADDRALIGN 0000000000000000 000000 000000 00 LE 4 0 4 +.section .text.f2,"ax",@progbits +.p2align 2 +.prefalign 8 + +// Minimum alignment > preferred alignment, preferred alignment rounded up to +// minimum alignment. No SHT_LLVM_MIN_ADDRALIGN emitted. +// ASM: .section .text.f3 +// ASM: .p2align 3 +// ASM: .prefalign 4 +// OBJ: .text.f3 +// OBJ-NOT: .llvm.minalign +.section .text.f3,"ax",@progbits +.p2align 3 +.prefalign 4 + +// Maximum of all .prefalign directives written to object file. +// ASM: .section .text.f4 +// ASM: .p2align 2 +// ASM: .prefalign 8 +// ASM: .prefalign 16 +// ASM: .prefalign 8 +// OBJ: [ 7] .text.f4 PROGBITS 0000000000000000 000040 000000 00 AX 0 0 16 +// OBJ: [ 8] .llvm.minalign LLVM_MIN_ADDRALIGN 0000000000000000 000000 000000 00 LE 7 0 4 +.section .text.f4,"ax",@progbits +.p2align 2 +.prefalign 8 +.prefalign 16 +.prefalign 8 `````````` </details> https://github.com/llvm/llvm-project/pull/150151 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits