In ilasm/codegen:
[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 : IMethodRef {
17
18                 private ExternTypeRef owner;
19                 private ITypeRef ret_type;
20                 private string name;
21                 private ITypeRef[] param;
22                 private PEAPI.CallConv call_conv;
23
24                 private PEAPI.Method peapi_method;
25                 private bool is_resolved;
26                 private int gen_param_count;
27
28                 public ExternMethodRef (ExternTypeRef owner, ITypeRef ret_type,
29                         PEAPI.CallConv call_conv, string name, ITypeRef[] param, int gen_param_count)
30                 {
31                         this.owner = owner;
32                         this.ret_type = ret_type;
33                         this.name = name;
34                         this.param = param;
35                         this.call_conv = call_conv;
36                         this.gen_param_count = gen_param_count;
37                         if (gen_param_count > 0)
38                                 CallConv |= PEAPI.CallConv.Generic;
39                         
40                         is_resolved = false;
41                 }
42
43                 public PEAPI.Method PeapiMethod {
44                         get { return peapi_method; }
45                 }
46
47                 public PEAPI.CallConv CallConv {
48                         get { return call_conv; }
49                         set { call_conv = value; }
50                 }
51
52                 public ITypeRef Owner {
53                         get { return owner; }
54                 }
55
56                 public void Resolve (CodeGen code_gen)
57                 {
58                         if (is_resolved)
59                                 return;
60
61                         if ((call_conv & PEAPI.CallConv.Vararg) != 0) {
62                                 ResolveVararg (code_gen);
63                                 return;
64                         }
65
66                         PEAPI.Type[] param_list = new PEAPI.Type[param.Length];
67                         string write_name;
68
69                         ret_type.Resolve (code_gen);
70
71                         int count = 0;
72                         foreach (ITypeRef typeref in param) {
73                                 typeref.Resolve (code_gen);
74                                 param_list[count++] = typeref.PeapiType;
75                         }
76
77                         if (name == "<init>")
78                                 write_name = ".ctor";
79                         else
80                                 write_name = name;
81
82                         owner.Resolve (code_gen);
83
84                         if (owner.UseTypeSpec) {
85                                 PEAPI.Type owner_ref = owner.PeapiType;
86                                 peapi_method = code_gen.PEFile.AddMethodToTypeSpec (owner_ref, write_name,
87                                                 ret_type.PeapiType, param_list, gen_param_count);
88                         } else {
89                                 PEAPI.ClassRef owner_ref;
90                                 owner_ref = (PEAPI.ClassRef) owner.PeapiType;
91                                 peapi_method = owner_ref.AddMethod (write_name,
92                                                 ret_type.PeapiType, param_list, gen_param_count);
93                         }
94
95                         peapi_method.AddCallConv (call_conv);
96
97                         is_resolved = true;
98                 }
99
100                 protected void ResolveVararg (CodeGen code_gen)
101                 {
102                         if (is_resolved)
103                                 return;
104
105                         ArrayList param_list = new ArrayList ();
106                         ArrayList opt_list = new ArrayList ();
107                         bool in_opt = false;
108                         string write_name;
109
110                         ret_type.Resolve (code_gen);
111
112                         int count = 0;
113                         foreach (ITypeRef typeref in param) {
114                                 if (in_opt) {
115                                         typeref.Resolve (code_gen);
116                                         opt_list.Add (typeref.PeapiType);
117                                 } else if (TypeRef.Ellipsis == typeref) {
118                                         in_opt = true;
119                                 } else {
120                                         typeref.Resolve (code_gen);
121                                         param_list.Add (typeref.PeapiType);
122                                 }
123                         }
124
125                         if (name == "<init>")
126                                 write_name = ".ctor";
127                         else
128                                 write_name = name;
129
130                         if (owner.IsArray)
131                                 throw new NotImplementedException ("Vararg methods on arrays are not supported yet.");
132
133                         owner.Resolve (code_gen);
134
135                         if (owner.UseTypeSpec) {
136                                 PEAPI.Type owner_ref = owner.PeapiType;
137                                 peapi_method = code_gen.PEFile.AddVarArgMethodToTypeSpec (owner_ref,
138                                                 write_name, ret_type.PeapiType,
139                                                 (PEAPI.Type[]) param_list.ToArray (typeof (PEAPI.Type)),
140                                                 (PEAPI.Type[]) opt_list.ToArray (typeof (PEAPI.Type)));
141                         } else {
142                                 PEAPI.ClassRef owner_ref;
143                                 owner_ref = (PEAPI.ClassRef) owner.PeapiType;
144                                 peapi_method = owner_ref.AddVarArgMethod (write_name,
145                                                 ret_type.PeapiType,
146                                                 (PEAPI.Type[]) param_list.ToArray (typeof (PEAPI.Type)),
147                                                 (PEAPI.Type[]) opt_list.ToArray (typeof (PEAPI.Type)));
148                         }
149
150
151                         peapi_method.AddCallConv (call_conv);
152                         
153                         is_resolved = true;
154                 }
155         }
156
157 }
158