@@ -58,6 +58,8 @@ pub struct DataFlowContext<'a, O> {
58
58
// So, to access the bits for any given id, you take a slice of
59
59
// the full vector (see the method `compute_id_range()`).
60
60
61
+ // NDM This comment seems to be inaccurate. These are indexed by CFG bit.
62
+
61
63
/// bits generated as we exit the scope `id`. Updated by `add_gen()`.
62
64
gens : Vec < uint > ,
63
65
@@ -69,13 +71,15 @@ pub struct DataFlowContext<'a, O> {
69
71
on_entry : Vec < uint > ,
70
72
}
71
73
74
+ pub trait BitwiseOperator {
75
+ /// Joins two predecessor bits together, typically either `|` or `&`
76
+ fn join ( & self , succ : uint , pred : uint ) -> uint ;
77
+ }
78
+
72
79
/// Parameterization for the precise form of data flow that is used.
73
- pub trait DataFlowOperator {
80
+ pub trait DataFlowOperator : BitwiseOperator {
74
81
/// Specifies the initial value for each bit in the `on_entry` set
75
82
fn initial_value ( & self ) -> bool ;
76
-
77
- /// Joins two predecessor bits together, typically either `|` or `&`
78
- fn join ( & self , succ : uint , pred : uint ) -> uint ;
79
83
}
80
84
81
85
struct PropagationContext < ' a , ' b , O > {
@@ -290,9 +294,9 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> {
290
294
self . analysis_name, cfgidx, mut_bits_to_str( bits) ) ;
291
295
let ( start, end) = self . compute_id_range ( cfgidx) ;
292
296
let gens = self . gens . slice ( start, end) ;
293
- bitwise ( bits, gens, |a , b| a | b ) ;
297
+ bitwise ( bits, gens, & Union ) ;
294
298
let kills = self . kills . slice ( start, end) ;
295
- bitwise ( bits, kills, |a , b| a & !b ) ;
299
+ bitwise ( bits, kills, & Subtract ) ;
296
300
297
301
debug ! ( "{:s} apply_gen_kill(cfgidx={}, bits={}) [after]" ,
298
302
self . analysis_name, cfgidx, mut_bits_to_str( bits) ) ;
@@ -391,6 +395,12 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> {
391
395
//! This is usually called (if it is called at all), after
392
396
//! all add_gen and add_kill calls, but before propagate.
393
397
398
+ // NDM -- It is interesting that we need this. It makes sense,
399
+ // but I had somehow expected that this should be managed as
400
+ // part of add_gen. Still, that would seem to require a
401
+ // separate index. Anyhow, maybe this should just be part of
402
+ // `propagate()`?
403
+
394
404
debug ! ( "{:s} add_kills_from_flow_exits" , self . analysis_name) ;
395
405
if self . bits_per_id == 0 {
396
406
// Skip the surprisingly common degenerate case. (Note
@@ -399,6 +409,7 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> {
399
409
}
400
410
cfg. graph . each_edge ( |_edge_index, edge| {
401
411
let flow_exit = edge. source ( ) ;
412
+ // why "ce"?
402
413
let ( ce_start, ce_end) = self . compute_id_range ( flow_exit) ;
403
414
let mut ce_orig_kills = self . kills . slice ( ce_start, ce_end) . to_owned ( ) ;
404
415
@@ -409,8 +420,9 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> {
409
420
Some ( cfg_idx) => {
410
421
let ( start, end) = self . compute_id_range ( cfg_idx) ;
411
422
let kills = self . kills . slice ( start, end) ;
412
- bitwise ( ce_orig_kills. as_mut_slice ( ) , kills, |a, b| a | b) ;
413
- changed = true ;
423
+ if bitwise ( ce_orig_kills. as_mut_slice ( ) , kills, & Union ) {
424
+ changed = true ;
425
+ } // NDM: if we're micro-optizing, let's micro-optimize!
414
426
}
415
427
None => {
416
428
debug ! ( "{:s} add_kills_from_flow_exits flow_exit={} \
@@ -490,7 +502,7 @@ impl<'a, 'b, O:DataFlowOperator> PropagationContext<'a, 'b, O> {
490
502
// Initialize local bitvector with state on-entry.
491
503
in_out. copy_from ( self . dfcx . on_entry . slice ( start, end) ) ;
492
504
493
- // Compute state on-exit by apply transfer function to state on-entry.
505
+ // Compute state on-exit by applying transfer function to state on-entry.
494
506
self . dfcx . apply_gen_kill ( node_index, in_out) ;
495
507
496
508
// Propagate state on-exit from node into its successors.
@@ -564,17 +576,19 @@ fn bits_to_str(words: &[uint]) -> String {
564
576
fn join_bits < O : DataFlowOperator > ( oper : & O ,
565
577
in_vec : & [ uint ] ,
566
578
out_vec : & mut [ uint ] ) -> bool {
567
- bitwise ( out_vec, in_vec, |a , b| oper. join ( a , b ) )
579
+ bitwise ( out_vec, in_vec, oper)
568
580
}
569
581
570
582
#[ inline]
571
- fn bitwise ( out_vec : & mut [ uint ] , in_vec : & [ uint ] , op : |uint , uint| -> uint)
572
- -> bool {
583
+ fn bitwise < O : BitwiseOperator > ( out_vec : & mut [ uint ] ,
584
+ in_vec : & [ uint ] ,
585
+ op : & O ) -> bool
586
+ {
573
587
assert_eq ! ( out_vec. len( ) , in_vec. len( ) ) ;
574
588
let mut changed = false ;
575
589
for ( out_elt, in_elt) in out_vec. mut_iter ( ) . zip ( in_vec. iter ( ) ) {
576
590
let old_val = * out_elt;
577
- let new_val = op ( old_val, * in_elt) ;
591
+ let new_val = op. join ( old_val, * in_elt) ;
578
592
* out_elt = new_val;
579
593
changed |= old_val != new_val;
580
594
}
@@ -599,3 +613,13 @@ fn bit_str(bit: uint) -> String {
599
613
let lobits = 1 << ( bit & 0xFF ) ;
600
614
format ! ( "[{}:{}-{:02x}]" , bit, byte, lobits)
601
615
}
616
+
617
+ struct Union ;
618
+ impl BitwiseOperator for Union {
619
+ fn join ( & self , a : uint , b : uint ) -> uint { a | b }
620
+ }
621
+
622
+ struct Subtract ;
623
+ impl BitwiseOperator for Subtract {
624
+ fn join ( & self , a : uint , b : uint ) -> uint { a & !b }
625
+ }
0 commit comments