@@ -9,7 +9,7 @@ public partial class ControlFlowGraphBuilder<D>
99        /// <summary> 
1010        /// The context of a Multi Branch instruction like IF or Evaluate. 
1111        /// </summary> 
12-         internal  class  MultiBranchContext 
12+         internal  class  MultiBranchContext   :   IMultiBranchContext < Node ,   D > 
1313        { 
1414            /// <summary> 
1515            /// Origin block before multi branches 
@@ -18,15 +18,11 @@ internal class MultiBranchContext
1818            /// <summary> 
1919            /// List of multi branch blocks 
2020            /// </summary> 
21-             internal  List < BasicBlockForNode >  Branches ; 
22-             /// <summary> 
23-             /// The Target Control Flow Graph Builder 
24-             /// </summary> 
25-             internal  ControlFlowGraphBuilder < D >  Builder ; 
21+             public  IList < BasicBlock < Node ,  D > >  Branches  {  get ;  internal  set ;  } 
2622            /// <summary> 
2723            /// Indices in the SuccessorEdges of all blocks in Branches 
2824            /// </summary> 
29-             internal   List < int >  BranchIndices ; 
25+             public   IList < int >  BranchIndices   {   get ;   internal   set ;   } 
3026            /// <summary> 
3127            /// Root Block of the multi branches 
3228            /// </summary> 
@@ -35,28 +31,45 @@ internal class MultiBranchContext
3531            /// The Index in the SuccessorEdge of the RootBlock if any, -1 otherwise. 
3632            /// </summary> 
3733            internal  int  RootBlockSuccessorIndex ; 
38- 
34+             /// <summary> 
35+             /// Terminals block associated to Multi branch Context if any. 
36+             /// Terminals blocks are block that have as successor NextFlowBlock or 
37+             /// a branching to the beginning of a loop instruction block. 
38+             /// </summary> 
39+             public  IList < BasicBlock < Node ,  D > >  Terminals  {  get ;  internal  set ;  } 
3940            /// <summary> 
4041            /// The instruction associated to this context. 
4142            /// </summary> 
42-             internal  Node  Instruction ; 
43- 
43+             public  Node  Instruction  {  get ;  internal  set ;  } 
4444            /// <summary> 
4545            /// List to hold When, WhenOther, WhenSearch and AtEnd nodes 
4646            /// encountered in Evaluate or Search statements. 
4747            /// </summary> 
4848            internal  List < Node >  ConditionNodes ; 
49+             /// <summary> 
50+             /// Block of the next flow 
51+             /// </summary> 
52+             public  BasicBlock < Node ,  D >  NextFlowBlock  {  get ;  internal  set ;  } 
53+             /// <summary> 
54+             /// Any Sub context if any, null otherwise. 
55+             /// For instance in COBOL EVALUATE Context has all WHEN and WHENOTHER as sub contexts. 
56+             /// </summary> 
57+             public  IList < IMultiBranchContext < Node ,  D > >  SubContexts  {  get ;  internal  set ;  } 
58+ 
59+             private  BasicBlock < Node ,  D >  RootBlockForEnd ; 
60+ 
61+             BasicBlock < Node ,  D >  IMultiBranchContext < Node ,  D > . OriginBlock  =>  this . OriginBlock ; 
62+ 
63+             BasicBlock < Node ,  D >  IMultiBranchContext < Node ,  D > . RootBlock  =>  this . RootBlock ; 
4964
5065            /// <summary> 
5166            /// Constructor 
52-             /// </summary> 
53-             /// <param name="currentProgramCfgBuilder">The related CFG Builder</param> 
67+             /// </summary>             
5468            /// <param name="instruction">The instruction associated to this context </param> 
55-             internal  MultiBranchContext ( ControlFlowGraphBuilder < D >   currentProgramCfgBuilder ,   Node  instruction ) 
69+             internal  MultiBranchContext ( Node  instruction ) 
5670            { 
57-                 Branches  =  new  List < BasicBlockForNode > ( ) ; 
71+                 Branches  =  new  List < BasicBlock < Node ,   D > > ( ) ; 
5872                BranchIndices  =  new  List < int > ( ) ; 
59-                 Builder  =  currentProgramCfgBuilder ; 
6073                Instruction  =  instruction ; 
6174                RootBlockSuccessorIndex  =  - 1 ; 
6275            } 
@@ -68,44 +81,94 @@ internal MultiBranchContext(ControlFlowGraphBuilder<D> currentProgramCfgBuilder,
6881            internal  void  Start ( BasicBlockForNode  originBlock ) 
6982            { 
7083                this . OriginBlock  =  originBlock ; 
84+                 this . OriginBlock . Context  =  this ; 
7185            } 
7286
7387            /// <summary> 
7488            /// End the multi branching. 
7589            /// </summary> 
90+             /// <param name="cfg">The related CFG Graph</param> 
7691            /// <param name="branchToNext">True if the CurrentBlock must be linked to the next branch also, false otherwise</param> 
7792            /// <param name="nextBlock">The next block for all branches</param> 
78-             internal  void  End ( bool  branchToNext ,  BasicBlockForNode  nextBlock ) 
93+             internal  void  End ( ControlFlowGraph < Node ,   D >   cfg ,   bool  branchToNext ,  BasicBlockForNode  nextBlock ) 
7994            { 
80-                 End ( branchToNext ,  OriginBlock ,  nextBlock ) ; 
95+                 End ( cfg ,   branchToNext ,  OriginBlock ,  nextBlock ) ; 
8196            } 
8297            /// <summary> 
8398            /// End the multi branching. 
8499            /// </summary> 
100+             /// <param name="cfg">The related CFG Graph</param> 
85101            /// <param name="branchToNext">True if the CurrentBlock must be linked to the next branch also, false otherwise</param> 
86102            /// <param name="rootBlock">Root block of the multi branch</param> 
87103            /// <param name="nextBlock">The next block for all branches</param> 
88-             internal  void  End ( bool  branchToNext ,  BasicBlockForNode  rootBlock ,  BasicBlockForNode  nextBlock ) 
104+             internal  void  End ( ControlFlowGraph < Node ,   D >   cfg ,   bool  branchToNext ,  BasicBlockForNode  rootBlock ,  BasicBlockForNode  nextBlock ) 
89105            { 
90-                 System . Diagnostics . Debug . Assert ( Builder  !=  null ) ; 
91106                System . Diagnostics . Debug . Assert ( rootBlock  !=  null ) ; 
92107                System . Diagnostics . Debug . Assert ( nextBlock  !=  null ) ; 
108+ 
109+                 Terminals  =  new  List < BasicBlock < Node ,  D > > ( ) ; 
93110                //Add the next block to the successors. 
94-                 int  nbIndex  =  Builder . Cfg . SuccessorEdges . Count ; 
95-                 Builder . Cfg . SuccessorEdges . Add ( nextBlock ) ; 
111+                 int  nbIndex  =  cfg . SuccessorEdges . Count ; 
112+                 cfg . SuccessorEdges . Add ( nextBlock ) ; 
96113                //Link current block to all branches. 
97114                foreach  ( var  b  in  Branches ) 
98115                { 
99116                    //Add branch to the successors 
100-                     BranchIndices . Add ( Builder . Cfg . SuccessorEdges . Count ) ; 
101-                     rootBlock . SuccessorEdges . Add ( Builder . Cfg . SuccessorEdges . Count ) ; 
102-                     Builder . Cfg . SuccessorEdges . Add ( b ) ; 
117+                     BranchIndices . Add ( cfg . SuccessorEdges . Count ) ; 
118+                     rootBlock . SuccessorEdges . Add ( cfg . SuccessorEdges . Count ) ; 
119+                     cfg . SuccessorEdges . Add ( b ) ; 
103120                    //Next Block is a successor of the branch. 
104-                     AddTerminalSuccessorEdge ( b ,  nbIndex ) ; 
121+                     AddTerminalSuccessorEdge ( cfg ,   b ,  nbIndex ) ; 
105122                } 
106123                if  ( branchToNext ) 
107124                { 
108125                    rootBlock . SuccessorEdges . Add ( nbIndex ) ; 
126+                     Terminals . Add ( rootBlock ) ; 
127+                 } 
128+                 RootBlockForEnd  =  rootBlock ; 
129+                 NextFlowBlock  =  nextBlock ;                 
130+             } 
131+ 
132+             /// <summary> 
133+             /// Change the successors 
134+             /// </summary> 
135+             /// <param name="cfg">The target CFG graph</param> 
136+             /// <param name="currentSucc">The current Successor</param> 
137+             /// <param name="newSucc">The new Successor</param> 
138+             internal  void  ChangeSuccessor ( ControlFlowGraph < Node ,  D >  cfg ,  BasicBlock < Node ,  D >  currentSucc ,  BasicBlock < Node ,  D >  newSucc ) 
139+             { 
140+                 if  ( NextFlowBlock  ==  currentSucc ) 
141+                     NextFlowBlock  =  newSucc ; 
142+                 if  ( RootBlockForEnd  !=  null ) 
143+                 { 
144+                     List < BasicBlock < Node ,  D > >  branches  =  ( List < BasicBlock < Node ,  D > > ) Branches ; 
145+                     List < int >  branchIndices  =  ( List < int > ) BranchIndices ; 
146+                     System . Diagnostics . Debug . Assert ( branches . Count  ==  branchIndices . Count ) ; 
147+                     for  ( int  i  =  0 ;  i  <  branches . Count ;  i ++ ) 
148+                     { 
149+                         if  ( branches [ i ]  ==  currentSucc ) 
150+                         { 
151+                             System . Diagnostics . Debug . Assert ( cfg . SuccessorEdges [ branchIndices [ i ] ]  ==  currentSucc ) ; 
152+                             branches [ i ]  =  newSucc ; 
153+                             RootBlockForEnd . SuccessorEdges . Remove ( branchIndices [ i ] ) ; 
154+                             branchIndices [ i ]  =  cfg . SuccessorEdges . Count ; 
155+                             RootBlockForEnd . SuccessorEdges . Add ( cfg . SuccessorEdges . Count ) ; 
156+                             cfg . SuccessorEdges . Add ( newSucc ) ; 
157+                             break ; 
158+                         } 
159+                     } 
160+                 } 
161+                 if  ( Terminals  !=  null ) 
162+                 { 
163+                     List < BasicBlock < Node ,  D > >  terminals  =  ( List < BasicBlock < Node ,  D > > ) Terminals ; 
164+                     for  ( int  i  =  0 ;  i  <  terminals . Count ;  i ++ ) 
165+                     { 
166+                         if  ( terminals [ i ]  ==  currentSucc ) 
167+                         { 
168+                             terminals [ i ]  =  newSucc ; 
169+                             break ; 
170+                         } 
171+                     } 
109172                } 
110173            } 
111174
@@ -121,10 +184,11 @@ internal void AddBranch(BasicBlockForNode block)
121184            /// <summary> 
122185            /// Add to all terminal block, from a given block b, a given successor index. 
123186            /// </summary> 
187+             /// <param name="cfg">The related CFG Graph</param> 
124188            /// <param name="b">The starting block</param> 
125189            /// <param name="nbIndex">The terminal successor index</param> 
126190            /// <param name="visitedBlockIndex">Set of already visited Block Index</param> 
127-             internal  void  AddTerminalSuccessorEdge ( BasicBlockForNode  b ,  int  nbIndex ,  HashSet < int >  visitedBlockIndex  =  null ) 
191+             internal  void  AddTerminalSuccessorEdge ( ControlFlowGraph < Node ,   D >   cfg ,   BasicBlock < Node ,   D >  b ,  int  nbIndex ,  HashSet < int >  visitedBlockIndex  =  null ) 
128192            { 
129193                if  ( visitedBlockIndex  ==  null ) 
130194                { 
@@ -139,46 +203,21 @@ internal void AddTerminalSuccessorEdge(BasicBlockForNode b, int nbIndex, HashSet
139203                    //Ending block has no successors. 
140204                    if  ( ! b . HasFlag ( BasicBlock < Node ,  D > . Flags . Ending ) ) 
141205                    { 
142-                         if  ( b  !=  Builder . Cfg . SuccessorEdges [ nbIndex ] ) 
206+                         if  ( b  !=  cfg . SuccessorEdges [ nbIndex ] ) 
143207                        { //Don't create recursion to ourselves 
144208                            b . SuccessorEdges . Add ( nbIndex ) ; 
209+                             Terminals ? . Add ( b ) ; 
145210                        } 
146211                    } 
147212                } 
148213                else 
149214                { 
150215                    foreach  ( var  s  in  b . SuccessorEdges ) 
151216                    { 
152-                         AddTerminalSuccessorEdge ( ( BasicBlockForNode ) Builder . Cfg . SuccessorEdges [ s ] ,  nbIndex ,  visitedBlockIndex ) ; 
217+                         AddTerminalSuccessorEdge ( cfg ,   ( BasicBlockForNode ) cfg . SuccessorEdges [ s ] ,  nbIndex ,  visitedBlockIndex ) ; 
153218                    } 
154219                } 
155220            } 
156- 
157-             /// <summary> 
158-             /// Get all terminal blocks from the given block. 
159-             /// </summary> 
160-             /// <param name="b">The starting block</param> 
161-             /// <param name="accumulator">Accumulator of  terminal blocks</param> 
162-             /// <param name="visitedBlockIndex">Set of already visited Block Index</param> 
163-             internal  void  GetTerminalSuccessorEdges ( BasicBlockForNode  b ,  List < BasicBlockForNode >  accumulator ,  HashSet < int >  visitedBlockIndex  =  null ) 
164-             { 
165-                 if  ( visitedBlockIndex  ==  null ) 
166-                 { 
167-                     visitedBlockIndex  =  new  HashSet < int > ( ) ; 
168-                 } 
169-                 if  ( visitedBlockIndex . Contains ( b . Index ) ) 
170-                     return ; 
171-                 visitedBlockIndex . Add ( b . Index ) ; 
172-                 if  ( b . SuccessorEdges . Count  ==  0 ) 
173-                 { 
174-                     accumulator . Add ( b ) ; 
175-                 } 
176-                 else  foreach  ( var  s  in  b . SuccessorEdges ) 
177-                 { 
178-                     GetTerminalSuccessorEdges ( ( BasicBlockForNode ) Builder . Cfg . SuccessorEdges [ s ] ,  accumulator ,  visitedBlockIndex ) ; 
179-                 } 
180-             } 
181- 
182221        } 
183222    } 
184- } 
223+ } 
0 commit comments