mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 06:38:47 +00:00
wasi: make the demo run on wasi and run it in CI
This commit is contained in:
@@ -97,7 +97,7 @@ jobs:
|
|||||||
- name: Download LLVM (MacOS ARM)
|
- name: Download LLVM (MacOS ARM)
|
||||||
if: matrix.os == 'macos-14'
|
if: matrix.os == 'macos-14'
|
||||||
run: |
|
run: |
|
||||||
brew install llvm@17
|
brew install llvm@17 wasmtime
|
||||||
echo "/opt/homebrew/opt/llvm@17/bin" >> $GITHUB_PATH
|
echo "/opt/homebrew/opt/llvm@17/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
- name: Build Odin
|
- name: Build Odin
|
||||||
@@ -147,6 +147,12 @@ jobs:
|
|||||||
run: ./odin check examples/all -vet -strict-style -target:openbsd_amd64
|
run: ./odin check examples/all -vet -strict-style -target:openbsd_amd64
|
||||||
if: matrix.os == 'ubuntu-latest'
|
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:
|
build_windows:
|
||||||
name: Windows Build, Check, and Test
|
name: Windows Build, Check, and Test
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
|
|||||||
@(link_name="_start", linkage="strong", require, export)
|
@(link_name="_start", linkage="strong", require, export)
|
||||||
_start :: proc "c" () {
|
_start :: proc "c" () {
|
||||||
context = default_context()
|
context = default_context()
|
||||||
|
|
||||||
|
when ODIN_OS == .WASI {
|
||||||
|
_wasi_setup_args()
|
||||||
|
}
|
||||||
|
|
||||||
#force_no_inline _startup_runtime()
|
#force_no_inline _startup_runtime()
|
||||||
intrinsics.__entry_point()
|
intrinsics.__entry_point()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,54 @@
|
|||||||
//+private
|
//+private
|
||||||
package runtime
|
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) {
|
_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
|
||||||
data_iovec := (wasi.ciovec_t)(data)
|
n: uint
|
||||||
n, err := wasi.fd_write(1, {data_iovec})
|
err := fd_write(1, {data}, &n)
|
||||||
return int(n), _OS_Errno(err)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -760,7 +760,7 @@ free :: proc(a: ^WASM_Allocator, ptr: rawptr, loc := #caller_location) {
|
|||||||
defer unlock(a)
|
defer unlock(a)
|
||||||
|
|
||||||
size := region.size
|
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_field := ([^]uint)(region)[-1]
|
||||||
prev_region_size := prev_region_size_field & ~uint(FREE_REGION_FLAG)
|
prev_region_size := prev_region_size_field & ~uint(FREE_REGION_FLAG)
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ tag_register_number :: proc(impl: Tag_Implementation, nr: Tag_Number, id: string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Controls initialization of default tag implementations.
|
// 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)
|
INITIALIZE_DEFAULT_TAGS :: #config(CBOR_INITIALIZE_DEFAULT_TAGS, !ODIN_DEFAULT_TO_PANIC_ALLOCATOR && !ODIN_DEFAULT_TO_NIL_ALLOCATOR)
|
||||||
|
|
||||||
@(private, init, disabled=!INITIALIZE_DEFAULT_TAGS)
|
@(private, init, disabled=!INITIALIZE_DEFAULT_TAGS)
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import "base:runtime"
|
|||||||
Handle :: distinct i32
|
Handle :: distinct i32
|
||||||
Errno :: distinct i32
|
Errno :: distinct i32
|
||||||
|
|
||||||
|
INVALID_HANDLE :: -1
|
||||||
|
|
||||||
ERROR_NONE :: Errno(wasi.errno_t.SUCCESS)
|
ERROR_NONE :: Errno(wasi.errno_t.SUCCESS)
|
||||||
|
|
||||||
O_RDONLY :: 0x00000
|
O_RDONLY :: 0x00000
|
||||||
@@ -26,6 +28,16 @@ stdout: Handle = 1
|
|||||||
stderr: Handle = 2
|
stderr: Handle = 2
|
||||||
current_dir: Handle = 3
|
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) {
|
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||||
iovs := wasi.ciovec_t(data)
|
iovs := wasi.ciovec_t(data)
|
||||||
n, err := wasi.fd_write(wasi.fd_t(fd), {iovs})
|
n, err := wasi.fd_write(wasi.fd_t(fd), {iovs})
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import "base:intrinsics"
|
|||||||
|
|
||||||
_ :: intrinsics
|
_ :: intrinsics
|
||||||
|
|
||||||
|
IS_SUPPORTED :: _IS_SUPPORTED
|
||||||
|
|
||||||
Thread_Proc :: #type proc(^Thread)
|
Thread_Proc :: #type proc(^Thread)
|
||||||
|
|
||||||
MAX_USER_ARGUMENTS :: 8
|
MAX_USER_ARGUMENTS :: 8
|
||||||
@@ -58,7 +60,9 @@ Thread :: struct {
|
|||||||
creation_allocator: mem.Allocator,
|
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 {
|
Thread_Priority :: enum {
|
||||||
Normal,
|
Normal,
|
||||||
|
|||||||
@@ -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")
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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")
|
||||||
|
}
|
||||||
|
|
||||||
@@ -6,6 +6,8 @@ import "core:sync"
|
|||||||
import "core:sys/unix"
|
import "core:sys/unix"
|
||||||
import "core:time"
|
import "core:time"
|
||||||
|
|
||||||
|
_IS_SUPPORTED :: true
|
||||||
|
|
||||||
CAS :: sync.atomic_compare_exchange_strong
|
CAS :: sync.atomic_compare_exchange_strong
|
||||||
|
|
||||||
// NOTE(tetra): Aligned here because of core/unix/pthread_linux.odin/pthread_t.
|
// NOTE(tetra): Aligned here because of core/unix/pthread_linux.odin/pthread_t.
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import "base:intrinsics"
|
|||||||
import "core:sync"
|
import "core:sync"
|
||||||
import win32 "core:sys/windows"
|
import win32 "core:sys/windows"
|
||||||
|
|
||||||
|
_IS_SUPPORTED :: true
|
||||||
|
|
||||||
Thread_Os_Specific :: struct {
|
Thread_Os_Specific :: struct {
|
||||||
win32_thread: win32.HANDLE,
|
win32_thread: win32.HANDLE,
|
||||||
win32_thread_id: win32.DWORD,
|
win32_thread_id: win32.DWORD,
|
||||||
|
|||||||
@@ -1140,6 +1140,7 @@ prefix_table := [?]string{
|
|||||||
|
|
||||||
print_mutex := b64(false)
|
print_mutex := b64(false)
|
||||||
|
|
||||||
|
@(disabled=!thread.IS_SUPPORTED)
|
||||||
threading_example :: proc() {
|
threading_example :: proc() {
|
||||||
fmt.println("\n# threading_example")
|
fmt.println("\n# threading_example")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user