diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -524,10 +524,9 @@ if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet)) return; - if (SA.getFragment() == SB.getFragment() && !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)) @@ -541,16 +540,39 @@ // Clear the symbol expr pointers to indicate we have folded these // operands. A = B = nullptr; + }; + + const MCFragment *FragA = SA.getFragment(); + const MCFragment *FragB = SB.getFragment(); + if (FragA == FragB && !SA.isVariable() && !SA.isUnset() && !SB.isVariable() && + !SB.isUnset()) { + + Addend += (SA.getOffset() - SB.getOffset()); + + FinalizeFolding(); return; } - if (!Layout) + const MCSection &SecA = *FragA->getParent(); + const MCSection &SecB = *FragB->getParent(); + + if ((&SecA != &SecB) && !Addrs) return; - const MCSection &SecA = *SA.getFragment()->getParent(); - const MCSection &SecB = *SB.getFragment()->getParent(); + if ((&SecA != &SecB) && !Addrs) + return; - if ((&SecA != &SecB) && !Addrs) + if (SecB.getFragmentList().getNextNode(*FragB) == FragA && + isa(FragA) && isa(FragB)) { + Addend += + (SA.getOffset() + (cast(FragB))->getContents().size() - + SB.getOffset()); + + FinalizeFolding(); + return; + } + + if (!Layout) return; // Eagerly evaluate. @@ -559,19 +581,7 @@ 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; + FinalizeFolding(); } static bool canFold(const MCAssembler *Asm, const MCSymbolRefExpr *A, diff --git a/llvm/test/MC/AsmParser/directive_if_offset.s b/llvm/test/MC/AsmParser/directive_if_offset.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AsmParser/directive_if_offset.s @@ -0,0 +1,12 @@ +@ RUN: clang -target arm-linux-gnueabihf %s -c -o /dev/null 2>&1 | FileCheck --allow-empty --check-prefix=CHECK-ARM %s +@ RUN: clang -target thumb-linux-gnueabihf %s -c -o /dev/null 2>&1 | FileCheck --allow-empty --check-prefix=CHECK-THUMB %s + +nop +.arch_extension sec +9997: nop ; +.if . - 9997b == 4 ; +// CHECK-ARM-NOT: :[[@LINE-1]]:5: error: expected absolute expression +// CHECK-THUMB-NOT: :[[@LINE-2]]:5: error: expected absolute expression +orr r1, r1, #1 ; +.else ; orr r1, r1, #2; +.endif;