[PATCH] Avoid creating >= 8GB EXPR_CONSTANT initializers for ilp32 targets (PR fortran/84065)

Jakub Jelinek jakub@redhat.com
Fri Jan 26 23:22:00 GMT 2018


Hi!

resolve_charlen is going to error on ilp32 target charlens above what
can fit into 32-bit signed int, but add_init_expr_to_sym is done before
resolve_charlen, allocating huge amounts of memory in those cases
when we'll error later is just waste of compile time if running on 64-bit
host with enough memory, or will unnecessarily ICE due to out of memory
otherwise.

Another option would be to emit the error resolve_charlen is going to
emit and arrange for it not to be emitted afterwards, this just seemed
to be easier.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

It would be nice if the FE had some way to express very large repetitive
EXPR_CONSTANT more efficiently, say by not allocating the memory for
the rest which is filled only by ' ', or by allowing to say this and this
is repeated after the initial portion this many times.

2018-01-26  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/84065
	* decl.c (add_init_expr_to_sym): Ignore initializers for too large
	lengths.

--- gcc/fortran/decl.c.jj	2018-01-23 21:35:04.000000000 +0100
+++ gcc/fortran/decl.c	2018-01-26 18:24:22.064763299 +0100
@@ -1757,22 +1757,32 @@ add_init_expr_to_sym (const char *name,
 	      if (!gfc_specification_expr (sym->ts.u.cl->length))
 		return false;
 
-	      HOST_WIDE_INT len = gfc_mpz_get_hwi (sym->ts.u.cl->length->value.integer);
-
-	      if (init->expr_type == EXPR_CONSTANT)
-		gfc_set_constant_character_len (len, init, -1);
-	      else if (init->expr_type == EXPR_ARRAY)
+	      int k = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind,
+					 false);
+	      /* resolve_charlen will complain later on if the length
+		 is too large.  Just skeep the initialization in that case.  */
+	      if (mpz_cmp (sym->ts.u.cl->length->value.integer,
+			   gfc_integer_kinds[k].huge) <= 0)
 		{
-		  gfc_constructor *c;
+		  HOST_WIDE_INT len
+		    = gfc_mpz_get_hwi (sym->ts.u.cl->length->value.integer);
+
+		  if (init->expr_type == EXPR_CONSTANT)
+		    gfc_set_constant_character_len (len, init, -1);
+		  else if (init->expr_type == EXPR_ARRAY)
+		    {
+		      gfc_constructor *c;
 
-		  /* Build a new charlen to prevent simplification from
-		     deleting the length before it is resolved.  */
-		  init->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
-		  init->ts.u.cl->length = gfc_copy_expr (sym->ts.u.cl->length);
+		      /* Build a new charlen to prevent simplification from
+			 deleting the length before it is resolved.  */
+		      init->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
+		      init->ts.u.cl->length
+			= gfc_copy_expr (sym->ts.u.cl->length);
 
-		  for (c = gfc_constructor_first (init->value.constructor);
-		       c; c = gfc_constructor_next (c))
-		    gfc_set_constant_character_len (len, c->expr, -1);
+		      for (c = gfc_constructor_first (init->value.constructor);
+			   c; c = gfc_constructor_next (c))
+			gfc_set_constant_character_len (len, c->expr, -1);
+		    }
 		}
 	    }
 	}

	Jakub



More information about the Gcc-patches mailing list