Passing a pointer to a function

I recently began hacking around with my first LLVM pass. The big
picture is that I would like to insert function calls for each
instruction type, and pass some parameters based on the instruction
type. Then I will link the output to some C file that implements those
functions.

Things were going well until I started trying to make function calls
with a pointer as a parameter. For example, I would like to do
something like:

void
visitLoadInst(LoadInst &I) {
  Value *P;
  P = I.getPointerOperand();

  CallInst::Create(load_fcall, P, "", &I);
}

Where load_fcall is build using a call to Module::getOrInsertFunction
as in the example here:

http://wiki.llvm.org/HowTo:_Insert_a_function_call

My question is, what do I pass as the argument type for P above? The
following seems to work, as long as there are no floating point ops:

PointerType::getUnqual(IntegerType::get(32))

So I tried using just a void pointer type, as in:
PointerType::getUnqual(Type::VoidTy)

But then Type.cpp throws this assertion.
Assertion `ValueType != Type::VoidTy && "Pointer to void is not valid,
use sbyte* instead!"' failed.

I can try checking the type before building the function, as in:

void
visitLoadInst(LoadInst &I) {
  Value *P;
  P = I.getPointerOperand();

  PointerType* PtrTy = (PointerType*)(P);

  Constant* fcall;

  if (PtrTy->getElementType()->isInteger()) {
    fcall = buildFcallMem(*theModule, "load_int", Type::Int32Ty);
    CallInst::Create(fcall, P, "", &I);
  } else if (PtrTy->getElementType()->isInteger()){
    fcall = buildFcallMem(*theModule, "load_float", Type::FloatTy);
    CallInst::Create(fcall, P, "", &I);
  }
}

But then I get segfaults or assertions fail in Type.h (it's a huge
mess). I could be more specific, but I have tried several different
approaches and am trying to be brief here.

Perhaps I am overlooking an obvious approach. I will continue snooping
through the code to attempt to learn what is going on, but if anyone
could nudge me in the right direction or point out where I am
completely off, that would probably be helpful.

Thanks,
Scott

Where load_fcall is build using a call to Module::getOrInsertFunction
as in the example here:

http://wiki.llvm.org/HowTo:_Insert_a_function_call

My question is, what do I pass as the argument type for P above? The
following seems to work, as long as there are no floating point ops:

I would suggest bit-casting p to an i8*.

So I tried using just a void pointer type, as in:
PointerType::getUnqual(Type::VoidTy)

But then Type.cpp throws this assertion.
Assertion `ValueType != Type::VoidTy && "Pointer to void is not valid,
use sbyte* instead!"' failed.

Yeah, void* in C == i8* in LLVM. VoidTy is only used for function return types.

I'm not sure why you're getting crashes with the last approach; it
looks like it should work.

-Eli

Eli: Thanks for the quick and helpful response.

I would suggest bit-casting p to an i8*.

Yup, that did the trick:

void
visitLoadInst(LoadInst &I) {
  Value *P = I.getPointerOperand();

  const Type *PtrTy = PointerType::getUnqual(Type::Int8Ty);

  BasicBlock::iterator it(I);
  ++it;

  CastInst *CI =
    CastInst::Create(Instruction::BitCast, P, PtrTy, "", it);

  CallInst::Create(load_fcall, CI, "", it);
}

I'm not sure why you're getting crashes with the last approach; it
looks like it should work.

In that particular case, it encounters a pointer to an element of type
label and then segfaults on the call to isInteger(). I didn't look
into this bug because of the bitcast solution works for now.

Thanks,
Scott

I am not an expert in this, but maybe what you are missing is a bitcast. I'm attaching a simple function I use to pass strings to functions I've inserted in target programs:

     //////////////////////////////////////////////////////////////////////
     // convert an STL std::string into an LLVM GlobalVariable holding a
     // ConstantArray and then cast it to a PointerType so we can pass it
     // to a function call as an actual.
     Value *stringToPtr(std::string str, Module *mdl, Instruction *instr){
         Constant *strConstant;
         GlobalVariable *gv;

         strConstant = ConstantArray::get(std::string(str));
         gv = new llvm::GlobalVariable(strConstant->getType(),
                                        true,
                                        GlobalValue::InternalLinkage,
                                        strConstant,
                                        "",
                                        mdl,
                                        false);
         PointerType *strPtrTy = PointerType::getUnqual(Type::Int8Ty);
         return CastInst::Create(Instruction::BitCast, gv, strPtrTy, "", instr);
     }

I hope it helps,
Anthony