diff options
author | burnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-01-04 22:16:26 +0000 |
---|---|---|
committer | burnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-01-04 22:16:26 +0000 |
commit | 712044056b0541167cdfdb8ba5889a1c10e02595 (patch) | |
tree | 7168cd7a21534cd29647cc6bac4bb6b05ec2d4a7 /gcc | |
parent | f9606ba37e7fbcc7759b331215bffe7b36e06e8e (diff) | |
download | gcc-712044056b0541167cdfdb8ba5889a1c10e02595.tar.gz |
2013-01-04 Tobias Burnus <burnus@net-b.de>
* trans.c (gfc_build_final_call): New function.
* trans.h (gfc_build_final_call, gfc_conv_scalar_to_descriptor):
New function prototypes.
* trans-expr.c (gfc_conv_scalar_to_descriptor): Renamed from
conv_scalar_to_descriptor, removed static attribute.
(gfc_conv_procedure_call): Honor renaming.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@194919 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/fortran/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.c | 10 | ||||
-rw-r--r-- | gcc/fortran/trans.c | 112 | ||||
-rw-r--r-- | gcc/fortran/trans.h | 7 |
4 files changed, 131 insertions, 7 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 6cc5aef59df..cff66679ceb 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,5 +1,14 @@ 2013-01-04 Tobias Burnus <burnus@net-b.de> + * trans.c (gfc_build_final_call): New function. + * trans.h (gfc_build_final_call, gfc_conv_scalar_to_descriptor): + New function prototypes. + * trans-expr.c (gfc_conv_scalar_to_descriptor): Renamed from + conv_scalar_to_descriptor, removed static attribute. + (gfc_conv_procedure_call): Honor renaming. + +2013-01-04 Tobias Burnus <burnus@net-b.de> + * intrinsic.c (add_functions): New internal intrinsic function GFC_PREFIX ("stride"). * gfortran.h (gfc_isym_id): Add GFC_ISYM_STRIDE. diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 452f2bcf974..0abb52d1dd8 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -1,6 +1,6 @@ /* Expression translation Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011, 2012 + 2011, 2012, 2013 Free Software Foundation, Inc. Contributed by Paul Brook <paul@nowt.org> and Steven Bosscher <s.bosscher@student.tudelft.nl> @@ -61,8 +61,8 @@ get_scalar_to_descriptor_type (tree scalar, symbol_attribute attr) akind, !(attr.pointer || attr.target)); } -static tree -conv_scalar_to_descriptor (gfc_se *se, tree scalar, symbol_attribute attr) +tree +gfc_conv_scalar_to_descriptor (gfc_se *se, tree scalar, symbol_attribute attr) { tree desc, type; @@ -4355,8 +4355,8 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, if (TREE_CODE (tmp) == ADDR_EXPR && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (tmp, 0)))) tmp = TREE_OPERAND (tmp, 0); - parmse.expr = conv_scalar_to_descriptor (&parmse, tmp, - fsym->attr); + parmse.expr = gfc_conv_scalar_to_descriptor (&parmse, tmp, + fsym->attr); parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr); } diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index 7b630563664..84b512727f9 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -1,6 +1,6 @@ /* Code translation -- generate GCC trees from gfc_code. Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011, 2012 Free Software Foundation, Inc. + 2011, 2012, 2013 Free Software Foundation, Inc. Contributed by Paul Brook This file is part of GCC. @@ -1023,6 +1023,116 @@ gfc_deallocate_with_status (tree pointer, tree status, tree errmsg, } +/* Build a call to a FINAL procedure, which finalizes "var". */ + +tree +gfc_build_final_call (gfc_typespec ts, gfc_expr *final_wrapper, gfc_expr *var, + bool fini_coarray, gfc_expr *class_size) +{ + stmtblock_t block; + gfc_se se; + tree final_fndecl, array, size, tmp; + + gcc_assert (final_wrapper->expr_type == EXPR_VARIABLE); + gcc_assert (var); + + gfc_init_se (&se, NULL); + gfc_conv_expr (&se, final_wrapper); + final_fndecl = se.expr; + if (POINTER_TYPE_P (TREE_TYPE (final_fndecl))) + final_fndecl = build_fold_indirect_ref_loc (input_location, final_fndecl); + + if (ts.type == BT_DERIVED) + { + tree elem_size; + + gcc_assert (!class_size); + elem_size = gfc_typenode_for_spec (&ts); + elem_size = TYPE_SIZE_UNIT (elem_size); + size = fold_convert (gfc_array_index_type, elem_size); + + gfc_init_se (&se, NULL); + se.want_pointer = 1; + if (var->rank || gfc_expr_attr (var).dimension) + { + se.descriptor_only = 1; + gfc_conv_expr_descriptor (&se, var); + array = se.expr; + if (!POINTER_TYPE_P (TREE_TYPE (array))) + array = gfc_build_addr_expr (NULL, array); + } + else + { + symbol_attribute attr; + gfc_clear_attr (&attr); + gfc_conv_expr (&se, var); + gcc_assert (se.pre.head == NULL_TREE && se.post.head == NULL_TREE); + array = se.expr; + if (TREE_CODE (array) == ADDR_EXPR + && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (array, 0)))) + tmp = TREE_OPERAND (array, 0); + + gfc_init_se (&se, NULL); + array = gfc_conv_scalar_to_descriptor (&se, array, attr); + array = gfc_build_addr_expr (NULL, array); + gcc_assert (se.post.head == NULL_TREE); + } + } + else + { + gfc_expr *array_expr; + gcc_assert (class_size); + gfc_init_se (&se, NULL); + gfc_conv_expr (&se, class_size); + gcc_assert (se.pre.head == NULL_TREE && se.post.head == NULL_TREE); + size = se.expr; + + array_expr = gfc_copy_expr (var); + gfc_add_data_component (array_expr); + gfc_init_se (&se, NULL); + se.want_pointer = 1; + if (array_expr->rank || gfc_expr_attr (array_expr).dimension) + { + se.descriptor_only = 1; + gfc_conv_expr_descriptor (&se, var); + array = se.expr; + if (! POINTER_TYPE_P (TREE_TYPE (array))) + array = gfc_build_addr_expr (NULL, array); + } + else + { + symbol_attribute attr; + + gfc_clear_attr (&attr); + gfc_conv_expr (&se, array_expr); + gcc_assert (se.pre.head == NULL_TREE && se.post.head == NULL_TREE); + array = se.expr; + if (TREE_CODE (array) == ADDR_EXPR + && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (array, 0)))) + tmp = TREE_OPERAND (array, 0); + + /* attr: Argument is neither a pointer/allocatable, + i.e. no copy back needed */ + gfc_init_se (&se, NULL); + array = gfc_conv_scalar_to_descriptor (&se, array, attr); + array = gfc_build_addr_expr (NULL, array); + gcc_assert (se.post.head == NULL_TREE); + } + gfc_free_expr (array_expr); + } + + gfc_start_block (&block); + gfc_add_block_to_block (&block, &se.pre); + tmp = build_call_expr_loc (input_location, + final_fndecl, 3, array, + size, fini_coarray ? boolean_true_node + : boolean_false_node); + gfc_add_block_to_block (&block, &se.post); + gfc_add_expr_to_block (&block, tmp); + return gfc_finish_block (&block); +} + + /* Generate code for deallocation of allocatable scalars (variables or components). Before the object itself is freed, any allocatable subcomponents are being deallocated. */ diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 17795750573..339261b73e3 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -1,6 +1,6 @@ /* Header for code translation functions Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011, 2012 + 2011, 2012, 2013 Free Software Foundation, Inc. Contributed by Paul Brook @@ -352,6 +352,8 @@ tree gfc_vtable_final_get (tree); tree gfc_get_vptr_from_expr (tree); tree gfc_get_class_array_ref (tree, tree); tree gfc_copy_class_to_class (tree, tree, tree); +tree gfc_build_final_call (gfc_typespec, gfc_expr *, gfc_expr *, bool, + gfc_expr *); void gfc_conv_derived_to_class (gfc_se *, gfc_expr *, gfc_typespec, tree, bool, bool); void gfc_conv_class_to_class (gfc_se *, gfc_expr *, gfc_typespec, bool, bool, @@ -403,6 +405,9 @@ void gfc_conv_expr_lhs (gfc_se * se, gfc_expr * expr); void gfc_conv_expr_reference (gfc_se * se, gfc_expr *); void gfc_conv_expr_type (gfc_se * se, gfc_expr *, tree); +tree gfc_conv_scalar_to_descriptor (gfc_se *, tree, symbol_attribute); + + /* trans-expr.c */ void gfc_conv_scalar_char_value (gfc_symbol *sym, gfc_se *se, gfc_expr **expr); tree gfc_string_to_single_character (tree len, tree str, int kind); |