internal LocalStorage(LambdaCompiler compiler, ParameterExpression v)
     : base(compiler, v) {
     // ByRef variables are supported. This is used internally by
     // the compiler when emitting an inlined lambda invoke, to 
     // handle ByRef parameters. BlockExpression prevents this
     // from being exposed to user created trees.
     _local = compiler.GetNamedLocal(v.IsByRef ? v.Type.MakeByRefType() : v.Type, v.Name);
 }
 private void AllocateLocals(LambdaCompiler lc)
 {
     foreach (ParameterExpression expression in this.GetVariables())
     {
         if (((VariableStorageKind) this.Definitions[expression]) == VariableStorageKind.Local)
         {
             Storage storage;
             if (this.IsMethod && lc.Parameters.Contains(expression))
             {
                 storage = new ArgumentStorage(lc, expression);
             }
             else
             {
                 storage = new LocalStorage(lc, expression);
             }
             this._locals.Add(expression, storage);
         }
     }
 }
        private void EmitDelegateConstruction(LambdaCompiler inner)
        {
            var delegateType = inner._lambda.Type;

            if (inner._method is DynamicMethod dynamicMethod)
            {
                // dynamicMethod.CreateDelegate(delegateType, closure)
                _boundConstants.EmitConstant(this, dynamicMethod, typeof(DynamicMethod));
                IL.EmitType(delegateType);
                EmitClosureCreation(inner);
                IL.Emit(OpCodes.Callvirt, typeof(DynamicMethod).GetMethod(nameof(DynamicMethod.CreateDelegate), new[] { typeof(Type), typeof(object) }));
                IL.Emit(OpCodes.Castclass, delegateType);
            }
            else
            {
                // new DelegateType(closure)
                EmitClosureCreation(inner);
                IL.Emit(OpCodes.Ldftn, inner._method);
                IL.Emit(OpCodes.Newobj, (ConstructorInfo)delegateType.GetMember(".ctor")[0]);
            }
        }
Example #4
0
        private void EmitConstantFromArray(LambdaCompiler lc, object value, Type type)
        {
            int index;

            if (!_indexes.TryGetValue(value, out index))
            {
                _indexes.Add(value, index = _values.Count);
                _values.Add(value);
            }

            lc.IL.EmitPrimitive(index);
            lc.IL.Emit(OpCodes.Ldelem_Ref);
            if (type.IsValueType)
            {
                lc.IL.Emit(OpCodes.Unbox_Any, type);
            }
            else if (type != typeof(object))
            {
                lc.IL.Emit(OpCodes.Castclass, type);
            }
        }
Example #5
0
 // Allocates slots for IL locals or IL arguments
 private void AllocateLocals(LambdaCompiler lc)
 {
     foreach (ParameterExpression v in GetVariables())
     {
         if (Definitions[v] == VariableStorageKind.Local)
         {
             Storage s;
             //If v is in lc.Parameters, it is a parameter.
             //Otherwise, it is a local variable.
             if (lc.Parameters.Contains(v))
             {
                 s = new ArgumentStorage(lc, v);
             }
             else
             {
                 s = new LocalStorage(lc, v);
             }
             _locals.Add(v, s);
         }
     }
 }
Example #6
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));
        }
Example #7
0
        internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection <ParameterExpression> vars)
        {
            if (NearestHoistedLocals != null)
            {
                // Find what array each variable is on & its index
                var indexes = new List <long>(vars.Count);

                foreach (var variable in vars)
                {
                    // For each variable, find what array it's defined on
                    ulong         parents = 0;
                    HoistedLocals locals  = NearestHoistedLocals;
                    while (!locals.Indexes.ContainsKey(variable))
                    {
                        parents++;
                        locals = locals.Parent;
                        Debug.Assert(locals != null);
                    }

                    // combine the number of parents we walked, with the
                    // real index of variable to get the index to emit.
                    ulong index = (parents << 32) | (uint)locals.Indexes[variable];

                    indexes.Add((long)index);
                }

                if (indexes.Count > 0)
                {
                    EmitGet(NearestHoistedLocals.SelfVariable);
                    lc.EmitConstantArray(indexes.ToArray());
                    lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", new[] { typeof(object[]), typeof(long[]) }));
                    return;
                }
            }

            // No visible variables
            lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", Type.EmptyTypes));
            return;
        }
