remove wrong assertion
[mono.git] / mono / jit / emit-x86.c
1 /*
2  * emit-x86.c: Support functions for emitting x86 code
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Miguel de Icaza (miguel@ximian.com)
7  *
8  * (C) 2001 Ximian, Inc.
9  */
10
11 #include <config.h>
12 #include <glib.h>
13
14 #include <mono/metadata/assembly.h>
15 #include <mono/metadata/loader.h>
16 #include <mono/metadata/cil-coff.h>
17 #include <mono/metadata/tabledefs.h>
18 #include <mono/metadata/class.h>
19 #include <mono/metadata/debug-helpers.h>
20 #include <mono/metadata/mono-endian.h>
21 #include <mono/arch/x86/x86-codegen.h>
22
23 #include "jit.h"
24 #include "codegen.h"
25 #include "debug.h"
26
27 static void
28 enter_method (MonoMethod *method, gpointer ebp)
29 {
30         int i, j;
31         MonoClass *class;
32         MonoObject *o;
33
34         printf ("ENTER: %s.%s::%s\n(", method->klass->name_space,
35                 method->klass->name, method->name);
36
37         
38         if (((int)ebp & 3) != 0) {
39                 g_error ("unaligned stack detected (%p)", ebp);
40         }
41
42         ebp += 8;
43
44         if (ISSTRUCT (method->signature->ret)) {
45                 int size, align;
46                 
47                 g_assert (!method->signature->ret->byref);
48
49                 size = mono_type_stack_size (method->signature->ret, &align);
50
51                 printf ("VALUERET:%p, ", *((gpointer *)ebp));
52                 ebp += sizeof (gpointer);
53         }
54
55         if (method->signature->hasthis) {
56                 if (method->klass->valuetype) {
57                         printf ("value:%p, ", *((gpointer *)ebp));
58                 } else {
59                         o = *((MonoObject **)ebp);
60
61                         g_assert (o);
62
63                         class = o->vtable->klass;
64
65                         if (class == mono_defaults.string_class) {
66                                 printf ("this:[STRING:%p:%s], ", o, mono_string_to_utf8 ((MonoString *)o));
67                         } else {
68                                 printf ("this:%p[%s.%s], ", o, class->name_space, class->name);
69                         }
70                 }
71                 ebp += sizeof (gpointer);
72         }
73
74         for (i = 0; i < method->signature->param_count; ++i) {
75                 MonoType *type = method->signature->params [i];
76                 int size, align;
77                 size = mono_type_stack_size (type, &align);
78
79                 if (type->byref) {
80                         printf ("[BYREF:%p], ", *((gpointer *)ebp)); 
81                 } else switch (type->type) {
82                         
83                 case MONO_TYPE_BOOLEAN:
84                 case MONO_TYPE_CHAR:
85                 case MONO_TYPE_I1:
86                 case MONO_TYPE_U1:
87                 case MONO_TYPE_I2:
88                 case MONO_TYPE_U2:
89                 case MONO_TYPE_I4:
90                 case MONO_TYPE_U4:
91                 case MONO_TYPE_I:
92                 case MONO_TYPE_U:
93                         printf ("%d, ", *((int *)(ebp)));
94                         break;
95                 case MONO_TYPE_STRING: {
96                         MonoString *s = *((MonoString **)ebp);
97                         if (s) {
98                                 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
99                                 printf ("[STRING:%p:%s], ", s, mono_string_to_utf8 (s));
100                         } else 
101                                 printf ("[STRING:null], ");
102                         break;
103                 }
104                 case MONO_TYPE_CLASS:
105                 case MONO_TYPE_OBJECT: {
106                         o = *((MonoObject **)ebp);
107                         if (o) {
108                                 class = o->vtable->klass;
109                     
110                                 if (class == mono_defaults.string_class) {
111                                         printf ("[STRING:%p:%s], ", o, mono_string_to_utf8 ((MonoString *)o));
112                                 } else if (class == mono_defaults.int32_class) {
113                                         printf ("[INT32:%p:%d], ", o, *(gint32 *)((gpointer)o + sizeof (MonoObject)));
114                                 } else
115                                         printf ("[%s.%s:%p], ", class->name_space, class->name, o);
116                         } else {
117                                 printf ("%p, ", *((gpointer *)(ebp)));                          
118                         }
119                         break;
120                 }
121                 case MONO_TYPE_PTR:
122                 case MONO_TYPE_FNPTR:
123                 case MONO_TYPE_ARRAY:
124                 case MONO_TYPE_SZARRAY:
125                         printf ("%p, ", *((gpointer *)(ebp)));
126                         break;
127                 case MONO_TYPE_I8:
128                         printf ("%lld, ", *((gint64 *)(ebp)));
129                         break;
130                 case MONO_TYPE_R4:
131                         printf ("%f, ", *((float *)(ebp)));
132                         break;
133                 case MONO_TYPE_R8:
134                         printf ("%f, ", *((double *)(ebp)));
135                         break;
136                 case MONO_TYPE_VALUETYPE: 
137                         printf ("[");
138                         for (j = 0; j < size; j++)
139                                 printf ("%02x,", *((guint8*)ebp +j));
140                         printf ("], ");
141                         break;
142                 default:
143                         printf ("XX, ");
144                 }
145
146                 g_assert (align == 4);
147                 ebp += size + 3;
148                 ebp = (gpointer)((unsigned)ebp & ~(3));
149         }
150
151         printf (")\n");
152 }
153
154 static void
155 leave_method (MonoMethod *method, int edx, int eax, double test)
156 {
157         gint64 l;
158
159         printf ("LEAVE: %s.%s::%s ", method->klass->name_space,
160                 method->klass->name, method->name);
161
162         switch (method->signature->ret->type) {
163         case MONO_TYPE_VOID:
164                 break;
165         case MONO_TYPE_BOOLEAN:
166                 if (eax)
167                         printf ("TRUE:%d", eax);
168                 else 
169                         printf ("FALSE");
170                         
171                 break;
172         case MONO_TYPE_CHAR:
173         case MONO_TYPE_I1:
174         case MONO_TYPE_U1:
175         case MONO_TYPE_I2:
176         case MONO_TYPE_U2:
177         case MONO_TYPE_I4:
178         case MONO_TYPE_U4:
179         case MONO_TYPE_I:
180         case MONO_TYPE_U:
181                 printf ("EAX=%d", eax);
182                 break;
183         case MONO_TYPE_STRING: {
184                 MonoString *s = (MonoString *)eax;
185
186                 if (s) {
187                         g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
188                         printf ("[STRING:%p:%s]", s, mono_string_to_utf8 (s));
189                 } else 
190                         printf ("[STRING:null], ");
191                 break;
192         }
193         case MONO_TYPE_OBJECT: {
194                 MonoObject *o = (MonoObject *)eax;
195
196                 if (o) {
197                         if (o->vtable->klass == mono_defaults.boolean_class) {
198                                 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));            
199                         } else if  (o->vtable->klass == mono_defaults.int32_class) {
200                                 printf ("[INT32:%p:%d]", o, *((gint32 *)((gpointer)o + sizeof (MonoObject))));  
201                         } else
202                                 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
203                 } else
204                         printf ("[OBJECT:%p]", o);
205                
206                 break;
207         }
208         case MONO_TYPE_CLASS:
209         case MONO_TYPE_PTR:
210         case MONO_TYPE_FNPTR:
211         case MONO_TYPE_ARRAY:
212         case MONO_TYPE_SZARRAY:
213                 printf ("EAX=%p", (gpointer)eax);
214                 break;
215         case MONO_TYPE_I8:
216                 *((gint32 *)&l) = eax;
217                 *((gint32 *)&l + 1) = edx;
218                 printf ("EAX/EDX=%lld", l);
219                 break;
220         case MONO_TYPE_R8:
221                 printf ("FP=%f\n", test);
222                 break;
223         default:
224                 printf ("(unknown return type)");
225         }
226
227         printf ("\n");
228 }
229
230 /**
231  * arch_emit_prologue:
232  * @cfg: pointer to status information
233  *
234  * Emits the function prolog.
235  */
236 static void
237 arch_emit_prologue (MonoFlowGraph *cfg)
238 {
239         x86_push_reg (cfg->code, X86_EBP);
240         x86_mov_reg_reg (cfg->code, X86_EBP, X86_ESP, 4);
241
242         if (cfg->locals_size)
243                 x86_alu_reg_imm (cfg->code, X86_SUB, X86_ESP, cfg->locals_size);
244
245         if (mono_regset_reg_used (cfg->rs, X86_EBX)) 
246                 x86_push_reg (cfg->code, X86_EBX);
247
248         if (mono_regset_reg_used (cfg->rs, X86_EDI)) 
249                 x86_push_reg (cfg->code, X86_EDI);
250
251         if (mono_regset_reg_used (cfg->rs, X86_ESI))
252                 x86_push_reg (cfg->code, X86_ESI);
253
254         if (mono_jit_trace_calls) {
255                 x86_push_reg (cfg->code, X86_EBP);
256                 x86_push_imm (cfg->code, cfg->method);
257                 x86_mov_reg_imm (cfg->code, X86_EAX, enter_method);
258                 x86_call_reg (cfg->code, X86_EAX);
259                 x86_alu_reg_imm (cfg->code, X86_ADD, X86_ESP, 8);
260         }
261 }
262
263 /**
264  * arch_emit_epilogue:
265  * @cfg: pointer to status information
266  *
267  * Emits the function epilog.
268  */
269 static void
270 arch_emit_epilogue (MonoFlowGraph *cfg)
271 {
272         if (mono_jit_trace_calls) {
273                 x86_fld_reg (cfg->code, 0);
274                 x86_alu_reg_imm (cfg->code, X86_SUB, X86_ESP, 8);
275                 x86_fst_membase (cfg->code, X86_ESP, 0, TRUE, TRUE);
276                 x86_push_reg (cfg->code, X86_EAX);
277                 x86_push_reg (cfg->code, X86_EDX);
278                 x86_push_imm (cfg->code, cfg->method);
279                 x86_mov_reg_imm (cfg->code, X86_EAX, leave_method);
280                 x86_call_reg (cfg->code, X86_EAX);
281                 x86_alu_reg_imm (cfg->code, X86_ADD, X86_ESP, 4);
282                 x86_pop_reg (cfg->code, X86_EDX);
283                 x86_pop_reg (cfg->code, X86_EAX);
284                 x86_alu_reg_imm (cfg->code, X86_ADD, X86_ESP, 8);
285         }
286
287         if (mono_regset_reg_used (cfg->rs, X86_ESI))
288                 x86_pop_reg (cfg->code, X86_ESI);
289
290         if (mono_regset_reg_used (cfg->rs, X86_EDI))
291                 x86_pop_reg (cfg->code, X86_EDI);
292
293         if (mono_regset_reg_used (cfg->rs, X86_EBX))
294                 x86_pop_reg (cfg->code, X86_EBX);
295
296         x86_leave (cfg->code);
297         x86_ret (cfg->code);
298 }
299
300 /*
301  * get_unbox_trampoline:
302  * @m: method pointer
303  * @addr: pointer to native code for @m
304  *
305  * when value type methods are called through the vtable we need to unbox the
306  * this argument. This method returns a pointer to a trampoline which does
307  * unboxing before calling the method
308  */
309 static gpointer
310 get_unbox_trampoline (MonoMethod *m, gpointer addr)
311 {
312         guint8 *code, *start;
313         int this_pos = 4;
314
315         if (!m->signature->ret->byref && m->signature->ret->type == MONO_TYPE_VALUETYPE)
316                 this_pos = 8;
317             
318         start = code = g_malloc (16);
319
320         x86_alu_membase_imm (code, X86_ADD, X86_ESP, this_pos, sizeof (MonoObject));
321         x86_jump_code (code, addr);
322         g_assert ((code - start) < 16);
323
324         return start;
325 }
326
327 /**
328  * x86_magic_trampoline:
329  * @eax: saved x86 register 
330  * @ecx: saved x86 register 
331  * @edx: saved x86 register 
332  * @esi: saved x86 register 
333  * @edi: saved x86 register 
334  * @ebx: saved x86 register
335  * @code: pointer into caller code
336  * @method: the method to translate
337  *
338  * This method is called by the trampoline functions for virtual
339  * methods. It inspects the caller code to find the address of the
340  * vtable slot, then calls the JIT compiler and writes the address
341  * of the compiled method back to the vtable. All virtual methods 
342  * are called with: x86_call_membase (inst, basereg, disp). We always
343  * use 32 bit displacement to ensure that the length of the call 
344  * instruction is 6 bytes. We need to get the value of the basereg 
345  * and the constant displacement.
346  */
347 static gpointer
348 x86_magic_trampoline (int eax, int ecx, int edx, int esi, int edi, 
349                       int ebx, const guint8 *code, MonoMethod *m)
350 {
351         guint8 reg;
352         gint32 disp;
353         gpointer o;
354         gpointer addr;
355
356         EnterCriticalSection (metadata_section);
357         addr = arch_compile_method (m);
358         LeaveCriticalSection (metadata_section);
359         g_assert (addr);
360
361
362         /* go to the start of the call instruction
363          *
364          * address_byte = (m << 6) | (o << 3) | reg
365          * call opcode: 0xff address_byte displacement
366          * 0xff m=1,o=2 imm8
367          * 0xff m=2,o=2 imm32
368          */
369         code -= 6;
370         if ((code [1] != 0xe8) && (code [3] == 0xff) && ((code [4] & 0x18) == 0x10) && ((code [4] >> 6) == 1)) {
371                 reg = code [4] & 0x07;
372                 disp = (signed char)code [5];
373         } else {
374                 if ((code [0] == 0xff) && ((code [1] & 0x18) == 0x10) && ((code [1] >> 6) == 2)) {
375                         reg = code [1] & 0x07;
376                         disp = *((gint32*)(code + 2));
377                 } else if ((code [1] == 0xe8)) {
378                         *((guint32*)(code + 2)) = (guint)addr - ((guint)code + 1) - 5; 
379                         return addr;
380                 } else {
381                         printf ("%x %x %x %x %x %x \n", code [0], code [1], code [2], code [3],
382                                 code [4], code [5]);
383                         g_assert_not_reached ();
384                 }
385         }
386
387         switch (reg) {
388         case X86_EAX:
389                 o = (gpointer)eax;
390                 break;
391         case X86_EDX:
392                 o = (gpointer)edx;
393                 break;
394         case X86_ECX:
395                 o = (gpointer)ecx;
396                 break;
397         case X86_ESI:
398                 o = (gpointer)esi;
399                 break;
400         case X86_EDI:
401                 o = (gpointer)edi;
402                 break;
403         case X86_EBX:
404                 o = (gpointer)ebx;
405                 break;
406         default:
407                 g_assert_not_reached ();
408         }
409
410         o += disp;
411
412         if (m->klass->valuetype) {
413                 return *((gpointer *)o) = get_unbox_trampoline (m, addr);
414         } else {
415                 return *((gpointer *)o) = addr;
416         }
417 }
418
419 /**
420  * arch_create_jit_trampoline:
421  * @method: pointer to the method info
422  *
423  * Creates a trampoline function for virtual methods. If the created
424  * code is called it first starts JIT compilation of method,
425  * and then calls the newly created method. I also replaces the
426  * corresponding vtable entry (see x86_magic_trampoline).
427  * 
428  * Returns: a pointer to the newly created code 
429  */
430 gpointer
431 arch_create_jit_trampoline (MonoMethod *method)
432 {
433         MonoDomain *domain = mono_domain_get ();
434         guint8 *code, *buf;
435         static guint8 *vc = NULL;
436         GHashTable *jit_code_hash;
437
438         /* previously created trampoline code */
439         if (method->info)
440                 return method->info;
441
442         /* icalls use method->addr */
443         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
444             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
445                 method->info = arch_create_native_wrapper (method);
446                 return method->info;
447         }
448
449         /* check if we already have JITed code */
450         if (mono_jit_share_code)
451                 jit_code_hash = mono_root_domain->jit_code_hash;
452         else
453                 jit_code_hash = domain->jit_code_hash;
454
455         if ((code = g_hash_table_lookup (jit_code_hash, method))) {
456                 mono_jit_stats.methods_lookups++;
457                 return code;
458         }
459
460         if (!vc) {
461                 vc = buf = g_malloc (256);
462
463                 /* save caller save regs because we need to do a call */ 
464                 x86_push_reg (buf, X86_EDX);
465                 x86_push_reg (buf, X86_EAX);
466                 x86_push_reg (buf, X86_ECX);
467
468                 /* save LMF begin */
469                 x86_push_reg (buf, X86_EBX);
470                 x86_push_reg (buf, X86_EDI);
471                 x86_push_reg (buf, X86_ESI);
472                 x86_push_reg (buf, X86_EBP);
473
474                 /* save the IP (caller ip) */
475                 x86_push_membase (buf, X86_ESP, 32);
476
477                 /* save method info */
478                 x86_push_membase (buf, X86_ESP, 32);
479                 /* get the address of lmf for the current thread */
480                 x86_call_code (buf, arch_get_lmf_addr);
481                 /* push lmf */
482                 x86_push_reg (buf, X86_EAX); 
483                 /* push *lfm (previous_lmf) */
484                 x86_push_membase (buf, X86_EAX, 0);
485                 /* *(lmf) = ESP */
486                 x86_mov_membase_reg (buf, X86_EAX, 0, X86_ESP, 4);
487                 /* save LFM end */
488
489                 /* push the method info */
490                 x86_push_membase (buf, X86_ESP, 44);
491                 /* push the return address onto the stack */
492                 x86_push_membase (buf, X86_ESP, 52);
493
494                 /* save all register values */
495                 x86_push_reg (buf, X86_EBX);
496                 x86_push_reg (buf, X86_EDI);
497                 x86_push_reg (buf, X86_ESI);
498                 x86_push_membase (buf, X86_ESP, 64); /* EDX */
499                 x86_push_membase (buf, X86_ESP, 64); /* ECX */
500                 x86_push_membase (buf, X86_ESP, 64); /* EAX */
501
502                 x86_call_code (buf, x86_magic_trampoline);
503                 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 8*4);
504
505                 /* restore LMF start */
506                 /* ebx = previous_lmf */
507                 x86_pop_reg (buf, X86_EBX);
508                 /* edi = lmf */
509                 x86_pop_reg (buf, X86_EDI);
510                 /* *(lmf) = previous_lmf */
511                 x86_mov_membase_reg (buf, X86_EDI, 0, X86_EBX, 4);
512                 /* discard method info */
513                 x86_pop_reg (buf, X86_ESI);
514                 /* discard save IP */
515                 x86_pop_reg (buf, X86_ESI);
516                 /* restore caller saved regs */
517                 x86_pop_reg (buf, X86_EBP);
518                 x86_pop_reg (buf, X86_ESI);
519                 x86_pop_reg (buf, X86_EDI);
520                 x86_pop_reg (buf, X86_EBX);
521                 /* restore LMF end */
522
523                 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 16);
524
525                 /* call the compiled method */
526                 x86_jump_reg (buf, X86_EAX);
527
528                 g_assert ((buf - vc) <= 256);
529         }
530
531         code = buf = g_malloc (16);
532         x86_push_imm (buf, method);
533         x86_jump_code (buf, vc);
534         g_assert ((buf - code) <= 16);
535
536         /* store trampoline address */
537         method->info = code;
538
539         mono_jit_stats.method_trampolines++;
540
541         return code;
542 }
543
544 static void
545 mono_label_cfg (MonoFlowGraph *cfg)
546 {
547         int i, j;
548         
549         for (i = 0; i < cfg->block_count; i++) {
550                 GPtrArray *forest = cfg->bblocks [i].forest;
551                 int top;
552
553                 if (!cfg->bblocks [i].reached) /* unreachable code */
554                         continue;
555                 
556                 top = forest->len;
557
558                 for (j = 0; j < top; j++) {
559                         MBTree *t1 = (MBTree *) g_ptr_array_index (forest, j);
560                         MBState *mbstate;
561
562                         mbstate =  mono_burg_label (t1, cfg);
563                         if (!mbstate) {
564                                 cfg->invalid = 1;
565                                 if (mono_debug_handle)
566                                         return;
567                                 g_warning ("tree does not match");
568                                 mono_print_ctree (t1); printf ("\n\n");
569
570                                 mono_print_forest (forest);
571                                 g_assert_not_reached ();
572                         }
573                 }
574         }
575 }
576
577 static void
578 tree_preallocate_regs (MBTree *tree, int goal, MonoRegSet *rs) 
579 {
580         switch (tree->op) {
581         case MB_TERM_CALL_I4:
582         case MB_TERM_CALL_I8:
583         case MB_TERM_CALL_R8:
584 //      case MB_TERM_CALL_VOID :
585                 tree->reg1 = mono_regset_alloc_reg (rs, X86_EAX, tree->exclude_mask);
586                 tree->reg2 = mono_regset_alloc_reg (rs, X86_EDX, tree->exclude_mask);
587                 tree->reg3 = mono_regset_alloc_reg (rs, X86_ECX, tree->exclude_mask);
588                 return;
589         default: break;
590         }
591
592         switch (goal) {
593         case MB_NTERM_reg:
594         case MB_NTERM_lreg: {
595                 switch (tree->op) {
596                 case MB_TERM_SHL:
597                 case MB_TERM_SHR:
598                 case MB_TERM_SHR_UN:
599                         tree->exclude_mask |= (1 << X86_ECX);
600                         tree->left->exclude_mask |= (1 << X86_ECX);
601                         break;
602                 case MB_TERM_MUL:
603                 case MB_TERM_MUL_OVF:
604                 case MB_TERM_MUL_OVF_UN:
605                 case MB_TERM_DIV:
606                 case MB_TERM_DIV_UN:
607                 case MB_TERM_REM:
608                 case MB_TERM_REM_UN:
609                         tree->reg1 = mono_regset_alloc_reg (rs, X86_EAX, tree->exclude_mask);
610                         tree->reg2 = mono_regset_alloc_reg (rs, X86_EDX, tree->exclude_mask);
611                         if (goal == MB_NTERM_reg) {
612                                 tree->left->exclude_mask |= (1 << X86_EDX);
613                                 tree->right->exclude_mask |= (1 << X86_EDX) | (1 << X86_EAX);
614                         }
615                         break;
616                 default:
617                         break;
618                 }
619                 break;
620         }
621         default:
622                 break;
623         }
624 }
625
626 static void
627 tree_allocate_regs (MBTree *tree, int goal, MonoRegSet *rs) 
628 {
629         MBTree *kids[10];
630         int ern = mono_burg_rule (tree->state, goal);
631         const guint16 *nts = mono_burg_nts [ern];
632         int i;
633         
634         mono_burg_kids (tree, ern, kids);
635
636         //printf ("RALLOC START %d %p %d\n",  tree->op, rs->free_mask, goal);
637
638         if (nts [0] && kids [0] == tree) {
639                 /* chain rule */
640                 tree_allocate_regs (kids [0], nts [0], rs);
641                 return;
642         }
643
644         for (i = 0; nts [i]; i++)
645                 tree_preallocate_regs (kids [i], nts [i], rs);
646
647         for (i = 0; nts [i]; i++)
648                 tree_allocate_regs (kids [i], nts [i], rs);
649
650         for (i = 0; nts [i]; i++) {
651                 mono_regset_free_reg (rs, kids [i]->reg1);
652                 mono_regset_free_reg (rs, kids [i]->reg2);
653                 mono_regset_free_reg (rs, kids [i]->reg3);
654         }
655
656         switch (goal) {
657         case MB_NTERM_reg:
658                 if (tree->reg1 < 0) { 
659                         tree->reg1 = mono_regset_alloc_reg (rs, -1, tree->exclude_mask);
660                         g_assert (tree->reg1 != -1);
661                 }
662                 break;
663
664         case MB_NTERM_lreg:
665                 if (tree->reg1 < 0) { 
666                         tree->reg1 = mono_regset_alloc_reg (rs, -1, tree->exclude_mask);
667                         g_assert (tree->reg1 != -1);
668                 }
669                 if (tree->reg2 < 0) { 
670                         tree->reg2 = mono_regset_alloc_reg (rs, -1, tree->exclude_mask);
671                         g_assert (tree->reg2 != -1);
672                 }
673                 break;
674
675         case MB_NTERM_freg:
676                 /* fixme: allocate floating point registers */
677                 break;
678       
679         case MB_NTERM_addr:
680                 if (tree->op == MB_TERM_ADD) {
681                         tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
682                         tree->reg2 = mono_regset_alloc_reg (rs, tree->right->reg1, tree->exclude_mask);
683                 }
684                 break;
685                 
686         case MB_NTERM_base:
687                 if (tree->op == MB_TERM_ADD) {
688                         tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
689                 }
690                 break;
691                
692         case MB_NTERM_index:
693                 if (tree->op == MB_TERM_SHL ||
694                     tree->op == MB_TERM_MUL) {
695                         tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
696                 }
697                 break;
698                
699         default:
700                 /* do nothing */
701         }
702
703         //printf ("RALLOC END %d %p\n",  tree->op, rs->free_mask);
704         tree->emit = mono_burg_func [ern];
705 }
706
707 static void
708 arch_allocate_regs (MonoFlowGraph *cfg)
709 {
710         int i, j;
711         
712         for (i = 0; i < cfg->block_count; i++) {
713                 GPtrArray *forest = cfg->bblocks [i].forest;
714                 int top;
715
716                 if (!cfg->bblocks [i].reached) /* unreachable code */
717                         continue;
718
719                 top = forest->len;
720
721                 for (j = 0; j < top; j++) {
722                         MBTree *t1 = (MBTree *) g_ptr_array_index (forest, j);
723                         //printf ("AREGSTART %d:%d %p\n", i, j, cfg->rs->free_mask);
724                         tree_allocate_regs (t1, 1, cfg->rs);
725                         //printf ("AREGENDT %d:%d %p\n", i, j, cfg->rs->free_mask);
726                         g_assert (cfg->rs->free_mask == 0xffffffff);
727                 }
728         }
729 }
730
731 static void
732 tree_emit (int goal, MonoFlowGraph *cfg, MBTree *tree) 
733 {
734         MBTree *kids[10];
735         int i, ern = mono_burg_rule (tree->state, goal);
736         const guint16 *nts = mono_burg_nts [ern];
737         MBEmitFunc emit;
738         int offset;
739
740         mono_burg_kids (tree, ern, kids);
741
742         for (i = 0; nts [i]; i++) 
743                 tree_emit (nts [i], cfg, kids [i]);
744
745         tree->addr = offset = cfg->code - cfg->start;
746
747         // we assume an instruction uses a maximum of 128 bytes
748         if ((cfg->code_size - offset) <= 128) {
749                 int add = MIN (cfg->code_size, 128);
750                 cfg->code_size += add;
751                 mono_jit_stats.code_reallocs++;
752                 cfg->start = g_realloc (cfg->start, cfg->code_size);
753                 g_assert (cfg->start);
754                 cfg->code = cfg->start + offset;
755         }
756
757         if ((emit = mono_burg_func [ern]))
758                 emit (tree, cfg);
759
760         g_assert ((cfg->code - cfg->start) < cfg->code_size);
761 }
762
763 static void
764 mono_emit_cfg (MonoFlowGraph *cfg)
765 {
766         int i, j;
767
768         for (i = 0; i < cfg->block_count; i++) {
769                 MonoBBlock *bb = &cfg->bblocks [i];
770                 GPtrArray *forest = bb->forest;
771                 int top;
772
773                 if (!bb->reached) /* unreachable code */
774                         continue;
775                 
776                 top = forest->len;
777
778                 bb->addr = cfg->code - cfg->start;
779           
780                 for (j = 0; j < top; j++) {
781                         MBTree *t1 = (MBTree *) g_ptr_array_index (forest, j);
782                         
783                         tree_emit (1, cfg, t1);
784                 }
785         }
786                 
787         cfg->epilog = cfg->code - cfg->start;
788 }
789
790 static void
791 mono_compute_branches (MonoFlowGraph *cfg)
792 {
793         MonoJumpInfo *ji;
794         guint8 *end;
795         int i, j;
796
797         end = cfg->code;
798
799         for (j = 0; j < cfg->block_count; j++) {
800                 MonoBBlock *bb = &cfg->bblocks [j];
801                 GPtrArray *forest = bb->forest;
802                 int top;
803                 
804                 if (!bb->reached) /* unreachable code */
805                         continue;
806
807                 top = forest->len;
808         
809                 for (i = 0; i < top; i++) {
810                         MBTree *t1 = (MBTree *) g_ptr_array_index (forest, i);
811
812                         if (t1->op == MB_TERM_SWITCH) {
813                                 MonoBBlock **jt = (MonoBBlock **)t1->data.p;
814                                 guint32 *rt = (guint32 *)t1->data.p;
815                                 
816                                 int m = *((guint32 *)t1->data.p) + 1;
817                                 int j;
818                                 
819                                 for (j = 1; j <= m; j++)
820                                         rt [j] = (int)(jt [j]->addr + cfg->start);
821                                 
822                                 /* emit the switch instruction again to update addresses */
823                                 cfg->code = cfg->start + t1->addr;
824                                 ((MBEmitFunc)t1->emit) (t1, cfg);
825                         }
826                 }
827         }
828
829         cfg->code = end;
830
831         for (ji = cfg->jump_info; ji; ji = ji->next) {
832                 gpointer *ip = GUINT_TO_POINTER (GPOINTER_TO_UINT (ji->ip) + cfg->start);
833                 gpointer target;
834
835                 switch (ji->type) {
836                 case MONO_JUMP_INFO_BB:
837                         target = ji->data.bb->addr + cfg->start;
838                         *ip = target - GPOINTER_TO_UINT(ip) - 4;
839                         break;
840                 case MONO_JUMP_INFO_ABS:
841                         target = ji->data.target;
842                         *ip = target - GPOINTER_TO_UINT(ip) - 4;
843                         break;
844                 case MONO_JUMP_INFO_EPILOG:
845                         target = cfg->epilog + cfg->start;
846                         *ip = target - GPOINTER_TO_UINT(ip) - 4;
847                         break;
848                 case MONO_JUMP_INFO_IP:
849                         *ip = ip;
850                         break;
851                 default:
852                         g_assert_not_reached ();
853                 }
854         }
855 }
856
857 void
858 mono_add_jump_info (MonoFlowGraph *cfg, gpointer ip, MonoJumpInfoType type, gpointer target)
859 {
860         MonoJumpInfo *ji = mono_mempool_alloc (cfg->mp, sizeof (MonoJumpInfo));
861
862         ji->type = type;
863         ji->ip = GUINT_TO_POINTER (GPOINTER_TO_UINT (ip) - GPOINTER_TO_UINT (cfg->start));
864         ji->data.target = target;
865         ji->next = cfg->jump_info;
866
867         cfg->jump_info = ji;
868 }
869
870 static int
871 match_debug_method (MonoMethod* method)
872 {
873         GList *tmp = mono_debug_methods;
874
875         for (; tmp; tmp = tmp->next) {
876                 if (mono_method_desc_full_match (tmp->data, method))
877                         return 1;
878         }
879         return 0;
880 }
881
882 static void
883 mono_delegate_ctor (MonoDelegate *this, MonoObject *target, 
884                     gpointer addr)
885 {
886         MonoDomain *domain = mono_domain_get ();
887         MonoClass *class;
888         MonoJitInfo *ji;
889
890         g_assert (this);
891         g_assert (addr);
892
893         class = this->object.vtable->klass;
894
895         if ((ji = mono_jit_info_table_find (mono_jit_info_table, addr))) {
896                 this->method_info = mono_method_get_object (domain, ji->method);
897         }
898         
899         this->target = target;
900         this->method_ptr = addr;
901
902 }
903
904 /**
905  * arch_compile_method:
906  * @method: pointer to the method info
907  *
908  * JIT compilation of a single method. 
909  *
910  * Returns: a pointer to the newly created code.
911  */
912 gpointer
913 arch_compile_method (MonoMethod *method)
914 {
915         MonoDomain *domain = mono_domain_get ();
916         MonoJitInfo *ji;
917         MonoMemPool *mp;
918         guint8 *addr;
919         GHashTable *jit_code_hash;
920
921         g_assert (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL));
922
923         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
924                 if (!method->info)
925                         method->info = arch_create_native_wrapper (method);
926                 return method->info;
927         }
928
929         if (mono_jit_share_code)
930                 jit_code_hash = mono_root_domain->jit_code_hash;
931         else
932                 jit_code_hash = domain->jit_code_hash;
933
934         if ((addr = g_hash_table_lookup (jit_code_hash, method))) {
935                 mono_jit_stats.methods_lookups++;
936                 return addr;
937         }
938
939         mono_jit_stats.methods_compiled++;
940         
941         mp = mono_mempool_new ();
942
943         if (mono_jit_trace_calls || mono_jit_dump_asm || mono_jit_dump_forest) {
944                 printf ("Start JIT compilation of %s.%s:%s\n", method->klass->name_space,
945                         method->klass->name, method->name);
946         }
947
948         if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
949                 const char *name = method->name;
950                 guint8 *code;
951                 gboolean delegate = FALSE;
952
953                 if (method->klass->parent == mono_defaults.multicastdelegate_class)
954                         delegate = TRUE;
955                                 
956                 if (delegate && *name == '.' && (strcmp (name, ".ctor") == 0)) {
957                         addr = (gpointer)mono_delegate_ctor;
958                 } else if (delegate && *name == 'I' && (strcmp (name, "Invoke") == 0)) {
959                         /*
960                          *      Invoke( args .. ) {
961                          *              if ( prev )
962                          *                      prev.Invoke();
963                          *              return this.<m_target>( args );
964                          *      }
965                          */
966                         MonoMethodSignature *csig = method->signature;
967                         guint8 *br[2], *pos[2];
968                         int i, arg_size, this_pos = 4;
969                         
970                         if (csig->ret->type == MONO_TYPE_VALUETYPE) {
971                                 g_assert (!csig->ret->byref);
972                                 this_pos = 8;
973                         }
974
975                         arg_size = 0;
976                         if (csig->param_count) {
977                                 int align;
978                                 
979                                 for (i = 0; i < csig->param_count; ++i) {
980                                         arg_size += mono_type_stack_size (csig->params [i], &align);
981                                         g_assert (align == 4);
982                                 }
983                         }
984
985                         addr = g_malloc (64 + arg_size);
986
987                         code = addr;
988                         /* load the this pointer */
989                         x86_mov_reg_membase (code, X86_EAX, X86_ESP, this_pos, 4);
990                         
991                         /* load prev */
992                         x86_mov_reg_membase (code, X86_EDX, X86_EAX, G_STRUCT_OFFSET (MonoMulticastDelegate, prev), 4);
993
994                         /* prev == 0 ? */
995                         x86_alu_reg_imm (code, X86_CMP, X86_EDX, 0);
996                         br[0] = code; x86_branch32 (code, X86_CC_EQ, 0, TRUE );
997                         pos[0] = code;
998
999                         x86_push_reg( code, X86_EAX );
1000                         /* push args */
1001                         for ( i = 0; i < (arg_size>>2); i++ )
1002                                 x86_push_membase( code, X86_ESP, (arg_size + this_pos + 4) );
1003                         /* push next */
1004                         x86_push_reg( code, X86_EDX );
1005                         if (this_pos == 8)
1006                                 x86_push_membase (code, X86_ESP, (arg_size + 8));
1007                         /* recurse */
1008                         br[1] = code; x86_call_imm( code, 0 );
1009                         pos[1] = code; x86_call_imm( br[1], addr - pos[1] );
1010
1011                         if (this_pos == 8)
1012                                 x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size + 8);
1013                         else
1014                                 x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size + 4);
1015                         x86_pop_reg( code, X86_EAX );
1016                         
1017                         /* prev == 0 */ 
1018                         x86_branch32( br[0], X86_CC_EQ, code - pos[0], TRUE );
1019                         
1020                         /* load mtarget */
1021                         x86_mov_reg_membase (code, X86_EDX, X86_EAX, G_STRUCT_OFFSET (MonoDelegate, target), 4); 
1022                         /* mtarget == 0 ? */
1023                         x86_alu_reg_imm (code, X86_CMP, X86_EDX, 0);
1024                         br[0] = code; x86_branch32 (code, X86_CC_EQ, 0, TRUE);
1025                         pos[0] = code;
1026
1027                         /* 
1028                          * virtual delegate methods: we have to
1029                          * replace the this pointer with the actual
1030                          * target
1031                          */
1032                         x86_mov_membase_reg (code, X86_ESP, this_pos, X86_EDX, 4); 
1033                         /* jump to method_ptr() */
1034                         x86_jump_membase (code, X86_EAX, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1035
1036                         /* mtarget != 0 */ 
1037                         x86_branch32( br[0], X86_CC_EQ, code - pos[0], TRUE);
1038                         /* 
1039                          * static delegate methods: we have to remove
1040                          * the this pointer from the activation frame
1041                          * - I do this creating a new stack frame anx
1042                          * copy all arguments except the this pointer
1043                          */
1044                         g_assert ((arg_size & 3) == 0);
1045                         for (i = 0; i < (arg_size>>2); i++) {
1046                                 x86_push_membase (code, X86_ESP, (arg_size + this_pos));
1047                         }
1048
1049                         if (this_pos == 8)
1050                                 x86_push_membase (code, X86_ESP, (arg_size + 4));
1051                         
1052                         x86_call_membase (code, X86_EAX, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1053                         if (arg_size) {
1054                                 if (this_pos == 8) 
1055                                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size + 4);
1056                                 else
1057                                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size);
1058                         }
1059
1060                         x86_ret (code);
1061                 
1062                         g_assert ((code - (guint8*)addr) < (64 + arg_size));
1063
1064                         if (mono_jit_dump_asm) {
1065                                 char *id = g_strdup_printf ("%s.%s_%s", method->klass->name_space,
1066                                                             method->klass->name, method->name);
1067                                 mono_disassemble_code( addr, code - (guint8*)addr, id );
1068                                 g_free (id);
1069                         }
1070                 } else {
1071                         if (mono_debug_handle) 
1072                                 return NULL;
1073
1074                         g_error ("Don't know how to exec runtime method %s.%s::%s", 
1075                                  method->klass->name_space, method->klass->name, method->name);
1076                 }
1077         
1078         } else {
1079                 MonoMethodHeader *header = ((MonoMethodNormal *)method)->header;
1080                 MonoFlowGraph *cfg;
1081
1082                 gulong code_size_ratio;
1083
1084                 ji = g_new0 (MonoJitInfo, 1);
1085                 
1086                 cfg = mono_cfg_new (method, mp);
1087
1088                 mono_analyze_flow (cfg);
1089                 if (cfg->invalid) 
1090                         return NULL;
1091                 
1092                 mono_analyze_stack (cfg);
1093                 if (cfg->invalid) 
1094                         return NULL;
1095                 
1096                 cfg->rs = mono_regset_new (X86_NREG);
1097                 mono_regset_reserve_reg (cfg->rs, X86_ESP);
1098                 mono_regset_reserve_reg (cfg->rs, X86_EBP);
1099
1100                 cfg->code_size = MAX (header->code_size * 5, 256);
1101                 cfg->start = cfg->code = g_malloc (cfg->code_size);
1102
1103                 if (match_debug_method (method))
1104                         x86_breakpoint (cfg->code);
1105                 else if (mono_debug_handle)
1106                         x86_nop (cfg->code);
1107
1108                 if (mono_jit_dump_forest) {
1109                         int i;
1110                         printf ("FOREST %s.%s:%s\n", method->klass->name_space,
1111                                 method->klass->name, method->name);
1112                         for (i = 0; i < cfg->block_count; i++) {
1113                                 printf ("BLOCK %d:\n", i);
1114                                 mono_print_forest (cfg->bblocks [i].forest);
1115                         }
1116                 }
1117         
1118                 mono_label_cfg (cfg);
1119                 if (cfg->invalid) 
1120                         return NULL;
1121                 
1122                 arch_allocate_regs (cfg);
1123
1124                 /* align to 8 byte boundary */
1125                 cfg->locals_size += 7;
1126                 cfg->locals_size &= ~7;
1127
1128                 arch_emit_prologue (cfg);
1129                 mono_emit_cfg (cfg);
1130                 arch_emit_epilogue (cfg);               
1131
1132                 addr = cfg->start;
1133
1134                 mono_jit_stats.allocated_code_size += cfg->code_size;
1135
1136                 code_size_ratio = cfg->code - cfg->start;
1137                 if (code_size_ratio > mono_jit_stats.biggest_method_size) {
1138                         mono_jit_stats.biggest_method_size = code_size_ratio;
1139                         mono_jit_stats.biggest_method = method;
1140                 }
1141                 code_size_ratio = (code_size_ratio * 100) / header->code_size;
1142                 if (code_size_ratio > mono_jit_stats.max_code_size_ratio) {
1143                         mono_jit_stats.max_code_size_ratio = code_size_ratio;
1144                         mono_jit_stats.max_ratio_method = method;
1145                 }
1146
1147                 mono_compute_branches (cfg);
1148                 
1149                 if (mono_jit_dump_asm) {
1150                         char *id = g_strdup_printf ("%s.%s_%s", method->klass->name_space,
1151                                                     method->klass->name, method->name);
1152                         mono_disassemble_code (cfg->start, cfg->code - cfg->start, id);
1153                         g_free (id);
1154                 }
1155                 if (mono_debug_handle)
1156                         mono_debug_add_method (mono_debug_handle, cfg);
1157
1158                 ji->code_size = cfg->code - cfg->start;
1159                 ji->used_regs = cfg->rs->used_mask;
1160                 ji->method = method;
1161                 ji->code_start = addr;
1162                 mono_jit_info_table_add (mono_jit_info_table, ji);
1163
1164                 mono_jit_stats.native_code_size += ji->code_size;
1165
1166                 if (header->num_clauses) {
1167                         int i, start_block, end_block;
1168
1169                         ji->num_clauses = header->num_clauses;
1170                         ji->clauses = g_new0 (MonoJitExceptionInfo, header->num_clauses);
1171
1172                         for (i = 0; i < header->num_clauses; i++) {
1173                                 MonoExceptionClause *ec = &header->clauses [i];
1174                                 MonoJitExceptionInfo *ei = &ji->clauses [i];
1175                         
1176                                 ei->flags = ec->flags;
1177                                 ei->token_or_filter = ec->token_or_filter;
1178
1179                                 g_assert (cfg->bcinfo [ec->try_offset].is_block_start);
1180                                 start_block = cfg->bcinfo [ec->try_offset].block_id;
1181                                 end_block = cfg->bcinfo [ec->try_offset + ec->try_len].block_id;
1182                                 g_assert (cfg->bcinfo [ec->try_offset + ec->try_len].is_block_start);
1183                                 
1184                                 ei->try_start = cfg->start + cfg->bblocks [start_block].addr;
1185                                 ei->try_end = cfg->start + cfg->bblocks [end_block].addr;
1186                                 
1187                                 g_assert (cfg->bcinfo [ec->handler_offset].is_block_start);
1188                                 start_block = cfg->bcinfo [ec->handler_offset].block_id;
1189                                 ei->handler_start = cfg->start + cfg->bblocks [start_block].addr;       
1190                                 
1191                                 //printf ("TEST %x %x %x\n", ei->try_start, ei->try_end, ei->handler_start);
1192                         }
1193                 }
1194                 
1195                 mono_regset_free (cfg->rs);
1196
1197                 mono_cfg_free (cfg);
1198
1199                 mono_mempool_destroy (mp);
1200
1201         }
1202
1203         if (mono_jit_trace_calls || mono_jit_dump_asm || mono_jit_dump_forest) {
1204                 printf ("END JIT compilation of %s.%s:%s %p %p\n", method->klass->name_space,
1205                         method->klass->name, method->name, method, addr);
1206         }
1207
1208         g_hash_table_insert (jit_code_hash, method, addr);
1209
1210         return addr;
1211 }
1212
1213 /*
1214  * arch_get_restore_context:
1215  *
1216  * Returns a pointer to a method which restores a previously saved sigcontext.
1217  */
1218 static gpointer
1219 arch_get_restore_context ()
1220 {
1221         static guint8 *start = NULL;
1222         guint8 *code;
1223
1224         if (start)
1225                 return start;
1226
1227         /* restore_contect (struct sigcontext *ctx) */
1228         /* we do not restore X86_EAX, X86_EDX */
1229
1230         start = code = g_malloc (1024);
1231         
1232         /* load ctx */
1233         x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4);
1234
1235         /* get return address, stored in EDX */
1236         x86_mov_reg_membase (code, X86_EDX, X86_EAX,  G_STRUCT_OFFSET (struct sigcontext, eip), 4);
1237         /* restore EBX */
1238         x86_mov_reg_membase (code, X86_EBX, X86_EAX,  G_STRUCT_OFFSET (struct sigcontext, ebx), 4);
1239         /* restore EDI */
1240         x86_mov_reg_membase (code, X86_EDI, X86_EAX,  G_STRUCT_OFFSET (struct sigcontext, edi), 4);
1241         /* restore ESI */
1242         x86_mov_reg_membase (code, X86_ESI, X86_EAX,  G_STRUCT_OFFSET (struct sigcontext, esi), 4);
1243         /* restore ESP */
1244         x86_mov_reg_membase (code, X86_ESP, X86_EAX,  G_STRUCT_OFFSET (struct sigcontext, esp), 4);
1245         /* restore EBP */
1246         x86_mov_reg_membase (code, X86_EBP, X86_EAX,  G_STRUCT_OFFSET (struct sigcontext, ebp), 4);
1247         /* restore ECX. the exception object is passed here to the catch handler */
1248         x86_mov_reg_membase (code, X86_ECX, X86_EAX,  G_STRUCT_OFFSET (struct sigcontext, ecx), 4);
1249
1250         /* jump to the saved IP */
1251         x86_jump_reg (code, X86_EDX);
1252
1253         return start;
1254 }
1255
1256 /*
1257  * arch_get_call_finally:
1258  *
1259  * Returns a pointer to a method which calls a finally handler.
1260  */
1261 static gpointer
1262 arch_get_call_finally ()
1263 {
1264         static guint8 start [28];
1265         static int inited = 0;
1266         guint8 *code;
1267
1268         if (inited)
1269                 return start;
1270
1271         inited = 1;
1272         /* call_finally (struct sigcontext *ctx, unsigned long eip) */
1273         code = start;
1274
1275         x86_push_reg (code, X86_EBP);
1276         x86_mov_reg_reg (code, X86_EBP, X86_ESP, 4);
1277         x86_push_reg (code, X86_EBX);
1278         x86_push_reg (code, X86_EDI);
1279         x86_push_reg (code, X86_ESI);
1280
1281         /* load ctx */
1282         x86_mov_reg_membase (code, X86_EAX, X86_EBP, 8, 4);
1283         /* load eip */
1284         x86_mov_reg_membase (code, X86_ECX, X86_EBP, 12, 4);
1285         /* save EBP */
1286         x86_push_reg (code, X86_EBP);
1287         /* set new EBP */
1288         x86_mov_reg_membase (code, X86_EBP, X86_EAX,  G_STRUCT_OFFSET (struct sigcontext, ebp), 4);
1289         /* call the handler */
1290         x86_call_reg (code, X86_ECX);
1291         /* restore EBP */
1292         x86_pop_reg (code, X86_EBP);
1293         /* restore saved regs */
1294         x86_pop_reg (code, X86_ESI);
1295         x86_pop_reg (code, X86_EDI);
1296         x86_pop_reg (code, X86_EBX);
1297         x86_leave (code);
1298         x86_ret (code);
1299
1300         g_assert ((code - start) < 28);
1301         return start;
1302 }
1303
1304 /**
1305  * arch_handle_exception:
1306  * @ctx: saved processor state
1307  * @obj:
1308  */
1309 void
1310 arch_handle_exception (struct sigcontext *ctx, gpointer obj)
1311 {
1312         MonoDomain *domain = mono_domain_get ();
1313         MonoJitInfo *ji;
1314         gpointer ip = (gpointer)ctx->eip;
1315         static void (*restore_context) (struct sigcontext *);
1316         static void (*call_finally) (struct sigcontext *, unsigned long);
1317        
1318         g_assert (ctx != NULL);
1319         g_assert (obj != NULL);
1320
1321         ji = mono_jit_info_table_find (mono_jit_info_table, ip);
1322
1323         if (!restore_context)
1324                 restore_context = arch_get_restore_context ();
1325         
1326         if (!call_finally)
1327                 call_finally = arch_get_call_finally ();
1328
1329         if (ji) { /* we are inside managed code */
1330                 MonoMethod *m = ji->method;
1331                 int offset = 2;
1332
1333                 if (ji->num_clauses) {
1334                         int i;
1335
1336                         g_assert (ji->clauses);
1337                         
1338                         for (i = 0; i < ji->num_clauses; i++) {
1339                                 MonoJitExceptionInfo *ei = &ji->clauses [i];
1340
1341                                 if (ei->try_start <= ip && ip <= (ei->try_end)) { 
1342                                         /* catch block */
1343                                         if (ei->flags == 0 && mono_object_isinst (obj, 
1344                                                 mono_class_get (m->klass->image, ei->token_or_filter))) {
1345                                         
1346                                                 ctx->eip = (unsigned long)ei->handler_start;
1347                                                 ctx->ecx = (unsigned long)obj;
1348                                                 restore_context (ctx);
1349                                                 g_assert_not_reached ();
1350                                         }
1351                                 }
1352                         }
1353
1354                         /* no handler found - we need to call all finally handlers */
1355                         for (i = 0; i < ji->num_clauses; i++) {
1356                                 MonoJitExceptionInfo *ei = &ji->clauses [i];
1357
1358                                 if (ei->try_start <= ip && ip < (ei->try_end) &&
1359                                     (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
1360                                         call_finally (ctx, (unsigned long)ei->handler_start);
1361                                 }
1362                         }
1363                 }
1364
1365                 if (mono_object_isinst (obj, mono_defaults.exception_class)) {
1366                         char  *strace = mono_string_to_utf8 (((MonoException*)obj)->stack_trace);
1367                         char  *tmp;
1368
1369                         if (!strcmp (strace, "TODO: implement stack traces")){
1370                                 g_free (strace);
1371                                 strace = g_strdup ("");
1372                         }
1373
1374                         tmp = g_strdup_printf ("%sin %s.%s:%s ()\n", strace, m->klass->name_space,  
1375                                                m->klass->name, m->name);
1376
1377                         g_free (strace);
1378
1379                         ((MonoException*)obj)->stack_trace = mono_string_new (domain, tmp);
1380                         g_free (tmp);
1381                 }
1382
1383                 /* continue unwinding */
1384
1385                 /* restore caller saved registers */
1386                 if (ji->used_regs & X86_ESI_MASK) {
1387                         ctx->esi = *((int *)ctx->ebp + offset);
1388                         offset++;
1389                 }
1390                 if (ji->used_regs & X86_EDI_MASK) {
1391                         ctx->edi = *((int *)ctx->ebp + offset);
1392                         offset++;
1393                 }
1394                 if (ji->used_regs & X86_EBX_MASK) {
1395                         ctx->ebx = *((int *)ctx->ebp + offset);
1396                 }
1397
1398                 ctx->esp = ctx->ebp;
1399                 ctx->eip = *((int *)ctx->ebp + 1);
1400                 ctx->ebp = *((int *)ctx->ebp);
1401                 
1402                 if (ctx->ebp < (unsigned)mono_end_of_stack)
1403                         arch_handle_exception (ctx, obj);
1404                 else
1405                         mono_jit_abort (obj);
1406         } else {
1407                 gpointer *lmf_addr = TlsGetValue (lmf_thread_id);
1408                 MonoLMF *lmf;
1409                 MonoMethod *m;
1410
1411                 g_assert (lmf_addr);
1412                 lmf = *((MonoLMF **)lmf_addr);
1413
1414                 if (!lmf)
1415                         mono_jit_abort (obj);
1416
1417                 m = lmf->method;
1418
1419                 *lmf_addr = lmf->previous_lmf;
1420
1421                 ctx->esi = lmf->esi;
1422                 ctx->edi = lmf->edi;
1423                 ctx->ebx = lmf->ebx;
1424                 ctx->ebp = lmf->ebp;
1425                 ctx->eip = lmf->eip;
1426                 ctx->esp = (unsigned long)&lmf->eip;
1427
1428                 if (mono_object_isinst (obj, mono_defaults.exception_class)) {
1429                         char  *strace = mono_string_to_utf8 (((MonoException*)obj)->stack_trace);
1430                         char  *tmp;
1431
1432                         if (!strcmp (strace, "TODO: implement stack traces"))
1433                                 strace = g_strdup ("");
1434
1435                         tmp = g_strdup_printf ("%sin (unmanaged) %s.%s:%s ()\n", strace, m->klass->name_space,  
1436                                                m->klass->name, m->name);
1437
1438                         g_free (strace);
1439
1440                         ((MonoException*)obj)->stack_trace = mono_string_new (domain, tmp);
1441                         g_free (tmp);
1442                 }
1443
1444                 if (ctx->eip < (unsigned)mono_end_of_stack)
1445                         arch_handle_exception (ctx, obj);
1446                 else
1447                         mono_jit_abort (obj);
1448         }
1449
1450         g_assert_not_reached ();
1451 }
1452
1453 static void
1454 throw_exception (unsigned long eax, unsigned long ecx, unsigned long edx, unsigned long ebx,
1455                  unsigned long esi, unsigned long edi, unsigned long ebp, MonoObject *exc,
1456                  unsigned long eip,  unsigned long esp)
1457 {
1458         struct sigcontext ctx;
1459
1460         ctx.esp = esp;
1461         ctx.eip = eip;
1462         ctx.ebp = ebp;
1463         ctx.edi = edi;
1464         ctx.esi = esi;
1465         ctx.ebx = ebx;
1466         ctx.edx = edx;
1467         ctx.ecx = ecx;
1468         ctx.eax = eax;
1469         
1470         arch_handle_exception (&ctx, exc);
1471
1472         g_assert_not_reached ();
1473 }
1474
1475 /**
1476  * arch_get_throw_exception:
1477  *
1478  * Returns a function pointer which can be used to raise 
1479  * exceptions. The returned function has the following 
1480  * signature: void (*func) (MonoException *exc); 
1481  * For example to raise an arithmetic exception you can use:
1482  *
1483  * x86_push_imm (code, mono_get_exception_arithmetic ()); 
1484  * x86_call_code (code, arch_get_throw_exception ()); 
1485  *
1486  */
1487 gpointer 
1488 arch_get_throw_exception (void)
1489 {
1490         static guint8 start [24];
1491         static int inited = 0;
1492         guint8 *code;
1493
1494         if (inited)
1495                 return start;
1496
1497         inited = 1;
1498         code = start;
1499
1500         x86_push_reg (code, X86_ESP);
1501         x86_push_membase (code, X86_ESP, 4); /* IP */
1502         x86_push_membase (code, X86_ESP, 12); /* exception */
1503         x86_push_reg (code, X86_EBP);
1504         x86_push_reg (code, X86_EDI);
1505         x86_push_reg (code, X86_ESI);
1506         x86_push_reg (code, X86_EBX);
1507         x86_push_reg (code, X86_EDX);
1508         x86_push_reg (code, X86_ECX);
1509         x86_push_reg (code, X86_EAX);
1510         x86_call_code (code, throw_exception);
1511         /* we should never reach this breakpoint */
1512         x86_breakpoint (code);
1513
1514         g_assert ((code - start) < 24);
1515         return start;
1516 }
1517
1518 /**
1519  * arch_get_throw_exception_by_name:
1520  *
1521  * Returns a function pointer which can be used to raise 
1522  * corlib exceptions. The returned function has the following 
1523  * signature: void (*func) (char *exc_name); 
1524  * For example to raise an arithmetic exception you can use:
1525  *
1526  * x86_push_imm (code, "ArithmeticException"); 
1527  * x86_call_code (code, arch_get_throw_exception ()); 
1528  *
1529  */
1530 gpointer 
1531 arch_get_throw_exception_by_name ()
1532 {
1533         static guint8 start [32];
1534         static int inited = 0;
1535         guint8 *code;
1536
1537         if (inited)
1538                 return start;
1539
1540         inited = 1;
1541         code = start;
1542
1543         /* fixme: we do not save EAX, EDX, ECD - unsure if we need that */
1544
1545         x86_push_membase (code, X86_ESP, 4); /* exception name */
1546         x86_push_imm (code, "System");
1547         x86_push_imm (code, mono_defaults.exception_class->image);
1548         x86_call_code (code, mono_exception_from_name);
1549         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 12);
1550         /* save the newly create object (overwrite exception name)*/
1551         x86_mov_membase_reg (code, X86_ESP, 4, X86_EAX, 4);
1552         x86_jump_code (code, arch_get_throw_exception ());
1553
1554         g_assert ((code - start) < 32);
1555
1556         return start;
1557 }       
1558
1559 /*
1560  * this returns a helper method to invoke a method with a user supplied
1561  * stack frame. The returned method has the following signature:
1562  * invoke_method_with_frame ((gpointer code, gpointer frame, int frame_size);
1563  */
1564 static gpointer
1565 get_invoke_method_with_frame ()
1566 {
1567         static guint8 *start;
1568         guint8 *code;
1569
1570         if (start)
1571                 return start;
1572
1573         start = code = g_malloc (64);
1574
1575         /* Prolog */
1576         x86_push_reg (code, X86_EBP);
1577         x86_mov_reg_reg (code, X86_EBP, X86_ESP, 4);
1578         x86_push_reg (code, X86_EBX);
1579         x86_push_reg (code, X86_EDI);
1580         x86_push_reg (code, X86_ESI);
1581
1582         x86_mov_reg_membase (code, X86_EAX, X86_EBP, 16, 4);
1583         x86_alu_reg_reg (code, X86_SUB, X86_ESP, X86_EAX);
1584
1585         x86_push_membase (code, X86_EBP, 16);
1586         x86_push_membase (code, X86_EBP, 12);
1587         x86_lea_membase (code, X86_EAX, X86_ESP, 2*4);
1588         x86_push_reg (code, X86_EAX);
1589         x86_call_code (code, memcpy);
1590         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 12);
1591
1592         x86_mov_reg_membase (code, X86_EAX, X86_EBP, 8, 4);
1593         x86_call_reg (code, X86_EAX);
1594
1595         x86_mov_reg_membase (code, X86_ECX, X86_EBP, 16, 4);
1596         x86_alu_reg_reg (code, X86_ADD, X86_ESP, X86_ECX);
1597
1598         /* Epilog */
1599         x86_pop_reg (code, X86_ESI);
1600         x86_pop_reg (code, X86_EDI);
1601         x86_pop_reg (code, X86_EBX);
1602         x86_leave (code);
1603         x86_ret (code);
1604         
1605         g_assert ((code - start) < 64);
1606
1607         return start;
1608 }
1609
1610 /**
1611  * arch_runtime_invoke:
1612  * @method: the method to invoke
1613  * @obj: this pointer
1614  * @params: array of parameter values.
1615  *
1616  * TODO: very ugly piece of code. we should replace that with a method-specific 
1617  * trampoline (as suggested by Paolo).
1618  */
1619 MonoObject*
1620 arch_runtime_invoke (MonoMethod *method, void *obj, void **params)
1621 {
1622         static guint64 (*invoke_int64) (gpointer code, gpointer frame, int frame_size) = NULL;
1623         static double (*invoke_double) (gpointer code, gpointer frame, int frame_size) = NULL;
1624         MonoObject *retval;
1625         MonoMethodSignature *sig = method->signature;
1626         int i, tmp, type, sp = 0;
1627         void *ret;
1628         int frame_size = 0;
1629         gpointer *frame;
1630         gpointer code;
1631
1632         /* allocate ret object. */
1633         if (sig->ret->type == MONO_TYPE_VOID) {
1634                 retval = NULL;
1635                 ret = NULL;
1636         } else {
1637                 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1638                 if (klass->valuetype) {
1639                         retval = mono_object_new (mono_domain_get (), klass);
1640                         ret = ((char*)retval) + sizeof (MonoObject);
1641                 } else {
1642                         ret = &retval;
1643                 }
1644         }
1645    
1646         if (ISSTRUCT (sig->ret))
1647                 frame_size += sizeof (gpointer);
1648         
1649         if (sig->hasthis) 
1650                 frame_size += sizeof (gpointer);
1651
1652         for (i = 0; i < sig->param_count; ++i) {
1653                 int align;
1654                 frame_size += mono_type_stack_size (sig->params [i], &align);
1655         }
1656
1657         frame = alloca (frame_size);
1658
1659         if (ISSTRUCT (sig->ret))
1660                 frame [sp++] = ret;
1661
1662         if (sig->hasthis) 
1663                 frame [sp++] = obj;
1664                 
1665
1666         for (i = 0; i < sig->param_count; ++i) {
1667                 if (sig->params [i]->byref) {
1668                         frame [sp++] = params [i];
1669                         continue;
1670                 }
1671                 type = sig->params [i]->type;
1672 handle_enum:
1673                 switch (type) {
1674                 case MONO_TYPE_U1:
1675                 case MONO_TYPE_I1:
1676                 case MONO_TYPE_BOOLEAN:
1677                         tmp = *(MonoBoolean*)params [i];
1678                         frame [sp++] = (gpointer)tmp;                   
1679                         break;
1680                 case MONO_TYPE_U2:
1681                 case MONO_TYPE_I2:
1682                 case MONO_TYPE_CHAR:
1683                         tmp = *(gint16*)params [i];
1684                         frame [sp++] = (gpointer)tmp;                   
1685                         break;
1686 #if SIZEOF_VOID_P == 4
1687                 case MONO_TYPE_U:
1688                 case MONO_TYPE_I:
1689 #endif
1690                 case MONO_TYPE_U4:
1691                 case MONO_TYPE_I4:
1692                         frame [sp++] = (gpointer)*(gint32*)params [i];
1693                         break;
1694 #if SIZEOF_VOID_P == 8
1695                 case MONO_TYPE_U:
1696                 case MONO_TYPE_I:
1697 #endif
1698                 case MONO_TYPE_U8:
1699                 case MONO_TYPE_I8:
1700                         frame [sp++] = (gpointer)*(gint32*)params [i];
1701                         frame [sp++] = (gpointer)*(((gint32*)params [i]) + 1);
1702                         break;
1703                 case MONO_TYPE_VALUETYPE:
1704                         if (sig->params [i]->data.klass->enumtype) {
1705                                 type = sig->params [i]->data.klass->enum_basetype->type;
1706                                 goto handle_enum;
1707                         } else {
1708                                 g_warning ("generic valutype %s not handled in runtime invoke", sig->params [i]->data.klass->name);
1709                         }
1710                         break;
1711                 case MONO_TYPE_STRING:
1712                         frame [sp++] = params [i];
1713                         break;
1714                 default:
1715                         g_error ("type 0x%x not handled in invoke", sig->params [i]->type);
1716                 }
1717         }
1718
1719         code = arch_compile_method (method);
1720
1721         if (!invoke_int64)
1722                 invoke_int64 = (gpointer)invoke_double = get_invoke_method_with_frame ();
1723
1724         type = sig->ret->type;
1725 handle_enum_2:
1726         switch (type) {
1727         case MONO_TYPE_VOID:
1728                 invoke_int64 (code, frame, frame_size);         
1729                 break;
1730         case MONO_TYPE_U1:
1731         case MONO_TYPE_I1:
1732         case MONO_TYPE_BOOLEAN:
1733         case MONO_TYPE_U2:
1734         case MONO_TYPE_I2:
1735         case MONO_TYPE_CHAR:
1736 #if SIZEOF_VOID_P == 4
1737         case MONO_TYPE_U:
1738         case MONO_TYPE_I:
1739 #endif
1740         case MONO_TYPE_U4:
1741         case MONO_TYPE_I4:
1742         case MONO_TYPE_STRING:
1743                 *((guint32 *)ret) = invoke_int64 (code, frame, frame_size);             
1744                 break;
1745 #if SIZEOF_VOID_P == 8
1746         case MONO_TYPE_U:
1747         case MONO_TYPE_I:
1748 #endif
1749         case MONO_TYPE_U8:
1750         case MONO_TYPE_I8:
1751                 *((guint64 *)ret) = invoke_int64 (code, frame, frame_size);             
1752                 break;
1753         case MONO_TYPE_R4:
1754                 *((float *)ret) = invoke_double (code, frame, frame_size);              
1755                 break;
1756         case MONO_TYPE_R8:
1757                 *((double *)ret) = invoke_double (code, frame, frame_size);             
1758                 break;
1759         case MONO_TYPE_VALUETYPE:
1760                 if (sig->params [i]->data.klass->enumtype) {
1761                         type = sig->params [i]->data.klass->enum_basetype->type;
1762                         goto handle_enum_2;
1763                 } else 
1764                         invoke_int64 (code, frame, frame_size);         
1765                 break;
1766         default:
1767                 g_error ("type 0x%x not handled in invoke", sig->params [i]->type);
1768         }
1769
1770         return retval;
1771 }
1772
1773 gpointer
1774 arch_create_native_wrapper (MonoMethod *method)
1775 {
1776         MonoMethodSignature *csig = method->signature;
1777         MonoJitInfo *ji;
1778         guint8 *code, *start;
1779         int i, align, locals = 0, arg_size = 0;
1780         gboolean pinvoke = FALSE;
1781         GList *str_list = NULL;
1782
1783         if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
1784             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
1785                 pinvoke = TRUE;
1786
1787         /* compute the size of the activation frame */
1788
1789         if (csig->hasthis)
1790                 arg_size += sizeof (gpointer);
1791
1792         if (csig->ret->type == MONO_TYPE_VALUETYPE) {
1793                 g_assert (!csig->ret->byref);
1794                 arg_size += sizeof (gpointer);          
1795         }
1796                 
1797         for (i = 0; i < csig->param_count; ++i) {
1798                 arg_size += mono_type_stack_size (csig->params [i], &align);
1799                 if (pinvoke && (csig->params [i]->type == MONO_TYPE_STRING))
1800                         locals++;
1801         }
1802
1803         start = code = g_malloc (512);
1804
1805         /* save LMF - the instruction pointer is already on the 
1806          * stack (return address) */
1807
1808         /* save all caller saved regs */
1809         x86_push_reg (code, X86_EBX);
1810         x86_push_reg (code, X86_EDI);
1811         x86_push_reg (code, X86_ESI);
1812         x86_push_reg (code, X86_EBP);
1813
1814         /* save method info */
1815         x86_push_imm (code, method);
1816         
1817         /* get the address of lmf for the current thread */
1818         x86_call_code (code, arch_get_lmf_addr);
1819         /* push lmf */
1820         x86_push_reg (code, X86_EAX); 
1821         /* push *lfm (previous_lmf) */
1822         x86_push_membase (code, X86_EAX, 0);
1823         /* *(lmf) = ESP */
1824         x86_mov_membase_reg (code, X86_EAX, 0, X86_ESP, 4);
1825
1826         if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
1827                 guint8 *l1, *l2;
1828
1829                 if (arg_size) {
1830                         /* repush all arguments */
1831                         /* load argument size -4 into ECX */
1832                         x86_mov_reg_imm (code, X86_ECX, (arg_size - 4));
1833                         /* load source address */
1834                         x86_lea_membase (code, X86_ESI, X86_ESP, sizeof (MonoLMF));
1835                         /* allocate destination */
1836                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, arg_size);
1837                         /* load destination address */
1838                         x86_mov_reg_reg (code, X86_EDI, X86_ESP, 4);
1839
1840                         l1 = code;
1841                         x86_mov_reg_memindex (code, X86_EAX, X86_ESI, 0, X86_ECX, 0, 4);
1842                         x86_mov_memindex_reg (code, X86_EDI, 0, X86_ECX, 0, X86_EAX, 4);
1843                         x86_alu_reg_imm (code, X86_SUB, X86_ECX, 4);
1844                         l2 = code;
1845                         x86_branch8 (code, X86_CC_GEZ, l1 - (l2 + 2), FALSE); 
1846                 }
1847
1848         } else if (pinvoke) {
1849                 int offset = arg_size + (locals <<2) + sizeof (MonoLMF) - 4;
1850                 int l = 0;
1851                 
1852                 /* allocate locals */
1853                 if (locals) {
1854                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, (locals<<2));
1855                         x86_mov_reg_reg (code, X86_EBP, X86_ESP, 4);
1856                 }
1857
1858                 for (i = csig->param_count - 1; i >= 0; i--) {
1859                         MonoType *t = csig->params [i];
1860                         int type;
1861
1862                         if (t->byref) {
1863                                 x86_push_membase (code, X86_ESP, offset);
1864                                 continue;
1865                         }
1866
1867                         type = t->type;
1868 enum_marshal:
1869                         switch (type) {
1870                         case MONO_TYPE_BOOLEAN:
1871                         case MONO_TYPE_CHAR:
1872                         case MONO_TYPE_I1:
1873                         case MONO_TYPE_U1:
1874                         case MONO_TYPE_I2:
1875                         case MONO_TYPE_U2:
1876                         case MONO_TYPE_I4:
1877                         case MONO_TYPE_U4:
1878                         case MONO_TYPE_I:
1879                         case MONO_TYPE_U:
1880                         case MONO_TYPE_OBJECT:
1881                         case MONO_TYPE_CLASS:
1882                         case MONO_TYPE_SZARRAY:
1883                         case MONO_TYPE_PTR:
1884                         case MONO_TYPE_FNPTR:
1885                         case MONO_TYPE_ARRAY:
1886                         case MONO_TYPE_TYPEDBYREF:
1887                         case MONO_TYPE_R4:
1888                                 x86_push_membase (code, X86_ESP, offset);
1889                                 break;
1890                         case MONO_TYPE_STRING:
1891                                 x86_push_membase (code, X86_ESP, offset);
1892                                 x86_call_code (code, mono_string_to_utf8);
1893                                 x86_mov_membase_reg (code, X86_ESP, 0, X86_EAX, 4);
1894                                 str_list = g_list_prepend (str_list, (gpointer)l);
1895                                 x86_mov_membase_reg (code, X86_EBP, l, X86_EAX, 4);
1896                                 l+= 4;
1897                                 break;
1898                         case MONO_TYPE_I8:
1899                         case MONO_TYPE_U8:
1900                         case MONO_TYPE_R8:
1901                                 x86_push_membase (code, X86_ESP, offset);
1902                                 x86_push_membase (code, X86_ESP, offset);
1903                                 break;
1904                         case MONO_TYPE_VALUETYPE:
1905                                 if (t->data.klass->enumtype) {
1906                                         type = t->data.klass->enum_basetype->type;
1907                                         goto enum_marshal;
1908                                 } else {
1909                                         int j, size;
1910                                         size = mono_type_stack_size (csig->params [i], &align);
1911                                         size = size >> 2;
1912                                         for (j = 0; j < size; j++)
1913                                                 x86_push_membase (code, X86_ESP, offset);
1914                                 }
1915                                 break;
1916                         default:
1917                                 g_error ("type 0x%02x unknown", t->type);
1918
1919                         }
1920                 }                       
1921
1922                 if (csig->ret->type == MONO_TYPE_VALUETYPE) {
1923                         g_assert (!csig->ret->byref);
1924                         x86_push_membase (code, X86_ESP, offset);
1925                 }
1926
1927                 if (csig->hasthis) {
1928                         x86_push_membase (code, X86_ESP, offset);
1929                 }
1930
1931         } else {
1932                 g_assert_not_reached ();
1933         }
1934
1935         if (method->addr) {
1936                 /* call the native code */
1937                 x86_call_code (code, method->addr);
1938         } else {
1939                 /* raise exception */
1940                 x86_push_imm (code, "NotImplementedException");              
1941                 x86_call_code (code, arch_get_throw_exception_by_name ());
1942         }
1943
1944         /* free pinvoke string args */
1945         if (str_list) {
1946                 GList *l;
1947
1948                 x86_push_reg (code, X86_EAX);
1949                 x86_push_reg (code, X86_EDX);
1950                 
1951                 for (l = str_list; l; l = l->next) {
1952                         x86_push_membase (code, X86_EBP, ((int)l->data));
1953                         x86_call_code (code, g_free);
1954                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
1955                 }
1956
1957                 x86_pop_reg (code, X86_EDX);
1958                 x86_pop_reg (code, X86_EAX);
1959
1960                 g_list_free (str_list);
1961         }
1962
1963         /* remove arguments from stack */
1964         if (arg_size || locals)
1965                 x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size + (locals<<2));
1966
1967         if (pinvoke && !csig->ret->byref && (csig->ret->type == MONO_TYPE_STRING)) {
1968                 /* If the argument is non-null, then convert the value back */
1969                 x86_alu_reg_reg (code, X86_OR, X86_EAX, X86_EAX);
1970                 x86_branch8 (code, X86_CC_EQ, 9, FALSE);
1971                 x86_push_reg (code, X86_EAX);
1972                 x86_call_code (code, mono_string_new_wrapper);
1973                 x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
1974         }
1975         
1976         /* restore the LMF */
1977         
1978         /* ebx = previous_lmf */
1979         x86_pop_reg (code, X86_EBX);
1980         /* edi = lmf */
1981         x86_pop_reg (code, X86_EDI);
1982         /* *(lmf) = previous_lmf */
1983         x86_mov_membase_reg (code, X86_EDI, 0, X86_EBX, 4);
1984
1985         /* discard method info */
1986         x86_pop_reg (code, X86_ESI);
1987
1988         /* restore caller saved regs */
1989         x86_pop_reg (code, X86_EBP);
1990         x86_pop_reg (code, X86_ESI);
1991         x86_pop_reg (code, X86_EDI);
1992         x86_pop_reg (code, X86_EBX);
1993
1994         x86_ret (code);
1995
1996         /* we store a dummy jit info (code size 4), so that mono_delegate_ctor
1997          * is able to find a method info for icalls and pinvoke methods */
1998         ji = g_new0 (MonoJitInfo, 1);
1999         ji->method = method;
2000         ji->code_start = start;
2001         ji->code_size = 4;
2002         ji->used_regs = 0;
2003         ji->num_clauses = 0;
2004         mono_jit_info_table_add (mono_jit_info_table, ji);
2005
2006         g_assert ((code - start) < 512);
2007
2008         return start;
2009 }
2010
2011