Browse Source

Experimental support for `-use-separate-modules`

gingerBill 4 years ago
parent
commit
dfe1dedeb1
4 changed files with 66 additions and 37 deletions
  1. 0 4
      src/build_settings.cpp
  2. 47 9
      src/llvm_backend.cpp
  3. 1 0
      src/llvm_backend.hpp
  4. 18 24
      src/main.cpp

+ 0 - 4
src/build_settings.cpp

@@ -809,10 +809,6 @@ void init_build_context(TargetMetrics *cross_target) {
 	bc->max_align   = metrics->max_align;
 	bc->max_align   = metrics->max_align;
 	bc->link_flags  = str_lit(" ");
 	bc->link_flags  = str_lit(" ");
 
 
-	if (bc->metrics.os == TargetOs_windows) {
-		// bc->use_separate_modules = bc->optimization_level == 0;
-	}
-
 
 
 	// NOTE(zangent): The linker flags to set the build architecture are different
 	// NOTE(zangent): The linker flags to set the build architecture are different
 	// across OSs. It doesn't make sense to allocate extra data on the heap
 	// across OSs. It doesn't make sense to allocate extra data on the heap

+ 47 - 9
src/llvm_backend.cpp

@@ -2721,6 +2721,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
 
 
 	if (ignore_body) {
 	if (ignore_body) {
 		p->body = nullptr;
 		p->body = nullptr;
+		LLVMSetLinkage(p->value, LLVMExternalLinkage);
 	}
 	}
 
 
 
 
@@ -5762,7 +5763,7 @@ lbValue lb_find_value_from_entity(lbModule *m, Entity *e) {
 			lbValue g = {};
 			lbValue g = {};
 			g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
 			g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
 			g.type = alloc_type_pointer(e->type);
 			g.type = alloc_type_pointer(e->type);
-			LLVMSetExternallyInitialized(g.value, true);
+			LLVMSetLinkage(g.value, LLVMExternalLinkage);
 
 
 			lb_add_entity(m, e, g);
 			lb_add_entity(m, e, g);
 			lb_add_member(m, name, g);
 			lb_add_member(m, name, g);
@@ -11179,15 +11180,19 @@ lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *expr) {
 		return lb_addr_load(p, lb_build_addr(p, expr));
 		return lb_addr_load(p, lb_build_addr(p, expr));
 	}
 	}
 
 
+	if (e->kind == Entity_Procedure) {
+		return lb_find_procedure_value_from_entity(m, e);
+	}
 	if (USE_SEPARTE_MODULES) {
 	if (USE_SEPARTE_MODULES) {
 		lbModule *other_module = lb_pkg_module(m->gen, e->pkg);
 		lbModule *other_module = lb_pkg_module(m->gen, e->pkg);
 		if (other_module != m) {
 		if (other_module != m) {
+
 			String name = lb_get_entity_name(other_module, e);
 			String name = lb_get_entity_name(other_module, e);
 
 
 			lbValue g = {};
 			lbValue g = {};
 			g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
 			g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
 			g.type = alloc_type_pointer(e->type);
 			g.type = alloc_type_pointer(e->type);
-			LLVMSetExternallyInitialized(g.value, true);
+			LLVMSetLinkage(g.value, LLVMExternalLinkage);
 
 
 			lb_add_entity(m, e, g);
 			lb_add_entity(m, e, g);
 			lb_add_member(m, name, g);
 			lb_add_member(m, name, g);
@@ -12995,13 +13000,15 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
 void lb_init_module(lbModule *m, Checker *c) {
 void lb_init_module(lbModule *m, Checker *c) {
 	m->info = &c->info;
 	m->info = &c->info;
 
 
-	gbString module_name = nullptr;
+	gbString module_name = gb_string_make(heap_allocator(), "odin_package-");
 	if (m->pkg) {
 	if (m->pkg) {
-		module_name = gb_string_make(heap_allocator(), "odin_package-");
 		module_name = gb_string_append_length(module_name, m->pkg->name.text, m->pkg->name.len);
 		module_name = gb_string_append_length(module_name, m->pkg->name.text, m->pkg->name.len);
+	} else if (USE_SEPARTE_MODULES) {
+		module_name = gb_string_appendc(module_name, "builtin");
+	} else {
+		module_name = "odin_package";
 	}
 	}
 
 
-
 	m->ctx = LLVMContextCreate();
 	m->ctx = LLVMContextCreate();
 	m->mod = LLVMModuleCreateWithNameInContext(module_name ? module_name : "odin_package", m->ctx);
 	m->mod = LLVMModuleCreateWithNameInContext(module_name ? module_name : "odin_package", m->ctx);
 	// m->debug_builder = nullptr;
 	// m->debug_builder = nullptr;
@@ -13089,6 +13096,7 @@ bool lb_init_generator(lbGenerator *gen, Checker *c) {
 	}
 	}
 	gbAllocator ha = heap_allocator();
 	gbAllocator ha = heap_allocator();
 	array_init(&gen->output_object_paths, ha);
 	array_init(&gen->output_object_paths, ha);
+	array_init(&gen->output_temp_paths, ha);
 
 
 	gen->output_base = path_to_full_path(ha, gen->output_base);
 	gen->output_base = path_to_full_path(ha, gen->output_base);
 
 
@@ -14110,8 +14118,20 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
 		lb_fill_slice(p, args, argv, argc);
 		lb_fill_slice(p, args, argv, argc);
 	}
 	}
 
 
+	{
+		auto args = array_make<lbValue>(permanent_allocator(), 1);
+		args[0] = lb_const_string(p->module, str_lit("Here0\n"));
+		lb_emit_runtime_call(p, "print_string", args);
+	}
+
 	LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(m, startup_runtime->type)), startup_runtime->value, nullptr, 0, "");
 	LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(m, startup_runtime->type)), startup_runtime->value, nullptr, 0, "");
 
 
