Skip to content

WIP: compiler: implement syscall.Syscall* on darwin (#4794)#5403

Open
neomantra wants to merge 1 commit into
tinygo-org:devfrom
neomantra:nm-darwin-syscall
Open

WIP: compiler: implement syscall.Syscall* on darwin (#4794)#5403
neomantra wants to merge 1 commit into
tinygo-org:devfrom
neomantra:nm-darwin-syscall

Conversation

@neomantra
Copy link
Copy Markdown

syscall.Syscall, syscall.Syscall6, syscall.RawSyscall and syscall.RawSyscall6 are declared bodyless on darwin in upstream Go and implemented in asm_darwin_{amd64,arm64}.s. TinyGo intentionally skipped them and never provided assembly, so any program calling them (directly or via modernc.org/memory and similar) failed to link:

linker could not find symbol _syscall.Syscall

This PR implements the syscalls for Darwin. I used an LLM to help port from these Golang implementation files:

I have tested this on arm64 and it is working for me so far. While I know 65C816 and 68k and can understand most of the syscall ASM implementations, my LLVM-foo is weak and would not have been able to generate this otherwise. I have had a few LLMs help review and have higher confidence since it is an ASM->LLVM port rather than something very original.

I am sensitive to the toil ; I did ensure there were some unit tests. I'm sharing this as scaffolding for those with stronger expertise in LLVM to ensure it is correct.

syscall.Syscall, syscall.Syscall6, syscall.RawSyscall and
syscall.RawSyscall6 are declared bodyless on darwin in upstream
Go and implemented in asm_darwin_{amd64,arm64}.s. TinyGo
intentionally skipped them and never provided assembly, so any
program calling them (directly or via modernc.org/memory and
similar) failed to link:

    linker could not find symbol _syscall.Syscall

Lower these calls in the compiler instead. Mirror upstream's ABI:

  - amd64: SYSCALL with trap + 0x2000000 in RAX, args in
    RDI/RSI/RDX/R10/R8/R9, primary in RAX, secondary in RDX,
    error indicated by the carry flag. Constraint: ={@ccc}.
  - arm64: SVC #0x80 with trap in X16, args in X0..X5, primary
    in X0, secondary in X1, error indicated by the carry flag
    (BCS). Constraint: ={@cccs}.

LLVM 20 rejects an i1 result type from these flag-output
constraints with "Glue output operand is of invalid type" on
both backends, so the flag is received as i32 and truncated to
i1 in IR. Clobber lists match the AArch64 caller-saved
convention (x0..x7) and the SYSCALL clobbers on x86 (rcx, r11).

The integration test exercises the three-arg form (SYS_GETPID
happy path, SYS_CLOSE error path returning EBADF) and the
six-arg form (anonymous SYS_MMAP, which uses all six argument
registers and would fail if any register slot were swapped).

Fixes tinygo-org#4794
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant