1
1
use super :: { backend_type:: to_backend_type, ctx:: BackendCtx , BackendError } ;
2
2
use llvm_sys:: {
3
3
core:: {
4
- LLVMAddGlobal , LLVMGetUndef , LLVMSetExternallyInitialized , LLVMSetInitializer ,
5
- LLVMSetLinkage , LLVMSetThreadLocal ,
4
+ LLVMAddGlobal , LLVMGetLinkage , LLVMGetNamedGlobal , LLVMGetThreadLocalMode , LLVMGetUndef ,
5
+ LLVMIsExternallyInitialized , LLVMSetExternallyInitialized , LLVMSetInitializer ,
6
+ LLVMSetLinkage , LLVMSetThreadLocalMode ,
6
7
} ,
7
- LLVMLinkage ,
8
+ LLVMLinkage , LLVMThreadLocalMode ,
8
9
} ;
9
10
use std:: ffi:: CString ;
10
11
@@ -13,9 +14,39 @@ pub unsafe fn create_globals(ctx: &mut BackendCtx) -> Result<(), BackendError> {
13
14
let backend_type = to_backend_type ( ctx. for_making_type ( ) , & global. ir_type ) ?;
14
15
15
16
let name = CString :: new ( global. mangled_name . as_bytes ( ) ) . unwrap ( ) ;
17
+ let existing = LLVMGetNamedGlobal ( ctx. backend_module . get ( ) , name. as_ptr ( ) ) ;
18
+
19
+ if !existing. is_null ( ) {
20
+ let existing_linkage = LLVMGetLinkage ( existing) ;
21
+
22
+ if ( global. exposure . is_exposed ( ) || global. is_foreign )
23
+ && existing_linkage != LLVMLinkage :: LLVMExternalLinkage
24
+ {
25
+ LLVMSetLinkage ( existing, LLVMLinkage :: LLVMExternalLinkage ) ;
26
+ }
27
+
28
+ if global. is_thread_local
29
+ && LLVMGetThreadLocalMode ( existing) == LLVMThreadLocalMode :: LLVMNotThreadLocal
30
+ {
31
+ LLVMSetThreadLocalMode ( existing, LLVMThreadLocalMode :: LLVMGeneralDynamicTLSModel ) ;
32
+ }
33
+
34
+ if LLVMIsExternallyInitialized ( existing) == 0 && !global. is_foreign {
35
+ // In order to prevent aggressive optimizations from removing necessary internal global
36
+ // variables, we'll mark them as externally-initialized
37
+ LLVMSetExternallyInitialized ( existing, true . into ( ) ) ;
38
+ LLVMSetInitializer ( existing, LLVMGetUndef ( backend_type) ) ;
39
+ }
40
+
41
+ // NOTE: We assume the two global variables have the same type here,
42
+ // if they aren't, then we technically don't even to report it.
43
+ ctx. globals . insert ( * global_ref, existing) ;
44
+ continue ;
45
+ }
46
+
16
47
let backend_global = LLVMAddGlobal ( ctx. backend_module . get ( ) , backend_type, name. as_ptr ( ) ) ;
17
48
18
- let linkage = if global. exposure . is_exposed ( ) {
49
+ let linkage = if global. exposure . is_exposed ( ) || global . is_foreign {
19
50
LLVMLinkage :: LLVMExternalLinkage
20
51
} else {
21
52
LLVMLinkage :: LLVMInternalLinkage
@@ -24,7 +55,10 @@ pub unsafe fn create_globals(ctx: &mut BackendCtx) -> Result<(), BackendError> {
24
55
LLVMSetLinkage ( backend_global, linkage) ;
25
56
26
57
if global. is_thread_local {
27
- LLVMSetThreadLocal ( backend_global, true . into ( ) ) ;
58
+ LLVMSetThreadLocalMode (
59
+ backend_global,
60
+ LLVMThreadLocalMode :: LLVMGeneralDynamicTLSModel ,
61
+ ) ;
28
62
}
29
63
30
64
if !global. is_foreign {
0 commit comments