2001-11-16 Dietmar Maurer <dietmar@ximian.com>
[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/mono-endian.h>
20 #include <mono/arch/x86/x86-codegen.h>
21
22 #include "jit.h"
23 #include "codegen.h"
24
25 static void
26 enter_method (MonoMethod *method, gpointer ebp)
27 {
28         int i, j;
29         MonoClass *class;
30         MonoObject *o;
31
32         printf ("ENTER: %s.%s::%s (", method->klass->name_space,
33                 method->klass->name, method->name);
34
35         ebp += 8;
36
37         if (method->signature->ret->type == MONO_TYPE_VALUETYPE) {
38                 int size, align;
39
40                 if ((size = mono_type_size (method->signature->ret, &align)) > 4 || size == 3) {
41                         printf ("VALUERET:%p, ", *((gpointer *)ebp));
42                         ebp += sizeof (gpointer);
43                 }
44         }
45
46         if (method->signature->hasthis) {
47                 if (method->klass->valuetype) {
48                         printf ("value:%p, ", *((gpointer *)ebp));
49                 } else {
50                         o = *((MonoObject **)ebp);
51                         class = o->klass;
52                         printf ("this:%p[%s.%s], ", o, class->name_space, class->name);
53                 }
54                 ebp += sizeof (gpointer);
55         }
56
57         for (i = 0; i < method->signature->param_count; ++i) {
58                 MonoType *type = method->signature->params [i];
59                 int size, align;
60                 size = mono_type_size (type, &align);
61
62                 switch (type->type) {
63                 case MONO_TYPE_BOOLEAN:
64                 case MONO_TYPE_CHAR:
65                 case MONO_TYPE_I1:
66                 case MONO_TYPE_U1:
67                 case MONO_TYPE_I2:
68                 case MONO_TYPE_U2:
69                 case MONO_TYPE_I4:
70                 case MONO_TYPE_U4:
71                 case MONO_TYPE_I:
72                 case MONO_TYPE_U:
73                         printf ("%d, ", *((int *)(ebp)));
74                         break;
75                 case MONO_TYPE_STRING:
76                 case MONO_TYPE_PTR:
77                 case MONO_TYPE_CLASS:
78                 case MONO_TYPE_OBJECT:
79                 case MONO_TYPE_FNPTR:
80                 case MONO_TYPE_ARRAY:
81                 case MONO_TYPE_SZARRAY:
82                         printf ("%p, ", *((gpointer *)(ebp)));
83                         break;
84                 case MONO_TYPE_I8:
85                         printf ("%lld, ", *((gint64 *)(ebp)));
86                         break;
87                 case MONO_TYPE_R8:
88                         printf ("%f, ", *((double *)(ebp)));
89                         break;
90                 case MONO_TYPE_VALUETYPE: 
91                         printf ("[");
92                         for (j = 0; j < size; j++)
93                                 printf ("%02x,", *((guint8*)ebp +j));
94                         printf ("], ");
95                         break;
96                 default:
97                         printf ("XX, ");
98                 }
99
100                 ebp += size + 3;
101                 ebp = (gpointer)((unsigned)ebp & ~(3));
102         }
103
104         printf (")\n");
105 }
106
107 static void
108 leave_method (MonoMethod *method, int edx, int eax, double test)
109 {
110         gint64 l;
111
112         switch (method->signature->ret->type) {
113         case MONO_TYPE_VOID:
114                 printf ("LEAVE: %s.%s::%s\n", method->klass->name_space,
115                         method->klass->name, method->name);
116                 break;
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                 printf ("LEAVE: %s.%s::%s EAX=%d\n", method->klass->name_space,
128                         method->klass->name, method->name, eax);
129                 break;
130         case MONO_TYPE_STRING:
131         case MONO_TYPE_PTR:
132         case MONO_TYPE_CLASS:
133         case MONO_TYPE_OBJECT:
134         case MONO_TYPE_FNPTR:
135         case MONO_TYPE_ARRAY:
136         case MONO_TYPE_SZARRAY:
137                 printf ("LEAVE: %s.%s::%s EAX=%p\n", method->klass->name_space,
138                         method->klass->name, method->name, (gpointer)eax);
139                 break;
140         case MONO_TYPE_I8:
141                 *((gint32 *)&l) = eax;
142                 *((gint32 *)&l + 1) = edx;
143                 printf ("LEAVE: %s.%s::%s EAX/EDX=%lld\n", method->klass->name_space,
144                         method->klass->name, method->name, l);
145                 break;
146         case MONO_TYPE_R8:
147                 printf ("LEAVE: %s.%s::%s FP=%f\n", method->klass->name_space,
148                         method->klass->name, method->name, test);
149                 break;
150         default:
151                 printf ("LEAVE: %s.%s::%s (unknown return type)\n", method->klass->name_space,
152                         method->klass->name, method->name);
153         }
154 }
155
156 /**
157  * arch_emit_prologue:
158  * @cfg: pointer to status information
159  *
160  * Emits the function prolog.
161  */
162 static void
163 arch_emit_prologue (MonoFlowGraph *cfg)
164 {
165         x86_push_reg (cfg->code, X86_EBP);
166         x86_mov_reg_reg (cfg->code, X86_EBP, X86_ESP, 4);
167         
168         if (cfg->locals_size)
169                 x86_alu_reg_imm (cfg->code, X86_SUB, X86_ESP, cfg->locals_size);
170
171         if (mono_regset_reg_used (cfg->rs, X86_EBX)) 
172                 x86_push_reg (cfg->code, X86_EBX);
173
174         if (mono_regset_reg_used (cfg->rs, X86_EDI)) 
175                 x86_push_reg (cfg->code, X86_EDI);
176
177         if (mono_regset_reg_used (cfg->rs, X86_ESI))
178                 x86_push_reg (cfg->code, X86_ESI);
179
180         if (mono_jit_trace_calls) {
181                 x86_push_reg (cfg->code, X86_EBP);
182                 x86_push_imm (cfg->code, cfg->method);
183                 x86_call_code (cfg->code, enter_method);
184                 x86_alu_reg_imm (cfg->code, X86_ADD, X86_ESP, 8);
185         }
186 }
187
188 /**
189  * arch_emit_epilogue:
190  * @cfg: pointer to status information
191  *
192  * Emits the function epilog.
193  */
194 static void
195 arch_emit_epilogue (MonoFlowGraph *cfg)
196 {
197         if (mono_jit_trace_calls) {
198                 x86_fld_reg (cfg->code, 0);
199                 x86_alu_reg_imm (cfg->code, X86_SUB, X86_ESP, 8);
200                 x86_fst_membase (cfg->code, X86_ESP, 0, TRUE, TRUE);
201                 x86_push_reg (cfg->code, X86_EAX);
202                 x86_push_reg (cfg->code, X86_EDX);
203                 x86_push_imm (cfg->code, cfg->method);
204                 x86_call_code (cfg->code, leave_method);
205                 x86_alu_reg_imm (cfg->code, X86_ADD, X86_ESP, 4);
206                 x86_pop_reg (cfg->code, X86_EDX);
207                 x86_pop_reg (cfg->code, X86_EAX);
208                 x86_alu_reg_imm (cfg->code, X86_ADD, X86_ESP, 8);
209         }
210
211         if (mono_regset_reg_used (cfg->rs, X86_EDI))
212                 x86_pop_reg (cfg->code, X86_EDI);
213
214         if (mono_regset_reg_used (cfg->rs, X86_ESI))
215                 x86_pop_reg (cfg->code, X86_ESI);
216
217         if (mono_regset_reg_used (cfg->rs, X86_EBX))
218                 x86_pop_reg (cfg->code, X86_EBX);
219
220         x86_leave (cfg->code);
221         x86_ret (cfg->code);
222 }
223
224 /**
225  * x86_magic_trampoline:
226  * @eax: saved x86 register 
227  * @ecx: saved x86 register 
228  * @edx: saved x86 register 
229  * @esi: saved x86 register 
230  * @edi: saved x86 register 
231  * @ebx: saved x86 register
232  * @code: pointer into caller code
233  * @method: the method to translate
234  *
235  * This method is called by the trampoline functions for virtual
236  * methods. It inspects the caller code to find the address of the
237  * vtable slot, then calls the JIT compiler and writes the address
238  * of the compiled method back to the vtable. All virtual methods 
239  * are called with: x86_call_membase (inst, basereg, disp). We always
240  * use 32 bit displacement to ensure that the length of the call 
241  * instruction is 6 bytes. We need to get the value of the basereg 
242  * and the constant displacement.
243  */
244 static gpointer
245 x86_magic_trampoline (int eax, int ecx, int edx, int esi, int edi, 
246                       int ebx, guint8 *code, MonoMethod *m)
247 {
248         guint8 ab, reg;
249         gint32 disp;
250         gpointer o;
251
252         /* go to the start of the call instruction */
253         code -= 6;
254         g_assert (*code == 0xff);
255
256         code++;
257         ab = *code;
258         g_assert ((ab >> 6) == 2);
259         
260         /* extract the register number containing the address */
261         reg = ab & 0x07;
262         code++;
263
264         /* extract the displacement */
265         disp = *((gint32*)code);
266
267         switch (reg) {
268         case X86_EAX:
269                 o = (gpointer)eax;
270                 break;
271         case X86_EDX:
272                 o = (gpointer)edx;
273                 break;
274         case X86_ECX:
275                 o = (gpointer)ecx;
276                 break;
277         case X86_ESI:
278                 o = (gpointer)esi;
279                 break;
280         case X86_EDI:
281                 o = (gpointer)edi;
282                 break;
283         case X86_EBX:
284                 o = (gpointer)ebx;
285                 break;
286         default:
287                 g_assert_not_reached ();
288         }
289
290         o += disp;
291
292         return *((gpointer *)o) = arch_compile_method (m);
293 }
294
295 /**
296  * arch_create_jit_trampoline:
297  * @method: pointer to the method info
298  *
299  * Creates a trampoline function for virtual methods. If the created
300  * code is called it first starts JIT compilation of method,
301  * and then calls the newly created method. I also replaces the
302  * corresponding vtable entry (see x86_magic_trampoline).
303  * 
304  * Returns: a pointer to the newly created code 
305  */
306 gpointer
307 arch_create_jit_trampoline (MonoMethod *method)
308 {
309         guint8 *code, *buf;
310         static guint8 *vc = NULL;
311
312         if (method->addr)
313                 return method->addr;
314
315         if (!vc) {
316                 vc = buf = g_malloc (24);
317
318                 /* push the return address onto the stack */
319                 x86_push_membase (buf, X86_ESP, 4);
320
321                 /* save all register values */
322                 x86_push_reg (buf, X86_EBX);
323                 x86_push_reg (buf, X86_EDI);
324                 x86_push_reg (buf, X86_ESI);
325                 x86_push_reg (buf, X86_EDX);
326                 x86_push_reg (buf, X86_ECX);
327                 x86_push_reg (buf, X86_EAX);
328
329                 x86_call_code (buf, x86_magic_trampoline);
330                 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 8*4);
331
332                 /* call the compiled method */
333                 x86_jump_reg (buf, X86_EAX);
334
335                 g_assert ((buf - vc) <= 24);
336         }
337
338         code = buf = g_malloc (16);
339         x86_push_imm (buf, method);
340         x86_jump_code (buf, vc);
341         g_assert ((buf - code) <= 16);
342
343         return code;
344 }
345
346 /**
347  * arch_create_simple_jit_trampoline:
348  * @method: pointer to the method info
349  *
350  * Creates a trampoline function for method. If the created
351  * code is called it first starts JIT compilation of method,
352  * and then calls the newly created method. I also replaces the
353  * address in method->addr with the result of the JIT 
354  * compilation step (in arch_compile_method).
355  * 
356  * Returns: a pointer to the newly created code 
357  */
358 gpointer
359 arch_create_simple_jit_trampoline (MonoMethod *method)
360 {
361         guint8 *code, *buf;
362
363         if (method->addr)
364                 return method->addr;
365
366         /* we never free the allocated code buffer */
367         code = buf = g_malloc (16);
368         x86_push_imm (buf, method);
369         x86_call_code (buf, arch_compile_method);
370         x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 4);
371         /* jump to the compiled method */
372         x86_jump_reg (buf, X86_EAX);
373         g_assert ((buf - code) < 16);
374
375         return code;
376 }
377
378 static void
379 mono_label_cfg (MonoFlowGraph *cfg)
380 {
381         int i, j;
382         
383         for (i = 0; i < cfg->block_count; i++) {
384                 GPtrArray *forest = cfg->bblocks [i].forest;
385                 const int top = forest->len;
386
387                 for (j = 0; j < top; j++) {
388                         MBTree *t1 = (MBTree *) g_ptr_array_index (forest, j);
389                         MBState *mbstate;
390
391                         mbstate =  mono_burg_label (t1, cfg);
392                         if (!mbstate) {
393                                 g_warning ("tree does not match");
394                                 mono_print_ctree (t1); printf ("\n\n");
395
396                                 mono_print_forest (forest);
397                                 g_assert_not_reached ();
398                         }
399                 }
400         }
401 }
402
403 static void
404 tree_allocate_regs (MBTree *tree, int goal, MonoRegSet *rs) 
405 {
406         MBTree *kids[10];
407         int ern = mono_burg_rule (tree->state, goal);
408         guint16 *nts = mono_burg_nts [ern];
409         int i;
410         
411         mono_burg_kids (tree, ern, kids);
412
413         switch (goal) {
414         case MB_NTERM_reg:
415         case MB_NTERM_lreg: {
416                 switch (tree->op) {
417                 case MB_TERM_SHL:
418                 case MB_TERM_SHR:
419                 case MB_TERM_SHR_UN:
420                         tree->exclude_mask |= (1 << X86_ECX);
421                         tree->left->exclude_mask |= (1 << X86_ECX);
422                         break;
423                 case MB_TERM_CALL_I4:
424                         tree->reg1 = X86_EAX;
425                         break;
426                 case MB_TERM_CALL_I8:
427                         tree->reg1 = X86_EAX;
428                         tree->reg2 = X86_EDX;
429                         break;
430                 case MB_TERM_DIV:
431                 case MB_TERM_DIV_UN:
432                 case MB_TERM_REM:
433                 case MB_TERM_REM_UN:
434                         tree->reg1 = X86_EAX;
435                         tree->reg2 = X86_EDX;
436                         if (goal == MB_NTERM_reg) {
437                                 tree->left->exclude_mask |= (1 << X86_EDX);
438                                 tree->right->exclude_mask |= (1 << X86_EDX);
439                         }
440                         break;
441                 default:
442                         break;
443                 }
444         }
445         default:
446                 break;
447         }
448
449         //printf ("RALLOC START %d %p %d\n",  tree->op, rs->free_mask, goal);
450
451         if (nts [0] && kids [0] == tree) {
452                 /* chain rule */
453                 tree_allocate_regs (kids [0], nts [0], rs);
454                 return;
455         }
456
457         for (i = 0; nts [i]; i++)
458                 tree_allocate_regs (kids [i], nts [i], rs);
459
460         for (i = 0; nts [i]; i++) {
461                 mono_regset_free_reg (rs, kids [i]->reg1);
462                 mono_regset_free_reg (rs, kids [i]->reg2);
463         }
464
465         switch (goal) {
466         case MB_NTERM_reg:
467                 if ((tree->reg1 = 
468                      mono_regset_alloc_reg (rs, tree->reg1, tree->exclude_mask)) == -1) {
469                         g_warning ("register allocation failed %d 0x%08x 0x%08x\n",  tree->reg1, rs->free_mask, tree->exclude_mask);
470                         g_assert_not_reached ();
471                 }
472                 break;
473
474         case MB_NTERM_lreg:
475                 if ((tree->reg1 = 
476                      mono_regset_alloc_reg (rs, tree->reg1, tree->exclude_mask)) == -1 ||
477                     (tree->reg2 = 
478                      mono_regset_alloc_reg (rs, tree->reg2, tree->exclude_mask)) == -1) {
479                         g_warning ("register allocation failed\n");
480                         g_assert_not_reached ();
481                 }
482                 break;
483
484         case MB_NTERM_freg:
485                 /* fixme: allocate floating point registers */
486                 break;
487       
488         case MB_NTERM_addr:
489                 if (tree->op == MB_TERM_ADD) {
490                         tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
491                         tree->reg2 = mono_regset_alloc_reg (rs, tree->right->reg1, tree->exclude_mask);
492                 }
493                 if (tree->op == MB_TERM_CALL_I4) {
494                         tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
495                 }
496                 break;
497                 
498         case MB_NTERM_base:
499                 if (tree->op == MB_TERM_ADD) {
500                         tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
501                 }
502                 break;
503                
504         case MB_NTERM_index:
505                 if (tree->op == MB_TERM_SHL ||
506                     tree->op == MB_TERM_MUL) {
507                         tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
508                 }
509                 break;
510                
511         default:
512                 /* do nothing */
513         }
514
515         //printf ("RALLOC END %d %p\n",  tree->op, rs->free_mask);
516         tree->emit = mono_burg_func [ern];
517 }
518
519 static void
520 arch_allocate_regs (MonoFlowGraph *cfg)
521 {
522         int i, j;
523         
524         for (i = 0; i < cfg->block_count; i++) {
525                 GPtrArray *forest = cfg->bblocks [i].forest;
526                 const int top = forest->len;
527
528                 for (j = 0; j < top; j++) {
529                         MBTree *t1 = (MBTree *) g_ptr_array_index (forest, j);
530                         //printf ("AREGSTART %d:%d %p\n", i, j, cfg->rs->free_mask);
531                         tree_allocate_regs (t1, 1, cfg->rs);
532                         //printf ("AREGENDT %d:%d %p\n", i, j, cfg->rs->free_mask);
533                         g_assert (cfg->rs->free_mask == 0xffffffff);
534                 }
535         }
536 }
537
538 static void
539 tree_emit (int goal, MonoFlowGraph *s, MBTree *tree) 
540 {
541         MBTree *kids[10];
542         int i, ern = mono_burg_rule (tree->state, goal);
543         guint16 *nts = mono_burg_nts [ern];
544         MBEmitFunc emit;
545
546         mono_burg_kids (tree, ern, kids);
547
548         for (i = 0; nts [i]; i++) 
549                 tree_emit (nts [i], s, kids [i]);
550
551         tree->addr = s->code - s->start;
552
553         if ((emit = mono_burg_func [ern]))
554                 emit (tree, s);
555 }
556
557 static void
558 mono_emit_cfg (MonoFlowGraph *cfg)
559 {
560         int i, j;
561
562         for (i = 0; i < cfg->block_count; i++) {
563                 MonoBBlock *bb = &cfg->bblocks [i];
564                 GPtrArray *forest = bb->forest;
565                 const int top = forest->len;
566
567                 bb->addr = cfg->code - cfg->start;
568           
569                 for (j = 0; j < top; j++) {
570                         MBTree *t1 = (MBTree *) g_ptr_array_index (forest, j);
571                         tree_emit (1, cfg, t1);
572                 }
573         }
574                 
575         cfg->epilog = cfg->code - cfg->start;
576 }
577
578 static void
579 mono_compute_branches (MonoFlowGraph *cfg)
580 {
581         guint8 *end;
582         int i, j;
583
584         end = cfg->code;
585
586         for (j = 0; j < cfg->block_count; j++) {
587                 MonoBBlock *bb = &cfg->bblocks [j];
588                 GPtrArray *forest = bb->forest;
589                 const int top = forest->len;
590         
591                 for (i = 0; i < top; i++) {
592                         MBTree *t1 = (MBTree *) g_ptr_array_index (forest, i);
593
594                         if (t1->is_jump) {
595
596                                 if (t1->op == MB_TERM_SWITCH) {
597                                         MonoBBlock **jt = (MonoBBlock **)t1->data.p;
598                                         guint32 *rt = (guint32 *)t1->data.p;
599
600                                         int m = *((guint32 *)t1->data.p) + 1;
601                                         int j;
602                                         
603                                         for (j = 1; j <= m; j++)
604                                                 rt [j] = (int)(jt [j]->addr + cfg->start);
605                                 }
606
607                                 /* emit the jump instruction again to update addresses */
608                                 cfg->code = cfg->start + t1->addr;
609                                 ((MBEmitFunc)t1->emit) (t1, cfg);
610
611                         }
612                 }
613         }
614
615         cfg->code = end;
616 }
617
618 /**
619  * arch_compile_method:
620  * @method: pointer to the method info
621  *
622  * JIT compilation of a single method. This method also writes the result 
623  * back to method->addr, an thus overwrites the trampoline function.
624  *
625  * Returns: a pointer to the newly created code.
626  */
627 gpointer
628 arch_compile_method (MonoMethod *method)
629 {
630         MonoFlowGraph *cfg;
631         MonoMemPool *mp = mono_mempool_new ();
632
633         g_assert (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL));
634         g_assert (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL));
635
636         if (mono_jit_trace_calls) {
637                 printf ("Start JIT compilation of %s.%s:%s\n", method->klass->name_space,
638                         method->klass->name, method->name);
639         }
640
641         cfg = mono_cfg_new (method, mp);
642
643         mono_analyze_flow (cfg);
644
645         mono_analyze_stack (cfg);
646
647         cfg->code = NULL;
648         cfg->rs = mono_regset_new (X86_NREG);
649         mono_regset_reserve_reg (cfg->rs, X86_ESP);
650         mono_regset_reserve_reg (cfg->rs, X86_EBP);
651
652         // fixme: remove limitation to 4096 bytes
653         method->addr = cfg->start = cfg->code = g_malloc (4096);
654
655         if (mono_jit_dump_forest) {
656                 int i;
657                 for (i = 0; i < cfg->block_count; i++) {
658                         printf ("BLOCK %d:\n", i);
659                         mono_print_forest (cfg->bblocks [i].forest);
660                 }
661         }
662
663         mono_label_cfg (cfg);
664
665         arch_allocate_regs (cfg);
666
667         arch_emit_prologue (cfg);
668
669         mono_emit_cfg (cfg);
670
671         arch_emit_epilogue (cfg);
672
673         mono_compute_branches (cfg);
674                 
675         if (mono_jit_dump_asm)
676                 mono_disassemble_code (cfg->start, cfg->code - cfg->start);
677
678         mono_regset_free (cfg->rs);
679
680         mono_cfg_free (cfg);
681
682         mono_mempool_destroy (mp);
683
684         if (mono_jit_trace_calls) {
685                 printf ("END JIT compilation of %s.%s:%s %p %p\n", method->klass->name_space,
686                         method->klass->name, method->name, method, method->addr);
687         }
688
689         return method->addr;
690 }
691
692
693