New test.
[mono.git] / mcs / ilasm / codegen / MethodDef.cs
1 //
2 // Mono.ILASM.MethodDef
3 //
4 // Author(s):
5 //  Jackson Harper (Jackson@LatitudeGeo.com)
6 //
7 // (C) 2003 Jackson Harper, All rights reserved
8 //
9
10
11 using System;
12 using System.Text;
13 using System.Collections;
14 using System.Security;
15
16 namespace Mono.ILASM {
17
18         public class MethodDef : ICustomAttrTarget, IDeclSecurityTarget {
19
20                 private PEAPI.MethAttr meth_attr;
21                 private PEAPI.CallConv call_conv;
22                 private PEAPI.ImplAttr impl_attr;
23                 private string name;
24                 private string signature;
25                 private Hashtable vararg_sig_table;
26                 private ParamDef ret_param;
27                 private ArrayList param_list;
28                 private ArrayList inst_list;
29                 private ArrayList customattr_list;
30                 private DeclSecurity decl_sec;
31                 private Hashtable label_table;
32                 private Hashtable labelref_table;
33                 private ArrayList label_list;
34                 private PEAPI.MethodDef methoddef;
35                 private bool entry_point;
36                 private bool zero_init;
37                 private bool is_resolved;
38                 private bool is_defined;
39                 private ArrayList local_list;
40                 private Hashtable named_local_table;
41                 private bool init_locals;
42                 private int max_stack;
43                 private bool pinvoke_info;
44                 private ExternModule pinvoke_mod;
45                 private string pinvoke_name;
46                 private PEAPI.PInvokeAttr pinvoke_attr;
47                 private SourceMethod source;
48                 private TypeDef type_def;
49                 private GenericParameters gen_params;
50                 private Location start;
51
52                 public MethodDef (CodeGen codegen, PEAPI.MethAttr meth_attr,
53                                   PEAPI.CallConv call_conv, PEAPI.ImplAttr impl_attr,
54                                   string name, BaseTypeRef ret_type, ArrayList param_list,
55                                   Location start, GenericParameters gen_params, TypeDef type_def)
56                 {
57                         this.meth_attr = meth_attr;
58                         this.call_conv = call_conv;
59                         this.impl_attr = impl_attr;
60                         this.name = name;
61                         this.param_list = param_list;
62                         this.type_def = type_def;
63                         this.gen_params = gen_params;
64                         this.ret_param = new ParamDef (PEAPI.ParamAttr.Default, "", ret_type);
65                         this.start = (Location) start.Clone ();
66
67                         inst_list = new ArrayList ();
68                         label_table = new Hashtable ();
69                         labelref_table = new Hashtable ();
70                         label_list = new ArrayList ();
71                         local_list = new ArrayList ();
72                         named_local_table = new Hashtable ();
73
74                         entry_point = false;
75                         zero_init = false;
76                         init_locals = false;
77                         max_stack = -1;
78                         pinvoke_info = false;
79
80                         is_defined = false;
81                         is_resolved = false;
82                         ResolveGenParams ();
83                         CreateSignature ();
84
85                         codegen.BeginMethodDef (this);
86
87                         if (codegen.SymbolWriter != null)
88                                 source = codegen.SymbolWriter.BeginMethod (this, start);
89                 }
90
91                 public string Name {
92                         get { return name; }
93                 }
94
95                 public string Signature {
96                         get { return signature; }
97                 }
98
99                 public BaseTypeRef RetType {
100                         get { return ret_param.Type; }
101                 }
102
103                 public PEAPI.CallConv CallConv {
104                         get { return call_conv; }
105                 }
106
107                 public PEAPI.MethodDef PeapiMethodDef {
108                         get { return methoddef; }
109                 }
110
111                 public PEAPI.MethAttr Attributes {
112                         get { return meth_attr; }
113                         set { meth_attr = value; }
114                 }
115
116                 public bool IsVararg {
117                         get { return (call_conv & PEAPI.CallConv.Vararg) != 0; }
118                 }
119
120                 public bool IsStatic {
121                         get { return (meth_attr & PEAPI.MethAttr.Static) != 0; }
122                 }
123
124                 public bool IsVirtual {
125                         get { return (meth_attr & PEAPI.MethAttr.Virtual) != 0; }
126                 }
127
128                 public bool IsAbstract {
129                         get { return (meth_attr & PEAPI.MethAttr.Abstract) != 0; }
130                 }
131
132                 public Location StartLocation {
133                         get { return start; }
134                 }
135
136                 public DeclSecurity DeclSecurity {
137                         get {
138                                 if (decl_sec == null)
139                                         decl_sec = new DeclSecurity ();
140                                 return decl_sec;
141                         }
142                 }
143
144                 public string FullName { 
145                         get {
146                                 if (type_def == null)
147                                         return Name;
148                                 return type_def.FullName + "." + Name;
149                         }
150                 }
151
152                 public BaseTypeRef[] ParamTypeList () {
153
154                         if (param_list == null)
155                                 return new BaseTypeRef[0];
156                         int count = 0;
157                         BaseTypeRef[] type_list = new BaseTypeRef[param_list.Count];
158                         foreach (ParamDef param in param_list) {
159                                 type_list[count++] = param.Type;
160                         }
161                         return type_list;
162                 }
163
164                 public void AddPInvokeInfo (PEAPI.PInvokeAttr pinvoke_attr, ExternModule pinvoke_mod,
165                                 string pinvoke_name)
166                 {
167                         this.pinvoke_attr = pinvoke_attr;
168                         this.pinvoke_mod = pinvoke_mod;
169                         this.pinvoke_name = pinvoke_name;
170                         pinvoke_info = true;
171                 }
172
173                 public int GenParamCount {
174                         get { return (gen_params != null ? gen_params.Count : 0); }
175                 }
176
177                 public GenericParameter GetGenericParam (string id)
178                 {
179                         if (gen_params == null)
180                                 return null;
181                         
182                         return gen_params.GetGenericParam (id);
183                 }
184
185                 public GenericParameter GetGenericParam (int index)
186                 {
187                         if (gen_params == null || index < 0 || index >= gen_params.Count)
188                                 return null;
189                         
190                         return gen_params [index];
191                 }
192
193                 public int GetGenericParamNum (string id)
194                 {
195                         if (gen_params == null)
196                                 return -1;
197                         
198                         return gen_params.GetGenericParamNum (id);
199                 }
200
201                 public void AddCustomAttribute (CustomAttr customattr)
202                 {
203                         if (customattr_list == null)
204                                 customattr_list = new ArrayList ();
205
206                         customattr_list.Add (customattr);
207                 }
208
209                 public void AddRetTypeMarshalInfo (PEAPI.NativeType native_type)
210                 {
211                         this.ret_param.AddMarshalInfo (native_type);
212                 }
213
214                 public void AddLocals (ArrayList local_list)
215                 {
216                         int slot_pos = this.local_list.Count;
217
218                         foreach (Local local in local_list) {
219                                 if (local.Slot == -1) {
220                                         local.Slot = slot_pos;
221                                 }
222                                 slot_pos++;
223                                 if (local.Name == null)
224                                         continue;
225                                 if(!named_local_table.Contains(local.Name))
226                                   named_local_table.Add (local.Name, local);
227                         }
228
229                         this.local_list.AddRange (local_list);
230                 }
231
232                 public Local GetNamedLocal (string name)
233                 {
234                         return (Local) named_local_table[name];
235                 }
236
237                 public int GetNamedLocalSlot (string name)
238                 {
239                         Local local = (Local) named_local_table[name];
240
241                         return local.Slot;
242                 }
243
244                 public int GetNamedParamPos (string name)
245                 {
246                         int pos = -1;
247                         if (param_list == null)
248                                 return -1;
249
250                         if (!IsStatic)
251                                 pos ++;
252                         foreach (ParamDef param in param_list) {
253                                 pos ++;
254                                 if (param.Name.CompareTo (name) == 0)
255                                         return pos;
256                         }
257
258                         return pos;
259                 }
260
261                 /* index - 0: return type
262                  *         1: params start from this
263                  */
264                 public ParamDef GetParam (int index)
265                 {
266                         if (index == 0)
267                                 return ret_param;
268
269                         if ((param_list == null) || (index < 0) || (index > param_list.Count))
270                                 return null;
271
272                         index --; /* param_list has params zero-based */
273
274                         if (param_list [index] != null)
275                                 return (ParamDef)param_list [index];
276                         else
277                                 return null;
278                 }
279
280                 public void InitLocals ()
281                 {
282                         init_locals = true;
283                 }
284
285                 public void EntryPoint ()
286                 {
287                         if (!IsStatic)
288                                 Report.Error ("Non-static method as entrypoint.");
289                         entry_point = true;
290                 }
291
292                 public void ZeroInit ()
293                 {
294                         zero_init = true;
295                 }
296                 
297                 public void SetMaxStack (int max_stack)
298                 {
299                         this.max_stack = max_stack;
300                 }
301
302                 public void ResolveGenParam (PEAPI.GenParam gpar)
303                 {
304                         if (gpar.Index != -1)
305                                 return;
306         
307                         if (gpar.Type == PEAPI.GenParamType.MVar)
308                                 gpar.Index = GetGenericParamNum (gpar.Name); 
309                         else
310                                 gpar.Index = type_def.GetGenericParamNum (gpar.Name);
311
312                         if (gpar.Index < 0)
313                                 Report.Error (String.Format ("Invalid {0}type parameter '{1}'", 
314                                                         (gpar.Type == PEAPI.GenParamType.MVar ? "method " : ""),
315                                                          gpar.Name));
316                 }
317
318                 public void ResolveGenParams ()
319                 {
320                         GenericParameters type_params = (type_def != null) ? type_def.TypeParameters : null;
321
322                         if (gen_params == null && type_params == null)
323                                 return;
324
325                         if (gen_params != null)
326                                 gen_params.ResolveConstraints (type_params, gen_params);
327                         
328                         BaseGenericTypeRef gtr = RetType as BaseGenericTypeRef;
329                         if (gtr != null)
330                                 gtr.Resolve (type_params, gen_params);
331
332                         if (param_list == null)
333                                 return;
334
335                         foreach (ParamDef param in param_list) {
336                                 gtr = param.Type as BaseGenericTypeRef;
337                                 if (gtr != null)
338                                         gtr.Resolve (type_params, gen_params);
339                         }        
340                 }
341
342                 public PEAPI.MethodDef Resolve (CodeGen code_gen)
343                 {
344                         return Resolve (code_gen, null);
345                 }
346
347                 public PEAPI.MethodDef Resolve (CodeGen code_gen, PEAPI.ClassDef classdef)
348                 {
349                         if (is_resolved)
350                                 return methoddef;
351
352                         PEAPI.Param [] param_array = GenerateParams (code_gen);
353                         FixAttributes ();
354                         ret_param.Define (code_gen);
355
356                         if (classdef == null)
357                                 methoddef = code_gen.PEFile.AddMethod (meth_attr, impl_attr,
358                                                 name, ret_param.PeapiParam, param_array);
359                         else                    
360                                 methoddef = classdef.AddMethod (meth_attr, impl_attr,
361                                                 name, ret_param.PeapiParam, param_array);
362
363                         methoddef.AddCallConv (call_conv);
364
365                         is_resolved = true;
366
367                         return methoddef;
368                 }
369
370                 private PEAPI.Param [] GenerateParams (CodeGen code_gen)
371                 {
372                         PEAPI.Param[] param_array;
373
374                         if (param_list != null && param_list.Count > 0) {
375                                  int param_count = param_list.Count;
376
377                                  // Remove the last param if its the sentinel, not sure what
378                                 // should happen with more then one sentinel
379                                 ParamDef last = (ParamDef) param_list [param_count-1];
380                                 if (last.IsSentinel ())
381                                         param_count--;
382
383                                 param_array = new PEAPI.Param [param_count];
384                                 for (int i = 0; i < param_count; i++) {
385                                         ParamDef paramdef = (ParamDef) param_list [i];
386                                         paramdef.Define (code_gen);
387                                         param_array [i] = paramdef.PeapiParam;
388                                 }
389
390                         } else {
391                                 param_array = new PEAPI.Param [0];
392                         }
393
394                         return param_array;
395                 }
396
397                 public PEAPI.MethodRef GetVarargSig (PEAPI.Type[] opt)
398                 {
399                         if (!is_resolved)
400                                 throw new InternalErrorException ("Methods must be resolved before a vararg sig can be created.");
401
402                         PEAPI.MethodRef methref = null;
403                         StringBuilder sigbuilder = new StringBuilder ();
404                         string sig;
405                         foreach (PEAPI.Type t in opt)
406                                 sigbuilder.Append (opt + ", ");
407                         sig = sigbuilder.ToString ();
408
409                         if (vararg_sig_table == null) {
410                                 vararg_sig_table = new Hashtable ();                                
411                         } else {
412                                 methref = vararg_sig_table [sig] as PEAPI.MethodRef;
413                         }
414
415                         if (methref == null) {
416                                 methref = methoddef.MakeVarArgSignature (opt);
417                                 vararg_sig_table [sig] = methref;
418                         }
419
420                         return methref;
421                 }
422
423                 /// <summary>
424                 ///  Define a member method
425                 /// </summary>
426                 public void Define (CodeGen code_gen)
427                 {
428                         if (is_defined)
429                                 return;
430
431                         if (type_def == null)
432                                 /* Global method */
433                                 Resolve (code_gen, null);
434                         else
435                                 Resolve (code_gen, (PEAPI.ClassDef) type_def.ClassDef);
436                                 
437                         WriteCode (code_gen, methoddef);
438
439                         //code_gen.Report.Message (String.Format ("Assembled method {0}::{1}", typedef.FullName, name));
440                         is_defined = true;
441                 }
442
443                 public void AddInstr (IInstr instr)
444                 {
445                         inst_list.Add (instr);
446                 }
447
448                 protected void WriteCode (CodeGen code_gen, PEAPI.MethodDef methoddef)
449                 {
450                         /// Add the custrom attributes to this method
451                         if (customattr_list != null)
452                                 foreach (CustomAttr customattr in customattr_list) {
453                                         customattr.AddTo (code_gen, methoddef);
454                                         if (customattr.IsSuppressUnmanaged (code_gen))
455                                                 methoddef.AddMethAttribute (PEAPI.MethAttr.HasSecurity);
456                                 }
457
458                         /// Add declarative security to this method
459                         if (decl_sec != null) {
460                                 decl_sec.AddTo (code_gen, methoddef);
461                                 methoddef.AddMethAttribute (PEAPI.MethAttr.HasSecurity);
462                         }        
463
464                         // Generic type parameters
465                         if (gen_params != null)
466                                 gen_params.Resolve (code_gen, methoddef);
467
468                         if (type_def == null) {
469                                 //Global method
470                                 meth_attr &= ~PEAPI.MethAttr.Abstract;
471                                 meth_attr |= PEAPI.MethAttr.Static;
472                         } else {
473                                 if ((inst_list.Count > 0) && type_def.IsInterface && !IsStatic)
474                                         Report.Error (start, "Method cannot have body if it is non-static declared in an interface");
475                                 
476                                 if (IsAbstract) {
477                                         if (!type_def.IsAbstract)
478                                                 Report.Error (start, String.Format ("Abstract method '{0}' in non-abstract class '{1}'", 
479                                                                         Name, type_def.FullName));
480                                         if (inst_list.Count > 0)
481                                                 Report.Error (start, "Method cannot have body if it is abstract.");
482                                         return;
483                                 }
484                         }
485
486                         if (entry_point)
487                                 methoddef.DeclareEntryPoint ();
488
489                         if (local_list.Count > 0) {
490                                 int ec = Report.ErrorCount;
491                                 PEAPI.Local[] local_array = new PEAPI.Local[local_list.Count];
492
493                                 foreach (Local local in local_list)
494                                         local_array[local.Slot]  = local.GetPeapiLocal (code_gen);
495
496                                 if (Report.ErrorCount > ec)
497                                         return;
498
499                                 if (zero_init)
500                                         init_locals = true;
501                                 
502                                 methoddef.AddLocals (local_array, init_locals);
503                         }
504
505                         /// Nothing seems to work if maxstack is not set,
506                         /// i need to find out if this NEEDs to be set
507                         /// and what its default value should be
508                         if (max_stack < 0)
509                                 max_stack = 8;
510                         methoddef.SetMaxStack (max_stack);
511
512                         if (pinvoke_info) {
513                                 methoddef.AddPInvokeInfo (pinvoke_mod.ModuleRef,
514                                                 (pinvoke_name != null ? pinvoke_name : name), pinvoke_attr);
515                         }
516
517                         if ((impl_attr & PEAPI.ImplAttr.Runtime) == PEAPI.ImplAttr.Runtime) {
518                                 if (inst_list.Count > 0)
519                                         Report.Error (start, String.Format ("Method cannot have body if it is non-IL runtime-supplied, '{0}'", 
520                                                                 FullName));
521                         } else {
522                                 if (((impl_attr & PEAPI.ImplAttr.Native) != 0) ||
523                                         ((impl_attr & PEAPI.ImplAttr.Unmanaged) != 0))
524                                         Report.Error (start, String.Format ("Cannot compile native/unmanaged method, '{0}'", 
525                                                                 FullName));
526                         }
527
528                         if (inst_list.Count > 0) {
529                                 /* Has body */
530                                 if ((impl_attr & PEAPI.ImplAttr.InternalCall) != 0)
531                                         Report.Error (start, String.Format ("Method cannot have body if it is an internal call, '{0}'", 
532                                                                 FullName));
533
534                                 if (pinvoke_info)
535                                         Report.Error (start, String.Format ("Method cannot have body if it is pinvoke, '{0}'",
536                                                                 FullName));
537                         } else {
538                                 if (pinvoke_info ||
539                                         ((impl_attr & PEAPI.ImplAttr.Runtime) != 0) ||
540                                         ((impl_attr & PEAPI.ImplAttr.InternalCall) != 0))
541                                         /* No body required */
542                                         return;
543
544                                 Report.Warning (start, "Method has no body, 'ret' emitted.");
545                                 AddInstr (new SimpInstr (PEAPI.Op.ret, start));
546                         }
547
548                         PEAPI.CILInstructions cil = methoddef.CreateCodeBuffer ();
549                         /// Create all the labels
550                         /// TODO: Most labels don't actually need to be created so we could
551                         /// probably only create the ones that need to be
552                         LabelInfo[] label_info = new LabelInfo[label_table.Count + label_list.Count];
553                         label_table.Values.CopyTo (label_info, 0);
554                         label_list.CopyTo (label_info, label_table.Count);
555                         int previous_pos = -1;
556                         LabelInfo previous_label = null;
557                         Array.Sort (label_info);
558
559                         foreach (LabelInfo label in label_info) {
560                                 if (label.UseOffset) {
561                                         label.Define (new PEAPI.CILLabel (label.Offset));
562                                         continue;
563                                 }
564                                 if (label.Pos == previous_pos)
565                                         label.Label = previous_label.Label;
566                                 else
567                                         label.Define (cil.NewLabel ());
568
569                                 previous_label = label;
570                                 previous_pos = label.Pos;
571                         }
572
573                         // Set all the label refs
574                         foreach (LabelInfo label in labelref_table.Values) {
575                                 LabelInfo def = (LabelInfo) label_table[label.Name];
576                                 if (def == null) {
577                                         Report.Error ("Undefined Label:  " + label);
578                                         return;
579                                 }
580                                 label.Label = def.Label;
581                         }
582
583                         int label_pos = 0;
584                         int next_label_pos = (label_info.Length > 0 ? label_info[0].Pos : -1);
585
586                         for (int i=0; i<inst_list.Count; i++) {
587                                 IInstr instr = (IInstr) inst_list[i];
588                                 if (next_label_pos == i) {
589                                         cil.CodeLabel (label_info[label_pos].Label);
590                                         if (label_pos < label_info.Length) {
591                                                 while (next_label_pos == i && ++label_pos < label_info.Length) {
592                                                         if (label_info[label_pos].UseOffset)
593                                                                 cil.CodeLabel (label_info[label_pos].Label);
594                                                        next_label_pos = label_info[label_pos].Pos;
595                                                 }
596                                         }
597                                         if (label_pos >= label_info.Length)
598                                                 next_label_pos = -1;
599                                 }
600                                 if (source != null)
601                                         source.MarkLocation (instr.Location.line, cil.Offset);
602                                 instr.Emit (code_gen, this, cil);
603                         }
604
605                         if (source != null)
606                                 source.MarkLocation (source.EndLine, cil.Offset);
607                 }
608
609                 public LabelInfo AddLabel (string name)
610                 {
611                         LabelInfo label_info = (LabelInfo) label_table[name];
612                         if (label_info != null)
613                                 Report.Error ("Duplicate label '" + name + "'");
614
615                         label_info = new LabelInfo (name, inst_list.Count);
616                         label_table [name] = label_info;
617                         return label_info;
618                 }
619
620                 public LabelInfo AddLabelRef (string name)
621                 {
622                         LabelInfo label_info = (LabelInfo) label_table[name];
623                         if (label_info != null)
624                                 return label_info;
625                         label_info = (LabelInfo) labelref_table[name];
626                         if (label_info != null)
627                                 return label_info;
628                         label_info = new LabelInfo (name, -1);
629                         labelref_table.Add (name, label_info);
630                         return label_info;
631                 }
632
633                 public LabelInfo AddLabel (int offset)
634                 {
635                         // We go pos + 1 so this line is not counted
636                         LabelInfo label_info = new LabelInfo (null, inst_list.Count+1, (uint) offset);
637                         label_list.Add (label_info);
638                         return label_info;
639                 }
640
641                 public LabelInfo AddLabel ()
642                 {
643                         LabelInfo label_info = new LabelInfo (null, inst_list.Count);
644                         label_list.Add (label_info);
645                         return label_info;
646                 }
647
648                 public PEAPI.CILLabel GetLabelDef (string name)
649                 {
650                         LabelInfo label_info = (LabelInfo) label_table[name];
651
652                         return label_info.Label;
653                 }
654
655                 public PEAPI.CILLabel GetLabelDef (int pos)
656                 {
657                         foreach (LabelInfo li in label_list) {
658                                 if (li.Pos == pos)
659                                         return li.Label;
660                         }
661                         return null;
662                 }
663
664                 private void CreateSignature ()
665                 {
666                         if (IsVararg)
667                                 signature = CreateVarargSignature (RetType, name, param_list);
668                         else
669                                 signature = CreateSignature (RetType, name, param_list, GenParamCount);
670                 }
671
672                 public static string CreateSignature (BaseTypeRef RetType, string name, IList param_list, int gen_param_count)
673                 {
674                         StringBuilder builder = new StringBuilder ();
675
676                         builder.Append (RetType.FullName);
677                         builder.Append (" ");
678                         builder.Append (name);
679                         if (gen_param_count > 0)
680                                 builder.AppendFormat ("`{0}", gen_param_count);
681                         builder.Append ('(');
682
683                         if (param_list != null) {
684                                 bool first = true;
685                                 foreach (ParamDef paramdef in param_list) {
686                                         if (!first)
687                                                 builder.Append (',');
688                                         builder.Append (paramdef.TypeName);
689                                         first = false;
690                                 }
691                         }
692                         builder.Append (')');
693
694                         return builder.ToString ();
695                 }
696
697                 public static string CreateVarargSignature (BaseTypeRef RetType, string name, IList param_list)
698                 {
699                         StringBuilder builder = new StringBuilder ();
700                         ParamDef last = null;
701
702                         builder.Append (RetType.FullName);
703                         builder.Append (" ");
704                         builder.Append (name);
705                         builder.Append ('(');
706
707                         bool first = true;
708                         if (param_list != null) {
709                                 foreach (ParamDef paramdef in param_list) {
710                                         if (!first)
711                                                 builder.Append (',');
712                                         builder.Append (paramdef.TypeName);
713                                         first = false;
714                                 }
715                                 last = (ParamDef) param_list[param_list.Count - 1];
716                         }
717
718                         
719                         if (last == null || !last.IsSentinel ()) {
720                                 if (!first)
721                                         builder.Append (',');
722                                 builder.Append ("...");
723                         }
724
725                         builder.Append (')');
726
727                         return builder.ToString ();
728                 }
729
730                 public static string CreateVarargSignature (BaseTypeRef RetType, string name, BaseTypeRef [] param_list)
731                 {
732                         StringBuilder builder = new StringBuilder ();
733                         BaseTypeRef last = null;
734
735                         builder.Append (RetType.FullName);
736                         builder.Append (" ");
737                         builder.Append (name);
738                         builder.Append ('(');
739
740                         bool first = true;
741                         if (param_list != null && param_list.Length > 0) {
742                                 foreach (BaseTypeRef param in param_list) {
743                                         if (!first)
744                                                 builder.Append (',');
745                                         builder.Append (param.FullName);
746                                         first = false;
747                                         last = param;
748                                         if (param is SentinelTypeRef)
749                                                 break;
750                                 }
751                                 
752                         }
753                         
754                         if (last == null || !(last is SentinelTypeRef)) {
755                                 if (!first)
756                                         builder.Append (',');
757                                 builder.Append ("...");
758                         }
759
760                         builder.Append (')');
761
762                         return builder.ToString ();
763                 }
764
765                 public static string CreateSignature (BaseTypeRef RetType, string name, BaseTypeRef[] param_list, int gen_param_count)
766                 {
767                         StringBuilder builder = new StringBuilder ();
768
769                         builder.Append (RetType.FullName);
770                         builder.Append (" ");
771                         builder.Append (name);
772                         if (gen_param_count > 0)
773                                 builder.AppendFormat ("`{0}", gen_param_count);
774                         builder.Append ('(');
775
776                         if (param_list != null) {
777                                 bool first = true;
778                                 foreach (BaseTypeRef param in param_list) {
779                                         if (!first)
780                                                 builder.Append (',');
781                                         builder.Append (param.FullName);
782                                         first = false;
783                                         if (param is SentinelTypeRef)
784                                                 break;
785                                 }
786                         }
787                         builder.Append (')');
788
789                         return builder.ToString ();
790                 }
791
792                 private void FixAttributes ()
793                 {
794                         if (name == ".ctor" || name == ".cctor")
795                                 meth_attr |= PEAPI.MethAttr.SpecialName | PEAPI.MethAttr.RTSpecialName;
796                         // If methods aren't flagged as static they are instance
797                         if ((PEAPI.MethAttr.Static & meth_attr) == 0)
798                                 call_conv |= PEAPI.CallConv.Instance;
799                 }
800
801         }
802
803 }
804