1 /* d-codegen.cc -- Code generation and routines for manipulation of GCC trees. 2 Copyright (C) 2006-2019 Free Software Foundation, Inc. 3 4 GCC is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 3, or (at your option) 7 any later version. 8 9 GCC is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with GCC; see the file COPYING3. If not see 16 <http://www.gnu.org/licenses/>. */ 17 18 #include "config.h" 19 #include "system.h" 20 #include "coretypes.h" 21 22 #include "dmd/aggregate.h" 23 #include "dmd/ctfe.h" 24 #include "dmd/declaration.h" 25 #include "dmd/identifier.h" 26 #include "dmd/target.h" 27 #include "dmd/template.h" 28 29 #include "tree.h" 30 #include "tree-iterator.h" 31 #include "fold-const.h" 32 #include "diagnostic.h" 33 #include "langhooks.h" 34 #include "target.h" 35 #include "stringpool.h" 36 #include "varasm.h" 37 #include "stor-layout.h" 38 #include "attribs.h" 39 #include "function.h" 40 41 #include "d-tree.h" 42 43 44 /* Return the GCC location for the D frontend location LOC. */ 45 46 location_t 47 make_location_t (const Loc& loc) 48 { 49 location_t gcc_location = input_location; 50 51 if (loc.filename) 52 { 53 linemap_add (line_table, LC_ENTER, 0, loc.filename, loc.linnum); 54 linemap_line_start (line_table, loc.linnum, 0); 55 gcc_location = linemap_position_for_column (line_table, loc.charnum); 56 linemap_add (line_table, LC_LEAVE, 0, NULL, 0); 57 } 58 59 return gcc_location; 60 } 61 62 /* Return the DECL_CONTEXT for symbol DSYM. */ 63 64 tree 65 d_decl_context (Dsymbol *dsym) 66 { 67 Dsymbol *parent = dsym; 68 Declaration *decl = dsym->isDeclaration (); 69 70 while ((parent = parent->toParent2 ())) 71 { 72 /* We've reached the top-level module namespace. 73 Set DECL_CONTEXT as the NAMESPACE_DECL of the enclosing module, 74 but only for extern(D) symbols. */ 75 if (parent->isModule ()) 76 { 77 if (decl != NULL && decl->linkage != LINKd) 78 return NULL_TREE; 79 80 return build_import_decl (parent); 81 } 82 83 /* Declarations marked as 'static' or '__gshared' are never 84 part of any context except at module level. */ 85 if (decl != NULL && decl->isDataseg ()) 86 continue; 87 88 /* Nested functions. */ 89 FuncDeclaration *fd = parent->isFuncDeclaration (); 90 if (fd != NULL) 91 return get_symbol_decl (fd); 92 93 /* Methods of classes or structs. */ 94 AggregateDeclaration *ad = parent->isAggregateDeclaration (); 95 if (ad != NULL) 96 { 97 tree context = build_ctype (ad->type); 98 /* Want the underlying RECORD_TYPE. */ 99 if (ad->isClassDeclaration ()) 100 context = TREE_TYPE (context); 101 102 return context; 103 } 104 } 105 106 return NULL_TREE; 107 } 108 109 /* Return a copy of record TYPE but safe to modify in any way. */ 110 111 tree 112 copy_aggregate_type (tree type) 113 { 114 tree newtype = build_distinct_type_copy (type); 115 TYPE_FIELDS (newtype) = copy_list (TYPE_FIELDS (type)); 116 117 for (tree f = TYPE_FIELDS (newtype); f; f = DECL_CHAIN (f)) 118 DECL_FIELD_CONTEXT (f) = newtype; 119 120 return newtype; 121 } 122 123 /* Return TRUE if declaration DECL is a reference type. */ 124 125 bool 126 declaration_reference_p (Declaration *decl) 127 { 128 Type *tb = decl->type->toBasetype (); 129 130 /* Declaration is a reference type. */ 131 if (tb->ty == Treference || decl->storage_class & (STCout | STCref)) 132 return true; 133 134 return false; 135 } 136 137 /* Returns the real type for declaration DECL. */ 138 139 tree 140 declaration_type (Declaration *decl) 141 { 142 /* Lazy declarations are converted to delegates. */ 143 if (decl->storage_class & STClazy) 144 { 145 TypeFunction *tf = TypeFunction::create (NULL, decl->type, false, LINKd); 146 TypeDelegate *t = TypeDelegate::create (tf); 147 return build_ctype (t->merge2 ()); 148 } 149 150 /* Static array va_list have array->pointer conversions applied. */ 151 if (decl->isParameter () && valist_array_p (decl->type)) 152 { 153 Type *valist = decl->type->nextOf ()->pointerTo (); 154 valist = valist->castMod (decl->type->mod); 155 return build_ctype (valist); 156 } 157 158 tree type = build_ctype (decl->type); 159 160 /* Parameter is passed by reference. */ 161 if (declaration_reference_p (decl)) 162 return build_reference_type (type); 163 164 /* The 'this' parameter is always const. */ 165 if (decl->isThisDeclaration ()) 166 return insert_type_modifiers (type, MODconst); 167 168 return type; 169 } 170 171 /* These should match the Declaration versions above 172 Return TRUE if parameter ARG is a reference type. */ 173 174 bool 175 argument_reference_p (Parameter *arg) 176 { 177 Type *tb = arg->type->toBasetype (); 178 179 /* Parameter is a reference type. */ 180 if (tb->ty == Treference || arg->storageClass & (STCout | STCref)) 181 return true; 182 183 tree type = build_ctype (arg->type); 184 if (TREE_ADDRESSABLE (type)) 185 return true; 186 187 return false; 188 } 189 190 /* Returns the real type for parameter ARG. */ 191 192 tree 193 type_passed_as (Parameter *arg) 194 { 195 /* Lazy parameters are converted to delegates. */ 196 if (arg->storageClass & STClazy) 197 { 198 TypeFunction *tf = TypeFunction::create (NULL, arg->type, false, LINKd); 199 TypeDelegate *t = TypeDelegate::create (tf); 200 return build_ctype (t->merge2 ()); 201 } 202 203 /* Static array va_list have array->pointer conversions applied. */ 204 if (valist_array_p (arg->type)) 205 { 206 Type *valist = arg->type->nextOf ()->pointerTo (); 207 valist = valist->castMod (arg->type->mod); 208 return build_ctype (valist); 209 } 210 211 tree type = build_ctype (arg->type); 212 213 /* Parameter is passed by reference. */ 214 if (argument_reference_p (arg)) 215 return build_reference_type (type); 216 217 return type; 218 } 219 220 /* Build INTEGER_CST of type TYPE with the value VALUE. */ 221 222 tree 223 build_integer_cst (dinteger_t value, tree type) 224 { 225 /* The type is error_mark_node, we can't do anything. */ 226 if (error_operand_p (type)) 227 return type; 228 229 return build_int_cst_type (type, value); 230 } 231 232 /* Build REAL_CST of type TOTYPE with the value VALUE. */ 233 234 tree 235 build_float_cst (const real_t& value, Type *totype) 236 { 237 real_t new_value; 238 TypeBasic *tb = totype->isTypeBasic (); 239 240 gcc_assert (tb != NULL); 241 242 tree type_node = build_ctype (tb); 243 real_convert (&new_value.rv (), TYPE_MODE (type_node), &value.rv ()); 244 245 return build_real (type_node, new_value.rv ()); 246 } 247 248 /* Returns the .length component from the D dynamic array EXP. */ 249 250 tree 251 d_array_length (tree exp) 252 { 253 if (error_operand_p (exp)) 254 return exp; 255 256 gcc_assert (TYPE_DYNAMIC_ARRAY (TREE_TYPE (exp))); 257 258 /* Get the back-end type for the array and pick out the array 259 length field (assumed to be the first field). */ 260 tree len_field = TYPE_FIELDS (TREE_TYPE (exp)); 261 return component_ref (exp, len_field); 262 } 263 264 /* Returns the .ptr component from the D dynamic array EXP. */ 265 266 tree 267 d_array_ptr (tree exp) 268 { 269 if (error_operand_p (exp)) 270 return exp; 271 272 gcc_assert (TYPE_DYNAMIC_ARRAY (TREE_TYPE (exp))); 273 274 /* Get the back-end type for the array and pick out the array 275 data pointer field (assumed to be the second field). */ 276 tree ptr_field = TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (exp))); 277 return component_ref (exp, ptr_field); 278 } 279 280 /* Returns a constructor for D dynamic array type TYPE of .length LEN 281 and .ptr pointing to DATA. */ 282 283 tree 284 d_array_value (tree type, tree len, tree data) 285 { 286 tree len_field, ptr_field; 287 vec<constructor_elt, va_gc> *ce = NULL; 288 289 gcc_assert (TYPE_DYNAMIC_ARRAY (type)); 290 len_field = TYPE_FIELDS (type); 291 ptr_field = TREE_CHAIN (len_field); 292 293 len = convert (TREE_TYPE (len_field), len); 294 data = convert (TREE_TYPE (ptr_field), data); 295 296 CONSTRUCTOR_APPEND_ELT (ce, len_field, len); 297 CONSTRUCTOR_APPEND_ELT (ce, ptr_field, data); 298 299 return build_constructor (type, ce); 300 } 301 302 /* Returns value representing the array length of expression EXP. 303 TYPE could be a dynamic or static array. */ 304 305 tree 306 get_array_length (tree exp, Type *type) 307 { 308 Type *tb = type->toBasetype (); 309 310 switch (tb->ty) 311 { 312 case Tsarray: 313 return size_int (((TypeSArray *) tb)->dim->toUInteger ()); 314 315 case Tarray: 316 return d_array_length (exp); 317 318 default: 319 error ("can't determine the length of a %qs", type->toChars ()); 320 return error_mark_node; 321 } 322 } 323 324 /* Create BINFO for a ClassDeclaration's inheritance tree. 325 InterfaceDeclaration's are not included. */ 326 327 tree 328 build_class_binfo (tree super, ClassDeclaration *cd) 329 { 330 tree binfo = make_tree_binfo (1); 331 tree ctype = build_ctype (cd->type); 332 333 /* Want RECORD_TYPE, not POINTER_TYPE. */ 334 BINFO_TYPE (binfo) = TREE_TYPE (ctype); 335 BINFO_INHERITANCE_CHAIN (binfo) = super; 336 BINFO_OFFSET (binfo) = integer_zero_node; 337 338 if (cd->baseClass) 339 BINFO_BASE_APPEND (binfo, build_class_binfo (binfo, cd->baseClass)); 340 341 return binfo; 342 } 343 344 /* Create BINFO for an InterfaceDeclaration's inheritance tree. 345 In order to access all inherited methods in the debugger, 346 the entire tree must be described. 347 This function makes assumptions about interface layout. */ 348 349 tree 350 build_interface_binfo (tree super, ClassDeclaration *cd, unsigned& offset) 351 { 352 tree binfo = make_tree_binfo (cd->baseclasses->dim); 353 tree ctype = build_ctype (cd->type); 354 355 /* Want RECORD_TYPE, not POINTER_TYPE. */ 356 BINFO_TYPE (binfo) = TREE_TYPE (ctype); 357 BINFO_INHERITANCE_CHAIN (binfo) = super; 358 BINFO_OFFSET (binfo) = size_int (offset * Target::ptrsize); 359 BINFO_VIRTUAL_P (binfo) = 1; 360 361 for (size_t i = 0; i < cd->baseclasses->dim; i++, offset++) 362 { 363 BaseClass *bc = (*cd->baseclasses)[i]; 364 BINFO_BASE_APPEND (binfo, build_interface_binfo (binfo, bc->sym, offset)); 365 } 366 367 return binfo; 368 } 369 370 /* Returns the .funcptr component from the D delegate EXP. */ 371 372 tree 373 delegate_method (tree exp) 374 { 375 /* Get the back-end type for the delegate and pick out the funcptr field 376 (assumed to be the second field). */ 377 gcc_assert (TYPE_DELEGATE (TREE_TYPE (exp))); 378 tree method_field = TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (exp))); 379 return component_ref (exp, method_field); 380 } 381 382 /* Returns the .object component from the delegate EXP. */ 383 384 tree 385 delegate_object (tree exp) 386 { 387 /* Get the back-end type for the delegate and pick out the object field 388 (assumed to be the first field). */ 389 gcc_assert (TYPE_DELEGATE (TREE_TYPE (exp))); 390 tree obj_field = TYPE_FIELDS (TREE_TYPE (exp)); 391 return component_ref (exp, obj_field); 392 } 393 394 /* Build a delegate literal of type TYPE whose pointer function is 395 METHOD, and hidden object is OBJECT. */ 396 397 tree 398 build_delegate_cst (tree method, tree object, Type *type) 399 { 400 tree ctor = make_node (CONSTRUCTOR); 401 tree ctype; 402 403 Type *tb = type->toBasetype (); 404 if (tb->ty == Tdelegate) 405 ctype = build_ctype (type); 406 else 407 { 408 /* Convert a function method into an anonymous delegate. */ 409 ctype = make_struct_type ("delegate()", 2, 410 get_identifier ("object"), TREE_TYPE (object), 411 get_identifier ("func"), TREE_TYPE (method)); 412 TYPE_DELEGATE (ctype) = 1; 413 } 414 415 vec<constructor_elt, va_gc> *ce = NULL; 416 CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (ctype), object); 417 CONSTRUCTOR_APPEND_ELT (ce, TREE_CHAIN (TYPE_FIELDS (ctype)), method); 418 419 CONSTRUCTOR_ELTS (ctor) = ce; 420 TREE_TYPE (ctor) = ctype; 421 422 return ctor; 423 } 424 425 /* Builds a temporary tree to store the CALLEE and OBJECT 426 of a method call expression of type TYPE. */ 427 428 tree 429 build_method_call (tree callee, tree object, Type *type) 430 { 431 tree t = build_delegate_cst (callee, object, type); 432 METHOD_CALL_EXPR (t) = 1; 433 return t; 434 } 435 436 /* Extract callee and object from T and return in to CALLEE and OBJECT. */ 437 438 void 439 extract_from_method_call (tree t, tree& callee, tree& object) 440 { 441 gcc_assert (METHOD_CALL_EXPR (t)); 442 object = CONSTRUCTOR_ELT (t, 0)->value; 443 callee = CONSTRUCTOR_ELT (t, 1)->value; 444 } 445 446 /* Build a typeof(null) constant of type TYPE. Handles certain special case 447 conversions, where the underlying type is an aggregate with a nullable 448 interior pointer. */ 449 450 tree 451 build_typeof_null_value (Type *type) 452 { 453 Type *tb = type->toBasetype (); 454 tree value; 455 456 /* For dynamic arrays, set length and pointer fields to zero. */ 457 if (tb->ty == Tarray) 458 value = d_array_value (build_ctype (type), size_int (0), null_pointer_node); 459 460 /* For associative arrays, set the pointer field to null. */ 461 else if (tb->ty == Taarray) 462 { 463 tree ctype = build_ctype (type); 464 gcc_assert (TYPE_ASSOCIATIVE_ARRAY (ctype)); 465 466 value = build_constructor_single (ctype, TYPE_FIELDS (ctype), 467 null_pointer_node); 468 } 469 470 /* For delegates, set the frame and function pointer fields to null. */ 471 else if (tb->ty == Tdelegate) 472 value = build_delegate_cst (null_pointer_node, null_pointer_node, type); 473 474 /* Simple zero constant for all other types. */ 475 else 476 value = build_zero_cst (build_ctype (type)); 477 478 TREE_CONSTANT (value) = 1; 479 return value; 480 } 481 482 /* Build a dereference into the virtual table for OBJECT to retrieve 483 a function pointer of type FNTYPE at position INDEX. */ 484 485 tree 486 build_vindex_ref (tree object, tree fntype, size_t index) 487 { 488 /* The vtable is the first field. Interface methods are also in the class's 489 vtable, so we don't need to convert from a class to an interface. */ 490 tree result = build_deref (object); 491 result = component_ref (result, TYPE_FIELDS (TREE_TYPE (result))); 492 493 gcc_assert (POINTER_TYPE_P (fntype)); 494 495 return build_memref (fntype, result, size_int (Target::ptrsize * index)); 496 } 497 498 /* Return TRUE if EXP is a valid lvalue. Lvalue references cannot be 499 made into temporaries, otherwise any assignments will be lost. */ 500 501 static bool 502 lvalue_p (tree exp) 503 { 504 const enum tree_code code = TREE_CODE (exp); 505 506 switch (code) 507 { 508 case SAVE_EXPR: 509 return false; 510 511 case ARRAY_REF: 512 case INDIRECT_REF: 513 case VAR_DECL: 514 case PARM_DECL: 515 case RESULT_DECL: 516 return !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (exp)); 517 518 case IMAGPART_EXPR: 519 case REALPART_EXPR: 520 case COMPONENT_REF: 521 CASE_CONVERT: 522 return lvalue_p (TREE_OPERAND (exp, 0)); 523 524 case COND_EXPR: 525 return (lvalue_p (TREE_OPERAND (exp, 1) 526 ? TREE_OPERAND (exp, 1) 527 : TREE_OPERAND (exp, 0)) 528 && lvalue_p (TREE_OPERAND (exp, 2))); 529 530 case TARGET_EXPR: 531 return true; 532 533 case COMPOUND_EXPR: 534 return lvalue_p (TREE_OPERAND (exp, 1)); 535 536 default: 537 return false; 538 } 539 } 540 541 /* Create a SAVE_EXPR if EXP might have unwanted side effects if referenced 542 more than once in an expression. */ 543 544 tree 545 d_save_expr (tree exp) 546 { 547 if (TREE_SIDE_EFFECTS (exp)) 548 { 549 if (lvalue_p (exp)) 550 return stabilize_reference (exp); 551 552 return save_expr (exp); 553 } 554 555 return exp; 556 } 557 558 /* VALUEP is an expression we want to pre-evaluate or perform a computation on. 559 The expression returned by this function is the part whose value we don't 560 care about, storing the value in VALUEP. Callers must ensure that the 561 returned expression is evaluated before VALUEP. */ 562 563 tree 564 stabilize_expr (tree *valuep) 565 { 566 tree expr = *valuep; 567 const enum tree_code code = TREE_CODE (expr); 568 tree lhs; 569 tree rhs; 570 571 switch (code) 572 { 573 case COMPOUND_EXPR: 574 /* Given ((e1, ...), eN): 575 Store the last RHS 'eN' expression in VALUEP. */ 576 lhs = TREE_OPERAND (expr, 0); 577 rhs = TREE_OPERAND (expr, 1); 578 lhs = compound_expr (lhs, stabilize_expr (&rhs)); 579 *valuep = rhs; 580 return lhs; 581 582 default: 583 return NULL_TREE; 584 } 585 } 586 587 /* Return a TARGET_EXPR, initializing the DECL with EXP. */ 588 589 tree 590 build_target_expr (tree decl, tree exp) 591 { 592 tree type = TREE_TYPE (decl); 593 tree result = build4 (TARGET_EXPR, type, decl, exp, NULL_TREE, NULL_TREE); 594 595 if (EXPR_HAS_LOCATION (exp)) 596 SET_EXPR_LOCATION (result, EXPR_LOCATION (exp)); 597 598 /* If decl must always reside in memory. */ 599 if (TREE_ADDRESSABLE (type)) 600 d_mark_addressable (decl); 601 602 /* Always set TREE_SIDE_EFFECTS so that expand_expr does not ignore the 603 TARGET_EXPR. If there really turn out to be no side effects, then the 604 optimizer should be able to remove it. */ 605 TREE_SIDE_EFFECTS (result) = 1; 606 607 return result; 608 } 609 610 /* Like the above function, but initializes a new temporary. */ 611 612 tree 613 force_target_expr (tree exp) 614 { 615 tree decl = create_temporary_var (TREE_TYPE (exp)); 616 617 return build_target_expr (decl, exp); 618 } 619 620 /* Returns the address of the expression EXP. */ 621 622 tree 623 build_address (tree exp) 624 { 625 if (error_operand_p (exp)) 626 return exp; 627 628 tree ptrtype; 629 tree type = TREE_TYPE (exp); 630 631 if (TREE_CODE (exp) == STRING_CST) 632 { 633 /* Just convert string literals (char[]) to C-style strings (char *), 634 otherwise the latter method (char[]*) causes conversion problems 635 during gimplification. */ 636 ptrtype = build_pointer_type (TREE_TYPE (type)); 637 } 638 else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node) 639 && TREE_CODE (TYPE_MAIN_VARIANT (type)) == ARRAY_TYPE) 640 { 641 /* Special case for va_list, allow arrays to decay to a pointer. */ 642 ptrtype = build_pointer_type (TREE_TYPE (type)); 643 } 644 else 645 ptrtype = build_pointer_type (type); 646 647 /* Maybe rewrite: &(e1, e2) => (e1, &e2). */ 648 tree init = stabilize_expr (&exp); 649 650 /* Can't take the address of a manifest constant, instead use its value. */ 651 if (TREE_CODE (exp) == CONST_DECL) 652 exp = DECL_INITIAL (exp); 653 654 /* Some expression lowering may request an address of a compile-time constant. 655 Make sure it is assigned to a location we can reference. */ 656 if (CONSTANT_CLASS_P (exp) && TREE_CODE (exp) != STRING_CST) 657 exp = force_target_expr (exp); 658 659 d_mark_addressable (exp); 660 exp = build_fold_addr_expr_with_type_loc (input_location, exp, ptrtype); 661 662 if (TREE_CODE (exp) == ADDR_EXPR) 663 TREE_NO_TRAMPOLINE (exp) = 1; 664 665 return compound_expr (init, exp); 666 } 667 668 /* Mark EXP saying that we need to be able to take the 669 address of it; it should not be allocated in a register. */ 670 671 tree 672 d_mark_addressable (tree exp) 673 { 674 switch (TREE_CODE (exp)) 675 { 676 case ADDR_EXPR: 677 case COMPONENT_REF: 678 case ARRAY_REF: 679 case REALPART_EXPR: 680 case IMAGPART_EXPR: 681 d_mark_addressable (TREE_OPERAND (exp, 0)); 682 break; 683 684 case PARM_DECL: 685 case VAR_DECL: 686 case RESULT_DECL: 687 case CONST_DECL: 688 case FUNCTION_DECL: 689 TREE_ADDRESSABLE (exp) = 1; 690 break; 691 692 case CONSTRUCTOR: 693 TREE_ADDRESSABLE (exp) = 1; 694 break; 695 696 case TARGET_EXPR: 697 TREE_ADDRESSABLE (exp) = 1; 698 d_mark_addressable (TREE_OPERAND (exp, 0)); 699 break; 700 701 default: 702 break; 703 } 704 705 return exp; 706 } 707 708 /* Mark EXP as "used" in the program for the benefit of 709 -Wunused warning purposes. */ 710 711 tree 712 d_mark_used (tree exp) 713 { 714 switch (TREE_CODE (exp)) 715 { 716 case VAR_DECL: 717 case CONST_DECL: 718 case PARM_DECL: 719 case RESULT_DECL: 720 case FUNCTION_DECL: 721 TREE_USED (exp) = 1; 722 break; 723 724 case ARRAY_REF: 725 case COMPONENT_REF: 726 case MODIFY_EXPR: 727 case REALPART_EXPR: 728 case IMAGPART_EXPR: 729 case NOP_EXPR: 730 case CONVERT_EXPR: 731 case ADDR_EXPR: 732 d_mark_used (TREE_OPERAND (exp, 0)); 733 break; 734 735 case COMPOUND_EXPR: 736 d_mark_used (TREE_OPERAND (exp, 0)); 737 d_mark_used (TREE_OPERAND (exp, 1)); 738 break; 739 740 default: 741 break; 742 } 743 return exp; 744 } 745 746 /* Mark EXP as read, not just set, for set but not used -Wunused 747 warning purposes. */ 748 749 tree 750 d_mark_read (tree exp) 751 { 752 switch (TREE_CODE (exp)) 753 { 754 case VAR_DECL: 755 case PARM_DECL: 756 TREE_USED (exp) = 1; 757 DECL_READ_P (exp) = 1; 758 break; 759 760 case ARRAY_REF: 761 case COMPONENT_REF: 762 case MODIFY_EXPR: 763 case REALPART_EXPR: 764 case IMAGPART_EXPR: 765 case NOP_EXPR: 766 case CONVERT_EXPR: 767 case ADDR_EXPR: 768 d_mark_read (TREE_OPERAND (exp, 0)); 769 break; 770 771 case COMPOUND_EXPR: 772 d_mark_read (TREE_OPERAND (exp, 1)); 773 break; 774 775 default: 776 break; 777 } 778 return exp; 779 } 780 781 /* Return TRUE if the struct SD is suitable for comparison using memcmp. 782 This is because we don't guarantee that padding is zero-initialized for 783 a stack variable, so we can't use memcmp to compare struct values. */ 784 785 bool 786 identity_compare_p (StructDeclaration *sd) 787 { 788 if (sd->isUnionDeclaration ()) 789 return true; 790 791 unsigned offset = 0; 792 793 for (size_t i = 0; i < sd->fields.dim; i++) 794 { 795 VarDeclaration *vd = sd->fields[i]; 796 Type *tb = vd->type->toBasetype (); 797 798 /* Check inner data structures. */ 799 if (tb->ty == Tstruct) 800 { 801 TypeStruct *ts = (TypeStruct *) tb; 802 if (!identity_compare_p (ts->sym)) 803 return false; 804 } 805 806 /* Check for types that may have padding. */ 807 if ((tb->ty == Tcomplex80 || tb->ty == Tfloat80 || tb->ty == Timaginary80) 808 && Target::realpad != 0) 809 return false; 810 811 if (offset <= vd->offset) 812 { 813 /* There's a hole in the struct. */ 814 if (offset != vd->offset) 815 return false; 816 817 offset += vd->type->size (); 818 } 819 } 820 821 /* Any trailing padding may not be zero. */ 822 if (offset < sd->structsize) 823 return false; 824 825 return true; 826 } 827 828 /* Build a floating-point identity comparison between T1 and T2, ignoring any 829 excessive padding in the type. CODE is EQ_EXPR or NE_EXPR comparison. */ 830 831 tree 832 build_float_identity (tree_code code, tree t1, tree t2) 833 { 834 tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP); 835 tree size = size_int (TYPE_PRECISION (TREE_TYPE (t1)) / BITS_PER_UNIT); 836 837 tree result = build_call_expr (tmemcmp, 3, build_address (t1), 838 build_address (t2), size); 839 return build_boolop (code, result, integer_zero_node); 840 } 841 842 /* Lower a field-by-field equality expression between T1 and T2 of type SD. 843 CODE is the EQ_EXPR or NE_EXPR comparison. */ 844 845 static tree 846 lower_struct_comparison (tree_code code, StructDeclaration *sd, 847 tree t1, tree t2) 848 { 849 tree_code tcode = (code == EQ_EXPR) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR; 850 tree tmemcmp = NULL_TREE; 851 852 /* We can skip the compare if the structs are empty. */ 853 if (sd->fields.dim == 0) 854 { 855 tmemcmp = build_boolop (code, integer_zero_node, integer_zero_node); 856 if (TREE_SIDE_EFFECTS (t2)) 857 tmemcmp = compound_expr (t2, tmemcmp); 858 if (TREE_SIDE_EFFECTS (t1)) 859 tmemcmp = compound_expr (t1, tmemcmp); 860 861 return tmemcmp; 862 } 863 864 /* Let back-end take care of union comparisons. */ 865 if (sd->isUnionDeclaration ()) 866 { 867 tmemcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP), 3, 868 build_address (t1), build_address (t2), 869 size_int (sd->structsize)); 870 871 return build_boolop (code, tmemcmp, integer_zero_node); 872 } 873 874 for (size_t i = 0; i < sd->fields.dim; i++) 875 { 876 VarDeclaration *vd = sd->fields[i]; 877 Type *type = vd->type->toBasetype (); 878 tree sfield = get_symbol_decl (vd); 879 880 tree t1ref = component_ref (t1, sfield); 881 tree t2ref = component_ref (t2, sfield); 882 tree tcmp; 883 884 if (type->ty == Tstruct) 885 { 886 /* Compare inner data structures. */ 887 StructDeclaration *decl = ((TypeStruct *) type)->sym; 888 tcmp = lower_struct_comparison (code, decl, t1ref, t2ref); 889 } 890 else if (type->ty != Tvector && type->isintegral ()) 891 { 892 /* Integer comparison, no special handling required. */ 893 tcmp = build_boolop (code, t1ref, t2ref); 894 } 895 else if (type->ty != Tvector && type->isfloating ()) 896 { 897 /* Floating-point comparison, don't compare padding in type. */ 898 if (!type->iscomplex ()) 899 tcmp = build_float_identity (code, t1ref, t2ref); 900 else 901 { 902 tree req = build_float_identity (code, real_part (t1ref), 903 real_part (t2ref)); 904 tree ieq = build_float_identity (code, imaginary_part (t1ref), 905 imaginary_part (t2ref)); 906 907 tcmp = build_boolop (tcode, req, ieq); 908 } 909 } 910 else 911 { 912 tree stype = build_ctype (type); 913 opt_scalar_int_mode mode = int_mode_for_mode (TYPE_MODE (stype)); 914 915 if (mode.exists ()) 916 { 917 /* Compare field bits as their corresponding integer type. 918 *((T*) &t1) == *((T*) &t2) */ 919 tree tmode = lang_hooks.types.type_for_mode (mode.require (), 1); 920 921 if (tmode == NULL_TREE) 922 tmode = make_unsigned_type (GET_MODE_BITSIZE (mode.require ())); 923 924 t1ref = build_vconvert (tmode, t1ref); 925 t2ref = build_vconvert (tmode, t2ref); 926 927 tcmp = build_boolop (code, t1ref, t2ref); 928 } 929 else 930 { 931 /* Simple memcmp between types. */ 932 tcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP), 933 3, build_address (t1ref), 934 build_address (t2ref), 935 TYPE_SIZE_UNIT (stype)); 936 937 tcmp = build_boolop (code, tcmp, integer_zero_node); 938 } 939 } 940 941 tmemcmp = (tmemcmp) ? build_boolop (tcode, tmemcmp, tcmp) : tcmp; 942 } 943 944 return tmemcmp; 945 } 946 947 948 /* Build an equality expression between two RECORD_TYPES T1 and T2 of type SD. 949 If possible, use memcmp, otherwise field-by-field comparison is done. 950 CODE is the EQ_EXPR or NE_EXPR comparison. */ 951 952 tree 953 build_struct_comparison (tree_code code, StructDeclaration *sd, 954 tree t1, tree t2) 955 { 956 /* We can skip the compare if the structs are empty. */ 957 if (sd->fields.dim == 0) 958 { 959 tree exp = build_boolop (code, integer_zero_node, integer_zero_node); 960 if (TREE_SIDE_EFFECTS (t2)) 961 exp = compound_expr (t2, exp); 962 if (TREE_SIDE_EFFECTS (t1)) 963 exp = compound_expr (t1, exp); 964 965 return exp; 966 } 967 968 /* Make temporaries to prevent multiple evaluations. */ 969 tree t1init = stabilize_expr (&t1); 970 tree t2init = stabilize_expr (&t2); 971 tree result; 972 973 t1 = d_save_expr (t1); 974 t2 = d_save_expr (t2); 975 976 /* Bitwise comparison of structs not returned in memory may not work 977 due to data holes loosing its zero padding upon return. 978 As a heuristic, small structs are not compared using memcmp either. */ 979 if (TYPE_MODE (TREE_TYPE (t1)) != BLKmode || !identity_compare_p (sd)) 980 result = lower_struct_comparison (code, sd, t1, t2); 981 else 982 { 983 /* Do bit compare of structs. */ 984 tree size = size_int (sd->structsize); 985 tree tmemcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP), 986 3, build_address (t1), 987 build_address (t2), size); 988 989 result = build_boolop (code, tmemcmp, integer_zero_node); 990 } 991 992 return compound_expr (compound_expr (t1init, t2init), result); 993 } 994 995 /* Build an equality expression between two ARRAY_TYPES of size LENGTH. 996 The pointer references are T1 and T2, and the element type is SD. 997 CODE is the EQ_EXPR or NE_EXPR comparison. */ 998 999 tree 1000 build_array_struct_comparison (tree_code code, StructDeclaration *sd, 1001 tree length, tree t1, tree t2) 1002 { 1003 tree_code tcode = (code == EQ_EXPR) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR; 1004 1005 /* Build temporary for the result of the comparison. 1006 Initialize as either 0 or 1 depending on operation. */ 1007 tree result = build_local_temp (d_bool_type); 1008 tree init = build_boolop (code, integer_zero_node, integer_zero_node); 1009 add_stmt (build_assign (INIT_EXPR, result, init)); 1010 1011 /* Cast pointer-to-array to pointer-to-struct. */ 1012 tree ptrtype = build_ctype (sd->type->pointerTo ()); 1013 tree lentype = TREE_TYPE (length); 1014 1015 push_binding_level (level_block); 1016 push_stmt_list (); 1017 1018 /* Build temporary locals for length and pointers. */ 1019 tree t = build_local_temp (size_type_node); 1020 add_stmt (build_assign (INIT_EXPR, t, length)); 1021 length = t; 1022 1023 t = build_local_temp (ptrtype); 1024 add_stmt (build_assign (INIT_EXPR, t, d_convert (ptrtype, t1))); 1025 t1 = t; 1026 1027 t = build_local_temp (ptrtype); 1028 add_stmt (build_assign (INIT_EXPR, t, d_convert (ptrtype, t2))); 1029 t2 = t; 1030 1031 /* Build loop for comparing each element. */ 1032 push_stmt_list (); 1033 1034 /* Exit logic for the loop. 1035 if (length == 0 || result OP 0) break; */ 1036 t = build_boolop (EQ_EXPR, length, d_convert (lentype, integer_zero_node)); 1037 t = build_boolop (TRUTH_ORIF_EXPR, t, build_boolop (code, result, 1038 boolean_false_node)); 1039 t = build1 (EXIT_EXPR, void_type_node, t); 1040 add_stmt (t); 1041 1042 /* Do comparison, caching the value. 1043 result = result OP (*t1 == *t2); */ 1044 t = build_struct_comparison (code, sd, build_deref (t1), build_deref (t2)); 1045 t = build_boolop (tcode, result, t); 1046 t = modify_expr (result, t); 1047 add_stmt (t); 1048 1049 /* Move both pointers to next element position. 1050 t1++, t2++; */ 1051 tree size = d_convert (ptrtype, TYPE_SIZE_UNIT (TREE_TYPE (ptrtype))); 1052 t = build2 (POSTINCREMENT_EXPR, ptrtype, t1, size); 1053 add_stmt (t); 1054 t = build2 (POSTINCREMENT_EXPR, ptrtype, t2, size); 1055 add_stmt (t); 1056 1057 /* Decrease loop counter. 1058 length -= 1; */ 1059 t = build2 (POSTDECREMENT_EXPR, lentype, length, 1060 d_convert (lentype, integer_one_node)); 1061 add_stmt (t); 1062 1063 /* Pop statements and finish loop. */ 1064 tree body = pop_stmt_list (); 1065 add_stmt (build1 (LOOP_EXPR, void_type_node, body)); 1066 1067 /* Wrap it up into a bind expression. */ 1068 tree stmt_list = pop_stmt_list (); 1069 tree block = pop_binding_level (); 1070 1071 body = build3 (BIND_EXPR, void_type_node, 1072 BLOCK_VARS (block), stmt_list, block); 1073 1074 return compound_expr (body, result); 1075 } 1076 1077 /* Create an anonymous field of type ubyte[T] at OFFSET to fill 1078 the alignment hole between OFFSET and FIELDPOS. */ 1079 1080 static tree 1081 build_alignment_field (tree type, HOST_WIDE_INT offset, HOST_WIDE_INT fieldpos) 1082 { 1083 tree atype = make_array_type (Type::tuns8, fieldpos - offset); 1084 tree field = create_field_decl (atype, NULL, 1, 1); 1085 1086 SET_DECL_OFFSET_ALIGN (field, TYPE_ALIGN (atype)); 1087 DECL_FIELD_OFFSET (field) = size_int (offset); 1088 DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node; 1089 DECL_FIELD_CONTEXT (field) = type; 1090 DECL_PADDING_P (field) = 1; 1091 1092 layout_decl (field, 0); 1093 1094 return field; 1095 } 1096 1097 /* Build a constructor for a variable of aggregate type TYPE using the 1098 initializer INIT, an ordered flat list of fields and values provided 1099 by the frontend. The returned constructor should be a value that 1100 matches the layout of TYPE. */ 1101 1102 tree 1103 build_struct_literal (tree type, vec<constructor_elt, va_gc> *init) 1104 { 1105 /* If the initializer was empty, use default zero initialization. */ 1106 if (vec_safe_is_empty (init)) 1107 return build_constructor (type, NULL); 1108 1109 vec<constructor_elt, va_gc> *ve = NULL; 1110 HOST_WIDE_INT offset = 0; 1111 bool constant_p = true; 1112 bool fillholes = true; 1113 bool finished = false; 1114 1115 /* Filling alignment holes this only applies to structs. */ 1116 if (TREE_CODE (type) != RECORD_TYPE 1117 || CLASS_TYPE_P (type) || TYPE_PACKED (type)) 1118 fillholes = false; 1119 1120 /* Walk through each field, matching our initializer list. */ 1121 for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) 1122 { 1123 bool is_initialized = false; 1124 tree value; 1125 1126 if (DECL_NAME (field) == NULL_TREE 1127 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)) 1128 && ANON_AGGR_TYPE_P (TREE_TYPE (field))) 1129 { 1130 /* Search all nesting aggregates, if nothing is found, then 1131 this will return an empty initializer to fill the hole. */ 1132 value = build_struct_literal (TREE_TYPE (field), init); 1133 1134 if (!initializer_zerop (value)) 1135 is_initialized = true; 1136 } 1137 else 1138 { 1139 /* Search for the value to initialize the next field. Once found, 1140 pop it from the init list so we don't look at it again. */ 1141 unsigned HOST_WIDE_INT idx; 1142 tree index; 1143 1144 FOR_EACH_CONSTRUCTOR_ELT (init, idx, index, value) 1145 { 1146 /* If the index is NULL, then just assign it to the next field. 1147 This comes from layout_typeinfo(), which generates a flat 1148 list of values that we must shape into the record type. */ 1149 if (index == field || index == NULL_TREE) 1150 { 1151 init->ordered_remove (idx); 1152 if (!finished) 1153 is_initialized = true; 1154 break; 1155 } 1156 } 1157 } 1158 1159 if (is_initialized) 1160 { 1161 HOST_WIDE_INT fieldpos = int_byte_position (field); 1162 gcc_assert (value != NULL_TREE); 1163 1164 /* Insert anonymous fields in the constructor for padding out 1165 alignment holes in-place between fields. */ 1166 if (fillholes && offset < fieldpos) 1167 { 1168 tree pfield = build_alignment_field (type, offset, fieldpos); 1169 tree pvalue = build_zero_cst (TREE_TYPE (pfield)); 1170 CONSTRUCTOR_APPEND_ELT (ve, pfield, pvalue); 1171 } 1172 1173 /* Must not initialize fields that overlap. */ 1174 if (fieldpos < offset) 1175 { 1176 /* Find the nearest user defined type and field. */ 1177 tree vtype = type; 1178 while (ANON_AGGR_TYPE_P (vtype)) 1179 vtype = TYPE_CONTEXT (vtype); 1180 1181 tree vfield = field; 1182 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (vfield)) 1183 && ANON_AGGR_TYPE_P (TREE_TYPE (vfield))) 1184 vfield = TYPE_FIELDS (TREE_TYPE (vfield)); 1185 1186 /* Must not generate errors for compiler generated fields. */ 1187 gcc_assert (TYPE_NAME (vtype) && DECL_NAME (vfield)); 1188 error ("overlapping initializer for field %qT.%qD", 1189 TYPE_NAME (vtype), DECL_NAME (vfield)); 1190 } 1191 1192 if (!TREE_CONSTANT (value)) 1193 constant_p = false; 1194 1195 CONSTRUCTOR_APPEND_ELT (ve, field, value); 1196 1197 /* For unions, only the first field is initialized, any other field 1198 initializers found for this union are drained and ignored. */ 1199 if (TREE_CODE (type) == UNION_TYPE) 1200 finished = true; 1201 } 1202 1203 /* Move offset to the next position in the struct. */ 1204 if (TREE_CODE (type) == RECORD_TYPE) 1205 { 1206 offset = int_byte_position (field) 1207 + int_size_in_bytes (TREE_TYPE (field)); 1208 } 1209 1210 /* If all initializers have been assigned, there's nothing else to do. */ 1211 if (vec_safe_is_empty (init)) 1212 break; 1213 } 1214 1215 /* Finally pad out the end of the record. */ 1216 if (fillholes && offset < int_size_in_bytes (type)) 1217 { 1218 tree pfield = build_alignment_field (type, offset, 1219 int_size_in_bytes (type)); 1220 tree pvalue = build_zero_cst (TREE_TYPE (pfield)); 1221 CONSTRUCTOR_APPEND_ELT (ve, pfield, pvalue); 1222 } 1223 1224 /* Ensure that we have consumed all values. */ 1225 gcc_assert (vec_safe_is_empty (init) || ANON_AGGR_TYPE_P (type)); 1226 1227 tree ctor = build_constructor (type, ve); 1228 1229 if (constant_p) 1230 TREE_CONSTANT (ctor) = 1; 1231 1232 return ctor; 1233 } 1234 1235 /* Given the TYPE of an anonymous field inside T, return the 1236 FIELD_DECL for the field. If not found return NULL_TREE. 1237 Because anonymous types can nest, we must also search all 1238 anonymous fields that are directly reachable. */ 1239 1240 static tree 1241 lookup_anon_field (tree t, tree type) 1242 { 1243 t = TYPE_MAIN_VARIANT (t); 1244 1245 for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) 1246 { 1247 if (DECL_NAME (field) == NULL_TREE) 1248 { 1249 /* If we find it directly, return the field. */ 1250 if (type == TYPE_MAIN_VARIANT (TREE_TYPE (field))) 1251 return field; 1252 1253 /* Otherwise, it could be nested, search harder. */ 1254 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)) 1255 && ANON_AGGR_TYPE_P (TREE_TYPE (field))) 1256 { 1257 tree subfield = lookup_anon_field (TREE_TYPE (field), type); 1258 if (subfield) 1259 return subfield; 1260 } 1261 } 1262 } 1263 1264 return NULL_TREE; 1265 } 1266 1267 /* Builds OBJECT.FIELD component reference. */ 1268 1269 tree 1270 component_ref (tree object, tree field) 1271 { 1272 if (error_operand_p (object) || error_operand_p (field)) 1273 return error_mark_node; 1274 1275 gcc_assert (TREE_CODE (field) == FIELD_DECL); 1276 1277 /* Maybe rewrite: (e1, e2).field => (e1, e2.field) */ 1278 tree init = stabilize_expr (&object); 1279 1280 /* If the FIELD is from an anonymous aggregate, generate a reference 1281 to the anonymous data member, and recur to find FIELD. */ 1282 if (ANON_AGGR_TYPE_P (DECL_CONTEXT (field))) 1283 { 1284 tree anonymous_field = lookup_anon_field (TREE_TYPE (object), 1285 DECL_CONTEXT (field)); 1286 object = component_ref (object, anonymous_field); 1287 } 1288 1289 tree result = fold_build3_loc (input_location, COMPONENT_REF, 1290 TREE_TYPE (field), object, field, NULL_TREE); 1291 1292 return compound_expr (init, result); 1293 } 1294 1295 /* Build an assignment expression of lvalue LHS from value RHS. 1296 CODE is the code for a binary operator that we use to combine 1297 the old value of LHS with RHS to get the new value. */ 1298 1299 tree 1300 build_assign (tree_code code, tree lhs, tree rhs) 1301 { 1302 tree init = stabilize_expr (&lhs); 1303 init = compound_expr (init, stabilize_expr (&rhs)); 1304 1305 /* If initializing the LHS using a function that returns via NRVO. */ 1306 if (code == INIT_EXPR && TREE_CODE (rhs) == CALL_EXPR 1307 && AGGREGATE_TYPE_P (TREE_TYPE (rhs)) 1308 && aggregate_value_p (TREE_TYPE (rhs), rhs)) 1309 { 1310 /* Mark as addressable here, which should ensure the return slot is the 1311 address of the LHS expression, taken care of by back-end. */ 1312 d_mark_addressable (lhs); 1313 CALL_EXPR_RETURN_SLOT_OPT (rhs) = true; 1314 } 1315 1316 /* The LHS assignment replaces the temporary in TARGET_EXPR_SLOT. */ 1317 if (TREE_CODE (rhs) == TARGET_EXPR) 1318 { 1319 /* If CODE is not INIT_EXPR, can't initialize LHS directly, 1320 since that would cause the LHS to be constructed twice. 1321 So we force the TARGET_EXPR to be expanded without a target. */ 1322 if (code != INIT_EXPR) 1323 rhs = compound_expr (rhs, TARGET_EXPR_SLOT (rhs)); 1324 else 1325 { 1326 d_mark_addressable (lhs); 1327 rhs = TARGET_EXPR_INITIAL (rhs); 1328 } 1329 } 1330 1331 tree result = fold_build2_loc (input_location, code, 1332 TREE_TYPE (lhs), lhs, rhs); 1333 return compound_expr (init, result); 1334 } 1335 1336 /* Build an assignment expression of lvalue LHS from value RHS. */ 1337 1338 tree 1339 modify_expr (tree lhs, tree rhs) 1340 { 1341 return build_assign (MODIFY_EXPR, lhs, rhs); 1342 } 1343 1344 /* Return EXP represented as TYPE. */ 1345 1346 tree 1347 build_nop (tree type, tree exp) 1348 { 1349 if (error_operand_p (exp)) 1350 return exp; 1351 1352 /* Maybe rewrite: cast(TYPE)(e1, e2) => (e1, cast(TYPE) e2) */ 1353 tree init = stabilize_expr (&exp); 1354 exp = fold_build1_loc (input_location, NOP_EXPR, type, exp); 1355 1356 return compound_expr (init, exp); 1357 } 1358 1359 /* Return EXP to be viewed as being another type TYPE. Same as build_nop, 1360 except that EXP is type-punned, rather than a straight-forward cast. */ 1361 1362 tree 1363 build_vconvert (tree type, tree exp) 1364 { 1365 /* Building *(cast(TYPE *)&e1) directly rather then using VIEW_CONVERT_EXPR 1366 makes sure this works for vector-to-array viewing, or if EXP ends up being 1367 used as the LHS of a MODIFY_EXPR. */ 1368 return indirect_ref (type, build_address (exp)); 1369 } 1370 1371 /* Maybe warn about ARG being an address that can never be null. */ 1372 1373 static void 1374 warn_for_null_address (tree arg) 1375 { 1376 if (TREE_CODE (arg) == ADDR_EXPR 1377 && decl_with_nonnull_addr_p (TREE_OPERAND (arg, 0))) 1378 warning (OPT_Waddress, 1379 "the address of %qD will never be %<null%>", 1380 TREE_OPERAND (arg, 0)); 1381 } 1382 1383 /* Build a boolean ARG0 op ARG1 expression. */ 1384 1385 tree 1386 build_boolop (tree_code code, tree arg0, tree arg1) 1387 { 1388 /* Aggregate comparisons may get lowered to a call to builtin memcmp, 1389 so need to remove all side effects incase its address is taken. */ 1390 if (AGGREGATE_TYPE_P (TREE_TYPE (arg0))) 1391 arg0 = d_save_expr (arg0); 1392 if (AGGREGATE_TYPE_P (TREE_TYPE (arg1))) 1393 arg1 = d_save_expr (arg1); 1394 1395 if (VECTOR_TYPE_P (TREE_TYPE (arg0)) && VECTOR_TYPE_P (TREE_TYPE (arg1))) 1396 { 1397 /* Build a vector comparison. 1398 VEC_COND_EXPR <e1 op e2, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>; */ 1399 tree type = TREE_TYPE (arg0); 1400 tree cmptype = build_same_sized_truth_vector_type (type); 1401 tree cmp = fold_build2_loc (input_location, code, cmptype, arg0, arg1); 1402 1403 return fold_build3_loc (input_location, VEC_COND_EXPR, type, cmp, 1404 build_minus_one_cst (type), 1405 build_zero_cst (type)); 1406 } 1407 1408 if (code == EQ_EXPR || code == NE_EXPR) 1409 { 1410 /* Check if comparing the address of a variable to null. */ 1411 if (POINTER_TYPE_P (TREE_TYPE (arg0)) && integer_zerop (arg1)) 1412 warn_for_null_address (arg0); 1413 if (POINTER_TYPE_P (TREE_TYPE (arg1)) && integer_zerop (arg0)) 1414 warn_for_null_address (arg1); 1415 } 1416 1417 return fold_build2_loc (input_location, code, d_bool_type, 1418 arg0, d_convert (TREE_TYPE (arg0), arg1)); 1419 } 1420 1421 /* Return a COND_EXPR. ARG0, ARG1, and ARG2 are the three 1422 arguments to the conditional expression. */ 1423 1424 tree 1425 build_condition (tree type, tree arg0, tree arg1, tree arg2) 1426 { 1427 if (arg1 == void_node) 1428 arg1 = build_empty_stmt (input_location); 1429 1430 if (arg2 == void_node) 1431 arg2 = build_empty_stmt (input_location); 1432 1433 return fold_build3_loc (input_location, COND_EXPR, 1434 type, arg0, arg1, arg2); 1435 } 1436 1437 tree 1438 build_vcondition (tree arg0, tree arg1, tree arg2) 1439 { 1440 return build_condition (void_type_node, arg0, arg1, arg2); 1441 } 1442 1443 /* Build a compound expr to join ARG0 and ARG1 together. */ 1444 1445 tree 1446 compound_expr (tree arg0, tree arg1) 1447 { 1448 if (arg1 == NULL_TREE) 1449 return arg0; 1450 1451 if (arg0 == NULL_TREE || !TREE_SIDE_EFFECTS (arg0)) 1452 return arg1; 1453 1454 if (TREE_CODE (arg1) == TARGET_EXPR) 1455 { 1456 /* If the rhs is a TARGET_EXPR, then build the compound expression 1457 inside the target_expr's initializer. This helps the compiler 1458 to eliminate unnecessary temporaries. */ 1459 tree init = compound_expr (arg0, TARGET_EXPR_INITIAL (arg1)); 1460 TARGET_EXPR_INITIAL (arg1) = init; 1461 1462 return arg1; 1463 } 1464 1465 return fold_build2_loc (input_location, COMPOUND_EXPR, 1466 TREE_TYPE (arg1), arg0, arg1); 1467 } 1468 1469 /* Build a return expression. */ 1470 1471 tree 1472 return_expr (tree ret) 1473 { 1474 return fold_build1_loc (input_location, RETURN_EXPR, 1475 void_type_node, ret); 1476 } 1477 1478 /* Return the product of ARG0 and ARG1 as a size_type_node. */ 1479 1480 tree 1481 size_mult_expr (tree arg0, tree arg1) 1482 { 1483 return fold_build2_loc (input_location, MULT_EXPR, size_type_node, 1484 d_convert (size_type_node, arg0), 1485 d_convert (size_type_node, arg1)); 1486 1487 } 1488 1489 /* Return the real part of CE, which should be a complex expression. */ 1490 1491 tree 1492 real_part (tree ce) 1493 { 1494 return fold_build1_loc (input_location, REALPART_EXPR, 1495 TREE_TYPE (TREE_TYPE (ce)), ce); 1496 } 1497 1498 /* Return the imaginary part of CE, which should be a complex expression. */ 1499 1500 tree 1501 imaginary_part (tree ce) 1502 { 1503 return fold_build1_loc (input_location, IMAGPART_EXPR, 1504 TREE_TYPE (TREE_TYPE (ce)), ce); 1505 } 1506 1507 /* Build a complex expression of type TYPE using RE and IM. */ 1508 1509 tree 1510 complex_expr (tree type, tree re, tree im) 1511 { 1512 return fold_build2_loc (input_location, COMPLEX_EXPR, 1513 type, re, im); 1514 } 1515 1516 /* Cast EXP (which should be a pointer) to TYPE* and then indirect. 1517 The back-end requires this cast in many cases. */ 1518 1519 tree 1520 indirect_ref (tree type, tree exp) 1521 { 1522 if (error_operand_p (exp)) 1523 return exp; 1524 1525 /* Maybe rewrite: *(e1, e2) => (e1, *e2) */ 1526 tree init = stabilize_expr (&exp); 1527 1528 if (TREE_CODE (TREE_TYPE (exp)) == REFERENCE_TYPE) 1529 exp = fold_build1 (INDIRECT_REF, type, exp); 1530 else 1531 { 1532 exp = build_nop (build_pointer_type (type), exp); 1533 exp = build_deref (exp); 1534 } 1535 1536 return compound_expr (init, exp); 1537 } 1538 1539 /* Returns indirect reference of EXP, which must be a pointer type. */ 1540 1541 tree 1542 build_deref (tree exp) 1543 { 1544 if (error_operand_p (exp)) 1545 return exp; 1546 1547 /* Maybe rewrite: *(e1, e2) => (e1, *e2) */ 1548 tree init = stabilize_expr (&exp); 1549 1550 gcc_assert (POINTER_TYPE_P (TREE_TYPE (exp))); 1551 1552 if (TREE_CODE (exp) == ADDR_EXPR) 1553 exp = TREE_OPERAND (exp, 0); 1554 else 1555 exp = build_fold_indirect_ref (exp); 1556 1557 return compound_expr (init, exp); 1558 } 1559 1560 /* Builds pointer offset expression PTR[INDEX]. */ 1561 1562 tree 1563 build_array_index (tree ptr, tree index) 1564 { 1565 if (error_operand_p (ptr) || error_operand_p (index)) 1566 return error_mark_node; 1567 1568 tree ptr_type = TREE_TYPE (ptr); 1569 tree target_type = TREE_TYPE (ptr_type); 1570 1571 tree type = lang_hooks.types.type_for_size (TYPE_PRECISION (sizetype), 1572 TYPE_UNSIGNED (sizetype)); 1573 1574 /* Array element size. */ 1575 tree size_exp = size_in_bytes (target_type); 1576 1577 if (integer_zerop (size_exp)) 1578 { 1579 /* Test for array of void. */ 1580 if (TYPE_MODE (target_type) == TYPE_MODE (void_type_node)) 1581 index = fold_convert (type, index); 1582 else 1583 { 1584 /* Should catch this earlier. */ 1585 error ("invalid use of incomplete type %qD", TYPE_NAME (target_type)); 1586 ptr_type = error_mark_node; 1587 } 1588 } 1589 else if (integer_onep (size_exp)) 1590 { 1591 /* Array of bytes -- No need to multiply. */ 1592 index = fold_convert (type, index); 1593 } 1594 else 1595 { 1596 index = d_convert (type, index); 1597 index = fold_build2 (MULT_EXPR, TREE_TYPE (index), 1598 index, d_convert (TREE_TYPE (index), size_exp)); 1599 index = fold_convert (type, index); 1600 } 1601 1602 if (integer_zerop (index)) 1603 return ptr; 1604 1605 return fold_build2 (POINTER_PLUS_EXPR, ptr_type, ptr, index); 1606 } 1607 1608 /* Builds pointer offset expression *(PTR OP OFFSET) 1609 OP could be a plus or minus expression. */ 1610 1611 tree 1612 build_offset_op (tree_code op, tree ptr, tree offset) 1613 { 1614 gcc_assert (op == MINUS_EXPR || op == PLUS_EXPR); 1615 1616 tree type = lang_hooks.types.type_for_size (TYPE_PRECISION (sizetype), 1617 TYPE_UNSIGNED (sizetype)); 1618 offset = fold_convert (type, offset); 1619 1620 if (op == MINUS_EXPR) 1621 offset = fold_build1 (NEGATE_EXPR, type, offset); 1622 1623 return fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr, offset); 1624 } 1625 1626 /* Builds pointer offset expression *(PTR + OFFSET). */ 1627 1628 tree 1629 build_offset (tree ptr, tree offset) 1630 { 1631 return build_offset_op (PLUS_EXPR, ptr, offset); 1632 } 1633 1634 tree 1635 build_memref (tree type, tree ptr, tree offset) 1636 { 1637 return fold_build2 (MEM_REF, type, ptr, fold_convert (type, offset)); 1638 } 1639 1640 /* Create a tree node to set multiple elements to a single value. */ 1641 1642 tree 1643 build_array_set (tree ptr, tree length, tree value) 1644 { 1645 tree ptrtype = TREE_TYPE (ptr); 1646 tree lentype = TREE_TYPE (length); 1647 1648 push_binding_level (level_block); 1649 push_stmt_list (); 1650 1651 /* Build temporary locals for length and ptr, and maybe value. */ 1652 tree t = build_local_temp (size_type_node); 1653 add_stmt (build_assign (INIT_EXPR, t, length)); 1654 length = t; 1655 1656 t = build_local_temp (ptrtype); 1657 add_stmt (build_assign (INIT_EXPR, t, ptr)); 1658 ptr = t; 1659 1660 if (TREE_SIDE_EFFECTS (value)) 1661 { 1662 t = build_local_temp (TREE_TYPE (value)); 1663 add_stmt (build_assign (INIT_EXPR, t, value)); 1664 value = t; 1665 } 1666 1667 /* Build loop to initialize { .length=length, .ptr=ptr } with value. */ 1668 push_stmt_list (); 1669 1670 /* Exit logic for the loop. 1671 if (length == 0) break; */ 1672 t = build_boolop (EQ_EXPR, length, d_convert (lentype, integer_zero_node)); 1673 t = build1 (EXIT_EXPR, void_type_node, t); 1674 add_stmt (t); 1675 1676 /* Assign value to the current pointer position. 1677 *ptr = value; */ 1678 t = modify_expr (build_deref (ptr), value); 1679 add_stmt (t); 1680 1681 /* Move pointer to next element position. 1682 ptr++; */ 1683 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptrtype)); 1684 t = build2 (POSTINCREMENT_EXPR, ptrtype, ptr, d_convert (ptrtype, size)); 1685 add_stmt (t); 1686 1687 /* Decrease loop counter. 1688 length -= 1; */ 1689 t = build2 (POSTDECREMENT_EXPR, lentype, length, 1690 d_convert (lentype, integer_one_node)); 1691 add_stmt (t); 1692 1693 /* Pop statements and finish loop. */ 1694 tree loop_body = pop_stmt_list (); 1695 add_stmt (build1 (LOOP_EXPR, void_type_node, loop_body)); 1696 1697 /* Wrap it up into a bind expression. */ 1698 tree stmt_list = pop_stmt_list (); 1699 tree block = pop_binding_level (); 1700 1701 return build3 (BIND_EXPR, void_type_node, 1702 BLOCK_VARS (block), stmt_list, block); 1703 } 1704 1705 1706 /* Build an array of type TYPE where all the elements are VAL. */ 1707 1708 tree 1709 build_array_from_val (Type *type, tree val) 1710 { 1711 gcc_assert (type->ty == Tsarray); 1712 1713 tree etype = build_ctype (type->nextOf ()); 1714 1715 /* Initializing a multidimensional array. */ 1716 if (TREE_CODE (etype) == ARRAY_TYPE && TREE_TYPE (val) != etype) 1717 val = build_array_from_val (type->nextOf (), val); 1718 1719 size_t dims = ((TypeSArray *) type)->dim->toInteger (); 1720 vec<constructor_elt, va_gc> *elms = NULL; 1721 vec_safe_reserve (elms, dims); 1722 1723 val = d_convert (etype, val); 1724 1725 for (size_t i = 0; i < dims; i++) 1726 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), val); 1727 1728 return build_constructor (build_ctype (type), elms); 1729 } 1730 1731 /* Implicitly converts void* T to byte* as D allows { void[] a; &a[3]; } */ 1732 1733 tree 1734 void_okay_p (tree t) 1735 { 1736 tree type = TREE_TYPE (t); 1737 1738 if (VOID_TYPE_P (TREE_TYPE (type))) 1739 { 1740 tree totype = build_ctype (Type::tuns8->pointerTo ()); 1741 return fold_convert (totype, t); 1742 } 1743 1744 return t; 1745 } 1746 1747 /* Builds a bounds condition checking that INDEX is between 0 and LEN. 1748 The condition returns the INDEX if true, or throws a RangeError. 1749 If INCLUSIVE, we allow INDEX == LEN to return true also. */ 1750 1751 tree 1752 build_bounds_condition (const Loc& loc, tree index, tree len, bool inclusive) 1753 { 1754 if (!array_bounds_check ()) 1755 return index; 1756 1757 /* Prevent multiple evaluations of the index. */ 1758 index = d_save_expr (index); 1759 1760 /* Generate INDEX >= LEN && throw RangeError. 1761 No need to check whether INDEX >= 0 as the front-end should 1762 have already taken care of implicit casts to unsigned. */ 1763 tree condition = fold_build2 (inclusive ? GT_EXPR : GE_EXPR, 1764 d_bool_type, index, len); 1765 /* Terminate the program with a trap if no D runtime present. */ 1766 tree boundserr = (global.params.checkAction == CHECKACTION_D) 1767 ? d_assert_call (loc, LIBCALL_ARRAY_BOUNDS) 1768 : build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0); 1769 1770 return build_condition (TREE_TYPE (index), condition, boundserr, index); 1771 } 1772 1773 /* Returns TRUE if array bounds checking code generation is turned on. */ 1774 1775 bool 1776 array_bounds_check (void) 1777 { 1778 FuncDeclaration *fd; 1779 1780 switch (global.params.useArrayBounds) 1781 { 1782 case BOUNDSCHECKoff: 1783 return false; 1784 1785 case BOUNDSCHECKon: 1786 return true; 1787 1788 case BOUNDSCHECKsafeonly: 1789 /* For D2 safe functions only. */ 1790 fd = d_function_chain->function; 1791 if (fd && fd->type->ty == Tfunction) 1792 { 1793 TypeFunction *tf = (TypeFunction *) fd->type; 1794 if (tf->trust == TRUSTsafe) 1795 return true; 1796 } 1797 return false; 1798 1799 default: 1800 gcc_unreachable (); 1801 } 1802 } 1803 1804 /* Return an undeclared local temporary of type TYPE 1805 for use with BIND_EXPR. */ 1806 1807 tree 1808 create_temporary_var (tree type) 1809 { 1810 tree decl = build_decl (input_location, VAR_DECL, NULL_TREE, type); 1811 1812 DECL_CONTEXT (decl) = current_function_decl; 1813 DECL_ARTIFICIAL (decl) = 1; 1814 DECL_IGNORED_P (decl) = 1; 1815 layout_decl (decl, 0); 1816 1817 return decl; 1818 } 1819 1820 /* Return an undeclared local temporary OUT_VAR initialized 1821 with result of expression EXP. */ 1822 1823 tree 1824 maybe_temporary_var (tree exp, tree *out_var) 1825 { 1826 tree t = exp; 1827 1828 /* Get the base component. */ 1829 while (TREE_CODE (t) == COMPONENT_REF) 1830 t = TREE_OPERAND (t, 0); 1831 1832 if (!DECL_P (t) && !REFERENCE_CLASS_P (t)) 1833 { 1834 *out_var = create_temporary_var (TREE_TYPE (exp)); 1835 DECL_INITIAL (*out_var) = exp; 1836 return *out_var; 1837 } 1838 else 1839 { 1840 *out_var = NULL_TREE; 1841 return exp; 1842 } 1843 } 1844 1845 /* Builds a BIND_EXPR around BODY for the variables VAR_CHAIN. */ 1846 1847 tree 1848 bind_expr (tree var_chain, tree body) 1849 { 1850 /* Only handles one var. */ 1851 gcc_assert (TREE_CHAIN (var_chain) == NULL_TREE); 1852 1853 if (DECL_INITIAL (var_chain)) 1854 { 1855 tree ini = build_assign (INIT_EXPR, var_chain, DECL_INITIAL (var_chain)); 1856 DECL_INITIAL (var_chain) = NULL_TREE; 1857 body = compound_expr (ini, body); 1858 } 1859 1860 return d_save_expr (build3 (BIND_EXPR, TREE_TYPE (body), 1861 var_chain, body, NULL_TREE)); 1862 } 1863 1864 /* Returns the TypeFunction class for Type T. 1865 Assumes T is already ->toBasetype(). */ 1866 1867 TypeFunction * 1868 get_function_type (Type *t) 1869 { 1870 TypeFunction *tf = NULL; 1871 if (t->ty == Tpointer) 1872 t = t->nextOf ()->toBasetype (); 1873 if (t->ty == Tfunction) 1874 tf = (TypeFunction *) t; 1875 else if (t->ty == Tdelegate) 1876 tf = (TypeFunction *) ((TypeDelegate *) t)->next; 1877 return tf; 1878 } 1879 1880 /* Returns TRUE if CALLEE is a plain nested function outside the scope of 1881 CALLER. In which case, CALLEE is being called through an alias that was 1882 passed to CALLER. */ 1883 1884 bool 1885 call_by_alias_p (FuncDeclaration *caller, FuncDeclaration *callee) 1886 { 1887 if (!callee->isNested ()) 1888 return false; 1889 1890 if (caller->toParent () == callee->toParent ()) 1891 return false; 1892 1893 Dsymbol *dsym = callee; 1894 1895 while (dsym) 1896 { 1897 if (dsym->isTemplateInstance ()) 1898 return false; 1899 else if (dsym->isFuncDeclaration () == caller) 1900 return false; 1901 dsym = dsym->toParent (); 1902 } 1903 1904 return true; 1905 } 1906 1907 /* Entry point for call routines. Builds a function call to FD. 1908 OBJECT is the 'this' reference passed and ARGS are the arguments to FD. */ 1909 1910 tree 1911 d_build_call_expr (FuncDeclaration *fd, tree object, Expressions *arguments) 1912 { 1913 return d_build_call (get_function_type (fd->type), 1914 build_address (get_symbol_decl (fd)), object, arguments); 1915 } 1916 1917 /* Builds a CALL_EXPR of type TF to CALLABLE. OBJECT holds the 'this' pointer, 1918 ARGUMENTS are evaluated in left to right order, saved and promoted 1919 before passing. */ 1920 1921 tree 1922 d_build_call (TypeFunction *tf, tree callable, tree object, 1923 Expressions *arguments) 1924 { 1925 tree ctype = TREE_TYPE (callable); 1926 tree callee = callable; 1927 1928 if (POINTER_TYPE_P (ctype)) 1929 ctype = TREE_TYPE (ctype); 1930 else 1931 callee = build_address (callable); 1932 1933 gcc_assert (FUNC_OR_METHOD_TYPE_P (ctype)); 1934 gcc_assert (tf != NULL); 1935 gcc_assert (tf->ty == Tfunction); 1936 1937 if (TREE_CODE (ctype) != FUNCTION_TYPE && object == NULL_TREE) 1938 { 1939 /* Front-end apparently doesn't check this. */ 1940 if (TREE_CODE (callable) == FUNCTION_DECL) 1941 { 1942 error ("need %<this%> to access member %qE", DECL_NAME (callable)); 1943 return error_mark_node; 1944 } 1945 1946 /* Probably an internal error. */ 1947 gcc_unreachable (); 1948 } 1949 1950 /* Build the argument list for the call. */ 1951 vec<tree, va_gc> *args = NULL; 1952 tree saved_args = NULL_TREE; 1953 1954 /* If this is a delegate call or a nested function being called as 1955 a delegate, the object should not be NULL. */ 1956 if (object != NULL_TREE) 1957 vec_safe_push (args, object); 1958 1959 if (arguments) 1960 { 1961 /* First pass, evaluated expanded tuples in function arguments. */ 1962 for (size_t i = 0; i < arguments->dim; ++i) 1963 { 1964 Lagain: 1965 Expression *arg = (*arguments)[i]; 1966 gcc_assert (arg->op != TOKtuple); 1967 1968 if (arg->op == TOKcomma) 1969 { 1970 CommaExp *ce = (CommaExp *) arg; 1971 tree tce = build_expr (ce->e1); 1972 saved_args = compound_expr (saved_args, tce); 1973 (*arguments)[i] = ce->e2; 1974 goto Lagain; 1975 } 1976 } 1977 1978 size_t nparams = Parameter::dim (tf->parameters); 1979 /* if _arguments[] is the first argument. */ 1980 size_t varargs = (tf->linkage == LINKd && tf->varargs == 1); 1981 1982 /* Assumes arguments->dim <= formal_args->dim if (!tf->varargs). */ 1983 for (size_t i = 0; i < arguments->dim; ++i) 1984 { 1985 Expression *arg = (*arguments)[i]; 1986 tree targ = build_expr (arg); 1987 1988 if (i - varargs < nparams && i >= varargs) 1989 { 1990 /* Actual arguments for declared formal arguments. */ 1991 Parameter *parg = Parameter::getNth (tf->parameters, i - varargs); 1992 targ = convert_for_argument (targ, parg); 1993 } 1994 1995 /* Don't pass empty aggregates by value. */ 1996 if (empty_aggregate_p (TREE_TYPE (targ)) && !TREE_ADDRESSABLE (targ) 1997 && TREE_CODE (targ) != CONSTRUCTOR) 1998 { 1999 tree t = build_constructor (TREE_TYPE (targ), NULL); 2000 targ = build2 (COMPOUND_EXPR, TREE_TYPE (t), targ, t); 2001 } 2002 2003 vec_safe_push (args, targ); 2004 } 2005 } 2006 2007 /* Evaluate the callee before calling it. */ 2008 if (TREE_SIDE_EFFECTS (callee)) 2009 { 2010 callee = d_save_expr (callee); 2011 saved_args = compound_expr (callee, saved_args); 2012 } 2013 2014 tree result = build_call_vec (TREE_TYPE (ctype), callee, args); 2015 2016 /* Enforce left to right evaluation. */ 2017 if (tf->linkage == LINKd) 2018 CALL_EXPR_ARGS_ORDERED (result) = 1; 2019 2020 result = maybe_expand_intrinsic (result); 2021 2022 /* Return the value in a temporary slot so that it can be evaluated 2023 multiple times by the caller. */ 2024 if (TREE_CODE (result) == CALL_EXPR 2025 && AGGREGATE_TYPE_P (TREE_TYPE (result)) 2026 && TREE_ADDRESSABLE (TREE_TYPE (result))) 2027 { 2028 CALL_EXPR_RETURN_SLOT_OPT (result) = true; 2029 result = force_target_expr (result); 2030 } 2031 2032 return compound_expr (saved_args, result); 2033 } 2034 2035 /* Builds a call to AssertError or AssertErrorMsg. */ 2036 2037 tree 2038 d_assert_call (const Loc& loc, libcall_fn libcall, tree msg) 2039 { 2040 tree file; 2041 tree line = size_int (loc.linnum); 2042 2043 /* File location is passed as a D string. */ 2044 if (loc.filename) 2045 { 2046 unsigned len = strlen (loc.filename); 2047 tree str = build_string (len, loc.filename); 2048 TREE_TYPE (str) = make_array_type (Type::tchar, len); 2049 2050 file = d_array_value (build_ctype (Type::tchar->arrayOf ()), 2051 size_int (len), build_address (str)); 2052 } 2053 else 2054 file = null_array_node; 2055 2056 if (msg != NULL) 2057 return build_libcall (libcall, Type::tvoid, 3, msg, file, line); 2058 else 2059 return build_libcall (libcall, Type::tvoid, 2, file, line); 2060 } 2061 2062 /* Build and return the correct call to fmod depending on TYPE. 2063 ARG0 and ARG1 are the arguments pass to the function. */ 2064 2065 tree 2066 build_float_modulus (tree type, tree arg0, tree arg1) 2067 { 2068 tree fmodfn = NULL_TREE; 2069 tree basetype = type; 2070 2071 if (COMPLEX_FLOAT_TYPE_P (basetype)) 2072 basetype = TREE_TYPE (basetype); 2073 2074 if (TYPE_MAIN_VARIANT (basetype) == double_type_node 2075 || TYPE_MAIN_VARIANT (basetype) == idouble_type_node) 2076 fmodfn = builtin_decl_explicit (BUILT_IN_FMOD); 2077 else if (TYPE_MAIN_VARIANT (basetype) == float_type_node 2078 || TYPE_MAIN_VARIANT (basetype) == ifloat_type_node) 2079 fmodfn = builtin_decl_explicit (BUILT_IN_FMODF); 2080 else if (TYPE_MAIN_VARIANT (basetype) == long_double_type_node 2081 || TYPE_MAIN_VARIANT (basetype) == ireal_type_node) 2082 fmodfn = builtin_decl_explicit (BUILT_IN_FMODL); 2083 2084 if (!fmodfn) 2085 { 2086 error ("tried to perform floating-point modulo division on %qT", type); 2087 return error_mark_node; 2088 } 2089 2090 if (COMPLEX_FLOAT_TYPE_P (type)) 2091 { 2092 tree re = build_call_expr (fmodfn, 2, real_part (arg0), arg1); 2093 tree im = build_call_expr (fmodfn, 2, imaginary_part (arg0), arg1); 2094 2095 return complex_expr (type, re, im); 2096 } 2097 2098 if (SCALAR_FLOAT_TYPE_P (type)) 2099 return build_call_expr (fmodfn, 2, arg0, arg1); 2100 2101 /* Should have caught this above. */ 2102 gcc_unreachable (); 2103 } 2104 2105 /* Build a function type whose first argument is a pointer to BASETYPE, 2106 which is to be used for the 'vthis' context parameter for TYPE. 2107 The base type may be a record for member functions, or a void for 2108 nested functions and delegates. */ 2109 2110 tree 2111 build_vthis_function (tree basetype, tree type) 2112 { 2113 gcc_assert (TREE_CODE (type) == FUNCTION_TYPE); 2114 2115 tree argtypes = tree_cons (NULL_TREE, build_pointer_type (basetype), 2116 TYPE_ARG_TYPES (type)); 2117 tree fntype = build_function_type (TREE_TYPE (type), argtypes); 2118 2119 if (RECORD_OR_UNION_TYPE_P (basetype)) 2120 TYPE_METHOD_BASETYPE (fntype) = TYPE_MAIN_VARIANT (basetype); 2121 else 2122 gcc_assert (VOID_TYPE_P (basetype)); 2123 2124 return fntype; 2125 } 2126 2127 /* If SYM is a nested function, return the static chain to be 2128 used when calling that function from the current function. 2129 2130 If SYM is a nested class or struct, return the static chain 2131 to be used when creating an instance of the class from CFUN. */ 2132 2133 tree 2134 get_frame_for_symbol (Dsymbol *sym) 2135 { 2136 FuncDeclaration *thisfd 2137 = d_function_chain ? d_function_chain->function : NULL; 2138 FuncDeclaration *fd = sym->isFuncDeclaration (); 2139 FuncDeclaration *fdparent = NULL; 2140 FuncDeclaration *fdoverride = NULL; 2141 2142 if (fd != NULL) 2143 { 2144 /* Check that the nested function is properly defined. */ 2145 if (!fd->fbody) 2146 { 2147 /* Should instead error on line that references 'fd'. */ 2148 error_at (make_location_t (fd->loc), "nested function missing body"); 2149 return null_pointer_node; 2150 } 2151 2152 fdparent = fd->toParent2 ()->isFuncDeclaration (); 2153 2154 /* Special case for __ensure and __require. */ 2155 if ((fd->ident == Identifier::idPool ("__ensure") 2156 || fd->ident == Identifier::idPool ("__require")) 2157 && fdparent != thisfd) 2158 { 2159 fdoverride = fdparent; 2160 fdparent = thisfd; 2161 } 2162 } 2163 else 2164 { 2165 /* It's a class (or struct). NewExp codegen has already determined its 2166 outer scope is not another class, so it must be a function. */ 2167 while (sym && !sym->isFuncDeclaration ()) 2168 sym = sym->toParent2 (); 2169 2170 fdparent = (FuncDeclaration *) sym; 2171 } 2172 2173 /* Not a nested function, there is no frame pointer to pass. */ 2174 if (fdparent == NULL) 2175 { 2176 /* Only delegate literals report as being nested, even if they are in 2177 global scope. */ 2178 gcc_assert (fd && fd->isFuncLiteralDeclaration ()); 2179 return null_pointer_node; 2180 } 2181 2182 gcc_assert (thisfd != NULL); 2183 2184 if (thisfd != fdparent) 2185 { 2186 /* If no frame pointer for this function. */ 2187 if (!thisfd->vthis) 2188 { 2189 error_at (make_location_t (sym->loc), 2190 "%qs is a nested function and cannot be accessed from %qs", 2191 fd->toPrettyChars (), thisfd->toPrettyChars ()); 2192 return null_pointer_node; 2193 } 2194 2195 /* Make sure we can get the frame pointer to the outer function. 2196 Go up each nesting level until we find the enclosing function. */ 2197 Dsymbol *dsym = thisfd; 2198 2199 while (fd != dsym) 2200 { 2201 /* Check if enclosing function is a function. */ 2202 FuncDeclaration *fd = dsym->isFuncDeclaration (); 2203 2204 if (fd != NULL) 2205 { 2206 if (fdparent == fd->toParent2 ()) 2207 break; 2208 2209 gcc_assert (fd->isNested () || fd->vthis); 2210 dsym = dsym->toParent2 (); 2211 continue; 2212 } 2213 2214 /* Check if enclosed by an aggregate. That means the current 2215 function must be a member function of that aggregate. */ 2216 AggregateDeclaration *ad = dsym->isAggregateDeclaration (); 2217 2218 if (ad == NULL) 2219 goto Lnoframe; 2220 if (ad->isClassDeclaration () && fdparent == ad->toParent2 ()) 2221 break; 2222 if (ad->isStructDeclaration () && fdparent == ad->toParent2 ()) 2223 break; 2224 2225 if (!ad->isNested () || !ad->vthis) 2226 { 2227 Lnoframe: 2228 error_at (make_location_t (thisfd->loc), 2229 "cannot get frame pointer to %qs", 2230 sym->toPrettyChars ()); 2231 return null_pointer_node; 2232 } 2233 2234 dsym = dsym->toParent2 (); 2235 } 2236 } 2237 2238 tree ffo = get_frameinfo (fdparent); 2239 if (FRAMEINFO_CREATES_FRAME (ffo) || FRAMEINFO_STATIC_CHAIN (ffo)) 2240 { 2241 tree frame_ref = get_framedecl (thisfd, fdparent); 2242 2243 /* If 'thisfd' is a derived member function, then 'fdparent' is the 2244 overridden member function in the base class. Even if there's a 2245 closure environment, we should give the original stack data as the 2246 nested function frame. */ 2247 if (fdoverride) 2248 { 2249 ClassDeclaration *cdo = fdoverride->isThis ()->isClassDeclaration (); 2250 ClassDeclaration *cd = thisfd->isThis ()->isClassDeclaration (); 2251 gcc_assert (cdo && cd); 2252 2253 int offset; 2254 if (cdo->isBaseOf (cd, &offset) && offset != 0) 2255 { 2256 /* Generate a new frame to pass to the overriden function that 2257 has the 'this' pointer adjusted. */ 2258 gcc_assert (offset != OFFSET_RUNTIME); 2259 2260 tree type = FRAMEINFO_TYPE (get_frameinfo (fdoverride)); 2261 tree fields = TYPE_FIELDS (type); 2262 /* The 'this' field comes immediately after the '__chain'. */ 2263 tree thisfield = chain_index (1, fields); 2264 vec<constructor_elt, va_gc> *ve = NULL; 2265 2266 tree framefields = TYPE_FIELDS (FRAMEINFO_TYPE (ffo)); 2267 frame_ref = build_deref (frame_ref); 2268 2269 for (tree field = fields; field; field = DECL_CHAIN (field)) 2270 { 2271 tree value = component_ref (frame_ref, framefields); 2272 if (field == thisfield) 2273 value = build_offset (value, size_int (offset)); 2274 2275 CONSTRUCTOR_APPEND_ELT (ve, field, value); 2276 framefields = DECL_CHAIN (framefields); 2277 } 2278 2279 frame_ref = build_address (build_constructor (type, ve)); 2280 } 2281 } 2282 2283 return frame_ref; 2284 } 2285 2286 return null_pointer_node; 2287 } 2288 2289 /* Return the parent function of a nested class CD. */ 2290 2291 static FuncDeclaration * 2292 d_nested_class (ClassDeclaration *cd) 2293 { 2294 FuncDeclaration *fd = NULL; 2295 while (cd && cd->isNested ()) 2296 { 2297 Dsymbol *dsym = cd->toParent2 (); 2298 if ((fd = dsym->isFuncDeclaration ())) 2299 return fd; 2300 else 2301 cd = dsym->isClassDeclaration (); 2302 } 2303 return NULL; 2304 } 2305 2306 /* Return the parent function of a nested struct SD. */ 2307 2308 static FuncDeclaration * 2309 d_nested_struct (StructDeclaration *sd) 2310 { 2311 FuncDeclaration *fd = NULL; 2312 while (sd && sd->isNested ()) 2313 { 2314 Dsymbol *dsym = sd->toParent2 (); 2315 if ((fd = dsym->isFuncDeclaration ())) 2316 return fd; 2317 else 2318 sd = dsym->isStructDeclaration (); 2319 } 2320 return NULL; 2321 } 2322 2323 2324 /* Starting from the current function FD, try to find a suitable value of 2325 'this' in nested function instances. A suitable 'this' value is an 2326 instance of OCD or a class that has OCD as a base. */ 2327 2328 static tree 2329 find_this_tree (ClassDeclaration *ocd) 2330 { 2331 FuncDeclaration *fd = d_function_chain ? d_function_chain->function : NULL; 2332 2333 while (fd) 2334 { 2335 AggregateDeclaration *ad = fd->isThis (); 2336 ClassDeclaration *cd = ad ? ad->isClassDeclaration () : NULL; 2337 2338 if (cd != NULL) 2339 { 2340 if (ocd == cd) 2341 return get_decl_tree (fd->vthis); 2342 else if (ocd->isBaseOf (cd, NULL)) 2343 return convert_expr (get_decl_tree (fd->vthis), 2344 cd->type, ocd->type); 2345 2346 fd = d_nested_class (cd); 2347 } 2348 else 2349 { 2350 if (fd->isNested ()) 2351 { 2352 fd = fd->toParent2 ()->isFuncDeclaration (); 2353 continue; 2354 } 2355 2356 fd = NULL; 2357 } 2358 } 2359 2360 return NULL_TREE; 2361 } 2362 2363 /* Retrieve the outer class/struct 'this' value of DECL from 2364 the current function. */ 2365 2366 tree 2367 build_vthis (AggregateDeclaration *decl) 2368 { 2369 ClassDeclaration *cd = decl->isClassDeclaration (); 2370 StructDeclaration *sd = decl->isStructDeclaration (); 2371 2372 /* If an aggregate nested in a function has no methods and there are no 2373 other nested functions, any static chain created here will never be 2374 translated. Use a null pointer for the link in this case. */ 2375 tree vthis_value = null_pointer_node; 2376 2377 if (cd != NULL || sd != NULL) 2378 { 2379 Dsymbol *outer = decl->toParent2 (); 2380 2381 /* If the parent is a templated struct, the outer context is instead 2382 the enclosing symbol of where the instantiation happened. */ 2383 if (outer->isStructDeclaration ()) 2384 { 2385 gcc_assert (outer->parent && outer->parent->isTemplateInstance ()); 2386 outer = ((TemplateInstance *) outer->parent)->enclosing; 2387 } 2388 2389 /* For outer classes, get a suitable 'this' value. 2390 For outer functions, get a suitable frame/closure pointer. */ 2391 ClassDeclaration *cdo = outer->isClassDeclaration (); 2392 FuncDeclaration *fdo = outer->isFuncDeclaration (); 2393 2394 if (cdo) 2395 { 2396 vthis_value = find_this_tree (cdo); 2397 gcc_assert (vthis_value != NULL_TREE); 2398 } 2399 else if (fdo) 2400 { 2401 tree ffo = get_frameinfo (fdo); 2402 if (FRAMEINFO_CREATES_FRAME (ffo) || FRAMEINFO_STATIC_CHAIN (ffo) 2403 || fdo->hasNestedFrameRefs ()) 2404 vthis_value = get_frame_for_symbol (decl); 2405 else if (cd != NULL) 2406 { 2407 /* Classes nested in methods are allowed to access any outer 2408 class fields, use the function chain in this case. */ 2409 if (fdo->vthis && fdo->vthis->type != Type::tvoidptr) 2410 vthis_value = get_decl_tree (fdo->vthis); 2411 } 2412 } 2413 else 2414 gcc_unreachable (); 2415 } 2416 2417 return vthis_value; 2418 } 2419 2420 /* Build the RECORD_TYPE that describes the function frame or closure type for 2421 the function FD. FFI is the tree holding all frame information. */ 2422 2423 static tree 2424 build_frame_type (tree ffi, FuncDeclaration *fd) 2425 { 2426 if (FRAMEINFO_TYPE (ffi)) 2427 return FRAMEINFO_TYPE (ffi); 2428 2429 tree frame_rec_type = make_node (RECORD_TYPE); 2430 char *name = concat (FRAMEINFO_IS_CLOSURE (ffi) ? "CLOSURE." : "FRAME.", 2431 fd->toPrettyChars (), NULL); 2432 TYPE_NAME (frame_rec_type) = get_identifier (name); 2433 free (name); 2434 2435 tree fields = NULL_TREE; 2436 2437 /* Function is a member or nested, so must have field for outer context. */ 2438 if (fd->vthis) 2439 { 2440 tree ptr_field = build_decl (BUILTINS_LOCATION, FIELD_DECL, 2441 get_identifier ("__chain"), ptr_type_node); 2442 DECL_FIELD_CONTEXT (ptr_field) = frame_rec_type; 2443 fields = chainon (NULL_TREE, ptr_field); 2444 DECL_NONADDRESSABLE_P (ptr_field) = 1; 2445 } 2446 2447 /* The __ensure and __require are called directly, so never make the outer 2448 functions closure, but nevertheless could still be referencing parameters 2449 of the calling function non-locally. So we add all parameters with nested 2450 refs to the function frame, this should also mean overriding methods will 2451 have the same frame layout when inheriting a contract. */ 2452 if ((global.params.useIn && fd->frequire) 2453 || (global.params.useOut && fd->fensure)) 2454 { 2455 if (fd->parameters) 2456 { 2457 for (size_t i = 0; fd->parameters && i < fd->parameters->dim; i++) 2458 { 2459 VarDeclaration *v = (*fd->parameters)[i]; 2460 /* Remove if already in closureVars so can push to front. */ 2461 for (size_t j = i; j < fd->closureVars.dim; j++) 2462 { 2463 Dsymbol *s = fd->closureVars[j]; 2464 if (s == v) 2465 { 2466 fd->closureVars.remove (j); 2467 break; 2468 } 2469 } 2470 fd->closureVars.insert (i, v); 2471 } 2472 } 2473 2474 /* Also add hidden 'this' to outer context. */ 2475 if (fd->vthis) 2476 { 2477 for (size_t i = 0; i < fd->closureVars.dim; i++) 2478 { 2479 Dsymbol *s = fd->closureVars[i]; 2480 if (s == fd->vthis) 2481 { 2482 fd->closureVars.remove (i); 2483 break; 2484 } 2485 } 2486 fd->closureVars.insert (0, fd->vthis); 2487 } 2488 } 2489 2490 for (size_t i = 0; i < fd->closureVars.dim; i++) 2491 { 2492 VarDeclaration *v = fd->closureVars[i]; 2493 tree vsym = get_symbol_decl (v); 2494 tree ident = v->ident 2495 ? get_identifier (v->ident->toChars ()) : NULL_TREE; 2496 2497 tree field = build_decl (make_location_t (v->loc), FIELD_DECL, ident, 2498 TREE_TYPE (vsym)); 2499 SET_DECL_LANG_FRAME_FIELD (vsym, field); 2500 DECL_FIELD_CONTEXT (field) = frame_rec_type; 2501 fields = chainon (fields, field); 2502 TREE_USED (vsym) = 1; 2503 2504 TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (vsym); 2505 DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (vsym); 2506 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (vsym); 2507 2508 /* Can't do nrvo if the variable is put in a frame. */ 2509 if (fd->nrvo_can && fd->nrvo_var == v) 2510 fd->nrvo_can = 0; 2511 2512 if (FRAMEINFO_IS_CLOSURE (ffi)) 2513 { 2514 /* Because the value needs to survive the end of the scope. */ 2515 if ((v->edtor && (v->storage_class & STCparameter)) 2516 || v->needsScopeDtor ()) 2517 error_at (make_location_t (v->loc), 2518 "has scoped destruction, cannot build closure"); 2519 } 2520 } 2521 2522 TYPE_FIELDS (frame_rec_type) = fields; 2523 TYPE_READONLY (frame_rec_type) = 1; 2524 layout_type (frame_rec_type); 2525 d_keep (frame_rec_type); 2526 2527 return frame_rec_type; 2528 } 2529 2530 /* Closures are implemented by taking the local variables that 2531 need to survive the scope of the function, and copying them 2532 into a GC allocated chuck of memory. That chunk, called the 2533 closure here, is inserted into the linked list of stack 2534 frames instead of the usual stack frame. 2535 2536 If a closure is not required, but FD still needs a frame to lower 2537 nested refs, then instead build custom static chain decl on stack. */ 2538 2539 void 2540 build_closure (FuncDeclaration *fd) 2541 { 2542 tree ffi = get_frameinfo (fd); 2543 2544 if (!FRAMEINFO_CREATES_FRAME (ffi)) 2545 return; 2546 2547 tree type = FRAMEINFO_TYPE (ffi); 2548 gcc_assert (COMPLETE_TYPE_P (type)); 2549 2550 tree decl, decl_ref; 2551 2552 if (FRAMEINFO_IS_CLOSURE (ffi)) 2553 { 2554 decl = build_local_temp (build_pointer_type (type)); 2555 DECL_NAME (decl) = get_identifier ("__closptr"); 2556 decl_ref = build_deref (decl); 2557 2558 /* Allocate memory for closure. */ 2559 tree arg = convert (build_ctype (Type::tsize_t), TYPE_SIZE_UNIT (type)); 2560 tree init = build_libcall (LIBCALL_ALLOCMEMORY, Type::tvoidptr, 1, arg); 2561 2562 tree init_exp = build_assign (INIT_EXPR, decl, 2563 build_nop (TREE_TYPE (decl), init)); 2564 add_stmt (init_exp); 2565 } 2566 else 2567 { 2568 decl = build_local_temp (type); 2569 DECL_NAME (decl) = get_identifier ("__frame"); 2570 decl_ref = decl; 2571 } 2572 2573 /* Set the first entry to the parent closure/frame, if any. */ 2574 if (fd->vthis) 2575 { 2576 tree chain_field = component_ref (decl_ref, TYPE_FIELDS (type)); 2577 tree chain_expr = modify_expr (chain_field, 2578 d_function_chain->static_chain); 2579 add_stmt (chain_expr); 2580 } 2581 2582 /* Copy parameters that are referenced nonlocally. */ 2583 for (size_t i = 0; i < fd->closureVars.dim; i++) 2584 { 2585 VarDeclaration *v = fd->closureVars[i]; 2586 2587 if (!v->isParameter ()) 2588 continue; 2589 2590 tree vsym = get_symbol_decl (v); 2591 2592 tree field = component_ref (decl_ref, DECL_LANG_FRAME_FIELD (vsym)); 2593 tree expr = modify_expr (field, vsym); 2594 add_stmt (expr); 2595 } 2596 2597 if (!FRAMEINFO_IS_CLOSURE (ffi)) 2598 decl = build_address (decl); 2599 2600 d_function_chain->static_chain = decl; 2601 } 2602 2603 /* Return the frame of FD. This could be a static chain or a closure 2604 passed via the hidden 'this' pointer. */ 2605 2606 tree 2607 get_frameinfo (FuncDeclaration *fd) 2608 { 2609 tree fds = get_symbol_decl (fd); 2610 if (DECL_LANG_FRAMEINFO (fds)) 2611 return DECL_LANG_FRAMEINFO (fds); 2612 2613 tree ffi = make_node (FUNCFRAME_INFO); 2614 2615 DECL_LANG_FRAMEINFO (fds) = ffi; 2616 2617 if (fd->needsClosure ()) 2618 { 2619 /* Set-up a closure frame, this will be allocated on the heap. */ 2620 FRAMEINFO_CREATES_FRAME (ffi) = 1; 2621 FRAMEINFO_IS_CLOSURE (ffi) = 1; 2622 } 2623 else if (fd->hasNestedFrameRefs ()) 2624 { 2625 /* Functions with nested refs must create a static frame for local 2626 variables to be referenced from. */ 2627 FRAMEINFO_CREATES_FRAME (ffi) = 1; 2628 } 2629 else 2630 { 2631 /* For nested functions, default to creating a frame. Even if there are 2632 no fields to populate the frame, create it anyway, as this will be 2633 used as the record type instead of `void*` for the this parameter. */ 2634 if (fd->vthis && fd->vthis->type == Type::tvoidptr) 2635 FRAMEINFO_CREATES_FRAME (ffi) = 1; 2636 2637 /* In checkNestedReference, references from contracts are not added to the 2638 closureVars array, so assume all parameters referenced. */ 2639 if ((global.params.useIn && fd->frequire) 2640 || (global.params.useOut && fd->fensure)) 2641 FRAMEINFO_CREATES_FRAME (ffi) = 1; 2642 2643 /* If however `fd` is nested (deeply) in a function that creates a 2644 closure, then `fd` instead inherits that closure via hidden vthis 2645 pointer, and doesn't create a stack frame at all. */ 2646 FuncDeclaration *ff = fd; 2647 2648 while (ff) 2649 { 2650 tree ffo = get_frameinfo (ff); 2651 2652 if (ff != fd && FRAMEINFO_CREATES_FRAME (ffo)) 2653 { 2654 gcc_assert (FRAMEINFO_TYPE (ffo)); 2655 FRAMEINFO_CREATES_FRAME (ffi) = 0; 2656 FRAMEINFO_STATIC_CHAIN (ffi) = 1; 2657 FRAMEINFO_IS_CLOSURE (ffi) = FRAMEINFO_IS_CLOSURE (ffo); 2658 gcc_assert (COMPLETE_TYPE_P (FRAMEINFO_TYPE (ffo))); 2659 FRAMEINFO_TYPE (ffi) = FRAMEINFO_TYPE (ffo); 2660 break; 2661 } 2662 2663 /* Stop looking if no frame pointer for this function. */ 2664 if (ff->vthis == NULL) 2665 break; 2666 2667 AggregateDeclaration *ad = ff->isThis (); 2668 if (ad && ad->isNested ()) 2669 { 2670 while (ad->isNested ()) 2671 { 2672 Dsymbol *d = ad->toParent2 (); 2673 ad = d->isAggregateDeclaration (); 2674 ff = d->isFuncDeclaration (); 2675 2676 if (ad == NULL) 2677 break; 2678 } 2679 } 2680 else 2681 ff = ff->toParent2 ()->isFuncDeclaration (); 2682 } 2683 } 2684 2685 /* Build type now as may be referenced from another module. */ 2686 if (FRAMEINFO_CREATES_FRAME (ffi)) 2687 FRAMEINFO_TYPE (ffi) = build_frame_type (ffi, fd); 2688 2689 return ffi; 2690 } 2691 2692 /* Return a pointer to the frame/closure block of OUTER 2693 so can be accessed from the function INNER. */ 2694 2695 tree 2696 get_framedecl (FuncDeclaration *inner, FuncDeclaration *outer) 2697 { 2698 tree result = d_function_chain->static_chain; 2699 FuncDeclaration *fd = inner; 2700 2701 while (fd && fd != outer) 2702 { 2703 AggregateDeclaration *ad; 2704 ClassDeclaration *cd; 2705 StructDeclaration *sd; 2706 2707 /* Parent frame link is the first field. */ 2708 if (FRAMEINFO_CREATES_FRAME (get_frameinfo (fd))) 2709 result = indirect_ref (ptr_type_node, result); 2710 2711 if (fd->isNested ()) 2712 fd = fd->toParent2 ()->isFuncDeclaration (); 2713 /* The frame/closure record always points to the outer function's 2714 frame, even if there are intervening nested classes or structs. 2715 So, we can just skip over these. */ 2716 else if ((ad = fd->isThis ()) && (cd = ad->isClassDeclaration ())) 2717 fd = d_nested_class (cd); 2718 else if ((ad = fd->isThis ()) && (sd = ad->isStructDeclaration ())) 2719 fd = d_nested_struct (sd); 2720 else 2721 break; 2722 } 2723 2724 /* Go get our frame record. */ 2725 gcc_assert (fd == outer); 2726 tree frame_type = FRAMEINFO_TYPE (get_frameinfo (outer)); 2727 2728 if (frame_type != NULL_TREE) 2729 { 2730 result = build_nop (build_pointer_type (frame_type), result); 2731 return result; 2732 } 2733 else 2734 { 2735 error_at (make_location_t (inner->loc), 2736 "forward reference to frame of %qs", outer->toChars ()); 2737 return null_pointer_node; 2738 } 2739 } 2740