feat(asm): read-write + place outputs
Implements read-write (`+r` / `+{reg}`) `-> @place` outputs. LLVM has
no `+` constraint, so a read-write place lowers to:
- an output `=` constraint (return slot, stored back through the
place after the call), with the leading `+` rewritten to `=`; plus
- a TIED input constraint (the decimal index of that output) appended
after the regular inputs, seeded with the place's loaded value
passed as a call arg.
Tied inputs are appended last so existing operand indices (%[name] ->
${N}) are undisturbed; asmOperandIndex stays correct. Lowering no longer
rejects `+` (indirect `*` still rejected). emitInlineAsm grows the
arg/param arrays by the rw count, loads each seed, and emits the tied
constraint.
Verified by running: increment-in-place (41 -> 42) and a mixed case
(rw place + regular input + value output) producing the textbook
"=r,=r,r,0" constraint with correct ${N} indices. 1650 flipped from
the rejection lock to a runnable aarch64-pinned example (ir-only
elsewhere). zig build test green (658 corpus, 446 unit).
This commit is contained in:
@@ -2345,12 +2345,10 @@ pub fn lowerAsmExpr(self: *Lowering, ae: *const ast.AsmExpr, span: ast.Span) Ref
|
||||
.input => operand_ref = self.lowerExpr(op.payload),
|
||||
.out_value => out_ty = self.resolveTypeWithBindings(op.payload),
|
||||
.out_place => {
|
||||
// Read-write (`+`) and indirect-memory (`*`) place outputs aren't
|
||||
// implemented yet — reject loudly rather than miscompile (§II.11).
|
||||
if (op.constraint.len > 0 and op.constraint[0] == '+') {
|
||||
diags.addFmt(.err, span, "read-write (`+`) asm outputs are not yet implemented; use a write-only `=` output", .{});
|
||||
return self.emitPlaceholder("inline_asm");
|
||||
}
|
||||
// Indirect-memory (`*`) place outputs aren't implemented yet —
|
||||
// reject loudly rather than miscompile (§II.11). Read-write (`+`)
|
||||
// outputs ARE implemented (emit ties an input to the output and
|
||||
// seeds it with the place's loaded value; see `emitInlineAsm`).
|
||||
if (std.mem.indexOfScalar(u8, op.constraint, '*') != null) {
|
||||
diags.addFmt(.err, span, "indirect-memory (`*`) asm outputs are not yet implemented", .{});
|
||||
return self.emitPlaceholder("inline_asm");
|
||||
|
||||
Reference in New Issue
Block a user