using System.Collections;
using System.Security;
+using Mono.CompilerServices.SymbolWriter;
+
namespace Mono.ILASM {
public class MethodDef : ICustomAttrTarget, IDeclSecurityTarget {
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;
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;
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;
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;
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;
}
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
*/
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;
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)
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);
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;
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;
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 ("...");
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);
builder.Append (',');
builder.Append (param.FullName);
first = false;
- if (param is SentinelTypeRef)
+ if (!include_optional && param is SentinelTypeRef)
break;
}
}