我是编写LLVM通道的新手,如果我想计算主函数调用printf()的次数(作为示例),我想知道我应该添加到通道中的内容。
说我有这个非常令人兴奋的主要内容:
#include <stdio.h>
int main() {
printf("hello world\n");
return 0;
}
我希望我的传递看看printf()是否被调用以及调用它的次数(例如,如果它在某些循环中)。
到目前为止,这是我通过的内容:
namespace {
struct SkeletonPass : public FunctionPass {
static char ID;
SkeletonPass() : FunctionPass(ID) {}
virtual bool runOnFunction(Function &F) {
errs() << "I saw a function called " << F.getName() << "!\n";
errs() << "It uses printf()" << F. //I'd like to write out how many times printf() is used here
return false;
}
};
}
答案 0 :(得分:1)
如果您只想检查printf是否被调用,而不是通过CFG。
llvm子类runOnFunction为每个函数体运行,你可以遍历函数指令并检查它们是否是CallInst并调用特别是printf。
inst_iterator inst = inst_begin(&F);
inst_iterator instEnd = inst_end(&F);
for(; inst != instEnd; ++inst)
{
if (CallInst* psCall = dyn_cast<CallInst>(&*inst))
{
StringRef name = psCall->getCalledFunction()->getName();
/* check name */
}
}
现在检查它是否在循环中。有一个子类runOnLoop但是LPPassManager接口应该用于更新循环嵌套。(如果你想更新它)
用于控制流搜索,
BasicBlocks已经以CFG方式组织,它们有后继者和前身,所以你不必建立新的图形。 您可以使用简单的递归DFS算法来完成cfg。
看这里 http://eli.thegreenplace.net/2013/09/16/analyzing-function-cfgs-with-llvm 这家伙解释得好多了。
还可以查看llvm手册,找到更好的接口和程序。 http://llvm.org/docs/WritingAnLLVMPass.html