Home | History | Annotate | Download | only in Script
      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