This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] [ARM] Keep separation between extensions and architecture bits throughout execution


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c168ce07e5b4a2a0258c796748899e1ba2e6dc7c

commit c168ce07e5b4a2a0258c796748899e1ba2e6dc7c
Author: Thomas Preud'homme <thomas.preudhomme@arm.com>
Date:   Wed Jun 21 14:08:08 2017 +0100

    [ARM] Keep separation between extensions and architecture bits throughout execution
    
    === Context ===
    
    This patch is part of a patch series to add support for ARMv8-R
    architecture. Its purpose is to keep the distinction between
    architecture feature bits and extension ones after parsing has occured.
    
    === Motivation ===
    
    This distinction is necessary to allow the Tag_CPU_arch build attribute
    value to be exactly as per the architecture of the selected CPU. With
    mixed architecture and extension feature bit, it is impossible to find
    an architecture with an exact match of feature bit and the build
    attribute value logic must then select the closest match which might not
    be the right architecture. The previous patch in the patch series makes
    the distinction possible when parsing -mcpu and .cpu directives but the
    distinction gets lost after. Similarly feature bits contributed by
    extensions in -march or .arch_extensions directive are mixed together
    with architecture extensions.
    
    === Patch description ===
    
    The patch adds new feature bit pointer for extension feature bits.
    Information from the parsing regarding extensions can then be kept
    separate in those. This requires adapting arm_parse_extension to deal
    with two feature bits, allowing the architecture bits to be marked as
    const. It also requires extra care when setting cpu_variant and
    selected_cpu because the extension bits are optional since there might
    not be any extension in use.
    
    Note that contrary to cpu feature bits, the extension feature bits are
    made read/write and are always dynamically allocated. This allows to
    unconditionally free them in arm_md_post_relax added for this occasion,
    thereby fixing a longstanding memory leak when arm_parse_extension was
    invoked (XNEW of ext_fset without corresponding XDELETE).
    Introduction of arm_md_post_relax is necessary to only free the
    extension feature bits after aeabi_set_attribute_string has been called
    for the last time.
    
    2017-06-21  Thomas Preud'homme  <thomas.preudhomme@arm.com>
    
    gas/
    	* config/tc-arm.c (dyn_mcpu_ext_opt): New static variable.
    	(dyn_march_ext_opt): Likewise.
    	(md_begin): Copy extension feature bits alongside architecture ones.
    	Merge extensions feature bits in selected_cpu and cpu_variant if there
    	is some.
    	(arm_parse_extension): Pass architecture and extension feature bits in
    	separate parameters, with architecture bits being read only.  Update
    	**opt_p directly rather than *ext_set and initialize it if needed.
    	(arm_parse_cpu): Stop merging architecture and extension feature bits
    	and instead use mcpu_cpu_opt and dyn_mcpu_ext_opt to memorize them
    	respectively.  Adapt to change in parameters of arm_parse_extension.
    	(arm_parse_arch): Adapt to change in parameters of arm_parse_extension.
    	(aeabi_set_attribute_string): Make function static.
    	(arm_md_post_relax): New function.
    	(s_arm_cpu): Stop merging architecture and extension feature bits and
    	instead use mcpu_cpu_opt and dyn_mcpu_ext_opt to memorize them
    	respectively.  Merge extension feature bits in cpu_variant
    	if there is any.
    	(s_arm_arch): Reset extension feature bit.  Set selected_cpu from
    	*mcpu_cpu_opt and cpu_variant from selected_cpu and *mfpu_opt for
    	consistency with s_arm_cpu.
    	(s_arm_arch_extension): Update *dyn_mcpu_ext_opt rather than
    	selected_cpu, allocating it before hand if needed.  Set selected_cpu
    	from it and then cpu_variant.
    	(s_arm_fpu): Merge *mcpu_ext_opt feature bits if any in cpu_variant.
    	* config/tc-arm.h (md_post_relax_hook): Set to arm_md_post_relax.
    	(aeabi_set_public_attributes): Delete external declaration.
    	(arm_md_post_relax): Declare externally.

Diff:
---
 gas/ChangeLog       | 31 +++++++++++++++++
 gas/config/tc-arm.c | 95 ++++++++++++++++++++++++++++++++++++++---------------
 gas/config/tc-arm.h |  4 +--
 3 files changed, 101 insertions(+), 29 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index d85e1d4..462c921 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,36 @@
 2017-06-21  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
