@@ -2507,90 +2507,101 @@ impl fmt::Display for Assembler {
25072507 }
25082508 }
25092509
2510- for insn in self . linearize_instructions ( ) . iter ( ) {
2511- match insn {
2512- Insn :: Comment ( comment) => {
2513- writeln ! ( f, " {bold_begin}# {comment}{bold_end}" ) ?;
2514- }
2515- Insn :: Label ( target) => {
2516- let & Target :: Label ( Label ( label_idx) ) = target else {
2517- panic ! ( "unexpected target for Insn::Label: {target:?}" ) ;
2518- } ;
2519- writeln ! ( f, " {}:" , label_name( self , label_idx, & label_counts) ) ?;
2520- }
2521- _ => {
2522- write ! ( f, " " ) ?;
2523-
2524- // Print output operand if any
2525- if let Some ( out) = insn. out_opnd ( ) {
2526- write ! ( f, "{out} = " ) ?;
2510+ for block_id in self . rpo ( ) {
2511+ let bb = & self . basic_blocks [ block_id. 0 ] ;
2512+ let params = & bb. parameters ;
2513+ for insn in & bb. insns {
2514+ match insn {
2515+ Insn :: Comment ( comment) => {
2516+ writeln ! ( f, " {bold_begin}# {comment}{bold_end}" ) ?;
25272517 }
2518+ Insn :: Label ( target) => {
2519+ let Target :: Label ( Label ( label_idx) ) = target else {
2520+ panic ! ( "unexpected target for Insn::Label: {target:?}" ) ;
2521+ } ;
2522+ write ! ( f, " {}(" , label_name( self , * label_idx, & label_counts) ) ?;
2523+ for ( idx, param) in params. iter ( ) . enumerate ( ) {
2524+ if idx > 0 {
2525+ write ! ( f, ", " ) ?;
2526+ }
2527+ write ! ( f, "{param}" ) ?;
2528+ }
2529+ writeln ! ( f, "):" ) ?;
2530+ }
2531+ _ => {
2532+ write ! ( f, " " ) ?;
2533+
2534+ // Print output operand if any
2535+ if let Some ( out) = insn. out_opnd ( ) {
2536+ write ! ( f, "{out} = " ) ?;
2537+ }
25282538
2529- // Print the instruction name
2530- write ! ( f, "{}" , insn. op( ) ) ?;
2539+ // Print the instruction name
2540+ write ! ( f, "{}" , insn. op( ) ) ?;
25312541
2532- // Show slot_count for FrameSetup
2533- if let Insn :: FrameSetup { slot_count, preserved } = insn {
2534- write ! ( f, " {slot_count}" ) ?;
2535- if !preserved. is_empty ( ) {
2536- write ! ( f, "," ) ?;
2542+ // Show slot_count for FrameSetup
2543+ if let Insn :: FrameSetup { slot_count, preserved } = insn {
2544+ write ! ( f, " {slot_count}" ) ?;
2545+ if !preserved. is_empty ( ) {
2546+ write ! ( f, "," ) ?;
2547+ }
25372548 }
2538- }
25392549
2540- // Print target
2541- if let Some ( target) = insn. target ( ) {
2542- match target {
2543- Target :: CodePtr ( code_ptr) => write ! ( f, " {code_ptr:?}" ) ?,
2544- Target :: Label ( Label ( label_idx) ) => write ! ( f, " {}" , label_name( self , * label_idx, & label_counts) ) ?,
2545- Target :: SideExit { reason, .. } => write ! ( f, " Exit({reason})" ) ?,
2546- Target :: Block ( edge) => {
2547- if edge. args . is_empty ( ) {
2548- write ! ( f, " bb{}" , edge. target. 0 ) ?;
2549- } else {
2550- write ! ( f, " bb{}(" , edge. target. 0 ) ?;
2551- for ( i, arg) in edge. args . iter ( ) . enumerate ( ) {
2552- if i > 0 {
2553- write ! ( f, ", " ) ?;
2550+ // Print target
2551+ if let Some ( target) = insn. target ( ) {
2552+ match target {
2553+ Target :: CodePtr ( code_ptr) => write ! ( f, " {code_ptr:?}" ) ?,
2554+ Target :: Label ( Label ( label_idx) ) => write ! ( f, " {}" , label_name( self , * label_idx, & label_counts) ) ?,
2555+ Target :: SideExit { reason, .. } => write ! ( f, " Exit({reason})" ) ?,
2556+ Target :: Block ( edge) => {
2557+ if edge. args . is_empty ( ) {
2558+ write ! ( f, " bb{}" , edge. target. 0 ) ?;
2559+ } else {
2560+ write ! ( f, " bb{}(" , edge. target. 0 ) ?;
2561+ for ( i, arg) in edge. args . iter ( ) . enumerate ( ) {
2562+ if i > 0 {
2563+ write ! ( f, ", " ) ?;
2564+ }
2565+ write ! ( f, "{}" , arg) ?;
25542566 }
2555- write ! ( f, "{}" , arg ) ?;
2567+ write ! ( f, ")" ) ?;
25562568 }
2557- write ! ( f, ")" ) ?;
25582569 }
25592570 }
25602571 }
2561- }
25622572
2563- // Print list of operands
2564- if let Some ( Target :: SideExit { .. } ) = insn. target ( ) {
2565- // If the instruction has a SideExit, avoid using opnd_iter(), which has stack/locals.
2566- // Here, only handle instructions that have both Opnd and Target.
2567- match insn {
2568- Insn :: Joz ( opnd, _) |
2569- Insn :: Jonz ( opnd, _) |
2570- Insn :: LeaJumpTarget { out : opnd, target : _ } => {
2571- write ! ( f, ", {opnd}" ) ?;
2573+ // Print list of operands
2574+ if let Some ( Target :: SideExit { .. } ) = insn. target ( ) {
2575+ // If the instruction has a SideExit, avoid using opnd_iter(), which has stack/locals.
2576+ // Here, only handle instructions that have both Opnd and Target.
2577+ match insn {
2578+ Insn :: Joz ( opnd, _) |
2579+ Insn :: Jonz ( opnd, _) |
2580+ Insn :: LeaJumpTarget { out : opnd, target : _ } => {
2581+ write ! ( f, ", {opnd}" ) ?;
2582+ }
2583+ _ => { }
25722584 }
2573- _ => { }
2574- }
2575- } else if let Some ( Target :: Block ( _ ) ) = insn . target ( ) {
2576- // If the instruction has a Block target, avoid using opnd_iter() for branch args
2577- // since they're already printed inline with the target. Only print non-target operands.
2578- match insn {
2579- Insn :: Joz ( opnd, _ ) |
2580- Insn :: Jonz ( opnd , _ ) |
2581- Insn :: LeaJumpTarget { out : opnd , target : _ } => {
2582- write ! ( f , ", {opnd}" ) ? ;
2585+ } else if let Some ( Target :: Block ( _ ) ) = insn . target ( ) {
2586+ // If the instruction has a Block target, avoid using opnd_iter() for branch args
2587+ // since they're already printed inline with the target. Only print non- target operands.
2588+ match insn {
2589+ Insn :: Joz ( opnd , _ ) |
2590+ Insn :: Jonz ( opnd , _ ) |
2591+ Insn :: LeaJumpTarget { out : opnd, target : _ } => {
2592+ write ! ( f , ", {opnd}" ) ? ;
2593+ }
2594+ _ => { }
25832595 }
2584- _ => { }
2596+ } else if let Insn :: ParallelMov { moves } = insn {
2597+ // Print operands with a special syntax for ParallelMov
2598+ moves. iter ( ) . try_fold ( " " , |prefix, ( dst, src) | write ! ( f, "{prefix}{dst} <- {src}" ) . and ( Ok ( ", " ) ) ) ?;
2599+ } else if insn. opnd_iter ( ) . count ( ) > 0 {
2600+ insn. opnd_iter ( ) . try_fold ( " " , |prefix, opnd| write ! ( f, "{prefix}{opnd}" ) . and ( Ok ( ", " ) ) ) ?;
25852601 }
2586- } else if let Insn :: ParallelMov { moves } = insn {
2587- // Print operands with a special syntax for ParallelMov
2588- moves. iter ( ) . try_fold ( " " , |prefix, ( dst, src) | write ! ( f, "{prefix}{dst} <- {src}" ) . and ( Ok ( ", " ) ) ) ?;
2589- } else if insn. opnd_iter ( ) . count ( ) > 0 {
2590- insn. opnd_iter ( ) . try_fold ( " " , |prefix, opnd| write ! ( f, "{prefix}{opnd}" ) . and ( Ok ( ", " ) ) ) ?;
2591- }
25922602
2593- write ! ( f, "\n " ) ?;
2603+ write ! ( f, "\n " ) ?;
2604+ }
25942605 }
25952606 }
25962607 }
@@ -3206,6 +3217,7 @@ impl Drop for AssemblerPanicHook {
32063217#[ cfg( test) ]
32073218mod tests {
32083219 use super :: * ;
3220+ use insta:: assert_snapshot;
32093221
32103222 fn scratch_reg ( ) -> Opnd {
32113223 Assembler :: new_with_scratch_reg ( ) . 1
@@ -3434,4 +3446,27 @@ mod tests {
34343446 vec![ r10. vreg_idx( ) , r12. vreg_idx( ) ]
34353447 ) ;
34363448 }
3449+
3450+ fn test_lir_debug_output ( ) {
3451+ let TestFunc { asm, .. } = build_func ( ) ;
3452+
3453+ // Test the LIR string output
3454+ let output = lir_string ( & asm) ;
3455+
3456+ assert_snapshot ! ( output, @"
3457+ bb0(v0, v1):
3458+ Jmp bb1(1, v1)
3459+ bb1(v2, v3):
3460+ Cmp v3, 1
3461+ Jl bb3
3462+ Jmp bb2
3463+ bb3():
3464+ v6 = Add v0, v2
3465+ CRet v6
3466+ bb2():
3467+ v4 = Mul v2, v3
3468+ v5 = Sub v3, 1
3469+ Jmp bb1(v4, v5)
3470+ " ) ;
3471+ }
34373472}
0 commit comments