Passing an element of an array to a function

I have an existing function created in my pass like this:

  Type *ArgTypes[1];
  ArgTypes[0] = TypeBuilder<types::i<64>*, false>::get(*Context);
  FunctionType *FuncType = FunctionType::get(Type::getVoidTy(*Context),
                                             ArgTypes, false /* vararg */);
  MyFn = Function::Create(FuncType, GlobalValue::WeakAnyLinkage, FnName, Mod);

I am trying to call this with a pointer to an i64 element.
This element is within an array that has below type:
ArrayType *ArrTy = ArrayType::get(Type::getInt64Ty(Mod->getContext()), size);
MyArr = new GlobalVariable(*Mod, ArrTy, …);

SmallVector<Value *, 2> IdxList;
Value *Elem = Builder.CreateInBoundsGEP(MyArr, IdxList);

SmallVector<Value *, 1> Args;
CallInst::Create(MyFn, Args, “”, 0);

I am getting an assert like this:
Expression: (i >= FTy->getNumParams() || FTy->getParamType(i) == Args[i]->getType()) && “Calling a function with a bad signature!”

I think I am getting the pointer to a particular i64 element from the CreateInBoundsGEP().
What am I doing wrong?

Very odd, I can’t see a problem with what you’re doing unless TypeBuilder is doing something weird. What do MyFn->dump() and Elem->dump() produce?

FYI, TypeBuilder was removed in 2019 in time for LLVM 8, you would be best served by migrating away from it.

For various reasons that I cannot control, I am on an earlier LLVM version. So, I guess, I need to live with Typebuilder for now.

You never needed to use TypeBuilder, it was just an alternative interface that was barely used and got removed. So no, you can switch away from TypeBuilder, and you’ll likely confuse fewer people by not using interfaces that were deleted a bit over 3 years ago.

MyFn->Dump produces:
declare weak void @__Mangle__MyFn(i64*)

Elem->dump produces:
i64 addrspace(1)* getelementptr inbounds ([2 x i64], [2 x i64] addrspace(1)* @_Mangle_MyArr, i64 0, i64 0)

Could it be an addr-space issue ?

That’s definitely it. So a lot rides on the “…” in your new GlobalVariable(...).

I added a CreateAddrSpaceCast(…) and it is working as intended now. Thank you !

I don’t think that’s a good idea. The global being in addrspace(1) might make the compiler put it somewhere strange, if not now then in the future some time.

I think the real issue is that in your new GlobalVariable(...) call you’re passing true somewhere, thinking it’s setting one option but LLVM is interpreting it as the address space. Or it could be some other enum parameter. Either way, you probably want to fix that because you’re probably not getting what you intended in other ways too.

1 Like