Example #8
0
        /// <summary>
        /// Emits code which creates new instance of the delegateType delegate.
        ///
        /// Since the delegate is getting closed over the "Closure" argument, this
        /// cannot be used with virtual/instance methods (inner must be static method)
        /// </summary>
        private void EmitDelegateConstruction(LambdaCompiler inner)
        {
            Type          delegateType  = inner._lambda.Type;
            DynamicMethod dynamicMethod = inner._method as DynamicMethod;

            if (dynamicMethod != null)
            {
                // Emit MethodInfo.CreateDelegate instead because DynamicMethod is not in Windows 8 Profile
                _boundConstants.EmitConstant(this, dynamicMethod, typeof(MethodInfo));
                _ilg.EmitType(delegateType);
                EmitClosureCreation(inner);
                _ilg.Emit(OpCodes.Callvirt, typeof(MethodInfo).GetMethod("CreateDelegate", new Type[] { typeof(Type), typeof(object) }));
                _ilg.Emit(OpCodes.Castclass, delegateType);
            }
            else
            {
                // new DelegateType(closure)
                EmitClosureCreation(inner);
                _ilg.Emit(OpCodes.Ldftn, (MethodInfo)inner._method);
                _ilg.Emit(OpCodes.Newobj, (ConstructorInfo)(delegateType.GetMember(".ctor")[0]));
            }
        }
 private void EmitNewHoistedLocals(LambdaCompiler lc)
 {
     if (this._hoistedLocals != null)
     {
         lc.IL.EmitInt(this._hoistedLocals.Variables.Count);
         lc.IL.Emit(OpCodes.Newarr, typeof(object));
         int num = 0;
         foreach (ParameterExpression expression in this._hoistedLocals.Variables)
         {
             lc.IL.Emit(OpCodes.Dup);
             lc.IL.EmitInt(num++);
             Type type = typeof(StrongBox <>).MakeGenericType(new Type[] { expression.Type });
             if (this.IsMethod && lc.Parameters.Contains(expression))
             {
                 int index = lc.Parameters.IndexOf(expression);
                 lc.EmitLambdaArgument(index);
                 lc.IL.Emit(OpCodes.Newobj, type.GetConstructor(new Type[] { expression.Type }));
             }
             else if (expression == this._hoistedLocals.ParentVariable)
             {
                 this.ResolveVariable(expression, this._closureHoistedLocals).EmitLoad();
                 lc.IL.Emit(OpCodes.Newobj, type.GetConstructor(new Type[] { expression.Type }));
             }
             else
             {
                 lc.IL.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
             }
             if (this.ShouldCache(expression))
             {
                 lc.IL.Emit(OpCodes.Dup);
                 this.CacheBoxToLocal(lc, expression);
             }
             lc.IL.Emit(OpCodes.Stelem_Ref);
         }
         this.EmitSet(this._hoistedLocals.SelfVariable);
     }
 }
        /// <summary>
        /// Emits a delegate to the method generated for the LambdaExpression.
        /// May end up creating a wrapper to match the requested delegate type.
        /// </summary>
        /// <param name="lambda">Lambda for which to generate a delegate</param>
        ///
        private void EmitDelegateConstruction(LambdaExpression lambda)
        {
            // 1. Create the new compiler
            LambdaCompiler impl;

            if (_method is DynamicMethod)
            {
                impl = new LambdaCompiler(_tree, lambda);
            }
            else
            {
                // When the lambda does not have a name or the name is empty, generate a unique name for it.
                var name = string.IsNullOrEmpty(lambda.Name) ? GetUniqueMethodName() : lambda.Name;
                var mb   = _typeBuilder.DefineMethod(name, MethodAttributes.Private | MethodAttributes.Static);
                impl = new LambdaCompiler(_tree, lambda, mb);
            }

            // 2. emit the lambda
            // Since additional ILs are always emitted after the lambda's body, should not emit with tail call optimization.
            impl.EmitLambdaBody(_scope, false, CompilationFlags.EmitAsNoTail);

            // 3. emit the delegate creation in the outer lambda
            EmitDelegateConstruction(impl);
        }
Example #11
0
        internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection <ParameterExpression> vars)
        {
            if (NearestHoistedLocals != null && vars.Count > 0)
            {
                // Find what array each variable is on & its index
                var indexes = new ArrayBuilder <long>(vars.Count);

                foreach (ParameterExpression variable in vars)
                {
                    // For each variable, find what array it's defined on
                    ulong         parents = 0;
                    HoistedLocals?locals  = NearestHoistedLocals;
                    while (!locals.Indexes.ContainsKey(variable))
                    {
                        parents++;
                        locals = locals.Parent;
                        Debug.Assert(locals != null);
                    }

                    // combine the number of parents we walked, with the
                    // real index of variable to get the index to emit.
                    ulong index = (parents << 32) | (uint)locals.Indexes[variable];

                    indexes.UncheckedAdd((long)index);
                }

                EmitGet(NearestHoistedLocals.SelfVariable);
                lc.EmitConstantArray(indexes.ToArray());
                lc.IL.Emit(OpCodes.Call, RuntimeOps_CreateRuntimeVariables_ObjectArray_Int64Array);
            }
            else
            {
                // No visible variables
                lc.IL.Emit(OpCodes.Call, RuntimeOps_CreateRuntimeVariables);
            }
        }
Example #12
0
 private void EmitClosureToVariable(LambdaCompiler lc, HoistedLocals locals)
 {
     lc.EmitClosureArgument();
     lc.IL.Emit(OpCodes.Ldfld, Closure_Locals);
     AddLocal(lc, locals.SelfVariable);
     EmitSet(locals.SelfVariable);
 }
Example #13
0
 private static void EmitConstantsArray(LambdaCompiler lc)
 {
     lc.EmitClosureArgument();
     lc.IL.Emit(OpCodes.Ldfld, typeof(Closure).GetField("Constants"));
 }
 internal ArgumentStorage(LambdaCompiler compiler, ParameterExpression p) : base(compiler, p)
 {
     this._argument = compiler.GetLambdaArgument(compiler.Parameters.IndexOf(p));
 }
 internal CompilerScope Enter(LambdaCompiler lc, CompilerScope parent)
 {
     this.SetParent(lc, parent);
     this.AllocateLocals(lc);
     if (this.IsMethod && (this._closureHoistedLocals != null))
     {
         this.EmitClosureAccess(lc, this._closureHoistedLocals);
     }
     this.EmitNewHoistedLocals(lc);
     if (this.IsMethod)
     {
         this.EmitCachedVariables();
     }
     return this;
 }
 private void EmitNewHoistedLocals(LambdaCompiler lc)
 {
     if (this._hoistedLocals != null)
     {
         lc.IL.EmitInt(this._hoistedLocals.Variables.Count);
         lc.IL.Emit(OpCodes.Newarr, typeof(object));
         int num = 0;
         foreach (ParameterExpression expression in this._hoistedLocals.Variables)
         {
             lc.IL.Emit(OpCodes.Dup);
             lc.IL.EmitInt(num++);
             Type type = typeof(StrongBox<>).MakeGenericType(new Type[] { expression.Type });
             if (this.IsMethod && lc.Parameters.Contains(expression))
             {
                 int index = lc.Parameters.IndexOf(expression);
                 lc.EmitLambdaArgument(index);
                 lc.IL.Emit(OpCodes.Newobj, type.GetConstructor(new Type[] { expression.Type }));
             }
             else if (expression == this._hoistedLocals.ParentVariable)
             {
                 this.ResolveVariable(expression, this._closureHoistedLocals).EmitLoad();
                 lc.IL.Emit(OpCodes.Newobj, type.GetConstructor(new Type[] { expression.Type }));
             }
             else
             {
                 lc.IL.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
             }
             if (this.ShouldCache(expression))
             {
                 lc.IL.Emit(OpCodes.Dup);
                 this.CacheBoxToLocal(lc, expression);
             }
             lc.IL.Emit(OpCodes.Stelem_Ref);
         }
         this.EmitSet(this._hoistedLocals.SelfVariable);
     }
 }
 internal LocalBoxStorage(LambdaCompiler compiler, ParameterExpression variable) : base(compiler, variable)
 {
     this._boxType       = typeof(StrongBox <>).MakeGenericType(new Type[] { variable.Type });
     this._boxValueField = this._boxType.GetField("Value");
     this._boxLocal      = compiler.GetNamedLocal(this._boxType, variable);
 }
