#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;
-void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
+void MCExpr::print(raw_ostream &OS) const {
switch (getKind()) {
+ case MCExpr::Target:
+ return cast<MCTargetExpr>(this)->PrintImpl(OS);
case MCExpr::Constant:
OS << cast<MCConstantExpr>(*this).getValue();
return;
// 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;
return;
}
case MCUnaryExpr::Not: OS << '~'; break;
case MCUnaryExpr::Plus: OS << '+'; break;
}
- UE.getSubExpr()->print(OS, MAI);
+ OS << *UE.getSubExpr();
return;
}
// Only print parens around the LHS if it is non-trivial.
if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) {
- BE.getLHS()->print(OS, MAI);
+ OS << *BE.getLHS();
} else {
- OS << '(';
- BE.getLHS()->print(OS, MAI);
- OS << ')';
+ OS << '(' << *BE.getLHS() << ')';
}
switch (BE.getOpcode()) {
// Only print parens around the LHS if it is non-trivial.
if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {
- BE.getRHS()->print(OS, MAI);
+ OS << *BE.getRHS();
} else {
- OS << '(';
- BE.getRHS()->print(OS, MAI);
- OS << ')';
+ OS << '(' << *BE.getRHS() << ')';
}
return;
}
}
void MCExpr::dump() const {
- print(errs(), 0);
- errs() << '\n';
+ print(dbgs());
+ dbgs() << '\n';
}
/* *** */
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();
return true;
}
-bool MCExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const {
+bool MCExpr::EvaluateAsRelocatable(MCValue &Res) const {
switch (getKind()) {
+ case Target:
+ return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res);
+
case Constant:
Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
return true;
case SymbolRef: {
const MCSymbol &Sym = cast<MCSymbolRefExpr>(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;
}
const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
MCValue Value;
- if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value))
+ if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value))
return false;
switch (AUE->getOpcode()) {
const MCBinaryExpr *ABE = cast<MCBinaryExpr>(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
}
// 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()) {