diff options
| author | Zachary Pierson <zacpiersonhehe@gmail.com> | 2017-03-30 00:26:46 -0500 |
|---|---|---|
| committer | Zachary Pierson <zacpiersonhehe@gmail.com> | 2017-03-30 00:26:46 -0500 |
| commit | 1349aa6f2cfc63ace0382a8dd6b346f24e861ea9 (patch) | |
| tree | 55b6fb23ecfb86e3c474bfd4bbc8e9bb5c78f986 /src | |
| parent | 7a28827602f29f0e9485ca6617daf316635802df (diff) | |
| parent | a75ccb6fbc529d2fee00f9b456ca7c0c830548ee (diff) | |
Merge https://github.com/gingerBill/Odin, cleaned up a bit, fixed the object file version message on macOS
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.c | 420 | ||||
| -rw-r--r-- | src/check_stmt.c | 18 | ||||
| -rw-r--r-- | src/ir.c | 46 | ||||
| -rw-r--r-- | src/ir_print.c | 4 | ||||
| -rw-r--r-- | src/main.c | 14 | ||||
| -rw-r--r-- | src/parser.c | 2 | ||||
| -rw-r--r-- | src/types.c | 23 |
7 files changed, 325 insertions, 202 deletions
diff --git a/src/check_expr.c b/src/check_expr.c index fcb3e948e..db1bbd135 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -1102,8 +1102,8 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type * if (e->type == NULL) { - compiler_error("Compiler error: How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(name)); - return NULL; + compiler_error("How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(name)); + // return NULL; } e->flags |= EntityFlag_Used; @@ -1339,14 +1339,11 @@ void check_map_type(Checker *c, Type *type, AstNode *node) { // error_node(node, "`map` types are not yet implemented"); } -Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { - ExactValue null_value = {ExactValue_Invalid}; - Type *type = NULL; - gbString err_str = NULL; - +bool check_type_extra_interal(Checker *c, AstNode *e, Type **type, Type *named_type) { + GB_ASSERT_NOT_NULL(type); if (e == NULL) { - type = t_invalid; - goto end; + *type = t_invalid; + return true; } switch (e->kind) { @@ -1358,17 +1355,19 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { case Addressing_Invalid: break; case Addressing_Type: { - type = o.type; - goto end; + *type = o.type; + return true; } break; - case Addressing_NoValue: - err_str = expr_to_string(e); + case Addressing_NoValue: { + gbString err_str = expr_to_string(e); error_node(e, "`%s` used as a type", err_str); - break; - default: - err_str = expr_to_string(e); + gb_string_free(err_str); + } break; + default: { + gbString err_str = expr_to_string(e); error_node(e, "`%s` used as a type when not a type", err_str); - break; + gb_string_free(err_str); + } break; } case_end; @@ -1381,43 +1380,46 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { break; case Addressing_Type: GB_ASSERT(o.type != NULL); - type = o.type; - goto end; - case Addressing_NoValue: - err_str = expr_to_string(e); + *type = o.type; + return true; + case Addressing_NoValue: { + gbString err_str = expr_to_string(e); error_node(e, "`%s` used as a type", err_str); - break; - default: - err_str = expr_to_string(e); + gb_string_free(err_str); + } break; + default: { + gbString err_str = expr_to_string(e); error_node(e, "`%s` is not a type", err_str); - break; + gb_string_free(err_str); + } break; } case_end; case_ast_node(pe, ParenExpr, e); - type = check_type_extra(c, pe->expr, named_type); - goto end; + *type = check_type_extra(c, pe->expr, named_type); + return true; case_end; case_ast_node(ue, UnaryExpr, e); if (ue->op.kind == Token_Pointer) { - type = make_type_pointer(c->allocator, check_type(c, ue->expr)); - goto end; + *type = make_type_pointer(c->allocator, check_type(c, ue->expr)); + return true; } /* else if (ue->op.kind == Token_Maybe) { - type = make_type_maybe(c->allocator, check_type(c, ue->expr)); - goto end; + *type = make_type_maybe(c->allocator, check_type(c, ue->expr)); + return true; } */ case_end; case_ast_node(ht, HelperType, e); - type = check_type(c, ht->type); - goto end; + *type = check_type(c, ht->type); + return true; case_end; case_ast_node(pt, PointerType, e); Type *elem = check_type(c, pt->type); - type = make_type_pointer(c->allocator, elem); - goto end; + i64 esz = type_size_of(c->allocator, elem); + *type = make_type_pointer(c->allocator, elem); + return true; case_end; case_ast_node(at, ArrayType, e); @@ -1425,21 +1427,39 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { Type *elem = check_type_extra(c, at->elem, NULL); i64 count = check_array_or_map_count(c, at->count, false); if (count < 0) { - error_node(at->count, "? can only be used in conjuction with compound literals"); + error_node(at->count, ".. can only be used in conjuction with compound literals"); count = 0; } - type = make_type_array(c->allocator, elem, count); + i64 esz = type_size_of(c->allocator, elem); + if (esz <= 0) { + gbString str = type_to_string(elem); + error_node(at->elem, "Zero sized element type `%s` is not allowed", str); + gb_string_free(str); + } + *type = make_type_array(c->allocator, elem, count); } else { Type *elem = check_type(c, at->elem); - type = make_type_slice(c->allocator, elem); + i64 esz = type_size_of(c->allocator, elem); + if (esz <= 0) { + gbString str = type_to_string(elem); + error_node(at->elem, "Zero sized element type `%s` is not allowed", str); + gb_string_free(str); + } + *type = make_type_slice(c->allocator, elem); } - goto end; + return true; case_end; case_ast_node(dat, DynamicArrayType, e); Type *elem = check_type_extra(c, dat->elem, NULL); - type = make_type_dynamic_array(c->allocator, elem); - goto end; + i64 esz = type_size_of(c->allocator, elem); + if (esz <= 0) { + gbString str = type_to_string(elem); + error_node(dat->elem, "Zero sized element type `%s` is not allowed", str); + gb_string_free(str); + } + *type = make_type_dynamic_array(c->allocator, elem); + return true; case_end; @@ -1449,84 +1469,96 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { Type *be = base_type(elem); i64 count = check_array_or_map_count(c, vt->count, false); if (is_type_vector(be) || (!is_type_boolean(be) && !is_type_numeric(be))) { - err_str = type_to_string(elem); + gbString err_str = type_to_string(elem); error_node(vt->elem, "Vector element type must be numerical or a boolean, got `%s`", err_str); + gb_string_free(err_str); } - type = make_type_vector(c->allocator, elem, count); - goto end; + *type = make_type_vector(c->allocator, elem, count); + return true; case_end; case_ast_node(st, StructType, e); - type = make_type_struct(c->allocator); - set_base_type(named_type, type); + *type = make_type_struct(c->allocator); + set_base_type(named_type, *type); check_open_scope(c, e); - check_struct_type(c, type, e); + check_struct_type(c, *type, e); check_close_scope(c); - type->Record.node = e; - goto end; + (*type)->Record.node = e; + return true; case_end; case_ast_node(ut, UnionType, e); - type = make_type_union(c->allocator); - set_base_type(named_type, type); + *type = make_type_union(c->allocator); + set_base_type(named_type, *type); check_open_scope(c, e); - check_union_type(c, type, e); + check_union_type(c, *type, e); check_close_scope(c); - type->Record.node = e; - goto end; + (*type)->Record.node = e; + return true; case_end; case_ast_node(rut, RawUnionType, e); - type = make_type_raw_union(c->allocator); - set_base_type(named_type, type); + *type = make_type_raw_union(c->allocator); + set_base_type(named_type, *type); check_open_scope(c, e); - check_raw_union_type(c, type, e); + check_raw_union_type(c, *type, e); check_close_scope(c); - type->Record.node = e; - goto end; + (*type)->Record.node = e; + return true; case_end; case_ast_node(et, EnumType, e); - type = make_type_enum(c->allocator); - set_base_type(named_type, type); + *type = make_type_enum(c->allocator); + set_base_type(named_type, *type); check_open_scope(c, e); - check_enum_type(c, type, named_type, e); + check_enum_type(c, *type, named_type, e); check_close_scope(c); - type->Record.node = e; - goto end; + (*type)->Record.node = e; + return true; case_end; case_ast_node(pt, ProcType, e); - type = alloc_type(c->allocator, Type_Proc); - set_base_type(named_type, type); + *type = alloc_type(c->allocator, Type_Proc); + set_base_type(named_type, *type); check_open_scope(c, e); - check_procedure_type(c, type, e); + check_procedure_type(c, *type, e); check_close_scope(c); - goto end; + return true; case_end; case_ast_node(mt, MapType, e); - type = alloc_type(c->allocator, Type_Map); - set_base_type(named_type, type); - check_map_type(c, type, e); - goto end; + *type = alloc_type(c->allocator, Type_Map); + set_base_type(named_type, *type); + check_map_type(c, *type, e); + return true; case_end; case_ast_node(ce, CallExpr, e); Operand o = {0}; check_expr_or_type(c, &o, e); if (o.mode == Addressing_Type) { - type = o.type; - goto end; + *type = o.type; + return true; } case_end; } - err_str = expr_to_string(e); - error_node(e, "`%s` is not a type", err_str); - type = t_invalid; -end: - gb_string_free(err_str); + *type = t_invalid; + return false; +} + + + +Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { + Type *type = NULL; + bool ok = check_type_extra_interal(c, e, &type, named_type); + + if (!ok) { + gbString err_str = expr_to_string(e); + error_node(e, "`%s` is not a type", err_str); + gb_string_free(err_str); + type = t_invalid; + } if (type == NULL) { type = t_invalid; @@ -1542,7 +1574,7 @@ end: } if (is_type_typed(type)) { - add_type_and_value(&c->info, e, Addressing_Type, type, null_value); + add_type_and_value(&c->info, e, Addressing_Type, type, (ExactValue){0}); } else { gbString name = type_to_string(type); error_node(e, "Invalid type definition of %s", name); @@ -1551,8 +1583,6 @@ end: } set_base_type(named_type, type); - - return type; } @@ -2093,9 +2123,19 @@ Operand check_ptr_addition(Checker *c, TokenKind op, Operand *ptr, Operand *offs return operand; } + Type *base_ptr = base_type(ptr->type); GB_ASSERT(base_ptr->kind == Type_Pointer); + Type *elem = base_ptr->Pointer.elem; + i64 elem_size = type_size_of(c->allocator, elem); + + if (elem_size <= 0) { + gbString str = type_to_string(elem); + error_node(node, "Size of pointer's element type `%s` is zero and cannot be used for pointer arithmetic", str); + gb_string_free(str); + operand.mode = Addressing_Invalid; + return operand; + } if (ptr->mode == Addressing_Constant && offset->mode == Addressing_Constant) { - i64 elem_size = type_size_of(c->allocator, ptr->type); i64 ptr_val = ptr->value.value_pointer; i64 offset_val = exact_value_to_integer(offset->value).value_integer; i64 new_ptr_val = ptr_val; @@ -2523,7 +2563,9 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level update_expr_type(c, operand->expr, target_type, false); } } else if (x_kind != y_kind) { - goto error; + operand->mode = Addressing_Invalid; + convert_untyped_error(c, operand, target_type); + return; } return; } @@ -2541,20 +2583,26 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level switch (operand->type->Basic.kind) { case Basic_UntypedBool: if (!is_type_boolean(target_type)) { - goto error; + operand->mode = Addressing_Invalid; + convert_untyped_error(c, operand, target_type); + return; } break; case Basic_UntypedInteger: case Basic_UntypedFloat: case Basic_UntypedRune: if (!is_type_numeric(target_type)) { - goto error; + operand->mode = Addressing_Invalid; + convert_untyped_error(c, operand, target_type); + return; } break; case Basic_UntypedNil: if (!type_has_nil(target_type)) { - goto error; + operand->mode = Addressing_Invalid; + convert_untyped_error(c, operand, target_type); + return; } break; } @@ -2563,7 +2611,9 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level default: if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) { - goto error; + operand->mode = Addressing_Invalid; + convert_untyped_error(c, operand, target_type); + return; } target_type = t_untyped_nil; break; @@ -2571,11 +2621,6 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level operand->type = target_type; update_expr_type(c, operand->expr, target_type, true); - return; - -error: - operand->mode = Addressing_Invalid; - convert_untyped_error(c, operand, target_type); } bool check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *value) { @@ -2670,16 +2715,22 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h Entity *entity = NULL; Selection sel = {0}; // NOTE(bill): Not used if it's an import name + operand->expr = node; + AstNode *op_expr = se->expr; AstNode *selector = unparen_expr(se->selector); if (selector == NULL) { - goto error; + operand->mode = Addressing_Invalid; + operand->expr = node; + return NULL; } // if (selector->kind != AstNode_Ident && selector->kind != AstNode_BasicLit) { if (selector->kind != AstNode_Ident) { error_node(selector, "Illegal selector kind: `%.*s`", LIT(ast_node_strings[selector->kind])); - goto error; + operand->mode = Addressing_Invalid; + operand->expr = node; + return NULL; } if (op_expr->kind == AstNode_Ident) { @@ -2716,7 +2767,9 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h } if (!is_declared) { error_node(op_expr, "`%.*s` is not declared by `%.*s`", LIT(entity_name), LIT(import_name)); - goto error; + operand->mode = Addressing_Invalid; + operand->expr = node; + return NULL; } check_entity_decl(c, entity, NULL, NULL); GB_ASSERT(entity->type != NULL); @@ -2736,7 +2789,9 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h gbString sel_str = expr_to_string(selector); error_node(op_expr, "`%s` is not exported by `%.*s`", sel_str, LIT(import_name)); gb_string_free(sel_str); - goto error; + operand->mode = Addressing_Invalid; + operand->expr = node; + return NULL; } if (is_overloaded) { @@ -2786,7 +2841,9 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h if (check_op_expr) { check_expr_base(c, operand, op_expr, NULL); if (operand->mode == Addressing_Invalid) { - goto error; + operand->mode = Addressing_Invalid; + operand->expr = node; + return NULL; } } @@ -2797,7 +2854,9 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h if (operand->mode != Addressing_Type && !check_is_field_exported(c, sel.entity)) { error_node(op_expr, "`%.*s` is an unexported field", LIT(field_name)); - goto error; + operand->mode = Addressing_Invalid; + operand->expr = node; + return NULL; } entity = sel.entity; @@ -2814,12 +2873,16 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h if (o.mode != Addressing_Constant || !is_type_integer(o.type)) { error_node(op_expr, "Indexed based selectors must be a constant integer %s"); - goto error; + operand->mode = Addressing_Invalid; + operand->expr = node; + return NULL; } i64 index = o.value.value_integer; if (index < 0) { error_node(o.expr, "Index %lld cannot be a negative value", index); - goto error; + operand->mode = Addressing_Invalid; + operand->expr = node; + return NULL; } i64 max_count = 0; @@ -2830,7 +2893,9 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h if (index >= max_count) { error_node(o.expr, "Index %lld is out of bounds range 0..<%lld", index, max_count); - goto error; + operand->mode = Addressing_Invalid; + operand->expr = node; + return NULL; } sel = lookup_field_from_index(heap_allocator(), type, index); @@ -2840,7 +2905,9 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h } else { error_node(op_expr, "Indexed based selectors may only be used on structs or tuples"); - goto error; + operand->mode = Addressing_Invalid; + operand->expr = node; + return NULL; } } @@ -2861,7 +2928,9 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h gb_string_free(sel_str); gb_string_free(type_str); gb_string_free(op_str); - goto error; + operand->mode = Addressing_Invalid; + operand->expr = node; + return NULL; } if (expr_entity != NULL && expr_entity->kind == Entity_Constant && entity->kind != Entity_Constant) { @@ -2872,7 +2941,9 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h gb_string_free(sel_str); gb_string_free(type_str); gb_string_free(op_str); - goto error; + operand->mode = Addressing_Invalid; + operand->expr = node; + return NULL; } @@ -2915,11 +2986,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h operand->expr = node; return entity; - -error: - operand->mode = Addressing_Invalid; - operand->expr = node; - return NULL; } bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) { @@ -4293,7 +4359,8 @@ bool check_set_index_data(Operand *o, Type *type, bool indirection, i64 *max_cou return false; } -ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint) { + +ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *type_hint) { ExprKind kind = Expr_Stmt; o->mode = Addressing_Invalid; @@ -4301,16 +4368,15 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint switch (node->kind) { default: - goto error; - break; + return kind; case_ast_node(be, BadExpr, node) - goto error; + return kind; case_end; case_ast_node(i, IntervalExpr, node); error_node(node, "Invalid use of an interval expression"); - goto error; + return kind; case_end; case_ast_node(i, Implicit, node) @@ -4318,7 +4384,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint case Token_context: if (c->context.proc_name.len == 0) { error_node(node, "`context` is only allowed within procedures"); - goto error; + return kind; } o->mode = Addressing_Value; @@ -4326,7 +4392,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint break; default: error_node(node, "Illegal implicit name `%.*s`", LIT(i->string)); - goto error; + return kind; } case_end; @@ -4378,7 +4444,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(node, "Invalid procedure literal `%s`", str); gb_string_free(str); check_close_scope(c); - goto error; + return kind; } if (pl->tags != 0) { error_node(node, "A procedure literal cannot have tags"); @@ -4409,22 +4475,22 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint check_expr_with_type_hint(c, &y, te->y, type_hint); } else { error_node(node, "A ternary expression must have an else clause"); - goto error; + return kind; } if (x.type == NULL || x.type == t_invalid || y.type == NULL || y.type == t_invalid) { - goto error; + return kind; } convert_to_typed(c, &x, y.type, 0); if (x.mode == Addressing_Invalid) { - goto error; + return kind; } convert_to_typed(c, &y, x.type, 0); if (y.mode == Addressing_Invalid) { x.mode = Addressing_Invalid; - goto error; + return kind; } @@ -4434,7 +4500,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(node, "Mismatched types in ternary expression, %s vs %s", its, ets); gb_string_free(ets); gb_string_free(its); - goto error; + return kind; } o->type = x.type; @@ -4479,7 +4545,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint if (type == NULL) { error_node(node, "Missing type in compound literal"); - goto error; + return kind; } Type *t = base_type(type); @@ -4773,7 +4839,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint gbString str = type_to_string(type); error_node(node, "Invalid compound literal type `%s`", str); gb_string_free(str); - goto error; + return kind; } break; } @@ -4810,7 +4876,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint Type *t = check_type(c, ce->type); check_expr(c, o, ce->expr); if (o->mode == Addressing_Invalid) { - goto error; + o->expr = node; + return kind; } switch (ce->token.kind) { case Token_cast: @@ -4822,7 +4889,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(o->expr, "Cannot transmute constant expression: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } if (is_type_untyped(o->type)) { @@ -4830,7 +4898,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(o->expr, "Cannot transmute untyped expression: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } i64 srcz = type_size_of(c->allocator, o->type); @@ -4842,7 +4911,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint gb_string_free(type_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } o->type = t; @@ -4854,7 +4924,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(o->expr, "Cannot `union_cast` a constant expression: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } if (is_type_untyped(o->type)) { @@ -4862,7 +4933,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(o->expr, "Cannot `union_cast` an untyped expression: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } bool src_is_ptr = is_type_pointer(o->type); @@ -4879,13 +4951,15 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint gb_string_free(dst_type_str); gb_string_free(src_type_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } if (!is_type_union(src)) { error_node(o->expr, "`union_cast` can only operate on unions"); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } bool ok = false; @@ -4904,7 +4978,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint gb_string_free(dst_type_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } add_type_info_type(c, o->type); @@ -4919,7 +4994,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(o->expr, "Cannot `down_cast` a constant expression: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } if (is_type_untyped(o->type)) { @@ -4927,7 +5003,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(o->expr, "Cannot `down_cast` an untyped expression: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } if (!(is_type_pointer(o->type) && is_type_pointer(t))) { @@ -4935,7 +5012,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(o->expr, "Can only `down_cast` pointers: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } Type *src = type_deref(o->type); @@ -4948,7 +5026,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(o->expr, "Can only `down_cast` pointer from structs or unions: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } if (!(is_type_struct(bdst) || is_type_raw_union(bdst))) { @@ -4956,7 +5035,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(o->expr, "Can only `down_cast` pointer to structs or unions: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } String param_name = check_down_cast_name(dst, src); @@ -4965,7 +5045,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(o->expr, "Illegal `down_cast`: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; - goto error; + o->expr = node; + return kind; } o->mode = Addressing_Value; @@ -4982,11 +5063,13 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint case_ast_node(ue, UnaryExpr, node); check_expr_base(c, o, ue->expr, type_hint); if (o->mode == Addressing_Invalid) { - goto error; + o->expr = node; + return kind; } check_unary_expr(c, o, ue->op, node); if (o->mode == Addressing_Invalid) { - goto error; + o->expr = node; + return kind; } case_end; @@ -4994,7 +5077,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint case_ast_node(be, BinaryExpr, node); check_binary_expr(c, o, node); if (o->mode == Addressing_Invalid) { - goto error; + o->expr = node; + return kind; } case_end; @@ -5008,7 +5092,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint case_ast_node(ie, IndexExpr, node); check_expr(c, o, ie->expr); if (o->mode == Addressing_Invalid) { - goto error; + o->expr = node; + return kind; } Type *t = base_type(type_deref(o->type)); @@ -5020,7 +5105,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint check_expr(c, &key, ie->index); check_assignment(c, &key, t->Map.key, str_lit("map index")); if (key.mode == Addressing_Invalid) { - goto error; + o->mode = Addressing_Invalid; + o->expr = node; + return kind; } o->mode = Addressing_MapIndex; o->type = t->Map.value; @@ -5050,14 +5137,18 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(o->expr, "Cannot index `%s`", str); } gb_string_free(str); - goto error; + o->mode = Addressing_Invalid; + o->expr = node; + return kind; } if (ie->index == NULL) { gbString str = expr_to_string(o->expr); error_node(o->expr, "Missing index for `%s`", str); gb_string_free(str); - goto error; + o->mode = Addressing_Invalid; + o->expr = node; + return kind; } i64 index = 0; @@ -5070,7 +5161,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint case_ast_node(se, SliceExpr, node); check_expr(c, o, se->expr); if (o->mode == Addressing_Invalid) { - goto error; + o->mode = Addressing_Invalid; + o->expr = node; + return kind; } bool valid = false; @@ -5081,7 +5174,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint if (is_type_string(t)) { if (se->index3) { error_node(node, "3-index slice on a string in not needed"); - goto error; + o->mode = Addressing_Invalid; + o->expr = node; + return kind; } valid = true; if (o->mode == Addressing_Constant) { @@ -5098,7 +5193,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint gbString str = expr_to_string(node); error_node(node, "Cannot slice array `%s`, value is not addressable", str); gb_string_free(str); - goto error; + o->mode = Addressing_Invalid; + o->expr = node; + return kind; } o->type = make_type_slice(c->allocator, t->Array.elem); break; @@ -5116,7 +5213,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint gbString str = expr_to_string(o->expr); error_node(o->expr, "Cannot slice `%s`", str); gb_string_free(str); - goto error; + o->mode = Addressing_Invalid; + o->expr = node; + return kind; } if (o->mode != Addressing_Immutable) { @@ -5125,7 +5224,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint if (se->index3 && (se->high == NULL || se->max == NULL)) { error(se->close, "2nd and 3rd indices are required in a 3-index slice"); - goto error; + o->mode = Addressing_Invalid; + o->expr = node; + return kind; } i64 indices[2] = {0}; @@ -5171,7 +5272,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint case_ast_node(de, DerefExpr, node); check_expr_or_type(c, o, de->expr); if (o->mode == Addressing_Invalid) { - goto error; + o->mode = Addressing_Invalid; + o->expr = node; + return kind; } else { Type *t = base_type(o->type); if (t->kind == Type_Pointer) { @@ -5183,7 +5286,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint gbString str = expr_to_string(o->expr); error_node(o->expr, "Cannot dereference `%s`", str); gb_string_free(str); - goto error; + o->mode = Addressing_Invalid; + o->expr = node; + return kind; } } case_end; @@ -5207,15 +5312,10 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint kind = Expr_Expr; o->expr = node; return kind; - -error: - o->mode = Addressing_Invalid; - o->expr = node; - return kind; } ExprKind check_expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint) { - ExprKind kind = check__expr_base(c, o, node, type_hint); + ExprKind kind = check_expr_base_internal(c, o, node, type_hint); Type *type = NULL; ExactValue value = {ExactValue_Invalid}; switch (o->mode) { diff --git a/src/check_stmt.c b/src/check_stmt.c index 2eabaf798..6aec1beee 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -689,8 +689,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { case_ast_node(rs, RangeStmt, node); u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed; - check_open_scope(c, node); + check_open_scope(c, node); check_label(c, rs->label); Type *val = NULL; @@ -885,6 +885,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { mod_flags |= Stmt_BreakAllowed; check_open_scope(c, node); + check_label(c, ms->label); // TODO(bill): What should the label's "scope" be? if (ms->init != NULL) { check_stmt(c, ms->init, 0); @@ -897,8 +898,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { x.type = t_bool; x.value = exact_value_bool(true); - Token token = {0}; - token.pos = ast_node_token(ms->body).pos; + Token token = {0}; + token.pos = ast_node_token(ms->body).pos; token.string = str_lit("true"); x.expr = ast_ident(c->curr_ast_file, token); } @@ -1025,6 +1026,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { mod_flags |= Stmt_BreakAllowed; check_open_scope(c, node); + check_label(c, ms->label); // TODO(bill): What should the label's "scope" be? MatchTypeKind match_type_kind = MatchType_Invalid; @@ -1051,8 +1053,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { match_type_kind = check_valid_type_match_type(x.type); if (check_valid_type_match_type(x.type) == MatchType_Invalid) { gbString str = type_to_string(x.type); - error_node(x.expr, - "Invalid type for this type match expression, got `%s`", str); + error_node(x.expr, "Invalid type for this type match expression, got `%s`", str); gb_string_free(str); break; } @@ -1387,7 +1388,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { case_ast_node(vd, ValueDecl, node); GB_ASSERT(!c->context.scope->is_file); - if (vd->is_var) { + if (!vd->is_var) { + // NOTE(bill): Handled elsewhere + } else { Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count); isize entity_count = 0; @@ -1497,9 +1500,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { } } } - - } else { - // NOTE(bill): Handled elsewhere } case_end; } @@ -1659,6 +1659,39 @@ irValue *ir_emit_ptr_offset(irProcedure *proc, irValue *ptr, irValue *offset) { return ir_emit(proc, ir_instr_ptr_offset(proc, ptr, offset)); } +irValue *ir_emit_unary_arith(irProcedure *proc, TokenKind op, irValue *x, Type *type) { + switch (op) { + case Token_Add: + return x; + case Token_Not: // Boolean not + case Token_Xor: // Bitwise not + case Token_Sub: // Bitwise Not + break; + case Token_Pointer: + GB_PANIC("This should be handled elsewhere"); + break; + } + if (is_type_vector(ir_type(x))) { + ir_emit_comment(proc, str_lit("vector.arith.begin")); + // IMPORTANT TODO(bill): This is very wasteful with regards to stack memory + Type *tl = base_type(ir_type(x)); + irValue *val = ir_address_from_load_or_generate_local(proc, x); + GB_ASSERT(is_type_vector(type)); + Type *elem_type = base_type(type)->Vector.elem; + + irValue *res = ir_add_local_generated(proc, type); + for (i32 i = 0; i < tl->Vector.count; i++) { + irValue *e = ir_emit_load(proc, ir_emit_array_epi(proc, val, i)); + irValue *z = ir_emit_unary_arith(proc, op, e, elem_type); + ir_emit_store(proc, ir_emit_array_epi(proc, res, i), z); + } + ir_emit_comment(proc, str_lit("vector.arith.end")); + return ir_emit_load(proc, res); + + } + return ir_emit(proc, ir_instr_unary_op(proc, op, x, type)); +} + irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *right, Type *type) { Type *t_left = ir_type(left); Type *t_right = ir_type(right); @@ -3143,17 +3176,8 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { switch (ue->op.kind) { case Token_Pointer: return ir_emit_ptr_offset(proc, ir_build_addr(proc, ue->expr).addr, v_zero); // Make a copy of the pointer - - // case Token_Maybe: - // return ir_emit_conv(proc, ir_build_expr(proc, ue->expr), type_of_expr(proc->module->info, expr)); - - case Token_Add: - return ir_build_expr(proc, ue->expr); - - case Token_Not: // Boolean not - case Token_Xor: // Bitwise not - case Token_Sub: // Bitwise not - return ir_emit(proc, ir_instr_unary_op(proc, ue->op.kind, ir_build_expr(proc, ue->expr), tv->type)); + default: + return ir_emit_unary_arith(proc, ue->op.kind, ir_build_expr(proc, ue->expr), tv->type); } case_end; diff --git a/src/ir_print.c b/src/ir_print.c index 973b3d6a0..beae020db 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -364,7 +364,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * } } break; case ExactValue_Float: { - GB_ASSERT(is_type_float(type)); + GB_ASSERT_MSG(is_type_float(type), "%s", type_to_string(type)); type = base_type(type); u64 u = *cast(u64*)&value.value_float; switch (type->Basic.kind) { @@ -942,7 +942,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { switch (uo->op) { case Token_Sub: if (is_type_float(elem_type)) { - ir_print_exact_value(f, m, exact_value_float(0), type); + ir_print_exact_value(f, m, exact_value_float(0), elem_type); } else { ir_fprintf(f, "0"); } diff --git a/src/main.c b/src/main.c index 242af444d..ccc2b4c3b 100644 --- a/src/main.c +++ b/src/main.c @@ -282,6 +282,12 @@ int main(int argc, char **argv) { "-mem2reg " "-memcpyopt " "-die " + #if defined(GB_SYSTEM_OSX) + // This sets a requirement of Mountain Lion and up, but the compiler doesn't work without this limit. + // NOTE: If you change this (although this minimum is as low as you can go with Odin working) + // make sure to also change the `macosx_version_min` param passed to `llc` + "-mtriple=x86_64-apple-macosx10.8 " + #endif // "-dse " // "-dce " // "-S " @@ -382,11 +388,12 @@ int main(int argc, char **argv) { // This allows you to specify '-f' in a #foreign_system_library, // without having to implement any new syntax specifically for MacOS. #if defined(GB_SYSTEM_OSX) + isize len; if(lib.len > 2 && lib.text[0] == '-' && lib.text[1] == 'f') { - isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), + len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), " -framework %.*s ", (int)(lib.len) - 2, lib.text + 2); } else { - isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), + len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), " -l%.*s ", LIT(lib)); } #else @@ -433,7 +440,10 @@ int main(int argc, char **argv) { " %s " #if defined(GB_SYSTEM_OSX) // This sets a requirement of Mountain Lion and up, but the compiler doesn't work without this limit. + // NOTE: If you change this (although this minimum is as low as you can go with Odin working) + // make sure to also change the `mtriple` param passed to `opt` " -macosx_version_min 10.8.0 " + // This points the linker to where the entry point is " -e _main " #endif , linker, LIT(output), LIT(output), output_ext, diff --git a/src/parser.c b/src/parser.c index a41fc5c06..fbedb3855 100644 --- a/src/parser.c +++ b/src/parser.c @@ -3366,7 +3366,7 @@ AstNode *parse_stmt(AstFile *f) { _SET_LABEL(MatchStmt, label); _SET_LABEL(TypeMatchStmt, label); default: - syntax_error(token, "#label may only be applied to a loop"); + syntax_error(token, "#label cannot only be applied to a loop or match statement"); break; } #undef _SET_LABEL diff --git a/src/types.c b/src/types.c index 534f00f15..eee10dd45 100644 --- a/src/types.c +++ b/src/types.c @@ -1035,24 +1035,13 @@ typedef enum ProcTypeOverloadKind { } ProcTypeOverloadKind; -#include "stdio.h" -bool has_encountered_null_proc_type = false; ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) { - if(x == NULL && y == NULL) { - if(!has_encountered_null_proc_type) { - printf("The compiler has encountered a NULL proc type.\n" - " This is probably not an error in your code, and\n" - " the compile is probably still successful.\n" - " This does mean that (at least once), there could be a\n" - " bad procedure overload in your program, and Odin wouldn't catch it.\n" - " As far as I know, this is a porting bug, and doesn't occur on mainline Odin.\n" - " Be careful, and sorry about this bug :(\n"); - has_encountered_null_proc_type = true; - } - return ProcOverload_ParamCount; - } - if (!is_type_proc(x)) return ProcOverload_NotProcedure; - if (!is_type_proc(y)) return ProcOverload_NotProcedure; + if (x == NULL && y == NULL) return ProcOverload_NotProcedure; + if (x == NULL && y != NULL) return ProcOverload_NotProcedure; + if (x != NULL && y == NULL) return ProcOverload_NotProcedure; + if (!is_type_proc(x)) return ProcOverload_NotProcedure; + if (!is_type_proc(y)) return ProcOverload_NotProcedure; + TypeProc px = base_type(x)->Proc; TypeProc py = base_type(y)->Proc; |