1 /* expr.cc -- Lower D frontend expressions to GCC trees.
2 Copyright (C) 2015-2023 Free Software Foundation, Inc.
4 GCC is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
9 GCC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with GCC; see the file COPYING3. If not see
16 <http://www.gnu.org/licenses/>. */
20 #include "coretypes.h"
22 #include "dmd/aggregate.h"
24 #include "dmd/declaration.h"
26 #include "dmd/expression.h"
27 #include "dmd/identifier.h"
29 #include "dmd/module.h"
30 #include "dmd/mtype.h"
31 #include "dmd/template.h"
34 #include "fold-const.h"
35 #include "diagnostic.h"
36 #include "langhooks.h"
42 #include "stor-layout.h"
47 /* Determine if type T is a struct that has a postblit. */
50 needs_postblit (Type
*t
)
54 if (TypeStruct
*ts
= t
->isTypeStruct ())
56 if (ts
->sym
->postblit
)
63 /* Determine if type T is a struct that has a destructor. */
70 if (TypeStruct
*ts
= t
->isTypeStruct ())
79 /* Determine if expression E is a suitable lvalue. */
82 lvalue_p (Expression
*e
)
84 SliceExp
*se
= e
->isSliceExp ();
85 if (se
!= NULL
&& se
->e1
->isLvalue ())
88 CastExp
*ce
= e
->isCastExp ();
89 if (ce
!= NULL
&& ce
->e1
->isLvalue ())
92 return (e
->op
!= EXP::slice
&& e
->isLvalue ());
95 /* Build an expression of code CODE, data type TYPE, and operands ARG0 and
96 ARG1. Perform relevant conversions needed for correct code operations. */
99 binary_op (tree_code code
, tree type
, tree arg0
, tree arg1
)
101 tree t0
= TREE_TYPE (arg0
);
102 tree t1
= TREE_TYPE (arg1
);
103 tree ret
= NULL_TREE
;
105 /* Deal with float mod expressions immediately. */
106 if (code
== FLOAT_MOD_EXPR
)
107 return build_float_modulus (type
, arg0
, arg1
);
109 if (POINTER_TYPE_P (t0
) && INTEGRAL_TYPE_P (t1
))
110 return build_nop (type
, build_offset_op (code
, arg0
, arg1
));
112 if (INTEGRAL_TYPE_P (t0
) && POINTER_TYPE_P (t1
))
113 return build_nop (type
, build_offset_op (code
, arg1
, arg0
));
115 if (POINTER_TYPE_P (t0
) && POINTER_TYPE_P (t1
))
117 gcc_assert (code
== MINUS_EXPR
);
118 tree ptrtype
= lang_hooks
.types
.type_for_mode (ptr_mode
, 0);
120 /* POINTER_DIFF_EXPR requires a signed integer type of the same size as
121 pointers. If some platform cannot provide that, or has a larger
122 ptrdiff_type to support differences larger than half the address
123 space, cast the pointers to some larger integer type and do the
124 computations in that type. */
125 if (TYPE_PRECISION (ptrtype
) > TYPE_PRECISION (t0
))
126 ret
= fold_build2 (MINUS_EXPR
, ptrtype
,
127 d_convert (ptrtype
, arg0
),
128 d_convert (ptrtype
, arg1
));
130 ret
= fold_build2 (POINTER_DIFF_EXPR
, ptrtype
, arg0
, arg1
);
134 /* If the operation needs excess precision. */
135 tree eptype
= excess_precision_type (type
);
136 if (eptype
!= NULL_TREE
)
138 arg0
= d_convert (eptype
, arg0
);
139 arg1
= d_convert (eptype
, arg1
);
143 /* Front-end does not do this conversion and GCC does not
144 always do it right. */
145 if (COMPLEX_FLOAT_TYPE_P (t0
) && !COMPLEX_FLOAT_TYPE_P (t1
))
146 arg1
= d_convert (t0
, arg1
);
147 else if (COMPLEX_FLOAT_TYPE_P (t1
) && !COMPLEX_FLOAT_TYPE_P (t0
))
148 arg0
= d_convert (t1
, arg0
);
153 ret
= build2 (code
, eptype
, arg0
, arg1
);
156 return d_convert (type
, ret
);
159 /* Build a binary expression of code CODE, assigning the result into E1. */
162 binop_assignment (tree_code code
, Expression
*e1
, Expression
*e2
)
164 /* Skip casts for lhs assignment. */
165 Expression
*e1b
= e1
;
166 while (e1b
->op
== EXP::cast_
)
168 CastExp
*ce
= e1b
->isCastExp ();
169 gcc_assert (same_type_p (ce
->type
, ce
->to
));
173 /* Stabilize LHS for assignment. */
174 tree lhs
= build_expr (e1b
);
175 tree lexpr
= stabilize_expr (&lhs
);
177 /* The LHS expression could be an assignment, to which its operation gets
178 lost during gimplification. */
179 if (TREE_CODE (lhs
) == MODIFY_EXPR
)
181 /* If LHS has side effects, call stabilize_reference on it, so it can
182 be evaluated multiple times. */
183 if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs
, 0)))
184 lhs
= build_assign (MODIFY_EXPR
,
185 stabilize_reference (TREE_OPERAND (lhs
, 0)),
186 TREE_OPERAND (lhs
, 1));
188 lexpr
= compound_expr (lexpr
, lhs
);
189 lhs
= TREE_OPERAND (lhs
, 0);
192 lhs
= stabilize_reference (lhs
);
194 /* Save RHS, to ensure that the expression is evaluated before LHS. */
195 tree rhs
= build_expr (e2
);
196 tree rexpr
= d_save_expr (rhs
);
198 rhs
= binary_op (code
, build_ctype (e1
->type
),
199 convert_expr (lhs
, e1b
->type
, e1
->type
), rexpr
);
200 if (TREE_SIDE_EFFECTS (rhs
))
201 rhs
= compound_expr (rexpr
, rhs
);
203 tree expr
= modify_expr (lhs
, convert_expr (rhs
, e1
->type
, e1b
->type
));
204 return compound_expr (lexpr
, expr
);
207 /* Implements the visitor interface to build the GCC trees of all Expression
208 AST classes emitted from the D Front-end.
209 All visit methods accept one parameter E, which holds the frontend AST
210 of the expression to compile. They also don't return any value, instead
211 generated code is cached in RESULT_ and returned from the caller. */
213 class ExprVisitor
: public Visitor
215 using Visitor::visit
;
222 ExprVisitor (bool constp
, bool literalp
)
224 this->result_
= NULL_TREE
;
225 this->constp_
= constp
;
226 this->literalp_
= literalp
;
231 return this->result_
;
234 /* Visitor interfaces, each Expression class should have
235 overridden the default. */
237 void visit (Expression
*) final override
242 /* Build a conditional expression. If either the second or third
243 expression is void, then the resulting type is void. Otherwise
244 they are implicitly converted to a common type. */
246 void visit (CondExp
*e
) final override
248 tree cond
= convert_for_condition (build_expr (e
->econd
),
250 tree t1
= build_expr (e
->e1
);
251 tree t2
= build_expr (e
->e2
);
253 if (e
->type
->ty
!= TY::Tvoid
)
255 t1
= convert_expr (t1
, e
->e1
->type
, e
->type
);
256 t2
= convert_expr (t2
, e
->e2
->type
, e
->type
);
259 this->result_
= build_condition (build_ctype (e
->type
), cond
, t1
, t2
);
262 /* Build an identity comparison expression. Operands go through the
263 usual conversions to bring them to a common type before comparison.
264 The result type is bool. */
266 void visit (IdentityExp
*e
) final override
268 tree_code code
= (e
->op
== EXP::identity
) ? EQ_EXPR
: NE_EXPR
;
269 Type
*tb1
= e
->e1
->type
->toBasetype ();
270 Type
*tb2
= e
->e2
->type
->toBasetype ();
272 if ((tb1
->ty
== TY::Tsarray
|| tb1
->ty
== TY::Tarray
)
273 && (tb2
->ty
== TY::Tsarray
|| tb2
->ty
== TY::Tarray
))
275 /* For static and dynamic arrays, identity is defined as referring to
276 the same array elements and the same number of elements. */
277 tree t1
= d_array_convert (e
->e1
);
278 tree t2
= d_array_convert (e
->e2
);
279 this->result_
= d_convert (build_ctype (e
->type
),
280 build_boolop (code
, t1
, t2
));
282 else if (tb1
->isfloating () && tb1
->ty
!= TY::Tvector
)
284 /* For floating-point values, identity is defined as the bits in the
285 operands being identical. */
286 tree t1
= d_save_expr (build_expr (e
->e1
));
287 tree t2
= d_save_expr (build_expr (e
->e2
));
289 if (!tb1
->iscomplex ())
290 this->result_
= build_float_identity (code
, t1
, t2
);
293 /* Compare the real and imaginary parts separately. */
294 tree req
= build_float_identity (code
, real_part (t1
),
296 tree ieq
= build_float_identity (code
, imaginary_part (t1
),
297 imaginary_part (t2
));
300 this->result_
= build_boolop (TRUTH_ANDIF_EXPR
, req
, ieq
);
302 this->result_
= build_boolop (TRUTH_ORIF_EXPR
, req
, ieq
);
305 else if (TypeStruct
*ts
= tb1
->isTypeStruct ())
307 /* For struct objects, identity is defined as bits in operands being
308 identical also. Alignment holes in structs are ignored. */
309 tree t1
= build_expr (e
->e1
);
310 tree t2
= build_expr (e
->e2
);
312 gcc_assert (same_type_p (tb1
, tb2
));
314 this->result_
= build_struct_comparison (code
, ts
->sym
, t1
, t2
);
318 /* For operands of other types, identity is defined as being the
319 same as equality expressions. */
320 tree t1
= build_expr (e
->e1
);
321 tree t2
= build_expr (e
->e2
);
322 this->result_
= d_convert (build_ctype (e
->type
),
323 build_boolop (code
, t1
, t2
));
327 /* Build an equality expression, which compare the two operands for either
328 equality or inequality. Operands go through the usual conversions to bring
329 them to a common type before comparison. The result type is bool. */
331 void visit (EqualExp
*e
) final override
333 Type
*tb1
= e
->e1
->type
->toBasetype ();
334 Type
*tb2
= e
->e2
->type
->toBasetype ();
335 tree_code code
= (e
->op
== EXP::equal
) ? EQ_EXPR
: NE_EXPR
;
337 if ((tb1
->ty
== TY::Tsarray
|| tb1
->ty
== TY::Tarray
)
338 && (tb2
->ty
== TY::Tsarray
|| tb2
->ty
== TY::Tarray
))
340 /* For static and dynamic arrays, equality is defined as the lengths of
341 the arrays matching, and all the elements are equal. */
342 Type
*t1elem
= tb1
->nextOf ()->toBasetype ();
343 Type
*t2elem
= tb1
->nextOf ()->toBasetype ();
345 /* Check if comparisons of arrays can be optimized using memcmp.
346 This will inline EQ expressions as:
347 e1.length == e2.length && memcmp(e1.ptr, e2.ptr, size) == 0;
348 Or when generating a NE expression:
349 e1.length != e2.length || memcmp(e1.ptr, e2.ptr, size) != 0; */
350 if ((t1elem
->isintegral () || t1elem
->ty
== TY::Tvoid
351 || (t1elem
->ty
== TY::Tstruct
352 && !t1elem
->isTypeStruct ()->sym
->xeq
))
353 && t1elem
->ty
== t2elem
->ty
)
355 tree t1
= d_array_convert (e
->e1
);
356 tree t2
= d_array_convert (e
->e2
);
359 /* Make temporaries to prevent multiple evaluations. */
360 tree t1saved
= d_save_expr (t1
);
361 tree t2saved
= d_save_expr (t2
);
363 /* Length of arrays, for comparisons done before calling memcmp. */
364 tree t1len
= d_array_length (t1saved
);
365 tree t2len
= d_array_length (t2saved
);
367 /* Reference to array data. */
368 tree t1ptr
= d_array_ptr (t1saved
);
369 tree t2ptr
= d_array_ptr (t2saved
);
371 /* Compare arrays using memcmp if possible, otherwise for structs,
372 each field is compared inline. */
373 if (t1elem
->ty
!= TY::Tstruct
374 || identity_compare_p (t1elem
->isTypeStruct ()->sym
))
376 tree size
= size_mult_expr (t1len
, size_int (t1elem
->size ()));
378 result
= build_memcmp_call (t1ptr
, t2ptr
, size
);
379 result
= build_boolop (code
, result
, integer_zero_node
);
383 StructDeclaration
*sd
= t1elem
->isTypeStruct ()->sym
;
385 result
= build_array_struct_comparison (code
, sd
, t1len
,
389 /* Check array length first before passing to memcmp.
390 For equality expressions, this becomes:
391 (e1.length == 0 || memcmp);
392 Otherwise for inequality:
393 (e1.length != 0 && memcmp); */
394 tree tsizecmp
= build_boolop (code
, t1len
, size_zero_node
);
395 if (e
->op
== EXP::equal
)
396 result
= build_boolop (TRUTH_ORIF_EXPR
, tsizecmp
, result
);
398 result
= build_boolop (TRUTH_ANDIF_EXPR
, tsizecmp
, result
);
400 /* Finally, check if lengths of both arrays match if dynamic.
401 The frontend should have already guaranteed that static arrays
403 if (tb1
->ty
== TY::Tsarray
&& tb2
->ty
== TY::Tsarray
)
404 gcc_assert (tb1
->size () == tb2
->size ());
407 tree tlencmp
= build_boolop (code
, t1len
, t2len
);
408 if (e
->op
== EXP::equal
)
409 result
= build_boolop (TRUTH_ANDIF_EXPR
, tlencmp
, result
);
411 result
= build_boolop (TRUTH_ORIF_EXPR
, tlencmp
, result
);
414 /* Ensure left-to-right order of evaluation. */
415 if (TREE_SIDE_EFFECTS (t2
))
416 result
= compound_expr (t2saved
, result
);
418 if (TREE_SIDE_EFFECTS (t1
))
419 result
= compound_expr (t1saved
, result
);
421 this->result_
= result
;
425 /* Use _adEq2() to compare each element. */
426 Type
*t1array
= t1elem
->arrayOf ();
427 tree result
= build_libcall (LIBCALL_ADEQ2
, e
->type
, 3,
428 d_array_convert (e
->e1
),
429 d_array_convert (e
->e2
),
430 build_typeinfo (e
, t1array
));
432 if (e
->op
== EXP::notEqual
)
433 result
= build1 (TRUTH_NOT_EXPR
, build_ctype (e
->type
), result
);
435 this->result_
= result
;
438 else if (TypeStruct
*ts
= tb1
->isTypeStruct ())
440 /* Equality for struct objects means the logical product of all
441 equality results of the corresponding object fields. */
442 tree t1
= build_expr (e
->e1
);
443 tree t2
= build_expr (e
->e2
);
445 gcc_assert (same_type_p (tb1
, tb2
));
447 this->result_
= build_struct_comparison (code
, ts
->sym
, t1
, t2
);
449 else if (tb1
->ty
== TY::Taarray
&& tb2
->ty
== TY::Taarray
)
451 /* Use _aaEqual() for associative arrays. */
452 tree result
= build_libcall (LIBCALL_AAEQUAL
, e
->type
, 3,
453 build_typeinfo (e
, tb1
),
457 if (e
->op
== EXP::notEqual
)
458 result
= build1 (TRUTH_NOT_EXPR
, build_ctype (e
->type
), result
);
460 this->result_
= result
;
464 /* For operands of other types, equality is defined as the bit pattern
465 of the type matches exactly. */
466 tree t1
= build_expr (e
->e1
);
467 tree t2
= build_expr (e
->e2
);
469 this->result_
= d_convert (build_ctype (e
->type
),
470 build_boolop (code
, t1
, t2
));
474 /* Build an `in' expression. This is a condition to see if an element
475 exists in an associative array. The result is a pointer to the
476 element, or null if false. */
478 void visit (InExp
*e
) final override
480 Type
*tb2
= e
->e2
->type
->toBasetype ();
481 Type
*tkey
= tb2
->isTypeAArray ()->index
->toBasetype ();
482 tree key
= convert_expr (build_expr (e
->e1
), e
->e1
->type
, tkey
);
484 /* Build a call to _aaInX(). */
485 this->result_
= build_libcall (LIBCALL_AAINX
, e
->type
, 3,
487 build_typeinfo (e
, tkey
),
488 build_address (key
));
491 /* Build a relational expression. The result type is bool. */
493 void visit (CmpExp
*e
) final override
495 Type
*tb1
= e
->e1
->type
->toBasetype ();
496 Type
*tb2
= e
->e2
->type
->toBasetype ();
503 case EXP::lessOrEqual
:
511 case EXP::greaterOrEqual
:
515 case EXP::greaterThan
:
523 /* For static and dynamic arrays, the relational op is turned into a
524 library call. It is not lowered during codegen. */
525 if ((tb1
->ty
== TY::Tsarray
|| tb1
->ty
== TY::Tarray
)
526 && (tb2
->ty
== TY::Tsarray
|| tb2
->ty
== TY::Tarray
))
528 error ("cannot handle comparison of type %<%s == %s%>",
529 tb1
->toChars (), tb2
->toChars ());
533 /* Simple comparison. */
534 result
= build_boolop (code
, build_expr (e
->e1
), build_expr (e
->e2
));
535 this->result_
= d_convert (build_ctype (e
->type
), result
);
538 /* Build a logical `and if' or `or if' expression. If the right operand
539 expression is void, then the resulting type is void. Otherwise the
542 void visit (LogicalExp
*e
) final override
544 tree_code code
= (e
->op
== EXP::andAnd
) ? TRUTH_ANDIF_EXPR
: TRUTH_ORIF_EXPR
;
546 if (e
->e2
->type
->toBasetype ()->ty
!= TY::Tvoid
)
548 tree t1
= build_expr (e
->e1
);
549 tree t2
= build_expr (e
->e2
);
551 t1
= convert_for_condition (t1
, e
->e1
->type
);
552 t2
= convert_for_condition (t2
, e
->e2
->type
);
554 this->result_
= d_convert (build_ctype (e
->type
),
555 build_boolop (code
, t1
, t2
));
559 tree t1
= convert_for_condition (build_expr (e
->e1
), e
->e1
->type
);
560 tree t2
= build_expr_dtor (e
->e2
);
562 /* Invert condition for logical or if expression. */
563 if (e
->op
== EXP::orOr
)
564 t1
= build1 (TRUTH_NOT_EXPR
, d_bool_type
, t1
);
566 this->result_
= build_condition (build_ctype (e
->type
),
571 /* Build a binary operand expression. Operands go through usual arithmetic
572 conversions to bring them to a common type before evaluating. */
574 void visit (BinExp
*e
) final override
582 if ((e
->e1
->type
->isreal () && e
->e2
->type
->isimaginary ())
583 || (e
->e1
->type
->isimaginary () && e
->e2
->type
->isreal ()))
585 /* If the result is complex, then we can shortcut binary_op.
586 Frontend should have already validated types and sizes. */
587 tree t1
= build_expr (e
->e1
);
588 tree t2
= build_expr (e
->e2
);
590 if (e
->op
== EXP::min
)
591 t2
= build1 (NEGATE_EXPR
, TREE_TYPE (t2
), t2
);
593 if (e
->e1
->type
->isreal ())
594 this->result_
= complex_expr (build_ctype (e
->type
), t1
, t2
);
596 this->result_
= complex_expr (build_ctype (e
->type
), t2
, t1
);
601 code
= (e
->op
== EXP::add
)
602 ? PLUS_EXPR
: MINUS_EXPR
;
610 /* Determine if the div expression is a lowered pointer diff operation.
611 The front-end rewrites `(p1 - p2)' into `(p1 - p2) / stride'. */
612 if (MinExp
*me
= e
->e1
->isMinExp ())
614 if (me
->e1
->type
->ty
== TY::Tpointer
615 && me
->e2
->type
->ty
== TY::Tpointer
616 && e
->e2
->op
== EXP::int64
)
618 code
= EXACT_DIV_EXPR
;
623 code
= e
->e1
->type
->isintegral ()
624 ? TRUNC_DIV_EXPR
: RDIV_EXPR
;
628 code
= e
->e1
->type
->isfloating ()
629 ? FLOAT_MOD_EXPR
: TRUNC_MOD_EXPR
;
648 case EXP::rightShift
:
652 case EXP::unsignedRightShift
:
653 code
= UNSIGNED_RSHIFT_EXPR
;
660 this->result_
= binary_op (code
, build_ctype (e
->type
),
661 build_expr (e
->e1
), build_expr (e
->e2
));
665 /* Build a concat expression, which concatenates two or more arrays of the
666 same type, producing a dynamic array with the result. If one operand
667 is an element type, that element is converted to an array of length 1. */
669 void visit (CatExp
*e
) final override
671 Type
*tb1
= e
->e1
->type
->toBasetype ();
672 Type
*tb2
= e
->e2
->type
->toBasetype ();
675 if (tb1
->ty
== TY::Tarray
|| tb1
->ty
== TY::Tsarray
)
676 etype
= tb1
->nextOf ();
678 etype
= tb2
->nextOf ();
682 if (e
->e1
->op
== EXP::concatenate
)
684 /* Flatten multiple concatenations to an array.
685 So the expression ((a ~ b) ~ c) becomes [a, b, c] */
688 for (Expression
*ex
= e
->e1
; ex
->op
== EXP::concatenate
;)
690 if (ex
->op
== EXP::concatenate
)
692 ex
= ex
->isCatExp ()->e1
;
697 /* Store all concatenation args to a temporary byte[][ndims] array. */
698 Type
*targselem
= Type::tint8
->arrayOf ();
699 tree var
= build_local_temp (make_array_type (targselem
, ndims
));
701 /* Loop through each concatenation from right to left. */
702 vec
<constructor_elt
, va_gc
> *elms
= NULL
;
706 for (Expression
*oe
= ce
->e2
; oe
!= NULL
;
707 (ce
->e1
->op
!= EXP::concatenate
709 : (ce
= ce
->e1
->isCatExp (), oe
= ce
->e2
)))
711 tree arg
= d_array_convert (etype
, oe
);
712 tree index
= size_int (dim
);
713 CONSTRUCTOR_APPEND_ELT (elms
, index
, d_save_expr (arg
));
715 /* Finished pushing all arrays. */
722 /* Check there is no logic bug in constructing byte[][] of arrays. */
723 gcc_assert (dim
== 0);
724 tree init
= build_constructor (TREE_TYPE (var
), elms
);
725 var
= compound_expr (modify_expr (var
, init
), var
);
727 tree arrs
= d_array_value (build_ctype (targselem
->arrayOf ()),
728 size_int (ndims
), build_address (var
));
730 result
= build_libcall (LIBCALL_ARRAYCATNTX
, e
->type
, 2,
731 build_typeinfo (e
, e
->type
), arrs
);
735 /* Handle single concatenation (a ~ b). */
736 result
= build_libcall (LIBCALL_ARRAYCATT
, e
->type
, 3,
737 build_typeinfo (e
, e
->type
),
738 d_array_convert (etype
, e
->e1
),
739 d_array_convert (etype
, e
->e2
));
742 this->result_
= result
;
745 /* Build an assignment operator expression. The right operand is implicitly
746 converted to the type of the left operand, and assigned to it. */
748 void visit (BinAssignExp
*e
) final override
751 Expression
*e1b
= e
->e1
;
768 code
= e
->e1
->type
->isintegral ()
769 ? TRUNC_DIV_EXPR
: RDIV_EXPR
;
773 code
= e
->e1
->type
->isfloating ()
774 ? FLOAT_MOD_EXPR
: TRUNC_MOD_EXPR
;
792 case EXP::leftShiftAssign
:
796 case EXP::rightShiftAssign
:
797 case EXP::unsignedRightShiftAssign
:
798 /* Use the original lhs type before it was promoted. The left operand
799 of `>>>=' does not undergo integral promotions before shifting.
800 Strip off casts just incase anyway. */
801 while (e1b
->op
== EXP::cast_
)
803 CastExp
*ce
= e1b
->isCastExp ();
804 gcc_assert (same_type_p (ce
->type
, ce
->to
));
807 code
= (e
->op
== EXP::rightShiftAssign
) ? RSHIFT_EXPR
: UNSIGNED_RSHIFT_EXPR
;
814 tree exp
= binop_assignment (code
, e1b
, e
->e2
);
815 this->result_
= convert_expr (exp
, e1b
->type
, e
->type
);
818 /* Build a concat assignment expression. The right operand is appended
819 to the left operand. */
821 void visit (CatAssignExp
*e
) final override
823 Type
*tb1
= e
->e1
->type
->toBasetype ();
824 Type
*tb2
= e
->e2
->type
->toBasetype ();
825 Type
*etype
= tb1
->nextOf ()->toBasetype ();
827 /* Save the address of `e1', so it can be evaluated first.
828 As all D run-time library functions for concat assignments update `e1'
829 in-place and then return its value, the saved address can also be used as
830 the result of this expression as well. */
831 tree lhs
= build_expr (e
->e1
);
832 tree lexpr
= stabilize_expr (&lhs
);
833 tree ptr
= d_save_expr (build_address (lhs
));
834 tree result
= NULL_TREE
;
836 if (tb1
->ty
== TY::Tarray
&& tb2
->ty
== TY::Tdchar
837 && (etype
->ty
== TY::Tchar
|| etype
->ty
== TY::Twchar
))
839 /* Append a dchar to a char[] or wchar[]:
840 The assignment is handled by the D run-time library, so only
841 need to call `_d_arrayappend[cw]d(&e1, e2)' */
842 libcall_fn libcall
= (etype
->ty
== TY::Tchar
)
843 ? LIBCALL_ARRAYAPPENDCD
: LIBCALL_ARRAYAPPENDWD
;
845 result
= build_libcall (libcall
, e
->type
, 2,
846 ptr
, build_expr (e
->e2
));
850 /* Appending an element or array to another array has already been
851 handled by the front-end. */
852 gcc_assert (tb1
->ty
== TY::Tarray
|| tb2
->ty
== TY::Tsarray
);
856 /* Construct in order: ptr = &e1, _d_arrayappend(ptr, e2), *ptr; */
857 result
= compound_expr (compound_expr (lexpr
, ptr
), result
);
858 this->result_
= compound_expr (result
, build_deref (ptr
));
861 /* Build an assignment expression. The right operand is implicitly
862 converted to the type of the left operand, and assigned to it. */
864 void visit (AssignExp
*e
) final override
866 /* First, handle special assignment semantics. */
868 /* Look for array.length = n; */
869 if (e
->e1
->op
== EXP::arrayLength
)
871 /* This case should have been rewritten to `_d_arraysetlengthT` in the
876 /* Look for exp = noreturn; */
877 if (e
->e2
->type
->isTypeNoreturn ())
879 /* If the RHS is a `noreturn' expression, there is no point generating
880 any code for the assignment, just evaluate side effects. */
881 tree t1
= build_expr (e
->e1
);
882 tree t2
= build_expr (e
->e2
);
883 this->result_
= compound_expr (t1
, t2
);
887 /* Look for array[] = n; */
888 if (e
->e1
->op
== EXP::slice
)
890 SliceExp
*se
= e
->e1
->isSliceExp ();
891 Type
*stype
= se
->e1
->type
->toBasetype ();
892 Type
*etype
= stype
->nextOf ()->toBasetype ();
894 /* Determine if we need to run postblit or dtor. */
895 bool postblit
= needs_postblit (etype
) && lvalue_p (e
->e2
);
896 bool destructor
= needs_dtor (etype
);
898 if (e
->memset
== MemorySet::blockAssign
)
900 /* Set a range of elements to one value. */
901 tree t1
= build_expr (e
->e1
);
902 tree t2
= build_expr (e
->e2
);
905 /* Extract any array bounds checks from the slice expression. */
906 tree init
= stabilize_expr (&t1
);
907 t1
= d_save_expr (t1
);
909 if ((postblit
|| destructor
) && e
->op
!= EXP::blit
)
911 /* This case should have been rewritten to `_d_arraysetassign`
912 in the semantic phase. */
916 if (integer_zerop (t2
))
918 tree size
= size_mult_expr (d_array_length (t1
),
919 size_int (etype
->size ()));
920 result
= build_memset_call (d_array_ptr (t1
), size
);
923 result
= build_array_set (d_array_ptr (t1
),
924 d_array_length (t1
), t2
);
926 result
= compound_expr (init
, result
);
927 this->result_
= compound_expr (result
, t1
);
931 /* Perform a memcpy operation. */
932 gcc_assert (e
->e2
->type
->ty
!= TY::Tpointer
);
934 if (!postblit
&& !destructor
)
936 tree t1
= d_save_expr (d_array_convert (e
->e1
));
937 tree t2
= d_save_expr (d_array_convert (e
->e2
));
939 /* References to array data. */
940 tree t1ptr
= d_array_ptr (t1
);
941 tree t1len
= d_array_length (t1
);
942 tree t2ptr
= d_array_ptr (t2
);
944 /* Generate: memcpy(to, from, size) */
945 tree size
= size_mult_expr (t1len
, size_int (etype
->size ()));
946 tree result
= build_memcpy_call (t1ptr
, t2ptr
, size
);
948 /* Insert check that array lengths match and do not overlap. */
949 if (array_bounds_check ())
951 /* tlencmp = (t1len == t2len) */
952 tree t2len
= d_array_length (t2
);
953 tree tlencmp
= build_boolop (EQ_EXPR
, t1len
, t2len
);
955 /* toverlap = (t1ptr + size <= t2ptr
956 || t2ptr + size <= t1ptr) */
957 tree t1ptrcmp
= build_boolop (LE_EXPR
,
958 build_offset (t1ptr
, size
),
960 tree t2ptrcmp
= build_boolop (LE_EXPR
,
961 build_offset (t2ptr
, size
),
963 tree toverlap
= build_boolop (TRUTH_ORIF_EXPR
, t1ptrcmp
,
966 /* (tlencmp && toverlap) ? memcpy() : _d_arraybounds() */
967 tree tassert
= build_array_bounds_call (e
->loc
);
968 tree tboundscheck
= build_boolop (TRUTH_ANDIF_EXPR
,
971 result
= build_condition (void_type_node
, tboundscheck
,
975 this->result_
= compound_expr (result
, t1
);
977 else if ((postblit
|| destructor
)
978 && e
->op
!= EXP::blit
&& e
->op
!= EXP::construct
)
980 /* Assigning to a non-trivially copyable array has already been
981 handled by the front-end. */
986 /* Generate: _d_arraycopy() */
987 this->result_
= build_libcall (LIBCALL_ARRAYCOPY
, e
->type
, 3,
988 size_int (etype
->size ()),
989 d_array_convert (e
->e2
),
990 d_array_convert (e
->e1
));
997 /* Look for reference initializations. */
998 if (e
->memset
== MemorySet::referenceInit
)
1000 gcc_assert (e
->op
== EXP::construct
|| e
->op
== EXP::blit
);
1001 gcc_assert (e
->e1
->op
== EXP::variable
);
1003 Declaration
*decl
= e
->e1
->isVarExp ()->var
;
1004 if (decl
->storage_class
& (STCout
| STCref
))
1006 tree t2
= convert_for_assignment (build_expr (e
->e2
),
1007 e
->e2
->type
, e
->e1
->type
);
1008 tree t1
= build_expr (e
->e1
);
1009 /* Want reference to lhs, not indirect ref. */
1010 t1
= TREE_OPERAND (t1
, 0);
1011 t2
= build_address (t2
);
1013 this->result_
= indirect_ref (build_ctype (e
->type
),
1014 build_assign (INIT_EXPR
, t1
, t2
));
1019 /* Other types of assignments that may require post construction. */
1020 Type
*tb1
= e
->e1
->type
->toBasetype ();
1021 tree_code modifycode
= (e
->op
== EXP::construct
) ? INIT_EXPR
: MODIFY_EXPR
;
1023 /* Look for struct assignment. */
1024 if (tb1
->ty
== TY::Tstruct
)
1026 tree t1
= build_expr (e
->e1
);
1027 tree t2
= convert_for_assignment (build_expr (e
->e2
, false, true),
1028 e
->e2
->type
, e
->e1
->type
);
1029 StructDeclaration
*sd
= tb1
->isTypeStruct ()->sym
;
1031 /* Look for struct = 0. */
1032 if (e
->e2
->op
== EXP::int64
)
1034 /* Use memset to fill struct. */
1035 gcc_assert (e
->op
== EXP::blit
);
1036 tree result
= build_memset_call (t1
);
1038 /* Maybe set-up hidden pointer to outer scope context. */
1039 if (sd
->isNested ())
1041 tree field
= get_symbol_decl (sd
->vthis
);
1042 tree value
= build_vthis (sd
);
1044 tree vthis_exp
= modify_expr (component_ref (t1
, field
), value
);
1045 result
= compound_expr (result
, vthis_exp
);
1048 this->result_
= compound_expr (result
, t1
);
1052 /* Simple struct literal assignment. */
1053 tree init
= NULL_TREE
;
1055 /* Fill any alignment holes in the struct using memset. */
1056 if ((e
->op
== EXP::construct
1057 || (e
->e2
->op
== EXP::structLiteral
&& e
->op
== EXP::blit
))
1058 && (sd
->isUnionDeclaration () || !identity_compare_p (sd
)))
1060 t1
= stabilize_reference (t1
);
1061 init
= build_memset_call (t1
);
1064 /* Elide generating assignment if init is all zeroes. */
1065 if (init
!= NULL_TREE
&& initializer_zerop (t2
))
1066 this->result_
= compound_expr (init
, t1
);
1069 tree result
= build_assign (modifycode
, t1
, t2
);
1070 this->result_
= compound_expr (init
, result
);
1077 /* Look for static array assignment. */
1078 if (tb1
->ty
== TY::Tsarray
)
1080 /* Look for array = 0. */
1081 if (e
->e2
->op
== EXP::int64
)
1083 /* Use memset to fill the array. */
1084 gcc_assert (e
->op
== EXP::blit
);
1085 this->result_
= build_memset_call (build_expr (e
->e1
));
1089 Type
*etype
= tb1
->nextOf ();
1090 gcc_assert (e
->e2
->type
->toBasetype ()->ty
== TY::Tsarray
);
1092 /* Determine if we need to run postblit. */
1093 const bool postblit
= needs_postblit (etype
);
1094 const bool destructor
= needs_dtor (etype
);
1095 const bool lvalue
= lvalue_p (e
->e2
);
1097 /* Optimize static array assignment with array literal. Even if the
1098 elements in rhs are all rvalues and don't have to call postblits,
1099 this assignment should call dtors on old assigned elements. */
1100 if ((!postblit
&& !destructor
)
1101 || (e
->op
== EXP::construct
&& e
->e2
->op
== EXP::arrayLiteral
)
1102 || (e
->op
== EXP::construct
&& e
->e2
->op
== EXP::call
)
1103 || (e
->op
== EXP::construct
&& !lvalue
&& postblit
)
1104 || (e
->op
== EXP::blit
|| e
->e1
->type
->size () == 0))
1106 tree t1
= build_expr (e
->e1
);
1107 tree t2
= convert_for_assignment (build_expr (e
->e2
),
1108 e
->e2
->type
, e
->e1
->type
);
1110 this->result_
= build_assign (modifycode
, t1
, t2
);
1114 /* All other kinds of lvalue or rvalue static array assignment.
1115 Array construction has already been handled by the front-end. */
1116 gcc_assert (e
->op
!= EXP::construct
);
1120 /* Simple assignment. */
1121 tree t1
= build_expr (e
->e1
);
1122 tree t2
= convert_for_assignment (build_expr (e
->e2
),
1123 e
->e2
->type
, e
->e1
->type
);
1125 this->result_
= build_assign (modifycode
, t1
, t2
);
1128 /* Build a throw expression. */
1130 void visit (ThrowExp
*e
) final override
1132 tree arg
= build_expr_dtor (e
->e1
);
1133 this->result_
= build_libcall (LIBCALL_THROW
, Type::tvoid
, 1, arg
);
1136 /* Build a postfix expression. */
1138 void visit (PostExp
*e
) final override
1142 if (e
->op
== EXP::plusPlus
)
1144 result
= build2 (POSTINCREMENT_EXPR
, build_ctype (e
->type
),
1145 build_expr (e
->e1
), build_expr (e
->e2
));
1147 else if (e
->op
== EXP::minusMinus
)
1149 result
= build2 (POSTDECREMENT_EXPR
, build_ctype (e
->type
),
1150 build_expr (e
->e1
), build_expr (e
->e2
));
1155 TREE_SIDE_EFFECTS (result
) = 1;
1156 this->result_
= result
;
1159 /* Build an index expression. */
1161 void visit (IndexExp
*e
) final override
1163 Type
*tb1
= e
->e1
->type
->toBasetype ();
1165 if (tb1
->ty
== TY::Taarray
)
1167 /* Get the key for the associative array. */
1168 Type
*tkey
= tb1
->isTypeAArray ()->index
->toBasetype ();
1169 tree key
= convert_expr (build_expr (e
->e2
), e
->e2
->type
, tkey
);
1175 libcall
= LIBCALL_AAGETY
;
1176 ptr
= build_address (build_expr (e
->e1
));
1177 tinfo
= build_typeinfo (e
, tb1
->unSharedOf ()->mutableOf ());
1181 libcall
= LIBCALL_AAGETRVALUEX
;
1182 ptr
= build_expr (e
->e1
);
1183 tinfo
= build_typeinfo (e
, tkey
);
1186 /* Index the associative array. */
1187 tree result
= build_libcall (libcall
, e
->type
->pointerTo (), 4,
1189 size_int (tb1
->nextOf ()->size ()),
1190 build_address (key
));
1192 if (!e
->indexIsInBounds
&& array_bounds_check ())
1194 tree tassert
= build_array_bounds_call (e
->loc
);
1196 result
= d_save_expr (result
);
1197 result
= build_condition (TREE_TYPE (result
),
1198 d_truthvalue_conversion (result
),
1202 this->result_
= indirect_ref (build_ctype (e
->type
), result
);
1206 /* Get the array and length for static and dynamic arrays. */
1207 tree array
= d_save_expr (build_expr (e
->e1
));
1209 tree length
= NULL_TREE
;
1210 if (tb1
->ty
!= TY::Tpointer
)
1211 length
= get_array_length (array
, tb1
);
1213 gcc_assert (e
->lengthVar
== NULL
);
1215 /* The __dollar variable just becomes a placeholder for the
1218 e
->lengthVar
->csym
= length
;
1220 /* Generate the index. */
1221 tree index
= build_expr (e
->e2
);
1223 /* If it's a static array and the index is constant, the front end has
1224 already checked the bounds. */
1225 if (tb1
->ty
!= TY::Tpointer
)
1226 index
= build_bounds_index_condition (e
, index
, length
);
1228 /* Convert vectors to their underlying array type. */
1229 if (VECTOR_TYPE_P (TREE_TYPE (array
)))
1232 build_array_type_nelts (TREE_TYPE (TREE_TYPE (array
)),
1233 TYPE_VECTOR_SUBPARTS (TREE_TYPE (array
)));
1234 d_mark_addressable (array
, false);
1235 array
= build1 (VIEW_CONVERT_EXPR
, array_type
, array
);
1238 if (TREE_CODE (TREE_TYPE (array
)) == ARRAY_TYPE
)
1240 /* Generate `array[index]'. When the index is non-constant, we must
1241 mark the array as addressable because we'll need to do pointer
1242 arithmetic on its address. */
1243 if (TREE_CODE (index
) != INTEGER_CST
)
1244 d_mark_addressable (array
);
1246 this->result_
= build4 (ARRAY_REF
, TREE_TYPE (TREE_TYPE (array
)),
1247 array
, index
, NULL_TREE
, NULL_TREE
);
1251 /* Generate `array.ptr[index]'. */
1252 tree ptr
= convert_expr (array
, tb1
, tb1
->nextOf ()->pointerTo ());
1253 ptr
= void_okay_p (ptr
);
1254 this->result_
= indirect_ref (TREE_TYPE (TREE_TYPE (ptr
)),
1255 build_pointer_index (ptr
, index
));
1260 /* Build a comma expression. The type is the type of the right operand. */
1262 void visit (CommaExp
*e
) final override
1264 tree t1
= build_expr (e
->e1
);
1265 tree t2
= build_expr (e
->e2
);
1266 tree type
= e
->type
? build_ctype (e
->type
) : void_type_node
;
1268 this->result_
= build2 (COMPOUND_EXPR
, type
, t1
, t2
);
1271 /* Build an array length expression. Returns the number of elements
1272 in the array. The result is of type size_t. */
1274 void visit (ArrayLengthExp
*e
) final override
1276 if (e
->e1
->type
->toBasetype ()->ty
== TY::Tarray
)
1277 this->result_
= d_array_length (build_expr (e
->e1
));
1280 /* Static arrays have already been handled by the front-end. */
1281 error ("unexpected type for array length: %qs", e
->type
->toChars ());
1282 this->result_
= error_mark_node
;
1286 /* Build a delegate pointer expression. This will return the frame
1287 pointer value as a type void*. */
1289 void visit (DelegatePtrExp
*e
) final override
1291 tree t1
= build_expr (e
->e1
);
1292 this->result_
= delegate_object (t1
);
1295 /* Build a delegate function pointer expression. This will return the
1296 function pointer value as a function type. */
1298 void visit (DelegateFuncptrExp
*e
) final override
1300 tree t1
= build_expr (e
->e1
);
1301 this->result_
= delegate_method (t1
);
1304 /* Build a slice expression. */
1306 void visit (SliceExp
*e
) final override
1308 Type
*tb
= e
->type
->toBasetype ();
1309 Type
*tb1
= e
->e1
->type
->toBasetype ();
1310 gcc_assert (tb
->ty
== TY::Tarray
|| tb
->ty
== TY::Tsarray
);
1312 /* Use convert-to-dynamic-array code if possible. */
1315 tree result
= build_expr (e
->e1
);
1316 if (e
->e1
->type
->toBasetype ()->ty
== TY::Tsarray
)
1317 result
= convert_expr (result
, e
->e1
->type
, e
->type
);
1319 this->result_
= result
;
1323 gcc_assert (e
->upr
!= NULL
);
1325 /* Get the data pointer and length for static and dynamic arrays. */
1326 tree array
= d_save_expr (build_expr (e
->e1
));
1327 tree ptr
= convert_expr (array
, tb1
, tb1
->nextOf ()->pointerTo ());
1328 tree length
= NULL_TREE
;
1330 /* Our array is already a SAVE_EXPR if necessary, so we don't make length
1331 a SAVE_EXPR which is, at most, a COMPONENT_REF on top of array. */
1332 if (tb1
->ty
!= TY::Tpointer
)
1333 length
= get_array_length (array
, tb1
);
1335 gcc_assert (e
->lengthVar
== NULL
);
1337 /* The __dollar variable just becomes a placeholder for the
1340 e
->lengthVar
->csym
= length
;
1342 /* Generate upper and lower bounds. */
1343 tree lwr_tree
= d_save_expr (build_expr (e
->lwr
));
1344 tree upr_tree
= d_save_expr (build_expr (e
->upr
));
1346 /* If the upper bound has any side effects, then the lower bound should be
1347 copied to a temporary always. */
1348 if (TREE_CODE (upr_tree
) == SAVE_EXPR
&& TREE_CODE (lwr_tree
) != SAVE_EXPR
)
1349 lwr_tree
= save_expr (lwr_tree
);
1351 /* Adjust the .ptr offset. */
1352 if (!integer_zerop (lwr_tree
))
1354 tree ptrtype
= TREE_TYPE (ptr
);
1355 ptr
= build_pointer_index (void_okay_p (ptr
), lwr_tree
);
1356 ptr
= build_nop (ptrtype
, ptr
);
1359 /* Nothing more to do for static arrays, their bounds checking has been
1360 done at compile-time. */
1361 if (tb
->ty
== TY::Tsarray
)
1363 this->result_
= indirect_ref (build_ctype (e
->type
), ptr
);
1367 gcc_assert (tb
->ty
== TY::Tarray
);
1369 /* Generate bounds checking code. */
1370 tree newlength
= build_bounds_slice_condition (e
, lwr_tree
, upr_tree
,
1372 tree result
= d_array_value (build_ctype (e
->type
), newlength
, ptr
);
1373 this->result_
= compound_expr (array
, result
);
1376 /* Build a cast expression, which converts the given unary expression to the
1379 void visit (CastExp
*e
) final override
1381 Type
*ebtype
= e
->e1
->type
->toBasetype ();
1382 Type
*tbtype
= e
->to
->toBasetype ();
1383 tree result
= build_expr (e
->e1
, this->constp_
, this->literalp_
);
1385 /* Just evaluate e1 if it has any side effects. */
1386 if (tbtype
->ty
== TY::Tvoid
)
1387 this->result_
= build_nop (build_ctype (tbtype
), result
);
1389 this->result_
= convert_for_rvalue (result
, ebtype
, tbtype
);
1392 /* Build a delete expression. */
1394 void visit (DeleteExp
*e
) final override
1396 tree t1
= build_expr (e
->e1
);
1397 Type
*tb1
= e
->e1
->type
->toBasetype ();
1399 if (tb1
->ty
== TY::Tclass
)
1401 /* For class object references, if there is a destructor for that class,
1402 the destructor is called for the object instance. */
1403 gcc_assert (e
->e1
->op
== EXP::variable
);
1405 VarDeclaration
*v
= e
->e1
->isVarExp ()->var
->isVarDeclaration ();
1406 gcc_assert (v
&& v
->onstack ());
1408 libcall_fn libcall
= tb1
->isClassHandle ()->isInterfaceDeclaration ()
1409 ? LIBCALL_CALLINTERFACEFINALIZER
: LIBCALL_CALLFINALIZER
;
1411 this->result_
= build_libcall (libcall
, Type::tvoid
, 1, t1
);
1416 error ("don%'t know how to delete %qs", e
->e1
->toChars ());
1417 this->result_
= error_mark_node
;
1421 /* Build a remove expression, which removes a particular key from an
1422 associative array. */
1424 void visit (RemoveExp
*e
) final override
1426 /* Check that the array is actually an associative array. */
1427 if (e
->e1
->type
->toBasetype ()->ty
== TY::Taarray
)
1429 Type
*tb
= e
->e1
->type
->toBasetype ();
1430 Type
*tkey
= tb
->isTypeAArray ()->index
->toBasetype ();
1431 tree index
= convert_expr (build_expr (e
->e2
), e
->e2
->type
, tkey
);
1433 this->result_
= build_libcall (LIBCALL_AADELX
, Type::tbool
, 3,
1435 build_typeinfo (e
, tkey
),
1436 build_address (index
));
1440 error ("%qs is not an associative array", e
->e1
->toChars ());
1441 this->result_
= error_mark_node
;
1445 /* Build an unary not expression. */
1447 void visit (NotExp
*e
) final override
1449 tree result
= convert_for_condition (build_expr (e
->e1
), e
->e1
->type
);
1450 /* Need to convert to boolean type or this will fail. */
1451 result
= fold_build1 (TRUTH_NOT_EXPR
, d_bool_type
, result
);
1453 this->result_
= d_convert (build_ctype (e
->type
), result
);
1456 /* Build a compliment expression, where all the bits in the value are
1457 complemented. Note: unlike in C, the usual integral promotions
1458 are not performed prior to the complement operation. */
1460 void visit (ComExp
*e
) final override
1462 TY ty1
= e
->e1
->type
->toBasetype ()->ty
;
1463 gcc_assert (ty1
!= TY::Tarray
&& ty1
!= TY::Tsarray
);
1465 this->result_
= fold_build1 (BIT_NOT_EXPR
, build_ctype (e
->type
),
1466 build_expr (e
->e1
));
1469 /* Build an unary negation expression. */
1471 void visit (NegExp
*e
) final override
1473 TY ty1
= e
->e1
->type
->toBasetype ()->ty
;
1474 gcc_assert (ty1
!= TY::Tarray
&& ty1
!= TY::Tsarray
);
1476 tree type
= build_ctype (e
->type
);
1477 tree expr
= build_expr (e
->e1
);
1479 /* If the operation needs excess precision. */
1480 tree eptype
= excess_precision_type (type
);
1481 if (eptype
!= NULL_TREE
)
1482 expr
= d_convert (eptype
, expr
);
1486 tree ret
= fold_build1 (NEGATE_EXPR
, eptype
, expr
);
1487 this->result_
= d_convert (type
, ret
);
1490 /* Build a pointer index expression. */
1492 void visit (PtrExp
*e
) final override
1498 if (e
->e1
->op
== EXP::add
)
1500 AddExp
*ae
= e
->e1
->isAddExp ();
1501 if (ae
->e1
->op
== EXP::address
1502 && ae
->e2
->isConst () && ae
->e2
->type
->isintegral ())
1504 Expression
*ex
= ae
->e1
->isAddrExp ()->e1
;
1505 tnext
= ex
->type
->toBasetype ();
1506 result
= build_expr (ex
);
1507 offset
= ae
->e2
->toUInteger ();
1510 else if (e
->e1
->op
== EXP::symbolOffset
)
1512 SymOffExp
*se
= e
->e1
->isSymOffExp ();
1513 if (!declaration_reference_p (se
->var
))
1515 tnext
= se
->var
->type
->toBasetype ();
1516 result
= get_decl_tree (se
->var
);
1517 offset
= se
->offset
;
1521 /* Produce better code by converting *(#record + n) to
1522 COMPONENT_REFERENCE. Otherwise, the variable will always be
1523 allocated in memory because its address is taken. */
1524 if (tnext
&& tnext
->ty
== TY::Tstruct
)
1526 StructDeclaration
*sd
= tnext
->isTypeStruct ()->sym
;
1528 for (size_t i
= 0; i
< sd
->fields
.length
; i
++)
1530 VarDeclaration
*field
= sd
->fields
[i
];
1532 if (field
->offset
== offset
1533 && same_type_p (field
->type
, e
->type
))
1535 /* Catch errors, backend will ICE otherwise. */
1536 if (error_operand_p (result
))
1537 this->result_
= result
;
1540 result
= component_ref (result
, get_symbol_decl (field
));
1541 this->result_
= result
;
1545 else if (field
->offset
> offset
)
1550 this->result_
= indirect_ref (build_ctype (e
->type
), build_expr (e
->e1
));
1553 /* Build an unary address expression. */
1555 void visit (AddrExp
*e
) final override
1557 tree type
= build_ctype (e
->type
);
1560 /* The frontend optimizer can convert const symbol into a struct literal.
1561 Taking the address of a struct literal is otherwise illegal. */
1562 if (e
->e1
->op
== EXP::structLiteral
)
1564 StructLiteralExp
*sle
= e
->e1
->isStructLiteralExp ()->origin
;
1565 gcc_assert (sle
!= NULL
);
1567 /* Build the reference symbol, the decl is built first as the
1568 initializer may have recursive references. */
1571 sle
->sym
= build_artificial_decl (build_ctype (sle
->type
),
1573 DECL_INITIAL (sle
->sym
) = build_expr (sle
, true);
1574 d_pushdecl (sle
->sym
);
1575 rest_of_decl_compilation (sle
->sym
, 1, 0);
1581 exp
= build_expr (e
->e1
, this->constp_
, this->literalp_
);
1583 TREE_CONSTANT (exp
) = 0;
1584 this->result_
= d_convert (type
, build_address (exp
));
1587 /* Build a function call expression. */
1589 void visit (CallExp
*e
) final override
1591 Type
*tb
= e
->e1
->type
->toBasetype ();
1592 Expression
*e1b
= e
->e1
;
1594 tree callee
= NULL_TREE
;
1595 tree object
= NULL_TREE
;
1596 tree cleanup
= NULL_TREE
;
1597 tree returnvalue
= NULL_TREE
;
1598 TypeFunction
*tf
= NULL
;
1600 /* Calls to delegates can sometimes look like this. */
1601 if (e1b
->op
== EXP::comma
)
1603 e1b
= e1b
->isCommaExp ()->e2
;
1604 gcc_assert (e1b
->op
== EXP::variable
);
1606 Declaration
*var
= e1b
->isVarExp ()->var
;
1607 gcc_assert (var
->isFuncDeclaration () && !var
->needThis ());
1610 if (e1b
->op
== EXP::dotVariable
&& tb
->ty
!= TY::Tdelegate
)
1612 DotVarExp
*dve
= e1b
->isDotVarExp ();
1614 /* Don't modify the static initializer for struct literals. */
1615 if (dve
->e1
->op
== EXP::structLiteral
)
1617 StructLiteralExp
*sle
= dve
->e1
->isStructLiteralExp ();
1618 sle
->useStaticInit
= false;
1621 FuncDeclaration
*fd
= dve
->var
->isFuncDeclaration ();
1624 /* Get the correct callee from the DotVarExp object. */
1625 tree fndecl
= get_symbol_decl (fd
);
1626 AggregateDeclaration
*ad
= fd
->isThis ();
1628 /* Static method; ignore the object instance. */
1630 callee
= build_address (fndecl
);
1633 tree thisexp
= build_expr (dve
->e1
);
1635 /* When constructing temporaries, if the constructor throws,
1636 then the object is destructed even though it is not a fully
1637 constructed object yet. And so this call will need to be
1638 moved inside the TARGET_EXPR_INITIAL slot. */
1639 if (fd
->isCtorDeclaration ()
1640 && TREE_CODE (thisexp
) == COMPOUND_EXPR
1641 && TREE_CODE (TREE_OPERAND (thisexp
, 0)) == TARGET_EXPR
1642 && TARGET_EXPR_CLEANUP (TREE_OPERAND (thisexp
, 0)))
1644 cleanup
= TREE_OPERAND (thisexp
, 0);
1645 thisexp
= TREE_OPERAND (thisexp
, 1);
1648 if (TREE_CODE (thisexp
) == CONSTRUCTOR
)
1649 thisexp
= force_target_expr (thisexp
);
1651 /* Want reference to `this' object. */
1652 if (!POINTER_TYPE_P (TREE_TYPE (thisexp
)))
1653 thisexp
= build_address (thisexp
);
1655 /* Make the callee a virtual call. */
1656 if (fd
->isVirtual () && !fd
->isFinalFunc () && !e
->directcall
)
1658 tree fntype
= build_pointer_type (TREE_TYPE (fndecl
));
1659 tree thistype
= build_ctype (ad
->handleType ());
1660 thisexp
= build_nop (thistype
, d_save_expr (thisexp
));
1661 fndecl
= build_vindex_ref (thisexp
, fntype
, fd
->vtblIndex
);
1664 fndecl
= build_address (fndecl
);
1666 /* C++ constructors return void, even though front-end semantic
1667 treats them as implicitly returning `this'. Set returnvalue
1668 to override the result of this expression. */
1669 if (fd
->isCtorDeclaration ())
1671 thisexp
= d_save_expr (thisexp
);
1672 returnvalue
= thisexp
;
1675 callee
= build_method_call (fndecl
, thisexp
, fd
->type
);
1680 if (callee
== NULL_TREE
)
1681 callee
= build_expr (e1b
);
1683 if (METHOD_CALL_EXPR (callee
))
1685 /* This could be a delegate expression (TY == Tdelegate), but not
1686 actually a delegate variable. */
1687 if (e1b
->op
== EXP::dotVariable
)
1689 /* This gets the true function type, getting the function type
1690 from e1->type can sometimes be incorrect, such as when calling
1691 a `ref' return function. */
1692 tf
= get_function_type (e1b
->isDotVarExp ()->var
->type
);
1695 tf
= get_function_type (tb
);
1697 extract_from_method_call (callee
, callee
, object
);
1699 else if (tb
->ty
== TY::Tdelegate
)
1701 /* Delegate call, extract .object and .funcptr from var. */
1702 callee
= d_save_expr (callee
);
1703 tf
= get_function_type (tb
);
1704 object
= delegate_object (callee
);
1705 callee
= delegate_method (callee
);
1707 else if (e1b
->op
== EXP::variable
)
1709 FuncDeclaration
*fd
= e1b
->isVarExp ()->var
->isFuncDeclaration ();
1710 gcc_assert (fd
!= NULL
);
1711 tf
= get_function_type (fd
->type
);
1713 if (fd
->isNested ())
1715 /* Maybe re-evaluate symbol storage treating `fd' as public. */
1716 if (call_by_alias_p (d_function_chain
->function
, fd
))
1717 TREE_PUBLIC (callee
) = 1;
1719 object
= get_frame_for_symbol (fd
);
1721 else if (fd
->needThis ())
1723 error_at (make_location_t (e1b
->loc
),
1724 "need %<this%> to access member %qs", fd
->toChars ());
1725 /* Continue compiling... */
1726 object
= null_pointer_node
;
1731 /* Normal direct function call. */
1732 tf
= get_function_type (tb
);
1735 gcc_assert (tf
!= NULL
);
1737 /* Now we have the type, callee and maybe object reference,
1738 build the call expression. */
1739 tree exp
= d_build_call (tf
, callee
, object
, e
->arguments
);
1741 if (returnvalue
!= NULL_TREE
)
1742 exp
= compound_expr (exp
, returnvalue
);
1745 exp
= build_deref (exp
);
1747 /* Some library calls are defined to return a generic type.
1748 this->type is the real type we want to return. */
1749 if (e
->type
->isTypeBasic ())
1750 exp
= d_convert (build_ctype (e
->type
), exp
);
1752 /* If this call was found to be a constructor for a temporary with a
1753 cleanup, then move the call inside the TARGET_EXPR. */
1754 if (cleanup
!= NULL_TREE
)
1756 tree init
= TARGET_EXPR_INITIAL (cleanup
);
1757 TARGET_EXPR_INITIAL (cleanup
) = compound_expr (init
, exp
);
1759 /* Keep the return value outside the TARGET_EXPR. */
1760 if (returnvalue
!= NULL_TREE
)
1761 cleanup
= compound_expr (cleanup
, TREE_OPERAND (exp
, 1));
1766 this->result_
= exp
;
1769 /* Build a delegate expression. */
1771 void visit (DelegateExp
*e
) final override
1773 if (e
->func
->semanticRun
== PASS::semantic3done
)
1775 /* Add the function as nested function if it belongs to this module.
1776 ie: it is a member of this module, or it is a template instance. */
1777 Dsymbol
*owner
= e
->func
->toParent ();
1778 while (!owner
->isTemplateInstance () && owner
->toParent ())
1779 owner
= owner
->toParent ();
1780 if (owner
->isTemplateInstance () || owner
== d_function_chain
->module
)
1781 build_decl_tree (e
->func
);
1787 if (e
->func
->isNested () && !e
->func
->isThis ())
1789 if (e
->e1
->op
== EXP::null_
)
1790 object
= build_expr (e
->e1
);
1792 object
= get_frame_for_symbol (e
->func
);
1794 fndecl
= build_address (get_symbol_decl (e
->func
));
1798 if (!e
->func
->isThis ())
1800 error ("delegates are only for non-static functions");
1801 this->result_
= error_mark_node
;
1805 object
= build_expr (e
->e1
);
1807 /* Want reference to `this' object. */
1808 if (e
->e1
->type
->ty
!= TY::Tclass
&& e
->e1
->type
->ty
!= TY::Tpointer
)
1809 object
= build_address (object
);
1811 /* Object reference could be the outer `this' field of a class or
1812 closure of type `void*'. Cast it to the right type. */
1813 if (e
->e1
->type
->ty
== TY::Tclass
)
1814 object
= d_convert (build_ctype (e
->e1
->type
), object
);
1816 fndecl
= get_symbol_decl (e
->func
);
1818 /* Get pointer to function out of the virtual table. */
1819 if (e
->func
->isVirtual () && !e
->func
->isFinalFunc ()
1820 && e
->e1
->op
!= EXP::super_
&& e
->e1
->op
!= EXP::dotType
)
1822 tree fntype
= build_pointer_type (TREE_TYPE (fndecl
));
1823 object
= d_save_expr (object
);
1824 fndecl
= build_vindex_ref (object
, fntype
, e
->func
->vtblIndex
);
1827 fndecl
= build_address (fndecl
);
1830 this->result_
= build_method_call (fndecl
, object
, e
->type
);
1833 /* Build a type component expression. */
1835 void visit (DotTypeExp
*e
) final override
1837 /* Just a pass through to underlying expression. */
1838 this->result_
= build_expr (e
->e1
);
1841 /* Build a component reference expression. */
1843 void visit (DotVarExp
*e
) final override
1845 VarDeclaration
*vd
= e
->var
->isVarDeclaration ();
1847 /* This could also be a function, but relying on that being taken
1848 care of by the visitor interface for CallExp. */
1851 if (!vd
->isField ())
1852 this->result_
= get_decl_tree (vd
);
1855 tree object
= build_expr (e
->e1
);
1856 Type
*tb
= e
->e1
->type
->toBasetype ();
1858 if (tb
->ty
!= TY::Tstruct
)
1859 object
= build_deref (object
);
1861 /* __complex is represented as a struct in the front-end, but
1862 underlying is really a complex type. */
1863 if (e
->e1
->type
->ty
== TY::Tenum
1864 && e
->e1
->type
->isTypeEnum ()->sym
->isSpecial ())
1865 object
= underlying_complex_expr (build_ctype (tb
), object
);
1867 this->result_
= component_ref (object
, get_symbol_decl (vd
));
1872 error ("%qs is not a field, but a %qs",
1873 e
->var
->toChars (), e
->var
->kind ());
1874 this->result_
= error_mark_node
;
1878 /* Build an assert expression, used to declare conditions that must hold at
1879 that a given point in the program. */
1881 void visit (AssertExp
*e
) final override
1883 Type
*tb1
= e
->e1
->type
->toBasetype ();
1884 tree arg
= build_expr (e
->e1
);
1885 tree tmsg
= NULL_TREE
;
1886 tree assert_pass
= void_node
;
1889 if (global
.params
.useAssert
== CHECKENABLEon
&& !checkaction_trap_p ())
1891 /* Generate: ((bool) e1 ? (void)0 : _d_assert (...))
1892 or: (e1 != null ? e1._invariant() : _d_assert (...)) */
1893 bool unittest_p
= d_function_chain
->function
->isUnitTestDeclaration ();
1898 tmsg
= build_expr_dtor (e
->msg
);
1899 libcall
= unittest_p
? LIBCALL_UNITTEST_MSG
: LIBCALL_ASSERT_MSG
;
1902 libcall
= unittest_p
? LIBCALL_UNITTESTP
: LIBCALL_ASSERTP
;
1904 /* Build a call to _d_assert(). */
1905 assert_fail
= build_assert_call (e
->loc
, libcall
, tmsg
);
1907 if (global
.params
.useInvariants
== CHECKENABLEon
)
1909 /* If the condition is a D class or struct object with an invariant,
1910 call it if the condition result is true. */
1911 if (tb1
->ty
== TY::Tclass
)
1913 ClassDeclaration
*cd
= tb1
->isClassHandle ();
1914 if (!cd
->isInterfaceDeclaration () && !cd
->isCPPclass ())
1916 arg
= d_save_expr (arg
);
1917 assert_pass
= build_libcall (LIBCALL_INVARIANT
,
1918 Type::tvoid
, 1, arg
);
1921 else if (tb1
->ty
== TY::Tpointer
1922 && tb1
->nextOf ()->ty
== TY::Tstruct
)
1924 StructDeclaration
*sd
= tb1
->nextOf ()->isTypeStruct ()->sym
;
1925 if (sd
->inv
!= NULL
)
1928 arg
= d_save_expr (arg
);
1929 assert_pass
= d_build_call_expr (sd
->inv
, arg
, &args
);
1934 else if (global
.params
.useAssert
== CHECKENABLEon
&& checkaction_trap_p ())
1936 /* Generate: __builtin_trap() */
1937 tree fn
= builtin_decl_explicit (BUILT_IN_TRAP
);
1938 assert_fail
= build_call_expr (fn
, 0);
1942 /* Assert contracts are turned off. */
1943 this->result_
= void_node
;
1947 /* Build condition that we are asserting in this contract. */
1948 tree condition
= convert_for_condition (arg
, e
->e1
->type
);
1950 /* We expect the condition to always be true, as what happens if an assert
1951 contract is false is undefined behavior. */
1952 tree fn
= builtin_decl_explicit (BUILT_IN_EXPECT
);
1953 tree arg_types
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
1954 tree pred_type
= TREE_VALUE (arg_types
);
1955 tree expected_type
= TREE_VALUE (TREE_CHAIN (arg_types
));
1957 condition
= build_call_expr (fn
, 2, d_convert (pred_type
, condition
),
1958 build_int_cst (expected_type
, 1));
1959 condition
= d_truthvalue_conversion (condition
);
1961 this->result_
= build_vcondition (condition
, assert_pass
, assert_fail
);
1964 /* Build a declaration expression. */
1966 void visit (DeclarationExp
*e
) final override
1968 /* Compile the declaration. */
1970 build_decl_tree (e
->declaration
);
1971 tree result
= pop_stmt_list ();
1973 /* Construction of an array for typesafe-variadic function arguments
1974 can cause an empty STMT_LIST here. This can causes problems
1975 during gimplification. */
1976 if (TREE_CODE (result
) == STATEMENT_LIST
&& !STATEMENT_LIST_HEAD (result
))
1977 result
= build_empty_stmt (input_location
);
1979 this->result_
= result
;
1982 /* Build a typeid expression. Returns an instance of class TypeInfo
1983 corresponding to. */
1985 void visit (TypeidExp
*e
) final override
1987 if (Type
*tid
= isType (e
->obj
))
1989 tree ti
= build_typeinfo (e
, tid
);
1991 /* If the typeinfo is at an offset. */
1992 if (tid
->vtinfo
->offset
)
1993 ti
= build_offset (ti
, size_int (tid
->vtinfo
->offset
));
1995 this->result_
= build_nop (build_ctype (e
->type
), ti
);
1997 else if (Expression
*tid
= isExpression (e
->obj
))
1999 Type
*type
= tid
->type
->toBasetype ();
2000 assert (type
->ty
== TY::Tclass
);
2002 /* Generate **classptr to get the classinfo. */
2003 tree ci
= build_expr (tid
);
2004 ci
= indirect_ref (ptr_type_node
, ci
);
2005 ci
= indirect_ref (ptr_type_node
, ci
);
2007 /* Add extra indirection for interfaces. */
2008 if (type
->isTypeClass ()->sym
->isInterfaceDeclaration ())
2009 ci
= indirect_ref (ptr_type_node
, ci
);
2011 this->result_
= build_nop (build_ctype (e
->type
), ci
);
2017 /* Build a function/lambda expression. */
2019 void visit (FuncExp
*e
) final override
2021 Type
*ftype
= e
->type
->toBasetype ();
2023 /* This check is for lambda's, remove `vthis' as function isn't nested. */
2024 if (e
->fd
->tok
== TOK::reserved
&& ftype
->ty
== TY::Tpointer
)
2026 e
->fd
->tok
= TOK::function_
;
2027 e
->fd
->vthis
= NULL
;
2030 /* Compile the function literal body. */
2031 build_decl_tree (e
->fd
);
2033 /* If nested, this will be a trampoline. */
2034 if (e
->fd
->isNested ())
2036 tree func
= build_address (get_symbol_decl (e
->fd
));
2041 /* Static delegate variables have no context pointer. */
2042 object
= null_pointer_node
;
2043 this->result_
= build_method_call (func
, object
, e
->fd
->type
);
2044 TREE_CONSTANT (this->result_
) = 1;
2048 object
= get_frame_for_symbol (e
->fd
);
2049 this->result_
= build_method_call (func
, object
, e
->fd
->type
);
2054 this->result_
= build_nop (build_ctype (e
->type
),
2055 build_address (get_symbol_decl (e
->fd
)));
2059 /* Build a halt expression. */
2061 void visit (HaltExp
*) final override
2063 /* Should we use trap() or abort()? */
2064 tree ttrap
= builtin_decl_explicit (BUILT_IN_TRAP
);
2065 this->result_
= build_call_expr (ttrap
, 0);
2068 /* Build a symbol pointer offset expression. */
2070 void visit (SymOffExp
*e
) final override
2072 /* Build the address and offset of the symbol. */
2073 size_t soffset
= e
->isSymOffExp ()->offset
;
2074 tree result
= get_decl_tree (e
->var
);
2075 TREE_USED (result
) = 1;
2077 if (declaration_reference_p (e
->var
))
2078 gcc_assert (POINTER_TYPE_P (TREE_TYPE (result
)));
2080 result
= build_address (result
);
2083 result
= d_convert (build_ctype (e
->type
), result
);
2086 tree offset
= size_int (soffset
);
2087 result
= build_nop (build_ctype (e
->type
),
2088 build_offset (result
, offset
));
2091 this->result_
= result
;
2094 /* Build a variable expression. */
2096 void visit (VarExp
*e
) final override
2098 if (e
->var
->needThis ())
2100 error ("need %<this%> to access member %qs", e
->var
->ident
->toChars ());
2101 this->result_
= error_mark_node
;
2104 else if (e
->var
->ident
== Identifier::idPool ("__ctfe"))
2106 /* __ctfe is always false at run-time. */
2107 this->result_
= integer_zero_node
;
2111 /* This check is same as is done in FuncExp for lambdas. */
2112 FuncLiteralDeclaration
*fld
= e
->var
->isFuncLiteralDeclaration ();
2115 if (fld
->tok
== TOK::reserved
)
2117 fld
->tok
= TOK::function_
;
2121 /* Compiler the function literal body. */
2122 build_decl_tree (fld
);
2127 /* Want the initializer, not the expression. */
2128 VarDeclaration
*var
= e
->var
->isVarDeclaration ();
2129 SymbolDeclaration
*sdecl
= e
->var
->isSymbolDeclaration ();
2130 tree init
= NULL_TREE
;
2132 if (var
&& (var
->isConst () || var
->isImmutable ())
2133 && e
->type
->toBasetype ()->ty
!= TY::Tsarray
&& var
->_init
)
2136 error_at (make_location_t (e
->loc
), "recursive reference %qs",
2141 init
= build_expr (initializerToExpression (var
->_init
), true);
2145 else if (sdecl
&& sdecl
->dsym
)
2147 if (StructDeclaration
*sd
= sdecl
->dsym
->isStructDeclaration ())
2148 init
= layout_struct_initializer (sd
);
2149 else if (ClassDeclaration
*cd
= sdecl
->dsym
->isClassDeclaration ())
2150 init
= layout_class_initializer (cd
);
2155 error_at (make_location_t (e
->loc
), "non-constant expression %qs",
2158 if (init
!= NULL_TREE
)
2159 this->result_
= init
;
2161 this->result_
= error_mark_node
;
2165 tree result
= get_decl_tree (e
->var
);
2166 TREE_USED (result
) = 1;
2168 /* The variable expression generated for `__traits(initSymbol)'. */
2169 if (SymbolDeclaration
*sd
= e
->var
->isSymbolDeclaration ())
2171 if (e
->type
->isTypeDArray ())
2173 /* Generate a slice for non-zero initialized aggregates,
2174 otherwise create an empty array. */
2175 gcc_assert (e
->type
== Type::tvoid
->arrayOf ()->constOf ());
2177 tree type
= build_ctype (e
->type
);
2178 tree length
= size_int (sd
->dsym
->structsize
);
2179 tree ptr
= (sd
->dsym
->isStructDeclaration ()
2180 && sd
->dsym
->type
->isZeroInit (e
->loc
))
2181 ? null_pointer_node
: build_address (result
);
2183 this->result_
= d_array_value (type
, length
, ptr
);
2188 /* For variables that are references - currently only out/inout
2189 arguments; objects don't count - evaluating the variable means
2190 we want what it refers to. */
2191 if (declaration_reference_p (e
->var
))
2192 result
= indirect_ref (build_ctype (e
->var
->type
), result
);
2194 this->result_
= result
;
2198 /* Build a this variable expression. */
2200 void visit (ThisExp
*e
) final override
2202 FuncDeclaration
*fd
= d_function_chain
? d_function_chain
->function
: NULL
;
2203 tree result
= NULL_TREE
;
2206 result
= get_decl_tree (e
->var
);
2209 gcc_assert (fd
&& fd
->vthis
);
2210 result
= get_decl_tree (fd
->vthis
);
2213 if (e
->type
->ty
== TY::Tstruct
)
2214 result
= build_deref (result
);
2216 this->result_
= result
;
2219 /* Build a new expression, which allocates memory either on the garbage
2220 collected heap or by using a class or struct specific allocator. */
2222 void visit (NewExp
*e
) final override
2224 Type
*tb
= e
->type
->toBasetype ();
2227 if (tb
->ty
== TY::Tclass
)
2229 /* Allocating a new class. */
2230 tb
= e
->newtype
->toBasetype ();
2232 ClassDeclaration
*cd
= tb
->isTypeClass ()->sym
;
2233 tree type
= build_ctype (tb
);
2234 tree setup_exp
= NULL_TREE
;
2239 /* If being used as an initializer for a local variable with scope
2240 storage class, then the instance is allocated on the stack
2241 rather than the heap or using the class specific allocator. */
2242 tree var
= build_local_temp (TREE_TYPE (type
));
2243 new_call
= build_nop (type
, build_address (var
));
2244 setup_exp
= modify_expr (var
, aggregate_initializer_decl (cd
));
2246 else if (global
.params
.ehnogc
&& e
->thrownew
)
2248 /* Allocating a `@nogc' Exception with `_d_newThrowable' has already
2249 been handled by the front-end. */
2254 /* Generate: _d_newclass() */
2255 tree arg
= build_address (get_classinfo_decl (cd
));
2256 new_call
= build_libcall (LIBCALL_NEWCLASS
, tb
, 1, arg
);
2259 /* Set the context pointer for nested classes. */
2260 if (cd
->isNested ())
2262 tree field
= get_symbol_decl (cd
->vthis
);
2263 tree value
= NULL_TREE
;
2267 ClassDeclaration
*tcd
= e
->thisexp
->type
->isClassHandle ();
2268 /* The class or function we're nested in. */
2269 Dsymbol
*outer
= cd
->toParentLocal ();
2271 value
= build_expr (e
->thisexp
);
2275 ClassDeclaration
*ocd
= outer
->isClassDeclaration ();
2277 gcc_assert (ocd
->isBaseOf (tcd
, &offset
));
2278 /* Could just add offset... */
2279 value
= convert_expr (value
, e
->thisexp
->type
, ocd
->type
);
2283 value
= build_vthis (cd
);
2285 if (value
!= NULL_TREE
)
2287 /* Generate: (new())->vthis = this; */
2288 new_call
= d_save_expr (new_call
);
2289 field
= component_ref (build_deref (new_call
), field
);
2290 setup_exp
= compound_expr (setup_exp
,
2291 modify_expr (field
, value
));
2294 new_call
= compound_expr (setup_exp
, new_call
);
2296 /* Call the class constructor. */
2298 result
= d_build_call_expr (e
->member
, new_call
, e
->arguments
);
2303 result
= compound_expr (build_expr (e
->argprefix
), result
);
2305 else if (tb
->ty
== TY::Tpointer
2306 && tb
->nextOf ()->toBasetype ()->ty
== TY::Tstruct
)
2308 /* Allocating memory for a new struct. */
2309 Type
*htype
= e
->newtype
->toBasetype ();
2310 gcc_assert (!e
->onstack
);
2312 TypeStruct
*stype
= htype
->isTypeStruct ();
2313 StructDeclaration
*sd
= stype
->sym
;
2316 /* Cannot new an opaque struct. */
2317 if (sd
->size (e
->loc
) == 0)
2319 this->result_
= d_convert (build_ctype (e
->type
),
2324 /* Generate: _d_newitemT() */
2325 libcall_fn libcall
= htype
->isZeroInit ()
2326 ? LIBCALL_NEWITEMT
: LIBCALL_NEWITEMIT
;
2327 tree arg
= build_typeinfo (e
, e
->newtype
);
2328 new_call
= build_libcall (libcall
, tb
, 1, arg
);
2330 if (e
->member
|| !e
->arguments
)
2332 /* Set the context pointer for nested structs. */
2333 if (sd
->isNested ())
2335 tree value
= build_vthis (sd
);
2336 tree field
= get_symbol_decl (sd
->vthis
);
2337 tree type
= build_ctype (stype
);
2339 new_call
= d_save_expr (new_call
);
2340 field
= component_ref (indirect_ref (type
, new_call
), field
);
2341 new_call
= compound_expr (modify_expr (field
, value
), new_call
);
2344 /* Call the struct constructor. */
2346 result
= d_build_call_expr (e
->member
, new_call
, e
->arguments
);
2352 /* If we have a user supplied initializer, then set-up with a
2354 if (e
->arguments
!= NULL
&& sd
->fields
.length
!= 0)
2356 StructLiteralExp
*se
= StructLiteralExp::create (e
->loc
, sd
,
2359 new_call
= d_save_expr (new_call
);
2360 se
->type
= sd
->type
;
2362 result
= compound_expr (build_expr (se
), new_call
);
2369 result
= compound_expr (build_expr (e
->argprefix
), result
);
2371 else if (tb
->ty
== TY::Tarray
)
2373 /* Allocating memory for a new D array. */
2374 tb
= e
->newtype
->toBasetype ();
2375 TypeDArray
*tarray
= tb
->isTypeDArray ();
2377 gcc_assert (e
->arguments
&& e
->arguments
->length
>= 1);
2379 if (e
->arguments
->length
== 1)
2381 /* Single dimension array allocations. */
2382 Expression
*arg
= (*e
->arguments
)[0];
2384 if (tarray
->next
->size () == 0)
2386 /* Array element size is unknown. */
2387 this->result_
= d_array_value (build_ctype (e
->type
),
2388 size_int (0), null_pointer_node
);
2392 libcall_fn libcall
= tarray
->next
->isZeroInit ()
2393 ? LIBCALL_NEWARRAYT
: LIBCALL_NEWARRAYIT
;
2394 result
= build_libcall (libcall
, tb
, 2,
2395 build_typeinfo (e
, e
->type
),
2400 /* Multidimensional array allocations. */
2401 tree tarray
= make_array_type (Type::tsize_t
, e
->arguments
->length
);
2402 tree var
= build_local_temp (tarray
);
2403 vec
<constructor_elt
, va_gc
> *elms
= NULL
;
2405 /* Get the base element type for the array, generating the
2406 initializer for the dims parameter along the way. */
2407 Type
*telem
= e
->newtype
->toBasetype ();
2408 for (size_t i
= 0; i
< e
->arguments
->length
; i
++)
2410 Expression
*arg
= (*e
->arguments
)[i
];
2411 CONSTRUCTOR_APPEND_ELT (elms
, size_int (i
), build_expr (arg
));
2413 gcc_assert (telem
->ty
== TY::Tarray
);
2414 telem
= telem
->toBasetype ()->nextOf ();
2418 /* Initialize the temporary. */
2419 tree init
= modify_expr (var
, build_constructor (tarray
, elms
));
2420 var
= compound_expr (init
, var
);
2422 /* Generate: _d_newarraymTX(ti, dims)
2423 or: _d_newarraymiTX(ti, dims) */
2424 libcall_fn libcall
= telem
->isZeroInit ()
2425 ? LIBCALL_NEWARRAYMTX
: LIBCALL_NEWARRAYMITX
;
2427 tree tinfo
= build_typeinfo (e
, e
->type
);
2428 tree dims
= d_array_value (build_ctype (Type::tsize_t
->arrayOf ()),
2429 size_int (e
->arguments
->length
),
2430 build_address (var
));
2432 result
= build_libcall (libcall
, tb
, 2, tinfo
, dims
);
2436 result
= compound_expr (build_expr (e
->argprefix
), result
);
2438 else if (tb
->ty
== TY::Tpointer
)
2440 /* Allocating memory for a new pointer. */
2441 TypePointer
*tpointer
= tb
->isTypePointer ();
2443 if (tpointer
->next
->size () == 0)
2445 /* Pointer element size is unknown. */
2446 this->result_
= d_convert (build_ctype (e
->type
),
2451 libcall_fn libcall
= tpointer
->next
->isZeroInit (e
->loc
)
2452 ? LIBCALL_NEWITEMT
: LIBCALL_NEWITEMIT
;
2454 tree arg
= build_typeinfo (e
, e
->newtype
);
2455 result
= build_libcall (libcall
, tb
, 1, arg
);
2457 if (e
->arguments
&& e
->arguments
->length
== 1)
2459 result
= d_save_expr (result
);
2460 tree init
= modify_expr (build_deref (result
),
2461 build_expr ((*e
->arguments
)[0]));
2462 result
= compound_expr (init
, result
);
2466 result
= compound_expr (build_expr (e
->argprefix
), result
);
2468 else if (tb
->ty
== TY::Taarray
)
2470 /* Allocating memory for a new associative array. */
2471 tree arg
= build_typeinfo (e
, e
->newtype
);
2472 tree mem
= build_libcall (LIBCALL_AANEW
, Type::tvoidptr
, 1, arg
);
2474 /* Return an associative array pointed to by MEM. */
2475 tree aatype
= build_ctype (tb
);
2476 vec
<constructor_elt
, va_gc
> *ce
= NULL
;
2477 CONSTRUCTOR_APPEND_ELT (ce
, TYPE_FIELDS (aatype
), mem
);
2479 result
= build_nop (build_ctype (e
->type
),
2480 build_constructor (aatype
, ce
));
2485 this->result_
= convert_expr (result
, tb
, e
->type
);
2488 /* Build an integer literal. */
2490 void visit (IntegerExp
*e
) final override
2492 tree ctype
= build_ctype (e
->type
->toBasetype ());
2493 this->result_
= build_integer_cst (e
->value
, ctype
);
2496 /* Build a floating-point literal. */
2498 void visit (RealExp
*e
) final override
2500 this->result_
= build_float_cst (e
->value
, e
->type
->toBasetype ());
2503 /* Build a complex literal. */
2505 void visit (ComplexExp
*e
) final override
2509 switch (e
->type
->toBasetype ()->ty
)
2511 case TY::Tcomplex32
:
2512 tnext
= (TypeBasic
*) Type::tfloat32
;
2515 case TY::Tcomplex64
:
2516 tnext
= (TypeBasic
*) Type::tfloat64
;
2519 case TY::Tcomplex80
:
2520 tnext
= (TypeBasic
*) Type::tfloat80
;
2527 this->result_
= build_complex (build_ctype (e
->type
),
2528 build_float_cst (creall (e
->value
), tnext
),
2529 build_float_cst (cimagl (e
->value
), tnext
));
2532 /* Build a string literal, all strings are null terminated except for
2535 void visit (StringExp
*e
) final override
2537 Type
*tb
= e
->type
->toBasetype ();
2538 tree type
= build_ctype (e
->type
);
2540 if (tb
->ty
== TY::Tsarray
)
2542 /* Turn the string into a constructor for the static array. */
2543 vec
<constructor_elt
, va_gc
> *elms
= NULL
;
2544 vec_safe_reserve (elms
, e
->len
);
2545 tree etype
= TREE_TYPE (type
);
2547 for (size_t i
= 0; i
< e
->len
; i
++)
2549 tree value
= build_integer_cst (e
->getCodeUnit (i
), etype
);
2550 CONSTRUCTOR_APPEND_ELT (elms
, size_int (i
), value
);
2553 tree ctor
= build_constructor (type
, elms
);
2554 TREE_CONSTANT (ctor
) = 1;
2555 this->result_
= ctor
;
2559 /* Copy the string contents to a null terminated string. */
2560 dinteger_t length
= (e
->len
* e
->sz
);
2561 char *string
= XALLOCAVEC (char, length
+ 1);
2563 memcpy (string
, e
->string
, length
);
2564 string
[length
] = '\0';
2566 /* String value and type includes the null terminator. */
2567 tree value
= build_string (length
, string
);
2568 TREE_TYPE (value
) = make_array_type (tb
->nextOf (), length
+ 1);
2569 value
= build_address (value
);
2571 if (tb
->ty
== TY::Tarray
)
2572 value
= d_array_value (type
, size_int (e
->len
), value
);
2574 TREE_CONSTANT (value
) = 1;
2575 this->result_
= d_convert (type
, value
);
2579 /* Build a tuple literal. Just an argument list that may have
2580 side effects that need evaluation. */
2582 void visit (TupleExp
*e
) final override
2584 tree result
= NULL_TREE
;
2587 result
= build_expr (e
->e0
, this->constp_
, true);
2589 for (size_t i
= 0; i
< e
->exps
->length
; ++i
)
2591 Expression
*exp
= (*e
->exps
)[i
];
2592 result
= compound_expr (result
, build_expr (exp
, this->constp_
, true));
2595 if (result
== NULL_TREE
)
2598 this->result_
= result
;
2601 /* Build an array literal. The common type of the all elements is taken to
2602 be the type of the array element, and all elements are implicitly
2603 converted to that type. */
2605 void visit (ArrayLiteralExp
*e
) final override
2607 Type
*tb
= e
->type
->toBasetype ();
2609 /* Implicitly convert void[n] to ubyte[n]. */
2610 if (tb
->ty
== TY::Tsarray
&& tb
->nextOf ()->toBasetype ()->ty
== TY::Tvoid
)
2611 tb
= Type::tuns8
->sarrayOf (tb
->isTypeSArray ()->dim
->toUInteger ());
2613 gcc_assert (tb
->ty
== TY::Tarray
|| tb
->ty
== TY::Tsarray
2614 || tb
->ty
== TY::Tpointer
);
2616 /* Handle empty array literals. */
2617 if (e
->elements
->length
== 0)
2619 if (tb
->ty
== TY::Tarray
)
2620 this->result_
= d_array_value (build_ctype (e
->type
),
2621 size_int (0), null_pointer_node
);
2623 this->result_
= build_constructor (make_array_type (tb
->nextOf (), 0),
2629 /* Build an expression that assigns the expressions in ELEMENTS to
2631 vec
<constructor_elt
, va_gc
> *elms
= NULL
;
2632 vec_safe_reserve (elms
, e
->elements
->length
);
2633 bool constant_p
= true;
2634 tree saved_elems
= NULL_TREE
;
2636 Type
*etype
= tb
->nextOf ();
2637 tree satype
= make_array_type (etype
, e
->elements
->length
);
2639 for (size_t i
= 0; i
< e
->elements
->length
; i
++)
2641 Expression
*expr
= e
->getElement (i
);
2642 tree value
= build_expr (expr
, this->constp_
, true);
2644 /* Only append nonzero values, the backend will zero out the rest
2645 of the constructor as we don't set CONSTRUCTOR_NO_CLEARING. */
2646 if (!initializer_zerop (value
))
2648 if (!TREE_CONSTANT (value
))
2651 /* Split construction of values out of the constructor if there
2652 may be side effects. */
2653 tree init
= stabilize_expr (&value
);
2654 if (init
!= NULL_TREE
)
2655 saved_elems
= compound_expr (saved_elems
, init
);
2657 CONSTRUCTOR_APPEND_ELT (elms
, size_int (i
),
2658 convert_expr (value
, expr
->type
, etype
));
2662 /* Now return the constructor as the correct type. For static arrays there
2663 is nothing else to do. For dynamic arrays, return a two field struct.
2664 For pointers, return the address. */
2665 tree ctor
= build_constructor (satype
, elms
);
2666 tree type
= build_ctype (e
->type
);
2668 /* Nothing else to do for static arrays. */
2669 if (tb
->ty
== TY::Tsarray
|| this->constp_
)
2671 /* Can't take the address of the constructor, so create an anonymous
2672 static symbol, and then refer to it. */
2673 if (tb
->ty
!= TY::Tsarray
)
2675 tree decl
= build_artificial_decl (TREE_TYPE (ctor
), ctor
, "A");
2676 ctor
= build_address (decl
);
2677 if (tb
->ty
== TY::Tarray
)
2678 ctor
= d_array_value (type
, size_int (e
->elements
->length
), ctor
);
2681 rest_of_decl_compilation (decl
, 1, 0);
2684 /* If the array literal is readonly or static. */
2686 TREE_CONSTANT (ctor
) = 1;
2687 if (constant_p
&& initializer_constant_valid_p (ctor
, TREE_TYPE (ctor
)))
2688 TREE_STATIC (ctor
) = 1;
2690 /* Use memset to fill any alignment holes in the array. */
2691 if (!this->constp_
&& !this->literalp_
)
2693 TypeStruct
*ts
= etype
->baseElemOf ()->isTypeStruct ();
2695 if (ts
!= NULL
&& (!identity_compare_p (ts
->sym
)
2696 || ts
->sym
->isUnionDeclaration ()))
2698 tree var
= build_local_temp (TREE_TYPE (ctor
));
2699 tree init
= build_memset_call (var
);
2700 /* Evaluate memset() first, then any saved elements. */
2701 saved_elems
= compound_expr (init
, saved_elems
);
2702 ctor
= compound_expr (modify_expr (var
, ctor
), var
);
2706 this->result_
= compound_expr (saved_elems
, d_convert (type
, ctor
));
2708 else if (e
->onstack
)
2710 /* Array literal for a `scope' dynamic array. */
2711 gcc_assert (tb
->ty
== TY::Tarray
);
2712 ctor
= force_target_expr (ctor
);
2713 this->result_
= d_array_value (type
, size_int (e
->elements
->length
),
2714 build_address (ctor
));
2718 /* Allocate space on the memory managed heap. */
2719 tree mem
= build_libcall (LIBCALL_ARRAYLITERALTX
,
2720 etype
->pointerTo (), 2,
2721 build_typeinfo (e
, etype
->arrayOf ()),
2722 size_int (e
->elements
->length
));
2723 mem
= d_save_expr (mem
);
2725 /* Now copy the constructor into memory. */
2726 tree size
= size_mult_expr (size_int (e
->elements
->length
),
2727 size_int (tb
->nextOf ()->size ()));
2729 tree result
= build_memcpy_call (mem
, build_address (ctor
), size
);
2731 /* Return the array pointed to by MEM. */
2732 result
= compound_expr (result
, mem
);
2734 if (tb
->ty
== TY::Tarray
)
2735 result
= d_array_value (type
, size_int (e
->elements
->length
), result
);
2737 this->result_
= compound_expr (saved_elems
, result
);
2741 /* Build an associative array literal. The common type of the all keys is
2742 taken to be the key type, and common type of all values the value type.
2743 All keys and values are then implicitly converted as needed. */
2745 void visit (AssocArrayLiteralExp
*e
) final override
2747 /* Want the mutable type for typeinfo reference. */
2748 Type
*tb
= e
->type
->toBasetype ()->mutableOf ();
2750 /* Handle empty assoc array literals. */
2751 TypeAArray
*ta
= tb
->isTypeAArray ();
2752 if (e
->keys
->length
== 0)
2754 this->result_
= build_constructor (build_ctype (ta
), NULL
);
2758 /* Build an expression that assigns all expressions in KEYS
2759 to a constructor. */
2760 tree akeys
= build_array_from_exprs (ta
->index
->sarrayOf (e
->keys
->length
),
2761 e
->keys
, this->constp_
);
2762 tree init
= stabilize_expr (&akeys
);
2764 /* Do the same with all expressions in VALUES. */
2765 tree avals
= build_array_from_exprs (ta
->next
->sarrayOf (e
->values
->length
),
2766 e
->values
, this->constp_
);
2767 init
= compound_expr (init
, stabilize_expr (&avals
));
2769 /* Generate: _d_assocarrayliteralTX (ti, keys, vals); */
2770 tree keys
= d_array_value (build_ctype (ta
->index
->arrayOf ()),
2771 size_int (e
->keys
->length
),
2772 build_address (akeys
));
2773 tree vals
= d_array_value (build_ctype (ta
->next
->arrayOf ()),
2774 size_int (e
->values
->length
),
2775 build_address (avals
));
2777 tree mem
= build_libcall (LIBCALL_ASSOCARRAYLITERALTX
, Type::tvoidptr
, 3,
2778 build_typeinfo (e
, ta
), keys
, vals
);
2780 /* Return an associative array pointed to by MEM. */
2781 tree aatype
= build_ctype (ta
);
2782 vec
<constructor_elt
, va_gc
> *ce
= NULL
;
2783 CONSTRUCTOR_APPEND_ELT (ce
, TYPE_FIELDS (aatype
), mem
);
2785 tree result
= build_nop (build_ctype (e
->type
),
2786 build_constructor (aatype
, ce
));
2787 this->result_
= compound_expr (init
, result
);
2790 /* Build a struct literal. */
2792 void visit (StructLiteralExp
*e
) final override
2794 /* Handle empty struct literals. */
2795 if (e
->elements
== NULL
|| e
->sd
->fields
.length
== 0)
2797 this->result_
= build_constructor (build_ctype (e
->type
), NULL
);
2801 /* Building sinit trees are delayed until after frontend semantic
2802 processing has complete. Build the static initializer now. */
2803 if (e
->useStaticInit
&& !this->constp_
)
2805 tree init
= aggregate_initializer_decl (e
->sd
);
2807 /* If initializing a symbol, don't forget to set it. */
2810 tree var
= build_deref (e
->sym
);
2811 init
= compound_expr (modify_expr (var
, init
), var
);
2814 this->result_
= init
;
2818 /* Build a constructor that assigns the expressions in ELEMENTS
2819 at each field index that has been filled in. */
2820 vec
<constructor_elt
, va_gc
> *ve
= NULL
;
2821 tree saved_elems
= NULL_TREE
;
2823 /* CTFE may fill the hidden pointer by NullExp. */
2824 gcc_assert (e
->elements
->length
<= e
->sd
->fields
.length
);
2826 Type
*tb
= e
->type
->toBasetype ();
2827 gcc_assert (tb
->ty
== TY::Tstruct
);
2829 for (size_t i
= 0; i
< e
->elements
->length
; i
++)
2831 Expression
*exp
= (*e
->elements
)[i
];
2835 VarDeclaration
*field
= e
->sd
->fields
[i
];
2836 Type
*type
= exp
->type
->toBasetype ();
2837 Type
*ftype
= field
->type
->toBasetype ();
2838 tree value
= NULL_TREE
;
2840 if (ftype
->ty
== TY::Tsarray
&& !same_type_p (type
, ftype
))
2842 /* Initialize a static array with a single element. */
2843 tree elem
= build_expr (exp
, this->constp_
, true);
2844 saved_elems
= compound_expr (saved_elems
, stabilize_expr (&elem
));
2845 elem
= d_save_expr (elem
);
2847 if (initializer_zerop (elem
))
2848 value
= build_constructor (build_ctype (ftype
), NULL
);
2850 value
= build_array_from_val (ftype
, elem
);
2854 value
= convert_expr (build_expr (exp
, this->constp_
, true),
2855 exp
->type
, field
->type
);
2858 /* Split construction of values out of the constructor. */
2859 saved_elems
= compound_expr (saved_elems
, stabilize_expr (&value
));
2861 CONSTRUCTOR_APPEND_ELT (ve
, get_symbol_decl (field
), value
);
2864 /* Maybe setup hidden pointer to outer scope context. */
2865 if (e
->sd
->isNested () && e
->elements
->length
!= e
->sd
->fields
.length
2866 && this->constp_
== false)
2868 tree field
= get_symbol_decl (e
->sd
->vthis
);
2869 tree value
= build_vthis (e
->sd
);
2870 CONSTRUCTOR_APPEND_ELT (ve
, field
, value
);
2871 gcc_assert (e
->useStaticInit
== false);
2874 /* Build a constructor in the correct shape of the aggregate type. */
2875 tree ctor
= build_struct_literal (build_ctype (e
->type
), ve
);
2877 /* Nothing more to do for constant literals. */
2880 /* If the struct literal is a valid for static data. */
2881 if (TREE_CONSTANT (ctor
)
2882 && initializer_constant_valid_p (ctor
, TREE_TYPE (ctor
)))
2883 TREE_STATIC (ctor
) = 1;
2885 this->result_
= compound_expr (saved_elems
, ctor
);
2889 /* Construct the struct literal for run-time. */
2892 /* Store the result in a symbol to initialize the literal. */
2893 tree var
= build_deref (e
->sym
);
2894 ctor
= compound_expr (modify_expr (var
, ctor
), var
);
2896 else if (!this->literalp_
)
2898 /* Use memset to fill any alignment holes in the object. */
2899 if (!identity_compare_p (e
->sd
) || e
->sd
->isUnionDeclaration ())
2901 tree var
= build_local_temp (TREE_TYPE (ctor
));
2902 tree init
= build_memset_call (var
);
2903 /* Evaluate memset() first, then any saved element constructors. */
2904 saved_elems
= compound_expr (init
, saved_elems
);
2905 ctor
= compound_expr (modify_expr (var
, ctor
), var
);
2909 this->result_
= compound_expr (saved_elems
, ctor
);
2912 /* Build a null literal. */
2914 void visit (NullExp
*e
) final override
2916 this->result_
= build_typeof_null_value (e
->type
);
2919 /* Build a vector literal. */
2921 void visit (VectorExp
*e
) final override
2923 /* First handle array literal expressions. */
2924 if (e
->e1
->op
== EXP::arrayLiteral
)
2926 ArrayLiteralExp
*ale
= e
->e1
->isArrayLiteralExp ();
2927 vec
<constructor_elt
, va_gc
> *elms
= NULL
;
2928 bool constant_p
= true;
2929 tree type
= build_ctype (e
->type
);
2931 vec_safe_reserve (elms
, ale
->elements
->length
);
2932 for (size_t i
= 0; i
< ale
->elements
->length
; i
++)
2934 Expression
*expr
= ale
->getElement (i
);
2935 tree value
= d_convert (TREE_TYPE (type
),
2936 build_expr (expr
, this->constp_
, true));
2937 if (!CONSTANT_CLASS_P (value
))
2940 CONSTRUCTOR_APPEND_ELT (elms
, size_int (i
), value
);
2943 /* Build a VECTOR_CST from a constant vector constructor. */
2945 this->result_
= build_vector_from_ctor (type
, elms
);
2947 this->result_
= build_constructor (type
, elms
);
2949 else if (e
->e1
->type
->toBasetype ()->ty
== TY::Tsarray
)
2951 /* Build a vector representation from a static array. */
2952 this->result_
= convert_expr (build_expr (e
->e1
, this->constp_
),
2953 e
->e1
->type
, e
->type
);
2957 /* Build constructor from single value. */
2958 tree type
= build_ctype (e
->type
);
2959 tree value
= d_convert (TREE_TYPE (type
),
2960 build_expr (e
->e1
, this->constp_
, true));
2961 this->result_
= build_vector_from_val (type
, value
);
2965 /* Build a static array representation of a vector expression. */
2967 void visit (VectorArrayExp
*e
) final override
2969 this->result_
= convert_expr (build_expr (e
->e1
, this->constp_
, true),
2970 e
->e1
->type
, e
->type
);
2973 /* Build a static class literal, return its reference. */
2975 void visit (ClassReferenceExp
*e
) final override
2977 /* The result of build_new_class_expr is a RECORD_TYPE, we want
2979 tree var
= build_address (build_new_class_expr (e
));
2981 /* If the type of this literal is an interface, the we must add the
2982 interface offset to symbol. */
2985 TypeClass
*tc
= e
->type
->toBasetype ()->isTypeClass ();
2986 InterfaceDeclaration
*to
= tc
->sym
->isInterfaceDeclaration ();
2990 ClassDeclaration
*from
= e
->originalClass ();
2993 gcc_assert (to
->isBaseOf (from
, &offset
) != 0);
2996 var
= build_offset (var
, size_int (offset
));
3000 this->result_
= var
;
3003 /* Build an uninitialized value, generated from void initializers. */
3005 void visit (VoidInitExp
*e
) final override
3007 /* The front-end only generates these for the initializer of globals.
3008 Represent `void' as zeroes, regardless of the type's default value. */
3009 gcc_assert (this->constp_
);
3010 this->result_
= build_zero_cst (build_ctype (e
->type
));
3013 /* These expressions are mainly just a placeholders in the frontend.
3014 We shouldn't see them here. */
3016 void visit (ScopeExp
*e
) final override
3018 error_at (make_location_t (e
->loc
), "%qs is not an expression",
3020 this->result_
= error_mark_node
;
3023 void visit (TypeExp
*e
) final override
3025 error_at (make_location_t (e
->loc
), "type %qs is not an expression",
3027 this->result_
= error_mark_node
;
3032 /* Main entry point for ExprVisitor interface to generate code for
3033 the Expression AST class E. If CONST_P is true, then E is a
3034 constant expression. If LITERAL_P is true, then E is a value used
3035 in the initialization of another literal. */
3038 build_expr (Expression
*e
, bool const_p
, bool literal_p
)
3040 ExprVisitor v
= ExprVisitor (const_p
, literal_p
);
3041 location_t saved_location
= input_location
;
3043 input_location
= make_location_t (e
->loc
);
3045 tree expr
= v
.result ();
3046 input_location
= saved_location
;
3048 /* Check if initializer expression is valid constant. */
3049 if (const_p
&& !initializer_constant_valid_p (expr
, TREE_TYPE (expr
)))
3051 error_at (make_location_t (e
->loc
), "non-constant expression %qs",
3053 return error_mark_node
;
3059 /* Same as build_expr, but also calls destructors on any temporaries. */
3062 build_expr_dtor (Expression
*e
)
3064 /* Codegen can be improved by determining if no exceptions can be thrown
3065 between the ctor and dtor, and eliminating the ctor and dtor. */
3066 size_t saved_vars
= vec_safe_length (d_function_chain
->vars_in_scope
);
3067 tree result
= build_expr (e
);
3069 if (saved_vars
!= vec_safe_length (d_function_chain
->vars_in_scope
))
3071 result
= fold_build_cleanup_point_expr (TREE_TYPE (result
), result
);
3072 vec_safe_truncate (d_function_chain
->vars_in_scope
, saved_vars
);
3078 /* Same as build_expr_dtor, but handles the result of E as a return value. */
3081 build_return_dtor (Expression
*e
, Type
*type
, TypeFunction
*tf
)
3083 size_t saved_vars
= vec_safe_length (d_function_chain
->vars_in_scope
);
3084 tree result
= build_expr (e
);
3086 /* Convert for initializing the DECL_RESULT. */
3089 /* If we are returning a reference, take the address. */
3090 result
= convert_expr (result
, e
->type
, type
);
3091 result
= build_address (result
);
3094 result
= convert_for_rvalue (result
, e
->type
, type
);
3096 /* The decl to store the return expression. */
3097 tree decl
= DECL_RESULT (cfun
->decl
);
3099 /* Split comma expressions, so that the result is returned directly. */
3100 tree expr
= stabilize_expr (&result
);
3101 result
= build_assign (INIT_EXPR
, decl
, result
);
3102 result
= compound_expr (expr
, return_expr (result
));
3104 /* May nest the return expression inside the try/finally expression. */
3105 if (saved_vars
!= vec_safe_length (d_function_chain
->vars_in_scope
))
3107 result
= fold_build_cleanup_point_expr (TREE_TYPE (result
), result
);
3108 vec_safe_truncate (d_function_chain
->vars_in_scope
, saved_vars
);