Browse Source

Fix `context` system; add more to -show-more-timings for LLVM API; Add `ODIN_USE_LLVM_API` global constant

gingerBill 5 years ago
parent
commit
28502ba53b
6 changed files with 73 additions and 49 deletions
  1. 3 4
      build.bat
  2. 30 10
      core/runtime/internal.odin
  3. 1 1
      examples/demo/demo.odin
  4. 1 0
      src/checker.cpp
  5. 1 1
      src/ir.cpp
  6. 37 33
      src/llvm_backend.cpp

+ 3 - 4
build.bat

@@ -49,15 +49,14 @@ del *.ilk > NUL 2> NUL
 
 cl %compiler_settings% "src\main.cpp" ^
 	/link %linker_settings% -OUT:%exe_name% ^
-	&& odin build examples/demo/demo.odin -llvm-api -show-timings
-	rem && odin build examples/llvm-demo/demo.odin -llvm-api -show-timings
+	&& odin build examples/demo/demo.odin -llvm-api -show-more-timings
 if %errorlevel% neq 0 (
 	goto end_of_build
 )
 
 link demo.obj kernel32.lib user32.lib /OUT:llvm_demo.exe ^
-	/nologo /incremental:no /opt:ref /subsystem:CONSOLE /defaultlib:libcmt -debug ^
-	&& llvm_demo
+	/nologo /incremental:no /opt:ref /subsystem:CONSOLE /defaultlib:libcmt -debug
+	rem && llvm_demo
 
 del *.obj > NUL 2> NUL
 

+ 30 - 10
core/runtime/internal.odin

@@ -57,12 +57,22 @@ mem_copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
 	if src == nil do return dst;
 	// NOTE(bill): This _must_ be implemented like C's memmove
 	foreign _ {
-		when size_of(rawptr) == 8 {
-			@(link_name="llvm.memmove.p0i8.p0i8.i64")
-			llvm_memmove :: proc(dst, src: rawptr, len: int, is_volatile: bool = false) ---;
+		when ODIN_USE_LLVM_API {
+			when size_of(rawptr) == 8 {
+				@(link_name="llvm.memmove.p0i8.p0i8.i64")
+				llvm_memmove :: proc(dst, src: rawptr, len: int, is_volatile: bool = false) ---;
+			} else {
+				@(link_name="llvm.memmove.p0i8.p0i8.i32")
+				llvm_memmove :: proc(dst, src: rawptr, len: int, is_volatile: bool = false) ---;
+			}
 		} else {
-			@(link_name="llvm.memmove.p0i8.p0i8.i32")
-			llvm_memmove :: proc(dst, src: rawptr, len: int, is_volatile: bool = false) ---;
+			when size_of(rawptr) == 8 {
+				@(link_name="llvm.memmove.p0i8.p0i8.i64")
+				llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32 = 1, is_volatile: bool = false) ---;
+			} else {
+				@(link_name="llvm.memmove.p0i8.p0i8.i32")
+				llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32 = 1, is_volatile: bool = false) ---;
+			}
 		}
 	}
 	llvm_memmove(dst, src, len);
@@ -73,12 +83,22 @@ mem_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> r
 	if src == nil do return dst;
 	// NOTE(bill): This _must_ be implemented like C's memcpy
 	foreign _ {
-		when size_of(rawptr) == 8 {
-			@(link_name="llvm.memcpy.p0i8.p0i8.i64")
-			llvm_memcpy :: proc(dst, src: rawptr, len: int, is_volatile: bool = false) ---;
+		when ODIN_USE_LLVM_API {
+			when size_of(rawptr) == 8 {
+				@(link_name="llvm.memcpy.p0i8.p0i8.i64")
+				llvm_memcpy :: proc(dst, src: rawptr, len: int, is_volatile: bool = false) ---;
+			} else {
+				@(link_name="llvm.memcpy.p0i8.p0i8.i32")
+				llvm_memcpy :: proc(dst, src: rawptr, len: int, is_volatile: bool = false) ---;
+			}
 		} else {
-			@(link_name="llvm.memcpy.p0i8.p0i8.i32")
-			llvm_memcpy :: proc(dst, src: rawptr, len: int, is_volatile: bool = false) ---;
+			when size_of(rawptr) == 8 {
+				@(link_name="llvm.memcpy.p0i8.p0i8.i64")
+				llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32 = 1, is_volatile: bool = false) ---;
+			} else {
+				@(link_name="llvm.memcpy.p0i8.p0i8.i32")
+				llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32 = 1, is_volatile: bool = false) ---;
+			}
 		}
 	}
 	llvm_memcpy(dst, src, len);

+ 1 - 1
examples/demo/demo.odin

