expand_builtin_longjmp and expand_builtin_nonlocal_goto both emit nonlocal gotos. They first try to use a target-provided pattern and fall back to generic code otherwise. These pieces of generic code are almost identical, and having them inline like this makes it difficult to define a nonlocal_goto pattern that only wants to add extra steps, not change the default ones.
Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? Richard gcc/ * builtins.h (emit_standard_nonlocal_goto): Declare. * builtins.cc (emit_standard_nonlocal_goto): New function, commonizing code from... (expand_builtin_longjmp, expand_builtin_nonlocal_goto): ...here. * genemit.cc (main): Emit an include of builtins.h. --- gcc/builtins.cc | 103 +++++++++++++++++++++--------------------------- gcc/builtins.h | 1 + gcc/genemit.cc | 1 + 3 files changed, 47 insertions(+), 58 deletions(-) diff --git a/gcc/builtins.cc b/gcc/builtins.cc index 4dc1ca672b2..2507745c17a 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -998,6 +998,49 @@ expand_builtin_setjmp_receiver (rtx receiver_label) emit_insn (gen_blockage ()); } +/* Emit the standard sequence for a nonlocal_goto. The arguments are + the operands to the .md pattern. */ + +void +emit_standard_nonlocal_goto (rtx value, rtx label, rtx stack, rtx fp) +{ + emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); + emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); + + label = copy_to_reg (label); + + /* Restore the frame pointer and stack pointer. We must use a + temporary since the setjmp buffer may be a local. */ + fp = copy_to_reg (fp); + emit_stack_restore (SAVE_NONLOCAL, stack); + + /* Ensure the frame pointer move is not optimized. */ + emit_insn (gen_blockage ()); + emit_clobber (hard_frame_pointer_rtx); + emit_clobber (frame_pointer_rtx); + emit_move_insn (hard_frame_pointer_rtx, fp); + + /* USE of hard_frame_pointer_rtx added for consistency; + not clear if really needed. */ + emit_use (hard_frame_pointer_rtx); + emit_use (stack_pointer_rtx); + + /* If the architecture is using a GP register, we must + conservatively assume that the target function makes use of it. + The prologue of functions with nonlocal gotos must therefore + initialize the GP register to the appropriate value, and we + must then make sure that this value is live at the point + of the jump. (Note that this doesn't necessarily apply + to targets with a nonlocal_goto pattern; they are free + to implement it in their own way. Note also that this is + a no-op if the GP register is a global invariant.) */ + unsigned regnum = PIC_OFFSET_TABLE_REGNUM; + if (value == const0_rtx && regnum != INVALID_REGNUM && fixed_regs[regnum]) + emit_use (pic_offset_table_rtx); + + emit_indirect_jump (label); +} + /* __builtin_longjmp is passed a pointer to an array of five words (not all will be used on all machines). It operates similarly to the C library function of the same name, but is more efficient. Much of @@ -1049,27 +1092,7 @@ expand_builtin_longjmp (rtx buf_addr, rtx value) what that value is, because builtin_setjmp does not use it. */ emit_insn (targetm.gen_nonlocal_goto (value, lab, stack, fp)); else - { - emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); - emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); - - lab = copy_to_reg (lab); - - /* Restore the frame pointer and stack pointer. We must use a - temporary since the setjmp buffer may be a local. */ - fp = copy_to_reg (fp); - emit_stack_restore (SAVE_NONLOCAL, stack); - - /* Ensure the frame pointer move is not optimized. */ - emit_insn (gen_blockage ()); - emit_clobber (hard_frame_pointer_rtx); - emit_clobber (frame_pointer_rtx); - emit_move_insn (hard_frame_pointer_rtx, fp); - - emit_use (hard_frame_pointer_rtx); - emit_use (stack_pointer_rtx); - emit_indirect_jump (lab); - } + emit_standard_nonlocal_goto (value, lab, stack, fp); } /* Search backwards and mark the jump insn as a non-local goto. @@ -1201,43 +1224,7 @@ expand_builtin_nonlocal_goto (tree exp) if (targetm.have_nonlocal_goto ()) emit_insn (targetm.gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp)); else - { - emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); - emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); - - r_label = copy_to_reg (r_label); - - /* Restore the frame pointer and stack pointer. We must use a - temporary since the setjmp buffer may be a local. */ - r_fp = copy_to_reg (r_fp); - emit_stack_restore (SAVE_NONLOCAL, r_sp); - - /* Ensure the frame pointer move is not optimized. */ - emit_insn (gen_blockage ()); - emit_clobber (hard_frame_pointer_rtx); - emit_clobber (frame_pointer_rtx); - emit_move_insn (hard_frame_pointer_rtx, r_fp); - - /* USE of hard_frame_pointer_rtx added for consistency; - not clear if really needed. */ - emit_use (hard_frame_pointer_rtx); - emit_use (stack_pointer_rtx); - - /* If the architecture is using a GP register, we must - conservatively assume that the target function makes use of it. - The prologue of functions with nonlocal gotos must therefore - initialize the GP register to the appropriate value, and we - must then make sure that this value is live at the point - of the jump. (Note that this doesn't necessarily apply - to targets with a nonlocal_goto pattern; they are free - to implement it in their own way. Note also that this is - a no-op if the GP register is a global invariant.) */ - unsigned regnum = PIC_OFFSET_TABLE_REGNUM; - if (regnum != INVALID_REGNUM && fixed_regs[regnum]) - emit_use (pic_offset_table_rtx); - - emit_indirect_jump (r_label); - } + emit_standard_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp); /* Search backwards to the jump insn and mark it as a non-local goto. */ diff --git a/gcc/builtins.h b/gcc/builtins.h index 5ad830c9fbf..5c86b241fea 100644 --- a/gcc/builtins.h +++ b/gcc/builtins.h @@ -150,6 +150,7 @@ extern char target_percent_c[3]; extern char target_percent_s_newline[4]; extern bool target_char_cst_p (tree t, char *p); extern rtx get_memory_rtx (tree exp, tree len); +extern void emit_standard_nonlocal_goto (rtx, rtx, rtx, rtx); extern internal_fn associated_internal_fn (combined_fn, tree); extern internal_fn associated_internal_fn (tree); diff --git a/gcc/genemit.cc b/gcc/genemit.cc index 909ac89a16b..c3e2152a491 100644 --- a/gcc/genemit.cc +++ b/gcc/genemit.cc @@ -905,6 +905,7 @@ from the machine description file `md'. */\n\n"); printf ("#include \"tm-constrs.h\"\n"); printf ("#include \"ggc.h\"\n"); printf ("#include \"target.h\"\n\n"); + printf ("#include \"builtins.h\"\n\n"); /* Read the machine description. */ -- 2.25.1