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

Reply via email to