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>
27using namespace llvm;
28using 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
33namespace {
34
35Function *llvm_getFunction(LLVM_BUILDER Builder) { return Builder.GetInsertBlock()->getParent(); }
36
37Module *llvm_getModule(LLVM_BUILDER Builder) { return llvm_getFunction(Builder)->getParent(); }
38
40std::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
48 if (seFuncType == ExprFuncStandard::FUNCN || seFuncType == ExprFuncStandard::FUNCNV ||
49 seFuncType == ExprFuncStandard::FUNCNVV)
50 return true;
51 return false;
52}
53
55 if (seFuncType == ExprFuncStandard::FUNC1VV || seFuncType == ExprFuncStandard::FUNC2VV ||
56 seFuncType == ExprFuncStandard::FUNCNVV)
57 return true;
58 return false;
59}
60
62 if (seFuncType <= ExprFuncStandard::FUNC6 || seFuncType == ExprFuncStandard::FUNCN) return true;
63 return false;
64}
65
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) {
99 FT = FunctionType::get(doubleType, paramTypes, false);
100 } else if (sft == ExprFuncStandard::FUNC1VV) {
102 FT = FunctionType::get(voidType, paramTypes, false);
103 } else if (sft == ExprFuncStandard::FUNC2VV) {
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) {
114 FT = FunctionType::get(voidType, paramTypes, false);
115 } else
116 assert(false);
117
118 return FT;
119}
120
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
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
145LLVM_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
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
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
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
190AllocaInst *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();
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
208AllocaInst *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();
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
225std::pair<LLVM_VALUE, LLVM_VALUE> promoteBinaryOperandsToAppropriateVector(LLVM_BUILDER Builder,
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
234 if (op1Ty->isVectorTy()) std::swap(toPromote, target);
235
236 assert(target->getType()->isVectorTy());
237
238 unsigned dim = target->getType()->getVectorNumElements();
240
241 if (op1Ty->isVectorTy())
242 op2 = vecVal;
243 else
244 op1 = vecVal;
245
246 return std::make_pair(op1, op2);
247}
248
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
259 LLVMContext &llvmContext = Builder.getContext();
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
271std::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
277std::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
284std::vector<LLVM_VALUE> promoteArgs(std::vector<LLVM_VALUE> args,
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
296std::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
303 std::vector<LLVM_VALUE> actualArgs,
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) {
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) {
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
344 std::vector<LLVM_VALUE> args,
346 LLVMContext &llvmContext = Builder.getContext();
347
348 args = promoteArgs(args, Builder, seFuncType);
350
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);
361}
362
363// TODO: Is this necessary? why not use printf custom function?
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));
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()) {
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.
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");
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 }
517 }
518 } else {
519 return Builder.CreateLoad(Builder.CreateConstGEP1_32(strArg, 1));
520 }
521
522 assert(false);
523 return 0;
524}
525}
526
527extern "C" void SeExpr2LLVMEvalFPVarRef(ExprVarRef *seVR, double *result) { seVR->eval(result); }
528extern "C" void SeExpr2LLVMEvalStrVarRef(ExprVarRef *seVR, char **result) { seVR->eval((const char **)result); }
529
530namespace SeExpr2 {
531
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
541 for (int i = 0; i < numChildren(); i++) child(i)->codegen(Builder);
542 return 0;
543}
544
547 for (int i = 0; i < numChildren(); i++) lastVal = child(i)->codegen(Builder);
549 return lastVal;
550}
551
554 for (int i = 0; i < numChildren(); i++) lastVal = child(i)->codegen(Builder);
556 return lastVal;
557}
558
560 return ConstantFP::get(Builder.getContext(), APFloat(_val));
561}
562
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.
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
659LLVM_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
665 LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
666 LLVM_VALUE op2 = getFirstElement(child(1)->codegen(Builder), Builder);
667
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
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
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
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);
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
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();
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
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
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;
854 for (unsigned i = 0; i < args.size(); ++i)
855 if (args[i]->getType()->isVectorTy()) {
856 maxVectorArgType = args[i]->getType();
858 }
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();
869 }
870 }
871 }
872
873 if (!maxVectorArgType) // nothing needs distribution so just execute normally
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) {
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 }
895 }
896 return createVecVal(Builder, ret);
897}
898
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
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
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
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));
1008 AI->setName(childNode->name());
1009 }
1010
1011 return F;
1012}
1013
1015 return Builder.CreateGlobalStringPtr(unescapeString(_str));
1016}
1017
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
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
1054struct 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
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),
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.");
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();
1107 Value *variableOffsetIndex = ConstantInt::get(Type::getInt32Ty(llvmContext), variableOffset);
1110 Value *variableStrideValue = ConstantInt::get(Type::getInt32Ty(llvmContext), variableStride);
1111 if (dim == 1) {
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);
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
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
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
void SeExpr2LLVMEvalFPVarRef(SeExpr2::ExprVarRef *seVR, double *result)
void SeExpr2LLVMEvalStrVarRef(SeExpr2::ExprVarRef *seVR, double *result)
double LLVM_BUILDER
Definition ExprLLVM.h:34
#define LLVM_BODY
Definition ExprLLVM.h:35
double LLVM_VALUE
Definition ExprLLVM.h:33
std::string unescapeString(const std::string &string)
Definition StringUtils.h:24
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
Node that calls a function.
Definition ExprNode.h:517
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
ExprLocalVar join (merge) references. Remembers which variables are possible assigners to this.
Definition ExprEnv.h:67
LLVM_VALUE _varPtr
Definition ExprEnv.h:41
virtual LLVM_VALUE codegen(LLVM_BUILDER, const std::string &name, LLVM_VALUE referenceType) LLVM_BODY
LLVM value that has been allocated.
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
Node that stores a string.
Definition ExprNode.h:502
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
bool isString() const
Definition ExprType.h:169
bool isFP() const
Direct is predicate checks.
Definition ExprType.h:164
int dim() const
Definition ExprType.h:160
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
Node that references a variable.
Definition ExprNode.h:465
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
abstract class for implementing variable references
Definition Expression.h:45
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
Internally implemented var ref used by SeExpr.
Definition VarBlock.h:87
you may not use this file except in compliance with the License and the following modification to it
Definition license.txt:10
const ExprStrNode * isString(const ExprNode *testee)
When fbmScale is zero(the default)
Between a and b
Definition userdoc.txt:180
Defined as a *alpha b *alpha< br ></div >< br > float< b > float a
Definition userdoc.txt:174
If a scalar is used in a vector context
Definition userdoc.txt:436