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