Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / ilasm / codegen / MethodDef.cs
index 152113cc418fa2f5e484a7c15f8c88e0551120b5..4e9d31c062899719be178ea0528ac3564026a69a 100644 (file)
@@ -13,6 +13,8 @@ using System.Text;
 using System.Collections;
 using System.Security;
 
+using Mono.CompilerServices.SymbolWriter;
+
 namespace Mono.ILASM {
 
         public class MethodDef : ICustomAttrTarget, IDeclSecurityTarget {
@@ -37,7 +39,8 @@ namespace Mono.ILASM {
                 private bool is_resolved;
                 private bool is_defined;
                 private ArrayList local_list;
-                private Hashtable named_local_table;
+                private ArrayList named_local_tables;
+                private int current_scope_depth;
                 private bool init_locals;
                 private int max_stack;
                 private bool pinvoke_info;
@@ -48,12 +51,14 @@ namespace Mono.ILASM {
                 private TypeDef type_def;
                 private GenericParameters gen_params;
                 private Location start;
+                private CodeGen codegen;
 
                 public MethodDef (CodeGen codegen, PEAPI.MethAttr meth_attr,
                                  PEAPI.CallConv call_conv, PEAPI.ImplAttr impl_attr,
                                  string name, BaseTypeRef ret_type, ArrayList param_list,
                                  Location start, GenericParameters gen_params, TypeDef type_def)
                 {
+                        this.codegen = codegen;
                         this.meth_attr = meth_attr;
                         this.call_conv = call_conv;
                         this.impl_attr = impl_attr;
@@ -69,7 +74,9 @@ namespace Mono.ILASM {
                         labelref_table = new Hashtable ();
                         label_list = new ArrayList ();
                         local_list = new ArrayList ();
-                        named_local_table = new Hashtable ();
+                        named_local_tables = new ArrayList ();
+                        named_local_tables.Add (new Hashtable ());
+                        current_scope_depth = 0;
 
                         entry_point = false;
                         zero_init = false;
@@ -211,10 +218,26 @@ namespace Mono.ILASM {
                         this.ret_param.AddMarshalInfo (native_type);
                 }
 
+                //try/catch scope, used to scope local vars
+                public void BeginLocalsScope ()
+                {
+                        current_scope_depth ++;
+                        named_local_tables.Add (new Hashtable ());
+                }
+
+                public void EndLocalsScope ()
+                {
+                        named_local_tables.RemoveAt (current_scope_depth);
+                        current_scope_depth --;
+                }
+
                 public void AddLocals (ArrayList local_list)
                 {
                         int slot_pos = this.local_list.Count;
 
+                        Hashtable current_named_table = null;
+                        current_named_table = (Hashtable) named_local_tables [current_scope_depth];
+
                         foreach (Local local in local_list) {
                                 if (local.Slot == -1) {
                                         local.Slot = slot_pos;
@@ -222,21 +245,33 @@ namespace Mono.ILASM {
                                 slot_pos++;
                                 if (local.Name == null)
                                         continue;
-                               if(!named_local_table.Contains(local.Name))
-                                 named_local_table.Add (local.Name, local);
-                        }
+
+                                if (!current_named_table.Contains (local.Name))
+                                        current_named_table.Add (local.Name, local);
+                         }
 
                         this.local_list.AddRange (local_list);
                 }
 
                 public Local GetNamedLocal (string name)
                 {
-                        return (Local) named_local_table[name];
+                        Local ret = null;
+                        int i = current_scope_depth;
+                        while (ret == null && i >= 0) {
+                                Hashtable current_named_table = (Hashtable) named_local_tables [i];
+                                ret = (Local) current_named_table [name];
+
+                                i --;
+                        }
+
+                        return ret;
                 }
 
                 public int GetNamedLocalSlot (string name)
                 {
-                        Local local = (Local) named_local_table[name];
+                        Local local = GetNamedLocal (name);
+                        if (local == null)
+                                return -1;
 
                         return local.Slot;
                 }
@@ -258,6 +293,18 @@ namespace Mono.ILASM {
                         return pos;
                 }
 
+                public LocalVariableEntry[] GetLocalVars()
+                {
+                        ArrayList named_locals = new ArrayList ();
+                        foreach (Local local in local_list) {
+                                if (local.Name != null) {  // only named variables
+                                        named_locals.Add (new LocalVariableEntry(local.Slot, local.Name, 0));
+                                }
+                        }
+                        return (LocalVariableEntry []) named_locals.ToArray (typeof (LocalVariableEntry));
+                }
+
+
                 /* index - 0: return type
                  *         1: params start from this
                  */
@@ -394,27 +441,22 @@ namespace Mono.ILASM {
                         return param_array;
                 }
 
-                public PEAPI.MethodRef GetVarargSig (PEAPI.Type[] opt)
+                public PEAPI.MethodRef GetVarargSig (PEAPI.Type[] opt, string full_signature)
                 {
                         if (!is_resolved)
                                 throw new InternalErrorException ("Methods must be resolved before a vararg sig can be created.");
 
                         PEAPI.MethodRef methref = null;
-                        StringBuilder sigbuilder = new StringBuilder ();
-                        string sig;
-                        foreach (PEAPI.Type t in opt)
-                                sigbuilder.Append (opt + ", ");
-                        sig = sigbuilder.ToString ();
-
                         if (vararg_sig_table == null) {
                                 vararg_sig_table = new Hashtable ();                                
                         } else {
-                                methref = vararg_sig_table [sig] as PEAPI.MethodRef;
+                                methref = vararg_sig_table [full_signature] as PEAPI.MethodRef;
                         }
 
                         if (methref == null) {
                                 methref = methoddef.MakeVarArgSignature (opt);
-                                vararg_sig_table [sig] = methref;
+                                methref.AddCallConv (call_conv);
+                                vararg_sig_table [full_signature] = methref;
                         }
 
                         return methref;
@@ -558,7 +600,7 @@ namespace Mono.ILASM {
 
                         foreach (LabelInfo label in label_info) {
                                 if (label.UseOffset) {
-                                        label.Define (new PEAPI.CILLabel (label.Offset));
+                                        label.Define (new PEAPI.CILLabel (label.Offset, true));
                                         continue;
                                 }
                                 if (label.Pos == previous_pos)
@@ -666,13 +708,16 @@ namespace Mono.ILASM {
                         if (IsVararg)
                                 signature = CreateVarargSignature (RetType, name, param_list);
                         else
-                                signature = CreateSignature (RetType, name, param_list, GenParamCount);
+                                signature = CreateSignature (RetType, name, param_list, GenParamCount, Attributes);
                 }
 
-                public static string CreateSignature (BaseTypeRef RetType, string name, IList param_list, int gen_param_count)
+                               static string CreateSignature (BaseTypeRef RetType, string name, IList param_list, int gen_param_count, PEAPI.MethAttr attrs)
                 {
                         StringBuilder builder = new StringBuilder ();
 
+                                               if ((attrs & PEAPI.MethAttr.Static) == 0)
+                                                       builder.Append ("instance ");
+
                        builder.Append (RetType.FullName);
                        builder.Append (" ");
                         builder.Append (name);
@@ -694,7 +739,7 @@ namespace Mono.ILASM {
                         return builder.ToString ();
                 }
 
-                public static string CreateVarargSignature (BaseTypeRef RetType, string name, IList param_list)
+                static string CreateVarargSignature (BaseTypeRef RetType, string name, IList param_list)
                 {
                         StringBuilder builder = new StringBuilder ();
                         ParamDef last = null;
@@ -727,7 +772,19 @@ namespace Mono.ILASM {
                         return builder.ToString ();
                 }
 
-                public static string CreateVarargSignature (BaseTypeRef RetType, string name, BaseTypeRef [] param_list)
+                // @include_optional: include optional parameters for vararg methods
+                // This will be true mostly for *Ref use, eg. methodrefs at call sites
+                // and false for *Def (include only the required params)
+                public static string CreateSignature (BaseTypeRef RetType, PEAPI.CallConv call_conv, string name,
+                                BaseTypeRef[] param_list, int gen_param_count, bool include_optional)
+                {
+                        if ((call_conv & PEAPI.CallConv.Vararg) != 0)
+                                return CreateVarargSignature (RetType, name, param_list, include_optional);
+                        else
+                                return CreateSignature (RetType, name, param_list, gen_param_count, include_optional, call_conv);
+                }
+
+                               static string CreateVarargSignature (BaseTypeRef RetType, string name, BaseTypeRef [] param_list, bool include_optional)
                 {
                         StringBuilder builder = new StringBuilder ();
                         BaseTypeRef last = null;
@@ -745,13 +802,13 @@ namespace Mono.ILASM {
                                         builder.Append (param.FullName);
                                         first = false;
                                         last = param;
-                                        if (param is SentinelTypeRef)
+                                        if (!include_optional && param is SentinelTypeRef)
                                                 break;
                                 }
                                 
                         }
                         
-                        if (last == null || !(last is SentinelTypeRef)) {
+                        if (!include_optional && (last == null || !(last is SentinelTypeRef))) {
                                 if (!first)
                                         builder.Append (',');
                                 builder.Append ("...");
@@ -762,10 +819,14 @@ namespace Mono.ILASM {
                         return builder.ToString ();
                 }
 
-                public static string CreateSignature (BaseTypeRef RetType, string name, BaseTypeRef[] param_list, int gen_param_count)
+                               static string CreateSignature (BaseTypeRef RetType, string name, BaseTypeRef[] param_list, int gen_param_count, bool include_optional, PEAPI.CallConv call_conv)
                 {
                         StringBuilder builder = new StringBuilder ();
 
+                                               if ((call_conv & PEAPI.CallConv.Instance) != 0)
+                                                       builder.Append ("instance ");
+
+
                        builder.Append (RetType.FullName);
                        builder.Append (" ");
                         builder.Append (name);
@@ -780,7 +841,7 @@ namespace Mono.ILASM {
                                                 builder.Append (',');
                                         builder.Append (param.FullName);
                                         first = false;
-                                        if (param is SentinelTypeRef)
+                                        if (!include_optional && param is SentinelTypeRef)
                                                 break;
                                 }
                         }