Skip to content

Commit 387663b

Browse files
mayanjefm-117
andauthored
2022 abstract int multi branch context (#2024)
* WI #2022 Introduce IMultiBranchContext.cs interface * WI #2022 Adding a comment * WI #2022 Handling SubContexts * WI #2022 Handle redirection on PERFORM AFTER branch * WI #2022 Change Review * WI #2022 Change review * WI #2022 replace builder by cfg argument * WI #2022 Move GetTerminalSuccessorEdges into CFG class Co-authored-by: fm-117 <milletfl@e-i.com>
1 parent 94208b4 commit 387663b

8 files changed

+220
-79
lines changed

TypeCobol.Analysis/Cfg/ControlFlowGraphBuilder.BasicBlockForNodeGroup.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ public int GroupIndex
2929
/// <summary>
3030
/// Terminal blocks within this Group.
3131
/// </summary>
32-
internal List<BasicBlockForNode> TerminalBlocks
32+
public IList<BasicBlock<Node, D>> TerminalBlocks
3333
{
3434
get;
35-
set;
35+
internal set;
3636
}
3737

3838
/// <summary>

TypeCobol.Analysis/Cfg/ControlFlowGraphBuilder.CfgAfterIterativePerformProcedureTransformer.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ private bool Callback(BasicBlock<Node, D> block, int incomingEdge, BasicBlock<No
4747
int entranceEdge = cfg.SuccessorEdges.Count;
4848
cfg.SuccessorEdges.Add(iterativeGroup.Group.First.Value);
4949
block.SuccessorEdges.Add(entranceEdge);
50+
System.Diagnostics.Debug.Assert(block.Context == null);
51+
//If the assert above fails (it should not be case), then it will be necessary to exeute the commented code below.
52+
//if(block.Context != null)
53+
//{
54+
// ((MultiBranchContext)block.Context).ChangeSuccessor(_cfg, iterativeGroup, iterativeGroup.Group.First.Value);
55+
//}
5056
}
5157

5258
//If the current block is a group, we must also traverse blocks of the group

TypeCobol.Analysis/Cfg/ControlFlowGraphBuilder.MultiBranchContext.cs

Lines changed: 94 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)