+	* config/tc-arm.c (dyn_mcpu_ext_opt): New static variable.
+	(dyn_march_ext_opt): Likewise.
+	(md_begin): Copy extension feature bits alongside architecture ones.
+	Merge extensions feature bits in selected_cpu and cpu_variant if there
+	is some.
+	(arm_parse_extension): Pass architecture and extension feature bits in
+	separate parameters, with architecture bits being read only.  Update
+	**opt_p directly rather than *ext_set and initialize it if needed.
+	(arm_parse_cpu): Stop merging architecture and extension feature bits
+	and instead use mcpu_cpu_opt and dyn_mcpu_ext_opt to memorize them
+	respectively.  Adapt to change in parameters of arm_parse_extension.
+	(arm_parse_arch): Adapt to change in parameters of arm_parse_extension.
+	(aeabi_set_attribute_string): Make function static.
+	(arm_md_post_relax): New function.
+	(s_arm_cpu): Stop merging architecture and extension feature bits and
+	instead use mcpu_cpu_opt and dyn_mcpu_ext_opt to memorize them
+	respectively.  Merge extension feature bits in cpu_variant
+	if there is any.
+	(s_arm_arch): Reset extension feature bit.  Set selected_cpu from
+	*mcpu_cpu_opt and cpu_variant from selected_cpu and *mfpu_opt for
+	consistency with s_arm_cpu.
+	(s_arm_arch_extension): Update *dyn_mcpu_ext_opt rather than
+	selected_cpu, allocating it before hand if needed.  Set selected_cpu
+	from it and then cpu_variant.
+	(s_arm_fpu): Merge *mcpu_ext_opt feature bits if any in cpu_variant.
+	* config/tc-arm.h (md_post_relax_hook): Set to arm_md_post_relax.
+	(aeabi_set_public_attributes): Delete external declaration.
+	(arm_md_post_relax): Declare externally.
+
+2017-06-21  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
 	* config/tc-arm.c (struct arm_cpu_option_table): New ext field.
 	(ARM_CPU_OPT): Add parameter to set new ext field and reorder canonical
 	name field just after the name field.
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index ca458d4..2be50f5 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -147,8 +147,10 @@ static const arm_feature_set *legacy_cpu = NULL;
 static const arm_feature_set *legacy_fpu = NULL;
 
 static const arm_feature_set *mcpu_cpu_opt = NULL;
+static arm_feature_set *dyn_mcpu_ext_opt = NULL;
 static const arm_feature_set *mcpu_fpu_opt = NULL;
 static const arm_feature_set *march_cpu_opt = NULL;
+static arm_feature_set *dyn_march_ext_opt = NULL;
 static const arm_feature_set *march_fpu_opt = NULL;
 static const arm_feature_set *mfpu_opt = NULL;
 static const arm_feature_set *object_arch = NULL;
@@ -25033,7 +25035,12 @@ md_begin (void)
       mcpu_cpu_opt = legacy_cpu;
     }
   else if (!mcpu_cpu_opt)
-    mcpu_cpu_opt = march_cpu_opt;
+    {
+      mcpu_cpu_opt = march_cpu_opt;
+      dyn_mcpu_ext_opt = dyn_march_ext_opt;
+      /* Avoid double free in arm_md_end.  */
+      dyn_march_ext_opt = NULL;
+    }
 
   if (legacy_fpu)
     {
@@ -25073,16 +25080,22 @@ md_begin (void)
       mcpu_cpu_opt = &cpu_default;
       selected_cpu = cpu_default;
     }
+  else if (dyn_mcpu_ext_opt)
+    ARM_MERGE_FEATURE_SETS (selected_cpu, *mcpu_cpu_opt, *dyn_mcpu_ext_opt);
   else
     selected_cpu = *mcpu_cpu_opt;
 #else
-  if (mcpu_cpu_opt)
+  if (mcpu_cpu_opt && dyn_mcpu_ext_opt)
+    ARM_MERGE_FEATURE_SETS (selected_cpu, *mcpu_cpu_opt, *dyn_mcpu_ext_opt);
+  else if (mcpu_cpu_opt)
     selected_cpu = *mcpu_cpu_opt;
   else
     mcpu_cpu_opt = &arm_arch_any;
 #endif
 
   ARM_MERGE_FEATURE_SETS (cpu_variant, *mcpu_cpu_opt, *mfpu_opt);
+  if (dyn_mcpu_ext_opt)
+    ARM_MERGE_FEATURE_SETS (cpu_variant, cpu_variant, *dyn_mcpu_ext_opt);
 
   autoselect_thumb_from_cpu_variant ();
 
@@ -26081,10 +26094,9 @@ struct arm_long_option_table
 };
 
 static bfd_boolean
