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