33 double* fp =
d.data();
34 char** str =
s.data();
41 block->
d.resize(
d.size());
43 memcpy(fp,
d.data(),
d.size() *
sizeof(
double));
46 block->
s.resize(
s.size());
47 str = block->
s.data();
48 memcpy(str,
s.data(),
s.size() *
sizeof(
char*));
52 str[0] =
reinterpret_cast<char*
>(block->
data());
53 str[1] =
reinterpret_cast<char*
>(
static_cast<size_t>(block->
indirectIndex));
57 int end =
static_cast<int>(
ops.size());
60 std::cerr <<
"Running op at " << pc << std::endl;
63 const std::pair<OpF, int>& op =
ops[pc];
64 int* opCurr = &
opData[0] + op.second;
65 pc += op.first(opCurr, fp, str,
callStack);
70 std::cerr <<
"---- ops ----------------------" << std::endl;
71 for (
size_t i = 0; i <
ops.size(); i++) {
72 const char* name =
"";
75 if (dladdr((
void*)
ops[i].first, &info)) name = info.dli_sname;
77 fprintf(stderr,
"%s %s %p (", pc == (
int)i ?
"-->" :
" ", name,
ops[i].first);
78 int nextGuy = (i ==
ops.size() - 1 ?
static_cast<int>(
opData.size()) :
ops[i + 1].second);
79 for (
int k =
ops[i].second; k < nextGuy; k++) {
80 fprintf(stderr,
" %d",
opData[k]);
82 fprintf(stderr,
")\n");
84 std::cerr <<
"---- opdata ----------------------" << std::endl;
85 for (
size_t k = 0; k <
opData.size(); k++) {
86 std::cerr <<
"opData[" << k <<
"]= " <<
opData[k] << std::endl;
89 std::cerr <<
"----- fp --------------------------" << std::endl;
90 for (
size_t k = 0; k <
d.size(); k++) {
91 std::cerr <<
"fp[" << k <<
"]= " <<
d[k] << std::endl;
94 std::cerr <<
"---- str ----------------------" << std::endl;
95 std::cerr <<
"s[0] reserved for datablock = " <<
reinterpret_cast<size_t>(
s[0]) << std::endl;
96 std::cerr <<
"s[1] is indirectIndex = " <<
reinterpret_cast<size_t>(
s[1]) << std::endl;
97 for (
size_t k = 2; k <
s.size(); k++) {
98 std::cerr <<
"s[" << k <<
"]= 0x" <<
s[k];
99 if (
s[k]) std::cerr <<
" '" <<
s[k][0] <<
s[k][1] <<
s[k][2] <<
s[k][3] <<
"...'";
100 std::cerr << std::endl;
110 template <
char c,
template <
char c1,
int d>
class T>
146 assert(
false &&
"Invalid dynamic parameter (not supported template)");
155 struct BinaryStringOp {
156 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
158 char*& out = *(
char**)c[opData[0]];
159 char* in1 = c[opData[1]];
160 char* in2 = c[opData[2]];
165 int len1 =
static_cast<int>(strlen(in1));
166 int len2 =
static_cast<int>(strlen(in2));
167 if (out == 0 || len1 + len2 + 1 > strlen(out))
170 out =
new char [len1 + len2 + 1];
174 memset(out, 0, len1 + len2 + 1);
178 strcat(out + len1, in2);
179 out[len1 + len2] =
'\0';
189 template <
char op,
int d>
191 static double niceMod(
double a,
double b) {
192 if (
b == 0)
return 0;
193 return a - floor(
a /
b) *
b;
196 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
197 double* in1 = fp + opData[0];
198 double* in2 = fp + opData[1];
199 double* out = fp + opData[2];
201 for (
int k = 0; k < d; k++) {
204 *out = (*in1) + (*in2);
207 *out = (*in1) - (*in2);
210 *out = (*in1) * (*in2);
213 *out = (*in1) / (*in2);
216 *out = niceMod(*in1, *in2);
219 *out =
pow(*in1, *in2);
223 *out = (*in1) < (*in2);
226 *out = (*in1) > (*in2);
229 *out = (*in1) <= (*in2);
232 *out = (*in1) >= (*in2);
235 *out = (*in1) && (*in2);
238 *out = (*in1) || (*in2);
252 template <
char op,
int d>
254 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
255 double* in = fp + opData[0];
256 double* out = fp + opData[1];
257 for (
int k = 0; k < d; k++) {
281 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
282 int tuple = opData[0];
283 int subscript = int(fp[opData[1]]);
285 if (subscript >= d || subscript < 0)
288 fp[out] = fp[tuple + subscript];
296 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
298 for (
int k = 0; k < d; k++) {
299 fp[out + k] = fp[opData[k]];
308 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
311 for (
int k = 0; k < d; k++) {
312 fp[out + k] = fp[in + k];
320 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
329 struct CondJmpRelativeIfFalse {
330 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
331 bool cond = (bool)fp[opData[0]];
340 struct CondJmpRelativeIfTrue {
341 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
342 bool cond = (bool)fp[opData[0]];
352 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
return opData[0]; }
357 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
358 ExprVarRef* ref =
reinterpret_cast<ExprVarRef*
>(c[opData[0]]);
359 if (ref->type().isFP()) {
360 ref->eval(fp + opData[1]);
362 ref->eval(
const_cast<const char**
>(c + opData[1]));
370 struct EvalVarBlock {
371 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
373 double* basePointer =
reinterpret_cast<double*
>(c[0]) + opData[0];
374 double* destPointer = fp + opData[1];
375 for (
int i = 0; i < dim; i++) destPointer[i] = basePointer[i];
382 template <
char uniform,
int dim>
383 struct EvalVarBlockIndirect {
384 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
386 int stride = opData[2];
387 int outputVarBlockOffset = opData[0];
388 int destIndex = opData[1];
389 size_t indirectIndex =
reinterpret_cast<size_t>(c[1]);
390 double* basePointer =
391 reinterpret_cast<double**
>(c[0])[outputVarBlockOffset] + (uniform ? 0 : (stride * indirectIndex));
392 double* destPointer = fp + destIndex;
393 for (
int i = 0; i < dim; i++) destPointer[i] = basePointer[i];
403 template <
char op,
int d>
405 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
407 double* in0 = fp + opData[0];
408 double* in1 = fp + opData[1];
409 double* out = fp + opData[2];
410 for (
int k = 0; k < d; k++) {
413 result &= (*in0) == (*in1);
416 result &= (*in0) != (*in1);
430 struct CompareEqOp<op, 3> {
431 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
432 bool eq = fp[opData[0]] == fp[opData[1]] && fp[opData[0] + 1] == fp[opData[1] + 1] &&
433 fp[opData[0] + 2] == fp[opData[1] + 2];
434 if (op ==
'=') fp[opData[2]] = eq;
435 if (op ==
'!') fp[opData[2]] = !eq;
440 template <
char op,
int d>
441 struct StrCompareEqOp {
443 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
446 fp[opData[2]] = strcmp(c[opData[0]], c[opData[1]]) == 0;
449 fp[opData[2]] = strcmp(c[opData[0]], c[opData[1]]) != 0;
458 int ProcedureReturn(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
459 int newPC = callStack.back();
460 callStack.pop_back();
461 return newPC - opData[0];
466 int ProcedureCall(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
467 callStack.push_back(opData[0]);
476 int basePC = interpreter->
nextPC();
478 interpreter->
addOp(ProcedureReturn);
481 interpreter->
endOp(
false);
488 std::vector<int> operands;
489 for (
int c = 0; c < callerNode->
numChildren(); c++) {
494 if (callerNode->
promote(c) != 0) {
496 interpreter->
addOp(getTemplatizedOp<Promote>(callerNode->
promote(c)));
500 interpreter->
endOp();
505 interpreter->
endOp();
511 operands.push_back(operand);
517 outoperand = interpreter->
allocPtr();
521 int basePC = interpreter->
nextPC();
522 interpreter->
addOp(ProcedureCall);
523 int returnAddress = interpreter->
addOperand(0);
525 interpreter->
endOp(
false);
527 interpreter->
opData[returnAddress] = interpreter->
nextPC();
530 interpreter->
addOp(getTemplatizedOp<AssignOp>(callerNode->
type().
dim()));
533 interpreter->
endOp();
544 int loc = interpreter->
allocFP(1);
545 interpreter->
d[loc] =
value();
551 interpreter->
s[loc] =
const_cast<char*
>(
_str.c_str());
556 std::vector<int> locs;
565 interpreter->
endOp();
571 int dim0 = child0->
type().
dim(), dim1 = child1->type().dim(), dimout =
type().
dim();
573 int op1 = child1->buildInterpreter(interpreter);
575 if (dim0 != dimout) {
576 interpreter->
addOp(getTemplatizedOp<Promote>(dimout));
577 int promoteOp0 = interpreter->
allocFP(dimout);
581 interpreter->
endOp();
583 if (dim1 != dimout) {
584 interpreter->
addOp(getTemplatizedOp<Promote>(dimout));
585 int promoteOp1 = interpreter->
allocFP(dimout);
589 interpreter->
endOp();
600 interpreter->
addOp(getTemplatizedOp2<'+', BinaryOp>(dimout));
603 interpreter->
addOp(getTemplatizedOp2<'-', BinaryOp>(dimout));
606 interpreter->
addOp(getTemplatizedOp2<'*', BinaryOp>(dimout));
609 interpreter->
addOp(getTemplatizedOp2<'/', BinaryOp>(dimout));
612 interpreter->
addOp(getTemplatizedOp2<'^', BinaryOp>(dimout));
615 interpreter->
addOp(getTemplatizedOp2<'%', BinaryOp>(dimout));
624 int intermediateOp = interpreter->
allocPtr();
625 interpreter->
s[intermediateOp] = (
char*)(&
_out);
637 op2 = interpreter->
allocFP(dimout);
665 interpreter->
addOp(getTemplatizedOp2<'-', UnaryOp>(dimout));
668 interpreter->
addOp(getTemplatizedOp2<'~', UnaryOp>(dimout));
671 interpreter->
addOp(getTemplatizedOp2<'!', UnaryOp>(dimout));
676 int op1 = interpreter->
allocFP(dimout);
679 interpreter->
endOp();
686 int dimin = child0->
type().
dim();
688 int op1 = child1->buildInterpreter(interpreter);
689 int op2 = interpreter->
allocFP(1);
691 interpreter->
addOp(getTemplatizedOp<Subscript>(dimin));
695 interpreter->
endOp();
702 Interpreter::VarToLoc::iterator i = interpreter->
varToLoc.find(
var);
703 if (i != interpreter->
varToLoc.end())
706 throw std::runtime_error(
"Unallocated variable encountered.");
712 destLoc = interpreter->
allocFP(dim);
717 if (blockVarRef->type().isLifetimeUniform())
718 interpreter->
addOp(getTemplatizedOp2<1, EvalVarBlockIndirect>(
type.
dim()));
720 interpreter->
addOp(getTemplatizedOp2<0, EvalVarBlockIndirect>(
type.
dim()));
721 interpreter->
addOperand(blockVarRef->offset());
723 interpreter->
addOperand(blockVarRef->stride());
724 interpreter->
endOp();
726 int varRefLoc = interpreter->
allocPtr();
728 interpreter->
s[varRefLoc] =
const_cast<char*
>(
reinterpret_cast<const char*
>(
var));
731 interpreter->
endOp();
739 return interpreter->
varToLoc[
this] =
745 assert(loc != -1 &&
"Invalid type found");
749 if (child0Type.
isFP()) {
750 interpreter->
addOp(getTemplatizedOp<AssignOp>(child0Type.
dim()));
754 assert(
false &&
"Invalid desired assign type");
765 int destDim = varDest->
type().
dim();
766 if (destDim != varSource->
type().
dim()) {
767 assert(varSource->
type().
dim() == 1);
768 interpreter->
addOp(getTemplatizedOp<Promote>(destDim));
770 interpreter->
addOp(getTemplatizedOp<AssignOp>(destDim));
774 interpreter->
endOp();
779 interpreter->
endOp();
781 assert(
false &&
"failed to promote invalid type");
787 int basePC = interpreter->
nextPC();
793 for (
auto&
it : merges) {
795 if (finalVar->
valid()) {
804 interpreter->
endOp();
808 for (
auto&
it : merges) {
810 if (finalVar->
valid()) {
816 interpreter->
endOp();
819 int child2PC = interpreter->
nextPC();
821 for (
auto&
it : merges) {
823 if (finalVar->
valid()) {
829 interpreter->
opData[destFalse] = child2PC - basePC;
830 interpreter->
opData[destEnd] = interpreter->
nextPC() - (child2PC - 1);
837 assert(
type().dim() == 1 &&
type().isFP());
839 if (
_op ==
'&' ||
_op ==
'|') {
843 int op2 = interpreter->
allocFP(1);
847 int basePC = (interpreter->
nextPC());
851 interpreter->
endOp();
853 int op1 = child1->buildInterpreter(interpreter);
855 interpreter->
addOp(
_op ==
'&' ? getTemplatizedOp2<'&', BinaryOp>(1) : getTemplatizedOp2<'|', BinaryOp>(1));
859 interpreter->
endOp();
862 interpreter->
endOp();
865 int falseConditionPC = interpreter->
nextPC();
869 interpreter->
endOp();
872 interpreter->
opData[destFalse] = falseConditionPC - basePC;
873 interpreter->
opData[destEnd] = interpreter->
nextPC() - (falseConditionPC - 1);
880 int op1 = child1->buildInterpreter(interpreter);
886 interpreter->
addOp(getTemplatizedOp2<'>
', BinaryOp>(1));
889 interpreter->addOp(getTemplatizedOp2<'l
', BinaryOp>(1));
892 interpreter->addOp(getTemplatizedOp2<'g
', BinaryOp>(1));
895 assert(false); // interpreter->addOp(getTemplatizedOp2<'&
',BinaryOp>(1));break;
897 assert(false); // interpreter->addOp(getTemplatizedOp2<'|
',BinaryOp>(1));break;
901 int op2 = interpreter->allocFP(1);
902 interpreter->addOperand(op0);
903 interpreter->addOperand(op1);
904 interpreter->addOperand(op2);
905 interpreter->endOp();
910 int ExprPrototypeNode::buildInterpreter(Interpreter* interpreter) const {
912 _interpreterOps.clear();
913 for (int c = 0; c < numChildren(); c++) {
914 if (const ExprVarNode* childVarNode = dynamic_cast<const ExprVarNode*>(child(c))) {
915 ExprType childType = childVarNode->type();
916 if (childType.isFP()) {
917 int operand = interpreter->allocFP(childType.dim());
918 _interpreterOps.push_back(operand);
919 interpreter->varToLoc[childVarNode->localVar()] = operand;
924 child(c)->buildInterpreter(interpreter);
926 // make sure we have a slot in our global activation record for the variables!
931 int ExprCompareEqNode::buildInterpreter(Interpreter* interpreter) const {
932 const ExprNode* child0 = child(0), *child1 = child(1);
933 int op0 = child0->buildInterpreter(interpreter);
934 int op1 = child1->buildInterpreter(interpreter);
936 if (child0->type().isFP()) {
937 int dim0 = child0->type().dim(), dim1 = child1->type().dim();
938 int dimCompare = std::max(dim0, dim1);
939 if (dimCompare > 1) {
941 interpreter->addOp(getTemplatizedOp<Promote>(dim1));
942 int promotedOp0 = interpreter->allocFP(dim1);
943 interpreter->addOperand(op0);
944 interpreter->addOperand(promotedOp0);
945 interpreter->endOp();
949 interpreter->addOp(getTemplatizedOp<Promote>(dim0));
950 int promotedOp1 = interpreter->allocFP(dim0);
951 interpreter->addOperand(op1);
952 interpreter->addOperand(promotedOp1);
953 interpreter->endOp();
958 interpreter->addOp(getTemplatizedOp2<'=
', CompareEqOp>(dimCompare));
960 interpreter->addOp(getTemplatizedOp2<'!
', CompareEqOp>(dimCompare));
962 assert(false && "Invalid operation");
963 } else if (child0->type().isString()) {
965 interpreter->addOp(getTemplatizedOp2<'=
', StrCompareEqOp>(1));
967 interpreter->addOp(getTemplatizedOp2<'!
', StrCompareEqOp>(1));
969 assert(false && "Invalid operation");
971 assert(false && "Invalid type for comparison");
972 int op2 = interpreter->allocFP(1);
973 interpreter->addOperand(op0);
974 interpreter->addOperand(op1);
975 interpreter->addOperand(op2);
976 interpreter->endOp(child0->type().isString() == false);
980 int ExprCondNode::buildInterpreter(Interpreter* interpreter) const {
982 // TODO: handle strings!
983 int dimout = type().dim();
986 int condOp = child(0)->buildInterpreter(interpreter);
987 int basePC = (interpreter->nextPC());
988 interpreter->addOp(CondJmpRelativeIfFalse::f);
989 interpreter->addOperand(condOp);
990 int destFalse = interpreter->addOperand(0);
991 interpreter->endOp();
993 // true way of working
994 int op1 = child(1)->buildInterpreter(interpreter);
996 interpreter->addOp(getTemplatizedOp<AssignOp>(dimout));
997 else if (type().isString())
998 interpreter->addOp(AssignStrOp::f);
1001 interpreter->addOperand(op1);
1002 int dataOutTrue = interpreter->addOperand(-1);
1003 interpreter->endOp(false);
1005 // jump past false way of working
1006 interpreter->addOp(JmpRelative::f);
1007 int destEnd = interpreter->addOperand(0);
1008 interpreter->endOp();
1010 // record start of false condition
1011 int child2PC = interpreter->nextPC();
1013 // false way of working
1014 int op2 = child(2)->buildInterpreter(interpreter);
1016 interpreter->addOp(getTemplatizedOp<AssignOp>(dimout));
1017 else if (type().isString())
1018 interpreter->addOp(AssignStrOp::f);
1021 interpreter->addOperand(op2);
1022 int dataOutFalse = interpreter->addOperand(-1);
1023 interpreter->endOp(false);
1025 // patch up relative jumps
1026 interpreter->opData[destFalse] = child2PC - basePC;
1027 interpreter->opData[destEnd] = interpreter->nextPC() - (child2PC - 1);
1031 opOut = interpreter->allocFP(type().dim());
1032 else if (type().isString())
1033 opOut = interpreter->allocPtr();
1037 // patch outputs on assigns in each condition
1038 interpreter->opData[dataOutTrue] = opOut;
1039 interpreter->opData[dataOutFalse] = opOut;
1044 int ExprBlockNode::buildInterpreter(Interpreter* interpreter) const {
1045 assert(numChildren() == 2);
1046 child(0)->buildInterpreter(interpreter);
1047 return child(1)->buildInterpreter(interpreter);
1050 int ExprModuleNode::buildInterpreter(Interpreter* interpreter) const {
1052 for (int c = 0; c < numChildren(); c++) {
1053 if (c == numChildren() - 1) interpreter->setPCStart(interpreter->nextPC());
1054 lastIdx = child(c)->buildInterpreter(interpreter);