diff options
author | Ayke van Laethem <[email protected]> | 2021-11-01 19:11:04 +0100 |
---|---|---|
committer | Ron Evans <[email protected]> | 2021-11-03 23:03:44 +0100 |
commit | 29206cf0a4a8efcdabe50306090fe6125f6b2d0c (patch) | |
tree | 2df5e3376a0a8b026d6f819f35e2a80880c7b039 | |
parent | c2165f74d81a2ed1b1649e710b73f1c613a54185 (diff) | |
download | tinygo-29206cf0a4a8efcdabe50306090fe6125f6b2d0c.tar.gz tinygo-29206cf0a4a8efcdabe50306090fe6125f6b2d0c.zip |
targets: add CPU property everywhere
This is for consistency with Clang, which always adds a CPU flag even if
it's not specified in CFLAGS.
This commit also adds some tests to make sure the Clang target-cpu
matches the CPU property in the JSON files.
This does have an effect on the generated binaries. The effect is very
small though: on average just 0.2% increase in binary size, apparently
because Cortex-M3 and Cortex-M4 are compiled a bit differently. However,
when rebased on top of https://github.com/tinygo-org/tinygo/pull/2218
(minsize), the difference drops to -0.1% (a slight decrease on average).
-rw-r--r-- | .circleci/config.yml | 2 | ||||
-rw-r--r-- | builder/builder_test.go | 141 | ||||
-rw-r--r-- | compileopts/config.go | 13 | ||||
-rw-r--r-- | compileopts/target.go | 9 | ||||
-rw-r--r-- | targets/atmega1280.json | 3 | ||||
-rw-r--r-- | targets/atmega1284p.json | 3 | ||||
-rw-r--r-- | targets/atmega2560.json | 3 | ||||
-rw-r--r-- | targets/atmega328p.json | 3 | ||||
-rw-r--r-- | targets/attiny85.json | 1 | ||||
-rw-r--r-- | targets/cortex-m0.json | 3 | ||||
-rw-r--r-- | targets/cortex-m0plus.json | 3 | ||||
-rw-r--r-- | targets/cortex-m3.json | 3 | ||||
-rw-r--r-- | targets/cortex-m4.json | 1 | ||||
-rw-r--r-- | targets/cortex-m7.json | 1 | ||||
-rw-r--r-- | targets/esp32.json | 3 | ||||
-rw-r--r-- | targets/esp8266.json | 3 | ||||
-rw-r--r-- | targets/fe310.json | 1 | ||||
-rw-r--r-- | targets/gameboy-advance.json | 1 | ||||
-rw-r--r-- | targets/nintendoswitch.json | 3 | ||||
-rw-r--r-- | targets/wasi.json | 1 | ||||
-rw-r--r-- | targets/wasm.json | 1 |
21 files changed, 174 insertions, 28 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index de7d5dfab..dbdb6b54b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -119,7 +119,7 @@ commands: - lib/wasi-libc/sysroot - run: name: "Test TinyGo" - command: go test -v -timeout=20m -tags=llvm<<parameters.llvm>> ./cgo ./compileopts ./compiler ./interp ./transform . + command: go test -v -timeout=20m -tags=llvm<<parameters.llvm>> ./builder ./cgo ./compileopts ./compiler ./interp ./transform . no_output_timeout: 20m - run: make gen-device -j4 - run: make smoketest XTENSA=0 diff --git a/builder/builder_test.go b/builder/builder_test.go new file mode 100644 index 000000000..9ce05689b --- /dev/null +++ b/builder/builder_test.go @@ -0,0 +1,141 @@ +package builder + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/tinygo-org/tinygo/compileopts" + "github.com/tinygo-org/tinygo/goenv" + "tinygo.org/x/go-llvm" +) + +// Test whether the Clang generated "target-cpu" attribute matches the CPU +// property in TinyGo target files. +func TestClangAttributes(t *testing.T) { + var targetNames = []string{ + // Please keep this list sorted! + "atmega328p", + "atmega1280", + "atmega1284p", + "atmega2560", + "attiny85", + "cortex-m0", + "cortex-m0plus", + "cortex-m3", + //"cortex-m33", // TODO: broken in LLVM 11, fixed in https://reviews.llvm.org/D90305 + "cortex-m4", + "cortex-m7", + "esp32c3", + "fe310", + "gameboy-advance", + "k210", + "nintendoswitch", + "riscv-qemu", + "wasi", + "wasm", + } + if hasBuiltinTools { + // hasBuiltinTools is set when TinyGo is statically linked with LLVM, + // which also implies it was built with Xtensa support. + targetNames = append(targetNames, "esp32", "esp8266") + } + for _, targetName := range targetNames { + targetName := targetName + t.Run(targetName, func(t *testing.T) { + testClangAttributes(t, &compileopts.Options{Target: targetName}) + }) + } + + for _, options := range []*compileopts.Options{ + {GOOS: "linux", GOARCH: "386"}, + {GOOS: "linux", GOARCH: "amd64"}, + {GOOS: "linux", GOARCH: "arm"}, + {GOOS: "linux", GOARCH: "arm64"}, + {GOOS: "darwin", GOARCH: "amd64"}, + {GOOS: "darwin", GOARCH: "arm64"}, + } { + t.Run("GOOS="+options.GOOS+",GOARCH="+options.GOARCH, func(t *testing.T) { + testClangAttributes(t, options) + }) + } +} + +func testClangAttributes(t *testing.T, options *compileopts.Options) { + testDir := t.TempDir() + clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT")) + + ctx := llvm.NewContext() + defer ctx.Dispose() + + target, err := compileopts.LoadTarget(options) + if err != nil { + t.Fatalf("could not load target: %s", err) + } + config := compileopts.Config{ + Options: options, + Target: target, + ClangHeaders: clangHeaderPath, + } + + // Create a very simple C input file. + srcpath := filepath.Join(testDir, "test.c") + err = ioutil.WriteFile(srcpath, []byte("int add(int a, int b) { return a + b; }"), 0o666) + if err != nil { + t.Fatalf("could not write target file %s: %s", srcpath, err) + } + + // Compile this file using Clang. + outpath := filepath.Join(testDir, "test.bc") + flags := append([]string{"-c", "-emit-llvm", "-o", outpath, srcpath}, config.CFlags()...) + if config.GOOS() == "darwin" { + // Silence some warnings that happen when testing GOOS=darwin on + // something other than MacOS. + flags = append(flags, "-Wno-missing-sysroot", "-Wno-incompatible-sysroot") + } + err = runCCompiler(flags...) + if err != nil { + t.Fatalf("failed to compile %s: %s", srcpath, err) + } + + // Read the resulting LLVM bitcode. + mod, err := ctx.ParseBitcodeFile(outpath) + if err != nil { + t.Fatalf("could not parse bitcode file %s: %s", outpath, err) + } + defer mod.Dispose() + + // Check the "target-cpu" string attribute of the add function. + add := mod.NamedFunction("add") + var cpu string + cpuAttr := add.GetStringAttributeAtIndex(-1, "target-cpu") + if !cpuAttr.IsNil() { + cpu = cpuAttr.GetStringValue() + } + if cpu != config.CPU() { + t.Errorf("target has CPU %#v but Clang makes it CPU %#v", config.CPU(), cpu) + } +} + +// This TestMain is necessary because TinyGo may also be invoked to run certain +// LLVM tools in a separate process. Not capturing these invocations would lead +// to recursive tests. +func TestMain(m *testing.M) { + if len(os.Args) >= 2 { + switch os.Args[1] { + case "clang", "ld.lld", "wasm-ld": + // Invoke a specific tool. + err := RunTool(os.Args[1], os.Args[2:]...) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + os.Exit(0) + } + } + + // Run normal tests. + os.Exit(m.Run()) +} diff --git a/compileopts/config.go b/compileopts/config.go index 7da0323df..a084403c7 100644 --- a/compileopts/config.go +++ b/compileopts/config.go @@ -220,6 +220,19 @@ func (c *Config) CFlags() []string { cflags = append(cflags, "-O"+c.Options.Opt) // Set the LLVM target triple. cflags = append(cflags, "--target="+c.Triple()) + // Set the -mcpu (or similar) flag. + if c.Target.CPU != "" { + if c.GOARCH() == "amd64" || c.GOARCH() == "386" { + // x86 prefers the -march flag (-mcpu is deprecated there). + cflags = append(cflags, "-march="+c.Target.CPU) + } else if strings.HasPrefix(c.Triple(), "avr") { + // AVR MCUs use -mmcu instead of -mcpu. + cflags = append(cflags, "-mmcu="+c.Target.CPU) + } else { + // The rest just uses -mcpu. + cflags = append(cflags, "-mcpu="+c.Target.CPU) + } + } return cflags } diff --git a/compileopts/target.go b/compileopts/target.go index aaa5fadad..88beb7a0a 100644 --- a/compileopts/target.go +++ b/compileopts/target.go @@ -221,8 +221,15 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) { GDB: []string{"gdb"}, PortReset: "false", } - if goarch == "386" { + switch goarch { + case "386": spec.CPU = "pentium4" + case "amd64": + spec.CPU = "x86-64" + case "arm": + spec.CPU = "generic" + case "arm64": + spec.CPU = "generic" } if goos == "darwin" { spec.CFlags = append(spec.CFlags, "-isysroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk") diff --git a/targets/atmega1280.json b/targets/atmega1280.json index 2b0bfde7b..bf2e8c8bc 100644 --- a/targets/atmega1280.json +++ b/targets/atmega1280.json @@ -3,9 +3,6 @@ "cpu": "atmega1280", "build-tags": ["atmega1280", "atmega"], "serial": "uart", - "cflags": [ - "-mmcu=atmega1280" - ], "ldflags": [ "-mmcu=avr51", "-Wl,--defsym=_stack_size=512" diff --git a/targets/atmega1284p.json b/targets/atmega1284p.json index 3fbecd4b7..7740ccf1c 100644 --- a/targets/atmega1284p.json +++ b/targets/atmega1284p.json @@ -3,9 +3,6 @@ "cpu": "atmega1284p", "build-tags": ["atmega1284p", "atmega"], "serial": "uart", - "cflags": [ - "-mmcu=atmega1284p" - ], "ldflags": [ "-mmcu=avr51", "-Wl,--defsym=_bootloader_size=0", diff --git a/targets/atmega2560.json b/targets/atmega2560.json index 9caa088cf..d3b37418e 100644 --- a/targets/atmega2560.json +++ b/targets/atmega2560.json @@ -3,9 +3,6 @@ "cpu": "atmega2560", "build-tags": ["atmega2560", "atmega"], "serial": "uart", - "cflags": [ - "-mmcu=atmega2560" - ], "ldflags": [ "-mmcu=avr6", "-Wl,--defsym=_stack_size=512" diff --git a/targets/atmega328p.json b/targets/atmega328p.json index 24a272147..6a763b727 100644 --- a/targets/atmega328p.json +++ b/targets/atmega328p.json @@ -3,9 +3,6 @@ "cpu": "atmega328p", "build-tags": ["atmega328p", "atmega", "avr5"], "serial": "uart", - "cflags": [ - "-mmcu=atmega328p" - ], "ldflags": [ "-mmcu=avr5" ], diff --git a/targets/attiny85.json b/targets/attiny85.json index 8cb4fcc0c..f28f4f84d 100644 --- a/targets/attiny85.json +++ b/targets/attiny85.json @@ -3,7 +3,6 @@ "cpu": "attiny85", "build-tags": ["attiny85", "attiny", "avr2", "avr25"], "cflags": [ - "-mmcu=attiny85", "-D__AVR_ARCH__=25" ], "ldflags": [ diff --git a/targets/cortex-m0.json b/targets/cortex-m0.json index 221d1a44e..b1e943f05 100644 --- a/targets/cortex-m0.json +++ b/targets/cortex-m0.json @@ -1,4 +1,5 @@ { "inherits": ["cortex-m"], - "llvm-target": "armv6m-unknown-unknown-eabi" + "llvm-target": "armv6m-unknown-unknown-eabi", + "cpu": "cortex-m0" } diff --git a/targets/cortex-m0plus.json b/targets/cortex-m0plus.json index 221d1a44e..7fef099b6 100644 --- a/targets/cortex-m0plus.json +++ b/targets/cortex-m0plus.json @@ -1,4 +1,5 @@ { "inherits": ["cortex-m"], - "llvm-target": "armv6m-unknown-unknown-eabi" + "llvm-target": "armv6m-unknown-unknown-eabi", + "cpu": "cortex-m0plus" } diff --git a/targets/cortex-m3.json b/targets/cortex-m3.json index b77a7f97a..a2dc974ad 100644 --- a/targets/cortex-m3.json +++ b/targets/cortex-m3.json @@ -1,4 +1,5 @@ { "inherits": ["cortex-m"], - "llvm-target": "armv7m-unknown-unknown-eabi" + "llvm-target": "armv7m-unknown-unknown-eabi", + "cpu": "cortex-m3" } diff --git a/targets/cortex-m4.json b/targets/cortex-m4.json index 409a97d2d..dd966d71a 100644 --- a/targets/cortex-m4.json +++ b/targets/cortex-m4.json @@ -1,6 +1,7 @@ { "inherits": ["cortex-m"], "llvm-target": "armv7em-unknown-unknown-eabi", + "cpu": "cortex-m4", "cflags": [ "-mfloat-abi=soft" ] diff --git a/targets/cortex-m7.json b/targets/cortex-m7.json index efd1f302e..dbe11dfd9 100644 --- a/targets/cortex-m7.json +++ b/targets/cortex-m7.json @@ -3,7 +3,6 @@ "llvm-target": "armv7em-unknown-unknown-eabi", "cpu": "cortex-m7", "cflags": [ - "-mcpu=cortex-m7", "-mfloat-abi=soft" ] } diff --git a/targets/esp32.json b/targets/esp32.json index ded861624..9fc32b305 100644 --- a/targets/esp32.json +++ b/targets/esp32.json @@ -6,9 +6,6 @@ "serial": "uart", "linker": "xtensa-esp32-elf-ld", "default-stack-size": 2048, - "cflags": [ - "-mcpu=esp32" - ], "rtlib": "compiler-rt", "libc": "picolibc", "linkerscript": "targets/esp32.ld", diff --git a/targets/esp8266.json b/targets/esp8266.json index e1304d245..cec09fdeb 100644 --- a/targets/esp8266.json +++ b/targets/esp8266.json @@ -5,9 +5,6 @@ "scheduler": "tasks", "linker": "xtensa-esp32-elf-ld", "default-stack-size": 2048, - "cflags": [ - "-mcpu=esp8266" - ], "rtlib": "compiler-rt", "libc": "picolibc", "linkerscript": "targets/esp8266.ld", diff --git a/targets/fe310.json b/targets/fe310.json index 76f749705..c513a39f1 100644 --- a/targets/fe310.json +++ b/targets/fe310.json @@ -1,5 +1,6 @@ { "inherits": ["riscv32"], + "cpu": "sifive-e31", "features": ["+a", "+c", "+m"], "build-tags": ["fe310", "sifive"] } diff --git a/targets/gameboy-advance.json b/targets/gameboy-advance.json index 77046954a..c929ab764 100644 --- a/targets/gameboy-advance.json +++ b/targets/gameboy-advance.json @@ -8,7 +8,6 @@ "rtlib": "compiler-rt", "libc": "picolibc", "cflags": [ - "-mcpu=arm7tdmi", "-Werror", "-fshort-enums", "-fomit-frame-pointer", diff --git a/targets/nintendoswitch.json b/targets/nintendoswitch.json index 6e3c44c7f..211b2b299 100644 --- a/targets/nintendoswitch.json +++ b/targets/nintendoswitch.json @@ -1,5 +1,6 @@ { "llvm-target": "aarch64", + "cpu": "cortex-a57", "build-tags": ["nintendoswitch", "arm64"], "scheduler": "tasks", "goos": "linux", @@ -9,11 +10,9 @@ "libc": "picolibc", "gc": "conservative", "relocation-model": "pic", - "cpu": "cortex-a57", "default-stack-size": 2048, "cflags": [ "-target", "aarch64-unknown-none", - "-mcpu=cortex-a57", "-fPIE", "-Werror", "-fshort-enums", diff --git a/targets/wasi.json b/targets/wasi.json index ab10cbda0..7826c48d1 100644 --- a/targets/wasi.json +++ b/targets/wasi.json @@ -1,5 +1,6 @@ { "llvm-target": "wasm32-unknown-wasi", + "cpu": "generic", "build-tags": ["tinygo.wasm", "wasi"], "goos": "linux", "goarch": "arm", diff --git a/targets/wasm.json b/targets/wasm.json index f7606c695..bfffc0058 100644 --- a/targets/wasm.json +++ b/targets/wasm.json @@ -1,5 +1,6 @@ { "llvm-target": "wasm32-unknown-wasi", + "cpu": "generic", "build-tags": ["tinygo.wasm"], "goos": "js", "goarch": "wasm", |