I’ve seen different things being passed for this parameter!
Sometimes it is the type the second argument is pointing too (in case of this is pointing to a structure).
Sometimes it is the type of an element of the array the second argument is pointing to.
Currently I’m getting a crash when trying to extract an element of a global/static array.
Looking at IR code generated from C++ code is of no help, as there are no types.
The IR code generated from C++ code is even storing a pointer parameter on the stack and reloading it instead of using it directly.
Here comes the code produced by chatgpt for me – as I said it is crashing.
I already tried passing arrayType instead of Type::getInt32Ty(context) to IRBuilder::CreateGEP().
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
using namespace llvm;
int main()
{
LLVMContext context;
Module *module = new Module("my_module", context);
// Create a static const array variable
ArrayType *arrayType = ArrayType::get(Type::getInt32Ty(context), 3);
Constant *arrayValues[] =
{ ConstantInt::get(Type::getInt32Ty(context), 1),
ConstantInt::get(Type::getInt32Ty(context), 2),
ConstantInt::get(Type::getInt32Ty(context), 3)
};
Constant *array = ConstantArray::get(arrayType, arrayValues);
GlobalVariable *myArray = new GlobalVariable(
*module, arrayType, true, GlobalValue::ExternalLinkage, array, "myArray");
// Create an IRBuilder
IRBuilder<> builder(context);
// Create a GetElementPtrInst instruction to access the first element of myArray
Value *zero = ConstantInt::get(Type::getInt32Ty(context), 0);
Value *indices[] = {zero, zero};
Value *firstElementPtr = builder.CreateGEP(Type::getInt32Ty(context), myArray, indices);
Value *firstElement = builder.CreateLoad(Type::getInt32Ty(context), firstElementPtr);
}
The problem applies to both, LLVM-15 (on ubuntu) and LLVM-16 (on windows).
Here is the stack-trace for windows:
Type parameter to checkGEPType() is a nullptr.
|>|global_array.exe!llvm::checkGEPType(llvm::Type * Ty) Line 933|C++|
| |global_array.exe!llvm::GetElementPtrInst::getGEPReturnType(llvm::Type * ElTy, llvm::Value * Ptr, llvm::ArrayRef<llvm::Value *> IdxList) Line 1090|C++|
| |global_array.exe!llvm::ConstantFoldGetElementPtr(llvm::Type * PointeeTy, llvm::Constant * C, bool InBounds, std::optional<unsigned int> InRangeIndex, llvm::ArrayRef<llvm::Value *> Idxs) Line 2025|C++|
| |global_array.exe!llvm::ConstantExpr::getGetElementPtr(llvm::Type * Ty, llvm::Constant * C, llvm::ArrayRef<llvm::Value *> Idxs, bool InBounds, std::optional<unsigned int> InRangeIndex, llvm::Type * OnlyIfReducedTy) Line 2423|C++|
| |global_array.exe!llvm::ConstantFolder::FoldGEP(llvm::Type * Ty, llvm::Value * Ptr, llvm::ArrayRef<llvm::Value *> IdxList, bool IsInBounds) Line 119|C++|
| |global_array.exe!llvm::IRBuilderBase::CreateGEP(llvm::Type * Ty, llvm::Value * Ptr, llvm::ArrayRef<llvm::Value *> IdxList, const llvm::Twine & Name, bool IsInBounds) Line 1797|C++|
| |global_array.exe!main() Line 31|C++|
I also tried using only a single index for the array:
Value *indices[] = {zero};
When doing this, IRBuilder::CreateGEP() succeeds but the following CreateLoad() fails due to a nullptr access:
|>|global_array.exe!llvm::BasicBlock::getParent() Line 112|C++|
|---|---|---|
| |global_array.exe!llvm::BasicBlock::getModule() Line 147|C++|
| |global_array.exe!llvm::BasicBlock::getModule() Line 123|C++|
| |global_array.exe!llvm::IRBuilderBase::CreateAlignedLoad(llvm::Type * Ty, llvm::Value * Ptr, llvm::MaybeAlign Align, bool isVolatile, const llvm::Twine & Name) Line 1749|C++|
| |global_array.exe!llvm::IRBuilderBase::CreateAlignedLoad(llvm::Type * Ty, llvm::Value * Ptr, llvm::MaybeAlign Align, const llvm::Twine & Name) Line 1744|C++|
| |global_array.exe!llvm::IRBuilderBase::CreateLoad(llvm::Type * Ty, llvm::Value * Ptr, const llvm::Twine & Name) Line 1725|C++|
| |global_array.exe!main() Line 32|C++|