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/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