aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--builder/build.go1
-rw-r--r--builder/builder_test.go9
-rw-r--r--builder/library.go5
-rw-r--r--compileopts/config.go9
-rw-r--r--compileopts/options.go1
-rw-r--r--compileopts/target.go16
-rw-r--r--goenv/goenv.go12
-rw-r--r--main.go3
-rw-r--r--main_test.go8
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
diff --git a/main.go b/main.go
index 32fc22665..cbe4b9dd4 100644
--- a/main.go
+++ b/main.go
@@ -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
}