diff options
Diffstat (limited to 'lib/MC/MCExpr.cpp')
-rw-r--r-- | lib/MC/MCExpr.cpp | 94 |
1 files changed, 80 insertions, 14 deletions
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 4439eba..a2ed20b 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -8,11 +8,15 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCExpr.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetAsmBackend.h" using namespace llvm; void MCExpr::print(raw_ostream &OS) const { @@ -24,7 +28,8 @@ void MCExpr::print(raw_ostream &OS) const { return; case MCExpr::SymbolRef: { - const MCSymbol &Sym = cast<MCSymbolRefExpr>(*this).getSymbol(); + const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this); + const MCSymbol &Sym = SRE.getSymbol(); // Parenthesize names that start with $ so that they don't look like // absolute names. @@ -32,6 +37,10 @@ void MCExpr::print(raw_ostream &OS) const { OS << '(' << Sym << ')'; else OS << Sym; + + if (SRE.getKind() != MCSymbolRefExpr::VK_None) + OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); + return; } @@ -124,28 +133,68 @@ const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) { return new (Ctx) MCConstantExpr(Value); } +/* *** */ + const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym, + VariantKind Kind, MCContext &Ctx) { - return new (Ctx) MCSymbolRefExpr(Sym); + return new (Ctx) MCSymbolRefExpr(Sym, Kind); } -const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, MCContext &Ctx) { - return Create(Ctx.GetOrCreateSymbol(Name), Ctx); +const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, VariantKind Kind, + MCContext &Ctx) { + return Create(Ctx.GetOrCreateSymbol(Name), Kind, Ctx); } const MCSymbolRefExpr *MCSymbolRefExpr::CreateTemp(StringRef Name, + VariantKind Kind, MCContext &Ctx) { - return Create(Ctx.GetOrCreateTemporarySymbol(Name), Ctx); + return Create(Ctx.GetOrCreateTemporarySymbol(Name), Kind, Ctx); } +StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { + switch (Kind) { + default: + case VK_Invalid: return "<<invalid>>"; + case VK_None: return "<<none>>"; + + case VK_GOT: return "GOT"; + case VK_GOTOFF: return "GOTOFF"; + case VK_GOTPCREL: return "GOTPCREL"; + case VK_GOTTPOFF: return "GOTTPOFF"; + case VK_INDNTPOFF: return "INDNTPOFF"; + case VK_NTPOFF: return "NTPOFF"; + case VK_PLT: return "PLT"; + case VK_TLSGD: return "TLSGD"; + case VK_TPOFF: return "TPOFF"; + } +} + +MCSymbolRefExpr::VariantKind +MCSymbolRefExpr::getVariantKindForName(StringRef Name) { + return StringSwitch<VariantKind>(Name) + .Case("GOT", VK_GOT) + .Case("GOTOFF", VK_GOTOFF) + .Case("GOTPCREL", VK_GOTPCREL) + .Case("GOTTPOFF", VK_GOTTPOFF) + .Case("INDNTPOFF", VK_INDNTPOFF) + .Case("NTPOFF", VK_NTPOFF) + .Case("PLT", VK_PLT) + .Case("TLSGD", VK_TLSGD) + .Case("TPOFF", VK_TPOFF) + .Default(VK_Invalid); +} + +/* *** */ + void MCTargetExpr::Anchor() {} /* *** */ -bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const { +bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout) const { MCValue Value; - if (!EvaluateAsRelocatable(Value) || !Value.isAbsolute()) + if (!EvaluateAsRelocatable(Value, Layout) || !Value.isAbsolute()) return false; Res = Value.getConstant(); @@ -174,10 +223,11 @@ static bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A, return true; } -bool MCExpr::EvaluateAsRelocatable(MCValue &Res) const { +bool MCExpr::EvaluateAsRelocatable(MCValue &Res, + const MCAsmLayout *Layout) const { switch (getKind()) { case Target: - return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res); + return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res, Layout); case Constant: Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); @@ -187,8 +237,24 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res) const { const MCSymbol &Sym = cast<MCSymbolRefExpr>(this)->getSymbol(); // Evaluate recursively if this is a variable. - if (Sym.isVariable()) - return Sym.getValue()->EvaluateAsRelocatable(Res); + 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()->isDefined() && Res.getSymB()->isDefined()) { + MCSymbolData &A = Layout->getAssembler().getSymbolData(*Res.getSymA()); + MCSymbolData &B = Layout->getAssembler().getSymbolData(*Res.getSymB()); + Res = MCValue::get(+ A.getFragment()->getAddress() + A.getOffset() + - B.getFragment()->getAddress() - B.getOffset() + + Res.getConstant()); + } + + return true; + } Res = MCValue::get(&Sym, 0, 0); return true; @@ -198,7 +264,7 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res) const { const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); MCValue Value; - if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value)) + if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value, Layout)) return false; switch (AUE->getOpcode()) { @@ -231,8 +297,8 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res) const { const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); MCValue LHSValue, RHSValue; - if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue) || - !ABE->getRHS()->EvaluateAsRelocatable(RHSValue)) + if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue, Layout) || + !ABE->getRHS()->EvaluateAsRelocatable(RHSValue, Layout)) return false; // We only support a few operations on non-constant expressions, handle |