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; var 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. var 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)); }
private void EmitDelegateConstruction(LambdaCompiler inner) { var delegateType = inner._lambda.Type; var dynamicMethod = inner._method as DynamicMethod; if (dynamicMethod != null) { var types = new[] { typeof(Type), typeof(object) }; var createDelegate = typeof(DynamicMethod).GetMethod("CreateDelegate", types); if (createDelegate != null) { _boundConstants.EmitConstant(this, dynamicMethod, typeof(DynamicMethod)); _ilg.EmitType(delegateType); EmitClosureCreation(inner); _ilg.Emit(OpCodes.Callvirt, createDelegate); _ilg.Emit(OpCodes.Castclass, delegateType); } else { // 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", types)); _ilg.Emit(OpCodes.Castclass, delegateType); } } else { // new DelegateType(closure) EmitClosureCreation(inner); _ilg.Emit(OpCodes.Ldftn, inner._method); _ilg.Emit(OpCodes.Newobj, (ConstructorInfo)(delegateType.GetMember(".ctor")[0])); } }
/// <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); }
internal void AddLocal(LambdaCompiler gen, ParameterExpression variable) { _locals.Add(variable, new LocalStorage(gen, variable)); }
internal ArgumentStorage(LambdaCompiler compiler, ParameterExpression p) : base(compiler, p) { _argument = compiler.GetLambdaArgument(compiler.Parameters.IndexOf(p)); }
protected Storage(LambdaCompiler compiler, ParameterExpression variable) { Compiler = compiler; Variable = variable; }