diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 20e808fb7..db97fa15b 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -516,14 +516,17 @@ __init_context :: proc "contextless" (c: ^Context) { } default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! { - print_caller_location(loc) - print_string(" ") - print_string(prefix) - if len(message) > 0 { - print_string(": ") - print_string(message) + when ODIN_OS == "freestanding" { + // Do nothing + } else { + print_caller_location(loc) + print_string(" ") + print_string(prefix) + if len(message) > 0 { + print_string(": ") + print_string(message) + } + print_byte('\n') } - print_byte('\n') - // intrinsics.debug_trap(); intrinsics.trap() } diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 775245cc8..4040edb99 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -3,7 +3,14 @@ package runtime import "core:intrinsics" @(private) -RUNTIME_LINKAGE :: "strong" when (ODIN_USE_SEPARATE_MODULES || ODIN_BUILD_MODE == "dynamic" || !ODIN_NO_CRT) else "internal" +RUNTIME_LINKAGE :: "strong" when ( + (ODIN_USE_SEPARATE_MODULES || + ODIN_BUILD_MODE == "dynamic" || + !ODIN_NO_CRT) && + !(ODIN_ARCH == "wasm32" || + ODIN_ARCH == "wasm64")) else "internal" +RUNTIME_REQUIRE :: !(ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64") + @(private) byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte #no_bounds_check { @@ -649,7 +656,7 @@ quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 { return quaternion(t0, t1, t2, t3) } -@(link_name="__truncsfhf2", linkage=RUNTIME_LINKAGE, require) +@(link_name="__truncsfhf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) truncsfhf2 :: proc "c" (value: f32) -> u16 { v: struct #raw_union { i: u32, f: f32 } i, s, e, m: i32 @@ -707,12 +714,12 @@ truncsfhf2 :: proc "c" (value: f32) -> u16 { } -@(link_name="__truncdfhf2", linkage=RUNTIME_LINKAGE, require) +@(link_name="__truncdfhf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) truncdfhf2 :: proc "c" (value: f64) -> u16 { return truncsfhf2(f32(value)) } -@(link_name="__gnu_h2f_ieee", linkage=RUNTIME_LINKAGE, require) +@(link_name="__gnu_h2f_ieee", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) gnu_h2f_ieee :: proc "c" (value: u16) -> f32 { fp32 :: struct #raw_union { u: u32, f: f32 } @@ -731,19 +738,19 @@ gnu_h2f_ieee :: proc "c" (value: u16) -> f32 { } -@(link_name="__gnu_f2h_ieee", linkage=RUNTIME_LINKAGE, require) +@(link_name="__gnu_f2h_ieee", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) gnu_f2h_ieee :: proc "c" (value: f32) -> u16 { return truncsfhf2(value) } -@(link_name="__extendhfsf2", linkage=RUNTIME_LINKAGE, require) +@(link_name="__extendhfsf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) extendhfsf2 :: proc "c" (value: u16) -> f32 { return gnu_h2f_ieee(value) } -@(link_name="__floattidf", linkage=RUNTIME_LINKAGE, require) +@(link_name="__floattidf", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) floattidf :: proc "c" (a: i128) -> f64 { DBL_MANT_DIG :: 53 if a == 0 { @@ -786,7 +793,7 @@ floattidf :: proc "c" (a: i128) -> f64 { } -@(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, require) +@(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) floattidf_unsigned :: proc "c" (a: u128) -> f64 { DBL_MANT_DIG :: 53 if a == 0 { @@ -828,14 +835,14 @@ floattidf_unsigned :: proc "c" (a: u128) -> f64 { -@(link_name="__fixunsdfti", linkage=RUNTIME_LINKAGE, require) +@(link_name="__fixunsdfti", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) fixunsdfti :: #force_no_inline proc "c" (a: f64) -> u128 { // TODO(bill): implement `fixunsdfti` correctly x := u64(a) return u128(x) } -@(link_name="__fixunsdfdi", linkage=RUNTIME_LINKAGE, require) +@(link_name="__fixunsdfdi", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) fixunsdfdi :: #force_no_inline proc "c" (a: f64) -> i128 { // TODO(bill): implement `fixunsdfdi` correctly x := i64(a) @@ -845,7 +852,7 @@ fixunsdfdi :: #force_no_inline proc "c" (a: f64) -> i128 { -@(link_name="__umodti3", linkage=RUNTIME_LINKAGE, require) +@(link_name="__umodti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) umodti3 :: proc "c" (a, b: u128) -> u128 { r: u128 = --- _ = udivmod128(a, b, &r) @@ -853,18 +860,18 @@ umodti3 :: proc "c" (a, b: u128) -> u128 { } -@(link_name="__udivmodti4", linkage=RUNTIME_LINKAGE, require) +@(link_name="__udivmodti4", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) udivmodti4 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { return udivmod128(a, b, rem) } -@(link_name="__udivti3", linkage=RUNTIME_LINKAGE, require) +@(link_name="__udivti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) udivti3 :: proc "c" (a, b: u128) -> u128 { return udivmodti4(a, b, nil) } -@(link_name="__modti3", linkage=RUNTIME_LINKAGE, require) +@(link_name="__modti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) modti3 :: proc "c" (a, b: i128) -> i128 { s_a := a >> (128 - 1) s_b := b >> (128 - 1) @@ -877,20 +884,20 @@ modti3 :: proc "c" (a, b: i128) -> i128 { } -@(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require) +@(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 { u := udivmod128(transmute(u128)a, transmute(u128)b, cast(^u128)rem) return transmute(i128)u } -@(link_name="__divti3", linkage=RUNTIME_LINKAGE, require) +@(link_name="__divti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) divti3 :: proc "c" (a, b: i128) -> i128 { u := udivmodti4(transmute(u128)a, transmute(u128)b, nil) return transmute(i128)u } -@(link_name="__fixdfti", linkage=RUNTIME_LINKAGE, require) +@(link_name="__fixdfti", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) fixdfti :: proc(a: u64) -> i128 { significandBits :: 52 typeWidth :: (size_of(u64)*8) diff --git a/core/runtime/procs_wasm32.odin b/core/runtime/procs_wasm32.odin index cc9715183..2b242bc90 100644 --- a/core/runtime/procs_wasm32.odin +++ b/core/runtime/procs_wasm32.odin @@ -3,6 +3,17 @@ package runtime @(link_name="__ashlti3", linkage="strong") __ashlti3 :: proc "c" (a: i64, b: i32) -> i64 { - // TODO(bill): __ashlti3 on wasm32 - return a + input: transmute([2]i32)a + result: [2]i32 + if b & 32 != 0 { + result[0] = 0 + result[1] = input[0] << (b - 32) + } else { + if b == 0 { + return a + } + result[0] = input[0]<>(32-b)) + } + return transmute(i64)result } \ No newline at end of file diff --git a/core/runtime/udivmod128.odin b/core/runtime/udivmod128.odin index ac0c20661..1fd1b5f84 100644 --- a/core/runtime/udivmod128.odin +++ b/core/runtime/udivmod128.odin @@ -8,7 +8,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { n := transmute([2]u64)a d := transmute([2]u64)b - q, r: [2]u64 = ---, --- + q, r: [2]u64 sr: u32 = 0 low :: 1 when ODIN_ENDIAN == "big" else 0 @@ -132,7 +132,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { } carry: u32 = 0 - r_all: u128 = --- + r_all: u128 for ; sr > 0; sr -= 1 { r[high] = (r[high] << 1) | (r[low] >> (U64_BITS - 1)) diff --git a/src/checker.cpp b/src/checker.cpp index 5d8d6dcdc..f544ea5e6 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2660,10 +2660,14 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { } return true; } else if (name == "require") { - if (value != nullptr) { - error(elem, "'require' does not have any parameters"); + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_Invalid) { + ac->require_declaration = true; + } else if (ev.kind == ExactValue_Bool) { + ac->require_declaration = ev.value_bool; + } else { + error(value, "Expected either a boolean or no parameter for 'require'"); } - ac->require_declaration = true; return true; } else if (name == "init") { if (value != nullptr) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index c002bfc5e..e468f3032 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1676,6 +1676,7 @@ void lb_generate_code(lbGenerator *gen) { lbModule *m = gen->modules.entries[i].value; lb_run_remove_unused_function_pass(m); + lb_run_remove_unused_globals_pass(m); auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData); wd->m = m; diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index e592243cc..de925655f 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -373,6 +373,20 @@ void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedure *p) { lb_run_remove_dead_instruction_pass(p); } +void llvm_delete_function(LLVMValueRef func) { + // for (LLVMBasicBlockRef block = LLVMGetFirstBasicBlock(func); block != nullptr; /**/) { + // LLVMBasicBlockRef curr_block = block; + // block = LLVMGetNextBasicBlock(block); + // for (LLVMValueRef instr = LLVMGetFirstInstruction(curr_block); instr != nullptr; /**/) { + // LLVMValueRef curr_instr = instr; + // instr = LLVMGetNextInstruction(instr); + + // LLVMInstructionEraseFromParent(curr_instr); + // } + // LLVMRemoveBasicBlockFromParent(curr_block); + // } + LLVMDeleteFunction(func); +} void lb_run_remove_unused_function_pass(lbModule *m) { isize removal_count = 0; @@ -380,7 +394,7 @@ void lb_run_remove_unused_function_pass(lbModule *m) { isize const max_pass_count = 10; // Custom remove dead function pass for (; pass_count < max_pass_count; pass_count++) { - bool was_dead_function = false; + bool was_dead = false; for (LLVMValueRef func = LLVMGetFirstFunction(m->mod); func != nullptr; /**/ @@ -412,12 +426,58 @@ void lb_run_remove_unused_function_pass(lbModule *m) { continue; } } - - LLVMDeleteFunction(curr_func); - was_dead_function = true; + + llvm_delete_function(curr_func); + was_dead = true; removal_count += 1; } - if (!was_dead_function) { + if (!was_dead) { + break; + } + } +} + + +void lb_run_remove_unused_globals_pass(lbModule *m) { + isize removal_count = 0; + isize pass_count = 0; + isize const max_pass_count = 10; + // Custom remove dead function pass + for (; pass_count < max_pass_count; pass_count++) { + bool was_dead = false; + for (LLVMValueRef global = LLVMGetFirstGlobal(m->mod); + global != nullptr; + /**/ + ) { + LLVMValueRef curr_global = global; + global = LLVMGetNextGlobal(global); + + LLVMUseRef first_use = LLVMGetFirstUse(curr_global); + if (first_use != nullptr) { + continue; + } + String name = {}; + name.text = cast(u8 *)LLVMGetValueName2(curr_global, cast(size_t *)&name.len); + + LLVMLinkage linkage = LLVMGetLinkage(curr_global); + if (linkage != LLVMInternalLinkage) { + continue; + } + + Entity **found = map_get(&m->procedure_values, curr_global); + if (found && *found) { + Entity *e = *found; + bool is_required = (e->flags & EntityFlag_Require) == EntityFlag_Require; + if (is_required) { + continue; + } + } + + LLVMDeleteGlobal(curr_global); + was_dead = true; + removal_count += 1; + } + if (!was_dead) { break; } }