LLVM无现成命令行工具校验MachineInstr,因其合法性依赖target、subtarget、寄存器分配等上下文;需用-debug构建的llc配合-verify-machineinstrs开关,在Pass前后自动调用TII->verifyInstruction()并检查BB结构。

MachineInstr 合法性检查没有现成命令行工具
LLVM 不提供像 opt -verify 那样直接校验 MachineInstr 的命令行开关。这是因为 MachineInstr 属于后端 Machine Code 层,已脱离 IR 语义范畴,其“合法”与否高度依赖 target、subtarget、寄存器分配状态和指令调度上下文——这些信息在纯文件层面无法还原。
常见错误现象包括:Segmentation fault 在 llc 中崩溃、Assertion failed: isProperlyTypeChecked()、或汇编输出中出现 unknown instruction / invalid operand 等提示,但这些往往发生在指令发射(MC layer)之后,不是 MachineInstr 本身校验失败的直接信号。
实操建议:
- 调试阶段可在自定义
MachineFunctionPass中调用MIB->isBundle() || MIB->getDesc().getOpcode() != TargetOpcode::PHI等基础断言,但这类检查非常浅层 - 真正有意义的合法性验证必须结合
TargetInstrInfo::verifyInstruction()—— 它由各 backend 实现,例如 RISC-V 的RISCVInstrInfo::verifyInstruction()会检查 immediate 范围、寄存器类兼容性、隐含操作数是否缺失等 - 若你在写 Pass 并修改了
MachineInstr,应在runOnMachineFunction()结尾插入:for (auto &MBB : MF) { for (auto &MI : MBB) { assert(TII->verifyInstruction(MI, &DB) && "MI illegal after my pass"); } },其中DB是DiagnosticBuilder,用于获取具体报错位置
为什么不能只靠 verifyInstruction 就认为 MachineInstr 安全
TargetInstrInfo::verifyInstruction() 只做静态结构检查:opcode 是否存在、operand 数量是否匹配、immediate 是否在允许范围内、寄存器是否属于该指令允许的 class。它不检查:
- 寄存器是否已被分配(
MachineInstr中的Register可能仍是虚拟寄存器,尚未被LiveIntervals或RegAlloc处理) - 指令是否违反 subtarget 特性(比如在不支持压缩指令的 subtarget 上生成
C.ADDI) - 内存操作数的地址模式是否被 target 支持(如 RISC-V 的
lw a0, 0(sp)合法,但lw a0, 123456(sp)可能因 offset 超出 12-bit 范围而非法) - 指令间依赖是否被破坏(例如修改了某条指令的 def,却没更新其所有 use 的
MachineOperand::setReg())
所以即使 verifyInstruction() 返回 true,后续 pass(如 BranchFolding、MachineCopyPropagation)仍可能 crash 或生成错误代码。
如何暴露 MachineInstr 层级的隐性错误
最有效的办法是启用 -verify-machineinstrs —— 这是 LLVM 内置的、专为 MachineInstr 设计的 verifier 开关,但它默认关闭,且只在 debug build 中生效。
使用方式:
- 编译时确保用
cmake -DCMAKE_BUILD_TYPE=Debug构建 LLVM - 运行
llc -march=riscv64 -verify-machineinstrs input.ll -o /dev/null - 它会在每个
MachineFunctionPass执行前后自动调用MachineFunction::verify(),后者内部遍历所有MachineInstr并调用TII->verifyInstruction(),同时检查 basic block 边界、terminator 唯一性、PHI placement 等 - 若你开发的是自定义 Pass,强烈建议搭配
-debug-pass=Structure查看 Pass 执行顺序,再配合-verify-machineinstrs定位污染点
注意:-verify-machineinstrs 不会出现在 release build 的 help 输出里,也**不会**在 clang 命令中透传 —— 它只对 llc 有效。
容易被忽略的关键点
MachineInstr 合法性不是孤立属性。同一个 MachineInstr 在 pre-RA 和 post-RA 阶段的“合法”定义完全不同:前者允许虚拟寄存器和未解析的 frame index,后者要求所有寄存器物理化、所有 stack slot 已布局。如果你看到 verifier 在某个 Pass 后突然失败,优先检查该 Pass 是否意外修改了寄存器分配状态,或是否遗漏了 MachineRegisterInfo::constrainRegClass() 调用。

















