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 
RpnEvaluator(const Module & pModule,const TargetLDBackend & pBackend)28 RpnEvaluator::RpnEvaluator(const Module& pModule,
29                            const TargetLDBackend& pBackend)
30     : m_Module(pModule), m_Backend(pBackend) {
31 }
32 
eval(const RpnExpr & pExpr,uint64_t & pResult)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@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