Starting work on WASM code generation
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 4 Jun 2020 15:52:33 +0000 (10:52 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 4 Jun 2020 15:52:33 +0000 (10:52 -0500)
include/onyxwasm.h
src/onyxwasm.c [new file with mode: 0644]

index 2fb91f01d7c7b629b1f2728d4c52d511878a43c7..8c05fe522e257d53da8ccab43d3191a19fbf0e18 100644 (file)
@@ -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 (file)
index 0000000..a210a60
--- /dev/null
@@ -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);
+}