diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-08-31 08:06:59 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-08-31 08:06:59 +0000 |
commit | 115e4d6d7b504988f46b0d95754762df22de96ff (patch) | |
tree | 4655e647e74609548dff6432c0627218813e75ae /llvm/lib/MC/MCExpr.cpp | |
parent | eedcd84803e8fcea24cde9e19c4f72da299f5164 (diff) | |
download | bcm5719-llvm-115e4d6d7b504988f46b0d95754762df22de96ff.tar.gz bcm5719-llvm-115e4d6d7b504988f46b0d95754762df22de96ff.zip |
llvm-mc: Move AsmExpr into MC lib (as MCExpr).
llvm-svn: 80567
Diffstat (limited to 'llvm/lib/MC/MCExpr.cpp')
-rw-r--r-- | llvm/lib/MC/MCExpr.cpp | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp new file mode 100644 index 00000000000..91ef7e77ec8 --- /dev/null +++ b/llvm/lib/MC/MCExpr.cpp @@ -0,0 +1,162 @@ +//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +using namespace llvm; + +MCExpr::~MCExpr() { +} + +bool MCExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const { + MCValue Value; + + if (!EvaluateAsRelocatable(Ctx, Value) || !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, + 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; + 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 + // permit expressions which eventually fold to a representable form -- such + // as (a + (0 - b)) -- if necessary. + if (!A) + return false; + } + Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst); + return true; +} + +bool MCExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const { + switch (getKind()) { + default: + assert(0 && "Invalid assembly expression kind!"); + + case Constant: + Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); + return true; + + case SymbolRef: { + MCSymbol *Sym = cast<MCSymbolRefExpr>(this)->getSymbol(); + if (const MCValue *Value = Ctx.GetSymbolValue(Sym)) + Res = *Value; + else + Res = MCValue::get(Sym, 0, 0); + return true; + } + + case Unary: { + const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); + MCValue Value; + + if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value)) + return false; + + switch (AUE->getOpcode()) { + case MCUnaryExpr::LNot: + if (!Value.isAbsolute()) + return false; + Res = MCValue::get(!Value.getConstant()); + break; + case MCUnaryExpr::Minus: + /// -(a - b + const) ==> (b - a - const) + if (Value.getSymA() && !Value.getSymB()) + return false; + Res = MCValue::get(Value.getSymB(), Value.getSymA(), + -Value.getConstant()); + break; + case MCUnaryExpr::Not: + if (!Value.isAbsolute()) + return false; + Res = MCValue::get(~Value.getConstant()); + break; + case MCUnaryExpr::Plus: + Res = Value; + break; + } + + return true; + } + + case Binary: { + const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); + MCValue LHSValue, RHSValue; + + if (!ABE->getLHS()->EvaluateAsRelocatable(Ctx, LHSValue) || + !ABE->getRHS()->EvaluateAsRelocatable(Ctx, RHSValue)) + return false; + + // We only support a few operations on non-constant expressions, handle + // those first. + if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { + switch (ABE->getOpcode()) { + default: + return false; + case MCBinaryExpr::Sub: + // Negate RHS and add. + return EvaluateSymbolicAdd(LHSValue, + RHSValue.getSymB(), RHSValue.getSymA(), + -RHSValue.getConstant(), + Res); + + case MCBinaryExpr::Add: + return EvaluateSymbolicAdd(LHSValue, + RHSValue.getSymA(), RHSValue.getSymB(), + RHSValue.getConstant(), + Res); + } + } + + // 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). + int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); + int64_t Result = 0; + switch (ABE->getOpcode()) { + case MCBinaryExpr::Add: Result = LHS + RHS; break; + case MCBinaryExpr::And: Result = LHS & RHS; break; + case MCBinaryExpr::Div: Result = LHS / RHS; break; + case MCBinaryExpr::EQ: Result = LHS == RHS; break; + case MCBinaryExpr::GT: Result = LHS > RHS; break; + case MCBinaryExpr::GTE: Result = LHS >= RHS; break; + case MCBinaryExpr::LAnd: Result = LHS && RHS; break; + case MCBinaryExpr::LOr: Result = LHS || RHS; break; + case MCBinaryExpr::LT: Result = LHS < RHS; break; + case MCBinaryExpr::LTE: Result = LHS <= RHS; break; + case MCBinaryExpr::Mod: Result = LHS % RHS; break; + case MCBinaryExpr::Mul: Result = LHS * RHS; break; + case MCBinaryExpr::NE: Result = LHS != RHS; break; + case MCBinaryExpr::Or: Result = LHS | RHS; break; + case MCBinaryExpr::Shl: Result = LHS << RHS; break; + case MCBinaryExpr::Shr: Result = LHS >> RHS; break; + case MCBinaryExpr::Sub: Result = LHS - RHS; break; + case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; + } + + Res = MCValue::get(Result); + return true; + } + } +} + |