[MC] Fold A-B when A is a pending label or A/B are separated by a MCFillFragment
authorFangrui Song <i@maskray.me>
Mon, 19 Jun 2023 00:18:38 +0000 (17:18 -0700)
committerFangrui Song <i@maskray.me>
Mon, 19 Jun 2023 00:18:38 +0000 (17:18 -0700)
When the MCAssembler is non-null and the MCAsmLayout is null, we can fold A-B
in these additional cases:

* when A is a pending label (will be reassigned to a real fragment in flushPendingLabels())
* A and B are separated by a MCFillFragment with a constant size

llvm/lib/MC/MCExpr.cpp
llvm/test/MC/ARM/directive-if-subtraction.s
llvm/test/MC/AsmParser/assembler-expressions.s
llvm/test/MC/RISCV/cfi-advance.s

index 3d47a52d8a3b1c00659606be1af479ea2bb705a8..d5b5aa8fba4e03542bb939c74e90d973bb3b4759 100644 (file)
@@ -658,15 +658,30 @@ static void AttemptToFoldSymbolOffsetDifference(
     // Try to find a constant displacement from FA to FB, add the displacement
     // between the offset in FA of SA and the offset in FB of SB.
     int64_t Displacement = SA.getOffset() - SB.getOffset();
+    bool Found = false;
     for (auto FI = FB->getIterator(), FE = SecA.end(); FI != FE; ++FI) {
+      auto DF = dyn_cast<MCDataFragment>(FI);
       if (&*FI == FA) {
-        Addend += Displacement;
-        return FinalizeFolding();
+        Found = true;
+        break;
       }
 
-      if (FI->getKind() != MCFragment::FT_Data)
+      int64_t Num;
+      if (DF) {
+        Displacement += DF->getContents().size();
+      } else if (auto *FF = dyn_cast<MCFillFragment>(FI);
+                 FF && FF->getNumValues().evaluateAsAbsolute(Num)) {
+        Displacement += Num * FF->getValueSize();
+      } else {
         return;
-      Displacement += cast<MCDataFragment>(FI)->getContents().size();
+      }
+    }
+    // If FA is found or if FA is a dummy fragment not in the fragment list,
+    // (which means SA is a pending label (see flushPendingLabels)), we can
+    // resolve the difference.
+    if (Found || isa<MCDummyFragment>(FA)) {
+      Addend += Displacement;
+      FinalizeFolding();
     }
   }
 }
index edb386593ba637ed55675c94f80ae29136f286ed..e67fe0ba572c9c2bf06eacf68d38fd50715386e2 100644 (file)
@@ -1,5 +1,5 @@
 // RUN: llvm-mc -triple armv7a-linux-gnueabihf %s -filetype=obj -o /dev/null 2>&1 | FileCheck --check-prefix=OBJ --allow-empty %s
-// RUN: not llvm-mc -triple armv7a-linux-gnueabihf %s -o /dev/null 2>&1 | FileCheck --check-prefix=ASM %s
+// RUN: not llvm-mc -triple armv7a-linux-gnueabihf %s -o /dev/null 2>&1 | FileCheck --check-prefix=ASM %s --implicit-check-not=error:
 // RUN: llvm-mc -triple armv7a-linux-gnueabihf %s -filetype=obj -o - | llvm-objdump -d - | FileCheck --check-prefix=DISASM %s
 
 nop
@@ -32,7 +32,6 @@ orr r1, r1, #2
       .space 4
       nop
 .if . - 9997b == 4
-// ARM-ERR:[[@LINE-1]]:5: error: expected absolute expression
 .endif
 
 9997:
index 4e3c507c9a4752c497ae424b947611fe3630b7d6..eb967adcabfcde6fa449e86bdfc4c378b17add77 100644 (file)
@@ -4,7 +4,7 @@
 .data
 
 # OBJDATA: Contents of section .data
-# OBJDATA-NEXT: 0000 aa01aa05 06ff
+# OBJDATA-NEXT: 0000 aa01aa05 06000000 08ff
 
 foo1:
 # ASM-ERR: :[[#@LINE+1]]:5: error: expected absolute expression
@@ -32,6 +32,16 @@ foo3:
    .byte 7
 .endif
 
+foo4:
+.byte 0
+.space 2
+# ASM-ERR: :[[#@LINE+1]]:5: error: expected absolute expression
+.if . - foo4 == 3
+    .byte 8
+.else
+    .byte 9
+.endif
+
 .byte 0xff
 
 # nop is a fixed size instruction so this should pass.
index b599b50692dbc21f94ca8edb3ec08809cd9fd66d..5520c7ad330df060f507c4bc5c4aadfe9f96a445 100644 (file)
@@ -3,11 +3,11 @@
 # RUN: llvm-dwarfdump --debug-frame %t.o 2>&1 \
 # RUN:     | FileCheck -check-prefix=CHECK-DWARFDUMP %s
 
-# CHECK: 0x26 R_RISCV_SET8 - 0x0
-# CHECK-NEXT: 0x26 R_RISCV_SUB8 - 0x0
-# CHECK-NEXT: 0x2A R_RISCV_SET16 - 0x0
-# CHECK-NEXT: 0x2A R_RISCV_SUB16 - 0x0
-# CHECK-NEXT: 0x2F R_RISCV_SET32 - 0x0
+# CHECK:      .rela.eh_frame {
+# CHECK-NEXT:   0x1C R_RISCV_32_PCREL - 0x0
+# CHECK-NEXT:   0x20 R_RISCV_ADD32 - 0x0
+# CHECK-NEXT:   0x20 R_RISCV_SUB32 - 0x0
+# CHECK-NEXT: }
 # CHECK-DWARFDUMP: DW_CFA_advance_loc1
 # CHECK-DWARFDUMP-NEXT: DW_CFA_def_cfa_offset
 # CHECK-DWARFDUMP-NEXT: DW_CFA_advance_loc2