Browse Source

Fix global variable initialization ordering
(related to #427)

gingerBill 6 years ago
parent
commit
c89fc35e94
5 changed files with 47 additions and 39 deletions
  1. 3 2
      src/check_decl.cpp
  2. 6 1
      src/check_stmt.cpp
  3. 34 23
      src/checker.cpp
  4. 2 11
      src/ir.cpp
  5. 2 2
      src/priority_queue.cpp

+ 3 - 2
src/check_decl.cpp

@@ -791,7 +791,7 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
 	}
 	}
 }
 }
 
 
-void check_var_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init_expr) {
+void check_global_variable_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init_expr) {
 	GB_ASSERT(e->type == nullptr);
 	GB_ASSERT(e->type == nullptr);
 	GB_ASSERT(e->kind == Entity_Variable);
 	GB_ASSERT(e->kind == Entity_Variable);
 
 
@@ -805,6 +805,7 @@ void check_var_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init_ex
 	ac.init_expr_list_count = init_expr != nullptr ? 1 : 0;
 	ac.init_expr_list_count = init_expr != nullptr ? 1 : 0;
 
 
 	DeclInfo *decl = decl_info_of_entity(e);
 	DeclInfo *decl = decl_info_of_entity(e);
+	GB_ASSERT(decl == ctx->decl);
 	if (decl != nullptr) {
 	if (decl != nullptr) {
 		check_decl_attributes(ctx, decl->attributes, var_decl_attribute, &ac);
 		check_decl_attributes(ctx, decl->attributes, var_decl_attribute, &ac);
 	}
 	}
@@ -1051,7 +1052,7 @@ void check_entity_decl(CheckerContext *ctx, Entity *e, DeclInfo *d, Type *named_
 
 
 	switch (e->kind) {
 	switch (e->kind) {
 	case Entity_Variable:
 	case Entity_Variable:
-		check_var_decl(&c, e, d->type_expr, d->init_expr);
+		check_global_variable_decl(&c, e, d->type_expr, d->init_expr);
 		break;
 		break;
 	case Entity_Constant:
 	case Entity_Constant:
 		check_const_decl(&c, e, d->type_expr, d->init_expr, named_type);
 		check_const_decl(&c, e, d->type_expr, d->init_expr, named_type);

+ 6 - 1
src/check_stmt.cpp

@@ -1735,7 +1735,12 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
 		}
 		}
 
 
 		for (isize i = 0; i < entity_count; i++) {
 		for (isize i = 0; i < entity_count; i++) {
-			add_entity(ctx->checker, ctx->scope, entities[i]->identifier, entities[i]);
+			Entity *e = entities[i];
+			DeclInfo *d = decl_info_of_entity(e);
+			GB_ASSERT(d == nullptr);
+			add_entity(ctx->checker, ctx->scope, e->identifier, e);
+			d = make_decl_info(ctx->allocator, ctx->scope, ctx->decl);
+			add_entity_and_decl_info(ctx, e->identifier, e, d);
 		}
 		}
 
 
 		check_stmt(ctx, rs->body, new_flags);
 		check_stmt(ctx, rs->body, new_flags);

+ 34 - 23
src/checker.cpp

@@ -85,9 +85,13 @@ int entity_graph_node_cmp(EntityGraphNode **data, isize i, isize j) {
 	EntityGraphNode *y = data[j];
 	EntityGraphNode *y = data[j];
 	isize a = x->entity->order_in_src;
 	isize a = x->entity->order_in_src;
 	isize b = y->entity->order_in_src;
 	isize b = y->entity->order_in_src;
-	if (x->dep_count < y->dep_count) return -1;
-	if (x->dep_count > y->dep_count) return +1;
-	return a < b ? -1 : b > a;
+	if (x->dep_count < y->dep_count) {
+		return -1;
+	}
+	if (x->dep_count == y->dep_count) {
+		return a < b ? -1 : b > a;
+	}
+	return +1;
 }
 }
 
 
 void entity_graph_node_swap(EntityGraphNode **data, isize i, isize j) {
 void entity_graph_node_swap(EntityGraphNode **data, isize i, isize j) {
@@ -1164,6 +1168,7 @@ void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, Dec
 	add_entity_definition(&c->checker->info, identifier, e);
 	add_entity_definition(&c->checker->info, identifier, e);
 	GB_ASSERT(e->decl_info == nullptr);
 	GB_ASSERT(e->decl_info == nullptr);
 	e->decl_info = d;
 	e->decl_info = d;
+	d->entity = e;
 	array_add(&c->checker->info.entities, e);
 	array_add(&c->checker->info.entities, e);
 	e->order_in_src = c->checker->info.entities.count;
 	e->order_in_src = c->checker->info.entities.count;
 	e->pkg = c->pkg;
 	e->pkg = c->pkg;
@@ -1602,6 +1607,7 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
 
 
 		str_lit("args__"),
 		str_lit("args__"),
 		str_lit("type_table"),
 		str_lit("type_table"),
+		str_lit("__type_info_of"),
 		str_lit("global_scratch_allocator"),
 		str_lit("global_scratch_allocator"),
 
 
 		str_lit("Type_Info"),
 		str_lit("Type_Info"),
@@ -1688,9 +1694,10 @@ bool is_entity_a_dependency(Entity *e) {
 	if (e == nullptr) return false;
 	if (e == nullptr) return false;
 	switch (e->kind) {
 	switch (e->kind) {
 	case Entity_Procedure:
 	case Entity_Procedure:
-	case Entity_Variable:
-	case Entity_Constant:
 		return true;
 		return true;
+	case Entity_Constant:
+	case Entity_Variable:
+		return e->pkg != nullptr;
 	}
 	}
 	return false;
 	return false;
 }
 }
@@ -1717,18 +1724,17 @@ Array<EntityGraphNode *> generate_entity_dependency_graph(CheckerInfo *info) {
 		EntityGraphNode *n = M.entries[i].value;
 		EntityGraphNode *n = M.entries[i].value;
 
 
 		DeclInfo *decl = decl_info_of_entity(e);
 		DeclInfo *decl = decl_info_of_entity(e);
-		if (decl != nullptr) {
-			for_array(j, decl->deps.entries) {
-				auto entry = decl->deps.entries[j];
-				Entity *dep = entry.ptr;
-				if (dep && is_entity_a_dependency(dep)) {
-					EntityGraphNode **m_ = map_get(&M, hash_pointer(dep));
-					if (m_ != nullptr) {
-						EntityGraphNode *m = *m_;
-						entity_graph_node_set_add(&n->succ, m);
-						entity_graph_node_set_add(&m->pred, n);
-					}
-				}
+		GB_ASSERT(decl != nullptr);
+
+		for_array(j, decl->deps.entries) {
+			Entity *dep = decl->deps.entries[j].ptr;
+			GB_ASSERT(dep != nullptr);
+			if (is_entity_a_dependency(dep)) {
+				EntityGraphNode **m_ = map_get(&M, hash_pointer(dep));
+				GB_ASSERT(m_ != nullptr);
+				EntityGraphNode *m = *m_;
+				entity_graph_node_set_add(&n->succ, m);
+				entity_graph_node_set_add(&m->pred, n);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -2562,6 +2568,7 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
 
 
 			Ast *init_expr = value;
 			Ast *init_expr = value;
 			DeclInfo *d = make_decl_info(heap_allocator(), c->scope, c->decl);
 			DeclInfo *d = make_decl_info(heap_allocator(), c->scope, c->decl);
+			d->entity    = e;
 			d->type_expr = vd->type;
 			d->type_expr = vd->type;
 			d->init_expr = init_expr;
 			d->init_expr = init_expr;
 			d->attributes = vd->attributes;
 			d->attributes = vd->attributes;
@@ -3576,7 +3583,6 @@ void calculate_global_init_order(Checker *c) {
 #define TIME_SECTION(str)
 #define TIME_SECTION(str)
 #endif
 #endif
 
 
-
 	CheckerInfo *info = &c->info;
 	CheckerInfo *info = &c->info;
 
 
 	TIME_SECTION("generate entity dependency graph");
 	TIME_SECTION("generate entity dependency graph");
@@ -3618,21 +3624,26 @@ void calculate_global_init_order(Checker *c) {
 
 
 		for_array(i, n->pred.entries) {
 		for_array(i, n->pred.entries) {
 			EntityGraphNode *p = n->pred.entries[i].ptr;
 			EntityGraphNode *p = n->pred.entries[i].ptr;
-			p->dep_count -= gb_max(p->dep_count-1, 0);
+			p->dep_count -= 1;
+			p->dep_count = gb_max(p->dep_count, 0);
 			priority_queue_fix(&pq, p->index);
 			priority_queue_fix(&pq, p->index);
 		}
 		}
 
 
-		if (e == nullptr || e->kind != Entity_Variable) {
+		DeclInfo *d = decl_info_of_entity(e);
+		if (e->kind != Entity_Variable) {
 			continue;
 			continue;
 		}
 		}
-		DeclInfo *d = decl_info_of_entity(e);
-
+		// IMPORTANT NOTE(bill, 2019-08-29): Just add it regardless of the ordering
+		// because it does not need any initialization other than zero
+		// if (!decl_info_has_init(d)) {
+		// 	continue;
+		// }
 		if (ptr_set_exists(&emitted, d)) {
 		if (ptr_set_exists(&emitted, d)) {
 			continue;
 			continue;
 		}
 		}
 		ptr_set_add(&emitted, d);
 		ptr_set_add(&emitted, d);
 
 
-		d->entity = e;
+
 		array_add(&info->variable_init_order, d);
 		array_add(&info->variable_init_order, d);
 	}
 	}
 
 

+ 2 - 11
src/ir.cpp

@@ -2226,18 +2226,9 @@ irDebugInfo *ir_add_debug_info_type_complex(irModule *module, Type *type) {
 
 
 	Type *field_type = base_complex_elem_type(type);
 	Type *field_type = base_complex_elem_type(type);
 
 
-	// Field "real"
-	irDebugInfo *real_di = ir_add_debug_info_field_internal(module, str_lit("real"), field_type,
-															0,
-															nullptr,
-															di);
+	irDebugInfo *real_di = ir_add_debug_info_field_internal(module, str_lit("real"), field_type, 0*cast(i32)type_size_of(field_type), nullptr, di);
+	irDebugInfo *imag_di = ir_add_debug_info_field_internal(module, str_lit("imag"), field_type, 1*cast(i32)type_size_of(field_type), nullptr, di);
 	map_set(&module->debug_info, hash_pointer(real_di), real_di);
 	map_set(&module->debug_info, hash_pointer(real_di), real_di);
-
-	// Field "imag"
-	irDebugInfo *imag_di = ir_add_debug_info_field_internal(module, str_lit("imag"), field_type,
-															real_di->DerivedType.size,
-															nullptr,
-															di);
 	map_set(&module->debug_info, hash_pointer(imag_di), imag_di);
 	map_set(&module->debug_info, hash_pointer(imag_di), imag_di);
 
 
 	irDebugInfo *elements_di = ir_add_debug_info_array(module, 0, 2);
 	irDebugInfo *elements_di = ir_add_debug_info_array(module, 0, 2);

+ 2 - 2
src/priority_queue.cpp

@@ -20,7 +20,7 @@ bool priority_queue_shift_down(PriorityQueue<T> *pq, isize i0, isize n) {
 		if (j2 < n && pq->cmp(&pq->queue[0], j2, j1) < 0) {
 		if (j2 < n && pq->cmp(&pq->queue[0], j2, j1) < 0) {
 			j = j2;
 			j = j2;
 		}
 		}
-		if (pq->cmp(&pq->queue[0], i, j) < 0) break;
+		if (pq->cmp(&pq->queue[0], j, i) >= 0) break;
 
 
 		pq->swap(&pq->queue[0], i, j);
 		pq->swap(&pq->queue[0], i, j);
 		i = j;
 		i = j;
@@ -32,7 +32,7 @@ template <typename T>
 void priority_queue_shift_up(PriorityQueue<T> *pq, isize j) {
 void priority_queue_shift_up(PriorityQueue<T> *pq, isize j) {
 	while (0 <= j && j < pq->queue.count) {
 	while (0 <= j && j < pq->queue.count) {
 		isize i = (j-1)/2;
 		isize i = (j-1)/2;
-		if (i == j || pq->cmp(&pq->queue[0], i, j) < 0) {
+		if (i == j || pq->cmp(&pq->queue[0], j, i) >= 0) {
 			break;
 			break;
 		}
 		}
 		pq->swap(&pq->queue[0], i, j);
 		pq->swap(&pq->queue[0], i, j);