1 /* expr.cc -- Lower D frontend expressions to GCC trees.
2 Copyright (C) 2015-2020 Free Software Foundation, Inc.
3
4 GCC is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GCC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GCC; see the file COPYING3. If not see
16 <http://www.gnu.org/licenses/>. */
17
18 #include "config.h"
19 #include "system.h"
20 #include "coretypes.h"
21
22 #include "dmd/aggregate.h"
23 #include "dmd/ctfe.h"
24 #include "dmd/declaration.h"
25 #include "dmd/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
52 class 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
needs_postblit(Type * t)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
needs_dtor(Type * t)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
lvalue_p(Expression * e)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
binary_op(tree_code code,tree type,tree arg0,tree arg1)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 = fold_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
binop_assignment(tree_code code,Expression * e1,Expression * e2)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
218 public:
ExprVisitor(bool constp)219 ExprVisitor (bool constp)
220 {
221 this->result_ = NULL_TREE;
222 this->constp_ = constp;
223 }
224
result(void)225 tree result (void)
226 {
227 return this->result_;
228 }
229
230 /* Visitor interfaces, each Expression class should have
231 overridden the default. */
232
visit(Expression *)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
visit(CondExp * e)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
visit(IdentityExp * e)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
visit(EqualExp * e)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
visit(InExp * e)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
visit(CmpExp * e)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
visit(AndAndExp * e)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
visit(OrOrExp * e)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
visit(BinExp * e)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
visit(CatExp * e)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
visit(BinAssignExp * e)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
visit(CatAssignExp * e)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 if (tb1->ty == Tarray && tb2->ty == Tdchar
842 && (etype->ty == Tchar || etype->ty == Twchar))
843 {
844 /* Append a dchar to a char[] or wchar[] */
845 libcall_fn libcall = (etype->ty == Tchar)
846 ? LIBCALL_ARRAYAPPENDCD : LIBCALL_ARRAYAPPENDWD;
847
848 this->result_ = build_libcall (libcall, e->type, 2,
849 build_address (build_expr (e->e1)),
850 build_expr (e->e2));
851 }
852 else
853 {
854 gcc_assert (tb1->ty == Tarray || tb2->ty == Tsarray);
855
856 tree tinfo = build_typeinfo (e->loc, e->type);
857 tree ptr = build_address (build_expr (e->e1));
858
859 if ((tb2->ty == Tarray || tb2->ty == Tsarray)
860 && same_type_p (etype, tb2->nextOf ()->toBasetype ()))
861 {
862 /* Append an array. */
863 this->result_ = build_libcall (LIBCALL_ARRAYAPPENDT, e->type, 3,
864 tinfo, ptr, d_array_convert (e->e2));
865
866 }
867 else if (same_type_p (etype, tb2))
868 {
869 /* Append an element. */
870 tree result = build_libcall (LIBCALL_ARRAYAPPENDCTX, e->type, 3,
871 tinfo, ptr, size_one_node);
872 result = d_save_expr (result);
873
874 /* Assign e2 to last element. */
875 tree offexp = d_array_length (result);
876 offexp = build2 (MINUS_EXPR, TREE_TYPE (offexp),
877 offexp, size_one_node);
878 offexp = d_save_expr (offexp);
879
880 tree ptrexp = d_array_ptr (result);
881 ptrexp = void_okay_p (ptrexp);
882 ptrexp = build_array_index (ptrexp, offexp);
883
884 /* Evaluate expression before appending. */
885 tree t2 = build_expr (e->e2);
886 tree expr = stabilize_expr (&t2);
887
888 t2 = d_save_expr (t2);
889 result = modify_expr (build_deref (ptrexp), t2);
890 result = compound_expr (t2, result);
891
892 this->result_ = compound_expr (expr, result);
893 }
894 else
895 gcc_unreachable ();
896 }
897 }
898
899 /* Build an assignment expression. The right operand is implicitly
900 converted to the type of the left operand, and assigned to it. */
901
visit(AssignExp * e)902 void visit (AssignExp *e)
903 {
904 /* First, handle special assignment semantics. */
905
906 /* Look for array.length = n; */
907 if (e->e1->op == TOKarraylength)
908 {
909 /* Assignment to an array's length property; resize the array. */
910 ArrayLengthExp *ale = (ArrayLengthExp *) e->e1;
911 tree newlength = convert_expr (build_expr (e->e2), e->e2->type,
912 Type::tsize_t);
913 tree ptr = build_address (build_expr (ale->e1));
914
915 /* Don't want the basetype for the element type. */
916 Type *etype = ale->e1->type->toBasetype ()->nextOf ();
917 libcall_fn libcall = etype->isZeroInit ()
918 ? LIBCALL_ARRAYSETLENGTHT : LIBCALL_ARRAYSETLENGTHIT;
919
920 tree result = build_libcall (libcall, ale->e1->type, 3,
921 build_typeinfo (ale->loc, ale->e1->type),
922 newlength, ptr);
923
924 this->result_ = d_array_length (result);
925 return;
926 }
927
928 /* Look for array[] = n; */
929 if (e->e1->op == TOKslice)
930 {
931 SliceExp *se = (SliceExp *) e->e1;
932 Type *stype = se->e1->type->toBasetype ();
933 Type *etype = stype->nextOf ()->toBasetype ();
934
935 /* Determine if we need to run postblit or dtor. */
936 bool postblit = this->needs_postblit (etype) && this->lvalue_p (e->e2);
937 bool destructor = this->needs_dtor (etype);
938
939 if (e->memset & blockAssign)
940 {
941 /* Set a range of elements to one value. */
942 tree t1 = d_save_expr (build_expr (e->e1));
943 tree t2 = build_expr (e->e2);
944 tree result;
945
946 if ((postblit || destructor) && e->op != TOKblit)
947 {
948 libcall_fn libcall = (e->op == TOKconstruct)
949 ? LIBCALL_ARRAYSETCTOR : LIBCALL_ARRAYSETASSIGN;
950 /* So we can call postblits on const/immutable objects. */
951 Type *tm = etype->unSharedOf ()->mutableOf ();
952 tree ti = build_typeinfo (e->loc, tm);
953
954 tree result = build_libcall (libcall, Type::tvoid, 4,
955 d_array_ptr (t1),
956 build_address (t2),
957 d_array_length (t1), ti);
958 this->result_ = compound_expr (result, t1);
959 return;
960 }
961
962 if (integer_zerop (t2))
963 {
964 tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
965 tree size = size_mult_expr (d_array_length (t1),
966 size_int (etype->size ()));
967
968 result = build_call_expr (tmemset, 3, d_array_ptr (t1),
969 integer_zero_node, size);
970 }
971 else
972 result = build_array_set (d_array_ptr (t1),
973 d_array_length (t1), t2);
974
975 this->result_ = compound_expr (result, t1);
976 }
977 else
978 {
979 /* Perform a memcpy operation. */
980 gcc_assert (e->e2->type->ty != Tpointer);
981
982 if (!postblit && !destructor && !array_bounds_check ())
983 {
984 tree t1 = d_save_expr (d_array_convert (e->e1));
985 tree t2 = d_array_convert (e->e2);
986 tree tmemcpy = builtin_decl_explicit (BUILT_IN_MEMCPY);
987 tree size = size_mult_expr (d_array_length (t1),
988 size_int (etype->size ()));
989
990 tree result = build_call_expr (tmemcpy, 3, d_array_ptr (t1),
991 d_array_ptr (t2), size);
992 this->result_ = compound_expr (result, t1);
993 }
994 else if ((postblit || destructor) && e->op != TOKblit)
995 {
996 /* Generate: _d_arrayassign(ti, from, to)
997 or: _d_arrayctor(ti, from, to) */
998 libcall_fn libcall = (e->op == TOKconstruct)
999 ? LIBCALL_ARRAYCTOR : LIBCALL_ARRAYASSIGN;
1000
1001 this->result_ = build_libcall (libcall, e->type, 3,
1002 build_typeinfo (e->loc, etype),
1003 d_array_convert (e->e2),
1004 d_array_convert (e->e1));
1005 }
1006 else
1007 {
1008 /* Generate: _d_arraycopy() */
1009 this->result_ = build_libcall (LIBCALL_ARRAYCOPY, e->type, 3,
1010 size_int (etype->size ()),
1011 d_array_convert (e->e2),
1012 d_array_convert (e->e1));
1013 }
1014 }
1015
1016 return;
1017 }
1018
1019 /* Look for reference initializations. */
1020 if (e->memset & referenceInit)
1021 {
1022 gcc_assert (e->op == TOKconstruct || e->op == TOKblit);
1023 gcc_assert (e->e1->op == TOKvar);
1024
1025 Declaration *decl = ((VarExp *) e->e1)->var;
1026 if (decl->storage_class & (STCout | STCref))
1027 {
1028 tree t2 = convert_for_assignment (build_expr (e->e2),
1029 e->e2->type, e->e1->type);
1030 tree t1 = build_expr (e->e1);
1031 /* Want reference to lhs, not indirect ref. */
1032 t1 = TREE_OPERAND (t1, 0);
1033 t2 = build_address (t2);
1034
1035 this->result_ = indirect_ref (build_ctype (e->type),
1036 build_assign (INIT_EXPR, t1, t2));
1037 return;
1038 }
1039 }
1040
1041 /* Other types of assignments that may require post construction. */
1042 Type *tb1 = e->e1->type->toBasetype ();
1043 tree_code modifycode = (e->op == TOKconstruct) ? INIT_EXPR : MODIFY_EXPR;
1044
1045 /* Look for struct assignment. */
1046 if (tb1->ty == Tstruct)
1047 {
1048 tree t1 = build_expr (e->e1);
1049 tree t2 = convert_for_assignment (build_expr (e->e2),
1050 e->e2->type, e->e1->type);
1051 StructDeclaration *sd = ((TypeStruct *) tb1)->sym;
1052
1053 /* Look for struct = 0. */
1054 if (e->e2->op == TOKint64)
1055 {
1056 /* Use memset to fill struct. */
1057 gcc_assert (e->op == TOKblit);
1058 tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
1059 tree result = build_call_expr (tmemset, 3, build_address (t1),
1060 t2, size_int (sd->structsize));
1061
1062 /* Maybe set-up hidden pointer to outer scope context. */
1063 if (sd->isNested ())
1064 {
1065 tree field = get_symbol_decl (sd->vthis);
1066 tree value = build_vthis (sd);
1067
1068 tree vthis_exp = modify_expr (component_ref (t1, field), value);
1069 result = compound_expr (result, vthis_exp);
1070 }
1071
1072 this->result_ = compound_expr (result, t1);
1073 }
1074 else
1075 {
1076 /* Simple struct literal assignment. */
1077 tree init = NULL_TREE;
1078
1079 /* Fill any alignment holes in the struct using memset. */
1080 if (e->op == TOKconstruct && !identity_compare_p (sd))
1081 {
1082 tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
1083 init = build_call_expr (tmemset, 3, build_address (t1),
1084 integer_zero_node,
1085 size_int (sd->structsize));
1086 }
1087
1088 tree result = build_assign (modifycode, t1, t2);
1089 this->result_ = compound_expr (init, result);
1090 }
1091
1092 return;
1093 }
1094
1095 /* Look for static array assignment. */
1096 if (tb1->ty == Tsarray)
1097 {
1098 /* Look for array = 0. */
1099 if (e->e2->op == TOKint64)
1100 {
1101 /* Use memset to fill the array. */
1102 gcc_assert (e->op == TOKblit);
1103
1104 tree t1 = build_expr (e->e1);
1105 tree t2 = convert_for_assignment (build_expr (e->e2),
1106 e->e2->type, e->e1->type);
1107 tree size = size_int (e->e1->type->size ());
1108
1109 tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
1110 this->result_ = build_call_expr (tmemset, 3, build_address (t1),
1111 t2, size);
1112 return;
1113 }
1114
1115 Type *etype = tb1->nextOf ();
1116 gcc_assert (e->e2->type->toBasetype ()->ty == Tsarray);
1117
1118 /* Determine if we need to run postblit. */
1119 bool postblit = this->needs_postblit (etype);
1120 bool destructor = this->needs_dtor (etype);
1121 bool lvalue_p = this->lvalue_p (e->e2);
1122
1123 /* Even if the elements in rhs are all rvalues and don't have
1124 to call postblits, this assignment should call dtors on old
1125 assigned elements. */
1126 if ((!postblit && !destructor)
1127 || (e->op == TOKconstruct && !lvalue_p && postblit)
1128 || (e->op == TOKblit || e->e1->type->size () == 0))
1129 {
1130 tree t1 = build_expr (e->e1);
1131 tree t2 = convert_for_assignment (build_expr (e->e2),
1132 e->e2->type, e->e1->type);
1133
1134 this->result_ = build_assign (modifycode, t1, t2);
1135 return;
1136 }
1137
1138 Type *arrtype = (e->type->ty == Tsarray) ? etype->arrayOf () : e->type;
1139 tree result;
1140
1141 if (e->op == TOKconstruct)
1142 {
1143 /* Generate: _d_arrayctor(ti, from, to) */
1144 result = build_libcall (LIBCALL_ARRAYCTOR, arrtype, 3,
1145 build_typeinfo (e->loc, etype),
1146 d_array_convert (e->e2),
1147 d_array_convert (e->e1));
1148 }
1149 else
1150 {
1151 /* Generate: _d_arrayassign_l()
1152 or: _d_arrayassign_r() */
1153 libcall_fn libcall = (lvalue_p)
1154 ? LIBCALL_ARRAYASSIGN_L : LIBCALL_ARRAYASSIGN_R;
1155 tree elembuf = build_local_temp (build_ctype (etype));
1156
1157 result = build_libcall (libcall, arrtype, 4,
1158 build_typeinfo (e->loc, etype),
1159 d_array_convert (e->e2),
1160 d_array_convert (e->e1),
1161 build_address (elembuf));
1162 }
1163
1164 /* Cast the libcall result back to a static array. */
1165 if (e->type->ty == Tsarray)
1166 result = indirect_ref (build_ctype (e->type),
1167 d_array_ptr (result));
1168
1169 this->result_ = result;
1170 return;
1171 }
1172
1173 /* Simple assignment. */
1174 tree t1 = build_expr (e->e1);
1175 tree t2 = convert_for_assignment (build_expr (e->e2),
1176 e->e2->type, e->e1->type);
1177
1178 this->result_ = build_assign (modifycode, t1, t2);
1179 }
1180
1181 /* Build a postfix expression. */
1182
visit(PostExp * e)1183 void visit (PostExp *e)
1184 {
1185 tree result;
1186
1187 if (e->op == TOKplusplus)
1188 {
1189 result = build2 (POSTINCREMENT_EXPR, build_ctype (e->type),
1190 build_expr (e->e1), build_expr (e->e2));
1191 }
1192 else if (e->op == TOKminusminus)
1193 {
1194 result = build2 (POSTDECREMENT_EXPR, build_ctype (e->type),
1195 build_expr (e->e1), build_expr (e->e2));
1196 }
1197 else
1198 gcc_unreachable ();
1199
1200 TREE_SIDE_EFFECTS (result) = 1;
1201 this->result_ = result;
1202 }
1203
1204 /* Build an index expression. */
1205
visit(IndexExp * e)1206 void visit (IndexExp *e)
1207 {
1208 Type *tb1 = e->e1->type->toBasetype ();
1209
1210 if (tb1->ty == Taarray)
1211 {
1212 /* Get the key for the associative array. */
1213 Type *tkey = ((TypeAArray *) tb1)->index->toBasetype ();
1214 tree key = convert_expr (build_expr (e->e2), e->e2->type, tkey);
1215 libcall_fn libcall;
1216 tree tinfo, ptr;
1217
1218 if (e->modifiable)
1219 {
1220 libcall = LIBCALL_AAGETY;
1221 ptr = build_address (build_expr (e->e1));
1222 tinfo = build_typeinfo (e->loc, tb1->unSharedOf ()->mutableOf ());
1223 }
1224 else
1225 {
1226 libcall = LIBCALL_AAGETRVALUEX;
1227 ptr = build_expr (e->e1);
1228 tinfo = build_typeinfo (e->loc, tkey);
1229 }
1230
1231 /* Index the associative array. */
1232 tree result = build_libcall (libcall, e->type->pointerTo (), 4,
1233 ptr, tinfo,
1234 size_int (tb1->nextOf ()->size ()),
1235 build_address (key));
1236
1237 if (!e->indexIsInBounds && array_bounds_check ())
1238 {
1239 tree tassert = (global.params.checkAction == CHECKACTION_D)
1240 ? d_assert_call (e->loc, LIBCALL_ARRAY_BOUNDS)
1241 : build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1242
1243 result = d_save_expr (result);
1244 result = build_condition (TREE_TYPE (result),
1245 d_truthvalue_conversion (result),
1246 result, tassert);
1247 }
1248
1249 this->result_ = indirect_ref (build_ctype (e->type), result);
1250 }
1251 else
1252 {
1253 /* Get the data pointer and length for static and dynamic arrays. */
1254 tree array = d_save_expr (build_expr (e->e1));
1255 tree ptr = convert_expr (array, tb1, tb1->nextOf ()->pointerTo ());
1256
1257 tree length = NULL_TREE;
1258 if (tb1->ty != Tpointer)
1259 length = get_array_length (array, tb1);
1260 else
1261 gcc_assert (e->lengthVar == NULL);
1262
1263 /* The __dollar variable just becomes a placeholder for the
1264 actual length. */
1265 if (e->lengthVar)
1266 e->lengthVar->csym = length;
1267
1268 /* Generate the index. */
1269 tree index = build_expr (e->e2);
1270
1271 /* If it's a static array and the index is constant, the front end has
1272 already checked the bounds. */
1273 if (tb1->ty != Tpointer && !e->indexIsInBounds)
1274 index = build_bounds_condition (e->e2->loc, index, length, false);
1275
1276 /* Index the .ptr. */
1277 ptr = void_okay_p (ptr);
1278 this->result_ = indirect_ref (TREE_TYPE (TREE_TYPE (ptr)),
1279 build_array_index (ptr, index));
1280 }
1281 }
1282
1283 /* Build a comma expression. The type is the type of the right operand. */
1284
visit(CommaExp * e)1285 void visit (CommaExp *e)
1286 {
1287 tree t1 = build_expr (e->e1);
1288 tree t2 = build_expr (e->e2);
1289 tree type = e->type ? build_ctype (e->type) : void_type_node;
1290
1291 this->result_ = build2 (COMPOUND_EXPR, type, t1, t2);
1292 }
1293
1294 /* Build an array length expression. Returns the number of elements
1295 in the array. The result is of type size_t. */
1296
visit(ArrayLengthExp * e)1297 void visit (ArrayLengthExp *e)
1298 {
1299 if (e->e1->type->toBasetype ()->ty == Tarray)
1300 this->result_ = d_array_length (build_expr (e->e1));
1301 else
1302 {
1303 /* Static arrays have already been handled by the front-end. */
1304 error ("unexpected type for array length: %qs", e->type->toChars ());
1305 this->result_ = error_mark_node;
1306 }
1307 }
1308
1309 /* Build a delegate pointer expression. This will return the frame
1310 pointer value as a type void*. */
1311
visit(DelegatePtrExp * e)1312 void visit (DelegatePtrExp *e)
1313 {
1314 tree t1 = build_expr (e->e1);
1315 this->result_ = delegate_object (t1);
1316 }
1317
1318 /* Build a delegate function pointer expression. This will return the
1319 function pointer value as a function type. */
1320
visit(DelegateFuncptrExp * e)1321 void visit (DelegateFuncptrExp *e)
1322 {
1323 tree t1 = build_expr (e->e1);
1324 this->result_ = delegate_method (t1);
1325 }
1326
1327 /* Build a slice expression. */
1328
visit(SliceExp * e)1329 void visit (SliceExp *e)
1330 {
1331 Type *tb = e->type->toBasetype ();
1332 Type *tb1 = e->e1->type->toBasetype ();
1333 gcc_assert (tb->ty == Tarray || tb->ty == Tsarray);
1334
1335 /* Use convert-to-dynamic-array code if possible. */
1336 if (!e->lwr)
1337 {
1338 tree result = build_expr (e->e1);
1339 if (e->e1->type->toBasetype ()->ty == Tsarray)
1340 result = convert_expr (result, e->e1->type, e->type);
1341
1342 this->result_ = result;
1343 return;
1344 }
1345 else
1346 gcc_assert (e->upr != NULL);
1347
1348 /* Get the data pointer and length for static and dynamic arrays. */
1349 tree array = d_save_expr (build_expr (e->e1));
1350 tree ptr = convert_expr (array, tb1, tb1->nextOf ()->pointerTo ());
1351 tree length = NULL_TREE;
1352
1353 /* Our array is already a SAVE_EXPR if necessary, so we don't make length
1354 a SAVE_EXPR which is, at most, a COMPONENT_REF on top of array. */
1355 if (tb1->ty != Tpointer)
1356 length = get_array_length (array, tb1);
1357 else
1358 gcc_assert (e->lengthVar == NULL);
1359
1360 /* The __dollar variable just becomes a placeholder for the
1361 actual length. */
1362 if (e->lengthVar)
1363 e->lengthVar->csym = length;
1364
1365 /* Generate upper and lower bounds. */
1366 tree lwr_tree = d_save_expr (build_expr (e->lwr));
1367 tree upr_tree = d_save_expr (build_expr (e->upr));
1368
1369 /* If the upper bound has any side effects, then the lower bound should be
1370 copied to a temporary always. */
1371 if (TREE_CODE (upr_tree) == SAVE_EXPR && TREE_CODE (lwr_tree) != SAVE_EXPR)
1372 lwr_tree = save_expr (lwr_tree);
1373
1374 /* Adjust the .ptr offset. */
1375 if (!integer_zerop (lwr_tree))
1376 {
1377 tree ptrtype = TREE_TYPE (ptr);
1378 ptr = build_array_index (void_okay_p (ptr), lwr_tree);
1379 ptr = build_nop (ptrtype, ptr);
1380 }
1381 else
1382 lwr_tree = NULL_TREE;
1383
1384 /* Nothing more to do for static arrays, their bounds checking has been
1385 done at compile-time. */
1386 if (tb->ty == Tsarray)
1387 {
1388 this->result_ = indirect_ref (build_ctype (e->type), ptr);
1389 return;
1390 }
1391 else
1392 gcc_assert (tb->ty == Tarray);
1393
1394 /* Generate bounds checking code. */
1395 tree newlength;
1396
1397 if (!e->upperIsInBounds)
1398 {
1399 if (length)
1400 {
1401 newlength = build_bounds_condition (e->upr->loc, upr_tree,
1402 length, true);
1403 }
1404 else
1405 {
1406 /* Still need to check bounds lwr <= upr for pointers. */
1407 gcc_assert (tb1->ty == Tpointer);
1408 newlength = upr_tree;
1409 }
1410 }
1411 else
1412 newlength = upr_tree;
1413
1414 if (lwr_tree)
1415 {
1416 /* Enforces lwr <= upr. No need to check lwr <= length as
1417 we've already ensured that upr <= length. */
1418 if (!e->lowerIsLessThanUpper)
1419 {
1420 tree cond = build_bounds_condition (e->lwr->loc, lwr_tree,
1421 upr_tree, true);
1422
1423 /* When bounds checking is off, the index value is
1424 returned directly. */
1425 if (cond != lwr_tree)
1426 newlength = compound_expr (cond, newlength);
1427 }
1428
1429 /* Need to ensure lwr always gets evaluated first, as it may be a
1430 function call. Generates (lwr, upr) - lwr. */
1431 newlength = fold_build2 (MINUS_EXPR, TREE_TYPE (newlength),
1432 compound_expr (lwr_tree, newlength), lwr_tree);
1433 }
1434
1435 tree result = d_array_value (build_ctype (e->type), newlength, ptr);
1436 this->result_ = compound_expr (array, result);
1437 }
1438
1439 /* Build a cast expression, which converts the given unary expression to the
1440 type of result. */
1441
visit(CastExp * e)1442 void visit (CastExp *e)
1443 {
1444 Type *ebtype = e->e1->type->toBasetype ();
1445 Type *tbtype = e->to->toBasetype ();
1446 tree result = build_expr (e->e1, this->constp_);
1447
1448 /* Just evaluate e1 if it has any side effects. */
1449 if (tbtype->ty == Tvoid)
1450 this->result_ = build_nop (build_ctype (tbtype), result);
1451 else
1452 this->result_ = convert_expr (result, ebtype, tbtype);
1453 }
1454
1455 /* Build a delete expression. */
1456
visit(DeleteExp * e)1457 void visit (DeleteExp *e)
1458 {
1459 tree t1 = build_expr (e->e1);
1460 Type *tb1 = e->e1->type->toBasetype ();
1461
1462 if (tb1->ty == Tclass)
1463 {
1464 /* For class object references, if there is a destructor for that class,
1465 the destructor is called for the object instance. */
1466 libcall_fn libcall;
1467
1468 if (e->e1->op == TOKvar)
1469 {
1470 VarDeclaration *v = ((VarExp *) e->e1)->var->isVarDeclaration ();
1471 if (v && v->onstack)
1472 {
1473 libcall = tb1->isClassHandle ()->isInterfaceDeclaration ()
1474 ? LIBCALL_CALLINTERFACEFINALIZER : LIBCALL_CALLFINALIZER;
1475
1476 this->result_ = build_libcall (libcall, Type::tvoid, 1, t1);
1477 return;
1478 }
1479 }
1480
1481 /* Otherwise, the garbage collector is called to immediately free the
1482 memory allocated for the class instance. */
1483 libcall = tb1->isClassHandle ()->isInterfaceDeclaration ()
1484 ? LIBCALL_DELINTERFACE : LIBCALL_DELCLASS;
1485
1486 t1 = build_address (t1);
1487 this->result_ = build_libcall (libcall, Type::tvoid, 1, t1);
1488 }
1489 else if (tb1->ty == Tarray)
1490 {
1491 /* For dynamic arrays, the garbage collector is called to immediately
1492 release the memory. */
1493 Type *telem = tb1->nextOf ()->baseElemOf ();
1494 tree ti = null_pointer_node;
1495
1496 if (telem->ty == Tstruct)
1497 {
1498 /* Might need to run destructor on array contents. */
1499 TypeStruct *ts = (TypeStruct *) telem;
1500 if (ts->sym->dtor)
1501 ti = build_typeinfo (e->loc, tb1->nextOf ());
1502 }
1503
1504 /* Generate: _delarray_t (&t1, ti); */
1505 this->result_ = build_libcall (LIBCALL_DELARRAYT, Type::tvoid, 2,
1506 build_address (t1), ti);
1507 }
1508 else if (tb1->ty == Tpointer)
1509 {
1510 /* For pointers to a struct instance, if the struct has overloaded
1511 operator delete, then that operator is called. */
1512 t1 = build_address (t1);
1513 Type *tnext = ((TypePointer *)tb1)->next->toBasetype ();
1514
1515 if (tnext->ty == Tstruct)
1516 {
1517 TypeStruct *ts = (TypeStruct *)tnext;
1518 if (ts->sym->dtor)
1519 {
1520 tree ti = build_typeinfo (e->loc, tnext);
1521 this->result_ = build_libcall (LIBCALL_DELSTRUCT, Type::tvoid,
1522 2, t1, ti);
1523 return;
1524 }
1525 }
1526
1527 /* Otherwise, the garbage collector is called to immediately free the
1528 memory allocated for the pointer. */
1529 this->result_ = build_libcall (LIBCALL_DELMEMORY, Type::tvoid, 1, t1);
1530 }
1531 else
1532 {
1533 error ("don%'t know how to delete %qs", e->e1->toChars ());
1534 this->result_ = error_mark_node;
1535 }
1536 }
1537
1538 /* Build a remove expression, which removes a particular key from an
1539 associative array. */
1540
visit(RemoveExp * e)1541 void visit (RemoveExp *e)
1542 {
1543 /* Check that the array is actually an associative array. */
1544 if (e->e1->type->toBasetype ()->ty == Taarray)
1545 {
1546 Type *tb = e->e1->type->toBasetype ();
1547 Type *tkey = ((TypeAArray *) tb)->index->toBasetype ();
1548 tree index = convert_expr (build_expr (e->e2), e->e2->type, tkey);
1549
1550 this->result_ = build_libcall (LIBCALL_AADELX, Type::tbool, 3,
1551 build_expr (e->e1),
1552 build_typeinfo (e->loc, tkey),
1553 build_address (index));
1554 }
1555 else
1556 {
1557 error ("%qs is not an associative array", e->e1->toChars ());
1558 this->result_ = error_mark_node;
1559 }
1560 }
1561
1562 /* Build an unary not expression. */
1563
visit(NotExp * e)1564 void visit (NotExp *e)
1565 {
1566 tree result = convert_for_condition (build_expr (e->e1), e->e1->type);
1567 /* Need to convert to boolean type or this will fail. */
1568 result = fold_build1 (TRUTH_NOT_EXPR, d_bool_type, result);
1569
1570 this->result_ = d_convert (build_ctype (e->type), result);
1571 }
1572
1573 /* Build a compliment expression, where all the bits in the value are
1574 complemented. Note: unlike in C, the usual integral promotions
1575 are not performed prior to the complement operation. */
1576
visit(ComExp * e)1577 void visit (ComExp *e)
1578 {
1579 TY ty1 = e->e1->type->toBasetype ()->ty;
1580 gcc_assert (ty1 != Tarray && ty1 != Tsarray);
1581
1582 this->result_ = fold_build1 (BIT_NOT_EXPR, build_ctype (e->type),
1583 build_expr (e->e1));
1584 }
1585
1586 /* Build an unary negation expression. */
1587
visit(NegExp * e)1588 void visit (NegExp *e)
1589 {
1590 TY ty1 = e->e1->type->toBasetype ()->ty;
1591 gcc_assert (ty1 != Tarray && ty1 != Tsarray);
1592
1593 tree type = build_ctype (e->type);
1594 tree expr = build_expr (e->e1);
1595
1596 /* If the operation needs excess precision. */
1597 tree eptype = excess_precision_type (type);
1598 if (eptype != NULL_TREE)
1599 expr = d_convert (eptype, expr);
1600 else
1601 eptype = type;
1602
1603 tree ret = fold_build1 (NEGATE_EXPR, eptype, expr);
1604 this->result_ = d_convert (type, ret);
1605 }
1606
1607 /* Build a pointer index expression. */
1608
visit(PtrExp * e)1609 void visit (PtrExp *e)
1610 {
1611 Type *tnext = NULL;
1612 size_t offset;
1613 tree result;
1614
1615 if (e->e1->op == TOKadd)
1616 {
1617 BinExp *be = (BinExp *) e->e1;
1618 if (be->e1->op == TOKaddress
1619 && be->e2->isConst () && be->e2->type->isintegral ())
1620 {
1621 Expression *ae = ((AddrExp *) be->e1)->e1;
1622 tnext = ae->type->toBasetype ();
1623 result = build_expr (ae);
1624 offset = be->e2->toUInteger ();
1625 }
1626 }
1627 else if (e->e1->op == TOKsymoff)
1628 {
1629 SymOffExp *se = (SymOffExp *) e->e1;
1630 if (!declaration_reference_p (se->var))
1631 {
1632 tnext = se->var->type->toBasetype ();
1633 result = get_decl_tree (se->var);
1634 offset = se->offset;
1635 }
1636 }
1637
1638 /* Produce better code by converting *(#record + n) to
1639 COMPONENT_REFERENCE. Otherwise, the variable will always be
1640 allocated in memory because its address is taken. */
1641 if (tnext && tnext->ty == Tstruct)
1642 {
1643 StructDeclaration *sd = ((TypeStruct *) tnext)->sym;
1644
1645 for (size_t i = 0; i < sd->fields.dim; i++)
1646 {
1647 VarDeclaration *field = sd->fields[i];
1648
1649 if (field->offset == offset
1650 && same_type_p (field->type, e->type))
1651 {
1652 /* Catch errors, backend will ICE otherwise. */
1653 if (error_operand_p (result))
1654 this->result_ = result;
1655 else
1656 {
1657 result = component_ref (result, get_symbol_decl (field));
1658 this->result_ = result;
1659 }
1660 return;
1661 }
1662 else if (field->offset > offset)
1663 break;
1664 }
1665 }
1666
1667 this->result_ = indirect_ref (build_ctype (e->type), build_expr (e->e1));
1668 }
1669
1670 /* Build an unary address expression. */
1671
visit(AddrExp * e)1672 void visit (AddrExp *e)
1673 {
1674 tree type = build_ctype (e->type);
1675 tree exp;
1676
1677 /* The frontend optimizer can convert const symbol into a struct literal.
1678 Taking the address of a struct literal is otherwise illegal. */
1679 if (e->e1->op == TOKstructliteral)
1680 {
1681 StructLiteralExp *sle = ((StructLiteralExp *) e->e1)->origin;
1682 gcc_assert (sle != NULL);
1683
1684 /* Build the reference symbol, the decl is built first as the
1685 initializer may have recursive references. */
1686 if (!sle->sym)
1687 {
1688 sle->sym = build_artificial_decl (build_ctype (sle->type),
1689 NULL_TREE, "S");
1690 DECL_INITIAL (sle->sym) = build_expr (sle, true);
1691 d_pushdecl (sle->sym);
1692 rest_of_decl_compilation (sle->sym, 1, 0);
1693 }
1694
1695 exp = sle->sym;
1696 }
1697 else
1698 exp = build_expr (e->e1, this->constp_);
1699
1700 TREE_CONSTANT (exp) = 0;
1701 this->result_ = d_convert (type, build_address (exp));
1702 }
1703
1704 /* Build a function call expression. */
1705
visit(CallExp * e)1706 void visit (CallExp *e)
1707 {
1708 Type *tb = e->e1->type->toBasetype ();
1709 Expression *e1b = e->e1;
1710
1711 tree callee = NULL_TREE;
1712 tree object = NULL_TREE;
1713 tree cleanup = NULL_TREE;
1714 TypeFunction *tf = NULL;
1715
1716 /* Calls to delegates can sometimes look like this. */
1717 if (e1b->op == TOKcomma)
1718 {
1719 e1b = ((CommaExp *) e1b)->e2;
1720 gcc_assert (e1b->op == TOKvar);
1721
1722 Declaration *var = ((VarExp *) e1b)->var;
1723 gcc_assert (var->isFuncDeclaration () && !var->needThis ());
1724 }
1725
1726 if (e1b->op == TOKdotvar && tb->ty != Tdelegate)
1727 {
1728 DotVarExp *dve = (DotVarExp *) e1b;
1729
1730 /* Don't modify the static initializer for struct literals. */
1731 if (dve->e1->op == TOKstructliteral)
1732 {
1733 StructLiteralExp *sle = (StructLiteralExp *) dve->e1;
1734 sle->useStaticInit = false;
1735 }
1736
1737 FuncDeclaration *fd = dve->var->isFuncDeclaration ();
1738 if (fd != NULL)
1739 {
1740 /* Get the correct callee from the DotVarExp object. */
1741 tree fndecl = get_symbol_decl (fd);
1742 AggregateDeclaration *ad = fd->isThis ();
1743
1744 /* Static method; ignore the object instance. */
1745 if (!ad)
1746 callee = build_address (fndecl);
1747 else
1748 {
1749 tree thisexp = build_expr (dve->e1);
1750
1751 /* When constructing temporaries, if the constructor throws,
1752 then the object is destructed even though it is not a fully
1753 constructed object yet. And so this call will need to be
1754 moved inside the TARGET_EXPR_INITIAL slot. */
1755 if (fd->isCtorDeclaration ()
1756 && TREE_CODE (thisexp) == COMPOUND_EXPR
1757 && TREE_CODE (TREE_OPERAND (thisexp, 0)) == TARGET_EXPR
1758 && TARGET_EXPR_CLEANUP (TREE_OPERAND (thisexp, 0)))
1759 {
1760 cleanup = TREE_OPERAND (thisexp, 0);
1761 thisexp = TREE_OPERAND (thisexp, 1);
1762 }
1763
1764 /* Want reference to 'this' object. */
1765 if (!POINTER_TYPE_P (TREE_TYPE (thisexp)))
1766 thisexp = build_address (thisexp);
1767
1768 /* Make the callee a virtual call. */
1769 if (fd->isVirtual () && !fd->isFinalFunc () && !e->directcall)
1770 {
1771 tree fntype = build_pointer_type (TREE_TYPE (fndecl));
1772 tree thistype = build_ctype (ad->handleType ());
1773 thisexp = build_nop (thistype, d_save_expr (thisexp));
1774 fndecl = build_vindex_ref (thisexp, fntype, fd->vtblIndex);
1775 }
1776 else
1777 fndecl = build_address (fndecl);
1778
1779 callee = build_method_call (fndecl, thisexp, fd->type);
1780 }
1781 }
1782 }
1783
1784 if (callee == NULL_TREE)
1785 callee = build_expr (e1b);
1786
1787 if (METHOD_CALL_EXPR (callee))
1788 {
1789 /* This could be a delegate expression (TY == Tdelegate), but not
1790 actually a delegate variable. */
1791 if (e1b->op == TOKdotvar)
1792 {
1793 /* This gets the true function type, getting the function type
1794 from e1->type can sometimes be incorrect, such as when calling
1795 a 'ref' return function. */
1796 tf = get_function_type (((DotVarExp *) e1b)->var->type);
1797 }
1798 else
1799 tf = get_function_type (tb);
1800
1801 extract_from_method_call (callee, callee, object);
1802 }
1803 else if (tb->ty == Tdelegate)
1804 {
1805 /* Delegate call, extract .object and .funcptr from var. */
1806 callee = d_save_expr (callee);
1807 tf = get_function_type (tb);
1808 object = delegate_object (callee);
1809 callee = delegate_method (callee);
1810 }
1811 else if (e1b->op == TOKvar)
1812 {
1813 FuncDeclaration *fd = ((VarExp *) e1b)->var->isFuncDeclaration ();
1814 gcc_assert (fd != NULL);
1815 tf = get_function_type (fd->type);
1816
1817 if (fd->isNested ())
1818 {
1819 /* Maybe re-evaluate symbol storage treating 'fd' as public. */
1820 if (call_by_alias_p (d_function_chain->function, fd))
1821 TREE_PUBLIC (callee) = 1;
1822
1823 object = get_frame_for_symbol (fd);
1824 }
1825 else if (fd->needThis ())
1826 {
1827 error_at (make_location_t (e1b->loc),
1828 "need %<this%> to access member %qs", fd->toChars ());
1829 /* Continue compiling... */
1830 object = null_pointer_node;
1831 }
1832 }
1833 else
1834 {
1835 /* Normal direct function call. */
1836 tf = get_function_type (tb);
1837 }
1838
1839 gcc_assert (tf != NULL);
1840
1841 /* Now we have the type, callee and maybe object reference,
1842 build the call expression. */
1843 tree exp = d_build_call (tf, callee, object, e->arguments);
1844
1845 if (tf->isref)
1846 exp = build_deref (exp);
1847
1848 /* Some library calls are defined to return a generic type.
1849 this->type is the real type we want to return. */
1850 if (e->type->isTypeBasic ())
1851 exp = d_convert (build_ctype (e->type), exp);
1852
1853 /* If this call was found to be a constructor for a temporary with a
1854 cleanup, then move the call inside the TARGET_EXPR. The original
1855 initializer is turned into an assignment, to keep its side effect. */
1856 if (cleanup != NULL_TREE)
1857 {
1858 tree init = TARGET_EXPR_INITIAL (cleanup);
1859 tree slot = TARGET_EXPR_SLOT (cleanup);
1860 d_mark_addressable (slot);
1861 init = build_assign (INIT_EXPR, slot, init);
1862
1863 TARGET_EXPR_INITIAL (cleanup) = compound_expr (init, exp);
1864 exp = cleanup;
1865 }
1866
1867 this->result_ = exp;
1868 }
1869
1870 /* Build a delegate expression. */
1871
visit(DelegateExp * e)1872 void visit (DelegateExp *e)
1873 {
1874 if (e->func->semanticRun == PASSsemantic3done)
1875 {
1876 /* Add the function as nested function if it belongs to this module.
1877 ie: it is a member of this module, or it is a template instance. */
1878 Dsymbol *owner = e->func->toParent ();
1879 while (!owner->isTemplateInstance () && owner->toParent ())
1880 owner = owner->toParent ();
1881 if (owner->isTemplateInstance () || owner == d_function_chain->module)
1882 build_decl_tree (e->func);
1883 }
1884
1885 tree fndecl;
1886 tree object;
1887
1888 if (e->func->isNested ())
1889 {
1890 if (e->e1->op == TOKnull)
1891 object = build_expr (e->e1);
1892 else
1893 object = get_frame_for_symbol (e->func);
1894
1895 fndecl = build_address (get_symbol_decl (e->func));
1896 }
1897 else
1898 {
1899 if (!e->func->isThis ())
1900 {
1901 error ("delegates are only for non-static functions");
1902 this->result_ = error_mark_node;
1903 return;
1904 }
1905
1906 object = build_expr (e->e1);
1907
1908 /* Want reference to `this' object. */
1909 if (e->e1->type->ty != Tclass && e->e1->type->ty != Tpointer)
1910 object = build_address (object);
1911
1912 /* Object reference could be the outer `this' field of a class or
1913 closure of type `void*'. Cast it to the right type. */
1914 if (e->e1->type->ty == Tclass)
1915 object = d_convert (build_ctype (e->e1->type), object);
1916
1917 fndecl = get_symbol_decl (e->func);
1918
1919 /* Get pointer to function out of the virtual table. */
1920 if (e->func->isVirtual () && !e->func->isFinalFunc ()
1921 && e->e1->op != TOKsuper && e->e1->op != TOKdottype)
1922 {
1923 tree fntype = build_pointer_type (TREE_TYPE (fndecl));
1924 object = d_save_expr (object);
1925 fndecl = build_vindex_ref (object, fntype, e->func->vtblIndex);
1926 }
1927 else
1928 fndecl = build_address (fndecl);
1929 }
1930
1931 this->result_ = build_method_call (fndecl, object, e->type);
1932 }
1933
1934 /* Build a type component expression. */
1935
visit(DotTypeExp * e)1936 void visit (DotTypeExp *e)
1937 {
1938 /* Just a pass through to underlying expression. */
1939 this->result_ = build_expr (e->e1);
1940 }
1941
1942 /* Build a component reference expression. */
1943
visit(DotVarExp * e)1944 void visit (DotVarExp *e)
1945 {
1946 VarDeclaration *vd = e->var->isVarDeclaration ();
1947
1948 /* This could also be a function, but relying on that being taken
1949 care of by the visitor interface for CallExp. */
1950 if (vd != NULL)
1951 {
1952 if (!vd->isField ())
1953 this->result_ = get_decl_tree (vd);
1954 else
1955 {
1956 tree object = build_expr (e->e1);
1957
1958 if (e->e1->type->toBasetype ()->ty != Tstruct)
1959 object = build_deref (object);
1960
1961 this->result_ = component_ref (object, get_symbol_decl (vd));
1962 }
1963 }
1964 else
1965 {
1966 error ("%qs is not a field, but a %qs",
1967 e->var->toChars (), e->var->kind ());
1968 this->result_ = error_mark_node;
1969 }
1970 }
1971
1972 /* Build an assert expression, used to declare conditions that must hold at
1973 that a given point in the program. */
1974
visit(AssertExp * e)1975 void visit (AssertExp *e)
1976 {
1977 Type *tb1 = e->e1->type->toBasetype ();
1978 tree arg = build_expr (e->e1);
1979 tree tmsg = NULL_TREE;
1980 tree assert_pass = void_node;
1981 tree assert_fail;
1982
1983 if (global.params.useAssert
1984 && global.params.checkAction == CHECKACTION_D)
1985 {
1986 /* Generate: ((bool) e1 ? (void)0 : _d_assert (...))
1987 or: (e1 != null ? e1._invariant() : _d_assert (...)) */
1988 bool unittest_p = d_function_chain->function->isUnitTestDeclaration ();
1989 libcall_fn libcall;
1990
1991 if (e->msg)
1992 {
1993 tmsg = build_expr_dtor (e->msg);
1994 libcall = unittest_p ? LIBCALL_UNITTEST_MSG : LIBCALL_ASSERT_MSG;
1995 }
1996 else
1997 libcall = unittest_p ? LIBCALL_UNITTEST : LIBCALL_ASSERT;
1998
1999 /* Build a call to _d_assert(). */
2000 assert_fail = d_assert_call (e->loc, libcall, tmsg);
2001
2002 if (global.params.useInvariants)
2003 {
2004 /* If the condition is a D class or struct object with an invariant,
2005 call it if the condition result is true. */
2006 if (tb1->ty == Tclass)
2007 {
2008 ClassDeclaration *cd = tb1->isClassHandle ();
2009 if (!cd->isInterfaceDeclaration () && !cd->isCPPclass ())
2010 {
2011 arg = d_save_expr (arg);
2012 assert_pass = build_libcall (LIBCALL_INVARIANT,
2013 Type::tvoid, 1, arg);
2014 }
2015 }
2016 else if (tb1->ty == Tpointer && tb1->nextOf ()->ty == Tstruct)
2017 {
2018 StructDeclaration *sd = ((TypeStruct *) tb1->nextOf ())->sym;
2019 if (sd->inv != NULL)
2020 {
2021 Expressions args;
2022 arg = d_save_expr (arg);
2023 assert_pass = d_build_call_expr (sd->inv, arg, &args);
2024 }
2025 }
2026 }
2027 }
2028 else if (global.params.useAssert
2029 && global.params.checkAction == CHECKACTION_C)
2030 {
2031 /* Generate: __builtin_trap() */
2032 tree fn = builtin_decl_explicit (BUILT_IN_TRAP);
2033 assert_fail = build_call_expr (fn, 0);
2034 }
2035 else
2036 {
2037 /* Assert contracts are turned off, if the contract condition has no
2038 side effects can still use it as a predicate for the optimizer. */
2039 if (TREE_SIDE_EFFECTS (arg))
2040 {
2041 this->result_ = void_node;
2042 return;
2043 }
2044
2045 assert_fail = build_predict_expr (PRED_NORETURN, NOT_TAKEN);
2046 }
2047
2048 /* Build condition that we are asserting in this contract. */
2049 tree condition = convert_for_condition (arg, e->e1->type);
2050
2051 /* We expect the condition to always be true, as what happens if an assert
2052 contract is false is undefined behavior. */
2053 tree fn = builtin_decl_explicit (BUILT_IN_EXPECT);
2054 tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
2055 tree pred_type = TREE_VALUE (arg_types);
2056 tree expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
2057
2058 condition = build_call_expr (fn, 2, d_convert (pred_type, condition),
2059 build_int_cst (expected_type, 1));
2060 condition = d_truthvalue_conversion (condition);
2061
2062 this->result_ = build_vcondition (condition, assert_pass, assert_fail);
2063 }
2064
2065 /* Build a declaration expression. */
2066
visit(DeclarationExp * e)2067 void visit (DeclarationExp *e)
2068 {
2069 /* Compile the declaration. */
2070 push_stmt_list ();
2071 build_decl_tree (e->declaration);
2072 tree result = pop_stmt_list ();
2073
2074 /* Construction of an array for typesafe-variadic function arguments
2075 can cause an empty STMT_LIST here. This can causes problems
2076 during gimplification. */
2077 if (TREE_CODE (result) == STATEMENT_LIST && !STATEMENT_LIST_HEAD (result))
2078 result = build_empty_stmt (input_location);
2079
2080 this->result_ = result;
2081 }
2082
2083 /* Build a typeid expression. Returns an instance of class TypeInfo
2084 corresponding to. */
2085
visit(TypeidExp * e)2086 void visit (TypeidExp *e)
2087 {
2088 if (Type *tid = isType (e->obj))
2089 {
2090 tree ti = build_typeinfo (e->loc, tid);
2091
2092 /* If the typeinfo is at an offset. */
2093 if (tid->vtinfo->offset)
2094 ti = build_offset (ti, size_int (tid->vtinfo->offset));
2095
2096 this->result_ = build_nop (build_ctype (e->type), ti);
2097 }
2098 else if (Expression *tid = isExpression (e->obj))
2099 {
2100 Type *type = tid->type->toBasetype ();
2101 assert (type->ty == Tclass);
2102
2103 /* Generate **classptr to get the classinfo. */
2104 tree ci = build_expr (tid);
2105 ci = indirect_ref (ptr_type_node, ci);
2106 ci = indirect_ref (ptr_type_node, ci);
2107
2108 /* Add extra indirection for interfaces. */
2109 if (((TypeClass *) type)->sym->isInterfaceDeclaration ())
2110 ci = indirect_ref (ptr_type_node, ci);
2111
2112 this->result_ = build_nop (build_ctype (e->type), ci);
2113 }
2114 else
2115 gcc_unreachable ();
2116 }
2117
2118 /* Build a function/lambda expression. */
2119
visit(FuncExp * e)2120 void visit (FuncExp *e)
2121 {
2122 Type *ftype = e->type->toBasetype ();
2123
2124 /* This check is for lambda's, remove 'vthis' as function isn't nested. */
2125 if (e->fd->tok == TOKreserved && ftype->ty == Tpointer)
2126 {
2127 e->fd->tok = TOKfunction;
2128 e->fd->vthis = NULL;
2129 }
2130
2131 /* Compile the function literal body. */
2132 build_decl_tree (e->fd);
2133
2134 /* If nested, this will be a trampoline. */
2135 if (e->fd->isNested ())
2136 {
2137 tree func = build_address (get_symbol_decl (e->fd));
2138 tree object;
2139
2140 if (this->constp_)
2141 {
2142 /* Static delegate variables have no context pointer. */
2143 object = null_pointer_node;
2144 this->result_ = build_method_call (func, object, e->fd->type);
2145 TREE_CONSTANT (this->result_) = 1;
2146 }
2147 else
2148 {
2149 object = get_frame_for_symbol (e->fd);
2150 this->result_ = build_method_call (func, object, e->fd->type);
2151 }
2152 }
2153 else
2154 {
2155 this->result_ = build_nop (build_ctype (e->type),
2156 build_address (get_symbol_decl (e->fd)));
2157 }
2158 }
2159
2160 /* Build a halt expression. */
2161
visit(HaltExp *)2162 void visit (HaltExp *)
2163 {
2164 /* Should we use trap() or abort()? */
2165 tree ttrap = builtin_decl_explicit (BUILT_IN_TRAP);
2166 this->result_ = build_call_expr (ttrap, 0);
2167 }
2168
2169 /* Build a symbol pointer offset expression. */
2170
visit(SymOffExp * e)2171 void visit (SymOffExp *e)
2172 {
2173 /* Build the address and offset of the symbol. */
2174 size_t soffset = ((SymOffExp *) e)->offset;
2175 tree result = get_decl_tree (e->var);
2176 TREE_USED (result) = 1;
2177
2178 if (declaration_reference_p (e->var))
2179 gcc_assert (POINTER_TYPE_P (TREE_TYPE (result)));
2180 else
2181 result = build_address (result);
2182
2183 if (!soffset)
2184 result = d_convert (build_ctype (e->type), result);
2185 else
2186 {
2187 tree offset = size_int (soffset);
2188 result = build_nop (build_ctype (e->type),
2189 build_offset (result, offset));
2190 }
2191
2192 this->result_ = result;
2193 }
2194
2195 /* Build a variable expression. */
2196
visit(VarExp * e)2197 void visit (VarExp *e)
2198 {
2199 if (e->var->needThis ())
2200 {
2201 error ("need %<this%> to access member %qs", e->var->ident->toChars ());
2202 this->result_ = error_mark_node;
2203 return;
2204 }
2205 else if (e->var->ident == Identifier::idPool ("__ctfe"))
2206 {
2207 /* __ctfe is always false at run-time. */
2208 this->result_ = integer_zero_node;
2209 return;
2210 }
2211
2212 /* This check is same as is done in FuncExp for lambdas. */
2213 FuncLiteralDeclaration *fld = e->var->isFuncLiteralDeclaration ();
2214 if (fld != NULL)
2215 {
2216 if (fld->tok == TOKreserved)
2217 {
2218 fld->tok = TOKfunction;
2219 fld->vthis = NULL;
2220 }
2221
2222 /* Compiler the function literal body. */
2223 build_decl_tree (fld);
2224 }
2225
2226 if (this->constp_)
2227 {
2228 /* Want the initializer, not the expression. */
2229 VarDeclaration *var = e->var->isVarDeclaration ();
2230 SymbolDeclaration *sd = e->var->isSymbolDeclaration ();
2231 tree init = NULL_TREE;
2232
2233 if (var && (var->isConst () || var->isImmutable ())
2234 && e->type->toBasetype ()->ty != Tsarray && var->_init)
2235 {
2236 if (var->inuse)
2237 error_at (make_location_t (e->loc), "recursive reference %qs",
2238 e->toChars ());
2239 else
2240 {
2241 var->inuse++;
2242 init = build_expr (initializerToExpression (var->_init), true);
2243 var->inuse--;
2244 }
2245 }
2246 else if (sd && sd->dsym)
2247 init = layout_struct_initializer (sd->dsym);
2248 else
2249 error_at (make_location_t (e->loc), "non-constant expression %qs",
2250 e->toChars ());
2251
2252 if (init != NULL_TREE)
2253 this->result_ = init;
2254 else
2255 this->result_ = error_mark_node;
2256 }
2257 else
2258 {
2259 tree result = get_decl_tree (e->var);
2260 TREE_USED (result) = 1;
2261
2262 /* For variables that are references - currently only out/inout
2263 arguments; objects don't count - evaluating the variable means
2264 we want what it refers to. */
2265 if (declaration_reference_p (e->var))
2266 result = indirect_ref (build_ctype (e->var->type), result);
2267
2268 this->result_ = result;
2269 }
2270 }
2271
2272 /* Build a this variable expression. */
2273
visit(ThisExp * e)2274 void visit (ThisExp *e)
2275 {
2276 FuncDeclaration *fd = d_function_chain ? d_function_chain->function : NULL;
2277 tree result = NULL_TREE;
2278
2279 if (e->var)
2280 result = get_decl_tree (e->var);
2281 else
2282 {
2283 gcc_assert (fd && fd->vthis);
2284 result = get_decl_tree (fd->vthis);
2285 }
2286
2287 if (e->type->ty == Tstruct)
2288 result = build_deref (result);
2289
2290 this->result_ = result;
2291 }
2292
2293 /* Build a new expression, which allocates memory either on the garbage
2294 collected heap or by using a class or struct specific allocator. */
2295
visit(NewExp * e)2296 void visit (NewExp *e)
2297 {
2298 Type *tb = e->type->toBasetype ();
2299 tree result;
2300
2301 if (e->allocator)
2302 gcc_assert (e->newargs);
2303
2304 if (tb->ty == Tclass)
2305 {
2306 /* Allocating a new class. */
2307 tb = e->newtype->toBasetype ();
2308 gcc_assert (tb->ty == Tclass);
2309
2310 ClassDeclaration *cd = ((TypeClass *) tb)->sym;
2311 tree type = build_ctype (tb);
2312 tree setup_exp = NULL_TREE;
2313 tree new_call;
2314
2315 if (e->onstack)
2316 {
2317 /* If being used as an initializer for a local variable with scope
2318 storage class, then the instance is allocated on the stack
2319 rather than the heap or using the class specific allocator. */
2320 tree var = build_local_temp (TREE_TYPE (type));
2321 new_call = build_nop (type, build_address (var));
2322 setup_exp = modify_expr (var, aggregate_initializer_decl (cd));
2323 }
2324 else if (e->allocator)
2325 {
2326 /* Call class allocator, and copy the initializer into memory. */
2327 new_call = d_build_call_expr (e->allocator, NULL_TREE, e->newargs);
2328 new_call = d_save_expr (new_call);
2329 new_call = build_nop (type, new_call);
2330 setup_exp = modify_expr (build_deref (new_call),
2331 aggregate_initializer_decl (cd));
2332 }
2333 else
2334 {
2335 /* Generate: _d_newclass() */
2336 tree arg = build_address (get_classinfo_decl (cd));
2337 new_call = build_libcall (LIBCALL_NEWCLASS, tb, 1, arg);
2338 }
2339
2340 /* Set the context pointer for nested classes. */
2341 if (cd->isNested ())
2342 {
2343 tree field = get_symbol_decl (cd->vthis);
2344 tree value = NULL_TREE;
2345
2346 if (e->thisexp)
2347 {
2348 ClassDeclaration *tcd = e->thisexp->type->isClassHandle ();
2349 Dsymbol *outer = cd->toParent2 ();
2350 int offset = 0;
2351
2352 value = build_expr (e->thisexp);
2353 if (outer != tcd)
2354 {
2355 ClassDeclaration *ocd = outer->isClassDeclaration ();
2356 gcc_assert (ocd->isBaseOf (tcd, &offset));
2357 /* Could just add offset... */
2358 value = convert_expr (value, e->thisexp->type, ocd->type);
2359 }
2360 }
2361 else
2362 value = build_vthis (cd);
2363
2364 if (value != NULL_TREE)
2365 {
2366 /* Generate: (new())->vthis = this; */
2367 new_call = d_save_expr (new_call);
2368 field = component_ref (build_deref (new_call), field);
2369 setup_exp = compound_expr (setup_exp,
2370 modify_expr (field, value));
2371 }
2372 }
2373 new_call = compound_expr (setup_exp, new_call);
2374
2375 /* Call the class constructor. */
2376 if (e->member)
2377 result = d_build_call_expr (e->member, new_call, e->arguments);
2378 else
2379 result = new_call;
2380
2381 if (e->argprefix)
2382 result = compound_expr (build_expr (e->argprefix), result);
2383 }
2384 else if (tb->ty == Tpointer && tb->nextOf ()->toBasetype ()->ty == Tstruct)
2385 {
2386 /* Allocating memory for a new struct. */
2387 Type *htype = e->newtype->toBasetype ();
2388 gcc_assert (htype->ty == Tstruct);
2389 gcc_assert (!e->onstack);
2390
2391 TypeStruct *stype = (TypeStruct *) htype;
2392 StructDeclaration *sd = stype->sym;
2393 tree new_call;
2394
2395 /* Cannot new an opaque struct. */
2396 if (sd->size (e->loc) == 0)
2397 {
2398 this->result_ = d_convert (build_ctype (e->type),
2399 integer_zero_node);
2400 return;
2401 }
2402
2403 if (e->allocator)
2404 {
2405 /* Call struct allocator. */
2406 new_call = d_build_call_expr (e->allocator, NULL_TREE, e->newargs);
2407 new_call = build_nop (build_ctype (tb), new_call);
2408 }
2409 else
2410 {
2411 /* Generate: _d_newitemT() */
2412 libcall_fn libcall = htype->isZeroInit ()
2413 ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
2414 tree arg = build_typeinfo (e->loc, e->newtype);
2415 new_call = build_libcall (libcall, tb, 1, arg);
2416 }
2417
2418 if (e->member || !e->arguments)
2419 {
2420 /* Set the context pointer for nested structs. */
2421 if (sd->isNested ())
2422 {
2423 tree value = build_vthis (sd);
2424 tree field = get_symbol_decl (sd->vthis);
2425 tree type = build_ctype (stype);
2426
2427 new_call = d_save_expr (new_call);
2428 field = component_ref (indirect_ref (type, new_call), field);
2429 new_call = compound_expr (modify_expr (field, value), new_call);
2430 }
2431
2432 /* Call the struct constructor. */
2433 if (e->member)
2434 result = d_build_call_expr (e->member, new_call, e->arguments);
2435 else
2436 result = new_call;
2437 }
2438 else
2439 {
2440 /* If we have a user supplied initializer, then set-up with a
2441 struct literal. */
2442 if (e->arguments != NULL && sd->fields.dim != 0)
2443 {
2444 StructLiteralExp *se = StructLiteralExp::create (e->loc, sd,
2445 e->arguments,
2446 htype);
2447 new_call = d_save_expr (new_call);
2448 se->type = sd->type;
2449 se->sym = new_call;
2450 result = compound_expr (build_expr (se), new_call);
2451 }
2452 else
2453 result = new_call;
2454 }
2455
2456 if (e->argprefix)
2457 result = compound_expr (build_expr (e->argprefix), result);
2458 }
2459 else if (tb->ty == Tarray)
2460 {
2461 /* Allocating memory for a new D array. */
2462 tb = e->newtype->toBasetype ();
2463 gcc_assert (tb->ty == Tarray);
2464 TypeDArray *tarray = (TypeDArray *) tb;
2465
2466 gcc_assert (!e->allocator);
2467 gcc_assert (e->arguments && e->arguments->dim >= 1);
2468
2469 if (e->arguments->dim == 1)
2470 {
2471 /* Single dimension array allocations. */
2472 Expression *arg = (*e->arguments)[0];
2473
2474 if (tarray->next->size () == 0)
2475 {
2476 /* Array element size is unknown. */
2477 this->result_ = d_array_value (build_ctype (e->type),
2478 size_int (0), null_pointer_node);
2479 return;
2480 }
2481
2482 libcall_fn libcall = tarray->next->isZeroInit ()
2483 ? LIBCALL_NEWARRAYT : LIBCALL_NEWARRAYIT;
2484 result = build_libcall (libcall, tb, 2,
2485 build_typeinfo (e->loc, e->type),
2486 build_expr (arg));
2487 }
2488 else
2489 {
2490 /* Multidimensional array allocations. */
2491 tree tarray = make_array_type (Type::tsize_t, e->arguments->dim);
2492 tree var = build_local_temp (tarray);
2493 vec<constructor_elt, va_gc> *elms = NULL;
2494
2495 /* Get the base element type for the array, generating the
2496 initializer for the dims parameter along the way. */
2497 Type *telem = e->newtype->toBasetype ();
2498 for (size_t i = 0; i < e->arguments->dim; i++)
2499 {
2500 Expression *arg = (*e->arguments)[i];
2501 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), build_expr (arg));
2502
2503 gcc_assert (telem->ty == Tarray);
2504 telem = telem->toBasetype ()->nextOf ();
2505 gcc_assert (telem);
2506 }
2507
2508 /* Initialize the temporary. */
2509 tree init = modify_expr (var, build_constructor (tarray, elms));
2510 var = compound_expr (init, var);
2511
2512 /* Generate: _d_newarraymTX(ti, dims)
2513 or: _d_newarraymiTX(ti, dims) */
2514 libcall_fn libcall = telem->isZeroInit ()
2515 ? LIBCALL_NEWARRAYMTX : LIBCALL_NEWARRAYMITX;
2516
2517 tree tinfo = build_typeinfo (e->loc, e->type);
2518 tree dims = d_array_value (build_ctype (Type::tsize_t->arrayOf ()),
2519 size_int (e->arguments->dim),
2520 build_address (var));
2521
2522 result = build_libcall (libcall, tb, 2, tinfo, dims);
2523 }
2524
2525 if (e->argprefix)
2526 result = compound_expr (build_expr (e->argprefix), result);
2527 }
2528 else if (tb->ty == Tpointer)
2529 {
2530 /* Allocating memory for a new pointer. */
2531 TypePointer *tpointer = (TypePointer *) tb;
2532
2533 if (tpointer->next->size () == 0)
2534 {
2535 /* Pointer element size is unknown. */
2536 this->result_ = d_convert (build_ctype (e->type),
2537 integer_zero_node);
2538 return;
2539 }
2540
2541 libcall_fn libcall = tpointer->next->isZeroInit (e->loc)
2542 ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
2543
2544 tree arg = build_typeinfo (e->loc, e->newtype);
2545 result = build_libcall (libcall, tb, 1, arg);
2546
2547 if (e->arguments && e->arguments->dim == 1)
2548 {
2549 result = d_save_expr (result);
2550 tree init = modify_expr (build_deref (result),
2551 build_expr ((*e->arguments)[0]));
2552 result = compound_expr (init, result);
2553 }
2554
2555 if (e->argprefix)
2556 result = compound_expr (build_expr (e->argprefix), result);
2557 }
2558 else
2559 gcc_unreachable ();
2560
2561 this->result_ = convert_expr (result, tb, e->type);
2562 }
2563
2564 /* Build an integer literal. */
2565
visit(IntegerExp * e)2566 void visit (IntegerExp *e)
2567 {
2568 tree ctype = build_ctype (e->type->toBasetype ());
2569 this->result_ = build_integer_cst (e->value, ctype);
2570 }
2571
2572 /* Build a floating-point literal. */
2573
visit(RealExp * e)2574 void visit (RealExp *e)
2575 {
2576 this->result_ = build_float_cst (e->value, e->type->toBasetype ());
2577 }
2578
2579 /* Build a complex literal. */
2580
visit(ComplexExp * e)2581 void visit (ComplexExp *e)
2582 {
2583 Type *tnext;
2584
2585 switch (e->type->toBasetype ()->ty)
2586 {
2587 case Tcomplex32:
2588 tnext = (TypeBasic *) Type::tfloat32;
2589 break;
2590
2591 case Tcomplex64:
2592 tnext = (TypeBasic *) Type::tfloat64;
2593 break;
2594
2595 case Tcomplex80:
2596 tnext = (TypeBasic *) Type::tfloat80;
2597 break;
2598
2599 default:
2600 gcc_unreachable ();
2601 }
2602
2603 this->result_ = build_complex (build_ctype (e->type),
2604 build_float_cst (creall (e->value), tnext),
2605 build_float_cst (cimagl (e->value), tnext));
2606 }
2607
2608 /* Build a string literal, all strings are null terminated except for
2609 static arrays. */
2610
visit(StringExp * e)2611 void visit (StringExp *e)
2612 {
2613 Type *tb = e->type->toBasetype ();
2614 tree type = build_ctype (e->type);
2615
2616 if (tb->ty == Tsarray)
2617 {
2618 /* Turn the string into a constructor for the static array. */
2619 vec<constructor_elt, va_gc> *elms = NULL;
2620 vec_safe_reserve (elms, e->len);
2621 tree etype = TREE_TYPE (type);
2622
2623 for (size_t i = 0; i < e->len; i++)
2624 {
2625 tree value = build_integer_cst (e->charAt (i), etype);
2626 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
2627 }
2628
2629 tree ctor = build_constructor (type, elms);
2630 TREE_CONSTANT (ctor) = 1;
2631 this->result_ = ctor;
2632 }
2633 else
2634 {
2635 /* Copy the string contents to a null terminated string. */
2636 dinteger_t length = (e->len * e->sz);
2637 char *string = XALLOCAVEC (char, length + 1);
2638 memcpy (string, e->string, length);
2639 string[length] = '\0';
2640
2641 /* String value and type includes the null terminator. */
2642 tree value = build_string (length, string);
2643 TREE_TYPE (value) = make_array_type (tb->nextOf (), length + 1);
2644 value = build_address (value);
2645
2646 if (tb->ty == Tarray)
2647 value = d_array_value (type, size_int (e->len), value);
2648
2649 TREE_CONSTANT (value) = 1;
2650 this->result_ = d_convert (type, value);
2651 }
2652 }
2653
2654 /* Build a tuple literal. Just an argument list that may have
2655 side effects that need evaluation. */
2656
visit(TupleExp * e)2657 void visit (TupleExp *e)
2658 {
2659 tree result = NULL_TREE;
2660
2661 if (e->e0)
2662 result = build_expr (e->e0);
2663
2664 for (size_t i = 0; i < e->exps->dim; ++i)
2665 {
2666 Expression *exp = (*e->exps)[i];
2667 result = compound_expr (result, build_expr (exp));
2668 }
2669
2670 if (result == NULL_TREE)
2671 result = void_node;
2672
2673 this->result_ = result;
2674 }
2675
2676 /* Build an array literal. The common type of the all elements is taken to
2677 be the type of the array element, and all elements are implicitly
2678 converted to that type. */
2679
visit(ArrayLiteralExp * e)2680 void visit (ArrayLiteralExp *e)
2681 {
2682 Type *tb = e->type->toBasetype ();
2683
2684 /* Implicitly convert void[n] to ubyte[n]. */
2685 if (tb->ty == Tsarray && tb->nextOf ()->toBasetype ()->ty == Tvoid)
2686 tb = Type::tuns8->sarrayOf (((TypeSArray *) tb)->dim->toUInteger ());
2687
2688 gcc_assert (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tpointer);
2689
2690 /* Handle empty array literals. */
2691 if (e->elements->dim == 0)
2692 {
2693 if (tb->ty == Tarray)
2694 this->result_ = d_array_value (build_ctype (e->type),
2695 size_int (0), null_pointer_node);
2696 else
2697 this->result_ = build_constructor (make_array_type (tb->nextOf (), 0),
2698 NULL);
2699
2700 return;
2701 }
2702
2703 /* Build an expression that assigns the expressions in ELEMENTS to
2704 a constructor. */
2705 vec<constructor_elt, va_gc> *elms = NULL;
2706 vec_safe_reserve (elms, e->elements->dim);
2707 bool constant_p = true;
2708 tree saved_elems = NULL_TREE;
2709
2710 Type *etype = tb->nextOf ();
2711 tree satype = make_array_type (etype, e->elements->dim);
2712
2713 for (size_t i = 0; i < e->elements->dim; i++)
2714 {
2715 Expression *expr = e->getElement (i);
2716 tree value = build_expr (expr, this->constp_);
2717
2718 /* Only append nonzero values, the backend will zero out the rest
2719 of the constructor as we don't set CONSTRUCTOR_NO_CLEARING. */
2720 if (!initializer_zerop (value))
2721 {
2722 if (!TREE_CONSTANT (value))
2723 constant_p = false;
2724
2725 /* Split construction of values out of the constructor if there
2726 may be side effects. */
2727 tree init = stabilize_expr (&value);
2728 if (init != NULL_TREE)
2729 saved_elems = compound_expr (saved_elems, init);
2730
2731 CONSTRUCTOR_APPEND_ELT (elms, size_int (i),
2732 convert_expr (value, expr->type, etype));
2733 }
2734 }
2735
2736 /* Now return the constructor as the correct type. For static arrays there
2737 is nothing else to do. For dynamic arrays, return a two field struct.
2738 For pointers, return the address. */
2739 tree ctor = build_constructor (satype, elms);
2740 tree type = build_ctype (e->type);
2741
2742 /* Nothing else to do for static arrays. */
2743 if (tb->ty == Tsarray || this->constp_)
2744 {
2745 /* Can't take the address of the constructor, so create an anonymous
2746 static symbol, and then refer to it. */
2747 if (tb->ty != Tsarray)
2748 {
2749 tree decl = build_artificial_decl (TREE_TYPE (ctor), ctor, "A");
2750 ctor = build_address (decl);
2751 if (tb->ty == Tarray)
2752 ctor = d_array_value (type, size_int (e->elements->dim), ctor);
2753
2754 d_pushdecl (decl);
2755 rest_of_decl_compilation (decl, 1, 0);
2756 }
2757
2758 /* If the array literal is readonly or static. */
2759 if (constant_p)
2760 TREE_CONSTANT (ctor) = 1;
2761 if (constant_p && initializer_constant_valid_p (ctor, TREE_TYPE (ctor)))
2762 TREE_STATIC (ctor) = 1;
2763
2764 this->result_ = compound_expr (saved_elems, d_convert (type, ctor));
2765 }
2766 else
2767 {
2768 /* Allocate space on the memory managed heap. */
2769 tree mem = build_libcall (LIBCALL_ARRAYLITERALTX,
2770 etype->pointerTo (), 2,
2771 build_typeinfo (e->loc, etype->arrayOf ()),
2772 size_int (e->elements->dim));
2773 mem = d_save_expr (mem);
2774
2775 /* Now copy the constructor into memory. */
2776 tree tmemcpy = builtin_decl_explicit (BUILT_IN_MEMCPY);
2777 tree size = size_mult_expr (size_int (e->elements->dim),
2778 size_int (tb->nextOf ()->size ()));
2779
2780 tree result = build_call_expr (tmemcpy, 3, mem,
2781 build_address (ctor), size);
2782
2783 /* Return the array pointed to by MEM. */
2784 result = compound_expr (result, mem);
2785
2786 if (tb->ty == Tarray)
2787 result = d_array_value (type, size_int (e->elements->dim), result);
2788
2789 this->result_ = compound_expr (saved_elems, result);
2790 }
2791 }
2792
2793 /* Build an associative array literal. The common type of the all keys is
2794 taken to be the key type, and common type of all values the value type.
2795 All keys and values are then implicitly converted as needed. */
2796
visit(AssocArrayLiteralExp * e)2797 void visit (AssocArrayLiteralExp *e)
2798 {
2799 /* Want the mutable type for typeinfo reference. */
2800 Type *tb = e->type->toBasetype ()->mutableOf ();
2801 gcc_assert (tb->ty == Taarray);
2802
2803 /* Handle empty assoc array literals. */
2804 TypeAArray *ta = (TypeAArray *) tb;
2805 if (e->keys->dim == 0)
2806 {
2807 this->result_ = build_constructor (build_ctype (ta), NULL);
2808 return;
2809 }
2810
2811 /* Build an expression that assigns all expressions in KEYS
2812 to a constructor. */
2813 vec<constructor_elt, va_gc> *kelts = NULL;
2814 vec_safe_reserve (kelts, e->keys->dim);
2815 for (size_t i = 0; i < e->keys->dim; i++)
2816 {
2817 Expression *key = (*e->keys)[i];
2818 tree t = build_expr (key);
2819 CONSTRUCTOR_APPEND_ELT (kelts, size_int (i),
2820 convert_expr (t, key->type, ta->index));
2821 }
2822 tree tkeys = make_array_type (ta->index, e->keys->dim);
2823 tree akeys = build_constructor (tkeys, kelts);
2824
2825 /* Do the same with all expressions in VALUES. */
2826 vec<constructor_elt, va_gc> *velts = NULL;
2827 vec_safe_reserve (velts, e->values->dim);
2828 for (size_t i = 0; i < e->values->dim; i++)
2829 {
2830 Expression *value = (*e->values)[i];
2831 tree t = build_expr (value);
2832 CONSTRUCTOR_APPEND_ELT (velts, size_int (i),
2833 convert_expr (t, value->type, ta->next));
2834 }
2835 tree tvals = make_array_type (ta->next, e->values->dim);
2836 tree avals = build_constructor (tvals, velts);
2837
2838 /* Generate: _d_assocarrayliteralTX (ti, keys, vals); */
2839 tree keys = d_array_value (build_ctype (ta->index->arrayOf ()),
2840 size_int (e->keys->dim), build_address (akeys));
2841 tree vals = d_array_value (build_ctype (ta->next->arrayOf ()),
2842 size_int (e->values->dim),
2843 build_address (avals));
2844
2845 tree mem = build_libcall (LIBCALL_ASSOCARRAYLITERALTX, Type::tvoidptr, 3,
2846 build_typeinfo (e->loc, ta), keys, vals);
2847
2848 /* Return an associative array pointed to by MEM. */
2849 tree aatype = build_ctype (ta);
2850 vec<constructor_elt, va_gc> *ce = NULL;
2851 CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (aatype), mem);
2852
2853 this->result_ = build_nop (build_ctype (e->type),
2854 build_constructor (aatype, ce));
2855 }
2856
2857 /* Build a struct literal. */
2858
visit(StructLiteralExp * e)2859 void visit (StructLiteralExp *e)
2860 {
2861 /* Handle empty struct literals. */
2862 if (e->elements == NULL || e->sd->fields.dim == 0)
2863 {
2864 this->result_ = build_constructor (build_ctype (e->type), NULL);
2865 return;
2866 }
2867
2868 /* Building sinit trees are delayed until after frontend semantic
2869 processing has complete. Build the static initializer now. */
2870 if (e->useStaticInit && !this->constp_)
2871 {
2872 this->result_ = aggregate_initializer_decl (e->sd);
2873 return;
2874 }
2875
2876 /* Build a constructor that assigns the expressions in ELEMENTS
2877 at each field index that has been filled in. */
2878 vec<constructor_elt, va_gc> *ve = NULL;
2879 tree saved_elems = NULL_TREE;
2880
2881 /* CTFE may fill the hidden pointer by NullExp. */
2882 gcc_assert (e->elements->dim <= e->sd->fields.dim);
2883
2884 Type *tb = e->type->toBasetype ();
2885 gcc_assert (tb->ty == Tstruct);
2886
2887 for (size_t i = 0; i < e->elements->dim; i++)
2888 {
2889 Expression *exp = (*e->elements)[i];
2890 if (!exp)
2891 continue;
2892
2893 VarDeclaration *field = e->sd->fields[i];
2894 Type *type = exp->type->toBasetype ();
2895 Type *ftype = field->type->toBasetype ();
2896 tree value = NULL_TREE;
2897
2898 if (ftype->ty == Tsarray && !same_type_p (type, ftype))
2899 {
2900 /* Initialize a static array with a single element. */
2901 tree elem = build_expr (exp, this->constp_);
2902 elem = d_save_expr (elem);
2903
2904 if (initializer_zerop (elem))
2905 value = build_constructor (build_ctype (ftype), NULL);
2906 else
2907 value = build_array_from_val (ftype, elem);
2908 }
2909 else
2910 {
2911 value = convert_expr (build_expr (exp, this->constp_),
2912 exp->type, field->type);
2913 }
2914
2915 /* Split construction of values out of the constructor. */
2916 tree init = stabilize_expr (&value);
2917 if (init != NULL_TREE)
2918 saved_elems = compound_expr (saved_elems, init);
2919
2920 CONSTRUCTOR_APPEND_ELT (ve, get_symbol_decl (field), value);
2921 }
2922
2923 /* Maybe setup hidden pointer to outer scope context. */
2924 if (e->sd->isNested () && e->elements->dim != e->sd->fields.dim
2925 && this->constp_ == false)
2926 {
2927 tree field = get_symbol_decl (e->sd->vthis);
2928 tree value = build_vthis (e->sd);
2929 CONSTRUCTOR_APPEND_ELT (ve, field, value);
2930 gcc_assert (e->useStaticInit == false);
2931 }
2932
2933 /* Build a constructor in the correct shape of the aggregate type. */
2934 tree ctor = build_struct_literal (build_ctype (e->type), ve);
2935
2936 /* Nothing more to do for constant literals. */
2937 if (this->constp_)
2938 {
2939 /* If the struct literal is a valid for static data. */
2940 if (TREE_CONSTANT (ctor)
2941 && initializer_constant_valid_p (ctor, TREE_TYPE (ctor)))
2942 TREE_STATIC (ctor) = 1;
2943
2944 this->result_ = compound_expr (saved_elems, ctor);
2945 return;
2946 }
2947
2948 if (e->sym != NULL)
2949 {
2950 tree var = build_deref (e->sym);
2951 ctor = compound_expr (modify_expr (var, ctor), var);
2952 this->result_ = compound_expr (saved_elems, ctor);
2953 }
2954 else if (e->sd->isUnionDeclaration ())
2955 {
2956 /* For unions, use memset to fill holes in the object. */
2957 tree var = build_local_temp (TREE_TYPE (ctor));
2958 tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
2959 tree init = build_call_expr (tmemset, 3, build_address (var),
2960 size_zero_node,
2961 size_int (e->sd->structsize));
2962
2963 init = compound_expr (init, saved_elems);
2964 init = compound_expr (init, modify_expr (var, ctor));
2965 this->result_ = compound_expr (init, var);
2966 }
2967 else
2968 this->result_ = compound_expr (saved_elems, ctor);
2969 }
2970
2971 /* Build a null literal. */
2972
visit(NullExp * e)2973 void visit (NullExp *e)
2974 {
2975 this->result_ = build_typeof_null_value (e->type);
2976 }
2977
2978 /* Build a vector literal. */
2979
visit(VectorExp * e)2980 void visit (VectorExp *e)
2981 {
2982 tree type = build_ctype (e->type);
2983 tree etype = TREE_TYPE (type);
2984
2985 /* First handle array literal expressions. */
2986 if (e->e1->op == TOKarrayliteral)
2987 {
2988 ArrayLiteralExp *ale = ((ArrayLiteralExp *) e->e1);
2989 vec<constructor_elt, va_gc> *elms = NULL;
2990 bool constant_p = true;
2991
2992 vec_safe_reserve (elms, ale->elements->dim);
2993 for (size_t i = 0; i < ale->elements->dim; i++)
2994 {
2995 Expression *expr = ale->getElement (i);
2996 tree value = d_convert (etype, build_expr (expr, this->constp_));
2997 if (!CONSTANT_CLASS_P (value))
2998 constant_p = false;
2999
3000 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
3001 }
3002
3003 /* Build a VECTOR_CST from a constant vector constructor. */
3004 if (constant_p)
3005 this->result_ = build_vector_from_ctor (type, elms);
3006 else
3007 this->result_ = build_constructor (type, elms);
3008 }
3009 else
3010 {
3011 /* Build constructor from single value. */
3012 tree val = d_convert (etype, build_expr (e->e1, this->constp_));
3013 this->result_ = build_vector_from_val (type, val);
3014 }
3015 }
3016
3017 /* Build a static array representation of a vector expression. */
3018
visit(VectorArrayExp * e)3019 void visit (VectorArrayExp *e)
3020 {
3021 this->result_ = convert_expr (build_expr (e->e1, this->constp_),
3022 e->e1->type, e->type);
3023 }
3024
3025 /* Build a static class literal, return its reference. */
3026
visit(ClassReferenceExp * e)3027 void visit (ClassReferenceExp *e)
3028 {
3029 /* The result of build_new_class_expr is a RECORD_TYPE, we want
3030 the reference. */
3031 tree var = build_address (build_new_class_expr (e));
3032
3033 /* If the type of this literal is an interface, the we must add the
3034 interface offset to symbol. */
3035 if (this->constp_)
3036 {
3037 TypeClass *tc = (TypeClass *) e->type;
3038 InterfaceDeclaration *to = tc->sym->isInterfaceDeclaration ();
3039
3040 if (to != NULL)
3041 {
3042 ClassDeclaration *from = e->originalClass ();
3043 int offset = 0;
3044
3045 gcc_assert (to->isBaseOf (from, &offset) != 0);
3046
3047 if (offset != 0)
3048 var = build_offset (var, size_int (offset));
3049 }
3050 }
3051
3052 this->result_ = var;
3053 }
3054
3055 /* These expressions are mainly just a placeholders in the frontend.
3056 We shouldn't see them here. */
3057
visit(ScopeExp * e)3058 void visit (ScopeExp *e)
3059 {
3060 error_at (make_location_t (e->loc), "%qs is not an expression",
3061 e->toChars ());
3062 this->result_ = error_mark_node;
3063 }
3064
visit(TypeExp * e)3065 void visit (TypeExp *e)
3066 {
3067 error_at (make_location_t (e->loc), "type %qs is not an expression",
3068 e->toChars ());
3069 this->result_ = error_mark_node;
3070 }
3071 };
3072
3073
3074 /* Main entry point for ExprVisitor interface to generate code for
3075 the Expression AST class E. If CONST_P is true, then E is a
3076 constant expression. */
3077
3078 tree
build_expr(Expression * e,bool const_p)3079 build_expr (Expression *e, bool const_p)
3080 {
3081 ExprVisitor v = ExprVisitor (const_p);
3082 location_t saved_location = input_location;
3083
3084 input_location = make_location_t (e->loc);
3085 e->accept (&v);
3086 tree expr = v.result ();
3087 input_location = saved_location;
3088
3089 /* Check if initializer expression is valid constant. */
3090 if (const_p && !initializer_constant_valid_p (expr, TREE_TYPE (expr)))
3091 {
3092 error_at (make_location_t (e->loc), "non-constant expression %qs",
3093 e->toChars ());
3094 return error_mark_node;
3095 }
3096
3097 return expr;
3098 }
3099
3100 /* Same as build_expr, but also calls destructors on any temporaries. */
3101
3102 tree
build_expr_dtor(Expression * e)3103 build_expr_dtor (Expression *e)
3104 {
3105 /* Codegen can be improved by determining if no exceptions can be thrown
3106 between the ctor and dtor, and eliminating the ctor and dtor. */
3107 size_t saved_vars = vec_safe_length (d_function_chain->vars_in_scope);
3108 tree result = build_expr (e);
3109
3110 if (saved_vars != vec_safe_length (d_function_chain->vars_in_scope))
3111 {
3112 result = fold_build_cleanup_point_expr (TREE_TYPE (result), result);
3113 vec_safe_truncate (d_function_chain->vars_in_scope, saved_vars);
3114 }
3115
3116 return result;
3117 }
3118
3119 /* Same as build_expr_dtor, but handles the result of E as a return value. */
3120
3121 tree
build_return_dtor(Expression * e,Type * type,TypeFunction * tf)3122 build_return_dtor (Expression *e, Type *type, TypeFunction *tf)
3123 {
3124 size_t saved_vars = vec_safe_length (d_function_chain->vars_in_scope);
3125 tree result = build_expr (e);
3126
3127 /* Convert for initializing the DECL_RESULT. */
3128 result = convert_expr (result, e->type, type);
3129
3130 /* If we are returning a reference, take the address. */
3131 if (tf->isref)
3132 result = build_address (result);
3133
3134 /* The decl to store the return expression. */
3135 tree decl = DECL_RESULT (cfun->decl);
3136
3137 /* Split comma expressions, so that the result is returned directly. */
3138 tree expr = stabilize_expr (&result);
3139 result = build_assign (INIT_EXPR, decl, result);
3140 result = compound_expr (expr, return_expr (result));
3141
3142 /* May nest the return expression inside the try/finally expression. */
3143 if (saved_vars != vec_safe_length (d_function_chain->vars_in_scope))
3144 {
3145 result = fold_build_cleanup_point_expr (TREE_TYPE (result), result);
3146 vec_safe_truncate (d_function_chain->vars_in_scope, saved_vars);
3147 }
3148
3149 return result;
3150 }
3151
3152