18

我已经写了一个 pass 来检测和打印函数中基本块的标签,因为我想splitBasicBlock()进一步使用。我是这样写的:

virtual bool runOnModule(Module &M)
{
    for(Module::iterator F = M.begin(), E = M.end(); F!= E; ++F)
    {
        errs()<<"Function:"<<F->getName()<<"\n";
        //for(Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
        for (iplist<BasicBlock>::iterator iter = F->getBasicBlockList().begin();
                    iter != F->getBasicBlockList().end();
                    iter++)
        {
          BasicBlock* currBB = iter;
          errs() << "BasicBlock: "  << currBB->getName() << "\n";   
        }
    }
    return true;
}

IR 文件如下所示:

; <label>:63                                      ; preds = %43
  %64 = load i32* %j, align 4
  %65 = sext i32 %64 to i64
  %66 = load i8** %tempdst, align 8
  %67 = getelementptr inbounds i8* %66, i64 %65
  store i8 -1, i8* %67, align 1
  br label %73

; <label>:68                                      ; preds = %43
  %69 = load i32* %j, align 4
  %70 = sext i32 %69 to i64
  %71 = load i8** %tempdst, align 8
  %72 = getelementptr inbounds i8* %71, i64 %70
  store i8 0, i8* %72, align 1
  br label %73

; <label>:73                                      ; preds = %68, %63
  br label %74

但是,我对标签一无所知:

Function:main
BasicBlock:
BasicBlock:
BasicBlock:

这些“未命名”的基本块有什么问题?我应该怎么办?

4

5 回答 5

15

虽然 BasicBlocks 可能没有名称(如方法所示),但可以通过使用而不是流式传输到的值hasName()来打印唯一的 BasicBlock 标识符。对于未命名的 BasicBlock,这将提供数字基本块表示,例如.currBB->printAsOperand(errs(), false)errs()currBB->getName()%68

于 2016-04-03T14:26:32.033 回答
11

LLVM IR 中的值不需要有名称;事实上,这些基本块没有名称,这就是为什么你从currBB->getName().

它们在 LLVM IR 打印输出中有名称的原因是,当您打印到 LLVM IR 的文本格式(如它出现在 .ll 文件中)时,您必须为它们分配一个名称以使其可引用,因此打印机分配基本块(和其他值)的顺序数字名称。但是,这些数字名称仅由打印机创建,实际上并不存在于模块中。

于 2014-10-09T17:42:41.703 回答
4

使用 clang 将源代码编译为位码时,请使用以下标志

-fno-discard-value-names

您将获得基本块的名称作为唯一字符串

于 2020-10-29T16:42:15.387 回答
3

我认为 LLVM 现在的行为有所不同。我使用类似的代码行并且可以在 LLVM-4.0 上获取标签的名称

for (auto &funct : m) {
            for (auto &basic_block : funct) {
            StringRef bbName(basic_block.getName());
                errs() << "BasicBlock: "  << bbName << "\n";
            }
}
于 2017-09-05T00:47:52.603 回答
2

正如 ElazarR 所说,currBB->printAsOperand(errs(), false)将在错误流中打印此类 ID,但如果这对您的逻辑更有趣,也可以将其存储在字符串中。

在 LLVM CFG 生成过程-dot-cfg中,它们总是使用 BB 的名称(如果有)或其表示为字符串来命名基本块。这个逻辑出现在CFGPrinter.h标题中(http://llvm.org/doxygen/CFGPrinter_8h_source.html#l00063):

static std::string getSimpleNodeLabel(const BasicBlock *Node,
                                      const Function *) {
    if (!Node->getName().empty())
        return Node->getName().str();

    std::string Str;
    raw_string_ostream OS(Str);

    Node->printAsOperand(OS, false);
    return OS.str();
}

您可以使用此逻辑始终为基本块返回有效名称。

于 2018-06-12T21:04:25.950 回答