From c6257b799c5c54bb1333c1dd2b1a19d570b6f0ff Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Mon, 24 Aug 2020 12:11:12 -0500 Subject: [PATCH] Added slice types; bugfixes --- core/builtin.onyx | 6 +- core/string.onyx | 61 +++++++++------- docs/plan | 16 ++--- include/onyxastnodes.h | 6 ++ include/onyxtypes.h | 3 +- onyx | Bin 170368 -> 174496 bytes progs/wasi_test.onyx | 47 ++++++++---- src/onyxchecker.c | 48 +++++++++++++ src/onyxparser.c | 50 +++++++++---- src/onyxsymres.c | 21 ++++-- src/onyxtypes.c | 41 +++++++++-- src/onyxutils.c | 2 + src/onyxwasm.c | 158 +++++++++++++++++++++++++++-------------- 13 files changed, 331 insertions(+), 128 deletions(-) diff --git a/core/builtin.onyx b/core/builtin.onyx index 18788c37..ebac5985 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -1,8 +1,4 @@ package builtin -string :: struct { - data : ^u8; - len : u32; -} - +string :: #type []u8; cstring :: #type ^u8; \ No newline at end of file diff --git a/core/string.onyx b/core/string.onyx index c3b41433..ebfbfaaa 100644 --- a/core/string.onyx +++ b/core/string.onyx @@ -15,7 +15,7 @@ string_make :: proc #overloaded { string_make_from_cstring } string_make_from_cstring :: proc (s: cstring) -> string { len :: string_length(s); - return string.{ len = len, data = s }; + return string.{ count = len, data = s }; } string_length :: proc #overloaded { @@ -31,12 +31,12 @@ string_length :: proc #overloaded { }, proc (s: string) -> u32 { - return s.len; + return s.count; }, } #private -string_length_string :: proc (s: string) -> u32 do return s.len; +string_length_string :: proc (s: string) -> u32 do return s.count; string_concat :: proc (a: Allocator, s1: string, s2: string) -> string { len1 :: string_length(s1); @@ -58,27 +58,37 @@ StringSplitResult :: struct { string_split :: proc (a: Allocator, str: string, delim: u8) -> StringSplitResult { delim_count := 0; - for i: 0, str.len do if str.data[i] == delim do delim_count += 1; + for i: 0, str.count do if str.data[i] == delim do delim_count += 1; strarr := cast(^string) alloc(a, sizeof string * (delim_count + 1)); curr_str := 0; - begin := str.data; + begin := 0; - for i: 0, str.len { + for i: 0, str.count { if str.data[i] == delim { - strarr[curr_str] = string.{ begin, cast(u32) ^str.data[i] - cast(u32) begin }; - begin = ^str.data[i + 1]; + strarr[curr_str] = str.data[begin : i]; + begin = i + 1; curr_str += 1; } } - strarr[curr_str] = string.{ begin, cast(u32) str.data + str.len - cast(u32) begin }; + strarr[curr_str] = str.data[begin : str.count]; return StringSplitResult.{ strarr, delim_count + 1 }; } +string_substr :: proc (str: string, sub: string) -> string { + for i: 0, str.count { + while j := 0; j < sub.count && str.data[i + j] == sub.data[j] { + j += 1; + if j == sub.count do return str.data[i : i + j]; + } + } + + return str.data[0:0]; +} StringBuilder :: struct { alloc : Allocator; @@ -103,11 +113,11 @@ string_builder_make :: proc (a: Allocator, initial_cap: u32) -> StringBuilder { } string_builder_add_string :: proc (use sb: ^StringBuilder, str: string) -> ^StringBuilder { - len_total :: len + str.len; + len_total :: len + str.count; if cap >= len_total { - for i: 0, str.len do data[len + i] = str.data[i]; - len += str.len; + for i: 0, str.count do data[len + i] = str.data[i]; + len += str.count; return sb; } @@ -120,8 +130,8 @@ string_builder_add_string :: proc (use sb: ^StringBuilder, str: string) -> ^Stri data = new_data; cap = new_cap; - for i: 0, str.len do data[len + i] = str.data[i]; - len += str.len; + for i: 0, str.count do data[len + i] = str.data[i]; + len += str.count; return sb; } @@ -141,20 +151,19 @@ u64_to_string :: proc (n_: u64, base: u64, buf: Buffer) -> string { s :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; - if n == 0l { - *c = #char "0"; + while n > 0l { + m :: n % base; + + *c = s.data[cast(u32) m]; len += 1; c -= 1; - } else { - while n > 0l { - m :: n % base; - *c = s.data[cast(u32) m]; - len += 1; - c -= 1; - - n /= base; - } + n /= base; + + } else { + *c = #char "0"; + len += 1; + c -= 1; } if base == 16l { @@ -175,7 +184,7 @@ u64_to_string :: proc (n_: u64, base: u64, buf: Buffer) -> string { c -= 1; } - return string.{ data = c + 1, len = len }; + return string.{ data = c + 1, count = len }; } string_builder_add_u64 :: proc (use sb: ^StringBuilder, n: u64) -> ^StringBuilder { diff --git a/docs/plan b/docs/plan index 0a230bab..b34d368c 100644 --- a/docs/plan +++ b/docs/plan @@ -199,6 +199,14 @@ HOW: // Loop never run } + [X] Add slices + - Arrays without a size + - Converted to a struct that looks like: + []T :: struct { + data : ^T; + count : u32; + } + [ ] 'use' enums and packages at an arbitrary scope [ ] convert to using an 'atom' like table @@ -218,14 +226,6 @@ HOW: - But, profiling says we are spending 50% of the program execution time in the lexer - That is awful - [ ] Add slices - - Arrays without a size - - Converted to a struct that looks like: - []T :: struct { - data : ^T; - count : u32; - } - [ ] Variadic arguments [ ] 'when' statements diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index c9814df0..c67803f9 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -19,6 +19,7 @@ typedef struct AstArgument AstArgument; typedef struct AstAddressOf AstAddressOf; typedef struct AstDereference AstDereference; typedef struct AstArrayAccess AstArrayAccess; +typedef struct AstSlice AstSlice; typedef struct AstFieldAccess AstFieldAccess; typedef struct AstSizeOf AstSizeOf; typedef struct AstAlignOf AstAlignOf; @@ -39,6 +40,7 @@ typedef struct AstBasicType AstBasicType; typedef struct AstPointerType AstPointerType; typedef struct AstFunctionType AstFunctionType; typedef struct AstArrayType AstArrayType; +typedef struct AstSliceType AstSliceType; typedef struct AstStructType AstStructType; typedef struct AstStructMember AstStructMember; typedef struct AstEnumType AstEnumType; @@ -93,6 +95,7 @@ typedef enum AstKind { Ast_Kind_Pointer_Type, Ast_Kind_Function_Type, Ast_Kind_Array_Type, + Ast_Kind_Slice_Type, Ast_Kind_Struct_Type, Ast_Kind_Enum_Type, Ast_Kind_Type_Alias, @@ -111,6 +114,7 @@ typedef enum AstKind { Ast_Kind_Address_Of, Ast_Kind_Dereference, Ast_Kind_Array_Access, + Ast_Kind_Slice, Ast_Kind_Field_Access, Ast_Kind_Ufc, Ast_Kind_Size_Of, @@ -283,6 +287,7 @@ struct AstArgument { AstTyped_base; AstTyped *value; }; struct AstAddressOf { AstTyped_base; AstTyped *expr; }; struct AstDereference { AstTyped_base; AstTyped *expr; }; struct AstArrayAccess { AstTyped_base; AstTyped *addr; AstTyped *expr; u64 elem_size; }; +struct AstSlice { AstTyped_base; AstTyped *addr; AstTyped *lo, *hi; u64 elem_size; }; struct AstFieldAccess { AstTyped_base; AstTyped *expr; u64 offset; }; struct AstSizeOf { AstTyped_base; AstType *so_type; u64 size; }; struct AstAlignOf { AstTyped_base; AstType *ao_type; u64 alignment; }; @@ -346,6 +351,7 @@ struct AstBasicType { AstType_base; Type* type; }; struct AstPointerType { AstType_base; AstType* elem; }; struct AstFunctionType { AstType_base; AstType* return_type; u64 param_count; AstType* params[]; }; struct AstArrayType { AstType_base; AstType* elem; AstTyped *count_expr; }; +struct AstSliceType { AstType_base; AstType* elem; }; struct AstStructType { AstType_base; diff --git a/include/onyxtypes.h b/include/onyxtypes.h index 27cd1a9d..1bfd25a5 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -62,7 +62,7 @@ typedef struct StructMember { TYPE_KIND(Struct, struct { \ char* name; \ u32 size; \ - u16 aligment, mem_count; \ + u16 alignment, mem_count; \ bh_table(StructMember) members; \ bh_arr(StructMember *) memarr; \ }) \ @@ -112,6 +112,7 @@ Type* type_build_from_ast(bh_allocator alloc, struct AstType* type_node); Type* type_build_function_type(bh_allocator alloc, struct AstFunction* func, struct AstType* return_type); Type* type_make_pointer(bh_allocator alloc, Type* to); +Type* type_make_slice(bh_allocator alloc, Type* of); const char* type_get_name(Type* type); u32 type_get_alignment_log2(Type* type); diff --git a/onyx b/onyx index a8ec773716b9d5449f5a0adfaa03f6b21d7a0e87..429da3352666060f26715b90e66b31f200fb030f 100755 GIT binary patch delta 61287 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 diff --git a/progs/wasi_test.onyx b/progs/wasi_test.onyx index 4e1ff14d..6743d1b4 100644 --- a/progs/wasi_test.onyx +++ b/progs/wasi_test.onyx @@ -62,7 +62,7 @@ print_u64_with_base :: proc (n_: u64, base: u64) { } print_string :: proc (s: string) -> u32 { - vec := IOVec.{ buf = s.data, len = s.len }; + vec := IOVec.{ buf = s.data, len = s.count }; tmp : Size; fd_write(1, IOVecArray.{ ^vec, 1 }, ^tmp); fd_datasync(1); @@ -190,13 +190,25 @@ output_s :: proc (sb: ^StringBuilder, s: ^S) -> ^StringBuilder { return sb; } +print_arr :: proc (sb: ^StringBuilder, arr: []i32) { + sb |> string_builder_clear(); + + a := arr.data; + + for i: 0, arr.count { + sb |> sba(cast(u64) a[i]) |> sba(" "); + } + + sb |> sba("\n") |> string_builder_to_string() |> print(); +} + main :: proc (argc: u32, argv: ^cstring) { sb := string_builder_make(heap_allocator, 256); timer := timer_start(); defer { ^sb |> string_builder_clear() - |> sba("Time taken: ") + |> sba("\nTime taken: ") |> sba(cast(u64) timer_end(timer), 10l) |> sba("ms\n") |> string_builder_to_string() @@ -213,15 +225,7 @@ main :: proc (argc: u32, argv: ^cstring) { |> print(); fd: FileDescriptor = -1; - if err := path_open(3, - LookupFlags.SymLinkFollow, - string_make(argv[1]), - cast(OFlags) 0, - Rights.DataSync | Rights.Write | Rights.Read | Rights.Tell | Rights.Seek | Rights.Advise | Rights.PathOpen | Rights.PathCreateFile, - Rights.DataSync | Rights.Write | Rights.Read | Rights.Tell | Rights.Seek | Rights.Advise | Rights.PathOpen | Rights.PathCreateFile, - FDFlags.Sync, - ^fd); - err != Errno.Success { + if err := path_open(3, LookupFlags.SymLinkFollow, string_make(argv[1]), cast(OFlags) 0, Rights.DataSync | Rights.Write | Rights.Read | Rights.Tell | Rights.Seek | Rights.Advise | Rights.PathOpen | Rights.PathCreateFile, Rights.DataSync | Rights.Write | Rights.Read | Rights.Tell | Rights.Seek | Rights.Advise | Rights.PathOpen | Rights.PathCreateFile, FDFlags.Sync, ^fd); err != Errno.Success { print("Failed to open file\n"); print("Error code: "); print_u64_with_base(cast(u64) err, 16l); @@ -301,10 +305,27 @@ main :: proc (argc: u32, argv: ^cstring) { |> print(); } - while i := 10; i < 10 { - print("Looping\n"); + ^sb |> string_builder_clear(); + while i := 0; i < 10 { + ^sb |> sba("Loop: ") |> sba(cast(u64) i) |> sba("\n"); + i += 1; } else { print("Never ran the loop\n"); } + + ^sb |> string_builder_to_string() |> print(); + + + arr : [128] i32; + for i: 0, 128 do arr[i] = i * i; + + slice := arr[14 : 20]; + + print_arr(^sb, slice); + + ss := string_substr("Hello, WoWorld!", "World"); + if ss.count > 0 { + print(ss); + } } diff --git a/src/onyxchecker.c b/src/onyxchecker.c index feace16d..c93ed3c4 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -20,6 +20,7 @@ CHECK(expression, AstTyped** expr); CHECK(address_of, AstAddressOf* aof); CHECK(dereference, AstDereference* deref); CHECK(array_access, AstArrayAccess* expr); +CHECK(slice, AstSlice* sl); CHECK(field_access, AstFieldAccess** pfield); CHECK(size_of, AstSizeOf* so); CHECK(align_of, AstAlignOf* ao); @@ -757,6 +758,52 @@ CHECK(array_access, AstArrayAccess* aa) { return 0; } +CHECK(slice, AstSlice* sl) { + if (check_expression(&sl->addr)) return 1; + if (check_expression(&sl->lo)) return 1; + if (check_expression(&sl->hi)) return 1; + + if (!type_is_pointer(sl->addr->type)) { + onyx_message_add(Msg_Type_Literal, + sl->token->pos, + "expected pointer or array type for left of slice creation"); + return 1; + } + + if (sl->lo->type->kind != Type_Kind_Basic + || (sl->lo->type->Basic.kind != Basic_Kind_I32 && sl->lo->type->Basic.kind != Basic_Kind_U32)) { + onyx_message_add(Msg_Type_Literal, + sl->token->pos, + "expected 32-bit integer type for lower index"); + return 1; + } + + if (sl->hi->type->kind != Type_Kind_Basic + || (sl->hi->type->Basic.kind != Basic_Kind_I32 && sl->hi->type->Basic.kind != Basic_Kind_U32)) { + onyx_message_add(Msg_Type_Literal, + sl->token->pos, + "expected 32-bit integer type for upper index"); + return 1; + } + + Type *of = NULL; + if (sl->addr->type->kind == Type_Kind_Pointer) + of = sl->addr->type->Pointer.elem; + else if (sl->addr->type->kind == Type_Kind_Array) + of = sl->addr->type->Array.elem; + else { + onyx_message_add(Msg_Type_Literal, + sl->token->pos, + "invalid type for left of slice creation"); + return 1; + } + + sl->type = type_make_slice(semstate.node_allocator, of); + sl->elem_size = type_size_of(of); + + return 0; +} + CHECK(field_access, AstFieldAccess** pfield) { AstFieldAccess* field = *pfield; if (check_expression(&field->expr)) return 1; @@ -838,6 +885,7 @@ CHECK(expression, AstTyped** pexpr) { case Ast_Kind_Address_Of: retval = check_address_of((AstAddressOf *) expr); break; case Ast_Kind_Dereference: retval = check_dereference((AstDereference *) expr); break; case Ast_Kind_Array_Access: retval = check_array_access((AstArrayAccess *) expr); break; + case Ast_Kind_Slice: retval = check_slice((AstSlice *) expr); break; case Ast_Kind_Field_Access: retval = check_field_access((AstFieldAccess **) pexpr); break; case Ast_Kind_Size_Of: retval = check_size_of((AstSizeOf *) expr); break; case Ast_Kind_Align_Of: retval = check_align_of((AstAlignOf *) expr); break; diff --git a/src/onyxparser.c b/src/onyxparser.c index bbd2cfa9..5c1b18c8 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -480,14 +480,32 @@ static AstTyped* parse_factor(OnyxParser* parser) { switch ((u16) parser->curr->type) { case '[': { - AstArrayAccess* aa_node = make_node(AstArrayAccess, Ast_Kind_Array_Access); - aa_node->token = expect_token(parser, '['); - aa_node->addr = retval; - aa_node->expr = parse_expression(parser); + OnyxToken *open_bracket = expect_token(parser, '['); + AstTyped *lo = parse_expression(parser); - expect_token(parser, ']'); + if (parser->curr->type == ':') { + consume_token(parser); + + AstSlice *sl_node = make_node(AstSlice, Ast_Kind_Slice); + sl_node->token = open_bracket; + sl_node->addr = retval; + sl_node->lo = lo; + sl_node->hi = parse_expression(parser); + + retval = (AstTyped *) sl_node; + expect_token(parser, ']'); + goto factor_parsed; + + } else { + AstArrayAccess* aa_node = make_node(AstArrayAccess, Ast_Kind_Array_Access); + aa_node->token = open_bracket; + aa_node->addr = retval; + aa_node->expr = lo; + + retval = (AstTyped *) aa_node; + expect_token(parser, ']'); + } - retval = (AstTyped *) aa_node; break; } @@ -1075,15 +1093,21 @@ static AstType* parse_type(OnyxParser* parser) { } else if (parser->curr->type == '[') { - AstArrayType* new = make_node(AstArrayType, Ast_Kind_Array_Type); - new->token = expect_token(parser, '['); + AstSliceType *new; + OnyxToken *open_bracket = expect_token(parser, '['); - if (parser->curr->type != ']') - new->count_expr = parse_expression(parser); + if (parser->curr->type == ']') { + new = make_node(AstSliceType, Ast_Kind_Slice_Type); + new->token = open_bracket; + } else { + new = make_node(AstArrayType, Ast_Kind_Array_Type); + new->token = open_bracket; + ((AstArrayType *) new)->count_expr = parse_expression(parser); + } - expect_token(parser, ']'); - *next_insertion = (AstType *) new; - next_insertion = &new->elem; + expect_token(parser, ']'); + *next_insertion = (AstType *) new; + next_insertion = &new->elem; } else if (parser->curr->type == Token_Type_Keyword_Proc) { diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 603e5a63..4c88b126 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -115,6 +115,13 @@ static AstType* symres_type(AstType* type) { return type; } + if (type->kind == Ast_Kind_Slice_Type) { + AstSliceType* s_node = (AstSliceType *) type; + s_node->elem = symres_type(s_node->elem); + + return type; + } + onyx_message_add(Msg_Type_Literal, (OnyxFilePos) { 0 }, onyx_ast_node_kind_string(type->kind)); @@ -217,16 +224,16 @@ static void symres_struct_literal(AstStructLiteral* sl) { if (sl->stnode != NULL) symres_expression(&sl->stnode); if (sl->stnode == NULL) return; - if (sl->stnode->kind != Ast_Kind_Struct_Type) { + sl->type_node = (AstType *) sl->stnode; + sl->type = type_build_from_ast(semstate.allocator, sl->type_node); + + if (sl->type->kind != Type_Kind_Struct) { onyx_message_add(Msg_Type_Literal, sl->token->pos, "type is not a struct type (BAD ERROR MESSAGE)"); return; } - sl->type_node = (AstType *) sl->stnode; - sl->type = type_build_from_ast(semstate.allocator, sl->type_node); - if (bh_arr_length(sl->values) == 0) { bh_arr_set_length(sl->values, sl->type->Struct.mem_count); bh_arr_zero(sl->values); @@ -312,6 +319,12 @@ static void symres_expression(AstTyped** expr) { symres_expression(&((AstArrayAccess *)(*expr))->expr); break; + case Ast_Kind_Slice: + symres_expression(&((AstSlice *)(*expr))->addr); + symres_expression(&((AstSlice *)(*expr))->lo); + symres_expression(&((AstSlice *)(*expr))->hi); + break; + case Ast_Kind_Struct_Literal: symres_struct_literal((AstStructLiteral *)(*expr)); break; diff --git a/src/onyxtypes.c b/src/onyxtypes.c index c921abfe..602c5dc9 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -47,8 +47,12 @@ b32 types_are_surface_compatible(Type* t1, Type* t2) { break; case Type_Kind_Pointer: - if (t2->kind == Type_Kind_Pointer) return 1; - break; + if (t2->kind != Type_Kind_Pointer) return 0; + + if (t1->Pointer.elem->kind == Type_Kind_Basic && t2->Pointer.elem->kind == Type_Kind_Basic) + return types_are_compatible(t1->Pointer.elem, t2->Pointer.elem); + + return 1; case Type_Kind_Array: { if (t2->kind != Type_Kind_Array) return 0; @@ -205,7 +209,7 @@ u32 type_alignment_of(Type* type) { case Type_Kind_Pointer: return 4; case Type_Kind_Function: return 4; case Type_Kind_Array: return type_alignment_of(type->Array.elem); - case Type_Kind_Struct: return type->Struct.aligment; + case Type_Kind_Struct: return type->Struct.alignment; case Type_Kind_Enum: return type_alignment_of(type->Enum.backing); default: return 1; } @@ -321,7 +325,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { } alignment = bh_max(s_node->min_alignment, alignment); - s_type->Struct.aligment = alignment; + s_type->Struct.alignment = alignment; if (size % alignment != 0) { size += alignment - (size % alignment); @@ -347,6 +351,10 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { return enum_type; } + case Ast_Kind_Slice_Type: { + return type_make_slice(alloc, type_build_from_ast(alloc, ((AstSliceType *) type_node)->elem)); + } + case Ast_Kind_Basic_Type: return ((AstBasicType *) type_node)->type; @@ -399,6 +407,31 @@ Type* type_make_pointer(bh_allocator alloc, Type* to) { return ptr_type; } +Type* type_make_slice(bh_allocator alloc, Type* of) { + Type* s_type = bh_alloc(alloc, sizeof(Type)); + s_type->kind = Type_Kind_Struct; + s_type->Struct.name = bh_aprintf(global_heap_allocator, "[] %s", type_get_name(of)); + s_type->Struct.mem_count = 2; + s_type->Struct.memarr = NULL; + + bh_table_init(global_heap_allocator, s_type->Struct.members, s_type->Struct.mem_count); + bh_arr_new(global_heap_allocator, s_type->Struct.memarr, s_type->Struct.mem_count); + + StructMember smem; + smem = (StructMember) { .offset = 0, .type = type_make_pointer(alloc, of), .idx = 0, }; + bh_table_put(StructMember, s_type->Struct.members, "data", smem); + smem = (StructMember) { .offset = 4, .type = &basic_types[Basic_Kind_U32], .idx = 1, }; + bh_table_put(StructMember, s_type->Struct.members, "count", smem); + + bh_arr_push(s_type->Struct.memarr, &bh_table_get(StructMember, s_type->Struct.members, "data")); + bh_arr_push(s_type->Struct.memarr, &bh_table_get(StructMember, s_type->Struct.members, "count")); + + s_type->Struct.alignment = 4; + s_type->Struct.size = 8; + + return s_type; +} + const char* type_get_name(Type* type) { if (type == NULL) return "unknown"; diff --git a/src/onyxutils.c b/src/onyxutils.c index 8dbacf26..3ed98c55 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -40,6 +40,7 @@ static const char* ast_node_names[] = { "POINTER_TYPE", "FUNCTION_TYPE", "ARRAY TYPE", + "SLICE TYPE", "STRUCT TYPE", "ENUM TYPE", "TYPE_ALIAS", @@ -58,6 +59,7 @@ static const char* ast_node_names[] = { "ADDRESS OF", "DEREFERENCE", "ARRAY_ACCESS", + "SLICE", "FIELD_ACCESS", "UFC", "SIZE OF", diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 3ba6923c..57978683 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -370,6 +370,7 @@ COMPILE_FUNC(array_access_location, AstArrayAccess* aa, u64* offset_retu COMPILE_FUNC(field_access_location, AstFieldAccess* field, u64* offset_return); COMPILE_FUNC(local_location, AstLocal* local, u64* offset_return); COMPILE_FUNC(memory_reservation_location, AstMemRes* memres); +COMPILE_FUNC(location, AstTyped* expr); COMPILE_FUNC(struct_load, Type* type, u64 offset); COMPILE_FUNC(struct_lval, AstTyped* lval); COMPILE_FUNC(struct_store, Type* type, u64 offset); @@ -1150,11 +1151,19 @@ COMPILE_FUNC(local_location, AstLocal* local, u64* offset_return) { bh_arr(WasmInstruction) code = *pcode; u64 local_offset = (u64) bh_imap_get(&mod->local_map, (u64) local); - assert((local_offset & (LOCAL_IS_WASM | LOCAL_F64)) == 0); - WIL(WI_LOCAL_GET, mod->stack_base_idx); + if (local_offset & LOCAL_IS_WASM) { + // HACK: This case doesn't feel quite right. I think the + // only way to end up here is if you are taking the slice + // off a pointer that is a local. But this still feels + // like the wrong long term solution. + WIL(WI_LOCAL_GET, local_offset); - *offset_return += local_offset; + } else { + WIL(WI_LOCAL_GET, mod->stack_base_idx); + + *offset_return += local_offset; + } *pcode = code; } @@ -1270,6 +1279,78 @@ COMPILE_FUNC(struct_literal, AstStructLiteral* sl) { *pcode = code; } +COMPILE_FUNC(location, AstTyped* expr) { + bh_arr(WasmInstruction) code = *pcode; + + switch (expr->kind) { + case Ast_Kind_Local: { + u64 offset = 0; + compile_local_location(mod, &code, (AstLocal *) expr, &offset); + if (offset != 0) { + WID(WI_I32_CONST, offset); + WI(WI_I32_ADD); + } + break; + } + + case Ast_Kind_Dereference: { + compile_expression(mod, &code, ((AstDereference *) expr)->expr); + break; + } + + case Ast_Kind_Array_Access: { + AstArrayAccess* aa = (AstArrayAccess *) expr; + u64 offset = 0; + compile_array_access_location(mod, &code, aa, &offset); + if (offset != 0) { + WID(WI_I32_CONST, offset); + WI(WI_I32_ADD); + } + break; + } + + case Ast_Kind_Field_Access: { + 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); + + u64 localidx = bh_imap_get(&mod->local_map, (u64) field->expr) + smem.idx; + + WIL(WI_LOCAL_GET, localidx); + break; + } + + u64 offset = 0; + compile_field_access_location(mod, &code, field, &offset); + if (offset != 0) { + WID(WI_I32_CONST, offset); + WI(WI_I32_ADD); + } + break; + } + + case Ast_Kind_Memres: { + AstMemRes* memres = (AstMemRes *) expr; + WID(WI_I32_CONST, memres->addr); + break; + } + + default: { + onyx_message_add(Msg_Type_Literal, + (OnyxFilePos) { 0 }, + "location unknown"); + break; + } + } + + *pcode = code; +} + COMPILE_FUNC(expression, AstTyped* expr) { bh_arr(WasmInstruction) code = *pcode; @@ -1371,57 +1452,7 @@ COMPILE_FUNC(expression, AstTyped* expr) { case Ast_Kind_Address_Of: { AstAddressOf* aof = (AstAddressOf *) expr; - - switch (aof->expr->kind) { - case Ast_Kind_Local: { - u64 offset = 0; - compile_local_location(mod, &code, (AstLocal *) aof->expr, &offset); - if (offset != 0) { - WID(WI_I32_CONST, offset); - WI(WI_I32_ADD); - } - break; - } - - case Ast_Kind_Dereference: { - compile_expression(mod, &code, ((AstDereference *) aof->expr)->expr); - break; - } - - case Ast_Kind_Array_Access: { - AstArrayAccess* aa = (AstArrayAccess *) aof->expr; - u64 offset = 0; - compile_array_access_location(mod, &code, aa, &offset); - if (offset != 0) { - WID(WI_I32_CONST, offset); - WI(WI_I32_ADD); - } - break; - } - - case Ast_Kind_Field_Access: { - AstFieldAccess* field = (AstFieldAccess *) aof->expr; - u64 offset = 0; - compile_field_access_location(mod, &code, field, &offset); - if (offset != 0) { - WID(WI_I32_CONST, offset); - WI(WI_I32_ADD); - } - break; - } - - case Ast_Kind_Memres: { - AstMemRes* memres = (AstMemRes *) aof->expr; - WID(WI_I32_CONST, memres->addr); - break; - } - - default: - onyx_message_add(Msg_Type_Literal, - aof->token->pos, - "unsupported address of"); - } - + compile_location(mod, &code, aof->expr); break; } @@ -1478,6 +1509,25 @@ COMPILE_FUNC(expression, AstTyped* expr) { break; } + case Ast_Kind_Slice: { + AstSlice* sl = (AstSlice *) expr; + + u64 tmp_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32); + + compile_expression(mod, &code, sl->lo); + WIL(WI_LOCAL_TEE, tmp_local); + WID(WI_I32_CONST, sl->elem_size); + WI(WI_I32_MUL); + compile_location(mod, &code, sl->addr); + WI(WI_I32_ADD); + compile_expression(mod, &code, sl->hi); + WIL(WI_LOCAL_GET, tmp_local); + WI(WI_I32_SUB); + + local_raw_free(mod->local_alloc, tmp_local); + break; + } + case Ast_Kind_Size_Of: { AstSizeOf* so = (AstSizeOf *) expr; WID(WI_I32_CONST, so->size); -- 2.25.1