-arm_parse_extension (const char *str, const arm_feature_set **opt_p)
+arm_parse_extension (const char *str, const arm_feature_set *opt_set,
+		     arm_feature_set **ext_set_p)
 {
-  arm_feature_set *ext_set = XNEW (arm_feature_set);
-
   /* We insist on extensions being specified in alphabetical order, and with
      extensions being added before being removed.  We achieve this by having
      the global ARM_EXTENSIONS table in alphabetical order, and using the
@@ -26095,9 +26107,11 @@ arm_parse_extension (const char *str, const arm_feature_set **opt_p)
   const arm_feature_set arm_any = ARM_ANY;
   int adding_value = -1;
 
-  /* Copy the feature set, so that we can modify it.  */
-  *ext_set = **opt_p;
-  *opt_p = ext_set;
+  if (!*ext_set_p)
+    {
+      *ext_set_p = XNEW (arm_feature_set);
+      **ext_set_p = arm_arch_none;
+    }
 
   while (str != NULL && *str != 0)
     {
@@ -26165,7 +26179,7 @@ arm_parse_extension (const char *str, const arm_feature_set **opt_p)
 		/* Empty entry.  */
 		if (ARM_FEATURE_EQUAL (opt->allowed_archs[i], arm_any))
 		  continue;
-		if (ARM_FSET_CPU_SUBSET (opt->allowed_archs[i], *ext_set))
+		if (ARM_FSET_CPU_SUBSET (opt->allowed_archs[i], *opt_set))
 		  break;
 	      }
 	    if (i == nb_allowed_archs)
@@ -26176,9 +26190,10 @@ arm_parse_extension (const char *str, const arm_feature_set **opt_p)
 
 	    /* Add or remove the extension.  */
 	    if (adding_value)
-	      ARM_MERGE_FEATURE_SETS (*ext_set, *ext_set, opt->merge_value);
+	      ARM_MERGE_FEATURE_SETS (**ext_set_p, **ext_set_p,
+				      opt->merge_value);
 	    else
-	      ARM_CLEAR_FEATURE (*ext_set, *ext_set, opt->clear_value);
+	      ARM_CLEAR_FEATURE (**ext_set_p, **ext_set_p, opt->clear_value);
 
 	    break;
 	  }
@@ -26234,9 +26249,10 @@ arm_parse_cpu (const char *str)
   for (opt = arm_cpus; opt->name != NULL; opt++)
     if (opt->name_len == len && strncmp (opt->name, str, len) == 0)
       {
-	arm_feature_set *cpu_set = XNEW (arm_feature_set);
-	ARM_MERGE_FEATURE_SETS (*cpu_set, opt->value, opt->ext);
-	mcpu_cpu_opt = cpu_set;
+	mcpu_cpu_opt = &opt->value;
+	if (!dyn_mcpu_ext_opt)
+	  dyn_mcpu_ext_opt = XNEW (arm_feature_set);
+	*dyn_mcpu_ext_opt = opt->ext;
 	mcpu_fpu_opt = &opt->default_fpu;
 	if (opt->canonical_name)
 	  {
@@ -26256,7 +26272,7 @@ arm_parse_cpu (const char *str)
 	  }
 
 	if (ext != NULL)
-	  return arm_parse_extension (ext, &mcpu_cpu_opt);
+	  return arm_parse_extension (ext, mcpu_cpu_opt, &dyn_mcpu_ext_opt);
 
 	return TRUE;
       }
@@ -26291,7 +26307,7 @@ arm_parse_arch (const char *str)
 	strcpy (selected_cpu_name, opt->name);
 
 	if (ext != NULL)
-	  return arm_parse_extension (ext, &march_cpu_opt);
+	  return arm_parse_extension (ext, march_cpu_opt, &dyn_march_ext_opt);
 
 	return TRUE;
       }
@@ -26577,7 +26593,7 @@ aeabi_set_attribute_string (int tag, const char *value)
 }
 
 /* Set the public EABI object attributes.  */
-void
+static void
 aeabi_set_public_attributes (void)
 {
   int arch;
@@ -26824,6 +26840,18 @@ aeabi_set_public_attributes (void)
     aeabi_set_attribute_int (Tag_Virtualization_use, virt_sec);
 }
 
+/* Post relaxation hook.  Recompute ARM attributes now that relaxation is
+   finished and free extension feature bits which will not be used anymore.  */
+void
+arm_md_post_relax (void)
+{
+  aeabi_set_public_attributes ();
+  XDELETE (dyn_mcpu_ext_opt);
+  dyn_mcpu_ext_opt = NULL;
+  XDELETE (dyn_march_ext_opt);
+  dyn_march_ext_opt = NULL;
+}
+
 /* Add the default contents for the .ARM.attributes section.  */
 void
 arm_md_end (void)
