11use std:: { collections:: BTreeMap , fmt:: Write } ;
22
3- use sonatina_ir:: { BlockId , Function , InstId , ValueId } ;
3+ use sonatina_ir:: {
4+ BlockId , Function , InstId , ValueId ,
5+ ir_writer:: { FuncWriteCtx , InstStatement , IrWrite } ,
6+ module:: FuncRef ,
7+ } ;
48
59use crate :: bitset:: BitSet ;
610
@@ -92,13 +96,19 @@ impl StackifyObserver for NullObserver {
9296pub ( super ) struct StackifyTrace {
9397 out : String ,
9498 action_chunks : Vec < ActionChunk > ,
99+ inst_chunks : Vec < InstChunk > ,
95100}
96101
97102struct ActionChunk {
98103 placeholder : String ,
99104 actions : crate :: stackalloc:: Actions ,
100105}
101106
107+ struct InstChunk {
108+ placeholder : String ,
109+ inst : InstId ,
110+ }
111+
102112impl StackifyTrace {
103113 pub ( super ) fn render ( self , func : & Function , alloc : & StackifyAlloc ) -> String {
104114 if func. layout . iter_block ( ) . next ( ) . is_none ( ) {
@@ -152,6 +162,10 @@ impl StackifyTrace {
152162 let formatted = fmt_actions ( & chunk. actions ) ;
153163 trace = trace. replace ( & chunk. placeholder , & formatted) ;
154164 }
165+ for chunk in self . inst_chunks {
166+ let comment = fmt_inst_comment ( func, chunk. inst ) ;
167+ trace = trace. replace ( & chunk. placeholder , & comment) ;
168+ }
155169 out. push_str ( & trace) ;
156170 out
157171 }
@@ -167,19 +181,34 @@ impl StackifyTrace {
167181 } ) ;
168182 placeholder
169183 }
184+
185+ fn push_inst_placeholder ( & mut self , inst : InstId ) -> String {
186+ let idx = self . inst_chunks . len ( ) ;
187+ let placeholder = format ! ( "@@INST:{idx}@@" ) ;
188+ self . inst_chunks . push ( InstChunk {
189+ placeholder : placeholder. clone ( ) ,
190+ inst,
191+ } ) ;
192+ placeholder
193+ }
170194}
171195
172196impl StackifyObserver for StackifyTrace {
173- type Checkpoint = ( usize , usize ) ;
197+ type Checkpoint = ( usize , usize , usize ) ;
174198
175199 fn checkpoint ( & mut self ) -> Self :: Checkpoint {
176- ( self . out . len ( ) , self . action_chunks . len ( ) )
200+ (
201+ self . out . len ( ) ,
202+ self . action_chunks . len ( ) ,
203+ self . inst_chunks . len ( ) ,
204+ )
177205 }
178206
179207 fn rollback ( & mut self , checkpoint : Self :: Checkpoint ) {
180- let ( out_len, chunk_len ) = checkpoint;
208+ let ( out_len, action_chunk_len , inst_chunk_len ) = checkpoint;
181209 self . out . truncate ( out_len) ;
182- self . action_chunks . truncate ( chunk_len) ;
210+ self . action_chunks . truncate ( action_chunk_len) ;
211+ self . inst_chunks . truncate ( inst_chunk_len) ;
183212 }
184213
185214 fn on_block_header ( & mut self , func : & Function , block : BlockId , template : & BlockTemplate ) {
@@ -218,12 +247,14 @@ impl StackifyObserver for StackifyTrace {
218247 fn on_inst_start (
219248 & mut self ,
220249 func : & Function ,
221- _inst : InstId ,
250+ inst : InstId ,
222251 stack : & SymStack ,
223252 live_future : & BitSet < ValueId > ,
224253 live_out : & BitSet < ValueId > ,
225254 last_use : & BitSet < ValueId > ,
226255 ) {
256+ let comment = self . push_inst_placeholder ( inst) ;
257+ let _ = writeln ! ( & mut self . out, " // {comment}" ) ;
227258 let stack_start = fmt_stack ( func, stack, live_future, live_out) ;
228259 let last_use_list: Vec < ValueId > = last_use. iter ( ) . collect ( ) ;
229260 if last_use_list. is_empty ( ) {
@@ -298,6 +329,32 @@ impl StackifyObserver for StackifyTrace {
298329 }
299330}
300331
332+ fn fmt_inst_comment ( func : & Function , inst : InstId ) -> String {
333+ let Some ( func_ref) = fallback_func_ref ( func) else {
334+ return fmt_inst_comment_fallback ( func, inst) ;
335+ } ;
336+ let ctx = FuncWriteCtx :: new ( func, func_ref) ;
337+ let mut bytes = Vec :: new ( ) ;
338+ if InstStatement ( inst) . write ( & mut bytes, & ctx) . is_ok ( )
339+ && let Ok ( comment) = String :: from_utf8 ( bytes)
340+ {
341+ return comment;
342+ }
343+ fmt_inst_comment_fallback ( func, inst)
344+ }
345+
346+ fn fallback_func_ref ( func : & Function ) -> Option < FuncRef > {
347+ func. ctx ( )
348+ . declared_funcs
349+ . iter ( )
350+ . next ( )
351+ . map ( |entry| * entry. key ( ) )
352+ }
353+
354+ fn fmt_inst_comment_fallback ( func : & Function , inst : InstId ) -> String {
355+ format ! ( "{};" , func. dfg. inst( inst) . as_text( ) )
356+ }
357+
301358fn fmt_immediate ( imm : sonatina_ir:: Immediate ) -> String {
302359 use sonatina_ir:: Immediate :: * ;
303360 match imm {
0 commit comments