mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-29 10:50:05 +00:00
Improve support for freestanding_wasm32
This commit is contained in:
+11
-8
@@ -516,14 +516,17 @@ __init_context :: proc "contextless" (c: ^Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {
|
default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {
|
||||||
print_caller_location(loc)
|
when ODIN_OS == "freestanding" {
|
||||||
print_string(" ")
|
// Do nothing
|
||||||
print_string(prefix)
|
} else {
|
||||||
if len(message) > 0 {
|
print_caller_location(loc)
|
||||||
print_string(": ")
|
print_string(" ")
|
||||||
print_string(message)
|
print_string(prefix)
|
||||||
|
if len(message) > 0 {
|
||||||
|
print_string(": ")
|
||||||
|
print_string(message)
|
||||||
|
}
|
||||||
|
print_byte('\n')
|
||||||
}
|
}
|
||||||
print_byte('\n')
|
|
||||||
// intrinsics.debug_trap();
|
|
||||||
intrinsics.trap()
|
intrinsics.trap()
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-17
@@ -3,7 +3,14 @@ package runtime
|
|||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
|
||||||
@(private)
|
@(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)
|
@(private)
|
||||||
byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte #no_bounds_check {
|
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)
|
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 {
|
truncsfhf2 :: proc "c" (value: f32) -> u16 {
|
||||||
v: struct #raw_union { i: u32, f: f32 }
|
v: struct #raw_union { i: u32, f: f32 }
|
||||||
i, s, e, m: i32
|
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 {
|
truncdfhf2 :: proc "c" (value: f64) -> u16 {
|
||||||
return truncsfhf2(f32(value))
|
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 {
|
gnu_h2f_ieee :: proc "c" (value: u16) -> f32 {
|
||||||
fp32 :: struct #raw_union { u: u32, f: 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 {
|
gnu_f2h_ieee :: proc "c" (value: f32) -> u16 {
|
||||||
return truncsfhf2(value)
|
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 {
|
extendhfsf2 :: proc "c" (value: u16) -> f32 {
|
||||||
return gnu_h2f_ieee(value)
|
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 {
|
floattidf :: proc "c" (a: i128) -> f64 {
|
||||||
DBL_MANT_DIG :: 53
|
DBL_MANT_DIG :: 53
|
||||||
if a == 0 {
|
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 {
|
floattidf_unsigned :: proc "c" (a: u128) -> f64 {
|
||||||
DBL_MANT_DIG :: 53
|
DBL_MANT_DIG :: 53
|
||||||
if a == 0 {
|
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 {
|
fixunsdfti :: #force_no_inline proc "c" (a: f64) -> u128 {
|
||||||
// TODO(bill): implement `fixunsdfti` correctly
|
// TODO(bill): implement `fixunsdfti` correctly
|
||||||
x := u64(a)
|
x := u64(a)
|
||||||
return u128(x)
|
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 {
|
fixunsdfdi :: #force_no_inline proc "c" (a: f64) -> i128 {
|
||||||
// TODO(bill): implement `fixunsdfdi` correctly
|
// TODO(bill): implement `fixunsdfdi` correctly
|
||||||
x := i64(a)
|
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 {
|
umodti3 :: proc "c" (a, b: u128) -> u128 {
|
||||||
r: u128 = ---
|
r: u128 = ---
|
||||||
_ = udivmod128(a, b, &r)
|
_ = 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 {
|
udivmodti4 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
|
||||||
return udivmod128(a, b, rem)
|
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 {
|
udivti3 :: proc "c" (a, b: u128) -> u128 {
|
||||||
return udivmodti4(a, b, nil)
|
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 {
|
modti3 :: proc "c" (a, b: i128) -> i128 {
|
||||||
s_a := a >> (128 - 1)
|
s_a := a >> (128 - 1)
|
||||||
s_b := b >> (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 {
|
divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 {
|
||||||
u := udivmod128(transmute(u128)a, transmute(u128)b, cast(^u128)rem)
|
u := udivmod128(transmute(u128)a, transmute(u128)b, cast(^u128)rem)
|
||||||
return transmute(i128)u
|
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 {
|
divti3 :: proc "c" (a, b: i128) -> i128 {
|
||||||
u := udivmodti4(transmute(u128)a, transmute(u128)b, nil)
|
u := udivmodti4(transmute(u128)a, transmute(u128)b, nil)
|
||||||
return transmute(i128)u
|
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 {
|
fixdfti :: proc(a: u64) -> i128 {
|
||||||
significandBits :: 52
|
significandBits :: 52
|
||||||
typeWidth :: (size_of(u64)*8)
|
typeWidth :: (size_of(u64)*8)
|
||||||
|
|||||||
@@ -3,6 +3,17 @@ package runtime
|
|||||||
|
|
||||||
@(link_name="__ashlti3", linkage="strong")
|
@(link_name="__ashlti3", linkage="strong")
|
||||||
__ashlti3 :: proc "c" (a: i64, b: i32) -> i64 {
|
__ashlti3 :: proc "c" (a: i64, b: i32) -> i64 {
|
||||||
// TODO(bill): __ashlti3 on wasm32
|
input: transmute([2]i32)a
|
||||||
return 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]<<b
|
||||||
|
result[1] = (input[1]<<b) | (input[0]>>(32-b))
|
||||||
|
}
|
||||||
|
return transmute(i64)result
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
|
|||||||
|
|
||||||
n := transmute([2]u64)a
|
n := transmute([2]u64)a
|
||||||
d := transmute([2]u64)b
|
d := transmute([2]u64)b
|
||||||
q, r: [2]u64 = ---, ---
|
q, r: [2]u64
|
||||||
sr: u32 = 0
|
sr: u32 = 0
|
||||||
|
|
||||||
low :: 1 when ODIN_ENDIAN == "big" else 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
|
carry: u32 = 0
|
||||||
r_all: u128 = ---
|
r_all: u128
|
||||||
|
|
||||||
for ; sr > 0; sr -= 1 {
|
for ; sr > 0; sr -= 1 {
|
||||||
r[high] = (r[high] << 1) | (r[low] >> (U64_BITS - 1))
|
r[high] = (r[high] << 1) | (r[low] >> (U64_BITS - 1))
|
||||||
|
|||||||
+7
-3
@@ -2660,10 +2660,14 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (name == "require") {
|
} else if (name == "require") {
|
||||||
if (value != nullptr) {
|
ExactValue ev = check_decl_attribute_value(c, value);
|
||||||
error(elem, "'require' does not have any parameters");
|
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;
|
return true;
|
||||||
} else if (name == "init") {
|
} else if (name == "init") {
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
|
|||||||
@@ -1676,6 +1676,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
lbModule *m = gen->modules.entries[i].value;
|
lbModule *m = gen->modules.entries[i].value;
|
||||||
|
|
||||||
lb_run_remove_unused_function_pass(m);
|
lb_run_remove_unused_function_pass(m);
|
||||||
|
lb_run_remove_unused_globals_pass(m);
|
||||||
|
|
||||||
auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
|
auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
|
||||||
wd->m = m;
|
wd->m = m;
|
||||||
|
|||||||
@@ -373,6 +373,20 @@ void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedure *p) {
|
|||||||
lb_run_remove_dead_instruction_pass(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) {
|
void lb_run_remove_unused_function_pass(lbModule *m) {
|
||||||
isize removal_count = 0;
|
isize removal_count = 0;
|
||||||
@@ -380,7 +394,7 @@ void lb_run_remove_unused_function_pass(lbModule *m) {
|
|||||||
isize const max_pass_count = 10;
|
isize const max_pass_count = 10;
|
||||||
// Custom remove dead function pass
|
// Custom remove dead function pass
|
||||||
for (; pass_count < max_pass_count; pass_count++) {
|
for (; pass_count < max_pass_count; pass_count++) {
|
||||||
bool was_dead_function = false;
|
bool was_dead = false;
|
||||||
for (LLVMValueRef func = LLVMGetFirstFunction(m->mod);
|
for (LLVMValueRef func = LLVMGetFirstFunction(m->mod);
|
||||||
func != nullptr;
|
func != nullptr;
|
||||||
/**/
|
/**/
|
||||||
@@ -412,12 +426,58 @@ void lb_run_remove_unused_function_pass(lbModule *m) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMDeleteFunction(curr_func);
|
llvm_delete_function(curr_func);
|
||||||
was_dead_function = true;
|
was_dead = true;
|
||||||
removal_count += 1;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user