diff --git a/builder/build.go b/builder/build.go index 17a007f8..8de5305f 100644 --- a/builder/build.go +++ b/builder/build.go @@ -163,6 +163,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe Triple: config.Triple(), CPU: config.CPU(), Features: config.Features(), + ABI: config.ABI(), GOOS: config.GOOS(), GOARCH: config.GOARCH(), CodeModel: config.CodeModel(), diff --git a/builder/library.go b/builder/library.go index 06b57632..23d93882 100644 --- a/builder/library.go +++ b/builder/library.go @@ -155,6 +155,9 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ args = append(args, "-mcpu="+cpu) } } + if config.ABI() != "" { + args = append(args, "-mabi="+config.ABI()) + } if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") { if strings.Split(target, "-")[2] == "linux" { args = append(args, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables") @@ -170,10 +173,10 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ args = append(args, "-mdouble=64") } if strings.HasPrefix(target, "riscv32-") { - args = append(args, "-march=rv32imac", "-mabi=ilp32", "-fforce-enable-int128") + args = append(args, "-march=rv32imac", "-fforce-enable-int128") } if strings.HasPrefix(target, "riscv64-") { - args = append(args, "-march=rv64gc", "-mabi=lp64") + args = append(args, "-march=rv64gc") } if strings.HasPrefix(target, "xtensa") { // Hack to work around an issue in the Xtensa port: diff --git a/compileopts/config.go b/compileopts/config.go index ebfc5082..37b523f7 100644 --- a/compileopts/config.go +++ b/compileopts/config.go @@ -47,6 +47,12 @@ func (c *Config) Features() string { return c.Target.Features + "," + c.Options.LLVMFeatures } +// ABI returns the -mabi= flag for this target (like -mabi=lp64). A zero-length +// string is returned if the target doesn't specify an ABI. +func (c *Config) ABI() string { + return c.Target.ABI +} + // GOOS returns the GOOS of the target. This might not always be the actual OS: // for example, bare-metal targets will usually pretend to be linux to get the // standard library to compile. @@ -230,6 +236,9 @@ func (c *Config) LibcPath(name string) (path string, precompiled bool) { if c.CPU() != "" { archname += "-" + c.CPU() } + if c.ABI() != "" { + archname += "-" + c.ABI() + } // Try to load a precompiled library. precompiledDir := filepath.Join(goenv.Get("TINYGOROOT"), "pkg", archname, name) @@ -338,6 +347,10 @@ func (c *Config) CFlags() []string { cflags = append(cflags, "-mcpu="+c.Target.CPU) } } + // Set the -mabi flag, if needed. + if c.ABI() != "" { + cflags = append(cflags, "-mabi="+c.ABI()) + } return cflags } diff --git a/compileopts/target.go b/compileopts/target.go index 1b5578ea..95e684b2 100644 --- a/compileopts/target.go +++ b/compileopts/target.go @@ -26,6 +26,7 @@ type TargetSpec struct { Inherits []string `json:"inherits"` Triple string `json:"llvm-target"` CPU string `json:"cpu"` + ABI string `json:"target-abi"` // rougly equivalent to -mabi= flag Features string `json:"features"` GOOS string `json:"goos"` GOARCH string `json:"goarch"` diff --git a/compiler/compiler.go b/compiler/compiler.go index fc47c29c..8b6e8661 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -41,6 +41,7 @@ type Config struct { Triple string CPU string Features string + ABI string GOOS string GOARCH string CodeModel string @@ -321,6 +322,18 @@ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package, c.dibuilder.Destroy() } + // Add the "target-abi" flag, which is necessary on RISC-V otherwise it will + // pick one that doesn't match the -mabi Clang flag. + if c.ABI != "" { + c.mod.AddNamedMetadataOperand("llvm.module.flags", + c.ctx.MDNode([]llvm.Metadata{ + llvm.ConstInt(c.ctx.Int32Type(), 1, false).ConstantAsMetadata(), // Error on mismatch + c.ctx.MDString("target-abi"), + c.ctx.MDString(c.ABI), + }), + ) + } + return c.mod, c.diagnostics } diff --git a/compiler/compiler_test.go b/compiler/compiler_test.go index 2ed26921..a5cd9c6b 100644 --- a/compiler/compiler_test.go +++ b/compiler/compiler_test.go @@ -73,6 +73,7 @@ func TestCompiler(t *testing.T) { compilerConfig := &Config{ Triple: config.Triple(), Features: config.Features(), + ABI: config.ABI(), GOOS: config.GOOS(), GOARCH: config.GOARCH(), CodeModel: config.CodeModel(), diff --git a/targets/riscv32.json b/targets/riscv32.json index c3c8dff5..a2878089 100644 --- a/targets/riscv32.json +++ b/targets/riscv32.json @@ -1,12 +1,12 @@ { "inherits": ["riscv"], "llvm-target": "riscv32-unknown-none", + "target-abi": "ilp32", "build-tags": ["tinygo.riscv32"], "scheduler": "tasks", "default-stack-size": 2048, "cflags": [ - "-march=rv32imac", - "-mabi=ilp32" + "-march=rv32imac" ], "ldflags": [ "-melf32lriscv" diff --git a/targets/riscv64.json b/targets/riscv64.json index c2378e97..fc45c91c 100644 --- a/targets/riscv64.json +++ b/targets/riscv64.json @@ -1,10 +1,10 @@ { "inherits": ["riscv"], "llvm-target": "riscv64-unknown-none", + "target-abi": "lp64", "build-tags": ["tinygo.riscv64"], "cflags": [ - "-march=rv64gc", - "-mabi=lp64" + "-march=rv64gc" ], "ldflags": [ "-melf64lriscv"