re PR target/13926 (GCC generates jumps that are too large to fit in word displacemen...
[gcc.git] / gcc / gimple-low.c
index aac3341b8ccee7d4220be47d3d7b1dbb46e46150..c29f591fe54f266ffe6cb773d6a1f6fac458d711 100644 (file)
@@ -67,6 +67,7 @@ lower_function_body (void)
   tree *body_p = &DECL_SAVED_TREE (current_function_decl);
   tree bind = *body_p;
   tree_stmt_iterator i;
+  tree t, x;
 
   if (TREE_CODE (bind) != BIND_EXPR)
     abort ();
@@ -83,25 +84,37 @@ lower_function_body (void)
   tsi_link_after (&i, bind, TSI_NEW_STMT);
   lower_bind_expr (&i, &data);
 
-  /* If we lowered any return statements, emit the representative at the
-     end of the function.  */
-  if (data.return_statements)
+  i = tsi_last (*body_p);
+
+  /* If the function falls off the end, we need a null return statement.
+     If we've already got one in the return_statements list, we don't
+     need to do anything special.  Otherwise build one by hand.  */
+  if (block_may_fallthru (*body_p)
+      && (data.return_statements == NULL
+          || TREE_OPERAND (TREE_VALUE (data.return_statements), 0) != NULL))
     {
-      tree t, x;
-      i = tsi_last (*body_p);
+      x = build (RETURN_EXPR, void_type_node, NULL);
+      SET_EXPR_LOCATION (x, cfun->function_end_locus);
+      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
+    }
 
-      for (t = data.return_statements; t ; t = TREE_CHAIN (t))
-       {
-         x = build (LABEL_EXPR, void_type_node, TREE_PURPOSE (t));
-          tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
-
-         /* Remove the line number from the representative return statement.
-            It now fills in for many such returns.  Failure to remove this
-            will result in incorrect results for coverage analysis.  */
-         x = TREE_VALUE (t);
-         SET_EXPR_LOCUS (x, NULL);
-          tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
-        }
+  /* If we lowered any return statements, emit the representative
+     at the end of the function.  */
+  for (t = data.return_statements ; t ; t = TREE_CHAIN (t))
+    {
+      x = build (LABEL_EXPR, void_type_node, TREE_PURPOSE (t));
+      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
+
+      /* Remove the line number from the representative return statement.
+        It now fills in for many such returns.  Failure to remove this
+        will result in incorrect results for coverage analysis.  */
+      x = TREE_VALUE (t);
+#ifdef USE_MAPPED_LOCATION
+      SET_EXPR_LOCATION (x, UNKNOWN_LOCATION);
+#else
+      SET_EXPR_LOCUS (x, NULL);
+#endif
+      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
     }
 
   if (data.block != DECL_INITIAL (current_function_decl))
@@ -110,10 +123,6 @@ lower_function_body (void)
     = blocks_nreverse (BLOCK_SUBBLOCKS (data.block));
 
   clear_block_marks (data.block);
-
-  /* Avoid producing notes for blocks.  */
-  cfun->dont_emit_block_notes = 1;
-  reset_block_changes ();
 }
 
 struct tree_opt_pass pass_lower_cf = 
@@ -467,8 +476,6 @@ expand_var_p (tree var)
   if (TREE_CODE (var) != VAR_DECL)
     return true;
 
-  ann = var_ann (var);
-
   /* Remove all unused, unaliased temporaries.  Also remove unused, unaliased
      local variables during highly optimizing compilations.  */
   ann = var_ann (var);