global :: 5 - This would replace all instances of 'global' with the integer constant
5. This would not make a global in WASM.
- global := 5 - This would work as expected but will make generating the WASM more difficult.
- This feature may wait to come back.
-
global :: i32 - This would work as a type alias. 'global' would have the type node as it's 'node'
print :: proc #foriegn "host" "print" (...) ---
min(2, 5);
min(4.5, 10.4);
+
+
// same position as AstNodeCall
struct AstIntrinsicCall { AstTyped base; AstArgument *arguments; OnyxIntrinsic intrinsic; };
-typedef struct OnyxProgram {
+// NOTE: Simple data structure for storing what comes out of the parser
+typedef struct ParserOutput {
bh_arr(AstBinding *) top_level_bindings;
bh_arr(AstNode *) nodes_to_process;
bh_arr(AstFunction *) functions;
-} OnyxProgram;
+} ParserOutput;
--- /dev/null
+#ifndef ONYXIR_H
+#define ONYXIR_H
+
+#include "bh.h"
+#include "onyxastnodes.h"
+#include "onyxtypes.h"
+#include "onyxmsgs.h"
+
+typedef struct IrFunction {
+ AstFunction* ast_func;
+ Type* type;
+ bh_arr(AstLocal *) locals;
+ AstLocal* first_param;
+ AstNode* body;
+
+ // NOTE: A function can either be either be:
+ // Normal
+ // Intrinsic
+ // Exported
+ // Foreign
+ union {
+ // NOTE: Set if the function is exported
+ char* exported_name;
+
+ // NOTE: Set if the function is a foreign
+ struct {
+ char* foreign_module;
+ char* foreign_name;
+ };
+
+ // NOTE: Set if the function is intrinsic
+ OnyxIntrinsic intrinsic;
+ };
+
+ u32 is_exported : 1;
+ u32 is_foreign : 1;
+ u32 is_intrinsic : 1;
+
+} IrFunction;
+
+typedef struct IrContext {
+ // NOTE: Properties used after ir generation is done
+ bh_allocator allocator;
+
+ bh_arr(IrFunction *) functions;
+
+ // NOTE: Properties used while ir is generating
+ IrFunction* curr_function;
+
+ OnyxMessages* msgs;
+} IrContext;
+
+
+IrContext ir_context_create(bh_allocator allocator);
+void ir_context_free(IrContext* context);
+void ir_generate(IrContext* context, ParserOutput parse_output);
+
+#endif // #ifndef ONYXIR_H
} OnyxSemPassState;
// NOTE: Resolving all symbols in the tree
-void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program);
+void onyx_resolve_symbols(OnyxSemPassState* state, ParserOutput* program);
// NOTE: Inferring and checking types in the tree
-void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program);
+void onyx_type_check(OnyxSemPassState* state, ParserOutput* program);
// NOTE: Full semantic pass
OnyxSemPassState onyx_sempass_create(bh_allocator alloc, bh_allocator node_alloc, OnyxMessages* msgs);
-void onyx_sempass(OnyxSemPassState* state, OnyxProgram* program);
+void onyx_sempass(OnyxSemPassState* state, ParserOutput* program);
#endif
#include "onyxastnodes.h"
#include "onyxmsgs.h"
+#include "onyxir.h"
typedef u8 WasmType;
u16 next_type_idx;
u16 next_func_idx;
- u16 next_import_func_idx;
u16 next_global_idx;
- u16 next_import_global_idx;
u16 export_count;
} OnyxWasmModule;
OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs);
-void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program);
+void onyx_wasm_module_compile(OnyxWasmModule* module, ParserOutput* program);
void onyx_wasm_module_free(OnyxWasmModule* module);
void onyx_wasm_module_write_to_file(OnyxWasmModule* module, bh_file file);
b := 1 + foo(2);
print(b);
- if b == 13
- ---
+ if b == 13 {}
else {
print(1024);
}
c := 123.0;
{
- a := 5.0f;
- b := 12.3;
+ d := 5.0f;
+ e := 12.3;
- print_f32(a);
- print_f64(b);
+ print_f32(d);
+ print_f64(e);
}
print_i32(a);
// }
main :: proc #export {
+ local_brute();
+
print_i32(clz_i32(16));
print_f32(sqrt_f32(2.0f));
bh_arr(const char *) queued_files;
OnyxMessages msgs;
- OnyxProgram program;
+ ParserOutput parse_output;
OnyxWasmModule wasm_mod;
} CompilerState;
}
bh_arr_each(AstBinding *, binding_node, results.bindings)
- bh_arr_push(compiler_state->program.top_level_bindings, *binding_node);
+ bh_arr_push(compiler_state->parse_output.top_level_bindings, *binding_node);
bh_arr_each(AstNode *, node, results.nodes_to_process)
- bh_arr_push(compiler_state->program.nodes_to_process, *node);
+ bh_arr_push(compiler_state->parse_output.nodes_to_process, *node);
if (onyx_message_has_errors(&compiler_state->msgs)) {
return ONYX_COMPILER_PROGRESS_FAILED_PARSE;
static void compiler_state_init(CompilerState* compiler_state, OnyxCompileOptions* opts) {
compiler_state->options = opts;
- bh_arr_new(global_heap_allocator, compiler_state->program.top_level_bindings, 4);
- bh_arr_new(global_heap_allocator, compiler_state->program.functions, 4);
+ bh_arr_new(global_heap_allocator, compiler_state->parse_output.top_level_bindings, 4);
+ bh_arr_new(global_heap_allocator, compiler_state->parse_output.nodes_to_process, 4);
+ bh_arr_new(global_heap_allocator, compiler_state->parse_output.functions, 4);
bh_arena_init(&compiler_state->msg_arena, opts->allocator, 4096);
compiler_state->msg_alloc = bh_arena_allocator(&compiler_state->msg_arena);
bh_printf("[Checking semantics]\n");
OnyxSemPassState sp_state = onyx_sempass_create(compiler_state->sp_alloc, compiler_state->ast_alloc, &compiler_state->msgs);
- onyx_sempass(&sp_state, &compiler_state->program);
+ onyx_sempass(&sp_state, &compiler_state->parse_output);
if (onyx_message_has_errors(&compiler_state->msgs)) {
return ONYX_COMPILER_PROGRESS_FAILED_SEMPASS;
bh_printf("[Generating WASM]\n");
compiler_state->wasm_mod = onyx_wasm_module_create(compiler_state->options->allocator, &compiler_state->msgs);
- onyx_wasm_module_compile(&compiler_state->wasm_mod, &compiler_state->program);
+ onyx_wasm_module_compile(&compiler_state->wasm_mod, &compiler_state->parse_output);
if (onyx_message_has_errors(&compiler_state->msgs)) {
return ONYX_COMPILER_PROGRESS_FAILED_BINARY_GEN;
OnyxCompileOptions compile_opts = compile_opts_parse(global_heap_allocator, argc, argv);
CompilerState compile_state = {
- .program = {
+ .parse_output = {
.top_level_bindings = NULL,
.nodes_to_process = NULL,
static b32 check_node(OnyxSemPassState* state, AstNode* node) {
switch (node->kind) {
- case Ast_Kind_Function: return check_function(state, (AstFunction *) node);
- case Ast_Kind_Block: return check_block(state, (AstBlock *) node);
- case Ast_Kind_Assignment: return check_assignment(state, (AstAssign *) node);
- case Ast_Kind_Return: return check_return(state, (AstReturn *) node);
- case Ast_Kind_If: return check_if(state, (AstIf *) node);
- case Ast_Kind_While: return check_while(state, (AstWhile *) node);
- case Ast_Kind_Call: return check_call(state, (AstCall *) node);
- case Ast_Kind_Binary_Op: return check_binaryop(state, (AstBinaryOp *) node);
- default: return check_expression(state, (AstTyped *) node);
+ case Ast_Kind_Function: return check_function(state, (AstFunction *) node);
+ case Ast_Kind_Block: return check_block(state, (AstBlock *) node);
+ case Ast_Kind_Assignment: return check_assignment(state, (AstAssign *) node);
+ case Ast_Kind_Return: return check_return(state, (AstReturn *) node);
+ case Ast_Kind_If: return check_if(state, (AstIf *) node);
+ case Ast_Kind_While: return check_while(state, (AstWhile *) node);
+ case Ast_Kind_Call: return check_call(state, (AstCall *) node);
+ case Ast_Kind_Binary_Op: return check_binaryop(state, (AstBinaryOp *) node);
+ default: return check_expression(state, (AstTyped *) node);
}
}
-void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program) {
-
- // bh_arr_each(AstForeign *, foreign, program->foreigns)
- // if ((*foreign)->import->kind == Ast_Kind_Function)
- // check_function(state, (AstFunction *) (*foreign)->import);
-
- // bh_arr_each(AstGlobal *, global, program->globals)
- // check_global(state, *global);
-
- // bh_arr_each(AstFunction *, function, program->functions)
- // check_function(state, *function);
-
+void onyx_type_check(OnyxSemPassState* state, ParserOutput* program) {
bh_arr_each(AstNode *, node, program->nodes_to_process) {
check_node(state, *node);
--- /dev/null
+#include "onyxir.h"
+
+#define IR_FUNC(kind, ...) static void ir_ ## kind (IrContext* c, __VA_ARGS__)
+
+IR_FUNC(function, AstFunction* ast_func);
+IR_FUNC(function_body, AstFunction* fd);
+IR_FUNC(block, AstBlock* block);
+IR_FUNC(statement, AstNode* stmt);
+IR_FUNC(assign_lval, AstTyped* lval);
+IR_FUNC(assignment, AstAssign* assign);
+IR_FUNC(if, AstIf* if_node);
+IR_FUNC(while, AstWhile* while_node);
+IR_FUNC(binop, AstBinaryOp* binop);
+IR_FUNC(unaryop, AstUnaryOp* unop);
+IR_FUNC(call, AstCall* call);
+IR_FUNC(intrinsic_call, AstIntrinsicCall* call);
+IR_FUNC(expression, AstTyped* expr);
+IR_FUNC(cast, AstUnaryOp* cast);
+IR_FUNC(return, AstReturn* ret);
+
+static OnyxIntrinsic intrinsic_lookup(char* name) {
+ if (!strcmp("memory_size", name)) return ONYX_INTRINSIC_MEMORY_SIZE;
+ else if (!strcmp("memory_grow", name)) return ONYX_INTRINSIC_MEMORY_GROW;
+
+ else if (!strcmp("clz_i32", name)) return ONYX_INTRINSIC_I32_CLZ;
+ else if (!strcmp("ctz_i32", name)) return ONYX_INTRINSIC_I32_CTZ;
+ else if (!strcmp("popcnt_i32", name)) return ONYX_INTRINSIC_I32_POPCNT;
+ else if (!strcmp("and_i32", name)) return ONYX_INTRINSIC_I32_AND;
+ else if (!strcmp("or_i32", name)) return ONYX_INTRINSIC_I32_OR;
+ else if (!strcmp("xor_i32", name)) return ONYX_INTRINSIC_I32_XOR;
+ else if (!strcmp("shl_i32", name)) return ONYX_INTRINSIC_I32_SHL;
+ else if (!strcmp("slr_i32", name)) return ONYX_INTRINSIC_I32_SLR;
+ else if (!strcmp("sar_i32", name)) return ONYX_INTRINSIC_I32_SAR;
+ else if (!strcmp("rotl_i32", name)) return ONYX_INTRINSIC_I32_ROTL;
+ else if (!strcmp("rotr_i32", name)) return ONYX_INTRINSIC_I32_ROTR;
+
+ else if (!strcmp("clz_i64", name)) return ONYX_INTRINSIC_I64_CLZ;
+ else if (!strcmp("ctz_i64", name)) return ONYX_INTRINSIC_I64_CTZ;
+ else if (!strcmp("popcnt_i64", name)) return ONYX_INTRINSIC_I64_POPCNT;
+ else if (!strcmp("and_i64", name)) return ONYX_INTRINSIC_I64_AND;
+ else if (!strcmp("or_i64", name)) return ONYX_INTRINSIC_I64_OR;
+ else if (!strcmp("xor_i64", name)) return ONYX_INTRINSIC_I64_XOR;
+ else if (!strcmp("shl_i64", name)) return ONYX_INTRINSIC_I64_SHL;
+ else if (!strcmp("slr_i64", name)) return ONYX_INTRINSIC_I64_SLR;
+ else if (!strcmp("sar_i64", name)) return ONYX_INTRINSIC_I64_SAR;
+ else if (!strcmp("rotl_i64", name)) return ONYX_INTRINSIC_I64_ROTL;
+ else if (!strcmp("rotr_i64", name)) return ONYX_INTRINSIC_I64_ROTR;
+
+ else if (!strcmp("abs_f32", name)) return ONYX_INTRINSIC_F32_ABS;
+ else if (!strcmp("ceil_f32", name)) return ONYX_INTRINSIC_F32_CEIL;
+ else if (!strcmp("floor_f32", name)) return ONYX_INTRINSIC_F32_FLOOR;
+ else if (!strcmp("trunc_f32", name)) return ONYX_INTRINSIC_F32_TRUNC;
+ else if (!strcmp("nearest_f32", name)) return ONYX_INTRINSIC_F32_NEAREST;
+ else if (!strcmp("sqrt_f32", name)) return ONYX_INTRINSIC_F32_SQRT;
+ else if (!strcmp("min_f32", name)) return ONYX_INTRINSIC_F32_MIN;
+ else if (!strcmp("max_f32", name)) return ONYX_INTRINSIC_F32_MAX;
+ else if (!strcmp("copysign_f32", name)) return ONYX_INTRINSIC_F32_COPYSIGN;
+
+ else if (!strcmp("abs_f64", name)) return ONYX_INTRINSIC_F64_ABS;
+ else if (!strcmp("ceil_f64", name)) return ONYX_INTRINSIC_F64_CEIL;
+ else if (!strcmp("floor_f64", name)) return ONYX_INTRINSIC_F64_FLOOR;
+ else if (!strcmp("trunc_f64", name)) return ONYX_INTRINSIC_F64_TRUNC;
+ else if (!strcmp("nearest_f64", name)) return ONYX_INTRINSIC_F64_NEAREST;
+ else if (!strcmp("sqrt_f64", name)) return ONYX_INTRINSIC_F64_SQRT;
+ else if (!strcmp("min_f64", name)) return ONYX_INTRINSIC_F64_MIN;
+ else if (!strcmp("max_f64", name)) return ONYX_INTRINSIC_F64_MAX;
+ else if (!strcmp("copysign_f64", name)) return ONYX_INTRINSIC_F64_COPYSIGN;
+ else return ONYX_INTRINSIC_UNDEFINED;
+}
+
+static void ir_add_local(IrContext* c, AstLocal* local) {
+ bh_arr_push(c->curr_function->locals, local);
+}
+
+IR_FUNC(ir_function, AstFunction* ast_func) {
+ IrFunction* func = bh_alloc_item(c->allocator, IrFunction);
+
+ func->ast_func = ast_func;
+ func->body = ast_func->body->body;
+ func->first_param = ast_func->params;
+
+ // NOTE: This is actually the return type (for now)
+ func->type = ast_func->base.type;
+
+ func->locals = NULL;
+ bh_arr_new(c->allocator, func->locals, 4);
+
+ func->is_exported = (ast_func->base.flags & Ast_Flag_Exported) != 0;
+ func->is_foreign = (ast_func->base.flags & Ast_Flag_Foreign) != 0;
+ func->is_intrinsic = (ast_func->base.flags & Ast_Flag_Intrinsic) != 0;
+
+ if (func->is_intrinsic) {
+ onyx_token_null_toggle(ast_func->base.token);
+ func->intrinsic = intrinsic_lookup(ast_func->base.token->text);
+ onyx_token_null_toggle(ast_func->base.token);
+ }
+
+ else if (func->is_exported) {
+ onyx_token_null_toggle(ast_func->base.token);
+ func->exported_name = bh_aprintf(c->allocator, "%s", ast_func->base.token->text);
+ onyx_token_null_toggle(ast_func->base.token);
+ }
+
+ else if (func->is_foreign) {
+ onyx_token_null_toggle(ast_func->foreign_module);
+ func->foreign_module = bh_aprintf(c->allocator, "%s", ast_func->foreign_module);
+ onyx_token_null_toggle(ast_func->foreign_module);
+
+ onyx_token_null_toggle(ast_func->foreign_name);
+ func->foreign_module = bh_aprintf(c->allocator, "%s", ast_func->foreign_name);
+ onyx_token_null_toggle(ast_func->foreign_name);
+ }
+
+ if (func->body != NULL) {
+ c->curr_function = func;
+ }
+}
+
+IR_FUNC(function_body, AstFunction* fd) {
+ if (fd->body == NULL) return;
+ ir_block(c, fd->body);
+}
+
+IR_FUNC(block, AstBlock* block) {
+ forll (AstLocal, local, block->locals->last_local, prev_local) {
+ ir_add_local(c, local);
+ }
+
+ forll (AstNode, stmt, block->body, next) {
+ ir_statement(c, stmt);
+ }
+}
+
+IR_FUNC(statement, AstNode* stmt) {
+ switch (stmt->kind) {
+ case Ast_Kind_Return: return ir_return(c, (AstReturn *) stmt);
+ case Ast_Kind_Assignment: return ir_assignment(c, (AstAssign *) stmt);
+ case Ast_Kind_If: return ir_if(c, (AstIf *) stmt);
+ case Ast_Kind_While: return ir_while(c, (AstWhile *) stmt);
+ case Ast_Kind_Block: return ir_block(c, (AstBlock *) stmt);
+
+ default: break;
+ }
+}
+
+IR_FUNC(if, AstIf* if_node) {
+ if (if_node->true_block.as_if->base.kind == Ast_Kind_Block) {
+ ir_block(c, if_node->true_block.as_block);
+ }
+
+ if (if_node->false_block.as_if->base.kind == Ast_Kind_Block) {
+ ir_block(c, if_node->false_block.as_block);
+ }
+}
+
+IR_FUNC(while, AstWhile* while_node) {
+ ir_block(c, while_node->body);
+}
+
+// NOTE: Currently, these functions don't have anything to
+// do so they are empty and not called. When I have a reason
+// to use them, I will populate their bodies
+IR_FUNC(assign_lval, AstTyped* lval) {}
+IR_FUNC(assignment, AstAssign* assign) {}
+IR_FUNC(binop, AstBinaryOp* binop) {}
+IR_FUNC(unaryop, AstUnaryOp* unop) {}
+IR_FUNC(expression, AstTyped* expr) {}
+IR_FUNC(cast, AstUnaryOp* cast) {}
+IR_FUNC(return, AstReturn* ret) {}
+
+IrContext ir_context_create(bh_allocator allocator) {
+ IrContext context = {
+ .allocator = allocator,
+ .functions = NULL,
+
+ .curr_function = NULL,
+ };
+
+ bh_arr_new(allocator, context.functions, 4);
+
+ return context;
+}
+
+void ir_context_free(IrContext* context) {
+ bh_arr_free(context.functions);
+}
+
+void ir_generate(IrContext* context, ParserOutput parse_output) {
+
+}
// WASM, this function may not be needed. It brings all of the locals
// defined in sub-scopes up to the function-block level. This is a
// requirement of WASM, but not of other targets.
-// static void collapse_scopes(OnyxProgram* program) {
-// bh_arr(AstBlock*) traversal_queue = NULL;
-// bh_arr_new(global_scratch_allocator, traversal_queue, 4);
-// bh_arr_set_length(traversal_queue, 0);
-//
-// bh_arr_each(AstFunction *, func, program->functions) {
-// AstLocalGroup* top_locals = (*func)->body->locals;
-//
-// bh_arr_push(traversal_queue, (*func)->body);
-// while (!bh_arr_is_empty(traversal_queue)) {
-// AstBlock* block = traversal_queue[0];
-//
-// if (block->base.kind == Ast_Kind_If) {
-// AstIf* if_node = (AstIf *) block;
-// if (if_node->true_block.as_block != NULL)
-// bh_arr_push(traversal_queue, if_node->true_block.as_block);
-//
-// if (if_node->false_block.as_block != NULL)
-// bh_arr_push(traversal_queue, if_node->false_block.as_block);
-//
-// } else {
-//
-// if (block->locals != top_locals && block->locals->last_local != NULL) {
-// AstLocal* last_local = block->locals->last_local;
-// while (last_local && last_local->prev_local != NULL) last_local = last_local->prev_local;
-//
-// last_local->prev_local = top_locals->last_local;
-// top_locals->last_local = block->locals->last_local;
-// block->locals->last_local = NULL;
-// }
-//
-// AstNode* walker = block->body;
-// while (walker) {
-// if (walker->kind == Ast_Kind_Block) {
-// bh_arr_push(traversal_queue, (AstBlock *) walker);
-//
-// } else if (walker->kind == Ast_Kind_While) {
-// bh_arr_push(traversal_queue, ((AstWhile *) walker)->body);
-//
-// } else if (walker->kind == Ast_Kind_If) {
-// if (((AstIf *) walker)->true_block.as_block != NULL)
-// bh_arr_push(traversal_queue, ((AstIf *) walker)->true_block.as_block);
-//
-// if (((AstIf *) walker)->false_block.as_block != NULL)
-// bh_arr_push(traversal_queue, ((AstIf *) walker)->false_block.as_block);
-// }
-//
-// walker = walker->next;
-// }
-// }
-//
-// bh_arr_deleten(traversal_queue, 0, 1);
-// }
-// }
-// }
-
-void onyx_sempass(OnyxSemPassState* state, OnyxProgram* program) {
+static void collapse_scopes(ParserOutput* program) {
+ bh_arr(AstBlock*) traversal_queue = NULL;
+ bh_arr_new(global_scratch_allocator, traversal_queue, 4);
+ bh_arr_set_length(traversal_queue, 0);
+
+ bh_arr_each(AstFunction *, func, program->functions) {
+ if ((*func)->base.flags & Ast_Flag_Intrinsic) continue;
+
+ AstLocalGroup* top_locals = (*func)->body->locals;
+
+ bh_arr_push(traversal_queue, (*func)->body);
+ while (!bh_arr_is_empty(traversal_queue)) {
+ AstBlock* block = traversal_queue[0];
+
+ if (block->base.kind == Ast_Kind_If) {
+ AstIf* if_node = (AstIf *) block;
+ if (if_node->true_block.as_block != NULL)
+ bh_arr_push(traversal_queue, if_node->true_block.as_block);
+
+ if (if_node->false_block.as_block != NULL)
+ bh_arr_push(traversal_queue, if_node->false_block.as_block);
+
+ } else {
+
+ if (block->locals != top_locals && block->locals->last_local != NULL) {
+ AstLocal* last_local = block->locals->last_local;
+ while (last_local && last_local->prev_local != NULL) last_local = last_local->prev_local;
+
+ last_local->prev_local = top_locals->last_local;
+ top_locals->last_local = block->locals->last_local;
+ block->locals->last_local = NULL;
+ }
+
+ AstNode* walker = block->body;
+ while (walker) {
+ if (walker->kind == Ast_Kind_Block) {
+ bh_arr_push(traversal_queue, (AstBlock *) walker);
+
+ } else if (walker->kind == Ast_Kind_While) {
+ bh_arr_push(traversal_queue, ((AstWhile *) walker)->body);
+
+ } else if (walker->kind == Ast_Kind_If) {
+ if (((AstIf *) walker)->true_block.as_block != NULL)
+ bh_arr_push(traversal_queue, ((AstIf *) walker)->true_block.as_block);
+
+ if (((AstIf *) walker)->false_block.as_block != NULL)
+ bh_arr_push(traversal_queue, ((AstIf *) walker)->false_block.as_block);
+ }
+
+ walker = walker->next;
+ }
+ }
+
+ bh_arr_deleten(traversal_queue, 0, 1);
+ }
+ }
+}
+
+void onyx_sempass(OnyxSemPassState* state, ParserOutput* program) {
onyx_resolve_symbols(state, program);
if (onyx_message_has_errors(state->msgs)) return;
onyx_type_check(state, program);
if (onyx_message_has_errors(state->msgs)) return;
- // collapse_scopes(program);
+ collapse_scopes(program);
}
}
}
-void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program) {
+void onyx_resolve_symbols(OnyxSemPassState* state, ParserOutput* program) {
// NOTE: Add types to global scope
symbol_basic_type_introduce(state, &basic_type_void);
"PARAM",
"ARGUMENT",
"CALL",
- "INTRINSIC_CALL",
"ASSIGN",
"RETURN",
}
if (basic->flags & Basic_Flag_Float) {
if (basic->size <= 4) return WASM_TYPE_FLOAT32;
- if (basic->size == 8) return WASM_TYPE_FLOAT64;;
+ if (basic->size == 8) return WASM_TYPE_FLOAT64;
}
if (basic->size == 0) return WASM_TYPE_VOID;
}
bh_arr(WasmInstruction) code = *pcode;
switch (stmt->kind) {
- case Ast_Kind_Return: compile_return(mod, &code, (AstReturn *) stmt); break;
+ case Ast_Kind_Return: compile_return(mod, &code, (AstReturn *) stmt); break;
case Ast_Kind_Assignment: compile_assignment(mod, &code, (AstAssign *) stmt); break;
- case Ast_Kind_If: compile_if(mod, &code, (AstIf *) stmt); break;
- case Ast_Kind_While: compile_while(mod, &code, (AstWhile *) stmt); break;
- case Ast_Kind_Break: compile_structured_jump(mod, &code, 0); break;
- case Ast_Kind_Continue: compile_structured_jump(mod, &code, 1); break;
- case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) stmt); break;
+ case Ast_Kind_If: compile_if(mod, &code, (AstIf *) stmt); break;
+ case Ast_Kind_While: compile_while(mod, &code, (AstWhile *) stmt); break;
+ case Ast_Kind_Break: compile_structured_jump(mod, &code, 0); break;
+ case Ast_Kind_Continue: compile_structured_jump(mod, &code, 1); break;
+ case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) stmt); break;
case Ast_Kind_Call:
case Ast_Kind_Intrinsic_Call:
WasmType operator_type = onyx_type_to_wasm_type(binop->left->type);
i32 optype = 0;
- if (operator_type == WASM_TYPE_INT32) optype = 0;
- else if (operator_type == WASM_TYPE_INT64) optype = 1;
+ if (operator_type == WASM_TYPE_INT32) optype = 0;
+ else if (operator_type == WASM_TYPE_INT64) optype = 1;
else if (operator_type == WASM_TYPE_FLOAT32) optype = 2;
else if (operator_type == WASM_TYPE_FLOAT64) optype = 3;
.export_count = 0,
.imports = NULL,
- .next_import_func_idx = 0,
- .next_import_global_idx = 0,
.globals = NULL,
.next_global_idx = 0,
return module;
}
-void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program) {
+void onyx_wasm_module_compile(OnyxWasmModule* module, ParserOutput* program) {
// NOTE: First, introduce all indicies for globals and functions
// bh_arr_each(AstForeign *, foreign, program->foreigns) {
bh_arr_each(AstFunction *, function, program->functions) {
if ((*function)->base.flags & Ast_Flag_Foreign) continue;
-
+
if (((*function)->base.flags & Ast_Flag_Intrinsic) == 0)
bh_imap_put(&module->func_map, (u64) *function, module->next_func_idx++);
}