private Expression GetIdentifierReference(VariableReference identifierReference, ref Expression target)
 {
     V_0 = target as MethodInvocationExpression;
     if (V_0 == null || V_0.get_MethodExpression().get_MethodDefinition() == null || !V_0.get_MethodExpression().get_MethodDefinition().get_IsStatic() || !String.op_Equality(V_0.get_MethodExpression().get_MethodDefinition().get_DeclaringType().get_FullName(), "System.Linq.Enumerable") && !String.op_Equality(V_0.get_MethodExpression().get_MethodDefinition().get_DeclaringType().get_FullName(), "System.Linq.Queryable") || !String.op_Equality(V_0.get_MethodExpression().get_Method().get_Name(), "Cast"))
     {
         return(new VariableReferenceExpression(identifierReference, null));
     }
     target    = V_0.get_Arguments().get_Item(0);
     dummyVar0 = this.methodContext.get_UndeclaredLinqVariables().Remove(identifierReference.Resolve());
     return(new VariableDeclarationExpression(identifierReference.Resolve(), null));
 }
            private Expression GetIdentifierReference(VariableReference identifierReference, ref Expression target)
            {
                MethodInvocationExpression targetInvocation = target as MethodInvocationExpression;

                if (targetInvocation != null && targetInvocation.MethodExpression.MethodDefinition != null &&
                    targetInvocation.MethodExpression.MethodDefinition.IsStatic &&
                    (targetInvocation.MethodExpression.MethodDefinition.DeclaringType.FullName == "System.Linq.Enumerable" ||
                     targetInvocation.MethodExpression.MethodDefinition.DeclaringType.FullName == "System.Linq.Queryable") &&
                    targetInvocation.MethodExpression.Method.Name == "Cast")
                {
                    target = targetInvocation.Arguments[0];
                    methodContext.UndeclaredLinqVariables.Remove(identifierReference.Resolve());
                    return(new VariableDeclarationExpression(identifierReference.Resolve(), null));
                }
                return(new VariableReferenceExpression(identifierReference, null));
            }
예제 #3
0
 private bool IsTempVariable(VariableReference variable)
 {
     V_0 = this.methodContext.get_VariableDefinitionToNameMap().get_Item(variable.Resolve());
     if (!V_0.StartsWith("CS$") && !V_0.StartsWith("VB$") && V_0.IndexOf("__init") <= 0 && !V_0.StartsWith("stackVariable") && !V_0.StartsWith("exception_"))
     {
         return(false);
     }
     return(true);
 }
예제 #4
0
        public void Collect(VariableReference vari)
        {
            VariableDefinition def;

            if ((def = vari as VariableDefinition ?? vari.Resolve()) != null)
            {
                Collect(def);
            }
        }
        //x = cond ? y : z;
        //
        //==
        //
        //if(cond)
        //{
        //      x = y;
        //}
        //else
        //{
        //      x = z;
        //}
        //
        //x - phi variable
        //y, z - expressions

        public bool TryMatchInternal(IfStatement theIfStatement, out Statement result)
        {
            result = null;

            if (theIfStatement == null)
            {
                return(false);
            }

            VariableReference xVariableReference  = null;
            VariableReference x1VariableReference = null;
            Expression        yExpressionValue;
            Expression        zExpressionValue;

            if (theIfStatement.Else == null ||
                theIfStatement.Then.Statements.Count != 1 || theIfStatement.Else.Statements.Count != 1 ||
                theIfStatement.Then.Statements[0].CodeNodeType != CodeNodeType.ExpressionStatement ||
                theIfStatement.Else.Statements[0].CodeNodeType != CodeNodeType.ExpressionStatement)
            {
                return(false);
            }

            BinaryExpression thenAssignExpression = (theIfStatement.Then.Statements[0] as ExpressionStatement).Expression as BinaryExpression;
            BinaryExpression elseAssignExpression = (theIfStatement.Else.Statements[0] as ExpressionStatement).Expression as BinaryExpression;

            if (!IsAssignToVariableExpression(thenAssignExpression, out x1VariableReference) ||
                !IsAssignToVariableExpression(elseAssignExpression, out xVariableReference))
            {
                return(false);
            }

            if (xVariableReference != x1VariableReference)
            {
                return(false);
            }
            if (!ShouldInlineExpressions(thenAssignExpression, elseAssignExpression))
            {
                /// Although correct syntax, nesting ternary expressions makes the code very unreadable.
                return(false);
            }

            yExpressionValue = GetRightExpressionMapped(thenAssignExpression);
            zExpressionValue = GetRightExpressionMapped(elseAssignExpression);

            ConditionExpression ternaryConditionExpression = new ConditionExpression(theIfStatement.Condition, yExpressionValue, zExpressionValue, null);
            BinaryExpression    ternaryAssign = new BinaryExpression(BinaryOperator.Assign,
                                                                     new VariableReferenceExpression(xVariableReference, null), ternaryConditionExpression, this.typeSystem, null);

            result = new ExpressionStatement(ternaryAssign)
            {
                Parent = theIfStatement.Parent
            };
            FixContext(xVariableReference.Resolve(), 1, 0, result as ExpressionStatement);
            return(true);
        }
