internal static KeyValuePair <MethodDefinition, KeyValuePair <string, string> > CreateMethodString(TypeDefinition s, MethodDefinition m)
        {
            if (s == null)
            {
                throw new ArgumentNullException("s");
            }

            if (m == null)
            {
                throw new ArgumentNullException("m");
            }

            var ctx = new DecompilerContext(s.Module)
            {
                CurrentType       = s,
                CurrentMethod     = m,
                CancellationToken = CancellationToken.None
            };

            var d = AstMethodBodyBuilder.CreateMethodBody(m, ctx);

            var glsl = new ASLShader.GLSLVisitor(d, ctx);

            var sig  = ASLShader.GLSLVisitor.GetSignature(m);
            var code = glsl.Result;
            var desc = new KeyValuePair <MethodDefinition, KeyValuePair <string, string> >(
                m,
                new KeyValuePair <string, string>(m.Name, sig + code)
                );

            return(desc);
        }
Beispiel #2
0
        public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
        {
            if (context.Settings.ExpressionTrees && ExpressionTreeConverter.CouldBeExpressionTree(invocationExpression))
            {
                Expression converted = ExpressionTreeConverter.TryConvert(context, invocationExpression);
                if (converted != null)
                {
                    invocationExpression.ReplaceWith(converted);
                    return(converted.AcceptVisitor(this, data));
                }
            }
            var definition = invocationExpression.Annotation <MethodDefinition>();

            if (definition != null)
            {
                //Handle hoisted base calls from yield return compiler generated class (can be generated by both Mono and Roslyn)
                if (definition.DeclaringType == context.CurrentType && definition.IsCompilerGenerated())
                {
                    DecompilerContext subContext = context.Clone();
                    subContext.CurrentMethod        = definition;
                    subContext.CurrentMethodIsAsync = false;
                    subContext.ReservedVariableNames.AddRange(currentlyUsedVariableNames);
                    var            parameters = AstBuilder.MakeParameters(definition, isLambda: true);
                    BlockStatement body       = AstMethodBodyBuilder.CreateMethodBody(definition, subContext, parameters);
                    TransformationPipeline.RunTransformationsUntil(body, v => v is DelegateConstruction, subContext);

                    if (body.Statements.Count == 1)
                    {
                        var        statement = body.Statements.Single();
                        Expression expr      = null;
                        if (statement is ReturnStatement)
                        {
                            expr = ((ReturnStatement)statement).Expression;
                        }
                        else if (statement is ExpressionStatement)
                        {
                            expr = ((ExpressionStatement)statement).Expression;
                        }
                        if (expr != null)
                        {
                            expr.Remove();
                            invocationExpression.ReplaceWith(expr);
                            return(expr.AcceptVisitor(this, data));
                        }
                    }
                }
            }
            return(base.VisitInvocationExpression(invocationExpression, data));
        }
Beispiel #3
0
        /// <summary>
        /// Public translation interface.
        /// Translates the given method to GLSL
        /// </summary>
        /// <param name="s">Shader type definition.</param>
        /// <param name="m">A method representing a shader to translate.</param>
        /// <param name="attr">The shader type as attribute (either FragmentShaderAttribute or VertexShaderAttribute</param>
        /// <param name="type">The shader type as ShaderType</param>
        /// <returns>The translated GLSL shader source</returns>
        public FunctionDescription Transform(TypeDefinition s, MethodDefinition m, CustomAttribute attr,
                                             ShaderType type)
        {
            if (s == null)
            {
                throw new ArgumentNullException("s");
            }

            if (m == null)
            {
                throw new ArgumentNullException("m");
            }

            if (attr == null)
            {
                throw new ArgumentNullException("attr");
            }

            var ctx = new DecompilerContext(s.Module)
            {
                CurrentType       = s,
                CurrentMethod     = m,
                CancellationToken = CancellationToken.None
            };

            var d = AstMethodBodyBuilder.CreateMethodBody(m, ctx);

            var glsl = new GlslVisitor(d, attr, ctx);

            _functions.UnionWith(glsl.Functions);

            var sig   = GlslVisitor.GetSignature(m);
            var entry = (bool)attr.ConstructorArguments.FirstOrDefault().Value;
            var code  = glsl.Result;
            var desc  = new FunctionDescription(Shader.GetMethodName(m), sig + code, entry, type);

            _dependencies.UnionWith(glsl.Dependencies);

            return(desc);
        }
Beispiel #4
0
        internal void Init(MethodDefinition methodDef)
        {
            CurrentMethod = methodDef;

            var type   = methodDef.DeclaringType;
            var module = methodDef.DeclaringType.Module;

            var decContext = new DecompilerContext(module)
            {
                CurrentType   = type,
                CurrentMethod = methodDef
            };

            // create AST and run optimization operations
            TopNode = AstMethodBodyBuilder.CreateMethodBody(methodDef, decContext);

            // replaces every "!(x == 5)" by "(x != 5)"
            var transform1 = (IAstTransform) new PushNegation();

            transform1.Run(TopNode);

            // replaces (unnecessary) while loops by for loops
            var transform2 = (IAstTransform) new PatternStatementTransform(decContext);

            transform2.Run(TopNode);

            // replaces every "x = Plus(x, y)" by "x += y", etc.
            var transform3 = (IAstTransform) new ReplaceMethodCallsWithOperators(decContext);

            transform3.Run(TopNode);

            // replaces every "var x; x = 5;" by "var x = 5;"
            var transform4 = (IAstTransform) new DeclareVariables(decContext);

            transform4.Run(TopNode);
        }
Beispiel #5
0
        bool HandleAnonymousMethod(ObjectCreateExpression objectCreateExpression, Expression target, MethodReference methodRef)
        {
            if (!context.Settings.AnonymousMethods)
            {
                return(false);                // anonymous method decompilation is disabled
            }
            if (target != null && !(target is IdentifierExpression || target is ThisReferenceExpression || target is NullReferenceExpression))
            {
                return(false);                // don't copy arbitrary expressions, deal with identifiers only
            }
            // Anonymous methods are defined in the same assembly
            MethodDefinition method = methodRef.ResolveWithinSameModule();

            if (!IsAnonymousMethod(context, method))
            {
                return(false);
            }

            // Create AnonymousMethodExpression and prepare parameters
            AnonymousMethodExpression ame = new AnonymousMethodExpression();

            ame.CopyAnnotationsFrom(objectCreateExpression); // copy ILRanges etc.
            ame.RemoveAnnotations <MethodReference>();       // remove reference to delegate ctor
            ame.AddAnnotation(method);                       // add reference to anonymous method
            ame.Parameters.AddRange(AstBuilder.MakeParameters(method, isLambda: true));
            ame.HasParameterList = true;

            // rename variables so that they don't conflict with the parameters:
            foreach (ParameterDeclaration pd in ame.Parameters)
            {
                EnsureVariableNameIsAvailable(objectCreateExpression, pd.Name);
            }

            // Decompile the anonymous method:

            DecompilerContext subContext = context.Clone();

            subContext.CurrentMethod        = method;
            subContext.CurrentMethodIsAsync = false;
            subContext.ReservedVariableNames.AddRange(currentlyUsedVariableNames);
            BlockStatement body = AstMethodBodyBuilder.CreateMethodBody(method, subContext, ame.Parameters);

            TransformationPipeline.RunTransformationsUntil(body,
                                                           v => v is DelegateConstruction,
                                                           subContext);
            body.AcceptVisitor(this, null);


            bool isLambda = false;

            if (ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None))
            {
                isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement);
            }
            // Remove the parameter list from an AnonymousMethodExpression if the original method had no names,
            // and the parameters are not used in the method body
            if (!isLambda && method.Parameters.All(p => string.IsNullOrEmpty(p.Name)))
            {
                var parameterReferencingIdentifiers =
                    from ident in body.Descendants.OfType <IdentifierExpression>()
                    let v = ident.Annotation <ILVariable>()
                            where v != null && v.IsParameter && method.Parameters.Contains(v.OriginalParameter)
                            select ident;
                if (!parameterReferencingIdentifiers.Any())
                {
                    ame.Parameters.Clear();
                    ame.HasParameterList = false;
                }
            }

            // Replace all occurrences of 'this' in the method body with the delegate's target:
            foreach (AstNode node in body.Descendants)
            {
                if (node is ThisReferenceExpression)
                {
                    node.ReplaceWith(target.Clone());
                }
            }
            Expression replacement;

            if (isLambda)
            {
                LambdaExpression lambda = new LambdaExpression();
                lambda.CopyAnnotationsFrom(ame);
                ame.Parameters.MoveTo(lambda.Parameters);
                Expression returnExpr = ((ReturnStatement)body.Statements.Single()).Expression;
                returnExpr.Remove();
                lambda.Body = returnExpr;
                replacement = lambda;
            }
            else
            {
                ame.Body    = body;
                replacement = ame;
            }
            var expectedType = objectCreateExpression.Annotation <TypeInformation>().ExpectedType.Resolve();

            if (expectedType != null && !expectedType.IsDelegate())
            {
                var simplifiedDelegateCreation = (ObjectCreateExpression)objectCreateExpression.Clone();
                simplifiedDelegateCreation.Arguments.Clear();
                simplifiedDelegateCreation.Arguments.Add(replacement);
                replacement = simplifiedDelegateCreation;
            }
            objectCreateExpression.ReplaceWith(replacement);
            return(true);
        }
Beispiel #6
0
        /// <summary>
        /// Public translation interface.
        /// Translates the given method to HLSL
        /// </summary>
        /// <param name="s">Shader type definition.</param>
        /// <param name="m">A method representing a shader to translate.</param>
        /// <param name="attr">The shader type as attribute (either FragmentShaderAttribute or VertexShaderAttribute</param>
        /// <param name="type">The shader type as ShaderType</param>
        /// <returns>The translated GLSL shader source</returns>
        public FunctionDescription Transform(TypeDefinition s, MethodDefinition m, CustomAttribute attr,
                                             ShaderType type)
        {
            if (s == null)
            {
                throw new ArgumentNullException("s");
            }

            if (m == null)
            {
                throw new ArgumentNullException("m");
            }

            if (attr == null)
            {
                throw new ArgumentNullException("attr");
            }

            var sbase = s.BaseType.Resolve();

            while (sbase.MetadataToken.ToInt32() != typeof(Shader).MetadataToken)
            {
                sbase = sbase.BaseType.Resolve();
            }

            var dctx = new DecompilerContext(s.Module)
            {
                CurrentType       = s,
                CurrentMethod     = m,
                CancellationToken = CancellationToken.None
            };
            var d = AstMethodBodyBuilder.CreateMethodBody(m, dctx);

            //var ctx = new CecilTypeResolveContext(sbase.Module);

            var loader   = new CecilLoader();
            var mscorlib = loader.LoadAssemblyFile(typeof(object).Assembly.Location);
            var slsharp  = loader.LoadAssembly(sbase.Module.Assembly);
            var project  = loader.LoadAssembly(s.Module.Assembly);

            var ctx      = new CompositeTypeResolveContext(new[] { project, slsharp, mscorlib });
            var resolver = new CSharpResolver(ctx, CancellationToken.None)
            {
                UsingScope = new UsingScope(project)
            };

            /*
             * foreach (var v in m.Body.Variables)
             * {
             *  resolver.AddVariable(v.VariableType, null, v.Name)
             * }*/

            //resolver.AddVariable()

            //resolver.LocalVariables = m.Body.Variables;


            // TODO: need a more sane way to get the correct class + member
            var ss = ctx.GetAllTypes().First(c => c.FullName == s.FullName);

            resolver.CurrentTypeDefinition = ss;
            resolver.CurrentMember         = ss.Methods.First(n => SameMethod(m, n, ctx));

            var rv = new ResolveVisitor(resolver, new ParsedFile("memory", resolver.UsingScope), null);

            var glsl = new HlslVisitor(d, attr, rv, dctx);

            _functions.UnionWith(glsl.Functions);

            var entry = (bool)attr.ConstructorArguments.FirstOrDefault().Value;
            var sig   = HlslVisitor.GetSignature(m);

            var code = glsl.Result;
            var desc = new FunctionDescription(Shader.GetMethodName(m), sig + code, entry, type);

            _dependencies.UnionWith(glsl.Dependencies);

            return(desc);
        }
Beispiel #7
0
        bool HandleAnonymousMethod(ObjectCreateExpression objectCreateExpression, Expression target, MethodReference methodRef)
        {
            if (!context.Settings.AnonymousMethods)
            {
                return(false);                // anonymous method decompilation is disabled
            }
            // Anonymous methods are defined in the same assembly
            MethodDefinition method = methodRef.ResolveWithinSameModule();

            if (!IsAnonymousMethod(context, method))
            {
                return(false);
            }

            // Create AnonymousMethodExpression and prepare parameters
            AnonymousMethodExpression ame = new AnonymousMethodExpression();

            ame.Parameters.AddRange(AstBuilder.MakeParameters(method.Parameters));
            ame.HasParameterList = true;

            // Decompile the anonymous method:

            DecompilerContext subContext = context.Clone();

            subContext.CurrentMethod = method;
            BlockStatement body = AstMethodBodyBuilder.CreateMethodBody(method, subContext, ame.Parameters);

            TransformationPipeline.RunTransformationsUntil(body, v => v is DelegateConstruction, subContext);
            body.AcceptVisitor(this, null);


            bool isLambda = false;

            if (ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None))
            {
                isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement);
            }
            // Remove the parameter list from an AnonymousMethodExpression if the original method had no names,
            // and the parameters are not used in the method body
            if (!isLambda && method.Parameters.All(p => string.IsNullOrEmpty(p.Name)))
            {
                var parameterReferencingIdentifiers =
                    from ident in body.Descendants.OfType <IdentifierExpression>()
                    let v = ident.Annotation <ILVariable>()
                            where v != null && v.IsParameter && method.Parameters.Contains(v.OriginalParameter)
                            select ident;
                if (!parameterReferencingIdentifiers.Any())
                {
                    ame.Parameters.Clear();
                    ame.HasParameterList = false;
                }
            }

            // Replace all occurrences of 'this' in the method body with the delegate's target:
            foreach (AstNode node in body.Descendants)
            {
                if (node is ThisReferenceExpression)
                {
                    node.ReplaceWith(target.Clone());
                }
            }
            if (isLambda)
            {
                LambdaExpression lambda = new LambdaExpression();
                ame.Parameters.MoveTo(lambda.Parameters);
                Expression returnExpr = ((ReturnStatement)body.Statements.Single()).Expression;
                returnExpr.Remove();
                lambda.Body = returnExpr;
                objectCreateExpression.ReplaceWith(lambda);
            }
            else
            {
                ame.Body = body;
                objectCreateExpression.ReplaceWith(ame);
            }
            return(true);
        }