compiler: add "target-cpu" and "target-features" attributes
This matches Clang, and with that, it adds support for inlining between Go and C because LLVM only allows inlining if the "target-cpu" and "target-features" string attributes match. For example, take a look at the following code: // int add(int a, int b) { // return a + b; // } import "C" func main() { println(C.add(3, 5)) } The 'add' function is not inlined into the main function before this commit, but after it, it can be inlined and trivially be optimized to `println(8)`.
Этот коммит содержится в:
родитель
78fec3719f
коммит
cf640290a3
6 изменённых файлов: 23 добавлений и 7 удалений
|
@ -23,7 +23,7 @@ import (
|
||||||
// Version of the compiler pacakge. Must be incremented each time the compiler
|
// Version of the compiler pacakge. Must be incremented each time the compiler
|
||||||
// package changes in a way that affects the generated LLVM module.
|
// package changes in a way that affects the generated LLVM module.
|
||||||
// This version is independent of the TinyGo version number.
|
// This version is independent of the TinyGo version number.
|
||||||
const Version = 24 // last change: add layout param to runtime.alloc calls
|
const Version = 25 // last change: add "target-cpu" and "target-features" attributes
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
llvm.InitializeAllTargets()
|
llvm.InitializeAllTargets()
|
||||||
|
|
|
@ -346,6 +346,12 @@ func (c *compilerContext) addStandardDeclaredAttributes(llvmFn llvm.Value) {
|
||||||
attr := c.ctx.CreateEnumAttribute(kind, 0)
|
attr := c.ctx.CreateEnumAttribute(kind, 0)
|
||||||
llvmFn.AddFunctionAttr(attr)
|
llvmFn.AddFunctionAttr(attr)
|
||||||
}
|
}
|
||||||
|
if c.CPU != "" {
|
||||||
|
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("target-cpu", c.CPU))
|
||||||
|
}
|
||||||
|
if c.Features != "" {
|
||||||
|
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("target-features", c.Features))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// addStandardDefinedAttributes adds the set of attributes that are added to
|
// addStandardDefinedAttributes adds the set of attributes that are added to
|
||||||
|
|
|
@ -3,7 +3,6 @@ package transform_test
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
|
||||||
"github.com/tinygo-org/tinygo/transform"
|
"github.com/tinygo-org/tinygo/transform"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
@ -11,7 +10,7 @@ import (
|
||||||
func TestInterfaceLowering(t *testing.T) {
|
func TestInterfaceLowering(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
testTransform(t, "testdata/interface", func(mod llvm.Module) {
|
testTransform(t, "testdata/interface", func(mod llvm.Module) {
|
||||||
err := transform.LowerInterfaces(mod, &compileopts.Config{Options: &compileopts.Options{Opt: "2"}})
|
err := transform.LowerInterfaces(mod, defaultTestConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,18 @@ import (
|
||||||
// attributes to a function. For example, it adds optsize when requested from
|
// attributes to a function. For example, it adds optsize when requested from
|
||||||
// the -opt= compiler flag.
|
// the -opt= compiler flag.
|
||||||
func AddStandardAttributes(fn llvm.Value, config *compileopts.Config) {
|
func AddStandardAttributes(fn llvm.Value, config *compileopts.Config) {
|
||||||
|
ctx := fn.Type().Context()
|
||||||
_, sizeLevel, _ := config.OptLevels()
|
_, sizeLevel, _ := config.OptLevels()
|
||||||
if sizeLevel >= 1 {
|
if sizeLevel >= 1 {
|
||||||
fn.AddFunctionAttr(fn.Type().Context().CreateEnumAttribute(llvm.AttributeKindID("optsize"), 0))
|
fn.AddFunctionAttr(ctx.CreateEnumAttribute(llvm.AttributeKindID("optsize"), 0))
|
||||||
}
|
}
|
||||||
if sizeLevel >= 2 {
|
if sizeLevel >= 2 {
|
||||||
fn.AddFunctionAttr(fn.Type().Context().CreateEnumAttribute(llvm.AttributeKindID("minsize"), 0))
|
fn.AddFunctionAttr(ctx.CreateEnumAttribute(llvm.AttributeKindID("minsize"), 0))
|
||||||
|
}
|
||||||
|
if config.CPU() != "" {
|
||||||
|
fn.AddFunctionAttr(ctx.CreateStringAttribute("target-cpu", config.CPU()))
|
||||||
|
}
|
||||||
|
if config.Features() != "" {
|
||||||
|
fn.AddFunctionAttr(ctx.CreateStringAttribute("target-features", config.Features()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,11 @@ import (
|
||||||
|
|
||||||
var update = flag.Bool("update", false, "update transform package tests")
|
var update = flag.Bool("update", false, "update transform package tests")
|
||||||
|
|
||||||
|
var defaultTestConfig = &compileopts.Config{
|
||||||
|
Target: &compileopts.TargetSpec{},
|
||||||
|
Options: &compileopts.Options{Opt: "2"},
|
||||||
|
}
|
||||||
|
|
||||||
// testTransform runs a transformation pass on an input file (pathPrefix+".ll")
|
// testTransform runs a transformation pass on an input file (pathPrefix+".ll")
|
||||||
// and checks whether it matches the expected output (pathPrefix+".out.ll"). The
|
// and checks whether it matches the expected output (pathPrefix+".out.ll"). The
|
||||||
// output is compared with a fuzzy match that ignores some irrelevant lines such
|
// output is compared with a fuzzy match that ignores some irrelevant lines such
|
||||||
|
|
|
@ -3,7 +3,6 @@ package transform_test
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
|
||||||
"github.com/tinygo-org/tinygo/transform"
|
"github.com/tinygo-org/tinygo/transform"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
@ -12,7 +11,7 @@ func TestWasmABI(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
testTransform(t, "testdata/wasm-abi", func(mod llvm.Module) {
|
testTransform(t, "testdata/wasm-abi", func(mod llvm.Module) {
|
||||||
// Run ABI change pass.
|
// Run ABI change pass.
|
||||||
err := transform.ExternalInt64AsPtr(mod, &compileopts.Config{Options: &compileopts.Options{Opt: "2"}})
|
err := transform.ExternalInt64AsPtr(mod, defaultTestConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to change wasm ABI: %v", err)
|
t.Errorf("failed to change wasm ABI: %v", err)
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче