summaryrefslogtreecommitdiffstats
path: root/lib/MC/MCExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC/MCExpr.cpp')
-rw-r--r--lib/MC/MCExpr.cpp94
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
OpenPOWER on IntegriCloud