6 #include "ExprConfig.h"
8 #if defined(SEEXPR_ENABLE_LLVM)
28 return Builder.GetInsertBlock()->getParent();
33 return llvm_getFunction(Builder)->getParent();
37 std::string llvmTypeString(llvm::Type *type)
40 llvm::raw_string_ostream rawStream(myString);
41 type->print(rawStream);
42 return rawStream.str();
47 return seFuncType == ExprFuncStandard::FUNCN || seFuncType == ExprFuncStandard::FUNCNV || seFuncType == ExprFuncStandard::FUNCNVV;
52 return seFuncType == ExprFuncStandard::FUNC1VV || seFuncType == ExprFuncStandard::FUNC2VV || seFuncType == ExprFuncStandard::FUNCNVV;
57 return seFuncType <= ExprFuncStandard::FUNC6 || seFuncType == ExprFuncStandard::FUNCN;
62 assert(sft != ExprFuncStandard::NONE);
64 Type *intType = Type::getInt32Ty(llvmContext);
65 Type *doubleType = Type::getDoubleTy(llvmContext);
66 Type *doublePtrType = PointerType::getUnqual(Type::getDoubleTy(llvmContext));
67 Type *voidType = Type::getVoidTy(llvmContext);
68 FunctionType *FT =
nullptr;
70 if (sft <= ExprFuncStandard::FUNC6) {
71 std::vector<Type *> paramTypes;
73 case ExprFuncStandard::FUNC6:
74 paramTypes.push_back(doubleType);
75 case ExprFuncStandard::FUNC5:
76 paramTypes.push_back(doubleType);
77 case ExprFuncStandard::FUNC4:
78 paramTypes.push_back(doubleType);
79 case ExprFuncStandard::FUNC3:
80 paramTypes.push_back(doubleType);
81 case ExprFuncStandard::FUNC2:
82 paramTypes.push_back(doubleType);
83 case ExprFuncStandard::FUNC1:
84 paramTypes.push_back(doubleType);
85 case ExprFuncStandard::FUNC0:
87 FT = FunctionType::get(doubleType, paramTypes,
false);
89 }
else if (sft == ExprFuncStandard::FUNC1V) {
90 std::array<Type*, 1> paramTypes = {doublePtrType};
91 FT = FunctionType::get(doubleType, paramTypes,
false);
92 }
else if (sft == ExprFuncStandard::FUNC2V) {
93 std::array<Type *, 2> paramTypes = {doublePtrType, doublePtrType};
94 FT = FunctionType::get(doubleType, paramTypes,
false);
95 }
else if (sft == ExprFuncStandard::FUNC1VV) {
96 std::array<Type *, 2> paramTypes = {doublePtrType, doublePtrType};
97 FT = FunctionType::get(voidType, paramTypes,
false);
98 }
else if (sft == ExprFuncStandard::FUNC2VV) {
99 std::array<Type *, 3> paramTypes = {doublePtrType, doublePtrType, doublePtrType};
100 FT = FunctionType::get(voidType, paramTypes,
false);
101 }
else if (sft == ExprFuncStandard::FUNCN) {
102 std::array<Type *, 2> paramTypes = {intType, doublePtrType};
103 FT = FunctionType::get(doubleType, paramTypes,
false);
104 }
else if (sft == ExprFuncStandard::FUNCNV) {
105 std::array<Type *, 2> paramTypes = {intType, doublePtrType};
106 FT = FunctionType::get(doubleType, paramTypes,
false);
107 }
else if (sft == ExprFuncStandard::FUNCNVV) {
108 std::array<Type *, 3> paramTypes = {doublePtrType, intType, doublePtrType};
109 FT = FunctionType::get(voidType, paramTypes,
false);
118 #if LLVM_VERSION_MAJOR >= 11
121 auto *funcCast = llvm::cast<llvm::CastInst>(addrVal);
122 assert(funcCast &&
"ERROR! The callee value is not a pointer cast!");
123 auto *funcPtr = llvm::cast<llvm::PointerType>(funcCast->getDestTy());
124 assert(funcPtr &&
"ERROR! The callee value does not contain a function!");
125 auto *TY = llvm::cast<llvm::FunctionType>(funcPtr->getElementType());
126 assert(TY &&
"ERROR! The callee value does not return a function signature!");
127 return Builder.CreateCall(TY, addrVal, args);
129 return Builder.CreateCall(addrVal, args);
133 Type *createLLVMTyForSeExprType(LLVMContext &llvmContext,
const ExprType& seType)
136 int dim = seType.
dim();
137 #if LLVM_VERSION_MAJOR >= 10
138 return dim == 1 ? Type::getDoubleTy(llvmContext) : VectorType::get(Type::getDoubleTy(llvmContext), dim, false);
140 return dim == 1 ? Type::getDoubleTy(llvmContext) : VectorType::get(Type::getDoubleTy(llvmContext), dim);
143 static_assert(
sizeof(
char*) == 8,
"Expect 64-bit pointers");
144 return Type::getInt8PtrTy(llvmContext);
146 assert(!
"unknown SeExpr type encountered");
153 LLVMContext &llvmContext = Builder.getContext();
154 #if LLVM_VERSION_MAJOR >= 10
155 VectorType *doubleVecTy = VectorType::get(Type::getDoubleTy(llvmContext), dim,
false);
157 VectorType *doubleVecTy = VectorType::get(Type::getDoubleTy(llvmContext), dim);
159 LLVM_VALUE vecVal = UndefValue::get(doubleVecTy);
160 for (
unsigned i = 0; i < dim; i++)
161 vecVal = Builder.CreateInsertElement(vecVal, val, ConstantInt::get(Type::getInt32Ty(llvmContext), i));
171 LLVMContext &llvmContext = Builder.getContext();
172 unsigned dim = val.size();
173 #if LLVM_VERSION_MAJOR >= 10
174 VectorType *elemType = VectorType::get(val[0]->getType(), dim,
false);
176 VectorType *elemType = VectorType::get(val[0]->getType(), dim);
178 LLVM_VALUE vecVal = UndefValue::get(elemType);
179 for (
unsigned i = 0; i < dim; i++)
180 vecVal = Builder.CreateInsertElement(vecVal, val[i], ConstantInt::get(Type::getInt32Ty(llvmContext), i), name);
186 Type *destTy = destPtr->getType()->getPointerElementType();
187 assert(destTy->isDoubleTy() || destTy->isArrayTy());
188 std::vector<LLVM_VALUE> vals;
190 for (
unsigned i = 0; i < vecLen; ++i) {
191 LLVM_VALUE ptr = destTy->isDoubleTy() ? CREATE_CONST_GEP1_32(Builder, destPtr, i) : Builder.CreateConstGEP2_32(nullptr, destPtr, 0, i);
192 vals.push_back(CREATE_LOAD(Builder, ptr));
195 return createVecVal(Builder, vals);
199 inline unsigned int getVectorNumElements(llvm::Type *ty)
201 #if LLVM_VERSION_MAJOR >= 11
202 assert(ty && ty->isVectorTy() &&
"This is not a vector type!");
203 auto *VT = llvm::cast<llvm::VectorType>(ty);
204 #if LLVM_VERSION_MAJOR >= 13
205 return VT->getElementCount().getKnownMinValue();
207 return VT->getNumElements();
210 return ty->getVectorNumElements();
216 Type *VTy = V->getType();
217 if (VTy->isDoubleTy())
219 if (VTy->isPointerTy())
222 assert(VTy->isVectorTy());
223 LLVMContext &llvmContext = Builder.getContext();
224 LLVM_VALUE zero = ConstantInt::get(Type::getInt32Ty(llvmContext), 0);
225 return Builder.CreateExtractElement(V, zero);
230 Type *srcTy = val->getType();
234 if (destTy->isDoubleTy())
237 return createVecVal(Builder, val, getVectorNumElements(destTy));
240 AllocaInst *createAllocaInst(
LLVM_BUILDER Builder, Type *ty,
unsigned arraySize = 1,
const StringRef &varName =
"")
243 BasicBlock *entryBB = &llvm_getFunction(Builder)->getEntryBlock();
244 IRBuilder<>::InsertPoint oldIP = Builder.saveIP();
245 if (!entryBB->empty())
246 Builder.SetInsertPoint(&entryBB->front());
248 Builder.SetInsertPoint(entryBB);
251 LLVMContext &llvmContext = Builder.getContext();
252 LLVM_VALUE arraySizeVal = ConstantInt::get(Type::getInt32Ty(llvmContext), arraySize);
253 AllocaInst *varPtr = Builder.CreateAlloca(ty, arraySizeVal,
static_cast<std::string
>(varName));
255 Builder.restoreIP(oldIP);
259 AllocaInst *createArray(
LLVM_BUILDER Builder, Type *ty,
unsigned arraySize,
const std::string &varName =
"")
262 BasicBlock *entryBB = &llvm_getFunction(Builder)->getEntryBlock();
263 IRBuilder<>::InsertPoint oldIP = Builder.saveIP();
264 if (!entryBB->empty())
265 Builder.SetInsertPoint(&entryBB->front());
267 Builder.SetInsertPoint(entryBB);
270 ArrayType *arrayTy = ArrayType::get(ty, arraySize);
271 AllocaInst *varPtr = Builder.CreateAlloca(arrayTy,
nullptr, varName);
273 Builder.restoreIP(oldIP);
279 Type *op1Ty = op1->getType();
280 Type *op2Ty = op2->getType();
282 return std::make_pair(op1, op2);
286 if (op1Ty->isVectorTy())
287 std::swap(toPromote, target);
289 assert(target->getType()->isVectorTy());
291 unsigned dim = getVectorNumElements(target->getType());
292 LLVM_VALUE vecVal = createVecVal(Builder, toPromote, dim);
294 if (op1Ty->isVectorTy())
299 return std::make_pair(op1, op2);
304 Type *valTy = val->getType();
305 if (refType.
isFP() && refType.
dim() > 1 && !valTy->isVectorTy()) {
306 return createVecVal(Builder, val, refType.
dim());
314 LLVMContext &llvmContext = Builder.getContext();
315 AllocaInst *doublePtr = createAllocaInst(Builder, Type::getDoubleTy(llvmContext), getVectorNumElements(vecVal->getType()));
316 for (
unsigned i = 0; i < 3; ++i) {
317 LLVM_VALUE idx = ConstantInt::get(Type::getInt32Ty(llvmContext), i);
318 LLVM_VALUE val = Builder.CreateExtractElement(vecVal, idx);
319 LLVM_VALUE ptr = CREATE_CONST_GEP1_32(Builder, doublePtr, i);
320 Builder.CreateStore(val, ptr);
327 std::vector<LLVM_VALUE> args;
334 std::vector<LLVM_VALUE> promoteArgs(std::vector<LLVM_VALUE> args,
LLVM_BUILDER Builder, FunctionType *llvmFuncType)
336 std::vector<LLVM_VALUE> ret;
337 for (
unsigned i = 0; i < args.size(); ++i)
338 ret.push_back(promoteToTy(args[i], llvmFuncType->getParamType(i), Builder));
344 if (isTakeOnlyDoubleArg(seFuncType))
347 LLVMContext &llvmContext = Builder.getContext();
348 #if LLVM_VERSION_MAJOR >= 10
349 VectorType *destTy = VectorType::get(Type::getDoubleTy(llvmContext), 3,
false);
351 VectorType *destTy = VectorType::get(Type::getDoubleTy(llvmContext), 3);
353 std::vector<LLVM_VALUE> ret;
354 ret.reserve(args.size());
355 for (
auto & arg : args)
356 ret.push_back(promoteToTy(arg, destTy, Builder));
360 std::vector<LLVM_VALUE> replaceVecArgWithDoublePointer(
LLVM_BUILDER Builder, std::vector<LLVM_VALUE> args)
362 for (
auto & arg : args)
363 if (arg->getType()->isVectorTy())
364 arg = storeVectorToDoublePtr(Builder, arg);
370 assert(isVarArg(seFuncType));
372 LLVMContext &llvmContext = Builder.getContext();
373 unsigned numArgs = actualArgs.size();
376 for (
unsigned i = 0; i < numArgs; ++i)
377 assert(actualArgs[i]->getType()->isDoubleTy() || actualArgs[i]->getType() == Type::getDoublePtrTy(llvmContext));
379 std::vector<LLVM_VALUE> args;
381 args.push_back(ConstantInt::get(Type::getInt32Ty(llvmContext), numArgs));
383 if (seFuncType == ExprFuncStandard::FUNCN) {
384 AllocaInst *doublePtr = createAllocaInst(Builder, Type::getDoubleTy(llvmContext), numArgs);
385 for (
unsigned i = 0; i < numArgs; ++i) {
386 LLVM_VALUE ptr = CREATE_CONST_GEP1_32(Builder, doublePtr, i);
387 Builder.CreateStore(actualArgs[i], ptr);
389 args.push_back(doublePtr);
393 AllocaInst *arrayPtr = createArray(Builder, ArrayType::get(Type::getDoubleTy(llvmContext), 3), numArgs);
394 for (
unsigned i = 0; i < numArgs; ++i) {
396 LLVM_VALUE subArrayPtr = Builder.CreateConstGEP2_32(
nullptr, arrayPtr, 0, i);
397 for (
unsigned j = 0; j < 3; ++j) {
398 LLVM_VALUE destAddr = Builder.CreateConstGEP2_32(
nullptr, subArrayPtr, 0, j);
399 LLVM_VALUE srcAddr = CREATE_CONST_GEP1_32(Builder, toInsert, j);
400 Builder.CreateStore(CREATE_LOAD(Builder, srcAddr), destAddr);
403 args.push_back(Builder.CreateBitCast(arrayPtr, Type::getDoublePtrTy(llvmContext)));
409 LLVMContext &llvmContext = Builder.getContext();
411 args = promoteArgs(args, Builder, seFuncType);
412 args = replaceVecArgWithDoublePointer(Builder, args);
414 if (isVarArg(seFuncType))
415 args = convertArgsToPointerAndLength(Builder, args, seFuncType);
417 if (isReturnVector(seFuncType) ==
false)
418 return CreateCall(Builder, addrVal, args);
422 AllocaInst *retPtr = createAllocaInst(Builder, Type::getDoubleTy(llvmContext), 3);
423 args.insert(args.begin(), retPtr);
424 CreateCall(Builder, addrVal, replaceVecArgWithDoublePointer(Builder, args));
425 return createVecValFromAlloca(Builder, retPtr, 3);
431 LLVMContext &llvmContext = Builder.getContext();
432 std::vector<LLVM_VALUE> args;
436 const auto *formatStrNode =
dynamic_cast<const ExprStrNode *
>(seFunc->
child(0));
437 assert(formatStrNode);
438 std::string formatStr(formatStrNode->str());
439 std::string::size_type pos = std::string::npos;
440 while ((pos = formatStr.find(
"%v")) != std::string::npos)
441 formatStr.replace(pos, 2, std::string(
"[%f,%f,%f]"));
442 formatStr.append(
"\n");
443 args.push_back(Builder.CreateGlobalStringPtr(formatStr));
448 if (arg->getType()->isVectorTy()) {
449 AllocaInst *vecArray = storeVectorToDoublePtr(Builder, arg);
450 for (
unsigned i = 0; i < getVectorNumElements(arg->getType()); ++i) {
451 LLVM_VALUE elemPtr = CREATE_CONST_GEP1_32(Builder, vecArray, i);
452 args.push_back(CREATE_LOAD(Builder, elemPtr));
458 CreateCall(Builder, callee, args);
459 return ConstantFP::get(Type::getDoubleTy(llvmContext), 0.0);
465 LLVMContext &llvmContext = Builder.getContext();
468 std::vector<LLVM_VALUE> args = codegenFuncCallArgs(Builder, funcNode);
470 assert(nargs == (
int)args.size());
473 auto sizeOfRet = (unsigned)funcNode->
type().
dim();
474 assert(sizeOfRet == 1 || funcNode->
type().
isFP());
477 createAllocaInst(Builder, Type::getDoubleTy(llvmContext), sizeOfRet);
480 unsigned sizeOfFpArgs = 1 + sizeOfRet;
481 unsigned sizeOfStrArgs = 2;
482 for (
int i = 0; i < nargs; ++i) {
484 if (argType.
isFP()) {
489 assert(
false &&
"invalid type encountered");
494 Type *int32Ty = Type::getInt32Ty(llvmContext);
495 Type *doubleTy = Type::getDoubleTy(llvmContext);
496 PointerType *int8PtrTy = Type::getInt8PtrTy(llvmContext);
497 Type *int64Ty = Type::getInt64Ty(llvmContext);
500 AllocaInst *opDataArg = createAllocaInst(Builder, int32Ty, (
unsigned)nargs + 4,
"opDataArgPtr");
501 AllocaInst *fpArg = createAllocaInst(Builder, doubleTy, sizeOfFpArgs,
"fpArgPtr");
502 AllocaInst *strArg = createAllocaInst(Builder, int8PtrTy, sizeOfStrArgs,
"strArgPtr");
505 Builder.CreateStore(ConstantFP::get(doubleTy, nargs), fpArg);
508 Builder.CreateStore(ConstantInt::get(int32Ty, 0), CREATE_CONST_GEP1_32(Builder, opDataArg, 0));
509 Builder.CreateStore(ConstantInt::get(int32Ty, 1), CREATE_CONST_GEP1_32(Builder, opDataArg, 1));
510 Builder.CreateStore(ConstantInt::get(int32Ty, 1), CREATE_CONST_GEP1_32(Builder, opDataArg, 2));
511 Builder.CreateStore(ConstantInt::get(int32Ty, 0), CREATE_CONST_GEP1_32(Builder, opDataArg, 3));
514 unsigned fpIdx = 1 + sizeOfRet;
516 for (
int argIndex = 0; argIndex < nargs; ++argIndex) {
517 int opIndex = argIndex + 4;
519 if (argType.
isFP()) {
521 Builder.CreateStore(ConstantInt::get(int32Ty, fpIdx), CREATE_CONST_GEP1_32(Builder, opDataArg, opIndex));
522 if (argType.
dim() > 1) {
523 for (
int comp = 0; comp < argType.
dim(); comp++) {
524 LLVM_VALUE compIndex = ConstantInt::get(int32Ty, comp);
525 LLVM_VALUE val = Builder.CreateExtractElement(args[argIndex], compIndex);
526 LLVM_VALUE fpArgPtr = CREATE_CONST_GEP1_32(Builder, fpArg, fpIdx + comp);
527 Builder.CreateStore(val, fpArgPtr);
529 fpIdx += argType.
dim();
532 int promote = funcNode->
promote(argIndex);
535 for (
int comp = 0; comp < promote; comp++) {
536 LLVM_VALUE fpArgPtr = CREATE_CONST_GEP1_32(Builder, fpArg, fpIdx + comp);
537 Builder.CreateStore(val, fpArgPtr);
541 Builder.CreateStore(args[argIndex], CREATE_CONST_GEP1_32(Builder, fpArg, fpIdx));
547 Builder.CreateStore(ConstantInt::get(int32Ty, strIdx), CREATE_CONST_GEP1_32(Builder, opDataArg, opIndex));
548 Builder.CreateStore(args[argIndex], CREATE_CONST_GEP1_32(Builder, strArg, strIdx));
554 Module *module = llvm_getModule(Builder);
558 auto *dataGV =
new GlobalVariable(*module, int8PtrTy,
false, GlobalValue::InternalLinkage, ConstantPointerNull::get(int8PtrTy));
561 Builder.CreateCall(module->getFunction(
"KSeExprLLVMEvalCustomFunction"), {opDataArg, fpArg, strArg, dataGV, ConstantInt::get(int64Ty, reinterpret_cast<uint64_t>(funcNode))});
564 int resultOffset = 1;
566 if (sizeOfRet == 1) {
567 return CREATE_LOAD(Builder, CREATE_CONST_GEP1_32(Builder, fpArg, resultOffset));
568 }
else if (sizeOfRet > 1) {
569 std::vector<LLVM_VALUE> resultArray;
570 for (
unsigned int comp = 0; comp < sizeOfRet; comp++) {
571 LLVM_VALUE ptr = CREATE_CONST_GEP1_32(Builder, fpArg, resultOffset + comp);
572 resultArray.push_back(CREATE_LOAD(Builder, ptr));
574 return createVecVal(Builder, resultArray);
577 return CREATE_LOAD(Builder, CREATE_CONST_GEP1_32(Builder, strArg, 1));
591 seVR->
eval((
const char **)result);
598 Type *srcTy = val->getType();
599 if (srcTy->isVectorTy() || dim <= 1)
602 assert(srcTy->isDoubleTy());
603 return createVecVal(Builder, val, dim);
608 for (
int i = 0; i < numChildren(); i++)
609 child(i)->codegen(Builder);
616 for (
int i = 0; i < numChildren(); i++)
617 lastVal = child(i)->codegen(Builder);
625 for (
int i = 0; i < numChildren(); i++)
626 lastVal = child(i)->codegen(Builder);
633 return ConstantFP::get(Builder.getContext(), APFloat(_val));
640 std::pair<LLVM_VALUE, LLVM_VALUE> pv = promoteBinaryOperandsToAppropriateVector(Builder, c1, c2);
649 return Builder.CreateFAdd(op1, op2);
651 return Builder.CreateFSub(op1, op2);
653 return Builder.CreateFMul(op1, op2);
655 return Builder.CreateFDiv(op1, op2);
661 Function *floorFun = Intrinsic::getDeclaration(llvm_getModule(Builder),
Intrinsic::floor, op1->getType());
662 LLVM_VALUE normal = Builder.CreateFSub(a, Builder.CreateFMul(Builder.CreateCall(floorFun, {aOverB}), b));
663 Constant *zero = ConstantFP::get(op1->getType(), 0.0);
664 return Builder.CreateSelect(Builder.CreateFCmpOEQ(zero, op1), zero, normal);
670 std::vector<Type *> arg_type;
671 arg_type.push_back(op1->getType());
672 Function *fun = Intrinsic::getDeclaration(llvm_getModule(Builder), Intrinsic::pow, arg_type);
673 std::vector<LLVM_VALUE> ops = {op1, op2};
674 return Builder.CreateCall(fun, ops);
679 LLVMContext &context = Builder.getContext();
680 Module *module = llvm_getModule(Builder);
681 PointerType *i8PtrPtrTy = PointerType::getUnqual(Type::getInt8PtrTy(context));
682 Type *i32Ty = Type::getInt32Ty(context);
683 Function *strlen = module->getFunction(
"strlen");
684 Function *malloc = module->getFunction(
"malloc");
685 Function *free = module->getFunction(
"free");
686 Function *memset = module->getFunction(
"memset");
687 Function *strcat = module->getFunction(
"strcat");
693 LLVM_VALUE len1 = Builder.CreateCall(strlen, {op1});
694 LLVM_VALUE len2 = Builder.CreateCall(strlen, {op2});
695 LLVM_VALUE len = Builder.CreateAdd(len1, len2);
698 LLVM_VALUE alloc = Builder.CreateCall(malloc, {len});
700 Builder.CreateCall(memset, {alloc, zero, len});
703 Builder.CreateCall(strcat, {alloc, op1});
704 LLVM_VALUE newAlloc = Builder.CreateGEP(
nullptr, alloc, len1);
705 Builder.CreateCall(strcat, {newAlloc, op2});
709 APInt outAddr = APInt(64,
reinterpret_cast<uint64_t
>(&_out));
710 LLVM_VALUE out = Constant::getIntegerValue(i8PtrPtrTy, outAddr);
711 Builder.CreateCall(free, {CREATE_LOAD(Builder, out)});
712 Builder.CreateStore(alloc, out);
716 assert(
false &&
"unexpected op");
727 const std::string &varName = name();
728 LLVM_VALUE varPtr = _localVar->codegen(Builder, varName, val);
730 Builder.CreateStore(val, varPtr);
737 _varPtr = createAllocaInst(Builder, refValue->getType(), 1, varName);
743 LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
744 LLVM_VALUE op2 = getFirstElement(child(1)->codegen(Builder), Builder);
753 boolVal = Builder.CreateFCmpONE(op1, op2);
756 boolVal = Builder.CreateFCmpOEQ(op1, op2);
759 assert(
false &&
"Unkown CompareEq op.");
761 return Builder.CreateUIToFP(boolVal, op1->getType());
764 LLVMContext &llvmContext = Builder.getContext();
765 Module *module = llvm_getModule(Builder);
766 Type *doubleTy = Type::getDoubleTy(llvmContext);
767 Function *strcmp = module->getFunction(
"strcmp");
769 LLVM_VALUE val = Builder.CreateCall(strcmp, {op1, op2});
770 Constant *zero = ConstantInt::get(strcmp->getReturnType(), 0);
774 boolVal = Builder.CreateICmpNE(val, zero);
777 boolVal = Builder.CreateICmpEQ(val, zero);
780 assert(
false &&
"Unkown CompareEq op.");
782 return Builder.CreateUIToFP(boolVal, doubleTy);
788 if (_op ==
'&' || _op ==
'|') {
790 LLVMContext &llvmContext = Builder.getContext();
792 LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
793 Type *opTy = op1->getType();
794 Constant *zero = ConstantFP::get(opTy, 0.0);
796 LLVM_VALUE op1IsOne = Builder.CreateFCmpUNE(op1, zero);
798 Function *F = llvm_getFunction(Builder);
799 BasicBlock *thenBlock = BasicBlock::Create(llvmContext,
"then", F);
800 BasicBlock *elseBlock = BasicBlock::Create(llvmContext,
"else", F);
801 BasicBlock *phiBlock = BasicBlock::Create(llvmContext,
"phi", F);
802 Builder.CreateCondBr(op1IsOne, thenBlock, elseBlock);
805 Type *intTy = Type::getInt1Ty(llvmContext);
806 Type *doubleTy = Type::getDoubleTy(llvmContext);
807 llvm::PHINode *phiNode =
nullptr;
810 Builder.SetInsertPoint(thenBlock);
812 op2IsOne = Builder.CreateFCmpUNE(op2, zero);
813 Builder.CreateBr(phiBlock);
814 thenBlock = Builder.GetInsertBlock();
816 Builder.SetInsertPoint(elseBlock);
817 Builder.CreateBr(phiBlock);
818 Builder.SetInsertPoint(phiBlock);
820 phiNode = Builder.CreatePHI(intTy, 2,
"iftmp");
821 phiNode->addIncoming(op2IsOne, thenBlock);
822 phiNode->addIncoming(op1IsOne, elseBlock);
823 }
else if (_op ==
'|') {
825 Builder.SetInsertPoint(thenBlock);
826 Builder.CreateBr(phiBlock);
828 Builder.SetInsertPoint(elseBlock);
830 op2IsOne = Builder.CreateFCmpUNE(op2, zero);
831 Builder.CreateBr(phiBlock);
832 elseBlock = Builder.GetInsertBlock();
834 Builder.SetInsertPoint(phiBlock);
835 phiNode = Builder.CreatePHI(intTy, 2,
"iftmp");
836 phiNode->addIncoming(op1IsOne, thenBlock);
837 phiNode->addIncoming(op2IsOne, elseBlock);
839 throw std::runtime_error(
"Logical inconsistency.");
841 LLVM_VALUE out = Builder.CreateUIToFP(phiNode, doubleTy);
844 LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
845 LLVM_VALUE op2 = getFirstElement(child(1)->codegen(Builder), Builder);
847 Type *opTy = op1->getType();
848 Constant *zero = ConstantFP::get(opTy, 0.0);
853 LLVM_VALUE op1IsOne = Builder.CreateFCmpUNE(op1, zero);
854 LLVM_VALUE op2IsOne = Builder.CreateFCmpUNE(op2, zero);
855 boolVal = Builder.CreateOr(op1IsOne, op2IsOne);
863 boolVal = Builder.CreateFCmpOGE(op1, op2);
866 boolVal = Builder.CreateFCmpOLE(op1, op2);
869 boolVal = Builder.CreateFCmpOGT(op1, op2);
872 boolVal = Builder.CreateFCmpOLT(op1, op2);
875 assert(
false &&
"Unkown Compare op.");
878 return Builder.CreateUIToFP(boolVal, opTy);
885 LLVM_VALUE condVal = getFirstElement(child(0)->codegen(Builder), Builder);
886 LLVM_VALUE cond = Builder.CreateFCmpUNE(condVal,
887 ConstantFP::get(condVal->getType(), 0.0));
888 LLVM_VALUE trueVal = child(1)->codegen(Builder);
889 LLVM_VALUE falseVal = child(2)->codegen(Builder);
890 std::pair<LLVM_VALUE, LLVM_VALUE> pv = promoteBinaryOperandsToAppropriateVector(Builder, trueVal, falseVal);
891 return Builder.CreateSelect(cond, pv.first, pv.second);
893 LLVM_VALUE condVal = getFirstElement(child(0)->codegen(Builder), Builder);
894 LLVM_VALUE condAsBool = Builder.CreateFCmpUNE(condVal, ConstantFP::get(condVal->getType(), 0.0));
895 LLVMContext &llvmContext = Builder.getContext();
896 Function *F = llvm_getFunction(Builder);
897 BasicBlock *thenBlock = BasicBlock::Create(llvmContext,
"then", F);
898 BasicBlock *elseBlock = BasicBlock::Create(llvmContext,
"else", F);
899 BasicBlock *phiBlock = BasicBlock::Create(llvmContext,
"phi", F);
900 Builder.CreateCondBr(condAsBool, thenBlock, elseBlock);
902 Builder.SetInsertPoint(thenBlock);
903 LLVM_VALUE trueVal = promoteOperand(Builder, _type, child(1)->codegen(Builder));
904 Builder.CreateBr(phiBlock);
905 thenBlock = Builder.GetInsertBlock();
907 Builder.SetInsertPoint(elseBlock);
908 LLVM_VALUE falseVal = promoteOperand(Builder, _type, child(2)->codegen(Builder));
909 Builder.CreateBr(phiBlock);
910 elseBlock = Builder.GetInsertBlock();
912 Builder.SetInsertPoint(phiBlock);
913 llvm::PHINode *phiNode = Builder.CreatePHI(trueVal->getType(), 2,
"iftmp");
914 phiNode->addIncoming(trueVal, thenBlock);
915 phiNode->addIncoming(falseVal, elseBlock);
923 LLVMContext &llvmContext = Builder.getContext();
924 Module *M = llvm_getModule(Builder);
925 std::string calleeName(name());
928 Function *callee = M->getFunction(calleeName);
929 if (calleeName ==
"printf") {
931 FunctionType *FT = FunctionType::get(Type::getVoidTy(llvmContext), Type::getInt8PtrTy(llvmContext),
true);
932 callee = Function::Create(FT, GlobalValue::ExternalLinkage,
"printf", llvm_getModule(Builder));
934 return callPrintf(
this, Builder, callee);
936 std::vector<LLVM_VALUE> args = promoteArgs(codegenFuncCallArgs(Builder,
this), Builder, callee->getFunctionType());
937 return Builder.CreateCall(callee, args);
942 const auto *standfunc =
dynamic_cast<const ExprFuncStandard *
>(_func->funcx());
944 return callCustomFunction(
this, Builder);
949 FunctionType *llvmFuncType = getSeExprFuncStandardLLVMType(seFuncType, llvmContext);
950 void *fp = standfunc->getFuncPointer();
951 ConstantInt *funcAddr = ConstantInt::get(Type::getInt64Ty(llvmContext),
reinterpret_cast<uint64_t
>(fp));
952 LLVM_VALUE addrVal = Builder.CreateIntToPtr(funcAddr, PointerType::getUnqual(llvmFuncType));
955 std::vector<LLVM_VALUE> args = codegenFuncCallArgs(Builder,
this);
956 std::vector<int> argumentIsVectorAndNeedsDistribution(args.size(), 0);
957 Type *maxVectorArgType =
nullptr;
958 if (seFuncType == ExprFuncStandard::FUNCN) {
959 for (
unsigned i = 0; i < args.size(); ++i) {
960 if (args[i]->getType()->isVectorTy()) {
961 maxVectorArgType = args[i]->getType();
962 argumentIsVectorAndNeedsDistribution[i] = 1;
965 }
else if (seFuncType == ExprFuncStandard::FUNCNV || seFuncType == ExprFuncStandard::FUNCNVV) {
967 unsigned shift = isReturnVector(seFuncType) ? 1 : 0;
968 for (
unsigned i = 0; i < args.size(); ++i) {
969 Type *paramType = llvmFuncType->getParamType(i + shift);
970 Type *argType = args[i]->getType();
971 if (argType->isVectorTy() && paramType->isDoubleTy()) {
972 maxVectorArgType = args[i]->getType();
973 argumentIsVectorAndNeedsDistribution[i] = 1;
978 if (!maxVectorArgType)
979 return executeStandardFunction(Builder, seFuncType, args, addrVal);
981 assert(maxVectorArgType->isVectorTy());
983 std::vector<LLVM_VALUE> ret;
984 for (
unsigned vecComponent = 0; vecComponent < getVectorNumElements(maxVectorArgType); ++vecComponent) {
985 LLVM_VALUE idx = ConstantInt::get(Type::getInt32Ty(llvmContext), vecComponent);
986 std::vector<LLVM_VALUE> realArgs;
989 for (
unsigned argIndex = 0; argIndex < args.size(); ++argIndex) {
991 if (argumentIsVectorAndNeedsDistribution[argIndex]) {
992 if (args[argIndex]->getType()->isPointerTy())
993 realArg = CREATE_LOAD(Builder, Builder.CreateConstGEP2_32(
nullptr, args[argIndex], 0, vecComponent));
995 realArg = Builder.CreateExtractElement(args[argIndex], idx);
997 realArgs.push_back(realArg);
999 ret.push_back(executeStandardFunction(Builder, seFuncType, realArgs, addrVal));
1001 return createVecVal(Builder, ret);
1006 LLVM_VALUE condVal = getFirstElement(child(0)->codegen(Builder), Builder);
1007 Type *condTy = condVal->getType();
1009 LLVMContext &llvmContext = Builder.getContext();
1011 Constant *zero = ConstantFP::get(condTy, 0.0);
1012 LLVM_VALUE intCond = Builder.CreateFCmpUNE(condVal, zero);
1014 Function *F = llvm_getFunction(Builder);
1015 BasicBlock *thenBlock = BasicBlock::Create(llvmContext,
"then", F);
1016 BasicBlock *elseBlock = BasicBlock::Create(llvmContext,
"else", F);
1017 BasicBlock *phiBlock = BasicBlock::Create(llvmContext,
"phi", F);
1018 Builder.CreateCondBr(intCond, thenBlock, elseBlock);
1020 Builder.SetInsertPoint(thenBlock);
1021 child(1)->codegen(Builder);
1022 thenBlock = Builder.GetInsertBlock();
1024 Builder.SetInsertPoint(elseBlock);
1025 child(2)->codegen(Builder);
1026 elseBlock = Builder.GetInsertBlock();
1030 Builder.SetInsertPoint(phiBlock);
1031 const auto &merges = _varEnv->merge(_varEnvMergeIndex);
1032 std::vector<LLVM_VALUE> phis;
1033 phis.reserve(merges.size());
1034 for (
const auto &it : merges) {
1036 if (finalVar->
valid()) {
1038 Builder.SetInsertPoint(thenBlock);
1040 Builder.SetInsertPoint(elseBlock);
1043 Type *finalType = thenValue->getType();
1044 Builder.SetInsertPoint(phiBlock);
1045 PHINode *phi = Builder.CreatePHI(finalType, 2, it.first);
1046 phi->addIncoming(thenValue, thenBlock);
1047 phi->addIncoming(elseValue, elseBlock);
1048 phis.push_back(phi);
1053 for (
auto &it : _varEnv->merge(_varEnvMergeIndex)) {
1054 const std::string &name = it.first;
1056 if (finalVar->
valid()) {
1057 LLVM_VALUE _finalVarPtr = finalVar->
codegen(Builder, name +
"-merge", phis[idx]);
1058 Builder.CreateStore(phis[idx++], _finalVarPtr);
1062 Builder.SetInsertPoint(thenBlock);
1063 Builder.CreateBr(phiBlock);
1064 Builder.SetInsertPoint(elseBlock);
1065 Builder.CreateBr(phiBlock);
1067 Builder.SetInsertPoint(phiBlock);
1074 IRBuilder<>::InsertPoint oldIP = Builder.saveIP();
1075 LLVMContext &llvmContext = Builder.getContext();
1078 auto *F = cast<Function>(child(0)->codegen(Builder));
1081 BasicBlock *BB = BasicBlock::Create(llvmContext,
"entry", F);
1082 Builder.SetInsertPoint(BB);
1083 for (
auto & AI : F->args()) {
1084 AllocaInst *Alloca = createAllocaInst(Builder, AI.getType(), 1, AI.getName());
1085 Alloca->takeName(&AI);
1086 Builder.CreateStore(&AI, Alloca);
1090 for (
int i = 1; i < numChildren(); i++)
1091 result = child(i)->codegen(Builder);
1093 Builder.CreateRet(result);
1094 Builder.restoreIP(oldIP);
1100 LLVMContext &llvmContext = Builder.getContext();
1103 std::vector<Type *> ParamTys;
1104 ParamTys.reserve(numChildren());
1105 for (
int i = 0; i < numChildren(); ++i)
1106 ParamTys.push_back(createLLVMTyForSeExprType(llvmContext, argType(i)));
1108 Type *retTy = createLLVMTyForSeExprType(llvmContext, returnType());
1110 FunctionType *FT = FunctionType::get(retTy, ParamTys,
false);
1111 Function *F = Function::Create(FT, GlobalValue::InternalLinkage, name(), llvm_getModule(Builder));
1114 auto *AI = F->arg_begin();
1115 for (
int i = 0, e = numChildren(); i != e; ++i, ++AI) {
1116 const auto *childNode =
dynamic_cast<const ExprVarNode *
>(child(i));
1118 AI->setName(childNode->name());
1134 if (op1->getType()->isDoubleTy())
1137 LLVMContext &llvmContext = Builder.getContext();
1138 LLVM_VALUE idx = Builder.CreateFPToUI(op2, Type::getInt32Ty(llvmContext));
1139 return Builder.CreateExtractElement(op1, idx);
1145 Type *op1Ty = op1->getType();
1146 Constant *negateZero = ConstantFP::getZeroValueForNegation(op1Ty);
1147 Constant *zero = ConstantFP::get(op1Ty, 0.0);
1148 Constant *one = ConstantFP::get(op1Ty, 1.0);
1152 return Builder.CreateFSub(negateZero, op1);
1154 LLVM_VALUE neg = Builder.CreateFSub(negateZero, op1);
1155 return Builder.CreateFAdd(neg, one);
1158 LLVM_VALUE eqZero = Builder.CreateFCmpOEQ(zero, op1);
1159 return Builder.CreateSelect(eqZero, one, zero);
1163 assert(
false &&
"not implemented.");
1168 struct VarCodeGeneration {
1171 LLVMContext &llvmContext = Builder.getContext();
1174 Type *int64Ty = Type::getInt64Ty(llvmContext);
1175 Type *doubleTy = Type::getDoubleTy(llvmContext);
1176 PointerType *int8PtrTy = Type::getInt8PtrTy(llvmContext);
1179 bool isDouble = varRef->
type().
isFP();
1180 int dim = varRef->
type().
dim();
1183 AllocaInst *returnValue = createAllocaInst(Builder, isDouble ? doubleTy : int8PtrTy, dim);
1186 Function *evalVarFunc = llvm_getModule(Builder)->getFunction(isDouble ==
true ?
"KSeExprLLVMEvalFPVarRef" :
"KSeExprLLVMEvalStrVarRef");
1187 Builder.CreateCall(evalVarFunc, {Builder.CreateIntToPtr(ConstantInt::get(int64Ty,
reinterpret_cast<uint64_t
>(varRef)), int8PtrTy), returnValue});
1192 ret = CREATE_LOAD(Builder, returnValue);
1194 ret = createVecValFromAlloca(Builder, returnValue, dim);
1197 AllocaInst *thisvar = createAllocaInst(Builder, ret->getType(), 1, varName);
1198 Builder.CreateStore(ret, thisvar);
1204 LLVMContext &llvmContext = Builder.getContext();
1206 int variableOffset = varRef->
offset();
1207 int variableStride = varRef->
stride();
1208 Function *
function = llvm_getFunction(Builder);
1209 auto *argIterator =
function->arg_begin();
1211 llvm::Argument *variableBlock = &*(argIterator++);
1212 llvm::Argument *indirectIndex = &*(argIterator++);
1214 int dim = varRef->
type().
dim();
1216 Type *ptrToPtrTy = variableBlock->getType();
1217 Value *variableBlockAsPtrPtr = Builder.CreatePointerCast(variableBlock, ptrToPtrTy);
1218 Value *variableOffsetIndex = ConstantInt::get(Type::getInt32Ty(llvmContext), variableOffset);
1219 Value *variableBlockIndirectPtrPtr = IN_BOUNDS_GEP(Builder, variableBlockAsPtrPtr, variableOffsetIndex);
1220 Value *baseMemory = CREATE_LOAD(Builder, variableBlockIndirectPtrPtr);
1221 Value *variableStrideValue = ConstantInt::get(Type::getInt32Ty(llvmContext), variableStride);
1224 Value *variablePointer = varRef->
type().
isLifetimeUniform() ? baseMemory : IN_BOUNDS_GEP(Builder, baseMemory, indirectIndex);
1225 return CREATE_LOAD(Builder, variablePointer);
1227 std::vector<Value *> loadedValues(dim);
1228 for (
int component = 0; component < dim; component++) {
1229 Value *componentIndex = ConstantInt::get(Type::getInt32Ty(llvmContext), component);
1231 Value *variablePointer = varRef->
type().
isLifetimeUniform() ? Builder.CreateInBoundsGEP(Type::getDoubleTy(llvmContext), baseMemory, componentIndex)
1232 : Builder.CreateInBoundsGEP(Type::getDoubleTy(llvmContext), baseMemory, Builder.CreateAdd(Builder.CreateMul(indirectIndex, variableStrideValue), componentIndex));
1233 loadedValues[component] = CREATE_LOAD_WITH_ID(Builder, variablePointer, varName);
1235 return createVecVal(Builder, loadedValues, varName);
1246 std::string varName(
"external_");
1247 varName.append(name());
1251 return VarCodeGeneration::codegen(varBlockRef, varName, Builder);
1253 return VarCodeGeneration::codegen(_var, varName, Builder);
1254 }
else if (_localVar) {
1259 assert(varPtr &&
"can not found symbol?");
1260 return CREATE_LOAD(Builder, varPtr);
1270 std::vector<LLVM_VALUE> elems;
1271 ConstantInt *zero = ConstantInt::get(Type::getInt32Ty(Builder.getContext()), 0);
1272 for (
int i = 0; i < numChildren(); i++) {
1274 elems.push_back(val->getType()->isVectorTy() ? Builder.CreateExtractElement(val, zero) : val);
1276 return createVecVal(Builder, elems);
void KSeExprLLVMEvalFPVarRef(KSeExpr::ExprVarRef *seVR, double *result)
void KSeExprLLVMEvalStrVarRef(KSeExpr::ExprVarRef *seVR, double *result)
std::string unescapeString(const std::string &string)
Node that calls a function.
ExprLocalVar join (merge) references. Remembers which variables are possible assigners to this.
virtual LLVM_VALUE codegen(LLVM_BUILDER, const std::string &, LLVM_VALUE) LLVM_BASE
LLVM value that has been allocated.
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) LLVM_BASE
int numChildren() const
Number of children.
const ExprType & type() const
The type of the node.
const ExprNode * child(size_t i) const
Get 0 indexed child.
Node that stores a string.
bool isLifetimeUniform() const
bool isFP() const
Direct is predicate checks.
Node that references a variable.
abstract class for implementing variable references
virtual ExprType type() const
returns (current) type
virtual void eval(double *result)=0
returns this variable's value by setting result
Internally implemented var ref used by SeExpr.
KSeExpr_DEFAULT double_t floor(double_t val)
double max(double x, double y)
const ExprStrNode * isString(const ExprNode *testee)