mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-03 10:37:46 +00:00
8bbfb1ee68
--allow-undefined can be a problem: it allows compiling code that will
fail when loaded. This change makes sure that if some symbols are
undefined, they are reported as an error by the linker.
Previously, people could get away with importing a function that was not
defined, like this:
func add(int a, int b) int
func test() {
println(add(3, 5))
}
This was always unintended but mostly worked. With this change, it isn't
possible anymore. Now every function needs to be marked with //export
explicitly:
//export add
func add(int a, int b) int
func test() {
println(add(3, 5))
}
As before, functions will be placed in the `env` module with the name
set from the `//export` tag. This can be overridden with
`//go:import-module`:
//go:import-module math
//export add
func add(int a, int b) int
func test() {
println(add(3, 5))
}
For the syscall/js package, I needed to give a list of symbols that are
undefined. This list is based on the JavaScript functions defined in
targets/wasm_exec.js.
107 lines
3.3 KiB
ArmAsm
107 lines
3.3 KiB
ArmAsm
.globaltype __stack_pointer, i32
|
|
|
|
.functype start_unwind (i32) -> ()
|
|
.import_module start_unwind, asyncify
|
|
.import_name start_unwind, start_unwind
|
|
.functype stop_unwind () -> ()
|
|
.import_module stop_unwind, asyncify
|
|
.import_name stop_unwind, stop_unwind
|
|
.functype start_rewind (i32) -> ()
|
|
.import_module start_rewind, asyncify
|
|
.import_name start_rewind, start_rewind
|
|
.functype stop_rewind () -> ()
|
|
.import_module stop_rewind, asyncify
|
|
.import_name stop_rewind, stop_rewind
|
|
|
|
.global tinygo_unwind
|
|
.hidden tinygo_unwind
|
|
.type tinygo_unwind,@function
|
|
tinygo_unwind: // func (state *stackState) unwind()
|
|
.functype tinygo_unwind (i32) -> ()
|
|
// Check if we are rewinding.
|
|
i32.const 0
|
|
i32.load8_u tinygo_rewinding
|
|
if // if tinygo_rewinding {
|
|
// Stop rewinding.
|
|
call stop_rewind
|
|
i32.const 0
|
|
i32.const 0
|
|
i32.store8 tinygo_rewinding // tinygo_rewinding = false;
|
|
else
|
|
// Save the C stack pointer (destination structure pointer is in local 0).
|
|
local.get 0
|
|
global.get __stack_pointer
|
|
i32.store 4 // state.csp = getCurrentStackPointer()
|
|
// Ask asyncify to unwind.
|
|
// When resuming, asyncify will return this function with tinygo_rewinding set to true.
|
|
local.get 0
|
|
call start_unwind // asyncify.start_unwind(state)
|
|
end_if
|
|
return
|
|
end_function
|
|
|
|
.global tinygo_launch
|
|
.hidden tinygo_launch
|
|
.type tinygo_launch,@function
|
|
tinygo_launch: // func (state *state) launch()
|
|
.functype tinygo_launch (i32) -> ()
|
|
// Switch to the goroutine's C stack.
|
|
global.get __stack_pointer // prev := getCurrentStackPointer()
|
|
local.get 0
|
|
i32.load 12
|
|
global.set __stack_pointer // setStackPointer(state.csp)
|
|
// Get the argument pack and entry pointer.
|
|
local.get 0
|
|
i32.load 4 // args := state.args
|
|
local.get 0
|
|
i32.load 0 // fn := state.entry
|
|
// Launch the entry function.
|
|
call_indirect (i32) -> () // fn(args)
|
|
// Stop unwinding.
|
|
call stop_unwind
|
|
// Restore the C stack.
|
|
global.set __stack_pointer // setStackPointer(prev)
|
|
return
|
|
end_function
|
|
|
|
.global tinygo_rewind
|
|
.hidden tinygo_rewind
|
|
.type tinygo_rewind,@function
|
|
tinygo_rewind: // func (state *state) rewind()
|
|
.functype tinygo_rewind (i32) -> ()
|
|
// Switch to the goroutine's C stack.
|
|
global.get __stack_pointer // prev := getCurrentStackPointer()
|
|
local.get 0
|
|
i32.load 12
|
|
global.set __stack_pointer // setStackPointer(state.csp)
|
|
// Get the argument pack and entry pointer.
|
|
local.get 0
|
|
i32.load 4 // args := state.args
|
|
local.get 0
|
|
i32.load 0 // fn := state.entry
|
|
// Prepare to rewind.
|
|
i32.const 0
|
|
i32.const 1
|
|
i32.store8 tinygo_rewinding // tinygo_rewinding = true;
|
|
local.get 0
|
|
i32.const 8
|
|
i32.add
|
|
call start_rewind // asyncify.start_rewind(&state.stackState)
|
|
// Launch the entry function.
|
|
// This will actually rewind the call stack.
|
|
call_indirect (i32) -> () // fn(args)
|
|
// Stop unwinding.
|
|
call stop_unwind
|
|
// Restore the C stack.
|
|
global.set __stack_pointer // setStackPointer(prev)
|
|
return
|
|
end_function
|
|
|
|
.hidden tinygo_rewinding # @tinygo_rewinding
|
|
.type tinygo_rewinding,@object
|
|
.section .bss.tinygo_rewinding,"",@
|
|
.globl tinygo_rewinding
|
|
tinygo_rewinding:
|
|
.int8 0 # 0x0
|
|
.size tinygo_rewinding, 1
|