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
On Wed, May 20, 2009 at 7:31 PM, Scott Ricketts <sricketts at maxentric.com> wrote:> 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 On May 20, 2009, at 10:31 PM, Scott Ricketts wrote:> 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 > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev