build/onyxlex.o \
build/onyxparser.o \
build/onyxtypes.o \
+ build/onyxbuiltins.o \
build/onyxsempass.o \
build/onyxsymres.o \
build/onyxchecker.o \
[X] Output 'drop' instruction for functions whose return value isn't used
- [ ] Devise and implement a simple set of implicit type casting rules.
- - Numeric literals always type cast to whatever type is needed (very flexible).
-
[X] Strings should work as pointers to data.
- Literals should be placed in data section with pointers to the start.
- Should strings be null-terminated or a length at the start of the string?
[X] Include other directories to search for files
+ [X] remove struct splatting at parameters
+ - structs can still be passed by value however
+ - removed the implicit splatting feature
+
+ [ ] package builtin
+ - Place to store builtin types and values
+ __heap_start
+ __stack_base
+ __stack_top
+ etc
+
+ [ ] multiple return values
+
+ [ ] multiple lvals and compound assignment
+ a := 2
+ b := 5
+ a, b = b, a;
+
+ [ ] 'use' enums and packages at an arbitrary scope
+
+ [ ] All code paths return correct value
+
+ [ ] Add slices
+ - Arrays without a size
+ - Converted to a struct that looks like:
+ []T :: struct {
+ count : u32;
+ data : ^T;
+ }
+
[ ] Arrays need to be much better
- Currently, they are basically just a pointer.
- The length should be stored with the pointer
- Dynamic resizing?
- They are just very hard to use at the moment
- [ ] 'use' enums and packages at an arbitrary scope
+ [ ] Type parameterized structs
[ ] Array literals
[ ] Top level variable initialization
- Works for numeric literals
- [ ] Better checking for casts
- - Checking which things are allowed to cast to/from should be checked in the checker,
- not in the wasm generatation
-
[X] Start work on evaluating compile time known values.
- An expression marked COMPTIME will be reduced to its value in the parse tree.
- [ ] All code paths return correct value
-
[ ] #initialize structs
+ [ ] Better checking for casts
+ - Checking which things are allowed to cast to/from should be checked in the checker,
+ not in the wasm generatation
+
[ ] Variadic arguments
[ ] Switch statements
#define bh_arr_pop(arr) ((arr)[--bh__arrhead(arr)->length])
#define bh_arr_last(arr) ((arr)[bh__arrhead(arr)->length - 1])
#define bh_arr_end(arr, i) ((i) >= &(arr)[bh_arr_length(arr)])
+#define bh_arr_start(arr, i) ((i) < (arr))
#define bh_arr_new(allocator_, arr, cap) (bh__arr_grow((allocator_), (void**) &(arr), sizeof(*(arr)), cap))
#define bh_arr_free(arr) (bh__arr_free((void**) &(arr)))
#define bh_arr_fastdelete(arr, i) (arr[i] = arr[--bh__arrhead(arr)->length])
#define bh_arr_each(T, var, arr) for (T* var = (arr); !bh_arr_end((arr), var); var++)
+#define bh_arr_rev_each(T, var, arr) for (T* var = &bh_arr_last((arr)); !bh_arr_start((arr), var); var--)
b32 bh__arr_grow(bh_allocator alloc, void** arr, i32 elemsize, i32 cap);
b32 bh__arr_shrink(void** arr, i32 elemsize, i32 cap);
// Expression flags
Ast_Flag_Expr_Ignored = BH_BIT(8),
- Ast_Flag_Param_Splatted = BH_BIT(9),
Ast_Flag_Param_Use = BH_BIT(10),
Ast_Flag_Address_Taken = BH_BIT(11),
extern AstBasicType basic_type_rawptr;
extern AstNumLit builtin_heap_start;
-extern AstGlobal builtin_stack_base;
extern AstGlobal builtin_stack_top;
typedef struct BuiltinSymbol {
extern const BuiltinSymbol builtin_symbols[];
+void initialize_builtins();
+
// NOTE: Useful not inlined functions
AstTyped* ast_reduce(bh_allocator a, AstTyped* node);
u32 next_datum_offset;
u32 next_elem_idx;
- u32 *stack_top_ptr, *stack_base_ptr;
+ i32 *stack_top_ptr;
+ u32 stack_base_idx;
b32 has_stack_locals : 1;
} OnyxWasmModule;
use package memory
use package printing
-proc #export "start" {
- heap_init();
-
- print("Creating initial memories");
- arr1 := cast(^u32) malloc(sizeof [10] u32);
- print_hex(cast(u64) arr1);
-
- arr2 := cast(^u32) malloc(sizeof [40] u32);
- print_hex(cast(u64) arr2);
+Vec2 :: struct {
+ x : i32;
+ y : i32;
+}
- print("Freeing arr1");
- mfree(arr1);
+other :: proc (use v: ^Vec2) -> i32 {
+ o : Vec2;
+ o.x = -100;
+ o.y = -10;
- print("Resizing arr2 (shouldn't change location)");
- arr2 = cast(^u32) mresize(arr2, sizeof [60] u32);
- print_hex(cast(u64) arr2);
+ return x * o.x + y * o.y;
+}
- print("Allocating arr3 (should be bigger than arr2)");
- arr3 := cast(^u32) malloc(sizeof [30] u32);
- print_hex(cast(u64) arr3);
-
- print("Allocating arr1 (should be in the same place as before)");
- arr1 = cast(^u32) malloc(sizeof [5] u32);
- print_hex(cast(u64) arr1);
- for i: 0, 5 do arr1[i] = i;
+proc #export "start" {
+ heap_init();
- print("Resizing arr1 (should be in the same place as before)");
- arr1 = cast(^u32) mresize(arr1, sizeof[10] u32);
- print_hex(cast(u64) arr1);
+ v : Vec2;
+ v.x = 10;
+ v.y = 100;
- print("Resizing arr1 (should have moved to after arr3)");
- arr1 = cast(^u32) mresize(arr1, sizeof[100] u32);
- print_hex(cast(u64) arr1);
+ other(^v) |> print();
+}
- print("Testing if the data was copied.");
- for i: 0, 5 do print(arr1[i]);
-}
\ No newline at end of file
+// proc #export "start2" {
+// heap_init();
+//
+// print("Creating initial memories");
+// arr1 := cast(^u32) malloc(sizeof [10] u32);
+// print_hex(cast(u64) arr1);
+//
+// arr2 := cast(^u32) malloc(sizeof [40] u32);
+// print_hex(cast(u64) arr2);
+//
+// print("Freeing arr1");
+// mfree(arr1);
+//
+// print("Resizing arr2 (shouldn't change location)");
+// arr2 = cast(^u32) mresize(arr2, sizeof [60] u32);
+// print_hex(cast(u64) arr2);
+//
+// print("Allocating arr3 (should be bigger than arr2)");
+// arr3 := cast(^u32) malloc(sizeof [30] u32);
+// print_hex(cast(u64) arr3);
+//
+// print("Allocating arr1 (should be in the same place as before)");
+// arr1 = cast(^u32) malloc(sizeof [5] u32);
+// print_hex(cast(u64) arr1);
+// for i: 0, 5 do arr1[i] = i;
+//
+// print("Resizing arr1 (should be in the same place as before)");
+// arr1 = cast(^u32) mresize(arr1, sizeof[10] u32);
+// print_hex(cast(u64) arr1);
+//
+// print("Resizing arr1 (should have moved to after arr3)");
+// arr1 = cast(^u32) mresize(arr1, sizeof[100] u32);
+// print_hex(cast(u64) arr1);
+//
+// print("Testing if the data was copied.");
+// for i: 0, 5 do print(arr1[i]);
+// }//
\ No newline at end of file
use package printing
use package memory
-sort :: proc (arr: [N]i32, cmp: proc (i32, i32) -> i32) -> [N]i32 {
+sort :: proc (arr: [N]i32, cmp: proc (i32, i32) -> i32) -> [N] i32 {
for i: 0, N {
smallest_idx := i;
return v;
}
+// NOTE: Anonymous functions do NOT have closure,
+// so in either of these function scopes, the
+// parameter 'n' is not accessible.
+//
+// This is intended behavior since creating new
+// procs at runtime is very difficult with WASM
+stupid_idea :: proc (n: i32) -> proc () -> i32 {
+ if n == 1234 {
+ return proc -> i32 { return 5678; };
+ }
+
+ return proc -> i32 { return -1; };
+}
+
some_value := 20 + 30 * 4 + 15 / 5;
start :: proc #export {
print_hex(cast(u64) some_value);
print("Hello, World!");
print_ptr(__heap_start);
- print_ptr(__stack_base);
print_ptr(__stack_top);
print_bin(42l);
print_hex(42l);
print(arr[1]|>sumN());
print(summing(cast(^i32) arr[1]));
- v1: Vec3;
- v1.x = 2;
- v1.y = 4;
- v1.z = 10;
-
- v2: Vec3;
- v2.x = 4;
- v2.y = 2;
- v2.z = 1;
-
- v3: Vec3;
- vec_add(v1, v2, ^v3);
- print(v3.x);
- print(v3.y);
- print(v3.z);
-
- print(v3|>mag_squared());
-
print(10 |> ret_val(4));
+ print(11 |> ret_val(5));
for i: 0, N do print(arr[1][i]);
|> clamp(30, 100);
print(val);
- for i: 0, N do print(something[i] |> clamp(3, 6));
+ for i: 0, N do
+ something[i]
+ |> clamp(3, 6)
+ |> print();
+
+ stupid_idea(1234)() |> print();
}
\ No newline at end of file
bh_arr_fastdelete(compiler_state->queued_files, 0);
}
+ initialize_builtins();
+
// Add builtin one-time entities
- bh_arr_push(compiler_state->prog_info.entities, ((Entity) {
- .type = Entity_Type_Global_Header,
- .global = &builtin_stack_base
- }));
bh_arr_push(compiler_state->prog_info.entities, ((Entity) {
.type = Entity_Type_Global_Header,
.global = &builtin_stack_top
}));
- bh_arr_push(compiler_state->prog_info.entities, ((Entity) {
- .type = Entity_Type_Global,
- .global = &builtin_stack_base
- }));
bh_arr_push(compiler_state->prog_info.entities, ((Entity) {
.type = Entity_Type_Global,
.global = &builtin_stack_top
--- /dev/null
+#include "onyxastnodes.h"
+#include "onyxtypes.h"
+
+AstBasicType basic_type_void = { { Ast_Kind_Basic_Type, 0, NULL, "void" }, &basic_types[Basic_Kind_Void] };
+AstBasicType basic_type_bool = { { Ast_Kind_Basic_Type, 0, NULL, "bool" }, &basic_types[Basic_Kind_Bool] };
+AstBasicType basic_type_i8 = { { Ast_Kind_Basic_Type, 0, NULL, "i8" }, &basic_types[Basic_Kind_I8] };
+AstBasicType basic_type_u8 = { { Ast_Kind_Basic_Type, 0, NULL, "u8" }, &basic_types[Basic_Kind_U8] };
+AstBasicType basic_type_i16 = { { Ast_Kind_Basic_Type, 0, NULL, "i16" }, &basic_types[Basic_Kind_I16] };
+AstBasicType basic_type_u16 = { { Ast_Kind_Basic_Type, 0, NULL, "u16" }, &basic_types[Basic_Kind_U16] };
+AstBasicType basic_type_i32 = { { Ast_Kind_Basic_Type, 0, NULL, "i32" }, &basic_types[Basic_Kind_I32] };
+AstBasicType basic_type_u32 = { { Ast_Kind_Basic_Type, 0, NULL, "u32" }, &basic_types[Basic_Kind_U32] };
+AstBasicType basic_type_i64 = { { Ast_Kind_Basic_Type, 0, NULL, "i64" }, &basic_types[Basic_Kind_I64] };
+AstBasicType basic_type_u64 = { { Ast_Kind_Basic_Type, 0, NULL, "u64" }, &basic_types[Basic_Kind_U64] };
+AstBasicType basic_type_f32 = { { Ast_Kind_Basic_Type, 0, NULL, "f32" }, &basic_types[Basic_Kind_F32] };
+AstBasicType basic_type_f64 = { { Ast_Kind_Basic_Type, 0, NULL, "f64" }, &basic_types[Basic_Kind_F64] };
+AstBasicType basic_type_rawptr = { { Ast_Kind_Basic_Type, 0, NULL, "rawptr" }, &basic_types[Basic_Kind_Rawptr] };
+
+static OnyxToken builtin_heap_start_token = { Token_Type_Symbol, 12, "__heap_start ", { 0 } };
+static OnyxToken builtin_stack_top_token = { Token_Type_Symbol, 11, "__stack_top ", { 0 } };
+AstNumLit builtin_heap_start = { Ast_Kind_NumLit, Ast_Flag_Const, &builtin_heap_start_token, NULL, (AstType *) &basic_type_rawptr, NULL, 0 };
+AstGlobal builtin_stack_top = { Ast_Kind_Global, Ast_Flag_Const | Ast_Flag_Global_Stack_Top, &builtin_stack_top_token, NULL, (AstType *) &basic_type_rawptr, NULL };
+
+const BuiltinSymbol builtin_symbols[] = {
+ { "void", (AstNode *) &basic_type_void },
+ { "bool", (AstNode *) &basic_type_bool },
+ { "i8", (AstNode *) &basic_type_i8 },
+ { "u8", (AstNode *) &basic_type_u8 },
+ { "i16", (AstNode *) &basic_type_i16 },
+ { "u16", (AstNode *) &basic_type_u16 },
+ { "i32", (AstNode *) &basic_type_i32 },
+ { "u32", (AstNode *) &basic_type_u32 },
+ { "i64", (AstNode *) &basic_type_i64 },
+ { "u64", (AstNode *) &basic_type_u64 },
+ { "f32", (AstNode *) &basic_type_f32 },
+ { "f64", (AstNode *) &basic_type_f64 },
+ { "rawptr", (AstNode *) &basic_type_rawptr },
+
+ { "__heap_start", (AstNode *) &builtin_heap_start },
+ { "__stack_top", (AstNode *) &builtin_stack_top },
+
+ { NULL, NULL },
+};
+
+void initialize_builtins() {
+}
\ No newline at end of file
if (check_expression(&call->callee)) return 1;
- // NOTE: Check arguments and splat structs
+ // NOTE: Check arguments
AstNode** prev_param = (AstNode **) &call->arguments;
AstArgument* actual_param = call->arguments;
while (actual_param != NULL) {
return 1;
}
- // NOTE: Splat structures into multiple arguments
- if (actual_param->type->kind == Type_Kind_Struct) {
- if (!type_struct_is_simple(actual_param->type)) {
- onyx_message_add(Msg_Type_Literal,
- actual_param->token->pos,
- "can only splat simple structure. nested structures or struct of arrays is not allowed.");
- return 1;
- }
-
- bh_arr_each(StructMember *, smem, actual_param->type->Struct.memarr) {
- AstFieldAccess* field = onyx_ast_node_new(semstate.node_allocator, sizeof(AstFieldAccess), Ast_Kind_Field_Access);
- field->expr = actual_param->value;
-
- // HACK: Since dereferences are not used for struct types, we need a
- // special case here.
- if (field->expr->kind == Ast_Kind_Dereference) {
- field->expr = ((AstDereference *) field->expr)->expr;
- }
-
- field->offset = (*smem)->offset;
- field->type = (*smem)->type;
-
- AstArgument* arg = onyx_ast_node_new(semstate.node_allocator, sizeof(AstArgument), Ast_Kind_Argument);
- arg->value = (AstTyped *) field;
- arg->type = field->type;
- arg->token = actual_param->token;
- arg->next = actual_param->next;
-
- call->arg_count++;
-
- *prev_param = (AstNode *) arg;
- prev_param = (AstNode **) &arg->next;
- }
- } else {
- prev_param = (AstNode **) &actual_param->next;
- }
-
+ prev_param = (AstNode **) &actual_param->next;
actual_param = (AstArgument *) actual_param->next;
}
return 1;
}
- if (field->expr->flags & Ast_Flag_Param_Splatted) {
- AstLocal* param = (AstLocal *) field->expr;
-
- u32 steps = smem.idx + 1;
- while (steps--) param = (AstLocal *) param->next;
-
- // NOTE: Not actually a field access
- *pfield = (AstFieldAccess *) param;
- token_toggle_end(field->token);
- return 0;
- }
-
field->offset = smem.offset;
field->type = smem.type;
}
CHECK(function_header, AstFunction* func) {
- i32 changed_params = 0;
-
- AstLocal **prev_param = &func->params;
AstLocal *param = func->params;
while (param != NULL) {
fill_in_type((AstTyped *) param);
return 1;
}
- if (param->type->kind == Type_Kind_Struct) {
- param->flags |= Ast_Flag_Param_Splatted;
-
- if (!type_struct_is_simple(param->type)) {
- onyx_message_add(Msg_Type_Literal,
- param->token->pos,
- "only simple structures can be passed by value");
- return 1;
- }
-
- changed_params = 1;
-
- AstLocal *first_new_param = NULL, *last_new_param = NULL;
- AstLocal** insertion = prev_param;
- bh_arr_each(StructMember *, smem, param->type->Struct.memarr) {
- AstLocal* new_param = onyx_ast_node_new(semstate.node_allocator, sizeof(AstLocal), Ast_Kind_Param);
- new_param->token = param->token;
- new_param->type = (*smem)->type;
- new_param->flags |= Ast_Flag_Const;
-
- if (first_new_param == NULL) first_new_param = new_param;
- last_new_param = new_param;
-
- *insertion = new_param;
- insertion = (AstLocal **) &new_param->next;
- }
-
- *prev_param = first_new_param;
- last_new_param->next = param->next;
- param->next = (AstNode *) first_new_param;
-
- prev_param = (AstLocal **) &last_new_param->next;
- } else {
- prev_param = (AstLocal **) ¶m->next;
- }
-
param = (AstLocal *) param->next;
}
- if (changed_params) {
- // NOTE: Need to rebuild the function parameters in a special way once the are modified.
- // This may/will get cleaned up at a later point.
-
- func->type = type_build_function_type(
- semstate.node_allocator, func,
- ((AstFunctionType *) func->type_node)->return_type);
- } else {
- fill_in_type((AstTyped *) func);
- }
+ fill_in_type((AstTyped *) func);
if ((func->flags & Ast_Flag_Exported) != 0) {
if ((func->flags & Ast_Flag_Foreign) != 0) {
bh_arr(AstType *) params = NULL;
bh_arr_new(global_scratch_allocator, params, 4);
+ bh_arr_set_length(params, 0);
expect_token(parser, '(');
while (parser->curr->type != ')') {
new->param_count = param_count;
new->return_type = return_type;
- fori (i, 0, param_count - 1) new->params[i] = params[i];
+ if (param_count > 0)
+ fori (i, 0, param_count - 1) new->params[i] = params[i];
*next_insertion = (AstType *) new;
next_insertion = NULL;
#include "onyxutils.h"
-AstBasicType basic_type_void = { { Ast_Kind_Basic_Type, 0, NULL, "void" }, &basic_types[Basic_Kind_Void] };
-AstBasicType basic_type_bool = { { Ast_Kind_Basic_Type, 0, NULL, "bool" }, &basic_types[Basic_Kind_Bool] };
-AstBasicType basic_type_i8 = { { Ast_Kind_Basic_Type, 0, NULL, "i8" }, &basic_types[Basic_Kind_I8] };
-AstBasicType basic_type_u8 = { { Ast_Kind_Basic_Type, 0, NULL, "u8" }, &basic_types[Basic_Kind_U8] };
-AstBasicType basic_type_i16 = { { Ast_Kind_Basic_Type, 0, NULL, "i16" }, &basic_types[Basic_Kind_I16] };
-AstBasicType basic_type_u16 = { { Ast_Kind_Basic_Type, 0, NULL, "u16" }, &basic_types[Basic_Kind_U16] };
-AstBasicType basic_type_i32 = { { Ast_Kind_Basic_Type, 0, NULL, "i32" }, &basic_types[Basic_Kind_I32] };
-AstBasicType basic_type_u32 = { { Ast_Kind_Basic_Type, 0, NULL, "u32" }, &basic_types[Basic_Kind_U32] };
-AstBasicType basic_type_i64 = { { Ast_Kind_Basic_Type, 0, NULL, "i64" }, &basic_types[Basic_Kind_I64] };
-AstBasicType basic_type_u64 = { { Ast_Kind_Basic_Type, 0, NULL, "u64" }, &basic_types[Basic_Kind_U64] };
-AstBasicType basic_type_f32 = { { Ast_Kind_Basic_Type, 0, NULL, "f32" }, &basic_types[Basic_Kind_F32] };
-AstBasicType basic_type_f64 = { { Ast_Kind_Basic_Type, 0, NULL, "f64" }, &basic_types[Basic_Kind_F64] };
-AstBasicType basic_type_rawptr = { { Ast_Kind_Basic_Type, 0, NULL, "rawptr" }, &basic_types[Basic_Kind_Rawptr] };
-
-static OnyxToken builtin_heap_start_token = { Token_Type_Symbol, 12, "__heap_start ", { 0 } };
-static OnyxToken builtin_stack_base_token = { Token_Type_Symbol, 12, "__stack_base ", { 0 } };
-static OnyxToken builtin_stack_top_token = { Token_Type_Symbol, 11, "__stack_top ", { 0 } };
-AstNumLit builtin_heap_start = { Ast_Kind_NumLit, Ast_Flag_Const, &builtin_heap_start_token, NULL, (AstType *) &basic_type_rawptr, NULL, 0 };
-AstGlobal builtin_stack_base = { Ast_Kind_Global, Ast_Flag_Const | Ast_Flag_Global_Stack_Base, &builtin_stack_base_token, NULL, (AstType *) &basic_type_rawptr, NULL };
-AstGlobal builtin_stack_top = { Ast_Kind_Global, Ast_Flag_Const | Ast_Flag_Global_Stack_Top, &builtin_stack_top_token, NULL, (AstType *) &basic_type_rawptr, NULL };
-
-const BuiltinSymbol builtin_symbols[] = {
- { "void", (AstNode *) &basic_type_void },
- { "bool", (AstNode *) &basic_type_bool },
- { "i8", (AstNode *) &basic_type_i8 },
- { "u8", (AstNode *) &basic_type_u8 },
- { "i16", (AstNode *) &basic_type_i16 },
- { "u16", (AstNode *) &basic_type_u16 },
- { "i32", (AstNode *) &basic_type_i32 },
- { "u32", (AstNode *) &basic_type_u32 },
- { "i64", (AstNode *) &basic_type_i64 },
- { "u64", (AstNode *) &basic_type_u64 },
- { "f32", (AstNode *) &basic_type_f32 },
- { "f64", (AstNode *) &basic_type_f64 },
- { "rawptr", (AstNode *) &basic_type_rawptr },
-
- { "__heap_start", (AstNode *) &builtin_heap_start },
- { "__stack_base", (AstNode *) &builtin_stack_base },
- { "__stack_top", (AstNode *) &builtin_stack_top },
-
- { NULL, NULL },
-};
static void scope_enter(Scope* new_scope);
static void scope_leave();
AstArgument* implicit_arg = onyx_ast_node_new(semstate.node_allocator,
sizeof(AstArgument),
Ast_Kind_Argument);
+ implicit_arg->token = (*ufc)->left->token;
implicit_arg->value = (*ufc)->left;
implicit_arg->next = (AstNode *) call_node->arguments;
if (!types_are_compatible(t1->Function.return_type, t2->Function.return_type)) return 0;
- fori (i, 0, t1->Function.param_count - 1) {
- if (!types_are_compatible(t1->Function.params[i], t2->Function.params[i])) return 0;
+ if (t1->Function.param_count > 0) {
+ fori (i, 0, t1->Function.param_count - 1) {
+ if (!types_are_compatible(t1->Function.params[i], t2->Function.params[i])) return 0;
+ }
}
return 1;
COMPILE_FUNC(block, AstBlock* block);
COMPILE_FUNC(statement, AstNode* stmt);
COMPILE_FUNC(assignment, AstBinaryOp* assign);
-COMPILE_FUNC(store_instruction, Type* type, u32 alignment, u32 offset);
+COMPILE_FUNC(store_instruction, Type* type, u32 offset);
COMPILE_FUNC(load_instruction, Type* type, u32 offset);
COMPILE_FUNC(if, AstIf* if_node);
COMPILE_FUNC(while, AstWhile* while_node);
u64 offset = 0;
compile_local_location(mod, &code, (AstLocal *) lval, &offset);
compile_expression(mod, &code, assign->right);
- compile_store_instruction(mod, &code, lval->type, type_get_alignment_log2(lval->type), offset);
+ compile_store_instruction(mod, &code, lval->type, offset);
}
} else if (lval->kind == Ast_Kind_Global) {
compile_expression(mod, &code, deref->expr);
compile_expression(mod, &code, assign->right);
- compile_store_instruction(mod, &code,
- deref->type,
- type_get_alignment_log2(deref->type),
- 0);
+ compile_store_instruction(mod, &code, deref->type, 0);
} else if (lval->kind == Ast_Kind_Array_Access) {
AstArrayAccess* aa = (AstArrayAccess *) lval;
compile_array_access_location(mod, &code, aa, &offset);
compile_expression(mod, &code, assign->right);
- compile_store_instruction(mod, &code,
- aa->type,
- type_get_alignment_log2(aa->type),
- offset);
+ compile_store_instruction(mod, &code, aa->type, offset);
} else if (lval->kind == Ast_Kind_Field_Access) {
AstFieldAccess* field = (AstFieldAccess *) lval;
compile_field_access_location(mod, &code, field, &offset);
compile_expression(mod, &code, assign->right);
- compile_store_instruction(mod, &code,
- field->type,
- type_get_alignment_log2(field->type),
- offset);
+ compile_store_instruction(mod, &code, field->type, offset);
} else {
assert(("Invalid lval", 0));
}
*pcode = code;
}
-COMPILE_FUNC(store_instruction, Type* type, u32 alignment, u32 offset) {
+COMPILE_FUNC(store_instruction, Type* type, u32 offset) {
bh_arr(WasmInstruction) code = *pcode;
+ u32 alignment = type_get_alignment_log2(type);
+
if (type->kind == Type_Kind_Enum) {
type = type->Enum.backing;
}
COMPILE_FUNC(load_instruction, Type* type, u32 offset) {
bh_arr(WasmInstruction) code = *pcode;
+ assert(("Should use compile_struct_load instead", type->kind != Type_Kind_Struct));
+
if (type->kind == Type_Kind_Array) {
if (offset != 0) {
WID(WI_I32_CONST, offset);
} else {
compile_local_location(mod, &code, var, &offset);
compile_expression(mod, &code, for_node->start);
- compile_store_instruction(mod, &code, var->type, type_get_alignment_log2(var->type), offset);
+ compile_store_instruction(mod, &code, var->type, offset);
}
WID(WI_BLOCK_START, 0x40);
compile_load_instruction(mod, &code, var->type, offset);
compile_expression(mod, &code, for_node->step);
WI(add_instr);
- compile_store_instruction(mod, &code, var->type, type_get_alignment_log2(var->type), offset);
+ compile_store_instruction(mod, &code, var->type, offset);
}
compile_deferred_stmts(mod, &code, (AstNode *) for_node);
COMPILE_FUNC(local_location, AstLocal* local, u64* offset_return) {
bh_arr(WasmInstruction) code = *pcode;
- i32 stack_base_idx = (i32) bh_imap_get(&mod->index_map, (u64) &builtin_stack_base);
i32 local_offset = (i32) bh_imap_get(&mod->local_map, (u64) local);
- WID(WI_GLOBAL_GET, stack_base_idx);
+ WID(WI_LOCAL_GET, mod->stack_base_idx);
*offset_return += local_offset;
*pcode = code;
}
+COMPILE_FUNC(struct_load, AstTyped* expr) {
+ bh_arr(WasmInstruction) code = *pcode;
+
+ assert(expr->type->kind == Type_Kind_Struct);
+
+ u64 offset = 0;
+
+ bh_arr_each(StructMember *, smem, expr->type->Struct.memarr) {
+ offset = 0;
+
+ switch (expr->kind) {
+ case Ast_Kind_Local: compile_local_location(mod, &code, (AstLocal *) expr, &offset); break;
+ case Ast_Kind_Dereference: compile_expression(mod, &code, ((AstDereference *) expr)->expr); break;
+ case Ast_Kind_Array_Access: compile_array_access_location(mod, &code, (AstArrayAccess *) expr, &offset); break;
+ case Ast_Kind_Field_Access: compile_field_access_location(mod, &code, (AstFieldAccess *) expr, &offset); break;
+
+ default: assert(0);
+ }
+
+ compile_load_instruction(mod, &code, (*smem)->type, offset + (*smem)->offset);
+ }
+
+ *pcode = code;
+}
+
COMPILE_FUNC(expression, AstTyped* expr) {
bh_arr(WasmInstruction) code = *pcode;
if (tmp & LOCAL_IS_WASM) {
WID(WI_LOCAL_GET, (u32) (tmp & ~LOCAL_IS_WASM));
} else {
+ if (expr->type->kind == Type_Kind_Struct) {
+ compile_struct_load(mod, &code, expr);
+ break;
+ }
+
u64 offset = 0;
compile_local_location(mod, &code, (AstLocal *) expr, &offset);
}
case Ast_Kind_Dereference: {
+ if (expr->type->kind == Type_Kind_Struct) {
+ compile_struct_load(mod, &code, expr);
+ break;
+ }
+
AstDereference* deref = (AstDereference *) expr;
compile_expression(mod, &code, deref->expr);
compile_load_instruction(mod, &code, deref->type, 0);
}
case Ast_Kind_Array_Access: {
+ if (expr->type->kind == Type_Kind_Struct) {
+ compile_struct_load(mod, &code, expr);
+ break;
+ }
+
AstArrayAccess* aa = (AstArrayAccess *) expr;
u64 offset = 0;
compile_array_access_location(mod, &code, aa, &offset);
}
case Ast_Kind_Field_Access: {
+ if (expr->type->kind == Type_Kind_Struct) {
+ compile_struct_load(mod, &code, expr);
+ break;
+ }
+
AstFieldAccess* field = (AstFieldAccess* ) expr;
+ if (field->expr->kind == Ast_Kind_Param && field->expr->type->kind == Type_Kind_Struct) {
+ StructMember smem;
+
+ token_toggle_end(field->token);
+ type_struct_lookup_member(field->expr->type, field->token->text, &smem);
+ token_toggle_end(field->token);
+
+ i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) field->expr) + smem.idx;
+
+ WID(WI_LOCAL_GET, localidx);
+ break;
+ }
+
u64 offset = 0;
compile_field_access_location(mod, &code, field, &offset);
compile_load_instruction(mod, &code, field->type, offset);
bh_arr(WasmInstruction) code = *pcode;
u32 stack_top_idx = bh_imap_get(&mod->index_map, (u64) &builtin_stack_top);
- u32 stack_base_idx = bh_imap_get(&mod->index_map, (u64) &builtin_stack_base);
WID(WI_GLOBAL_GET, stack_top_idx);
- WID(WI_GLOBAL_GET, stack_base_idx);
- WID(WI_I32_STORE, ((WasmInstructionData) { 2, 0 }));
- WID(WI_GLOBAL_GET, stack_top_idx);
- WID(WI_I32_CONST, 4);
- WI(WI_I32_ADD);
- WID(WI_GLOBAL_SET, stack_top_idx);
- WID(WI_GLOBAL_GET, stack_top_idx);
- WID(WI_GLOBAL_SET, stack_base_idx);
- WID(WI_GLOBAL_GET, stack_top_idx);
+ WID(WI_LOCAL_TEE, mod->stack_base_idx);
WID(WI_I32_CONST, stacksize);
WI(WI_I32_ADD);
- WID(WI_GLOBAL_SET, stack_top_idx);
+ WID(WI_GLOBAL_SET, stack_top_idx);
*pcode = code;
}
bh_arr(WasmInstruction) code = *pcode;
u32 stack_top_idx = bh_imap_get(&mod->index_map, (u64) &builtin_stack_top);
- u32 stack_base_idx = bh_imap_get(&mod->index_map, (u64) &builtin_stack_base);
-
- WID(WI_GLOBAL_GET, stack_base_idx);
- WID(WI_GLOBAL_SET, stack_top_idx);
- WID(WI_GLOBAL_GET, stack_top_idx);
- WID(WI_I32_CONST, 4);
- WI(WI_I32_SUB);
+ WID(WI_LOCAL_GET, mod->stack_base_idx);
WID(WI_GLOBAL_SET, stack_top_idx);
- WID(WI_GLOBAL_GET, stack_top_idx);
- WID(WI_I32_LOAD, ((WasmInstructionData) { 2, 0 }));
- WID(WI_GLOBAL_SET, stack_base_idx);
-
*pcode = code;
}
i32 param_count = ft->Function.param_count;
i32 params_left = param_count;
while (params_left-- > 0) {
- // HACK: Using these directly as part of a string feels weird but they are
- // valid characters so I don't think it is going to be much of an issue
- *(t++) = (char) onyx_type_to_wasm_type(*param_type);
+ if ((*param_type)->kind == Type_Kind_Struct) {
+ bh_arr_each(StructMember *, smem, (*param_type)->Struct.memarr) {
+ *(t++) = (char) onyx_type_to_wasm_type((*smem)->type);
+ }
+
+ param_count += (*param_type)->Struct.mem_count - 1;
+
+ } else {
+ *(t++) = (char) onyx_type_to_wasm_type(*param_type);
+ }
+
param_type++;
}
*(t++) = ':';
WasmFunc wasm_func = {
.type_idx = type_idx,
.locals = {
- .i32_count = 0,
+ .i32_count = 1, // NOTE: for the old stack base
.i64_count = 0,
.f32_count = 0,
.f64_count = 0,
// NOTE: Generate the local map
u64 localidx = 0;
for (AstLocal *param = fd->params; param != NULL; param = (AstLocal *) param->next) {
- bh_imap_put(&mod->local_map, (u64) param, localidx++ | LOCAL_IS_WASM);
+ if (param->type->kind == Type_Kind_Struct) {
+ bh_imap_put(&mod->local_map, (u64) param, localidx);
+ localidx += param->type->Struct.mem_count;
+
+ } else {
+ bh_imap_put(&mod->local_map, (u64) param, localidx++ | LOCAL_IS_WASM);
+ }
}
static const WasmType local_types[4] = { WASM_TYPE_INT32, WASM_TYPE_INT64, WASM_TYPE_FLOAT32, WASM_TYPE_FLOAT64 };
+ mod->stack_base_idx = localidx++;
+
// HACK: This assumes that the order of the count members
// is the same as the order of the local_types above
u8* count = &wasm_func.locals.i32_count;
if (global->flags & Ast_Flag_Global_Stack_Top)
module->stack_top_ptr = &bh_arr_last(module->globals).initial_value[0].data.i1;
- if (global->flags & Ast_Flag_Global_Stack_Base)
- module->stack_base_ptr = &bh_arr_last(module->globals).initial_value[0].data.i1;
}
.structured_jump_target = NULL,
.stack_top_ptr = NULL,
- .stack_base_ptr = NULL,
+ .stack_base_idx = 0,
};
bh_arr_new(alloc, module.types, 4);
bh_arr_each(Entity, entity, program->entities) {
- if (module->stack_base_ptr) {
- *module->stack_base_ptr = module->next_datum_offset;
+ if (module->stack_top_ptr) {
+ *module->stack_top_ptr = module->next_datum_offset;
- if (*module->stack_base_ptr % 16 != 0) {
- *module->stack_base_ptr += 16 - (*module->stack_base_ptr % 16);
+ if (*module->stack_top_ptr % 16 != 0) {
+ *module->stack_top_ptr += 16 - (*module->stack_top_ptr % 16);
}
- if (module->stack_top_ptr)
- *module->stack_top_ptr = *module->stack_base_ptr;
-
- builtin_heap_start.value.i = *module->stack_base_ptr + (1 << 16);
+ builtin_heap_start.value.i = *module->stack_top_ptr + (1 << 16);
if (builtin_heap_start.value.i % 16 != 0) {
builtin_heap_start.value.i += 16 - (builtin_heap_start.value.i % 16);
}