Как я могу получить ссылку на операнд? - PullRequest
0 голосов
/ 12 апреля 2019

В настоящее время у меня есть код C ++, который выглядит следующим образом:

/*
 * class declarations
 */

int main() {
    Object1 obj;

    obj->foo();
}

Я хочу сделать передачу функции llvm, которая вставит инструкцию, чтобы она выглядела следующим образом:

/*
 * class declarations
 */

int main() {
    Object1 obj;

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

В настоящее время я могу определить место, куда мне нужно вставить. Однако у меня возникли некоторые проблемы при вставке вызова функции bar ().

В частности, в моем проходе llvm я могу получить объект "obj" из инструкции "obj.foo ();". Однако после создания функции мне трудно передать ссылку obj на панель функций ().

Ниже моя функция проход:

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 Ответ

1 голос
/ 13 апреля 2019

Хорошо, я исправил проблему. Ниже я поделюсь решением для всех моих братьев и сестер, борющихся с этой проблемой:

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);
            }
        }
    }
}
...