2008-09-08 Zoltan Varga <vargaz@gmail.com>
[mcs.git] / ilasm / codegen / MethodTable.cs
blob2ac19d11aab0e2805477bc90ea733a92fad2104a
1 //
2 // Mono.ILASM.MethodTable.cs
3 //
4 // Author(s):
5 // Jackson Harper (Jackson@LatitudeGeo.com)
6 //
7 // (C) 2003 Jackson Harper, All rights reserved
8 //
10 using PEAPI;
11 using System;
12 using System.Text;
13 using System.Collections;
15 namespace Mono.ILASM {
18 public delegate void MethodDefinedEvent (object sender, MethodDefinedEventArgs args);
19 public delegate void MethodReferencedEvent (object sender, MethodReferencedEventArgs args);
21 public class MethodEventArgs : EventArgs {
23 public readonly string Signature;
24 public readonly string Name;
25 public readonly TypeRef ReturnType;
26 public readonly Param[] ParamList;
27 public readonly bool IsInTable;
29 public MethodEventArgs (string signature, string name,
30 TypeRef return_type, Param[] param_list, bool is_in_table)
32 Signature = signature;
33 Name = name;
34 ReturnType = return_type;
35 ParamList = param_list;
36 IsInTable = is_in_table;
40 public class MethodDefinedEventArgs : MethodEventArgs {
42 public readonly MethAttr MethodAttributes;
43 public readonly ImplAttr ImplAttributes;
44 public readonly CallConv CallConv;
46 public MethodDefinedEventArgs (string signature, string name,
47 TypeRef return_type, Param[] param_list, bool is_in_table, MethAttr method_attr,
48 ImplAttr impl_attr, CallConv call_conv) : base (signature, name,
49 return_type, param_list, is_in_table)
51 MethodAttributes = method_attr;
52 ImplAttributes = impl_attr;
53 CallConv = call_conv;
57 public class MethodReferencedEventArgs : MethodEventArgs {
59 public MethodReferencedEventArgs (string signature, string name,
60 TypeRef return_type, Param[] param_list, bool is_in_table) : base (signature, name,
61 return_type, param_list, is_in_table)
68 public class MethodTable {
70 private class MethodTableItem {
72 private static readonly int DefinedFlag = 2;
74 private int flags;
76 public ArrayList LocationList;
77 public MethodDef Method;
79 public MethodTableItem (MethodDef method, Location location)
81 flags = 0;
82 Method = method;
83 LocationList = new ArrayList ();
84 LocationList.Add (location);
87 public bool Defined {
88 get { return ((flags & DefinedFlag) != 0); }
89 set {
90 if (value)
91 flags |= DefinedFlag;
92 else
93 flags ^= DefinedFlag;
98 protected Hashtable table;
99 protected ClassDef parent_class;
101 public static event MethodReferencedEvent MethodReferencedEvent;
102 public static event MethodDefinedEvent MethodDefinedEvent;
104 public MethodTable (ClassDef parent_class)
106 this.parent_class = parent_class;
107 table = new Hashtable ();
110 public Method GetReference (string name, TypeRef return_type,
111 Param[] param_list, TypeRef[] param_type_list, Location location)
113 string signature = GetSignature (name, return_type, param_type_list);
115 if (MethodReferencedEvent != null)
116 MethodReferencedEvent (this, new MethodReferencedEventArgs (signature, name,
117 return_type, param_list, table.Contains (signature)));
119 MethodTableItem item = table[signature] as MethodTableItem;
121 if (item != null) {
122 item.LocationList.Add (location);
123 return item.Method;
126 MethodDef method = parent_class.AddMethod (name, return_type.Type,
127 param_list);
129 AddReferenced (signature, method, location);
131 return method;
134 public MethodDef AddDefinition (MethAttr method_attr, ImplAttr impl_attr, CallConv call_conv,
135 string name, TypeRef return_type, Param[] param_list,
136 TypeRef[] param_type_list, Location location)
138 string signature = GetSignature (name, return_type, param_type_list);
140 if (MethodDefinedEvent != null)
141 MethodDefinedEvent (this, new MethodDefinedEventArgs (signature, name,
142 return_type, param_list, table.Contains (signature), method_attr,
143 impl_attr, call_conv));
145 MethodTableItem item = (MethodTableItem) table[signature];
147 if (item == null) {
148 MethodDef method = parent_class.AddMethod (method_attr, impl_attr, name,
149 return_type.Type, param_list);
150 method.AddCallConv (call_conv);
151 AddDefined (signature, method, location);
152 return method;
155 item.Method.AddMethAttribute (method_attr);
156 item.Method.AddImplAttribute (impl_attr);
157 item.Method.AddCallConv (call_conv);
158 item.Defined = true;
160 return item.Method;
163 public bool CheckDefined ()
165 foreach (DictionaryEntry dic_entry in table) {
166 MethodTableItem table_item = (MethodTableItem) dic_entry.Value;
167 if (table_item.Defined)
168 continue;
169 Report.Error (String.Format ("Method: {0} is not defined.", dic_entry.Key));
171 return true;
174 protected string GetSignature (string name, TypeRef return_type,
175 TypeRef[] param_list)
177 StringBuilder builder = new StringBuilder ();
179 builder.Append (return_type.FullName);
180 builder.Append ('_');
181 builder.Append (name);
182 builder.Append ('(');
184 bool first = true;
185 foreach (TypeRef type_ref in param_list) {
186 if (!first)
187 builder.Append (',');
188 builder.Append (type_ref.FullName);
190 builder.Append (')');
192 return builder.ToString ();
195 protected void AddDefined (string signature, MethodDef method, Location location)
197 if (table.Contains (signature))
198 return;
200 MethodTableItem item = new MethodTableItem (method, location);
201 item.Defined = true;
203 table[signature] = item;
206 protected void AddReferenced (string signature, MethodDef method, Location location)
208 MethodTableItem item = new MethodTableItem (method, location);
210 table[signature] = item;
213 /// <summary>
214 /// If a method is allready defined throw an Error
215 /// </summary>
216 protected void CheckExists (string signature)
218 MethodTableItem item = table[signature] as MethodTableItem;
220 if ((item != null) && (item.Defined)) {
221 Report.Error (String.Format ("Method: {0} defined in multiple locations.",
222 signature));