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