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