在 LLVM 字节码中查找循环
Posted
技术标签:
【中文标题】在 LLVM 字节码中查找循环【英文标题】:Find loops in LLVM bytecode 【发布时间】:2015-09-23 00:27:07 【问题描述】:我想在 LLVM 字节码中找到简单的循环,并提取基本的 循环的信息。
例如:
for (i=0; i<1000; i++)
sum += i;
我想提取边界 [0, 1000)、循环变量“i”和 循环体 (sum += i)。 我该怎么办?
我阅读了 LLVM API 文档,发现了一些有用的类,比如“Loop”, “循环信息”。 但是具体怎么用就不知道了。
你能给我一些帮助吗?详细的用法可能会更有帮助。
【问题讨论】:
【参考方案1】:如果您不想使用 pass manager,您可能需要在 IR 中的每个函数上调用 llvm::LoopInfoBase 类中的 Analyze 方法(假设您使用的是 LLVM-3.4 )。但是,Analyze 方法将每个函数的 DominatorTree 作为输入,您必须首先生成它。以下代码是我用 LLVM-3.4 测试的(假设您已读取 IR 文件并将其转换为名为 module 的 Module*):
for(llvm::Module::iterator func = module->begin(), y=module->end(); func!=y; func++)
//get the dominatortree of the current function
llvm::DominatorTree* DT = new llvm::DominatorTree();
DT->DT->recalculate(*func);
//generate the LoopInfoBase for the current function
llvm::LoopInfoBase<llvm::BasicBlock, llvm::Loop>* KLoop = new llvm::LoopInfoBase<llvm::BasicBlock, llvm::Loop>();
KLoop->releaseMemory();
KLoop->Analyze(DT->getBase());
基本上,通过生成 KLoop,您可以获得 IR 级别的各种 LOOP 信息。您可以参考 LoopInfoBase 类中的 API 以了解详细信息。顺便说一句,您可能想要添加以下标题: "llvm/Analysis/LoopInfo.h" "llvm/Analysis/Dominators.h".
【讨论】:
【参考方案2】:一旦您达到 LLVM IR 级别,您请求的信息可能不再准确。例如,clang 可能已经转换了您的代码,以便 i 从 -1000 变为 0。或者它可能已经完全优化了“i”,因此没有显式的归纳变量。如果您确实需要完全按照 C 代码中的面值提取信息,那么您需要查看 clang,而不是 LLVM IR。否则,您能做的最好的事情就是计算循环行程计数,在这种情况下,请查看 ScalarEvolution pass。
检查 PowerPC 硬件循环转换通道,它很好地演示了行程计数计算:http://llvm.org/docs/doxygen/html/PPCCTRLoops_8cpp_source.html
代码相当繁重,但应该可以遵循。有趣的函数是 PPCCTRLoops::convertToCTRLoop。如果您对此有任何其他问题,我可以尝试回答。
【讨论】:
【参考方案3】:LLVM 只是一个库。你不会在那里找到 AST 节点。
我建议看看 Clang,它是一个基于 LLVM 构建的编译器。
也许this 是您要找的?
【讨论】:
【参考方案4】:就像 Matteo 所说的,为了让 LLVM 能够识别循环变量和条件,文件需要在 LLVM IR 中。问题说你在 LLVM 字节码中有它,但由于 LLVM IR 是以 SSA 形式编写的,所以谈论“循环变量”并不是真的true。我敢肯定,如果您描述一下您正在尝试做什么,以及您希望我们能提供什么类型的结果,我们可以提供进一步的帮助。
一些帮助您入门的代码:
virtual void getAnalysisUsage(AnalysisUsage &AU) const
AU.addRequired<LoopInfo>();
bool runOnLoop(Loop* L, LPPassManager&)
BasicBlock* h = L->getHeader();
if (BranchInst *bi = dyn_cast<BranchInst>(h->getTerminator()))
Value *loopCond = bi->getCondition();
return false;
此代码 sn-p 来自常规 LLVM 通道。
【讨论】:
谢谢,安德烈亚斯。但我不习惯写 LLVM 通行证。我总是使用 LLVM 库函数来编写转换程序。输入是 LLVM 字节码文件,输出是修改后的字节码文件。有没有办法将 LLVM 传递更改为转换程序?【参考方案5】:只是 Junxzm 答案的更新,LLVM 3.5 中的一些引用、指针和方法已更改。
for(llvm::Module::iterator f = m->begin(), fe=m->end(); f!=fe; ++f)
llvm::DominatorTree DT = llvm::DominatorTree();
DT.recalculate(*f);
llvm::LoopInfoBase<llvm::BasicBlock, llvm::Loop>* LoopInfo = new llvm::LoopInfoBase<llvm::BasicBlock, llvm::Loop>();
LoopInfo->releaseMemory();
LoopInfo->Analyze(DT);
【讨论】:
以上是关于在 LLVM 字节码中查找循环的主要内容,如果未能解决你的问题,请参考以下文章