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).
48 #include "vm/jit/jitcache.hpp"
56 #include "mm/memory.h"
58 #include "toolbox/avl.h"
59 #include "toolbox/list.hpp"
60 #include "toolbox/logging.h"
62 #include "native/llni.h"
63 #include "native/localref.hpp"
64 #include "native/native.hpp"
66 #include "threads/thread.hpp"
68 #include "vm/jit/builtin.hpp"
69 #include "vm/exceptions.hpp"
70 #include "vm/method.h"
71 #include "vm/options.h"
72 #include "vm/string.hpp"
74 # include "vm/statistics.h"
77 #include "vm/jit/abi.h"
78 #include "vm/jit/asmpart.h"
79 #include "vm/jit/code.hpp"
80 #include "vm/jit/codegen-common.hpp"
82 #if defined(ENABLE_DISASSEMBLER)
83 # include "vm/jit/disass.h"
86 #include "vm/jit/dseg.h"
87 #include "vm/jit/emit-common.hpp"
88 #include "vm/jit/jit.hpp"
89 #include "vm/jit/linenumbertable.hpp"
90 #include "vm/jit/methodheader.h"
91 #include "vm/jit/methodtree.h"
92 #include "vm/jit/patcher-common.hpp"
93 #include "vm/jit/replace.hpp"
94 #if defined(ENABLE_SSA)
95 # include "vm/jit/optimizing/lsra.h"
96 # include "vm/jit/optimizing/ssa.h"
98 #include "vm/jit/stacktrace.hpp"
99 #include "vm/jit/trace.hpp"
101 #if defined(ENABLE_INTRP)
102 #include "vm/jit/intrp/intrp.h"
105 #if defined(ENABLE_VMLOG)
106 #include <vmlog_cacao.h>
112 /* codegen_init ****************************************************************
116 *******************************************************************************/
118 void codegen_init(void)
123 /* codegen_setup ***************************************************************
125 Allocates and initialises code area, data area and references.
127 *******************************************************************************/
129 void codegen_setup(jitdata *jd)
134 /* get required compiler data */
139 /* initialize members */
141 // Set flags as requested.
142 if (opt_AlwaysEmitLongBranches) {
143 cd->flags = CODEGENDATA_FLAG_LONGBRANCHES;
149 cd->mcodebase = (u1*) DumpMemory::allocate(MCODEINITSIZE);
150 cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
151 cd->mcodesize = MCODEINITSIZE;
153 /* initialize mcode variables */
155 cd->mcodeptr = cd->mcodebase;
156 cd->lastmcodeptr = cd->mcodebase;
158 #if defined(ENABLE_INTRP)
159 /* native dynamic superinstructions variables */
162 cd->ncodebase = (u1*) DumpMemory::allocate(NCODEINITSIZE);
163 cd->ncodesize = NCODEINITSIZE;
165 /* initialize ncode variables */
167 cd->ncodeptr = cd->ncodebase;
169 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
170 cd->superstarts = NULL;
177 cd->jumpreferences = NULL;
179 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
180 cd->datareferences = NULL;
183 cd->brancheslabel = new DumpList<branch_label_ref_t*>();
184 cd->linenumbers = new DumpList<Linenumber>();
188 /* codegen_reset ***************************************************************
190 Resets the codegen data structure so we can recompile the method.
192 *******************************************************************************/
194 static void codegen_reset(jitdata *jd)
200 /* get required compiler data */
205 /* reset error flag */
207 cd->flags &= ~CODEGENDATA_FLAG_ERROR;
209 /* reset some members, we reuse the code memory already allocated
210 as this should have almost the correct size */
212 cd->mcodeptr = cd->mcodebase;
213 cd->lastmcodeptr = cd->mcodebase;
218 cd->jumpreferences = NULL;
220 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
221 cd->datareferences = NULL;
224 cd->brancheslabel = new DumpList<branch_label_ref_t*>();
225 cd->linenumbers = new DumpList<Linenumber>();
227 /* We need to clear the mpc and the branch references from all
228 basic blocks as they will definitely change. */
230 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
232 bptr->branchrefs = NULL;
235 /* We need to clear all the patcher references from the codeinfo
236 since they all will be regenerated */
238 patcher_list_reset(code);
240 #if defined(ENABLE_REPLACEMENT)
241 code->rplpoints = NULL;
242 code->rplpointcount = 0;
243 code->regalloc = NULL;
244 code->regalloccount = 0;
245 code->globalcount = 0;
250 /* codegen_generate ************************************************************
252 Generates the code for the currently compiled method.
254 *******************************************************************************/
256 bool codegen_generate(jitdata *jd)
260 /* get required compiler data */
264 /* call the machine-dependent code generation function */
266 if (!codegen_emit(jd))
269 /* check for an error */
271 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
272 /* check for long-branches flag, if it is set we recompile the
277 log_message_method("Re-generating code: ", jd->m);
280 /* XXX maybe we should tag long-branches-methods for recompilation */
282 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
283 /* we have to reset the codegendata structure first */
287 /* and restart the compiler run */
289 if (!codegen_emit(jd))
293 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
298 log_message_method("Re-generating code done: ", jd->m);
302 /* reallocate the memory and finish the code generation */
306 /* everything's ok */
312 /* codegen_close ***************************************************************
316 *******************************************************************************/
318 void codegen_close(void)
320 /* TODO: release avl tree on i386 and x86_64 */
324 /* codegen_increase ************************************************************
328 *******************************************************************************/
330 void codegen_increase(codegendata *cd)
334 /* save old mcodebase pointer */
336 oldmcodebase = cd->mcodebase;
338 /* reallocate to new, doubled memory */
340 cd->mcodebase = (u1*) DumpMemory::reallocate(cd->mcodebase,
344 cd->mcodeend = cd->mcodebase + cd->mcodesize;
346 /* set new mcodeptr */
348 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
350 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
351 || defined(__SPARC_64__)
352 /* adjust the pointer to the last patcher position */
354 if (cd->lastmcodeptr != NULL)
355 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
360 /* codegen_ncode_increase ******************************************************
364 *******************************************************************************/
366 #if defined(ENABLE_INTRP)
367 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
371 /* save old ncodebase pointer */
373 oldncodebase = cd->ncodebase;
375 /* reallocate to new, doubled memory */
377 cd->ncodebase = DMREALLOC(cd->ncodebase,
383 /* return the new ncodeptr */
385 return (cd->ncodebase + (ncodeptr - oldncodebase));
390 /* codegen_add_branch_ref ******************************************************
392 Prepends an branch to the list.
394 *******************************************************************************/
396 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
401 STATISTICS(count_branches_unresolved++);
403 /* calculate the mpc of the branch instruction */
405 branchmpc = cd->mcodeptr - cd->mcodebase;
407 br = (branchref*) DumpMemory::allocate(sizeof(branchref));
409 br->branchmpc = branchmpc;
410 br->condition = condition;
412 br->options = options;
413 br->next = target->branchrefs;
415 target->branchrefs = br;
419 /* codegen_resolve_branchrefs **************************************************
421 Resolves and patches the branch references of a given basic block.
423 *******************************************************************************/
425 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
430 /* Save the mcodeptr because in the branch emitting functions
431 we generate code somewhere inside already generated code,
432 but we're still in the actual code generation phase. */
434 mcodeptr = cd->mcodeptr;
436 /* just to make sure */
438 assert(bptr->mpc >= 0);
440 for (br = bptr->branchrefs; br != NULL; br = br->next) {
441 /* temporary set the mcodeptr */
443 cd->mcodeptr = cd->mcodebase + br->branchmpc;
445 /* emit_bccz and emit_branch emit the correct code, even if we
446 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
448 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
451 /* restore mcodeptr */
453 cd->mcodeptr = mcodeptr;
457 /* codegen_branch_label_add ****************************************************
459 Append an branch to the label-branch list.
461 *******************************************************************************/
463 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
465 // Calculate the current mpc.
466 int32_t mpc = cd->mcodeptr - cd->mcodebase;
468 branch_label_ref_t* br = (branch_label_ref_t*) DumpMemory::allocate(sizeof(branch_label_ref_t));
472 br->condition = condition;
474 br->options = options;
476 // Add the branch to the list.
477 cd->brancheslabel->push_back(br);
481 /* codegen_set_replacement_point_notrap ****************************************
483 Record the position of a non-trappable replacement point.
485 *******************************************************************************/
487 #if defined(ENABLE_REPLACEMENT)
489 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
491 void codegen_set_replacement_point_notrap(codegendata *cd)
494 assert(cd->replacementpoint);
495 assert(cd->replacementpoint->type == type);
496 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
498 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
500 cd->replacementpoint++;
502 #endif /* defined(ENABLE_REPLACEMENT) */
505 /* codegen_set_replacement_point ***********************************************
507 Record the position of a trappable replacement point.
509 *******************************************************************************/
511 #if defined(ENABLE_REPLACEMENT)
513 void codegen_set_replacement_point(codegendata *cd, s4 type)
515 void codegen_set_replacement_point(codegendata *cd)
518 assert(cd->replacementpoint);
519 assert(cd->replacementpoint->type == type);
520 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
522 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
524 cd->replacementpoint++;
527 /* XXX actually we should use an own REPLACEMENT_NOPS here! */
528 if (opt_TestReplacement)
532 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
534 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
536 #endif /* defined(ENABLE_REPLACEMENT) */
539 /* codegen_finish **************************************************************
541 Finishes the code generation. A new memory, large enough for both
542 data and code, is allocated and data and code are copied together
543 to their final layout, unresolved jumps are resolved, ...
545 *******************************************************************************/
547 void codegen_finish(jitdata *jd)
552 #if defined(ENABLE_INTRP)
560 /* get required compiler data */
565 /* prevent compiler warning */
567 #if defined(ENABLE_INTRP)
571 /* calculate the code length */
573 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
575 #if defined(ENABLE_STATISTICS)
577 count_code_len += mcodelen;
578 count_data_len += cd->dseglen;
582 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
584 #if defined(ENABLE_INTRP)
586 ncodelen = cd->ncodeptr - cd->ncodebase;
588 ncodelen = 0; /* avoid compiler warning */
592 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
593 alignedlen = alignedmcodelen + cd->dseglen;
595 #if defined(ENABLE_INTRP)
597 alignedlen += ncodelen;
601 /* allocate new memory */
603 code->mcodelength = mcodelen + cd->dseglen;
604 code->mcode = CNEW(u1, alignedlen);
606 /* set the entrypoint of the method */
608 assert(code->entrypoint == NULL);
609 code->entrypoint = epoint = (code->mcode + cd->dseglen);
611 /* fill the data segment (code->entrypoint must already be set!) */
615 /* copy code to the new location */
617 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
619 #if defined(ENABLE_INTRP)
620 /* relocate native dynamic superinstruction code (if any) */
623 cd->mcodebase = code->entrypoint;
626 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
628 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
630 /* flush the instruction and data caches */
632 md_cacheflush(ncodebase, ncodelen);
634 /* set some cd variables for dynamic_super_rerwite */
636 cd->ncodebase = ncodebase;
639 cd->ncodebase = NULL;
642 dynamic_super_rewrite(cd);
646 /* Create the exception table. */
648 exceptiontable_create(jd);
650 /* Create the linenumber table. */
652 code->linenumbertable = new LinenumberTable(jd);
654 /* jump table resolving */
656 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
658 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
659 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
661 JITCACHE_ADD_CACHED_REF(code, CRT_JUMPREFERENCE, jr->target->mpc, jr->tablepos);
664 /* patcher resolving */
668 #if defined(ENABLE_REPLACEMENT)
669 /* replacement point resolving */
674 rp = code->rplpoints;
675 for (i=0; i<code->rplpointcount; ++i, ++rp) {
676 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
679 #endif /* defined(ENABLE_REPLACEMENT) */
681 /* Insert method into methodtree to find the entrypoint. */
683 methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
685 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
686 /* resolve data segment references */
688 dseg_resolve_datareferences(jd);
691 /* flush the instruction and data caches */
693 md_cacheflush(code->mcode, code->mcodelength);
697 /* codegen_start_native_call ***************************************************
699 Prepares the stuff required for a native (JNI) function call:
701 - adds a stackframe info structure to the chain, for stacktraces
702 - prepares the local references table on the stack
704 The layout of the native stub stackframe should look like this:
706 +---------------------------+ <- java SP (of parent Java function)
708 +---------------------------+ <- data SP
710 | stackframe info structure |
712 +---------------------------+
714 | local references table |
716 +---------------------------+
718 | saved registers (if any) |
720 +---------------------------+
722 | arguments (if any) |
724 +---------------------------+ <- current SP (native stub)
726 *******************************************************************************/
728 java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
730 stackframeinfo_t *sfi;
740 STATISTICS(count_calls_java_to_native++);
742 /* Get the methodinfo. */
744 m = code_get_methodinfo_for_pv(pv);
748 framesize = *((int32_t *) (pv + FrameSize));
750 assert(framesize >= (int32_t) (sizeof(stackframeinfo_t) + sizeof(localref_table)));
752 /* calculate needed values */
754 #if defined(__ALPHA__) || defined(__ARM__)
755 datasp = sp + framesize - SIZEOF_VOID_P;
756 javasp = sp + framesize;
757 arg_regs = (uint64_t *) sp;
758 arg_stack = (uint64_t *) javasp;
759 #elif defined(__MIPS__)
760 /* MIPS always uses 8 bytes to store the RA */
761 datasp = sp + framesize - 8;
762 javasp = sp + framesize;
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(__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)
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 #elif defined(__S390__)
875 datasp = sp + framesize - 8;
876 ret_regs = (uint64_t *) (sp + 96);
877 #elif defined(__I386__)
878 datasp = sp + framesize;
879 ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
880 #elif defined(__M68K__)
881 datasp = sp + framesize;
882 ret_regs = (uint64_t *) (sp + 2 * 8);
883 #elif defined(__X86_64__)
884 datasp = sp + framesize;
885 ret_regs = (uint64_t *) sp;
886 #elif defined(__POWERPC__)
887 datasp = sp + framesize;
888 ret_regs = (uint64_t *) (sp + LA_SIZE + 2 * SIZEOF_VOID_P);
889 #elif defined(__POWERPC64__)
890 datasp = sp + framesize;
891 ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
893 vm_abort("codegen_finish_native_call: unsupported architecture");
896 /* get data structures from stack */
898 sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
900 /* Remove current stackframeinfo from chain. */
902 stacktrace_stackframeinfo_remove(sfi);
904 #if defined(ENABLE_HANDLES)
905 /* unwrap the return value from the local reference table */
906 /* AFTER: removing the stackframeinfo */
907 /* BEFORE: releasing the local reference table */
909 localref_native_exit(m, ret_regs);
912 /* get and unwrap the exception */
913 /* AFTER: removing the stackframe info */
914 /* BEFORE: releasing the local reference table */
916 e = exceptions_get_and_clear_exception();
919 #if defined(ENABLE_JNI)
920 /* release JNI local references table for this thread */
922 localref_frame_pop_all();
923 localref_table_remove();
927 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
928 /* print the call-trace if necesarry */
929 /* AFTER: unwrapping the return value */
931 if (opt_TraceJavaCalls)
932 trace_java_call_exit(m, ret_regs);
940 /* codegen_reg_of_var **********************************************************
942 This function determines a register, to which the result of an
943 operation should go, when it is ultimatively intended to store the
944 result in pseudoregister v. If v is assigned to an actual
945 register, this register will be returned. Otherwise (when v is
946 spilled) this function returns tempregnum. If not already done,
947 regoff and flags are set in the stack location.
949 *******************************************************************************/
951 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
953 if (!(v->flags & INMEMORY))
960 /* codegen_reg_of_dst **********************************************************
962 This function determines a register, to which the result of an
963 operation should go, when it is ultimatively intended to store the
964 result in iptr->dst.var. If dst.var is assigned to an actual
965 register, this register will be returned. Otherwise (when it is
966 spilled) this function returns tempregnum. If not already done,
967 regoff and flags are set in the stack location.
969 *******************************************************************************/
971 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
973 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
977 /* codegen_emit_phi_moves ****************************************************
979 Emits phi moves at the end of the basicblock.
981 *******************************************************************************/
983 #if defined(ENABLE_SSA)
984 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
997 /* Moves from phi functions with highest indices have to be */
998 /* inserted first, since this is the order as is used for */
999 /* conflict resolution */
1001 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1002 lt_d = ls->phi_moves[bptr->nr][i][0];
1003 lt_s = ls->phi_moves[bptr->nr][i][1];
1004 #if defined(SSA_DEBUG_VERBOSE)
1006 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1008 if (lt_s == UNUSED) {
1009 #if defined(SSA_DEBUG_VERBOSE)
1011 printf(" ... not processed \n");
1016 d = VAR(ls->lifetime[lt_d].v_index);
1017 s = VAR(ls->lifetime[lt_s].v_index);
1020 if (d->type == -1) {
1021 #if defined(SSA_DEBUG_VERBOSE)
1023 printf("...returning - phi lifetimes where joined\n");
1028 if (s->type == -1) {
1029 #if defined(SSA_DEBUG_VERBOSE)
1031 printf("...returning - phi lifetimes where joined\n");
1037 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1038 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1039 emit_copy(jd, &tmp_i);
1041 #if defined(SSA_DEBUG_VERBOSE)
1042 if (compileverbose) {
1043 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1045 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1047 else if (IS_INMEMORY(s->flags)) {
1049 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1051 else if (IS_INMEMORY(d->flags)) {
1053 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1057 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1061 #endif /* defined(SSA_DEBUG_VERBOSE) */
1064 #endif /* defined(ENABLE_SSA) */
1067 /* REMOVEME When we have exception handling in C. */
1069 void *md_asm_codegen_get_pv_from_pc(void *ra)
1071 return md_codegen_get_pv_from_pc(ra);
1076 * These are local overrides for various environment variables in Emacs.
1077 * Please do not remove this and leave it at the end of the file, where
1078 * Emacs will automagically detect them.
1079 * ---------------------------------------------------------------------
1082 * indent-tabs-mode: t
1086 * vim:noexpandtab:sw=4:ts=4: