2007-10-17 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / mcs / codegen.cs
index c173d1c5971b3a2c444d78d7a48226a71fae8df8..c94a61772f490f90dd39d4eab2b5b2a219205f19 100644 (file)
@@ -8,9 +8,14 @@
 // (C) 2004 Novell, Inc.
 //
 
-#if !DEBUG
-       #define PRODUCTION
-#endif
+//
+// Please leave this defined on SVN: The idea is that when we ship the
+// compiler to end users, if the compiler crashes, they have a chance
+// to narrow down the problem.   
+//
+// Only remove it if you need to debug locally on your tree.
+//
+#define PRODUCTION
 
 using System;
 using System.IO;
@@ -144,6 +149,12 @@ namespace Mono.CSharp {
                                return false;
                        }
 
+#if GMCS_SOURCE
+                       // Get the complete AssemblyName from the builder
+                       // (We need to get the public key and token)
+                       Assembly.Name = Assembly.Builder.GetName ();
+#endif
+
                        //
                        // Pass a path-less name to DefineDynamicModule.  Wonder how
                        // this copes with output in different directories then.
@@ -193,6 +204,14 @@ namespace Mono.CSharp {
                DeclSpace DeclContainer { get; }
                bool IsInObsoleteScope { get; }
                bool IsInUnsafeScope { get; }
+
+               // the declcontainer to lookup for type-parameters.  Should only use LookupGeneric on it.
+               //
+               // FIXME: This is somewhat of a hack.  We don't need a full DeclSpace for this.  We just need the
+               //        current type parameters in scope. IUIC, that will require us to rewrite GenericMethod.
+               //        Maybe we can replace this with a 'LookupGeneric (string)' instead, but we'll have to 
+               //        handle generic method overrides differently
+               DeclSpace GenericDeclContainer { get; }
        }
 
        /// <summary>
