通用化将汇编代码(asm)转换为三地址码IL的可行方法咨询
多架构汇编到三地址码IL的通用转换方案
基于指令语义规范的自动生成
- 利用指令集架构(ISA)的官方语义文档(比如ARM的ARM Architecture Reference Manual),提取每条指令的操作语义(运算类型、操作数顺序、结果目标等),编写脚本自动生成映射字典。例如Aarch64的
mneg语义是Rd = -(Rn * Rm),脚本可解析这类结构化描述,自动生成对应的HLI对象代码。 - 借助LLVM的TableGen这类ISA语义库,它原本就是用来定义指令集语义并生成后端代码的工具。基于TableGen的指令定义编写转换器,直接映射到你的三地址码IL结构,省去手动重复编码的工作量。
复用成熟中间表示的转换逻辑
- 先将汇编代码转成LLVM IR(通过LLVM的汇编器
llc或直接调用LLVM API),再把LLVM IR转换为自定义三地址码IL。LLVM IR本身就是通用的三地址码风格中间表示,已支持几乎所有主流架构,你只需处理LLVM IR到自有IL的映射,比直接处理各架构汇编简单得多。 - 类似的还有GCC的GIMPLE中间表示,可借助GCC前端的多架构处理能力,先完成汇编到GIMPLE的转换,再转成你的IL。
基于模板的半自动生成
- 针对同类型指令(算术运算、逻辑运算等)编写通用模板,所有二元运算指令(add、sub、mul等)都能复用同一模板,只需传入操作符类型、操作数索引、结果寄存器索引。示例代码:
这种方式能大幅减少重复代码,仅需为def binary_op_template(inst, op_type): return [HLI(op=Op.ASGN, result=Name(value=get_inst_operand_reg_at_index(inst, 0)), arg=BinOp(left=get_expr_for_operand(inst, 1), op=op_type, right=get_expr_for_operand(inst, 2)))] # 批量注册同类型指令 op_map = { "add": lambda inst: binary_op_template(inst, BinaryOperator.ADD), "sub": lambda inst: binary_op_template(inst, BinaryOperator.SUB), "mul": lambda inst: binary_op_template(inst, BinaryOperator.MUL), # 其他二元指令直接套用模板 }mneg这类复合操作的特殊指令编写单独映射。
避坑提示
- 优先复用现有成熟工具的语义解析能力,不要从零造轮子,LLVM/GCC的前端已经解决了多架构指令解析和语义转换的核心问题。
- 若自定义IL有特殊需求(比如数据流分析所需的依赖关系、副作用标记),可在模板或自动生成的代码中统一注入相关逻辑。
内容的提问来源于stack exchange,提问作者Jorayen
相关产品推荐
相关产品推荐

