support WASI target (#1373)
* initial commit for WASI support * merge "time" package with wasi build tag * override syscall package with wasi build tag * create runtime_wasm_{js,wasi}.go files * create syscall_wasi.go file * create time/zoneinfo_wasi.go file as the replacement of zoneinfo_js.go * add targets/wasi.json target * set visbility hidden for runtime extern variables Accodring to the WASI docs (https://github.com/WebAssembly/WASI/blob/master/design/application-abi.md#current-unstable-abi), none of exports of WASI executable(Command) should no be accessed. v0.19.0 of bytecodealliance/wasmetime, which is often refered to as the reference implementation of WASI, does not accept any exports except functions and the only limited variables like "table", "memory". * merge syscall_{baremetal,wasi}.go * fix js target build * mv wasi functions to syscall/wasi && implement sleepTicks * WASI: set visibility hidden for globals variables * mv back syscall/wasi/* to runtime package * WASI: add test * unexport wasi types * WASI test: fix wasmtime path * stop changing visibility of runtime.alloc * use GOOS=linux, GOARCH=arm for wasi target Signed-off-by: mathetake <takeshi@tetrate.io> * WASI: fix build tags for os/runtime packages Signed-off-by: mathetake <takeshi@tetrate.io> * run WASI test only on Linux Signed-off-by: mathetake <takeshi@tetrate.io> * set InternalLinkage instead of changing visibility Signed-off-by: mathetake <takeshi@tetrate.io>
Этот коммит содержится в:
родитель
d39c7abb4d
коммит
f50ad3585d
17 изменённых файлов: 241 добавлений и 72 удалений
|
@ -44,6 +44,13 @@ commands:
|
||||||
command: |
|
command: |
|
||||||
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||||
sudo apt install ./google-chrome-stable_current_amd64.deb
|
sudo apt install ./google-chrome-stable_current_amd64.deb
|
||||||
|
install-wasmtime:
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: "Install wasmtime"
|
||||||
|
command: |
|
||||||
|
curl https://wasmtime.dev/install.sh -sSf | bash
|
||||||
|
sudo ln -s ~/.wasmtime/bin/wasmtime /usr/local/bin/wasmtime
|
||||||
install-xtensa-toolchain:
|
install-xtensa-toolchain:
|
||||||
parameters:
|
parameters:
|
||||||
variant:
|
variant:
|
||||||
|
@ -91,6 +98,7 @@ commands:
|
||||||
llvm: "<<parameters.llvm>>"
|
llvm: "<<parameters.llvm>>"
|
||||||
- install-node
|
- install-node
|
||||||
- install-chrome
|
- install-chrome
|
||||||
|
- install-wasmtime
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
|
- go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
|
||||||
|
@ -134,6 +142,7 @@ commands:
|
||||||
gcc-avr \
|
gcc-avr \
|
||||||
avr-libc
|
avr-libc
|
||||||
- install-node
|
- install-node
|
||||||
|
- install-wasmtime
|
||||||
- install-xtensa-toolchain:
|
- install-xtensa-toolchain:
|
||||||
variant: "linux-amd64"
|
variant: "linux-amd64"
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
|
@ -194,6 +203,7 @@ commands:
|
||||||
gcc-avr \
|
gcc-avr \
|
||||||
avr-libc
|
avr-libc
|
||||||
- install-node
|
- install-node
|
||||||
|
- install-wasmtime
|
||||||
- install-xtensa-toolchain:
|
- install-xtensa-toolchain:
|
||||||
variant: "linux-amd64"
|
variant: "linux-amd64"
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
|
|
|
@ -189,7 +189,7 @@ func mergeDirectory(goroot, tinygoroot, tmpgoroot, importPath string, overrides
|
||||||
// with the TinyGo version. This is the case on some targets.
|
// with the TinyGo version. This is the case on some targets.
|
||||||
func needsSyscallPackage(buildTags []string) bool {
|
func needsSyscallPackage(buildTags []string) bool {
|
||||||
for _, tag := range buildTags {
|
for _, tag := range buildTags {
|
||||||
if tag == "baremetal" || tag == "darwin" || tag == "nintendoswitch" {
|
if tag == "baremetal" || tag == "darwin" || tag == "nintendoswitch" || tag == "wasi" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
main_test.go
10
main_test.go
|
@ -98,6 +98,10 @@ func TestCompiler(t *testing.T) {
|
||||||
runPlatTests("wasm", matches, t)
|
runPlatTests("wasm", matches, t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Run("WASI", func(t *testing.T) {
|
||||||
|
runPlatTests("wasi", matches, t)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +113,6 @@ func runPlatTests(target string, matches []string, t *testing.T) {
|
||||||
|
|
||||||
t.Run(filepath.Base(path), func(t *testing.T) {
|
t.Run(filepath.Base(path), func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
runTest(path, target, t)
|
runTest(path, target, t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -161,6 +164,11 @@ func runTest(path, target string, t *testing.T) {
|
||||||
PrintSizes: "",
|
PrintSizes: "",
|
||||||
WasmAbi: "js",
|
WasmAbi: "js",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if target == "wasi" {
|
||||||
|
config.WasmAbi = "generic"
|
||||||
|
}
|
||||||
|
|
||||||
binary := filepath.Join(tmpdir, "test")
|
binary := filepath.Join(tmpdir, "test")
|
||||||
err = runBuild("./"+path, binary, config)
|
err = runBuild("./"+path, binary, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
|
||||||
|
|
||||||
package os
|
package os
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// +build arm,!baremetal arm,arm7tdmi
|
// +build arm,!baremetal,!wasm arm,arm7tdmi
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
|
||||||
// +build !nintendoswitch
|
// +build !nintendoswitch
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
|
||||||
// +build !nintendoswitch
|
// +build !nintendoswitch
|
||||||
|
|
||||||
// +build gc.conservative gc.leaking
|
// +build gc.conservative gc.leaking
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
|
||||||
|
|
||||||
// +build !nintendoswitch
|
// +build !nintendoswitch
|
||||||
|
|
||||||
|
|
|
@ -2,35 +2,26 @@
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import "unsafe"
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
type timeUnit float64 // time in milliseconds, just like Date.now() in JavaScript
|
// Implements __wasi_iovec_t.
|
||||||
|
type __wasi_iovec_t struct {
|
||||||
// Implements __wasi_ciovec_t and __wasi_iovec_t.
|
|
||||||
type wasiIOVec struct {
|
|
||||||
buf unsafe.Pointer
|
buf unsafe.Pointer
|
||||||
bufLen uint
|
bufLen uint
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:wasm-module wasi_unstable
|
//go:wasm-module wasi_unstable
|
||||||
//export fd_write
|
//export fd_write
|
||||||
func fd_write(id uint32, iovs *wasiIOVec, iovs_len uint, nwritten *uint) (errno uint)
|
func fd_write(id uint32, iovs *__wasi_iovec_t, iovs_len uint, nwritten *uint) (errno uint)
|
||||||
|
|
||||||
func postinit() {}
|
func postinit() {}
|
||||||
|
|
||||||
//export _start
|
|
||||||
func _start() {
|
|
||||||
// These need to be initialized early so that the heap can be initialized.
|
|
||||||
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
|
||||||
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
|
||||||
|
|
||||||
run()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Using global variables to avoid heap allocation.
|
// Using global variables to avoid heap allocation.
|
||||||
var (
|
var (
|
||||||
putcharBuf = byte(0)
|
putcharBuf = byte(0)
|
||||||
putcharIOVec = wasiIOVec{
|
putcharIOVec = __wasi_iovec_t{
|
||||||
buf: unsafe.Pointer(&putcharBuf),
|
buf: unsafe.Pointer(&putcharBuf),
|
||||||
bufLen: 1,
|
bufLen: 1,
|
||||||
}
|
}
|
||||||
|
@ -44,49 +35,6 @@ func putchar(c byte) {
|
||||||
fd_write(stdout, &putcharIOVec, 1, &nwritten)
|
fd_write(stdout, &putcharIOVec, 1, &nwritten)
|
||||||
}
|
}
|
||||||
|
|
||||||
var handleEvent func()
|
|
||||||
|
|
||||||
//go:linkname setEventHandler syscall/js.setEventHandler
|
|
||||||
func setEventHandler(fn func()) {
|
|
||||||
handleEvent = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
//export resume
|
|
||||||
func resume() {
|
|
||||||
go func() {
|
|
||||||
handleEvent()
|
|
||||||
}()
|
|
||||||
scheduler()
|
|
||||||
}
|
|
||||||
|
|
||||||
//export go_scheduler
|
|
||||||
func go_scheduler() {
|
|
||||||
scheduler()
|
|
||||||
}
|
|
||||||
|
|
||||||
const asyncScheduler = true
|
|
||||||
|
|
||||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
|
||||||
// The JavaScript API works in float64 milliseconds, so convert to
|
|
||||||
// nanoseconds first before converting to a timeUnit (which is a float64),
|
|
||||||
// to avoid precision loss.
|
|
||||||
return int64(ticks * 1e6)
|
|
||||||
}
|
|
||||||
|
|
||||||
func nanosecondsToTicks(ns int64) timeUnit {
|
|
||||||
// The JavaScript API works in float64 milliseconds, so convert to timeUnit
|
|
||||||
// (which is a float64) first before dividing, to avoid precision loss.
|
|
||||||
return timeUnit(ns) / 1e6
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is called by the scheduler.
|
|
||||||
// Schedule a call to runtime.scheduler, do not actually sleep.
|
|
||||||
//export runtime.sleepTicks
|
|
||||||
func sleepTicks(d timeUnit)
|
|
||||||
|
|
||||||
//export runtime.ticks
|
|
||||||
func ticks() timeUnit
|
|
||||||
|
|
||||||
// Abort executes the wasm 'unreachable' instruction.
|
// Abort executes the wasm 'unreachable' instruction.
|
||||||
func abort() {
|
func abort() {
|
||||||
trap()
|
trap()
|
||||||
|
|
59
src/runtime/runtime_wasm_js.go
Обычный файл
59
src/runtime/runtime_wasm_js.go
Обычный файл
|
@ -0,0 +1,59 @@
|
||||||
|
// +build wasm,!wasi
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
type timeUnit float64 // time in milliseconds, just like Date.now() in JavaScript
|
||||||
|
|
||||||
|
//export _start
|
||||||
|
func _start() {
|
||||||
|
// These need to be initialized early so that the heap can be initialized.
|
||||||
|
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||||
|
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
||||||
|
|
||||||
|
run()
|
||||||
|
}
|
||||||
|
|
||||||
|
var handleEvent func()
|
||||||
|
|
||||||
|
//go:linkname setEventHandler syscall/js.setEventHandler
|
||||||
|
func setEventHandler(fn func()) {
|
||||||
|
handleEvent = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
//export resume
|
||||||
|
func resume() {
|
||||||
|
go func() {
|
||||||
|
handleEvent()
|
||||||
|
}()
|
||||||
|
scheduler()
|
||||||
|
}
|
||||||
|
|
||||||
|
//export go_scheduler
|
||||||
|
func go_scheduler() {
|
||||||
|
scheduler()
|
||||||
|
}
|
||||||
|
|
||||||
|
const asyncScheduler = true
|
||||||
|
|
||||||
|
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||||
|
// The JavaScript API works in float64 milliseconds, so convert to
|
||||||
|
// nanoseconds first before converting to a timeUnit (which is a float64),
|
||||||
|
// to avoid precision loss.
|
||||||
|
return int64(ticks * 1e6)
|
||||||
|
}
|
||||||
|
|
||||||
|
func nanosecondsToTicks(ns int64) timeUnit {
|
||||||
|
// The JavaScript API works in float64 milliseconds, so convert to timeUnit
|
||||||
|
// (which is a float64) first before dividing, to avoid precision loss.
|
||||||
|
return timeUnit(ns) / 1e6
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is called by the scheduler.
|
||||||
|
// Schedule a call to runtime.scheduler, do not actually sleep.
|
||||||
|
//export runtime.sleepTicks
|
||||||
|
func sleepTicks(d timeUnit)
|
||||||
|
|
||||||
|
//export runtime.ticks
|
||||||
|
func ticks() timeUnit
|
117
src/runtime/runtime_wasm_wasi.go
Обычный файл
117
src/runtime/runtime_wasm_wasi.go
Обычный файл
|
@ -0,0 +1,117 @@
|
||||||
|
// +build wasm,wasi
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type timeUnit int64
|
||||||
|
|
||||||
|
//export _start
|
||||||
|
func _start() {
|
||||||
|
// These need to be initialized early so that the heap can be initialized.
|
||||||
|
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||||
|
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
||||||
|
run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||||
|
return int64(ticks)
|
||||||
|
}
|
||||||
|
|
||||||
|
func nanosecondsToTicks(ns int64) timeUnit {
|
||||||
|
return timeUnit(ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
asyncScheduler = false
|
||||||
|
timePrecisionNanoseconds = 1000 // TODO: how can we determine the appropriate `precision`?
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
sleepTicksSubscription = __wasi_subscription_t{
|
||||||
|
userData: 0,
|
||||||
|
u: __wasi_subscription_u_t{
|
||||||
|
tag: __wasi_eventtype_t_clock,
|
||||||
|
u: __wasi_subscription_clock_t{
|
||||||
|
userData: 0,
|
||||||
|
id: 0,
|
||||||
|
timeout: 0,
|
||||||
|
precision: timePrecisionNanoseconds,
|
||||||
|
flags: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
sleepTicksResult = __wasi_event_t{}
|
||||||
|
sleepTicksNEvents uint32
|
||||||
|
)
|
||||||
|
|
||||||
|
func sleepTicks(d timeUnit) {
|
||||||
|
sleepTicksSubscription.u.u.timeout = int64(d)
|
||||||
|
poll_oneoff(&sleepTicksSubscription, &sleepTicksResult, 1, &sleepTicksNEvents)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ticks() timeUnit {
|
||||||
|
var nano int64
|
||||||
|
clock_time_get(0, timePrecisionNanoseconds, &nano)
|
||||||
|
return timeUnit(nano)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementations of wasi_unstable APIs
|
||||||
|
|
||||||
|
//go:wasm-module wasi_unstable
|
||||||
|
//export clock_time_get
|
||||||
|
func clock_time_get(clockid uint32, precision uint64, time *int64) (errno uint16)
|
||||||
|
|
||||||
|
//go:wasm-module wasi_unstable
|
||||||
|
//export poll_oneoff
|
||||||
|
func poll_oneoff(in *__wasi_subscription_t, out *__wasi_event_t, nsubscriptions uint32, nevents *uint32) (errno uint16)
|
||||||
|
|
||||||
|
type __wasi_eventtype_t = uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
__wasi_eventtype_t_clock __wasi_eventtype_t = 0
|
||||||
|
// TODO: __wasi_eventtype_t_fd_read __wasi_eventtype_t = 1
|
||||||
|
// TODO: __wasi_eventtype_t_fd_write __wasi_eventtype_t = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// https://github.com/wasmerio/wasmer/blob/1.0.0-alpha3/lib/wasi/src/syscalls/types.rs#L584-L588
|
||||||
|
__wasi_subscription_t struct {
|
||||||
|
userData uint64
|
||||||
|
u __wasi_subscription_u_t
|
||||||
|
}
|
||||||
|
|
||||||
|
__wasi_subscription_u_t struct {
|
||||||
|
tag __wasi_eventtype_t
|
||||||
|
|
||||||
|
// TODO: support fd_read/fd_write event
|
||||||
|
u __wasi_subscription_clock_t
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/wasmerio/wasmer/blob/1.0.0-alpha3/lib/wasi/src/syscalls/types.rs#L711-L718
|
||||||
|
__wasi_subscription_clock_t struct {
|
||||||
|
userData uint64
|
||||||
|
id uint32
|
||||||
|
timeout int64
|
||||||
|
precision int64
|
||||||
|
flags uint16
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// https://github.com/wasmerio/wasmer/blob/1.0.0-alpha3/lib/wasi/src/syscalls/types.rs#L191-L198
|
||||||
|
__wasi_event_t struct {
|
||||||
|
userData uint64
|
||||||
|
errno uint16
|
||||||
|
eventType __wasi_eventtype_t
|
||||||
|
|
||||||
|
// only used for fd_read or fd_write events
|
||||||
|
// TODO: support fd_read/fd_write event
|
||||||
|
_ struct {
|
||||||
|
nBytes uint64
|
||||||
|
flags uint16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
|
@ -1,4 +1,4 @@
|
||||||
// +build baremetal
|
// +build baremetal wasi
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build baremetal nintendoswitch
|
// +build baremetal nintendoswitch wasi
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
|
|
22
targets/wasi.json
Обычный файл
22
targets/wasi.json
Обычный файл
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"llvm-target": "wasm32--wasi",
|
||||||
|
"build-tags": ["wasm", "wasi"],
|
||||||
|
"goos": "linux",
|
||||||
|
"goarch": "arm",
|
||||||
|
"compiler": "clang",
|
||||||
|
"linker": "wasm-ld",
|
||||||
|
"cflags": [
|
||||||
|
"--target=wasm32--wasi",
|
||||||
|
"--sysroot={root}/lib/wasi-libc/sysroot",
|
||||||
|
"-Oz"
|
||||||
|
],
|
||||||
|
"ldflags": [
|
||||||
|
"--allow-undefined",
|
||||||
|
"--no-threads",
|
||||||
|
"--stack-first",
|
||||||
|
"--export-dynamic",
|
||||||
|
"--no-demangle",
|
||||||
|
"{root}/lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a"
|
||||||
|
],
|
||||||
|
"emulator": ["wasmtime"]
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
|
||||||
}
|
}
|
||||||
stackChainStart := mod.NamedGlobal("runtime.stackChainStart")
|
stackChainStart := mod.NamedGlobal("runtime.stackChainStart")
|
||||||
if !stackChainStart.IsNil() {
|
if !stackChainStart.IsNil() {
|
||||||
|
stackChainStart.SetLinkage(llvm.InternalLinkage)
|
||||||
stackChainStart.SetInitializer(llvm.ConstNull(stackChainStart.Type().ElementType()))
|
stackChainStart.SetInitializer(llvm.ConstNull(stackChainStart.Type().ElementType()))
|
||||||
stackChainStart.SetGlobalConstant(true)
|
stackChainStart.SetGlobalConstant(true)
|
||||||
}
|
}
|
||||||
|
@ -94,6 +95,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
stackChainStart.SetLinkage(llvm.InternalLinkage)
|
||||||
stackChainStartType := stackChainStart.Type().ElementType()
|
stackChainStartType := stackChainStart.Type().ElementType()
|
||||||
stackChainStart.SetInitializer(llvm.ConstNull(stackChainStartType))
|
stackChainStart.SetInitializer(llvm.ConstNull(stackChainStartType))
|
||||||
|
|
||||||
|
@ -333,11 +335,13 @@ func AddGlobalsBitmap(mod llvm.Module) bool {
|
||||||
// Update trackedGlobalsStart, which points to the globals bundle.
|
// Update trackedGlobalsStart, which points to the globals bundle.
|
||||||
trackedGlobalsStart := llvm.ConstPtrToInt(globalsBundle, uintptrType)
|
trackedGlobalsStart := llvm.ConstPtrToInt(globalsBundle, uintptrType)
|
||||||
mod.NamedGlobal("runtime.trackedGlobalsStart").SetInitializer(trackedGlobalsStart)
|
mod.NamedGlobal("runtime.trackedGlobalsStart").SetInitializer(trackedGlobalsStart)
|
||||||
|
mod.NamedGlobal("runtime.trackedGlobalsStart").SetLinkage(llvm.InternalLinkage)
|
||||||
|
|
||||||
// Update trackedGlobalsLength, which contains the length (in words) of the
|
// Update trackedGlobalsLength, which contains the length (in words) of the
|
||||||
// globals bundle.
|
// globals bundle.
|
||||||
alignment := targetData.PrefTypeAlignment(llvm.PointerType(ctx.Int8Type(), 0))
|
alignment := targetData.PrefTypeAlignment(llvm.PointerType(ctx.Int8Type(), 0))
|
||||||
trackedGlobalsLength := llvm.ConstInt(uintptrType, targetData.TypeAllocSize(globalsBundleType)/uint64(alignment), false)
|
trackedGlobalsLength := llvm.ConstInt(uintptrType, targetData.TypeAllocSize(globalsBundleType)/uint64(alignment), false)
|
||||||
|
mod.NamedGlobal("runtime.trackedGlobalsLength").SetLinkage(llvm.InternalLinkage)
|
||||||
mod.NamedGlobal("runtime.trackedGlobalsLength").SetInitializer(trackedGlobalsLength)
|
mod.NamedGlobal("runtime.trackedGlobalsLength").SetInitializer(trackedGlobalsLength)
|
||||||
|
|
||||||
// Create a bitmap (a new global) that stores for each word in the globals
|
// Create a bitmap (a new global) that stores for each word in the globals
|
||||||
|
@ -357,6 +361,7 @@ func AddGlobalsBitmap(mod llvm.Module) bool {
|
||||||
bitmapOld.ReplaceAllUsesWith(llvm.ConstBitCast(bitmapNew, bitmapOld.Type()))
|
bitmapOld.ReplaceAllUsesWith(llvm.ConstBitCast(bitmapNew, bitmapOld.Type()))
|
||||||
bitmapNew.SetInitializer(bitmapArray)
|
bitmapNew.SetInitializer(bitmapArray)
|
||||||
bitmapNew.SetName("runtime.trackedGlobalsBitmap")
|
bitmapNew.SetName("runtime.trackedGlobalsBitmap")
|
||||||
|
bitmapNew.SetLinkage(llvm.InternalLinkage)
|
||||||
|
|
||||||
return true // the IR was changed
|
return true // the IR was changed
|
||||||
}
|
}
|
||||||
|
|
6
transform/testdata/gc-globals.out.ll
предоставленный
6
transform/testdata/gc-globals.out.ll
предоставленный
|
@ -7,11 +7,11 @@ target triple = "wasm32-unknown-unknown-wasm"
|
||||||
@globalInt = global i32 5
|
@globalInt = global i32 5
|
||||||
@constString = constant %runtime._string zeroinitializer
|
@constString = constant %runtime._string zeroinitializer
|
||||||
@constInterface = constant %runtime._interface zeroinitializer
|
@constInterface = constant %runtime._interface zeroinitializer
|
||||||
@runtime.trackedGlobalsLength = global i32 4
|
@runtime.trackedGlobalsLength = internal global i32 4
|
||||||
@runtime.trackedGlobalsBitmap = external global [0 x i8]
|
@runtime.trackedGlobalsBitmap = external global [0 x i8]
|
||||||
@runtime.trackedGlobalsStart = global i32 ptrtoint ({ %runtime._string, %runtime._interface }* @tinygo.trackedGlobals to i32)
|
@runtime.trackedGlobalsStart = internal global i32 ptrtoint ({ %runtime._string, %runtime._interface }* @tinygo.trackedGlobals to i32)
|
||||||
@tinygo.trackedGlobals = internal unnamed_addr global { %runtime._string, %runtime._interface } zeroinitializer
|
@tinygo.trackedGlobals = internal unnamed_addr global { %runtime._string, %runtime._interface } zeroinitializer
|
||||||
@runtime.trackedGlobalsBitmap.1 = global [1 x i8] c"\09"
|
@runtime.trackedGlobalsBitmap.1 = internal global [1 x i8] c"\09"
|
||||||
|
|
||||||
define void @main() {
|
define void @main() {
|
||||||
%1 = load i32, i32* @globalInt
|
%1 = load i32, i32* @globalInt
|
||||||
|
|
2
transform/testdata/gc-stackslots.out.ll
предоставленный
2
transform/testdata/gc-stackslots.out.ll
предоставленный
|
@ -3,7 +3,7 @@ target triple = "wasm32-unknown-unknown-wasm"
|
||||||
|
|
||||||
%runtime.stackChainObject = type { %runtime.stackChainObject*, i32 }
|
%runtime.stackChainObject = type { %runtime.stackChainObject*, i32 }
|
||||||
|
|
||||||
@runtime.stackChainStart = global %runtime.stackChainObject* null
|
@runtime.stackChainStart = internal global %runtime.stackChainObject* null
|
||||||
@someGlobal = global i8 3
|
@someGlobal = global i8 3
|
||||||
|
|
||||||
declare void @runtime.trackPointer(i8* nocapture readonly)
|
declare void @runtime.trackPointer(i8* nocapture readonly)
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче