public override Method VisitMethod(Method method) { if (method == null) return null; Method dup = (Method)this.DuplicateFor[method.UniqueKey]; if (dup != null) return dup; this.DuplicateFor[method.UniqueKey] = dup = (Method)method.Clone(); dup.ProviderHandle = null; if (TargetPlatform.UseGenerics) { this.FindTypesToBeDuplicated(method.TemplateParameters); } dup.LocalList = null; Method savedTarget = this.TargetMethod; this.TargetMethod = dup; if (TargetPlatform.UseGenerics) { dup.TemplateParameters = this.VisitTypeParameterList(method.TemplateParameters); } if (dup.Scope != null) { this.TypesToBeDuplicated[dup.Scope.UniqueKey] = dup.Scope; dup.Scope = this.VisitTypeNode(dup.Scope) as MethodScope; } dup.DeclaringMember = this.VisitMemberReference(dup.DeclaringMember); if (this.CopyDocumentation) dup.Documentation = method.Documentation; dup.ImplementedInterfaceMethods = this.VisitMethodReferenceList(method.ImplementedInterfaceMethods); dup.DeclaringType = this.TargetType; if (!method.IsAbstract) dup.Body = this.DummyBody; if (this.RecordOriginalAsTemplate) { if (method.Template != null) dup.Template = method.Template; else dup.Template = method; } dup.PInvokeModule = this.VisitModuleReference(dup.PInvokeModule); if (method.ReturnTypeMarshallingInformation != null) dup.ReturnTypeMarshallingInformation = method.ReturnTypeMarshallingInformation.Clone(); dup.ThisParameter = (This)this.VisitParameter(dup.ThisParameter); dup = base.VisitMethod(dup); //^ assume dup != null; dup.fullName = null; dup.DocumentationId = null; dup.ProviderHandle = method; // we always need the handle, as we may use it for attributes. dup.Attributes = null; dup.ProvideMethodAttributes = new Method.MethodAttributeProvider(this.ProvideMethodAttributes); if (!this.SkipBodies && !method.IsAbstract) { dup.Body = null; dup.ProvideBody = new Method.MethodBodyProvider(this.ProvideMethodBody); } if(this.SkipBodies) dup.Instructions = new InstructionList(); this.TargetMethod = savedTarget; return dup; }
/// <summary> /// Flattens the code of the method <c>method</c>. Leaves the CCI representation of <c>method</c> intact. /// /// Returns a mutated copy. /// /// Important! don't forget to adjust handler block boundaries as well /// </summary> /// <param name="expandAllocations">When true, then Construct expressions are expanded into a separate allocation and separate /// constructor call.</param> /// <param name="constantFoldEvenInContracts">When <c>true</c>, use constant folding /// to prune infeasible branches.</param> public static Method MakeFlat(Method method, bool expandAllocations, bool constantFold, out CodeMap codeMap) { /* Console.Out.WriteLine("+++++++++++++++++++++++++++"); CodePrinter.PrintMethod(Console.Out, method); */ #region Compensate for a bug involving re-initializing a method body { // We're going to muck with the method's Body. But then at one point the ExceptionHandlers // are evaluated and since that is null, it causes the Body to be re-initialized from the IL. // So just force some evaluations which fill in the backing stores to an empty list // (at least) instead of "null". // Do this for Body, Instructions, and ExceptionHandlers (the three things that cause // the ProvideBody delegate to execute). Block dummyBody = method.Body; InstructionList dummyInstructions = method.Instructions; ExceptionHandlerList dummyExceptions = method.ExceptionHandlers; } #endregion Compensate for a bug involving re-initializing a method body method = (Method)method.Clone(); Block body = method.Body; if ((method == null) || (body == null)) { codeMap = null; return method; } // Add test case by inserting BlockExpressions and nested blocks // body = new FlattenerTest().VisitBlock(body); if(body.Statements == null) { codeMap = null; return method; } body = (Block)body.Clone(); method.Body = body; CodeFlattener flatener = new CodeFlattener(method, expandAllocations, constantFold); flatener.FlattenBlock(body); flatener.AdjustBranches(); flatener.AdjustHandlers(method); // now store the bodyList in the method body block body.Statements = flatener.new_blocks; /* Console.Out.WriteLine("---------------------------"); CodePrinter.PrintMethod(Console.Out, method); Console.Out.WriteLine(); */ /* Console.WriteLine("----CodeFlattener on {0}", method.FullName); Console.WriteLine("orig blocks: {0}", flatener.orig2newBlocks.Count); Console.WriteLine("branches: {0}", flatener.branchInstructions.Length); */ codeMap = new CodeMap(flatener.orig2Copy); return method; }