MC: Improve expression parsing and implement evaluation of absolute expressions
authorDaniel Dunbar <daniel@zuster.org>
Mon, 29 Jun 2009 20:40:36 +0000 (20:40 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Mon, 29 Jun 2009 20:40:36 +0000 (20:40 +0000)
(missed files).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74450 91177308-0d34-0410-b5e6-96231b3b80d8

tools/llvm-mc/AsmExpr.cpp [new file with mode: 0644]
tools/llvm-mc/AsmExpr.h [new file with mode: 0644]

diff --git a/tools/llvm-mc/AsmExpr.cpp b/tools/llvm-mc/AsmExpr.cpp
new file mode 100644 (file)
index 0000000..7e4baf8
--- /dev/null
@@ -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;
+  }
+  }
+}
+
diff --git a/tools/llvm-mc/AsmExpr.h b/tools/llvm-mc/AsmExpr.h
new file mode 100644 (file)
index 0000000..be26b46
--- /dev/null
@@ -0,0 +1,157 @@
+//===- AsmExpr.h - Assembly file expressions --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ASMEXPR_H
+#define ASMEXPR_H
+
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+class MCContext;
+class MCSymbol;
+
+class AsmExpr {
+public:
+  enum AsmExprKind {
+    Binary,    /// Binary expressions.
+    Constant,  /// Constant expressions.
+    SymbolRef, /// References to labels and assigned expressions.
+    Unary      /// Unary expressions.
+  };
+  
+private:
+  AsmExprKind Kind;
+  
+protected:
+  AsmExpr(AsmExprKind _Kind) : Kind(_Kind) {}
+  
+public:
+  virtual ~AsmExpr();
+
+  AsmExprKind getKind() const { return Kind; }
+
+  /// EvaluateAsAbsolute - Try to evaluate the expression to an absolute value.
+  ///
+  /// @param Res - The absolute value if evaluation succeeds.
+  /// @result - True on success.
+  bool EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const;
+
+  static bool classof(const AsmExpr *) { return true; }
+};
+
+class AsmConstantExpr : public AsmExpr {
+  int64_t Value;
+
+public:
+  AsmConstantExpr(int64_t _Value) 
+    : AsmExpr(AsmExpr::Constant), Value(_Value) {}
+  
+  int64_t getValue() const { return Value; }
+
+  static bool classof(const AsmExpr *E) { 
+    return E->getKind() == AsmExpr::Constant; 
+  }
+  static bool classof(const AsmConstantExpr *) { return true; }
+};
+
+class AsmSymbolRefExpr : public AsmExpr {
+  MCSymbol *Symbol;
+
+public:
+  AsmSymbolRefExpr(MCSymbol *_Symbol) 
+    : AsmExpr(AsmExpr::SymbolRef), Symbol(_Symbol) {}
+  
+  MCSymbol *getSymbol() const { return Symbol; }
+
+  static bool classof(const AsmExpr *E) { 
+    return E->getKind() == AsmExpr::SymbolRef; 
+  }
+  static bool classof(const AsmSymbolRefExpr *) { return true; }
+};
+
+class AsmUnaryExpr : public AsmExpr {
+public:
+  enum Opcode {
+    LNot,  /// Logical negation.
+    Minus, /// Unary minus.
+    Not,   /// Bit-wise negation.
+    Plus   /// Unary plus.
+  };
+
+private:
+  Opcode Op;
+  AsmExpr *Expr;
+
+public:
+  AsmUnaryExpr(Opcode _Op, AsmExpr *_Expr)
+    : AsmExpr(AsmExpr::Unary), Op(_Op), Expr(_Expr) {}
+  ~AsmUnaryExpr() {
+    delete Expr;
+  }
+
+  Opcode getOpcode() const { return Op; }
+
+  AsmExpr *getSubExpr() const { return Expr; }
+
+  static bool classof(const AsmExpr *E) { 
+    return E->getKind() == AsmExpr::Unary; 
+  }
+  static bool classof(const AsmUnaryExpr *) { return true; }
+};
+
+class AsmBinaryExpr : public AsmExpr {
+public:
+  enum Opcode {
+    Add,  /// Addition.
+    And,  /// Bitwise and.
+    Div,  /// Division.
+    EQ,   /// Equality comparison.
+    GT,   /// Greater than comparison.
+    GTE,  /// Greater than or equal comparison.
+    LAnd, /// Logical and.
+    LOr,  /// Logical or.
+    LT,   /// Less than comparison.
+    LTE,  /// Less than or equal comparison.
+    Mod,  /// Modulus.
+    Mul,  /// Multiplication.
+    NE,   /// Inequality comparison.
+    Or,   /// Bitwise or.
+    Shl,  /// Bitwise shift left.
+    Shr,  /// Bitwise shift right.
+    Sub,  /// Subtraction.
+    Xor   /// Bitwise exclusive or.
+  };
+
+private:
+  Opcode Op;
+  AsmExpr *LHS, *RHS;
+
+public:
+  AsmBinaryExpr(Opcode _Op, AsmExpr *_LHS, AsmExpr *_RHS)
+    : AsmExpr(AsmExpr::Binary), Op(_Op), LHS(_LHS), RHS(_RHS) {}
+  ~AsmBinaryExpr() {
+    delete LHS;
+    delete RHS;
+  }
+
+  Opcode getOpcode() const { return Op; }
+
+  AsmExpr *getLHS() const { return LHS; }
+  AsmExpr *getRHS() const { return RHS; }
+
+  static bool classof(const AsmExpr *E) { 
+    return E->getKind() == AsmExpr::Binary; 
+  }
+  static bool classof(const AsmBinaryExpr *) { return true; }
+};
+
+} // end namespace llvm
+
+#endif