我偶然发现了一些非常特殊的东西 - 我正在写一个LLVM模块Pass。我迭代模块的所有函数,然后迭代每个非声明函数的所有循环,并将指针存储到std::vector
中的循环。这是来源:
virtual bool runOnModule(Module& Mod){
std::vector<Loop*> loops;
// first gather all loop info
for(Module::iterator f = Mod.begin(), fend = Mod.end(); f != fend; ++f){
if (!(*f).isDeclaration()){
LoopInfo& LI = getAnalysis<LoopInfo>(*f);
for(LoopInfo::iterator l = LI.begin(), lend = LI.end(); l != lend; ++l){
loops.push_back(*l);
}
}
}
for (auto& l: loops) errs () << *l << " ";
}
现在,如果我运行这个,我得到一个运行时错误 - 它无法打印循环,不知怎的,我正在做空指针取消引用或某事。有什么想法吗?
答案 0 :(得分:1)
您必须确保LoopInfo
通行证在通行证之前实际运行。这是一个完整的示例 - 来自opt
的stanalone:
class AnalyzeLoops : public FunctionPass {
public:
AnalyzeLoops()
: FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LoopInfo>();
}
virtual bool runOnFunction(Function &F) {
LoopInfo &LI = getAnalysis<LoopInfo>();
for (LoopInfo::iterator L = LI.begin(), LE = LI.end(); L != LE; ++L) {
(*L)->dump();
}
return false;
}
static char ID;
};
此外,在创建传球时,请执行以下操作:
PassManager PM;
PM.add(new LoopInfo());
PM.add(new AnalyzeLoops());
PM.run(*Mod);
我怀疑要让opt
在你通过之前实际运行LoopInfo
,你也应该通过-loops
。
另外,请注意我定义getAnalysisUsage
- 如果LoopInfo
在此次传递之前未运行,这将使LLVM抱怨,从而使问题更加明显。
请注意,LoopInfo
具体为FunctionPass
,作为分析,必须使用其他FunctionPass
。 LoopInfo
数据结构在不同函数之间并不存在,并且由于它拥有其数据(那些Loop*
对象),它们也将被销毁。
如果你真的需要ModulePass
,你可以做的一件事就是手动调用LoopInfo
而不是分析。当您迭代模块中的函数时,为每个函数创建一个新的LoopInfo
对象并使用其runOnFunction
方法。虽然在这种情况下,如果您想使用后者,您必须确保拥有给定LoopInfo
的{{1}}幸存。
答案 1 :(得分:1)
首先,LoopInfo应该在for循环之前运行一次。 其次,LoopInfo :: iterator只包含Function的顶级循环。为了访问所有循环,您还需要迭代每个循环的子循环。它既可以作为递归函数实现,也可以通过WorkList实现,如此`
virtual bool runOnFunction(Function &F) {
LoopInfo *loopinfo;
loopinfo = &getAnalysis<LoopInfo>();
std::vector<Loop*> allLoops;
for (LoopInfo::iterator Li = loopinfo->begin(), Le = loopinfo->end();
Li != Le; Li++) {
Loop *L = *Li;
allLoops.push_back(L);
dfsOnLoops(L, loopinfo, allLoops);
}
}
void dfsOnLoops(Loop *L, LoopInfo *loopinfo, std::vector<Loop*> LoopS) {
std::vector<Loop *> subloops = L->getSubLoops();
if (subloops.size()) {
// recursive on subloops
for (std::vector<Loop *>::iterator Li = subloops.begin();Li != subloops.end(); Li++){
LoopS.push_back(*Li);
dfsOnLoops(*Li, loopinfo, LoopS);
}
}
}
`
答案 2 :(得分:1)
没有一个答案真的有帮助,但我自己设法解决了这个问题。基本上,每个llvm pass都可以定义一个releaseMemory()方法,阅读更多here。 LoopInfo类实现了该方法,因此每次调用getAnalysis时,分析信息都会丢失。我只是删除了Loopinfo.h中的releaseMemory()方法,并且不再释放内存。请注意,这触发了代码库的一个重大变化,甚至必须重建,所以这样做通常可能是一个坏主意,这肯定不会被轻易接受为llvm的变化(我推测,不确定)。
答案 3 :(得分:0)
我认为解决此问题的最佳方法是显式创建LoopInfo对象并保存它们。这是LLVM 3.5的代码
using LoopInfoType=llvm::LoopInfoBase<llvm::BasicBlock, llvm::Loop>;
std::vector<llvm::Loop*> loopVec;
std::vector<LoopInfoType*> loopInfoVec;
for(llvm::Module::iterator F = M.begin(); F!= M.end(); F++){
//skip declrations
if(F->isDeclaration()){
continue;
}
//TODO that scope problem
llvm::DominatorTree DT = llvm::DominatorTree();
DT.recalculate(*F);
LoopInfoType *loopInfo = new LoopInfoType();
loopInfo->releaseMemory();
loopInfo->Analyze(DT);
loopInfoVec.push_back(loopInfo);
for(llvm::LoopInfo::iterator lit = loopInfo->begin(); lit != loopInfo->end(); lit++){
Loop * L = * lit;
loopVec.push_back(L);
//L->dump();
}
}//for all functions
cin.get();
for(auto loop : loopVec){
std::cout << "loop\n";
loop->dump();
for(llvm::Loop::block_iterator bit = loop->block_begin(); bit != loop->block_end(); bit++){
llvm::BasicBlock * B = * bit;
B->dump();
std::cout << "\n\n";
}
}