2002-02-19 Radek Doulik <rodo@ximian.com>
[mono.git] / mono / arch / ppc / tramp.c
1 /*
2  * Create trampolines to invoke arbitrary functions.
3  * 
4  * Copyright (C) Radek Doulik
5  * 
6  */
7
8 #include "config.h"
9 #include <stdlib.h>
10 #include "ppc-codegen.h"
11 #include "mono/metadata/class.h"
12 #include "mono/metadata/tabledefs.h"
13 #include "mono/interpreter/interp.h"
14 #include "mono/metadata/appdomain.h"
15
16 #ifdef NEED_MPROTECT
17 #include <sys/mman.h>
18 #include <limits.h>    /* for PAGESIZE */
19 #ifndef PAGESIZE
20 #define PAGESIZE 4096
21 #endif
22 #endif
23
24 /* gpointer
25 fake_func (gpointer (*callme)(gpointer), stackval *retval, void *this_obj, stackval *arguments)
26 {
27         guint32 i = 0xc002becd;
28
29         callme = (gpointer) 0x100fabcd;
30
31         *(gpointer*)retval = (gpointer)(*callme) (arguments [0].data.p, arguments [1].data.p, arguments [2].data.p);
32         *(gdouble*) retval = (gdouble)(*callme) (arguments [0].data.f);
33
34         return (gpointer) (*callme) (((MonoType *)arguments [0]. data.p)->data.klass);
35 } */
36
37 #define MIN_CACHE_LINE 8
38
39 static void inline
40 flush_icache (guint8 *code, guint size)
41 {
42         guint i;
43         guint8 *p;
44
45         p = code;
46         for (i = 0; i < size; i += MIN_CACHE_LINE, p += MIN_CACHE_LINE) {
47                 asm ("dcbst 0,%0;" : : "r"(p) : "memory");
48         }
49         asm ("sync");
50         p = code;
51         for (i = 0; i < size; i += MIN_CACHE_LINE, p += MIN_CACHE_LINE) {
52                 asm ("icbi 0,%0; sync;" : : "r"(p) : "memory");
53         }
54         asm ("sync");
55         asm ("isync");
56 }
57
58 #define NOT_IMPLEMENTED(x) \
59                 g_error ("FIXME: %s is not yet implemented. (trampoline)", x);
60
61 #define PROLOG_INS 8
62 #define CALL_INS   2
63 #define EPILOG_INS 6
64 #define MINIMAL_STACK_SIZE 5
65 #define FLOAT_REGS 8
66 #define GENERAL_REGS 8
67
68 static void inline
69 add_general (guint *gr, guint *stack_size, guint *code_size, gboolean simple)
70 {
71         if (simple) {
72                 if (*gr >= GENERAL_REGS) {
73                         *stack_size += 4;
74                         *code_size += 8;    /* load from stack, save on stack */
75                 } else {
76                         *code_size += 4;    /* load from stack */
77                 }
78         } else {
79                 if (*gr >= GENERAL_REGS - 1) {
80                         *stack_size += 8 + (*stack_size % 8);
81                         *code_size += 16;   /* 2x load from stack, save to stack */
82                 } else {
83                         *code_size += 16;   /* 2x load from stack */
84                 }
85                 if ((*gr) && 1)
86                         (*gr) ++;
87                 (*gr) ++;
88         }
89         (*gr) ++;
90 }
91
92 static void inline
93 calculate_sizes (MonoMethod *method, guint *stack_size, guint *code_size, guint *strings, gint runtime)
94 {
95         MonoMethodSignature *sig;
96         guint i, fr, gr;
97         guint32 simpletype;
98
99         fr = gr = 0;
100         *stack_size = MINIMAL_STACK_SIZE*4;
101         *code_size  = (PROLOG_INS + CALL_INS + EPILOG_INS)*4;
102         *strings = 0;
103
104         sig = method->signature;
105         if (sig->hasthis) {
106                 add_general (&gr, stack_size, code_size, TRUE);
107         }
108
109         for (i = 0; i < sig->param_count; ++i) {
110                 if (sig->params [i]->byref) {
111                         add_general (&gr, stack_size, code_size, TRUE);
112                         continue;
113                 }
114                 simpletype = sig->params [i]->type;
115         enum_calc_size:
116                 switch (simpletype) {
117                 case MONO_TYPE_BOOLEAN:
118                 case MONO_TYPE_CHAR:
119                 case MONO_TYPE_I1:
120                 case MONO_TYPE_U1:
121                 case MONO_TYPE_I2:
122                 case MONO_TYPE_U2:
123                 case MONO_TYPE_I4:
124                 case MONO_TYPE_U4:
125                 case MONO_TYPE_I:
126                 case MONO_TYPE_U:
127                 case MONO_TYPE_PTR:
128                 case MONO_TYPE_SZARRAY:
129                 case MONO_TYPE_CLASS:
130                 case MONO_TYPE_OBJECT:
131                         add_general (&gr, stack_size, code_size, TRUE);
132                         break;
133                 case MONO_TYPE_VALUETYPE:
134                         if (sig->params [i]->data.klass->enumtype) {
135                                 simpletype = sig->params [i]->data.klass->enum_basetype->type;
136                                 goto enum_calc_size;
137                         }
138                         if (mono_class_value_size (sig->params [i]->data.klass, NULL) != 4)
139                                 g_error ("can only marshal enums, not generic structures (size: %d)",
140                                          mono_class_value_size (sig->params [i]->data.klass, NULL));
141                         add_general (&gr, stack_size, code_size, TRUE);
142                         *code_size += 4;
143                         break;
144                 case MONO_TYPE_STRING:
145                         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || runtime) {
146                                 add_general (&gr, stack_size, code_size, TRUE);
147                                 break;
148                         }
149                         (*strings) ++;
150                         *code_size += 12*4;
151                         *stack_size += 4;
152                         break;
153                 case MONO_TYPE_I8:
154                         add_general (&gr, stack_size, code_size, FALSE);
155                         break;
156                 case MONO_TYPE_R4:
157                 case MONO_TYPE_R8:
158                         if (fr < 7) {
159                                 *code_size += 4;
160                                 fr ++;
161                         } else {
162                                 NOT_IMPLEMENTED ("R8 arg");
163                         }
164                         break;
165                 default:
166                         g_error ("Can't trampoline 0x%x", sig->params [i]->type);
167                 }
168         }
169
170         if (sig->ret->byref) {
171                 *code_size += 8;
172         } else {
173                 simpletype = sig->ret->type;
174 enum_retvalue:
175                 switch (simpletype) {
176                 case MONO_TYPE_BOOLEAN:
177                 case MONO_TYPE_I1:
178                 case MONO_TYPE_U1:
179                 case MONO_TYPE_I2:
180                 case MONO_TYPE_U2:
181                 case MONO_TYPE_CHAR:
182                 case MONO_TYPE_I4:
183                 case MONO_TYPE_U4:
184                 case MONO_TYPE_I:
185                 case MONO_TYPE_U:
186                 case MONO_TYPE_CLASS:
187                 case MONO_TYPE_OBJECT:
188                 case MONO_TYPE_R4:
189                 case MONO_TYPE_R8:
190                 case MONO_TYPE_SZARRAY:
191                 case MONO_TYPE_ARRAY:
192                         *code_size += 8;
193                         break;
194                 case MONO_TYPE_STRING:
195                         *code_size += 8;
196                         if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && !runtime) {
197                                 *code_size += 16;
198                         }
199                         break;
200                 case MONO_TYPE_I8:
201                         *code_size += 12;
202                         break;
203                 case MONO_TYPE_VALUETYPE:
204                         if (sig->ret->data.klass->enumtype) {
205                                 simpletype = sig->ret->data.klass->enum_basetype->type;
206                                 goto enum_retvalue;
207                         }
208                         NOT_IMPLEMENTED ("valuetype");
209                         break;
210                 case MONO_TYPE_VOID:
211                         break;
212                 default:
213                         g_error ("Can't handle as return value 0x%x", sig->ret->type);
214                 }
215         }
216
217         if (*strings) {
218                 /* space to keep parameters and prepared strings */
219                  *stack_size += 8;
220                  *code_size += 16;
221                  if (sig->hasthis) {
222                          *stack_size += 4;
223                          *code_size  += 12;
224                  }
225         }
226         /* align stack size to 16 */
227         printf ("      stack size: %d (%d)\n       code size: %d\n", (*stack_size + 15) & ~15, *stack_size, *code_size);
228         *stack_size = (*stack_size + 15) & ~15;
229
230 }
231
232 static inline guint8 *
233 emit_prolog (guint8 *p, MonoMethod *method, guint stack_size, guint strings)
234 {
235         /* function prolog */
236         ppc_stwu (p, ppc_r1, -stack_size, ppc_r1);     /* sp      <--- sp - stack_size, sp[0] <---- sp save sp, alloc stack */
237         ppc_mflr (p, ppc_r0);                          /* r0      <--- LR */
238         ppc_stw  (p, ppc_r31, stack_size - 4, ppc_r1); /* sp[+4]  <--- r31     save r31 */
239         ppc_stw  (p, ppc_r0, stack_size + 4, ppc_r1);  /* sp[-4]  <--- LR      save return address for "callme" */
240         ppc_mr   (p, ppc_r31, ppc_r1);                 /* r31     <--- sp */
241
242         /* handle our parameters */
243         if (strings) {
244                 ppc_stw  (p, ppc_r30, stack_size - 16, ppc_r1);
245                 ppc_stw  (p, ppc_r29, stack_size - 12, ppc_r1);
246                 if (method->signature->hasthis) {
247                         ppc_stw  (p, ppc_r28, 24, ppc_r1);
248                 }
249                 ppc_mr   (p, ppc_r30, ppc_r6);                        /* args */
250                 ppc_mr   (p, ppc_r29, ppc_r3);                        /* callme */
251                 if (method->signature->hasthis) {
252                         ppc_mr   (p, ppc_r28, ppc_r5);                /* this */
253                 }
254         } else {
255                 ppc_mr   (p, ppc_r12, ppc_r6);                        /* keep "arguments" in register */
256                 ppc_mr   (p, ppc_r0, ppc_r3);                         /* keep "callme" in register */
257         }
258         ppc_stw  (p, ppc_r4, 8, ppc_r31);                             /* preserve "retval", sp[+8] */
259
260         return p;
261 }
262
263 #define ARG_BASE strings ? ppc_r30 : ppc_r12
264 #define SAVE_4_IN_GENERIC_REGISTER \
265                         if (gr < GENERAL_REGS) { \
266                                 ppc_lwz  (p, ppc_r3 + gr, i*16, ARG_BASE); \
267                                 gr ++; \
268                         } else { \
269                                 NOT_IMPLEMENTED("save on stack"); \
270                         }
271 #define SAVE_2_IN_GENERIC_REGISTER \
272                         if (gr < GENERAL_REGS) { \
273                                 ppc_lhz  (p, ppc_r3 + gr, i*16, ARG_BASE); \
274                                 gr ++; \
275                         } else { \
276                                 NOT_IMPLEMENTED("save on stack"); \
277                         }
278 #define SAVE_1_IN_GENERIC_REGISTER \
279                         if (gr < GENERAL_REGS) { \
280                                 ppc_lbz  (p, ppc_r3 + gr, i*16, ARG_BASE); \
281                                 gr ++; \
282                         } else { \
283                                 NOT_IMPLEMENTED("save on stack"); \
284                         }
285
286 inline static guint8*
287 emit_save_parameters (guint8 *p, MonoMethod *method, guint stack_size, guint strings, gint runtime)
288 {
289         MonoMethodSignature *sig;
290         guint i, fr, gr, act_strs;
291         guint32 simpletype;
292
293         fr = gr = 0;
294         act_strs = 0;
295         sig = method->signature;
296
297         if (strings) {
298                 for (i = 0; i < sig->param_count; ++i) {
299                         if (!sig->params [i]->byref && sig->params [i]->type == MONO_TYPE_STRING
300                             && !((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || runtime)) {
301                                 ppc_lis  (p, ppc_r0,     (guint32) mono_string_to_utf8 >> 16);
302                                 ppc_lwz  (p, ppc_r3, i*16, ppc_r30);
303                                 ppc_ori  (p, ppc_r0, ppc_r0, (guint32) mono_string_to_utf8 & 0xffff);
304                                 ppc_mtlr (p, ppc_r0);
305                                 ppc_blrl (p);
306                                 ppc_stw  (p, ppc_r3, stack_size - 20 - act_strs, ppc_r31);
307                                 act_strs += 4;
308                         }
309                 }
310         }
311
312         if (sig->hasthis) {
313                 ppc_mr (p, ppc_r3, ppc_r5);
314                 gr ++;
315         }
316
317         act_strs = 0;
318         for (i = 0; i < sig->param_count; ++i) {
319                 if (sig->params [i]->byref) {
320                         SAVE_4_IN_GENERIC_REGISTER;
321                         continue;
322                 }
323                 simpletype = sig->params [i]->type;
324         enum_calc_size:
325                 switch (simpletype) {
326                 case MONO_TYPE_BOOLEAN:
327                 case MONO_TYPE_I1:
328                 case MONO_TYPE_U1:
329                         SAVE_1_IN_GENERIC_REGISTER;
330                         break;
331                 case MONO_TYPE_I2:
332                 case MONO_TYPE_U2:
333                 case MONO_TYPE_CHAR:
334                         SAVE_2_IN_GENERIC_REGISTER;
335                         break;
336                 case MONO_TYPE_I4:
337                 case MONO_TYPE_U4:
338                 case MONO_TYPE_I:
339                 case MONO_TYPE_U:
340                 case MONO_TYPE_PTR:
341                 case MONO_TYPE_SZARRAY:
342                 case MONO_TYPE_CLASS:
343                 case MONO_TYPE_OBJECT:
344                         SAVE_4_IN_GENERIC_REGISTER;
345                         break;
346                 case MONO_TYPE_VALUETYPE:
347                         if (sig->params [i]->data.klass->enumtype) {
348                                 simpletype = sig->params [i]->data.klass->enum_basetype->type;
349                                 goto enum_calc_size;
350                         }
351                         if (mono_class_value_size (sig->params [i]->data.klass, NULL) != 4)
352                                 g_error ("can only marshal enums, not generic structures (size: %d)",
353                                          mono_class_value_size (sig->params [i]->data.klass, NULL));
354                         if (gr < GENERAL_REGS) {
355                                 ppc_lwz  (p, ppc_r3 + gr, i*16, ARG_BASE);
356                                 ppc_lwz  (p, ppc_r3 + gr, 0, ppc_r3 + gr);
357                                 gr ++;
358                         } else {
359                                 NOT_IMPLEMENTED ("save value type on stack");
360                         }
361                         break;
362                 case MONO_TYPE_STRING:
363                         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || runtime) {
364                                 SAVE_4_IN_GENERIC_REGISTER;
365                         } else {
366                                 if (gr < 8) {
367                                         ppc_lwz (p, ppc_r3 + gr, stack_size - 20 - act_strs, ppc_r31);
368                                         gr ++;
369                                         act_strs += 4;
370                                 } else
371                                         NOT_IMPLEMENTED ("string on stack");
372                         }
373                         break;
374                 case MONO_TYPE_I8:
375                         if (gr < 7) {
376                                 if (gr & 1)
377                                         gr ++;
378                                 g_warning ("check endianess");
379                                 ppc_lwz  (p, ppc_r3 + gr, i*16, ARG_BASE);
380                                 gr ++;
381                                 ppc_lwz  (p, ppc_r3 + gr, i*17, ARG_BASE);
382                                 gr ++;
383                         } else {
384                                 NOT_IMPLEMENTED ("i8 on stack");
385                         }
386                         break;
387                 case MONO_TYPE_R4:
388                         if (fr < 7) {
389                                 ppc_lfs  (p, ppc_f1 + fr, i*16, ARG_BASE);
390                                 fr ++;
391                         } else {
392                                 NOT_IMPLEMENTED ("r4 on stack");
393                         }
394                         break;
395                 case MONO_TYPE_R8:
396                         if (fr < 7) {
397                                 ppc_lfd  (p, ppc_f1 + fr, i*16, ARG_BASE);
398                                 fr ++;
399                         } else {
400                                 NOT_IMPLEMENTED ("r8 on stack");
401                         }
402                         break;
403                 default:
404                         g_error ("Can't trampoline 0x%x", sig->params [i]->type);
405                 }
406         }
407
408         return p;
409 }
410
411 static inline guint8 *
412 alloc_code_memory (guint code_size)
413 {
414         guint8 *p;
415
416 #ifdef NEED_MPROTECT
417         p = g_malloc (code_size + PAGESIZE - 1);
418
419         /* Align to a multiple of PAGESIZE, assumed to be a power of two */
420         p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));
421 #else
422         p = g_malloc (code_size);
423 #endif
424         printf ("           align: %p (%d)\n", p, (guint)p % 4);
425
426         return p;
427 }
428
429 static MonoString*
430 mono_string_new_wrapper (const char *text)
431 {
432         return text ? mono_string_new (mono_domain_get (), text) : NULL;
433 }
434
435 static inline guint8 *
436 emit_call_and_store_retval (guint8 *p, MonoMethod *method, guint strings, gint runtime)
437 {
438         MonoMethodSignature *sig = method->signature;
439         guint32 simpletype;
440
441         /* call "callme" */
442         ppc_mtlr (p, strings ? ppc_r29 : ppc_r0);
443         ppc_blrl (p);
444
445         /* get return value */
446         if (sig->ret->byref) {
447                 ppc_lwz  (p, ppc_r9, 8, ppc_r31);        /* load "retval" address */
448                 ppc_stw  (p, ppc_r3, 0, ppc_r9);         /* save return value (r3) to "retval" */
449         } else {
450                 simpletype = sig->ret->type;
451 enum_retvalue:
452                 switch (simpletype) {
453                 case MONO_TYPE_BOOLEAN:
454                 case MONO_TYPE_I1:
455                 case MONO_TYPE_U1:
456                         ppc_lwz  (p, ppc_r9, 8, ppc_r31);        /* load "retval" address */
457                         ppc_stb  (p, ppc_r3, 0, ppc_r9);         /* save return value (r3) to "retval" */
458                         break;
459                 case MONO_TYPE_I2:
460                 case MONO_TYPE_U2:
461                 case MONO_TYPE_CHAR:
462                         ppc_lwz  (p, ppc_r9, 8, ppc_r31);        /* load "retval" address */
463                         ppc_sth  (p, ppc_r3, 0, ppc_r9);         /* save return value (r3) to "retval" */
464                         break;
465                 case MONO_TYPE_I4:
466                 case MONO_TYPE_U4:
467                 case MONO_TYPE_I:
468                 case MONO_TYPE_U:
469                 case MONO_TYPE_CLASS:
470                 case MONO_TYPE_OBJECT:
471                 case MONO_TYPE_SZARRAY:
472                 case MONO_TYPE_ARRAY:
473                         ppc_lwz  (p, ppc_r9, 8, ppc_r31);        /* load "retval" address */
474                         ppc_stw  (p, ppc_r3, 0, ppc_r9);         /* save return value (r3) to "retval" */
475                         break;
476                 case MONO_TYPE_STRING:
477                         if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && !runtime) {
478                                 ppc_lis  (p, ppc_r0,     (guint32) mono_string_new_wrapper >> 16);
479                                 ppc_ori  (p, ppc_r0, ppc_r0, (guint32) mono_string_new_wrapper & 0xffff);
480                                 ppc_mtlr (p, ppc_r0);
481                                 ppc_blrl (p);
482                         }
483
484                         ppc_lwz  (p, ppc_r9, 8, ppc_r31);        /* load "retval" address */
485                         ppc_stw  (p, ppc_r3, 0, ppc_r9);         /* save return value (r3) to "retval" */
486
487                         break;
488                 case MONO_TYPE_R4:
489                         ppc_lwz  (p, ppc_r9, 8, ppc_r31);        /* load "retval" address */
490                         ppc_stfs (p, ppc_f1, 0, ppc_r9);         /* save return value (f1) to "retval" */
491                         break;
492                 case MONO_TYPE_R8:
493                         ppc_lwz  (p, ppc_r9, 8, ppc_r31);        /* load "retval" address */
494                         ppc_stfd (p, ppc_f1, 0, ppc_r9);         /* save return value (f1) to "retval" */
495                         break;
496                 case MONO_TYPE_I8:
497                         g_warning ("check endianess");
498                         ppc_lwz  (p, ppc_r9, 8, ppc_r31);        /* load "retval" address */
499                         ppc_stw  (p, ppc_r3, 0, ppc_r9);         /* save return value (r3) to "retval" */
500                         ppc_stw  (p, ppc_r4, 4, ppc_r9);         /* save return value (r3) to "retval" */
501                         break;
502                 case MONO_TYPE_VALUETYPE:
503                         if (sig->ret->data.klass->enumtype) {
504                                 simpletype = sig->ret->data.klass->enum_basetype->type;
505                                 goto enum_retvalue;
506                         }
507                         NOT_IMPLEMENTED ("retval valuetype");
508                         break;
509                 case MONO_TYPE_VOID:
510                         break;
511                 default:
512                         g_error ("Can't handle as return value 0x%x", sig->ret->type);
513                 }
514         }
515
516         return p;
517 }
518
519 static inline guint8 *
520 emit_epilog (guint8 *p, MonoMethod *method, guint stack_size, guint strings, gboolean runtime)
521 {
522         if (strings) {
523                 MonoMethodSignature *sig = method->signature;
524                 guint i, act_strs;
525
526                 /* free allocated memory */
527                 act_strs = 0;
528                 for (i = 0; i < sig->param_count; ++i) {
529                         if (!sig->params [i]->byref && sig->params [i]->type == MONO_TYPE_STRING
530                             && !((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || runtime)) {
531                                 ppc_lis  (p, ppc_r0,     (guint32) g_free >> 16);
532                                 ppc_lwz  (p, ppc_r3, stack_size - 20 - act_strs, ppc_r31);
533                                 ppc_ori  (p, ppc_r0, ppc_r0, (guint32) g_free & 0xffff);
534                                 ppc_mtlr (p, ppc_r0);
535                                 ppc_blrl (p);
536                                 act_strs += 4;
537                         }
538                 }
539
540                 /* restore volatile registers */
541                 ppc_lwz  (p, ppc_r30, stack_size - 16, ppc_r1);
542                 ppc_lwz  (p, ppc_r29, stack_size - 12, ppc_r1);
543                 if (method->signature->hasthis) {
544                         ppc_lwz  (p, ppc_r28, 24, ppc_r1);
545                 }
546         }
547
548         /* function epilog */
549         ppc_lwz  (p, ppc_r11, 0,  ppc_r1);        /* r11     <--- sp[0]   load backchain from caller's function */
550         ppc_lwz  (p, ppc_r0, 4, ppc_r11);         /* r0      <--- r11[4]  load return address */
551         ppc_mtlr (p, ppc_r0);                     /* LR      <--- r0      set return address */
552         ppc_lwz  (p, ppc_r31, -4, ppc_r11);       /* r31     <--- r11[-4] restore r31 */
553         ppc_mr   (p, ppc_r1, ppc_r11);            /* sp      <--- r11     restore stack */
554         ppc_blr  (p);                             /* return */
555
556         return p;
557 }
558
559 MonoPIFunc
560 mono_create_trampoline (MonoMethod *method, int runtime)
561 {
562         guint8 *p, *code_buffer;
563         guint stack_size, code_size, strings;
564
565         printf ("\nPInvoke [start emiting] %s\n", method->name);
566         calculate_sizes (method, &stack_size, &code_size, &strings, runtime);
567
568         p = code_buffer = alloc_code_memory (code_size);
569         p = emit_prolog (p, method, stack_size, strings);
570         p = emit_save_parameters (p, method, stack_size, strings, runtime);
571         p = emit_call_and_store_retval (p, method, strings, runtime);
572         p = emit_epilog (p, method, stack_size, strings, runtime);
573
574         /* {
575                 guchar *cp;
576                 printf (".text\n.align 4\n.globl main\n.type main,@function\nmain:\n");
577                 for (cp = code_buffer; cp < p; cp++) {
578                         printf (".byte 0x%x\n", *cp);
579                 }
580                 } */
581
582 #ifdef NEED_MPROTECT
583         if (mprotect (code_buffer, 1024, PROT_READ | PROT_WRITE | PROT_EXEC)) {
584                 g_error ("Cannot mprotect trampoline\n");
585         }
586 #endif
587
588         printf ("emited code size: %d\n", p - code_buffer);
589         flush_icache (code_buffer, p - code_buffer);
590
591         printf ("PInvoke [end emiting]\n");
592
593         return (MonoPIFunc) code_buffer;
594         /* return fake_func; */
595 }
596
597
598 #define MINV_POS  (- sizeof (MonoInvocation))
599 #define STACK_POS (MINV_POS - sizeof (stackval) * sig->param_count)
600 #define OBJ_POS   8
601 #define TYPE_OFFSET (G_STRUCT_OFFSET (stackval, type))
602
603 /*
604  * Returns a pointer to a native function that can be used to
605  * call the specified method.
606  * The function created will receive the arguments according
607  * to the call convention specified in the method.
608  * This function works by creating a MonoInvocation structure,
609  * filling the fields in and calling ves_exec_method on it.
610  * Still need to figure out how to handle the exception stuff
611  * across the managed/unmanaged boundary.
612  */
613 void *
614 mono_create_method_pointer (MonoMethod *method)
615 {
616         return NULL;
617 }
618
619
620 /*
621  * mono_create_method_pointer () will insert a pointer to the MonoMethod
622  * so that the interp can easily get at the data: this function will retrieve 
623  * the method from the code stream.
624  */
625 MonoMethod*
626 mono_method_pointer_get (void *code)
627 {
628         return NULL;
629 }
630