X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FMCExpr.cpp;h=e419043a771749acc36796fa71f937f01a41139d;hb=45f48746110f5e6f7e65af7de239333dbd45d1d1;hp=10759687b2fd444556d7b2765848f321955c3dc8;hpb=9643ac55142d40da404caa8e5fedfef2cd7b4afc;p=oota-llvm.git diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 10759687b2f..e419043a771 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -11,18 +11,112 @@ #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" using namespace llvm; -const MCBinaryExpr * MCBinaryExpr::Create(Opcode Opc, - const MCExpr *LHS, - const MCExpr *RHS, - MCContext &Ctx) { +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(); + + // Parenthesize names that start with $ so that they don't look like + // absolute names. + if (Sym.getName()[0] == '$') + OS << '(' << Sym << ')'; + else + OS << Sym; + return; + } + + case MCExpr::Unary: { + const MCUnaryExpr &UE = cast(*this); + switch (UE.getOpcode()) { + default: assert(0 && "Invalid opcode!"); + case MCUnaryExpr::LNot: OS << '!'; break; + case MCUnaryExpr::Minus: OS << '-'; break; + case MCUnaryExpr::Not: OS << '~'; break; + case MCUnaryExpr::Plus: OS << '+'; break; + } + 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())) { + OS << *BE.getLHS(); + } else { + OS << '(' << *BE.getLHS() << ')'; + } + + switch (BE.getOpcode()) { + default: assert(0 && "Invalid opcode!"); + case MCBinaryExpr::Add: + // Print "X-42" instead of "X+-42". + if (const MCConstantExpr *RHSC = dyn_cast(BE.getRHS())) { + if (RHSC->getValue() < 0) { + OS << RHSC->getValue(); + return; + } + } + + OS << '+'; + break; + case MCBinaryExpr::And: OS << '&'; break; + case MCBinaryExpr::Div: OS << '/'; break; + case MCBinaryExpr::EQ: OS << "=="; break; + case MCBinaryExpr::GT: OS << '>'; break; + case MCBinaryExpr::GTE: OS << ">="; break; + case MCBinaryExpr::LAnd: OS << "&&"; break; + case MCBinaryExpr::LOr: OS << "||"; break; + case MCBinaryExpr::LT: OS << '<'; break; + case MCBinaryExpr::LTE: OS << "<="; break; + case MCBinaryExpr::Mod: OS << '%'; break; + case MCBinaryExpr::Mul: 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; + } + + // Only print parens around the LHS if it is non-trivial. + if (isa(BE.getRHS()) || isa(BE.getRHS())) { + OS << *BE.getRHS(); + } else { + OS << '(' << *BE.getRHS() << ')'; + } + return; + } + } + + assert(0 && "Invalid expression kind!"); +} + +void MCExpr::dump() const { + print(dbgs()); + dbgs() << '\n'; +} + +/* *** */ + +const MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS, + const MCExpr *RHS, MCContext &Ctx) { return new (Ctx) MCBinaryExpr(Opc, LHS, RHS); } -const MCUnaryExpr * MCUnaryExpr::Create(Opcode Opc, - const MCExpr *Expr, - MCContext &Ctx) { +const MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr, + MCContext &Ctx) { return new (Ctx) MCUnaryExpr(Opc, Expr); } @@ -35,12 +129,18 @@ const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym, return new (Ctx) MCSymbolRefExpr(Sym); } +const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, MCContext &Ctx) { + return Create(Ctx.GetOrCreateSymbol(Name), Ctx); +} + +void MCTargetExpr::Anchor() {} + /* *** */ -bool MCExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const { +bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const { MCValue Value; - if (!EvaluateAsRelocatable(Ctx, Value) || !Value.isAbsolute()) + if (!EvaluateAsRelocatable(Value) || !Value.isAbsolute()) return false; Res = Value.getConstant(); @@ -69,18 +169,23 @@ 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 { switch (getKind()) { + case Target: + return cast(this)->EvaluateAsRelocatableImpl(Res); + case Constant: Res = MCValue::get(cast(this)->getValue()); return true; case SymbolRef: { const MCSymbol &Sym = cast(this)->getSymbol(); - if (const MCValue *Value = Ctx.GetSymbolValue(&Sym)) - Res = *Value; - else - Res = MCValue::get(&Sym, 0, 0); + + // Evaluate recursively if this is a variable. + if (Sym.isVariable()) + return Sym.getValue()->EvaluateAsRelocatable(Res); + + Res = MCValue::get(&Sym, 0, 0); return true; } @@ -88,7 +193,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)) return false; switch (AUE->getOpcode()) { @@ -121,8 +226,8 @@ bool MCExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const { const MCBinaryExpr *ABE = cast(this); MCValue LHSValue, RHSValue; - if (!ABE->getLHS()->EvaluateAsRelocatable(Ctx, LHSValue) || - !ABE->getRHS()->EvaluateAsRelocatable(Ctx, RHSValue)) + if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue) || + !ABE->getRHS()->EvaluateAsRelocatable(RHSValue)) return false; // We only support a few operations on non-constant expressions, handle @@ -147,8 +252,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()) {