added for loops over fixed size arrays
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 5 Sep 2020 05:10:27 +0000 (00:10 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 5 Sep 2020 05:10:27 +0000 (00:10 -0500)
onyx
progs/poly_test.onyx
src/onyxchecker.c
src/onyxwasm.c

diff --git a/onyx b/onyx
index 72b0bd66b59e0791e368135e90b59027dae26985..93ad2c335c45c7618426304e61a2e7c2f379f783 100755 (executable)
Binary files a/onyx and b/onyx differ
index b025dbd3f6c81dcca25c8f80a817036f1c2215fb..f966ab9ba4d1a0e2df892667eb23e12def1f9a25 100644 (file)
@@ -127,18 +127,29 @@ main :: proc (args: [] cstring) {
     print(r);
     print_array(^s.a);
 
+    // NOTE: Iterating by value
     for vec: s.c {
         print(vec);
         print(" ");
     }
     print("\n");
 
+    // NOTE: Iterating by pointer
     for ^vec: s.c {
         print(vec);
         print(" ");
     }
     print("\n");
 
+    small : [12] i32;
+    for ^it: small do *it = 1234 + cast(u32) it;
+
+    for it: small {
+        print(it);
+        print(" ");
+    }
+    print("\n");
+
 
     array_sort(^s.a, cmp_dec);
     array_sort(^s.b, cmp_dec);
index 165b7d516efeefeb4333a2e73f5268118875a1ee..d2f1f51a3891bb4e0aa80f50a7ec93d2dd64f062 100644 (file)
@@ -116,6 +116,14 @@ b32 check_for(AstFor* fornode) {
         fornode->loop_type = For_Loop_Range;
 
     }
+    else if (iter_type->kind == Type_Kind_Array) {
+        can_iterate = 1;
+
+        if (fornode->by_pointer) fornode->var->type = type_make_pointer(semstate.node_allocator, iter_type->Array.elem);
+        else                     fornode->var->type = iter_type->Array.elem;
+
+        fornode->loop_type = For_Loop_Array;
+    }
     else if (iter_type->kind == Type_Kind_Slice) {
         can_iterate = 1;
 
index 7534e82746b00cb08d956a3a0d764ffeeaf5f929..9661f1d6e48dfe71d5ea7d197bf06fc73ba658c6 100644 (file)
@@ -834,6 +834,96 @@ EMIT_FUNC(for_range, AstFor* for_node, u64 iter_local) {
     *pcode = code;
 }
 
+EMIT_FUNC(for_array, AstFor* for_node, u64 iter_local) {
+    bh_arr(WasmInstruction) code = *pcode;
+
+    // NOTE: This implementation is only for loops by value, not by pointer.
+
+    // At this point the stack will look like:
+    //      data
+
+    u64 end_ptr_local, ptr_local;
+    end_ptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
+
+    if (for_node->by_pointer) {
+        ptr_local = iter_local;
+    } else {
+        ptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
+    }
+
+    AstLocal* var = for_node->var;
+    b32 it_is_local = (b32) ((iter_local & LOCAL_IS_WASM) != 0);
+    u64 offset = 0;
+
+    u64 elem_size;
+    if (for_node->by_pointer) elem_size = type_size_of(var->type->Pointer.elem);
+    else                      elem_size = type_size_of(var->type);
+
+    WIL(WI_LOCAL_TEE, ptr_local);
+    WIL(WI_I32_CONST, for_node->iter->type->Array.count * elem_size);
+    WI(WI_I32_ADD);
+    WIL(WI_LOCAL_SET, end_ptr_local);
+
+    WID(WI_BLOCK_START, 0x40);
+    WID(WI_LOOP_START, 0x40);
+    WID(WI_BLOCK_START, 0x40);
+
+    bh_arr_push(mod->structured_jump_target, 1);
+    bh_arr_push(mod->structured_jump_target, 0);
+    bh_arr_push(mod->structured_jump_target, 2);
+
+    WIL(WI_LOCAL_GET, ptr_local);
+    WIL(WI_LOCAL_GET, end_ptr_local);
+    WI(WI_I32_GE_S);
+    WID(WI_COND_JUMP, 0x02);
+
+    if (!for_node->by_pointer) {
+        // NOTE: Storing structs requires that the location to store it is,
+        // the top most thing on the stack. Everything requires it to be
+        // 'under' the other element being stored.  -brendanfh 2020/09/04
+        if (!it_is_local && var->type->kind != Type_Kind_Struct) {
+            emit_local_location(mod, &code, var, &offset);
+        }
+
+        WIL(WI_LOCAL_GET, ptr_local);
+        emit_load_instruction(mod, &code, var->type, 0);
+        if (it_is_local) {
+            WIL(WI_LOCAL_SET, iter_local);
+        } else {
+            if (var->type->kind != Type_Kind_Struct) {
+                emit_store_instruction(mod, &code, var->type, offset);
+            } else {
+                emit_local_location(mod, &code, var, &offset);
+                emit_store_instruction(mod, &code, var->type, offset);
+            }
+        }
+    }
+
+    emit_block(mod, &code, for_node->stmt, 0);
+
+    bh_arr_pop(mod->structured_jump_target);
+    WI(WI_BLOCK_END);
+
+    WIL(WI_LOCAL_GET, ptr_local);
+    WIL(WI_I32_CONST, elem_size);
+    WI(WI_I32_ADD);
+    WIL(WI_LOCAL_SET, ptr_local);
+
+    bh_arr_pop(mod->structured_jump_target);
+    bh_arr_pop(mod->structured_jump_target);
+
+    if (bh_arr_last(code).type != WI_JUMP)
+        WID(WI_JUMP, 0x00);
+
+    WI(WI_LOOP_END);
+    WI(WI_BLOCK_END);
+
+    local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
+    if (!for_node->by_pointer) local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
+
+    *pcode = code;
+}
+
 EMIT_FUNC(for_slice, AstFor* for_node, u64 iter_local) {
     bh_arr(WasmInstruction) code = *pcode;
 
@@ -842,11 +932,6 @@ EMIT_FUNC(for_slice, AstFor* for_node, u64 iter_local) {
     // At this point the stack will look like:
     //      data
     //      count
-    //
-    // The locals we need to have:
-    //      end_ptr
-    //      start_ptr
-    //
 
     u64 end_ptr_local, ptr_local;
     end_ptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
@@ -930,7 +1015,7 @@ EMIT_FUNC(for_slice, AstFor* for_node, u64 iter_local) {
     WI(WI_BLOCK_END);
 
     local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
-    local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
+    if (!for_node->by_pointer) local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
 
     *pcode = code;
 }
@@ -946,6 +1031,8 @@ EMIT_FUNC(for, AstFor* for_node) {
 
     if (for_node->loop_type == For_Loop_Range) {
         emit_for_range(mod, &code, for_node, iter_local);
+    } else if (for_node->loop_type == For_Loop_Array) {
+        emit_for_array(mod, &code, for_node, iter_local);
     } else if (for_node->loop_type == For_Loop_Slice) {
         emit_for_slice(mod, &code, for_node, iter_local);
     } else if (for_node->loop_type == For_Loop_DynArr) {