1 /* src/vm/jit/codegen-common.cpp - architecture independent code generator stuff
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
23 All functions assume the following code area / data area layout:
27 | code area | code area grows to higher addresses
29 +-----------+ <-- start of procedure
31 | data area | data area grows to lower addresses
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).
54 #include "mm/memory.hpp"
56 #include "toolbox/avl.h"
57 #include "toolbox/list.hpp"
58 #include "toolbox/logging.hpp"
60 #include "native/llni.h"
61 #include "native/localref.hpp"
62 #include "native/native.hpp"
64 #include "threads/thread.hpp"
66 #include "vm/jit/builtin.hpp"
67 #include "vm/exceptions.hpp"
68 #include "vm/method.hpp"
69 #include "vm/options.h"
70 #include "vm/string.hpp"
72 # include "vm/statistics.h"
75 #include "vm/jit/abi.h"
76 #include "vm/jit/asmpart.h"
77 #include "vm/jit/code.hpp"
78 #include "vm/jit/codegen-common.hpp"
80 #if defined(ENABLE_DISASSEMBLER)
81 # include "vm/jit/disass.h"
84 #include "vm/jit/dseg.h"
85 #include "vm/jit/emit-common.hpp"
86 #include "vm/jit/jit.hpp"
87 #include "vm/jit/linenumbertable.hpp"
88 #include "vm/jit/methodheader.h"
89 #include "vm/jit/methodtree.h"
90 #include "vm/jit/patcher-common.hpp"
91 #include "vm/jit/replace.hpp"
92 #if defined(ENABLE_SSA)
93 # include "vm/jit/optimizing/lsra.h"
94 # include "vm/jit/optimizing/ssa.h"
96 #include "vm/jit/stacktrace.hpp"
97 #include "vm/jit/trace.hpp"
99 #if defined(ENABLE_INTRP)
100 #include "vm/jit/intrp/intrp.h"
103 #if defined(ENABLE_VMLOG)
104 #include <vmlog_cacao.h>
110 /* codegen_init ****************************************************************
114 *******************************************************************************/
116 void codegen_init(void)
121 /* codegen_setup ***************************************************************
123 Allocates and initialises code area, data area and references.
125 *******************************************************************************/
127 void codegen_setup(jitdata *jd)
132 /* get required compiler data */
137 /* initialize members */
139 // Set flags as requested.
140 if (opt_AlwaysEmitLongBranches) {
141 cd->flags = CODEGENDATA_FLAG_LONGBRANCHES;
147 cd->mcodebase = (u1*) DumpMemory::allocate(MCODEINITSIZE);
148 cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
149 cd->mcodesize = MCODEINITSIZE;
151 /* initialize mcode variables */
153 cd->mcodeptr = cd->mcodebase;
154 cd->lastmcodeptr = cd->mcodebase;
156 #if defined(ENABLE_INTRP)
157 /* native dynamic superinstructions variables */
160 cd->ncodebase = (u1*) DumpMemory::allocate(NCODEINITSIZE);
161 cd->ncodesize = NCODEINITSIZE;
163 /* initialize ncode variables */
165 cd->ncodeptr = cd->ncodebase;
167 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
168 cd->superstarts = NULL;
175 cd->jumpreferences = NULL;
177 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
178 cd->datareferences = NULL;
181 cd->brancheslabel = new DumpList<branch_label_ref_t*>();
182 cd->linenumbers = new DumpList<Linenumber>();
186 /* codegen_reset ***************************************************************
188 Resets the codegen data structure so we can recompile the method.
190 *******************************************************************************/
192 static void codegen_reset(jitdata *jd)
198 /* get required compiler data */
203 /* reset error flag */
205 cd->flags &= ~CODEGENDATA_FLAG_ERROR;
207 /* reset some members, we reuse the code memory already allocated
208 as this should have almost the correct size */
210 cd->mcodeptr = cd->mcodebase;
211 cd->lastmcodeptr = cd->mcodebase;
216 cd->jumpreferences = NULL;
218 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
219 cd->datareferences = NULL;
222 cd->brancheslabel = new DumpList<branch_label_ref_t*>();
223 cd->linenumbers = new DumpList<Linenumber>();
225 /* We need to clear the mpc and the branch references from all
226 basic blocks as they will definitely change. */
228 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
230 bptr->branchrefs = NULL;
233 /* We need to clear all the patcher references from the codeinfo
234 since they all will be regenerated */
236 patcher_list_reset(code);
238 #if defined(ENABLE_REPLACEMENT)
239 code->rplpoints = NULL;
240 code->rplpointcount = 0;
241 code->regalloc = NULL;
242 code->regalloccount = 0;
243 code->globalcount = 0;
248 /* codegen_generate ************************************************************
250 Generates the code for the currently compiled method.
252 *******************************************************************************/
254 bool codegen_generate(jitdata *jd)
258 /* get required compiler data */
262 /* call the machine-dependent code generation function */
264 if (!codegen_emit(jd))
267 /* check for an error */
269 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
270 /* check for long-branches flag, if it is set we recompile the
275 log_message_method("Re-generating code: ", jd->m);
278 /* XXX maybe we should tag long-branches-methods for recompilation */
280 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
281 /* we have to reset the codegendata structure first */
285 /* and restart the compiler run */
287 if (!codegen_emit(jd))
291 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
296 log_message_method("Re-generating code done: ", jd->m);
300 /* reallocate the memory and finish the code generation */
304 /* everything's ok */
310 /* codegen_close ***************************************************************
314 *******************************************************************************/
316 void codegen_close(void)
318 /* TODO: release avl tree on i386 and x86_64 */
322 /* codegen_increase ************************************************************
326 *******************************************************************************/
328 void codegen_increase(codegendata *cd)
332 /* save old mcodebase pointer */
334 oldmcodebase = cd->mcodebase;
336 /* reallocate to new, doubled memory */
338 cd->mcodebase = (u1*) DumpMemory::reallocate(cd->mcodebase,
342 cd->mcodeend = cd->mcodebase + cd->mcodesize;
344 /* set new mcodeptr */
346 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
348 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
349 || defined(__SPARC_64__)
350 /* adjust the pointer to the last patcher position */
352 if (cd->lastmcodeptr != NULL)
353 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
358 /* codegen_ncode_increase ******************************************************
362 *******************************************************************************/
364 #if defined(ENABLE_INTRP)
365 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
369 /* save old ncodebase pointer */
371 oldncodebase = cd->ncodebase;
373 /* reallocate to new, doubled memory */
375 cd->ncodebase = DMREALLOC(cd->ncodebase,
381 /* return the new ncodeptr */
383 return (cd->ncodebase + (ncodeptr - oldncodebase));
388 /* codegen_add_branch_ref ******************************************************
390 Prepends an branch to the list.
392 *******************************************************************************/
394 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
399 STATISTICS(count_branches_unresolved++);
401 /* calculate the mpc of the branch instruction */
403 branchmpc = cd->mcodeptr - cd->mcodebase;
405 br = (branchref*) DumpMemory::allocate(sizeof(branchref));
407 br->branchmpc = branchmpc;
408 br->condition = condition;
410 br->options = options;
411 br->next = target->branchrefs;
413 target->branchrefs = br;
417 /* codegen_resolve_branchrefs **************************************************
419 Resolves and patches the branch references of a given basic block.
421 *******************************************************************************/
423 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
428 /* Save the mcodeptr because in the branch emitting functions
429 we generate code somewhere inside already generated code,
430 but we're still in the actual code generation phase. */
432 mcodeptr = cd->mcodeptr;
434 /* just to make sure */
436 assert(bptr->mpc >= 0);
438 for (br = bptr->branchrefs; br != NULL; br = br->next) {
439 /* temporary set the mcodeptr */
441 cd->mcodeptr = cd->mcodebase + br->branchmpc;
443 /* emit_bccz and emit_branch emit the correct code, even if we
444 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
446 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
449 /* restore mcodeptr */
451 cd->mcodeptr = mcodeptr;
455 /* codegen_branch_label_add ****************************************************
457 Append an branch to the label-branch list.
459 *******************************************************************************/
461 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
463 // Calculate the current mpc.
464 int32_t mpc = cd->mcodeptr - cd->mcodebase;
466 branch_label_ref_t* br = (branch_label_ref_t*) DumpMemory::allocate(sizeof(branch_label_ref_t));
470 br->condition = condition;
472 br->options = options;
474 // Add the branch to the list.
475 cd->brancheslabel->push_back(br);
479 /* codegen_set_replacement_point_notrap ****************************************
481 Record the position of a non-trappable replacement point.
483 *******************************************************************************/
485 #if defined(ENABLE_REPLACEMENT)
487 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
489 void codegen_set_replacement_point_notrap(codegendata *cd)
492 assert(cd->replacementpoint);
493 assert(cd->replacementpoint->type == type);
494 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
496 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
498 cd->replacementpoint++;
500 #endif /* defined(ENABLE_REPLACEMENT) */
503 /* codegen_set_replacement_point ***********************************************
505 Record the position of a trappable replacement point.
507 *******************************************************************************/
509 #if defined(ENABLE_REPLACEMENT)
511 void codegen_set_replacement_point(codegendata *cd, s4 type)
513 void codegen_set_replacement_point(codegendata *cd)
516 assert(cd->replacementpoint);
517 assert(cd->replacementpoint->type == type);
518 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
520 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
522 cd->replacementpoint++;
525 /* XXX actually we should use an own REPLACEMENT_NOPS here! */
526 if (opt_TestReplacement)
530 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
532 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
534 #endif /* defined(ENABLE_REPLACEMENT) */
537 /* codegen_finish **************************************************************
539 Finishes the code generation. A new memory, large enough for both
540 data and code, is allocated and data and code are copied together
541 to their final layout, unresolved jumps are resolved, ...
543 *******************************************************************************/
545 void codegen_finish(jitdata *jd)
550 #if defined(ENABLE_INTRP)
558 /* get required compiler data */
563 /* prevent compiler warning */
565 #if defined(ENABLE_INTRP)
569 /* calculate the code length */
571 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
573 #if defined(ENABLE_STATISTICS)
575 count_code_len += mcodelen;
576 count_data_len += cd->dseglen;
580 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
582 #if defined(ENABLE_INTRP)
584 ncodelen = cd->ncodeptr - cd->ncodebase;
586 ncodelen = 0; /* avoid compiler warning */
590 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
591 alignedlen = alignedmcodelen + cd->dseglen;
593 #if defined(ENABLE_INTRP)
595 alignedlen += ncodelen;
599 /* allocate new memory */
601 code->mcodelength = mcodelen + cd->dseglen;
602 code->mcode = CNEW(u1, alignedlen);
604 /* set the entrypoint of the method */
606 assert(code->entrypoint == NULL);
607 code->entrypoint = epoint = (code->mcode + cd->dseglen);
609 /* fill the data segment (code->entrypoint must already be set!) */
613 /* copy code to the new location */
615 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
617 #if defined(ENABLE_INTRP)
618 /* relocate native dynamic superinstruction code (if any) */
621 cd->mcodebase = code->entrypoint;
624 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
626 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
628 /* flush the instruction and data caches */
630 md_cacheflush(ncodebase, ncodelen);
632 /* set some cd variables for dynamic_super_rerwite */
634 cd->ncodebase = ncodebase;
637 cd->ncodebase = NULL;
640 dynamic_super_rewrite(cd);
644 /* Create the exception table. */
646 exceptiontable_create(jd);
648 /* Create the linenumber table. */
650 code->linenumbertable = new LinenumberTable(jd);
652 /* jump table resolving */
654 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
655 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
656 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
658 /* patcher resolving */
662 #if defined(ENABLE_REPLACEMENT)
663 /* replacement point resolving */
668 rp = code->rplpoints;
669 for (i=0; i<code->rplpointcount; ++i, ++rp) {
670 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
673 #endif /* defined(ENABLE_REPLACEMENT) */
675 /* Insert method into methodtree to find the entrypoint. */
677 methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
679 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
680 /* resolve data segment references */
682 dseg_resolve_datareferences(jd);
685 /* flush the instruction and data caches */
687 md_cacheflush(code->mcode, code->mcodelength);
691 /* codegen_start_native_call ***************************************************
693 Prepares the stuff required for a native (JNI) function call:
695 - adds a stackframe info structure to the chain, for stacktraces
696 - prepares the local references table on the stack
698 The layout of the native stub stackframe should look like this:
700 +---------------------------+ <- java SP (of parent Java function)
702 +---------------------------+ <- data SP
704 | stackframe info structure |
706 +---------------------------+
708 | local references table |
710 +---------------------------+
712 | saved registers (if any) |
714 +---------------------------+
716 | arguments (if any) |
718 +---------------------------+ <- current SP (native stub)
720 *******************************************************************************/
722 java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
724 stackframeinfo_t *sfi;
734 STATISTICS(count_calls_java_to_native++);
736 /* Get the methodinfo. */
738 m = code_get_methodinfo_for_pv(pv);
742 framesize = *((int32_t *) (pv + FrameSize));
744 assert(framesize >= (int32_t) (sizeof(stackframeinfo_t) + sizeof(localref_table)));
746 /* calculate needed values */
748 #if defined(__ALPHA__) || defined(__ARM__)
749 datasp = sp + framesize - SIZEOF_VOID_P;
750 javasp = sp + framesize;
751 arg_regs = (uint64_t *) sp;
752 arg_stack = (uint64_t *) javasp;
753 #elif defined(__MIPS__)
754 /* MIPS always uses 8 bytes to store the RA */
755 datasp = sp + framesize - 8;
756 javasp = sp + framesize;
757 # if SIZEOF_VOID_P == 8
758 arg_regs = (uint64_t *) sp;
760 arg_regs = (uint64_t *) (sp + 5 * 8);
762 arg_stack = (uint64_t *) javasp;
763 #elif defined(__S390__)
764 datasp = sp + framesize - 8;
765 javasp = sp + framesize;
766 arg_regs = (uint64_t *) (sp + 96);
767 arg_stack = (uint64_t *) javasp;
768 #elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
769 datasp = sp + framesize;
770 javasp = sp + framesize + SIZEOF_VOID_P;
771 arg_regs = (uint64_t *) sp;
772 arg_stack = (uint64_t *) javasp;
773 #elif defined(__POWERPC__)
774 datasp = sp + framesize;
775 javasp = sp + framesize;
776 arg_regs = (uint64_t *) (sp + LA_SIZE + 4 * SIZEOF_VOID_P);
777 arg_stack = (uint64_t *) javasp;
778 #elif defined(__POWERPC64__)
779 datasp = sp + framesize;
780 javasp = sp + framesize;
781 arg_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
782 arg_stack = (uint64_t *) javasp;
784 /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
785 /* XXX maybe we need to pass the RA as argument there */
786 vm_abort("codegen_start_native_call: unsupported architecture");
789 /* get data structures from stack */
791 sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
792 lrt = (localref_table *) (datasp - sizeof(stackframeinfo_t) -
793 sizeof(localref_table));
795 #if defined(ENABLE_JNI)
796 /* add current JNI local references table to this thread */
798 localref_table_add(lrt);
802 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
803 /* print the call-trace if necesarry */
804 /* BEFORE: filling the local reference table */
806 if (opt_TraceJavaCalls || opt_TraceBuiltinCalls)
807 trace_java_call_enter(m, arg_regs, arg_stack);
811 #if defined(ENABLE_HANDLES)
812 /* place all references into the local reference table */
813 /* BEFORE: creating stackframeinfo */
815 localref_native_enter(m, arg_regs, arg_stack);
818 /* Add a stackframeinfo for this native method. We don't have RA
819 and XPC here. These are determined in
820 stacktrace_stackframeinfo_add. */
822 stacktrace_stackframeinfo_add(sfi, pv, sp, NULL, NULL);
824 /* Return a wrapped classinfo for static methods. */
826 if (m->flags & ACC_STATIC)
827 return (java_handle_t *) LLNI_classinfo_wrap(m->clazz);
833 /* codegen_finish_native_call **************************************************
835 Removes the stuff required for a native (JNI) function call.
836 Additionally it checks for an exceptions and in case, get the
837 exception object and clear the pointer.
839 *******************************************************************************/
841 java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
843 stackframeinfo_t *sfi;
853 /* get information from method header */
855 code = code_get_codeinfo_for_pv(pv);
857 framesize = *((int32_t *) (pv + FrameSize));
861 /* get the methodinfo */
866 /* calculate needed values */
868 #if defined(__ALPHA__) || defined(__ARM__)
869 datasp = sp + framesize - SIZEOF_VOID_P;
870 ret_regs = (uint64_t *) sp;
871 #elif defined(__MIPS__)
872 /* MIPS always uses 8 bytes to store the RA */
873 datasp = sp + framesize - 8;
874 # if SIZEOF_VOID_P == 8
875 ret_regs = (uint64_t *) sp;
877 ret_regs = (uint64_t *) (sp + 1 * 8);
879 #elif defined(__S390__)
880 datasp = sp + framesize - 8;
881 ret_regs = (uint64_t *) (sp + 96);
882 #elif defined(__I386__)
883 datasp = sp + framesize;
884 ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
885 #elif defined(__M68K__)
886 datasp = sp + framesize;
887 ret_regs = (uint64_t *) (sp + 2 * 8);
888 #elif defined(__X86_64__)
889 datasp = sp + framesize;
890 ret_regs = (uint64_t *) sp;
891 #elif defined(__POWERPC__)
892 datasp = sp + framesize;
893 ret_regs = (uint64_t *) (sp + LA_SIZE + 2 * SIZEOF_VOID_P);
894 #elif defined(__POWERPC64__)
895 datasp = sp + framesize;
896 ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
898 vm_abort("codegen_finish_native_call: unsupported architecture");
901 /* get data structures from stack */
903 sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
905 /* Remove current stackframeinfo from chain. */
907 stacktrace_stackframeinfo_remove(sfi);
909 #if defined(ENABLE_HANDLES)
910 /* unwrap the return value from the local reference table */
911 /* AFTER: removing the stackframeinfo */
912 /* BEFORE: releasing the local reference table */
914 localref_native_exit(m, ret_regs);
917 /* get and unwrap the exception */
918 /* AFTER: removing the stackframe info */
919 /* BEFORE: releasing the local reference table */
921 e = exceptions_get_and_clear_exception();
924 #if defined(ENABLE_JNI)
925 /* release JNI local references table for this thread */
927 localref_frame_pop_all();
928 localref_table_remove();
932 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
933 /* print the call-trace if necesarry */
934 /* AFTER: unwrapping the return value */
936 if (opt_TraceJavaCalls || opt_TraceBuiltinCalls)
937 trace_java_call_exit(m, ret_regs);
945 /* codegen_reg_of_var **********************************************************
947 This function determines a register, to which the result of an
948 operation should go, when it is ultimatively intended to store the
949 result in pseudoregister v. If v is assigned to an actual
950 register, this register will be returned. Otherwise (when v is
951 spilled) this function returns tempregnum. If not already done,
952 regoff and flags are set in the stack location.
954 *******************************************************************************/
956 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
958 if (!(v->flags & INMEMORY))
965 /* codegen_reg_of_dst **********************************************************
967 This function determines a register, to which the result of an
968 operation should go, when it is ultimatively intended to store the
969 result in iptr->dst.var. If dst.var is assigned to an actual
970 register, this register will be returned. Otherwise (when it is
971 spilled) this function returns tempregnum. If not already done,
972 regoff and flags are set in the stack location.
974 *******************************************************************************/
976 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
978 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
982 /* codegen_emit_phi_moves ****************************************************
984 Emits phi moves at the end of the basicblock.
986 *******************************************************************************/
988 #if defined(ENABLE_SSA)
989 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1002 /* Moves from phi functions with highest indices have to be */
1003 /* inserted first, since this is the order as is used for */
1004 /* conflict resolution */
1006 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1007 lt_d = ls->phi_moves[bptr->nr][i][0];
1008 lt_s = ls->phi_moves[bptr->nr][i][1];
1009 #if defined(SSA_DEBUG_VERBOSE)
1011 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1013 if (lt_s == UNUSED) {
1014 #if defined(SSA_DEBUG_VERBOSE)
1016 printf(" ... not processed \n");
1021 d = VAR(ls->lifetime[lt_d].v_index);
1022 s = VAR(ls->lifetime[lt_s].v_index);
1025 if (d->type == -1) {
1026 #if defined(SSA_DEBUG_VERBOSE)
1028 printf("...returning - phi lifetimes where joined\n");
1033 if (s->type == -1) {
1034 #if defined(SSA_DEBUG_VERBOSE)
1036 printf("...returning - phi lifetimes where joined\n");
1042 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1043 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1044 emit_copy(jd, &tmp_i);
1046 #if defined(SSA_DEBUG_VERBOSE)
1047 if (compileverbose) {
1048 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1050 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1052 else if (IS_INMEMORY(s->flags)) {
1054 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1056 else if (IS_INMEMORY(d->flags)) {
1058 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1062 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1066 #endif /* defined(SSA_DEBUG_VERBOSE) */
1069 #endif /* defined(ENABLE_SSA) */
1072 /* REMOVEME When we have exception handling in C. */
1074 void *md_asm_codegen_get_pv_from_pc(void *ra)
1076 return md_codegen_get_pv_from_pc(ra);
1081 * These are local overrides for various environment variables in Emacs.
1082 * Please do not remove this and leave it at the end of the file, where
1083 * Emacs will automagically detect them.
1084 * ---------------------------------------------------------------------
1087 * indent-tabs-mode: t
1091 * vim:noexpandtab:sw=4:ts=4: