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