Skip to content

Commit 33246f7

Browse files
committed
[MC] Rework evaluateSymbolicAdd to eliminate MCValue::SymB reliance
Reworked evaluateSymbolicAdd and isSymbolRefDifferenceFullyResolved to remove their reliance on MCValue::SymB, which previously used the MCSymbolRefExpr member when folding two symbolic expressions. This dependency prevented replacing MCValue::SymB with a MCSymbol. By refactoring, we enable this replacement, which is a more significant improvement. Note that this change eliminates the rare "unsupported subtraction of qualified symbol" diagnostic, resulting in a minor loss of information. However, the benefit of enabling MCValue::SymB replacement with MCSymbol outweighs this slight regression.
1 parent 6ac5cbd commit 33246f7

File tree

10 files changed

+93
-113
lines changed

10 files changed

+93
-113
lines changed

llvm/include/llvm/MC/MCExpr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,9 @@ class MCSymbolRefExpr : public MCExpr {
259259
VariantKind getKind() const {
260260
return (VariantKind)(getSubclassData() & VariantKindMask);
261261
}
262+
uint16_t getSpecifier() const {
263+
return (getSubclassData() & VariantKindMask);
264+
}
262265

263266
bool hasSubsectionsViaSymbols() const {
264267
return (getSubclassData() & HasSubsectionsViaSymbolsBit) != 0;

llvm/include/llvm/MC/MCObjectWriter.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,7 @@ class MCObjectWriter {
8383
/// Clients are not required to answer precisely and may conservatively return
8484
/// false, even when a difference is fully resolved.
8585
bool isSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
86-
const MCSymbolRefExpr *A,
87-
const MCSymbolRefExpr *B,
86+
const MCSymbol &A, const MCSymbol &B,
8887
bool InSet) const;
8988

9089
virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,

llvm/include/llvm/MC/MCValue.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,17 @@ class raw_ostream;
3636
class MCValue {
3737
const MCSymbolRefExpr *SymA = nullptr, *SymB = nullptr;
3838
int64_t Cst = 0;
39-
uint32_t RefKind = 0;
39+
uint32_t Specifier = 0;
4040

4141
public:
42+
friend class MCExpr;
4243
MCValue() = default;
4344
int64_t getConstant() const { return Cst; }
4445
const MCSymbolRefExpr *getSymA() const { return SymA; }
4546
const MCSymbolRefExpr *getSymB() const { return SymB; }
46-
uint32_t getRefKind() const { return RefKind; }
47-
void setSpecifier(uint32_t S) { RefKind = S; }
47+
uint32_t getRefKind() const { return Specifier; }
48+
uint32_t getSpecifier() const { return Specifier; }
49+
void setSpecifier(uint32_t S) { Specifier = S; }
4850

4951
const MCSymbol *getAddSym() const {
5052
return SymA ? &SymA->getSymbol() : nullptr;
@@ -71,7 +73,7 @@ class MCValue {
7173
R.Cst = Val;
7274
R.SymA = SymA;
7375
R.SymB = SymB;
74-
R.RefKind = RefKind;
76+
R.Specifier = RefKind;
7577
return R;
7678
}
7779

@@ -80,7 +82,7 @@ class MCValue {
8082
R.Cst = Val;
8183
R.SymA = nullptr;
8284
R.SymB = nullptr;
83-
R.RefKind = 0;
85+
R.Specifier = 0;
8486
return R;
8587
}
8688

llvm/lib/MC/MCAssembler.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,6 @@ bool MCAssembler::evaluateFixup(const MCFixup &Fixup, const MCFragment *DF,
159159
Ctx.reportError(Fixup.getLoc(), "expected relocatable expression");
160160
return true;
161161
}
162-
if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
163-
if (RefB->getKind() != MCSymbolRefExpr::VK_None) {
164-
Ctx.reportError(Fixup.getLoc(),
165-
"unsupported subtraction of qualified symbol");
166-
return true;
167-
}
168-
}
169162

170163
unsigned FixupFlags = getBackend().getFixupKindInfo(Fixup.getKind()).Flags;
171164
if (FixupFlags & MCFixupKindInfo::FKF_IsTarget)

llvm/lib/MC/MCExpr.cpp

Lines changed: 69 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -295,19 +295,18 @@ bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
295295
}
296296

297297
/// Helper method for \see EvaluateSymbolAdd().
298-
static void AttemptToFoldSymbolOffsetDifference(
299-
const MCAssembler *Asm, const SectionAddrMap *Addrs, bool InSet,
300-
const MCSymbolRefExpr *&A, const MCSymbolRefExpr *&B, int64_t &Addend) {
298+
static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm,
299+
const SectionAddrMap *Addrs,
300+
bool InSet, const MCSymbol *&A,
301+
const MCSymbol *&B,
302+
int64_t &Addend) {
301303
if (!A || !B)
302304
return;
303305

304-
const MCSymbol &SA = A->getSymbol();
305-
const MCSymbol &SB = B->getSymbol();
306-
306+
const MCSymbol &SA = *A, &SB = *B;
307307
if (SA.isUndefined() || SB.isUndefined())
308308
return;
309-
310-
if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet))
309+
if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, SA, SB, InSet))
311310
return;
312311