예제 #6
0
 public static VariableDefinition TryResolve(this VariableReference r)
 {
     try
     {
         return(r.Resolve());
     }
     catch (Exception)
     {
         return(null);
     }
 }
        private bool IsTempVariable(VariableReference variable)
        {
            var name = methodContext.VariableDefinitionToNameMap[variable.Resolve()];

            if (name.StartsWith("CS$") ||
                name.StartsWith("VB$") ||
                name.IndexOf("__init") > 0 ||
                name.StartsWith("stackVariable") ||
                name.StartsWith("exception_"))
            {
                return(true);
            }
            return(false);
        }
예제 #8
0
        public static string GetName(this VariableReference self, MethodBody body)
        {
            if (self == null)
            {
                return(String.Empty);
            }

            var def = self.Resolve();

            if (def == null)
            {
                return(self.ToString());
            }

            return(GetVariableName(def, body));
        }
        private void ProcessVariableReferenceExpression(VariableReferenceExpression variableReferenceExpression)
        {
            VariableReference variableReference = variableReferenceExpression.Variable;

            if (this.variableToAssignedCodeNodeTypeMap.ContainsKey(variableReference))
            {
                CodeNodeType       variableAssignmentType = this.variableToAssignedCodeNodeTypeMap[variableReference];
                VariableDefinition variable = variableReference.Resolve();
                if (!this.variablesToNotInline.Contains(variable))
                {
                    if (!this.language.IsValidLineStarter(variableAssignmentType))
                    {
                        this.variablesToNotInline.Add(variable);
                    }
                }
            }
        }
        private bool IsOnlyAssignedOnce(VariableReference variable, out TypeReference type)
        {
            type = null;
            StackVariableDefineUseInfo defineUseInfo;

            if (!context.MethodContext.StackData.VariableToDefineUseInfo.TryGetValue(variable.Resolve(), out defineUseInfo))
            {
                throw new Exception("Define/use info not found.");
            }

            if (defineUseInfo.DefinedAt.Count != 1)
            {
                return(false);
            }

            type = offsetToExpression[First(defineUseInfo.DefinedAt)].ExpressionType;
            return(true);
        }
        private bool IsOnlyUsedOnce(VariableReference variable, out TypeReference type)
        {
            type = null;
            StackVariableDefineUseInfo defineUseInfo;

            if (!context.MethodContext.StackData.VariableToDefineUseInfo.TryGetValue(variable.Resolve(), out defineUseInfo))
            {
                throw new Exception("Define/use info not found.");
            }

            if (defineUseInfo.UsedAt.Count != 1)
            {
                return(false);
            }

            int instructionOffset        = First(defineUseInfo.UsedAt);
            UsedAsTypeHelper uath        = new UsedAsTypeHelper(context.MethodContext);
            Instruction      instruction = context.MethodContext.ControlFlowGraph.OffsetToInstruction[instructionOffset];

            type = uath.GetUseExpressionTypeNode(instruction, offsetToExpression[instructionOffset], variable);
            return(true);
        }
