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