Browse Source

Improve minimal dependency system

gingerBill 7 years ago
parent
commit
18a9fa7355
8 changed files with 161 additions and 51 deletions
  1. 83 5
      src/check_expr.cpp
  2. 1 0
      src/check_stmt.cpp
  3. 4 0
      src/check_type.cpp
  4. 33 5
      src/checker.cpp
  5. 33 38
      src/ir.cpp
  6. 7 1
      src/ir_print.cpp
  7. 0 1
      src/parser.cpp
  8. 0 1
      src/tokenizer.cpp

+ 83 - 5
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;
 		}
 

+ 1 - 0
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:

+ 4 - 0
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);

+ 33 - 5
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<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 *
 	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");

+ 33 - 38
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<irValue *>(proc->module->allocator, 1);
-				args[0] = value;
-				return ir_emit_global_call(proc, "__gnu_h2f_ieee", args);
-				break;
-			}
-			case 8: {
-				auto args = array_make<irValue *>(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<irValue *>(proc->module->allocator, 1);
-				args[0] = value;
-				return ir_emit_global_call(proc, "__gnu_f2h_ieee", args);
-				break;
-			}
-			case 8: {
-				auto args = array_make<irValue *>(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<irValue *>(proc->module->allocator, 1);
+		// 		args[0] = value;
+		// 		return ir_emit_global_call(proc, "__gnu_h2f_ieee", args);
+		// 		break;
+		// 	}
+		// 	case 8: {
+		// 		auto args = array_make<irValue *>(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<irValue *>(proc->module->allocator, 1);
+		// 		args[0] = value;
+		// 		return ir_emit_global_call(proc, "__gnu_f2h_ieee", args);
+		// 		break;
+		// 	}
+		// 	case 8: {
+		// 		auto args = array_make<irValue *>(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);
 		}

+ 7 - 1
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");
 

+ 0 - 1
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)));
 
 

+ 0 - 1
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"),                  \