8789e282c3f5092cc07eb6ace928a7ea4525c85a
[cacao.git] / src / vm / jit / codegen-common.c
1 /* src/vm/jit/codegen-common.c - architecture independent code generator stuff
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    All functions assume the following code area / data area layout:
26
27    +-----------+
28    |           |
29    | code area | code area grows to higher addresses
30    |           |
31    +-----------+ <-- start of procedure
32    |           |
33    | data area | data area grows to lower addresses
34    |           |
35    +-----------+
36
37    The functions first write into a temporary code/data area allocated by
38    "codegen_init". "codegen_finish" copies the code and data area into permanent
39    memory. All functions writing values into the data area return the offset
40    relative the begin of the code area (start of procedure).    
41
42 */
43
44
45 #include "config.h"
46
47 #include <assert.h>
48 #include <string.h>
49
50 #include "vm/types.h"
51
52 #if defined(ENABLE_JIT)
53 /* this is required PATCHER_CALL_SIZE */
54 # include "codegen.h"
55 #endif
56
57 #include "mm/memory.h"
58
59 #include "toolbox/avl.h"
60 #include "toolbox/list.h"
61 #include "toolbox/logging.h"
62
63 #include "native/jni.h"
64 #include "native/localref.h"
65 #include "native/native.h"
66
67 #include "threads/threads-common.h"
68
69 #include "vm/builtin.h"
70 #include "vm/exceptions.h"
71 #include "vm/stringlocal.h"
72
73 #include "vm/jit/abi.h"
74 #include "vm/jit/asmpart.h"
75 #include "vm/jit/codegen-common.h"
76
77 #if defined(ENABLE_DISASSEMBLER)
78 # include "vm/jit/disass.h"
79 #endif
80
81 #include "vm/jit/dseg.h"
82 #include "vm/jit/emit-common.h"
83 #include "vm/jit/jit.h"
84 #include "vm/jit/md.h"
85 #include "vm/jit/patcher-common.h"
86 #include "vm/jit/replace.h"
87 #if defined(ENABLE_SSA)
88 # include "vm/jit/optimizing/lsra.h"
89 # include "vm/jit/optimizing/ssa.h"
90 #endif
91 #include "vm/jit/stacktrace.h"
92
93 #if defined(ENABLE_INTRP)
94 #include "vm/jit/intrp/intrp.h"
95 #endif
96
97 #include "vmcore/method.h"
98 #include "vmcore/options.h"
99
100 # include "vmcore/statistics.h"
101
102 #if defined(ENABLE_VMLOG)
103 #include <vmlog_cacao.h>
104 #endif
105
106 #include "show.h"
107
108 /* in this tree we store all method addresses *********************************/
109
110 static avl_tree_t *methodtree = NULL;
111 static s4 methodtree_comparator(const void *treenode, const void *node);
112
113
114 /* codegen_init ****************************************************************
115
116    TODO
117
118 *******************************************************************************/
119
120 void codegen_init(void)
121 {
122         /* this tree is global, not method specific */
123
124         if (!methodtree) {
125 #if defined(ENABLE_JIT)
126                 methodtree_element *mte;
127 #endif
128
129                 methodtree = avl_create(&methodtree_comparator);
130
131 #if defined(ENABLE_JIT)
132                 /* insert asm_vm_call_method */
133
134                 mte = NEW(methodtree_element);
135
136                 mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
137                 mte->endpc   = (u1 *) (ptrint) asm_vm_call_method_end;
138
139                 avl_insert(methodtree, mte);
140 #endif /* defined(ENABLE_JIT) */
141
142         }
143
144 }
145
146
147 /* codegen_setup ***************************************************************
148
149    Allocates and initialises code area, data area and references.
150
151 *******************************************************************************/
152
153 void codegen_setup(jitdata *jd)
154 {
155         methodinfo  *m;
156         codegendata *cd;
157
158         /* get required compiler data */
159
160         m  = jd->m;
161         cd = jd->cd;
162
163         /* initialize members */
164
165         cd->flags        = 0;
166
167         cd->mcodebase    = DMNEW(u1, MCODEINITSIZE);
168         cd->mcodeend     = cd->mcodebase + MCODEINITSIZE;
169         cd->mcodesize    = MCODEINITSIZE;
170
171         /* initialize mcode variables */
172
173         cd->mcodeptr     = cd->mcodebase;
174         cd->lastmcodeptr = cd->mcodebase;
175
176 #if defined(ENABLE_INTRP)
177         /* native dynamic superinstructions variables */
178
179         if (opt_intrp) {
180                 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
181                 cd->ncodesize = NCODEINITSIZE;
182
183                 /* initialize ncode variables */
184         
185                 cd->ncodeptr = cd->ncodebase;
186
187                 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
188                 cd->superstarts = NULL;
189         }
190 #endif
191
192         cd->dseg           = NULL;
193         cd->dseglen        = 0;
194
195         cd->jumpreferences = NULL;
196
197 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
198         cd->datareferences = NULL;
199 #endif
200
201 /*      cd->patchrefs      = list_create_dump(OFFSET(patchref, linkage)); */
202         cd->patchrefs      = NULL;
203         cd->brancheslabel  = list_create_dump(OFFSET(branch_label_ref_t, linkage));
204         cd->listcritical   = list_create_dump(OFFSET(critical_section_ref_t, linkage));
205
206         cd->linenumberreferences = NULL;
207         cd->linenumbertablesizepos = 0;
208         cd->linenumbertablestartpos = 0;
209         cd->linenumbertab = 0;
210 }
211
212
213 /* codegen_reset ***************************************************************
214
215    Resets the codegen data structure so we can recompile the method.
216
217 *******************************************************************************/
218
219 static void codegen_reset(jitdata *jd)
220 {
221         codeinfo    *code;
222         codegendata *cd;
223         basicblock  *bptr;
224
225         /* get required compiler data */
226
227         code = jd->code;
228         cd   = jd->cd;
229
230         /* reset error flag */
231
232         cd->flags          &= ~CODEGENDATA_FLAG_ERROR;
233
234         /* reset some members, we reuse the code memory already allocated
235            as this should have almost the correct size */
236
237         cd->mcodeptr        = cd->mcodebase;
238         cd->lastmcodeptr    = cd->mcodebase;
239
240         cd->dseg            = NULL;
241         cd->dseglen         = 0;
242
243         cd->jumpreferences  = NULL;
244
245 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
246         cd->datareferences  = NULL;
247 #endif
248
249 /*      cd->patchrefs       = list_create_dump(OFFSET(patchref, linkage)); */
250         cd->patchrefs       = NULL;
251         cd->brancheslabel   = list_create_dump(OFFSET(branch_label_ref_t, linkage));
252         cd->listcritical    = list_create_dump(OFFSET(critical_section_ref_t, linkage));
253
254         cd->linenumberreferences    = NULL;
255         cd->linenumbertablesizepos  = 0;
256         cd->linenumbertablestartpos = 0;
257         cd->linenumbertab           = 0;
258         
259         /* We need to clear the mpc and the branch references from all
260            basic blocks as they will definitely change. */
261
262         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
263                 bptr->mpc        = -1;
264                 bptr->branchrefs = NULL;
265         }
266
267         /* We need to clear all the patcher references from the codeinfo
268            since they all will be regenerated */
269
270         patcher_list_reset(code);
271
272 #if defined(ENABLE_REPLACEMENT)
273         code->rplpoints     = NULL;
274         code->rplpointcount = 0;
275         code->regalloc      = NULL;
276         code->regalloccount = 0;
277         code->globalcount   = 0;
278 #endif
279 }
280
281
282 /* codegen_generate ************************************************************
283
284    Generates the code for the currently compiled method.
285
286 *******************************************************************************/
287
288 bool codegen_generate(jitdata *jd)
289 {
290         codegendata *cd;
291
292         /* get required compiler data */
293
294         cd = jd->cd;
295
296         /* call the machine-dependent code generation function */
297
298         if (!codegen_emit(jd))
299                 return false;
300
301         /* check for an error */
302
303         if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
304                 /* check for long-branches flag, if it is set we recompile the
305                    method */
306
307 #if !defined(NDEBUG)
308         if (compileverbose)
309             log_message_method("Re-generating code: ", jd->m);
310 #endif
311
312                 /* XXX maybe we should tag long-branches-methods for recompilation */
313
314                 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
315                         /* we have to reset the codegendata structure first */
316
317                         codegen_reset(jd);
318
319                         /* and restart the compiler run */
320
321                         if (!codegen_emit(jd))
322                                 return false;
323                 }
324                 else {
325                         vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
326                 }
327
328 #if !defined(NDEBUG)
329         if (compileverbose)
330             log_message_method("Re-generating code done: ", jd->m);
331 #endif
332         }
333
334         /* reallocate the memory and finish the code generation */
335
336         codegen_finish(jd);
337
338         /* everything's ok */
339
340         return true;
341 }
342
343
344 /* codegen_close ***************************************************************
345
346    TODO
347
348 *******************************************************************************/
349
350 void codegen_close(void)
351 {
352         /* TODO: release avl tree on i386 and x86_64 */
353 }
354
355
356 /* codegen_increase ************************************************************
357
358    Doubles code area.
359
360 *******************************************************************************/
361
362 void codegen_increase(codegendata *cd)
363 {
364         u1 *oldmcodebase;
365
366         /* save old mcodebase pointer */
367
368         oldmcodebase = cd->mcodebase;
369
370         /* reallocate to new, doubled memory */
371
372         cd->mcodebase = DMREALLOC(cd->mcodebase,
373                                                           u1,
374                                                           cd->mcodesize,
375                                                           cd->mcodesize * 2);
376         cd->mcodesize *= 2;
377         cd->mcodeend   = cd->mcodebase + cd->mcodesize;
378
379         /* set new mcodeptr */
380
381         cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
382
383 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
384  || defined(__SPARC_64__)
385         /* adjust the pointer to the last patcher position */
386
387         if (cd->lastmcodeptr != NULL)
388                 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
389 #endif
390 }
391
392
393 /* codegen_ncode_increase ******************************************************
394
395    Doubles code area.
396
397 *******************************************************************************/
398
399 #if defined(ENABLE_INTRP)
400 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
401 {
402         u1 *oldncodebase;
403
404         /* save old ncodebase pointer */
405
406         oldncodebase = cd->ncodebase;
407
408         /* reallocate to new, doubled memory */
409
410         cd->ncodebase = DMREALLOC(cd->ncodebase,
411                                                           u1,
412                                                           cd->ncodesize,
413                                                           cd->ncodesize * 2);
414         cd->ncodesize *= 2;
415
416         /* return the new ncodeptr */
417
418         return (cd->ncodebase + (ncodeptr - oldncodebase));
419 }
420 #endif
421
422
423 /* codegen_add_branch_ref ******************************************************
424
425    Prepends an branch to the list.
426
427 *******************************************************************************/
428
429 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
430 {
431         branchref *br;
432         s4         branchmpc;
433
434         STATISTICS(count_branches_unresolved++);
435
436         /* calculate the mpc of the branch instruction */
437
438         branchmpc = cd->mcodeptr - cd->mcodebase;
439
440         br = DNEW(branchref);
441
442         br->branchmpc = branchmpc;
443         br->condition = condition;
444         br->reg       = reg;
445         br->options   = options;
446         br->next      = target->branchrefs;
447
448         target->branchrefs = br;
449 }
450
451
452 /* codegen_resolve_branchrefs **************************************************
453
454    Resolves and patches the branch references of a given basic block.
455
456 *******************************************************************************/
457
458 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
459 {
460         branchref *br;
461         u1        *mcodeptr;
462
463         /* Save the mcodeptr because in the branch emitting functions
464            we generate code somewhere inside already generated code,
465            but we're still in the actual code generation phase. */
466
467         mcodeptr = cd->mcodeptr;
468
469         /* just to make sure */
470
471         assert(bptr->mpc >= 0);
472
473         for (br = bptr->branchrefs; br != NULL; br = br->next) {
474                 /* temporary set the mcodeptr */
475
476                 cd->mcodeptr = cd->mcodebase + br->branchmpc;
477
478                 /* emit_bccz and emit_branch emit the correct code, even if we
479                    pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
480
481                 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
482         }
483
484         /* restore mcodeptr */
485
486         cd->mcodeptr = mcodeptr;
487 }
488
489
490 /* codegen_branch_label_add ****************************************************
491
492    Append an branch to the label-branch list.
493
494 *******************************************************************************/
495
496 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
497 {
498         list_t             *list;
499         branch_label_ref_t *br;
500         s4                  mpc;
501
502         /* get the label list */
503
504         list = cd->brancheslabel;
505         
506         /* calculate the current mpc */
507
508         mpc = cd->mcodeptr - cd->mcodebase;
509
510         br = DNEW(branch_label_ref_t);
511
512         br->mpc       = mpc;
513         br->label     = label;
514         br->condition = condition;
515         br->reg       = reg;
516         br->options   = options;
517
518         /* add the branch to the list */
519
520         list_add_last_unsynced(list, br);
521 }
522
523
524 /* codegen_add_patch_ref *******************************************************
525
526    Appends a new patcher reference to the list of patching positions.
527
528 *******************************************************************************/
529
530 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
531                                                    s4 disp)
532 {
533         patchref *pr;
534         s4        branchmpc;
535
536         branchmpc = cd->mcodeptr - cd->mcodebase;
537
538         pr = DNEW(patchref);
539
540         pr->branchpos = branchmpc;
541         pr->disp      = disp;
542         pr->patcher   = patcher;
543         pr->ref       = ref;
544
545 /*      list_add_first(cd->patchrefs, pr); */
546         pr->next      = cd->patchrefs;
547         cd->patchrefs = pr;
548
549         /* Generate NOPs for opt_shownops. */
550
551         if (opt_shownops)
552                 PATCHER_NOPS;
553
554 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__MIPS__) \
555  || defined(__SPARC_64__) || defined(__X86_64__))
556
557         /* On some architectures the patcher stub call instruction might
558            be longer than the actual instruction generated.  On this
559            architectures we store the last patcher call position and after
560            the basic block code generation is completed, we check the
561            range and maybe generate some nop's. */
562         /* The nops are generated in codegen_emit in each codegen */
563
564         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
565 #endif
566 }
567
568
569 /* codegen_critical_section_new ************************************************
570
571    Allocates a new critical-section reference and adds it to the
572    critical-section list.
573
574 *******************************************************************************/
575
576 #if defined(ENABLE_THREADS)
577 void codegen_critical_section_new(codegendata *cd)
578 {
579         list_t                 *list;
580         critical_section_ref_t *csr;
581         s4                      mpc;
582
583         /* get the critical section list */
584
585         list = cd->listcritical;
586         
587         /* calculate the current mpc */
588
589         mpc = cd->mcodeptr - cd->mcodebase;
590
591         csr = DNEW(critical_section_ref_t);
592
593         /* We only can set restart right now, as start and end are set by
594            the following, corresponding functions. */
595
596         csr->start   = -1;
597         csr->end     = -1;
598         csr->restart = mpc;
599
600         /* add the branch to the list */
601
602         list_add_last_unsynced(list, csr);
603 }
604 #endif
605
606
607 /* codegen_critical_section_start **********************************************
608
609    Set the start-point of the current critical section (which is the
610    last element of the list).
611
612 *******************************************************************************/
613
614 #if defined(ENABLE_THREADS)
615 void codegen_critical_section_start(codegendata *cd)
616 {
617         list_t                 *list;
618         critical_section_ref_t *csr;
619         s4                      mpc;
620
621         /* get the critical section list */
622
623         list = cd->listcritical;
624         
625         /* calculate the current mpc */
626
627         mpc = cd->mcodeptr - cd->mcodebase;
628
629         /* get the current critical section */
630
631         csr = list_last_unsynced(list);
632
633         /* set the start point */
634
635         assert(csr->start == -1);
636
637         csr->start = mpc;
638 }
639 #endif
640
641
642 /* codegen_critical_section_end ************************************************
643
644    Set the end-point of the current critical section (which is the
645    last element of the list).
646
647 *******************************************************************************/
648
649 #if defined(ENABLE_THREADS)
650 void codegen_critical_section_end(codegendata *cd)
651 {
652         list_t                 *list;
653         critical_section_ref_t *csr;
654         s4                      mpc;
655
656         /* get the critical section list */
657
658         list = cd->listcritical;
659         
660         /* calculate the current mpc */
661
662         mpc = cd->mcodeptr - cd->mcodebase;
663
664         /* get the current critical section */
665
666         csr = list_last_unsynced(list);
667
668         /* set the end point */
669
670         assert(csr->end == -1);
671
672         csr->end = mpc;
673 }
674 #endif
675
676
677 /* codegen_critical_section_finish *********************************************
678
679    Finish the critical sections, create the critical section nodes for
680    the AVL tree and insert them into the tree.
681
682 *******************************************************************************/
683
684 #if defined(ENABLE_THREADS)
685 static void codegen_critical_section_finish(jitdata *jd)
686 {
687         codeinfo    *code;
688         codegendata *cd;
689         list_t                  *list;
690         critical_section_ref_t  *csr;
691         critical_section_node_t *csn;
692
693         /* get required compiler data */
694
695         code = jd->code;
696         cd   = jd->cd;
697
698         /* get the critical section list */
699
700         list = cd->listcritical;
701
702         /* iterate over all critical sections */
703
704         for (csr = list_first_unsynced(list); csr != NULL;
705                  csr = list_next_unsynced(list, csr)) {
706                 /* check if all points are set */
707
708                 assert(csr->start   != -1);
709                 assert(csr->end     != -1);
710                 assert(csr->restart != -1);
711
712                 /* allocate tree node */
713
714                 csn = NEW(critical_section_node_t);
715
716                 csn->start   = code->entrypoint + csr->start;
717                 csn->end     = code->entrypoint + csr->end;
718                 csn->restart = code->entrypoint + csr->restart;
719
720                 /* insert into the tree */
721
722                 critical_section_register(csn);
723         }
724 }
725 #endif
726
727
728 /* methodtree_comparator *******************************************************
729
730    Comparator function used for the AVL tree of methods.
731
732    ARGUMENTS:
733       treenode....the node from the tree
734       node........the node to compare to the tree-node
735
736 *******************************************************************************/
737
738 static s4 methodtree_comparator(const void *treenode, const void *node)
739 {
740         methodtree_element *mte;
741         methodtree_element *mtepc;
742
743         mte   = (methodtree_element *) treenode;
744         mtepc = (methodtree_element *) node;
745
746         /* compare both startpc and endpc of pc, even if they have the same value,
747            otherwise the avl_probe sometimes thinks the element is already in the
748            tree */
749
750 #ifdef __S390__
751         /* On S390 addresses are 31 bit. Compare only 31 bits of value.
752          */
753 #       define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
754 #else
755 #       define ADDR_MASK(a) (a)
756 #endif
757
758         if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
759                 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
760                 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
761                 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
762                 return 0;
763
764         } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
765                 return -1;
766
767         } else {
768                 return 1;
769         }
770
771 #       undef ADDR_MASK
772 }
773
774
775 /* codegen_insertmethod ********************************************************
776
777    Insert the machine code range of a method into the AVL tree of methods.
778
779 *******************************************************************************/
780
781 void codegen_insertmethod(u1 *startpc, u1 *endpc)
782 {
783         methodtree_element *mte;
784
785         /* allocate new method entry */
786
787         mte = NEW(methodtree_element);
788
789         mte->startpc = startpc;
790         mte->endpc   = endpc;
791
792         /* this function does not return an error, but asserts for
793            duplicate entries */
794
795         avl_insert(methodtree, mte);
796 }
797
798
799 /* codegen_get_pv_from_pc ******************************************************
800
801    Find the PV for the given PC by searching in the AVL tree of
802    methods.
803
804 *******************************************************************************/
805
806 u1 *codegen_get_pv_from_pc(u1 *pc)
807 {
808         methodtree_element  mtepc;
809         methodtree_element *mte;
810
811         /* allocation of the search structure on the stack is much faster */
812
813         mtepc.startpc = pc;
814         mtepc.endpc   = pc;
815
816         mte = avl_find(methodtree, &mtepc);
817
818         if (mte == NULL) {
819                 /* No method was found.  Let's dump a stacktrace. */
820
821 #if defined(ENABLE_VMLOG)
822                 vmlog_cacao_signl("SIGSEGV");
823 #endif
824
825                 log_println("We received a SIGSEGV and tried to handle it, but we were");
826                 log_println("unable to find a Java method at:");
827                 log_println("");
828 #if SIZEOF_VOID_P == 8
829                 log_println("PC=0x%016lx", pc);
830 #else
831                 log_println("PC=0x%08x", pc);
832 #endif
833                 log_println("");
834                 assert(0);
835                 log_println("Dumping the current stacktrace:");
836
837 #if defined(ENABLE_THREADS)
838                 /* XXX michi: This should be available even without threads! */
839                 threads_print_stacktrace();
840 #endif
841
842                 vm_abort("Exiting...");
843         }
844
845         return mte->startpc;
846 }
847
848
849 /* codegen_get_pv_from_pc_nocheck **********************************************
850
851    Find the PV for the given PC by searching in the AVL tree of
852    methods.  This method does not check the return value and is used
853    by the profiler.
854
855 *******************************************************************************/
856
857 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
858 {
859         methodtree_element  mtepc;
860         methodtree_element *mte;
861
862         /* allocation of the search structure on the stack is much faster */
863
864         mtepc.startpc = pc;
865         mtepc.endpc   = pc;
866
867         mte = avl_find(methodtree, &mtepc);
868
869         if (mte == NULL)
870                 return NULL;
871         else
872                 return mte->startpc;
873 }
874
875
876 /* codegen_set_replacement_point_notrap ****************************************
877
878    Record the position of a non-trappable replacement point.
879
880 *******************************************************************************/
881
882 #if defined(ENABLE_REPLACEMENT)
883 #if !defined(NDEBUG)
884 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
885 #else
886 void codegen_set_replacement_point_notrap(codegendata *cd)
887 #endif
888 {
889         assert(cd->replacementpoint);
890         assert(cd->replacementpoint->type == type);
891         assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
892
893         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
894
895         cd->replacementpoint++;
896 }
897 #endif /* defined(ENABLE_REPLACEMENT) */
898
899
900 /* codegen_set_replacement_point ***********************************************
901
902    Record the position of a trappable replacement point.
903
904 *******************************************************************************/
905
906 #if defined(ENABLE_REPLACEMENT)
907 #if !defined(NDEBUG)
908 void codegen_set_replacement_point(codegendata *cd, s4 type)
909 #else
910 void codegen_set_replacement_point(codegendata *cd)
911 #endif
912 {
913         assert(cd->replacementpoint);
914         assert(cd->replacementpoint->type == type);
915         assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
916
917         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
918
919         cd->replacementpoint++;
920
921         /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
922
923         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
924 }
925 #endif /* defined(ENABLE_REPLACEMENT) */
926
927
928 /* codegen_finish **************************************************************
929
930    Finishes the code generation. A new memory, large enough for both
931    data and code, is allocated and data and code are copied together
932    to their final layout, unresolved jumps are resolved, ...
933
934 *******************************************************************************/
935
936 void codegen_finish(jitdata *jd)
937 {
938         codeinfo    *code;
939         codegendata *cd;
940         s4           mcodelen;
941 #if defined(ENABLE_INTRP)
942         s4           ncodelen;
943 #endif
944         s4           alignedmcodelen;
945         jumpref     *jr;
946         patchref_t  *pr;
947         u1          *epoint;
948         s4           alignedlen;
949
950         /* get required compiler data */
951
952         code = jd->code;
953         cd   = jd->cd;
954
955         /* prevent compiler warning */
956
957 #if defined(ENABLE_INTRP)
958         ncodelen = 0;
959 #endif
960
961         /* calculate the code length */
962
963         mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
964
965 #if defined(ENABLE_STATISTICS)
966         if (opt_stat) {
967                 count_code_len += mcodelen;
968                 count_data_len += cd->dseglen;
969         }
970 #endif
971
972         alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
973
974 #if defined(ENABLE_INTRP)
975         if (opt_intrp)
976                 ncodelen = cd->ncodeptr - cd->ncodebase;
977         else {
978                 ncodelen = 0; /* avoid compiler warning */
979         }
980 #endif
981
982         cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
983         alignedlen = alignedmcodelen + cd->dseglen;
984
985 #if defined(ENABLE_INTRP)
986         if (opt_intrp) {
987                 alignedlen += ncodelen;
988         }
989 #endif
990
991         /* allocate new memory */
992
993         code->mcodelength = mcodelen + cd->dseglen;
994         code->mcode       = CNEW(u1, alignedlen);
995
996         /* set the entrypoint of the method */
997         
998         assert(code->entrypoint == NULL);
999         code->entrypoint = epoint = (code->mcode + cd->dseglen);
1000
1001         /* fill the data segment (code->entrypoint must already be set!) */
1002
1003         dseg_finish(jd);
1004
1005         /* copy code to the new location */
1006
1007         MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1008
1009 #if defined(ENABLE_INTRP)
1010         /* relocate native dynamic superinstruction code (if any) */
1011
1012         if (opt_intrp) {
1013                 cd->mcodebase = code->entrypoint;
1014
1015                 if (ncodelen > 0) {
1016                         u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1017
1018                         MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1019
1020                         /* flush the instruction and data caches */
1021
1022                         md_cacheflush(ncodebase, ncodelen);
1023
1024                         /* set some cd variables for dynamic_super_rerwite */
1025
1026                         cd->ncodebase = ncodebase;
1027
1028                 } else {
1029                         cd->ncodebase = NULL;
1030                 }
1031
1032                 dynamic_super_rewrite(cd);
1033         }
1034 #endif
1035
1036         /* jump table resolving */
1037
1038         for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1039                 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1040                         (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1041
1042         /* line number table resolving */
1043         {
1044                 linenumberref *lr;
1045                 ptrint lrtlen = 0;
1046                 ptrint target;
1047
1048                 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1049                         lrtlen++;
1050                         target = lr->targetmpc;
1051                         /* if the entry contains an mcode pointer (normal case), resolve it */
1052                         /* (see doc/inlining_stacktrace.txt for details)                    */
1053                         if (lr->linenumber >= -2) {
1054                             target += (ptrint) epoint;
1055                         }
1056                         *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) = 
1057                                 (functionptr) target;
1058                 }
1059                 
1060                 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1061                         (functionptr) ((ptrint) epoint + cd->linenumbertab);
1062
1063                 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1064         }
1065
1066         /* patcher resolving */
1067
1068         pr = list_first_unsynced(code->patchers);
1069         while (pr) {
1070                 pr->mpc += (ptrint) epoint;
1071                 pr->datap = (ptrint) (pr->disp + epoint);
1072                 pr = list_next_unsynced(code->patchers, pr);
1073         }
1074
1075 #if defined(ENABLE_REPLACEMENT)
1076         /* replacement point resolving */
1077         {
1078                 int i;
1079                 rplpoint *rp;
1080
1081                 rp = code->rplpoints;
1082                 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1083                         rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1084                 }
1085         }
1086 #endif /* defined(ENABLE_REPLACEMENT) */
1087
1088         /* add method into methodtree to find the entrypoint */
1089
1090         codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1091
1092 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1093         /* resolve data segment references */
1094
1095         dseg_resolve_datareferences(jd);
1096 #endif
1097
1098 #if defined(ENABLE_THREADS)
1099         /* create cirtical sections */
1100
1101         codegen_critical_section_finish(jd);
1102 #endif
1103
1104         /* flush the instruction and data caches */
1105
1106         md_cacheflush(code->mcode, code->mcodelength);
1107 }
1108
1109
1110 /* codegen_generate_stub_compiler **********************************************
1111
1112    Wrapper for codegen_emit_stub_compiler.
1113
1114    Returns:
1115        pointer to the compiler stub code.
1116
1117 *******************************************************************************/
1118
1119 u1 *codegen_generate_stub_compiler(methodinfo *m)
1120 {
1121         jitdata     *jd;
1122         codegendata *cd;
1123         ptrint      *d;                     /* pointer to data memory             */
1124         u1          *c;                     /* pointer to code memory             */
1125         s4           dumpsize;
1126
1127         /* mark dump memory */
1128
1129         dumpsize = dump_size();
1130
1131         /* allocate required data structures */
1132
1133         jd = DNEW(jitdata);
1134
1135         jd->m     = m;
1136         jd->cd    = DNEW(codegendata);
1137         jd->flags = 0;
1138
1139         /* get required compiler data */
1140
1141         cd = jd->cd;
1142
1143         /* allocate code memory */
1144
1145         c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1146
1147         /* set pointers correctly */
1148
1149         d = (ptrint *) c;
1150
1151         cd->mcodebase = c;
1152
1153         c = c + 3 * SIZEOF_VOID_P;
1154         cd->mcodeptr = c;
1155
1156         /* NOTE: The codeinfo pointer is actually a pointer to the
1157            methodinfo (this fakes a codeinfo structure). */
1158
1159         d[0] = (ptrint) asm_call_jit_compiler;
1160         d[1] = (ptrint) m;
1161         d[2] = (ptrint) &d[1];                                    /* fake code->m */
1162
1163         /* call the emit function */
1164
1165         codegen_emit_stub_compiler(jd);
1166
1167 #if defined(ENABLE_STATISTICS)
1168         if (opt_stat)
1169                 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1170 #endif
1171
1172         /* flush caches */
1173
1174         md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1175
1176         /* release dump memory */
1177
1178         dump_release(dumpsize);
1179
1180         /* return native stub code */
1181
1182         return c;
1183 }
1184
1185
1186 /* codegen_generate_stub_builtin ***********************************************
1187
1188    Wrapper for codegen_emit_stub_builtin.
1189
1190    Returns:
1191        Pointer to the entrypoint of the stub.
1192
1193 *******************************************************************************/
1194
1195 void codegen_generate_stub_builtin(builtintable_entry *bte)
1196 {
1197         jitdata  *jd;
1198         codeinfo *code;
1199         s4        dumpsize;
1200
1201         /* mark dump memory */
1202
1203         dumpsize = dump_size();
1204
1205         jd = DNEW(jitdata);
1206
1207         jd->m     = NULL;
1208         jd->cd    = DNEW(codegendata);
1209         jd->rd    = NULL;
1210         jd->flags = 0;
1211
1212         /* Allocate codeinfo memory from the heap as we need to keep them. */
1213
1214         jd->code  = code_codeinfo_new(NULL);
1215
1216         /* get required compiler data */
1217
1218         code = jd->code;
1219
1220         /* setup code generation stuff */
1221
1222         codegen_setup(jd);
1223
1224         /* generate the code */
1225
1226 #if defined(ENABLE_JIT)
1227 # if defined(ENABLE_INTRP)
1228         if (!opt_intrp)
1229 # endif
1230                 codegen_emit_stub_builtin(jd, bte);
1231 #endif
1232
1233         /* reallocate the memory and finish the code generation */
1234
1235         codegen_finish(jd);
1236
1237         /* set the stub entry point in the builtin table */
1238
1239         bte->stub = code->entrypoint;
1240
1241 #if defined(ENABLE_STATISTICS)
1242         if (opt_stat)
1243                 size_stub_native += code->mcodelength;
1244 #endif
1245
1246         /* release memory */
1247
1248         dump_release(dumpsize);
1249 }
1250
1251
1252 /* codegen_generate_stub_native ************************************************
1253
1254    Wrapper for codegen_emit_stub_native.
1255
1256    Returns:
1257        the codeinfo representing the stub code.
1258
1259 *******************************************************************************/
1260
1261 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1262 {
1263         jitdata     *jd;
1264         codeinfo    *code;
1265         s4           dumpsize;
1266         methoddesc  *md;
1267         methoddesc  *nmd;       
1268         s4           nativeparams;
1269
1270         /* mark dump memory */
1271
1272         dumpsize = dump_size();
1273
1274         jd = DNEW(jitdata);
1275
1276         jd->m     = m;
1277         jd->cd    = DNEW(codegendata);
1278         jd->rd    = DNEW(registerdata);
1279         jd->flags = 0;
1280
1281         /* Allocate codeinfo memory from the heap as we need to keep them. */
1282
1283         jd->code  = code_codeinfo_new(m); /* XXX check allocation */
1284
1285         /* get required compiler data */
1286
1287         code = jd->code;
1288
1289         /* set the flags for the current JIT run */
1290
1291 #if defined(ENABLE_PROFILING)
1292         if (opt_prof)
1293                 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1294 #endif
1295
1296         if (opt_verbosecall)
1297                 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1298
1299         /* setup code generation stuff */
1300
1301 #if defined(ENABLE_JIT)
1302 # if defined(ENABLE_INTRP)
1303         if (!opt_intrp)
1304 # endif
1305                 reg_setup(jd);
1306 #endif
1307
1308         codegen_setup(jd);
1309
1310         /* create new method descriptor with additional native parameters */
1311
1312         md = m->parseddesc;
1313         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1314         
1315         nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1316                                                            md->paramcount * sizeof(typedesc) +
1317                                                            nativeparams * sizeof(typedesc));
1318
1319         nmd->paramcount = md->paramcount + nativeparams;
1320
1321         nmd->params = DMNEW(paramdesc, nmd->paramcount);
1322
1323         nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer            */
1324
1325         if (m->flags & ACC_STATIC)
1326                 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer              */
1327
1328         MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1329                   md->paramcount);
1330
1331 #if defined(ENABLE_JIT)
1332 # if defined(ENABLE_INTRP)
1333         if (!opt_intrp)
1334 # endif
1335                 /* pre-allocate the arguments for the native ABI */
1336
1337                 md_param_alloc_native(nmd);
1338 #endif
1339
1340         /* generate the code */
1341
1342 #if defined(ENABLE_JIT)
1343 # if defined(ENABLE_INTRP)
1344         if (opt_intrp)
1345                 intrp_createnativestub(f, jd, nmd);
1346         else
1347 # endif
1348                 codegen_emit_stub_native(jd, nmd, f);
1349 #else
1350         intrp_createnativestub(f, jd, nmd);
1351 #endif
1352
1353         /* reallocate the memory and finish the code generation */
1354
1355         codegen_finish(jd);
1356
1357 #if defined(ENABLE_STATISTICS)
1358         /* must be done after codegen_finish() */
1359
1360         if (opt_stat)
1361                 size_stub_native += code->mcodelength;
1362 #endif
1363
1364 #if !defined(NDEBUG)
1365         /* disassemble native stub */
1366
1367         if (opt_shownativestub) {
1368 #if defined(ENABLE_DEBUG_FILTER)
1369                 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1370 #endif
1371                 {
1372 #if defined(ENABLE_DISASSEMBLER)
1373                         codegen_disassemble_nativestub(m,
1374                                                                                    (u1 *) (ptrint) code->entrypoint,
1375                                                                                    (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1376 #endif
1377
1378                         /* show data segment */
1379
1380                         if (opt_showddatasegment)
1381                                 dseg_display(jd);
1382                 }
1383         }
1384 #endif /* !defined(NDEBUG) */
1385
1386         /* release memory */
1387
1388         dump_release(dumpsize);
1389
1390         /* return native stub code */
1391
1392         return code;
1393 }
1394
1395
1396 /* codegen_disassemble_nativestub **********************************************
1397
1398    Disassembles the generated native stub.
1399
1400 *******************************************************************************/
1401
1402 #if defined(ENABLE_DISASSEMBLER)
1403 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1404 {
1405         printf("Native stub: ");
1406         utf_fprint_printable_ascii_classname(stdout, m->class->name);
1407         printf(".");
1408         utf_fprint_printable_ascii(stdout, m->name);
1409         utf_fprint_printable_ascii(stdout, m->descriptor);
1410         printf("\n\nLength: %d\n\n", (s4) (end - start));
1411
1412         DISASSEMBLE(start, end);
1413 }
1414 #endif
1415
1416
1417 /* codegen_stub_builtin_enter **************************************************
1418
1419    Prepares the stuff required for a builtin function call:
1420
1421    - adds a stackframe info structure to the chain, for stacktraces
1422
1423    The layout of the builtin stub stackframe should look like this:
1424
1425    +---------------------------+ <- SP (of parent Java function)
1426    | return address            |
1427    +---------------------------+
1428    |                           |
1429    | stackframe info structure |
1430    |                           |
1431    +---------------------------+
1432    |                           |
1433    | arguments (if any)        |
1434    |                           |
1435    +---------------------------+ <- SP (native stub)
1436
1437 *******************************************************************************/
1438
1439 void codegen_stub_builtin_enter(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1440 {
1441         stackframeinfo *sfi;
1442
1443         /* get data structures from stack */
1444
1445         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1446
1447         /* add a stackframeinfo to the chain */
1448
1449         stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1450
1451 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1452         /* set the native world flag */
1453
1454         THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1455 #endif
1456 }
1457
1458
1459 /* codegen_stub_builtin_exit ***************************************************
1460
1461    Removes the stuff required for a builtin function call.
1462
1463 *******************************************************************************/
1464
1465 void codegen_stub_builtin_exit(u1 *datasp)
1466 {
1467         stackframeinfo     *sfi;
1468         stackframeinfo    **psfi;
1469
1470         /* get data structures from stack */
1471
1472         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1473
1474         /* remove current stackframeinfo from chain */
1475
1476         psfi = &STACKFRAMEINFO;
1477
1478         *psfi = sfi->prev;
1479
1480 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1481         /* clear the native world flag */
1482
1483         THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1484 #endif
1485 }
1486
1487
1488 /* codegen_start_native_call ***************************************************
1489
1490    Prepares the stuff required for a native (JNI) function call:
1491
1492    - adds a stackframe info structure to the chain, for stacktraces
1493    - prepares the local references table on the stack
1494
1495    The layout of the native stub stackframe should look like this:
1496
1497    +---------------------------+ <- SP (of parent Java function)
1498    | return address            |
1499    +---------------------------+
1500    |                           |
1501    | stackframe info structure |
1502    |                           |
1503    +---------------------------+
1504    |                           |
1505    | local references table    |
1506    |                           |
1507    +---------------------------+
1508    |                           |
1509    | arguments (if any)        |
1510    |                           |
1511    +---------------------------+ <- SP (native stub)
1512
1513 *******************************************************************************/
1514
1515 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1516 {
1517         stackframeinfo *sfi;
1518         localref_table *lrt;
1519
1520         STATISTICS(count_calls_java_to_native++);
1521
1522         /* get data structures from stack */
1523
1524         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1525         lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
1526                                                           sizeof(localref_table));
1527
1528         /* add a stackframeinfo to the chain */
1529
1530         stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1531
1532 #if defined(ENABLE_JNI)
1533         /* add current JNI local references table to this thread */
1534
1535         localref_table_add(lrt);
1536 #endif
1537
1538 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1539         /* set the native world flag */
1540
1541         THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1542 #endif
1543 }
1544
1545
1546 /* codegen_finish_native_call **************************************************
1547
1548    Removes the stuff required for a native (JNI) function call.
1549    Additionally it checks for an exceptions and in case, get the
1550    exception object and clear the pointer.
1551
1552 *******************************************************************************/
1553
1554 java_object_t *codegen_finish_native_call(u1 *datasp)
1555 {
1556         stackframeinfo  *sfi;
1557         stackframeinfo **psfi;
1558         java_handle_t   *e;
1559
1560         /* get data structures from stack */
1561
1562         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1563
1564 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1565         /* clear the native world flag */
1566
1567         THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1568 #endif
1569
1570         /* remove current stackframeinfo from chain */
1571
1572         psfi = &STACKFRAMEINFO;
1573
1574         *psfi = sfi->prev;
1575
1576 #if defined(ENABLE_JNI)
1577         /* release JNI local references table for this thread */
1578
1579         localref_frame_pop_all();
1580         localref_table_remove();
1581 #endif
1582
1583         /* get the exception and return it */
1584
1585         e = exceptions_get_and_clear_exception();
1586
1587         return e;
1588 }
1589
1590
1591 /* removecompilerstub **********************************************************
1592
1593    Deletes a compilerstub from memory (simply by freeing it).
1594
1595 *******************************************************************************/
1596
1597 void removecompilerstub(u1 *stub)
1598 {
1599         /* pass size 1 to keep the intern function happy */
1600
1601         CFREE((void *) stub, 1);
1602 }
1603
1604
1605 /* removenativestub ************************************************************
1606
1607    Removes a previously created native-stub from memory.
1608     
1609 *******************************************************************************/
1610
1611 void removenativestub(u1 *stub)
1612 {
1613         /* pass size 1 to keep the intern function happy */
1614
1615         CFREE((void *) stub, 1);
1616 }
1617
1618
1619 /* codegen_reg_of_var **********************************************************
1620
1621    This function determines a register, to which the result of an
1622    operation should go, when it is ultimatively intended to store the
1623    result in pseudoregister v.  If v is assigned to an actual
1624    register, this register will be returned.  Otherwise (when v is
1625    spilled) this function returns tempregnum.  If not already done,
1626    regoff and flags are set in the stack location.
1627        
1628 *******************************************************************************/
1629
1630 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1631 {
1632
1633 #if 0
1634         /* Do we have to generate a conditional move?  Yes, then always
1635            return the temporary register.  The real register is identified
1636            during the store. */
1637
1638         if (opcode & ICMD_CONDITION_MASK)
1639                 return tempregnum;
1640 #endif
1641
1642         if (!(v->flags & INMEMORY))
1643                 return v->vv.regoff;
1644
1645         return tempregnum;
1646 }
1647
1648
1649 /* codegen_reg_of_dst **********************************************************
1650
1651    This function determines a register, to which the result of an
1652    operation should go, when it is ultimatively intended to store the
1653    result in iptr->dst.var.  If dst.var is assigned to an actual
1654    register, this register will be returned.  Otherwise (when it is
1655    spilled) this function returns tempregnum.  If not already done,
1656    regoff and flags are set in the stack location.
1657        
1658 *******************************************************************************/
1659
1660 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1661 {
1662         return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1663 }
1664
1665
1666 /* codegen_emit_phi_moves ****************************************************
1667
1668    Emits phi moves at the end of the basicblock.
1669
1670 *******************************************************************************/
1671
1672 #if defined(ENABLE_SSA)
1673 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1674 {
1675         int lt_d,lt_s,i;
1676         lsradata *ls;
1677         codegendata *cd;
1678         varinfo *s, *d;
1679         instruction tmp_i;
1680
1681         cd = jd->cd;
1682         ls = jd->ls;
1683
1684         MCODECHECK(512);
1685
1686         /* Moves from phi functions with highest indices have to be */
1687         /* inserted first, since this is the order as is used for   */
1688         /* conflict resolution */
1689
1690         for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1691                 lt_d = ls->phi_moves[bptr->nr][i][0];
1692                 lt_s = ls->phi_moves[bptr->nr][i][1];
1693 #if defined(SSA_DEBUG_VERBOSE)
1694                 if (compileverbose)
1695                         printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1696 #endif
1697                 if (lt_s == UNUSED) {
1698 #if defined(SSA_DEBUG_VERBOSE)
1699                 if (compileverbose)
1700                         printf(" ... not processed \n");
1701 #endif
1702                         continue;
1703                 }
1704                         
1705                 d = VAR(ls->lifetime[lt_d].v_index);
1706                 s = VAR(ls->lifetime[lt_s].v_index);
1707                 
1708
1709                 if (d->type == -1) {
1710 #if defined(SSA_DEBUG_VERBOSE)
1711                         if (compileverbose)
1712                                 printf("...returning - phi lifetimes where joined\n");
1713 #endif
1714                         return;
1715                 }
1716
1717                 if (s->type == -1) {
1718 #if defined(SSA_DEBUG_VERBOSE)
1719                         if (compileverbose)
1720                                 printf("...returning - phi lifetimes where joined\n");
1721 #endif
1722                         return;
1723                 }
1724
1725                 tmp_i.opc = 0;
1726                 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1727                 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1728                 emit_copy(jd, &tmp_i);
1729
1730 #if defined(SSA_DEBUG_VERBOSE)
1731                 if (compileverbose) {
1732                         if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1733                                 /* mem -> mem */
1734                                 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1735                         }
1736                         else if (IS_INMEMORY(s->flags)) {
1737                                 /* mem -> reg */
1738                                 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1739                         }
1740                         else if (IS_INMEMORY(d->flags)) {
1741                                 /* reg -> mem */
1742                                 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1743                         }
1744                         else {
1745                                 /* reg -> reg */
1746                                 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1747                         }
1748                         printf("\n");
1749                 }
1750 #endif /* defined(SSA_DEBUG_VERBOSE) */
1751         }
1752 }
1753 #endif /* defined(ENABLE_SSA) */
1754
1755
1756
1757 /*
1758  * These are local overrides for various environment variables in Emacs.
1759  * Please do not remove this and leave it at the end of the file, where
1760  * Emacs will automagically detect them.
1761  * ---------------------------------------------------------------------
1762  * Local variables:
1763  * mode: c
1764  * indent-tabs-mode: t
1765  * c-basic-offset: 4
1766  * tab-width: 4
1767  * End:
1768  * vim:noexpandtab:sw=4:ts=4:
1769  */