diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-06-29 20:40:36 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-06-29 20:40:36 +0000 |
commit | a1f046427f7e58cc67c0b4b1764750e0585cfd30 (patch) | |
tree | c65fc02fcf69a914844c44f63bb122a11f95e57e /tools/llvm-mc | |
parent | f97a05a660127943c74fa508a1acda357bb20cec (diff) | |
download | external_llvm-a1f046427f7e58cc67c0b4b1764750e0585cfd30.zip external_llvm-a1f046427f7e58cc67c0b4b1764750e0585cfd30.tar.gz external_llvm-a1f046427f7e58cc67c0b4b1764750e0585cfd30.tar.bz2 |
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
Diffstat (limited to 'tools/llvm-mc')
-rw-r--r-- | tools/llvm-mc/AsmExpr.cpp | 92 | ||||
-rw-r--r-- | tools/llvm-mc/AsmExpr.h | 157 |
2 files changed, 249 insertions, 0 deletions
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; + } + } +} + diff --git a/tools/llvm-mc/AsmExpr.h b/tools/llvm-mc/AsmExpr.h new file mode 100644 index 0000000..be26b46 --- /dev/null +++ b/tools/llvm-mc/AsmExpr.h @@ -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 |