Beispiel #1
0
        /// <summary>
        /// Creates a lambda compiler that will compile to a dynamic method
        /// </summary>
        private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda)
        {
            Type[] parameterTypes = GetParameterTypes(lambda, typeof(Closure));

            int lambdaMethodIndex = Interlocked.Increment(ref s_lambdaMethodIndex);
            var method            = new DynamicMethod(lambda.Name ?? ("lambda_method" + lambdaMethodIndex.ToString()), lambda.ReturnType, parameterTypes, true);

            _tree   = tree;
            _lambda = lambda;
            _method = method;

            // In a Win8 immersive process user code is not allowed to access non-W8P framework APIs through
            // reflection or RefEmit. Framework code, however, is given an exemption.
            // This is to make sure that user code cannot access non-W8P framework APIs via ExpressionTree.

            // TODO: This API is not available, is there an alternative way to achieve the same.
            // method.ProfileAPICheck = true;

            _ilg = method.GetILGenerator();

            _hasClosureArgument = true;

            // These are populated by AnalyzeTree/VariableBinder
            _scope          = tree.Scopes[lambda];
            _boundConstants = tree.Constants[lambda];

            InitializeMethod();
        }
Beispiel #2
0
        /// <summary>
        /// Creates a lambda compiler that will compile into the provided MethodBuilder
        /// </summary>
        private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda, MethodBuilder method)
        {
            var scope = tree.Scopes[lambda];
            var hasClosureArgument = scope.NeedsClosure;

            Type[] paramTypes = GetParameterTypes(lambda, hasClosureArgument ? typeof(Closure) : null);

            method.SetReturnType(lambda.ReturnType);
            method.SetParameters(paramTypes);
            var parameters = lambda.Parameters;
            // parameters are index from 1, with closure argument we need to skip the first arg
            int startIndex = hasClosureArgument ? 2 : 1;

            for (int i = 0, n = parameters.Count; i < n; i++)
            {
                method.DefineParameter(i + startIndex, ParameterAttributes.None, parameters[i].Name);
            }

            _tree               = tree;
            _lambda             = lambda;
            _typeBuilder        = (TypeBuilder)method.DeclaringType;
            _method             = method;
            _hasClosureArgument = hasClosureArgument;

            _ilg = method.GetILGenerator();

            // These are populated by AnalyzeTree/VariableBinder
            _scope          = scope;
            _boundConstants = tree.Constants[lambda];

            InitializeMethod();
        }
Beispiel #3
0
        /// <summary>
        /// Creates a compiler backed by dynamic method. Sometimes (when debugging is required) the dynamic
        /// method is actually a 'fake' dynamic method and is backed by static type created specifically for
        /// the one method
        /// </summary>
        private static LambdaCompiler CreateDynamicCompiler(
            AnalyzedTree tree,
            LambdaExpression lambda,
            string methodName,
            Type returnType,
            IList <Type> paramTypes,
            IList <string> paramNames,
            bool emitDebugSymbols,
            bool forceDynamic)
        {
            Assert.NotEmpty(methodName);
            Assert.NotNull(returnType);
            Assert.NotNullItems(paramTypes);

            LambdaCompiler lc;

            //
            // Generate a static method if either
            // 1) we want to dump all geneated IL to an assembly on disk (SaveSnippets on)
            // 2) the method is debuggable, i.e. DebugMode is on and a source unit is associated with the method
            //
            if ((Snippets.Shared.SaveSnippets || emitDebugSymbols) && !forceDynamic)
            {
                var typeBuilder = Snippets.Shared.DefineType(methodName, typeof(object), false, false, emitDebugSymbols);
                lc = CreateStaticCompiler(
                    tree,
                    lambda,
                    typeBuilder,
                    methodName,
                    TypeUtils.PublicStatic,
                    returnType,
                    paramTypes,
                    paramNames,
                    true, // dynamicMethod
                    emitDebugSymbols
                    );
            }
            else
            {
                Type[]        parameterTypes = paramTypes.AddFirst(typeof(Closure));
                DynamicMethod target         = Snippets.Shared.CreateDynamicMethod(methodName, returnType, parameterTypes);
                lc = new LambdaCompiler(
                    tree,
                    lambda,
                    null, // typeGen
                    target,
                    target.GetILGenerator(),
                    parameterTypes,
                    true, // dynamicMethod
                    false // emitDebugSymbols
                    );
            }

            return(lc);
        }
 /// <summary>
 /// Creates a lambda compiler for an inlined lambda
 /// </summary>
 private LambdaCompiler(LambdaCompiler parent, LambdaExpression lambda)
 {
     _tree               = parent._tree;
     _lambda             = lambda;
     _method             = parent._method;
     _ilg                = parent._ilg;
     _hasClosureArgument = parent._hasClosureArgument;
     _typeBuilder        = parent._typeBuilder;
     _scope              = _tree.Scopes[lambda];
     _boundConstants     = parent._boundConstants;
 }
