📄 ia64.c
字号:
with the POST_DEC below, but it's nice to not use it when we can immediately tell it's not necessary. */ addr_dead_p = ((noreturn_p || sibcall_p || TEST_HARD_REG_BIT (regs_invalidated_by_call, REGNO (addr))) && !FUNCTION_ARG_REGNO_P (REGNO (addr))); /* Load the code address into scratch_b. */ tmp = gen_rtx_POST_INC (Pmode, addr); tmp = gen_rtx_MEM (Pmode, tmp); emit_move_insn (scratch_r, tmp); emit_move_insn (scratch_b, scratch_r); /* Load the GP address. If ADDR is not dead here, then we must revert the change made above via the POST_INCREMENT. */ if (!addr_dead_p) tmp = gen_rtx_POST_DEC (Pmode, addr); else tmp = addr; tmp = gen_rtx_MEM (Pmode, tmp); emit_move_insn (pic_offset_table_rtx, tmp); is_desc = true; addr = scratch_b; } if (sibcall_p) insn = gen_sibcall_nogp (addr); else if (retval) insn = gen_call_value_nogp (retval, addr, retaddr); else insn = gen_call_nogp (addr, retaddr); emit_call_insn (insn); if ((!TARGET_CONST_GP || is_desc) && !noreturn_p && !sibcall_p) ia64_reload_gp ();}/* Begin the assembly file. */static voidia64_file_start (void){ /* Variable tracking should be run after all optimizations which change order of insns. It also needs a valid CFG. This can't be done in ia64_override_options, because flag_var_tracking is finallized after that. */ ia64_flag_var_tracking = flag_var_tracking; flag_var_tracking = 0; default_file_start (); emit_safe_across_calls ();}voidemit_safe_across_calls (void){ unsigned int rs, re; int out_state; rs = 1; out_state = 0; while (1) { while (rs < 64 && call_used_regs[PR_REG (rs)]) rs++; if (rs >= 64) break; for (re = rs + 1; re < 64 && ! call_used_regs[PR_REG (re)]; re++) continue; if (out_state == 0) { fputs ("\t.pred.safe_across_calls ", asm_out_file); out_state = 1; } else fputc (',', asm_out_file); if (re == rs + 1) fprintf (asm_out_file, "p%u", rs); else fprintf (asm_out_file, "p%u-p%u", rs, re - 1); rs = re + 1; } if (out_state) fputc ('\n', asm_out_file);}/* Helper function for ia64_compute_frame_size: find an appropriate general register to spill some special register to. SPECIAL_SPILL_MASK contains bits in GR0 to GR31 that have already been allocated by this routine. TRY_LOCALS is true if we should attempt to locate a local regnum. */static intfind_gr_spill (int try_locals){ int regno; /* If this is a leaf function, first try an otherwise unused call-clobbered register. */ if (current_function_is_leaf) { for (regno = GR_REG (1); regno <= GR_REG (31); regno++) if (! regs_ever_live[regno] && call_used_regs[regno] && ! fixed_regs[regno] && ! global_regs[regno] && ((current_frame_info.gr_used_mask >> regno) & 1) == 0) { current_frame_info.gr_used_mask |= 1 << regno; return regno; } } if (try_locals) { regno = current_frame_info.n_local_regs; /* If there is a frame pointer, then we can't use loc79, because that is HARD_FRAME_POINTER_REGNUM. In particular, see the reg_name switching code in ia64_expand_prologue. */ if (regno < (80 - frame_pointer_needed)) { current_frame_info.n_local_regs = regno + 1; return LOC_REG (0) + regno; } } /* Failed to find a general register to spill to. Must use stack. */ return 0;}/* In order to make for nice schedules, we try to allocate every temporary to a different register. We must of course stay away from call-saved, fixed, and global registers. We must also stay away from registers allocated in current_frame_info.gr_used_mask, since those include regs used all through the prologue. Any register allocated here must be used immediately. The idea is to aid scheduling, not to solve data flow problems. */static int last_scratch_gr_reg;static intnext_scratch_gr_reg (void){ int i, regno; for (i = 0; i < 32; ++i) { regno = (last_scratch_gr_reg + i + 1) & 31; if (call_used_regs[regno] && ! fixed_regs[regno] && ! global_regs[regno] && ((current_frame_info.gr_used_mask >> regno) & 1) == 0) { last_scratch_gr_reg = regno; return regno; } } /* There must be _something_ available. */ abort ();}/* Helper function for ia64_compute_frame_size, called through diddle_return_value. Mark REG in current_frame_info.gr_used_mask. */static voidmark_reg_gr_used_mask (rtx reg, void *data ATTRIBUTE_UNUSED){ unsigned int regno = REGNO (reg); if (regno < 32) { unsigned int i, n = HARD_REGNO_NREGS (regno, GET_MODE (reg)); for (i = 0; i < n; ++i) current_frame_info.gr_used_mask |= 1 << (regno + i); }}/* Returns the number of bytes offset between the frame pointer and the stack pointer for the current function. SIZE is the number of bytes of space needed for local variables. */static voidia64_compute_frame_size (HOST_WIDE_INT size){ HOST_WIDE_INT total_size; HOST_WIDE_INT spill_size = 0; HOST_WIDE_INT extra_spill_size = 0; HOST_WIDE_INT pretend_args_size; HARD_REG_SET mask; int n_spilled = 0; int spilled_gr_p = 0; int spilled_fr_p = 0; unsigned int regno; int i; if (current_frame_info.initialized) return; memset (¤t_frame_info, 0, sizeof current_frame_info); CLEAR_HARD_REG_SET (mask); /* Don't allocate scratches to the return register. */ diddle_return_value (mark_reg_gr_used_mask, NULL); /* Don't allocate scratches to the EH scratch registers. */ if (cfun->machine->ia64_eh_epilogue_sp) mark_reg_gr_used_mask (cfun->machine->ia64_eh_epilogue_sp, NULL); if (cfun->machine->ia64_eh_epilogue_bsp) mark_reg_gr_used_mask (cfun->machine->ia64_eh_epilogue_bsp, NULL); /* Find the size of the register stack frame. We have only 80 local registers, because we reserve 8 for the inputs and 8 for the outputs. */ /* Skip HARD_FRAME_POINTER_REGNUM (loc79) when frame_pointer_needed, since we'll be adjusting that down later. */ regno = LOC_REG (78) + ! frame_pointer_needed; for (; regno >= LOC_REG (0); regno--) if (regs_ever_live[regno]) break; current_frame_info.n_local_regs = regno - LOC_REG (0) + 1; /* For functions marked with the syscall_linkage attribute, we must mark all eight input registers as in use, so that locals aren't visible to the caller. */ if (cfun->machine->n_varargs > 0 || lookup_attribute ("syscall_linkage", TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) current_frame_info.n_input_regs = 8; else { for (regno = IN_REG (7); regno >= IN_REG (0); regno--) if (regs_ever_live[regno]) break; current_frame_info.n_input_regs = regno - IN_REG (0) + 1; } for (regno = OUT_REG (7); regno >= OUT_REG (0); regno--) if (regs_ever_live[regno]) break; i = regno - OUT_REG (0) + 1; /* When -p profiling, we need one output register for the mcount argument. Likewise for -a profiling for the bb_init_func argument. For -ax profiling, we need two output registers for the two bb_init_trace_func arguments. */ if (current_function_profile) i = MAX (i, 1); current_frame_info.n_output_regs = i; /* ??? No rotating register support yet. */ current_frame_info.n_rotate_regs = 0; /* Discover which registers need spilling, and how much room that will take. Begin with floating point and general registers, which will always wind up on the stack. */ for (regno = FR_REG (2); regno <= FR_REG (127); regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) { SET_HARD_REG_BIT (mask, regno); spill_size += 16; n_spilled += 1; spilled_fr_p = 1; } for (regno = GR_REG (1); regno <= GR_REG (31); regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) { SET_HARD_REG_BIT (mask, regno); spill_size += 8; n_spilled += 1; spilled_gr_p = 1; } for (regno = BR_REG (1); regno <= BR_REG (7); regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) { SET_HARD_REG_BIT (mask, regno); spill_size += 8; n_spilled += 1; } /* Now come all special registers that might get saved in other general registers. */ if (frame_pointer_needed) { current_frame_info.reg_fp = find_gr_spill (1); /* If we did not get a register, then we take LOC79. This is guaranteed to be free, even if regs_ever_live is already set, because this is HARD_FRAME_POINTER_REGNUM. This requires incrementing n_local_regs, as we don't count loc79 above. */ if (current_frame_info.reg_fp == 0) { current_frame_info.reg_fp = LOC_REG (79); current_frame_info.n_local_regs++; } } if (! current_function_is_leaf) { /* Emit a save of BR0 if we call other functions. Do this even if this function doesn't return, as EH depends on this to be able to unwind the stack. */ SET_HARD_REG_BIT (mask, BR_REG (0)); current_frame_info.reg_save_b0 = find_gr_spill (1); if (current_frame_info.reg_save_b0 == 0) { spill_size += 8; n_spilled += 1; } /* Similarly for ar.pfs. */ SET_HARD_REG_BIT (mask, AR_PFS_REGNUM); current_frame_info.reg_save_ar_pfs = find_gr_spill (1); if (current_frame_info.reg_save_ar_pfs == 0) { extra_spill_size += 8; n_spilled += 1; } /* Similarly for gp. Note that if we're calling setjmp, the stacked registers are clobbered, so we fall back to the stack. */ current_frame_info.reg_save_gp = (current_function_calls_setjmp ? 0 : find_gr_spill (1)); if (current_frame_info.reg_save_gp == 0) { SET_HARD_REG_BIT (mask, GR_REG (1)); spill_size += 8; n_spilled += 1; } } else { if (regs_ever_live[BR_REG (0)] && ! call_used_regs[BR_REG (0)]) { SET_HARD_REG_BIT (mask, BR_REG (0)); spill_size += 8; n_spilled += 1; } if (regs_ever_live[AR_PFS_REGNUM]) { SET_HARD_REG_BIT (mask, AR_PFS_REGNUM); current_frame_info.reg_save_ar_pfs = find_gr_spill (1); if (current_frame_info.reg_save_ar_pfs == 0) { extra_spill_size += 8; n_spilled += 1; } } } /* Unwind descriptor hackery: things are most efficient if we allocate consecutive GR save registers for RP, PFS, FP in that order. However, it is absolutely critical that FP get the only hard register that's guaranteed to be free, so we allocated it first. If all three did happen to be allocated hard regs, and are consecutive, rearrange them into the preferred order now. */ if (current_frame_info.reg_fp != 0 && current_frame_info.reg_save_b0 == current_frame_info.reg_fp + 1 && current_frame_info.reg_save_ar_pfs == current_frame_info.reg_fp + 2) { current_frame_info.reg_save_b0 = current_frame_info.reg_fp; current_frame_info.reg_save_ar_pfs = current_frame_info.reg_fp + 1; current_frame_info.reg_fp = current_frame_info.reg_fp + 2; } /* See if we need to store the predicate register block. */ for (regno = PR_REG (0); regno <= PR_REG (63); regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) break; if (regno <= PR_REG (63)) { SET_HARD_REG_BIT (mask, PR_REG (0)); current_frame_info.reg_save_pr = find_gr_spill (1); if (current_frame_info.reg_save_pr == 0) { extra_spill_size += 8; n_spilled += 1; } /* ??? Mark them all as used so that register renaming and such are free to use them. */ for (regno = PR_REG (0); regno <= PR_REG (63); regno++) regs_ever_live[regno] = 1; } /* If we're forced to use st8.spill, we're forced to save and restore ar.unat as well. The check for existing liveness allows inline asm to touch ar.unat. */ if (spilled_gr_p || cfun->machine->n_varargs || regs_ever_live[AR_UNAT_REGNUM]) { regs_ever_live[AR_UNAT_REGNUM] = 1; SET_HARD_REG_BIT (mask, AR_UNAT_REGNUM); current_frame_info.reg_save_ar_unat = find_gr_spill (spill_size == 0); if (current_frame_info.reg_save_ar_unat == 0) { extra_spill_size += 8; n_spilled += 1; } } if (regs_ever_live[AR_LC_REGNUM]) { SET_HARD_REG_BIT (mask, AR_LC_REGNUM); current_frame_info.reg_save_ar_lc = find_gr_spill (spill_size == 0); if (current_frame_info.reg_save_ar_lc == 0) { extra_spill_size += 8; n_spilled += 1; } } /* If we have an odd number of words of pretend arguments written to the stack, then the FR save area will be unaligned. We round the size of this area up to keep things 16 byte aligned. */ if (spilled_fr_p) pretend_args_size = IA64_STACK_ALIGN (current_function_pretend_args_size); else pretend_args_size = current_function_pretend_args_size; total_size = (spill_size + extra_spill_size + size + pretend_args_size + current_function_outgoing_args_size); total_size = IA64_STACK_ALIGN (total_size); /* We always use the 16
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -