From 78fec3719f73e75b5f8ba8e13de0a4f61499e557 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 6 Nov 2021 15:29:54 +0100 Subject: [PATCH] all: add target-features string to all targets This makes sure that the LLVM target features match the one generated by Clang: - This fixes a bug introduced when setting the target CPU for all targets: Cortex-M4 would now start using floating point operations while they were disabled in C. - This will make it possible in the future to inline C functions in Go and vice versa. This will need some more work though. There is a code size impact. Cortex-M4 targets are increased slightly in binary size while Cortex-M0 targets tend to be reduced a little bit. Other than that, there is little impact. --- builder/build.go | 1 - builder/builder_test.go | 22 ++++++++++++++++++---- compileopts/config.go | 18 ++++++++++-------- compileopts/target.go | 6 +++++- compiler/compiler.go | 11 ++--------- targets/cortex-m0.json | 3 ++- targets/cortex-m0plus.json | 3 ++- targets/cortex-m3.json | 3 ++- targets/cortex-m4.json | 1 + targets/cortex-m7.json | 1 + targets/esp32c3.json | 5 ++++- targets/fe310.json | 2 +- targets/gameboy-advance.json | 1 + targets/k210.json | 2 +- targets/nintendoswitch.json | 1 + targets/riscv-qemu.json | 2 +- targets/riscv.json | 1 + 17 files changed, 53 insertions(+), 30 deletions(-) diff --git a/builder/build.go b/builder/build.go index d9fc4139..5c3150c1 100644 --- a/builder/build.go +++ b/builder/build.go @@ -136,7 +136,6 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil DefaultStackSize: config.Target.DefaultStackSize, NeedsStackObjects: config.NeedsStackObjects(), Debug: true, - LLVMFeatures: config.LLVMFeatures(), } // Load the target machine, which is the LLVM object that contains all diff --git a/builder/builder_test.go b/builder/builder_test.go index 970c82ea..3d443dc4 100644 --- a/builder/builder_test.go +++ b/builder/builder_test.go @@ -12,8 +12,8 @@ import ( "tinygo.org/x/go-llvm" ) -// Test whether the Clang generated "target-cpu" attribute matches the CPU -// property in TinyGo target files. +// Test whether the Clang generated "target-cpu" and "target-features" +// attributes match the CPU and Features property in TinyGo target files. func TestClangAttributes(t *testing.T) { var targetNames = []string{ // Please keep this list sorted! @@ -112,16 +112,30 @@ func testClangAttributes(t *testing.T, options *compileopts.Options) { t.Errorf("target has LLVM triple %#v but Clang makes it LLVM triple %#v", config.Triple(), mod.Target()) } - // Check the "target-cpu" string attribute of the add function. + // Check the "target-cpu" and "target-features" string attribute of the add + // function. add := mod.NamedFunction("add") - var cpu string + var cpu, features string cpuAttr := add.GetStringAttributeAtIndex(-1, "target-cpu") + featuresAttr := add.GetStringAttributeAtIndex(-1, "target-features") if !cpuAttr.IsNil() { cpu = cpuAttr.GetStringValue() } + if !featuresAttr.IsNil() { + features = featuresAttr.GetStringValue() + } if cpu != config.CPU() { t.Errorf("target has CPU %#v but Clang makes it CPU %#v", config.CPU(), cpu) } + if features != config.Features() { + if llvm.Version != "11.0.0" { + // This needs to be removed once we switch to LLVM 12. + // LLVM 11.0.0 uses a different "target-features" string than LLVM + // 11.1.0 for Thumb targets. The Xtensa fork is still based on LLVM + // 11.0.0, so we need to skip this check on that version. + t.Errorf("target has LLVM features %#v but Clang makes it %#v", config.Features(), features) + } + } } // This TestMain is necessary because TinyGo may also be invoked to run certain diff --git a/compileopts/config.go b/compileopts/config.go index bdbdd0d2..0ee4d1d0 100644 --- a/compileopts/config.go +++ b/compileopts/config.go @@ -34,10 +34,16 @@ func (c *Config) CPU() string { } // Features returns a list of features this CPU supports. For example, for a -// RISC-V processor, that could be ["+a", "+c", "+m"]. For many targets, an -// empty list will be returned. -func (c *Config) Features() []string { - return c.Target.Features +// RISC-V processor, that could be "+a,+c,+m". For many targets, an empty list +// will be returned. +func (c *Config) Features() string { + if c.Target.Features == "" { + return c.Options.LLVMFeatures + } + if c.Options.LLVMFeatures == "" { + return c.Target.Features + } + return c.Target.Features + "," + c.Options.LLVMFeatures } // GOOS returns the GOOS of the target. This might not always be the actual OS: @@ -441,10 +447,6 @@ func (c *Config) WasmAbi() string { return c.Target.WasmAbi } -func (c *Config) LLVMFeatures() string { - return c.Options.LLVMFeatures -} - type TestConfig struct { CompileTestBinary bool // TODO: Filter the test functions to run, include verbose flag, etc diff --git a/compileopts/target.go b/compileopts/target.go index c15316e2..f16df32c 100644 --- a/compileopts/target.go +++ b/compileopts/target.go @@ -25,7 +25,7 @@ type TargetSpec struct { Inherits []string `json:"inherits"` Triple string `json:"llvm-target"` CPU string `json:"cpu"` - Features []string `json:"features"` + Features string `json:"features"` GOOS string `json:"goos"` GOARCH string `json:"goarch"` BuildTags []string `json:"build-tags"` @@ -234,12 +234,16 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) { switch goarch { case "386": spec.CPU = "pentium4" + spec.Features = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87" case "amd64": spec.CPU = "x86-64" + spec.Features = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87" case "arm": spec.CPU = "generic" + spec.Features = "+armv7-a,+dsp,+fp64,+vfp2,+vfp2sp,+vfp3d16,+vfp3d16sp,-thumb-mode" case "arm64": spec.CPU = "generic" + spec.Features = "+neon" } if goos == "darwin" { spec.CFlags = append(spec.CFlags, "-isysroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk") diff --git a/compiler/compiler.go b/compiler/compiler.go index fabfa54b..3d56fb1b 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -43,7 +43,7 @@ type Config struct { // Target and output information. Triple string CPU string - Features []string + Features string GOOS string GOARCH string CodeModel string @@ -57,7 +57,6 @@ type Config struct { DefaultStackSize uint64 NeedsStackObjects bool Debug bool // Whether to emit debug information in the LLVM module. - LLVMFeatures string } // compilerContext contains function-independent data that should still be @@ -189,12 +188,6 @@ func NewTargetMachine(config *Config) (llvm.TargetMachine, error) { return llvm.TargetMachine{}, err } - feat := config.Features - if len(config.LLVMFeatures) > 0 { - feat = append(feat, config.LLVMFeatures) - } - features := strings.Join(feat, ",") - var codeModel llvm.CodeModel var relocationModel llvm.RelocMode @@ -222,7 +215,7 @@ func NewTargetMachine(config *Config) (llvm.TargetMachine, error) { relocationModel = llvm.RelocDynamicNoPic } - machine := target.CreateTargetMachine(config.Triple, config.CPU, features, llvm.CodeGenLevelDefault, relocationModel, codeModel) + machine := target.CreateTargetMachine(config.Triple, config.CPU, config.Features, llvm.CodeGenLevelDefault, relocationModel, codeModel) return machine, nil } diff --git a/targets/cortex-m0.json b/targets/cortex-m0.json index 4cb4987c..fe356805 100644 --- a/targets/cortex-m0.json +++ b/targets/cortex-m0.json @@ -1,5 +1,6 @@ { "inherits": ["cortex-m"], "llvm-target": "thumbv6m-unknown-unknown-eabi", - "cpu": "cortex-m0" + "cpu": "cortex-m0", + "features": "+armv6-m,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" } diff --git a/targets/cortex-m0plus.json b/targets/cortex-m0plus.json index 4b364f06..a21d06ca 100644 --- a/targets/cortex-m0plus.json +++ b/targets/cortex-m0plus.json @@ -1,5 +1,6 @@ { "inherits": ["cortex-m"], "llvm-target": "thumbv6m-unknown-unknown-eabi", - "cpu": "cortex-m0plus" + "cpu": "cortex-m0plus", + "features": "+armv6-m,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" } diff --git a/targets/cortex-m3.json b/targets/cortex-m3.json index 629d578e..7b878d52 100644 --- a/targets/cortex-m3.json +++ b/targets/cortex-m3.json @@ -1,5 +1,6 @@ { "inherits": ["cortex-m"], "llvm-target": "thumbv7m-unknown-unknown-eabi", - "cpu": "cortex-m3" + "cpu": "cortex-m3", + "features": "+armv7-m,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" } diff --git a/targets/cortex-m4.json b/targets/cortex-m4.json index 84601e4d..ce947efb 100644 --- a/targets/cortex-m4.json +++ b/targets/cortex-m4.json @@ -2,6 +2,7 @@ "inherits": ["cortex-m"], "llvm-target": "thumbv7em-unknown-unknown-eabi", "cpu": "cortex-m4", + "features": "+armv7e-m,+dsp,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp", "cflags": [ "-mfloat-abi=soft" ] diff --git a/targets/cortex-m7.json b/targets/cortex-m7.json index 08bb6595..43fe532f 100644 --- a/targets/cortex-m7.json +++ b/targets/cortex-m7.json @@ -2,6 +2,7 @@ "inherits": ["cortex-m"], "llvm-target": "thumbv7em-unknown-unknown-eabi", "cpu": "cortex-m7", + "features": "+armv7e-m,+dsp,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp", "cflags": [ "-mfloat-abi=soft" ] diff --git a/targets/esp32c3.json b/targets/esp32c3.json index 1ef70922..d377fcec 100644 --- a/targets/esp32c3.json +++ b/targets/esp32c3.json @@ -1,10 +1,13 @@ { "inherits": ["riscv32"], - "features": ["+c", "+m"], + "features": "+c,+m,-relax,-save-restore", "build-tags": ["esp32c3", "esp"], "serial": "uart", "rtlib": "compiler-rt", "libc": "picolibc", + "cflags": [ + "-march=rv32imc" + ], "linkerscript": "targets/esp32c3.ld", "extra-files": [ "src/device/esp/esp32c3.S" diff --git a/targets/fe310.json b/targets/fe310.json index c513a39f..2c9e6b5c 100644 --- a/targets/fe310.json +++ b/targets/fe310.json @@ -1,6 +1,6 @@ { "inherits": ["riscv32"], "cpu": "sifive-e31", - "features": ["+a", "+c", "+m"], + "features": "+a,+c,+m,-64bit,-relax,-save-restore", "build-tags": ["fe310", "sifive"] } diff --git a/targets/gameboy-advance.json b/targets/gameboy-advance.json index eec103c5..24e16cda 100644 --- a/targets/gameboy-advance.json +++ b/targets/gameboy-advance.json @@ -1,6 +1,7 @@ { "llvm-target": "armv4t-unknown-unknown-eabi", "cpu": "arm7tdmi", + "features": "+armv4t,+soft-float,+strict-align,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-ras,-sb,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp", "build-tags": ["gameboyadvance", "arm7tdmi", "baremetal", "linux", "arm"], "goos": "linux", "goarch": "arm", diff --git a/targets/k210.json b/targets/k210.json index 4c5f3f91..2416a593 100644 --- a/targets/k210.json +++ b/targets/k210.json @@ -1,6 +1,6 @@ { "inherits": ["riscv64"], - "features": ["+a", "+c", "+m", "+f", "+d"], + "features": "+a,+c,+d,+f,+m,-relax,-save-restore", "build-tags": ["k210", "kendryte"], "code-model": "medium" } diff --git a/targets/nintendoswitch.json b/targets/nintendoswitch.json index 211b2b29..ec0b2713 100644 --- a/targets/nintendoswitch.json +++ b/targets/nintendoswitch.json @@ -1,6 +1,7 @@ { "llvm-target": "aarch64", "cpu": "cortex-a57", + "features": "+aes,+crc,+crypto,+fp-armv8,+neon,+sha2", "build-tags": ["nintendoswitch", "arm64"], "scheduler": "tasks", "goos": "linux", diff --git a/targets/riscv-qemu.json b/targets/riscv-qemu.json index 4f2c695f..0af2ef87 100644 --- a/targets/riscv-qemu.json +++ b/targets/riscv-qemu.json @@ -1,6 +1,6 @@ { "inherits": ["riscv32"], - "features": ["+a", "+c", "+m"], + "features": "+a,+c,+m,-relax,-save-restore", "build-tags": ["virt", "qemu"], "linkerscript": "targets/riscv-qemu.ld", "emulator": ["qemu-system-riscv32", "-machine", "virt", "-nographic", "-bios", "none", "-kernel"] diff --git a/targets/riscv.json b/targets/riscv.json index 4fe9af50..8d9dbb26 100644 --- a/targets/riscv.json +++ b/targets/riscv.json @@ -8,6 +8,7 @@ "libc": "picolibc", "cflags": [ "-Werror", + "-mno-relax", "-fno-exceptions", "-fno-unwind-tables", "-ffunction-sections", "-fdata-sections" ],