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