OSDN Git Service

2008-11-09 Thomas Schwinge <tschwinge@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / trans-io.c
index 2f35002..af46ea2 100644 (file)
@@ -1,6 +1,6 @@
 /* IO Code translation/library interface
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software
-   Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
    Contributed by Paul Brook
 
 This file is part of GCC.
@@ -24,7 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tree.h"
-#include "tree-gimple.h"
+#include "gimple.h"
 #include "ggc.h"
 #include "toplev.h"
 #include "real.h"
@@ -121,6 +121,7 @@ enum iocall
   IOCALL_X_INTEGER,
   IOCALL_X_LOGICAL,
   IOCALL_X_CHARACTER,
+  IOCALL_X_CHARACTER_WIDE,
   IOCALL_X_REAL,
   IOCALL_X_COMPLEX,
   IOCALL_X_ARRAY,
@@ -290,7 +291,7 @@ gfc_build_io_library_fndecls (void)
                            = build_pointer_type (gfc_intio_type_node);
   types[IOPARM_type_parray] = pchar_type_node;
   types[IOPARM_type_pchar] = pchar_type_node;
-  pad_size = 16 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (pchar_type_node));
+  pad_size = 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (pchar_type_node));
   pad_size += 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (integer_type_node));
   pad_idx = build_index_type (build_int_cst (NULL_TREE, pad_size));
   types[IOPARM_type_pad] = build_array_type (char_type_node, pad_idx);
@@ -327,6 +328,13 @@ gfc_build_io_library_fndecls (void)
                                     void_type_node, 3, dt_parm_type,
                                     pvoid_type_node, gfc_int4_type_node);
 
+  iocall[IOCALL_X_CHARACTER_WIDE] =
+    gfc_build_library_function_decl (get_identifier
+                                    (PREFIX("transfer_character_wide")),
+                                    void_type_node, 4, dt_parm_type,
+                                    pvoid_type_node, gfc_charlen_type_node,
+                                    gfc_int4_type_node);
+
   iocall[IOCALL_X_REAL] =
     gfc_build_library_function_decl (get_identifier (PREFIX("transfer_real")),
                                     void_type_node, 3, dt_parm_type,
@@ -442,7 +450,7 @@ set_parameter_const (stmtblock_t *block, tree var, enum iofield type,
                       var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
   tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field), var, p->field,
                     NULL_TREE);
-  gfc_add_modify_expr (block, tmp, build_int_cst (TREE_TYPE (p->field), val));
+  gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (p->field), val));
   return p->mask;
 }
 
@@ -497,7 +505,7 @@ set_parameter_value (stmtblock_t *block, tree var, enum iofield type,
                       var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
 
   tmp = fold_build3 (COMPONENT_REF, dest_type, var, p->field, NULL_TREE);
-  gfc_add_modify_expr (block, tmp, se.expr);
+  gfc_add_modify (block, tmp, se.expr);
   return p->mask;
 }
 
@@ -527,7 +535,7 @@ set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock,
       /* If this is for the iostat variable initialize the
         user variable to LIBERROR_OK which is zero.  */
       if (type == IOPARM_common_iostat)
-       gfc_add_modify_expr (block, se.expr,
+       gfc_add_modify (block, se.expr,
                             build_int_cst (TREE_TYPE (se.expr), LIBERROR_OK));
     }
   else
@@ -541,13 +549,13 @@ set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock,
       /* If this is for the iostat variable, initialize the
         user variable to LIBERROR_OK which is zero.  */
       if (type == IOPARM_common_iostat)
-       gfc_add_modify_expr (block, tmpvar,
+       gfc_add_modify (block, tmpvar,
                             build_int_cst (TREE_TYPE (tmpvar), LIBERROR_OK));
 
       addr = build_fold_addr_expr (tmpvar);
        /* After the I/O operation, we set the variable from the temporary.  */
       tmp = convert (TREE_TYPE (se.expr), tmpvar);
-      gfc_add_modify_expr (postblock, se.expr, tmp);
+      gfc_add_modify (postblock, se.expr, tmp);
      }
 
   if (p->param_type == IOPARM_ptype_common)
@@ -555,7 +563,7 @@ set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock,
                       var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
   tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
                     var, p->field, NULL_TREE);
-  gfc_add_modify_expr (block, tmp, addr);
+  gfc_add_modify (block, tmp, addr);
   return p->mask;
 }
 
