Skip to content

Commit e7e0c65

Browse files
committed
compiler, runtime: apply review feedback for darwin cgo import lowering
Shorten the new comment blocks and write them in Simplified Technical English. Give the reason for the manual ioctl declaration. Change syscall_libc_open to the uintptr_t parameter style of the other wrappers. Add t.Parallel and llvm.VerifyModule to TestDarwinCgoImportDynamic.
1 parent 688e47c commit e7e0c65

4 files changed

Lines changed: 24 additions & 61 deletions

File tree

compiler/compiler_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ func TestValidateWasmFunctionParameters(t *testing.T) {
353353
}
354354

355355
func TestDarwinCgoImportDynamic(t *testing.T) {
356+
t.Parallel()
357+
356358
options := &compileopts.Options{GOOS: "darwin", GOARCH: "arm64"}
357359
mod, errs := testCompilePackage(t, options, "cgo-import-dynamic.go")
358360
if len(errs) != 0 {
@@ -363,6 +365,10 @@ func TestDarwinCgoImportDynamic(t *testing.T) {
363365
}
364366
defer mod.Dispose()
365367

368+
if err := llvm.VerifyModule(mod, llvm.ReturnStatusAction); err != nil {
369+
t.Fatal(err)
370+
}
371+
366372
ir := mod.String()
367373
if !strings.Contains(ir, `declare void @"remote$INODE64"()`) {
368374
t.Error("missing external declaration for cgo_import_dynamic remote symbol")

compiler/symbol.go

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -774,19 +774,8 @@ func (c *compilerContext) fileForFunc(f *ssa.Function) *ast.File {
774774
// declaration and apply to the whole package.
775775
func (c *compilerContext) loadASTComments(pkg *loader.Package) {
776776
for _, file := range pkg.Files {
777-
// cgo_import_dynamic directives are file-level pragmas. Darwin's
778-
// generated syscall wrappers use the local symbol to name an assembly
779-
// trampoline and the remote symbol to name the actual dylib function.
780-
// Like the gc compiler, accept all three operand forms:
781-
//
782-
// //go:cgo_import_dynamic local [remote ["library"]]
783-
//
784-
// The remote symbol defaults to the local symbol when omitted. The
785-
// library operand is not needed here (the linker resolves the symbol
786-
// against the libraries it already links) and is ignored, so a library
787-
// path containing spaces does not break parsing. A repeated local
788-
// symbol keeps the last remote symbol, matching gc's behavior of
789-
// simply recording each directive.
777+
// Collect //go:cgo_import_dynamic local [remote ["library"]] directives.
778+
// The remote symbol defaults to local. The library operand is ignored.
790779
for _, group := range file.Comments {
791780
for _, comment := range group.List {
792781
parts := strings.Fields(comment.Text)

compiler/syscall.go

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,8 @@ func (b *builder) createDarwinFuncPCABI0Call(instr *ssa.CallCommon) llvm.Value {
525525
// Extract the libc function name.
526526
name := strings.TrimPrefix(strings.TrimSuffix(calledFn.Name(), "_trampoline"), "libc_")
527527
if wrapper, ok := darwinVariadicImports[name]; ok {
528-
// Variadic functions can't be called like a regular function, so use a
529-
// wrapper implemented in C. See the comment on darwinVariadicImports.
528+
// A variadic function does not use the standard calling convention.
529+
// Use its C wrapper. See darwinVariadicImports.
530530
name = wrapper
531531
}
532532
if b.GOARCH == "amd64" {
@@ -541,25 +541,8 @@ func (b *builder) createDarwinFuncPCABI0Call(instr *ssa.CallCommon) llvm.Value {
541541
return b.createDarwinImportedFunctionAddr(name)
542542
}
543543

544-
// darwinVariadicImports maps the variadic libc functions imported by Darwin
545-
// syscall wrappers to fixed-signature C wrappers defined in
546-
// src/runtime/os_darwin.c. The syscall engine calls an imported address
547-
// through a fixed-signature function pointer (tinygo_syscallX and friends in
548-
// src/runtime/os_darwin.c), which passes every argument in a register. A
549-
// variadic callee, however, takes its variadic arguments from the stack on
550-
// darwin/arm64, so calling one of these functions directly makes it read
551-
// garbage arguments (a direct ioctl call observably failed with EFAULT, and
552-
// a direct fcntl(F_SETFL) wrote garbage flags). This applies to both
553-
// trampoline flavors: the standard library's function-based pattern
554-
// (createDarwinFuncPCABI0Call above) and the address-global pattern used by
555-
// golang.org/x/sys (createDarwinCgoImportDynamicLoad below).
556-
//
557-
// The set comes from cross-referencing the symbols that darwin's generated
558-
// syscall wrappers import (the //go:cgo_import_dynamic directives in
559-
// zsyscall_darwin_*.go, both in golang.org/x/sys/unix and in the standard
560-
// library) against their Darwin SDK declarations: of those imports, exactly
561-
// open(2), openat(2), fcntl(2), and ioctl(2) are declared variadic (see
562-
// sys/fcntl.h and sys/ioctl.h, or lib/macos-minimal-sdk's copies).
544+
// darwinVariadicImports maps each variadic libc import to a fixed-signature C
545+
// wrapper in src/runtime/os_darwin.c. See sys/fcntl.h and sys/ioctl.h.
563546
var darwinVariadicImports = map[string]string{
564547
"fcntl": "syscall_libc_fcntl",
565548
"ioctl": "syscall_libc_ioctl",

src/runtime/os_darwin.c

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,29 @@
44

55
#include <fcntl.h>
66

7+
// sys/ioctl.h is not in lib/macos-minimal-sdk. Declare ioctl here.
78
extern int ioctl(int fd, unsigned long request, ...);
89

9-
// Wrapper function because 'open' is a variadic function and variadic functions
10-
// use a different (incompatible) calling convention on darwin/arm64.
11-
// This function is referenced from the compiler, when it sees a
12-
// syscall.libc_open_trampoline function.
13-
int syscall_libc_open(const char *pathname, int flags, mode_t mode) {
14-
return open(pathname, flags, mode);
10+
// Fixed-signature wrappers for the variadic libc imports. Variadic functions
11+
// take stack arguments on darwin/arm64. See darwinVariadicImports in
12+
// compiler/syscall.go.
13+
14+
int syscall_libc_open(uintptr_t pathname, uintptr_t flags, uintptr_t mode) {
15+
return open((const char *)pathname, (int)flags, (mode_t)mode);
1516
}
1617

17-
// Wrapper for ioctl, which is variadic just like open and therefore also uses
18-
// an incompatible calling convention on darwin/arm64. Use uintptr_t arguments
19-
// to match the fixed-signature call made by tinygo_syscall below.
2018
int syscall_libc_ioctl(uintptr_t fd, uintptr_t request, uintptr_t arg) {
21-
return ioctl((int)fd, request, (void *)arg);
19+
return ioctl((int)fd, (unsigned long)request, (void *)arg);
2220
}
2321

24-
// Wrappers for the remaining variadic libc functions that darwin syscall
25-
// wrappers import with //go:cgo_import_dynamic (see darwinVariadicImports in
26-
// compiler/syscall.go): of the symbols imported by the generated
27-
// zsyscall_darwin_*.go files in golang.org/x/sys/unix and the standard
28-
// library, exactly open, openat, fcntl, and ioctl are declared variadic in
29-
// the Darwin SDK headers (sys/fcntl.h and sys/ioctl.h). The tinygo_syscall*
30-
// functions below call through fixed-signature function pointers that pass
31-
// every argument in a register, while a variadic callee takes its variadic
32-
// arguments from the stack on darwin/arm64, so each of these needs a
33-
// fixed-signature wrapper. The uintptr_t parameters match the uintptr
34-
// arguments the Go syscall engine passes.
35-
36-
// fcntl's third argument is an int for some commands and a pointer for
37-
// others; passing the raw pointer-sized value covers both.
22+
// The third fcntl argument is an int for some commands and a pointer for
23+
// other commands. The raw pointer-sized value is correct for both.
3824
int syscall_libc_fcntl(uintptr_t fd, uintptr_t cmd, uintptr_t arg) {
3925
return fcntl((int)fd, (int)cmd, (void *)arg);
4026
}
4127

42-
// openat is invoked by x/sys through syscall6 with six arguments, the last
43-
// two of which are zero padding; the two extra register arguments are
44-
// harmless to a four-parameter callee.
28+
// x/sys calls openat through syscall6 with two trailing zero arguments. The
29+
// two extra register arguments are harmless to a four-parameter callee.
4530
int syscall_libc_openat(uintptr_t dirfd, uintptr_t pathname, uintptr_t flags, uintptr_t mode) {
4631
return openat((int)dirfd, (const char *)pathname, (int)flags, (mode_t)mode);
4732
}

0 commit comments

Comments
 (0)