compile a single codegen unit. This involves getting its llvm module and doing some housekeeping such as monomorphizing items and using RAUW on statics. This codegenned module is then given to other functions to "compile it" (in our case not really because nvvm does codegen on all the modules at once) and then link it (once again, nvvm does linking and codegen in a single step)
(tcx: TyCtxt<'_>, cgu_name: Symbol)
| 238 | /// codegen on all the modules at once) and then link it (once again, nvvm does linking and codegen |
| 239 | /// in a single step) |
| 240 | pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen<LlvmMod>, u64) { |
| 241 | let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); |
| 242 | let (module, _) = tcx.dep_graph.with_task( |
| 243 | dep_node, |
| 244 | tcx, |
| 245 | cgu_name, |
| 246 | module_codegen, |
| 247 | Some(dep_graph::hash_result), |
| 248 | ); |
| 249 | |
| 250 | fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<LlvmMod> { |
| 251 | let cgu = tcx.codegen_unit(cgu_name); |
| 252 | |
| 253 | // Instantiate monomorphizations without filling out definitions yet... |
| 254 | let llvm_module = LlvmMod::new(&cgu_name.as_str()); |
| 255 | { |
| 256 | let cx = CodegenCx::new(tcx, cgu, &llvm_module); |
| 257 | |
| 258 | let mono_items = cx.codegen_unit.items_in_deterministic_order(cx.tcx); |
| 259 | |
| 260 | for &(mono_item, (linkage, visibility)) in &mono_items { |
| 261 | mono_item.predefine::<Builder<'_, '_, '_>>(&cx, linkage, visibility); |
| 262 | } |
| 263 | |
| 264 | // ... and now that we have everything pre-defined, fill out those definitions. |
| 265 | for &(mono_item, _) in &mono_items { |
| 266 | if let MonoItem::Fn(func) = mono_item { |
| 267 | define_or_override_fn(func, &cx); |
| 268 | } else { |
| 269 | mono_item.define::<Builder<'_, '_, '_>>(&cx); |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | // a main function for gpu kernels really makes no sense but |
| 274 | // codegen it anyways. |
| 275 | // sanitize attrs are not allowed in nvvm so do nothing further. |
| 276 | maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx); |
| 277 | |
| 278 | // Run replace-all-uses-with for statics that need it |
| 279 | for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() { |
| 280 | unsafe { |
| 281 | let bitcast = llvm::LLVMConstPointerCast(new_g, cx.val_ty(old_g)); |
| 282 | llvm::LLVMReplaceAllUsesWith(old_g, bitcast); |
| 283 | llvm::LLVMDeleteGlobal(old_g); |
| 284 | } |
| 285 | } |
| 286 | |
| 287 | // Create the llvm.used and llvm.compiler.used variables. |
| 288 | if !cx.used_statics().borrow().is_empty() { |
| 289 | cx.create_used_variable(); |
| 290 | } |
| 291 | if !cx.compiler_used_statics().borrow().is_empty() { |
| 292 | cx.create_compiler_used_variable(); |
| 293 | } |
| 294 | |
| 295 | // Finalize debuginfo |
| 296 | if cx.sess().opts.debuginfo != DebugInfo::None { |
| 297 | cx.debuginfo_finalize(); |
no test coverage detected