control flow structuring

This commit is contained in:
Colton1skees
2023-02-19 21:03:07 -06:00
parent 6c9ad9c32a
commit daa28ec41a
26 changed files with 585 additions and 52 deletions
+4
View File
@@ -0,0 +1,4 @@
[*.cs]
# CS8603: Possible null reference return.
dotnet_diagnostic.CS8603.severity = silent
@@ -9,6 +9,13 @@ namespace Dna.ControlFlow.Analysis
{
public static class DominatorAnalysis
{
/// <summary>
/// Constructs a dominator tree for the control flow graph.
/// For each node {N}, yield a set of nodes all nodes which dominate {N}.
/// </summary>
/// <param name="graph"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public static IReadOnlyDictionary<Node, HashSet<Node>> GetDominatorTree(Graph graph)
{
if (graph.Nodes.First().IncomingEdges.Count > 0)
+50 -11
View File
@@ -22,6 +22,8 @@ using ClangSharp.Interop;
using ClangSharp;
using Dna.Decompiler;
using Dna.Emulation.Unicorn;
using Dna.Decompilation;
using Dna.Structuring.Stackify;
// Load the 64 bit PE file.
// Note: This file is automatically copied to the build directory.
@@ -54,21 +56,21 @@ for (int i = 0; i < 3; i++)
//blockDcePass.Run();
// Print the optimized control flow graph.
Console.WriteLine("Optimized cfg:\n{0}", GraphFormatter.FormatGraph(liftedCfg));
//Console.WriteLine("Optimized cfg:\n{0}", GraphFormatter.FormatGraph(liftedCfg));
// Create a .DOT file for visualizing the IR cfg.
var dotGraph = GraphVisualizer.GetDotGraph(liftedCfg);
File.WriteAllText("graph.dot", dotGraph.Compile(false, false));
//var dotGraph = GraphVisualizer.GetDotGraph(liftedCfg);
//File.WriteAllText("graph.dot", dotGraph.Compile(false, false));
// Load the binary into unicorn engine.
var emulator = new UnicornEmulator(architecture);
PEMapper.MapBinary(emulator, binary);
// var emulator = new UnicornEmulator(architecture);
//PEMapper.MapBinary(emulator, binary);
// Setup the stack.
ulong rsp = 0x100000000;
emulator.MapMemory(rsp, 0x1000 * 12);
rsp += 0x100;
emulator.SetRegister(register_e.ID_REG_X86_RSP, rsp);
//ulong rsp = 0x100000000;
//emulator.MapMemory(rsp, 0x1000 * 12);
//rsp += 0x100;
//emulator.SetRegister(register_e.ID_REG_X86_RSP, rsp);
// Execute the function.
//emulator.Start(0x140001747);
@@ -99,7 +101,6 @@ passManager.AddInstructionCombiningPass();
passManager.AddCFGSimplificationPass();
passManager.AddDeadStoreEliminationPass();
passManager.AddAggressiveDCEPass();
passManager.InitializeFunctionPassManager();
for (int i = 0; i < 10; i++)
{
@@ -113,8 +114,46 @@ bool printLLVM = false;
if (printLLVM)
llvmLifter.Module.Dump();
llvmLifter.Module.PrintToFile(@"C:\Users\colton\Downloads\dfgfgfgd\code.ll");
var llPath = @"C:\Users\colton\Downloads\dfgfgfgd\code.ll";
var compiledAsmPath = @"C:\Users\colton\Downloads\dfgfgfgd\code.asm";
var wasmTextPath = @"C:\Users\colton\Downloads\dfgfgfgd\code.wat";
var wasmBinaryPath = @"C:\Users\colton\Downloads\dfgfgfgd\code.wasm";
var compiledExePath = @"C:\Users\colton\Downloads\dfgfgfgd\code.exe";
llvmLifter.Module.PrintToFile(llPath);
llvmLifter.Module.WriteBitcodeToFile(@"C:\Users\colton\Downloads\dfgfgfgd\lifted.bc");
var stackifier = new CfgStackifier();
stackifier.Stackify(liftedCfg);
Console.WriteLine("Press enter.");
Console.ReadLine();
// Compile the bitcode to a native executable.
var nativeDecompiler = new LLVMDecompiler();
//nativeDecompiler.RunClang($"{llPath} -S -o {compiledAsmPath} -O3 -target x86_64");
//nativeDecompiler.RunClang($"{compiledAsmPath} -target x86_64 -O3 -c -o {compiledExePath}");
// Compile the bitcode to wasm text.
/*
nativeDecompiler.RunClang($"{llPath} -o {compiledAsmPath} -O3 -target wasm64");
var cmd = $"{llPath} -S -o {wasmTextPath} -O3 -target wasm64";
Console.WriteLine(cmd);
nativeDecompiler.RunClang(cmd);
// Compile the bitcode to wasm binary.
var cmd2 = $"wat2wasm {wasmTextPath} -o {wasmBinaryPath}";
Console.WriteLine(cmd2);
nativeDecompiler.RunClang(cmd2);
*/
var cmd = $"{llPath} -S -o {wasmTextPath} -O3 -target wasm64";
//nativeDecompiler.RunClang(cmd);
//nativeDecompiler.RunClang($"{llPath} -S -o {wasmBinaryPath} -O3 -target wasm64");
//nativeDecompiler.RunClang($"--target=wasm64 -O3 -nostdlib {llPath} -o {wasmBinaryPath} -Wl,--no-entry");
// Decompile the bitcode to pseudo C.
nativeDecompiler.Decompile(wasmBinaryPath);
Console.WriteLine("Press enter to run rellic.");
Console.ReadLine();
// Optionally decompile the lifted function to go-to free pseudo C, via Rellic.
// On my machine, a fork of Rellic runs under WSL2 and communiucates via gRPC.
// If you are not hosting this server at localhost:50051, then the API
+5
View File
@@ -21,6 +21,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dna.Decompiler", "Dna.Decom
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unicorn.Net", "unicorn-net\src\Unicorn.Net\Unicorn.Net.csproj", "{47D397E7-098D-4058-9B19-DC01124ED897}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{09C09202-899C-4F09-9884-93AAAD5CF6A5}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+41
View File
@@ -0,0 +1,41 @@
using LLVMSharp.Interop;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebAssembly;
namespace Dna.Decompilation
{
public class LLVMDecompiler
{
// TODO: Remove hardcoded path.
private const string clangPath = @"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\x64\bin\clang.exe";
public void Decompile(string wasmPath)
{
var module = Module.ReadFromBinary(wasmPath);
Console.WriteLine(module);
}
public void RunClang(string arguments)
{
var process = new Process();
process.StartInfo.FileName = clangPath;
process.StartInfo.Arguments = arguments;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.Start();
Console.WriteLine(clangPath + " " + arguments);
process.WaitForExit();
if(process.ExitCode != 0 )
{
throw new Exception("command failed.");
}
}
}
}
+1
View File
@@ -35,6 +35,7 @@
<PackageReference Include="LLVMSharp" Version="15.0.0-beta1" />
<PackageReference Include="Microsoft.Z3" Version="4.11.2" />
<PackageReference Include="Rivers" Version="0.1.0" />
<PackageReference Include="WebAssembly" Version="1.2.1" />
</ItemGroup>
<ItemGroup>
+4 -18
View File
@@ -21,9 +21,7 @@ namespace Dna.Lifting
private readonly LLVMBuilderRef builder;
private LLVMValueRef memoryPtr;
private LLVMValueRef percentOne;
private readonly LLVMValueRef memoryPtr;
private readonly Func<IOperand, LLVMValueRef> load;
@@ -38,11 +36,6 @@ namespace Dna.Lifting
this.storeToOperand = storeToOperand;
}
public void SetMemoryPtr(LLVMValueRef percentOne)
{
this.percentOne = percentOne;
}
public void LiftInstructionToLLVM(AbstractInst instruction, Func<ulong, LLVMBasicBlockRef> getBlockByAddress)
{
LLVMValueRef? one = null;
@@ -210,13 +203,9 @@ namespace Dna.Lifting
case InstLoad inst:
// Cast the address to a pointer.
var loadValType = LLVMTypeRef.CreateInt(inst.Bitsize);
var ptrType = LLVMTypeRef.CreatePointer(loadValType, 0);
//var percentFour = builder.BuildLoad2(ptrType, memoryPtr);
var loadPointer = builder.BuildInBoundsGEP2(ptrType, percentOne, new LLVMValueRef[] { op1() });
//var loadPointer = builder.BuildIntToPtr(op1(), ptrType, "loadPtr");
//var loadPointer = builder.BuildInBoundsGEP2(ptrType, op1(), new LLVMValueRef[] {});
var loadPointer = builder.BuildIntToPtr(op1(), ptrType, "loadPtr");
// Dereference the pointer.
var loadValue = builder.BuildLoad2(loadValType, loadPointer, "load");
@@ -232,10 +221,7 @@ namespace Dna.Lifting
// Cast the destination address to a pointer of the source value width.
var storeIntType = LLVMTypeRef.CreateInt(inst.Op1.Bitsize);
var storePtrType = LLVMTypeRef.CreatePointer(storeIntType, 0);
//var percentFour2 = builder.BuildLoad2(storePtrType, memoryPtr);
//var storePtr = builder.BuildIntToPtr(storeAddr, storePtrType, "storePtr");
var storePtr = builder.BuildInBoundsGEP2(storeIntType, percentOne, new LLVMValueRef[] { storeAddr });
var storePtr = builder.BuildIntToPtr(storeAddr, storePtrType, "storePtr");
// Write to memory.
builder.BuildStore(storeValue, storePtr);
+3 -11
View File
@@ -53,14 +53,14 @@ namespace Dna.Lifting
// Constrct an LLVM module and builder.
module = LLVMModuleRef.CreateWithName("TritonTranslator");
module.Target = "x86_64";
module.Target = "wasm64";
builder = Module.Context.CreateBuilder();
// Create an i64* pointer to store memory.
var memoryPtrType = LLVMTypeRef.CreatePointer(LLVMTypeRef.CreateInt(64), 0);
var memoryPtrType = LLVMTypeRef.CreateInt(64);
memoryPtr = Module.AddGlobal(memoryPtrType, "memory");
memoryPtr.Linkage = LLVMLinkage.LLVMCommonLinkage;
var memoryPtrNull = LLVMValueRef.CreateConstPointerNull(LLVMTypeRef.CreateInt(64));
var memoryPtrNull = LLVMValueRef.CreateConstInt(memoryPtrType, 0, false);
memoryPtr.Initializer = memoryPtrNull;
// Construct an LLVM lifter for translating individual instructions.
@@ -131,14 +131,6 @@ namespace Dna.Lifting
// Lift each block to LLVM IR.
foreach(var block in irBlocks)
{
if(block == irBlocks.First())
{
var storeIntType = LLVMTypeRef.CreateInt(64);
var storePtrType = LLVMTypeRef.CreatePointer(storeIntType, 0);
var percentFour2 = builder.BuildLoad2(storePtrType, memoryPtr);
lifter.SetMemoryPtr(percentFour2);
}
builder.PositionAtEnd(liftedBlockMapping[block]);
foreach(var inst in block.Instructions)
{
@@ -6,7 +6,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dna.Structuring
namespace Dna.Structuring.Revng
{
/// <summary>
/// The following algorithm is a reimplementation from the paper:
@@ -45,7 +45,7 @@ namespace Dna.Structuring
{
// Insert a dummy node for each retreating edge.
// TODO: Add code to JMP to the correct destination.
foreach(var backEdge in backEdges)
foreach (var backEdge in backEdges)
{
var target = backEdge.TargetBlock;
var dummy = NodeInserter.InsertArtificalNode(graph);
@@ -6,7 +6,7 @@ using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
namespace Dna.Structuring
namespace Dna.Structuring.Revng
{
public static class EdgeUpdater
{
@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dna.Structuring
namespace Dna.Structuring.Revng
{
public interface IMetaRegion<T>
{
@@ -6,7 +6,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dna.Structuring
namespace Dna.Structuring.Revng
{
public class MetaRegion<T> : IMetaRegion<T>
{
@@ -38,7 +38,7 @@ namespace Dna.Structuring
{
// Remove old SCS nodes.
bool needSubstitution = false;
foreach(var node in removal)
foreach (var node in removal)
{
// Skip if the node does not need to be removed.
if (!Nodes.Contains(node))
@@ -84,7 +84,7 @@ namespace Dna.Structuring
public bool IntersectsWith(IMetaRegion<T> region)
{
// If the region contains any node from our node list, there is an intersection.
foreach(var node in Nodes)
foreach (var node in Nodes)
{
if (region.Nodes.Contains(node))
return true;
@@ -97,7 +97,7 @@ namespace Dna.Structuring
// TODO: Validate.
public bool IsSubSet(IMetaRegion<T> region)
{
foreach(var node in region.Nodes)
foreach (var node in region.Nodes)
{
if (!Nodes.Contains(node))
return false;
@@ -109,7 +109,7 @@ namespace Dna.Structuring
// TODO: Validate.
public bool IsSuperSet(IMetaRegion<T> region)
{
foreach(var node in Nodes)
foreach (var node in Nodes)
{
if (!region.Nodes.Contains(node))
return false;
@@ -134,9 +134,9 @@ namespace Dna.Structuring
public BasicBlock<T> GetProbableEntry(IEnumerable<BasicBlock<T>> reversePostOrderTraveral)
{
foreach(var node in reversePostOrderTraveral)
foreach (var node in reversePostOrderTraveral)
{
if(ContainsNode(node))
if (ContainsNode(node))
return node;
}
@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dna.Structuring
namespace Dna.Structuring.Revng
{
public class NodeInserter
{
+251
View File
@@ -0,0 +1,251 @@
using Dna.ControlFlow;
using Dna.ControlFlow.Analysis;
using Dna.Structuring.Stackify.Structured;
using Iced.Intel;
using Rivers;
using Rivers.Analysis.Traversal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TritonTranslator.Intermediate;
using static Dna.Structuring.Stackify.Structured.CtrlEntry;
namespace Dna.Structuring.Stackify
{
/// <summary>
/// Class for structuring arbitrary control flow graphs using the stackify algorithm. References:
/// - https://github.com/cfallin/waffle/blob/main/src/backend/stackify.rs
/// </summary>
public class CfgStackifier
{
private ControlFlowGraph<AbstractInst> cfg;
private Stack<CtrlEntry> ctrlStack = new Stack<CtrlEntry>();
private IReadOnlyDictionary<Node, HashSet<Node>> dominatorTree;
private HashSet<BasicBlock<AbstractInst>> loopHeaders;
private HashSet<BasicBlock<AbstractInst>> mergeNodes;
Dictionary<Node, int> rpoPositions;
public void Stackify(ControlFlowGraph<AbstractInst> cfg)
{
// Compute merge nodes and loop headers.
this.cfg = cfg;
dominatorTree = DominatorAnalysis.GetDominatorTree(cfg);
var info = ComputeMergeNodesAndLoopHeaders();
var body = new List<WasmBlock>();
HandleDomSubtree(cfg.GetBlocks().First(), ref body);
Console.WriteLine("Done");
//Console.WriteLine(info);
}
private (HashSet<BasicBlock<AbstractInst>> mergeNodes, HashSet<BasicBlock<AbstractInst>> loopHeaders) ComputeMergeNodesAndLoopHeaders()
{
loopHeaders = new HashSet<BasicBlock<AbstractInst>>();
mergeNodes = new HashSet<BasicBlock<AbstractInst>>();
var branchedOnce = new HashSet<BasicBlock<AbstractInst>>();
// Record a reverse postorder traversal of the control flow.
var traversal = new DepthFirstTraversal();
var recorder = new PostOrderRecorder(traversal);
traversal.Run(cfg.Nodes.First());
var rpo = recorder.GetOrder().Reverse().ToList();
// Store a position of each block in the RPO, if reachable.
rpoPositions = new();
for (int i = 0; i < rpo.Count; i++)
rpoPositions.Add(rpo[i], i);
// Collect a set of merge nodes and loop headers.
foreach(var entry in rpoPositions)
{
var block = entry.Key;
var blockRpo = entry.Value;
foreach(var successor in block.OutgoingEdges.Select(x => (BasicBlock<AbstractInst>)x.Target))
{
var succRpo = rpoPositions[successor];
if(succRpo <= blockRpo)
{
// If the successor node does not dominate the current block.
if (!dominatorTree[block].Contains(successor))
{
throw new InvalidOperationException("Encountered irreducible control flow.");
}
loopHeaders.Add(successor);
}
else
{
if(!branchedOnce.Add(successor))
mergeNodes.Add(successor);
}
}
}
// I *think* the algorithm does some special case here for switch cases.
// TODO: Handle switch statements.
if (cfg.Nodes.Any(x => x.OutgoingEdges.Count > 2))
throw new InvalidOperationException("TODO: Handle switch cases");
return (mergeNodes, loopHeaders);
}
private void Compute()
{
}
private void HandleDomSubtree(BasicBlock<AbstractInst> block, ref List<WasmBlock> into)
{
var mergeNodeChildren = dominatorTree[block]
.Where(x => mergeNodes.Contains(x))
.Cast<BasicBlock<AbstractInst>>()
.ToList();
// Sort merge nodes so the highest RPO number comes first.
mergeNodeChildren.OrderByDescending(x => rpoPositions[x]);
var isLoopHeader = loopHeaders.Contains(block);
if(isLoopHeader)
{
ctrlStack.Push(new CtrlEntryLoop(block));
var body = new List<WasmBlock>();
NodeWithin(block, mergeNodeChildren, ref body);
ctrlStack.Pop();
into.Add(new Loop()
{
Body = body,
Header = block,
});
}
else
{
NodeWithin(block, mergeNodeChildren, ref into);
}
}
void NodeWithin(BasicBlock<AbstractInst> block, IEnumerable<BasicBlock<AbstractInst>> mergeNodes, ref List<WasmBlock> into)
{
if (mergeNodes.Any())
{
var first = mergeNodes.First();
ctrlStack.Push(new CtrlEntryBlock(first));
var body = new List<WasmBlock>();
NodeWithin(block, mergeNodes.Skip(1), ref body);
into.Add(new Block()
{
Body = body,
Out = first
});
ctrlStack.Pop();
HandleDomSubtree(first, ref into);
}
else
{
into.Add(new Leaf()
{
Block = block,
});
switch(block.ExitInstruction)
{
case InstJmp inst:
var target = cfg.GetBlocks().Single(x => x.Address == inst.JumpDestination.Value);
DoBranch(block, target, ref into);
break;
case InstJcc inst:
// Compute the blocks which are taken depending on the JCC.
var thenBlock = cfg.GetBlocks().Single(x => x.Address == inst.ThenOp.Value);
var elseBlock = cfg.GetBlocks().Single(x => x.Address == inst.ElseOp.Value);
// Push an ITE node.
ctrlStack.Push(new CtrlEntryIfThenElse());
// Handle the true block.
var ifTrueBody = new List<WasmBlock>();
DoBranch(block, thenBlock, ref ifTrueBody);
// Handle the false block.
var ifFalseBody = new List<WasmBlock>();
DoBranch(block, elseBlock, ref ifFalseBody);
// Push the if statement.
ctrlStack.Pop();
into.Add(new If()
{
Cond = inst.Op1,
IfTrue = ifTrueBody,
IfFalse = ifFalseBody,
});
break;
case InstRet:
into.Add(new Return());
break;
default:
throw new Exception($"Handle handle terminator {block.ExitInstruction}");
}
}
}
private void DoBranch(BasicBlock<AbstractInst> source, BasicBlock<AbstractInst> target, ref List<WasmBlock> into)
{
// This will be a branch to some entry in the control stack if
// the target is either a merge block, or is a backward branch
// (by RPO number).
if(mergeNodes.Contains(target) || rpoPositions[target] <= rpoPositions[source])
{
var index = ResolveTarget(target);
DoBlockParamTransfer(ref into);
into.Add(new Br()
{
Target = index,
});
}
else
{
// Otherwise, we must dominate the block, so just emit it inline.
if (!dominatorTree[target].Contains(source))
throw new InvalidOperationException($"Expected target node {target} to be dominated by source {source}.");
DoBlockParamTransfer(ref into);
HandleDomSubtree(target, ref into);
}
}
private WasmLabel ResolveTarget(BasicBlock<AbstractInst> target)
{
// This is horribly inefficient. TODO: Refactor.
var index = ctrlStack
.Reverse()
.ToList()
.FindIndex(x => x.Label() == target);
if (index == -1)
throw new InvalidOperationException();
return new WasmLabel(index);
}
private void DoBlockParamTransfer(ref List<WasmBlock> into)
{
// Our IR does not have block params, so we do nothing.
// Still, we have to push this empty entry since the rest
// of the algorithm expects this to be on the stack.
into.Add(new BlockParams());
}
}
}
@@ -0,0 +1,17 @@
using Dna.ControlFlow;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TritonTranslator.Intermediate;
namespace Dna.Structuring.Stackify.Structured
{
public class Block : WasmBlock
{
public List<WasmBlock> Body { get; set; } = new();
public BasicBlock<AbstractInst> Out { get; set; }
}
}
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dna.Structuring.Stackify.Structured
{
public class BlockParams : WasmBlock
{
}
}
+13
View File
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dna.Structuring.Stackify.Structured
{
public class Br : WasmBlock
{
public WasmLabel Target { get; set; }
}
}
@@ -0,0 +1,35 @@
using Dna.ControlFlow;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TritonTranslator.Intermediate;
namespace Dna.Structuring.Stackify.Structured
{
public enum CtrlEntryType
{
Block,
Loop,
IfThenElse,
}
public abstract record CtrlEntry
{
public record CtrlEntryBlock(BasicBlock<AbstractInst> outBlock) : CtrlEntry();
public record CtrlEntryLoop(BasicBlock<AbstractInst> header) : CtrlEntry();
public record CtrlEntryIfThenElse() : CtrlEntry();
public BasicBlock<AbstractInst> Label()
{
return this switch
{
CtrlEntryBlock ctrl => ctrl.outBlock,
CtrlEntryLoop ctrl => ctrl.header,
CtrlEntryIfThenElse ctrl => null,
_ => throw new InvalidOperationException($"Cannot get label for {this}"),
};
}
}
}
+18
View File
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TritonTranslator.Intermediate.Operands;
namespace Dna.Structuring.Stackify.Structured
{
public class If : WasmBlock
{
public IOperand Cond { get; set; }
public List<WasmBlock> IfTrue { get; set; } = new();
public List<WasmBlock> IfFalse { get; set; } = new();
}
}
@@ -0,0 +1,15 @@
using Dna.ControlFlow;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TritonTranslator.Intermediate;
namespace Dna.Structuring.Stackify.Structured
{
public class Leaf : WasmBlock
{
public BasicBlock<AbstractInst> Block { get; set; }
}
}
@@ -0,0 +1,17 @@
using Dna.ControlFlow;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TritonTranslator.Intermediate;
namespace Dna.Structuring.Stackify.Structured
{
public class Loop : WasmBlock
{
public List<WasmBlock> Body { get; set; } = new();
public BasicBlock<AbstractInst> Header { get; set; }
}
}
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TritonTranslator.Intermediate.Operands;
namespace Dna.Structuring.Stackify.Structured
{
public class Return : WasmBlock
{
public List<IOperand> Values { get; set; } = new();
}
}
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TritonTranslator.Intermediate.Operands;
namespace Dna.Structuring.Stackify.Structured
{
public class Select : WasmBlock
{
public IOperand Selector { get; set; }
public List<WasmLabel> Targets { get; set; } = new();
public WasmLabel Default { get; set; }
}
}
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dna.Structuring.Stackify.Structured
{
public class Unreachable : WasmBlock
{
}
}
@@ -0,0 +1,15 @@
using Dna.ControlFlow;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TritonTranslator.Intermediate;
namespace Dna.Structuring.Stackify.Structured
{
public class WasmBlock
{
}
}
@@ -0,0 +1,21 @@
using Dna.ControlFlow;
using LLVMSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TritonTranslator.Intermediate;
namespace Dna.Structuring.Stackify.Structured
{
public class WasmLabel
{
public int Index { get; set; }
public WasmLabel(int index)
{
Index = index;
}
}
}