Skip to content

Commit 132cc7b

Browse files
committed
Add support for using wizer to handle running initAll()
1 parent 20b58a0 commit 132cc7b

File tree

11 files changed

+143
-10
lines changed

11 files changed

+143
-10
lines changed

builder/build.go

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,33 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
854854
}
855855
}
856856

857+
if config.Options.WizerInit {
858+
var args []string
859+
860+
resultWizer := result.Executable + "-wizer"
861+
862+
args = append(args,
863+
"--allow-wasi",
864+
"--wasm-bulk-memory=true",
865+
"-f", "runtime.wizerInit",
866+
result.Executable,
867+
"-o", resultWizer,
868+
)
869+
870+
cmd := exec.Command(goenv.Get("WIZER"), args...)
871+
cmd.Stdout = os.Stdout
872+
cmd.Stderr = os.Stderr
873+
874+
err := cmd.Run()
875+
if err != nil {
876+
return fmt.Errorf("wizer failed: %w", err)
877+
}
878+
879+
if err := os.Rename(resultWizer, result.Executable); err != nil {
880+
return fmt.Errorf("rename failed: %w", err)
881+
}
882+
}
883+
857884
// Print code size if requested.
858885
if config.Options.PrintSizes == "short" || config.Options.PrintSizes == "full" {
859886
packagePathMap := make(map[string]string, len(lprogram.Packages))
@@ -1051,9 +1078,10 @@ func createEmbedObjectFile(data, hexSum, sourceFile, sourceDir, tmpdir string, c
10511078
// needed to convert a program to its final form. Some transformations are not
10521079
// optional and must be run as the compiler expects them to run.
10531080
func optimizeProgram(mod llvm.Module, config *compileopts.Config, globalValues map[string]map[string]string) error {
1054-
err := interp.Run(mod, config.Options.InterpTimeout, config.DumpSSA())
1055-
if err != nil {
1056-
return err
1081+
if !config.Options.WizerInit {
1082+
if err := interp.Run(mod, config.Options.InterpTimeout, config.DumpSSA()); err != nil {
1083+
return err
1084+
}
10571085
}
10581086
if config.VerifyIR() {
10591087
// Only verify if we really need it.
@@ -1069,7 +1097,7 @@ func optimizeProgram(mod llvm.Module, config *compileopts.Config, globalValues m
10691097
}
10701098

10711099
// Insert values from -ldflags="-X ..." into the IR.
1072-
err = setGlobalValues(mod, globalValues)
1100+
err := setGlobalValues(mod, globalValues)
10731101
if err != nil {
10741102
return err
10751103
}

compileopts/options.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ type Options struct {
5353
Monitor bool
5454
BaudRate int
5555
Timeout time.Duration
56+
WizerInit bool
5657
}
5758

5859
// Verify performs a validation on the given options, raising an error if options are not valid.

goenv/goenv.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,35 @@ func Get(name string) string {
159159
}
160160

161161
return findWasmOpt()
162+
163+
case "WIZER":
164+
if path := os.Getenv("WIZER"); path != "" {
165+
wizerBin := "wizer"
166+
if runtime.GOOS == "windows" {
167+
wizerBin += ".exe"
168+
}
169+
170+
_, err := exec.LookPath(wizerBin)
171+
if err != nil {
172+
fmt.Fprintf(os.Stderr, "cannot use %q as wasm-opt (from WASMOPT environment variable): %s", path, err.Error())
173+
os.Exit(1)
174+
}
175+
176+
return path
177+
}
178+
179+
wizerBin := "wizer"
180+
if runtime.GOOS == "windows" {
181+
wizerBin += ".exe"
182+
}
183+
184+
path, err := exec.LookPath(wizerBin)
185+
if err != nil {
186+
fmt.Fprintf(os.Stderr, "cannot use %q as wizer: %s", path, err.Error())
187+
os.Exit(1)
188+
}
189+
return path
190+
162191
default:
163192
return ""
164193
}

main.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,7 @@ func main() {
14401440
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
14411441
monitor := flag.Bool("monitor", false, "enable serial monitor")
14421442
baudrate := flag.Int("baudrate", 115200, "baudrate of serial monitor")
1443+
wizerInit := flag.Bool("wizer-init", false, "use wizer for package initialization")
14431444

14441445
// Internal flags, that are only intended for TinyGo development.
14451446
printIR := flag.Bool("internal-printir", false, "print LLVM IR")
@@ -1512,6 +1513,11 @@ func main() {
15121513
ocdCommands = strings.Split(*ocdCommandsString, ",")
15131514
}
15141515

1516+
if *wizerInit && *target != "wasip1" {
1517+
fmt.Fprintf(os.Stderr, "-wizer-init only makes sense with -target=wasip1, got -target=%q\n", *target)
1518+
os.Exit(1)
1519+
}
1520+
15151521
options := &compileopts.Options{
15161522
GOOS: goenv.Get("GOOS"),
15171523
GOARCH: goenv.Get("GOARCH"),
@@ -1544,7 +1550,9 @@ func main() {
15441550
Monitor: *monitor,
15451551
BaudRate: *baudrate,
15461552
Timeout: *timeout,
1553+
WizerInit: *wizerInit,
15471554
}
1555+
15481556
if *printCommands {
15491557
options.PrintCommands = printCommand
15501558
}

src/runtime/runtime.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ const Compiler = "tinygo"
1212
// package.
1313
func initAll()
1414

15+
var runtimeInitialized = false
16+
17+
func runtime_is_initialized() bool {
18+
return runtimeInitialized
19+
}
20+
1521
//go:linkname callMain main.main
1622
func callMain()
1723

src/runtime/runtime_wasip1.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,29 @@ func __wasm_call_ctors()
1515

1616
//export _start
1717
func _start() {
18+
runtimeInitialize()
19+
run()
20+
}
21+
22+
//export runtime.wizerInit
23+
func runtimeInitialize() {
24+
if runtimeInitialized {
25+
// Second time initialization is happening. Refresh environment
26+
// to whatever our current host gives us instead of whatever
27+
// libc cached.
28+
reset_libc_environment()
29+
return
30+
}
1831
// These need to be initialized early so that the heap can be initialized.
1932
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
2033
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
21-
run()
34+
initHeap()
35+
if hasScheduler {
36+
go initAll()
37+
} else {
38+
initAll()
39+
}
40+
runtimeInitialized = true
2241
}
2342

2443
// Read the command line arguments from WASI.
@@ -29,6 +48,17 @@ func init() {
2948
__wasm_call_ctors()
3049
}
3150

51+
//export __wasilibc_deinitialize_environ
52+
func __wasilibc_deinitialize_environ()
53+
54+
//export __wasilibc_initialize_environ
55+
func __wasilibc_initialize_environ()
56+
57+
func reset_libc_environment() {
58+
__wasilibc_deinitialize_environ()
59+
__wasilibc_initialize_environ()
60+
}
61+
3262
var args []string
3363

3464
//go:linkname os_runtime_args os.runtime_args
@@ -39,7 +69,10 @@ func os_runtime_args() []string {
3969
var argc, argv_buf_size uint32
4070
args_sizes_get(&argc, &argv_buf_size)
4171
if argc == 0 {
42-
return nil
72+
// Most things expect os.Args to have at least the
73+
// program name. We don't have one, but also don't
74+
// return just a nil slice.
75+
return []string{""}
4376
}
4477

4578
// Obtain the command line arguments

src/runtime/scheduler_any.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,14 @@ func sleep(duration int64) {
1919
// run is called by the program entry point to execute the go program.
2020
// With a scheduler, init and the main function are invoked in a goroutine before starting the scheduler.
2121
func run() {
22-
initHeap()
22+
if !runtimeInitialized {
23+
initHeap()
24+
}
2325
go func() {
24-
initAll()
26+
if !runtimeInitialized {
27+
initAll()
28+
runtimeInitialized = true
29+
}
2530
callMain()
2631
schedulerDone = true
2732
}()

src/runtime/scheduler_none.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@ func getSystemStackPointer() uintptr {
2020
// run is called by the program entry point to execute the go program.
2121
// With the "none" scheduler, init and the main function are invoked directly.
2222
func run() {
23-
initHeap()
24-
initAll()
23+
if !runtimeInitialized {
24+
initHeap()
25+
initAll()
26+
runtimeInitialized = true
27+
}
2528
callMain()
2629
}
2730

src/syscall/build_asserts.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//go:build syscall_asserts
2+
3+
package syscall
4+
5+
// enable assertions for checking Environ during runtime preinitialization.
6+
// This is to catch people using os.Environ() during package inits with wizer.
7+
const panicOnEnvironDuringInitAll = true

src/syscall/build_noasserts.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//go:build !syscall_asserts
2+
3+
package syscall
4+
5+
// enable assertions for checking Environ during runtime preinitialization.
6+
// This is to catch people using os.Environ() during package init with wizer.
7+
const panicOnEnvironDuringInitAll = false

0 commit comments

Comments
 (0)