如何获得对操作数的引用?

时间:2019-04-12 17:44:16

标签: c++ compiler-errors llvm llvm-c++-api

目前,我有一个C ++代码,如下所示:

/*
 * class declarations
 */

int main() {
    Object1 obj;

    obj->foo();
}

我想传递一个llvm函数,该函数插入一条指令使其看起来像这样:

/*
 * class declarations
 */

int main() {
    Object1 obj;

    bar(&obj);
    obj.foo();
}

当前,我可以检测到需要插入的位置。但是,插入bar()函数调用有点麻烦。

具体地说,在我的llvm传递中,我能够通过指令“ obj.foo();”获得对象“ obj”。但是,在创建函数之后,我很难将“ obj”的引用传递给函数bar()。

下面是我的函数传递:

bool runOnFunction(Function &F) {
    for (auto &BB : F) {
        for (auto &I : BB) {
            if (I.getOpcode() == Instruction::Call || I.getOpcode() == Instruction::Invoke) {
                /*
                 * few more filters to get the virtual function calls
                 */

                 // Grabbing "obj" from "obj.foo();"
                 Value *currOperand = I.getOperand(0);
                 Type *currType = const_cast<Type*> (currOperand->getType());

                 // Inserting bar(&obj); 
                 IRBuilder<> builder(F.getContext());
                 Type *result = Type::getVoidTy(F.getContext());
                 ArrayRef<Type*> params = {
                     PointerType::getUnqual(currType)
                 };
                 FunctionType *func_type = FunctionType::get(result, params, false);
                 FunctionCallee bar = I.getModule()->getOrInsertFunction("bar", func_type);

                 ArrayRef<Value*> args = {
                     // I think this line below is wrong
                     builder.CreateIntToPtr(currOperand, currType) 
                 };
                 builder.CreateCall(bar, args);
            }
        }
    }
}

当前在builder.CreateCall(bar。args);处出错。并显示以下错误消息。

"Calling a function with a bad signature!" failed.

这使我相信我的“ args”变量是错误的。任何帮助,将不胜感激!

1 个答案:

答案 0 :(得分:1)

好的,我已解决此问题。我将为所有在这个问题上苦苦挣扎的兄弟姐妹分享以下解决方案:

bool runOnFunction(Function &F) {
    for (auto &BB : F) {
        for (auto &I : BB) {
            if (I.getOpcode() == Instruction::Call || I.getOpcode() == Instruction::Invoke) {
                /*
                 * few more filters here to get the virtual function calls
                 */

                 // Grabbing "obj" from "obj.foo();"
                 Value *currOperand = I.getOperand(0);
                 Type *currType = const_cast<Type*> (currOperand->getType());

                 // Inserting bar(&obj);
                 LLVMContext &ctx = F.getContext();
                 IRBuilder<> builder(ctx);
                 builder.SetInsertPoint(&I);

                 ArrayRef<Type*> params = {
                     currType->getPointerTo()
                 };
                 Type *result = Type::getVoidTy(ctx);
                 FunctionType *func_type = FunctionType::get(result, params, false);
                 FunctionCallee bar = I.getModule()->getOrInsertFunction("bar", func_type);

                 ArrayRef<Value*> args = {
                     builder.CreatePointerCast(currOperand, currType->getPointerTo()) 
                 };
                 builder.CreateCall(bar, args);
            }
        }
    }
}