Udon Decompiler

IR 和 IR 变换

本节介绍函数 IR 的构建方式, src/decompiler/transform/*src/decompiler/transform/* 中的变换框架, 以及默认 IR 变换管线中各 pass 的作用.

构建 IR

IR 的构建发生在数据流分析之后, 入口是 build_ir_functionsbuild_ir_functions.

对每个已经识别出的函数, 反编译器会遍历其 FunctionCfg.block_idsFunctionCfg.block_ids, 逐块读取原始指令, 并利用堆栈模拟阶段记录的 instruction_statesinstruction_states 将指令翻译为机械化的 IR 语句.

在这个阶段, 常见指令会被翻译为如下 IR:

  • COPYCOPY -> IrAssignmentStatementIrAssignmentStatement
  • EXTERNEXTERN -> IrExpressionStatementIrExpressionStatement 或赋值语句
  • 普通 JUMPJUMP -> IrJumpIrJump
  • returning call / tail call 形态的 JUMPJUMP -> IrInternalCallExpressionIrInternalCallExpressionIrReturnIrReturn
  • JUMP_IF_FALSEJUMP_IF_FALSE -> IrIfIrIf
  • 已识别 switch scaffold 的 JUMP_INDIRECTJUMP_INDIRECT -> IrSwitchIrSwitch
  • 返回语义的 JUMP_INDIRECTJUMP_INDIRECT -> IrLeaveIrLeave

IR 变换

IR 变换的入口是 TransformPipeline::runTransformPipeline::run. 它分两段执行:

  • 函数级 transforms: 依次对每个 IrFunctionIrFunction 执行
  • 程序级 transforms: 在所有函数都完成函数级变换后执行

Transform 框架

当前主要有三层接口:

  • ITransformITransform: 函数级 pass, 输入是一个 IrFunctionIrFunction
  • IProgramTransformIProgramTransform: 程序级 pass, 输入是整个函数数组
  • IBlockTransformIBlockTransform / IStatementTransformIStatementTransform: 更细粒度的 block / statement 变换接口

为了让各个 pass 共享必要信息, 框架提供了两层 context:

  • ProgramTransformContextProgramTransformContext: 整个变换阶段共享
  • TransformContextTransformContext: 单个函数 pass 运行时使用, 内部持有对 ProgramTransformContextProgramTransformContext 的可变借用

ProgramTransformContextProgramTransformContext 里目前最重要的内容包括:

  • class_nameclass_name: 最终输出类名
  • ir_classir_class: 程序级 transforms 构造出的类 IR
  • decompile_contextdecompile_context: 原始反编译上下文, 供各 pass 查询变量、原始符号、模块信息等
  • metadatametadata: 跨 pass 共享的小型状态表. 目前主要用于保存 METADATA_SYNTHETIC_BLOCK_ADDRMETADATA_SYNTHETIC_BLOCK_ADDR, 供多个结构化 pass 分配 synthetic block address, 防止不同 pass 生成冲突的人工块地址.

默认 Transform 管线

默认管线由 build_default_pipelinebuild_default_pipeline 构造. 当前顺序为

  • 函数级

    • ControlFlowSimplificationControlFlowSimplification: 折叠 jump chain 并清理空块
    • ConstToLiteralConstToLiteral: 将常量变量引用改写为字面量
    • TempVariableInlineTempVariableInline: 内联最明显的临时变量赋值
    • DetectExitPoints(false)DetectExitPoints(false): 第一轮退出点检测, 为结构恢复做准备
    • LoopDetectionLoopDetection: 识别 loop / switch body 并构造容器
    • DetectExitPoints(true)DetectExitPoints(true): 在容器成形后再做一轮退出点检测
    • ConditionDetectionConditionDetection: 把典型 block 跳转形态改写为条件结构
    • HighLevelLoopTransformHighLevelLoopTransform: 继续提升 loop container 的控制流结构
    • HighLevelSwitchTransformHighLevelSwitchTransform: 将低层 switch 容器提升为高层 switch 语句
    • HighLevelLoopStatementTransformHighLevelLoopStatementTransform: 将 loop container 提升为 whilewhile / do-whiledo-while
    • StructuredControlFlowCleanupTransformStructuredControlFlowCleanupTransform: 清理残留 goto 风格结构
    • CollectLabelUsageCollectLabelUsage: 重新标记仍需输出的块标签和出口标签
    • CollectVariablesCollectVariables: 收集函数最终实际使用到的变量声明
  • 程序级

    • IrClassConstructionTransformIrClassConstructionTransform: 将所有函数组合为类级 IR
    • PromoteGlobalsPromoteGlobals: 将共享变量提升到类级声明