[llvm] 415a4fb - [MC] Resolve the difference of symbols in consecutive MCDataFragements
Jian Cai via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 9 12:39:52 PDT 2020
Author: Jian Cai
Date: 2020-09-09T12:35:43-07:00
New Revision: 415a4fbea7c1a39c780caa3cb7287fe09c5267d2
URL: https://github.com/llvm/llvm-project/commit/415a4fbea7c1a39c780caa3cb7287fe09c5267d2
DIFF: https://github.com/llvm/llvm-project/commit/415a4fbea7c1a39c780caa3cb7287fe09c5267d2.diff
LOG: [MC] Resolve the difference of symbols in consecutive MCDataFragements
Try to resolve the difference of two symbols in consecutive MCDataFragments.
This is important for an idiom like "foo:instr; .if . - foo; instr; .endif"
(https://bugs.llvm.org/show_bug.cgi?id=43795).
Reviewed By: nickdesaulniers
Differential Revision: https://reviews.llvm.org/D69411
Added:
llvm/test/MC/ARM/directive-if-subtraction.s
Modified:
llvm/include/llvm/MC/MCFragment.h
llvm/lib/MC/MCExpr.cpp
llvm/lib/MC/MCSection.cpp
llvm/test/MC/MachO/reloc-diff.s
Removed:
################################################################################
diff --git a/llvm/include/llvm/MC/MCFragment.h b/llvm/include/llvm/MC/MCFragment.h
index 87338ab46cc2..0e5a5976cc8e 100644
--- a/llvm/include/llvm/MC/MCFragment.h
+++ b/llvm/include/llvm/MC/MCFragment.h
@@ -64,6 +64,10 @@ class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
/// The layout order of this fragment.
unsigned LayoutOrder;
+ /// The subsection this fragment belongs to. This is 0 if the fragment is not
+ // in any subsection.
+ unsigned SubsectionNumber = 0;
+
FragmentType Kind;
/// Whether fragment is being laid out.
@@ -102,6 +106,9 @@ class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
bool hasInstructions() const { return HasInstructions; }
void dump() const;
+
+ void setSubsectionNumber(unsigned Value) { SubsectionNumber = Value; }
+ unsigned getSubsectionNumber() const { return SubsectionNumber; }
};
class MCDummyFragment : public MCFragment {
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 07680e95e8e1..7f282a1ba497 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -588,12 +588,7 @@ static void AttemptToFoldSymbolOffsetDifference(
if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet))
return;
- MCFragment *FA = SA.getFragment();
- MCFragment *FB = SB.getFragment();
- if (FA == FB && !SA.isVariable() && !SA.isUnset() && !SB.isVariable() &&
- !SB.isUnset()) {
- Addend += (SA.getOffset() - SB.getOffset());
-
+ auto FinalizeFolding = [&]() {
// Pointers to Thumb symbols need to have their low-bit set to allow
// for interworking.
if (Asm->isThumbFunc(&SA))
@@ -607,11 +602,17 @@ static void AttemptToFoldSymbolOffsetDifference(
// Clear the symbol expr pointers to indicate we have folded these
// operands.
A = B = nullptr;
- return;
- }
+ };
- if (!Layout)
- return;
+ const MCFragment *FA = SA.getFragment();
+ const MCFragment *FB = SB.getFragment();
+ // If both symbols are in the same fragment, return the
diff erence of their
+ // offsets
+ if (FA == FB && !SA.isVariable() && !SA.isUnset() && !SB.isVariable() &&
+ !SB.isUnset()) {
+ Addend += SA.getOffset() - SB.getOffset();
+ return FinalizeFolding();
+ }
const MCSection &SecA = *FA->getParent();
const MCSection &SecB = *FB->getParent();
@@ -619,30 +620,46 @@ static void AttemptToFoldSymbolOffsetDifference(
if ((&SecA != &SecB) && !Addrs)
return;
- // One of the symbol involved is part of a fragment being laid out. Quit now
- // to avoid a self loop.
- if (!Layout->canGetFragmentOffset(FA) || !Layout->canGetFragmentOffset(FB))
- return;
+ if (Layout) {
+ // One of the symbol involved is part of a fragment being laid out. Quit now
+ // to avoid a self loop.
+ if (!Layout->canGetFragmentOffset(FA) || !Layout->canGetFragmentOffset(FB))
+ return;
+
+ // Eagerly evaluate when layout is finalized.
+ Addend += Layout->getSymbolOffset(A->getSymbol()) -
+ Layout->getSymbolOffset(B->getSymbol());
+ if (Addrs && (&SecA != &SecB))
+ Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB));
+
+ FinalizeFolding();
+ } else {
+ // When layout is not finalized, our ability to resolve
diff erences between
+ // symbols is limited to specific cases where the fragments between two
+ // symbols (including the fragments the symbols are defined in) are
+ // fixed-size fragments so the
diff erence can be calculated. For example,
+ // this is important when the Subtarget is changed and a new MCDataFragment
+ // is created in the case of foo: instr; .arch_extension ext; instr .if . -
+ // foo.
+ if (SA.isVariable() || SA.isUnset() || SB.isVariable() || SB.isUnset() ||
+ FA->getKind() != MCFragment::FT_Data ||
+ FB->getKind() != MCFragment::FT_Data ||
+ FA->getSubsectionNumber() != FB->getSubsectionNumber())
+ return;
+ // 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();
+ for (auto FI = FB->getIterator(), FE = SecA.end(); FI != FE; ++FI) {
+ if (&*FI == FA) {
+ Addend += Displacement;
+ return FinalizeFolding();
+ }
- // Eagerly evaluate.
- Addend += Layout->getSymbolOffset(A->getSymbol()) -
- Layout->getSymbolOffset(B->getSymbol());
- if (Addrs && (&SecA != &SecB))
- Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB));
-
- // Pointers to Thumb symbols need to have their low-bit set to allow
- // for interworking.
- if (Asm->isThumbFunc(&SA))
- Addend |= 1;
-
- // If symbol is labeled as micromips, we set low-bit to ensure
- // correct offset in .gcc_except_table
- if (Asm->getBackend().isMicroMips(&SA))
- Addend |= 1;
-
- // Clear the symbol expr pointers to indicate we have folded these
- // operands.
- A = B = nullptr;
+ if (FI->getKind() != MCFragment::FT_Data)
+ return;
+ Displacement += cast<MCDataFragment>(FI)->getContents().size();
+ }
+ }
}
static bool canFold(const MCAssembler *Asm, const MCSymbolRefExpr *A,
diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp
index ba256102080a..7c5834895e52 100644
--- a/llvm/lib/MC/MCSection.cpp
+++ b/llvm/lib/MC/MCSection.cpp
@@ -82,6 +82,7 @@ MCSection::getSubsectionInsertionPoint(unsigned Subsection) {
SubsectionFragmentMap.insert(MI, std::make_pair(Subsection, F));
getFragmentList().insert(IP, F);
F->setParent(this);
+ F->setSubsectionNumber(Subsection);
}
return IP;
diff --git a/llvm/test/MC/ARM/directive-if-subtraction.s b/llvm/test/MC/ARM/directive-if-subtraction.s
new file mode 100644
index 000000000000..edb386593ba6
--- /dev/null
+++ b/llvm/test/MC/ARM/directive-if-subtraction.s
@@ -0,0 +1,52 @@
+// 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: llvm-mc -triple armv7a-linux-gnueabihf %s -filetype=obj -o - | llvm-objdump -d - | FileCheck --check-prefix=DISASM %s
+
+nop
+// Create a new MCDataFragment due to Subtarget change
+.arch_extension sec
+9997:nop
+.if . - 9997b == 0
+// OBJ-NOT:[[@LINE-1]]:5: error: expected absolute expression
+// ASM:[[@LINE-2]]:5: error: expected absolute expression
+// DISASM: orr r1, r1, #2
+orr r1, r1, #1
+.else
+orr r1, r1, #2
+.endif
+
+
+
+@ RUN: not llvm-mc -filetype=obj -triple arm-linux-gnueabihf --defsym=ERR=1 %s -o /dev/null 2>&1 | FileCheck --check-prefix=ARM-ERR %s
+@ RUN: not llvm-mc -filetype=obj -triple thumbv7a-linux-gnueabihf --defsym=ERR=1 %s -o /dev/null 2>&1 | FileCheck --check-prefix=THUMB2-ERR %s
+
+.ifdef ERR
+9997: nop
+ .align 4
+ nop
+.if . - 9997b == 4
+// ARM-ERR:[[@LINE-1]]:5: error: expected absolute expression
+.endif
+
+9997: nop
+ .space 4
+ nop
+.if . - 9997b == 4
+// ARM-ERR:[[@LINE-1]]:5: error: expected absolute expression
+.endif
+
+9997:
+ ldr r0,=0x12345678
+ .ltorg
+ nop
+.if . - 9997b == 4
+// ARM-ERR:[[@LINE-1]]:5: error: expected absolute expression
+.endif
+
+9997: nop
+ b external
+ nop
+.if . - 9997b == 4
+// THUMB2-ERR:[[@LINE-1]]:5: error: expected absolute expression
+.endif
+.endif
diff --git a/llvm/test/MC/MachO/reloc-
diff .s b/llvm/test/MC/MachO/reloc-
diff .s
index 8b2e7606b354..ba00e7bb1c9f 100644
--- a/llvm/test/MC/MachO/reloc-
diff .s
+++ b/llvm/test/MC/MachO/reloc-
diff .s
@@ -22,9 +22,5 @@ Ltemp:
// CHECK-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 0x0
// CHECK-NEXT: 0x8 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 0x0
// CHECK-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 0x0
-// CHECK-NEXT: 0x4 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 0x0
-// CHECK-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 0x0
-// CHECK-NEXT: 0x0 0 2 n/a GENERIC_RELOC_SECTDIFF 1 0x0
-// CHECK-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]
More information about the llvm-commits
mailing list