17#include "ExprConfig.h"
19#ifdef SEEXPR_ENABLE_LLVM
35Function *llvm_getFunction(
LLVM_BUILDER Builder) {
return Builder.GetInsertBlock()->getParent(); }
37Module *llvm_getModule(
LLVM_BUILDER Builder) {
return llvm_getFunction(Builder)->getParent(); }
40std::string llvmTypeString(llvm::Type *type) {
42 llvm::raw_string_ostream rawStream(myString);
43 type->print(rawStream);
44 return rawStream.str();
48 if (seFuncType == ExprFuncStandard::FUNCN || seFuncType == ExprFuncStandard::FUNCNV ||
49 seFuncType == ExprFuncStandard::FUNCNVV)
55 if (seFuncType == ExprFuncStandard::FUNC1VV || seFuncType == ExprFuncStandard::FUNC2VV ||
56 seFuncType == ExprFuncStandard::FUNCNVV)
62 if (seFuncType <= ExprFuncStandard::FUNC6 || seFuncType == ExprFuncStandard::FUNCN)
return true;
67 assert(sft != ExprFuncStandard::NONE);
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);
75 if (sft <= ExprFuncStandard::FUNC6) {
76 std::vector<Type *> paramTypes;
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:
92 FT = FunctionType::get(doubleType, paramTypes,
false);
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);
121Type *createLLVMTyForSeExprType(LLVMContext &llvmContext,
ExprType seType) {
123 int dim = seType.
dim();
124 return dim == 1 ? Type::getDoubleTy(llvmContext) : VectorType::get(Type::getDoubleTy(llvmContext), dim);
128 return Type::getInt8PtrTy(llvmContext);
130 assert(!
"unknown SeExpr type encountered");
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));
146 if (!val.size())
return 0;
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);
158 Type *destTy = destPtr->getType()->getPointerElementType();
159 assert(destTy->isDoubleTy() || destTy->isArrayTy());
160 std::vector<LLVM_VALUE> vals;
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));
168 return createVecVal(Builder, vals);
172 Type *VTy = V->getType();
173 if (VTy->isDoubleTy())
return V;
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);
182 Type *srcTy = val->getType();
183 if (srcTy == destTy)
return val;
185 if (destTy->isDoubleTy())
return val;
187 return createVecVal(Builder, val, destTy->getVectorNumElements());
190AllocaInst *createAllocaInst(
LLVM_BUILDER Builder, Type *ty,
unsigned arraySize = 1,
const std::string &varName =
"") {
192 BasicBlock *entryBB = &llvm_getFunction(Builder)->getEntryBlock();
193 IRBuilder<>::InsertPoint oldIP = Builder.saveIP();
195 Builder.SetInsertPoint(&entryBB->front());
197 Builder.SetInsertPoint(entryBB);
200 LLVMContext &llvmContext = Builder.getContext();
201 LLVM_VALUE arraySizeVal = ConstantInt::get(Type::getInt32Ty(llvmContext), arraySize);
202 AllocaInst *varPtr = Builder.CreateAlloca(ty, arraySizeVal, varName);
204 Builder.restoreIP(oldIP);
208AllocaInst *createArray(
LLVM_BUILDER Builder, Type *ty,
unsigned arraySize,
const std::string &varName =
"") {
210 BasicBlock *entryBB = &llvm_getFunction(Builder)->getEntryBlock();
211 IRBuilder<>::InsertPoint oldIP = Builder.saveIP();
213 Builder.SetInsertPoint(&entryBB->front());
215 Builder.SetInsertPoint(entryBB);
218 ArrayType *arrayTy = ArrayType::get(ty, arraySize);
219 AllocaInst *varPtr = Builder.CreateAlloca(arrayTy, 0, varName);
221 Builder.restoreIP(oldIP);
225std::pair<LLVM_VALUE, LLVM_VALUE> promoteBinaryOperandsToAppropriateVector(
LLVM_BUILDER Builder,
228 Type *op1Ty = op1->getType();
229 Type *op2Ty = op2->getType();
230 if (op1Ty == op2Ty)
return std::make_pair(op1, op2);
234 if (op1Ty->isVectorTy()) std::swap(toPromote, target);
236 assert(target->getType()->isVectorTy());
238 unsigned dim = target->getType()->getVectorNumElements();
239 LLVM_VALUE vecVal = createVecVal(Builder, toPromote, dim);
241 if (op1Ty->isVectorTy())
246 return std::make_pair(op1, op2);
250 Type *valTy = val->getType();
251 if (refType.
isFP() && refType.
dim() > 1 && !valTy->isVectorTy()) {
252 return createVecVal(Builder, val, refType.
dim());
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);
272 std::vector<LLVM_VALUE> args;
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));
284std::vector<LLVM_VALUE> promoteArgs(std::vector<LLVM_VALUE> args,
287 if (isTakeOnlyDoubleArg(seFuncType))
return args;
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));
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]);
302std::vector<LLVM_VALUE> convertArgsToPointerAndLength(
LLVM_BUILDER Builder,
303 std::vector<LLVM_VALUE> actualArgs,
305 assert(isVarArg(seFuncType));
307 LLVMContext &llvmContext = Builder.getContext();
308 unsigned numArgs = actualArgs.size();
311 for (
unsigned i = 0; i < numArgs; ++i)
312 assert(actualArgs[i]->getType()->isDoubleTy() || actualArgs[i]->getType() == Type::getDoublePtrTy(llvmContext));
314 std::vector<LLVM_VALUE> args;
316 args.push_back(ConstantInt::get(Type::getInt32Ty(llvmContext), numArgs));
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);
324 args.push_back(doublePtr);
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);
338 args.push_back(Builder.CreateBitCast(arrayPtr, Type::getDoublePtrTy(llvmContext)));
344 std::vector<LLVM_VALUE> args,
346 LLVMContext &llvmContext = Builder.getContext();
348 args = promoteArgs(args, Builder, seFuncType);
349 args = replaceVecArgWithDoublePointer(Builder, args);
351 if (isVarArg(seFuncType)) args = convertArgsToPointerAndLength(Builder, args, seFuncType);
353 if (isReturnVector(seFuncType) ==
false)
return Builder.CreateCall(addrVal, args);
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);
365 LLVMContext &llvmContext = Builder.getContext();
366 std::vector<LLVM_VALUE> args;
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));
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));
391 Builder.CreateCall(callee, args);
392 return ConstantFP::get(Type::getDoubleTy(llvmContext), 0.0);
397 LLVMContext &llvmContext = Builder.getContext();
400 std::vector<LLVM_VALUE> args = codegenFuncCallArgs(Builder, funcNode);
402 assert(nargs == (
int)args.size());
405 unsigned sizeOfRet = (unsigned)funcNode->
type().
dim();
406 assert(sizeOfRet == 1 || funcNode->
type().
isFP());
409 createAllocaInst(Builder, Type::getDoubleTy(llvmContext), sizeOfRet);
412 unsigned sizeOfFpArgs = 1 + sizeOfRet;
413 unsigned sizeOfStrArgs = 2;
414 for (
int i = 0; i < nargs; ++i) {
416 if (argType.
isFP()) {
417 sizeOfFpArgs += std::max(funcNode->
promote(i), argType.
dim());
421 assert(
false &&
"invalid type encountered");
426 Type* int32Ty = Type::getInt32Ty(llvmContext);
427 Type* doubleTy = Type::getDoubleTy(llvmContext);
428 PointerType* int8PtrTy = Type::getInt8PtrTy(llvmContext);
429 Type* int64Ty = Type::getInt64Ty(llvmContext);
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");
438 Builder.CreateStore(ConstantFP::get(doubleTy, nargs), fpArg);
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));
447 unsigned fpIdx = 1 + sizeOfRet;
449 for (
int argIndex = 0; argIndex < nargs; ++argIndex) {
450 int opIndex = argIndex + 4;
452 if (argType.
isFP()) {
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);
462 fpIdx += argType.
dim();
465 int promote = funcNode->
promote(argIndex);
468 for (
int comp = 0; comp < promote; comp++) {
469 LLVM_VALUE fpArgPtr = Builder.CreateConstGEP1_32(fpArg, fpIdx + comp);
470 Builder.CreateStore(val, fpArgPtr);
474 Builder.CreateStore(args[argIndex], Builder.CreateConstGEP1_32(fpArg, fpIdx));
480 Builder.CreateStore(ConstantInt::get(int32Ty, strIdx), Builder.CreateConstGEP1_32(opDataArg, opIndex));
481 Builder.CreateStore(args[argIndex], Builder.CreateConstGEP1_32(strArg, strIdx));
487 Module* module = llvm_getModule(Builder);
491 GlobalVariable *dataGV =
new GlobalVariable(*module, int8PtrTy,
false, GlobalValue::InternalLinkage, ConstantPointerNull::get(int8PtrTy));
495 module->getFunction(
"SeExpr2LLVMEvalCustomFunction"),
501 ConstantInt::get(int64Ty, (uint64_t)funcNode)
506 int resultOffset = 1;
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);
514 resultArray.push_back(Builder.CreateLoad(ptr));
516 return createVecVal(Builder, resultArray);
519 return Builder.CreateLoad(Builder.CreateConstGEP1_32(strArg, 1));
533 Type *srcTy = val->getType();
534 if (srcTy->isVectorTy() || dim <= 1)
return val;
536 assert(srcTy->isDoubleTy());
537 return createVecVal(Builder, val, dim);
541 for (
int i = 0; i < numChildren(); i++) child(i)->codegen(Builder);
547 for (
int i = 0; i < numChildren(); i++) lastVal = child(i)->codegen(Builder);
554 for (
int i = 0; i < numChildren(); i++) lastVal = child(i)->codegen(Builder);
560 return ConstantFP::get(Builder.getContext(), APFloat(_val));
566 std::pair<LLVM_VALUE, LLVM_VALUE> pv = promoteBinaryOperandsToAppropriateVector(Builder, c1, c2);
575 return Builder.CreateFAdd(op1, op2);
577 return Builder.CreateFSub(op1, op2);
579 return Builder.CreateFMul(op1, op2);
581 return Builder.CreateFDiv(op1, op2);
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);
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);
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");
618 LLVM_VALUE len1 = Builder.CreateCall(strlen, { op1 });
619 LLVM_VALUE len2 = Builder.CreateCall(strlen, { op2 });
620 LLVM_VALUE len = Builder.CreateAdd(len1, len2);
623 LLVM_VALUE alloc = Builder.CreateCall(malloc, { len });
625 Builder.CreateCall(memset, { alloc,
zero, len });
628 Builder.CreateCall(strcat, { alloc, op1 });
629 LLVM_VALUE newAlloc = Builder.CreateGEP(
nullptr, alloc, len1);
630 Builder.CreateCall(strcat, { newAlloc, op2 });
634 APInt outAddr = APInt(64, (uint64_t)&_out);
635 LLVM_VALUE out = Constant::getIntegerValue(i8PtrPtrTy, outAddr);
636 Builder.CreateCall(free, { Builder.CreateLoad(out) });
637 Builder.CreateStore(alloc, out);
641 assert(
false &&
"unexpected op");
651 const std::string &varName = name();
652 LLVM_VALUE varPtr = _localVar->codegen(Builder, varName, val);
654 Builder.CreateStore(val, varPtr);
660 _varPtr = createAllocaInst(Builder, refValue->getType(), 1, varName);
665 LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
666 LLVM_VALUE op2 = getFirstElement(child(1)->codegen(Builder), Builder);
671 boolVal = Builder.CreateFCmpONE(op1, op2);
674 boolVal = Builder.CreateFCmpOEQ(op1, op2);
677 assert(
false &&
"Unkown CompareEq op.");
680 return Builder.CreateUIToFP(boolVal, op1->getType());
684 if (_op ==
'&' || _op ==
'|') {
686 LLVMContext &llvmContext = Builder.getContext();
688 LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
689 Type *opTy = op1->getType();
690 Constant *
zero = ConstantFP::get(opTy, 0.0);
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);
701 Type *intTy = Type::getInt1Ty(llvmContext);
702 Type *doubleTy = Type::getDoubleTy(llvmContext);
703 llvm::PHINode *phiNode =
nullptr;
706 Builder.SetInsertPoint(thenBlock);
708 op2IsOne = Builder.CreateFCmpUNE(op2,
zero);
709 Builder.CreateBr(phiBlock);
710 thenBlock = Builder.GetInsertBlock();
712 Builder.SetInsertPoint(elseBlock);
713 Builder.CreateBr(phiBlock);
714 Builder.SetInsertPoint(phiBlock);
716 phiNode = Builder.CreatePHI(intTy, 2,
"iftmp");
717 phiNode->addIncoming(op2IsOne, thenBlock);
718 phiNode->addIncoming(op1IsOne, elseBlock);
719 }
else if (_op ==
'|') {
721 Builder.SetInsertPoint(thenBlock);
722 Builder.CreateBr(phiBlock);
724 Builder.SetInsertPoint(elseBlock);
726 op2IsOne = Builder.CreateFCmpUNE(op2,
zero);
727 Builder.CreateBr(phiBlock);
728 elseBlock = Builder.GetInsertBlock();
730 Builder.SetInsertPoint(phiBlock);
731 phiNode = Builder.CreatePHI(intTy, 2,
"iftmp");
732 phiNode->addIncoming(op1IsOne, thenBlock);
733 phiNode->addIncoming(op2IsOne, elseBlock);
735 throw std::runtime_error(
"Logical inconsistency.");
737 LLVM_VALUE out = Builder.CreateUIToFP(phiNode, doubleTy);
740 LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
741 LLVM_VALUE op2 = getFirstElement(child(1)->codegen(Builder), Builder);
743 Type *opTy = op1->getType();
744 Constant *
zero = ConstantFP::get(opTy, 0.0);
751 boolVal = Builder.CreateOr(op1IsOne, op2IsOne);
759 boolVal = Builder.CreateFCmpOGE(op1, op2);
762 boolVal = Builder.CreateFCmpOLE(op1, op2);
765 boolVal = Builder.CreateFCmpOGT(op1, op2);
768 boolVal = Builder.CreateFCmpOLT(op1, op2);
771 assert(
false &&
"Unkown Compare op.");
774 return Builder.CreateUIToFP(boolVal, opTy);
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);
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);
798 Builder.SetInsertPoint(thenBlock);
799 LLVM_VALUE trueVal = promoteOperand(Builder, _type, child(1)->codegen(Builder));
800 Builder.CreateBr(phiBlock);
801 thenBlock = Builder.GetInsertBlock();
803 Builder.SetInsertPoint(elseBlock);
804 LLVM_VALUE falseVal = promoteOperand(Builder, _type, child(2)->codegen(Builder));
805 Builder.CreateBr(phiBlock);
806 elseBlock = Builder.GetInsertBlock();
808 Builder.SetInsertPoint(phiBlock);
809 llvm::PHINode *phiNode = Builder.CreatePHI(trueVal->getType(), 2,
"iftmp");
810 phiNode->addIncoming(trueVal, thenBlock);
811 phiNode->addIncoming(falseVal, elseBlock);
818 LLVMContext &llvmContext = Builder.getContext();
819 Module *M = llvm_getModule(Builder);
820 std::string calleeName(name());
823 Function *callee = M->getFunction(calleeName);
824 if (calleeName ==
"printf") {
826 FunctionType *FT = FunctionType::get(Type::getVoidTy(llvmContext), Type::getInt8PtrTy(llvmContext),
true);
827 callee = Function::Create(FT, GlobalValue::ExternalLinkage,
"printf", llvm_getModule(Builder));
829 return callPrintf(
this, Builder, callee);
831 std::vector<LLVM_VALUE> args =
832 promoteArgs(codegenFuncCallArgs(Builder,
this), Builder, callee->getFunctionType());
833 return Builder.CreateCall(callee, args);
839 if (!standfunc)
return callCustomFunction(
this, Builder);
844 FunctionType *llvmFuncType = getSeExprFuncStandardLLVMType(seFuncType, llvmContext);
846 ConstantInt *funcAddr = ConstantInt::get(Type::getInt64Ty(llvmContext), (uint64_t)fp);
847 LLVM_VALUE addrVal = Builder.CreateIntToPtr(funcAddr, PointerType::getUnqual(llvmFuncType));
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();
857 argumentIsVectorAndNeedsDistribution[i] = 1;
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;
873 if (!maxVectorArgType)
874 return executeStandardFunction(Builder, seFuncType, args, addrVal);
876 assert(maxVectorArgType->isVectorTy());
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;
884 for (
unsigned argIndex = 0; argIndex < args.size(); ++argIndex) {
886 if (argumentIsVectorAndNeedsDistribution[argIndex]) {
887 if (args[argIndex]->getType()->isPointerTy())
888 realArg = Builder.CreateLoad(Builder.CreateConstGEP2_32(
nullptr, args[argIndex], 0, vecComponent));
890 realArg = Builder.CreateExtractElement(args[argIndex], idx);
892 realArgs.push_back(realArg);
894 ret.push_back(executeStandardFunction(Builder, seFuncType, realArgs, addrVal));
896 return createVecVal(Builder, ret);
900 LLVM_VALUE condVal = getFirstElement(child(0)->codegen(Builder), Builder);
901 Type *condTy = condVal->getType();
903 LLVMContext &llvmContext = Builder.getContext();
905 Constant *
zero = ConstantFP::get(condTy, 0.0);
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);
914 Builder.SetInsertPoint(thenBlock);
915 child(1)->codegen(Builder);
916 thenBlock = Builder.GetInsertBlock();
918 Builder.SetInsertPoint(elseBlock);
919 child(2)->codegen(Builder);
920 elseBlock = Builder.GetInsertBlock();
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) {
930 if (finalVar->
valid()) {
932 Builder.SetInsertPoint(thenBlock);
934 Builder.SetInsertPoint(elseBlock);
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);
947 for (
auto &
it : _varEnv->merge(_varEnvMergeIndex)) {
948 const std::string &name =
it.first;
950 if (finalVar->
valid()) {
951 LLVM_VALUE _finalVarPtr = finalVar->
codegen(Builder, name +
"-merge", phis[idx]);
952 Builder.CreateStore(phis[idx++], _finalVarPtr);
956 Builder.SetInsertPoint(thenBlock);
957 Builder.CreateBr(phiBlock);
958 Builder.SetInsertPoint(elseBlock);
959 Builder.CreateBr(phiBlock);
961 Builder.SetInsertPoint(phiBlock);
967 IRBuilder<>::InsertPoint oldIP = Builder.saveIP();
968 LLVMContext &llvmContext = Builder.getContext();
971 Function *F = cast<Function>(child(0)->codegen(Builder));
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);
984 for (
int i = 1; i < numChildren(); i++) result = child(i)->codegen(Builder);
986 Builder.CreateRet(result);
987 Builder.restoreIP(oldIP);
992 LLVMContext &llvmContext = Builder.getContext();
995 std::vector<Type *> ParamTys;
996 for (
int i = 0; i < numChildren(); ++i) ParamTys.push_back(createLLVMTyForSeExprType(llvmContext, argType(i)));
998 Type *retTy = createLLVMTyForSeExprType(llvmContext, returnType());
1000 FunctionType *FT = FunctionType::get(retTy, ParamTys,
false);
1001 Function *F = Function::Create(FT, GlobalValue::InternalLinkage, name(), llvm_getModule(Builder));
1004 auto AI = F->arg_begin();
1005 for (
int i = 0, e = numChildren(); i != e; ++i, ++AI) {
1008 AI->setName(childNode->
name());
1022 if (op1->getType()->isDoubleTy())
return op1;
1024 LLVMContext &llvmContext = Builder.getContext();
1025 LLVM_VALUE idx = Builder.CreateFPToUI(op2, Type::getInt32Ty(llvmContext));
1026 return Builder.CreateExtractElement(op1, idx);
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);
1038 return Builder.CreateFSub(negateZero, op1);
1040 LLVM_VALUE neg = Builder.CreateFSub(negateZero, op1);
1041 return Builder.CreateFAdd(neg, one);
1045 return Builder.CreateSelect(eqZero, one,
zero);
1049 assert(
false &&
"not implemented.");
1054struct VarCodeGeneration {
1056 LLVMContext &llvmContext = Builder.getContext();
1059 Type *int64Ty = Type::getInt64Ty(llvmContext);
1060 Type *doubleTy = Type::getDoubleTy(llvmContext);
1061 PointerType *int8PtrTy = Type::getInt8PtrTy(llvmContext);
1064 bool isDouble = varRef->
type().
isFP();
1065 int dim = varRef->
type().
dim();
1068 AllocaInst *returnValue = createAllocaInst(Builder, isDouble ? doubleTy : int8PtrTy, dim);
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),
1080 ret = Builder.CreateLoad(returnValue);
1083 assert(dim == 3 &&
"future work.");
1084 ret = createVecValFromAlloca(Builder, returnValue, dim);
1087 AllocaInst *thisvar = createAllocaInst(Builder, ret->getType(), 1, varName);
1088 Builder.CreateStore(ret, thisvar);
1093 LLVMContext &llvmContext = Builder.getContext();
1095 int variableOffset = varRef->
offset();
1096 int variableStride = varRef->
stride();
1097 Function *function = llvm_getFunction(Builder);
1098 auto argIterator = function->arg_begin();
1100 llvm::Argument *variableBlock = &*(argIterator++);
1101 llvm::Argument *indirectIndex = &*(argIterator++);
1103 int dim = varRef->
type().
dim();
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);
1113 Value *variablePointer =
1114 varRef->
type().
isLifetimeUniform() ? baseMemory : Builder.CreateInBoundsGEP(baseMemory, indirectIndex);
1115 return Builder.CreateLoad(variablePointer);
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 =
1123 ? Builder.CreateInBoundsGEP(Type::getDoubleTy(llvmContext), baseMemory, componentIndex)
1124 : Builder.CreateInBoundsGEP(
1125 Type::getDoubleTy(llvmContext),
1127 Builder.CreateAdd(Builder.CreateMul(indirectIndex, variableStrideValue), componentIndex));
1128 loadedValues[component] = Builder.CreateLoad(variablePointer, varName);
1130 return createVecVal(Builder, loadedValues, varName);
1140 std::string varName(
"external_");
1141 varName.append(name());
1145 return VarCodeGeneration::codegen(varBlockRef, varName, Builder);
1147 return VarCodeGeneration::codegen(_var, varName, Builder);
1148 }
else if (_localVar) {
1153 assert(varPtr &&
"can not found symbol?");
1154 return Builder.CreateLoad(varPtr);
1163 std::vector<LLVM_VALUE> elems;
1164 ConstantInt *
zero = ConstantInt::get(Type::getInt32Ty(Builder.getContext()), 0);
1165 for (
int i = 0; i < numChildren(); i++) {
1167 elems.push_back(val->getType()->isVectorTy() ? Builder.CreateExtractElement(val,
zero) : val);
1169 return createVecVal(Builder, elems);
void SeExpr2LLVMEvalFPVarRef(SeExpr2::ExprVarRef *seVR, double *result)
void SeExpr2LLVMEvalStrVarRef(SeExpr2::ExprVarRef *seVR, double *result)
std::string unescapeString(const std::string &string)
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.
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
FuncType getFuncType() const
void * getFuncPointer() const
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.
virtual LLVM_VALUE varPtr()
LLVM value that has been pre-done.
ExprType type() const
returns type of the variable
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
int numChildren() const
Number of children.
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
const ExprNode * child(size_t i) const
Get 0 indexed child.
const ExprType & type() const
The type of the node.
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
Node that stores a string.
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
bool isFP() const
Direct is predicate checks.
bool isLifetimeUniform() const
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
Node that references a variable.
const char * name() const
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
abstract class for implementing variable references
virtual void eval(double *result)=0
returns this variable's value by setting result
virtual ExprType type() const
returns (current) type
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
Internally implemented var ref used by SeExpr.
you may not use this file except in compliance with the License and the following modification to it
const ExprStrNode * isString(const ExprNode *testee)
When fbmScale is zero(the default)
Defined as a *alpha b *alpha< br ></div >< br > float< b > float a
If a scalar is used in a vector context