Merge pull request #475 from pruiz/xamarin-bug-7408
[mono.git] / mcs / ilasm / codegen / ExternMethodRef.cs
1 //
2 // Mono.ILASM.ExternMethodRef
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.Collections;
13
14 namespace Mono.ILASM {
15
16         public class ExternMethodRef : BaseMethodRef {
17
18                 public ExternMethodRef (ExternTypeRef owner, BaseTypeRef ret_type,
19                         PEAPI.CallConv call_conv, string name, BaseTypeRef[] param, int gen_param_count)
20                         : base (owner, call_conv, ret_type, name, param, gen_param_count)
21                 {
22                 }
23
24                 public override void Resolve (CodeGen code_gen)
25                 {
26                         if (is_resolved)
27                                 return;
28
29                         if ((call_conv & PEAPI.CallConv.Vararg) != 0) {
30                                 ResolveVararg (code_gen);
31                                 return;
32                         }
33
34                         PEAPI.Type[] param_list = new PEAPI.Type[param.Length];
35                         string write_name;
36
37                         ret_type.Resolve (code_gen);
38
39                         int count = 0;
40                         foreach (BaseTypeRef typeref in param) {
41                                 typeref.Resolve (code_gen);
42                                 param_list[count++] = typeref.PeapiType;
43                         }
44
45                         if (name == "<init>")
46                                 write_name = ".ctor";
47                         else
48                                 write_name = name;
49
50                         owner.Resolve (code_gen);
51
52                         if (owner.UseTypeSpec) {
53                                 PEAPI.Type owner_ref = owner.PeapiType;
54                                 peapi_method = code_gen.PEFile.AddMethodToTypeSpec (owner_ref, write_name,
55                                                 ret_type.PeapiType, param_list, gen_param_count);
56                         } else {
57                                 PEAPI.ClassRef owner_ref;
58                                 owner_ref = (PEAPI.ClassRef) owner.PeapiType;
59                                 peapi_method = owner_ref.AddMethod (write_name,
60                                                 ret_type.PeapiType, param_list, gen_param_count);
61                         }
62
63                         peapi_method.AddCallConv (call_conv);
64
65                         is_resolved = true;
66                 }
67
68                 protected void ResolveVararg (CodeGen code_gen)
69                 {
70                         if (is_resolved)
71                                 return;
72
73                         ArrayList param_list = new ArrayList ();
74                         ArrayList opt_list = new ArrayList ();
75                         bool in_opt = false;
76                         string write_name;
77
78                         ret_type.Resolve (code_gen);
79
80                         foreach (BaseTypeRef typeref in param) {
81                                 if (in_opt) {
82                                         typeref.Resolve (code_gen);
83                                         opt_list.Add (typeref.PeapiType);
84                                 } else if (typeref is SentinelTypeRef) {
85                                         in_opt = true;
86                                 } else {
87                                         typeref.Resolve (code_gen);
88                                         param_list.Add (typeref.PeapiType);
89                                 }
90                         }
91
92                         if (name == "<init>")
93                                 write_name = ".ctor";
94                         else
95                                 write_name = name;
96
97                         if (owner.IsArray)
98                                 Report.Error ("Vararg methods on arrays are not supported yet.");
99
100                         owner.Resolve (code_gen);
101
102                         if (owner.UseTypeSpec) {
103                                 PEAPI.Type owner_ref = owner.PeapiType;
104                                 peapi_method = code_gen.PEFile.AddVarArgMethodToTypeSpec (owner_ref,
105                                                 write_name, ret_type.PeapiType,
106                                                 (PEAPI.Type[]) param_list.ToArray (typeof (PEAPI.Type)),
107                                                 (PEAPI.Type[]) opt_list.ToArray (typeof (PEAPI.Type)));
108                         } else {
109                                 PEAPI.ClassRef owner_ref;
110                                 owner_ref = (PEAPI.ClassRef) owner.PeapiType;
111                                 peapi_method = owner_ref.AddVarArgMethod (write_name,
112                                                 ret_type.PeapiType,
113                                                 (PEAPI.Type[]) param_list.ToArray (typeof (PEAPI.Type)),
114                                                 (PEAPI.Type[]) opt_list.ToArray (typeof (PEAPI.Type)));
115                         }
116
117
118                         peapi_method.AddCallConv (call_conv);
119                         
120                         is_resolved = true;
121                 }
122         }
123
124 }
125