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]

[gfortran,patch] We don't need libgfortran wrappers for malloc and free


Hi all,

This patch is not a regression, wrong-code or ice-on-valid-code fix,
but I've had it ready for submission for 3 months, so I decided to
submit it. It fixes PR30723, a missed-optimization issue with the way
we allocate memory for internal use.

Currently, the front-end allocates memory for internal use by calls to
_gfortran_internal_malloc (or _gfortran_internal_malloc64 on 64-bit
systems) and frees the memory by calls to _gfortran_internal_free.
These routines are very simple wrappers around malloc/free, and
they're not really needed. Getting rid of them will enable the
middle-end to perform further optimization (some is done already, and
some will be possible in the future). This patch makes the front-end
generate code directly for these three routines. It's a bit long, but
very mechanical. What is does is:
 * remove the library routines _gfortran_internal_free,
_gfortran_internal_malloc{,64}
 * expose the library function _gfortran_os_error, which is called
when memory allocation fails
 * create functions gfc_call_free and gfc_call_malloc in trans.c;
these functions generate the code that is equivalent to the library
functions I'm removing, including calling _gfortran_os_error when
allocation fails
 * throughout the front-end, change all library calls to
_gfortran_internal_free and _gfortran_internal_malloc{,64} into code
generated using gfc_call_free and gfc_call_malloc

Bootstrapped and regtested on i686-linux, OK for mainline?

FX



:ADDPATCH fortran:

2007-05-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>

       PR fortran/30723
       * trans.h (gfor_fndecl_internal_malloc, gfor_fndecl_internal_malloc64,
       gfor_fndecl_internal_free): Remove prototypes.
       (gfor_fndecl_os_error, gfc_call_free, gfc_call_malloc): Add prototypes.
       * trans.c (gfc_call_malloc, gfc_call_free): New functions.
       * f95-lang.c (gfc_init_builtin_functions): Add __builtin_free
       and __builtin_malloc builtins.
       * trans-decl.c (gfor_fndecl_internal_malloc,
       gfor_fndecl_internal_malloc64, gfor_fndecl_internal_free): Remove.
       (gfor_fndecl_os_error): Add.
       (gfc_build_builtin_function_decls): Don't create internal_malloc,
       internal_malloc64 and internal_free library function declaration.
       Create os_error library call function declaration.
       * trans-array.c (gfc_trans_allocate_array_storage,
       gfc_trans_auto_array_allocation, gfc_trans_dummy_array_bias,
       gfc_conv_array_parameter, gfc_duplicate_allocatable): Use
       gfc_call_malloc and gfc_call_free instead of building calls to
       internal_malloc and internal_free.
       * trans-expr.c (gfc_conv_string_tmp): Likewise.
       * trans-stmt.c (gfc_do_allocate, gfc_trans_assign_need_temp,
       gfc_trans_pointer_assign_need_temp, gfc_trans_forall_1,
       gfc_trans_where_2: Likewise.
       * trans-intrinsic.c (gfc_conv_intrinsic_ctime,
       gfc_conv_intrinsic_fdate, gfc_conv_intrinsic_ttynam,
       gfc_conv_intrinsic_array_transfer, gfc_conv_intrinsic_trim): Likewise.


2007-05-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>


       PR fortran/30723
       * runtime/memory.c (internal_malloc, internal_malloc64,
       internal_free): Remove.
       * runtime/error.c (os_error): Export function.
       * intrinsics/move_alloc.c: Include stdlib.h.
       (move_alloc): Call free instead of internal_free.
       (move_alloc_c): Wrap long lines.
       * libgfortran.h (os_error): Export prototype.
       (internal_free): Remove prototype.
       * gfortran.map (GFORTRAN_1.0): Remove _gfortran_internal_free,
       _gfortran_internal_malloc and _gfortran_internal_malloc64.
       Add _gfortran_os_error.
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(revision 124497)
+++ gcc/fortran/trans-expr.c	(working copy)
@@ -928,13 +928,11 @@ gfc_conv_string_tmp (gfc_se * se, tree t
     {
       /* Allocate a temporary to hold the result.  */
       var = gfc_create_var (type, "pstr");
-      tmp = build_call_expr (gfor_fndecl_internal_malloc, 1, len);
-      tmp = convert (type, tmp);
+      tmp = gfc_call_malloc (&se->pre, type, len);
       gfc_add_modify_expr (&se->pre, var, tmp);
 
       /* Free the temporary afterwards.  */
-      tmp = convert (pvoid_type_node, var);
-      tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmp);
+      tmp = gfc_call_free (convert (pvoid_type_node, var));
       gfc_add_expr_to_block (&se->post, tmp);
     }
 
Index: gcc/fortran/trans-array.c
===================================================================
--- gcc/fortran/trans-array.c	(revision 124497)
+++ gcc/fortran/trans-array.c	(working copy)
@@ -533,13 +533,7 @@ gfc_trans_allocate_array_storage (stmtbl
       else
 	{
 	  /* Allocate memory to hold the data.  */
-	  if (gfc_index_integer_kind == 4)
-	    tmp = gfor_fndecl_internal_malloc;
-	  else if (gfc_index_integer_kind == 8)
-	    tmp = gfor_fndecl_internal_malloc64;
-	  else
-	    gcc_unreachable ();
-	  tmp = build_call_expr (tmp, 1, size);
+	  tmp = gfc_call_malloc (pre, NULL, size);
 	  tmp = gfc_evaluate_now (tmp, pre);
 	  gfc_conv_descriptor_data_set (pre, desc, tmp);
 	}
@@ -555,8 +549,7 @@ gfc_trans_allocate_array_storage (stmtbl
     {
       /* Free the temporary.  */
       tmp = gfc_conv_descriptor_data_get (desc);
-      tmp = fold_convert (pvoid_type_node, tmp);
-      tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmp);
+      tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp));
       gfc_add_expr_to_block (post, tmp);
     }
 }
