[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