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