rustc_codegen_llvm/back/
profiling.rs

1use std::ffi::{CStr, c_void};
2use std::os::raw::c_char;
3use std::sync::Arc;
4
5use measureme::event_id::SEPARATOR_BYTE;
6use measureme::{EventId, StringComponent, StringId};
7use rustc_data_structures::profiling::{SelfProfiler, TimingGuard};
8
9fn llvm_args_to_string_id(profiler: &SelfProfiler, pass_name: &str, ir_name: &str) -> EventId {
10    let pass_name = profiler.get_or_alloc_cached_string(pass_name);
11    let mut components = vec![StringComponent::Ref(pass_name)];
12    // handle that LazyCallGraph::SCC is a comma separated list within parentheses
13    let parentheses: &[_] = &['(', ')'];
14    let trimmed = ir_name.trim_matches(parentheses);
15    for part in trimmed.split(", ") {
16        let demangled_ir_name = rustc_demangle::demangle(part).to_string();
17        let ir_name = profiler.get_or_alloc_cached_string(demangled_ir_name);
18        components.push(StringComponent::Value(SEPARATOR_BYTE));
19        components.push(StringComponent::Ref(ir_name));
20    }
21    EventId::from_label(profiler.alloc_string(components.as_slice()))
22}
23
24pub(crate) struct LlvmSelfProfiler<'a> {
25    profiler: Arc<SelfProfiler>,
26    stack: Vec<TimingGuard<'a>>,
27    llvm_pass_event_kind: StringId,
28}
29
30impl<'a> LlvmSelfProfiler<'a> {
31    pub(crate) fn new(profiler: Arc<SelfProfiler>) -> Self {
32        let llvm_pass_event_kind = profiler.alloc_string("LLVM Pass");
33        Self { profiler, stack: Vec::default(), llvm_pass_event_kind }
34    }
35
36    fn before_pass_callback(&'a mut self, pass_name: &str, ir_name: &str) {
37        let event_id = llvm_args_to_string_id(&self.profiler, pass_name, ir_name);
38
39        self.stack.push(TimingGuard::start(&self.profiler, self.llvm_pass_event_kind, event_id));
40    }
41    fn after_pass_callback(&mut self) {
42        self.stack.pop();
43    }
44}
45
46pub(crate) unsafe extern "C" fn selfprofile_before_pass_callback(
47    llvm_self_profiler: *mut c_void,
48    pass_name: *const c_char,
49    ir_name: *const c_char,
50) {
51    unsafe {
52        let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>);
53        let pass_name = CStr::from_ptr(pass_name).to_str().expect("valid UTF-8");
54        let ir_name = CStr::from_ptr(ir_name).to_str().expect("valid UTF-8");
55        llvm_self_profiler.before_pass_callback(pass_name, ir_name);
56    }
57}
58
59pub(crate) unsafe extern "C" fn selfprofile_after_pass_callback(llvm_self_profiler: *mut c_void) {
60    let llvm_self_profiler = unsafe { &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>) };
61    llvm_self_profiler.after_pass_callback();
62}