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