//
using System;
+using System.IO;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
-using System.Diagnostics.SymbolStore;
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)
{
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));
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)
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);
}
}
}
/// </summary>
public class EmitContext {
public DeclSpace DeclSpace;
- public TypeContainer TypeContainer;
+ public DeclSpace TypeContainer;
public ILGenerator ig;
/// <summary>
public Block CurrentBlock;
+ public int CurrentFile;
+
/// <summary>
/// The location where we store the return value.
/// </summary>
/// </summary>
public bool InTry;
+ /// <summary>
+ /// Whether we are inside an iterator block.
+ /// </summary>
+ public bool InIterator;
+
+ /// <summary>
+ /// Whether remapping of locals, parameters and fields is turned on.
+ /// Used by iterators and anonymous methods.
+ /// </summary>
+ public bool RemapToProxy;
+
/// <summary>
/// Whether we are in a Catch block
/// </summary>
public bool InUnsafe;
/// <summary>
- /// Whether we break from a loop or not
+ /// Whether we are inside an anonymous method.
/// </summary>
- public bool Breaks;
+ public bool InAnonymousMethod;
/// <summary>
/// Location for this EmitContext
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;
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.
{
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);
}
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){
// 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)
ig.Emit (OpCodes.Ret);
} else {
if (!InTry){
+ if (InIterator)
+ has_ret = true;
+
if (!has_ret || HasReturnLabel)
ig.Emit (OpCodes.Ret);
}
/// This is called immediately before emitting an IL opcode to tell the symbol
/// writer to which source line this opcode belongs.
/// </summary>
- 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);
+ }
/// <summary>
/// Returns a temporary storage for a variable of type t as
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");
+ }
+ }
+
/// <summary>
/// A dynamic This that is shared by all variables in a emitcontext.
/// Created on demand.