如何在llvm中更改Callinst中的操作数类型?
我正在尝试实现CallInst的转换,并执行以下操作:如何在llvm中更改Callinst中的操作数类型?,llvm,Llvm,我正在尝试实现CallInst的转换,并执行以下操作: 更改函数调用参数的类型 更改返回值的类型 例如,我想更改以下IR: %call = call double @add(double %0, double %1) define double @add(double %x, double %y) #0 { entry: %x.addr = alloca double, align 8 %y.addr = alloca double, align
%call = call double @add(double %0, double %1)
define double @add(double %x, double %y) #0 {
entry:
%x.addr = alloca double, align 8
%y.addr = alloca double, align 8
store double %x, double* %x.addr, align 8
store double %y, double* %y.addr, align 8
%0 = load double, double* %x.addr, align 8
%1 = load double, double* %x.addr, align 8
%add = fadd double %0, %1
ret double %add
}
要更新,请执行以下操作:
%call = call x86_fp80 @new_add(x86_fp80 %0, x86_fp80 %1)
define x86_fp80 @new_add(x86_fp80 %x, x86_fp80 %y) #0 {
entry:
%x.addr = alloca x86_fp80, align 16
%y.addr = alloca x86_fp80, align 16
store x86_fp80 %x, x86_fp80* %x.addr, align 16
store x86_fp80 %y, x86_fp80* %y.addr, align 16
%0 = load x86_fp80, x86_fp80* %x.addr, align 16
%1 = load x86_fp80, x86_fp80* %x.addr, align 16
%add = fadd x86_fp80 %0, %1
ret x86_fp80 %add
}
我已经完成了AllocaInst、StoreInst、LoadInst、BinaryOperator和ReturnInst的类型更改
我现在很困惑如何对付卡林斯特
我最初的想法是迭代所有指令时,如果我找到一个CallInst
if (CallInst *call = dyn_cast<CallInst>(it)){
使用
CallInst *new_call = CallInst::Create(new_fun, *arrayRefOperands, "newCall", call);
new_call->takeName(call);
}
%call = call x86_fp80 (x86_fp80, x86_fp80, ...) @0(x86_fp80 %5, x86_fp80 %7)
declare x86_fp80 @new_add(x86_fp80, x86_fp80, ...)
已构造被调用函数的新定义(声明x86_fp80@new_add(x86_fp80,x86_fp80,…),但此新函数的主体为空。我很困惑如何添加身体和得到新的我想要的。我天真的想法是:
for (Instruction i : called function(add in the example)){
create new_i with type x86_fp80;
insert new_i in the new function constructed(new_add in the example);
}
这是实现我目标的好方法吗
任何建议都将不胜感激:)如果您不再在其他地方使用原始函数,您可以使用llvm::Value::mutateType(llvm::Ty)将double type Value更改为x86_fp80。 使用CallInst->getCalledFunction()转到函数定义,并迭代所有值,然后将双精度类型变为x86_fp80
参考:非常感谢您的回答。然而,据说直接突变基因型是非常危险的。因此,在我的代码中,我用我想要的新类型创建了一个新函数。这不管用吗?我认为我的问题在于如何创建新函数的主体,对吗?如果有一个优雅的方法可以做到这一点,你能给我一些建议吗?非常感谢:)您还可以使用llvm::CloneFunction(const llvm::Function,ValueToValueMapTy*)这不会将函数添加到当前模块中,您可以使用clone->setname(string)设置返回函数名称,然后使用module->getFunctionList()->push_bask(clone)将其添加到当前模块函数列表中,此处ValueToValueMapTy用于引用,以指定在克隆函数中更改的映射。有关更多信息,请参阅(参考:)CloneFunction的其他变体。您可以根据需要使用它们。我在答案中尝试了您的方法,但它会导致返回类型和操作数类型的运行时错误不容易匹配。例如,将函数foo double foo(double x){double y=x;return y;}的类型变异有两个步骤,1)使用mutateType()将foo的声明变异为long double(long double x);2)将函数体中的返回指令变异为long double无论我先执行步骤1)还是步骤2),首先都会出现核心转储错误。因为两个步骤必须在一个语句中完成,才能使类型匹配。非常感谢您的耐心。我对克隆函数法有一个疑问。你是说我需要在克隆函数上进行类型变异吗?顺便问一下,你认为我在文章末尾的想法是什么?非常感谢:)
CallInst *new_call = CallInst::Create(new_fun, *arrayRefOperands, "newCall", call);
new_call->takeName(call);
}
%call = call x86_fp80 (x86_fp80, x86_fp80, ...) @0(x86_fp80 %5, x86_fp80 %7)
declare x86_fp80 @new_add(x86_fp80, x86_fp80, ...)
for (Instruction i : called function(add in the example)){
create new_i with type x86_fp80;
insert new_i in the new function constructed(new_add in the example);
}