#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCObjectFormat.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/Debug.h"
const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this);
const MCSymbol &Sym = SRE.getSymbol();
+ if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_HI16 ||
+ SRE.getKind() == MCSymbolRefExpr::VK_ARM_LO16)
+ OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
+
// Parenthesize names that start with $ so that they don't look like
// absolute names.
if (Sym.getName()[0] == '$')
else
OS << Sym;
- if (SRE.getKind() != MCSymbolRefExpr::VK_None)
+ if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_PLT ||
+ SRE.getKind() == MCSymbolRefExpr::VK_ARM_TLSGD ||
+ SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOT ||
+ SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTOFF ||
+ SRE.getKind() == MCSymbolRefExpr::VK_ARM_TPOFF ||
+ SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF)
+ OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
+ else if (SRE.getKind() != MCSymbolRefExpr::VK_None &&
+ SRE.getKind() != MCSymbolRefExpr::VK_ARM_HI16 &&
+ SRE.getKind() != MCSymbolRefExpr::VK_ARM_LO16)
OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
return;
return Create(Ctx.GetOrCreateSymbol(Name), Kind, Ctx);
}
-const MCSymbolRefExpr *MCSymbolRefExpr::CreateTemp(StringRef Name,
- VariantKind Kind,
- MCContext &Ctx) {
- return Create(Ctx.GetOrCreateTemporarySymbol(Name), Kind, Ctx);
-}
-
StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
switch (Kind) {
default:
case VK_GOTTPOFF: return "GOTTPOFF";
case VK_INDNTPOFF: return "INDNTPOFF";
case VK_NTPOFF: return "NTPOFF";
+ case VK_GOTNTPOFF: return "GOTNTPOFF";
case VK_PLT: return "PLT";
case VK_TLSGD: return "TLSGD";
+ case VK_TLSLD: return "TLSLD";
+ case VK_TLSLDM: return "TLSLDM";
case VK_TPOFF: return "TPOFF";
+ case VK_DTPOFF: return "DTPOFF";
+ case VK_ARM_HI16: return ":upper16:";
+ case VK_ARM_LO16: return ":lower16:";
+ case VK_ARM_PLT: return "(PLT)";
+ case VK_ARM_GOT: return "(GOT)";
+ case VK_ARM_GOTOFF: return "(GOTOFF)";
+ case VK_ARM_TPOFF: return "(tpoff)";
+ case VK_ARM_GOTTPOFF: return "(gottpoff)";
+ case VK_ARM_TLSGD: return "(tldgd)";
+ case VK_TLVP: return "TLVP";
}
}
.Case("GOTTPOFF", VK_GOTTPOFF)
.Case("INDNTPOFF", VK_INDNTPOFF)
.Case("NTPOFF", VK_NTPOFF)
+ .Case("GOTNTPOFF", VK_GOTNTPOFF)
.Case("PLT", VK_PLT)
.Case("TLSGD", VK_TLSGD)
+ .Case("TLSLD", VK_TLSLD)
+ .Case("TLSLDM", VK_TLSLDM)
.Case("TPOFF", VK_TPOFF)
+ .Case("DTPOFF", VK_DTPOFF)
+ .Case("TLVP", VK_TLVP)
.Default(VK_Invalid);
}
return true;
}
- if (!EvaluateAsRelocatable(Value, Layout) || !Value.isAbsolute())
+ if (!EvaluateAsRelocatable(Value, Layout) || !Value.isAbsolute()) {
+ // EvaluateAsAbsolute is defined to return the "current value" of
+ // the expression if we are given a Layout object, even in cases
+ // when the value is not fixed.
+ if (Layout) {
+ Res = Value.getConstant();
+ if (Value.getSymA()) {
+ Res += Layout->getSymbolAddress(
+ &Layout->getAssembler().getSymbolData(Value.getSymA()->getSymbol()));
+ }
+ if (Value.getSymB()) {
+ Res -= Layout->getSymbolAddress(
+ &Layout->getAssembler().getSymbolData(Value.getSymB()->getSymbol()));
+ }
+ }
return false;
+ }
Res = Value.getConstant();
return true;
}
-static bool EvaluateSymbolicAdd(const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
+static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout, bool InSet,
+ const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst,
MCValue &Res) {
// We can't add or subtract two symbols.
if (!A)
return false;
}
+
+ // Absolutize symbol differences between defined symbols when we have a
+ // layout object and the target requests it.
+
+ if (Layout && A && B) {
+ const MCSymbol &SA = A->getSymbol();
+ const MCSymbol &SB = B->getSymbol();
+ const MCObjectFormat &F =
+ Layout->getAssembler().getBackend().getObjectFormat();
+ if (SA.isDefined() && SB.isDefined() && F.isAbsolute(InSet, SA, SB)) {
+ const MCAssembler &Asm = Layout->getAssembler();
+ MCSymbolData &AD = Asm.getSymbolData(A->getSymbol());
+ MCSymbolData &BD = Asm.getSymbolData(B->getSymbol());
+ Res = MCValue::get(+ Layout->getSymbolAddress(&AD)
+ - Layout->getSymbolAddress(&BD)
+ + LHS.getConstant()
+ + RHS_Cst);
+ return true;
+ }
+ }
+
+
Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst);
return true;
}
bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
const MCAsmLayout *Layout) const {
+ return EvaluateAsRelocatableImpl(Res, Layout, false);
+}
+
+bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
+ const MCAsmLayout *Layout,
+ bool InSet) const {
++stats::MCExprEvaluate;
switch (getKind()) {
const MCSymbol &Sym = SRE->getSymbol();
// Evaluate recursively if this is a variable.
- if (Sym.isVariable()) {
- if (!Sym.getValue()->EvaluateAsRelocatable(Res, Layout))
- return false;
-
- // Absolutize symbol differences between defined symbols when we have a
- // layout object and the target requests it.
- if (Layout && Res.getSymB() &&
- Layout->getAssembler().getBackend().hasAbsolutizedSet() &&
- Res.getSymA()->getSymbol().isDefined() &&
- Res.getSymB()->getSymbol().isDefined()) {
- MCSymbolData &A =
- Layout->getAssembler().getSymbolData(Res.getSymA()->getSymbol());
- MCSymbolData &B =
- Layout->getAssembler().getSymbolData(Res.getSymB()->getSymbol());
- Res = MCValue::get(+ A.getFragment()->getAddress() + A.getOffset()
- - B.getFragment()->getAddress() - B.getOffset()
- + Res.getConstant());
- }
-
- return true;
- }
+ if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None)
+ return Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Layout,
+ true);
Res = MCValue::get(SRE, 0, 0);
return true;
const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
MCValue Value;
- if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value, Layout))
+ if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Layout, InSet))
return false;
switch (AUE->getOpcode()) {
const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
MCValue LHSValue, RHSValue;
- if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue, Layout) ||
- !ABE->getRHS()->EvaluateAsRelocatable(RHSValue, Layout))
+ if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Layout, InSet) ||
+ !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Layout, InSet))
return false;
// We only support a few operations on non-constant expressions, handle
return false;
case MCBinaryExpr::Sub:
// Negate RHS and add.
- return EvaluateSymbolicAdd(LHSValue,
+ return EvaluateSymbolicAdd(Layout, InSet, LHSValue,
RHSValue.getSymB(), RHSValue.getSymA(),
-RHSValue.getConstant(),
Res);
case MCBinaryExpr::Add:
- return EvaluateSymbolicAdd(LHSValue,
+ return EvaluateSymbolicAdd(Layout, InSet, LHSValue,
RHSValue.getSymA(), RHSValue.getSymB(),
RHSValue.getConstant(),
Res);