从caleidoscope教程和一个堆栈交换问题开始,我试图用LLVM输出一些数组创建和访问代码。这个想法是有一个";alloca";堆栈变量";a";它保存一个指向用malloc分配的数组的双*。生成的代码失败了,我认为主要问题是我的"呼叫";CreateInBoundsGEP";在C++中。
所以我在一句话中的主要问题是";如何调用CreateInBoundsGEP以便输出正确的IR代码">
我尝试的是以下内容:
我的分配代码是作为llvm c++接口的";CreateMalloc";从上面提到的问题中调用。
%a = alloca double*, align 8
%malloccall = tail call i8* @malloc(i32 48)
%0 = bitcast i8* %malloccall to double*
store double* %0, double** %a, align 8
这段代码对我来说很好,但在使用verifyFunction((进行检查时,它已经导致了错误/警告。
Call parameter type does not match function signature!
i32 48
遗憾的是,它没有告诉我,什么是正确的参数类型(i64?(。IR参考不是指";malloc"-函数调用,但提到了";malloc";改为IR操作(参考(!
我的主要问题(如果以前没有发现,还会导致内存错误(发生在对数组的写访问上。
我的第一次尝试是直接从引用的堆栈交换问题1:中复制(或多或少(
//ret is the base adress of the pointer, ie "a"
//rhs is the Value* to the right hand side that is assigned
//index is the Value* to the array index
auto element_ptr = Builder->CreateInBoundsGEP(ret, index, "acc_tmp");
Builder->CreateStore(rhs, element_ptr);
哪个输出(对于[1]=5作为输入代码(
%acc_tmp = getelementptr inbounds double*, double** %a, i32 1
store double 5.000000e+00, double** %acc_tmp, align 8
这创建了一个";verifyFunction";错误,我可以看到";双**";可能应该是";双*";。由于我也收到了一个弃用警告,我决定尝试带有类型参数的CreateInBoundsGEP。由于文件没有告诉我";类型";应该是元素或指针类型,我尝试了两种
auto element_ptr = Builder->CreateInBoundsGEP(rhs->getType()->getPointerTo(), ret, index, "acc_tmp");
或
auto element_ptr = Builder->CreateInBoundsGEP(rhs->getType(), ret, index, "acc_tmp");
两者都不起作用,第一个版本在不传递类型的情况下输出相同的代码,第二个版本导致
static llvm::GetElementPtrInst *llvm::GetElementPtrInst::Create(llvm::Type *, llvm::Value *, ArrayRef<llvm::Value *>, const llvm::Twine &, llvm::Instruction *): Assertion `cast<PointerType>(Ptr->getType()->getScalarType()) ->isOpaqueOrPointeeTypeMatches(PointeeType)' failed.
正如我在最初的问题中注意到的,我的指令中有一个指针*太多了。起初我不明白为什么会这样,但后来我在一个看似无关的问题1中找到了问题的答案:
如果直接使用返回值"0";CreateMalloc";作为";CreateInBoundsGEP";,我最初从2复制的代码将起作用。
然而,在我的情况下,还涉及一个步骤:;CreateMalloc";本地变量中的返回值,该本地变量又被分配有"0"的指针引用;alloca";。因此,与原始代码段相比,我需要一个额外的取消引用步骤来访问我的数组元素。
如在1中所提到的,LLVM-IR中的解引用只是一个"参考";加载";。所以一个正确的数组访问代码看起来像
//ret is the pointer to(!) the base adress of the array, ie "a"
//rhs is the Value* to the right hand side that is assigned
//index is the Value* holding the array index
llvm::Value* index = visit(ctx->index).as<llvm::Value*>();
llvm::Value* ret_deref = Builder->CreateLoad(llvm::Type::getDoubleTy(*TheContext)->getPointerTo(),ret,"deref_tmp");
auto element_ptr = Builder->CreateInBoundsGEP(rhs->getType(), ret_deref, index, "acc_tmp");
Builder->CreateStore(rhs, element_ptr);