This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix PR ada/29025


It's a regression present on the mainline and 4.1 branch.

When passing a misaligned actual by reference for an out/in-out argument
in a procedure call, we need to make a properly aligned temporary copy,
pass its address, and copy back after the call.

We were relying on SAVE_EXPR semantics for this, which was not working
because we were introducing an extra intermediate temporary for &SAVE_EXPR
in our gimplifier hook, not visible to the copy back code.

The fix applied here consists in not making the extra temporary in this
case. We rely on the common gimplifier code instead, to handle both the
temporary copy creation and its propagation in place of the SAVE_EXPR
instance in the copy back code.

The testcase below is expected to compile and run silently. The bogus
behavior was observed as part of code expanded for the 'Output/'Input
calls.

with Ada.Streams.Stream_IO;
procedure P is

   use Ada.Streams;  use Stream_IO;

   File : Stream_IO.File_Type;

   type Bitmap is array (Natural range <>) of Boolean;
   for Bitmap'Component_Size use 1;

   type Message   is record
      B : Bitmap (0 .. 14);
   end record;
   for Message use record
      B  at 0 range 2 .. 16;
   end record;

   TX, RX : Message;
begin
   TX.B  := (others => False);
   Stream_IO.Create (File => File, Mode => Out_File, Name => "data");
   Message'Output (Stream (File), TX);
   Stream_IO.Close (File);
   --
   Stream_IO.Open (File => File, Mode => In_File, Name => "data");
   RX := Message'Input (Stream (File));
   Stream_IO.Close (File);

   if RX /= TX then
      raise Program_Error;
   end if;
end;

Bootstrapped/regtested on i586-suse-linux, applied to the mainline and 4.1 
branch.


2006-09-13  Olivier Hainque  <hainque@adacore.com>

	PR ada/29025
	* trans.c (gnat_gimplify_expr) <ADDR_EXPR>: When taking the address
	of a SAVE_EXPR, just make the operand addressable/not-readonly and
	let the common gimplifier code make and propagate a temporary copy.
	(call_to_gnu): Clarify the use of SAVE_EXPR for not addressable
	out/in-out actuals and defer setting the addressable/readonly bits
	to the gimplifier.


-- 
Eric Botcazou
Index: trans.c
===================================================================
RCS file: /gnat.dev/cvs/Dev/gnat/trans.c,v
retrieving revision 1.68.2.142
retrieving revision 1.68.2.143
diff -u -p -r1.68.2.142 -r1.68.2.143
--- trans.c	10 Mar 2006 23:17:50 -0000	1.68.2.142
+++ trans.c	23 Mar 2006 18:07:18 -0000	1.68.2.143
@@ -1780,18 +1780,12 @@ call_to_gnu (Node_Id gnat_node, tree *gn
 		       && (TYPE_JUSTIFIED_MODULAR_P (gnu_name_type)))
 		gnu_name = convert (gnu_name_type, gnu_name);
 
+	      /* Make a SAVE_EXPR to both properly account for potential side
+		 effects and handle the creation of a temporary copy.  Special
+		 code in gnat_gimplify_expr ensures that the same temporary is
+		 used as the actual and copied back after the call.  */
 	      gnu_actual = save_expr (gnu_name);
 
-	      /* Since we're going to take the address of the SAVE_EXPR, we
-		 don't want it to be marked as unchanging. So set
-		 TREE_ADDRESSABLE.  */
-	      gnu_temp = skip_simple_arithmetic (gnu_actual);
-	      if (TREE_CODE (gnu_temp) == SAVE_EXPR)
-		{
-		  TREE_ADDRESSABLE (gnu_temp) = 1;
-		  TREE_READONLY (gnu_temp) = 0;
-		}
-
 	      /* Set up to move the copy back to the original.  */
 	      gnu_temp = build_binary_op (MODIFY_EXPR, NULL_TREE,
 					  gnu_copy, gnu_actual);
@@ -4711,6 +4705,19 @@ gnat_gimplify_expr (tree *expr_p, tree *
 	  return GS_ALL_DONE;
 	}
 
+      /* If we are taking the address of a SAVE_EXPR, we are typically
+	 processing a misaligned argument to be passed by reference in a
+	 procedure call.  We just mark the operand as addressable + not
+	 readonly here and let the common gimplifier code perform the
+	 temporary creation, initialization, and "instantiation" in place of
+	 the SAVE_EXPR in further operands, in particular in the copy back
+	 code inserted after the call.  */
+      else if (TREE_CODE (op) == SAVE_EXPR)
+	{
+	  TREE_ADDRESSABLE (op) = 1;
+	  TREE_READONLY (op) = 0;
+	}
+
       /* Otherwise, if we are taking the address of something that is neither
 	 reference, declaration, or constant, make a variable for the operand
 	 here and then take its address.  If we don't do it this way, we may

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]