feat(asm): Phase C.0 — add inline_asm IR op (lock, no behavior change)

Adds the `inline_asm: InlineAsm` opcode to the IR Op union (inst.zig): interned
template + operand list (role/name/constraint/operand) + interned clobber names
+ has_side_effects; the result rides on Inst.ty (void / scalar / tuple).

The new variant forces coverage in the exhaustive Op switches:
- interp.zig: loud bailDetail — inline asm is never comptime-evaluable.
- print.zig: an IR-dump arm.
- emit_llvm.zig: a @panic TRIPWIRE — emit lands in Phase D, and until then
  lowerAsmExpr still bails, so no inline_asm op is ever created. Reaching emit
  would mean lowering switched over before emit was ready; crash loudly rather
  than miscompile.

No behavior change: lowering still bails, the op is constructed only in the new
`inline_asm op shape` unit test (inst.test.zig).

zig build test green (652 corpus, 446 unit).
This commit is contained in:
agra
2026-06-15 21:00:12 +03:00
parent 5f444aae26
commit 6c08de8ec1
6 changed files with 120 additions and 14 deletions

View File

@@ -328,6 +328,14 @@ fn printInst(instruction: *const Inst, ref_idx: u32, tt: *const TypeTable, write
try writeArgs(c.args, writer);
try writer.writeAll(") : ");
},
.inline_asm => |a| {
try writer.print("inline_asm{s} tmpl=#{d} ops={d} clobbers={d} : ", .{
if (a.has_side_effects) " volatile" else "",
a.template.index(),
a.operands.len,
a.clobbers.len,
});
},
.compiler_call => |cc| {
const name = tt.getString(@enumFromInt(cc.name));
try writer.print("compiler_call \"{s}\"(", .{name});