public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] rust constexprC: start porting cxx_eval_builtin_function_call
@ 2022-08-29 15:34 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-08-29 15:34 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:e1170b0abe208b212eb395dc1d79fcfb7515e754

commit e1170b0abe208b212eb395dc1d79fcfb7515e754
Author: Faisal Abbas <90.abbasfaisal@gmail.com>
Date:   Mon Aug 8 18:22:54 2022 +0100

    rust constexprC: start porting cxx_eval_builtin_function_call
    
    Signed-off-by: Faisal Abbas <90.abbasfaisal@gmail.com>

Diff:
---
 gcc/rust/backend/rust-tree.cc | 732 ++++++++++++++++++++++++++++++++++++++++++
 gcc/rust/backend/rust-tree.h  |  86 +++++
 2 files changed, 818 insertions(+)

diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc
index ad457a2e4ce..8c6543271aa 100644
--- a/gcc/rust/backend/rust-tree.cc
+++ b/gcc/rust/backend/rust-tree.cc
@@ -31,6 +31,11 @@
 #include "gimplify.h"
 #include "function.h"
 #include "gcc-rich-location.h"
+#include "target.h"
+#include "file-prefix-map.h"
+#include "cgraph.h"
+
+#include "output.h"
 
 // forked from gcc/c-family/c-common.cc c_global_trees
 tree c_global_trees[CTI_MAX];
@@ -44,6 +49,9 @@ namespace Rust {
 void
 mark_exp_read (tree exp)
 {
+  char tmp_name[32];
+  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lsrc_loc", 1);
+
   if (exp == NULL)
     return;
 
@@ -4151,4 +4159,728 @@ rs_get_callee_fndecl_nofold (tree call)
   return rs_get_fndecl_from_callee (cp_get_callee (call), false);
 }
 
+// forked from gcc/cp/init.cc is_class_type
+
+/* Report an error if TYPE is not a user-defined, class type.  If
+   OR_ELSE is nonzero, give an error message.  */
+
+int
+is_class_type (tree type, int or_else)
+{
+  if (type == error_mark_node)
+    return 0;
+
+  if (!CLASS_TYPE_P (type))
+    {
+      if (or_else)
+	error ("%qT is not a class type", type);
+      return 0;
+    }
+  return 1;
+}
+
+// forked from gcc/cp/decl.cc lookup_enumerator
+
+/* Look for an enumerator with the given NAME within the enumeration
+   type ENUMTYPE.  This routine is used primarily for qualified name
+   lookup into an enumerator in C++0x, e.g.,
+
+     enum class Color { Red, Green, Blue };
+
+     Color color = Color::Red;
+
+   Returns the value corresponding to the enumerator, or
+   NULL_TREE if no such enumerator was found.  */
+tree
+lookup_enumerator (tree enumtype, tree name)
+{
+  tree e;
+  gcc_assert (enumtype && TREE_CODE (enumtype) == ENUMERAL_TYPE);
+
+  e = purpose_member (name, TYPE_VALUES (enumtype));
+  return e ? TREE_VALUE (e) : NULL_TREE;
+}
+
+// forked from gcc/cp/init.cc constant_value_1
+// commented out mark_used
+
+/* If DECL is a scalar enumeration constant or variable with a
+   constant initializer, return the initializer (or, its initializers,
+   recursively); otherwise, return DECL.  If STRICT_P, the
+   initializer is only returned if DECL is a
+   constant-expression.  If RETURN_AGGREGATE_CST_OK_P, it is ok to
+   return an aggregate constant.  If UNSHARE_P, return an unshared
+   copy of the initializer.  */
+
+static tree
+constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p,
+		  bool unshare_p)
+{
+  while (TREE_CODE (decl) == CONST_DECL || decl_constant_var_p (decl)
+	 || (!strict_p && VAR_P (decl)
+	     && RS_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))))
+    {
+      tree init;
+      /* If DECL is a static data member in a template
+	 specialization, we must instantiate it here.  The
+	 initializer for the static data member is not processed
+	 until needed; we need it now.  */
+      // mark_used (decl, tf_none);
+      init = DECL_INITIAL (decl);
+      if (init == error_mark_node)
+	{
+	  if (TREE_CODE (decl) == CONST_DECL
+	      || DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+	    /* Treat the error as a constant to avoid cascading errors on
+	       excessively recursive template instantiation (c++/9335).  */
+	    return init;
+	  else
+	    return decl;
+	}
+
+      /* Instantiate a non-dependent initializer for user variables.  We
+	 mustn't do this for the temporary for an array compound literal;
+	 trying to instatiate the initializer will keep creating new
+	 temporaries until we crash.  Probably it's not useful to do it for
+	 other artificial variables, either.  */
+      if (!DECL_ARTIFICIAL (decl))
+	init = instantiate_non_dependent_or_null (init);
+      if (!init || !TREE_TYPE (init) || !TREE_CONSTANT (init)
+	  || (!return_aggregate_cst_ok_p
+	      /* Unless RETURN_AGGREGATE_CST_OK_P is true, do not
+		 return an aggregate constant (of which string
+		 literals are a special case), as we do not want
+		 to make inadvertent copies of such entities, and
+		 we must be sure that their addresses are the
+		 same everywhere.  */
+	      && (TREE_CODE (init) == CONSTRUCTOR
+		  || TREE_CODE (init) == STRING_CST)))
+	break;
+      /* Don't return a CONSTRUCTOR for a variable with partial run-time
+	 initialization, since it doesn't represent the entire value.
+	 Similarly for VECTOR_CSTs created by cp_folding those
+	 CONSTRUCTORs.  */
+      if ((TREE_CODE (init) == CONSTRUCTOR || TREE_CODE (init) == VECTOR_CST)
+	  && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+	break;
+      /* If the variable has a dynamic initializer, don't use its
+	 DECL_INITIAL which doesn't reflect the real value.  */
+      if (VAR_P (decl) && TREE_STATIC (decl)
+	  && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
+	  && DECL_NONTRIVIALLY_INITIALIZED_P (decl))
+	break;
+      decl = init;
+    }
+  return unshare_p ? unshare_expr (decl) : decl;
+}
+
+// forked from gcc/cp/init.cc decl_constant_value
+
+/* A more relaxed version of decl_really_constant_value, used by the
+   common C/C++ code.  */
+
+tree
+decl_constant_value (tree decl, bool unshare_p)
+{
+  return constant_value_1 (decl, /*strict_p=*/false,
+			   /*return_aggregate_cst_ok_p=*/true,
+			   /*unshare_p=*/unshare_p);
+}
+
+// Below is forked from gcc/cp/init.cc decl_constant_value
+
+tree
+decl_constant_value (tree decl)
+{
+  return decl_constant_value (decl, /*unshare_p=*/true);
+}
+
+// Below is forked from gcc/cp/cp-gimplify.cc
+
+/* Type for source_location_table hash_set.  */
+struct GTY ((for_user)) source_location_table_entry
+{
+  location_t loc;
+  unsigned uid;
+  tree var;
+};
+
+/* Traits class for function start hash maps below.  */
+
+struct source_location_table_entry_hash
+  : ggc_remove<source_location_table_entry>
+{
+  typedef source_location_table_entry value_type;
+  typedef source_location_table_entry compare_type;
+
+  static hashval_t hash (const source_location_table_entry &ref)
+  {
+    inchash::hash hstate (0);
+    hstate.add_int (ref.loc);
+    hstate.add_int (ref.uid);
+    return hstate.end ();
+  }
+
+  static bool equal (const source_location_table_entry &ref1,
+		     const source_location_table_entry &ref2)
+  {
+    return ref1.loc == ref2.loc && ref1.uid == ref2.uid;
+  }
+
+  static void mark_deleted (source_location_table_entry &ref)
+  {
+    ref.loc = UNKNOWN_LOCATION;
+    ref.uid = -1U;
+    ref.var = NULL_TREE;
+  }
+
+  static const bool empty_zero_p = true;
+
+  static void mark_empty (source_location_table_entry &ref)
+  {
+    ref.loc = UNKNOWN_LOCATION;
+    ref.uid = 0;
+    ref.var = NULL_TREE;
+  }
+
+  static bool is_deleted (const source_location_table_entry &ref)
+  {
+    return (ref.loc == UNKNOWN_LOCATION && ref.uid == -1U
+	    && ref.var == NULL_TREE);
+  }
+
+  static bool is_empty (const source_location_table_entry &ref)
+  {
+    return (ref.loc == UNKNOWN_LOCATION && ref.uid == 0
+	    && ref.var == NULL_TREE);
+  }
+
+  static void pch_nx (source_location_table_entry &p)
+  {
+    extern void gt_pch_nx (source_location_table_entry &);
+    gt_pch_nx (p);
+  }
+
+  static void pch_nx (source_location_table_entry &p, gt_pointer_operator op,
+		      void *cookie)
+  {
+    extern void gt_pch_nx (source_location_table_entry *, gt_pointer_operator,
+			   void *);
+    gt_pch_nx (&p, op, cookie);
+  }
+};
+
+static GTY (())
+  hash_table<source_location_table_entry_hash> *source_location_table;
+static GTY (()) unsigned int source_location_id;
+
+// Above is forked from gcc/cp/cp-gimplify.cc
+
+// forked from gcc/cp/tree.cc lvalue_kind
+
+/* If REF is an lvalue, returns the kind of lvalue that REF is.
+   Otherwise, returns clk_none.  */
+
+cp_lvalue_kind
+lvalue_kind (const_tree ref)
+{
+  cp_lvalue_kind op1_lvalue_kind = clk_none;
+  cp_lvalue_kind op2_lvalue_kind = clk_none;
+
+  /* Expressions of reference type are sometimes wrapped in
+     INDIRECT_REFs.  INDIRECT_REFs are just internal compiler
+     representation, not part of the language, so we have to look
+     through them.  */
+  if (REFERENCE_REF_P (ref))
+    return lvalue_kind (TREE_OPERAND (ref, 0));
+
+  if (TREE_TYPE (ref) && TYPE_REF_P (TREE_TYPE (ref)))
+    {
+      /* unnamed rvalue references are rvalues */
+      if (TYPE_REF_IS_RVALUE (TREE_TYPE (ref)) && TREE_CODE (ref) != PARM_DECL
+	  && !VAR_P (ref)
+	  && TREE_CODE (ref) != COMPONENT_REF
+	  /* Functions are always lvalues.  */
+	  && TREE_CODE (TREE_TYPE (TREE_TYPE (ref))) != FUNCTION_TYPE)
+	{
+	  op1_lvalue_kind = clk_rvalueref;
+	  if (implicit_rvalue_p (ref))
+	    op1_lvalue_kind |= clk_implicit_rval;
+	  return op1_lvalue_kind;
+	}
+
+      /* lvalue references and named rvalue references are lvalues.  */
+      return clk_ordinary;
+    }
+
+  if (ref == current_class_ptr)
+    return clk_none;
+
+  /* Expressions with cv void type are prvalues.  */
+  if (TREE_TYPE (ref) && VOID_TYPE_P (TREE_TYPE (ref)))
+    return clk_none;
+
+  switch (TREE_CODE (ref))
+    {
+    case SAVE_EXPR:
+      return clk_none;
+
+      /* preincrements and predecrements are valid lvals, provided
+	 what they refer to are valid lvals.  */
+    case PREINCREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+    case TRY_CATCH_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+    case VIEW_CONVERT_EXPR:
+      return lvalue_kind (TREE_OPERAND (ref, 0));
+
+      case ARRAY_REF: {
+	tree op1 = TREE_OPERAND (ref, 0);
+	if (TREE_CODE (TREE_TYPE (op1)) == ARRAY_TYPE)
+	  {
+	    op1_lvalue_kind = lvalue_kind (op1);
+	    if (op1_lvalue_kind == clk_class)
+	      /* in the case of an array operand, the result is an lvalue if
+		 that operand is an lvalue and an xvalue otherwise */
+	      op1_lvalue_kind = clk_rvalueref;
+	    return op1_lvalue_kind;
+	  }
+	else
+	  return clk_ordinary;
+      }
+
+    case MEMBER_REF:
+    case DOTSTAR_EXPR:
+      if (TREE_CODE (ref) == MEMBER_REF)
+	op1_lvalue_kind = clk_ordinary;
+      else
+	op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0));
+      if (TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (ref, 1))))
+	op1_lvalue_kind = clk_none;
+      else if (op1_lvalue_kind == clk_class)
+	/* The result of a .* expression whose second operand is a pointer to a
+	   data member is an lvalue if the first operand is an lvalue and an
+	   xvalue otherwise.  */
+	op1_lvalue_kind = clk_rvalueref;
+      return op1_lvalue_kind;
+
+    case COMPONENT_REF:
+      op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0));
+      if (op1_lvalue_kind == clk_class)
+	/* If E1 is an lvalue, then E1.E2 is an lvalue;
+	   otherwise E1.E2 is an xvalue.  */
+	op1_lvalue_kind = clk_rvalueref;
+
+      /* Look at the member designator.  */
+      if (!op1_lvalue_kind)
+	;
+      else if (is_overloaded_fn (TREE_OPERAND (ref, 1)))
+	/* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
+	   situations.  If we're seeing a COMPONENT_REF, it's a non-static
+	   member, so it isn't an lvalue. */
+	op1_lvalue_kind = clk_none;
+      else if (TREE_CODE (TREE_OPERAND (ref, 1)) != FIELD_DECL)
+	/* This can be IDENTIFIER_NODE in a template.  */;
+      else if (DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
+	{
+	  /* Clear the ordinary bit.  If this object was a class
+	     rvalue we want to preserve that information.  */
+	  op1_lvalue_kind &= ~clk_ordinary;
+	  /* The lvalue is for a bitfield.  */
+	  op1_lvalue_kind |= clk_bitfield;
+	}
+      else if (DECL_PACKED (TREE_OPERAND (ref, 1)))
+	op1_lvalue_kind |= clk_packed;
+
+      return op1_lvalue_kind;
+
+    case STRING_CST:
+    case COMPOUND_LITERAL_EXPR:
+      return clk_ordinary;
+
+    case CONST_DECL:
+      /* CONST_DECL without TREE_STATIC are enumeration values and
+	 thus not lvalues.  With TREE_STATIC they are used by ObjC++
+	 in objc_build_string_object and need to be considered as
+	 lvalues.  */
+      if (!TREE_STATIC (ref))
+	return clk_none;
+      /* FALLTHRU */
+    case VAR_DECL:
+      if (VAR_P (ref) && DECL_HAS_VALUE_EXPR_P (ref))
+	return lvalue_kind (DECL_VALUE_EXPR (CONST_CAST_TREE (ref)));
+
+      if (TREE_READONLY (ref) && !TREE_STATIC (ref) && DECL_LANG_SPECIFIC (ref)
+	  && DECL_IN_AGGR_P (ref))
+	return clk_none;
+      /* FALLTHRU */
+    case INDIRECT_REF:
+    case ARROW_EXPR:
+    case PARM_DECL:
+    case RESULT_DECL:
+    case PLACEHOLDER_EXPR:
+      return clk_ordinary;
+
+    case MAX_EXPR:
+    case MIN_EXPR:
+      /* Disallow <? and >? as lvalues if either argument side-effects.  */
+      if (TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 0))
+	  || TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 1)))
+	return clk_none;
+      op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0));
+      op2_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 1));
+      break;
+
+      case COND_EXPR: {
+	tree op1 = TREE_OPERAND (ref, 1);
+	if (!op1)
+	  op1 = TREE_OPERAND (ref, 0);
+	tree op2 = TREE_OPERAND (ref, 2);
+	op1_lvalue_kind = lvalue_kind (op1);
+	op2_lvalue_kind = lvalue_kind (op2);
+	if (!op1_lvalue_kind != !op2_lvalue_kind)
+	  {
+	    /* The second or the third operand (but not both) is a
+	       throw-expression; the result is of the type
+	       and value category of the other.  */
+	    if (op1_lvalue_kind && TREE_CODE (op2) == THROW_EXPR)
+	      op2_lvalue_kind = op1_lvalue_kind;
+	    else if (op2_lvalue_kind && TREE_CODE (op1) == THROW_EXPR)
+	      op1_lvalue_kind = op2_lvalue_kind;
+	  }
+      }
+      break;
+
+    case MODIFY_EXPR:
+    case TYPEID_EXPR:
+      return clk_ordinary;
+
+    case COMPOUND_EXPR:
+      return lvalue_kind (TREE_OPERAND (ref, 1));
+
+    case TARGET_EXPR:
+      return clk_class;
+
+    case VA_ARG_EXPR:
+      return (CLASS_TYPE_P (TREE_TYPE (ref)) ? clk_class : clk_none);
+
+    case CALL_EXPR:
+      /* We can see calls outside of TARGET_EXPR in templates.  */
+      if (CLASS_TYPE_P (TREE_TYPE (ref)))
+	return clk_class;
+      return clk_none;
+
+    case FUNCTION_DECL:
+      /* All functions (except non-static-member functions) are
+	 lvalues.  */
+      return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref) ? clk_none : clk_ordinary);
+
+    case NON_DEPENDENT_EXPR:
+    case PAREN_EXPR:
+      return lvalue_kind (TREE_OPERAND (ref, 0));
+
+    case TEMPLATE_PARM_INDEX:
+      if (CLASS_TYPE_P (TREE_TYPE (ref)))
+	/* A template parameter object is an lvalue.  */
+	return clk_ordinary;
+      return clk_none;
+
+    default:
+    default_:
+      if (!TREE_TYPE (ref))
+	return clk_none;
+      if (CLASS_TYPE_P (TREE_TYPE (ref))
+	  || TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
+	return clk_class;
+      return clk_none;
+    }
+
+  /* If one operand is not an lvalue at all, then this expression is
+     not an lvalue.  */
+  if (!op1_lvalue_kind || !op2_lvalue_kind)
+    return clk_none;
+
+  /* Otherwise, it's an lvalue, and it has all the odd properties
+     contributed by either operand.  */
+  op1_lvalue_kind = op1_lvalue_kind | op2_lvalue_kind;
+  /* It's not an ordinary lvalue if it involves any other kind.  */
+  if ((op1_lvalue_kind & ~clk_ordinary) != clk_none)
+    op1_lvalue_kind &= ~clk_ordinary;
+  /* It can't be both a pseudo-lvalue and a non-addressable lvalue.
+     A COND_EXPR of those should be wrapped in a TARGET_EXPR.  */
+  if ((op1_lvalue_kind & (clk_rvalueref | clk_class))
+      && (op1_lvalue_kind & (clk_bitfield | clk_packed)))
+    op1_lvalue_kind = clk_none;
+  return op1_lvalue_kind;
+}
+
+// forked from gcc/cp/tree.cc glvalue_p
+
+/* This differs from lvalue_p in that xvalues are included.  */
+
+bool
+glvalue_p (const_tree ref)
+{
+  cp_lvalue_kind kind = lvalue_kind (ref);
+  if (kind & clk_class)
+    return false;
+  else
+    return (kind != clk_none);
+}
+
+// forked from gcc/cp/init.cc cv_qualified_p
+
+/* Returns nonzero if TYPE is const or volatile.  */
+
+bool
+cv_qualified_p (const_tree type)
+{
+  int quals = rs_type_quals (type);
+  return (quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)) != 0;
+}
+
+// forked from gcc/cp/tree.cc rvalue
+
+/* EXPR is being used in an rvalue context.  Return a version of EXPR
+   that is marked as an rvalue.  */
+
+tree
+rvalue (tree expr)
+{
+  tree type;
+
+  if (error_operand_p (expr))
+    return expr;
+
+  expr = mark_rvalue_use (expr);
+
+  /* [basic.lval]
+
+     Non-class rvalues always have cv-unqualified types.  */
+  type = TREE_TYPE (expr);
+  if (!CLASS_TYPE_P (type) && cv_qualified_p (type))
+    type = cv_unqualified (type);
+
+  /* We need to do this for rvalue refs as well to get the right answer
+     from decltype; see c++/36628.  */
+  if (glvalue_p (expr))
+    {
+      /* But don't use this function for class lvalues; use move (to treat an
+	 lvalue as an xvalue) or force_rvalue (to make a prvalue copy).  */
+      gcc_checking_assert (!CLASS_TYPE_P (type));
+      expr = build1 (NON_LVALUE_EXPR, type, expr);
+    }
+  else if (type != TREE_TYPE (expr))
+    expr = build_nop (type, expr);
+
+  return expr;
+}
+
+// forked from gcc/cp/tree.cc bitfield_p
+
+/* True if REF is a bit-field.  */
+
+bool
+bitfield_p (const_tree ref)
+{
+  return (lvalue_kind (ref) & clk_bitfield);
+}
+
+// forked from gcc/cp/typeck.cc cxx_mark_addressable
+
+/* Mark EXP saying that we need to be able to take the
+   address of it; it should not be allocated in a register.
+   Value is true if successful.  ARRAY_REF_P is true if this
+   is for ARRAY_REF construction - in that case we don't want
+   to look through VIEW_CONVERT_EXPR from VECTOR_TYPE to ARRAY_TYPE,
+   it is fine to use ARRAY_REFs for vector subscripts on vector
+   register variables.
+
+   C++: we do not allow `current_class_ptr' to be addressable.  */
+
+bool
+cxx_mark_addressable (tree exp, bool array_ref_p)
+{
+  tree x = exp;
+
+  while (1)
+    switch (TREE_CODE (x))
+      {
+      case VIEW_CONVERT_EXPR:
+	if (array_ref_p && TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
+	    && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))))
+	  return true;
+	x = TREE_OPERAND (x, 0);
+	break;
+
+      case COMPONENT_REF:
+	if (bitfield_p (x))
+	  error ("attempt to take address of bit-field");
+	/* FALLTHRU */
+      case ADDR_EXPR:
+      case ARRAY_REF:
+      case REALPART_EXPR:
+      case IMAGPART_EXPR:
+	x = TREE_OPERAND (x, 0);
+	break;
+
+      case PARM_DECL:
+	if (x == current_class_ptr)
+	  {
+	    error ("cannot take the address of %<this%>, which is an rvalue "
+		   "expression");
+	    TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later.  */
+	    return true;
+	  }
+	/* Fall through.  */
+
+      case VAR_DECL:
+	/* Caller should not be trying to mark initialized
+	   constant fields addressable.  */
+	gcc_assert (DECL_LANG_SPECIFIC (x) == 0 || DECL_IN_AGGR_P (x) == 0
+		    || TREE_STATIC (x) || DECL_EXTERNAL (x));
+	/* Fall through.  */
+
+      case RESULT_DECL:
+	if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x) && !DECL_ARTIFICIAL (x))
+	  {
+	    if (VAR_P (x) && DECL_HARD_REGISTER (x))
+	      {
+		error ("address of explicit register variable %qD requested",
+		       x);
+		return false;
+	      }
+	    else if (extra_warnings)
+	      warning (
+		OPT_Wextra,
+		"address requested for %qD, which is declared %<register%>", x);
+	  }
+	TREE_ADDRESSABLE (x) = 1;
+	return true;
+
+      case CONST_DECL:
+      case FUNCTION_DECL:
+	TREE_ADDRESSABLE (x) = 1;
+	return true;
+
+      case CONSTRUCTOR:
+	TREE_ADDRESSABLE (x) = 1;
+	return true;
+
+      case TARGET_EXPR:
+	TREE_ADDRESSABLE (x) = 1;
+	cxx_mark_addressable (TREE_OPERAND (x, 0));
+	return true;
+
+      default:
+	return true;
+      }
+}
+
+// forked from gcc/cp/typeck.cc build_address
+
+/* Returns the address of T.  This function will fold away
+   ADDR_EXPR of INDIRECT_REF.  This is only for low-level usage;
+   most places should use cp_build_addr_expr instead.  */
+
+tree
+build_address (tree t)
+{
+  if (error_operand_p (t) || !cxx_mark_addressable (t))
+    return error_mark_node;
+  gcc_checking_assert (TREE_CODE (t) != CONSTRUCTOR);
+  t = build_fold_addr_expr_loc (EXPR_LOCATION (t), t);
+  if (TREE_CODE (t) != ADDR_EXPR)
+    t = rvalue (t);
+  return t;
+}
+
+// forked from gcc/cp/gp-gimplify.cc fold_builtin_source_location
+
+/* Fold __builtin_source_location () call.  LOC is the location
+   of the call.  */
+
+tree
+fold_builtin_source_location (location_t loc)
+{
+  if (source_location_impl == error_mark_node)
+    return build_zero_cst (const_ptr_type_node);
+  if (source_location_table == NULL)
+    source_location_table
+      = hash_table<source_location_table_entry_hash>::create_ggc (64);
+  const line_map_ordinary *map;
+  source_location_table_entry entry;
+  entry.loc = linemap_resolve_location (line_table, loc,
+					LRK_MACRO_EXPANSION_POINT, &map);
+  entry.uid = current_function_decl ? DECL_UID (current_function_decl) : -1;
+  entry.var = error_mark_node;
+  source_location_table_entry *entryp
+    = source_location_table->find_slot (entry, INSERT);
+  tree var;
+  if (entryp->var)
+    var = entryp->var;
+  else
+    {
+      char tmp_name[32];
+      ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lsrc_loc", source_location_id++);
+      var = build_decl (loc, VAR_DECL, get_identifier (tmp_name),
+			source_location_impl);
+      TREE_STATIC (var) = 1;
+      TREE_PUBLIC (var) = 0;
+      DECL_ARTIFICIAL (var) = 1;
+      DECL_IGNORED_P (var) = 1;
+      DECL_EXTERNAL (var) = 0;
+      DECL_DECLARED_CONSTEXPR_P (var) = 1;
+      DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (var) = 1;
+      layout_decl (var, 0);
+
+      vec<constructor_elt, va_gc> *v = NULL;
+      vec_alloc (v, 4);
+      for (tree field = TYPE_FIELDS (source_location_impl);
+	   (field = next_initializable_field (field)) != NULL_TREE;
+	   field = DECL_CHAIN (field))
+	{
+	  const char *n = IDENTIFIER_POINTER (DECL_NAME (field));
+	  tree val = NULL_TREE;
+	  if (strcmp (n, "_M_file_name") == 0)
+	    {
+	      if (const char *fname = LOCATION_FILE (loc))
+		{
+		  fname = remap_macro_filename (fname);
+		  val = build_string_literal (strlen (fname) + 1, fname);
+		}
+	      else
+		val = build_string_literal (1, "");
+	    }
+	  else if (strcmp (n, "_M_function_name") == 0)
+	    {
+	      const char *name = "todo: add funciton name here";
+
+	      // if (current_function_decl)
+	      // name = cxx_printable_name (current_function_decl, 2);
+
+	      val = build_string_literal (strlen (name) + 1, name);
+	    }
+	  else if (strcmp (n, "_M_line") == 0)
+	    val = build_int_cst (TREE_TYPE (field), LOCATION_LINE (loc));
+	  else if (strcmp (n, "_M_column") == 0)
+	    val = build_int_cst (TREE_TYPE (field), LOCATION_COLUMN (loc));
+	  else
+	    gcc_unreachable ();
+	  CONSTRUCTOR_APPEND_ELT (v, field, val);
+	}
+
+      tree ctor = build_constructor (source_location_impl, v);
+      TREE_CONSTANT (ctor) = 1;
+      TREE_STATIC (ctor) = 1;
+      DECL_INITIAL (var) = ctor;
+      varpool_node::finalize_decl (var);
+      *entryp = entry;
+      entryp->var = var;
+    }
+
+  return build_fold_addr_expr_with_type_loc (loc, var, const_ptr_type_node);
+}
+
 } // namespace Rust
diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h
index 9efa4096bf6..bb3b4304372 100644
--- a/gcc/rust/backend/rust-tree.h
+++ b/gcc/rust/backend/rust-tree.h
@@ -1279,6 +1279,24 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
 #define TARGET_EXPR_DIRECT_INIT_P(NODE)                                        \
   TREE_LANG_FLAG_2 (TARGET_EXPR_CHECK (NODE))
 
+/* Nonzero if DECL is a declaration of __builtin_constant_p.  */
+#define DECL_IS_BUILTIN_CONSTANT_P(NODE)                                       \
+  (TREE_CODE (NODE) == FUNCTION_DECL                                           \
+   && DECL_BUILT_IN_CLASS (NODE) == BUILT_IN_NORMAL                            \
+   && DECL_FUNCTION_CODE (NODE) == BUILT_IN_CONSTANT_P)
+
+/* True iff this represents an lvalue being treated as an rvalue during return
+   or throw as per [class.copy.elision].  */
+#define IMPLICIT_RVALUE_P(NODE)                                                \
+  TREE_LANG_FLAG_3 (TREE_CHECK2 ((NODE), NON_LVALUE_EXPR, STATIC_CAST_EXPR))
+
+/* Nonzero for _DECL means that this decl appears in (or will appear
+   in) as a member in a RECORD_TYPE or UNION_TYPE node.  It is also for
+   detecting circularity in case members are multiply defined.  In the
+   case of a VAR_DECL, it means that no definition has been seen, even
+   if an initializer has been.  */
+#define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3 (NODE))
+
 #if defined ENABLE_TREE_CHECKING
 
 #define LANG_DECL_MIN_CHECK(NODE)                                              \
@@ -1400,6 +1418,16 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
 
 // Above macros are copied from gcc/c-family/c-common.h
 
+// Below macros are copied from gcc/cp/name-lookup.h
+
+/* Lookup walker marking.  */
+#define LOOKUP_SEEN_P(NODE) TREE_VISITED (NODE)
+#define LOOKUP_FOUND_P(NODE)                                                   \
+  TREE_LANG_FLAG_4 (TREE_CHECK4 (NODE, RECORD_TYPE, UNION_TYPE, ENUMERAL_TYPE, \
+				 NAMESPACE_DECL))
+
+// Above macros are copied from gcc/cp/name-lookup.h
+
 // Below macros are copied from gcc/cp/name-lookup.cc
 
 /* Create an overload suitable for recording an artificial TYPE_DECL
@@ -1435,6 +1463,22 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
 
 // Above macros are copied from gcc/cp/name-lookup.cc
 
+/* The various kinds of lvalues we distinguish.  */
+enum cp_lvalue_kind_flags
+{
+  clk_none = 0,	     /* Things that are not an lvalue.  */
+  clk_ordinary = 1,  /* An ordinary lvalue.  */
+  clk_rvalueref = 2, /* An xvalue (rvalue formed using an rvalue reference) */
+  clk_class = 4,     /* A prvalue of class or array type.  */
+  clk_bitfield = 8,  /* An lvalue for a bit-field.  */
+  clk_packed = 16,   /* An lvalue for a packed field.  */
+  clk_implicit_rval = 1 << 5 /* An lvalue being treated as an xvalue.  */
+};
+
+/* This type is used for parameters and variables which hold
+   combinations of the flags in enum cp_lvalue_kind_flags.  */
+typedef int cp_lvalue_kind;
+
 // forked from gcc/cp/name_lookup.h scope_kind
 
 /* The kinds of scopes we recognize.  */
