X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fcodegen.cs;h=b10dc6be02c81b9267e52687c8eb5461763bdb49;hb=bb70a0084a34cabdffa0164caa961383b6ca0722;hp=bc9ca7b853445a03fc319e2ce350a67a0e8155ce;hpb=0ab5f8b4da531f22ed3311bfdeb6cdefa90fc86c;p=mono.git diff --git a/mcs/mcs/codegen.cs b/mcs/mcs/codegen.cs index bc9ca7b8534..b10dc6be02c 100755 --- a/mcs/mcs/codegen.cs +++ b/mcs/mcs/codegen.cs @@ -8,10 +8,10 @@ // using System; +using System.IO; using System.Collections; using System.Reflection; using System.Reflection.Emit; -using System.Diagnostics.SymbolStore; namespace Mono.CSharp { @@ -23,7 +23,7 @@ namespace Mono.CSharp { public static AssemblyBuilder AssemblyBuilder; public static ModuleBuilder ModuleBuilder; - static public ISymbolWriter SymbolWriter; + static public SymbolWriter SymbolWriter; public static string Basename (string name) { @@ -62,90 +62,34 @@ namespace Mono.CSharp { static public string FileName; - // - // This routine initializes the Mono runtime SymbolWriter. - // - static bool InitMonoSymbolWriter (string basename, string output_file, - string[] debug_args) - { - string symbol_output = basename + ".dbg"; - - Type itype = SymbolWriter.GetType (); - if (itype == null) - return false; - - Type[] arg_types = new Type [3]; - arg_types [0] = typeof (string); - arg_types [1] = typeof (string); - arg_types [2] = typeof (string[]); - - MethodInfo initialize = itype.GetMethod ("Initialize", arg_types); - if (initialize == null) - return false; - - object[] args = new object [3]; - args [0] = output_file; - args [1] = symbol_output; - args [2] = debug_args; - - initialize.Invoke (SymbolWriter, args); - return true; - } - // // Initializes the symbol writer // - static void InitializeSymbolWriter (string basename, string output_file, - string[] args) + static void InitializeSymbolWriter () { - SymbolWriter = ModuleBuilder.GetSymWriter (); + SymbolWriter = SymbolWriter.GetSymbolWriter (ModuleBuilder); // // If we got an ISymbolWriter instance, initialize it. // if (SymbolWriter == null) { - Report.Error ( - -18, "Cannot find any symbol writer"); + Report.Warning ( + -18, "Could not find the symbol writer assembly (Mono.CSharp.Debugger.dll). This is normally an installation problem. Please make sure to compile and install the mcs/class/Mono.CSharp.Debugger directory."); return; } - - // - // Due to lacking documentation about the first argument of the - // Initialize method, we cannot use Microsoft's default symbol - // writer yet. - // - // If we're using the mono symbol writer, the SymbolWriter object - // is of type MonoSymbolWriter - but that's defined in a dynamically - // loaded DLL - that's why we're doing a comparision based on the type - // name here instead of using `SymbolWriter is MonoSymbolWriter'. - // - Type sym_type = ((object) SymbolWriter).GetType (); - - switch (sym_type.Name){ - case "MonoSymbolWriter": - if (!InitMonoSymbolWriter (basename, output_file, args)) - Report.Error ( - -18, "Cannot initialize the symbol writer"); - break; - - default: - Report.Error ( - -18, "Cannot generate debugging information on this platform"); - break; - } } // // Initializes the code generator variables // - static public void Init (string name, string output, bool want_debugging_support, - string[] debug_args) + static public void Init (string name, string output, bool want_debugging_support) { AssemblyName an; FileName = output; an = new AssemblyName (); - an.Name = TrimExt (Basename (name)); + an.Name = Path.GetFileNameWithoutExtension (name); + current_domain = AppDomain.CurrentDomain; AssemblyBuilder = current_domain.DefineDynamicAssembly ( an, AssemblyBuilderAccess.RunAndSave, Dirname (name)); @@ -161,17 +105,8 @@ namespace Mono.CSharp { ModuleBuilder = AssemblyBuilder.DefineDynamicModule ( Basename (name), Basename (output), want_debugging_support); - if (want_debugging_support) { - int pos = output.LastIndexOf ("."); - - string basename; - if (pos > 0) - basename = output.Substring (0, pos); - else - basename = output; - - InitializeSymbolWriter (basename, output, debug_args); - } + if (want_debugging_support) + InitializeSymbolWriter (); } static public void Save (string name) @@ -179,20 +114,7 @@ namespace Mono.CSharp { try { AssemblyBuilder.Save (Basename (name)); } catch (System.IO.IOException io){ - Report.Error (16, "Coult not write to file `"+name+"', cause: " + io.Message); - } - } - - static public void SaveSymbols () - { - if (SymbolWriter != null) { - // If we have a symbol writer, call its Close() method to write - // the symbol file to disk. - // - // When using Mono's default symbol writer, the Close() method must - // be called after the assembly has already been written to disk since - // it opens the assembly and reads its metadata. - SymbolWriter.Close (); + Report.Error (16, "Could not write to file `"+name+"', cause: " + io.Message); } } } @@ -203,7 +125,7 @@ namespace Mono.CSharp { /// public class EmitContext { public DeclSpace DeclSpace; - public TypeContainer TypeContainer; + public DeclSpace TypeContainer; public ILGenerator ig; /// @@ -267,6 +189,8 @@ namespace Mono.CSharp { public Block CurrentBlock; + public int CurrentFile; + /// /// The location where we store the return value. /// @@ -293,6 +217,17 @@ namespace Mono.CSharp { /// public bool InTry; + /// + /// Whether we are inside an iterator block. + /// + public bool InIterator; + + /// + /// Whether remapping of locals, parameters and fields is turned on. + /// Used by iterators and anonymous methods. + /// + public bool RemapToProxy; + /// /// Whether we are in a Catch block /// @@ -304,9 +239,9 @@ namespace Mono.CSharp { public bool InUnsafe; /// - /// Whether we break from a loop or not + /// Whether we are inside an anonymous method. /// - public bool Breaks; + public bool InAnonymousMethod; /// /// Location for this EmitContext @@ -332,7 +267,7 @@ namespace Mono.CSharp { protected Stack FlowStack; - public EmitContext (TypeContainer parent, DeclSpace ds, Location l, ILGenerator ig, + public EmitContext (DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig, Type return_type, int code_flags, bool is_constructor) { this.ig = ig; @@ -343,9 +278,12 @@ namespace Mono.CSharp { ConstantCheckState = true; IsStatic = (code_flags & Modifiers.STATIC) != 0; + InIterator = (code_flags & Modifiers.METHOD_YIELDS) != 0; + RemapToProxy = InIterator; ReturnType = return_type; IsConstructor = is_constructor; CurrentBlock = null; + CurrentFile = 0; if (parent != null){ // Can only be null for the ResolveType contexts. @@ -488,12 +426,11 @@ namespace Mono.CSharp { { bool has_ret = false; -// Console.WriteLine ("Emitting: " + loc); - - if (CodeGen.SymbolWriter != null) - Mark (loc); + if (!Location.IsNull (loc)) + CurrentFile = loc.File; if (block != null){ + try { int errors = Report.Errors; block.EmitMeta (this, block); @@ -512,17 +449,32 @@ namespace Mono.CSharp { } cfb = (FlowBranching) FlowStack.Pop (); - cfb.MergeTopBlock (); + FlowReturns returns = cfb.MergeTopBlock (); DoFlowAnalysis = old_do_flow_analysis; has_ret = block.Emit (this); + if ((returns == FlowReturns.ALWAYS) || + (returns == FlowReturns.EXCEPTION) || + (returns == FlowReturns.UNREACHABLE)) + has_ret = true; + if (Report.Errors == errors){ if (RootContext.WarningLevel >= 3) block.UsageWarning (); } } + } catch { + Console.WriteLine ("Exception caught by the compiler while compiling:"); + Console.WriteLine (" Block that caused the problem begin at: " + loc); + + if (CurrentBlock != null){ + Console.WriteLine (" Block being compiled: [{0},{1}]", + CurrentBlock.StartLocation, CurrentBlock.EndLocation); + } + throw; + } } if (ReturnType != null && !has_ret){ @@ -531,8 +483,10 @@ namespace Mono.CSharp { // correctly and emit an error instead of a warning. // // - Report.Error (161, loc, "Not all code paths return a value"); - return; + if (!InIterator){ + Report.Error (161, loc, "Not all code paths return a value"); + return; + } } if (HasReturnLabel) @@ -542,6 +496,9 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Ret); } else { if (!InTry){ + if (InIterator) + has_ret = true; + if (!has_ret || HasReturnLabel) ig.Emit (OpCodes.Ret); } @@ -552,15 +509,16 @@ namespace Mono.CSharp { /// This is called immediately before emitting an IL opcode to tell the symbol /// writer to which source line this opcode belongs. /// - public void Mark (Location loc) + public void Mark (Location loc, bool check_file) { - if (!Location.IsNull (loc)) { - ISymbolDocumentWriter doc = loc.SymbolDocument; + if ((CodeGen.SymbolWriter == null) || Location.IsNull (loc)) + return; - if (doc != null) - ig.MarkSequencePoint (doc, loc.Row, 0, loc.Row, 0); - } } + if (check_file && (CurrentFile != loc.File)) + return; + ig.MarkSequencePoint (null, loc.Row, 0, 0, 0); + } /// /// Returns a temporary storage for a variable of type t as @@ -635,6 +593,34 @@ namespace Mono.CSharp { return return_value; } + // + // Creates a field `name' with the type `t' on the proxy class + // + public FieldBuilder MapVariable (string name, Type t) + { + if (InIterator){ + return IteratorHandler.Current.MapVariable (name, t); + } + + throw new Exception ("MapVariable for an unknown state"); + } + + // + // Emits the proper object to address fields on a remapped + // variable/parameter to field in anonymous-method/iterator proxy classes. + // + public void EmitThis () + { + ig.Emit (OpCodes.Ldarg_0); + + if (!IsStatic){ + if (InIterator) + ig.Emit (OpCodes.Ldfld, IteratorHandler.Current.this_field); + else + throw new Exception ("EmitThis for an unknown state"); + } + } + /// /// A dynamic This that is shared by all variables in a emitcontext. /// Created on demand.