public static ModuleClass Module;
static CodeGen ()
+ {
+ Reset ();
+ }
+
+ public static void Reset ()
{
Assembly = new AssemblyClass ();
Module = new ModuleClass (RootContext.Unsafe);
return ".";
}
- static string TrimExt (string name)
- {
- int pos = name.LastIndexOf ('.');
-
- return name.Substring (0, pos);
- }
-
static public string FileName;
//
//
// Initializes the code generator variables
//
- static public void Init (string name, string output, bool want_debugging_support)
+ static public bool Init (string name, string output, bool want_debugging_support)
{
FileName = output;
AssemblyName an = Assembly.GetAssemblyName (name, output);
+ if (an == null)
+ return false;
if (an.KeyPair != null) {
// If we are going to strong name our assembly make
RootContext.StrongNameKeyContainer + "'.");
Environment.Exit (1);
}
- throw;
+ return false;
}
catch (CryptographicException) {
if ((RootContext.StrongNameKeyContainer != null) || (RootContext.StrongNameKeyFile != null)) {
Report.Error (1548, "Could not use the specified key to strongname the assembly.");
Environment.Exit (1);
}
- throw;
+ return false;
}
//
if (want_debugging_support)
InitializeSymbolWriter (output);
+
+ return true;
}
static public void Save (string name)
catch (System.IO.IOException io) {
Report.Error (16, "Could not write to file `"+name+"', cause: " + io.Message);
}
+ catch (System.UnauthorizedAccessException ua) {
+ Report.Error (16, "Could not write to file `"+name+"', cause: " + ua.Message);
+ }
if (SymbolWriter != null)
SymbolWriter.WriteSymbolFile ();
}
}
- //
- // Provides "local" store across code that can yield: locals
- // or fields, notice that this should not be used by anonymous
- // methods to create local storage, those only require
- // variable mapping.
- //
- public class VariableStorage {
- FieldBuilder fb;
- LocalBuilder local;
-
- static int count;
-
- public VariableStorage (EmitContext ec, Type t)
- {
- count++;
- if (ec.InIterator)
- fb = ec.CurrentIterator.MapVariable ("s_", count.ToString (), t);
- else
- local = ec.ig.DeclareLocal (t);
- }
-
- public void EmitThis (ILGenerator ig)
- {
- if (fb != null)
- ig.Emit (OpCodes.Ldarg_0);
- }
-
- public void EmitStore (ILGenerator ig)
- {
- if (fb == null)
- ig.Emit (OpCodes.Stloc, local);
- else
- ig.Emit (OpCodes.Stfld, fb);
- }
-
- public void EmitLoad (ILGenerator ig)
- {
- if (fb == null)
- ig.Emit (OpCodes.Ldloc, local);
- else
- ig.Emit (OpCodes.Ldfld, fb);
- }
-
- public void EmitLoadAddress (ILGenerator ig)
- {
- if (fb == null)
- ig.Emit (OpCodes.Ldloca, local);
- else
- ig.Emit (OpCodes.Ldflda, fb);
- }
-
- public void EmitCall (ILGenerator ig, MethodInfo mi)
- {
- // FIXME : we should handle a call like tostring
- // here, where boxing is needed. However, we will
- // never encounter that with the current usage.
-
- bool value_type_call;
- EmitThis (ig);
- if (fb == null) {
- value_type_call = local.LocalType.IsValueType;
-
- if (value_type_call)
- ig.Emit (OpCodes.Ldloca, local);
- else
- ig.Emit (OpCodes.Ldloc, local);
- } else {
- value_type_call = fb.FieldType.IsValueType;
-
- if (value_type_call)
- ig.Emit (OpCodes.Ldflda, fb);
- else
- ig.Emit (OpCodes.Ldfld, fb);
- }
-
- ig.Emit (value_type_call ? OpCodes.Call : OpCodes.Callvirt, mi);
- }
- }
-
/// <summary>
/// An Emit Context is created for each body of code (from methods,
/// properties bodies, indexer bodies or constructor bodies)
/// </summary>
public bool IsStatic;
+ /// <summary>
+ /// Whether the actual created method is static or instance method.
+ /// Althoug the method might be declared as `static', if an anonymous
+ /// method is involved, we might turn this into an instance method.
+ ///
+ /// So this reflects the low-level staticness of the method, while
+ /// IsStatic represents the semantic, high-level staticness.
+ /// </summary>
+ public bool MethodIsStatic;
+
/// <summary>
/// Whether we are emitting a field initializer
/// </summary>
public bool IsFieldInitializer;
+ /// <summary>
+ /// We are resolving a class'es base class and interfaces.
+ /// </summary>
+ public bool ResolvingTypeTree;
+
/// <summary>
/// The value that is allowed to be returned or NULL if there is no
/// return type.
/// Whether we're control flow analysis enabled
/// </summary>
public bool DoFlowAnalysis;
-
+
/// <summary>
/// Keeps track of the Type to LocalBuilder temporary storage created
/// to store structures (used to compute the address of the structure
public bool IsLastStatement;
- /// <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 inside an unsafe block
/// </summary>
/// </summary>
public bool InFixedInitializer;
+ public bool InRefOutArgumentResolving;
+
+ public bool InCatch;
+ public bool InFinally;
+
/// <summary>
/// Whether we are inside an anonymous method.
/// </summary>
- public AnonymousMethod CurrentAnonymousMethod;
+ public AnonymousContainer CurrentAnonymousMethod;
/// <summary>
/// Location for this EmitContext
/// </summary>
public Location loc;
- /// <summary>
- /// Used to flag that it is ok to define types recursively, as the
- /// expressions are being evaluated as part of the type lookup
- /// during the type resolution process
- /// </summary>
- public bool ResolvingTypeTree;
-
/// <summary>
/// Inside an enum definition, we do not resolve enumeration values
/// to their enumerations, but rather to the underlying type/value
}
Phase current_phase;
-
FlowBranching current_flow_branching;
+
+ static int next_id = 0;
+ int id = ++next_id;
+
+ public override string ToString ()
+ {
+ return String.Format ("EmitContext ({0}:{1}:{2})", id,
+ CurrentIterator, capture_context, loc);
+ }
public EmitContext (DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig,
Type return_type, int code_flags, bool is_constructor)
ConstantCheckState = true;
if ((return_type is TypeBuilder) && return_type.IsGenericTypeDefinition)
- throw new Exception ("FUCK");
+ throw new InternalErrorException ();
IsStatic = (code_flags & Modifiers.STATIC) != 0;
+ MethodIsStatic = IsStatic;
InIterator = (code_flags & Modifiers.METHOD_YIELDS) != 0;
- RemapToProxy = InIterator;
ReturnType = return_type;
IsConstructor = is_constructor;
CurrentBlock = null;
{
FlowBranching.BranchingType type;
- if (CurrentBranching.Type == FlowBranching.BranchingType.Switch)
+ if ((CurrentBranching != null) &&
+ (CurrentBranching.Type == FlowBranching.BranchingType.Switch))
type = FlowBranching.BranchingType.SwitchSection;
else
type = FlowBranching.BranchingType.Block;
- current_flow_branching = FlowBranching.CreateBranching (CurrentBranching, type, block, block.StartLocation);
+ DoFlowAnalysis = true;
+
+ current_flow_branching = FlowBranching.CreateBranching (
+ CurrentBranching, type, block, block.StartLocation);
return current_flow_branching;
}
public void CaptureParameter (string name, Type t, int idx)
{
-
capture_context.AddParameter (this, CurrentAnonymousMethod, name, t, idx);
}
+
+ public void CaptureThis ()
+ {
+ capture_context.CaptureThis ();
+ }
+
//
// Use to register a field as captured
public void EmitMeta (ToplevelBlock b, InternalParameters ip)
{
if (capture_context != null)
- capture_context.EmitHelperClasses (this);
+ capture_context.EmitAnonymousHelperClasses (this);
b.EmitMeta (this);
if (HasReturnLabel)
}
}
+ bool resolved;
+
public bool ResolveTopBlock (EmitContext anonymous_method_host, ToplevelBlock block,
InternalParameters ip, Location loc, out bool unreachable)
{
unreachable = false;
+ if (resolved)
+ return true;
+
capture_context = block.CaptureContext;
if (!Location.IsNull (loc))
CurrentFile = loc.File;
#if PRODUCTION
- try {
+ try {
#endif
- int errors = Report.Errors;
-
- block.ResolveMeta (block, this, ip);
-
+ if (!block.ResolveMeta (this, ip))
+ return false;
- if (Report.Errors == errors){
- bool old_do_flow_analysis = DoFlowAnalysis;
- DoFlowAnalysis = true;
+ bool old_do_flow_analysis = DoFlowAnalysis;
+ DoFlowAnalysis = true;
- if (anonymous_method_host != null)
- current_flow_branching = FlowBranching.CreateBranching (
- anonymous_method_host.CurrentBranching, FlowBranching.BranchingType.Block,
- block, loc);
- else
+ if (anonymous_method_host != null)
current_flow_branching = FlowBranching.CreateBranching (
- null, FlowBranching.BranchingType.Block, block, loc);
-
- if (!block.Resolve (this)) {
- current_flow_branching = null;
- DoFlowAnalysis = old_do_flow_analysis;
- return false;
- }
+ anonymous_method_host.CurrentBranching,
+ FlowBranching.BranchingType.Block, block, loc);
+ else
+ current_flow_branching = block.TopLevelBranching;
- FlowBranching.Reachability reachability = current_flow_branching.MergeTopBlock ();
+ if (!block.Resolve (this)) {
current_flow_branching = null;
-
DoFlowAnalysis = old_do_flow_analysis;
+ return false;
+ }
- if (reachability.AlwaysReturns ||
- reachability.AlwaysThrows ||
- reachability.IsUnreachable)
- unreachable = true;
- }
+ FlowBranching.Reachability reachability = current_flow_branching.MergeTopBlock ();
+ current_flow_branching = null;
+
+ DoFlowAnalysis = old_do_flow_analysis;
+
+ if (reachability.AlwaysReturns ||
+ reachability.AlwaysThrows ||
+ reachability.IsUnreachable)
+ unreachable = true;
#if PRODUCTION
- } catch (Exception e) {
+ } catch (Exception e) {
Console.WriteLine ("Exception caught by the compiler while compiling:");
Console.WriteLine (" Block that caused the problem begin at: " + loc);
}
#endif
- if (ReturnType != null && !unreachable){
- if (!InIterator){
- if (CurrentAnonymousMethod != null){
- Report.Error (1643, loc, "Not all code paths return a value in anonymous method of type `{0}'",
- CurrentAnonymousMethod.Type);
- } else {
+ if (ReturnType != null && !unreachable) {
+ if (CurrentAnonymousMethod == null) {
Report.Error (161, loc, "Not all code paths return a value");
- }
-
+ return false;
+ } else if (!CurrentAnonymousMethod.IsIterator) {
+ Report.Error (
+ 1643, loc, "Not all code paths return a " +
+ "value in anonymous method of type `{0}'",
+ CurrentAnonymousMethod.Type);
return false;
}
}
- block.CompleteContexts ();
+ block.CompleteContexts ();
+ resolved = true;
return true;
}
// this case.
//
+ bool in_iterator = (CurrentAnonymousMethod != null) &&
+ CurrentAnonymousMethod.IsIterator && InIterator;
+
if ((block != null) && block.IsDestructor) {
// Nothing to do; S.R.E automatically emits a leave.
- } else if (HasReturnLabel || (!unreachable && !InIterator)) {
+ } else if (HasReturnLabel || (!unreachable && !in_iterator)) {
if (ReturnType != null)
ig.Emit (OpCodes.Ldloc, TemporaryReturn ());
ig.Emit (OpCodes.Ret);
// Close pending helper classes if we are the toplevel
//
if (capture_context != null && capture_context.ParentToplevel == null)
- capture_context.CloseHelperClasses ();
+ capture_context.CloseAnonymousHelperClasses ();
}
/// <summary>
CodeGen.SymbolWriter.DefineLocalVariable (name, builder);
}
+ public void BeginScope ()
+ {
+ ig.BeginScope();
+
+ if (CodeGen.SymbolWriter != null)
+ CodeGen.SymbolWriter.OpenScope(ig);
+ }
+
+ public void EndScope ()
+ {
+ ig.EndScope();
+
+ if (CodeGen.SymbolWriter != null)
+ CodeGen.SymbolWriter.CloseScope(ig);
+ }
+
/// <summary>
/// Returns a temporary storage for a variable of type t as
/// a local variable in the current body.
if (!InIterator && !HasReturnLabel)
HasReturnLabel = true;
- }
-
- //
- // Creates a field `name' with the type `t' on the proxy class
- //
- public FieldBuilder MapVariable (string name, Type t)
- {
- if (InIterator)
- return CurrentIterator.MapVariable ("v_", name, t);
-
- throw new Exception ("MapVariable for an unknown state");
}
- public Expression RemapParameter (int idx)
- {
- FieldExpr fe = new FieldExprNoAddress (CurrentIterator.parameter_fields [idx].FieldBuilder, loc);
- fe.InstanceExpression = new ProxyInstance ();
- return fe.DoResolve (this);
- }
-
- public Expression RemapParameterLValue (int idx, Expression right_side)
- {
- FieldExpr fe = new FieldExprNoAddress (CurrentIterator.parameter_fields [idx].FieldBuilder, loc);
- fe.InstanceExpression = new ProxyInstance ();
- return fe.DoResolveLValue (this, right_side);
- }
-
//
// 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 (InIterator){
- if (!IsStatic){
- FieldBuilder this_field = CurrentIterator.this_field.FieldBuilder;
- if (TypeManager.IsValueType (this_field.FieldType))
- ig.Emit (OpCodes.Ldflda, this_field);
- else
- ig.Emit (OpCodes.Ldfld, this_field);
- }
- } else if (capture_context != null && CurrentAnonymousMethod != null){
+ if (capture_context != null && CurrentAnonymousMethod != null){
ScopeInfo si = CurrentAnonymousMethod.Scope;
while (si != null){
if (si.ParentLink != null)
//
public void EmitCapturedVariableInstance (LocalInfo li)
{
- if (RemapToProxy){
- ig.Emit (OpCodes.Ldarg_0);
- return;
- }
-
if (capture_context == null)
throw new Exception ("Calling EmitCapturedContext when there is no capture_context");
OptAttributes.Emit (ec, this);
}
- protected Attribute GetClsCompliantAttribute ()
+ protected Attribute ResolveAttribute (Type a_type)
{
if (OptAttributes == null)
return null;
return null;
EmitContext temp_ec = new EmitContext (RootContext.Tree.Types, Mono.CSharp.Location.Null, null, null, 0, false);
- Attribute a = OptAttributes.Search (TypeManager.cls_compliant_attribute_type, temp_ec);
+ Attribute a = OptAttributes.Search (a_type, temp_ec);
if (a != null) {
a.Resolve (temp_ec);
}
}
}
- public override bool IsClsCompliaceRequired(DeclSpace ds)
+ public override bool IsClsComplianceRequired(DeclSpace ds)
{
return is_cls_compliant;
}
public void ResolveClsCompliance ()
{
- ClsCompliantAttribute = GetClsCompliantAttribute ();
+ ClsCompliantAttribute = ResolveAttribute (TypeManager.cls_compliant_attribute_type);
if (ClsCompliantAttribute == null)
return;
RootContext.StrongNameKeyFile +
"' doesn't have a private key.");
}
- Environment.Exit (1);
+ return null;
}
}
}
else {
Report.Error (1548, "Could not strongname the assembly. File `" +
RootContext.StrongNameKeyFile + "' not found.");
- Environment.Exit (1);
+ return null;
}
return an;
}
public ModuleBuilder Builder;
bool m_module_is_unsafe;
+ public CharSet DefaultCharSet = CharSet.Ansi;
+ public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
+
static string[] attribute_targets = new string [] { "module" };
public ModuleClass (bool is_unsafe)
}
}
- public override bool IsClsCompliaceRequired(DeclSpace ds)
+ public override bool IsClsComplianceRequired(DeclSpace ds)
{
return CodeGen.Assembly.IsClsCompliant;
}
Builder.SetCustomAttribute (customBuilder);
}
+ /// <summary>
+ /// It is called very early therefore can resolve only predefined attributes
+ /// </summary>
+ public void ResolveAttributes ()
+ {
+ Attribute a = ResolveAttribute (TypeManager.default_charset_type);
+ if (a != null) {
+ DefaultCharSet = a.GetCharSetValue ();
+ switch (DefaultCharSet) {
+ case CharSet.Ansi:
+ case CharSet.None:
+ break;
+ case CharSet.Auto:
+ DefaultCharSetType = TypeAttributes.AutoClass;
+ break;
+ case CharSet.Unicode:
+ DefaultCharSetType = TypeAttributes.UnicodeClass;
+ break;
+ default:
+ Report.Error (1724, a.Location, "Value specified for the argument to 'System.Runtime.InteropServices.DefaultCharSetAttribute' is not valid");
+ break;
+ }
+ }
+ }
+
public override string[] ValidAttributeTargets {
get {
return attribute_targets;