mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-11 14:33:41 +00:00
builder: refactor creation of runtime.initAll
Create it in a separate LLVM module that is then linked. This refactor is useful for the -lto=thin build mode. I checked the binary size difference and while the machine code of most binaries did change, there was no change in binary size (except for one smoke test with -opt=1, which doesn't really count).
This commit is contained in:
+44
-18
@@ -511,24 +511,11 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
|
|
||||||
// Create runtime.initAll function that calls the runtime
|
// Create runtime.initAll function that calls the runtime
|
||||||
// initializer of each package.
|
// initializer of each package.
|
||||||
llvmInitFn := mod.NamedFunction("runtime.initAll")
|
initAllModule := createInitAll(ctx, config, compilerConfig, lprogram.Sorted())
|
||||||
llvmInitFn.SetLinkage(llvm.InternalLinkage)
|
err := llvm.LinkModules(mod, initAllModule)
|
||||||
llvmInitFn.SetUnnamedAddr(true)
|
if err != nil {
|
||||||
transform.AddStandardAttributes(llvmInitFn, config)
|
return fmt.Errorf("failed to link module: %w", err)
|
||||||
llvmInitFn.Param(0).SetName("context")
|
|
||||||
block := mod.Context().AddBasicBlock(llvmInitFn, "entry")
|
|
||||||
irbuilder := mod.Context().NewBuilder()
|
|
||||||
defer irbuilder.Dispose()
|
|
||||||
irbuilder.SetInsertPointAtEnd(block)
|
|
||||||
i8ptrType := llvm.PointerType(mod.Context().Int8Type(), 0)
|
|
||||||
for _, pkg := range lprogram.Sorted() {
|
|
||||||
pkgInit := mod.NamedFunction(pkg.Pkg.Path() + ".init")
|
|
||||||
if pkgInit.IsNil() {
|
|
||||||
panic("init not found for " + pkg.Pkg.Path())
|
|
||||||
}
|
|
||||||
irbuilder.CreateCall(pkgInit.GlobalValueType(), pkgInit, []llvm.Value{llvm.Undef(i8ptrType)}, "")
|
|
||||||
}
|
}
|
||||||
irbuilder.CreateRetVoid()
|
|
||||||
|
|
||||||
// After linking, functions should (as far as possible) be set to
|
// After linking, functions should (as far as possible) be set to
|
||||||
// private linkage or internal linkage. The compiler package marks
|
// private linkage or internal linkage. The compiler package marks
|
||||||
@@ -561,7 +548,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
|
|
||||||
// Run all optimization passes, which are much more effective now
|
// Run all optimization passes, which are much more effective now
|
||||||
// that the optimizer can see the whole program at once.
|
// that the optimizer can see the whole program at once.
|
||||||
err := optimizeProgram(mod, config)
|
err = optimizeProgram(mod, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -1032,6 +1019,45 @@ func createEmbedObjectFile(data, hexSum, sourceFile, sourceDir, tmpdir string, c
|
|||||||
return outfile.Name(), outfile.Close()
|
return outfile.Name(), outfile.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a module with the runtime.initAll function that calls all package
|
||||||
|
// initializers in initialization order.
|
||||||
|
func createInitAll(ctx llvm.Context, config *compileopts.Config, compilerConfig *compiler.Config, pkgs []*loader.Package) llvm.Module {
|
||||||
|
// Create LLVM module.
|
||||||
|
mod := ctx.NewModule("runtime-initAll")
|
||||||
|
|
||||||
|
// Add datalayout string.
|
||||||
|
machine, err := compiler.NewTargetMachine(compilerConfig)
|
||||||
|
if err != nil {
|
||||||
|
panic(err) // extremely unlikely to fail here (NewTargetMachine is called many times before)
|
||||||
|
}
|
||||||
|
defer machine.Dispose()
|
||||||
|
targetData := machine.CreateTargetData()
|
||||||
|
defer targetData.Dispose()
|
||||||
|
mod.SetTarget(config.Triple())
|
||||||
|
mod.SetDataLayout(targetData.String())
|
||||||
|
|
||||||
|
// Create empty runtime.initAll function.
|
||||||
|
i8ptrType := llvm.PointerType(mod.Context().Int8Type(), 0)
|
||||||
|
fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{i8ptrType}, false)
|
||||||
|
fn := llvm.AddFunction(mod, "runtime.initAll", fnType)
|
||||||
|
fn.SetUnnamedAddr(true)
|
||||||
|
transform.AddStandardAttributes(fn, config)
|
||||||
|
|
||||||
|
// Add calls to package initializers.
|
||||||
|
fn.Param(0).SetName("context")
|
||||||
|
block := mod.Context().AddBasicBlock(fn, "entry")
|
||||||
|
irbuilder := mod.Context().NewBuilder()
|
||||||
|
defer irbuilder.Dispose()
|
||||||
|
irbuilder.SetInsertPointAtEnd(block)
|
||||||
|
for _, pkg := range pkgs {
|
||||||
|
pkgInit := llvm.AddFunction(mod, pkg.Pkg.Path()+".init", fnType)
|
||||||
|
irbuilder.CreateCall(fnType, pkgInit, []llvm.Value{llvm.Undef(i8ptrType)}, "")
|
||||||
|
}
|
||||||
|
irbuilder.CreateRetVoid()
|
||||||
|
|
||||||
|
return mod
|
||||||
|
}
|
||||||
|
|
||||||
// optimizeProgram runs a series of optimizations and transformations that are
|
// optimizeProgram runs a series of optimizations and transformations that are
|
||||||
// needed to convert a program to its final form. Some transformations are not
|
// needed to convert a program to its final form. Some transformations are not
|
||||||
// optional and must be run as the compiler expects them to run.
|
// optional and must be run as the compiler expects them to run.
|
||||||
|
|||||||
Reference in New Issue
Block a user