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