changed: function pointers now have a closure pointer
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 19 Apr 2023 04:25:19 +0000 (23:25 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 19 Apr 2023 04:25:19 +0000 (23:25 -0500)
compiler/src/checker.c
compiler/src/types.c
compiler/src/wasm_emit.c
compiler/src/wasm_output.h
core/runtime/platform/wasi/platform.onyx
core/runtime/platform/wasi/wasi_fs.onyx
runtime/src/ort_threads.h
tests/char_literals.onyx

index abafdefe3d67201024319b912e3c4a96f1788fcb..7112f11b57428d3a4daae3a69b877a8e2ff9c98b 100644 (file)
@@ -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.");
 
index f03c91a2c4788eab6f278d05db84fb61a5c01479..953163cc78026251c63e0c08fe6a6f4b3e0c62d1 100644 (file)
@@ -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;
index 445b9f2f6b36c068bc3c303f8bdd6829be47f8e3..5c27686868b5e6a8694adfa9cba1a92a3e866549 100644 (file)
@@ -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]) {
index 2500b343eb99f91b94bf8b21f47df4042f8e6f62..7626f1f1e3577c4539424741fd15203844f1836c 100644 (file)
@@ -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, &section_buff);
+                output_unsigned_integer(type->Function.param_count, &section_buff);
+
+                fori (i, 0, (i32) type->Function.param_count) {
+                    output_unsigned_integer(type->Function.params[i]->id, &section_buff);
+                }
+
+                output_unsigned_integer(type->Function.return_type->id, &section_buff);
+                continue;
+            }
+
             if (type_is_structlike_strict(type)) {
                 output_unsigned_integer(3, &section_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, &section_buff);
-                output_unsigned_integer(type->Function.param_count, &section_buff);
-
-                fori (i, 0, (i32) type->Function.param_count) {
-                    output_unsigned_integer(type->Function.params[i]->id, &section_buff);
-                }
-
-                output_unsigned_integer(type->Function.return_type->id, &section_buff);
-                continue;
-            }
-
             if (type->kind == Type_Kind_Distinct) {
                 output_unsigned_integer(5, &section_buff);
                 output_unsigned_integer(2, &section_buff);
index ac8a8597ef45ee6f99b446a45e8011605c497b69..92d3887933475accb496b4bd4e05a3f2749f356b 100644 (file)
@@ -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
index c2dfe65abbf758c7d4cdec0de38923178b7812bf..d4a8bdf436491cac540bacb7e5ea5ea75a24eb35 100644 (file)
@@ -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;
index 45481323fff278d4dc2ee73ea9271d45569a2500..5b966e795af3ef260b30b8ae5e81af4932a572f0 100644 (file)
@@ -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);
index 7d152fc52c7c17ae3a6c3d473ec168307c40e608..5e174b115303127cb80d894de11e48e51ca35fc3 100644 (file)
@@ -17,4 +17,4 @@ main :: () {
     a_newline := '\n';
     printf("{}", a_newline);
     println("Something else");
-}
\ No newline at end of file
+}