Skip to content

Commit 28d1269

Browse files
committed
Feat: add a way to export the final llvm ir fed to libnvvm
1 parent ef4fcc8 commit 28d1269

File tree

5 files changed

+40
-5
lines changed

5 files changed

+40
-5
lines changed

crates/cuda_builder/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ pub struct CudaBuilder {
136136
pub debug: DebugInfo,
137137
/// Additional arguments passed to cargo during `cargo build`.
138138
pub build_args: Vec<String>,
139+
/// An optional path where to dump LLVM IR of the final output the codegen will feed to libnvvm. Usually
140+
/// used for debugging.
141+
pub final_module_path: Option<PathBuf>,
139142
}
140143

141144
impl CudaBuilder {
@@ -156,6 +159,7 @@ impl CudaBuilder {
156159
override_libm: true,
157160
debug: DebugInfo::None,
158161
build_args: vec![],
162+
final_module_path: None,
159163
}
160164
}
161165

@@ -282,6 +286,13 @@ impl CudaBuilder {
282286
self
283287
}
284288

289+
/// An optional path where to dump LLVM IR of the final output the codegen will feed to libnvvm. Usually
290+
/// used for debugging.
291+
pub fn final_module_path(mut self, path: impl AsRef<Path>) -> Self {
292+
self.final_module_path = Some(path.as_ref().to_path_buf());
293+
self
294+
}
295+
285296
/// Runs rustc to build the codegen and codegens the gpu crate, returning the path of the final
286297
/// ptx file. If [`ptx_file_copy_path`](Self::ptx_file_copy_path) is set, this returns the copied path.
287298
pub fn build(self) -> Result<PathBuf, CudaBuilderError> {
@@ -404,6 +415,11 @@ fn invoke_rustc(builder: &CudaBuilder) -> Result<PathBuf, CudaBuilderError> {
404415
llvm_args.push("--override-libm".to_string());
405416
}
406417

418+
if let Some(path) = &builder.final_module_path {
419+
llvm_args.push("--final-module-path".to_string());
420+
llvm_args.push(path.to_str().unwrap().to_string());
421+
}
422+
407423
if builder.debug != DebugInfo::None {
408424
let (nvvm_flag, rustc_flag) = builder.debug.into_nvvm_and_rustc_options();
409425
llvm_args.push(nvvm_flag);

crates/rustc_codegen_nvvm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Notable changes to this project will be documented in this file.
66

77
- Added symbols for cuda_std to link to for warp intrinsics.
88
- Completely remove support for 32-bit CUDA (it was broken and it is essentially unused nowadays).
9+
- Add a way to export the final llvm ir module fed to libnvvm.
910

1011
## 0.2.3 - 1/2/22
1112

crates/rustc_codegen_nvvm/src/context.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use std::cell::{Cell, RefCell};
3131
use std::ffi::CStr;
3232
use std::hash::BuildHasherDefault;
3333
use std::os::raw::c_char;
34+
use std::path::PathBuf;
3435
use std::ptr::null;
3536
use std::str::FromStr;
3637
use tracing::{debug, trace};
@@ -523,6 +524,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
523524
pub struct CodegenArgs {
524525
pub nvvm_options: Vec<NvvmOption>,
525526
pub override_libm: bool,
527+
pub final_module_path: Option<PathBuf>,
526528
}
527529

528530
impl CodegenArgs {
@@ -535,11 +537,15 @@ impl CodegenArgs {
535537
// TODO: replace this with a "proper" arg parser.
536538
let mut cg_args = Self::default();
537539

538-
for arg in args {
540+
for (idx, arg) in args.iter().enumerate() {
539541
if let Ok(flag) = NvvmOption::from_str(arg) {
540542
cg_args.nvvm_options.push(flag);
541543
} else if arg == "--override-libm" {
542544
cg_args.override_libm = true;
545+
} else if arg == "--final-module-path" {
546+
cg_args.final_module_path = Some(PathBuf::from(
547+
args.get(idx + 1).expect("No path for --final-module-path"),
548+
));
543549
}
544550
}
545551

crates/rustc_codegen_nvvm/src/link.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,9 @@ fn codegen_into_ptx_file(
256256
// modules to nvvm to make a final ptx file
257257

258258
// we need to actually parse the codegen args again, because codegencx is not available at link time.
259-
let nvvm_opts = CodegenArgs::from_session(sess).nvvm_options;
259+
let args = CodegenArgs::from_session(sess);
260260

261-
let ptx_bytes = match crate::nvvm::codegen_bitcode_modules(&nvvm_opts, sess, modules, cx.llcx) {
261+
let ptx_bytes = match crate::nvvm::codegen_bitcode_modules(&args, sess, modules, cx.llcx) {
262262
Ok(bytes) => bytes,
263263
Err(err) => {
264264
// TODO(RDambrosio016): maybe include the nvvm log with this fatal error

crates/rustc_codegen_nvvm/src/nvvm.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
//! Final steps in codegen, coalescing modules and feeding them to libnvvm.
22
3+
use crate::back::demangle_callback;
34
use crate::builder::unnamed;
5+
use crate::context::CodegenArgs;
46
use crate::llvm::*;
57
use crate::lto::ThinBuffer;
68
use find_cuda_helper::find_cuda_root;
79
use nvvm::*;
810
use rustc_codegen_ssa::traits::ThinBufferMethods;
11+
use rustc_fs_util::path_to_c_string;
912
use rustc_session::{config::DebugInfo, Session};
1013
use std::ffi::OsStr;
1114
use std::fmt::Display;
@@ -50,7 +53,7 @@ impl Display for CodegenErr {
5053
/// Note that this will implicitly try to find libdevice and add it, so don't do that
5154
/// step before this. It will fatal error if it cannot find it.
5255
pub fn codegen_bitcode_modules(
53-
opts: &[NvvmOption],
56+
args: &CodegenArgs,
5457
sess: &Session,
5558
modules: Vec<Vec<u8>>,
5659
llcx: &Context,
@@ -89,7 +92,16 @@ pub fn codegen_bitcode_modules(
8992
let node = LLVMMDNodeInContext(llcx, vals.as_ptr(), vals.len() as u32);
9093

9194
LLVMAddNamedMetadataOperand(module, "nvvmir.version\0".as_ptr().cast(), node);
95+
96+
if let Some(path) = &args.final_module_path {
97+
let out_c = path_to_c_string(path);
98+
let result = LLVMRustPrintModule(module, out_c.as_ptr(), demangle_callback);
99+
result
100+
.into_result()
101+
.expect("Failed to write final llvm module output");
102+
}
92103
}
104+
93105
let buf = ThinBuffer::new(module);
94106

95107
prog.add_module(buf.data(), "merged".to_string())?;
@@ -122,7 +134,7 @@ pub fn codegen_bitcode_modules(
122134
);
123135
}
124136

125-
let res = match prog.compile(opts) {
137+
let res = match prog.compile(&args.nvvm_options) {
126138
Ok(b) => b,
127139
Err(error) => {
128140
// this should never happen, if it does, something went really bad or its a bug on libnvvm's end

0 commit comments

Comments
 (0)