feat(asm): Phase 2 — -> @place write-through outputs
An asm result can be STORED through a place (a local / struct field) instead of returned; the place output does not join the result tuple. - parser.zig: `-> @place` parses `@place` as an ordinary address-of expression → an out_place operand (the in-function form; reuses the existing `@` prefix). - inst.zig: AsmOperand gains out_ty (the output slot's value type) so emit can build the combined return struct without re-deriving from Inst.ty. - lower/expr.zig: out_place operand = the lowered @place address, out_ty = the pointee. Read-write (`+`) and indirect-memory (`*`) constraints rejected loudly (not yet implemented) rather than miscompiled. - ops.zig emitInlineAsm: the LLVM return type is built from ALL outputs (out_value + out_place); after the call, out_place slots are stored through their address and out_value slots rebuild the sx result. Fast path when there are no place outputs (the struct return IS the result — pure-value asm IR unchanged). Verified: write-to-local (42), struct field, mixed value+place (v=10 b=20), `+` rejected. Locked with 1649-platform-asm-place-output (mixed, runs on aarch64). zig build test green (657 corpus, 446 unit).
This commit is contained in:
19
examples/1649-platform-asm-place-output.sx
Normal file
19
examples/1649-platform-asm-place-output.sx
Normal file
@@ -0,0 +1,19 @@
|
||||
// ASM stream Phase 2 — `-> @place` write-through output. An asm result can be
|
||||
// STORED through a place (a local / struct field) instead of returned: the
|
||||
// place output does NOT join the result tuple. Here one value output is
|
||||
// returned (into `main_val`) while a second is written through `@other`. The
|
||||
// two are combined to 42. Read-write (`+`) and indirect (`*`) place outputs are
|
||||
// not yet implemented (rejected at lowering). aarch64-pinned; ir-only elsewhere.
|
||||
compute :: () -> i64 {
|
||||
other : i64 = 0;
|
||||
main_val := asm volatile {
|
||||
#string ASM
|
||||
mov %[m], #5
|
||||
mov %[o], #37
|
||||
ASM,
|
||||
[m] "=r" -> i64, // value output → returned
|
||||
[o] "=r" -> @other, // place output → stored through @other
|
||||
};
|
||||
return main_val + other; // 5 + 37 = 42
|
||||
}
|
||||
main :: () -> i64 { return compute(); }
|
||||
1
examples/expected/1649-platform-asm-place-output.build
Normal file
1
examples/expected/1649-platform-asm-place-output.build
Normal file
@@ -0,0 +1 @@
|
||||
{ "target": "macos" }
|
||||
1
examples/expected/1649-platform-asm-place-output.exit
Normal file
1
examples/expected/1649-platform-asm-place-output.exit
Normal file
@@ -0,0 +1 @@
|
||||
42
|
||||
25
examples/expected/1649-platform-asm-place-output.ir
Normal file
25
examples/expected/1649-platform-asm-place-output.ir
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal i64 @compute() #0 {
|
||||
entry:
|
||||
%alloca = alloca i64, align 8
|
||||
store i64 0, ptr %alloca, align 8
|
||||
%asm = call { i64, i64 } asm sideeffect " mov ${0}, #5\0A mov ${1}, #37\0A", "=r,=r"()
|
||||
%asm.out = extractvalue { i64, i64 } %asm, 0
|
||||
%asm.out1 = extractvalue { i64, i64 } %asm, 1
|
||||
store i64 %asm.out1, ptr %alloca, align 8
|
||||
%allocaN = alloca i64, align 8
|
||||
store i64 %asm.out, ptr %allocaN, align 8
|
||||
%load = load i64, ptr %allocaN, align 8
|
||||
%loadN = load i64, ptr %alloca, align 8
|
||||
%add = add i64 %load, %loadN
|
||||
ret i64 %add
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i32 @main() #0 {
|
||||
entry:
|
||||
%call = call i64 @compute()
|
||||
%ca.tr = trunc i64 %call to i32
|
||||
ret i32 %ca.tr
|
||||
}
|
||||
1
examples/expected/1649-platform-asm-place-output.stderr
Normal file
1
examples/expected/1649-platform-asm-place-output.stderr
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
1
examples/expected/1649-platform-asm-place-output.stdout
Normal file
1
examples/expected/1649-platform-asm-place-output.stdout
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user