@@ -38,6 +38,22 @@ const DUMMY_HIR_BLOCK_ID: usize = usize::MAX;
3838/// Dummy RPO index used when creating test or invalid LIR blocks
3939const DUMMY_RPO_INDEX : usize = usize:: MAX ;
4040
41+ /// LIR Instruction ID. Unique ID for each instruction in the LIR.
42+ #[ derive( Copy , Clone , Eq , PartialEq , Hash , Debug , PartialOrd , Ord ) ]
43+ pub struct InsnId ( pub usize ) ;
44+
45+ impl From < InsnId > for usize {
46+ fn from ( val : InsnId ) -> Self {
47+ val. 0
48+ }
49+ }
50+
51+ impl std:: fmt:: Display for InsnId {
52+ fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
53+ write ! ( f, "i{}" , self . 0 )
54+ }
55+ }
56+
4157#[ derive( Debug , PartialEq , Clone ) ]
4258pub struct BranchEdge {
4359 pub target : BlockId ,
@@ -58,11 +74,18 @@ pub struct BasicBlock {
5874 // Instructions in this basic block
5975 pub insns : Vec < Insn > ,
6076
77+ // Instruction IDs for each instruction (same length as insns)
78+ pub insn_ids : Vec < Option < InsnId > > ,
79+
6180 // Input parameters for this block
6281 pub parameters : Vec < Opnd > ,
6382
6483 // RPO position of the source HIR block
6584 pub rpo_index : usize ,
85+
86+ // Range of instruction IDs in this block (inclusive start, exclusive end)
87+ pub from : InsnId ,
88+ pub to : InsnId ,
6689}
6790
6891pub struct EdgePair ( Option < BranchEdge > , Option < BranchEdge > ) ;
@@ -74,8 +97,11 @@ impl BasicBlock {
7497 hir_block_id,
7598 is_entry,
7699 insns : vec ! [ ] ,
100+ insn_ids : vec ! [ ] ,
77101 parameters : vec ! [ ] ,
78102 rpo_index,
103+ from : InsnId ( 0 ) ,
104+ to : InsnId ( 0 ) ,
79105 }
80106 }
81107
@@ -85,6 +111,7 @@ impl BasicBlock {
85111
86112 pub fn push_insn ( & mut self , insn : Insn ) {
87113 self . insns . push ( insn) ;
114+ self . insn_ids . push ( None ) ;
88115 }
89116
90117 pub fn edges ( & self ) -> EdgePair {
@@ -2304,6 +2331,38 @@ impl Assembler
23042331 }
23052332 result
23062333 }
2334+
2335+ /// Number all instructions in the LIR in reverse postorder.
2336+ /// This assigns a unique InsnId to each instruction across all blocks.
2337+ /// Also sets the from/to range on each block.
2338+ /// Returns the next available instruction ID after numbering.
2339+ pub fn number_instructions ( & mut self , start : usize ) -> usize {
2340+ let rpo_order = self . rpo ( ) ;
2341+ let mut insn_id = start;
2342+ for block_id in rpo_order {
2343+ let block = & mut self . basic_blocks [ block_id. 0 ] ;
2344+ let block_start = insn_id;
2345+ for id_slot in & mut block. insn_ids {
2346+ * id_slot = Some ( InsnId ( insn_id) ) ;
2347+ insn_id += 2 ;
2348+ }
2349+ block. from = InsnId ( block_start) ;
2350+ block. to = InsnId ( insn_id) ;
2351+ }
2352+ insn_id
2353+ }
2354+
2355+ /// Iterate over all instructions mutably with their block ID, instruction ID, and instruction index within the block.
2356+ /// Returns an iterator of (BlockId, Option<InsnId>, usize, &mut Insn).
2357+ pub fn iter_insns_mut ( & mut self ) -> impl Iterator < Item = ( BlockId , Option < InsnId > , usize , & mut Insn ) > {
2358+ self . basic_blocks . iter_mut ( ) . flat_map ( |block| {
2359+ let block_id = block. id ;
2360+ block. insns . iter_mut ( )
2361+ . zip ( block. insn_ids . iter ( ) . copied ( ) )
2362+ . enumerate ( )
2363+ . map ( move |( idx, ( insn, insn_id) ) | ( block_id, insn_id, idx, insn) )
2364+ } )
2365+ }
23072366}
23082367
23092368/// Return a result of fmt::Display for Assembler without escape sequence
0 commit comments