From: Brendan Hansen Date: Mon, 17 Aug 2020 19:59:35 +0000 (-0500) Subject: added basic union types; force structs to be a particular alignment or size X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=e46698b5e4c59650ada83d6fcc06afb41a5c182b;p=onyx.git added basic union types; force structs to be a particular alignment or size --- diff --git a/docs/plan b/docs/plan index 88ef7965..614d56fe 100644 --- a/docs/plan +++ b/docs/plan @@ -175,12 +175,18 @@ HOW: X Named member initialization X Default values on structs so they don't have to be named - [ ] #union on structs + [X] #union on structs - [ ] #align on structs + [X] #align on structs + + [X] #size on structs [ ] 'use' enums and packages at an arbitrary scope + [ ] 'when' statements + - Compile time conditions + - Only evalutate code blocks that evaluate to be true + [ ] Array literals [ ] Top level variable initialization diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index df3cda9e..ca9e7499 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -159,6 +159,9 @@ typedef enum AstFlags { // Enum flags Ast_Flag_Enum_Is_Flags = BH_BIT(11), + + // Struct flags + Ast_Flag_Struct_Is_Union = BH_BIT(12), } AstFlags; typedef enum UnaryOp { @@ -340,6 +343,8 @@ struct AstStructType { bh_arr(AstStructMember *) members; + u32 min_alignment, min_size; + // NOTE: Used to cache the actual type, since building // a struct type is kind of complicated and should // only happen once. diff --git a/onyx b/onyx index d1e7a979..3e28fe9a 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/stack_based.onyx b/progs/stack_based.onyx index 3c8d28ff..5301b59a 100644 --- a/progs/stack_based.onyx +++ b/progs/stack_based.onyx @@ -149,7 +149,7 @@ start :: proc #export { stupid_idea(1234)(1234) |> print(); varr : [5] Vec3; - varr[2] = Vec3 .{4, 5, 6}; + varr[2] = Vec3.{4, 5, 6}; mag_squared(varr[2]) |> print(); @@ -160,16 +160,25 @@ start :: proc #export { print(v2.y); print(v2.z); - buf := core.Buffer.{ - length = 16, - }; + buf := core.Buffer.{ length = 16 }; + + un : UnionTest; + un.f = 1.25f; + print_hex(cast(u64) un.i); } vadd :: proc (v1: Vec3, v2: Vec3) -> ^Vec3 { out := cast(^Vec3) alloc(return_scratch_alloc, sizeof Vec3); - out.x = v1.x + v2.x; - out.y = v1.y + v2.y; - out.z = v1.z + v2.z; + *out = Vec3.{ + x = v1.x + v2.x, + y = v1.y + v2.y, + z = v1.z + v2.z, + }; return out; +} + +UnionTest :: struct #union { + i : i32; + f : f32; } \ No newline at end of file diff --git a/src/onyxparser.c b/src/onyxparser.c index 69942803..4d2b41e8 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -1131,6 +1131,37 @@ static AstStructType* parse_struct(OnyxParser* parser) { bh_arr_new(global_heap_allocator, s_node->members, 4); + while (parser->curr->type == '#') { + if (parser->hit_unexpected_token) return NULL; + + if (parse_possible_directive(parser, "union")) { + s_node->flags |= Ast_Flag_Struct_Is_Union; + } + + else if (parse_possible_directive(parser, "align")) { + AstNumLit* numlit = parse_int_literal(parser); + if (numlit == NULL) return NULL; + + s_node->min_alignment = numlit->value.i; + } + + else if (parse_possible_directive(parser, "size")) { + AstNumLit* numlit = parse_int_literal(parser); + if (numlit == NULL) return NULL; + + s_node->min_size = numlit->value.i; + } + + else { + OnyxToken* directive_token = expect_token(parser, '#'); + OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol); + + onyx_message_add(Msg_Type_Unknown_Directive, + directive_token->pos, + symbol_token->text, symbol_token->length); + } + } + expect_token(parser, '{'); while (parser->curr->type != '}') { if (parser->hit_unexpected_token) return s_node; diff --git a/src/onyxtypes.c b/src/onyxtypes.c index cd6cfd06..7f1c6aa4 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -278,6 +278,8 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { 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); + b32 is_union = (s_node->flags & Ast_Flag_Struct_Is_Union) != 0; + u32 size = 0; u32 offset = 0; u32 alignment = 1, mem_alignment; u32 idx = 0; @@ -301,7 +303,11 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { bh_table_put(StructMember, s_type->Struct.members, (*member)->token->text, smem); token_toggle_end((*member)->token); - offset += type_size_of((*member)->type); + u32 type_size = type_size_of((*member)->type); + if (!is_union) offset += type_size; + if (!is_union) size += type_size; + else size = bh_max(size, type_size); + idx++; } @@ -314,12 +320,15 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { token_toggle_end((*member)->token); } + alignment = bh_max(s_node->min_alignment, alignment); s_type->Struct.aligment = alignment; - if (offset % alignment != 0) { - offset += alignment - (offset % alignment); + if (size % alignment != 0) { + size += alignment - (size % alignment); } - s_type->Struct.size = offset; + + size = bh_max(s_node->min_size, size); + s_type->Struct.size = size; return s_type; }