public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++ PATCH] lang_decl selector & decomposition
@ 2017-05-31 17:05 Nathan Sidwell
  2017-05-31 17:11 ` Jakub Jelinek
  0 siblings, 1 reply; 6+ messages in thread
From: Nathan Sidwell @ 2017-05-31 17:05 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jakub Jelinek

[-- Attachment #1: Type: text/plain, Size: 1102 bytes --]

This patch reworks how decl_decomposition is marked.  With the new 
lang_decl_decomp struct, the selector grew another used but -- which 
affected me on the modules branch.  however, we can use that use 
selector value in place of the decompostion_p bitfield.

This patch makes that change, but it also replaces the use of magic 
constants [0-4] with an enumeration.

Rather than have retrofit_lang_decl know about decomposition conversion, 
I broke out a fit_decomposition_lang_decl function for just that purpose.

The other change I made is breaking out new maybe_add_lang_decl_raw and 
maybe_add_lang_type_raw functions.  On the modules branch I need to 
recreate the lang_decl/lang_type nodes, but based on an untrustworth 
binary file.  So we don't want to assert if they're called incorrectly. 
I was going to leave that on the modules branch, until Jakub altered 
retrofit_lang_decl, and I had a more complicated merge.

Jakub, I discovered that fit_decomposition_lang_decl can get called 
repeatedly on the same var but with different base vars.  Is that expected?

nathan

-- 
Nathan Sidwell

[-- Attachment #2: decomp.diff --]
[-- Type: text/x-patch, Size: 13354 bytes --]

2017-05-31  Nathan Sidwell  <nathan@acm.org>

	* cp-tree.h (lang_decl_slector): New enum.
	(lang_decl_base): Make selector an enum.  Drop decomposition_p
	field.
	(lang_decl): Use enum for discrimination.
	(LANG_DECL_FN_CHECK, LANG_DECL_NS_CHECK, LANG_DECL_PARM_CHECK,
	LANG_DECL_DEOMP_CHECK): Use enum.
	(DECL_DECOMPOSITION_P): Use selector value.
	(SET_DECL_DECOMPOSITION_P): Delete.
	(retrofit_lang_decl): Lose SEL parm.
	(fit_decomposition_lang_decl): Declare.
	* decl.c (cp_finish_decomp, grokdeclarator): Use
	fit_decomposition_lang_decl.
	* lex.c (maybe_add_lang_decl_raw): New. Broken out of
	retrofit_lang_decl.
	(set_decl_linkage): New.  Broken out of retrofit_lang_decl.  Use enum.
	(fit_decomposition_lang_decl): Likewise.
	(retrofit_lang_decl): Use worker functions.
	(cxx_dup_lang_specific_decl): Use selector enum.
	(maybe_add_lang_type_raw): New.  Broken out of ...
	(cxx_make_type_name): ... here.  Call it.

Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 248745)
+++ cp/cp-tree.h	(working copy)
@@ -2423,13 +2423,25 @@ struct GTY(()) lang_type {
 #define NAMESPACE_LEVEL(NODE) \
   (LANG_DECL_NS_CHECK (NODE)->level)
 \f
+/* Discriminator values for lang_decl.  */
+
+enum lang_decl_selector
+{
+  lds_min,
+  lds_fn,
+  lds_ns,
+  lds_parm,
+  lds_decomp
+};
+
 /* Flags shared by all forms of DECL_LANG_SPECIFIC.
 
    Some of the flags live here only to make lang_decl_min/fn smaller.  Do
    not make this struct larger than 32 bits; instead, make sel smaller.  */
o 
 struct GTY(()) lang_decl_base {
-  unsigned selector : 16;   /* Larger than necessary for faster access.  */
+  /* Larger than necessary for faster access.  */
+  ENUM_BITFIELD(lang_decl_selector) selector : 16;
   ENUM_BITFIELD(languages) language : 1;
   unsigned use_template : 2;
   unsigned not_really_extern : 1;	   /* var or fn */
@@ -2444,8 +2456,7 @@ struct GTY(()) lang_decl_base {
   unsigned u2sel : 1;
   unsigned concept_p : 1;                  /* applies to vars and functions */
   unsigned var_declared_inline_p : 1;	   /* var */
-  unsigned decomposition_p : 1;		   /* var */
-  /* 1 spare bit */
+  /* 2 spare bits */
 };
 
 /* True for DECL codes which have template info and access.  */
@@ -2577,12 +2588,13 @@ struct GTY(()) lang_decl_decomp {
 
 struct GTY(()) lang_decl {
   union GTY((desc ("%h.base.selector"))) lang_decl_u {
+     /* Nothing of only the base type exists.  */
     struct lang_decl_base GTY ((default)) base;
-    struct lang_decl_min GTY((tag ("0"))) min;
-    struct lang_decl_fn GTY ((tag ("1"))) fn;
-    struct lang_decl_ns GTY((tag ("2"))) ns;
-    struct lang_decl_parm GTY((tag ("3"))) parm;
-    struct lang_decl_decomp GTY((tag ("4"))) decomp;
+    struct lang_decl_min GTY((tag ("lds_min"))) min;
+    struct lang_decl_fn GTY ((tag ("lds_fn"))) fn;
+    struct lang_decl_ns GTY((tag ("lds_ns"))) ns;
+    struct lang_decl_parm GTY((tag ("lds_parm"))) parm;
+    struct lang_decl_decomp GTY((tag ("lds_decomp"))) decomp;
   } u;
 };
 
@@ -2603,26 +2615,29 @@ struct GTY(()) lang_decl {
    lang_decl_fn, look down through a TEMPLATE_DECL into its result.  */
 #define LANG_DECL_FN_CHECK(NODE) __extension__				\
 ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (STRIP_TEMPLATE (NODE));	\
-   if (!DECL_DECLARES_FUNCTION_P (NODE) || lt->u.base.selector != 1)	\
+   if (!DECL_DECLARES_FUNCTION_P (NODE)					\
+       || lt->u.base.selector != lds_fn)				\
      lang_check_failed (__FILE__, __LINE__, __FUNCTION__);		\
    &lt->u.fn; })
 
 #define LANG_DECL_NS_CHECK(NODE) __extension__				\
 ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE);			\
-   if (TREE_CODE (NODE) != NAMESPACE_DECL || lt->u.base.selector != 2)	\
+   if (TREE_CODE (NODE) != NAMESPACE_DECL				\
+       || lt->u.base.selector != lds_ns)				\
      lang_check_failed (__FILE__, __LINE__, __FUNCTION__);		\
    &lt->u.ns; })
 
 #define LANG_DECL_PARM_CHECK(NODE) __extension__		\
 ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE);		\
-  if (TREE_CODE (NODE) != PARM_DECL)				\
+  if (TREE_CODE (NODE) != PARM_DECL				\
+      || lt->u.base.selector != lds_parm)			\
     lang_check_failed (__FILE__, __LINE__, __FUNCTION__);	\
   &lt->u.parm; })
 
 #define LANG_DECL_DECOMP_CHECK(NODE) __extension__		\
 ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE);		\
   if (!VAR_P (NODE)						\
-      || lt->u.base.selector != 4)				\
+      || lt->u.base.selector != lds_decomp)			\
     lang_check_failed (__FILE__, __LINE__, __FUNCTION__);	\
   &lt->u.decomp; })
 
@@ -3893,11 +3908,8 @@ more_aggr_init_expr_args_p (const aggr_i
    declaration or one of VAR_DECLs for the user identifiers in it.  */
 #define DECL_DECOMPOSITION_P(NODE) \
   (VAR_P (NODE) && DECL_LANG_SPECIFIC (NODE)			\
-   ? DECL_LANG_SPECIFIC (NODE)->u.base.decomposition_p		\
+   ? DECL_LANG_SPECIFIC (NODE)->u.base.selector == lds_decomp		\
    : false)
-#define SET_DECL_DECOMPOSITION_P(NODE) \
-  (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.decomposition_p \
-   = true)
 
 /* The underlying artificial VAR_DECL for structured binding.  */
 #define DECL_DECOMP_BASE(NODE) \
@@ -6338,7 +6350,8 @@ extern tree unqualified_name_lookup_erro
 extern tree unqualified_fn_lookup_error		(cp_expr);
 extern tree build_lang_decl			(enum tree_code, tree, tree);
 extern tree build_lang_decl_loc			(location_t, enum tree_code, tree, tree);
-extern void retrofit_lang_decl			(tree, int = 0);
+extern void retrofit_lang_decl			(tree);
+extern void fit_decomposition_lang_decl		(tree, tree);
 extern tree copy_decl				(tree CXX_MEM_STAT_INFO);
 extern tree copy_type				(tree CXX_MEM_STAT_INFO);
 extern tree cxx_make_type			(enum tree_code);
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 248745)
+++ cp/decl.c	(working copy)
@@ -7372,11 +7372,7 @@ cp_finish_decomp (tree decl, tree first,
 	      DECL_HAS_VALUE_EXPR_P (first) = 1;
 	    }
 	  if (processing_template_decl)
-	    {
-	      retrofit_lang_decl (first, 4);
-	      SET_DECL_DECOMPOSITION_P (first);
-	      DECL_DECOMP_BASE (first) = decl;
-	    }
+	    fit_decomposition_lang_decl (first, decl);
 	  first = DECL_CHAIN (first);
 	}
       return;
@@ -7388,9 +7384,7 @@ cp_finish_decomp (tree decl, tree first,
   for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d))
     {
       v[count - i - 1] = d;
-      retrofit_lang_decl (d, 4);
-      SET_DECL_DECOMPOSITION_P (d);
-      DECL_DECOMP_BASE (d) = decl;
+      fit_decomposition_lang_decl (d, decl);
     }
 
   tree type = TREE_TYPE (decl);
@@ -12314,10 +12308,8 @@ grokdeclarator (const cp_declarator *dec
 	  {
 	    gcc_assert (declarator && declarator->kind == cdk_decomp);
 	    DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
-	    retrofit_lang_decl (decl, 4);
 	    DECL_ARTIFICIAL (decl) = 1;
-	    SET_DECL_DECOMPOSITION_P (decl);
-	    DECL_DECOMP_BASE (decl) = NULL_TREE;
+	    fit_decomposition_lang_decl (decl, NULL_TREE);
 	  }
       }
 
Index: cp/lex.c
===================================================================
--- cp/lex.c	(revision 248745)
+++ cp/lex.c	(working copy)
@@ -525,53 +525,52 @@ build_lang_decl_loc (location_t loc, enu
   return t;
 }
 
-/* Add DECL_LANG_SPECIFIC info to T.  Called from build_lang_decl
-   and pushdecl (for functions generated by the back end).  */
+/* Maybe add a raw lang_decl to T, a decl.  Return true if it needed
+   one.  */
 
-void
-retrofit_lang_decl (tree t, int sel)
+static bool
+maybe_add_lang_decl_raw (tree t, bool decomp_p)
 {
-  struct lang_decl *ld;
   size_t size;
-  size_t oldsize = 0;
-
-  if (DECL_LANG_SPECIFIC (t))
-    {
-      if (sel)
-	{
-	  if (DECL_LANG_SPECIFIC (t)->u.base.selector == sel)
-	    return;
-	  gcc_assert (DECL_LANG_SPECIFIC (t)->u.base.selector == 0);
-	  oldsize = sizeof (struct lang_decl_min);
-	}
-      else
-	return;
-    }
+  lang_decl_selector sel;
 
-  if (sel == 4)
-    size = sizeof (struct lang_decl_decomp);
+  if (decomp_p)
+    sel = lds_decomp, size = sizeof (struct lang_decl_decomp);
   else if (TREE_CODE (t) == FUNCTION_DECL)
-    sel = 1, size = sizeof (struct lang_decl_fn);
+    sel = lds_fn, size = sizeof (struct lang_decl_fn);
   else if (TREE_CODE (t) == NAMESPACE_DECL)
-    sel = 2, size = sizeof (struct lang_decl_ns);
+    sel = lds_ns, size = sizeof (struct lang_decl_ns);
   else if (TREE_CODE (t) == PARM_DECL)
-    sel = 3, size = sizeof (struct lang_decl_parm);
+    sel = lds_parm, size = sizeof (struct lang_decl_parm);
   else if (LANG_DECL_HAS_MIN (t))
-    sel = 0, size = sizeof (struct lang_decl_min);
+    sel = lds_min, size = sizeof (struct lang_decl_min);
   else
-    gcc_unreachable ();
+    return false;
 
-  ld = (struct lang_decl *) ggc_internal_cleared_alloc (size);
-  if (oldsize)
-    memcpy (ld, DECL_LANG_SPECIFIC (t), oldsize);
+  struct lang_decl *ld
+    = (struct lang_decl *) ggc_internal_cleared_alloc (size);
 
   ld->u.base.selector = sel;
   DECL_LANG_SPECIFIC (t) = ld;
 
-  if (sel == 2)
+  if (sel == lds_ns)
     /* Who'd create a namespace, only to put nothing in it?  */
     ld->u.ns.bindings = hash_map<lang_identifier *, tree>::create_ggc (499);
 
+  if (GATHER_STATISTICS)
+    {
+      tree_node_counts[(int)lang_decl] += 1;
+      tree_node_sizes[(int)lang_decl] += size;
+    }
+  return true;
+}
+
+/* T has just had a decl_lang_specific added.  Initialize its
+   linkage.  */
+
+static void
+set_decl_linkage (tree t)
+{
   if (current_lang_name == lang_name_cplusplus
       || decl_linkage (t) == lk_none)
     SET_DECL_LANGUAGE (t, lang_cplusplus);
@@ -579,37 +578,79 @@ retrofit_lang_decl (tree t, int sel)
     SET_DECL_LANGUAGE (t, lang_c);
   else
     gcc_unreachable ();
+}
 
-  if (GATHER_STATISTICS)
+/* T is a VAR_DECL node that needs to be a decomposition of BASE.  */
+
+void
+fit_decomposition_lang_decl (tree t, tree base)
+{
+  if (struct lang_decl *orig_ld = DECL_LANG_SPECIFIC (t))
     {
-      tree_node_counts[(int)lang_decl] += 1;
-      tree_node_sizes[(int)lang_decl] += size;
+      if (orig_ld->u.base.selector == lds_min)
+	{
+	  maybe_add_lang_decl_raw (t, true);
+	  memcpy (DECL_LANG_SPECIFIC (t), orig_ld,
+		  sizeof (struct lang_decl_min));
+	  /* Reset selector, which will have been bashed by the
+	     memcpy.  */
+	  DECL_LANG_SPECIFIC (t)->u.base.selector = lds_decomp;
+	}
+      else
+	gcc_checking_assert (orig_ld->u.base.selector == lds_decomp);
     }
+  else
+    {
+      maybe_add_lang_decl_raw (t, true);
+      set_decl_linkage (t);
+    }
+
+  DECL_DECOMP_BASE (t) = base;
+}
+
+/* Add DECL_LANG_SPECIFIC info to T, if it needs one.  Generally
+   every C++ decl needs one, but C builtins etc do not.   */
+
+void
+retrofit_lang_decl (tree t)
+{
+  if (DECL_LANG_SPECIFIC (t))
+    return;
+
+  if (maybe_add_lang_decl_raw (t, false))
+    set_decl_linkage (t);
 }
 
 void
 cxx_dup_lang_specific_decl (tree node)
 {
   int size;
-  struct lang_decl *ld;
 
   if (! DECL_LANG_SPECIFIC (node))
     return;
 
-  if (TREE_CODE (node) == FUNCTION_DECL)
-    size = sizeof (struct lang_decl_fn);
-  else if (TREE_CODE (node) == NAMESPACE_DECL)
-    size = sizeof (struct lang_decl_ns);
-  else if (TREE_CODE (node) == PARM_DECL)
-    size = sizeof (struct lang_decl_parm);
-  else if (DECL_DECOMPOSITION_P (node))
-    size = sizeof (struct lang_decl_decomp);
-  else if (LANG_DECL_HAS_MIN (node))
-    size = sizeof (struct lang_decl_min);
-  else
-    gcc_unreachable ();
+  switch (DECL_LANG_SPECIFIC (node)->u.base.selector)
+    {
+    case lds_min:
+      size = sizeof (struct lang_decl_min);
+      break;
+    case lds_fn:
+      size = sizeof (struct lang_decl_fn);
+      break;
+    case lds_ns:
+      size = sizeof (struct lang_decl_ns);
+      break;
+    case lds_parm:
+      size = sizeof (struct lang_decl_parm);
+      break;
+    case lds_decomp:
+      size = sizeof (struct lang_decl_decomp);
+      break;
+    default:
+      gcc_unreachable ();
+    }
 
-  ld = (struct lang_decl *) ggc_internal_alloc (size);
+  struct lang_decl *ld = (struct lang_decl *) ggc_internal_alloc (size);
   memcpy (ld, DECL_LANG_SPECIFIC (node), size);
   DECL_LANG_SPECIFIC (node) = ld;
 
@@ -670,18 +711,18 @@ copy_type (tree type MEM_STAT_DECL)
   return copy;
 }
 
-tree
-cxx_make_type (enum tree_code code)
-{
-  tree t = make_node (code);
+/* Add a raw lang_type to T, a type, should it need one.  */
 
-  /* Create lang_type structure.  */
-  if (RECORD_OR_UNION_CODE_P (code)
-      || code == BOUND_TEMPLATE_TEMPLATE_PARM)
+static bool
+maybe_add_lang_type_raw (tree t)
+{
+  bool add = (RECORD_OR_UNION_CODE_P (TREE_CODE (t))
+	      || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM);
+  if (add)
     {
       struct lang_type *pi
-          = (struct lang_type *) ggc_internal_cleared_alloc
-	  (sizeof (struct lang_type));
+	= (struct lang_type *) ggc_internal_cleared_alloc
+	(sizeof (struct lang_type));
 
       TYPE_LANG_SPECIFIC (t) = pi;
       pi->u.c.h.is_lang_type_class = 1;
@@ -692,6 +733,15 @@ cxx_make_type (enum tree_code code)
 	  tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
 	}
     }
+  return add;
+}
+
+tree
+cxx_make_type (enum tree_code code)
+{
+  tree t = make_node (code);
+
+  maybe_add_lang_type_raw (t);
 
   /* Set up some flags that give proper default behavior.  */
   if (RECORD_OR_UNION_CODE_P (code))

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-06-05 11:22 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-31 17:05 [C++ PATCH] lang_decl selector & decomposition Nathan Sidwell
2017-05-31 17:11 ` Jakub Jelinek
2017-05-31 17:18   ` Nathan Sidwell
2017-05-31 17:36     ` Jakub Jelinek
2017-06-05 11:13     ` Jakub Jelinek
2017-06-05 11:22       ` Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).