5 // Alexander Chebaturkin (chebaturkin@gmail.com)
7 // Copyright (C) 2011 Alexander Chebaturkin
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections.Generic;
33 using Mono.CodeContracts.Static.AST;
34 using Mono.CodeContracts.Static.Analysis;
35 using Mono.CodeContracts.Static.ControlFlow.Blocks;
36 using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
37 using Mono.CodeContracts.Static.DataStructures;
38 using Mono.CodeContracts.Static.Providers;
40 namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
41 abstract class SubroutineBase<Label> : Subroutine, IGraph<CFGBlock, Dummy>, IStackInfo, IEdgeSubroutineAdaptor {
42 private const int UnusedBlockIndex = Int32.MaxValue - 1;
43 protected readonly Label StartLabel;
44 public readonly SubroutineFacade SubroutineFacade;
46 private readonly Dictionary<Pair<CFGBlock, CFGBlock>, LispList<Pair<EdgeTag, Subroutine>>> edge_subroutines
47 = new Dictionary<Pair<CFGBlock, CFGBlock>, LispList<Pair<EdgeTag, Subroutine>>> ();
49 private readonly BlockWithLabels<Label> entry;
50 private readonly BlockWithLabels<Label> entry_after_requires;
51 private readonly BlockWithLabels<Label> exception_exit;
52 private readonly BlockWithLabels<Label> exit;
54 private readonly List<Edge<CFGBlock, EdgeTag>> successors = new List<Edge<CFGBlock, EdgeTag>> ();
55 protected int BlockIdGenerator;
56 protected Dictionary<Label, BlockWithLabels<Label>> LabelsThatStartBlocks = new Dictionary<Label, BlockWithLabels<Label>> ();
58 private CFGBlock[] blocks;
59 private DepthFirst.Visitor<CFGBlock, Dummy> edge_info;
60 private EdgeMap<EdgeTag> predecessor_edges;
61 private EdgeMap<EdgeTag> successor_edges;
63 protected SubroutineBase (SubroutineFacade subroutineFacade)
65 this.SubroutineFacade = subroutineFacade;
66 this.entry = new EntryBlock<Label> (this, ref this.BlockIdGenerator);
67 this.exit = new EntryExitBlock<Label> (this, ref this.BlockIdGenerator);
68 this.exception_exit = new CatchFilterEntryBlock<Label> (this, ref this.BlockIdGenerator);
71 protected SubroutineBase (SubroutineFacade SubroutineFacade,
72 Label startLabel, SubroutineBuilder<Label> builder)
73 : this (SubroutineFacade)
75 this.StartLabel = startLabel;
77 CodeProvider = builder.CodeProvider;
78 this.entry_after_requires = GetTargetBlock (startLabel);
80 AddSuccessor (this.entry, EdgeTag.Entry, this.entry_after_requires);
83 public override bool HasContextDependentStackDepth
88 public override bool HasReturnValue
93 public override int StackDelta
98 protected SubroutineBuilder<Label> Builder { get; set; }
100 public override DepthFirst.Visitor<CFGBlock, Dummy> EdgeInfo
102 get { return this.edge_info; }
105 public ICodeProvider<Label> CodeProvider { get; private set; }
107 public override int BlockCount
109 get { return this.blocks.Length; }
112 public override IEnumerable<CFGBlock> Blocks
114 get { return this.blocks; }
117 public override string Name
119 get { return "SR" + Id; }
122 public override EdgeMap<EdgeTag> SuccessorEdges
124 get { return this.successor_edges; }
127 public override EdgeMap<EdgeTag> PredecessorEdges
131 if (this.predecessor_edges == null)
132 this.predecessor_edges = this.successor_edges.Reverse ();
133 return this.predecessor_edges;
138 public override CFGBlock Entry
140 get { return this.entry; }
143 public override CFGBlock EntryAfterRequires
147 if (this.entry_after_requires != null)
148 return this.entry_after_requires;
153 public override CFGBlock Exit
155 get { return this.exit; }
158 public override CFGBlock ExceptionExit
160 get { return this.exception_exit; }
164 #region IEdgeSubroutineAdaptor Members
165 public LispList<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutinesInternal (CFGBlock from, CFGBlock to, LispList<Edge<CFGBlock, EdgeTag>> context)
167 LispList<Pair<EdgeTag, Subroutine>> list;
168 this.edge_subroutines.TryGetValue (new Pair<CFGBlock, CFGBlock> (from, to), out list);
169 if (list != null && context != null)
170 list = list.Where (FilterRecursiveContracts (to, context));
175 #region IGraph<CFGBlock,Dummy> Members
176 public IEnumerable<CFGBlock> Nodes
178 get { return this.blocks; }
181 public virtual IEnumerable<Pair<Dummy, CFGBlock>> Successors (CFGBlock node)
183 foreach (var pair in this.successor_edges [node])
184 yield return new Pair<Dummy, CFGBlock> (Dummy.Value, pair.Value);
186 if (node != this.exception_exit)
187 yield return new Pair<Dummy, CFGBlock> (Dummy.Value, this.exception_exit);
191 #region IStackInfo Members
192 bool IStackInfo.IsCallOnThis (APC apc)
198 public override IEnumerable<CFGBlock> SuccessorBlocks (CFGBlock block)
200 return SuccessorEdges [block].Select (it => it.Value);
203 public override bool HasSingleSuccessor (APC point, out APC ifFound)
205 if (point.Index < point.Block.Count) {
206 ifFound = new APC (point.Block, point.Index + 1, point.SubroutineContext);
210 if (IsSubroutineEnd (point.Block)) {
211 if (point.SubroutineContext == null) {
216 ifFound = ComputeSubroutineContinuation (point);
220 BlockWithLabels<Label> onlyOne = null;
221 foreach (BlockWithLabels<Label> successor in point.Block.Subroutine.SuccessorBlocks (point.Block)) {
230 if (onlyOne != null) {
231 ifFound = ComputeTargetFinallyContext (point, onlyOne);
239 public override bool HasSinglePredecessor (APC point, out APC ifFound)
241 if (point.Index > 0) {
242 ifFound = new APC (point.Block, point.Index - 1, point.SubroutineContext);
246 if (IsSubroutineStart (point.Block)) {
247 if (point.SubroutineContext == null) {
252 bool hasSinglePredecessor;
253 ifFound = ComputeSubroutinePreContinuation (point, out hasSinglePredecessor);
254 return hasSinglePredecessor;
258 CFGBlock onlyOne = null;
259 foreach (CFGBlock predecessor in point.Block.Subroutine.PredecessorBlocks (point.Block)) {
260 if (onlyOne != null) {
264 onlyOne = predecessor;
266 if (onlyOne == null) {
271 LispList<Pair<EdgeTag, Subroutine>> list = EdgeSubroutinesOuterToInner (onlyOne, point.Block, point.SubroutineContext);
272 if (list.IsEmpty ()) {
273 ifFound = APC.ForEnd (onlyOne, point.SubroutineContext);
277 var edge = new Edge<CFGBlock, EdgeTag> (onlyOne, point.Block, list.Head.Key);
278 Subroutine sub = list.Head.Value;
279 ifFound = APC.ForEnd (sub.Exit, point.SubroutineContext.Cons (edge));
283 private APC ComputeSubroutinePreContinuation (APC point, out bool hasSinglePredecessor)
285 Edge<CFGBlock, EdgeTag> head = point.SubroutineContext.Head;
286 bool isExceptionHandlerEdge;
287 LispList<Edge<CFGBlock, EdgeTag>> tail = point.SubroutineContext.Tail;
288 LispList<Pair<EdgeTag, Subroutine>> flist = EdgeSubroutinesOuterToInner (head.From, head.To, out isExceptionHandlerEdge, tail);
289 while (flist.Head.Value != this)
291 if (flist.Tail.IsEmpty ()) {
292 if (isExceptionHandlerEdge && head.From.Count > 1) {
293 hasSinglePredecessor = false;
297 hasSinglePredecessor = true;
298 return APC.ForEnd (head.From, tail);
300 Pair<EdgeTag, Subroutine> first = flist.Tail.Head;
301 Subroutine sub = first.Value;
302 hasSinglePredecessor = true;
304 return APC.ForEnd (sub.Exit, point.SubroutineContext.Cons (new Edge<CFGBlock, EdgeTag> (head.From, head.To, first.Key)));
307 private APC ComputeSubroutineContinuation (APC point)
309 Edge<CFGBlock, EdgeTag> head = point.SubroutineContext.Head;
310 LispList<Edge<CFGBlock, EdgeTag>> tail = point.SubroutineContext.Tail;
311 LispList<Pair<EdgeTag, Subroutine>> outerToInner = EdgeSubroutinesOuterToInner (head.From, head.To, tail);
312 if (outerToInner.Head.Value == this)
313 return new APC (head.To, 0, tail);
315 while (outerToInner.Tail.Head.Value != this)
316 outerToInner = outerToInner.Tail;
318 return new APC (outerToInner.Head.Value.Entry, 0, tail.Cons (new Edge<CFGBlock, EdgeTag> (head.From, head.To, outerToInner.Head.Key)));
321 public override IEnumerable<CFGBlock> PredecessorBlocks (CFGBlock block)
323 return PredecessorEdges [block].Select (it => it.Value);
326 public override bool IsJoinPoint (CFGBlock block)
328 if (IsCatchFilterHeader (block) || IsSubroutineStart (block) || IsSubroutineEnd (block))
331 return PredecessorEdges [block].Count > 1;
334 public override bool IsSubroutineEnd (CFGBlock block)
336 return block == this.exit || block == this.exception_exit;
339 public override bool IsSubroutineStart (CFGBlock block)
341 return block == this.entry;
344 public override bool IsSplitPoint (CFGBlock block)
346 if (IsSubroutineStart (block) || IsSubroutineEnd (block))
349 return SuccessorEdges [block].Count > 1;
352 public override bool IsCatchFilterHeader (CFGBlock block)
354 return block is CatchFilterEntryBlock<Label>;
357 public void AddSuccessor (CFGBlock from, EdgeTag tag, CFGBlock to)
359 AddNormalControlFlowEdge (this.successors, from, tag, to);
362 private void AddNormalControlFlowEdge (List<Edge<CFGBlock, EdgeTag>> succs, CFGBlock from, EdgeTag tag, CFGBlock to)
364 succs.Add (new Edge<CFGBlock, EdgeTag> (from, to, tag));
367 public virtual void AddReturnBlock (BlockWithLabels<Label> block)
371 public BlockWithLabels<Label> GetTargetBlock (Label label)
373 return GetBlock (label);
376 public BlockWithLabels<Label> GetBlock (Label label)
378 IMetaDataProvider metadataDecoder = this.SubroutineFacade.MetaDataProvider;
380 BlockWithLabels<Label> block;
381 if (!this.LabelsThatStartBlocks.TryGetValue (label, out block)) {
382 Pair<Method, bool> methodVirtualPair;
386 throw new InvalidOperationException ("Builder must be not null");
388 if (Builder.IsMethodCallSite (label, out methodVirtualPair)) {
389 int parametersCount = metadataDecoder.Parameters (methodVirtualPair.Key).Count;
390 block = new MethodCallBlock<Label> (methodVirtualPair.Key, this, ref this.BlockIdGenerator, parametersCount, methodVirtualPair.Value);
391 } else if (Builder.IsNewObjSite (label, out constructor)) {
392 int parametersCount = metadataDecoder.Parameters (constructor).Count;
393 block = new NewObjCallBlock<Label> (constructor, parametersCount, this, ref this.BlockIdGenerator);
397 if (Builder.IsTargetLabel (label))
398 this.LabelsThatStartBlocks.Add (label, block);
403 public virtual BlockWithLabels<Label> NewBlock ()
405 return new BlockWithLabels<Label> (this, ref this.BlockIdGenerator);
408 public AssumeBlock<Label> NewAssumeBlock (Label pc, EdgeTag tag)
410 return new AssumeBlock<Label> (this, pc, tag, ref this.BlockIdGenerator);
413 public override sealed void AddEdgeSubroutine (CFGBlock from, CFGBlock to, Subroutine subroutine, EdgeTag tag)
415 if (subroutine == null)
418 var key = new Pair<CFGBlock, CFGBlock> (from, to);
419 LispList<Pair<EdgeTag, Subroutine>> list;
420 var item = new Pair<EdgeTag, Subroutine> (tag, subroutine);
422 this.edge_subroutines.TryGetValue (key, out list);
423 this.edge_subroutines [key] = list.Cons (item);
426 public override IEnumerable<APC> Successors (APC pc)
429 if (HasSingleSuccessor (pc, out singleNext))
430 yield return singleNext;
432 foreach (CFGBlock block in pc.Block.Subroutine.SuccessorBlocks (pc.Block))
433 yield return pc.Block.Subroutine.ComputeTargetFinallyContext (pc, block);
437 public override IEnumerable<APC> Predecessors (APC pc)
440 yield return new APC (pc.Block, pc.Index - 1, pc.SubroutineContext);
442 else if (IsSubroutineStart (pc.Block)) {
443 if (!pc.SubroutineContext.IsEmpty ()) {
444 foreach (APC apc in ComputeSubroutinePreContinuation (pc))
448 foreach (CFGBlock block in pc.Block.Subroutine.PredecessorBlocks (pc.Block)) {
449 LispList<Pair<EdgeTag, Subroutine>> diffs = EdgeSubroutinesOuterToInner (block, pc.Block, pc.SubroutineContext);
450 if (diffs.IsEmpty ())
451 yield return APC.ForEnd (block, pc.SubroutineContext);
453 Subroutine sub = diffs.Head.Value;
454 var edge = new Edge<CFGBlock, EdgeTag> (block, pc.Block, diffs.Head.Key);
455 yield return APC.ForEnd (sub.Exit, pc.SubroutineContext.Cons (edge));
461 private IEnumerable<APC> ComputeSubroutinePreContinuation (APC point)
463 Edge<CFGBlock, EdgeTag> edge = point.SubroutineContext.Head;
464 LispList<Edge<CFGBlock, EdgeTag>> tail = point.SubroutineContext.Tail;
467 LispList<Pair<EdgeTag, Subroutine>> diffs = EdgeSubroutinesOuterToInner (edge.From, edge.To, out isHandlerEdge, tail);
468 while (diffs.Head.Value != this)
471 if (diffs.Tail == null) {
473 for (int i = 0; i < edge.From.Count; i++)
474 yield return new APC (edge.From, i, tail);
476 yield return APC.ForEnd (edge.From, tail);
478 Pair<EdgeTag, Subroutine> first = diffs.Tail.Head;
479 Subroutine nextSubroutine = first.Value;
480 yield return APC.ForEnd (nextSubroutine.Exit, point.SubroutineContext.Cons (new Edge<CFGBlock, EdgeTag> (edge.From, edge.To, first.Key)));
484 public override APC ComputeTargetFinallyContext (APC pc, CFGBlock succ)
486 LispList<Pair<EdgeTag, Subroutine>> list = EdgeSubroutinesOuterToInner (pc.Block, succ, pc.SubroutineContext);
488 return new APC (succ, 0, pc.SubroutineContext);
490 Pair<EdgeTag, Subroutine> last = list.Last ();
491 return new APC (last.Value.Entry, 0, pc.SubroutineContext.Cons (new Edge<CFGBlock, EdgeTag> (pc.Block, succ, last.Key)));
494 private LispList<Pair<EdgeTag, Subroutine>> EdgeSubroutinesOuterToInner (CFGBlock from, CFGBlock succ, LispList<Edge<CFGBlock, EdgeTag>> subroutineContext)
496 bool isExceptionHandlerEdge;
497 return EdgeSubroutinesOuterToInner (from, succ, out isExceptionHandlerEdge, subroutineContext);
500 public override LispList<Pair<EdgeTag, Subroutine>> EdgeSubroutinesOuterToInner (CFGBlock from, CFGBlock succ, out bool isExceptionHandlerEdge, LispList<Edge<CFGBlock, EdgeTag>> context)
502 if (from.Subroutine != this)
503 return from.Subroutine.EdgeSubroutinesOuterToInner (from, succ, out isExceptionHandlerEdge, context);
505 isExceptionHandlerEdge = IsCatchFilterHeader (succ);
506 return GetOrdinaryEdgeSubroutines (from, succ, context);
509 public override LispList<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutines (CFGBlock from, CFGBlock to, LispList<Edge<CFGBlock, EdgeTag>> context)
511 IMetaDataProvider metadataDecoder = this.SubroutineFacade.MetaDataProvider;
512 var apc = new APC (to, 0, context);
514 DecoratorHelper.Push (this);
516 LispList<Pair<EdgeTag, Subroutine>> list = DecoratorHelper.Dispatch<IEdgeSubroutineAdaptor> (this).GetOrdinaryEdgeSubroutinesInternal (from, to, context);
517 if (apc.InsideContract) {
518 if (context != null && !list.IsEmpty ()) {
522 if (@from.IsMethodCallBlock (out calledMethod, out isNewObj, out isVirtual) && isVirtual && ((IStackInfo) this).IsCallOnThis (new APC (@from, 0, null))) {
523 TypeNode type = metadataDecoder.DeclaringType (calledMethod);
525 if (context.Head.Tag.Is (EdgeTag.InheritedMask) || context.Head.Tag.Is (EdgeTag.ExtraMask) || context.Head.Tag.Is (EdgeTag.OldMask))
526 context = context.Tail;
528 Method calledMethod2;
531 if (context.Head.Tag.Is (EdgeTag.AfterMask) && context.Head.From.IsMethodCallBlock (out calledMethod2, out isNewObj2, out isVirtual2)) {
532 TypeNode sub = metadataDecoder.DeclaringType (calledMethod2);
533 if (metadataDecoder.DerivesFrom (sub, type))
535 if (!DecoratorHelper.Dispatch<IStackInfo> (this).IsCallOnThis (new APC (context.Head.From, 0, null)))
537 } else if (context.Head.Tag.Is (EdgeTag.BeforeMask) && context.Head.To.IsMethodCallBlock (out calledMethod2, out isNewObj2, out isVirtual2)) {
538 TypeNode sub = metadataDecoder.DeclaringType (calledMethod2);
539 if (metadataDecoder.DerivesFrom (sub, type))
541 if (!DecoratorHelper.Dispatch<IStackInfo> (this).IsCallOnThis (new APC (context.Head.To, 0, null)))
543 } else if (context.Head.Tag == EdgeTag.Exit) {
544 var methodInfo = context.Head.From.Subroutine as IMethodInfo;
545 if (methodInfo != null) {
546 TypeNode sub = metadataDecoder.DeclaringType (methodInfo.Method);
547 if (metadataDecoder.DerivesFrom (sub, type))
552 if (context.Head.Tag != EdgeTag.Entry)
554 var methodInfo = context.Head.From.Subroutine as IMethodInfo;
555 if (methodInfo != null) {
556 TypeNode sub = metadataDecoder.DeclaringType (methodInfo.Method);
557 if (metadataDecoder.DerivesFrom (sub, type))
562 context = context.Tail;
564 } while (!context.IsEmpty ());
565 Method implementingMethod;
566 if (!metadataDecoder.Equal (type, metadataDecoder.DeclaringType (calledMethod)) &&
567 metadataDecoder.TryGetImplementingMethod (type, calledMethod, out implementingMethod))
568 list = SpecializedEnsures (list, this.SubroutineFacade.GetEnsures (calledMethod), this.SubroutineFacade.GetEnsures (implementingMethod));
575 if (@from.IsMethodCallBlock (out calledMethod, out isNewObj, out isVirtual)) {
576 if (DecoratorHelper.Dispatch<IStackInfo> (this).IsCallOnThis (new APC (@from, 0, null))) {
577 var methodInfo = @from.Subroutine as IMethodInfo;
578 if (methodInfo != null) {
579 TypeNode bestType = metadataDecoder.DeclaringType (methodInfo.Method);
580 Method implementingMethod;
581 if (isVirtual && metadataDecoder.TryGetImplementingMethod (bestType, calledMethod, out implementingMethod))
582 list = SpecializedEnsures (list, this.SubroutineFacade.GetEnsures (calledMethod), this.SubroutineFacade.GetEnsures (implementingMethod));
583 list = InsertInvariant (@from, list, calledMethod, ref bestType, context);
590 DecoratorHelper.Pop ();
594 private LispList<Pair<EdgeTag, Subroutine>> InsertInvariant (CFGBlock from, LispList<Pair<EdgeTag, Subroutine>> list,
595 Method calledMethod, ref TypeNode type,
596 LispList<Edge<CFGBlock, EdgeTag>> context)
598 IMetaDataProvider metadataDecoder = this.SubroutineFacade.MetaDataProvider;
601 if (metadataDecoder.IsPropertySetter (calledMethod, out property)
602 && (metadataDecoder.IsAutoPropertyMember (calledMethod) || WithinConstructor (from, context)))
605 if (metadataDecoder.IsConstructor (calledMethod))
606 type = metadataDecoder.DeclaringType (calledMethod);
608 Subroutine invariant = this.SubroutineFacade.GetInvariant (type);
609 if (invariant != null) {
610 var methodCallBlock = from as MethodCallBlock<Label>;
611 if (methodCallBlock != null) {
612 EdgeTag first = methodCallBlock.IsNewObj ? EdgeTag.AfterNewObj : EdgeTag.AfterCall;
613 return list.Cons (new Pair<EdgeTag, Subroutine> (first, invariant));
620 private bool WithinConstructor (CFGBlock current, LispList<Edge<CFGBlock, EdgeTag>> context)
622 return new APC (current, 0, context).InsideConstructor;
625 private LispList<Pair<EdgeTag, Subroutine>> SpecializedEnsures (LispList<Pair<EdgeTag, Subroutine>> subroutines,
626 Subroutine toReplace, Subroutine specializedEnsures)
628 return subroutines.Select (pair => new Pair<EdgeTag, Subroutine> (pair.Key, pair.Value == toReplace ? specializedEnsures : pair.Value));
631 private static Predicate<Pair<EdgeTag, Subroutine>> FilterRecursiveContracts (CFGBlock from, LispList<Edge<CFGBlock, EdgeTag>> context)
633 return (candidate) => {
634 Subroutine sub = candidate.Value;
637 if (sub == @from.Subroutine)
639 if (context.Any (ctx => sub == ctx.From.Subroutine))
645 public abstract override void Initialize ();
647 public virtual void Commit ()
649 PostProcessBlocks ();
652 protected void PostProcessBlocks ()
654 var blockStack = new Stack<CFGBlock> ();
655 this.successor_edges = new EdgeMap<EdgeTag> (this.successors);
656 this.edge_info = new DepthFirst.Visitor<CFGBlock, Dummy> (this, null, (block) => blockStack.Push (block), null);
657 this.edge_info.VisitSubGraphNonRecursive (this.exception_exit);
658 this.edge_info.VisitSubGraphNonRecursive (this.exit);
659 this.edge_info.VisitSubGraphNonRecursive (this.entry);
661 foreach (var successorEdge in this.successor_edges) {
662 int idGen = UnusedBlockIndex;
663 successorEdge.From.Renumber (ref idGen);
666 foreach (CFGBlock cfgBlock in blockStack)
667 cfgBlock.Renumber (ref idGen1);
669 SuccessorEdges.Filter ((e) => e.From.Index != UnusedBlockIndex);
670 this.predecessor_edges = this.successor_edges.Reverse ();
672 var visitor = new DepthFirst.Visitor<CFGBlock, EdgeTag> (this.predecessor_edges, null, block => block.ReversePostOrderIndex = finishTime++, null);
673 visitor.VisitSubGraphNonRecursive (this.exit);
674 foreach (CFGBlock node in blockStack)
675 visitor.VisitSubGraphNonRecursive (node);
677 SuccessorEdges.Resort ();
678 this.blocks = blockStack.ToArray ();
679 this.LabelsThatStartBlocks = null;
683 public override IEnumerable<Subroutine> UsedSubroutines (HashSet<int> alreadySeen)
685 foreach (var list in this.edge_subroutines.Values) {
686 foreach (var pair in list.AsEnumerable ()) {
687 Subroutine sub = pair.Value;
688 if (!alreadySeen.Contains (sub.Id)) {
689 alreadySeen.Add (sub.Id);
696 public override IEnumerable<CFGBlock> ExceptionHandlers<Data, TType> (CFGBlock block, Subroutine innerSubroutine,
697 Data data, IHandlerFilter<Data> handlerPredicate)
699 yield return this.exception_exit;
703 public override void Print (TextWriter tw, ILPrinter<APC> printer, Func<CFGBlock,
704 IEnumerable<LispList<Edge<CFGBlock, EdgeTag>>>> contextLookup,
705 LispList<Edge<CFGBlock, EdgeTag>> context,
706 HashSet<Pair<Subroutine, LispList<Edge<CFGBlock, EdgeTag>>>> printed)
708 var element = new Pair<Subroutine, LispList<Edge<CFGBlock, EdgeTag>>> (this, context);
709 if (printed.Contains (element))
711 printed.Add (element);
712 var subs = new HashSet<Subroutine> ();
713 var methodInfo = this as IMethodInfo;
714 string method = (methodInfo != null) ? String.Format ("({0})", this.SubroutineFacade.MetaDataProvider.FullName (methodInfo.Method)) : null;
716 tw.WriteLine ("Subroutine SR{0} {1} {2}", Id, Kind, method);
717 tw.WriteLine ("-------------");
718 foreach (BlockWithLabels<Label> block in this.blocks) {
719 tw.Write ("Block {0} ({1})", block.Index, block.ReversePostOrderIndex);
720 if (this.edge_info.DepthFirstInfo (block).TargetOfBackEdge)
721 tw.WriteLine (" (target of backedge)");
722 else if (IsJoinPoint (block))
723 tw.WriteLine (" (join point)");
727 tw.Write (" Predecessors: ");
728 foreach (var edge in block.Subroutine.PredecessorEdges [block])
729 tw.Write ("({0}, {1}) ", edge.Key, edge.Value.Index);
731 PrintHandlers (tw, block);
733 tw.WriteLine (" Code:");
734 foreach (APC apc in block.APCs ())
735 printer (apc, " ", tw);
737 tw.Write (" Successors: ");
738 foreach (var edge in block.Subroutine.SuccessorEdges [block]) {
739 tw.Write ("({0}, {1}", edge.Key, edge.Value.Index);
740 if (this.edge_info.IsBackEdge (block, Dummy.Value, edge.Value))
743 for (LispList<Pair<EdgeTag, Subroutine>> list = GetOrdinaryEdgeSubroutines (block, edge.Value, context); list != null; list = list.Tail) {
744 subs.Add (list.Head.Value);
745 tw.Write (" SR{0}({1})", list.Head.Value.Id, list.Head.Key);
751 PrintReferencedSubroutines (tw, subs, printer, contextLookup, context, printed);
754 protected virtual void PrintReferencedSubroutines (TextWriter tw, HashSet<Subroutine> subs, ILPrinter<APC> printer,
755 Func<CFGBlock, IEnumerable<LispList<Edge<CFGBlock, EdgeTag>>>> contextLookup,
756 LispList<Edge<CFGBlock, EdgeTag>> context,
757 HashSet<Pair<Subroutine, LispList<Edge<CFGBlock, EdgeTag>>>> printed)
759 foreach (Subroutine subroutine in subs) {
760 if (contextLookup == null)
761 subroutine.Print (tw, printer, contextLookup, context, printed);
763 foreach (var ctx in contextLookup (subroutine.Entry))
764 subroutine.Print (tw, printer, contextLookup, ctx, printed);
769 protected virtual void PrintHandlers (TextWriter tw, BlockWithLabels<Label> block)
771 tw.Write (" Handlers: ");
772 if (block != ExceptionExit)
773 tw.Write ("{0} ", ExceptionExit.Index);
777 public int GetILOffset (Label label)
779 return CodeProvider.GetILOffset (label);