Beispiel #5
0
        /// <summary>
        /// Mutates the MethodBuilder parameter, filling in IL, parameters,
        /// and return type.
        ///
        /// (probably shouldn't be modifying parameters/return type...)
        /// </summary>
        internal static void Compile(LambdaExpression lambda, MethodBuilder method)
        {
            // 1. Bind lambda
            AnalyzedTree tree = AnalyzeLambda(ref lambda);

            // 2. Create lambda compiler
            LambdaCompiler c = new LambdaCompiler(tree, lambda, method);

            // 3. Emit
            c.EmitLambdaBody();
        }
Beispiel #6
0
        /// <summary>
        /// Compiler entry point
        /// </summary>
        /// <param name="lambda">LambdaExpression to compile.</param>
        /// <returns>The compiled delegate.</returns>
        internal static Delegate Compile(LambdaExpression lambda)
        {
            // 1. Bind lambda
            AnalyzedTree tree = AnalyzeLambda(ref lambda);

            // 2. Create lambda compiler
            LambdaCompiler c = new LambdaCompiler(tree, lambda);

            // 3. Emit
            c.EmitLambdaBody();

            // 4. Return the delegate.
            return(c.CreateDelegate());
        }
Beispiel #7
0
        /// <summary>
        /// Creates a LambdaCompiler backed by a method on a static type
        /// </summary>
        private static LambdaCompiler CreateStaticCompiler(
            AnalyzedTree tree,
            LambdaExpression lambda,
            TypeBuilder typeBuilder,
            string name,
            MethodAttributes attributes,
            Type retType,
            IList <Type> paramTypes,
            IList <string> paramNames,
            bool dynamicMethod,
            bool emitDebugSymbols)
        {
            Assert.NotNull(name, retType);

            bool closure = tree.Scopes[lambda].NeedsClosure;

            Type[] parameterTypes;
            if (dynamicMethod || closure)
            {
                parameterTypes = paramTypes.AddFirst(typeof(Closure));
            }
            else
            {
                parameterTypes = paramTypes.ToArray();
            }

            MethodBuilder  mb = typeBuilder.DefineMethod(name, attributes, retType, parameterTypes);
            LambdaCompiler lc = new LambdaCompiler(
                tree,
                lambda,
                typeBuilder,
                mb,
                mb.GetILGenerator(),
                parameterTypes,
                dynamicMethod,
                emitDebugSymbols
                );

            if (paramNames != null)
            {
                // parameters are index from 1, with closure argument we need to skip the first arg
                int startIndex = (dynamicMethod || closure) ? 2 : 1;
                for (int i = 0; i < paramNames.Count; i++)
                {
                    mb.DefineParameter(i + startIndex, ParameterAttributes.None, paramNames[i]);
                }
            }
            return(lc);
        }
Beispiel #8
0
 /// <summary>
 /// Creates a lambda compiler for an inlined lambda
 /// </summary>
 private LambdaCompiler(
     LambdaCompiler parent,
     LambdaExpression lambda,
     InvocationExpression invocation)
 {
     _tree               = parent._tree;
     _lambda             = lambda;
     _method             = parent._method;
     _ilg                = parent._ilg;
     _hasClosureArgument = parent._hasClosureArgument;
     _typeBuilder        = parent._typeBuilder;
     // inlined scopes are associated with invocation, not with the lambda
     _scope          = _tree.Scopes[invocation];
     _boundConstants = parent._boundConstants;
 }
