aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-06-30 01:49:52 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-06-30 01:49:52 +0000
commit15d170709608e2f1efcada74c297c10c8c71fdcf (patch)
treefb8cb7f88ebf927bad158feab87b50974bbafacb /tools
parent9b27622ecb00a4e4b23fe501d11f344c7b9ba7ed (diff)
downloadexternal_llvm-15d170709608e2f1efcada74c297c10c8c71fdcf.zip
external_llvm-15d170709608e2f1efcada74c297c10c8c71fdcf.tar.gz
external_llvm-15d170709608e2f1efcada74c297c10c8c71fdcf.tar.bz2
llvm-mc: Evaluation for relocatable expressions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74496 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r--tools/llvm-mc/AsmExpr.cpp133
-rw-r--r--tools/llvm-mc/AsmExpr.h10
-rw-r--r--tools/llvm-mc/AsmParser.cpp12
-rw-r--r--tools/llvm-mc/AsmParser.h17
4 files changed, 132 insertions, 40 deletions
diff --git a/tools/llvm-mc/AsmExpr.cpp b/tools/llvm-mc/AsmExpr.cpp
index 7e4baf8..ffc09eb 100644
--- a/tools/llvm-mc/AsmExpr.cpp
+++ b/tools/llvm-mc/AsmExpr.cpp
@@ -9,6 +9,7 @@
#include "AsmExpr.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
using namespace llvm;
@@ -16,38 +17,61 @@ AsmExpr::~AsmExpr() {
}
bool AsmExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
+ MCValue Value;
+
+ if (!EvaluateAsRelocatable(Ctx, Value) || !Value.isConstant())
+ return false;
+
+ Res = Value.getConstant();
+ return true;
+}
+
+bool AsmExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const {
switch (getKind()) {
default:
assert(0 && "Invalid assembly expression kind!");
case Constant:
- Res = cast<AsmConstantExpr>(this)->getValue();
+ Res = MCValue::get(cast<AsmConstantExpr>(this)->getValue());
return true;
case SymbolRef: {
MCSymbol *Sym = cast<AsmSymbolRefExpr>(this)->getSymbol();
- const MCValue *Value = Ctx.GetSymbolValue(Sym);
-
- // FIXME: Return more information about the failure.
- if (!Value || !Value->isConstant())
- return false;
-
- Res = Value->getConstant();
+ if (const MCValue *Value = Ctx.GetSymbolValue(Sym))
+ Res = *Value;
+ else
+ Res = MCValue::get(Sym, 0, 0);
return true;
}
case Unary: {
const AsmUnaryExpr *AUE = cast<AsmUnaryExpr>(this);
- int64_t Value;
+ MCValue Value;
- if (!AUE->getSubExpr()->EvaluateAsAbsolute(Ctx, Value))
+ if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value))
return false;
switch (AUE->getOpcode()) {
- case AsmUnaryExpr::LNot: Res = !Value; break;
- case AsmUnaryExpr::Minus: Res = -Value; break;
- case AsmUnaryExpr::Not: Res = ~Value; break;
- case AsmUnaryExpr::Plus: Res = +Value; break;
+ case AsmUnaryExpr::LNot:
+ if (!Value.isConstant())
+ return false;
+ Res = MCValue::get(!Value.getConstant());
+ break;
+ case AsmUnaryExpr::Minus:
+ /// -(a - b + const) ==> (b - a - const)
+ if (Value.getSymA() && !Value.getSymA())
+ return false;
+ Res = MCValue::get(Value.getSymB(), Value.getSymA(),
+ -Value.getConstant());
+ break;
+ case AsmUnaryExpr::Not:
+ if (!Value.isConstant())
+ return false;
+ Res = MCValue::get(~Value.getConstant());
+ break;
+ case AsmUnaryExpr::Plus:
+ Res = Value;
+ break;
}
return true;
@@ -55,36 +79,75 @@ bool AsmExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
case Binary: {
const AsmBinaryExpr *ABE = cast<AsmBinaryExpr>(this);
- int64_t LHS, RHS;
+ MCValue LHSValue, RHSValue;
- if (!ABE->getLHS()->EvaluateAsAbsolute(Ctx, LHS) ||
- !ABE->getRHS()->EvaluateAsAbsolute(Ctx, RHS))
+ 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.isConstant() || !RHSValue.isConstant()) {
+ switch (ABE->getOpcode()) {
+ default:
+ return false;
+ case AsmBinaryExpr::Sub:
+ // Negate RHS and fall through.
+ RHSValue = MCValue::get(RHSValue.getSymB(), RHSValue.getSymA(),
+ -RHSValue.getConstant());
+ case AsmBinaryExpr::Add:
+ // (a_0 - b_0 + cst_0) + (a_1 - b_1 + cst_1)
+
+ // We can't add or subtract two symbols.
+ if ((LHSValue.getSymA() && RHSValue.getSymB()) ||
+ (LHSValue.getSymB() && RHSValue.getSymB()))
+ return false;
+
+ MCSymbol *A =
+ LHSValue.getSymA() ? LHSValue.getSymA() : RHSValue.getSymA();
+ MCSymbol *B =
+ LHSValue.getSymB() ? LHSValue.getSymB() : RHSValue.getSymB();
+ if (B) {
+ // If we have a negated symbol, then we must have also have a
+ // non-negated symbol, and both symbols must be in the same
+ // non-external section. 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 || !A->getSection() || A->getSection() != B->getSection())
+ return false;
+ }
+ Res = MCValue::get(A, B,
+ LHSValue.getConstant() + RHSValue.getConstant());
+ return true;
+ }
+ }
+
// 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 Result, LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
switch (ABE->getOpcode()) {
- case AsmBinaryExpr::Add: Res = LHS + RHS; break;
- case AsmBinaryExpr::And: Res = LHS & RHS; break;
- case AsmBinaryExpr::Div: Res = LHS / RHS; break;
- case AsmBinaryExpr::EQ: Res = LHS == RHS; break;
- case AsmBinaryExpr::GT: Res = LHS > RHS; break;
- case AsmBinaryExpr::GTE: Res = LHS >= RHS; break;
- case AsmBinaryExpr::LAnd: Res = LHS && RHS; break;
- case AsmBinaryExpr::LOr: Res = LHS || RHS; break;
- case AsmBinaryExpr::LT: Res = LHS < RHS; break;
- case AsmBinaryExpr::LTE: Res = LHS <= RHS; break;
- case AsmBinaryExpr::Mod: Res = LHS % RHS; break;
- case AsmBinaryExpr::Mul: Res = LHS * RHS; break;
- case AsmBinaryExpr::NE: Res = LHS != RHS; break;
- case AsmBinaryExpr::Or: Res = LHS | RHS; break;
- case AsmBinaryExpr::Shl: Res = LHS << RHS; break;
- case AsmBinaryExpr::Shr: Res = LHS >> RHS; break;
- case AsmBinaryExpr::Sub: Res = LHS - RHS; break;
- case AsmBinaryExpr::Xor: Res = LHS ^ RHS; break;
+ case AsmBinaryExpr::Add: Result = LHS + RHS; break;
+ case AsmBinaryExpr::And: Result = LHS & RHS; break;
+ case AsmBinaryExpr::Div: Result = LHS / RHS; break;
+ case AsmBinaryExpr::EQ: Result = LHS == RHS; break;
+ case AsmBinaryExpr::GT: Result = LHS > RHS; break;
+ case AsmBinaryExpr::GTE: Result = LHS >= RHS; break;
+ case AsmBinaryExpr::LAnd: Result = LHS && RHS; break;
+ case AsmBinaryExpr::LOr: Result = LHS || RHS; break;
+ case AsmBinaryExpr::LT: Result = LHS < RHS; break;
+ case AsmBinaryExpr::LTE: Result = LHS <= RHS; break;
+ case AsmBinaryExpr::Mod: Result = LHS % RHS; break;
+ case AsmBinaryExpr::Mul: Result = LHS * RHS; break;
+ case AsmBinaryExpr::NE: Result = LHS != RHS; break;
+ case AsmBinaryExpr::Or: Result = LHS | RHS; break;
+ case AsmBinaryExpr::Shl: Result = LHS << RHS; break;
+ case AsmBinaryExpr::Shr: Result = LHS >> RHS; break;
+ case AsmBinaryExpr::Sub: Result = LHS - RHS; break;
+ case AsmBinaryExpr::Xor: Result = LHS ^ RHS; break;
}
+ Res = MCValue::get(Result);
return true;
}
}
diff --git a/tools/llvm-mc/AsmExpr.h b/tools/llvm-mc/AsmExpr.h
index be26b46..e8650e4 100644
--- a/tools/llvm-mc/AsmExpr.h
+++ b/tools/llvm-mc/AsmExpr.h
@@ -16,6 +16,7 @@
namespace llvm {
class MCContext;
class MCSymbol;
+class MCValue;
class AsmExpr {
public:
@@ -39,10 +40,17 @@ public:
/// EvaluateAsAbsolute - Try to evaluate the expression to an absolute value.
///
- /// @param Res - The absolute value if evaluation succeeds.
+ /// @param Res - The absolute value, if evaluation succeeds.
/// @result - True on success.
bool EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const;
+ /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable
+ /// value.
+ ///
+ /// @param Res - The relocatable value, if evaluation succeeds.
+ /// @result - True on success.
+ bool EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const;
+
static bool classof(const AsmExpr *) { return true; }
};
diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp
index 9414f99..9330728 100644
--- a/tools/llvm-mc/AsmParser.cpp
+++ b/tools/llvm-mc/AsmParser.cpp
@@ -153,6 +153,18 @@ bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
return false;
}
+bool AsmParser::ParseRelocatableExpression(MCValue &Res) {
+ AsmExpr *Expr;
+
+ if (ParseExpression(Expr))
+ return true;
+
+ if (!Expr->EvaluateAsRelocatable(Ctx, Res))
+ return TokError("expected relocatable expression");
+
+ return false;
+}
+
static unsigned getBinOpPrecedence(asmtok::TokKind K,
AsmBinaryExpr::Opcode &Kind) {
switch (K) {
diff --git a/tools/llvm-mc/AsmParser.h b/tools/llvm-mc/AsmParser.h
index 8cd40eb..3a812c3 100644
--- a/tools/llvm-mc/AsmParser.h
+++ b/tools/llvm-mc/AsmParser.h
@@ -22,7 +22,8 @@ class AsmExpr;
class MCContext;
class MCInst;
class MCStreamer;
-
+class MCValue;
+
class AsmParser {
AsmLexer Lexer;
MCContext &Ctx;
@@ -53,15 +54,23 @@ private:
/// @param Res - The resulting expression. The pointer value is null on error.
/// @result - False on success.
bool ParseExpression(AsmExpr *&Res);
-
- /// ParseAbsoluteExpr - Parse an expression which must evaluate to an absolute
- /// value.
+
+ /// ParseAbsoluteExpression - Parse an expression which must evaluate to an
+ /// absolute value.
///
/// @param Res - The value of the absolute expression. The result is undefined
/// on error.
/// @result - False on success.
bool ParseAbsoluteExpression(int64_t &Res);
+ /// ParseRelocatableExpression - Parse an expression which must be
+ /// relocatable.
+ ///
+ /// @param Res - The relocatable expression value. The result is undefined on
+ /// error.
+ /// @result - False on success.
+ bool ParseRelocatableExpression(MCValue &Res);
+
bool ParsePrimaryExpr(AsmExpr *&Res);
bool ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res);
bool ParseParenExpr(AsmExpr *&Res);