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