Example #18
0
 // Allocates slots for IL locals or IL arguments
 private void AllocateLocals(LambdaCompiler lc) {
     foreach (ParameterExpression v in GetVariables()) {
         if (Definitions[v] == VariableStorageKind.Local) {
             Storage s;
             //If v is in lc.Parameters, it is a parameter.
             //Otherwise, it is a local variable.
             if (lc.Parameters.Contains(v)) {
                 s = new ArgumentStorage(lc, v);
             } else {
                 s = new LocalStorage(lc, v);
             }
             _locals.Add(v, s);
         }
     }
 }
Example #19
0
        internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection<ParameterExpression> vars) {
            if (NearestHoistedLocals != null) {
                // Find what array each variable is on & its index
                var indexes = new List<long>(vars.Count);

                foreach (var variable in vars) {
                    // For each variable, find what array it's defined on
                    ulong parents = 0;
                    HoistedLocals locals = NearestHoistedLocals;
                    while (!locals.Indexes.ContainsKey(variable)) {
                        parents++;
                        locals = locals.Parent;
                        Debug.Assert(locals != null);
                    }
                    
                    // combine the number of parents we walked, with the
                    // real index of variable to get the index to emit.
                    ulong index = (parents << 32) | (uint)locals.Indexes[variable];

                    indexes.Add((long)index);
                }

                if (indexes.Count > 0) {
                    EmitGet(NearestHoistedLocals.SelfVariable);
                    lc.EmitConstantArray(indexes.ToArray());
                    lc.IL.EmitCall(typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", new[] { typeof(object[]), typeof(long[]) }));
                    return;
                }
            }

            // No visible variables
            lc.IL.EmitCall(typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", Type.EmptyTypes));
            return;
        }
 internal LocalStorage(LambdaCompiler compiler, ParameterExpression variable)
     : base(compiler, variable)
 {
     _local = compiler.GetNamedLocal(variable.Type, variable.Name);
 }
 internal LocalStorage(LambdaCompiler compiler, ParameterExpression variable) : base(compiler, variable)
 {
     this._local = compiler.GetNamedLocal(variable.IsByRef ? variable.Type.MakeByRefType() : variable.Type, variable);
 }
 internal LocalStorage(LambdaCompiler compiler, ParameterExpression variable)
     : base(compiler, variable) {
     _local = compiler.GetNamedLocal(variable.Type, variable.Name);
 }
Example #23
0
 // Allocates slots for IL locals or IL arguments
 private void AllocateLocals(LambdaCompiler lc)
 {
     foreach (ParameterExpression v in GetVariables())
     {
         if (Definitions[v] == VariableStorageKind.Local)
         {
             //
             // If v is in lc.Parameters, it is a parameter.
             // Otherwise, it is a local variable.
             //
             // Also, for inlined lambdas we'll create a local, which
             // is possibly a byref local if the parameter is byref.
             //
             Storage s;
             if (IsMethod && lc.Parameters.Contains(v))
             {
                 s = new ArgumentStorage(lc, v);
             }
             else
             {
                 s = new LocalStorage(lc, v);
             }
             _locals.Add(v, s);
         }
     }
 }
 private void EmitClosureToVariable(LambdaCompiler lc, HoistedLocals locals)
 {
     lc.EmitClosureArgument();
     lc.IL.Emit(OpCodes.Ldfld, typeof(Closure).GetField("Locals"));
     this.AddLocal(lc, locals.SelfVariable);
     this.EmitSet(locals.SelfVariable);
 }
 internal LocalStorage(LambdaCompiler compiler, ParameterExpression variable) : base(compiler, variable)
 {
     this._local = compiler.GetNamedLocal(variable.IsByRef ? variable.Type.MakeByRefType() : variable.Type, variable);
 }
 internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection<ParameterExpression> vars)
 {
     if (this.NearestHoistedLocals != null)
     {
         List<long> list = new List<long>(vars.Count);
         foreach (ParameterExpression expression in vars)
         {
             ulong num = 0L;
             HoistedLocals nearestHoistedLocals = this.NearestHoistedLocals;
             while (!nearestHoistedLocals.Indexes.ContainsKey(expression))
             {
                 num += (ulong) 1L;
                 nearestHoistedLocals = nearestHoistedLocals.Parent;
             }
             ulong num2 = (num << 0x20) | ((ulong) nearestHoistedLocals.Indexes[expression]);
             list.Add((long) num2);
         }
         if (list.Count > 0)
         {
             this.EmitGet(this.NearestHoistedLocals.SelfVariable);
             lc.EmitConstantArray<long>(list.ToArray());
             lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", new Type[] { typeof(object[]), typeof(long[]) }));
             return;
         }
     }
     lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", Type.EmptyTypes));
 }
 private void CacheBoxToLocal(LambdaCompiler lc, ParameterExpression v)
 {
     LocalBoxStorage storage = new LocalBoxStorage(lc, v);
     storage.EmitStoreBox();
     this._locals.Add(v, storage);
 }
 private void SetParent(LambdaCompiler lc, CompilerScope parent)
 {
     this._parent = parent;
     if (this.NeedsClosure && (this._parent != null))
     {
         this._closureHoistedLocals = this._parent.NearestHoistedLocals;
     }
     ReadOnlyCollection<ParameterExpression> vars = (from p in this.GetVariables()
         where ((VariableStorageKind) this.Definitions[p]) == VariableStorageKind.Hoisted
         select p).ToReadOnly<ParameterExpression>();
     if (vars.Count > 0)
     {
         this._hoistedLocals = new HoistedLocals(this._closureHoistedLocals, vars);
         this.AddLocal(lc, this._hoistedLocals.SelfVariable);
     }
 }
Example #29
0
 internal Storage(LambdaCompiler compiler, ParameterExpression variable)
 {
     Compiler = compiler;
     Variable = variable;
 }
 internal void AddLocal(LambdaCompiler gen, ParameterExpression variable)
 {
     this._locals.Add(variable, new LocalStorage(gen, variable));
 }
        private void EmitInlinedInvoke(InvocationExpression invoke) {
            var lambda = invoke.LambdaOperand;

            // This is tricky: we need to emit the arguments outside of the
            // scope, but set them inside the scope. Fortunately, using the IL
            // stack it is entirely doable.

            // 1. Emit invoke arguments
            List<WriteBack> wb = EmitArguments(lambda.Type.GetMethod("Invoke"), invoke);

            // 2. Create the nested LambdaCompiler
            var inner = new LambdaCompiler(this, lambda);

            // 3. Emit the body
            inner.EmitLambdaBody(_scope, true);

            // 4. Emit writebacks if needed
            EmitWriteBack(wb);
        }
 internal LocalBoxStorage(LambdaCompiler compiler, ParameterExpression variable) : base(compiler, variable)
 {
     this._boxType = typeof(StrongBox<>).MakeGenericType(new Type[] { variable.Type });
     this._boxValueField = this._boxType.GetField("Value");
     this._boxLocal = compiler.GetNamedLocal(this._boxType, variable);
 }
Example #33
0
        /// <summary>
        /// Called when entering a lambda/block. Performs all variable allocation
        /// needed, including creating hoisted locals and IL locals for accessing
        /// parent locals
        /// </summary>
        internal CompilerScope Enter(LambdaCompiler lc, CompilerScope parent)
        {
            SetParent(lc, parent);

            AllocateLocals(lc);

            if (IsMethod && _closureHoistedLocals != null)
            {
                EmitClosureAccess(lc, _closureHoistedLocals);
            }

            EmitNewHoistedLocals(lc);

            if (IsMethod)
            {
                EmitCachedVariables();
            }

            return this;
        }
 internal Storage(LambdaCompiler compiler, ParameterExpression variable)
 {
     this.Compiler = compiler;
     this.Variable = variable;
 }
Example #35
0
        internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection<ParameterExpression> vars)
        {
            if (NearestHoistedLocals != null && vars.Count > 0)
            {
                // Find what array each variable is on & its index
                var indexes = new ArrayBuilder<long>(vars.Count);

                foreach (ParameterExpression variable in vars)
                {
                    // For each variable, find what array it's defined on
                    ulong parents = 0;
                    HoistedLocals locals = NearestHoistedLocals;
                    while (!locals.Indexes.ContainsKey(variable))
                    {
                        parents++;
                        locals = locals.Parent;
                        Debug.Assert(locals != null);
                    }

                    // combine the number of parents we walked, with the
                    // real index of variable to get the index to emit.
                    ulong index = (parents << 32) | (uint)locals.Indexes[variable];

                    indexes.UncheckedAdd((long)index);
                }

                EmitGet(NearestHoistedLocals.SelfVariable);
                lc.EmitConstantArray(indexes.ToArray());
                lc.IL.Emit(OpCodes.Call, RuntimeOps_CreateRuntimeVariables_ObjectArray_Int64Array);
            }
            else
            {
                // No visible variables
                lc.IL.Emit(OpCodes.Call, RuntimeOps_CreateRuntimeVariables);
            }
        }
 private void EmitClosureAccess(LambdaCompiler lc, HoistedLocals locals)
 {
     if (locals != null)
     {
         this.EmitClosureToVariable(lc, locals);
         while ((locals = locals.Parent) != null)
         {
             ParameterExpression selfVariable = locals.SelfVariable;
             LocalStorage storage = new LocalStorage(lc, selfVariable);
             storage.EmitStore(this.ResolveVariable(selfVariable));
             this._locals.Add(selfVariable, storage);
         }
     }
 }
