1
+ using System . Collections . Generic ;
2
+ using NetSsa . Instructions ;
3
+ using System . Linq ;
4
+
5
+ namespace NetSsa . Analyses
6
+ {
7
+ public abstract class BackwardsDataFlowAnalysis < Data >
8
+ {
9
+ public BackwardsDataFlowAnalysis ( ControlFlowGraph cfg ) {
10
+ this . cfg = cfg ;
11
+ this . irBody = cfg . IRBody ;
12
+ }
13
+
14
+ protected ControlFlowGraph cfg ;
15
+ protected IRBody irBody ;
16
+
17
+ protected abstract Data Meet ( Data a , Data b ) ; // This is expected to create a copy of the input data
18
+ protected virtual Data MeetSuccessors ( TacInstruction leader ) {
19
+ IList < TacInstruction > successors = cfg . BasicBlockSuccessors ( leader ) ;
20
+ Data result = IN [ successors [ 0 ] ] ;
21
+ for ( int i = 1 ; i < successors . Count ; i ++ ) {
22
+ result = Meet ( result , IN [ successors [ i ] ] ) ;
23
+ }
24
+ return result ;
25
+ }
26
+
27
+ protected abstract Data Gen ( TacInstruction leader ) ;
28
+ protected abstract Data Kill ( TacInstruction leader ) ;
29
+ protected abstract bool TransferInstruction ( TacInstruction instruction , Data incomingData ) ;
30
+
31
+ protected virtual void Transfer ( TacInstruction leader , Data incomingData , ref bool changed ) {
32
+ IList < TacInstruction > instructions = cfg . BasicBlockInstructions ( leader ) . ToList ( ) ;
33
+
34
+ bool currentChanged = TransferInstruction ( instructions [ instructions . Count - 1 ] , incomingData ) ;
35
+ for ( int i = instructions . Count - 2 ; i >= 0 ; i -- ) {
36
+ currentChanged = currentChanged || TransferInstruction ( instructions [ i ] , IN [ instructions [ i + 1 ] ] ) ;
37
+ }
38
+
39
+ changed = currentChanged ;
40
+ }
41
+
42
+ protected abstract Data InitBasicBlock ( TacInstruction leader ) ;
43
+
44
+ public IDictionary < TacInstruction , Data > IN = new Dictionary < TacInstruction , Data > ( ) ;
45
+ public IDictionary < TacInstruction , Data > OUT = new Dictionary < TacInstruction , Data > ( ) ;
46
+
47
+ protected virtual IEnumerable < TacInstruction > GetExitBasicBlocks ( ) {
48
+ foreach ( TacInstruction leader in cfg . Leaders ( ) ) {
49
+ if ( cfg . BasicBlockSuccessors ( leader ) . Count == 0 ) {
50
+ yield return leader ;
51
+ }
52
+ }
53
+ }
54
+
55
+ protected void InitializeBasicBlocks ( ) {
56
+ foreach ( TacInstruction leader in cfg . Leaders ( ) ) {
57
+ foreach ( TacInstruction instruction in cfg . BasicBlockInstructions ( leader ) ) {
58
+ IN [ instruction ] = InitBasicBlock ( leader ) ;
59
+ }
60
+ }
61
+ }
62
+
63
+ public void Flow ( ) {
64
+ InitializeBasicBlocks ( ) ;
65
+ bool inChanged ;
66
+ do {
67
+ inChanged = false ;
68
+ foreach ( TacInstruction leader in cfg . Leaders ( ) . Except ( GetExitBasicBlocks ( ) ) ) {
69
+ OUT [ leader ] = MeetSuccessors ( leader ) ;
70
+ Transfer ( leader , OUT [ leader ] , ref inChanged ) ;
71
+ }
72
+ } while ( inChanged ) ;
73
+ }
74
+ }
75
+
76
+ }
0 commit comments