+#include "types.h"
#define BH_DEBUG
#include "wasm_emit.h"
#include "utils.h"
*pcode = code;
}
-EMIT_FUNC(for_range, AstFor* for_node, u64 iter_local) {
+EMIT_FUNC(for__prologue, AstFor* for_node, u64 iter_local, i64 index_local) {
+ bh_arr(WasmInstruction) code = *pcode;
+
+ if (for_node->has_first) {
+ for_node->first_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
+ WIL(for_node->token, WI_I32_CONST, 1);
+ WIL(for_node->token, WI_LOCAL_SET, for_node->first_local);
+ }
+
+ if (index_local != -1) {
+ if (type_is_small_integer(for_node->index_var->type)) {
+ WIL(for_node->token, WI_I32_CONST, 0);
+ } else {
+ WIL(for_node->token, WI_I64_CONST, 0);
+ }
+
+ WIL(for_node->token, WI_LOCAL_SET, index_local);
+ }
+
+ *pcode = code;
+}
+
+EMIT_FUNC(for__epilogue, AstFor* for_node, u64 iter_local, i64 index_local) {
+ bh_arr(WasmInstruction) code = *pcode;
+
+ if (for_node->has_first) {
+ WIL(NULL, WI_I32_CONST, 0);
+ WIL(NULL, WI_LOCAL_SET, for_node->first_local);
+ }
+
+ if (index_local != -1) {
+ WIL(for_node->token, WI_LOCAL_GET, index_local);
+
+ if (type_is_small_integer(for_node->index_var->type)) {
+ WIL(for_node->token, WI_I32_CONST, 1);
+ WI(for_node->token, WI_I32_ADD);
+ } else {
+ WIL(for_node->token, WI_I64_CONST, 1);
+ WI(for_node->token, WI_I64_ADD);
+ }
+
+ WIL(for_node->token, WI_LOCAL_SET, index_local);
+ }
+
+ *pcode = code;
+}
+
+EMIT_FUNC(for_range, AstFor* for_node, u64 iter_local, i64 index_local) {
bh_arr(WasmInstruction) code = *pcode;
// NOTE: There are some aspects of the code below that rely on the
AstStructLiteral *range = (AstStructLiteral *) for_node->iter;
u64 offset = 0;
- StructMember low_mem, high_mem, step_mem;
- type_lookup_member(builtin_range_type_type, "low", &low_mem);
+ StructMember high_mem, step_mem;
type_lookup_member(builtin_range_type_type, "high", &high_mem);
type_lookup_member(builtin_range_type_type, "step", &step_mem);
- u64 low_local = local_raw_allocate(mod->local_alloc, onyx_type_to_wasm_type(low_mem.type));
u64 high_local = local_raw_allocate(mod->local_alloc, onyx_type_to_wasm_type(high_mem.type));
u64 step_local = local_raw_allocate(mod->local_alloc, onyx_type_to_wasm_type(step_mem.type));
WIL(for_node->token, WI_LOCAL_SET, step_local);
WIL(for_node->token, WI_LOCAL_SET, high_local);
- WIL(for_node->token, WI_LOCAL_TEE, low_local);
WIL(for_node->token, WI_LOCAL_SET, iter_local);
- if (for_node->has_first) {
- for_node->first_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
- WIL(for_node->token, WI_I32_CONST, 1);
- WIL(for_node->token, WI_LOCAL_SET, for_node->first_local);
- }
+ emit_for__prologue(mod, &code, for_node, iter_local, index_local);
emit_enter_structured_block(mod, &code, SBT_Breakable_Block, for_node->token);
emit_enter_structured_block(mod, &code, SBT_Basic_Loop, for_node->token);
WI(for_node->token, WI_I32_ADD);
WIL(for_node->token, WI_LOCAL_SET, iter_local);
- if (for_node->has_first) {
- WIL(for_node->token, WI_I32_CONST, 0);
- WIL(for_node->token, WI_LOCAL_SET, for_node->first_local);
- }
+ emit_for__epilogue(mod, &code, for_node, iter_local, index_local);
if (bh_arr_last(code).type != WI_JUMP)
WID(for_node->token, WI_JUMP, 0x00);
emit_leave_structured_block(mod, &code);
if (for_node->has_first) local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
- local_raw_free(mod->local_alloc, onyx_type_to_wasm_type(low_mem.type));
local_raw_free(mod->local_alloc, onyx_type_to_wasm_type(high_mem.type));
local_raw_free(mod->local_alloc, onyx_type_to_wasm_type(step_mem.type));
*pcode = code;
}
-EMIT_FUNC(for_slice, AstFor* for_node, u64 iter_local) {
+EMIT_FUNC(for_slice, AstFor* for_node, u64 iter_local, i64 index_local) {
bh_arr(WasmInstruction) code = *pcode;
u64 end_ptr_local, ptr_local;
WI(for_node->token, WI_PTR_ADD);
WIL(for_node->token, WI_LOCAL_SET, end_ptr_local);
- if (for_node->has_first) {
- for_node->first_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
- WIL(for_node->token, WI_I32_CONST, 1);
- WIL(for_node->token, WI_LOCAL_SET, for_node->first_local);
- }
+ emit_for__prologue(mod, &code, for_node, iter_local, index_local);
emit_enter_structured_block(mod, &code, SBT_Breakable_Block, for_node->token);
emit_enter_structured_block(mod, &code, SBT_Basic_Loop, for_node->token);
WI(for_node->token, WI_PTR_ADD);
WIL(for_node->token, WI_LOCAL_SET, ptr_local);
- if (for_node->has_first) {
- WIL(NULL, WI_I32_CONST, 0);
- WIL(NULL, WI_LOCAL_SET, for_node->first_local);
- }
+ emit_for__epilogue(mod, &code, for_node, iter_local, index_local);
if (bh_arr_last(code).type != WI_JUMP)
WID(for_node->token, WI_JUMP, 0x00);
*pcode = code;
}
-EMIT_FUNC(for_iterator, AstFor* for_node, u64 iter_local) {
+EMIT_FUNC(for_iterator, AstFor* for_node, u64 iter_local, i64 index_local) {
bh_arr(WasmInstruction) code = *pcode;
// Allocate temporaries for iterator contents
bh_arr_push(mod->for_remove_info, remove_info);
}
- if (for_node->has_first) {
- for_node->first_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
- WIL(for_node->token, WI_I32_CONST, 1);
- WIL(for_node->token, WI_LOCAL_SET, for_node->first_local);
- }
+ emit_for__prologue(mod, &code, for_node, iter_local, index_local);
AstLocal* var = for_node->var;
b32 it_is_local = (b32) ((iter_local & LOCAL_IS_WASM) != 0);
emit_block(mod, &code, for_node->stmt, 0);
- if (for_node->has_first) {
- WIL(NULL, WI_I32_CONST, 0);
- WIL(NULL, WI_LOCAL_SET, for_node->first_local);
- }
+ emit_for__epilogue(mod, &code, for_node, iter_local, index_local);
WID(for_node->token, WI_JUMP, 0x00);
u64 iter_local = local_allocate(mod->local_alloc, (AstTyped *) var);
bh_imap_put(&mod->local_map, (u64) var, iter_local);
+ i64 index_local = -1;
+ if (for_node->index_var) {
+ index_local = local_allocate(mod->local_alloc, (AstTyped *) for_node->index_var);
+ bh_imap_put(&mod->local_map, (u64) for_node->index_var, index_local);
+ }
+
debug_enter_symbol_frame(mod);
debug_introduce_symbol(mod, var->token,
local_is_wasm_local((AstTyped *) var) ? DSL_REGISTER : DSL_STACK,
iter_local, var->type);
+ if (for_node->index_var) {
+ // index variables must be register allocated.
+ debug_introduce_symbol(mod, for_node->index_var->token, DSL_REGISTER, index_local, for_node->index_var->type);
+ }
+
emit_expression(mod, &code, for_node->iter);
switch (for_node->loop_type) {
- case For_Loop_Range: emit_for_range(mod, &code, for_node, iter_local); break;
+ case For_Loop_Range: emit_for_range(mod, &code, for_node, iter_local, index_local); break;
// NOTE: For static arrays, simply outputing the size
// of the array right after the pointer to the start
// of the array essentially makes it a slice.
case For_Loop_Array:
WIL(NULL, WI_I32_CONST, for_node->iter->type->Array.count);
- emit_for_slice(mod, &code, for_node, iter_local);
+ emit_for_slice(mod, &code, for_node, iter_local, index_local);
break;
// NOTE: A dynamic array is just a slice with a capacity and allocator on the end.
emit_load_slice(mod, &code);
// fallthrough
- case For_Loop_Slice: emit_for_slice(mod, &code, for_node, iter_local); break;
- case For_Loop_Iterator: emit_for_iterator(mod, &code, for_node, iter_local); break;
+ case For_Loop_Slice: emit_for_slice(mod, &code, for_node, iter_local, index_local); break;
+ case For_Loop_Iterator: emit_for_iterator(mod, &code, for_node, iter_local, index_local); break;
default: onyx_report_error(for_node->token->pos, Error_Critical, "Invalid for loop type. You should probably not be seeing this...");
}