Merge pull request #1464 from akoeplinger/fix-portable-target
[mono.git] / mcs / ilasm / codegen / MethodPointerTypeRef.cs
1 //
2 // Mono.ILASM.MethodPointerTypeRef
3 //
4 // Author(s):
5 //  Jackson Harper (jackson@ximian.com)
6 //
7 // Copyright 2004 Novell, Inc (http://www.novell.com)
8 //
9
10
11 using System;
12 using System.Text;
13 using System.Collections;
14
15 namespace Mono.ILASM {
16
17         public class MethodPointerTypeRef : BaseTypeRef {
18
19                 private PEAPI.CallConv callconv;
20                 private BaseTypeRef ret;
21                 private ArrayList param_list;
22
23                 public MethodPointerTypeRef (PEAPI.CallConv callconv, BaseTypeRef ret, ArrayList param_list)
24                         : this (callconv, ret, param_list, null, String.Empty)
25                 {
26                 }
27
28                 public MethodPointerTypeRef (PEAPI.CallConv callconv, BaseTypeRef ret, ArrayList param_list, ArrayList conv_list, string sig_mod)
29                         : base (String.Empty, conv_list, sig_mod)
30                 {
31                         this.callconv = callconv;
32                         this.ret = ret;
33                         this.param_list = param_list;
34
35                         // We just need these to not break the interface
36                         full_name = BuildTypeName ();
37                         //sig_mod = String.Empty;
38                 }
39
40                 private String BuildTypeName ()
41                 {
42                         StringBuilder builder = new StringBuilder ();
43                         builder.Append ("method ");
44                         if (callconv != PEAPI.CallConv.Default) {
45                                 builder.Append (callconv.ToString ());
46                                 builder.Append (' ');
47                         }
48                         builder.Append (ret.FullName);
49                         builder.Append ("*(");
50                         if (param_list != null) {
51                                 bool first = true;
52                                 foreach (ParamDef paramdef in param_list) {
53                                         if (!first)
54                                                 builder.Append (',');
55                                         builder.Append (paramdef.TypeName);
56                                         first = false;
57                                 }
58                         }
59                         builder.Append (')');
60                         return builder.ToString ();
61                 }
62
63                 public override BaseTypeRef Clone ()
64                 {
65                         return new MethodPointerTypeRef (callconv, ret,
66                                         param_list == null ? null : (ArrayList) param_list.Clone (),
67                                         (ArrayList) ConversionList.Clone (), sig_mod);
68                 }
69
70                 public override void Resolve (CodeGen code_gen)
71                 {
72                         if (is_resolved)
73                                 return;
74
75                         PEAPI.Type [] arg_array;
76                         PEAPI.Type [] opt_array;
77                         bool is_vararg = false;
78
79                         if (param_list != null) {
80                                 ArrayList opt_list = new ArrayList ();
81                                 ArrayList arg_list = new ArrayList ();
82                                 bool in_opt = false;
83                                 int max = param_list.Count;
84
85                                 for (int i = 0; i < max; i++) {
86                                         ParamDef param = (ParamDef) param_list [i];
87
88                                         if (param.IsSentinel ()) {
89                                                 is_vararg = true;
90                                                 in_opt = true;
91                                                 param.Type.Resolve (code_gen);
92                                         } else if (in_opt) {
93                                                 param.Type.Resolve (code_gen);
94                                                 opt_list.Add (param.Type.PeapiType);
95                                         } else {
96                                                 param.Type.Resolve (code_gen);
97                                                 arg_list.Add (param.Type.PeapiType);
98                                         }
99                                 }
100
101                                 arg_array = (PEAPI.Type []) arg_list.ToArray (typeof (PEAPI.Type));
102                                 opt_array = (PEAPI.Type []) opt_list.ToArray (typeof (PEAPI.Type));
103                         } else {
104                                 arg_array = new PEAPI.Type [0];
105                                 opt_array = new PEAPI.Type [0];
106                         }
107
108                         ret.Resolve (code_gen);
109
110                         type = new PEAPI.MethPtrType (callconv, ret.PeapiType, arg_array, is_vararg, opt_array);
111                         type = Modify (code_gen, type);
112
113                         is_resolved = true;
114                 }
115
116                 protected override BaseMethodRef CreateMethodRef (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
117                                 string name, BaseTypeRef[] param, int gen_param_count)
118                 {
119                         return new TypeSpecMethodRef (this, call_conv, ret_type, name, param, gen_param_count);
120                 }
121
122                 protected override IFieldRef CreateFieldRef (BaseTypeRef ret_type, string name)
123                 {
124                         return new TypeSpecFieldRef (this, ret_type, name);
125                 }
126
127         }
128
129 }
130