Commit 54c537e6 by Chung-Ju Wu Committed by Chung-Ju Wu

[NDS32] new attribute no_prologue and new option -mret-in-naked-func.

gcc/
	* config/nds32/nds32.c (nds32_attribute_table): Add "no_prologue".
	(nds32_init_machine_status): Initialize machine->attr_naked_p and
	machine->attr_no_prologue_p.
	(nds32_compute_stack_frame): Check "naked" and "no_prologue" attributes.
	(nds32_naked_function_p): Handle "naked" and "no_prologue" attributes.
	(nds32_expand_epilogue): Consider attr_naked_p.
	(nds32_expand_epilogue_v3pop): Likewise.
	(nds32_can_use_return_insn): Likewise.
	* config/nds32/nds32.h (machine_function): Add attr_naked_p and
	attr_no_prologue_p fields.
	* config/nds32/nds32.opt (mret-in-naked-func): New option.

From-SVN: r260803
parent 4cdb54ea
2018-05-27 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32.c (nds32_attribute_table): Add "no_prologue".
(nds32_init_machine_status): Initialize machine->attr_naked_p and
machine->attr_no_prologue_p.
(nds32_compute_stack_frame): Check "naked" and "no_prologue" attributes.
(nds32_naked_function_p): Handle "naked" and "no_prologue" attributes.
(nds32_expand_epilogue): Consider attr_naked_p.
(nds32_expand_epilogue_v3pop): Likewise.
(nds32_can_use_return_insn): Likewise.
* config/nds32/nds32.h (machine_function): Add attr_naked_p and
attr_no_prologue_p fields.
* config/nds32/nds32.opt (mret-in-naked-func): New option.
2018-05-27 Jakub Jelinek <jakub@redhat.com> 2018-05-27 Jakub Jelinek <jakub@redhat.com>
PR target/85918 PR target/85918
......
...@@ -320,6 +320,10 @@ static const struct attribute_spec nds32_attribute_table[] = ...@@ -320,6 +320,10 @@ static const struct attribute_spec nds32_attribute_table[] =
/* The attribute is used to tell this function to be ROM patch. */ /* The attribute is used to tell this function to be ROM patch. */
{ "indirect_call",0, 0, false, false, false, false, NULL, NULL }, { "indirect_call",0, 0, false, false, false, false, NULL, NULL },
/* FOR BACKWARD COMPATIBILITY,
this attribute also tells no prologue/epilogue. */
{ "no_prologue", 0, 0, false, false, false, false, NULL, NULL },
/* The last attribute spec is set to be NULL. */ /* The last attribute spec is set to be NULL. */
{ NULL, 0, 0, false, false, false, false, NULL, NULL } { NULL, 0, 0, false, false, false, false, NULL, NULL }
}; };
...@@ -348,6 +352,10 @@ nds32_init_machine_status (void) ...@@ -348,6 +352,10 @@ nds32_init_machine_status (void)
/* Initially this function is not under strictly aligned situation. */ /* Initially this function is not under strictly aligned situation. */
machine->strict_aligned_p = 0; machine->strict_aligned_p = 0;
/* Initially this function has no naked and no_prologue attributes. */
machine->attr_naked_p = 0;
machine->attr_no_prologue_p = 0;
return machine; return machine;
} }
...@@ -365,6 +373,15 @@ nds32_compute_stack_frame (void) ...@@ -365,6 +373,15 @@ nds32_compute_stack_frame (void)
needs prologue/epilogue. */ needs prologue/epilogue. */
cfun->machine->naked_p = 0; cfun->machine->naked_p = 0;
/* We need to mark whether this function has naked and no_prologue
attribute so that we can distinguish the difference if users applies
-mret-in-naked-func option. */
cfun->machine->attr_naked_p
= lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))
? 1 : 0;
cfun->machine->attr_no_prologue_p
= lookup_attribute ("no_prologue", DECL_ATTRIBUTES (current_function_decl))
? 1 : 0;
/* If __builtin_eh_return is used, we better have frame pointer needed /* If __builtin_eh_return is used, we better have frame pointer needed
so that we can easily locate the stack slot of return address. */ so that we can easily locate the stack slot of return address. */
...@@ -501,7 +518,7 @@ nds32_compute_stack_frame (void) ...@@ -501,7 +518,7 @@ nds32_compute_stack_frame (void)
} }
/* Check if this function can omit prologue/epilogue code fragment. /* Check if this function can omit prologue/epilogue code fragment.
If there is 'naked' attribute in this function, If there is 'no_prologue'/'naked' attribute in this function,
we can set 'naked_p' flag to indicate that we can set 'naked_p' flag to indicate that
we do not have to generate prologue/epilogue. we do not have to generate prologue/epilogue.
Or, if all the following conditions succeed, Or, if all the following conditions succeed,
...@@ -514,7 +531,8 @@ nds32_compute_stack_frame (void) ...@@ -514,7 +531,8 @@ nds32_compute_stack_frame (void)
is no outgoing size. is no outgoing size.
condition 3: There is no local_size, which means condition 3: There is no local_size, which means
we do not need to adjust $sp. */ we do not need to adjust $sp. */
if (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) if (lookup_attribute ("no_prologue", DECL_ATTRIBUTES (current_function_decl))
|| lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))
|| (cfun->machine->callee_saved_first_gpr_regno == SP_REGNUM || (cfun->machine->callee_saved_first_gpr_regno == SP_REGNUM
&& cfun->machine->callee_saved_last_gpr_regno == SP_REGNUM && cfun->machine->callee_saved_last_gpr_regno == SP_REGNUM
&& cfun->machine->callee_saved_first_fpr_regno == SP_REGNUM && cfun->machine->callee_saved_first_fpr_regno == SP_REGNUM
...@@ -1376,14 +1394,22 @@ nds32_needs_double_word_align (machine_mode mode, const_tree type) ...@@ -1376,14 +1394,22 @@ nds32_needs_double_word_align (machine_mode mode, const_tree type)
static bool static bool
nds32_naked_function_p (tree func) nds32_naked_function_p (tree func)
{ {
tree t; /* FOR BACKWARD COMPATIBILITY,
we need to support 'no_prologue' attribute as well. */
tree t_naked;
tree t_no_prologue;
if (TREE_CODE (func) != FUNCTION_DECL) if (TREE_CODE (func) != FUNCTION_DECL)
abort (); abort ();
t = lookup_attribute ("naked", DECL_ATTRIBUTES (func)); /* We have to use lookup_attribute() to check attributes.
Because attr_naked_p and attr_no_prologue_p are set in
nds32_compute_stack_frame() and the function has not been
invoked yet. */
t_naked = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
t_no_prologue = lookup_attribute ("no_prologue", DECL_ATTRIBUTES (func));
return (t != NULL_TREE); return ((t_naked != NULL_TREE) || (t_no_prologue != NULL_TREE));
} }
/* Function that determine whether a load postincrement is a good thing to use /* Function that determine whether a load postincrement is a good thing to use
...@@ -4719,7 +4745,16 @@ nds32_expand_epilogue (bool sibcall_p) ...@@ -4719,7 +4745,16 @@ nds32_expand_epilogue (bool sibcall_p)
/* Generate return instruction by using 'return_internal' pattern. /* Generate return instruction by using 'return_internal' pattern.
Make sure this instruction is after gen_blockage(). */ Make sure this instruction is after gen_blockage(). */
if (!sibcall_p) if (!sibcall_p)
emit_jump_insn (gen_return_internal ()); {
/* We need to further check attributes to determine whether
there should be return instruction at epilogue.
If the attribute naked exists but -mno-ret-in-naked-func
is issued, there is NO need to generate return instruction. */
if (cfun->machine->attr_naked_p && !flag_ret_in_naked_func)
return;
emit_jump_insn (gen_return_internal ());
}
return; return;
} }
...@@ -5075,9 +5110,19 @@ nds32_expand_epilogue_v3pop (bool sibcall_p) ...@@ -5075,9 +5110,19 @@ nds32_expand_epilogue_v3pop (bool sibcall_p)
if (cfun->machine->naked_p) if (cfun->machine->naked_p)
{ {
/* Generate return instruction by using 'return_internal' pattern. /* Generate return instruction by using 'return_internal' pattern.
Make sure this instruction is after gen_blockage(). */ Make sure this instruction is after gen_blockage().
First we need to check this is a function without sibling call. */
if (!sibcall_p) if (!sibcall_p)
emit_jump_insn (gen_return_internal ()); {
/* We need to further check attributes to determine whether
there should be return instruction at epilogue.
If the attribute naked exists but -mno-ret-in-naked-func
is issued, there is NO need to generate return instruction. */
if (cfun->machine->attr_naked_p && !flag_ret_in_naked_func)
return;
emit_jump_insn (gen_return_internal ());
}
return; return;
} }
...@@ -5241,6 +5286,11 @@ nds32_can_use_return_insn (void) ...@@ -5241,6 +5286,11 @@ nds32_can_use_return_insn (void)
if (!reload_completed) if (!reload_completed)
return 0; return 0;
/* If attribute 'naked' appears but -mno-ret-in-naked-func is used,
we cannot use return instruction. */
if (cfun->machine->attr_naked_p && !flag_ret_in_naked_func)
return 0;
sp_adjust = cfun->machine->local_size sp_adjust = cfun->machine->local_size
+ cfun->machine->out_args_size + cfun->machine->out_args_size
+ cfun->machine->callee_saved_area_gpr_padding_bytes + cfun->machine->callee_saved_area_gpr_padding_bytes
......
...@@ -318,6 +318,10 @@ struct GTY(()) machine_function ...@@ -318,6 +318,10 @@ struct GTY(()) machine_function
2. The rtl lowering and optimization are close to target code. 2. The rtl lowering and optimization are close to target code.
For this case we need address to be strictly aligned. */ For this case we need address to be strictly aligned. */
int strict_aligned_p; int strict_aligned_p;
/* Record two similar attributes status. */
int attr_naked_p;
int attr_no_prologue_p;
}; };
/* A C structure that contains the arguments information. */ /* A C structure that contains the arguments information. */
......
...@@ -439,6 +439,10 @@ mforce-no-ext-dsp ...@@ -439,6 +439,10 @@ mforce-no-ext-dsp
Target Undocumented Report Mask(FORCE_NO_EXT_DSP) Target Undocumented Report Mask(FORCE_NO_EXT_DSP)
Force disable hardware loop, even use -mext-dsp. Force disable hardware loop, even use -mext-dsp.
mret-in-naked-func
Target Var(flag_ret_in_naked_func) Init(1)
Generate return instruction in naked function.
malways-save-lp malways-save-lp
Target Var(flag_always_save_lp) Init(0) Target Var(flag_always_save_lp) Init(0)
Always save $lp in the stack. Always save $lp in the stack.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment