Exemplo n.º 1
0
        public void AnyVariableExpressionShouldMatch()
        {
            var variable = new DummyVariable("variable");
            var pattern  = ExpressionPattern.Variable <DummyInstruction>();

            Assert.True(pattern.Matches(new VariableExpression <DummyInstruction>(variable)));
        }
Exemplo n.º 2
0
        public void ReplacingSourcesInPhiStatement()
        {
            var target   = new DummyVariable("target");
            var sources1 = new[]
            {
                new DummyVariable("source1"),
                new DummyVariable("source2"),
                new DummyVariable("source3"),
                new DummyVariable("source4")
            };
            var sources2 = new[]
            {
                new DummyVariable("newSource1"),
                new DummyVariable("newSource2"),
                new DummyVariable("newSource3"),
                new DummyVariable("newSource4"),
                new DummyVariable("newSource5")
            };
            var phi = new PhiStatement <DummyInstruction>(
                target, sources1.Select(s => new VariableExpression <DummyInstruction>(s)));

            var sourceExpr = sources2.Select(s => new VariableExpression <DummyInstruction>(s)).ToList();

            phi.WithSources(sourceExpr);

            Assert.Equal(5, phi.Sources.Count);
            Assert.All(phi.Sources, s =>
            {
                Assert.Equal(phi, s.Parent);
                Assert.Equal(sources2[sourceExpr.IndexOf(s)], s.Variable);
            });
        }
Exemplo n.º 3
0
        public void IgnoreStackDependenciesWhenNotIncluded()
        {
            var variable = new DummyVariable("v1");

            var dfg = new DataFlowGraph <int>(IntArchitecture.Instance);
            var n1  = dfg.Nodes.Add(1, 1);
            var n2  = dfg.Nodes.Add(2, 2);
            var n3  = dfg.Nodes.Add(3, 3);
            var n4  = dfg.Nodes.Add(4, 4);
            var n5  = dfg.Nodes.Add(5, 5);

            n1.StackDependencies.SetCount(1);
            n1.StackDependencies[0].Add(n2);

            var dependency = new VariableDependency <int>(variable);

            n1.VariableDependencies.Add(dependency);
            dependency.Add(n3);

            n3.StackDependencies.SetCount(1);
            n3.StackDependencies[0].Add(n4);

            dependency = new VariableDependency <int>(variable);
            n3.VariableDependencies.Add(dependency);
            dependency.Add(n5);

            Assert.Equal(new[]
            {
                n5, n3, n1
            }, n1.GetOrderedDependencies(DependencyCollectionFlags.IncludeVariableDependencies));
        }
Exemplo n.º 4
0
        private string AddLocalVariable(DummyVariable incrementor, Type type)
        {
            string localName = incrementor.GetNext();

            _currentOperand = _g.Local(type);
            _localVariablesTable.Add(localName, _currentOperand);
            return(localName);
        }
