OS << '+';
break;
+ case MCBinaryExpr::AShr: OS << ">>"; break;
case MCBinaryExpr::And: OS << '&'; break;
case MCBinaryExpr::Div: OS << '/'; break;
case MCBinaryExpr::EQ: OS << "=="; break;
case MCBinaryExpr::GTE: OS << ">="; break;
case MCBinaryExpr::LAnd: OS << "&&"; break;
case MCBinaryExpr::LOr: OS << "||"; break;
+ case MCBinaryExpr::LShr: OS << ">>"; break;
case MCBinaryExpr::LT: OS << '<'; break;
case MCBinaryExpr::LTE: OS << "<="; break;
case MCBinaryExpr::Mod: OS << '%'; break;
case MCBinaryExpr::NE: OS << "!="; break;
case MCBinaryExpr::Or: OS << '|'; break;
case MCBinaryExpr::Shl: OS << "<<"; break;
- case MCBinaryExpr::Shr: OS << ">>"; break;
case MCBinaryExpr::Sub: OS << '-'; break;
case MCBinaryExpr::Xor: OS << '^'; break;
}
case VK_GOTPAGE: return "GOTPAGE";
case VK_GOTPAGEOFF: return "GOTPAGEOFF";
case VK_SECREL: return "SECREL32";
+ case VK_SIZE: return "SIZE";
case VK_WEAKREF: return "WEAKREF";
case VK_ARM_NONE: return "none";
case VK_ARM_TARGET1: return "target1";
case VK_Mips_PCREL_HI16: return "PCREL_HI16";
case VK_Mips_PCREL_LO16: return "PCREL_LO16";
case VK_COFF_IMGREL32: return "IMGREL";
+ case VK_Hexagon_PCREL: return "PCREL";
+ case VK_Hexagon_LO16: return "LO16";
+ case VK_Hexagon_HI16: return "HI16";
+ case VK_Hexagon_GPREL: return "GPREL";
+ case VK_Hexagon_GD_GOT: return "GDGOT";
+ case VK_Hexagon_LD_GOT: return "LDGOT";
+ case VK_Hexagon_GD_PLT: return "GDPLT";
+ case VK_Hexagon_LD_PLT: return "LDPLT";
+ case VK_Hexagon_IE: return "IE";
+ case VK_Hexagon_IE_GOT: return "IEGOT";
+ case VK_TPREL: return "tprel";
+ case VK_DTPREL: return "dtprel";
}
llvm_unreachable("Invalid variant kind");
}
.Case("gotpageoff", VK_GOTPAGEOFF)
.Case("imgrel", VK_COFF_IMGREL32)
.Case("secrel32", VK_SECREL)
+ .Case("size", VK_SIZE)
.Case("l", VK_PPC_LO)
.Case("h", VK_PPC_HI)
.Case("ha", VK_PPC_HA)
return EvaluateAsAbsolute(Res, &Asm, nullptr, nullptr);
}
-int64_t MCExpr::evaluateKnownAbsolute(const MCAsmLayout &Layout) const {
- int64_t Res;
- bool Abs =
- evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, true);
- (void)Abs;
- assert(Abs && "Not actually absolute");
- return Res;
+bool MCExpr::evaluateKnownAbsolute(int64_t &Res,
+ const MCAsmLayout &Layout) const {
+ return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr,
+ true);
}
bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
return true;
}
- bool IsRelocatable = EvaluateAsRelocatableImpl(
- Value, Asm, Layout, nullptr, Addrs, InSet, /*ForceVarExpansion*/ false);
+ bool IsRelocatable =
+ EvaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet);
// Record the current value.
Res = Value.getConstant();
}
/// \brief Helper method for \see EvaluateSymbolAdd().
-static void AttemptToFoldSymbolOffsetDifference(const MCAssembler *Asm,
- const MCAsmLayout *Layout,
- const SectionAddrMap *Addrs,
- bool InSet,
- const MCSymbolRefExpr *&A,
- const MCSymbolRefExpr *&B,
- int64_t &Addend) {
+static void AttemptToFoldSymbolOffsetDifference(
+ const MCAssembler *Asm, const MCAsmLayout *Layout,
+ const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A,
+ const MCSymbolRefExpr *&B, int64_t &Addend) {
if (!A || !B)
return;
/// They might look redundant, but this function can be used before layout
/// is done (see the object streamer for example) and having the Asm argument
/// lets us avoid relaxations early.
-static bool EvaluateSymbolicAdd(const MCAssembler *Asm,
- const MCAsmLayout *Layout,
- const SectionAddrMap *Addrs,
- bool InSet,
- const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
- const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst,
- MCValue &Res) {
+static bool
+EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout,
+ const SectionAddrMap *Addrs, bool InSet, const MCValue &LHS,
+ const MCSymbolRefExpr *RHS_A, const MCSymbolRefExpr *RHS_B,
+ int64_t RHS_Cst, MCValue &Res) {
// FIXME: This routine (and other evaluation parts) are *incredibly* sloppy
// about dealing with modifiers. This will ultimately bite us, one day.
const MCSymbolRefExpr *LHS_A = LHS.getSymA();
const MCFixup *Fixup) const {
MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr;
return EvaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr,
- false, /*ForceVarExpansion*/ false);
+ false);
}
-bool MCExpr::EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout,
- const MCFixup *Fixup) const {
- MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr;
- return EvaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr,
- false, /*ForceVarExpansion*/ true);
+bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const {
+ MCAssembler *Assembler = &Layout.getAssembler();
+ return EvaluateAsRelocatableImpl(Res, Assembler, &Layout, nullptr, nullptr,
+ true);
+}
+
+static bool canExpand(const MCSymbol &Sym, const MCAssembler *Asm, bool InSet) {
+ if (InSet)
+ return true;
+ if (!Asm)
+ return false;
+ const MCSymbolData &SD = Asm->getSymbolData(Sym);
+ return !Asm->getWriter().isWeak(SD);
}
bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout,
const MCFixup *Fixup,
- const SectionAddrMap *Addrs, bool InSet,
- bool ForceVarExpansion) const {
+ const SectionAddrMap *Addrs,
+ bool InSet) const {
++stats::MCExprEvaluate;
switch (getKind()) {
const MCSymbol &Sym = SRE->getSymbol();
// Evaluate recursively if this is a variable.
- if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
+ if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None &&
+ canExpand(Sym, Asm, InSet)) {
+ bool IsMachO = SRE->hasSubsectionsViaSymbols();
if (Sym.getVariableValue()->EvaluateAsRelocatableImpl(
- Res, Asm, Layout, Fixup, Addrs, true, ForceVarExpansion)) {
+ Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) {
+ if (!IsMachO)
+ return true;
+
const MCSymbolRefExpr *A = Res.getSymA();
const MCSymbolRefExpr *B = Res.getSymB();
-
- if (SRE->hasSubsectionsViaSymbols()) {
- // FIXME: This is small hack. Given
- // a = b + 4
- // .long a
- // the OS X assembler will completely drop the 4. We should probably
- // include it in the relocation or produce an error if that is not
- // possible.
- if (!A && !B)
- return true;
- } else {
- if (ForceVarExpansion)
- return true;
- bool IsSymbol = A && A->getSymbol().isDefined();
- if (!IsSymbol)
- return true;
- }
+ // FIXME: This is small hack. Given
+ // a = b + 4
+ // .long a
+ // the OS X assembler will completely drop the 4. We should probably
+ // include it in the relocation or produce an error if that is not
+ // possible.
+ if (!A && !B)
+ return true;
}
}
const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
MCValue Value;
- if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout,
- Fixup, Addrs, InSet,
- ForceVarExpansion))
+ if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, Fixup,
+ Addrs, InSet))
return false;
switch (AUE->getOpcode()) {
const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
MCValue LHSValue, RHSValue;
- if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout,
- Fixup, Addrs, InSet,
- ForceVarExpansion) ||
- !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout,
- Fixup, Addrs, InSet,
- ForceVarExpansion))
+ if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup,
+ Addrs, InSet) ||
+ !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup,
+ Addrs, InSet))
return false;
// We only support a few operations on non-constant expressions, handle
// Negate RHS and add.
return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
RHSValue.getSymB(), RHSValue.getSymA(),
- -RHSValue.getConstant(),
- Res);
+ -RHSValue.getConstant(), Res);
case MCBinaryExpr::Add:
return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
RHSValue.getSymA(), RHSValue.getSymB(),
- RHSValue.getConstant(),
- Res);
+ RHSValue.getConstant(), Res);
}
}
// FIXME: We need target hooks for the evaluation. It may be limited in
- // width, and gas defines the result of comparisons and right shifts
- // differently from Apple as.
+ // width, and gas defines the result of comparisons differently from
+ // Apple as.
int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
int64_t Result = 0;
switch (ABE->getOpcode()) {
+ case MCBinaryExpr::AShr: Result = LHS >> RHS; break;
case MCBinaryExpr::Add: Result = LHS + RHS; break;
case MCBinaryExpr::And: Result = LHS & RHS; break;
case MCBinaryExpr::Div: Result = LHS / RHS; break;
case MCBinaryExpr::GTE: Result = LHS >= RHS; break;
case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
case MCBinaryExpr::LOr: Result = LHS || RHS; break;
+ case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break;
case MCBinaryExpr::LT: Result = LHS < RHS; break;
case MCBinaryExpr::LTE: Result = LHS <= RHS; break;
case MCBinaryExpr::Mod: Result = LHS % RHS; break;
case MCBinaryExpr::NE: Result = LHS != RHS; break;
case MCBinaryExpr::Or: Result = LHS | RHS; break;
case MCBinaryExpr::Shl: Result = LHS << RHS; break;
- case MCBinaryExpr::Shr: Result = LHS >> RHS; break;
case MCBinaryExpr::Sub: Result = LHS - RHS; break;
case MCBinaryExpr::Xor: Result = LHS ^ RHS; break;
}
if (RHS_S == MCSymbol::AbsolutePseudoSection)
return LHS_S;
+ // Not always correct, but probably the best we can do without more context.
+ if (BE->getOpcode() == MCBinaryExpr::Sub)
+ return MCSymbol::AbsolutePseudoSection;
+
// Otherwise, return the first non-null section.
return LHS_S ? LHS_S : RHS_S;
}