1 //===- RpnEvaluator.cpp ---------------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include "mcld/Script/RpnEvaluator.h" 10 11 #include "mcld/LD/LDSymbol.h" 12 #include "mcld/Script/ExprToken.h" 13 #include "mcld/Script/Operand.h" 14 #include "mcld/Script/Operator.h" 15 #include "mcld/Script/RpnExpr.h" 16 #include "mcld/Support/MsgHandling.h" 17 #include "mcld/Module.h" 18 19 #include <llvm/Support/Casting.h> 20 #include <llvm/Support/DataTypes.h> 21 22 #include <stack> 23 24 #include <cassert> 25 26 namespace mcld { 27 28 RpnEvaluator::RpnEvaluator(const Module& pModule, 29 const TargetLDBackend& pBackend) 30 : m_Module(pModule), m_Backend(pBackend) { 31 } 32 33 bool RpnEvaluator::eval(const RpnExpr& pExpr, uint64_t& pResult) { 34 std::stack<Operand*> operandStack; 35 for (RpnExpr::const_iterator it = pExpr.begin(), ie = pExpr.end(); it != ie; 36 ++it) { 37 switch ((*it)->kind()) { 38 case ExprToken::OPERATOR: { 39 Operator* op = llvm::cast<Operator>(*it); 40 switch (op->arity()) { 41 case Operator::NULLARY: { 42 operandStack.push(op->eval(m_Module, m_Backend)); 43 break; 44 } 45 case Operator::UNARY: { 46 Operand* opd = operandStack.top(); 47 operandStack.pop(); 48 op->appendOperand(opd); 49 operandStack.push(op->eval(m_Module, m_Backend)); 50 break; 51 } 52 case Operator::BINARY: { 53 Operand* opd2 = operandStack.top(); 54 operandStack.pop(); 55 Operand* opd1 = operandStack.top(); 56 operandStack.pop(); 57 op->appendOperand(opd1); 58 op->appendOperand(opd2); 59 operandStack.push(op->eval(m_Module, m_Backend)); 60 break; 61 } 62 case Operator::TERNARY: { 63 Operand* opd3 = operandStack.top(); 64 operandStack.pop(); 65 Operand* opd2 = operandStack.top(); 66 operandStack.pop(); 67 Operand* opd1 = operandStack.top(); 68 operandStack.pop(); 69 op->appendOperand(opd1); 70 op->appendOperand(opd2); 71 op->appendOperand(opd3); 72 operandStack.push(op->eval(m_Module, m_Backend)); 73 break; 74 } 75 } // end of switch operator arity 76 break; 77 } 78 79 case ExprToken::OPERAND: { 80 Operand* opd = llvm::cast<Operand>(*it); 81 switch (opd->type()) { 82 case Operand::SYMBOL: { 83 // It's possible that there are no operators in an expression, so 84 // we set up symbol operand here. 85 if (!opd->isDot()) { 86 SymOperand* sym_opd = llvm::cast<SymOperand>(opd); 87 const LDSymbol* symbol = 88 m_Module.getNamePool().findSymbol(sym_opd->name()); 89 if (symbol == NULL) { 90 fatal(diag::fail_sym_resolution) << __FILE__ << __LINE__ 91 << "mclinker (at) googlegroups.com"; 92 } 93 sym_opd->setValue(symbol->value()); 94 } 95 operandStack.push(opd); 96 break; 97 } 98 default: 99 operandStack.push(opd); 100 break; 101 } // end of switch operand type 102 break; 103 } 104 } // end of switch 105 } // end of for 106 107 // stack top is result 108 assert(operandStack.top()->type() == Operand::SYMBOL || 109 operandStack.top()->type() == Operand::INTEGER || 110 operandStack.top()->type() == Operand::FRAGMENT); 111 pResult = operandStack.top()->value(); 112 return true; 113 } 114 115 } // namespace mcld 116