@@ -1940,7 +1940,7 @@ main :: proc() {
 		struct_type();
 		union_type();
 		using_statement();
-		// implicit_context_system();
+		implicit_context_system();
 		parametric_polymorphism();
 		array_programming();
 		map_type();

+ 1 - 0
src/checker.cpp

@@ -711,6 +711,7 @@ void init_universal(void) {
 	add_global_string_constant(str_lit("ODIN_ROOT"),    bc->ODIN_ROOT);
 	add_global_constant(str_lit("ODIN_DEBUG"), t_untyped_bool, exact_value_bool(bc->ODIN_DEBUG));
 	add_global_constant(str_lit("ODIN_DISABLE_ASSERT"), t_untyped_bool, exact_value_bool(bc->ODIN_DISABLE_ASSERT));
+	add_global_constant(str_lit("ODIN_USE_LLVM_API"), t_untyped_bool, exact_value_bool(bc->use_llvm_api));
 
 
 // Builtin Procedures

+ 1 - 1
src/ir.cpp

@@ -11445,7 +11445,7 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
 				ir_emit_store(proc, results, ir_get_type_info_ptr(proc, t->Proc.results));
 			}
 			ir_emit_store(proc, variadic, ir_const_bool(t->Proc.variadic));
-			ir_emit_store(proc, convention, ir_const_int(t->Proc.calling_convention));
+			ir_emit_store(proc, convention, ir_const_u8(t->Proc.calling_convention));
 
 			// TODO(bill): TypeInfo for procedures
 			break;

+ 37 - 33
src/llvm_backend.cpp

@@ -303,6 +303,8 @@ lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) {
 			lbValue a = addr.addr;
 			lbValue b = lb_emit_deep_field_gep(p, a, addr.ctx.sel);
 			return lb_emit_load(p, b);
+		} else {
+			return lb_emit_load(p, addr.addr);
 		}
 	} else if (addr.kind == lbAddr_SoaVariable) {
 		Type *t = type_deref(addr.addr.type);
@@ -2002,30 +2004,15 @@ void lb_close_scope(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, bool p
 	GB_ASSERT(p->scope_index > 0);
 
 	// NOTE(bill): Remove `context`s made in that scope
-
-	isize end_idx = p->context_stack.count-1;
-	isize pop_count = 0;
-
-	for (;;) {
-		if (end_idx < 0) {
-			break;
-		}
-		lbContextData *end = &p->context_stack[end_idx];
-		if (end == nullptr) {
-			break;
-		}
-		if (end->scope_index != p->scope_index) {
-			break;
-		}
-		end_idx -= 1;
-		pop_count += 1;
-	}
-	if (pop_stack) {
-		for (isize i = 0; i < pop_count; i++) {
+	while (p->context_stack.count > 0) {
+		lbContextData *ctx = &p->context_stack[p->context_stack.count-1];
+		if (ctx->scope_index >= p->scope_index) {
 			array_pop(&p->context_stack);
+		} else {
+			break;
 		}
-	}
 
+	}
 
 	p->scope_index -= 1;
 }
@@ -5292,15 +5279,19 @@ lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t) {
 }
 
 
-void lb_emit_init_context(lbProcedure *p, lbValue c) {
+void lb_emit_init_context(lbProcedure *p, lbAddr addr) {
+	GB_ASSERT(addr.kind == lbAddr_Context);
+	GB_ASSERT(addr.ctx.sel.index.count == 0);
+
 	lbModule *m = p->module;
 	gbAllocator a = heap_allocator();
 	auto args = array_make<lbValue>(a, 1);
-	args[0] = c.value != nullptr ? c : m->global_default_context.addr;
+	args[0] = addr.addr;
 	lb_emit_runtime_call(p, "__init_context", args);
 }
 
 void lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx) {
+	ctx.kind = lbAddr_Context;
 	lbContextData cd = {ctx, p->scope_index};
 	array_add(&p->context_stack, cd);
 }
@@ -5315,7 +5306,7 @@ lbAddr lb_find_or_generate_context_ptr(lbProcedure *p) {
 	c.kind = lbAddr_Context;
 	lb_push_context_onto_stack(p, c);
 	lb_addr_store(p, c, lb_addr_load(p, p->module->global_default_context));
-	lb_emit_init_context(p, c.addr);
+	lb_emit_init_context(p, c);
 	return c;
 }
 
@@ -8307,7 +8298,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
 						sel = selection_combine(addr.ctx.sel, sel);
 					}
 					addr.ctx.sel = sel;
