* src/vm/jit/jit.c: Moved to .cpp.
[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/llni.h"
61 #include "native/localref.h"
62 #include "native/native.h"
63
64 #include "threads/thread.hpp"
65
66 #include "vm/builtin.h"
67 #include "vm/exceptions.hpp"
68 #include "vm/method.h"
69 #include "vm/options.h"
70 #include "vm/string.hpp"
71
72 # include "vm/statistics.h"
73
74
75 #include "vm/jit/abi.h"
76 #include "vm/jit/asmpart.h"
77 #include "vm/jit/code.h"
78 #include "vm/jit/codegen-common.h"
79
80 #if defined(ENABLE_DISASSEMBLER)
81 # include "vm/jit/disass.h"
82 #endif
83
84 #include "vm/jit/dseg.h"
85 #include "vm/jit/emit-common.h"
86 #include "vm/jit/jit.hpp"
87 #include "vm/jit/linenumbertable.h"
88 #include "vm/jit/methodheader.h"
89 #include "vm/jit/methodtree.h"
90 #include "vm/jit/patcher-common.h"
91 #include "vm/jit/replace.h"
92 #if defined(ENABLE_SSA)
93 # include "vm/jit/optimizing/lsra.h"
94 # include "vm/jit/optimizing/ssa.h"
95 #endif
96 #include "vm/jit/stacktrace.hpp"
97 #include "vm/jit/trace.hpp"
98
99 #if defined(ENABLE_INTRP)
100 #include "vm/jit/intrp/intrp.h"
101 #endif
102
103 #if defined(ENABLE_VMLOG)
104 #include <vmlog_cacao.h>
105 #endif
106
107 #include "show.h"
108
109
110 /* codegen_init ****************************************************************
111
112    TODO
113
114 *******************************************************************************/
115
116 void codegen_init(void)
117 {
118 }
119
120
121 /* codegen_setup ***************************************************************
122
123    Allocates and initialises code area, data area and references.
124
125 *******************************************************************************/
126
127 void codegen_setup(jitdata *jd)
128 {
129         methodinfo  *m;
130         codegendata *cd;
131
132         /* get required compiler data */
133
134         m  = jd->m;
135         cd = jd->cd;
136
137         /* initialize members */
138
139         cd->flags        = 0;
140
141         cd->mcodebase    = DMNEW(u1, MCODEINITSIZE);
142         cd->mcodeend     = cd->mcodebase + MCODEINITSIZE;
143         cd->mcodesize    = MCODEINITSIZE;
144
145         /* initialize mcode variables */
146
147         cd->mcodeptr     = cd->mcodebase;
148         cd->lastmcodeptr = cd->mcodebase;
149
150 #if defined(ENABLE_INTRP)
151         /* native dynamic superinstructions variables */
152
153         if (opt_intrp) {
154                 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
155                 cd->ncodesize = NCODEINITSIZE;
156
157                 /* initialize ncode variables */
158         
159                 cd->ncodeptr = cd->ncodebase;
160
161                 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
162                 cd->superstarts = NULL;
163         }
164 #endif
165
166         cd->dseg           = NULL;
167         cd->dseglen        = 0;
168
169         cd->jumpreferences = NULL;
170
171 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
172         cd->datareferences = NULL;
173 #endif
174
175         cd->brancheslabel  = list_create_dump(OFFSET(branch_label_ref_t, linkage));
176         cd->linenumbers    = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
177 }
178
179
180 /* codegen_reset ***************************************************************
181
182    Resets the codegen data structure so we can recompile the method.
183
184 *******************************************************************************/
185
186 static void codegen_reset(jitdata *jd)
187 {
188         codeinfo    *code;
189         codegendata *cd;
190         basicblock  *bptr;
191
192         /* get required compiler data */
193
194         code = jd->code;
195         cd   = jd->cd;
196
197         /* reset error flag */
198
199         cd->flags          &= ~CODEGENDATA_FLAG_ERROR;
200
201         /* reset some members, we reuse the code memory already allocated
202            as this should have almost the correct size */
203
204         cd->mcodeptr        = cd->mcodebase;
205         cd->lastmcodeptr    = cd->mcodebase;
206
207         cd->dseg            = NULL;
208         cd->dseglen         = 0;
209
210         cd->jumpreferences  = NULL;
211
212 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
213         cd->datareferences  = NULL;
214 #endif
215
216         cd->brancheslabel   = list_create_dump(OFFSET(branch_label_ref_t, linkage));
217         cd->linenumbers     = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
218         
219         /* We need to clear the mpc and the branch references from all
220            basic blocks as they will definitely change. */
221
222         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
223                 bptr->mpc        = -1;
224                 bptr->branchrefs = NULL;
225         }
226
227         /* We need to clear all the patcher references from the codeinfo
228            since they all will be regenerated */
229
230         patcher_list_reset(code);
231
232 #if defined(ENABLE_REPLACEMENT)
233         code->rplpoints     = NULL;
234         code->rplpointcount = 0;
235         code->regalloc      = NULL;
236         code->regalloccount = 0;
237         code->globalcount   = 0;
238 #endif
239 }
240
241
242 /* codegen_generate ************************************************************
243
244    Generates the code for the currently compiled method.
245
246 *******************************************************************************/
247
248 bool codegen_generate(jitdata *jd)
249 {
250         codegendata *cd;
251
252         /* get required compiler data */
253
254         cd = jd->cd;
255
256         /* call the machine-dependent code generation function */
257
258         if (!codegen_emit(jd))
259                 return false;
260
261         /* check for an error */
262
263         if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
264                 /* check for long-branches flag, if it is set we recompile the
265                    method */
266
267 #if !defined(NDEBUG)
268         if (compileverbose)
269             log_message_method("Re-generating code: ", jd->m);
270 #endif
271
272                 /* XXX maybe we should tag long-branches-methods for recompilation */
273
274                 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
275                         /* we have to reset the codegendata structure first */
276
277                         codegen_reset(jd);
278
279                         /* and restart the compiler run */
280
281                         if (!codegen_emit(jd))
282                                 return false;
283                 }
284                 else {
285                         vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
286                 }
287
288 #if !defined(NDEBUG)
289         if (compileverbose)
290             log_message_method("Re-generating code done: ", jd->m);
291 #endif
292         }
293
294         /* reallocate the memory and finish the code generation */
295
296         codegen_finish(jd);
297
298         /* everything's ok */
299
300         return true;
301 }
302
303
304 /* codegen_close ***************************************************************
305
306    TODO
307
308 *******************************************************************************/
309
310 void codegen_close(void)
311 {
312         /* TODO: release avl tree on i386 and x86_64 */
313 }
314
315
316 /* codegen_increase ************************************************************
317
318    Doubles code area.
319
320 *******************************************************************************/
321
322 void codegen_increase(codegendata *cd)
323 {
324         u1 *oldmcodebase;
325
326         /* save old mcodebase pointer */
327
328         oldmcodebase = cd->mcodebase;
329
330         /* reallocate to new, doubled memory */
331
332         cd->mcodebase = DMREALLOC(cd->mcodebase,
333                                                           u1,
334                                                           cd->mcodesize,
335                                                           cd->mcodesize * 2);
336         cd->mcodesize *= 2;
337         cd->mcodeend   = cd->mcodebase + cd->mcodesize;
338
339         /* set new mcodeptr */
340
341         cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
342
343 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
344  || defined(__SPARC_64__)
345         /* adjust the pointer to the last patcher position */
346
347         if (cd->lastmcodeptr != NULL)
348                 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
349 #endif
350 }
351
352
353 /* codegen_ncode_increase ******************************************************
354
355    Doubles code area.
356
357 *******************************************************************************/
358
359 #if defined(ENABLE_INTRP)
360 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
361 {
362         u1 *oldncodebase;
363
364         /* save old ncodebase pointer */
365
366         oldncodebase = cd->ncodebase;
367
368         /* reallocate to new, doubled memory */
369
370         cd->ncodebase = DMREALLOC(cd->ncodebase,
371                                                           u1,
372                                                           cd->ncodesize,
373                                                           cd->ncodesize * 2);
374         cd->ncodesize *= 2;
375
376         /* return the new ncodeptr */
377
378         return (cd->ncodebase + (ncodeptr - oldncodebase));
379 }
380 #endif
381
382
383 /* codegen_add_branch_ref ******************************************************
384
385    Prepends an branch to the list.
386
387 *******************************************************************************/
388
389 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
390 {
391         branchref *br;
392         s4         branchmpc;
393
394         STATISTICS(count_branches_unresolved++);
395
396         /* calculate the mpc of the branch instruction */
397
398         branchmpc = cd->mcodeptr - cd->mcodebase;
399
400         br = DNEW(branchref);
401
402         br->branchmpc = branchmpc;
403         br->condition = condition;
404         br->reg       = reg;
405         br->options   = options;
406         br->next      = target->branchrefs;
407
408         target->branchrefs = br;
409 }
410
411
412 /* codegen_resolve_branchrefs **************************************************
413
414    Resolves and patches the branch references of a given basic block.
415
416 *******************************************************************************/
417
418 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
419 {
420         branchref *br;
421         u1        *mcodeptr;
422
423         /* Save the mcodeptr because in the branch emitting functions
424            we generate code somewhere inside already generated code,
425            but we're still in the actual code generation phase. */
426
427         mcodeptr = cd->mcodeptr;
428
429         /* just to make sure */
430
431         assert(bptr->mpc >= 0);
432
433         for (br = bptr->branchrefs; br != NULL; br = br->next) {
434                 /* temporary set the mcodeptr */
435
436                 cd->mcodeptr = cd->mcodebase + br->branchmpc;
437
438                 /* emit_bccz and emit_branch emit the correct code, even if we
439                    pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
440
441                 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
442         }
443
444         /* restore mcodeptr */
445
446         cd->mcodeptr = mcodeptr;
447 }
448
449
450 /* codegen_branch_label_add ****************************************************
451
452    Append an branch to the label-branch list.
453
454 *******************************************************************************/
455
456 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
457 {
458         list_t             *l;
459         branch_label_ref_t *br;
460         s4                  mpc;
461
462         /* Get the label list. */
463
464         l = cd->brancheslabel;
465         
466         /* calculate the current mpc */
467
468         mpc = cd->mcodeptr - cd->mcodebase;
469
470         br = DNEW(branch_label_ref_t);
471
472         br->mpc       = mpc;
473         br->label     = label;
474         br->condition = condition;
475         br->reg       = reg;
476         br->options   = options;
477
478         /* Add the branch to the list. */
479
480         list_add_last(l, br);
481 }
482
483
484 /* codegen_set_replacement_point_notrap ****************************************
485
486    Record the position of a non-trappable replacement point.
487
488 *******************************************************************************/
489
490 #if defined(ENABLE_REPLACEMENT)
491 #if !defined(NDEBUG)
492 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
493 #else
494 void codegen_set_replacement_point_notrap(codegendata *cd)
495 #endif
496 {
497         assert(cd->replacementpoint);
498         assert(cd->replacementpoint->type == type);
499         assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
500
501         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
502
503         cd->replacementpoint++;
504 }
505 #endif /* defined(ENABLE_REPLACEMENT) */
506
507
508 /* codegen_set_replacement_point ***********************************************
509
510    Record the position of a trappable replacement point.
511
512 *******************************************************************************/
513
514 #if defined(ENABLE_REPLACEMENT)
515 #if !defined(NDEBUG)
516 void codegen_set_replacement_point(codegendata *cd, s4 type)
517 #else
518 void codegen_set_replacement_point(codegendata *cd)
519 #endif
520 {
521         assert(cd->replacementpoint);
522         assert(cd->replacementpoint->type == type);
523         assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
524
525         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
526
527         cd->replacementpoint++;
528
529 #if !defined(NDEBUG)
530         /* XXX actually we should use an own REPLACEMENT_NOPS here! */
531         if (opt_TestReplacement)
532                 PATCHER_NOPS;
533 #endif
534
535         /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
536
537         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
538 }
539 #endif /* defined(ENABLE_REPLACEMENT) */
540
541
542 /* codegen_finish **************************************************************
543
544    Finishes the code generation. A new memory, large enough for both
545    data and code, is allocated and data and code are copied together
546    to their final layout, unresolved jumps are resolved, ...
547
548 *******************************************************************************/
549
550 void codegen_finish(jitdata *jd)
551 {
552         codeinfo    *code;
553         codegendata *cd;
554         s4           mcodelen;
555 #if defined(ENABLE_INTRP)
556         s4           ncodelen;
557 #endif
558         s4           alignedmcodelen;
559         jumpref     *jr;
560         u1          *epoint;
561         s4           alignedlen;
562
563         /* get required compiler data */
564
565         code = jd->code;
566         cd   = jd->cd;
567
568         /* prevent compiler warning */
569
570 #if defined(ENABLE_INTRP)
571         ncodelen = 0;
572 #endif
573
574         /* calculate the code length */
575
576         mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
577
578 #if defined(ENABLE_STATISTICS)
579         if (opt_stat) {
580                 count_code_len += mcodelen;
581                 count_data_len += cd->dseglen;
582         }
583 #endif
584
585         alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
586
587 #if defined(ENABLE_INTRP)
588         if (opt_intrp)
589                 ncodelen = cd->ncodeptr - cd->ncodebase;
590         else {
591                 ncodelen = 0; /* avoid compiler warning */
592         }
593 #endif
594
595         cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
596         alignedlen = alignedmcodelen + cd->dseglen;
597
598 #if defined(ENABLE_INTRP)
599         if (opt_intrp) {
600                 alignedlen += ncodelen;
601         }
602 #endif
603
604         /* allocate new memory */
605
606         code->mcodelength = mcodelen + cd->dseglen;
607         code->mcode       = CNEW(u1, alignedlen);
608
609         /* set the entrypoint of the method */
610         
611         assert(code->entrypoint == NULL);
612         code->entrypoint = epoint = (code->mcode + cd->dseglen);
613
614         /* fill the data segment (code->entrypoint must already be set!) */
615
616         dseg_finish(jd);
617
618         /* copy code to the new location */
619
620         MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
621
622 #if defined(ENABLE_INTRP)
623         /* relocate native dynamic superinstruction code (if any) */
624
625         if (opt_intrp) {
626                 cd->mcodebase = code->entrypoint;
627
628                 if (ncodelen > 0) {
629                         u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
630
631                         MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
632
633                         /* flush the instruction and data caches */
634
635                         md_cacheflush(ncodebase, ncodelen);
636
637                         /* set some cd variables for dynamic_super_rerwite */
638
639                         cd->ncodebase = ncodebase;
640
641                 } else {
642                         cd->ncodebase = NULL;
643                 }
644
645                 dynamic_super_rewrite(cd);
646         }
647 #endif
648
649         /* Create the exception table. */
650
651         exceptiontable_create(jd);
652
653         /* Create the linenumber table. */
654
655         linenumbertable_create(jd);
656
657         /* jump table resolving */
658
659         for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
660                 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
661                         (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
662
663         /* patcher resolving */
664
665         patcher_resolve(jd);
666
667 #if defined(ENABLE_REPLACEMENT)
668         /* replacement point resolving */
669         {
670                 int i;
671                 rplpoint *rp;
672
673                 rp = code->rplpoints;
674                 for (i=0; i<code->rplpointcount; ++i, ++rp) {
675                         rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
676                 }
677         }
678 #endif /* defined(ENABLE_REPLACEMENT) */
679
680         /* Insert method into methodtree to find the entrypoint. */
681
682         methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
683
684 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
685         /* resolve data segment references */
686
687         dseg_resolve_datareferences(jd);
688 #endif
689
690         /* flush the instruction and data caches */
691
692         md_cacheflush(code->mcode, code->mcodelength);
693 }
694
695
696 /* codegen_start_native_call ***************************************************
697
698    Prepares the stuff required for a native (JNI) function call:
699
700    - adds a stackframe info structure to the chain, for stacktraces
701    - prepares the local references table on the stack
702
703    The layout of the native stub stackframe should look like this:
704
705    +---------------------------+ <- java SP (of parent Java function)
706    | return address            |
707    +---------------------------+ <- data SP
708    |                           |
709    | stackframe info structure |
710    |                           |
711    +---------------------------+
712    |                           |
713    | local references table    |
714    |                           |
715    +---------------------------+
716    |                           |
717    | saved registers (if any)  |
718    |                           |
719    +---------------------------+
720    |                           |
721    | arguments (if any)        |
722    |                           |
723    +---------------------------+ <- current SP (native stub)
724
725 *******************************************************************************/
726
727 java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
728 {
729         stackframeinfo_t *sfi;
730         localref_table   *lrt;
731         methodinfo       *m;
732         int32_t           framesize;
733
734         uint8_t  *datasp;
735         uint8_t  *javasp;
736         uint64_t *arg_regs;
737         uint64_t *arg_stack;
738
739         STATISTICS(count_calls_java_to_native++);
740
741         /* Get the methodinfo. */
742
743         m = code_get_methodinfo_for_pv(pv);
744
745         assert(m);
746
747         framesize = *((int32_t *) (pv + FrameSize));
748
749         assert(framesize >= sizeof(stackframeinfo_t) + sizeof(localref_table));
750
751         /* calculate needed values */
752
753 #if defined(__ALPHA__) || defined(__ARM__)
754         datasp    = sp + framesize - SIZEOF_VOID_P;
755         javasp    = sp + framesize;
756         arg_regs  = (uint64_t *) sp;
757         arg_stack = (uint64_t *) javasp;
758 #elif defined(__MIPS__)
759         /* MIPS always uses 8 bytes to store the RA */
760         datasp    = sp + framesize - 8;
761         javasp    = sp + framesize;
762 #elif defined(__S390__)
763         datasp    = sp + framesize - 8;
764         javasp    = sp + framesize;
765         arg_regs  = (uint64_t *) (sp + 96);
766         arg_stack = (uint64_t *) javasp;
767 #elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
768         datasp    = sp + framesize;
769         javasp    = sp + framesize + SIZEOF_VOID_P;
770         arg_regs  = (uint64_t *) sp;
771         arg_stack = (uint64_t *) javasp;
772 #elif defined(__POWERPC__)
773         datasp    = sp + framesize;
774         javasp    = sp + framesize;
775         arg_regs  = (uint64_t *) (sp + LA_SIZE + 4 * SIZEOF_VOID_P);
776         arg_stack = (uint64_t *) javasp;
777 #elif defined(__POWERPC64__)
778         datasp    = sp + framesize;
779         javasp    = sp + framesize;
780         arg_regs  = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
781         arg_stack = (uint64_t *) javasp;
782 #else
783         /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
784         /* XXX maybe we need to pass the RA as argument there */
785         vm_abort("codegen_start_native_call: unsupported architecture");
786 #endif
787
788         /* get data structures from stack */
789
790         sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
791         lrt = (localref_table *)   (datasp - sizeof(stackframeinfo_t) - 
792                                                                 sizeof(localref_table));
793
794 #if defined(ENABLE_JNI)
795         /* add current JNI local references table to this thread */
796
797         localref_table_add(lrt);
798 #endif
799
800 #if !defined(NDEBUG)
801 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
802         /* print the call-trace if necesarry */
803         /* BEFORE: filling the local reference table */
804
805         if (opt_TraceJavaCalls)
806                 trace_java_call_enter(m, arg_regs, arg_stack);
807 # endif
808 #endif
809
810 #if defined(ENABLE_HANDLES)
811         /* place all references into the local reference table */
812         /* BEFORE: creating stackframeinfo */
813
814         localref_native_enter(m, arg_regs, arg_stack);
815 #endif
816
817         /* Add a stackframeinfo for this native method.  We don't have RA
818            and XPC here.  These are determined in
819            stacktrace_stackframeinfo_add. */
820
821         stacktrace_stackframeinfo_add(sfi, pv, sp, NULL, NULL);
822
823         /* Return a wrapped classinfo for static methods. */
824
825         if (m->flags & ACC_STATIC)
826                 return (java_handle_t *) LLNI_classinfo_wrap(m->clazz);
827         else
828                 return NULL;
829 }
830
831
832 /* codegen_finish_native_call **************************************************
833
834    Removes the stuff required for a native (JNI) function call.
835    Additionally it checks for an exceptions and in case, get the
836    exception object and clear the pointer.
837
838 *******************************************************************************/
839
840 java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
841 {
842         stackframeinfo_t *sfi;
843         java_handle_t    *e;
844         java_object_t    *o;
845         codeinfo         *code;
846         methodinfo       *m;
847         int32_t           framesize;
848
849         uint8_t  *datasp;
850         uint64_t *ret_regs;
851
852         /* get information from method header */
853
854         code = code_get_codeinfo_for_pv(pv);
855
856         framesize = *((int32_t *) (pv + FrameSize));
857
858         assert(code);
859
860         /* get the methodinfo */
861
862         m = code->m;
863         assert(m);
864
865         /* calculate needed values */
866
867 #if defined(__ALPHA__) || defined(__ARM__)
868         datasp   = sp + framesize - SIZEOF_VOID_P;
869         ret_regs = (uint64_t *) sp;
870 #elif defined(__MIPS__)
871         /* MIPS always uses 8 bytes to store the RA */
872         datasp   = sp + framesize - 8;
873 #elif defined(__S390__)
874         datasp   = sp + framesize - 8;
875         ret_regs = (uint64_t *) (sp + 96);
876 #elif defined(__I386__)
877         datasp   = sp + framesize;
878         ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
879 #elif defined(__M68K__)
880         datasp   = sp + framesize;
881         ret_regs = (uint64_t *) (sp + 2 * 8);
882 #elif defined(__X86_64__)
883         datasp   = sp + framesize;
884         ret_regs = (uint64_t *) sp;
885 #elif defined(__POWERPC__)
886         datasp   = sp + framesize;
887         ret_regs = (uint64_t *) (sp + LA_SIZE + 2 * SIZEOF_VOID_P);
888 #elif defined(__POWERPC64__)
889         datasp   = sp + framesize;
890         ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
891 #else
892         vm_abort("codegen_finish_native_call: unsupported architecture");
893 #endif
894
895         /* get data structures from stack */
896
897         sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
898
899         /* Remove current stackframeinfo from chain. */
900
901         stacktrace_stackframeinfo_remove(sfi);
902
903 #if defined(ENABLE_HANDLES)
904         /* unwrap the return value from the local reference table */
905         /* AFTER: removing the stackframeinfo */
906         /* BEFORE: releasing the local reference table */
907
908         localref_native_exit(m, ret_regs);
909 #endif
910
911         /* get and unwrap the exception */
912         /* AFTER: removing the stackframe info */
913         /* BEFORE: releasing the local reference table */
914
915         e = exceptions_get_and_clear_exception();
916         o = LLNI_UNWRAP(e);
917
918 #if defined(ENABLE_JNI)
919         /* release JNI local references table for this thread */
920
921         localref_frame_pop_all();
922         localref_table_remove();
923 #endif
924
925 #if !defined(NDEBUG)
926 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
927         /* print the call-trace if necesarry */
928         /* AFTER: unwrapping the return value */
929
930         if (opt_TraceJavaCalls)
931                 trace_java_call_exit(m, ret_regs);
932 # endif
933 #endif
934
935         return o;
936 }
937
938
939 /* codegen_reg_of_var **********************************************************
940
941    This function determines a register, to which the result of an
942    operation should go, when it is ultimatively intended to store the
943    result in pseudoregister v.  If v is assigned to an actual
944    register, this register will be returned.  Otherwise (when v is
945    spilled) this function returns tempregnum.  If not already done,
946    regoff and flags are set in the stack location.
947        
948 *******************************************************************************/
949
950 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
951 {
952         if (!(v->flags & INMEMORY))
953                 return v->vv.regoff;
954
955         return tempregnum;
956 }
957
958
959 /* codegen_reg_of_dst **********************************************************
960
961    This function determines a register, to which the result of an
962    operation should go, when it is ultimatively intended to store the
963    result in iptr->dst.var.  If dst.var is assigned to an actual
964    register, this register will be returned.  Otherwise (when it is
965    spilled) this function returns tempregnum.  If not already done,
966    regoff and flags are set in the stack location.
967        
968 *******************************************************************************/
969
970 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
971 {
972         return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
973 }
974
975
976 /* codegen_emit_phi_moves ****************************************************
977
978    Emits phi moves at the end of the basicblock.
979
980 *******************************************************************************/
981
982 #if defined(ENABLE_SSA)
983 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
984 {
985         int lt_d,lt_s,i;
986         lsradata *ls;
987         codegendata *cd;
988         varinfo *s, *d;
989         instruction tmp_i;
990
991         cd = jd->cd;
992         ls = jd->ls;
993
994         MCODECHECK(512);
995
996         /* Moves from phi functions with highest indices have to be */
997         /* inserted first, since this is the order as is used for   */
998         /* conflict resolution */
999
1000         for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1001                 lt_d = ls->phi_moves[bptr->nr][i][0];
1002                 lt_s = ls->phi_moves[bptr->nr][i][1];
1003 #if defined(SSA_DEBUG_VERBOSE)
1004                 if (compileverbose)
1005                         printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1006 #endif
1007                 if (lt_s == UNUSED) {
1008 #if defined(SSA_DEBUG_VERBOSE)
1009                 if (compileverbose)
1010                         printf(" ... not processed \n");
1011 #endif
1012                         continue;
1013                 }
1014                         
1015                 d = VAR(ls->lifetime[lt_d].v_index);
1016                 s = VAR(ls->lifetime[lt_s].v_index);
1017                 
1018
1019                 if (d->type == -1) {
1020 #if defined(SSA_DEBUG_VERBOSE)
1021                         if (compileverbose)
1022                                 printf("...returning - phi lifetimes where joined\n");
1023 #endif
1024                         continue;
1025                 }
1026
1027                 if (s->type == -1) {
1028 #if defined(SSA_DEBUG_VERBOSE)
1029                         if (compileverbose)
1030                                 printf("...returning - phi lifetimes where joined\n");
1031 #endif
1032                         continue;
1033                 }
1034
1035                 tmp_i.opc = 0;
1036                 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1037                 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1038                 emit_copy(jd, &tmp_i);
1039
1040 #if defined(SSA_DEBUG_VERBOSE)
1041                 if (compileverbose) {
1042                         if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1043                                 /* mem -> mem */
1044                                 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1045                         }
1046                         else if (IS_INMEMORY(s->flags)) {
1047                                 /* mem -> reg */
1048                                 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1049                         }
1050                         else if (IS_INMEMORY(d->flags)) {
1051                                 /* reg -> mem */
1052                                 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1053                         }
1054                         else {
1055                                 /* reg -> reg */
1056                                 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1057                         }
1058                         printf("\n");
1059                 }
1060 #endif /* defined(SSA_DEBUG_VERBOSE) */
1061         }
1062 }
1063 #endif /* defined(ENABLE_SSA) */
1064
1065
1066 /* REMOVEME When we have exception handling in C. */
1067
1068 void *md_asm_codegen_get_pv_from_pc(void *ra)
1069 {
1070         return md_codegen_get_pv_from_pc(ra);
1071 }
1072
1073
1074 /*
1075  * These are local overrides for various environment variables in Emacs.
1076  * Please do not remove this and leave it at the end of the file, where
1077  * Emacs will automagically detect them.
1078  * ---------------------------------------------------------------------
1079  * Local variables:
1080  * mode: c
1081  * indent-tabs-mode: t
1082  * c-basic-offset: 4
1083  * tab-width: 4
1084  * End:
1085  * vim:noexpandtab:sw=4:ts=4:
1086  */