313312
auto FinalizeFolding = [&]() {
@@ -345,8 +344,7 @@ static void AttemptToFoldSymbolOffsetDifference(
345344
}
346345

347346
// Eagerly evaluate when layout is finalized.
348-
Addend += Asm->getSymbolOffset(A->getSymbol()) -
349-
Asm->getSymbolOffset(B->getSymbol());
347+
Addend += Asm->getSymbolOffset(SA) - Asm->getSymbolOffset(SB);
350348
if (Addrs && (&SecA != &SecB))
351349
Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB));
352350

@@ -420,65 +418,52 @@ static void AttemptToFoldSymbolOffsetDifference(
420418
}
421419
}
422420

423-
/// Evaluate the result of an add between (conceptually) two MCValues.
424-
///
425-
/// This routine conceptually attempts to construct an MCValue:
426-
/// Result = (Result_A - Result_B + Result_Cst)
427-
/// from two MCValue's LHS and RHS where
428-
/// Result = LHS + RHS
429-
/// and
430-
/// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
431-
///
432-
/// This routine attempts to aggressively fold the operands such that the result
433-
/// is representable in an MCValue, but may not always succeed.
434-
///
435-
/// \returns True on success, false if the result is not representable in an
436-
/// MCValue.
437-
438-
/// NOTE: It is really important to have both the Asm and Layout arguments.
439-
/// They might look redundant, but this function can be used before layout
440-
/// is done (see the object streamer for example) and having the Asm argument
441-
/// lets us avoid relaxations early.
421+
// Evaluate the sum of two relocatable expressions.
422+
//
423+
// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
424+
//
425+
// This routine attempts to aggressively fold the operands such that the result
426+
// is representable in an MCValue, but may not always succeed.
427+
//
428+
// LHS_A and RHS_A might have relocation specifiers while LHS_B and RHS_B
429+
// cannot have specifiers.
430+
//
431+
// \returns True on success, false if the result is not representable in an
432+
// MCValue.
433+
434+
// NOTE: This function can be used before layout is done (see the object
435+
// streamer for example) and having the Asm argument lets us avoid relaxations
436+
// early.
442437
static bool evaluateSymbolicAdd(const MCAssembler *Asm,
443438
const SectionAddrMap *Addrs, bool InSet,
444-
const MCValue &LHS, const MCValue &RHS,
439+
const MCValue &LHS,
440+
const MCSymbolRefExpr *RhsAdd,
441+
const MCSymbolRefExpr *RhsSub, int64_t RHS_Cst,
445442
MCValue &Res) {
446-
// FIXME: This routine (and other evaluation parts) are *incredibly* sloppy
447-
// about dealing with modifiers. This will ultimately bite us, one day.
448-
const MCSymbolRefExpr *LHS_A = LHS.getSymA();
449-
const MCSymbolRefExpr *LHS_B = LHS.getSymB();
443+
const MCSymbol *LHS_A = LHS.getAddSym();
444+
const MCSymbol *LHS_B = LHS.getSubSym();
450445
int64_t LHS_Cst = LHS.getConstant();
451446

452-
const MCSymbolRefExpr *RHS_A = RHS.getSymA();
453-
const MCSymbolRefExpr *RHS_B = RHS.getSymB();
454-
int64_t RHS_Cst = RHS.getConstant();
455-
456-
if (LHS.getRefKind() != RHS.getRefKind())
457-
return false;
447+
const MCSymbol *RHS_A = RhsAdd ? &RhsAdd->getSymbol() : nullptr;
448+
const MCSymbol *RHS_B = RhsSub ? &RhsSub->getSymbol() : nullptr;
458449

459450
// Fold the result constant immediately.
460451
int64_t Result_Cst = LHS_Cst + RHS_Cst;
461452

462453
// If we have a layout, we can fold resolved differences.
463454
if (Asm) {
464-
// First, fold out any differences which are fully resolved. By
465-
// reassociating terms in
455+
// While LHS_A-LHS_B and RHS_A-RHS_B from recursive calls have already been
456+
// folded, reassociating terms in
466457
// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
467-
// we have the four possible differences:
468-
// (LHS_A - LHS_B),
469-
// (LHS_A - RHS_B),
470-
// (RHS_A - LHS_B),
471-
// (RHS_A - RHS_B).
472-
// Since we are attempting to be as aggressive as possible about folding, we
473-
// attempt to evaluate each possible alternative.
474-
AttemptToFoldSymbolOffsetDifference(Asm, Addrs, InSet, LHS_A, LHS_B,
475-
Result_Cst);
476-
AttemptToFoldSymbolOffsetDifference(Asm, Addrs, InSet, LHS_A, RHS_B,
477-
Result_Cst);
478-
AttemptToFoldSymbolOffsetDifference(Asm, Addrs, InSet, RHS_A, LHS_B,
479-
Result_Cst);
480-
AttemptToFoldSymbolOffsetDifference(Asm, Addrs, InSet, RHS_A, RHS_B,
481-
Result_Cst);
458+
// might bring more opportunities.
459+
if (LHS_A && RHS_B && !LHS.getSymA()->getSpecifier()) {
460+
attemptToFoldSymbolOffsetDifference(Asm, Addrs, InSet, LHS_A, RHS_B,
461+
Result_Cst);
462+
}
463+
if (RHS_A && LHS_B && !RhsAdd->getSpecifier()) {
464+
attemptToFoldSymbolOffsetDifference(Asm, Addrs, InSet, RHS_A, LHS_B,
465+
Result_Cst);
466+
}
482467
}
483468

484469
// We can't represent the addition or subtraction of two symbols.
@@ -487,9 +472,10 @@ static bool evaluateSymbolicAdd(const MCAssembler *Asm,
487472

488473
// At this point, we have at most one additive symbol and one subtractive
489474
// symbol -- find them.
490-
const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A;
491-
const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B;
492-
475+
auto *A = LHS_A ? LHS.getSymA() : RHS_A ? RhsAdd : nullptr;
476+
auto *B = LHS_B ? LHS.getSymB() : RHS_B ? RhsSub : nullptr;
477+
if (B && B->getKind() != MCSymbolRefExpr::VK_None)
478+
return false;
493479
Res = MCValue::get(A, B, Result_Cst);
494480
return true;
495481
}
@@ -641,31 +627,40 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
641627

642628
// We only support a few operations on non-constant expressions, handle
643629
// those first.
630+
auto Op = ABE->getOpcode();
631+
int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
644632
if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
645-
switch (ABE->getOpcode()) {
633+
switch (Op) {
646634
default:
647635
return false;
648-
case MCBinaryExpr::Sub:
649-
// Negate RHS and add.
650-
// The cast avoids undefined behavior if the constant is INT64_MIN.
651-
return evaluateSymbolicAdd(
652-
Asm, Addrs, InSet, LHSValue,
653-
MCValue::get(RHSValue.getSymB(), RHSValue.getSymA(),
654-
-(uint64_t)RHSValue.getConstant(),
655-
RHSValue.getRefKind()),
656-
Res);
657-
658636
case MCBinaryExpr::Add:
659-
return evaluateSymbolicAdd(Asm, Addrs, InSet, LHSValue, RHSValue, Res);
637+
case MCBinaryExpr::Sub:
638+
// TODO: Prevent folding for AArch64 @AUTH operands.
639+
if (LHSValue.getSpecifier() || RHSValue.getSpecifier())
640+
return false;
641+
if (Op == MCBinaryExpr::Sub) {
642+
std::swap(RHSValue.SymA, RHSValue.SymB);
643+
RHSValue.Cst = -(uint64_t)RHSValue.Cst;
644+
}
645+
if (RHSValue.isAbsolute()) {
646+
LHSValue.Cst += RHSValue.Cst;
647+
Res = LHSValue;
648+
return true;
649+
}
650+
if (LHSValue.isAbsolute()) {
651+
RHSValue.Cst += LHSValue.Cst;
652+
Res = RHSValue;
653+
return true;
654+
}
655+
return evaluateSymbolicAdd(Asm, Addrs, InSet, LHSValue, RHSValue.SymA,
656+
RHSValue.SymB, RHSValue.Cst, Res);
660657
}
661658
}
662659

663660
// FIXME: We need target hooks for the evaluation. It may be limited in
664661
// width, and gas defines the result of comparisons differently from
665662
// Apple as.
666-
int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
667663
int64_t Result = 0;
668-
auto Op = ABE->getOpcode();
669664
switch (Op) {
670665
case MCBinaryExpr::AShr: Result = LHS >> RHS; break;
671666
case MCBinaryExpr::Add: Result = LHS + RHS; break;

llvm/lib/MC/MCObjectWriter.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,10 @@ void MCObjectWriter::reset() {
2727
CGProfile.clear();
2828
}
2929

30-
bool MCObjectWriter::isSymbolRefDifferenceFullyResolved(
31-
const MCAssembler &Asm, const MCSymbolRefExpr *A, const MCSymbolRefExpr *B,
32-
bool InSet) const {
33-
// Modified symbol references cannot be resolved.
34-
if (A->getKind() != MCSymbolRefExpr::VK_None ||
35-
B->getKind() != MCSymbolRefExpr::VK_None)
36-
return false;
37-
38-
const MCSymbol &SA = A->getSymbol();
39-
const MCSymbol &SB = B->getSymbol();
30+
bool MCObjectWriter::isSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
31+
const MCSymbol &SA,
32+
const MCSymbol &SB,
33+
bool InSet) const {
4034
assert(!SA.isUndefined() && !SB.isUndefined());
4135
return isSymbolRefDifferenceFullyResolvedImpl(Asm, SA, *SB.getFragment(),
4236
InSet, /*IsPCRel=*/false);

llvm/test/MC/AArch64/elf-reloc-ptrauth.s

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@
4141
// RELOC-NEXT: 70 00000000 10000000
4242
// ^^^^ discriminator
4343
// ^^ 0 no addr diversity 0 reserved 00 ia key 0000 reserved
44-
// RELOC-NEXT: 80 04000000 00000000
45-
// Folded to constant 4 bytes difference between _g9 and _g8
4644

4745
.section .helper
4846
.local "_g 6"
@@ -91,10 +89,6 @@ _g9:
9189
.quad ("_g 7" + 7)@AUTH(ia,16)
9290
.quad 0
9391

94-
// ASM: .xword _g9@AUTH(ia,42)-_g8@AUTH(ia,42)
95-
.quad _g9@AUTH(ia,42) - _g8@AUTH(ia,42)
96-
.quad 0
97-
9892
.ifdef ASMONLY
9993

10094
// ASM: .xword _g10@AUTH(ia,42)+1
@@ -190,4 +184,8 @@ _g9:
190184
// ERROBJ: :[[#@LINE+1]]:7: error: expected relocatable expression
191185
.quad _g9@AUTH(ia,42) - _g8
192186

187+
// ERROBJ: :[[#@LINE+1]]:7: error: expected relocatable expression
188+
.quad _g9@AUTH(ia,42) - _g8@AUTH(ia,42)
189+
.quad 0
190+
193191
.endif // ERROBJ

llvm/test/MC/AArch64/label-arithmetic-diags-darwin.s

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,9 @@ Lend:
1414
// CHECK-NEXT: ^
1515

1616
add w0, w1, #(Lend - var@TLVPPAGEOFF)
17+
// CHECK: [[#@LINE-1]]:3: error: expected relocatable expression
1718
cmp w0, #(Lend - var@TLVPPAGEOFF)
18-
// CHECK: error: unsupported subtraction of qualified symbol
19-
// CHECK-NEXT: add w0, w1, #(Lend - var@TLVPPAGEOFF)
20-
// CHECK-NEXT: ^
21-
// CHECK: error: unsupported subtraction of qualified symbol
22-
// CHECK-NEXT: cmp w0, #(Lend - var@TLVPPAGEOFF)
23-
// CHECK-NEXT: ^
19+
// CHECK: [[#@LINE-1]]:3: error: expected relocatable expression
2420

2521
add w0, w1, #(Lstart - Lend)
2622
cmp w0, #(Lstart - Lend)

llvm/test/MC/ELF/bad-expr.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ x:
77
// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: symbol '__executable_start' can not be undefined in a subtraction expression
88
.quad x-__executable_start
99

10-
// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: unsupported subtraction of qualified symbol
11-
.long bar - foo@got
10+
// CHECK: [[@LINE+1]]:7: error: expected relocatable expression
11+
.long bar - foo@got
1212
foo:

llvm/test/MC/X86/macho-reloc-errors-x86_64.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
mov %rax, thing@TLVP
1111

1212
// CHECK-ERROR: 3:9: error: 32-bit absolute addressing is not supported in 64-bit mode
13-
// CHECK-ERROR: 4:9: error: unsupported subtraction of qualified symbol
13+
// CHECK-ERROR: 4:9: error: expected relocatable expression
1414
// CHECK-ERROR: 5:9: error: unsupported pc-relative relocation of difference
1515
// CHECK-ERROR: 6:9: error: unsupported relocation with identical base
1616
// CHECK-ERROR: 7:9: error: unsupported relocation with subtraction expression, symbol 'thing' can not be undefined in a subtraction expression

0 commit comments

Comments
 (0)