public override IExpression Rewrite(ICreateDelegateInstance createDelegate) { var newDel = new CreateDelegateInstance(createDelegate); newDel.MethodToCallViaDelegate = CurrentMethod.ContainingTypeDefinition.Methods .First(m => m.ToString() == MutationTarget.PassInfo); return newDel; }
/// <summary> /// Rewrites the given anonymous delegate expression. /// </summary> public override IExpression Rewrite(IAnonymousDelegate anonymousDelegate) { if (this.isInsideAnonymousMethod) return base.Rewrite(anonymousDelegate); IMethodReference method = this.CreateClosureMethod((AnonymousDelegate)anonymousDelegate); var createDelegate = new CreateDelegateInstance() { MethodToCallViaDelegate = method, Type = anonymousDelegate.Type }; if (!method.IsStatic) { //TODO: if there is reason to believe the delegate will be constructed in a loop, but its closure is constructed before the loop, then cache the delegate in a local //that is in the same scope as the closure instance if (method.ContainingType == this.currentClosureInstance) createDelegate.Instance = this.currentClosureObject; else //non static peer method createDelegate.Instance = new ThisReference() { Type = NamedTypeDefinition.SelfInstance((INamedTypeDefinition)this.method.ContainingTypeDefinition, this.host.InternFactory) }; } else if ((method.CallingConvention & CallingConvention.Generic) == 0) { //cache the delegate in a static field (we can only do this if method is not generic, i.e. when at most one instance will be created). var cache = this.CreateStaticCacheField(anonymousDelegate.Type); var boundField = new BoundExpression() { Definition = cache, Type = cache.Type }; var statements = new List<IStatement>(1); var conditional = new ConditionalStatement() { Condition = new Equality() { LeftOperand = boundField, RightOperand = new CompileTimeConstant() { Value = null, Type = cache.Type }, Type = this.host.PlatformType.SystemBoolean }, TrueBranch = new ExpressionStatement() { Expression = new Assignment() { Target = new TargetExpression() { Definition = cache, Type = cache.Type }, Source = createDelegate, Type = cache.Type } } }; statements.Add(conditional); return new BlockExpression() { BlockStatement = new BlockStatement() { Statements = statements }, Expression = boundField }; } return createDelegate; }
public override IExpression Rewrite(ICreateObjectInstance createObjectInstance) { var mutableCreateObjectInstance = createObjectInstance as CreateObjectInstance; if (mutableCreateObjectInstance != null && mutableCreateObjectInstance.Arguments.Count == 2) { AddressOf/*?*/ aexpr = mutableCreateObjectInstance.Arguments[1] as AddressOf; if (aexpr != null && aexpr.Expression.Definition is IMethodReference) { CreateDelegateInstance createDel = new CreateDelegateInstance(); createDel.Instance = mutableCreateObjectInstance.Arguments[0]; createDel.IsVirtualDelegate = aexpr.Expression.Instance != null; createDel.MethodToCallViaDelegate = (IMethodReference)aexpr.Expression.Definition; createDel.Locations = mutableCreateObjectInstance.Locations; createDel.Type = createObjectInstance.Type; return this.Rewrite(createDel); } } return base.Rewrite(createObjectInstance); }
/// <summary> /// Visits the specified create delegate instance. /// </summary> /// <param name="createDelegateInstance">The create delegate instance.</param> /// <returns></returns> protected virtual IExpression DeepCopy(CreateDelegateInstance createDelegateInstance) { createDelegateInstance.MethodToCallViaDelegate = this.Substitute(createDelegateInstance.MethodToCallViaDelegate); if (createDelegateInstance.Instance != null) createDelegateInstance.Instance = Substitute(createDelegateInstance.Instance); createDelegateInstance.Type = this.Substitute(createDelegateInstance.Type); return createDelegateInstance; }
/// <summary> /// Visits the specified create delegate instance. /// </summary> /// <param name="createDelegateInstance">The create delegate instance.</param> public override void Visit(ICreateDelegateInstance createDelegateInstance) { CreateDelegateInstance mutableCreateDelegateInstance = new CreateDelegateInstance(createDelegateInstance); this.resultExpression = this.myCodeCopier.DeepCopy(mutableCreateDelegateInstance); }
private IExpression ConvertToAnonymousDelegate(CreateDelegateInstance createDelegateInstance, bool iteratorsHaveNotBeenDecompiled) { IMethodDefinition closureMethod = createDelegateInstance.MethodToCallViaDelegate.ResolvedMethod; if (this.sourceMethodBody.privateHelperMethodsToRemove == null) this.sourceMethodBody.privateHelperMethodsToRemove = new Dictionary<uint, IMethodDefinition>(); IMethodBody closureMethodBody = UnspecializedMethods.GetMethodBodyFromUnspecializedVersion(closureMethod); AnonymousDelegate anonDel = new AnonymousDelegate(); anonDel.CallingConvention = closureMethod.CallingConvention; var unspecializedClosureMethod = UnspecializedMethods.UnspecializedMethodDefinition(closureMethod); this.sourceMethodBody.privateHelperMethodsToRemove[unspecializedClosureMethod.InternedKey] = unspecializedClosureMethod; anonDel.Parameters = new List<IParameterDefinition>(unspecializedClosureMethod.Parameters); for (int i = 0, n = anonDel.Parameters.Count; i < n; i++) { IParameterDefinition closureMethodPar = UnspecializedParameterDefinition(anonDel.Parameters[i]); ParameterDefinition par = new ParameterDefinition(); this.parameterMap.Add(closureMethodPar, par); par.Copy(closureMethodPar, this.host.InternFactory); par.ContainingSignature = anonDel; anonDel.Parameters[i] = par; } var alreadyDecompiledBody = closureMethodBody as SourceMethodBody; ISourceMethodBody anonDelSourceMethodBody = alreadyDecompiledBody; if (alreadyDecompiledBody == null) { var alreadyDecompiledBody2 = closureMethodBody as Microsoft.Cci.MutableCodeModel.SourceMethodBody; if (alreadyDecompiledBody2 == null) { var smb = new SourceMethodBody(closureMethodBody, this.sourceMethodBody.host, this.sourceMethodBody.sourceLocationProvider, this.sourceMethodBody.localScopeProvider, this.sourceMethodBody.options); anonDelSourceMethodBody = smb; anonDel.Body = smb.Block; } else { anonDel.Body = alreadyDecompiledBody2.Block; anonDelSourceMethodBody = alreadyDecompiledBody2; } } else { anonDel.Body = alreadyDecompiledBody.Block; } anonDel.ReturnValueIsByRef = closureMethod.ReturnValueIsByRef; if (closureMethod.ReturnValueIsModified) anonDel.ReturnValueCustomModifiers = new List<ICustomModifier>(closureMethod.ReturnValueCustomModifiers); anonDel.ReturnType = closureMethod.Type; anonDel.Type = createDelegateInstance.Type; if (iteratorsHaveNotBeenDecompiled && unspecializedClosureMethod.ContainingTypeDefinition.IsGeneric && unspecializedClosureMethod.ContainingTypeDefinition.GenericParameterCount == this.sourceMethodBody.MethodDefinition.ContainingTypeDefinition.GenericParameterCount) { var mapper = new GenericTypeParameterMapper(this.host, this.sourceMethodBody.MethodDefinition.ContainingTypeDefinition, unspecializedClosureMethod.ContainingTypeDefinition); mapper.Rewrite(anonDel); } BlockStatement bs = anonDel.Body as BlockStatement; if (bs != null) { var savedReferencedLabels = this.referencedLabels; this.referencedLabels = null; anonDel.Body = this.RemoveCompilationArtifacts(bs); this.referencedLabels = savedReferencedLabels; } IExpression result = anonDel; if (this.sourceMethodBody.MethodDefinition.IsGeneric) { if (unspecializedClosureMethod.IsGeneric) this.genericParameterMapper = new GenericMethodParameterMapper(this.host, this.sourceMethodBody.MethodDefinition, unspecializedClosureMethod); // If the closure method was not generic, then its containing type is generic // and the generic parameter mapper was created when the closure instance creation // was discovered at the beginning of this visitor. if (this.genericParameterMapper != null) { result = this.genericParameterMapper.Visit(result); foreach (var v in this.capturedBinding.Values) { // Do NOT visit any of the parameters in the table because that // will cause them to (possibly) have their types changed. But // they already have the correct type because they are parameters // of the enclosing method. // But the locals are ones that were created by this visitor so // they need their types updated. LocalDefinition ld = v.Definition as LocalDefinition; if (ld != null) { ld.Type = this.genericParameterMapper.Visit(ld.Type); ld.MethodDefinition = this.sourceMethodBody.MethodDefinition; } } } } return result; }
public override IExpression Visit(CreateDelegateInstance createDelegateInstance) { IMethodDefinition delegateMethodDefinition = createDelegateInstance.MethodToCallViaDelegate.ResolvedMethod; delegateMethodDefinition = UnspecializedMethods.UnspecializedMethodDefinition(delegateMethodDefinition); ITypeReference delegateContainingType = createDelegateInstance.MethodToCallViaDelegate.ContainingType; delegateContainingType = UnspecializedMethods.AsUnspecializedTypeReference(delegateContainingType); INestedTypeDefinition/*?*/ dctnt = delegateContainingType.ResolvedType as INestedTypeDefinition; ITypeDefinition/*?*/ dctct = dctnt == null ? null : dctnt.ContainingTypeDefinition; if (this.restoreAnonymousDelegates && (TypeHelper.TypesAreEquivalent(delegateContainingType.ResolvedType, this.containingType) || TypeHelper.TypesAreEquivalent(dctct, this.containingType)) && UnspecializedMethods.IsCompilerGenerated(delegateMethodDefinition)) return ConvertToAnonymousDelegate(createDelegateInstance, iteratorsHaveNotBeenDecompiled: false); // REVIEW: This is needed only when iterators are *not* decompiled. When they are, then that happens before this phase and the create delegate instances // have been moved into the iterator method (from the MoveNext method) so the above pattern catches everything. if (this.restoreAnonymousDelegates && UnspecializedMethods.IsCompilerGenerated(delegateMethodDefinition)) { var containingTypeAsNestedType = this.containingType as INestedTypeDefinition; if (containingTypeAsNestedType != null && dctnt != null && TypeHelper.TypesAreEquivalent(dctnt.ContainingType, containingTypeAsNestedType.ContainingType)) { return ConvertToAnonymousDelegate(createDelegateInstance, iteratorsHaveNotBeenDecompiled: true); } } return base.Visit(createDelegateInstance); }
/// <summary> /// Rewrites the children of the anonymous object creation expression. /// </summary> public virtual void RewriteChildren(CreateDelegateInstance createDelegateInstance) { this.RewriteChildren((Expression)createDelegateInstance); if (createDelegateInstance.Instance != null) createDelegateInstance.Instance = this.Rewrite(createDelegateInstance.Instance); createDelegateInstance.MethodToCallViaDelegate = this.Rewrite(createDelegateInstance.MethodToCallViaDelegate); }
/// <summary> /// Visits the specified create delegate instance. /// </summary> /// <param name="createDelegateInstance">The create delegate instance.</param> /// <returns></returns> public virtual IExpression Visit(CreateDelegateInstance createDelegateInstance) { createDelegateInstance.MethodToCallViaDelegate = this.Visit(createDelegateInstance.MethodToCallViaDelegate); if (createDelegateInstance.Instance != null) createDelegateInstance.Instance = Visit(createDelegateInstance.Instance); createDelegateInstance.Type = this.Visit(createDelegateInstance.Type); return createDelegateInstance; }
/// <summary> /// Visits the specified create delegate instance. /// </summary> /// <param name="createDelegateInstance">The create delegate instance.</param> public override void Visit(ICreateDelegateInstance createDelegateInstance) { CreateDelegateInstance mutableCreateDelegateInstance = createDelegateInstance as CreateDelegateInstance; if (alwaysMakeACopy || mutableCreateDelegateInstance == null) mutableCreateDelegateInstance = new CreateDelegateInstance(createDelegateInstance); this.resultExpression = this.myCodeMutator.Visit(mutableCreateDelegateInstance); }