public class MethodDef : ICustomAttrTarget, IDeclSecurityTarget {
- protected class GenericInfo {
- public string Id;
- public int num;
- 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 BaseTypeRef ret_type;
+ private ParamDef ret_param;
private ArrayList param_list;
private ArrayList inst_list;
private ArrayList customattr_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,
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 ();
}
public BaseTypeRef RetType {
- get { return ret_type; }
+ get { return ret_param.Type; }
}
public PEAPI.CallConv CallConv {
get { return (meth_attr & PEAPI.MethAttr.Abstract) != 0; }
}
+ 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)
get { return (gen_params != null ? gen_params.Count : 0); }
}
- public int GetGenericParamNum (string id)
+ public GenericParameter GetGenericParam (string id)
{
if (gen_params == null)
- return -1;
+ return null;
- return gen_params.GetGenericParamNum (id);
+ return gen_params.GetGenericParam (id);
}
- public void AddParamDefaultValue (int index, PEAPI.Constant defval)
+ public GenericParameter GetGenericParam (int index)
{
- if (param_list [index] != null) {
- ((ParamDef)param_list [index]).AddDefaultValue (defval);
- }
+ if (gen_params == null || index < 0 || index >= gen_params.Count)
+ return null;
+
+ return gen_params [index];
+ }
+
+ public int GetGenericParamNum (string id)
+ {
+ if (gen_params == null)
+ return -1;
+
+ return gen_params.GetGenericParamNum (id);
}
public void AddCustomAttribute (CustomAttr customattr)
customattr_list.Add (customattr);
}
- public void AddPermissionSet (PEAPI.SecurityAction sec_action, PermissionSet ps)
- {
- if (decl_sec == null)
- decl_sec = new DeclSecurity ();
-
- decl_sec.AddPermissionSet (sec_action, ps);
- }
-
- public void AddPermission (PEAPI.SecurityAction sec_action, IPermission iper)
- {
- if (decl_sec == null)
- decl_sec = new DeclSecurity ();
-
- decl_sec.AddPermission (sec_action, iper);
- }
-
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;
}
gpar.Index = type_def.GetGenericParamNum (gpar.Name);
if (gpar.Index < 0)
- /* TODO: Report error */
- throw new Exception (String.Format ("Invalid {0}type parameter '{1}'",
+ Report.Error (String.Format ("Invalid {0}type parameter '{1}'",
(gpar.Type == PEAPI.GenParamType.MVar ? "method " : ""),
gpar.Name));
}
if (gen_params != null)
gen_params.ResolveConstraints (type_params, gen_params);
- BaseGenericTypeRef gtr = ret_type as BaseGenericTypeRef;
+ BaseGenericTypeRef gtr = RetType as BaseGenericTypeRef;
if (gtr != null)
gtr.Resolve (type_params, gen_params);
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 ();
if (gen_params != null)
gen_params.Resolve (code_gen, methoddef);
- if (IsAbstract)
- return;
+ 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;
{
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;