1 1.1 mrg /* Statement translation -- generate GCC trees from gfc_code. 2 1.1 mrg Copyright (C) 2002-2022 Free Software Foundation, Inc. 3 1.1 mrg Contributed by Paul Brook <paul (at) nowt.org> 4 1.1 mrg and Steven Bosscher <s.bosscher (at) student.tudelft.nl> 5 1.1 mrg 6 1.1 mrg This file is part of GCC. 7 1.1 mrg 8 1.1 mrg GCC is free software; you can redistribute it and/or modify it under 9 1.1 mrg the terms of the GNU General Public License as published by the Free 10 1.1 mrg Software Foundation; either version 3, or (at your option) any later 11 1.1 mrg version. 12 1.1 mrg 13 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 1.1 mrg for more details. 17 1.1 mrg 18 1.1 mrg You should have received a copy of the GNU General Public License 19 1.1 mrg along with GCC; see the file COPYING3. If not see 20 1.1 mrg <http://www.gnu.org/licenses/>. */ 21 1.1 mrg 22 1.1 mrg 23 1.1 mrg #include "config.h" 24 1.1 mrg #include "system.h" 25 1.1 mrg #include "coretypes.h" 26 1.1 mrg #include "options.h" 27 1.1 mrg #include "tree.h" 28 1.1 mrg #include "gfortran.h" 29 1.1 mrg #include "trans.h" 30 1.1 mrg #include "stringpool.h" 31 1.1 mrg #include "fold-const.h" 32 1.1 mrg #include "trans-stmt.h" 33 1.1 mrg #include "trans-types.h" 34 1.1 mrg #include "trans-array.h" 35 1.1 mrg #include "trans-const.h" 36 1.1 mrg #include "dependency.h" 37 1.1 mrg 38 1.1 mrg typedef struct iter_info 39 1.1 mrg { 40 1.1 mrg tree var; 41 1.1 mrg tree start; 42 1.1 mrg tree end; 43 1.1 mrg tree step; 44 1.1 mrg struct iter_info *next; 45 1.1 mrg } 46 1.1 mrg iter_info; 47 1.1 mrg 48 1.1 mrg typedef struct forall_info 49 1.1 mrg { 50 1.1 mrg iter_info *this_loop; 51 1.1 mrg tree mask; 52 1.1 mrg tree maskindex; 53 1.1 mrg int nvar; 54 1.1 mrg tree size; 55 1.1 mrg struct forall_info *prev_nest; 56 1.1 mrg bool do_concurrent; 57 1.1 mrg } 58 1.1 mrg forall_info; 59 1.1 mrg 60 1.1 mrg static void gfc_trans_where_2 (gfc_code *, tree, bool, 61 1.1 mrg forall_info *, stmtblock_t *); 62 1.1 mrg 63 1.1 mrg /* Translate a F95 label number to a LABEL_EXPR. */ 64 1.1 mrg 65 1.1 mrg tree 66 1.1 mrg gfc_trans_label_here (gfc_code * code) 67 1.1 mrg { 68 1.1 mrg return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here)); 69 1.1 mrg } 70 1.1 mrg 71 1.1 mrg 72 1.1 mrg /* Given a variable expression which has been ASSIGNed to, find the decl 73 1.1 mrg containing the auxiliary variables. For variables in common blocks this 74 1.1 mrg is a field_decl. */ 75 1.1 mrg 76 1.1 mrg void 77 1.1 mrg gfc_conv_label_variable (gfc_se * se, gfc_expr * expr) 78 1.1 mrg { 79 1.1 mrg gcc_assert (expr->symtree->n.sym->attr.assign == 1); 80 1.1 mrg gfc_conv_expr (se, expr); 81 1.1 mrg /* Deals with variable in common block. Get the field declaration. */ 82 1.1 mrg if (TREE_CODE (se->expr) == COMPONENT_REF) 83 1.1 mrg se->expr = TREE_OPERAND (se->expr, 1); 84 1.1 mrg /* Deals with dummy argument. Get the parameter declaration. */ 85 1.1 mrg else if (TREE_CODE (se->expr) == INDIRECT_REF) 86 1.1 mrg se->expr = TREE_OPERAND (se->expr, 0); 87 1.1 mrg } 88 1.1 mrg 89 1.1 mrg /* Translate a label assignment statement. */ 90 1.1 mrg 91 1.1 mrg tree 92 1.1 mrg gfc_trans_label_assign (gfc_code * code) 93 1.1 mrg { 94 1.1 mrg tree label_tree; 95 1.1 mrg gfc_se se; 96 1.1 mrg tree len; 97 1.1 mrg tree addr; 98 1.1 mrg tree len_tree; 99 1.1 mrg int label_len; 100 1.1 mrg 101 1.1 mrg /* Start a new block. */ 102 1.1 mrg gfc_init_se (&se, NULL); 103 1.1 mrg gfc_start_block (&se.pre); 104 1.1 mrg gfc_conv_label_variable (&se, code->expr1); 105 1.1 mrg 106 1.1 mrg len = GFC_DECL_STRING_LEN (se.expr); 107 1.1 mrg addr = GFC_DECL_ASSIGN_ADDR (se.expr); 108 1.1 mrg 109 1.1 mrg label_tree = gfc_get_label_decl (code->label1); 110 1.1 mrg 111 1.1 mrg if (code->label1->defined == ST_LABEL_TARGET 112 1.1 mrg || code->label1->defined == ST_LABEL_DO_TARGET) 113 1.1 mrg { 114 1.1 mrg label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree); 115 1.1 mrg len_tree = build_int_cst (gfc_charlen_type_node, -1); 116 1.1 mrg } 117 1.1 mrg else 118 1.1 mrg { 119 1.1 mrg gfc_expr *format = code->label1->format; 120 1.1 mrg 121 1.1 mrg label_len = format->value.character.length; 122 1.1 mrg len_tree = build_int_cst (gfc_charlen_type_node, label_len); 123 1.1 mrg label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1, 124 1.1 mrg format->value.character.string); 125 1.1 mrg label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree); 126 1.1 mrg } 127 1.1 mrg 128 1.1 mrg gfc_add_modify (&se.pre, len, fold_convert (TREE_TYPE (len), len_tree)); 129 1.1 mrg gfc_add_modify (&se.pre, addr, label_tree); 130 1.1 mrg 131 1.1 mrg return gfc_finish_block (&se.pre); 132 1.1 mrg } 133 1.1 mrg 134 1.1 mrg /* Translate a GOTO statement. */ 135 1.1 mrg 136 1.1 mrg tree 137 1.1 mrg gfc_trans_goto (gfc_code * code) 138 1.1 mrg { 139 1.1 mrg locus loc = code->loc; 140 1.1 mrg tree assigned_goto; 141 1.1 mrg tree target; 142 1.1 mrg tree tmp; 143 1.1 mrg gfc_se se; 144 1.1 mrg 145 1.1 mrg if (code->label1 != NULL) 146 1.1 mrg return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1)); 147 1.1 mrg 148 1.1 mrg /* ASSIGNED GOTO. */ 149 1.1 mrg gfc_init_se (&se, NULL); 150 1.1 mrg gfc_start_block (&se.pre); 151 1.1 mrg gfc_conv_label_variable (&se, code->expr1); 152 1.1 mrg tmp = GFC_DECL_STRING_LEN (se.expr); 153 1.1 mrg tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp, 154 1.1 mrg build_int_cst (TREE_TYPE (tmp), -1)); 155 1.1 mrg gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc, 156 1.1 mrg "Assigned label is not a target label"); 157 1.1 mrg 158 1.1 mrg assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr); 159 1.1 mrg 160 1.1 mrg /* We're going to ignore a label list. It does not really change the 161 1.1 mrg statement's semantics (because it is just a further restriction on 162 1.1 mrg what's legal code); before, we were comparing label addresses here, but 163 1.1 mrg that's a very fragile business and may break with optimization. So 164 1.1 mrg just ignore it. */ 165 1.1 mrg 166 1.1 mrg target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node, 167 1.1 mrg assigned_goto); 168 1.1 mrg gfc_add_expr_to_block (&se.pre, target); 169 1.1 mrg return gfc_finish_block (&se.pre); 170 1.1 mrg } 171 1.1 mrg 172 1.1 mrg 173 1.1 mrg /* Translate an ENTRY statement. Just adds a label for this entry point. */ 174 1.1 mrg tree 175 1.1 mrg gfc_trans_entry (gfc_code * code) 176 1.1 mrg { 177 1.1 mrg return build1_v (LABEL_EXPR, code->ext.entry->label); 178 1.1 mrg } 179 1.1 mrg 180 1.1 mrg 181 1.1 mrg /* Replace a gfc_ss structure by another both in the gfc_se struct 182 1.1 mrg and the gfc_loopinfo struct. This is used in gfc_conv_elemental_dependencies 183 1.1 mrg to replace a variable ss by the corresponding temporary. */ 184 1.1 mrg 185 1.1 mrg static void 186 1.1 mrg replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss) 187 1.1 mrg { 188 1.1 mrg gfc_ss **sess, **loopss; 189 1.1 mrg 190 1.1 mrg /* The old_ss is a ss for a single variable. */ 191 1.1 mrg gcc_assert (old_ss->info->type == GFC_SS_SECTION); 192 1.1 mrg 193 1.1 mrg for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next)) 194 1.1 mrg if (*sess == old_ss) 195 1.1 mrg break; 196 1.1 mrg gcc_assert (*sess != gfc_ss_terminator); 197 1.1 mrg 198 1.1 mrg *sess = new_ss; 199 1.1 mrg new_ss->next = old_ss->next; 200 1.1 mrg 201 1.1 mrg /* Make sure that trailing references are not lost. */ 202 1.1 mrg if (old_ss->info 203 1.1 mrg && old_ss->info->data.array.ref 204 1.1 mrg && old_ss->info->data.array.ref->next 205 1.1 mrg && !(new_ss->info->data.array.ref 206 1.1 mrg && new_ss->info->data.array.ref->next)) 207 1.1 mrg new_ss->info->data.array.ref = old_ss->info->data.array.ref; 208 1.1 mrg 209 1.1 mrg for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator; 210 1.1 mrg loopss = &((*loopss)->loop_chain)) 211 1.1 mrg if (*loopss == old_ss) 212 1.1 mrg break; 213 1.1 mrg gcc_assert (*loopss != gfc_ss_terminator); 214 1.1 mrg 215 1.1 mrg *loopss = new_ss; 216 1.1 mrg new_ss->loop_chain = old_ss->loop_chain; 217 1.1 mrg new_ss->loop = old_ss->loop; 218 1.1 mrg 219 1.1 mrg gfc_free_ss (old_ss); 220 1.1 mrg } 221 1.1 mrg 222 1.1 mrg 223 1.1 mrg /* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of 224 1.1 mrg elemental subroutines. Make temporaries for output arguments if any such 225 1.1 mrg dependencies are found. Output arguments are chosen because internal_unpack 226 1.1 mrg can be used, as is, to copy the result back to the variable. */ 227 1.1 mrg static void 228 1.1 mrg gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse, 229 1.1 mrg gfc_symbol * sym, gfc_actual_arglist * arg, 230 1.1 mrg gfc_dep_check check_variable) 231 1.1 mrg { 232 1.1 mrg gfc_actual_arglist *arg0; 233 1.1 mrg gfc_expr *e; 234 1.1 mrg gfc_formal_arglist *formal; 235 1.1 mrg gfc_se parmse; 236 1.1 mrg gfc_ss *ss; 237 1.1 mrg gfc_symbol *fsym; 238 1.1 mrg tree data; 239 1.1 mrg tree size; 240 1.1 mrg tree tmp; 241 1.1 mrg 242 1.1 mrg if (loopse->ss == NULL) 243 1.1 mrg return; 244 1.1 mrg 245 1.1 mrg ss = loopse->ss; 246 1.1 mrg arg0 = arg; 247 1.1 mrg formal = gfc_sym_get_dummy_args (sym); 248 1.1 mrg 249 1.1 mrg /* Loop over all the arguments testing for dependencies. */ 250 1.1 mrg for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL) 251 1.1 mrg { 252 1.1 mrg e = arg->expr; 253 1.1 mrg if (e == NULL) 254 1.1 mrg continue; 255 1.1 mrg 256 1.1 mrg /* Obtain the info structure for the current argument. */ 257 1.1 mrg for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next) 258 1.1 mrg if (ss->info->expr == e) 259 1.1 mrg break; 260 1.1 mrg 261 1.1 mrg /* If there is a dependency, create a temporary and use it 262 1.1 mrg instead of the variable. */ 263 1.1 mrg fsym = formal ? formal->sym : NULL; 264 1.1 mrg if (e->expr_type == EXPR_VARIABLE 265 1.1 mrg && e->rank && fsym 266 1.1 mrg && fsym->attr.intent != INTENT_IN 267 1.1 mrg && gfc_check_fncall_dependency (e, fsym->attr.intent, 268 1.1 mrg sym, arg0, check_variable)) 269 1.1 mrg { 270 1.1 mrg tree initial, temptype; 271 1.1 mrg stmtblock_t temp_post; 272 1.1 mrg gfc_ss *tmp_ss; 273 1.1 mrg 274 1.1 mrg tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen, 275 1.1 mrg GFC_SS_SECTION); 276 1.1 mrg gfc_mark_ss_chain_used (tmp_ss, 1); 277 1.1 mrg tmp_ss->info->expr = ss->info->expr; 278 1.1 mrg replace_ss (loopse, ss, tmp_ss); 279 1.1 mrg 280 1.1 mrg /* Obtain the argument descriptor for unpacking. */ 281 1.1 mrg gfc_init_se (&parmse, NULL); 282 1.1 mrg parmse.want_pointer = 1; 283 1.1 mrg gfc_conv_expr_descriptor (&parmse, e); 284 1.1 mrg gfc_add_block_to_block (&se->pre, &parmse.pre); 285 1.1 mrg 286 1.1 mrg /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT), 287 1.1 mrg initialize the array temporary with a copy of the values. */ 288 1.1 mrg if (fsym->attr.intent == INTENT_INOUT 289 1.1 mrg || (fsym->ts.type ==BT_DERIVED 290 1.1 mrg && fsym->attr.intent == INTENT_OUT)) 291 1.1 mrg initial = parmse.expr; 292 1.1 mrg /* For class expressions, we always initialize with the copy of 293 1.1 mrg the values. */ 294 1.1 mrg else if (e->ts.type == BT_CLASS) 295 1.1 mrg initial = parmse.expr; 296 1.1 mrg else 297 1.1 mrg initial = NULL_TREE; 298 1.1 mrg 299 1.1 mrg if (e->ts.type != BT_CLASS) 300 1.1 mrg { 301 1.1 mrg /* Find the type of the temporary to create; we don't use the type 302 1.1 mrg of e itself as this breaks for subcomponent-references in e 303 1.1 mrg (where the type of e is that of the final reference, but 304 1.1 mrg parmse.expr's type corresponds to the full derived-type). */ 305 1.1 mrg /* TODO: Fix this somehow so we don't need a temporary of the whole 306 1.1 mrg array but instead only the components referenced. */ 307 1.1 mrg temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */ 308 1.1 mrg gcc_assert (TREE_CODE (temptype) == POINTER_TYPE); 309 1.1 mrg temptype = TREE_TYPE (temptype); 310 1.1 mrg temptype = gfc_get_element_type (temptype); 311 1.1 mrg } 312 1.1 mrg 313 1.1 mrg else 314 1.1 mrg /* For class arrays signal that the size of the dynamic type has to 315 1.1 mrg be obtained from the vtable, using the 'initial' expression. */ 316 1.1 mrg temptype = NULL_TREE; 317 1.1 mrg 318 1.1 mrg /* Generate the temporary. Cleaning up the temporary should be the 319 1.1 mrg very last thing done, so we add the code to a new block and add it 320 1.1 mrg to se->post as last instructions. */ 321 1.1 mrg size = gfc_create_var (gfc_array_index_type, NULL); 322 1.1 mrg data = gfc_create_var (pvoid_type_node, NULL); 323 1.1 mrg gfc_init_block (&temp_post); 324 1.1 mrg tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss, 325 1.1 mrg temptype, initial, false, true, 326 1.1 mrg false, &arg->expr->where); 327 1.1 mrg gfc_add_modify (&se->pre, size, tmp); 328 1.1 mrg tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data); 329 1.1 mrg gfc_add_modify (&se->pre, data, tmp); 330 1.1 mrg 331 1.1 mrg /* Update other ss' delta. */ 332 1.1 mrg gfc_set_delta (loopse->loop); 333 1.1 mrg 334 1.1 mrg /* Copy the result back using unpack..... */ 335 1.1 mrg if (e->ts.type != BT_CLASS) 336 1.1 mrg tmp = build_call_expr_loc (input_location, 337 1.1 mrg gfor_fndecl_in_unpack, 2, parmse.expr, data); 338 1.1 mrg else 339 1.1 mrg { 340 1.1 mrg /* ... except for class results where the copy is 341 1.1 mrg unconditional. */ 342 1.1 mrg tmp = build_fold_indirect_ref_loc (input_location, parmse.expr); 343 1.1 mrg tmp = gfc_conv_descriptor_data_get (tmp); 344 1.1 mrg tmp = build_call_expr_loc (input_location, 345 1.1 mrg builtin_decl_explicit (BUILT_IN_MEMCPY), 346 1.1 mrg 3, tmp, data, 347 1.1 mrg fold_convert (size_type_node, size)); 348 1.1 mrg } 349 1.1 mrg gfc_add_expr_to_block (&se->post, tmp); 350 1.1 mrg 351 1.1 mrg /* parmse.pre is already added above. */ 352 1.1 mrg gfc_add_block_to_block (&se->post, &parmse.post); 353 1.1 mrg gfc_add_block_to_block (&se->post, &temp_post); 354 1.1 mrg } 355 1.1 mrg } 356 1.1 mrg } 357 1.1 mrg 358 1.1 mrg 359 1.1 mrg /* Given an executable statement referring to an intrinsic function call, 360 1.1 mrg returns the intrinsic symbol. */ 361 1.1 mrg 362 1.1 mrg static gfc_intrinsic_sym * 363 1.1 mrg get_intrinsic_for_code (gfc_code *code) 364 1.1 mrg { 365 1.1 mrg if (code->op == EXEC_CALL) 366 1.1 mrg { 367 1.1 mrg gfc_intrinsic_sym * const isym = code->resolved_isym; 368 1.1 mrg if (isym) 369 1.1 mrg return isym; 370 1.1 mrg else 371 1.1 mrg return gfc_get_intrinsic_for_expr (code->expr1); 372 1.1 mrg } 373 1.1 mrg 374 1.1 mrg return NULL; 375 1.1 mrg } 376 1.1 mrg 377 1.1 mrg 378 1.1 mrg /* Translate the CALL statement. Builds a call to an F95 subroutine. */ 379 1.1 mrg 380 1.1 mrg tree 381 1.1 mrg gfc_trans_call (gfc_code * code, bool dependency_check, 382 1.1 mrg tree mask, tree count1, bool invert) 383 1.1 mrg { 384 1.1 mrg gfc_se se; 385 1.1 mrg gfc_ss * ss; 386 1.1 mrg int has_alternate_specifier; 387 1.1 mrg gfc_dep_check check_variable; 388 1.1 mrg tree index = NULL_TREE; 389 1.1 mrg tree maskexpr = NULL_TREE; 390 1.1 mrg tree tmp; 391 1.1 mrg bool is_intrinsic_mvbits; 392 1.1 mrg 393 1.1 mrg /* A CALL starts a new block because the actual arguments may have to 394 1.1 mrg be evaluated first. */ 395 1.1 mrg gfc_init_se (&se, NULL); 396 1.1 mrg gfc_start_block (&se.pre); 397 1.1 mrg 398 1.1 mrg gcc_assert (code->resolved_sym); 399 1.1 mrg 400 1.1 mrg ss = gfc_ss_terminator; 401 1.1 mrg if (code->resolved_sym->attr.elemental) 402 1.1 mrg ss = gfc_walk_elemental_function_args (ss, code->ext.actual, 403 1.1 mrg get_intrinsic_for_code (code), 404 1.1 mrg GFC_SS_REFERENCE); 405 1.1 mrg 406 1.1 mrg /* MVBITS is inlined but needs the dependency checking found here. */ 407 1.1 mrg is_intrinsic_mvbits = code->resolved_isym 408 1.1 mrg && code->resolved_isym->id == GFC_ISYM_MVBITS; 409 1.1 mrg 410 1.1 mrg /* Is not an elemental subroutine call with array valued arguments. */ 411 1.1 mrg if (ss == gfc_ss_terminator) 412 1.1 mrg { 413 1.1 mrg 414 1.1 mrg if (is_intrinsic_mvbits) 415 1.1 mrg { 416 1.1 mrg has_alternate_specifier = 0; 417 1.1 mrg gfc_conv_intrinsic_mvbits (&se, code->ext.actual, NULL); 418 1.1 mrg } 419 1.1 mrg else 420 1.1 mrg { 421 1.1 mrg /* Translate the call. */ 422 1.1 mrg has_alternate_specifier = 423 1.1 mrg gfc_conv_procedure_call (&se, code->resolved_sym, 424 1.1 mrg code->ext.actual, code->expr1, NULL); 425 1.1 mrg 426 1.1 mrg /* A subroutine without side-effect, by definition, does nothing! */ 427 1.1 mrg TREE_SIDE_EFFECTS (se.expr) = 1; 428 1.1 mrg } 429 1.1 mrg 430 1.1 mrg /* Chain the pieces together and return the block. */ 431 1.1 mrg if (has_alternate_specifier) 432 1.1 mrg { 433 1.1 mrg gfc_code *select_code; 434 1.1 mrg gfc_symbol *sym; 435 1.1 mrg select_code = code->next; 436 1.1 mrg gcc_assert(select_code->op == EXEC_SELECT); 437 1.1 mrg sym = select_code->expr1->symtree->n.sym; 438 1.1 mrg se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr); 439 1.1 mrg if (sym->backend_decl == NULL) 440 1.1 mrg sym->backend_decl = gfc_get_symbol_decl (sym); 441 1.1 mrg gfc_add_modify (&se.pre, sym->backend_decl, se.expr); 442 1.1 mrg } 443 1.1 mrg else 444 1.1 mrg gfc_add_expr_to_block (&se.pre, se.expr); 445 1.1 mrg 446 1.1 mrg gfc_add_block_to_block (&se.pre, &se.post); 447 1.1 mrg } 448 1.1 mrg 449 1.1 mrg else 450 1.1 mrg { 451 1.1 mrg /* An elemental subroutine call with array valued arguments has 452 1.1 mrg to be scalarized. */ 453 1.1 mrg gfc_loopinfo loop; 454 1.1 mrg stmtblock_t body; 455 1.1 mrg stmtblock_t block; 456 1.1 mrg gfc_se loopse; 457 1.1 mrg gfc_se depse; 458 1.1 mrg 459 1.1 mrg /* gfc_walk_elemental_function_args renders the ss chain in the 460 1.1 mrg reverse order to the actual argument order. */ 461 1.1 mrg ss = gfc_reverse_ss (ss); 462 1.1 mrg 463 1.1 mrg /* Initialize the loop. */ 464 1.1 mrg gfc_init_se (&loopse, NULL); 465 1.1 mrg gfc_init_loopinfo (&loop); 466 1.1 mrg gfc_add_ss_to_loop (&loop, ss); 467 1.1 mrg 468 1.1 mrg gfc_conv_ss_startstride (&loop); 469 1.1 mrg /* TODO: gfc_conv_loop_setup generates a temporary for vector 470 1.1 mrg subscripts. This could be prevented in the elemental case 471 1.1 mrg as temporaries are handled separatedly 472 1.1 mrg (below in gfc_conv_elemental_dependencies). */ 473 1.1 mrg if (code->expr1) 474 1.1 mrg gfc_conv_loop_setup (&loop, &code->expr1->where); 475 1.1 mrg else 476 1.1 mrg gfc_conv_loop_setup (&loop, &code->loc); 477 1.1 mrg 478 1.1 mrg gfc_mark_ss_chain_used (ss, 1); 479 1.1 mrg 480 1.1 mrg /* Convert the arguments, checking for dependencies. */ 481 1.1 mrg gfc_copy_loopinfo_to_se (&loopse, &loop); 482 1.1 mrg loopse.ss = ss; 483 1.1 mrg 484 1.1 mrg /* For operator assignment, do dependency checking. */ 485 1.1 mrg if (dependency_check) 486 1.1 mrg check_variable = ELEM_CHECK_VARIABLE; 487 1.1 mrg else 488 1.1 mrg check_variable = ELEM_DONT_CHECK_VARIABLE; 489 1.1 mrg 490 1.1 mrg gfc_init_se (&depse, NULL); 491 1.1 mrg gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym, 492 1.1 mrg code->ext.actual, check_variable); 493 1.1 mrg 494 1.1 mrg gfc_add_block_to_block (&loop.pre, &depse.pre); 495 1.1 mrg gfc_add_block_to_block (&loop.post, &depse.post); 496 1.1 mrg 497 1.1 mrg /* Generate the loop body. */ 498 1.1 mrg gfc_start_scalarized_body (&loop, &body); 499 1.1 mrg gfc_init_block (&block); 500 1.1 mrg 501 1.1 mrg if (mask && count1) 502 1.1 mrg { 503 1.1 mrg /* Form the mask expression according to the mask. */ 504 1.1 mrg index = count1; 505 1.1 mrg maskexpr = gfc_build_array_ref (mask, index, NULL); 506 1.1 mrg if (invert) 507 1.1 mrg maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR, 508 1.1 mrg TREE_TYPE (maskexpr), maskexpr); 509 1.1 mrg } 510 1.1 mrg 511 1.1 mrg if (is_intrinsic_mvbits) 512 1.1 mrg { 513 1.1 mrg has_alternate_specifier = 0; 514 1.1 mrg gfc_conv_intrinsic_mvbits (&loopse, code->ext.actual, &loop); 515 1.1 mrg } 516 1.1 mrg else 517 1.1 mrg { 518 1.1 mrg /* Add the subroutine call to the block. */ 519 1.1 mrg gfc_conv_procedure_call (&loopse, code->resolved_sym, 520 1.1 mrg code->ext.actual, code->expr1, 521 1.1 mrg NULL); 522 1.1 mrg } 523 1.1 mrg 524 1.1 mrg if (mask && count1) 525 1.1 mrg { 526 1.1 mrg tmp = build3_v (COND_EXPR, maskexpr, loopse.expr, 527 1.1 mrg build_empty_stmt (input_location)); 528 1.1 mrg gfc_add_expr_to_block (&loopse.pre, tmp); 529 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, 530 1.1 mrg gfc_array_index_type, 531 1.1 mrg count1, gfc_index_one_node); 532 1.1 mrg gfc_add_modify (&loopse.pre, count1, tmp); 533 1.1 mrg } 534 1.1 mrg else 535 1.1 mrg gfc_add_expr_to_block (&loopse.pre, loopse.expr); 536 1.1 mrg 537 1.1 mrg gfc_add_block_to_block (&block, &loopse.pre); 538 1.1 mrg gfc_add_block_to_block (&block, &loopse.post); 539 1.1 mrg 540 1.1 mrg /* Finish up the loop block and the loop. */ 541 1.1 mrg gfc_add_expr_to_block (&body, gfc_finish_block (&block)); 542 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body); 543 1.1 mrg gfc_add_block_to_block (&se.pre, &loop.pre); 544 1.1 mrg gfc_add_block_to_block (&se.pre, &loop.post); 545 1.1 mrg gfc_add_block_to_block (&se.pre, &se.post); 546 1.1 mrg gfc_cleanup_loop (&loop); 547 1.1 mrg } 548 1.1 mrg 549 1.1 mrg return gfc_finish_block (&se.pre); 550 1.1 mrg } 551 1.1 mrg 552 1.1 mrg 553 1.1 mrg /* Translate the RETURN statement. */ 554 1.1 mrg 555 1.1 mrg tree 556 1.1 mrg gfc_trans_return (gfc_code * code) 557 1.1 mrg { 558 1.1 mrg if (code->expr1) 559 1.1 mrg { 560 1.1 mrg gfc_se se; 561 1.1 mrg tree tmp; 562 1.1 mrg tree result; 563 1.1 mrg 564 1.1 mrg /* If code->expr is not NULL, this return statement must appear 565 1.1 mrg in a subroutine and current_fake_result_decl has already 566 1.1 mrg been generated. */ 567 1.1 mrg 568 1.1 mrg result = gfc_get_fake_result_decl (NULL, 0); 569 1.1 mrg if (!result) 570 1.1 mrg { 571 1.1 mrg gfc_warning (0, 572 1.1 mrg "An alternate return at %L without a * dummy argument", 573 1.1 mrg &code->expr1->where); 574 1.1 mrg return gfc_generate_return (); 575 1.1 mrg } 576 1.1 mrg 577 1.1 mrg /* Start a new block for this statement. */ 578 1.1 mrg gfc_init_se (&se, NULL); 579 1.1 mrg gfc_start_block (&se.pre); 580 1.1 mrg 581 1.1 mrg gfc_conv_expr (&se, code->expr1); 582 1.1 mrg 583 1.1 mrg /* Note that the actually returned expression is a simple value and 584 1.1 mrg does not depend on any pointers or such; thus we can clean-up with 585 1.1 mrg se.post before returning. */ 586 1.1 mrg tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result), 587 1.1 mrg result, fold_convert (TREE_TYPE (result), 588 1.1 mrg se.expr)); 589 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 590 1.1 mrg gfc_add_block_to_block (&se.pre, &se.post); 591 1.1 mrg 592 1.1 mrg tmp = gfc_generate_return (); 593 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 594 1.1 mrg return gfc_finish_block (&se.pre); 595 1.1 mrg } 596 1.1 mrg 597 1.1 mrg return gfc_generate_return (); 598 1.1 mrg } 599 1.1 mrg 600 1.1 mrg 601 1.1 mrg /* Translate the PAUSE statement. We have to translate this statement 602 1.1 mrg to a runtime library call. */ 603 1.1 mrg 604 1.1 mrg tree 605 1.1 mrg gfc_trans_pause (gfc_code * code) 606 1.1 mrg { 607 1.1 mrg tree gfc_int8_type_node = gfc_get_int_type (8); 608 1.1 mrg gfc_se se; 609 1.1 mrg tree tmp; 610 1.1 mrg 611 1.1 mrg /* Start a new block for this statement. */ 612 1.1 mrg gfc_init_se (&se, NULL); 613 1.1 mrg gfc_start_block (&se.pre); 614 1.1 mrg 615 1.1 mrg 616 1.1 mrg if (code->expr1 == NULL) 617 1.1 mrg { 618 1.1 mrg tmp = build_int_cst (size_type_node, 0); 619 1.1 mrg tmp = build_call_expr_loc (input_location, 620 1.1 mrg gfor_fndecl_pause_string, 2, 621 1.1 mrg build_int_cst (pchar_type_node, 0), tmp); 622 1.1 mrg } 623 1.1 mrg else if (code->expr1->ts.type == BT_INTEGER) 624 1.1 mrg { 625 1.1 mrg gfc_conv_expr (&se, code->expr1); 626 1.1 mrg tmp = build_call_expr_loc (input_location, 627 1.1 mrg gfor_fndecl_pause_numeric, 1, 628 1.1 mrg fold_convert (gfc_int8_type_node, se.expr)); 629 1.1 mrg } 630 1.1 mrg else 631 1.1 mrg { 632 1.1 mrg gfc_conv_expr_reference (&se, code->expr1); 633 1.1 mrg tmp = build_call_expr_loc (input_location, 634 1.1 mrg gfor_fndecl_pause_string, 2, 635 1.1 mrg se.expr, fold_convert (size_type_node, 636 1.1 mrg se.string_length)); 637 1.1 mrg } 638 1.1 mrg 639 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 640 1.1 mrg 641 1.1 mrg gfc_add_block_to_block (&se.pre, &se.post); 642 1.1 mrg 643 1.1 mrg return gfc_finish_block (&se.pre); 644 1.1 mrg } 645 1.1 mrg 646 1.1 mrg 647 1.1 mrg /* Translate the STOP statement. We have to translate this statement 648 1.1 mrg to a runtime library call. */ 649 1.1 mrg 650 1.1 mrg tree 651 1.1 mrg gfc_trans_stop (gfc_code *code, bool error_stop) 652 1.1 mrg { 653 1.1 mrg gfc_se se; 654 1.1 mrg tree tmp; 655 1.1 mrg tree quiet; 656 1.1 mrg 657 1.1 mrg /* Start a new block for this statement. */ 658 1.1 mrg gfc_init_se (&se, NULL); 659 1.1 mrg gfc_start_block (&se.pre); 660 1.1 mrg 661 1.1 mrg if (code->expr2) 662 1.1 mrg { 663 1.1 mrg gfc_conv_expr_val (&se, code->expr2); 664 1.1 mrg quiet = fold_convert (boolean_type_node, se.expr); 665 1.1 mrg } 666 1.1 mrg else 667 1.1 mrg quiet = boolean_false_node; 668 1.1 mrg 669 1.1 mrg if (code->expr1 == NULL) 670 1.1 mrg { 671 1.1 mrg tmp = build_int_cst (size_type_node, 0); 672 1.1 mrg tmp = build_call_expr_loc (input_location, 673 1.1 mrg error_stop 674 1.1 mrg ? (flag_coarray == GFC_FCOARRAY_LIB 675 1.1 mrg ? gfor_fndecl_caf_error_stop_str 676 1.1 mrg : gfor_fndecl_error_stop_string) 677 1.1 mrg : (flag_coarray == GFC_FCOARRAY_LIB 678 1.1 mrg ? gfor_fndecl_caf_stop_str 679 1.1 mrg : gfor_fndecl_stop_string), 680 1.1 mrg 3, build_int_cst (pchar_type_node, 0), tmp, 681 1.1 mrg quiet); 682 1.1 mrg } 683 1.1 mrg else if (code->expr1->ts.type == BT_INTEGER) 684 1.1 mrg { 685 1.1 mrg gfc_conv_expr (&se, code->expr1); 686 1.1 mrg tmp = build_call_expr_loc (input_location, 687 1.1 mrg error_stop 688 1.1 mrg ? (flag_coarray == GFC_FCOARRAY_LIB 689 1.1 mrg ? gfor_fndecl_caf_error_stop 690 1.1 mrg : gfor_fndecl_error_stop_numeric) 691 1.1 mrg : (flag_coarray == GFC_FCOARRAY_LIB 692 1.1 mrg ? gfor_fndecl_caf_stop_numeric 693 1.1 mrg : gfor_fndecl_stop_numeric), 2, 694 1.1 mrg fold_convert (integer_type_node, se.expr), 695 1.1 mrg quiet); 696 1.1 mrg } 697 1.1 mrg else 698 1.1 mrg { 699 1.1 mrg gfc_conv_expr_reference (&se, code->expr1); 700 1.1 mrg tmp = build_call_expr_loc (input_location, 701 1.1 mrg error_stop 702 1.1 mrg ? (flag_coarray == GFC_FCOARRAY_LIB 703 1.1 mrg ? gfor_fndecl_caf_error_stop_str 704 1.1 mrg : gfor_fndecl_error_stop_string) 705 1.1 mrg : (flag_coarray == GFC_FCOARRAY_LIB 706 1.1 mrg ? gfor_fndecl_caf_stop_str 707 1.1 mrg : gfor_fndecl_stop_string), 708 1.1 mrg 3, se.expr, fold_convert (size_type_node, 709 1.1 mrg se.string_length), 710 1.1 mrg quiet); 711 1.1 mrg } 712 1.1 mrg 713 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 714 1.1 mrg 715 1.1 mrg gfc_add_block_to_block (&se.pre, &se.post); 716 1.1 mrg 717 1.1 mrg return gfc_finish_block (&se.pre); 718 1.1 mrg } 719 1.1 mrg 720 1.1 mrg /* Translate the FAIL IMAGE statement. */ 721 1.1 mrg 722 1.1 mrg tree 723 1.1 mrg gfc_trans_fail_image (gfc_code *code ATTRIBUTE_UNUSED) 724 1.1 mrg { 725 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB) 726 1.1 mrg return build_call_expr_loc (input_location, 727 1.1 mrg gfor_fndecl_caf_fail_image, 0); 728 1.1 mrg else 729 1.1 mrg { 730 1.1 mrg const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4); 731 1.1 mrg gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name); 732 1.1 mrg tree tmp = gfc_get_symbol_decl (exsym); 733 1.1 mrg return build_call_expr_loc (input_location, tmp, 1, integer_zero_node); 734 1.1 mrg } 735 1.1 mrg } 736 1.1 mrg 737 1.1 mrg /* Translate the FORM TEAM statement. */ 738 1.1 mrg 739 1.1 mrg tree 740 1.1 mrg gfc_trans_form_team (gfc_code *code) 741 1.1 mrg { 742 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB) 743 1.1 mrg { 744 1.1 mrg gfc_se se; 745 1.1 mrg gfc_se argse1, argse2; 746 1.1 mrg tree team_id, team_type, tmp; 747 1.1 mrg 748 1.1 mrg gfc_init_se (&se, NULL); 749 1.1 mrg gfc_init_se (&argse1, NULL); 750 1.1 mrg gfc_init_se (&argse2, NULL); 751 1.1 mrg gfc_start_block (&se.pre); 752 1.1 mrg 753 1.1 mrg gfc_conv_expr_val (&argse1, code->expr1); 754 1.1 mrg gfc_conv_expr_val (&argse2, code->expr2); 755 1.1 mrg team_id = fold_convert (integer_type_node, argse1.expr); 756 1.1 mrg team_type = gfc_build_addr_expr (ppvoid_type_node, argse2.expr); 757 1.1 mrg 758 1.1 mrg gfc_add_block_to_block (&se.pre, &argse1.pre); 759 1.1 mrg gfc_add_block_to_block (&se.pre, &argse2.pre); 760 1.1 mrg tmp = build_call_expr_loc (input_location, 761 1.1 mrg gfor_fndecl_caf_form_team, 3, 762 1.1 mrg team_id, team_type, 763 1.1 mrg build_int_cst (integer_type_node, 0)); 764 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 765 1.1 mrg gfc_add_block_to_block (&se.pre, &argse1.post); 766 1.1 mrg gfc_add_block_to_block (&se.pre, &argse2.post); 767 1.1 mrg return gfc_finish_block (&se.pre); 768 1.1 mrg } 769 1.1 mrg else 770 1.1 mrg { 771 1.1 mrg const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4); 772 1.1 mrg gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name); 773 1.1 mrg tree tmp = gfc_get_symbol_decl (exsym); 774 1.1 mrg return build_call_expr_loc (input_location, tmp, 1, integer_zero_node); 775 1.1 mrg } 776 1.1 mrg } 777 1.1 mrg 778 1.1 mrg /* Translate the CHANGE TEAM statement. */ 779 1.1 mrg 780 1.1 mrg tree 781 1.1 mrg gfc_trans_change_team (gfc_code *code) 782 1.1 mrg { 783 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB) 784 1.1 mrg { 785 1.1 mrg gfc_se argse; 786 1.1 mrg tree team_type, tmp; 787 1.1 mrg 788 1.1 mrg gfc_init_se (&argse, NULL); 789 1.1 mrg gfc_conv_expr_val (&argse, code->expr1); 790 1.1 mrg team_type = gfc_build_addr_expr (ppvoid_type_node, argse.expr); 791 1.1 mrg 792 1.1 mrg tmp = build_call_expr_loc (input_location, 793 1.1 mrg gfor_fndecl_caf_change_team, 2, team_type, 794 1.1 mrg build_int_cst (integer_type_node, 0)); 795 1.1 mrg gfc_add_expr_to_block (&argse.pre, tmp); 796 1.1 mrg gfc_add_block_to_block (&argse.pre, &argse.post); 797 1.1 mrg return gfc_finish_block (&argse.pre); 798 1.1 mrg } 799 1.1 mrg else 800 1.1 mrg { 801 1.1 mrg const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4); 802 1.1 mrg gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name); 803 1.1 mrg tree tmp = gfc_get_symbol_decl (exsym); 804 1.1 mrg return build_call_expr_loc (input_location, tmp, 1, integer_zero_node); 805 1.1 mrg } 806 1.1 mrg } 807 1.1 mrg 808 1.1 mrg /* Translate the END TEAM statement. */ 809 1.1 mrg 810 1.1 mrg tree 811 1.1 mrg gfc_trans_end_team (gfc_code *code ATTRIBUTE_UNUSED) 812 1.1 mrg { 813 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB) 814 1.1 mrg { 815 1.1 mrg return build_call_expr_loc (input_location, 816 1.1 mrg gfor_fndecl_caf_end_team, 1, 817 1.1 mrg build_int_cst (pchar_type_node, 0)); 818 1.1 mrg } 819 1.1 mrg else 820 1.1 mrg { 821 1.1 mrg const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4); 822 1.1 mrg gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name); 823 1.1 mrg tree tmp = gfc_get_symbol_decl (exsym); 824 1.1 mrg return build_call_expr_loc (input_location, tmp, 1, integer_zero_node); 825 1.1 mrg } 826 1.1 mrg } 827 1.1 mrg 828 1.1 mrg /* Translate the SYNC TEAM statement. */ 829 1.1 mrg 830 1.1 mrg tree 831 1.1 mrg gfc_trans_sync_team (gfc_code *code) 832 1.1 mrg { 833 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB) 834 1.1 mrg { 835 1.1 mrg gfc_se argse; 836 1.1 mrg tree team_type, tmp; 837 1.1 mrg 838 1.1 mrg gfc_init_se (&argse, NULL); 839 1.1 mrg gfc_conv_expr_val (&argse, code->expr1); 840 1.1 mrg team_type = gfc_build_addr_expr (ppvoid_type_node, argse.expr); 841 1.1 mrg 842 1.1 mrg tmp = build_call_expr_loc (input_location, 843 1.1 mrg gfor_fndecl_caf_sync_team, 2, 844 1.1 mrg team_type, 845 1.1 mrg build_int_cst (integer_type_node, 0)); 846 1.1 mrg gfc_add_expr_to_block (&argse.pre, tmp); 847 1.1 mrg gfc_add_block_to_block (&argse.pre, &argse.post); 848 1.1 mrg return gfc_finish_block (&argse.pre); 849 1.1 mrg } 850 1.1 mrg else 851 1.1 mrg { 852 1.1 mrg const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4); 853 1.1 mrg gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name); 854 1.1 mrg tree tmp = gfc_get_symbol_decl (exsym); 855 1.1 mrg return build_call_expr_loc (input_location, tmp, 1, integer_zero_node); 856 1.1 mrg } 857 1.1 mrg } 858 1.1 mrg 859 1.1 mrg tree 860 1.1 mrg gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op) 861 1.1 mrg { 862 1.1 mrg gfc_se se, argse; 863 1.1 mrg tree stat = NULL_TREE, stat2 = NULL_TREE; 864 1.1 mrg tree lock_acquired = NULL_TREE, lock_acquired2 = NULL_TREE; 865 1.1 mrg 866 1.1 mrg /* Short cut: For single images without STAT= or LOCK_ACQUIRED 867 1.1 mrg return early. (ERRMSG= is always untouched for -fcoarray=single.) */ 868 1.1 mrg if (!code->expr2 && !code->expr4 && flag_coarray != GFC_FCOARRAY_LIB) 869 1.1 mrg return NULL_TREE; 870 1.1 mrg 871 1.1 mrg if (code->expr2) 872 1.1 mrg { 873 1.1 mrg gcc_assert (code->expr2->expr_type == EXPR_VARIABLE); 874 1.1 mrg gfc_init_se (&argse, NULL); 875 1.1 mrg gfc_conv_expr_val (&argse, code->expr2); 876 1.1 mrg stat = argse.expr; 877 1.1 mrg } 878 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_LIB) 879 1.1 mrg stat = null_pointer_node; 880 1.1 mrg 881 1.1 mrg if (code->expr4) 882 1.1 mrg { 883 1.1 mrg gcc_assert (code->expr4->expr_type == EXPR_VARIABLE); 884 1.1 mrg gfc_init_se (&argse, NULL); 885 1.1 mrg gfc_conv_expr_val (&argse, code->expr4); 886 1.1 mrg lock_acquired = argse.expr; 887 1.1 mrg } 888 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_LIB) 889 1.1 mrg lock_acquired = null_pointer_node; 890 1.1 mrg 891 1.1 mrg gfc_start_block (&se.pre); 892 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB) 893 1.1 mrg { 894 1.1 mrg tree tmp, token, image_index, errmsg, errmsg_len; 895 1.1 mrg tree index = build_zero_cst (gfc_array_index_type); 896 1.1 mrg tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1); 897 1.1 mrg 898 1.1 mrg if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED 899 1.1 mrg || code->expr1->symtree->n.sym->ts.u.derived->from_intmod 900 1.1 mrg != INTMOD_ISO_FORTRAN_ENV 901 1.1 mrg || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id 902 1.1 mrg != ISOFORTRAN_LOCK_TYPE) 903 1.1 mrg { 904 1.1 mrg gfc_error ("Sorry, the lock component of derived type at %L is not " 905 1.1 mrg "yet supported", &code->expr1->where); 906 1.1 mrg return NULL_TREE; 907 1.1 mrg } 908 1.1 mrg 909 1.1 mrg gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE, 910 1.1 mrg code->expr1); 911 1.1 mrg 912 1.1 mrg if (gfc_is_coindexed (code->expr1)) 913 1.1 mrg image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl); 914 1.1 mrg else 915 1.1 mrg image_index = integer_zero_node; 916 1.1 mrg 917 1.1 mrg /* For arrays, obtain the array index. */ 918 1.1 mrg if (gfc_expr_attr (code->expr1).dimension) 919 1.1 mrg { 920 1.1 mrg tree desc, tmp, extent, lbound, ubound; 921 1.1 mrg gfc_array_ref *ar, ar2; 922 1.1 mrg int i; 923 1.1 mrg 924 1.1 mrg /* TODO: Extend this, once DT components are supported. */ 925 1.1 mrg ar = &code->expr1->ref->u.ar; 926 1.1 mrg ar2 = *ar; 927 1.1 mrg memset (ar, '\0', sizeof (*ar)); 928 1.1 mrg ar->as = ar2.as; 929 1.1 mrg ar->type = AR_FULL; 930 1.1 mrg 931 1.1 mrg gfc_init_se (&argse, NULL); 932 1.1 mrg argse.descriptor_only = 1; 933 1.1 mrg gfc_conv_expr_descriptor (&argse, code->expr1); 934 1.1 mrg gfc_add_block_to_block (&se.pre, &argse.pre); 935 1.1 mrg desc = argse.expr; 936 1.1 mrg *ar = ar2; 937 1.1 mrg 938 1.1 mrg extent = build_one_cst (gfc_array_index_type); 939 1.1 mrg for (i = 0; i < ar->dimen; i++) 940 1.1 mrg { 941 1.1 mrg gfc_init_se (&argse, NULL); 942 1.1 mrg gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type); 943 1.1 mrg gfc_add_block_to_block (&argse.pre, &argse.pre); 944 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]); 945 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, 946 1.1 mrg TREE_TYPE (lbound), argse.expr, lbound); 947 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR, 948 1.1 mrg TREE_TYPE (tmp), extent, tmp); 949 1.1 mrg index = fold_build2_loc (input_location, PLUS_EXPR, 950 1.1 mrg TREE_TYPE (tmp), index, tmp); 951 1.1 mrg if (i < ar->dimen - 1) 952 1.1 mrg { 953 1.1 mrg ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]); 954 1.1 mrg tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL); 955 1.1 mrg extent = fold_build2_loc (input_location, MULT_EXPR, 956 1.1 mrg TREE_TYPE (tmp), extent, tmp); 957 1.1 mrg } 958 1.1 mrg } 959 1.1 mrg } 960 1.1 mrg 961 1.1 mrg /* errmsg. */ 962 1.1 mrg if (code->expr3) 963 1.1 mrg { 964 1.1 mrg gfc_init_se (&argse, NULL); 965 1.1 mrg argse.want_pointer = 1; 966 1.1 mrg gfc_conv_expr (&argse, code->expr3); 967 1.1 mrg gfc_add_block_to_block (&se.pre, &argse.pre); 968 1.1 mrg errmsg = argse.expr; 969 1.1 mrg errmsg_len = fold_convert (size_type_node, argse.string_length); 970 1.1 mrg } 971 1.1 mrg else 972 1.1 mrg { 973 1.1 mrg errmsg = null_pointer_node; 974 1.1 mrg errmsg_len = build_zero_cst (size_type_node); 975 1.1 mrg } 976 1.1 mrg 977 1.1 mrg if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node) 978 1.1 mrg { 979 1.1 mrg stat2 = stat; 980 1.1 mrg stat = gfc_create_var (integer_type_node, "stat"); 981 1.1 mrg } 982 1.1 mrg 983 1.1 mrg if (lock_acquired != null_pointer_node 984 1.1 mrg && TREE_TYPE (lock_acquired) != integer_type_node) 985 1.1 mrg { 986 1.1 mrg lock_acquired2 = lock_acquired; 987 1.1 mrg lock_acquired = gfc_create_var (integer_type_node, "acquired"); 988 1.1 mrg } 989 1.1 mrg 990 1.1 mrg index = fold_convert (size_type_node, index); 991 1.1 mrg if (op == EXEC_LOCK) 992 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7, 993 1.1 mrg token, index, image_index, 994 1.1 mrg lock_acquired != null_pointer_node 995 1.1 mrg ? gfc_build_addr_expr (NULL, lock_acquired) 996 1.1 mrg : lock_acquired, 997 1.1 mrg stat != null_pointer_node 998 1.1 mrg ? gfc_build_addr_expr (NULL, stat) : stat, 999 1.1 mrg errmsg, errmsg_len); 1000 1.1 mrg else 1001 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6, 1002 1.1 mrg token, index, image_index, 1003 1.1 mrg stat != null_pointer_node 1004 1.1 mrg ? gfc_build_addr_expr (NULL, stat) : stat, 1005 1.1 mrg errmsg, errmsg_len); 1006 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 1007 1.1 mrg 1008 1.1 mrg /* It guarantees memory consistency within the same segment */ 1009 1.1 mrg tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), 1010 1.1 mrg tmp = build5_loc (input_location, ASM_EXPR, void_type_node, 1011 1.1 mrg gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE, 1012 1.1 mrg tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE); 1013 1.1 mrg ASM_VOLATILE_P (tmp) = 1; 1014 1.1 mrg 1015 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 1016 1.1 mrg 1017 1.1 mrg if (stat2 != NULL_TREE) 1018 1.1 mrg gfc_add_modify (&se.pre, stat2, 1019 1.1 mrg fold_convert (TREE_TYPE (stat2), stat)); 1020 1.1 mrg 1021 1.1 mrg if (lock_acquired2 != NULL_TREE) 1022 1.1 mrg gfc_add_modify (&se.pre, lock_acquired2, 1023 1.1 mrg fold_convert (TREE_TYPE (lock_acquired2), 1024 1.1 mrg lock_acquired)); 1025 1.1 mrg 1026 1.1 mrg return gfc_finish_block (&se.pre); 1027 1.1 mrg } 1028 1.1 mrg 1029 1.1 mrg if (stat != NULL_TREE) 1030 1.1 mrg gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0)); 1031 1.1 mrg 1032 1.1 mrg if (lock_acquired != NULL_TREE) 1033 1.1 mrg gfc_add_modify (&se.pre, lock_acquired, 1034 1.1 mrg fold_convert (TREE_TYPE (lock_acquired), 1035 1.1 mrg boolean_true_node)); 1036 1.1 mrg 1037 1.1 mrg return gfc_finish_block (&se.pre); 1038 1.1 mrg } 1039 1.1 mrg 1040 1.1 mrg tree 1041 1.1 mrg gfc_trans_event_post_wait (gfc_code *code, gfc_exec_op op) 1042 1.1 mrg { 1043 1.1 mrg gfc_se se, argse; 1044 1.1 mrg tree stat = NULL_TREE, stat2 = NULL_TREE; 1045 1.1 mrg tree until_count = NULL_TREE; 1046 1.1 mrg 1047 1.1 mrg if (code->expr2) 1048 1.1 mrg { 1049 1.1 mrg gcc_assert (code->expr2->expr_type == EXPR_VARIABLE); 1050 1.1 mrg gfc_init_se (&argse, NULL); 1051 1.1 mrg gfc_conv_expr_val (&argse, code->expr2); 1052 1.1 mrg stat = argse.expr; 1053 1.1 mrg } 1054 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_LIB) 1055 1.1 mrg stat = null_pointer_node; 1056 1.1 mrg 1057 1.1 mrg if (code->expr4) 1058 1.1 mrg { 1059 1.1 mrg gfc_init_se (&argse, NULL); 1060 1.1 mrg gfc_conv_expr_val (&argse, code->expr4); 1061 1.1 mrg until_count = fold_convert (integer_type_node, argse.expr); 1062 1.1 mrg } 1063 1.1 mrg else 1064 1.1 mrg until_count = integer_one_node; 1065 1.1 mrg 1066 1.1 mrg if (flag_coarray != GFC_FCOARRAY_LIB) 1067 1.1 mrg { 1068 1.1 mrg gfc_start_block (&se.pre); 1069 1.1 mrg gfc_init_se (&argse, NULL); 1070 1.1 mrg gfc_conv_expr_val (&argse, code->expr1); 1071 1.1 mrg 1072 1.1 mrg if (op == EXEC_EVENT_POST) 1073 1.1 mrg gfc_add_modify (&se.pre, argse.expr, 1074 1.1 mrg fold_build2_loc (input_location, PLUS_EXPR, 1075 1.1 mrg TREE_TYPE (argse.expr), argse.expr, 1076 1.1 mrg build_int_cst (TREE_TYPE (argse.expr), 1))); 1077 1.1 mrg else 1078 1.1 mrg gfc_add_modify (&se.pre, argse.expr, 1079 1.1 mrg fold_build2_loc (input_location, MINUS_EXPR, 1080 1.1 mrg TREE_TYPE (argse.expr), argse.expr, 1081 1.1 mrg fold_convert (TREE_TYPE (argse.expr), 1082 1.1 mrg until_count))); 1083 1.1 mrg if (stat != NULL_TREE) 1084 1.1 mrg gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0)); 1085 1.1 mrg 1086 1.1 mrg return gfc_finish_block (&se.pre); 1087 1.1 mrg } 1088 1.1 mrg 1089 1.1 mrg gfc_start_block (&se.pre); 1090 1.1 mrg tree tmp, token, image_index, errmsg, errmsg_len; 1091 1.1 mrg tree index = build_zero_cst (gfc_array_index_type); 1092 1.1 mrg tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1); 1093 1.1 mrg 1094 1.1 mrg if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED 1095 1.1 mrg || code->expr1->symtree->n.sym->ts.u.derived->from_intmod 1096 1.1 mrg != INTMOD_ISO_FORTRAN_ENV 1097 1.1 mrg || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id 1098 1.1 mrg != ISOFORTRAN_EVENT_TYPE) 1099 1.1 mrg { 1100 1.1 mrg gfc_error ("Sorry, the event component of derived type at %L is not " 1101 1.1 mrg "yet supported", &code->expr1->where); 1102 1.1 mrg return NULL_TREE; 1103 1.1 mrg } 1104 1.1 mrg 1105 1.1 mrg gfc_init_se (&argse, NULL); 1106 1.1 mrg gfc_get_caf_token_offset (&argse, &token, NULL, caf_decl, NULL_TREE, 1107 1.1 mrg code->expr1); 1108 1.1 mrg gfc_add_block_to_block (&se.pre, &argse.pre); 1109 1.1 mrg 1110 1.1 mrg if (gfc_is_coindexed (code->expr1)) 1111 1.1 mrg image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl); 1112 1.1 mrg else 1113 1.1 mrg image_index = integer_zero_node; 1114 1.1 mrg 1115 1.1 mrg /* For arrays, obtain the array index. */ 1116 1.1 mrg if (gfc_expr_attr (code->expr1).dimension) 1117 1.1 mrg { 1118 1.1 mrg tree desc, tmp, extent, lbound, ubound; 1119 1.1 mrg gfc_array_ref *ar, ar2; 1120 1.1 mrg int i; 1121 1.1 mrg 1122 1.1 mrg /* TODO: Extend this, once DT components are supported. */ 1123 1.1 mrg ar = &code->expr1->ref->u.ar; 1124 1.1 mrg ar2 = *ar; 1125 1.1 mrg memset (ar, '\0', sizeof (*ar)); 1126 1.1 mrg ar->as = ar2.as; 1127 1.1 mrg ar->type = AR_FULL; 1128 1.1 mrg 1129 1.1 mrg gfc_init_se (&argse, NULL); 1130 1.1 mrg argse.descriptor_only = 1; 1131 1.1 mrg gfc_conv_expr_descriptor (&argse, code->expr1); 1132 1.1 mrg gfc_add_block_to_block (&se.pre, &argse.pre); 1133 1.1 mrg desc = argse.expr; 1134 1.1 mrg *ar = ar2; 1135 1.1 mrg 1136 1.1 mrg extent = build_one_cst (gfc_array_index_type); 1137 1.1 mrg for (i = 0; i < ar->dimen; i++) 1138 1.1 mrg { 1139 1.1 mrg gfc_init_se (&argse, NULL); 1140 1.1 mrg gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type); 1141 1.1 mrg gfc_add_block_to_block (&argse.pre, &argse.pre); 1142 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]); 1143 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, 1144 1.1 mrg TREE_TYPE (lbound), argse.expr, lbound); 1145 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR, 1146 1.1 mrg TREE_TYPE (tmp), extent, tmp); 1147 1.1 mrg index = fold_build2_loc (input_location, PLUS_EXPR, 1148 1.1 mrg TREE_TYPE (tmp), index, tmp); 1149 1.1 mrg if (i < ar->dimen - 1) 1150 1.1 mrg { 1151 1.1 mrg ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]); 1152 1.1 mrg tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL); 1153 1.1 mrg extent = fold_build2_loc (input_location, MULT_EXPR, 1154 1.1 mrg TREE_TYPE (tmp), extent, tmp); 1155 1.1 mrg } 1156 1.1 mrg } 1157 1.1 mrg } 1158 1.1 mrg 1159 1.1 mrg /* errmsg. */ 1160 1.1 mrg if (code->expr3) 1161 1.1 mrg { 1162 1.1 mrg gfc_init_se (&argse, NULL); 1163 1.1 mrg argse.want_pointer = 1; 1164 1.1 mrg gfc_conv_expr (&argse, code->expr3); 1165 1.1 mrg gfc_add_block_to_block (&se.pre, &argse.pre); 1166 1.1 mrg errmsg = argse.expr; 1167 1.1 mrg errmsg_len = fold_convert (size_type_node, argse.string_length); 1168 1.1 mrg } 1169 1.1 mrg else 1170 1.1 mrg { 1171 1.1 mrg errmsg = null_pointer_node; 1172 1.1 mrg errmsg_len = build_zero_cst (size_type_node); 1173 1.1 mrg } 1174 1.1 mrg 1175 1.1 mrg if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node) 1176 1.1 mrg { 1177 1.1 mrg stat2 = stat; 1178 1.1 mrg stat = gfc_create_var (integer_type_node, "stat"); 1179 1.1 mrg } 1180 1.1 mrg 1181 1.1 mrg index = fold_convert (size_type_node, index); 1182 1.1 mrg if (op == EXEC_EVENT_POST) 1183 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_post, 6, 1184 1.1 mrg token, index, image_index, 1185 1.1 mrg stat != null_pointer_node 1186 1.1 mrg ? gfc_build_addr_expr (NULL, stat) : stat, 1187 1.1 mrg errmsg, errmsg_len); 1188 1.1 mrg else 1189 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_wait, 6, 1190 1.1 mrg token, index, until_count, 1191 1.1 mrg stat != null_pointer_node 1192 1.1 mrg ? gfc_build_addr_expr (NULL, stat) : stat, 1193 1.1 mrg errmsg, errmsg_len); 1194 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 1195 1.1 mrg 1196 1.1 mrg /* It guarantees memory consistency within the same segment */ 1197 1.1 mrg tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), 1198 1.1 mrg tmp = build5_loc (input_location, ASM_EXPR, void_type_node, 1199 1.1 mrg gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE, 1200 1.1 mrg tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE); 1201 1.1 mrg ASM_VOLATILE_P (tmp) = 1; 1202 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 1203 1.1 mrg 1204 1.1 mrg if (stat2 != NULL_TREE) 1205 1.1 mrg gfc_add_modify (&se.pre, stat2, fold_convert (TREE_TYPE (stat2), stat)); 1206 1.1 mrg 1207 1.1 mrg return gfc_finish_block (&se.pre); 1208 1.1 mrg } 1209 1.1 mrg 1210 1.1 mrg tree 1211 1.1 mrg gfc_trans_sync (gfc_code *code, gfc_exec_op type) 1212 1.1 mrg { 1213 1.1 mrg gfc_se se, argse; 1214 1.1 mrg tree tmp; 1215 1.1 mrg tree images = NULL_TREE, stat = NULL_TREE, 1216 1.1 mrg errmsg = NULL_TREE, errmsglen = NULL_TREE; 1217 1.1 mrg 1218 1.1 mrg /* Short cut: For single images without bound checking or without STAT=, 1219 1.1 mrg return early. (ERRMSG= is always untouched for -fcoarray=single.) */ 1220 1.1 mrg if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) 1221 1.1 mrg && flag_coarray != GFC_FCOARRAY_LIB) 1222 1.1 mrg return NULL_TREE; 1223 1.1 mrg 1224 1.1 mrg gfc_init_se (&se, NULL); 1225 1.1 mrg gfc_start_block (&se.pre); 1226 1.1 mrg 1227 1.1 mrg if (code->expr1 && code->expr1->rank == 0) 1228 1.1 mrg { 1229 1.1 mrg gfc_init_se (&argse, NULL); 1230 1.1 mrg gfc_conv_expr_val (&argse, code->expr1); 1231 1.1 mrg images = argse.expr; 1232 1.1 mrg } 1233 1.1 mrg 1234 1.1 mrg if (code->expr2) 1235 1.1 mrg { 1236 1.1 mrg gcc_assert (code->expr2->expr_type == EXPR_VARIABLE 1237 1.1 mrg || code->expr2->expr_type == EXPR_FUNCTION); 1238 1.1 mrg gfc_init_se (&argse, NULL); 1239 1.1 mrg gfc_conv_expr_val (&argse, code->expr2); 1240 1.1 mrg stat = argse.expr; 1241 1.1 mrg } 1242 1.1 mrg else 1243 1.1 mrg stat = null_pointer_node; 1244 1.1 mrg 1245 1.1 mrg if (code->expr3 && flag_coarray == GFC_FCOARRAY_LIB) 1246 1.1 mrg { 1247 1.1 mrg gcc_assert (code->expr3->expr_type == EXPR_VARIABLE 1248 1.1 mrg || code->expr3->expr_type == EXPR_FUNCTION); 1249 1.1 mrg gfc_init_se (&argse, NULL); 1250 1.1 mrg argse.want_pointer = 1; 1251 1.1 mrg gfc_conv_expr (&argse, code->expr3); 1252 1.1 mrg gfc_conv_string_parameter (&argse); 1253 1.1 mrg errmsg = gfc_build_addr_expr (NULL, argse.expr); 1254 1.1 mrg errmsglen = fold_convert (size_type_node, argse.string_length); 1255 1.1 mrg } 1256 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_LIB) 1257 1.1 mrg { 1258 1.1 mrg errmsg = null_pointer_node; 1259 1.1 mrg errmsglen = build_int_cst (size_type_node, 0); 1260 1.1 mrg } 1261 1.1 mrg 1262 1.1 mrg /* Check SYNC IMAGES(imageset) for valid image index. 1263 1.1 mrg FIXME: Add a check for image-set arrays. */ 1264 1.1 mrg if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) 1265 1.1 mrg && code->expr1->rank == 0) 1266 1.1 mrg { 1267 1.1 mrg tree images2 = fold_convert (integer_type_node, images); 1268 1.1 mrg tree cond; 1269 1.1 mrg if (flag_coarray != GFC_FCOARRAY_LIB) 1270 1.1 mrg cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, 1271 1.1 mrg images, build_int_cst (TREE_TYPE (images), 1)); 1272 1.1 mrg else 1273 1.1 mrg { 1274 1.1 mrg tree cond2; 1275 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 1276 1.1 mrg 2, integer_zero_node, 1277 1.1 mrg build_int_cst (integer_type_node, -1)); 1278 1.1 mrg cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, 1279 1.1 mrg images2, tmp); 1280 1.1 mrg cond2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node, 1281 1.1 mrg images, 1282 1.1 mrg build_int_cst (TREE_TYPE (images), 1)); 1283 1.1 mrg cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, 1284 1.1 mrg logical_type_node, cond, cond2); 1285 1.1 mrg } 1286 1.1 mrg gfc_trans_runtime_check (true, false, cond, &se.pre, 1287 1.1 mrg &code->expr1->where, "Invalid image number " 1288 1.1 mrg "%d in SYNC IMAGES", images2); 1289 1.1 mrg } 1290 1.1 mrg 1291 1.1 mrg /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the 1292 1.1 mrg image control statements SYNC IMAGES and SYNC ALL. */ 1293 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB) 1294 1.1 mrg { 1295 1.1 mrg tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), 1296 1.1 mrg tmp = build5_loc (input_location, ASM_EXPR, void_type_node, 1297 1.1 mrg gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE, 1298 1.1 mrg tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE); 1299 1.1 mrg ASM_VOLATILE_P (tmp) = 1; 1300 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 1301 1.1 mrg } 1302 1.1 mrg 1303 1.1 mrg if (flag_coarray != GFC_FCOARRAY_LIB) 1304 1.1 mrg { 1305 1.1 mrg /* Set STAT to zero. */ 1306 1.1 mrg if (code->expr2) 1307 1.1 mrg gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0)); 1308 1.1 mrg } 1309 1.1 mrg else if (type == EXEC_SYNC_ALL || type == EXEC_SYNC_MEMORY) 1310 1.1 mrg { 1311 1.1 mrg /* SYNC ALL => stat == null_pointer_node 1312 1.1 mrg SYNC ALL(stat=s) => stat has an integer type 1313 1.1 mrg 1314 1.1 mrg If "stat" has the wrong integer type, use a temp variable of 1315 1.1 mrg the right type and later cast the result back into "stat". */ 1316 1.1 mrg if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node) 1317 1.1 mrg { 1318 1.1 mrg if (TREE_TYPE (stat) == integer_type_node) 1319 1.1 mrg stat = gfc_build_addr_expr (NULL, stat); 1320 1.1 mrg 1321 1.1 mrg if(type == EXEC_SYNC_MEMORY) 1322 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_memory, 1323 1.1 mrg 3, stat, errmsg, errmsglen); 1324 1.1 mrg else 1325 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all, 1326 1.1 mrg 3, stat, errmsg, errmsglen); 1327 1.1 mrg 1328 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 1329 1.1 mrg } 1330 1.1 mrg else 1331 1.1 mrg { 1332 1.1 mrg tree tmp_stat = gfc_create_var (integer_type_node, "stat"); 1333 1.1 mrg 1334 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all, 1335 1.1 mrg 3, gfc_build_addr_expr (NULL, tmp_stat), 1336 1.1 mrg errmsg, errmsglen); 1337 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 1338 1.1 mrg 1339 1.1 mrg gfc_add_modify (&se.pre, stat, 1340 1.1 mrg fold_convert (TREE_TYPE (stat), tmp_stat)); 1341 1.1 mrg } 1342 1.1 mrg } 1343 1.1 mrg else 1344 1.1 mrg { 1345 1.1 mrg tree len; 1346 1.1 mrg 1347 1.1 mrg gcc_assert (type == EXEC_SYNC_IMAGES); 1348 1.1 mrg 1349 1.1 mrg if (!code->expr1) 1350 1.1 mrg { 1351 1.1 mrg len = build_int_cst (integer_type_node, -1); 1352 1.1 mrg images = null_pointer_node; 1353 1.1 mrg } 1354 1.1 mrg else if (code->expr1->rank == 0) 1355 1.1 mrg { 1356 1.1 mrg len = build_int_cst (integer_type_node, 1); 1357 1.1 mrg images = gfc_build_addr_expr (NULL_TREE, images); 1358 1.1 mrg } 1359 1.1 mrg else 1360 1.1 mrg { 1361 1.1 mrg /* FIXME. */ 1362 1.1 mrg if (code->expr1->ts.kind != gfc_c_int_kind) 1363 1.1 mrg gfc_fatal_error ("Sorry, only support for integer kind %d " 1364 1.1 mrg "implemented for image-set at %L", 1365 1.1 mrg gfc_c_int_kind, &code->expr1->where); 1366 1.1 mrg 1367 1.1 mrg gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len); 1368 1.1 mrg images = se.expr; 1369 1.1 mrg 1370 1.1 mrg tmp = gfc_typenode_for_spec (&code->expr1->ts); 1371 1.1 mrg if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp)) 1372 1.1 mrg tmp = gfc_get_element_type (tmp); 1373 1.1 mrg 1374 1.1 mrg len = fold_build2_loc (input_location, TRUNC_DIV_EXPR, 1375 1.1 mrg TREE_TYPE (len), len, 1376 1.1 mrg fold_convert (TREE_TYPE (len), 1377 1.1 mrg TYPE_SIZE_UNIT (tmp))); 1378 1.1 mrg len = fold_convert (integer_type_node, len); 1379 1.1 mrg } 1380 1.1 mrg 1381 1.1 mrg /* SYNC IMAGES(imgs) => stat == null_pointer_node 1382 1.1 mrg SYNC IMAGES(imgs,stat=s) => stat has an integer type 1383 1.1 mrg 1384 1.1 mrg If "stat" has the wrong integer type, use a temp variable of 1385 1.1 mrg the right type and later cast the result back into "stat". */ 1386 1.1 mrg if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node) 1387 1.1 mrg { 1388 1.1 mrg if (TREE_TYPE (stat) == integer_type_node) 1389 1.1 mrg stat = gfc_build_addr_expr (NULL, stat); 1390 1.1 mrg 1391 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images, 1392 1.1 mrg 5, fold_convert (integer_type_node, len), 1393 1.1 mrg images, stat, errmsg, errmsglen); 1394 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 1395 1.1 mrg } 1396 1.1 mrg else 1397 1.1 mrg { 1398 1.1 mrg tree tmp_stat = gfc_create_var (integer_type_node, "stat"); 1399 1.1 mrg 1400 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images, 1401 1.1 mrg 5, fold_convert (integer_type_node, len), 1402 1.1 mrg images, gfc_build_addr_expr (NULL, tmp_stat), 1403 1.1 mrg errmsg, errmsglen); 1404 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 1405 1.1 mrg 1406 1.1 mrg gfc_add_modify (&se.pre, stat, 1407 1.1 mrg fold_convert (TREE_TYPE (stat), tmp_stat)); 1408 1.1 mrg } 1409 1.1 mrg } 1410 1.1 mrg 1411 1.1 mrg return gfc_finish_block (&se.pre); 1412 1.1 mrg } 1413 1.1 mrg 1414 1.1 mrg 1415 1.1 mrg /* Generate GENERIC for the IF construct. This function also deals with 1416 1.1 mrg the simple IF statement, because the front end translates the IF 1417 1.1 mrg statement into an IF construct. 1418 1.1 mrg 1419 1.1 mrg We translate: 1420 1.1 mrg 1421 1.1 mrg IF (cond) THEN 1422 1.1 mrg then_clause 1423 1.1 mrg ELSEIF (cond2) 1424 1.1 mrg elseif_clause 1425 1.1 mrg ELSE 1426 1.1 mrg else_clause 1427 1.1 mrg ENDIF 1428 1.1 mrg 1429 1.1 mrg into: 1430 1.1 mrg 1431 1.1 mrg pre_cond_s; 1432 1.1 mrg if (cond_s) 1433 1.1 mrg { 1434 1.1 mrg then_clause; 1435 1.1 mrg } 1436 1.1 mrg else 1437 1.1 mrg { 1438 1.1 mrg pre_cond_s 1439 1.1 mrg if (cond_s) 1440 1.1 mrg { 1441 1.1 mrg elseif_clause 1442 1.1 mrg } 1443 1.1 mrg else 1444 1.1 mrg { 1445 1.1 mrg else_clause; 1446 1.1 mrg } 1447 1.1 mrg } 1448 1.1 mrg 1449 1.1 mrg where COND_S is the simplified version of the predicate. PRE_COND_S 1450 1.1 mrg are the pre side-effects produced by the translation of the 1451 1.1 mrg conditional. 1452 1.1 mrg We need to build the chain recursively otherwise we run into 1453 1.1 mrg problems with folding incomplete statements. */ 1454 1.1 mrg 1455 1.1 mrg static tree 1456 1.1 mrg gfc_trans_if_1 (gfc_code * code) 1457 1.1 mrg { 1458 1.1 mrg gfc_se if_se; 1459 1.1 mrg tree stmt, elsestmt; 1460 1.1 mrg locus saved_loc; 1461 1.1 mrg location_t loc; 1462 1.1 mrg 1463 1.1 mrg /* Check for an unconditional ELSE clause. */ 1464 1.1 mrg if (!code->expr1) 1465 1.1 mrg return gfc_trans_code (code->next); 1466 1.1 mrg 1467 1.1 mrg /* Initialize a statement builder for each block. Puts in NULL_TREEs. */ 1468 1.1 mrg gfc_init_se (&if_se, NULL); 1469 1.1 mrg gfc_start_block (&if_se.pre); 1470 1.1 mrg 1471 1.1 mrg /* Calculate the IF condition expression. */ 1472 1.1 mrg if (code->expr1->where.lb) 1473 1.1 mrg { 1474 1.1 mrg gfc_save_backend_locus (&saved_loc); 1475 1.1 mrg gfc_set_backend_locus (&code->expr1->where); 1476 1.1 mrg } 1477 1.1 mrg 1478 1.1 mrg gfc_conv_expr_val (&if_se, code->expr1); 1479 1.1 mrg 1480 1.1 mrg if (code->expr1->where.lb) 1481 1.1 mrg gfc_restore_backend_locus (&saved_loc); 1482 1.1 mrg 1483 1.1 mrg /* Translate the THEN clause. */ 1484 1.1 mrg stmt = gfc_trans_code (code->next); 1485 1.1 mrg 1486 1.1 mrg /* Translate the ELSE clause. */ 1487 1.1 mrg if (code->block) 1488 1.1 mrg elsestmt = gfc_trans_if_1 (code->block); 1489 1.1 mrg else 1490 1.1 mrg elsestmt = build_empty_stmt (input_location); 1491 1.1 mrg 1492 1.1 mrg /* Build the condition expression and add it to the condition block. */ 1493 1.1 mrg loc = code->expr1->where.lb ? gfc_get_location (&code->expr1->where) 1494 1.1 mrg : input_location; 1495 1.1 mrg stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt, 1496 1.1 mrg elsestmt); 1497 1.1 mrg 1498 1.1 mrg gfc_add_expr_to_block (&if_se.pre, stmt); 1499 1.1 mrg 1500 1.1 mrg /* Finish off this statement. */ 1501 1.1 mrg return gfc_finish_block (&if_se.pre); 1502 1.1 mrg } 1503 1.1 mrg 1504 1.1 mrg tree 1505 1.1 mrg gfc_trans_if (gfc_code * code) 1506 1.1 mrg { 1507 1.1 mrg stmtblock_t body; 1508 1.1 mrg tree exit_label; 1509 1.1 mrg 1510 1.1 mrg /* Create exit label so it is available for trans'ing the body code. */ 1511 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE); 1512 1.1 mrg code->exit_label = exit_label; 1513 1.1 mrg 1514 1.1 mrg /* Translate the actual code in code->block. */ 1515 1.1 mrg gfc_init_block (&body); 1516 1.1 mrg gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block)); 1517 1.1 mrg 1518 1.1 mrg /* Add exit label. */ 1519 1.1 mrg gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label)); 1520 1.1 mrg 1521 1.1 mrg return gfc_finish_block (&body); 1522 1.1 mrg } 1523 1.1 mrg 1524 1.1 mrg 1525 1.1 mrg /* Translate an arithmetic IF expression. 1526 1.1 mrg 1527 1.1 mrg IF (cond) label1, label2, label3 translates to 1528 1.1 mrg 1529 1.1 mrg if (cond <= 0) 1530 1.1 mrg { 1531 1.1 mrg if (cond < 0) 1532 1.1 mrg goto label1; 1533 1.1 mrg else // cond == 0 1534 1.1 mrg goto label2; 1535 1.1 mrg } 1536 1.1 mrg else // cond > 0 1537 1.1 mrg goto label3; 1538 1.1 mrg 1539 1.1 mrg An optimized version can be generated in case of equal labels. 1540 1.1 mrg E.g., if label1 is equal to label2, we can translate it to 1541 1.1 mrg 1542 1.1 mrg if (cond <= 0) 1543 1.1 mrg goto label1; 1544 1.1 mrg else 1545 1.1 mrg goto label3; 1546 1.1 mrg */ 1547 1.1 mrg 1548 1.1 mrg tree 1549 1.1 mrg gfc_trans_arithmetic_if (gfc_code * code) 1550 1.1 mrg { 1551 1.1 mrg gfc_se se; 1552 1.1 mrg tree tmp; 1553 1.1 mrg tree branch1; 1554 1.1 mrg tree branch2; 1555 1.1 mrg tree zero; 1556 1.1 mrg 1557 1.1 mrg /* Start a new block. */ 1558 1.1 mrg gfc_init_se (&se, NULL); 1559 1.1 mrg gfc_start_block (&se.pre); 1560 1.1 mrg 1561 1.1 mrg /* Pre-evaluate COND. */ 1562 1.1 mrg gfc_conv_expr_val (&se, code->expr1); 1563 1.1 mrg se.expr = gfc_evaluate_now (se.expr, &se.pre); 1564 1.1 mrg 1565 1.1 mrg /* Build something to compare with. */ 1566 1.1 mrg zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node); 1567 1.1 mrg 1568 1.1 mrg if (code->label1->value != code->label2->value) 1569 1.1 mrg { 1570 1.1 mrg /* If (cond < 0) take branch1 else take branch2. 1571 1.1 mrg First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */ 1572 1.1 mrg branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1)); 1573 1.1 mrg branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2)); 1574 1.1 mrg 1575 1.1 mrg if (code->label1->value != code->label3->value) 1576 1.1 mrg tmp = fold_build2_loc (input_location, LT_EXPR, logical_type_node, 1577 1.1 mrg se.expr, zero); 1578 1.1 mrg else 1579 1.1 mrg tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, 1580 1.1 mrg se.expr, zero); 1581 1.1 mrg 1582 1.1 mrg branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node, 1583 1.1 mrg tmp, branch1, branch2); 1584 1.1 mrg } 1585 1.1 mrg else 1586 1.1 mrg branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1)); 1587 1.1 mrg 1588 1.1 mrg if (code->label1->value != code->label3->value 1589 1.1 mrg && code->label2->value != code->label3->value) 1590 1.1 mrg { 1591 1.1 mrg /* if (cond <= 0) take branch1 else take branch2. */ 1592 1.1 mrg branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3)); 1593 1.1 mrg tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node, 1594 1.1 mrg se.expr, zero); 1595 1.1 mrg branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node, 1596 1.1 mrg tmp, branch1, branch2); 1597 1.1 mrg } 1598 1.1 mrg 1599 1.1 mrg /* Append the COND_EXPR to the evaluation of COND, and return. */ 1600 1.1 mrg gfc_add_expr_to_block (&se.pre, branch1); 1601 1.1 mrg return gfc_finish_block (&se.pre); 1602 1.1 mrg } 1603 1.1 mrg 1604 1.1 mrg 1605 1.1 mrg /* Translate a CRITICAL block. */ 1606 1.1 mrg tree 1607 1.1 mrg gfc_trans_critical (gfc_code *code) 1608 1.1 mrg { 1609 1.1 mrg stmtblock_t block; 1610 1.1 mrg tree tmp, token = NULL_TREE; 1611 1.1 mrg 1612 1.1 mrg gfc_start_block (&block); 1613 1.1 mrg 1614 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB) 1615 1.1 mrg { 1616 1.1 mrg tree zero_size = build_zero_cst (size_type_node); 1617 1.1 mrg token = gfc_get_symbol_decl (code->resolved_sym); 1618 1.1 mrg token = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (token)); 1619 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7, 1620 1.1 mrg token, zero_size, integer_one_node, 1621 1.1 mrg null_pointer_node, null_pointer_node, 1622 1.1 mrg null_pointer_node, zero_size); 1623 1.1 mrg gfc_add_expr_to_block (&block, tmp); 1624 1.1 mrg 1625 1.1 mrg /* It guarantees memory consistency within the same segment */ 1626 1.1 mrg tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), 1627 1.1 mrg tmp = build5_loc (input_location, ASM_EXPR, void_type_node, 1628 1.1 mrg gfc_build_string_const (1, ""), 1629 1.1 mrg NULL_TREE, NULL_TREE, 1630 1.1 mrg tree_cons (NULL_TREE, tmp, NULL_TREE), 1631 1.1 mrg NULL_TREE); 1632 1.1 mrg ASM_VOLATILE_P (tmp) = 1; 1633 1.1 mrg 1634 1.1 mrg gfc_add_expr_to_block (&block, tmp); 1635 1.1 mrg } 1636 1.1 mrg 1637 1.1 mrg tmp = gfc_trans_code (code->block->next); 1638 1.1 mrg gfc_add_expr_to_block (&block, tmp); 1639 1.1 mrg 1640 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB) 1641 1.1 mrg { 1642 1.1 mrg tree zero_size = build_zero_cst (size_type_node); 1643 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6, 1644 1.1 mrg token, zero_size, integer_one_node, 1645 1.1 mrg null_pointer_node, null_pointer_node, 1646 1.1 mrg zero_size); 1647 1.1 mrg gfc_add_expr_to_block (&block, tmp); 1648 1.1 mrg 1649 1.1 mrg /* It guarantees memory consistency within the same segment */ 1650 1.1 mrg tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), 1651 1.1 mrg tmp = build5_loc (input_location, ASM_EXPR, void_type_node, 1652 1.1 mrg gfc_build_string_const (1, ""), 1653 1.1 mrg NULL_TREE, NULL_TREE, 1654 1.1 mrg tree_cons (NULL_TREE, tmp, NULL_TREE), 1655 1.1 mrg NULL_TREE); 1656 1.1 mrg ASM_VOLATILE_P (tmp) = 1; 1657 1.1 mrg 1658 1.1 mrg gfc_add_expr_to_block (&block, tmp); 1659 1.1 mrg } 1660 1.1 mrg 1661 1.1 mrg return gfc_finish_block (&block); 1662 1.1 mrg } 1663 1.1 mrg 1664 1.1 mrg 1665 1.1 mrg /* Return true, when the class has a _len component. */ 1666 1.1 mrg 1667 1.1 mrg static bool 1668 1.1 mrg class_has_len_component (gfc_symbol *sym) 1669 1.1 mrg { 1670 1.1 mrg gfc_component *comp = sym->ts.u.derived->components; 1671 1.1 mrg while (comp) 1672 1.1 mrg { 1673 1.1 mrg if (strcmp (comp->name, "_len") == 0) 1674 1.1 mrg return true; 1675 1.1 mrg comp = comp->next; 1676 1.1 mrg } 1677 1.1 mrg return false; 1678 1.1 mrg } 1679 1.1 mrg 1680 1.1 mrg 1681 1.1 mrg static void 1682 1.1 mrg copy_descriptor (stmtblock_t *block, tree dst, tree src, int rank) 1683 1.1 mrg { 1684 1.1 mrg int n; 1685 1.1 mrg tree dim; 1686 1.1 mrg tree tmp; 1687 1.1 mrg tree tmp2; 1688 1.1 mrg tree size; 1689 1.1 mrg tree offset; 1690 1.1 mrg 1691 1.1 mrg offset = gfc_index_zero_node; 1692 1.1 mrg 1693 1.1 mrg /* Use memcpy to copy the descriptor. The size is the minimum of 1694 1.1 mrg the sizes of 'src' and 'dst'. This avoids a non-trivial conversion. */ 1695 1.1 mrg tmp = TYPE_SIZE_UNIT (TREE_TYPE (src)); 1696 1.1 mrg tmp2 = TYPE_SIZE_UNIT (TREE_TYPE (dst)); 1697 1.1 mrg size = fold_build2_loc (input_location, MIN_EXPR, 1698 1.1 mrg TREE_TYPE (tmp), tmp, tmp2); 1699 1.1 mrg tmp = builtin_decl_explicit (BUILT_IN_MEMCPY); 1700 1.1 mrg tmp = build_call_expr_loc (input_location, tmp, 3, 1701 1.1 mrg gfc_build_addr_expr (NULL_TREE, dst), 1702 1.1 mrg gfc_build_addr_expr (NULL_TREE, src), 1703 1.1 mrg fold_convert (size_type_node, size)); 1704 1.1 mrg gfc_add_expr_to_block (block, tmp); 1705 1.1 mrg 1706 1.1 mrg /* Set the offset correctly. */ 1707 1.1 mrg for (n = 0; n < rank; n++) 1708 1.1 mrg { 1709 1.1 mrg dim = gfc_rank_cst[n]; 1710 1.1 mrg tmp = gfc_conv_descriptor_lbound_get (src, dim); 1711 1.1 mrg tmp2 = gfc_conv_descriptor_stride_get (src, dim); 1712 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp), 1713 1.1 mrg tmp, tmp2); 1714 1.1 mrg offset = fold_build2_loc (input_location, MINUS_EXPR, 1715 1.1 mrg TREE_TYPE (offset), offset, tmp); 1716 1.1 mrg offset = gfc_evaluate_now (offset, block); 1717 1.1 mrg } 1718 1.1 mrg 1719 1.1 mrg gfc_conv_descriptor_offset_set (block, dst, offset); 1720 1.1 mrg } 1721 1.1 mrg 1722 1.1 mrg 1723 1.1 mrg /* Do proper initialization for ASSOCIATE names. */ 1724 1.1 mrg 1725 1.1 mrg static void 1726 1.1 mrg trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) 1727 1.1 mrg { 1728 1.1 mrg gfc_expr *e; 1729 1.1 mrg tree tmp; 1730 1.1 mrg bool class_target; 1731 1.1 mrg bool unlimited; 1732 1.1 mrg tree desc; 1733 1.1 mrg tree offset; 1734 1.1 mrg tree dim; 1735 1.1 mrg int n; 1736 1.1 mrg tree charlen; 1737 1.1 mrg bool need_len_assign; 1738 1.1 mrg bool whole_array = true; 1739 1.1 mrg gfc_ref *ref; 1740 1.1 mrg gfc_symbol *sym2; 1741 1.1 mrg 1742 1.1 mrg gcc_assert (sym->assoc); 1743 1.1 mrg e = sym->assoc->target; 1744 1.1 mrg 1745 1.1 mrg class_target = (e->expr_type == EXPR_VARIABLE) 1746 1.1 mrg && (gfc_is_class_scalar_expr (e) 1747 1.1 mrg || gfc_is_class_array_ref (e, NULL)); 1748 1.1 mrg 1749 1.1 mrg unlimited = UNLIMITED_POLY (e); 1750 1.1 mrg 1751 1.1 mrg for (ref = e->ref; ref; ref = ref->next) 1752 1.1 mrg if (ref->type == REF_ARRAY 1753 1.1 mrg && ref->u.ar.type == AR_FULL 1754 1.1 mrg && ref->next) 1755 1.1 mrg { 1756 1.1 mrg whole_array = false; 1757 1.1 mrg break; 1758 1.1 mrg } 1759 1.1 mrg 1760 1.1 mrg /* Assignments to the string length need to be generated, when 1761 1.1 mrg ( sym is a char array or 1762 1.1 mrg sym has a _len component) 1763 1.1 mrg and the associated expression is unlimited polymorphic, which is 1764 1.1 mrg not (yet) correctly in 'unlimited', because for an already associated 1765 1.1 mrg BT_DERIVED the u-poly flag is not set, i.e., 1766 1.1 mrg __tmp_CHARACTER_0_1 => w => arg 1767 1.1 mrg ^ generated temp ^ from code, the w does not have the u-poly 1768 1.1 mrg flag set, where UNLIMITED_POLY(e) expects it. */ 1769 1.1 mrg need_len_assign = ((unlimited || (e->ts.type == BT_DERIVED 1770 1.1 mrg && e->ts.u.derived->attr.unlimited_polymorphic)) 1771 1.1 mrg && (sym->ts.type == BT_CHARACTER 1772 1.1 mrg || ((sym->ts.type == BT_CLASS || sym->ts.type == BT_DERIVED) 1773 1.1 mrg && class_has_len_component (sym))) 1774 1.1 mrg && !sym->attr.select_rank_temporary); 1775 1.1 mrg 1776 1.1 mrg /* Do a `pointer assignment' with updated descriptor (or assign descriptor 1777 1.1 mrg to array temporary) for arrays with either unknown shape or if associating 1778 1.1 mrg to a variable. Select rank temporaries need somewhat different treatment 1779 1.1 mrg to other associate names and case temporaries. This because the selector 1780 1.1 mrg is assumed rank and so the offset in particular has to be changed. Also, 1781 1.1 mrg the case temporaries carry both allocatable and target attributes if 1782 1.1 mrg present in the selector. This means that an allocatation or change of 1783 1.1 mrg association can occur and so has to be dealt with. */ 1784 1.1 mrg if (sym->attr.select_rank_temporary) 1785 1.1 mrg { 1786 1.1 mrg gfc_se se; 1787 1.1 mrg tree class_decl = NULL_TREE; 1788 1.1 mrg int rank = 0; 1789 1.1 mrg bool class_ptr; 1790 1.1 mrg 1791 1.1 mrg sym2 = e->symtree->n.sym; 1792 1.1 mrg gfc_init_se (&se, NULL); 1793 1.1 mrg if (e->ts.type == BT_CLASS) 1794 1.1 mrg { 1795 1.1 mrg /* Go straight to the class data. */ 1796 1.1 mrg if (sym2->attr.dummy && !sym2->attr.optional) 1797 1.1 mrg { 1798 1.1 mrg class_decl = sym2->backend_decl; 1799 1.1 mrg if (DECL_LANG_SPECIFIC (class_decl) 1800 1.1 mrg && GFC_DECL_SAVED_DESCRIPTOR (class_decl)) 1801 1.1 mrg class_decl = GFC_DECL_SAVED_DESCRIPTOR (class_decl); 1802 1.1 mrg if (POINTER_TYPE_P (TREE_TYPE (class_decl))) 1803 1.1 mrg class_decl = build_fold_indirect_ref_loc (input_location, 1804 1.1 mrg class_decl); 1805 1.1 mrg gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (class_decl))); 1806 1.1 mrg se.expr = gfc_class_data_get (class_decl); 1807 1.1 mrg } 1808 1.1 mrg else 1809 1.1 mrg { 1810 1.1 mrg class_decl = sym2->backend_decl; 1811 1.1 mrg gfc_conv_expr_descriptor (&se, e); 1812 1.1 mrg if (POINTER_TYPE_P (TREE_TYPE (se.expr))) 1813 1.1 mrg se.expr = build_fold_indirect_ref_loc (input_location, 1814 1.1 mrg se.expr); 1815 1.1 mrg } 1816 1.1 mrg 1817 1.1 mrg if (CLASS_DATA (sym)->as && CLASS_DATA (sym)->as->rank > 0) 1818 1.1 mrg rank = CLASS_DATA (sym)->as->rank; 1819 1.1 mrg } 1820 1.1 mrg else 1821 1.1 mrg { 1822 1.1 mrg gfc_conv_expr_descriptor (&se, e); 1823 1.1 mrg if (sym->as && sym->as->rank > 0) 1824 1.1 mrg rank = sym->as->rank; 1825 1.1 mrg } 1826 1.1 mrg 1827 1.1 mrg desc = sym->backend_decl; 1828 1.1 mrg 1829 1.1 mrg /* The SELECT TYPE mechanisms turn class temporaries into pointers, which 1830 1.1 mrg point to the selector. */ 1831 1.1 mrg class_ptr = class_decl != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (desc)); 1832 1.1 mrg if (class_ptr) 1833 1.1 mrg { 1834 1.1 mrg tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (desc)), "class"); 1835 1.1 mrg tmp = gfc_build_addr_expr (NULL, tmp); 1836 1.1 mrg gfc_add_modify (&se.pre, desc, tmp); 1837 1.1 mrg 1838 1.1 mrg tmp = gfc_class_vptr_get (class_decl); 1839 1.1 mrg gfc_add_modify (&se.pre, gfc_class_vptr_get (desc), tmp); 1840 1.1 mrg if (UNLIMITED_POLY (sym)) 1841 1.1 mrg gfc_add_modify (&se.pre, gfc_class_len_get (desc), 1842 1.1 mrg gfc_class_len_get (class_decl)); 1843 1.1 mrg 1844 1.1 mrg desc = gfc_class_data_get (desc); 1845 1.1 mrg } 1846 1.1 mrg 1847 1.1 mrg /* SELECT RANK temporaries can carry the allocatable and pointer 1848 1.1 mrg attributes so the selector descriptor must be copied in and 1849 1.1 mrg copied out. */ 1850 1.1 mrg if (rank > 0) 1851 1.1 mrg copy_descriptor (&se.pre, desc, se.expr, rank); 1852 1.1 mrg else 1853 1.1 mrg { 1854 1.1 mrg tmp = gfc_conv_descriptor_data_get (se.expr); 1855 1.1 mrg gfc_add_modify (&se.pre, desc, 1856 1.1 mrg fold_convert (TREE_TYPE (desc), tmp)); 1857 1.1 mrg } 1858 1.1 mrg 1859 1.1 mrg /* Deal with associate_name => selector. Class associate names are 1860 1.1 mrg treated in the same way as in SELECT TYPE. */ 1861 1.1 mrg sym2 = sym->assoc->target->symtree->n.sym; 1862 1.1 mrg if (sym2->assoc && sym->assoc->target && sym2->ts.type != BT_CLASS) 1863 1.1 mrg { 1864 1.1 mrg sym2 = sym2->assoc->target->symtree->n.sym; 1865 1.1 mrg se.expr = sym2->backend_decl; 1866 1.1 mrg 1867 1.1 mrg if (POINTER_TYPE_P (TREE_TYPE (se.expr))) 1868 1.1 mrg se.expr = build_fold_indirect_ref_loc (input_location, 1869 1.1 mrg se.expr); 1870 1.1 mrg } 1871 1.1 mrg 1872 1.1 mrg /* There could have been reallocation. Copy descriptor back to the 1873 1.1 mrg selector and update the offset. */ 1874 1.1 mrg if (sym->attr.allocatable || sym->attr.pointer 1875 1.1 mrg || (sym->ts.type == BT_CLASS 1876 1.1 mrg && (CLASS_DATA (sym)->attr.allocatable 1877 1.1 mrg || CLASS_DATA (sym)->attr.pointer))) 1878 1.1 mrg { 1879 1.1 mrg if (rank > 0) 1880 1.1 mrg copy_descriptor (&se.post, se.expr, desc, rank); 1881 1.1 mrg else 1882 1.1 mrg gfc_conv_descriptor_data_set (&se.post, se.expr, desc); 1883 1.1 mrg 1884 1.1 mrg /* The dynamic type could have changed too. */ 1885 1.1 mrg if (sym->ts.type == BT_CLASS) 1886 1.1 mrg { 1887 1.1 mrg tmp = sym->backend_decl; 1888 1.1 mrg if (class_ptr) 1889 1.1 mrg tmp = build_fold_indirect_ref_loc (input_location, tmp); 1890 1.1 mrg gfc_add_modify (&se.post, gfc_class_vptr_get (class_decl), 1891 1.1 mrg gfc_class_vptr_get (tmp)); 1892 1.1 mrg if (UNLIMITED_POLY (sym)) 1893 1.1 mrg gfc_add_modify (&se.post, gfc_class_len_get (class_decl), 1894 1.1 mrg gfc_class_len_get (tmp)); 1895 1.1 mrg } 1896 1.1 mrg } 1897 1.1 mrg 1898 1.1 mrg tmp = gfc_finish_block (&se.post); 1899 1.1 mrg 1900 1.1 mrg gfc_add_init_cleanup (block, gfc_finish_block (&se.pre), tmp); 1901 1.1 mrg } 1902 1.1 mrg /* Now all the other kinds of associate variable. */ 1903 1.1 mrg else if (sym->attr.dimension && !class_target 1904 1.1 mrg && (sym->as->type == AS_DEFERRED || sym->assoc->variable)) 1905 1.1 mrg { 1906 1.1 mrg gfc_se se; 1907 1.1 mrg tree desc; 1908 1.1 mrg bool cst_array_ctor; 1909 1.1 mrg 1910 1.1 mrg desc = sym->backend_decl; 1911 1.1 mrg cst_array_ctor = e->expr_type == EXPR_ARRAY 1912 1.1 mrg && gfc_constant_array_constructor_p (e->value.constructor) 1913 1.1 mrg && e->ts.type != BT_CHARACTER; 1914 1.1 mrg 1915 1.1 mrg /* If association is to an expression, evaluate it and create temporary. 1916 1.1 mrg Otherwise, get descriptor of target for pointer assignment. */ 1917 1.1 mrg gfc_init_se (&se, NULL); 1918 1.1 mrg 1919 1.1 mrg if (sym->assoc->variable || cst_array_ctor) 1920 1.1 mrg { 1921 1.1 mrg se.direct_byref = 1; 1922 1.1 mrg se.use_offset = 1; 1923 1.1 mrg se.expr = desc; 1924 1.1 mrg GFC_DECL_PTR_ARRAY_P (sym->backend_decl) = 1; 1925 1.1 mrg } 1926 1.1 mrg 1927 1.1 mrg gfc_conv_expr_descriptor (&se, e); 1928 1.1 mrg 1929 1.1 mrg if (sym->ts.type == BT_CHARACTER 1930 1.1 mrg && sym->ts.deferred 1931 1.1 mrg && !sym->attr.select_type_temporary 1932 1.1 mrg && VAR_P (sym->ts.u.cl->backend_decl) 1933 1.1 mrg && se.string_length != sym->ts.u.cl->backend_decl) 1934 1.1 mrg { 1935 1.1 mrg gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl, 1936 1.1 mrg fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl), 1937 1.1 mrg se.string_length)); 1938 1.1 mrg } 1939 1.1 mrg 1940 1.1 mrg /* If we didn't already do the pointer assignment, set associate-name 1941 1.1 mrg descriptor to the one generated for the temporary. */ 1942 1.1 mrg if ((!sym->assoc->variable && !cst_array_ctor) 1943 1.1 mrg || !whole_array) 1944 1.1 mrg { 1945 1.1 mrg int dim; 1946 1.1 mrg 1947 1.1 mrg if (whole_array) 1948 1.1 mrg gfc_add_modify (&se.pre, desc, se.expr); 1949 1.1 mrg 1950 1.1 mrg /* The generated descriptor has lower bound zero (as array 1951 1.1 mrg temporary), shift bounds so we get lower bounds of 1. */ 1952 1.1 mrg for (dim = 0; dim < e->rank; ++dim) 1953 1.1 mrg gfc_conv_shift_descriptor_lbound (&se.pre, desc, 1954 1.1 mrg dim, gfc_index_one_node); 1955 1.1 mrg } 1956 1.1 mrg 1957 1.1 mrg /* If this is a subreference array pointer associate name use the 1958 1.1 mrg associate variable element size for the value of 'span'. */ 1959 1.1 mrg if (sym->attr.subref_array_pointer && !se.direct_byref) 1960 1.1 mrg { 1961 1.1 mrg gcc_assert (e->expr_type == EXPR_VARIABLE); 1962 1.1 mrg tmp = gfc_get_array_span (se.expr, e); 1963 1.1 mrg 1964 1.1 mrg gfc_conv_descriptor_span_set (&se.pre, desc, tmp); 1965 1.1 mrg } 1966 1.1 mrg 1967 1.1 mrg if (e->expr_type == EXPR_FUNCTION 1968 1.1 mrg && sym->ts.type == BT_DERIVED 1969 1.1 mrg && sym->ts.u.derived 1970 1.1 mrg && sym->ts.u.derived->attr.pdt_type) 1971 1.1 mrg { 1972 1.1 mrg tmp = gfc_deallocate_pdt_comp (sym->ts.u.derived, se.expr, 1973 1.1 mrg sym->as->rank); 1974 1.1 mrg gfc_add_expr_to_block (&se.post, tmp); 1975 1.1 mrg } 1976 1.1 mrg 1977 1.1 mrg /* Done, register stuff as init / cleanup code. */ 1978 1.1 mrg gfc_add_init_cleanup (block, gfc_finish_block (&se.pre), 1979 1.1 mrg gfc_finish_block (&se.post)); 1980 1.1 mrg } 1981 1.1 mrg 1982 1.1 mrg /* Temporaries, arising from TYPE IS, just need the descriptor of class 1983 1.1 mrg arrays to be assigned directly. */ 1984 1.1 mrg else if (class_target && sym->attr.dimension 1985 1.1 mrg && (sym->ts.type == BT_DERIVED || unlimited)) 1986 1.1 mrg { 1987 1.1 mrg gfc_se se; 1988 1.1 mrg 1989 1.1 mrg gfc_init_se (&se, NULL); 1990 1.1 mrg se.descriptor_only = 1; 1991 1.1 mrg /* In a select type the (temporary) associate variable shall point to 1992 1.1 mrg a standard fortran array (lower bound == 1), but conv_expr () 1993 1.1 mrg just maps to the input array in the class object, whose lbound may 1994 1.1 mrg be arbitrary. conv_expr_descriptor solves this by inserting a 1995 1.1 mrg temporary array descriptor. */ 1996 1.1 mrg gfc_conv_expr_descriptor (&se, e); 1997 1.1 mrg 1998 1.1 mrg gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)) 1999 1.1 mrg || GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr))); 2000 1.1 mrg gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl))); 2001 1.1 mrg 2002 1.1 mrg if (GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr))) 2003 1.1 mrg { 2004 1.1 mrg if (INDIRECT_REF_P (se.expr)) 2005 1.1 mrg tmp = TREE_OPERAND (se.expr, 0); 2006 1.1 mrg else 2007 1.1 mrg tmp = se.expr; 2008 1.1 mrg 2009 1.1 mrg gfc_add_modify (&se.pre, sym->backend_decl, 2010 1.1 mrg gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (tmp))); 2011 1.1 mrg } 2012 1.1 mrg else 2013 1.1 mrg gfc_add_modify (&se.pre, sym->backend_decl, se.expr); 2014 1.1 mrg 2015 1.1 mrg if (unlimited) 2016 1.1 mrg { 2017 1.1 mrg /* Recover the dtype, which has been overwritten by the 2018 1.1 mrg assignment from an unlimited polymorphic object. */ 2019 1.1 mrg tmp = gfc_conv_descriptor_dtype (sym->backend_decl); 2020 1.1 mrg gfc_add_modify (&se.pre, tmp, 2021 1.1 mrg gfc_get_dtype (TREE_TYPE (sym->backend_decl))); 2022 1.1 mrg } 2023 1.1 mrg 2024 1.1 mrg gfc_add_init_cleanup (block, gfc_finish_block (&se.pre), 2025 1.1 mrg gfc_finish_block (&se.post)); 2026 1.1 mrg } 2027 1.1 mrg 2028 1.1 mrg /* Do a scalar pointer assignment; this is for scalar variable targets. */ 2029 1.1 mrg else if (gfc_is_associate_pointer (sym)) 2030 1.1 mrg { 2031 1.1 mrg gfc_se se; 2032 1.1 mrg 2033 1.1 mrg gcc_assert (!sym->attr.dimension); 2034 1.1 mrg 2035 1.1 mrg gfc_init_se (&se, NULL); 2036 1.1 mrg 2037 1.1 mrg /* Class associate-names come this way because they are 2038 1.1 mrg unconditionally associate pointers and the symbol is scalar. */ 2039 1.1 mrg if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension) 2040 1.1 mrg { 2041 1.1 mrg tree target_expr; 2042 1.1 mrg /* For a class array we need a descriptor for the selector. */ 2043 1.1 mrg gfc_conv_expr_descriptor (&se, e); 2044 1.1 mrg /* Needed to get/set the _len component below. */ 2045 1.1 mrg target_expr = se.expr; 2046 1.1 mrg 2047 1.1 mrg /* Obtain a temporary class container for the result. */ 2048 1.1 mrg gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false); 2049 1.1 mrg se.expr = build_fold_indirect_ref_loc (input_location, se.expr); 2050 1.1 mrg 2051 1.1 mrg /* Set the offset. */ 2052 1.1 mrg desc = gfc_class_data_get (se.expr); 2053 1.1 mrg offset = gfc_index_zero_node; 2054 1.1 mrg for (n = 0; n < e->rank; n++) 2055 1.1 mrg { 2056 1.1 mrg dim = gfc_rank_cst[n]; 2057 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR, 2058 1.1 mrg gfc_array_index_type, 2059 1.1 mrg gfc_conv_descriptor_stride_get (desc, dim), 2060 1.1 mrg gfc_conv_descriptor_lbound_get (desc, dim)); 2061 1.1 mrg offset = fold_build2_loc (input_location, MINUS_EXPR, 2062 1.1 mrg gfc_array_index_type, 2063 1.1 mrg offset, tmp); 2064 1.1 mrg } 2065 1.1 mrg if (need_len_assign) 2066 1.1 mrg { 2067 1.1 mrg if (e->symtree 2068 1.1 mrg && DECL_LANG_SPECIFIC (e->symtree->n.sym->backend_decl) 2069 1.1 mrg && GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl) 2070 1.1 mrg && TREE_CODE (target_expr) != COMPONENT_REF) 2071 1.1 mrg /* Use the original class descriptor stored in the saved 2072 1.1 mrg descriptor to get the target_expr. */ 2073 1.1 mrg target_expr = 2074 1.1 mrg GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl); 2075 1.1 mrg else 2076 1.1 mrg /* Strip the _data component from the target_expr. */ 2077 1.1 mrg target_expr = TREE_OPERAND (target_expr, 0); 2078 1.1 mrg /* Add a reference to the _len comp to the target expr. */ 2079 1.1 mrg tmp = gfc_class_len_get (target_expr); 2080 1.1 mrg /* Get the component-ref for the temp structure's _len comp. */ 2081 1.1 mrg charlen = gfc_class_len_get (se.expr); 2082 1.1 mrg /* Add the assign to the beginning of the block... */ 2083 1.1 mrg gfc_add_modify (&se.pre, charlen, 2084 1.1 mrg fold_convert (TREE_TYPE (charlen), tmp)); 2085 1.1 mrg /* and the oposite way at the end of the block, to hand changes 2086 1.1 mrg on the string length back. */ 2087 1.1 mrg gfc_add_modify (&se.post, tmp, 2088 1.1 mrg fold_convert (TREE_TYPE (tmp), charlen)); 2089 1.1 mrg /* Length assignment done, prevent adding it again below. */ 2090 1.1 mrg need_len_assign = false; 2091 1.1 mrg } 2092 1.1 mrg gfc_conv_descriptor_offset_set (&se.pre, desc, offset); 2093 1.1 mrg } 2094 1.1 mrg else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS 2095 1.1 mrg && CLASS_DATA (e)->attr.dimension) 2096 1.1 mrg { 2097 1.1 mrg /* This is bound to be a class array element. */ 2098 1.1 mrg gfc_conv_expr_reference (&se, e); 2099 1.1 mrg /* Get the _vptr component of the class object. */ 2100 1.1 mrg tmp = gfc_get_vptr_from_expr (se.expr); 2101 1.1 mrg /* Obtain a temporary class container for the result. */ 2102 1.1 mrg gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false); 2103 1.1 mrg se.expr = build_fold_indirect_ref_loc (input_location, se.expr); 2104 1.1 mrg need_len_assign = false; 2105 1.1 mrg } 2106 1.1 mrg else 2107 1.1 mrg { 2108 1.1 mrg /* For BT_CLASS and BT_DERIVED, this boils down to a pointer assign, 2109 1.1 mrg which has the string length included. For CHARACTERS it is still 2110 1.1 mrg needed and will be done at the end of this routine. */ 2111 1.1 mrg gfc_conv_expr (&se, e); 2112 1.1 mrg need_len_assign = need_len_assign && sym->ts.type == BT_CHARACTER; 2113 1.1 mrg } 2114 1.1 mrg 2115 1.1 mrg if (sym->ts.type == BT_CHARACTER 2116 1.1 mrg && !sym->attr.select_type_temporary 2117 1.1 mrg && VAR_P (sym->ts.u.cl->backend_decl) 2118 1.1 mrg && se.string_length != sym->ts.u.cl->backend_decl) 2119 1.1 mrg { 2120 1.1 mrg gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl, 2121 1.1 mrg fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl), 2122 1.1 mrg se.string_length)); 2123 1.1 mrg if (e->expr_type == EXPR_FUNCTION) 2124 1.1 mrg { 2125 1.1 mrg tmp = gfc_call_free (sym->backend_decl); 2126 1.1 mrg gfc_add_expr_to_block (&se.post, tmp); 2127 1.1 mrg } 2128 1.1 mrg } 2129 1.1 mrg 2130 1.1 mrg if (sym->ts.type == BT_CHARACTER && e->ts.type == BT_CHARACTER 2131 1.1 mrg && POINTER_TYPE_P (TREE_TYPE (se.expr))) 2132 1.1 mrg { 2133 1.1 mrg /* These are pointer types already. */ 2134 1.1 mrg tmp = fold_convert (TREE_TYPE (sym->backend_decl), se.expr); 2135 1.1 mrg } 2136 1.1 mrg else 2137 1.1 mrg { 2138 1.1 mrg tree ctree = gfc_get_class_from_expr (se.expr); 2139 1.1 mrg tmp = TREE_TYPE (sym->backend_decl); 2140 1.1 mrg 2141 1.1 mrg /* Coarray scalar component expressions can emerge from 2142 1.1 mrg the front end as array elements of the _data field. */ 2143 1.1 mrg if (sym->ts.type == BT_CLASS 2144 1.1 mrg && e->ts.type == BT_CLASS && e->rank == 0 2145 1.1 mrg && !GFC_CLASS_TYPE_P (TREE_TYPE (se.expr)) && ctree) 2146 1.1 mrg { 2147 1.1 mrg tree stmp; 2148 1.1 mrg tree dtmp; 2149 1.1 mrg 2150 1.1 mrg se.expr = ctree; 2151 1.1 mrg dtmp = TREE_TYPE (TREE_TYPE (sym->backend_decl)); 2152 1.1 mrg ctree = gfc_create_var (dtmp, "class"); 2153 1.1 mrg 2154 1.1 mrg stmp = gfc_class_data_get (se.expr); 2155 1.1 mrg gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (stmp))); 2156 1.1 mrg 2157 1.1 mrg /* Set the fields of the target class variable. */ 2158 1.1 mrg stmp = gfc_conv_descriptor_data_get (stmp); 2159 1.1 mrg dtmp = gfc_class_data_get (ctree); 2160 1.1 mrg stmp = fold_convert (TREE_TYPE (dtmp), stmp); 2161 1.1 mrg gfc_add_modify (&se.pre, dtmp, stmp); 2162 1.1 mrg stmp = gfc_class_vptr_get (se.expr); 2163 1.1 mrg dtmp = gfc_class_vptr_get (ctree); 2164 1.1 mrg stmp = fold_convert (TREE_TYPE (dtmp), stmp); 2165 1.1 mrg gfc_add_modify (&se.pre, dtmp, stmp); 2166 1.1 mrg if (UNLIMITED_POLY (sym)) 2167 1.1 mrg { 2168 1.1 mrg stmp = gfc_class_len_get (se.expr); 2169 1.1 mrg dtmp = gfc_class_len_get (ctree); 2170 1.1 mrg stmp = fold_convert (TREE_TYPE (dtmp), stmp); 2171 1.1 mrg gfc_add_modify (&se.pre, dtmp, stmp); 2172 1.1 mrg } 2173 1.1 mrg se.expr = ctree; 2174 1.1 mrg } 2175 1.1 mrg tmp = gfc_build_addr_expr (tmp, se.expr); 2176 1.1 mrg } 2177 1.1 mrg 2178 1.1 mrg gfc_add_modify (&se.pre, sym->backend_decl, tmp); 2179 1.1 mrg 2180 1.1 mrg gfc_add_init_cleanup (block, gfc_finish_block( &se.pre), 2181 1.1 mrg gfc_finish_block (&se.post)); 2182 1.1 mrg } 2183 1.1 mrg 2184 1.1 mrg /* Do a simple assignment. This is for scalar expressions, where we 2185 1.1 mrg can simply use expression assignment. */ 2186 1.1 mrg else 2187 1.1 mrg { 2188 1.1 mrg gfc_expr *lhs; 2189 1.1 mrg tree res; 2190 1.1 mrg gfc_se se; 2191 1.1 mrg 2192 1.1 mrg gfc_init_se (&se, NULL); 2193 1.1 mrg 2194 1.1 mrg /* resolve.cc converts some associate names to allocatable so that 2195 1.1 mrg allocation can take place automatically in gfc_trans_assignment. 2196 1.1 mrg The frontend prevents them from being either allocated, 2197 1.1 mrg deallocated or reallocated. */ 2198 1.1 mrg if (sym->attr.allocatable) 2199 1.1 mrg { 2200 1.1 mrg tmp = sym->backend_decl; 2201 1.1 mrg if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp))) 2202 1.1 mrg tmp = gfc_conv_descriptor_data_get (tmp); 2203 1.1 mrg gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp), 2204 1.1 mrg null_pointer_node)); 2205 1.1 mrg } 2206 1.1 mrg 2207 1.1 mrg lhs = gfc_lval_expr_from_sym (sym); 2208 1.1 mrg res = gfc_trans_assignment (lhs, e, false, true); 2209 1.1 mrg gfc_add_expr_to_block (&se.pre, res); 2210 1.1 mrg 2211 1.1 mrg tmp = sym->backend_decl; 2212 1.1 mrg if (e->expr_type == EXPR_FUNCTION 2213 1.1 mrg && sym->ts.type == BT_DERIVED 2214 1.1 mrg && sym->ts.u.derived 2215 1.1 mrg && sym->ts.u.derived->attr.pdt_type) 2216 1.1 mrg { 2217 1.1 mrg tmp = gfc_deallocate_pdt_comp (sym->ts.u.derived, tmp, 2218 1.1 mrg 0); 2219 1.1 mrg } 2220 1.1 mrg else if (e->expr_type == EXPR_FUNCTION 2221 1.1 mrg && sym->ts.type == BT_CLASS 2222 1.1 mrg && CLASS_DATA (sym)->ts.u.derived 2223 1.1 mrg && CLASS_DATA (sym)->ts.u.derived->attr.pdt_type) 2224 1.1 mrg { 2225 1.1 mrg tmp = gfc_class_data_get (tmp); 2226 1.1 mrg tmp = gfc_deallocate_pdt_comp (CLASS_DATA (sym)->ts.u.derived, 2227 1.1 mrg tmp, 0); 2228 1.1 mrg } 2229 1.1 mrg else if (sym->attr.allocatable) 2230 1.1 mrg { 2231 1.1 mrg tmp = sym->backend_decl; 2232 1.1 mrg 2233 1.1 mrg if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp))) 2234 1.1 mrg tmp = gfc_conv_descriptor_data_get (tmp); 2235 1.1 mrg 2236 1.1 mrg /* A simple call to free suffices here. */ 2237 1.1 mrg tmp = gfc_call_free (tmp); 2238 1.1 mrg 2239 1.1 mrg /* Make sure that reallocation on assignment cannot occur. */ 2240 1.1 mrg sym->attr.allocatable = 0; 2241 1.1 mrg } 2242 1.1 mrg else 2243 1.1 mrg tmp = NULL_TREE; 2244 1.1 mrg 2245 1.1 mrg res = gfc_finish_block (&se.pre); 2246 1.1 mrg gfc_add_init_cleanup (block, res, tmp); 2247 1.1 mrg gfc_free_expr (lhs); 2248 1.1 mrg } 2249 1.1 mrg 2250 1.1 mrg /* Set the stringlength, when needed. */ 2251 1.1 mrg if (need_len_assign) 2252 1.1 mrg { 2253 1.1 mrg gfc_se se; 2254 1.1 mrg gfc_init_se (&se, NULL); 2255 1.1 mrg if (e->symtree->n.sym->ts.type == BT_CHARACTER) 2256 1.1 mrg { 2257 1.1 mrg /* Deferred strings are dealt with in the preceeding. */ 2258 1.1 mrg gcc_assert (!e->symtree->n.sym->ts.deferred); 2259 1.1 mrg tmp = e->symtree->n.sym->ts.u.cl->backend_decl; 2260 1.1 mrg } 2261 1.1 mrg else if (e->symtree->n.sym->attr.function 2262 1.1 mrg && e->symtree->n.sym == e->symtree->n.sym->result) 2263 1.1 mrg { 2264 1.1 mrg tmp = gfc_get_fake_result_decl (e->symtree->n.sym, 0); 2265 1.1 mrg tmp = gfc_class_len_get (tmp); 2266 1.1 mrg } 2267 1.1 mrg else 2268 1.1 mrg tmp = gfc_class_len_get (gfc_get_symbol_decl (e->symtree->n.sym)); 2269 1.1 mrg gfc_get_symbol_decl (sym); 2270 1.1 mrg charlen = sym->ts.type == BT_CHARACTER ? sym->ts.u.cl->backend_decl 2271 1.1 mrg : gfc_class_len_get (sym->backend_decl); 2272 1.1 mrg /* Prevent adding a noop len= len. */ 2273 1.1 mrg if (tmp != charlen) 2274 1.1 mrg { 2275 1.1 mrg gfc_add_modify (&se.pre, charlen, 2276 1.1 mrg fold_convert (TREE_TYPE (charlen), tmp)); 2277 1.1 mrg gfc_add_init_cleanup (block, gfc_finish_block (&se.pre), 2278 1.1 mrg gfc_finish_block (&se.post)); 2279 1.1 mrg } 2280 1.1 mrg } 2281 1.1 mrg } 2282 1.1 mrg 2283 1.1 mrg 2284 1.1 mrg /* Translate a BLOCK construct. This is basically what we would do for a 2285 1.1 mrg procedure body. */ 2286 1.1 mrg 2287 1.1 mrg tree 2288 1.1 mrg gfc_trans_block_construct (gfc_code* code) 2289 1.1 mrg { 2290 1.1 mrg gfc_namespace* ns; 2291 1.1 mrg gfc_symbol* sym; 2292 1.1 mrg gfc_wrapped_block block; 2293 1.1 mrg tree exit_label; 2294 1.1 mrg stmtblock_t body; 2295 1.1 mrg gfc_association_list *ass; 2296 1.1 mrg 2297 1.1 mrg ns = code->ext.block.ns; 2298 1.1 mrg gcc_assert (ns); 2299 1.1 mrg sym = ns->proc_name; 2300 1.1 mrg gcc_assert (sym); 2301 1.1 mrg 2302 1.1 mrg /* Process local variables. */ 2303 1.1 mrg gcc_assert (!sym->tlink); 2304 1.1 mrg sym->tlink = sym; 2305 1.1 mrg gfc_process_block_locals (ns); 2306 1.1 mrg 2307 1.1 mrg /* Generate code including exit-label. */ 2308 1.1 mrg gfc_init_block (&body); 2309 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE); 2310 1.1 mrg code->exit_label = exit_label; 2311 1.1 mrg 2312 1.1 mrg finish_oacc_declare (ns, sym, true); 2313 1.1 mrg 2314 1.1 mrg gfc_add_expr_to_block (&body, gfc_trans_code (ns->code)); 2315 1.1 mrg gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label)); 2316 1.1 mrg 2317 1.1 mrg /* Finish everything. */ 2318 1.1 mrg gfc_start_wrapped_block (&block, gfc_finish_block (&body)); 2319 1.1 mrg gfc_trans_deferred_vars (sym, &block); 2320 1.1 mrg for (ass = code->ext.block.assoc; ass; ass = ass->next) 2321 1.1 mrg trans_associate_var (ass->st->n.sym, &block); 2322 1.1 mrg 2323 1.1 mrg return gfc_finish_wrapped_block (&block); 2324 1.1 mrg } 2325 1.1 mrg 2326 1.1 mrg /* Translate the simple DO construct in a C-style manner. 2327 1.1 mrg This is where the loop variable has integer type and step +-1. 2328 1.1 mrg Following code will generate infinite loop in case where TO is INT_MAX 2329 1.1 mrg (for +1 step) or INT_MIN (for -1 step) 2330 1.1 mrg 2331 1.1 mrg We translate a do loop from: 2332 1.1 mrg 2333 1.1 mrg DO dovar = from, to, step 2334 1.1 mrg body 2335 1.1 mrg END DO 2336 1.1 mrg 2337 1.1 mrg to: 2338 1.1 mrg 2339 1.1 mrg [Evaluate loop bounds and step] 2340 1.1 mrg dovar = from; 2341 1.1 mrg for (;;) 2342 1.1 mrg { 2343 1.1 mrg if (dovar > to) 2344 1.1 mrg goto end_label; 2345 1.1 mrg body; 2346 1.1 mrg cycle_label: 2347 1.1 mrg dovar += step; 2348 1.1 mrg } 2349 1.1 mrg end_label: 2350 1.1 mrg 2351 1.1 mrg This helps the optimizers by avoiding the extra pre-header condition and 2352 1.1 mrg we save a register as we just compare the updated IV (not a value in 2353 1.1 mrg previous step). */ 2354 1.1 mrg 2355 1.1 mrg static tree 2356 1.1 mrg gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar, 2357 1.1 mrg tree from, tree to, tree step, tree exit_cond) 2358 1.1 mrg { 2359 1.1 mrg stmtblock_t body; 2360 1.1 mrg tree type; 2361 1.1 mrg tree cond; 2362 1.1 mrg tree tmp; 2363 1.1 mrg tree saved_dovar = NULL; 2364 1.1 mrg tree cycle_label; 2365 1.1 mrg tree exit_label; 2366 1.1 mrg location_t loc; 2367 1.1 mrg type = TREE_TYPE (dovar); 2368 1.1 mrg bool is_step_positive = tree_int_cst_sgn (step) > 0; 2369 1.1 mrg 2370 1.1 mrg loc = gfc_get_location (&code->ext.iterator->start->where); 2371 1.1 mrg 2372 1.1 mrg /* Initialize the DO variable: dovar = from. */ 2373 1.1 mrg gfc_add_modify_loc (loc, pblock, dovar, 2374 1.1 mrg fold_convert (TREE_TYPE (dovar), from)); 2375 1.1 mrg 2376 1.1 mrg /* Save value for do-tinkering checking. */ 2377 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_DO) 2378 1.1 mrg { 2379 1.1 mrg saved_dovar = gfc_create_var (type, ".saved_dovar"); 2380 1.1 mrg gfc_add_modify_loc (loc, pblock, saved_dovar, dovar); 2381 1.1 mrg } 2382 1.1 mrg 2383 1.1 mrg /* Cycle and exit statements are implemented with gotos. */ 2384 1.1 mrg cycle_label = gfc_build_label_decl (NULL_TREE); 2385 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE); 2386 1.1 mrg 2387 1.1 mrg /* Put the labels where they can be found later. See gfc_trans_do(). */ 2388 1.1 mrg code->cycle_label = cycle_label; 2389 1.1 mrg code->exit_label = exit_label; 2390 1.1 mrg 2391 1.1 mrg /* Loop body. */ 2392 1.1 mrg gfc_start_block (&body); 2393 1.1 mrg 2394 1.1 mrg /* Exit the loop if there is an I/O result condition or error. */ 2395 1.1 mrg if (exit_cond) 2396 1.1 mrg { 2397 1.1 mrg tmp = build1_v (GOTO_EXPR, exit_label); 2398 1.1 mrg tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, 2399 1.1 mrg exit_cond, tmp, 2400 1.1 mrg build_empty_stmt (loc)); 2401 1.1 mrg gfc_add_expr_to_block (&body, tmp); 2402 1.1 mrg } 2403 1.1 mrg 2404 1.1 mrg /* Evaluate the loop condition. */ 2405 1.1 mrg if (is_step_positive) 2406 1.1 mrg cond = fold_build2_loc (loc, GT_EXPR, logical_type_node, dovar, 2407 1.1 mrg fold_convert (type, to)); 2408 1.1 mrg else 2409 1.1 mrg cond = fold_build2_loc (loc, LT_EXPR, logical_type_node, dovar, 2410 1.1 mrg fold_convert (type, to)); 2411 1.1 mrg 2412 1.1 mrg cond = gfc_evaluate_now_loc (loc, cond, &body); 2413 1.1 mrg if (code->ext.iterator->unroll && cond != error_mark_node) 2414 1.1 mrg cond 2415 1.1 mrg = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, 2416 1.1 mrg build_int_cst (integer_type_node, annot_expr_unroll_kind), 2417 1.1 mrg build_int_cst (integer_type_node, code->ext.iterator->unroll)); 2418 1.1 mrg 2419 1.1 mrg if (code->ext.iterator->ivdep && cond != error_mark_node) 2420 1.1 mrg cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, 2421 1.1 mrg build_int_cst (integer_type_node, annot_expr_ivdep_kind), 2422 1.1 mrg integer_zero_node); 2423 1.1 mrg if (code->ext.iterator->vector && cond != error_mark_node) 2424 1.1 mrg cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, 2425 1.1 mrg build_int_cst (integer_type_node, annot_expr_vector_kind), 2426 1.1 mrg integer_zero_node); 2427 1.1 mrg if (code->ext.iterator->novector && cond != error_mark_node) 2428 1.1 mrg cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, 2429 1.1 mrg build_int_cst (integer_type_node, annot_expr_no_vector_kind), 2430 1.1 mrg integer_zero_node); 2431 1.1 mrg 2432 1.1 mrg /* The loop exit. */ 2433 1.1 mrg tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label); 2434 1.1 mrg TREE_USED (exit_label) = 1; 2435 1.1 mrg tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, 2436 1.1 mrg cond, tmp, build_empty_stmt (loc)); 2437 1.1 mrg gfc_add_expr_to_block (&body, tmp); 2438 1.1 mrg 2439 1.1 mrg /* Check whether the induction variable is equal to INT_MAX 2440 1.1 mrg (respectively to INT_MIN). */ 2441 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_DO) 2442 1.1 mrg { 2443 1.1 mrg tree boundary = is_step_positive ? TYPE_MAX_VALUE (type) 2444 1.1 mrg : TYPE_MIN_VALUE (type); 2445 1.1 mrg 2446 1.1 mrg tmp = fold_build2_loc (loc, EQ_EXPR, logical_type_node, 2447 1.1 mrg dovar, boundary); 2448 1.1 mrg gfc_trans_runtime_check (true, false, tmp, &body, &code->loc, 2449 1.1 mrg "Loop iterates infinitely"); 2450 1.1 mrg } 2451 1.1 mrg 2452 1.1 mrg /* Main loop body. */ 2453 1.1 mrg tmp = gfc_trans_code_cond (code->block->next, exit_cond); 2454 1.1 mrg gfc_add_expr_to_block (&body, tmp); 2455 1.1 mrg 2456 1.1 mrg /* Label for cycle statements (if needed). */ 2457 1.1 mrg if (TREE_USED (cycle_label)) 2458 1.1 mrg { 2459 1.1 mrg tmp = build1_v (LABEL_EXPR, cycle_label); 2460 1.1 mrg gfc_add_expr_to_block (&body, tmp); 2461 1.1 mrg } 2462 1.1 mrg 2463 1.1 mrg /* Check whether someone has modified the loop variable. */ 2464 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_DO) 2465 1.1 mrg { 2466 1.1 mrg tmp = fold_build2_loc (loc, NE_EXPR, logical_type_node, 2467 1.1 mrg dovar, saved_dovar); 2468 1.1 mrg gfc_trans_runtime_check (true, false, tmp, &body, &code->loc, 2469 1.1 mrg "Loop variable has been modified"); 2470 1.1 mrg } 2471 1.1 mrg 2472 1.1 mrg /* Increment the loop variable. */ 2473 1.1 mrg tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step); 2474 1.1 mrg gfc_add_modify_loc (loc, &body, dovar, tmp); 2475 1.1 mrg 2476 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_DO) 2477 1.1 mrg gfc_add_modify_loc (loc, &body, saved_dovar, dovar); 2478 1.1 mrg 2479 1.1 mrg /* Finish the loop body. */ 2480 1.1 mrg tmp = gfc_finish_block (&body); 2481 1.1 mrg tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp); 2482 1.1 mrg 2483 1.1 mrg gfc_add_expr_to_block (pblock, tmp); 2484 1.1 mrg 2485 1.1 mrg /* Add the exit label. */ 2486 1.1 mrg tmp = build1_v (LABEL_EXPR, exit_label); 2487 1.1 mrg gfc_add_expr_to_block (pblock, tmp); 2488 1.1 mrg 2489 1.1 mrg return gfc_finish_block (pblock); 2490 1.1 mrg } 2491 1.1 mrg 2492 1.1 mrg /* Translate the DO construct. This obviously is one of the most 2493 1.1 mrg important ones to get right with any compiler, but especially 2494 1.1 mrg so for Fortran. 2495 1.1 mrg 2496 1.1 mrg We special case some loop forms as described in gfc_trans_simple_do. 2497 1.1 mrg For other cases we implement them with a separate loop count, 2498 1.1 mrg as described in the standard. 2499 1.1 mrg 2500 1.1 mrg We translate a do loop from: 2501 1.1 mrg 2502 1.1 mrg DO dovar = from, to, step 2503 1.1 mrg body 2504 1.1 mrg END DO 2505 1.1 mrg 2506 1.1 mrg to: 2507 1.1 mrg 2508 1.1 mrg [evaluate loop bounds and step] 2509 1.1 mrg empty = (step > 0 ? to < from : to > from); 2510 1.1 mrg countm1 = (to - from) / step; 2511 1.1 mrg dovar = from; 2512 1.1 mrg if (empty) goto exit_label; 2513 1.1 mrg for (;;) 2514 1.1 mrg { 2515 1.1 mrg body; 2516 1.1 mrg cycle_label: 2517 1.1 mrg dovar += step 2518 1.1 mrg countm1t = countm1; 2519 1.1 mrg countm1--; 2520 1.1 mrg if (countm1t == 0) goto exit_label; 2521 1.1 mrg } 2522 1.1 mrg exit_label: 2523 1.1 mrg 2524 1.1 mrg countm1 is an unsigned integer. It is equal to the loop count minus one, 2525 1.1 mrg because the loop count itself can overflow. */ 2526 1.1 mrg 2527 1.1 mrg tree 2528 1.1 mrg gfc_trans_do (gfc_code * code, tree exit_cond) 2529 1.1 mrg { 2530 1.1 mrg gfc_se se; 2531 1.1 mrg tree dovar; 2532 1.1 mrg tree saved_dovar = NULL; 2533 1.1 mrg tree from; 2534 1.1 mrg tree to; 2535 1.1 mrg tree step; 2536 1.1 mrg tree countm1; 2537 1.1 mrg tree type; 2538 1.1 mrg tree utype; 2539 1.1 mrg tree cond; 2540 1.1 mrg tree cycle_label; 2541 1.1 mrg tree exit_label; 2542 1.1 mrg tree tmp; 2543 1.1 mrg stmtblock_t block; 2544 1.1 mrg stmtblock_t body; 2545 1.1 mrg location_t loc; 2546 1.1 mrg 2547 1.1 mrg gfc_start_block (&block); 2548 1.1 mrg 2549 1.1 mrg loc = gfc_get_location (&code->ext.iterator->start->where); 2550 1.1 mrg 2551 1.1 mrg /* Evaluate all the expressions in the iterator. */ 2552 1.1 mrg gfc_init_se (&se, NULL); 2553 1.1 mrg gfc_conv_expr_lhs (&se, code->ext.iterator->var); 2554 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 2555 1.1 mrg dovar = se.expr; 2556 1.1 mrg type = TREE_TYPE (dovar); 2557 1.1 mrg 2558 1.1 mrg gfc_init_se (&se, NULL); 2559 1.1 mrg gfc_conv_expr_val (&se, code->ext.iterator->start); 2560 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 2561 1.1 mrg from = gfc_evaluate_now (se.expr, &block); 2562 1.1 mrg 2563 1.1 mrg gfc_init_se (&se, NULL); 2564 1.1 mrg gfc_conv_expr_val (&se, code->ext.iterator->end); 2565 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 2566 1.1 mrg to = gfc_evaluate_now (se.expr, &block); 2567 1.1 mrg 2568 1.1 mrg gfc_init_se (&se, NULL); 2569 1.1 mrg gfc_conv_expr_val (&se, code->ext.iterator->step); 2570 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 2571 1.1 mrg step = gfc_evaluate_now (se.expr, &block); 2572 1.1 mrg 2573 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_DO) 2574 1.1 mrg { 2575 1.1 mrg tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, step, 2576 1.1 mrg build_zero_cst (type)); 2577 1.1 mrg gfc_trans_runtime_check (true, false, tmp, &block, &code->loc, 2578 1.1 mrg "DO step value is zero"); 2579 1.1 mrg } 2580 1.1 mrg 2581 1.1 mrg /* Special case simple loops. */ 2582 1.1 mrg if (TREE_CODE (type) == INTEGER_TYPE 2583 1.1 mrg && (integer_onep (step) 2584 1.1 mrg || tree_int_cst_equal (step, integer_minus_one_node))) 2585 1.1 mrg return gfc_trans_simple_do (code, &block, dovar, from, to, step, 2586 1.1 mrg exit_cond); 2587 1.1 mrg 2588 1.1 mrg if (TREE_CODE (type) == INTEGER_TYPE) 2589 1.1 mrg utype = unsigned_type_for (type); 2590 1.1 mrg else 2591 1.1 mrg utype = unsigned_type_for (gfc_array_index_type); 2592 1.1 mrg countm1 = gfc_create_var (utype, "countm1"); 2593 1.1 mrg 2594 1.1 mrg /* Cycle and exit statements are implemented with gotos. */ 2595 1.1 mrg cycle_label = gfc_build_label_decl (NULL_TREE); 2596 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE); 2597 1.1 mrg TREE_USED (exit_label) = 1; 2598 1.1 mrg 2599 1.1 mrg /* Put these labels where they can be found later. */ 2600 1.1 mrg code->cycle_label = cycle_label; 2601 1.1 mrg code->exit_label = exit_label; 2602 1.1 mrg 2603 1.1 mrg /* Initialize the DO variable: dovar = from. */ 2604 1.1 mrg gfc_add_modify (&block, dovar, from); 2605 1.1 mrg 2606 1.1 mrg /* Save value for do-tinkering checking. */ 2607 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_DO) 2608 1.1 mrg { 2609 1.1 mrg saved_dovar = gfc_create_var (type, ".saved_dovar"); 2610 1.1 mrg gfc_add_modify_loc (loc, &block, saved_dovar, dovar); 2611 1.1 mrg } 2612 1.1 mrg 2613 1.1 mrg /* Initialize loop count and jump to exit label if the loop is empty. 2614 1.1 mrg This code is executed before we enter the loop body. We generate: 2615 1.1 mrg if (step > 0) 2616 1.1 mrg { 2617 1.1 mrg countm1 = (to - from) / step; 2618 1.1 mrg if (to < from) 2619 1.1 mrg goto exit_label; 2620 1.1 mrg } 2621 1.1 mrg else 2622 1.1 mrg { 2623 1.1 mrg countm1 = (from - to) / -step; 2624 1.1 mrg if (to > from) 2625 1.1 mrg goto exit_label; 2626 1.1 mrg } 2627 1.1 mrg */ 2628 1.1 mrg 2629 1.1 mrg if (TREE_CODE (type) == INTEGER_TYPE) 2630 1.1 mrg { 2631 1.1 mrg tree pos, neg, tou, fromu, stepu, tmp2; 2632 1.1 mrg 2633 1.1 mrg /* The distance from FROM to TO cannot always be represented in a signed 2634 1.1 mrg type, thus use unsigned arithmetic, also to avoid any undefined 2635 1.1 mrg overflow issues. */ 2636 1.1 mrg tou = fold_convert (utype, to); 2637 1.1 mrg fromu = fold_convert (utype, from); 2638 1.1 mrg stepu = fold_convert (utype, step); 2639 1.1 mrg 2640 1.1 mrg /* For a positive step, when to < from, exit, otherwise compute 2641 1.1 mrg countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */ 2642 1.1 mrg tmp = fold_build2_loc (loc, LT_EXPR, logical_type_node, to, from); 2643 1.1 mrg tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype, 2644 1.1 mrg fold_build2_loc (loc, MINUS_EXPR, utype, 2645 1.1 mrg tou, fromu), 2646 1.1 mrg stepu); 2647 1.1 mrg pos = build2 (COMPOUND_EXPR, void_type_node, 2648 1.1 mrg fold_build2 (MODIFY_EXPR, void_type_node, 2649 1.1 mrg countm1, tmp2), 2650 1.1 mrg build3_loc (loc, COND_EXPR, void_type_node, 2651 1.1 mrg gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER), 2652 1.1 mrg build1_loc (loc, GOTO_EXPR, void_type_node, 2653 1.1 mrg exit_label), NULL_TREE)); 2654 1.1 mrg 2655 1.1 mrg /* For a negative step, when to > from, exit, otherwise compute 2656 1.1 mrg countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */ 2657 1.1 mrg tmp = fold_build2_loc (loc, GT_EXPR, logical_type_node, to, from); 2658 1.1 mrg tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype, 2659 1.1 mrg fold_build2_loc (loc, MINUS_EXPR, utype, 2660 1.1 mrg fromu, tou), 2661 1.1 mrg fold_build1_loc (loc, NEGATE_EXPR, utype, stepu)); 2662 1.1 mrg neg = build2 (COMPOUND_EXPR, void_type_node, 2663 1.1 mrg fold_build2 (MODIFY_EXPR, void_type_node, 2664 1.1 mrg countm1, tmp2), 2665 1.1 mrg build3_loc (loc, COND_EXPR, void_type_node, 2666 1.1 mrg gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER), 2667 1.1 mrg build1_loc (loc, GOTO_EXPR, void_type_node, 2668 1.1 mrg exit_label), NULL_TREE)); 2669 1.1 mrg 2670 1.1 mrg tmp = fold_build2_loc (loc, LT_EXPR, logical_type_node, step, 2671 1.1 mrg build_int_cst (TREE_TYPE (step), 0)); 2672 1.1 mrg tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos); 2673 1.1 mrg 2674 1.1 mrg gfc_add_expr_to_block (&block, tmp); 2675 1.1 mrg } 2676 1.1 mrg else 2677 1.1 mrg { 2678 1.1 mrg tree pos_step; 2679 1.1 mrg 2680 1.1 mrg /* TODO: We could use the same width as the real type. 2681 1.1 mrg This would probably cause more problems that it solves 2682 1.1 mrg when we implement "long double" types. */ 2683 1.1 mrg 2684 1.1 mrg tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from); 2685 1.1 mrg tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step); 2686 1.1 mrg tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp); 2687 1.1 mrg gfc_add_modify (&block, countm1, tmp); 2688 1.1 mrg 2689 1.1 mrg /* We need a special check for empty loops: 2690 1.1 mrg empty = (step > 0 ? to < from : to > from); */ 2691 1.1 mrg pos_step = fold_build2_loc (loc, GT_EXPR, logical_type_node, step, 2692 1.1 mrg build_zero_cst (type)); 2693 1.1 mrg tmp = fold_build3_loc (loc, COND_EXPR, logical_type_node, pos_step, 2694 1.1 mrg fold_build2_loc (loc, LT_EXPR, 2695 1.1 mrg logical_type_node, to, from), 2696 1.1 mrg fold_build2_loc (loc, GT_EXPR, 2697 1.1 mrg logical_type_node, to, from)); 2698 1.1 mrg /* If the loop is empty, go directly to the exit label. */ 2699 1.1 mrg tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, 2700 1.1 mrg build1_v (GOTO_EXPR, exit_label), 2701 1.1 mrg build_empty_stmt (input_location)); 2702 1.1 mrg gfc_add_expr_to_block (&block, tmp); 2703 1.1 mrg } 2704 1.1 mrg 2705 1.1 mrg /* Loop body. */ 2706 1.1 mrg gfc_start_block (&body); 2707 1.1 mrg 2708 1.1 mrg /* Main loop body. */ 2709 1.1 mrg tmp = gfc_trans_code_cond (code->block->next, exit_cond); 2710 1.1 mrg gfc_add_expr_to_block (&body, tmp); 2711 1.1 mrg 2712 1.1 mrg /* Label for cycle statements (if needed). */ 2713 1.1 mrg if (TREE_USED (cycle_label)) 2714 1.1 mrg { 2715 1.1 mrg tmp = build1_v (LABEL_EXPR, cycle_label); 2716 1.1 mrg gfc_add_expr_to_block (&body, tmp); 2717 1.1 mrg } 2718 1.1 mrg 2719 1.1 mrg /* Check whether someone has modified the loop variable. */ 2720 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_DO) 2721 1.1 mrg { 2722 1.1 mrg tmp = fold_build2_loc (loc, NE_EXPR, logical_type_node, dovar, 2723 1.1 mrg saved_dovar); 2724 1.1 mrg gfc_trans_runtime_check (true, false, tmp, &body, &code->loc, 2725 1.1 mrg "Loop variable has been modified"); 2726 1.1 mrg } 2727 1.1 mrg 2728 1.1 mrg /* Exit the loop if there is an I/O result condition or error. */ 2729 1.1 mrg if (exit_cond) 2730 1.1 mrg { 2731 1.1 mrg tmp = build1_v (GOTO_EXPR, exit_label); 2732 1.1 mrg tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, 2733 1.1 mrg exit_cond, tmp, 2734 1.1 mrg build_empty_stmt (input_location)); 2735 1.1 mrg gfc_add_expr_to_block (&body, tmp); 2736 1.1 mrg } 2737 1.1 mrg 2738 1.1 mrg /* Increment the loop variable. */ 2739 1.1 mrg tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step); 2740 1.1 mrg gfc_add_modify_loc (loc, &body, dovar, tmp); 2741 1.1 mrg 2742 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_DO) 2743 1.1 mrg gfc_add_modify_loc (loc, &body, saved_dovar, dovar); 2744 1.1 mrg 2745 1.1 mrg /* Initialize countm1t. */ 2746 1.1 mrg tree countm1t = gfc_create_var (utype, "countm1t"); 2747 1.1 mrg gfc_add_modify_loc (loc, &body, countm1t, countm1); 2748 1.1 mrg 2749 1.1 mrg /* Decrement the loop count. */ 2750 1.1 mrg tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1, 2751 1.1 mrg build_int_cst (utype, 1)); 2752 1.1 mrg gfc_add_modify_loc (loc, &body, countm1, tmp); 2753 1.1 mrg 2754 1.1 mrg /* End with the loop condition. Loop until countm1t == 0. */ 2755 1.1 mrg cond = fold_build2_loc (loc, EQ_EXPR, logical_type_node, countm1t, 2756 1.1 mrg build_int_cst (utype, 0)); 2757 1.1 mrg if (code->ext.iterator->unroll && cond != error_mark_node) 2758 1.1 mrg cond 2759 1.1 mrg = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, 2760 1.1 mrg build_int_cst (integer_type_node, annot_expr_unroll_kind), 2761 1.1 mrg build_int_cst (integer_type_node, code->ext.iterator->unroll)); 2762 1.1 mrg 2763 1.1 mrg if (code->ext.iterator->ivdep && cond != error_mark_node) 2764 1.1 mrg cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, 2765 1.1 mrg build_int_cst (integer_type_node, annot_expr_ivdep_kind), 2766 1.1 mrg integer_zero_node); 2767 1.1 mrg if (code->ext.iterator->vector && cond != error_mark_node) 2768 1.1 mrg cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, 2769 1.1 mrg build_int_cst (integer_type_node, annot_expr_vector_kind), 2770 1.1 mrg integer_zero_node); 2771 1.1 mrg if (code->ext.iterator->novector && cond != error_mark_node) 2772 1.1 mrg cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, 2773 1.1 mrg build_int_cst (integer_type_node, annot_expr_no_vector_kind), 2774 1.1 mrg integer_zero_node); 2775 1.1 mrg 2776 1.1 mrg tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label); 2777 1.1 mrg tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, 2778 1.1 mrg cond, tmp, build_empty_stmt (loc)); 2779 1.1 mrg gfc_add_expr_to_block (&body, tmp); 2780 1.1 mrg 2781 1.1 mrg /* End of loop body. */ 2782 1.1 mrg tmp = gfc_finish_block (&body); 2783 1.1 mrg 2784 1.1 mrg /* The for loop itself. */ 2785 1.1 mrg tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp); 2786 1.1 mrg gfc_add_expr_to_block (&block, tmp); 2787 1.1 mrg 2788 1.1 mrg /* Add the exit label. */ 2789 1.1 mrg tmp = build1_v (LABEL_EXPR, exit_label); 2790 1.1 mrg gfc_add_expr_to_block (&block, tmp); 2791 1.1 mrg 2792 1.1 mrg return gfc_finish_block (&block); 2793 1.1 mrg } 2794 1.1 mrg 2795 1.1 mrg 2796 1.1 mrg /* Translate the DO WHILE construct. 2797 1.1 mrg 2798 1.1 mrg We translate 2799 1.1 mrg 2800 1.1 mrg DO WHILE (cond) 2801 1.1 mrg body 2802 1.1 mrg END DO 2803 1.1 mrg 2804 1.1 mrg to: 2805 1.1 mrg 2806 1.1 mrg for ( ; ; ) 2807 1.1 mrg { 2808 1.1 mrg pre_cond; 2809 1.1 mrg if (! cond) goto exit_label; 2810 1.1 mrg body; 2811 1.1 mrg cycle_label: 2812 1.1 mrg } 2813 1.1 mrg exit_label: 2814 1.1 mrg 2815 1.1 mrg Because the evaluation of the exit condition `cond' may have side 2816 1.1 mrg effects, we can't do much for empty loop bodies. The backend optimizers 2817 1.1 mrg should be smart enough to eliminate any dead loops. */ 2818 1.1 mrg 2819 1.1 mrg tree 2820 1.1 mrg gfc_trans_do_while (gfc_code * code) 2821 1.1 mrg { 2822 1.1 mrg gfc_se cond; 2823 1.1 mrg tree tmp; 2824 1.1 mrg tree cycle_label; 2825 1.1 mrg tree exit_label; 2826 1.1 mrg stmtblock_t block; 2827 1.1 mrg 2828 1.1 mrg /* Everything we build here is part of the loop body. */ 2829 1.1 mrg gfc_start_block (&block); 2830 1.1 mrg 2831 1.1 mrg /* Cycle and exit statements are implemented with gotos. */ 2832 1.1 mrg cycle_label = gfc_build_label_decl (NULL_TREE); 2833 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE); 2834 1.1 mrg 2835 1.1 mrg /* Put the labels where they can be found later. See gfc_trans_do(). */ 2836 1.1 mrg code->cycle_label = cycle_label; 2837 1.1 mrg code->exit_label = exit_label; 2838 1.1 mrg 2839 1.1 mrg /* Create a GIMPLE version of the exit condition. */ 2840 1.1 mrg gfc_init_se (&cond, NULL); 2841 1.1 mrg gfc_conv_expr_val (&cond, code->expr1); 2842 1.1 mrg gfc_add_block_to_block (&block, &cond.pre); 2843 1.1 mrg cond.expr = fold_build1_loc (gfc_get_location (&code->expr1->where), 2844 1.1 mrg TRUTH_NOT_EXPR, TREE_TYPE (cond.expr), 2845 1.1 mrg cond.expr); 2846 1.1 mrg 2847 1.1 mrg /* Build "IF (! cond) GOTO exit_label". */ 2848 1.1 mrg tmp = build1_v (GOTO_EXPR, exit_label); 2849 1.1 mrg TREE_USED (exit_label) = 1; 2850 1.1 mrg tmp = fold_build3_loc (gfc_get_location (&code->expr1->where), COND_EXPR, 2851 1.1 mrg void_type_node, cond.expr, tmp, 2852 1.1 mrg build_empty_stmt (gfc_get_location ( 2853 1.1 mrg &code->expr1->where))); 2854 1.1 mrg gfc_add_expr_to_block (&block, tmp); 2855 1.1 mrg 2856 1.1 mrg /* The main body of the loop. */ 2857 1.1 mrg tmp = gfc_trans_code (code->block->next); 2858 1.1 mrg gfc_add_expr_to_block (&block, tmp); 2859 1.1 mrg 2860 1.1 mrg /* Label for cycle statements (if needed). */ 2861 1.1 mrg if (TREE_USED (cycle_label)) 2862 1.1 mrg { 2863 1.1 mrg tmp = build1_v (LABEL_EXPR, cycle_label); 2864 1.1 mrg gfc_add_expr_to_block (&block, tmp); 2865 1.1 mrg } 2866 1.1 mrg 2867 1.1 mrg /* End of loop body. */ 2868 1.1 mrg tmp = gfc_finish_block (&block); 2869 1.1 mrg 2870 1.1 mrg gfc_init_block (&block); 2871 1.1 mrg /* Build the loop. */ 2872 1.1 mrg tmp = fold_build1_loc (gfc_get_location (&code->expr1->where), LOOP_EXPR, 2873 1.1 mrg void_type_node, tmp); 2874 1.1 mrg gfc_add_expr_to_block (&block, tmp); 2875 1.1 mrg 2876 1.1 mrg /* Add the exit label. */ 2877 1.1 mrg tmp = build1_v (LABEL_EXPR, exit_label); 2878 1.1 mrg gfc_add_expr_to_block (&block, tmp); 2879 1.1 mrg 2880 1.1 mrg return gfc_finish_block (&block); 2881 1.1 mrg } 2882 1.1 mrg 2883 1.1 mrg 2884 1.1 mrg /* Deal with the particular case of SELECT_TYPE, where the vtable 2885 1.1 mrg addresses are used for the selection. Since these are not sorted, 2886 1.1 mrg the selection has to be made by a series of if statements. */ 2887 1.1 mrg 2888 1.1 mrg static tree 2889 1.1 mrg gfc_trans_select_type_cases (gfc_code * code) 2890 1.1 mrg { 2891 1.1 mrg gfc_code *c; 2892 1.1 mrg gfc_case *cp; 2893 1.1 mrg tree tmp; 2894 1.1 mrg tree cond; 2895 1.1 mrg tree low; 2896 1.1 mrg tree high; 2897 1.1 mrg gfc_se se; 2898 1.1 mrg gfc_se cse; 2899 1.1 mrg stmtblock_t block; 2900 1.1 mrg stmtblock_t body; 2901 1.1 mrg bool def = false; 2902 1.1 mrg gfc_expr *e; 2903 1.1 mrg gfc_start_block (&block); 2904 1.1 mrg 2905 1.1 mrg /* Calculate the switch expression. */ 2906 1.1 mrg gfc_init_se (&se, NULL); 2907 1.1 mrg gfc_conv_expr_val (&se, code->expr1); 2908 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 2909 1.1 mrg 2910 1.1 mrg /* Generate an expression for the selector hash value, for 2911 1.1 mrg use to resolve character cases. */ 2912 1.1 mrg e = gfc_copy_expr (code->expr1->value.function.actual->expr); 2913 1.1 mrg gfc_add_hash_component (e); 2914 1.1 mrg 2915 1.1 mrg TREE_USED (code->exit_label) = 0; 2916 1.1 mrg 2917 1.1 mrg repeat: 2918 1.1 mrg for (c = code->block; c; c = c->block) 2919 1.1 mrg { 2920 1.1 mrg cp = c->ext.block.case_list; 2921 1.1 mrg 2922 1.1 mrg /* Assume it's the default case. */ 2923 1.1 mrg low = NULL_TREE; 2924 1.1 mrg high = NULL_TREE; 2925 1.1 mrg tmp = NULL_TREE; 2926 1.1 mrg 2927 1.1 mrg /* Put the default case at the end. */ 2928 1.1 mrg if ((!def && !cp->low) || (def && cp->low)) 2929 1.1 mrg continue; 2930 1.1 mrg 2931 1.1 mrg if (cp->low && (cp->ts.type == BT_CLASS 2932 1.1 mrg || cp->ts.type == BT_DERIVED)) 2933 1.1 mrg { 2934 1.1 mrg gfc_init_se (&cse, NULL); 2935 1.1 mrg gfc_conv_expr_val (&cse, cp->low); 2936 1.1 mrg gfc_add_block_to_block (&block, &cse.pre); 2937 1.1 mrg low = cse.expr; 2938 1.1 mrg } 2939 1.1 mrg else if (cp->ts.type != BT_UNKNOWN) 2940 1.1 mrg { 2941 1.1 mrg gcc_assert (cp->high); 2942 1.1 mrg gfc_init_se (&cse, NULL); 2943 1.1 mrg gfc_conv_expr_val (&cse, cp->high); 2944 1.1 mrg gfc_add_block_to_block (&block, &cse.pre); 2945 1.1 mrg high = cse.expr; 2946 1.1 mrg } 2947 1.1 mrg 2948 1.1 mrg gfc_init_block (&body); 2949 1.1 mrg 2950 1.1 mrg /* Add the statements for this case. */ 2951 1.1 mrg tmp = gfc_trans_code (c->next); 2952 1.1 mrg gfc_add_expr_to_block (&body, tmp); 2953 1.1 mrg 2954 1.1 mrg /* Break to the end of the SELECT TYPE construct. The default 2955 1.1 mrg case just falls through. */ 2956 1.1 mrg if (!def) 2957 1.1 mrg { 2958 1.1 mrg TREE_USED (code->exit_label) = 1; 2959 1.1 mrg tmp = build1_v (GOTO_EXPR, code->exit_label); 2960 1.1 mrg gfc_add_expr_to_block (&body, tmp); 2961 1.1 mrg } 2962 1.1 mrg 2963 1.1 mrg tmp = gfc_finish_block (&body); 2964 1.1 mrg 2965 1.1 mrg if (low != NULL_TREE) 2966 1.1 mrg { 2967 1.1 mrg /* Compare vtable pointers. */ 2968 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, 2969 1.1 mrg TREE_TYPE (se.expr), se.expr, low); 2970 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, 2971 1.1 mrg cond, tmp, 2972 1.1 mrg build_empty_stmt (input_location)); 2973 1.1 mrg } 2974 1.1 mrg else if (high != NULL_TREE) 2975 1.1 mrg { 2976 1.1 mrg /* Compare hash values for character cases. */ 2977 1.1 mrg gfc_init_se (&cse, NULL); 2978 1.1 mrg gfc_conv_expr_val (&cse, e); 2979 1.1 mrg gfc_add_block_to_block (&block, &cse.pre); 2980 1.1 mrg 2981 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, 2982 1.1 mrg TREE_TYPE (se.expr), high, cse.expr); 2983 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, 2984 1.1 mrg cond, tmp, 2985 1.1 mrg build_empty_stmt (input_location)); 2986 1.1 mrg } 2987 1.1 mrg 2988 1.1 mrg gfc_add_expr_to_block (&block, tmp); 2989 1.1 mrg } 2990 1.1 mrg 2991 1.1 mrg if (!def) 2992 1.1 mrg { 2993 1.1 mrg def = true; 2994 1.1 mrg goto repeat; 2995 1.1 mrg } 2996 1.1 mrg 2997 1.1 mrg gfc_free_expr (e); 2998 1.1 mrg 2999 1.1 mrg return gfc_finish_block (&block); 3000 1.1 mrg } 3001 1.1 mrg 3002 1.1 mrg 3003 1.1 mrg /* Translate the SELECT CASE construct for INTEGER case expressions, 3004 1.1 mrg without killing all potential optimizations. The problem is that 3005 1.1 mrg Fortran allows unbounded cases, but the back-end does not, so we 3006 1.1 mrg need to intercept those before we enter the equivalent SWITCH_EXPR 3007 1.1 mrg we can build. 3008 1.1 mrg 3009 1.1 mrg For example, we translate this, 3010 1.1 mrg 3011 1.1 mrg SELECT CASE (expr) 3012 1.1 mrg CASE (:100,101,105:115) 3013 1.1 mrg block_1 3014 1.1 mrg CASE (190:199,200:) 3015 1.1 mrg block_2 3016 1.1 mrg CASE (300) 3017 1.1 mrg block_3 3018 1.1 mrg CASE DEFAULT 3019 1.1 mrg block_4 3020 1.1 mrg END SELECT 3021 1.1 mrg 3022 1.1 mrg to the GENERIC equivalent, 3023 1.1 mrg 3024 1.1 mrg switch (expr) 3025 1.1 mrg { 3026 1.1 mrg case (minimum value for typeof(expr) ... 100: 3027 1.1 mrg case 101: 3028 1.1 mrg case 105 ... 114: 3029 1.1 mrg block1: 3030 1.1 mrg goto end_label; 3031 1.1 mrg 3032 1.1 mrg case 200 ... (maximum value for typeof(expr): 3033 1.1 mrg case 190 ... 199: 3034 1.1 mrg block2; 3035 1.1 mrg goto end_label; 3036 1.1 mrg 3037 1.1 mrg case 300: 3038 1.1 mrg block_3; 3039 1.1 mrg goto end_label; 3040 1.1 mrg 3041 1.1 mrg default: 3042 1.1 mrg block_4; 3043 1.1 mrg goto end_label; 3044 1.1 mrg } 3045 1.1 mrg 3046 1.1 mrg end_label: */ 3047 1.1 mrg 3048 1.1 mrg static tree 3049 1.1 mrg gfc_trans_integer_select (gfc_code * code) 3050 1.1 mrg { 3051 1.1 mrg gfc_code *c; 3052 1.1 mrg gfc_case *cp; 3053 1.1 mrg tree end_label; 3054 1.1 mrg tree tmp; 3055 1.1 mrg gfc_se se; 3056 1.1 mrg stmtblock_t block; 3057 1.1 mrg stmtblock_t body; 3058 1.1 mrg 3059 1.1 mrg gfc_start_block (&block); 3060 1.1 mrg 3061 1.1 mrg /* Calculate the switch expression. */ 3062 1.1 mrg gfc_init_se (&se, NULL); 3063 1.1 mrg gfc_conv_expr_val (&se, code->expr1); 3064 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 3065 1.1 mrg 3066 1.1 mrg end_label = gfc_build_label_decl (NULL_TREE); 3067 1.1 mrg 3068 1.1 mrg gfc_init_block (&body); 3069 1.1 mrg 3070 1.1 mrg for (c = code->block; c; c = c->block) 3071 1.1 mrg { 3072 1.1 mrg for (cp = c->ext.block.case_list; cp; cp = cp->next) 3073 1.1 mrg { 3074 1.1 mrg tree low, high; 3075 1.1 mrg tree label; 3076 1.1 mrg 3077 1.1 mrg /* Assume it's the default case. */ 3078 1.1 mrg low = high = NULL_TREE; 3079 1.1 mrg 3080 1.1 mrg if (cp->low) 3081 1.1 mrg { 3082 1.1 mrg low = gfc_conv_mpz_to_tree (cp->low->value.integer, 3083 1.1 mrg cp->low->ts.kind); 3084 1.1 mrg 3085 1.1 mrg /* If there's only a lower bound, set the high bound to the 3086 1.1 mrg maximum value of the case expression. */ 3087 1.1 mrg if (!cp->high) 3088 1.1 mrg high = TYPE_MAX_VALUE (TREE_TYPE (se.expr)); 3089 1.1 mrg } 3090 1.1 mrg 3091 1.1 mrg if (cp->high) 3092 1.1 mrg { 3093 1.1 mrg /* Three cases are possible here: 3094 1.1 mrg 3095 1.1 mrg 1) There is no lower bound, e.g. CASE (:N). 3096 1.1 mrg 2) There is a lower bound .NE. high bound, that is 3097 1.1 mrg a case range, e.g. CASE (N:M) where M>N (we make 3098 1.1 mrg sure that M>N during type resolution). 3099 1.1 mrg 3) There is a lower bound, and it has the same value 3100 1.1 mrg as the high bound, e.g. CASE (N:N). This is our 3101 1.1 mrg internal representation of CASE(N). 3102 1.1 mrg 3103 1.1 mrg In the first and second case, we need to set a value for 3104 1.1 mrg high. In the third case, we don't because the GCC middle 3105 1.1 mrg end represents a single case value by just letting high be 3106 1.1 mrg a NULL_TREE. We can't do that because we need to be able 3107 1.1 mrg to represent unbounded cases. */ 3108 1.1 mrg 3109 1.1 mrg if (!cp->low 3110 1.1 mrg || (mpz_cmp (cp->low->value.integer, 3111 1.1 mrg cp->high->value.integer) != 0)) 3112 1.1 mrg high = gfc_conv_mpz_to_tree (cp->high->value.integer, 3113 1.1 mrg cp->high->ts.kind); 3114 1.1 mrg 3115 1.1 mrg /* Unbounded case. */ 3116 1.1 mrg if (!cp->low) 3117 1.1 mrg low = TYPE_MIN_VALUE (TREE_TYPE (se.expr)); 3118 1.1 mrg } 3119 1.1 mrg 3120 1.1 mrg /* Build a label. */ 3121 1.1 mrg label = gfc_build_label_decl (NULL_TREE); 3122 1.1 mrg 3123 1.1 mrg /* Add this case label. 3124 1.1 mrg Add parameter 'label', make it match GCC backend. */ 3125 1.1 mrg tmp = build_case_label (low, high, label); 3126 1.1 mrg gfc_add_expr_to_block (&body, tmp); 3127 1.1 mrg } 3128 1.1 mrg 3129 1.1 mrg /* Add the statements for this case. */ 3130 1.1 mrg tmp = gfc_trans_code (c->next); 3131 1.1 mrg gfc_add_expr_to_block (&body, tmp); 3132 1.1 mrg 3133 1.1 mrg /* Break to the end of the construct. */ 3134 1.1 mrg tmp = build1_v (GOTO_EXPR, end_label); 3135 1.1 mrg gfc_add_expr_to_block (&body, tmp); 3136 1.1 mrg } 3137 1.1 mrg 3138 1.1 mrg tmp = gfc_finish_block (&body); 3139 1.1 mrg tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, se.expr, tmp); 3140 1.1 mrg gfc_add_expr_to_block (&block, tmp); 3141 1.1 mrg 3142 1.1 mrg tmp = build1_v (LABEL_EXPR, end_label); 3143 1.1 mrg gfc_add_expr_to_block (&block, tmp); 3144 1.1 mrg 3145 1.1 mrg return gfc_finish_block (&block); 3146 1.1 mrg } 3147 1.1 mrg 3148 1.1 mrg 3149 1.1 mrg /* Translate the SELECT CASE construct for LOGICAL case expressions. 3150 1.1 mrg 3151 1.1 mrg There are only two cases possible here, even though the standard 3152 1.1 mrg does allow three cases in a LOGICAL SELECT CASE construct: .TRUE., 3153 1.1 mrg .FALSE., and DEFAULT. 3154 1.1 mrg 3155 1.1 mrg We never generate more than two blocks here. Instead, we always 3156 1.1 mrg try to eliminate the DEFAULT case. This way, we can translate this 3157 1.1 mrg kind of SELECT construct to a simple 3158 1.1 mrg 3159 1.1 mrg if {} else {}; 3160 1.1 mrg 3161 1.1 mrg expression in GENERIC. */ 3162 1.1 mrg 3163 1.1 mrg static tree 3164 1.1 mrg gfc_trans_logical_select (gfc_code * code) 3165 1.1 mrg { 3166 1.1 mrg gfc_code *c; 3167 1.1 mrg gfc_code *t, *f, *d; 3168 1.1 mrg gfc_case *cp; 3169 1.1 mrg gfc_se se; 3170 1.1 mrg stmtblock_t block; 3171 1.1 mrg 3172 1.1 mrg /* Assume we don't have any cases at all. */ 3173 1.1 mrg t = f = d = NULL; 3174 1.1 mrg 3175 1.1 mrg /* Now see which ones we actually do have. We can have at most two 3176 1.1 mrg cases in a single case list: one for .TRUE. and one for .FALSE. 3177 1.1 mrg The default case is always separate. If the cases for .TRUE. and 3178 1.1 mrg .FALSE. are in the same case list, the block for that case list 3179 1.1 mrg always executed, and we don't generate code a COND_EXPR. */ 3180 1.1 mrg for (c = code->block; c; c = c->block) 3181 1.1 mrg { 3182 1.1 mrg for (cp = c->ext.block.case_list; cp; cp = cp->next) 3183 1.1 mrg { 3184 1.1 mrg if (cp->low) 3185 1.1 mrg { 3186 1.1 mrg if (cp->low->value.logical == 0) /* .FALSE. */ 3187 1.1 mrg f = c; 3188 1.1 mrg else /* if (cp->value.logical != 0), thus .TRUE. */ 3189 1.1 mrg t = c; 3190 1.1 mrg } 3191 1.1 mrg else 3192 1.1 mrg d = c; 3193 1.1 mrg } 3194 1.1 mrg } 3195 1.1 mrg 3196 1.1 mrg /* Start a new block. */ 3197 1.1 mrg gfc_start_block (&block); 3198 1.1 mrg 3199 1.1 mrg /* Calculate the switch expression. We always need to do this 3200 1.1 mrg because it may have side effects. */ 3201 1.1 mrg gfc_init_se (&se, NULL); 3202 1.1 mrg gfc_conv_expr_val (&se, code->expr1); 3203 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 3204 1.1 mrg 3205 1.1 mrg if (t == f && t != NULL) 3206 1.1 mrg { 3207 1.1 mrg /* Cases for .TRUE. and .FALSE. are in the same block. Just 3208 1.1 mrg translate the code for these cases, append it to the current 3209 1.1 mrg block. */ 3210 1.1 mrg gfc_add_expr_to_block (&block, gfc_trans_code (t->next)); 3211 1.1 mrg } 3212 1.1 mrg else 3213 1.1 mrg { 3214 1.1 mrg tree true_tree, false_tree, stmt; 3215 1.1 mrg 3216 1.1 mrg true_tree = build_empty_stmt (input_location); 3217 1.1 mrg false_tree = build_empty_stmt (input_location); 3218 1.1 mrg 3219 1.1 mrg /* If we have a case for .TRUE. and for .FALSE., discard the default case. 3220 1.1 mrg Otherwise, if .TRUE. or .FALSE. is missing and there is a default case, 3221 1.1 mrg make the missing case the default case. */ 3222 1.1 mrg if (t != NULL && f != NULL) 3223 1.1 mrg d = NULL; 3224 1.1 mrg else if (d != NULL) 3225 1.1 mrg { 3226 1.1 mrg if (t == NULL) 3227 1.1 mrg t = d; 3228 1.1 mrg else 3229 1.1 mrg f = d; 3230 1.1 mrg } 3231 1.1 mrg 3232 1.1 mrg /* Translate the code for each of these blocks, and append it to 3233 1.1 mrg the current block. */ 3234 1.1 mrg if (t != NULL) 3235 1.1 mrg true_tree = gfc_trans_code (t->next); 3236 1.1 mrg 3237 1.1 mrg if (f != NULL) 3238 1.1 mrg false_tree = gfc_trans_code (f->next); 3239 1.1 mrg 3240 1.1 mrg stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node, 3241 1.1 mrg se.expr, true_tree, false_tree); 3242 1.1 mrg gfc_add_expr_to_block (&block, stmt); 3243 1.1 mrg } 3244 1.1 mrg 3245 1.1 mrg return gfc_finish_block (&block); 3246 1.1 mrg } 3247 1.1 mrg 3248 1.1 mrg 3249 1.1 mrg /* The jump table types are stored in static variables to avoid 3250 1.1 mrg constructing them from scratch every single time. */ 3251 1.1 mrg static GTY(()) tree select_struct[2]; 3252 1.1 mrg 3253 1.1 mrg /* Translate the SELECT CASE construct for CHARACTER case expressions. 3254 1.1 mrg Instead of generating compares and jumps, it is far simpler to 3255 1.1 mrg generate a data structure describing the cases in order and call a 3256 1.1 mrg library subroutine that locates the right case. 3257 1.1 mrg This is particularly true because this is the only case where we 3258 1.1 mrg might have to dispose of a temporary. 3259 1.1 mrg The library subroutine returns a pointer to jump to or NULL if no 3260 1.1 mrg branches are to be taken. */ 3261 1.1 mrg 3262 1.1 mrg static tree 3263 1.1 mrg gfc_trans_character_select (gfc_code *code) 3264 1.1 mrg { 3265 1.1 mrg tree init, end_label, tmp, type, case_num, label, fndecl; 3266 1.1 mrg stmtblock_t block, body; 3267 1.1 mrg gfc_case *cp, *d; 3268 1.1 mrg gfc_code *c; 3269 1.1 mrg gfc_se se, expr1se; 3270 1.1 mrg int n, k; 3271 1.1 mrg vec<constructor_elt, va_gc> *inits = NULL; 3272 1.1 mrg 3273 1.1 mrg tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind); 3274 1.1 mrg 3275 1.1 mrg /* The jump table types are stored in static variables to avoid 3276 1.1 mrg constructing them from scratch every single time. */ 3277 1.1 mrg static tree ss_string1[2], ss_string1_len[2]; 3278 1.1 mrg static tree ss_string2[2], ss_string2_len[2]; 3279 1.1 mrg static tree ss_target[2]; 3280 1.1 mrg 3281 1.1 mrg cp = code->block->ext.block.case_list; 3282 1.1 mrg while (cp->left != NULL) 3283 1.1 mrg cp = cp->left; 3284 1.1 mrg 3285 1.1 mrg /* Generate the body */ 3286 1.1 mrg gfc_start_block (&block); 3287 1.1 mrg gfc_init_se (&expr1se, NULL); 3288 1.1 mrg gfc_conv_expr_reference (&expr1se, code->expr1); 3289 1.1 mrg 3290 1.1 mrg gfc_add_block_to_block (&block, &expr1se.pre); 3291 1.1 mrg 3292 1.1 mrg end_label = gfc_build_label_decl (NULL_TREE); 3293 1.1 mrg 3294 1.1 mrg gfc_init_block (&body); 3295 1.1 mrg 3296 1.1 mrg /* Attempt to optimize length 1 selects. */ 3297 1.1 mrg if (integer_onep (expr1se.string_length)) 3298 1.1 mrg { 3299 1.1 mrg for (d = cp; d; d = d->right) 3300 1.1 mrg { 3301 1.1 mrg gfc_charlen_t i; 3302 1.1 mrg if (d->low) 3303 1.1 mrg { 3304 1.1 mrg gcc_assert (d->low->expr_type == EXPR_CONSTANT 3305 1.1 mrg && d->low->ts.type == BT_CHARACTER); 3306 1.1 mrg if (d->low->value.character.length > 1) 3307 1.1 mrg { 3308 1.1 mrg for (i = 1; i < d->low->value.character.length; i++) 3309 1.1 mrg if (d->low->value.character.string[i] != ' ') 3310 1.1 mrg break; 3311 1.1 mrg if (i != d->low->value.character.length) 3312 1.1 mrg { 3313 1.1 mrg if (optimize && d->high && i == 1) 3314 1.1 mrg { 3315 1.1 mrg gcc_assert (d->high->expr_type == EXPR_CONSTANT 3316 1.1 mrg && d->high->ts.type == BT_CHARACTER); 3317 1.1 mrg if (d->high->value.character.length > 1 3318 1.1 mrg && (d->low->value.character.string[0] 3319 1.1 mrg == d->high->value.character.string[0]) 3320 1.1 mrg && d->high->value.character.string[1] != ' ' 3321 1.1 mrg && ((d->low->value.character.string[1] < ' ') 3322 1.1 mrg == (d->high->value.character.string[1] 3323 1.1 mrg < ' '))) 3324 1.1 mrg continue; 3325 1.1 mrg } 3326 1.1 mrg break; 3327 1.1 mrg } 3328 1.1 mrg } 3329 1.1 mrg } 3330 1.1 mrg if (d->high) 3331 1.1 mrg { 3332 1.1 mrg gcc_assert (d->high->expr_type == EXPR_CONSTANT 3333 1.1 mrg && d->high->ts.type == BT_CHARACTER); 3334 1.1 mrg if (d->high->value.character.length > 1) 3335 1.1 mrg { 3336 1.1 mrg for (i = 1; i < d->high->value.character.length; i++) 3337 1.1 mrg if (d->high->value.character.string[i] != ' ') 3338 1.1 mrg break; 3339 1.1 mrg if (i != d->high->value.character.length) 3340 1.1 mrg break; 3341 1.1 mrg } 3342 1.1 mrg } 3343 1.1 mrg } 3344 1.1 mrg if (d == NULL) 3345 1.1 mrg { 3346 1.1 mrg tree ctype = gfc_get_char_type (code->expr1->ts.kind); 3347 1.1 mrg 3348 1.1 mrg for (c = code->block; c; c = c->block) 3349 1.1 mrg { 3350 1.1 mrg for (cp = c->ext.block.case_list; cp; cp = cp->next) 3351 1.1 mrg { 3352 1.1 mrg tree low, high; 3353 1.1 mrg tree label; 3354 1.1 mrg gfc_char_t r; 3355 1.1 mrg 3356 1.1 mrg /* Assume it's the default case. */ 3357 1.1 mrg low = high = NULL_TREE; 3358 1.1 mrg 3359 1.1 mrg if (cp->low) 3360 1.1 mrg { 3361 1.1 mrg /* CASE ('ab') or CASE ('ab':'az') will never match 3362 1.1 mrg any length 1 character. */ 3363 1.1 mrg if (cp->low->value.character.length > 1 3364 1.1 mrg && cp->low->value.character.string[1] != ' ') 3365 1.1 mrg continue; 3366 1.1 mrg 3367 1.1 mrg if (cp->low->value.character.length > 0) 3368 1.1 mrg r = cp->low->value.character.string[0]; 3369 1.1 mrg else 3370 1.1 mrg r = ' '; 3371 1.1 mrg low = build_int_cst (ctype, r); 3372 1.1 mrg 3373 1.1 mrg /* If there's only a lower bound, set the high bound 3374 1.1 mrg to the maximum value of the case expression. */ 3375 1.1 mrg if (!cp->high) 3376 1.1 mrg high = TYPE_MAX_VALUE (ctype); 3377 1.1 mrg } 3378 1.1 mrg 3379 1.1 mrg if (cp->high) 3380 1.1 mrg { 3381 1.1 mrg if (!cp->low 3382 1.1 mrg || (cp->low->value.character.string[0] 3383 1.1 mrg != cp->high->value.character.string[0])) 3384 1.1 mrg { 3385 1.1 mrg if (cp->high->value.character.length > 0) 3386 1.1 mrg r = cp->high->value.character.string[0]; 3387 1.1 mrg else 3388 1.1 mrg r = ' '; 3389 1.1 mrg high = build_int_cst (ctype, r); 3390 1.1 mrg } 3391 1.1 mrg 3392 1.1 mrg /* Unbounded case. */ 3393 1.1 mrg if (!cp->low) 3394 1.1 mrg low = TYPE_MIN_VALUE (ctype); 3395 1.1 mrg } 3396 1.1 mrg 3397 1.1 mrg /* Build a label. */ 3398 1.1 mrg label = gfc_build_label_decl (NULL_TREE); 3399 1.1 mrg 3400 1.1 mrg /* Add this case label. 3401 1.1 mrg Add parameter 'label', make it match GCC backend. */ 3402 1.1 mrg tmp = build_case_label (low, high, label); 3403 1.1 mrg gfc_add_expr_to_block (&body, tmp); 3404 1.1 mrg } 3405 1.1 mrg 3406 1.1 mrg /* Add the statements for this case. */ 3407 1.1 mrg tmp = gfc_trans_code (c->next); 3408 1.1 mrg gfc_add_expr_to_block (&body, tmp); 3409 1.1 mrg 3410 1.1 mrg /* Break to the end of the construct. */ 3411 1.1 mrg tmp = build1_v (GOTO_EXPR, end_label); 3412 1.1 mrg gfc_add_expr_to_block (&body, tmp); 3413 1.1 mrg } 3414 1.1 mrg 3415 1.1 mrg tmp = gfc_string_to_single_character (expr1se.string_length, 3416 1.1 mrg expr1se.expr, 3417 1.1 mrg code->expr1->ts.kind); 3418 1.1 mrg case_num = gfc_create_var (ctype, "case_num"); 3419 1.1 mrg gfc_add_modify (&block, case_num, tmp); 3420 1.1 mrg 3421 1.1 mrg gfc_add_block_to_block (&block, &expr1se.post); 3422 1.1 mrg 3423 1.1 mrg tmp = gfc_finish_block (&body); 3424 1.1 mrg tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, 3425 1.1 mrg case_num, tmp); 3426 1.1 mrg gfc_add_expr_to_block (&block, tmp); 3427 1.1 mrg 3428 1.1 mrg tmp = build1_v (LABEL_EXPR, end_label); 3429 1.1 mrg gfc_add_expr_to_block (&block, tmp); 3430 1.1 mrg 3431 1.1 mrg return gfc_finish_block (&block); 3432 1.1 mrg } 3433 1.1 mrg } 3434 1.1 mrg 3435 1.1 mrg if (code->expr1->ts.kind == 1) 3436 1.1 mrg k = 0; 3437 1.1 mrg else if (code->expr1->ts.kind == 4) 3438 1.1 mrg k = 1; 3439 1.1 mrg else 3440 1.1 mrg gcc_unreachable (); 3441 1.1 mrg 3442 1.1 mrg if (select_struct[k] == NULL) 3443 1.1 mrg { 3444 1.1 mrg tree *chain = NULL; 3445 1.1 mrg select_struct[k] = make_node (RECORD_TYPE); 3446 1.1 mrg 3447 1.1 mrg if (code->expr1->ts.kind == 1) 3448 1.1 mrg TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1"); 3449 1.1 mrg else if (code->expr1->ts.kind == 4) 3450 1.1 mrg TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4"); 3451 1.1 mrg else 3452 1.1 mrg gcc_unreachable (); 3453 1.1 mrg 3454 1.1 mrg #undef ADD_FIELD 3455 1.1 mrg #define ADD_FIELD(NAME, TYPE) \ 3456 1.1 mrg ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \ 3457 1.1 mrg get_identifier (stringize(NAME)), \ 3458 1.1 mrg TYPE, \ 3459 1.1 mrg &chain) 3460 1.1 mrg 3461 1.1 mrg ADD_FIELD (string1, pchartype); 3462 1.1 mrg ADD_FIELD (string1_len, gfc_charlen_type_node); 3463 1.1 mrg 3464 1.1 mrg ADD_FIELD (string2, pchartype); 3465 1.1 mrg ADD_FIELD (string2_len, gfc_charlen_type_node); 3466 1.1 mrg 3467 1.1 mrg ADD_FIELD (target, integer_type_node); 3468 1.1 mrg #undef ADD_FIELD 3469 1.1 mrg 3470 1.1 mrg gfc_finish_type (select_struct[k]); 3471 1.1 mrg } 3472 1.1 mrg 3473 1.1 mrg n = 0; 3474 1.1 mrg for (d = cp; d; d = d->right) 3475 1.1 mrg d->n = n++; 3476 1.1 mrg 3477 1.1 mrg for (c = code->block; c; c = c->block) 3478 1.1 mrg { 3479 1.1 mrg for (d = c->ext.block.case_list; d; d = d->next) 3480 1.1 mrg { 3481 1.1 mrg label = gfc_build_label_decl (NULL_TREE); 3482 1.1 mrg tmp = build_case_label ((d->low == NULL && d->high == NULL) 3483 1.1 mrg ? NULL 3484 1.1 mrg : build_int_cst (integer_type_node, d->n), 3485 1.1 mrg NULL, label); 3486 1.1 mrg gfc_add_expr_to_block (&body, tmp); 3487 1.1 mrg } 3488 1.1 mrg 3489 1.1 mrg tmp = gfc_trans_code (c->next); 3490 1.1 mrg gfc_add_expr_to_block (&body, tmp); 3491 1.1 mrg 3492 1.1 mrg tmp = build1_v (GOTO_EXPR, end_label); 3493 1.1 mrg gfc_add_expr_to_block (&body, tmp); 3494 1.1 mrg } 3495 1.1 mrg 3496 1.1 mrg /* Generate the structure describing the branches */ 3497 1.1 mrg for (d = cp; d; d = d->right) 3498 1.1 mrg { 3499 1.1 mrg vec<constructor_elt, va_gc> *node = NULL; 3500 1.1 mrg 3501 1.1 mrg gfc_init_se (&se, NULL); 3502 1.1 mrg 3503 1.1 mrg if (d->low == NULL) 3504 1.1 mrg { 3505 1.1 mrg CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node); 3506 1.1 mrg CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], build_zero_cst (gfc_charlen_type_node)); 3507 1.1 mrg } 3508 1.1 mrg else 3509 1.1 mrg { 3510 1.1 mrg gfc_conv_expr_reference (&se, d->low); 3511 1.1 mrg 3512 1.1 mrg CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr); 3513 1.1 mrg CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length); 3514 1.1 mrg } 3515 1.1 mrg 3516 1.1 mrg if (d->high == NULL) 3517 1.1 mrg { 3518 1.1 mrg CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node); 3519 1.1 mrg CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], build_zero_cst (gfc_charlen_type_node)); 3520 1.1 mrg } 3521 1.1 mrg else 3522 1.1 mrg { 3523 1.1 mrg gfc_init_se (&se, NULL); 3524 1.1 mrg gfc_conv_expr_reference (&se, d->high); 3525 1.1 mrg 3526 1.1 mrg CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr); 3527 1.1 mrg CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length); 3528 1.1 mrg } 3529 1.1 mrg 3530 1.1 mrg CONSTRUCTOR_APPEND_ELT (node, ss_target[k], 3531 1.1 mrg build_int_cst (integer_type_node, d->n)); 3532 1.1 mrg 3533 1.1 mrg tmp = build_constructor (select_struct[k], node); 3534 1.1 mrg CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp); 3535 1.1 mrg } 3536 1.1 mrg 3537 1.1 mrg type = build_array_type (select_struct[k], 3538 1.1 mrg build_index_type (size_int (n-1))); 3539 1.1 mrg 3540 1.1 mrg init = build_constructor (type, inits); 3541 1.1 mrg TREE_CONSTANT (init) = 1; 3542 1.1 mrg TREE_STATIC (init) = 1; 3543 1.1 mrg /* Create a static variable to hold the jump table. */ 3544 1.1 mrg tmp = gfc_create_var (type, "jumptable"); 3545 1.1 mrg TREE_CONSTANT (tmp) = 1; 3546 1.1 mrg TREE_STATIC (tmp) = 1; 3547 1.1 mrg TREE_READONLY (tmp) = 1; 3548 1.1 mrg DECL_INITIAL (tmp) = init; 3549 1.1 mrg init = tmp; 3550 1.1 mrg 3551 1.1 mrg /* Build the library call */ 3552 1.1 mrg init = gfc_build_addr_expr (pvoid_type_node, init); 3553 1.1 mrg 3554 1.1 mrg if (code->expr1->ts.kind == 1) 3555 1.1 mrg fndecl = gfor_fndecl_select_string; 3556 1.1 mrg else if (code->expr1->ts.kind == 4) 3557 1.1 mrg fndecl = gfor_fndecl_select_string_char4; 3558 1.1 mrg else 3559 1.1 mrg gcc_unreachable (); 3560 1.1 mrg 3561 1.1 mrg tmp = build_call_expr_loc (input_location, 3562 1.1 mrg fndecl, 4, init, 3563 1.1 mrg build_int_cst (gfc_charlen_type_node, n), 3564 1.1 mrg expr1se.expr, expr1se.string_length); 3565 1.1 mrg case_num = gfc_create_var (integer_type_node, "case_num"); 3566 1.1 mrg gfc_add_modify (&block, case_num, tmp); 3567 1.1 mrg 3568 1.1 mrg gfc_add_block_to_block (&block, &expr1se.post); 3569 1.1 mrg 3570 1.1 mrg tmp = gfc_finish_block (&body); 3571 1.1 mrg tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, 3572 1.1 mrg case_num, tmp); 3573 1.1 mrg gfc_add_expr_to_block (&block, tmp); 3574 1.1 mrg 3575 1.1 mrg tmp = build1_v (LABEL_EXPR, end_label); 3576 1.1 mrg gfc_add_expr_to_block (&block, tmp); 3577 1.1 mrg 3578 1.1 mrg return gfc_finish_block (&block); 3579 1.1 mrg } 3580 1.1 mrg 3581 1.1 mrg 3582 1.1 mrg /* Translate the three variants of the SELECT CASE construct. 3583 1.1 mrg 3584 1.1 mrg SELECT CASEs with INTEGER case expressions can be translated to an 3585 1.1 mrg equivalent GENERIC switch statement, and for LOGICAL case 3586 1.1 mrg expressions we build one or two if-else compares. 3587 1.1 mrg 3588 1.1 mrg SELECT CASEs with CHARACTER case expressions are a whole different 3589 1.1 mrg story, because they don't exist in GENERIC. So we sort them and 3590 1.1 mrg do a binary search at runtime. 3591 1.1 mrg 3592 1.1 mrg Fortran has no BREAK statement, and it does not allow jumps from 3593 1.1 mrg one case block to another. That makes things a lot easier for 3594 1.1 mrg the optimizers. */ 3595 1.1 mrg 3596 1.1 mrg tree 3597 1.1 mrg gfc_trans_select (gfc_code * code) 3598 1.1 mrg { 3599 1.1 mrg stmtblock_t block; 3600 1.1 mrg tree body; 3601 1.1 mrg tree exit_label; 3602 1.1 mrg 3603 1.1 mrg gcc_assert (code && code->expr1); 3604 1.1 mrg gfc_init_block (&block); 3605 1.1 mrg 3606 1.1 mrg /* Build the exit label and hang it in. */ 3607 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE); 3608 1.1 mrg code->exit_label = exit_label; 3609 1.1 mrg 3610 1.1 mrg /* Empty SELECT constructs are legal. */ 3611 1.1 mrg if (code->block == NULL) 3612 1.1 mrg body = build_empty_stmt (input_location); 3613 1.1 mrg 3614 1.1 mrg /* Select the correct translation function. */ 3615 1.1 mrg else 3616 1.1 mrg switch (code->expr1->ts.type) 3617 1.1 mrg { 3618 1.1 mrg case BT_LOGICAL: 3619 1.1 mrg body = gfc_trans_logical_select (code); 3620 1.1 mrg break; 3621 1.1 mrg 3622 1.1 mrg case BT_INTEGER: 3623 1.1 mrg body = gfc_trans_integer_select (code); 3624 1.1 mrg break; 3625 1.1 mrg 3626 1.1 mrg case BT_CHARACTER: 3627 1.1 mrg body = gfc_trans_character_select (code); 3628 1.1 mrg break; 3629 1.1 mrg 3630 1.1 mrg default: 3631 1.1 mrg gfc_internal_error ("gfc_trans_select(): Bad type for case expr."); 3632 1.1 mrg /* Not reached */ 3633 1.1 mrg } 3634 1.1 mrg 3635 1.1 mrg /* Build everything together. */ 3636 1.1 mrg gfc_add_expr_to_block (&block, body); 3637 1.1 mrg gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label)); 3638 1.1 mrg 3639 1.1 mrg return gfc_finish_block (&block); 3640 1.1 mrg } 3641 1.1 mrg 3642 1.1 mrg tree 3643 1.1 mrg gfc_trans_select_type (gfc_code * code) 3644 1.1 mrg { 3645 1.1 mrg stmtblock_t block; 3646 1.1 mrg tree body; 3647 1.1 mrg tree exit_label; 3648 1.1 mrg 3649 1.1 mrg gcc_assert (code && code->expr1); 3650 1.1 mrg gfc_init_block (&block); 3651 1.1 mrg 3652 1.1 mrg /* Build the exit label and hang it in. */ 3653 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE); 3654 1.1 mrg code->exit_label = exit_label; 3655 1.1 mrg 3656 1.1 mrg /* Empty SELECT constructs are legal. */ 3657 1.1 mrg if (code->block == NULL) 3658 1.1 mrg body = build_empty_stmt (input_location); 3659 1.1 mrg else 3660 1.1 mrg body = gfc_trans_select_type_cases (code); 3661 1.1 mrg 3662 1.1 mrg /* Build everything together. */ 3663 1.1 mrg gfc_add_expr_to_block (&block, body); 3664 1.1 mrg 3665 1.1 mrg if (TREE_USED (exit_label)) 3666 1.1 mrg gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label)); 3667 1.1 mrg 3668 1.1 mrg return gfc_finish_block (&block); 3669 1.1 mrg } 3670 1.1 mrg 3671 1.1 mrg 3672 1.1 mrg static tree 3673 1.1 mrg gfc_trans_select_rank_cases (gfc_code * code) 3674 1.1 mrg { 3675 1.1 mrg gfc_code *c; 3676 1.1 mrg gfc_case *cp; 3677 1.1 mrg tree tmp; 3678 1.1 mrg tree cond; 3679 1.1 mrg tree low; 3680 1.1 mrg tree rank; 3681 1.1 mrg gfc_se se; 3682 1.1 mrg gfc_se cse; 3683 1.1 mrg stmtblock_t block; 3684 1.1 mrg stmtblock_t body; 3685 1.1 mrg bool def = false; 3686 1.1 mrg 3687 1.1 mrg gfc_start_block (&block); 3688 1.1 mrg 3689 1.1 mrg /* Calculate the switch expression. */ 3690 1.1 mrg gfc_init_se (&se, NULL); 3691 1.1 mrg gfc_conv_expr_descriptor (&se, code->expr1); 3692 1.1 mrg rank = gfc_conv_descriptor_rank (se.expr); 3693 1.1 mrg rank = gfc_evaluate_now (rank, &block); 3694 1.1 mrg symbol_attribute attr = gfc_expr_attr (code->expr1); 3695 1.1 mrg if (!attr.pointer && !attr.allocatable) 3696 1.1 mrg { 3697 1.1 mrg /* Special case for assumed-rank ('rank(*)', internally -1): 3698 1.1 mrg rank = (rank == 0 || ubound[rank-1] != -1) ? rank : -1. */ 3699 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, 3700 1.1 mrg rank, build_int_cst (TREE_TYPE (rank), 0)); 3701 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, 3702 1.1 mrg fold_convert (gfc_array_index_type, rank), 3703 1.1 mrg gfc_index_one_node); 3704 1.1 mrg tmp = gfc_conv_descriptor_ubound_get (se.expr, tmp); 3705 1.1 mrg tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, 3706 1.1 mrg tmp, build_int_cst (TREE_TYPE (tmp), -1)); 3707 1.1 mrg cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR, 3708 1.1 mrg logical_type_node, cond, tmp); 3709 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (rank), 3710 1.1 mrg cond, rank, build_int_cst (TREE_TYPE (rank), -1)); 3711 1.1 mrg rank = gfc_evaluate_now (tmp, &block); 3712 1.1 mrg } 3713 1.1 mrg TREE_USED (code->exit_label) = 0; 3714 1.1 mrg 3715 1.1 mrg repeat: 3716 1.1 mrg for (c = code->block; c; c = c->block) 3717 1.1 mrg { 3718 1.1 mrg cp = c->ext.block.case_list; 3719 1.1 mrg 3720 1.1 mrg /* Assume it's the default case. */ 3721 1.1 mrg low = NULL_TREE; 3722 1.1 mrg tmp = NULL_TREE; 3723 1.1 mrg 3724 1.1 mrg /* Put the default case at the end. */ 3725 1.1 mrg if ((!def && !cp->low) || (def && cp->low)) 3726 1.1 mrg continue; 3727 1.1 mrg 3728 1.1 mrg if (cp->low) 3729 1.1 mrg { 3730 1.1 mrg gfc_init_se (&cse, NULL); 3731 1.1 mrg gfc_conv_expr_val (&cse, cp->low); 3732 1.1 mrg gfc_add_block_to_block (&block, &cse.pre); 3733 1.1 mrg low = cse.expr; 3734 1.1 mrg } 3735 1.1 mrg 3736 1.1 mrg gfc_init_block (&body); 3737 1.1 mrg 3738 1.1 mrg /* Add the statements for this case. */ 3739 1.1 mrg tmp = gfc_trans_code (c->next); 3740 1.1 mrg gfc_add_expr_to_block (&body, tmp); 3741 1.1 mrg 3742 1.1 mrg /* Break to the end of the SELECT RANK construct. The default 3743 1.1 mrg case just falls through. */ 3744 1.1 mrg if (!def) 3745 1.1 mrg { 3746 1.1 mrg TREE_USED (code->exit_label) = 1; 3747 1.1 mrg tmp = build1_v (GOTO_EXPR, code->exit_label); 3748 1.1 mrg gfc_add_expr_to_block (&body, tmp); 3749 1.1 mrg } 3750 1.1 mrg 3751 1.1 mrg tmp = gfc_finish_block (&body); 3752 1.1 mrg 3753 1.1 mrg if (low != NULL_TREE) 3754 1.1 mrg { 3755 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, 3756 1.1 mrg TREE_TYPE (rank), rank, 3757 1.1 mrg fold_convert (TREE_TYPE (rank), low)); 3758 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, 3759 1.1 mrg cond, tmp, 3760 1.1 mrg build_empty_stmt (input_location)); 3761 1.1 mrg } 3762 1.1 mrg 3763 1.1 mrg gfc_add_expr_to_block (&block, tmp); 3764 1.1 mrg } 3765 1.1 mrg 3766 1.1 mrg if (!def) 3767 1.1 mrg { 3768 1.1 mrg def = true; 3769 1.1 mrg goto repeat; 3770 1.1 mrg } 3771 1.1 mrg 3772 1.1 mrg return gfc_finish_block (&block); 3773 1.1 mrg } 3774 1.1 mrg 3775 1.1 mrg 3776 1.1 mrg tree 3777 1.1 mrg gfc_trans_select_rank (gfc_code * code) 3778 1.1 mrg { 3779 1.1 mrg stmtblock_t block; 3780 1.1 mrg tree body; 3781 1.1 mrg tree exit_label; 3782 1.1 mrg 3783 1.1 mrg gcc_assert (code && code->expr1); 3784 1.1 mrg gfc_init_block (&block); 3785 1.1 mrg 3786 1.1 mrg /* Build the exit label and hang it in. */ 3787 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE); 3788 1.1 mrg code->exit_label = exit_label; 3789 1.1 mrg 3790 1.1 mrg /* Empty SELECT constructs are legal. */ 3791 1.1 mrg if (code->block == NULL) 3792 1.1 mrg body = build_empty_stmt (input_location); 3793 1.1 mrg else 3794 1.1 mrg body = gfc_trans_select_rank_cases (code); 3795 1.1 mrg 3796 1.1 mrg /* Build everything together. */ 3797 1.1 mrg gfc_add_expr_to_block (&block, body); 3798 1.1 mrg 3799 1.1 mrg if (TREE_USED (exit_label)) 3800 1.1 mrg gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label)); 3801 1.1 mrg 3802 1.1 mrg return gfc_finish_block (&block); 3803 1.1 mrg } 3804 1.1 mrg 3805 1.1 mrg 3806 1.1 mrg /* Traversal function to substitute a replacement symtree if the symbol 3807 1.1 mrg in the expression is the same as that passed. f == 2 signals that 3808 1.1 mrg that variable itself is not to be checked - only the references. 3809 1.1 mrg This group of functions is used when the variable expression in a 3810 1.1 mrg FORALL assignment has internal references. For example: 3811 1.1 mrg FORALL (i = 1:4) p(p(i)) = i 3812 1.1 mrg The only recourse here is to store a copy of 'p' for the index 3813 1.1 mrg expression. */ 3814 1.1 mrg 3815 1.1 mrg static gfc_symtree *new_symtree; 3816 1.1 mrg static gfc_symtree *old_symtree; 3817 1.1 mrg 3818 1.1 mrg static bool 3819 1.1 mrg forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f) 3820 1.1 mrg { 3821 1.1 mrg if (expr->expr_type != EXPR_VARIABLE) 3822 1.1 mrg return false; 3823 1.1 mrg 3824 1.1 mrg if (*f == 2) 3825 1.1 mrg *f = 1; 3826 1.1 mrg else if (expr->symtree->n.sym == sym) 3827 1.1 mrg expr->symtree = new_symtree; 3828 1.1 mrg 3829 1.1 mrg return false; 3830 1.1 mrg } 3831 1.1 mrg 3832 1.1 mrg static void 3833 1.1 mrg forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f) 3834 1.1 mrg { 3835 1.1 mrg gfc_traverse_expr (e, sym, forall_replace, f); 3836 1.1 mrg } 3837 1.1 mrg 3838 1.1 mrg static bool 3839 1.1 mrg forall_restore (gfc_expr *expr, 3840 1.1 mrg gfc_symbol *sym ATTRIBUTE_UNUSED, 3841 1.1 mrg int *f ATTRIBUTE_UNUSED) 3842 1.1 mrg { 3843 1.1 mrg if (expr->expr_type != EXPR_VARIABLE) 3844 1.1 mrg return false; 3845 1.1 mrg 3846 1.1 mrg if (expr->symtree == new_symtree) 3847 1.1 mrg expr->symtree = old_symtree; 3848 1.1 mrg 3849 1.1 mrg return false; 3850 1.1 mrg } 3851 1.1 mrg 3852 1.1 mrg static void 3853 1.1 mrg forall_restore_symtree (gfc_expr *e) 3854 1.1 mrg { 3855 1.1 mrg gfc_traverse_expr (e, NULL, forall_restore, 0); 3856 1.1 mrg } 3857 1.1 mrg 3858 1.1 mrg static void 3859 1.1 mrg forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post) 3860 1.1 mrg { 3861 1.1 mrg gfc_se tse; 3862 1.1 mrg gfc_se rse; 3863 1.1 mrg gfc_expr *e; 3864 1.1 mrg gfc_symbol *new_sym; 3865 1.1 mrg gfc_symbol *old_sym; 3866 1.1 mrg gfc_symtree *root; 3867 1.1 mrg tree tmp; 3868 1.1 mrg 3869 1.1 mrg /* Build a copy of the lvalue. */ 3870 1.1 mrg old_symtree = c->expr1->symtree; 3871 1.1 mrg old_sym = old_symtree->n.sym; 3872 1.1 mrg e = gfc_lval_expr_from_sym (old_sym); 3873 1.1 mrg if (old_sym->attr.dimension) 3874 1.1 mrg { 3875 1.1 mrg gfc_init_se (&tse, NULL); 3876 1.1 mrg gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false); 3877 1.1 mrg gfc_add_block_to_block (pre, &tse.pre); 3878 1.1 mrg gfc_add_block_to_block (post, &tse.post); 3879 1.1 mrg tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr); 3880 1.1 mrg 3881 1.1 mrg if (c->expr1->ref->u.ar.type != AR_SECTION) 3882 1.1 mrg { 3883 1.1 mrg /* Use the variable offset for the temporary. */ 3884 1.1 mrg tmp = gfc_conv_array_offset (old_sym->backend_decl); 3885 1.1 mrg gfc_conv_descriptor_offset_set (pre, tse.expr, tmp); 3886 1.1 mrg } 3887 1.1 mrg } 3888 1.1 mrg else 3889 1.1 mrg { 3890 1.1 mrg gfc_init_se (&tse, NULL); 3891 1.1 mrg gfc_init_se (&rse, NULL); 3892 1.1 mrg gfc_conv_expr (&rse, e); 3893 1.1 mrg if (e->ts.type == BT_CHARACTER) 3894 1.1 mrg { 3895 1.1 mrg tse.string_length = rse.string_length; 3896 1.1 mrg tmp = gfc_get_character_type_len (gfc_default_character_kind, 3897 1.1 mrg tse.string_length); 3898 1.1 mrg tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp), 3899 1.1 mrg rse.string_length); 3900 1.1 mrg gfc_add_block_to_block (pre, &tse.pre); 3901 1.1 mrg gfc_add_block_to_block (post, &tse.post); 3902 1.1 mrg } 3903 1.1 mrg else 3904 1.1 mrg { 3905 1.1 mrg tmp = gfc_typenode_for_spec (&e->ts); 3906 1.1 mrg tse.expr = gfc_create_var (tmp, "temp"); 3907 1.1 mrg } 3908 1.1 mrg 3909 1.1 mrg tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, 3910 1.1 mrg e->expr_type == EXPR_VARIABLE, false); 3911 1.1 mrg gfc_add_expr_to_block (pre, tmp); 3912 1.1 mrg } 3913 1.1 mrg gfc_free_expr (e); 3914 1.1 mrg 3915 1.1 mrg /* Create a new symbol to represent the lvalue. */ 3916 1.1 mrg new_sym = gfc_new_symbol (old_sym->name, NULL); 3917 1.1 mrg new_sym->ts = old_sym->ts; 3918 1.1 mrg new_sym->attr.referenced = 1; 3919 1.1 mrg new_sym->attr.temporary = 1; 3920 1.1 mrg new_sym->attr.dimension = old_sym->attr.dimension; 3921 1.1 mrg new_sym->attr.flavor = old_sym->attr.flavor; 3922 1.1 mrg 3923 1.1 mrg /* Use the temporary as the backend_decl. */ 3924 1.1 mrg new_sym->backend_decl = tse.expr; 3925 1.1 mrg 3926 1.1 mrg /* Create a fake symtree for it. */ 3927 1.1 mrg root = NULL; 3928 1.1 mrg new_symtree = gfc_new_symtree (&root, old_sym->name); 3929 1.1 mrg new_symtree->n.sym = new_sym; 3930 1.1 mrg gcc_assert (new_symtree == root); 3931 1.1 mrg 3932 1.1 mrg /* Go through the expression reference replacing the old_symtree 3933 1.1 mrg with the new. */ 3934 1.1 mrg forall_replace_symtree (c->expr1, old_sym, 2); 3935 1.1 mrg 3936 1.1 mrg /* Now we have made this temporary, we might as well use it for 3937 1.1 mrg the right hand side. */ 3938 1.1 mrg forall_replace_symtree (c->expr2, old_sym, 1); 3939 1.1 mrg } 3940 1.1 mrg 3941 1.1 mrg 3942 1.1 mrg /* Handles dependencies in forall assignments. */ 3943 1.1 mrg static int 3944 1.1 mrg check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post) 3945 1.1 mrg { 3946 1.1 mrg gfc_ref *lref; 3947 1.1 mrg gfc_ref *rref; 3948 1.1 mrg int need_temp; 3949 1.1 mrg gfc_symbol *lsym; 3950 1.1 mrg 3951 1.1 mrg lsym = c->expr1->symtree->n.sym; 3952 1.1 mrg need_temp = gfc_check_dependency (c->expr1, c->expr2, 0); 3953 1.1 mrg 3954 1.1 mrg /* Now check for dependencies within the 'variable' 3955 1.1 mrg expression itself. These are treated by making a complete 3956 1.1 mrg copy of variable and changing all the references to it 3957 1.1 mrg point to the copy instead. Note that the shallow copy of 3958 1.1 mrg the variable will not suffice for derived types with 3959 1.1 mrg pointer components. We therefore leave these to their 3960 1.1 mrg own devices. Likewise for allocatable components. */ 3961 1.1 mrg if (lsym->ts.type == BT_DERIVED 3962 1.1 mrg && (lsym->ts.u.derived->attr.pointer_comp 3963 1.1 mrg || lsym->ts.u.derived->attr.alloc_comp)) 3964 1.1 mrg return need_temp; 3965 1.1 mrg 3966 1.1 mrg new_symtree = NULL; 3967 1.1 mrg if (find_forall_index (c->expr1, lsym, 2)) 3968 1.1 mrg { 3969 1.1 mrg forall_make_variable_temp (c, pre, post); 3970 1.1 mrg need_temp = 0; 3971 1.1 mrg } 3972 1.1 mrg 3973 1.1 mrg /* Substrings with dependencies are treated in the same 3974 1.1 mrg way. */ 3975 1.1 mrg if (c->expr1->ts.type == BT_CHARACTER 3976 1.1 mrg && c->expr1->ref 3977 1.1 mrg && c->expr2->expr_type == EXPR_VARIABLE 3978 1.1 mrg && lsym == c->expr2->symtree->n.sym) 3979 1.1 mrg { 3980 1.1 mrg for (lref = c->expr1->ref; lref; lref = lref->next) 3981 1.1 mrg if (lref->type == REF_SUBSTRING) 3982 1.1 mrg break; 3983 1.1 mrg for (rref = c->expr2->ref; rref; rref = rref->next) 3984 1.1 mrg if (rref->type == REF_SUBSTRING) 3985 1.1 mrg break; 3986 1.1 mrg 3987 1.1 mrg if (rref && lref 3988 1.1 mrg && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0) 3989 1.1 mrg { 3990 1.1 mrg forall_make_variable_temp (c, pre, post); 3991 1.1 mrg need_temp = 0; 3992 1.1 mrg } 3993 1.1 mrg } 3994 1.1 mrg return need_temp; 3995 1.1 mrg } 3996 1.1 mrg 3997 1.1 mrg 3998 1.1 mrg static void 3999 1.1 mrg cleanup_forall_symtrees (gfc_code *c) 4000 1.1 mrg { 4001 1.1 mrg forall_restore_symtree (c->expr1); 4002 1.1 mrg forall_restore_symtree (c->expr2); 4003 1.1 mrg free (new_symtree->n.sym); 4004 1.1 mrg free (new_symtree); 4005 1.1 mrg } 4006 1.1 mrg 4007 1.1 mrg 4008 1.1 mrg /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY 4009 1.1 mrg is the contents of the FORALL block/stmt to be iterated. MASK_FLAG 4010 1.1 mrg indicates whether we should generate code to test the FORALLs mask 4011 1.1 mrg array. OUTER is the loop header to be used for initializing mask 4012 1.1 mrg indices. 4013 1.1 mrg 4014 1.1 mrg The generated loop format is: 4015 1.1 mrg count = (end - start + step) / step 4016 1.1 mrg loopvar = start 4017 1.1 mrg while (1) 4018 1.1 mrg { 4019 1.1 mrg if (count <=0 ) 4020 1.1 mrg goto end_of_loop 4021 1.1 mrg <body> 4022 1.1 mrg loopvar += step 4023 1.1 mrg count -- 4024 1.1 mrg } 4025 1.1 mrg end_of_loop: */ 4026 1.1 mrg 4027 1.1 mrg static tree 4028 1.1 mrg gfc_trans_forall_loop (forall_info *forall_tmp, tree body, 4029 1.1 mrg int mask_flag, stmtblock_t *outer) 4030 1.1 mrg { 4031 1.1 mrg int n, nvar; 4032 1.1 mrg tree tmp; 4033 1.1 mrg tree cond; 4034 1.1 mrg stmtblock_t block; 4035 1.1 mrg tree exit_label; 4036 1.1 mrg tree count; 4037 1.1 mrg tree var, start, end, step; 4038 1.1 mrg iter_info *iter; 4039 1.1 mrg 4040 1.1 mrg /* Initialize the mask index outside the FORALL nest. */ 4041 1.1 mrg if (mask_flag && forall_tmp->mask) 4042 1.1 mrg gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node); 4043 1.1 mrg 4044 1.1 mrg iter = forall_tmp->this_loop; 4045 1.1 mrg nvar = forall_tmp->nvar; 4046 1.1 mrg for (n = 0; n < nvar; n++) 4047 1.1 mrg { 4048 1.1 mrg var = iter->var; 4049 1.1 mrg start = iter->start; 4050 1.1 mrg end = iter->end; 4051 1.1 mrg step = iter->step; 4052 1.1 mrg 4053 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE); 4054 1.1 mrg TREE_USED (exit_label) = 1; 4055 1.1 mrg 4056 1.1 mrg /* The loop counter. */ 4057 1.1 mrg count = gfc_create_var (TREE_TYPE (var), "count"); 4058 1.1 mrg 4059 1.1 mrg /* The body of the loop. */ 4060 1.1 mrg gfc_init_block (&block); 4061 1.1 mrg 4062 1.1 mrg /* The exit condition. */ 4063 1.1 mrg cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, 4064 1.1 mrg count, build_int_cst (TREE_TYPE (count), 0)); 4065 1.1 mrg 4066 1.1 mrg /* PR 83064 means that we cannot use annot_expr_parallel_kind until 4067 1.1 mrg the autoparallelizer can hande this. */ 4068 1.1 mrg if (forall_tmp->do_concurrent) 4069 1.1 mrg cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, 4070 1.1 mrg build_int_cst (integer_type_node, 4071 1.1 mrg annot_expr_ivdep_kind), 4072 1.1 mrg integer_zero_node); 4073 1.1 mrg 4074 1.1 mrg tmp = build1_v (GOTO_EXPR, exit_label); 4075 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, 4076 1.1 mrg cond, tmp, build_empty_stmt (input_location)); 4077 1.1 mrg gfc_add_expr_to_block (&block, tmp); 4078 1.1 mrg 4079 1.1 mrg /* The main loop body. */ 4080 1.1 mrg gfc_add_expr_to_block (&block, body); 4081 1.1 mrg 4082 1.1 mrg /* Increment the loop variable. */ 4083 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var, 4084 1.1 mrg step); 4085 1.1 mrg gfc_add_modify (&block, var, tmp); 4086 1.1 mrg 4087 1.1 mrg /* Advance to the next mask element. Only do this for the 4088 1.1 mrg innermost loop. */ 4089 1.1 mrg if (n == 0 && mask_flag && forall_tmp->mask) 4090 1.1 mrg { 4091 1.1 mrg tree maskindex = forall_tmp->maskindex; 4092 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 4093 1.1 mrg maskindex, gfc_index_one_node); 4094 1.1 mrg gfc_add_modify (&block, maskindex, tmp); 4095 1.1 mrg } 4096 1.1 mrg 4097 1.1 mrg /* Decrement the loop counter. */ 4098 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count, 4099 1.1 mrg build_int_cst (TREE_TYPE (var), 1)); 4100 1.1 mrg gfc_add_modify (&block, count, tmp); 4101 1.1 mrg 4102 1.1 mrg body = gfc_finish_block (&block); 4103 1.1 mrg 4104 1.1 mrg /* Loop var initialization. */ 4105 1.1 mrg gfc_init_block (&block); 4106 1.1 mrg gfc_add_modify (&block, var, start); 4107 1.1 mrg 4108 1.1 mrg 4109 1.1 mrg /* Initialize the loop counter. */ 4110 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step, 4111 1.1 mrg start); 4112 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end, 4113 1.1 mrg tmp); 4114 1.1 mrg tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var), 4115 1.1 mrg tmp, step); 4116 1.1 mrg gfc_add_modify (&block, count, tmp); 4117 1.1 mrg 4118 1.1 mrg /* The loop expression. */ 4119 1.1 mrg tmp = build1_v (LOOP_EXPR, body); 4120 1.1 mrg gfc_add_expr_to_block (&block, tmp); 4121 1.1 mrg 4122 1.1 mrg /* The exit label. */ 4123 1.1 mrg tmp = build1_v (LABEL_EXPR, exit_label); 4124 1.1 mrg gfc_add_expr_to_block (&block, tmp); 4125 1.1 mrg 4126 1.1 mrg body = gfc_finish_block (&block); 4127 1.1 mrg iter = iter->next; 4128 1.1 mrg } 4129 1.1 mrg return body; 4130 1.1 mrg } 4131 1.1 mrg 4132 1.1 mrg 4133 1.1 mrg /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG 4134 1.1 mrg is nonzero, the body is controlled by all masks in the forall nest. 4135 1.1 mrg Otherwise, the innermost loop is not controlled by it's mask. This 4136 1.1 mrg is used for initializing that mask. */ 4137 1.1 mrg 4138 1.1 mrg static tree 4139 1.1 mrg gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body, 4140 1.1 mrg int mask_flag) 4141 1.1 mrg { 4142 1.1 mrg tree tmp; 4143 1.1 mrg stmtblock_t header; 4144 1.1 mrg forall_info *forall_tmp; 4145 1.1 mrg tree mask, maskindex; 4146 1.1 mrg 4147 1.1 mrg gfc_start_block (&header); 4148 1.1 mrg 4149 1.1 mrg forall_tmp = nested_forall_info; 4150 1.1 mrg while (forall_tmp != NULL) 4151 1.1 mrg { 4152 1.1 mrg /* Generate body with masks' control. */ 4153 1.1 mrg if (mask_flag) 4154 1.1 mrg { 4155 1.1 mrg mask = forall_tmp->mask; 4156 1.1 mrg maskindex = forall_tmp->maskindex; 4157 1.1 mrg 4158 1.1 mrg /* If a mask was specified make the assignment conditional. */ 4159 1.1 mrg if (mask) 4160 1.1 mrg { 4161 1.1 mrg tmp = gfc_build_array_ref (mask, maskindex, NULL); 4162 1.1 mrg body = build3_v (COND_EXPR, tmp, body, 4163 1.1 mrg build_empty_stmt (input_location)); 4164 1.1 mrg } 4165 1.1 mrg } 4166 1.1 mrg body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header); 4167 1.1 mrg forall_tmp = forall_tmp->prev_nest; 4168 1.1 mrg mask_flag = 1; 4169 1.1 mrg } 4170 1.1 mrg 4171 1.1 mrg gfc_add_expr_to_block (&header, body); 4172 1.1 mrg return gfc_finish_block (&header); 4173 1.1 mrg } 4174 1.1 mrg 4175 1.1 mrg 4176 1.1 mrg /* Allocate data for holding a temporary array. Returns either a local 4177 1.1 mrg temporary array or a pointer variable. */ 4178 1.1 mrg 4179 1.1 mrg static tree 4180 1.1 mrg gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock, 4181 1.1 mrg tree elem_type) 4182 1.1 mrg { 4183 1.1 mrg tree tmpvar; 4184 1.1 mrg tree type; 4185 1.1 mrg tree tmp; 4186 1.1 mrg 4187 1.1 mrg if (INTEGER_CST_P (size)) 4188 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, 4189 1.1 mrg size, gfc_index_one_node); 4190 1.1 mrg else 4191 1.1 mrg tmp = NULL_TREE; 4192 1.1 mrg 4193 1.1 mrg type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp); 4194 1.1 mrg type = build_array_type (elem_type, type); 4195 1.1 mrg if (gfc_can_put_var_on_stack (bytesize) && INTEGER_CST_P (size)) 4196 1.1 mrg { 4197 1.1 mrg tmpvar = gfc_create_var (type, "temp"); 4198 1.1 mrg *pdata = NULL_TREE; 4199 1.1 mrg } 4200 1.1 mrg else 4201 1.1 mrg { 4202 1.1 mrg tmpvar = gfc_create_var (build_pointer_type (type), "temp"); 4203 1.1 mrg *pdata = convert (pvoid_type_node, tmpvar); 4204 1.1 mrg 4205 1.1 mrg tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize); 4206 1.1 mrg gfc_add_modify (pblock, tmpvar, tmp); 4207 1.1 mrg } 4208 1.1 mrg return tmpvar; 4209 1.1 mrg } 4210 1.1 mrg 4211 1.1 mrg 4212 1.1 mrg /* Generate codes to copy the temporary to the actual lhs. */ 4213 1.1 mrg 4214 1.1 mrg static tree 4215 1.1 mrg generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3, 4216 1.1 mrg tree count1, 4217 1.1 mrg gfc_ss *lss, gfc_ss *rss, 4218 1.1 mrg tree wheremask, bool invert) 4219 1.1 mrg { 4220 1.1 mrg stmtblock_t block, body1; 4221 1.1 mrg gfc_loopinfo loop; 4222 1.1 mrg gfc_se lse; 4223 1.1 mrg gfc_se rse; 4224 1.1 mrg tree tmp; 4225 1.1 mrg tree wheremaskexpr; 4226 1.1 mrg 4227 1.1 mrg (void) rss; /* TODO: unused. */ 4228 1.1 mrg 4229 1.1 mrg gfc_start_block (&block); 4230 1.1 mrg 4231 1.1 mrg gfc_init_se (&rse, NULL); 4232 1.1 mrg gfc_init_se (&lse, NULL); 4233 1.1 mrg 4234 1.1 mrg if (lss == gfc_ss_terminator) 4235 1.1 mrg { 4236 1.1 mrg gfc_init_block (&body1); 4237 1.1 mrg gfc_conv_expr (&lse, expr); 4238 1.1 mrg rse.expr = gfc_build_array_ref (tmp1, count1, NULL); 4239 1.1 mrg } 4240 1.1 mrg else 4241 1.1 mrg { 4242 1.1 mrg /* Initialize the loop. */ 4243 1.1 mrg gfc_init_loopinfo (&loop); 4244 1.1 mrg 4245 1.1 mrg /* We may need LSS to determine the shape of the expression. */ 4246 1.1 mrg gfc_add_ss_to_loop (&loop, lss); 4247 1.1 mrg 4248 1.1 mrg gfc_conv_ss_startstride (&loop); 4249 1.1 mrg gfc_conv_loop_setup (&loop, &expr->where); 4250 1.1 mrg 4251 1.1 mrg gfc_mark_ss_chain_used (lss, 1); 4252 1.1 mrg /* Start the loop body. */ 4253 1.1 mrg gfc_start_scalarized_body (&loop, &body1); 4254 1.1 mrg 4255 1.1 mrg /* Translate the expression. */ 4256 1.1 mrg gfc_copy_loopinfo_to_se (&lse, &loop); 4257 1.1 mrg lse.ss = lss; 4258 1.1 mrg gfc_conv_expr (&lse, expr); 4259 1.1 mrg 4260 1.1 mrg /* Form the expression of the temporary. */ 4261 1.1 mrg rse.expr = gfc_build_array_ref (tmp1, count1, NULL); 4262 1.1 mrg } 4263 1.1 mrg 4264 1.1 mrg /* Use the scalar assignment. */ 4265 1.1 mrg rse.string_length = lse.string_length; 4266 1.1 mrg tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, 4267 1.1 mrg expr->expr_type == EXPR_VARIABLE, false); 4268 1.1 mrg 4269 1.1 mrg /* Form the mask expression according to the mask tree list. */ 4270 1.1 mrg if (wheremask) 4271 1.1 mrg { 4272 1.1 mrg wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL); 4273 1.1 mrg if (invert) 4274 1.1 mrg wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR, 4275 1.1 mrg TREE_TYPE (wheremaskexpr), 4276 1.1 mrg wheremaskexpr); 4277 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, 4278 1.1 mrg wheremaskexpr, tmp, 4279 1.1 mrg build_empty_stmt (input_location)); 4280 1.1 mrg } 4281 1.1 mrg 4282 1.1 mrg gfc_add_expr_to_block (&body1, tmp); 4283 1.1 mrg 4284 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1), 4285 1.1 mrg count1, gfc_index_one_node); 4286 1.1 mrg gfc_add_modify (&body1, count1, tmp); 4287 1.1 mrg 4288 1.1 mrg if (lss == gfc_ss_terminator) 4289 1.1 mrg gfc_add_block_to_block (&block, &body1); 4290 1.1 mrg else 4291 1.1 mrg { 4292 1.1 mrg /* Increment count3. */ 4293 1.1 mrg if (count3) 4294 1.1 mrg { 4295 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, 4296 1.1 mrg gfc_array_index_type, 4297 1.1 mrg count3, gfc_index_one_node); 4298 1.1 mrg gfc_add_modify (&body1, count3, tmp); 4299 1.1 mrg } 4300 1.1 mrg 4301 1.1 mrg /* Generate the copying loops. */ 4302 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body1); 4303 1.1 mrg 4304 1.1 mrg gfc_add_block_to_block (&block, &loop.pre); 4305 1.1 mrg gfc_add_block_to_block (&block, &loop.post); 4306 1.1 mrg 4307 1.1 mrg gfc_cleanup_loop (&loop); 4308 1.1 mrg /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful 4309 1.1 mrg as tree nodes in SS may not be valid in different scope. */ 4310 1.1 mrg } 4311 1.1 mrg 4312 1.1 mrg tmp = gfc_finish_block (&block); 4313 1.1 mrg return tmp; 4314 1.1 mrg } 4315 1.1 mrg 4316 1.1 mrg 4317 1.1 mrg /* Generate codes to copy rhs to the temporary. TMP1 is the address of 4318 1.1 mrg temporary, LSS and RSS are formed in function compute_inner_temp_size(), 4319 1.1 mrg and should not be freed. WHEREMASK is the conditional execution mask 4320 1.1 mrg whose sense may be inverted by INVERT. */ 4321 1.1 mrg 4322 1.1 mrg static tree 4323 1.1 mrg generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3, 4324 1.1 mrg tree count1, gfc_ss *lss, gfc_ss *rss, 4325 1.1 mrg tree wheremask, bool invert) 4326 1.1 mrg { 4327 1.1 mrg stmtblock_t block, body1; 4328 1.1 mrg gfc_loopinfo loop; 4329 1.1 mrg gfc_se lse; 4330 1.1 mrg gfc_se rse; 4331 1.1 mrg tree tmp; 4332 1.1 mrg tree wheremaskexpr; 4333 1.1 mrg 4334 1.1 mrg gfc_start_block (&block); 4335 1.1 mrg 4336 1.1 mrg gfc_init_se (&rse, NULL); 4337 1.1 mrg gfc_init_se (&lse, NULL); 4338 1.1 mrg 4339 1.1 mrg if (lss == gfc_ss_terminator) 4340 1.1 mrg { 4341 1.1 mrg gfc_init_block (&body1); 4342 1.1 mrg gfc_conv_expr (&rse, expr2); 4343 1.1 mrg lse.expr = gfc_build_array_ref (tmp1, count1, NULL); 4344 1.1 mrg } 4345 1.1 mrg else 4346 1.1 mrg { 4347 1.1 mrg /* Initialize the loop. */ 4348 1.1 mrg gfc_init_loopinfo (&loop); 4349 1.1 mrg 4350 1.1 mrg /* We may need LSS to determine the shape of the expression. */ 4351 1.1 mrg gfc_add_ss_to_loop (&loop, lss); 4352 1.1 mrg gfc_add_ss_to_loop (&loop, rss); 4353 1.1 mrg 4354 1.1 mrg gfc_conv_ss_startstride (&loop); 4355 1.1 mrg gfc_conv_loop_setup (&loop, &expr2->where); 4356 1.1 mrg 4357 1.1 mrg gfc_mark_ss_chain_used (rss, 1); 4358 1.1 mrg /* Start the loop body. */ 4359 1.1 mrg gfc_start_scalarized_body (&loop, &body1); 4360 1.1 mrg 4361 1.1 mrg /* Translate the expression. */ 4362 1.1 mrg gfc_copy_loopinfo_to_se (&rse, &loop); 4363 1.1 mrg rse.ss = rss; 4364 1.1 mrg gfc_conv_expr (&rse, expr2); 4365 1.1 mrg 4366 1.1 mrg /* Form the expression of the temporary. */ 4367 1.1 mrg lse.expr = gfc_build_array_ref (tmp1, count1, NULL); 4368 1.1 mrg } 4369 1.1 mrg 4370 1.1 mrg /* Use the scalar assignment. */ 4371 1.1 mrg lse.string_length = rse.string_length; 4372 1.1 mrg tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, 4373 1.1 mrg expr2->expr_type == EXPR_VARIABLE, false); 4374 1.1 mrg 4375 1.1 mrg /* Form the mask expression according to the mask tree list. */ 4376 1.1 mrg if (wheremask) 4377 1.1 mrg { 4378 1.1 mrg wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL); 4379 1.1 mrg if (invert) 4380 1.1 mrg wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR, 4381 1.1 mrg TREE_TYPE (wheremaskexpr), 4382 1.1 mrg wheremaskexpr); 4383 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, 4384 1.1 mrg wheremaskexpr, tmp, 4385 1.1 mrg build_empty_stmt (input_location)); 4386 1.1 mrg } 4387 1.1 mrg 4388 1.1 mrg gfc_add_expr_to_block (&body1, tmp); 4389 1.1 mrg 4390 1.1 mrg if (lss == gfc_ss_terminator) 4391 1.1 mrg { 4392 1.1 mrg gfc_add_block_to_block (&block, &body1); 4393 1.1 mrg 4394 1.1 mrg /* Increment count1. */ 4395 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1), 4396 1.1 mrg count1, gfc_index_one_node); 4397 1.1 mrg gfc_add_modify (&block, count1, tmp); 4398 1.1 mrg } 4399 1.1 mrg else 4400 1.1 mrg { 4401 1.1 mrg /* Increment count1. */ 4402 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 4403 1.1 mrg count1, gfc_index_one_node); 4404 1.1 mrg gfc_add_modify (&body1, count1, tmp); 4405 1.1 mrg 4406 1.1 mrg /* Increment count3. */ 4407 1.1 mrg if (count3) 4408 1.1 mrg { 4409 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, 4410 1.1 mrg gfc_array_index_type, 4411 1.1 mrg count3, gfc_index_one_node); 4412 1.1 mrg gfc_add_modify (&body1, count3, tmp); 4413 1.1 mrg } 4414 1.1 mrg 4415 1.1 mrg /* Generate the copying loops. */ 4416 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body1); 4417 1.1 mrg 4418 1.1 mrg gfc_add_block_to_block (&block, &loop.pre); 4419 1.1 mrg gfc_add_block_to_block (&block, &loop.post); 4420 1.1 mrg 4421 1.1 mrg gfc_cleanup_loop (&loop); 4422 1.1 mrg /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful 4423 1.1 mrg as tree nodes in SS may not be valid in different scope. */ 4424 1.1 mrg } 4425 1.1 mrg 4426 1.1 mrg tmp = gfc_finish_block (&block); 4427 1.1 mrg return tmp; 4428 1.1 mrg } 4429 1.1 mrg 4430 1.1 mrg 4431 1.1 mrg /* Calculate the size of temporary needed in the assignment inside forall. 4432 1.1 mrg LSS and RSS are filled in this function. */ 4433 1.1 mrg 4434 1.1 mrg static tree 4435 1.1 mrg compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2, 4436 1.1 mrg stmtblock_t * pblock, 4437 1.1 mrg gfc_ss **lss, gfc_ss **rss) 4438 1.1 mrg { 4439 1.1 mrg gfc_loopinfo loop; 4440 1.1 mrg tree size; 4441 1.1 mrg int i; 4442 1.1 mrg int save_flag; 4443 1.1 mrg tree tmp; 4444 1.1 mrg 4445 1.1 mrg *lss = gfc_walk_expr (expr1); 4446 1.1 mrg *rss = NULL; 4447 1.1 mrg 4448 1.1 mrg size = gfc_index_one_node; 4449 1.1 mrg if (*lss != gfc_ss_terminator) 4450 1.1 mrg { 4451 1.1 mrg gfc_init_loopinfo (&loop); 4452 1.1 mrg 4453 1.1 mrg /* Walk the RHS of the expression. */ 4454 1.1 mrg *rss = gfc_walk_expr (expr2); 4455 1.1 mrg if (*rss == gfc_ss_terminator) 4456 1.1 mrg /* The rhs is scalar. Add a ss for the expression. */ 4457 1.1 mrg *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2); 4458 1.1 mrg 4459 1.1 mrg /* Associate the SS with the loop. */ 4460 1.1 mrg gfc_add_ss_to_loop (&loop, *lss); 4461 1.1 mrg /* We don't actually need to add the rhs at this point, but it might 4462 1.1 mrg make guessing the loop bounds a bit easier. */ 4463 1.1 mrg gfc_add_ss_to_loop (&loop, *rss); 4464 1.1 mrg 4465 1.1 mrg /* We only want the shape of the expression, not rest of the junk 4466 1.1 mrg generated by the scalarizer. */ 4467 1.1 mrg loop.array_parameter = 1; 4468 1.1 mrg 4469 1.1 mrg /* Calculate the bounds of the scalarization. */ 4470 1.1 mrg save_flag = gfc_option.rtcheck; 4471 1.1 mrg gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS; 4472 1.1 mrg gfc_conv_ss_startstride (&loop); 4473 1.1 mrg gfc_option.rtcheck = save_flag; 4474 1.1 mrg gfc_conv_loop_setup (&loop, &expr2->where); 4475 1.1 mrg 4476 1.1 mrg /* Figure out how many elements we need. */ 4477 1.1 mrg for (i = 0; i < loop.dimen; i++) 4478 1.1 mrg { 4479 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, 4480 1.1 mrg gfc_array_index_type, 4481 1.1 mrg gfc_index_one_node, loop.from[i]); 4482 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, 4483 1.1 mrg gfc_array_index_type, tmp, loop.to[i]); 4484 1.1 mrg size = fold_build2_loc (input_location, MULT_EXPR, 4485 1.1 mrg gfc_array_index_type, size, tmp); 4486 1.1 mrg } 4487 1.1 mrg gfc_add_block_to_block (pblock, &loop.pre); 4488 1.1 mrg size = gfc_evaluate_now (size, pblock); 4489 1.1 mrg gfc_add_block_to_block (pblock, &loop.post); 4490 1.1 mrg 4491 1.1 mrg /* TODO: write a function that cleans up a loopinfo without freeing 4492 1.1 mrg the SS chains. Currently a NOP. */ 4493 1.1 mrg } 4494 1.1 mrg 4495 1.1 mrg return size; 4496 1.1 mrg } 4497 1.1 mrg 4498 1.1 mrg 4499 1.1 mrg /* Calculate the overall iterator number of the nested forall construct. 4500 1.1 mrg This routine actually calculates the number of times the body of the 4501 1.1 mrg nested forall specified by NESTED_FORALL_INFO is executed and multiplies 4502 1.1 mrg that by the expression INNER_SIZE. The BLOCK argument specifies the 4503 1.1 mrg block in which to calculate the result, and the optional INNER_SIZE_BODY 4504 1.1 mrg argument contains any statements that need to executed (inside the loop) 4505 1.1 mrg to initialize or calculate INNER_SIZE. */ 4506 1.1 mrg 4507 1.1 mrg static tree 4508 1.1 mrg compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size, 4509 1.1 mrg stmtblock_t *inner_size_body, stmtblock_t *block) 4510 1.1 mrg { 4511 1.1 mrg forall_info *forall_tmp = nested_forall_info; 4512 1.1 mrg tree tmp, number; 4513 1.1 mrg stmtblock_t body; 4514 1.1 mrg 4515 1.1 mrg /* We can eliminate the innermost unconditional loops with constant 4516 1.1 mrg array bounds. */ 4517 1.1 mrg if (INTEGER_CST_P (inner_size)) 4518 1.1 mrg { 4519 1.1 mrg while (forall_tmp 4520 1.1 mrg && !forall_tmp->mask 4521 1.1 mrg && INTEGER_CST_P (forall_tmp->size)) 4522 1.1 mrg { 4523 1.1 mrg inner_size = fold_build2_loc (input_location, MULT_EXPR, 4524 1.1 mrg gfc_array_index_type, 4525 1.1 mrg inner_size, forall_tmp->size); 4526 1.1 mrg forall_tmp = forall_tmp->prev_nest; 4527 1.1 mrg } 4528 1.1 mrg 4529 1.1 mrg /* If there are no loops left, we have our constant result. */ 4530 1.1 mrg if (!forall_tmp) 4531 1.1 mrg return inner_size; 4532 1.1 mrg } 4533 1.1 mrg 4534 1.1 mrg /* Otherwise, create a temporary variable to compute the result. */ 4535 1.1 mrg number = gfc_create_var (gfc_array_index_type, "num"); 4536 1.1 mrg gfc_add_modify (block, number, gfc_index_zero_node); 4537 1.1 mrg 4538 1.1 mrg gfc_start_block (&body); 4539 1.1 mrg if (inner_size_body) 4540 1.1 mrg gfc_add_block_to_block (&body, inner_size_body); 4541 1.1 mrg if (forall_tmp) 4542 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, 4543 1.1 mrg gfc_array_index_type, number, inner_size); 4544 1.1 mrg else 4545 1.1 mrg tmp = inner_size; 4546 1.1 mrg gfc_add_modify (&body, number, tmp); 4547 1.1 mrg tmp = gfc_finish_block (&body); 4548 1.1 mrg 4549 1.1 mrg /* Generate loops. */ 4550 1.1 mrg if (forall_tmp != NULL) 4551 1.1 mrg tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1); 4552 1.1 mrg 4553 1.1 mrg gfc_add_expr_to_block (block, tmp); 4554 1.1 mrg 4555 1.1 mrg return number; 4556 1.1 mrg } 4557 1.1 mrg 4558 1.1 mrg 4559 1.1 mrg /* Allocate temporary for forall construct. SIZE is the size of temporary 4560 1.1 mrg needed. PTEMP1 is returned for space free. */ 4561 1.1 mrg 4562 1.1 mrg static tree 4563 1.1 mrg allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block, 4564 1.1 mrg tree * ptemp1) 4565 1.1 mrg { 4566 1.1 mrg tree bytesize; 4567 1.1 mrg tree unit; 4568 1.1 mrg tree tmp; 4569 1.1 mrg 4570 1.1 mrg unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type)); 4571 1.1 mrg if (!integer_onep (unit)) 4572 1.1 mrg bytesize = fold_build2_loc (input_location, MULT_EXPR, 4573 1.1 mrg gfc_array_index_type, size, unit); 4574 1.1 mrg else 4575 1.1 mrg bytesize = size; 4576 1.1 mrg 4577 1.1 mrg *ptemp1 = NULL; 4578 1.1 mrg tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type); 4579 1.1 mrg 4580 1.1 mrg if (*ptemp1) 4581 1.1 mrg tmp = build_fold_indirect_ref_loc (input_location, tmp); 4582 1.1 mrg return tmp; 4583 1.1 mrg } 4584 1.1 mrg 4585 1.1 mrg 4586 1.1 mrg /* Allocate temporary for forall construct according to the information in 4587 1.1 mrg nested_forall_info. INNER_SIZE is the size of temporary needed in the 4588 1.1 mrg assignment inside forall. PTEMP1 is returned for space free. */ 4589 1.1 mrg 4590 1.1 mrg static tree 4591 1.1 mrg allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type, 4592 1.1 mrg tree inner_size, stmtblock_t * inner_size_body, 4593 1.1 mrg stmtblock_t * block, tree * ptemp1) 4594 1.1 mrg { 4595 1.1 mrg tree size; 4596 1.1 mrg 4597 1.1 mrg /* Calculate the total size of temporary needed in forall construct. */ 4598 1.1 mrg size = compute_overall_iter_number (nested_forall_info, inner_size, 4599 1.1 mrg inner_size_body, block); 4600 1.1 mrg 4601 1.1 mrg return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1); 4602 1.1 mrg } 4603 1.1 mrg 4604 1.1 mrg 4605 1.1 mrg /* Handle assignments inside forall which need temporary. 4606 1.1 mrg 4607 1.1 mrg forall (i=start:end:stride; maskexpr) 4608 1.1 mrg e<i> = f<i> 4609 1.1 mrg end forall 4610 1.1 mrg (where e,f<i> are arbitrary expressions possibly involving i 4611 1.1 mrg and there is a dependency between e<i> and f<i>) 4612 1.1 mrg Translates to: 4613 1.1 mrg masktmp(:) = maskexpr(:) 4614 1.1 mrg 4615 1.1 mrg maskindex = 0; 4616 1.1 mrg count1 = 0; 4617 1.1 mrg num = 0; 4618 1.1 mrg for (i = start; i <= end; i += stride) 4619 1.1 mrg num += SIZE (f<i>) 4620 1.1 mrg count1 = 0; 4621 1.1 mrg ALLOCATE (tmp(num)) 4622 1.1 mrg for (i = start; i <= end; i += stride) 4623 1.1 mrg { 4624 1.1 mrg if (masktmp[maskindex++]) 4625 1.1 mrg tmp[count1++] = f<i> 4626 1.1 mrg } 4627 1.1 mrg maskindex = 0; 4628 1.1 mrg count1 = 0; 4629 1.1 mrg for (i = start; i <= end; i += stride) 4630 1.1 mrg { 4631 1.1 mrg if (masktmp[maskindex++]) 4632 1.1 mrg e<i> = tmp[count1++] 4633 1.1 mrg } 4634 1.1 mrg DEALLOCATE (tmp) 4635 1.1 mrg */ 4636 1.1 mrg static void 4637 1.1 mrg gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2, 4638 1.1 mrg tree wheremask, bool invert, 4639 1.1 mrg forall_info * nested_forall_info, 4640 1.1 mrg stmtblock_t * block) 4641 1.1 mrg { 4642 1.1 mrg tree type; 4643 1.1 mrg tree inner_size; 4644 1.1 mrg gfc_ss *lss, *rss; 4645 1.1 mrg tree count, count1; 4646 1.1 mrg tree tmp, tmp1; 4647 1.1 mrg tree ptemp1; 4648 1.1 mrg stmtblock_t inner_size_body; 4649 1.1 mrg 4650 1.1 mrg /* Create vars. count1 is the current iterator number of the nested 4651 1.1 mrg forall. */ 4652 1.1 mrg count1 = gfc_create_var (gfc_array_index_type, "count1"); 4653 1.1 mrg 4654 1.1 mrg /* Count is the wheremask index. */ 4655 1.1 mrg if (wheremask) 4656 1.1 mrg { 4657 1.1 mrg count = gfc_create_var (gfc_array_index_type, "count"); 4658 1.1 mrg gfc_add_modify (block, count, gfc_index_zero_node); 4659 1.1 mrg } 4660 1.1 mrg else 4661 1.1 mrg count = NULL; 4662 1.1 mrg 4663 1.1 mrg /* Initialize count1. */ 4664 1.1 mrg gfc_add_modify (block, count1, gfc_index_zero_node); 4665 1.1 mrg 4666 1.1 mrg /* Calculate the size of temporary needed in the assignment. Return loop, lss 4667 1.1 mrg and rss which are used in function generate_loop_for_rhs_to_temp(). */ 4668 1.1 mrg /* The type of LHS. Used in function allocate_temp_for_forall_nest */ 4669 1.1 mrg if (expr1->ts.type == BT_CHARACTER) 4670 1.1 mrg { 4671 1.1 mrg type = NULL; 4672 1.1 mrg if (expr1->ref && expr1->ref->type == REF_SUBSTRING) 4673 1.1 mrg { 4674 1.1 mrg gfc_se ssse; 4675 1.1 mrg gfc_init_se (&ssse, NULL); 4676 1.1 mrg gfc_conv_expr (&ssse, expr1); 4677 1.1 mrg type = gfc_get_character_type_len (gfc_default_character_kind, 4678 1.1 mrg ssse.string_length); 4679 1.1 mrg } 4680 1.1 mrg else 4681 1.1 mrg { 4682 1.1 mrg if (!expr1->ts.u.cl->backend_decl) 4683 1.1 mrg { 4684 1.1 mrg gfc_se tse; 4685 1.1 mrg gcc_assert (expr1->ts.u.cl->length); 4686 1.1 mrg gfc_init_se (&tse, NULL); 4687 1.1 mrg gfc_conv_expr (&tse, expr1->ts.u.cl->length); 4688 1.1 mrg expr1->ts.u.cl->backend_decl = tse.expr; 4689 1.1 mrg } 4690 1.1 mrg type = gfc_get_character_type_len (gfc_default_character_kind, 4691 1.1 mrg expr1->ts.u.cl->backend_decl); 4692 1.1 mrg } 4693 1.1 mrg } 4694 1.1 mrg else 4695 1.1 mrg type = gfc_typenode_for_spec (&expr1->ts); 4696 1.1 mrg 4697 1.1 mrg gfc_init_block (&inner_size_body); 4698 1.1 mrg inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body, 4699 1.1 mrg &lss, &rss); 4700 1.1 mrg 4701 1.1 mrg /* Allocate temporary for nested forall construct according to the 4702 1.1 mrg information in nested_forall_info and inner_size. */ 4703 1.1 mrg tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size, 4704 1.1 mrg &inner_size_body, block, &ptemp1); 4705 1.1 mrg 4706 1.1 mrg /* Generate codes to copy rhs to the temporary . */ 4707 1.1 mrg tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss, 4708 1.1 mrg wheremask, invert); 4709 1.1 mrg 4710 1.1 mrg /* Generate body and loops according to the information in 4711 1.1 mrg nested_forall_info. */ 4712 1.1 mrg tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1); 4713 1.1 mrg gfc_add_expr_to_block (block, tmp); 4714 1.1 mrg 4715 1.1 mrg /* Reset count1. */ 4716 1.1 mrg gfc_add_modify (block, count1, gfc_index_zero_node); 4717 1.1 mrg 4718 1.1 mrg /* Reset count. */ 4719 1.1 mrg if (wheremask) 4720 1.1 mrg gfc_add_modify (block, count, gfc_index_zero_node); 4721 1.1 mrg 4722 1.1 mrg /* TODO: Second call to compute_inner_temp_size to initialize lss and 4723 1.1 mrg rss; there must be a better way. */ 4724 1.1 mrg inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body, 4725 1.1 mrg &lss, &rss); 4726 1.1 mrg 4727 1.1 mrg /* Generate codes to copy the temporary to lhs. */ 4728 1.1 mrg tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1, 4729 1.1 mrg lss, rss, 4730 1.1 mrg wheremask, invert); 4731 1.1 mrg 4732 1.1 mrg /* Generate body and loops according to the information in 4733 1.1 mrg nested_forall_info. */ 4734 1.1 mrg tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1); 4735 1.1 mrg gfc_add_expr_to_block (block, tmp); 4736 1.1 mrg 4737 1.1 mrg if (ptemp1) 4738 1.1 mrg { 4739 1.1 mrg /* Free the temporary. */ 4740 1.1 mrg tmp = gfc_call_free (ptemp1); 4741 1.1 mrg gfc_add_expr_to_block (block, tmp); 4742 1.1 mrg } 4743 1.1 mrg } 4744 1.1 mrg 4745 1.1 mrg 4746 1.1 mrg /* Translate pointer assignment inside FORALL which need temporary. */ 4747 1.1 mrg 4748 1.1 mrg static void 4749 1.1 mrg gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2, 4750 1.1 mrg forall_info * nested_forall_info, 4751 1.1 mrg stmtblock_t * block) 4752 1.1 mrg { 4753 1.1 mrg tree type; 4754 1.1 mrg tree inner_size; 4755 1.1 mrg gfc_ss *lss, *rss; 4756 1.1 mrg gfc_se lse; 4757 1.1 mrg gfc_se rse; 4758 1.1 mrg gfc_array_info *info; 4759 1.1 mrg gfc_loopinfo loop; 4760 1.1 mrg tree desc; 4761 1.1 mrg tree parm; 4762 1.1 mrg tree parmtype; 4763 1.1 mrg stmtblock_t body; 4764 1.1 mrg tree count; 4765 1.1 mrg tree tmp, tmp1, ptemp1; 4766 1.1 mrg 4767 1.1 mrg count = gfc_create_var (gfc_array_index_type, "count"); 4768 1.1 mrg gfc_add_modify (block, count, gfc_index_zero_node); 4769 1.1 mrg 4770 1.1 mrg inner_size = gfc_index_one_node; 4771 1.1 mrg lss = gfc_walk_expr (expr1); 4772 1.1 mrg rss = gfc_walk_expr (expr2); 4773 1.1 mrg if (lss == gfc_ss_terminator) 4774 1.1 mrg { 4775 1.1 mrg type = gfc_typenode_for_spec (&expr1->ts); 4776 1.1 mrg type = build_pointer_type (type); 4777 1.1 mrg 4778 1.1 mrg /* Allocate temporary for nested forall construct according to the 4779 1.1 mrg information in nested_forall_info and inner_size. */ 4780 1.1 mrg tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, 4781 1.1 mrg inner_size, NULL, block, &ptemp1); 4782 1.1 mrg gfc_start_block (&body); 4783 1.1 mrg gfc_init_se (&lse, NULL); 4784 1.1 mrg lse.expr = gfc_build_array_ref (tmp1, count, NULL); 4785 1.1 mrg gfc_init_se (&rse, NULL); 4786 1.1 mrg rse.want_pointer = 1; 4787 1.1 mrg gfc_conv_expr (&rse, expr2); 4788 1.1 mrg gfc_add_block_to_block (&body, &rse.pre); 4789 1.1 mrg gfc_add_modify (&body, lse.expr, 4790 1.1 mrg fold_convert (TREE_TYPE (lse.expr), rse.expr)); 4791 1.1 mrg gfc_add_block_to_block (&body, &rse.post); 4792 1.1 mrg 4793 1.1 mrg /* Increment count. */ 4794 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 4795 1.1 mrg count, gfc_index_one_node); 4796 1.1 mrg gfc_add_modify (&body, count, tmp); 4797 1.1 mrg 4798 1.1 mrg tmp = gfc_finish_block (&body); 4799 1.1 mrg 4800 1.1 mrg /* Generate body and loops according to the information in 4801 1.1 mrg nested_forall_info. */ 4802 1.1 mrg tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1); 4803 1.1 mrg gfc_add_expr_to_block (block, tmp); 4804 1.1 mrg 4805 1.1 mrg /* Reset count. */ 4806 1.1 mrg gfc_add_modify (block, count, gfc_index_zero_node); 4807 1.1 mrg 4808 1.1 mrg gfc_start_block (&body); 4809 1.1 mrg gfc_init_se (&lse, NULL); 4810 1.1 mrg gfc_init_se (&rse, NULL); 4811 1.1 mrg rse.expr = gfc_build_array_ref (tmp1, count, NULL); 4812 1.1 mrg lse.want_pointer = 1; 4813 1.1 mrg gfc_conv_expr (&lse, expr1); 4814 1.1 mrg gfc_add_block_to_block (&body, &lse.pre); 4815 1.1 mrg gfc_add_modify (&body, lse.expr, rse.expr); 4816 1.1 mrg gfc_add_block_to_block (&body, &lse.post); 4817 1.1 mrg /* Increment count. */ 4818 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 4819 1.1 mrg count, gfc_index_one_node); 4820 1.1 mrg gfc_add_modify (&body, count, tmp); 4821 1.1 mrg tmp = gfc_finish_block (&body); 4822 1.1 mrg 4823 1.1 mrg /* Generate body and loops according to the information in 4824 1.1 mrg nested_forall_info. */ 4825 1.1 mrg tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1); 4826 1.1 mrg gfc_add_expr_to_block (block, tmp); 4827 1.1 mrg } 4828 1.1 mrg else 4829 1.1 mrg { 4830 1.1 mrg gfc_init_loopinfo (&loop); 4831 1.1 mrg 4832 1.1 mrg /* Associate the SS with the loop. */ 4833 1.1 mrg gfc_add_ss_to_loop (&loop, rss); 4834 1.1 mrg 4835 1.1 mrg /* Setup the scalarizing loops and bounds. */ 4836 1.1 mrg gfc_conv_ss_startstride (&loop); 4837 1.1 mrg 4838 1.1 mrg gfc_conv_loop_setup (&loop, &expr2->where); 4839 1.1 mrg 4840 1.1 mrg info = &rss->info->data.array; 4841 1.1 mrg desc = info->descriptor; 4842 1.1 mrg 4843 1.1 mrg /* Make a new descriptor. */ 4844 1.1 mrg parmtype = gfc_get_element_type (TREE_TYPE (desc)); 4845 1.1 mrg parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0, 4846 1.1 mrg loop.from, loop.to, 1, 4847 1.1 mrg GFC_ARRAY_UNKNOWN, true); 4848 1.1 mrg 4849 1.1 mrg /* Allocate temporary for nested forall construct. */ 4850 1.1 mrg tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype, 4851 1.1 mrg inner_size, NULL, block, &ptemp1); 4852 1.1 mrg gfc_start_block (&body); 4853 1.1 mrg gfc_init_se (&lse, NULL); 4854 1.1 mrg lse.expr = gfc_build_array_ref (tmp1, count, NULL); 4855 1.1 mrg lse.direct_byref = 1; 4856 1.1 mrg gfc_conv_expr_descriptor (&lse, expr2); 4857 1.1 mrg 4858 1.1 mrg gfc_add_block_to_block (&body, &lse.pre); 4859 1.1 mrg gfc_add_block_to_block (&body, &lse.post); 4860 1.1 mrg 4861 1.1 mrg /* Increment count. */ 4862 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 4863 1.1 mrg count, gfc_index_one_node); 4864 1.1 mrg gfc_add_modify (&body, count, tmp); 4865 1.1 mrg 4866 1.1 mrg tmp = gfc_finish_block (&body); 4867 1.1 mrg 4868 1.1 mrg /* Generate body and loops according to the information in 4869 1.1 mrg nested_forall_info. */ 4870 1.1 mrg tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1); 4871 1.1 mrg gfc_add_expr_to_block (block, tmp); 4872 1.1 mrg 4873 1.1 mrg /* Reset count. */ 4874 1.1 mrg gfc_add_modify (block, count, gfc_index_zero_node); 4875 1.1 mrg 4876 1.1 mrg parm = gfc_build_array_ref (tmp1, count, NULL); 4877 1.1 mrg gfc_init_se (&lse, NULL); 4878 1.1 mrg gfc_conv_expr_descriptor (&lse, expr1); 4879 1.1 mrg gfc_add_modify (&lse.pre, lse.expr, parm); 4880 1.1 mrg gfc_start_block (&body); 4881 1.1 mrg gfc_add_block_to_block (&body, &lse.pre); 4882 1.1 mrg gfc_add_block_to_block (&body, &lse.post); 4883 1.1 mrg 4884 1.1 mrg /* Increment count. */ 4885 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 4886 1.1 mrg count, gfc_index_one_node); 4887 1.1 mrg gfc_add_modify (&body, count, tmp); 4888 1.1 mrg 4889 1.1 mrg tmp = gfc_finish_block (&body); 4890 1.1 mrg 4891 1.1 mrg tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1); 4892 1.1 mrg gfc_add_expr_to_block (block, tmp); 4893 1.1 mrg } 4894 1.1 mrg /* Free the temporary. */ 4895 1.1 mrg if (ptemp1) 4896 1.1 mrg { 4897 1.1 mrg tmp = gfc_call_free (ptemp1); 4898 1.1 mrg gfc_add_expr_to_block (block, tmp); 4899 1.1 mrg } 4900 1.1 mrg } 4901 1.1 mrg 4902 1.1 mrg 4903 1.1 mrg /* FORALL and WHERE statements are really nasty, especially when you nest 4904 1.1 mrg them. All the rhs of a forall assignment must be evaluated before the 4905 1.1 mrg actual assignments are performed. Presumably this also applies to all the 4906 1.1 mrg assignments in an inner where statement. */ 4907 1.1 mrg 4908 1.1 mrg /* Generate code for a FORALL statement. Any temporaries are allocated as a 4909 1.1 mrg linear array, relying on the fact that we process in the same order in all 4910 1.1 mrg loops. 4911 1.1 mrg 4912 1.1 mrg forall (i=start:end:stride; maskexpr) 4913 1.1 mrg e<i> = f<i> 4914 1.1 mrg g<i> = h<i> 4915 1.1 mrg end forall 4916 1.1 mrg (where e,f,g,h<i> are arbitrary expressions possibly involving i) 4917 1.1 mrg Translates to: 4918 1.1 mrg count = ((end + 1 - start) / stride) 4919 1.1 mrg masktmp(:) = maskexpr(:) 4920 1.1 mrg 4921 1.1 mrg maskindex = 0; 4922 1.1 mrg for (i = start; i <= end; i += stride) 4923 1.1 mrg { 4924 1.1 mrg if (masktmp[maskindex++]) 4925 1.1 mrg e<i> = f<i> 4926 1.1 mrg } 4927 1.1 mrg maskindex = 0; 4928 1.1 mrg for (i = start; i <= end; i += stride) 4929 1.1 mrg { 4930 1.1 mrg if (masktmp[maskindex++]) 4931 1.1 mrg g<i> = h<i> 4932 1.1 mrg } 4933 1.1 mrg 4934 1.1 mrg Note that this code only works when there are no dependencies. 4935 1.1 mrg Forall loop with array assignments and data dependencies are a real pain, 4936 1.1 mrg because the size of the temporary cannot always be determined before the 4937 1.1 mrg loop is executed. This problem is compounded by the presence of nested 4938 1.1 mrg FORALL constructs. 4939 1.1 mrg */ 4940 1.1 mrg 4941 1.1 mrg static tree 4942 1.1 mrg gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) 4943 1.1 mrg { 4944 1.1 mrg stmtblock_t pre; 4945 1.1 mrg stmtblock_t post; 4946 1.1 mrg stmtblock_t block; 4947 1.1 mrg stmtblock_t body; 4948 1.1 mrg tree *var; 4949 1.1 mrg tree *start; 4950 1.1 mrg tree *end; 4951 1.1 mrg tree *step; 4952 1.1 mrg gfc_expr **varexpr; 4953 1.1 mrg tree tmp; 4954 1.1 mrg tree assign; 4955 1.1 mrg tree size; 4956 1.1 mrg tree maskindex; 4957 1.1 mrg tree mask; 4958 1.1 mrg tree pmask; 4959 1.1 mrg tree cycle_label = NULL_TREE; 4960 1.1 mrg int n; 4961 1.1 mrg int nvar; 4962 1.1 mrg int need_temp; 4963 1.1 mrg gfc_forall_iterator *fa; 4964 1.1 mrg gfc_se se; 4965 1.1 mrg gfc_code *c; 4966 1.1 mrg gfc_saved_var *saved_vars; 4967 1.1 mrg iter_info *this_forall; 4968 1.1 mrg forall_info *info; 4969 1.1 mrg bool need_mask; 4970 1.1 mrg 4971 1.1 mrg /* Do nothing if the mask is false. */ 4972 1.1 mrg if (code->expr1 4973 1.1 mrg && code->expr1->expr_type == EXPR_CONSTANT 4974 1.1 mrg && !code->expr1->value.logical) 4975 1.1 mrg return build_empty_stmt (input_location); 4976 1.1 mrg 4977 1.1 mrg n = 0; 4978 1.1 mrg /* Count the FORALL index number. */ 4979 1.1 mrg for (fa = code->ext.forall_iterator; fa; fa = fa->next) 4980 1.1 mrg n++; 4981 1.1 mrg nvar = n; 4982 1.1 mrg 4983 1.1 mrg /* Allocate the space for var, start, end, step, varexpr. */ 4984 1.1 mrg var = XCNEWVEC (tree, nvar); 4985 1.1 mrg start = XCNEWVEC (tree, nvar); 4986 1.1 mrg end = XCNEWVEC (tree, nvar); 4987 1.1 mrg step = XCNEWVEC (tree, nvar); 4988 1.1 mrg varexpr = XCNEWVEC (gfc_expr *, nvar); 4989 1.1 mrg saved_vars = XCNEWVEC (gfc_saved_var, nvar); 4990 1.1 mrg 4991 1.1 mrg /* Allocate the space for info. */ 4992 1.1 mrg info = XCNEW (forall_info); 4993 1.1 mrg 4994 1.1 mrg gfc_start_block (&pre); 4995 1.1 mrg gfc_init_block (&post); 4996 1.1 mrg gfc_init_block (&block); 4997 1.1 mrg 4998 1.1 mrg n = 0; 4999 1.1 mrg for (fa = code->ext.forall_iterator; fa; fa = fa->next) 5000 1.1 mrg { 5001 1.1 mrg gfc_symbol *sym = fa->var->symtree->n.sym; 5002 1.1 mrg 5003 1.1 mrg /* Allocate space for this_forall. */ 5004 1.1 mrg this_forall = XCNEW (iter_info); 5005 1.1 mrg 5006 1.1 mrg /* Create a temporary variable for the FORALL index. */ 5007 1.1 mrg tmp = gfc_typenode_for_spec (&sym->ts); 5008 1.1 mrg var[n] = gfc_create_var (tmp, sym->name); 5009 1.1 mrg gfc_shadow_sym (sym, var[n], &saved_vars[n]); 5010 1.1 mrg 5011 1.1 mrg /* Record it in this_forall. */ 5012 1.1 mrg this_forall->var = var[n]; 5013 1.1 mrg 5014 1.1 mrg /* Replace the index symbol's backend_decl with the temporary decl. */ 5015 1.1 mrg sym->backend_decl = var[n]; 5016 1.1 mrg 5017 1.1 mrg /* Work out the start, end and stride for the loop. */ 5018 1.1 mrg gfc_init_se (&se, NULL); 5019 1.1 mrg gfc_conv_expr_val (&se, fa->start); 5020 1.1 mrg /* Record it in this_forall. */ 5021 1.1 mrg this_forall->start = se.expr; 5022 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 5023 1.1 mrg start[n] = se.expr; 5024 1.1 mrg 5025 1.1 mrg gfc_init_se (&se, NULL); 5026 1.1 mrg gfc_conv_expr_val (&se, fa->end); 5027 1.1 mrg /* Record it in this_forall. */ 5028 1.1 mrg this_forall->end = se.expr; 5029 1.1 mrg gfc_make_safe_expr (&se); 5030 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 5031 1.1 mrg end[n] = se.expr; 5032 1.1 mrg 5033 1.1 mrg gfc_init_se (&se, NULL); 5034 1.1 mrg gfc_conv_expr_val (&se, fa->stride); 5035 1.1 mrg /* Record it in this_forall. */ 5036 1.1 mrg this_forall->step = se.expr; 5037 1.1 mrg gfc_make_safe_expr (&se); 5038 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 5039 1.1 mrg step[n] = se.expr; 5040 1.1 mrg 5041 1.1 mrg /* Set the NEXT field of this_forall to NULL. */ 5042 1.1 mrg this_forall->next = NULL; 5043 1.1 mrg /* Link this_forall to the info construct. */ 5044 1.1 mrg if (info->this_loop) 5045 1.1 mrg { 5046 1.1 mrg iter_info *iter_tmp = info->this_loop; 5047 1.1 mrg while (iter_tmp->next != NULL) 5048 1.1 mrg iter_tmp = iter_tmp->next; 5049 1.1 mrg iter_tmp->next = this_forall; 5050 1.1 mrg } 5051 1.1 mrg else 5052 1.1 mrg info->this_loop = this_forall; 5053 1.1 mrg 5054 1.1 mrg n++; 5055 1.1 mrg } 5056 1.1 mrg nvar = n; 5057 1.1 mrg 5058 1.1 mrg /* Calculate the size needed for the current forall level. */ 5059 1.1 mrg size = gfc_index_one_node; 5060 1.1 mrg for (n = 0; n < nvar; n++) 5061 1.1 mrg { 5062 1.1 mrg /* size = (end + step - start) / step. */ 5063 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]), 5064 1.1 mrg step[n], start[n]); 5065 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]), 5066 1.1 mrg end[n], tmp); 5067 1.1 mrg tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp), 5068 1.1 mrg tmp, step[n]); 5069 1.1 mrg tmp = convert (gfc_array_index_type, tmp); 5070 1.1 mrg 5071 1.1 mrg size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, 5072 1.1 mrg size, tmp); 5073 1.1 mrg } 5074 1.1 mrg 5075 1.1 mrg /* Record the nvar and size of current forall level. */ 5076 1.1 mrg info->nvar = nvar; 5077 1.1 mrg info->size = size; 5078 1.1 mrg 5079 1.1 mrg if (code->expr1) 5080 1.1 mrg { 5081 1.1 mrg /* If the mask is .true., consider the FORALL unconditional. */ 5082 1.1 mrg if (code->expr1->expr_type == EXPR_CONSTANT 5083 1.1 mrg && code->expr1->value.logical) 5084 1.1 mrg need_mask = false; 5085 1.1 mrg else 5086 1.1 mrg need_mask = true; 5087 1.1 mrg } 5088 1.1 mrg else 5089 1.1 mrg need_mask = false; 5090 1.1 mrg 5091 1.1 mrg /* First we need to allocate the mask. */ 5092 1.1 mrg if (need_mask) 5093 1.1 mrg { 5094 1.1 mrg /* As the mask array can be very big, prefer compact boolean types. */ 5095 1.1 mrg tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind); 5096 1.1 mrg mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type, 5097 1.1 mrg size, NULL, &block, &pmask); 5098 1.1 mrg maskindex = gfc_create_var_np (gfc_array_index_type, "mi"); 5099 1.1 mrg 5100 1.1 mrg /* Record them in the info structure. */ 5101 1.1 mrg info->maskindex = maskindex; 5102 1.1 mrg info->mask = mask; 5103 1.1 mrg } 5104 1.1 mrg else 5105 1.1 mrg { 5106 1.1 mrg /* No mask was specified. */ 5107 1.1 mrg maskindex = NULL_TREE; 5108 1.1 mrg mask = pmask = NULL_TREE; 5109 1.1 mrg } 5110 1.1 mrg 5111 1.1 mrg /* Link the current forall level to nested_forall_info. */ 5112 1.1 mrg info->prev_nest = nested_forall_info; 5113 1.1 mrg nested_forall_info = info; 5114 1.1 mrg 5115 1.1 mrg /* Copy the mask into a temporary variable if required. 5116 1.1 mrg For now we assume a mask temporary is needed. */ 5117 1.1 mrg if (need_mask) 5118 1.1 mrg { 5119 1.1 mrg /* As the mask array can be very big, prefer compact boolean types. */ 5120 1.1 mrg tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind); 5121 1.1 mrg 5122 1.1 mrg gfc_add_modify (&block, maskindex, gfc_index_zero_node); 5123 1.1 mrg 5124 1.1 mrg /* Start of mask assignment loop body. */ 5125 1.1 mrg gfc_start_block (&body); 5126 1.1 mrg 5127 1.1 mrg /* Evaluate the mask expression. */ 5128 1.1 mrg gfc_init_se (&se, NULL); 5129 1.1 mrg gfc_conv_expr_val (&se, code->expr1); 5130 1.1 mrg gfc_add_block_to_block (&body, &se.pre); 5131 1.1 mrg 5132 1.1 mrg /* Store the mask. */ 5133 1.1 mrg se.expr = convert (mask_type, se.expr); 5134 1.1 mrg 5135 1.1 mrg tmp = gfc_build_array_ref (mask, maskindex, NULL); 5136 1.1 mrg gfc_add_modify (&body, tmp, se.expr); 5137 1.1 mrg 5138 1.1 mrg /* Advance to the next mask element. */ 5139 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 5140 1.1 mrg maskindex, gfc_index_one_node); 5141 1.1 mrg gfc_add_modify (&body, maskindex, tmp); 5142 1.1 mrg 5143 1.1 mrg /* Generate the loops. */ 5144 1.1 mrg tmp = gfc_finish_block (&body); 5145 1.1 mrg tmp = gfc_trans_nested_forall_loop (info, tmp, 0); 5146 1.1 mrg gfc_add_expr_to_block (&block, tmp); 5147 1.1 mrg } 5148 1.1 mrg 5149 1.1 mrg if (code->op == EXEC_DO_CONCURRENT) 5150 1.1 mrg { 5151 1.1 mrg gfc_init_block (&body); 5152 1.1 mrg cycle_label = gfc_build_label_decl (NULL_TREE); 5153 1.1 mrg code->cycle_label = cycle_label; 5154 1.1 mrg tmp = gfc_trans_code (code->block->next); 5155 1.1 mrg gfc_add_expr_to_block (&body, tmp); 5156 1.1 mrg 5157 1.1 mrg if (TREE_USED (cycle_label)) 5158 1.1 mrg { 5159 1.1 mrg tmp = build1_v (LABEL_EXPR, cycle_label); 5160 1.1 mrg gfc_add_expr_to_block (&body, tmp); 5161 1.1 mrg } 5162 1.1 mrg 5163 1.1 mrg tmp = gfc_finish_block (&body); 5164 1.1 mrg nested_forall_info->do_concurrent = true; 5165 1.1 mrg tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1); 5166 1.1 mrg gfc_add_expr_to_block (&block, tmp); 5167 1.1 mrg goto done; 5168 1.1 mrg } 5169 1.1 mrg 5170 1.1 mrg c = code->block->next; 5171 1.1 mrg 5172 1.1 mrg /* TODO: loop merging in FORALL statements. */ 5173 1.1 mrg /* Now that we've got a copy of the mask, generate the assignment loops. */ 5174 1.1 mrg while (c) 5175 1.1 mrg { 5176 1.1 mrg switch (c->op) 5177 1.1 mrg { 5178 1.1 mrg case EXEC_ASSIGN: 5179 1.1 mrg /* A scalar or array assignment. DO the simple check for 5180 1.1 mrg lhs to rhs dependencies. These make a temporary for the 5181 1.1 mrg rhs and form a second forall block to copy to variable. */ 5182 1.1 mrg need_temp = check_forall_dependencies(c, &pre, &post); 5183 1.1 mrg 5184 1.1 mrg /* Temporaries due to array assignment data dependencies introduce 5185 1.1 mrg no end of problems. */ 5186 1.1 mrg if (need_temp || flag_test_forall_temp) 5187 1.1 mrg gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false, 5188 1.1 mrg nested_forall_info, &block); 5189 1.1 mrg else 5190 1.1 mrg { 5191 1.1 mrg /* Use the normal assignment copying routines. */ 5192 1.1 mrg assign = gfc_trans_assignment (c->expr1, c->expr2, false, true); 5193 1.1 mrg 5194 1.1 mrg /* Generate body and loops. */ 5195 1.1 mrg tmp = gfc_trans_nested_forall_loop (nested_forall_info, 5196 1.1 mrg assign, 1); 5197 1.1 mrg gfc_add_expr_to_block (&block, tmp); 5198 1.1 mrg } 5199 1.1 mrg 5200 1.1 mrg /* Cleanup any temporary symtrees that have been made to deal 5201 1.1 mrg with dependencies. */ 5202 1.1 mrg if (new_symtree) 5203 1.1 mrg cleanup_forall_symtrees (c); 5204 1.1 mrg 5205 1.1 mrg break; 5206 1.1 mrg 5207 1.1 mrg case EXEC_WHERE: 5208 1.1 mrg /* Translate WHERE or WHERE construct nested in FORALL. */ 5209 1.1 mrg gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block); 5210 1.1 mrg break; 5211 1.1 mrg 5212 1.1 mrg /* Pointer assignment inside FORALL. */ 5213 1.1 mrg case EXEC_POINTER_ASSIGN: 5214 1.1 mrg need_temp = gfc_check_dependency (c->expr1, c->expr2, 0); 5215 1.1 mrg /* Avoid cases where a temporary would never be needed and where 5216 1.1 mrg the temp code is guaranteed to fail. */ 5217 1.1 mrg if (need_temp 5218 1.1 mrg || (flag_test_forall_temp 5219 1.1 mrg && c->expr2->expr_type != EXPR_CONSTANT 5220 1.1 mrg && c->expr2->expr_type != EXPR_NULL)) 5221 1.1 mrg gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2, 5222 1.1 mrg nested_forall_info, &block); 5223 1.1 mrg else 5224 1.1 mrg { 5225 1.1 mrg /* Use the normal assignment copying routines. */ 5226 1.1 mrg assign = gfc_trans_pointer_assignment (c->expr1, c->expr2); 5227 1.1 mrg 5228 1.1 mrg /* Generate body and loops. */ 5229 1.1 mrg tmp = gfc_trans_nested_forall_loop (nested_forall_info, 5230 1.1 mrg assign, 1); 5231 1.1 mrg gfc_add_expr_to_block (&block, tmp); 5232 1.1 mrg } 5233 1.1 mrg break; 5234 1.1 mrg 5235 1.1 mrg case EXEC_FORALL: 5236 1.1 mrg tmp = gfc_trans_forall_1 (c, nested_forall_info); 5237 1.1 mrg gfc_add_expr_to_block (&block, tmp); 5238 1.1 mrg break; 5239 1.1 mrg 5240 1.1 mrg /* Explicit subroutine calls are prevented by the frontend but interface 5241 1.1 mrg assignments can legitimately produce them. */ 5242 1.1 mrg case EXEC_ASSIGN_CALL: 5243 1.1 mrg assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false); 5244 1.1 mrg tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1); 5245 1.1 mrg gfc_add_expr_to_block (&block, tmp); 5246 1.1 mrg break; 5247 1.1 mrg 5248 1.1 mrg default: 5249 1.1 mrg gcc_unreachable (); 5250 1.1 mrg } 5251 1.1 mrg 5252 1.1 mrg c = c->next; 5253 1.1 mrg } 5254 1.1 mrg 5255 1.1 mrg done: 5256 1.1 mrg /* Restore the original index variables. */ 5257 1.1 mrg for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++) 5258 1.1 mrg gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]); 5259 1.1 mrg 5260 1.1 mrg /* Free the space for var, start, end, step, varexpr. */ 5261 1.1 mrg free (var); 5262 1.1 mrg free (start); 5263 1.1 mrg free (end); 5264 1.1 mrg free (step); 5265 1.1 mrg free (varexpr); 5266 1.1 mrg free (saved_vars); 5267 1.1 mrg 5268 1.1 mrg for (this_forall = info->this_loop; this_forall;) 5269 1.1 mrg { 5270 1.1 mrg iter_info *next = this_forall->next; 5271 1.1 mrg free (this_forall); 5272 1.1 mrg this_forall = next; 5273 1.1 mrg } 5274 1.1 mrg 5275 1.1 mrg /* Free the space for this forall_info. */ 5276 1.1 mrg free (info); 5277 1.1 mrg 5278 1.1 mrg if (pmask) 5279 1.1 mrg { 5280 1.1 mrg /* Free the temporary for the mask. */ 5281 1.1 mrg tmp = gfc_call_free (pmask); 5282 1.1 mrg gfc_add_expr_to_block (&block, tmp); 5283 1.1 mrg } 5284 1.1 mrg if (maskindex) 5285 1.1 mrg pushdecl (maskindex); 5286 1.1 mrg 5287 1.1 mrg gfc_add_block_to_block (&pre, &block); 5288 1.1 mrg gfc_add_block_to_block (&pre, &post); 5289 1.1 mrg 5290 1.1 mrg return gfc_finish_block (&pre); 5291 1.1 mrg } 5292 1.1 mrg 5293 1.1 mrg 5294 1.1 mrg /* Translate the FORALL statement or construct. */ 5295 1.1 mrg 5296 1.1 mrg tree gfc_trans_forall (gfc_code * code) 5297 1.1 mrg { 5298 1.1 mrg return gfc_trans_forall_1 (code, NULL); 5299 1.1 mrg } 5300 1.1 mrg 5301 1.1 mrg 5302 1.1 mrg /* Translate the DO CONCURRENT construct. */ 5303 1.1 mrg 5304 1.1 mrg tree gfc_trans_do_concurrent (gfc_code * code) 5305 1.1 mrg { 5306 1.1 mrg return gfc_trans_forall_1 (code, NULL); 5307 1.1 mrg } 5308 1.1 mrg 5309 1.1 mrg 5310 1.1 mrg /* Evaluate the WHERE mask expression, copy its value to a temporary. 5311 1.1 mrg If the WHERE construct is nested in FORALL, compute the overall temporary 5312 1.1 mrg needed by the WHERE mask expression multiplied by the iterator number of 5313 1.1 mrg the nested forall. 5314 1.1 mrg ME is the WHERE mask expression. 5315 1.1 mrg MASK is the current execution mask upon input, whose sense may or may 5316 1.1 mrg not be inverted as specified by the INVERT argument. 5317 1.1 mrg CMASK is the updated execution mask on output, or NULL if not required. 5318 1.1 mrg PMASK is the pending execution mask on output, or NULL if not required. 5319 1.1 mrg BLOCK is the block in which to place the condition evaluation loops. */ 5320 1.1 mrg 5321 1.1 mrg static void 5322 1.1 mrg gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info, 5323 1.1 mrg tree mask, bool invert, tree cmask, tree pmask, 5324 1.1 mrg tree mask_type, stmtblock_t * block) 5325 1.1 mrg { 5326 1.1 mrg tree tmp, tmp1; 5327 1.1 mrg gfc_ss *lss, *rss; 5328 1.1 mrg gfc_loopinfo loop; 5329 1.1 mrg stmtblock_t body, body1; 5330 1.1 mrg tree count, cond, mtmp; 5331 1.1 mrg gfc_se lse, rse; 5332 1.1 mrg 5333 1.1 mrg gfc_init_loopinfo (&loop); 5334 1.1 mrg 5335 1.1 mrg lss = gfc_walk_expr (me); 5336 1.1 mrg rss = gfc_walk_expr (me); 5337 1.1 mrg 5338 1.1 mrg /* Variable to index the temporary. */ 5339 1.1 mrg count = gfc_create_var (gfc_array_index_type, "count"); 5340 1.1 mrg /* Initialize count. */ 5341 1.1 mrg gfc_add_modify (block, count, gfc_index_zero_node); 5342 1.1 mrg 5343 1.1 mrg gfc_start_block (&body); 5344 1.1 mrg 5345 1.1 mrg gfc_init_se (&rse, NULL); 5346 1.1 mrg gfc_init_se (&lse, NULL); 5347 1.1 mrg 5348 1.1 mrg if (lss == gfc_ss_terminator) 5349 1.1 mrg { 5350 1.1 mrg gfc_init_block (&body1); 5351 1.1 mrg } 5352 1.1 mrg else 5353 1.1 mrg { 5354 1.1 mrg /* Initialize the loop. */ 5355 1.1 mrg gfc_init_loopinfo (&loop); 5356 1.1 mrg 5357 1.1 mrg /* We may need LSS to determine the shape of the expression. */ 5358 1.1 mrg gfc_add_ss_to_loop (&loop, lss); 5359 1.1 mrg gfc_add_ss_to_loop (&loop, rss); 5360 1.1 mrg 5361 1.1 mrg gfc_conv_ss_startstride (&loop); 5362 1.1 mrg gfc_conv_loop_setup (&loop, &me->where); 5363 1.1 mrg 5364 1.1 mrg gfc_mark_ss_chain_used (rss, 1); 5365 1.1 mrg /* Start the loop body. */ 5366 1.1 mrg gfc_start_scalarized_body (&loop, &body1); 5367 1.1 mrg 5368 1.1 mrg /* Translate the expression. */ 5369 1.1 mrg gfc_copy_loopinfo_to_se (&rse, &loop); 5370 1.1 mrg rse.ss = rss; 5371 1.1 mrg gfc_conv_expr (&rse, me); 5372 1.1 mrg } 5373 1.1 mrg 5374 1.1 mrg /* Variable to evaluate mask condition. */ 5375 1.1 mrg cond = gfc_create_var (mask_type, "cond"); 5376 1.1 mrg if (mask && (cmask || pmask)) 5377 1.1 mrg mtmp = gfc_create_var (mask_type, "mask"); 5378 1.1 mrg else mtmp = NULL_TREE; 5379 1.1 mrg 5380 1.1 mrg gfc_add_block_to_block (&body1, &lse.pre); 5381 1.1 mrg gfc_add_block_to_block (&body1, &rse.pre); 5382 1.1 mrg 5383 1.1 mrg gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr)); 5384 1.1 mrg 5385 1.1 mrg if (mask && (cmask || pmask)) 5386 1.1 mrg { 5387 1.1 mrg tmp = gfc_build_array_ref (mask, count, NULL); 5388 1.1 mrg if (invert) 5389 1.1 mrg tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp); 5390 1.1 mrg gfc_add_modify (&body1, mtmp, tmp); 5391 1.1 mrg } 5392 1.1 mrg 5393 1.1 mrg if (cmask) 5394 1.1 mrg { 5395 1.1 mrg tmp1 = gfc_build_array_ref (cmask, count, NULL); 5396 1.1 mrg tmp = cond; 5397 1.1 mrg if (mask) 5398 1.1 mrg tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, 5399 1.1 mrg mtmp, tmp); 5400 1.1 mrg gfc_add_modify (&body1, tmp1, tmp); 5401 1.1 mrg } 5402 1.1 mrg 5403 1.1 mrg if (pmask) 5404 1.1 mrg { 5405 1.1 mrg tmp1 = gfc_build_array_ref (pmask, count, NULL); 5406 1.1 mrg tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond); 5407 1.1 mrg if (mask) 5408 1.1 mrg tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp, 5409 1.1 mrg tmp); 5410 1.1 mrg gfc_add_modify (&body1, tmp1, tmp); 5411 1.1 mrg } 5412 1.1 mrg 5413 1.1 mrg gfc_add_block_to_block (&body1, &lse.post); 5414 1.1 mrg gfc_add_block_to_block (&body1, &rse.post); 5415 1.1 mrg 5416 1.1 mrg if (lss == gfc_ss_terminator) 5417 1.1 mrg { 5418 1.1 mrg gfc_add_block_to_block (&body, &body1); 5419 1.1 mrg } 5420 1.1 mrg else 5421 1.1 mrg { 5422 1.1 mrg /* Increment count. */ 5423 1.1 mrg tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 5424 1.1 mrg count, gfc_index_one_node); 5425 1.1 mrg gfc_add_modify (&body1, count, tmp1); 5426 1.1 mrg 5427 1.1 mrg /* Generate the copying loops. */ 5428 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body1); 5429 1.1 mrg 5430 1.1 mrg gfc_add_block_to_block (&body, &loop.pre); 5431 1.1 mrg gfc_add_block_to_block (&body, &loop.post); 5432 1.1 mrg 5433 1.1 mrg gfc_cleanup_loop (&loop); 5434 1.1 mrg /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful 5435 1.1 mrg as tree nodes in SS may not be valid in different scope. */ 5436 1.1 mrg } 5437 1.1 mrg 5438 1.1 mrg tmp1 = gfc_finish_block (&body); 5439 1.1 mrg /* If the WHERE construct is inside FORALL, fill the full temporary. */ 5440 1.1 mrg if (nested_forall_info != NULL) 5441 1.1 mrg tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1); 5442 1.1 mrg 5443 1.1 mrg gfc_add_expr_to_block (block, tmp1); 5444 1.1 mrg } 5445 1.1 mrg 5446 1.1 mrg 5447 1.1 mrg /* Translate an assignment statement in a WHERE statement or construct 5448 1.1 mrg statement. The MASK expression is used to control which elements 5449 1.1 mrg of EXPR1 shall be assigned. The sense of MASK is specified by 5450 1.1 mrg INVERT. */ 5451 1.1 mrg 5452 1.1 mrg static tree 5453 1.1 mrg gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2, 5454 1.1 mrg tree mask, bool invert, 5455 1.1 mrg tree count1, tree count2, 5456 1.1 mrg gfc_code *cnext) 5457 1.1 mrg { 5458 1.1 mrg gfc_se lse; 5459 1.1 mrg gfc_se rse; 5460 1.1 mrg gfc_ss *lss; 5461 1.1 mrg gfc_ss *lss_section; 5462 1.1 mrg gfc_ss *rss; 5463 1.1 mrg 5464 1.1 mrg gfc_loopinfo loop; 5465 1.1 mrg tree tmp; 5466 1.1 mrg stmtblock_t block; 5467 1.1 mrg stmtblock_t body; 5468 1.1 mrg tree index, maskexpr; 5469 1.1 mrg 5470 1.1 mrg /* A defined assignment. */ 5471 1.1 mrg if (cnext && cnext->resolved_sym) 5472 1.1 mrg return gfc_trans_call (cnext, true, mask, count1, invert); 5473 1.1 mrg 5474 1.1 mrg #if 0 5475 1.1 mrg /* TODO: handle this special case. 5476 1.1 mrg Special case a single function returning an array. */ 5477 1.1 mrg if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0) 5478 1.1 mrg { 5479 1.1 mrg tmp = gfc_trans_arrayfunc_assign (expr1, expr2); 5480 1.1 mrg if (tmp) 5481 1.1 mrg return tmp; 5482 1.1 mrg } 5483 1.1 mrg #endif 5484 1.1 mrg 5485 1.1 mrg /* Assignment of the form lhs = rhs. */ 5486 1.1 mrg gfc_start_block (&block); 5487 1.1 mrg 5488 1.1 mrg gfc_init_se (&lse, NULL); 5489 1.1 mrg gfc_init_se (&rse, NULL); 5490 1.1 mrg 5491 1.1 mrg /* Walk the lhs. */ 5492 1.1 mrg lss = gfc_walk_expr (expr1); 5493 1.1 mrg rss = NULL; 5494 1.1 mrg 5495 1.1 mrg /* In each where-assign-stmt, the mask-expr and the variable being 5496 1.1 mrg defined shall be arrays of the same shape. */ 5497 1.1 mrg gcc_assert (lss != gfc_ss_terminator); 5498 1.1 mrg 5499 1.1 mrg /* The assignment needs scalarization. */ 5500 1.1 mrg lss_section = lss; 5501 1.1 mrg 5502 1.1 mrg /* Find a non-scalar SS from the lhs. */ 5503 1.1 mrg while (lss_section != gfc_ss_terminator 5504 1.1 mrg && lss_section->info->type != GFC_SS_SECTION) 5505 1.1 mrg lss_section = lss_section->next; 5506 1.1 mrg 5507 1.1 mrg gcc_assert (lss_section != gfc_ss_terminator); 5508 1.1 mrg 5509 1.1 mrg /* Initialize the scalarizer. */ 5510 1.1 mrg gfc_init_loopinfo (&loop); 5511 1.1 mrg 5512 1.1 mrg /* Walk the rhs. */ 5513 1.1 mrg rss = gfc_walk_expr (expr2); 5514 1.1 mrg if (rss == gfc_ss_terminator) 5515 1.1 mrg { 5516 1.1 mrg /* The rhs is scalar. Add a ss for the expression. */ 5517 1.1 mrg rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2); 5518 1.1 mrg rss->info->where = 1; 5519 1.1 mrg } 5520 1.1 mrg 5521 1.1 mrg /* Associate the SS with the loop. */ 5522 1.1 mrg gfc_add_ss_to_loop (&loop, lss); 5523 1.1 mrg gfc_add_ss_to_loop (&loop, rss); 5524 1.1 mrg 5525 1.1 mrg /* Calculate the bounds of the scalarization. */ 5526 1.1 mrg gfc_conv_ss_startstride (&loop); 5527 1.1 mrg 5528 1.1 mrg /* Resolve any data dependencies in the statement. */ 5529 1.1 mrg gfc_conv_resolve_dependencies (&loop, lss_section, rss); 5530 1.1 mrg 5531 1.1 mrg /* Setup the scalarizing loops. */ 5532 1.1 mrg gfc_conv_loop_setup (&loop, &expr2->where); 5533 1.1 mrg 5534 1.1 mrg /* Setup the gfc_se structures. */ 5535 1.1 mrg gfc_copy_loopinfo_to_se (&lse, &loop); 5536 1.1 mrg gfc_copy_loopinfo_to_se (&rse, &loop); 5537 1.1 mrg 5538 1.1 mrg rse.ss = rss; 5539 1.1 mrg gfc_mark_ss_chain_used (rss, 1); 5540 1.1 mrg if (loop.temp_ss == NULL) 5541 1.1 mrg { 5542 1.1 mrg lse.ss = lss; 5543 1.1 mrg gfc_mark_ss_chain_used (lss, 1); 5544 1.1 mrg } 5545 1.1 mrg else 5546 1.1 mrg { 5547 1.1 mrg lse.ss = loop.temp_ss; 5548 1.1 mrg gfc_mark_ss_chain_used (lss, 3); 5549 1.1 mrg gfc_mark_ss_chain_used (loop.temp_ss, 3); 5550 1.1 mrg } 5551 1.1 mrg 5552 1.1 mrg /* Start the scalarized loop body. */ 5553 1.1 mrg gfc_start_scalarized_body (&loop, &body); 5554 1.1 mrg 5555 1.1 mrg /* Translate the expression. */ 5556 1.1 mrg gfc_conv_expr (&rse, expr2); 5557 1.1 mrg if (lss != gfc_ss_terminator && loop.temp_ss != NULL) 5558 1.1 mrg gfc_conv_tmp_array_ref (&lse); 5559 1.1 mrg else 5560 1.1 mrg gfc_conv_expr (&lse, expr1); 5561 1.1 mrg 5562 1.1 mrg /* Form the mask expression according to the mask. */ 5563 1.1 mrg index = count1; 5564 1.1 mrg maskexpr = gfc_build_array_ref (mask, index, NULL); 5565 1.1 mrg if (invert) 5566 1.1 mrg maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR, 5567 1.1 mrg TREE_TYPE (maskexpr), maskexpr); 5568 1.1 mrg 5569 1.1 mrg /* Use the scalar assignment as is. */ 5570 1.1 mrg tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, 5571 1.1 mrg false, loop.temp_ss == NULL); 5572 1.1 mrg 5573 1.1 mrg tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location)); 5574 1.1 mrg 5575 1.1 mrg gfc_add_expr_to_block (&body, tmp); 5576 1.1 mrg 5577 1.1 mrg if (lss == gfc_ss_terminator) 5578 1.1 mrg { 5579 1.1 mrg /* Increment count1. */ 5580 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 5581 1.1 mrg count1, gfc_index_one_node); 5582 1.1 mrg gfc_add_modify (&body, count1, tmp); 5583 1.1 mrg 5584 1.1 mrg /* Use the scalar assignment as is. */ 5585 1.1 mrg gfc_add_block_to_block (&block, &body); 5586 1.1 mrg } 5587 1.1 mrg else 5588 1.1 mrg { 5589 1.1 mrg gcc_assert (lse.ss == gfc_ss_terminator 5590 1.1 mrg && rse.ss == gfc_ss_terminator); 5591 1.1 mrg 5592 1.1 mrg if (loop.temp_ss != NULL) 5593 1.1 mrg { 5594 1.1 mrg /* Increment count1 before finish the main body of a scalarized 5595 1.1 mrg expression. */ 5596 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, 5597 1.1 mrg gfc_array_index_type, count1, gfc_index_one_node); 5598 1.1 mrg gfc_add_modify (&body, count1, tmp); 5599 1.1 mrg gfc_trans_scalarized_loop_boundary (&loop, &body); 5600 1.1 mrg 5601 1.1 mrg /* We need to copy the temporary to the actual lhs. */ 5602 1.1 mrg gfc_init_se (&lse, NULL); 5603 1.1 mrg gfc_init_se (&rse, NULL); 5604 1.1 mrg gfc_copy_loopinfo_to_se (&lse, &loop); 5605 1.1 mrg gfc_copy_loopinfo_to_se (&rse, &loop); 5606 1.1 mrg 5607 1.1 mrg rse.ss = loop.temp_ss; 5608 1.1 mrg lse.ss = lss; 5609 1.1 mrg 5610 1.1 mrg gfc_conv_tmp_array_ref (&rse); 5611 1.1 mrg gfc_conv_expr (&lse, expr1); 5612 1.1 mrg 5613 1.1 mrg gcc_assert (lse.ss == gfc_ss_terminator 5614 1.1 mrg && rse.ss == gfc_ss_terminator); 5615 1.1 mrg 5616 1.1 mrg /* Form the mask expression according to the mask tree list. */ 5617 1.1 mrg index = count2; 5618 1.1 mrg maskexpr = gfc_build_array_ref (mask, index, NULL); 5619 1.1 mrg if (invert) 5620 1.1 mrg maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR, 5621 1.1 mrg TREE_TYPE (maskexpr), maskexpr); 5622 1.1 mrg 5623 1.1 mrg /* Use the scalar assignment as is. */ 5624 1.1 mrg tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, true); 5625 1.1 mrg tmp = build3_v (COND_EXPR, maskexpr, tmp, 5626 1.1 mrg build_empty_stmt (input_location)); 5627 1.1 mrg gfc_add_expr_to_block (&body, tmp); 5628 1.1 mrg 5629 1.1 mrg /* Increment count2. */ 5630 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, 5631 1.1 mrg gfc_array_index_type, count2, 5632 1.1 mrg gfc_index_one_node); 5633 1.1 mrg gfc_add_modify (&body, count2, tmp); 5634 1.1 mrg } 5635 1.1 mrg else 5636 1.1 mrg { 5637 1.1 mrg /* Increment count1. */ 5638 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, 5639 1.1 mrg gfc_array_index_type, count1, 5640 1.1 mrg gfc_index_one_node); 5641 1.1 mrg gfc_add_modify (&body, count1, tmp); 5642 1.1 mrg } 5643 1.1 mrg 5644 1.1 mrg /* Generate the copying loops. */ 5645 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body); 5646 1.1 mrg 5647 1.1 mrg /* Wrap the whole thing up. */ 5648 1.1 mrg gfc_add_block_to_block (&block, &loop.pre); 5649 1.1 mrg gfc_add_block_to_block (&block, &loop.post); 5650 1.1 mrg gfc_cleanup_loop (&loop); 5651 1.1 mrg } 5652 1.1 mrg 5653 1.1 mrg return gfc_finish_block (&block); 5654 1.1 mrg } 5655 1.1 mrg 5656 1.1 mrg 5657 1.1 mrg /* Translate the WHERE construct or statement. 5658 1.1 mrg This function can be called iteratively to translate the nested WHERE 5659 1.1 mrg construct or statement. 5660 1.1 mrg MASK is the control mask. */ 5661 1.1 mrg 5662 1.1 mrg static void 5663 1.1 mrg gfc_trans_where_2 (gfc_code * code, tree mask, bool invert, 5664 1.1 mrg forall_info * nested_forall_info, stmtblock_t * block) 5665 1.1 mrg { 5666 1.1 mrg stmtblock_t inner_size_body; 5667 1.1 mrg tree inner_size, size; 5668 1.1 mrg gfc_ss *lss, *rss; 5669 1.1 mrg tree mask_type; 5670 1.1 mrg gfc_expr *expr1; 5671 1.1 mrg gfc_expr *expr2; 5672 1.1 mrg gfc_code *cblock; 5673 1.1 mrg gfc_code *cnext; 5674 1.1 mrg tree tmp; 5675 1.1 mrg tree cond; 5676 1.1 mrg tree count1, count2; 5677 1.1 mrg bool need_cmask; 5678 1.1 mrg bool need_pmask; 5679 1.1 mrg int need_temp; 5680 1.1 mrg tree pcmask = NULL_TREE; 5681 1.1 mrg tree ppmask = NULL_TREE; 5682 1.1 mrg tree cmask = NULL_TREE; 5683 1.1 mrg tree pmask = NULL_TREE; 5684 1.1 mrg gfc_actual_arglist *arg; 5685 1.1 mrg 5686 1.1 mrg /* the WHERE statement or the WHERE construct statement. */ 5687 1.1 mrg cblock = code->block; 5688 1.1 mrg 5689 1.1 mrg /* As the mask array can be very big, prefer compact boolean types. */ 5690 1.1 mrg mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind); 5691 1.1 mrg 5692 1.1 mrg /* Determine which temporary masks are needed. */ 5693 1.1 mrg if (!cblock->block) 5694 1.1 mrg { 5695 1.1 mrg /* One clause: No ELSEWHEREs. */ 5696 1.1 mrg need_cmask = (cblock->next != 0); 5697 1.1 mrg need_pmask = false; 5698 1.1 mrg } 5699 1.1 mrg else if (cblock->block->block) 5700 1.1 mrg { 5701 1.1 mrg /* Three or more clauses: Conditional ELSEWHEREs. */ 5702 1.1 mrg need_cmask = true; 5703 1.1 mrg need_pmask = true; 5704 1.1 mrg } 5705 1.1 mrg else if (cblock->next) 5706 1.1 mrg { 5707 1.1 mrg /* Two clauses, the first non-empty. */ 5708 1.1 mrg need_cmask = true; 5709 1.1 mrg need_pmask = (mask != NULL_TREE 5710 1.1 mrg && cblock->block->next != 0); 5711 1.1 mrg } 5712 1.1 mrg else if (!cblock->block->next) 5713 1.1 mrg { 5714 1.1 mrg /* Two clauses, both empty. */ 5715 1.1 mrg need_cmask = false; 5716 1.1 mrg need_pmask = false; 5717 1.1 mrg } 5718 1.1 mrg /* Two clauses, the first empty, the second non-empty. */ 5719 1.1 mrg else if (mask) 5720 1.1 mrg { 5721 1.1 mrg need_cmask = (cblock->block->expr1 != 0); 5722 1.1 mrg need_pmask = true; 5723 1.1 mrg } 5724 1.1 mrg else 5725 1.1 mrg { 5726 1.1 mrg need_cmask = true; 5727 1.1 mrg need_pmask = false; 5728 1.1 mrg } 5729 1.1 mrg 5730 1.1 mrg if (need_cmask || need_pmask) 5731 1.1 mrg { 5732 1.1 mrg /* Calculate the size of temporary needed by the mask-expr. */ 5733 1.1 mrg gfc_init_block (&inner_size_body); 5734 1.1 mrg inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1, 5735 1.1 mrg &inner_size_body, &lss, &rss); 5736 1.1 mrg 5737 1.1 mrg gfc_free_ss_chain (lss); 5738 1.1 mrg gfc_free_ss_chain (rss); 5739 1.1 mrg 5740 1.1 mrg /* Calculate the total size of temporary needed. */ 5741 1.1 mrg size = compute_overall_iter_number (nested_forall_info, inner_size, 5742 1.1 mrg &inner_size_body, block); 5743 1.1 mrg 5744 1.1 mrg /* Check whether the size is negative. */ 5745 1.1 mrg cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, size, 5746 1.1 mrg gfc_index_zero_node); 5747 1.1 mrg size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, 5748 1.1 mrg cond, gfc_index_zero_node, size); 5749 1.1 mrg size = gfc_evaluate_now (size, block); 5750 1.1 mrg 5751 1.1 mrg /* Allocate temporary for WHERE mask if needed. */ 5752 1.1 mrg if (need_cmask) 5753 1.1 mrg cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block, 5754 1.1 mrg &pcmask); 5755 1.1 mrg 5756 1.1 mrg /* Allocate temporary for !mask if needed. */ 5757 1.1 mrg if (need_pmask) 5758 1.1 mrg pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block, 5759 1.1 mrg &ppmask); 5760 1.1 mrg } 5761 1.1 mrg 5762 1.1 mrg while (cblock) 5763 1.1 mrg { 5764 1.1 mrg /* Each time around this loop, the where clause is conditional 5765 1.1 mrg on the value of mask and invert, which are updated at the 5766 1.1 mrg bottom of the loop. */ 5767 1.1 mrg 5768 1.1 mrg /* Has mask-expr. */ 5769 1.1 mrg if (cblock->expr1) 5770 1.1 mrg { 5771 1.1 mrg /* Ensure that the WHERE mask will be evaluated exactly once. 5772 1.1 mrg If there are no statements in this WHERE/ELSEWHERE clause, 5773 1.1 mrg then we don't need to update the control mask (cmask). 5774 1.1 mrg If this is the last clause of the WHERE construct, then 5775 1.1 mrg we don't need to update the pending control mask (pmask). */ 5776 1.1 mrg if (mask) 5777 1.1 mrg gfc_evaluate_where_mask (cblock->expr1, nested_forall_info, 5778 1.1 mrg mask, invert, 5779 1.1 mrg cblock->next ? cmask : NULL_TREE, 5780 1.1 mrg cblock->block ? pmask : NULL_TREE, 5781 1.1 mrg mask_type, block); 5782 1.1 mrg else 5783 1.1 mrg gfc_evaluate_where_mask (cblock->expr1, nested_forall_info, 5784 1.1 mrg NULL_TREE, false, 5785 1.1 mrg (cblock->next || cblock->block) 5786 1.1 mrg ? cmask : NULL_TREE, 5787 1.1 mrg NULL_TREE, mask_type, block); 5788 1.1 mrg 5789 1.1 mrg invert = false; 5790 1.1 mrg } 5791 1.1 mrg /* It's a final elsewhere-stmt. No mask-expr is present. */ 5792 1.1 mrg else 5793 1.1 mrg cmask = mask; 5794 1.1 mrg 5795 1.1 mrg /* The body of this where clause are controlled by cmask with 5796 1.1 mrg sense specified by invert. */ 5797 1.1 mrg 5798 1.1 mrg /* Get the assignment statement of a WHERE statement, or the first 5799 1.1 mrg statement in where-body-construct of a WHERE construct. */ 5800 1.1 mrg cnext = cblock->next; 5801 1.1 mrg while (cnext) 5802 1.1 mrg { 5803 1.1 mrg switch (cnext->op) 5804 1.1 mrg { 5805 1.1 mrg /* WHERE assignment statement. */ 5806 1.1 mrg case EXEC_ASSIGN_CALL: 5807 1.1 mrg 5808 1.1 mrg arg = cnext->ext.actual; 5809 1.1 mrg expr1 = expr2 = NULL; 5810 1.1 mrg for (; arg; arg = arg->next) 5811 1.1 mrg { 5812 1.1 mrg if (!arg->expr) 5813 1.1 mrg continue; 5814 1.1 mrg if (expr1 == NULL) 5815 1.1 mrg expr1 = arg->expr; 5816 1.1 mrg else 5817 1.1 mrg expr2 = arg->expr; 5818 1.1 mrg } 5819 1.1 mrg goto evaluate; 5820 1.1 mrg 5821 1.1 mrg case EXEC_ASSIGN: 5822 1.1 mrg expr1 = cnext->expr1; 5823 1.1 mrg expr2 = cnext->expr2; 5824 1.1 mrg evaluate: 5825 1.1 mrg if (nested_forall_info != NULL) 5826 1.1 mrg { 5827 1.1 mrg need_temp = gfc_check_dependency (expr1, expr2, 0); 5828 1.1 mrg if ((need_temp || flag_test_forall_temp) 5829 1.1 mrg && cnext->op != EXEC_ASSIGN_CALL) 5830 1.1 mrg gfc_trans_assign_need_temp (expr1, expr2, 5831 1.1 mrg cmask, invert, 5832 1.1 mrg nested_forall_info, block); 5833 1.1 mrg else 5834 1.1 mrg { 5835 1.1 mrg /* Variables to control maskexpr. */ 5836 1.1 mrg count1 = gfc_create_var (gfc_array_index_type, "count1"); 5837 1.1 mrg count2 = gfc_create_var (gfc_array_index_type, "count2"); 5838 1.1 mrg gfc_add_modify (block, count1, gfc_index_zero_node); 5839 1.1 mrg gfc_add_modify (block, count2, gfc_index_zero_node); 5840 1.1 mrg 5841 1.1 mrg tmp = gfc_trans_where_assign (expr1, expr2, 5842 1.1 mrg cmask, invert, 5843 1.1 mrg count1, count2, 5844 1.1 mrg cnext); 5845 1.1 mrg 5846 1.1 mrg tmp = gfc_trans_nested_forall_loop (nested_forall_info, 5847 1.1 mrg tmp, 1); 5848 1.1 mrg gfc_add_expr_to_block (block, tmp); 5849 1.1 mrg } 5850 1.1 mrg } 5851 1.1 mrg else 5852 1.1 mrg { 5853 1.1 mrg /* Variables to control maskexpr. */ 5854 1.1 mrg count1 = gfc_create_var (gfc_array_index_type, "count1"); 5855 1.1 mrg count2 = gfc_create_var (gfc_array_index_type, "count2"); 5856 1.1 mrg gfc_add_modify (block, count1, gfc_index_zero_node); 5857 1.1 mrg gfc_add_modify (block, count2, gfc_index_zero_node); 5858 1.1 mrg 5859 1.1 mrg tmp = gfc_trans_where_assign (expr1, expr2, 5860 1.1 mrg cmask, invert, 5861 1.1 mrg count1, count2, 5862 1.1 mrg cnext); 5863 1.1 mrg gfc_add_expr_to_block (block, tmp); 5864 1.1 mrg 5865 1.1 mrg } 5866 1.1 mrg break; 5867 1.1 mrg 5868 1.1 mrg /* WHERE or WHERE construct is part of a where-body-construct. */ 5869 1.1 mrg case EXEC_WHERE: 5870 1.1 mrg gfc_trans_where_2 (cnext, cmask, invert, 5871 1.1 mrg nested_forall_info, block); 5872 1.1 mrg break; 5873 1.1 mrg 5874 1.1 mrg default: 5875 1.1 mrg gcc_unreachable (); 5876 1.1 mrg } 5877 1.1 mrg 5878 1.1 mrg /* The next statement within the same where-body-construct. */ 5879 1.1 mrg cnext = cnext->next; 5880 1.1 mrg } 5881 1.1 mrg /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */ 5882 1.1 mrg cblock = cblock->block; 5883 1.1 mrg if (mask == NULL_TREE) 5884 1.1 mrg { 5885 1.1 mrg /* If we're the initial WHERE, we can simply invert the sense 5886 1.1 mrg of the current mask to obtain the "mask" for the remaining 5887 1.1 mrg ELSEWHEREs. */ 5888 1.1 mrg invert = true; 5889 1.1 mrg mask = cmask; 5890 1.1 mrg } 5891 1.1 mrg else 5892 1.1 mrg { 5893 1.1 mrg /* Otherwise, for nested WHERE's we need to use the pending mask. */ 5894 1.1 mrg invert = false; 5895 1.1 mrg mask = pmask; 5896 1.1 mrg } 5897 1.1 mrg } 5898 1.1 mrg 5899 1.1 mrg /* If we allocated a pending mask array, deallocate it now. */ 5900 1.1 mrg if (ppmask) 5901 1.1 mrg { 5902 1.1 mrg tmp = gfc_call_free (ppmask); 5903 1.1 mrg gfc_add_expr_to_block (block, tmp); 5904 1.1 mrg } 5905 1.1 mrg 5906 1.1 mrg /* If we allocated a current mask array, deallocate it now. */ 5907 1.1 mrg if (pcmask) 5908 1.1 mrg { 5909 1.1 mrg tmp = gfc_call_free (pcmask); 5910 1.1 mrg gfc_add_expr_to_block (block, tmp); 5911 1.1 mrg } 5912 1.1 mrg } 5913 1.1 mrg 5914 1.1 mrg /* Translate a simple WHERE construct or statement without dependencies. 5915 1.1 mrg CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR 5916 1.1 mrg is the mask condition, and EBLOCK if non-NULL is the "else" clause. 5917 1.1 mrg Currently both CBLOCK and EBLOCK are restricted to single assignments. */ 5918 1.1 mrg 5919 1.1 mrg static tree 5920 1.1 mrg gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock) 5921 1.1 mrg { 5922 1.1 mrg stmtblock_t block, body; 5923 1.1 mrg gfc_expr *cond, *tdst, *tsrc, *edst, *esrc; 5924 1.1 mrg tree tmp, cexpr, tstmt, estmt; 5925 1.1 mrg gfc_ss *css, *tdss, *tsss; 5926 1.1 mrg gfc_se cse, tdse, tsse, edse, esse; 5927 1.1 mrg gfc_loopinfo loop; 5928 1.1 mrg gfc_ss *edss = 0; 5929 1.1 mrg gfc_ss *esss = 0; 5930 1.1 mrg bool maybe_workshare = false; 5931 1.1 mrg 5932 1.1 mrg /* Allow the scalarizer to workshare simple where loops. */ 5933 1.1 mrg if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY)) 5934 1.1 mrg == OMPWS_WORKSHARE_FLAG) 5935 1.1 mrg { 5936 1.1 mrg maybe_workshare = true; 5937 1.1 mrg ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY; 5938 1.1 mrg } 5939 1.1 mrg 5940 1.1 mrg cond = cblock->expr1; 5941 1.1 mrg tdst = cblock->next->expr1; 5942 1.1 mrg tsrc = cblock->next->expr2; 5943 1.1 mrg edst = eblock ? eblock->next->expr1 : NULL; 5944 1.1 mrg esrc = eblock ? eblock->next->expr2 : NULL; 5945 1.1 mrg 5946 1.1 mrg gfc_start_block (&block); 5947 1.1 mrg gfc_init_loopinfo (&loop); 5948 1.1 mrg 5949 1.1 mrg /* Handle the condition. */ 5950 1.1 mrg gfc_init_se (&cse, NULL); 5951 1.1 mrg css = gfc_walk_expr (cond); 5952 1.1 mrg gfc_add_ss_to_loop (&loop, css); 5953 1.1 mrg 5954 1.1 mrg /* Handle the then-clause. */ 5955 1.1 mrg gfc_init_se (&tdse, NULL); 5956 1.1 mrg gfc_init_se (&tsse, NULL); 5957 1.1 mrg tdss = gfc_walk_expr (tdst); 5958 1.1 mrg tsss = gfc_walk_expr (tsrc); 5959 1.1 mrg if (tsss == gfc_ss_terminator) 5960 1.1 mrg { 5961 1.1 mrg tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc); 5962 1.1 mrg tsss->info->where = 1; 5963 1.1 mrg } 5964 1.1 mrg gfc_add_ss_to_loop (&loop, tdss); 5965 1.1 mrg gfc_add_ss_to_loop (&loop, tsss); 5966 1.1 mrg 5967 1.1 mrg if (eblock) 5968 1.1 mrg { 5969 1.1 mrg /* Handle the else clause. */ 5970 1.1 mrg gfc_init_se (&edse, NULL); 5971 1.1 mrg gfc_init_se (&esse, NULL); 5972 1.1 mrg edss = gfc_walk_expr (edst); 5973 1.1 mrg esss = gfc_walk_expr (esrc); 5974 1.1 mrg if (esss == gfc_ss_terminator) 5975 1.1 mrg { 5976 1.1 mrg esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc); 5977 1.1 mrg esss->info->where = 1; 5978 1.1 mrg } 5979 1.1 mrg gfc_add_ss_to_loop (&loop, edss); 5980 1.1 mrg gfc_add_ss_to_loop (&loop, esss); 5981 1.1 mrg } 5982 1.1 mrg 5983 1.1 mrg gfc_conv_ss_startstride (&loop); 5984 1.1 mrg gfc_conv_loop_setup (&loop, &tdst->where); 5985 1.1 mrg 5986 1.1 mrg gfc_mark_ss_chain_used (css, 1); 5987 1.1 mrg gfc_mark_ss_chain_used (tdss, 1); 5988 1.1 mrg gfc_mark_ss_chain_used (tsss, 1); 5989 1.1 mrg if (eblock) 5990 1.1 mrg { 5991 1.1 mrg gfc_mark_ss_chain_used (edss, 1); 5992 1.1 mrg gfc_mark_ss_chain_used (esss, 1); 5993 1.1 mrg } 5994 1.1 mrg 5995 1.1 mrg gfc_start_scalarized_body (&loop, &body); 5996 1.1 mrg 5997 1.1 mrg gfc_copy_loopinfo_to_se (&cse, &loop); 5998 1.1 mrg gfc_copy_loopinfo_to_se (&tdse, &loop); 5999 1.1 mrg gfc_copy_loopinfo_to_se (&tsse, &loop); 6000 1.1 mrg cse.ss = css; 6001 1.1 mrg tdse.ss = tdss; 6002 1.1 mrg tsse.ss = tsss; 6003 1.1 mrg if (eblock) 6004 1.1 mrg { 6005 1.1 mrg gfc_copy_loopinfo_to_se (&edse, &loop); 6006 1.1 mrg gfc_copy_loopinfo_to_se (&esse, &loop); 6007 1.1 mrg edse.ss = edss; 6008 1.1 mrg esse.ss = esss; 6009 1.1 mrg } 6010 1.1 mrg 6011 1.1 mrg gfc_conv_expr (&cse, cond); 6012 1.1 mrg gfc_add_block_to_block (&body, &cse.pre); 6013 1.1 mrg cexpr = cse.expr; 6014 1.1 mrg 6015 1.1 mrg gfc_conv_expr (&tsse, tsrc); 6016 1.1 mrg if (tdss != gfc_ss_terminator && loop.temp_ss != NULL) 6017 1.1 mrg gfc_conv_tmp_array_ref (&tdse); 6018 1.1 mrg else 6019 1.1 mrg gfc_conv_expr (&tdse, tdst); 6020 1.1 mrg 6021 1.1 mrg if (eblock) 6022 1.1 mrg { 6023 1.1 mrg gfc_conv_expr (&esse, esrc); 6024 1.1 mrg if (edss != gfc_ss_terminator && loop.temp_ss != NULL) 6025 1.1 mrg gfc_conv_tmp_array_ref (&edse); 6026 1.1 mrg else 6027 1.1 mrg gfc_conv_expr (&edse, edst); 6028 1.1 mrg } 6029 1.1 mrg 6030 1.1 mrg tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, true); 6031 1.1 mrg estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, 6032 1.1 mrg false, true) 6033 1.1 mrg : build_empty_stmt (input_location); 6034 1.1 mrg tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt); 6035 1.1 mrg gfc_add_expr_to_block (&body, tmp); 6036 1.1 mrg gfc_add_block_to_block (&body, &cse.post); 6037 1.1 mrg 6038 1.1 mrg if (maybe_workshare) 6039 1.1 mrg ompws_flags &= ~OMPWS_SCALARIZER_BODY; 6040 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body); 6041 1.1 mrg gfc_add_block_to_block (&block, &loop.pre); 6042 1.1 mrg gfc_add_block_to_block (&block, &loop.post); 6043 1.1 mrg gfc_cleanup_loop (&loop); 6044 1.1 mrg 6045 1.1 mrg return gfc_finish_block (&block); 6046 1.1 mrg } 6047 1.1 mrg 6048 1.1 mrg /* As the WHERE or WHERE construct statement can be nested, we call 6049 1.1 mrg gfc_trans_where_2 to do the translation, and pass the initial 6050 1.1 mrg NULL values for both the control mask and the pending control mask. */ 6051 1.1 mrg 6052 1.1 mrg tree 6053 1.1 mrg gfc_trans_where (gfc_code * code) 6054 1.1 mrg { 6055 1.1 mrg stmtblock_t block; 6056 1.1 mrg gfc_code *cblock; 6057 1.1 mrg gfc_code *eblock; 6058 1.1 mrg 6059 1.1 mrg cblock = code->block; 6060 1.1 mrg if (cblock->next 6061 1.1 mrg && cblock->next->op == EXEC_ASSIGN 6062 1.1 mrg && !cblock->next->next) 6063 1.1 mrg { 6064 1.1 mrg eblock = cblock->block; 6065 1.1 mrg if (!eblock) 6066 1.1 mrg { 6067 1.1 mrg /* A simple "WHERE (cond) x = y" statement or block is 6068 1.1 mrg dependence free if cond is not dependent upon writing x, 6069 1.1 mrg and the source y is unaffected by the destination x. */ 6070 1.1 mrg if (!gfc_check_dependency (cblock->next->expr1, 6071 1.1 mrg cblock->expr1, 0) 6072 1.1 mrg && !gfc_check_dependency (cblock->next->expr1, 6073 1.1 mrg cblock->next->expr2, 0)) 6074 1.1 mrg return gfc_trans_where_3 (cblock, NULL); 6075 1.1 mrg } 6076 1.1 mrg else if (!eblock->expr1 6077 1.1 mrg && !eblock->block 6078 1.1 mrg && eblock->next 6079 1.1 mrg && eblock->next->op == EXEC_ASSIGN 6080 1.1 mrg && !eblock->next->next) 6081 1.1 mrg { 6082 1.1 mrg /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE" 6083 1.1 mrg block is dependence free if cond is not dependent on writes 6084 1.1 mrg to x1 and x2, y1 is not dependent on writes to x2, and y2 6085 1.1 mrg is not dependent on writes to x1, and both y's are not 6086 1.1 mrg dependent upon their own x's. In addition to this, the 6087 1.1 mrg final two dependency checks below exclude all but the same 6088 1.1 mrg array reference if the where and elswhere destinations 6089 1.1 mrg are the same. In short, this is VERY conservative and this 6090 1.1 mrg is needed because the two loops, required by the standard 6091 1.1 mrg are coalesced in gfc_trans_where_3. */ 6092 1.1 mrg if (!gfc_check_dependency (cblock->next->expr1, 6093 1.1 mrg cblock->expr1, 0) 6094 1.1 mrg && !gfc_check_dependency (eblock->next->expr1, 6095 1.1 mrg cblock->expr1, 0) 6096 1.1 mrg && !gfc_check_dependency (cblock->next->expr1, 6097 1.1 mrg eblock->next->expr2, 1) 6098 1.1 mrg && !gfc_check_dependency (eblock->next->expr1, 6099 1.1 mrg cblock->next->expr2, 1) 6100 1.1 mrg && !gfc_check_dependency (cblock->next->expr1, 6101 1.1 mrg cblock->next->expr2, 1) 6102 1.1 mrg && !gfc_check_dependency (eblock->next->expr1, 6103 1.1 mrg eblock->next->expr2, 1) 6104 1.1 mrg && !gfc_check_dependency (cblock->next->expr1, 6105 1.1 mrg eblock->next->expr1, 0) 6106 1.1 mrg && !gfc_check_dependency (eblock->next->expr1, 6107 1.1 mrg cblock->next->expr1, 0)) 6108 1.1 mrg return gfc_trans_where_3 (cblock, eblock); 6109 1.1 mrg } 6110 1.1 mrg } 6111 1.1 mrg 6112 1.1 mrg gfc_start_block (&block); 6113 1.1 mrg 6114 1.1 mrg gfc_trans_where_2 (code, NULL, false, NULL, &block); 6115 1.1 mrg 6116 1.1 mrg return gfc_finish_block (&block); 6117 1.1 mrg } 6118 1.1 mrg 6119 1.1 mrg 6120 1.1 mrg /* CYCLE a DO loop. The label decl has already been created by 6121 1.1 mrg gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code 6122 1.1 mrg node at the head of the loop. We must mark the label as used. */ 6123 1.1 mrg 6124 1.1 mrg tree 6125 1.1 mrg gfc_trans_cycle (gfc_code * code) 6126 1.1 mrg { 6127 1.1 mrg tree cycle_label; 6128 1.1 mrg 6129 1.1 mrg cycle_label = code->ext.which_construct->cycle_label; 6130 1.1 mrg gcc_assert (cycle_label); 6131 1.1 mrg 6132 1.1 mrg TREE_USED (cycle_label) = 1; 6133 1.1 mrg return build1_v (GOTO_EXPR, cycle_label); 6134 1.1 mrg } 6135 1.1 mrg 6136 1.1 mrg 6137 1.1 mrg /* EXIT a DO loop. Similar to CYCLE, but now the label is in 6138 1.1 mrg TREE_VALUE (backend_decl) of the gfc_code node at the head of the 6139 1.1 mrg loop. */ 6140 1.1 mrg 6141 1.1 mrg tree 6142 1.1 mrg gfc_trans_exit (gfc_code * code) 6143 1.1 mrg { 6144 1.1 mrg tree exit_label; 6145 1.1 mrg 6146 1.1 mrg exit_label = code->ext.which_construct->exit_label; 6147 1.1 mrg gcc_assert (exit_label); 6148 1.1 mrg 6149 1.1 mrg TREE_USED (exit_label) = 1; 6150 1.1 mrg return build1_v (GOTO_EXPR, exit_label); 6151 1.1 mrg } 6152 1.1 mrg 6153 1.1 mrg 6154 1.1 mrg /* Get the initializer expression for the code and expr of an allocate. 6155 1.1 mrg When no initializer is needed return NULL. */ 6156 1.1 mrg 6157 1.1 mrg static gfc_expr * 6158 1.1 mrg allocate_get_initializer (gfc_code * code, gfc_expr * expr) 6159 1.1 mrg { 6160 1.1 mrg if (!gfc_bt_struct (expr->ts.type) && expr->ts.type != BT_CLASS) 6161 1.1 mrg return NULL; 6162 1.1 mrg 6163 1.1 mrg /* An explicit type was given in allocate ( T:: object). */ 6164 1.1 mrg if (code->ext.alloc.ts.type == BT_DERIVED 6165 1.1 mrg && (code->ext.alloc.ts.u.derived->attr.alloc_comp 6166 1.1 mrg || gfc_has_default_initializer (code->ext.alloc.ts.u.derived))) 6167 1.1 mrg return gfc_default_initializer (&code->ext.alloc.ts); 6168 1.1 mrg 6169 1.1 mrg if (gfc_bt_struct (expr->ts.type) 6170 1.1 mrg && (expr->ts.u.derived->attr.alloc_comp 6171 1.1 mrg || gfc_has_default_initializer (expr->ts.u.derived))) 6172 1.1 mrg return gfc_default_initializer (&expr->ts); 6173 1.1 mrg 6174 1.1 mrg if (expr->ts.type == BT_CLASS 6175 1.1 mrg && (CLASS_DATA (expr)->ts.u.derived->attr.alloc_comp 6176 1.1 mrg || gfc_has_default_initializer (CLASS_DATA (expr)->ts.u.derived))) 6177 1.1 mrg return gfc_default_initializer (&CLASS_DATA (expr)->ts); 6178 1.1 mrg 6179 1.1 mrg return NULL; 6180 1.1 mrg } 6181 1.1 mrg 6182 1.1 mrg /* Translate the ALLOCATE statement. */ 6183 1.1 mrg 6184 1.1 mrg tree 6185 1.1 mrg gfc_trans_allocate (gfc_code * code) 6186 1.1 mrg { 6187 1.1 mrg gfc_alloc *al; 6188 1.1 mrg gfc_expr *expr, *e3rhs = NULL, *init_expr; 6189 1.1 mrg gfc_se se, se_sz; 6190 1.1 mrg tree tmp; 6191 1.1 mrg tree parm; 6192 1.1 mrg tree stat; 6193 1.1 mrg tree errmsg; 6194 1.1 mrg tree errlen; 6195 1.1 mrg tree label_errmsg; 6196 1.1 mrg tree label_finish; 6197 1.1 mrg tree memsz; 6198 1.1 mrg tree al_vptr, al_len; 6199 1.1 mrg /* If an expr3 is present, then store the tree for accessing its 6200 1.1 mrg _vptr, and _len components in the variables, respectively. The 6201 1.1 mrg element size, i.e. _vptr%size, is stored in expr3_esize. Any of 6202 1.1 mrg the trees may be the NULL_TREE indicating that this is not 6203 1.1 mrg available for expr3's type. */ 6204 1.1 mrg tree expr3, expr3_vptr, expr3_len, expr3_esize; 6205 1.1 mrg /* Classify what expr3 stores. */ 6206 1.1 mrg enum { E3_UNSET = 0, E3_SOURCE, E3_MOLD, E3_DESC } e3_is; 6207 1.1 mrg stmtblock_t block; 6208 1.1 mrg stmtblock_t post; 6209 1.1 mrg stmtblock_t final_block; 6210 1.1 mrg tree nelems; 6211 1.1 mrg bool upoly_expr, tmp_expr3_len_flag = false, al_len_needs_set, is_coarray; 6212 1.1 mrg bool needs_caf_sync, caf_refs_comp; 6213 1.1 mrg bool e3_has_nodescriptor = false; 6214 1.1 mrg gfc_symtree *newsym = NULL; 6215 1.1 mrg symbol_attribute caf_attr; 6216 1.1 mrg gfc_actual_arglist *param_list; 6217 1.1 mrg 6218 1.1 mrg if (!code->ext.alloc.list) 6219 1.1 mrg return NULL_TREE; 6220 1.1 mrg 6221 1.1 mrg stat = tmp = memsz = al_vptr = al_len = NULL_TREE; 6222 1.1 mrg expr3 = expr3_vptr = expr3_len = expr3_esize = NULL_TREE; 6223 1.1 mrg label_errmsg = label_finish = errmsg = errlen = NULL_TREE; 6224 1.1 mrg e3_is = E3_UNSET; 6225 1.1 mrg is_coarray = needs_caf_sync = false; 6226 1.1 mrg 6227 1.1 mrg gfc_init_block (&block); 6228 1.1 mrg gfc_init_block (&post); 6229 1.1 mrg gfc_init_block (&final_block); 6230 1.1 mrg 6231 1.1 mrg /* STAT= (and maybe ERRMSG=) is present. */ 6232 1.1 mrg if (code->expr1) 6233 1.1 mrg { 6234 1.1 mrg /* STAT=. */ 6235 1.1 mrg tree gfc_int4_type_node = gfc_get_int_type (4); 6236 1.1 mrg stat = gfc_create_var (gfc_int4_type_node, "stat"); 6237 1.1 mrg 6238 1.1 mrg /* ERRMSG= only makes sense with STAT=. */ 6239 1.1 mrg if (code->expr2) 6240 1.1 mrg { 6241 1.1 mrg gfc_init_se (&se, NULL); 6242 1.1 mrg se.want_pointer = 1; 6243 1.1 mrg gfc_conv_expr_lhs (&se, code->expr2); 6244 1.1 mrg errmsg = se.expr; 6245 1.1 mrg errlen = se.string_length; 6246 1.1 mrg } 6247 1.1 mrg else 6248 1.1 mrg { 6249 1.1 mrg errmsg = null_pointer_node; 6250 1.1 mrg errlen = build_int_cst (gfc_charlen_type_node, 0); 6251 1.1 mrg } 6252 1.1 mrg 6253 1.1 mrg /* GOTO destinations. */ 6254 1.1 mrg label_errmsg = gfc_build_label_decl (NULL_TREE); 6255 1.1 mrg label_finish = gfc_build_label_decl (NULL_TREE); 6256 1.1 mrg TREE_USED (label_finish) = 0; 6257 1.1 mrg } 6258 1.1 mrg 6259 1.1 mrg /* When an expr3 is present evaluate it only once. The standards prevent a 6260 1.1 mrg dependency of expr3 on the objects in the allocate list. An expr3 can 6261 1.1 mrg be pre-evaluated in all cases. One just has to make sure, to use the 6262 1.1 mrg correct way, i.e., to get the descriptor or to get a reference 6263 1.1 mrg expression. */ 6264 1.1 mrg if (code->expr3) 6265 1.1 mrg { 6266 1.1 mrg bool vtab_needed = false, temp_var_needed = false, 6267 1.1 mrg temp_obj_created = false; 6268 1.1 mrg 6269 1.1 mrg is_coarray = gfc_is_coarray (code->expr3); 6270 1.1 mrg 6271 1.1 mrg if (code->expr3->expr_type == EXPR_FUNCTION && !code->expr3->mold 6272 1.1 mrg && (gfc_is_class_array_function (code->expr3) 6273 1.1 mrg || gfc_is_alloc_class_scalar_function (code->expr3))) 6274 1.1 mrg code->expr3->must_finalize = 1; 6275 1.1 mrg 6276 1.1 mrg /* Figure whether we need the vtab from expr3. */ 6277 1.1 mrg for (al = code->ext.alloc.list; !vtab_needed && al != NULL; 6278 1.1 mrg al = al->next) 6279 1.1 mrg vtab_needed = (al->expr->ts.type == BT_CLASS); 6280 1.1 mrg 6281 1.1 mrg gfc_init_se (&se, NULL); 6282 1.1 mrg /* When expr3 is a variable, i.e., a very simple expression, 6283 1.1 mrg then convert it once here. */ 6284 1.1 mrg if (code->expr3->expr_type == EXPR_VARIABLE 6285 1.1 mrg || code->expr3->expr_type == EXPR_ARRAY 6286 1.1 mrg || code->expr3->expr_type == EXPR_CONSTANT) 6287 1.1 mrg { 6288 1.1 mrg if (!code->expr3->mold 6289 1.1 mrg || code->expr3->ts.type == BT_CHARACTER 6290 1.1 mrg || vtab_needed 6291 1.1 mrg || code->ext.alloc.arr_spec_from_expr3) 6292 1.1 mrg { 6293 1.1 mrg /* Convert expr3 to a tree. For all "simple" expression just 6294 1.1 mrg get the descriptor or the reference, respectively, depending 6295 1.1 mrg on the rank of the expr. */ 6296 1.1 mrg if (code->ext.alloc.arr_spec_from_expr3 || code->expr3->rank != 0) 6297 1.1 mrg gfc_conv_expr_descriptor (&se, code->expr3); 6298 1.1 mrg else 6299 1.1 mrg { 6300 1.1 mrg gfc_conv_expr_reference (&se, code->expr3); 6301 1.1 mrg 6302 1.1 mrg /* gfc_conv_expr_reference wraps POINTER_PLUS_EXPR in a 6303 1.1 mrg NOP_EXPR, which prevents gfortran from getting the vptr 6304 1.1 mrg from the source=-expression. Remove the NOP_EXPR and go 6305 1.1 mrg with the POINTER_PLUS_EXPR in this case. */ 6306 1.1 mrg if (code->expr3->ts.type == BT_CLASS 6307 1.1 mrg && TREE_CODE (se.expr) == NOP_EXPR 6308 1.1 mrg && (TREE_CODE (TREE_OPERAND (se.expr, 0)) 6309 1.1 mrg == POINTER_PLUS_EXPR 6310 1.1 mrg || is_coarray)) 6311 1.1 mrg se.expr = TREE_OPERAND (se.expr, 0); 6312 1.1 mrg } 6313 1.1 mrg /* Create a temp variable only for component refs to prevent 6314 1.1 mrg having to go through the full deref-chain each time and to 6315 1.1 mrg simplfy computation of array properties. */ 6316 1.1 mrg temp_var_needed = TREE_CODE (se.expr) == COMPONENT_REF; 6317 1.1 mrg } 6318 1.1 mrg } 6319 1.1 mrg else 6320 1.1 mrg { 6321 1.1 mrg /* In all other cases evaluate the expr3. */ 6322 1.1 mrg symbol_attribute attr; 6323 1.1 mrg /* Get the descriptor for all arrays, that are not allocatable or 6324 1.1 mrg pointer, because the latter are descriptors already. 6325 1.1 mrg The exception are function calls returning a class object: 6326 1.1 mrg The descriptor is stored in their results _data component, which 6327 1.1 mrg is easier to access, when first a temporary variable for the 6328 1.1 mrg result is created and the descriptor retrieved from there. */ 6329 1.1 mrg attr = gfc_expr_attr (code->expr3); 6330 1.1 mrg if (code->expr3->rank != 0 6331 1.1 mrg && ((!attr.allocatable && !attr.pointer) 6332 1.1 mrg || (code->expr3->expr_type == EXPR_FUNCTION 6333 1.1 mrg && (code->expr3->ts.type != BT_CLASS 6334 1.1 mrg || (code->expr3->value.function.isym 6335 1.1 mrg && code->expr3->value.function.isym 6336 1.1 mrg ->transformational))))) 6337 1.1 mrg gfc_conv_expr_descriptor (&se, code->expr3); 6338 1.1 mrg else 6339 1.1 mrg gfc_conv_expr_reference (&se, code->expr3); 6340 1.1 mrg if (code->expr3->ts.type == BT_CLASS) 6341 1.1 mrg gfc_conv_class_to_class (&se, code->expr3, 6342 1.1 mrg code->expr3->ts, 6343 1.1 mrg false, true, 6344 1.1 mrg false, false); 6345 1.1 mrg temp_obj_created = temp_var_needed = !VAR_P (se.expr); 6346 1.1 mrg } 6347 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 6348 1.1 mrg if (code->expr3->must_finalize) 6349 1.1 mrg gfc_add_block_to_block (&final_block, &se.post); 6350 1.1 mrg else 6351 1.1 mrg gfc_add_block_to_block (&post, &se.post); 6352 1.1 mrg 6353 1.1 mrg /* Special case when string in expr3 is zero. */ 6354 1.1 mrg if (code->expr3->ts.type == BT_CHARACTER 6355 1.1 mrg && integer_zerop (se.string_length)) 6356 1.1 mrg { 6357 1.1 mrg gfc_init_se (&se, NULL); 6358 1.1 mrg temp_var_needed = false; 6359 1.1 mrg expr3_len = build_zero_cst (gfc_charlen_type_node); 6360 1.1 mrg e3_is = E3_MOLD; 6361 1.1 mrg } 6362 1.1 mrg /* Prevent aliasing, i.e., se.expr may be already a 6363 1.1 mrg variable declaration. */ 6364 1.1 mrg else if (se.expr != NULL_TREE && temp_var_needed) 6365 1.1 mrg { 6366 1.1 mrg tree var, desc; 6367 1.1 mrg tmp = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)) || is_coarray ? 6368 1.1 mrg se.expr 6369 1.1 mrg : build_fold_indirect_ref_loc (input_location, se.expr); 6370 1.1 mrg 6371 1.1 mrg /* Get the array descriptor and prepare it to be assigned to the 6372 1.1 mrg temporary variable var. For classes the array descriptor is 6373 1.1 mrg in the _data component and the object goes into the 6374 1.1 mrg GFC_DECL_SAVED_DESCRIPTOR. */ 6375 1.1 mrg if (code->expr3->ts.type == BT_CLASS 6376 1.1 mrg && code->expr3->rank != 0) 6377 1.1 mrg { 6378 1.1 mrg /* When an array_ref was in expr3, then the descriptor is the 6379 1.1 mrg first operand. */ 6380 1.1 mrg if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray) 6381 1.1 mrg { 6382 1.1 mrg desc = TREE_OPERAND (tmp, 0); 6383 1.1 mrg } 6384 1.1 mrg else 6385 1.1 mrg { 6386 1.1 mrg desc = tmp; 6387 1.1 mrg tmp = gfc_class_data_get (tmp); 6388 1.1 mrg } 6389 1.1 mrg if (code->ext.alloc.arr_spec_from_expr3) 6390 1.1 mrg e3_is = E3_DESC; 6391 1.1 mrg } 6392 1.1 mrg else 6393 1.1 mrg desc = !is_coarray ? se.expr 6394 1.1 mrg : TREE_OPERAND (TREE_OPERAND (se.expr, 0), 0); 6395 1.1 mrg /* We need a regular (non-UID) symbol here, therefore give a 6396 1.1 mrg prefix. */ 6397 1.1 mrg var = gfc_create_var (TREE_TYPE (tmp), "source"); 6398 1.1 mrg if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray) 6399 1.1 mrg { 6400 1.1 mrg gfc_allocate_lang_decl (var); 6401 1.1 mrg GFC_DECL_SAVED_DESCRIPTOR (var) = desc; 6402 1.1 mrg } 6403 1.1 mrg gfc_add_modify_loc (input_location, &block, var, tmp); 6404 1.1 mrg 6405 1.1 mrg expr3 = var; 6406 1.1 mrg if (se.string_length) 6407 1.1 mrg /* Evaluate it assuming that it also is complicated like expr3. */ 6408 1.1 mrg expr3_len = gfc_evaluate_now (se.string_length, &block); 6409 1.1 mrg } 6410 1.1 mrg else 6411 1.1 mrg { 6412 1.1 mrg expr3 = se.expr; 6413 1.1 mrg expr3_len = se.string_length; 6414 1.1 mrg } 6415 1.1 mrg 6416 1.1 mrg /* Deallocate any allocatable components in expressions that use a 6417 1.1 mrg temporary object, i.e. are not a simple alias of to an EXPR_VARIABLE. 6418 1.1 mrg E.g. temporaries of a function call need freeing of their components 6419 1.1 mrg here. */ 6420 1.1 mrg if ((code->expr3->ts.type == BT_DERIVED 6421 1.1 mrg || code->expr3->ts.type == BT_CLASS) 6422 1.1 mrg && (code->expr3->expr_type != EXPR_VARIABLE || temp_obj_created) 6423 1.1 mrg && code->expr3->ts.u.derived->attr.alloc_comp 6424 1.1 mrg && !code->expr3->must_finalize) 6425 1.1 mrg { 6426 1.1 mrg tmp = gfc_deallocate_alloc_comp (code->expr3->ts.u.derived, 6427 1.1 mrg expr3, code->expr3->rank); 6428 1.1 mrg gfc_prepend_expr_to_block (&post, tmp); 6429 1.1 mrg } 6430 1.1 mrg 6431 1.1 mrg /* Store what the expr3 is to be used for. */ 6432 1.1 mrg if (e3_is == E3_UNSET) 6433 1.1 mrg e3_is = expr3 != NULL_TREE ? 6434 1.1 mrg (code->ext.alloc.arr_spec_from_expr3 ? 6435 1.1 mrg E3_DESC 6436 1.1 mrg : (code->expr3->mold ? E3_MOLD : E3_SOURCE)) 6437 1.1 mrg : E3_UNSET; 6438 1.1 mrg 6439 1.1 mrg /* Figure how to get the _vtab entry. This also obtains the tree 6440 1.1 mrg expression for accessing the _len component, because only 6441 1.1 mrg unlimited polymorphic objects, which are a subcategory of class 6442 1.1 mrg types, have a _len component. */ 6443 1.1 mrg if (code->expr3->ts.type == BT_CLASS) 6444 1.1 mrg { 6445 1.1 mrg gfc_expr *rhs; 6446 1.1 mrg tmp = expr3 != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (expr3)) ? 6447 1.1 mrg build_fold_indirect_ref (expr3): expr3; 6448 1.1 mrg /* Polymorphic SOURCE: VPTR must be determined at run time. 6449 1.1 mrg expr3 may be a temporary array declaration, therefore check for 6450 1.1 mrg GFC_CLASS_TYPE_P before trying to get the _vptr component. */ 6451 1.1 mrg if (tmp != NULL_TREE 6452 1.1 mrg && (e3_is == E3_DESC 6453 1.1 mrg || (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)) 6454 1.1 mrg && (VAR_P (tmp) || !code->expr3->ref)) 6455 1.1 mrg || (VAR_P (tmp) && DECL_LANG_SPECIFIC (tmp)))) 6456 1.1 mrg tmp = gfc_class_vptr_get (expr3); 6457 1.1 mrg else 6458 1.1 mrg { 6459 1.1 mrg rhs = gfc_find_and_cut_at_last_class_ref (code->expr3); 6460 1.1 mrg gfc_add_vptr_component (rhs); 6461 1.1 mrg gfc_init_se (&se, NULL); 6462 1.1 mrg se.want_pointer = 1; 6463 1.1 mrg gfc_conv_expr (&se, rhs); 6464 1.1 mrg tmp = se.expr; 6465 1.1 mrg gfc_free_expr (rhs); 6466 1.1 mrg } 6467 1.1 mrg /* Set the element size. */ 6468 1.1 mrg expr3_esize = gfc_vptr_size_get (tmp); 6469 1.1 mrg if (vtab_needed) 6470 1.1 mrg expr3_vptr = tmp; 6471 1.1 mrg /* Initialize the ref to the _len component. */ 6472 1.1 mrg if (expr3_len == NULL_TREE && UNLIMITED_POLY (code->expr3)) 6473 1.1 mrg { 6474 1.1 mrg /* Same like for retrieving the _vptr. */ 6475 1.1 mrg if (expr3 != NULL_TREE && !code->expr3->ref) 6476 1.1 mrg expr3_len = gfc_class_len_get (expr3); 6477 1.1 mrg else 6478 1.1 mrg { 6479 1.1 mrg rhs = gfc_find_and_cut_at_last_class_ref (code->expr3); 6480 1.1 mrg gfc_add_len_component (rhs); 6481 1.1 mrg gfc_init_se (&se, NULL); 6482 1.1 mrg gfc_conv_expr (&se, rhs); 6483 1.1 mrg expr3_len = se.expr; 6484 1.1 mrg gfc_free_expr (rhs); 6485 1.1 mrg } 6486 1.1 mrg } 6487 1.1 mrg } 6488 1.1 mrg else 6489 1.1 mrg { 6490 1.1 mrg /* When the object to allocate is polymorphic type, then it 6491 1.1 mrg needs its vtab set correctly, so deduce the required _vtab 6492 1.1 mrg and _len from the source expression. */ 6493 1.1 mrg if (vtab_needed) 6494 1.1 mrg { 6495 1.1 mrg /* VPTR is fixed at compile time. */ 6496 1.1 mrg gfc_symbol *vtab; 6497 1.1 mrg 6498 1.1 mrg vtab = gfc_find_vtab (&code->expr3->ts); 6499 1.1 mrg gcc_assert (vtab); 6500 1.1 mrg expr3_vptr = gfc_get_symbol_decl (vtab); 6501 1.1 mrg expr3_vptr = gfc_build_addr_expr (NULL_TREE, 6502 1.1 mrg expr3_vptr); 6503 1.1 mrg } 6504 1.1 mrg /* _len component needs to be set, when ts is a character 6505 1.1 mrg array. */ 6506 1.1 mrg if (expr3_len == NULL_TREE 6507 1.1 mrg && code->expr3->ts.type == BT_CHARACTER) 6508 1.1 mrg { 6509 1.1 mrg if (code->expr3->ts.u.cl 6510 1.1 mrg && code->expr3->ts.u.cl->length) 6511 1.1 mrg { 6512 1.1 mrg gfc_init_se (&se, NULL); 6513 1.1 mrg gfc_conv_expr (&se, code->expr3->ts.u.cl->length); 6514 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 6515 1.1 mrg expr3_len = gfc_evaluate_now (se.expr, &block); 6516 1.1 mrg } 6517 1.1 mrg gcc_assert (expr3_len); 6518 1.1 mrg } 6519 1.1 mrg /* For character arrays only the kind's size is needed, because 6520 1.1 mrg the array mem_size is _len * (elem_size = kind_size). 6521 1.1 mrg For all other get the element size in the normal way. */ 6522 1.1 mrg if (code->expr3->ts.type == BT_CHARACTER) 6523 1.1 mrg expr3_esize = TYPE_SIZE_UNIT ( 6524 1.1 mrg gfc_get_char_type (code->expr3->ts.kind)); 6525 1.1 mrg else 6526 1.1 mrg expr3_esize = TYPE_SIZE_UNIT ( 6527 1.1 mrg gfc_typenode_for_spec (&code->expr3->ts)); 6528 1.1 mrg } 6529 1.1 mrg gcc_assert (expr3_esize); 6530 1.1 mrg expr3_esize = fold_convert (sizetype, expr3_esize); 6531 1.1 mrg if (e3_is == E3_MOLD) 6532 1.1 mrg /* The expr3 is no longer valid after this point. */ 6533 1.1 mrg expr3 = NULL_TREE; 6534 1.1 mrg } 6535 1.1 mrg else if (code->ext.alloc.ts.type != BT_UNKNOWN) 6536 1.1 mrg { 6537 1.1 mrg /* Compute the explicit typespec given only once for all objects 6538 1.1 mrg to allocate. */ 6539 1.1 mrg if (code->ext.alloc.ts.type != BT_CHARACTER) 6540 1.1 mrg expr3_esize = TYPE_SIZE_UNIT ( 6541 1.1 mrg gfc_typenode_for_spec (&code->ext.alloc.ts)); 6542 1.1 mrg else if (code->ext.alloc.ts.u.cl->length != NULL) 6543 1.1 mrg { 6544 1.1 mrg gfc_expr *sz; 6545 1.1 mrg sz = gfc_copy_expr (code->ext.alloc.ts.u.cl->length); 6546 1.1 mrg gfc_init_se (&se_sz, NULL); 6547 1.1 mrg gfc_conv_expr (&se_sz, sz); 6548 1.1 mrg gfc_free_expr (sz); 6549 1.1 mrg tmp = gfc_get_char_type (code->ext.alloc.ts.kind); 6550 1.1 mrg tmp = TYPE_SIZE_UNIT (tmp); 6551 1.1 mrg tmp = fold_convert (TREE_TYPE (se_sz.expr), tmp); 6552 1.1 mrg gfc_add_block_to_block (&block, &se_sz.pre); 6553 1.1 mrg expr3_esize = fold_build2_loc (input_location, MULT_EXPR, 6554 1.1 mrg TREE_TYPE (se_sz.expr), 6555 1.1 mrg tmp, se_sz.expr); 6556 1.1 mrg expr3_esize = gfc_evaluate_now (expr3_esize, &block); 6557 1.1 mrg } 6558 1.1 mrg else 6559 1.1 mrg expr3_esize = NULL_TREE; 6560 1.1 mrg } 6561 1.1 mrg 6562 1.1 mrg /* The routine gfc_trans_assignment () already implements all 6563 1.1 mrg techniques needed. Unfortunately we may have a temporary 6564 1.1 mrg variable for the source= expression here. When that is the 6565 1.1 mrg case convert this variable into a temporary gfc_expr of type 6566 1.1 mrg EXPR_VARIABLE and used it as rhs for the assignment. The 6567 1.1 mrg advantage is, that we get scalarizer support for free, 6568 1.1 mrg don't have to take care about scalar to array treatment and 6569 1.1 mrg will benefit of every enhancements gfc_trans_assignment () 6570 1.1 mrg gets. 6571 1.1 mrg No need to check whether e3_is is E3_UNSET, because that is 6572 1.1 mrg done by expr3 != NULL_TREE. 6573 1.1 mrg Exclude variables since the following block does not handle 6574 1.1 mrg array sections. In any case, there is no harm in sending 6575 1.1 mrg variables to gfc_trans_assignment because there is no 6576 1.1 mrg evaluation of variables. */ 6577 1.1 mrg if (code->expr3) 6578 1.1 mrg { 6579 1.1 mrg if (code->expr3->expr_type != EXPR_VARIABLE 6580 1.1 mrg && e3_is != E3_MOLD && expr3 != NULL_TREE 6581 1.1 mrg && DECL_P (expr3) && DECL_ARTIFICIAL (expr3)) 6582 1.1 mrg { 6583 1.1 mrg /* Build a temporary symtree and symbol. Do not add it to the current 6584 1.1 mrg namespace to prevent accidently modifying a colliding 6585 1.1 mrg symbol's as. */ 6586 1.1 mrg newsym = XCNEW (gfc_symtree); 6587 1.1 mrg /* The name of the symtree should be unique, because gfc_create_var () 6588 1.1 mrg took care about generating the identifier. */ 6589 1.1 mrg newsym->name 6590 1.1 mrg = gfc_get_string ("%s", IDENTIFIER_POINTER (DECL_NAME (expr3))); 6591 1.1 mrg newsym->n.sym = gfc_new_symbol (newsym->name, NULL); 6592 1.1 mrg /* The backend_decl is known. It is expr3, which is inserted 6593 1.1 mrg here. */ 6594 1.1 mrg newsym->n.sym->backend_decl = expr3; 6595 1.1 mrg e3rhs = gfc_get_expr (); 6596 1.1 mrg e3rhs->rank = code->expr3->rank; 6597 1.1 mrg e3rhs->symtree = newsym; 6598 1.1 mrg /* Mark the symbol referenced or gfc_trans_assignment will bug. */ 6599 1.1 mrg newsym->n.sym->attr.referenced = 1; 6600 1.1 mrg e3rhs->expr_type = EXPR_VARIABLE; 6601 1.1 mrg e3rhs->where = code->expr3->where; 6602 1.1 mrg /* Set the symbols type, upto it was BT_UNKNOWN. */ 6603 1.1 mrg if (IS_CLASS_ARRAY (code->expr3) 6604 1.1 mrg && code->expr3->expr_type == EXPR_FUNCTION 6605 1.1 mrg && code->expr3->value.function.isym 6606 1.1 mrg && code->expr3->value.function.isym->transformational) 6607 1.1 mrg { 6608 1.1 mrg e3rhs->ts = CLASS_DATA (code->expr3)->ts; 6609 1.1 mrg } 6610 1.1 mrg else if (code->expr3->ts.type == BT_CLASS 6611 1.1 mrg && !GFC_CLASS_TYPE_P (TREE_TYPE (expr3))) 6612 1.1 mrg e3rhs->ts = CLASS_DATA (code->expr3)->ts; 6613 1.1 mrg else 6614 1.1 mrg e3rhs->ts = code->expr3->ts; 6615 1.1 mrg newsym->n.sym->ts = e3rhs->ts; 6616 1.1 mrg /* Check whether the expr3 is array valued. */ 6617 1.1 mrg if (e3rhs->rank) 6618 1.1 mrg { 6619 1.1 mrg gfc_array_spec *arr; 6620 1.1 mrg arr = gfc_get_array_spec (); 6621 1.1 mrg arr->rank = e3rhs->rank; 6622 1.1 mrg arr->type = AS_DEFERRED; 6623 1.1 mrg /* Set the dimension and pointer attribute for arrays 6624 1.1 mrg to be on the safe side. */ 6625 1.1 mrg newsym->n.sym->attr.dimension = 1; 6626 1.1 mrg newsym->n.sym->attr.pointer = 1; 6627 1.1 mrg newsym->n.sym->as = arr; 6628 1.1 mrg if (IS_CLASS_ARRAY (code->expr3) 6629 1.1 mrg && code->expr3->expr_type == EXPR_FUNCTION 6630 1.1 mrg && code->expr3->value.function.isym 6631 1.1 mrg && code->expr3->value.function.isym->transformational) 6632 1.1 mrg { 6633 1.1 mrg gfc_array_spec *tarr; 6634 1.1 mrg tarr = gfc_get_array_spec (); 6635 1.1 mrg *tarr = *arr; 6636 1.1 mrg e3rhs->ts.u.derived->as = tarr; 6637 1.1 mrg } 6638 1.1 mrg gfc_add_full_array_ref (e3rhs, arr); 6639 1.1 mrg } 6640 1.1 mrg else if (POINTER_TYPE_P (TREE_TYPE (expr3))) 6641 1.1 mrg newsym->n.sym->attr.pointer = 1; 6642 1.1 mrg /* The string length is known, too. Set it for char arrays. */ 6643 1.1 mrg if (e3rhs->ts.type == BT_CHARACTER) 6644 1.1 mrg newsym->n.sym->ts.u.cl->backend_decl = expr3_len; 6645 1.1 mrg gfc_commit_symbol (newsym->n.sym); 6646 1.1 mrg } 6647 1.1 mrg else 6648 1.1 mrg e3rhs = gfc_copy_expr (code->expr3); 6649 1.1 mrg 6650 1.1 mrg // We need to propagate the bounds of the expr3 for source=/mold=. 6651 1.1 mrg // However, for non-named arrays, the lbound has to be 1 and neither the 6652 1.1 mrg // bound used inside the called function even when returning an 6653 1.1 mrg // allocatable/pointer nor the zero used internally. 6654 1.1 mrg if (e3_is == E3_DESC 6655 1.1 mrg && code->expr3->expr_type != EXPR_VARIABLE) 6656 1.1 mrg e3_has_nodescriptor = true; 6657 1.1 mrg } 6658 1.1 mrg 6659 1.1 mrg /* Loop over all objects to allocate. */ 6660 1.1 mrg for (al = code->ext.alloc.list; al != NULL; al = al->next) 6661 1.1 mrg { 6662 1.1 mrg expr = gfc_copy_expr (al->expr); 6663 1.1 mrg /* UNLIMITED_POLY () needs the _data component to be set, when 6664 1.1 mrg expr is a unlimited polymorphic object. But the _data component 6665 1.1 mrg has not been set yet, so check the derived type's attr for the 6666 1.1 mrg unlimited polymorphic flag to be safe. */ 6667 1.1 mrg upoly_expr = UNLIMITED_POLY (expr) 6668 1.1 mrg || (expr->ts.type == BT_DERIVED 6669 1.1 mrg && expr->ts.u.derived->attr.unlimited_polymorphic); 6670 1.1 mrg gfc_init_se (&se, NULL); 6671 1.1 mrg 6672 1.1 mrg /* For class types prepare the expressions to ref the _vptr 6673 1.1 mrg and the _len component. The latter for unlimited polymorphic 6674 1.1 mrg types only. */ 6675 1.1 mrg if (expr->ts.type == BT_CLASS) 6676 1.1 mrg { 6677 1.1 mrg gfc_expr *expr_ref_vptr, *expr_ref_len; 6678 1.1 mrg gfc_add_data_component (expr); 6679 1.1 mrg /* Prep the vptr handle. */ 6680 1.1 mrg expr_ref_vptr = gfc_copy_expr (al->expr); 6681 1.1 mrg gfc_add_vptr_component (expr_ref_vptr); 6682 1.1 mrg se.want_pointer = 1; 6683 1.1 mrg gfc_conv_expr (&se, expr_ref_vptr); 6684 1.1 mrg al_vptr = se.expr; 6685 1.1 mrg se.want_pointer = 0; 6686 1.1 mrg gfc_free_expr (expr_ref_vptr); 6687 1.1 mrg /* Allocated unlimited polymorphic objects always have a _len 6688 1.1 mrg component. */ 6689 1.1 mrg if (upoly_expr) 6690 1.1 mrg { 6691 1.1 mrg expr_ref_len = gfc_copy_expr (al->expr); 6692 1.1 mrg gfc_add_len_component (expr_ref_len); 6693 1.1 mrg gfc_conv_expr (&se, expr_ref_len); 6694 1.1 mrg al_len = se.expr; 6695 1.1 mrg gfc_free_expr (expr_ref_len); 6696 1.1 mrg } 6697 1.1 mrg else 6698 1.1 mrg /* In a loop ensure that all loop variable dependent variables 6699 1.1 mrg are initialized at the same spot in all execution paths. */ 6700 1.1 mrg al_len = NULL_TREE; 6701 1.1 mrg } 6702 1.1 mrg else 6703 1.1 mrg al_vptr = al_len = NULL_TREE; 6704 1.1 mrg 6705 1.1 mrg se.want_pointer = 1; 6706 1.1 mrg se.descriptor_only = 1; 6707 1.1 mrg 6708 1.1 mrg gfc_conv_expr (&se, expr); 6709 1.1 mrg if (expr->ts.type == BT_CHARACTER && expr->ts.deferred) 6710 1.1 mrg /* se.string_length now stores the .string_length variable of expr 6711 1.1 mrg needed to allocate character(len=:) arrays. */ 6712 1.1 mrg al_len = se.string_length; 6713 1.1 mrg 6714 1.1 mrg al_len_needs_set = al_len != NULL_TREE; 6715 1.1 mrg /* When allocating an array one cannot use much of the 6716 1.1 mrg pre-evaluated expr3 expressions, because for most of them the 6717 1.1 mrg scalarizer is needed which is not available in the pre-evaluation 6718 1.1 mrg step. Therefore gfc_array_allocate () is responsible (and able) 6719 1.1 mrg to handle the complete array allocation. Only the element size 6720 1.1 mrg needs to be provided, which is done most of the time by the 6721 1.1 mrg pre-evaluation step. */ 6722 1.1 mrg nelems = NULL_TREE; 6723 1.1 mrg if (expr3_len && (code->expr3->ts.type == BT_CHARACTER 6724 1.1 mrg || code->expr3->ts.type == BT_CLASS)) 6725 1.1 mrg { 6726 1.1 mrg /* When al is an array, then the element size for each element 6727 1.1 mrg in the array is needed, which is the product of the len and 6728 1.1 mrg esize for char arrays. For unlimited polymorphics len can be 6729 1.1 mrg zero, therefore take the maximum of len and one. */ 6730 1.1 mrg tmp = fold_build2_loc (input_location, MAX_EXPR, 6731 1.1 mrg TREE_TYPE (expr3_len), 6732 1.1 mrg expr3_len, fold_convert (TREE_TYPE (expr3_len), 6733 1.1 mrg integer_one_node)); 6734 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR, 6735 1.1 mrg TREE_TYPE (expr3_esize), expr3_esize, 6736 1.1 mrg fold_convert (TREE_TYPE (expr3_esize), tmp)); 6737 1.1 mrg } 6738 1.1 mrg else 6739 1.1 mrg tmp = expr3_esize; 6740 1.1 mrg 6741 1.1 mrg if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen, 6742 1.1 mrg label_finish, tmp, &nelems, 6743 1.1 mrg e3rhs ? e3rhs : code->expr3, 6744 1.1 mrg e3_is == E3_DESC ? expr3 : NULL_TREE, 6745 1.1 mrg e3_has_nodescriptor)) 6746 1.1 mrg { 6747 1.1 mrg /* A scalar or derived type. First compute the size to 6748 1.1 mrg allocate. 6749 1.1 mrg 6750 1.1 mrg expr3_len is set when expr3 is an unlimited polymorphic 6751 1.1 mrg object or a deferred length string. */ 6752 1.1 mrg if (expr3_len != NULL_TREE) 6753 1.1 mrg { 6754 1.1 mrg tmp = fold_convert (TREE_TYPE (expr3_esize), expr3_len); 6755 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR, 6756 1.1 mrg TREE_TYPE (expr3_esize), 6757 1.1 mrg expr3_esize, tmp); 6758 1.1 mrg if (code->expr3->ts.type != BT_CLASS) 6759 1.1 mrg /* expr3 is a deferred length string, i.e., we are 6760 1.1 mrg done. */ 6761 1.1 mrg memsz = tmp; 6762 1.1 mrg else 6763 1.1 mrg { 6764 1.1 mrg /* For unlimited polymorphic enties build 6765 1.1 mrg (len > 0) ? element_size * len : element_size 6766 1.1 mrg to compute the number of bytes to allocate. 6767 1.1 mrg This allows the allocation of unlimited polymorphic 6768 1.1 mrg objects from an expr3 that is also unlimited 6769 1.1 mrg polymorphic and stores a _len dependent object, 6770 1.1 mrg e.g., a string. */ 6771 1.1 mrg memsz = fold_build2_loc (input_location, GT_EXPR, 6772 1.1 mrg logical_type_node, expr3_len, 6773 1.1 mrg build_zero_cst 6774 1.1 mrg (TREE_TYPE (expr3_len))); 6775 1.1 mrg memsz = fold_build3_loc (input_location, COND_EXPR, 6776 1.1 mrg TREE_TYPE (expr3_esize), 6777 1.1 mrg memsz, tmp, expr3_esize); 6778 1.1 mrg } 6779 1.1 mrg } 6780 1.1 mrg else if (expr3_esize != NULL_TREE) 6781 1.1 mrg /* Any other object in expr3 just needs element size in 6782 1.1 mrg bytes. */ 6783 1.1 mrg memsz = expr3_esize; 6784 1.1 mrg else if ((expr->ts.type == BT_CHARACTER && expr->ts.deferred) 6785 1.1 mrg || (upoly_expr 6786 1.1 mrg && code->ext.alloc.ts.type == BT_CHARACTER)) 6787 1.1 mrg { 6788 1.1 mrg /* Allocating deferred length char arrays need the length 6789 1.1 mrg to allocate in the alloc_type_spec. But also unlimited 6790 1.1 mrg polymorphic objects may be allocated as char arrays. 6791 1.1 mrg Both are handled here. */ 6792 1.1 mrg gfc_init_se (&se_sz, NULL); 6793 1.1 mrg gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length); 6794 1.1 mrg gfc_add_block_to_block (&se.pre, &se_sz.pre); 6795 1.1 mrg se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre); 6796 1.1 mrg gfc_add_block_to_block (&se.pre, &se_sz.post); 6797 1.1 mrg expr3_len = se_sz.expr; 6798 1.1 mrg tmp_expr3_len_flag = true; 6799 1.1 mrg tmp = TYPE_SIZE_UNIT ( 6800 1.1 mrg gfc_get_char_type (code->ext.alloc.ts.kind)); 6801 1.1 mrg memsz = fold_build2_loc (input_location, MULT_EXPR, 6802 1.1 mrg TREE_TYPE (tmp), 6803 1.1 mrg fold_convert (TREE_TYPE (tmp), 6804 1.1 mrg expr3_len), 6805 1.1 mrg tmp); 6806 1.1 mrg } 6807 1.1 mrg else if (expr->ts.type == BT_CHARACTER) 6808 1.1 mrg { 6809 1.1 mrg /* Compute the number of bytes needed to allocate a fixed 6810 1.1 mrg length char array. */ 6811 1.1 mrg gcc_assert (se.string_length != NULL_TREE); 6812 1.1 mrg tmp = TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind)); 6813 1.1 mrg memsz = fold_build2_loc (input_location, MULT_EXPR, 6814 1.1 mrg TREE_TYPE (tmp), tmp, 6815 1.1 mrg fold_convert (TREE_TYPE (tmp), 6816 1.1 mrg se.string_length)); 6817 1.1 mrg } 6818 1.1 mrg else if (code->ext.alloc.ts.type != BT_UNKNOWN) 6819 1.1 mrg /* Handle all types, where the alloc_type_spec is set. */ 6820 1.1 mrg memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts)); 6821 1.1 mrg else 6822 1.1 mrg /* Handle size computation of the type declared to alloc. */ 6823 1.1 mrg memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr))); 6824 1.1 mrg 6825 1.1 mrg /* Store the caf-attributes for latter use. */ 6826 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB 6827 1.1 mrg && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp)) 6828 1.1 mrg .codimension) 6829 1.1 mrg { 6830 1.1 mrg /* Scalar allocatable components in coarray'ed derived types make 6831 1.1 mrg it here and are treated now. */ 6832 1.1 mrg tree caf_decl, token; 6833 1.1 mrg gfc_se caf_se; 6834 1.1 mrg 6835 1.1 mrg is_coarray = true; 6836 1.1 mrg /* Set flag, to add synchronize after the allocate. */ 6837 1.1 mrg needs_caf_sync = needs_caf_sync 6838 1.1 mrg || caf_attr.coarray_comp || !caf_refs_comp; 6839 1.1 mrg 6840 1.1 mrg gfc_init_se (&caf_se, NULL); 6841 1.1 mrg 6842 1.1 mrg caf_decl = gfc_get_tree_for_caf_expr (expr); 6843 1.1 mrg gfc_get_caf_token_offset (&caf_se, &token, NULL, caf_decl, 6844 1.1 mrg NULL_TREE, NULL); 6845 1.1 mrg gfc_add_block_to_block (&se.pre, &caf_se.pre); 6846 1.1 mrg gfc_allocate_allocatable (&se.pre, se.expr, memsz, 6847 1.1 mrg gfc_build_addr_expr (NULL_TREE, token), 6848 1.1 mrg NULL_TREE, NULL_TREE, NULL_TREE, 6849 1.1 mrg label_finish, expr, 1); 6850 1.1 mrg } 6851 1.1 mrg /* Allocate - for non-pointers with re-alloc checking. */ 6852 1.1 mrg else if (gfc_expr_attr (expr).allocatable) 6853 1.1 mrg gfc_allocate_allocatable (&se.pre, se.expr, memsz, 6854 1.1 mrg NULL_TREE, stat, errmsg, errlen, 6855 1.1 mrg label_finish, expr, 0); 6856 1.1 mrg else 6857 1.1 mrg gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat); 6858 1.1 mrg } 6859 1.1 mrg else 6860 1.1 mrg { 6861 1.1 mrg /* Allocating coarrays needs a sync after the allocate executed. 6862 1.1 mrg Set the flag to add the sync after all objects are allocated. */ 6863 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB 6864 1.1 mrg && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp)) 6865 1.1 mrg .codimension) 6866 1.1 mrg { 6867 1.1 mrg is_coarray = true; 6868 1.1 mrg needs_caf_sync = needs_caf_sync 6869 1.1 mrg || caf_attr.coarray_comp || !caf_refs_comp; 6870 1.1 mrg } 6871 1.1 mrg 6872 1.1 mrg if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE 6873 1.1 mrg && expr3_len != NULL_TREE) 6874 1.1 mrg { 6875 1.1 mrg /* Arrays need to have a _len set before the array 6876 1.1 mrg descriptor is filled. */ 6877 1.1 mrg gfc_add_modify (&block, al_len, 6878 1.1 mrg fold_convert (TREE_TYPE (al_len), expr3_len)); 6879 1.1 mrg /* Prevent setting the length twice. */ 6880 1.1 mrg al_len_needs_set = false; 6881 1.1 mrg } 6882 1.1 mrg else if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE 6883 1.1 mrg && code->ext.alloc.ts.u.cl->length) 6884 1.1 mrg { 6885 1.1 mrg /* Cover the cases where a string length is explicitly 6886 1.1 mrg specified by a type spec for deferred length character 6887 1.1 mrg arrays or unlimited polymorphic objects without a 6888 1.1 mrg source= or mold= expression. */ 6889 1.1 mrg gfc_init_se (&se_sz, NULL); 6890 1.1 mrg gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length); 6891 1.1 mrg gfc_add_block_to_block (&block, &se_sz.pre); 6892 1.1 mrg gfc_add_modify (&block, al_len, 6893 1.1 mrg fold_convert (TREE_TYPE (al_len), 6894 1.1 mrg se_sz.expr)); 6895 1.1 mrg al_len_needs_set = false; 6896 1.1 mrg } 6897 1.1 mrg } 6898 1.1 mrg 6899 1.1 mrg gfc_add_block_to_block (&block, &se.pre); 6900 1.1 mrg 6901 1.1 mrg /* Error checking -- Note: ERRMSG only makes sense with STAT. */ 6902 1.1 mrg if (code->expr1) 6903 1.1 mrg { 6904 1.1 mrg tmp = build1_v (GOTO_EXPR, label_errmsg); 6905 1.1 mrg parm = fold_build2_loc (input_location, NE_EXPR, 6906 1.1 mrg logical_type_node, stat, 6907 1.1 mrg build_int_cst (TREE_TYPE (stat), 0)); 6908 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, 6909 1.1 mrg gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC), 6910 1.1 mrg tmp, build_empty_stmt (input_location)); 6911 1.1 mrg gfc_add_expr_to_block (&block, tmp); 6912 1.1 mrg } 6913 1.1 mrg 6914 1.1 mrg /* Set the vptr only when no source= is set. When source= is set, then 6915 1.1 mrg the trans_assignment below will set the vptr. */ 6916 1.1 mrg if (al_vptr != NULL_TREE && (!code->expr3 || code->expr3->mold)) 6917 1.1 mrg { 6918 1.1 mrg if (expr3_vptr != NULL_TREE) 6919 1.1 mrg /* The vtab is already known, so just assign it. */ 6920 1.1 mrg gfc_add_modify (&block, al_vptr, 6921 1.1 mrg fold_convert (TREE_TYPE (al_vptr), expr3_vptr)); 6922 1.1 mrg else 6923 1.1 mrg { 6924 1.1 mrg /* VPTR is fixed at compile time. */ 6925 1.1 mrg gfc_symbol *vtab; 6926 1.1 mrg gfc_typespec *ts; 6927 1.1 mrg 6928 1.1 mrg if (code->expr3) 6929 1.1 mrg /* Although expr3 is pre-evaluated above, it may happen, 6930 1.1 mrg that for arrays or in mold= cases the pre-evaluation 6931 1.1 mrg was not successful. In these rare cases take the vtab 6932 1.1 mrg from the typespec of expr3 here. */ 6933 1.1 mrg ts = &code->expr3->ts; 6934 1.1 mrg else if (code->ext.alloc.ts.type == BT_DERIVED || upoly_expr) 6935 1.1 mrg /* The alloc_type_spec gives the type to allocate or the 6936 1.1 mrg al is unlimited polymorphic, which enforces the use of 6937 1.1 mrg an alloc_type_spec that is not necessarily a BT_DERIVED. */ 6938 1.1 mrg ts = &code->ext.alloc.ts; 6939 1.1 mrg else 6940 1.1 mrg /* Prepare for setting the vtab as declared. */ 6941 1.1 mrg ts = &expr->ts; 6942 1.1 mrg 6943 1.1 mrg vtab = gfc_find_vtab (ts); 6944 1.1 mrg gcc_assert (vtab); 6945 1.1 mrg tmp = gfc_build_addr_expr (NULL_TREE, 6946 1.1 mrg gfc_get_symbol_decl (vtab)); 6947 1.1 mrg gfc_add_modify (&block, al_vptr, 6948 1.1 mrg fold_convert (TREE_TYPE (al_vptr), tmp)); 6949 1.1 mrg } 6950 1.1 mrg } 6951 1.1 mrg 6952 1.1 mrg /* Add assignment for string length. */ 6953 1.1 mrg if (al_len != NULL_TREE && al_len_needs_set) 6954 1.1 mrg { 6955 1.1 mrg if (expr3_len != NULL_TREE) 6956 1.1 mrg { 6957 1.1 mrg gfc_add_modify (&block, al_len, 6958 1.1 mrg fold_convert (TREE_TYPE (al_len), 6959 1.1 mrg expr3_len)); 6960 1.1 mrg /* When tmp_expr3_len_flag is set, then expr3_len is 6961 1.1 mrg abused to carry the length information from the 6962 1.1 mrg alloc_type. Clear it to prevent setting incorrect len 6963 1.1 mrg information in future loop iterations. */ 6964 1.1 mrg if (tmp_expr3_len_flag) 6965 1.1 mrg /* No need to reset tmp_expr3_len_flag, because the 6966 1.1 mrg presence of an expr3 cannot change within in the 6967 1.1 mrg loop. */ 6968 1.1 mrg expr3_len = NULL_TREE; 6969 1.1 mrg } 6970 1.1 mrg else if (code->ext.alloc.ts.type == BT_CHARACTER 6971 1.1 mrg && code->ext.alloc.ts.u.cl->length) 6972 1.1 mrg { 6973 1.1 mrg /* Cover the cases where a string length is explicitly 6974 1.1 mrg specified by a type spec for deferred length character 6975 1.1 mrg arrays or unlimited polymorphic objects without a 6976 1.1 mrg source= or mold= expression. */ 6977 1.1 mrg if (expr3_esize == NULL_TREE || code->ext.alloc.ts.kind != 1) 6978 1.1 mrg { 6979 1.1 mrg gfc_init_se (&se_sz, NULL); 6980 1.1 mrg gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length); 6981 1.1 mrg gfc_add_block_to_block (&block, &se_sz.pre); 6982 1.1 mrg gfc_add_modify (&block, al_len, 6983 1.1 mrg fold_convert (TREE_TYPE (al_len), 6984 1.1 mrg se_sz.expr)); 6985 1.1 mrg } 6986 1.1 mrg else 6987 1.1 mrg gfc_add_modify (&block, al_len, 6988 1.1 mrg fold_convert (TREE_TYPE (al_len), 6989 1.1 mrg expr3_esize)); 6990 1.1 mrg } 6991 1.1 mrg else 6992 1.1 mrg /* No length information needed, because type to allocate 6993 1.1 mrg has no length. Set _len to 0. */ 6994 1.1 mrg gfc_add_modify (&block, al_len, 6995 1.1 mrg fold_convert (TREE_TYPE (al_len), 6996 1.1 mrg integer_zero_node)); 6997 1.1 mrg } 6998 1.1 mrg 6999 1.1 mrg init_expr = NULL; 7000 1.1 mrg if (code->expr3 && !code->expr3->mold && e3_is != E3_MOLD) 7001 1.1 mrg { 7002 1.1 mrg /* Initialization via SOURCE block (or static default initializer). 7003 1.1 mrg Switch off automatic reallocation since we have just done the 7004 1.1 mrg ALLOCATE. */ 7005 1.1 mrg int realloc_lhs = flag_realloc_lhs; 7006 1.1 mrg gfc_expr *init_expr = gfc_expr_to_initialize (expr); 7007 1.1 mrg gfc_expr *rhs = e3rhs ? e3rhs : gfc_copy_expr (code->expr3); 7008 1.1 mrg flag_realloc_lhs = 0; 7009 1.1 mrg tmp = gfc_trans_assignment (init_expr, rhs, true, false, true, 7010 1.1 mrg false); 7011 1.1 mrg flag_realloc_lhs = realloc_lhs; 7012 1.1 mrg /* Free the expression allocated for init_expr. */ 7013 1.1 mrg gfc_free_expr (init_expr); 7014 1.1 mrg if (rhs != e3rhs) 7015 1.1 mrg gfc_free_expr (rhs); 7016 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7017 1.1 mrg } 7018 1.1 mrg /* Set KIND and LEN PDT components and allocate those that are 7019 1.1 mrg parameterized. */ 7020 1.1 mrg else if (expr->ts.type == BT_DERIVED 7021 1.1 mrg && expr->ts.u.derived->attr.pdt_type) 7022 1.1 mrg { 7023 1.1 mrg if (code->expr3 && code->expr3->param_list) 7024 1.1 mrg param_list = code->expr3->param_list; 7025 1.1 mrg else if (expr->param_list) 7026 1.1 mrg param_list = expr->param_list; 7027 1.1 mrg else 7028 1.1 mrg param_list = expr->symtree->n.sym->param_list; 7029 1.1 mrg tmp = gfc_allocate_pdt_comp (expr->ts.u.derived, se.expr, 7030 1.1 mrg expr->rank, param_list); 7031 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7032 1.1 mrg } 7033 1.1 mrg /* Ditto for CLASS expressions. */ 7034 1.1 mrg else if (expr->ts.type == BT_CLASS 7035 1.1 mrg && CLASS_DATA (expr)->ts.u.derived->attr.pdt_type) 7036 1.1 mrg { 7037 1.1 mrg if (code->expr3 && code->expr3->param_list) 7038 1.1 mrg param_list = code->expr3->param_list; 7039 1.1 mrg else if (expr->param_list) 7040 1.1 mrg param_list = expr->param_list; 7041 1.1 mrg else 7042 1.1 mrg param_list = expr->symtree->n.sym->param_list; 7043 1.1 mrg tmp = gfc_allocate_pdt_comp (CLASS_DATA (expr)->ts.u.derived, 7044 1.1 mrg se.expr, expr->rank, param_list); 7045 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7046 1.1 mrg } 7047 1.1 mrg else if (code->expr3 && code->expr3->mold 7048 1.1 mrg && code->expr3->ts.type == BT_CLASS) 7049 1.1 mrg { 7050 1.1 mrg /* Use class_init_assign to initialize expr. */ 7051 1.1 mrg gfc_code *ini; 7052 1.1 mrg ini = gfc_get_code (EXEC_INIT_ASSIGN); 7053 1.1 mrg ini->expr1 = gfc_find_and_cut_at_last_class_ref (expr, true); 7054 1.1 mrg tmp = gfc_trans_class_init_assign (ini); 7055 1.1 mrg gfc_free_statements (ini); 7056 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7057 1.1 mrg } 7058 1.1 mrg else if ((init_expr = allocate_get_initializer (code, expr))) 7059 1.1 mrg { 7060 1.1 mrg /* Use class_init_assign to initialize expr. */ 7061 1.1 mrg gfc_code *ini; 7062 1.1 mrg int realloc_lhs = flag_realloc_lhs; 7063 1.1 mrg ini = gfc_get_code (EXEC_INIT_ASSIGN); 7064 1.1 mrg ini->expr1 = gfc_expr_to_initialize (expr); 7065 1.1 mrg ini->expr2 = init_expr; 7066 1.1 mrg flag_realloc_lhs = 0; 7067 1.1 mrg tmp= gfc_trans_init_assign (ini); 7068 1.1 mrg flag_realloc_lhs = realloc_lhs; 7069 1.1 mrg gfc_free_statements (ini); 7070 1.1 mrg /* Init_expr is freeed by above free_statements, just need to null 7071 1.1 mrg it here. */ 7072 1.1 mrg init_expr = NULL; 7073 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7074 1.1 mrg } 7075 1.1 mrg 7076 1.1 mrg /* Nullify all pointers in derived type coarrays. This registers a 7077 1.1 mrg token for them which allows their allocation. */ 7078 1.1 mrg if (is_coarray) 7079 1.1 mrg { 7080 1.1 mrg gfc_symbol *type = NULL; 7081 1.1 mrg symbol_attribute caf_attr; 7082 1.1 mrg int rank = 0; 7083 1.1 mrg if (code->ext.alloc.ts.type == BT_DERIVED 7084 1.1 mrg && code->ext.alloc.ts.u.derived->attr.pointer_comp) 7085 1.1 mrg { 7086 1.1 mrg type = code->ext.alloc.ts.u.derived; 7087 1.1 mrg rank = type->attr.dimension ? type->as->rank : 0; 7088 1.1 mrg gfc_clear_attr (&caf_attr); 7089 1.1 mrg } 7090 1.1 mrg else if (expr->ts.type == BT_DERIVED 7091 1.1 mrg && expr->ts.u.derived->attr.pointer_comp) 7092 1.1 mrg { 7093 1.1 mrg type = expr->ts.u.derived; 7094 1.1 mrg rank = expr->rank; 7095 1.1 mrg caf_attr = gfc_caf_attr (expr, true); 7096 1.1 mrg } 7097 1.1 mrg 7098 1.1 mrg /* Initialize the tokens of pointer components in derived type 7099 1.1 mrg coarrays. */ 7100 1.1 mrg if (type) 7101 1.1 mrg { 7102 1.1 mrg tmp = (caf_attr.codimension && !caf_attr.dimension) 7103 1.1 mrg ? gfc_conv_descriptor_data_get (se.expr) : se.expr; 7104 1.1 mrg tmp = gfc_nullify_alloc_comp (type, tmp, rank, 7105 1.1 mrg GFC_STRUCTURE_CAF_MODE_IN_COARRAY); 7106 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7107 1.1 mrg } 7108 1.1 mrg } 7109 1.1 mrg 7110 1.1 mrg gfc_free_expr (expr); 7111 1.1 mrg } // for-loop 7112 1.1 mrg 7113 1.1 mrg if (e3rhs) 7114 1.1 mrg { 7115 1.1 mrg if (newsym) 7116 1.1 mrg { 7117 1.1 mrg gfc_free_symbol (newsym->n.sym); 7118 1.1 mrg XDELETE (newsym); 7119 1.1 mrg } 7120 1.1 mrg gfc_free_expr (e3rhs); 7121 1.1 mrg } 7122 1.1 mrg /* STAT. */ 7123 1.1 mrg if (code->expr1) 7124 1.1 mrg { 7125 1.1 mrg tmp = build1_v (LABEL_EXPR, label_errmsg); 7126 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7127 1.1 mrg } 7128 1.1 mrg 7129 1.1 mrg /* ERRMSG - only useful if STAT is present. */ 7130 1.1 mrg if (code->expr1 && code->expr2) 7131 1.1 mrg { 7132 1.1 mrg const char *msg = "Attempt to allocate an allocated object"; 7133 1.1 mrg tree slen, dlen, errmsg_str; 7134 1.1 mrg stmtblock_t errmsg_block; 7135 1.1 mrg 7136 1.1 mrg gfc_init_block (&errmsg_block); 7137 1.1 mrg 7138 1.1 mrg errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG"); 7139 1.1 mrg gfc_add_modify (&errmsg_block, errmsg_str, 7140 1.1 mrg gfc_build_addr_expr (pchar_type_node, 7141 1.1 mrg gfc_build_localized_cstring_const (msg))); 7142 1.1 mrg 7143 1.1 mrg slen = build_int_cst (gfc_charlen_type_node, strlen (msg)); 7144 1.1 mrg dlen = gfc_get_expr_charlen (code->expr2); 7145 1.1 mrg slen = fold_build2_loc (input_location, MIN_EXPR, 7146 1.1 mrg TREE_TYPE (slen), dlen, slen); 7147 1.1 mrg 7148 1.1 mrg gfc_trans_string_copy (&errmsg_block, dlen, errmsg, 7149 1.1 mrg code->expr2->ts.kind, 7150 1.1 mrg slen, errmsg_str, 7151 1.1 mrg gfc_default_character_kind); 7152 1.1 mrg dlen = gfc_finish_block (&errmsg_block); 7153 1.1 mrg 7154 1.1 mrg tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, 7155 1.1 mrg stat, build_int_cst (TREE_TYPE (stat), 0)); 7156 1.1 mrg 7157 1.1 mrg tmp = build3_v (COND_EXPR, tmp, 7158 1.1 mrg dlen, build_empty_stmt (input_location)); 7159 1.1 mrg 7160 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7161 1.1 mrg } 7162 1.1 mrg 7163 1.1 mrg /* STAT block. */ 7164 1.1 mrg if (code->expr1) 7165 1.1 mrg { 7166 1.1 mrg if (TREE_USED (label_finish)) 7167 1.1 mrg { 7168 1.1 mrg tmp = build1_v (LABEL_EXPR, label_finish); 7169 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7170 1.1 mrg } 7171 1.1 mrg 7172 1.1 mrg gfc_init_se (&se, NULL); 7173 1.1 mrg gfc_conv_expr_lhs (&se, code->expr1); 7174 1.1 mrg tmp = convert (TREE_TYPE (se.expr), stat); 7175 1.1 mrg gfc_add_modify (&block, se.expr, tmp); 7176 1.1 mrg } 7177 1.1 mrg 7178 1.1 mrg if (needs_caf_sync) 7179 1.1 mrg { 7180 1.1 mrg /* Add a sync all after the allocation has been executed. */ 7181 1.1 mrg tree zero_size = build_zero_cst (size_type_node); 7182 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all, 7183 1.1 mrg 3, null_pointer_node, null_pointer_node, 7184 1.1 mrg zero_size); 7185 1.1 mrg gfc_add_expr_to_block (&post, tmp); 7186 1.1 mrg } 7187 1.1 mrg 7188 1.1 mrg gfc_add_block_to_block (&block, &se.post); 7189 1.1 mrg gfc_add_block_to_block (&block, &post); 7190 1.1 mrg if (code->expr3 && code->expr3->must_finalize) 7191 1.1 mrg gfc_add_block_to_block (&block, &final_block); 7192 1.1 mrg 7193 1.1 mrg return gfc_finish_block (&block); 7194 1.1 mrg } 7195 1.1 mrg 7196 1.1 mrg 7197 1.1 mrg /* Translate a DEALLOCATE statement. */ 7198 1.1 mrg 7199 1.1 mrg tree 7200 1.1 mrg gfc_trans_deallocate (gfc_code *code) 7201 1.1 mrg { 7202 1.1 mrg gfc_se se; 7203 1.1 mrg gfc_alloc *al; 7204 1.1 mrg tree apstat, pstat, stat, errmsg, errlen, tmp; 7205 1.1 mrg tree label_finish, label_errmsg; 7206 1.1 mrg stmtblock_t block; 7207 1.1 mrg 7208 1.1 mrg pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE; 7209 1.1 mrg label_finish = label_errmsg = NULL_TREE; 7210 1.1 mrg 7211 1.1 mrg gfc_start_block (&block); 7212 1.1 mrg 7213 1.1 mrg /* Count the number of failed deallocations. If deallocate() was 7214 1.1 mrg called with STAT= , then set STAT to the count. If deallocate 7215 1.1 mrg was called with ERRMSG, then set ERRMG to a string. */ 7216 1.1 mrg if (code->expr1) 7217 1.1 mrg { 7218 1.1 mrg tree gfc_int4_type_node = gfc_get_int_type (4); 7219 1.1 mrg 7220 1.1 mrg stat = gfc_create_var (gfc_int4_type_node, "stat"); 7221 1.1 mrg pstat = gfc_build_addr_expr (NULL_TREE, stat); 7222 1.1 mrg 7223 1.1 mrg /* GOTO destinations. */ 7224 1.1 mrg label_errmsg = gfc_build_label_decl (NULL_TREE); 7225 1.1 mrg label_finish = gfc_build_label_decl (NULL_TREE); 7226 1.1 mrg TREE_USED (label_finish) = 0; 7227 1.1 mrg } 7228 1.1 mrg 7229 1.1 mrg /* Set ERRMSG - only needed if STAT is available. */ 7230 1.1 mrg if (code->expr1 && code->expr2) 7231 1.1 mrg { 7232 1.1 mrg gfc_init_se (&se, NULL); 7233 1.1 mrg se.want_pointer = 1; 7234 1.1 mrg gfc_conv_expr_lhs (&se, code->expr2); 7235 1.1 mrg errmsg = se.expr; 7236 1.1 mrg errlen = se.string_length; 7237 1.1 mrg } 7238 1.1 mrg 7239 1.1 mrg for (al = code->ext.alloc.list; al != NULL; al = al->next) 7240 1.1 mrg { 7241 1.1 mrg gfc_expr *expr = gfc_copy_expr (al->expr); 7242 1.1 mrg bool is_coarray = false, is_coarray_array = false; 7243 1.1 mrg int caf_mode = 0; 7244 1.1 mrg 7245 1.1 mrg gcc_assert (expr->expr_type == EXPR_VARIABLE); 7246 1.1 mrg 7247 1.1 mrg if (expr->ts.type == BT_CLASS) 7248 1.1 mrg gfc_add_data_component (expr); 7249 1.1 mrg 7250 1.1 mrg gfc_init_se (&se, NULL); 7251 1.1 mrg gfc_start_block (&se.pre); 7252 1.1 mrg 7253 1.1 mrg se.want_pointer = 1; 7254 1.1 mrg se.descriptor_only = 1; 7255 1.1 mrg gfc_conv_expr (&se, expr); 7256 1.1 mrg 7257 1.1 mrg /* Deallocate PDT components that are parameterized. */ 7258 1.1 mrg tmp = NULL; 7259 1.1 mrg if (expr->ts.type == BT_DERIVED 7260 1.1 mrg && expr->ts.u.derived->attr.pdt_type 7261 1.1 mrg && expr->symtree->n.sym->param_list) 7262 1.1 mrg tmp = gfc_deallocate_pdt_comp (expr->ts.u.derived, se.expr, expr->rank); 7263 1.1 mrg else if (expr->ts.type == BT_CLASS 7264 1.1 mrg && CLASS_DATA (expr)->ts.u.derived->attr.pdt_type 7265 1.1 mrg && expr->symtree->n.sym->param_list) 7266 1.1 mrg tmp = gfc_deallocate_pdt_comp (CLASS_DATA (expr)->ts.u.derived, 7267 1.1 mrg se.expr, expr->rank); 7268 1.1 mrg 7269 1.1 mrg if (tmp) 7270 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7271 1.1 mrg 7272 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB 7273 1.1 mrg || flag_coarray == GFC_FCOARRAY_SINGLE) 7274 1.1 mrg { 7275 1.1 mrg bool comp_ref; 7276 1.1 mrg symbol_attribute caf_attr = gfc_caf_attr (expr, false, &comp_ref); 7277 1.1 mrg if (caf_attr.codimension) 7278 1.1 mrg { 7279 1.1 mrg is_coarray = true; 7280 1.1 mrg is_coarray_array = caf_attr.dimension || !comp_ref 7281 1.1 mrg || caf_attr.coarray_comp; 7282 1.1 mrg 7283 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB) 7284 1.1 mrg /* When the expression to deallocate is referencing a 7285 1.1 mrg component, then only deallocate it, but do not 7286 1.1 mrg deregister. */ 7287 1.1 mrg caf_mode = GFC_STRUCTURE_CAF_MODE_IN_COARRAY 7288 1.1 mrg | (comp_ref && !caf_attr.coarray_comp 7289 1.1 mrg ? GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY : 0); 7290 1.1 mrg } 7291 1.1 mrg } 7292 1.1 mrg 7293 1.1 mrg if (expr->rank || is_coarray_array) 7294 1.1 mrg { 7295 1.1 mrg gfc_ref *ref; 7296 1.1 mrg 7297 1.1 mrg if (gfc_bt_struct (expr->ts.type) 7298 1.1 mrg && expr->ts.u.derived->attr.alloc_comp 7299 1.1 mrg && !gfc_is_finalizable (expr->ts.u.derived, NULL)) 7300 1.1 mrg { 7301 1.1 mrg gfc_ref *last = NULL; 7302 1.1 mrg 7303 1.1 mrg for (ref = expr->ref; ref; ref = ref->next) 7304 1.1 mrg if (ref->type == REF_COMPONENT) 7305 1.1 mrg last = ref; 7306 1.1 mrg 7307 1.1 mrg /* Do not deallocate the components of a derived type 7308 1.1 mrg ultimate pointer component. */ 7309 1.1 mrg if (!(last && last->u.c.component->attr.pointer) 7310 1.1 mrg && !(!last && expr->symtree->n.sym->attr.pointer)) 7311 1.1 mrg { 7312 1.1 mrg if (is_coarray && expr->rank == 0 7313 1.1 mrg && (!last || !last->u.c.component->attr.dimension) 7314 1.1 mrg && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))) 7315 1.1 mrg { 7316 1.1 mrg /* Add the ref to the data member only, when this is not 7317 1.1 mrg a regular array or deallocate_alloc_comp will try to 7318 1.1 mrg add another one. */ 7319 1.1 mrg tmp = gfc_conv_descriptor_data_get (se.expr); 7320 1.1 mrg } 7321 1.1 mrg else 7322 1.1 mrg tmp = se.expr; 7323 1.1 mrg tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, 7324 1.1 mrg expr->rank, caf_mode); 7325 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 7326 1.1 mrg } 7327 1.1 mrg } 7328 1.1 mrg 7329 1.1 mrg if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))) 7330 1.1 mrg { 7331 1.1 mrg gfc_coarray_deregtype caf_dtype; 7332 1.1 mrg 7333 1.1 mrg if (is_coarray) 7334 1.1 mrg caf_dtype = gfc_caf_is_dealloc_only (caf_mode) 7335 1.1 mrg ? GFC_CAF_COARRAY_DEALLOCATE_ONLY 7336 1.1 mrg : GFC_CAF_COARRAY_DEREGISTER; 7337 1.1 mrg else 7338 1.1 mrg caf_dtype = GFC_CAF_COARRAY_NOCOARRAY; 7339 1.1 mrg tmp = gfc_deallocate_with_status (se.expr, pstat, errmsg, errlen, 7340 1.1 mrg label_finish, false, expr, 7341 1.1 mrg caf_dtype); 7342 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 7343 1.1 mrg } 7344 1.1 mrg else if (TREE_CODE (se.expr) == COMPONENT_REF 7345 1.1 mrg && TREE_CODE (TREE_TYPE (se.expr)) == ARRAY_TYPE 7346 1.1 mrg && TREE_CODE (TREE_TYPE (TREE_TYPE (se.expr))) 7347 1.1 mrg == RECORD_TYPE) 7348 1.1 mrg { 7349 1.1 mrg /* class.cc(finalize_component) generates these, when a 7350 1.1 mrg finalizable entity has a non-allocatable derived type array 7351 1.1 mrg component, which has allocatable components. Obtain the 7352 1.1 mrg derived type of the array and deallocate the allocatable 7353 1.1 mrg components. */ 7354 1.1 mrg for (ref = expr->ref; ref; ref = ref->next) 7355 1.1 mrg { 7356 1.1 mrg if (ref->u.c.component->attr.dimension 7357 1.1 mrg && ref->u.c.component->ts.type == BT_DERIVED) 7358 1.1 mrg break; 7359 1.1 mrg } 7360 1.1 mrg 7361 1.1 mrg if (ref && ref->u.c.component->ts.u.derived->attr.alloc_comp 7362 1.1 mrg && !gfc_is_finalizable (ref->u.c.component->ts.u.derived, 7363 1.1 mrg NULL)) 7364 1.1 mrg { 7365 1.1 mrg tmp = gfc_deallocate_alloc_comp 7366 1.1 mrg (ref->u.c.component->ts.u.derived, 7367 1.1 mrg se.expr, expr->rank); 7368 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 7369 1.1 mrg } 7370 1.1 mrg } 7371 1.1 mrg 7372 1.1 mrg if (al->expr->ts.type == BT_CLASS) 7373 1.1 mrg { 7374 1.1 mrg gfc_reset_vptr (&se.pre, al->expr); 7375 1.1 mrg if (UNLIMITED_POLY (al->expr) 7376 1.1 mrg || (al->expr->ts.type == BT_DERIVED 7377 1.1 mrg && al->expr->ts.u.derived->attr.unlimited_polymorphic)) 7378 1.1 mrg /* Clear _len, too. */ 7379 1.1 mrg gfc_reset_len (&se.pre, al->expr); 7380 1.1 mrg } 7381 1.1 mrg } 7382 1.1 mrg else 7383 1.1 mrg { 7384 1.1 mrg tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, label_finish, 7385 1.1 mrg false, al->expr, 7386 1.1 mrg al->expr->ts, is_coarray); 7387 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 7388 1.1 mrg 7389 1.1 mrg /* Set to zero after deallocation. */ 7390 1.1 mrg tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, 7391 1.1 mrg se.expr, 7392 1.1 mrg build_int_cst (TREE_TYPE (se.expr), 0)); 7393 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 7394 1.1 mrg 7395 1.1 mrg if (al->expr->ts.type == BT_CLASS) 7396 1.1 mrg { 7397 1.1 mrg gfc_reset_vptr (&se.pre, al->expr); 7398 1.1 mrg if (UNLIMITED_POLY (al->expr) 7399 1.1 mrg || (al->expr->ts.type == BT_DERIVED 7400 1.1 mrg && al->expr->ts.u.derived->attr.unlimited_polymorphic)) 7401 1.1 mrg /* Clear _len, too. */ 7402 1.1 mrg gfc_reset_len (&se.pre, al->expr); 7403 1.1 mrg } 7404 1.1 mrg } 7405 1.1 mrg 7406 1.1 mrg if (code->expr1) 7407 1.1 mrg { 7408 1.1 mrg tree cond; 7409 1.1 mrg 7410 1.1 mrg cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, stat, 7411 1.1 mrg build_int_cst (TREE_TYPE (stat), 0)); 7412 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, 7413 1.1 mrg gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), 7414 1.1 mrg build1_v (GOTO_EXPR, label_errmsg), 7415 1.1 mrg build_empty_stmt (input_location)); 7416 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp); 7417 1.1 mrg } 7418 1.1 mrg 7419 1.1 mrg tmp = gfc_finish_block (&se.pre); 7420 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7421 1.1 mrg gfc_free_expr (expr); 7422 1.1 mrg } 7423 1.1 mrg 7424 1.1 mrg if (code->expr1) 7425 1.1 mrg { 7426 1.1 mrg tmp = build1_v (LABEL_EXPR, label_errmsg); 7427 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7428 1.1 mrg } 7429 1.1 mrg 7430 1.1 mrg /* Set ERRMSG - only needed if STAT is available. */ 7431 1.1 mrg if (code->expr1 && code->expr2) 7432 1.1 mrg { 7433 1.1 mrg const char *msg = "Attempt to deallocate an unallocated object"; 7434 1.1 mrg stmtblock_t errmsg_block; 7435 1.1 mrg tree errmsg_str, slen, dlen, cond; 7436 1.1 mrg 7437 1.1 mrg gfc_init_block (&errmsg_block); 7438 1.1 mrg 7439 1.1 mrg errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG"); 7440 1.1 mrg gfc_add_modify (&errmsg_block, errmsg_str, 7441 1.1 mrg gfc_build_addr_expr (pchar_type_node, 7442 1.1 mrg gfc_build_localized_cstring_const (msg))); 7443 1.1 mrg slen = build_int_cst (gfc_charlen_type_node, strlen (msg)); 7444 1.1 mrg dlen = gfc_get_expr_charlen (code->expr2); 7445 1.1 mrg 7446 1.1 mrg gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind, 7447 1.1 mrg slen, errmsg_str, gfc_default_character_kind); 7448 1.1 mrg tmp = gfc_finish_block (&errmsg_block); 7449 1.1 mrg 7450 1.1 mrg cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, stat, 7451 1.1 mrg build_int_cst (TREE_TYPE (stat), 0)); 7452 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, 7453 1.1 mrg gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp, 7454 1.1 mrg build_empty_stmt (input_location)); 7455 1.1 mrg 7456 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7457 1.1 mrg } 7458 1.1 mrg 7459 1.1 mrg if (code->expr1 && TREE_USED (label_finish)) 7460 1.1 mrg { 7461 1.1 mrg tmp = build1_v (LABEL_EXPR, label_finish); 7462 1.1 mrg gfc_add_expr_to_block (&block, tmp); 7463 1.1 mrg } 7464 1.1 mrg 7465 1.1 mrg /* Set STAT. */ 7466 1.1 mrg if (code->expr1) 7467 1.1 mrg { 7468 1.1 mrg gfc_init_se (&se, NULL); 7469 1.1 mrg gfc_conv_expr_lhs (&se, code->expr1); 7470 1.1 mrg tmp = convert (TREE_TYPE (se.expr), stat); 7471 1.1 mrg gfc_add_modify (&block, se.expr, tmp); 7472 1.1 mrg } 7473 1.1 mrg 7474 1.1 mrg return gfc_finish_block (&block); 7475 1.1 mrg } 7476 1.1 mrg 7477 1.1 mrg #include "gt-fortran-trans-stmt.h" 7478