flux_common/
dbg.rs

1//! This file contains functions and macros to log debugging information meant for developers.
2use std::{
3    fmt, fs,
4    io::{self, Write},
5};
6
7use flux_config as config;
8use rustc_hir::def_id::DefId;
9use rustc_middle::ty::TyCtxt;
10
11pub fn writer_for_item(
12    tcx: TyCtxt,
13    def_id: DefId,
14    ext: impl AsRef<str>,
15) -> io::Result<impl io::Write> {
16    fs::create_dir_all(config::log_dir())?;
17    let path = config::log_dir().join(dump_base_name(tcx, def_id, ext));
18    let file = fs::File::create(path)?;
19    let buf = std::io::BufWriter::new(file);
20    Ok(buf)
21}
22
23pub fn dump_item_info<T: fmt::Debug>(
24    tcx: TyCtxt,
25    def_id: impl Into<DefId>,
26    ext: impl AsRef<str>,
27    val: T,
28) -> io::Result<()> {
29    let mut writer = writer_for_item(tcx, def_id.into(), ext)?;
30    writeln!(writer, "{val:#?}")
31}
32
33#[macro_export]
34macro_rules! _shape_mode_span {
35    ($tcx:expr, $def_id:expr) => {{
36        let path = $tcx.def_path(rustc_hir::def_id::DefId::from($def_id));
37        let def_id = path.data.iter().join("::");
38        tracing::info_span!("shape", def_id = def_id.as_str())
39    }};
40}
41pub use crate::_shape_mode_span as shape_mode_span;
42
43#[macro_export]
44macro_rules! _refine_mode_span {
45    ($tcx:expr, $def_id:expr, $bb_envs:expr) => {{
46        let path = $tcx.def_path(rustc_hir::def_id::DefId::from($def_id));
47        let def_id = path.data.iter().join("::");
48        tracing::info_span!("refine", def_id = def_id.as_str(), bb_envs = ?$bb_envs)
49    }};
50}
51pub use crate::_refine_mode_span as refine_mode_span;
52
53#[macro_export]
54macro_rules! _check_fn_span {
55    ($tcx:expr, $def_id:expr) => {{
56        let path = $tcx.def_path(rustc_hir::def_id::DefId::from($def_id));
57        let def_id = path.data.iter().join("::");
58        tracing::info_span!("check_fn", def_id = def_id.as_str())
59    }};
60}
61pub use crate::_check_fn_span as check_fn_span;
62
63#[macro_export]
64macro_rules! _basic_block_start {
65    ($bb:expr, $rcx:expr, $env:expr) => {{
66        tracing::debug!(event = "basic_block_start", bb = ?$bb, rcx = ?$rcx, env = ?$env)
67    }};
68}
69pub use crate::_basic_block_start as basic_block_start;
70
71#[macro_export]
72macro_rules! _statement{
73    ($pos:literal, $stmt:expr, $infcx:expr, $env:expr, $span:expr, $checker:expr) => {{
74        if config::dump_checker_trace() {
75            let rcx = $infcx.cursor();
76            let ck = $checker;
77            let genv = ck.genv;
78            let local_names = &ck.body.local_names;
79            let local_decls = &ck.body.local_decls;
80            let rcx_json = RefineCtxtTrace::new(genv, rcx);
81            let env_json = TypeEnvTrace::new(genv, local_names, local_decls, $env);
82            let span_json = SpanTrace::new(genv, $span);
83            tracing::info!(event = concat!("statement_", $pos), stmt = ?$stmt, stmt_span = ?$span, rcx = ?rcx, env = ?$env, rcx_json = ?rcx_json, env_json = ?env_json, stmt_span_json = ?span_json)
84        }
85    }};
86}
87pub use crate::_statement as statement;
88
89#[macro_export]
90macro_rules! _terminator{
91    ($pos:literal, $terminator:expr, $rcx:expr, $env:expr) => {{
92        tracing::debug!(event = concat!("terminator_", $pos), terminator = ?$terminator, rcx = ?$rcx, env = ?$env)
93    }};
94}
95pub use crate::_terminator as terminator;
96
97#[macro_export]
98macro_rules! _refine_goto {
99    ($target:expr, $rcx:expr, $env:expr, $bb_env:expr) => {{
100        tracing::debug!(event = "refine_goto", target = ?$target, rcx = ?$rcx, env = ?$env, bb_env = ?$bb_env)
101    }};
102}
103pub use crate::_refine_goto as refine_goto;
104
105#[macro_export]
106macro_rules! _shape_goto_enter {
107    ($target:expr, $env:expr, $bb_env:expr) => {{
108        if let Some(bb_env) = &$bb_env {
109            tracing::debug!(event = "shape_goto_enter", target = ?$target, env = ?&$env, ?bb_env)
110        } else {
111            tracing::debug!(event = "shape_goto_enter", target = ?$target, env = ?&$env, bb_env = "empty")
112        }
113    }};
114}
115pub use crate::_shape_goto_enter as shape_goto_enter;
116
117#[macro_export]
118macro_rules! _shape_goto_exit {
119    ($target:expr, $bb_env:expr) => {{
120        tracing::debug!(event = "shape_goto_exit", target = ?$target, bb_env = ?&$bb_env)
121    }};
122}
123pub use crate::_shape_goto_exit as shape_goto_exit;
124
125fn dump_base_name(tcx: TyCtxt, def_id: DefId, ext: impl AsRef<str>) -> String {
126    let crate_name = tcx.crate_name(def_id.krate);
127    let item_name = tcx.def_path(def_id).to_filename_friendly_no_crate();
128    format!("{crate_name}.{item_name}.{}", ext.as_ref())
129}
130
131#[macro_export]
132macro_rules! _debug_assert_eq3 {
133    ($e1:expr, $e2:expr, $e3:expr) => {{
134        debug_assert!($e1 == $e2 && $e2 == $e3, "{:?} != {:?} != {:?}", $e1, $e2, $e3);
135    }};
136}
137pub use crate::_debug_assert_eq3 as debug_assert_eq3;