OSDN Git Service

* gcc.dg/asm-b.c: Fix comment typos.
[pf3gnuchains/gcc-fork.git] / gcc / gimplify.c
index 34b22cc..d461d77 100644 (file)
@@ -1,6 +1,6 @@
 /* Tree lowering pass.  This pass converts the GENERIC functions-as-trees
    tree representation into the GIMPLE form.
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    Major work done by Sebastian Pop <s.pop@laposte.net>,
    Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
 
@@ -293,6 +293,7 @@ create_artificial_label (void)
   tree lab = build_decl (LABEL_DECL, NULL_TREE, void_type_node);
 
   DECL_ARTIFICIAL (lab) = 1;
+  DECL_IGNORED_P (lab) = 1;
   DECL_CONTEXT (lab) = current_function_decl;
   return lab;
 }
@@ -996,7 +997,12 @@ gimplify_decl_expr (tree *stmt_p)
             of the emitted code: see mx_register_decls().  */
          tree t, args, addr, ptr_type;
 
-         gimplify_type_sizes (TREE_TYPE (decl), stmt_p);
+         /* ??? We really shouldn't need to gimplify the type of the variable
+            since it already should have been done.  But leave this here
+            for now to avoid disrupting too many things at once.  */
+         if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (decl)))
+           gimplify_type_sizes (TREE_TYPE (decl), stmt_p);
+
          gimplify_one_sizepos (&DECL_SIZE (decl), stmt_p);
          gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p);
 
@@ -1427,8 +1433,15 @@ gimplify_compound_lval (tree *expr_p, tree *pre_p,
   VARRAY_GENERIC_PTR_NOGC_INIT (stack, 10, "stack");
 
   /* We can handle anything that get_inner_reference can deal with.  */
-  for (p = expr_p; handled_component_p (*p); p = &TREE_OPERAND (*p, 0))
-    VARRAY_PUSH_GENERIC_PTR_NOGC (stack, *p);
+  for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
+    {
+      /* Fold INDIRECT_REFs now to turn them into ARRAY_REFs.  */
+      if (TREE_CODE (*p) == INDIRECT_REF)
+       *p = fold_indirect_ref (*p);
+      if (!handled_component_p (*p))
+       break;
+      VARRAY_PUSH_GENERIC_PTR_NOGC (stack, *p);
+    }
 
   gcc_assert (VARRAY_ACTIVE_SIZE (stack));
 
@@ -1742,7 +1755,8 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
          return GS_OK;
        }
 