예제 #12
0
        /// <summary>
        /// Check if the local variable has a name which was generated by the compiler.
        /// Note that this will return true for all variables if debugging information is not present.
        /// </summary>
        /// <param name="self">The VariableReference on which the extension method can be called.</param>
        /// <returns>True if the field name was generated by the compiler, False otherwise</returns>
        public static bool IsGeneratedName(this VariableReference self, MethodBody body)
        {
            if (self == null)
            {
                return(false);
            }

            var def = self.Resolve();

            if (def == null)
            {
                return(false);
            }

            string name = GetVariableName(def, body);

            if (String.IsNullOrEmpty(name))
            {
                return(true);
            }

            return((name [0] == '<') || (name.IndexOf('$') != -1));
        }
 private bool IsOnlyUsedOnce(VariableReference variable, out TypeReference type)
 {
     type = null;
     if (!this.context.get_MethodContext().get_StackData().get_VariableToDefineUseInfo().TryGetValue(variable.Resolve(), out V_0))
     {
         throw new Exception("Define/use info not found.");
     }
     if (V_0.get_UsedAt().get_Count() != 1)
     {
         return(false);
     }
     V_1  = this.First <int>(V_0.get_UsedAt());
     V_2  = new UsedAsTypeHelper(this.context.get_MethodContext());
     V_3  = this.context.get_MethodContext().get_ControlFlowGraph().get_OffsetToInstruction().get_Item(V_1);
     type = V_2.GetUseExpressionTypeNode(V_3, this.offsetToExpression.get_Item(V_1), variable);
     return(true);
 }
            private LinqQueryExpression RemoveTransparentIdentifiers(LinqQueryExpression originalQuery)
            {
                LinqQueryExpression          linqQuery              = (LinqQueryExpression)originalQuery.Clone();
                List <VariableReference>     identifiers            = new List <VariableReference>();
                TransparentIdentifierCleaner cleaner                = new TransparentIdentifierCleaner();
                HashSet <VariableReference>  transparentIdentifiers = new HashSet <VariableReference>();

                for (int i = 0; i < linqQuery.Clauses.Count; i++)
                {
                    linqQuery.Clauses[i] = (QueryClause)cleaner.Visit(linqQuery.Clauses[i]);
                    QueryClause currentClause = linqQuery.Clauses[i];

                    if (currentClause.CodeNodeType == CodeNodeType.FromClause)
                    {
                        identifiers.Add(GetVariableReference((currentClause as FromClause).Identifier));
                    }
                    else if (currentClause.CodeNodeType == CodeNodeType.JoinClause)
                    {
                        if (linqQuery.Clauses[i + 1].CodeNodeType != CodeNodeType.IntoClause)
                        {
                            identifiers.Add(GetVariableReference((currentClause as JoinClause).InnerIdentifier));
                        }
                        else
                        {
                            identifiers.Add(((IntoClause)linqQuery.Clauses[i + 1]).Identifier.Variable);
                            i++;
                        }
                    }
                    else if (currentClause.CodeNodeType == CodeNodeType.SelectClause && i != linqQuery.Clauses.Count - 1)
                    {
                        VariableReference intoIdentifier = ((IntoClause)linqQuery.Clauses[i + 1]).Identifier.Variable;
                        if (IsTransparentIdentifier(intoIdentifier))
                        {
                            Dictionary <PropertyDefinition, Expression> propertyToValueMap = GetPropertyToValueMap((currentClause as SelectClause).Expression);
                            if (propertyToValueMap == null)
                            {
                                return(originalQuery);
                            }

                            if (identifiers.Count == 2)
                            {
                                if (!RemoveIdentifier(propertyToValueMap, identifiers))
                                {
                                    return(originalQuery);
                                }
                                linqQuery.Clauses.RemoveAt(i);
                                linqQuery.Clauses.RemoveAt(i);
                                i--;
                            }
                            else if (identifiers.Count == 1)
                            {
                                LetClause letClause = GenerateLetClause(propertyToValueMap, identifiers[0]);
                                if (letClause == null)
                                {
                                    return(originalQuery);
                                }
                                linqQuery.Clauses[i] = letClause;
                                linqQuery.Clauses.RemoveAt(i + 1);
                            }
                            else
                            {
                                return(originalQuery);
                            }

                            this.methodContext.VariablesToRename.Add(intoIdentifier.Resolve());
                            transparentIdentifiers.Add(intoIdentifier);
                            identifiers.Clear();
                            identifiers.Add(intoIdentifier);
                            UpdateCleaner(cleaner, intoIdentifier, propertyToValueMap);
                        }
                    }
                    else if (currentClause.CodeNodeType == CodeNodeType.IntoClause)
                    {
                        identifiers.Clear();
                        identifiers.Add(((IntoClause)currentClause).Identifier.Variable);
                    }
                }

                TransparentIdentifierFinder finder = new TransparentIdentifierFinder(transparentIdentifiers);

                if (finder.ContainsTransparentIdentifiers(linqQuery))
                {
                    return(originalQuery);
                }

                return(linqQuery);
            }
