SeExpr
ExprLLVMCodeGeneration.cpp
Go to the documentation of this file.
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 "ExprConfig.h"
18 
19 #ifdef SEEXPR_ENABLE_LLVM
20 #include "ExprLLVM.h"
21 #include "ExprLLVMAll.h"
22 #include "ExprNode.h"
23 #include "ExprFunc.h"
24 #include "VarBlock.h"
25 #include "StringUtils.h"
26 #include <array>
27 using namespace llvm;
28 using namespace SeExpr2;
29 
30 // TODO: Use ordered or unordered float comparison?
31 // TODO: factor out commonly used llvm types
32 // TODO: factor out integer/double constant creation
33 namespace {
34 
35 Function *llvm_getFunction(LLVM_BUILDER Builder) { return Builder.GetInsertBlock()->getParent(); }
36 
37 Module *llvm_getModule(LLVM_BUILDER Builder) { return llvm_getFunction(Builder)->getParent(); }
38 
40 std::string llvmTypeString(llvm::Type *type) {
41  std::string myString;
42  llvm::raw_string_ostream rawStream(myString);
43  type->print(rawStream);
44  return rawStream.str();
45 }
46 
47 bool isVarArg(ExprFuncStandard::FuncType seFuncType) {
48  if (seFuncType == ExprFuncStandard::FUNCN || seFuncType == ExprFuncStandard::FUNCNV ||
49  seFuncType == ExprFuncStandard::FUNCNVV)
50  return true;
51  return false;
52 }
53 
54 bool isReturnVector(ExprFuncStandard::FuncType seFuncType) {
55  if (seFuncType == ExprFuncStandard::FUNC1VV || seFuncType == ExprFuncStandard::FUNC2VV ||
56  seFuncType == ExprFuncStandard::FUNCNVV)
57  return true;
58  return false;
59 }
60 
61 bool isTakeOnlyDoubleArg(ExprFuncStandard::FuncType seFuncType) {
62  if (seFuncType <= ExprFuncStandard::FUNC6 || seFuncType == ExprFuncStandard::FUNCN) return true;
63  return false;
64 }
65 
66 FunctionType *getSeExprFuncStandardLLVMType(ExprFuncStandard::FuncType sft, LLVMContext &llvmContext) {
67  assert(sft != ExprFuncStandard::NONE);
68 
69  Type *intType = Type::getInt32Ty(llvmContext);
70  Type *doubleType = Type::getDoubleTy(llvmContext);
71  Type *doublePtrType = PointerType::getUnqual(Type::getDoubleTy(llvmContext));
72  Type *voidType = Type::getVoidTy(llvmContext);
73  FunctionType *FT = 0;
74 
75  if (sft <= ExprFuncStandard::FUNC6) {
76  std::vector<Type *> paramTypes;
77  switch (sft) {
78  case ExprFuncStandard::FUNC6:
79  paramTypes.push_back(doubleType);
80  case ExprFuncStandard::FUNC5:
81  paramTypes.push_back(doubleType);
82  case ExprFuncStandard::FUNC4:
83  paramTypes.push_back(doubleType);
84  case ExprFuncStandard::FUNC3:
85  paramTypes.push_back(doubleType);
86  case ExprFuncStandard::FUNC2:
87  paramTypes.push_back(doubleType);
88  case ExprFuncStandard::FUNC1:
89  paramTypes.push_back(doubleType);
90  case ExprFuncStandard::FUNC0:
91  default:
92  FT = FunctionType::get(doubleType, paramTypes, false);
93  }
94  } else if (sft == ExprFuncStandard::FUNC1V) {
95  Type *paramTypes[1] = {doublePtrType};
96  FT = FunctionType::get(doubleType, paramTypes, false);
97  } else if (sft == ExprFuncStandard::FUNC2V) {
98  Type *paramTypes[2] = {doublePtrType, doublePtrType};
99  FT = FunctionType::get(doubleType, paramTypes, false);
100  } else if (sft == ExprFuncStandard::FUNC1VV) {
101  Type *paramTypes[2] = {doublePtrType, doublePtrType};
102  FT = FunctionType::get(voidType, paramTypes, false);
103  } else if (sft == ExprFuncStandard::FUNC2VV) {
104  Type *paramTypes[3] = {doublePtrType, doublePtrType, doublePtrType};
105  FT = FunctionType::get(voidType, paramTypes, false);
106  } else if (sft == ExprFuncStandard::FUNCN) {
107  Type *paramTypes[2] = {intType, doublePtrType};
108  FT = FunctionType::get(doubleType, paramTypes, false);
109  } else if (sft == ExprFuncStandard::FUNCNV) {
110  Type *paramTypes[2] = {intType, doublePtrType};
111  FT = FunctionType::get(doubleType, paramTypes, false);
112  } else if (sft == ExprFuncStandard::FUNCNVV) {
113  Type *paramTypes[3] = {doublePtrType, intType, doublePtrType};
114  FT = FunctionType::get(voidType, paramTypes, false);
115  } else
116  assert(false);
117 
118  return FT;
119 }
120 
121 Type *createLLVMTyForSeExprType(LLVMContext &llvmContext, ExprType seType) {
122  if (seType.isFP()) {
123  int dim = seType.dim();
124  return dim == 1 ? Type::getDoubleTy(llvmContext) : VectorType::get(Type::getDoubleTy(llvmContext), dim);
125  } else if (seType.isString()) {
126  // TODO: post c++11
127  // static_assert(sizeof(char*) == 8, "Expect 64-bit pointers");
128  return Type::getInt8PtrTy(llvmContext);
129  }
130  assert(!"unknown SeExpr type encountered"); // unknown type
131  return 0;
132 }
133 
134 // Copy a scalar "val" to a vector of "dim" length
135 LLVM_VALUE createVecVal(LLVM_BUILDER Builder, LLVM_VALUE val, unsigned dim) {
136  LLVMContext &llvmContext = Builder.getContext();
137  VectorType *doubleVecTy = VectorType::get(Type::getDoubleTy(llvmContext), dim);
138  LLVM_VALUE vecVal = UndefValue::get(doubleVecTy);
139  for (unsigned i = 0; i < dim; i++)
140  vecVal = Builder.CreateInsertElement(vecVal, val, ConstantInt::get(Type::getInt32Ty(llvmContext), i));
141  return vecVal;
142 }
143 
144 // Copy a vector "val" to a vector of the same length
145 LLVM_VALUE createVecVal(LLVM_BUILDER Builder, ArrayRef<LLVM_VALUE> val, const std::string &name = "") {
146  if (!val.size()) return 0;
147 
148  LLVMContext &llvmContext = Builder.getContext();
149  unsigned dim = val.size();
150  VectorType *elemType = VectorType::get(val[0]->getType(), dim);
151  LLVM_VALUE vecVal = UndefValue::get(elemType);
152  for (unsigned i = 0; i < dim; i++)
153  vecVal = Builder.CreateInsertElement(vecVal, val[i], ConstantInt::get(Type::getInt32Ty(llvmContext), i), name);
154  return vecVal;
155 }
156 
157 LLVM_VALUE createVecValFromAlloca(LLVM_BUILDER Builder, AllocaInst *destPtr, unsigned vecLen) {
158  Type *destTy = destPtr->getType()->getPointerElementType();
159  assert(destTy->isDoubleTy() || destTy->isArrayTy());
160  std::vector<LLVM_VALUE> vals;
161 
162  for (unsigned i = 0; i < vecLen; ++i) {
163  LLVM_VALUE ptr = destTy->isDoubleTy() ? Builder.CreateConstGEP1_32(destPtr, i)
164  : Builder.CreateConstGEP2_32(nullptr, destPtr, 0, i);
165  vals.push_back(Builder.CreateLoad(ptr));
166  }
167 
168  return createVecVal(Builder, vals);
169 }
170 
171 LLVM_VALUE getFirstElement(LLVM_VALUE V, IRBuilder<> Builder) {
172  Type *VTy = V->getType();
173  if (VTy->isDoubleTy()) return V;
174 
175  assert(VTy->isVectorTy());
176  LLVMContext &llvmContext = Builder.getContext();
177  LLVM_VALUE zero = ConstantInt::get(Type::getInt32Ty(llvmContext), 0);
178  return Builder.CreateExtractElement(V, zero);
179 }
180 
181 LLVM_VALUE promoteToTy(LLVM_VALUE val, Type *destTy, LLVM_BUILDER Builder) {
182  Type *srcTy = val->getType();
183  if (srcTy == destTy) return val;
184 
185  if (destTy->isDoubleTy()) return val;
186 
187  return createVecVal(Builder, val, destTy->getVectorNumElements());
188 }
189 
190 AllocaInst *createAllocaInst(LLVM_BUILDER Builder, Type *ty, unsigned arraySize = 1, const std::string &varName = "") {
191  // move builder to first position of entry BB
192  BasicBlock *entryBB = &llvm_getFunction(Builder)->getEntryBlock();
193  IRBuilder<>::InsertPoint oldIP = Builder.saveIP();
194  if (entryBB->size())
195  Builder.SetInsertPoint(&entryBB->front());
196  else
197  Builder.SetInsertPoint(entryBB);
198 
199  // allocate stack memory and store value to it.
200  LLVMContext &llvmContext = Builder.getContext();
201  LLVM_VALUE arraySizeVal = ConstantInt::get(Type::getInt32Ty(llvmContext), arraySize);
202  AllocaInst *varPtr = Builder.CreateAlloca(ty, arraySizeVal, varName);
203  // restore builder insertion position
204  Builder.restoreIP(oldIP);
205  return varPtr;
206 }
207 
208 AllocaInst *createArray(LLVM_BUILDER Builder, Type *ty, unsigned arraySize, const std::string &varName = "") {
209  // move builder to first position of entry BB
210  BasicBlock *entryBB = &llvm_getFunction(Builder)->getEntryBlock();
211  IRBuilder<>::InsertPoint oldIP = Builder.saveIP();
212  if (entryBB->size())
213  Builder.SetInsertPoint(&entryBB->front());
214  else
215  Builder.SetInsertPoint(entryBB);
216 
217  // allocate stack memory and store value to it.
218  ArrayType *arrayTy = ArrayType::get(ty, arraySize);
219  AllocaInst *varPtr = Builder.CreateAlloca(arrayTy, 0, varName);
220  // restore builder insertion position
221  Builder.restoreIP(oldIP);
222  return varPtr;
223 }
224 
225 std::pair<LLVM_VALUE, LLVM_VALUE> promoteBinaryOperandsToAppropriateVector(LLVM_BUILDER Builder,
226  LLVM_VALUE op1,
227  LLVM_VALUE op2) {
228  Type *op1Ty = op1->getType();
229  Type *op2Ty = op2->getType();
230  if (op1Ty == op2Ty) return std::make_pair(op1, op2);
231 
232  LLVM_VALUE toPromote = op1;
233  LLVM_VALUE target = op2;
234  if (op1Ty->isVectorTy()) std::swap(toPromote, target);
235 
236  assert(target->getType()->isVectorTy());
237 
238  unsigned dim = target->getType()->getVectorNumElements();
239  LLVM_VALUE vecVal = createVecVal(Builder, toPromote, dim);
240 
241  if (op1Ty->isVectorTy())
242  op2 = vecVal;
243  else
244  op1 = vecVal;
245 
246  return std::make_pair(op1, op2);
247 }
248 
249 LLVM_VALUE promoteOperand(LLVM_BUILDER Builder, const ExprType refType, LLVM_VALUE val) {
250  Type *valTy = val->getType();
251  if (refType.isFP() && refType.dim() > 1 && !valTy->isVectorTy()) {
252  return createVecVal(Builder, val, refType.dim());
253  } else {
254  return val;
255  }
256 }
257 
258 AllocaInst *storeVectorToDoublePtr(LLVM_BUILDER Builder, LLVM_VALUE vecVal) {
259  LLVMContext &llvmContext = Builder.getContext();
260  AllocaInst *doublePtr =
261  createAllocaInst(Builder, Type::getDoubleTy(llvmContext), vecVal->getType()->getVectorNumElements());
262  for (unsigned i = 0; i < 3; ++i) {
263  LLVM_VALUE idx = ConstantInt::get(Type::getInt32Ty(llvmContext), i);
264  LLVM_VALUE val = Builder.CreateExtractElement(vecVal, idx);
265  LLVM_VALUE ptr = Builder.CreateConstGEP1_32(doublePtr, i);
266  Builder.CreateStore(val, ptr);
267  }
268  return doublePtr;
269 }
270 
271 std::vector<LLVM_VALUE> codegenFuncCallArgs(LLVM_BUILDER Builder, const ExprFuncNode *funcNode) {
272  std::vector<LLVM_VALUE> args;
273  for (int i = 0; i < funcNode->numChildren(); ++i) args.push_back(funcNode->child(i)->codegen(Builder));
274  return args;
275 }
276 
277 std::vector<LLVM_VALUE> promoteArgs(std::vector<LLVM_VALUE> args, LLVM_BUILDER Builder, FunctionType *llvmFuncType) {
278  std::vector<LLVM_VALUE> ret;
279  for (unsigned i = 0; i < args.size(); ++i)
280  ret.push_back(promoteToTy(args[i], llvmFuncType->getParamType(i), Builder));
281  return ret;
282 }
283 
284 std::vector<LLVM_VALUE> promoteArgs(std::vector<LLVM_VALUE> args,
285  LLVM_BUILDER Builder,
286  ExprFuncStandard::FuncType seFuncType) {
287  if (isTakeOnlyDoubleArg(seFuncType)) return args;
288 
289  LLVMContext &llvmContext = Builder.getContext();
290  VectorType *destTy = VectorType::get(Type::getDoubleTy(llvmContext), 3);
291  std::vector<LLVM_VALUE> ret;
292  for (unsigned i = 0; i < args.size(); ++i) ret.push_back(promoteToTy(args[i], destTy, Builder));
293  return ret;
294 }
295 
296 std::vector<LLVM_VALUE> replaceVecArgWithDoublePointer(LLVM_BUILDER Builder, std::vector<LLVM_VALUE> args) {
297  for (unsigned i = 0; i < args.size(); ++i)
298  if (args[i]->getType()->isVectorTy()) args[i] = storeVectorToDoublePtr(Builder, args[i]);
299  return args;
300 }
301 
302 std::vector<LLVM_VALUE> convertArgsToPointerAndLength(LLVM_BUILDER Builder,
303  std::vector<LLVM_VALUE> actualArgs,
304  ExprFuncStandard::FuncType seFuncType) {
305  assert(isVarArg(seFuncType));
306 
307  LLVMContext &llvmContext = Builder.getContext();
308  unsigned numArgs = actualArgs.size();
309 
310  // type of arg should be either double or double*(aka. vector).
311  for (unsigned i = 0; i < numArgs; ++i)
312  assert(actualArgs[i]->getType()->isDoubleTy() || actualArgs[i]->getType() == Type::getDoublePtrTy(llvmContext));
313 
314  std::vector<LLVM_VALUE> args;
315  // push "int n"
316  args.push_back(ConstantInt::get(Type::getInt32Ty(llvmContext), numArgs));
317 
318  if (seFuncType == ExprFuncStandard::FUNCN) {
319  AllocaInst *doublePtr = createAllocaInst(Builder, Type::getDoubleTy(llvmContext), numArgs);
320  for (unsigned i = 0; i < numArgs; ++i) {
321  LLVM_VALUE ptr = Builder.CreateConstGEP1_32(doublePtr, i);
322  Builder.CreateStore(actualArgs[i], ptr);
323  }
324  args.push_back(doublePtr);
325  return args;
326  }
327 
328  AllocaInst *arrayPtr = createArray(Builder, ArrayType::get(Type::getDoubleTy(llvmContext), 3), numArgs);
329  for (unsigned i = 0; i < numArgs; ++i) {
330  LLVM_VALUE toInsert = actualArgs[i];
331  LLVM_VALUE subArrayPtr = Builder.CreateConstGEP2_32(nullptr, arrayPtr, 0, i);
332  for (unsigned j = 0; j < 3; ++j) {
333  LLVM_VALUE destAddr = Builder.CreateConstGEP2_32(nullptr, subArrayPtr, 0, j);
334  LLVM_VALUE srcAddr = Builder.CreateConstGEP1_32(toInsert, j);
335  Builder.CreateStore(Builder.CreateLoad(srcAddr), destAddr);
336  }
337  }
338  args.push_back(Builder.CreateBitCast(arrayPtr, Type::getDoublePtrTy(llvmContext)));
339  return args;
340 }
341 
342 LLVM_VALUE executeStandardFunction(LLVM_BUILDER Builder,
343  ExprFuncStandard::FuncType seFuncType,
344  std::vector<LLVM_VALUE> args,
345  LLVM_VALUE addrVal) {
346  LLVMContext &llvmContext = Builder.getContext();
347 
348  args = promoteArgs(args, Builder, seFuncType);
349  args = replaceVecArgWithDoublePointer(Builder, args);
350 
351  if (isVarArg(seFuncType)) args = convertArgsToPointerAndLength(Builder, args, seFuncType);
352 
353  if (isReturnVector(seFuncType) == false) return Builder.CreateCall(addrVal, args);
354 
355  // TODO: assume standard function all use vector of length 3 as parameter
356  // or return type.
357  AllocaInst *retPtr = createAllocaInst(Builder, Type::getDoubleTy(llvmContext), 3);
358  args.insert(args.begin(), retPtr);
359  Builder.CreateCall(addrVal, replaceVecArgWithDoublePointer(Builder, args));
360  return createVecValFromAlloca(Builder, retPtr, 3);
361 }
362 
363 // TODO: Is this necessary? why not use printf custom function?
364 LLVM_VALUE callPrintf(const ExprFuncNode *seFunc, LLVM_BUILDER Builder, Function *callee) {
365  LLVMContext &llvmContext = Builder.getContext();
366  std::vector<LLVM_VALUE> args;
367 
368  // TODO: promotion for printf?
369  { // preprocess format string.
370  const ExprStrNode *formatStrNode = dynamic_cast<const ExprStrNode *>(seFunc->child(0));
371  assert(formatStrNode);
372  std::string formatStr(formatStrNode->str());
373  std::string::size_type pos = std::string::npos;
374  while ((pos = formatStr.find("%v")) != std::string::npos) formatStr.replace(pos, 2, std::string("[%f,%f,%f]"));
375  formatStr.append("\n");
376  args.push_back(Builder.CreateGlobalStringPtr(formatStr));
377  }
378 
379  for (int i = 1; i < seFunc->numChildren(); ++i) {
380  LLVM_VALUE arg = seFunc->child(i)->codegen(Builder);
381  if (arg->getType()->isVectorTy()) {
382  AllocaInst *vecArray = storeVectorToDoublePtr(Builder, arg);
383  for (unsigned i = 0; i < arg->getType()->getVectorNumElements(); ++i) {
384  LLVM_VALUE elemPtr = Builder.CreateConstGEP1_32(vecArray, i);
385  args.push_back(Builder.CreateLoad(elemPtr));
386  }
387  } else
388  args.push_back(arg);
389  }
390 
391  Builder.CreateCall(callee, args);
392  return ConstantFP::get(Type::getDoubleTy(llvmContext), 0.0);
393 }
394 
395 // TODO: not good. need better implementation.
396 LLVM_VALUE callCustomFunction(const ExprFuncNode *funcNode, LLVM_BUILDER Builder) {
397  LLVMContext &llvmContext = Builder.getContext();
398 
399  // get the function's arguments
400  std::vector<LLVM_VALUE> args = codegenFuncCallArgs(Builder, funcNode);
401  int nargs = funcNode->numChildren();
402  assert(nargs == (int)args.size());
403 
404  // get the number of items that the function returns
405  unsigned sizeOfRet = (unsigned)funcNode->type().dim();
406  assert(sizeOfRet == 1 || funcNode->type().isFP());
407 
408  // TODO: is this necessary ? Doesn't seem to be used :/
409  createAllocaInst(Builder, Type::getDoubleTy(llvmContext), sizeOfRet);
410 
411  // calculate how much space for opData, fpArg and strArg
412  unsigned sizeOfFpArgs = 1 + sizeOfRet;
413  unsigned sizeOfStrArgs = 2;
414  for (int i = 0; i < nargs; ++i) {
415  ExprType argType = funcNode->child(i)->type();
416  if (argType.isFP()) {
417  sizeOfFpArgs += std::max(funcNode->promote(i), argType.dim());
418  } else if (argType.isString()) {
419  sizeOfStrArgs += 1;
420  } else {
421  assert(false && "invalid type encountered");
422  }
423  }
424 
425  // a few types that are reused throughout this function
426  Type* int32Ty = Type::getInt32Ty(llvmContext); // int
427  Type* doubleTy = Type::getDoubleTy(llvmContext); // double
428  PointerType* int8PtrTy = Type::getInt8PtrTy(llvmContext); // char*
429  Type* int64Ty = Type::getInt64Ty(llvmContext); // int64_t
430 
431 
432  // allocate data that we will feed to SeExpr2LLVMEvalCustomFunction on the stack
433  AllocaInst *opDataArg = createAllocaInst(Builder, int32Ty, (unsigned)nargs + 4, "opDataArgPtr");
434  AllocaInst *fpArg = createAllocaInst(Builder, doubleTy, sizeOfFpArgs, "fpArgPtr");
435  AllocaInst *strArg = createAllocaInst(Builder, int8PtrTy, sizeOfStrArgs, "strArgPtr");
436 
437  // fill fpArgPtr's first value
438  Builder.CreateStore(ConstantFP::get(doubleTy, nargs), fpArg);
439 
440  // fill opDataArgPtr
441  Builder.CreateStore(ConstantInt::get(int32Ty, 0), Builder.CreateConstGEP1_32(opDataArg, 0));
442  Builder.CreateStore(ConstantInt::get(int32Ty, 1), Builder.CreateConstGEP1_32(opDataArg, 1));
443  Builder.CreateStore(ConstantInt::get(int32Ty, 1), Builder.CreateConstGEP1_32(opDataArg, 2));
444  Builder.CreateStore(ConstantInt::get(int32Ty, 0), Builder.CreateConstGEP1_32(opDataArg, 3));
445 
446  // Load arguments into the pseudo interpreter data structure
447  unsigned fpIdx = 1 + sizeOfRet;
448  unsigned strIdx = 2;
449  for (int argIndex = 0; argIndex < nargs; ++argIndex) {
450  int opIndex = argIndex + 4;
451  ExprType argType = funcNode->child(argIndex)->type();
452  if (argType.isFP()) {
453  // store the fpArgPtr indirection index
454  Builder.CreateStore(ConstantInt::get(int32Ty, fpIdx), Builder.CreateConstGEP1_32(opDataArg, opIndex));
455  if (argType.dim() > 1) {
456  for (int comp = 0; comp < argType.dim(); comp++) {
457  LLVM_VALUE compIndex = ConstantInt::get(int32Ty, comp);
458  LLVM_VALUE val = Builder.CreateExtractElement(args[argIndex], compIndex);
459  LLVM_VALUE fpArgPtr = Builder.CreateConstGEP1_32(fpArg, fpIdx + comp);
460  Builder.CreateStore(val, fpArgPtr);
461  }
462  fpIdx += argType.dim();
463  } else {
464  // TODO: this needs the promote!!!
465  int promote = funcNode->promote(argIndex);
466  if (promote) {
467  LLVM_VALUE val = args[argIndex];
468  for (int comp = 0; comp < promote; comp++) {
469  LLVM_VALUE fpArgPtr = Builder.CreateConstGEP1_32(fpArg, fpIdx + comp);
470  Builder.CreateStore(val, fpArgPtr);
471  }
472  fpIdx += promote;
473  } else {
474  Builder.CreateStore(args[argIndex], Builder.CreateConstGEP1_32(fpArg, fpIdx));
475  fpIdx++;
476  }
477  }
478  } else if (argType.isString()) {
479  // store the strArgPtr indirection index
480  Builder.CreateStore(ConstantInt::get(int32Ty, strIdx), Builder.CreateConstGEP1_32(opDataArg, opIndex));
481  Builder.CreateStore(args[argIndex], Builder.CreateConstGEP1_32(strArg, strIdx));
482  strIdx++;
483  }
484  }
485 
486  // get the module from the builder
487  Module* module = llvm_getModule(Builder);
488 
489  // TODO: thread safety?
490  // TODO: This leaks!
491  GlobalVariable *dataGV = new GlobalVariable(*module, int8PtrTy, false, GlobalValue::InternalLinkage, ConstantPointerNull::get(int8PtrTy));
492 
493  // call the function
494  Builder.CreateCall(
495  module->getFunction("SeExpr2LLVMEvalCustomFunction"),
496  {
497  opDataArg,
498  fpArg,
499  strArg,
500  dataGV,
501  ConstantInt::get(int64Ty, (uint64_t)funcNode)
502  }
503  );
504 
505  // read the result from memory
506  int resultOffset = 1;
507  if (funcNode->type().isFP()) {
508  if (sizeOfRet == 1) {
509  return Builder.CreateLoad(Builder.CreateConstGEP1_32(fpArg, resultOffset));
510  } else if (sizeOfRet > 1) {
511  std::vector<LLVM_VALUE> resultArray;
512  for (unsigned int comp = 0; comp < sizeOfRet; comp++) {
513  LLVM_VALUE ptr = Builder.CreateConstGEP1_32(fpArg, resultOffset + comp); // skip nargs
514  resultArray.push_back(Builder.CreateLoad(ptr));
515  }
516  return createVecVal(Builder, resultArray);
517  }
518  } else {
519  return Builder.CreateLoad(Builder.CreateConstGEP1_32(strArg, 1));
520  }
521 
522  assert(false);
523  return 0;
524 }
525 }
526 
527 extern "C" void SeExpr2LLVMEvalFPVarRef(ExprVarRef *seVR, double *result) { seVR->eval(result); }
528 extern "C" void SeExpr2LLVMEvalStrVarRef(ExprVarRef *seVR, char **result) { seVR->eval((const char **)result); }
529 
530 namespace SeExpr2 {
531 
532 LLVM_VALUE promoteToDim(LLVM_VALUE val, unsigned dim, LLVM_BUILDER Builder) {
533  Type *srcTy = val->getType();
534  if (srcTy->isVectorTy() || dim <= 1) return val;
535 
536  assert(srcTy->isDoubleTy());
537  return createVecVal(Builder, val, dim);
538 }
539 
540 LLVM_VALUE ExprNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
541  for (int i = 0; i < numChildren(); i++) child(i)->codegen(Builder);
542  return 0;
543 }
544 
545 LLVM_VALUE ExprModuleNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
546  LLVM_VALUE lastVal = 0;
547  for (int i = 0; i < numChildren(); i++) lastVal = child(i)->codegen(Builder);
548  assert(lastVal);
549  return lastVal;
550 }
551 
552 LLVM_VALUE ExprBlockNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
553  LLVM_VALUE lastVal = 0;
554  for (int i = 0; i < numChildren(); i++) lastVal = child(i)->codegen(Builder);
555  assert(lastVal);
556  return lastVal;
557 }
558 
559 LLVM_VALUE ExprNumNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
560  return ConstantFP::get(Builder.getContext(), APFloat(_val));
561 }
562 
563 LLVM_VALUE ExprBinaryOpNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
564  LLVM_VALUE c1 = child(0)->codegen(Builder);
565  LLVM_VALUE c2 = child(1)->codegen(Builder);
566  std::pair<LLVM_VALUE, LLVM_VALUE> pv = promoteBinaryOperandsToAppropriateVector(Builder, c1, c2);
567  LLVM_VALUE op1 = pv.first;
568  LLVM_VALUE op2 = pv.second;
569 
570  const bool isString = child(0)->type().isString();
571 
572  if (isString == false) {
573  switch (_op) {
574  case '+':
575  return Builder.CreateFAdd(op1, op2);
576  case '-':
577  return Builder.CreateFSub(op1, op2);
578  case '*':
579  return Builder.CreateFMul(op1, op2);
580  case '/':
581  return Builder.CreateFDiv(op1, op2);
582  case '%': {
583  // niceMod() from v1: b==0 ? 0 : a-floor(a/b)*b
584  LLVM_VALUE a = op1, b = op2;
585  LLVM_VALUE aOverB = Builder.CreateFDiv(a, b);
586  Function *floorFun = Intrinsic::getDeclaration(llvm_getModule(Builder), Intrinsic::floor, op1->getType());
587  LLVM_VALUE normal = Builder.CreateFSub(a, Builder.CreateFMul(Builder.CreateCall(floorFun, {aOverB}), b));
588  Constant *zero = ConstantFP::get(op1->getType(), 0.0);
589  return Builder.CreateSelect(Builder.CreateFCmpOEQ(zero, op1), zero, normal);
590  }
591  case '^': {
592  // TODO: make external function reference work with interpreter, libffi
593  // TODO: needed for MCJIT??
594  // TODO: is the above not already done?!
595  std::vector<Type *> arg_type;
596  arg_type.push_back(op1->getType());
597  Function *fun = Intrinsic::getDeclaration(llvm_getModule(Builder), Intrinsic::pow, arg_type);
598  std::vector<LLVM_VALUE> ops = {op1, op2};
599  return Builder.CreateCall(fun, ops);
600  }
601  }
602  } else {
603  // precompute a few things
604  LLVMContext &context = Builder.getContext();
605  Module *module = llvm_getModule(Builder);
606  PointerType *i8PtrPtrTy = PointerType::getUnqual(Type::getInt8PtrTy(context));
607  Type *i32Ty = Type::getInt32Ty(context);
608  Function *strlen = module->getFunction("strlen");
609  Function *malloc = module->getFunction("malloc");
610  Function *free = module->getFunction("free");
611  Function *memset = module->getFunction("memset");
612  Function *strcat = module->getFunction("strcat");
613 
614  // do magic (see the pseudo C code on the comments at the end
615  // of each LLVM instruction)
616 
617  // compute the length of the operand strings
618  LLVM_VALUE len1 = Builder.CreateCall(strlen, { op1 }); // len1 = strlen(op1);
619  LLVM_VALUE len2 = Builder.CreateCall(strlen, { op2 }); // len2 = strlen(op2);
620  LLVM_VALUE len = Builder.CreateAdd(len1, len2); // len = len1 + len2;
621 
622  // allocate and clear memory
623  LLVM_VALUE alloc = Builder.CreateCall(malloc, { len }); // alloc = malloc(len1 + len2);
624  LLVM_VALUE zero = ConstantInt::get(i32Ty, 0); // zero = 0;
625  Builder.CreateCall(memset, { alloc, zero, len }); // memset(alloc, zero, len);
626 
627  // concatenate operand strings into output string
628  Builder.CreateCall(strcat, { alloc, op1 }); // strcat(alloc, op1);
629  LLVM_VALUE newAlloc = Builder.CreateGEP(nullptr, alloc, len1); // newAlloc = alloc + len1
630  Builder.CreateCall(strcat, { newAlloc, op2 }); // strcat(alloc, op2);
631 
632  // store the address in the node's _out member so that it will be
633  // cleaned up when the expression is destroyed.
634  APInt outAddr = APInt(64, (uint64_t)&_out);
635  LLVM_VALUE out = Constant::getIntegerValue(i8PtrPtrTy, outAddr); // out = &_out;
636  Builder.CreateCall(free, { Builder.CreateLoad(out) }); // free(*out);
637  Builder.CreateStore(alloc, out); // *out = alloc
638  return alloc;
639  }
640 
641  assert(false && "unexpected op");
642  return 0;
643 }
644 
645 // This is the def of def-use chain
646 // We don't go to VarNode::codegen. It is codegen'd here.
647 LLVM_VALUE ExprAssignNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
648  // codegen value to store
649  LLVM_VALUE val = child(0)->codegen(Builder);
650  // code gen pointer to store into
651  const std::string &varName = name();
652  LLVM_VALUE varPtr = _localVar->codegen(Builder, varName, val);
653  // do actual store
654  Builder.CreateStore(val, varPtr);
655  return 0;
656 }
657 
659 LLVM_VALUE ExprLocalVar::codegen(LLVM_BUILDER Builder, const std::string &varName, LLVM_VALUE refValue) const {
660  _varPtr = createAllocaInst(Builder, refValue->getType(), 1, varName);
661  return _varPtr;
662 }
663 
664 LLVM_VALUE ExprCompareEqNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
665  LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
666  LLVM_VALUE op2 = getFirstElement(child(1)->codegen(Builder), Builder);
667 
668  LLVM_VALUE boolVal = 0;
669  switch (_op) {
670  case '!':
671  boolVal = Builder.CreateFCmpONE(op1, op2);
672  break;
673  case '=':
674  boolVal = Builder.CreateFCmpOEQ(op1, op2);
675  break;
676  default:
677  assert(false && "Unkown CompareEq op.");
678  }
679 
680  return Builder.CreateUIToFP(boolVal, op1->getType());
681 }
682 
683 LLVM_VALUE ExprCompareNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
684  if (_op == '&' || _op == '|') {
685  // Handle & and | specially as conditionals to handle short circuiting!
686  LLVMContext &llvmContext = Builder.getContext();
687 
688  LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
689  Type *opTy = op1->getType();
690  Constant *zero = ConstantFP::get(opTy, 0.0);
691 
692  LLVM_VALUE op1IsOne = Builder.CreateFCmpUNE(op1, zero);
693 
694  Function *F = llvm_getFunction(Builder);
695  BasicBlock *thenBlock = BasicBlock::Create(llvmContext, "then", F);
696  BasicBlock *elseBlock = BasicBlock::Create(llvmContext, "else", F);
697  BasicBlock *phiBlock = BasicBlock::Create(llvmContext, "phi", F);
698  Builder.CreateCondBr(op1IsOne, thenBlock, elseBlock);
699 
700  LLVM_VALUE op2IsOne;
701  Type *intTy = Type::getInt1Ty(llvmContext);
702  Type *doubleTy = Type::getDoubleTy(llvmContext);
703  llvm::PHINode *phiNode = nullptr;
704  if (_op == '&') {
705  // TODO: full IfThenElsenot needed
706  Builder.SetInsertPoint(thenBlock);
707  LLVM_VALUE op2 = child(1)->codegen(Builder);
708  op2IsOne = Builder.CreateFCmpUNE(op2, zero);
709  Builder.CreateBr(phiBlock);
710  thenBlock = Builder.GetInsertBlock();
711 
712  Builder.SetInsertPoint(elseBlock);
713  Builder.CreateBr(phiBlock);
714  Builder.SetInsertPoint(phiBlock);
715 
716  phiNode = Builder.CreatePHI(intTy, 2, "iftmp");
717  phiNode->addIncoming(op2IsOne, thenBlock);
718  phiNode->addIncoming(op1IsOne, elseBlock);
719  } else if (_op == '|') {
720  // TODO: full IfThenElsenot needed
721  Builder.SetInsertPoint(thenBlock);
722  Builder.CreateBr(phiBlock);
723 
724  Builder.SetInsertPoint(elseBlock);
725  LLVM_VALUE op2 = child(1)->codegen(Builder);
726  op2IsOne = Builder.CreateFCmpUNE(op2, zero);
727  Builder.CreateBr(phiBlock);
728  elseBlock = Builder.GetInsertBlock();
729 
730  Builder.SetInsertPoint(phiBlock);
731  phiNode = Builder.CreatePHI(intTy, 2, "iftmp");
732  phiNode->addIncoming(op1IsOne, thenBlock);
733  phiNode->addIncoming(op2IsOne, elseBlock);
734  } else {
735  throw std::runtime_error("Logical inconsistency.");
736  }
737  LLVM_VALUE out = Builder.CreateUIToFP(phiNode, doubleTy);
738  return out;
739  } else {
740  LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
741  LLVM_VALUE op2 = getFirstElement(child(1)->codegen(Builder), Builder);
742 
743  Type *opTy = op1->getType();
744  Constant *zero = ConstantFP::get(opTy, 0.0);
745  LLVM_VALUE boolVal = 0;
746 
747  switch (_op) {
748  case '|': {
749  LLVM_VALUE op1IsOne = Builder.CreateFCmpUNE(op1, zero);
750  LLVM_VALUE op2IsOne = Builder.CreateFCmpUNE(op2, zero);
751  boolVal = Builder.CreateOr(op1IsOne, op2IsOne);
752  break;
753  }
754  case '&': {
755  assert(false); // handled above
756  break;
757  }
758  case 'g':
759  boolVal = Builder.CreateFCmpOGE(op1, op2);
760  break;
761  case 'l':
762  boolVal = Builder.CreateFCmpOLE(op1, op2);
763  break;
764  case '>':
765  boolVal = Builder.CreateFCmpOGT(op1, op2);
766  break;
767  case '<':
768  boolVal = Builder.CreateFCmpOLT(op1, op2);
769  break;
770  default:
771  assert(false && "Unkown Compare op.");
772  }
773 
774  return Builder.CreateUIToFP(boolVal, opTy);
775  }
776 }
777 
778 LLVM_VALUE ExprCondNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
779 
780 #if 0 // old non-short circuit
781  LLVM_VALUE condVal = getFirstElement(child(0)->codegen(Builder), Builder);
782  LLVM_VALUE cond = Builder.CreateFCmpUNE(condVal,
783  ConstantFP::get(condVal->getType(), 0.0));
784  LLVM_VALUE trueVal = child(1)->codegen(Builder);
785  LLVM_VALUE falseVal = child(2)->codegen(Builder);
786  std::pair<LLVM_VALUE, LLVM_VALUE> pv = promoteBinaryOperandsToAppropriateVector(Builder, trueVal, falseVal);
787  return Builder.CreateSelect(cond, pv.first, pv.second);
788 #else // new short circuit version
789  LLVM_VALUE condVal = getFirstElement(child(0)->codegen(Builder), Builder);
790  LLVM_VALUE condAsBool = Builder.CreateFCmpUNE(condVal, ConstantFP::get(condVal->getType(), 0.0));
791  LLVMContext &llvmContext = Builder.getContext();
792  Function *F = llvm_getFunction(Builder);
793  BasicBlock *thenBlock = BasicBlock::Create(llvmContext, "then", F);
794  BasicBlock *elseBlock = BasicBlock::Create(llvmContext, "else", F);
795  BasicBlock *phiBlock = BasicBlock::Create(llvmContext, "phi", F);
796  Builder.CreateCondBr(condAsBool, thenBlock, elseBlock);
797 
798  Builder.SetInsertPoint(thenBlock);
799  LLVM_VALUE trueVal = promoteOperand(Builder, _type, child(1)->codegen(Builder));
800  Builder.CreateBr(phiBlock);
801  thenBlock = Builder.GetInsertBlock();
802 
803  Builder.SetInsertPoint(elseBlock);
804  LLVM_VALUE falseVal = promoteOperand(Builder, _type, child(2)->codegen(Builder));
805  Builder.CreateBr(phiBlock);
806  elseBlock = Builder.GetInsertBlock();
807 
808  Builder.SetInsertPoint(phiBlock);
809  llvm::PHINode *phiNode = Builder.CreatePHI(trueVal->getType(), 2, "iftmp");
810  phiNode->addIncoming(trueVal, thenBlock);
811  phiNode->addIncoming(falseVal, elseBlock);
812  return phiNode;
813 
814 #endif
815 }
816 
817 LLVM_VALUE ExprFuncNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
818  LLVMContext &llvmContext = Builder.getContext();
819  Module *M = llvm_getModule(Builder);
820  std::string calleeName(name());
821 
822  /************* call local function or printf *************/
823  Function *callee = M->getFunction(calleeName);
824  if (calleeName == "printf") {
825  if (!callee) {
826  FunctionType *FT = FunctionType::get(Type::getVoidTy(llvmContext), Type::getInt8PtrTy(llvmContext), true);
827  callee = Function::Create(FT, GlobalValue::ExternalLinkage, "printf", llvm_getModule(Builder));
828  }
829  return callPrintf(this, Builder, callee);
830  } else if (callee) {
831  std::vector<LLVM_VALUE> args =
832  promoteArgs(codegenFuncCallArgs(Builder, this), Builder, callee->getFunctionType());
833  return Builder.CreateCall(callee, args);
834  }
835 
836  /************* call standard function or custom function *************/
837  // call custom function
838  const ExprFuncStandard *standfunc = dynamic_cast<const ExprFuncStandard *>(_func->funcx());
839  if (!standfunc) return callCustomFunction(this, Builder);
840 
841  // call standard function
842  // get function pointer
843  ExprFuncStandard::FuncType seFuncType = standfunc->getFuncType();
844  FunctionType *llvmFuncType = getSeExprFuncStandardLLVMType(seFuncType, llvmContext);
845  void *fp = standfunc->getFuncPointer();
846  ConstantInt *funcAddr = ConstantInt::get(Type::getInt64Ty(llvmContext), (uint64_t)fp);
847  LLVM_VALUE addrVal = Builder.CreateIntToPtr(funcAddr, PointerType::getUnqual(llvmFuncType));
848 
849  // Collect distribution positions
850  std::vector<LLVM_VALUE> args = codegenFuncCallArgs(Builder, this);
851  std::vector<int> argumentIsVectorAndNeedsDistribution(args.size(), 0);
852  Type *maxVectorArgType = nullptr;
853  if (seFuncType == ExprFuncStandard::FUNCN) {
854  for (unsigned i = 0; i < args.size(); ++i)
855  if (args[i]->getType()->isVectorTy()) {
856  maxVectorArgType = args[i]->getType();
857  argumentIsVectorAndNeedsDistribution[i] = 1;
858  }
859  } else if (seFuncType == ExprFuncStandard::FUNCNV || seFuncType == ExprFuncStandard::FUNCNVV) {
860 
861  } else {
862  unsigned shift = isReturnVector(seFuncType) ? 1 : 0;
863  for (unsigned i = 0; i < args.size(); ++i) {
864  Type *paramType = llvmFuncType->getParamType(i + shift);
865  Type *argType = args[i]->getType();
866  if (argType->isVectorTy() && paramType->isDoubleTy()) {
867  maxVectorArgType = args[i]->getType();
868  argumentIsVectorAndNeedsDistribution[i] = 1;
869  }
870  }
871  }
872 
873  if (!maxVectorArgType) // nothing needs distribution so just execute normally
874  return executeStandardFunction(Builder, seFuncType, args, addrVal);
875 
876  assert(maxVectorArgType->isVectorTy());
877 
878  std::vector<LLVM_VALUE> ret;
879  for (unsigned vecComponent = 0; vecComponent < maxVectorArgType->getVectorNumElements(); ++vecComponent) {
880  LLVM_VALUE idx = ConstantInt::get(Type::getInt32Ty(llvmContext), vecComponent);
881  std::vector<LLVM_VALUE> realArgs;
882  // Break the function into multiple calls per component of the output
883  // i.e. sin([1,2,3]) should be [sin(1),sin(2),sin(3)]
884  for (unsigned argIndex = 0; argIndex < args.size(); ++argIndex) {
885  LLVM_VALUE realArg = args[argIndex];
886  if (argumentIsVectorAndNeedsDistribution[argIndex]) {
887  if (args[argIndex]->getType()->isPointerTy())
888  realArg = Builder.CreateLoad(Builder.CreateConstGEP2_32(nullptr, args[argIndex], 0, vecComponent));
889  else
890  realArg = Builder.CreateExtractElement(args[argIndex], idx);
891  }
892  realArgs.push_back(realArg);
893  }
894  ret.push_back(executeStandardFunction(Builder, seFuncType, realArgs, addrVal));
895  }
896  return createVecVal(Builder, ret);
897 }
898 
899 LLVM_VALUE ExprIfThenElseNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
900  LLVM_VALUE condVal = getFirstElement(child(0)->codegen(Builder), Builder);
901  Type *condTy = condVal->getType();
902 
903  LLVMContext &llvmContext = Builder.getContext();
904 
905  Constant *zero = ConstantFP::get(condTy, 0.0);
906  LLVM_VALUE intCond = Builder.CreateFCmpUNE(condVal, zero);
907 
908  Function *F = llvm_getFunction(Builder);
909  BasicBlock *thenBlock = BasicBlock::Create(llvmContext, "then", F);
910  BasicBlock *elseBlock = BasicBlock::Create(llvmContext, "else", F);
911  BasicBlock *phiBlock = BasicBlock::Create(llvmContext, "phi", F);
912  Builder.CreateCondBr(intCond, thenBlock, elseBlock);
913 
914  Builder.SetInsertPoint(thenBlock);
915  child(1)->codegen(Builder);
916  thenBlock = Builder.GetInsertBlock();
917 
918  Builder.SetInsertPoint(elseBlock);
919  child(2)->codegen(Builder);
920  elseBlock = Builder.GetInsertBlock();
921 
922  // make all the merged variables. in the if then basic blocks
923  // this is because we need phi ops to be alone
924  Builder.SetInsertPoint(phiBlock);
925  const auto &merges = _varEnv->merge(_varEnvMergeIndex);
926  std::vector<LLVM_VALUE> phis;
927  phis.reserve(merges.size());
928  for (auto &it : merges) {
929  ExprLocalVarPhi *finalVar = it.second;
930  if (finalVar->valid()) {
931  ExprType refType = finalVar->type();
932  Builder.SetInsertPoint(thenBlock);
933  LLVM_VALUE thenValue = promoteOperand(Builder, refType, Builder.CreateLoad(finalVar->_thenVar->varPtr()));
934  Builder.SetInsertPoint(elseBlock);
935  LLVM_VALUE elseValue = promoteOperand(Builder, refType, Builder.CreateLoad(finalVar->_elseVar->varPtr()));
936 
937  Type *finalType = thenValue->getType();
938  Builder.SetInsertPoint(phiBlock);
939  PHINode *phi = Builder.CreatePHI(finalType, 2, it.first);
940  phi->addIncoming(thenValue, thenBlock);
941  phi->addIncoming(elseValue, elseBlock);
942  phis.push_back(phi);
943  }
944  }
945  // Now that we made all of the phi blocks, we must store them into the variables
946  int idx = 0;
947  for (auto &it : _varEnv->merge(_varEnvMergeIndex)) {
948  const std::string &name = it.first;
949  ExprLocalVarPhi *finalVar = it.second;
950  if (finalVar->valid()) {
951  LLVM_VALUE _finalVarPtr = finalVar->codegen(Builder, name + "-merge", phis[idx]);
952  Builder.CreateStore(phis[idx++], _finalVarPtr);
953  }
954  }
955  // Insert the ending jumps out of the then, else basic blocks
956  Builder.SetInsertPoint(thenBlock);
957  Builder.CreateBr(phiBlock);
958  Builder.SetInsertPoint(elseBlock);
959  Builder.CreateBr(phiBlock);
960  // insert at end again
961  Builder.SetInsertPoint(phiBlock);
962 
963  return 0;
964 }
965 
966 LLVM_VALUE ExprLocalFunctionNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
967  IRBuilder<>::InsertPoint oldIP = Builder.saveIP();
968  LLVMContext &llvmContext = Builder.getContext();
969 
970  // codegen prototype
971  Function *F = cast<Function>(child(0)->codegen(Builder));
972 
973  // create alloca for args
974  BasicBlock *BB = BasicBlock::Create(llvmContext, "entry", F);
975  Builder.SetInsertPoint(BB);
976  Function::arg_iterator AI = F->arg_begin();
977  for (int i = 0, e = F->arg_size(); i != e; ++i, ++AI) {
978  AllocaInst *Alloca = createAllocaInst(Builder, AI->getType(), 1, AI->getName());
979  Alloca->takeName(&*AI);
980  Builder.CreateStore(&*AI, Alloca);
981  }
982 
983  LLVM_VALUE result = 0;
984  for (int i = 1; i < numChildren(); i++) result = child(i)->codegen(Builder);
985 
986  Builder.CreateRet(result);
987  Builder.restoreIP(oldIP);
988  return 0;
989 }
990 
991 LLVM_VALUE ExprPrototypeNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
992  LLVMContext &llvmContext = Builder.getContext();
993 
994  // get arg type
995  std::vector<Type *> ParamTys;
996  for (int i = 0; i < numChildren(); ++i) ParamTys.push_back(createLLVMTyForSeExprType(llvmContext, argType(i)));
997  // get ret type
998  Type *retTy = createLLVMTyForSeExprType(llvmContext, returnType());
999 
1000  FunctionType *FT = FunctionType::get(retTy, ParamTys, false);
1001  Function *F = Function::Create(FT, GlobalValue::InternalLinkage, name(), llvm_getModule(Builder));
1002 
1003  // Set names for all arguments.
1004  auto AI = F->arg_begin();
1005  for (int i = 0, e = numChildren(); i != e; ++i, ++AI) {
1006  const ExprVarNode *childNode = dynamic_cast<const ExprVarNode *>(child(i));
1007  assert(childNode);
1008  AI->setName(childNode->name());
1009  }
1010 
1011  return F;
1012 }
1013 
1014 LLVM_VALUE ExprStrNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
1015  return Builder.CreateGlobalStringPtr(unescapeString(_str));
1016 }
1017 
1018 LLVM_VALUE ExprSubscriptNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
1019  LLVM_VALUE op1 = child(0)->codegen(Builder);
1020  LLVM_VALUE op2 = child(1)->codegen(Builder);
1021 
1022  if (op1->getType()->isDoubleTy()) return op1;
1023 
1024  LLVMContext &llvmContext = Builder.getContext();
1025  LLVM_VALUE idx = Builder.CreateFPToUI(op2, Type::getInt32Ty(llvmContext));
1026  return Builder.CreateExtractElement(op1, idx);
1027 }
1028 
1029 LLVM_VALUE ExprUnaryOpNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
1030  LLVM_VALUE op1 = child(0)->codegen(Builder);
1031  Type *op1Ty = op1->getType();
1032  Constant *negateZero = ConstantFP::getZeroValueForNegation(op1Ty);
1033  Constant *zero = ConstantFP::get(op1Ty, 0.0);
1034  Constant *one = ConstantFP::get(op1Ty, 1.0);
1035 
1036  switch (_op) {
1037  case '-':
1038  return Builder.CreateFSub(negateZero, op1);
1039  case '~': {
1040  LLVM_VALUE neg = Builder.CreateFSub(negateZero, op1);
1041  return Builder.CreateFAdd(neg, one);
1042  }
1043  case '!': {
1044  LLVM_VALUE eqZero = Builder.CreateFCmpOEQ(zero, op1);
1045  return Builder.CreateSelect(eqZero, one, zero);
1046  }
1047  }
1048 
1049  assert(false && "not implemented.");
1050  return 0;
1051 }
1052 
1054 struct VarCodeGeneration {
1055  static LLVM_VALUE codegen(ExprVarRef *varRef, const std::string &varName, LLVM_BUILDER Builder) {
1056  LLVMContext &llvmContext = Builder.getContext();
1057 
1058  // a few types
1059  Type *int64Ty = Type::getInt64Ty(llvmContext); // int64_t
1060  Type *doubleTy = Type::getDoubleTy(llvmContext); // double
1061  PointerType *int8PtrTy = Type::getInt8PtrTy(llvmContext); // char *
1062 
1063  // get var informations
1064  bool isDouble = varRef->type().isFP();
1065  int dim = varRef->type().dim();
1066 
1067  // create the return value on the stack
1068  AllocaInst *returnValue = createAllocaInst(Builder, isDouble ? doubleTy : int8PtrTy, dim);
1069 
1070  // get our eval var function, and call it with a pointer to our var ref and a ref to the return value
1071  Function *evalVarFunc = llvm_getModule(Builder)->getFunction(isDouble == true ? "SeExpr2LLVMEvalFPVarRef" : "SeExpr2LLVMEvalStrVarRef");
1072  Builder.CreateCall(evalVarFunc, {
1073  Builder.CreateIntToPtr(ConstantInt::get(int64Ty, (uint64_t)varRef), int8PtrTy),
1074  returnValue
1075  });
1076 
1077  // load our return value
1078  LLVM_VALUE ret = 0;
1079  if (dim == 1) {
1080  ret = Builder.CreateLoad(returnValue);
1081  } else {
1082  // TODO: I don't really see how this requires dim==3... this assert should be removable
1083  assert(dim == 3 && "future work.");
1084  ret = createVecValFromAlloca(Builder, returnValue, dim);
1085  }
1086 
1087  AllocaInst *thisvar = createAllocaInst(Builder, ret->getType(), 1, varName);
1088  Builder.CreateStore(ret, thisvar);
1089  return ret;
1090  }
1091 
1092  static LLVM_VALUE codegen(VarBlockCreator::Ref *varRef, const std::string &varName, LLVM_BUILDER Builder) {
1093  LLVMContext &llvmContext = Builder.getContext();
1094 
1095  int variableOffset = varRef->offset();
1096  int variableStride = varRef->stride();
1097  Function *function = llvm_getFunction(Builder);
1098  auto argIterator = function->arg_begin();
1099  argIterator++; // skip first arg
1100  llvm::Argument *variableBlock = &*(argIterator++);
1101  llvm::Argument *indirectIndex = &*(argIterator++);
1102 
1103  int dim = varRef->type().dim();
1104 
1105  Type *ptrToPtrTy = variableBlock->getType();
1106  Value *variableBlockAsPtrPtr = Builder.CreatePointerCast(variableBlock, ptrToPtrTy);
1107  Value *variableOffsetIndex = ConstantInt::get(Type::getInt32Ty(llvmContext), variableOffset);
1108  Value *variableBlockIndirectPtrPtr = Builder.CreateInBoundsGEP(variableBlockAsPtrPtr, variableOffsetIndex);
1109  Value *baseMemory = Builder.CreateLoad(variableBlockIndirectPtrPtr);
1110  Value *variableStrideValue = ConstantInt::get(Type::getInt32Ty(llvmContext), variableStride);
1111  if (dim == 1) {
1113  Value *variablePointer =
1114  varRef->type().isLifetimeUniform() ? baseMemory : Builder.CreateInBoundsGEP(baseMemory, indirectIndex);
1115  return Builder.CreateLoad(variablePointer);
1116  } else {
1117  std::vector<Value *> loadedValues(dim);
1118  for (int component = 0; component < dim; component++) {
1119  Value *componentIndex = ConstantInt::get(Type::getInt32Ty(llvmContext), component);
1121  Value *variablePointer =
1122  varRef->type().isLifetimeUniform()
1123  ? Builder.CreateInBoundsGEP(Type::getDoubleTy(llvmContext), baseMemory, componentIndex)
1124  : Builder.CreateInBoundsGEP(
1125  Type::getDoubleTy(llvmContext),
1126  baseMemory,
1127  Builder.CreateAdd(Builder.CreateMul(indirectIndex, variableStrideValue), componentIndex));
1128  loadedValues[component] = Builder.CreateLoad(variablePointer, varName);
1129  }
1130  return createVecVal(Builder, loadedValues, varName);
1131  }
1132  }
1133 };
1134 
1135 // This is the use of def-use chain
1136 LLVM_VALUE ExprVarNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
1137  if (_var) {
1138  // All external var has the prefix "external_" in current function to avoid
1139  // potential name conflict with local variable
1140  std::string varName("external_");
1141  varName.append(name());
1142  // if (LLVM_VALUE valPtr = resolveLocalVar(varName.c_str(), Builder))
1143  // return Builder.CreateLoad(valPtr);
1144  if (VarBlockCreator::Ref *varBlockRef = dynamic_cast<VarBlockCreator::Ref *>(_var))
1145  return VarCodeGeneration::codegen(varBlockRef, varName, Builder);
1146  else
1147  return VarCodeGeneration::codegen(_var, varName, Builder);
1148  } else if (_localVar) {
1149  ExprType varTy = _localVar->type();
1150  if (varTy.isFP() || varTy.isString()) {
1151  // LLVM_VALUE valPtr = resolveLocalVar(name(), Builder);
1152  LLVM_VALUE varPtr = _localVar->varPtr();
1153  assert(varPtr && "can not found symbol?");
1154  return Builder.CreateLoad(varPtr);
1155  }
1156  }
1157 
1158  assert(false);
1159  return 0;
1160 }
1161 
1162 LLVM_VALUE ExprVecNode::codegen(LLVM_BUILDER Builder) LLVM_BODY {
1163  std::vector<LLVM_VALUE> elems;
1164  ConstantInt *zero = ConstantInt::get(Type::getInt32Ty(Builder.getContext()), 0);
1165  for (int i = 0; i < numChildren(); i++) {
1166  LLVM_VALUE val = child(i)->codegen(Builder);
1167  elems.push_back(val->getType()->isVectorTy() ? Builder.CreateExtractElement(val, zero) : val);
1168  }
1169  return createVecVal(Builder, elems);
1170 }
1171 }
1172 
1173 #endif
SeExpr2::ExprType::isString
bool isString() const
Definition: ExprType.h:169
unescapeString
std::string unescapeString(const std::string &string)
Definition: StringUtils.h:24
llvm
Definition: Expression.h:31
SeExpr2::isString
const ExprStrNode * isString(const ExprNode *testee)
Definition: ExprPatterns.h:44
SeExpr2::ExprNode::numChildren
int numChildren() const
Number of children.
Definition: ExprNode.h:114
SeExpr2::ExprNode::type
const ExprType & type() const
The type of the node.
Definition: ExprNode.h:145
SeExpr2LLVMEvalStrVarRef
void SeExpr2LLVMEvalStrVarRef(SeExpr2::ExprVarRef *seVR, double *result)
SeExpr2::VarBlockCreator::Ref::stride
uint32_t stride() const
Definition: VarBlock.h:93
LLVM_BUILDER
double LLVM_BUILDER
Definition: ExprLLVM.h:34
SeExpr2::ExprType::type
Type type() const
Definition: ExprType.h:159
SeExpr2::ExprFuncStandard::getFuncType
FuncType getFuncType() const
Definition: ExprFuncStandard.h:145
SeExpr2::ExprStrNode::str
const char * str() const
Definition: ExprNode.h:509
SeExpr2::ExprType::isLifetimeUniform
bool isLifetimeUniform() const
Definition: ExprType.h:184
SeExpr2::ExprVarNode::name
const char * name() const
Definition: ExprNode.h:475
zero
When fbmScale is zero(the default)
SeExpr2::ExprLocalVarPhi
ExprLocalVar join (merge) references. Remembers which variables are possible assigners to this.
Definition: ExprEnv.h:67
SeExpr2::ExprType::dim
int dim() const
Definition: ExprType.h:160
ExprLLVMAll.h
ExprFunc.h
SeExpr2::ExprType
Definition: ExprType.h:39
SeExpr2::ExprFuncNode
Node that calls a function.
Definition: ExprNode.h:517
SeExpr2::ExprLocalVar::type
ExprType type() const
returns type of the variable
Definition: ExprEnv.h:51
SeExpr2::ExprFuncStandard::getFuncPointer
void * getFuncPointer() const
Definition: ExprFuncStandard.h:144
SeExpr2::ExprLocalVar::codegen
virtual LLVM_VALUE codegen(LLVM_BUILDER, const std::string &name, LLVM_VALUE referenceType) LLVM_BODY
LLVM value that has been allocated.
SeExpr2::VarBlockCreator::Ref::offset
uint32_t offset() const
Definition: VarBlock.h:92
SeExpr2::ExprFuncStandard::FuncType
FuncType
Definition: ExprFuncStandard.h:27
LLVM_VALUE
double LLVM_VALUE
Definition: ExprLLVM.h:33
SeExpr2
Definition: Context.h:22
ExprNode.h
SeExpr2::ExprNode::codegen
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
ExprLLVM.h
SeExpr2::VarBlockCreator::Ref
Internally implemented var ref used by SeExpr.
Definition: VarBlock.h:87
SeExpr2::ExprLocalVar::varPtr
virtual LLVM_VALUE varPtr()
LLVM value that has been pre-done.
Definition: ExprEnv.h:59
it
you may not use this file except in compliance with the License and the following modification to it
Definition: license.txt:10
SeExpr2::ExprLocalVarPhi::valid
bool valid() const
Definition: ExprEnv.h:81
SeExpr2::ExprType::isFP
bool isFP() const
Direct is predicate checks.
Definition: ExprType.h:164
SeExpr2::max
double max(double x, double y)
Definition: ExprBuiltins.h:42
SeExpr2::ExprVarNode
Node that references a variable.
Definition: ExprNode.h:465
StringUtils.h
a
Defined as a *alpha b *alpha< br ></div >< br > float< b > float a
Definition: userdoc.txt:174
SeExpr2::ExprVarRef::eval
virtual void eval(double *result)=0
returns this variable's value by setting result
SeExpr2::ExprFuncStandard
Definition: ExprFuncStandard.h:25
SeExpr2::ExprStrNode
Node that stores a string.
Definition: ExprNode.h:502
SeExpr2::ExprLocalVarPhi::_thenVar
ExprLocalVar * _thenVar
Definition: ExprEnv.h:90
SeExpr2LLVMEvalFPVarRef
void SeExpr2LLVMEvalFPVarRef(SeExpr2::ExprVarRef *seVR, double *result)
LLVM_BODY
#define LLVM_BODY
Definition: ExprLLVM.h:35
SeExpr2::ExprVarRef
abstract class for implementing variable references
Definition: Expression.h:45
SeExpr2::ExprNode::child
const ExprNode * child(size_t i) const
Get 0 indexed child.
Definition: ExprNode.h:117
SeExpr2::ExprVarRef::type
virtual ExprType type() const
returns (current) type
Definition: Expression.h:59
context
If a scalar is used in a vector context
Definition: userdoc.txt:436
SeExpr2::ExprFuncNode::promote
int promote(int i) const
Definition: ExprNode.h:590
b
Between a and b
Definition: userdoc.txt:180
pow
< br > pow($a, 0.5)+ $b< br >< br ></div > External variables can also be overridden by local assignment. &nbsp
SeExpr2::ExprLocalVarPhi::_elseVar
ExprLocalVar * _elseVar
Definition: ExprEnv.h:90
VarBlock.h