@@ -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.
442437static 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 ;
0 commit comments