예제 #15
0
 /// <summary>
 /// A cecil variable reference will be directed to this method.
 /// </summary>
 /// <param name="item">Cecil reference.</param>
 /// <param name="resolvedItem">Output parameter that will be populated with the resolved cecil definition.</param>
 /// <returns><c>true</c></returns>
 private static bool TryResolve(VariableReference item, out object resolvedItem)
 {
     resolvedItem = item.Resolve();
     return(true);
 }
예제 #16
0
 internal void RemoveVariable(VariableReference reference)
 {
     this.RemoveVariable(reference.Resolve());
     return;
 }
예제 #17
0
        private bool ProcessDelegateAllocation(AssemblyProcessorContext context, MethodDefinition method, Instruction delegateAllocationInstruction)
        {
            // The instruction must be a delegate allocation
            // If not, this might be a static delegate, or some unsupported construct
            if (delegateAllocationInstruction.OpCode != OpCodes.Newobj)
            {
                return(false);
            }

            var delegateInstanceConstructor = (MethodReference)delegateAllocationInstruction.Operand;
            var delegateInstanceType        = delegateInstanceConstructor.DeclaringType;

            // The previous instruction pushes the delegate method onto the stack
            var functionPointerInstruction = delegateAllocationInstruction.Previous;

            if (functionPointerInstruction.OpCode != OpCodes.Ldftn)
            {
                return(false);
            }

            var delegateMethod = (MethodReference)functionPointerInstruction.Operand;

            // The previous instruction pushes the target onto the stack
            // If it's the this-parameter, we can create an instance field, and reuse the same delegate
            var loadClosureInstruction = functionPointerInstruction.Previous;

            if ((loadClosureInstruction.OpCode == OpCodes.Ldarg_0 || loadClosureInstruction.OpCode == OpCodes.Ldnull) && !method.IsStatic)
            {
                // TODO: Handle generic methods/delegates
                // TODO: Handle multiple constructors propertly
                var constructor     = method.DeclaringType.Methods.FirstOrDefault(x => x.Name == ".ctor" && !x.HasParameters);
                var retInstruction3 = constructor?.Body.Instructions.FirstOrDefault(x => x.OpCode == OpCodes.Ret);
                if (retInstruction3 == null)
                {
                    return(false);
                }

                // Create an instance field for the shared delegate
                var sharedDelegateField = new FieldDefinition($"<delegate>{delegateMethod.Name}", FieldAttributes.Private, delegateInstanceType);
                method.DeclaringType.Fields.Add(sharedDelegateField);

                // Create and store the delegate in constructor
                var ilProcessor5 = constructor.Body.GetILProcessor();
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Ldarg_0));
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(loadClosureInstruction.OpCode));
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Ldftn, delegateMethod));
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Newobj, delegateInstanceConstructor));
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Stfld, sharedDelegateField));

                // Load from field instead of allocating
                var ilProcessor4 = method.Body.GetILProcessor();
                ilProcessor4.Remove(functionPointerInstruction);
                loadClosureInstruction.OpCode = OpCodes.Ldarg_0; // In case it was a ldnull
                ilProcessor4.Replace(delegateAllocationInstruction, ilProcessor4.Create(OpCodes.Ldfld, sharedDelegateField));

                return(true);
            }

            // If the target is a compiler generated closure, we only handle local variable load instructions
            int    variableIndex;
            OpCode storeOpCode;

            if (!TryGetStoreOpcode(loadClosureInstruction, out storeOpCode, out variableIndex))
            {
                return(false);
            }

            // Find the instruction that stores the closure variable
            var storeClosureInstruction      = loadClosureInstruction.Previous;
            VariableReference closureVarible = null;

            while (storeClosureInstruction != null)
            {
                closureVarible = storeClosureInstruction.Operand as VariableReference;
                if (storeClosureInstruction.OpCode == storeOpCode && (closureVarible == null || variableIndex == closureVarible.Index))
                {
                    break;
                }

                storeClosureInstruction = storeClosureInstruction.Previous;
            }
            if (storeClosureInstruction == null)
            {
                return(false);
            }

            var closureInstanceType = method.Body.Variables[variableIndex].VariableType;
            var closureType         = closureInstanceType.Resolve();
            var genericParameters   = closureType.GenericParameters.Cast <TypeReference>().ToArray();

            // Patch closure
            var closure = ProcessClosure(context, closureType, genericParameters);

            // Create delegate field
            var delegateFieldType = ChangeGenericArguments(context, delegateInstanceType, closureInstanceType);
            var delegateField     = new FieldDefinition($"<delegate>{delegateMethod.Name}", FieldAttributes.Public, delegateFieldType);

            closureType.Fields.Add(delegateField);
            var localDelegateFieldInstance = delegateField.MakeGeneric(genericParameters);

            // Initialize delegate field (the closure instance (local 0) is already on the stack)
            var delegateConstructorInstance = (MethodReference)delegateAllocationInstruction.Operand;
            var delegateGenericArguments    = (delegateFieldType as GenericInstanceType)?.GenericArguments.ToArray() ?? new TypeReference[0];
            var genericDelegateConstructor  = context.Assembly.MainModule.ImportReference(delegateConstructorInstance.Resolve()).MakeGeneric(delegateGenericArguments);

            var methodInstance = (MethodReference)functionPointerInstruction.Operand;
            var genericMethod  = methodInstance.Resolve().MakeGeneric(closureType.GenericParameters.ToArray());

            if (methodInstance is GenericInstanceMethod)
            {
                throw new NotImplementedException();
            }

            var ilProcessor3      = closure.FactoryMethod.Body.GetILProcessor();
            var returnInstruction = ilProcessor3.Body.Instructions.FirstOrDefault(x => x.OpCode == OpCodes.Ret);

            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Ldloc_0));
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Ldftn, genericMethod));
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Newobj, genericDelegateConstructor));
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Stfld, localDelegateFieldInstance));
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Ldloc_0));

            var ilProcessor = method.Body.GetILProcessor();

            Func <Instruction> generateClosureVariable = () => closureVarible == null?ilProcessor.Create(loadClosureInstruction.OpCode) : ilProcessor.Create(loadClosureInstruction.OpCode, closureVarible.Resolve());

            // Retrieve from pool
            var closureGenericArguments = (closureInstanceType as GenericInstanceType)?.GenericArguments.ToArray() ?? new TypeReference[0];
            var closureAllocation       = storeClosureInstruction.Previous;

            if (closureAllocation.OpCode == OpCodes.Newobj)
            {
                // Retrieve closure from pool, instead of allocating
                ilProcessor.Replace(storeClosureInstruction, ilProcessor.Create(OpCodes.Nop));

                var acquireClosure      = ilProcessor.Create(OpCodes.Callvirt, poolAcquireMethod.MakeGeneric(closureInstanceType));
                var methodPreviousStart = ilProcessor.Body.Instructions.First();
                ilProcessor.InsertBefore(methodPreviousStart, ilProcessor.Create(OpCodes.Nop));
                ilProcessor.InsertBefore(methodPreviousStart, ilProcessor.Create(OpCodes.Ldsfld, closure.PoolField.MakeGeneric(closureGenericArguments)));
                ilProcessor.InsertBefore(methodPreviousStart, acquireClosure);
                ilProcessor.InsertBefore(methodPreviousStart, storeClosureInstruction);
                closureAllocation.OpCode  = OpCodes.Nop; // Change to Nop instead of removing it, as this instruction might be reference somewhere?
                closureAllocation.Operand = null;

                // Add a reference
                ilProcessor.InsertBefore(methodPreviousStart, generateClosureVariable());
                ilProcessor.InsertBefore(methodPreviousStart, ilProcessor.Create(OpCodes.Callvirt, closure.AddReferenceMethod.MakeGeneric(closureGenericArguments)));

                // TODO: Multiple returns + try/finally
                // Release reference
                var retInstructions = method.Body.Instructions.Where(x => x.OpCode == OpCodes.Ret).ToArray();

                Instruction beforeReturn         = generateClosureVariable();
                Instruction newReturnInstruction = ilProcessor.Create(OpCodes.Ret);
                ilProcessor.Append(beforeReturn);
                ilProcessor.Append(ilProcessor.Create(OpCodes.Ldnull));
                ilProcessor.Append(ilProcessor.Create(OpCodes.Beq, newReturnInstruction));
                ilProcessor.Append(generateClosureVariable());
                ilProcessor.Append(ilProcessor.Create(OpCodes.Callvirt, closure.ReleaseMethod.MakeGeneric(closureGenericArguments)));
                ilProcessor.Append(newReturnInstruction);

                foreach (var retInstruction2 in retInstructions)
                {
                    retInstruction2.OpCode  = OpCodes.Br;
                    retInstruction2.Operand = beforeReturn;
                }
            }

            // Get delegate from closure, instead of allocating
            ilProcessor.Remove(functionPointerInstruction);
            ilProcessor.Replace(delegateAllocationInstruction, ilProcessor.Create(OpCodes.Ldfld, delegateField.MakeGeneric(closureGenericArguments))); // Closure object is already on the stack

            return(true);
        }
 private bool IsStackVariable(VariableReference varRef)
 {
     return(methodContext.StackData.VariableToDefineUseInfo.ContainsKey(varRef.Resolve()));
 }
예제 #19
0
 private bool IsStackVariable(VariableReference varRef)
 {
     return(this.methodContext.get_StackData().get_VariableToDefineUseInfo().ContainsKey(varRef.Resolve()));
 }
 public void RemoveVariable(VariableReference reference)
 {
     RemoveVariable(reference.Resolve());
 }
 private bool IsOnlyAssignedOnce(VariableReference variable, out TypeReference type)
 {
     type = null;
     if (!this.context.get_MethodContext().get_StackData().get_VariableToDefineUseInfo().TryGetValue(variable.Resolve(), out V_0))
     {
         throw new Exception("Define/use info not found.");
     }
     if (V_0.get_DefinedAt().get_Count() != 1)
     {
         return(false);
     }
     type = this.offsetToExpression.get_Item(this.First <int>(V_0.get_DefinedAt())).get_ExpressionType();
     return(true);
 }
 internal void RemoveVariable(VariableReference reference)
 {
     RemoveVariable(reference.Resolve());
 }