Skip to content

Commit 391e8e4

Browse files
committed
(wip) Feat: fix debug info generation on opt=3
1 parent 4728fe0 commit 391e8e4

File tree

4 files changed

+80
-36
lines changed

4 files changed

+80
-36
lines changed

crates/cuda_builder/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ pub struct CudaBuilder {
117117
///
118118
/// `true` by default.
119119
pub override_libm: bool,
120+
pub debug: bool,
120121
}
121122

122123
impl CudaBuilder {
@@ -136,9 +137,15 @@ impl CudaBuilder {
136137
emit: None,
137138
optix: false,
138139
override_libm: true,
140+
debug: false,
139141
}
140142
}
141143

144+
pub fn debug(mut self, debug: bool) -> Self {
145+
self.debug = debug;
146+
self
147+
}
148+
142149
/// Whether to compile the gpu crate for release.
143150
pub fn release(mut self, release: bool) -> Self {
144151
self.release = release;
@@ -378,6 +385,11 @@ fn invoke_rustc(builder: &CudaBuilder) -> Result<PathBuf, CudaBuilderError> {
378385
llvm_args.push("--override-libm".to_string());
379386
}
380387

388+
if builder.debug {
389+
rustflags.push("-Cdebuginfo=1".to_string());
390+
llvm_args.push("-generate-line-info".to_string());
391+
}
392+
381393
let llvm_args = llvm_args.join(" ");
382394
if !llvm_args.is_empty() {
383395
rustflags.push(["-Cllvm-args=", &llvm_args].concat());

crates/rustc_codegen_nvvm/src/back.rs

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,35 @@ pub fn target_machine_factory(
128128
})
129129
}
130130

131+
pub extern "C" fn demangle_callback(
132+
input_ptr: *const c_char,
133+
input_len: size_t,
134+
output_ptr: *mut c_char,
135+
output_len: size_t,
136+
) -> size_t {
137+
let input = unsafe { slice::from_raw_parts(input_ptr as *const u8, input_len as usize) };
138+
139+
let input = match std::str::from_utf8(input) {
140+
Ok(s) => s,
141+
Err(_) => return 0,
142+
};
143+
144+
let output = unsafe { slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) };
145+
let mut cursor = io::Cursor::new(output);
146+
147+
let demangled = match rustc_demangle::try_demangle(input) {
148+
Ok(d) => d,
149+
Err(_) => return 0,
150+
};
151+
152+
if write!(cursor, "{:#}", demangled).is_err() {
153+
// Possible only if provided buffer is not big enough
154+
return 0;
155+
}
156+
157+
cursor.position() as size_t
158+
}
159+
131160
/// Compile a single module (in an nvvm context this means getting the llvm bitcode out of it)
132161
pub(crate) unsafe fn codegen(
133162
cgcx: &CodegenContext<NvvmCodegenBackend>,
@@ -168,37 +197,6 @@ pub(crate) unsafe fn codegen(
168197
.temp_path(OutputType::LlvmAssembly, module_name);
169198
let out_c = path_to_c_string(&out);
170199

171-
extern "C" fn demangle_callback(
172-
input_ptr: *const c_char,
173-
input_len: size_t,
174-
output_ptr: *mut c_char,
175-
output_len: size_t,
176-
) -> size_t {
177-
let input =
178-
unsafe { slice::from_raw_parts(input_ptr as *const u8, input_len as usize) };
179-
180-
let input = match std::str::from_utf8(input) {
181-
Ok(s) => s,
182-
Err(_) => return 0,
183-
};
184-
185-
let output =
186-
unsafe { slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) };
187-
let mut cursor = io::Cursor::new(output);
188-
189-
let demangled = match rustc_demangle::try_demangle(input) {
190-
Ok(d) => d,
191-
Err(_) => return 0,
192-
};
193-
194-
if write!(cursor, "{:#}", demangled).is_err() {
195-
// Possible only if provided buffer is not big enough
196-
return 0;
197-
}
198-
199-
cursor.position() as size_t
200-
}
201-
202200
let result = llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback);
203201

