Improve minimal dependency system

This commit is contained in:
gingerBill
2018-05-12 10:27:55 +01:00
parent b32af841c5
commit 18a9fa7355
8 changed files with 161 additions and 51 deletions
+83 -5
View File
@@ -1561,9 +1561,38 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) {
} else { } else {
x->mode = Addressing_Value; x->mode = Addressing_Value;
update_expr_type(c, x->expr, default_type(x->type), true); update_expr_type(c, x->expr, default_type(x->type), true);
update_expr_type(c, y->expr, default_type(y->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; x->type = t_untyped_bool;
@@ -1820,6 +1849,9 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
} }
// cstring -> string // cstring -> string
if (src == t_cstring && dst == t_string) { if (src == t_cstring && dst == t_string) {
if (operand->mode != Addressing_Constant) {
add_preload_dependency(c, "__cstring_to_string");
}
return true; return true;
} }
// cstring -> ^u8 // 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->type = t_source_code_location;
operand->mode = Addressing_Value; operand->mode = Addressing_Value;
add_preload_dependency(c, "make_source_code_location");
} else if (name == "assert") { } else if (name == "assert") {
if (ce->args.count != 1) { if (ce->args.count != 1) {
error(call, "'#assert' expects at 1 argument, got %td", ce->args.count); 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; type = t_untyped_integer;
} else { } else {
mode = Addressing_Value; mode = Addressing_Value;
if (is_type_cstring(op_type)) {
add_preload_dependency(c, "__cstring_len");
}
} }
} else if (is_type_array(op_type)) { } else if (is_type_array(op_type)) {
Type *at = core_type(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)) { if (is_type_slice(type)) {
min_args = 2; min_args = 2;
max_args = 2; max_args = 2;
add_preload_dependency(c, "alloc");
} else if (is_type_map(type)) { } else if (is_type_map(type)) {
min_args = 1; min_args = 1;
max_args = 2; max_args = 2;
add_preload_dependency(c, "__dynamic_map_reserve");
} else if (is_type_dynamic_array(type)) { } else if (is_type_dynamic_array(type)) {
min_args = 1; min_args = 1;
max_args = 3; max_args = 3;
add_preload_dependency(c, "__dynamic_array_make");
} else { } else {
gbString str = type_to_string(type); gbString str = type_to_string(type);
error(call, "Cannot 'make' %s; type must be a slice, map, or dynamic array", str); 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); gb_string_free(type_a);
return false; 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); gb_string_free(type_a);
return false; 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 { } else {
operand->mode = Addressing_Value; 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)) { if (is_type_complex(operand->type)) {
@@ -3924,6 +3984,18 @@ break;
gb_string_free(type_x); gb_string_free(type_x);
return false; 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; break;
@@ -5149,10 +5221,6 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
o->mode = Addressing_Builtin; o->mode = Addressing_Builtin;
o->builtin_id = BuiltinProc_type_of; o->builtin_id = BuiltinProc_type_of;
break; break;
case Token_type_info_of:
o->mode = Addressing_Builtin;
o->builtin_id = BuiltinProc_type_info_of;
break;
default: default:
error(node, "Illegal implicit name '%.*s'", LIT(i->string)); 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; elem_type = t->DynamicArray.elem;
context_name = str_lit("dynamic array literal"); context_name = str_lit("dynamic array literal");
is_constant = false; is_constant = false;
add_preload_dependency(c, "__dynamic_array_reserve");
add_preload_dependency(c, "__dynamic_array_append");
} else { } else {
GB_PANIC("unreachable"); 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; break;
} }
@@ -5813,6 +5886,8 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
o->expr = node; o->expr = node;
return kind; return kind;
} }
add_preload_dependency(c, "__type_assertion_check");
case_end; case_end;
case_ast_node(tc, TypeCast, node); 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->mode = Addressing_MapIndex;
o->type = t->Map.value; o->type = t->Map.value;
o->expr = node; o->expr = node;
add_preload_dependency(c, "__dynamic_map_get");
add_preload_dependency(c, "__dynamic_map_set");
return Expr_Expr; return Expr_Expr;
} }
+1
View File
@@ -1411,6 +1411,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (is_type_string(t)) { if (is_type_string(t)) {
val0 = t_rune; val0 = t_rune;
val1 = t_int; val1 = t_int;
add_preload_dependency(c, "__string_decode_rune");
} }
break; break;
case Type_Array: case Type_Array:
+4
View File
@@ -1827,6 +1827,10 @@ void check_map_type(Checker *c, Type *type, AstNode *node) {
type->Map.key = key; type->Map.key = key;
type->Map.value = value; type->Map.value = value;
if (is_type_string(key)) {
add_preload_dependency(c, "__default_hash_string");
}
init_preload(c); init_preload(c);
init_map_internal_types(type); init_map_internal_types(type);
+33 -5
View File
@@ -484,6 +484,13 @@ void add_dependency(DeclInfo *d, Entity *e) {
ptr_set_add(&d->deps, 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) { void add_declaration_dependency(Checker *c, Entity *e) {
if (e == nullptr) { if (e == nullptr) {
return; return;
@@ -1177,17 +1184,38 @@ void add_dependency_to_map(PtrSet<Entity *> *map, CheckerInfo *info, Entity *ent
} }
} }
PtrSet<Entity *> generate_minimum_dependency_set(CheckerInfo *info, Entity *start) { PtrSet<Entity *> generate_minimum_dependency_set(Checker *c, Entity *start) {
CheckerInfo *info = &c->info;
PtrSet<Entity *> map = {}; // Key: Entity * PtrSet<Entity *> map = {}; // Key: Entity *
ptr_set_init(&map, heap_allocator()); 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) { for_array(i, info->definitions) {
Entity *e = info->definitions[i]; 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 && !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->scope->is_global) { // TODO(bill): is the check enough?
if (e->type == nullptr || !is_type_poly_proc(e->type)) { if (e->type == nullptr || !is_type_poly_proc(e->type)) {
// NOTE(bill): Require runtime stuff if (e->kind == Entity_TypeName) {
add_dependency_to_map(&map, info, e); 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) { } else if (e->kind == Entity_Procedure && e->Procedure.is_export) {
add_dependency_to_map(&map, info, e); add_dependency_to_map(&map, info, e);
@@ -3115,7 +3143,7 @@ void check_parsed_files(Checker *c) {
} }
TIME_SECTION("generate minimum dependency set"); 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"); TIME_SECTION("calculate global init order");
+33 -38
View File
@@ -3149,39 +3149,39 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
gbAllocator a = proc->module->allocator; gbAllocator a = proc->module->allocator;
i64 sz = type_size_of(src); i64 sz = type_size_of(src);
i64 dz = type_size_of(dst); i64 dz = type_size_of(dst);
if (sz == 2) { // if (sz == 2) {
switch (dz) { // switch (dz) {
case 2: return value; // case 2: return value;
case 4: { // case 4: {
auto args = array_make<irValue *>(proc->module->allocator, 1); // auto args = array_make<irValue *>(proc->module->allocator, 1);
args[0] = value; // args[0] = value;
return ir_emit_global_call(proc, "__gnu_h2f_ieee", args); // return ir_emit_global_call(proc, "__gnu_h2f_ieee", args);
break; // break;
} // }
case 8: { // case 8: {
auto args = array_make<irValue *>(proc->module->allocator, 1); // auto args = array_make<irValue *>(proc->module->allocator, 1);
args[0] = value; // args[0] = value;
return ir_emit_global_call(proc, "__f16_to_f64", args); // return ir_emit_global_call(proc, "__f16_to_f64", args);
break; // break;
} // }
} // }
} else if (dz == 2) { // } else if (dz == 2) {
switch (sz) { // switch (sz) {
case 2: return value; // case 2: return value;
case 4: { // case 4: {
auto args = array_make<irValue *>(proc->module->allocator, 1); // auto args = array_make<irValue *>(proc->module->allocator, 1);
args[0] = value; // args[0] = value;
return ir_emit_global_call(proc, "__gnu_f2h_ieee", args); // return ir_emit_global_call(proc, "__gnu_f2h_ieee", args);
break; // break;
} // }
case 8: { // case 8: {
auto args = array_make<irValue *>(proc->module->allocator, 1); // auto args = array_make<irValue *>(proc->module->allocator, 1);
args[0] = value; // args[0] = value;
return ir_emit_global_call(proc, "__truncdfhf2", args); // return ir_emit_global_call(proc, "__truncdfhf2", args);
break; // break;
} // }
} // }
} // }
irConvKind kind = irConv_fptrunc; irConvKind kind = irConv_fptrunc;
if (dz >= sz) { if (dz >= sz) {
@@ -5113,11 +5113,6 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
id = cast(BuiltinProcId)e->Builtin.id; id = cast(BuiltinProcId)e->Builtin.id;
} else { } else {
id = BuiltinProc_DIRECTIVE; 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); return ir_build_builtin_proc(proc, expr, tv, id);
} }
+7 -1
View File
@@ -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_Or: ir_write_str_lit(f, "or"); break;
case Token_Xor: ir_write_str_lit(f, "xor"); break; case Token_Xor: ir_write_str_lit(f, "xor"); break;
case Token_Shl: ir_write_str_lit(f, "shl"); 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_Mul: ir_write_str_lit(f, "mul"); break;
case Token_Not: ir_write_str_lit(f, "xor"); 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"); case Token_AndNot: GB_PANIC("Token_AndNot Should never be called");
-1
View File
@@ -1621,7 +1621,6 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
case Token_size_of: case Token_size_of:
case Token_align_of: case Token_align_of:
case Token_offset_of: case Token_offset_of:
case Token_type_info_of:
return parse_call_expr(f, ast_implicit(f, advance_token(f))); return parse_call_expr(f, ast_implicit(f, advance_token(f)));
-1
View File
@@ -120,7 +120,6 @@ TOKEN_KIND(Token__KeywordBegin, ""), \
TOKEN_KIND(Token_align_of, "align_of"), \ TOKEN_KIND(Token_align_of, "align_of"), \
TOKEN_KIND(Token_offset_of, "offset_of"), \ TOKEN_KIND(Token_offset_of, "offset_of"), \
TOKEN_KIND(Token_type_of, "type_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_const, "const"), \
TOKEN_KIND(Token_asm, "asm"), \ TOKEN_KIND(Token_asm, "asm"), \
TOKEN_KIND(Token_yield, "yield"), \ TOKEN_KIND(Token_yield, "yield"), \