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