X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fflowanalysis.cs;h=bc7f898d76a7ca61dd3529478be69450a2d5a421;hb=35c139e3eba84b5e3a33d242964b6c5fdce90035;hp=8f0e94e0e6434f73af909c01176258cb950dfc6d;hpb=9bf050c846147fd139bc8dddfc8c8185ba8c62ca;p=mono.git diff --git a/mcs/gmcs/flowanalysis.cs b/mcs/gmcs/flowanalysis.cs index 8f0e94e0e64..bc7f898d76a 100644 --- a/mcs/gmcs/flowanalysis.cs +++ b/mcs/gmcs/flowanalysis.cs @@ -168,10 +168,15 @@ namespace Mono.CSharp return; } + a.And (b, do_break); + } + + public void And (Reachability b, bool do_break) + { // // `break' does not "break" in a Switch or a LoopBlock // - bool a_breaks = do_break && a.AlwaysBreaks; + bool a_breaks = do_break && AlwaysBreaks; bool b_breaks = do_break && b.AlwaysBreaks; bool a_has_barrier, b_has_barrier; @@ -180,55 +185,55 @@ namespace Mono.CSharp // This is the normal case: the code following a barrier // cannot be reached. // - a_has_barrier = a.AlwaysHasBarrier; + a_has_barrier = AlwaysHasBarrier; b_has_barrier = b.AlwaysHasBarrier; } else { // // Special case for Switch and LoopBlocks: we can reach the // code after the barrier via the `break'. // - a_has_barrier = !a.AlwaysBreaks && a.AlwaysHasBarrier; + a_has_barrier = !AlwaysBreaks && AlwaysHasBarrier; b_has_barrier = !b.AlwaysBreaks && b.AlwaysHasBarrier; } - bool a_unreachable = a_breaks || a.AlwaysThrows || a_has_barrier; + bool a_unreachable = a_breaks || AlwaysThrows || a_has_barrier; bool b_unreachable = b_breaks || b.AlwaysThrows || b_has_barrier; // // Do all code paths always return ? // - if (a.AlwaysReturns) { + if (AlwaysReturns) { if (b.AlwaysReturns || b_unreachable) - a.returns = FlowReturns.Always; + returns = FlowReturns.Always; else - a.returns = FlowReturns.Sometimes; + returns = FlowReturns.Sometimes; } else if (b.AlwaysReturns) { - if (a.AlwaysReturns || a_unreachable) - a.returns = FlowReturns.Always; + if (AlwaysReturns || a_unreachable) + returns = FlowReturns.Always; else - a.returns = FlowReturns.Sometimes; - } else if (!a.MayReturn) { + returns = FlowReturns.Sometimes; + } else if (!MayReturn) { if (b.MayReturn) - a.returns = FlowReturns.Sometimes; + returns = FlowReturns.Sometimes; else - a.returns = FlowReturns.Never; + returns = FlowReturns.Never; } else if (!b.MayReturn) { - if (a.MayReturn) - a.returns = FlowReturns.Sometimes; + if (MayReturn) + returns = FlowReturns.Sometimes; else - a.returns = FlowReturns.Never; + returns = FlowReturns.Never; } - a.breaks = AndFlowReturns (a.breaks, b.breaks); - a.throws = AndFlowReturns (a.throws, b.throws); - a.barrier = AndFlowReturns (a.barrier, b.barrier); + breaks = AndFlowReturns (breaks, b.breaks); + throws = AndFlowReturns (throws, b.throws); + barrier = AndFlowReturns (barrier, b.barrier); if (a_unreachable && b_unreachable) - a.barrier = FlowReturns.Always; + barrier = FlowReturns.Always; else if (a_unreachable || b_unreachable) - a.barrier = FlowReturns.Sometimes; + barrier = FlowReturns.Sometimes; else - a.barrier = FlowReturns.Never; + barrier = FlowReturns.Never; } public void Or (Reachability b) @@ -334,6 +339,11 @@ namespace Mono.CSharp barrier = FlowReturns.Always; } + public void ResetBarrier () + { + barrier = FlowReturns.Never; + } + static string ShortName (FlowReturns returns) { switch (returns) { @@ -359,10 +369,10 @@ namespace Mono.CSharp { switch (type) { case BranchingType.Exception: - return new FlowBranchingException (parent, block, loc); + throw new InvalidOperationException (); case BranchingType.Switch: - return new FlowBranchingBlock (parent, type, SiblingType.SwitchSection, block, loc); + return new FlowBranchingSwitch (parent, block, loc); case BranchingType.SwitchSection: return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc); @@ -624,7 +634,7 @@ namespace Mono.CSharp { UsageVector result = branching.Merge (); - Report.Debug (2, " MERGING CHILD", this, IsDirty, + Report.Debug (2, " MERGING CHILD", this, branching, IsDirty, result.ParameterVector, result.LocalVector, result.Reachability, reachability, Type); @@ -642,21 +652,19 @@ namespace Mono.CSharp // then we do always return (or stay in the // loop forever). new_r.SetReturns (); - } + } new_r.SetBarrier (); - } else { - if (new_r.Returns == FlowReturns.Always) { - // We're either finite or we may leave the loop. - new_r.SetReturnsSometimes (); - } - if (new_r.Throws == FlowReturns.Always) { - // We're either finite or we may leave the loop. - new_r.SetThrowsSometimes (); - } - } - } else if (branching.Type == BranchingType.Switch) + } + + if (may_leave_loop) + new_r.ResetBarrier (); + } else if (branching.Type == BranchingType.Switch) { + if (new_r.MayBreak || new_r.MayReturn) + new_r.ResetBarrier (); + new_r.ResetBreaks (); + } // // We've now either reached the point after the branching or we will @@ -680,7 +688,10 @@ namespace Mono.CSharp if (result.ParameterVector != null) parameters.Or (result.ParameterVector); - reachability.Or (new_r); + if ((branching.Type == BranchingType.Block) && branching.Block.Implicit) + reachability = new_r.Clone (); + else + reachability.Or (new_r); Report.Debug (2, " MERGING CHILD DONE", this, result, new_r, reachability); @@ -740,30 +751,35 @@ namespace Mono.CSharp reachability = Reachability.Never (); - if (o_vectors == null) + if (o_vectors == null) { + reachability.SetBarrier (); return; + } bool first = true; for (UsageVector vector = o_vectors; vector != null; vector = vector.Next) { - Report.Debug (1, " MERGING JUMP ORIGIN", vector); + Report.Debug (1, " MERGING JUMP ORIGIN", vector, + first, locals, vector.Locals); if (first) { if (locals != null && vector.Locals != null) - locals.Or (vector.locals); + locals.Or (vector.locals); if (parameters != null) parameters.Or (vector.parameters); first = false; } else { - if (locals != null && vector.Locals != null) - locals.And (vector.locals); - if (parameters != null) - parameters.And (vector.parameters); - } + if (locals != null) + locals.And (vector.locals); + if (parameters != null) + parameters.And (vector.parameters); + } Reachability.And (ref reachability, vector.Reachability, true); + + Report.Debug (1, " MERGING JUMP ORIGIN #1", vector); } Report.Debug (1, " MERGING JUMP ORIGINS DONE", this); @@ -791,18 +807,18 @@ namespace Mono.CSharp Report.Debug (1, " MERGING FINALLY ORIGIN DONE", this); } - public void MergeBreakOrigins (UsageVector o_vectors) + public void MergeBreakOrigins (FlowBranching branching, UsageVector o_vectors) { Report.Debug (1, " MERGING BREAK ORIGINS", this); if (o_vectors == null) return; - bool first = true; + bool first = branching.Infinite; for (UsageVector vector = o_vectors; vector != null; vector = vector.Next) { - Report.Debug (1, " MERGING BREAK ORIGIN", vector); + Report.Debug (1, " MERGING BREAK ORIGIN", vector, first); if (first) { if (locals != null && vector.Locals != null) @@ -817,6 +833,8 @@ namespace Mono.CSharp if (parameters != null) parameters.And (vector.parameters); } + + reachability.And (vector.Reachability, false); } Report.Debug (1, " MERGING BREAK ORIGINS DONE", this); @@ -1124,7 +1142,7 @@ namespace Mono.CSharp throw new NotSupportedException (); UsageVector vector = new UsageVector ( - SiblingType.Conditional, null, Block, Location, + SiblingType.Block, null, Block, Location, param_map.Length, local_map.Length); UsageVector result = vector.MergeChild (this); @@ -1154,29 +1172,11 @@ namespace Mono.CSharp return false; } - // - // Checks whether we're in a `catch' block. - // - public virtual bool InCatch () + public virtual bool InTryWithCatch () { if (Parent != null) - return Parent.InCatch (); - else - return false; - } - - // - // Checks whether we're in a `finally' block. - // - public virtual bool InFinally (bool is_return) - { - if (!is_return && - ((Type == BranchingType.Loop) || (Type == BranchingType.Switch))) - return false; - else if (Parent != null) - return Parent.InFinally (is_return); - else - return false; + return Parent.InTryWithCatch (); + return false; } public virtual bool InLoop () @@ -1225,6 +1225,12 @@ namespace Mono.CSharp throw new NotSupportedException (); } + public virtual void StealFinallyClauses (ref ArrayList list) + { + if (Parent != null) + Parent.StealFinallyClauses (ref list); + } + public bool IsAssigned (VariableInfo vi) { return CurrentUsageVector.IsAssigned (vi); @@ -1346,7 +1352,32 @@ namespace Mono.CSharp { UsageVector vector = base.Merge (); - vector.MergeBreakOrigins (break_origins); + vector.MergeBreakOrigins (this, break_origins); + + return vector; + } + } + + public class FlowBranchingSwitch : FlowBranchingBlock + { + UsageVector break_origins; + + public FlowBranchingSwitch (FlowBranching parent, Block block, Location loc) + : base (parent, BranchingType.Switch, SiblingType.SwitchSection, block, loc) + { } + + public override void AddBreakVector (UsageVector vector) + { + vector = vector.Clone (); + vector.Next = break_origins; + break_origins = vector; + } + + protected override UsageVector Merge () + { + UsageVector vector = base.Merge (); + + vector.MergeBreakOrigins (this, break_origins); return vector; } @@ -1354,30 +1385,33 @@ namespace Mono.CSharp public class FlowBranchingException : FlowBranching { + ExceptionStatement stmt; UsageVector current_vector; UsageVector catch_vectors; UsageVector finally_vector; UsageVector finally_origins; - bool in_try; + bool emit_finally; - public FlowBranchingException (FlowBranching parent, Block block, Location loc) - : base (parent, BranchingType.Exception, SiblingType.Try, block, loc) - { } + public FlowBranchingException (FlowBranching parent, + ExceptionStatement stmt) + : base (parent, BranchingType.Exception, SiblingType.Try, + null, stmt.loc) + { + this.stmt = stmt; + this.emit_finally = true; + } protected override void AddSibling (UsageVector sibling) { if (sibling.Type == SiblingType.Try) { sibling.Next = catch_vectors; catch_vectors = sibling; - in_try = true; } else if (sibling.Type == SiblingType.Catch) { sibling.Next = catch_vectors; catch_vectors = sibling; - in_try = false; } else if (sibling.Type == SiblingType.Finally) { sibling.MergeFinallyOrigins (finally_origins); finally_vector = sibling; - in_try = false; } else throw new InvalidOperationException (); @@ -1393,14 +1427,18 @@ namespace Mono.CSharp return finally_vector == null; } - public override bool InCatch () + public override bool InTryWithCatch () { - return !in_try && (finally_vector == null); - } + if (finally_vector == null) { + Try t = stmt as Try; + if (t != null && t.HasCatch) + return true; + } - public override bool InFinally (bool is_return) - { - return finally_vector != null; + if (Parent != null) + return Parent.InTryWithCatch (); + + return false; } public override bool BreakCrossesTryCatchBoundary () @@ -1415,6 +1453,19 @@ namespace Mono.CSharp finally_origins = vector; } + public override void StealFinallyClauses (ref ArrayList list) + { + if (list == null) + list = new ArrayList (); + list.Add (stmt); + emit_finally = false; + base.StealFinallyClauses (ref list); + } + + public bool EmitFinally { + get { return emit_finally; } + } + public override LabeledStatement LookupLabel (string name, Location loc) { if (current_vector.Block == null) @@ -1638,13 +1689,15 @@ namespace Mono.CSharp if (type is TypeBuilder) { TypeContainer tc = TypeManager.LookupTypeContainer (type); - ArrayList fields = tc.Fields; + ArrayList fields = null; + if (tc != null) + fields = tc.Fields; ArrayList public_fields = new ArrayList (); ArrayList non_public_fields = new ArrayList (); if (fields != null) { - foreach (Field field in fields) { + foreach (FieldMember field in fields) { if ((field.ModFlags & Modifiers.STATIC) != 0) continue; if ((field.ModFlags & Modifiers.PUBLIC) != 0) @@ -2173,7 +2226,12 @@ namespace Mono.CSharp // public void And (MyBitVector new_vector) { - BitArray new_array = new_vector.Vector; + BitArray new_array; + + if (new_vector != null) + new_array = new_vector.Vector; + else + new_array = new BitArray (Count, false); initialize_vector ();