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