@@ -3793,7 +3786,6 @@ gfc_trans_auto_array_allocation (tree de
   stmtblock_t block;
   tree type;
   tree tmp;
-  tree fndecl;
   tree size;
   tree offset;
   bool onstack;
@@ -3857,14 +3849,7 @@ gfc_trans_auto_array_allocation (tree de
   size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
 
   /* Allocate memory to hold the data.  */
-  if (gfc_index_integer_kind == 4)
-    fndecl = gfor_fndecl_internal_malloc;
-  else if (gfc_index_integer_kind == 8)
-    fndecl = gfor_fndecl_internal_malloc64;
-  else
-    gcc_unreachable ();
-  tmp = build_call_expr (fndecl, 1, size);
-  tmp = fold_convert (TREE_TYPE (decl), tmp);
+  tmp = gfc_call_malloc (&block, TREE_TYPE (decl), size);
   gfc_add_modify_expr (&block, decl, tmp);
 
   /* Set offset of the array.  */
@@ -3878,8 +3863,7 @@ gfc_trans_auto_array_allocation (tree de
   gfc_add_expr_to_block (&block, fnbody);
 
   /* Free the temporary.  */
-  tmp = convert (pvoid_type_node, decl);
-  tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmp);
+  tmp = gfc_call_free (convert (pvoid_type_node, decl));
   gfc_add_expr_to_block (&block, tmp);
 
   return gfc_finish_block (&block);
@@ -4235,7 +4219,7 @@ gfc_trans_dummy_array_bias (gfc_symbol *
 	}
 
       /* Free the temporary.  */
-      tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmpdesc);
+      tmp = gfc_call_free (tmpdesc);
       gfc_add_expr_to_block (&cleanup, tmp);
 
       stmt = gfc_finish_block (&cleanup);
@@ -4813,8 +4797,7 @@ gfc_conv_array_parameter (gfc_se * se, g
       gfc_add_expr_to_block (&block, tmp);
 
       /* Free the temporary.  */
-      tmp = convert (pvoid_type_node, ptr);
-      tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmp);
+      tmp = gfc_call_free (convert (pvoid_type_node, ptr));
       gfc_add_expr_to_block (&block, tmp);
 
       stmt = gfc_finish_block (&block);
@@ -4914,13 +4897,8 @@ gfc_duplicate_allocatable(tree dest, tre
 		      TYPE_SIZE_UNIT (gfc_get_element_type (type)));
 
   /* Allocate memory to the destination.  */
-  if (gfc_index_integer_kind == 4)
-    tmp = build_call_expr (gfor_fndecl_internal_malloc, 1, size);
-  else if (gfc_index_integer_kind == 8)
-    tmp = build_call_expr (gfor_fndecl_internal_malloc64, 1, size);
-  else
-    gcc_unreachable ();
-  tmp = fold_convert (TREE_TYPE (gfc_conv_descriptor_data_get (src)), tmp);
+  tmp = gfc_call_malloc (&block, TREE_TYPE (gfc_conv_descriptor_data_get (src)),
+			 size);
   gfc_conv_descriptor_data_set (&block, dest, tmp);
 
   /* We know the temporary and the value will be the same length,
Index: gcc/fortran/trans-stmt.c
===================================================================
--- gcc/fortran/trans-stmt.c	(revision 124497)
+++ gcc/fortran/trans-stmt.c	(working copy)
@@ -1712,14 +1712,7 @@ gfc_do_allocate (tree bytesize, tree siz
       tmpvar = gfc_create_var (build_pointer_type (type), "temp");
       *pdata = convert (pvoid_type_node, tmpvar);
 
-      if (gfc_index_integer_kind == 4)
-	tmp = gfor_fndecl_internal_malloc;
-      else if (gfc_index_integer_kind == 8)
-	tmp = gfor_fndecl_internal_malloc64;
-      else
-	gcc_unreachable ();
-      tmp = build_call_expr (tmp, 1, bytesize);
-      tmp = convert (TREE_TYPE (tmpvar), tmp);
+      tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
       gfc_add_modify_expr (pblock, tmpvar, tmp);
     }
   return tmpvar;
@@ -2230,7 +2223,7 @@ gfc_trans_assign_need_temp (gfc_expr * e
   if (ptemp1)
     {
       /* Free the temporary.  */
-      tmp = build_call_expr (gfor_fndecl_internal_free, 1, ptemp1);
+      tmp = gfc_call_free (ptemp1);
       gfc_add_expr_to_block (block, tmp);
     }
 }
