public override IMethodBody Rewrite(IMethodBody body) { var method = body.MethodDefinition; _log.Info("Rewriting IMethodBody of: " + method + " Pass: " + MutationTarget.PassInfo); var newBody = new SourceMethodBody(Host) { MethodDefinition = method, LocalsAreZeroed = true }; var block = new BlockStatement(); newBody.Block = block; var replacement = method.ContainingTypeDefinition.Methods.Single(m => m.ToString() == MutationTarget.PassInfo); var methodCall = new MethodCall { MethodToCall = replacement, Type = replacement.Type, ThisArgument = new ThisReference() {Type = method.ContainingTypeDefinition} }; foreach (var param in replacement.Parameters) { methodCall.Arguments.Add(new BoundExpression() { Definition = method.Parameters .First(p => ((INamedTypeReference)p.Type).Name.Value == ((INamedTypeReference)param.Type).Name.Value) }); // methodCall.Arguments.Add(method.Parameters.First(p => new )); } if (replacement.Type == Host.PlatformType.SystemVoid) { block.Statements.Add(new ExpressionStatement { Expression = methodCall }); block.Statements.Add(new ReturnStatement()); } else { block.Statements.Add(new ReturnStatement { Expression = methodCall }); } return newBody; }
/// <summary> /// Records all of the helper types of the method body into this.helperTypes. /// </summary> /// <param name="methodBody"></param> public override void TraverseChildren(IMethodBody methodBody) { if (!(methodBody is SourceMethodBody)) { // BCT omitted? return; } var mutableBody = (SourceMethodBody)methodBody; var block = mutableBody.Block; //force decompilation bool denormalize = false; if (mutableBody.privateHelperTypesToRemove != null) { denormalize = true; foreach (var helperType in mutableBody.privateHelperTypesToRemove) { Contract.Assume(helperType != null); this.helperTypes[helperType.InternedKey] = helperType; } } if (mutableBody.privateHelperMethodsToRemove != null) { denormalize = true; foreach (var helperMethod in mutableBody.privateHelperMethodsToRemove.Values) { Contract.Assume(helperMethod != null); this.helperMethods[helperMethod.InternedKey] = helperMethod; } } if (mutableBody.privateHelperFieldsToRemove != null) { denormalize = true; foreach (var helperField in mutableBody.privateHelperFieldsToRemove) { this.helperFields[helperField] = helperField; } } if (denormalize) { var mutableMethod = (MethodDefinition)mutableBody.MethodDefinition; var denormalizedBody = new Microsoft.Cci.MutableCodeModel.SourceMethodBody(this.host, this.sourceLocationProvider); denormalizedBody.LocalsAreZeroed = mutableBody.LocalsAreZeroed; denormalizedBody.IsNormalized = false; denormalizedBody.Block = block; denormalizedBody.MethodDefinition = mutableMethod; mutableMethod.Body = denormalizedBody; } }
/// <summary> /// Given a method definition and a block of statements that represents the Block property of the body of the method, /// returns a SourceMethod with a body that no longer has any yield statements or anonymous delegate expressions. /// The given block of statements is mutated in place. /// </summary> public SourceMethodBody GetNormalizedSourceMethodBodyFor(IMethodDefinition method, IBlockStatement body) { var finder = new ClosureFinder(method, this.host); finder.Traverse(body); var privateHelperTypes = new List<ITypeDefinition>(); if (finder.foundYield) { this.isIteratorBody = true; body = this.GetNormalizedIteratorBody(body, method, privateHelperTypes); } SourceMethodBody result = new SourceMethodBody(this.host, this.sourceLocationProvider); result.Block = body; result.MethodDefinition = method; result.IsNormalized = true; result.LocalsAreZeroed = true; result.PrivateHelperTypes = privateHelperTypes; return result; }
/// <summary> /// Create the generic version of the GetEnumerator for the iterator closure class. /// </summary> /// <param name="iteratorClosure"></param> private void CreateGetEnumeratorMethodGeneric(IteratorClosureInformation iteratorClosure) { // Metadata MethodDefinition genericGetEnumerator = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("System.Collections.Generic.IEnumerable<" + iteratorClosure.ElementType.ToString()+">.GetEnumerator") }; CustomAttribute debuggerHiddenAttribute = new CustomAttribute() { Constructor = this.DebuggerHiddenCtor }; genericGetEnumerator.Attributes.Add(debuggerHiddenAttribute); genericGetEnumerator.CallingConvention |= CallingConvention.HasThis; genericGetEnumerator.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; genericGetEnumerator.Visibility = TypeMemberVisibility.Public; genericGetEnumerator.Type = iteratorClosure.GenericIEnumeratorInterface; genericGetEnumerator.IsVirtual = true; genericGetEnumerator.IsNewSlot = true; genericGetEnumerator.IsHiddenBySignature = true; genericGetEnumerator.IsSealed = true; // Membership iteratorClosure.GenericGetEnumerator = genericGetEnumerator; IMethodReference genericGetEnumeratorOriginal = Dummy.MethodReference; // Explicit implementation of IEnumerable<T>.GetEnumerator foreach (var memref in iteratorClosure.GenericIEnumerableInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("GetEnumerator"), false)) { IMethodReference mref = memref as IMethodReference; if (mref != null) { genericGetEnumeratorOriginal = mref; break; } } var genericGetEnumeratorImp = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementingMethod = genericGetEnumerator, ImplementedMethod = genericGetEnumeratorOriginal }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(genericGetEnumeratorImp); // Body var block = GetBodyOfGenericGetEnumerator(iteratorClosure); var body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.LocalsAreZeroed = true; body.IsNormalized = true; body.Block = block; body.MethodDefinition = genericGetEnumerator; genericGetEnumerator.Body = body; }
/// <summary> /// DisposeMethod method. Currently the method body does nothing. /// </summary> private void CreateDisposeMethod(IteratorClosureInformation iteratorClosure) { MethodDefinition disposeMethod = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("Dispose") }; disposeMethod.Attributes.Add(new CustomAttribute() { Constructor = this.debuggerHiddenCtor }); disposeMethod.CallingConvention |= CallingConvention.HasThis; disposeMethod.Visibility = TypeMemberVisibility.Public; disposeMethod.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; disposeMethod.Type = this.host.PlatformType.SystemVoid; disposeMethod.IsVirtual = true; disposeMethod.IsNewSlot = true; disposeMethod.IsHiddenBySignature = true; disposeMethod.IsSealed = true; // Add disposeMethod to parent's member list. iteratorClosure.DisposeMethod = disposeMethod; // Explicitly implements IDisposable's dispose. IMethodReference disposeImplemented = Dummy.MethodReference; foreach (var memref in iteratorClosure.DisposableInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("Dispose"), false)) { IMethodReference mref = memref as IMethodReference; if (mref != null) { disposeImplemented = mref; break; } } MethodImplementation disposeImp = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementedMethod = disposeImplemented, ImplementingMethod = disposeMethod }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(disposeImp); // Body is a sole return. BlockStatement block = new BlockStatement(); block.Statements.Add(new ReturnStatement() { Expression = null, Locations = iteratorClosure.ClosureDefinition.Locations }); SourceMethodBody body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.LocalsAreZeroed = true; body.IsNormalized = true; body.Block = block; body.MethodDefinition = disposeMethod; disposeMethod.Body = body; }
/// <summary> /// Rewrites the children of the the given source method body. /// </summary> public virtual void RewriteChildren(SourceMethodBody sourceMethodBody) { sourceMethodBody.Block = this.Rewrite((BlockStatement)sourceMethodBody.Block); }
/// <summary> /// Creates a new nested type definition with a default constructor and no other members and adds it to this.closureClasses. /// If this.method is generic, then the closure class is generic as well, with the same /// number of type parameters (constrained in the same way) as the generic method. /// Initializes this.currentClosure, this.currentClosureInstance and this.currentClosureSelfInstance. /// </summary> private void CreateClosureClass() { if (this.closureClasses == null) this.closureClasses = new List<ITypeDefinition>(); NestedTypeDefinition closure = new NestedTypeDefinition(); var containingType = this.method.ContainingTypeDefinition; closure.Name = this.host.NameTable.GetNameFor("<"+this.method.Name+">c__DisplayClass"+closure.GetHashCode()); closure.Attributes = new List<ICustomAttribute>(1) { this.compilerGenerated }; closure.BaseClasses = new List<ITypeReference>(1) { this.host.PlatformType.SystemObject }; closure.ContainingTypeDefinition = containingType; closure.Fields = new List<IFieldDefinition>(); closure.InternFactory = this.host.InternFactory; closure.IsBeforeFieldInit = true; closure.IsClass = true; closure.IsSealed = true; closure.Layout = LayoutKind.Auto; closure.Methods = new List<IMethodDefinition>(); closure.StringFormat = StringFormatKind.Ansi; closure.Visibility = TypeMemberVisibility.Private; this.closureClasses.Add(closure); this.currentClosureClass = closure; //generics if (this.method.IsGeneric) { Dictionary<ushort, IGenericParameterReference> genericMethodParameterMap = new Dictionary<ushort, IGenericParameterReference>(); this.genericMethodParameterMap = genericMethodParameterMap; bool foundConstraints = false; var genericTypeParameters = new List<IGenericTypeParameter>(this.method.GenericParameterCount); closure.GenericParameters = genericTypeParameters; foreach (var genericMethodParameter in this.method.GenericParameters) { var copyOfGenericMethodParameter = this.copier.Copy(genericMethodParameter); //so that we have mutable constraints to rewrite var genericTypeParameter = new GenericTypeParameter(); genericTypeParameter.Copy(copyOfGenericMethodParameter, this.host.InternFactory); genericTypeParameter.DefiningType = closure; if (genericTypeParameter.Constraints != null && genericTypeParameter.Constraints.Count > 0) foundConstraints = true; genericTypeParameters.Add(genericTypeParameter); genericMethodParameterMap.Add(copyOfGenericMethodParameter.Index, genericTypeParameter); } if (foundConstraints) { //Fix up any self references that might lurk inside constraints. closure.GenericParameters = new GenericParameterRewriter(this.host, genericMethodParameterMap).Rewrite(genericTypeParameters); } var instanceType = closure.InstanceType; var genericArguments = IteratorHelper.GetConversionEnumerable<IGenericMethodParameter, ITypeReference>(this.method.GenericParameters); this.currentClosureInstance = new Immutable.GenericTypeInstanceReference(instanceType.GenericType, genericArguments, this.host.InternFactory); this.currentClosureSelfInstance = instanceType; } else { //if any of the containing types are generic, we need an instance or a specialized nested type. this.currentClosureInstance = NestedTypeDefinition.SelfInstance(closure, this.host.InternFactory); this.currentClosureSelfInstance = this.currentClosureInstance; } //default constructor var block = new BlockStatement(); block.Statements.Add( new ExpressionStatement() { Expression = new MethodCall() { ThisArgument = new ThisReference() { Type = this.currentClosureSelfInstance }, MethodToCall = this.objectCtor, Type = this.host.PlatformType.SystemVoid } } ); var constructorBody = new SourceMethodBody(this.host, this.sourceLocationProvider) { LocalsAreZeroed = true, IsNormalized = true, Block = block }; var defaultConstructor = new MethodDefinition() { Body = constructorBody, ContainingTypeDefinition = closure, CallingConvention = CallingConvention.HasThis, InternFactory = this.host.InternFactory, IsCil = true, IsHiddenBySignature = true, IsRuntimeSpecial = true, IsSpecialName = true, Name = this.host.NameTable.Ctor, Type = this.host.PlatformType.SystemVoid, Visibility = TypeMemberVisibility.Public, }; constructorBody.MethodDefinition = defaultConstructor; closure.Methods.Add(defaultConstructor); }
private NamespaceTypeDefinition CreateContractReferenceAssemblyAttribute(IRootUnitNamespace rootNs) { var internFactory = this.host.InternFactory; var nameTable = this.host.NameTable; var contractReferenceAssemblyAttributeName = nameTable.GetNameFor("ContractReferenceAssemblyAttribute"); var contractNamespaceName = nameTable.GetNameFor("System.Diagnostics.Contracts"); #region Define type CustomAttribute compilerGeneratedAttribute = new CustomAttribute() { Constructor = new Microsoft.Cci.MethodReference( this.host, this.compilerGeneratedAttributeType, CallingConvention.HasThis, this.systemVoidType, this.host.NameTable.Ctor, 0) }; var contractsNs = new NestedUnitNamespace() { ContainingUnitNamespace = rootNs, Name = contractNamespaceName, }; NamespaceTypeDefinition result = new NamespaceTypeDefinition() { Name = contractReferenceAssemblyAttributeName, Attributes = new List<ICustomAttribute>{ compilerGeneratedAttribute }, BaseClasses = new List<ITypeReference>{ this.systemAttributeType }, ContainingUnitNamespace = contractsNs, //unitNamespace, InternFactory = internFactory, IsBeforeFieldInit = true, IsClass = true, IsSealed = true, Methods = new List<IMethodDefinition>(), Layout = LayoutKind.Auto, StringFormat = StringFormatKind.Ansi, }; contractsNs.Members.Add(result); this.allTypes.Add(result); #endregion Define type #region Define the ctor List<IStatement> statements = new List<IStatement>(); SourceMethodBody body = new SourceMethodBody(this.host) { LocalsAreZeroed = true, Block = new BlockStatement() { Statements = statements }, }; MethodDefinition ctor = new MethodDefinition() { Body = body, CallingConvention = CallingConvention.HasThis, ContainingTypeDefinition = result, InternFactory = internFactory, IsRuntimeSpecial = true, IsStatic = false, IsSpecialName = true, Name = nameTable.Ctor, Type = this.systemVoidType, Visibility = TypeMemberVisibility.Public, }; body.MethodDefinition = ctor; var thisRef = new ThisReference() { Type = result, }; // base(); foreach (var baseClass in result.BaseClasses) { var baseCtor = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = baseClass, GenericParameterCount = 0, InternFactory = this.host.InternFactory, Name = nameTable.Ctor, Type = this.systemVoidType, }; statements.Add( new ExpressionStatement() { Expression = new MethodCall() { MethodToCall = baseCtor, IsStaticCall = false, // REVIEW: Is this needed in addition to setting the ThisArgument? ThisArgument = new ThisReference() { Type = result, }, Type = this.systemVoidType, // REVIEW: Is this the right way to do this? Arguments = new List<IExpression>(), } } ); break; } // return; statements.Add(new ReturnStatement()); result.Methods.Add(ctor); #endregion Define the ctor return result; }
/// <summary> /// Returns a method whose body is empty, but which can be replaced with the real body when it is /// available. /// </summary> /// <remarks> /// Public because it needs to get called when an anonymous delegate is encountered /// while translating a method body. Just mapping the anonymous delegate doesn't /// provide the information needed. The parameters of a method reference are not /// IParameterDefinitions. /// </remarks> public MethodDefinition TranslateMetadata(R.IMethodSymbol methodSymbol) { Contract.Requires(methodSymbol != null); Contract.Ensures(Contract.Result<MethodDefinition>() != null); var containingType = (ITypeDefinition)this.typeSymbolCache[methodSymbol.ContainingType]; var isConstructor = methodSymbol.MethodKind == R.CommonMethodKind.Constructor; List<IParameterDefinition> parameters = new List<IParameterDefinition>(); var m = new MethodDefinition() { CallingConvention = methodSymbol.IsStatic ? CallingConvention.Default : CallingConvention.HasThis, ContainingTypeDefinition = containingType, InternFactory = this.host.InternFactory, IsHiddenBySignature = true, // REVIEW IsNewSlot = containingType.IsInterface, // REVIEW IsRuntimeSpecial = isConstructor, IsSpecialName = isConstructor, IsStatic = methodSymbol.IsStatic, IsVirtual = containingType.IsInterface, // REVIEW: Why doesn't using methodSymbol.Virtual work for interface methods? Locations = Helper.WrapLocations(methodSymbol.Locations), Name = this.nameTable.GetNameFor(methodSymbol.Name), Parameters = parameters, Type = this.Map(methodSymbol.ReturnType), Visibility = this.Map(methodSymbol.DeclaredAccessibility), }; // IMPORTANT: Have to add it to the cache before doing anything else because it may // get looked up if it is generic and a parameter's type involves the generic // method parameter. this.methodSymbolCache.Add(methodSymbol, m); #region Define the generic parameters if (methodSymbol.IsGenericMethod) { var genericParameters = new List<IGenericMethodParameter>(); foreach (var gp in methodSymbol.TypeParameters) { var gp2 = this.CreateTypeDefinition(gp); genericParameters.Add((IGenericMethodParameter) gp2); } m.GenericParameters = genericParameters; } #endregion #region Define the parameters ushort i = 0; foreach (var p in methodSymbol.Parameters) { var p_prime = new ParameterDefinition() { ContainingSignature = m, IsByReference = p.RefKind == RefKind.Ref, IsIn = p.RefKind == RefKind.None, IsOut = p.RefKind == RefKind.Out, Name = nameTable.GetNameFor(p.Name), Type = this.Map(p.Type), Index = i++, }; parameters.Add(p_prime); } #endregion Define the parameters #region Define default ctor, if needed if (/*methodSymbol.IsSynthesized &&*/ isConstructor) { // BUGBUG!! m.IsHiddenBySignature = true; m.IsRuntimeSpecial = true; m.IsSpecialName = true; var statements = new List<IStatement>(); var body = new SourceMethodBody(this.host, null, null) { LocalsAreZeroed = true, Block = new BlockStatement() { Statements = statements }, }; var thisRef = new ThisReference() { Type = containingType, }; // base(); foreach (var baseClass in containingType.BaseClasses) { var baseCtor = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = baseClass, GenericParameterCount = 0, InternFactory = this.host.InternFactory, Name = nameTable.Ctor, Type = this.host.PlatformType.SystemVoid, }; statements.Add( new ExpressionStatement() { Expression = new MethodCall() { MethodToCall = baseCtor, IsStaticCall = false, // REVIEW: Is this needed in addition to setting the ThisArgument? ThisArgument = thisRef, Type = this.host.PlatformType.SystemVoid, // REVIEW: Is this the right way to do this? Arguments = new List<IExpression>(), } } ); break; } // return; statements.Add(new ReturnStatement()); body.MethodDefinition = m; m.Body = body; } #endregion return m; }
/// <summary> /// Override the parent Substitute so that when we see a source method body, we will visit its statements. /// </summary> /// <param name="methodBody"></param> /// <returns></returns> public override IMethodBody Substitute(IMethodBody methodBody) { //^ requires (methodBody is ISourceMethodBody ==> this.cache.ContainsKeymethodBody.MethodDefinition)); ISourceMethodBody sourceMethodBody = methodBody as ISourceMethodBody; if (sourceMethodBody != null) { SourceMethodBody mutableSourceMethodBody = new SourceMethodBody(this.host, this.sourceLocationProvider, null); mutableSourceMethodBody.Block = (IBlockStatement)this.Substitute(sourceMethodBody.Block); mutableSourceMethodBody.MethodDefinition = (IMethodDefinition)this.cache[methodBody.MethodDefinition]; mutableSourceMethodBody.LocalsAreZeroed = methodBody.LocalsAreZeroed; return mutableSourceMethodBody; } return base.Substitute(methodBody); }
/// <summary> /// Create the non-generic version of GetEnumerator and add it to the member list of iterator closure class. /// </summary> private void CreateGetEnumeratorMethodNonGeneric(IteratorClosureInformation iteratorClosure) { // GetEnumerator non-generic version, which delegates to the generic version. // Metadata MethodDefinition nongenericGetEnumerator = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("System.Collections.IEnumerable.GetEnumerator") }; nongenericGetEnumerator.Attributes.Add( new CustomAttribute() { Constructor = this.DebuggerHiddenCtor } ); nongenericGetEnumerator.CallingConvention |= CallingConvention.HasThis; nongenericGetEnumerator.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; nongenericGetEnumerator.Visibility = TypeMemberVisibility.Public; nongenericGetEnumerator.Type = iteratorClosure.NonGenericIEnumeratorInterface; nongenericGetEnumerator.IsVirtual = true; nongenericGetEnumerator.IsNewSlot = true; nongenericGetEnumerator.IsHiddenBySignature = true; nongenericGetEnumerator.IsSealed = true; iteratorClosure.NonGenericGetEnumerator = nongenericGetEnumerator; // Explicitly implements IEnumerable.GetEnumerator(); IMethodReference nongenericGetEnumeratorOriginal = Dummy.MethodReference; foreach (var memref in iteratorClosure.NonGenericIEnumerableInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("GetEnumerator"), false)) { IMethodReference mref = memref as IMethodReference; if (mref != null) { nongenericGetEnumeratorOriginal = mref; break; } } MethodImplementation nonGenericGetEnumeratorImp = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementedMethod = nongenericGetEnumeratorOriginal, ImplementingMethod = nongenericGetEnumerator }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(nonGenericGetEnumeratorImp); // Body: call this.GetEnumerator (the generic version). BlockStatement block1 = new BlockStatement(); block1.Statements.Add(new ReturnStatement() { Expression = new MethodCall() { IsStaticCall = false, MethodToCall = iteratorClosure.GenericGetEnumeratorReference, ThisArgument = new ThisReference(), Type = iteratorClosure.NonGenericIEnumeratorInterface } }); SourceMethodBody body1 = new SourceMethodBody(this.host, this.sourceLocationProvider); body1.IsNormalized = true; body1.LocalsAreZeroed = true; body1.Block = block1; body1.MethodDefinition = nongenericGetEnumerator; nongenericGetEnumerator.Body = body1; }
private IModule CreateNewDll(string assemblyName) { var host = new PeReader.DefaultHost(); var core = host.LoadAssembly(host.CoreAssemblySymbolicIdentity); var assembly = new Assembly(); assembly.Name = host.NameTable.GetNameFor(assemblyName); assembly.ModuleName = host.NameTable.GetNameFor(assemblyName + ".dll"); assembly.Kind = ModuleKind.DynamicallyLinkedLibrary; assembly.PlatformType = host.PlatformType; assembly.TargetRuntimeVersion = core.TargetRuntimeVersion; assembly.AssemblyReferences.Add(core); foreach (var referencePath in model.ReferencePaths) { assembly.AssemblyReferences.Add(host.LoadUnitFrom(referencePath) as IAssembly); } var root = new RootUnitNamespace(); root.Unit = assembly; assembly.UnitNamespaceRoot = root; var module = new NamespaceTypeDefinition(); module.Name = host.NameTable.GetNameFor("<Module>"); module.IsClass = true; module.InternFactory = host.InternFactory; module.ContainingUnitNamespace = root; assembly.AllTypes.Add(module); var rootTypeNamespace = new NestedUnitNamespace(); rootTypeNamespace.Name = host.NameTable.GetNameFor(assembly.Name.Value); root.Members.Add(rootTypeNamespace); foreach (var classConfiguration in model.Classes) { var newClass = new NamespaceTypeDefinition(); newClass.IsAbstract = classConfiguration.IsAbstract; newClass.IsClass = true; newClass.BaseClasses = new List<ITypeReference>{ host.PlatformType.SystemObject }; newClass.IsPublic = true; if (classConfiguration.IsStatic) { newClass.IsStatic = true; newClass.IsAbstract = true; newClass.IsSealed = true; } if (!String.IsNullOrEmpty(classConfiguration.Namespace)) { NestedUnitNamespace classContainer = rootTypeNamespace; var namespaceNames = classConfiguration.Namespace.Split('.'); foreach (var namespaceName in namespaceNames) { var existingMembers = classContainer.GetMembersNamed(host.NameTable.GetNameFor(namespaceName), false); var nestedNamespace = new NestedUnitNamespace(); foreach (var existing in existingMembers) { if (existing as NestedUnitNamespace != null) { nestedNamespace = existing as NestedUnitNamespace; break; } } nestedNamespace.Name = host.NameTable.GetNameFor(namespaceName); nestedNamespace.ContainingUnitNamespace = classContainer; classContainer.Members.Add(nestedNamespace); classContainer = nestedNamespace; } newClass.ContainingUnitNamespace = classContainer; } else { newClass.ContainingUnitNamespace = rootTypeNamespace; } newClass.InternFactory = host.InternFactory; newClass.Name = host.NameTable.GetNameFor(classConfiguration.Name); newClass.Methods = new List<IMethodDefinition>(classConfiguration.Methods.Count); newClass.Fields = new List<IFieldDefinition>(classConfiguration.Fields.Count); foreach (var methodConfiguration in classConfiguration.Methods) { var newMethod = new MethodDefinition(); newMethod.Name = host.NameTable.GetNameFor(methodConfiguration.Name); newMethod.IsStatic = methodConfiguration.IsStatic; newMethod.ContainingTypeDefinition = newClass; newMethod.IsCil = true; newMethod.IsHiddenBySignature = true; newMethod.InternFactory = host.InternFactory; newMethod.Visibility = TypeMemberVisibility.Public; newMethod.Type = host.PlatformType.SystemVoid; var newMethodParameters = new List<IParameterDefinition>(); foreach (var param in methodConfiguration.Parameters) { var newMethodParameter = new ParameterDefinition(); newMethodParameter.ContainingSignature = newMethod; newMethodParameter.Index = (ushort)methodConfiguration.Parameters.IndexOf(param); newMethodParameter.Name = host.NameTable.GetNameFor(param.Key); newMethodParameter.Type = new UnitReflector(host).Get(param.Value); newMethodParameters.Add(newMethodParameter); } newMethod.Parameters = newMethodParameters; var methodBody = new SourceMethodBody(host, null); methodBody.MethodDefinition = newMethod; methodBody.LocalsAreZeroed = true; var block = new BlockStatement(); var returnStatement = new ReturnStatement(); if (methodConfiguration.ReturnType != null) { newMethod.Type = new UnitReflector(host).Get(methodConfiguration.ReturnType); returnStatement.Expression = new CompileTimeConstant(); } if (methodConfiguration.MethodBody != null) { var codeBuilder = new CodeBuilder(host, newMethod.Parameters); methodConfiguration.MethodBody(codeBuilder); foreach (var statement in codeBuilder.Statements) { block.Statements.Add(statement); } } // "Stack must be empty on return from a void method" //returnStatement.Expression = new CompileTimeConstant(); //block.Statements.Add(returnStatement); methodBody.Block = block; newMethod.Body = methodBody; newClass.Methods.Add(newMethod); } foreach (var field in classConfiguration.Fields) { var fieldDefinition = new FieldDefinition(); fieldDefinition.ContainingTypeDefinition = newClass; fieldDefinition.InternFactory = host.InternFactory; fieldDefinition.IsReadOnly = field.IsReadonly; fieldDefinition.IsStatic = field.IsStatic; fieldDefinition.Name = host.NameTable.GetNameFor(field.Name); fieldDefinition.Type = new UnitReflector(host).Get(field.FieldType); fieldDefinition.Visibility = field.Accessibility.ToTypeMemberVisibility(); newClass.Fields.Add(fieldDefinition); } assembly.AllTypes.Add(newClass); } using (var dll = File.Create(assemblyName + ".dll")) { PeWriter.WritePeToStream(assembly, host, dll); dll.Close(); } return assembly; }
/// <summary> /// If the <paramref name="typeDefinition"/> has a type contract, generate a /// contract invariant method and add it to the Methods of the <paramref name="typeDefinition"/>. /// </summary> private void VisitTypeDefinition(ITypeDefinition typeDefinition) { ITypeContract typeContract = this.contractProvider.GetTypeContractFor(typeDefinition); if (typeContract != null) { #region Define the method List<IStatement> statements = new List<IStatement>(); var methodBody = new SourceMethodBody(this.host) { LocalsAreZeroed = true, Block = new BlockStatement() { Statements = statements } }; List<ICustomAttribute> attributes = new List<ICustomAttribute>(); MethodDefinition m = new MethodDefinition() { Attributes = attributes, Body = methodBody, CallingConvention = CallingConvention.HasThis, ContainingTypeDefinition = typeDefinition, InternFactory = this.host.InternFactory, IsStatic = false, Name = this.host.NameTable.GetNameFor("$InvariantMethod$"), Type = systemVoid, Visibility = TypeMemberVisibility.Private, }; methodBody.MethodDefinition = m; #region Add calls to Contract.Invariant foreach (var inv in typeContract.Invariants) { var methodCall = new MethodCall() { Arguments = new List<IExpression> { inv.Condition, }, IsStaticCall = true, MethodToCall = this.contractProvider.ContractMethods.Invariant, Type = systemVoid, Locations = new List<ILocation>(inv.Locations), }; ExpressionStatement es = new ExpressionStatement() { Expression = methodCall }; statements.Add(es); } statements.Add(new ReturnStatement()); #endregion #region Add [ContractInvariantMethod] var contractInvariantMethodType = new Immutable.NamespaceTypeReference( this.host, this.host.PlatformType.SystemDiagnosticsContractsContract.ContainingUnitNamespace, this.host.NameTable.GetNameFor("ContractInvariantMethodAttribute"), 0, false, false, true, PrimitiveTypeCode.NotPrimitive ); var contractInvariantMethodCtor = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = contractInvariantMethodType, GenericParameterCount = 0, InternFactory = this.host.InternFactory, Name = host.NameTable.Ctor, Type = host.PlatformType.SystemVoid, }; var contractInvariantMethodAttribute = new CustomAttribute(); contractInvariantMethodAttribute.Constructor = contractInvariantMethodCtor; attributes.Add(contractInvariantMethodAttribute); #endregion var namedTypeDefinition = (NamedTypeDefinition)typeDefinition; var newMethods = new List<IMethodDefinition>(namedTypeDefinition.Methods == null ? 1 : namedTypeDefinition.Methods.Count() + 1); if (namedTypeDefinition.Methods != null) { foreach (var meth in namedTypeDefinition.Methods) { if (!ContractHelper.IsInvariantMethod(this.host, meth)) newMethods.Add(meth); } } namedTypeDefinition.Methods = newMethods; namedTypeDefinition.Methods.Add(m); #endregion Define the method } }
public override void RewriteChildren(MethodDefinition methodDefinition) { IMethodContract methodContract = this.contractProvider.GetMethodContractFor(methodDefinition); if (methodContract == null) return; ISourceMethodBody sourceMethodBody = methodDefinition.Body as ISourceMethodBody; if (sourceMethodBody == null) return; List<IStatement> contractStatements = new List<IStatement>(); foreach (var precondition in methodContract.Preconditions) { var methodCall = new MethodCall() { Arguments = new List<IExpression> { precondition.Condition, }, IsStaticCall = true, MethodToCall = this.contractProvider.ContractMethods.Requires, Type = systemVoid, Locations = new List<ILocation>(precondition.Locations), }; ExpressionStatement es = new ExpressionStatement() { Expression = methodCall }; contractStatements.Add(es); } foreach (var postcondition in methodContract.Postconditions) { var methodCall = new MethodCall() { Arguments = new List<IExpression> { this.Rewrite(postcondition.Condition), }, IsStaticCall = true, MethodToCall = this.contractProvider.ContractMethods.Ensures, Type = systemVoid, Locations = new List<ILocation>(postcondition.Locations), }; ExpressionStatement es = new ExpressionStatement() { Expression = methodCall }; contractStatements.Add(es); } List<IStatement> existingStatements = new List<IStatement>(sourceMethodBody.Block.Statements); existingStatements = this.Rewrite(existingStatements); // keep the call to the base constructor at the top if (methodDefinition.IsConstructor && existingStatements.Count > 0) { contractStatements.Insert(0, existingStatements[0]); existingStatements.RemoveAt(0); } contractStatements.AddRange(existingStatements); // replaces assert/assume var newSourceMethodBody = new SourceMethodBody(this.host, this.sourceLocationProvider) { Block = new BlockStatement() { Statements = contractStatements, }, IsNormalized = false, LocalsAreZeroed = sourceMethodBody.LocalsAreZeroed, MethodDefinition = methodDefinition, }; methodDefinition.Body = newSourceMethodBody; return; }
private static NamespaceTypeDefinition DefineMethodHashAttributeType(HostEnvironment host, RootUnitNamespace rootUnitNamespace) { Contract.Requires(host != null); var internFactory = host.InternFactory; #region Define the type var methodHashAttributeType = new NamespaceTypeDefinition() { BaseClasses = new List<ITypeReference> { host.PlatformType.SystemAttribute, }, ContainingUnitNamespace = rootUnitNamespace, InternFactory = internFactory, //IsBeforeFieldInit = true, IsClass = true, IsPublic = true, //IsSealed = true, Methods = new List<IMethodDefinition>(1), Name = host.NameTable.GetNameFor("MethodHashAttribute"), //Layout = LayoutKind.Auto, //StringFormat = StringFormatKind.Ansi, }; #endregion #region Define the ctor var systemVoidType = host.PlatformType.SystemVoid; List<IStatement> statements = new List<IStatement>(); SourceMethodBody body = new SourceMethodBody(host) { LocalsAreZeroed = true, Block = new BlockStatement() { Statements = statements }, }; var ctor = new MethodDefinition() { Body = body, CallingConvention = CallingConvention.HasThis, ContainingTypeDefinition = methodHashAttributeType, InternFactory = internFactory, IsRuntimeSpecial = true, IsStatic = false, IsSpecialName = true, Name = host.NameTable.Ctor, Type = systemVoidType, Visibility = TypeMemberVisibility.Public, }; var systemStringType = host.PlatformType.SystemString; var systemIntType = host.PlatformType.SystemInt32; ctor.Parameters = new List<IParameterDefinition>(){ new ParameterDefinition() { ContainingSignature = ctor, Name = host.NameTable.GetNameFor("a"), Type = systemStringType, Index = 0, }, new ParameterDefinition() { ContainingSignature = ctor, Name = host.NameTable.GetNameFor("b"), Type = systemIntType, Index = 1, } }; body.MethodDefinition = ctor; var thisRef = new ThisReference() { Type = methodHashAttributeType, }; // base(); foreach (var baseClass in methodHashAttributeType.BaseClasses) { var baseCtor = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = baseClass, GenericParameterCount = 0, InternFactory = internFactory, Name = host.NameTable.Ctor, Type = systemVoidType, }; statements.Add( new ExpressionStatement() { Expression = new MethodCall() { MethodToCall = baseCtor, IsStaticCall = false, // REVIEW: Is this needed in addition to setting the ThisArgument? ThisArgument = new ThisReference() { Type = methodHashAttributeType, }, Type = systemVoidType, // REVIEW: Is this the right way to do this? Arguments = new List<IExpression>(), } } ); break; } // return; statements.Add(new ReturnStatement()); methodHashAttributeType.Methods.Add(ctor); #endregion Define the ctor return methodHashAttributeType; }
/// <summary> /// Returns a shallow copy of the given source method body. /// </summary> /// <param name="sourceMethodBody"></param> public SourceMethodBody Copy(ISourceMethodBody sourceMethodBody) { Contract.Requires(sourceMethodBody != null); Contract.Ensures(Contract.Result<SourceMethodBody>() != null); var copy = new SourceMethodBody(this.targetHost, this.sourceLocationProvider, this.localScopeProvider); copy.Block = sourceMethodBody.Block; copy.LocalsAreZeroed = sourceMethodBody.LocalsAreZeroed; copy.MethodDefinition = sourceMethodBody.MethodDefinition; return copy; }
/// <summary> /// Create two properties: object Current and T Current as the closure class implements both the /// generic and non-generic version of ienumerator. /// /// Current Implementation generates getters, but not the property. /// </summary> /// <param name="iteratorClosure">Information about the closure created when compiling the current iterator method</param> private void CreateIteratorClosureProperties(IteratorClosureInformation iteratorClosure) { // Non-generic version of the get_Current, which returns the generic version of get_Current. MethodDefinition getterNonGenericCurrent = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("System.Collections.IEnumerator.get_Current") }; CustomAttribute debuggerHiddenAttribute = new CustomAttribute(); debuggerHiddenAttribute.Constructor = this.DebuggerHiddenCtor; getterNonGenericCurrent.Attributes.Add(debuggerHiddenAttribute); getterNonGenericCurrent.CallingConvention |= CallingConvention.HasThis; getterNonGenericCurrent.Visibility |= TypeMemberVisibility.Public; getterNonGenericCurrent.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; getterNonGenericCurrent.Type = this.host.PlatformType.SystemObject; getterNonGenericCurrent.IsSpecialName = true; getterNonGenericCurrent.IsVirtual = true; getterNonGenericCurrent.IsNewSlot = true; getterNonGenericCurrent.IsHiddenBySignature = true; getterNonGenericCurrent.IsSealed = true; iteratorClosure.NonGenericGetCurrent = getterNonGenericCurrent; IMethodReference originalMethod = Dummy.MethodReference; foreach (ITypeMemberReference tref in iteratorClosure.NonGenericIEnumeratorInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("get_Current"), false)) { originalMethod = tref as IMethodReference; if (originalMethod != null) break; } // assert originalMethod != Dummy MethodImplementation getterImplementation = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementingMethod = getterNonGenericCurrent, ImplementedMethod = originalMethod }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(getterImplementation); List<IStatement> statements = new List<IStatement>(); IFieldReference currentField = iteratorClosure.CurrentFieldReference; BoundExpression thisDotCurr = new BoundExpression() { Definition = currentField, Instance = new ThisReference(), Locations = iteratorClosure.ClosureDefinition.Locations, Type = currentField.Type }; IExpression returnExpression; if (!iteratorClosure.ElementType.IsValueType && TypeHelper.TypesAreAssignmentCompatible(iteratorClosure.ElementType.ResolvedType, this.host.PlatformType.SystemObject.ResolvedType)) { returnExpression = thisDotCurr; } else { Conversion convertion = new Conversion() { CheckNumericRange = false, Type = this.host.PlatformType.SystemObject, TypeAfterConversion = getterNonGenericCurrent.Type, ValueToConvert = thisDotCurr }; returnExpression = convertion; } ReturnStatement returnCurrent = new ReturnStatement() { Expression = returnExpression, Locations = iteratorClosure.ClosureDefinition.Locations }; statements.Add(returnCurrent); BlockStatement block = new BlockStatement() { Statements = statements }; SourceMethodBody body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.IsNormalized = true; body.LocalsAreZeroed = true; body.Block = block; body.MethodDefinition = getterNonGenericCurrent; getterNonGenericCurrent.Body = body; // Create generic version of get_Current, the body of which is simply returning this.current. MethodDefinition getterGenericCurrent = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("System.Collections.Generic.IEnumerator<" + iteratorClosure.ElementType.ToString() +">.get_Current") }; getterGenericCurrent.Attributes.Add(debuggerHiddenAttribute); getterGenericCurrent.CallingConvention |= CallingConvention.HasThis; getterGenericCurrent.Visibility |= TypeMemberVisibility.Public; getterGenericCurrent.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; getterGenericCurrent.Type = iteratorClosure.ElementType; getterGenericCurrent.IsSpecialName = true; getterGenericCurrent.IsVirtual = true; getterGenericCurrent.IsNewSlot = true; getterGenericCurrent.IsHiddenBySignature = true; getterGenericCurrent.IsSealed = true; iteratorClosure.GenericGetCurrent = getterGenericCurrent; originalMethod = Dummy.MethodReference; foreach (ITypeMemberReference tref in iteratorClosure.GenericIEnumeratorInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("get_Current"), false)) { originalMethod = tref as IMethodReference; if (originalMethod != null) break; } MethodImplementation getterImplementation2 = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementingMethod = getterGenericCurrent, ImplementedMethod = originalMethod }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(getterImplementation2); statements = new List<IStatement>(); currentField = iteratorClosure.CurrentFieldReference; BoundExpression thisDotCurrent = new BoundExpression() { Definition = currentField, Instance = new ThisReference(), Locations = iteratorClosure.ClosureDefinition.Locations, Type = currentField.Type }; returnCurrent = new ReturnStatement() { Expression = thisDotCurrent, Locations = iteratorClosure.ClosureDefinition.Locations }; statements.Add(returnCurrent); block = new BlockStatement() { Statements = statements }; body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.LocalsAreZeroed = true; body.Block = block; body.MethodDefinition = getterGenericCurrent; getterGenericCurrent.Body = body; }
/// <summary> /// Returns a shallow copy of the given source method body. /// </summary> /// <param name="sourceMethodBody"></param> public SourceMethodBody Copy(ISourceMethodBody sourceMethodBody) { var copy = new SourceMethodBody(this.targetHost, this.sourceLocationProvider); copy.Block = sourceMethodBody.Block; copy.LocalsAreZeroed = sourceMethodBody.LocalsAreZeroed; copy.MethodDefinition = sourceMethodBody.MethodDefinition; return copy; }
/// <summary> /// Create the constuctor of the iterator class. The pseudo-code is: /// /// Ctor(int state) { /// object.Ctor(); /// this.state = state; /// this.threadid = Thread.CurrentThread.ManagedThreadId; /// } /// </summary> private void CreateIteratorClosureConstructor(IteratorClosureInformation iteratorClosure) { MethodDefinition constructor = new MethodDefinition() { InternFactory = this.host.InternFactory, Parameters = new List<IParameterDefinition>(1), }; // Parameter ParameterDefinition stateParameter = new ParameterDefinition() { ContainingSignature = constructor, Index = 0, Name = this.host.NameTable.GetNameFor("state"), Type = this.host.PlatformType.SystemInt32 }; constructor.Parameters.Add(stateParameter); // Statements MethodCall baseConstructorCall = new MethodCall() { ThisArgument = new ThisReference(), MethodToCall = this.ObjectCtor, Type = this.host.PlatformType.SystemVoid }; ExpressionStatement baseConstructorCallStatement = new ExpressionStatement() { Expression = baseConstructorCall }; List<IStatement> statements = new List<IStatement>(); ExpressionStatement thisDotStateEqState = new ExpressionStatement() { Expression = new Assignment() { Source = new BoundExpression() { Definition = stateParameter, Instance = null, Type = this.host.PlatformType.SystemInt32 }, Target = new TargetExpression() { Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32, Definition = iteratorClosure.StateFieldReference }, Type = this.host.PlatformType.SystemInt32 } }; ExpressionStatement thisThreadIdEqCurrentThreadId = new ExpressionStatement() { Expression = new Assignment() { Source = new MethodCall() { MethodToCall = this.ThreadDotManagedThreadId.Getter, ThisArgument = this.ThreadDotCurrentThread, Type = this.host.PlatformType.SystemInt32 }, Target = new TargetExpression() { Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32, Definition = iteratorClosure.InitThreadIdFieldReference }, Type = this.host.PlatformType.SystemInt32 } }; statements.Add(baseConstructorCallStatement); statements.Add(thisDotStateEqState); statements.Add(thisThreadIdEqCurrentThreadId); BlockStatement block = new BlockStatement() { Statements = statements }; SourceMethodBody body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.LocalsAreZeroed = true; body.IsNormalized = true; body.Block = block; constructor.Body = body; body.MethodDefinition = constructor; // Metadata of the constructor constructor.CallingConvention = CallingConvention.HasThis; constructor.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; constructor.IsCil = true; constructor.IsHiddenBySignature = true; constructor.IsRuntimeSpecial = true; constructor.IsSpecialName = true; constructor.Name = this.host.NameTable.Ctor; constructor.Type = this.host.PlatformType.SystemVoid; constructor.Visibility = TypeMemberVisibility.Public; iteratorClosure.Constructor = constructor; }
/// <summary> /// Records all of the helper types of the method body into this.helperTypes. /// </summary> /// <param name="methodBody"></param> public override void TraverseChildren(IMethodBody methodBody) { var mutableBody = (SourceMethodBody)methodBody; var block = mutableBody.Block; //force decompilation bool denormalize = false; if (mutableBody.privateHelperTypesToRemove != null) { denormalize = true; foreach (var helperType in mutableBody.privateHelperTypesToRemove) this.helperTypes[helperType.InternedKey] = helperType; } if (mutableBody.privateHelperMethodsToRemove != null) { denormalize = true; foreach (var helperMethod in mutableBody.privateHelperMethodsToRemove.Values) this.helperMethods[helperMethod.InternedKey] = helperMethod; } if (mutableBody.privateHelperFieldsToRemove != null) { denormalize = true; foreach (var helperField in mutableBody.privateHelperFieldsToRemove.Values) this.helperFields[helperField] = helperField; } if (denormalize) { var mutableMethod = (MethodDefinition)mutableBody.MethodDefinition; var denormalizedBody = new Microsoft.Cci.MutableCodeModel.SourceMethodBody(this.host, this.sourceLocationProvider); denormalizedBody.LocalsAreZeroed = mutableBody.LocalsAreZeroed; denormalizedBody.IsNormalized = false; denormalizedBody.Block = block; denormalizedBody.MethodDefinition = mutableMethod; mutableMethod.Body = denormalizedBody; } }
/// <summary> /// Create the MoveNext method. This method sets up metadata and calls TranslateIteratorMethodBodyToMoveNextBody /// to compile the body. /// </summary> private void CreateMoveNextMethod(IteratorClosureInformation /*!*/ iteratorClosure, BlockStatement blockStatement) { // Method definition and metadata. MethodDefinition moveNext = new MethodDefinition() { InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("MoveNext") }; moveNext.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; moveNext.Visibility = TypeMemberVisibility.Private; moveNext.CallingConvention |= CallingConvention.HasThis; moveNext.Type = this.host.PlatformType.SystemBoolean; moveNext.InternFactory = this.host.InternFactory; moveNext.IsSealed = true; moveNext.IsVirtual = true; moveNext.IsHiddenBySignature = true; moveNext.IsNewSlot = true; iteratorClosure.MoveNext = moveNext; IMethodReference moveNextOriginal = Dummy.MethodReference; foreach (ITypeMemberReference tmref in iteratorClosure.NonGenericIEnumeratorInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("MoveNext"), false)) { moveNextOriginal = tmref as IMethodReference; if (moveNextOriginal != null) break; } // Explicit method implementation MethodImplementation moveNextImp = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementingMethod = moveNext, ImplementedMethod = moveNextOriginal }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(moveNextImp); SourceMethodBody body = new SourceMethodBody(this.host, this.sourceLocationProvider, null, this.iteratorLocalCount); IBlockStatement block = TranslateIteratorMethodBodyToMoveNextBody(iteratorClosure, blockStatement); moveNext.Body = body; body.IsNormalized = true; body.LocalsAreZeroed = true; body.Block = block; body.MethodDefinition = moveNext; }
private SourceMethodBody GetBody(IMethodDefinition method, IMethodReference originalCall) { var body = new SourceMethodBody(host, null, null); body.MethodDefinition = method; body.LocalsAreZeroed = true; var block = new BlockStatement(); body.Block = block; AddAlternativeInvocation(block, method, originalCall); return body; }
/// <summary> /// Create the Reset method. Like in CSC, this method contains nothing. /// </summary> private void CreateResetMethod(IteratorClosureInformation iteratorClosure) { // System.Collections.IEnumerator.Reset: Simply throws an exception MethodDefinition reset = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("Reset") }; CustomAttribute debuggerHiddenAttribute = new CustomAttribute() { Constructor = this.DebuggerHiddenCtor }; reset.Attributes.Add(debuggerHiddenAttribute); reset.CallingConvention |= CallingConvention.HasThis; reset.Visibility = TypeMemberVisibility.Private; reset.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; reset.Type = this.host.PlatformType.SystemVoid; reset.IsVirtual = true; reset.IsNewSlot = true; reset.IsHiddenBySignature = true; reset.IsSealed = true; iteratorClosure.Reset = reset; // explicitly state that this reset method implements IEnumerator's reset method. IMethodReference resetImplemented = Dummy.MethodReference; foreach (var memref in iteratorClosure.NonGenericIEnumeratorInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("Reset"), false)) { IMethodReference mref = memref as IMethodReference; if (mref != null) { resetImplemented = mref; break; } } MethodImplementation resetImp = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementedMethod = resetImplemented, ImplementingMethod = reset }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(resetImp); List<IStatement> statements = new List<IStatement>(); ReturnStatement returnCurrent = new ReturnStatement() { Expression = null, Locations = iteratorClosure.ClosureDefinition.Locations }; statements.Add(returnCurrent); BlockStatement block = new BlockStatement() { Statements = statements }; SourceMethodBody body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.LocalsAreZeroed = true; body.IsNormalized = true; body.Block = block; body.MethodDefinition = reset; reset.Body = body; }
/// <summary> /// Returns a reference to the closure method. If the method is generic, the reference is to an instantiation, /// using the generic parameters of the current class as arguments. /// </summary> private IMethodReference CreateClosureMethod(AnonymousDelegate anonymousDelegate) { bool isPeerMethod = this.helperMembers != null && !this.anonymousDelegatesThatCaptureLocalsOrParameters.ContainsKey(anonymousDelegate); bool isStaticMethod = isPeerMethod && !this.anonymousDelegatesThatCaptureThis.ContainsKey(anonymousDelegate); var body = new SourceMethodBody(this.host, this.sourceLocationProvider) { Block = anonymousDelegate.Body, LocalsAreZeroed = true }; var counter = isPeerMethod ? this.helperMembers.Count : this.anonymousDelegateCounter++; var prefix = "<"+this.method.Name.Value; prefix += isPeerMethod ? ">p__" : ">b__"; var method = new MethodDefinition() { ContainingTypeDefinition = isPeerMethod ? this.method.ContainingTypeDefinition : this.currentClosureClass, Name = this.host.NameTable.GetNameFor(prefix+counter), Visibility = isPeerMethod ? TypeMemberVisibility.Private : TypeMemberVisibility.Public, Body = body, CallingConvention = isStaticMethod ? CallingConvention.Default : CallingConvention.HasThis, InternFactory = this.host.InternFactory, Parameters = anonymousDelegate.Parameters, Type = anonymousDelegate.ReturnType, IsCil = true, IsStatic = isStaticMethod, IsHiddenBySignature = true, }; body.MethodDefinition = method; if (method.Parameters != null) { foreach (ParameterDefinition parameterDefinition in method.Parameters) parameterDefinition.ContainingSignature = method; } if (isPeerMethod) { this.helperMembers.Add(method); if (this.method.IsGeneric) this.MakeDelegateMethodGeneric(method); method.Attributes = new List<ICustomAttribute>(1); method.Attributes.Add(this.compilerGenerated); } else { this.currentClosureClass.Methods.Add(method); this.isInsideAnonymousMethod = true; this.RewriteChildren(method); this.isInsideAnonymousMethod = false; } IMethodReference methodReference = method; ITypeReference containingTypeDefinitionInstance = method.ContainingTypeDefinition; if (isPeerMethod) containingTypeDefinitionInstance = NamedTypeDefinition.SelfInstance((INamedTypeDefinition)method.ContainingTypeDefinition, this.host.InternFactory); if ((isPeerMethod && method.ContainingTypeDefinition != containingTypeDefinitionInstance) || (!isPeerMethod && this.currentClosureClass != this.currentClosureInstance)) { methodReference = new MethodReference() { CallingConvention = method.CallingConvention, ContainingType = isPeerMethod ? containingTypeDefinitionInstance : this.currentClosureInstance, GenericParameterCount = method.GenericParameterCount, InternFactory = this.host.InternFactory, Name = method.Name, Parameters = methodReference.ParameterCount == 0 ? null : new List<IParameterTypeInformation>(methodReference.Parameters), Type = method.Type, }; } if (!method.IsGeneric) return methodReference; return new GenericMethodInstanceReference() { CallingConvention = method.CallingConvention, ContainingType = method.ContainingTypeDefinition, GenericArguments = new List<ITypeReference>(IteratorHelper.GetConversionEnumerable<IGenericMethodParameter, ITypeReference>(method.GenericParameters)), GenericMethod = methodReference, InternFactory = this.host.InternFactory, Name = method.Name, Parameters = methodReference.ParameterCount == 0 ? null : new List<IParameterTypeInformation>(methodReference.Parameters), Type = method.Type, }; }
/// <summary> /// Visits the specified method body. /// </summary> /// <param name="methodBody">The method body.</param> public override IMethodBody Visit(IMethodBody methodBody) { ISourceMethodBody sourceMethodBody = methodBody as ISourceMethodBody; if (sourceMethodBody != null) { SourceMethodBody mutableSourceMethodBody = null; if (this.copyOnlyIfNotAlreadyMutable) mutableSourceMethodBody = sourceMethodBody as SourceMethodBody; if (mutableSourceMethodBody == null) mutableSourceMethodBody = new SourceMethodBody(this.host, this.sourceLocationProvider, null); mutableSourceMethodBody.Block = this.Visit(sourceMethodBody.Block); mutableSourceMethodBody.LocalsAreZeroed = methodBody.LocalsAreZeroed; mutableSourceMethodBody.MethodDefinition = this.GetCurrentMethod(); return mutableSourceMethodBody; } return base.Visit(methodBody); }