Skip to content

Commit

Permalink
Add ScopeRegion::ScopeType and DominatorTree extension class
Browse files Browse the repository at this point in the history
  • Loading branch information
Washi1337 committed Jan 7, 2025
1 parent a8f5417 commit 29fb8a7
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 48 deletions.
17 changes: 17 additions & 0 deletions src/Core/Echo.ControlFlow/Analysis/Domination/DominatorTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@

namespace Echo.ControlFlow.Analysis.Domination
{
/// <summary>
/// Provides extension methods for constructing dominator trees.
/// </summary>
public static class DominatorTree
{
/// <summary>
/// Constructs a dominator tree from a control flow graph.
/// </summary>
/// <param name="graph">The control flow graph to turn into a dominator tree.</param>
/// <returns>The constructed dominator tree.</returns>
public static DominatorTree<TInstruction> FromGraph<TInstruction>(ControlFlowGraph<TInstruction> graph)
where TInstruction : notnull
{
return DominatorTree<TInstruction>.FromGraph(graph);
}
}

/// <summary>
/// Represents a dominator tree, where each tree node corresponds to one node in a graph, and each
/// is immediately dominated by its parent.
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Echo.ControlFlow/Collections/RegionCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public RegionCollection(IControlFlowRegion<TInstruction> owner)

private void AssertRegionValidity(TRegion item)
{
if (item.ParentRegion is {})
if (item.ParentRegion is not null)
throw new ArgumentException("Region is already part of another graph.");
}

Expand Down
2 changes: 2 additions & 0 deletions src/Core/Echo.ControlFlow/ControlFlowGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public NodeCollection<TInstruction> Nodes
get;
}

ICollection<ControlFlowNode<TInstruction>> IScopeControlFlowRegion<TInstruction>.Nodes => Nodes;

/// <summary>
/// Gets a collection of top-level regions that this control flow graph defines.
/// </summary>
Expand Down
19 changes: 1 addition & 18 deletions src/Core/Echo.ControlFlow/Regions/IControlFlowRegion.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using Echo.ControlFlow.Collections;
using Echo.Graphing;

namespace Echo.ControlFlow.Regions
Expand Down Expand Up @@ -39,7 +38,7 @@ public interface IControlFlowRegion<TInstruction> : ISubGraph
/// <summary>
/// Gets a collection of all nested regions defined in this region.
/// </summary>
/// <returns>The sub regions.</returns>
/// <returns>The subregions.</returns>
IEnumerable<ControlFlowRegion<TInstruction>> GetSubRegions();

/// <summary>
Expand Down Expand Up @@ -70,22 +69,6 @@ public interface IControlFlowRegion<TInstruction> : ISubGraph
IEnumerable<ControlFlowNode<TInstruction>> GetSuccessors();
}

/// <summary>
/// Represents a scope of regions.
/// </summary>
/// <typeparam name="TInstruction">The type of data that each node in the graph stores.</typeparam>
public interface IScopeControlFlowRegion<TInstruction> : IControlFlowRegion<TInstruction>
where TInstruction : notnull
{
/// <summary>
/// Gets a collection of nested sub regions that this region defines.
/// </summary>
public RegionCollection<TInstruction, ControlFlowRegion<TInstruction>> Regions
{
get;
}
}

/// <summary>
/// Provides extensions to the <see cref="IControlFlowRegion{TInstruction}"/> interface.
/// </summary>
Expand Down
22 changes: 22 additions & 0 deletions src/Core/Echo.ControlFlow/Regions/IScopeControlFlowRegion.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Collections.Generic;
using Echo.ControlFlow.Collections;

namespace Echo.ControlFlow.Regions;

