(mono_marshal_get_managed_wrapper): support more types
[mono.git] / mono / metadata / marshal.c
1 /*
2  * marshal.c: Routines for marshaling complex types in P/Invoke methods.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.  http://www.ximian.com
8  *
9  */
10
11 #include "config.h"
12 #include "object.h"
13 #include "loader.h"
14 #include "metadata/marshal.h"
15 #include "metadata/tabledefs.h"
16 #include "metadata/exception.h"
17 #include "metadata/appdomain.h"
18
19 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
20         a = i,
21
22 enum {
23 #include "mono/cil/opcode.def"
24         LAST = 0xff
25 };
26 #undef OPDEF
27
28 struct _MonoMethodBuilder {
29         MonoMethod *method;
30         GList *locals_list;
31         int locals;
32         guint32 code_size, pos;
33         unsigned char *code;
34 };
35
36 gpointer
37 mono_delegate_to_ftnptr (MonoDelegate *delegate)
38 {
39         MonoMethod *method, *invoke, *wrapper;
40         MonoMethodSignature *sig;
41         MonoClass *klass;
42
43         if (!delegate)
44                 return NULL;
45
46         if (delegate->delegate_trampoline)
47                 return delegate->delegate_trampoline;
48
49         klass = ((MonoObject *)delegate)->vtable->klass;
50         g_assert (klass->delegate);
51         
52         method = delegate->method_info->method;
53         sig = method->signature;
54         
55         invoke = mono_get_delegate_invoke (klass);
56         wrapper = mono_marshal_get_managed_wrapper (invoke, (MonoObject *)delegate);
57
58         delegate->delegate_trampoline =  mono_compile_method (wrapper);
59
60         return delegate->delegate_trampoline;
61 }
62
63 gpointer
64 mono_array_to_savearray (MonoArray *array)
65 {
66         if (!array)
67                 return NULL;
68
69         g_assert_not_reached ();
70         return NULL;
71 }
72
73 gpointer
74 mono_array_to_lparray (MonoArray *array)
75 {
76         if (!array)
77                 return NULL;
78
79         g_assert_not_reached ();
80         return NULL;
81 }
82
83 gpointer
84 mono_string_to_ansibstr (MonoString *string_obj)
85 {
86         g_error ("implement me");
87         return NULL;
88 }
89
90 gpointer
91 mono_string_to_bstr (MonoString *string_obj)
92 {
93         g_error ("implement me");
94         return NULL;
95 }
96
97 void
98 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
99 {
100         char *s;
101         int len;
102
103         g_assert (dst != NULL);
104         g_assert (size > 0);
105
106         if (!src) {
107                 memset (dst, 0, size);
108                 return;
109         }
110
111         s = mono_string_to_utf8 (src);
112         len = MIN (size, strlen (s));
113         memcpy (dst, s, len);
114         g_free (s);
115
116         *((char *)dst + size - 1) = 0;
117 }
118
119 void
120 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
121 {
122         int len;
123
124         g_assert (dst != NULL);
125         g_assert (size > 1);
126
127         if (!src) {
128                 memset (dst, 0, size);
129                 return;
130         }
131
132         len = MIN (size, (mono_string_length (src) * 2));
133         memcpy (dst, mono_string_chars (src), len);
134
135         *((char *)dst + size - 1) = 0;
136         *((char *)dst + size - 2) = 0;
137 }
138
139
140 static MonoMethod *
141 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
142 {
143         MonoMethod *res = NULL;
144         int i;
145
146         for (i = 0; i < klass->method.count; ++i) {
147                 if ((klass->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
148                     klass->methods [i]->name[0] == name [0] && 
149                     !strcmp (name, klass->methods [i]->name) &&
150                     klass->methods [i]->signature->param_count == param_count) {
151                         res = klass->methods [i];
152                         break;
153                 }
154         }
155         return res;
156 }
157
158 void
159 mono_mb_free (MonoMethodBuilder *mb)
160 {
161         g_list_free (mb->locals_list);
162         g_free (mb);
163 }
164
165 MonoMethodBuilder *
166 mono_mb_new (MonoClass *klass, const char *name)
167 {
168         MonoMethodBuilder *mb;
169         MonoMethod *m;
170
171         g_assert (klass != NULL);
172         g_assert (name != NULL);
173
174         mb = g_new0 (MonoMethodBuilder, 1);
175
176         mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
177
178         m->klass = klass;
179         m->name = g_strdup (name);
180         m->inline_info = 1;
181         m->inline_count = -1;
182         m->is_wrapper = 1;
183
184         mb->code_size = 256;
185         mb->code = g_malloc (mb->code_size);
186         
187         return mb;
188 }
189
190 int
191 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
192 {
193         int res = mb->locals;
194
195         g_assert (mb != NULL);
196         g_assert (type != NULL);
197
198         mb->locals_list = g_list_append (mb->locals_list, type);
199         mb->locals++;
200
201         return res;
202 }
203
204 MonoMethod *
205 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
206 {
207         MonoMethodHeader *header;
208         GList *l;
209         int i;
210
211         g_assert (mb != NULL);
212
213         ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *) 
214                 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
215
216         if (max_stack < 8)
217                 max_stack = 8;
218
219         header->max_stack = max_stack;
220
221         for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
222                 header->locals [i] = (MonoType *)l->data;
223         }
224
225         mb->method->signature = signature;
226         header->code = mb->code;
227         header->code_size = mb->pos;
228         header->num_locals = mb->locals;
229
230 #if 0
231         printf ("MB METHOD %s.%s:%s\n", mb->method->klass->name_space, mb->method->klass->name,
232                 mb->method->name);
233         
234         for (i = 0; i < mb->pos; i++)
235                 printf (" IL%05x %02x\n", i, mb->code [i]);
236
237 #endif
238
239         return mb->method;
240 }
241
242 guint32
243 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
244 {
245         MonoMethodWrapper *mw;
246
247         g_assert (mb != NULL);
248
249         mw = (MonoMethodWrapper *)mb->method;
250
251         mw->data = g_list_append (mw->data, data);
252
253         return g_list_length (mw->data);
254 }
255
256 void
257 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
258 {
259         *((gint32 *)(&mb->code [pos])) = value;
260 }
261
262 void
263 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
264 {
265         if (mb->pos >= mb->code_size) {
266                 mb->code_size += 64;
267                 mb->code = g_realloc (mb->code, mb->code_size);
268         }
269
270         mb->code [mb->pos++] = op;
271 }
272
273 void
274 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
275 {
276         if ((mb->pos + 4) >= mb->code_size) {
277                 mb->code_size += 64;
278                 mb->code = g_realloc (mb->code, mb->code_size);
279         }
280
281         *((gint32 *)(&mb->code [mb->pos])) = data;
282         mb->pos += 4;
283 }
284
285 void
286 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
287 {
288         if ((mb->pos + 2) >= mb->code_size) {
289                 mb->code_size += 64;
290                 mb->code = g_realloc (mb->code, mb->code_size);
291         }
292
293         *((gint16 *)(&mb->code [mb->pos])) = data;
294         mb->pos += 2;
295 }
296
297 void
298 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
299 {
300         if (argnum < 4) {
301                 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
302         } else if (argnum < 256) {
303                 mono_mb_emit_byte (mb, CEE_LDARG_S);
304                 mono_mb_emit_byte (mb, argnum);
305         } else {
306                 mono_mb_emit_byte (mb, CEE_PREFIX1);
307                 mono_mb_emit_byte (mb, CEE_LDARG);
308                 mono_mb_emit_i4 (mb, argnum);
309         }
310 }
311
312 void
313 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
314 {
315         if (argnum < 256) {
316                 mono_mb_emit_byte (mb, CEE_LDARGA_S);
317                 mono_mb_emit_byte (mb, argnum);
318         } else {
319                 mono_mb_emit_byte (mb, CEE_PREFIX1);
320                 mono_mb_emit_byte (mb, CEE_LDARGA);
321                 mono_mb_emit_i4 (mb, argnum);
322         }
323 }
324
325 void
326 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
327 {
328         if (num < 4) {
329                 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
330         } else if (num < 256) {
331                 mono_mb_emit_byte (mb, CEE_LDLOC_S);
332                 mono_mb_emit_byte (mb, num);
333         } else {
334                 mono_mb_emit_byte (mb, CEE_PREFIX1);
335                 mono_mb_emit_byte (mb, CEE_LDLOC);
336                 mono_mb_emit_i4 (mb, num);
337         }
338 }
339
340 void
341 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
342 {
343         if (num < 4) {
344                 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
345         } else if (num < 256) {
346                 mono_mb_emit_byte (mb, CEE_STLOC_S);
347                 mono_mb_emit_byte (mb, num);
348         } else {
349                 mono_mb_emit_byte (mb, CEE_PREFIX1);
350                 mono_mb_emit_byte (mb, CEE_STLOC);
351                 mono_mb_emit_i4 (mb, num);
352         }
353 }
354
355 void
356 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
357 {
358         if (value >= -1 && value < 8) {
359                 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
360         } else if (value >= -128 && value <= 127) {
361                 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
362                 mono_mb_emit_byte (mb, value);
363         } else {
364                 mono_mb_emit_byte (mb, CEE_LDC_I4);
365                 mono_mb_emit_i4 (mb, value);
366         }
367 }
368
369 void
370 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
371 {
372         if (!opt_sig)
373                 opt_sig = method->signature;
374         mono_mb_emit_byte (mb, CEE_PREFIX1);
375         mono_mb_emit_byte (mb, CEE_LDFTN);
376         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
377         mono_mb_emit_byte (mb, CEE_CALLI);
378         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
379 }
380
381 void
382 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
383 {
384         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
385         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
386         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
387         mono_mb_emit_byte (mb, CEE_CALLI);
388         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
389 }
390
391 void
392 mono_mb_emit_exception (MonoMethodBuilder *mb)
393 {
394         mono_mb_emit_byte (mb, CEE_LDNULL);
395         mono_mb_emit_byte (mb, CEE_THROW);
396         
397 }
398
399 void
400 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint8 local, gint8 incr)
401 {
402         mono_mb_emit_ldloc (mb, local); 
403         mono_mb_emit_icon (mb, incr);
404         mono_mb_emit_byte (mb, CEE_ADD);
405         mono_mb_emit_stloc (mb, local); 
406 }
407
408 static void
409 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, int msize)
410 {
411         /* fixme: dont know what do do here - docs say 
412            this does not work for value types  */
413
414         g_warning ("not implemented");
415         g_assert_not_reached ();
416 }
417
418 static void
419 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, int msize)
420 {
421         switch (conv) {
422         case MONO_MARSHAL_CONV_BOOL_I4:
423                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
424                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
425                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
426                 mono_mb_emit_byte (mb, CEE_STIND_I4);
427                 break;
428         case MONO_MARSHAL_CONV_STR_LPWSTR:
429         case MONO_MARSHAL_CONV_STR_LPSTR:
430         case MONO_MARSHAL_CONV_STR_LPTSTR:
431         case MONO_MARSHAL_CONV_STR_BSTR:
432         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
433         case MONO_MARSHAL_CONV_STR_TBSTR:
434         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
435         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
436                 /* free space if ARG_2 == true */
437                 mono_mb_emit_byte (mb, CEE_LDARG_2);
438                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
439                 mono_mb_emit_byte (mb, 4);
440                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
441                 mono_mb_emit_byte (mb, CEE_LDIND_I);
442                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
443                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
444                 
445                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
446                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
447                 mono_mb_emit_byte (mb, CEE_LDIND_I);
448                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
449                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
450                 mono_mb_emit_byte (mb, conv);
451                 mono_mb_emit_byte (mb, CEE_STIND_I);
452                 break;
453         case MONO_MARSHAL_CONV_STR_BYVALSTR: 
454         case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
455                 if (!usize)
456                         break;
457
458                 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
459                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
460                 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
461                 mono_mb_emit_icon (mb, usize);
462                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
463                 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
464                 mono_mb_emit_byte (mb, conv);
465                 break;
466         }
467         case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
468                 if (!usize) 
469                         break;
470
471                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
472                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
473                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
474                 mono_mb_emit_byte (mb, 15);
475
476                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
477                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
478                 mono_mb_emit_byte (mb, CEE_LDIND_I);    
479                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
480                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
481                 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
482                 mono_mb_emit_byte (mb, CEE_ADD);
483                 mono_mb_emit_icon (mb, usize);
484                 mono_mb_emit_byte (mb, CEE_PREFIX1);
485                 mono_mb_emit_byte (mb, CEE_CPBLK);                      
486                 break;
487         }
488         case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
489         default:
490                 g_error ("marshalling conversion %d not implemented", conv);
491         }
492 }
493
494 static void
495 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
496 {
497         MonoMarshalType *info;
498         int i;
499
500         info = mono_marshal_load_type_info (klass);
501
502         for (i = 0; i < info->num_fields; i++) {
503                 MonoMarshalNative ntype;
504                 MonoMarshalConv conv;
505                 MonoType *ftype = info->fields [i].field->type;
506                 int msize = 0;
507                 int usize = 0;
508                 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
509
510                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
511                         continue;
512
513                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
514                         
515                 if (last_field) {
516                         msize = klass->instance_size - info->fields [i].field->offset;
517                         usize = info->native_size - info->fields [i].offset;
518                 } else {
519                         msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
520                         usize = info->fields [i + 1].offset - info->fields [i].offset;
521                 }
522                 g_assert (msize > 0 && usize > 0);
523
524                 switch (conv) {
525                 case MONO_MARSHAL_CONV_NONE:
526
527                         if (ftype->byref || ftype->type == MONO_TYPE_I ||
528                             ftype->type == MONO_TYPE_U) {
529                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
530                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
531                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
532                                 mono_mb_emit_byte (mb, CEE_STIND_I);
533                                 break;
534                         }
535
536                         switch (ftype->type) {
537                         case MONO_TYPE_I4:
538                         case MONO_TYPE_U4:
539                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
540                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
541                                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
542                                 mono_mb_emit_byte (mb, CEE_STIND_I4);
543                                 break;
544                         case MONO_TYPE_I1:
545                         case MONO_TYPE_U1:
546                         case MONO_TYPE_BOOLEAN:
547                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
548                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
549                                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
550                                 mono_mb_emit_byte (mb, CEE_STIND_I1);
551                                 break;
552                         case MONO_TYPE_I2:
553                         case MONO_TYPE_U2:
554                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
555                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
556                                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
557                                 mono_mb_emit_byte (mb, CEE_STIND_I2);
558                                 break;
559                         case MONO_TYPE_I8:
560                         case MONO_TYPE_U8:
561                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
562                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
563                                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
564                                 mono_mb_emit_byte (mb, CEE_STIND_I8);
565                                 break;
566                         case MONO_TYPE_R4:
567                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
568                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
569                                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
570                                 mono_mb_emit_byte (mb, CEE_STIND_R4);
571                                 break;
572                         case MONO_TYPE_R8:
573                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
574                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
575                                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
576                                 mono_mb_emit_byte (mb, CEE_STIND_R8);
577                                 break;
578                         case MONO_TYPE_VALUETYPE:
579                                 emit_struct_conv (mb, ftype->data.klass, to_object);
580                                 break;
581                         default:
582                                 g_error ("marshalling type %02x not implemented", ftype->type);
583                         }
584                         break;
585
586                 default:
587                         if (to_object) 
588                                 emit_ptr_to_str_conv (mb, conv, usize, msize);
589                         else
590                                 emit_str_to_ptr_conv (mb, conv, usize, msize);  
591                 }
592
593                 if (!last_field) {
594                         mono_mb_emit_add_to_local (mb, 0, msize);
595                         mono_mb_emit_add_to_local (mb, 1, usize);
596                 }               
597         }
598 }
599
600 static MonoObject *
601 delegate_test (MonoDelegate *delegate, gpointer *params)
602 {
603         g_assert_not_reached ();
604         return NULL;
605 }
606
607 MonoMethod *
608 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
609 {
610         MonoMethodSignature *sig;
611         static MonoMethodSignature *csig = NULL;
612         MonoMethodBuilder *mb;
613         MonoMethod *res;
614         MonoClass *ret_class;
615         MonoType *ret_type;
616         int i;
617
618         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
619                   !strcmp (method->name, "BeginInvoke"));
620
621         sig = method->signature;
622
623         if (sig->ret->byref)
624                 ret_type = &mono_defaults.int_class->byval_arg;
625         else if (sig->ret->type == MONO_TYPE_VALUETYPE && sig->ret->data.klass->enumtype)
626                 ret_type = sig->ret->data.klass->enum_basetype;
627         else 
628                 ret_type = sig->ret;
629
630         ret_class = mono_class_from_mono_type (ret_type);
631
632
633         if (!csig) {
634                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
635                 csig = g_malloc0 (sigsize);
636
637                 /* MonoObject *begin_invoke (MonoDelegate *delegate, gpointer params[]) */
638                 csig->param_count = 2;
639                 csig->ret = &mono_defaults.object_class->byval_arg;
640                 csig->params [0] = &mono_defaults.object_class->byval_arg;
641                 csig->params [1] = &mono_defaults.int_class->byval_arg;
642         }
643
644         mb = mono_mb_new (method->klass, method->name);
645
646         /* allocate local 0 (pointer) *params[] */
647         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
648         /* allocate local 1 (pointer) tmo */
649         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
650
651         /* alloate space on stack to store an array of pointers to the arguments */
652         mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
653         mono_mb_emit_byte (mb, CEE_PREFIX1);
654         mono_mb_emit_byte (mb, CEE_LOCALLOC);
655         mono_mb_emit_byte (mb, CEE_STLOC_0);
656
657         /* tmp = params */
658         mono_mb_emit_byte (mb, CEE_LDLOC_0);
659         mono_mb_emit_byte (mb, CEE_STLOC_1);
660
661         for (i = 0; i < sig->param_count; i++) {
662
663                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
664                 mono_mb_emit_ldarg_addr (mb, i);
665                 mono_mb_emit_byte (mb, CEE_STIND_I);
666                 /* tmp = tmp + sizeof (gpointer) */
667                 if (i < (sig->param_count - 1))
668                         mono_mb_emit_add_to_local (mb, 1, sizeof (gpointer));
669         }
670
671         mono_mb_emit_ldarg (mb, 0);
672         mono_mb_emit_byte (mb, CEE_LDLOC_0);
673         mono_mb_emit_native_call (mb, csig, delegate_test);
674
675         /* unbox the result if necessary */
676
677         switch (ret_type->type) {
678         case MONO_TYPE_STRING:
679         case MONO_TYPE_CLASS: 
680         case MONO_TYPE_OBJECT: 
681         case MONO_TYPE_ARRAY: 
682         case MONO_TYPE_SZARRAY: 
683         case MONO_TYPE_VOID:
684                 /* nothing to do */
685                 break;
686         case MONO_TYPE_U1:
687         case MONO_TYPE_I1:
688         case MONO_TYPE_BOOLEAN:
689         case MONO_TYPE_U2:
690         case MONO_TYPE_I2:
691         case MONO_TYPE_CHAR:
692         case MONO_TYPE_U:
693         case MONO_TYPE_I:
694         case MONO_TYPE_U4:
695         case MONO_TYPE_I4:
696         case MONO_TYPE_U8:
697         case MONO_TYPE_I8:
698         case MONO_TYPE_R4:
699         case MONO_TYPE_R8:
700         case MONO_TYPE_VALUETYPE:
701                 mono_mb_emit_byte (mb, CEE_UNBOX);
702                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, ret_class));
703                 break;
704         default:
705                 g_warning ("type 0x%x not handled", ret_type->type);
706                 g_assert_not_reached ();
707         }
708
709         mono_mb_emit_byte (mb, CEE_RET);
710
711         res = mono_mb_create_method (mb, sig, 0);
712         mono_mb_free (mb);
713         return res;
714 }
715
716 /*
717  * the returned method invokes all methods in a multicast delegate 
718  */
719 MonoMethod *
720 mono_marshal_get_delegate_invoke (MonoMethod *method)
721 {
722         MonoMethodSignature *sig, *static_sig;
723         int i, sigsize;
724         MonoMethodBuilder *mb;
725         MonoMethod *res;
726         GHashTable *cache;
727         int pos [3];
728
729         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
730                   !strcmp (method->name, "Invoke"));
731                 
732         cache = method->klass->image->delegate_invoke_cache;
733         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
734                 return res;
735
736         sig = method->signature;
737
738         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
739         static_sig = g_memdup (sig, sigsize);
740         static_sig->hasthis = 0;
741
742         mb = mono_mb_new (method->klass, method->name);
743
744         /* allocate local 0 (object) prev */
745         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
746         /* allocate local 1 (object) target */
747         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
748         /* allocate local 2 (pointer) mptr */
749         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
750
751         /* allocate local 3 to store the return value */
752         if (sig->ret->type != MONO_TYPE_VOID)
753                 mono_mb_add_local (mb, sig->ret);
754
755         g_assert (sig->hasthis);
756
757         /* prev = addr of delegate */
758         mono_mb_emit_ldarg (mb, 0);
759         mono_mb_emit_stloc (mb, 0);
760
761         /* loop */
762         pos [0] = mb->pos;
763         /* target = delegate->target */
764         mono_mb_emit_ldloc (mb, 0);
765         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
766         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
767         mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, target));
768         mono_mb_emit_byte (mb, CEE_ADD);
769         mono_mb_emit_byte (mb, CEE_LDIND_I);
770         mono_mb_emit_stloc (mb, 1);
771
772         /* mptr = delegate->method_ptr */
773         mono_mb_emit_ldloc (mb, 0);
774         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
775         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
776         mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
777         mono_mb_emit_byte (mb, CEE_ADD);
778         mono_mb_emit_byte (mb, CEE_LDIND_I);
779         mono_mb_emit_stloc (mb, 2);
780
781         /* target == null ? */
782         mono_mb_emit_ldloc (mb, 1);
783         mono_mb_emit_byte (mb, CEE_BRTRUE); 
784         pos [1] = mb->pos;
785         mono_mb_emit_i4 (mb, 0);
786
787         /* emit static method call */
788
789         for (i = 0; i < sig->param_count; i++)
790                 mono_mb_emit_ldarg (mb, i + 1);
791
792         mono_mb_emit_ldloc (mb, 2);
793         mono_mb_emit_byte (mb, CEE_CALLI);
794         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
795
796         if (sig->ret->type != MONO_TYPE_VOID)
797                 mono_mb_emit_stloc (mb, 3);
798
799         mono_mb_emit_byte (mb, CEE_BR);
800         pos [2] = mb->pos;
801         mono_mb_emit_i4 (mb, 0);
802    
803         /* target != null, emit non static method call */
804
805         mono_mb_patch_addr (mb, pos [1], mb->pos - (pos [1] + 4));
806         mono_mb_emit_ldloc (mb, 1);
807
808         for (i = 0; i < sig->param_count; i++)
809                 mono_mb_emit_ldarg (mb, i + 1);
810         
811         mono_mb_emit_ldloc (mb, 2);
812         mono_mb_emit_byte (mb, CEE_CALLI);
813         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
814
815         if (sig->ret->type != MONO_TYPE_VOID)
816                 mono_mb_emit_stloc (mb, 3);
817
818         mono_mb_patch_addr (mb, pos [2], mb->pos - (pos [2] + 4));
819
820         /* prev = delegate->prev */
821         mono_mb_emit_ldloc (mb, 0);
822         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
823         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
824         mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
825         mono_mb_emit_byte (mb, CEE_ADD);
826         mono_mb_emit_byte (mb, CEE_LDIND_I);
827         mono_mb_emit_stloc (mb, 0);
828
829         /* if prev != null goto loop */
830         mono_mb_emit_ldloc (mb, 0);
831         mono_mb_emit_byte (mb, CEE_BRTRUE);
832         mono_mb_emit_i4 (mb, pos [0] - (mb->pos + 4));
833
834         if (sig->ret->type != MONO_TYPE_VOID)
835                 mono_mb_emit_ldloc (mb, 3);
836
837         mono_mb_emit_byte (mb, CEE_RET);
838
839         res = mono_mb_create_method (mb, sig, 0);
840         mono_mb_free (mb);
841
842         g_hash_table_insert (cache, method, res);
843
844         return res;     
845 }
846
847 /*
848  * generates IL code for the runtime invoke function 
849  * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
850  *
851  * we also catch exceptions if exc != null
852  */
853 MonoMethod *
854 mono_marshal_get_runtime_invoke (MonoMethod *method)
855 {
856         MonoMethodSignature *sig, *csig;
857         MonoExceptionClause *clause;
858         MonoMethodHeader *header;
859         MonoMethodBuilder *mb;
860         MonoMethod *res;
861         GHashTable *cache;
862         static MonoString *string_dummy = NULL;
863         int i, pos, sigsize;
864
865         g_assert (method);
866
867         cache = method->klass->image->runtime_invoke_cache;
868         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
869                 return res;
870         
871         /* to make it work with our special string constructors */
872         if (!string_dummy)
873                 string_dummy = mono_string_new_wrapper ("dummy");
874
875         sig = method->signature;
876
877         sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
878         csig = g_malloc0 (sigsize);
879
880         csig->param_count = 3;
881         csig->ret = &mono_defaults.object_class->byval_arg;
882         csig->params [0] = &mono_defaults.object_class->byval_arg;
883         csig->params [1] = &mono_defaults.int_class->byval_arg;
884         csig->params [2] = &mono_defaults.int_class->byval_arg;
885
886         mb = mono_mb_new (method->klass, method->name);
887
888         /* allocate local 0 (object) tmp */
889         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
890         /* allocate local 1 (object) exc */
891         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
892
893
894         /* cond set *exc to null */
895         mono_mb_emit_byte (mb, CEE_LDARG_2);
896         mono_mb_emit_byte (mb, CEE_BRFALSE_S);
897         mono_mb_emit_byte (mb, 3);      
898         mono_mb_emit_byte (mb, CEE_LDARG_2);
899         mono_mb_emit_byte (mb, CEE_LDNULL);
900         mono_mb_emit_byte (mb, CEE_STIND_I);
901
902         if (sig->hasthis) {
903                 if (method->string_ctor) {
904                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
905                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
906                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
907                 } else {
908                         mono_mb_emit_ldarg (mb, 0);
909                 }
910         }
911
912         for (i = 0; i < sig->param_count; i++) {
913                 MonoType *t = sig->params [i];
914                 int type;
915
916                 mono_mb_emit_ldarg (mb, 1);
917                 if (i) {
918                         mono_mb_emit_icon (mb, sizeof (gpointer) * i);
919                         mono_mb_emit_byte (mb, CEE_ADD);
920                 }
921                 mono_mb_emit_byte (mb, CEE_LDIND_I);
922
923                 if (t->byref)
924                         continue;
925
926                 type = sig->params [i]->type;
927 handle_enum:
928                 switch (type) {
929                 case MONO_TYPE_I1:
930                         mono_mb_emit_byte (mb, CEE_LDIND_I1);
931                         break;
932                 case MONO_TYPE_BOOLEAN:
933                 case MONO_TYPE_U1:
934                         mono_mb_emit_byte (mb, CEE_LDIND_U1);
935                         break;
936                 case MONO_TYPE_I2:
937                         mono_mb_emit_byte (mb, CEE_LDIND_I2);
938                         break;
939                 case MONO_TYPE_U2:
940                 case MONO_TYPE_CHAR:
941                         mono_mb_emit_byte (mb, CEE_LDIND_U2);
942                         break;
943 #if SIZEOF_VOID_P == 4
944                 case MONO_TYPE_I:
945 #endif
946                 case MONO_TYPE_I4:
947                         mono_mb_emit_byte (mb, CEE_LDIND_I4);
948                         break;
949 #if SIZEOF_VOID_P == 4
950                 case MONO_TYPE_U:
951 #endif
952                 case MONO_TYPE_U4:
953                         mono_mb_emit_byte (mb, CEE_LDIND_U4);
954                         break;
955                 case MONO_TYPE_R4:
956                         mono_mb_emit_byte (mb, CEE_LDIND_R4);
957                         break;
958                 case MONO_TYPE_R8:
959                         mono_mb_emit_byte (mb, CEE_LDIND_R8);
960                         break;
961 #if SIZEOF_VOID_P == 8
962                 case MONO_TYPE_I:
963                 case MONO_TYPE_U:
964 #endif
965                 case MONO_TYPE_I8:
966                 case MONO_TYPE_U8:
967                         mono_mb_emit_byte (mb, CEE_LDIND_I8);
968                         break;
969                 case MONO_TYPE_STRING:
970                 case MONO_TYPE_CLASS:  
971                 case MONO_TYPE_ARRAY:
972                 case MONO_TYPE_PTR:
973                 case MONO_TYPE_SZARRAY:
974                 case MONO_TYPE_OBJECT:
975                         /* do nothing */
976                         break;
977                 case MONO_TYPE_VALUETYPE:
978                         if (t->data.klass->enumtype) {
979                                 type = t->data.klass->enum_basetype->type;
980                                 goto handle_enum;
981                         }
982                         g_assert_not_reached ();
983                         break;
984                 default:
985                         g_assert_not_reached ();
986                 }               
987         }
988
989         if (method->string_ctor) {
990                 MonoMethodSignature *strsig;
991
992                 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
993                 strsig = g_memdup (sig, sigsize);
994                 strsig->ret = &mono_defaults.string_class->byval_arg;
995
996                 mono_mb_emit_managed_call (mb, method, strsig);         
997         } else 
998                 mono_mb_emit_managed_call (mb, method, NULL);
999
1000         switch (sig->ret->type) {
1001         case MONO_TYPE_VOID:
1002                 if (!method->string_ctor)
1003                         mono_mb_emit_byte (mb, CEE_LDNULL);
1004                 break;
1005         case MONO_TYPE_I1:
1006         case MONO_TYPE_U1:
1007         case MONO_TYPE_I2:
1008         case MONO_TYPE_U2:
1009         case MONO_TYPE_I4:
1010         case MONO_TYPE_U4:
1011         case MONO_TYPE_I:
1012         case MONO_TYPE_U:
1013         case MONO_TYPE_R4:
1014         case MONO_TYPE_R8:
1015         case MONO_TYPE_I8:
1016         case MONO_TYPE_U8:
1017         case MONO_TYPE_VALUETYPE:
1018                 /* box value types */
1019                 mono_mb_emit_byte (mb, CEE_BOX);
1020                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1021                 break;
1022         case MONO_TYPE_STRING:
1023         case MONO_TYPE_CLASS:  
1024         case MONO_TYPE_ARRAY:
1025         case MONO_TYPE_SZARRAY:
1026         case MONO_TYPE_OBJECT:
1027                 /* nothing to do */
1028                 break;
1029         case MONO_TYPE_PTR:
1030         default:
1031                 g_assert_not_reached ();
1032         }
1033
1034         mono_mb_emit_stloc (mb, 0);
1035                 
1036         mono_mb_emit_byte (mb, CEE_LEAVE);
1037         pos = mb->pos;
1038         mono_mb_emit_i4 (mb, 0);
1039
1040         /* fixme: use a filter clause and only catch exceptions
1041          * when exc != null. With RETHROW we get wrong stack 
1042          * traces. */
1043         clause = g_new0 (MonoExceptionClause, 1);
1044         clause->flags = MONO_EXCEPTION_CLAUSE_NONE;
1045         clause->try_offset = 0;
1046         clause->try_len = mb->pos;
1047         clause->handler_offset = mb->pos;
1048
1049         /* handler code */
1050
1051         /* store exception */
1052         mono_mb_emit_stloc (mb, 1);
1053         
1054         mono_mb_emit_byte (mb, CEE_LDARG_2);
1055         mono_mb_emit_byte (mb, CEE_BRTRUE_S);
1056         mono_mb_emit_byte (mb, 2);
1057         mono_mb_emit_byte (mb, CEE_PREFIX1);
1058         mono_mb_emit_byte (mb, CEE_RETHROW);
1059         
1060         mono_mb_emit_byte (mb, CEE_LDARG_2);
1061         mono_mb_emit_ldloc (mb, 1);
1062         mono_mb_emit_byte (mb, CEE_STIND_I);
1063
1064         mono_mb_emit_byte (mb, CEE_LEAVE);
1065         mono_mb_emit_i4 (mb, 0);
1066
1067         clause->handler_len = mb->pos - clause->handler_offset;
1068
1069         /* return result */
1070         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1071         mono_mb_emit_ldloc (mb, 0);
1072         mono_mb_emit_byte (mb, CEE_RET);
1073         
1074         res = mono_mb_create_method (mb, csig, 0);
1075         mono_mb_free (mb);
1076
1077         header = ((MonoMethodNormal *)res)->header;
1078         header->num_clauses = 1;
1079         header->clauses = clause;
1080
1081         g_hash_table_insert (cache, method, res);
1082
1083         return res;     
1084 }
1085
1086 /*
1087  * generates IL code to call managed methods from unmanaged code 
1088  */
1089 MonoMethod *
1090 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1091 {
1092         MonoMethodSignature *sig, *csig;
1093         MonoMethodBuilder *mb;
1094         MonoMethod *res;
1095         GHashTable *cache;
1096         int i, sigsize;
1097
1098         g_assert (method != NULL);
1099
1100         cache = method->klass->image->managed_wrapper_cache;
1101         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1102                 return res;
1103
1104         sig = method->signature;
1105
1106         mb = mono_mb_new (method->klass, method->name);
1107
1108         /* we copy the signature, so that we can modify it */
1109         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1110         csig = g_memdup (sig, sigsize);
1111
1112         /* fixme: howto handle this ? */
1113         if (sig->hasthis) {
1114
1115                 if (this) {
1116                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1117                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1118                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1119
1120
1121                 } else {
1122                         /* fixme: */
1123                         g_assert_not_reached ();
1124                 }
1125         } 
1126
1127         for (i = 0; i < sig->param_count; i++) {
1128                 MonoType *t = sig->params [i];
1129
1130                 switch (t->type) {
1131                 case MONO_TYPE_I1:
1132                 case MONO_TYPE_U1:
1133                 case MONO_TYPE_I2:
1134                 case MONO_TYPE_U2:
1135                 case MONO_TYPE_I4:
1136                 case MONO_TYPE_U4:
1137                 case MONO_TYPE_I:
1138                 case MONO_TYPE_U:
1139                 case MONO_TYPE_PTR:
1140                 case MONO_TYPE_R4:
1141                 case MONO_TYPE_R8:
1142                 case MONO_TYPE_I8:
1143                 case MONO_TYPE_U8:
1144                         mono_mb_emit_ldarg (mb, i);
1145                         break;
1146                 case MONO_TYPE_STRING:
1147                         csig->params [i] = &mono_defaults.int_class->byval_arg;
1148                         mono_mb_emit_ldarg (mb, i);
1149                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1150                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1151                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1152                         break;  
1153                 case MONO_TYPE_CLASS:  
1154                 case MONO_TYPE_ARRAY:
1155                 case MONO_TYPE_SZARRAY:
1156                 case MONO_TYPE_OBJECT:
1157                         /* fixme: conversions ? */
1158                         mono_mb_emit_ldarg (mb, i);
1159                         break;
1160                 default:
1161                         g_warning ("type 0x%02x unknown", t->type);     
1162                         g_assert_not_reached ();
1163                 }
1164         }
1165
1166         mono_mb_emit_managed_call (mb, method, NULL);
1167         
1168         /* fixme: add return type conversions */
1169
1170         mono_mb_emit_byte (mb, CEE_RET);
1171
1172         res = mono_mb_create_method (mb, csig, 0);
1173         mono_mb_free (mb);
1174
1175         g_hash_table_insert (cache, method, res);
1176
1177         return res;
1178 }
1179
1180 /*
1181  * generates IL code for the pinvoke wrapper (the generated method
1182  * call the unamnage code in method->addr)
1183  */
1184 MonoMethod *
1185 mono_marshal_get_native_wrapper (MonoMethod *method)
1186 {
1187         MonoMethodSignature *sig, *csig;
1188         MonoMethodBuilder *mb;
1189         MonoMethod *res;
1190         GHashTable *cache;
1191         MonoClass *klass;
1192         gboolean pinvoke = FALSE;
1193         int i, argnum, *tmp_locals, sigsize;
1194
1195         g_assert (method != NULL);
1196
1197         cache = method->klass->image->native_wrapper_cache;
1198         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1199                 return res;
1200
1201         sig = method->signature;
1202
1203         if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
1204             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
1205                 pinvoke = TRUE;
1206
1207         mb = mono_mb_new (method->klass, method->name);
1208
1209         mb->method->save_lmf = 1;
1210
1211         if (pinvoke && !method->addr)
1212                 mono_lookup_pinvoke_call (method);
1213
1214         if (!method->addr) {
1215                 mono_mb_emit_exception (mb);
1216                 res = mono_mb_create_method (mb, sig, 0);
1217                 mono_mb_free (mb);
1218                 g_hash_table_insert (cache, method, res);
1219                 return res;
1220         }
1221
1222         /* we copy the signature, so that we can modify it */
1223         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1224         csig = g_memdup (sig, sigsize);
1225
1226         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
1227
1228                 if (method->string_ctor)
1229                         csig->ret = &mono_defaults.string_class->byval_arg;
1230
1231                 if (sig->hasthis)
1232                         mono_mb_emit_byte (mb, CEE_LDARG_0);
1233
1234                 for (i = 0; i < sig->param_count; i++)
1235                         mono_mb_emit_ldarg (mb, i + sig->hasthis);
1236
1237                 g_assert (method->addr);
1238                 mono_mb_emit_native_call (mb, csig, method->addr);
1239
1240                 mono_mb_emit_byte (mb, CEE_RET);
1241
1242                 res = mono_mb_create_method (mb, csig, 0);
1243                 mono_mb_free (mb);
1244                 g_hash_table_insert (cache, method, res);
1245                 return res;
1246         }
1247
1248         g_assert (pinvoke);
1249
1250         /* we allocate local for use with emit_struct_conv() */
1251         /* allocate local 0 (pointer) src_ptr */
1252         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1253         /* allocate local 1 (pointer) dst_ptr */
1254         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1255         /* allocate local 2 (pointer) as tmp/scratch storage */
1256         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1257
1258         if (sig->ret->type != MONO_TYPE_VOID) {
1259                 /* allocate local 3 to store the return value */
1260                 mono_mb_add_local (mb, sig->ret);
1261         }
1262
1263         /* we first do all conversions */
1264         tmp_locals = alloca (sizeof (int) * sig->param_count);
1265         for (i = 0; i < sig->param_count; i ++) {
1266                 MonoType *t = sig->params [i];
1267
1268                 argnum = i + sig->hasthis;
1269
1270                 /* allocate one tmp/scratch storage for each parameter */
1271                 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1272
1273                 switch (t->type) {
1274                 case MONO_TYPE_VALUETYPE:
1275                         klass = sig->params [i]->data.klass;
1276                         if (klass->enumtype)
1277                                 break;
1278                         
1279                         /* store the address of the source into local variable 0 */
1280                         mono_mb_emit_byte (mb, CEE_LDARGA);
1281                         mono_mb_emit_i2 (mb, argnum);
1282                         mono_mb_emit_byte (mb, CEE_STLOC_0);
1283                         
1284                         /* allocate space for the native struct and
1285                          * store the address into local variable 1 (dest) */
1286                         mono_mb_emit_icon (mb, mono_class_native_size (klass));
1287                         mono_mb_emit_byte (mb, CEE_LOCALLOC);
1288                         mono_mb_emit_stloc (mb, tmp_locals [i]);
1289                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1290                         mono_mb_emit_byte (mb, CEE_STLOC_1);
1291
1292                         /* emit valuetype convnversion code code */
1293                         emit_struct_conv (mb, sig->params [i]->data.klass, FALSE);
1294
1295                         break;
1296                 case MONO_TYPE_STRING:
1297                         /* fixme: load the address instead */
1298                         mono_mb_emit_ldarg (mb, argnum);
1299                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1300                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1301                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1302                         mono_mb_emit_stloc (mb, tmp_locals [i]);
1303                         break;
1304                 case MONO_TYPE_CLASS:
1305                 case MONO_TYPE_OBJECT:
1306                         if (t->data.klass->delegate) {
1307                                 mono_mb_emit_ldarg (mb, argnum);
1308                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1309                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1310                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
1311                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
1312                         } else {
1313                                 mono_mb_emit_ldarg (mb, argnum);
1314                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1315                                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1316                                 /* fixme: convert to what ? */
1317                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
1318                         }
1319                         break;
1320                 }
1321         }
1322
1323         /* push all arguments */
1324
1325         if (sig->hasthis)
1326                 mono_mb_emit_byte (mb, CEE_LDARG_0);
1327
1328         for (i = 0; i < sig->param_count; i++) {
1329                 MonoType *t = sig->params [i];
1330                 
1331                 argnum = i + sig->hasthis;
1332
1333                 if (t->byref) {
1334                         mono_mb_emit_ldarg (mb, argnum);
1335                         continue;
1336                 }
1337
1338                 switch (t->type) {
1339                 case MONO_TYPE_BOOLEAN:
1340                         mono_mb_emit_ldarg (mb, argnum);
1341                         break;
1342                 case MONO_TYPE_I1:
1343                 case MONO_TYPE_U1:
1344                 case MONO_TYPE_I2:
1345                 case MONO_TYPE_U2:
1346                 case MONO_TYPE_I4:
1347                 case MONO_TYPE_U4:
1348                 case MONO_TYPE_I:
1349                 case MONO_TYPE_U:
1350                 case MONO_TYPE_PTR:
1351                 case MONO_TYPE_R4:
1352                 case MONO_TYPE_R8:
1353                 case MONO_TYPE_I8:
1354                 case MONO_TYPE_U8:
1355                         mono_mb_emit_ldarg (mb, argnum);
1356                         break;
1357                 case MONO_TYPE_VALUETYPE:
1358                         klass = sig->params [i]->data.klass;
1359                         if (klass->enumtype) {
1360                                 mono_mb_emit_ldarg (mb, argnum);
1361                                 break;
1362                         }                       
1363                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1364                         //mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1365                         //mono_mb_emit_byte (mb, CEE_MONO_LDOBJ);
1366                         //mono_mb_emit_i4 (mb, mono_klass_native_size (klass));
1367
1368                         break;
1369                 case MONO_TYPE_STRING:
1370                         /* fixme: load the address instead */
1371                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1372                         break;
1373                 case MONO_TYPE_CLASS:
1374                 case MONO_TYPE_OBJECT:
1375                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1376                         break;
1377                 case MONO_TYPE_CHAR:
1378                 case MONO_TYPE_ARRAY:
1379                 case MONO_TYPE_SZARRAY:
1380                 case MONO_TYPE_TYPEDBYREF:
1381                 case MONO_TYPE_FNPTR:
1382                 default:
1383                         g_warning ("type 0x%02x unknown", t->type);     
1384                         g_assert_not_reached ();
1385                 }
1386         }                       
1387
1388         /* call the native method */
1389         mono_mb_emit_native_call (mb, csig, method->addr);
1390
1391         switch (sig->ret->type) {
1392         case MONO_TYPE_VOID:
1393         case MONO_TYPE_I1:
1394         case MONO_TYPE_U1:
1395         case MONO_TYPE_I2:
1396         case MONO_TYPE_U2:
1397         case MONO_TYPE_I4:
1398         case MONO_TYPE_U4:
1399         case MONO_TYPE_I:
1400         case MONO_TYPE_U:
1401         case MONO_TYPE_PTR:
1402         case MONO_TYPE_R4:
1403         case MONO_TYPE_R8:
1404         case MONO_TYPE_I8:
1405         case MONO_TYPE_U8:
1406                 /* no conversions necessary */
1407                 break;
1408         case MONO_TYPE_BOOLEAN:
1409                 /* maybe we need to make sure that it fits within 8 bits */
1410                 break;
1411         case MONO_TYPE_STRING:
1412                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1413                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1414                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1415                 break;
1416         case MONO_TYPE_ARRAY:
1417         case MONO_TYPE_SZARRAY:
1418         case MONO_TYPE_CLASS:
1419         case MONO_TYPE_OBJECT:
1420                 /* fixme: we need conversions here */
1421                 break;
1422         case MONO_TYPE_CHAR:
1423         case MONO_TYPE_TYPEDBYREF:
1424         case MONO_TYPE_FNPTR:
1425         default:
1426                 g_warning ("return type 0x%02x unknown", sig->ret->type);       
1427                 g_assert_not_reached ();
1428         }
1429
1430         mono_mb_emit_byte (mb, CEE_RET);
1431
1432         res = mono_mb_create_method (mb, sig, 0);
1433         mono_mb_free (mb);
1434
1435         g_hash_table_insert (cache, method, res);
1436
1437         return res;
1438 }
1439
1440 /*
1441  * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
1442  */
1443 MonoMethod *
1444 mono_marshal_get_struct_to_ptr (MonoClass *klass)
1445 {
1446         MonoMethodBuilder *mb;
1447         static MonoMethod *stoptr = NULL;
1448         MonoMethod *res;
1449
1450         g_assert (klass != NULL);
1451
1452         if (klass->str_to_ptr)
1453                 return klass->str_to_ptr;
1454
1455         if (!stoptr) 
1456                 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
1457         g_assert (stoptr);
1458
1459         mb = mono_mb_new (stoptr->klass, stoptr->name);
1460
1461         /* allocate local 0 (pointer) src_ptr */
1462         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1463         /* allocate local 1 (pointer) dst_ptr */
1464         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1465         /* allocate local 2 (pointer) as tmp/scratch storage */
1466         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1467
1468         /* initialize src_ptr to point to the start of object data */
1469         mono_mb_emit_byte (mb, CEE_LDARG_0);
1470         mono_mb_emit_icon (mb, sizeof (MonoObject));
1471         mono_mb_emit_byte (mb, CEE_ADD);
1472         mono_mb_emit_byte (mb, CEE_STLOC_0);
1473
1474         /* initialize dst_ptr */
1475         mono_mb_emit_byte (mb, CEE_LDARG_1);
1476         mono_mb_emit_byte (mb, CEE_STLOC_1);
1477
1478         emit_struct_conv (mb, klass, FALSE);
1479
1480         mono_mb_emit_byte (mb, CEE_RET);
1481
1482         res = mono_mb_create_method (mb, stoptr->signature, 0);
1483         mono_mb_free (mb);
1484
1485         klass->str_to_ptr = res;
1486         return res;
1487 }
1488
1489 /*
1490  * generates IL code for PtrToStructure (IntPtr src, object structure)
1491  */
1492 MonoMethod *
1493 mono_marshal_get_ptr_to_struct (MonoClass *klass)
1494 {
1495         MonoMethodBuilder *mb;
1496         static MonoMethod *ptostr = NULL;
1497         MonoMethod *res;
1498
1499         g_assert (klass != NULL);
1500
1501         if (klass->ptr_to_str)
1502                 return klass->ptr_to_str;
1503
1504         if (!ptostr) 
1505                 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
1506         g_assert (ptostr);
1507
1508         mb = mono_mb_new (ptostr->klass, ptostr->name);
1509
1510         /* allocate local 0 (pointer) src_ptr */
1511         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1512         /* allocate local 1 (pointer) dst_ptr */
1513         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1514         /* allocate local 2 (pointer) as tmp/scratch storage */
1515         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1516
1517         /* initialize src_ptr to point to the start of object data */
1518         mono_mb_emit_byte (mb, CEE_LDARG_0);
1519         mono_mb_emit_byte (mb, CEE_STLOC_0);
1520
1521         /* initialize dst_ptr */
1522         mono_mb_emit_byte (mb, CEE_LDARG_1);
1523         mono_mb_emit_icon (mb, sizeof (MonoObject));
1524         mono_mb_emit_byte (mb, CEE_ADD);
1525         mono_mb_emit_byte (mb, CEE_STLOC_1);
1526
1527         emit_struct_conv (mb, klass, TRUE);
1528
1529         mono_mb_emit_byte (mb, CEE_RET);
1530
1531         res = mono_mb_create_method (mb, ptostr->signature, 0);
1532         mono_mb_free (mb);
1533
1534         klass->ptr_to_str = res;
1535         return res;
1536 }
1537
1538 /* FIXME: on win32 we should probably use GlobalAlloc(). */
1539 void*
1540 mono_marshal_alloc (gpointer size) {
1541         return g_try_malloc ((gulong)size);
1542 }
1543
1544 void
1545 mono_marshal_free (gpointer ptr) {
1546         g_free (ptr);
1547 }
1548
1549 void*
1550 mono_marshal_realloc (gpointer ptr, gpointer size) {
1551         return g_try_realloc (ptr, (gulong)size);
1552 }
1553
1554 void*
1555 mono_marshal_string_array (MonoArray *array)
1556 {
1557         char **result;
1558         int i, len;
1559
1560         if (!array)
1561                 return NULL;
1562
1563         len = mono_array_length (array);
1564
1565         result = g_malloc (sizeof (char*) * len);
1566         for (i = 0; i < len; ++i) {
1567                 MonoString *s = (MonoString*)mono_array_get (array, gpointer, i);
1568                 result [i] = s ? mono_string_to_utf8 (s): NULL;
1569         }
1570         return result;
1571 }
1572
1573 void
1574 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
1575                                                                     gpointer dest, gint32 length)
1576 {
1577         int element_size;
1578         void *source_addr;
1579
1580         MONO_CHECK_ARG_NULL (src);
1581         MONO_CHECK_ARG_NULL (dest);
1582
1583         g_assert (src->obj.vtable->klass->rank == 1);
1584         g_assert (start_index >= 0 && start_index < mono_array_length (src));
1585         g_assert (start_index + length <= mono_array_length (src));
1586
1587         element_size = mono_array_element_size (src->obj.vtable->klass);
1588           
1589         source_addr = mono_array_addr_with_size (src, element_size, start_index);
1590
1591         memcpy (dest, source_addr, length * element_size);
1592 }
1593
1594 void
1595 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
1596                                                                       MonoArray *dest, gint32 length)
1597 {
1598         int element_size;
1599         void *dest_addr;
1600
1601         MONO_CHECK_ARG_NULL (src);
1602         MONO_CHECK_ARG_NULL (dest);
1603
1604         g_assert (dest->obj.vtable->klass->rank == 1);
1605         g_assert (start_index >= 0 && start_index < mono_array_length (dest));
1606         g_assert (start_index + length <= mono_array_length (dest));
1607
1608         element_size = mono_array_element_size (dest->obj.vtable->klass);
1609           
1610         dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
1611
1612         memcpy (dest_addr, src, length * element_size);
1613 }
1614
1615 gpointer
1616 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
1617 {
1618         char *p = ptr;
1619         return *(gpointer*)(p + offset);
1620 }
1621
1622 unsigned char
1623 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
1624 {
1625         char *p = ptr;
1626         return *(unsigned char*)(p + offset);
1627 }
1628
1629 gint16
1630 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
1631 {
1632         char *p = ptr;
1633         return *(gint16*)(p + offset);
1634 }
1635
1636 gint32
1637 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
1638 {
1639         char *p = ptr;
1640         return *(gint32*)(p + offset);
1641 }
1642
1643 gint64
1644 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
1645 {
1646         char *p = ptr;
1647         return *(gint64*)(p + offset);
1648 }
1649
1650 void
1651 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
1652 {
1653         char *p = ptr;
1654         *(unsigned char*)(p + offset) = val;
1655 }
1656
1657 void
1658 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
1659 {
1660         char *p = ptr;
1661         *(gpointer*)(p + offset) = val;
1662 }
1663
1664 void
1665 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
1666 {
1667         char *p = ptr;
1668         *(gint16*)(p + offset) = val;
1669 }
1670
1671 void
1672 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
1673 {
1674         char *p = ptr;
1675         *(gint32*)(p + offset) = val;
1676 }
1677
1678 void
1679 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
1680 {
1681         char *p = ptr;
1682         *(gint64*)(p + offset) = val;
1683 }
1684
1685 MonoString*
1686 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAuto (gpointer ptr)
1687 {
1688         MonoDomain *domain = mono_domain_get (); 
1689
1690         return mono_string_new (domain, (char *)ptr);
1691 }
1692
1693 guint32 
1694 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
1695 {
1696         return (GetLastError ());
1697 }
1698
1699 guint32 
1700 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
1701 {
1702         MonoClass *klass;
1703
1704         MONO_CHECK_ARG_NULL (rtype);
1705
1706         klass = mono_class_from_mono_type (rtype->type);
1707
1708         return mono_class_native_size (klass);
1709 }
1710
1711 void
1712 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
1713 {
1714         MonoMethod *method;
1715         gpointer pa [3];
1716
1717         MONO_CHECK_ARG_NULL (obj);
1718         MONO_CHECK_ARG_NULL (dst);
1719
1720         method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
1721
1722         pa [0] = obj;
1723         pa [1] = &dst;
1724         pa [2] = &delete_old;
1725
1726         mono_runtime_invoke (method, NULL, pa, NULL);
1727 }
1728
1729 void
1730 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
1731 {
1732         MonoMethod *method;
1733         gpointer pa [2];
1734
1735         MONO_CHECK_ARG_NULL (src);
1736         MONO_CHECK_ARG_NULL (dst);
1737
1738         method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
1739
1740         pa [0] = &src;
1741         pa [1] = dst;
1742
1743         mono_runtime_invoke (method, NULL, pa, NULL);
1744 }