Skip to content

Commit da61325

Browse files
authored
Rollup merge of rust-lang#64149 - eddyb:llvm-var-names, r=rkruppe
rustc_codegen_llvm: give names to non-alloca variable values. These names only matter when looking at LLVM IR, but they can help. When one value is used for multiple variables, I decided to combine the names. I chose `,` as a separator but maybe `=` or ` ` (space) are more appropriate. (LLVM names can contain any characters - if necessary they end up having quotes) As an example, this function: ```rust #[no_mangle] pub fn test(a: u32, b: u32) -> u32 { let c = a + b; let d = c; let e = d * a; e } ``` Used to produce this LLVM IR: ```llvm define i32 @test(i32 %a, i32 %b) unnamed_addr #0 { start: %0 = add i32 %a, %b %1 = mul i32 %0, %a ret i32 %1 } ``` But after this PR you get this: ```llvm define i32 @test(i32 %a, i32 %b) unnamed_addr #0 { start: %"c,d" = add i32 %a, %b %e = mul i32 %"c,d", %a ret i32 %e } ``` cc @nagisa @rkruppe
2 parents 7dcac19 + eedf555 commit da61325

File tree

6 files changed

+73
-13
lines changed

6 files changed

+73
-13
lines changed

src/librustc_codegen_llvm/debuginfo/mod.rs

+32-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, MirDebugScope, Variable
3232

3333
use libc::c_uint;
3434
use std::cell::RefCell;
35-
use std::ffi::CString;
35+
use std::ffi::{CStr, CString};
3636

3737
use syntax_pos::{self, Span, Pos};
3838
use syntax::ast;
@@ -224,8 +224,37 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
224224
gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
225225
}
226226

227-
fn set_value_name(&mut self, value: &'ll Value, name: &str) {
228-
let cname = SmallCStr::new(name);
227+
fn set_var_name(&mut self, value: &'ll Value, name: impl ToString) {
228+
// Avoid wasting time if LLVM value names aren't even enabled.
229+
if self.sess().fewer_names() {
230+
return;
231+
}
232+
233+
// Only function parameters and instructions are local to a function,
234+
// don't change the name of anything else (e.g. globals).
235+
let param_or_inst = unsafe {
236+
llvm::LLVMIsAArgument(value).is_some() ||
237+
llvm::LLVMIsAInstruction(value).is_some()
238+
};
239+
if !param_or_inst {
240+
return;
241+
}
242+
243+
let old_name = unsafe {
244+
CStr::from_ptr(llvm::LLVMGetValueName(value))
245+
};
246+
match old_name.to_str() {
247+
Ok("") => {}
248+
Ok(_) => {
249+
// Avoid replacing the name if it already exists.
250+
// While we could combine the names somehow, it'd
251+
// get noisy quick, and the usefulness is dubious.
252+
return;
253+
}
254+
Err(_) => return,
255+
}
256+
257+
let cname = CString::new(name.to_string()).unwrap();
229258
unsafe {
230259
llvm::LLVMSetValueName(value, cname.as_ptr());
231260
}

src/librustc_codegen_llvm/llvm/ffi.rs

+2
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,7 @@ extern "C" {
806806
pub fn LLVMRustRemoveFunctionAttributes(Fn: &Value, index: c_uint, attr: Attribute);
807807

808808
// Operations on parameters
809+
pub fn LLVMIsAArgument(Val: &Value) -> Option<&Value>;
809810
pub fn LLVMCountParams(Fn: &Value) -> c_uint;
810811
pub fn LLVMGetParam(Fn: &Value, Index: c_uint) -> &Value;
811812

@@ -818,6 +819,7 @@ extern "C" {
818819
pub fn LLVMDeleteBasicBlock(BB: &BasicBlock);
819820

820821
// Operations on instructions
822+
pub fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>;
821823
pub fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock;
822824

823825
// Operations on call sites

src/librustc_codegen_ssa/mir/mod.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -518,19 +518,19 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
518518
PassMode::Ignore(IgnoreMode::CVarArgs) => {}
519519
PassMode::Direct(_) => {
520520
let llarg = bx.get_param(llarg_idx);
521-
bx.set_value_name(llarg, &name);
521+
bx.set_var_name(llarg, &name);
522522
llarg_idx += 1;
523523
return local(
524524
OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout));
525525
}
526526
PassMode::Pair(..) => {
527-
let a = bx.get_param(llarg_idx);
528-
bx.set_value_name(a, &(name.clone() + ".0"));
529-
llarg_idx += 1;
527+
let (a, b) = (bx.get_param(llarg_idx), bx.get_param(llarg_idx + 1));
528+
llarg_idx += 2;
530529

531-
let b = bx.get_param(llarg_idx);
532-
bx.set_value_name(b, &(name + ".1"));
533-
llarg_idx += 1;
530+
// FIXME(eddyb) these are scalar components,
531+
// maybe extract the high-level fields?
532+
bx.set_var_name(a, format_args!("{}.0", name));
533+
bx.set_var_name(b, format_args!("{}.1", name));
534534

535535
return local(OperandRef {
536536
val: OperandValue::Pair(a, b),
@@ -546,7 +546,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
546546
// already put it in a temporary alloca and gave it up.
547547
// FIXME: lifetimes
548548
let llarg = bx.get_param(llarg_idx);
549-
bx.set_value_name(llarg, &name);
549+
bx.set_var_name(llarg, &name);
550550
llarg_idx += 1;
551551
PlaceRef::new_sized(llarg, arg.layout)
552552
} else if arg.is_unsized_indirect() {

src/librustc_codegen_ssa/mir/statement.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
2929
self.codegen_rvalue_unsized(bx, cg_indirect_dest, rvalue)
3030
}
3131
LocalRef::Operand(None) => {
32-
let (bx, operand) = self.codegen_rvalue_operand(bx, rvalue);
32+
let (mut bx, operand) = self.codegen_rvalue_operand(bx, rvalue);
33+
if let Some(name) = self.mir.local_decls[index].name {
34+
match operand.val {
35+
OperandValue::Ref(x, ..) |
36+
OperandValue::Immediate(x) => {
37+
bx.set_var_name(x, name);
38+
}
39+
OperandValue::Pair(a, b) => {
40+
// FIXME(eddyb) these are scalar components,
41+
// maybe extract the high-level fields?
42+
bx.set_var_name(a, format_args!("{}.0", name));
43+
bx.set_var_name(b, format_args!("{}.1", name));
44+
}
45+
}
46+
}
3347
self.locals[index] = LocalRef::Operand(Some(operand));
3448
bx
3549
}

src/librustc_codegen_ssa/traits/debuginfo.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,5 @@ pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
5757
span: Span,
5858
);
5959
fn insert_reference_to_gdb_debug_scripts_section_global(&mut self);
60-
fn set_value_name(&mut self, value: Self::Value, name: &str);
60+
fn set_var_name(&mut self, value: Self::Value, name: impl ToString);
6161
}

src/test/codegen/var-names.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// compile-flags: -O -C no-prepopulate-passes
2+
3+
#![crate_type = "lib"]
4+
5+
// CHECK-LABEL: define i32 @test(i32 %a, i32 %b)
6+
#[no_mangle]
7+
pub fn test(a: u32, b: u32) -> u32 {
8+
let c = a + b;
9+
// CHECK: %c = add i32 %a, %b
10+
let d = c;
11+
let e = d * a;
12+
// CHECK-NEXT: %e = mul i32 %c, %a
13+
e
14+
// CHECK-NEXT: ret i32 %e
15+
}

0 commit comments

Comments
 (0)