我试图通过编写LLVM传递来获取分支指令的结果,以便我可以计算出CFG的边沿频率。
我已经阅读了多个教程文件和LLVM文档。我尝试的解决方案是识别分支指令,插入对显示分支源和目标的日志函数的调用。
我写了一个函数传递,看起来像这样:
for (auto &BB : F) {
for (auto &I: BB) {
if (auto* op = dyn_cast<BranchInst>(&I)) {
IRBuilder<> builder(op);
builder.SetInsertPoint(&BB, builder.GetInsertPoint());
Value* condition;
Value* false_dst;
Value* true_dst;
if (op->isConditional()) {
condition = op->getOperand(0);
false_dst = op->getOperand(1);
true_dst = op->getOperand(2);
} else {
condition = builder.getInt32(1);
false_dst = op->getOperand(0);
true_dst = op->getOperand(0);
}
Value* args[] = {condition, false_dst, true_dst};
builder.CreateCall(log_func, args);
}
}
}
我已经尝试了大约 10 个小时的多种解决方案,但没有一个奏效。我一直遇到此错误:
void llvm::CallInst::init(llvm::FunctionType*, llvm::Value*, llvm::ArrayRef<llvm::Value*>, llvm::ArrayRef<llvm::OperandBundleDefT<llvm::Value*> >, const llvm::Twine&): Assertion `(Args.size() == FTy->getNumParams() || (FTy->isVarArg() && Args.size() > FTy->getNumParams())) && "Calling a function with bad signature!"' failed.
它似乎只使用分支指令执行此操作,因为我已经使用二进制运算符进行了测试,并且它工作正常。
在调试器下运行代码并计算log_func->dump()
表达式。这将使您了解此函数需要哪些类型的参数。
我怀疑,问题出在最后 2 个参数上。这些是基本的块标签,不能作为call
指令的参数传递。您可能希望创建具有 BB 名称的字符串常量并传递它们。