+	{
+		auto args = array_make<lbValue>(permanent_allocator(), 1);
+		args[0] = lb_const_string(p->module, str_lit("Here1\n"));
+		lb_emit_runtime_call(p, "print_string", args);
+	}
+
 	if (build_context.command_kind == Command_test) {
 	if (build_context.command_kind == Command_test) {
 		Type *t_Internal_Test = find_type_in_pkg(m->info, str_lit("testing"), str_lit("Internal_Test"));
 		Type *t_Internal_Test = find_type_in_pkg(m->info, str_lit("testing"), str_lit("Internal_Test"));
 		Type *array_type = alloc_type_array(t_Internal_Test, m->info->testing_procedures.count);
 		Type *array_type = alloc_type_array(t_Internal_Test, m->info->testing_procedures.count);
@@ -14189,6 +14209,8 @@ String lb_filepath_ll_for_module(lbModule *m) {
 	String path = m->gen->output_base;
 	String path = m->gen->output_base;
 	if (m->pkg) {
 	if (m->pkg) {
 		path = concatenate3_strings(permanent_allocator(), path, STR_LIT("-"), m->pkg->name);
 		path = concatenate3_strings(permanent_allocator(), path, STR_LIT("-"), m->pkg->name);
+	} else if (USE_SEPARTE_MODULES) {
+		path = concatenate_strings(permanent_allocator(), path, STR_LIT("-builtin"));
 	}
 	}
 	path = concatenate_strings(permanent_allocator(), path, STR_LIT(".ll"));
 	path = concatenate_strings(permanent_allocator(), path, STR_LIT(".ll"));
 
 
@@ -14522,6 +14544,7 @@ void lb_generate_code(lbGenerator *gen) {
 			LLVMSetThreadLocalMode(g.value, mode);
 			LLVMSetThreadLocalMode(g.value, mode);
 		}
 		}
 		if (is_foreign) {
 		if (is_foreign) {
+			LLVMSetLinkage(g.value, LLVMExternalLinkage);
 			LLVMSetExternallyInitialized(g.value, true);
 			LLVMSetExternallyInitialized(g.value, true);
 			lb_add_foreign_library_path(m, e->Variable.foreign_library);
 			lb_add_foreign_library_path(m, e->Variable.foreign_library);
 		} else {
 		} else {
@@ -14840,12 +14863,20 @@ void lb_generate_code(lbGenerator *gen) {
 
 
 		for_array(j, gen->modules.entries) {
 		for_array(j, gen->modules.entries) {
 			lbModule *m = gen->modules.entries[j].value;
 			lbModule *m = gen->modules.entries[j].value;
+
+			if (LLVMGetFirstFunction(m->mod) == nullptr &&
+			    LLVMGetFirstGlobal(m->mod) == nullptr) {
+				continue;
+			}
+
 			String filepath_ll = lb_filepath_ll_for_module(m);
 			String filepath_ll = lb_filepath_ll_for_module(m);
 			if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
 			if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
 				gb_printf_err("LLVM Error: %s\n", llvm_error);
 				gb_printf_err("LLVM Error: %s\n", llvm_error);
 				gb_exit(1);
 				gb_exit(1);
 				return;
 				return;
 			}
 			}
+			array_add(&gen->output_temp_paths, filepath_ll);
+
 		}
 		}
 		if (build_context.build_mode == BuildMode_LLVM_IR) {
 		if (build_context.build_mode == BuildMode_LLVM_IR) {
 			gb_exit(0);
 			gb_exit(0);
@@ -14857,6 +14888,16 @@ void lb_generate_code(lbGenerator *gen) {
 
 
 	for_array(j, gen->modules.entries) {
 	for_array(j, gen->modules.entries) {
 		lbModule *m = gen->modules.entries[j].value;
 		lbModule *m = gen->modules.entries[j].value;
+		for_array(i, m->info->required_foreign_imports_through_force) {
+			Entity *e = m->info->required_foreign_imports_through_force[i];
+			lb_add_foreign_library_path(m, e);
+		}
+
+		if (LLVMGetFirstFunction(m->mod) == nullptr &&
+		    LLVMGetFirstGlobal(m->mod) == nullptr) {
+			continue;
+		}
+
 		String filepath_obj = lb_filepath_obj_for_module(m);
 		String filepath_obj = lb_filepath_obj_for_module(m);
 
 
 		if (LLVMTargetMachineEmitToFile(target_machine, m->mod, cast(char *)filepath_obj.text, code_gen_file_type, &llvm_error)) {
 		if (LLVMTargetMachineEmitToFile(target_machine, m->mod, cast(char *)filepath_obj.text, code_gen_file_type, &llvm_error)) {
@@ -14866,10 +14907,7 @@ void lb_generate_code(lbGenerator *gen) {
 		}
 		}
 
 
 		array_add(&gen->output_object_paths, filepath_obj);
 		array_add(&gen->output_object_paths, filepath_obj);
-		for_array(i, m->info->required_foreign_imports_through_force) {
-			Entity *e = m->info->required_foreign_imports_through_force[i];
-			lb_add_foreign_library_path(m, e);
-		}
+
 	}
 	}
 
 
 
 

+ 1 - 0
src/llvm_backend.hpp

@@ -128,6 +128,7 @@ struct lbGenerator {
 	CheckerInfo *info;
 	CheckerInfo *info;
 
 
 	Array<String> output_object_paths;
 	Array<String> output_object_paths;
+	Array<String> output_temp_paths;
 	String   output_base;
 	String   output_base;
 	String   output_name;
 	String   output_name;
 	Map<lbModule *> modules; // Key: AstPackage *
 	Map<lbModule *> modules; // Key: AstPackage *

+ 18 - 24
src/main.cpp

@@ -596,6 +596,7 @@ enum BuildFlagKind {
 	BuildFlag_NoCRT,
 	BuildFlag_NoCRT,
 	BuildFlag_NoEntryPoint,
 	BuildFlag_NoEntryPoint,
 	BuildFlag_UseLLD,
 	BuildFlag_UseLLD,
+	BuildFlag_UseSeparateModules,
 	BuildFlag_Vet,
 	BuildFlag_Vet,
 	BuildFlag_VetExtra,
 	BuildFlag_VetExtra,
 	BuildFlag_UseLLVMApi,
 	BuildFlag_UseLLVMApi,
@@ -716,6 +717,7 @@ bool parse_build_flags(Array<String> args) {
 	add_flag(&build_flags, BuildFlag_NoCRT,             str_lit("no-crt"),              BuildFlagParam_None, Command__does_build);
 	add_flag(&build_flags, BuildFlag_NoCRT,             str_lit("no-crt"),              BuildFlagParam_None, Command__does_build);
 	add_flag(&build_flags, BuildFlag_NoEntryPoint,      str_lit("no-entry-point"),      BuildFlagParam_None, Command__does_check &~ Command_test);
 	add_flag(&build_flags, BuildFlag_NoEntryPoint,      str_lit("no-entry-point"),      BuildFlagParam_None, Command__does_check &~ Command_test);
 	add_flag(&build_flags, BuildFlag_UseLLD,            str_lit("lld"),                 BuildFlagParam_None, Command__does_build);
 	add_flag(&build_flags, BuildFlag_UseLLD,            str_lit("lld"),                 BuildFlagParam_None, Command__does_build);
+	add_flag(&build_flags, BuildFlag_UseSeparateModules,str_lit("use-separate-modules"),BuildFlagParam_None, Command__does_build);
 	add_flag(&build_flags, BuildFlag_Vet,               str_lit("vet"),                 BuildFlagParam_None, Command__does_check);
 	add_flag(&build_flags, BuildFlag_Vet,               str_lit("vet"),                 BuildFlagParam_None, Command__does_check);
 	add_flag(&build_flags, BuildFlag_VetExtra,          str_lit("vet-extra"),           BuildFlagParam_None, Command__does_check);
 	add_flag(&build_flags, BuildFlag_VetExtra,          str_lit("vet-extra"),           BuildFlagParam_None, Command__does_check);
 	add_flag(&build_flags, BuildFlag_UseLLVMApi,        str_lit("llvm-api"),            BuildFlagParam_None, Command__does_build);
 	add_flag(&build_flags, BuildFlag_UseLLVMApi,        str_lit("llvm-api"),            BuildFlagParam_None, Command__does_build);
@@ -1195,6 +1197,10 @@ bool parse_build_flags(Array<String> args) {
 							build_context.use_lld = true;
 							build_context.use_lld = true;
 							break;
 							break;
 
 
+						case BuildFlag_UseSeparateModules:
+							build_context.use_separate_modules = true;
+							break;
+
 						case BuildFlag_Vet:
 						case BuildFlag_Vet:
 							build_context.vet = true;
 							build_context.vet = true;
 							break;
 							break;
@@ -1545,35 +1551,17 @@ void show_timings(Checker *c, Timings *t) {
 void remove_temp_files(lbGenerator *gen) {
 void remove_temp_files(lbGenerator *gen) {
 	if (build_context.keep_temp_files) return;
 	if (build_context.keep_temp_files) return;
 
 
-	String output_base = gen->output_base;
-
-	auto data = array_make<u8>(heap_allocator(), output_base.len + 30);
-	defer (array_free(&data));
-
-	for_array(i, gen->output_object_paths) {
-		String path = gen->output_object_paths[i];
+	for_array(i, gen->output_temp_paths) {
+		String path = gen->output_temp_paths[i];
 		gb_file_remove(cast(char const *)path.text);
 		gb_file_remove(cast(char const *)path.text);
 	}
 	}
 
 
-	isize n = output_base.len;
-	gb_memmove(data.data, output_base.text, n);
-#define EXT_REMOVE(s) do {                         \
-		gb_memmove(data.data+n, s, gb_size_of(s)); \
-		gb_file_remove(cast(char const *)data.data);     \
-	} while (0)
-	EXT_REMOVE(".ll");
-	EXT_REMOVE(".bc");
-	EXT_REMOVE("_memcpy_pass.bc");
 	if (build_context.build_mode != BuildMode_Object && !build_context.keep_object_files) {
 	if (build_context.build_mode != BuildMode_Object && !build_context.keep_object_files) {
-	#if defined(GB_SYSTEM_WINDOWS)
-		EXT_REMOVE(".obj");
-		EXT_REMOVE(".res");
-	#else
-		EXT_REMOVE(".o");
-	#endif
+		for_array(i, gen->output_object_paths) {
+			String path = gen->output_object_paths[i];
+			gb_file_remove(cast(char const *)path.text);
+		}
 	}
 	}
-
-#undef EXT_REMOVE
 }
 }
 
 
 
 
@@ -1734,6 +1722,12 @@ void print_show_help(String const arg0, String const &command) {
 		print_usage_line(1, "-use-lld");
 		print_usage_line(1, "-use-lld");
 		print_usage_line(2, "Use the LLD linker rather than the default");
 		print_usage_line(2, "Use the LLD linker rather than the default");
 		print_usage_line(0, "");
 		print_usage_line(0, "");
+
+		print_usage_line(1, "-use-separate-modules");
+		print_usage_line(2, "The backend generates multiple build units which are then linked together");
+		print_usage_line(2, "Normally, a single build unit is generated for a standard project");
+		print_usage_line(0, "");
+
 	}
 	}
 
 
 	if (check) {
 	if (check) {