aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2021-11-01 19:11:04 +0100
committerRon Evans <[email protected]>2021-11-03 23:03:44 +0100
commit29206cf0a4a8efcdabe50306090fe6125f6b2d0c (patch)
tree2df5e3376a0a8b026d6f819f35e2a80880c7b039
parentc2165f74d81a2ed1b1649e710b73f1c613a54185 (diff)
downloadtinygo-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.yml2
-rw-r--r--builder/builder_test.go141
-rw-r--r--compileopts/config.go13
-rw-r--r--compileopts/target.go9
-rw-r--r--targets/atmega1280.json3
-rw-r--r--targets/atmega1284p.json3
-rw-r--r--targets/atmega2560.json3
-rw-r--r--targets/atmega328p.json3
-rw-r--r--targets/attiny85.json1
-rw-r--r--targets/cortex-m0.json3
-rw-r--r--targets/cortex-m0plus.json3
-rw-r--r--targets/cortex-m3.json3
-rw-r--r--targets/cortex-m4.json1
-rw-r--r--targets/cortex-m7.json1
-rw-r--r--targets/esp32.json3
-rw-r--r--targets/esp8266.json3
-rw-r--r--targets/fe310.json1
-rw-r--r--targets/gameboy-advance.json1
-rw-r--r--targets/nintendoswitch.json3
-rw-r--r--targets/wasi.json1
-rw-r--r--targets/wasm.json1
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",