17
17
//! See the main module comment in `mod.rs` for more details on the VCode-based
18
18
//! backend pipeline.
19
19
20
+ use crate :: entity:: SecondaryMap ;
20
21
use crate :: ir;
22
+ use crate :: ir:: SourceLoc ;
21
23
use crate :: machinst:: * ;
22
24
use crate :: settings;
23
25
@@ -59,6 +61,10 @@ pub struct VCode<I: VCodeInst> {
59
61
/// Lowered machine instructions in order corresponding to the original IR.
60
62
insts : Vec < I > ,
61
63
64
+ /// Source locations for each instruction. (`SourceLoc` is a `u32`, so it is
65
+ /// reasonable to keep one of these per instruction.)
66
+ srclocs : Vec < Option < SourceLoc > > ,
67
+
62
68
/// Entry block.
63
69
entry : BlockIndex ,
64
70
@@ -115,13 +121,16 @@ pub struct VCodeBuilder<I: VCodeInst> {
115
121
116
122
/// Current basic block instructions, in reverse order (because blocks are
117
123
/// built bottom-to-top).
118
- bb_insns : SmallVec < [ I ; 32 ] > ,
124
+ bb_insns : SmallVec < [ ( I , Option < SourceLoc > ) ; 32 ] > ,
119
125
120
126
/// Current IR-inst instructions, in forward order.
121
- ir_inst_insns : SmallVec < [ I ; 4 ] > ,
127
+ ir_inst_insns : SmallVec < [ ( I , Option < SourceLoc > ) ; 4 ] > ,
122
128
123
129
/// Start of succs for the current block in the concatenated succs list.
124
130
succ_start : usize ,
131
+
132
+ /// Current source location.
133
+ cur_srcloc : Option < SourceLoc > ,
125
134
}
126
135
127
136
impl < I : VCodeInst > VCodeBuilder < I > {
@@ -133,6 +142,7 @@ impl<I: VCodeInst> VCodeBuilder<I> {
133
142
bb_insns : SmallVec :: new ( ) ,
134
143
ir_inst_insns : SmallVec :: new ( ) ,
135
144
succ_start : 0 ,
145
+ cur_srcloc : None ,
136
146
}
137
147
}
138
148
@@ -179,8 +189,8 @@ impl<I: VCodeInst> VCodeBuilder<I> {
179
189
/// End the current IR instruction. Must be called after pushing any
180
190
/// instructions and prior to ending the basic block.
181
191
pub fn end_ir_inst ( & mut self ) {
182
- while let Some ( i ) = self . ir_inst_insns . pop ( ) {
183
- self . bb_insns . push ( i ) ;
192
+ while let Some ( pair ) = self . ir_inst_insns . pop ( ) {
193
+ self . bb_insns . push ( pair ) ;
184
194
}
185
195
}
186
196
@@ -191,8 +201,9 @@ impl<I: VCodeInst> VCodeBuilder<I> {
191
201
let block_num = self . vcode . block_ranges . len ( ) as BlockIndex ;
192
202
// Push the instructions.
193
203
let start_idx = self . vcode . insts . len ( ) as InsnIndex ;
194
- while let Some ( i ) = self . bb_insns . pop ( ) {
204
+ while let Some ( ( i , loc ) ) = self . bb_insns . pop ( ) {
195
205
self . vcode . insts . push ( i) ;
206
+ self . vcode . srclocs . push ( loc) ;
196
207
}
197
208
let end_idx = self . vcode . insts . len ( ) as InsnIndex ;
198
209
// Add the instruction index range to the list of blocks.
@@ -224,7 +235,12 @@ impl<I: VCodeInst> VCodeBuilder<I> {
224
235
}
225
236
}
226
237
}
227
- self . ir_inst_insns . push ( insn) ;
238
+ self . ir_inst_insns . push ( ( insn, self . cur_srcloc ) ) ;
239
+ }
240
+
241
+ /// Set the current source location.
242
+ pub fn set_srcloc ( & mut self , srcloc : Option < SourceLoc > ) {
243
+ self . cur_srcloc = srcloc;
228
244
}
229
245
230
246
/// Build the final VCode.
@@ -286,6 +302,7 @@ impl<I: VCodeInst> VCode<I> {
286
302
liveouts : abi. liveouts ( ) ,
287
303
vreg_types : vec ! [ ] ,
288
304
insts : vec ! [ ] ,
305
+ srclocs : vec ! [ ] ,
289
306
entry : 0 ,
290
307
block_ranges : vec ! [ ] ,
291
308
block_succ_range : vec ! [ ] ,
@@ -349,14 +366,18 @@ impl<I: VCodeInst> VCode<I> {
349
366
block_ranges ( result. target_map . elems ( ) , result. insns . len ( ) ) ;
350
367
let mut final_insns = vec ! [ ] ;
351
368
let mut final_block_ranges = vec ! [ ( 0 , 0 ) ; self . num_blocks( ) ] ;
369
+ let mut final_srclocs = vec ! [ ] ;
352
370
353
371
for block in & self . final_block_order {
354
372
let ( start, end) = block_ranges[ * block as usize ] ;
355
373
let final_start = final_insns. len ( ) as InsnIndex ;
356
374
357
375
if * block == self . entry {
358
376
// Start with the prologue.
359
- final_insns. extend ( self . abi . gen_prologue ( ) . into_iter ( ) ) ;
377
+ let prologue = self . abi . gen_prologue ( ) ;
378
+ let len = prologue. len ( ) ;
379
+ final_insns. extend ( prologue. into_iter ( ) ) ;
380
+ final_srclocs. extend ( iter:: repeat ( None ) . take ( len) ) ;
360
381
}
361
382
362
383
for i in start..end {
@@ -368,21 +389,34 @@ impl<I: VCodeInst> VCode<I> {
368
389
continue ;
369
390
}
370
391
392
+ // Is there a srcloc associated with this insn? Look it up based on original
393
+ // instruction index (if new insn corresponds to some original insn, i.e., is not
394
+ // an inserted load/spill/move).
395
+ let srcloc: Option < SourceLoc > = result. orig_insn_map [ InstIx :: new ( i as u32 ) ]
396
+ . and_then ( |orig_idx| self . srclocs [ orig_idx. get ( ) as usize ] ) ;
397
+
371
398
// Whenever encountering a return instruction, replace it
372
399
// with the epilogue.
373
400
let is_ret = insn. is_term ( ) == MachTerminator :: Ret ;
374
401
if is_ret {
375
- final_insns. extend ( self . abi . gen_epilogue ( ) . into_iter ( ) ) ;
402
+ let epilogue = self . abi . gen_epilogue ( ) ;
403
+ let len = epilogue. len ( ) ;
404
+ final_insns. extend ( epilogue. into_iter ( ) ) ;
405
+ final_srclocs. extend ( iter:: repeat ( srcloc) . take ( len) ) ;
376
406
} else {
377
407
final_insns. push ( insn. clone ( ) ) ;
408
+ final_srclocs. push ( srcloc) ;
378
409
}
379
410
}
380
411
381
412
let final_end = final_insns. len ( ) as InsnIndex ;
382
413
final_block_ranges[ * block as usize ] = ( final_start, final_end) ;
383
414
}
384
415
416
+ debug_assert ! ( final_insns. len( ) == final_srclocs. len( ) ) ;
417
+
385
418
self . insts = final_insns;
419
+ self . srclocs = final_srclocs;
386
420
self . block_ranges = final_block_ranges;
387
421
}
388
422
@@ -512,6 +546,7 @@ impl<I: VCodeInst> VCode<I> {
512
546
let code_section = sections. get_section ( code_idx) ;
513
547
514
548
let flags = self . abi . flags ( ) ;
549
+ let mut cur_srcloc: Option < SourceLoc > = None ;
515
550
for & block in & self . final_block_order {
516
551
let new_offset = I :: align_basic_block ( code_section. cur_offset_from_start ( ) ) ;
517
552
while new_offset > code_section. cur_offset_from_start ( ) {
@@ -523,8 +558,24 @@ impl<I: VCodeInst> VCode<I> {
523
558
524
559
let ( start, end) = self . block_ranges [ block as usize ] ;
525
560
for iix in start..end {
561
+ let srcloc = self . srclocs [ iix as usize ] ;
562
+ if srcloc != cur_srcloc {
563
+ if cur_srcloc. is_some ( ) {
564
+ code_section. end_srcloc ( ) ;
565
+ }
566
+ if srcloc. is_some ( ) {
567
+ code_section. start_srcloc ( srcloc. unwrap ( ) ) ;
568
+ }
569
+ cur_srcloc = srcloc;
570
+ }
571
+
526
572
self . insts [ iix as usize ] . emit ( code_section, flags) ;
527
573
}
574
+
575
+ if cur_srcloc. is_some ( ) {
576
+ code_section. end_srcloc ( ) ;
577
+ cur_srcloc = None ;
578
+ }
528
579
}
529
580
530
581
sections
0 commit comments