1 /*
2 Copyright Disney Enterprises, Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License
6 and the following modification to it: Section 6 Trademarks.
7 deleted and replaced with:
8
9 6. Trademarks. This License does not grant permission to use the
10 trade names, trademarks, service marks, or product names of the
11 Licensor and its affiliates, except as required for reproducing
12 the content of the NOTICE file.
13
14 You may obtain a copy of the License at
15 http://www.apache.org/licenses/LICENSE-2.0
16 */
17 #ifndef _Interpreter_h_
18 #define _Interpreter_h_
19
20 #include <vector>
21 #include <stack>
22
23 namespace SeExpr2 {
24 class ExprLocalVar;
25
26 //! Promotes a FP[1] to FP[d]
27 template <int d>
28 struct Promote {
29 // TODO: this needs a name that is prefixed by Se!
fPromote30 static int f(int* opData, double* fp, char** c, std::vector<int>& callStack) {
31 int posIn = opData[0];
32 int posOut = opData[1];
33 for (int k = posOut; k < posOut + d; k++) fp[k] = fp[posIn];
34 return 1;
35 }
36 };
37
38 /// Non-LLVM manual interpreter. This is a simple computation machine. There are no dynamic activation records
39 /// just fixed locations, because we have no recursion!
40 class Interpreter {
41 public:
42 /// Double data (constants and evaluated)
43 std::vector<double> d;
44 /// constant and evaluated pointer data
45 std::vector<char*> s;
46 /// Ooperands to op
47 std::vector<int> opData;
48
49 /// Not needed for eval only building
50 typedef std::map<const ExprLocalVar*, int> VarToLoc;
51 VarToLoc varToLoc;
52
53 /// Op function pointer arguments are (int* currOpData,double* currD,char** c,std::stack<int>& callStackurrS)
54 typedef int (*OpF)(int*, double*, char**, std::vector<int>&);
55
56 std::vector<std::pair<OpF, int> > ops;
57 std::vector<int> callStack;
58
59 private:
60 bool _startedOp;
61 int _pcStart;
62
63 public:
Interpreter()64 Interpreter() : _startedOp(false) {
65 s.push_back(nullptr); // reserved for double** of variable block
66 s.push_back(nullptr); // reserved for double** of variable block
67 }
68
69 /// Return the position that the next instruction will be placed at
nextPC()70 int nextPC() { return static_cast<int>(ops.size()); }
71
72 ///! adds an operator to the program (pointing to the data at the current location)
addOp(OpF op)73 int addOp(OpF op) {
74 if (_startedOp) {
75 assert(false && "addOp called within another addOp");
76 }
77 _startedOp = true;
78 int pc = static_cast<int>(ops.size());
79 ops.push_back(std::make_pair(op, static_cast<int>(opData.size())));
80 return pc;
81 }
82
83 void endOp(bool execute = true) {
84 _startedOp = false;
85 if (execute) {
86 double* fp = &d[0];
87 char** str = &s[0];
88 int pc = static_cast<int>(ops.size()) - 1;
89 const std::pair<OpF, int>& op = ops[pc];
90 int* opCurr = &opData[0] + op.second;
91 pc += op.first(opCurr, fp, str, callStack);
92 }
93 }
94
95 ///! Adds an operand. Note this should be done after doing the addOp!
addOperand(int param)96 int addOperand(int param) {
97 assert(_startedOp);
98 int ret = static_cast<int>(opData.size());
99 opData.push_back(param);
100 return ret;
101 }
102
103 ///! Allocate a floating point set of data of dimension n
allocFP(int n)104 int allocFP(int n) {
105 int ret = static_cast<int>(d.size());
106 for (int k = 0; k < n; k++) d.push_back(0);
107 return ret;
108 }
109
110 /// Allocate a pointer location (can be anything, but typically space for char*)
allocPtr()111 int allocPtr() {
112 int ret = static_cast<int>(s.size());
113 s.push_back(0);
114 return ret;
115 }
116
117 /// Evaluate program
118 void eval(VarBlock* varBlock, bool debug = false);
119 /// Debug by printing program
120 void print(int pc = -1) const;
121
setPCStart(int pcStart)122 void setPCStart(int pcStart) { _pcStart = pcStart; }
123 };
124
125 //! Return the function f encapsulated in class T for the dynamic i converted to a static d.
126 template <template <int d> class T, class T_FUNCTYPE = Interpreter::OpF>
getTemplatizedOp(int i)127 T_FUNCTYPE getTemplatizedOp(int i) {
128 switch (i) {
129 case 1:
130 return T<1>::f;
131 case 2:
132 return T<2>::f;
133 case 3:
134 return T<3>::f;
135 case 4:
136 return T<4>::f;
137 case 5:
138 return T<5>::f;
139 case 6:
140 return T<6>::f;
141 case 7:
142 return T<7>::f;
143 case 8:
144 return T<8>::f;
145 case 9:
146 return T<9>::f;
147 case 10:
148 return T<10>::f;
149 case 11:
150 return T<11>::f;
151 case 12:
152 return T<12>::f;
153 case 13:
154 return T<13>::f;
155 case 14:
156 return T<14>::f;
157 case 15:
158 return T<15>::f;
159 case 16:
160 return T<16>::f;
161 default:
162 assert(false && "Invalid dynamic parameter (not supported template)");
163 break;
164 }
165 return 0;
166 }
167 }
168
169 #endif
170