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