From: Brendan Hansen Date: Thu, 4 Jun 2020 15:52:33 +0000 (-0500) Subject: Starting work on WASM code generation X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=669e8a8c665129a5292e3c732496accf46960fe7;p=onyx.git Starting work on WASM code generation --- diff --git a/include/onyxwasm.h b/include/onyxwasm.h index 2fb91f01..8c05fe52 100644 --- a/include/onyxwasm.h +++ b/include/onyxwasm.h @@ -6,17 +6,40 @@ #include "onyxparser.h" -enum WasmType { +typedef enum WasmType : char { WASM_TYPE_INT32 = 0x7F, WASM_TYPE_INT64 = 0x7E, WASM_TYPE_FLOAT32 = 0x7D, WASM_TYPE_FLOAT64 = 0x7C -}; +} WasmType; + +typedef struct WasmFuncType { + // NOTE: For now, WASM only allows for 1 return value. + // This may be lifted in the future. + WasmType return_type; + i32 param_count; + WasmType param_types[]; +} WasmFuncType; + +typedef struct WasmFunc { + WasmFuncType* type; + i32 idx; +} WasmFunc; typedef struct OnyxWasmModule { + bh_allocator allocator; + + // NOTE: Used internally as a map from strings that represent function types, + // 0x7f 0x7f : 0x7f ( (i32, i32) -> i32 ) + // to the function type index if it has been created. + bh_hash(i32) type_map; + i32 curr_type_idx; + bh_arr(WasmFuncType*) functypes; + bh_arr(WasmFunc) funcs; } OnyxWasmModule; OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* program); +void onyx_wasm_module_free(OnyxWasmModule* module); #endif diff --git a/src/onyxwasm.c b/src/onyxwasm.c new file mode 100644 index 00000000..a210a605 --- /dev/null +++ b/src/onyxwasm.c @@ -0,0 +1,90 @@ +#include "onyxwasm.h" + +static WasmType onyx_type_to_wasm_type(OnyxTypeInfo* type) { + if (type->is_bool) return WASM_TYPE_INT32; + if (type->is_int) { + if (type->size == 4) return WASM_TYPE_INT32; + if (type->size == 8) return WASM_TYPE_INT64; + } + if (type->is_float) { + if (type->size == 4) return WASM_TYPE_FLOAT32; + if (type->size == 8) return WASM_TYPE_FLOAT64; + } + + // TODO: Should produce an error message if this isn't successful + // TODO: Also, this should be able to handle a "void" type + return WASM_TYPE_INT32; +} + +static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) { + static char type_repr_buf[128]; + + char* t = type_repr_buf; + OnyxAstNodeParam* param = fd->params; + i32 param_count = 0; + while (param) { + *(t++) = (char) onyx_type_to_wasm_type(param->type); + param_count++; + param = param->next; + } + *(t++) = ':'; + + WasmType return_type = onyx_type_to_wasm_type(fd->return_type); + *(t++) = (char) return_type; + *t = '\0'; + + i32 type_idx = 0; + if (bh_hash_has(i32, mod->type_map, type_repr_buf)) { + type_idx = bh_hash_get(i32, mod->type_map, type_repr_buf); + } else { + // NOTE: Make a new type + WasmFuncType* type = (WasmFuncType*) bh_alloc(mod->allocator, sizeof(WasmFuncType) + sizeof(WasmType) * param_count); + type->return_type = return_type; + type->param_count = param_count; + + // HACK ish thing + memcpy(type->param_types, type_repr_buf, type->param_count); + + bh_arr_push(mod->functypes, type); + + bh_hash_put(i32, mod->type_map, type_repr_buf, mod->curr_type_idx); + type_idx = mod->curr_type_idx; + mod->curr_type_idx++; + } +} + +OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* program) { + OnyxWasmModule module = { + .allocator = alloc, + + .type_map = NULL, + .curr_type_idx = 0, + + .functypes = NULL, + .funcs = NULL, + }; + + bh_arr_new(alloc, module.functypes, 4); + bh_arr_new(alloc, module.funcs, 4); + + bh_hash_init(bh_heap_allocator(), module.type_map); + + OnyxAstNode* walker = program; + while (walker) { + switch (walker->kind) { + case ONYX_AST_NODE_KIND_FUNCDEF: + process_function_definition(&module, &walker->as_funcdef); + break; + default: break; + } + + walker = walker->next; + } + + return module; +} + +void onyx_wasm_module_free(OnyxWasmModule* module) { + bh_arr_free(module.functypes); + bh_arr_free(module.funcs); +}