using System;
using System.Text;
using System.Collections;
-
+using System.Security;
namespace Mono.ILASM {
public class MethodDef : ICustomAttrTarget, IDeclSecurityTarget {
- protected class GenericInfo {
- public string Id;
- public ArrayList ConstraintList;
- }
-
private PEAPI.MethAttr meth_attr;
private PEAPI.CallConv call_conv;
private PEAPI.ImplAttr impl_attr;
private string name;
private string signature;
private Hashtable vararg_sig_table;
- private ITypeRef ret_type;
- private ArrayList typar_list;
+ private ParamDef ret_param;
private ArrayList param_list;
private ArrayList inst_list;
private ArrayList customattr_list;
- private ArrayList declsecurity_list;
+ private DeclSecurity decl_sec;
private Hashtable label_table;
private Hashtable labelref_table;
private ArrayList label_list;
private string pinvoke_name;
private PEAPI.PInvokeAttr pinvoke_attr;
private SourceMethod source;
- private PEAPI.NativeType ret_native_type;
+ private TypeDef type_def;
+ private GenericParameters gen_params;
+ private Location start;
public MethodDef (CodeGen codegen, PEAPI.MethAttr meth_attr,
PEAPI.CallConv call_conv, PEAPI.ImplAttr impl_attr,
- string name, ITypeRef ret_type, ArrayList param_list,
- Location start)
+ string name, BaseTypeRef ret_type, ArrayList param_list,
+ Location start, GenericParameters gen_params, TypeDef type_def)
{
this.meth_attr = meth_attr;
this.call_conv = call_conv;
this.impl_attr = impl_attr;
this.name = name;
- this.ret_type = ret_type;
this.param_list = param_list;
+ this.type_def = type_def;
+ this.gen_params = gen_params;
+ this.ret_param = new ParamDef (PEAPI.ParamAttr.Default, "", ret_type);
+ this.start = (Location) start.Clone ();
inst_list = new ArrayList ();
label_table = new Hashtable ();
is_defined = false;
is_resolved = false;
+ ResolveGenParams ();
CreateSignature ();
codegen.BeginMethodDef (this);
get { return signature; }
}
- public ITypeRef RetType {
- get { return ret_type; }
+ public BaseTypeRef RetType {
+ get { return ret_param.Type; }
}
public PEAPI.CallConv CallConv {
get { return (meth_attr & PEAPI.MethAttr.Abstract) != 0; }
}
- public ITypeRef[] ParamTypeList () {
+ public Location StartLocation {
+ get { return start; }
+ }
+
+ public DeclSecurity DeclSecurity {
+ get {
+ if (decl_sec == null)
+ decl_sec = new DeclSecurity ();
+ return decl_sec;
+ }
+ }
+
+ public string FullName {
+ get {
+ if (type_def == null)
+ return Name;
+ return type_def.FullName + "." + Name;
+ }
+ }
+
+ public BaseTypeRef[] ParamTypeList () {
if (param_list == null)
- return new ITypeRef[0];
+ return new BaseTypeRef[0];
int count = 0;
- ITypeRef[] type_list = new ITypeRef[param_list.Count];
+ BaseTypeRef[] type_list = new BaseTypeRef[param_list.Count];
foreach (ParamDef param in param_list) {
type_list[count++] = param.Type;
}
pinvoke_info = true;
}
- public void AddGenericParam (string id)
- {
- if (typar_list == null)
- typar_list = new ArrayList ();
-
- GenericInfo gi = new GenericInfo ();
- gi.Id = id;
-
- typar_list.Add (gi);
+ public int GenParamCount {
+ get { return (gen_params != null ? gen_params.Count : 0); }
}
- public void AddGenericConstraint (int index, ITypeRef constraint)
+ public GenericParameter GetGenericParam (string id)
{
- GenericInfo gi = (GenericInfo) typar_list[index];
+ if (gen_params == null)
+ return null;
+
+ return gen_params.GetGenericParam (id);
+ }
- if (gi.ConstraintList == null)
- gi.ConstraintList = new ArrayList ();
- gi.ConstraintList.Add (constraint);
+ public GenericParameter GetGenericParam (int index)
+ {
+ if (gen_params == null || index < 0 || index >= gen_params.Count)
+ return null;
+
+ return gen_params [index];
}
- public void AddParamDefaultValue (int index, PEAPI.Constant defval)
+ public int GetGenericParamNum (string id)
{
- if (param_list [index] != null) {
- ((ParamDef)param_list [index]).AddDefaultValue (defval);
- }
+ if (gen_params == null)
+ return -1;
+
+ return gen_params.GetGenericParamNum (id);
}
public void AddCustomAttribute (CustomAttr customattr)
customattr_list.Add (customattr);
}
- public void AddDeclSecurity (DeclSecurity declsecurity)
- {
- if (declsecurity_list == null)
- declsecurity_list = new ArrayList ();
-
- declsecurity_list.Add (declsecurity);
- }
-
public void AddRetTypeMarshalInfo (PEAPI.NativeType native_type)
{
- this.ret_native_type = native_type;
+ this.ret_param.AddMarshalInfo (native_type);
}
public void AddLocals (ArrayList local_list)
public int GetNamedParamPos (string name)
{
int pos = -1;
+ if (param_list == null)
+ return -1;
+
if (!IsStatic)
pos ++;
foreach (ParamDef param in param_list) {
return pos;
}
+ /* index - 0: return type
+ * 1: params start from this
+ */
public ParamDef GetParam (int index)
{
+ if (index == 0)
+ return ret_param;
+
+ if ((param_list == null) || (index < 0) || (index > param_list.Count))
+ return null;
+
+ index --; /* param_list has params zero-based */
+
if (param_list [index] != null)
return (ParamDef)param_list [index];
else
public void EntryPoint ()
{
if (!IsStatic)
- throw new Exception ("Non-static method as entrypoint.");
+ Report.Error ("Non-static method as entrypoint.");
entry_point = true;
}
this.max_stack = max_stack;
}
+ public void ResolveGenParam (PEAPI.GenParam gpar)
+ {
+ if (gpar.Index != -1)
+ return;
+
+ if (gpar.Type == PEAPI.GenParamType.MVar)
+ gpar.Index = GetGenericParamNum (gpar.Name);
+ else
+ gpar.Index = type_def.GetGenericParamNum (gpar.Name);
+
+ if (gpar.Index < 0)
+ Report.Error (String.Format ("Invalid {0}type parameter '{1}'",
+ (gpar.Type == PEAPI.GenParamType.MVar ? "method " : ""),
+ gpar.Name));
+ }
+
+ public void ResolveGenParams ()
+ {
+ GenericParameters type_params = (type_def != null) ? type_def.TypeParameters : null;
+
+ if (gen_params == null && type_params == null)
+ return;
+
+ if (gen_params != null)
+ gen_params.ResolveConstraints (type_params, gen_params);
+
+ BaseGenericTypeRef gtr = RetType as BaseGenericTypeRef;
+ if (gtr != null)
+ gtr.Resolve (type_params, gen_params);
+
+ if (param_list == null)
+ return;
+
+ foreach (ParamDef param in param_list) {
+ gtr = param.Type as BaseGenericTypeRef;
+ if (gtr != null)
+ gtr.Resolve (type_params, gen_params);
+ }
+ }
+
public PEAPI.MethodDef Resolve (CodeGen code_gen)
{
return Resolve (code_gen, null);
PEAPI.Param [] param_array = GenerateParams (code_gen);
FixAttributes ();
- ret_type.Resolve (code_gen);
+ ret_param.Define (code_gen);
if (classdef == null)
methoddef = code_gen.PEFile.AddMethod (meth_attr, impl_attr,
- name, ret_type.PeapiType, param_array);
+ name, ret_param.PeapiParam, param_array);
else
methoddef = classdef.AddMethod (meth_attr, impl_attr,
- name, ret_type.PeapiType, param_array);
+ name, ret_param.PeapiParam, param_array);
methoddef.AddCallConv (call_conv);
- if (ret_native_type != null)
- methoddef.AddRetTypeMarshallInfo (ret_native_type);
-
is_resolved = true;
return methoddef;
public PEAPI.MethodRef GetVarargSig (PEAPI.Type[] opt)
{
if (!is_resolved)
- throw new Exception ("Methods must be resolved before a vararg sig can be created.");
+ throw new InternalErrorException ("Methods must be resolved before a vararg sig can be created.");
PEAPI.MethodRef methref = null;
StringBuilder sigbuilder = new StringBuilder ();
return methref;
}
- /// <summary>
- /// Define a global method
- /// </summary>
- public void Define (CodeGen code_gen)
- {
- if (is_defined)
- return;
-
- Resolve (code_gen);
-
- WriteCode (code_gen, methoddef);
-
- //code_gen.Report.Message (String.Format ("Assembled method '<Module>'::{0}", name));
- is_defined = true;
- }
-
/// <summary>
/// Define a member method
/// </summary>
- public void Define (CodeGen code_gen, TypeDef typedef)
+ public void Define (CodeGen code_gen)
{
if (is_defined)
return;
- Resolve (code_gen, (PEAPI.ClassDef) typedef.ClassDef);
+ if (type_def == null)
+ /* Global method */
+ Resolve (code_gen, null);
+ else
+ Resolve (code_gen, (PEAPI.ClassDef) type_def.ClassDef);
+
WriteCode (code_gen, methoddef);
- //code_gen.Report.Message (String.Format ("Assembled method {0}::{1}", typedef.FullName, name)); is_defined = true;
+ //code_gen.Report.Message (String.Format ("Assembled method {0}::{1}", typedef.FullName, name));
+ is_defined = true;
}
public void AddInstr (IInstr instr)
}
/// Add declarative security to this method
- if (declsecurity_list != null) {
- foreach (DeclSecurity declsecurity in declsecurity_list)
- declsecurity.AddTo (code_gen, methoddef);
-
+ if (decl_sec != null) {
+ decl_sec.AddTo (code_gen, methoddef);
methoddef.AddMethAttribute (PEAPI.MethAttr.HasSecurity);
}
- if (IsAbstract)
- return;
+ // Generic type parameters
+ if (gen_params != null)
+ gen_params.Resolve (code_gen, methoddef);
+
+ if (type_def == null) {
+ //Global method
+ meth_attr &= ~PEAPI.MethAttr.Abstract;
+ meth_attr |= PEAPI.MethAttr.Static;
+ } else {
+ if ((inst_list.Count > 0) && type_def.IsInterface && !IsStatic)
+ Report.Error (start, "Method cannot have body if it is non-static declared in an interface");
+
+ if (IsAbstract) {
+ if (!type_def.IsAbstract)
+ Report.Error (start, String.Format ("Abstract method '{0}' in non-abstract class '{1}'",
+ Name, type_def.FullName));
+ if (inst_list.Count > 0)
+ Report.Error (start, "Method cannot have body if it is abstract.");
+ return;
+ }
+ }
if (entry_point)
methoddef.DeclareEntryPoint ();
if (local_list.Count > 0) {
- int ec = code_gen.Report.ErrorCount;
+ int ec = Report.ErrorCount;
PEAPI.Local[] local_array = new PEAPI.Local[local_list.Count];
- int i = 0;
foreach (Local local in local_list)
local_array[local.Slot] = local.GetPeapiLocal (code_gen);
- if (code_gen.Report.ErrorCount > ec)
+ if (Report.ErrorCount > ec)
return;
if (zero_init)
(pinvoke_name != null ? pinvoke_name : name), pinvoke_attr);
}
- if (inst_list.Count < 1)
- return;
+ if ((impl_attr & PEAPI.ImplAttr.Runtime) == PEAPI.ImplAttr.Runtime) {
+ if (inst_list.Count > 0)
+ Report.Error (start, String.Format ("Method cannot have body if it is non-IL runtime-supplied, '{0}'",
+ FullName));
+ } else {
+ if (((impl_attr & PEAPI.ImplAttr.Native) != 0) ||
+ ((impl_attr & PEAPI.ImplAttr.Unmanaged) != 0))
+ Report.Error (start, String.Format ("Cannot compile native/unmanaged method, '{0}'",
+ FullName));
+ }
+
+ if (inst_list.Count > 0) {
+ /* Has body */
+ if ((impl_attr & PEAPI.ImplAttr.InternalCall) != 0)
+ Report.Error (start, String.Format ("Method cannot have body if it is an internal call, '{0}'",
+ FullName));
+
+ if (pinvoke_info)
+ Report.Error (start, String.Format ("Method cannot have body if it is pinvoke, '{0}'",
+ FullName));
+ } else {
+ if (pinvoke_info ||
+ ((impl_attr & PEAPI.ImplAttr.Runtime) != 0) ||
+ ((impl_attr & PEAPI.ImplAttr.InternalCall) != 0))
+ /* No body required */
+ return;
+
+ Report.Warning (start, "Method has no body, 'ret' emitted.");
+ AddInstr (new SimpInstr (PEAPI.Op.ret, start));
+ }
PEAPI.CILInstructions cil = methoddef.CreateCodeBuffer ();
/// Create all the labels
foreach (LabelInfo label in labelref_table.Values) {
LabelInfo def = (LabelInfo) label_table[label.Name];
if (def == null) {
- code_gen.Report.Error ("Undefined Label: " + label);
+ Report.Error ("Undefined Label: " + label);
return;
}
label.Label = def.Label;
if (source != null)
source.MarkLocation (source.EndLine, cil.Offset);
-
- // Generic type parameters
- if (typar_list != null) {
- short index = 0;
- foreach (GenericInfo gi in typar_list) {
- PEAPI.GenericParameter gp = methoddef.AddGenericParameter (index++, gi.Id);
- if (gi.ConstraintList != null) {
- foreach (ITypeRef cnst in gi.ConstraintList) {
- cnst.Resolve (code_gen);
- gp.AddConstraint (cnst.PeapiType);
- }
- }
- }
- }
}
public LabelInfo AddLabel (string name)
{
LabelInfo label_info = (LabelInfo) label_table[name];
if (label_info != null)
- return label_info;
+ Report.Error ("Duplicate label '" + name + "'");
+
label_info = new LabelInfo (name, inst_list.Count);
- label_table.Add (name, label_info);
+ label_table [name] = label_info;
return label_info;
}
public LabelInfo AddLabel ()
{
- int pos = inst_list.Count;
LabelInfo label_info = new LabelInfo (null, inst_list.Count);
label_list.Add (label_info);
return label_info;
if (IsVararg)
signature = CreateVarargSignature (RetType, name, param_list);
else
- signature = CreateSignature (RetType, name, param_list);
+ signature = CreateSignature (RetType, name, param_list, GenParamCount);
}
- public static string CreateSignature (ITypeRef RetType, string name, IList param_list)
+ public static string CreateSignature (BaseTypeRef RetType, string name, IList param_list, int gen_param_count)
{
StringBuilder builder = new StringBuilder ();
builder.Append (RetType.FullName);
builder.Append (" ");
builder.Append (name);
+ if (gen_param_count > 0)
+ builder.AppendFormat ("`{0}", gen_param_count);
builder.Append ('(');
if (param_list != null) {
return builder.ToString ();
}
- public static string CreateVarargSignature (ITypeRef RetType, string name, IList param_list)
+ public static string CreateVarargSignature (BaseTypeRef RetType, string name, IList param_list)
{
StringBuilder builder = new StringBuilder ();
ParamDef last = null;
return builder.ToString ();
}
- public static string CreateVarargSignature (ITypeRef RetType, string name, ITypeRef [] param_list)
+ public static string CreateVarargSignature (BaseTypeRef RetType, string name, BaseTypeRef [] param_list)
{
StringBuilder builder = new StringBuilder ();
- ITypeRef last = null;
+ BaseTypeRef last = null;
builder.Append (RetType.FullName);
builder.Append (" ");
bool first = true;
if (param_list != null && param_list.Length > 0) {
- foreach (ITypeRef param in param_list) {
+ foreach (BaseTypeRef param in param_list) {
if (!first)
builder.Append (',');
builder.Append (param.FullName);
return builder.ToString ();
}
- public static string CreateSignature (ITypeRef RetType, string name, ITypeRef[] param_list)
+ public static string CreateSignature (BaseTypeRef RetType, string name, BaseTypeRef[] param_list, int gen_param_count)
{
StringBuilder builder = new StringBuilder ();
builder.Append (RetType.FullName);
builder.Append (" ");
builder.Append (name);
+ if (gen_param_count > 0)
+ builder.AppendFormat ("`{0}", gen_param_count);
builder.Append ('(');
if (param_list != null) {
bool first = true;
- foreach (ITypeRef param in param_list) {
+ foreach (BaseTypeRef param in param_list) {
if (!first)
builder.Append (',');
builder.Append (param.FullName);