@@ -201,12 +220,18 @@ namespace Mono.CSharp {
        /// </summary>
        public class EmitContext : IResolveContext {
 
-               DeclSpace declSpace;
+               //
+               // Holds a varible used during collection or object initialization.
+               //
+               public Expression CurrentInitializerVariable;
+
+               DeclSpace decl_space;
+               
                public DeclSpace TypeContainer;
-               public ILGenerator   ig;
+               public ILGenerator ig;
 
                [Flags]
-               public enum Flags : byte {
+               public enum Flags : int {
                        /// <summary>
                        ///   This flag tracks the `checked' state of the compilation,
                        ///   it controls whether we should generate code that does overflow
@@ -245,7 +270,19 @@ namespace Mono.CSharp {
                        ///   Whether control flow analysis is disabled on structs
                        ///   (only meaningful when DoFlowAnalysis is set)
                        /// </summary>
-                       OmitStructFlowAnalysis = 1 << 6
+                       OmitStructFlowAnalysis = 1 << 6,
+
+                       ///
+                       /// Indicates the current context is in probing mode, no errors are reported. 
+                       ///
+                       ProbingMode = 1 <<      7,
+
+                       //
+                       // Inside field intializer expression
+                       //
+                       InFieldInitializer = 1 << 8,
+                       
+                       InferReturnType = 1 << 9
                }
 
                Flags flags;
@@ -265,16 +302,11 @@ namespace Mono.CSharp {
                /// </summary>
                public bool MethodIsStatic;
 
-               /// <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.
                /// </summary>
-               public Type ReturnType;
+               Type return_type;
 
                /// <summary>
                ///   Points to the Type (extracted from the TypeContainer) that
@@ -319,8 +351,6 @@ namespace Mono.CSharp {
                /// </summary>
                public bool InIterator;
 
-               public bool IsLastStatement;
-
                /// <summary>
                ///  Whether we are in a `fixed' initialization
                /// </summary>
@@ -346,19 +376,14 @@ namespace Mono.CSharp {
                /// </summary>
                public bool InEnumContext;
 
-               /// <summary>
-               ///   Anonymous methods can capture local variables and fields,
-               ///   this object tracks it.  It is copied from the TopLevelBlock
-               ///   field.
-               /// </summary>
-               public CaptureContext capture_context;
-
                public readonly IResolveContext ResolveContext;
 
                /// <summary>
                ///    The current iterator
                /// </summary>
-               public Iterator CurrentIterator;
+               public Iterator CurrentIterator {
+                       get { return CurrentAnonymousMethod as Iterator; }
+               }
 
                /// <summary>
                ///    Whether we are in the resolving stage or not
@@ -369,6 +394,8 @@ namespace Mono.CSharp {
                        Emitting
                }
 
+               public static EmitContext TempEc;
+               
                bool isAnonymousMethodAllowed = true;
 
                Phase current_phase;
@@ -379,8 +406,8 @@ namespace Mono.CSharp {
 
                public override string ToString ()
                {
-                       return String.Format ("EmitContext ({0}:{1}:{2})", id,
-                                             CurrentIterator, capture_context, loc);
+                       return String.Format ("EmitContext ({0}:{1})", id,
+                                             CurrentAnonymousMethod, loc);
                }
                
                public EmitContext (IResolveContext rc, DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig,
@@ -390,11 +417,18 @@ namespace Mono.CSharp {
                        this.ig = ig;
 
                        TypeContainer = parent;
-                       this.declSpace = ds;
+                       this.decl_space = ds;
                        if (RootContext.Checked)
                                flags |= Flags.CheckState;
                        flags |= Flags.ConstantCheckState;
 
+                       if (return_type == null)
+                               throw new ArgumentNullException ("return_type");
+#if GMCS_SOURCE
+                       if ((return_type is TypeBuilder) && return_type.IsGenericTypeDefinition)
+                               throw new InternalErrorException ();
+#endif
+
                        IsStatic = (code_flags & Modifiers.STATIC) != 0;
                        MethodIsStatic = IsStatic;
                        InIterator = (code_flags & Modifiers.METHOD_YIELDS) != 0;
@@ -411,9 +445,6 @@ namespace Mono.CSharp {
                                        flags |= Flags.InUnsafe;
                        }
                        loc = l;
-
-                       if (ReturnType == TypeManager.void_type)
-                               ReturnType = null;
                }
 
                public EmitContext (IResolveContext rc, DeclSpace ds, Location l, ILGenerator ig,
@@ -429,8 +460,12 @@ namespace Mono.CSharp {
                }
 
                public DeclSpace DeclContainer { 
-                       get { return declSpace; }
-                       set { declSpace = value; }
+                       get { return decl_space; }
+                       set { decl_space = value; }
+               }
+
+               public DeclSpace GenericDeclContainer {
+                       get { return DeclContainer; }
                }
 
                public bool CheckState {
@@ -466,21 +501,39 @@ namespace Mono.CSharp {
                public struct FlagsHandle : IDisposable
                {
                        EmitContext ec;
-                       Flags invmask, oldval;
+                       readonly Flags invmask, oldval;
+
+                       public FlagsHandle (EmitContext ec, Flags flagsToSet)
+                               : this (ec, flagsToSet, flagsToSet)
+                       {
+                       }
+
                        internal FlagsHandle (EmitContext ec, Flags mask, Flags val)
                        {
                                this.ec = ec;
                                invmask = ~mask;
                                oldval = ec.flags & mask;
                                ec.flags = (ec.flags & invmask) | (val & mask);
+
+                               if ((mask & Flags.ProbingMode) != 0)
+                                       Report.DisableReporting ();
                        }
+
                        public void Dispose ()
                        {
+                               if ((invmask & Flags.ProbingMode) == 0)
+                                       Report.EnableReporting ();
+
                                ec.flags = (ec.flags & invmask) | oldval;
                        }
                }
 
                // Temporarily set all the given flags to the given value.  Should be used in an 'using' statement
+               public FlagsHandle Set (Flags flagsToSet)
+               {
+                       return new FlagsHandle (this, flagsToSet);
+               }
+
                public FlagsHandle With (Flags bits, bool enable)
                {
                        return new FlagsHandle (this, bits, enable ? bits : 0);
@@ -493,9 +546,26 @@ namespace Mono.CSharp {
                                (omit_struct_analysis ? Flags.OmitStructFlowAnalysis : 0);
                        return new FlagsHandle (this, Flags.DoFlowAnalysis | Flags.OmitStructFlowAnalysis, newflags);
                }
+               
+               /// <summary>
+               ///   If this is true, then Return and ContextualReturn statements
+               ///   will set the ReturnType value based on the expression types
+               ///   of each return statement instead of the method return type
+               ///   (which is initially null).
+               /// </summary>
+               public bool InferReturnType {
+                       get { return (flags & Flags.InferReturnType) != 0; }
+               }
 
                public bool IsInObsoleteScope {
-                       get { return ResolveContext.IsInObsoleteScope; }
+                       get {
+                               // Disables obsolete checks when probing is on
+                               return IsInProbingMode || ResolveContext.IsInObsoleteScope;
+                       }
+               }
+
+               public bool IsInProbingMode {
+                       get { return (flags & Flags.ProbingMode) != 0; }
                }
 
                public bool IsInUnsafeScope {
@@ -507,18 +577,12 @@ namespace Mono.CSharp {
                        set { isAnonymousMethodAllowed = value; }
                }
 
-               public FlowBranching CurrentBranching {
-                       get { return current_flow_branching; }
+               public bool IsInFieldInitializer {
+                       get { return (flags & Flags.InFieldInitializer) != 0; }
                }
 
-               public bool HaveCaptureInfo {
-                       get { return capture_context != null; }
-               }
-
-               public void EmitScopeInitFromBlock (Block b)
-               {
-                       if (capture_context != null)
-                               capture_context.EmitScopeInitFromBlock (this, b);
+               public FlowBranching CurrentBranching {
+                       get { return current_flow_branching; }
                }
 
                // <summary>
@@ -588,11 +652,11 @@ namespace Mono.CSharp {
                //   Ends a code branching.  Merges the state of locals and parameters
                //   from all the children of the ending branching.
                // </summary>
-               public FlowBranching.Reachability EndFlowBranching ()
+               public bool EndFlowBranching ()
                {
                        FlowBranching.UsageVector vector = DoEndFlowBranching ();
 
-                       return vector.Reachability;
+                       return vector.IsUnreachable;
                }
 
                // <summary>
@@ -604,84 +668,17 @@ namespace Mono.CSharp {
                        current_flow_branching = current_flow_branching.Parent;
                }
 
-               public void CaptureVariable (LocalInfo li)
-               {
-                       capture_context.AddLocal (CurrentAnonymousMethod, li);
-                       li.IsCaptured = true;
-               }
-
-               public void CaptureParameter (string name, Type t, int idx)
+               public bool MustCaptureVariable (LocalInfo local)
                {
-                       capture_context.AddParameter (this, CurrentAnonymousMethod, name, t, idx);
-               }
-
-               public void CaptureThis ()
-               {
-                       capture_context.CaptureThis (CurrentAnonymousMethod);
-               }
-               
-               
-               //
-               // Use to register a field as captured
-               //
-               public void CaptureField (FieldExpr fe)
-               {
-                       capture_context.AddField (this, CurrentAnonymousMethod, fe);
-               }
-
-               //
-               // Whether anonymous methods have captured variables
-               //
-               public bool HaveCapturedVariables ()
-               {
-                       if (capture_context != null)
-                               return capture_context.HaveCapturedVariables;
-                       return false;
-               }
-
-               //
-               // Whether anonymous methods have captured fields or this.
-               //
-               public bool HaveCapturedFields ()
-               {
-                       if (capture_context != null)
-                               return capture_context.HaveCapturedFields;
-                       return false;
-               }
-
-               //
-               // Emits the instance pointer for the host method
-               //
-               public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)
-               {
-                       if (capture_context != null)
-                               capture_context.EmitMethodHostInstance (target, am);
-                       else if (IsStatic)
-                               target.ig.Emit (OpCodes.Ldnull);
-                       else
-                               target.ig.Emit (OpCodes.Ldarg_0);
-               }
-
-               //
-               // Returns whether the `local' variable has been captured by an anonymous
-               // method
-               //
-               public bool IsCaptured (LocalInfo local)
-               {
-                       return capture_context.IsCaptured (local);
-               }
-
-               public bool IsParameterCaptured (string name)
-               {
-                       if (capture_context != null)
-                               return capture_context.IsParameterCaptured (name);
-                       return false;
+                       if (CurrentAnonymousMethod == null)
+                               return false;
+                       if (CurrentAnonymousMethod.IsIterator)
+                               return true;
+                       return local.Block.Toplevel != CurrentBlock.Toplevel;
                }
                
                public void EmitMeta (ToplevelBlock b)
                {
-                       if (capture_context != null)
-                               capture_context.EmitAnonymousHelperClasses (this);
                        b.EmitMeta (this);
 
                        if (HasReturnLabel)
@@ -701,6 +698,9 @@ namespace Mono.CSharp {
                        bool unreachable;
                        
                        if (ResolveTopBlock (null, block, md.ParameterInfo, md, out unreachable)){
+                               if (Report.Errors > 0)
+                                       return;
+
                                EmitMeta (block);
 
                                current_phase = Phase.Emitting;
@@ -720,8 +720,6 @@ namespace Mono.CSharp {
                        if (resolved)
                                return true;
 
-                       capture_context = block.CaptureContext;
-                       
                        if (!loc.IsNull)
                                CurrentFile = loc.File;
 
@@ -731,6 +729,11 @@ namespace Mono.CSharp {
                                if (!block.ResolveMeta (this, ip))
                                        return false;
 
+                               if ((md != null) && (md.Iterator != null)) {
+                                       if (!md.Iterator.Define (this))
+                                               return false;
+                               }
+
                                using (this.With (EmitContext.Flags.DoFlowAnalysis, true)) {
                                        FlowBranchingToplevel top_level;
                                        if (anonymous_method_host != null)
@@ -745,8 +748,8 @@ namespace Mono.CSharp {
                                        if (!ok)
                                                return false;
 
-                                       FlowBranching.Reachability reachability = top_level.End ();
-                                       if (reachability.IsUnreachable)
+                                       bool flow_unreachable = top_level.End ();
+                                       if (flow_unreachable)
                                                unreachable = true;
                                }
 #if PRODUCTION
@@ -763,30 +766,41 @@ namespace Mono.CSharp {
                        }
 #endif
 
-                       if (ReturnType != null && !unreachable) {
+                       if (return_type != TypeManager.void_type && !unreachable) {
                                if (CurrentAnonymousMethod == null) {
                                        Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ());
                                        return false;
                                } else if (!CurrentAnonymousMethod.IsIterator) {
                                        Report.Error (1643, CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
-                                               CurrentAnonymousMethod.GetSignatureForError ());
+                                                     CurrentAnonymousMethod.GetSignatureForError ());
                                        return false;
                                }
                        }
 
-                       block.CompleteContexts ();
+                       if (!block.CompleteContexts (this))
+                               return false;
+
                        resolved = true;
                        return true;
                }
 
+               public Type ReturnType {
+                       set {
+                               return_type = value;
+                       }
+                       get {
+                               return return_type;
+                       }
+               }
+
                public void EmitResolvedTopBlock (ToplevelBlock block, bool unreachable)
                {
                        if (block != null)
                                block.Emit (this);
-                       
+
                        if (HasReturnLabel)
                                ig.MarkLabel (ReturnLabel);
-                       
+
                        if (return_value != null){
                                ig.Emit (OpCodes.Ldloc, return_value);
                                ig.Emit (OpCodes.Ret);
@@ -810,17 +824,11 @@ namespace Mono.CSharp {
                                if ((block != null) && block.IsDestructor) {
                                        // Nothing to do; S.R.E automatically emits a leave.
                                } else if (HasReturnLabel || (!unreachable && !in_iterator)) {
-                                       if (ReturnType != null)
+                                       if (return_type != TypeManager.void_type)
                                                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.CloseAnonymousHelperClasses ();
                }
 
                /// <summary>
@@ -939,7 +947,7 @@ namespace Mono.CSharp {
                public LocalBuilder TemporaryReturn ()
                {
                        if (return_value == null){
-                               return_value = ig.DeclareLocal (ReturnType);
+                               return_value = ig.DeclareLocal (return_type);
                                if (!HasReturnLabel){
                                        ReturnLabel = ig.DefineLabel ();
                                        HasReturnLabel = true;
@@ -967,57 +975,7 @@ namespace Mono.CSharp {
                                HasReturnLabel = true;
                }
 
-               //
-               // Emits the proper object to address fields on a remapped
-               // variable/parameter to field in anonymous-method/iterator proxy classes.
-               //
-               public void EmitThis (bool need_address)
-               {
-                       ig.Emit (OpCodes.Ldarg_0);
-                       if (capture_context != null && CurrentAnonymousMethod != null){
-                               ScopeInfo si = CurrentAnonymousMethod.Scope;
-                               while (si != null){
-                                       if (si.ParentLink != null)
-                                               ig.Emit (OpCodes.Ldfld, si.ParentLink);
-                                       if (si.THIS != null){
-                                               if (need_address && TypeManager.IsValueType (si.THIS.FieldType))
-                                                       ig.Emit (OpCodes.Ldflda, si.THIS);
-                                               else
-                                                       ig.Emit (OpCodes.Ldfld, si.THIS);
-                                               break;
-                                       }
-                                       si = si.ParentScope;
-                               }
-                       } 
-               }
-
-               //
-               // Emits the code necessary to load the instance required
-               // to access the captured LocalInfo
-               //
-               public void EmitCapturedVariableInstance (LocalInfo li)
-               {
-                       if (capture_context == null)
-                               throw new Exception ("Calling EmitCapturedContext when there is no capture_context");
-                       
-                       capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod);
-               }
-
-               public void EmitParameter (string name, bool leave_copy, bool prepared, ref LocalTemporary temp)
-               {
-                       capture_context.EmitParameter (this, name, leave_copy, prepared, ref temp);
-               }
-
-               public void EmitAssignParameter (string name, Expression source, bool leave_copy, bool prepare_for_load, ref LocalTemporary  temp)
-               {
-                       capture_context.EmitAssignParameter (this, name, source, leave_copy, prepare_for_load, ref temp);
-               }
 
-               public void EmitAddressOfParameter (string name)
-               {
-                       capture_context.EmitAddressOfParameter (this, name);
-               }
-               
                public Expression GetThis (Location loc)
                {
                        This my_this;
@@ -1060,16 +1018,9 @@ namespace Mono.CSharp {
 
                        OptAttributes.Emit ();
                }
-                
+
                protected Attribute ResolveAttribute (Type a_type)
                {
-                       if (OptAttributes == null)
-                               return null;
-
-                       // Ensure that we only have GlobalAttributes, since the Search below isn't safe with other types.
-                       if (!OptAttributes.CheckTargets ())
-                               return null;
-
                        Attribute a = OptAttributes.Search (a_type);
                        if (a != null) {
                                a.Resolve ();
@@ -1087,6 +1038,10 @@ namespace Mono.CSharp {
                        get { return RootContext.ToplevelTypes; }
                }
 
+               public DeclSpace GenericDeclContainer {
+                       get { return DeclContainer; }
+               }
+
                public bool IsInObsoleteScope {
                        get { return false; }
                }
@@ -1107,13 +1062,29 @@ namespace Mono.CSharp {
                public Attribute ClsCompliantAttribute;
 
                ListDictionary declarative_security;
+#if GMCS_SOURCE
+               bool has_extension_method;              
+               public AssemblyName Name;
+               MethodInfo add_type_forwarder;
+               ListDictionary emitted_forwarders;
+#endif
 
                // Module is here just because of error messages
                static string[] attribute_targets = new string [] { "assembly", "module" };
 
                public AssemblyClass (): base ()
                {
+#if GMCS_SOURCE
                        wrap_non_exception_throws = true;
+#endif
+               }
+
+               public bool HasExtensionMethods {
+                       set {
+#if GMCS_SOURCE                                
+                               has_extension_method = value;
+#endif
+                       }
                }
 
                public bool IsClsCompliant {
@@ -1141,12 +1112,19 @@ namespace Mono.CSharp {
 
                public void Resolve ()
                {
+                       if (OptAttributes == null)
+                               return;
+
+                       // Ensure that we only have GlobalAttributes, since the Search isn't safe with other types.
+                       if (!OptAttributes.CheckTargets())
+                               return;
+
                        ClsCompliantAttribute = ResolveAttribute (TypeManager.cls_compliant_attribute_type);
                        if (ClsCompliantAttribute != null) {
                                is_cls_compliant = ClsCompliantAttribute.GetClsCompliantAttributeValue ();
                        }
 
-#if NET_2_0
+#if GMCS_SOURCE
                        Attribute a = ResolveAttribute (TypeManager.runtime_compatibility_attr_type);
                        if (a != null) {
                                object val = a.GetPropertyValue ("WrapNonExceptionThrows");
@@ -1306,6 +1284,54 @@ namespace Mono.CSharp {
                        Report.Error (1548, "Error during assembly signing. " + text);
                }
 
+#if GMCS_SOURCE
+               bool CheckInternalsVisibleAttribute (Attribute a)
+               {
+                       string assembly_name = a.GetString ();
+                       if (assembly_name.Length == 0)
+                               return false;
+                               
+                       AssemblyName aname = null;
+                       try {
+                               aname = new AssemblyName (assembly_name);
+                       } catch (FileLoadException) {
+                       } catch (ArgumentException) {
+                       }
+                               
+                       // Bad assembly name format
+                       if (aname == null)
+                               Report.Warning (1700, 3, a.Location, "Assembly reference `" + assembly_name + "' is invalid and cannot be resolved");
+                       // Report error if we have defined Version or Culture
+                       else if (aname.Version != null || aname.CultureInfo != null)
+                               throw new Exception ("Friend assembly `" + a.GetString () + 
+                                               "' is invalid. InternalsVisibleTo cannot have version or culture specified.");
+                       else if (aname.GetPublicKey () == null && Name.GetPublicKey () != null) {
+                               Report.Error (1726, a.Location, "Friend assembly reference `" + aname.FullName + "' is invalid." +
+                                               " Strong named assemblies must specify a public key in their InternalsVisibleTo declarations");
+                               return false;
+                       }
+
+                       return true;
+               }
+#endif
+
+               static bool IsValidAssemblyVersion (string version)
+               {
+                       Version v;
+                       try {
+                               v = new Version (version);
+                       } catch {
+                               return false;
+                       }
+
+                       foreach (int candidate in new int [] { v.Major, v.Minor, v.Build, v.Revision }) {
+                               if (candidate > ushort.MaxValue)
+                                       return false;
+                       }
+
+                       return true;
+               }
+
                public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder)
                {
                        if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (true)) {
@@ -1327,6 +1353,78 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       if (a.Type == TypeManager.assembly_version_attribute_type) {
+                               string value = a.GetString ();
+                               if (value == null || value.Length == 0)
+                                       return;
+
+                               value = value.Replace ('*', '0');
+
+                               if (!IsValidAssemblyVersion (value)) {
+                                       a.Error_AttributeEmitError (string.Format ("Specified version `{0}' is not valid", value));
+                                       return;
+                               }
+                       }
+
+#if GMCS_SOURCE
+                       if (a.Type == TypeManager.internals_visible_attr_type && !CheckInternalsVisibleAttribute (a))
+                               return;
+
+                       if (a.Type == TypeManager.type_forwarder_attr_type) {
+                               Type t = a.GetArgumentType ();
+                               if (t == null || TypeManager.HasElementType (t)) {
+                                       Report.Error (735, a.Location, "Invalid type specified as an argument for TypeForwardedTo attribute");
+                                       return;
+                               }
+
+                               if (emitted_forwarders == null) {
+                                       emitted_forwarders = new ListDictionary();
+                               } else if (emitted_forwarders.Contains(t)) {
+                                       Report.SymbolRelatedToPreviousError(((Attribute)emitted_forwarders[t]).Location, null);
+                                       Report.Error(739, a.Location, "A duplicate type forward of type `{0}'",
+                                               TypeManager.CSharpName(t));
+                                       return;
+                               }
+
+                               emitted_forwarders.Add(t, a);
+
+                               if (TypeManager.LookupDeclSpace (t) != null) {
+                                       Report.SymbolRelatedToPreviousError (t);
+                                       Report.Error (729, a.Location, "Cannot forward type `{0}' because it is defined in this assembly",
+                                               TypeManager.CSharpName (t));
+                                       return;
+                               }
+
+                               if (t.IsNested) {
+                                       Report.Error (730, a.Location, "Cannot forward type `{0}' because it is a nested type",
+                                               TypeManager.CSharpName (t));
+                                       return;
+                               }
+
+                               if (t.IsGenericType) {
+                                       Report.Error (733, a.Location, "Cannot forward generic type `{0}'", TypeManager.CSharpName (t));
+                                       return;
+                               }
+
+                               if (add_type_forwarder == null) {
+                                       add_type_forwarder = typeof (AssemblyBuilder).GetMethod ("AddTypeForwarder",
+                                               BindingFlags.NonPublic | BindingFlags.Instance);
+
+                                       if (add_type_forwarder == null) {
+                                               Report.RuntimeMissingSupport (a.Location, "TypeForwardedTo attribute");
+                                               return;
+                                       }
+                               }
+
+                               add_type_forwarder.Invoke (Builder, new object[] { t });
+                               return;
+                       }
+                       
+                       if (a.Type == TypeManager.extension_attribute_type) {
+                               a.Error_MisusedExtensionAttribute ();
+                               return;
+                       }
+#endif
                        Builder.SetCustomAttribute (customBuilder);
                }
 
@@ -1334,6 +1432,23 @@ namespace Mono.CSharp {
                {
                        base.Emit (tc);
 
+#if GMCS_SOURCE
+                       if (has_extension_method)
+                               Builder.SetCustomAttribute (TypeManager.extension_attribute_attr);
+
+                       // FIXME: Does this belong inside SRE.AssemblyBuilder instead?
+                       if (OptAttributes == null || !OptAttributes.Contains (TypeManager.runtime_compatibility_attr_type)) {
+                               ConstructorInfo ci = TypeManager.GetConstructor (
+                                       TypeManager.runtime_compatibility_attr_type, Type.EmptyTypes);
+                               PropertyInfo [] pis = new PropertyInfo [1];
+                               pis [0] = TypeManager.GetProperty (
+                                       TypeManager.runtime_compatibility_attr_type, "WrapNonExceptionThrows");
+                               object [] pargs = new object [1];
+                               pargs [0] = true;
+                               Builder.SetCustomAttribute (new CustomAttributeBuilder (ci, new object [0], pis, pargs));
+                       }
+#endif
+
                        if (declarative_security != null) {
 
                                MethodInfo add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic);
@@ -1365,12 +1480,37 @@ namespace Mono.CSharp {
                                return attribute_targets;
                        }
                }
+
+               // Wrapper for AssemblyBuilder.AddModule
+               static MethodInfo adder_method;
+               static public MethodInfo AddModule_Method {
+                       get {
+                               if (adder_method == null)
+                                       adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.NonPublic);
+                               return adder_method;
+                       }
+               }
+               public Module AddModule (string module)
+               {
+                       MethodInfo m = AddModule_Method;
+                       if (m == null) {
+                               Report.RuntimeMissingSupport (Location.Null, "/addmodule");
+                               Environment.Exit (1);
+                       }
+
+                       try {
+                               return (Module) m.Invoke (Builder, new object [] { module });
+                       } catch (TargetInvocationException ex) {
+                               throw ex.InnerException;
+                       }
+               }               
        }
 
        public class ModuleClass : CommonAssemblyModulClass {
                // TODO: make it private and move all builder based methods here
                public ModuleBuilder Builder;
                bool m_module_is_unsafe;
+               bool has_default_charset;
 
                public CharSet DefaultCharSet = CharSet.Ansi;
                public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
@@ -1424,14 +1564,27 @@ namespace Mono.CSharp {
                        Builder.SetCustomAttribute (customBuilder);
                }
 
+               public bool HasDefaultCharSet {
+                       get {
+                               return has_default_charset;
+                       }
+               }
+
                /// <summary>
                /// It is called very early therefore can resolve only predefined attributes
                /// </summary>
-               public void ResolveAttributes ()
+               public void Resolve ()
                {
-#if NET_2_0
+#if GMCS_SOURCE
+                       if (OptAttributes == null)
+                               return;
+
+                       if (!OptAttributes.CheckTargets())
+                               return;
+
                        Attribute a = ResolveAttribute (TypeManager.default_charset_type);
                        if (a != null) {
+                               has_default_charset = true;
                                DefaultCharSet = a.GetCharSetValue ();
                                switch (DefaultCharSet) {
                                        case CharSet.Ansi: