//
using System;
+using System.IO;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
using System.Diagnostics.SymbolStore;
-namespace Mono.CSharp {
+namespace Mono.MonoBASIC {
/// <summary>
/// Code generator class.
//
// This routine initializes the Mono runtime SymbolWriter.
//
- static void InitMonoSymbolWriter (string basename, string[] debug_args)
+ static bool InitMonoSymbolWriter (string basename, string symbol_output,
+ string exe_output_file, string[] debug_args)
{
- string symbol_output = basename + "-debug.s";
-
Type itype = SymbolWriter.GetType ();
if (itype == null)
- return;
+ return false;
- Type[] arg_types = new Type [2];
+ Type[] arg_types = new Type [3];
arg_types [0] = typeof (string);
- arg_types [1] = typeof (string[]);
+ arg_types [1] = typeof (string);
+ arg_types [2] = typeof (string[]);
MethodInfo initialize = itype.GetMethod ("Initialize", arg_types);
if (initialize == null)
- return;
+ return false;
- object[] args = new object [2];
- args [0] = symbol_output;
- args [1] = debug_args;
+ object[] args = new object [3];
+ args [0] = exe_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[] args)
+ static void InitializeSymbolWriter (string basename, string symbol_output,
+ string exe_output_file, string[] args)
{
SymbolWriter = ModuleBuilder.GetSymWriter ();
//
// If we got an ISymbolWriter instance, initialize it.
//
- if (SymbolWriter == null)
+ if (SymbolWriter == null) {
+ Report.Warning (
+ -18, "Cannot find any symbol writer");
return;
+ }
//
// Due to lacking documentation about the first argument of the
switch (sym_type.Name){
case "MonoSymbolWriter":
- InitMonoSymbolWriter (basename, args);
+ if (!InitMonoSymbolWriter (basename, symbol_output,
+ exe_output_file, args))
+ Report.Warning (
+ -18, "Cannot initialize the symbol writer");
break;
default:
- Report.Error (
+ Report.Warning (
-18, "Cannot generate debugging information on this platform");
break;
}
ModuleBuilder = AssemblyBuilder.DefineDynamicModule (
Basename (name), Basename (output), want_debugging_support);
+ int pos = output.LastIndexOf (".");
+
+ string basename;
+ if (pos > 0)
+ basename = output.Substring (0, pos);
+ else
+ basename = output;
+
+ string symbol_output = basename + ".dbg";
+
if (want_debugging_support)
- InitializeSymbolWriter (an.Name, debug_args);
+ InitializeSymbolWriter (basename, symbol_output, output, debug_args);
+ else {
+ try {
+ File.Delete (symbol_output);
+ } catch {
+ // Ignore errors.
+ }
+ }
}
static public void Save (string name)
/// </summary>
public bool IsStatic;
+ /// <summary>
+ /// Whether we are emitting a field initializer
+ /// </summary>
+ public bool IsFieldInitializer;
+
/// <summary>
/// The value that is allowed to be returned or NULL if there is no
/// return type.
/// Whether we are inside an unsafe block
/// </summary>
public bool InUnsafe;
-
- /// <summary>
- /// Whether we break from a loop or not
- /// </summary>
- public bool Breaks;
/// <summary>
- /// Location for this EmitContext
+ /// Whether we are inside an unsafe block
/// </summary>
- public Location loc;
+ public bool InvokingOwnOverload;
/// <summary>
- /// Used to "flag" the resolution process to only lookup types,
- /// and nothing else. This is an out-of-band communication
- /// path to SimpleName from the cast operation.
+ /// Location for this EmitContext
/// </summary>
- public bool OnlyLookupTypes;
+ public Location loc;
/// <summary>
/// Used to flag that it is ok to define types recursively, as the
/// we relax the rules
/// </summary>
public bool InEnumContext;
+
+ public string BlockName;
protected Stack FlowStack;
ReturnType = return_type;
IsConstructor = is_constructor;
CurrentBlock = null;
+ BlockName = "";
+ InvokingOwnOverload = false;
if (parent != null){
// Can only be null for the ResolveType contexts.
- ContainerType = parent.TypeBuilder;
- InUnsafe = ((parent.ModFlags | code_flags) & Modifiers.UNSAFE) != 0;
+ ContainerType = parent.TypeBuilder;
+ if (parent.UnsafeContext)
+ InUnsafe = true;
+ else
+ InUnsafe = (code_flags & Modifiers.UNSAFE) != 0;
}
- OnlyLookupTypes = false;
loc = l;
FlowStack = new Stack ();
CurrentBranching.SetParameterAssigned (number);
}
+ // These are two overloaded methods for EmitTopBlock
+ // since in MonoBasic functions we need the Function name
+ // along with its top block, in order to be able to
+ // retrieve the return value when there is no explicit
+ // 'Return' statement
public void EmitTopBlock (Block block, InternalParameters ip, Location loc)
{
- bool has_ret = false;
+ EmitTopBlock (block, "", ip, loc);
+ }
-// Console.WriteLine ("Emitting: " + loc);
+ public void EmitTopBlock (Block block, string bname, InternalParameters ip, Location loc)
+ {
+ bool has_ret = false;
+ //Console.WriteLine ("Emitting: '{0}", bname);
+ BlockName = bname;
if (CodeGen.SymbolWriter != null)
Mark (loc);
}
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 ();
if (ReturnType != null && !has_ret){
//
- // FIXME: we need full flow analysis to implement this
- // correctly and emit an error instead of a warning.
- //
+ // mcs here would report an error (and justly so), but functions without
+ // an explicit return value are perfectly legal in MonoBasic
//
- Report.Error (161, loc, "Not all code paths return a value");
+
+ VariableInfo vi = block.GetVariableInfo (bname);
+ if (vi != null)
+ {
+ ig.Emit (OpCodes.Ldloc, vi.LocalBuilder);
+ ig.Emit (OpCodes.Ret);
+ }
+ else
+ Report.Error (-200, "This is not supposed to happen !");
return;
}
/// </summary>
public void Mark (Location loc)
{
- if (!Location.IsNull (loc)) {
+ if ((CodeGen.SymbolWriter != null) && !Location.IsNull (loc)) {
ISymbolDocumentWriter doc = loc.SymbolDocument;
if (doc != null)
ig.MarkSequencePoint (doc, loc.Row, 0, loc.Row, 0);
- } }
-
+ }
+ }
/// <summary>
/// Returns a temporary storage for a variable of type t as
public Expression my_this;
public Expression This {
get {
- if (my_this == null)
- my_this = new This (loc).Resolve (this);
+ if (my_this == null) {
+ if (CurrentBlock != null)
+ my_this = new This (CurrentBlock, loc);
+ else
+ my_this = new This (loc);
+
+ my_this = my_this.Resolve (this);
+ }
return my_this;
}