comp.lang.ada
 help / color / mirror / Atom feed
* Interesting Array Initialization Code Gen [FSF GNAT 4.9.2]
@ 2015-05-11 18:02 visaoni
  2015-05-11 22:45 ` visaoni
  0 siblings, 1 reply; 3+ messages in thread
From: visaoni @ 2015-05-11 18:02 UTC (permalink / raw)


Recently I was messing around with some large arrays and noticed something strange. Large arrays (allocated with new) cause a stack overflow when initialized with a function call. Another pair of eyes (thanks, Lucretia) was able to spot the issue.


-----
procedure Main is
   function X( I : Integer ) return Integer is (I);

   type Arr is array (1..2**30) of Integer;
   type Arr_Ptr is access Arr;

   Q : Arr_Ptr := new Arr'(others => X(1));
begin
   null;
end Main;
------


Interestingly this creates an array on the stack, initializes it, and then copies it into a newly allocated array.


-----
procedure main is
   function main__x (i : integer) return integer;
   type main__arr is array (1 .. 16#4000_0000#) of integer;
   type main__arr_ptr is access main__arr;
   [type main__TarrB is array (1 .. 16#4000_0000# range <>) of integer]
   freeze main__TarrB []
   [subtype main__T5b is main__TarrB (1 .. 16#4000_0000#)]
   A6b : main__T5b;
   for J7b in 1 .. 16#4000_0000# loop
      A6b (J7b) := main__x (1);
   end loop;
   q : main__arr_ptr := new main__arr'(A6b);

   function main__x (i : integer) return integer is
   begin
      return (i);
   end main__x;
begin
   null;
   return;
end main;
-----


Furthermore, if you don't use a function, like so...


-----
procedure Main is
   function X( I : Integer ) return Integer is (I);

   type Arr is array (1..2**30) of Integer;
   type Arr_Ptr is access Arr;

   Q : Arr_Ptr := new Arr'(others => 1);
begin
   null;
end Main;
-----


You get something that seems more sensible, with no array on the stack and the allocated array initialized via pointer.


-----
procedure main is
   function main__x (i : integer) return integer;
   type main__arr is array (1 .. 16#4000_0000#) of integer;
   type main__arr_ptr is access main__arr;
   [type main__TarrB is array (1 .. 16#4000_0000# range <>) of integer]
   freeze main__TarrB []
   [subtype main__T5b is main__TarrB (1 .. 16#4000_0000#)]
   P6b : main__arr_ptr := new main__T5b;
   for J8b in 1 .. 16#4000_0000# loop
      main__T5b!(P6b.all) (J8b) := 1;
   end loop;
   q : main__arr_ptr := P6b;

   function main__x (i : integer) return integer is
   begin
      return (i);
   end main__x;
begin
   null;
   return;
end main;
-----


Particularly in light of the second bit, the code gen for initialization by function seems incorrect. Or is this allowed somehow, even though it effectively means potentially large arrays can't be initialized by function?

Also, GNAT GPL 2014 generates similar code but in both cases raises a storage error saying the object is too large.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Interesting Array Initialization Code Gen [FSF GNAT 4.9.2]
  2015-05-11 18:02 Interesting Array Initialization Code Gen [FSF GNAT 4.9.2] visaoni
@ 2015-05-11 22:45 ` visaoni
  2015-05-12  1:23   ` Randy Brukardt
  0 siblings, 1 reply; 3+ messages in thread
From: visaoni @ 2015-05-11 22:45 UTC (permalink / raw)


Just a bit of an update (which probably isn't much of a surprise).

Assignment produces the same kind of code in the same situations. Assignments by function create a new array on the stack, sets the values there, and then copies it into the result array. Using a literal value instead just sets the values directly in the result array.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Interesting Array Initialization Code Gen [FSF GNAT 4.9.2]
  2015-05-11 22:45 ` visaoni
@ 2015-05-12  1:23   ` Randy Brukardt
  0 siblings, 0 replies; 3+ messages in thread
From: Randy Brukardt @ 2015-05-12  1:23 UTC (permalink / raw)


<visaoni@gmail.com> wrote in message 
news:42b0aa4e-1002-4ada-af4f-61f996350965@googlegroups.com...
>Just a bit of an update (which probably isn't much of a surprise).
>
>Assignment produces the same kind of code in the same situations. 
>Assignments by
> function create a new array on the stack, sets the values there, and then 
> copies it
> into the result array. Using a literal value instead just sets the values 
> directly in the
> result array.

I'm not sure what the surprise is here (assignment). Ada essentially 
requires this in any case where the creation of the aggregate (the array 
value) could fail by an exception, as overriding part but not all of the 
target is not allowed. In the initialization of a aggregate case, the 
compiler could have noted the different situation (if the aggregate fails, 
the allocated object could never be used, so partially initializing it is 
fine), but I'm not all that surprised that not all compilers do).

In any case, you should have avoided the function and written your original 
question as:

  Q : Arr_Ptr := new Arr'(for I in Arr'range => I); -- Best, but sorry (see 
below)

except for the minor problem that this syntax (rather needed, IMHO) never 
made it into Ada (it was proposed for Ada 95, Ada 2005, and is up again for 
Ada 202x). Maybe it will make it this time.

                                           Randy.


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-05-12  1:23 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-11 18:02 Interesting Array Initialization Code Gen [FSF GNAT 4.9.2] visaoni
2015-05-11 22:45 ` visaoni
2015-05-12  1:23   ` Randy Brukardt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox