about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_errors/src/json.rs1
-rw-r--r--compiler/rustc_errors/src/timings.rs47
-rw-r--r--compiler/rustc_interface/src/passes.rs3
-rw-r--r--compiler/rustc_interface/src/queries.rs3
4 files changed, 50 insertions, 4 deletions
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index 6d600f896a0..4348610be0a 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -129,6 +129,7 @@ impl Emitter for JsonEmitter {
         };
         let name = match record.section {
             TimingSection::Linking => "link",
+            TimingSection::Codegen => "codegen",
         };
         let data = SectionTimestamp { name, event, timestamp: record.timestamp };
         let result = self.emit(EmitTyped::SectionTiming(data));
diff --git a/compiler/rustc_errors/src/timings.rs b/compiler/rustc_errors/src/timings.rs
index 27fc9df8d79..0d82f3e8db8 100644
--- a/compiler/rustc_errors/src/timings.rs
+++ b/compiler/rustc_errors/src/timings.rs
@@ -1,10 +1,15 @@
 use std::time::Instant;
 
+use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sync::Lock;
+
 use crate::DiagCtxtHandle;
 
 /// A high-level section of the compilation process.
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub enum TimingSection {
+    /// Time spent doing codegen.
+    Codegen,
     /// Time spent linking.
     Linking,
 }
@@ -36,23 +41,59 @@ pub struct TimingSectionHandler {
     /// Time when the compilation session started.
     /// If `None`, timing is disabled.
     origin: Option<Instant>,
+    /// Sanity check to ensure that we open and close sections correctly.
+    opened_sections: Lock<FxHashSet<TimingSection>>,
 }
 
 impl TimingSectionHandler {
     pub fn new(enabled: bool) -> Self {
         let origin = if enabled { Some(Instant::now()) } else { None };
-        Self { origin }
+        Self { origin, opened_sections: Lock::new(FxHashSet::default()) }
     }
 
     /// Returns a RAII guard that will immediately emit a start the provided section, and then emit
     /// its end when it is dropped.
-    pub fn start_section<'a>(
+    pub fn section_guard<'a>(
         &self,
         diag_ctxt: DiagCtxtHandle<'a>,
         section: TimingSection,
     ) -> TimingSectionGuard<'a> {
+        if self.is_enabled() && self.opened_sections.borrow().contains(&section) {
+            diag_ctxt
+                .bug(format!("Section `{section:?}` was started again before it was finished"));
+        }
+
         TimingSectionGuard::create(diag_ctxt, section, self.origin)
     }
+
+    /// Start the provided section.
+    pub fn start_section(&self, diag_ctxt: DiagCtxtHandle<'_>, section: TimingSection) {
+        if let Some(origin) = self.origin {
+            let mut opened = self.opened_sections.borrow_mut();
+            if !opened.insert(section) {
+                diag_ctxt
+                    .bug(format!("Section `{section:?}` was started again before it was finished"));
+            }
+
+            diag_ctxt.emit_timing_section_start(TimingRecord::from_origin(origin, section));
+        }
+    }
+
+    /// End the provided section.
+    pub fn end_section(&self, diag_ctxt: DiagCtxtHandle<'_>, section: TimingSection) {
+        if let Some(origin) = self.origin {
+            let mut opened = self.opened_sections.borrow_mut();
+            if !opened.remove(&section) {
+                diag_ctxt.bug(format!("Section `{section:?}` was ended before being started"));
+            }
+
+            diag_ctxt.emit_timing_section_end(TimingRecord::from_origin(origin, section));
+        }
+    }
+
+    fn is_enabled(&self) -> bool {
+        self.origin.is_some()
+    }
 }
 
 /// RAII wrapper for starting and ending section timings.
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 201b7e2b940..0b9facfc7af 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -11,6 +11,7 @@ use rustc_data_structures::jobserver::Proxy;
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, WorkerLocal};
 use rustc_data_structures::{parallel, thousands};
+use rustc_errors::timings::TimingSection;
 use rustc_expand::base::{ExtCtxt, LintStoreExpand};
 use rustc_feature::Features;
 use rustc_fs_util::try_canonicalize;
@@ -1176,6 +1177,8 @@ pub(crate) fn start_codegen<'tcx>(
     codegen_backend: &dyn CodegenBackend,
     tcx: TyCtxt<'tcx>,
 ) -> (Box<dyn Any>, EncodedMetadata) {
+    tcx.sess.timings.start_section(tcx.sess.dcx(), TimingSection::Codegen);
+
     // Hook for tests.
     if let Some((def_id, _)) = tcx.entry_fn(())
         && tcx.has_attr(def_id, sym::rustc_delayed_bug_from_inside_query)
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 877440ec7d2..2bc30fa7cb0 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -48,6 +48,7 @@ impl Linker {
         let (codegen_results, work_products) = sess.time("finish_ongoing_codegen", || {
             codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames)
         });
+        sess.timings.end_section(sess.dcx(), TimingSection::Codegen);
 
         sess.dcx().abort_if_errors();
 
@@ -89,7 +90,7 @@ impl Linker {
         }
 
         let _timer = sess.prof.verbose_generic_activity("link_crate");
-        let _timing = sess.timings.start_section(sess.dcx(), TimingSection::Linking);
+        let _timing = sess.timings.section_guard(sess.dcx(), TimingSection::Linking);
         codegen_backend.link(sess, codegen_results, self.metadata, &self.output_filenames)
     }
 }