public void ExceptionHandlerWithPrologueAndEpilogue() { var ranges = new[] { new ExceptionHandlerRange( new AddressRange(1, 3), new AddressRange(3, 5), new AddressRange(5, 7), new AddressRange(7, 9)) }; var instructions = new[] { DummyInstruction.Op(0, 0, 0), // try start DummyInstruction.Op(1, 0, 0), DummyInstruction.Jmp(2, 9), // handler prologue start DummyInstruction.Op(3, 0, 0), DummyInstruction.Ret(4), // handler start DummyInstruction.Op(5, 0, 0), DummyInstruction.Jmp(6, 9), // handler epilogue start DummyInstruction.Op(7, 0, 0), DummyInstruction.Ret(8), DummyInstruction.Ret(9), }; var cfg = ConstructGraphWithEHRegions(instructions, ranges); var rootScope = cfg.ConstructBlocks(); Assert.Equal(3, rootScope.Blocks.Count); var ehBlock = Assert.IsAssignableFrom <ExceptionHandlerBlock <DummyInstruction> >(rootScope.Blocks[1]); Assert.Equal(new[] { 1L }, ehBlock.ProtectedBlock.GetAllBlocks().Select(b => b.Offset)); var handlerBlock = Assert.Single(ehBlock.Handlers); Assert.NotNull(handlerBlock); Assert.Equal(new[] { 3L }, handlerBlock.Prologue.GetAllBlocks().Select(b => b.Offset)); Assert.Equal(new[] { 5L }, handlerBlock.Contents.GetAllBlocks().Select(b => b.Offset)); Assert.Equal(new[] { 7L }, handlerBlock.Epilogue.GetAllBlocks().Select(b => b.Offset)); }
public void RootNodesShouldHaveNoParent() { var ast = ConstructAst(new[] { DummyInstruction.Push(0, 1), DummyInstruction.Push(1, 2), DummyInstruction.Op(2, 2, 1), DummyInstruction.Op(3, 2, 0), DummyInstruction.Ret(4) }); Assert.Single(ast.Nodes); var block = ast.Entrypoint.Contents.Instructions; Assert.Equal(5, block.Count); Assert.All(block, node => Assert.Null(node.Parent)); }
public void JumpBackToFarBlock() { var instructions = new[] { DummyInstruction.Pop(0, 1), DummyInstruction.Ret(1), DummyInstruction.Push(100, 1), DummyInstruction.Jmp(101, 0), }; var(cfg, dfg) = BuildFlowGraphs(instructions, 100); Assert.Equal(new[] { 0L, 100L }, cfg.Nodes.Select(n => n.Offset)); }
public void JoiningPathsWithDifferentStackHeightsShouldThrow() { var instructions = new[] { DummyInstruction.Push(0, 1), DummyInstruction.JmpCond(1, 4), DummyInstruction.Push(2, 2), DummyInstruction.Jmp(3, 5), DummyInstruction.Push(4, 1), DummyInstruction.Pop(5, 1), DummyInstruction.Ret(6) }; Assert.Throws <StackImbalanceException>(() => BuildFlowGraphs(instructions)); }
public void JumpForwardToFarBlock() { var instructions = new[] { DummyInstruction.Push(0, 1), DummyInstruction.Jmp(1, 100), DummyInstruction.Pop(100, 1), DummyInstruction.Ret(101), }; var graph = BuildControlFlowGraph(instructions); Assert.Equal(new[] { 0L, 100L }, graph.Nodes.Select(n => n.Offset)); }
public void SingleBlock() { var instructions = new[] { DummyInstruction.Push(0, 1), DummyInstruction.Push(1, 1), DummyInstruction.Op(2, 2, 1), DummyInstruction.Push(3, 1), DummyInstruction.Push(4, 1), DummyInstruction.Ret(5) }; var graph = BuildControlFlowGraph(instructions); Assert.Single(graph.Nodes); Assert.Equal(instructions, graph.Nodes.First().Contents.Instructions); Assert.Equal(graph.Nodes.First(), graph.Entrypoint); }
public void BranchTargetChangeToAnotherNodeHeaderShouldUpdateFallThroughEdge() { var cfg = BuildControlFlowGraph(new[] { DummyInstruction.Op(0, 0, 0), DummyInstruction.Jmp(1, 10), DummyInstruction.Jmp(10, 20), DummyInstruction.Ret(20) }); // Change branch target of the first jmp to the ret at offset 20. cfg.Nodes[0].Contents.Footer.Operands[0] = 20L; Assert.True(cfg.UpdateFlowControl(DummyArchitecture.Instance.SuccessorResolver)); Assert.Same(cfg.Nodes[20], cfg.Nodes[0].FallThroughNeighbour); }
public void BlockHeadersImpliedByInstructionsShouldAlwaysBeAdded() { var instructions = new[] { DummyInstruction.PushOffset(0, 10), DummyInstruction.Ret(1), DummyInstruction.Op(10, 0, 0), DummyInstruction.Ret(11), }; var(cfg, _) = BuildFlowGraphs(instructions); Assert.Contains(cfg.Nodes, n => n.Offset == 0); Assert.Contains(cfg.Nodes, n => n.Offset == 10); Assert.DoesNotContain(cfg.Nodes, n => n.Offset == 1); Assert.Empty(cfg.Nodes[0].GetOutgoingEdges()); Assert.Empty(cfg.Nodes[10].GetIncomingEdges()); }
public void WeirdOrder() { var instructions = new[] { DummyInstruction.Op(0, 0, 0), DummyInstruction.Op(1, 0, 0), DummyInstruction.Op(2, 0, 0), DummyInstruction.Jmp(3, 6), DummyInstruction.Op(4, 0, 0), DummyInstruction.Ret(5), DummyInstruction.Op(6, 0, 0), DummyInstruction.Op(7, 0, 0), DummyInstruction.Jmp(8, 15), DummyInstruction.Op(9, 0, 0), DummyInstruction.Op(10, 0, 0), DummyInstruction.Jmp(11, 4), DummyInstruction.Op(12, 0, 0), DummyInstruction.Op(13, 0, 0), DummyInstruction.Jmp(14, 9), DummyInstruction.Op(15, 0, 0), DummyInstruction.Op(16, 0, 0), DummyInstruction.Jmp(17, 12), }; var cfgBuilder = new StaticFlowGraphBuilder <DummyInstruction>( DummyArchitecture.Instance, instructions, DummyArchitecture.Instance.SuccessorResolver); var cfg = cfgBuilder.ConstructFlowGraph(0); var blockBuilder = new BlockBuilder <DummyInstruction>(); var rootScope = blockBuilder.ConstructBlocks(cfg); var order = rootScope.GetAllBlocks().ToArray(); Assert.Equal( new long[] { 0, 6, 15, 12, 9, 4 }, order.Select(b => b.Offset)); }
public void PushingTwoValuesOnStackShouldResultInTwoVariablesAssigned() { var cfg = ConstructAst(new[] { DummyInstruction.Push(0, 2), DummyInstruction.Pop(1, 2), DummyInstruction.Ret(2) }); var variableCapture = new CaptureGroup("variable"); var argumentsCapture = new CaptureGroup("argument"); var pattern = new SequencePattern <Statement <DummyInstruction> >( // stack_slot_1, stack_slot_2 = push 2() StatementPattern .Assignment <DummyInstruction>() .WithVariables(2) .CaptureVariables(variableCapture), // pop(?, ?) StatementPattern.Expression(ExpressionPattern .Instruction <DummyInstruction>() .WithArguments(2) .CaptureArguments(argumentsCapture)), // ret() StatementPattern.Instruction(new DummyInstructionPattern(DummyOpCode.Ret)) ); var result = pattern.Match(cfg.Nodes[0].Contents.Instructions); Assert.True(result.IsSuccess); var variables = result.Captures[variableCapture] .Cast <IVariable>() .ToArray(); var arguments = result.Captures[argumentsCapture] .Cast <VariableExpression <DummyInstruction> >() .Select(e => e.Variable) .ToArray(); Assert.Equal(variables, arguments); }
public void MultiplePopsShouldHaveMultipleStackDependencies() { var instructions = new[] { DummyInstruction.Push(0, 1), DummyInstruction.Push(1, 1), DummyInstruction.Push(2, 1), DummyInstruction.Pop(3, 3), DummyInstruction.Ret(4) }; var(cfg, dfg) = BuildFlowGraphs(instructions); Assert.Equal(3, dfg.Nodes[3].StackDependencies.Count); Assert.Equal(new[] { dfg.Nodes[0], dfg.Nodes[1], dfg.Nodes[2], }, dfg.Nodes[3].StackDependencies.Select(dep => dep.First().Node)); }
public void SwitchWithAssignmentsToSameVariableShouldResultInPhiNodeWithTheSameNumberOfSources() { var variable = new DummyVariable("temp"); var cfg = ConstructAst(new[] { // switch(some_value) DummyInstruction.Push(0, 1), DummyInstruction.Switch(1, 5, 8, 11), // default: DummyInstruction.Push(2, 1), DummyInstruction.Set(3, variable), DummyInstruction.Jmp(4, 13), // case 0: DummyInstruction.Push(5, 1), DummyInstruction.Set(6, variable), DummyInstruction.Jmp(7, 13), // case 1: DummyInstruction.Push(8, 1), DummyInstruction.Set(9, variable), DummyInstruction.Jmp(10, 13), // case 2: DummyInstruction.Push(11, 1), DummyInstruction.Set(12, variable), // end: DummyInstruction.Get(13, variable), DummyInstruction.Pop(14, 1), DummyInstruction.Ret(15) }); // variable = phi(?, ?) var phiPattern = StatementPattern .Phi <DummyInstruction>() .WithSources(4); Assert.True(phiPattern.Matches(cfg.Nodes[13].Contents.Header), "Node 13 was expected to start with a phi node with 4 sources."); }
public void AddBranchInMiddleOfBlockShouldSplit() { var instructions = new[] { DummyInstruction.Op(0, 0, 0), DummyInstruction.Op(1, 0, 0), DummyInstruction.Op(2, 0, 0), DummyInstruction.Op(3, 0, 0), DummyInstruction.Ret(4), }; var cfg = BuildControlFlowGraph(instructions, 0); cfg.Nodes[0].Contents.Instructions[1] = DummyInstruction.Jmp(1, 4); cfg.UpdateFlowControl(DummyArchitecture.Instance.SuccessorResolver); Assert.True(cfg.Nodes.Contains(0)); Assert.True(cfg.Nodes.Contains(4)); Assert.Same(cfg.Nodes[4], cfg.Nodes[0].FallThroughNeighbour); }
public void EntryPointPopWithInitialStateEmptyShouldThrow() { var instructions = new[] { DummyInstruction.Pop(0, 1), DummyInstruction.Ret(1), }; var dfgBuilder = new DummyTransitionResolver { InitialState = new SymbolicProgramState <DummyInstruction>() }; var cfgBuilder = new SymbolicFlowGraphBuilder <DummyInstruction>( DummyArchitecture.Instance, instructions, dfgBuilder); Assert.Throws <StackImbalanceException>(() => cfgBuilder.ConstructFlowGraph(0)); }
public void ReplacingInstructionInInstructionExpression() { var ast = ConstructAst(new[] { DummyInstruction.Push(0, 1), DummyInstruction.Pop(1, 1), DummyInstruction.Ret(2) }); Assert.Single(ast.Nodes); var block = ast.Entrypoint.Contents.Instructions; Assert.Equal(3, block.Count); Assert.All(block, node => Assert.Null(node.Parent)); var instruction = DummyInstruction.Jmp(0, 69); var asmt = Assert.IsType <AssignmentStatement <DummyInstruction> >(block[0]); var expr = Assert.IsType <InstructionExpression <DummyInstruction> >(asmt.Expression); Assert.Equal(instruction, expr.WithInstruction(instruction).Instruction); }
public void EHWithMultipleHandlersByRangesShouldGroupTogether(bool reverse) { var ranges = new[] { new ExceptionHandlerRange(new AddressRange(1, 3), new AddressRange(3, 5)), new ExceptionHandlerRange(new AddressRange(1, 3), new AddressRange(5, 7)), }; if (reverse) { Array.Reverse(ranges); } var instructions = new[] { DummyInstruction.Op(0, 0, 0), // try start 1 & 2 DummyInstruction.Op(1, 0, 0), DummyInstruction.Jmp(2, 7), // handler start 2 DummyInstruction.Op(3, 0, 0), DummyInstruction.Jmp(4, 7), // handler start 1 DummyInstruction.Op(5, 0, 0), DummyInstruction.Jmp(6, 7), DummyInstruction.Ret(7), }; var cfg = ConstructGraphWithEHRegions(instructions, ranges); var ehRegion = cfg.Nodes[1].GetParentExceptionHandler(); Assert.Same(ehRegion, cfg.Nodes[3].GetParentExceptionHandler()); Assert.Same(ehRegion, cfg.Nodes[5].GetParentExceptionHandler()); Assert.NotSame(cfg.Nodes[3].ParentRegion, cfg.Nodes[5].ParentRegion); }
public void BasicRegionShouldTranslateToSingleScopeBlock() { var instructions = new[] { DummyInstruction.Push(0, 1), DummyInstruction.JmpCond(1, 4), DummyInstruction.Op(2, 0, 0), DummyInstruction.Jmp(3, 4), DummyInstruction.Op(4, 0, 0), DummyInstruction.Ret(5), }; var cfgBuilder = new StaticFlowGraphBuilder <DummyInstruction>( DummyArchitecture.Instance, instructions, DummyArchitecture.Instance.SuccessorResolver); var cfg = cfgBuilder.ConstructFlowGraph(0); var region = new BasicControlFlowRegion <DummyInstruction>(); cfg.Regions.Add(region); region.Nodes.Add(cfg.Nodes[2]); var blockBuilder = new BlockBuilder <DummyInstruction>(); var rootScope = blockBuilder.ConstructBlocks(cfg); Assert.Equal(3, rootScope.Blocks.Count); Assert.IsAssignableFrom <BasicBlock <DummyInstruction> >(rootScope.Blocks[0]); Assert.IsAssignableFrom <ScopeBlock <DummyInstruction> >(rootScope.Blocks[1]); Assert.IsAssignableFrom <BasicBlock <DummyInstruction> >(rootScope.Blocks[2]); var order = rootScope.GetAllBlocks().ToArray(); Assert.Equal( new long[] { 0, 2, 4 }, order.Select(b => b.Offset)); }
public void SplittedNodeShouldBeRemergedAfterDetectingInvalidFallThroughNeighbour() { var instructions = new[] { DummyInstruction.Op(0, 0, 0), DummyInstruction.Jmp(1, 10), DummyInstruction.Op(10, 0, 0), DummyInstruction.Op(11, 0, 0), DummyInstruction.Op(12, 0, 0), DummyInstruction.Jmp(13, 20), DummyInstruction.Ret(20), }; var cfg = BuildControlFlowGraph(instructions, 0); instructions[1].Operands[0] = 12L; instructions[5].Operands[0] = 100L; Assert.Throws <ArgumentException>(() => cfg.UpdateFlowControl(DummyArchitecture.Instance.SuccessorResolver)); Assert.Same(cfg.Nodes[10], cfg.Nodes[0].FallThroughNeighbour); Assert.False(cfg.Nodes.Contains(12)); }
public void LoopCounterShouldResultInOnlyOnePhiNode() { var counterVariable = new DummyVariable("i"); var cfg = ConstructAst(new[] { // i = initial(); DummyInstruction.Push(0, 1), DummyInstruction.Set(1, counterVariable), // loop: // if (cond(i)) goto end; DummyInstruction.Get(2, counterVariable), DummyInstruction.JmpCond(3, 9), // Loop body. DummyInstruction.Op(4, 0, 0), // i = next(i); // goto loop DummyInstruction.Get(5, counterVariable), DummyInstruction.Op(6, 1, 1), DummyInstruction.Set(7, counterVariable), DummyInstruction.Jmp(8, 2), // end: DummyInstruction.Ret(9) }); // variable = phi(?, ?) var phiPattern = StatementPattern .Phi <DummyInstruction>() .WithSources(2); Assert.True(phiPattern.Matches(cfg.Nodes[2].Contents.Header)); Assert.All(cfg.Nodes[0].Contents.Instructions, s => Assert.False(phiPattern.Matches(s))); Assert.All(cfg.Nodes[4].Contents.Instructions, s => Assert.False(phiPattern.Matches(s))); Assert.All(cfg.Nodes[9].Contents.Instructions, s => Assert.False(phiPattern.Matches(s))); }
public void ReplacingExpressionInStatementShouldChangeParent() { var ast = ConstructAst(new[] { DummyInstruction.Push(0, 2), DummyInstruction.Pop(1, 2), DummyInstruction.Ret(2) }); Assert.Single(ast.Nodes); var block = ast.Entrypoint.Contents.Instructions; Assert.Equal(3, block.Count); Assert.All(block, node => Assert.Null(node.Parent)); var expr = new InstructionExpression <DummyInstruction>(DummyInstruction.Jmp(0, 69), Array.Empty <Expression <DummyInstruction> >()); var stmt = Assert.IsType <ExpressionStatement <DummyInstruction> >(block[1]); Assert.Equal(expr, stmt.WithExpression(expr).Expression); Assert.Equal(stmt, expr.Parent); }
public static ControlFlowGraph <DummyInstruction> CreateIf() { var graph = new ControlFlowGraph <DummyInstruction>(DummyArchitecture.Instance); var n1 = new ControlFlowNode <DummyInstruction>(0, DummyInstruction.Op(0, 0, 1), DummyInstruction.JmpCond(1, 3)); var n2 = new ControlFlowNode <DummyInstruction>(2, DummyInstruction.Op(2, 0, 0)); var n3 = new ControlFlowNode <DummyInstruction>(3, DummyInstruction.Ret(3)); graph.Nodes.AddRange(new[] { n1, n2, n3 }); graph.Entrypoint = n1; n1.ConnectWith(n2); n1.ConnectWith(n3, ControlFlowEdgeType.Conditional); n2.ConnectWith(n3); return(graph); }
public void FlatGraphShouldProduceFlatBlock() { var instructions = new[] { DummyInstruction.Op(0, 0, 0), DummyInstruction.Op(1, 0, 0), DummyInstruction.Op(2, 0, 0), DummyInstruction.Op(3, 0, 0), DummyInstruction.Ret(4), }; var cfgBuilder = new StaticFlowGraphBuilder <DummyInstruction>( DummyArchitecture.Instance, instructions, DummyArchitecture.Instance.SuccessorResolver); var cfg = cfgBuilder.ConstructFlowGraph(0); var rootScope = cfg.ConstructBlocks(); Assert.Single(rootScope.Blocks); Assert.IsAssignableFrom <BasicBlock <DummyInstruction> >(rootScope.Blocks[0]); Assert.Equal(instructions, ((BasicBlock <DummyInstruction>)rootScope.Blocks[0]).Instructions); }
public static ControlFlowGraph <DummyInstruction> CreateIfElseNested() { var graph = new ControlFlowGraph <DummyInstruction>(DummyArchitecture.Instance); var n1 = new ControlFlowNode <DummyInstruction>(0, DummyInstruction.Op(0, 0, 1), DummyInstruction.JmpCond(1, 7)); var n2 = new ControlFlowNode <DummyInstruction>(2, DummyInstruction.Op(2, 0, 1), DummyInstruction.JmpCond(3, 4)); var n3 = new ControlFlowNode <DummyInstruction>(4, DummyInstruction.Jmp(4, 6)); var n4 = new ControlFlowNode <DummyInstruction>(5, DummyInstruction.Jmp(5, 6)); var n5 = new ControlFlowNode <DummyInstruction>(6, DummyInstruction.Jmp(6, 7)); var n6 = new ControlFlowNode <DummyInstruction>(7, DummyInstruction.Ret(7)); graph.Nodes.AddRange(new[] { n1, n2, n3, n4, n5, n6 }); graph.Entrypoint = n1; n1.ConnectWith(n2); n1.ConnectWith(n6, ControlFlowEdgeType.Conditional); n2.ConnectWith(n3); n2.ConnectWith(n4, ControlFlowEdgeType.Conditional); n3.ConnectWith(n5); n4.ConnectWith(n5); n5.ConnectWith(n6); return(graph); }
public void EHWithMultipleHandlersByRangesShouldGroupTogether() { var ranges = new[] { new ExceptionHandlerRange(new AddressRange(1, 3), new AddressRange(3, 5)), new ExceptionHandlerRange(new AddressRange(1, 3), new AddressRange(5, 7)), }; var instructions = new[] { DummyInstruction.Op(0, 0, 0), // try start 1 & 2 DummyInstruction.Op(1, 0, 0), DummyInstruction.Jmp(2, 7), // handler start 2 DummyInstruction.Op(3, 0, 0), DummyInstruction.Jmp(4, 7), // handler start 1 DummyInstruction.Op(5, 0, 0), DummyInstruction.Jmp(6, 7), DummyInstruction.Ret(7), }; var cfg = ConstructGraphWithEHRegions(instructions, ranges); var blockBuilder = new BlockBuilder <DummyInstruction>(); var rootScope = blockBuilder.ConstructBlocks(cfg); var order = rootScope.GetAllBlocks().ToArray(); Assert.Equal(3, rootScope.Blocks.Count); Assert.IsAssignableFrom <ExceptionHandlerBlock <DummyInstruction> >(rootScope.Blocks[1]); Assert.Equal(2, ((ExceptionHandlerBlock <DummyInstruction>)rootScope.Blocks[1]).HandlerBlocks.Count); }
public void SwapUnconditionalWithConditionalBranchShouldUpdateFallThroughAndConditionalEdge() { var cfg = BuildControlFlowGraph(new[] { DummyInstruction.Push(0, 1), DummyInstruction.Jmp(1, 10), DummyInstruction.Jmp(2, 20), DummyInstruction.Jmp(10, 2), DummyInstruction.Ret(20) }, 0); // Update unconditional jmp to a conditional one. var blockInstructions = cfg.Nodes[0].Contents.Instructions; blockInstructions[blockInstructions.Count - 1] = DummyInstruction.JmpCond(1, 20); Assert.True(cfg.UpdateFlowControl(DummyArchitecture.Instance.SuccessorResolver)); Assert.Same(cfg.Nodes[2], cfg.Nodes[0].FallThroughNeighbour); Assert.Single(cfg.Nodes[0].ConditionalEdges); Assert.True(cfg.Nodes[0].ConditionalEdges.Contains(cfg.Nodes[20])); }
public void BranchingPathsShouldCopyDependency() { var instructions = new[] { DummyInstruction.Push(0, 1), DummyInstruction.Push(1, 1), DummyInstruction.JmpCond(2, 5), DummyInstruction.Pop(3, 1), DummyInstruction.Jmp(4, 6), DummyInstruction.Pop(5, 1), DummyInstruction.Ret(6) }; var(cfg, dfg) = BuildFlowGraphs(instructions); Assert.Single(dfg.Nodes[3].StackDependencies); Assert.Equal(dfg.Nodes[0], dfg.Nodes[3].StackDependencies[0].First().Node); Assert.Single(dfg.Nodes[5].StackDependencies); Assert.Equal(dfg.Nodes[0], dfg.Nodes[5].StackDependencies[0].First().Node); }
public void ReplacingVariablesInAssignmentShouldGetRidOfOldOnes() { var var1 = new DummyVariable("1"); var ast = ConstructAst(new[] { DummyInstruction.Push(0, 1), DummyInstruction.Set(1, var1), DummyInstruction.Ret(2), }); Assert.Single(ast.Nodes); var block = ast.Entrypoint.Contents.Instructions; Assert.Equal(3, block.Count); Assert.All(block, node => Assert.Null(node.Parent)); var var2 = new DummyVariable("2"); var var3 = new DummyVariable("3"); var asmt = Assert.IsType <AssignmentStatement <DummyInstruction> >(block[1]); Assert.Equal(2, asmt.WithVariables(var2, var3).Variables.Count); Assert.Equal(asmt.Variables[0], var2); Assert.Equal(asmt.Variables[1], var3); }
public void TestComplexCapture() { var valueExpression = new InstructionExpression <DummyInstruction>(DummyInstruction.Push(0, 1), ArraySegment <Expression <DummyInstruction> > .Empty); var statement = new ExpressionStatement <DummyInstruction>(new InstructionExpression <DummyInstruction>(DummyInstruction.Ret(1), new List <Expression <DummyInstruction> > { valueExpression })); // Define capture group. var returnValueGroup = new CaptureGroup("returnValue"); // Create ret(?) pattern. var pattern = StatementPattern.Expression( ExpressionPattern .Instruction(new DummyInstructionPattern(DummyOpCode.Ret)) .WithArguments( ExpressionPattern.Any <DummyInstruction>().CaptureAs(returnValueGroup) ) ); // Match. var result = pattern.Match(statement); // Extract return expression node. var capturedObject = result.Captures[returnValueGroup][0]; Assert.Same(valueExpression, capturedObject); }
public void JoiningPathsWithMultipleAssignmentsShouldOnlyUseLatestVersion() { var variable = new DummyVariable("temp"); var cfg = ConstructAst(new[] { // if (cond) goto else: DummyInstruction.Push(0, 1), DummyInstruction.JmpCond(1, 7), // temp = some_value (not used). DummyInstruction.Push(2, 1), DummyInstruction.Set(3, variable), // temp = some_value (render previous value useless) DummyInstruction.Push(4, 1), DummyInstruction.Set(5, variable), // goto end DummyInstruction.Jmp(6, 9), // else: // temp = some_value DummyInstruction.Push(7, 1), DummyInstruction.Set(8, variable), // end: // pop(temp) DummyInstruction.Get(9, variable), DummyInstruction.Pop(10, 1), // return DummyInstruction.Ret(11) }); var phiSourcesCapture = new CaptureGroup("sources"); var variablesCapture = new CaptureGroup("variables"); // variable = phi(?, ?) var phiPattern = StatementPattern .Phi <DummyInstruction>() .WithSources(2) .CaptureSources(phiSourcesCapture); // temp_vx = set(?) var assignPattern = StatementPattern .Assignment <DummyInstruction>() .WithExpression(ExpressionPattern .Instruction(new DummyInstructionPattern(DummyOpCode.Set)) .WithArguments(1)) .CaptureVariables(variablesCapture); var assignment1Results = assignPattern .FindAllMatches(cfg.Nodes[7].Contents.Instructions) .ToArray(); var assignment2Results = assignPattern .FindAllMatches(cfg.Nodes[2].Contents.Instructions) .ToArray(); var phiResult = phiPattern.Match(cfg.Nodes[9].Contents.Header); Assert.True(assignment1Results.Length == 1, "Node 7 was expected to have one assignment to 'temp'."); Assert.True(assignment2Results.Length == 2, "Node 2 was expected to have two assignments to 'temp'."); Assert.True(phiResult.IsSuccess, "Node 9 was expected to start with a phi node with two sources."); var sources = phiResult.Captures[phiSourcesCapture] .Cast <VariableExpression <DummyInstruction> >() .Select(s => s.Variable); var allVariables = new[] { (IVariable)assignment1Results[0].Captures[variablesCapture][0], (IVariable)assignment2Results[1].Captures[variablesCapture][0] }; Assert.Equal(allVariables.ToHashSet(), sources.ToHashSet()); }
private static DataFlowNode <DummyInstruction> CreateDummyNode(long id) { return(new DataFlowNode <DummyInstruction>(id, DummyInstruction.Op(id, 0, 1))); }