1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3
4//go:build ignore
5
6package main
7
8import (
9 "log"
10 "os"
11 "strings"
12 "text/template"
13)
14
15const templateSymbols = `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
16
17// SPDX-License-Identifier: Apache-2.0
18// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
19
20//go:build darwin || linux
21
22package fakecgo
23
24import (
25 "syscall"
26 "unsafe"
27)
28
29// setg_trampoline calls setg with the G provided
30func setg_trampoline(setg uintptr, G uintptr)
31
32//go:linkname memmove runtime.memmove
33func memmove(to, from unsafe.Pointer, n uintptr)
34
35// call5 takes fn the C function and 5 arguments and calls the function with those arguments
36func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr
37
38{{ range . -}}
39func {{.Name}}(
40{{- range .Args -}}
41 {{- if .Name -}}
42 {{.Name}} {{.Type}},
43 {{- end -}}
44{{- end -}}) {{.Return}} {
45 {{- if .Return -}}
46 {{- if eq .Return "unsafe.Pointer" -}}
47 ret :=
48 {{- else -}}
49 return {{.Return}}(
50 {{- end -}}
51 {{- end -}}
52call5({{.Name}}ABI0,
53{{- range .Args}}
54 {{- if .Name -}}
55 {{- if hasPrefix .Type "*" -}}
56 uintptr(unsafe.Pointer({{.Name}})),
57 {{- else -}}
58 uintptr({{.Name}}),
59 {{- end -}}
60 {{- else -}}
61 0,
62 {{- end -}}
63{{- end -}}
64 ) {{/* end of call5 */}}
65{{- if .Return -}}
66 {{- if eq .Return "unsafe.Pointer"}}
67 // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer
68 return *(*unsafe.Pointer)(unsafe.Pointer(&ret))
69 {{- else -}}
70 ) {{/* end of cast */}}
71 {{- end -}}
72{{- end}}
73}
74
75{{end}}
76{{- range . }}
77//go:linkname _{{.Name}} _{{.Name}}
78var _{{.Name}} uintptr
79var {{.Name}}ABI0 = uintptr(unsafe.Pointer(&_{{.Name}}))
80{{ end }}
81`
82
83const templateTrampolinesStubs = `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
84
85// SPDX-License-Identifier: Apache-2.0
86// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
87
88//go:build darwin || linux
89
90#include "textflag.h"
91
92// these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm64
93{{ range . }}
94TEXT _{{.Name}}(SB), NOSPLIT, $0-0
95 JMP purego_{{.Name}}(SB)
96 RET
97{{ end -}}
98`
99
100type Arg struct {
101 Name string
102 Type string
103}
104
105type Symbol struct {
106 Name string
107 Args [5]Arg
108 Return string
109}
110
111var symbols = []Symbol{
112 {"malloc", [5]Arg{{"size", "uintptr"}}, "unsafe.Pointer"},
113 {"free", [5]Arg{{"ptr", "unsafe.Pointer"}}, ""},
114 {"setenv", [5]Arg{{"name", "*byte"}, {"value", "*byte"}, {"overwrite", "int32"}}, "int32"},
115 {"unsetenv", [5]Arg{{"name", "*byte"}}, "int32"},
116 {"pthread_attr_init", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32"},
117 {"pthread_create", [5]Arg{{"thread", "*pthread_t"}, {"attr", "*pthread_attr_t"}, {"start", "unsafe.Pointer"}, {"arg", "unsafe.Pointer"}}, "int32"},
118 {"pthread_detach", [5]Arg{{"thread", "pthread_t"}}, "int32"},
119 {"pthread_sigmask", [5]Arg{{"how", "sighow"}, {"ign", "*sigset_t"}, {"oset", "*sigset_t"}}, "int32"},
120 {"pthread_self", [5]Arg{}, "pthread_t"},
121 {"pthread_get_stacksize_np", [5]Arg{{"thread", "pthread_t"}}, "size_t"},
122 {"pthread_attr_getstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"stacksize", "*size_t"}}, "int32"},
123 {"pthread_attr_setstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"size", "size_t"}}, "int32"},
124 {"pthread_attr_destroy", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32"},
125 {"sigfillset", [5]Arg{{"set", "*sigset_t"}}, "int32"},
126 {"nanosleep", [5]Arg{{"ts", "*syscall.Timespec"}, {"rem", "*syscall.Timespec"}}, "int32"},
127 {"abort", [5]Arg{}, ""},
128}
129
130var funcs = map[string]any{
131 "hasPrefix": strings.HasPrefix,
132}
133
134func run() error {
135 t, err := template.New("symbol.go").Funcs(funcs).Parse(templateSymbols)
136 if err != nil {
137 return err
138 }
139 f, err := os.Create("symbols.go")
140 defer f.Close()
141 if err != nil {
142 return err
143 }
144 if err := t.Execute(f, symbols); err != nil {
145 return err
146 }
147 t, err = template.New("trampolines_stubs.s").Funcs(funcs).Parse(templateTrampolinesStubs)
148 if err != nil {
149 return err
150 }
151 f, err = os.Create("trampolines_stubs.s")
152 defer f.Close()
153 if err != nil {
154 return err
155 }
156 if err := t.Execute(f, symbols); err != nil {
157 return err
158 }
159 return nil
160}
161
162func main() {
163 if err := run(); err != nil {
164 log.Fatal(err)
165 }
166}