diff mbox

[ARM] attribute target (thumb,arm) [6/6] respin (4th)

Message ID 554A253A.4080905@st.com
State New
Headers show

Commit Message

Christian Bruel May 6, 2015, 2:29 p.m. UTC
Implement the -mflip-thump option. Undocumented for internal testing
only. This option artificially inserts alternative attribute thumb/modes
on functions.

This close the patch set. Thanks for your review,

Christian
diff mbox

Patch

2014-09-23  Christian Bruel  <christian.bruel@st.com>

	* config/arm/arm.c (add_attribute, arm_insert_attributes): New functions
	(TARGET_INSERT_ATTRIBUTES): Define.
	(thumb_flipper): New var.
	* config/arm/arm.opt (-mflip-thumb): New switch.

diff '--exclude=.svn' -ruN gnu_trunk.p5/gcc/gcc/config/arm/arm.c gnu_trunk.p6/gcc/gcc/config/arm/arm.c
--- gnu_trunk.p5/gcc/gcc/config/arm/arm.c	2015-05-06 15:03:29.393992051 +0200
+++ gnu_trunk.p6/gcc/gcc/config/arm/arm.c	2015-05-06 15:04:15.970072133 +0200
@@ -99,6 +99,7 @@ 
 #include "tm-constrs.h"
 #include "rtl-iter.h"
 #include "sched-int.h"
+#include "tree.h"
 
 /* Forward definitions of types.  */
 typedef struct minipool_node    Mnode;
@@ -232,6 +233,7 @@ 
 
 static void arm_file_end (void);
 static void arm_file_start (void);
+static void arm_insert_attributes (tree, tree *);
 
 static void arm_setup_incoming_varargs (cumulative_args_t, machine_mode,
 					tree, int *, int);
@@ -390,6 +392,9 @@ 
 #undef  TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE arm_attribute_table
 
+#undef  TARGET_INSERT_ATTRIBUTES
+#define TARGET_INSERT_ATTRIBUTES arm_insert_attributes
+
 #undef TARGET_ASM_FILE_START
 #define TARGET_ASM_FILE_START arm_file_start
 #undef TARGET_ASM_FILE_END
@@ -2763,6 +2768,10 @@ 
     }
 }
 
+/* True if -mflip-thumb should next add an attribute for the default
+   mode, false if it should next add an attribute for the opposite mode.  */
+static GTY(()) bool thumb_flipper;
+
 /* Options after initial target override.  */
 static GTY(()) tree init_optimize;
 
@@ -3329,6 +3338,9 @@ 
      options.  */
   target_option_default_node = target_option_current_node
     = build_target_option_node (&global_options);
+
+  /* Init initial mode for testing.  */
+  thumb_flipper = TARGET_THUMB;
 }
 
 static void
@@ -29459,6 +29471,52 @@ 
   return build_target_option_node (opts);
 }
 
+static void 
+add_attribute  (const char * mode, tree *attributes)
+{
+  size_t len = strlen (mode);
+  tree value = build_string (len, mode);
+
+  TREE_TYPE (value) = build_array_type (char_type_node,
+					build_index_type (size_int (len)));
+
+  *attributes = tree_cons (get_identifier ("target"),
+			   build_tree_list (NULL_TREE, value),
+			   *attributes);
+}
+
+/* For testing. Insert thumb or arm modes alternatively on functions.  */
+
+static void
+arm_insert_attributes (tree fndecl, tree * attributes)
+{
+  const char *mode;
+
+  if (! TARGET_FLIP_THUMB)
+    return;
+
+  if (TREE_CODE (fndecl) != FUNCTION_DECL || DECL_EXTERNAL(fndecl)
+      || DECL_BUILT_IN (fndecl) || DECL_ARTIFICIAL (fndecl))
+   return;
+
+  /* Nested definitions must inherit mode.  */
+  if (current_function_decl)
+   {
+     mode = TARGET_THUMB ? "thumb" : "arm";      
+     add_attribute (mode, attributes);
+     return;
+   }
+
+  /* If there is already a setting don't change it.  */
+  if (lookup_attribute ("target", *attributes) != NULL)
+    return;
+
+  mode = thumb_flipper ? "thumb" : "arm";
+  add_attribute (mode, attributes);
+
+  thumb_flipper = !thumb_flipper;
+}
+
 /* Hook to validate attribute((target("string"))).  */
 
 static bool
