From 6bd898e552392b1bd11ad16c7476833261c1d4b7 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Wed, 24 Aug 2016 15:06:36 +0100 Subject: [PATCH] Untagged (unsafe) unions and unambiguous in|postfix notation. --- examples/demo.odin | 11 +- examples/math.odin | 6 +- src/checker/checker.cpp | 4 +- src/checker/expr.cpp | 217 ++++++++++++++++---------- src/checker/stmt.cpp | 26 ++-- src/checker/type.cpp | 301 +++++++++++++++++++++---------------- src/codegen/print_llvm.cpp | 62 ++++---- src/codegen/ssa.cpp | 92 +++++++----- src/main.cpp | 74 ++++----- src/parser.cpp | 59 ++++++-- src/tokenizer.cpp | 28 +--- 11 files changed, 516 insertions(+), 364 deletions(-) diff --git a/examples/demo.odin b/examples/demo.odin index f5afa04fc..550b499fb 100644 --- a/examples/demo.odin +++ b/examples/demo.odin @@ -12,6 +12,15 @@ main :: proc() { // data_control(); // run_game(); + + Thing :: type union { + i: i32, + f: f32, + } + t: Thing; + t.f = 123; + print_int_base(t.i as int, 16); + print_nl(); } hellope :: proc() -> int { @@ -153,7 +162,7 @@ procedures :: proc() { print_int(a + b); } - print_int(3 'add' 4); // Infix style + print_int(3 ''add 4); // Infix style print_nl(); print_int(12 'fibonacci); // Postfix style print_nl(); diff --git a/examples/math.odin b/examples/math.odin index 0345fb65e..c961e891a 100644 --- a/examples/math.odin +++ b/examples/math.odin @@ -102,9 +102,9 @@ cross :: proc(x, y: Vec3) -> Vec3 { } -vec2_mag :: proc(v: Vec2) -> f32 { return fsqrt(v 'dot2' v); } -vec3_mag :: proc(v: Vec3) -> f32 { return fsqrt(v 'dot3' v); } -vec4_mag :: proc(v: Vec4) -> f32 { return fsqrt(v 'dot4' v); } +vec2_mag :: proc(v: Vec2) -> f32 { return fsqrt(v ''dot2 v); } +vec3_mag :: proc(v: Vec3) -> f32 { return fsqrt(v ''dot3 v); } +vec4_mag :: proc(v: Vec4) -> f32 { return fsqrt(v ''dot4 v); } vec2_norm :: proc(v: Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)}; } vec3_norm :: proc(v: Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)}; } diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index 22d734af6..458ce0dce 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -337,12 +337,12 @@ void init_universal_scope(void) { // Types for (isize i = 0; i < gb_count_of(basic_types); i++) { Token token = {Token_Identifier}; - token.string = basic_types[i].basic.name; + token.string = basic_types[i].Basic.name; add_global_entity(make_entity_type_name(a, NULL, token, &basic_types[i])); } for (isize i = 0; i < gb_count_of(basic_type_aliases); i++) { Token token = {Token_Identifier}; - token.string = basic_type_aliases[i].basic.name; + token.string = basic_type_aliases[i].Basic.name; add_global_entity(make_entity_type_name(a, NULL, token, &basic_type_aliases[i])); } diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index 63a87f3f5..5e67af727 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -16,7 +16,7 @@ void update_expr_type (Checker *c, AstNode *e, Type *type, b32 void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { GB_ASSERT(node->kind == AstNode_StructType); - GB_ASSERT(struct_type->kind == Type_Structure); + GB_ASSERT(struct_type->kind == Type_Struct); ast_node(st, StructType, node); Map entity_map = {}; @@ -52,14 +52,57 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { add_entity_use(&c->info, name, e); } } - struct_type->structure.fields = fields; - struct_type->structure.field_count = field_count; - struct_type->structure.is_packed = st->is_packed; + struct_type->Struct.fields = fields; + struct_type->Struct.field_count = field_count; + struct_type->Struct.is_packed = st->is_packed; } +void check_union_type(Checker *c, Type *union_type, AstNode *node) { + GB_ASSERT(node->kind == AstNode_UnionType); + GB_ASSERT(union_type->kind == Type_Union); + ast_node(ut, UnionType, node); + + Map entity_map = {}; + map_init(&entity_map, gb_heap_allocator()); + defer (map_destroy(&entity_map)); + + isize field_count = 0; + for (AstNode *field = ut->field_list; field != NULL; field = field->next) { + for (AstNode *name = field->Field.name_list; name != NULL; name = name->next) { + GB_ASSERT(name->kind == AstNode_Ident); + field_count++; + } + } + + Entity **fields = gb_alloc_array(c->allocator, Entity *, ut->field_count); + isize field_index = 0; + for (AstNode *field = ut->field_list; field != NULL; field = field->next) { + ast_node(f, Field, field); + Type *type = check_type(c, f->type); + for (AstNode *name = f->name_list; name != NULL; name = name->next) { + ast_node(i, Ident, name); + Token name_token = i->token; + // TODO(bill): is the curr_scope correct? + Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type); + HashKey key = hash_string(name_token.string); + if (map_get(&entity_map, key)) { + // TODO(bill): Scope checking already checks the declaration + error(&c->error_collector, name_token, "`%.*s` is already declared in this union", LIT(name_token.string)); + } else { + map_set(&entity_map, key, e); + fields[field_index++] = e; + } + add_entity_use(&c->info, name, e); + } + } + union_type->Union.fields = fields; + union_type->Union.field_count = field_count; +} + + void check_enum_type(Checker *c, Type *enum_type, AstNode *node) { GB_ASSERT(node->kind == AstNode_EnumType); - GB_ASSERT(enum_type->kind == Type_Enumeration); + GB_ASSERT(enum_type->kind == Type_Enum); ast_node(et, EnumType, node); Map entity_map = {}; @@ -78,7 +121,7 @@ void check_enum_type(Checker *c, Type *enum_type, AstNode *node) { if (base_type == NULL) { base_type = t_int; } - enum_type->enumeration.base = base_type; + enum_type->Enum.base = base_type; Entity **fields = gb_alloc_array(c->allocator, Entity *, et->field_count); isize field_index = 0; @@ -120,8 +163,8 @@ void check_enum_type(Checker *c, Type *enum_type, AstNode *node) { } add_entity_use(&c->info, f->field, e); } - enum_type->enumeration.fields = fields; - enum_type->enumeration.field_count = et->field_count; + enum_type->Enum.fields = fields; + enum_type->Enum.field_count = et->field_count; } Type *check_get_params(Checker *c, Scope *scope, AstNode *field_list, isize field_count) { @@ -149,8 +192,8 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *field_list, isize fiel } } } - tuple->tuple.variables = variables; - tuple->tuple.variable_count = field_count; + tuple->Tuple.variables = variables; + tuple->Tuple.variable_count = field_count; return tuple; } @@ -171,8 +214,8 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *list, isize list_coun // NOTE(bill): No need to record variables[variable_index++] = param; } - tuple->tuple.variables = variables; - tuple->tuple.variable_count = list_count; + tuple->Tuple.variables = variables; + tuple->Tuple.variable_count = list_count; return tuple; } @@ -189,11 +232,11 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) { Type *params = check_get_params(c, c->context.scope, pt->param_list, param_count); Type *results = check_get_results(c, c->context.scope, pt->result_list, result_count); - type->proc.scope = c->context.scope; - type->proc.params = params; - type->proc.param_count = pt->param_count; - type->proc.results = results; - type->proc.result_count = pt->result_count; + type->Proc.scope = c->context.scope; + type->Proc.params = params; + type->Proc.param_count = pt->param_count; + type->Proc.results = results; + type->Proc.result_count = pt->result_count; } @@ -354,7 +397,7 @@ Type *check_type_expr_extra(Checker *c, AstNode *e, Type *named_type) { case_end; case_ast_node(st, StructType, e); - Type *t = make_type_structure(c->allocator); + Type *t = make_type_struct(c->allocator); set_base_type(named_type, t); check_struct_type(c, t, e); return t; @@ -460,14 +503,21 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) { case_end; case_ast_node(st, StructType, e); - type = make_type_structure(c->allocator); + type = make_type_struct(c->allocator); set_base_type(named_type, type); check_struct_type(c, type, e); goto end; case_end; + case_ast_node(st, UnionType, e); + type = make_type_union(c->allocator); + set_base_type(named_type, type); + check_union_type(c, type, e); + goto end; + case_end; + case_ast_node(et, EnumType, e); - type = make_type_enumeration(c->allocator); + type = make_type_enum(c->allocator); set_base_type(named_type, type); check_enum_type(c, type, e); goto end; @@ -613,7 +663,7 @@ b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exac i64 imax = (1ll << (s-1ll)); - switch (type->basic.kind) { + switch (type->Basic.kind) { case Basic_i8: case Basic_i16: case Basic_i32: @@ -638,7 +688,7 @@ b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exac if (v.kind != ExactValue_Float) return false; - switch (type->basic.kind) { + switch (type->Basic.kind) { case Basic_f32: if (out_value) *out_value = v; return true; @@ -791,7 +841,7 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) { } if (is_type_vector(get_base_type(y->type))) { - x->type = make_type_vector(c->allocator, t_bool, get_base_type(y->type)->vector.count); + x->type = make_type_vector(c->allocator, t_bool, get_base_type(y->type)->Vector.count); } else { x->type = t_untyped_bool; } @@ -1253,7 +1303,7 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) { update_expr_value(c, operand->expr, operand->value); } else { // TODO(bill): Is this really needed? - switch (operand->type->basic.kind) { + switch (operand->type->Basic.kind) { case Basic_UntypedBool: if (!is_type_boolean(target_type)) { convert_untyped_error(c, operand, target_type); @@ -1272,7 +1322,7 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) { } break; case Type_Pointer: - switch (operand->type->basic.kind) { + switch (operand->type->Basic.kind) { case Basic_UntypedPointer: target_type = t_untyped_pointer; break; @@ -1283,7 +1333,7 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) { break; case Type_Proc: - switch (operand->type->basic.kind) { + switch (operand->type->Basic.kind) { case Basic_UntypedPointer: break; default: @@ -1359,14 +1409,14 @@ Entity *lookup_field(Type *type, AstNode *field_node, isize *index = NULL) { GB_ASSERT(field_node->kind == AstNode_Ident); type = get_base_type(type); if (type->kind == Type_Pointer) - type = get_base_type(type->pointer.elem); + type = get_base_type(type->Pointer.elem); ast_node(i, Ident, field_node); String field_str = i->token.string; switch (type->kind) { - case Type_Structure: - for (isize i = 0; i < type->structure.field_count; i++) { - Entity *f = type->structure.fields[i]; + case Type_Struct: + for (isize i = 0; i < type->Struct.field_count; i++) { + Entity *f = type->Struct.fields[i]; GB_ASSERT(f->kind == Entity_Variable && f->Variable.is_field); String str = f->token.string; if (are_strings_equal(field_str, str)) { @@ -1375,9 +1425,22 @@ Entity *lookup_field(Type *type, AstNode *field_node, isize *index = NULL) { } } break; - case Type_Enumeration: - for (isize i = 0; i < type->enumeration.field_count; i++) { - Entity *f = type->enumeration.fields[i]; + + case Type_Union: + for (isize i = 0; i < type->Union.field_count; i++) { + Entity *f = type->Union.fields[i]; + GB_ASSERT(f->kind == Entity_Variable && f->Variable.is_field); + String str = f->token.string; + if (are_strings_equal(field_str, str)) { + if (index) *index = i; + return f; + } + } + break; + + case Type_Enum: + for (isize i = 0; i < type->Enum.field_count; i++) { + Entity *f = type->Enum.fields[i]; GB_ASSERT(f->kind == Entity_Constant); String str = f->token.string; if (are_strings_equal(field_str, str)) { @@ -1522,7 +1585,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Type *type = get_base_type(check_type(c, ce->arg_list)); AstNode *field_arg = unparen_expr(ce->arg_list->next); if (type) { - if (type->kind != Type_Structure) { + if (type->kind != Type_Struct) { error(&c->error_collector, ast_node_token(ce->arg_list), "Expected a structure type for `offset_of`"); return false; } @@ -1565,8 +1628,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Type *type = operand->type; if (get_base_type(type)->kind == Type_Pointer) { Type *p = get_base_type(type); - if (get_base_type(p)->kind == Type_Structure) - type = p->pointer.elem; + if (get_base_type(p)->kind == Type_Struct) + type = p->Pointer.elem; } isize index = 0; @@ -1628,12 +1691,12 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) case Type_Array: mode = Addressing_Constant; - value = make_exact_value_integer(t->array.count); + value = make_exact_value_integer(t->Array.count); break; case Type_Vector: mode = Addressing_Constant; - value = make_exact_value_integer(t->vector.count); + value = make_exact_value_integer(t->Vector.count); break; case Type_Slice: @@ -1662,7 +1725,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Type *d = get_base_type(operand->type); if (d->kind == Type_Slice) - dest_type = d->slice.elem; + dest_type = d->Slice.elem; Operand op = {}; check_expr(c, &op, ce->arg_list->next); @@ -1670,7 +1733,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) return false; Type *s = get_base_type(op.type); if (s->kind == Type_Slice) - src_type = s->slice.elem; + src_type = s->Slice.elem; if (dest_type == NULL || src_type == NULL) { error(&c->error_collector, ast_node_token(call), "`copy` only expects slices as arguments"); @@ -1707,12 +1770,12 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) return false; y_type = get_base_type(op.type); - if (!(is_type_pointer(x_type) && is_type_slice(x_type->pointer.elem))) { + if (!(is_type_pointer(x_type) && is_type_slice(x_type->Pointer.elem))) { error(&c->error_collector, ast_node_token(call), "First argument to `append` must be a pointer to a slice"); return false; } - Type *elem_type = x_type->pointer.elem->slice.elem; + Type *elem_type = x_type->Pointer.elem->Slice.elem; if (!check_is_assignable_to(c, &op, elem_type)) { gbString d_arg = expr_to_string(ce->arg_list); gbString s_arg = expr_to_string(ce->arg_list->next); @@ -1744,7 +1807,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) return false; } - isize max_count = vector_type->vector.count; + isize max_count = vector_type->Vector.count; isize arg_count = 0; for (AstNode *arg = ce->arg_list->next; arg != NULL; arg = arg->next) { Operand op = {}; @@ -1775,7 +1838,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) return false; } - Type *elem_type = vector_type->vector.elem; + Type *elem_type = vector_type->Vector.elem; operand->type = make_type_vector(c->allocator, elem_type, arg_count); operand->mode = Addressing_Value; } break; @@ -1793,8 +1856,8 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode isize param_index = 0; isize param_count = 0; - if (proc_type->proc.params) - param_count = proc_type->proc.params->tuple.variable_count; + if (proc_type->Proc.params) + param_count = proc_type->Proc.params->Tuple.variable_count; if (ce->arg_list_count == 0 && param_count == 0) return; @@ -1802,7 +1865,7 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode if (ce->arg_list_count > param_count) { error_code = +1; } else { - Entity **sig_params = proc_type->proc.params->tuple.variables; + Entity **sig_params = proc_type->Proc.params->Tuple.variables; AstNode *call_arg = ce->arg_list; for (; call_arg != NULL; call_arg = call_arg->next) { check_multi_expr(c, operand, call_arg); @@ -1813,7 +1876,7 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode check_assignment(c, operand, sig_params[param_index]->type, make_string("argument")); param_index++; } else { - auto *tuple = &operand->type->tuple; + auto *tuple = &operand->type->Tuple; isize i = 0; for (; i < tuple->variable_count && param_index < param_count; @@ -1897,12 +1960,12 @@ ExpressionKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { check_call_arguments(c, operand, proc_type, call); - auto *proc = &proc_type->proc; + auto *proc = &proc_type->Proc; if (proc->result_count == 0) { operand->mode = Addressing_NoValue; } else if (proc->result_count == 1) { operand->mode = Addressing_Value; - operand->type = proc->results->tuple.variables[0]->type; + operand->type = proc->results->Tuple.variables[0]->type; } else { operand->mode = Addressing_Value; operand->type = proc->results; @@ -2007,12 +2070,12 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ Type *t = get_base_type(type); switch (t->kind) { - case Type_Structure: { + case Type_Struct: { if (cl->elem_count == 0) break; // NOTE(bill): No need to init { // Checker values AstNode *elem = cl->elem_list; - isize field_count = t->structure.field_count; + isize field_count = t->Struct.field_count; if (elem->kind == AstNode_FieldValue) { b32 *fields_visited = gb_alloc_array(c->allocator, b32, field_count); @@ -2041,7 +2104,7 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ "Unknown field `%.*s` in structure literal", LIT(name)); continue; } - Entity *field = t->structure.fields[index]; + Entity *field = t->Struct.fields[index]; add_entity_use(&c->info, kv->field, field); if (fields_visited[index]) { @@ -2064,7 +2127,7 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ "Mixture of `field = value` and value elements in a structure literal is not allowed"); continue; } - Entity *field = t->structure.fields[index]; + Entity *field = t->Struct.fields[index]; check_expr(c, o, elem); if (index >= field_count) { @@ -2088,13 +2151,13 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ Type *elem_type = NULL; String context_name = {}; if (t->kind == Type_Slice) { - elem_type = t->slice.elem; + elem_type = t->Slice.elem; context_name = make_string("slice literal"); } else if (t->kind == Type_Vector) { - elem_type = t->vector.elem; + elem_type = t->Vector.elem; context_name = make_string("vector literal"); } else { - elem_type = t->array.elem; + elem_type = t->Array.elem; context_name = make_string("array literal"); } @@ -2111,14 +2174,14 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ if (t->kind == Type_Array && - t->array.count >= 0 && - index >= t->array.count) { - error(&c->error_collector, ast_node_token(elem), "Index %lld is out of bounds (>= %lld) for array literal", index, t->array.count); + t->Array.count >= 0 && + index >= t->Array.count) { + error(&c->error_collector, ast_node_token(elem), "Index %lld is out of bounds (>= %lld) for array literal", index, t->Array.count); } if (t->kind == Type_Vector && - t->vector.count >= 0 && - index >= t->vector.count) { - error(&c->error_collector, ast_node_token(elem), "Index %lld is out of bounds (>= %lld) for vector literal", index, t->vector.count); + t->Vector.count >= 0 && + index >= t->Vector.count) { + error(&c->error_collector, ast_node_token(elem), "Index %lld is out of bounds (>= %lld) for vector literal", index, t->Vector.count); } Operand o = {}; @@ -2129,14 +2192,14 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ max = index; if (t->kind == Type_Vector) { - if (t->vector.count > 1 && gb_is_between(index, 2, t->vector.count-1)) { + if (t->Vector.count > 1 && gb_is_between(index, 2, t->Vector.count-1)) { error(&c->error_collector, ast_node_token(cl->elem_list), - "Expected either 1 (broadcast) or %td elements in vector literal, got %td", t->vector.count, index); + "Expected either 1 (broadcast) or %td elements in vector literal, got %td", t->Vector.count, index); } } if (t->kind == Type_Array && ellipsis_array) { - t->array.count = max; + t->Array.count = max; } } break; @@ -2213,31 +2276,31 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ case Type_Array: valid = true; - max_count = t->array.count; + max_count = t->Array.count; if (o->mode != Addressing_Variable) o->mode = Addressing_Value; - o->type = t->array.elem; + o->type = t->Array.elem; break; case Type_Vector: valid = true; - max_count = t->vector.count; + max_count = t->Vector.count; if (o->mode != Addressing_Variable) o->mode = Addressing_Value; - o->type = t->vector.elem; + o->type = t->Vector.elem; break; case Type_Slice: valid = true; - o->type = t->slice.elem; + o->type = t->Slice.elem; o->mode = Addressing_Variable; break; case Type_Pointer: valid = true; o->mode = Addressing_Variable; - o->type = get_base_type(t->pointer.elem); + o->type = get_base_type(t->Pointer.elem); break; } @@ -2282,14 +2345,14 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ case Type_Array: valid = true; - max_count = t->array.count; + max_count = t->Array.count; if (o->mode != Addressing_Variable) { gbString str = expr_to_string(node); error(&c->error_collector, ast_node_token(node), "Cannot slice array `%s`, value is not addressable", str); gb_string_free(str); goto error; } - o->type = make_type_slice(c->allocator, t->array.elem); + o->type = make_type_slice(c->allocator, t->Array.elem); o->mode = Addressing_Value; break; @@ -2300,7 +2363,7 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ case Type_Pointer: valid = true; - o->type = make_type_slice(c->allocator, get_base_type(t->pointer.elem)); + o->type = make_type_slice(c->allocator, get_base_type(t->Pointer.elem)); o->mode = Addressing_Value; break; } @@ -2355,7 +2418,7 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ Type *t = get_base_type(o->type); if (t->kind == Type_Pointer) { o->mode = Addressing_Variable; - o->type = t->pointer.elem; + o->type = t->Pointer.elem; } else { gbString str = expr_to_string(o->expr); error(&c->error_collector, ast_node_token(o->expr), "Cannot dereference `%s`", str); @@ -2439,7 +2502,7 @@ void check_not_tuple(Checker *c, Operand *o) { if (o->mode == Addressing_Value) { // NOTE(bill): Tuples are not first class thus never named if (o->type->kind == Type_Tuple) { - isize count = o->type->tuple.variable_count; + isize count = o->type->Tuple.variable_count; GB_ASSERT(count != 1); error(&c->error_collector, ast_node_token(o->expr), "%td-valued tuple found where single value expected", count); diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index a78db4623..e120a467f 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -91,10 +91,10 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type) { if (operand->mode == Addressing_Constant) return check_value_is_expressible(c, operand->value, tb, NULL); if (sb->kind == Type_Basic) - return sb->basic.kind == Basic_UntypedBool && is_type_boolean(tb); + return sb->Basic.kind == Basic_UntypedBool && is_type_boolean(tb); break; case Type_Pointer: - return sb->basic.kind == Basic_UntypedPointer; + return sb->Basic.kind == Basic_UntypedPointer; } } @@ -108,13 +108,13 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type) { return true; if (sb->kind == Type_Array && tb->kind == Type_Array) { - if (are_types_identical(sb->array.elem, tb->array.elem)) { - return sb->array.count == tb->array.count; + if (are_types_identical(sb->Array.elem, tb->Array.elem)) { + return sb->Array.count == tb->Array.count; } } if (sb->kind == Type_Slice && tb->kind == Type_Slice) { - if (are_types_identical(sb->slice.elem, tb->slice.elem)) { + if (are_types_identical(sb->Slice.elem, tb->Slice.elem)) { return true; } } @@ -278,7 +278,7 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNode *in if (o.type->kind != Type_Tuple) { gb_array_append(operands, o); } else { - auto *tuple = &o.type->tuple; + auto *tuple = &o.type->Tuple; for (isize j = 0; j < tuple->variable_count; j++) { o.type = tuple->variables[j]->type; gb_array_append(operands, o); @@ -362,7 +362,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_e void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *named_type) { GB_ASSERT(e->type == NULL); Type *named = make_type_named(c->allocator, e->token.string, NULL, e); - named->named.type_name = e; + named->Named.type_name = e; set_base_type(named_type, named); e->type = named; @@ -381,7 +381,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod push_procedure(c, type); ast_node(bs, BlockStmt, body); check_stmt_list(c, bs->list, 0); - if (type->proc.result_count > 0) { + if (type->Proc.result_count > 0) { if (!check_is_terminating(c, body)) { error(&c->error_collector, bs->close, "Missing return statement at the end of the procedure"); } @@ -414,7 +414,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) { if (d->scope == c->global_scope && are_strings_equal(e->token.string, make_string("main"))) { if (proc_type != NULL) { - auto *pt = &proc_type->proc; + auto *pt = &proc_type->Proc; if (pt->param_count != 0 || pt->result_count) { gbString str = type_to_string(proc_type); @@ -596,7 +596,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { if (o.type->kind != Type_Tuple) { gb_array_append(operands, o); } else { - auto *tuple = &o.type->tuple; + auto *tuple = &o.type->Tuple; for (isize j = 0; j < tuple->variable_count; j++) { o.type = tuple->variables[j]->type; gb_array_append(operands, o); @@ -696,15 +696,15 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { Type *proc_type = c->proc_stack[gb_array_count(c->proc_stack)-1]; isize result_count = 0; - if (proc_type->proc.results) - result_count = proc_type->proc.results->tuple.variable_count; + if (proc_type->Proc.results) + result_count = proc_type->Proc.results->Tuple.variable_count; if (result_count != rs->result_count) { error(&c->error_collector, rs->token, "Expected %td return %s, got %td", result_count, (result_count != 1 ? "values" : "value"), rs->result_count); } else if (result_count > 0) { - auto *tuple = &proc_type->proc.results->tuple; + auto *tuple = &proc_type->Proc.results->Tuple; check_init_variables(c, tuple->variables, tuple->variable_count, rs->result_list, rs->result_count, make_string("return statement")); } diff --git a/src/checker/type.cpp b/src/checker/type.cpp index ed8130d1e..e7cf827d3 100644 --- a/src/checker/type.cpp +++ b/src/checker/type.cpp @@ -61,8 +61,9 @@ struct BasicType { TYPE_KIND(Array), \ TYPE_KIND(Vector), \ TYPE_KIND(Slice), \ - TYPE_KIND(Structure), \ - TYPE_KIND(Enumeration), \ + TYPE_KIND(Struct), \ + TYPE_KIND(Union), \ + TYPE_KIND(Enum), \ TYPE_KIND(Pointer), \ TYPE_KIND(Named), \ TYPE_KIND(Tuple), \ @@ -90,18 +91,18 @@ struct Type { u32 flags; TypeKind kind; union { - BasicType basic; + BasicType Basic; struct { Type *elem; i64 count; - } array; + } Array; struct { Type *elem; i64 count; - } vector; + } Vector; struct { Type *elem; - } slice; + } Slice; struct { // Theses are arrays Entity **fields; // Entity_Variable @@ -109,42 +110,46 @@ struct Type { i64 * offsets; b32 are_offsets_set; b32 is_packed; - } structure; - struct { Type *elem; } pointer; + } Struct; + struct { + Entity **fields; // Entity_Variable + isize field_count; + } Union; + struct { Type *elem; } Pointer; struct { String name; Type * base; Entity *type_name; // Entity_TypeName - } named; + } Named; struct { Entity **variables; // Entity_Variable isize variable_count; - } tuple; + } Tuple; struct { Scope *scope; Type * params; // Type_Tuple Type * results; // Type_Tuple isize param_count; isize result_count; - } proc; + } Proc; struct { Type * base; // Default is `int` Entity **fields; // Entity_Constant isize field_count; - } enumeration; + } Enum; }; }; Type *get_base_type(Type *t) { while (t->kind == Type_Named) { - t = t->named.base; + t = t->Named.base; } return t; } void set_base_type(Type *t, Type *base) { if (t && t->kind == Type_Named) { - t->named.base = base; + t->Named.base = base; } } @@ -158,51 +163,56 @@ Type *alloc_type(gbAllocator a, TypeKind kind) { Type *make_type_basic(gbAllocator a, BasicType basic) { Type *t = alloc_type(a, Type_Basic); - t->basic = basic; + t->Basic = basic; return t; } Type *make_type_array(gbAllocator a, Type *elem, i64 count) { Type *t = alloc_type(a, Type_Array); - t->array.elem = elem; - t->array.count = count; + t->Array.elem = elem; + t->Array.count = count; return t; } Type *make_type_vector(gbAllocator a, Type *elem, i64 count) { Type *t = alloc_type(a, Type_Vector); - t->vector.elem = elem; - t->vector.count = count; + t->Vector.elem = elem; + t->Vector.count = count; return t; } Type *make_type_slice(gbAllocator a, Type *elem) { Type *t = alloc_type(a, Type_Slice); - t->array.elem = elem; + t->Array.elem = elem; return t; } -Type *make_type_structure(gbAllocator a) { - Type *t = alloc_type(a, Type_Structure); +Type *make_type_struct(gbAllocator a) { + Type *t = alloc_type(a, Type_Struct); return t; } -Type *make_type_enumeration(gbAllocator a) { - Type *t = alloc_type(a, Type_Enumeration); +Type *make_type_union(gbAllocator a) { + Type *t = alloc_type(a, Type_Union); + return t; +} + +Type *make_type_enum(gbAllocator a) { + Type *t = alloc_type(a, Type_Enum); return t; } Type *make_type_pointer(gbAllocator a, Type *elem) { Type *t = alloc_type(a, Type_Pointer); - t->pointer.elem = elem; + t->Pointer.elem = elem; return t; } Type *make_type_named(gbAllocator a, String name, Type *base, Entity *type_name) { Type *t = alloc_type(a, Type_Named); - t->named.name = name; - t->named.base = base; - t->named.type_name = type_name; + t->Named.name = name; + t->Named.base = base; + t->Named.type_name = type_name; return t; } @@ -213,11 +223,11 @@ Type *make_type_tuple(gbAllocator a) { Type *make_type_proc(gbAllocator a, Scope *scope, Type *params, isize param_count, Type *results, isize result_count) { Type *t = alloc_type(a, Type_Proc); - t->proc.scope = scope; - t->proc.params = params; - t->proc.param_count = param_count; - t->proc.results = results; - t->proc.result_count = result_count; + t->Proc.scope = scope; + t->Proc.params = params; + t->Proc.param_count = param_count; + t->Proc.results = results; + t->Proc.result_count = result_count; return t; } @@ -226,7 +236,7 @@ Type *type_deref(Type *t) { if (t != NULL) { Type *bt = get_base_type(t); if (bt != NULL && bt->kind == Type_Pointer) - return bt->pointer.elem; + return bt->Pointer.elem; } return t; } @@ -301,51 +311,51 @@ b32 is_type_named(Type *t) { b32 is_type_boolean(Type *t) { t = get_base_type(t); if (t->kind == Type_Basic) - return (t->basic.flags & BasicFlag_Boolean) != 0; + return (t->Basic.flags & BasicFlag_Boolean) != 0; return false; } b32 is_type_integer(Type *t) { t = get_base_type(t); if (t->kind == Type_Basic) - return (t->basic.flags & BasicFlag_Integer) != 0; + return (t->Basic.flags & BasicFlag_Integer) != 0; return false; } b32 is_type_unsigned(Type *t) { t = get_base_type(t); if (t->kind == Type_Basic) - return (t->basic.flags & BasicFlag_Unsigned) != 0; + return (t->Basic.flags & BasicFlag_Unsigned) != 0; return false; } b32 is_type_numeric(Type *t) { t = get_base_type(t); if (t->kind == Type_Basic) - return (t->basic.flags & BasicFlag_Numeric) != 0; + return (t->Basic.flags & BasicFlag_Numeric) != 0; if (t->kind == Type_Vector) - return is_type_numeric(t->vector.elem); + return is_type_numeric(t->Vector.elem); return false; } b32 is_type_string(Type *t) { t = get_base_type(t); if (t->kind == Type_Basic) - return (t->basic.flags & BasicFlag_String) != 0; + return (t->Basic.flags & BasicFlag_String) != 0; return false; } b32 is_type_typed(Type *t) { t = get_base_type(t); if (t->kind == Type_Basic) - return (t->basic.flags & BasicFlag_Untyped) == 0; + return (t->Basic.flags & BasicFlag_Untyped) == 0; return true; } b32 is_type_untyped(Type *t) { t = get_base_type(t); if (t->kind == Type_Basic) - return (t->basic.flags & BasicFlag_Untyped) != 0; + return (t->Basic.flags & BasicFlag_Untyped) != 0; return false; } b32 is_type_ordered(Type *t) { t = get_base_type(t); if (t->kind == Type_Basic) - return (t->basic.flags & BasicFlag_Ordered) != 0; + return (t->Basic.flags & BasicFlag_Ordered) != 0; if (t->kind == Type_Pointer) return true; return false; @@ -353,35 +363,35 @@ b32 is_type_ordered(Type *t) { b32 is_type_constant_type(Type *t) { t = get_base_type(t); if (t->kind == Type_Basic) - return (t->basic.flags & BasicFlag_ConstantType) != 0; + return (t->Basic.flags & BasicFlag_ConstantType) != 0; return false; } b32 is_type_float(Type *t) { t = get_base_type(t); if (t->kind == Type_Basic) - return (t->basic.flags & BasicFlag_Float) != 0; + return (t->Basic.flags & BasicFlag_Float) != 0; return false; } b32 is_type_pointer(Type *t) { t = get_base_type(t); if (t->kind == Type_Basic) - return (t->basic.flags & BasicFlag_Pointer) != 0; + return (t->Basic.flags & BasicFlag_Pointer) != 0; return t->kind == Type_Pointer; } b32 is_type_int_or_uint(Type *t) { if (t->kind == Type_Basic) - return (t->basic.kind == Basic_int) || (t->basic.kind == Basic_uint); + return (t->Basic.kind == Basic_int) || (t->Basic.kind == Basic_uint); return false; } b32 is_type_rawptr(Type *t) { if (t->kind == Type_Basic) - return t->basic.kind == Basic_rawptr; + return t->Basic.kind == Basic_rawptr; return false; } b32 is_type_u8(Type *t) { if (t->kind == Type_Basic) - return t->basic.kind == Basic_u8; + return t->Basic.kind == Basic_u8; return false; } b32 is_type_slice(Type *t) { @@ -391,7 +401,7 @@ b32 is_type_slice(Type *t) { b32 is_type_u8_slice(Type *t) { t = get_base_type(t); if (t->kind == Type_Slice) - return is_type_u8(t->slice.elem); + return is_type_u8(t->Slice.elem); return false; } b32 is_type_vector(Type *t) { @@ -403,18 +413,18 @@ b32 is_type_proc(Type *t) { } Type *base_vector_type(Type *t) { if (is_type_vector(t)) { - return t->vector.elem; + return t->Vector.elem; } return t; } b32 is_type_enum(Type *t) { t = get_base_type(t); - return t->kind == Type_Enumeration; + return t->kind == Type_Enum; } Type *get_enum_base_type(Type *t) { Type *bt = get_base_type(t); if (is_type_enum(bt)) { - return bt->enumeration.base; + return bt->Enum.base; } return t; } @@ -428,19 +438,19 @@ b32 is_type_comparable(Type *t) { return true; case Type_Pointer: return true; - case Type_Structure: { - for (isize i = 0; i < t->structure.field_count; i++) { - if (!is_type_comparable(t->structure.fields[i]->type)) + case Type_Struct: { + for (isize i = 0; i < t->Struct.field_count; i++) { + if (!is_type_comparable(t->Struct.fields[i]->type)) return false; } return true; } break; case Type_Array: - return is_type_comparable(t->array.elem); + return is_type_comparable(t->Array.elem); case Type_Vector: - return is_type_comparable(t->vector.elem); - case Type_Enumeration: - return is_type_comparable(t->enumeration.base); + return is_type_comparable(t->Vector.elem); + case Type_Enum: + return is_type_comparable(t->Enum.base); case Type_Proc: return true; } @@ -459,29 +469,29 @@ b32 are_types_identical(Type *x, Type *y) { switch (x->kind) { case Type_Basic: if (y->kind == Type_Basic) - return x->basic.kind == y->basic.kind; + return x->Basic.kind == y->Basic.kind; break; case Type_Array: if (y->kind == Type_Array) - return (x->array.count == y->array.count) && are_types_identical(x->array.elem, y->array.elem); + return (x->Array.count == y->Array.count) && are_types_identical(x->Array.elem, y->Array.elem); break; case Type_Vector: if (y->kind == Type_Vector) - return (x->vector.count == y->vector.count) && are_types_identical(x->vector.elem, y->vector.elem); + return (x->Vector.count == y->Vector.count) && are_types_identical(x->Vector.elem, y->Vector.elem); break; case Type_Slice: if (y->kind == Type_Slice) - return are_types_identical(x->slice.elem, y->slice.elem); + return are_types_identical(x->Slice.elem, y->Slice.elem); break; - case Type_Structure: - if (y->kind == Type_Structure) { - if (x->structure.field_count == y->structure.field_count) { - for (isize i = 0; i < x->structure.field_count; i++) { - if (!are_types_identical(x->structure.fields[i]->type, y->structure.fields[i]->type)) { + case Type_Struct: + if (y->kind == Type_Struct) { + if (x->Struct.field_count == y->Struct.field_count) { + for (isize i = 0; i < x->Struct.field_count; i++) { + if (!are_types_identical(x->Struct.fields[i]->type, y->Struct.fields[i]->type)) { return false; } } @@ -493,19 +503,19 @@ b32 are_types_identical(Type *x, Type *y) { case Type_Pointer: if (y->kind == Type_Pointer) - return are_types_identical(x->pointer.elem, y->pointer.elem); + return are_types_identical(x->Pointer.elem, y->Pointer.elem); break; case Type_Named: if (y->kind == Type_Named) - return x->named.base == y->named.base; + return x->Named.base == y->Named.base; break; case Type_Tuple: if (y->kind == Type_Tuple) { - if (x->tuple.variable_count == y->tuple.variable_count) { - for (isize i = 0; i < x->tuple.variable_count; i++) { - if (!are_types_identical(x->tuple.variables[i]->type, y->tuple.variables[i]->type)) + if (x->Tuple.variable_count == y->Tuple.variable_count) { + for (isize i = 0; i < x->Tuple.variable_count; i++) { + if (!are_types_identical(x->Tuple.variables[i]->type, y->Tuple.variables[i]->type)) return false; } return true; @@ -515,8 +525,8 @@ b32 are_types_identical(Type *x, Type *y) { case Type_Proc: if (y->kind == Type_Proc) { - return are_types_identical(x->proc.params, y->proc.params) && - are_types_identical(x->proc.results, y->proc.results); + return are_types_identical(x->Proc.params, y->Proc.params) && + are_types_identical(x->Proc.results, y->Proc.results); } break; } @@ -528,7 +538,7 @@ b32 are_types_identical(Type *x, Type *y) { Type *default_type(Type *type) { if (type->kind == Type_Basic) { - switch (type->basic.kind) { + switch (type->Basic.kind) { case Basic_UntypedBool: return &basic_types[Basic_bool]; case Basic_UntypedInteger: return &basic_types[Basic_int]; case Basic_UntypedFloat: return &basic_types[Basic_f64]; @@ -585,20 +595,20 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { switch (t->kind) { case Type_Array: - return type_align_of(s, allocator, t->array.elem); + return type_align_of(s, allocator, t->Array.elem); case Type_Vector: { - i64 size = type_size_of(s, allocator, t->vector.elem); - size *= t->vector.count; + i64 size = type_size_of(s, allocator, t->Vector.elem); + size *= t->Vector.count; size = next_pow2(size); // TODO(bill): Type_Vector type_align_of return gb_clamp(size, s.max_align, 4*s.max_align); } break; - case Type_Structure: { - if (!t->structure.is_packed) { + case Type_Struct: { + if (!t->Struct.is_packed) { i64 max = 1; - for (isize i = 0; i < t->structure.field_count; i++) { - i64 align = type_align_of(s, allocator, t->structure.fields[i]->type); + for (isize i = 0; i < t->Struct.field_count; i++) { + i64 align = type_align_of(s, allocator, t->Struct.fields[i]->type); if (max < align) max = align; } @@ -606,8 +616,18 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { } } break; - case Type_Enumeration: - return type_align_of(s, allocator, t->enumeration.base); + case Type_Union: { + i64 max = 1; + for (isize i = 0; i < t->Union.field_count; i++) { + i64 align = type_align_of(s, allocator, t->Union.fields[i]->type); + if (max < align) + max = align; + } + return max; + } break; + + case Type_Enum: + return type_align_of(s, allocator, t->Enum.base); } return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.max_align); @@ -635,10 +655,10 @@ i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields } b32 type_set_offsets(BaseTypeSizes s, gbAllocator allocator, Type *t) { - GB_ASSERT(t->kind == Type_Structure); - if (!t->structure.are_offsets_set) { - t->structure.offsets = type_set_offsets_of(s, allocator, t->structure.fields, t->structure.field_count, t->structure.is_packed); - t->structure.are_offsets_set = true; + GB_ASSERT(t->kind == Type_Struct); + if (!t->Struct.are_offsets_set) { + t->Struct.offsets = type_set_offsets_of(s, allocator, t->Struct.fields, t->Struct.field_count, t->Struct.is_packed); + t->Struct.are_offsets_set = true; return true; } return false; @@ -649,7 +669,7 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { switch (t->kind) { case Type_Basic: { GB_ASSERT(is_type_typed(t)); - BasicKind kind = t->basic.kind; + BasicKind kind = t->Basic.kind; if (kind < gb_count_of(basic_type_sizes)) { i64 size = basic_type_sizes[kind]; if (size > 0) @@ -660,22 +680,22 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { } break; case Type_Array: { - i64 count = t->array.count; + i64 count = t->Array.count; if (count == 0) return 0; - i64 align = type_align_of(s, allocator, t->array.elem); - i64 size = type_size_of(s, allocator, t->array.elem); + i64 align = type_align_of(s, allocator, t->Array.elem); + i64 size = type_size_of(s, allocator, t->Array.elem); i64 alignment = align_formula(size, align); return alignment*(count-1) + size; } break; case Type_Vector: { - i64 count = t->vector.count; + i64 count = t->Vector.count; if (count == 0) return 0; - // i64 align = type_align_of(s, allocator, t->vector.elem); - i64 bit_size = 8*type_size_of(s, allocator, t->vector.elem); - if (is_type_boolean(t->vector.elem)) { + // i64 align = type_align_of(s, allocator, t->Vector.elem); + i64 bit_size = 8*type_size_of(s, allocator, t->Vector.elem); + if (is_type_boolean(t->Vector.elem)) { bit_size = 1; // NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1` // Silly LLVM spec } @@ -691,16 +711,27 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { case Type_Slice: // ptr + len + cap return 3 * s.word_size; - case Type_Structure: { - i64 count = t->structure.field_count; + case Type_Struct: { + i64 count = t->Struct.field_count; if (count == 0) return 0; type_set_offsets(s, allocator, t); - return t->structure.offsets[count-1] + type_size_of(s, allocator, t->structure.fields[count-1]->type); + return t->Struct.offsets[count-1] + type_size_of(s, allocator, t->Struct.fields[count-1]->type); } break; - case Type_Enumeration: - return type_size_of(s, allocator, t->enumeration.base); + case Type_Union: { + i64 count = t->Union.field_count; + i64 max = 0; + for (isize i = 0; i < count; i++) { + i64 size = type_size_of(s, allocator, t->Struct.fields[i]->type); + if (max < size) + max = size; + } + return max; + } break; + + case Type_Enum: + return type_size_of(s, allocator, t->Enum.base); } // Catch all @@ -708,10 +739,10 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { } i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, isize index) { - if (t->kind == Type_Structure) { + if (t->kind == Type_Struct) { type_set_offsets(s, allocator, t); - if (gb_is_between(index, 0, t->structure.field_count-1)) { - return t->structure.offsets[index]; + if (gb_is_between(index, 0, t->Struct.field_count-1)) { + return t->Struct.offsets[index]; } } return 0; @@ -725,31 +756,31 @@ gbString write_type_to_string(gbString str, Type *type) { switch (type->kind) { case Type_Basic: - str = gb_string_append_length(str, type->basic.name.text, type->basic.name.len); + str = gb_string_append_length(str, type->Basic.name.text, type->Basic.name.len); break; case Type_Array: - str = gb_string_appendc(str, gb_bprintf("[%td]", type->array.count)); - str = write_type_to_string(str, type->array.elem); + str = gb_string_appendc(str, gb_bprintf("[%td]", type->Array.count)); + str = write_type_to_string(str, type->Array.elem); break; case Type_Vector: - str = gb_string_appendc(str, gb_bprintf("{%td}", type->vector.count)); - str = write_type_to_string(str, type->vector.elem); + str = gb_string_appendc(str, gb_bprintf("{%td}", type->Vector.count)); + str = write_type_to_string(str, type->Vector.elem); break; case Type_Slice: str = gb_string_appendc(str, "[]"); - str = write_type_to_string(str, type->array.elem); + str = write_type_to_string(str, type->Array.elem); break; - case Type_Structure: { + case Type_Struct: { str = gb_string_appendc(str, "struct{"); - for (isize i = 0; i < type->structure.field_count; i++) { - Entity *f = type->structure.fields[i]; + for (isize i = 0; i < type->Struct.field_count; i++) { + Entity *f = type->Struct.fields[i]; GB_ASSERT(f->kind == Entity_Variable); if (i > 0) - str = gb_string_appendc(str, "; "); + str = gb_string_appendc(str, ", "); str = gb_string_append_length(str, f->token.string.text, f->token.string.len); str = gb_string_appendc(str, ": "); str = write_type_to_string(str, f->type); @@ -757,19 +788,33 @@ gbString write_type_to_string(gbString str, Type *type) { str = gb_string_appendc(str, "}"); } break; - case Type_Enumeration: { + case Type_Union: { + str = gb_string_appendc(str, "union{"); + for (isize i = 0; i < type->Union.field_count; i++) { + Entity *f = type->Union.fields[i]; + GB_ASSERT(f->kind == Entity_Variable); + if (i > 0) + str = gb_string_appendc(str, ", "); + str = gb_string_append_length(str, f->token.string.text, f->token.string.len); + str = gb_string_appendc(str, ": "); + str = write_type_to_string(str, f->type); + } + str = gb_string_appendc(str, "}"); + } break; + + case Type_Enum: { str = gb_string_appendc(str, "enum "); - str = write_type_to_string(str, type->enumeration.base); + str = write_type_to_string(str, type->Enum.base); } break; case Type_Pointer: str = gb_string_appendc(str, "^"); - str = write_type_to_string(str, type->pointer.elem); + str = write_type_to_string(str, type->Pointer.elem); break; case Type_Named: - if (type->named.type_name != NULL) { - str = gb_string_append_length(str, type->named.name.text, type->named.name.len); + if (type->Named.type_name != NULL) { + str = gb_string_append_length(str, type->Named.name.text, type->Named.name.len); } else { // NOTE(bill): Just in case str = gb_string_appendc(str, ""); @@ -777,9 +822,9 @@ gbString write_type_to_string(gbString str, Type *type) { break; case Type_Tuple: - if (type->tuple.variable_count > 0) { - for (isize i = 0; i < type->tuple.variable_count; i++) { - Entity *var = type->tuple.variables[i]; + if (type->Tuple.variable_count > 0) { + for (isize i = 0; i < type->Tuple.variable_count; i++) { + Entity *var = type->Tuple.variables[i]; if (var != NULL) { GB_ASSERT(var->kind == Entity_Variable); if (i > 0) @@ -792,12 +837,12 @@ gbString write_type_to_string(gbString str, Type *type) { case Type_Proc: str = gb_string_appendc(str, "proc("); - if (type->proc.params) - str = write_type_to_string(str, type->proc.params); + if (type->Proc.params) + str = write_type_to_string(str, type->Proc.params); str = gb_string_appendc(str, ")"); - if (type->proc.results) { + if (type->Proc.results) { str = gb_string_appendc(str, " -> "); - str = write_type_to_string(str, type->proc.results); + str = write_type_to_string(str, type->Proc.results); } break; } diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index cb2e1e3ad..c5571712c 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -99,7 +99,7 @@ void ssa_print_type(gbFile *f, BaseTypeSizes s, Type *t) { switch (t->kind) { case Type_Basic: - switch (t->basic.kind) { + switch (t->Basic.kind) { case Basic_bool: ssa_fprintf(f, "i1"); break; case Basic_i8: ssa_fprintf(f, "i8"); break; case Basic_i16: ssa_fprintf(f, "i16"); break; @@ -120,74 +120,78 @@ void ssa_print_type(gbFile *f, BaseTypeSizes s, Type *t) { } break; case Type_Array: - ssa_fprintf(f, "[%lld x ", t->array.count); - ssa_print_type(f, s, t->array.elem); + ssa_fprintf(f, "[%lld x ", t->Array.count); + ssa_print_type(f, s, t->Array.elem); ssa_fprintf(f, "]"); break; case Type_Vector: { // TODO(bill): actually do correctly - ssa_fprintf(f, "<%lld x ", t->vector.count); - ssa_print_type(f, s, t->vector.elem); + ssa_fprintf(f, "<%lld x ", t->Vector.count); + ssa_print_type(f, s, t->Vector.elem); ssa_fprintf(f, ">"); } break; case Type_Slice: ssa_fprintf(f, "{"); - ssa_print_type(f, s, t->slice.elem); + ssa_print_type(f, s, t->Slice.elem); ssa_fprintf(f, "*, i%lld, i%lld}", word_bits, word_bits); break; - case Type_Structure: - if (t->structure.is_packed) { + case Type_Struct: + if (t->Struct.is_packed) { ssa_fprintf(f, "<"); } ssa_fprintf(f, "{"); - for (isize i = 0; i < t->structure.field_count; i++) { + for (isize i = 0; i < t->Struct.field_count; i++) { if (i > 0) { ssa_fprintf(f, ", "); } - Type *ft = t->structure.fields[i]->type; + Type *ft = t->Struct.fields[i]->type; Type *bft = get_base_type(ft); - if (bft->kind != Type_Structure) { + if (bft->kind != Type_Struct) { ft = bft; } ssa_print_type(f, s, ft); } ssa_fprintf(f, "}"); - if (t->structure.is_packed) { + if (t->Struct.is_packed) { ssa_fprintf(f, ">"); } break; - case Type_Enumeration: - ssa_print_type(f, s, t->enumeration.base); + case Type_Union: { + i64 size = type_size_of(s, gb_heap_allocator(), t); + ssa_fprintf(f, "[%lld x i8]", size); + } break; + case Type_Enum: + ssa_print_type(f, s, t->Enum.base); break; case Type_Pointer: - ssa_print_type(f, s, t->pointer.elem); + ssa_print_type(f, s, t->Pointer.elem); ssa_fprintf(f, "*"); break; case Type_Named: - ssa_print_encoded_local(f, t->named.name); + ssa_print_encoded_local(f, t->Named.name); break; case Type_Tuple: - if (t->tuple.variable_count == 1) { - ssa_print_type(f, s, t->tuple.variables[0]->type); + if (t->Tuple.variable_count == 1) { + ssa_print_type(f, s, t->Tuple.variables[0]->type); } else { ssa_fprintf(f, "{"); - for (isize i = 0; i < t->tuple.variable_count; i++) { + for (isize i = 0; i < t->Tuple.variable_count; i++) { if (i > 0) ssa_fprintf(f, ", "); - ssa_print_type(f, s, t->tuple.variables[i]->type); + ssa_print_type(f, s, t->Tuple.variables[i]->type); } ssa_fprintf(f, "}"); } break; case Type_Proc: { - if (t->proc.result_count == 0) { + if (t->Proc.result_count == 0) { ssa_fprintf(f, "void"); } else { - ssa_print_type(f, s, t->proc.results); + ssa_print_type(f, s, t->Proc.results); } ssa_fprintf(f, " ("); - auto *params = &t->proc.params->tuple; - for (isize i = 0; i < t->proc.param_count; i++) { + auto *params = &t->Proc.params->Tuple; + for (isize i = 0; i < t->Proc.param_count; i++) { if (i > 0) { ssa_fprintf(f, ", "); } @@ -234,7 +238,7 @@ void ssa_print_exact_value(gbFile *f, ssaModule *m, ExactValue value, Type *type } break; case ExactValue_Float: { u64 u = *cast(u64*)&value.value_float; - if (is_type_float(type) && type->basic.kind == Basic_f32) { + if (is_type_float(type) && type->Basic.kind == Basic_f32) { // IMPORTANT NOTE(bill): LLVM requires all floating point constants to be // a 64 bit number if bits_of(float type) <= 64. // For some bizarre reason, you need to clear the bottom 29 bits @@ -437,7 +441,7 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { Type *type = get_base_type(ssa_type(bo->left)); Type *elem_type = type; while (elem_type->kind == Type_Vector) { - elem_type = get_base_type(elem_type->vector.elem); + elem_type = get_base_type(elem_type->Vector.elem); } ssa_fprintf(f, "%%%d = ", value->id); @@ -558,7 +562,7 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { if (call->arg_count > 0) { Type *proc_type = get_base_type(ssa_type(call->value)); GB_ASSERT(proc_type->kind == Type_Proc); - auto *params = &proc_type->proc.params->tuple; + auto *params = &proc_type->Proc.params->Tuple; for (isize i = 0; i < call->arg_count; i++) { Entity *e = params->variables[i]; GB_ASSERT(e != NULL); @@ -682,7 +686,7 @@ void ssa_print_proc(gbFile *f, ssaModule *m, ssaProcedure *proc) { ssa_fprintf(f, "\ndefine "); } - auto *proc_type = &proc->type->proc; + auto *proc_type = &proc->type->Proc; if (proc_type->result_count == 0) { ssa_fprintf(f, "void"); @@ -696,7 +700,7 @@ void ssa_print_proc(gbFile *f, ssaModule *m, ssaProcedure *proc) { ssa_fprintf(f, "("); if (proc_type->param_count > 0) { - auto *params = &proc_type->params->tuple; + auto *params = &proc_type->params->Tuple; for (isize i = 0; i < params->variable_count; i++) { Entity *e = params->variables[i]; if (i > 0) diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index ad5e997ed..c346f39b3 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -347,8 +347,8 @@ Type *ssa_type(ssaInstr *instr) { case ssaInstr_Call: { Type *pt = get_base_type(instr->Call.type); if (pt != NULL) { - if (pt->kind == Type_Tuple && pt->tuple.variable_count == 1) - return pt->tuple.variables[0]->type; + if (pt->kind == Type_Tuple && pt->Tuple.variable_count == 1) + return pt->Tuple.variables[0]->type; return pt; } return NULL; @@ -536,7 +536,7 @@ ssaValue *ssa_make_instr_extract_value(ssaProcedure *p, ssaValue *address, i32 i i->ExtractValue.result_type = result_type; Type *et = ssa_type(address); i->ExtractValue.elem_type = et; - GB_ASSERT(et->kind == Type_Structure || et->kind == Type_Array || et->kind == Type_Tuple); + GB_ASSERT(et->kind == Type_Struct || et->kind == Type_Array || et->kind == Type_Tuple); return v; } @@ -628,7 +628,7 @@ ssaValue *ssa_make_instr_shuffle_vector(ssaProcedure *p, ssaValue *vector, i32 * v->Instr.ShuffleVector.index_count = index_count; Type *vt = get_base_type(ssa_type(vector)); - v->Instr.ShuffleVector.type = make_type_vector(p->module->allocator, vt->vector.elem, index_count); + v->Instr.ShuffleVector.type = make_type_vector(p->module->allocator, vt->Vector.elem, index_count); return v; } @@ -865,7 +865,7 @@ ssaValue *ssa_lvalue_store(ssaProcedure *proc, ssaAddr lval, ssaValue *value) { if (lval.is_vector) { // HACK(bill): Fix how lvalues for vectors work ssaValue *v = ssa_emit_load(proc, lval.addr); - Type *elem_type = get_base_type(ssa_type(v))->vector.elem; + Type *elem_type = get_base_type(ssa_type(v))->Vector.elem; ssaValue *elem = ssa_emit_conv(proc, value, elem_type); ssaValue *out = ssa_emit(proc, ssa_make_instr_insert_element(proc, v, elem, lval.index)); return ssa_emit_store(proc, lval.addr, out); @@ -901,8 +901,8 @@ void ssa_begin_procedure_body(ssaProcedure *proc) { gb_array_init(proc->defer_stmts, gb_heap_allocator()); proc->curr_block = ssa_add_block(proc, proc->type_expr, make_string("entry")); - if (proc->type->proc.params != NULL) { - auto *params = &proc->type->proc.params->tuple; + if (proc->type->Proc.params != NULL) { + auto *params = &proc->type->Proc.params->Tuple; for (isize i = 0; i < params->variable_count; i++) { Entity *e = params->variables[i]; ssa_add_param(proc, e); @@ -911,7 +911,7 @@ void ssa_begin_procedure_body(ssaProcedure *proc) { } void ssa_end_procedure_body(ssaProcedure *proc) { - if (proc->type->proc.result_count == 0) { + if (proc->type->Proc.result_count == 0) { ssa_emit_ret(proc, NULL); } @@ -1005,7 +1005,7 @@ ssaValue *ssa_emit_comp(ssaProcedure *proc, Token op, ssaValue *left, ssaValue * ssaValue *v = ssa_make_instr_binary_op(proc, op, left, right); Type *result = t_bool; if (is_type_vector(a)) { - result = make_type_vector(proc->module->allocator, t_bool, a->vector.count); + result = make_type_vector(proc->module->allocator, t_bool, a->Vector.count); } ssa_set_type(v, result); return ssa_emit(proc, v); @@ -1057,7 +1057,7 @@ ssaValue *ssa_emit_struct_ev(ssaProcedure *proc, ssaValue *s, i32 index, Type *r ssaValue *ssa_array_elem(ssaProcedure *proc, ssaValue *array) { Type *t = ssa_type(array); GB_ASSERT(t->kind == Type_Array); - Type *base_type = t->array.elem; + Type *base_type = t->Array.elem; ssaValue *elem = ssa_make_instr_get_element_ptr(proc, array, v_zero, v_zero, 2, true); Type *result_type = make_type_pointer(proc->module->allocator, base_type); elem->Instr.GetElementPtr.elem_type = t; @@ -1067,7 +1067,7 @@ ssaValue *ssa_array_elem(ssaProcedure *proc, ssaValue *array) { ssaValue *ssa_array_len(ssaProcedure *proc, ssaValue *array) { Type *t = ssa_type(array); GB_ASSERT(t->kind == Type_Array); - return ssa_make_value_constant(proc->module->allocator, t_int, make_exact_value_integer(t->array.count)); + return ssa_make_value_constant(proc->module->allocator, t_int, make_exact_value_integer(t->Array.count)); } ssaValue *ssa_array_cap(ssaProcedure *proc, ssaValue *array) { return ssa_array_len(proc, array); @@ -1077,7 +1077,7 @@ ssaValue *ssa_slice_elem(ssaProcedure *proc, ssaValue *slice) { Type *t = ssa_type(slice); GB_ASSERT(t->kind == Type_Slice); - Type *result_type = make_type_pointer(proc->module->allocator, t->slice.elem); + Type *result_type = make_type_pointer(proc->module->allocator, t->Slice.elem); return ssa_emit_load(proc, ssa_emit_struct_gep(proc, slice, v_zero32, result_type)); } ssaValue *ssa_slice_len(ssaProcedure *proc, ssaValue *slice) { @@ -1093,7 +1093,7 @@ ssaValue *ssa_slice_cap(ssaProcedure *proc, ssaValue *slice) { ssaValue *ssa_string_elem(ssaProcedure *proc, ssaValue *string) { Type *t = ssa_type(string); - GB_ASSERT(t->kind == Type_Basic && t->basic.kind == Basic_string); + GB_ASSERT(t->kind == Type_Basic && t->Basic.kind == Basic_string); Type *base_type = t_u8; ssaValue *elem = ssa_make_instr_get_element_ptr(proc, string, v_zero, v_zero32, 2, true); Type *result_type = make_type_pointer(proc->module->allocator, base_type); @@ -1103,7 +1103,7 @@ ssaValue *ssa_string_elem(ssaProcedure *proc, ssaValue *string) { } ssaValue *ssa_string_len(ssaProcedure *proc, ssaValue *string) { Type *t = ssa_type(string); - GB_ASSERT(t->kind == Type_Basic && t->basic.kind == Basic_string); + GB_ASSERT(t->kind == Type_Basic && t->Basic.kind == Basic_string); return ssa_emit_load(proc, ssa_emit_struct_gep(proc, string, v_one32, t_int)); } @@ -1217,7 +1217,7 @@ ssaValue *ssa_emit_string(ssaProcedure *proc, ssaValue *elem, ssaValue *len) { Type *t_u8_ptr = ssa_type(elem); GB_ASSERT(t_u8_ptr->kind == Type_Pointer); - GB_ASSERT(is_type_u8(t_u8_ptr->pointer.elem)); + GB_ASSERT(is_type_u8(t_u8_ptr->Pointer.elem)); ssaValue *str = ssa_add_local_generated(proc, t_string); ssaValue *str_elem = ssa_emit_struct_gep(proc, str, v_zero32, t_u8_ptr); @@ -1293,8 +1293,8 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) { // float -> float if (is_type_float(src) && is_type_float(dst)) { - i64 sz = basic_type_sizes[src->basic.kind]; - i64 dz = basic_type_sizes[dst->basic.kind]; + i64 sz = basic_type_sizes[src->Basic.kind]; + i64 dz = basic_type_sizes[dst->Basic.kind]; ssaConvKind kind = ssaConv_fptrunc; if (dz >= sz) { kind = ssaConv_fpext; @@ -1368,13 +1368,13 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) { } if (is_type_vector(dst)) { - Type *dst_elem = dst->vector.elem; + Type *dst_elem = dst->Vector.elem; value = ssa_emit_conv(proc, value, dst_elem); ssaValue *v = ssa_add_local_generated(proc, t); v = ssa_emit_load(proc, v); v = ssa_emit(proc, ssa_make_instr_insert_element(proc, v, value, v_zero32)); // NOTE(bill): Broadcast lowest value to all values - isize index_count = dst->vector.count; + isize index_count = dst->Vector.count; i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count); for (isize i = 0; i < index_count; i++) { indices[i] = 0; @@ -1557,9 +1557,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue Type *et = NULL; switch (base_type->kind) { - case Type_Vector: et = base_type->vector.elem; break; - case Type_Array: et = base_type->array.elem; break; - case Type_Slice: et = base_type->slice.elem; break; + case Type_Vector: et = base_type->Vector.elem; break; + case Type_Array: et = base_type->Array.elem; break; + case Type_Slice: et = base_type->Slice.elem; break; } switch (base_type->kind) { @@ -1578,8 +1578,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue *i = ssa_make_value_constant(proc->module->allocator, t_int, make_exact_value_integer(index)); result = ssa_emit(proc, ssa_make_instr_insert_element(proc, result, ev, i)); } - if (index == 1 && base_type->vector.count > 1) { - isize index_count = base_type->vector.count; + if (index == 1 && base_type->Vector.count > 1) { + isize index_count = base_type->Vector.count; i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count); for (isize i = 0; i < index_count; i++) { indices[i] = 0; @@ -1592,8 +1592,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue return result; } break; - case Type_Structure: { - auto *st = &base_type->structure; + case Type_Struct: { + auto *st = &base_type->Struct; if (cl->elem_list != NULL) { isize index = 0; AstNode *elem = cl->elem_list; @@ -1699,7 +1699,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue *src_slice = ssa_build_addr(proc, src_node).addr; Type *slice_type = get_base_type(ssa_type(dst_slice)); GB_ASSERT(slice_type->kind == Type_Slice); - Type *elem_type = slice_type->slice.elem; + Type *elem_type = slice_type->Slice.elem; i64 size_of_elem = type_size_of(proc->module->sizes, proc->module->allocator, elem_type); ssaValue *dst = ssa_emit_conv(proc, ssa_slice_elem(proc, dst_slice), t_rawptr); @@ -1803,7 +1803,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue *value = ssa_build_expr(proc, ce->proc); Type *proc_type_ = get_base_type(ssa_type(value)); GB_ASSERT(proc_type_->kind == Type_Proc); - auto *type = &proc_type_->proc; + auto *type = &proc_type_->Proc; isize arg_index = 0; isize arg_count = type->param_count; @@ -1813,8 +1813,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue *a = ssa_build_expr(proc, arg); Type *at = ssa_type(a); if (at->kind == Type_Tuple) { - for (isize i = 0; i < at->tuple.variable_count; i++) { - Entity *e = at->tuple.variables[i]; + for (isize i = 0; i < at->Tuple.variable_count; i++) { + Entity *e = at->Tuple.variables[i]; ssaValue *v = ssa_emit_struct_ev(proc, a, i, e->type); args[arg_index++] = v; } @@ -1823,7 +1823,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } } - auto *pt = &proc_type_->proc.params->tuple; + auto *pt = &proc_type_->Proc.params->Tuple; for (isize i = 0; i < arg_count; i++) { args[i] = ssa_emit_conv(proc, args[i], pt->variables[i]->type); } @@ -1914,8 +1914,18 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { ssa_set_type(e, type_deref(type)); } - ssaValue *v = ssa_emit_struct_gep(proc, e, field_index, entity->type); - return ssa_make_addr(v, expr); + if (type->kind == Type_Union) { + ssaValue *v = ssa_emit_ptr_offset(proc, e, v_zero); + ssa_set_type(v, make_type_pointer(proc->module->allocator, type)); + ssaValue *f = ssa_emit_conv(proc, v, make_type_pointer(proc->module->allocator, entity->type)); + f = ssa_emit_ptr_offset(proc, f, v_zero); + ssa_set_type(f, entity->type); + return ssa_make_addr(f, expr); + + } else { + ssaValue *v = ssa_emit_struct_gep(proc, e, field_index, entity->type); + return ssa_make_addr(v, expr); + } case_end; case_ast_node(ue, UnaryExpr, expr); @@ -2159,8 +2169,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ssaValue *init = ssa_build_expr(proc, value); Type *t = ssa_type(init); if (t->kind == Type_Tuple) { - for (isize i = 0; i < t->tuple.variable_count; i++) { - Entity *e = t->tuple.variables[i]; + for (isize i = 0; i < t->Tuple.variable_count; i++) { + Entity *e = t->Tuple.variables[i]; ssaValue *v = ssa_emit_struct_ev(proc, init, i, e->type); gb_array_append(inits, v); } @@ -2239,7 +2249,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ssaValue *value = ssa_make_value_type_name(proc->module->allocator, name, e->type); // HACK(bill): Override name of type so printer prints it correctly - e->type->named.name = name; + e->type->Named.name = name; ssa_module_add_value(proc->module, e, value); gb_array_append(proc->module->nested_type_names, value); case_end; @@ -2303,8 +2313,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { Type *t = ssa_type(init); // TODO(bill): refactor for code reuse as this is repeated a bit if (t->kind == Type_Tuple) { - for (isize i = 0; i < t->tuple.variable_count; i++) { - Entity *e = t->tuple.variables[i]; + for (isize i = 0; i < t->Tuple.variable_count; i++) { + Entity *e = t->Tuple.variables[i]; ssaValue *v = ssa_emit_struct_ev(proc, init, i, e->type); gb_array_append(inits, v); } @@ -2356,8 +2366,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_ast_node(rs, ReturnStmt, node); ssaValue *v = NULL; - auto *return_type_tuple = &proc->type->proc.results->tuple; - isize return_count = proc->type->proc.result_count; + auto *return_type_tuple = &proc->type->Proc.results->Tuple; + isize return_count = proc->type->Proc.result_count; if (rs->result_count == 1 && return_count > 1) { GB_PANIC("ReturnStmt tuple return statement"); } else if (return_count == 1) { @@ -2368,7 +2378,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { // No return values } else { // 1:1 multiple return values - Type *ret_type = proc->type->proc.results; + Type *ret_type = proc->type->Proc.results; v = ssa_add_local_generated(proc, ret_type); isize i = 0; AstNode *r = rs->result_list; diff --git a/src/main.cpp b/src/main.cpp index df9bd5205..c2cbb124b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,6 +35,7 @@ i32 win32_exec_command_line_app(char *fmt, ...) { return cast(i32)exit_code; } else { // NOTE(bill): failed to create process + gb_printf_err("Failed to execute command:\n\t%s\n", cmd_line); return -1; } } @@ -56,51 +57,50 @@ int main(int argc, char **argv) { Parser parser = {0}; - if (init_parser(&parser)) { - defer (destroy_parser(&parser)); + if (!init_parser(&parser)) + return 1; + defer (destroy_parser(&parser)); - if (parse_files(&parser, init_filename) == ParseFile_None) { - // print_ast(parser.files[0].decls, 0); + if (parse_files(&parser, init_filename) != ParseFile_None) + return 1; - Checker checker = {}; + // print_ast(parser.files[0].decls, 0); - init_checker(&checker, &parser); - defer (destroy_checker(&checker)); + Checker checker = {}; - check_parsed_files(&checker); - ssaGen ssa = {}; - if (ssa_gen_init(&ssa, &checker)) { - defer (ssa_gen_destroy(&ssa)); + init_checker(&checker, &parser); + defer (destroy_checker(&checker)); - ssa_gen_code(&ssa); + check_parsed_files(&checker); + ssaGen ssa = {}; + if (!ssa_gen_init(&ssa, &checker)) + return 1; + defer (ssa_gen_destroy(&ssa)); - char const *output_name = ssa.output_file.filename; - isize base_name_len = gb_path_extension(output_name)-1 - output_name; + ssa_gen_code(&ssa); - i32 exit_code = win32_exec_command_line_app( - "../misc/llvm-bin/opt -mem2reg %s -o %.*s.bc", - output_name, cast(int)base_name_len, output_name); - if (exit_code != 0) - return exit_code; + char const *output_name = ssa.output_file.filename; + isize base_name_len = gb_path_extension(output_name)-1 - output_name; - exit_code = win32_exec_command_line_app( - "clang -o %.*s.exe %.*s.bc " - "-Wno-override-module " - // "-nostartfiles " - "-lKernel32.lib -lUser32.lib -lGdi32.lib -lOpengl32.lib " - , - cast(int)base_name_len, output_name, - cast(int)base_name_len, output_name); - if (exit_code != 0) - return exit_code; + i32 exit_code = win32_exec_command_line_app( + "../misc/llvm-bin/opt -mem2reg %s -o %.*s.bc", + output_name, cast(int)base_name_len, output_name); + if (exit_code != 0) + return exit_code; - if (run_output) { - win32_exec_command_line_app("%.*s.exe", cast(int)base_name_len, output_name); - } - return 0; - } - } + exit_code = win32_exec_command_line_app( + "clang -o %.*s.exe %.*s.bc " + "-Wno-override-module " + // "-nostartfiles " + "-lKernel32.lib -lUser32.lib -lGdi32.lib -lOpengl32.lib " + , + cast(int)base_name_len, output_name, + cast(int)base_name_len, output_name); + if (exit_code != 0) + return exit_code; + + if (run_output) { + win32_exec_command_line_app("%.*s.exe", cast(int)base_name_len, output_name); } - - return 1; + return 0; } diff --git a/src/parser.cpp b/src/parser.cpp index 6fb491557..56a90aca9 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -82,9 +82,9 @@ enum VarDeclTag { }; enum CallExprKind { - CallExpr_Normal, - CallExpr_UnaryOp, - CallExpr_BinaryOp, + CallExpr_Prefix, // call(...) + CallExpr_Postfix, // a'call + CallExpr_Infix, // a ''call b }; #define AST_NODE_KINDS \ @@ -225,6 +225,11 @@ AST_NODE_KIND(_TypeBegin, struct{}) \ isize field_count; \ b32 is_packed; \ }) \ + AST_NODE_KIND(UnionType, struct { \ + Token token; \ + AstNode *field_list; \ + isize field_count; \ + }) \ AST_NODE_KIND(EnumType, struct { \ Token token; \ AstNode *base_type; \ @@ -374,6 +379,8 @@ Token ast_node_token(AstNode *node) { return node->VectorType.token; case AstNode_StructType: return node->StructType.token; + case AstNode_UnionType: + return node->UnionType.token; case AstNode_EnumType: return node->EnumType.token; } @@ -778,6 +785,14 @@ gb_inline AstNode *make_struct_type(AstFile *f, Token token, AstNode *field_list return result; } +gb_inline AstNode *make_union_type(AstFile *f, Token token, AstNode *field_list, isize field_count) { + AstNode *result = make_node(f, AstNode_UnionType); + result->UnionType.token = token; + result->UnionType.field_list = field_list; + result->UnionType.field_count = field_count; + return result; +} + gb_inline AstNode *make_enum_type(AstFile *f, Token token, AstNode *base_type, AstNode *field_list, isize field_count) { AstNode *result = make_node(f, AstNode_EnumType); @@ -1194,12 +1209,12 @@ AstNode *parse_atom_expr(AstFile *f, b32 lhs) { while (loop) { switch (f->cursor[0].kind) { - case Token_CustomUnaryOp: { - Token op = expect_token(f, Token_CustomUnaryOp); + case Token_Prime: { + Token op = expect_token(f, Token_Prime); if (lhs) { // TODO(bill): Handle this } - AstNode *proc = make_ident(f, op); + AstNode *proc = parse_identifier(f); operand = make_call_expr(f, proc, operand, 1, ast_node_token(operand), op); } break; @@ -1363,6 +1378,15 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) { lhs = false; } + + if (op.kind == Token_DoublePrime) { + AstNode *proc = parse_identifier(f); + AstNode *right = parse_binary_expr(f, false, prec+1); + expression->next = right; + expression = make_call_expr(f, proc, expression, 2, op, ast_node_token(right)); + continue; + } + if (op.kind == Token_as || op.kind == Token_transmute) { right = parse_type(f); } else { @@ -1372,13 +1396,7 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) { } } - if (op.kind == Token_CustomBinaryOp) { - AstNode *proc = make_ident(f, op); - expression->next = right; - expression = make_call_expr(f, proc, expression, 2, ast_node_token(expression), ast_node_token(right)); - } else { - expression = make_binary_expr(f, op, expression, right); - } + expression = make_binary_expr(f, op, expression, right); } } return expression; @@ -1657,6 +1675,20 @@ AstNode *parse_identifier_or_type(AstFile *f) { return make_struct_type(f, token, params, param_count, is_packed); } + case Token_union: { + Token token = expect_token(f, Token_union); + Token open, close; + AstNode *params = NULL; + isize param_count = 0; + AstScope *scope = make_ast_scope(f, NULL); // NOTE(bill): The union needs its own scope with NO parent + + open = expect_token(f, Token_OpenBrace); + params = parse_parameter_list(f, scope, ¶m_count); + close = expect_token(f, Token_CloseBrace); + + return make_union_type(f, token, params, param_count); + } + case Token_enum: { Token token = expect_token(f, Token_enum); AstNode *base_type = NULL; @@ -2055,6 +2087,7 @@ AstNode *parse_stmt(AstFile *f) { if (s->kind != AstNode_ProcDecl && (s->kind == AstNode_TypeDecl && s->TypeDecl.type->kind != AstNode_StructType && + s->TypeDecl.type->kind != AstNode_UnionType && s->TypeDecl.type->kind != AstNode_EnumType && s->TypeDecl.type->kind != AstNode_ProcType) && !allow_token(f, Token_Semicolon)) { diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 82c98e256..c931a7eb0 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -31,8 +31,8 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \ TOKEN_KIND(Token_as, "as"), \ TOKEN_KIND(Token_transmute, "transmute"), \ \ - TOKEN_KIND(Token_CustomUnaryOp, "custom unary op"), \ - TOKEN_KIND(Token_CustomBinaryOp, "custom binary op"), \ + TOKEN_KIND(Token_Prime, "'"), \ + TOKEN_KIND(Token_DoublePrime, "''"), \ \ TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \ TOKEN_KIND(Token_AddEq, "+="), \ @@ -96,6 +96,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ TOKEN_KIND(Token_struct, "struct"), \ TOKEN_KIND(Token_union, "union"), \ TOKEN_KIND(Token_enum, "enum"), \ + TOKEN_KIND(Token_using, "using"), \ TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \ TOKEN_KIND(Token_Count, "") @@ -202,7 +203,7 @@ i32 token_precedence(Token t) { case Token_Shl: case Token_Shr: return 5; - case Token_CustomBinaryOp: + case Token_DoublePrime: return 6; case Token_as: case Token_transmute: @@ -647,26 +648,13 @@ Token tokenizer_get_token(Tokenizer *t) { token.kind = Token_EOF; break; - case '\'': { - token.kind = Token_CustomUnaryOp; - while (rune_is_whitespace(t->curr_rune)) - advance_to_next_rune(t); - token.string.text = t->curr; - while (rune_is_letter(t->curr_rune) || rune_is_digit(t->curr_rune)) { - advance_to_next_rune(t); - } - token.string.len = t->curr - token.string.text; - - while (rune_is_whitespace(t->curr_rune)) - advance_to_next_rune(t); - + case '\'': + token.kind = Token_Prime; if (t->curr_rune == '\'') { advance_to_next_rune(t); - token.kind = Token_CustomBinaryOp; + token.kind = Token_DoublePrime; } - - return token; - } break; + break; case '`': // Raw String Literal case '"': // String Literal