Avoid explicit use of machine modes (1/n) varasm.c

Zack Weinberg zack@codesourcery.com
Mon Sep 29 21:31:00 GMT 2003


This is part 1 of a series of patches to avoid explicit use of
machine mode constants as much as possible in the target-independent
parts of the compiler: that is, everything outside gcc/config except
reg-stack.c (which is effectively part of the i386 backend).  Uses of
VOIDmode and BLKmode will be left alone.  In all cases avoiding XXmode
seems to be the clean thing to do, not just the abstract right thing.

This patch is for varasm.c.  assemble_real formerly had a mess of
switch statements to deduce which REAL_VALUE_TO_TARGET_* macro to use
for a given mode.  By using real_to_target instead, all of this can be
avoided.  (The code still contains the embedded assumption that all
supported real formats have <=128 bits.)

Bootstrapped i686-linux.  I could not find any target that actually
uses TQFmode.  Therefore a corner case of this code (where the last
element of real_to_target's result array doesn't contain as many
significant bits as the rest of them) has gone untested, but the new
code is simple and obvious enough that I feel confident it works
anyway.

Future direction for this code: avoid going through assemble_integer
(and therefore needing to create throwaway RTL).

zw

        * varasm.c (assemble_real): Use real_to_target directly,
        calculate the number of significant elements of the result
        array and write them out in a loop, instead of using a giant
        switch statement to pick the correct REAL_VALUE_TO_TARGET_*
        macro.

===================================================================
Index: varasm.c
--- varasm.c	23 Sep 2003 19:47:00 -0000	1.386
+++ varasm.c	29 Sep 2003 21:16:22 -0000
@@ -1889,77 +1889,34 @@ void
 assemble_real (REAL_VALUE_TYPE d, enum machine_mode mode, unsigned int align)
 {
   long data[4];
-  long l;
-  unsigned int nalign = min_align (align, 32);
+  int i;
+  int bitsize, nelts, nunits, units_per;
 
-  switch (BITS_PER_UNIT)
-    {
-    case 8:
-      switch (mode)
-	{
-	case SFmode:
-	  REAL_VALUE_TO_TARGET_SINGLE (d, l);
-	  assemble_integer (GEN_INT (l), 4, align, 1);
-	  break;
-	case DFmode:
-	  REAL_VALUE_TO_TARGET_DOUBLE (d, data);
-	  assemble_integer (GEN_INT (data[0]), 4, align, 1);
-	  assemble_integer (GEN_INT (data[1]), 4, nalign, 1);
-	  break;
-	case XFmode:
-	  REAL_VALUE_TO_TARGET_LONG_DOUBLE (d, data);
-	  assemble_integer (GEN_INT (data[0]), 4, align, 1);
-	  assemble_integer (GEN_INT (data[1]), 4, nalign, 1);
-	  assemble_integer (GEN_INT (data[2]), 4, nalign, 1);
-	  break;
-	case TFmode:
-	  REAL_VALUE_TO_TARGET_LONG_DOUBLE (d, data);
-	  assemble_integer (GEN_INT (data[0]), 4, align, 1);
-	  assemble_integer (GEN_INT (data[1]), 4, nalign, 1);
-	  assemble_integer (GEN_INT (data[2]), 4, nalign, 1);
-	  assemble_integer (GEN_INT (data[3]), 4, nalign, 1);
-	  break;
-	default:
-	  abort ();
-	}
-      break;
+  /* This is hairy.  We have a quantity of known bitsize.  real_to_target
+     will put it into an array of *host* longs, 32 bits per element
+     (even if long is more than 32 bits).  We need to determine the
+     number of array elements that are occupied (nelts) and the number
+     of *target* min-addressable units that will be occupied in the
+     object file (nunits).  We can assume that BITS_PER_UNIT divides
+     the mode's bitsize evenly, but we can not assume that 32 does.  */
+  bitsize = GET_MODE_BITSIZE (mode);
+  nunits = bitsize / BITS_PER_UNIT;
+  nelts = CEIL (bitsize, 32);
+  units_per = 32 / BITS_PER_UNIT;
+
+  real_to_target (data, &d, mode);
 
-    case 16:
-      switch (mode)
-	{
-	case HFmode:
-	  REAL_VALUE_TO_TARGET_SINGLE (d, l);
-	  assemble_integer (GEN_INT (l), 2, align, 1);
-	  break;
-	case TQFmode:
-	  REAL_VALUE_TO_TARGET_DOUBLE (d, data);
-	  assemble_integer (GEN_INT (data[0]), 2, align, 1);
-	  assemble_integer (GEN_INT (data[1]), 1, nalign, 1);
-	  break;
-	default:
-	  abort ();
-	}
-      break;
+  /* Put out the first word with the specified alignment.  */
+  assemble_integer (GEN_INT (data[0]), MIN (nunits, units_per), align, 1);
+  nunits -= units_per;
 
-    case 32:
-      switch (mode)
-	{
-	case QFmode:
-	  REAL_VALUE_TO_TARGET_SINGLE (d, l);
-	  assemble_integer (GEN_INT (l), 1, align, 1);
-	  break;
-	case HFmode:
-	  REAL_VALUE_TO_TARGET_DOUBLE (d, data);
-	  assemble_integer (GEN_INT (data[0]), 1, align, 1);
-	  assemble_integer (GEN_INT (data[1]), 1, nalign, 1);
-	  break;
-	default:
-	  abort ();
-	}
-      break;
+  /* Subsequent words need only 32-bit alignment.  */
+  align = min_align (align, 32);
 
-    default:
-      abort ();
+  for (i = 1; i < nelts; i++)
+    {
+      assemble_integer (GEN_INT (data[i]), MIN (nunits, units_per), align, 1);
+      nunits -= units_per;
     }
 }
 



More information about the Gcc-patches mailing list