LLVM 基本块通行证

Posted

技术标签:

【中文标题】LLVM 基本块通行证【英文标题】:LLVM BasicBlock pass 【发布时间】:2012-12-17 16:52:30 【问题描述】:

我是 LLVM 的初学者。我试图在 BasicBlock 的指令中移动,但我不能。在这个特定示例中,我尝试获取结束指令的前一条指令。我正在尝试两种方法:

    我有以下代码序列:

    bool patternDC::runOnBasicBlock(BasicBlock &BB) 
    ...
    if (BB.getTerminator())
      
                Instruction* current = BB.getTerminator();
                errs() << "\n LAST: "<<*current<<"\n";
    
            Instruction* prev = &BB.back();
            errs() << "\n PENULTIMATE: "<<*prev<<"\n";         
           ...
    

终端打印相同的指令。我不知道 back() 是如何工作的。 (BasicBlock.h 文件第 199 行的定义。)

    我也试过了:

    bool patternDC::runOnBasicBlock(BasicBlock &BB) 
    ...
    BasicBlock::const_iterator I = BB.begin();
    BasicBlock::const_iterator E = BB.end();
    BasicBlock::const_iterator prev_iter,last_iter;
    prev_iter = NULL; last_iter = NULL;
    for(;I!=E;I++)
        prev_iter = last_iter;
        last_iter = I;
    
    if(prev_iter)
        errs() << "prev_iter: " << *(dyn_cast<Instruction>(prev_iter)) << "\n";
    
    if(last_iter)
        errs() << "last_iter: " << *(dyn_cast<Instruction>(last_iter)) << "\n";
    
     // not related to the main question: uncomment the next line for an unusual      
    //behavior: lastlast is DIFFERENT from last.lastlast=section(BasicBlock)
      // errs() << "lastlast: " << *(dyn_cast<Instruction>(I)) << "\n";
      ...
       Instruction* prev = *(dyn_cast<Instruction*>(prev_iter));
        errs() << "\n prev: "<<*prev<<"\n";
    

终端可以很好地打印出 prev 和 last,但是在尝试分配到 Instruction* prev 时出现编译错误 Clang错误是: “…… /home/alex/llvm/include/llvm/Support/Casting.h:51:28: 错误:‘classof’不是‘llvm::Instruction*’的成员”

如果有人知道使用基本块中的任何元素的更好方法,或者知道为什么这些元素不起作用,请告诉我 :)

谢谢你, 亚历克斯

【问题讨论】:

【参考方案1】:

所有 LLVM Instruction 类也是 ilist_node,这意味着您可以查询它们以获取包含它们的列表中的下一条/上一条指令(在本例中为基本块)。更具体地回答您的问题:

Instruction* last = BB.getTerminator();
Instruction* prev = last->getPrevNode();

查看 LLVM 源代码中ilist_node 的定义以查看相关 API。

【讨论】:

谢谢!现在我没有任何编译错误。但是现在每当我尝试使用 *prev 时,在运行时都会出现堆栈转储错误。 @user1817807:您可能有基本块,其中只有一条指令。检查 prev 是否为 NULL。 谢谢!我会检查每一种可能性。 好的,主要的段错误问题是:当我遍历函数的基本块时,我使用指令*指针数组。之后我想使用这些数组。也许 LLVM 在遍历基本块时不保护地址。所以:我需要使用指令数组而不是指令* 数组。但是我怎样才能创建只有 Instruction* 的 llvm::Instruction ? @Alex:我不确定我是否理解您的需求,这可能是一个完全不同的问题。但不管怎样,Instruction 有一个clone 方法,如果你想复制它。【参考方案2】:

我通过检查 if(BB->size()>1) 来解决只有一个元素的基本块

【讨论】:

以上是关于LLVM 基本块通行证的主要内容,如果未能解决你的问题,请参考以下文章

如何在编译时检测 XNU 内核二进制文件?

LLVM ICmpInst 到指令转换

选择与 irtranslator 通行证崩溃

LLVM 错误:发现损坏的函数,编译中止!在 removeFromParent() 之后

如何从 TBAA 元数据节点 (MDNode) [llvm 7.0] 中获取类型

如何将 LLVMPass long opt 命令更改为简单命令