c++ [3.0]关于如何使用存储IR指令获取块地址的问题

kmbjn2e3  于 2022-11-27  发布在  其他
关注(0)|答案(1)|浏览(107)

我写这封信是想询问一个问题,当我读到一段C程序生成的IR语言时,我发现在C程序中,获取标签地址的行为在翻译成IR后是由一个store指令来处理的。

store i8* blockaddress(@func_name, %label_name), i8** %val_name

不过,我看过官方文件,Blockaddress的工作原理是这样的:
blockaddress(@function,%block)'blockaddress'常数会计算指定函式中指定基本区块的位址,而且永远是i8* 型别。取得项目区块的位址是不合法的。这个值只有在当做'[indirectbr](file:///D:/opensource/llvm-3.0.src/docs/LangRef. html #i_indirectbr)'指令的算子使用时,或用来与null进行比较时,才会有已定义的行为。标签位址之间的指标相等性测试会导致未定义的行为-不过,与null进行比较也没问题,而且没有标签相等null指标。只要未检查比特,这个值就可以当做不透明的指标大小值传递。只要在indirectbr指令之前重建原始值,就可以在这些值上执行ptrtoint和算术运算。最后,某些目的在将值当做内嵌组件的算子使用时,可能会提供已定义的语意,但这是目的特定的。
所以我想弄清楚存储是如何在IR程序中通过将它们存储在%5中来构造块地址的。如果我想用C++来构造这个存储指令以获得基本块的地址,我该怎么做?
我做了一些尝试,比如构建一个间接br:

irBuilder.SetInsertPoint(indirectbr_bb);
    IndirectBrInst *indirect_br = IndirectBrInst::Create(BlockAddress::get(func, instr2_bb), 0, indirectbr_bb);
    indirect_br->addDestination(instr1_bb);
    indirect_br->addDestination(instr2_bb);

生成的IR程序如下:

indirectbr_bb:                                    ; preds = %dispatch_then_bb
  indirectbr i8* blockaddress(@jit_func, %instr2_bb), [label %instr1_bb, label %instr2_bb]

经过我的测试,它可以正确地执行,因此,我想知道如何构造一个类似的存储IR来存储阵列中基本块的地址。

qyzbxkaa

qyzbxkaa1#

Blockaddress::get(basicblock *bb)返回一个块地址指针,它是常量的子类,也是Value的派生类。在LLVM IR中,所有变量都是Value类型。因此我们可以这样做:

ArrayType *arrayType = ArrayType::get(irBuilder.getInt8PtrTy(), 1024);
module->getOrInsertGlobal("label_array", arrayType);
GlobalVariable *label_array = module->getNamedGlobal("label_array");

vector <Constant *> array_elems;
array_elems.push_back(BlockAddress::get(func, ret_bb));
array_elems.push_back(BlockAddress::get(func, instr1_bb));
array_elems.push_back(BlockAddress::get(func, instr2_bb));
label_array->setInitializer(ConstantArray::get(arrayType, array_elems));

相关问题