2 // Mono.ILASM.MethodDef
5 // Jackson Harper (Jackson@LatitudeGeo.com)
7 // (C) 2003 Jackson Harper, All rights reserved
13 using System.Collections;
16 namespace Mono.ILASM {
18 public class MethodDef {
20 protected class LabelInfo : IComparable {
22 public readonly string Name;
23 public readonly int Pos;
24 public PEAPI.CILLabel Label;
26 public LabelInfo (string name, int pos)
33 public void Define (PEAPI.CILLabel label)
38 public int CompareTo (object obj)
40 LabelInfo other = obj as LabelInfo;
43 return Pos.CompareTo(other.Pos);
45 throw new ArgumentException ("object is not a LabelInfo");
49 private PEAPI.MethAttr meth_attr;
50 private PEAPI.ImplAttr impl_attr;
52 private string signature;
53 private ITypeRef ret_type;
54 private ArrayList param_list;
55 private ArrayList inst_list;
56 private Hashtable label_table;
57 private PEAPI.MethodDef methoddef;
58 private bool entry_point;
59 private bool is_resolved;
60 private bool is_defined;
61 private ArrayList local_list;
62 private Hashtable named_local_table;
63 private bool init_locals;
64 private int max_stack;
66 public MethodDef (PEAPI.MethAttr meth_attr, PEAPI.ImplAttr impl_attr,
67 string name, ITypeRef ret_type, ArrayList param_list)
69 this.meth_attr = meth_attr;
70 this.impl_attr = impl_attr;
72 this.ret_type = ret_type;
73 this.param_list = param_list;
75 inst_list = new ArrayList ();
76 label_table = new Hashtable ();
77 local_list = new ArrayList ();
78 named_local_table = new Hashtable ();
92 public string Signature {
93 get { return signature; }
96 public PEAPI.MethodDef PeapiMethodDef {
97 get { return methoddef; }
100 public void AddLocals (ArrayList local_list)
102 int slot_pos = this.local_list.Count;
104 foreach (Local local in local_list) {
105 if (local.Slot == -1) {
106 local.Slot = slot_pos;
109 if (local.Name == null)
111 named_local_table.Add (local.Name, local);
114 this.local_list.AddRange (local_list);
117 public Local GetNamedLocal (string name)
119 return (Local) named_local_table[name];
122 public void InitLocals ()
127 public void EntryPoint ()
132 public void SetMaxStack (int max_stack)
134 this.max_stack = max_stack;
137 public PEAPI.MethodDef Resolve (CodeGen code_gen)
142 PEAPI.Param[] param_array = new PEAPI.Param[param_list.Count];
144 ret_type.Resolve (code_gen);
146 foreach (ParamDef paramdef in param_list) {
147 paramdef.Define (code_gen);
148 param_array[count++] = paramdef.PeapiParam;
151 methoddef = code_gen.PEFile.AddMethod (meth_attr, impl_attr,
152 name, ret_type.PeapiType, param_array);
159 public PEAPI.MethodDef Resolve (CodeGen code_gen, PEAPI.ClassDef classdef)
164 PEAPI.Param[] param_array = new PEAPI.Param[param_list.Count];
166 ret_type.Resolve (code_gen);
168 foreach (ParamDef paramdef in param_list) {
169 paramdef.Define (code_gen);
170 param_array[count++] = paramdef.PeapiParam;
173 methoddef = classdef.AddMethod (meth_attr, impl_attr,
174 name, ret_type.PeapiType, param_array);
182 /// Define a global method
184 public void Define (CodeGen code_gen)
191 WriteCode (code_gen, methoddef);
197 /// Define a member method
199 public void Define (CodeGen code_gen, PEAPI.ClassDef classdef)
204 Resolve (code_gen, classdef);
206 WriteCode (code_gen, methoddef);
211 public void AddInstr (IInstr instr)
213 inst_list.Add (instr);
216 protected void WriteCode (CodeGen code_gen, PEAPI.MethodDef methoddef)
219 methoddef.DeclareEntryPoint ();
221 if (local_list != null) {
222 PEAPI.Local[] local_array = new PEAPI.Local[local_list.Count];
225 foreach (Local local in local_list)
226 local_array[local.Slot] = local.GetPeapiLocal (code_gen);
228 methoddef.AddLocals (local_array, init_locals);
231 /// Nothing seems to work if maxstack is not set,
232 /// i need to find out if this NEEDs to be set
233 /// and what its default value should be
236 methoddef.SetMaxStack (max_stack);
238 if (inst_list.Count < 1)
241 PEAPI.CILInstructions cil = methoddef.CreateCodeBuffer ();
242 /// Create all the labels
243 /// TODO: Most labels don't actually need to be created so we could
244 /// probably only create the ones that need to be
245 LabelInfo[] label_info = new LabelInfo[label_table.Count];
246 label_table.Values.CopyTo (label_info, 0);
247 Array.Sort (label_info);
249 foreach (LabelInfo label in label_info)
250 label.Define (cil.NewLabel ());
253 int next_label_pos = (label_info.Length > 0 ? label_info[0].Pos : -1);
255 for (int i=0; i<inst_list.Count; i++) {
256 IInstr instr = (IInstr) inst_list[i];
257 if (next_label_pos == i) {
258 cil.CodeLabel (label_info[label_pos].Label);
259 if (++label_pos < label_info.Length)
260 next_label_pos = label_info[label_pos].Pos;
264 instr.Emit (code_gen, cil);
269 public void AddLabel (string name)
271 LabelInfo label_info = new LabelInfo (name, inst_list.Count);
273 label_table.Add (name, label_info);
276 public PEAPI.CILLabel GetLabelDef (string name)
278 LabelInfo label_info = (LabelInfo) label_table[name];
280 return label_info.Label;
283 private void CreateSignature ()
285 signature = CreateSignature (name, param_list);
288 public static string CreateSignature (string name, ICollection param_list)
290 StringBuilder builder = new StringBuilder ();
292 builder.Append (name);
293 builder.Append ('(');
296 foreach (ParamDef paramdef in param_list) {
298 builder.Append (',');
299 builder.Append (paramdef.TypeName);
301 builder.Append (')');
304 return builder.ToString ();