Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions TypeCobol.Analysis.Test/BasicCfgPrograms/HanoiPrg.doms
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Dominators[Block0]={0}
Dominators[Block1]={0, 1}
Dominators[Block2]={0, 1, 2}
Dominators[Block3]={0, 1, 2, 3, 25, 26, 29}
Dominators[Block4]={0, 1, 2, 3, 4, 25, 26, 29}
Dominators[Block5]={0, 1, 2, 3, 4, 5, 25, 26, 29}
Dominators[Block6]={0, 1, 2, 3, 4, 5, 6, 25, 26, 29}
Dominators[Block25]={0, 1, 2, 25}
Dominators[Block26]={0, 1, 2, 25, 26}
Dominators[Block27]={0, 1, 2, 25, 26, 27}
Dominators[Block29]={0, 1, 2, 25, 26, 29}
Dominators[Block30]={0, 1, 2, 3, 4, 25, 26, 29, 30}
Dominators[Block31]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31}
Dominators[Block32]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31, 32}
Dominators[Block33]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31, 32, 33}
Dominators[Block34]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31, 32, 33, 34, 43}
Dominators[Block35]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31, 35}
Dominators[Block36]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31, 36}
Dominators[Block37]={0, 1, 2, 3, 4, 25, 26, 29, 30, 37}
Dominators[Block38]={0, 1, 2, 3, 4, 25, 26, 29, 30, 37, 38}
Dominators[Block39]={0, 1, 2, 3, 4, 25, 26, 29, 30, 37, 38, 39, 44}
Dominators[Block40]={0, 1, 2, 3, 4, 25, 26, 29, 30, 40}
Dominators[Block43]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31, 32, 33, 43}
Dominators[Block44]={0, 1, 2, 3, 4, 25, 26, 29, 30, 37, 38, 44}
24 changes: 24 additions & 0 deletions TypeCobol.Analysis.Test/BasicCfgPrograms/HanoiPrg.idoms
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Dominators[Block0]={}
Dominators[Block1]={0}
Dominators[Block2]={1}
Dominators[Block3]={29}
Dominators[Block4]={3}
Dominators[Block5]={4}
Dominators[Block6]={5}
Dominators[Block25]={2}
Dominators[Block26]={25}
Dominators[Block27]={26}
Dominators[Block29]={26}
Dominators[Block30]={4}
Dominators[Block31]={30}
Dominators[Block32]={31}
Dominators[Block33]={32}
Dominators[Block34]={43}
Dominators[Block35]={31}
Dominators[Block36]={31}
Dominators[Block37]={30}
Dominators[Block38]={37}
Dominators[Block39]={44}
Dominators[Block40]={30}
Dominators[Block43]={33}
Dominators[Block44]={38}
63 changes: 63 additions & 0 deletions TypeCobol.Analysis.Test/CfgDfaDominatorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using TypeCobol.Analysis.Graph;
using TypeCobol.Test;
using static TypeCobol.Analysis.Test.CfgTestUtils;
using CFG = TypeCobol.Analysis.Graph.ControlFlowGraph<TypeCobol.Compiler.Nodes.Node,
TypeCobol.Analysis.Dfa.DfaBasicBlockInfo<TypeCobol.Compiler.Symbols.VariableSymbol>>;

namespace TypeCobol.Analysis.Test
{
[TestClass]
public class CfgDfaDominatorTests
{
[TestMethod]
[TestCategory("Dominator")]
public void HanoiPrgCfgExtendedDominator()
{
string path = Path.Combine(BasicCfgPrograms, "HanoiPrg.cbl");
var dfaResults = ParseCompareDiagnosticsWithDfa(path);
Assert.IsTrue(dfaResults.Graphs.Count == 1);
var blocks_dominators = dfaResults.Graphs[0].ComputeDominators();

string expectedDomsFile = Path.Combine(BasicCfgPrograms, "HanoiPrg.doms");
StringWriter writer = new StringWriter();
CFG.DumpDominators(blocks_dominators.Item2, writer);
// compare with expected result
string result = writer.ToString();
string expected = File.ReadAllText(expectedDomsFile);
TestUtils.compareLines(path, result, expected, expectedDomsFile);
}

private static void HanoiPrgCfgExtendedImmediateDominator(bool duplicate)
{
string path = Path.Combine(BasicCfgPrograms, "HanoiPrg.cbl");
var dfaResults = ParseCompareDiagnosticsWithDfa(path);
Assert.IsTrue(dfaResults.Graphs.Count == 1);
var blocks_dominators = dfaResults.Graphs[0].ComputeDominators();
var idoms = dfaResults.Graphs[0].ComputeImmediateDominators(blocks_dominators.Item1, blocks_dominators.Item2, duplicate);

string expectedDomsFile = Path.Combine(BasicCfgPrograms, "HanoiPrg.idoms");
StringWriter writer = new StringWriter();
CFG.DumpDominators(idoms, writer);
// compare with expected result
string result = writer.ToString();
string expected = File.ReadAllText(expectedDomsFile);
TestUtils.compareLines(path, result, expected, expectedDomsFile);
}

[TestMethod]
[TestCategory("ImmediateDominator")]
public void HanoiPrgCfgExtendedImmediateDominatorDup()
{
HanoiPrgCfgExtendedImmediateDominator(true);
}

[TestMethod]
[TestCategory("ImmediateDominator")]
public void HanoiPrgCfgExtendedImmediateDominatorNoDup()
{
HanoiPrgCfgExtendedImmediateDominator(false);
}
}
}
3 changes: 3 additions & 0 deletions TypeCobol.Analysis.Test/TypeCobol.Analysis.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<Compile Include="BasicControlFlowInstructionTest.cs" />
<Compile Include="BitSetTest.cs" />
<Compile Include="CfgDfaBuildingTests.cs" />
<Compile Include="CfgDfaDominatorTests.cs" />
<Compile Include="CfgTestUtils.cs" />
<Compile Include="CfgTestResults.cs" />
<Compile Include="DfaBuildUseAndDefListTest.cs" />
Expand All @@ -62,6 +63,8 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="BasicCfgPrograms\HanoiPrg.doms" />
<None Include="BasicCfgPrograms\HanoiPrg.idoms" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
Expand Down
125 changes: 125 additions & 0 deletions TypeCobol.Analysis/Graph/ControlFlowGraph.Dominator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using TypeCobol.Analysis.Util;

