diff options
| author | gingerBill <bill@gingerbill.org> | 2019-10-13 12:38:23 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2019-10-13 12:38:23 +0100 |
| commit | 2a6d9e8927ad1eb1e5f3a79fc9ed068a02cbfdfc (patch) | |
| tree | 1e771afe3e07425e536b3519818306a6d4e022ff /src | |
| parent | fa81061db0d08a508ab8bbedfcf7bf5ad1e27daa (diff) | |
`#panic`; Minor change to demo.odin; Fix `#assert` bug at file scope
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.cpp | 22 | ||||
| -rw-r--r-- | src/check_type.cpp | 37 | ||||
| -rw-r--r-- | src/checker.cpp | 13 | ||||
| -rw-r--r-- | src/checker.hpp | 1 | ||||
| -rw-r--r-- | src/main.cpp | 14 | ||||
| -rw-r--r-- | src/parser.cpp | 38 | ||||
| -rw-r--r-- | src/types.cpp | 66 |
7 files changed, 106 insertions, 85 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 6a0d8221f..7c418c4f0 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3071,7 +3071,6 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ } if (selector->kind != Ast_Ident) { - // if (selector->kind != Ast_Ident) { error(selector, "Illegal selector kind: '%.*s'", LIT(ast_strings[selector->kind])); operand->mode = Addressing_Invalid; operand->expr = node; @@ -3544,6 +3543,25 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 operand->type = t_untyped_bool; operand->mode = Addressing_Constant; + } else if (name == "panic") { + if (ce->args.count != 1) { + error(call, "'#panic' expects 1 argument, got %td", ce->args.count); + return false; + } + if (!is_type_string(operand->type) && operand->mode != Addressing_Constant) { + gbString str = expr_to_string(ce->args[0]); + error(call, "'%s' is not a constant string", str); + gb_string_free(str); + return false; + } + error(call, "Compile time panic: %.*s", LIT(operand->value.value_string)); + if (c->proc_name != "") { + gbString str = type_to_string(c->curr_proc_sig); + error_line("\tCalled within '%.*s' :: %s\n", LIT(c->proc_name), str); + gb_string_free(str); + } + operand->type = t_invalid; + operand->mode = Addressing_NoValue; } else if (name == "defined") { if (ce->args.count != 1) { error(call, "'#defined' expects 1 argument, got %td", ce->args.count); @@ -6349,7 +6367,7 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call) { ce->proc->kind == Ast_BasicDirective) { ast_node(bd, BasicDirective, ce->proc); String name = bd->name; - if (name == "location" || name == "assert" || name == "defined" || name == "load") { + if (name == "location" || name == "assert" || name == "panic" || name == "defined" || name == "load") { operand->mode = Addressing_Builtin; operand->builtin_id = BuiltinProc_DIRECTIVE; operand->expr = ce->proc; diff --git a/src/check_type.cpp b/src/check_type.cpp index 329755ea5..4d107a9ac 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1847,7 +1847,7 @@ Array<Type *> systemv_distribute_struct_fields(Type *t) { } auto distributed = array_make<Type *>(heap_allocator(), 0, distributed_cap); - + i64 sz = type_size_of(bt); switch (bt->kind) { case Type_Basic: switch (bt->Basic.kind){ @@ -1925,9 +1925,9 @@ Array<Type *> systemv_distribute_struct_fields(Type *t) { array_add(&distributed, t_int); break; + case Type_Union: case Type_DynamicArray: case Type_Map: - case Type_Union: case Type_BitField: // TODO(bill): Ignore? // NOTE(bill, 2019-10-10): Odin specific, don't worry about C calling convention yet goto DEFAULT; @@ -1937,7 +1937,7 @@ Array<Type *> systemv_distribute_struct_fields(Type *t) { case Type_SimdVector: // TODO(bill): Is this correct logic? default: DEFAULT:; - if (type_size_of(bt) > 0) { + if (sz > 0) { array_add(&distributed, bt); } break; @@ -1959,13 +1959,22 @@ Type *handle_single_distributed_type_parameter(Array<Type *> const &types, bool if (types.count == 1) { if (offset) *offset = 1; + + i64 sz = type_size_of(types[0]); + if (is_type_float(types[0])) { return types[0]; - } else if (type_size_of(types[0]) == 8) { + } + switch (sz) { + case 0: + GB_PANIC("Zero sized type found!"); + case 1: + case 2: + case 4: + case 8: return types[0]; - } else { - return t_u64; } + return t_u64; } else if (types.count >= 2) { if (types[0] == t_f32 && types[1] == t_f32) { if (offset) *offset = 2; @@ -2050,7 +2059,7 @@ Type *handle_struct_system_v_amd64_abi_type(Type *t) { Type *final_type = nullptr; if (field_types.count == 0) { - return t; + final_type = t; } else if (field_types.count == 1) { final_type = field_types[0]; } else { @@ -2072,8 +2081,22 @@ Type *handle_struct_system_v_amd64_abi_type(Type *t) { variables[1] = alloc_entity_param(nullptr, empty_token, two_types[1], false, false); final_type = alloc_type_tuple(); final_type->Tuple.variables = variables; + if (t->kind == Type_Struct) { + // NOTE(bill): Make this packed + final_type->Tuple.is_packed = t->Struct.is_packed; + } } } + + + GB_ASSERT(final_type != nullptr); + i64 ftsz = type_size_of(final_type); + i64 otsz = type_size_of(original_type); + if (ftsz != otsz) { + // TODO(bill): Handle this case which will be caused by #packed most likely + GB_PANIC("Incorrectly handled case for handle_struct_system_v_amd64_abi_type, %lld vs %lld", ftsz, otsz); + } + return final_type; } } diff --git a/src/checker.cpp b/src/checker.cpp index f30273439..8ce9d8ec2 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3367,8 +3367,9 @@ bool collect_file_decls(CheckerContext *ctx, Array<Ast *> const &decls) { if (es->expr->kind == Ast_CallExpr) { ast_node(ce, CallExpr, es->expr); if (ce->proc->kind == Ast_BasicDirective) { - Operand o = {}; - check_expr(ctx, &o, es->expr); + if (ctx->collect_delayed_decls) { + array_add(&ctx->scope->delayed_directives, es->expr); + } } } case_end; @@ -3525,12 +3526,18 @@ void check_import_entities(Checker *c) { for_array(i, pkg->files) { AstFile *f = pkg->files[i]; CheckerContext ctx = c->init_ctx; - add_curr_ast_file(&ctx, f); + for_array(j, f->scope->delayed_imports) { Ast *decl = f->scope->delayed_imports[j]; check_add_import_decl(&ctx, decl); } + } + for_array(i, pkg->files) { + AstFile *f = pkg->files[i]; + CheckerContext ctx = c->init_ctx; + add_curr_ast_file(&ctx, f); + for_array(j, f->scope->delayed_directives) { Ast *expr = f->scope->delayed_directives[j]; Operand o = {}; diff --git a/src/checker.hpp b/src/checker.hpp index 58cb01a82..f86acce5c 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -222,6 +222,7 @@ struct ForeignContext { typedef Array<Entity *> CheckerTypePath; typedef Array<Type *> CheckerPolyPath; + // CheckerInfo stores all the symbol information for a type-checked program struct CheckerInfo { Map<ExprInfo> untyped; // Key: Ast * | Expression -> ExprInfo diff --git a/src/main.cpp b/src/main.cpp index b294e7f96..78859e04e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -445,7 +445,7 @@ bool parse_build_flags(Array<String> args) { path = substring(path, 0, string_extension_position(path)); } #endif - build_context.out_filepath = path; + build_context.out_filepath = path_to_full_path(heap_allocator(), path); } else { gb_printf_err("Invalid -out path, got %.*s\n", LIT(path)); bad_flags = true; @@ -624,7 +624,7 @@ bool parse_build_flags(Array<String> args) { break; } - if (str == "dll") { + if (str == "dll" || str == "shared") { build_context.is_dll = true; } else if (str == "exe") { build_context.is_dll = false; @@ -1112,7 +1112,7 @@ int main(int arg_count, char **arg_ptr) { if (0) { #ifdef GB_SYSTEM_UNIX } else if (selected_target_metrics->metrics == &target_essence_amd64) { - system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s", + system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s", LIT(output_base), LIT(output_base), LIT(build_context.link_flags)); #endif } else { @@ -1239,10 +1239,7 @@ int main(int arg_count, char **arg_ptr) { // 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) - if (lib.len > 2 && lib[0] == '-' && lib[1] == 'f') { - // framework thingie - lib_str = gb_string_append_fmt(lib_str, " -framework %.*s ", (int)(lib.len) - 2, lib.text + 2); - } else if (string_ends_with(lib, str_lit(".framework"))) { + if (string_ends_with(lib, str_lit(".framework"))) { // framework thingie String lib_name = lib; lib_name = remove_extension_from_path(lib_name); @@ -1251,8 +1248,7 @@ int main(int arg_count, char **arg_ptr) { // static libs, absolute full path relative to the file in which the lib was imported from lib_str = gb_string_append_fmt(lib_str, " %.*s ", LIT(lib)); } else if (string_ends_with(lib, str_lit(".dylib"))) { - // dynamic lib, relative path to executable - // lib_str = gb_string_append_fmt(lib_str, " -l:%s/%.*s ", cwd, LIT(lib)); + // dynamic lib lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib)); } else { // dynamic or static system lib, just link regularly searching system library paths diff --git a/src/parser.cpp b/src/parser.cpp index 025a181ba..f69efc0ce 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3970,34 +3970,6 @@ Ast *parse_stmt(AstFile *f) { return s; } - // case Token_static: { - // CommentGroup *docs = f->lead_comment; - // Token token = expect_token(f, Token_static); - - // Ast *decl = nullptr; - // Array<Ast *> list = parse_lhs_expr_list(f); - // if (list.count == 0) { - // syntax_error(token, "Illegal use of 'static' statement"); - // expect_semicolon(f, nullptr); - // return ast_bad_stmt(f, token, f->curr_token); - // } - - // expect_token_after(f, Token_Colon, "identifier list"); - // decl = parse_value_decl(f, list, docs); - - // if (decl != nullptr && decl->kind == Ast_ValueDecl) { - // if (decl->ValueDecl.is_mutable) { - // decl->ValueDecl.is_static = true; - // } else { - // error(token, "'static' may only be currently used with variable declaration"); - // } - // return decl; - // } - - // syntax_error(token, "Illegal use of 'static' statement"); - // return ast_bad_stmt(f, token, f->curr_token); - // } break; - case Token_using: { CommentGroup *docs = f->lead_comment; Token token = expect_token(f, Token_using); @@ -4071,12 +4043,10 @@ Ast *parse_stmt(AstFile *f) { } else if (tag == "assert") { Ast *t = ast_basic_directive(f, hash_token, tag); return ast_expr_stmt(f, parse_call_expr(f, t)); - } /* else if (name.string == "no_deferred") { - s = parse_stmt(f); - s->stmt_state_flags |= StmtStateFlag_no_deferred; - } */ - - if (tag == "include") { + } else if (tag == "panic") { + Ast *t = ast_basic_directive(f, hash_token, tag); + return ast_expr_stmt(f, parse_call_expr(f, t)); + } else if (tag == "include") { syntax_error(token, "#include is not a valid import declaration kind. Did you mean 'import'?"); s = ast_bad_stmt(f, token, f->curr_token); } else { diff --git a/src/types.cpp b/src/types.cpp index d8a579510..8ad352f62 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -113,21 +113,22 @@ struct BasicType { struct TypeStruct { Array<Entity *> fields; Array<String> tags; - Ast *node; - Scope * scope; - - Array<i64> offsets; - bool are_offsets_set; - bool are_offsets_being_processed; - bool is_packed; - bool is_raw_union; - bool is_polymorphic; - bool is_poly_specialized; + Array<i64> offsets; + Ast * node; + Scope * scope; + Type * polymorphic_params; // Type_Tuple Type * polymorphic_parent; - i64 custom_align; // NOTE(bill): Only used in structs at the moment + i64 custom_align; Entity * names; + + bool are_offsets_set; + bool are_offsets_being_processed; + bool is_packed; + bool is_raw_union; + bool is_polymorphic; + bool is_poly_specialized; }; struct TypeUnion { @@ -137,12 +138,11 @@ struct TypeUnion { i64 variant_block_size; i64 custom_align; i64 tag_size; + Type * polymorphic_params; // Type_Tuple + Type * polymorphic_parent; bool no_nil; - - bool is_polymorphic; - bool is_poly_specialized; - Type * polymorphic_params; // Type_Tuple - Type * polymorphic_parent; + bool is_polymorphic; + bool is_poly_specialized; }; #define TYPE_KINDS \ @@ -190,7 +190,9 @@ struct TypeUnion { TYPE_KIND(Tuple, struct { \ Array<Entity *> variables; /* Entity_Variable */ \ Array<i64> offsets; \ + bool are_offsets_being_processed; \ bool are_offsets_set; \ + bool is_packed; \ }) \ TYPE_KIND(Proc, struct { \ Ast *node; \ @@ -201,9 +203,8 @@ struct TypeUnion { i32 result_count; \ Array<Type *> abi_compat_params; \ Type * abi_compat_result_type; \ - bool return_by_pointer; \ - bool variadic; \ i32 variadic_index; \ + bool variadic; \ bool require_results; \ bool c_vararg; \ bool is_polymorphic; \ @@ -211,6 +212,7 @@ struct TypeUnion { bool has_proc_default_values; \ bool has_named_results; \ bool diverging; /* no return */ \ + bool return_by_pointer; \ u64 tags; \ isize specialization_count; \ ProcCallingConvention calling_convention; \ @@ -1782,7 +1784,8 @@ bool are_types_identical(Type *x, Type *y) { case Type_Tuple: if (y->kind == Type_Tuple) { - if (x->Tuple.variables.count == y->Tuple.variables.count) { + if (x->Tuple.variables.count == y->Tuple.variables.count && + x->Tuple.is_packed == y->Tuple.is_packed) { for_array(i, x->Tuple.variables) { Entity *xe = x->Tuple.variables[i]; Entity *ye = y->Tuple.variables[i]; @@ -2231,19 +2234,22 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty if (type->Array.count <= 4) { // HACK(bill): Memory leak switch (type->Array.count) { - #define _ARRAY_FIELD_CASE(_length, _name) \ - case (_length): \ - if (field_name == _name) { \ + #define _ARRAY_FIELD_CASE_IF(_length, _name) \ + if (field_name == (_name)) { \ selection_add_index(&sel, (_length)-1); \ sel.entity = alloc_entity_array_elem(nullptr, make_token_ident(str_lit(_name)), type->Array.elem, (_length)-1); \ return sel; \ - } \ + } + #define _ARRAY_FIELD_CASE(_length, _name0, _name1) \ + case (_length): \ + _ARRAY_FIELD_CASE_IF(_length, _name0); \ + _ARRAY_FIELD_CASE_IF(_length, _name1); \ /*fallthrough*/ - _ARRAY_FIELD_CASE(4, "w"); - _ARRAY_FIELD_CASE(3, "z"); - _ARRAY_FIELD_CASE(2, "y"); - _ARRAY_FIELD_CASE(1, "x"); + _ARRAY_FIELD_CASE(4, "w", "a"); + _ARRAY_FIELD_CASE(3, "z", "b"); + _ARRAY_FIELD_CASE(2, "y", "g"); + _ARRAY_FIELD_CASE(1, "x", "r"); default: break; #undef _ARRAY_FIELD_CASE @@ -2590,9 +2596,9 @@ bool type_set_offsets(Type *t) { } } else if (is_type_tuple(t)) { if (!t->Tuple.are_offsets_set) { - t->Struct.are_offsets_being_processed = true; - t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, false, false); - t->Struct.are_offsets_being_processed = false; + t->Tuple.are_offsets_being_processed = true; + t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, t->Tuple.is_packed, false); + t->Tuple.are_offsets_being_processed = false; t->Tuple.are_offsets_set = true; return true; } |