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 uint32
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 spec.features = "+ete,+fp-armv8,+neon,+trbe,+v8a,-fmv,-outline-atomics"
53 case goarch == "wasm":
54 if goos != "js" {
55 return -1
56 }
57 llvmarch = "wasm32"
58 spec.cpu = "generic"
59 spec.features = "+mutable-globals,+sign-ext"
60 default:
61 return -1
62 }
63
64 llvmos := goos
65 llvmvendor := "unknown"
66
67 switch {
68 case goos == "linux":
69 spec.gc = "boehm"
70 spec.linker = "ld.lld"
71 spec.rtlib = "compiler-rt"
72 spec.libc = "musl"
73 spec.ldflags = append(spec.ldflags, "--gc-sections")
74 if goarch == "arm64" {
75 spec.cflags = append(spec.cflags, "-mno-outline-atomics")
76 }
77 spec.extraFiles = append(spec.extraFiles,
78 "src/runtime/runtime_unix.c",
79 "src/runtime/secalloc.c",
80 "src/runtime/signal.c",
81 "src/runtime/spawn_unix.c",
82 "src/internal/futex/futex_linux.c")
83 case goos == "js":
84 spec.gc = "leaking"
85 spec.linker = "wasm-ld"
86 spec.buildTags = append(spec.buildTags, "moxie.wasm", "moxie.unicore")
87 spec.ldflags = append(spec.ldflags,
88 "--export-dynamic",
89 "--allow-undefined",
90 "--gc-sections")
91 default:
92 return -1
93 }
94
95 if spec.gc == "boehm" {
96 spec.extraFiles = append(spec.extraFiles, "src/runtime/gc_boehm.c")
97 }
98
99 spec.triple = llvmarch | "-" | llvmvendor | "-" | llvmos
100 if goos == "linux" {
101 spec.triple = spec.triple | "-musleabihf"
102 }
103
104 if goarch != "wasm" {
105 spec.extraFiles = append(spec.extraFiles, "src/runtime/asm_" | goarch | ".S")
106 }
107
108 spec.buildTags = append(spec.buildTags, goos, goarch)
109
110 if buildMode == 1 {
111 spec.buildMode = "c-shared"
112 spec.ldflags = append(spec.ldflags, "--shared")
113 }
114
115 targets = append(targets, spec)
116 return int32(len(targets) - 1)
117 }
118
119 func copyToOut(s string, outPtr unsafe.Pointer, outCap int32) int32 {
120 n := int32(len(s))
121 if n > outCap {
122 n = outCap
123 }
124 out := unsafe.Slice((*byte)(outPtr), outCap)
125 copy(out[:n], s)
126 return n
127 }
128
129 func validTarget(h int32) *targetSpec {
130 if h < 0 || h >= int32(len(targets)) {
131 return nil
132 }
133 return targets[h]
134 }
135
136 //export moxie_target_triple
137 func moxie_target_triple(h int32, outPtr unsafe.Pointer, outCap int32) int32 {
138 t := validTarget(h)
139 if t == nil {
140 return -1
141 }
142 return copyToOut(t.triple, outPtr, outCap)
143 }
144
145 //export moxie_target_cpu
146 func moxie_target_cpu(h int32, outPtr unsafe.Pointer, outCap int32) int32 {
147 t := validTarget(h)
148 if t == nil {
149 return -1
150 }
151 return copyToOut(t.cpu, outPtr, outCap)
152 }
153
154 //export moxie_target_features
155 func moxie_target_features(h int32, outPtr unsafe.Pointer, outCap int32) int32 {
156 t := validTarget(h)
157 if t == nil {
158 return -1
159 }
160 return copyToOut(t.features, outPtr, outCap)
161 }
162
163 //export moxie_target_gc
164 func moxie_target_gc(h int32, outPtr unsafe.Pointer, outCap int32) int32 {
165 t := validTarget(h)
166 if t == nil {
167 return -1
168 }
169 return copyToOut(t.gc, outPtr, outCap)
170 }
171
172 //export moxie_target_linker
173 func moxie_target_linker(h int32, outPtr unsafe.Pointer, outCap int32) int32 {
174 t := validTarget(h)
175 if t == nil {
176 return -1
177 }
178 return copyToOut(t.linker, outPtr, outCap)
179 }
180
181 //export moxie_target_libc
182 func moxie_target_libc(h int32, outPtr unsafe.Pointer, outCap int32) int32 {
183 t := validTarget(h)
184 if t == nil {
185 return -1
186 }
187 return copyToOut(t.libc, outPtr, outCap)
188 }
189
190 //export moxie_target_stack_size
191 func moxie_target_stack_size(h int32) int32 {
192 t := validTarget(h)
193 if t == nil {
194 return -1
195 }
196 return int32(t.stackSize)
197 }
198
199 //export moxie_target_ldflag_count
200 func moxie_target_ldflag_count(h int32) int32 {
201 t := validTarget(h)
202 if t == nil {
203 return -1
204 }
205 return int32(len(t.ldflags))
206 }
207
208 //export moxie_target_ldflag
209 func moxie_target_ldflag(h int32, idx int32, outPtr unsafe.Pointer, outCap int32) int32 {
210 t := validTarget(h)
211 if t == nil || idx < 0 || idx >= int32(len(t.ldflags)) {
212 return -1
213 }
214 return copyToOut(t.ldflags[idx], outPtr, outCap)
215 }
216
217 //export moxie_target_extra_file_count
218 func moxie_target_extra_file_count(h int32) int32 {
219 t := validTarget(h)
220 if t == nil {
221 return -1
222 }
223 return int32(len(t.extraFiles))
224 }
225
226 //export moxie_target_extra_file
227 func moxie_target_extra_file(h int32, idx int32, outPtr unsafe.Pointer, outCap int32) int32 {
228 t := validTarget(h)
229 if t == nil || idx < 0 || idx >= int32(len(t.extraFiles)) {
230 return -1
231 }
232 return copyToOut(t.extraFiles[idx], outPtr, outCap)
233 }
234
235 //export moxie_target_build_tag_count
236 func moxie_target_build_tag_count(h int32) int32 {
237 t := validTarget(h)
238 if t == nil {
239 return -1
240 }
241 return int32(len(t.buildTags))
242 }
243
244 //export moxie_target_build_tag
245 func moxie_target_build_tag(h int32, idx int32, outPtr unsafe.Pointer, outCap int32) int32 {
246 t := validTarget(h)
247 if t == nil || idx < 0 || idx >= int32(len(t.buildTags)) {
248 return -1
249 }
250 return copyToOut(t.buildTags[idx], outPtr, outCap)
251 }
252
253 //export moxie_target_opt_level
254 func moxie_target_opt_level(optPtr unsafe.Pointer, optLen int32, outSpeed unsafe.Pointer, outSize unsafe.Pointer) int32 {
255 opt := unsafe.Slice((*byte)(optPtr), optLen)
256 var speed, size int32
257 switch {
258 case opt == "none" || opt == "0":
259 speed, size = 0, 0
260 case opt == "1":
261 speed, size = 1, 0
262 case opt == "2":
263 speed, size = 2, 0
264 case opt == "s":
265 speed, size = 2, 1
266 case opt == "z":
267 speed, size = 2, 2
268 default:
269 return -1
270 }
271 *(*int32)(outSpeed) = speed
272 *(*int32)(outSize) = size
273 return 0
274 }
275
276 //export moxie_target_canonical_arch
277 func moxie_target_canonical_arch(triplePtr unsafe.Pointer, tripleLen int32, outPtr unsafe.Pointer, outCap int32) int32 {
278 triple := unsafe.Slice((*byte)(triplePtr), tripleLen)
279 idx := bytes.IndexByte(triple, '-')
280 arch := triple
281 if idx >= 0 {
282 arch = triple[:idx]
283 }
284 if arch == "arm64" {
285 arch = "aarch64"
286 }
287 return copyToOut(arch, outPtr, outCap)
288 }
289
290 //export moxie_target_free
291 func moxie_target_free(h int32) {
292 if h >= 0 && h < int32(len(targets)) {
293 targets[h] = nil
294 }
295 }
296
297 func main() {}
298