From 28502ba53b32a0e5eb9aa7d8c41424fa090ff7ef Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 8 Mar 2020 12:34:36 +0000 Subject: [PATCH] Fix `context` system; add more to -show-more-timings for LLVM API; Add `ODIN_USE_LLVM_API` global constant --- build.bat | 7 ++-- core/runtime/internal.odin | 40 ++++++++++++++++------ examples/demo/demo.odin | 2 +- src/checker.cpp | 1 + src/ir.cpp | 2 +- src/llvm_backend.cpp | 70 ++++++++++++++++++++------------------ 6 files changed, 73 insertions(+), 49 deletions(-) diff --git a/build.bat b/build.bat index 4f3f665f2..436e7852f 100644 --- a/build.bat +++ b/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 diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 01b9ed616..bcc91eb6b 100644 --- a/core/runtime/internal.odin +++ b/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); diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index ed39eba8d..4ef9b2a8c 100644 --- a/examples/demo/demo.odin +++ b/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(); diff --git a/src/checker.cpp b/src/checker.cpp index 23e27af87..0494bde4b 100644 --- a/src/checker.cpp +++ b/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 diff --git a/src/ir.cpp b/src/ir.cpp index c5b140991..16999a209 100644 --- a/src/ir.cpp +++ b/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; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 8ddd37677..554323b54 100644 --- a/src/llvm_backend.cpp +++ b/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(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 }