19
19
20
20
use crate :: ir:: pcc:: * ;
21
21
use crate :: ir:: { self , types, Constant , ConstantData , ValueLabel } ;
22
- use crate :: machinst:: * ;
23
22
use crate :: ranges:: Ranges ;
24
23
use crate :: timing;
25
24
use crate :: trace;
26
25
use crate :: CodegenError ;
26
+ use crate :: { machinst:: * , trace_log_enabled} ;
27
27
use crate :: { LabelValueLoc , ValueLocRange } ;
28
28
use regalloc2:: {
29
29
Edit , Function as RegallocFunction , InstOrEdit , InstRange , MachineEnv , Operand ,
30
30
OperandConstraint , OperandKind , PRegSet , RegClass ,
31
31
} ;
32
32
use rustc_hash:: FxHashMap ;
33
33
34
+ use core:: cmp:: Ordering ;
35
+ use core:: fmt:: { self , Write } ;
34
36
use core:: mem:: take;
35
37
use cranelift_entity:: { entity_impl, Keys } ;
36
38
use std:: collections:: hash_map:: Entry ;
37
39
use std:: collections:: HashMap ;
38
- use std:: fmt;
39
40
40
41
/// Index referring to an instruction in VCode.
41
42
pub type InsnIndex = regalloc2:: Inst ;
@@ -731,9 +732,6 @@ impl<I: VCodeInst> VCode<I> {
731
732
where
732
733
I : VCodeInst ,
733
734
{
734
- // To write into disasm string.
735
- use core:: fmt:: Write ;
736
-
737
735
let _tt = timing:: vcode_emit ( ) ;
738
736
let mut buffer = MachBuffer :: new ( ) ;
739
737
buffer. set_log2_min_function_alignment ( self . log2_min_function_alignment ) ;
@@ -1157,11 +1155,14 @@ impl<I: VCodeInst> VCode<I> {
1157
1155
return ValueLabelsRanges :: default ( ) ;
1158
1156
}
1159
1157
1158
+ if trace_log_enabled ! ( ) {
1159
+ self . log_value_labels_ranges ( regalloc, inst_offsets) ;
1160
+ }
1161
+
1160
1162
let mut value_labels_ranges: ValueLabelsRanges = HashMap :: new ( ) ;
1161
1163
for & ( label, from, to, alloc) in & regalloc. debug_locations {
1162
- let ranges = value_labels_ranges
1163
- . entry ( ValueLabel :: from_u32 ( label) )
1164
- . or_insert_with ( || vec ! [ ] ) ;
1164
+ let label = ValueLabel :: from_u32 ( label) ;
1165
+ let ranges = value_labels_ranges. entry ( label) . or_insert_with ( || vec ! [ ] ) ;
1165
1166
let from_offset = inst_offsets[ from. inst ( ) . index ( ) ] ;
1166
1167
let to_offset = if to. inst ( ) . index ( ) == inst_offsets. len ( ) {
1167
1168
func_body_len
@@ -1214,7 +1215,7 @@ impl<I: VCodeInst> VCode<I> {
1214
1215
if let Some ( last_loc_range) = ranges. last_mut ( ) {
1215
1216
if last_loc_range. loc == loc && last_loc_range. end == start {
1216
1217
trace ! (
1217
- "Extending debug range for VL{ } in {:?} to {}" ,
1218
+ "Extending debug range for {:? } in {:?} to {}" ,
1218
1219
label,
1219
1220
loc,
1220
1221
end
@@ -1225,7 +1226,7 @@ impl<I: VCodeInst> VCode<I> {
1225
1226
}
1226
1227
1227
1228
trace ! (
1228
- "Recording debug range for VL{ } in {:?}: [Inst {}..Inst {}) [{}..{})" ,
1229
+ "Recording debug range for {:? } in {:?}: [Inst {}..Inst {}) [{}..{})" ,
1229
1230
label,
1230
1231
loc,
1231
1232
from. inst( ) . index( ) ,
@@ -1240,6 +1241,200 @@ impl<I: VCodeInst> VCode<I> {
1240
1241
value_labels_ranges
1241
1242
}
1242
1243
1244
+ fn log_value_labels_ranges ( & self , regalloc : & regalloc2:: Output , inst_offsets : & [ CodeOffset ] ) {
1245
+ debug_assert ! ( trace_log_enabled!( ) ) ;
1246
+
1247
+ // What debug labels do we have? Note we'll skip those that have not been
1248
+ // allocated any location at all. They will show up as numeric gaps in the table.
1249
+ let mut labels = vec ! [ ] ;
1250
+ for & ( label, _, _, _) in & regalloc. debug_locations {
1251
+ if Some ( & label) == labels. last ( ) {
1252
+ continue ;
1253
+ }
1254
+ labels. push ( label) ;
1255
+ }
1256
+
1257
+ // Reformat the data on what VRegs were the VLs assigned to by lowering, since
1258
+ // the array we have is sorted by VReg, and we want it sorted by VL for easy
1259
+ // access in the loop below.
1260
+ let mut vregs = vec ! [ ] ;
1261
+ for & ( vreg, start, end, label) in & self . debug_value_labels {
1262
+ if matches ! ( labels. binary_search( & label) , Ok ( _) ) {
1263
+ vregs. push ( ( label, start, end, vreg) ) ;
1264
+ }
1265
+ }
1266
+ vregs. sort_unstable_by (
1267
+ |( l_label, l_start, _, _) , ( r_label, r_start, _, _) | match l_label. cmp ( r_label) {
1268
+ Ordering :: Equal => l_start. cmp ( r_start) ,
1269
+ cmp => cmp,
1270
+ } ,
1271
+ ) ;
1272
+
1273
+ #[ derive( PartialEq ) ]
1274
+ enum Mode {
1275
+ Measure ,
1276
+ Emit ,
1277
+ }
1278
+ #[ derive( PartialEq ) ]
1279
+ enum Row {
1280
+ Head ,
1281
+ Line ,
1282
+ Inst ( usize ) ,
1283
+ }
1284
+
1285
+ let mut widths = vec ! [ 0 ; 2 + 2 * labels. len( ) ] ;
1286
+ let mut row = String :: new ( ) ;
1287
+ let mut output_row = |row_kind : Row , mode : Mode | {
1288
+ let mut column_index = 0 ;
1289
+ row. clear ( ) ;
1290
+
1291
+ macro_rules! output_cell_impl {
1292
+ ( $fill: literal, $span: literal, $( $cell_fmt: tt) * ) => {
1293
+ let column_start = row. len( ) ;
1294
+ {
1295
+ row. push( '|' ) ;
1296
+ write!( row, $( $cell_fmt) * ) . unwrap( ) ;
1297
+ }
1298
+
1299
+ let next_column_index = column_index + $span;
1300
+ let expected_width: usize = widths[ column_index..next_column_index] . iter( ) . sum( ) ;
1301
+ if mode == Mode :: Measure {
1302
+ let actual_width = row. len( ) - column_start;
1303
+ if actual_width > expected_width {
1304
+ widths[ next_column_index - 1 ] += actual_width - expected_width;
1305
+ }
1306
+ } else {
1307
+ let column_end = column_start + expected_width;
1308
+ while row. len( ) != column_end {
1309
+ row. push( $fill) ;
1310
+ }
1311
+ }
1312
+ column_index = next_column_index;
1313
+ } ;
1314
+ }
1315
+ macro_rules! output_cell {
1316
+ ( $( $cell_fmt: tt) * ) => {
1317
+ output_cell_impl!( ' ' , 1 , $( $cell_fmt) * ) ;
1318
+ } ;
1319
+ }
1320
+
1321
+ match row_kind {
1322
+ Row :: Head => {
1323
+ output_cell ! ( "Inst" ) ;
1324
+ output_cell ! ( "IP" ) ;
1325
+ for label in & labels {
1326
+ output_cell_impl ! ( ' ' , 2 , "{:?}" , ValueLabel :: from_u32( * label) ) ;
1327
+ }
1328
+ }
1329
+ Row :: Line => {
1330
+ debug_assert ! ( mode == Mode :: Emit ) ;
1331
+ output_cell_impl ! ( '-' , 1 , "" ) ;
1332
+ output_cell_impl ! ( '-' , 1 , "" ) ;
1333
+ for _ in & labels {
1334
+ output_cell_impl ! ( '-' , 2 , "" ) ;
1335
+ }
1336
+ }
1337
+ Row :: Inst ( inst_index) => {
1338
+ output_cell ! ( "Inst {inst_index} " ) ;
1339
+ output_cell ! ( "{} " , inst_offsets[ inst_index] ) ;
1340
+
1341
+ // The ranges which we query below operate on the logic of
1342
+ // "IP(inst) == IP after inst", while the rows of our table
1343
+ // represent IPs 'before' "inst", so we need to convert "inst"
1344
+ // into these "IP after" coordinates.
1345
+ let inst_ip_index = inst_index. wrapping_sub ( 1 ) ;
1346
+ for label in & labels {
1347
+ // First, the VReg.
1348
+ use regalloc2:: Inst ;
1349
+ let vreg_cmp = |inst : usize ,
1350
+ vreg_label : & u32 ,
1351
+ range_start : & Inst ,
1352
+ range_end : & Inst | {
1353
+ match vreg_label. cmp ( & label) {
1354
+ Ordering :: Equal => {
1355
+ if range_end. index ( ) <= inst {
1356
+ Ordering :: Less
1357
+ } else if range_start. index ( ) > inst {
1358
+ Ordering :: Greater
1359
+ } else {
1360
+ Ordering :: Equal
1361
+ }
1362
+ }
1363
+ cmp => cmp,
1364
+ }
1365
+ } ;
1366
+ let vreg_index =
1367
+ vregs. binary_search_by ( |( l, s, e, _) | vreg_cmp ( inst_ip_index, l, s, e) ) ;
1368
+ if let Ok ( vreg_index) = vreg_index {
1369
+ let mut prev_vreg = None ;
1370
+ if inst_ip_index > 0 {
1371
+ let prev_vreg_index = vregs. binary_search_by ( |( l, s, e, _) | {
1372
+ vreg_cmp ( inst_ip_index - 1 , l, s, e)
1373
+ } ) ;
1374
+ if let Ok ( prev_vreg_index) = prev_vreg_index {
1375
+ prev_vreg = Some ( vregs[ prev_vreg_index] . 3 ) ;
1376
+ }
1377
+ }
1378
+
1379
+ let vreg = vregs[ vreg_index] . 3 ;
1380
+ if Some ( vreg) == prev_vreg {
1381
+ output_cell ! ( "*" ) ;
1382
+ } else {
1383
+ output_cell ! ( "{}" , vreg) ;
1384
+ }
1385
+ } else {
1386
+ output_cell ! ( "" ) ;
1387
+ }
1388
+
1389
+ // Second, the allocated location.
1390
+ let range_index = regalloc. debug_locations . binary_search_by (
1391
+ |( range_label, range_start, range_end, _) | match range_label. cmp ( label)
1392
+ {
1393
+ Ordering :: Equal => {
1394
+ if range_end. inst ( ) . index ( ) <= inst_ip_index {
1395
+ Ordering :: Less
1396
+ } else if range_start. inst ( ) . index ( ) > inst_ip_index {
1397
+ Ordering :: Greater
1398
+ } else {
1399
+ Ordering :: Equal
1400
+ }
1401
+ }
1402
+ cmp => cmp,
1403
+ } ,
1404
+ ) ;
1405
+ if let Ok ( range_index) = range_index {
1406
+ // Live at this instruction, print the location.
1407
+ if let Some ( reg) = regalloc. debug_locations [ range_index] . 3 . as_reg ( ) {
1408
+ output_cell ! ( "{:?}" , Reg :: from( reg) ) ;
1409
+ } else {
1410
+ output_cell ! ( "Stk" ) ;
1411
+ }
1412
+ } else {
1413
+ // Not live at this instruction.
1414
+ output_cell ! ( "" ) ;
1415
+ }
1416
+ }
1417
+ }
1418
+ }
1419
+ row. push ( '|' ) ;
1420
+
1421
+ if mode == Mode :: Emit {
1422
+ trace ! ( "{}" , row. as_str( ) ) ;
1423
+ }
1424
+ } ;
1425
+
1426
+ for inst_index in 0 ..inst_offsets. len ( ) {
1427
+ output_row ( Row :: Inst ( inst_index) , Mode :: Measure ) ;
1428
+ }
1429
+ output_row ( Row :: Head , Mode :: Measure ) ;
1430
+
1431
+ output_row ( Row :: Head , Mode :: Emit ) ;
1432
+ output_row ( Row :: Line , Mode :: Emit ) ;
1433
+ for inst_index in 0 ..inst_offsets. len ( ) {
1434
+ output_row ( Row :: Inst ( inst_index) , Mode :: Emit ) ;
1435
+ }
1436
+ }
1437
+
1243
1438
/// Get the IR block for a BlockIndex, if one exists.
1244
1439
pub fn bindex_to_bb ( & self , block : BlockIndex ) -> Option < ir:: Block > {
1245
1440
self . block_order . lowered_order ( ) [ block. index ( ) ] . orig_block ( )
0 commit comments