
When using the latest wasi-libc I experienced a panic on an attempt to call realloc. My first attempt to add it to arch_tinygowasm.go was obviously not good (PR #2194). So here is another suggestion.
106 строки
2,7 КиБ
Go
106 строки
2,7 КиБ
Go
// +build tinygo.wasm
|
|
|
|
package runtime
|
|
|
|
import (
|
|
"unsafe"
|
|
)
|
|
|
|
const GOARCH = "wasm"
|
|
|
|
// The bitness of the CPU (e.g. 8, 32, 64).
|
|
const TargetBits = 32
|
|
|
|
//go:extern __heap_base
|
|
var heapStartSymbol [0]byte
|
|
|
|
//go:extern __global_base
|
|
var globalsStartSymbol [0]byte
|
|
|
|
//export llvm.wasm.memory.size.i32
|
|
func wasm_memory_size(index int32) int32
|
|
|
|
//export llvm.wasm.memory.grow.i32
|
|
func wasm_memory_grow(index int32, delta int32) int32
|
|
|
|
var (
|
|
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
|
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
|
globalsStart = uintptr(unsafe.Pointer(&globalsStartSymbol))
|
|
globalsEnd = uintptr(unsafe.Pointer(&heapStartSymbol))
|
|
)
|
|
|
|
const wasmPageSize = 64 * 1024
|
|
|
|
func align(ptr uintptr) uintptr {
|
|
// Align to 16, which is the alignment of max_align_t:
|
|
// https://godbolt.org/z/dYqTsWrGq
|
|
const heapAlign = 16
|
|
return (ptr + heapAlign - 1) &^ (heapAlign - 1)
|
|
}
|
|
|
|
func getCurrentStackPointer() uintptr
|
|
|
|
// growHeap tries to grow the heap size. It returns true if it succeeds, false
|
|
// otherwise.
|
|
func growHeap() bool {
|
|
// Grow memory by the available size, which means the heap size is doubled.
|
|
memorySize := wasm_memory_size(0)
|
|
result := wasm_memory_grow(0, memorySize)
|
|
if result == -1 {
|
|
// Grow failed.
|
|
return false
|
|
}
|
|
|
|
setHeapEnd(uintptr(wasm_memory_size(0) * wasmPageSize))
|
|
|
|
// Heap has grown successfully.
|
|
return true
|
|
}
|
|
|
|
// The below functions override the default allocator of wasi-libc.
|
|
// Most functions are defined but unimplemented to make sure that if there is
|
|
// any code using them, they will get an error instead of (incorrectly) using
|
|
// the wasi-libc dlmalloc heap implementation instead. If they are needed by any
|
|
// program, they can certainly be implemented.
|
|
|
|
//export malloc
|
|
func libc_malloc(size uintptr) unsafe.Pointer {
|
|
return alloc(size, nil)
|
|
}
|
|
|
|
//export free
|
|
func libc_free(ptr unsafe.Pointer) {
|
|
free(ptr)
|
|
}
|
|
|
|
//export calloc
|
|
func libc_calloc(nmemb, size uintptr) unsafe.Pointer {
|
|
// Note: we could be even more correct here and check that nmemb * size
|
|
// doesn't overflow. However the current implementation should normally work
|
|
// fine.
|
|
return alloc(nmemb*size, nil)
|
|
}
|
|
|
|
//export realloc
|
|
func libc_realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer {
|
|
return realloc(ptr, size)
|
|
}
|
|
|
|
//export posix_memalign
|
|
func libc_posix_memalign(memptr *unsafe.Pointer, alignment, size uintptr) int {
|
|
runtimePanic("unimplemented: posix_memalign")
|
|
return 0
|
|
}
|
|
|
|
//export aligned_alloc
|
|
func libc_aligned_alloc(alignment, bytes uintptr) unsafe.Pointer {
|
|
runtimePanic("unimplemented: aligned_alloc")
|
|
return nil
|
|
}
|
|
|
|
//export malloc_usable_size
|
|
func libc_malloc_usable_size(ptr unsafe.Pointer) uintptr {
|
|
runtimePanic("unimplemented: malloc_usable_size")
|
|
return 0
|
|
}
|