📄 integrate.c
字号:
register RTX_CODE code; register enum machine_mode mode; register char *format_ptr; int regno; if (orig == 0) return 0; code = GET_CODE (orig); mode = GET_MODE (orig); switch (code) { case REG: /* If a frame-pointer register shows up, then we must `fix' the reference. If the stack pointer register shows up, it must be part of stack-adjustments (*not* because we eliminated the frame pointer!). Small hard registers are returned as-is. Pseudo-registers go through their `reg_map'. */ regno = REGNO (orig); if (regno < FIRST_PSEUDO_REGISTER) { /* Some hard registers are also mapped, but others are not translated. */ if (reg_map[regno] != 0) return reg_map[regno]; if (REG_FUNCTION_VALUE_P (orig)) { /* This is a reference to the function return value. If the function doesn't have a return value, error. If it does, it may not be the same mode as `inline_target' because SUBREG is not required for hard regs. If not, adjust mode of inline_target to fit the context. */ if (inline_target == 0) abort (); if (mode == GET_MODE (inline_target)) return inline_target; return gen_rtx (SUBREG, mode, inline_target, 0); } if (regno == FRAME_POINTER_REGNUM) return plus_constant (orig, fp_delta); return orig; } if (reg_map[regno] == NULL) { reg_map[regno] = gen_reg_rtx (mode); REG_USERVAR_P (reg_map[regno]) = REG_USERVAR_P (orig); } return reg_map[regno]; case SUBREG: copy = copy_rtx_and_substitute (SUBREG_REG (orig)); /* SUBREG is ordinary, but don't make nested SUBREGs. */ if (GET_CODE (copy) == SUBREG) return gen_rtx (SUBREG, GET_MODE (orig), SUBREG_REG (copy), SUBREG_WORD (orig) + SUBREG_WORD (copy)); return gen_rtx (SUBREG, GET_MODE (orig), copy, SUBREG_WORD (orig)); case CODE_LABEL: return label_map[CODE_LABEL_NUMBER (orig)]; case LABEL_REF: copy = rtx_alloc (LABEL_REF); PUT_MODE (copy, mode); XEXP (copy, 0) = label_map[CODE_LABEL_NUMBER (XEXP (orig, 0))]; return copy; case PC: case CC0: case CONST_INT: case CONST_DOUBLE: case SYMBOL_REF: return orig; case ASM_OPERANDS: /* If a single asm insn contains multiple output operands then it contains multiple ASM_OPERANDS rtx's that share operand 3. We must make sure that the copied insn continues to share it. */ if (orig_asm_operands_vector == XVEC (orig, 3)) { copy = rtx_alloc (ASM_OPERANDS); XSTR (copy, 0) = XSTR (orig, 0); XSTR (copy, 1) = XSTR (orig, 1); XINT (copy, 2) = XINT (orig, 2); XVEC (copy, 3) = copy_asm_operands_vector; XVEC (copy, 4) = copy_asm_constraints_vector; XSTR (copy, 5) = XSTR (orig, 5); XINT (copy, 6) = XINT (orig, 6); return copy; } break; case CALL: /* This is given special treatment because the first operand of a CALL is a (MEM ...) which may get forced into a register for cse. This is undesirable if function-address cse isn't wanted or if we won't do cse. */#ifndef NO_FUNCTION_CSE if (! (optimize && ! flag_no_function_cse))#endif return gen_rtx (CALL, GET_MODE (orig), gen_rtx (MEM, GET_MODE (XEXP (orig, 0)), copy_rtx_and_substitute (XEXP (XEXP (orig, 0), 0))), copy_rtx_and_substitute (XEXP (orig, 1))); break; case PLUS: /* Note: the PLUS case is not nearly as careful as the MEM case in terms of preserving addresses. The reason for this is that it is expected that if a PLUS_EXPR turns out not to be a legitimate address, reload can fix that up, without doing major damage. However, a MEM rtx must preside over a legitimate address. The MEM case has lots of hair to deal with what happens when it sits on a PLUS... */ /* Take care of the easy case quickly. */ if (XEXP (orig, 0) == frame_pointer_rtx || XEXP (orig, 1) == frame_pointer_rtx || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM && (XEXP (orig, 0) == arg_pointer_rtx || XEXP (orig, 1) == arg_pointer_rtx))) { rtx reg; if (XEXP (orig, 0) == frame_pointer_rtx || XEXP (orig, 0) == arg_pointer_rtx) reg = XEXP (orig, 0), copy = XEXP (orig, 1); else reg = XEXP (orig, 1), copy = XEXP (orig, 0); if (GET_CODE (copy) == CONST_INT) { int c = INTVAL (copy); if (reg == arg_pointer_rtx && c >= first_parm_offset && (c / UNITS_PER_WORD) < parm_map_size) { copy = access_parm_map (c, VOIDmode); if (GET_CODE (copy) != MEM) /* Should not happen, because a parm we need to address should not be living in a register. (expand_inline_function copied it to a stack slot.) */ abort (); return XEXP (copy, 0); } return gen_rtx (PLUS, mode, frame_pointer_rtx, gen_rtx (CONST_INT, SImode, c + fp_delta)); } copy = copy_rtx_and_substitute (copy); temp = force_reg (mode, gen_rtx (PLUS, mode, frame_pointer_rtx, copy)); return plus_constant (temp, fp_delta); } else if (frame_pointer_sum_p (orig)) { /* If we have a complex sum which has a frame pointer in it, and it was a legitimate address, then keep it that way. */ if (memory_address_p (mode, orig)) { if (GET_CODE (XEXP (orig, 0)) == CONST_INT) { copy = copy_rtx_and_substitute (XEXP (orig, 1)); temp = plus_constant (copy, INTVAL (XEXP (orig, 0))); } else if (GET_CODE (XEXP (orig, 1)) == CONST_INT) { copy = copy_rtx_and_substitute (XEXP (orig, 0)); temp = plus_constant (copy, INTVAL (XEXP (orig, 1))); } else { temp = gen_rtx (PLUS, GET_MODE (orig), copy_rtx_and_substitute (XEXP (orig, 0)), copy_rtx_and_substitute (XEXP (orig, 1))); } temp = memory_address (mode, temp); } else temp = gen_rtx (PLUS, GET_MODE (orig), copy_rtx_and_substitute (XEXP (orig, 0)), copy_rtx_and_substitute (XEXP (orig, 1))); } else temp = gen_rtx (PLUS, GET_MODE (orig), copy_rtx_and_substitute (XEXP (orig, 0)), copy_rtx_and_substitute (XEXP (orig, 1))); return temp; case MEM: /* Take care of easiest case here. */ copy = XEXP (orig, 0); if (copy == frame_pointer_rtx || copy == arg_pointer_rtx) return gen_rtx (MEM, mode, plus_constant (frame_pointer_rtx, fp_delta)); /* Allow a pushing-address even if that is not valid as an ordinary memory address. It indicates we are inlining a special push-insn. These must be copied; otherwise unshare_all_rtl might clobber them to point at temporary rtl of this function. */#ifdef STACK_GROWS_DOWNWARD if (GET_CODE (copy) == PRE_DEC && XEXP (copy, 0) == stack_pointer_rtx) return gen_rtx (MEM, mode, copy_rtx_and_substitute (copy));#else if (GET_CODE (copy) == PRE_INC && XEXP (copy, 0) == stack_pointer_rtx) return gen_rtx (MEM, mode, copy_rtx_and_substitute (copy));#endif /* If this is some other sort of address that isn't generally valid, break out all the registers referred to. */ if (! memory_address_p (mode, copy)) return gen_rtx (MEM, mode, copy_address (copy)); if (GET_CODE (copy) == PLUS) { if (XEXP (copy, 0) == frame_pointer_rtx || XEXP (copy, 1) == frame_pointer_rtx || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM && (XEXP (copy, 0) == arg_pointer_rtx || XEXP (copy, 1) == arg_pointer_rtx))) { rtx reg; if (XEXP (copy, 0) == frame_pointer_rtx || XEXP (copy, 0) == arg_pointer_rtx) reg = XEXP (copy, 0), copy = XEXP (copy, 1); else reg = XEXP (copy, 1), copy = XEXP (copy, 0); if (GET_CODE (copy) == CONST_INT) { int c = INTVAL (copy); if (reg == arg_pointer_rtx && c >= first_parm_offset && (c / UNITS_PER_WORD) < parm_map_size) return access_parm_map (c, mode); temp = gen_rtx (PLUS, Pmode, frame_pointer_rtx, gen_rtx (CONST_INT, SImode, c + fp_delta)); if (! memory_address_p (Pmode, temp)) return gen_rtx (MEM, mode, plus_constant (inline_fp_rtx, c)); } copy = copy_rtx_and_substitute (copy); temp = gen_rtx (PLUS, Pmode, frame_pointer_rtx, copy); temp = plus_constant (temp, fp_delta); temp = memory_address (Pmode, temp); } else if (reg_mentioned_p (frame_pointer_rtx, copy) || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM && reg_mentioned_p (arg_pointer_rtx, copy))) { if (GET_CODE (XEXP (copy, 0)) == CONST_INT) { temp = copy_rtx_and_substitute (XEXP (copy, 1)); temp = plus_constant (temp, INTVAL (XEXP (copy, 0))); } else if (GET_CODE (XEXP (copy, 1)) == CONST_INT) { temp = copy_rtx_and_substitute (XEXP (copy, 0)); temp = plus_constant (temp, INTVAL (XEXP (copy, 1))); } else { temp = gen_rtx (PLUS, GET_MODE (copy), copy_rtx_and_substitute (XEXP (copy, 0)), copy_rtx_and_substitute (XEXP (copy, 1))); } } else { if (GET_CODE (XEXP (copy, 1)) == CONST_INT) temp = plus_constant (copy_rtx_and_substitute (XEXP (copy, 0)), INTVAL (XEXP (copy, 1))); else if (GET_CODE (XEXP (copy, 0)) == CONST_INT) temp = plus_constant (copy_rtx_and_substitute (XEXP (copy, 1)), INTVAL (XEXP (copy, 0))); else { rtx left = copy_rtx_and_substitute (XEXP (copy, 0)); rtx right = copy_rtx_and_substitute (XEXP (copy, 1)); temp = gen_rtx (PLUS, GET_MODE (copy), left, right); } } } else temp = copy_rtx_and_substitute (copy); /* Avoid change_address if we can, because it copies certain valid addresses into registers. And doing that on a memref that appears twice in the insn (with a match_dup) would lose. */ if (memory_address_p (mode, temp)) { rtx new = gen_rtx (MEM, mode, temp); MEM_VOLATILE_P (new) = MEM_VOLATILE_P (orig); RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (orig); MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (orig); return new; } /* I think this will never be reached. And I hope so, because if it is reached, that implies it can probably be reached for a memref that appears twice in one insn, and that would cause a crash. The clean thing to do would be to abort here, see if there is a bug, and fix it. But that would probably cause more errors in the short term, and long-term cleanups in GCC version 1 don't matter. */ return change_address (orig, mode, temp); case RETURN: abort (); } 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 (); } } if (code == ASM_OPERANDS && orig_asm_operands_vector == 0) { orig_asm_operands_vector = XVEC (orig, 3); copy_asm_operands_vector = XVEC (copy, 3); copy_asm_constraints_vector = XVEC (copy, 4); } return copy;}/* Get the value corresponding to an address relative to the arg pointer at index RELADDRESS. MODE is the machine mode of the reference. MODE is used only when the value is a REG. Pass VOIDmode for MODE when the mode is not known; in such cases, you should make sure the value is a MEM. */static rtxaccess_parm_map (reladdress, mode) int reladdress; enum machine_mode mode;{ /* Index in parm_map. */ int index = reladdress / UNITS_PER_WORD; /* Offset of the data being referenced from the beginning of the value for that parm. */ int offset = reladdress % UNITS_PER_WORD; rtx copy; /* If we are referring to the middle of a multiword parm, find the beginning of that parm. OFFSET gets the offset of the reference from the beginning of the parm. */ while (parm_map[index] == 0) { index--; if (index < first_parm_offset / UNITS_PER_WORD) /* If this abort happens, it means we need to handle "decrementing" INDEX back far enough to start looking among the reg parms instead of the stack parms. What a mess! */ abort (); offset += UNITS_PER_WORD; } copy = parm_map[index];#ifdef BYTES_BIG_ENDIAN /* Subtract from OFFSET the offset of where the actual parm value would start. */ if (GET_MODE_SIZE (GET_MODE (copy)) < UNITS_PER_WORD)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -