This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Patch, fortran] PR25289 Cannot handle record numbers large than huge(0_4)
- From: Jerry DeLisle <jvdelisle at verizon dot net>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>, fortran at gcc dot gnu dot org
- Date: Tue, 27 Jun 2006 21:06:31 -0700
- Subject: Re: [Patch, fortran] PR25289 Cannot handle record numbers large than huge(0_4)
- References: <A7E4CB800B73A2409E113012513E03944CDFA8@EX1V.rl.gov>
: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