diff --git a/builder/build.go b/builder/build.go index 1bc06af4..c1d82370 100644 --- a/builder/build.go +++ b/builder/build.go @@ -53,7 +53,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri } if config.GOOS() != "darwin" { - c.ApplyFunctionSections() // -ffunction-sections + transform.ApplyFunctionSections(c.Module()) // -ffunction-sections } // Browsers cannot handle external functions that have type i64 because it diff --git a/compiler/compiler.go b/compiler/compiler.go index 0e459be3..8556f839 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -2585,19 +2585,6 @@ func (c *Compiler) Verify() error { return llvm.VerifyModule(c.mod, llvm.PrintMessageAction) } -func (c *Compiler) ApplyFunctionSections() { - // Put every function in a separate section. This makes it possible for the - // linker to remove dead code (-ffunction-sections). - llvmFn := c.mod.FirstFunction() - for !llvmFn.IsNil() { - if !llvmFn.IsDeclaration() { - name := llvmFn.Name() - llvmFn.SetSection(".text." + name) - } - llvmFn = llvm.NextFunction(llvmFn) - } -} - // Turn all global constants into global variables. This works around a // limitation on Harvard architectures (e.g. AVR), where constant and // non-constant pointers point to a different address space. diff --git a/transform/globals.go b/transform/globals.go new file mode 100644 index 00000000..c142fed8 --- /dev/null +++ b/transform/globals.go @@ -0,0 +1,20 @@ +package transform + +import "tinygo.org/x/go-llvm" + +// This file implements small transformations on globals (functions and global +// variables) for specific ABIs/architectures. + +// ApplyFunctionSections puts every function in a separate section. This makes +// it possible for the linker to remove dead code. It is the equivalent of +// passing -ffunction-sections to a C compiler. +func ApplyFunctionSections(mod llvm.Module) { + llvmFn := mod.FirstFunction() + for !llvmFn.IsNil() { + if !llvmFn.IsDeclaration() { + name := llvmFn.Name() + llvmFn.SetSection(".text." + name) + } + llvmFn = llvm.NextFunction(llvmFn) + } +} diff --git a/transform/globals_test.go b/transform/globals_test.go new file mode 100644 index 00000000..0dcb0608 --- /dev/null +++ b/transform/globals_test.go @@ -0,0 +1,14 @@ +package transform + +import ( + "testing" + + "tinygo.org/x/go-llvm" +) + +func TestApplyFunctionSections(t *testing.T) { + t.Parallel() + testTransform(t, "testdata/globals-function-sections", func(mod llvm.Module) { + ApplyFunctionSections(mod) + }) +} diff --git a/transform/testdata/globals-function-sections.ll b/transform/testdata/globals-function-sections.ll new file mode 100644 index 00000000..505ba5aa --- /dev/null +++ b/transform/testdata/globals-function-sections.ll @@ -0,0 +1,8 @@ +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "armv7em-none-eabi" + +declare void @foo() + +define void @bar() { + ret void +} diff --git a/transform/testdata/globals-function-sections.out.ll b/transform/testdata/globals-function-sections.out.ll new file mode 100644 index 00000000..e3d03ed0 --- /dev/null +++ b/transform/testdata/globals-function-sections.out.ll @@ -0,0 +1,8 @@ +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "armv7em-none-eabi" + +declare void @foo() + +define void @bar() section ".text.bar" { + ret void +}