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