builder: remove non-ThinLTO build mode
All targets now support ThinLTO so let's remove the old unused code.
Этот коммит содержится в:
родитель
201592d93b
коммит
488174767b
7 изменённых файлов: 40 добавлений и 127 удалений
|
@ -594,12 +594,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||||
defer llvmBuf.Dispose()
|
defer llvmBuf.Dispose()
|
||||||
return result, os.WriteFile(outpath, llvmBuf.Bytes(), 0666)
|
return result, os.WriteFile(outpath, llvmBuf.Bytes(), 0666)
|
||||||
case ".bc":
|
case ".bc":
|
||||||
var buf llvm.MemoryBuffer
|
buf := llvm.WriteThinLTOBitcodeToMemoryBuffer(mod)
|
||||||
if config.UseThinLTO() {
|
|
||||||
buf = llvm.WriteThinLTOBitcodeToMemoryBuffer(mod)
|
|
||||||
} else {
|
|
||||||
buf = llvm.WriteBitcodeToMemoryBuffer(mod)
|
|
||||||
}
|
|
||||||
defer buf.Dispose()
|
defer buf.Dispose()
|
||||||
return result, os.WriteFile(outpath, buf.Bytes(), 0666)
|
return result, os.WriteFile(outpath, buf.Bytes(), 0666)
|
||||||
case ".ll":
|
case ".ll":
|
||||||
|
@ -621,16 +616,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||||
dependencies: []*compileJob{programJob},
|
dependencies: []*compileJob{programJob},
|
||||||
result: objfile,
|
result: objfile,
|
||||||
run: func(*compileJob) error {
|
run: func(*compileJob) error {
|
||||||
var llvmBuf llvm.MemoryBuffer
|
llvmBuf := llvm.WriteThinLTOBitcodeToMemoryBuffer(mod)
|
||||||
if config.UseThinLTO() {
|
|
||||||
llvmBuf = llvm.WriteThinLTOBitcodeToMemoryBuffer(mod)
|
|
||||||
} else {
|
|
||||||
var err error
|
|
||||||
llvmBuf, err = machine.EmitToMemoryBuffer(mod, llvm.ObjectFile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer llvmBuf.Dispose()
|
defer llvmBuf.Dispose()
|
||||||
return os.WriteFile(objfile, llvmBuf.Bytes(), 0666)
|
return os.WriteFile(objfile, llvmBuf.Bytes(), 0666)
|
||||||
},
|
},
|
||||||
|
@ -664,7 +650,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||||
job := &compileJob{
|
job := &compileJob{
|
||||||
description: "compile extra file " + path,
|
description: "compile extra file " + path,
|
||||||
run: func(job *compileJob) error {
|
run: func(job *compileJob) error {
|
||||||
result, err := compileAndCacheCFile(abspath, tmpdir, config.CFlags(), config.UseThinLTO(), config.Options.PrintCommands)
|
result, err := compileAndCacheCFile(abspath, tmpdir, config.CFlags(), config.Options.PrintCommands)
|
||||||
job.result = result
|
job.result = result
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
|
@ -682,7 +668,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||||
job := &compileJob{
|
job := &compileJob{
|
||||||
description: "compile CGo file " + abspath,
|
description: "compile CGo file " + abspath,
|
||||||
run: func(job *compileJob) error {
|
run: func(job *compileJob) error {
|
||||||
result, err := compileAndCacheCFile(abspath, tmpdir, pkg.CFlags, config.UseThinLTO(), config.Options.PrintCommands)
|
result, err := compileAndCacheCFile(abspath, tmpdir, pkg.CFlags, config.Options.PrintCommands)
|
||||||
job.result = result
|
job.result = result
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
|
@ -741,36 +727,34 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||||
}
|
}
|
||||||
ldflags = append(ldflags, dependency.result)
|
ldflags = append(ldflags, dependency.result)
|
||||||
}
|
}
|
||||||
if config.UseThinLTO() {
|
ldflags = append(ldflags, "-mllvm", "-mcpu="+config.CPU())
|
||||||
ldflags = append(ldflags, "-mllvm", "-mcpu="+config.CPU())
|
if config.GOOS() == "windows" {
|
||||||
if config.GOOS() == "windows" {
|
// Options for the MinGW wrapper for the lld COFF linker.
|
||||||
// Options for the MinGW wrapper for the lld COFF linker.
|
ldflags = append(ldflags,
|
||||||
ldflags = append(ldflags,
|
"-Xlink=/opt:lldlto="+strconv.Itoa(optLevel),
|
||||||
"-Xlink=/opt:lldlto="+strconv.Itoa(optLevel),
|
"--thinlto-cache-dir="+filepath.Join(cacheDir, "thinlto"))
|
||||||
"--thinlto-cache-dir="+filepath.Join(cacheDir, "thinlto"))
|
} else if config.GOOS() == "darwin" {
|
||||||
} else if config.GOOS() == "darwin" {
|
// Options for the ld64-compatible lld linker.
|
||||||
// Options for the ld64-compatible lld linker.
|
ldflags = append(ldflags,
|
||||||
ldflags = append(ldflags,
|
"--lto-O"+strconv.Itoa(optLevel),
|
||||||
"--lto-O"+strconv.Itoa(optLevel),
|
"-cache_path_lto", filepath.Join(cacheDir, "thinlto"))
|
||||||
"-cache_path_lto", filepath.Join(cacheDir, "thinlto"))
|
} else {
|
||||||
} else {
|
// Options for the ELF linker.
|
||||||
// Options for the ELF linker.
|
ldflags = append(ldflags,
|
||||||
ldflags = append(ldflags,
|
"--lto-O"+strconv.Itoa(optLevel),
|
||||||
"--lto-O"+strconv.Itoa(optLevel),
|
"--thinlto-cache-dir="+filepath.Join(cacheDir, "thinlto"),
|
||||||
"--thinlto-cache-dir="+filepath.Join(cacheDir, "thinlto"),
|
)
|
||||||
)
|
}
|
||||||
}
|
if config.CodeModel() != "default" {
|
||||||
if config.CodeModel() != "default" {
|
ldflags = append(ldflags,
|
||||||
ldflags = append(ldflags,
|
"-mllvm", "-code-model="+config.CodeModel())
|
||||||
"-mllvm", "-code-model="+config.CodeModel())
|
}
|
||||||
}
|
if sizeLevel >= 2 {
|
||||||
if sizeLevel >= 2 {
|
// Workaround with roughly the same effect as
|
||||||
// Workaround with roughly the same effect as
|
// https://reviews.llvm.org/D119342.
|
||||||
// https://reviews.llvm.org/D119342.
|
// Can hopefully be removed in LLVM 15.
|
||||||
// Can hopefully be removed in LLVM 15.
|
ldflags = append(ldflags,
|
||||||
ldflags = append(ldflags,
|
"-mllvm", "--rotation-max-header-size=0")
|
||||||
"-mllvm", "--rotation-max-header-size=0")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if config.Options.PrintCommands != nil {
|
if config.Options.PrintCommands != nil {
|
||||||
config.Options.PrintCommands(config.Target.Linker, ldflags...)
|
config.Options.PrintCommands(config.Target.Linker, ldflags...)
|
||||||
|
@ -1069,10 +1053,6 @@ func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.GOOS() != "darwin" && !config.UseThinLTO() {
|
|
||||||
transform.ApplyFunctionSections(mod) // -ffunction-sections
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert values from -ldflags="-X ..." into the IR.
|
// Insert values from -ldflags="-X ..." into the IR.
|
||||||
err = setGlobalValues(mod, config.Options.GlobalValues)
|
err = setGlobalValues(mod, config.Options.GlobalValues)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -56,7 +56,7 @@ import (
|
||||||
// depfile but without invalidating its name. For this reason, the depfile is
|
// depfile but without invalidating its name. For this reason, the depfile is
|
||||||
// written on each new compilation (even when it seems unnecessary). However, it
|
// written on each new compilation (even when it seems unnecessary). However, it
|
||||||
// could in rare cases lead to a stale file fetched from the cache.
|
// could in rare cases lead to a stale file fetched from the cache.
|
||||||
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool, printCommands func(string, ...string)) (string, error) {
|
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands func(string, ...string)) (string, error) {
|
||||||
// Hash input file.
|
// Hash input file.
|
||||||
fileHash, err := hashFile(abspath)
|
fileHash, err := hashFile(abspath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -67,11 +67,6 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
|
||||||
unlock := lock(filepath.Join(goenv.Get("GOCACHE"), fileHash+".c.lock"))
|
unlock := lock(filepath.Join(goenv.Get("GOCACHE"), fileHash+".c.lock"))
|
||||||
defer unlock()
|
defer unlock()
|
||||||
|
|
||||||
ext := ".o"
|
|
||||||
if thinlto {
|
|
||||||
ext = ".bc"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create cache key for the dependencies file.
|
// Create cache key for the dependencies file.
|
||||||
buf, err := json.Marshal(struct {
|
buf, err := json.Marshal(struct {
|
||||||
Path string
|
Path string
|
||||||
|
@ -104,7 +99,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtain hashes of all the files listed as a dependency.
|
// Obtain hashes of all the files listed as a dependency.
|
||||||
outpath, err := makeCFileCachePath(dependencies, depfileNameHash, ext)
|
outpath, err := makeCFileCachePath(dependencies, depfileNameHash)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if _, err := os.Stat(outpath); err == nil {
|
if _, err := os.Stat(outpath); err == nil {
|
||||||
return outpath, nil
|
return outpath, nil
|
||||||
|
@ -117,7 +112,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
objTmpFile, err := os.CreateTemp(goenv.Get("GOCACHE"), "tmp-*"+ext)
|
objTmpFile, err := os.CreateTemp(goenv.Get("GOCACHE"), "tmp-*.bc")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -127,11 +122,8 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
depTmpFile.Close()
|
depTmpFile.Close()
|
||||||
flags := append([]string{}, cflags...) // copy cflags
|
flags := append([]string{}, cflags...) // copy cflags
|
||||||
flags = append(flags, "-MD", "-MV", "-MTdeps", "-MF", depTmpFile.Name()) // autogenerate dependencies
|
flags = append(flags, "-MD", "-MV", "-MTdeps", "-MF", depTmpFile.Name(), "-flto=thin") // autogenerate dependencies
|
||||||
if thinlto {
|
|
||||||
flags = append(flags, "-flto=thin")
|
|
||||||
}
|
|
||||||
flags = append(flags, "-c", "-o", objTmpFile.Name(), abspath)
|
flags = append(flags, "-c", "-o", objTmpFile.Name(), abspath)
|
||||||
if strings.ToLower(filepath.Ext(abspath)) == ".s" {
|
if strings.ToLower(filepath.Ext(abspath)) == ".s" {
|
||||||
// If this is an assembly file (.s or .S, lowercase or uppercase), then
|
// If this is an assembly file (.s or .S, lowercase or uppercase), then
|
||||||
|
@ -189,7 +181,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move temporary object file to final location.
|
// Move temporary object file to final location.
|
||||||
outpath, err := makeCFileCachePath(dependencySlice, depfileNameHash, ext)
|
outpath, err := makeCFileCachePath(dependencySlice, depfileNameHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -204,7 +196,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
|
||||||
// Create a cache path (a path in GOCACHE) to store the output of a compiler
|
// Create a cache path (a path in GOCACHE) to store the output of a compiler
|
||||||
// job. This path is based on the dep file name (which is a hash of metadata
|
// job. This path is based on the dep file name (which is a hash of metadata
|
||||||
// including compiler flags) and the hash of all input files in the paths slice.
|
// including compiler flags) and the hash of all input files in the paths slice.
|
||||||
func makeCFileCachePath(paths []string, depfileNameHash, ext string) (string, error) {
|
func makeCFileCachePath(paths []string, depfileNameHash string) (string, error) {
|
||||||
// Hash all input files.
|
// Hash all input files.
|
||||||
fileHashes := make(map[string]string, len(paths))
|
fileHashes := make(map[string]string, len(paths))
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
|
@ -229,7 +221,7 @@ func makeCFileCachePath(paths []string, depfileNameHash, ext string) (string, er
|
||||||
outFileNameBuf := sha512.Sum512_224(buf)
|
outFileNameBuf := sha512.Sum512_224(buf)
|
||||||
cacheKey := hex.EncodeToString(outFileNameBuf[:])
|
cacheKey := hex.EncodeToString(outFileNameBuf[:])
|
||||||
|
|
||||||
outpath := filepath.Join(goenv.Get("GOCACHE"), "obj-"+cacheKey+ext)
|
outpath := filepath.Join(goenv.Get("GOCACHE"), "obj-"+cacheKey+".bc")
|
||||||
return outpath, nil
|
return outpath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,14 +191,6 @@ func (c *Config) StackSize() uint64 {
|
||||||
return c.Target.DefaultStackSize
|
return c.Target.DefaultStackSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseThinLTO returns whether ThinLTO should be used for the given target.
|
|
||||||
func (c *Config) UseThinLTO() bool {
|
|
||||||
// All architectures support ThinLTO now. However, this code is kept for the
|
|
||||||
// time being in case there are regressions. The non-ThinLTO code support
|
|
||||||
// should be removed when it is proven to work reliably.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// RP2040BootPatch returns whether the RP2040 boot patch should be applied that
|
// RP2040BootPatch returns whether the RP2040 boot patch should be applied that
|
||||||
// calculates and patches in the checksum for the 2nd stage bootloader.
|
// calculates and patches in the checksum for the 2nd stage bootloader.
|
||||||
func (c *Config) RP2040BootPatch() bool {
|
func (c *Config) RP2040BootPatch() bool {
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
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() && llvmFn.Section() == "" {
|
|
||||||
name := llvmFn.Name()
|
|
||||||
llvmFn.SetSection(".text." + name)
|
|
||||||
}
|
|
||||||
llvmFn = llvm.NextFunction(llvmFn)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
package transform_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/transform"
|
|
||||||
"tinygo.org/x/go-llvm"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestApplyFunctionSections(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
testTransform(t, "testdata/globals-function-sections", func(mod llvm.Module) {
|
|
||||||
transform.ApplyFunctionSections(mod)
|
|
||||||
})
|
|
||||||
}
|
|
8
transform/testdata/globals-function-sections.ll
предоставленный
8
transform/testdata/globals-function-sections.ll
предоставленный
|
@ -1,8 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
8
transform/testdata/globals-function-sections.out.ll
предоставленный
8
transform/testdata/globals-function-sections.out.ll
предоставленный
|
@ -1,8 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче