1use 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;