@@ -29470,13 +29528,15 @@ 
   tree cur_tree, new_optimize;
   gcc_assert ((fndecl != NULL_TREE) && (args != NULL_TREE));
 
+  tree old_optimize = build_optimization_node (&global_options);
+
   /* Get the optimization options of the current function.  */
   tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
 
   /* If the function changed the optimization levels as well as setting target
      options, start with the optimizations specified.  */
   if (!func_optimize)
-    func_optimize = optimization_default_node;
+    func_optimize = old_optimize;
 
   /* Init func_options.  */
   memset (&func_options, 0, sizeof (func_options));
@@ -29494,14 +29554,17 @@ 
   cur_tree = arm_valid_target_attribute_tree (args, &func_options,
 					      &global_options_set);
 
-  if (cur_tree == NULL_TREE)
-    ret = false;
-
   new_optimize = build_optimization_node (&func_options);
 
-  DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = cur_tree;
+  if (cur_tree == NULL_TREE)
+    ret = false;
+  else
+    {
+      DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = cur_tree;
 
-  DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
+      if (old_optimize != new_optimize)
+	DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
+    }
 
   return ret;
 }
diff '--exclude=.svn' -ruN gnu_trunk.p5/gcc/gcc/config/arm/arm-c.c gnu_trunk.p6/gcc/gcc/config/arm/arm-c.c
--- gnu_trunk.p5/gcc/gcc/config/arm/arm-c.c	2015-05-06 14:36:21.987195830 +0200
+++ gnu_trunk.p6/gcc/gcc/config/arm/arm-c.c	2015-05-06 14:37:58.799362130 +0200
@@ -20,7 +20,6 @@ 
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "tm_p.h"
 #include "hash-set.h"
 #include "machmode.h"
 #include "vec.h"
@@ -31,7 +30,11 @@ 
 #include "wide-int.h"
 #include "inchash.h"
 #include "tree.h"
+#include "tm_p.h"
 #include "c-family/c-common.h"
+#include "target.h"
+#include "target-def.h"
+#include "c-family/c-pragma.h"
 
 /* Output C specific EABI object attributes.  These can not be done in
    arm.c because they require information from the C frontend.  */
@@ -121,3 +124,79 @@ 
  cpp_def_or_undef (in, "__ARM_ASM_SYNTAX_UNIFIED__", inline_asm_unified);
 }
 
