From 18a9fa735503e96d69efd968c542e490abe69be0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 12 May 2018 10:27:55 +0100 Subject: [PATCH] Improve minimal dependency system --- src/check_expr.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++--- src/check_stmt.cpp | 1 + src/check_type.cpp | 4 +++ src/checker.cpp | 38 +++++++++++++++++--- src/ir.cpp | 71 +++++++++++++++++-------------------- src/ir_print.cpp | 8 ++++- src/parser.cpp | 1 - src/tokenizer.cpp | 1 - 8 files changed, 161 insertions(+), 51 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 139b376f2..8bdb23658 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1561,9 +1561,38 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) { } else { x->mode = Addressing_Value; - update_expr_type(c, x->expr, default_type(x->type), true); update_expr_type(c, y->expr, default_type(y->type), true); + + i64 size = 0; + if (!is_type_untyped(x->type)) size = gb_max(size, type_size_of(x->type)); + if (!is_type_untyped(y->type)) size = gb_max(size, type_size_of(y->type)); + + if (is_type_string(x->type) || is_type_string(y->type)) { + switch (op) { + case Token_CmpEq: add_preload_dependency(c, "__string_eq"); break; + case Token_NotEq: add_preload_dependency(c, "__string_ne"); break; + case Token_Lt: add_preload_dependency(c, "__string_lt"); break; + case Token_Gt: add_preload_dependency(c, "__string_gt"); break; + case Token_LtEq: add_preload_dependency(c, "__string_le"); break; + case Token_GtEq: add_preload_dependency(c, "__string_gt"); break; + } + } else if (is_type_complex(x->type) || is_type_complex(y->type)) { + switch (op) { + case Token_CmpEq: + switch (8*size) { + case 64: add_preload_dependency(c, "__complex64_eq"); break; + case 128: add_preload_dependency(c, "__complex128_eq"); break; + } + break; + case Token_NotEq: + switch (8*size) { + case 64: add_preload_dependency(c, "__complex64_ne"); break; + case 128: add_preload_dependency(c, "__complex128_ne"); break; + } + break; + } + } } x->type = t_untyped_bool; @@ -1820,6 +1849,9 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) { } // cstring -> string if (src == t_cstring && dst == t_string) { + if (operand->mode != Addressing_Constant) { + add_preload_dependency(c, "__cstring_to_string"); + } return true; } // cstring -> ^u8 @@ -2878,6 +2910,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id operand->type = t_source_code_location; operand->mode = Addressing_Value; + add_preload_dependency(c, "make_source_code_location"); } else if (name == "assert") { if (ce->args.count != 1) { error(call, "'#assert' expects at 1 argument, got %td", ce->args.count); @@ -2920,6 +2953,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id type = t_untyped_integer; } else { mode = Addressing_Value; + if (is_type_cstring(op_type)) { + add_preload_dependency(c, "__cstring_len"); + } } } else if (is_type_array(op_type)) { Type *at = core_type(op_type); @@ -3021,12 +3057,15 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (is_type_slice(type)) { min_args = 2; max_args = 2; + add_preload_dependency(c, "alloc"); } else if (is_type_map(type)) { min_args = 1; max_args = 2; + add_preload_dependency(c, "__dynamic_map_reserve"); } else if (is_type_dynamic_array(type)) { min_args = 1; max_args = 3; + add_preload_dependency(c, "__dynamic_array_make"); } else { gbString str = type_to_string(type); error(call, "Cannot 'make' %s; type must be a slice, map, or dynamic array", str); @@ -3723,6 +3762,13 @@ break; gb_string_free(type_a); return false; } + + { + Type *bt = base_type(a.type); + if (bt == t_f32) add_preload_dependency(c, "__min_f32"); + if (bt == t_f64) add_preload_dependency(c, "__min_f64"); + } + } @@ -3793,6 +3839,12 @@ break; gb_string_free(type_a); return false; } + + { + Type *bt = base_type(a.type); + if (bt == t_f32) add_preload_dependency(c, "__max_f32"); + if (bt == t_f64) add_preload_dependency(c, "__max_f64"); + } } @@ -3829,6 +3881,14 @@ break; } } else { operand->mode = Addressing_Value; + + { + Type *bt = base_type(operand->type); + if (bt == t_f32) add_preload_dependency(c, "__abs_f32"); + if (bt == t_f64) add_preload_dependency(c, "__abs_f64"); + if (bt == t_complex64) add_preload_dependency(c, "__abs_complex64"); + if (bt == t_complex128) add_preload_dependency(c, "__abs_complex128"); + } } if (is_type_complex(operand->type)) { @@ -3924,6 +3984,18 @@ break; gb_string_free(type_x); return false; } + + { + Type *bt = base_type(x.type); + if (bt == t_f32) { + add_preload_dependency(c, "__min_f32"); + add_preload_dependency(c, "__max_f32"); + } + if (bt == t_f64) { + add_preload_dependency(c, "__min_f64"); + add_preload_dependency(c, "__max_f64"); + } + } } break; @@ -5149,10 +5221,6 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t o->mode = Addressing_Builtin; o->builtin_id = BuiltinProc_type_of; break; - case Token_type_info_of: - o->mode = Addressing_Builtin; - o->builtin_id = BuiltinProc_type_info_of; - break; default: error(node, "Illegal implicit name '%.*s'", LIT(i->string)); @@ -5534,6 +5602,9 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t elem_type = t->DynamicArray.elem; context_name = str_lit("dynamic array literal"); is_constant = false; + + add_preload_dependency(c, "__dynamic_array_reserve"); + add_preload_dependency(c, "__dynamic_array_append"); } else { GB_PANIC("unreachable"); } @@ -5692,6 +5763,8 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t } } + add_preload_dependency(c, "__dynamic_map_reserve"); + add_preload_dependency(c, "__dynamic_map_set"); break; } @@ -5813,6 +5886,8 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t o->expr = node; return kind; } + + add_preload_dependency(c, "__type_assertion_check"); case_end; case_ast_node(tc, TypeCast, node); @@ -5911,6 +5986,9 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t o->mode = Addressing_MapIndex; o->type = t->Map.value; o->expr = node; + + add_preload_dependency(c, "__dynamic_map_get"); + add_preload_dependency(c, "__dynamic_map_set"); return Expr_Expr; } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 80e5baf37..13b95ddad 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1411,6 +1411,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (is_type_string(t)) { val0 = t_rune; val1 = t_int; + add_preload_dependency(c, "__string_decode_rune"); } break; case Type_Array: diff --git a/src/check_type.cpp b/src/check_type.cpp index c3ee0a51a..35953d7bb 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1827,6 +1827,10 @@ void check_map_type(Checker *c, Type *type, AstNode *node) { type->Map.key = key; type->Map.value = value; + if (is_type_string(key)) { + add_preload_dependency(c, "__default_hash_string"); + } + init_preload(c); init_map_internal_types(type); diff --git a/src/checker.cpp b/src/checker.cpp index 70ad8e4b6..cd6239582 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -484,6 +484,13 @@ void add_dependency(DeclInfo *d, Entity *e) { ptr_set_add(&d->deps, e); } +void add_preload_dependency(Checker *c, char *name) { + String n = make_string_c(name); + Entity *e = scope_lookup_entity(c->global_scope, n); + GB_ASSERT(e != nullptr); + ptr_set_add(&c->context.decl->deps, e); +} + void add_declaration_dependency(Checker *c, Entity *e) { if (e == nullptr) { return; @@ -1177,17 +1184,38 @@ void add_dependency_to_map(PtrSet *map, CheckerInfo *info, Entity *ent } } -PtrSet generate_minimum_dependency_set(CheckerInfo *info, Entity *start) { +PtrSet generate_minimum_dependency_set(Checker *c, Entity *start) { + CheckerInfo *info = &c->info; PtrSet map = {}; // Key: Entity * ptr_set_init(&map, heap_allocator()); + String required_entities[] = { + str_lit("__mem_zero"), + str_lit("__init_context"), + str_lit("default_allocator"), + str_lit("make_source_code_location"), + + str_lit("__bounds_check_error"), + str_lit("__slice_expr_error"), + str_lit("__dynamic_array_expr_error"), + + str_lit("__args__"), + str_lit("__type_table"), + }; + for (isize i = 0; i < gb_count_of(required_entities); i++) { + add_dependency_to_map(&map, info, scope_lookup_entity(c->global_scope, required_entities[i])); + } + for_array(i, info->definitions) { Entity *e = info->definitions[i]; // if (e->scope->is_global && !is_type_poly_proc(e->type)) { // TODO(bill): is the check enough? if (e->scope->is_global) { // TODO(bill): is the check enough? - if (e->type == nullptr || !is_type_poly_proc(e->type)) { - // NOTE(bill): Require runtime stuff - add_dependency_to_map(&map, info, e); + if (e->type == nullptr || !is_type_poly_proc(e->type)) { + if (e->kind == Entity_TypeName) { + add_dependency_to_map(&map, info, e); + } else { + // add_dependency_to_map(&map, info, e); + } } } else if (e->kind == Entity_Procedure && e->Procedure.is_export) { add_dependency_to_map(&map, info, e); @@ -3115,7 +3143,7 @@ void check_parsed_files(Checker *c) { } TIME_SECTION("generate minimum dependency set"); - c->info.minimum_dependency_set = generate_minimum_dependency_set(&c->info, c->info.entry_point); + c->info.minimum_dependency_set = generate_minimum_dependency_set(c, c->info.entry_point); TIME_SECTION("calculate global init order"); diff --git a/src/ir.cpp b/src/ir.cpp index 9ed06a617..18e7eed6a 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -3149,39 +3149,39 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) { gbAllocator a = proc->module->allocator; i64 sz = type_size_of(src); i64 dz = type_size_of(dst); - if (sz == 2) { - switch (dz) { - case 2: return value; - case 4: { - auto args = array_make(proc->module->allocator, 1); - args[0] = value; - return ir_emit_global_call(proc, "__gnu_h2f_ieee", args); - break; - } - case 8: { - auto args = array_make(proc->module->allocator, 1); - args[0] = value; - return ir_emit_global_call(proc, "__f16_to_f64", args); - break; - } - } - } else if (dz == 2) { - switch (sz) { - case 2: return value; - case 4: { - auto args = array_make(proc->module->allocator, 1); - args[0] = value; - return ir_emit_global_call(proc, "__gnu_f2h_ieee", args); - break; - } - case 8: { - auto args = array_make(proc->module->allocator, 1); - args[0] = value; - return ir_emit_global_call(proc, "__truncdfhf2", args); - break; - } - } - } + // if (sz == 2) { + // switch (dz) { + // case 2: return value; + // case 4: { + // auto args = array_make(proc->module->allocator, 1); + // args[0] = value; + // return ir_emit_global_call(proc, "__gnu_h2f_ieee", args); + // break; + // } + // case 8: { + // auto args = array_make(proc->module->allocator, 1); + // args[0] = value; + // return ir_emit_global_call(proc, "__f16_to_f64", args); + // break; + // } + // } + // } else if (dz == 2) { + // switch (sz) { + // case 2: return value; + // case 4: { + // auto args = array_make(proc->module->allocator, 1); + // args[0] = value; + // return ir_emit_global_call(proc, "__gnu_f2h_ieee", args); + // break; + // } + // case 8: { + // auto args = array_make(proc->module->allocator, 1); + // args[0] = value; + // return ir_emit_global_call(proc, "__truncdfhf2", args); + // break; + // } + // } + // } irConvKind kind = irConv_fptrunc; if (dz >= sz) { @@ -5113,11 +5113,6 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) { id = cast(BuiltinProcId)e->Builtin.id; } else { id = BuiltinProc_DIRECTIVE; - if (ce->proc->kind == AstNode_Implicit) { - ast_node(i, Implicit, ce->proc); - GB_ASSERT(i->kind == Token_type_info_of); - id = BuiltinProc_type_info_of; - } } return ir_build_builtin_proc(proc, expr, tv, id); } diff --git a/src/ir_print.cpp b/src/ir_print.cpp index f8adc1e38..e24859413 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1344,9 +1344,15 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { case Token_Or: ir_write_str_lit(f, "or"); break; case Token_Xor: ir_write_str_lit(f, "xor"); break; case Token_Shl: ir_write_str_lit(f, "shl"); break; - case Token_Shr: ir_write_str_lit(f, "lshr"); break; case Token_Mul: ir_write_str_lit(f, "mul"); break; case Token_Not: ir_write_str_lit(f, "xor"); break; + case Token_Shr: + if (is_type_unsigned(elem_type)) { + ir_write_str_lit(f, "lshr"); + } else { + ir_write_str_lit(f, "ashr"); + } + break; case Token_AndNot: GB_PANIC("Token_AndNot Should never be called"); diff --git a/src/parser.cpp b/src/parser.cpp index d00d5e2a7..f5df64902 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1621,7 +1621,6 @@ AstNode *parse_operand(AstFile *f, bool lhs) { case Token_size_of: case Token_align_of: case Token_offset_of: - case Token_type_info_of: return parse_call_expr(f, ast_implicit(f, advance_token(f))); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 70f52ab8f..3890ae000 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -120,7 +120,6 @@ TOKEN_KIND(Token__KeywordBegin, ""), \ TOKEN_KIND(Token_align_of, "align_of"), \ TOKEN_KIND(Token_offset_of, "offset_of"), \ TOKEN_KIND(Token_type_of, "type_of"), \ - TOKEN_KIND(Token_type_info_of, "type_info_of"), \ TOKEN_KIND(Token_const, "const"), \ TOKEN_KIND(Token_asm, "asm"), \ TOKEN_KIND(Token_yield, "yield"), \