2006-11-14 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / ilasm / codegen / MethodDef.cs
index d8329115bf6e908e4b7b7eb1125a517514336e19..152113cc418fa2f5e484a7c15f8c88e0551120b5 100644 (file)
@@ -23,7 +23,7 @@ namespace Mono.ILASM {
                 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;
@@ -45,9 +45,9 @@ namespace Mono.ILASM {
                 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,
@@ -58,10 +58,11 @@ namespace Mono.ILASM {
                         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 ();
@@ -96,7 +97,7 @@ namespace Mono.ILASM {
                 }
 
                 public BaseTypeRef RetType {
-                        get { return ret_type; }
+                        get { return ret_param.Type; }
                 }
 
                 public PEAPI.CallConv CallConv {
@@ -128,6 +129,26 @@ namespace Mono.ILASM {
                         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)
@@ -177,13 +198,6 @@ namespace Mono.ILASM {
                         return gen_params.GetGenericParamNum (id);
                 }
 
-                public void AddParamDefaultValue (int index, PEAPI.Constant defval)
-                {
-                        if (param_list [index] != null) {
-                                ((ParamDef)param_list [index]).AddDefaultValue (defval);
-                        }
-                }
-
                 public void AddCustomAttribute (CustomAttr customattr)
                 {
                         if (customattr_list == null)
@@ -192,25 +206,9 @@ namespace Mono.ILASM {
                         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)
@@ -246,6 +244,9 @@ namespace Mono.ILASM {
                 public int GetNamedParamPos (string name)
                 {
                         int pos = -1;
+                        if (param_list == null)
+                                return -1;
+
                         if (!IsStatic)
                                 pos ++;
                         foreach (ParamDef param in param_list) {
@@ -257,8 +258,19 @@ namespace Mono.ILASM {
                         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
@@ -313,7 +325,7 @@ namespace Mono.ILASM {
                        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);
 
@@ -339,20 +351,17 @@ namespace Mono.ILASM {
 
                         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;
@@ -456,8 +465,23 @@ namespace Mono.ILASM {
                         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 ();
@@ -490,8 +514,36 @@ namespace Mono.ILASM {
                                                 (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