-
+					addr.kind = lbAddr_Context;
 					return addr;
 				} else if (addr.kind == lbAddr_SoaVariable) {
 					lbValue index = addr.soa.index;
@@ -10042,6 +10033,10 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
 
 
 void lb_generate_code(lbGenerator *gen) {
+	#define TIME_SECTION(str) do { if (build_context.show_more_timings) timings_start_section(&global_timings, str_lit(str)); } while (0)
+
+	TIME_SECTION("LLVM Global Variables");
+
 	lbModule *m = &gen->module;
 	LLVMModuleRef mod = gen->module.mod;
 	CheckerInfo *info = gen->info;
@@ -10051,7 +10046,7 @@ void lb_generate_code(lbGenerator *gen) {
 	gbAllocator temp_allocator = arena_allocator(&temp_arena);
 
 	gen->module.global_default_context = lb_add_global_generated(m, t_context, {});
-
+	gen->module.global_default_context.kind = lbAddr_Context;
 
 	auto *min_dep_set = &info->minimum_dependency_set;
 
@@ -10278,6 +10273,7 @@ void lb_generate_code(lbGenerator *gen) {
 	}
 
 
+	TIME_SECTION("LLVM Global Procedures and Types");
 	for_array(i, info->entities) {
 		// arena_free_all(&temp_arena);
 		// gbAllocator a = temp_allocator;
@@ -10335,6 +10331,7 @@ void lb_generate_code(lbGenerator *gen) {
 		}
 	}
 
+	TIME_SECTION("LLVM Procedure Generation");
 	for_array(i, m->procedures_to_generate) {
 		lbProcedure *p = m->procedures_to_generate[i];
 		if (p->is_done) {
@@ -10350,14 +10347,14 @@ void lb_generate_code(lbGenerator *gen) {
 
 		if (LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
 			gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name));
-			// LLVMDumpValue(p->value);
-			// gb_printf_err("\n\n\n\n");
-			// LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
-			exit(1);
+			LLVMDumpValue(p->value);
+			gb_printf_err("\n\n\n\n");
+			LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
 		}
 	}
 
 
+	TIME_SECTION("LLVM Function Pass");
 
 	LLVMPassRegistryRef pass_registry = LLVMGetGlobalPassRegistry();
 	LLVMPassManagerRef function_pass_manager = LLVMCreateFunctionPassManagerForModule(mod);
@@ -10432,7 +10429,7 @@ void lb_generate_code(lbGenerator *gen) {
 			}
 		}
 
-		lb_emit_init_context(p, {});
+		lb_emit_init_context(p, p->module->global_default_context);
 
 		lb_end_procedure_body(p);
 
@@ -10483,6 +10480,8 @@ void lb_generate_code(lbGenerator *gen) {
 	}
 
 
+	TIME_SECTION("LLVM Module Pass");
+
 	LLVMPassManagerRef module_pass_manager = LLVMCreatePassManager();
 	defer (LLVMDisposePassManager(module_pass_manager));
 	LLVMAddAlwaysInlinerPass(module_pass_manager);
@@ -10490,8 +10489,8 @@ void lb_generate_code(lbGenerator *gen) {
 
 	LLVMPassManagerBuilderRef pass_manager_builder = LLVMPassManagerBuilderCreate();
 	defer (LLVMPassManagerBuilderDispose(pass_manager_builder));
-	LLVMPassManagerBuilderSetOptLevel(pass_manager_builder, 3);
-	LLVMPassManagerBuilderSetSizeLevel(pass_manager_builder, 3);
+	LLVMPassManagerBuilderSetOptLevel(pass_manager_builder, build_context.optimization_level);
+	LLVMPassManagerBuilderSetSizeLevel(pass_manager_builder, build_context.optimization_level);
 
 	LLVMPassManagerBuilderPopulateLTOPassManager(pass_manager_builder, module_pass_manager, false, false);
 	LLVMRunPassManager(module_pass_manager, mod);
@@ -10513,6 +10512,8 @@ void lb_generate_code(lbGenerator *gen) {
 	LLVMVerifyModule(mod, LLVMAbortProcessAction, &llvm_error);
 	llvm_error = nullptr;
 
+	TIME_SECTION("LLVM Initializtion");
+
 	LLVMInitializeAllTargetInfos();
 	LLVMInitializeAllTargets();
 	LLVMInitializeAllTargetMCs();
@@ -10521,6 +10522,8 @@ void lb_generate_code(lbGenerator *gen) {
 	LLVMInitializeAllDisassemblers();
 	LLVMInitializeNativeTarget();
 
+	timings_start_section(&global_timings, str_lit("LLVM Object Generation"));
+
 	char const *target_triple = "x86_64-pc-windows-msvc";
 	char const *target_data_layout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128";
 	LLVMSetTarget(mod, target_triple);
@@ -10539,4 +10542,5 @@ void lb_generate_code(lbGenerator *gen) {
 		return;
 	}
 
+#undef TIME_SECTION
 }