1f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===- RpnEvaluator.cpp ---------------------------------------------------===//
2f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//
3f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//                     The MCLinker Project
4f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//
5f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// This file is distributed under the University of Illinois Open Source
6f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// License. See LICENSE.TXT for details.
7f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//
8f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
9f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Support/MsgHandling.h>
10f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/LD/LDSymbol.h>
11f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/RpnExpr.h>
12f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/RpnEvaluator.h>
13f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/ExprToken.h>
14f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/Operator.h>
15f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/Operand.h>
16f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Module.h>
17f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/Support/Casting.h>
18f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/Support/DataTypes.h>
19f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <stack>
20f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <cassert>
21f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
22f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesusing namespace mcld;
23f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
24f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesRpnEvaluator::RpnEvaluator(const Module& pModule,
25f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                           const TargetLDBackend& pBackend)
26f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  : m_Module(pModule),
27f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    m_Backend(pBackend)
28f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
29f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
30f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
31f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool RpnEvaluator::eval(const RpnExpr& pExpr, uint64_t& pResult)
32f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
33f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  std::stack<Operand*> operandStack;
34f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (RpnExpr::const_iterator it = pExpr.begin(), ie = pExpr.end(); it != ie;
35f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    ++it) {
36f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    switch((*it)->kind()) {
37f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    case ExprToken::OPERATOR: {
38f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      Operator* op = llvm::cast<Operator>(*it);
39f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      switch (op->arity()) {
40f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      case Operator::NULLARY: {
41f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        operandStack.push(op->eval(m_Module, m_Backend));
42f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        break;
43f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
44f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      case Operator::UNARY: {
45f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        Operand* opd = operandStack.top();
46f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        operandStack.pop();
47f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        op->appendOperand(opd);
48f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        operandStack.push(op->eval(m_Module, m_Backend));
49f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        break;
50f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
51f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      case Operator::BINARY: {
52f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        Operand* opd2 = operandStack.top();
53f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        operandStack.pop();
54f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        Operand* opd1 = operandStack.top();
55f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        operandStack.pop();
56f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        op->appendOperand(opd1);
57f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        op->appendOperand(opd2);
58f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        operandStack.push(op->eval(m_Module, m_Backend));
59f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        break;
60f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
61f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      case Operator::TERNARY: {
62f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        Operand* opd3 = operandStack.top();
63f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        operandStack.pop();
64f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        Operand* opd2 = operandStack.top();
65f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        operandStack.pop();
66f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        Operand* opd1 = operandStack.top();
67f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        operandStack.pop();
68f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        op->appendOperand(opd1);
69f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        op->appendOperand(opd2);
70f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        op->appendOperand(opd3);
71f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        operandStack.push(op->eval(m_Module, m_Backend));
72f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        break;
73f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
74f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      } // end of switch operator arity
75f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      break;
76f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
77f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
78f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    case ExprToken::OPERAND: {
79f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      Operand* opd = llvm::cast<Operand>(*it);
80f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      switch (opd->type()) {
81f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      case Operand::SYMBOL: {
82f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // It's possible that there are no operators in an expression, so
83f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // we set up symbol operand here.
84f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (!opd->isDot()) {
85f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          SymOperand* sym_opd = llvm::cast<SymOperand>(opd);
86f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          const LDSymbol* symbol =
87f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines            m_Module.getNamePool().findSymbol(sym_opd->name());
88f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          if (symbol == NULL) {
89f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines            fatal(diag::fail_sym_resolution) << __FILE__ << __LINE__
90f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                             << "mclinker@googlegroups.com";
91f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          }
92f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          sym_opd->setValue(symbol->value());
93f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        }
94f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        operandStack.push(opd);
95f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        break;
96f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
97f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      default:
98f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        operandStack.push(opd);
99f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        break;
100f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      } // end of switch operand type
101f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      break;
102f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
103f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
104f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    } // end of switch
105f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  } // end of for
106f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
107f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // stack top is result
108f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  assert(operandStack.top()->type() == Operand::SYMBOL ||
109f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines         operandStack.top()->type() == Operand::INTEGER ||
110f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines         operandStack.top()->type() == Operand::FRAGMENT);
111f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  pResult = operandStack.top()->value();
112f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  return true;
113f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
114f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
115