[LLVMdev] Insert a call to a function that takes an LLVM instruction as argument - Calling a function with a bad signature!

Tobias Grosser tobias at grosser.es
Thu May 29 16:11:41 PDT 2014



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



More information about the llvm-dev mailing list