Skip to content

Commit 0d534d8

Browse files
committed
Added support for linking against C global variables defined within Adept code from Adept code
1 parent ec0b111 commit 0d534d8

File tree

3 files changed

+57
-5
lines changed

3 files changed

+57
-5
lines changed

Diff for: src/llvm_backend/globals.rs

+39-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use super::{backend_type::to_backend_type, ctx::BackendCtx, BackendError};
22
use llvm_sys::{
33
core::{
4-
LLVMAddGlobal, LLVMGetUndef, LLVMSetExternallyInitialized, LLVMSetInitializer,
5-
LLVMSetLinkage, LLVMSetThreadLocal,
4+
LLVMAddGlobal, LLVMGetLinkage, LLVMGetNamedGlobal, LLVMGetThreadLocalMode, LLVMGetUndef,
5+
LLVMIsExternallyInitialized, LLVMSetExternallyInitialized, LLVMSetInitializer,
6+
LLVMSetLinkage, LLVMSetThreadLocalMode,
67
},
7-
LLVMLinkage,
8+
LLVMLinkage, LLVMThreadLocalMode,
89
};
910
use std::ffi::CString;
1011

@@ -13,9 +14,39 @@ pub unsafe fn create_globals(ctx: &mut BackendCtx) -> Result<(), BackendError> {
1314
let backend_type = to_backend_type(ctx.for_making_type(), &global.ir_type)?;
1415

1516
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+
1647
let backend_global = LLVMAddGlobal(ctx.backend_module.get(), backend_type, name.as_ptr());
1748

18-
let linkage = if global.exposure.is_exposed() {
49+
let linkage = if global.exposure.is_exposed() || global.is_foreign {
1950
LLVMLinkage::LLVMExternalLinkage
2051
} else {
2152
LLVMLinkage::LLVMInternalLinkage
@@ -24,7 +55,10 @@ pub unsafe fn create_globals(ctx: &mut BackendCtx) -> Result<(), BackendError> {
2455
LLVMSetLinkage(backend_global, linkage);
2556

2657
if global.is_thread_local {
27-
LLVMSetThreadLocal(backend_global, true.into());
58+
LLVMSetThreadLocalMode(
59+
backend_global,
60+
LLVMThreadLocalMode::LLVMGeneralDynamicTLSModel,
61+
);
2862
}
2963

3064
if !global.is_foreign {

Diff for: tests/success/global_variables_exposed/_.adept

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
pragma => adept("3.0")
3+
4+
#[foreign]
5+
func printf(format ptr#char, ...) int
6+
7+
#[foreign]
8+
special_value int
9+
10+
func main {
11+
special_value = 1234
12+
printf(c"special_value = %d\n", special_value)
13+
}
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
#[private, exposed]
3+
special_value int
4+

0 commit comments

Comments
 (0)