Commit 8528f27b by Kito Cheng Committed by Jim Wilson

RISC-V: Error if function declared with different interrupt modes.

	gcc/
	2018-07-06  Kito Cheng  <kito.cheng@gmail.com>
        * config/riscv/riscv.c (enum riscv_privilege_levels): Add UNKNOWN_MODE.
        (riscv_expand_epilogue): Add assertion to check interrupt mode.
        (riscv_set_current_function): Extract getting interrupt type to new
        function.
        (riscv_get_interrupt_type): New function.
        (riscv_merge_decl_attributes): New function, checking interrupt type is
        same.
        (TARGET_MERGE_DECL_ATTRIBUTES): Define.

	gcc/testsuite/
	2018-07-06  Kito Cheng  <kito.cheng@gmail.com>
        * gcc.target/riscv/interrupt-conflict-mode.c: New.

From-SVN: r262607
parent 9b452033
2018-07-12 Kito Cheng <kito.cheng@gmail.com>
* config/riscv/riscv.c (enum riscv_privilege_levels): Add UNKNOWN_MODE.
(riscv_expand_epilogue): Add assertion to check interrupt mode.
(riscv_set_current_function): Extract getting interrupt type to new
function.
(riscv_get_interrupt_type): New function.
(riscv_merge_decl_attributes): New function, checking interrupt type is
same.
(TARGET_MERGE_DECL_ATTRIBUTES): Define.
2018-07-12 Paul Koning <ni1d@arrl.net> 2018-07-12 Paul Koning <ni1d@arrl.net>
* config/pdp11/pdp11.c (pdp11_output_def): Fix typo in .set * config/pdp11/pdp11.c (pdp11_output_def): Fix typo in .set
......
...@@ -123,7 +123,7 @@ struct GTY(()) riscv_frame_info { ...@@ -123,7 +123,7 @@ struct GTY(()) riscv_frame_info {
}; };
enum riscv_privilege_levels { enum riscv_privilege_levels {
USER_MODE, SUPERVISOR_MODE, MACHINE_MODE UNKNOWN_MODE, USER_MODE, SUPERVISOR_MODE, MACHINE_MODE
}; };
struct GTY(()) machine_function { struct GTY(()) machine_function {
...@@ -3984,6 +3984,8 @@ riscv_expand_epilogue (int style) ...@@ -3984,6 +3984,8 @@ riscv_expand_epilogue (int style)
{ {
enum riscv_privilege_levels mode = cfun->machine->interrupt_mode; enum riscv_privilege_levels mode = cfun->machine->interrupt_mode;
gcc_assert (mode != UNKNOWN_MODE);
if (mode == MACHINE_MODE) if (mode == MACHINE_MODE)
emit_jump_insn (gen_riscv_mret ()); emit_jump_insn (gen_riscv_mret ());
else if (mode == SUPERVISOR_MODE) else if (mode == SUPERVISOR_MODE)
...@@ -4530,6 +4532,37 @@ riscv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, ...@@ -4530,6 +4532,37 @@ riscv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
return true; return true;
} }
/* Get the intterupt type, return UNKNOWN_MODE if it's not
interrupt function. */
static enum riscv_privilege_levels
riscv_get_interrupt_type (tree decl)
{
gcc_assert (decl != NULL_TREE);
if ((TREE_CODE(decl) != FUNCTION_DECL)
|| (!riscv_interrupt_type_p (TREE_TYPE (decl))))
return UNKNOWN_MODE;
tree attr_args
= TREE_VALUE (lookup_attribute ("interrupt",
TYPE_ATTRIBUTES (TREE_TYPE (decl))));
if (attr_args && TREE_CODE (TREE_VALUE (attr_args)) != VOID_TYPE)
{
const char *string = TREE_STRING_POINTER (TREE_VALUE (attr_args));
if (!strcmp (string, "user"))
return USER_MODE;
else if (!strcmp (string, "supervisor"))
return SUPERVISOR_MODE;
else /* Must be "machine". */
return MACHINE_MODE;
}
else
/* Interrupt attributes are machine mode by default. */
return MACHINE_MODE;
}
/* Implement `TARGET_SET_CURRENT_FUNCTION'. */ /* Implement `TARGET_SET_CURRENT_FUNCTION'. */
/* Sanity cheching for above function attributes. */ /* Sanity cheching for above function attributes. */
static void static void
...@@ -4554,9 +4587,6 @@ riscv_set_current_function (tree decl) ...@@ -4554,9 +4587,6 @@ riscv_set_current_function (tree decl)
{ {
tree ret = TREE_TYPE (TREE_TYPE (decl)); tree ret = TREE_TYPE (TREE_TYPE (decl));
tree args = TYPE_ARG_TYPES (TREE_TYPE (decl)); tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree attr_args
= TREE_VALUE (lookup_attribute ("interrupt",
TYPE_ATTRIBUTES (TREE_TYPE (decl))));
if (TREE_CODE (ret) != VOID_TYPE) if (TREE_CODE (ret) != VOID_TYPE)
error ("%qs function cannot return a value", "interrupt"); error ("%qs function cannot return a value", "interrupt");
...@@ -4564,26 +4594,39 @@ riscv_set_current_function (tree decl) ...@@ -4564,26 +4594,39 @@ riscv_set_current_function (tree decl)
if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE) if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
error ("%qs function cannot have arguments", "interrupt"); error ("%qs function cannot have arguments", "interrupt");
if (attr_args && TREE_CODE (TREE_VALUE (attr_args)) != VOID_TYPE) cfun->machine->interrupt_mode = riscv_get_interrupt_type (decl);
{
const char *string = TREE_STRING_POINTER (TREE_VALUE (attr_args)); gcc_assert (cfun->machine->interrupt_mode != UNKNOWN_MODE);
if (!strcmp (string, "user"))
cfun->machine->interrupt_mode = USER_MODE;
else if (!strcmp (string, "supervisor"))
cfun->machine->interrupt_mode = SUPERVISOR_MODE;
else /* Must be "machine". */
cfun->machine->interrupt_mode = MACHINE_MODE;
}
else
/* Interrupt attributes are machine mode by default. */
cfun->machine->interrupt_mode = MACHINE_MODE;
} }
/* Don't print the above diagnostics more than once. */ /* Don't print the above diagnostics more than once. */
cfun->machine->attributes_checked_p = 1; cfun->machine->attributes_checked_p = 1;
} }
/* Implement TARGET_MERGE_DECL_ATTRIBUTES. */
static tree
riscv_merge_decl_attributes (tree olddecl, tree newdecl)
{
tree combined_attrs;
enum riscv_privilege_levels old_interrupt_type
= riscv_get_interrupt_type (olddecl);
enum riscv_privilege_levels new_interrupt_type
= riscv_get_interrupt_type (newdecl);
/* Check old and new has same interrupt type. */
if ((old_interrupt_type != UNKNOWN_MODE)
&& (new_interrupt_type != UNKNOWN_MODE)
&& (old_interrupt_type != new_interrupt_type))
error ("%qs function cannot have different intterupt type.", "interrupt");
/* Create combined attributes. */
combined_attrs = merge_attributes (DECL_ATTRIBUTES (olddecl),
DECL_ATTRIBUTES (newdecl));
return combined_attrs;
}
/* Implement TARGET_CANNOT_COPY_INSN_P. */ /* Implement TARGET_CANNOT_COPY_INSN_P. */
static bool static bool
...@@ -4780,6 +4823,9 @@ riscv_constant_alignment (const_tree exp, HOST_WIDE_INT align) ...@@ -4780,6 +4823,9 @@ riscv_constant_alignment (const_tree exp, HOST_WIDE_INT align)
#undef TARGET_CONSTANT_ALIGNMENT #undef TARGET_CONSTANT_ALIGNMENT
#define TARGET_CONSTANT_ALIGNMENT riscv_constant_alignment #define TARGET_CONSTANT_ALIGNMENT riscv_constant_alignment
#undef TARGET_MERGE_DECL_ATTRIBUTES
#define TARGET_MERGE_DECL_ATTRIBUTES riscv_merge_decl_attributes
#undef TARGET_ATTRIBUTE_TABLE #undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE riscv_attribute_table #define TARGET_ATTRIBUTE_TABLE riscv_attribute_table
......
2018-07-12 Kito Cheng <kito.cheng@gmail.com>
* gcc.target/riscv/interrupt-conflict-mode.c: New.
2018-07-12 Jakub Jelinek <jakub@redhat.com> 2018-07-12 Jakub Jelinek <jakub@redhat.com>
* c-c++-common/gomp/declare-target-3.c: New test. * c-c++-common/gomp/declare-target-3.c: New test.
......
/* Verify proper errors are generated for conflicted interrupt type. */
/* { dg-do compile } */
/* { dg-options "-O" } */
void __attribute__ ((interrupt ("user")))
foo(void);
void __attribute__ ((interrupt ("machine")))
foo (void)
{ /* { dg-error "function cannot have different intterupt type." } */
}
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