@@ -660,13 +668,13 @@ set_string (stmtblock_t * block, stmtblock_t * postblock, tree var,
 
       asprintf(&msg, "Label assigned to variable '%s' (%%ld) is not a format "
               "label", e->symtree->name);
-      gfc_trans_runtime_check (cond, &se.pre, &e->where, msg,
+      gfc_trans_runtime_check (true, false, cond, &se.pre, &e->where, msg,
                               fold_convert (long_integer_type_node, tmp));
       gfc_free (msg);
 
-      gfc_add_modify_expr (&se.pre, io,
+      gfc_add_modify (&se.pre, io,
                 fold_convert (TREE_TYPE (io), GFC_DECL_ASSIGN_ADDR (se.expr)));
-      gfc_add_modify_expr (&se.pre, len, GFC_DECL_STRING_LEN (se.expr));
+      gfc_add_modify (&se.pre, len, GFC_DECL_STRING_LEN (se.expr));
     }
   else
     {
@@ -680,8 +688,8 @@ set_string (stmtblock_t * block, stmtblock_t * postblock, tree var,
        gcc_unreachable ();
 
       gfc_conv_string_parameter (&se);
-      gfc_add_modify_expr (&se.pre, io, fold_convert (TREE_TYPE (io), se.expr));
-      gfc_add_modify_expr (&se.pre, len, se.string_length);
+      gfc_add_modify (&se.pre, io, fold_convert (TREE_TYPE (io), se.expr));
+      gfc_add_modify (&se.pre, len, se.string_length);
     }
 
   gfc_add_block_to_block (block, &se.pre);
@@ -756,10 +764,10 @@ set_internal_unit (stmtblock_t * block, stmtblock_t * post_block,
 
   /* The cast is needed for character substrings and the descriptor
      data.  */
-  gfc_add_modify_expr (&se.pre, io, fold_convert (TREE_TYPE (io), tmp));
-  gfc_add_modify_expr (&se.pre, len,
+  gfc_add_modify (&se.pre, io, fold_convert (TREE_TYPE (io), tmp));
+  gfc_add_modify (&se.pre, len,
                       fold_convert (TREE_TYPE (len), se.string_length));
-  gfc_add_modify_expr (&se.pre, desc, se.expr);
+  gfc_add_modify (&se.pre, desc, se.expr);
 
   gfc_add_block_to_block (block, &se.pre);
   gfc_add_block_to_block (post_block, &se.post);
@@ -857,7 +865,7 @@ set_error_locus (stmtblock_t * block, tree var, locus * where)
   str = gfc_build_cstring_const (f->filename);
 
   str = gfc_build_addr_expr (pchar_type_node, str);
-  gfc_add_modify_expr (block, locus_file, str);
+  gfc_add_modify (block, locus_file, str);
 
   line = LOCATION_LINE (where->lb->location);
   set_parameter_const (block, var, IOPARM_common_line, line);
@@ -1892,7 +1900,7 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code);
    recursive.  */
 
 static tree
-transfer_array_component (tree expr, gfc_component * cm)
+transfer_array_component (tree expr, gfc_component * cm, locus * where)
 {
   tree tmp;
   stmtblock_t body;
@@ -1936,7 +1944,7 @@ transfer_array_component (tree expr, gfc_component * cm)
   gfc_init_loopinfo (&loop);
   gfc_add_ss_to_loop (&loop, ss);
   gfc_conv_ss_startstride (&loop);
-  gfc_conv_loop_setup (&loop);
+  gfc_conv_loop_setup (&loop, where);
   gfc_mark_ss_chain_used (ss, 1);
   gfc_start_scalarized_body (&loop, &body);
 
@@ -1977,7 +1985,7 @@ transfer_array_component (tree expr, gfc_component * cm)
 static void
 transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
 {
-  tree tmp, function, arg2, field, expr;
+  tree tmp, function, arg2, arg3, field, expr;
   gfc_component *c;
   int kind;
 
@@ -2009,6 +2017,7 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
   kind = ts->kind;
   function = NULL;
   arg2 = NULL;
+  arg3 = NULL;
 
   switch (ts->type)
     {
@@ -2033,6 +2042,26 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
       break;
 
     case BT_CHARACTER:
+      if (kind == 4)
+       {
+         if (se->string_length)
+           arg2 = se->string_length;
+         else
+           {
+             tmp = build_fold_indirect_ref (addr_expr);
+             gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
+             arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
+             arg2 = fold_convert (gfc_charlen_type_node, arg2);
+           }
+         arg3 = build_int_cst (NULL_TREE, kind);
+         function = iocall[IOCALL_X_CHARACTER_WIDE];
+         tmp = build_fold_addr_expr (dt_parm);
+         tmp = build_call_expr (function, 4, tmp, addr_expr, arg2, arg3);
+         gfc_add_expr_to_block (&se->pre, tmp);
+         gfc_add_block_to_block (&se->pre, &se->post);
+         return;
+       }
+      /* Fall through. */
     case BT_HOLLERITH:
       if (se->string_length)
        arg2 = se->string_length;
@@ -2058,14 +2087,14 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
          tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
                             expr, field, NULL_TREE);
 
-          if (c->dimension)
+          if (c->attr.dimension)
             {
-              tmp = transfer_array_component (tmp, c);
+              tmp = transfer_array_component (tmp, c, & code->loc);
               gfc_add_expr_to_block (&se->pre, tmp);
             }
           else
             {
-              if (!c->pointer)
+              if (!c->attr.pointer)
                 tmp = build_fold_addr_expr (tmp);
               transfer_expr (se, &c->ts, tmp, code);
             }
@@ -2184,7 +2213,7 @@ gfc_trans_transfer (gfc_code * code)
 
       /* Initialize the loop.  */
       gfc_conv_ss_startstride (&loop);
-      gfc_conv_loop_setup (&loop);
+      gfc_conv_loop_setup (&loop, &code->expr->where);
 
       /* The main loop body.  */
       gfc_mark_ss_chain_used (ss, 1);