Beispiel #9
0
        /// <summary>
        /// Compiler entry point
        /// </summary>
        /// <param name="lambda">LambdaExpression to compile.</param>
        /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
        /// <returns>The compiled delegate.</returns>
        internal static Delegate Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator)
        {
            lambda.ValidateArgumentCount();

            // 1. Bind lambda
            AnalyzedTree tree = AnalyzeLambda(ref lambda);

            // 2. Create lambda compiler
            LambdaCompiler c = new LambdaCompiler(tree, lambda, debugInfoGenerator);

            // 3. Emit
            c.EmitLambdaBody();

            // 4. Return the delegate.
            return(c.CreateDelegate());
        }
Beispiel #10
0
        /// <summary>
        /// Creates a lambda compiler that will compile to a dynamic method
        /// </summary>
        private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda)
        {
            Type[] parameterTypes = GetParameterTypes(lambda, typeof(Closure));

            var method = new DynamicMethod(lambda.Name ?? "lambda_method", lambda.ReturnType, parameterTypes, true);

            _tree   = tree;
            _lambda = lambda;
            _method = method;

            _ilg = method.GetILGenerator();

            _hasClosureArgument = true;

            // These are populated by AnalyzeTree/VariableBinder
            _scope          = tree.Scopes[lambda];
            _boundConstants = tree.Constants[lambda];

            InitializeMethod();
        }
Beispiel #11
0
        /// <summary>
        /// Compiler entry point
        /// </summary>
        /// <param name="lambda">LambdaExpression to compile.</param>
        /// <param name="method">Product of compilation</param>
        /// <param name="delegateType">Type of the delegate to create</param>
        /// <param name="emitDebugSymbols">True to emit debug symbols, false otherwise.</param>
        /// <param name="forceDynamic">Force dynamic method regardless of save assemblies.</param>
        /// <returns>The compiled delegate.</returns>
        internal static Delegate CompileLambda(LambdaExpression lambda, Type delegateType, bool emitDebugSymbols, bool forceDynamic, out MethodInfo method)
        {
            // 1. Create signature
            List <Type>   types;
            List <string> names;
            string        name;
            Type          returnType;

            ComputeSignature(lambda, out types, out names, out name, out returnType);

            // 2. Bind lambda
            AnalyzedTree tree = AnalyzeLambda(ref lambda);

            // 3. Create lambda compiler
            LambdaCompiler c = CreateDynamicCompiler(tree, lambda, name, returnType, types, null, emitDebugSymbols, forceDynamic);

            // 4. Emit
            c.EmitLambdaBody(null);

            // 5. Return the delegate.
            return(c.CreateDelegate(delegateType, out method));
        }
Beispiel #12
0
        private LambdaCompiler(
            AnalyzedTree tree,
            LambdaExpression lambda,
            TypeBuilder typeBuilder,
            MethodInfo method,
            ILGenerator ilg,
            IList <Type> paramTypes,
            bool dynamicMethod,
            bool emitDebugSymbols)
        {
            ContractUtils.Requires(dynamicMethod || method.IsStatic, "dynamicMethod");
            _tree          = tree;
            _lambda        = lambda;
            _typeBuilder   = typeBuilder;
            _method        = method;
            _paramTypes    = new ReadOnlyCollection <Type>(paramTypes);
            _dynamicMethod = dynamicMethod;

            // These are populated by AnalyzeTree/VariableBinder
            _scope          = tree.Scopes[lambda];
            _boundConstants = tree.Constants[lambda];

            if (!dynamicMethod && _boundConstants.Count > 0)
            {
                throw Error.RtConstRequiresBundDelegate();
            }

            _ilg = new ILGen(ilg);

            Debug.Assert(!emitDebugSymbols || _typeBuilder != null, "emitting debug symbols requires a TypeBuilder");
            _emitDebugSymbols = emitDebugSymbols;

            // See if we can find a return label, so we can emit better IL
            AddReturnLabel(_lambda.Body);

            _boundConstants.EmitCacheConstants(this);
        }