namespace TypeCobol.Analysis.Graph
{
/// <summary>
/// Dominator algorithm implementation
/// </summary>
/// <typeparam name="N"></typeparam>
/// <typeparam name="D"></typeparam>
public partial class ControlFlowGraph<N, D>
{
/// <summary>
/// Compute a Dominator set on this CFG Graph
/// </summary>
/// <returns>A Tuple of a List of reachable nodes and an array of BitSet indexed by BasicBlock Indices</returns>
public Tuple<List<int>,BitSet[]> ComputeDominators()
{
BitSet[] dominators = new BitSet[this.AllBlocks.Count];
//Compute reachable blocks
List<int> blocks = new List<int>();
this.DFS((block, incomingEdge, predecessorBlock, cfg) =>
{
blocks.Add(block.Index);
dominators[block.Index] = new BitSet(dominators.Length);
if (block.Index != this.RootBlock.Index)
dominators[block.Index].Full();
return true;
});
//Setup prececessors
this.SetupPredecessorEdgesFromRoot();

//Reflexivity on root block
dominators[this.RootBlock.Index].Set(this.RootBlock.Index);

bool change = false;
BitSet workSet = new BitSet(dominators.Length); //workingSet
do
{
change = false;
foreach (int n in blocks)
{
if (n == this.RootBlock.Index)
continue;
BasicBlock<N, D> b = this.AllBlocks[n];
System.Diagnostics.Debug.Assert(b.PredecessorEdges != null);
workSet.Full();
foreach (int r in b.PredecessorEdges)
{
BasicBlock<N, D> p = PredecessorEdges[r];
workSet.And(dominators[p.Index]);
}
workSet.Set(n);//reflexivity
if (!workSet.Equals(dominators[n]))
{
dominators[n].Copy(workSet);
change = true;
}
}
} while (change);

return new Tuple<List<int>, BitSet[]>(blocks, dominators);
}

/// <summary>
/// Compute the immediate dominance relation.
/// </summary>
/// <param name="blocks">The blocks of the graph on which to work.</param>
/// <param name="dominators">The dominator sets</param>
/// <param name="duplicate">true to create new sets, rather then pruning dominators set</param>
/// <returns>The immediate dominance sets</returns>
public BitSet[] ComputeImmediateDominators(List<int> blocks, BitSet[] dominators, bool duplicate = true)
{
BitSet[] idoms = duplicate ? new BitSet[dominators.Length] : dominators;
foreach (var b in blocks)
{
if (duplicate)
{
idoms[b] = new BitSet(dominators.Length);
idoms[b].Copy(dominators[b]);
}
idoms[b].Clear(b); //Remove reflexivity
}
BitSet tmp = new BitSet();
foreach (var r in blocks)
{
if (r == this.RootBlock.Index) continue;
tmp.Copy(idoms[r]);
foreach (var s in blocks)
{
if (tmp.Get(s))
{
foreach (var t in blocks)
{
if (t == s) continue;
if (tmp.Get(t) && idoms[s].Get(t))
{
idoms[r].Clear(t);
}
}
}
}
}
return idoms;
}

/// <summary>
/// Dump a set of Dominators
/// </summary>
/// <param name="dominators">The set of Dominators</param>
/// <param name="writer"></param>
public static void DumpDominators(BitSet[] dominators, System.IO.TextWriter writer)
{
for (int i = 0; i < dominators.Length; i++)
{
BitSet doms = dominators[i];
if (doms != null)
{
writer.WriteLine($"Dominators[Block{i}]={doms.ToString()}");
}
}
}
}
}
2 changes: 1 addition & 1 deletion TypeCobol.Analysis/Graph/ControlFlowGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace TypeCobol.Analysis.Graph
/// </summary>
/// <typeparam name="N"></typeparam>
/// <typeparam name="D"></typeparam>
public class ControlFlowGraph<N, D>
public partial class ControlFlowGraph<N, D>
{
/// <summary>
/// BasicBlock callback type.
Expand Down
1 change: 1 addition & 0 deletions TypeCobol.Analysis/TypeCobol.Analysis.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<Compile Include="Graph\BasicBlock.cs" />
<Compile Include="Graph\CfgDotFileForNodeGenerator.cs" />
<Compile Include="Graph\ControlFlowGraph.cs" />
<Compile Include="Graph\ControlFlowGraph.Dominator.cs" />
<Compile Include="Graph\ICfgFileGenerator.cs" />
<Compile Include="Graph\ICfgTransform.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down
9 changes: 9 additions & 0 deletions TypeCobol.Analysis/Util/BitSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,15 @@ public void Clear()
_data[i] = 0;
}

/// <summary>
/// Set all bit to 1
/// </summary>
public void Full()
{
for (int i = 0; i < _data.Length; i++)
_data[i] = ulong.MaxValue;
}

public void Copy(BitSet from)
{
if (_data.Length != from._data.Length)
Expand Down