"do",
"switch",
"case",
+ "fallthrough",
"->",
"<-",
char curr = *tokenizer->curr;
switch (curr) {
case 'a':
- LITERAL_TOKEN("alignof", 1, Token_Type_Keyword_Alignof);
- LITERAL_TOKEN("as", 1, Token_Type_Keyword_As);
+ LITERAL_TOKEN("alignof", 1, Token_Type_Keyword_Alignof);
+ LITERAL_TOKEN("as", 1, Token_Type_Keyword_As);
break;
case 'b':
- LITERAL_TOKEN("break", 1, Token_Type_Keyword_Break);
+ LITERAL_TOKEN("break", 1, Token_Type_Keyword_Break);
break;
case 'c':
- LITERAL_TOKEN("case", 1, Token_Type_Keyword_Case);
- LITERAL_TOKEN("cast", 1, Token_Type_Keyword_Cast);
- LITERAL_TOKEN("continue", 1, Token_Type_Keyword_Continue);
+ LITERAL_TOKEN("case", 1, Token_Type_Keyword_Case);
+ LITERAL_TOKEN("cast", 1, Token_Type_Keyword_Cast);
+ LITERAL_TOKEN("continue", 1, Token_Type_Keyword_Continue);
break;
case 'd':
- LITERAL_TOKEN("defer", 1, Token_Type_Keyword_Defer);
- LITERAL_TOKEN("do", 1, Token_Type_Keyword_Do);
+ LITERAL_TOKEN("defer", 1, Token_Type_Keyword_Defer);
+ LITERAL_TOKEN("do", 1, Token_Type_Keyword_Do);
break;
case 'e':
- LITERAL_TOKEN("enum" , 1, Token_Type_Keyword_Enum);
- LITERAL_TOKEN("elseif", 1, Token_Type_Keyword_Elseif);
- LITERAL_TOKEN("else", 1, Token_Type_Keyword_Else);
+ LITERAL_TOKEN("enum", 1, Token_Type_Keyword_Enum);
+ LITERAL_TOKEN("elseif", 1, Token_Type_Keyword_Elseif);
+ LITERAL_TOKEN("else", 1, Token_Type_Keyword_Else);
break;
case 'f':
- LITERAL_TOKEN("for", 1, Token_Type_Keyword_For);
- LITERAL_TOKEN("false", 1, Token_Type_Literal_False);
+ LITERAL_TOKEN("for", 1, Token_Type_Keyword_For);
+ LITERAL_TOKEN("false", 1, Token_Type_Literal_False);
+ LITERAL_TOKEN("fallthrough", 1, Token_Type_Keyword_Fallthrough);
break;
case 'g':
- LITERAL_TOKEN("global", 1, Token_Type_Keyword_Global);
+ LITERAL_TOKEN("global", 1, Token_Type_Keyword_Global);
break;
case 'i':
- LITERAL_TOKEN("if", 1, Token_Type_Keyword_If);
+ LITERAL_TOKEN("if", 1, Token_Type_Keyword_If);
break;
case 'p':
- LITERAL_TOKEN("package", 1, Token_Type_Keyword_Package);
- LITERAL_TOKEN("proc", 1, Token_Type_Keyword_Proc);
+ LITERAL_TOKEN("package", 1, Token_Type_Keyword_Package);
+ LITERAL_TOKEN("proc", 1, Token_Type_Keyword_Proc);
break;
case 'r':
- LITERAL_TOKEN("return", 1, Token_Type_Keyword_Return);
+ LITERAL_TOKEN("return", 1, Token_Type_Keyword_Return);
break;
case 's':
- LITERAL_TOKEN("sizeof", 1, Token_Type_Keyword_Sizeof);
- LITERAL_TOKEN("struct", 1, Token_Type_Keyword_Struct);
- LITERAL_TOKEN("switch", 1, Token_Type_Keyword_Switch);
+ LITERAL_TOKEN("sizeof", 1, Token_Type_Keyword_Sizeof);
+ LITERAL_TOKEN("struct", 1, Token_Type_Keyword_Struct);
+ LITERAL_TOKEN("switch", 1, Token_Type_Keyword_Switch);
break;
case 't':
- LITERAL_TOKEN("true", 1, Token_Type_Literal_True);
+ LITERAL_TOKEN("true", 1, Token_Type_Literal_True);
break;
case 'u':
- LITERAL_TOKEN("use", 1, Token_Type_Keyword_Use);
+ LITERAL_TOKEN("use", 1, Token_Type_Keyword_Use);
break;
case 'w':
- LITERAL_TOKEN("while", 1, Token_Type_Keyword_While);
+ LITERAL_TOKEN("while", 1, Token_Type_Keyword_While);
break;
case '-':
- LITERAL_TOKEN("->", 0, Token_Type_Right_Arrow);
- LITERAL_TOKEN("---", 0, Token_Type_Empty_Block);
- LITERAL_TOKEN("-=", 0, Token_Type_Minus_Equal);
+ LITERAL_TOKEN("->", 0, Token_Type_Right_Arrow);
+ LITERAL_TOKEN("---", 0, Token_Type_Empty_Block);
+ LITERAL_TOKEN("-=", 0, Token_Type_Minus_Equal);
break;
case '<':
- LITERAL_TOKEN("<-", 0, Token_Type_Right_Arrow);
- LITERAL_TOKEN("<<=", 0, Token_Type_Shl_Equal);
- LITERAL_TOKEN("<<", 0, Token_Type_Shift_Left);
- LITERAL_TOKEN("<=", 0, Token_Type_Less_Equal);
+ LITERAL_TOKEN("<-", 0, Token_Type_Right_Arrow);
+ LITERAL_TOKEN("<<=", 0, Token_Type_Shl_Equal);
+ LITERAL_TOKEN("<<", 0, Token_Type_Shift_Left);
+ LITERAL_TOKEN("<=", 0, Token_Type_Less_Equal);
break;
case '>':
- LITERAL_TOKEN(">>>=", 0, Token_Type_Sar_Equal);
- LITERAL_TOKEN(">>=", 0, Token_Type_Shr_Equal);
- LITERAL_TOKEN(">>>", 0, Token_Type_Shift_Arith_Right);
- LITERAL_TOKEN(">>", 0, Token_Type_Shift_Right);
- LITERAL_TOKEN(">=", 0, Token_Type_Greater_Equal);
+ LITERAL_TOKEN(">>>=", 0, Token_Type_Sar_Equal);
+ LITERAL_TOKEN(">>=", 0, Token_Type_Shr_Equal);
+ LITERAL_TOKEN(">>>", 0, Token_Type_Shift_Arith_Right);
+ LITERAL_TOKEN(">>", 0, Token_Type_Shift_Right);
+ LITERAL_TOKEN(">=", 0, Token_Type_Greater_Equal);
break;
case '&':
- LITERAL_TOKEN("&&", 0, Token_Type_And_And);
- LITERAL_TOKEN("&=", 0, Token_Type_And_Equal);
+ LITERAL_TOKEN("&&", 0, Token_Type_And_And);
+ LITERAL_TOKEN("&=", 0, Token_Type_And_Equal);
break;
case '|':
- LITERAL_TOKEN("|>", 0, Token_Type_Pipe);
- LITERAL_TOKEN("||", 0, Token_Type_Or_Or);
- LITERAL_TOKEN("|=", 0, Token_Type_Or_Equal);
+ LITERAL_TOKEN("|>", 0, Token_Type_Pipe);
+ LITERAL_TOKEN("||", 0, Token_Type_Or_Or);
+ LITERAL_TOKEN("|=", 0, Token_Type_Or_Equal);
break;
default:
- LITERAL_TOKEN("^=", 0, Token_Type_Xor_Equal);
- LITERAL_TOKEN("==", 0, Token_Type_Equal_Equal);
- LITERAL_TOKEN("!=", 0, Token_Type_Not_Equal);
- LITERAL_TOKEN("+=", 0, Token_Type_Plus_Equal);
- LITERAL_TOKEN("*=", 0, Token_Type_Star_Equal);
- LITERAL_TOKEN("/=", 0, Token_Type_Fslash_Equal);
- LITERAL_TOKEN("%=", 0, Token_Type_Percent_Equal);
+ LITERAL_TOKEN("^=", 0, Token_Type_Xor_Equal);
+ LITERAL_TOKEN("==", 0, Token_Type_Equal_Equal);
+ LITERAL_TOKEN("!=", 0, Token_Type_Not_Equal);
+ LITERAL_TOKEN("+=", 0, Token_Type_Plus_Equal);
+ LITERAL_TOKEN("*=", 0, Token_Type_Star_Equal);
+ LITERAL_TOKEN("/=", 0, Token_Type_Fslash_Equal);
+ LITERAL_TOKEN("%=", 0, Token_Type_Percent_Equal);
break;
}
*pcode = code;
}
-COMPILE_FUNC(structured_jump, i32 jump_count) {
+COMPILE_FUNC(structured_jump, i32 jump_count, JumpType jump) {
bh_arr(WasmInstruction) code = *pcode;
+ static const u8 wants[Jump_Type_Count] = { 1, 2, 3 };
+
i32 labelidx = 0;
- u8 wanted = (jump_count < 0) ? 2 : 1;
+ u8 wanted = wants[jump];
b32 success = 0;
- if (jump_count < 0) jump_count = -jump_count;
-
i32 len = bh_arr_length(mod->structured_jump_target) - 1;
for (u8* t = &bh_arr_last(mod->structured_jump_target); len >= 0; len--, t--) {
if (*t == wanted) jump_count--;
case Ast_Kind_While: compile_while(mod, &code, (AstIfWhile *) stmt); break;
case Ast_Kind_For: compile_for(mod, &code, (AstFor *) stmt); break;
case Ast_Kind_Switch: compile_switch(mod, &code, (AstSwitch *) stmt); break;
- case Ast_Kind_Break: compile_structured_jump(mod, &code, ((AstBreak *) stmt)->count); break;
- case Ast_Kind_Continue: compile_structured_jump(mod, &code, -((AstContinue *) stmt)->count); break;
+ case Ast_Kind_Jump: compile_structured_jump(mod, &code, ((AstJump *) stmt)->count, ((AstJump *) stmt)->jump); break;
case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) stmt, 1); break;
case Ast_Kind_Defer: compile_defer(mod, &code, (AstDefer *) stmt); break;
default: compile_expression(mod, &code, (AstTyped *) stmt); break;
bh_imap block_map;
bh_imap_init(&block_map, global_heap_allocator, bh_arr_length(switch_node->cases));
+ u32 jump_target = 1;
+
if (switch_node->default_case != NULL) {
WID(WI_BLOCK_START, 0x40);
- bh_arr_push(mod->structured_jump_target, 0);
+
+ bh_arr_push(mod->structured_jump_target, jump_target);
+ jump_target = 3;
}
u64 block_num = 0;
if (bh_imap_has(&block_map, (u64) sc->block)) continue;
WID(WI_BLOCK_START, 0x40);
- bh_arr_push(mod->structured_jump_target, 0);
+ bh_arr_push(mod->structured_jump_target, jump_target);
bh_imap_put(&block_map, (u64) sc->block, block_num);
block_num++;
bh_buffer_append(buff, leb, leb_len);
break;
+ case WI_JUMP_TABLE: {
+ BranchTable* bt = (BranchTable *) instr->data.p;
+
+ leb = uint_to_uleb128((u64) bt->count, &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
+
+ fori (i, 0, bt->count) {
+ leb = uint_to_uleb128((u64) bt->cases[i], &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
+ }
+
+ leb = uint_to_uleb128((u64) bt->default_case, &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
+ break;
+ }
+
+
case WI_CALL_INDIRECT:
case WI_I32_STORE:
case WI_I32_STORE_8: