]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cfgexpand.c
c++: Handle multiple aggregate overloads [PR95319].
[thirdparty/gcc.git] / gcc / cfgexpand.c
index 5a93447f520f1ea8b739249bfdfec56775c91f79..2f6ec97ed04f2023d71be8bb5b40bd74333a24f4 100644 (file)
@@ -1,5 +1,5 @@
 /* A pass for lowering trees to RTL.
-   Copyright (C) 2004-2019 Free Software Foundation, Inc.
+   Copyright (C) 2004-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -61,7 +61,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-pretty-print.h"
 #include "toplev.h"
 #include "debug.h"
-#include "params.h"
 #include "tree-inline.h"
 #include "value-prof.h"
 #include "tree-ssa-live.h"
@@ -104,38 +103,38 @@ tree
 gimple_assign_rhs_to_tree (gimple *stmt)
 {
   tree t;
-  enum gimple_rhs_class grhs_class;
-
-  grhs_class = get_gimple_rhs_class (gimple_expr_code (stmt));
-
-  if (grhs_class == GIMPLE_TERNARY_RHS)
-    t = build3 (gimple_assign_rhs_code (stmt),
-               TREE_TYPE (gimple_assign_lhs (stmt)),
-               gimple_assign_rhs1 (stmt),
-               gimple_assign_rhs2 (stmt),
-               gimple_assign_rhs3 (stmt));
-  else if (grhs_class == GIMPLE_BINARY_RHS)
-    t = build2 (gimple_assign_rhs_code (stmt),
-               TREE_TYPE (gimple_assign_lhs (stmt)),
-               gimple_assign_rhs1 (stmt),
-               gimple_assign_rhs2 (stmt));
-  else if (grhs_class == GIMPLE_UNARY_RHS)
-    t = build1 (gimple_assign_rhs_code (stmt),
-               TREE_TYPE (gimple_assign_lhs (stmt)),
-               gimple_assign_rhs1 (stmt));
-  else if (grhs_class == GIMPLE_SINGLE_RHS)
-    {
-      t = gimple_assign_rhs1 (stmt);
-      /* Avoid modifying this tree in place below.  */
-      if ((gimple_has_location (stmt) && CAN_HAVE_LOCATION_P (t)
-          && gimple_location (stmt) != EXPR_LOCATION (t))
-         || (gimple_block (stmt)
-             && currently_expanding_to_rtl
-             && EXPR_P (t)))
-       t = copy_node (t);
+  switch (get_gimple_rhs_class (gimple_expr_code (stmt)))
+    {
+    case GIMPLE_TERNARY_RHS:
+      t = build3 (gimple_assign_rhs_code (stmt),
+                 TREE_TYPE (gimple_assign_lhs (stmt)),
+                 gimple_assign_rhs1 (stmt), gimple_assign_rhs2 (stmt),
+                 gimple_assign_rhs3 (stmt));
+      break;
+    case GIMPLE_BINARY_RHS:
+      t = build2 (gimple_assign_rhs_code (stmt),
+                 TREE_TYPE (gimple_assign_lhs (stmt)),
+                 gimple_assign_rhs1 (stmt), gimple_assign_rhs2 (stmt));
+      break;
+    case GIMPLE_UNARY_RHS:
+      t = build1 (gimple_assign_rhs_code (stmt),
+                 TREE_TYPE (gimple_assign_lhs (stmt)),
+                 gimple_assign_rhs1 (stmt));
+      break;
+    case GIMPLE_SINGLE_RHS:
+      {
+       t = gimple_assign_rhs1 (stmt);
+       /* Avoid modifying this tree in place below.  */
+       if ((gimple_has_location (stmt) && CAN_HAVE_LOCATION_P (t)
+            && gimple_location (stmt) != EXPR_LOCATION (t))
+           || (gimple_block (stmt) && currently_expanding_to_rtl
+               && EXPR_P (t)))
+         t = copy_node (t);
+       break;
+      }
+    default:
+      gcc_unreachable ();
     }
-  else
-    gcc_unreachable ();
 
   if (gimple_has_location (stmt) && CAN_HAVE_LOCATION_P (t))
     SET_EXPR_LOCATION (t, gimple_location (stmt));
@@ -863,6 +862,9 @@ union_stack_vars (size_t a, size_t b)
   stack_vars[b].representative = a;
   stack_vars[a].next = b;
 
+  /* Make sure A is big enough to hold B.  */
+  stack_vars[a].size = upper_bound (stack_vars[a].size, stack_vars[b].size);
+
   /* Update the required alignment of partition A to account for B.  */
   if (stack_vars[a].alignb < stack_vars[b].alignb)
     stack_vars[a].alignb = stack_vars[b].alignb;
@@ -1548,7 +1550,7 @@ defer_stack_allocation (tree var, bool toplevel)
   bool smallish
     = (poly_int_tree_p (size_unit, &size)
        && (estimated_poly_value (size)
-          < PARAM_VALUE (PARAM_MIN_SIZE_FOR_STACK_SHARING)));
+          < param_min_size_for_stack_sharing));
 
   /* If stack protection is enabled, *all* stack variables must be deferred,
      so that we can re-order the strings to the top of the frame.
@@ -1788,7 +1790,7 @@ stack_protect_classify_type (tree type)
          || t == signed_char_type_node
          || t == unsigned_char_type_node)
        {
-         unsigned HOST_WIDE_INT max = PARAM_VALUE (PARAM_SSP_BUFFER_SIZE);
+         unsigned HOST_WIDE_INT max = param_ssp_buffer_size;
          unsigned HOST_WIDE_INT len;
 
          if (!TYPE_SIZE_UNIT (type)
@@ -1889,17 +1891,23 @@ asan_decl_phase_3 (size_t i)
 }
 
 /* Ensure that variables in different stack protection phases conflict
-   so that they are not merged and share the same stack slot.  */
+   so that they are not merged and share the same stack slot.
+   Return true if there are any address taken variables.  */
 
-static void
+static bool
 add_stack_protection_conflicts (void)
 {
   size_t i, j, n = stack_vars_num;
   unsigned char *phase;
+  bool ret = false;
 
   phase = XNEWVEC (unsigned char, n);
   for (i = 0; i < n; ++i)
-    phase[i] = stack_protect_decl_phase (stack_vars[i].decl);
+    {
+      phase[i] = stack_protect_decl_phase (stack_vars[i].decl);
+      if (TREE_ADDRESSABLE (stack_vars[i].decl))
+       ret = true;
+    }
 
   for (i = 0; i < n; ++i)
     {
@@ -1910,6 +1918,7 @@ add_stack_protection_conflicts (void)
     }
 
   XDELETEVEC (phase);
+  return ret;
 }
 
 /* Create a decl for the guard at the top of the stack frame.  */
@@ -1994,50 +2003,6 @@ estimated_stack_frame_size (struct cgraph_node *node)
   return estimated_poly_value (size);
 }
 
-/* Helper routine to check if a record or union contains an array field. */
-
-static int
-record_or_union_type_has_array_p (const_tree tree_type)
-{
-  tree fields = TYPE_FIELDS (tree_type);
-  tree f;
-
-  for (f = fields; f; f = DECL_CHAIN (f))
-    if (TREE_CODE (f) == FIELD_DECL)
-      {
-       tree field_type = TREE_TYPE (f);
-       if (RECORD_OR_UNION_TYPE_P (field_type)
-           && record_or_union_type_has_array_p (field_type))
-         return 1;
-       if (TREE_CODE (field_type) == ARRAY_TYPE)
-         return 1;
-      }
-  return 0;
-}
-
-/* Check if the current function has local referenced variables that
-   have their addresses taken, contain an array, or are arrays.  */
-
-static bool
-stack_protect_decl_p ()
-{
-  unsigned i;
-  tree var;
-
-  FOR_EACH_LOCAL_DECL (cfun, i, var)
-    if (!is_global_var (var))
-      {
-       tree var_type = TREE_TYPE (var);
-       if (VAR_P (var)
-           && (TREE_CODE (var_type) == ARRAY_TYPE
-               || TREE_ADDRESSABLE (var)
-               || (RECORD_OR_UNION_TYPE_P (var_type)
-                   && record_or_union_type_has_array_p (var_type))))
-         return true;
-      }
-  return false;
-}
-
 /* Check if the current function has calls that use a return slot.  */
 
 static bool
@@ -2104,8 +2069,7 @@ expand_used_vars (void)
     }
 
   if (flag_stack_protect == SPCT_FLAG_STRONG)
-      gen_stack_protect_signal
-       = stack_protect_decl_p () || stack_protect_return_slot_p ();
+    gen_stack_protect_signal = stack_protect_return_slot_p ();
 
   /* At this point all variables on the local_decls with TREE_USED
      set are not associated with any block scope.  Lay them out.  */
@@ -2181,6 +2145,8 @@ expand_used_vars (void)
 
   if (stack_vars_num > 0)
     {
+      bool has_addressable_vars = false;
+
       add_scope_conflicts ();
 
       /* If stack protection is enabled, we don't share space between
@@ -2190,7 +2156,10 @@ expand_used_vars (void)
              || (flag_stack_protect == SPCT_FLAG_EXPLICIT
                  && lookup_attribute ("stack_protect",
                                       DECL_ATTRIBUTES (current_function_decl)))))
-       add_stack_protection_conflicts ();
+       has_addressable_vars = add_stack_protection_conflicts ();
+
+      if (flag_stack_protect == SPCT_FLAG_STRONG && has_addressable_vars)
+       gen_stack_protect_signal = true;
 
       /* Now that we have collected all stack variables, and have computed a
         minimal interference graph, attempt to save some stack space.  */
@@ -2207,14 +2176,16 @@ expand_used_vars (void)
 
     case SPCT_FLAG_STRONG:
       if (gen_stack_protect_signal
-         || cfun->calls_alloca || has_protected_decls
+         || cfun->calls_alloca
+         || has_protected_decls
          || lookup_attribute ("stack_protect",
                               DECL_ATTRIBUTES (current_function_decl)))
        create_stack_guard ();
       break;
 
     case SPCT_FLAG_DEFAULT:
-      if (cfun->calls_alloca || has_protected_decls
+      if (cfun->calls_alloca
+         || has_protected_decls
          || lookup_attribute ("stack_protect",
                               DECL_ATTRIBUTES (current_function_decl)))
        create_stack_guard ();
@@ -2225,8 +2196,9 @@ expand_used_vars (void)
                            DECL_ATTRIBUTES (current_function_decl)))
        create_stack_guard ();
       break;
+
     default:
-      ;
+      break;
     }
 
   /* Assign rtl to each variable based on these partitions.  */
@@ -3891,7 +3863,6 @@ expand_gimple_stmt (gimple *stmt)
              /* If we want exceptions for non-call insns, any
                 may_trap_p instruction may throw.  */
              && GET_CODE (PATTERN (insn)) != CLOBBER
-             && GET_CODE (PATTERN (insn)) != CLOBBER_HIGH
              && GET_CODE (PATTERN (insn)) != USE
              && insn_could_throw_p (insn))
            make_reg_eh_region_note (insn, 0, lp_nr);
@@ -5192,6 +5163,7 @@ expand_debug_expr (tree exp)
     case VEC_PERM_EXPR:
     case VEC_DUPLICATE_EXPR:
     case VEC_SERIES_EXPR:
+    case SAD_EXPR:
       return NULL;
 
     /* Misc codes.  */
@@ -6135,10 +6107,48 @@ discover_nonconstant_array_refs_r (tree * tp, int *walk_subtrees,
 
       *walk_subtrees = 0;
     }
+  /* References of size POLY_INT_CST to a fixed-size object must go
+     through memory.  It's more efficient to force that here than
+     to create temporary slots on the fly.  */
+  else if ((TREE_CODE (t) == MEM_REF || TREE_CODE (t) == TARGET_MEM_REF)
+          && TYPE_SIZE (TREE_TYPE (t))
+          && POLY_INT_CST_P (TYPE_SIZE (TREE_TYPE (t))))
+    {
+      tree base = get_base_address (t);
+      if (base
+         && DECL_P (base)
+         && DECL_MODE (base) != BLKmode
+         && GET_MODE_SIZE (DECL_MODE (base)).is_constant ())
+       TREE_ADDRESSABLE (base) = 1;
+      *walk_subtrees = 0;
+    }
 
   return NULL_TREE;
 }
 
