LLVM中不同BasicBlock共享相同对象ID?程序是否存在Bug?
为什么llvmlite中不同BasicBlock会共享相同的对象ID?
你用llvmlite代码打印LLVM模块中BasicBlock的对象ID时,发现不同BasicBlock的ID重复,比如main函数的BasicBlock和foo的第一个BasicBlock ID相同,foo内部也有重复ID。输出如下:
foo
Block ID: 140516957688448
Block ID: 140516957688544
Block ID: 140516957688448
Block ID: 140516957688544
Block ID: 140516957688448
Block ID: 140516957688544
printf
main
Block ID: 140516957688448
你的代码如下:
from llvmlite import binding as llvm # Initialize the LLVM system llvm.initialize() llvm.initialize_native_target() llvm.initialize_native_asmprinter() def find_basic_block_ids(ir): # Parse the LLVM IR llvm_module = llvm.parse_assembly(ir) llvm_module.verify() for function in llvm_module.functions: print (function.name) for block in function.blocks: block_id = id(block) print(f"Block ID: {block_id}") if __name__ == "__main__": with open("mycode.ll", "r") as f: llvm_ir = f.read() find_basic_block_ids(llvm_ir)
原因分析
这不是你的程序Bug,是llvmlite的对象包装机制导致的:
- llvmlite在访问LLVM底层对象(比如BasicBlock)时,不会为每个底层对象持续创建新的Python包装器。当遍历完一个BasicBlock后,对应的Python包装器会被Python的垃圾回收机制回收,其占用的内存地址会被重新分配给后续新创建的包装器。
- 你看到的重复ID,其实是不同Python包装器复用了同一块内存地址,它们对应的是LLVM底层不同的BasicBlock实例,但Python层面的包装对象被回收后复用了ID。
正确的标识方式
如果需要区分不同的BasicBlock,不要用Python的id(),应该用:
- BasicBlock的名称:如果IR中给块命名了,可以用
block.name获取 - LLVM内部的唯一标识:通过
block.as_pointer()获取底层LLVM对象的指针值,这个值是唯一的,不会重复
修改后的代码示例:
from llvmlite import binding as llvm # Initialize the LLVM system llvm.initialize() llvm.initialize_native_target() llvm.initialize_native_asmprinter() def find_basic_block_ids(ir): llvm_module = llvm.parse_assembly(ir) llvm_module.verify() for function in llvm_module.functions: print(function.name) for block in function.blocks: # 使用底层指针值作为唯一标识 block_ptr = block.as_pointer() # 或者使用块名称(如果有命名) block_name = block.name if block.name else "unnamed" print(f"Block Name: {block_name}, LLVM Pointer: {block_ptr}") if __name__ == "__main__": with open("mycode.ll", "r") as f: llvm_ir = f.read() find_basic_block_ids(llvm_ir)
内容的提问来源于stack exchange,提问作者zell
相关产品推荐
相关产品推荐

