MC: Improve expression parsing and implement evaluation of absolute expressions
(missed files).


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74450 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/llvm-mc/AsmExpr.cpp b/tools/llvm-mc/AsmExpr.cpp
new file mode 100644
index 0000000..7e4baf8
--- /dev/null
+++ b/tools/llvm-mc/AsmExpr.cpp
@@ -0,0 +1,92 @@
+//===- AsmExpr.cpp - Assembly file expressions ----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AsmExpr.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCValue.h"
+using namespace llvm;
+
+AsmExpr::~AsmExpr() {
+}
+
+bool AsmExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
+  switch (getKind()) {
+  default:
+    assert(0 && "Invalid assembly expression kind!");
+
+  case Constant:
+    Res = 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();
+    return true;
+  }
+
+  case Unary: {
+    const AsmUnaryExpr *AUE = cast<AsmUnaryExpr>(this);
+    int64_t Value;
+
+    if (!AUE->getSubExpr()->EvaluateAsAbsolute(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;
+    }
+
+    return true;
+  }
+
+  case Binary: {
+    const AsmBinaryExpr *ABE = cast<AsmBinaryExpr>(this);
+    int64_t LHS, RHS;
+    
+    if (!ABE->getLHS()->EvaluateAsAbsolute(Ctx, LHS) ||
+        !ABE->getRHS()->EvaluateAsAbsolute(Ctx, RHS))
+      return false;
+
+    // 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).
+    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;
+    }
+
+    return true;
+  }
+  }
+}
+