@@ -2388,7 +2381,7 @@ gfc_trans_pointer_assign_need_temp (gfc_
   /* Free the temporary.  */
   if (ptemp1)
     {
-      tmp = build_call_expr (gfor_fndecl_internal_free, 1, ptemp1);
+      tmp = gfc_call_free (ptemp1);
       gfc_add_expr_to_block (block, tmp);
     }
 }
@@ -2723,7 +2716,7 @@ gfc_trans_forall_1 (gfc_code * code, for
   if (pmask)
     {
       /* Free the temporary for the mask.  */
-      tmp = build_call_expr (gfor_fndecl_internal_free, 1, pmask);
+      tmp = gfc_call_free (pmask);
       gfc_add_expr_to_block (&block, tmp);
     }
   if (maskindex)
@@ -3320,14 +3313,14 @@ gfc_trans_where_2 (gfc_code * code, tree
   /* If we allocated a pending mask array, deallocate it now.  */
   if (ppmask)
     {
-      tmp = build_call_expr (gfor_fndecl_internal_free, 1, ppmask);
+      tmp = gfc_call_free (ppmask);
       gfc_add_expr_to_block (block, tmp);
     }
 
   /* If we allocated a current mask array, deallocate it now.  */
   if (pcmask)
     {
-      tmp = build_call_expr (gfor_fndecl_internal_free, 1, pcmask);
+      tmp = gfc_call_free (pcmask);
       gfc_add_expr_to_block (block, tmp);
     }
 }
Index: gcc/fortran/trans.c
===================================================================
--- gcc/fortran/trans.c	(revision 124497)
+++ gcc/fortran/trans.c	(working copy)
@@ -29,6 +29,7 @@ Software Foundation, 51 Franklin Street,
 #include "toplev.h"
 #include "defaults.h"
 #include "real.h"
+#include "flags.h"
 #include "gfortran.h"
 #include "trans.h"
 #include "trans-stmt.h"
@@ -372,6 +373,86 @@ gfc_trans_runtime_check (tree cond, cons
 }
 
 
+/* Call malloc to allocate size bytes of memory, with special conditions:
+      + if size < 0, generate a runtime error,
+      + if size == 0, return a NULL pointer,
+      + if malloc returns NULL, issue a runtime error.  */
+tree
+gfc_call_malloc (stmtblock_t * block, tree type, tree size)
+{
+  tree tmp, msg, negative, zero, malloc_result, null_result, res;
+  stmtblock_t block2;
+
+  size = gfc_evaluate_now (size, block);
+
+  if (TREE_TYPE (size) != TREE_TYPE (size_type_node))
+    size = fold_convert (size_type_node, size);
+
+  /* Create a variable to hold the result.  */
+  res = gfc_create_var (pvoid_type_node, NULL);
+
+  /* size < 0 ?  */
+  negative = fold_build2 (LT_EXPR, boolean_type_node, size,
+			  build_int_cst (size_type_node, 0));
+  msg = gfc_build_addr_expr (pchar_type_node, gfc_build_cstring_const
+      ("Attempt to allocate a negative amount of memory."));
+  tmp = fold_build3 (COND_EXPR, void_type_node, negative,
+		     build_call_expr (gfor_fndecl_runtime_error, 1, msg),
+		     build_empty_stmt ());
+  gfc_add_expr_to_block (block, tmp);
+
+  /* Call malloc and check the result.  */
+  gfc_start_block (&block2);
+  gfc_add_modify_expr (&block2, res,
+		       build_call_expr (built_in_decls[BUILT_IN_MALLOC], 1,
+		       size));
+  null_result = fold_build2 (EQ_EXPR, boolean_type_node, res,
+			     build_int_cst (pvoid_type_node, 0));
+  msg = gfc_build_addr_expr (pchar_type_node, gfc_build_cstring_const
+      ("Memory allocation failed"));
+  tmp = fold_build3 (COND_EXPR, void_type_node, null_result,
+		     build_call_expr (gfor_fndecl_os_error, 1, msg),
+		     build_empty_stmt ());
+  gfc_add_expr_to_block (&block2, tmp);
+  malloc_result = gfc_finish_block (&block2);
+
+  /* size == 0  */
+  zero = fold_build2 (EQ_EXPR, boolean_type_node, size,
+		      build_int_cst (size_type_node, 0));
+  tmp = fold_build2 (MODIFY_EXPR, pvoid_type_node, res,
+		     build_int_cst (pvoid_type_node, 0));
+  tmp = fold_build3 (COND_EXPR, void_type_node, zero, tmp, malloc_result);
+  gfc_add_expr_to_block (block, tmp);
+
+  if (type != NULL)
+    res = fold_convert (type, res);
+  return res;
+}
+
+
+/* Free a given variable, if it's not NULL.  */
+tree
+gfc_call_free (tree var)
+{
+  stmtblock_t block;
+  tree tmp, cond, call;
+
+  if (TREE_TYPE (var) != TREE_TYPE (pvoid_type_node))
+    var = fold_convert (pvoid_type_node, var);
+
+  gfc_start_block (&block);
+  var = gfc_evaluate_now (var, &block);
+  cond = fold_build2 (NE_EXPR, boolean_type_node, var,
+		      build_int_cst (pvoid_type_node, 0));
+  call = build_call_expr (built_in_decls[BUILT_IN_FREE], 1, var);
+  tmp = fold_build3 (COND_EXPR, void_type_node, cond, call,
+		     build_empty_stmt ());
+  gfc_add_expr_to_block (&block, tmp);
+
+  return gfc_finish_block (&block);
+}
+
+
 /* Add a statement to a block.  */
 
 void
Index: gcc/fortran/trans.h
===================================================================
--- gcc/fortran/trans.h	(revision 124497)
+++ gcc/fortran/trans.h	(working copy)
@@ -439,6 +439,12 @@ bool get_array_ctor_strlen (gfc_construc
 /* Generate a runtime error check.  */
 void gfc_trans_runtime_check (tree, const char *, stmtblock_t *, locus *);
 
+/* Generate a call to free() after checking that its arg is non-NULL.  */
+tree gfc_call_free (tree);
+
+/* Allocate memory after performing a few checks.  */
+tree gfc_call_malloc (stmtblock_t *, tree, tree);
+
 /* Generate code for an assignment, includes scalarization.  */
 tree gfc_trans_assignment (gfc_expr *, gfc_expr *, bool);
 
@@ -472,11 +478,8 @@ struct gimplify_omp_ctx;
 void gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *, tree);
 
 /* Runtime library function decls.  */
-extern GTY(()) tree gfor_fndecl_internal_malloc;
-extern GTY(()) tree gfor_fndecl_internal_malloc64;
 extern GTY(()) tree gfor_fndecl_internal_realloc;
 extern GTY(()) tree gfor_fndecl_internal_realloc64;
-extern GTY(()) tree gfor_fndecl_internal_free;
 extern GTY(()) tree gfor_fndecl_allocate;
 extern GTY(()) tree gfor_fndecl_allocate64;
 extern GTY(()) tree gfor_fndecl_allocate_array;
@@ -489,6 +492,7 @@ extern GTY(()) tree gfor_fndecl_stop_str
 extern GTY(()) tree gfor_fndecl_select_string;
 extern GTY(()) tree gfor_fndecl_runtime_error;
 extern GTY(()) tree gfor_fndecl_runtime_error_at;
+extern GTY(()) tree gfor_fndecl_os_error;
 extern GTY(()) tree gfor_fndecl_generate_error;
 extern GTY(()) tree gfor_fndecl_set_fpe;
 extern GTY(()) tree gfor_fndecl_set_std;
Index: gcc/fortran/f95-lang.c
===================================================================
--- gcc/fortran/f95-lang.c	(revision 124497)
+++ gcc/fortran/f95-lang.c	(working copy)
@@ -990,6 +990,17 @@ gfc_init_builtin_functions (void)
   gfc_define_builtin ("__builtin_expect", ftype, BUILT_IN_EXPECT,
 		      "__builtin_expect", true);
 
+  tmp = tree_cons (NULL_TREE, pvoid_type_node, void_list_node);
+  ftype = build_function_type (void_type_node, tmp);
+  gfc_define_builtin ("__builtin_free", ftype, BUILT_IN_FREE,
+		      "free", false);
+
+  tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
+  ftype = build_function_type (pvoid_type_node, tmp);
+  gfc_define_builtin ("__builtin_malloc", ftype, BUILT_IN_MALLOC,
+		      "malloc", false);
+  DECL_IS_MALLOC (built_in_decls[BUILT_IN_MALLOC]) = 1;
+
 #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
   builtin_types[(int) ENUM] = VALUE;
 #define DEF_FUNCTION_TYPE_0(ENUM, RETURN)		\
Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c	(revision 124497)
+++ gcc/fortran/trans-decl.c	(working copy)
@@ -74,11 +74,8 @@ tree gfc_static_ctors;
 
 /* Function declarations for builtin library functions.  */
 
-tree gfor_fndecl_internal_malloc;
-tree gfor_fndecl_internal_malloc64;
 tree gfor_fndecl_internal_realloc;
 tree gfor_fndecl_internal_realloc64;
-tree gfor_fndecl_internal_free;
 tree gfor_fndecl_allocate;
 tree gfor_fndecl_allocate64;
 tree gfor_fndecl_allocate_array;
@@ -91,6 +88,7 @@ tree gfor_fndecl_stop_string;
 tree gfor_fndecl_select_string;
 tree gfor_fndecl_runtime_error;
 tree gfor_fndecl_runtime_error_at;
+tree gfor_fndecl_os_error;
 tree gfor_fndecl_generate_error;
 tree gfor_fndecl_set_fpe;
 tree gfor_fndecl_set_std;
@@ -2247,18 +2245,6 @@ gfc_build_builtin_function_decls (void)
   tree gfc_logical4_type_node = gfc_get_logical_type (4);
   tree gfc_pint4_type_node = build_pointer_type (gfc_int4_type_node);
 
-  /* Treat these two internal malloc wrappers as malloc.  */
-  gfor_fndecl_internal_malloc =
-    gfc_build_library_function_decl (get_identifier (PREFIX("internal_malloc")),
-				     pvoid_type_node, 1, gfc_int4_type_node);
-  DECL_IS_MALLOC (gfor_fndecl_internal_malloc) = 1;
-
-  gfor_fndecl_internal_malloc64 =
-    gfc_build_library_function_decl (get_identifier
-				     (PREFIX("internal_malloc64")),
-				     pvoid_type_node, 1, gfc_int8_type_node);
-  DECL_IS_MALLOC (gfor_fndecl_internal_malloc64) = 1;
-
   gfor_fndecl_internal_realloc =
     gfc_build_library_function_decl (get_identifier
 				     (PREFIX("internal_realloc")),
@@ -2271,10 +2257,6 @@ gfc_build_builtin_function_decls (void)
 				     pvoid_type_node, 2, pvoid_type_node,
 				     gfc_int8_type_node);
 
-  gfor_fndecl_internal_free =
-    gfc_build_library_function_decl (get_identifier (PREFIX("internal_free")),
-				     void_type_node, 1, pvoid_type_node);
-
   gfor_fndecl_allocate =
     gfc_build_library_function_decl (get_identifier (PREFIX("allocate")),
 				     pvoid_type_node, 2,
@@ -2349,6 +2331,12 @@ gfc_build_builtin_function_decls (void)
 				     void_type_node, 3, pvoid_type_node,
                                      gfc_c_int_type_node, pchar_type_node);
 
+  gfor_fndecl_os_error =
+    gfc_build_library_function_decl (get_identifier (PREFIX("os_error")),
+				     void_type_node, 1, pchar_type_node);
+  /* The runtime_error function does not return.  */
+  TREE_THIS_VOLATILE (gfor_fndecl_os_error) = 1;
+
   gfor_fndecl_set_fpe =
     gfc_build_library_function_decl (get_identifier (PREFIX("set_fpe")),
 				    void_type_node, 1, gfc_c_int_type_node);
Index: gcc/fortran/trans-intrinsic.c
===================================================================
--- gcc/fortran/trans-intrinsic.c	(revision 124497)
+++ gcc/fortran/trans-intrinsic.c	(working copy)
@@ -1275,7 +1275,7 @@ gfc_conv_intrinsic_ctime (gfc_se * se, g
   /* Free the temporary afterwards, if necessary.  */
   cond = build2 (GT_EXPR, boolean_type_node, len,
 		 build_int_cst (TREE_TYPE (len), 0));
-  tmp = build_call_expr (gfor_fndecl_internal_free, 1, var);
+  tmp = gfc_call_free (var);
   tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
   gfc_add_expr_to_block (&se->post, tmp);
 
@@ -1310,7 +1310,7 @@ gfc_conv_intrinsic_fdate (gfc_se * se, g
   /* Free the temporary afterwards, if necessary.  */
   cond = build2 (GT_EXPR, boolean_type_node, len,
 		 build_int_cst (TREE_TYPE (len), 0));
-  tmp = build_call_expr (gfor_fndecl_internal_free, 1, var);
+  tmp = gfc_call_free (var);
   tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
   gfc_add_expr_to_block (&se->post, tmp);
 
@@ -1347,7 +1347,7 @@ gfc_conv_intrinsic_ttynam (gfc_se * se, 
   /* Free the temporary afterwards, if necessary.  */
   cond = build2 (GT_EXPR, boolean_type_node, len,
 		 build_int_cst (TREE_TYPE (len), 0));
-  tmp = build_call_expr (gfor_fndecl_internal_free, 1, var);
+  tmp = gfc_call_free (var);
   tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
   gfc_add_expr_to_block (&se->post, tmp);
 
@@ -2866,8 +2866,7 @@ gfc_conv_intrinsic_array_transfer (gfc_s
 
 	  /* Free the temporary.  */
 	  gfc_start_block (&block);
-	  tmp = convert (pvoid_type_node, source);
-	  tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmp);
+	  tmp = gfc_call_free (convert (pvoid_type_node, source));
 	  gfc_add_expr_to_block (&block, tmp);
 	  stmt = gfc_finish_block (&block);
 
@@ -3364,7 +3363,7 @@ gfc_conv_intrinsic_trim (gfc_se * se, gf
   /* Free the temporary afterwards, if necessary.  */
   cond = build2 (GT_EXPR, boolean_type_node, len,
 		 build_int_cst (TREE_TYPE (len), 0));
-  tmp = build_call_expr (gfor_fndecl_internal_free, 1, var);
+  tmp = gfc_call_free (var);
   tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
   gfc_add_expr_to_block (&se->post, tmp);
 
Index: libgfortran/runtime/memory.c
===================================================================
--- libgfortran/runtime/memory.c	(revision 124497)
+++ libgfortran/runtime/memory.c	(working copy)
@@ -77,46 +77,6 @@ internal_malloc_size (size_t size)
   return get_mem (size);
 }
 
-extern void *internal_malloc (GFC_INTEGER_4);
-export_proto(internal_malloc);
-
-void *
-internal_malloc (GFC_INTEGER_4 size)
-{
-#ifdef GFC_CHECK_MEMORY
-  /* Under normal circumstances, this is _never_ going to happen!  */
-  if (size < 0)
-    runtime_error ("Attempt to allocate a negative amount of memory.");
-
-#endif
-  return internal_malloc_size ((size_t) size);
-}
-
-extern void *internal_malloc64 (GFC_INTEGER_8);
-export_proto(internal_malloc64);
-
-void *
-internal_malloc64 (GFC_INTEGER_8 size)
-{
-#ifdef GFC_CHECK_MEMORY
-  /* Under normal circumstances, this is _never_ going to happen!  */
-  if (size < 0)
-    runtime_error ("Attempt to allocate a negative amount of memory.");
-#endif
-  return internal_malloc_size ((size_t) size);
-}
-
-
-/* Free internally allocated memory.  Pointer is NULLified.  Also used to
-   free user allocated memory.  */
-
-void
-internal_free (void *mem)
-{
-  if (mem != NULL)
-    free (mem);
-}
-iexport(internal_free);
 
 /* Reallocate internal memory MEM so it has SIZE bytes of data.
    Allocate a new block if MEM is zero, and free the block if
Index: libgfortran/runtime/error.c
===================================================================
--- libgfortran/runtime/error.c	(revision 124497)
+++ libgfortran/runtime/error.c	(working copy)
@@ -285,6 +285,7 @@ os_error (const char *message)
   st_printf ("Operating system error: %s\n%s\n", get_oserror (), message);
   sys_exit (1);
 }
+iexport(os_error);
 
 
 /* void runtime_error()-- These are errors associated with an
Index: libgfortran/intrinsics/move_alloc.c
===================================================================
--- libgfortran/intrinsics/move_alloc.c	(revision 124497)
+++ libgfortran/intrinsics/move_alloc.c	(working copy)
@@ -28,8 +28,13 @@ License along with libgfortran; see the 
 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 Boston, MA 02110-1301, USA.  */
 
+#include "config.h"
 #include "libgfortran.h"
 
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
 extern void move_alloc (gfc_array_char *, gfc_array_char *);
 export_proto(move_alloc);
 
@@ -38,7 +43,8 @@ move_alloc (gfc_array_char * from, gfc_a
 {
   int i;
 
-  internal_free (to->data);
+  if (to->data)
+    free (to->data);
 
   for (i = 0; i < GFC_DESCRIPTOR_RANK (from); i++)
     {
@@ -60,8 +66,10 @@ extern void move_alloc_c (gfc_array_char
 export_proto(move_alloc_c);
 
 void
-move_alloc_c (gfc_array_char * from, GFC_INTEGER_4 from_length __attribute__((unused)),
-	      gfc_array_char * to, GFC_INTEGER_4 to_length __attribute__((unused)))
+move_alloc_c (gfc_array_char * from,
+	      GFC_INTEGER_4 from_length __attribute__((unused)),
+	      gfc_array_char * to,
+	      GFC_INTEGER_4 to_length __attribute__((unused)))
 {
   move_alloc (from, to);
 }
Index: libgfortran/gfortran.map
===================================================================
--- libgfortran/gfortran.map	(revision 124497)
+++ libgfortran/gfortran.map	(working copy)
@@ -502,6 +502,7 @@ GFORTRAN_1.0 {
     _gfortran_nearest_r16;
     _gfortran_nearest_r4;
     _gfortran_nearest_r8;
+    _gfortran_os_error;
     _gfortran_pack;
     _gfortran_pack_char;
     _gfortran_pack_s;
Index: libgfortran/libgfortran.h
===================================================================
--- libgfortran/libgfortran.h	(revision 124497)
+++ libgfortran/libgfortran.h	(working copy)
@@ -583,7 +583,7 @@ extern const char *xtoa (GFC_UINTEGER_LA
 internal_proto(xtoa);
 
 extern void os_error (const char *) __attribute__ ((noreturn));
-internal_proto(os_error);
+iexport_proto(os_error);
 
 extern void show_locus (st_parameter_common *);
 internal_proto(show_locus);
@@ -634,9 +634,6 @@ internal_proto(free_mem);
 extern void *internal_malloc_size (size_t);
 internal_proto(internal_malloc_size);
 
-extern void internal_free (void *);
-iexport_proto(internal_free);
-
 /* environ.c */
 
 extern int check_buffered (int);

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