EMIT_FUNC(array_store, Type* type, u32 offset);
EMIT_FUNC(array_literal, AstArrayLiteral* al);
EMIT_FUNC(range_literal, AstRangeLiteral* range);
+EMIT_FUNC_NO_ARGS(load_slice);
EMIT_FUNC(if_expression, AstIfExpression* if_expr);
EMIT_FUNC(do_block, AstDoBlock* doblock);
EMIT_FUNC(expression, AstTyped* expr);
bh_arr(WasmInstruction) code = *pcode;
// Allocate temporaries for iterator contents
+ u64 iterator_base_ptr = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
+ WIL(for_node->token, WI_LOCAL_TEE, iterator_base_ptr);
+ emit_load_instruction(mod, &code, &basic_types[Basic_Kind_Rawptr], 0);
+ WIL(for_node->token, WI_LOCAL_GET, iterator_base_ptr);
+ emit_load_instruction(mod, &code, &basic_types[Basic_Kind_Rawptr], 4);
+ WIL(for_node->token, WI_LOCAL_GET, iterator_base_ptr);
+ emit_load_instruction(mod, &code, &basic_types[Basic_Kind_Rawptr], 8);
+ WIL(for_node->token, WI_LOCAL_GET, iterator_base_ptr);
+ emit_load_instruction(mod, &code, &basic_types[Basic_Kind_Rawptr], 12);
+ local_raw_free(mod->local_alloc, WASM_TYPE_PTR);
+
u64 iterator_data_ptr = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
u64 iterator_next_func = local_raw_allocate(mod->local_alloc, WASM_TYPE_FUNC);
u64 iterator_close_func = local_raw_allocate(mod->local_alloc, WASM_TYPE_FUNC);
local_raw_free(mod->local_alloc, WASM_TYPE_PTR);
local_raw_free(mod->local_alloc, WASM_TYPE_FUNC);
local_raw_free(mod->local_alloc, WASM_TYPE_FUNC);
+ local_raw_free(mod->local_alloc, WASM_TYPE_FUNC);
local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
*pcode = code;
}
// - brendanfh 2020/09/04
// - brendanfh 2021/04/13
case For_Loop_DynArr:
- WI(for_node->token, WI_DROP);
- WI(for_node->token, WI_DROP);
- WI(for_node->token, WI_DROP);
+ emit_load_slice(mod, &code);
// fallthrough
case For_Loop_Slice: emit_for_slice(mod, &code, for_node, iter_local); break;
// there should be a separate path taken to reduce the amount of redundant memory.
WIL(sl->token, WI_LOCAL_GET, mod->stack_base_idx);
emit_expression(mod, &code, *val);
- emit_store_instruction(mod, &code, (*val)->type, smem.offset);
+ emit_store_instruction(mod, &code, (*val)->type, smem.offset + local_offset);
idx += 1;
}
*pcode = code;
}
+EMIT_FUNC_NO_ARGS(load_slice) {
+ bh_arr(WasmInstruction) code = *pcode;
+
+ u64 ugly_temporary = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
+ WIL(NULL, WI_LOCAL_TEE, ugly_temporary);
+ emit_load_instruction(mod, &code, &basic_types[Basic_Kind_Rawptr], 0);
+
+ WIL(NULL, WI_LOCAL_GET, ugly_temporary);
+ emit_load_instruction(mod, &code, &basic_types[Basic_Kind_I32], POINTER_SIZE);
+
+ local_raw_free(mod->local_alloc, WASM_TYPE_PTR);
+
+ *pcode = code;
+}
+
EMIT_FUNC(if_expression, AstIfExpression* if_expr) {
bh_arr(WasmInstruction) code = *pcode;
case Ast_Kind_Array_Literal:
case Ast_Kind_Struct_Literal:
case Ast_Kind_Do_Block:
- case Ast_Kind_If_Expression: {
+ case Ast_Kind_If_Expression:
+ case Ast_Kind_Call_Site: {
emit_local_location(mod, &code, (AstLocal *) expr, offset_return);
break;
}
case Ast_Kind_Call_Site: {
AstCallSite* callsite = (AstCallSite *) expr;
+ emit_local_allocation(mod, &code, (AstTyped *) callsite);
+
+ u64 local_offset = (u64) bh_imap_get(&mod->local_map, (u64) callsite);
+ assert((local_offset & LOCAL_IS_WASM) == 0);
+
+ StructMember smem;
+
+ type_lookup_member_by_idx(callsite->type, 0, &smem);
+ WIL(NULL, WI_LOCAL_GET, mod->stack_base_idx);
emit_expression(mod, &code, (AstTyped *) callsite->filename);
+ emit_store_instruction(mod, &code, smem.type, local_offset + smem.offset);
+
+ type_lookup_member_by_idx(callsite->type, 1, &smem);
+ WIL(NULL, WI_LOCAL_GET, mod->stack_base_idx);
emit_expression(mod, &code, (AstTyped *) callsite->line);
+ emit_store_instruction(mod, &code, smem.type, local_offset + smem.offset);
+
+ type_lookup_member_by_idx(callsite->type, 2, &smem);
+ WIL(NULL, WI_LOCAL_GET, mod->stack_base_idx);
emit_expression(mod, &code, (AstTyped *) callsite->column);
+ emit_store_instruction(mod, &code, smem.type, local_offset + smem.offset);
+
+ WIL(NULL, WI_LOCAL_GET, mod->stack_base_idx);
+ WIL(NULL, WI_PTR_CONST, local_offset);
+ WI(NULL, WI_PTR_ADD);
break;
}
}
if (to->kind == Type_Kind_Slice && from->kind == Type_Kind_DynArray) {
- WI(NULL, WI_DROP);
- WI(NULL, WI_DROP);
- WI(NULL, WI_DROP);
+ emit_load_slice(mod, &code);
*pcode = code;
return;
}
use package core
-FileData :: struct {
- Handle :: #distinct i64
-
- handle: Handle = -1;
-}
-
+FileData :: #distinct i64
DirectoryData :: #distinct u64
__file_open :: (path: str, mode := os.OpenMode.Read) -> (FileData, os.FileError) {
- handle: FileData.Handle;
+ handle: FileData;
error := __file_open_impl(path, mode, ^handle);
- fd := FileData.{ handle };
- return fd, error;
+ return handle, error;
}
#foreign "onyx_runtime" {
- __file_open_impl :: (path: str, mode: os.OpenMode, out_handle: ^FileData.Handle) -> os.FileError ---
+ __file_open_impl :: (path: str, mode: os.OpenMode, out_handle: ^FileData) -> os.FileError ---
__file_close :: (fd: FileData) -> os.FileError ---
__file_stat :: (path: str, stat: ^os.FileStat) -> bool ---
__file_remove :: (path: str) -> bool ---
__file_rename :: (old_path: str, new_path: str) -> bool ---
- __file_seek :: (handle: FileData.Handle, to: i32, whence: io.SeekFrom) -> i32 ---
- __file_tell :: (handle: FileData.Handle) -> u32 ---
- __file_read :: (handle: FileData.Handle, output_buffer: [] u8, bytes_read: ^u64) -> io.Error ---
- __file_write :: (handle: FileData.Handle, input_buffer: [] u8, bytes_wrote: ^u64) -> io.Error ---
- __file_flush :: (handle: FileData.Handle) -> io.Error ---
- __file_size :: (handle: FileData.Handle) -> u32 ---
+ __file_seek :: (handle: FileData, to: i32, whence: io.SeekFrom) -> i32 ---
+ __file_tell :: (handle: FileData) -> u32 ---
+ __file_read :: (handle: FileData, output_buffer: [] u8, bytes_read: ^u64) -> io.Error ---
+ __file_write :: (handle: FileData, input_buffer: [] u8, bytes_wrote: ^u64) -> io.Error ---
+ __file_flush :: (handle: FileData) -> io.Error ---
+ __file_size :: (handle: FileData) -> u32 ---
__dir_open :: (path: str, dir: ^DirectoryData) -> bool ---
__dir_close :: (dir: DirectoryData) -> void ---
__file_stream_vtable := io.Stream_Vtable.{
seek = (use fs: ^os.File, to: i32, whence: io.SeekFrom) -> io.Error {
- now := __file_seek(data.handle, to, whence);
+ now := __file_seek(data, to, whence);
return (.None) if now >= 0 else .BadFile;
},
tell = (use fs: ^os.File) -> (io.Error, u32) {
- return .None, __file_tell(data.handle);
+ return .None, __file_tell(data);
},
read = (use fs: ^os.File, buffer: [] u8) -> (io.Error, u32) {
bytes_read: u64;
- error := __file_read(data.handle, buffer, ^bytes_read);
+ error := __file_read(data, buffer, ^bytes_read);
return error, ~~bytes_read;
},
read_at = (use fs: ^os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
- __file_seek(data.handle, at, .Start);
+ __file_seek(data, at, .Start);
bytes_read: u64;
- error := __file_read(data.handle, buffer, ^bytes_read);
+ error := __file_read(data, buffer, ^bytes_read);
return error, ~~bytes_read;
},
read_byte = (use fs: ^os.File) -> (io.Error, u8) {
byte: u8;
- error := __file_read(data.handle, ~~ cast([1] u8) ^byte, null);
+ error := __file_read(data, ~~ cast([1] u8) ^byte, null);
return error, byte;
},
write = (use fs: ^os.File, buffer: [] u8) -> (io.Error, u32) {
bytes_wrote: u64;
- error := __file_write(data.handle, buffer, ^bytes_wrote);
+ error := __file_write(data, buffer, ^bytes_wrote);
return error, ~~bytes_wrote;
},
write_at = (use fs: ^os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
- __file_seek(data.handle, at, .Start);
+ __file_seek(data, at, .Start);
bytes_wrote: u64;
- error := __file_write(data.handle, buffer, ^bytes_wrote);
+ error := __file_write(data, buffer, ^bytes_wrote);
return error, ~~bytes_wrote;
},
write_byte = (use fs: ^os.File, byte: u8) -> io.Error {
b := byte;
bytes_wrote: u64;
- error := __file_write(data.handle, .{ ^b, 1 }, ^bytes_wrote);
+ error := __file_write(data, .{ ^b, 1 }, ^bytes_wrote);
return error;
},
},
flush = (use fs: ^os.File) -> io.Error {
- return __file_flush(data.handle);
+ return __file_flush(data);
},
size = (use fs: ^os.File) -> i32 {
- return __file_size(data.handle);
+ return __file_size(data);
},
};
File :: struct {
use stream : io.Stream;
- use data : fs.FileData;
+ data : fs.FileData;
}
// Most of these types were stollen directly from
#library "onyx_runtime"
#foreign "onyx_runtime" {
- __file_get_standard :: (fd: i32, out: ^fs.FileData.Handle) -> bool ---
+ __file_get_standard :: (fd: i32, out: ^fs.FileData) -> bool ---
__args_get :: (argv: ^^u8, arg_buf: ^u8) -> void ---
__args_sizes_get :: (argc: ^i32, arg_buf_size: ^i32) -> void ---
}
#export "_start" () {
- fd: fs.FileData.Handle;
+ fd: fs.FileData;
__file_get_standard(1, ^fd);
__stdout = .{
.{ ^fs.__file_stream_vtable },
- .{ fd },
+ fd
};
__file_get_standard(2, ^fd);
__stderr = .{
.{ ^fs.__file_stream_vtable },
- .{ fd },
+ fd
};
__file_get_standard(0, ^fd);
__stdin = .{
.{ ^fs.__file_stream_vtable },
- .{ fd },
+ fd
};
__runtime_initialize();
vec := IOVec.{ buf = cast(u32) s.data, len = s.count };
tmp : Size;
- fd_write(STDOUT_FILENO, IOVecArray.{ cast(u32) ^vec, 1 }, ^tmp);
+ fd_write(STDOUT_FILENO, ^vec, 1, ^tmp);
fd_datasync(STDOUT_FILENO);
return tmp;
}
vec := IOVec.{ buf = cast(i32) buffer.data, len = buffer.count };
read: Size;
- error := fd_read(STDIN_FILENO, .{ cast(i32) ^vec, 1 }, ^read);
+ error := fd_read(STDIN_FILENO, ^vec, 1, ^read);
if error != .Success do return -1;
return read;
};
}
-IOVecArray :: struct {
- iovs : u32; // actually ^IOVec; see comment above
- iovs_len : Size;
-}
-
// FUNCTIONS
args_get :: (argv: ^^u8, argv_buf: ^u8) -> Errno #foreign "wasi_snapshot_preview1" "args_get"---
fd_filestat_get :: (fd: FileDescriptor, buf: ^FileStat) -> Errno #foreign "wasi_snapshot_preview1" "fd_filestat_get" ---
fd_filestat_set_size :: (fd: FileDescriptor, size: Filesize) -> Errno #foreign "wasi_snapshot_preview1" "fd_filestat_set_size" ---
fd_filestat_set_times :: (fd: FileDescriptor, atim: Timestamp, mtim: Timestamp, fst_flags: FSTFlags) -> Errno #foreign "wasi_snapshot_preview1" "fd_filestat_set_times" ---
-fd_pread :: (fd: FileDescriptor, iovs: IOVecArray, offset: Filesize, nread: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_pread" ---
+fd_pread :: (fd: FileDescriptor, iovs: ^IOVec, iovs_len: Size, offset: Filesize, nread: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_pread" ---
fd_prestat_get :: (fd: FileDescriptor, buf: ^PrestatTagged) -> Errno #foreign "wasi_snapshot_preview1" "fd_prestat_get" ---
fd_prestat_dir_name :: (fd: FileDescriptor, path: str) -> Errno #foreign "wasi_snapshot_preview1" "fd_prestat_dir_name" ---
-fd_pwrite :: (fd: FileDescriptor, iovs: IOVecArray, offset: Filesize, nwritten: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_pwrite" ---
-fd_read :: (fd: FileDescriptor, iovs: IOVecArray, nread: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_read" ---
+fd_pwrite :: (fd: FileDescriptor, iovs: ^IOVec, iovs_len: Size, offset: Filesize, nwritten: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_pwrite" ---
+fd_read :: (fd: FileDescriptor, iovs: ^IOVec, iovs_len: Size, nread: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_read" ---
fd_readdir :: (fd: FileDescriptor, buf: ^u8, buf_len: Size, cookie: DirCookie, bufused: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_readdir" ---
fd_renumber :: (fd: FileDescriptor, to: FileDescriptor) -> Errno #foreign "wasi_snapshot_preview1" "fd_renumber" ---
fd_seek :: (fd: FileDescriptor, offset: FileDelta, whence: Whence, newoffset: ^Filesize) -> Errno #foreign "wasi_snapshot_preview1" "fd_seek" ---
fd_sync :: (fd: FileDescriptor) -> Errno #foreign "wasi_snapshot_preview1" "fd_sync" ---
fd_tell :: (fd: FileDescriptor, offset: ^Filesize) -> Errno #foreign "wasi_snapshot_preview1" "fd_tell" ---
-fd_write :: (fd: FileDescriptor, iovs: IOVecArray, nwritten: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_write" ---
+fd_write :: (fd: FileDescriptor, iovs: ^IOVec, iovs_len: Size, nwritten: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_write" ---
path_create_directory :: (fd: FileDescriptor, path: str) -> Errno #foreign "wasi_snapshot_preview1" "path_create_directory" ---
path_filestat_get :: (fd: FileDescriptor, flags: LookupFlags, path: str, buf: ^FileStat) -> Errno #foreign "wasi_snapshot_preview1" "path_filestat_get" ---
random_get :: (buf: ^u8, buf_len: Size) -> Errno #foreign "wasi_snapshot_preview1" "random_get" ---
-sock_recv :: (fd: FileDescriptor, ri_data: IOVecArray, ri_flags: RIFlags, ro_datalen: ^Size, ro_flags: ^ROFlags) -> Errno #foreign "wasi_snapshot_preview1" "sock_recv" ---
-sock_send :: (fd: FileDescriptor, si_data: IOVecArray, si_flags: SIFlags, so_datalen: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "sock_send" ---
+sock_recv :: (fd: FileDescriptor, ri_data: ^IOVec, ri_data_len: Size, ri_flags: RIFlags, ro_datalen: ^Size, ro_flags: ^ROFlags) -> Errno #foreign "wasi_snapshot_preview1" "sock_recv" ---
+sock_send :: (fd: FileDescriptor, si_data: ^IOVec, ri_data_len: Size, si_flags: SIFlags, so_datalen: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "sock_send" ---
sock_shutdown :: (fd: FileDescriptor, how: SDFlags) -> Errno #foreign "wasi_snapshot_preview1" "sock_shutdown" ---
FileDescriptor,
FDFlags, OFlags, Rights,
LookupFlags, Errno,
- IOVec, IOVecArray, Size,
+ IOVec, Size,
FileStat, Whence
}
read = (use fs: ^os.File, buffer: [] u8) -> (io.Error, u32) {
bytes_read : wasi.Size;
vec := IOVec.{ buf = cast(u32) buffer.data, len = buffer.count };
- error := wasi.fd_read(data.fd, IOVecArray.{ cast(u32) ^vec, 1 }, ^bytes_read);
+ error := wasi.fd_read(data.fd, ^vec, 1, ^bytes_read);
if error != .Success do return .BadFile, 0;
return .None, bytes_read;
read_at = (use fs: ^os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
bytes_read : wasi.Size;
vec := IOVec.{ buf = cast(u32) buffer.data, len = buffer.count };
- error := wasi.fd_pread(data.fd, IOVecArray.{ cast(u32) ^vec, 1 }, ~~at, ^bytes_read);
+ error := wasi.fd_pread(data.fd, ^vec, 1, ~~at, ^bytes_read);
// FIX: Maybe report io.Error.OutOfBounds if the 'at' was out of bounds?
if error != .Success do return .BadFile, 0;
bytes_read : wasi.Size;
byte : u8;
vec := IOVec.{ buf = cast(u32) ^byte, len = 1};
- error := wasi.fd_read(data.fd, IOVecArray.{ cast(u32) ^vec, 1 }, ^bytes_read);
+ error := wasi.fd_read(data.fd, ^vec, 1, ^bytes_read);
if error != .Success do return .BadFile, 0;
return .None, byte;
write = (use fs: ^os.File, buffer: [] u8) -> (io.Error, u32) {
bytes_written : wasi.Size;
vec := IOVec.{ buf = cast(u32) buffer.data, len = buffer.count };
- error := wasi.fd_write(data.fd, IOVecArray.{ cast(u32) ^vec, 1 }, ^bytes_written);
+ error := wasi.fd_write(data.fd, ^vec, 1, ^bytes_written);
if error != .Success do return .BadFile, 0;
return .None, bytes_written;
write_at = (use fs: ^os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
bytes_written : wasi.Size;
vec := IOVec.{ buf = cast(u32) buffer.data, len = buffer.count };
- error := wasi.fd_pwrite(data.fd, IOVecArray.{ cast(u32) ^vec, 1 }, ~~at, ^bytes_written);
+ error := wasi.fd_pwrite(data.fd, ^vec, 1, ~~at, ^bytes_written);
// FIX: Maybe report io.Error.OutOfBounds if the 'at' was out of bounds?
if error != .Success do return .BadFile, 0;
bytes_written : wasi.Size;
byte_to_write := byte;
vec := IOVec.{ buf = cast(u32) ^byte_to_write, len = 1 };
- error := wasi.fd_write(data.fd, IOVecArray.{ cast(u32) ^vec, 1 }, ^bytes_written);
+ error := wasi.fd_write(data.fd, ^vec, 1, ^bytes_written);
if error != .Success do return .BadFile;
return .None;