Exemplo n.º 5
0
        public void JoiningControlFlowPathsWithDifferentVariableVersionsShouldResultInPhiNode()
        {
            var variable = new DummyVariable("temp");

            var cfg = ConstructAst(new[]
            {
                DummyInstruction.Push(0, 1),
                DummyInstruction.JmpCond(1, 5),

                DummyInstruction.Push(2, 1),
                DummyInstruction.Set(3, variable),
                DummyInstruction.Jmp(4, 7),

                DummyInstruction.Push(5, 1),
                DummyInstruction.Set(6, variable),

                DummyInstruction.Get(7, variable),
                DummyInstruction.Pop(8, 1),
                DummyInstruction.Ret(9)
            });

            var phiSourcesCapture = new CaptureGroup("sources");
            var variablesCapture  = new CaptureGroup("variables");

            // temp_vx = set(?)
            var assignPattern = StatementPattern
                                .Assignment <DummyInstruction>()
                                .WithExpression(ExpressionPattern
                                                .Instruction(new DummyInstructionPattern(DummyOpCode.Set))
                                                .WithArguments(1))
                                .CaptureVariables(variablesCapture);

            // variable = phi(?, ?)
            var phiPattern = StatementPattern
                             .Phi <DummyInstruction>()
                             .WithSources(2)
                             .CaptureSources(phiSourcesCapture);

            var set1Result = assignPattern.FindFirstMatch(cfg.Nodes[2].Contents.Instructions);
            var set2Result = assignPattern.FindFirstMatch(cfg.Nodes[5].Contents.Instructions);
            var phiResult  = phiPattern.Match(cfg.Nodes[7].Contents.Header);

            Assert.True(set1Result.IsSuccess, "Node 2 was expected to contain an assignment statement.");
            Assert.True(set2Result.IsSuccess, "Node 5 was expected to contain an assignment statement.");
            Assert.True(phiResult.IsSuccess, "Node 7 was expected to start with a phi statement.");

            var sources = phiResult.Captures[phiSourcesCapture]
                          .Cast <VariableExpression <DummyInstruction> >()
                          .Select(s => s.Variable);

            var allVariables = new[]
            {
                (IVariable)set1Result.Captures[variablesCapture][0],
                (IVariable)set2Result.Captures[variablesCapture][0]
            };

            Assert.Equal(allVariables.ToHashSet(), sources.ToHashSet());
        }
Exemplo n.º 6
0
        public void ReplacingVariableInVariableExpression()
        {
            var var1 = new DummyVariable("old");
            var var2 = new DummyVariable("new");

            var expr = new VariableExpression <DummyInstruction>(var1);

            Assert.Equal(var2, expr.WithVariable(var2).Variable);
        }
Exemplo n.º 7
0
        public void DifferentSpecificVariableShouldMatch()
        {
            var variable1 = new DummyVariable("variable1");
            var variable2 = new DummyVariable("variable2");

            var pattern = ExpressionPattern.Variable <DummyInstruction>(variable1);

            Assert.False(pattern.Matches(new VariableExpression <DummyInstruction>(variable2)));
        }
Exemplo n.º 8
0
        public void AddVariableDependencyWithMultipleSourcesShouldSetDegree()
        {
            var variable = new DummyVariable("var1");
            var graph    = new DataFlowGraph <int>(IntArchitecture.Instance);

            var n1 = graph.Nodes.Add(1, 1);
            var n2 = graph.Nodes.Add(2, 2);
            var n3 = graph.Nodes.Add(3, 3);

            Assert.Equal(0, n1.OutDegree);
            n1.VariableDependencies.Add(variable, new DataDependency <int>(new[] { n2, n3 }));
            Assert.Equal(2, n1.OutDegree);
        }
Exemplo n.º 9
0
        public void AddVariableDependencyWithSingeSourceShouldSetDegree()
        {
            var variable = new DummyVariable("var1");
            var graph    = new DataFlowGraph <int>(IntArchitecture.Instance);

            var n1 = graph.Nodes.Add(1, 1);
            var n2 = graph.Nodes.Add(2, 2);

            Assert.Equal(0, n1.OutDegree);
            n1.VariableDependencies.Add(variable, new DataDependency <int>(n2));
            Assert.Equal(1, n1.OutDegree);
            Assert.Equal(1, n2.InDegree);
        }
Exemplo n.º 10
0
        public void VariableAccessThatHasntBeenWrittenToBeforeShouldntResultInPhi()
        {
            var variable = new DummyVariable("dummy");
            var cfg      = ConstructAst(new[]
            {
                DummyInstruction.Get(0, variable),
                DummyInstruction.Op(1, 1, 0),
                DummyInstruction.Ret(2)
            });

            Assert.Single(cfg.Nodes);
            Assert.All(cfg.Entrypoint.Contents.Instructions, Assert.IsNotType <PhiStatement <DummyInstruction> >);
        }