204202
result.into_result().map_err(|()| {

crates/rustc_codegen_nvvm/src/llvm.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
// in case we need them in the future for things like debug info or LTO.
1818
#![allow(dead_code)]
1919

20-
use libc::{c_char, c_uint, size_t};
20+
use libc::{c_char, c_uint, c_void, size_t};
2121
use libc::{c_int, c_ulonglong};
2222
use std::ffi::{CStr, CString};
2323
use std::fmt;
@@ -1849,6 +1849,12 @@ extern "C" {
18491849
len: usize,
18501850
out_len: &mut usize,
18511851
) -> *const u8;
1852+
pub(crate) fn LLVMRustThinLTOGetDICompileUnit(
1853+
M: &Module,
1854+
CU1: &mut *mut c_void,
1855+
CU2: &mut *mut c_void,
1856+
);
1857+
pub(crate) fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void);
18521858

18531859
pub(crate) fn LLVMRustAddDereferenceableAttr(Fn: &Value, index: c_uint, bytes: u64);
18541860
pub(crate) fn LLVMRustAddDereferenceableOrNullAttr(Fn: &Value, index: c_uint, bytes: u64);

crates/rustc_codegen_nvvm/src/nvvm.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ use crate::lto::ThinBuffer;
66
use find_cuda_helper::find_cuda_root;
77
use nvvm::*;
88
use rustc_codegen_ssa::traits::ThinBufferMethods;
9-
use rustc_session::Session;
9+
use rustc_session::{config::DebugInfo, Session};
1010
use std::ffi::OsStr;
1111
use std::fmt::Display;
12-
use std::fs;
1312
use std::marker::PhantomData;
1413
use std::path::Path;
14+
use std::{fs, ptr};
1515
use tracing::debug;
1616

1717
// see libintrinsics.ll on what this is.
@@ -71,6 +71,24 @@ pub fn codegen_bitcode_modules(
7171
unsafe {
7272
internalize_pass(module, llcx);
7373
dce_pass(module);
74+
75+
if sess.opts.debuginfo != DebugInfo::None {
76+
cleanup_dicompileunit(module);
77+
}
78+
79+
let (dbg_major, dbg_minor) = nvvm::dbg_version();
80+
81+
// needed for debug info or else nvvm complains about ir version mismatch for some
82+
// reason. It works if you don't use debug info though...
83+
let ty_i32 = LLVMInt32TypeInContext(llcx);
84+
let major = LLVMConstInt(ty_i32, major as u64, False);
85+
let minor = LLVMConstInt(ty_i32, minor as u64, False);
86+
let dbg_major = LLVMConstInt(ty_i32, dbg_major as u64, False);
87+
let dbg_minor = LLVMConstInt(ty_i32, dbg_minor as u64, False);
88+
let vals = vec![major, minor, dbg_major, dbg_minor];
89+
let node = LLVMMDNodeInContext(llcx, vals.as_ptr(), vals.len() as u32);
90+
91+
LLVMAddNamedMetadataOperand(module, "nvvmir.version\0".as_ptr().cast(), node);
7492
}
7593
let buf = ThinBuffer::new(module);
7694

@@ -106,9 +124,12 @@ pub fn codegen_bitcode_modules(
106124

107125
let res = match prog.compile(opts) {
108126
Ok(b) => b,
109-
Err(_) => {
127+
Err(error) => {
110128
// this should never happen, if it does, something went really bad or its a bug on libnvvm's end
111-
panic!("libnvvm returned an error that was not previously caught by the verifier");
129+
panic!(
130+
"libnvvm returned an error that was not previously caught by the verifier: {:?}",
131+
error
132+
);
112133
}
113134
};
114135

@@ -131,6 +152,13 @@ pub fn find_libdevice() -> Option<Vec<u8>> {
131152
}
132153
}
133154

155+
unsafe fn cleanup_dicompileunit(module: &Module) {
156+
let mut cu1 = ptr::null_mut();
157+
let mut cu2 = ptr::null_mut();
158+
LLVMRustThinLTOGetDICompileUnit(module, &mut cu1, &mut cu2);
159+
LLVMRustThinLTOPatchDICompileUnit(module, cu1);
160+
}
161+
134162
// Merging and DCE (dead code elimination) logic. Inspired a lot by rust-ptx-linker.
135163
//
136164
// This works in a couple of steps starting from the bitcode of every single module (crate), then:

0 commit comments

Comments
 (0)