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:
@@ -226,6 +226,13 @@ pub const Op = union(enum) {
|
||||
/// Method-ID caching across call sites is added in step 1.17.
|
||||
jni_msg_send: JniMsgSend,
|
||||
|
||||
/// `asm volatile? { "tmpl", operands…, clobbers(.…) }` — inline assembly
|
||||
/// (ASM stream, design §II.6). emit_llvm.zig assembles the LLVM constraint
|
||||
/// string + rewrites the `%[name]` template, then `LLVMGetInlineAsm` +
|
||||
/// `LLVMBuildCall2`. The result rides on `Inst.ty` (void / a scalar / a tuple
|
||||
/// of the `out_value` types). Never comptime-evaluable — the interp bails.
|
||||
inline_asm: InlineAsm,
|
||||
|
||||
// ── Closure creation ────────────────────────────────────────────
|
||||
closure_create: ClosureCreate,
|
||||
|
||||
@@ -339,6 +346,35 @@ pub const ObjcMsgSend = struct {
|
||||
args: []const Ref, // additional args after recv + sel
|
||||
};
|
||||
|
||||
/// Inline assembly payload (design §II.6). All strings interned; operands in
|
||||
/// SOURCE ORDER (= the `%N` index space and the LLVM constraint order). The
|
||||
/// result type rides on `Inst.ty`: void (no value outputs), a scalar (one), or
|
||||
/// a tuple (N). emit_llvm.zig owns the constraint-string assembly + `%[name]`
|
||||
/// template rewrite.
|
||||
pub const InlineAsm = struct {
|
||||
/// Interned template, RAW — the `%[name]`→`${N}` rewrite happens at emit.
|
||||
template: StringId,
|
||||
/// Declaration order preserved (keys `%N` and the LLVM operand order).
|
||||
operands: []const AsmOperand,
|
||||
/// Interned dot-names from `clobbers(.…)`: "rcx", "cc", "memory", …
|
||||
clobbers: []const StringId,
|
||||
/// `volatile` — passed as LLVM `HasSideEffects`.
|
||||
has_side_effects: bool,
|
||||
|
||||
pub const AsmOperand = struct {
|
||||
role: Role,
|
||||
/// Effective operand name (explicit `[name]` or auto-derived register);
|
||||
/// `.empty` when anonymous.
|
||||
name: StringId,
|
||||
/// Verbatim constraint, e.g. "={rax}", "=r", "+r", "{rdi}", "r".
|
||||
constraint: StringId,
|
||||
/// `input` → the value `Ref`; `out_value` → `.none` (the asm yields it).
|
||||
operand: Ref,
|
||||
|
||||
pub const Role = enum { out_value, out_place, input };
|
||||
};
|
||||
};
|
||||
|
||||
/// JNI dispatch payload. `env` is `JNIEnv*` (typed as ptr); `target`
|
||||
/// is a `jobject` for instance calls and a `jclass` for static calls.
|
||||
/// `name` and `sig` are pointers to NUL-terminated bytes (typically
|
||||
|
||||
Reference in New Issue
Block a user