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