在 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 字节码中查找循环的主要内容,如果未能解决你的问题,请参考以下文章

如何识别Java字节码中的覆盖方法?

字节码中的类型

在字节码中存储值[关闭]

无法将使用 JVM 目标 1.8 构建的字节码内联到使用 JVM 目标 1.6 构建的字节码中

Java字节码中“GOTO”之后的数字是多少?

反射机制