mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-03 18:47:47 +00:00
612a38e363
This fixes bug https://github.com/tinygo-org/tinygo/issues/4874.
104 lines
3.1 KiB
Go
104 lines
3.1 KiB
Go
//go:build tinygo.wasm
|
|
|
|
package runtime
|
|
|
|
// Entry points for WebAssembly modules, and runtime support for
|
|
// //go:wasmexport: runtime.wasmExport* function calls are inserted by the
|
|
// compiler for //go:wasmexport support.
|
|
|
|
import (
|
|
"internal/task"
|
|
"unsafe"
|
|
)
|
|
|
|
// This is the _start entry point, when using -buildmode=default.
|
|
func wasmEntryCommand() {
|
|
// These need to be initialized early so that the heap can be initialized.
|
|
initializeCalled = true
|
|
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
|
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
|
run()
|
|
if mainExited {
|
|
// To make sure wasm_exec.js knows that we've exited, exit explicitly.
|
|
mainReturnExit()
|
|
}
|
|
}
|
|
|
|
// This is the _initialize entry point, when using -buildmode=c-shared.
|
|
func wasmEntryReactor() {
|
|
// This function is called before any //go:wasmexport functions are called
|
|
// to initialize everything. It must not block.
|
|
|
|
initializeCalled = true
|
|
|
|
// Initialize the heap.
|
|
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
|
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
|
initHeap()
|
|
initRand()
|
|
|
|
if hasScheduler {
|
|
// A package initializer might do funky stuff like start a goroutine and
|
|
// wait until it completes, so we have to run package initializers in a
|
|
// goroutine.
|
|
go func() {
|
|
initAll()
|
|
}()
|
|
scheduler(true)
|
|
} else {
|
|
// There are no goroutines (except for the main one, if you can call it
|
|
// that), so we can just run all the package initializers.
|
|
initAll()
|
|
}
|
|
}
|
|
|
|
// This is the _start entry point, when using -buildmode=wasi-legacy.
|
|
func wasmEntryLegacy() {
|
|
// These need to be initialized early so that the heap can be initialized.
|
|
initializeCalled = true
|
|
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
|
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
|
run()
|
|
}
|
|
|
|
// Whether the runtime was initialized by a call to _initialize or _start.
|
|
var initializeCalled bool
|
|
|
|
func wasmExportCheckRun() {
|
|
switch {
|
|
case !initializeCalled:
|
|
runtimePanic("//go:wasmexport function called before runtime initialization")
|
|
case mainExited:
|
|
runtimePanic("//go:wasmexport function called after main.main returned")
|
|
}
|
|
}
|
|
|
|
// Called from within a //go:wasmexport wrapper (the one that's exported from
|
|
// the wasm module) after the goroutine has been queued. Just run the scheduler,
|
|
// and check that the goroutine finished when the scheduler is idle (as required
|
|
// by the //go:wasmexport proposal).
|
|
//
|
|
// This function is not called when the scheduler is disabled.
|
|
func wasmExportRun(done *bool) {
|
|
scheduler(true)
|
|
if !*done {
|
|
runtimePanic("//go:wasmexport function did not finish")
|
|
}
|
|
}
|
|
|
|
// Called from the goroutine wrapper for the //go:wasmexport function. It just
|
|
// signals to the runtime that the //go:wasmexport call has finished, and can
|
|
// switch back to the wasmExportRun function.
|
|
//
|
|
// This function is not called when the scheduler is disabled.
|
|
func wasmExportExit() {
|
|
// Signal to the scheduler that it should return, since this call to a
|
|
// //go:wasmexport function has exited.
|
|
schedulerExit = true
|
|
|
|
task.Pause()
|
|
|
|
// TODO: we could cache the allocated stack so we don't have to keep
|
|
// allocating a new stack on every //go:wasmexport call.
|
|
}
|