1/* expr.cc -- Lower D frontend expressions to GCC trees. 2 Copyright (C) 2015-2020 Free Software Foundation, Inc. 3 4GCC is free software; you can redistribute it and/or modify 5it under the terms of the GNU General Public License as published by 6the Free Software Foundation; either version 3, or (at your option) 7any later version. 8 9GCC is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12GNU General Public License for more details. 13 14You should have received a copy of the GNU General Public License 15along 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/expression.h" 26#include "dmd/identifier.h" 27#include "dmd/init.h" 28#include "dmd/module.h" 29#include "dmd/mtype.h" 30#include "dmd/template.h" 31 32#include "tree.h" 33#include "fold-const.h" 34#include "diagnostic.h" 35#include "langhooks.h" 36#include "tm.h" 37#include "function.h" 38#include "toplev.h" 39#include "varasm.h" 40#include "predict.h" 41#include "stor-layout.h" 42 43#include "d-tree.h" 44 45 46/* Implements the visitor interface to build the GCC trees of all Expression 47 AST classes emitted from the D Front-end. 48 All visit methods accept one parameter E, which holds the frontend AST 49 of the expression to compile. They also don't return any value, instead 50 generated code is cached in RESULT_ and returned from the caller. */ 51 52class ExprVisitor : public Visitor 53{ 54 using Visitor::visit; 55 56 tree result_; 57 bool constp_; 58 59 /* Determine if type is a struct that has a postblit. */ 60 61 bool needs_postblit (Type *t) 62 { 63 t = t->baseElemOf (); 64 65 if (t->ty == Tstruct) 66 { 67 StructDeclaration *sd = ((TypeStruct *) t)->sym; 68 if (sd->postblit) 69 return true; 70 } 71 72 return false; 73 } 74 75 /* Determine if type is a struct that has a destructor. */ 76 77 bool needs_dtor (Type *t) 78 { 79 t = t->baseElemOf (); 80 81 if (t->ty == Tstruct) 82 { 83 StructDeclaration *sd = ((TypeStruct *) t)->sym; 84 if (sd->dtor) 85 return true; 86 } 87 88 return false; 89 } 90 91 /* Determine if expression is suitable lvalue. */ 92 93 bool lvalue_p (Expression *e) 94 { 95 return ((e->op != TOKslice && e->isLvalue ()) 96 || (e->op == TOKslice && ((UnaExp *) e)->e1->isLvalue ()) 97 || (e->op == TOKcast && ((UnaExp *) e)->e1->isLvalue ())); 98 } 99 100 /* Build an expression of code CODE, data type TYPE, and operands ARG0 and 101 ARG1. Perform relevant conversions needed for correct code operations. */ 102 103 tree binary_op (tree_code code, tree type, tree arg0, tree arg1) 104 { 105 tree t0 = TREE_TYPE (arg0); 106 tree t1 = TREE_TYPE (arg1); 107 tree ret = NULL_TREE; 108 109 bool unsignedp = TYPE_UNSIGNED (t0) || TYPE_UNSIGNED (t1); 110 111 /* Deal with float mod expressions immediately. */ 112 if (code == FLOAT_MOD_EXPR) 113 return build_float_modulus (type, arg0, arg1); 114 115 if (POINTER_TYPE_P (t0) && INTEGRAL_TYPE_P (t1)) 116 return build_nop (type, build_offset_op (code, arg0, arg1)); 117 118 if (INTEGRAL_TYPE_P (t0) && POINTER_TYPE_P (t1)) 119 return build_nop (type, build_offset_op (code, arg1, arg0)); 120 121 if (POINTER_TYPE_P (t0) && POINTER_TYPE_P (t1)) 122 { 123 gcc_assert (code == MINUS_EXPR); 124 tree ptrtype = lang_hooks.types.type_for_mode (ptr_mode, 0); 125 126 /* POINTER_DIFF_EXPR requires a signed integer type of the same size as 127 pointers. If some platform cannot provide that, or has a larger 128 ptrdiff_type to support differences larger than half the address 129 space, cast the pointers to some larger integer type and do the 130 computations in that type. */ 131 if (TYPE_PRECISION (ptrtype) > TYPE_PRECISION (t0)) 132 ret = fold_build2 (MINUS_EXPR, ptrtype, 133 d_convert (ptrtype, arg0), 134 d_convert (ptrtype, arg1)); 135 else 136 ret = fold_build2 (POINTER_DIFF_EXPR, ptrtype, arg0, arg1); 137 } 138 else if (INTEGRAL_TYPE_P (type) && (TYPE_UNSIGNED (type) != unsignedp)) 139 { 140 tree inttype = (unsignedp) 141 ? d_unsigned_type (type) : d_signed_type (type); 142 ret = fold_build2 (code, inttype, arg0, arg1); 143 } 144 else 145 { 146 /* If the operation needs excess precision. */ 147 tree eptype = excess_precision_type (type); 148 if (eptype != NULL_TREE) 149 { 150 arg0 = d_convert (eptype, arg0); 151 arg1 = d_convert (eptype, arg1); 152 } 153 else 154 { 155 /* Front-end does not do this conversion and GCC does not 156 always do it right. */ 157 if (COMPLEX_FLOAT_TYPE_P (t0) && !COMPLEX_FLOAT_TYPE_P (t1)) 158 arg1 = d_convert (t0, arg1); 159 else if (COMPLEX_FLOAT_TYPE_P (t1) && !COMPLEX_FLOAT_TYPE_P (t0)) 160 arg0 = d_convert (t1, arg0); 161 162 eptype = type; 163 } 164 165 ret = build2 (code, eptype, arg0, arg1); 166 } 167 168 return d_convert (type, ret); 169 } 170 171 /* Build a binary expression of code CODE, assigning the result into E1. */ 172 173 tree binop_assignment (tree_code code, Expression *e1, Expression *e2) 174 { 175 /* Skip casts for lhs assignment. */ 176 Expression *e1b = e1; 177 while (e1b->op == TOKcast) 178 { 179 CastExp *ce = (CastExp *) e1b; 180 gcc_assert (same_type_p (ce->type, ce->to)); 181 e1b = ce->e1; 182 } 183 184 /* Stabilize LHS for assignment. */ 185 tree lhs = build_expr (e1b); 186 tree lexpr = stabilize_expr (&lhs); 187 188 /* The LHS expression could be an assignment, to which its operation gets 189 lost during gimplification. */ 190 if (TREE_CODE (lhs) == MODIFY_EXPR) 191 { 192 /* If LHS has side effects, call stabilize_reference on it, so it can 193 be evaluated multiple times. */ 194 if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0))) 195 lhs = build_assign (MODIFY_EXPR, 196 stabilize_reference (TREE_OPERAND (lhs, 0)), 197 TREE_OPERAND (lhs, 1)); 198 199 lexpr = compound_expr (lexpr, lhs); 200 lhs = TREE_OPERAND (lhs, 0); 201 } 202 203 lhs = stabilize_reference (lhs); 204 205 /* Save RHS, to ensure that the expression is evaluated before LHS. */ 206 tree rhs = build_expr (e2); 207 tree rexpr = d_save_expr (rhs); 208 209 rhs = this->binary_op (code, build_ctype (e1->type), 210 convert_expr (lhs, e1b->type, e1->type), rexpr); 211 if (TREE_SIDE_EFFECTS (rhs)) 212 rhs = compound_expr (rexpr, rhs); 213 214 tree expr = modify_expr (lhs, convert_expr (rhs, e1->type, e1b->type)); 215 return compound_expr (lexpr, expr); 216 } 217 218public: 219 ExprVisitor (bool constp) 220 { 221 this->result_ = NULL_TREE; 222 this->constp_ = constp; 223 } 224 225 tree result (void) 226 { 227 return this->result_; 228 } 229 230 /* Visitor interfaces, each Expression class should have 231 overridden the default. */ 232 233 void visit (Expression *) 234 { 235 gcc_unreachable (); 236 } 237 238 /* Build a conditional expression. If either the second or third 239 expression is void, then the resulting type is void. Otherwise 240 they are implicitly converted to a common type. */ 241 242 void visit (CondExp *e) 243 { 244 tree cond = convert_for_condition (build_expr (e->econd), 245 e->econd->type); 246 tree t1 = build_expr (e->e1); 247 tree t2 = build_expr (e->e2); 248 249 if (e->type->ty != Tvoid) 250 { 251 t1 = convert_expr (t1, e->e1->type, e->type); 252 t2 = convert_expr (t2, e->e2->type, e->type); 253 } 254 255 this->result_ = build_condition (build_ctype (e->type), cond, t1, t2); 256 } 257 258 /* Build an identity comparison expression. Operands go through the 259 usual conversions to bring them to a common type before comparison. 260 The result type is bool. */ 261 262 void visit (IdentityExp *e) 263 { 264 tree_code code = (e->op == TOKidentity) ? EQ_EXPR : NE_EXPR; 265 Type *tb1 = e->e1->type->toBasetype (); 266 Type *tb2 = e->e2->type->toBasetype (); 267 268 if ((tb1->ty == Tsarray || tb1->ty == Tarray) 269 && (tb2->ty == Tsarray || tb2->ty == Tarray)) 270 { 271 /* For static and dynamic arrays, identity is defined as referring to 272 the same array elements and the same number of elements. */ 273 tree t1 = d_array_convert (e->e1); 274 tree t2 = d_array_convert (e->e2); 275 this->result_ = d_convert (build_ctype (e->type), 276 build_boolop (code, t1, t2)); 277 } 278 else if (tb1->isfloating () && tb1->ty != Tvector) 279 { 280 /* For floating-point values, identity is defined as the bits in the 281 operands being identical. */ 282 tree t1 = d_save_expr (build_expr (e->e1)); 283 tree t2 = d_save_expr (build_expr (e->e2)); 284 285 if (!tb1->iscomplex ()) 286 this->result_ = build_float_identity (code, t1, t2); 287 else 288 { 289 /* Compare the real and imaginary parts separately. */ 290 tree req = build_float_identity (code, real_part (t1), 291 real_part (t2)); 292 tree ieq = build_float_identity (code, imaginary_part (t1), 293 imaginary_part (t2)); 294 295 if (code == EQ_EXPR) 296 this->result_ = build_boolop (TRUTH_ANDIF_EXPR, req, ieq); 297 else 298 this->result_ = build_boolop (TRUTH_ORIF_EXPR, req, ieq); 299 } 300 } 301 else if (tb1->ty == Tstruct) 302 { 303 /* For struct objects, identity is defined as bits in operands being 304 identical also. Alignment holes in structs are ignored. */ 305 StructDeclaration *sd = ((TypeStruct *) tb1)->sym; 306 tree t1 = build_expr (e->e1); 307 tree t2 = build_expr (e->e2); 308 309 gcc_assert (same_type_p (tb1, tb2)); 310 311 this->result_ = build_struct_comparison (code, sd, t1, t2); 312 } 313 else 314 { 315 /* For operands of other types, identity is defined as being the 316 same as equality expressions. */ 317 tree t1 = build_expr (e->e1); 318 tree t2 = build_expr (e->e2); 319 this->result_ = d_convert (build_ctype (e->type), 320 build_boolop (code, t1, t2)); 321 } 322 } 323 324 /* Build an equality expression, which compare the two operands for either 325 equality or inequality. Operands go through the usual conversions to bring 326 them to a common type before comparison. The result type is bool. */ 327 328 void visit (EqualExp *e) 329 { 330 Type *tb1 = e->e1->type->toBasetype (); 331 Type *tb2 = e->e2->type->toBasetype (); 332 tree_code code = (e->op == TOKequal) ? EQ_EXPR : NE_EXPR; 333 334 if ((tb1->ty == Tsarray || tb1->ty == Tarray) 335 && (tb2->ty == Tsarray || tb2->ty == Tarray)) 336 { 337 /* For static and dynamic arrays, equality is defined as the lengths of 338 the arrays matching, and all the elements are equal. */ 339 Type *t1elem = tb1->nextOf ()->toBasetype (); 340 Type *t2elem = tb1->nextOf ()->toBasetype (); 341 342 /* Check if comparisons of arrays can be optimized using memcmp. 343 This will inline EQ expressions as: 344 e1.length == e2.length && memcmp(e1.ptr, e2.ptr, size) == 0; 345 Or when generating a NE expression: 346 e1.length != e2.length || memcmp(e1.ptr, e2.ptr, size) != 0; */ 347 if ((t1elem->isintegral () || t1elem->ty == Tvoid 348 || (t1elem->ty == Tstruct && !((TypeStruct *)t1elem)->sym->xeq)) 349 && t1elem->ty == t2elem->ty) 350 { 351 tree t1 = d_array_convert (e->e1); 352 tree t2 = d_array_convert (e->e2); 353 tree result; 354 355 /* Make temporaries to prevent multiple evaluations. */ 356 tree t1saved = d_save_expr (t1); 357 tree t2saved = d_save_expr (t2); 358 359 /* Length of arrays, for comparisons done before calling memcmp. */ 360 tree t1len = d_array_length (t1saved); 361 tree t2len = d_array_length (t2saved); 362 363 /* Reference to array data. */ 364 tree t1ptr = d_array_ptr (t1saved); 365 tree t2ptr = d_array_ptr (t2saved); 366 367 /* Compare arrays using memcmp if possible, otherwise for structs, 368 each field is compared inline. */ 369 if (t1elem->ty != Tstruct 370 || identity_compare_p (((TypeStruct *) t1elem)->sym)) 371 { 372 tree size = size_mult_expr (t1len, size_int (t1elem->size ())); 373 tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP); 374 375 result = build_call_expr (tmemcmp, 3, t1ptr, t2ptr, size); 376 result = build_boolop (code, result, integer_zero_node); 377 } 378 else 379 { 380 StructDeclaration *sd = ((TypeStruct *) t1elem)->sym; 381 382 result = build_array_struct_comparison (code, sd, t1len, 383 t1ptr, t2ptr); 384 } 385 386 /* Check array length first before passing to memcmp. 387 For equality expressions, this becomes: 388 (e1.length == 0 || memcmp); 389 Otherwise for inequality: 390 (e1.length != 0 && memcmp); */ 391 tree tsizecmp = build_boolop (code, t1len, size_zero_node); 392 if (e->op == TOKequal) 393 result = build_boolop (TRUTH_ORIF_EXPR, tsizecmp, result); 394 else 395 result = build_boolop (TRUTH_ANDIF_EXPR, tsizecmp, result); 396 397 /* Finally, check if lengths of both arrays match if dynamic. 398 The frontend should have already guaranteed that static arrays 399 have same size. */ 400 if (tb1->ty == Tsarray && tb2->ty == Tsarray) 401 gcc_assert (tb1->size () == tb2->size ()); 402 else 403 { 404 tree tlencmp = build_boolop (code, t1len, t2len); 405 if (e->op == TOKequal) 406 result = build_boolop (TRUTH_ANDIF_EXPR, tlencmp, result); 407 else 408 result = build_boolop (TRUTH_ORIF_EXPR, tlencmp, result); 409 } 410 411 /* Ensure left-to-right order of evaluation. */ 412 if (TREE_SIDE_EFFECTS (t2)) 413 result = compound_expr (t2saved, result); 414 415 if (TREE_SIDE_EFFECTS (t1)) 416 result = compound_expr (t1saved, result); 417 418 this->result_ = result; 419 } 420 else 421 { 422 /* Use _adEq2() to compare each element. */ 423 Type *t1array = t1elem->arrayOf (); 424 tree result = build_libcall (LIBCALL_ADEQ2, e->type, 3, 425 d_array_convert (e->e1), 426 d_array_convert (e->e2), 427 build_typeinfo (e->loc, t1array)); 428 429 if (e->op == TOKnotequal) 430 result = build1 (TRUTH_NOT_EXPR, build_ctype (e->type), result); 431 432 this->result_ = result; 433 } 434 } 435 else if (tb1->ty == Tstruct) 436 { 437 /* Equality for struct objects means the logical product of all 438 equality results of the corresponding object fields. */ 439 StructDeclaration *sd = ((TypeStruct *) tb1)->sym; 440 tree t1 = build_expr (e->e1); 441 tree t2 = build_expr (e->e2); 442 443 gcc_assert (same_type_p (tb1, tb2)); 444 445 this->result_ = build_struct_comparison (code, sd, t1, t2); 446 } 447 else if (tb1->ty == Taarray && tb2->ty == Taarray) 448 { 449 /* Use _aaEqual() for associative arrays. */ 450 TypeAArray *taa1 = (TypeAArray *) tb1; 451 tree result = build_libcall (LIBCALL_AAEQUAL, e->type, 3, 452 build_typeinfo (e->loc, taa1), 453 build_expr (e->e1), 454 build_expr (e->e2)); 455 456 if (e->op == TOKnotequal) 457 result = build1 (TRUTH_NOT_EXPR, build_ctype (e->type), result); 458 459 this->result_ = result; 460 } 461 else 462 { 463 /* For operands of other types, equality is defined as the bit pattern 464 of the type matches exactly. */ 465 tree t1 = build_expr (e->e1); 466 tree t2 = build_expr (e->e2); 467 468 this->result_ = d_convert (build_ctype (e->type), 469 build_boolop (code, t1, t2)); 470 } 471 } 472 473 /* Build an `in' expression. This is a condition to see if an element 474 exists in an associative array. The result is a pointer to the 475 element, or null if false. */ 476 477 void visit (InExp *e) 478 { 479 Type *tb2 = e->e2->type->toBasetype (); 480 gcc_assert (tb2->ty == Taarray); 481 482 Type *tkey = ((TypeAArray *) tb2)->index->toBasetype (); 483 tree key = convert_expr (build_expr (e->e1), e->e1->type, tkey); 484 485 /* Build a call to _aaInX(). */ 486 this->result_ = build_libcall (LIBCALL_AAINX, e->type, 3, 487 build_expr (e->e2), 488 build_typeinfo (e->loc, tkey), 489 build_address (key)); 490 } 491 492 /* Build a relational expression. The result type is bool. */ 493 494 void visit (CmpExp *e) 495 { 496 Type *tb1 = e->e1->type->toBasetype (); 497 Type *tb2 = e->e2->type->toBasetype (); 498 499 tree result; 500 tree_code code; 501 502 switch (e->op) 503 { 504 case TOKle: 505 code = LE_EXPR; 506 break; 507 508 case TOKlt: 509 code = LT_EXPR; 510 break; 511 512 case TOKge: 513 code = GE_EXPR; 514 break; 515 516 case TOKgt: 517 code = GT_EXPR; 518 break; 519 520 default: 521 gcc_unreachable (); 522 } 523 524 if ((tb1->ty == Tsarray || tb1->ty == Tarray) 525 && (tb2->ty == Tsarray || tb2->ty == Tarray)) 526 { 527 /* For static and dynamic arrays, the result of the relational op is 528 the result of the operator applied to the first non-equal element 529 of the array. If two arrays compare equal, but are of different 530 lengths, the shorter array compares as less than the longer. */ 531 Type *telem = tb1->nextOf ()->toBasetype (); 532 533 tree call = build_libcall (LIBCALL_ADCMP2, Type::tint32, 3, 534 d_array_convert (e->e1), 535 d_array_convert (e->e2), 536 build_typeinfo (e->loc, telem->arrayOf ())); 537 result = build_boolop (code, call, integer_zero_node); 538 539 this->result_ = d_convert (build_ctype (e->type), result); 540 return; 541 } 542 543 /* Simple comparison. */ 544 result = build_boolop (code, build_expr (e->e1), build_expr (e->e2)); 545 this->result_ = d_convert (build_ctype (e->type), result); 546 } 547 548 /* Build an `and if' expression. If the right operand expression is void, 549 then the resulting type is void. Otherwise the result is bool. */ 550 551 void visit (AndAndExp *e) 552 { 553 if (e->e2->type->toBasetype ()->ty != Tvoid) 554 { 555 tree t1 = build_expr (e->e1); 556 tree t2 = build_expr (e->e2); 557 558 t1 = convert_for_condition (t1, e->e1->type); 559 t2 = convert_for_condition (t2, e->e2->type); 560 561 this->result_ = d_convert (build_ctype (e->type), 562 build_boolop (TRUTH_ANDIF_EXPR, t1, t2)); 563 } 564 else 565 { 566 tree t1 = convert_for_condition (build_expr (e->e1), e->e1->type); 567 tree t2 = build_expr_dtor (e->e2); 568 569 this->result_ = build_condition (build_ctype (e->type), 570 t1, t2, void_node); 571 } 572 } 573 574 /* Build an `or if' expression. If the right operand expression is void, 575 then the resulting type is void. Otherwise the result is bool. */ 576 577 void visit (OrOrExp *e) 578 { 579 if (e->e2->type->toBasetype ()->ty != Tvoid) 580 { 581 tree t1 = convert_for_condition (build_expr (e->e1), e->e1->type); 582 tree t2 = convert_for_condition (build_expr (e->e2), e->e2->type); 583 584 this->result_ = d_convert (build_ctype (e->type), 585 build_boolop (TRUTH_ORIF_EXPR, t1, t2)); 586 } 587 else 588 { 589 tree t1 = convert_for_condition (build_expr (e->e1), e->e1->type); 590 tree t2 = build_expr_dtor (e->e2); 591 tree cond = build1 (TRUTH_NOT_EXPR, d_bool_type, t1); 592 593 this->result_ = build_condition (build_ctype (e->type), 594 cond, t2, void_node); 595 } 596 } 597 598 /* Build a binary operand expression. Operands go through usual arithmetic 599 conversions to bring them to a common type before evaluating. */ 600 601 void visit (BinExp *e) 602 { 603 tree_code code; 604 605 switch (e->op) 606 { 607 case TOKadd: 608 case TOKmin: 609 if ((e->e1->type->isreal () && e->e2->type->isimaginary ()) 610 || (e->e1->type->isimaginary () && e->e2->type->isreal ())) 611 { 612 /* If the result is complex, then we can shortcut binary_op. 613 Frontend should have already validated types and sizes. */ 614 tree t1 = build_expr (e->e1); 615 tree t2 = build_expr (e->e2); 616 617 if (e->op == TOKmin) 618 t2 = build1 (NEGATE_EXPR, TREE_TYPE (t2), t2); 619 620 if (e->e1->type->isreal ()) 621 this->result_ = complex_expr (build_ctype (e->type), t1, t2); 622 else 623 this->result_ = complex_expr (build_ctype (e->type), t2, t1); 624 625 return; 626 } 627 else 628 code = (e->op == TOKadd) 629 ? PLUS_EXPR : MINUS_EXPR; 630 break; 631 632 case TOKmul: 633 code = MULT_EXPR; 634 break; 635 636 case TOKdiv: 637 code = e->e1->type->isintegral () 638 ? TRUNC_DIV_EXPR : RDIV_EXPR; 639 break; 640 641 case TOKmod: 642 code = e->e1->type->isfloating () 643 ? FLOAT_MOD_EXPR : TRUNC_MOD_EXPR; 644 break; 645 646 case TOKand: 647 code = BIT_AND_EXPR; 648 break; 649 650 case TOKor: 651 code = BIT_IOR_EXPR; 652 break; 653 654 case TOKxor: 655 code = BIT_XOR_EXPR; 656 break; 657 658 case TOKshl: 659 code = LSHIFT_EXPR; 660 break; 661 662 case TOKshr: 663 code = RSHIFT_EXPR; 664 break; 665 666 case TOKushr: 667 code = UNSIGNED_RSHIFT_EXPR; 668 break; 669 670 default: 671 gcc_unreachable (); 672 } 673 674 this->result_ = this->binary_op (code, build_ctype (e->type), 675 build_expr (e->e1), build_expr (e->e2)); 676 } 677 678 679 /* Build a concat expression, which concatenates two or more arrays of the 680 same type, producing a dynamic array with the result. If one operand 681 is an element type, that element is converted to an array of length 1. */ 682 683 void visit (CatExp *e) 684 { 685 Type *tb1 = e->e1->type->toBasetype (); 686 Type *tb2 = e->e2->type->toBasetype (); 687 Type *etype; 688 689 if (tb1->ty == Tarray || tb1->ty == Tsarray) 690 etype = tb1->nextOf (); 691 else 692 etype = tb2->nextOf (); 693 694 tree result; 695 696 if (e->e1->op == TOKcat) 697 { 698 /* Flatten multiple concatenations to an array. 699 So the expression ((a ~ b) ~ c) becomes [a, b, c] */ 700 int ndims = 2; 701 702 for (Expression *ex = e->e1; ex->op == TOKcat;) 703 { 704 if (ex->op == TOKcat) 705 { 706 ex = ((CatExp *) ex)->e1; 707 ndims++; 708 } 709 } 710 711 /* Store all concatenation args to a temporary byte[][ndims] array. */ 712 Type *targselem = Type::tint8->arrayOf (); 713 tree var = build_local_temp (make_array_type (targselem, ndims)); 714 715 /* Loop through each concatenation from right to left. */ 716 vec<constructor_elt, va_gc> *elms = NULL; 717 CatExp *ce = e; 718 int dim = ndims - 1; 719 720 for (Expression *oe = ce->e2; oe != NULL; 721 (ce->e1->op != TOKcat 722 ? (oe = ce->e1) 723 : (ce = (CatExp *)ce->e1, oe = ce->e2))) 724 { 725 tree arg = d_array_convert (etype, oe); 726 tree index = size_int (dim); 727 CONSTRUCTOR_APPEND_ELT (elms, index, d_save_expr (arg)); 728 729 /* Finished pushing all arrays. */ 730 if (oe == ce->e1) 731 break; 732 733 dim -= 1; 734 } 735 736 /* Check there is no logic bug in constructing byte[][] of arrays. */ 737 gcc_assert (dim == 0); 738 tree init = build_constructor (TREE_TYPE (var), elms); 739 var = compound_expr (modify_expr (var, init), var); 740 741 tree arrs = d_array_value (build_ctype (targselem->arrayOf ()), 742 size_int (ndims), build_address (var)); 743 744 result = build_libcall (LIBCALL_ARRAYCATNTX, e->type, 2, 745 build_typeinfo (e->loc, e->type), arrs); 746 } 747 else 748 { 749 /* Handle single concatenation (a ~ b). */ 750 result = build_libcall (LIBCALL_ARRAYCATT, e->type, 3, 751 build_typeinfo (e->loc, e->type), 752 d_array_convert (etype, e->e1), 753 d_array_convert (etype, e->e2)); 754 } 755 756 this->result_ = result; 757 } 758 759 /* Build an assignment operator expression. The right operand is implicitly 760 converted to the type of the left operand, and assigned to it. */ 761 762 void visit (BinAssignExp *e) 763 { 764 tree_code code; 765 Expression *e1b = e->e1; 766 767 switch (e->op) 768 { 769 case TOKaddass: 770 code = PLUS_EXPR; 771 break; 772 773 case TOKminass: 774 code = MINUS_EXPR; 775 break; 776 777 case TOKmulass: 778 code = MULT_EXPR; 779 break; 780 781 case TOKdivass: 782 code = e->e1->type->isintegral () 783 ? TRUNC_DIV_EXPR : RDIV_EXPR; 784 break; 785 786 case TOKmodass: 787 code = e->e1->type->isfloating () 788 ? FLOAT_MOD_EXPR : TRUNC_MOD_EXPR; 789 break; 790 791 case TOKandass: 792 code = BIT_AND_EXPR; 793 break; 794 795 case TOKorass: 796 code = BIT_IOR_EXPR; 797 break; 798 799 case TOKxorass: 800 code = BIT_XOR_EXPR; 801 break; 802 803 case TOKpowass: 804 gcc_unreachable (); 805 806 case TOKshlass: 807 code = LSHIFT_EXPR; 808 break; 809 810 case TOKshrass: 811 case TOKushrass: 812 /* Use the original lhs type before it was promoted. The left operand 813 of `>>>=' does not undergo integral promotions before shifting. 814 Strip off casts just incase anyway. */ 815 while (e1b->op == TOKcast) 816 { 817 CastExp *ce = (CastExp *) e1b; 818 gcc_assert (same_type_p (ce->type, ce->to)); 819 e1b = ce->e1; 820 } 821 code = (e->op == TOKshrass) ? RSHIFT_EXPR : UNSIGNED_RSHIFT_EXPR; 822 break; 823 824 default: 825 gcc_unreachable (); 826 } 827 828 tree exp = this->binop_assignment (code, e1b, e->e2); 829 this->result_ = convert_expr (exp, e1b->type, e->type); 830 } 831 832 /* Build a concat assignment expression. The right operand is appended 833 to the left operand. */ 834 835 void visit (CatAssignExp *e) 836 { 837 Type *tb1 = e->e1->type->toBasetype (); 838 Type *tb2 = e->e2->type->toBasetype (); 839 Type *etype = tb1->nextOf ()->toBasetype (); 840 841 /* Save the address of `e1', so it can be evaluated first. 842 As all D run-time library functions for concat assignments update `e1' 843 in-place and then return its value, the saved address can also be used as 844 the result of this expression as well. */ 845 tree lhs = build_expr (e->e1); 846 tree lexpr = stabilize_expr (&lhs); 847 tree ptr = d_save_expr (build_address (lhs)); 848 tree result = NULL_TREE; 849 850 if (tb1->ty == Tarray && tb2->ty == Tdchar 851 && (etype->ty == Tchar || etype->ty == Twchar)) 852 { 853 /* Append a dchar to a char[] or wchar[]: 854 The assignment is handled by the D run-time library, so only 855 need to call `_d_arrayappend[cw]d(&e1, e2)' */ 856 libcall_fn libcall = (etype->ty == Tchar) 857 ? LIBCALL_ARRAYAPPENDCD : LIBCALL_ARRAYAPPENDWD; 858 859 result = build_libcall (libcall, e->type, 2, 860 ptr, build_expr (e->e2)); 861 } 862 else 863 { 864 gcc_assert (tb1->ty == Tarray || tb2->ty == Tsarray); 865 866 if ((tb2->ty == Tarray || tb2->ty == Tsarray) 867 && same_type_p (etype, tb2->nextOf ()->toBasetype ())) 868 { 869 /* Append an array to another array: 870 The assignment is handled by the D run-time library, so only 871 need to call `_d_arrayappendT(ti, &e1, e2)' */ 872 result = build_libcall (LIBCALL_ARRAYAPPENDT, e->type, 3, 873 build_typeinfo (e->loc, e->type), 874 ptr, d_array_convert (e->e2)); 875 } 876 else if (same_type_p (etype, tb2)) 877 { 878 /* Append an element to an array: 879 The assignment is generated inline, so need to handle temporaries 880 here, and ensure that they are evaluated in the correct order. 881 882 The generated code should end up being equivalent to: 883 _d_arrayappendcTX(ti, &e1, 1)[e1.length - 1] = e2 884 */ 885 tree callexp = build_libcall (LIBCALL_ARRAYAPPENDCTX, e->type, 3, 886 build_typeinfo (e->loc, e->type), 887 ptr, size_one_node); 888 callexp = d_save_expr (callexp); 889 890 /* Assign e2 to last element. */ 891 tree offexp = d_array_length (callexp); 892 offexp = build2 (MINUS_EXPR, TREE_TYPE (offexp), 893 offexp, size_one_node); 894 895 tree ptrexp = d_array_ptr (callexp); 896 ptrexp = void_okay_p (ptrexp); 897 ptrexp = build_array_index (ptrexp, offexp); 898 899 /* Evaluate expression before appending. */ 900 tree rhs = build_expr (e->e2); 901 tree rexpr = stabilize_expr (&rhs); 902 903 if (TREE_CODE (rhs) == CALL_EXPR) 904 rhs = force_target_expr (rhs); 905 906 result = modify_expr (build_deref (ptrexp), rhs); 907 result = compound_expr (rexpr, result); 908 } 909 else 910 gcc_unreachable (); 911 } 912 913 /* Construct in order: ptr = &e1, _d_arrayappend(ptr, e2), *ptr; */ 914 result = compound_expr (compound_expr (lexpr, ptr), result); 915 this->result_ = compound_expr (result, build_deref (ptr)); 916 } 917 918 /* Build an assignment expression. The right operand is implicitly 919 converted to the type of the left operand, and assigned to it. */ 920 921 void visit (AssignExp *e) 922 { 923 /* First, handle special assignment semantics. */ 924 925 /* Look for array.length = n; */ 926 if (e->e1->op == TOKarraylength) 927 { 928 /* Assignment to an array's length property; resize the array. */ 929 ArrayLengthExp *ale = (ArrayLengthExp *) e->e1; 930 tree newlength = convert_expr (build_expr (e->e2), e->e2->type, 931 Type::tsize_t); 932 tree ptr = build_address (build_expr (ale->e1)); 933 934 /* Don't want the basetype for the element type. */ 935 Type *etype = ale->e1->type->toBasetype ()->nextOf (); 936 libcall_fn libcall = etype->isZeroInit () 937 ? LIBCALL_ARRAYSETLENGTHT : LIBCALL_ARRAYSETLENGTHIT; 938 939 tree result = build_libcall (libcall, ale->e1->type, 3, 940 build_typeinfo (ale->loc, ale->e1->type), 941 newlength, ptr); 942 943 this->result_ = d_array_length (result); 944 return; 945 } 946 947 /* Look for array[] = n; */ 948 if (e->e1->op == TOKslice) 949 { 950 SliceExp *se = (SliceExp *) e->e1; 951 Type *stype = se->e1->type->toBasetype (); 952 Type *etype = stype->nextOf ()->toBasetype (); 953 954 /* Determine if we need to run postblit or dtor. */ 955 bool postblit = this->needs_postblit (etype) && this->lvalue_p (e->e2); 956 bool destructor = this->needs_dtor (etype); 957 958 if (e->memset & blockAssign) 959 { 960 /* Set a range of elements to one value. */ 961 tree t1 = d_save_expr (build_expr (e->e1)); 962 tree t2 = build_expr (e->e2); 963 tree result; 964 965 if ((postblit || destructor) && e->op != TOKblit) 966 { 967 libcall_fn libcall = (e->op == TOKconstruct) 968 ? LIBCALL_ARRAYSETCTOR : LIBCALL_ARRAYSETASSIGN; 969 /* So we can call postblits on const/immutable objects. */ 970 Type *tm = etype->unSharedOf ()->mutableOf (); 971 tree ti = build_typeinfo (e->loc, tm); 972 973 tree result = build_libcall (libcall, Type::tvoid, 4, 974 d_array_ptr (t1), 975 build_address (t2), 976 d_array_length (t1), ti); 977 this->result_ = compound_expr (result, t1); 978 return; 979 } 980 981 if (integer_zerop (t2)) 982 { 983 tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET); 984 tree size = size_mult_expr (d_array_length (t1), 985 size_int (etype->size ())); 986 987 result = build_call_expr (tmemset, 3, d_array_ptr (t1), 988 integer_zero_node, size); 989 } 990 else 991 result = build_array_set (d_array_ptr (t1), 992 d_array_length (t1), t2); 993 994 this->result_ = compound_expr (result, t1); 995 } 996 else 997 { 998 /* Perform a memcpy operation. */ 999 gcc_assert (e->e2->type->ty != Tpointer); 1000 1001 if (!postblit && !destructor && !array_bounds_check ()) 1002 { 1003 tree t1 = d_save_expr (d_array_convert (e->e1)); 1004 tree t2 = d_array_convert (e->e2); 1005 tree tmemcpy = builtin_decl_explicit (BUILT_IN_MEMCPY); 1006 tree size = size_mult_expr (d_array_length (t1), 1007 size_int (etype->size ())); 1008 1009 tree result = build_call_expr (tmemcpy, 3, d_array_ptr (t1), 1010 d_array_ptr (t2), size); 1011 this->result_ = compound_expr (result, t1); 1012 } 1013 else if ((postblit || destructor) && e->op != TOKblit) 1014 { 1015 /* Generate: _d_arrayassign(ti, from, to) 1016 or: _d_arrayctor(ti, from, to) */ 1017 libcall_fn libcall = (e->op == TOKconstruct) 1018 ? LIBCALL_ARRAYCTOR : LIBCALL_ARRAYASSIGN; 1019 1020 this->result_ = build_libcall (libcall, e->type, 3, 1021 build_typeinfo (e->loc, etype), 1022 d_array_convert (e->e2), 1023 d_array_convert (e->e1)); 1024 } 1025 else 1026 { 1027 /* Generate: _d_arraycopy() */ 1028 this->result_ = build_libcall (LIBCALL_ARRAYCOPY, e->type, 3, 1029 size_int (etype->size ()), 1030 d_array_convert (e->e2), 1031 d_array_convert (e->e1)); 1032 } 1033 } 1034 1035 return; 1036 } 1037 1038 /* Look for reference initializations. */ 1039 if (e->memset & referenceInit) 1040 { 1041 gcc_assert (e->op == TOKconstruct || e->op == TOKblit); 1042 gcc_assert (e->e1->op == TOKvar); 1043 1044 Declaration *decl = ((VarExp *) e->e1)->var; 1045 if (decl->storage_class & (STCout | STCref)) 1046 { 1047 tree t2 = convert_for_assignment (build_expr (e->e2), 1048 e->e2->type, e->e1->type); 1049 tree t1 = build_expr (e->e1); 1050 /* Want reference to lhs, not indirect ref. */ 1051 t1 = TREE_OPERAND (t1, 0); 1052 t2 = build_address (t2); 1053 1054 this->result_ = indirect_ref (build_ctype (e->type), 1055 build_assign (INIT_EXPR, t1, t2)); 1056 return; 1057 } 1058 } 1059 1060 /* Other types of assignments that may require post construction. */ 1061 Type *tb1 = e->e1->type->toBasetype (); 1062 tree_code modifycode = (e->op == TOKconstruct) ? INIT_EXPR : MODIFY_EXPR; 1063 1064 /* Look for struct assignment. */ 1065 if (tb1->ty == Tstruct) 1066 { 1067 tree t1 = build_expr (e->e1); 1068 tree t2 = convert_for_assignment (build_expr (e->e2), 1069 e->e2->type, e->e1->type); 1070 StructDeclaration *sd = ((TypeStruct *) tb1)->sym; 1071 1072 /* Look for struct = 0. */ 1073 if (e->e2->op == TOKint64) 1074 { 1075 /* Use memset to fill struct. */ 1076 gcc_assert (e->op == TOKblit); 1077 tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET); 1078 tree result = build_call_expr (tmemset, 3, build_address (t1), 1079 t2, size_int (sd->structsize)); 1080 1081 /* Maybe set-up hidden pointer to outer scope context. */ 1082 if (sd->isNested ()) 1083 { 1084 tree field = get_symbol_decl (sd->vthis); 1085 tree value = build_vthis (sd); 1086 1087 tree vthis_exp = modify_expr (component_ref (t1, field), value); 1088 result = compound_expr (result, vthis_exp); 1089 } 1090 1091 this->result_ = compound_expr (result, t1); 1092 } 1093 else 1094 { 1095 /* Simple struct literal assignment. */ 1096 tree init = NULL_TREE; 1097 1098 /* Fill any alignment holes in the struct using memset. */ 1099 if (e->op == TOKconstruct && !identity_compare_p (sd)) 1100 { 1101 tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET); 1102 init = build_call_expr (tmemset, 3, build_address (t1), 1103 integer_zero_node, 1104 size_int (sd->structsize)); 1105 } 1106 1107 tree result = build_assign (modifycode, t1, t2); 1108 this->result_ = compound_expr (init, result); 1109 } 1110 1111 return; 1112 } 1113 1114 /* Look for static array assignment. */ 1115 if (tb1->ty == Tsarray) 1116 { 1117 /* Look for array = 0. */ 1118 if (e->e2->op == TOKint64) 1119 { 1120 /* Use memset to fill the array. */ 1121 gcc_assert (e->op == TOKblit); 1122 1123 tree t1 = build_expr (e->e1); 1124 tree t2 = convert_for_assignment (build_expr (e->e2), 1125 e->e2->type, e->e1->type); 1126 tree size = size_int (e->e1->type->size ()); 1127 1128 tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET); 1129 this->result_ = build_call_expr (tmemset, 3, build_address (t1), 1130 t2, size); 1131 return; 1132 } 1133 1134 Type *etype = tb1->nextOf (); 1135 gcc_assert (e->e2->type->toBasetype ()->ty == Tsarray); 1136 1137 /* Determine if we need to run postblit. */ 1138 bool postblit = this->needs_postblit (etype); 1139 bool destructor = this->needs_dtor (etype); 1140 bool lvalue_p = this->lvalue_p (e->e2); 1141 1142 /* Even if the elements in rhs are all rvalues and don't have 1143 to call postblits, this assignment should call dtors on old 1144 assigned elements. */ 1145 if ((!postblit && !destructor) 1146 || (e->op == TOKconstruct && !lvalue_p && postblit) 1147 || (e->op == TOKblit || e->e1->type->size () == 0)) 1148 { 1149 tree t1 = build_expr (e->e1); 1150 tree t2 = convert_for_assignment (build_expr (e->e2), 1151 e->e2->type, e->e1->type); 1152 1153 this->result_ = build_assign (modifycode, t1, t2); 1154 return; 1155 } 1156 1157 Type *arrtype = (e->type->ty == Tsarray) ? etype->arrayOf () : e->type; 1158 tree result; 1159 1160 if (e->op == TOKconstruct) 1161 { 1162 /* Generate: _d_arrayctor(ti, from, to) */ 1163 result = build_libcall (LIBCALL_ARRAYCTOR, arrtype, 3, 1164 build_typeinfo (e->loc, etype), 1165 d_array_convert (e->e2), 1166 d_array_convert (e->e1)); 1167 } 1168 else 1169 { 1170 /* Generate: _d_arrayassign_l() 1171 or: _d_arrayassign_r() */ 1172 libcall_fn libcall = (lvalue_p) 1173 ? LIBCALL_ARRAYASSIGN_L : LIBCALL_ARRAYASSIGN_R; 1174 tree elembuf = build_local_temp (build_ctype (etype)); 1175 1176 result = build_libcall (libcall, arrtype, 4, 1177 build_typeinfo (e->loc, etype), 1178 d_array_convert (e->e2), 1179 d_array_convert (e->e1), 1180 build_address (elembuf)); 1181 } 1182 1183 /* Cast the libcall result back to a static array. */ 1184 if (e->type->ty == Tsarray) 1185 result = indirect_ref (build_ctype (e->type), 1186 d_array_ptr (result)); 1187 1188 this->result_ = result; 1189 return; 1190 } 1191 1192 /* Simple assignment. */ 1193 tree t1 = build_expr (e->e1); 1194 tree t2 = convert_for_assignment (build_expr (e->e2), 1195 e->e2->type, e->e1->type); 1196 1197 this->result_ = build_assign (modifycode, t1, t2); 1198 } 1199 1200 /* Build a postfix expression. */ 1201 1202 void visit (PostExp *e) 1203 { 1204 tree result; 1205 1206 if (e->op == TOKplusplus) 1207 { 1208 result = build2 (POSTINCREMENT_EXPR, build_ctype (e->type), 1209 build_expr (e->e1), build_expr (e->e2)); 1210 } 1211 else if (e->op == TOKminusminus) 1212 { 1213 result = build2 (POSTDECREMENT_EXPR, build_ctype (e->type), 1214 build_expr (e->e1), build_expr (e->e2)); 1215 } 1216 else 1217 gcc_unreachable (); 1218 1219 TREE_SIDE_EFFECTS (result) = 1; 1220 this->result_ = result; 1221 } 1222 1223 /* Build an index expression. */ 1224 1225 void visit (IndexExp *e) 1226 { 1227 Type *tb1 = e->e1->type->toBasetype (); 1228 1229 if (tb1->ty == Taarray) 1230 { 1231 /* Get the key for the associative array. */ 1232 Type *tkey = ((TypeAArray *) tb1)->index->toBasetype (); 1233 tree key = convert_expr (build_expr (e->e2), e->e2->type, tkey); 1234 libcall_fn libcall; 1235 tree tinfo, ptr; 1236 1237 if (e->modifiable) 1238 { 1239 libcall = LIBCALL_AAGETY; 1240 ptr = build_address (build_expr (e->e1)); 1241 tinfo = build_typeinfo (e->loc, tb1->unSharedOf ()->mutableOf ()); 1242 } 1243 else 1244 { 1245 libcall = LIBCALL_AAGETRVALUEX; 1246 ptr = build_expr (e->e1); 1247 tinfo = build_typeinfo (e->loc, tkey); 1248 } 1249 1250 /* Index the associative array. */ 1251 tree result = build_libcall (libcall, e->type->pointerTo (), 4, 1252 ptr, tinfo, 1253 size_int (tb1->nextOf ()->size ()), 1254 build_address (key)); 1255 1256 if (!e->indexIsInBounds && array_bounds_check ()) 1257 { 1258 tree tassert = (global.params.checkAction == CHECKACTION_D) 1259 ? d_assert_call (e->loc, LIBCALL_ARRAY_BOUNDS) 1260 : build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0); 1261 1262 result = d_save_expr (result); 1263 result = build_condition (TREE_TYPE (result), 1264 d_truthvalue_conversion (result), 1265 result, tassert); 1266 } 1267 1268 this->result_ = indirect_ref (build_ctype (e->type), result); 1269 } 1270 else 1271 { 1272 /* Get the data pointer and length for static and dynamic arrays. */ 1273 tree array = d_save_expr (build_expr (e->e1)); 1274 tree ptr = convert_expr (array, tb1, tb1->nextOf ()->pointerTo ()); 1275 1276 tree length = NULL_TREE; 1277 if (tb1->ty != Tpointer) 1278 length = get_array_length (array, tb1); 1279 else 1280 gcc_assert (e->lengthVar == NULL); 1281 1282 /* The __dollar variable just becomes a placeholder for the 1283 actual length. */ 1284 if (e->lengthVar) 1285 e->lengthVar->csym = length; 1286 1287 /* Generate the index. */ 1288 tree index = build_expr (e->e2); 1289 1290 /* If it's a static array and the index is constant, the front end has 1291 already checked the bounds. */ 1292 if (tb1->ty != Tpointer && !e->indexIsInBounds) 1293 index = build_bounds_condition (e->e2->loc, index, length, false); 1294 1295 /* Index the .ptr. */ 1296 ptr = void_okay_p (ptr); 1297 this->result_ = indirect_ref (TREE_TYPE (TREE_TYPE (ptr)), 1298 build_array_index (ptr, index)); 1299 } 1300 } 1301 1302 /* Build a comma expression. The type is the type of the right operand. */ 1303 1304 void visit (CommaExp *e) 1305 { 1306 tree t1 = build_expr (e->e1); 1307 tree t2 = build_expr (e->e2); 1308 tree type = e->type ? build_ctype (e->type) : void_type_node; 1309 1310 this->result_ = build2 (COMPOUND_EXPR, type, t1, t2); 1311 } 1312 1313 /* Build an array length expression. Returns the number of elements 1314 in the array. The result is of type size_t. */ 1315 1316 void visit (ArrayLengthExp *e) 1317 { 1318 if (e->e1->type->toBasetype ()->ty == Tarray) 1319 this->result_ = d_array_length (build_expr (e->e1)); 1320 else 1321 { 1322 /* Static arrays have already been handled by the front-end. */ 1323 error ("unexpected type for array length: %qs", e->type->toChars ()); 1324 this->result_ = error_mark_node; 1325 } 1326 } 1327 1328 /* Build a delegate pointer expression. This will return the frame 1329 pointer value as a type void*. */ 1330 1331 void visit (DelegatePtrExp *e) 1332 { 1333 tree t1 = build_expr (e->e1); 1334 this->result_ = delegate_object (t1); 1335 } 1336 1337 /* Build a delegate function pointer expression. This will return the 1338 function pointer value as a function type. */ 1339 1340 void visit (DelegateFuncptrExp *e) 1341 { 1342 tree t1 = build_expr (e->e1); 1343 this->result_ = delegate_method (t1); 1344 } 1345 1346 /* Build a slice expression. */ 1347 1348 void visit (SliceExp *e) 1349 { 1350 Type *tb = e->type->toBasetype (); 1351 Type *tb1 = e->e1->type->toBasetype (); 1352 gcc_assert (tb->ty == Tarray || tb->ty == Tsarray); 1353 1354 /* Use convert-to-dynamic-array code if possible. */ 1355 if (!e->lwr) 1356 { 1357 tree result = build_expr (e->e1); 1358 if (e->e1->type->toBasetype ()->ty == Tsarray) 1359 result = convert_expr (result, e->e1->type, e->type); 1360 1361 this->result_ = result; 1362 return; 1363 } 1364 else 1365 gcc_assert (e->upr != NULL); 1366 1367 /* Get the data pointer and length for static and dynamic arrays. */ 1368 tree array = d_save_expr (build_expr (e->e1)); 1369 tree ptr = convert_expr (array, tb1, tb1->nextOf ()->pointerTo ()); 1370 tree length = NULL_TREE; 1371 1372 /* Our array is already a SAVE_EXPR if necessary, so we don't make length 1373 a SAVE_EXPR which is, at most, a COMPONENT_REF on top of array. */ 1374 if (tb1->ty != Tpointer) 1375 length = get_array_length (array, tb1); 1376 else 1377 gcc_assert (e->lengthVar == NULL); 1378 1379 /* The __dollar variable just becomes a placeholder for the 1380 actual length. */ 1381 if (e->lengthVar) 1382 e->lengthVar->csym = length; 1383 1384 /* Generate upper and lower bounds. */ 1385 tree lwr_tree = d_save_expr (build_expr (e->lwr)); 1386 tree upr_tree = d_save_expr (build_expr (e->upr)); 1387 1388 /* If the upper bound has any side effects, then the lower bound should be 1389 copied to a temporary always. */ 1390 if (TREE_CODE (upr_tree) == SAVE_EXPR && TREE_CODE (lwr_tree) != SAVE_EXPR) 1391 lwr_tree = save_expr (lwr_tree); 1392 1393 /* Adjust the .ptr offset. */ 1394 if (!integer_zerop (lwr_tree)) 1395 { 1396 tree ptrtype = TREE_TYPE (ptr); 1397 ptr = build_array_index (void_okay_p (ptr), lwr_tree); 1398 ptr = build_nop (ptrtype, ptr); 1399 } 1400 else 1401 lwr_tree = NULL_TREE; 1402 1403 /* Nothing more to do for static arrays, their bounds checking has been 1404 done at compile-time. */ 1405 if (tb->ty == Tsarray) 1406 { 1407 this->result_ = indirect_ref (build_ctype (e->type), ptr); 1408 return; 1409 } 1410 else 1411 gcc_assert (tb->ty == Tarray); 1412 1413 /* Generate bounds checking code. */ 1414 tree newlength; 1415 1416 if (!e->upperIsInBounds) 1417 { 1418 if (length) 1419 { 1420 newlength = build_bounds_condition (e->upr->loc, upr_tree, 1421 length, true); 1422 } 1423 else 1424 { 1425 /* Still need to check bounds lwr <= upr for pointers. */ 1426 gcc_assert (tb1->ty == Tpointer); 1427 newlength = upr_tree; 1428 } 1429 } 1430 else 1431 newlength = upr_tree; 1432 1433 if (lwr_tree) 1434 { 1435 /* Enforces lwr <= upr. No need to check lwr <= length as 1436 we've already ensured that upr <= length. */ 1437 if (!e->lowerIsLessThanUpper) 1438 { 1439 tree cond = build_bounds_condition (e->lwr->loc, lwr_tree, 1440 upr_tree, true); 1441 1442 /* When bounds checking is off, the index value is 1443 returned directly. */ 1444 if (cond != lwr_tree) 1445 newlength = compound_expr (cond, newlength); 1446 } 1447 1448 /* Need to ensure lwr always gets evaluated first, as it may be a 1449 function call. Generates (lwr, upr) - lwr. */ 1450 newlength = fold_build2 (MINUS_EXPR, TREE_TYPE (newlength), 1451 compound_expr (lwr_tree, newlength), lwr_tree); 1452 } 1453 1454 tree result = d_array_value (build_ctype (e->type), newlength, ptr); 1455 this->result_ = compound_expr (array, result); 1456 } 1457 1458 /* Build a cast expression, which converts the given unary expression to the 1459 type of result. */ 1460 1461 void visit (CastExp *e) 1462 { 1463 Type *ebtype = e->e1->type->toBasetype (); 1464 Type *tbtype = e->to->toBasetype (); 1465 tree result = build_expr (e->e1, this->constp_); 1466 1467 /* Just evaluate e1 if it has any side effects. */ 1468 if (tbtype->ty == Tvoid) 1469 this->result_ = build_nop (build_ctype (tbtype), result); 1470 else 1471 this->result_ = convert_for_rvalue (result, ebtype, tbtype); 1472 } 1473 1474 /* Build a delete expression. */ 1475 1476 void visit (DeleteExp *e) 1477 { 1478 tree t1 = build_expr (e->e1); 1479 Type *tb1 = e->e1->type->toBasetype (); 1480 1481 if (tb1->ty == Tclass) 1482 { 1483 /* For class object references, if there is a destructor for that class, 1484 the destructor is called for the object instance. */ 1485 libcall_fn libcall; 1486 1487 if (e->e1->op == TOKvar) 1488 { 1489 VarDeclaration *v = ((VarExp *) e->e1)->var->isVarDeclaration (); 1490 if (v && v->onstack) 1491 { 1492 libcall = tb1->isClassHandle ()->isInterfaceDeclaration () 1493 ? LIBCALL_CALLINTERFACEFINALIZER : LIBCALL_CALLFINALIZER; 1494 1495 this->result_ = build_libcall (libcall, Type::tvoid, 1, t1); 1496 return; 1497 } 1498 } 1499 1500 /* Otherwise, the garbage collector is called to immediately free the 1501 memory allocated for the class instance. */ 1502 libcall = tb1->isClassHandle ()->isInterfaceDeclaration () 1503 ? LIBCALL_DELINTERFACE : LIBCALL_DELCLASS; 1504 1505 t1 = build_address (t1); 1506 this->result_ = build_libcall (libcall, Type::tvoid, 1, t1); 1507 } 1508 else if (tb1->ty == Tarray) 1509 { 1510 /* For dynamic arrays, the garbage collector is called to immediately 1511 release the memory. */ 1512 Type *telem = tb1->nextOf ()->baseElemOf (); 1513 tree ti = null_pointer_node; 1514 1515 if (telem->ty == Tstruct) 1516 { 1517 /* Might need to run destructor on array contents. */ 1518 TypeStruct *ts = (TypeStruct *) telem; 1519 if (ts->sym->dtor) 1520 ti = build_typeinfo (e->loc, tb1->nextOf ()); 1521 } 1522 1523 /* Generate: _delarray_t (&t1, ti); */ 1524 this->result_ = build_libcall (LIBCALL_DELARRAYT, Type::tvoid, 2, 1525 build_address (t1), ti); 1526 } 1527 else if (tb1->ty == Tpointer) 1528 { 1529 /* For pointers to a struct instance, if the struct has overloaded 1530 operator delete, then that operator is called. */ 1531 t1 = build_address (t1); 1532 Type *tnext = ((TypePointer *)tb1)->next->toBasetype (); 1533 1534 if (tnext->ty == Tstruct) 1535 { 1536 TypeStruct *ts = (TypeStruct *)tnext; 1537 if (ts->sym->dtor) 1538 { 1539 tree ti = build_typeinfo (e->loc, tnext); 1540 this->result_ = build_libcall (LIBCALL_DELSTRUCT, Type::tvoid, 1541 2, t1, ti); 1542 return; 1543 } 1544 } 1545 1546 /* Otherwise, the garbage collector is called to immediately free the 1547 memory allocated for the pointer. */ 1548 this->result_ = build_libcall (LIBCALL_DELMEMORY, Type::tvoid, 1, t1); 1549 } 1550 else 1551 { 1552 error ("don%'t know how to delete %qs", e->e1->toChars ()); 1553 this->result_ = error_mark_node; 1554 } 1555 } 1556 1557 /* Build a remove expression, which removes a particular key from an 1558 associative array. */ 1559 1560 void visit (RemoveExp *e) 1561 { 1562 /* Check that the array is actually an associative array. */ 1563 if (e->e1->type->toBasetype ()->ty == Taarray) 1564 { 1565 Type *tb = e->e1->type->toBasetype (); 1566 Type *tkey = ((TypeAArray *) tb)->index->toBasetype (); 1567 tree index = convert_expr (build_expr (e->e2), e->e2->type, tkey); 1568 1569 this->result_ = build_libcall (LIBCALL_AADELX, Type::tbool, 3, 1570 build_expr (e->e1), 1571 build_typeinfo (e->loc, tkey), 1572 build_address (index)); 1573 } 1574 else 1575 { 1576 error ("%qs is not an associative array", e->e1->toChars ()); 1577 this->result_ = error_mark_node; 1578 } 1579 } 1580 1581 /* Build an unary not expression. */ 1582 1583 void visit (NotExp *e) 1584 { 1585 tree result = convert_for_condition (build_expr (e->e1), e->e1->type); 1586 /* Need to convert to boolean type or this will fail. */ 1587 result = fold_build1 (TRUTH_NOT_EXPR, d_bool_type, result); 1588 1589 this->result_ = d_convert (build_ctype (e->type), result); 1590 } 1591 1592 /* Build a compliment expression, where all the bits in the value are 1593 complemented. Note: unlike in C, the usual integral promotions 1594 are not performed prior to the complement operation. */ 1595 1596 void visit (ComExp *e) 1597 { 1598 TY ty1 = e->e1->type->toBasetype ()->ty; 1599 gcc_assert (ty1 != Tarray && ty1 != Tsarray); 1600 1601 this->result_ = fold_build1 (BIT_NOT_EXPR, build_ctype (e->type), 1602 build_expr (e->e1)); 1603 } 1604 1605 /* Build an unary negation expression. */ 1606 1607 void visit (NegExp *e) 1608 { 1609 TY ty1 = e->e1->type->toBasetype ()->ty; 1610 gcc_assert (ty1 != Tarray && ty1 != Tsarray); 1611 1612 tree type = build_ctype (e->type); 1613 tree expr = build_expr (e->e1); 1614 1615 /* If the operation needs excess precision. */ 1616 tree eptype = excess_precision_type (type); 1617 if (eptype != NULL_TREE) 1618 expr = d_convert (eptype, expr); 1619 else 1620 eptype = type; 1621 1622 tree ret = fold_build1 (NEGATE_EXPR, eptype, expr); 1623 this->result_ = d_convert (type, ret); 1624 } 1625 1626 /* Build a pointer index expression. */ 1627 1628 void visit (PtrExp *e) 1629 { 1630 Type *tnext = NULL; 1631 size_t offset; 1632 tree result; 1633 1634 if (e->e1->op == TOKadd) 1635 { 1636 BinExp *be = (BinExp *) e->e1; 1637 if (be->e1->op == TOKaddress 1638 && be->e2->isConst () && be->e2->type->isintegral ()) 1639 { 1640 Expression *ae = ((AddrExp *) be->e1)->e1; 1641 tnext = ae->type->toBasetype (); 1642 result = build_expr (ae); 1643 offset = be->e2->toUInteger (); 1644 } 1645 } 1646 else if (e->e1->op == TOKsymoff) 1647 { 1648 SymOffExp *se = (SymOffExp *) e->e1; 1649 if (!declaration_reference_p (se->var)) 1650 { 1651 tnext = se->var->type->toBasetype (); 1652 result = get_decl_tree (se->var); 1653 offset = se->offset; 1654 } 1655 } 1656 1657 /* Produce better code by converting *(#record + n) to 1658 COMPONENT_REFERENCE. Otherwise, the variable will always be 1659 allocated in memory because its address is taken. */ 1660 if (tnext && tnext->ty == Tstruct) 1661 { 1662 StructDeclaration *sd = ((TypeStruct *) tnext)->sym; 1663 1664 for (size_t i = 0; i < sd->fields.dim; i++) 1665 { 1666 VarDeclaration *field = sd->fields[i]; 1667 1668 if (field->offset == offset 1669 && same_type_p (field->type, e->type)) 1670 { 1671 /* Catch errors, backend will ICE otherwise. */ 1672 if (error_operand_p (result)) 1673 this->result_ = result; 1674 else 1675 { 1676 result = component_ref (result, get_symbol_decl (field)); 1677 this->result_ = result; 1678 } 1679 return; 1680 } 1681 else if (field->offset > offset) 1682 break; 1683 } 1684 } 1685 1686 this->result_ = indirect_ref (build_ctype (e->type), build_expr (e->e1)); 1687 } 1688 1689 /* Build an unary address expression. */ 1690 1691 void visit (AddrExp *e) 1692 { 1693 tree type = build_ctype (e->type); 1694 tree exp; 1695 1696 /* The frontend optimizer can convert const symbol into a struct literal. 1697 Taking the address of a struct literal is otherwise illegal. */ 1698 if (e->e1->op == TOKstructliteral) 1699 { 1700 StructLiteralExp *sle = ((StructLiteralExp *) e->e1)->origin; 1701 gcc_assert (sle != NULL); 1702 1703 /* Build the reference symbol, the decl is built first as the 1704 initializer may have recursive references. */ 1705 if (!sle->sym) 1706 { 1707 sle->sym = build_artificial_decl (build_ctype (sle->type), 1708 NULL_TREE, "S"); 1709 DECL_INITIAL (sle->sym) = build_expr (sle, true); 1710 d_pushdecl (sle->sym); 1711 rest_of_decl_compilation (sle->sym, 1, 0); 1712 } 1713 1714 exp = sle->sym; 1715 } 1716 else 1717 exp = build_expr (e->e1, this->constp_); 1718 1719 TREE_CONSTANT (exp) = 0; 1720 this->result_ = d_convert (type, build_address (exp)); 1721 } 1722 1723 /* Build a function call expression. */ 1724 1725 void visit (CallExp *e) 1726 { 1727 Type *tb = e->e1->type->toBasetype (); 1728 Expression *e1b = e->e1; 1729 1730 tree callee = NULL_TREE; 1731 tree object = NULL_TREE; 1732 tree cleanup = NULL_TREE; 1733 TypeFunction *tf = NULL; 1734 1735 /* Calls to delegates can sometimes look like this. */ 1736 if (e1b->op == TOKcomma) 1737 { 1738 e1b = ((CommaExp *) e1b)->e2; 1739 gcc_assert (e1b->op == TOKvar); 1740 1741 Declaration *var = ((VarExp *) e1b)->var; 1742 gcc_assert (var->isFuncDeclaration () && !var->needThis ()); 1743 } 1744 1745 if (e1b->op == TOKdotvar && tb->ty != Tdelegate) 1746 { 1747 DotVarExp *dve = (DotVarExp *) e1b; 1748 1749 /* Don't modify the static initializer for struct literals. */ 1750 if (dve->e1->op == TOKstructliteral) 1751 { 1752 StructLiteralExp *sle = (StructLiteralExp *) dve->e1; 1753 sle->useStaticInit = false; 1754 } 1755 1756 FuncDeclaration *fd = dve->var->isFuncDeclaration (); 1757 if (fd != NULL) 1758 { 1759 /* Get the correct callee from the DotVarExp object. */ 1760 tree fndecl = get_symbol_decl (fd); 1761 AggregateDeclaration *ad = fd->isThis (); 1762 1763 /* Static method; ignore the object instance. */ 1764 if (!ad) 1765 callee = build_address (fndecl); 1766 else 1767 { 1768 tree thisexp = build_expr (dve->e1); 1769 1770 /* When constructing temporaries, if the constructor throws, 1771 then the object is destructed even though it is not a fully 1772 constructed object yet. And so this call will need to be 1773 moved inside the TARGET_EXPR_INITIAL slot. */ 1774 if (fd->isCtorDeclaration () 1775 && TREE_CODE (thisexp) == COMPOUND_EXPR 1776 && TREE_CODE (TREE_OPERAND (thisexp, 0)) == TARGET_EXPR 1777 && TARGET_EXPR_CLEANUP (TREE_OPERAND (thisexp, 0))) 1778 { 1779 cleanup = TREE_OPERAND (thisexp, 0); 1780 thisexp = TREE_OPERAND (thisexp, 1); 1781 } 1782 1783 /* Want reference to 'this' object. */ 1784 if (!POINTER_TYPE_P (TREE_TYPE (thisexp))) 1785 thisexp = build_address (thisexp); 1786 1787 /* Make the callee a virtual call. */ 1788 if (fd->isVirtual () && !fd->isFinalFunc () && !e->directcall) 1789 { 1790 tree fntype = build_pointer_type (TREE_TYPE (fndecl)); 1791 tree thistype = build_ctype (ad->handleType ()); 1792 thisexp = build_nop (thistype, d_save_expr (thisexp)); 1793 fndecl = build_vindex_ref (thisexp, fntype, fd->vtblIndex); 1794 } 1795 else 1796 fndecl = build_address (fndecl); 1797 1798 callee = build_method_call (fndecl, thisexp, fd->type); 1799 } 1800 } 1801 } 1802 1803 if (callee == NULL_TREE) 1804 callee = build_expr (e1b); 1805 1806 if (METHOD_CALL_EXPR (callee)) 1807 { 1808 /* This could be a delegate expression (TY == Tdelegate), but not 1809 actually a delegate variable. */ 1810 if (e1b->op == TOKdotvar) 1811 { 1812 /* This gets the true function type, getting the function type 1813 from e1->type can sometimes be incorrect, such as when calling 1814 a 'ref' return function. */ 1815 tf = get_function_type (((DotVarExp *) e1b)->var->type); 1816 } 1817 else 1818 tf = get_function_type (tb); 1819 1820 extract_from_method_call (callee, callee, object); 1821 } 1822 else if (tb->ty == Tdelegate) 1823 { 1824 /* Delegate call, extract .object and .funcptr from var. */ 1825 callee = d_save_expr (callee); 1826 tf = get_function_type (tb); 1827 object = delegate_object (callee); 1828 callee = delegate_method (callee); 1829 } 1830 else if (e1b->op == TOKvar) 1831 { 1832 FuncDeclaration *fd = ((VarExp *) e1b)->var->isFuncDeclaration (); 1833 gcc_assert (fd != NULL); 1834 tf = get_function_type (fd->type); 1835 1836 if (fd->isNested ()) 1837 { 1838 /* Maybe re-evaluate symbol storage treating 'fd' as public. */ 1839 if (call_by_alias_p (d_function_chain->function, fd)) 1840 TREE_PUBLIC (callee) = 1; 1841 1842 object = get_frame_for_symbol (fd); 1843 } 1844 else if (fd->needThis ()) 1845 { 1846 error_at (make_location_t (e1b->loc), 1847 "need %<this%> to access member %qs", fd->toChars ()); 1848 /* Continue compiling... */ 1849 object = null_pointer_node; 1850 } 1851 } 1852 else 1853 { 1854 /* Normal direct function call. */ 1855 tf = get_function_type (tb); 1856 } 1857 1858 gcc_assert (tf != NULL); 1859 1860 /* Now we have the type, callee and maybe object reference, 1861 build the call expression. */ 1862 tree exp = d_build_call (tf, callee, object, e->arguments); 1863 1864 if (tf->isref) 1865 exp = build_deref (exp); 1866 1867 /* Some library calls are defined to return a generic type. 1868 this->type is the real type we want to return. */ 1869 if (e->type->isTypeBasic ()) 1870 exp = d_convert (build_ctype (e->type), exp); 1871 1872 /* If this call was found to be a constructor for a temporary with a 1873 cleanup, then move the call inside the TARGET_EXPR. */ 1874 if (cleanup != NULL_TREE) 1875 { 1876 tree init = TARGET_EXPR_INITIAL (cleanup); 1877 TARGET_EXPR_INITIAL (cleanup) = compound_expr (init, exp); 1878 exp = cleanup; 1879 } 1880 1881 this->result_ = exp; 1882 } 1883 1884 /* Build a delegate expression. */ 1885 1886 void visit (DelegateExp *e) 1887 { 1888 if (e->func->semanticRun == PASSsemantic3done) 1889 { 1890 /* Add the function as nested function if it belongs to this module. 1891 ie: it is a member of this module, or it is a template instance. */ 1892 Dsymbol *owner = e->func->toParent (); 1893 while (!owner->isTemplateInstance () && owner->toParent ()) 1894 owner = owner->toParent (); 1895 if (owner->isTemplateInstance () || owner == d_function_chain->module) 1896 build_decl_tree (e->func); 1897 } 1898 1899 tree fndecl; 1900 tree object; 1901 1902 if (e->func->isNested ()) 1903 { 1904 if (e->e1->op == TOKnull) 1905 object = build_expr (e->e1); 1906 else 1907 object = get_frame_for_symbol (e->func); 1908 1909 fndecl = build_address (get_symbol_decl (e->func)); 1910 } 1911 else 1912 { 1913 if (!e->func->isThis ()) 1914 { 1915 error ("delegates are only for non-static functions"); 1916 this->result_ = error_mark_node; 1917 return; 1918 } 1919 1920 object = build_expr (e->e1); 1921 1922 /* Want reference to `this' object. */ 1923 if (e->e1->type->ty != Tclass && e->e1->type->ty != Tpointer) 1924 object = build_address (object); 1925 1926 /* Object reference could be the outer `this' field of a class or 1927 closure of type `void*'. Cast it to the right type. */ 1928 if (e->e1->type->ty == Tclass) 1929 object = d_convert (build_ctype (e->e1->type), object); 1930 1931 fndecl = get_symbol_decl (e->func); 1932 1933 /* Get pointer to function out of the virtual table. */ 1934 if (e->func->isVirtual () && !e->func->isFinalFunc () 1935 && e->e1->op != TOKsuper && e->e1->op != TOKdottype) 1936 { 1937 tree fntype = build_pointer_type (TREE_TYPE (fndecl)); 1938 object = d_save_expr (object); 1939 fndecl = build_vindex_ref (object, fntype, e->func->vtblIndex); 1940 } 1941 else 1942 fndecl = build_address (fndecl); 1943 } 1944 1945 this->result_ = build_method_call (fndecl, object, e->type); 1946 } 1947 1948 /* Build a type component expression. */ 1949 1950 void visit (DotTypeExp *e) 1951 { 1952 /* Just a pass through to underlying expression. */ 1953 this->result_ = build_expr (e->e1); 1954 } 1955 1956 /* Build a component reference expression. */ 1957 1958 void visit (DotVarExp *e) 1959 { 1960 VarDeclaration *vd = e->var->isVarDeclaration (); 1961 1962 /* This could also be a function, but relying on that being taken 1963 care of by the visitor interface for CallExp. */ 1964 if (vd != NULL) 1965 { 1966 if (!vd->isField ()) 1967 this->result_ = get_decl_tree (vd); 1968 else 1969 { 1970 tree object = build_expr (e->e1); 1971 1972 if (e->e1->type->toBasetype ()->ty != Tstruct) 1973 object = build_deref (object); 1974 1975 this->result_ = component_ref (object, get_symbol_decl (vd)); 1976 } 1977 } 1978 else 1979 { 1980 error ("%qs is not a field, but a %qs", 1981 e->var->toChars (), e->var->kind ()); 1982 this->result_ = error_mark_node; 1983 } 1984 } 1985 1986 /* Build an assert expression, used to declare conditions that must hold at 1987 that a given point in the program. */ 1988 1989 void visit (AssertExp *e) 1990 { 1991 Type *tb1 = e->e1->type->toBasetype (); 1992 tree arg = build_expr (e->e1); 1993 tree tmsg = NULL_TREE; 1994 tree assert_pass = void_node; 1995 tree assert_fail; 1996 1997 if (global.params.useAssert 1998 && global.params.checkAction == CHECKACTION_D) 1999 { 2000 /* Generate: ((bool) e1 ? (void)0 : _d_assert (...)) 2001 or: (e1 != null ? e1._invariant() : _d_assert (...)) */ 2002 bool unittest_p = d_function_chain->function->isUnitTestDeclaration (); 2003 libcall_fn libcall; 2004 2005 if (e->msg) 2006 { 2007 tmsg = build_expr_dtor (e->msg); 2008 libcall = unittest_p ? LIBCALL_UNITTEST_MSG : LIBCALL_ASSERT_MSG; 2009 } 2010 else 2011 libcall = unittest_p ? LIBCALL_UNITTEST : LIBCALL_ASSERT; 2012 2013 /* Build a call to _d_assert(). */ 2014 assert_fail = d_assert_call (e->loc, libcall, tmsg); 2015 2016 if (global.params.useInvariants) 2017 { 2018 /* If the condition is a D class or struct object with an invariant, 2019 call it if the condition result is true. */ 2020 if (tb1->ty == Tclass) 2021 { 2022 ClassDeclaration *cd = tb1->isClassHandle (); 2023 if (!cd->isInterfaceDeclaration () && !cd->isCPPclass ()) 2024 { 2025 arg = d_save_expr (arg); 2026 assert_pass = build_libcall (LIBCALL_INVARIANT, 2027 Type::tvoid, 1, arg); 2028 } 2029 } 2030 else if (tb1->ty == Tpointer && tb1->nextOf ()->ty == Tstruct) 2031 { 2032 StructDeclaration *sd = ((TypeStruct *) tb1->nextOf ())->sym; 2033 if (sd->inv != NULL) 2034 { 2035 Expressions args; 2036 arg = d_save_expr (arg); 2037 assert_pass = d_build_call_expr (sd->inv, arg, &args); 2038 } 2039 } 2040 } 2041 } 2042 else if (global.params.useAssert 2043 && global.params.checkAction == CHECKACTION_C) 2044 { 2045 /* Generate: __builtin_trap() */ 2046 tree fn = builtin_decl_explicit (BUILT_IN_TRAP); 2047 assert_fail = build_call_expr (fn, 0); 2048 } 2049 else 2050 { 2051 /* Assert contracts are turned off, if the contract condition has no 2052 side effects can still use it as a predicate for the optimizer. */ 2053 if (TREE_SIDE_EFFECTS (arg)) 2054 { 2055 this->result_ = void_node; 2056 return; 2057 } 2058 2059 assert_fail = build_predict_expr (PRED_NORETURN, NOT_TAKEN); 2060 } 2061 2062 /* Build condition that we are asserting in this contract. */ 2063 tree condition = convert_for_condition (arg, e->e1->type); 2064 2065 /* We expect the condition to always be true, as what happens if an assert 2066 contract is false is undefined behavior. */ 2067 tree fn = builtin_decl_explicit (BUILT_IN_EXPECT); 2068 tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); 2069 tree pred_type = TREE_VALUE (arg_types); 2070 tree expected_type = TREE_VALUE (TREE_CHAIN (arg_types)); 2071 2072 condition = build_call_expr (fn, 2, d_convert (pred_type, condition), 2073 build_int_cst (expected_type, 1)); 2074 condition = d_truthvalue_conversion (condition); 2075 2076 this->result_ = build_vcondition (condition, assert_pass, assert_fail); 2077 } 2078 2079 /* Build a declaration expression. */ 2080 2081 void visit (DeclarationExp *e) 2082 { 2083 /* Compile the declaration. */ 2084 push_stmt_list (); 2085 build_decl_tree (e->declaration); 2086 tree result = pop_stmt_list (); 2087 2088 /* Construction of an array for typesafe-variadic function arguments 2089 can cause an empty STMT_LIST here. This can causes problems 2090 during gimplification. */ 2091 if (TREE_CODE (result) == STATEMENT_LIST && !STATEMENT_LIST_HEAD (result)) 2092 result = build_empty_stmt (input_location); 2093 2094 this->result_ = result; 2095 } 2096 2097 /* Build a typeid expression. Returns an instance of class TypeInfo 2098 corresponding to. */ 2099 2100 void visit (TypeidExp *e) 2101 { 2102 if (Type *tid = isType (e->obj)) 2103 { 2104 tree ti = build_typeinfo (e->loc, tid); 2105 2106 /* If the typeinfo is at an offset. */ 2107 if (tid->vtinfo->offset) 2108 ti = build_offset (ti, size_int (tid->vtinfo->offset)); 2109 2110 this->result_ = build_nop (build_ctype (e->type), ti); 2111 } 2112 else if (Expression *tid = isExpression (e->obj)) 2113 { 2114 Type *type = tid->type->toBasetype (); 2115 assert (type->ty == Tclass); 2116 2117 /* Generate **classptr to get the classinfo. */ 2118 tree ci = build_expr (tid); 2119 ci = indirect_ref (ptr_type_node, ci); 2120 ci = indirect_ref (ptr_type_node, ci); 2121 2122 /* Add extra indirection for interfaces. */ 2123 if (((TypeClass *) type)->sym->isInterfaceDeclaration ()) 2124 ci = indirect_ref (ptr_type_node, ci); 2125 2126 this->result_ = build_nop (build_ctype (e->type), ci); 2127 } 2128 else 2129 gcc_unreachable (); 2130 } 2131 2132 /* Build a function/lambda expression. */ 2133 2134 void visit (FuncExp *e) 2135 { 2136 Type *ftype = e->type->toBasetype (); 2137 2138 /* This check is for lambda's, remove 'vthis' as function isn't nested. */ 2139 if (e->fd->tok == TOKreserved && ftype->ty == Tpointer) 2140 { 2141 e->fd->tok = TOKfunction; 2142 e->fd->vthis = NULL; 2143 } 2144 2145 /* Compile the function literal body. */ 2146 build_decl_tree (e->fd); 2147 2148 /* If nested, this will be a trampoline. */ 2149 if (e->fd->isNested ()) 2150 { 2151 tree func = build_address (get_symbol_decl (e->fd)); 2152 tree object; 2153 2154 if (this->constp_) 2155 { 2156 /* Static delegate variables have no context pointer. */ 2157 object = null_pointer_node; 2158 this->result_ = build_method_call (func, object, e->fd->type); 2159 TREE_CONSTANT (this->result_) = 1; 2160 } 2161 else 2162 { 2163 object = get_frame_for_symbol (e->fd); 2164 this->result_ = build_method_call (func, object, e->fd->type); 2165 } 2166 } 2167 else 2168 { 2169 this->result_ = build_nop (build_ctype (e->type), 2170 build_address (get_symbol_decl (e->fd))); 2171 } 2172 } 2173 2174 /* Build a halt expression. */ 2175 2176 void visit (HaltExp *) 2177 { 2178 /* Should we use trap() or abort()? */ 2179 tree ttrap = builtin_decl_explicit (BUILT_IN_TRAP); 2180 this->result_ = build_call_expr (ttrap, 0); 2181 } 2182 2183 /* Build a symbol pointer offset expression. */ 2184 2185 void visit (SymOffExp *e) 2186 { 2187 /* Build the address and offset of the symbol. */ 2188 size_t soffset = ((SymOffExp *) e)->offset; 2189 tree result = get_decl_tree (e->var); 2190 TREE_USED (result) = 1; 2191 2192 if (declaration_reference_p (e->var)) 2193 gcc_assert (POINTER_TYPE_P (TREE_TYPE (result))); 2194 else 2195 result = build_address (result); 2196 2197 if (!soffset) 2198 result = d_convert (build_ctype (e->type), result); 2199 else 2200 { 2201 tree offset = size_int (soffset); 2202 result = build_nop (build_ctype (e->type), 2203 build_offset (result, offset)); 2204 } 2205 2206 this->result_ = result; 2207 } 2208 2209 /* Build a variable expression. */ 2210 2211 void visit (VarExp *e) 2212 { 2213 if (e->var->needThis ()) 2214 { 2215 error ("need %<this%> to access member %qs", e->var->ident->toChars ()); 2216 this->result_ = error_mark_node; 2217 return; 2218 } 2219 else if (e->var->ident == Identifier::idPool ("__ctfe")) 2220 { 2221 /* __ctfe is always false at run-time. */ 2222 this->result_ = integer_zero_node; 2223 return; 2224 } 2225 2226 /* This check is same as is done in FuncExp for lambdas. */ 2227 FuncLiteralDeclaration *fld = e->var->isFuncLiteralDeclaration (); 2228 if (fld != NULL) 2229 { 2230 if (fld->tok == TOKreserved) 2231 { 2232 fld->tok = TOKfunction; 2233 fld->vthis = NULL; 2234 } 2235 2236 /* Compiler the function literal body. */ 2237 build_decl_tree (fld); 2238 } 2239 2240 if (this->constp_) 2241 { 2242 /* Want the initializer, not the expression. */ 2243 VarDeclaration *var = e->var->isVarDeclaration (); 2244 SymbolDeclaration *sd = e->var->isSymbolDeclaration (); 2245 tree init = NULL_TREE; 2246 2247 if (var && (var->isConst () || var->isImmutable ()) 2248 && e->type->toBasetype ()->ty != Tsarray && var->_init) 2249 { 2250 if (var->inuse) 2251 error_at (make_location_t (e->loc), "recursive reference %qs", 2252 e->toChars ()); 2253 else 2254 { 2255 var->inuse++; 2256 init = build_expr (initializerToExpression (var->_init), true); 2257 var->inuse--; 2258 } 2259 } 2260 else if (sd && sd->dsym) 2261 init = layout_struct_initializer (sd->dsym); 2262 else 2263 error_at (make_location_t (e->loc), "non-constant expression %qs", 2264 e->toChars ()); 2265 2266 if (init != NULL_TREE) 2267 this->result_ = init; 2268 else 2269 this->result_ = error_mark_node; 2270 } 2271 else 2272 { 2273 tree result = get_decl_tree (e->var); 2274 TREE_USED (result) = 1; 2275 2276 /* For variables that are references - currently only out/inout 2277 arguments; objects don't count - evaluating the variable means 2278 we want what it refers to. */ 2279 if (declaration_reference_p (e->var)) 2280 result = indirect_ref (build_ctype (e->var->type), result); 2281 2282 this->result_ = result; 2283 } 2284 } 2285 2286 /* Build a this variable expression. */ 2287 2288 void visit (ThisExp *e) 2289 { 2290 FuncDeclaration *fd = d_function_chain ? d_function_chain->function : NULL; 2291 tree result = NULL_TREE; 2292 2293 if (e->var) 2294 result = get_decl_tree (e->var); 2295 else 2296 { 2297 gcc_assert (fd && fd->vthis); 2298 result = get_decl_tree (fd->vthis); 2299 } 2300 2301 if (e->type->ty == Tstruct) 2302 result = build_deref (result); 2303 2304 this->result_ = result; 2305 } 2306 2307 /* Build a new expression, which allocates memory either on the garbage 2308 collected heap or by using a class or struct specific allocator. */ 2309 2310 void visit (NewExp *e) 2311 { 2312 Type *tb = e->type->toBasetype (); 2313 tree result; 2314 2315 if (e->allocator) 2316 gcc_assert (e->newargs); 2317 2318 if (tb->ty == Tclass) 2319 { 2320 /* Allocating a new class. */ 2321 tb = e->newtype->toBasetype (); 2322 gcc_assert (tb->ty == Tclass); 2323 2324 ClassDeclaration *cd = ((TypeClass *) tb)->sym; 2325 tree type = build_ctype (tb); 2326 tree setup_exp = NULL_TREE; 2327 tree new_call; 2328 2329 if (e->onstack) 2330 { 2331 /* If being used as an initializer for a local variable with scope 2332 storage class, then the instance is allocated on the stack 2333 rather than the heap or using the class specific allocator. */ 2334 tree var = build_local_temp (TREE_TYPE (type)); 2335 new_call = build_nop (type, build_address (var)); 2336 setup_exp = modify_expr (var, aggregate_initializer_decl (cd)); 2337 } 2338 else if (e->allocator) 2339 { 2340 /* Call class allocator, and copy the initializer into memory. */ 2341 new_call = d_build_call_expr (e->allocator, NULL_TREE, e->newargs); 2342 new_call = d_save_expr (new_call); 2343 new_call = build_nop (type, new_call); 2344 setup_exp = modify_expr (build_deref (new_call), 2345 aggregate_initializer_decl (cd)); 2346 } 2347 else 2348 { 2349 /* Generate: _d_newclass() */ 2350 tree arg = build_address (get_classinfo_decl (cd)); 2351 new_call = build_libcall (LIBCALL_NEWCLASS, tb, 1, arg); 2352 } 2353 2354 /* Set the context pointer for nested classes. */ 2355 if (cd->isNested ()) 2356 { 2357 tree field = get_symbol_decl (cd->vthis); 2358 tree value = NULL_TREE; 2359 2360 if (e->thisexp) 2361 { 2362 ClassDeclaration *tcd = e->thisexp->type->isClassHandle (); 2363 Dsymbol *outer = cd->toParent2 (); 2364 int offset = 0; 2365 2366 value = build_expr (e->thisexp); 2367 if (outer != tcd) 2368 { 2369 ClassDeclaration *ocd = outer->isClassDeclaration (); 2370 gcc_assert (ocd->isBaseOf (tcd, &offset)); 2371 /* Could just add offset... */ 2372 value = convert_expr (value, e->thisexp->type, ocd->type); 2373 } 2374 } 2375 else 2376 value = build_vthis (cd); 2377 2378 if (value != NULL_TREE) 2379 { 2380 /* Generate: (new())->vthis = this; */ 2381 new_call = d_save_expr (new_call); 2382 field = component_ref (build_deref (new_call), field); 2383 setup_exp = compound_expr (setup_exp, 2384 modify_expr (field, value)); 2385 } 2386 } 2387 new_call = compound_expr (setup_exp, new_call); 2388 2389 /* Call the class constructor. */ 2390 if (e->member) 2391 result = d_build_call_expr (e->member, new_call, e->arguments); 2392 else 2393 result = new_call; 2394 2395 if (e->argprefix) 2396 result = compound_expr (build_expr (e->argprefix), result); 2397 } 2398 else if (tb->ty == Tpointer && tb->nextOf ()->toBasetype ()->ty == Tstruct) 2399 { 2400 /* Allocating memory for a new struct. */ 2401 Type *htype = e->newtype->toBasetype (); 2402 gcc_assert (htype->ty == Tstruct); 2403 gcc_assert (!e->onstack); 2404 2405 TypeStruct *stype = (TypeStruct *) htype; 2406 StructDeclaration *sd = stype->sym; 2407 tree new_call; 2408 2409 /* Cannot new an opaque struct. */ 2410 if (sd->size (e->loc) == 0) 2411 { 2412 this->result_ = d_convert (build_ctype (e->type), 2413 integer_zero_node); 2414 return; 2415 } 2416 2417 if (e->allocator) 2418 { 2419 /* Call struct allocator. */ 2420 new_call = d_build_call_expr (e->allocator, NULL_TREE, e->newargs); 2421 new_call = build_nop (build_ctype (tb), new_call); 2422 } 2423 else 2424 { 2425 /* Generate: _d_newitemT() */ 2426 libcall_fn libcall = htype->isZeroInit () 2427 ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT; 2428 tree arg = build_typeinfo (e->loc, e->newtype); 2429 new_call = build_libcall (libcall, tb, 1, arg); 2430 } 2431 2432 if (e->member || !e->arguments) 2433 { 2434 /* Set the context pointer for nested structs. */ 2435 if (sd->isNested ()) 2436 { 2437 tree value = build_vthis (sd); 2438 tree field = get_symbol_decl (sd->vthis); 2439 tree type = build_ctype (stype); 2440 2441 new_call = d_save_expr (new_call); 2442 field = component_ref (indirect_ref (type, new_call), field); 2443 new_call = compound_expr (modify_expr (field, value), new_call); 2444 } 2445 2446 /* Call the struct constructor. */ 2447 if (e->member) 2448 result = d_build_call_expr (e->member, new_call, e->arguments); 2449 else 2450 result = new_call; 2451 } 2452 else 2453 { 2454 /* If we have a user supplied initializer, then set-up with a 2455 struct literal. */ 2456 if (e->arguments != NULL && sd->fields.dim != 0) 2457 { 2458 StructLiteralExp *se = StructLiteralExp::create (e->loc, sd, 2459 e->arguments, 2460 htype); 2461 new_call = d_save_expr (new_call); 2462 se->type = sd->type; 2463 se->sym = new_call; 2464 result = compound_expr (build_expr (se), new_call); 2465 } 2466 else 2467 result = new_call; 2468 } 2469 2470 if (e->argprefix) 2471 result = compound_expr (build_expr (e->argprefix), result); 2472 } 2473 else if (tb->ty == Tarray) 2474 { 2475 /* Allocating memory for a new D array. */ 2476 tb = e->newtype->toBasetype (); 2477 gcc_assert (tb->ty == Tarray); 2478 TypeDArray *tarray = (TypeDArray *) tb; 2479 2480 gcc_assert (!e->allocator); 2481 gcc_assert (e->arguments && e->arguments->dim >= 1); 2482 2483 if (e->arguments->dim == 1) 2484 { 2485 /* Single dimension array allocations. */ 2486 Expression *arg = (*e->arguments)[0]; 2487 2488 if (tarray->next->size () == 0) 2489 { 2490 /* Array element size is unknown. */ 2491 this->result_ = d_array_value (build_ctype (e->type), 2492 size_int (0), null_pointer_node); 2493 return; 2494 } 2495 2496 libcall_fn libcall = tarray->next->isZeroInit () 2497 ? LIBCALL_NEWARRAYT : LIBCALL_NEWARRAYIT; 2498 result = build_libcall (libcall, tb, 2, 2499 build_typeinfo (e->loc, e->type), 2500 build_expr (arg)); 2501 } 2502 else 2503 { 2504 /* Multidimensional array allocations. */ 2505 tree tarray = make_array_type (Type::tsize_t, e->arguments->dim); 2506 tree var = build_local_temp (tarray); 2507 vec<constructor_elt, va_gc> *elms = NULL; 2508 2509 /* Get the base element type for the array, generating the 2510 initializer for the dims parameter along the way. */ 2511 Type *telem = e->newtype->toBasetype (); 2512 for (size_t i = 0; i < e->arguments->dim; i++) 2513 { 2514 Expression *arg = (*e->arguments)[i]; 2515 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), build_expr (arg)); 2516 2517 gcc_assert (telem->ty == Tarray); 2518 telem = telem->toBasetype ()->nextOf (); 2519 gcc_assert (telem); 2520 } 2521 2522 /* Initialize the temporary. */ 2523 tree init = modify_expr (var, build_constructor (tarray, elms)); 2524 var = compound_expr (init, var); 2525 2526 /* Generate: _d_newarraymTX(ti, dims) 2527 or: _d_newarraymiTX(ti, dims) */ 2528 libcall_fn libcall = telem->isZeroInit () 2529 ? LIBCALL_NEWARRAYMTX : LIBCALL_NEWARRAYMITX; 2530 2531 tree tinfo = build_typeinfo (e->loc, e->type); 2532 tree dims = d_array_value (build_ctype (Type::tsize_t->arrayOf ()), 2533 size_int (e->arguments->dim), 2534 build_address (var)); 2535 2536 result = build_libcall (libcall, tb, 2, tinfo, dims); 2537 } 2538 2539 if (e->argprefix) 2540 result = compound_expr (build_expr (e->argprefix), result); 2541 } 2542 else if (tb->ty == Tpointer) 2543 { 2544 /* Allocating memory for a new pointer. */ 2545 TypePointer *tpointer = (TypePointer *) tb; 2546 2547 if (tpointer->next->size () == 0) 2548 { 2549 /* Pointer element size is unknown. */ 2550 this->result_ = d_convert (build_ctype (e->type), 2551 integer_zero_node); 2552 return; 2553 } 2554 2555 libcall_fn libcall = tpointer->next->isZeroInit (e->loc) 2556 ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT; 2557 2558 tree arg = build_typeinfo (e->loc, e->newtype); 2559 result = build_libcall (libcall, tb, 1, arg); 2560 2561 if (e->arguments && e->arguments->dim == 1) 2562 { 2563 result = d_save_expr (result); 2564 tree init = modify_expr (build_deref (result), 2565 build_expr ((*e->arguments)[0])); 2566 result = compound_expr (init, result); 2567 } 2568 2569 if (e->argprefix) 2570 result = compound_expr (build_expr (e->argprefix), result); 2571 } 2572 else 2573 gcc_unreachable (); 2574 2575 this->result_ = convert_expr (result, tb, e->type); 2576 } 2577 2578 /* Build an integer literal. */ 2579 2580 void visit (IntegerExp *e) 2581 { 2582 tree ctype = build_ctype (e->type->toBasetype ()); 2583 this->result_ = build_integer_cst (e->value, ctype); 2584 } 2585 2586 /* Build a floating-point literal. */ 2587 2588 void visit (RealExp *e) 2589 { 2590 this->result_ = build_float_cst (e->value, e->type->toBasetype ()); 2591 } 2592 2593 /* Build a complex literal. */ 2594 2595 void visit (ComplexExp *e) 2596 { 2597 Type *tnext; 2598 2599 switch (e->type->toBasetype ()->ty) 2600 { 2601 case Tcomplex32: 2602 tnext = (TypeBasic *) Type::tfloat32; 2603 break; 2604 2605 case Tcomplex64: 2606 tnext = (TypeBasic *) Type::tfloat64; 2607 break; 2608 2609 case Tcomplex80: 2610 tnext = (TypeBasic *) Type::tfloat80; 2611 break; 2612 2613 default: 2614 gcc_unreachable (); 2615 } 2616 2617 this->result_ = build_complex (build_ctype (e->type), 2618 build_float_cst (creall (e->value), tnext), 2619 build_float_cst (cimagl (e->value), tnext)); 2620 } 2621 2622 /* Build a string literal, all strings are null terminated except for 2623 static arrays. */ 2624 2625 void visit (StringExp *e) 2626 { 2627 Type *tb = e->type->toBasetype (); 2628 tree type = build_ctype (e->type); 2629 2630 if (tb->ty == Tsarray) 2631 { 2632 /* Turn the string into a constructor for the static array. */ 2633 vec<constructor_elt, va_gc> *elms = NULL; 2634 vec_safe_reserve (elms, e->len); 2635 tree etype = TREE_TYPE (type); 2636 2637 for (size_t i = 0; i < e->len; i++) 2638 { 2639 tree value = build_integer_cst (e->charAt (i), etype); 2640 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value); 2641 } 2642 2643 tree ctor = build_constructor (type, elms); 2644 TREE_CONSTANT (ctor) = 1; 2645 this->result_ = ctor; 2646 } 2647 else 2648 { 2649 /* Copy the string contents to a null terminated string. */ 2650 dinteger_t length = (e->len * e->sz); 2651 char *string = XALLOCAVEC (char, length + 1); 2652 memcpy (string, e->string, length); 2653 string[length] = '\0'; 2654 2655 /* String value and type includes the null terminator. */ 2656 tree value = build_string (length, string); 2657 TREE_TYPE (value) = make_array_type (tb->nextOf (), length + 1); 2658 value = build_address (value); 2659 2660 if (tb->ty == Tarray) 2661 value = d_array_value (type, size_int (e->len), value); 2662 2663 TREE_CONSTANT (value) = 1; 2664 this->result_ = d_convert (type, value); 2665 } 2666 } 2667 2668 /* Build a tuple literal. Just an argument list that may have 2669 side effects that need evaluation. */ 2670 2671 void visit (TupleExp *e) 2672 { 2673 tree result = NULL_TREE; 2674 2675 if (e->e0) 2676 result = build_expr (e->e0); 2677 2678 for (size_t i = 0; i < e->exps->dim; ++i) 2679 { 2680 Expression *exp = (*e->exps)[i]; 2681 result = compound_expr (result, build_expr (exp)); 2682 } 2683 2684 if (result == NULL_TREE) 2685 result = void_node; 2686 2687 this->result_ = result; 2688 } 2689 2690 /* Build an array literal. The common type of the all elements is taken to 2691 be the type of the array element, and all elements are implicitly 2692 converted to that type. */ 2693 2694 void visit (ArrayLiteralExp *e) 2695 { 2696 Type *tb = e->type->toBasetype (); 2697 2698 /* Implicitly convert void[n] to ubyte[n]. */ 2699 if (tb->ty == Tsarray && tb->nextOf ()->toBasetype ()->ty == Tvoid) 2700 tb = Type::tuns8->sarrayOf (((TypeSArray *) tb)->dim->toUInteger ()); 2701 2702 gcc_assert (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tpointer); 2703 2704 /* Handle empty array literals. */ 2705 if (e->elements->dim == 0) 2706 { 2707 if (tb->ty == Tarray) 2708 this->result_ = d_array_value (build_ctype (e->type), 2709 size_int (0), null_pointer_node); 2710 else 2711 this->result_ = build_constructor (make_array_type (tb->nextOf (), 0), 2712 NULL); 2713 2714 return; 2715 } 2716 2717 /* Build an expression that assigns the expressions in ELEMENTS to 2718 a constructor. */ 2719 vec<constructor_elt, va_gc> *elms = NULL; 2720 vec_safe_reserve (elms, e->elements->dim); 2721 bool constant_p = true; 2722 tree saved_elems = NULL_TREE; 2723 2724 Type *etype = tb->nextOf (); 2725 tree satype = make_array_type (etype, e->elements->dim); 2726 2727 for (size_t i = 0; i < e->elements->dim; i++) 2728 { 2729 Expression *expr = e->getElement (i); 2730 tree value = build_expr (expr, this->constp_); 2731 2732 /* Only append nonzero values, the backend will zero out the rest 2733 of the constructor as we don't set CONSTRUCTOR_NO_CLEARING. */ 2734 if (!initializer_zerop (value)) 2735 { 2736 if (!TREE_CONSTANT (value)) 2737 constant_p = false; 2738 2739 /* Split construction of values out of the constructor if there 2740 may be side effects. */ 2741 tree init = stabilize_expr (&value); 2742 if (init != NULL_TREE) 2743 saved_elems = compound_expr (saved_elems, init); 2744 2745 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), 2746 convert_expr (value, expr->type, etype)); 2747 } 2748 } 2749 2750 /* Now return the constructor as the correct type. For static arrays there 2751 is nothing else to do. For dynamic arrays, return a two field struct. 2752 For pointers, return the address. */ 2753 tree ctor = build_constructor (satype, elms); 2754 tree type = build_ctype (e->type); 2755 2756 /* Nothing else to do for static arrays. */ 2757 if (tb->ty == Tsarray || this->constp_) 2758 { 2759 /* Can't take the address of the constructor, so create an anonymous 2760 static symbol, and then refer to it. */ 2761 if (tb->ty != Tsarray) 2762 { 2763 tree decl = build_artificial_decl (TREE_TYPE (ctor), ctor, "A"); 2764 ctor = build_address (decl); 2765 if (tb->ty == Tarray) 2766 ctor = d_array_value (type, size_int (e->elements->dim), ctor); 2767 2768 d_pushdecl (decl); 2769 rest_of_decl_compilation (decl, 1, 0); 2770 } 2771 2772 /* If the array literal is readonly or static. */ 2773 if (constant_p) 2774 TREE_CONSTANT (ctor) = 1; 2775 if (constant_p && initializer_constant_valid_p (ctor, TREE_TYPE (ctor))) 2776 TREE_STATIC (ctor) = 1; 2777 2778 this->result_ = compound_expr (saved_elems, d_convert (type, ctor)); 2779 } 2780 else 2781 { 2782 /* Allocate space on the memory managed heap. */ 2783 tree mem = build_libcall (LIBCALL_ARRAYLITERALTX, 2784 etype->pointerTo (), 2, 2785 build_typeinfo (e->loc, etype->arrayOf ()), 2786 size_int (e->elements->dim)); 2787 mem = d_save_expr (mem); 2788 2789 /* Now copy the constructor into memory. */ 2790 tree tmemcpy = builtin_decl_explicit (BUILT_IN_MEMCPY); 2791 tree size = size_mult_expr (size_int (e->elements->dim), 2792 size_int (tb->nextOf ()->size ())); 2793 2794 tree result = build_call_expr (tmemcpy, 3, mem, 2795 build_address (ctor), size); 2796 2797 /* Return the array pointed to by MEM. */ 2798 result = compound_expr (result, mem); 2799 2800 if (tb->ty == Tarray) 2801 result = d_array_value (type, size_int (e->elements->dim), result); 2802 2803 this->result_ = compound_expr (saved_elems, result); 2804 } 2805 } 2806 2807 /* Build an associative array literal. The common type of the all keys is 2808 taken to be the key type, and common type of all values the value type. 2809 All keys and values are then implicitly converted as needed. */ 2810 2811 void visit (AssocArrayLiteralExp *e) 2812 { 2813 /* Want the mutable type for typeinfo reference. */ 2814 Type *tb = e->type->toBasetype ()->mutableOf (); 2815 gcc_assert (tb->ty == Taarray); 2816 2817 /* Handle empty assoc array literals. */ 2818 TypeAArray *ta = (TypeAArray *) tb; 2819 if (e->keys->dim == 0) 2820 { 2821 this->result_ = build_constructor (build_ctype (ta), NULL); 2822 return; 2823 } 2824 2825 /* Build an expression that assigns all expressions in KEYS 2826 to a constructor. */ 2827 vec<constructor_elt, va_gc> *kelts = NULL; 2828 vec_safe_reserve (kelts, e->keys->dim); 2829 for (size_t i = 0; i < e->keys->dim; i++) 2830 { 2831 Expression *key = (*e->keys)[i]; 2832 tree t = build_expr (key); 2833 CONSTRUCTOR_APPEND_ELT (kelts, size_int (i), 2834 convert_expr (t, key->type, ta->index)); 2835 } 2836 tree tkeys = make_array_type (ta->index, e->keys->dim); 2837 tree akeys = build_constructor (tkeys, kelts); 2838 2839 /* Do the same with all expressions in VALUES. */ 2840 vec<constructor_elt, va_gc> *velts = NULL; 2841 vec_safe_reserve (velts, e->values->dim); 2842 for (size_t i = 0; i < e->values->dim; i++) 2843 { 2844 Expression *value = (*e->values)[i]; 2845 tree t = build_expr (value); 2846 CONSTRUCTOR_APPEND_ELT (velts, size_int (i), 2847 convert_expr (t, value->type, ta->next)); 2848 } 2849 tree tvals = make_array_type (ta->next, e->values->dim); 2850 tree avals = build_constructor (tvals, velts); 2851 2852 /* Generate: _d_assocarrayliteralTX (ti, keys, vals); */ 2853 tree keys = d_array_value (build_ctype (ta->index->arrayOf ()), 2854 size_int (e->keys->dim), build_address (akeys)); 2855 tree vals = d_array_value (build_ctype (ta->next->arrayOf ()), 2856 size_int (e->values->dim), 2857 build_address (avals)); 2858 2859 tree mem = build_libcall (LIBCALL_ASSOCARRAYLITERALTX, Type::tvoidptr, 3, 2860 build_typeinfo (e->loc, ta), keys, vals); 2861 2862 /* Return an associative array pointed to by MEM. */ 2863 tree aatype = build_ctype (ta); 2864 vec<constructor_elt, va_gc> *ce = NULL; 2865 CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (aatype), mem); 2866 2867 this->result_ = build_nop (build_ctype (e->type), 2868 build_constructor (aatype, ce)); 2869 } 2870 2871 /* Build a struct literal. */ 2872 2873 void visit (StructLiteralExp *e) 2874 { 2875 /* Handle empty struct literals. */ 2876 if (e->elements == NULL || e->sd->fields.dim == 0) 2877 { 2878 this->result_ = build_constructor (build_ctype (e->type), NULL); 2879 return; 2880 } 2881 2882 /* Building sinit trees are delayed until after frontend semantic 2883 processing has complete. Build the static initializer now. */ 2884 if (e->useStaticInit && !this->constp_) 2885 { 2886 this->result_ = aggregate_initializer_decl (e->sd); 2887 return; 2888 } 2889 2890 /* Build a constructor that assigns the expressions in ELEMENTS 2891 at each field index that has been filled in. */ 2892 vec<constructor_elt, va_gc> *ve = NULL; 2893 tree saved_elems = NULL_TREE; 2894 2895 /* CTFE may fill the hidden pointer by NullExp. */ 2896 gcc_assert (e->elements->dim <= e->sd->fields.dim); 2897 2898 Type *tb = e->type->toBasetype (); 2899 gcc_assert (tb->ty == Tstruct); 2900 2901 for (size_t i = 0; i < e->elements->dim; i++) 2902 { 2903 Expression *exp = (*e->elements)[i]; 2904 if (!exp) 2905 continue; 2906 2907 VarDeclaration *field = e->sd->fields[i]; 2908 Type *type = exp->type->toBasetype (); 2909 Type *ftype = field->type->toBasetype (); 2910 tree value = NULL_TREE; 2911 2912 if (ftype->ty == Tsarray && !same_type_p (type, ftype)) 2913 { 2914 /* Initialize a static array with a single element. */ 2915 tree elem = build_expr (exp, this->constp_); 2916 elem = d_save_expr (elem); 2917 2918 if (initializer_zerop (elem)) 2919 value = build_constructor (build_ctype (ftype), NULL); 2920 else 2921 value = build_array_from_val (ftype, elem); 2922 } 2923 else 2924 { 2925 value = convert_expr (build_expr (exp, this->constp_), 2926 exp->type, field->type); 2927 } 2928 2929 /* Split construction of values out of the constructor. */ 2930 tree init = stabilize_expr (&value); 2931 if (init != NULL_TREE) 2932 saved_elems = compound_expr (saved_elems, init); 2933 2934 CONSTRUCTOR_APPEND_ELT (ve, get_symbol_decl (field), value); 2935 } 2936 2937 /* Maybe setup hidden pointer to outer scope context. */ 2938 if (e->sd->isNested () && e->elements->dim != e->sd->fields.dim 2939 && this->constp_ == false) 2940 { 2941 tree field = get_symbol_decl (e->sd->vthis); 2942 tree value = build_vthis (e->sd); 2943 CONSTRUCTOR_APPEND_ELT (ve, field, value); 2944 gcc_assert (e->useStaticInit == false); 2945 } 2946 2947 /* Build a constructor in the correct shape of the aggregate type. */ 2948 tree ctor = build_struct_literal (build_ctype (e->type), ve); 2949 2950 /* Nothing more to do for constant literals. */ 2951 if (this->constp_) 2952 { 2953 /* If the struct literal is a valid for static data. */ 2954 if (TREE_CONSTANT (ctor) 2955 && initializer_constant_valid_p (ctor, TREE_TYPE (ctor))) 2956 TREE_STATIC (ctor) = 1; 2957 2958 this->result_ = compound_expr (saved_elems, ctor); 2959 return; 2960 } 2961 2962 if (e->sym != NULL) 2963 { 2964 tree var = build_deref (e->sym); 2965 ctor = compound_expr (modify_expr (var, ctor), var); 2966 this->result_ = compound_expr (saved_elems, ctor); 2967 } 2968 else if (e->sd->isUnionDeclaration ()) 2969 { 2970 /* For unions, use memset to fill holes in the object. */ 2971 tree var = build_local_temp (TREE_TYPE (ctor)); 2972 tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET); 2973 tree init = build_call_expr (tmemset, 3, build_address (var), 2974 size_zero_node, 2975 size_int (e->sd->structsize)); 2976 2977 init = compound_expr (init, saved_elems); 2978 init = compound_expr (init, modify_expr (var, ctor)); 2979 this->result_ = compound_expr (init, var); 2980 } 2981 else 2982 this->result_ = compound_expr (saved_elems, ctor); 2983 } 2984 2985 /* Build a null literal. */ 2986 2987 void visit (NullExp *e) 2988 { 2989 this->result_ = build_typeof_null_value (e->type); 2990 } 2991 2992 /* Build a vector literal. */ 2993 2994 void visit (VectorExp *e) 2995 { 2996 /* First handle array literal expressions. */ 2997 if (e->e1->op == TOKarrayliteral) 2998 { 2999 ArrayLiteralExp *ale = ((ArrayLiteralExp *) e->e1); 3000 vec<constructor_elt, va_gc> *elms = NULL; 3001 bool constant_p = true; 3002 tree type = build_ctype (e->type); 3003 3004 vec_safe_reserve (elms, ale->elements->dim); 3005 for (size_t i = 0; i < ale->elements->dim; i++) 3006 { 3007 Expression *expr = ale->getElement (i); 3008 tree value = d_convert (TREE_TYPE (type), 3009 build_expr (expr, this->constp_)); 3010 if (!CONSTANT_CLASS_P (value)) 3011 constant_p = false; 3012 3013 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value); 3014 } 3015 3016 /* Build a VECTOR_CST from a constant vector constructor. */ 3017 if (constant_p) 3018 this->result_ = build_vector_from_ctor (type, elms); 3019 else 3020 this->result_ = build_constructor (type, elms); 3021 } 3022 else if (e->e1->type->toBasetype ()->ty == Tsarray) 3023 { 3024 /* Build a vector representation from a static array. */ 3025 this->result_ = convert_expr (build_expr (e->e1, this->constp_), 3026 e->e1->type, e->type); 3027 } 3028 else 3029 { 3030 /* Build constructor from single value. */ 3031 tree type = build_ctype (e->type); 3032 tree val = d_convert (TREE_TYPE (type), 3033 build_expr (e->e1, this->constp_)); 3034 this->result_ = build_vector_from_val (type, val); 3035 } 3036 } 3037 3038 /* Build a static array representation of a vector expression. */ 3039 3040 void visit (VectorArrayExp *e) 3041 { 3042 this->result_ = convert_expr (build_expr (e->e1, this->constp_), 3043 e->e1->type, e->type); 3044 } 3045 3046 /* Build a static class literal, return its reference. */ 3047 3048 void visit (ClassReferenceExp *e) 3049 { 3050 /* The result of build_new_class_expr is a RECORD_TYPE, we want 3051 the reference. */ 3052 tree var = build_address (build_new_class_expr (e)); 3053 3054 /* If the type of this literal is an interface, the we must add the 3055 interface offset to symbol. */ 3056 if (this->constp_) 3057 { 3058 TypeClass *tc = (TypeClass *) e->type; 3059 InterfaceDeclaration *to = tc->sym->isInterfaceDeclaration (); 3060 3061 if (to != NULL) 3062 { 3063 ClassDeclaration *from = e->originalClass (); 3064 int offset = 0; 3065 3066 gcc_assert (to->isBaseOf (from, &offset) != 0); 3067 3068 if (offset != 0) 3069 var = build_offset (var, size_int (offset)); 3070 } 3071 } 3072 3073 this->result_ = var; 3074 } 3075 3076 /* These expressions are mainly just a placeholders in the frontend. 3077 We shouldn't see them here. */ 3078 3079 void visit (ScopeExp *e) 3080 { 3081 error_at (make_location_t (e->loc), "%qs is not an expression", 3082 e->toChars ()); 3083 this->result_ = error_mark_node; 3084 } 3085 3086 void visit (TypeExp *e) 3087 { 3088 error_at (make_location_t (e->loc), "type %qs is not an expression", 3089 e->toChars ()); 3090 this->result_ = error_mark_node; 3091 } 3092}; 3093 3094 3095/* Main entry point for ExprVisitor interface to generate code for 3096 the Expression AST class E. If CONST_P is true, then E is a 3097 constant expression. */ 3098 3099tree 3100build_expr (Expression *e, bool const_p) 3101{ 3102 ExprVisitor v = ExprVisitor (const_p); 3103 location_t saved_location = input_location; 3104 3105 input_location = make_location_t (e->loc); 3106 e->accept (&v); 3107 tree expr = v.result (); 3108 input_location = saved_location; 3109 3110 /* Check if initializer expression is valid constant. */ 3111 if (const_p && !initializer_constant_valid_p (expr, TREE_TYPE (expr))) 3112 { 3113 error_at (make_location_t (e->loc), "non-constant expression %qs", 3114 e->toChars ()); 3115 return error_mark_node; 3116 } 3117 3118 return expr; 3119} 3120 3121/* Same as build_expr, but also calls destructors on any temporaries. */ 3122 3123tree 3124build_expr_dtor (Expression *e) 3125{ 3126 /* Codegen can be improved by determining if no exceptions can be thrown 3127 between the ctor and dtor, and eliminating the ctor and dtor. */ 3128 size_t saved_vars = vec_safe_length (d_function_chain->vars_in_scope); 3129 tree result = build_expr (e); 3130 3131 if (saved_vars != vec_safe_length (d_function_chain->vars_in_scope)) 3132 { 3133 result = fold_build_cleanup_point_expr (TREE_TYPE (result), result); 3134 vec_safe_truncate (d_function_chain->vars_in_scope, saved_vars); 3135 } 3136 3137 return result; 3138} 3139 3140/* Same as build_expr_dtor, but handles the result of E as a return value. */ 3141 3142tree 3143build_return_dtor (Expression *e, Type *type, TypeFunction *tf) 3144{ 3145 size_t saved_vars = vec_safe_length (d_function_chain->vars_in_scope); 3146 tree result = build_expr (e); 3147 3148 /* Convert for initializing the DECL_RESULT. */ 3149 if (tf->isref) 3150 { 3151 /* If we are returning a reference, take the address. */ 3152 result = convert_expr (result, e->type, type); 3153 result = build_address (result); 3154 } 3155 else 3156 result = convert_for_rvalue (result, e->type, type); 3157 3158 /* The decl to store the return expression. */ 3159 tree decl = DECL_RESULT (cfun->decl); 3160 3161 /* Split comma expressions, so that the result is returned directly. */ 3162 tree expr = stabilize_expr (&result); 3163 result = build_assign (INIT_EXPR, decl, result); 3164 result = compound_expr (expr, return_expr (result)); 3165 3166 /* May nest the return expression inside the try/finally expression. */ 3167 if (saved_vars != vec_safe_length (d_function_chain->vars_in_scope)) 3168 { 3169 result = fold_build_cleanup_point_expr (TREE_TYPE (result), result); 3170 vec_safe_truncate (d_function_chain->vars_in_scope, saved_vars); 3171 } 3172 3173 return result; 3174} 3175 3176