@@ -2673,6 +2717,29 @@ in_immediate_context ();
 
 extern tree cp_get_callee_fndecl_nofold (tree);
 
+extern bool
+cxx_mark_addressable (tree, bool = false);
+
+extern tree fold_builtin_source_location (location_t);
+
+extern tree build_address (tree);
+
+extern bool bitfield_p (const_tree);
+
+extern tree rvalue (tree);
+
+extern bool glvalue_p (const_tree);
+
+extern cp_lvalue_kind lvalue_kind (const_tree);
+
+extern tree
+decl_constant_value (tree, bool);
+
+extern tree lookup_enumerator (tree, tree);
+
+extern int
+is_class_type (tree, int);
+
 // forked from gcc/cp/cp-tree.h
 
 enum
@@ -2875,6 +2942,25 @@ cxx_incomplete_type_error (const_tree value, const_tree type)
 extern location_t
 location_of (tree t);
 
+/* Helpers for IMPLICIT_RVALUE_P to look through automatic dereference.  */
+
+inline bool
+implicit_rvalue_p (const_tree t)
+{
+  if (REFERENCE_REF_P (t))
+    t = TREE_OPERAND (t, 0);
+  return ((TREE_CODE (t) == NON_LVALUE_EXPR) && IMPLICIT_RVALUE_P (t));
+}
+inline tree
+set_implicit_rvalue_p (tree ot)
+{
+  tree t = ot;
+  if (REFERENCE_REF_P (t))
+    t = TREE_OPERAND (t, 0);
+  IMPLICIT_RVALUE_P (t) = 1;
+  return ot;
+}
+
 namespace Compile {
 extern tree
 maybe_constant_init (tree, tree = NULL_TREE, bool = false);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-08-29 15:34 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-29 15:34 [gcc/devel/rust/master] rust constexprC: start porting cxx_eval_builtin_function_call Thomas Schwinge

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).