+/* Hook to validate the current #pragma GCC target and set the arch custom
+   mode state.  If ARGS is NULL, then POP_TARGET is used to reset
+   the options.  */
+static bool
+arm_pragma_target_parse (tree args, tree pop_target)
+{
+  tree prev_tree = build_target_option_node (&global_options);
+  tree cur_tree;
+  struct cl_target_option *prev_opt;
+  struct cl_target_option *cur_opt;
+  bool cur_mode, prev_mode;
+
+  if (! args)
+    {
+      cur_tree = ((pop_target) ? pop_target : target_option_default_node);
+      cl_target_option_restore (&global_options,
+				TREE_TARGET_OPTION (cur_tree));
+    }
+  else
+    {
+      cur_tree = arm_valid_target_attribute_tree (args, &global_options,
+						  &global_options_set);
+      if (cur_tree == NULL_TREE)
+	{
+	  cl_target_option_restore (&global_options,
+				    TREE_TARGET_OPTION (prev_tree));
+	  return false;
+	}
+    }
+
+  target_option_current_node = cur_tree;
+  arm_reset_previous_fndecl ();
+
+  /* Figure out the previous mode.  */
+  prev_opt  = TREE_TARGET_OPTION (prev_tree);
+  cur_opt   = TREE_TARGET_OPTION (cur_tree);
+
+  gcc_assert (prev_opt);
+  gcc_assert (cur_opt);
+
+  cur_mode = TARGET_THUMB_P (cur_opt->x_target_flags);
+  prev_mode = TARGET_THUMB_P (prev_opt->x_target_flags);
+
+  if (prev_mode != cur_mode)
+    {
+      /* For the definitions, ensure all newly defined macros are considered
+	 as used for -Wunused-macros.  There is no point warning about the
+	 compiler predefined macros.  */
+      cpp_options *cpp_opts = cpp_get_options (parse_in);
+      unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
+      cpp_opts->warn_unused_macros = 0;
+
+      /* Update macros.  */
+      arm_cpp_builtins (parse_in, cur_mode);
+
+      cpp_opts->warn_unused_macros = saved_warn_unused_macros;
+    }
+
+  return true;
+}
+
+/* Register target pragmas.  We need to add the hook for parsing #pragma GCC
+   option here rather than in arm.c since it will pull in various preprocessor
+   functions, and those are not present in languages like fortran without a
+   preprocessor.  */
+
+void
+arm_register_target_pragmas (void)
+{
+  /* Update pragma hook to allow parsing #pragma GCC target.  */
+  targetm.target_option.pragma_parse = arm_pragma_target_parse;
+
+#ifdef REGISTER_SUBTARGET_PRAGMAS
+  REGISTER_SUBTARGET_PRAGMAS ();
+#endif
+}
diff '--exclude=.svn' -ruN gnu_trunk.p5/gcc/gcc/config/arm/arm.h gnu_trunk.p6/gcc/gcc/config/arm/arm.h
--- gnu_trunk.p5/gcc/gcc/config/arm/arm.h	2015-05-06 14:36:32.227213416 +0200
+++ gnu_trunk.p6/gcc/gcc/config/arm/arm.h	2015-05-06 14:37:58.799362130 +0200
@@ -2070,7 +2070,8 @@ 
   c_register_pragma (0, "long_calls", arm_pr_long_calls);		\
   c_register_pragma (0, "no_long_calls", arm_pr_no_long_calls);		\
   c_register_pragma (0, "long_calls_off", arm_pr_long_calls_off);	\
-  arm_lang_object_attributes_init(); \
+  arm_lang_object_attributes_init();					\
+  arm_register_target_pragmas();                                       \
 } while (0)
 
 /* Condition code information.  */
diff '--exclude=.svn' -ruN gnu_trunk.p5/gcc/gcc/config/arm/arm.opt gnu_trunk.p6/gcc/gcc/config/arm/arm.opt
--- gnu_trunk.p5/gcc/gcc/config/arm/arm.opt	2015-05-06 14:36:32.231213422 +0200
+++ gnu_trunk.p6/gcc/gcc/config/arm/arm.opt	2015-05-06 14:38:02.215367999 +0200
@@ -122,6 +122,10 @@ 
 EnumValue
 Enum(float_abi_type) String(hard) Value(ARM_FLOAT_ABI_HARD)
 
+mflip-thumb
+Target Report Var(TARGET_FLIP_THUMB)
+Switch ARM/Thumb modes on alternating functions for compiler testing
+
 mfp16-format=
 Target RejectNegative Joined Enum(arm_fp16_format_type) Var(arm_fp16_format) Init(ARM_FP16_FORMAT_NONE)
 Specify the __fp16 floating-point format
diff '--exclude=.svn' -ruN gnu_trunk.p5/gcc/gcc/config/arm/arm-protos.h gnu_trunk.p6/gcc/gcc/config/arm/arm-protos.h
--- gnu_trunk.p5/gcc/gcc/config/arm/arm-protos.h	2015-05-06 14:36:32.231213422 +0200
+++ gnu_trunk.p6/gcc/gcc/config/arm/arm-protos.h	2015-05-06 14:37:58.799362130 +0200
@@ -327,6 +327,7 @@ 
 
 /* Defined in gcc/common/config/arm-c.c.  */
 extern void arm_lang_object_attributes_init(void);
+extern void arm_register_target_pragmas (void);
 extern void arm_cpp_builtins (struct cpp_reader *, bool);
 
 extern bool arm_is_constant_pool_ref (rtx);