From: Brendan Hansen Date: Wed, 19 Apr 2023 04:25:19 +0000 (-0500) Subject: changed: function pointers now have a closure pointer X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=b4d4e8ac65ae8b807c9a4ad7d4d312dd68c72f87;p=onyx.git changed: function pointers now have a closure pointer --- diff --git a/compiler/src/checker.c b/compiler/src/checker.c index abafdefe..7112f11b 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -2158,17 +2158,6 @@ CheckStatus check_expression(AstTyped** pexpr) { break; case Ast_Kind_Function: - // NOTE: Will need something like this at some point - // AstFunction* func = (AstFunction *) expr; - // bh_arr_each(AstParam, param, func->params) { - // if (param->default_value != NULL) { - // onyx_message_add(Msg_Type_Literal, - // func->token->pos, - // "cannot use functions with default parameters in this way"); - // retval = 1; - // break; - // } - // } if (expr->type == NULL) YIELD(expr->token->pos, "Waiting for function type to be resolved."); diff --git a/compiler/src/types.c b/compiler/src/types.c index f03c91a2..953163cc 100644 --- a/compiler/src/types.c +++ b/compiler/src/types.c @@ -251,13 +251,13 @@ u32 type_size_of(Type* type) { case Type_Kind_Basic: return type->Basic.size; case Type_Kind_MultiPointer: case Type_Kind_Pointer: return POINTER_SIZE; - case Type_Kind_Function: return 4; + case Type_Kind_Function: return 2 * POINTER_SIZE; case Type_Kind_Array: return type->Array.size; case Type_Kind_Struct: return type->Struct.size; case Type_Kind_Enum: return type_size_of(type->Enum.backing); case Type_Kind_Slice: return POINTER_SIZE * 2; // HACK: These should not have to be 16 bytes in size, they should only have to be 12, case Type_Kind_VarArgs: return POINTER_SIZE * 2; // but there are alignment issues right now with that so I decided to not fight it and just make them 16 bytes in size. - case Type_Kind_DynArray: return POINTER_SIZE + 8 + 2 * POINTER_SIZE; // data (8), count (4), capacity (4), allocator { func (4), ---(4), data (8) } + case Type_Kind_DynArray: return POINTER_SIZE + 8 + 4 * POINTER_SIZE; // data (8), count (4), capacity (4), allocator { func (8), data (8) } case Type_Kind_Compound: return type->Compound.size; case Type_Kind_Distinct: return type_size_of(type->Distinct.base_type); default: return 0; @@ -271,7 +271,7 @@ u32 type_alignment_of(Type* type) { case Type_Kind_Basic: return type->Basic.alignment; case Type_Kind_MultiPointer: case Type_Kind_Pointer: return POINTER_SIZE; - case Type_Kind_Function: return 4; + case Type_Kind_Function: return POINTER_SIZE; case Type_Kind_Array: return type_alignment_of(type->Array.elem); case Type_Kind_Struct: return type->Struct.alignment; case Type_Kind_Enum: return type_alignment_of(type->Enum.backing); @@ -991,7 +991,7 @@ void build_linear_types_with_offset(Type* type, bh_arr(TypeWithOffset)* pdest, u elem_offset += bh_max(type_size_of(type->Compound.types[i]), 4); } - } else if (type->kind == Type_Kind_Slice || type->kind == Type_Kind_VarArgs) { + } else if (type->kind == Type_Kind_Slice || type->kind == Type_Kind_VarArgs || type->kind == Type_Kind_Function) { u32 mem_count = type_structlike_mem_count(type); StructMember smem = { 0 }; fori (i, 0, mem_count) { @@ -1252,6 +1252,11 @@ static const StructMember array_members[] = { { POINTER_SIZE, 1, &basic_types[Basic_Kind_U32], "length", NULL, NULL, -1, 0, 0 }, }; +static const StructMember func_members[] = { + { 0, 0, &basic_types[Basic_Kind_U32], "__funcidx", NULL, NULL, -1, 0, 0 }, + { POINTER_SIZE, 1, &basic_types[Basic_Kind_Rawptr], "data", NULL, NULL, -1, 0, 0 }, +}; + b32 type_lookup_member(Type* type, char* member, StructMember* smem) { if (type->kind == Type_Kind_Pointer) type = type->Pointer.elem; @@ -1291,6 +1296,15 @@ b32 type_lookup_member(Type* type, char* member, StructMember* smem) { return 0; } + case Type_Kind_Function: { + fori (i, 0, (i64) (sizeof(func_members) / sizeof(StructMember))) { + if (strcmp(func_members[i].name, member) == 0) { + *smem = func_members[i]; + return 1; + } + } + } + default: return 0; } } @@ -1329,6 +1343,13 @@ b32 type_lookup_member_by_idx(Type* type, i32 idx, StructMember* smem) { return 1; } + case Type_Kind_Function: { + if (idx > 2) return 0; + + *smem = func_members[idx]; + return 1; + } + default: return 0; } } @@ -1338,6 +1359,7 @@ i32 type_linear_member_count(Type* type) { switch (type->kind) { case Type_Kind_Slice: case Type_Kind_VarArgs: return 2; + case Type_Kind_Function: return 2; case Type_Kind_Compound: return bh_arr_length(type->Compound.linear_members); default: return 1; } @@ -1386,6 +1408,17 @@ b32 type_linear_member_lookup(Type* type, i32 idx, TypeWithOffset* two) { two->offset = 0; return 1; + case Type_Kind_Function: + if (idx == 0) { + two->type = &basic_types[Basic_Kind_U32]; + two->offset = 0; + } + if (idx == 1) { + two->type = &basic_types[Basic_Kind_Rawptr]; + two->offset = POINTER_SIZE; + } + return 1; + default: { if (idx > 0) return 0; two->offset = 0; @@ -1420,6 +1453,11 @@ i32 type_get_idx_of_linear_member_with_offset(Type* type, u32 offset) { return -1; } + case Type_Kind_Function: { + if (offset == 0) return 0; + if (offset == POINTER_SIZE) return 1; + return -1; + } default: if (offset == 0) return 0; return -1; @@ -1499,10 +1537,10 @@ b32 type_is_simd(Type* type) { b32 type_results_in_void(Type* type) { return (type == NULL) - || (type->kind == Type_Kind_Basic && type->Basic.kind == Basic_Kind_Void) - || ( (type->kind == Type_Kind_Function) - && (type->Function.return_type->kind == Type_Kind_Basic) - && (type->Function.return_type->Basic.kind == Basic_Kind_Void)); + || (type->kind == Type_Kind_Basic && type->Basic.kind == Basic_Kind_Void); + // || ( (type->kind == Type_Kind_Function) + // && (type->Function.return_type->kind == Type_Kind_Basic) + // && (type->Function.return_type->Basic.kind == Basic_Kind_Void)); } b32 type_is_array_accessible(Type* type) { @@ -1521,6 +1559,7 @@ b32 type_is_structlike(Type* type) { if (type->kind == Type_Kind_Array) return 1; if (type->kind == Type_Kind_Struct) return 1; if (type->kind == Type_Kind_Slice) return 1; + if (type->kind == Type_Kind_Function) return 1; if (type->kind == Type_Kind_DynArray) return 1; if (type->kind == Type_Kind_VarArgs) return 1; if (type->kind == Type_Kind_Pointer) { @@ -1536,6 +1575,7 @@ b32 type_is_structlike_strict(Type* type) { if (type->kind == Type_Kind_Struct) return 1; if (type->kind == Type_Kind_Slice) return 1; if (type->kind == Type_Kind_DynArray) return 1; + if (type->kind == Type_Kind_Function) return 1; if (type->kind == Type_Kind_VarArgs) return 1; return 0; } @@ -1546,6 +1586,7 @@ u32 type_structlike_mem_count(Type* type) { case Type_Kind_Struct: return type->Struct.mem_count; case Type_Kind_Slice: return 2; case Type_Kind_VarArgs: return 2; + case Type_Kind_Function: return 2; case Type_Kind_DynArray: return 4; default: return 0; } @@ -1556,6 +1597,7 @@ u32 type_structlike_is_simple(Type* type) { switch (type->kind) { case Type_Kind_Slice: return 1; case Type_Kind_VarArgs: return 1; + case Type_Kind_Function: return 1; case Type_Kind_DynArray: return 0; case Type_Kind_Struct: return 0; default: return 0; diff --git a/compiler/src/wasm_emit.c b/compiler/src/wasm_emit.c index 445b9f2f..5c276868 100644 --- a/compiler/src/wasm_emit.c +++ b/compiler/src/wasm_emit.c @@ -47,7 +47,7 @@ static WasmType onyx_type_to_wasm_type(Type* type) { if (type->kind == Type_Kind_Distinct) return onyx_type_to_wasm_type(type->Distinct.base_type); if (type->kind == Type_Kind_Pointer) return WASM_TYPE_PTR; if (type->kind == Type_Kind_Array) return WASM_TYPE_PTR; - if (type->kind == Type_Kind_Function) return WASM_TYPE_FUNC; + if (type->kind == Type_Kind_Function) return WASM_TYPE_VOID; if (type->kind == Type_Kind_MultiPointer) return WASM_TYPE_PTR; if (type->kind == Type_Kind_Basic) { @@ -967,7 +967,7 @@ EMIT_FUNC(store_instruction, Type* type, u32 offset) { if (type->kind == Type_Kind_Struct) type = type_struct_is_just_one_basic_value(type); if (type->kind == Type_Kind_Enum) type = type->Enum.backing; if (type->kind == Type_Kind_Distinct) type = type->Distinct.base_type; - if (type->kind == Type_Kind_Function) type = &basic_types[Basic_Kind_U32]; + if (type->kind == Type_Kind_Function) assert(5678 && 0); assert(type); @@ -1079,7 +1079,7 @@ EMIT_FUNC(load_instruction, Type* type, u32 offset) { if (type->kind == Type_Kind_Struct) type = type_struct_is_just_one_basic_value(type); if (type->kind == Type_Kind_Enum) type = type->Enum.backing; if (type->kind == Type_Kind_Distinct) type = type->Distinct.base_type; - if (type->kind == Type_Kind_Function) type = &basic_types[Basic_Kind_U32]; + if (type->kind == Type_Kind_Function) assert(1234 && 0); assert(type); @@ -1411,8 +1411,11 @@ EMIT_FUNC(for_iterator, AstFor* for_node, u64 iter_local) { u64 iterator_close_func = local_raw_allocate(mod->local_alloc, WASM_TYPE_FUNC); u64 iterator_remove_func = local_raw_allocate(mod->local_alloc, WASM_TYPE_FUNC); u64 iterator_done_bool = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32); + WI(for_node->token, WI_DROP); WIL(for_node->token, WI_LOCAL_SET, iterator_remove_func); + WI(for_node->token, WI_DROP); WIL(for_node->token, WI_LOCAL_SET, iterator_close_func); + WI(for_node->token, WI_DROP); WIL(for_node->token, WI_LOCAL_SET, iterator_next_func); WIL(for_node->token, WI_LOCAL_SET, iterator_data_ptr); @@ -1826,7 +1829,14 @@ EMIT_FUNC(binop, AstBinaryOp* binop) { } emit_expression(mod, &code, binop->left); + if (binop->left->type->kind == Type_Kind_Function) { // nocheckin + WI(NULL, WI_DROP); + } + emit_expression(mod, &code, binop->right); + if (binop->right->type->kind == Type_Kind_Function) { // nocheckin + WI(NULL, WI_DROP); + } WI(binop->token, binop_instr); @@ -2113,6 +2123,7 @@ EMIT_FUNC(call, AstCall* call) { } else { emit_expression(mod, &code, call->callee); + WI(NULL, WI_DROP); i32 type_idx = generate_type_idx(mod, call->callee->type); WID(NULL, WI_CALL_INDIRECT, ((WasmInstructionData) { type_idx, 0x00 })); @@ -3364,6 +3375,7 @@ EMIT_FUNC(expression, AstTyped* expr) { i32 elemidx = get_element_idx(mod, (AstFunction *) expr); WID(NULL, WI_I32_CONST, elemidx); + WIL(NULL, WI_I32_CONST, 0); break; } @@ -3631,6 +3643,12 @@ EMIT_FUNC(expression, AstTyped* expr) { break; } + case Ast_Kind_Capture_Local: { + printf("HANDLE CAPTURE LOCAL!!!\n"); + assert(0); + break; + } + default: bh_printf("Unhandled case: %d\n", expr->kind); DEBUG_HERE; @@ -3927,6 +3945,7 @@ EMIT_FUNC(zero_value_for_type, Type* type, OnyxToken* where, AstTyped *alloc_nod } else if (type->kind == Type_Kind_Function) { WID(NULL, WI_I32_CONST, mod->null_proc_func_idx); + WIL(NULL, WI_I32_CONST, 0); } else { if (type == &basic_types[Basic_Kind_Void]) { diff --git a/compiler/src/wasm_output.h b/compiler/src/wasm_output.h index 2500b343..7626f1f1 100644 --- a/compiler/src/wasm_output.h +++ b/compiler/src/wasm_output.h @@ -986,6 +986,18 @@ static i32 output_ovm_debug_sections(OnyxWasmModule* module, bh_buffer* buff) { // continue; // } + if (type->kind == Type_Kind_Function) { + output_unsigned_integer(6, §ion_buff); + output_unsigned_integer(type->Function.param_count, §ion_buff); + + fori (i, 0, (i32) type->Function.param_count) { + output_unsigned_integer(type->Function.params[i]->id, §ion_buff); + } + + output_unsigned_integer(type->Function.return_type->id, §ion_buff); + continue; + } + if (type_is_structlike_strict(type)) { output_unsigned_integer(3, §ion_buff); @@ -1006,18 +1018,6 @@ static i32 output_ovm_debug_sections(OnyxWasmModule* module, bh_buffer* buff) { continue; } - if (type->kind == Type_Kind_Function) { - output_unsigned_integer(6, §ion_buff); - output_unsigned_integer(type->Function.param_count, §ion_buff); - - fori (i, 0, (i32) type->Function.param_count) { - output_unsigned_integer(type->Function.params[i]->id, §ion_buff); - } - - output_unsigned_integer(type->Function.return_type->id, §ion_buff); - continue; - } - if (type->kind == Type_Kind_Distinct) { output_unsigned_integer(5, §ion_buff); output_unsigned_integer(2, §ion_buff); diff --git a/core/runtime/platform/wasi/platform.onyx b/core/runtime/platform/wasi/platform.onyx index ac8a8597..92d38879 100644 --- a/core/runtime/platform/wasi/platform.onyx +++ b/core/runtime/platform/wasi/platform.onyx @@ -7,7 +7,6 @@ use core use wasi use runtime -use core use wasi { IOVec, SubscriptionTagged, Subscription, Event, Size, poll_oneoff, fd_write, fd_datasync, fd_read, @@ -18,6 +17,9 @@ use runtime { __runtime_initialize, Multi_Threading_Enabled, } +use core { + __flush_stdio +} // Platform supports diff --git a/core/runtime/platform/wasi/wasi_fs.onyx b/core/runtime/platform/wasi/wasi_fs.onyx index c2dfe65a..d4a8bdf4 100644 --- a/core/runtime/platform/wasi/wasi_fs.onyx +++ b/core/runtime/platform/wasi/wasi_fs.onyx @@ -1,11 +1,9 @@ package runtime.platform use runtime -use core +use core {package, *} use wasi -use core - #if runtime.runtime != .Wasi { #error "The file system library is currently only available on the WASI runtime, and should only be included if that is the chosen runtime." } @@ -297,7 +295,7 @@ __dir_read :: (dir: DirectoryData, out_entry: &os.DirectoryEntry) -> bool { err := wasi.fd_readdir(dir.dir_fd, ~~buffer, 512, dir.last_cookie, &bufused); if err != .Success || bufused == 0 do return false; - dirent := cast(&wasi.DirEnt) buffer; + dirent := cast(& wasi.DirEnt) buffer; switch dirent.d_type { case .Unknown do out_entry.type = .Unknown; case .BlockDevice do out_entry.type = .Block; @@ -311,7 +309,7 @@ __dir_read :: (dir: DirectoryData, out_entry: &os.DirectoryEntry) -> bool { out_entry.identifier = ~~dirent.d_ino; out_entry.name_length = dirent.d_namlen; memory.set(~~&out_entry.name_data, 0, 256); - memory.copy(~~&out_entry.name_data, ~~(dirent + 1), math.min(dirent.d_namlen, sizeof typeof out_entry.name_data)); + memory.copy(~~&out_entry.name_data, ~~(cast([&] wasi.DirEnt) dirent + 1), math.min(dirent.d_namlen, sizeof typeof out_entry.name_data)); dir.last_cookie = dirent.d_next; return true; diff --git a/runtime/src/ort_threads.h b/runtime/src/ort_threads.h index 45481323..5b966e79 100644 --- a/runtime/src/ort_threads.h +++ b/runtime/src/ort_threads.h @@ -7,6 +7,7 @@ typedef struct OnyxThread { i32 tls_base; i32 stack_base; i32 funcidx; + i32 closureptr; i32 dataptr; wasm_instance_t* instance; @@ -50,7 +51,7 @@ static i32 onyx_run_thread(void *data) { i32 thread_id = thread->id; { // Call the _thread_start procedure - wasm_val_t args[] = { WASM_I32_VAL(thread_id), WASM_I32_VAL(thread->tls_base), WASM_I32_VAL(thread->stack_base), WASM_I32_VAL(thread->funcidx), WASM_I32_VAL(thread->dataptr) }; + wasm_val_t args[] = { WASM_I32_VAL(thread_id), WASM_I32_VAL(thread->tls_base), WASM_I32_VAL(thread->stack_base), WASM_I32_VAL(thread->funcidx), WASM_I32_VAL(thread->closureptr), WASM_I32_VAL(thread->dataptr) }; wasm_val_vec_t results = { 0, 0 }; wasm_val_vec_t args_array = WASM_ARRAY_VEC(args); @@ -74,7 +75,7 @@ static i32 onyx_run_thread(void *data) { return 0; } -ONYX_DEF(__spawn_thread, (WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) { +ONYX_DEF(__spawn_thread, (WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) { if (threads == NULL) bh_arr_new(bh_heap_allocator(), threads, 128); bh_arr_insert_end(threads, 1); OnyxThread *thread = &bh_arr_last(threads); @@ -83,7 +84,8 @@ ONYX_DEF(__spawn_thread, (WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WA thread->tls_base = params->data[1].of.i32; thread->stack_base = params->data[2].of.i32; thread->funcidx = params->data[3].of.i32; - thread->dataptr = params->data[4].of.i32; + thread->closureptr = params->data[4].of.i32; + thread->dataptr = params->data[5].of.i32; #ifdef _BH_LINUX pthread_create(&thread->thread, NULL, onyx_run_thread, thread); diff --git a/tests/char_literals.onyx b/tests/char_literals.onyx index 7d152fc5..5e174b11 100644 --- a/tests/char_literals.onyx +++ b/tests/char_literals.onyx @@ -17,4 +17,4 @@ main :: () { a_newline := '\n'; printf("{}", a_newline); println("Something else"); -} \ No newline at end of file +}