/// <summary>
/// Represents a scope of nodes and regions.
/// </summary>
/// <typeparam name="TInstruction">The type of data that each node in the graph stores.</typeparam>
public interface IScopeControlFlowRegion<TInstruction> : IControlFlowRegion<TInstruction>
where TInstruction : notnull
{
/// <summary>
/// Gets a collection of top-level nodes stored in this region.
/// </summary>
public ICollection<ControlFlowNode<TInstruction>> Nodes { get; }

/// <summary>
/// Gets a collection of nested subregions that this region defines.
/// </summary>
public RegionCollection<TInstruction, ControlFlowRegion<TInstruction>> Regions { get; }
}
39 changes: 23 additions & 16 deletions src/Core/Echo.ControlFlow/Regions/ScopeRegion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,52 @@ namespace Echo.ControlFlow.Regions
/// Represents a simple unordered region defining an inner scope in the control flow graph.
/// </summary>
/// <typeparam name="TInstruction">The type of data that each node in the graph stores.</typeparam>
public class ScopeRegion<TInstruction> : ControlFlowRegion<TInstruction>
public class ScopeRegion<TInstruction> : ControlFlowRegion<TInstruction>, IScopeControlFlowRegion<TInstruction>
where TInstruction : notnull
{
/// <summary>
/// Creates a new instance of the <see cref="ScopeRegion{TInstruction}"/> class.
/// Creates a new empty scope region with no extra semantics attached.
/// </summary>
public ScopeRegion()
: this(ScopeRegionType.None)
{
}

/// <summary>
/// Creates a new empty scope region of the provided scope type.
/// </summary>
/// <param name="type">The type.</param>
public ScopeRegion(ScopeRegionType type)
{
Regions = new RegionCollection<TInstruction, ControlFlowRegion<TInstruction>>(this);
Nodes = new RegionNodeCollection<TInstruction>(this);
ScopeType = type;
}

/// <summary>
/// Gets or sets the first node that is executed in the region.
/// </summary>
public ControlFlowNode<TInstruction>? EntryPoint
{
get;
set;
}
public ControlFlowNode<TInstruction>? EntryPoint { get; set; }

/// <summary>
/// Gets a collection of top-level nodes that this region consists of.
/// </summary>
/// <remarks>
/// This collection does not include any nodes in the nested sub regions.
/// </remarks>
public RegionNodeCollection<TInstruction> Nodes
{
get;
}
public RegionNodeCollection<TInstruction> Nodes { get; }

ICollection<ControlFlowNode<TInstruction>> IScopeControlFlowRegion<TInstruction>.Nodes => Nodes;

/// <summary>
/// Gets a collection of nested sub regions that this region defines.
/// Gets a collection of nested subregions that this region defines.
/// </summary>
public RegionCollection<TInstruction, ControlFlowRegion<TInstruction>> Regions
{
get;
}
public RegionCollection<TInstruction, ControlFlowRegion<TInstruction>> Regions { get; }

/// <summary>
/// Gets or sets the type of scope.
/// </summary>
public ScopeRegionType ScopeType { get; set; }

/// <inheritdoc />
public override IEnumerable<ControlFlowNode<TInstruction>> GetNodes()
Expand Down
25 changes: 25 additions & 0 deletions src/Core/Echo.ControlFlow/Regions/ScopeRegionType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace Echo.ControlFlow.Regions;

/// <summary>
/// Provides members describing all possible types a scope region can be.
/// </summary>
public enum ScopeRegionType
{
/// <summary>
/// Indicates no special semantics.
/// </summary>
None,

/// <summary>
/// Indicates the scope was introduced as a result of a conditional branch (e.g., if-else or switch).
/// The entry point node of the scope implements the condition and the true/false branches.
/// </summary>
Conditional,

/// <summary>
/// Indicates the scope was introduced as a result of one or more back-edges and forms a loop.
/// The entry point node of the scope is the loop header, and all incoming edges originating from within the scope
/// define all back-edges.
/// </summary>
Loop,
}
Original file line number Diff line number Diff line change
Expand Up @@ -213,19 +213,13 @@ private static string GetScopeRegionPrefix(ScopeRegion<TInstruction> basicRegion

private (DotEntityStyle Style, string Label) GetSubGraphStyle(IControlFlowRegion<TInstruction> region)
{
switch (region)
return region switch
{
case ScopeRegion<TInstruction> basicRegion:
return GetScopeStyle(basicRegion);

case ExceptionHandlerRegion<TInstruction> _:
return (ExceptionHandlerStyle, ExceptionHandlerLabel);

case HandlerRegion<TInstruction> _:
return (HandlerStyle, HandlerLabel);
}

return (DefaultStyle, string.Empty);
ScopeRegion<TInstruction> basicRegion => GetScopeStyle(basicRegion),
ExceptionHandlerRegion<TInstruction> _ => (ExceptionHandlerStyle, ExceptionHandlerLabel),
HandlerRegion<TInstruction> _ => (HandlerStyle, HandlerLabel),
_ => (DefaultStyle, string.Empty)
};
}

private (DotEntityStyle Style, string Label) GetScopeStyle(ScopeRegion<TInstruction> basicRegion)
Expand All @@ -251,7 +245,11 @@ private static string GetScopeRegionPrefix(ScopeRegion<TInstruction> basicRegion
}
}

return (DefaultStyle, "Scope");
string label = basicRegion.ScopeType != ScopeRegionType.None
? basicRegion.ScopeType.ToString()
: "Scope";

return (DefaultStyle, label);
}

}
Expand Down

0 comments on commit 29fb8a7

Please sign in to comment.