-      if (DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_START)
+      if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
+         && DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_START)
         {
          tree arglist = TREE_OPERAND (*expr_p, 1);
          
@@ -1904,7 +1918,7 @@ shortcut_cond_expr (tree expr)
   tree true_label, false_label, end_label, t;
   tree *true_label_p;
   tree *false_label_p;
-  bool emit_end, emit_false;
+  bool emit_end, emit_false, jump_over_else;
   bool then_se = then_ && TREE_SIDE_EFFECTS (then_);
   bool else_se = else_ && TREE_SIDE_EFFECTS (else_);
 
@@ -1916,6 +1930,7 @@ shortcut_cond_expr (tree expr)
        {
          TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
          then_ = shortcut_cond_expr (expr);
+         then_se = then_ && TREE_SIDE_EFFECTS (then_);
          pred = TREE_OPERAND (pred, 0);
          expr = build (COND_EXPR, void_type_node, pred, then_, NULL_TREE);
        }
@@ -1930,6 +1945,7 @@ shortcut_cond_expr (tree expr)
        {
          TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
          else_ = shortcut_cond_expr (expr);
+         else_se = else_ && TREE_SIDE_EFFECTS (else_);
          pred = TREE_OPERAND (pred, 0);
          expr = build (COND_EXPR, void_type_node, pred, NULL_TREE, else_);
        }
@@ -2006,6 +2022,16 @@ shortcut_cond_expr (tree expr)
   emit_end = (end_label == NULL_TREE);
   emit_false = (false_label == NULL_TREE);
 
+  /* We only emit the jump over the else clause if we have to--if the
+     then clause may fall through.  Otherwise we can wind up with a
+     useless jump and a useless label at the end of gimplified code,
+     which will cause us to think that this conditional as a whole
+     falls through even if it doesn't.  If we then inline a function
+     which ends with such a condition, that can cause us to issue an
+     inappropriate warning about control reaching the end of a
+     non-void function.  */
+  jump_over_else = block_may_fallthru (then_);
+
   pred = shortcut_cond_r (pred, true_label_p, false_label_p);
 
   expr = NULL;
@@ -2014,8 +2040,11 @@ shortcut_cond_expr (tree expr)
   append_to_statement_list (then_, &expr);
   if (else_se)
     {
-      t = build_and_jump (&end_label);
-      append_to_statement_list (t, &expr);
+      if (jump_over_else)
+       {
+         t = build_and_jump (&end_label);
+         append_to_statement_list (t, &expr);
+       }
       if (emit_false)
        {
          t = build1 (LABEL_EXPR, void_type_node, false_label);
@@ -2088,10 +2117,13 @@ gimple_boolify (tree expr)
     TARGET is the tree for T1 above.
 
     PRE_P points to the list where side effects that must happen before
-       *EXPR_P should be stored.  */
+       *EXPR_P should be stored.
+
+   POST_P points to the list where side effects that must happen after
+     *EXPR_P should be stored.  */
 
 static enum gimplify_status
-gimplify_cond_expr (tree *expr_p, tree *pre_p, tree target)
+gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target)
 {
   tree expr = *expr_p;
   tree tmp, tmp2, type;
@@ -2107,7 +2139,7 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree target)
     {
       if (target)
        {
-         ret = gimplify_expr (&target, pre_p, NULL,
+         ret = gimplify_expr (&target, pre_p, post_p,
                               is_gimple_min_lval, fb_lvalue);
          if (ret != GS_ERROR)
            ret = GS_OK;
@@ -2576,11 +2608,12 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
 
        categorize_ctor_elements (ctor, &num_nonzero_elements,
                                  &num_nonconstant_elements,
-                                 &num_ctor_elements);
+                                 &num_ctor_elements, &cleared);
 
        /* If a const aggregate variable is being initialized, then it
           should never be a lose to promote the variable to be static.  */
        if (num_nonconstant_elements == 0
+           && num_nonzero_elements > 1
            && TREE_READONLY (object)
            && TREE_CODE (object) == VAR_DECL)
          {
@@ -2662,7 +2695,6 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
        num_type_elements = count_type_elements (TREE_TYPE (ctor));
 
        /* If there are "lots" of zeros, then block clear the object first.  */
-       cleared = false;
        if (num_type_elements - num_nonzero_elements > CLEAR_RATIO
            && num_nonzero_elements < num_type_elements/4)
          cleared = true;
@@ -2751,20 +2783,33 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
     case VECTOR_TYPE:
       /* Go ahead and simplify constant constructors to VECTOR_CST.  */
       if (TREE_CONSTANT (ctor))
-       TREE_OPERAND (*expr_p, 1) = build_vector (type, elt_list);
-      else
        {
-         /* Vector types use CONSTRUCTOR all the way through gimple
-            compilation as a general initializer.  */
-         for (; elt_list; elt_list = TREE_CHAIN (elt_list))
+         tree tem;
+
+         /* Even when ctor is constant, it might contain non-*_CST
+            elements (e.g. { 1.0/0.0 - 1.0/0.0, 0.0 }) and those don't
+            belong into VECTOR_CST nodes.  */
+         for (tem = elt_list; tem; tem = TREE_CHAIN (tem))
+           if (! CONSTANT_CLASS_P (TREE_VALUE (tem)))
+             break;
+
+         if (! tem)
            {
-             enum gimplify_status tret;
-             tret = gimplify_expr (&TREE_VALUE (elt_list), pre_p, post_p,
-                                   is_gimple_val, fb_rvalue);
-             if (tret == GS_ERROR)
-               ret = GS_ERROR;
+             TREE_OPERAND (*expr_p, 1) = build_vector (type, elt_list);
+             break;
            }
        }
+
+      /* Vector types use CONSTRUCTOR all the way through gimple
+        compilation as a general initializer.  */
+      for (; elt_list; elt_list = TREE_CHAIN (elt_list))
+       {
+         enum gimplify_status tret;
+         tret = gimplify_expr (&TREE_VALUE (elt_list), pre_p, post_p,
+                               is_gimple_val, fb_rvalue);
+         if (tret == GS_ERROR)
+           ret = GS_ERROR;
+       }
       break;
 
     default:
@@ -2796,6 +2841,28 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
   while (ret != GS_UNHANDLED)
     switch (TREE_CODE (*from_p))
       {
+      case INDIRECT_REF:
+       {
+         /* If we have code like 
+
+               *(const A*)(A*)&x
+
+            where the type of "x" is a (possibly cv-qualified variant
+            of "A"), treat the entire expression as identical to "x".
+            This kind of code arises in C++ when an object is bound
+            to a const reference, and if "x" is a TARGET_EXPR we want
+            to take advantage of the optimization below.  */
+         tree t = fold_indirect_ref (*from_p);
+         if (t != *from_p)
+           {
+             *from_p = t;
+             ret = GS_OK;
+           }
+         else
+           ret = GS_UNHANDLED;
+         break;
+       }
+
       case TARGET_EXPR:
        {
          /* If we are initializing something from a TARGET_EXPR, strip the
@@ -2840,7 +2907,7 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
        if (!is_gimple_reg_type (TREE_TYPE (*from_p)))
          {
            *expr_p = *from_p;
-           return gimplify_cond_expr (expr_p, pre_p, *to_p);
+           return gimplify_cond_expr (expr_p, pre_p, post_p, *to_p);
          }
        else
          ret = GS_UNHANDLED;
@@ -3226,10 +3293,6 @@ gimplify_asm_expr (tree *expr_p, tree *pre_p, tree *post_p)
   bool allows_mem, allows_reg, is_inout;
   enum gimplify_status ret, tret;
 
-  ASM_STRING (expr)
-    = resolve_asm_operand_names (ASM_STRING (expr), ASM_OUTPUTS (expr),
-                                ASM_INPUTS (expr));
-
   ret = GS_ALL_DONE;
   for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = TREE_CHAIN (link))
     {
@@ -3482,7 +3545,7 @@ gimplify_target_expr (tree *expr_p, tree *pre_p, tree *post_p)
          ret = GS_OK;
           if (TREE_CODE (init) == BIND_EXPR)
            gimplify_bind_expr (&init, temp, pre_p);
-          if (init != temp)
+         if (init != temp)
            {
              init = build (MODIFY_EXPR, void_type_node, temp, init);
              ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt,
@@ -3658,7 +3721,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
          break;
 
        case COND_EXPR:
-         ret = gimplify_cond_expr (expr_p, pre_p, NULL_TREE);
+         ret = gimplify_cond_expr (expr_p, pre_p, post_p, NULL_TREE);
          break;
 
        case CALL_EXPR:
@@ -3733,9 +3796,13 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
          recalculate_side_effects (*expr_p);
          break;
 
+       case INDIRECT_REF:
+         *expr_p = fold_indirect_ref (*expr_p);
+         if (*expr_p != save_expr)
+           break;
+         /* else fall through.  */
        case ALIGN_INDIRECT_REF:
        case MISALIGNED_INDIRECT_REF:
-       case INDIRECT_REF:
          ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
                               is_gimple_reg, fb_rvalue);
          recalculate_side_effects (*expr_p);
@@ -4180,7 +4247,17 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
 void
 gimplify_type_sizes (tree type, tree *list_p)
 {
-  tree field;
+  tree field, t;
+
+  /* Note that we do not check for TYPE_SIZES_GIMPLIFIED already set because
+     that's not supposed to happen on types where gimplification does anything.
+     We should assert that it isn't set, but we can indeed be called multiple
+     times on pointers.  Unfortunately, this includes fat pointers which we
+     can't easily test for.  We could pass TYPE down to gimplify_one_sizepos
+     and test there, but it doesn't seem worth it.  */
+
+  /* We first do the main variant, then copy into any other variants. */
+  type = TYPE_MAIN_VARIANT (type);
 
   switch (TREE_CODE (type))
     {
@@ -4194,11 +4271,22 @@ gimplify_type_sizes (tree type, tree *list_p)
     case REAL_TYPE:
       gimplify_one_sizepos (&TYPE_MIN_VALUE (type), list_p);
       gimplify_one_sizepos (&TYPE_MAX_VALUE (type), list_p);
+
+      for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+       {
+         TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type);
+         TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type);
+         TYPE_SIZES_GIMPLIFIED (t) = 1;
+       }
       break;
 
     case ARRAY_TYPE:
-      /* These anonymous types don't have declarations, so handle them here.  */
-      gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
+      /* These types may not have declarations, so handle them here.  */
+      if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (type)))
+       gimplify_type_sizes (TREE_TYPE (type), list_p);
+
+      if (!TYPE_SIZES_GIMPLIFIED (TYPE_DOMAIN (type)))
+         gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
       break;
 
     case RECORD_TYPE:
@@ -4215,9 +4303,19 @@ gimplify_type_sizes (tree type, tree *list_p)
 
   gimplify_one_sizepos (&TYPE_SIZE (type), list_p);
   gimplify_one_sizepos (&TYPE_SIZE_UNIT (type), list_p);
+
+  for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+    {
+      TYPE_SIZE (t) = TYPE_SIZE (type);
+      TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type);
+      TYPE_SIZES_GIMPLIFIED (t) = 1;
+    }
+
+  TYPE_SIZES_GIMPLIFIED (type) = 1;
 }
 
-/* Subroutine of the above to gimplify one size or position, *EXPR_P.
+/* A subroutine of gimplify_type_sizes to make sure that *EXPR_P,
+   a size or position, has had all of its SAVE_EXPRs evaluated.
    We add any required statements to STMT_P.  */
 
 void
@@ -4233,6 +4331,7 @@ gimplify_one_sizepos (tree *expr_p, tree *stmt_p)
       || CONTAINS_PLACEHOLDER_P (*expr_p))
     return;
 
+  *expr_p = unshare_expr (*expr_p);
   gimplify_expr (expr_p, stmt_p, NULL, is_gimple_val, fb_rvalue);
 }
 \f