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).
Этот коммит содержится в:
Ayke van Laethem 2021-11-01 19:11:04 +01:00 коммит произвёл Ron Evans
родитель c2165f74d8
коммит 29206cf0a4
21 изменённых файлов: 174 добавлений и 28 удалений

Просмотреть файл

@ -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

141
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())
}

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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")

Просмотреть файл

@ -3,9 +3,6 @@
"cpu": "atmega1280",
"build-tags": ["atmega1280", "atmega"],
"serial": "uart",
"cflags": [
"-mmcu=atmega1280"
],
"ldflags": [
"-mmcu=avr51",
"-Wl,--defsym=_stack_size=512"

Просмотреть файл

@ -3,9 +3,6 @@
"cpu": "atmega1284p",
"build-tags": ["atmega1284p", "atmega"],
"serial": "uart",
"cflags": [
"-mmcu=atmega1284p"
],
"ldflags": [
"-mmcu=avr51",
"-Wl,--defsym=_bootloader_size=0",

Просмотреть файл

@ -3,9 +3,6 @@
"cpu": "atmega2560",
"build-tags": ["atmega2560", "atmega"],
"serial": "uart",
"cflags": [
"-mmcu=atmega2560"
],
"ldflags": [
"-mmcu=avr6",
"-Wl,--defsym=_stack_size=512"

Просмотреть файл

@ -3,9 +3,6 @@
"cpu": "atmega328p",
"build-tags": ["atmega328p", "atmega", "avr5"],
"serial": "uart",
"cflags": [
"-mmcu=atmega328p"
],
"ldflags": [
"-mmcu=avr5"
],

Просмотреть файл

@ -3,7 +3,6 @@
"cpu": "attiny85",
"build-tags": ["attiny85", "attiny", "avr2", "avr25"],
"cflags": [
"-mmcu=attiny85",
"-D__AVR_ARCH__=25"
],
"ldflags": [

Просмотреть файл

@ -1,4 +1,5 @@
{
"inherits": ["cortex-m"],
"llvm-target": "armv6m-unknown-unknown-eabi"
"llvm-target": "armv6m-unknown-unknown-eabi",
"cpu": "cortex-m0"
}

Просмотреть файл

@ -1,4 +1,5 @@
{
"inherits": ["cortex-m"],
"llvm-target": "armv6m-unknown-unknown-eabi"
"llvm-target": "armv6m-unknown-unknown-eabi",
"cpu": "cortex-m0plus"
}

Просмотреть файл

@ -1,4 +1,5 @@
{
"inherits": ["cortex-m"],
"llvm-target": "armv7m-unknown-unknown-eabi"
"llvm-target": "armv7m-unknown-unknown-eabi",
"cpu": "cortex-m3"
}

Просмотреть файл

@ -1,6 +1,7 @@
{
"inherits": ["cortex-m"],
"llvm-target": "armv7em-unknown-unknown-eabi",
"cpu": "cortex-m4",
"cflags": [
"-mfloat-abi=soft"
]

Просмотреть файл

@ -3,7 +3,6 @@
"llvm-target": "armv7em-unknown-unknown-eabi",
"cpu": "cortex-m7",
"cflags": [
"-mcpu=cortex-m7",
"-mfloat-abi=soft"
]
}

Просмотреть файл

@ -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",

Просмотреть файл

@ -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",

Просмотреть файл

@ -1,5 +1,6 @@
{
"inherits": ["riscv32"],
"cpu": "sifive-e31",
"features": ["+a", "+c", "+m"],
"build-tags": ["fe310", "sifive"]
}

Просмотреть файл

@ -8,7 +8,6 @@
"rtlib": "compiler-rt",
"libc": "picolibc",
"cflags": [
"-mcpu=arm7tdmi",
"-Werror",
"-fshort-enums",
"-fomit-frame-pointer",

Просмотреть файл

@ -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",

Просмотреть файл

@ -1,5 +1,6 @@
{
"llvm-target": "wasm32-unknown-wasi",
"cpu": "generic",
"build-tags": ["tinygo.wasm", "wasi"],
"goos": "linux",
"goarch": "arm",

Просмотреть файл

@ -1,5 +1,6 @@
{
"llvm-target": "wasm32-unknown-wasi",
"cpu": "generic",
"build-tags": ["tinygo.wasm"],
"goos": "js",
"goarch": "wasm",