Example #37
0
        private void SetParent(LambdaCompiler lc, CompilerScope parent)
        {
            Debug.Assert(_parent == null && parent != this);
            _parent = parent;

            if (NeedsClosure && _parent != null)
            {
                _closureHoistedLocals = _parent.NearestHoistedLocals;
            }

            ReadOnlyCollection<ParameterExpression> hoistedVars = GetVariables().Where(p => Definitions[p] == VariableStorageKind.Hoisted).ToReadOnly();

            if (hoistedVars.Count > 0)
            {
                _hoistedLocals = new HoistedLocals(_closureHoistedLocals, hoistedVars);
                AddLocal(lc, _hoistedLocals.SelfVariable);
            }
        }
Example #38
0
 internal ArgumentStorage(LambdaCompiler compiler, ParameterExpression p)
     : base(compiler, p)
 {
     _argument = compiler.GetLambdaArgument(compiler.Parameters.IndexOf(p));
 }
Example #39
0
        // Emits creation of the hoisted local storage
        private void EmitNewHoistedLocals(LambdaCompiler lc)
        {
            if (_hoistedLocals == null)
            {
                return;
            }

            // create the array
            lc.IL.EmitInt(_hoistedLocals.Variables.Count);
            lc.IL.Emit(OpCodes.Newarr, typeof(object));

            // initialize all elements
            int i = 0;
            foreach (ParameterExpression v in _hoistedLocals.Variables)
            {
                // array[i] = new StrongBox<T>(...);
                lc.IL.Emit(OpCodes.Dup);
                lc.IL.EmitInt(i++);
                Type boxType = typeof(StrongBox<>).MakeGenericType(v.Type);

                if (IsMethod && lc.Parameters.Contains(v))
                {
                    // array[i] = new StrongBox<T>(argument);
                    int index = lc.Parameters.IndexOf(v);
                    lc.EmitLambdaArgument(index);
                    lc.IL.Emit(OpCodes.Newobj, boxType.GetConstructor(new Type[] { v.Type }));
                }
                else if (v == _hoistedLocals.ParentVariable)
                {
                    // array[i] = new StrongBox<T>(closure.Locals);
                    ResolveVariable(v, _closureHoistedLocals).EmitLoad();
                    lc.IL.Emit(OpCodes.Newobj, boxType.GetConstructor(new Type[] { v.Type }));
                }
                else
                {
                    // array[i] = new StrongBox<T>();
                    lc.IL.Emit(OpCodes.Newobj, boxType.GetConstructor(Type.EmptyTypes));
                }
                // if we want to cache this into a local, do it now
                if (ShouldCache(v))
                {
                    lc.IL.Emit(OpCodes.Dup);
                    CacheBoxToLocal(lc, v);
                }
                lc.IL.Emit(OpCodes.Stelem_Ref);
            }

            // store it
            EmitSet(_hoistedLocals.SelfVariable);
        }
