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 #include "ExprFunc.h"
18 #include "ExprFuncX.h"
19 #include "Interpreter.h"
20 #include "ExprNode.h"
21 #include <cstdio>
22 
23 namespace SeExpr2 {
EvalOp(int * opData,double * fp,char ** c,std::vector<int> & callStack)24 int ExprFuncSimple::EvalOp(int *opData, double *fp, char **c, std::vector<int> &callStack) {
25     ExprFuncSimple *simple = reinterpret_cast<ExprFuncSimple *>(c[opData[0]]);
26     //    ExprFuncNode::Data* simpleData=reinterpret_cast<ExprFuncNode::Data*>(c[opData[1]]);
27     ArgHandle args(opData, fp, c, callStack);
28     simple->eval(args);
29     return 1;
30 }
31 
buildInterpreter(const ExprFuncNode * node,Interpreter * interpreter) const32 int ExprFuncSimple::buildInterpreter(const ExprFuncNode *node, Interpreter *interpreter) const {
33     std::vector<int> operands;
34     for (int c = 0; c < node->numChildren(); c++) {
35         int operand = node->child(c)->buildInterpreter(interpreter);
36 #if 0
37         // debug
38         std::cerr<<"we are "<<node->promote(c)<<" "<<c<<std::endl;
39 #endif
40         if (node->promote(c) != 0) {
41             interpreter->addOp(getTemplatizedOp<Promote>(node->promote(c)));
42             int promotedOperand = interpreter->allocFP(node->promote(c));
43             interpreter->addOperand(operand);
44             interpreter->addOperand(promotedOperand);
45             operand = promotedOperand;
46             interpreter->endOp();
47         }
48         operands.push_back(operand);
49     }
50     int outoperand = -1;
51     int nargsData = interpreter->allocFP(1);
52     interpreter->d[nargsData] = node->numChildren();
53     if (node->type().isFP())
54         outoperand = interpreter->allocFP(node->type().dim());
55     else if (node->type().isString())
56         outoperand = interpreter->allocPtr();
57     else
58         assert(false);
59 
60     interpreter->addOp(EvalOp);
61     int ptrLoc = interpreter->allocPtr();
62     int ptrDataLoc = interpreter->allocPtr();
63     interpreter->s[ptrLoc] = (char *)this;
64     interpreter->addOperand(ptrLoc);
65     interpreter->addOperand(ptrDataLoc);
66     interpreter->addOperand(outoperand);
67     interpreter->addOperand(nargsData);
68     for (size_t c = 0; c < operands.size(); c++) {
69         interpreter->addOperand(operands[c]);
70     }
71     interpreter->endOp(false);  // do not eval because the function may not be evaluatable!
72 
73     // call into interpreter eval
74     int pc = interpreter->nextPC() - 1;
75     int *opCurr = (&interpreter->opData[0]) + interpreter->ops[pc].second;
76 
77     ArgHandle args(opCurr, &interpreter->d[0], &interpreter->s[0], interpreter->callStack);
78     ExprFuncNode::Data* data = evalConstant(node, args);
79     node->setData(data);
80     interpreter->s[ptrDataLoc] = reinterpret_cast<char *>(data);
81 
82     return outoperand;
83 }
84 }
85 
86 extern "C" {
87 //            allocate int[4+number of args];
88 //            allocate char*[2];
89 //            allocate double[1+ sizeof(ret) + sizeof(args)]
90 //
91 //            int[0]= c , 0
92 //            int[1]= c , 1
93 //            int[2]= f,  0
94 //            int[3]= f,  8
95 //
96 //            int[4]= f, 8
97 //            int[5]= f, 9
98 //
99 //
100 //                    double[0] = 0
101 //                    double[1] = 0
102 //                    double[2] = 0
103 //                    double[3] = 0
104 // opData indexes either into f or into c.
105 // opdata[0] points to ExprFuncSimple instance
106 // opdata[1] points to the data generated by evalConstant
107 // opdata[2] points to return value
108 // opdata[3] points to number of args
109 // opdata[4] points to beginning of arguments in
SeExpr2LLVMEvalCustomFunction(int * opDataArg,double * fpArg,char ** strArg,void ** funcdata,const SeExpr2::ExprFuncNode * node)110 void SeExpr2LLVMEvalCustomFunction(int *opDataArg,
111                                    double *fpArg,
112                                    char **strArg,
113                                    void **funcdata,
114                                    const SeExpr2::ExprFuncNode *node) {
115     const SeExpr2::ExprFunc *func = node->func();
116     SeExpr2::ExprFuncX *funcX = const_cast<SeExpr2::ExprFuncX *>(func->funcx());
117     SeExpr2::ExprFuncSimple *funcSimple = static_cast<SeExpr2::ExprFuncSimple *>(funcX);
118 
119     strArg[0] = reinterpret_cast<char *>(funcSimple);
120 
121     std::vector<int> callStack;
122     SeExpr2::ExprFuncSimple::ArgHandle handle(opDataArg, fpArg, strArg, callStack);
123     if (!*funcdata) {
124         handle.data = funcSimple->evalConstant(node, handle);
125         *funcdata = reinterpret_cast<void *>(handle.data);
126         node->setData(handle.data);
127     } else {
128         handle.data = reinterpret_cast<SeExpr2::ExprFuncNode::Data *>(*funcdata);
129     }
130 
131     funcSimple->eval(handle);
132     // for (int i = 0; i < retSize; ++i) result[i] = fp[1 + i];
133 }
134 }
135