//===- RpnEvaluator.cpp ---------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "mcld/Script/RpnEvaluator.h" #include "mcld/LD/LDSymbol.h" #include "mcld/Script/ExprToken.h" #include "mcld/Script/Operand.h" #include "mcld/Script/Operator.h" #include "mcld/Script/RpnExpr.h" #include "mcld/Support/MsgHandling.h" #include "mcld/Module.h" #include <llvm/Support/Casting.h> #include <llvm/Support/DataTypes.h> #include <stack> #include <cassert> namespace mcld { RpnEvaluator::RpnEvaluator(const Module& pModule, const TargetLDBackend& pBackend) : m_Module(pModule), m_Backend(pBackend) { } bool RpnEvaluator::eval(const RpnExpr& pExpr, uint64_t& pResult) { std::stack<Operand*> operandStack; for (RpnExpr::const_iterator it = pExpr.begin(), ie = pExpr.end(); it != ie; ++it) { switch ((*it)->kind()) { case ExprToken::OPERATOR: { Operator* op = llvm::cast<Operator>(*it); switch (op->arity()) { case Operator::NULLARY: { operandStack.push(op->eval(m_Module, m_Backend)); break; } case Operator::UNARY: { Operand* opd = operandStack.top(); operandStack.pop(); op->appendOperand(opd); operandStack.push(op->eval(m_Module, m_Backend)); break; } case Operator::BINARY: { Operand* opd2 = operandStack.top(); operandStack.pop(); Operand* opd1 = operandStack.top(); operandStack.pop(); op->appendOperand(opd1); op->appendOperand(opd2); operandStack.push(op->eval(m_Module, m_Backend)); break; } case Operator::TERNARY: { Operand* opd3 = operandStack.top(); operandStack.pop(); Operand* opd2 = operandStack.top(); operandStack.pop(); Operand* opd1 = operandStack.top(); operandStack.pop(); op->appendOperand(opd1); op->appendOperand(opd2); op->appendOperand(opd3); operandStack.push(op->eval(m_Module, m_Backend)); break; } } // end of switch operator arity break; } case ExprToken::OPERAND: { Operand* opd = llvm::cast<Operand>(*it); switch (opd->type()) { case Operand::SYMBOL: { // It's possible that there are no operators in an expression, so // we set up symbol operand here. if (!opd->isDot()) { SymOperand* sym_opd = llvm::cast<SymOperand>(opd); const LDSymbol* symbol = m_Module.getNamePool().findSymbol(sym_opd->name()); if (symbol == NULL) { fatal(diag::fail_sym_resolution) << __FILE__ << __LINE__ << "mclinker@googlegroups.com"; } sym_opd->setValue(symbol->value()); } operandStack.push(opd); break; } default: operandStack.push(opd); break; } // end of switch operand type break; } } // end of switch } // end of for // stack top is result assert(operandStack.top()->type() == Operand::SYMBOL || operandStack.top()->type() == Operand::INTEGER || operandStack.top()->type() == Operand::FRAGMENT); pResult = operandStack.top()->value(); return true; } } // namespace mcld