@@ -26855,10 +26883,11 @@ s_arm_cpu (int ignored ATTRIBUTE_UNUSED)
   for (opt = arm_cpus + 1; opt->name != NULL; opt++)
     if (streq (opt->name, name))
       {
-	arm_feature_set *cpu_set = XNEW (arm_feature_set);
-	ARM_MERGE_FEATURE_SETS (*cpu_set, opt->value, opt->ext);
-	mcpu_cpu_opt = cpu_set;
-	selected_cpu = *mcpu_cpu_opt;
+	mcpu_cpu_opt = &opt->value;
+	if (!dyn_mcpu_ext_opt)
+	  dyn_mcpu_ext_opt = XNEW (arm_feature_set);
+	*dyn_mcpu_ext_opt = opt->ext;
+	ARM_MERGE_FEATURE_SETS (selected_cpu, *mcpu_cpu_opt, *dyn_mcpu_ext_opt);
 	if (opt->canonical_name)
 	  strcpy (selected_cpu_name, opt->canonical_name);
 	else
@@ -26870,6 +26899,8 @@ s_arm_cpu (int ignored ATTRIBUTE_UNUSED)
 	    selected_cpu_name[i] = 0;
 	  }
 	ARM_MERGE_FEATURE_SETS (cpu_variant, *mcpu_cpu_opt, *mfpu_opt);
+	if (dyn_mcpu_ext_opt)
+	  ARM_MERGE_FEATURE_SETS (cpu_variant, cpu_variant, *dyn_mcpu_ext_opt);
 	*input_line_pointer = saved_char;
 	demand_empty_rest_of_line ();
 	return;
@@ -26900,9 +26931,11 @@ s_arm_arch (int ignored ATTRIBUTE_UNUSED)
     if (streq (opt->name, name))
       {
 	mcpu_cpu_opt = &opt->value;
-	selected_cpu = opt->value;
+	XDELETE (dyn_mcpu_ext_opt);
+	dyn_mcpu_ext_opt = NULL;
+	selected_cpu = *mcpu_cpu_opt;
 	strcpy (selected_cpu_name, opt->name);
-	ARM_MERGE_FEATURE_SETS (cpu_variant, *mcpu_cpu_opt, *mfpu_opt);
+	ARM_MERGE_FEATURE_SETS (cpu_variant, selected_cpu, *mfpu_opt);
 	*input_line_pointer = saved_char;
 	demand_empty_rest_of_line ();
 	return;
@@ -26989,14 +27022,20 @@ s_arm_arch_extension (int ignored ATTRIBUTE_UNUSED)
 	    break;
 	  }
 
+	if (!dyn_mcpu_ext_opt)
+	  {
+	    dyn_mcpu_ext_opt = XNEW (arm_feature_set);
+	    *dyn_mcpu_ext_opt = arm_arch_none;
+	  }
 	if (adding_value)
-	  ARM_MERGE_FEATURE_SETS (selected_cpu, selected_cpu,
+	  ARM_MERGE_FEATURE_SETS (*dyn_mcpu_ext_opt, *dyn_mcpu_ext_opt,
 				  opt->merge_value);
 	else
-	  ARM_CLEAR_FEATURE (selected_cpu, selected_cpu, opt->clear_value);
+	  ARM_CLEAR_FEATURE (*dyn_mcpu_ext_opt, *dyn_mcpu_ext_opt,
+			     opt->clear_value);
 
-	mcpu_cpu_opt = &selected_cpu;
-	ARM_MERGE_FEATURE_SETS (cpu_variant, *mcpu_cpu_opt, *mfpu_opt);
+	ARM_MERGE_FEATURE_SETS (selected_cpu, *mcpu_cpu_opt, *dyn_mcpu_ext_opt);
+	ARM_MERGE_FEATURE_SETS (cpu_variant, selected_cpu, *mfpu_opt);
 	*input_line_pointer = saved_char;
 	demand_empty_rest_of_line ();
 	return;
@@ -27029,6 +27068,8 @@ s_arm_fpu (int ignored ATTRIBUTE_UNUSED)
       {
 	mfpu_opt = &opt->value;
 	ARM_MERGE_FEATURE_SETS (cpu_variant, *mcpu_cpu_opt, *mfpu_opt);
+	if (dyn_mcpu_ext_opt)
+	  ARM_MERGE_FEATURE_SETS (cpu_variant, cpu_variant, *dyn_mcpu_ext_opt);
 	*input_line_pointer = saved_char;
 	demand_empty_rest_of_line ();
 	return;
diff --git a/gas/config/tc-arm.h b/gas/config/tc-arm.h
index 53c4986..1187d19 100644
--- a/gas/config/tc-arm.h
+++ b/gas/config/tc-arm.h
@@ -118,8 +118,8 @@ extern bfd_boolean tc_start_label_without_colon (void);
 extern void arm_md_end (void);
 bfd_boolean arm_is_eabi (void);
 
-#define md_post_relax_hook		aeabi_set_public_attributes ()
-extern void aeabi_set_public_attributes (void);
+#define md_post_relax_hook		arm_md_post_relax ()
+extern void arm_md_post_relax (void);
 #endif
 
 /* NOTE: The fake label creation in stabs.c:s_stab_generic() has


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]