builder: remove non-ThinLTO build mode

All targets now support ThinLTO so let's remove the old unused code.
Этот коммит содержится в:
Ayke van Laethem 2023-02-26 14:52:56 +01:00 коммит произвёл Ron Evans
родитель 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 предоставленный
Просмотреть файл

@ -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 предоставленный
Просмотреть файл

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