Example #40
0
 /// <summary>
 /// Adds a new virtual variable corresponding to an IL local
 /// </summary>
 internal void AddLocal(LambdaCompiler gen, ParameterExpression variable)
 {
     _locals.Add(variable, new LocalStorage(gen, variable));
 }
Example #41
0
 private void CacheBoxToLocal(LambdaCompiler lc, ParameterExpression v)
 {
     Debug.Assert(ShouldCache(v) && !_locals.ContainsKey(v));
     var local = new LocalBoxStorage(lc, v);
     local.EmitStoreBox();
     _locals.Add(v, local);
 }
        private void EmitInlinedInvoke(InvocationExpression invoke, CompilationFlags flags)
        {
            var lambda = invoke.LambdaOperand;

            // This is tricky: we need to emit the arguments outside of the
            // scope, but set them inside the scope. Fortunately, using the IL
            // stack it is entirely doable.

            // 1. Emit invoke arguments
            List<WriteBack> wb = EmitArguments(lambda.Type.GetMethod("Invoke"), invoke);

            // 2. Create the nested LambdaCompiler
            var inner = new LambdaCompiler(this, lambda, invoke);

            // 3. Emit the body
            // if the inlined lambda is the last expression of the whole lambda,
            // tail call can be applied.
            if (wb.Count != 0)
            {
                flags = UpdateEmitAsTailCallFlag(flags, CompilationFlags.EmitAsNoTail);
            }
            inner.EmitLambdaBody(_scope, true, flags);

            // 4. Emit write-backs if needed
            EmitWriteBack(wb);
        }
Example #43
0
        // Creates IL locals for accessing closures
        private void EmitClosureAccess(LambdaCompiler lc, HoistedLocals locals)
        {
            if (locals == null)
            {
                return;
            }

            EmitClosureToVariable(lc, locals);

            while ((locals = locals.Parent) != null)
            {
                ParameterExpression v = locals.SelfVariable;
                var local = new LocalStorage(lc, v);
                local.EmitStore(ResolveVariable(v));
                _locals.Add(v, local);
            }
        }