X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FMCExpr.cpp;h=343f334752351ddb0124c531c6a761f5284d713e;hb=c96a82a53415fd0b6cb1bbea2593dc18683c70cc;hp=d6e545fa78c9e387329ea61271811a27fc3fe972;hpb=7c3600de949347bf5ea6369b2546fac15bd96415;p=oota-llvm.git diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index d6e545fa78c..343f3347523 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -7,31 +7,54 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "mcexpr" #include "llvm/MC/MCExpr.h" +#include "llvm/ADT/Statistic.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 MCAsmInfo *MAI) const { +namespace { +namespace stats { +STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations"); +} +} + +void MCExpr::print(raw_ostream &OS) const { switch (getKind()) { + case MCExpr::Target: + return cast(this)->PrintImpl(OS); case MCExpr::Constant: OS << cast(*this).getValue(); return; case MCExpr::SymbolRef: { - const MCSymbol &Sym = cast(*this).getSymbol(); - + const MCSymbolRefExpr &SRE = cast(*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] == '$') { - OS << '('; - Sym.print(OS, MAI); - OS << ')'; - } else { - Sym.print(OS, MAI); - } + if (Sym.getName()[0] == '$') + OS << '(' << Sym << ')'; + else + OS << Sym; + + if (SRE.getKind() != MCSymbolRefExpr::VK_None && + SRE.getKind() != MCSymbolRefExpr::VK_ARM_HI16 && + SRE.getKind() != MCSymbolRefExpr::VK_ARM_LO16) + OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); + return; } @@ -44,22 +67,20 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { case MCUnaryExpr::Not: OS << '~'; break; case MCUnaryExpr::Plus: OS << '+'; break; } - UE.getSubExpr()->print(OS, MAI); + OS << *UE.getSubExpr(); return; } case MCExpr::Binary: { const MCBinaryExpr &BE = cast(*this); - + // Only print parens around the LHS if it is non-trivial. if (isa(BE.getLHS()) || isa(BE.getLHS())) { - BE.getLHS()->print(OS, MAI); + OS << *BE.getLHS(); } else { - OS << '('; - BE.getLHS()->print(OS, MAI); - OS << ')'; + OS << '(' << *BE.getLHS() << ')'; } - + switch (BE.getOpcode()) { default: assert(0 && "Invalid opcode!"); case MCBinaryExpr::Add: @@ -70,7 +91,7 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { return; } } - + OS << '+'; break; case MCBinaryExpr::And: OS << '&'; break; @@ -91,14 +112,12 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { case MCBinaryExpr::Sub: OS << '-'; break; case MCBinaryExpr::Xor: OS << '^'; break; } - + // Only print parens around the LHS if it is non-trivial. if (isa(BE.getRHS()) || isa(BE.getRHS())) { - BE.getRHS()->print(OS, MAI); + OS << *BE.getRHS(); } else { - OS << '('; - BE.getRHS()->print(OS, MAI); - OS << ')'; + OS << '(' << *BE.getRHS() << ')'; } return; } @@ -108,8 +127,8 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { } void MCExpr::dump() const { - print(errs(), 0); - errs() << '\n'; + print(dbgs()); + dbgs() << '\n'; } /* *** */ @@ -128,39 +147,88 @@ 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(const StringRef &Name, +const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, VariantKind Kind, MCContext &Ctx) { - return Create(Ctx.GetOrCreateSymbol(Name), Ctx); + return Create(Ctx.GetOrCreateSymbol(Name), Kind, Ctx); +} + +StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { + switch (Kind) { + default: + case VK_Invalid: return "<>"; + case VK_None: return "<>"; + + 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"; + case VK_ARM_HI16: return ":upper16:"; + case VK_ARM_LO16: return ":lower16:"; + case VK_TLVP: return "TLVP"; + } +} + +MCSymbolRefExpr::VariantKind +MCSymbolRefExpr::getVariantKindForName(StringRef Name) { + return StringSwitch(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) + .Case("TLVP", VK_TLVP) + .Default(VK_Invalid); } +/* *** */ + +void MCTargetExpr::Anchor() {} /* *** */ -bool MCExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const { +bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout) const { MCValue Value; - - if (!EvaluateAsRelocatable(Ctx, Value) || !Value.isAbsolute()) + + // Fast path constants. + if (const MCConstantExpr *CE = dyn_cast(this)) { + Res = CE->getValue(); + return true; + } + + if (!EvaluateAsRelocatable(Value, Layout) || !Value.isAbsolute()) return false; Res = Value.getConstant(); return true; } -static bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A, - const MCSymbol *RHS_B, int64_t RHS_Cst, +static bool EvaluateSymbolicAdd(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 ((LHS.getSymA() && RHS_A) || (LHS.getSymB() && RHS_B)) return false; - const MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A; - const MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B; + const MCSymbolRefExpr *A = LHS.getSymA() ? LHS.getSymA() : RHS_A; + const MCSymbolRefExpr *B = LHS.getSymB() ? LHS.getSymB() : RHS_B; if (B) { // If we have a negated symbol, then we must have also have a non-negated // symbol in order to encode the expression. We can do this check later to @@ -173,20 +241,46 @@ static bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A, return true; } -bool MCExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const { +bool MCExpr::EvaluateAsRelocatable(MCValue &Res, + const MCAsmLayout *Layout) const { + ++stats::MCExprEvaluate; + switch (getKind()) { + case Target: + return cast(this)->EvaluateAsRelocatableImpl(Res, Layout); + case Constant: Res = MCValue::get(cast(this)->getValue()); return true; case SymbolRef: { - const MCSymbol &Sym = cast(this)->getSymbol(); + const MCSymbolRefExpr *SRE = cast(this); + const MCSymbol &Sym = SRE->getSymbol(); // Evaluate recursively if this is a variable. - if (Sym.isVariable()) - return Sym.getValue()->EvaluateAsRelocatable(Ctx, Res); + if (Sym.isVariable()) { + if (!Sym.getVariableValue()->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(+ Layout->getSymbolAddress(&A) + - Layout->getSymbolAddress(&B) + + Res.getConstant()); + } + + return true; + } - Res = MCValue::get(&Sym, 0, 0); + Res = MCValue::get(SRE, 0, 0); return true; } @@ -194,7 +288,7 @@ bool MCExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const { const MCUnaryExpr *AUE = cast(this); MCValue Value; - if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value)) + if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value, Layout)) return false; switch (AUE->getOpcode()) { @@ -207,13 +301,13 @@ bool MCExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const { /// -(a - b + const) ==> (b - a - const) if (Value.getSymA() && !Value.getSymB()) return false; - Res = MCValue::get(Value.getSymB(), Value.getSymA(), - -Value.getConstant()); + Res = MCValue::get(Value.getSymB(), Value.getSymA(), + -Value.getConstant()); break; case MCUnaryExpr::Not: if (!Value.isAbsolute()) return false; - Res = MCValue::get(~Value.getConstant()); + Res = MCValue::get(~Value.getConstant()); break; case MCUnaryExpr::Plus: Res = Value; @@ -226,9 +320,9 @@ bool MCExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const { case Binary: { const MCBinaryExpr *ABE = cast(this); MCValue LHSValue, RHSValue; - - if (!ABE->getLHS()->EvaluateAsRelocatable(Ctx, LHSValue) || - !ABE->getRHS()->EvaluateAsRelocatable(Ctx, 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 @@ -253,8 +347,8 @@ bool MCExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const { } // FIXME: We need target hooks for the evaluation. It may be limited in - // width, and gas defines the result of comparisons differently from Apple - // as (the result is sign extended). + // width, and gas defines the result of comparisons and right shifts + // differently from Apple as. int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); int64_t Result = 0; switch (ABE->getOpcode()) {