📄 integrate.c
字号:
offset -= (UNITS_PER_WORD - GET_MODE_SIZE (GET_MODE (copy)));#endif /* For memory ref, adjust it by the desired offset. */ if (GET_CODE (copy) == MEM) { if (offset != 0) return change_address (copy, mode, plus_constant (XEXP (copy, 0), offset)); return copy; } if (GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG && ! CONSTANT_P (copy)) abort (); if (mode == VOIDmode) abort (); /* A REG cannot be offset by bytes, so use a subreg (which is possible only in certain cases). */ if (GET_MODE (copy) != mode && GET_MODE (copy) != VOIDmode) { int word; /* Crash if the portion of the arg wanted is not the least significant. Functions with refs to other parts of a parameter should not be inline-- see function_cannot_inline_p. */#ifdef BYTES_BIG_ENDIAN if ((offset + GET_MODE_SIZE (mode)) % UNITS_PER_WORD != GET_MODE_SIZE (GET_MODE (copy)) % UNITS_PER_WORD) abort ();#else if ((offset % UNITS_PER_WORD) != 0) abort ();#endif word = offset / UNITS_PER_WORD; if (GET_CODE (copy) == SUBREG) word += SUBREG_WORD (copy), copy = SUBREG_REG (copy); if (CONSTANT_P (copy)) copy = force_reg (GET_MODE (copy), copy); return gen_rtx (SUBREG, mode, copy, word); } return copy;}/* Like copy_rtx_and_substitute but produces different output, suitable for an ideosyncractic address that isn't memory_address_p. The output resembles the input except that REGs and MEMs are replaced with new psuedo registers. All the "real work" is done in separate insns which set up the values of these new registers. */static rtxcopy_address (orig) register rtx orig;{ register rtx copy; register int i, j; register RTX_CODE code; register enum machine_mode mode; register char *format_ptr; if (orig == 0) return 0; code = GET_CODE (orig); mode = GET_MODE (orig); switch (code) { case REG: if (REGNO (orig) != FRAME_POINTER_REGNUM) return copy_rtx_and_substitute (orig); return plus_constant (frame_pointer_rtx, fp_delta); case PLUS: if (GET_CODE (XEXP (orig, 0)) == REG && REGNO (XEXP (orig, 0)) == FRAME_POINTER_REGNUM) return plus_constant (orig, fp_delta); break; case MEM: return copy_to_reg (copy_rtx_and_substitute (orig)); case CODE_LABEL: case LABEL_REF: return copy_rtx_and_substitute (orig); case PC: case CC0: case CONST_INT: case CONST_DOUBLE: case SYMBOL_REF: return orig; } copy = rtx_alloc (code); PUT_MODE (copy, mode); copy->in_struct = orig->in_struct; copy->volatil = orig->volatil; copy->unchanging = orig->unchanging; format_ptr = GET_RTX_FORMAT (GET_CODE (copy)); for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++) { switch (*format_ptr++) { case '0': break; case 'e': XEXP (copy, i) = copy_rtx_and_substitute (XEXP (orig, i)); break; case 'u': /* Change any references to old-insns to point to the corresponding copied insns. */ XEXP (copy, i) = insn_map[INSN_UID (XEXP (orig, i))]; break; case 'E': XVEC (copy, i) = XVEC (orig, i); if (XVEC (orig, i) != NULL && XVECLEN (orig, i) != 0) { XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); for (j = 0; j < XVECLEN (copy, i); j++) XVECEXP (copy, i, j) = copy_rtx_and_substitute (XVECEXP (orig, i, j)); } break; case 'i': XINT (copy, i) = XINT (orig, i); break; case 's': XSTR (copy, i) = XSTR (orig, i); break; default: abort (); } } return copy;}/* Attempt to simplify INSN while copying it from an inline fn, assuming it is a SET that sets CC0. If we simplify it, we emit the appropriate insns and return the last insn that we have handled (since we may handle the insn that follows INSN as well as INSN itself). Otherwise we do nothing and return zero. */static rtxtry_fold_cc0 (insn) rtx insn;{ rtx cnst = copy_rtx_and_substitute (SET_SRC (PATTERN (insn))); rtx pat, copy; if (CONSTANT_P (cnst) /* @@ Cautious: Don't know how many of these tests we need. */ && NEXT_INSN (insn) && GET_CODE (pat = PATTERN (NEXT_INSN (insn))) == SET && SET_DEST (pat) == pc_rtx && GET_CODE (pat = SET_SRC (pat)) == IF_THEN_ELSE && GET_RTX_LENGTH (GET_CODE (XEXP (pat, 0))) == 2) { rtx cnst2; rtx cond = XEXP (pat, 0); if ((XEXP (cond, 0) == cc0_rtx && CONSTANT_P (XEXP (cond, 1)) && (cnst2 = XEXP (cond, 1))) || (XEXP (cond, 1) == cc0_rtx && CONSTANT_P (XEXP (cond, 0)) && (cnst2 = XEXP (cond, 0)))) { copy = fold_out_const_cc0 (cond, XEXP (pat, 1), XEXP (pat, 2), cnst, cnst2); if (copy) { if (GET_CODE (copy) == LABEL_REF) { /* We will branch unconditionally to the label specified by COPY. Eliminate dead code by running down the list of insn until we see a CODE_LABEL. If the CODE_LABEL is the one specified by COPY, we win, and can delete all code up to (but not necessarily including) that label. Otherwise only win a little: emit the branch insn, and continue expanding. */ rtx tmp = NEXT_INSN (insn); while (tmp && GET_CODE (tmp) != CODE_LABEL) tmp = NEXT_INSN (tmp); if (! tmp) abort (); if (label_map[CODE_LABEL_NUMBER (tmp)] == XEXP (copy, 0)) { /* Big win. */ return PREV_INSN (tmp); } else { /* Small win. Emit the unconditional branch, followed by a BARRIER, so that jump optimization will know what to do. */ emit_jump (copy); return NEXT_INSN (insn); } } else if (copy == pc_rtx) { /* Do not take the branch, just fall through. Jump optimize should handle the elimination of dead code if appropriate. */ return NEXT_INSN (insn); } else abort (); } } } return 0;}/* If (COND_RTX CNST1 CNST2) yield a result we can treat as being constant, return THEN_RTX if the result is always non-zero, and return ELSE_RTX otherwise. */static rtxfold_out_const_cc0 (cond_rtx, then_rtx, else_rtx, cnst1, cnst2) rtx cond_rtx, then_rtx, else_rtx; rtx cnst1, cnst2;{ int value1, value2; int int1 = GET_CODE (cnst1) == CONST_INT; int int2 = GET_CODE (cnst2) == CONST_INT; if (int1) value1 = INTVAL (cnst1); else value1 = 1; if (int2) value2 = INTVAL (cnst2); else value2 = 1; switch (GET_CODE (cond_rtx)) { case NE: if (int1 && int2) if (value1 != value2) return copy_rtx_and_substitute (then_rtx); else return copy_rtx_and_substitute (else_rtx); if (value1 == 0 || value2 == 0) return copy_rtx_and_substitute (then_rtx); if (int1 == 0 && int2 == 0) if (rtx_equal_p (cnst1, cnst2)) return copy_rtx_and_substitute (else_rtx); break; case EQ: if (int1 && int2) if (value1 == value2) return copy_rtx_and_substitute (then_rtx); else return copy_rtx_and_substitute (else_rtx); if (value1 == 0 || value2 == 0) return copy_rtx_and_substitute (else_rtx); if (int1 == 0 && int2 == 0) if (rtx_equal_p (cnst1, cnst2)) return copy_rtx_and_substitute (then_rtx); break; case GE: if (int1 && int2) if (value1 >= value2) return copy_rtx_and_substitute (then_rtx); else return copy_rtx_and_substitute (else_rtx); if (value1 == 0) return copy_rtx_and_substitute (else_rtx); if (value2 == 0) return copy_rtx_and_substitute (then_rtx); break; case GT: if (int1 && int2) if (value1 > value2) return copy_rtx_and_substitute (then_rtx); else return copy_rtx_and_substitute (else_rtx); if (value1 == 0) return copy_rtx_and_substitute (else_rtx); if (value2 == 0) return copy_rtx_and_substitute (then_rtx); break; case LE: if (int1 && int2) if (value1 <= value2) return copy_rtx_and_substitute (then_rtx); else return copy_rtx_and_substitute (else_rtx); if (value1 == 0) return copy_rtx_and_substitute (then_rtx); if (value2 == 0) return copy_rtx_and_substitute (else_rtx); break; case LT: if (int1 && int2) if (value1 < value2) return copy_rtx_and_substitute (then_rtx); else return copy_rtx_and_substitute (else_rtx); if (value1 == 0) return copy_rtx_and_substitute (then_rtx); if (value2 == 0) return copy_rtx_and_substitute (else_rtx); break; case GEU: if (int1 && int2) if ((unsigned)value1 >= (unsigned)value2) return copy_rtx_and_substitute (then_rtx); else return copy_rtx_and_substitute (else_rtx); if (value1 == 0) return copy_rtx_and_substitute (else_rtx); if (value2 == 0) return copy_rtx_and_substitute (then_rtx); break; case GTU: if (int1 && int2) if ((unsigned)value1 > (unsigned)value2) return copy_rtx_and_substitute (then_rtx); else return copy_rtx_and_substitute (else_rtx); if (value1 == 0) return copy_rtx_and_substitute (else_rtx); if (value2 == 0) return copy_rtx_and_substitute (then_rtx); break; case LEU: if (int1 && int2) if ((unsigned)value1 <= (unsigned)value2) return copy_rtx_and_substitute (then_rtx); else return copy_rtx_and_substitute (else_rtx); if (value1 == 0) return copy_rtx_and_substitute (then_rtx); if (value2 == 0) return copy_rtx_and_substitute (else_rtx); break; case LTU: if (int1 && int2) if ((unsigned)value1 < (unsigned)value2) return copy_rtx_and_substitute (then_rtx); else return copy_rtx_and_substitute (else_rtx); if (value1 == 0) return copy_rtx_and_substitute (then_rtx); if (value2 == 0) return copy_rtx_and_substitute (else_rtx); break; } /* Could not hack it. */ return 0;}/* Output the assembly language code for the function FNDECL from its DECL_SAVED_INSNS. Used for inline functions that are output at end of compilation instead of where they came in the source. */voidoutput_inline_function (fndecl) tree fndecl;{ rtx head = DECL_SAVED_INSNS (fndecl); rtx last; extern rtx stack_slot_list; temporary_allocation (); current_function_decl = fndecl; /* This call is only used to initialize global variables. */ init_function_start (fndecl, "lossage", 1); /* Set stack frame size. */ assign_stack_local (BLKmode, DECL_FRAME_SIZE (fndecl)); restore_reg_data (FIRST_PARM_INSN (head)); stack_slot_list = XEXP (head, 9); expand_function_end (DECL_SOURCE_FILE (fndecl), DECL_SOURCE_LINE (fndecl)); for (last = head; NEXT_INSN (last); last = NEXT_INSN (last)) ; set_new_first_and_last_insn (FIRST_PARM_INSN (head), last); /* Compile this function all the way down to assembly code. */ rest_of_compilation (fndecl); current_function_decl = 0; permanent_allocation ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -