|
| 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 | +} |
0 commit comments