Exemplo n.º 11
0
        public void ReplacingTargetVariableInPhiStatement()
        {
            var target1 = new DummyVariable("old");
            var target2 = new DummyVariable("new");
            var sources = new[]
            {
                new DummyVariable("source1"),
                new DummyVariable("source2"),
                new DummyVariable("source3"),
                new DummyVariable("source4")
            };
            var phi = new PhiStatement <DummyInstruction>(
                target1, sources.Select(s => new VariableExpression <DummyInstruction>(s)));

            Assert.Equal(target2, phi.WithTarget(target2).Target);
        }
Exemplo n.º 12
0
        public void DisconnectNodeShouldRemoveEdge(DataDependencyType edgeType, bool removeSourceNode)
        {
            var variable = new DummyVariable("var");

            var graph = new DataFlowGraph <int>(IntArchitecture.Instance);

            var n1 = new DataFlowNode <int>(0, 0);

            n1.StackDependencies.Add(new DataDependency <int>());
            n1.VariableDependencies.Add(variable, new DataDependency <int>());

            var n2 = new DataFlowNode <int>(1, 1);

            graph.Nodes.AddRange(new[]
            {
                n1,
                n2
            });

            switch (edgeType)
            {
            case DataDependencyType.Stack:
                n1.StackDependencies[0].Add(new DataSource <int>(n2));
                break;

            case DataDependencyType.Variable:
                n1.VariableDependencies[variable].Add(new DataSource <int>(n2));
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(edgeType), edgeType, null);
            }

            if (removeSourceNode)
            {
                n1.Disconnect();
            }
            else
            {
                n2.Disconnect();
            }

            Assert.Empty(n1.StackDependencies[0]);
            Assert.Empty(n1.VariableDependencies[variable]);
            Assert.Empty(n2.GetDependants());
        }
Exemplo n.º 13
0
        public void RemoveNodeShouldRemoveVarDeps()
        {
            var variable = new DummyVariable("V_1");

            var dfg = new DataFlowGraph <int>(IntArchitecture.Instance);
            var n1  = dfg.Nodes.Add(1, 0);
            var n2  = dfg.Nodes.Add(2, 0);

            n1.VariableDependencies[variable] = new DataDependency <int>(n2);

            Assert.Single(n1.VariableDependencies[variable]);
            Assert.Single(n2.GetDependants());

            dfg.Nodes.Remove(n2);

            Assert.Empty(n1.VariableDependencies[variable]);
            Assert.Empty(n2.GetDependants());
        }
Exemplo n.º 14
0
        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.");
        }
Exemplo n.º 15
0
        public void MergeSingleVariableNoChange()
        {
            var source = CreateDummyNode(0);

            var variable = new DummyVariable("V_1");

            var variables1 = ImmutableDictionary <IVariable, SymbolicValue <DummyInstruction> > .Empty;

            variables1 = variables1.SetItem(variable, SymbolicValue <DummyInstruction> .CreateVariableValue(source, variable));

            var variables2 = ImmutableDictionary <IVariable, SymbolicValue <DummyInstruction> > .Empty;

            variables2 = variables2.SetItem(variable, SymbolicValue <DummyInstruction> .CreateVariableValue(source, variable));

            var state1 = new SymbolicProgramState <DummyInstruction>(0, variables1);
            var state2 = new SymbolicProgramState <DummyInstruction>(0, variables2);

            Assert.False(state1.MergeStates(state2, out var newState));
            Assert.Equal(new HashSet <DataFlowNode <DummyInstruction> >(new [] { source }), newState.Variables[variable].GetNodes());
        }
Exemplo n.º 16
0
        public void IgnoreVariableDependenciesWhenNotIncluded()
        {
            var variable = new DummyVariable("v1");

            var dfg = new DataFlowGraph <int>(IntArchitecture.Instance);
            var n1  = dfg.Nodes.Add(1, 1);
            var n2  = dfg.Nodes.Add(2, 2);
            var n3  = dfg.Nodes.Add(3, 3);
            var n4  = dfg.Nodes.Add(4, 4);
            var n5  = dfg.Nodes.Add(5, 5);

            n1.StackDependencies.Add(new DataDependency <int>(n2));
            n1.VariableDependencies.Add(variable, new DataDependency <int>(n3));
            n2.StackDependencies.Add(new DataDependency <int>(n4));
            n2.VariableDependencies.Add(variable, new DataDependency <int>(n5));

            Assert.Equal(new[]
            {
                n4, n2, n1
            }, n1.GetOrderedDependencies(DependencyCollectionFlags.IncludeStackDependencies));
        }
