aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaytan Laats <laytanlaats@hotmail.com>2024-06-29 23:09:49 +0200
committerLaytan Laats <laytanlaats@hotmail.com>2024-06-29 23:15:31 +0200
commit604551eb2d106d64eb9159bc17aa5c57bbca0ca4 (patch)
tree27ca9e57f7091af156f86f01311928567d01e4a9
parent476d0087c8d47102c23cf6de71eb4014b9a7b6b2 (diff)
wasi: make the demo run on wasi and run it in CI
-rw-r--r--.github/workflows/ci.yml8
-rw-r--r--base/runtime/entry_wasm.odin5
-rw-r--r--base/runtime/os_specific_wasi.odin50
-rw-r--r--base/runtime/wasm_allocator.odin2
-rw-r--r--core/encoding/cbor/tags.odin1
-rw-r--r--core/os/os_wasi.odin12
-rw-r--r--core/thread/thread.odin6
-rw-r--r--core/thread/thread_js.odin47
-rw-r--r--core/thread/thread_other.odin47
-rw-r--r--core/thread/thread_unix.odin2
-rw-r--r--core/thread/thread_windows.odin2
-rw-r--r--examples/demo/demo.odin1
12 files changed, 129 insertions, 54 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c9c453331..94f6bef12 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -97,7 +97,7 @@ jobs:
- name: Download LLVM (MacOS ARM)
if: matrix.os == 'macos-14'
run: |
- brew install llvm@17
+ brew install llvm@17 wasmtime
echo "/opt/homebrew/opt/llvm@17/bin" >> $GITHUB_PATH
- name: Build Odin
@@ -147,6 +147,12 @@ jobs:
run: ./odin check examples/all -vet -strict-style -target:openbsd_amd64
if: matrix.os == 'ubuntu-latest'
+ - name: Run demo on WASI WASM32
+ run: |
+ ./odin build examples/demo -target:wasi_wasm32 -vet -strict-style -out:demo.wasm
+ wasmtime ./demo.wasm
+ if: matrix.os == 'macos-14'
+
build_windows:
name: Windows Build, Check, and Test
runs-on: windows-2022
diff --git a/base/runtime/entry_wasm.odin b/base/runtime/entry_wasm.odin
index a24c6f4b7..99cd8201d 100644
--- a/base/runtime/entry_wasm.odin
+++ b/base/runtime/entry_wasm.odin
@@ -22,6 +22,11 @@ when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
@(link_name="_start", linkage="strong", require, export)
_start :: proc "c" () {
context = default_context()
+
+ when ODIN_OS == .WASI {
+ _wasi_setup_args()
+ }
+
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
}
diff --git a/base/runtime/os_specific_wasi.odin b/base/runtime/os_specific_wasi.odin
index 0e229ac7e..b85d7adea 100644
--- a/base/runtime/os_specific_wasi.odin
+++ b/base/runtime/os_specific_wasi.odin
@@ -2,10 +2,54 @@
//+private
package runtime
-import "core:sys/wasm/wasi"
+foreign import wasi "wasi_snapshot_preview1"
+
+@(default_calling_convention="contextless")
+foreign wasi {
+ fd_write :: proc(
+ fd: i32,
+ iovs: [][]byte,
+ n: ^uint,
+ ) -> u16 ---
+
+ @(private="file")
+ args_sizes_get :: proc(
+ num_of_args: ^uint,
+ size_of_args: ^uint,
+ ) -> u16 ---
+
+ @(private="file")
+ args_get :: proc(
+ argv: [^]cstring,
+ argv_buf: [^]byte,
+ ) -> u16 ---
+}
_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
- data_iovec := (wasi.ciovec_t)(data)
- n, err := wasi.fd_write(1, {data_iovec})
+ n: uint
+ err := fd_write(1, {data}, &n)
return int(n), _OS_Errno(err)
}
+
+_wasi_setup_args :: proc() {
+ num_of_args, size_of_args: uint
+ if errno := args_sizes_get(&num_of_args, &size_of_args); errno != 0 {
+ return
+ }
+
+ err: Allocator_Error
+ if args__, err = make([]cstring, num_of_args); err != nil {
+ return
+ }
+
+ args_buf: []byte
+ if args_buf, err = make([]byte, size_of_args); err != nil {
+ delete(args__)
+ return
+ }
+
+ if errno := args_get(raw_data(args__), raw_data(args_buf)); errno != 0 {
+ delete(args__)
+ delete(args_buf)
+ }
+}
diff --git a/base/runtime/wasm_allocator.odin b/base/runtime/wasm_allocator.odin
index fb0600ea2..f4b399c47 100644
--- a/base/runtime/wasm_allocator.odin
+++ b/base/runtime/wasm_allocator.odin
@@ -760,7 +760,7 @@ free :: proc(a: ^WASM_Allocator, ptr: rawptr, loc := #caller_location) {
defer unlock(a)
size := region.size
- assert(region_is_in_use(region), "double free", loc=loc)
+ assert(region_is_in_use(region), "double free or corrupt region", loc=loc)
prev_region_size_field := ([^]uint)(region)[-1]
prev_region_size := prev_region_size_field & ~uint(FREE_REGION_FLAG)
diff --git a/core/encoding/cbor/tags.odin b/core/encoding/cbor/tags.odin
index 3dc79a5dd..17420af46 100644
--- a/core/encoding/cbor/tags.odin
+++ b/core/encoding/cbor/tags.odin
@@ -95,7 +95,6 @@ tag_register_number :: proc(impl: Tag_Implementation, nr: Tag_Number, id: string
}
// Controls initialization of default tag implementations.
-// JS and WASI default to a panic allocator so we don't want to do it on those.
INITIALIZE_DEFAULT_TAGS :: #config(CBOR_INITIALIZE_DEFAULT_TAGS, !ODIN_DEFAULT_TO_PANIC_ALLOCATOR && !ODIN_DEFAULT_TO_NIL_ALLOCATOR)
@(private, init, disabled=!INITIALIZE_DEFAULT_TAGS)
diff --git a/core/os/os_wasi.odin b/core/os/os_wasi.odin
index 9bfd87322..8a1acb194 100644
--- a/core/os/os_wasi.odin
+++ b/core/os/os_wasi.odin
@@ -6,6 +6,8 @@ import "base:runtime"
Handle :: distinct i32
Errno :: distinct i32
+INVALID_HANDLE :: -1
+
ERROR_NONE :: Errno(wasi.errno_t.SUCCESS)
O_RDONLY :: 0x00000
@@ -26,6 +28,16 @@ stdout: Handle = 1
stderr: Handle = 2
current_dir: Handle = 3
+args := _alloc_command_line_arguments()
+
+_alloc_command_line_arguments :: proc() -> (args: []string) {
+ args = make([]string, len(runtime.args__))
+ for &arg, i in args {
+ arg = string(runtime.args__[i])
+ }
+ return
+}
+
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
iovs := wasi.ciovec_t(data)
n, err := wasi.fd_write(wasi.fd_t(fd), {iovs})
diff --git a/core/thread/thread.odin b/core/thread/thread.odin
index 55f73d106..80e60d6cf 100644
--- a/core/thread/thread.odin
+++ b/core/thread/thread.odin
@@ -6,6 +6,8 @@ import "base:intrinsics"
_ :: intrinsics
+IS_SUPPORTED :: _IS_SUPPORTED
+
Thread_Proc :: #type proc(^Thread)
MAX_USER_ARGUMENTS :: 8
@@ -58,7 +60,9 @@ Thread :: struct {
creation_allocator: mem.Allocator,
}
-#assert(size_of(Thread{}.user_index) == size_of(uintptr))
+when IS_SUPPORTED {
+ #assert(size_of(Thread{}.user_index) == size_of(uintptr))
+}
Thread_Priority :: enum {
Normal,
diff --git a/core/thread/thread_js.odin b/core/thread/thread_js.odin
deleted file mode 100644
index 4f5b5b086..000000000
--- a/core/thread/thread_js.odin
+++ /dev/null
@@ -1,47 +0,0 @@
-//+build js
-package thread
-
-import "base:intrinsics"
-import "core:sync"
-import "core:mem"
-
-Thread_Os_Specific :: struct {}
-
-_thread_priority_map := [Thread_Priority]i32{
- .Normal = 0,
- .Low = -2,
- .High = +2,
-}
-
-_create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread {
- unimplemented("core:thread procedure not supported on js target")
-}
-
-_start :: proc(t: ^Thread) {
- unimplemented("core:thread procedure not supported on js target")
-}
-
-_is_done :: proc(t: ^Thread) -> bool {
- unimplemented("core:thread procedure not supported on js target")
-}
-
-_join :: proc(t: ^Thread) {
- unimplemented("core:thread procedure not supported on js target")
-}
-
-_join_multiple :: proc(threads: ..^Thread) {
- unimplemented("core:thread procedure not supported on js target")
-}
-
-_destroy :: proc(thread: ^Thread) {
- unimplemented("core:thread procedure not supported on js target")
-}
-
-_terminate :: proc(using thread : ^Thread, exit_code: int) {
- unimplemented("core:thread procedure not supported on js target")
-}
-
-_yield :: proc() {
- unimplemented("core:thread procedure not supported on js target")
-}
-
diff --git a/core/thread/thread_other.odin b/core/thread/thread_other.odin
new file mode 100644
index 000000000..34bbfda08
--- /dev/null
+++ b/core/thread/thread_other.odin
@@ -0,0 +1,47 @@
+//+build js, wasi, orca
+package thread
+
+import "base:intrinsics"
+
+_IS_SUPPORTED :: false
+
+Thread_Os_Specific :: struct {}
+
+_thread_priority_map := [Thread_Priority]i32{
+ .Normal = 0,
+ .Low = -2,
+ .High = +2,
+}
+
+_create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread {
+ unimplemented("core:thread procedure not supported on target")
+}
+
+_start :: proc(t: ^Thread) {
+ unimplemented("core:thread procedure not supported on target")
+}
+
+_is_done :: proc(t: ^Thread) -> bool {
+ unimplemented("core:thread procedure not supported on target")
+}
+
+_join :: proc(t: ^Thread) {
+ unimplemented("core:thread procedure not supported on target")
+}
+
+_join_multiple :: proc(threads: ..^Thread) {
+ unimplemented("core:thread procedure not supported on target")
+}
+
+_destroy :: proc(thread: ^Thread) {
+ unimplemented("core:thread procedure not supported on target")
+}
+
+_terminate :: proc(using thread : ^Thread, exit_code: int) {
+ unimplemented("core:thread procedure not supported on target")
+}
+
+_yield :: proc() {
+ unimplemented("core:thread procedure not supported on target")
+}
+
diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin
index 2218afdd3..363f50862 100644
--- a/core/thread/thread_unix.odin
+++ b/core/thread/thread_unix.odin
@@ -6,6 +6,8 @@ import "core:sync"
import "core:sys/unix"
import "core:time"
+_IS_SUPPORTED :: true
+
CAS :: sync.atomic_compare_exchange_strong
// NOTE(tetra): Aligned here because of core/unix/pthread_linux.odin/pthread_t.
diff --git a/core/thread/thread_windows.odin b/core/thread/thread_windows.odin
index 314ef5842..8da75a2d9 100644
--- a/core/thread/thread_windows.odin
+++ b/core/thread/thread_windows.odin
@@ -6,6 +6,8 @@ import "base:intrinsics"
import "core:sync"
import win32 "core:sys/windows"
+_IS_SUPPORTED :: true
+
Thread_Os_Specific :: struct {
win32_thread: win32.HANDLE,
win32_thread_id: win32.DWORD,
diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin
index e27686099..0ad9f4ab0 100644
--- a/examples/demo/demo.odin
+++ b/examples/demo/demo.odin
@@ -1140,6 +1140,7 @@ prefix_table := [?]string{
print_mutex := b64(false)
+@(disabled=!thread.IS_SUPPORTED)
threading_example :: proc() {
fmt.println("\n# threading_example")