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