diff options
-rw-r--r-- | builder/build.go | 1 | ||||
-rw-r--r-- | builder/builder_test.go | 9 | ||||
-rw-r--r-- | builder/library.go | 5 | ||||
-rw-r--r-- | compileopts/config.go | 9 | ||||
-rw-r--r-- | compileopts/options.go | 1 | ||||
-rw-r--r-- | compileopts/target.go | 16 | ||||
-rw-r--r-- | goenv/goenv.go | 12 | ||||
-rw-r--r-- | main.go | 3 | ||||
-rw-r--r-- | main_test.go | 8 |
9 files changed, 58 insertions, 6 deletions
diff --git a/builder/build.go b/builder/build.go index 33c3b2858..f728cde79 100644 --- a/builder/build.go +++ b/builder/build.go @@ -746,6 +746,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe ldflags = append(ldflags, dependency.result) } ldflags = append(ldflags, "-mllvm", "-mcpu="+config.CPU()) + ldflags = append(ldflags, "-mllvm", "-mattr="+config.Features()) // needed for MIPS softfloat if config.GOOS() == "windows" { // Options for the MinGW wrapper for the lld COFF linker. ldflags = append(ldflags, diff --git a/builder/builder_test.go b/builder/builder_test.go index 1b3e76ded..92ed9bdcc 100644 --- a/builder/builder_test.go +++ b/builder/builder_test.go @@ -57,8 +57,10 @@ func TestClangAttributes(t *testing.T) { {GOOS: "linux", GOARCH: "arm", GOARM: "6"}, {GOOS: "linux", GOARCH: "arm", GOARM: "7"}, {GOOS: "linux", GOARCH: "arm64"}, - {GOOS: "linux", GOARCH: "mips"}, - {GOOS: "linux", GOARCH: "mipsle"}, + {GOOS: "linux", GOARCH: "mips", GOMIPS: "hardfloat"}, + {GOOS: "linux", GOARCH: "mipsle", GOMIPS: "hardfloat"}, + {GOOS: "linux", GOARCH: "mips", GOMIPS: "softfloat"}, + {GOOS: "linux", GOARCH: "mipsle", GOMIPS: "softfloat"}, {GOOS: "darwin", GOARCH: "amd64"}, {GOOS: "darwin", GOARCH: "arm64"}, {GOOS: "windows", GOARCH: "amd64"}, @@ -69,6 +71,9 @@ func TestClangAttributes(t *testing.T) { if options.GOARCH == "arm" { name += ",GOARM=" + options.GOARM } + if options.GOARCH == "mips" || options.GOARCH == "mipsle" { + name += ",GOMIPS=" + options.GOMIPS + } t.Run(name, func(t *testing.T) { testClangAttributes(t, options) }) diff --git a/builder/library.go b/builder/library.go index 0ab7fa0e4..b8d183414 100644 --- a/builder/library.go +++ b/builder/library.go @@ -169,6 +169,11 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ case "mips": args = append(args, "-fno-pic") } + if config.Target.SoftFloat { + // Use softfloat instead of floating point instructions. This is + // supported on many architectures. + args = append(args, "-msoft-float") + } var once sync.Once diff --git a/compileopts/config.go b/compileopts/config.go index a5ab7cd8f..67c773de1 100644 --- a/compileopts/config.go +++ b/compileopts/config.go @@ -72,6 +72,12 @@ func (c *Config) GOARM() string { return c.Options.GOARM } +// GOMIPS will return the GOMIPS environment variable given to the compiler when +// building a program. +func (c *Config) GOMIPS() string { + return c.Options.GOMIPS +} + // BuildTags returns the complete list of build tags used during this build. func (c *Config) BuildTags() []string { tags := append([]string(nil), c.Target.BuildTags...) // copy slice (avoid a race) @@ -240,6 +246,9 @@ func (c *Config) LibcPath(name string) (path string, precompiled bool) { if c.ABI() != "" { archname += "-" + c.ABI() } + if c.Target.SoftFloat { + archname += "-softfloat" + } // Try to load a precompiled library. precompiledDir := filepath.Join(goenv.Get("TINYGOROOT"), "pkg", archname, name) diff --git a/compileopts/options.go b/compileopts/options.go index 8b0e2266d..9601ae322 100644 --- a/compileopts/options.go +++ b/compileopts/options.go @@ -23,6 +23,7 @@ type Options struct { GOOS string // environment variable GOARCH string // environment variable GOARM string // environment variable (only used with GOARCH=arm) + GOMIPS string // environment variable (only used with GOARCH=mips and GOARCH=mipsle) Directory string // working dir, leave it unset to use the current working dir Target string Opt string diff --git a/compileopts/target.go b/compileopts/target.go index ecbebd8b3..9388b8496 100644 --- a/compileopts/target.go +++ b/compileopts/target.go @@ -30,6 +30,7 @@ type TargetSpec struct { Features string `json:"features,omitempty"` GOOS string `json:"goos,omitempty"` GOARCH string `json:"goarch,omitempty"` + SoftFloat bool // used for non-baremetal systems (GOMIPS=softfloat etc) BuildTags []string `json:"build-tags,omitempty"` GC string `json:"gc,omitempty"` Scheduler string `json:"scheduler,omitempty"` @@ -86,6 +87,10 @@ func (spec *TargetSpec) overrideProperties(child *TargetSpec) error { if src.Uint() != 0 { dst.Set(src) } + case reflect.Bool: + if src.Bool() { + dst.Set(src) + } case reflect.Ptr: // for pointers, copy if not nil if !src.IsNil() { dst.Set(src) @@ -290,13 +295,22 @@ func defaultTarget(options *Options) (*TargetSpec, error) { } case "mips", "mipsle": spec.CPU = "mips32r2" - spec.Features = "+fpxx,+mips32r2,+nooddspreg,-noabicalls" spec.CFlags = append(spec.CFlags, "-fno-pic") if options.GOOS == "mips" { llvmarch = "mips" // big endian } else { llvmarch = "mipsel" // little endian } + switch options.GOMIPS { + case "hardfloat": + spec.Features = "+fpxx,+mips32r2,+nooddspreg,-noabicalls" + case "softfloat": + spec.SoftFloat = true + spec.Features = "+mips32r2,+soft-float,-noabicalls" + spec.CFlags = append(spec.CFlags, "-msoft-float") + default: + return nil, fmt.Errorf("invalid GOMIPS=%s: must be hardfloat or softfloat", options.GOMIPS) + } case "wasm": llvmarch = "wasm32" spec.CPU = "generic" diff --git a/goenv/goenv.go b/goenv/goenv.go index 187bcc6df..fe4c8bf63 100644 --- a/goenv/goenv.go +++ b/goenv/goenv.go @@ -30,8 +30,11 @@ var Keys = []string{ } func init() { - if Get("GOARCH") == "arm" { + switch Get("GOARCH") { + case "arm": Keys = append(Keys, "GOARM") + case "mips", "mipsle": + Keys = append(Keys, "GOMIPS") } } @@ -128,6 +131,13 @@ func Get(name string) string { // difference between ARMv6 and ARMv7. ARMv6 binaries are much smaller, // especially when floating point instructions are involved. return "6" + case "GOMIPS": + gomips := os.Getenv("GOMIPS") + if gomips == "" { + // Default to hardfloat (this matches the Go toolchain). + gomips = "hardfloat" + } + return gomips case "GOROOT": readGoEnvVars() return goEnvVars.GOROOT @@ -1499,6 +1499,7 @@ func main() { GOOS: goenv.Get("GOOS"), GOARCH: goenv.Get("GOARCH"), GOARM: goenv.Get("GOARM"), + GOMIPS: goenv.Get("GOMIPS"), Target: *target, StackSize: stackSize, Opt: *opt, @@ -1737,6 +1738,7 @@ func main() { GOOS string `json:"goos"` GOARCH string `json:"goarch"` GOARM string `json:"goarm"` + GOMIPS string `json:"gomips"` BuildTags []string `json:"build_tags"` GC string `json:"garbage_collector"` Scheduler string `json:"scheduler"` @@ -1747,6 +1749,7 @@ func main() { GOOS: config.GOOS(), GOARCH: config.GOARCH(), GOARM: config.GOARM(), + GOMIPS: config.GOMIPS(), BuildTags: config.BuildTags(), GC: config.GC(), Scheduler: config.Scheduler(), diff --git a/main_test.go b/main_test.go index ccd490d62..4c11f7b18 100644 --- a/main_test.go +++ b/main_test.go @@ -36,7 +36,7 @@ var supportedLinuxArches = map[string]string{ "X86Linux": "linux/386", "ARMLinux": "linux/arm/6", "ARM64Linux": "linux/arm64", - "MIPSLinux": "linux/mipsle", + "MIPSLinux": "linux/mipsle/hardfloat", "WASIp1": "wasip1/wasm", } @@ -325,6 +325,7 @@ func optionsFromTarget(target string, sema chan struct{}) compileopts.Options { GOOS: goenv.Get("GOOS"), GOARCH: goenv.Get("GOARCH"), GOARM: goenv.Get("GOARM"), + GOMIPS: goenv.Get("GOMIPS"), Target: target, Semaphore: sema, InterpTimeout: 180 * time.Second, @@ -348,8 +349,11 @@ func optionsFromOSARCH(osarch string, sema chan struct{}) compileopts.Options { VerifyIR: true, Opt: "z", } - if options.GOARCH == "arm" { + switch options.GOARCH { + case "arm": options.GOARM = parts[2] + case "mips", "mipsle": + options.GOMIPS = parts[2] } return options } |