+/* If there's a chance to get a pseudo for t then if it would be of float mode
+   and the actual access is via an integer mode (lowered memcpy or similar
+   access) then avoid the register expansion if the mode likely is not storage
+   suitable for raw bits processing (like XFmode on i?86).  */
+
+static void
+avoid_type_punning_on_regs (tree t)
+{
+  machine_mode access_mode = TYPE_MODE (TREE_TYPE (t));
+  if (access_mode != BLKmode
+      && !SCALAR_INT_MODE_P (access_mode))
+    return;
+  tree base = get_base_address (t);
+  if (DECL_P (base)
+      && !TREE_ADDRESSABLE (base)
+      && FLOAT_MODE_P (DECL_MODE (base))
+      && maybe_lt (GET_MODE_PRECISION (DECL_MODE (base)),
+                  GET_MODE_BITSIZE (GET_MODE_INNER (DECL_MODE (base))))
+      /* Double check in the expensive way we really would get a pseudo.  */
+      && use_register_for_decl (base))
+    TREE_ADDRESSABLE (base) = 1;
+}
+
 /* RTL expansion is not able to compile array references with variable
    offsets for arrays stored in single register.  Discover such
    expressions and mark variables as addressable to avoid this
@@ -6172,6 +6182,12 @@ discover_nonconstant_array_refs (void)
                default:
                  break;
                }
+           if (gimple_vdef (stmt))
+             {
+               tree t = gimple_get_lhs (stmt);
+               if (t && REFERENCE_CLASS_P (t))
+                 avoid_type_punning_on_regs (t);
+             }
          }
       }
 }
@@ -6436,7 +6452,7 @@ pass_expand::execute (function *fun)
        warning (OPT_Wstack_protector,
                 "stack protector not protecting function: "
                 "all local arrays are less than %d bytes long",
-                (int) PARAM_VALUE (PARAM_SSP_BUFFER_SIZE));
+                (int) param_ssp_buffer_size);
     }
 
   /* Set up parameters and prepare for return, for the function.  */
@@ -6546,7 +6562,7 @@ pass_expand::execute (function *fun)
 
   /* If the function has too many markers, drop them while expanding.  */
   if (cfun->debug_marker_count
-      >= PARAM_VALUE (PARAM_MAX_DEBUG_MARKER_COUNT))
+      >= param_max_debug_marker_count)
     cfun->debug_nonbind_markers = false;
 
   lab_rtx_for_bb = new hash_map<basic_block, rtx_code_label *>;
@@ -6669,7 +6685,40 @@ pass_expand::execute (function *fun)
   if (crtl->tail_call_emit)
     fixup_tail_calls ();
 
-  /* BB subdivision may have created basic blocks that are are only reachable
+  unsigned HOST_WIDE_INT patch_area_size = function_entry_patch_area_size;
+  unsigned HOST_WIDE_INT patch_area_entry = function_entry_patch_area_start;
+
+  tree patchable_function_entry_attr
+    = lookup_attribute ("patchable_function_entry",
+                       DECL_ATTRIBUTES (cfun->decl));
+  if (patchable_function_entry_attr)
+    {
+      tree pp_val = TREE_VALUE (patchable_function_entry_attr);
+      tree patchable_function_entry_value1 = TREE_VALUE (pp_val);
+
+      patch_area_size = tree_to_uhwi (patchable_function_entry_value1);
+      patch_area_entry = 0;
+      if (TREE_CHAIN (pp_val) != NULL_TREE)
+       {
+         tree patchable_function_entry_value2
+           = TREE_VALUE (TREE_CHAIN (pp_val));
+         patch_area_entry = tree_to_uhwi (patchable_function_entry_value2);
+       }
+    }
+
+  if (patch_area_entry > patch_area_size)
+    {
+      if (patch_area_size > 0)
+       warning (OPT_Wattributes,
+                "patchable function entry %wu exceeds size %wu",
+                patch_area_entry, patch_area_size);
+      patch_area_entry = 0;
+    }
+
+  crtl->patch_area_size = patch_area_size;
+  crtl->patch_area_entry = patch_area_entry;
+
+  /* BB subdivision may have created basic blocks that are only reachable
      from unlikely bbs but not marked as such in the profile.  */
   if (optimize)
     propagate_unlikely_bbs_forward ();