mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
@(linkage=<string>) for procedures and variables; @(require) for procedures; package runtime linkage improvements; Subsequence improvements to lb_run_remove_unused_function_pass
This commit is contained in:
+19
-16
@@ -2,6 +2,9 @@ package runtime
|
|||||||
|
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
RUNTIME_LINKAGE :: "strong" when ODIN_USE_SEPARATE_MODULES else "internal"
|
||||||
|
|
||||||
@(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 {
|
||||||
return ([^]byte)(data)[:max(len, 0)]
|
return ([^]byte)(data)[:max(len, 0)]
|
||||||
@@ -646,7 +649,7 @@ quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {
|
|||||||
return quaternion(t0, t1, t2, t3)
|
return quaternion(t0, t1, t2, t3)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(link_name="__truncsfhf2")
|
@(link_name="__truncsfhf2", linkage=RUNTIME_LINKAGE, 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
|
||||||
@@ -704,12 +707,12 @@ truncsfhf2 :: proc "c" (value: f32) -> u16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(link_name="__truncdfhf2")
|
@(link_name="__truncdfhf2", linkage=RUNTIME_LINKAGE, 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")
|
@(link_name="__gnu_h2f_ieee", linkage=RUNTIME_LINKAGE, 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 }
|
||||||
|
|
||||||
@@ -728,19 +731,19 @@ gnu_h2f_ieee :: proc "c" (value: u16) -> f32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(link_name="__gnu_f2h_ieee")
|
@(link_name="__gnu_f2h_ieee", linkage=RUNTIME_LINKAGE, 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")
|
@(link_name="__extendhfsf2", linkage=RUNTIME_LINKAGE, 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")
|
@(link_name="__floattidf", linkage=RUNTIME_LINKAGE, 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 {
|
||||||
@@ -783,7 +786,7 @@ floattidf :: proc "c" (a: i128) -> f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(link_name="__floattidf_unsigned")
|
@(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, 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 {
|
||||||
@@ -825,14 +828,14 @@ floattidf_unsigned :: proc "c" (a: u128) -> f64 {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@(link_name="__fixunsdfti")
|
@(link_name="__fixunsdfti", linkage=RUNTIME_LINKAGE, 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")
|
@(link_name="__fixunsdfdi", linkage=RUNTIME_LINKAGE, 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)
|
||||||
@@ -842,7 +845,7 @@ fixunsdfdi :: #force_no_inline proc "c" (a: f64) -> i128 {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@(link_name="__umodti3")
|
@(link_name="__umodti3", linkage=RUNTIME_LINKAGE, 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)
|
||||||
@@ -850,18 +853,18 @@ umodti3 :: proc "c" (a, b: u128) -> u128 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(link_name="__udivmodti4")
|
@(link_name="__udivmodti4", linkage=RUNTIME_LINKAGE, 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")
|
@(link_name="__udivti3", linkage=RUNTIME_LINKAGE, 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")
|
@(link_name="__modti3", linkage=RUNTIME_LINKAGE, 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)
|
||||||
@@ -874,20 +877,20 @@ modti3 :: proc "c" (a, b: i128) -> i128 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(link_name="__divmodti4")
|
@(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, 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")
|
@(link_name="__divti3", linkage=RUNTIME_LINKAGE, 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")
|
@(link_name="__fixdfti", linkage=RUNTIME_LINKAGE, 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)
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
package runtime
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
package runtime
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" {
|
when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" {
|
||||||
@(link_name="memset")
|
@(link_name="memset", require)
|
||||||
memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr {
|
memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr {
|
||||||
if ptr != nil && len != 0 {
|
if ptr != nil && len != 0 {
|
||||||
b := byte(val)
|
b := byte(val)
|
||||||
@@ -13,7 +13,7 @@ when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" {
|
|||||||
return ptr
|
return ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
@(link_name="memmove")
|
@(link_name="memmove", require)
|
||||||
memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
|
memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
|
||||||
if dst != src {
|
if dst != src {
|
||||||
d, s := ([^]byte)(dst), ([^]byte)(src)
|
d, s := ([^]byte)(dst), ([^]byte)(src)
|
||||||
@@ -26,8 +26,7 @@ when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" {
|
|||||||
|
|
||||||
}
|
}
|
||||||
} else when ODIN_NO_CRT {
|
} else when ODIN_NO_CRT {
|
||||||
@(export)
|
@(link_name="memset", linkage=RUNTIME_LINKAGE, require)
|
||||||
@(link_name="memset")
|
|
||||||
memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr {
|
memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr {
|
||||||
if ptr != nil && len != 0 {
|
if ptr != nil && len != 0 {
|
||||||
b := byte(val)
|
b := byte(val)
|
||||||
@@ -39,8 +38,7 @@ when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" {
|
|||||||
return ptr
|
return ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
@(export)
|
@(link_name="memmove", linkage=RUNTIME_LINKAGE, require)
|
||||||
@(link_name="memmove")
|
|
||||||
memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
|
memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
|
||||||
if dst != src {
|
if dst != src {
|
||||||
d, s := ([^]byte)(dst), ([^]byte)(src)
|
d, s := ([^]byte)(dst), ([^]byte)(src)
|
||||||
@@ -52,8 +50,7 @@ when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" {
|
|||||||
return dst
|
return dst
|
||||||
|
|
||||||
}
|
}
|
||||||
@(export)
|
@(link_name="memcpy", linkage=RUNTIME_LINKAGE, require)
|
||||||
@(link_name="memcpy")
|
|
||||||
memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
|
memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
|
||||||
if dst != src {
|
if dst != src {
|
||||||
d, s := ([^]byte)(dst), ([^]byte)(src)
|
d, s := ([^]byte)(dst), ([^]byte)(src)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
//+build wasm32
|
//+build wasm32
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
@(link_name="__ashlti3")
|
@(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
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ windows_trap_type_assertion :: proc "contextless" () -> ! {
|
|||||||
windows_trap_array_bounds()
|
windows_trap_array_bounds()
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private, require, link_name="_fltused") _fltused: i32 = 0x9875
|
@(private, export, link_name="_fltused") _fltused: i32 = 0x9875
|
||||||
|
|
||||||
@(private, require, link_name="_tls_index") _tls_index: u32
|
@(private, export, link_name="_tls_index") _tls_index: u32
|
||||||
@(private, require, link_name="_tls_array") _tls_array: u32
|
@(private, export, link_name="_tls_array") _tls_array: u32
|
||||||
|
|||||||
+17
-1
@@ -730,7 +730,6 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
|||||||
if (ac.set_cold) {
|
if (ac.set_cold) {
|
||||||
e->flags |= EntityFlag_Cold;
|
e->flags |= EntityFlag_Cold;
|
||||||
}
|
}
|
||||||
|
|
||||||
e->Procedure.optimization_mode = cast(ProcedureOptimizationMode)ac.optimization_mode;
|
e->Procedure.optimization_mode = cast(ProcedureOptimizationMode)ac.optimization_mode;
|
||||||
|
|
||||||
|
|
||||||
@@ -760,6 +759,22 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
|||||||
|
|
||||||
bool is_foreign = e->Procedure.is_foreign;
|
bool is_foreign = e->Procedure.is_foreign;
|
||||||
bool is_export = e->Procedure.is_export;
|
bool is_export = e->Procedure.is_export;
|
||||||
|
|
||||||
|
if (ac.linkage.len != 0) {
|
||||||
|
if (ac.linkage == "internal") { e->flags |= EntityFlag_CustomLinkage_Internal; }
|
||||||
|
else if (ac.linkage == "strong") { e->flags |= EntityFlag_CustomLinkage_Strong; }
|
||||||
|
else if (ac.linkage == "weak") { e->flags |= EntityFlag_CustomLinkage_Weak; }
|
||||||
|
else if (ac.linkage == "link_once") { e->flags |= EntityFlag_CustomLinkage_LinkOnce; }
|
||||||
|
|
||||||
|
if (is_foreign && (e->flags & EntityFlag_CustomLinkage_Internal)) {
|
||||||
|
error(e->token, "A foreign procedure may not have an \"internal\" linkage");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ac.require_declaration) {
|
||||||
|
e->flags |= EntityFlag_Require;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (e->pkg != nullptr && e->token.string == "main") {
|
if (e->pkg != nullptr && e->token.string == "main") {
|
||||||
if (pt->param_count != 0 ||
|
if (pt->param_count != 0 ||
|
||||||
@@ -943,6 +958,7 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast *type_expr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ac.require_declaration) {
|
if (ac.require_declaration) {
|
||||||
|
e->flags |= EntityFlag_Require;
|
||||||
mpmc_enqueue(&ctx->info->required_global_variable_queue, e);
|
mpmc_enqueue(&ctx->info->required_global_variable_queue, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+53
-2
@@ -783,6 +783,7 @@ void init_universal(void) {
|
|||||||
add_global_bool_constant("ODIN_DEFAULT_TO_NIL_ALLOCATOR", bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR);
|
add_global_bool_constant("ODIN_DEFAULT_TO_NIL_ALLOCATOR", bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR);
|
||||||
add_global_bool_constant("ODIN_NO_DYNAMIC_LITERALS", bc->no_dynamic_literals);
|
add_global_bool_constant("ODIN_NO_DYNAMIC_LITERALS", bc->no_dynamic_literals);
|
||||||
add_global_bool_constant("ODIN_NO_CRT", bc->no_crt);
|
add_global_bool_constant("ODIN_NO_CRT", bc->no_crt);
|
||||||
|
add_global_bool_constant("ODIN_USE_SEPARATE_MODULES", bc->use_separate_modules);
|
||||||
add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test);
|
add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test);
|
||||||
|
|
||||||
|
|
||||||
@@ -1388,7 +1389,9 @@ bool could_entity_be_lazy(Entity *e, DeclInfo *d) {
|
|||||||
return false;
|
return false;
|
||||||
} else if (name == "init") {
|
} else if (name == "init") {
|
||||||
return false;
|
return false;
|
||||||
}
|
} else if (name == "linkage") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2658,6 +2661,32 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
} else if (name == "linkage") {
|
||||||
|
ExactValue ev = check_decl_attribute_value(c, value);
|
||||||
|
if (ev.kind != ExactValue_String) {
|
||||||
|
error(value, "Expected either a string 'linkage'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String linkage = ev.value_string;
|
||||||
|
if (linkage == "internal" ||
|
||||||
|
linkage == "strong" ||
|
||||||
|
linkage == "weak" ||
|
||||||
|
linkage == "link_once") {
|
||||||
|
ac->linkage = linkage;
|
||||||
|
} else {
|
||||||
|
error(elem, "Invalid linkage '%.*s'. Valid kinds:", LIT(linkage));
|
||||||
|
error_line("\tinternal\n");
|
||||||
|
error_line("\tstrong\n");
|
||||||
|
error_line("\tweak\n");
|
||||||
|
error_line("\tlink_once\n");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if (name == "require") {
|
||||||
|
if (value != nullptr) {
|
||||||
|
error(elem, "'require' does not have any parameters");
|
||||||
|
}
|
||||||
|
ac->require_declaration = true;
|
||||||
|
return true;
|
||||||
} else if (name == "init") {
|
} else if (name == "init") {
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
error(value, "'%.*s' expects no parameter, or a string literal containing \"file\" or \"package\"", LIT(name));
|
error(value, "'%.*s' expects no parameter, or a string literal containing \"file\" or \"package\"", LIT(name));
|
||||||
@@ -2894,7 +2923,7 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) {
|
|||||||
|
|
||||||
if (name == "require") {
|
if (name == "require") {
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
error(elem, "'static' does not have any parameters");
|
error(elem, "'require' does not have any parameters");
|
||||||
}
|
}
|
||||||
ac->require_declaration = true;
|
ac->require_declaration = true;
|
||||||
return true;
|
return true;
|
||||||
@@ -2912,6 +2941,26 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) {
|
|||||||
error(elem, "An exported variable cannot be thread local");
|
error(elem, "An exported variable cannot be thread local");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
} else if (name == "linkage") {
|
||||||
|
ExactValue ev = check_decl_attribute_value(c, value);
|
||||||
|
if (ev.kind != ExactValue_String) {
|
||||||
|
error(value, "Expected either a string 'linkage'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String linkage = ev.value_string;
|
||||||
|
if (linkage == "internal" ||
|
||||||
|
linkage == "strong" ||
|
||||||
|
linkage == "weak" ||
|
||||||
|
linkage == "link_once") {
|
||||||
|
ac->linkage = linkage;
|
||||||
|
} else {
|
||||||
|
error(elem, "Invalid linkage '%.*s'. Valid kinds:", LIT(linkage));
|
||||||
|
error_line("\tinternal\n");
|
||||||
|
error_line("\tstrong\n");
|
||||||
|
error_line("\tweak\n");
|
||||||
|
error_line("\tlink_once\n");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
} else if (name == "link_name") {
|
} else if (name == "link_name") {
|
||||||
if (ev.kind == ExactValue_String) {
|
if (ev.kind == ExactValue_String) {
|
||||||
ac->link_name = ev.value_string;
|
ac->link_name = ev.value_string;
|
||||||
@@ -3959,6 +4008,8 @@ DECL_ATTRIBUTE_PROC(foreign_import_decl_attribute) {
|
|||||||
if (name == "force" || name == "require") {
|
if (name == "force" || name == "require") {
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
error(elem, "Expected no parameter for '%.*s'", LIT(name));
|
error(elem, "Expected no parameter for '%.*s'", LIT(name));
|
||||||
|
} else if (name == "force") {
|
||||||
|
warning(elem, "'force' is deprecated and is identical to 'require'");
|
||||||
}
|
}
|
||||||
ac->require_declaration = true;
|
ac->require_declaration = true;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ struct AttributeContext {
|
|||||||
String link_name;
|
String link_name;
|
||||||
String link_prefix;
|
String link_prefix;
|
||||||
String link_section;
|
String link_section;
|
||||||
|
String linkage;
|
||||||
isize init_expr_list_count;
|
isize init_expr_list_count;
|
||||||
String thread_local_model;
|
String thread_local_model;
|
||||||
String deprecated_message;
|
String deprecated_message;
|
||||||
|
|||||||
@@ -76,6 +76,12 @@ enum EntityFlag : u64 {
|
|||||||
EntityFlag_Init = 1ull<<31,
|
EntityFlag_Init = 1ull<<31,
|
||||||
|
|
||||||
EntityFlag_CustomLinkName = 1ull<<40,
|
EntityFlag_CustomLinkName = 1ull<<40,
|
||||||
|
EntityFlag_CustomLinkage_Internal = 1ull<<41,
|
||||||
|
EntityFlag_CustomLinkage_Strong = 1ull<<42,
|
||||||
|
EntityFlag_CustomLinkage_Weak = 1ull<<43,
|
||||||
|
EntityFlag_CustomLinkage_LinkOnce = 1ull<<44,
|
||||||
|
|
||||||
|
EntityFlag_Require = 1ull<<50,
|
||||||
|
|
||||||
EntityFlag_Overridden = 1ull<<63,
|
EntityFlag_Overridden = 1ull<<63,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1498,6 +1498,8 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
LLVMSetLinkage(g.value, LLVMInternalLinkage);
|
LLVMSetLinkage(g.value, LLVMInternalLinkage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lb_set_linkage_from_entity_flags(m, g.value, e->flags);
|
||||||
|
|
||||||
if (e->Variable.link_section.len > 0) {
|
if (e->Variable.link_section.len > 0) {
|
||||||
LLVMSetSection(g.value, alloc_cstring(permanent_allocator(), e->Variable.link_section));
|
LLVMSetSection(g.value, alloc_cstring(permanent_allocator(), e->Variable.link_section));
|
||||||
}
|
}
|
||||||
@@ -1675,7 +1677,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
for_array(i, gen->modules.entries) {
|
for_array(i, gen->modules.entries) {
|
||||||
lbModule *m = gen->modules.entries[i].value;
|
lbModule *m = gen->modules.entries[i].value;
|
||||||
|
|
||||||
lb_run_remove_unused_function_pass(m->mod);
|
lb_run_remove_unused_function_pass(m);
|
||||||
|
|
||||||
auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
|
auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
|
||||||
wd->m = m;
|
wd->m = m;
|
||||||
|
|||||||
@@ -605,4 +605,6 @@ char const *llvm_linkage_strings[] = {
|
|||||||
"common linkage",
|
"common linkage",
|
||||||
"linker private linkage",
|
"linker private linkage",
|
||||||
"linker private weak linkage"
|
"linker private weak linkage"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ODIN_METADATA_REQUIRE "odin-metadata-require", 21
|
||||||
|
|||||||
@@ -2692,3 +2692,16 @@ lbAddr lb_add_local_generated_temp(lbProcedure *p, Type *type, i64 min_alignment
|
|||||||
lb_try_update_alignment(res.addr, cast(unsigned)min_alignment);
|
lb_try_update_alignment(res.addr, cast(unsigned)min_alignment);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void lb_set_linkage_from_entity_flags(lbModule *m, LLVMValueRef value, u64 flags) {
|
||||||
|
if (flags & EntityFlag_CustomLinkage_Internal) {
|
||||||
|
LLVMSetLinkage(value, LLVMInternalLinkage);
|
||||||
|
} else if (flags & EntityFlag_CustomLinkage_Strong) {
|
||||||
|
LLVMSetLinkage(value, LLVMExternalLinkage);
|
||||||
|
} else if (flags & EntityFlag_CustomLinkage_Weak) {
|
||||||
|
LLVMSetLinkage(value, LLVMExternalWeakLinkage);
|
||||||
|
} else if (flags & EntityFlag_CustomLinkage_LinkOnce) {
|
||||||
|
LLVMSetLinkage(value, LLVMLinkOnceAnyLinkage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+11
-21
@@ -357,14 +357,14 @@ void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedure *p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void lb_run_remove_unused_function_pass(LLVMModuleRef mod) {
|
void lb_run_remove_unused_function_pass(lbModule *m) {
|
||||||
isize removal_count = 0;
|
isize removal_count = 0;
|
||||||
isize pass_count = 0;
|
isize pass_count = 0;
|
||||||
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_function = false;
|
||||||
for (LLVMValueRef func = LLVMGetFirstFunction(mod);
|
for (LLVMValueRef func = LLVMGetFirstFunction(m->mod);
|
||||||
func != nullptr;
|
func != nullptr;
|
||||||
/**/
|
/**/
|
||||||
) {
|
) {
|
||||||
@@ -382,30 +382,20 @@ void lb_run_remove_unused_function_pass(LLVMModuleRef mod) {
|
|||||||
// Ignore for the time being
|
// Ignore for the time being
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
LLVMLinkage linkage = LLVMGetLinkage(curr_func);
|
||||||
if (name == "memset" ||
|
if (linkage != LLVMInternalLinkage) {
|
||||||
name == "memmove" ||
|
|
||||||
name == "memcpy") {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (is_arch_wasm()) {
|
|
||||||
if (name == "__ashlti3") {
|
Entity **found = map_get(&m->procedure_values, hash_pointer(curr_func));
|
||||||
LLVMSetLinkage(curr_func, LLVMExternalLinkage);
|
if (found && *found) {
|
||||||
|
Entity *e = *found;
|
||||||
|
bool is_required = (e->flags & EntityFlag_Require) == EntityFlag_Require;
|
||||||
|
if (is_required) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMLinkage linkage = LLVMGetLinkage(curr_func);
|
|
||||||
|
|
||||||
switch (linkage) {
|
|
||||||
case LLVMExternalLinkage:
|
|
||||||
case LLVMDLLImportLinkage:
|
|
||||||
case LLVMDLLExportLinkage:
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
case LLVMInternalLinkage:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LLVMDeleteFunction(curr_func);
|
LLVMDeleteFunction(curr_func);
|
||||||
was_dead_function = true;
|
was_dead_function = true;
|
||||||
removal_count += 1;
|
removal_count += 1;
|
||||||
|
|||||||
@@ -203,6 +203,8 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lb_set_linkage_from_entity_flags(p->module, p->value, entity->flags);
|
||||||
|
|
||||||
|
|
||||||
if (p->is_foreign) {
|
if (p->is_foreign) {
|
||||||
lb_set_wasm_import_attributes(p->value, entity, p->name);
|
lb_set_wasm_import_attributes(p->value, entity, p->name);
|
||||||
|
|||||||
Reference in New Issue
Block a user