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