[llvm] df71243 - MC: Evaluate .org during fragment relaxation

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 4 00:29:19 PDT 2025


Author: Fangrui Song
Date: 2025-08-04T00:29:14-07:00
New Revision: df71243fa885cd3db701dc35a0c8d157adaf93b3

URL: https://github.com/llvm/llvm-project/commit/df71243fa885cd3db701dc35a0c8d157adaf93b3
DIFF: https://github.com/llvm/llvm-project/commit/df71243fa885cd3db701dc35a0c8d157adaf93b3.diff

LOG: MC: Evaluate .org during fragment relaxation

Similar to 742ecfc13e8aa34cfff2900e31838f657fcafe30 for MCFillFragment,
ensure `.org` directives with expressions are re-evaluated during
fragment relaxation, as their sizes may change. Continue iteration to
prevent stale, incorrect sizes. While I knew MCOrgFragment likely needed
to be re-evaluated at all, I did not have a motivation to add it;-)

This fixes the root cause of
https://github.com/ClangBuiltLinux/linux/issues/2116
(writeSectionData assertion failure when building the Linux kernel for arm64)

The issue cannot be reliably replicated. The specific test case would
not replicate if any of the following condition was not satisfied:

* .org was not re-evaluated. Fixed by this commit.
* clang -cc1as has a redundant `initSections` call, leading to a
  redundant initial FT_Align fragment. llvm-mc -filetype=obj, lacking
  the redundant `initSections`, doesn't replicate.
* faa931b717c02d57f0814caa9133219040e6a85b decreased sizeof(MCFragment).
* f1aa6050bd90f8ec4273da55d362e23905ad3a81 added more fragments

Added: 
    

Modified: 
    llvm/include/llvm/MC/MCAssembler.h
    llvm/include/llvm/MC/MCSection.h
    llvm/lib/MC/MCAssembler.cpp
    llvm/test/MC/ELF/mc-dump.s

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h
index ffde5ca247d41..afd38d2e6d106 100644
--- a/llvm/include/llvm/MC/MCAssembler.h
+++ b/llvm/include/llvm/MC/MCAssembler.h
@@ -120,6 +120,7 @@ class MCAssembler {
   bool relaxCVInlineLineTable(MCCVInlineLineTableFragment &DF);
   bool relaxCVDefRange(MCCVDefRangeFragment &DF);
   bool relaxFill(MCFillFragment &F);
+  bool relaxOrg(MCOrgFragment &F);
 
 public:
   /// Construct a new assembler instance.

diff  --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h
index 493bd1167a3a4..cc191ae0a0da7 100644
--- a/llvm/include/llvm/MC/MCSection.h
+++ b/llvm/include/llvm/MC/MCSection.h
@@ -383,13 +383,16 @@ class MCOrgFragment : public MCFragment {
   /// Source location of the directive that this fragment was created for.
   SMLoc Loc;
 
+  uint64_t Size = 0;
+
 public:
   MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc)
       : MCFragment(FT_Org), Value(Value), Offset(&Offset), Loc(Loc) {}
 
   const MCExpr &getOffset() const { return *Offset; }
-
   uint8_t getValue() const { return Value; }
+  uint64_t getSize() const { return Size; }
+  void setSize(uint64_t Value) { Size = Value; }
 
   SMLoc getLoc() const { return Loc; }
 

diff  --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index 5c8e90452ec9a..d172ad170a4d5 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -945,6 +945,14 @@ bool MCAssembler::relaxFill(MCFillFragment &F) {
   return true;
 }
 
+bool MCAssembler::relaxOrg(MCOrgFragment &F) {
+  uint64_t Size = computeFragmentSize(F);
+  if (F.getSize() == Size)
+    return false;
+  F.setSize(Size);
+  return true;
+}
+
 bool MCAssembler::relaxFragment(MCFragment &F) {
   switch(F.getKind()) {
   default:
@@ -966,6 +974,8 @@ bool MCAssembler::relaxFragment(MCFragment &F) {
     return relaxCVDefRange(cast<MCCVDefRangeFragment>(F));
   case MCFragment::FT_Fill:
     return relaxFill(cast<MCFillFragment>(F));
+  case MCFragment::FT_Org:
+    return relaxOrg(static_cast<MCOrgFragment &>(F));
   }
 }
 

diff  --git a/llvm/test/MC/ELF/mc-dump.s b/llvm/test/MC/ELF/mc-dump.s
index 51b3ff4774cf3..a590e1c3d9be4 100644
--- a/llvm/test/MC/ELF/mc-dump.s
+++ b/llvm/test/MC/ELF/mc-dump.s
@@ -30,7 +30,7 @@
 # CHECK-NEXT:5 LEB Size:0+1 [15] Value:.Ltmp0-_start Signed:0
 #      CHECK:]
 
-# CHECK:  2 assembler         - Number of fixup evaluations for relaxation
+# CHECK:  3 assembler         - Number of fixup evaluations for relaxation
 # CHECK:  8 assembler         - Number of fixups
 
 # RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t -debug-only=mc-dump -save-temp-labels -g 2>&1 | FileCheck %s --check-prefix=CHECK2


        


More information about the llvm-commits mailing list