Caparros Cabezas Victoria
2014-May-28 16:22 UTC
[LLVMdev] Insert a call to a function that takes an LLVM instruction as argument - Calling a function with a bad signature!
Hi, I would like to instrument LLVM IR such that whenever a find a load, I insert a call to a self-implemented function that takes this load as an argument and then do some operations on the load. The C++ signature of the function call is: void analyzeInstruction(Instruction &I) {..} which in LLVM IR corresponds to (if I am not mistaken): define void @analyzeInstruction(%"class.llvm::Instruction"* %I). For that I write a pass such that whenever I find a load, I insert the following function call: virtual bool runOnBasicBlock(Function::iterator &BB) { for(BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ++BI) { if(isa<LoadInst>(&(*BI))){ LoadInst *CI = dyn_cast<LoadInst>(BI); Instruction *CI = dyn_cast<Instruction>(BI); CallInst* void_114 = CallInst::Create(analyze_func, CI, ""); void_114->setCallingConv(CallingConv::C); void_114->setTailCall(false); AttributeSet void_114_PAL; void_114->setAttributes(void_114_PAL); BB->getInstList ().insertAfter ((Instruction *)CI , void_114 ); } } } Where analyze_func is defined as: Function *analyze_func; PointerType* PointerTy_420; PointerType* PointerTy_421; FunctionType* FuncTy_analyzeInstruction; StructType *StructTy_class_llvm__LoadInst; StructTy_class_llvm__LoadInst= M.getTypeByName("class.llvm::LoadInst"); if (!StructTy_class_llvm__LoadInst) { StructTy_class_llvm__LoadInst = StructType::create(M.getContext(), "class.llvm::LoadInst"); } PointerTy_420 = PointerType::get(StructTy_class_llvm__LoadInst, 0); std::vector<Type*> FuncTy_analyzeInstruction_args; FuncTy_analyzeInstruction_args.push_back(PointerTy_420); FuncTy_analyzeInstruction = FunctionType::get( Type::getVoidTy(M.getContext()), FuncTy_analyzeInstruction_args, false); analyze_func = M.getFunction("analyzeInstruction"); if (!analyze_funcion){ analyze_func = Function::Create( FuncTy_analyzeInstruction, GlobalValue::ExternalLinkage, "analyzeInstruction", &M ); analyze_func->setCallingConv (CallingConv::C); } The problem is that when the function call is going to be created, I get the error that the function has bad signature because the expected type of the argument according to the function definition is: FTy->getParamType(i) -> %"class.llvm::LoadInst"* but the type of the argument is the actual type of the value loaded, which is: Args[i]->getType() -> i32 How can I create the function call such that the function signature is correct? Many thanks in advance, Victoria
Tobias Grosser
2014-May-29 23:11 UTC
[LLVMdev] Insert a call to a function that takes an LLVM instruction as argument - Calling a function with a bad signature!
On 29/05/2014 01:22, Caparros Cabezas Victoria wrote:> Hi, > > I would like to instrument LLVM IR such that whenever > a find a load, I insert a call to a self-implemented function > that takes this load as an argument and then do some > operations on the load. > > The C++ signature of the function call is: > > void analyzeInstruction(Instruction &I) {..} > > which in LLVM IR corresponds to (if I am not mistaken): > > > define void @analyzeInstruction(%"class.llvm::Instruction"* %I).This means just that you have a pointer to a type with the name %"class.llvm::Instruction". This type does not have need to have anything in common with the C++ type llvm::Instruction, but totally depends on how it is defined in this LLVM-module. Looking at your code" > StructTy_class_llvm__LoadInst=M.getTypeByName("class.llvm::LoadInst"); > if (!StructTy_class_llvm__LoadInst) { > StructTy_class_llvm__LoadInst = StructType::create(M.getContext(), "class.llvm::LoadInst"); > } You seem to define an llvm::Instructions as an empty struct. As far as I remember you just want to use this parameter to identify a specific LLVM-IR instruction in your library. For this a simple *i8 or just a i64 would be enough. Furthermore, you also need to forward the actual value loaded to ensure the function call remains related to the instruction you analyze. You could possibly use something like: define void @analyzeInstruction(i64 %Identifier, i64 %LoadedValue)> For that I write a pass such that whenever I find a load, I insert > > the following function call: > > > > > virtual bool runOnBasicBlock(Function::iterator &BB) { > > for(BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ++BI) { > > if(isa<LoadInst>(&(*BI))){ > > LoadInst *CI = dyn_cast<LoadInst>(BI);You could also use the IR-Builder. It has a very convenient interface to create functions.> > Instruction *CI = dyn_cast<Instruction>(BI); > > CallInst* void_114 = CallInst::Create(analyze_func, CI, ""); > > void_114->setCallingConv(CallingConv::C);I believe this is default anyway.> > void_114->setTailCall(false);That should also be default.> AttributeSet void_114_PAL; > > void_114->setAttributes(void_114_PAL);I don't understand that piece of code. I am more familiar to the IRBuilder. Though what you probably want to do is to pass two parameters: 1) The value loaded (possibly zeroextended/truncated to i64) 2) An identifier for this specific LLVM-IR instruction. You could possibly just use 'CI', the value of the pointer that points to this instruction. Using the IR builder, you can create an llvm::Value that represents this pointer as an integer constant.> BB->getInstList ().insertAfter ((Instruction *)CI , void_114 );> > } > } > } > > Where analyze_func is defined as: > > Function *analyze_func; > PointerType* PointerTy_420; > PointerType* PointerTy_421;> FunctionType* FuncTy_analyzeInstruction; > StructType *StructTy_class_llvm__LoadInst; > > StructTy_class_llvm__LoadInst= M.getTypeByName("class.llvm::LoadInst"); > if (!StructTy_class_llvm__LoadInst) { > StructTy_class_llvm__LoadInst = StructType::create(M.getContext(), "class.llvm::LoadInst"); > } > > PointerTy_420 = PointerType::get(StructTy_class_llvm__LoadInst, 0); > > std::vector<Type*> FuncTy_analyzeInstruction_args; > FuncTy_analyzeInstruction_args.push_back(PointerTy_420);If you use the interface above, those should be just two i64 values.> > > FuncTy_analyzeInstruction = FunctionType::get( > Type::getVoidTy(M.getContext()), > FuncTy_analyzeInstruction_args, > false); > > > analyze_func = M.getFunction("analyzeInstruction"); > if (!analyze_funcion){ > > analyze_func = Function::Create( > FuncTy_analyzeInstruction, > GlobalValue::ExternalLinkage, > "analyzeInstruction", &M > ); > analyze_func->setCallingConv (CallingConv::C); > } > > > The problem is that when the function call is going to be created, I get > the error that the function has bad signature because the expected type > of the argument according to the function definition is: > > FTy->getParamType(i) -> %"class.llvm::LoadInst"* > > but the type of the argument is the actual type of the value loaded, which > is: > > > Args[i]->getType() -> i32 > > > How can I create the function call such that the function signature is correct?I gave some ideas above. Let me know if you have further questions. Tobias