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]

Re: [Patch, fortran] PR25289 Cannot handle record numbers large than huge(0_4)


:REVIEWMAIL:

The attached patch is revised from previous attempts. This patch borrows code from trans-types.c to determine whether or not a target supports integer 8 or not. A new function is added to make this determination.

On the library side I am sticking with gfc_offset which I think is being handled correctly. If it is preferred that I do further work on the runtime library side, let me know.

OK for 4.2 only? Comments welcome. As I have stated before, these are some first explorations into the front-end for me. There is always much to learn.

Regression tested. Attached previous test case for convenience.

Regards,

Jerry

2006-06-27 Jerry DeLisle <jvdelisle@gcc.gnu.org>

	PR fortran/25289
	trans-io.c: Include target.h.
	(iofield_type): Add IOPARM_type_intoff.
	(gfc_get_large_int): New function to determine if large integer 8
	is available, returns size_t 8 if so, otherwise size_t 4.
	(gfc_build_st_parameter): Use IOPARM_type_intoff.
	(gfc_build_io_library_fndecls): Use new function.
	ioparm.def: Change IOPARM dt->rec to intoff.
	
	PR libgfortran/25289
	io.h (st_parameter_dt): Change rec type to gfc_offset.


Index: gcc/fortran/trans-io.c
===================================================================
--- gcc/fortran/trans-io.c	(revision 114994)
+++ gcc/fortran/trans-io.c	(working copy)
@@ -27,6 +27,7 @@
 #include "tree-gimple.h"
 #include "ggc.h"
 #include "toplev.h"
+#include "target.h"
 #include "real.h"
 #include "gfortran.h"
 #include "trans.h"
@@ -52,6 +53,7 @@
 enum iofield_type
 {
   IOPARM_type_int4,
+  IOPARM_type_intoff,
   IOPARM_type_pint4,
   IOPARM_type_pchar,
   IOPARM_type_parray,
@@ -147,6 +149,44 @@
 static GTY(()) tree dt_parm;
 static stmtblock_t *dt_post_end_block;
 
+#define MAX_INT_KINDS 5
+
+static size_t
+gfc_get_large_int_kind (void)
+{
+  enum machine_mode mode;
+  int i_index;
+  bool saw_i8 = false;
+
+  for (i_index = 0, mode = MIN_MODE_INT; mode <= MAX_MODE_INT; mode++)
+    {
+      int kind, bitsize;
+
+      if (!targetm.scalar_mode_supported_p (mode))
+	continue;
+
+      /* The middle end doesn't support constants larger than 2*HWI.
+	 Perhaps the target hook shouldn't have accepted these either,
+	 but just to be safe...  */
+      bitsize = GET_MODE_BITSIZE (mode);
+      if (bitsize > 2*HOST_BITS_PER_WIDE_INT)
+	continue;
+
+      gcc_assert (i_index != MAX_INT_KINDS);
+
+      /* Let the kind equal the bit size divided by 8.  This insulates the
+	 programmer from the underlying byte size.  */
+      kind = bitsize / 8;
+
+      if (kind == 8)
+	saw_i8 = true;
+    }
+  if (saw_i8)
+    return 8;
+  else
+    return 4;
+}
+
 static void
 gfc_build_st_parameter (enum ioparam_type ptype, tree *types)
 {
@@ -168,6 +208,7 @@
       switch (p->type)
 	{
 	case IOPARM_type_int4:
+	case IOPARM_type_intoff:
 	case IOPARM_type_pint4:
 	case IOPARM_type_parray:
 	case IOPARM_type_pchar:
@@ -214,12 +255,18 @@
 gfc_build_io_library_fndecls (void)
 {
   tree types[IOPARM_type_num], pad_idx, gfc_int4_type_node;
+  tree gfc_intoff_type_node;
   tree parm_type, dt_parm_type;
   tree gfc_c_int_type_node;
   HOST_WIDE_INT pad_size;
   enum ioparam_type ptype;
+  size_t offset_kind;
 
+  offset_kind = gfc_get_large_int_kind ();
+
   types[IOPARM_type_int4] = gfc_int4_type_node = gfc_get_int_type (4);
+  types[IOPARM_type_intoff] = gfc_intoff_type_node
+			    = gfc_get_int_type (offset_kind);
   types[IOPARM_type_pint4] = build_pointer_type (gfc_int4_type_node);
   types[IOPARM_type_parray] = pchar_type_node;
   types[IOPARM_type_pchar] = pchar_type_node;
Index: gcc/fortran/ioparm.def
===================================================================
--- gcc/fortran/ioparm.def	(revision 114994)
+++ gcc/fortran/ioparm.def	(working copy)
@@ -58,7 +58,7 @@
 #define IOPARM_dt_namelist_read_mode	(1 << 8)
 #endif
 IOPARM (dt,      common,	0,	 common)
-IOPARM (dt,      rec,		1 << 9,  int4)
+IOPARM (dt,      rec,		1 << 9,  intoff)
 IOPARM (dt,      size,		1 << 10, pint4)
 IOPARM (dt,      iolength,	1 << 11, pint4)
 IOPARM (dt,      internal_unit_desc, 0,  parray)
Index: libgfortran/io/io.h
===================================================================
--- libgfortran/io/io.h	(revision 114994)
+++ libgfortran/io/io.h	(working copy)
@@ -355,7 +355,7 @@
 typedef struct st_parameter_dt
 {
   st_parameter_common common;
-  GFC_INTEGER_4 rec;
+  gfc_offset rec;
   GFC_INTEGER_4 *size, *iolength;
   gfc_array_char *internal_unit_desc;
   CHARACTER1 (format);
!{ dg-do run }
!{ dg-options "-std=gnu" }
! PR25289 Cannot handle record numbers larger than huge(0_4).
! This test checks that very large record numbers can be used.
! Derived from example in PR.
! Submitted by Jerry DeLisle  <jvdelisle@gcc.gnu.org>
      integer*1 abyte
      integer*8 n
      n = huge(0_4)
      n = n * 256
      abyte = 105
      open(10,file="foo",recl=2,form='unformatted',access='direct')
      write(10,rec=n) abyte
      abyte = 0
      read(10,rec=n) abyte
      if (abyte.ne.105) call abort()
      write(10,rec=1) abyte
      abyte = 0
      read(10,rec=1) abyte
      if (abyte.ne.105) call abort()
      n=n/2
      write(10,rec=n) abyte
      abyte = 0
      read(10,rec=n) abyte
      if (abyte.ne.105) call abort()
      close(10, status="delete")
      end
      

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