Skip to content

Commit 12ea74b

Browse files
committed
postpone wrapper generation
1 parent ed8ae06 commit 12ea74b

File tree

6 files changed

+161
-1
lines changed

6 files changed

+161
-1
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::{iter, ptr};
44

55
pub(crate) mod autodiff;
66
pub(crate) mod gpu_offload;
7+
pub(crate) mod gpu_wrapper;
78

89
use libc::{c_char, c_uint, size_t};
910
use rustc_abi as abi;

compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::llvm::{self, Linkage};
1212
use crate::{LlvmCodegenBackend, SimpleCx, attributes};
1313

1414
pub(crate) fn handle_gpu_code<'ll>(
15-
_cgcx: &CodegenContext<LlvmCodegenBackend>,
15+
cgcx: &CodegenContext<LlvmCodegenBackend>,
1616
cx: &'ll SimpleCx<'_>,
1717
) {
1818
let (offload_entry_ty, at_one, begin, update, end, tgt_bin_desc, fn_ty) = gen_globals(&cx);
@@ -27,6 +27,7 @@ pub(crate) fn handle_gpu_code<'ll>(
2727
}
2828
}
2929
gen_call_handling(&cx, &kernels, at_one, begin, update, end, tgt_bin_desc, fn_ty, &o_types);
30+
crate::builder::gpu_wrapper::gen_image_wrapper_module(&cgcx);
3031
}
3132

3233
// The meaning of the __tgt_offload_entry (as per llvm docs) is
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
use std::ffi::CString;
2+
3+
use llvm::Linkage::*;
4+
use rustc_abi::Align;
5+
use rustc_codegen_ssa::back::write::CodegenContext;
6+
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods;
7+
8+
use crate::builder::gpu_offload::*;
9+
use crate::llvm::{self, Visibility};
10+
use crate::{LlvmCodegenBackend, ModuleLlvm, SimpleCx};
11+
12+
pub(crate) fn create_struct_ty<'ll>(
13+
cx: &'ll SimpleCx<'_>,
14+
name: &str,
15+
tys: &[&'ll llvm::Type],
16+
) -> &'ll llvm::Type {
17+
let entry_struct_name = CString::new(name).unwrap();
18+
unsafe {
19+
let entry_struct = llvm::LLVMStructCreateNamed(cx.llcx, entry_struct_name.as_ptr());
20+
llvm::LLVMStructSetBody(entry_struct, tys.as_ptr(), tys.len() as u32, 0);
21+
entry_struct
22+
}
23+
}
24+
25+
// We don't copy types from other functions because we generate a new module and context.
26+
// Bringing in types from other contexts would likely cause issues.
27+
pub(crate) fn gen_image_wrapper_module(cgcx: &CodegenContext<LlvmCodegenBackend>) {
28+
let dl_cstr = CString::new("e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9").unwrap();
29+
let target_cstr = CString::new("amdgcn-amd-amdhsa").unwrap();
30+
let name = "offload.wrapper.module";
31+
let m: crate::ModuleLlvm =
32+
ModuleLlvm::new_simple(name, dl_cstr.into_raw(), target_cstr.into_raw(), &cgcx).unwrap();
33+
let cx = SimpleCx::new(m.llmod(), m.llcx, cgcx.pointer_size);
34+
let tptr = cx.type_ptr();
35+
let ti64 = cx.type_i64();
36+
let ti32 = cx.type_i32();
37+
let ti16 = cx.type_i16();
38+
39+
let entry_fields = [ti64, ti16, ti16, ti32, tptr, tptr, ti64, ti64, tptr];
40+
create_struct_ty(&cx, "__tgt_offload_entry", &entry_fields);
41+
create_struct_ty(&cx, "__tgt_device_image", &[tptr, tptr, tptr, tptr]);
42+
create_struct_ty(&cx, "__tgt_bin_desc", &[ti32, tptr, tptr, tptr]);
43+
44+
let offload_entry_ty = add_tgt_offload_entry(&cx);
45+
let offload_entry_arr = cx.type_array(offload_entry_ty, 0);
46+
47+
let c_name = CString::new("__start_omp_offloading_entries").unwrap();
48+
let llglobal = llvm::add_global(cx.llmod, offload_entry_arr, &c_name);
49+
llvm::set_global_constant(llglobal, true);
50+
llvm::set_linkage(llglobal, ExternalLinkage);
51+
llvm::set_visibility(llglobal, Visibility::Hidden);
52+
let c_name = CString::new("__stop_omp_offloading_entries").unwrap();
53+
let llglobal = llvm::add_global(cx.llmod, offload_entry_arr, &c_name);
54+
llvm::set_global_constant(llglobal, true);
55+
llvm::set_linkage(llglobal, ExternalLinkage);
56+
llvm::set_visibility(llglobal, Visibility::Hidden);
57+
58+
let c_name = CString::new("__dummy.omp_offloading_entries").unwrap();
59+
let llglobal = llvm::add_global(cx.llmod, offload_entry_arr, &c_name);
60+
llvm::set_global_constant(llglobal, true);
61+
llvm::set_linkage(llglobal, InternalLinkage);
62+
let c_section_name = CString::new("omp_offloading_entries").unwrap();
63+
llvm::set_section(llglobal, &c_section_name);
64+
let zeroinit = cx.const_null(offload_entry_arr);
65+
llvm::set_initializer(llglobal, zeroinit);
66+
67+
CString::new("llvm.compiler.used").unwrap();
68+
let arr_val = cx.const_array(tptr, &[llglobal]);
69+
let c_section_name = CString::new("llvm.metadata").unwrap();
70+
let llglobal = add_global(&cx, "llvm.compiler.used", arr_val, AppendingLinkage);
71+
llvm::set_section(llglobal, &c_section_name);
72+
llvm::set_global_constant(llglobal, false);
73+
74+
//@llvm.compiler.used = appending global [1 x ptr] [ptr @__dummy.omp_offloading_entries], section "llvm.metadata"
75+
76+
let mapper_fn_ty = cx.type_func(&[tptr], cx.type_void());
77+
crate::declare::declare_simple_fn(
78+
&cx,
79+
&"__tgt_unregister_lib",
80+
llvm::CallConv::CCallConv,
81+
llvm::UnnamedAddr::No,
82+
llvm::Visibility::Default,
83+
mapper_fn_ty,
84+
);
85+
crate::declare::declare_simple_fn(
86+
&cx,
87+
&"__tgt_register_lib",
88+
llvm::CallConv::CCallConv,
89+
llvm::UnnamedAddr::No,
90+
llvm::Visibility::Default,
91+
mapper_fn_ty,
92+
);
93+
crate::declare::declare_simple_fn(
94+
&cx,
95+
&"atexit",
96+
llvm::CallConv::CCallConv,
97+
llvm::UnnamedAddr::No,
98+
llvm::Visibility::Default,
99+
cx.type_func(&[tptr], ti32),
100+
);
101+
102+
let unknown_txt = "11111111111111";
103+
let c_entry_name = CString::new(unknown_txt).unwrap();
104+
let c_val = c_entry_name.as_bytes_with_nul();
105+
let initializer = crate::common::bytes_in_context(cx.llcx, c_val);
106+
let llglobal =
107+
add_unnamed_global(&cx, &".omp_offloading.device_image", initializer, InternalLinkage);
108+
let c_section_name = CString::new(".llvm.offloading").unwrap();
109+
llvm::set_section(llglobal, &c_section_name);
110+
llvm::set_alignment(llglobal, Align::EIGHT);
111+
112+
unsafe {
113+
llvm::LLVMPrintModuleToFile(
114+
cx.llmod,
115+
CString::new("rustmagic.openmp.image.wrapper.ll").unwrap().as_ptr(),
116+
std::ptr::null_mut(),
117+
);
118+
}
119+
}

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,23 @@ fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
160160
}
161161
}
162162

163+
// FIXME(offload): This method is not relying on a tcx. We might still want to try to share some of
164+
// the logic with create_module, e.g. the target_data_layout handling.
165+
pub(crate) unsafe fn create_simple_module<'ll>(
166+
llcx: &'ll llvm::Context,
167+
target_data_layout: *const i8,
168+
target_triple: *const i8,
169+
mod_name: &str,
170+
) -> &'ll llvm::Module {
171+
let mod_name = SmallCStr::new(mod_name);
172+
let llmod = unsafe { llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx) };
173+
unsafe {
174+
llvm::LLVMSetDataLayout(llmod, target_data_layout);
175+
llvm::LLVMSetTarget(llmod, target_triple);
176+
}
177+
llmod
178+
}
179+
163180
pub(crate) unsafe fn create_module<'ll>(
164181
tcx: TyCtxt<'_>,
165182
llcx: &'ll llvm::Context,

compiler/rustc_codegen_llvm/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,21 @@ unsafe impl Send for ModuleLlvm {}
399399
unsafe impl Sync for ModuleLlvm {}
400400

401401
impl ModuleLlvm {
402+
fn new_simple(
403+
name: &str,
404+
dl_cstr: *const i8,
405+
target_cstr: *const i8,
406+
cgcx: &CodegenContext<LlvmCodegenBackend>,
407+
) -> Result<Self, FatalError> {
408+
unsafe {
409+
let llcx = llvm::LLVMRustContextCreate(false);
410+
let llmod_raw = context::create_simple_module(llcx, dl_cstr, target_cstr, name);
411+
let dcx = cgcx.create_dcx();
412+
let tm = ModuleLlvm::tm_from_cgcx(cgcx, name, dcx.handle())?;
413+
Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
414+
}
415+
}
416+
402417
fn new(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
403418
unsafe {
404419
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,12 +1009,19 @@ unsafe extern "C" {
10091009
ModuleID: *const c_char,
10101010
C: &Context,
10111011
) -> &Module;
1012+
pub(crate) fn LLVMPrintModuleToFile(
1013+
M: &Module,
1014+
Name: *const c_char,
1015+
Error_message: *mut c_char,
1016+
);
10121017
pub(crate) fn LLVMCloneModule(M: &Module) -> &Module;
10131018

10141019
/// Data layout. See Module::getDataLayout.
10151020
pub(crate) fn LLVMGetDataLayoutStr(M: &Module) -> *const c_char;
10161021
pub(crate) fn LLVMSetDataLayout(M: &Module, Triple: *const c_char);
10171022

1023+
pub(crate) fn LLVMSetTarget(M: &Module, Name: *const c_char);
1024+
10181025
/// Append inline assembly to a module. See `Module::appendModuleInlineAsm`.
10191026
pub(crate) fn LLVMAppendModuleInlineAsm(
10201027
M: &Module,

0 commit comments

Comments
 (0)