compileopts.mx raw
1 package main
2
3 import (
4 "bytes"
5 "unsafe"
6 )
7
8 type targetSpec struct {
9 triple string
10 cpu string
11 features string
12 goos string
13 goarch string
14 gc string
15 scheduler string
16 linker string
17 rtlib string
18 libc string
19 stackSize uint64
20 buildMode string
21 ldflags []string
22 cflags []string
23 extraFiles []string
24 buildTags []string
25 binaryFormat string
26 }
27
28 var targets []*targetSpec
29
30 //export moxie_target_load
31 func moxie_target_load(goosPtr unsafe.Pointer, goosLen int32, goarchPtr unsafe.Pointer, goarchLen int32, buildMode int32) int32 {
32 goos := unsafe.Slice((*byte)(goosPtr), goosLen)
33 goarch := unsafe.Slice((*byte)(goarchPtr), goarchLen)
34
35 spec := &targetSpec{
36 goos: goos,
37 goarch: goarch,
38 linker: "cc",
39 stackSize: 1024 * 64,
40 scheduler: "none",
41 }
42
43 var llvmarch string
44 switch {
45 case goarch == "amd64":
46 llvmarch = "x86_64"
47 spec.cpu = "x86-64"
48 spec.features = "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
49 case goarch == "arm64":
50 spec.cpu = "generic"
51 llvmarch = "aarch64"
52 if goos == "darwin" {
53 spec.features = "+ete,+fp-armv8,+neon,+trbe,+v8a"
54 llvmarch = "arm64"
55 } else {
56 spec.features = "+ete,+fp-armv8,+neon,+trbe,+v8a,-fmv,-outline-atomics"
57 }
58 case goarch == "wasm":
59 if goos != "js" {
60 return -1
61 }
62 llvmarch = "wasm32"
63 spec.cpu = "generic"
64 spec.features = "+mutable-globals,+sign-ext"
65 default:
66 return -1
67 }
68
69 llvmos := goos
70 llvmvendor := "unknown"
71
72 switch {
73 case goos == "darwin":
74 spec.gc = "boehm"
75 platformVersion := "10.12.0"
76 if goarch == "arm64" {
77 platformVersion = "11.0.0"
78 }
79 llvmvendor = "apple"
80 spec.linker = "ld.lld"
81 spec.libc = "darwin-libSystem"
82 llvmos = "macosx" | platformVersion
83 spec.ldflags = append(spec.ldflags,
84 "-flavor", "darwin",
85 "-dead_strip",
86 "-arch", llvmarch,
87 "-platform_version", "macos", platformVersion, platformVersion)
88 spec.extraFiles = append(spec.extraFiles,
89 "src/runtime/os_darwin.c",
90 "src/runtime/runtime_unix.c",
91 "src/runtime/secalloc.c",
92 "src/runtime/signal.c",
93 "src/runtime/spawn_unix.c",
94 "src/internal/futex/futex_darwin.c")
95 case goos == "linux":
96 spec.gc = "boehm"
97 spec.linker = "ld.lld"
98 spec.rtlib = "compiler-rt"
99 spec.libc = "musl"
100 spec.ldflags = append(spec.ldflags, "--gc-sections")
101 if goarch == "arm64" {
102 spec.cflags = append(spec.cflags, "-mno-outline-atomics")
103 }
104 spec.extraFiles = append(spec.extraFiles,
105 "src/runtime/runtime_unix.c",
106 "src/runtime/secalloc.c",
107 "src/runtime/signal.c",
108 "src/runtime/spawn_unix.c",
109 "src/internal/futex/futex_linux.c")
110 case goos == "js":
111 spec.gc = "leaking"
112 spec.linker = "wasm-ld"
113 spec.buildTags = append(spec.buildTags, "moxie.wasm", "moxie.unicore")
114 spec.ldflags = append(spec.ldflags,
115 "--export-dynamic",
116 "--allow-undefined",
117 "--gc-sections")
118 default:
119 return -1
120 }
121
122 if spec.gc == "boehm" {
123 spec.extraFiles = append(spec.extraFiles, "src/runtime/gc_boehm.c")
124 }
125
126 spec.triple = llvmarch | "-" | llvmvendor | "-" | llvmos
127 if goos == "linux" {
128 spec.triple = spec.triple | "-musleabihf"
129 }
130
131 if goarch != "wasm" {
132 spec.extraFiles = append(spec.extraFiles, "src/runtime/asm_" | goarch | ".S")
133 }
134
135 spec.buildTags = append(spec.buildTags, goos, goarch)
136
137 if buildMode == 1 {
138 spec.buildMode = "c-shared"
139 spec.ldflags = append(spec.ldflags, "--shared")
140 }
141
142 targets = append(targets, spec)
143 return int32(len(targets) - 1)
144 }
145
146 func copyToOut(s string, outPtr unsafe.Pointer, outCap int32) int32 {
147 n := int32(len(s))
148 if n > outCap {
149 n = outCap
150 }
151 out := unsafe.Slice((*byte)(outPtr), outCap)
152 copy(out[:n], s)
153 return n
154 }
155
156 func validTarget(h int32) *targetSpec {
157 if h < 0 || h >= int32(len(targets)) {
158 return nil
159 }
160 return targets[h]
161 }
162
163 //export moxie_target_triple
164 func moxie_target_triple(h int32, outPtr unsafe.Pointer, outCap int32) int32 {
165 t := validTarget(h)
166 if t == nil {
167 return -1
168 }
169 return copyToOut(t.triple, outPtr, outCap)
170 }
171
172 //export moxie_target_cpu
173 func moxie_target_cpu(h int32, outPtr unsafe.Pointer, outCap int32) int32 {
174 t := validTarget(h)
175 if t == nil {
176 return -1
177 }
178 return copyToOut(t.cpu, outPtr, outCap)
179 }
180
181 //export moxie_target_features
182 func moxie_target_features(h int32, outPtr unsafe.Pointer, outCap int32) int32 {
183 t := validTarget(h)
184 if t == nil {
185 return -1
186 }
187 return copyToOut(t.features, outPtr, outCap)
188 }
189
190 //export moxie_target_gc
191 func moxie_target_gc(h int32, outPtr unsafe.Pointer, outCap int32) int32 {
192 t := validTarget(h)
193 if t == nil {
194 return -1
195 }
196 return copyToOut(t.gc, outPtr, outCap)
197 }
198
199 //export moxie_target_linker
200 func moxie_target_linker(h int32, outPtr unsafe.Pointer, outCap int32) int32 {
201 t := validTarget(h)
202 if t == nil {
203 return -1
204 }
205 return copyToOut(t.linker, outPtr, outCap)
206 }
207
208 //export moxie_target_libc
209 func moxie_target_libc(h int32, outPtr unsafe.Pointer, outCap int32) int32 {
210 t := validTarget(h)
211 if t == nil {
212 return -1
213 }
214 return copyToOut(t.libc, outPtr, outCap)
215 }
216
217 //export moxie_target_stack_size
218 func moxie_target_stack_size(h int32) int64 {
219 t := validTarget(h)
220 if t == nil {
221 return -1
222 }
223 return int64(t.stackSize)
224 }
225
226 //export moxie_target_ldflag_count
227 func moxie_target_ldflag_count(h int32) int32 {
228 t := validTarget(h)
229 if t == nil {
230 return -1
231 }
232 return int32(len(t.ldflags))
233 }
234
235 //export moxie_target_ldflag
236 func moxie_target_ldflag(h int32, idx int32, outPtr unsafe.Pointer, outCap int32) int32 {
237 t := validTarget(h)
238 if t == nil || idx < 0 || idx >= int32(len(t.ldflags)) {
239 return -1
240 }
241 return copyToOut(t.ldflags[idx], outPtr, outCap)
242 }
243
244 //export moxie_target_extra_file_count
245 func moxie_target_extra_file_count(h int32) int32 {
246 t := validTarget(h)
247 if t == nil {
248 return -1
249 }
250 return int32(len(t.extraFiles))
251 }
252
253 //export moxie_target_extra_file
254 func moxie_target_extra_file(h int32, idx int32, outPtr unsafe.Pointer, outCap int32) int32 {
255 t := validTarget(h)
256 if t == nil || idx < 0 || idx >= int32(len(t.extraFiles)) {
257 return -1
258 }
259 return copyToOut(t.extraFiles[idx], outPtr, outCap)
260 }
261
262 //export moxie_target_build_tag_count
263 func moxie_target_build_tag_count(h int32) int32 {
264 t := validTarget(h)
265 if t == nil {
266 return -1
267 }
268 return int32(len(t.buildTags))
269 }
270
271 //export moxie_target_build_tag
272 func moxie_target_build_tag(h int32, idx int32, outPtr unsafe.Pointer, outCap int32) int32 {
273 t := validTarget(h)
274 if t == nil || idx < 0 || idx >= int32(len(t.buildTags)) {
275 return -1
276 }
277 return copyToOut(t.buildTags[idx], outPtr, outCap)
278 }
279
280 //export moxie_target_opt_level
281 func moxie_target_opt_level(optPtr unsafe.Pointer, optLen int32, outSpeed unsafe.Pointer, outSize unsafe.Pointer) int32 {
282 opt := unsafe.Slice((*byte)(optPtr), optLen)
283 var speed, size int32
284 switch {
285 case opt == "none" || opt == "0":
286 speed, size = 0, 0
287 case opt == "1":
288 speed, size = 1, 0
289 case opt == "2":
290 speed, size = 2, 0
291 case opt == "s":
292 speed, size = 2, 1
293 case opt == "z":
294 speed, size = 2, 2
295 default:
296 return -1
297 }
298 *(*int32)(outSpeed) = speed
299 *(*int32)(outSize) = size
300 return 0
301 }
302
303 //export moxie_target_canonical_arch
304 func moxie_target_canonical_arch(triplePtr unsafe.Pointer, tripleLen int32, outPtr unsafe.Pointer, outCap int32) int32 {
305 triple := unsafe.Slice((*byte)(triplePtr), tripleLen)
306 idx := bytes.IndexByte(triple, '-')
307 arch := triple
308 if idx >= 0 {
309 arch = triple[:idx]
310 }
311 if arch == "arm64" {
312 arch = "aarch64"
313 }
314 return copyToOut(arch, outPtr, outCap)
315 }
316
317 //export moxie_target_free
318 func moxie_target_free(h int32) {
319 if h >= 0 && h < int32(len(targets)) {
320 targets[h] = nil
321 }
322 }
323
324 func main() {}
325