X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fstatement.cs;h=e3159d390829546bd4d4340b79469adb24841a25;hb=cc21ca3500fc936982e24d92f616165106c9e628;hp=d5cbd64de832fbc7c9d65fefd77f5f3b3778a531;hpb=aa9fca6196336c2ded89beadcf768a232eaff45d;p=mono.git diff --git a/mcs/mcs/statement.cs b/mcs/mcs/statement.cs index d5cbd64de83..e3159d39082 100644 --- a/mcs/mcs/statement.cs +++ b/mcs/mcs/statement.cs @@ -6,8 +6,8 @@ // Martin Baulig (martin@ximian.com) // Marek Safar (marek.safar@seznam.cz) // -// (C) 2001, 2002, 2003 Ximian, Inc. -// (C) 2003, 2004 Novell, Inc. +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003, 2004 Novell, Inc. // using System; @@ -116,6 +116,7 @@ namespace Mono.CSharp { return Clone (clonectx); } + public abstract void MutateHoistedGenericType (AnonymousMethodStorey storey); } // @@ -202,6 +203,10 @@ namespace Mono.CSharp { { } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + } + protected override void CloneTo (CloneContext clonectx, Statement target) { // nothing needed. @@ -233,6 +238,14 @@ namespace Mono.CSharp { loc = l; } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + expr.MutateHoistedGenericType (storey); + TrueStatement.MutateHoistedGenericType (storey); + if (FalseStatement != null) + FalseStatement.MutateHoistedGenericType (storey); + } + public override bool Resolve (EmitContext ec) { bool ok = true; @@ -305,35 +318,17 @@ namespace Mono.CSharp { // If we're a boolean constant, Resolve() already // eliminated dead code for us. // - if (expr is Constant){ - - // - // Simple bool constant - // - if (expr is BoolConstant) { - bool take = ((BoolConstant) expr).Value; - - if (take) - TrueStatement.Emit (ec); - else if (FalseStatement != null) - FalseStatement.Emit (ec); - - return; - } - - // - // Bool constant with side-effects - // - expr.Emit (ec); - ig.Emit (OpCodes.Pop); + Constant c = expr as Constant; + if (c != null){ + c.EmitSideEffect (ec); - if (TrueStatement != null) + if (!c.IsDefaultValue) TrueStatement.Emit (ec); - if (FalseStatement != null) + else if (FalseStatement != null) FalseStatement.Emit (ec); return; - } + } expr.EmitBranchable (ec, false_target, false); @@ -372,7 +367,6 @@ namespace Mono.CSharp { public class Do : Statement { public Expression expr; public Statement EmbeddedStatement; - bool infinite; public Do (Statement statement, Expression bool_expr, Location l) { @@ -400,14 +394,11 @@ namespace Mono.CSharp { expr = Expression.ResolveBoolean (ec, expr, loc); if (expr == null) ok = false; - else if (expr is BoolConstant){ - bool res = ((BoolConstant) expr).Value; - - if (res) - infinite = true; + else if (expr is Constant){ + bool infinite = !((Constant) expr).IsDefaultValue; + if (infinite) + ec.CurrentBranching.CurrentUsageVector.Goto (); } - if (infinite) - ec.CurrentBranching.CurrentUsageVector.Goto (); ec.EndFlowBranching (); @@ -431,9 +422,10 @@ namespace Mono.CSharp { // // Dead code elimination // - if (expr is BoolConstant){ - bool res = ((BoolConstant) expr).Value; + if (expr is Constant){ + bool res = !((Constant) expr).IsDefaultValue; + expr.EmitSideEffect (ec); if (res) ec.ig.Emit (OpCodes.Br, loop); } else @@ -445,6 +437,12 @@ namespace Mono.CSharp { ec.LoopEnd = old_end; } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + expr.MutateHoistedGenericType (storey); + EmbeddedStatement.MutateHoistedGenericType (storey); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { Do target = (Do) t; @@ -477,10 +475,10 @@ namespace Mono.CSharp { // // Inform whether we are infinite or not // - if (expr is BoolConstant){ - BoolConstant bc = (BoolConstant) expr; + if (expr is Constant){ + bool value = !((Constant) expr).IsDefaultValue; - if (bc.Value == false){ + if (value == false){ if (!Statement.ResolveUnreachable (ec, true)) return false; empty = true; @@ -508,8 +506,10 @@ namespace Mono.CSharp { protected override void DoEmit (EmitContext ec) { - if (empty) + if (empty) { + expr.EmitSideEffect (ec); return; + } ILGenerator ig = ec.ig; Label old_begin = ec.LoopBegin; @@ -521,8 +521,10 @@ namespace Mono.CSharp { // // Inform whether we are infinite or not // - if (expr is BoolConstant){ + if (expr is Constant){ + // expr is 'true', since the 'empty' case above handles the 'false' case ig.MarkLabel (ec.LoopBegin); + expr.EmitSideEffect (ec); Statement.Emit (ec); ig.Emit (OpCodes.Br, ec.LoopBegin); @@ -563,6 +565,12 @@ namespace Mono.CSharp { target.expr = expr.Clone (clonectx); target.Statement = Statement.Clone (clonectx); } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + expr.MutateHoistedGenericType (storey); + Statement.MutateHoistedGenericType (storey); + } } public class For : Statement { @@ -598,10 +606,10 @@ namespace Mono.CSharp { Test = Expression.ResolveBoolean (ec, Test, loc); if (Test == null) ok = false; - else if (Test is BoolConstant){ - BoolConstant bc = (BoolConstant) Test; + else if (Test is Constant){ + bool value = !((Constant) Test).IsDefaultValue; - if (bc.Value == false){ + if (value == false){ if (!Statement.ResolveUnreachable (ec, true)) return false; if ((Increment != null) && @@ -643,20 +651,22 @@ namespace Mono.CSharp { return ok; } - + protected override void DoEmit (EmitContext ec) { - if (empty) + if (InitStatement != null && InitStatement != EmptyStatement.Value) + InitStatement.Emit (ec); + + if (empty) { + Test.EmitSideEffect (ec); return; + } ILGenerator ig = ec.ig; Label old_begin = ec.LoopBegin; Label old_end = ec.LoopEnd; Label loop = ig.DefineLabel (); Label test = ig.DefineLabel (); - - if (InitStatement != null && InitStatement != EmptyStatement.Value) - InitStatement.Emit (ec); ec.LoopBegin = ig.DefineLabel (); ec.LoopEnd = ig.DefineLabel (); @@ -677,13 +687,15 @@ namespace Mono.CSharp { if (Test != null){ // // The Resolve code already catches the case for - // Test == BoolConstant (false) so we know that + // Test == Constant (false) so we know that // this is true // - if (Test is BoolConstant) + if (Test is Constant) { + Test.EmitSideEffect (ec); ig.Emit (OpCodes.Br, loop); - else + } else { Test.EmitBranchable (ec, loop, true); + } } else ig.Emit (OpCodes.Br, loop); @@ -693,6 +705,18 @@ namespace Mono.CSharp { ec.LoopEnd = old_end; } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + if (InitStatement != null) + InitStatement.MutateHoistedGenericType (storey); + if (Test != null) + Test.MutateHoistedGenericType (storey); + if (Increment != null) + Increment.MutateHoistedGenericType (storey); + + Statement.MutateHoistedGenericType (storey); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { For target = (For) t; @@ -728,6 +752,11 @@ namespace Mono.CSharp { expr.EmitStatement (ec); } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + expr.MutateHoistedGenericType (storey); + } + public override string ToString () { return "StatementExpression (" + expr + ")"; @@ -788,7 +817,7 @@ namespace Mono.CSharp { return false; } - AnonymousContainer am = ec.CurrentAnonymousMethod; + AnonymousExpression am = ec.CurrentAnonymousMethod; if ((am != null) && am.IsIterator && ec.InIterator) { Report.Error (1622, loc, "Cannot return a value from iterators. Use the yield return " + "statement to return a value, or yield break to end the iteration"); @@ -846,6 +875,12 @@ namespace Mono.CSharp { ec.ig.Emit (OpCodes.Ret); } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + if (Expr != null) + Expr.MutateHoistedGenericType (storey); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { Return target = (Return) t; @@ -891,6 +926,10 @@ namespace Mono.CSharp { Label l = label.LabelTarget (ec); ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, l); } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + } } public class LabeledStatement : Statement { @@ -957,6 +996,10 @@ namespace Mono.CSharp { ec.ig.MarkLabel (label); } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + } + public void AddReference () { referenced = true; @@ -993,6 +1036,10 @@ namespace Mono.CSharp { } ec.ig.Emit (OpCodes.Br, ec.Switch.DefaultTarget); } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + } } /// @@ -1061,12 +1108,16 @@ namespace Mono.CSharp { ec.ig.Emit (OpCodes.Br, sl.GetILLabelCode (ec)); } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + expr.MutateHoistedGenericType (storey); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { GotoCase target = (GotoCase) t; target.expr = expr.Clone (clonectx); - target.sl = sl.Clone (clonectx); } } @@ -1120,6 +1171,12 @@ namespace Mono.CSharp { } } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + if (expr != null) + expr.MutateHoistedGenericType (storey); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { Throw target = (Throw) t; @@ -1150,6 +1207,10 @@ namespace Mono.CSharp { { ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopEnd); } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + } protected override void CloneTo (CloneContext clonectx, Statement t) { @@ -1179,33 +1240,21 @@ namespace Mono.CSharp { ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopBegin); } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + } + protected override void CloneTo (CloneContext clonectx, Statement t) { // nothing needed. } } - public abstract class Variable + public interface ILocalVariable { - public abstract Type Type { - get; - } - - public abstract bool HasInstance { - get; - } - - public abstract bool NeedsTemporary { - get; - } - - public abstract void EmitInstance (EmitContext ec); - - public abstract void Emit (EmitContext ec); - - public abstract void EmitAssign (EmitContext ec); - - public abstract void EmitAddressOf (EmitContext ec); + void Emit (EmitContext ec); + void EmitAssign (EmitContext ec); + void EmitAddressOf (EmitContext ec); } public interface IKnownVariable { @@ -1216,8 +1265,8 @@ namespace Mono.CSharp { // // The information about a user-perceived local variable // - public class LocalInfo : IKnownVariable { - public Expression Type; + public class LocalInfo : IKnownVariable, ILocalVariable { + public readonly Expression Type; public Type VariableType; public readonly string Name; @@ -1225,11 +1274,7 @@ namespace Mono.CSharp { public readonly Block Block; public VariableInfo VariableInfo; - - Variable var; - public Variable Variable { - get { return var; } - } + public HoistedVariable HoistedVariableReference; [Flags] enum Flags : byte { @@ -1237,7 +1282,6 @@ namespace Mono.CSharp { ReadOnly = 2, Pinned = 4, IsThis = 8, - Captured = 16, AddressTaken = 32, CompilerGenerated = 64, IsConstant = 128 @@ -1270,11 +1314,10 @@ namespace Mono.CSharp { public void ResolveVariable (EmitContext ec) { - Block theblock = Block; - if (theblock.ScopeInfo != null) - var = theblock.ScopeInfo.GetCapturedVariable (this); + if (HoistedVariableReference != null) + return; - if (var == null) { + if (builder == null) { if (Pinned) // // This is needed to compile on both .NET 1.x and .NET 2.x @@ -1283,11 +1326,24 @@ namespace Mono.CSharp { builder = TypeManager.DeclareLocalPinned (ec.ig, VariableType); else builder = ec.ig.DeclareLocal (VariableType); - - var = new LocalVariable (this, builder); } } + public void Emit (EmitContext ec) + { + ec.ig.Emit (OpCodes.Ldloc, builder); + } + + public void EmitAssign (EmitContext ec) + { + ec.ig.Emit (OpCodes.Stloc, builder); + } + + public void EmitAddressOf (EmitContext ec) + { + ec.ig.Emit (OpCodes.Ldloca, builder); + } + public void EmitSymbolInfo (EmitContext ec, string name) { if (builder != null) @@ -1315,13 +1371,14 @@ namespace Mono.CSharp { public bool Resolve (EmitContext ec) { - if (VariableType == null) { - TypeExpr texpr = Type.ResolveAsContextualType (ec, false); - if (texpr == null) - return false; + if (VariableType != null) + return true; + + TypeExpr texpr = Type.ResolveAsContextualType (ec, false); + if (texpr == null) + return false; - VariableType = texpr.Type; - } + VariableType = texpr.Type; if (TypeManager.IsGenericParameter (VariableType)) return true; @@ -1342,11 +1399,6 @@ namespace Mono.CSharp { return true; } - public bool IsCaptured { - get { return (flags & Flags.Captured) != 0; } - set { flags |= Flags.Captured; } - } - public bool IsConstant { get { return (flags & Flags.IsConstant) != 0; } set { flags |= Flags.IsConstant; } @@ -1421,50 +1473,6 @@ namespace Mono.CSharp { get { return Location; } } - protected class LocalVariable : Variable - { - public readonly LocalInfo LocalInfo; - LocalBuilder builder; - - public LocalVariable (LocalInfo local, LocalBuilder builder) - { - this.LocalInfo = local; - this.builder = builder; - } - - public override Type Type { - get { return LocalInfo.VariableType; } - } - - public override bool HasInstance { - get { return false; } - } - - public override bool NeedsTemporary { - get { return false; } - } - - public override void EmitInstance (EmitContext ec) - { - // Do nothing. - } - - public override void Emit (EmitContext ec) - { - ec.ig.Emit (OpCodes.Ldloc, builder); - } - - public override void EmitAssign (EmitContext ec) - { - ec.ig.Emit (OpCodes.Stloc, builder); - } - - public override void EmitAddressOf (EmitContext ec) - { - ec.ig.Emit (OpCodes.Ldloca, builder); - } - } - public LocalInfo Clone (CloneContext clonectx) { // @@ -1502,7 +1510,7 @@ namespace Mono.CSharp { public Location EndLocation = Location.Null; public ExplicitBlock Explicit; - public ToplevelBlock Toplevel; + public ToplevelBlock Toplevel; // TODO: Use Explicit [Flags] public enum Flags : byte { @@ -1511,9 +1519,7 @@ namespace Mono.CSharp { VariablesInitialized = 4, HasRet = 8, IsDestructor = 16, - Unsafe = 32, - HasVarargs = 64, // Used in ToplevelBlock - IsIterator = 128 + Unsafe = 32 } protected Flags flags; @@ -1531,7 +1537,6 @@ namespace Mono.CSharp { // The statements in this block // protected ArrayList statements; - int num_statements; // // An array of Blocks. We keep track of children just @@ -1545,7 +1550,7 @@ namespace Mono.CSharp { // // Labels. (label, block) pairs. // - HybridDictionary labels; + protected HybridDictionary labels; // // Keeps track of (name, type) pairs @@ -1566,8 +1571,6 @@ namespace Mono.CSharp { // Block switch_block; - // TODO: merge with scope_initializers - ExpressionStatement scope_init; ArrayList scope_initializers; ArrayList anonymous_children; @@ -1577,7 +1580,6 @@ namespace Mono.CSharp { int this_id; int assignable_slots; - protected ScopeInfo scope_info; bool unreachable_shown; bool unreachable; @@ -1986,18 +1988,6 @@ namespace Mono.CSharp { } } - public ScopeInfo ScopeInfo { - get { return scope_info; } - } - - public ScopeInfo CreateScopeInfo () - { - if (scope_info == null) - scope_info = ScopeInfo.CreateScope (this); - - return scope_info; - } - public ArrayList AnonymousChildren { get { return anonymous_children; } } @@ -2105,13 +2095,6 @@ namespace Mono.CSharp { // public virtual void EmitMeta (EmitContext ec) { - Report.Debug (64, "BLOCK EMIT META", this, Parent, Toplevel, ScopeInfo, ec); - if (ScopeInfo != null) { - scope_init = ScopeInfo.GetScopeInitializer (ec); - Report.Debug (64, "BLOCK EMIT META #1", this, Toplevel, ScopeInfo, - ec, scope_init); - } - if (variables != null){ foreach (LocalInfo vi in variables.Values) vi.ResolveVariable (ec); @@ -2243,15 +2226,13 @@ namespace Mono.CSharp { if (unreachable && !(s is LabeledStatement) && !(s is Block)) statements [ix] = EmptyStatement.Value; - num_statements = ix + 1; - unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable; if (unreachable && s is LabeledStatement) throw new InternalErrorException ("should not happen"); } Report.Debug (4, "RESOLVE BLOCK DONE", StartLocation, - ec.CurrentBranching, statement_count, num_statements); + ec.CurrentBranching, statement_count); while (ec.CurrentBranching is FlowBranchingLabeled) ec.EndFlowBranching (); @@ -2297,7 +2278,7 @@ namespace Mono.CSharp { protected override void DoEmit (EmitContext ec) { - for (int ix = 0; ix < num_statements; ix++){ + for (int ix = 0; ix < statements.Count; ix++){ Statement s = (Statement) statements [ix]; s.Emit (ec); } @@ -2306,48 +2287,23 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { Block prev_block = ec.CurrentBlock; - ec.CurrentBlock = this; - bool emit_debug_info = SymbolWriter.HasSymbolWriter; - bool is_lexical_block = (this == Explicit) && (Parent != null) && - ((flags & Flags.IsIterator) == 0); - - bool omit_debug_info = ec.OmitDebuggingInfo; - - if (emit_debug_info) { - if (is_lexical_block) - ec.BeginScope (); - } - - if ((scope_init != null) || (scope_initializers != null)) + if (scope_initializers != null) { SymbolWriter.OpenCompilerGeneratedBlock (ec.ig); - if (scope_init != null) { - ec.OmitDebuggingInfo = true; - scope_init.EmitStatement (ec); - ec.OmitDebuggingInfo = omit_debug_info; - } - if (scope_initializers != null) { + bool omit_debug_info = ec.OmitDebuggingInfo; ec.OmitDebuggingInfo = true; foreach (StatementExpression s in scope_initializers) s.Emit (ec); ec.OmitDebuggingInfo = omit_debug_info; - } - if ((scope_init != null) || (scope_initializers != null)) SymbolWriter.CloseCompilerGeneratedBlock (ec.ig); + } ec.Mark (StartLocation, true); DoEmit (ec); - if (emit_debug_info) { - EmitSymbolInfo (ec); - - if (is_lexical_block) - ec.EndScope (); - } - ec.CurrentBlock = prev_block; } @@ -2363,6 +2319,28 @@ namespace Mono.CSharp { } } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + MutateVariables (storey); + + foreach (Statement s in statements) + s.MutateHoistedGenericType (storey); + } + + void MutateVariables (AnonymousMethodStorey storey) + { + if (variables != null) { + foreach (LocalInfo vi in variables.Values) { + vi.VariableType = storey.MutateType (vi.VariableType); + } + } + + if (temporary_variables != null) { + foreach (LocalInfo vi in temporary_variables) + vi.VariableType = storey.MutateType (vi.VariableType); + } + } + public override string ToString () { return String.Format ("{0} ({1}:{2})", GetType (),ID, StartLocation); @@ -2407,6 +2385,9 @@ namespace Mono.CSharp { } public class ExplicitBlock : Block { + HybridDictionary known_variables; + protected AnonymousMethodStorey am_storey; + public ExplicitBlock (Block parent, Location start, Location end) : this (parent, (Flags) 0, start, end) { @@ -2418,12 +2399,6 @@ namespace Mono.CSharp { this.Explicit = this; } - public bool IsIterator { - get { return (flags & Flags.IsIterator) != 0; } - } - - HybridDictionary known_variables; - // // Marks a variable with name @name as being used in this or a child block. // If a variable name has been used in a child block, it's illegal to @@ -2440,11 +2415,125 @@ namespace Mono.CSharp { Parent.Explicit.AddKnownVariable (name, info); } + public AnonymousMethodStorey AnonymousMethodStorey { + get { return am_storey; } + } + + // + // Creates anonymous method storey in current block + // + public AnonymousMethodStorey CreateAnonymousMethodStorey (EmitContext ec) + { + // + // When referencing a variable in iterator storey from children anonymous method + // + if (Toplevel.am_storey is IteratorStorey) { + ec.CurrentAnonymousMethod.AddStoreyReference (Toplevel.am_storey); + return Toplevel.am_storey; + } + + // + // An iterator has only 1 storey block + // + if (ec.CurrentIterator != null) + return ec.CurrentIterator.Storey; + + if (am_storey == null) { + MemberBase mc = ec.ResolveContext as MemberBase; + GenericMethod gm = mc == null ? null : mc.GenericMethod; + + // + // Create anonymous method storey for this block + // + am_storey = new AnonymousMethodStorey (this, ec.TypeContainer, mc, gm, "AnonStorey"); + } + + // + // Creates a link between this block and the anonymous method + // + // An anonymous method can reference variables from any outer block, but they are + // hoisted in their own ExplicitBlock. When more than one block is referenced we + // need to create another link between those variable storeys + // + ec.CurrentAnonymousMethod.AddStoreyReference (am_storey); + return am_storey; + } + + public override void Emit (EmitContext ec) + { + if (am_storey != null) + am_storey.EmitHoistedVariables (ec); + + bool emit_debug_info = SymbolWriter.HasSymbolWriter; + bool is_lexical_block = Parent != null && !(am_storey is IteratorStorey); + if (emit_debug_info && is_lexical_block) + ec.BeginScope (); + + base.Emit (ec); + + if (emit_debug_info) { + EmitSymbolInfo (ec); + if (is_lexical_block) + ec.EndScope (); + } + } + + public override void EmitMeta (EmitContext ec) + { + base.EmitMeta (ec); + + // + // It has to be done when all storey references are resolved + // + if (am_storey != null && am_storey.HasHoistedVariables) + am_storey.DefineMembers (); + } + + protected override void EmitSymbolInfo (EmitContext ec) + { + if (am_storey != null) + SymbolWriter.DefineScopeVariable (am_storey.ID); + + base.EmitSymbolInfo (ec); + } + internal IKnownVariable GetKnownVariable (string name) { return known_variables == null ? null : (IKnownVariable) known_variables [name]; } + public void PropagateStoreyReference (AnonymousMethodStorey s) + { + if (Parent != null && am_storey != s) { + if (am_storey != null) + am_storey.AddParentStoreyReference (s); + + Parent.Explicit.PropagateStoreyReference (s); + } + } + + public override bool Resolve (EmitContext ec) + { + bool ok = base.Resolve (ec); + + // + // Define an anonymous method storey when this block has hoisted variables + // otherwise the storey can be discarded + // + if (am_storey != null) { + if (am_storey.HasHoistedVariables) { + am_storey.DefineType (); + am_storey.DefineMembers (); + am_storey.Parent.PartialContainer.AddCompilerGeneratedClass (am_storey); + } else { + am_storey.Undo (); + am_storey = null; + } + } + + return ok; + } + protected override void CloneTo (CloneContext clonectx, Statement t) { ExplicitBlock target = (ExplicitBlock) t; @@ -2486,15 +2575,11 @@ namespace Mono.CSharp { public class ToplevelBlock : ExplicitBlock { GenericMethod generic; FlowBranchingToplevel top_level_branching; - AnonymousContainer anonymous_container; - RootScopeInfo root_scope; Parameters parameters; ToplevelParameterInfo[] parameter_info; + LocalInfo this_variable; - public bool HasVarargs { - get { return (flags & Flags.HasVarargs) != 0; } - set { flags |= Flags.HasVarargs; } - } + public HoistedVariable HoistedThisVariable; // // The parameters for the block. @@ -2503,29 +2588,6 @@ namespace Mono.CSharp { get { return parameters; } } - public bool CompleteContexts (EmitContext ec) - { - Report.Debug (64, "TOPLEVEL COMPLETE CONTEXTS", this, Parent, root_scope); - - if (root_scope != null) - root_scope.LinkScopes (); - - if (Parent == null && root_scope != null) { - Report.Debug (64, "TOPLEVEL COMPLETE CONTEXTS #1", this, root_scope); - - if (root_scope.DefineType () == null) - return false; - if (!root_scope.ResolveType ()) - return false; - if (!root_scope.ResolveMembers ()) - return false; - if (!root_scope.DefineMembers ()) - return false; - } - - return true; - } - public GenericMethod GenericMethod { get { return generic; } } @@ -2534,11 +2596,6 @@ namespace Mono.CSharp { get { return Parent == null ? null : Parent.Toplevel; } } - public AnonymousContainer AnonymousContainer { - get { return anonymous_container; } - set { anonymous_container = value; } - } - public ToplevelBlock (Block parent, Parameters parameters, Location start) : this (parent, (Flags) 0, parameters, start) { @@ -2555,7 +2612,7 @@ namespace Mono.CSharp { { } - public ToplevelBlock (Flags flags, Parameters parameters, Location start) : + ToplevelBlock (Flags flags, Parameters parameters, Location start) : this (null, flags, parameters, start) { } @@ -2659,69 +2716,38 @@ namespace Mono.CSharp { return true; } - public RootScopeInfo CreateRootScope (TypeContainer host) - { - if (root_scope != null) - return root_scope; - - if (Container == null) - root_scope = new RootScopeInfo ( - this, host, generic, StartLocation); - - if (scope_info != null) - throw new InternalErrorException (); - - scope_info = root_scope; - return root_scope; - } - public override Expression CreateExpressionTree (EmitContext ec) { return ((Statement) statements [0]).CreateExpressionTree (ec); } - public void CreateIteratorHost (RootScopeInfo root) + // + // Reformats this block to be top-level iterator block + // + public IteratorStorey ChangeToIterator (Iterator iterator, ToplevelBlock source) { - Report.Debug (64, "CREATE ITERATOR HOST", this, root, Parent, root_scope); + // Create block with original statements + ExplicitBlock iter_block = new ExplicitBlock (this, flags, StartLocation, EndLocation); - if (Parent != null || root_scope != null) - throw new InternalErrorException (); + // TODO: Change to iter_block.statements = statements; + foreach (Statement stmt in source.statements) + iter_block.AddStatement (stmt); + labels = source.labels; + + AddStatement (new IteratorStatement (iterator, iter_block)); - scope_info = root_scope = root; - } + source.statements = new ArrayList (1); + source.AddStatement (new Return (iterator, iterator.Location)); - public RootScopeInfo RootScope { - get { - if (root_scope != null) - return root_scope; - else if (Container != null) - return Container.RootScope; - else - return null; - } + IteratorStorey iterator_storey = new IteratorStorey (iterator); + source.am_storey = iterator_storey; + return iterator_storey; } public FlowBranchingToplevel TopLevelBranching { get { return top_level_branching; } } - // - // This is used if anonymous methods are used inside an iterator - // (see 2test-22.cs for an example). - // - // The AnonymousMethod is created while parsing - at a time when we don't - // know yet that we're inside an iterator, so it's `Container' is initially - // null. Later on, when resolving the iterator, we need to move the - // anonymous method into that iterator. - // - public void ReParent (ToplevelBlock new_parent) - { - if ((flags & Flags.VariablesInitialized) != 0) - throw new InternalErrorException ("block has already been resolved"); - - Parent = new_parent; - } - // // Returns a `ParameterReference' for the given name, or null if there // is no such parameter @@ -2743,8 +2769,6 @@ namespace Mono.CSharp { return null; } - LocalInfo this_variable = null; - // // Returns the "this" instance variable of this block. // See AddThisVariable() for more information. @@ -2839,63 +2863,19 @@ namespace Mono.CSharp { public override void EmitMeta (EmitContext ec) { + parameters.ResolveVariable (); + // Avoid declaring an IL variable for this_variable since it is not accessed // from the generated IL if (this_variable != null) Variables.Remove ("this"); base.EmitMeta (ec); - parameters.ResolveVariable (this); - } - - protected override void EmitSymbolInfo (EmitContext ec) - { - if ((AnonymousContainer != null) && (AnonymousContainer.Scope != null)) - SymbolWriter.DefineScopeVariable (AnonymousContainer.Scope.ID); - - base.EmitSymbolInfo (ec); - } - - public void MakeIterator (Iterator iterator) - { - flags |= Flags.IsIterator; - - Block block = new ExplicitBlock (this, flags, StartLocation, EndLocation); - foreach (Statement stmt in statements) - block.AddStatement (stmt); - statements.Clear (); - statements.Add (new MoveNextStatement (iterator, block)); } - protected class MoveNextStatement : Statement { - Iterator iterator; - Block block; - - public MoveNextStatement (Iterator iterator, Block block) - { - this.iterator = iterator; - this.block = block; - this.loc = iterator.Location; - } - - public override bool Resolve (EmitContext ec) - { - ec.StartFlowBranching (iterator); - bool ok = block.Resolve (ec); - ec.EndFlowBranching (); - return ok; - } - - protected override void DoEmit (EmitContext ec) - { - iterator.EmitMoveNext (ec, block); - } - } - - public override string ToString () + public override void Emit (EmitContext ec) { - return String.Format ("{0} ({1}:{2}{3}:{4})", GetType (), ID, StartLocation, - root_scope, anonymous_container != null ? - anonymous_container.Scope : null); + base.Emit (ec); + ec.Mark (EndLocation, true); } } @@ -3615,6 +3595,12 @@ namespace Mono.CSharp { return null; } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + foreach (SwitchSection ss in Sections) + ss.Block.MutateHoistedGenericType (storey); + } + public override bool Resolve (EmitContext ec) { Expr = Expr.Resolve (ec); @@ -3797,6 +3783,7 @@ namespace Mono.CSharp { } } + // Base class for statements that are implemented in terms of try...finally public abstract class ExceptionStatement : ResumableStatement { bool code_follows; @@ -4008,7 +3995,7 @@ namespace Mono.CSharp { { ILGenerator ig = ec.ig; - temp.Store (ec, expr); + temp.EmitAssign (ec, expr); temp.Emit (ec); ig.Emit (OpCodes.Call, TypeManager.void_monitor_enter_object); } @@ -4023,6 +4010,13 @@ namespace Mono.CSharp { temp.Emit (ec); ec.ig.Emit (OpCodes.Call, TypeManager.void_monitor_exit_object); } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + expr.MutateHoistedGenericType (storey); + temp.MutateHoistedGenericType (storey); + Statement.MutateHoistedGenericType (storey); + } protected override void CloneTo (CloneContext clonectx, Statement t) { @@ -4054,6 +4048,11 @@ namespace Mono.CSharp { Block.Emit (ec); } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + Block.MutateHoistedGenericType (storey); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { Unchecked target = (Unchecked) t; @@ -4083,6 +4082,11 @@ namespace Mono.CSharp { Block.Emit (ec); } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + Block.MutateHoistedGenericType (storey); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { Checked target = (Checked) t; @@ -4111,6 +4115,12 @@ namespace Mono.CSharp { using (ec.With (EmitContext.Flags.InUnsafe, true)) Block.Emit (ec); } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + Block.MutateHoistedGenericType (storey); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { Unsafe target = (Unsafe) t; @@ -4156,18 +4166,60 @@ namespace Mono.CSharp { // Store pointer in pinned location // converted.Emit (ec); - vi.Variable.EmitAssign (ec); + vi.EmitAssign (ec); } public override void EmitExit (EmitContext ec) { ec.ig.Emit (OpCodes.Ldc_I4_0); ec.ig.Emit (OpCodes.Conv_U); - vi.Variable.EmitAssign (ec); + vi.EmitAssign (ec); } } class StringEmitter : Emitter { + class StringPtr : Expression + { + LocalBuilder b; + + public StringPtr (LocalBuilder b, Location l) + { + this.b = b; + eclass = ExprClass.Value; + type = TypeManager.char_ptr_type; + loc = l; + } + + public override Expression CreateExpressionTree (EmitContext ec) + { + throw new NotSupportedException ("ET"); + } + + public override Expression DoResolve (EmitContext ec) + { + // This should never be invoked, we are born in fully + // initialized state. + + return this; + } + + public override void Emit (EmitContext ec) + { + if (TypeManager.int_get_offset_to_string_data == null) { + // TODO: Move to resolve !! + TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedMethod ( + TypeManager.runtime_helpers_type, "get_OffsetToStringData", loc, Type.EmptyTypes); + } + + ILGenerator ig = ec.ig; + + ig.Emit (OpCodes.Ldloc, b); + ig.Emit (OpCodes.Conv_I); + ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data); + ig.Emit (OpCodes.Add); + } + } + LocalBuilder pinned_string; Location loc; @@ -4193,7 +4245,7 @@ namespace Mono.CSharp { return; converted.Emit (ec); - vi.Variable.EmitAssign (ec); + vi.EmitAssign (ec); } public override void EmitExit (EmitContext ec) @@ -4403,6 +4455,12 @@ namespace Mono.CSharp { } } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + // Fixed statement cannot be used inside anonymous methods or lambdas + throw new NotSupportedException (); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { Fixed target = (Fixed) t; @@ -4463,19 +4521,21 @@ namespace Mono.CSharp { VarBlock.Emit (ec); if (Name != null) { - LocalInfo vi = Block.GetLocalInfo (Name); - if (vi == null) - throw new Exception ("Variable does not exist in this block"); - - if (vi.Variable.NeedsTemporary) { - LocalBuilder e = ig.DeclareLocal (vi.VariableType); - ig.Emit (OpCodes.Stloc, e); + // TODO: Move to resolve + LocalVariableReference lvr = new LocalVariableReference (Block, Name, loc); + lvr.Resolve (ec); + + Expression source; + if (lvr.IsHoisted) { + LocalTemporary lt = new LocalTemporary (lvr.Type); + lt.Store (ec); + source = lt; + } else { + // Variable is at the top of the stack + source = EmptyExpression.Null; + } - vi.Variable.EmitInstance (ec); - ig.Emit (OpCodes.Ldloc, e); - vi.Variable.EmitAssign (ec); - } else - vi.Variable.EmitAssign (ec); + lvr.EmitAssign (ec, source, false, false); } else ig.Emit (OpCodes.Pop); @@ -4511,6 +4571,15 @@ namespace Mono.CSharp { } } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + if (type != null) + type = storey.MutateType (type); + if (VarBlock != null) + VarBlock.MutateHoistedGenericType (storey); + Block.MutateHoistedGenericType (storey); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { Catch target = (Catch) t; @@ -4571,6 +4640,12 @@ namespace Mono.CSharp { fini.Emit (ec); } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + stmt.MutateHoistedGenericType (storey); + fini.MutateHoistedGenericType (storey); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { TryFinally target = (TryFinally) t; @@ -4693,6 +4768,18 @@ namespace Mono.CSharp { ig.EndExceptionBlock (); } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + Block.MutateHoistedGenericType (storey); + + if (General != null) + General.MutateHoistedGenericType (storey); + if (Specific != null) { + foreach (Catch c in Specific) + c.MutateHoistedGenericType (storey); + } + } + protected override void CloneTo (CloneContext clonectx, Statement t) { TryCatch target = (TryCatch) t; @@ -4757,7 +4844,7 @@ namespace Mono.CSharp { protected override void EmitPreTryBody (EmitContext ec) { - local_copy.Store (ec, expr); + local_copy.EmitAssign (ec, expr); } protected override void EmitTryBody (EmitContext ec) @@ -4765,7 +4852,7 @@ namespace Mono.CSharp { Statement.Emit (ec); } - protected override void EmitFinallyBody (EmitContext ec) + protected override void EmitFinallyBody (EmitContext ec) { ILGenerator ig = ec.ig; if (!expr_type.IsValueType) { @@ -4807,6 +4894,13 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Call, mi); } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + expr_type = storey.MutateType (expr_type); + local_copy.MutateHoistedGenericType (storey); + Statement.MutateHoistedGenericType (storey); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { UsingTemporary target = (UsingTemporary) t; @@ -4838,7 +4932,7 @@ namespace Mono.CSharp { bool ResolveVariable (EmitContext ec) { - ExpressionStatement a = new Assign (var, init, loc); + ExpressionStatement a = new SimpleAssign (var, init, loc); a = a.ResolveStatement (ec); if (a == null) return false; @@ -4919,6 +5013,13 @@ namespace Mono.CSharp { } } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + assign.MutateHoistedGenericType (storey); + var.MutateHoistedGenericType (storey); + stmt.MutateHoistedGenericType (storey); + } + public override bool Resolve (EmitContext ec) { if (!ResolveVariable (ec)) @@ -4958,8 +5059,6 @@ namespace Mono.CSharp { Expression variable; Expression expr; Statement statement; - ArrayForeach array; - CollectionForeach collection; public Foreach (Expression type, LocalVariableReference var, Expression expr, Statement stmt, Location l) @@ -4992,26 +5091,13 @@ namespace Mono.CSharp { return false; } - // - // We need an instance variable. Not sure this is the best - // way of doing this. - // - // FIXME: When we implement propertyaccess, will those turn - // out to return values in ExprClass? I think they should. - // - if (!(expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.Value || - expr.eclass == ExprClass.PropertyAccess || expr.eclass == ExprClass.IndexerAccess)){ - collection.Error_Enumerator (); - return false; - } - if (expr.Type.IsArray) { - array = new ArrayForeach (type, variable, expr, statement, loc); - return array.Resolve (ec); + statement = new ArrayForeach (type, variable, expr, statement, loc); + } else { + statement = new CollectionForeach (type, variable, expr, statement, loc); } - collection = new CollectionForeach (type, variable, expr, statement, loc); - return collection.Resolve (ec); + return statement.Resolve (ec); } protected override void DoEmit (EmitContext ec) @@ -5022,10 +5108,7 @@ namespace Mono.CSharp { ec.LoopBegin = ig.DefineLabel (); ec.LoopEnd = ig.DefineLabel (); - if (collection != null) - collection.Emit (ec); - else - array.Emit (ec); + statement.Emit (ec); ec.LoopBegin = old_begin; ec.LoopEnd = old_end; @@ -5033,24 +5116,22 @@ namespace Mono.CSharp { protected class ArrayCounter : TemporaryVariable { + StatementExpression increment; + public ArrayCounter (Location loc) : base (TypeManager.int32_type, loc) - { } + { + } - public void Initialize (EmitContext ec) + public void ResolveIncrement (EmitContext ec) { - EmitThis (ec); - ec.ig.Emit (OpCodes.Ldc_I4_0); - EmitStore (ec); + increment = new StatementExpression (new UnaryMutator (UnaryMutator.Mode.PostIncrement, this, loc)); + increment.Resolve (ec); } - public void Increment (EmitContext ec) + public void EmitIncrement (EmitContext ec) { - EmitThis (ec); - Emit (ec); - ec.ig.Emit (OpCodes.Ldc_I4_1); - ec.ig.Emit (OpCodes.Add); - EmitStore (ec); + increment.Emit (ec); } } @@ -5066,6 +5147,7 @@ namespace Mono.CSharp { TemporaryVariable copy; Expression access; + Expression[] length_exprs; public ArrayForeach (Expression var_type, Expression var, Expression expr, Statement stmt, Location l) @@ -5087,15 +5169,24 @@ namespace Mono.CSharp { counter = new ArrayCounter [rank]; lengths = new TemporaryVariable [rank]; + length_exprs = new Expression [rank]; - ArrayList list = new ArrayList (); + ArrayList list = new ArrayList (rank); for (int i = 0; i < rank; i++) { counter [i] = new ArrayCounter (loc); - counter [i].Resolve (ec); + counter [i].ResolveIncrement (ec); lengths [i] = new TemporaryVariable (TypeManager.int32_type, loc); lengths [i].Resolve (ec); + if (rank == 1) { + length_exprs [i] = new MemberAccess (copy, "Length").Resolve (ec); + } else { + ArrayList args = new ArrayList (1); + args.Add (new Argument (new IntConstant (i, loc))); + length_exprs [i] = new Invocation (new MemberAccess (copy, "GetLength"), args).Resolve (ec); + } + list.Add (counter [i]); } @@ -5143,7 +5234,7 @@ namespace Mono.CSharp { { ILGenerator ig = ec.ig; - copy.Store (ec, expr); + copy.EmitAssign (ec, expr); Label[] test = new Label [rank]; Label[] loop = new Label [rank]; @@ -5152,13 +5243,12 @@ namespace Mono.CSharp { test [i] = ig.DefineLabel (); loop [i] = ig.DefineLabel (); - lengths [i].EmitThis (ec); - ((ArrayAccess) access).EmitGetLength (ec, i); - lengths [i].EmitStore (ec); + lengths [i].EmitAssign (ec, length_exprs [i]); } + IntConstant zero = new IntConstant (0, loc); for (int i = 0; i < rank; i++) { - counter [i].Initialize (ec); + counter [i].EmitAssign (ec, zero); ig.Emit (OpCodes.Br, test [i]); ig.MarkLabel (loop [i]); @@ -5171,7 +5261,7 @@ namespace Mono.CSharp { ig.MarkLabel (ec.LoopBegin); for (int i = rank - 1; i >= 0; i--){ - counter [i].Increment (ec); + counter [i].EmitIncrement (ec); ig.MarkLabel (test [i]); counter [i].Emit (ec); @@ -5181,6 +5271,19 @@ namespace Mono.CSharp { ig.MarkLabel (ec.LoopEnd); } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + copy.MutateHoistedGenericType (storey); + conv.MutateHoistedGenericType (storey); + variable.MutateHoistedGenericType (storey); + statement.MutateHoistedGenericType (storey); + + for (int i = 0; i < rank; i++) { + counter [i].MutateHoistedGenericType (storey); + lengths [i].MutateHoistedGenericType (storey); + } + } } protected class CollectionForeach : Statement @@ -5364,7 +5467,7 @@ namespace Mono.CSharp { return null; } - public void Error_Enumerator () + void Error_Enumerator () { if (enumerator_found) { return; @@ -5572,6 +5675,11 @@ namespace Mono.CSharp { parent.EmitLoopInit (ec); parent.EmitLoopBody (ec); } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + throw new NotSupportedException (); + } } class DisposableWrapper : ExceptionStatement { @@ -5616,6 +5724,11 @@ namespace Mono.CSharp { { parent.EmitFinallyBody (ec); } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + throw new NotSupportedException (); + } } bool ResolveLoop (EmitContext ec) @@ -5625,7 +5738,7 @@ namespace Mono.CSharp { void EmitLoopInit (EmitContext ec) { - enumerator.Store (ec, init); + enumerator.EmitAssign (ec, init); } void EmitLoopBody (EmitContext ec) @@ -5640,7 +5753,7 @@ namespace Mono.CSharp { if (enumerator_type.IsValueType) { MethodInfo mi = FetchMethodDispose (enumerator_type); if (mi != null) { - enumerator.EmitLoadAddress (ec); + enumerator.AddressOf (ec, AddressOp.Load); ig.Emit (OpCodes.Call, mi); } else { enumerator.Emit (ec); @@ -5663,6 +5776,13 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void); } } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + enumerator_type = storey.MutateType (enumerator_type); + init.MutateHoistedGenericType (storey); + loop.MutateHoistedGenericType (storey); + } } protected class CollectionForeachStatement : Statement @@ -5693,7 +5813,7 @@ namespace Mono.CSharp { if (conv == null) return false; - assign = new Assign (variable, conv, loc); + assign = new SimpleAssign (variable, conv, loc); if (assign.Resolve (ec) == null) return false; @@ -5708,6 +5828,12 @@ namespace Mono.CSharp { assign.EmitStatement (ec); statement.Emit (ec); } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + assign.MutateHoistedGenericType (storey); + statement.MutateHoistedGenericType (storey); + } } protected override void CloneTo (CloneContext clonectx, Statement t) @@ -5719,5 +5845,10 @@ namespace Mono.CSharp { target.expr = expr.Clone (clonectx); target.statement = statement.Clone (clonectx); } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + statement.MutateHoistedGenericType (storey); + } } }