Exemplo n.º 17
0
        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)));
        }
Exemplo n.º 18
0
        public void ReplacingExpressionInAssignmentShouldChangeParent()
        {
            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 expr = new InstructionExpression <DummyInstruction>(DummyInstruction.Jmp(0, 69),
                                                                    Array.Empty <Expression <DummyInstruction> >());
            var asmt = Assert.IsType <AssignmentStatement <DummyInstruction> >(block[1]);

            Assert.Equal(expr, asmt.WithExpression(expr).Expression);
            Assert.Equal(asmt, expr.Parent);
        }
Exemplo n.º 19
0
        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);
        }
Exemplo n.º 20
0
        private static List <ExpressionBase> ConvertRoslynExpressionToWandaExpression(
            SimpleCompoundStatement wandaBlock,
            ExpressionSyntax expressionSyntax)
        {
            var result = new List <ExpressionBase>();

            switch (expressionSyntax)
            {
            case AssignmentExpressionSyntax assignmentExpressionSyntax:
            {
                var            left          = assignmentExpressionSyntax.Left;
                var            operatorToken = assignmentExpressionSyntax.OperatorToken;
                var            right         = assignmentExpressionSyntax.Right;
                var            leftValue     = wandaBlock.ResolveLValue(result, left, true);
                var            rightValue    = wandaBlock.ResolveValue(result, right, true);
                AssignmentBase assignment    = null;

                switch (operatorToken.Kind())
                {
                case SyntaxKind.EqualsToken:
                    assignment = new SimpleAssignment(leftValue, rightValue);
                    break;

                case SyntaxKind.SlashEqualsToken:
                    assignment = new OperatorAssignment(leftValue, rightValue, BinaryDivideOperator.Instance);
                    break;

                case SyntaxKind.PlusEqualsToken:
                    assignment = new OperatorAssignment(leftValue, rightValue, BinaryAddOperator.Instance);
                    break;

                case SyntaxKind.MinusEqualsToken:
                    assignment = new OperatorAssignment(leftValue, rightValue, BinarySubtractOperator.Instance);
                    break;

                case SyntaxKind.AsteriskEqualsToken:
                    assignment = new OperatorAssignment(leftValue, rightValue, BinaryMultiplyOperator.Instance);
                    break;

                case SyntaxKind.PercentEqualsToken:
                    assignment =
                        new OperatorAssignment(leftValue, rightValue, BinaryRemainderOperator.Instance);
                    break;

                case SyntaxKind.AmpersandEqualsToken:
                    assignment = new OperatorAssignment(leftValue, rightValue, BinaryBitAndOperator.Instance);
                    break;

                case SyntaxKind.CaretEqualsToken:
                    assignment = new OperatorAssignment(leftValue, rightValue, BinaryBitXorOperator.Instance);
                    break;

                case SyntaxKind.BarEqualsToken:
                    assignment = new OperatorAssignment(leftValue, rightValue, BinaryBitOrOperator.Instance);
                    break;

                case SyntaxKind.LessThanLessThanEqualsToken:
                    assignment = new OperatorAssignment(leftValue, rightValue,
                                                        BinaryBitShiftLeftOperator.Instance);
                    break;

                case SyntaxKind.GreaterThanGreaterThanEqualsToken:
                    assignment = new OperatorAssignment(leftValue, rightValue,
                                                        BinaryBitShiftRightOperator.Instance);
                    break;

                case SyntaxKind.QuestionQuestionEqualsToken:
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (assignment != null)
                {
                    result.Add(assignment);
                }
                else
                {
                    Log.Debug("{Left} {Operator} {Right}", left,
                              operatorToken.Text,
                              right);
                }

                break;
            }

            case PrefixUnaryExpressionSyntax unaryExpressionSyntax:
            {
                var            operand       = unaryExpressionSyntax.Operand;
                var            leftValue     = wandaBlock.ResolveLValue(result, operand, true);
                AssignmentBase assignment    = null;
                var            operatorToken = unaryExpressionSyntax.OperatorToken;
                switch (operatorToken.Kind())
                {
                case SyntaxKind.PlusToken:
                case SyntaxKind.MinusToken:
                case SyntaxKind.TildeToken:
                case SyntaxKind.ExclamationToken:
                    break;

                case SyntaxKind.PlusPlusToken:
                    assignment = new OperatorAssignment(leftValue, IntegerLiteral.One,
                                                        BinaryAddOperator.Instance);
                    break;

                case SyntaxKind.MinusMinusToken:
                    assignment = new OperatorAssignment(leftValue, IntegerLiteral.One,
                                                        BinarySubtractOperator.Instance);
                    break;

                case SyntaxKind.AmpersandToken:
                case SyntaxKind.AsteriskToken:
                case SyntaxKind.CaretToken:
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (assignment != null)
                {
                    result.Add(assignment);
                }
                else
                {
                    Log.Debug("{Operator} {Right}", operatorToken.Text,
                              unaryExpressionSyntax.Operand);
                }

                break;
            }

            case PostfixUnaryExpressionSyntax unaryExpressionSyntax:
            {
                var            operand       = unaryExpressionSyntax.Operand;
                var            leftValue     = wandaBlock.ResolveLValue(result, operand, true);
                AssignmentBase assignment    = null;
                var            operatorToken = unaryExpressionSyntax.OperatorToken;
                switch (operatorToken.Kind())
                {
                case SyntaxKind.PlusPlusToken:
                    assignment = new OperatorAssignment(leftValue, IntegerLiteral.One,
                                                        BinaryAddOperator.Instance);
                    break;

                case SyntaxKind.MinusMinusToken:
                    assignment = new OperatorAssignment(leftValue, IntegerLiteral.One,
                                                        BinarySubtractOperator.Instance);
                    break;

                case SyntaxKind.ExclamationToken:
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (assignment != null)
                {
                    // todo: that's not right. The value returned by expression is not as simple
                    result.Add(assignment);
                }
                else
                {
                    Log.Debug("{Left} {Operator}", unaryExpressionSyntax.Operand,
                              operatorToken.Text);
                }

                break;
            }

            case InvocationExpressionSyntax invocationExpressionSyntax:
            {
                var what = invocationExpressionSyntax.Expression.ToString();

                FunctionCallParameter Selector(ArgumentSyntax x)
                {
                    var xRefKindKeyword = x.RefKindKeyword.Kind();

                    var(isRef, isOut) = (
                        xRefKindKeyword == SyntaxKind.RefKeyword,
                        xRefKindKeyword == SyntaxKind.OutKeyword);

                    return(new FunctionCallParameter
                        {
                            Value = wandaBlock.ResolveValue(result, x.Expression, true),
                            Out = isOut,
                            Ref = isRef
                        });
                }

                var with = invocationExpressionSyntax.ArgumentList.Arguments.Select(Selector);

                var functionCallOperator = new FunctionCallOperator {
                    Name = what
                };
                functionCallOperator.Arguments.AddRange(with);

                result.Add(functionCallOperator);
                break;
            }

            case IdentifierNameSyntax identifierNameSyntax:
            {
                result.Add(wandaBlock.ResolveVariableByName(identifierNameSyntax.Identifier.Text));
                break;
            }

            case LiteralExpressionSyntax literalExpressionSyntax:
            {
                result.Add(ResolveLiteral(literalExpressionSyntax));
                break;
            }

            case ElementAccessExpressionSyntax elementAccessExpressionSyntax:
            {
                result.Add(
                    ResolveRoslynElementAccessExpressionToWandaOperator(elementAccessExpressionSyntax,
                                                                        result,
                                                                        wandaBlock));
                break;
            }

            case BinaryExpressionSyntax binaryExpressionSyntax:
            {
                var       operatorToken = binaryExpressionSyntax.OperatorToken;
                PureBase  operatorBase  = null;
                LogicBase logicBase     = null;
                switch (operatorToken.Kind())
                {
                case SyntaxKind.PlusToken:
                    operatorBase = BinaryAddOperator.Instance;
                    break;

                case SyntaxKind.MinusToken:
                    operatorBase = BinarySubtractOperator.Instance;
                    break;

                case SyntaxKind.AsteriskToken:
                    operatorBase = BinaryMultiplyOperator.Instance;
                    break;

                case SyntaxKind.SlashToken:
                    operatorBase = BinaryDivideOperator.Instance;
                    break;

                case SyntaxKind.PercentToken:
                    operatorBase = BinaryRemainderOperator.Instance;
                    break;

                case SyntaxKind.LessThanLessThanToken:
                    operatorBase = BinaryBitShiftLeftOperator.Instance;
                    break;

                case SyntaxKind.GreaterThanGreaterThanToken:
                    operatorBase = BinaryBitShiftRightOperator.Instance;
                    break;

                case SyntaxKind.BarBarToken:
                    logicBase = OrLogic.Instance;
                    break;

                case SyntaxKind.AmpersandAmpersandToken:
                    logicBase = AndLogic.Instance;
                    break;

                case SyntaxKind.BarToken:
                    operatorBase = BinaryBitOrOperator.Instance;
                    break;

                case SyntaxKind.AmpersandToken:
                    operatorBase = BinaryBitAndOperator.Instance;
                    break;

                case SyntaxKind.CaretToken:
                    operatorBase = BinaryBitXorOperator.Instance;
                    break;

                case SyntaxKind.EqualsEqualsToken:
                    logicBase = EqualLogic.Instance;
                    break;

                case SyntaxKind.ExclamationEqualsToken:
                    logicBase = NotEqualLogic.Instance;
                    break;

                case SyntaxKind.LessThanToken:
                    logicBase = LessLogic.Instance;
                    break;

                case SyntaxKind.LessThanEqualsToken:
                    logicBase = LessOrEqualLogic.Instance;
                    break;

                case SyntaxKind.GreaterThanToken:
                    logicBase = GreaterLogic.Instance;
                    break;

                case SyntaxKind.GreaterThanEqualsToken:
                    logicBase = GreaterOrEqualLogic.Instance;
                    break;

                case SyntaxKind.IsKeyword:
                case SyntaxKind.AsKeyword:
                case SyntaxKind.QuestionQuestionToken:
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                switch (operatorBase != null, logicBase != null)
                {
                case (true, false):
                {
                    var left  = wandaBlock.ResolveValue(result, binaryExpressionSyntax.Left, true);
                    var right = wandaBlock.ResolveValue(result, binaryExpressionSyntax.Right, true);

                    var dummy = new DummyVariable
                    {
                        TypeRef = ApproximateResultTypeOfBinaryOperator(left, right)
                    };
                    wandaBlock.LocalVariables.Add(dummy);

                    var assignment = new SimpleAssignment(dummy, left);
                    result.Add(assignment);

                    var operatorAssignment = new OperatorAssignment(dummy, right, operatorBase);
                    result.Add(operatorAssignment);
                    break;
                }

                case (false, true):
                {
                    var left  = wandaBlock.ResolveValue(result, binaryExpressionSyntax.Left, true);
                    var right = wandaBlock.ResolveValue(result, binaryExpressionSyntax.Right, true);

                    var operatorAssignment = new BinaryLogicExpression(logicBase, left, right);
                    result.Add(operatorAssignment);
                    break;
                }

                case (false, false):
                {
                    Log.Debug("BINARY: {Left} {Operator} {Right} ({Kind})",
                              binaryExpressionSyntax.Left,
                              operatorToken.Text,
                              binaryExpressionSyntax.Right,
                              operatorToken.Kind());
                    break;
                }

                default:
                    throw new ArgumentOutOfRangeException();
                }

                break;
            }
Exemplo n.º 21
0
        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());
        }