]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/d-codegen.cc
d: Fix a couple of ICEs found in the dmd front-end (PR97842)
[thirdparty/gcc.git] / gcc / d / d-codegen.cc
CommitLineData
b4c522fa 1/* d-codegen.cc -- Code generation and routines for manipulation of GCC trees.
8d9254fc 2 Copyright (C) 2006-2020 Free Software Foundation, Inc.
b4c522fa
IB
3
4GCC is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 3, or (at your option)
7any later version.
8
9GCC is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with GCC; see the file COPYING3. If not see
16<http://www.gnu.org/licenses/>. */
17
18#include "config.h"
19#include "system.h"
20#include "coretypes.h"
21
22#include "dmd/aggregate.h"
23#include "dmd/ctfe.h"
24#include "dmd/declaration.h"
25#include "dmd/identifier.h"
26#include "dmd/target.h"
27#include "dmd/template.h"
28
29#include "tree.h"
30#include "tree-iterator.h"
31#include "fold-const.h"
32#include "diagnostic.h"
33#include "langhooks.h"
34#include "target.h"
35#include "stringpool.h"
36#include "varasm.h"
37#include "stor-layout.h"
38#include "attribs.h"
39#include "function.h"
40
41#include "d-tree.h"
42
43
44/* Return the GCC location for the D frontend location LOC. */
45
46location_t
af3c19f0 47make_location_t (const Loc &loc)
b4c522fa
IB
48{
49 location_t gcc_location = input_location;
50
51 if (loc.filename)
52 {
53 linemap_add (line_table, LC_ENTER, 0, loc.filename, loc.linnum);
54 linemap_line_start (line_table, loc.linnum, 0);
55 gcc_location = linemap_position_for_column (line_table, loc.charnum);
56 linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
57 }
58
59 return gcc_location;
60}
61
62/* Return the DECL_CONTEXT for symbol DSYM. */
63
64tree
65d_decl_context (Dsymbol *dsym)
66{
67 Dsymbol *parent = dsym;
68 Declaration *decl = dsym->isDeclaration ();
75f758a7 69 AggregateDeclaration *ad = dsym->isAggregateDeclaration ();
b4c522fa 70
9dddefef 71 while ((parent = parent->toParent2 ()))
b4c522fa
IB
72 {
73 /* We've reached the top-level module namespace.
74 Set DECL_CONTEXT as the NAMESPACE_DECL of the enclosing module,
75 but only for extern(D) symbols. */
76 if (parent->isModule ())
77 {
75f758a7
IB
78 if ((decl != NULL && decl->linkage != LINKd)
79 || (ad != NULL && ad->classKind != ClassKind::d))
b4c522fa
IB
80 return NULL_TREE;
81
82 return build_import_decl (parent);
83 }
84
cdbf48be 85 /* Declarations marked as `static' or `__gshared' are never
b4c522fa
IB
86 part of any context except at module level. */
87 if (decl != NULL && decl->isDataseg ())
88 continue;
89
90 /* Nested functions. */
91 FuncDeclaration *fd = parent->isFuncDeclaration ();
92 if (fd != NULL)
93 return get_symbol_decl (fd);
94
95 /* Methods of classes or structs. */
96 AggregateDeclaration *ad = parent->isAggregateDeclaration ();
97 if (ad != NULL)
98 {
99 tree context = build_ctype (ad->type);
100 /* Want the underlying RECORD_TYPE. */
101 if (ad->isClassDeclaration ())
102 context = TREE_TYPE (context);
103
104 return context;
105 }
b4c522fa
IB
106 }
107
108 return NULL_TREE;
109}
110
111/* Return a copy of record TYPE but safe to modify in any way. */
112
113tree
114copy_aggregate_type (tree type)
115{
116 tree newtype = build_distinct_type_copy (type);
117 TYPE_FIELDS (newtype) = copy_list (TYPE_FIELDS (type));
118
119 for (tree f = TYPE_FIELDS (newtype); f; f = DECL_CHAIN (f))
120 DECL_FIELD_CONTEXT (f) = newtype;
121
122 return newtype;
123}
124
125/* Return TRUE if declaration DECL is a reference type. */
126
127bool
128declaration_reference_p (Declaration *decl)
129{
130 Type *tb = decl->type->toBasetype ();
131
132 /* Declaration is a reference type. */
133 if (tb->ty == Treference || decl->storage_class & (STCout | STCref))
134 return true;
135
136 return false;
137}
138
139/* Returns the real type for declaration DECL. */
140
141tree
142declaration_type (Declaration *decl)
143{
144 /* Lazy declarations are converted to delegates. */
145 if (decl->storage_class & STClazy)
146 {
c3a2ba10
IB
147 TypeFunction *tf = TypeFunction::create (NULL, decl->type,
148 VARARGnone, LINKd);
b4c522fa
IB
149 TypeDelegate *t = TypeDelegate::create (tf);
150 return build_ctype (t->merge2 ());
151 }
152
153 /* Static array va_list have array->pointer conversions applied. */
154 if (decl->isParameter () && valist_array_p (decl->type))
155 {
156 Type *valist = decl->type->nextOf ()->pointerTo ();
157 valist = valist->castMod (decl->type->mod);
158 return build_ctype (valist);
159 }
160
161 tree type = build_ctype (decl->type);
162
163 /* Parameter is passed by reference. */
164 if (declaration_reference_p (decl))
165 return build_reference_type (type);
166
cdbf48be 167 /* The `this' parameter is always const. */
b4c522fa
IB
168 if (decl->isThisDeclaration ())
169 return insert_type_modifiers (type, MODconst);
170
171 return type;
172}
173
174/* These should match the Declaration versions above
175 Return TRUE if parameter ARG is a reference type. */
176
177bool
2370bdbb 178parameter_reference_p (Parameter *arg)
b4c522fa
IB
179{
180 Type *tb = arg->type->toBasetype ();
181
182 /* Parameter is a reference type. */
183 if (tb->ty == Treference || arg->storageClass & (STCout | STCref))
184 return true;
185
b4c522fa
IB
186 return false;
187}
188
189/* Returns the real type for parameter ARG. */
190
191tree
2370bdbb 192parameter_type (Parameter *arg)
b4c522fa
IB
193{
194 /* Lazy parameters are converted to delegates. */
195 if (arg->storageClass & STClazy)
196 {
c3a2ba10
IB
197 TypeFunction *tf = TypeFunction::create (NULL, arg->type,
198 VARARGnone, LINKd);
b4c522fa
IB
199 TypeDelegate *t = TypeDelegate::create (tf);
200 return build_ctype (t->merge2 ());
201 }
202
203 /* Static array va_list have array->pointer conversions applied. */
204 if (valist_array_p (arg->type))
205 {
206 Type *valist = arg->type->nextOf ()->pointerTo ();
207 valist = valist->castMod (arg->type->mod);
208 return build_ctype (valist);
209 }
210
211 tree type = build_ctype (arg->type);
212
213 /* Parameter is passed by reference. */
2370bdbb 214 if (parameter_reference_p (arg))
b4c522fa
IB
215 return build_reference_type (type);
216
2370bdbb
IB
217 /* Pass non-POD structs by invisible reference. */
218 if (TREE_ADDRESSABLE (type))
219 {
220 type = build_reference_type (type);
221 /* There are no other pointer to this temporary. */
222 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
223 }
224
225 /* Front-end has already taken care of type promotions. */
b4c522fa
IB
226 return type;
227}
228
229/* Build INTEGER_CST of type TYPE with the value VALUE. */
230
231tree
232build_integer_cst (dinteger_t value, tree type)
233{
234 /* The type is error_mark_node, we can't do anything. */
235 if (error_operand_p (type))
236 return type;
237
238 return build_int_cst_type (type, value);
239}
240
241/* Build REAL_CST of type TOTYPE with the value VALUE. */
242
243tree
af3c19f0 244build_float_cst (const real_t &value, Type *totype)
b4c522fa
IB
245{
246 real_t new_value;
247 TypeBasic *tb = totype->isTypeBasic ();
248
249 gcc_assert (tb != NULL);
250
251 tree type_node = build_ctype (tb);
252 real_convert (&new_value.rv (), TYPE_MODE (type_node), &value.rv ());
253
254 return build_real (type_node, new_value.rv ());
255}
256
257/* Returns the .length component from the D dynamic array EXP. */
258
259tree
260d_array_length (tree exp)
261{
262 if (error_operand_p (exp))
263 return exp;
264
265 gcc_assert (TYPE_DYNAMIC_ARRAY (TREE_TYPE (exp)));
266
267 /* Get the back-end type for the array and pick out the array
268 length field (assumed to be the first field). */
269 tree len_field = TYPE_FIELDS (TREE_TYPE (exp));
270 return component_ref (exp, len_field);
271}
272
273/* Returns the .ptr component from the D dynamic array EXP. */
274
275tree
276d_array_ptr (tree exp)
277{
278 if (error_operand_p (exp))
279 return exp;
280
281 gcc_assert (TYPE_DYNAMIC_ARRAY (TREE_TYPE (exp)));
282
283 /* Get the back-end type for the array and pick out the array
284 data pointer field (assumed to be the second field). */
285 tree ptr_field = TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (exp)));
286 return component_ref (exp, ptr_field);
287}
288
289/* Returns a constructor for D dynamic array type TYPE of .length LEN
290 and .ptr pointing to DATA. */
291
292tree
293d_array_value (tree type, tree len, tree data)
294{
295 tree len_field, ptr_field;
af3c19f0 296 vec <constructor_elt, va_gc> *ce = NULL;
b4c522fa
IB
297
298 gcc_assert (TYPE_DYNAMIC_ARRAY (type));
299 len_field = TYPE_FIELDS (type);
300 ptr_field = TREE_CHAIN (len_field);
301
302 len = convert (TREE_TYPE (len_field), len);
303 data = convert (TREE_TYPE (ptr_field), data);
304
305 CONSTRUCTOR_APPEND_ELT (ce, len_field, len);
306 CONSTRUCTOR_APPEND_ELT (ce, ptr_field, data);
307
308 return build_constructor (type, ce);
309}
310
311/* Returns value representing the array length of expression EXP.
312 TYPE could be a dynamic or static array. */
313
314tree
315get_array_length (tree exp, Type *type)
316{
317 Type *tb = type->toBasetype ();
318
319 switch (tb->ty)
320 {
321 case Tsarray:
89fdaf5a 322 return size_int (tb->isTypeSArray ()->dim->toUInteger ());
b4c522fa
IB
323
324 case Tarray:
325 return d_array_length (exp);
326
327 default:
a9c697b8 328 error ("cannot determine the length of a %qs", type->toChars ());
b4c522fa
IB
329 return error_mark_node;
330 }
331}
332
333/* Create BINFO for a ClassDeclaration's inheritance tree.
334 InterfaceDeclaration's are not included. */
335
336tree
337build_class_binfo (tree super, ClassDeclaration *cd)
338{
339 tree binfo = make_tree_binfo (1);
340 tree ctype = build_ctype (cd->type);
341
342 /* Want RECORD_TYPE, not POINTER_TYPE. */
343 BINFO_TYPE (binfo) = TREE_TYPE (ctype);
344 BINFO_INHERITANCE_CHAIN (binfo) = super;
345 BINFO_OFFSET (binfo) = integer_zero_node;
346
347 if (cd->baseClass)
348 BINFO_BASE_APPEND (binfo, build_class_binfo (binfo, cd->baseClass));
349
350 return binfo;
351}
352
353/* Create BINFO for an InterfaceDeclaration's inheritance tree.
354 In order to access all inherited methods in the debugger,
355 the entire tree must be described.
356 This function makes assumptions about interface layout. */
357
358tree
af3c19f0 359build_interface_binfo (tree super, ClassDeclaration *cd, unsigned &offset)
b4c522fa 360{
2cbc99d1 361 tree binfo = make_tree_binfo (cd->baseclasses->length);
b4c522fa
IB
362 tree ctype = build_ctype (cd->type);
363
364 /* Want RECORD_TYPE, not POINTER_TYPE. */
365 BINFO_TYPE (binfo) = TREE_TYPE (ctype);
366 BINFO_INHERITANCE_CHAIN (binfo) = super;
5905cbdb 367 BINFO_OFFSET (binfo) = size_int (offset * target.ptrsize);
b4c522fa
IB
368 BINFO_VIRTUAL_P (binfo) = 1;
369
2cbc99d1 370 for (size_t i = 0; i < cd->baseclasses->length; i++, offset++)
b4c522fa
IB
371 {
372 BaseClass *bc = (*cd->baseclasses)[i];
373 BINFO_BASE_APPEND (binfo, build_interface_binfo (binfo, bc->sym, offset));
374 }
375
376 return binfo;
377}
378
379/* Returns the .funcptr component from the D delegate EXP. */
380
381tree
382delegate_method (tree exp)
383{
384 /* Get the back-end type for the delegate and pick out the funcptr field
385 (assumed to be the second field). */
386 gcc_assert (TYPE_DELEGATE (TREE_TYPE (exp)));
387 tree method_field = TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (exp)));
388 return component_ref (exp, method_field);
389}
390
391/* Returns the .object component from the delegate EXP. */
392
393tree
394delegate_object (tree exp)
395{
396 /* Get the back-end type for the delegate and pick out the object field
397 (assumed to be the first field). */
398 gcc_assert (TYPE_DELEGATE (TREE_TYPE (exp)));
399 tree obj_field = TYPE_FIELDS (TREE_TYPE (exp));
400 return component_ref (exp, obj_field);
401}
402
403/* Build a delegate literal of type TYPE whose pointer function is
404 METHOD, and hidden object is OBJECT. */
405
406tree
407build_delegate_cst (tree method, tree object, Type *type)
408{
409 tree ctor = make_node (CONSTRUCTOR);
410 tree ctype;
411
412 Type *tb = type->toBasetype ();
413 if (tb->ty == Tdelegate)
414 ctype = build_ctype (type);
415 else
416 {
417 /* Convert a function method into an anonymous delegate. */
418 ctype = make_struct_type ("delegate()", 2,
419 get_identifier ("object"), TREE_TYPE (object),
420 get_identifier ("func"), TREE_TYPE (method));
421 TYPE_DELEGATE (ctype) = 1;
422 }
423
af3c19f0 424 vec <constructor_elt, va_gc> *ce = NULL;
b4c522fa
IB
425 CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (ctype), object);
426 CONSTRUCTOR_APPEND_ELT (ce, TREE_CHAIN (TYPE_FIELDS (ctype)), method);
427
428 CONSTRUCTOR_ELTS (ctor) = ce;
429 TREE_TYPE (ctor) = ctype;
430
431 return ctor;
432}
433
434/* Builds a temporary tree to store the CALLEE and OBJECT
435 of a method call expression of type TYPE. */
436
437tree
438build_method_call (tree callee, tree object, Type *type)
439{
440 tree t = build_delegate_cst (callee, object, type);
441 METHOD_CALL_EXPR (t) = 1;
442 return t;
443}
444
445/* Extract callee and object from T and return in to CALLEE and OBJECT. */
446
447void
af3c19f0 448extract_from_method_call (tree t, tree &callee, tree &object)
b4c522fa
IB
449{
450 gcc_assert (METHOD_CALL_EXPR (t));
451 object = CONSTRUCTOR_ELT (t, 0)->value;
452 callee = CONSTRUCTOR_ELT (t, 1)->value;
453}
454
5e95646e
IB
455/* Build a typeof(null) constant of type TYPE. Handles certain special case
456 conversions, where the underlying type is an aggregate with a nullable
457 interior pointer. */
458
459tree
460build_typeof_null_value (Type *type)
461{
462 Type *tb = type->toBasetype ();
463 tree value;
464
465 /* For dynamic arrays, set length and pointer fields to zero. */
466 if (tb->ty == Tarray)
467 value = d_array_value (build_ctype (type), size_int (0), null_pointer_node);
468
469 /* For associative arrays, set the pointer field to null. */
470 else if (tb->ty == Taarray)
471 {
472 tree ctype = build_ctype (type);
473 gcc_assert (TYPE_ASSOCIATIVE_ARRAY (ctype));
474
475 value = build_constructor_single (ctype, TYPE_FIELDS (ctype),
476 null_pointer_node);
477 }
478
479 /* For delegates, set the frame and function pointer fields to null. */
480 else if (tb->ty == Tdelegate)
481 value = build_delegate_cst (null_pointer_node, null_pointer_node, type);
482
483 /* Simple zero constant for all other types. */
484 else
485 value = build_zero_cst (build_ctype (type));
486
487 TREE_CONSTANT (value) = 1;
488 return value;
489}
490
b4c522fa
IB
491/* Build a dereference into the virtual table for OBJECT to retrieve
492 a function pointer of type FNTYPE at position INDEX. */
493
494tree
495build_vindex_ref (tree object, tree fntype, size_t index)
496{
497 /* The vtable is the first field. Interface methods are also in the class's
498 vtable, so we don't need to convert from a class to an interface. */
499 tree result = build_deref (object);
500 result = component_ref (result, TYPE_FIELDS (TREE_TYPE (result)));
501
502 gcc_assert (POINTER_TYPE_P (fntype));
503
5905cbdb 504 return build_memref (fntype, result, size_int (target.ptrsize * index));
b4c522fa
IB
505}
506
507/* Return TRUE if EXP is a valid lvalue. Lvalue references cannot be
508 made into temporaries, otherwise any assignments will be lost. */
509
510static bool
511lvalue_p (tree exp)
512{
513 const enum tree_code code = TREE_CODE (exp);
514
515 switch (code)
516 {
517 case SAVE_EXPR:
518 return false;
519
520 case ARRAY_REF:
521 case INDIRECT_REF:
522 case VAR_DECL:
523 case PARM_DECL:
524 case RESULT_DECL:
525 return !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (exp));
526
527 case IMAGPART_EXPR:
528 case REALPART_EXPR:
529 case COMPONENT_REF:
530 CASE_CONVERT:
531 return lvalue_p (TREE_OPERAND (exp, 0));
532
533 case COND_EXPR:
534 return (lvalue_p (TREE_OPERAND (exp, 1)
535 ? TREE_OPERAND (exp, 1)
536 : TREE_OPERAND (exp, 0))
537 && lvalue_p (TREE_OPERAND (exp, 2)));
538
539 case TARGET_EXPR:
540 return true;
541
542 case COMPOUND_EXPR:
543 return lvalue_p (TREE_OPERAND (exp, 1));
544
545 default:
546 return false;
547 }
548}
549
550/* Create a SAVE_EXPR if EXP might have unwanted side effects if referenced
551 more than once in an expression. */
552
553tree
554d_save_expr (tree exp)
555{
556 if (TREE_SIDE_EFFECTS (exp))
557 {
558 if (lvalue_p (exp))
559 return stabilize_reference (exp);
560
561 return save_expr (exp);
562 }
563
564 return exp;
565}
566
567/* VALUEP is an expression we want to pre-evaluate or perform a computation on.
568 The expression returned by this function is the part whose value we don't
569 care about, storing the value in VALUEP. Callers must ensure that the
570 returned expression is evaluated before VALUEP. */
571
572tree
573stabilize_expr (tree *valuep)
574{
575 tree expr = *valuep;
576 const enum tree_code code = TREE_CODE (expr);
577 tree lhs;
578 tree rhs;
579
580 switch (code)
581 {
582 case COMPOUND_EXPR:
583 /* Given ((e1, ...), eN):
584 Store the last RHS 'eN' expression in VALUEP. */
585 lhs = TREE_OPERAND (expr, 0);
586 rhs = TREE_OPERAND (expr, 1);
587 lhs = compound_expr (lhs, stabilize_expr (&rhs));
588 *valuep = rhs;
589 return lhs;
590
591 default:
592 return NULL_TREE;
593 }
594}
595
596/* Return a TARGET_EXPR, initializing the DECL with EXP. */
597
598tree
599build_target_expr (tree decl, tree exp)
600{
601 tree type = TREE_TYPE (decl);
602 tree result = build4 (TARGET_EXPR, type, decl, exp, NULL_TREE, NULL_TREE);
603
604 if (EXPR_HAS_LOCATION (exp))
605 SET_EXPR_LOCATION (result, EXPR_LOCATION (exp));
606
607 /* If decl must always reside in memory. */
608 if (TREE_ADDRESSABLE (type))
609 d_mark_addressable (decl);
610
611 /* Always set TREE_SIDE_EFFECTS so that expand_expr does not ignore the
612 TARGET_EXPR. If there really turn out to be no side effects, then the
613 optimizer should be able to remove it. */
614 TREE_SIDE_EFFECTS (result) = 1;
615
616 return result;
617}
618
619/* Like the above function, but initializes a new temporary. */
620
621tree
622force_target_expr (tree exp)
623{
0af711e1
IB
624 tree decl = build_decl (input_location, VAR_DECL, NULL_TREE,
625 TREE_TYPE (exp));
626 DECL_CONTEXT (decl) = current_function_decl;
627 DECL_ARTIFICIAL (decl) = 1;
628 DECL_IGNORED_P (decl) = 1;
629 layout_decl (decl, 0);
b4c522fa
IB
630
631 return build_target_expr (decl, exp);
632}
633
634/* Returns the address of the expression EXP. */
635
636tree
637build_address (tree exp)
638{
639 if (error_operand_p (exp))
640 return exp;
641
642 tree ptrtype;
643 tree type = TREE_TYPE (exp);
644
645 if (TREE_CODE (exp) == STRING_CST)
646 {
647 /* Just convert string literals (char[]) to C-style strings (char *),
648 otherwise the latter method (char[]*) causes conversion problems
649 during gimplification. */
650 ptrtype = build_pointer_type (TREE_TYPE (type));
651 }
652 else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node)
653 && TREE_CODE (TYPE_MAIN_VARIANT (type)) == ARRAY_TYPE)
654 {
655 /* Special case for va_list, allow arrays to decay to a pointer. */
656 ptrtype = build_pointer_type (TREE_TYPE (type));
657 }
658 else
659 ptrtype = build_pointer_type (type);
660
661 /* Maybe rewrite: &(e1, e2) => (e1, &e2). */
662 tree init = stabilize_expr (&exp);
663
664 /* Can't take the address of a manifest constant, instead use its value. */
665 if (TREE_CODE (exp) == CONST_DECL)
666 exp = DECL_INITIAL (exp);
667
884efbd5
IB
668 /* Some expression lowering may request an address of a compile-time constant,
669 or other non-lvalue expression. Make sure it is assigned to a location we
670 can reference. */
1db88844 671 if (CONSTANT_CLASS_P (exp) && TREE_CODE (exp) != STRING_CST)
b4c522fa 672 exp = force_target_expr (exp);
1db88844
IB
673 else if (TREE_CODE (exp) == CALL_EXPR)
674 {
675 /* When a struct or array is returned in registers, we need to again fill
676 in all alignment holes. */
677 if (AGGREGATE_TYPE_P (TREE_TYPE (exp))
678 && !aggregate_value_p (TREE_TYPE (exp), exp))
679 {
680 tree tmp = build_local_temp (TREE_TYPE (exp));
681 init = compound_expr (init, build_memset_call (tmp));
682 init = compound_expr (init, modify_expr (tmp, exp));
683 exp = tmp;
684 }
685 else
686 exp = force_target_expr (exp);
687 }
b4c522fa
IB
688
689 d_mark_addressable (exp);
690 exp = build_fold_addr_expr_with_type_loc (input_location, exp, ptrtype);
691
692 if (TREE_CODE (exp) == ADDR_EXPR)
693 TREE_NO_TRAMPOLINE (exp) = 1;
694
695 return compound_expr (init, exp);
696}
697
698/* Mark EXP saying that we need to be able to take the
699 address of it; it should not be allocated in a register. */
700
701tree
702d_mark_addressable (tree exp)
703{
704 switch (TREE_CODE (exp))
705 {
706 case ADDR_EXPR:
707 case COMPONENT_REF:
708 case ARRAY_REF:
709 case REALPART_EXPR:
710 case IMAGPART_EXPR:
711 d_mark_addressable (TREE_OPERAND (exp, 0));
712 break;
713
714 case PARM_DECL:
715 case VAR_DECL:
716 case RESULT_DECL:
717 case CONST_DECL:
718 case FUNCTION_DECL:
719 TREE_ADDRESSABLE (exp) = 1;
720 break;
721
722 case CONSTRUCTOR:
723 TREE_ADDRESSABLE (exp) = 1;
724 break;
725
726 case TARGET_EXPR:
727 TREE_ADDRESSABLE (exp) = 1;
728 d_mark_addressable (TREE_OPERAND (exp, 0));
729 break;
730
731 default:
732 break;
733 }
734
735 return exp;
736}
737
738/* Mark EXP as "used" in the program for the benefit of
739 -Wunused warning purposes. */
740
741tree
742d_mark_used (tree exp)
743{
744 switch (TREE_CODE (exp))
745 {
746 case VAR_DECL:
747 case CONST_DECL:
748 case PARM_DECL:
749 case RESULT_DECL:
750 case FUNCTION_DECL:
751 TREE_USED (exp) = 1;
752 break;
753
754 case ARRAY_REF:
755 case COMPONENT_REF:
756 case MODIFY_EXPR:
757 case REALPART_EXPR:
758 case IMAGPART_EXPR:
759 case NOP_EXPR:
760 case CONVERT_EXPR:
761 case ADDR_EXPR:
762 d_mark_used (TREE_OPERAND (exp, 0));
763 break;
764
765 case COMPOUND_EXPR:
766 d_mark_used (TREE_OPERAND (exp, 0));
767 d_mark_used (TREE_OPERAND (exp, 1));
768 break;
769
770 default:
771 break;
772 }
773 return exp;
774}
775
776/* Mark EXP as read, not just set, for set but not used -Wunused
777 warning purposes. */
778
779tree
780d_mark_read (tree exp)
781{
782 switch (TREE_CODE (exp))
783 {
784 case VAR_DECL:
785 case PARM_DECL:
786 TREE_USED (exp) = 1;
787 DECL_READ_P (exp) = 1;
788 break;
789
790 case ARRAY_REF:
791 case COMPONENT_REF:
792 case MODIFY_EXPR:
793 case REALPART_EXPR:
794 case IMAGPART_EXPR:
795 case NOP_EXPR:
796 case CONVERT_EXPR:
797 case ADDR_EXPR:
798 d_mark_read (TREE_OPERAND (exp, 0));
799 break;
800
801 case COMPOUND_EXPR:
802 d_mark_read (TREE_OPERAND (exp, 1));
803 break;
804
805 default:
806 break;
807 }
808 return exp;
809}
810
ab0edbcb
IB
811/* Build a call to memcmp(), compares the first NUM bytes of PTR1 with PTR2. */
812
813tree
814build_memcmp_call (tree ptr1, tree ptr2, tree num)
815{
816 return build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP), 3,
817 ptr1, ptr2, num);
818}
819
820/* Build a call to memcpy(), copies the first NUM bytes of SRC into DST. */
821
822tree
823build_memcpy_call (tree dst, tree src, tree num)
824{
825 return build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
826 dst, src, num);
827}
828
829/* Build a call to memset(), fills the first NUM bytes of PTR with zeros.
830 If NUM is NULL, then we expect PTR to be object that requires filling. */
831
832tree
833build_memset_call (tree ptr, tree num)
834{
835 if (num == NULL_TREE)
836 {
837 gcc_assert (TREE_CODE (ptr) != ADDR_EXPR);
838 num = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
839 ptr = build_address (ptr);
840 }
841
1db88844
IB
842 /* Use a zero constant to fill the destination if setting the entire object.
843 For CONSTRUCTORs, the memcpy() is lowered to a ref-all pointer assignment,
844 which can then be merged with other stores to the object. */
845 tree valtype = TREE_TYPE (TREE_TYPE (ptr));
846 if (tree_int_cst_equal (TYPE_SIZE_UNIT (valtype), num))
847 {
848 tree cst = build_zero_cst (valtype);
849 if (TREE_CODE (cst) == CONSTRUCTOR)
850 return build_memcpy_call (ptr, build_address (cst), num);
851
852 return modify_expr (build_deref (ptr), cst);
853 }
854
ab0edbcb
IB
855 return build_call_expr (builtin_decl_explicit (BUILT_IN_MEMSET), 3,
856 ptr, integer_zero_node, num);
857}
858
b4c522fa
IB
859/* Return TRUE if the struct SD is suitable for comparison using memcmp.
860 This is because we don't guarantee that padding is zero-initialized for
861 a stack variable, so we can't use memcmp to compare struct values. */
862
863bool
864identity_compare_p (StructDeclaration *sd)
865{
866 if (sd->isUnionDeclaration ())
867 return true;
868
869 unsigned offset = 0;
870
2cbc99d1 871 for (size_t i = 0; i < sd->fields.length; i++)
b4c522fa
IB
872 {
873 VarDeclaration *vd = sd->fields[i];
5bdebb51 874 Type *tb = vd->type->toBasetype ();
b4c522fa
IB
875
876 /* Check inner data structures. */
89fdaf5a 877 if (TypeStruct *ts = tb->isTypeStruct ())
b4c522fa 878 {
b4c522fa
IB
879 if (!identity_compare_p (ts->sym))
880 return false;
881 }
882
5bdebb51
IB
883 /* Check for types that may have padding. */
884 if ((tb->ty == Tcomplex80 || tb->ty == Tfloat80 || tb->ty == Timaginary80)
5905cbdb 885 && target.realpad != 0)
5bdebb51
IB
886 return false;
887
b4c522fa
IB
888 if (offset <= vd->offset)
889 {
890 /* There's a hole in the struct. */
891 if (offset != vd->offset)
892 return false;
893
894 offset += vd->type->size ();
895 }
896 }
897
898 /* Any trailing padding may not be zero. */
899 if (offset < sd->structsize)
900 return false;
901
902 return true;
903}
904
5bdebb51
IB
905/* Build a floating-point identity comparison between T1 and T2, ignoring any
906 excessive padding in the type. CODE is EQ_EXPR or NE_EXPR comparison. */
907
908tree
909build_float_identity (tree_code code, tree t1, tree t2)
910{
5bdebb51 911 tree size = size_int (TYPE_PRECISION (TREE_TYPE (t1)) / BITS_PER_UNIT);
ab0edbcb
IB
912 tree result = build_memcmp_call (build_address (t1),
913 build_address (t2), size);
5bdebb51
IB
914 return build_boolop (code, result, integer_zero_node);
915}
916
b4c522fa
IB
917/* Lower a field-by-field equality expression between T1 and T2 of type SD.
918 CODE is the EQ_EXPR or NE_EXPR comparison. */
919
920static tree
921lower_struct_comparison (tree_code code, StructDeclaration *sd,
922 tree t1, tree t2)
923{
924 tree_code tcode = (code == EQ_EXPR) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
925 tree tmemcmp = NULL_TREE;
926
927 /* We can skip the compare if the structs are empty. */
2cbc99d1 928 if (sd->fields.length == 0)
b4c522fa
IB
929 {
930 tmemcmp = build_boolop (code, integer_zero_node, integer_zero_node);
931 if (TREE_SIDE_EFFECTS (t2))
932 tmemcmp = compound_expr (t2, tmemcmp);
933 if (TREE_SIDE_EFFECTS (t1))
934 tmemcmp = compound_expr (t1, tmemcmp);
935
936 return tmemcmp;
937 }
938
939 /* Let back-end take care of union comparisons. */
940 if (sd->isUnionDeclaration ())
941 {
ab0edbcb
IB
942 tmemcmp = build_memcmp_call (build_address (t1), build_address (t2),
943 size_int (sd->structsize));
b4c522fa
IB
944 return build_boolop (code, tmemcmp, integer_zero_node);
945 }
946
2cbc99d1 947 for (size_t i = 0; i < sd->fields.length; i++)
b4c522fa
IB
948 {
949 VarDeclaration *vd = sd->fields[i];
5bdebb51 950 Type *type = vd->type->toBasetype ();
b4c522fa
IB
951 tree sfield = get_symbol_decl (vd);
952
953 tree t1ref = component_ref (t1, sfield);
954 tree t2ref = component_ref (t2, sfield);
955 tree tcmp;
956
89fdaf5a 957 if (TypeStruct *ts = type->isTypeStruct ())
b4c522fa
IB
958 {
959 /* Compare inner data structures. */
89fdaf5a 960 tcmp = lower_struct_comparison (code, ts->sym, t1ref, t2ref);
b4c522fa 961 }
5bdebb51
IB
962 else if (type->ty != Tvector && type->isintegral ())
963 {
964 /* Integer comparison, no special handling required. */
965 tcmp = build_boolop (code, t1ref, t2ref);
966 }
967 else if (type->ty != Tvector && type->isfloating ())
968 {
969 /* Floating-point comparison, don't compare padding in type. */
970 if (!type->iscomplex ())
971 tcmp = build_float_identity (code, t1ref, t2ref);
972 else
973 {
974 tree req = build_float_identity (code, real_part (t1ref),
975 real_part (t2ref));
976 tree ieq = build_float_identity (code, imaginary_part (t1ref),
977 imaginary_part (t2ref));
978
979 tcmp = build_boolop (tcode, req, ieq);
980 }
981 }
b4c522fa
IB
982 else
983 {
5bdebb51 984 tree stype = build_ctype (type);
b4c522fa
IB
985 opt_scalar_int_mode mode = int_mode_for_mode (TYPE_MODE (stype));
986
5bdebb51 987 if (mode.exists ())
b4c522fa
IB
988 {
989 /* Compare field bits as their corresponding integer type.
990 *((T*) &t1) == *((T*) &t2) */
991 tree tmode = lang_hooks.types.type_for_mode (mode.require (), 1);
992
993 if (tmode == NULL_TREE)
994 tmode = make_unsigned_type (GET_MODE_BITSIZE (mode.require ()));
995
996 t1ref = build_vconvert (tmode, t1ref);
997 t2ref = build_vconvert (tmode, t2ref);
998
999 tcmp = build_boolop (code, t1ref, t2ref);
1000 }
1001 else
1002 {
1003 /* Simple memcmp between types. */
ab0edbcb
IB
1004 tcmp = build_memcmp_call (build_address (t1ref),
1005 build_address (t2ref),
1006 TYPE_SIZE_UNIT (stype));
b4c522fa
IB
1007 tcmp = build_boolop (code, tcmp, integer_zero_node);
1008 }
1009 }
1010
1011 tmemcmp = (tmemcmp) ? build_boolop (tcode, tmemcmp, tcmp) : tcmp;
1012 }
1013
1014 return tmemcmp;
1015}
1016
1017
1018/* Build an equality expression between two RECORD_TYPES T1 and T2 of type SD.
1019 If possible, use memcmp, otherwise field-by-field comparison is done.
1020 CODE is the EQ_EXPR or NE_EXPR comparison. */
1021
1022tree
1023build_struct_comparison (tree_code code, StructDeclaration *sd,
1024 tree t1, tree t2)
1025{
1026 /* We can skip the compare if the structs are empty. */
2cbc99d1 1027 if (sd->fields.length == 0)
b4c522fa
IB
1028 {
1029 tree exp = build_boolop (code, integer_zero_node, integer_zero_node);
1030 if (TREE_SIDE_EFFECTS (t2))
1031 exp = compound_expr (t2, exp);
1032 if (TREE_SIDE_EFFECTS (t1))
1033 exp = compound_expr (t1, exp);
1034
1035 return exp;
1036 }
1037
1038 /* Make temporaries to prevent multiple evaluations. */
1039 tree t1init = stabilize_expr (&t1);
1040 tree t2init = stabilize_expr (&t2);
1041 tree result;
1042
1043 t1 = d_save_expr (t1);
1044 t2 = d_save_expr (t2);
1045
1046 /* Bitwise comparison of structs not returned in memory may not work
1047 due to data holes loosing its zero padding upon return.
1048 As a heuristic, small structs are not compared using memcmp either. */
1049 if (TYPE_MODE (TREE_TYPE (t1)) != BLKmode || !identity_compare_p (sd))
1050 result = lower_struct_comparison (code, sd, t1, t2);
1051 else
1052 {
1053 /* Do bit compare of structs. */
ab0edbcb
IB
1054 tree tmemcmp = build_memcmp_call (build_address (t1), build_address (t2),
1055 size_int (sd->structsize));
b4c522fa
IB
1056 result = build_boolop (code, tmemcmp, integer_zero_node);
1057 }
1058
1059 return compound_expr (compound_expr (t1init, t2init), result);
1060}
1061
1062/* Build an equality expression between two ARRAY_TYPES of size LENGTH.
1063 The pointer references are T1 and T2, and the element type is SD.
1064 CODE is the EQ_EXPR or NE_EXPR comparison. */
1065
1066tree
1067build_array_struct_comparison (tree_code code, StructDeclaration *sd,
1068 tree length, tree t1, tree t2)
1069{
1070 tree_code tcode = (code == EQ_EXPR) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
1071
1072 /* Build temporary for the result of the comparison.
1073 Initialize as either 0 or 1 depending on operation. */
1074 tree result = build_local_temp (d_bool_type);
1075 tree init = build_boolop (code, integer_zero_node, integer_zero_node);
1076 add_stmt (build_assign (INIT_EXPR, result, init));
1077
1078 /* Cast pointer-to-array to pointer-to-struct. */
1079 tree ptrtype = build_ctype (sd->type->pointerTo ());
1080 tree lentype = TREE_TYPE (length);
1081
1082 push_binding_level (level_block);
1083 push_stmt_list ();
1084
1085 /* Build temporary locals for length and pointers. */
1086 tree t = build_local_temp (size_type_node);
1087 add_stmt (build_assign (INIT_EXPR, t, length));
1088 length = t;
1089
1090 t = build_local_temp (ptrtype);
1091 add_stmt (build_assign (INIT_EXPR, t, d_convert (ptrtype, t1)));
1092 t1 = t;
1093
1094 t = build_local_temp (ptrtype);
1095 add_stmt (build_assign (INIT_EXPR, t, d_convert (ptrtype, t2)));
1096 t2 = t;
1097
1098 /* Build loop for comparing each element. */
1099 push_stmt_list ();
1100
1101 /* Exit logic for the loop.
1102 if (length == 0 || result OP 0) break; */
1103 t = build_boolop (EQ_EXPR, length, d_convert (lentype, integer_zero_node));
1104 t = build_boolop (TRUTH_ORIF_EXPR, t, build_boolop (code, result,
1105 boolean_false_node));
1106 t = build1 (EXIT_EXPR, void_type_node, t);
1107 add_stmt (t);
1108
1109 /* Do comparison, caching the value.
1110 result = result OP (*t1 == *t2); */
1111 t = build_struct_comparison (code, sd, build_deref (t1), build_deref (t2));
1112 t = build_boolop (tcode, result, t);
1113 t = modify_expr (result, t);
1114 add_stmt (t);
1115
1116 /* Move both pointers to next element position.
1117 t1++, t2++; */
1118 tree size = d_convert (ptrtype, TYPE_SIZE_UNIT (TREE_TYPE (ptrtype)));
1119 t = build2 (POSTINCREMENT_EXPR, ptrtype, t1, size);
1120 add_stmt (t);
1121 t = build2 (POSTINCREMENT_EXPR, ptrtype, t2, size);
1122 add_stmt (t);
1123
1124 /* Decrease loop counter.
1125 length -= 1; */
1126 t = build2 (POSTDECREMENT_EXPR, lentype, length,
1127 d_convert (lentype, integer_one_node));
1128 add_stmt (t);
1129
1130 /* Pop statements and finish loop. */
1131 tree body = pop_stmt_list ();
1132 add_stmt (build1 (LOOP_EXPR, void_type_node, body));
1133
1134 /* Wrap it up into a bind expression. */
1135 tree stmt_list = pop_stmt_list ();
1136 tree block = pop_binding_level ();
1137
1138 body = build3 (BIND_EXPR, void_type_node,
1139 BLOCK_VARS (block), stmt_list, block);
1140
1141 return compound_expr (body, result);
1142}
1143
b4c522fa
IB
1144/* Build a constructor for a variable of aggregate type TYPE using the
1145 initializer INIT, an ordered flat list of fields and values provided
1146 by the frontend. The returned constructor should be a value that
1147 matches the layout of TYPE. */
1148
1149tree
af3c19f0 1150build_struct_literal (tree type, vec <constructor_elt, va_gc> *init)
b4c522fa
IB
1151{
1152 /* If the initializer was empty, use default zero initialization. */
1153 if (vec_safe_is_empty (init))
1154 return build_constructor (type, NULL);
1155
af3c19f0 1156 vec <constructor_elt, va_gc> *ve = NULL;
b4c522fa
IB
1157 HOST_WIDE_INT offset = 0;
1158 bool constant_p = true;
b4c522fa
IB
1159 bool finished = false;
1160
b4c522fa
IB
1161 /* Walk through each field, matching our initializer list. */
1162 for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
1163 {
1164 bool is_initialized = false;
1165 tree value;
1166
1167 if (DECL_NAME (field) == NULL_TREE
1168 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
1169 && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
1170 {
1171 /* Search all nesting aggregates, if nothing is found, then
1172 this will return an empty initializer to fill the hole. */
1173 value = build_struct_literal (TREE_TYPE (field), init);
1174
1175 if (!initializer_zerop (value))
1176 is_initialized = true;
1177 }
1178 else
1179 {
1180 /* Search for the value to initialize the next field. Once found,
1181 pop it from the init list so we don't look at it again. */
1182 unsigned HOST_WIDE_INT idx;
1183 tree index;
1184
1185 FOR_EACH_CONSTRUCTOR_ELT (init, idx, index, value)
1186 {
1187 /* If the index is NULL, then just assign it to the next field.
1188 This comes from layout_typeinfo(), which generates a flat
1189 list of values that we must shape into the record type. */
1190 if (index == field || index == NULL_TREE)
1191 {
1192 init->ordered_remove (idx);
1193 if (!finished)
1194 is_initialized = true;
1195 break;
1196 }
1197 }
1198 }
1199
1200 if (is_initialized)
1201 {
1202 HOST_WIDE_INT fieldpos = int_byte_position (field);
1203 gcc_assert (value != NULL_TREE);
1204
b4c522fa
IB
1205 /* Must not initialize fields that overlap. */
1206 if (fieldpos < offset)
1207 {
1208 /* Find the nearest user defined type and field. */
1209 tree vtype = type;
1210 while (ANON_AGGR_TYPE_P (vtype))
1211 vtype = TYPE_CONTEXT (vtype);
1212
1213 tree vfield = field;
1214 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (vfield))
1215 && ANON_AGGR_TYPE_P (TREE_TYPE (vfield)))
1216 vfield = TYPE_FIELDS (TREE_TYPE (vfield));
1217
1218 /* Must not generate errors for compiler generated fields. */
1219 gcc_assert (TYPE_NAME (vtype) && DECL_NAME (vfield));
1220 error ("overlapping initializer for field %qT.%qD",
1221 TYPE_NAME (vtype), DECL_NAME (vfield));
1222 }
1223
1224 if (!TREE_CONSTANT (value))
1225 constant_p = false;
1226
1227 CONSTRUCTOR_APPEND_ELT (ve, field, value);
1228
1229 /* For unions, only the first field is initialized, any other field
1230 initializers found for this union are drained and ignored. */
1231 if (TREE_CODE (type) == UNION_TYPE)
1232 finished = true;
1233 }
1234
1235 /* Move offset to the next position in the struct. */
1236 if (TREE_CODE (type) == RECORD_TYPE)
1237 {
1238 offset = int_byte_position (field)
1239 + int_size_in_bytes (TREE_TYPE (field));
1240 }
1241
1242 /* If all initializers have been assigned, there's nothing else to do. */
1243 if (vec_safe_is_empty (init))
1244 break;
1245 }
1246
b4c522fa
IB
1247 /* Ensure that we have consumed all values. */
1248 gcc_assert (vec_safe_is_empty (init) || ANON_AGGR_TYPE_P (type));
1249
1250 tree ctor = build_constructor (type, ve);
1251
1252 if (constant_p)
1253 TREE_CONSTANT (ctor) = 1;
1254
1255 return ctor;
1256}
1257
1258/* Given the TYPE of an anonymous field inside T, return the
1259 FIELD_DECL for the field. If not found return NULL_TREE.
1260 Because anonymous types can nest, we must also search all
1261 anonymous fields that are directly reachable. */
1262
1263static tree
1264lookup_anon_field (tree t, tree type)
1265{
1266 t = TYPE_MAIN_VARIANT (t);
1267
1268 for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
1269 {
1270 if (DECL_NAME (field) == NULL_TREE)
1271 {
1272 /* If we find it directly, return the field. */
1273 if (type == TYPE_MAIN_VARIANT (TREE_TYPE (field)))
1274 return field;
1275
1276 /* Otherwise, it could be nested, search harder. */
1277 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
1278 && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
1279 {
1280 tree subfield = lookup_anon_field (TREE_TYPE (field), type);
1281 if (subfield)
1282 return subfield;
1283 }
1284 }
1285 }
1286
1287 return NULL_TREE;
1288}
1289
1290/* Builds OBJECT.FIELD component reference. */
1291
1292tree
1293component_ref (tree object, tree field)
1294{
1295 if (error_operand_p (object) || error_operand_p (field))
1296 return error_mark_node;
1297
1298 gcc_assert (TREE_CODE (field) == FIELD_DECL);
1299
1300 /* Maybe rewrite: (e1, e2).field => (e1, e2.field) */
1301 tree init = stabilize_expr (&object);
1302
1303 /* If the FIELD is from an anonymous aggregate, generate a reference
1304 to the anonymous data member, and recur to find FIELD. */
1305 if (ANON_AGGR_TYPE_P (DECL_CONTEXT (field)))
1306 {
1307 tree anonymous_field = lookup_anon_field (TREE_TYPE (object),
1308 DECL_CONTEXT (field));
1309 object = component_ref (object, anonymous_field);
1310 }
1311
1312 tree result = fold_build3_loc (input_location, COMPONENT_REF,
1313 TREE_TYPE (field), object, field, NULL_TREE);
1314
1315 return compound_expr (init, result);
1316}
1317
1318/* Build an assignment expression of lvalue LHS from value RHS.
1319 CODE is the code for a binary operator that we use to combine
1320 the old value of LHS with RHS to get the new value. */
1321
1322tree
1323build_assign (tree_code code, tree lhs, tree rhs)
1324{
1325 tree init = stabilize_expr (&lhs);
1326 init = compound_expr (init, stabilize_expr (&rhs));
1327
1328 /* If initializing the LHS using a function that returns via NRVO. */
1329 if (code == INIT_EXPR && TREE_CODE (rhs) == CALL_EXPR
1330 && AGGREGATE_TYPE_P (TREE_TYPE (rhs))
1331 && aggregate_value_p (TREE_TYPE (rhs), rhs))
1332 {
1333 /* Mark as addressable here, which should ensure the return slot is the
1334 address of the LHS expression, taken care of by back-end. */
1335 d_mark_addressable (lhs);
1336 CALL_EXPR_RETURN_SLOT_OPT (rhs) = true;
1337 }
1338
1339 /* The LHS assignment replaces the temporary in TARGET_EXPR_SLOT. */
1340 if (TREE_CODE (rhs) == TARGET_EXPR)
1341 {
1342 /* If CODE is not INIT_EXPR, can't initialize LHS directly,
1343 since that would cause the LHS to be constructed twice.
1344 So we force the TARGET_EXPR to be expanded without a target. */
1345 if (code != INIT_EXPR)
1346 rhs = compound_expr (rhs, TARGET_EXPR_SLOT (rhs));
1347 else
1348 {
1349 d_mark_addressable (lhs);
1350 rhs = TARGET_EXPR_INITIAL (rhs);
1351 }
1352 }
1353
1354 tree result = fold_build2_loc (input_location, code,
1355 TREE_TYPE (lhs), lhs, rhs);
1356 return compound_expr (init, result);
1357}
1358
1359/* Build an assignment expression of lvalue LHS from value RHS. */
1360
1361tree
1362modify_expr (tree lhs, tree rhs)
1363{
1364 return build_assign (MODIFY_EXPR, lhs, rhs);
1365}
1366
1367/* Return EXP represented as TYPE. */
1368
1369tree
1370build_nop (tree type, tree exp)
1371{
1372 if (error_operand_p (exp))
1373 return exp;
1374
1375 /* Maybe rewrite: cast(TYPE)(e1, e2) => (e1, cast(TYPE) e2) */
1376 tree init = stabilize_expr (&exp);
1377 exp = fold_build1_loc (input_location, NOP_EXPR, type, exp);
1378
1379 return compound_expr (init, exp);
1380}
1381
1382/* Return EXP to be viewed as being another type TYPE. Same as build_nop,
1383 except that EXP is type-punned, rather than a straight-forward cast. */
1384
1385tree
1386build_vconvert (tree type, tree exp)
1387{
1388 /* Building *(cast(TYPE *)&e1) directly rather then using VIEW_CONVERT_EXPR
1389 makes sure this works for vector-to-array viewing, or if EXP ends up being
1390 used as the LHS of a MODIFY_EXPR. */
1391 return indirect_ref (type, build_address (exp));
1392}
1393
1394/* Maybe warn about ARG being an address that can never be null. */
1395
1396static void
1397warn_for_null_address (tree arg)
1398{
1399 if (TREE_CODE (arg) == ADDR_EXPR
1400 && decl_with_nonnull_addr_p (TREE_OPERAND (arg, 0)))
1401 warning (OPT_Waddress,
1402 "the address of %qD will never be %<null%>",
1403 TREE_OPERAND (arg, 0));
1404}
1405
1406/* Build a boolean ARG0 op ARG1 expression. */
1407
1408tree
1409build_boolop (tree_code code, tree arg0, tree arg1)
1410{
1411 /* Aggregate comparisons may get lowered to a call to builtin memcmp,
1412 so need to remove all side effects incase its address is taken. */
1413 if (AGGREGATE_TYPE_P (TREE_TYPE (arg0)))
1414 arg0 = d_save_expr (arg0);
1415 if (AGGREGATE_TYPE_P (TREE_TYPE (arg1)))
1416 arg1 = d_save_expr (arg1);
1417
1418 if (VECTOR_TYPE_P (TREE_TYPE (arg0)) && VECTOR_TYPE_P (TREE_TYPE (arg1)))
1419 {
1420 /* Build a vector comparison.
1421 VEC_COND_EXPR <e1 op e2, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>; */
1422 tree type = TREE_TYPE (arg0);
e8738f4e 1423 tree cmptype = truth_type_for (type);
b4c522fa
IB
1424 tree cmp = fold_build2_loc (input_location, code, cmptype, arg0, arg1);
1425
1426 return fold_build3_loc (input_location, VEC_COND_EXPR, type, cmp,
1427 build_minus_one_cst (type),
1428 build_zero_cst (type));
1429 }
1430
1431 if (code == EQ_EXPR || code == NE_EXPR)
1432 {
1433 /* Check if comparing the address of a variable to null. */
1434 if (POINTER_TYPE_P (TREE_TYPE (arg0)) && integer_zerop (arg1))
1435 warn_for_null_address (arg0);
1436 if (POINTER_TYPE_P (TREE_TYPE (arg1)) && integer_zerop (arg0))
1437 warn_for_null_address (arg1);
1438 }
1439
1440 return fold_build2_loc (input_location, code, d_bool_type,
1441 arg0, d_convert (TREE_TYPE (arg0), arg1));
1442}
1443
1444/* Return a COND_EXPR. ARG0, ARG1, and ARG2 are the three
1445 arguments to the conditional expression. */
1446
1447tree
1448build_condition (tree type, tree arg0, tree arg1, tree arg2)
1449{
1450 if (arg1 == void_node)
1451 arg1 = build_empty_stmt (input_location);
1452
1453 if (arg2 == void_node)
1454 arg2 = build_empty_stmt (input_location);
1455
1456 return fold_build3_loc (input_location, COND_EXPR,
1457 type, arg0, arg1, arg2);
1458}
1459
1460tree
1461build_vcondition (tree arg0, tree arg1, tree arg2)
1462{
1463 return build_condition (void_type_node, arg0, arg1, arg2);
1464}
1465
1466/* Build a compound expr to join ARG0 and ARG1 together. */
1467
1468tree
1469compound_expr (tree arg0, tree arg1)
1470{
1471 if (arg1 == NULL_TREE)
1472 return arg0;
1473
1474 if (arg0 == NULL_TREE || !TREE_SIDE_EFFECTS (arg0))
1475 return arg1;
1476
1477 if (TREE_CODE (arg1) == TARGET_EXPR)
1478 {
1479 /* If the rhs is a TARGET_EXPR, then build the compound expression
1480 inside the target_expr's initializer. This helps the compiler
1481 to eliminate unnecessary temporaries. */
1482 tree init = compound_expr (arg0, TARGET_EXPR_INITIAL (arg1));
1483 TARGET_EXPR_INITIAL (arg1) = init;
1484
1485 return arg1;
1486 }
1487
1488 return fold_build2_loc (input_location, COMPOUND_EXPR,
1489 TREE_TYPE (arg1), arg0, arg1);
1490}
1491
1492/* Build a return expression. */
1493
1494tree
1495return_expr (tree ret)
1496{
1497 return fold_build1_loc (input_location, RETURN_EXPR,
1498 void_type_node, ret);
1499}
1500
1501/* Return the product of ARG0 and ARG1 as a size_type_node. */
1502
1503tree
1504size_mult_expr (tree arg0, tree arg1)
1505{
1506 return fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1507 d_convert (size_type_node, arg0),
1508 d_convert (size_type_node, arg1));
1509
1510}
1511
1512/* Return the real part of CE, which should be a complex expression. */
1513
1514tree
1515real_part (tree ce)
1516{
1517 return fold_build1_loc (input_location, REALPART_EXPR,
1518 TREE_TYPE (TREE_TYPE (ce)), ce);
1519}
1520
1521/* Return the imaginary part of CE, which should be a complex expression. */
1522
1523tree
1524imaginary_part (tree ce)
1525{
1526 return fold_build1_loc (input_location, IMAGPART_EXPR,
1527 TREE_TYPE (TREE_TYPE (ce)), ce);
1528}
1529
1530/* Build a complex expression of type TYPE using RE and IM. */
1531
1532tree
1533complex_expr (tree type, tree re, tree im)
1534{
1535 return fold_build2_loc (input_location, COMPLEX_EXPR,
1536 type, re, im);
1537}
1538
1539/* Cast EXP (which should be a pointer) to TYPE* and then indirect.
1540 The back-end requires this cast in many cases. */
1541
1542tree
1543indirect_ref (tree type, tree exp)
1544{
1545 if (error_operand_p (exp))
1546 return exp;
1547
1548 /* Maybe rewrite: *(e1, e2) => (e1, *e2) */
1549 tree init = stabilize_expr (&exp);
1550
1551 if (TREE_CODE (TREE_TYPE (exp)) == REFERENCE_TYPE)
1552 exp = fold_build1 (INDIRECT_REF, type, exp);
1553 else
1554 {
1555 exp = build_nop (build_pointer_type (type), exp);
1556 exp = build_deref (exp);
1557 }
1558
1559 return compound_expr (init, exp);
1560}
1561
1562/* Returns indirect reference of EXP, which must be a pointer type. */
1563
1564tree
1565build_deref (tree exp)
1566{
1567 if (error_operand_p (exp))
1568 return exp;
1569
1570 /* Maybe rewrite: *(e1, e2) => (e1, *e2) */
1571 tree init = stabilize_expr (&exp);
1572
1573 gcc_assert (POINTER_TYPE_P (TREE_TYPE (exp)));
1574
1575 if (TREE_CODE (exp) == ADDR_EXPR)
1576 exp = TREE_OPERAND (exp, 0);
1577 else
1578 exp = build_fold_indirect_ref (exp);
1579
1580 return compound_expr (init, exp);
1581}
1582
1583/* Builds pointer offset expression PTR[INDEX]. */
1584
1585tree
1586build_array_index (tree ptr, tree index)
1587{
1588 if (error_operand_p (ptr) || error_operand_p (index))
1589 return error_mark_node;
1590
1591 tree ptr_type = TREE_TYPE (ptr);
1592 tree target_type = TREE_TYPE (ptr_type);
1593
1594 tree type = lang_hooks.types.type_for_size (TYPE_PRECISION (sizetype),
1595 TYPE_UNSIGNED (sizetype));
1596
1597 /* Array element size. */
1598 tree size_exp = size_in_bytes (target_type);
1599
1600 if (integer_zerop (size_exp))
1601 {
1602 /* Test for array of void. */
1603 if (TYPE_MODE (target_type) == TYPE_MODE (void_type_node))
1604 index = fold_convert (type, index);
1605 else
1606 {
1607 /* Should catch this earlier. */
1608 error ("invalid use of incomplete type %qD", TYPE_NAME (target_type));
1609 ptr_type = error_mark_node;
1610 }
1611 }
1612 else if (integer_onep (size_exp))
1613 {
1614 /* Array of bytes -- No need to multiply. */
1615 index = fold_convert (type, index);
1616 }
1617 else
1618 {
1619 index = d_convert (type, index);
1620 index = fold_build2 (MULT_EXPR, TREE_TYPE (index),
1621 index, d_convert (TREE_TYPE (index), size_exp));
1622 index = fold_convert (type, index);
1623 }
1624
1625 if (integer_zerop (index))
1626 return ptr;
1627
1628 return fold_build2 (POINTER_PLUS_EXPR, ptr_type, ptr, index);
1629}
1630
1631/* Builds pointer offset expression *(PTR OP OFFSET)
1632 OP could be a plus or minus expression. */
1633
1634tree
1635build_offset_op (tree_code op, tree ptr, tree offset)
1636{
1637 gcc_assert (op == MINUS_EXPR || op == PLUS_EXPR);
1638
1639 tree type = lang_hooks.types.type_for_size (TYPE_PRECISION (sizetype),
1640 TYPE_UNSIGNED (sizetype));
1641 offset = fold_convert (type, offset);
1642
1643 if (op == MINUS_EXPR)
1644 offset = fold_build1 (NEGATE_EXPR, type, offset);
1645
1646 return fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr, offset);
1647}
1648
1649/* Builds pointer offset expression *(PTR + OFFSET). */
1650
1651tree
1652build_offset (tree ptr, tree offset)
1653{
1654 return build_offset_op (PLUS_EXPR, ptr, offset);
1655}
1656
1657tree
1658build_memref (tree type, tree ptr, tree offset)
1659{
1660 return fold_build2 (MEM_REF, type, ptr, fold_convert (type, offset));
1661}
1662
1663/* Create a tree node to set multiple elements to a single value. */
1664
1665tree
1666build_array_set (tree ptr, tree length, tree value)
1667{
1668 tree ptrtype = TREE_TYPE (ptr);
1669 tree lentype = TREE_TYPE (length);
1670
1671 push_binding_level (level_block);
1672 push_stmt_list ();
1673
1674 /* Build temporary locals for length and ptr, and maybe value. */
1675 tree t = build_local_temp (size_type_node);
1676 add_stmt (build_assign (INIT_EXPR, t, length));
1677 length = t;
1678
1679 t = build_local_temp (ptrtype);
1680 add_stmt (build_assign (INIT_EXPR, t, ptr));
1681 ptr = t;
1682
1683 if (TREE_SIDE_EFFECTS (value))
1684 {
1685 t = build_local_temp (TREE_TYPE (value));
1686 add_stmt (build_assign (INIT_EXPR, t, value));
1687 value = t;
1688 }
1689
1690 /* Build loop to initialize { .length=length, .ptr=ptr } with value. */
1691 push_stmt_list ();
1692
1693 /* Exit logic for the loop.
1694 if (length == 0) break; */
1695 t = build_boolop (EQ_EXPR, length, d_convert (lentype, integer_zero_node));
1696 t = build1 (EXIT_EXPR, void_type_node, t);
1697 add_stmt (t);
1698
1699 /* Assign value to the current pointer position.
1700 *ptr = value; */
1701 t = modify_expr (build_deref (ptr), value);
1702 add_stmt (t);
1703
1704 /* Move pointer to next element position.
1705 ptr++; */
1706 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptrtype));
1707 t = build2 (POSTINCREMENT_EXPR, ptrtype, ptr, d_convert (ptrtype, size));
1708 add_stmt (t);
1709
1710 /* Decrease loop counter.
1711 length -= 1; */
1712 t = build2 (POSTDECREMENT_EXPR, lentype, length,
1713 d_convert (lentype, integer_one_node));
1714 add_stmt (t);
1715
1716 /* Pop statements and finish loop. */
1717 tree loop_body = pop_stmt_list ();
1718 add_stmt (build1 (LOOP_EXPR, void_type_node, loop_body));
1719
1720 /* Wrap it up into a bind expression. */
1721 tree stmt_list = pop_stmt_list ();
1722 tree block = pop_binding_level ();
1723
1724 return build3 (BIND_EXPR, void_type_node,
1725 BLOCK_VARS (block), stmt_list, block);
1726}
1727
1728
1729/* Build an array of type TYPE where all the elements are VAL. */
1730
1731tree
1732build_array_from_val (Type *type, tree val)
1733{
b4c522fa
IB
1734 tree etype = build_ctype (type->nextOf ());
1735
1736 /* Initializing a multidimensional array. */
1737 if (TREE_CODE (etype) == ARRAY_TYPE && TREE_TYPE (val) != etype)
1738 val = build_array_from_val (type->nextOf (), val);
1739
89fdaf5a 1740 size_t dims = type->isTypeSArray ()->dim->toInteger ();
af3c19f0 1741 vec <constructor_elt, va_gc> *elms = NULL;
b4c522fa
IB
1742 vec_safe_reserve (elms, dims);
1743
1744 val = d_convert (etype, val);
1745
1746 for (size_t i = 0; i < dims; i++)
1747 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), val);
1748
1749 return build_constructor (build_ctype (type), elms);
1750}
1751
7508a7e9
IB
1752/* Build a static array of type TYPE from an array of EXPS.
1753 If CONST_P is true, then all elements in EXPS are constants. */
1754
1755tree
1756build_array_from_exprs (Type *type, Expressions *exps, bool const_p)
1757{
1758 /* Build a CONSTRUCTOR from all expressions. */
1759 vec <constructor_elt, va_gc> *elms = NULL;
1760 vec_safe_reserve (elms, exps->length);
1761
1762 Type *etype = type->nextOf ();
1763 tree satype = make_array_type (etype, exps->length);
1764
1765 for (size_t i = 0; i < exps->length; i++)
1766 {
1767 Expression *expr = (*exps)[i];
1768 tree t = build_expr (expr, const_p);
1769 CONSTRUCTOR_APPEND_ELT (elms, size_int (i),
1770 convert_expr (t, expr->type, etype));
1771 }
1772
1773 /* Create a new temporary to store the array. */
1774 tree var = build_local_temp (satype);
1775
1776 /* Fill any alignment holes with zeroes. */
1777 TypeStruct *ts = etype->baseElemOf ()->isTypeStruct ();
1778 tree init = NULL;
1779 if (ts && (!identity_compare_p (ts->sym) || ts->sym->isUnionDeclaration ()))
1780 init = build_memset_call (var);
1781
1782 /* Initialize the temporary. */
1783 tree assign = modify_expr (var, build_constructor (satype, elms));
1784 return compound_expr (compound_expr (init, assign), var);
1785}
1786
1787
b4c522fa
IB
1788/* Implicitly converts void* T to byte* as D allows { void[] a; &a[3]; } */
1789
1790tree
1791void_okay_p (tree t)
1792{
1793 tree type = TREE_TYPE (t);
1794
1795 if (VOID_TYPE_P (TREE_TYPE (type)))
1796 {
1797 tree totype = build_ctype (Type::tuns8->pointerTo ());
1798 return fold_convert (totype, t);
1799 }
1800
1801 return t;
1802}
1803
f267a310
IB
1804/* Builds a CALL_EXPR at location LOC in the source file to execute when an
1805 array bounds check fails. */
1806
1807tree
1808build_array_bounds_call (const Loc &loc)
1809{
1810 switch (global.params.checkAction)
1811 {
1812 case CHECKACTION_D:
1813 return d_assert_call (loc, LIBCALL_ARRAY_BOUNDS);
1814
1815 case CHECKACTION_C:
1816 case CHECKACTION_halt:
1817 return build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1818
1819 default:
1820 gcc_unreachable ();
1821 }
1822}
1823
b4c522fa
IB
1824/* Builds a bounds condition checking that INDEX is between 0 and LEN.
1825 The condition returns the INDEX if true, or throws a RangeError.
1826 If INCLUSIVE, we allow INDEX == LEN to return true also. */
1827
1828tree
af3c19f0 1829build_bounds_condition (const Loc &loc, tree index, tree len, bool inclusive)
b4c522fa
IB
1830{
1831 if (!array_bounds_check ())
1832 return index;
1833
1834 /* Prevent multiple evaluations of the index. */
1835 index = d_save_expr (index);
1836
1837 /* Generate INDEX >= LEN && throw RangeError.
1838 No need to check whether INDEX >= 0 as the front-end should
1839 have already taken care of implicit casts to unsigned. */
1840 tree condition = fold_build2 (inclusive ? GT_EXPR : GE_EXPR,
1841 d_bool_type, index, len);
c0aebc60 1842 /* Terminate the program with a trap if no D runtime present. */
f267a310 1843 tree boundserr = build_array_bounds_call (loc);
b4c522fa
IB
1844
1845 return build_condition (TREE_TYPE (index), condition, boundserr, index);
1846}
1847
1848/* Returns TRUE if array bounds checking code generation is turned on. */
1849
1850bool
1851array_bounds_check (void)
1852{
1853 FuncDeclaration *fd;
1854
1855 switch (global.params.useArrayBounds)
1856 {
0cdc55f5 1857 case CHECKENABLEoff:
b4c522fa
IB
1858 return false;
1859
0cdc55f5 1860 case CHECKENABLEon:
b4c522fa
IB
1861 return true;
1862
0cdc55f5 1863 case CHECKENABLEsafeonly:
b4c522fa
IB
1864 /* For D2 safe functions only. */
1865 fd = d_function_chain->function;
1866 if (fd && fd->type->ty == Tfunction)
1867 {
89fdaf5a 1868 if (fd->type->isTypeFunction ()->trust == TRUSTsafe)
b4c522fa
IB
1869 return true;
1870 }
1871 return false;
1872
1873 default:
1874 gcc_unreachable ();
1875 }
1876}
1877
b4c522fa
IB
1878/* Returns the TypeFunction class for Type T.
1879 Assumes T is already ->toBasetype(). */
1880
1881TypeFunction *
1882get_function_type (Type *t)
1883{
1884 TypeFunction *tf = NULL;
1885 if (t->ty == Tpointer)
1886 t = t->nextOf ()->toBasetype ();
1887 if (t->ty == Tfunction)
89fdaf5a 1888 tf = t->isTypeFunction ();
b4c522fa 1889 else if (t->ty == Tdelegate)
89fdaf5a 1890 tf = t->isTypeDelegate ()->next->isTypeFunction ();
b4c522fa
IB
1891 return tf;
1892}
1893
1894/* Returns TRUE if CALLEE is a plain nested function outside the scope of
1895 CALLER. In which case, CALLEE is being called through an alias that was
1896 passed to CALLER. */
1897
1898bool
1899call_by_alias_p (FuncDeclaration *caller, FuncDeclaration *callee)
1900{
1901 if (!callee->isNested ())
1902 return false;
1903
1904 if (caller->toParent () == callee->toParent ())
1905 return false;
1906
1907 Dsymbol *dsym = callee;
1908
1909 while (dsym)
1910 {
1911 if (dsym->isTemplateInstance ())
1912 return false;
1913 else if (dsym->isFuncDeclaration () == caller)
1914 return false;
1915 dsym = dsym->toParent ();
1916 }
1917
1918 return true;
1919}
1920
1921/* Entry point for call routines. Builds a function call to FD.
cdbf48be 1922 OBJECT is the `this' reference passed and ARGS are the arguments to FD. */
b4c522fa
IB
1923
1924tree
1925d_build_call_expr (FuncDeclaration *fd, tree object, Expressions *arguments)
1926{
1927 return d_build_call (get_function_type (fd->type),
1928 build_address (get_symbol_decl (fd)), object, arguments);
1929}
1930
cdbf48be 1931/* Builds a CALL_EXPR of type TF to CALLABLE. OBJECT holds the `this' pointer,
b4c522fa
IB
1932 ARGUMENTS are evaluated in left to right order, saved and promoted
1933 before passing. */
1934
1935tree
1936d_build_call (TypeFunction *tf, tree callable, tree object,
1937 Expressions *arguments)
1938{
1939 tree ctype = TREE_TYPE (callable);
1940 tree callee = callable;
1941
1942 if (POINTER_TYPE_P (ctype))
1943 ctype = TREE_TYPE (ctype);
1944 else
1945 callee = build_address (callable);
1946
1947 gcc_assert (FUNC_OR_METHOD_TYPE_P (ctype));
1948 gcc_assert (tf != NULL);
1949 gcc_assert (tf->ty == Tfunction);
1950
1951 if (TREE_CODE (ctype) != FUNCTION_TYPE && object == NULL_TREE)
1952 {
1953 /* Front-end apparently doesn't check this. */
1954 if (TREE_CODE (callable) == FUNCTION_DECL)
1955 {
1956 error ("need %<this%> to access member %qE", DECL_NAME (callable));
1957 return error_mark_node;
1958 }
1959
1960 /* Probably an internal error. */
1961 gcc_unreachable ();
1962 }
1963
1964 /* Build the argument list for the call. */
af3c19f0 1965 vec <tree, va_gc> *args = NULL;
b4c522fa
IB
1966 tree saved_args = NULL_TREE;
1967
1968 /* If this is a delegate call or a nested function being called as
1969 a delegate, the object should not be NULL. */
1970 if (object != NULL_TREE)
1971 vec_safe_push (args, object);
1972
1973 if (arguments)
1974 {
1975 /* First pass, evaluated expanded tuples in function arguments. */
2cbc99d1 1976 for (size_t i = 0; i < arguments->length; ++i)
b4c522fa
IB
1977 {
1978 Lagain:
1979 Expression *arg = (*arguments)[i];
1980 gcc_assert (arg->op != TOKtuple);
1981
1982 if (arg->op == TOKcomma)
1983 {
d873350a 1984 CommaExp *ce = arg->isCommaExp ();
b4c522fa
IB
1985 tree tce = build_expr (ce->e1);
1986 saved_args = compound_expr (saved_args, tce);
1987 (*arguments)[i] = ce->e2;
1988 goto Lagain;
1989 }
1990 }
1991
c3a2ba10 1992 size_t nparams = tf->parameterList.length ();
b4c522fa 1993 /* if _arguments[] is the first argument. */
c3a2ba10 1994 size_t varargs = tf->isDstyleVariadic ();
b4c522fa 1995
2cbc99d1
IB
1996 /* Assumes arguments->length <= formal_args->length if (!tf->varargs). */
1997 for (size_t i = 0; i < arguments->length; ++i)
b4c522fa
IB
1998 {
1999 Expression *arg = (*arguments)[i];
2000 tree targ = build_expr (arg);
2001
2002 if (i - varargs < nparams && i >= varargs)
2003 {
2004 /* Actual arguments for declared formal arguments. */
c3a2ba10 2005 Parameter *parg = tf->parameterList[i - varargs];
b4c522fa
IB
2006 targ = convert_for_argument (targ, parg);
2007 }
2008
2009 /* Don't pass empty aggregates by value. */
2010 if (empty_aggregate_p (TREE_TYPE (targ)) && !TREE_ADDRESSABLE (targ)
2011 && TREE_CODE (targ) != CONSTRUCTOR)
2012 {
2013 tree t = build_constructor (TREE_TYPE (targ), NULL);
2014 targ = build2 (COMPOUND_EXPR, TREE_TYPE (t), targ, t);
2015 }
2016
312ad889 2017 /* Parameter is a struct or array passed by invisible reference. */
2370bdbb
IB
2018 if (TREE_ADDRESSABLE (TREE_TYPE (targ)))
2019 {
2020 Type *t = arg->type->toBasetype ();
312ad889 2021 StructDeclaration *sd = t->baseElemOf ()->isTypeStruct ()->sym;
2370bdbb
IB
2022
2023 /* Nested structs also have ADDRESSABLE set, but if the type has
2024 neither a copy constructor nor a destructor available, then we
2025 need to take care of copying its value before passing it. */
2026 if (arg->op == TOKstructliteral || (!sd->postblit && !sd->dtor))
2027 targ = force_target_expr (targ);
2028
2029 targ = convert (build_reference_type (TREE_TYPE (targ)),
2030 build_address (targ));
2031 }
2032
b4c522fa
IB
2033 vec_safe_push (args, targ);
2034 }
2035 }
2036
2037 /* Evaluate the callee before calling it. */
2038 if (TREE_SIDE_EFFECTS (callee))
2039 {
2040 callee = d_save_expr (callee);
2041 saved_args = compound_expr (callee, saved_args);
2042 }
2043
2044 tree result = build_call_vec (TREE_TYPE (ctype), callee, args);
707e9159 2045 SET_EXPR_LOCATION (result, input_location);
b4c522fa
IB
2046
2047 /* Enforce left to right evaluation. */
2048 if (tf->linkage == LINKd)
2049 CALL_EXPR_ARGS_ORDERED (result) = 1;
2050
2051 result = maybe_expand_intrinsic (result);
2052
2053 /* Return the value in a temporary slot so that it can be evaluated
2054 multiple times by the caller. */
2055 if (TREE_CODE (result) == CALL_EXPR
2056 && AGGREGATE_TYPE_P (TREE_TYPE (result))
2057 && TREE_ADDRESSABLE (TREE_TYPE (result)))
2058 {
2059 CALL_EXPR_RETURN_SLOT_OPT (result) = true;
2060 result = force_target_expr (result);
2061 }
2062
2063 return compound_expr (saved_args, result);
2064}
2065
2066/* Builds a call to AssertError or AssertErrorMsg. */
2067
2068tree
af3c19f0 2069d_assert_call (const Loc &loc, libcall_fn libcall, tree msg)
b4c522fa
IB
2070{
2071 tree file;
2072 tree line = size_int (loc.linnum);
2073
2074 /* File location is passed as a D string. */
2075 if (loc.filename)
2076 {
2077 unsigned len = strlen (loc.filename);
2078 tree str = build_string (len, loc.filename);
2079 TREE_TYPE (str) = make_array_type (Type::tchar, len);
2080
2081 file = d_array_value (build_ctype (Type::tchar->arrayOf ()),
2082 size_int (len), build_address (str));
2083 }
2084 else
2085 file = null_array_node;
2086
2087 if (msg != NULL)
2088 return build_libcall (libcall, Type::tvoid, 3, msg, file, line);
2089 else
2090 return build_libcall (libcall, Type::tvoid, 2, file, line);
2091}
2092
2093/* Build and return the correct call to fmod depending on TYPE.
2094 ARG0 and ARG1 are the arguments pass to the function. */
2095
2096tree
2097build_float_modulus (tree type, tree arg0, tree arg1)
2098{
2099 tree fmodfn = NULL_TREE;
2100 tree basetype = type;
2101
2102 if (COMPLEX_FLOAT_TYPE_P (basetype))
2103 basetype = TREE_TYPE (basetype);
2104
2105 if (TYPE_MAIN_VARIANT (basetype) == double_type_node
2106 || TYPE_MAIN_VARIANT (basetype) == idouble_type_node)
2107 fmodfn = builtin_decl_explicit (BUILT_IN_FMOD);
2108 else if (TYPE_MAIN_VARIANT (basetype) == float_type_node
2109 || TYPE_MAIN_VARIANT (basetype) == ifloat_type_node)
2110 fmodfn = builtin_decl_explicit (BUILT_IN_FMODF);
2111 else if (TYPE_MAIN_VARIANT (basetype) == long_double_type_node
2112 || TYPE_MAIN_VARIANT (basetype) == ireal_type_node)
2113 fmodfn = builtin_decl_explicit (BUILT_IN_FMODL);
2114
2115 if (!fmodfn)
2116 {
2117 error ("tried to perform floating-point modulo division on %qT", type);
2118 return error_mark_node;
2119 }
2120
2121 if (COMPLEX_FLOAT_TYPE_P (type))
2122 {
2123 tree re = build_call_expr (fmodfn, 2, real_part (arg0), arg1);
2124 tree im = build_call_expr (fmodfn, 2, imaginary_part (arg0), arg1);
2125
2126 return complex_expr (type, re, im);
2127 }
2128
2129 if (SCALAR_FLOAT_TYPE_P (type))
2130 return build_call_expr (fmodfn, 2, arg0, arg1);
2131
2132 /* Should have caught this above. */
2133 gcc_unreachable ();
2134}
2135
2136/* Build a function type whose first argument is a pointer to BASETYPE,
cdbf48be 2137 which is to be used for the `vthis' context parameter for TYPE.
b4c522fa
IB
2138 The base type may be a record for member functions, or a void for
2139 nested functions and delegates. */
2140
2141tree
2142build_vthis_function (tree basetype, tree type)
2143{
2144 gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
2145
2146 tree argtypes = tree_cons (NULL_TREE, build_pointer_type (basetype),
2147 TYPE_ARG_TYPES (type));
2148 tree fntype = build_function_type (TREE_TYPE (type), argtypes);
2149
2150 if (RECORD_OR_UNION_TYPE_P (basetype))
2151 TYPE_METHOD_BASETYPE (fntype) = TYPE_MAIN_VARIANT (basetype);
2152 else
2153 gcc_assert (VOID_TYPE_P (basetype));
2154
2155 return fntype;
2156}
2157
2b1c2a4b
IB
2158/* Raise an error at that the context pointer of the function or object SYM is
2159 not accessible from the current scope. */
2160
2161tree
2162error_no_frame_access (Dsymbol *sym)
2163{
2164 error_at (input_location, "cannot get frame pointer to %qs",
2165 sym->toPrettyChars ());
2166 return null_pointer_node;
2167}
2168
b4c522fa
IB
2169/* If SYM is a nested function, return the static chain to be
2170 used when calling that function from the current function.
2171
2172 If SYM is a nested class or struct, return the static chain
2173 to be used when creating an instance of the class from CFUN. */
2174
2175tree
2176get_frame_for_symbol (Dsymbol *sym)
2177{
2178 FuncDeclaration *thisfd
2179 = d_function_chain ? d_function_chain->function : NULL;
2180 FuncDeclaration *fd = sym->isFuncDeclaration ();
2181 FuncDeclaration *fdparent = NULL;
2182 FuncDeclaration *fdoverride = NULL;
2183
2184 if (fd != NULL)
2185 {
2186 /* Check that the nested function is properly defined. */
2187 if (!fd->fbody)
2188 {
cdbf48be 2189 /* Should instead error on line that references `fd'. */
b4c522fa
IB
2190 error_at (make_location_t (fd->loc), "nested function missing body");
2191 return null_pointer_node;
2192 }
2193
2194 fdparent = fd->toParent2 ()->isFuncDeclaration ();
2195
2196 /* Special case for __ensure and __require. */
2197 if ((fd->ident == Identifier::idPool ("__ensure")
2198 || fd->ident == Identifier::idPool ("__require"))
2199 && fdparent != thisfd)
2200 {
2201 fdoverride = fdparent;
2202 fdparent = thisfd;
2203 }
2204 }
2205 else
2206 {
2207 /* It's a class (or struct). NewExp codegen has already determined its
2208 outer scope is not another class, so it must be a function. */
2209 while (sym && !sym->isFuncDeclaration ())
2210 sym = sym->toParent2 ();
2211
2212 fdparent = (FuncDeclaration *) sym;
2213 }
2214
9fa5d5de
IB
2215 /* Not a nested function, there is no frame pointer to pass. */
2216 if (fdparent == NULL)
2217 {
2218 /* Only delegate literals report as being nested, even if they are in
2219 global scope. */
2220 gcc_assert (fd && fd->isFuncLiteralDeclaration ());
2221 return null_pointer_node;
2222 }
2223
2224 gcc_assert (thisfd != NULL);
b4c522fa
IB
2225
2226 if (thisfd != fdparent)
2227 {
2228 /* If no frame pointer for this function. */
2229 if (!thisfd->vthis)
2230 {
2231 error_at (make_location_t (sym->loc),
9fa5d5de 2232 "%qs is a nested function and cannot be accessed from %qs",
2b1c2a4b 2233 fdparent->toPrettyChars (), thisfd->toPrettyChars ());
b4c522fa
IB
2234 return null_pointer_node;
2235 }
2236
2237 /* Make sure we can get the frame pointer to the outer function.
2238 Go up each nesting level until we find the enclosing function. */
2239 Dsymbol *dsym = thisfd;
2240
2241 while (fd != dsym)
2242 {
2243 /* Check if enclosing function is a function. */
2b1c2a4b
IB
2244 FuncDeclaration *fdp = dsym->isFuncDeclaration ();
2245 Dsymbol *parent = dsym->toParent2 ();
b4c522fa 2246
2b1c2a4b 2247 if (fdp != NULL)
b4c522fa 2248 {
2b1c2a4b 2249 if (fdparent == parent)
b4c522fa
IB
2250 break;
2251
2b1c2a4b
IB
2252 gcc_assert (fdp->isNested () || fdp->vthis);
2253 dsym = parent;
b4c522fa
IB
2254 continue;
2255 }
2256
2257 /* Check if enclosed by an aggregate. That means the current
2258 function must be a member function of that aggregate. */
2b1c2a4b 2259 AggregateDeclaration *adp = dsym->isAggregateDeclaration ();
b4c522fa 2260
2b1c2a4b 2261 if (adp != NULL)
b4c522fa 2262 {
2b1c2a4b
IB
2263 if ((adp->isClassDeclaration () || adp->isStructDeclaration ())
2264 && fdparent == parent)
2265 break;
b4c522fa
IB
2266 }
2267
2b1c2a4b
IB
2268 /* No frame to outer function found. */
2269 if (!adp || !adp->isNested () || !adp->vthis)
2270 return error_no_frame_access (sym);
2271
2272 dsym = parent;
b4c522fa
IB
2273 }
2274 }
2275
2276 tree ffo = get_frameinfo (fdparent);
2277 if (FRAMEINFO_CREATES_FRAME (ffo) || FRAMEINFO_STATIC_CHAIN (ffo))
2278 {
2279 tree frame_ref = get_framedecl (thisfd, fdparent);
2280
cdbf48be 2281 /* If `thisfd' is a derived member function, then `fdparent' is the
b4c522fa
IB
2282 overridden member function in the base class. Even if there's a
2283 closure environment, we should give the original stack data as the
2284 nested function frame. */
2285 if (fdoverride)
2286 {
2287 ClassDeclaration *cdo = fdoverride->isThis ()->isClassDeclaration ();
2288 ClassDeclaration *cd = thisfd->isThis ()->isClassDeclaration ();
2289 gcc_assert (cdo && cd);
2290
2291 int offset;
2292 if (cdo->isBaseOf (cd, &offset) && offset != 0)
2293 {
2294 /* Generate a new frame to pass to the overriden function that
cdbf48be 2295 has the `this' pointer adjusted. */
b4c522fa
IB
2296 gcc_assert (offset != OFFSET_RUNTIME);
2297
2298 tree type = FRAMEINFO_TYPE (get_frameinfo (fdoverride));
2299 tree fields = TYPE_FIELDS (type);
cdbf48be 2300 /* The `this' field comes immediately after the `__chain'. */
b4c522fa 2301 tree thisfield = chain_index (1, fields);
af3c19f0 2302 vec <constructor_elt, va_gc> *ve = NULL;
b4c522fa
IB
2303
2304 tree framefields = TYPE_FIELDS (FRAMEINFO_TYPE (ffo));
2305 frame_ref = build_deref (frame_ref);
2306
2307 for (tree field = fields; field; field = DECL_CHAIN (field))
2308 {
2309 tree value = component_ref (frame_ref, framefields);
2310 if (field == thisfield)
2311 value = build_offset (value, size_int (offset));
2312
2313 CONSTRUCTOR_APPEND_ELT (ve, field, value);
2314 framefields = DECL_CHAIN (framefields);
2315 }
2316
2317 frame_ref = build_address (build_constructor (type, ve));
2318 }
2319 }
2320
2321 return frame_ref;
2322 }
2323
2324 return null_pointer_node;
2325}
2326
2327/* Return the parent function of a nested class CD. */
2328
2329static FuncDeclaration *
2330d_nested_class (ClassDeclaration *cd)
2331{
2332 FuncDeclaration *fd = NULL;
2333 while (cd && cd->isNested ())
2334 {
2335 Dsymbol *dsym = cd->toParent2 ();
2336 if ((fd = dsym->isFuncDeclaration ()))
2337 return fd;
2338 else
2339 cd = dsym->isClassDeclaration ();
2340 }
2341 return NULL;
2342}
2343
2344/* Return the parent function of a nested struct SD. */
2345
2346static FuncDeclaration *
2347d_nested_struct (StructDeclaration *sd)
2348{
2349 FuncDeclaration *fd = NULL;
2350 while (sd && sd->isNested ())
2351 {
2352 Dsymbol *dsym = sd->toParent2 ();
2353 if ((fd = dsym->isFuncDeclaration ()))
2354 return fd;
2355 else
2356 sd = dsym->isStructDeclaration ();
2357 }
2358 return NULL;
2359}
2360
2361
2362/* Starting from the current function FD, try to find a suitable value of
cdbf48be 2363 `this' in nested function instances. A suitable `this' value is an
b4c522fa
IB
2364 instance of OCD or a class that has OCD as a base. */
2365
2366static tree
2367find_this_tree (ClassDeclaration *ocd)
2368{
2369 FuncDeclaration *fd = d_function_chain ? d_function_chain->function : NULL;
2370
2371 while (fd)
2372 {
2373 AggregateDeclaration *ad = fd->isThis ();
2374 ClassDeclaration *cd = ad ? ad->isClassDeclaration () : NULL;
2375
2376 if (cd != NULL)
2377 {
2378 if (ocd == cd)
2379 return get_decl_tree (fd->vthis);
2380 else if (ocd->isBaseOf (cd, NULL))
2381 return convert_expr (get_decl_tree (fd->vthis),
2382 cd->type, ocd->type);
2383
2384 fd = d_nested_class (cd);
2385 }
2386 else
2387 {
2388 if (fd->isNested ())
2389 {
2390 fd = fd->toParent2 ()->isFuncDeclaration ();
2391 continue;
2392 }
2393
2394 fd = NULL;
2395 }
2396 }
2397
2398 return NULL_TREE;
2399}
2400
cdbf48be 2401/* Retrieve the outer class/struct `this' value of DECL from
b4c522fa
IB
2402 the current function. */
2403
2404tree
2405build_vthis (AggregateDeclaration *decl)
2406{
2407 ClassDeclaration *cd = decl->isClassDeclaration ();
2408 StructDeclaration *sd = decl->isStructDeclaration ();
2409
2410 /* If an aggregate nested in a function has no methods and there are no
2411 other nested functions, any static chain created here will never be
2412 translated. Use a null pointer for the link in this case. */
2413 tree vthis_value = null_pointer_node;
2414
2415 if (cd != NULL || sd != NULL)
2416 {
2417 Dsymbol *outer = decl->toParent2 ();
2418
2419 /* If the parent is a templated struct, the outer context is instead
2420 the enclosing symbol of where the instantiation happened. */
2421 if (outer->isStructDeclaration ())
2422 {
2423 gcc_assert (outer->parent && outer->parent->isTemplateInstance ());
2424 outer = ((TemplateInstance *) outer->parent)->enclosing;
2425 }
2426
cdbf48be 2427 /* For outer classes, get a suitable `this' value.
b4c522fa
IB
2428 For outer functions, get a suitable frame/closure pointer. */
2429 ClassDeclaration *cdo = outer->isClassDeclaration ();
2430 FuncDeclaration *fdo = outer->isFuncDeclaration ();
2431
2432 if (cdo)
2433 {
2434 vthis_value = find_this_tree (cdo);
2435 gcc_assert (vthis_value != NULL_TREE);
2436 }
2437 else if (fdo)
2438 {
2439 tree ffo = get_frameinfo (fdo);
2440 if (FRAMEINFO_CREATES_FRAME (ffo) || FRAMEINFO_STATIC_CHAIN (ffo)
2441 || fdo->hasNestedFrameRefs ())
2442 vthis_value = get_frame_for_symbol (decl);
2443 else if (cd != NULL)
2444 {
2445 /* Classes nested in methods are allowed to access any outer
2446 class fields, use the function chain in this case. */
2447 if (fdo->vthis && fdo->vthis->type != Type::tvoidptr)
2448 vthis_value = get_decl_tree (fdo->vthis);
2449 }
2450 }
2451 else
2452 gcc_unreachable ();
2453 }
2454
2455 return vthis_value;
2456}
2457
2458/* Build the RECORD_TYPE that describes the function frame or closure type for
2459 the function FD. FFI is the tree holding all frame information. */
2460
2461static tree
2462build_frame_type (tree ffi, FuncDeclaration *fd)
2463{
2464 if (FRAMEINFO_TYPE (ffi))
2465 return FRAMEINFO_TYPE (ffi);
2466
2467 tree frame_rec_type = make_node (RECORD_TYPE);
2468 char *name = concat (FRAMEINFO_IS_CLOSURE (ffi) ? "CLOSURE." : "FRAME.",
2469 fd->toPrettyChars (), NULL);
2470 TYPE_NAME (frame_rec_type) = get_identifier (name);
2471 free (name);
2472
2473 tree fields = NULL_TREE;
2474
2475 /* Function is a member or nested, so must have field for outer context. */
2476 if (fd->vthis)
2477 {
2478 tree ptr_field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2479 get_identifier ("__chain"), ptr_type_node);
2480 DECL_FIELD_CONTEXT (ptr_field) = frame_rec_type;
2481 fields = chainon (NULL_TREE, ptr_field);
2482 DECL_NONADDRESSABLE_P (ptr_field) = 1;
2483 }
2484
2485 /* The __ensure and __require are called directly, so never make the outer
2486 functions closure, but nevertheless could still be referencing parameters
2487 of the calling function non-locally. So we add all parameters with nested
2488 refs to the function frame, this should also mean overriding methods will
2489 have the same frame layout when inheriting a contract. */
0cdc55f5
IB
2490 if ((global.params.useIn == CHECKENABLEon && fd->frequire)
2491 || (global.params.useOut == CHECKENABLEon && fd->fensure))
b4c522fa
IB
2492 {
2493 if (fd->parameters)
2494 {
2cbc99d1 2495 for (size_t i = 0; fd->parameters && i < fd->parameters->length; i++)
b4c522fa
IB
2496 {
2497 VarDeclaration *v = (*fd->parameters)[i];
2498 /* Remove if already in closureVars so can push to front. */
2cbc99d1 2499 for (size_t j = i; j < fd->closureVars.length; j++)
b4c522fa
IB
2500 {
2501 Dsymbol *s = fd->closureVars[j];
2502 if (s == v)
2503 {
2504 fd->closureVars.remove (j);
2505 break;
2506 }
2507 }
2508 fd->closureVars.insert (i, v);
2509 }
2510 }
2511
cdbf48be 2512 /* Also add hidden `this' to outer context. */
b4c522fa
IB
2513 if (fd->vthis)
2514 {
2cbc99d1 2515 for (size_t i = 0; i < fd->closureVars.length; i++)
b4c522fa
IB
2516 {
2517 Dsymbol *s = fd->closureVars[i];
2518 if (s == fd->vthis)
2519 {
2520 fd->closureVars.remove (i);
2521 break;
2522 }
2523 }
2524 fd->closureVars.insert (0, fd->vthis);
2525 }
2526 }
2527
2cbc99d1 2528 for (size_t i = 0; i < fd->closureVars.length; i++)
b4c522fa
IB
2529 {
2530 VarDeclaration *v = fd->closureVars[i];
2531 tree vsym = get_symbol_decl (v);
2532 tree ident = v->ident
2533 ? get_identifier (v->ident->toChars ()) : NULL_TREE;
2534
2535 tree field = build_decl (make_location_t (v->loc), FIELD_DECL, ident,
2536 TREE_TYPE (vsym));
2537 SET_DECL_LANG_FRAME_FIELD (vsym, field);
2538 DECL_FIELD_CONTEXT (field) = frame_rec_type;
2539 fields = chainon (fields, field);
2540 TREE_USED (vsym) = 1;
2541
2542 TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (vsym);
2543 DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (vsym);
2544 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (vsym);
2545
2546 /* Can't do nrvo if the variable is put in a frame. */
2547 if (fd->nrvo_can && fd->nrvo_var == v)
2548 fd->nrvo_can = 0;
2549
2550 if (FRAMEINFO_IS_CLOSURE (ffi))
2551 {
2552 /* Because the value needs to survive the end of the scope. */
2553 if ((v->edtor && (v->storage_class & STCparameter))
2554 || v->needsScopeDtor ())
2555 error_at (make_location_t (v->loc),
2556 "has scoped destruction, cannot build closure");
2557 }
2558 }
2559
2560 TYPE_FIELDS (frame_rec_type) = fields;
2561 TYPE_READONLY (frame_rec_type) = 1;
2562 layout_type (frame_rec_type);
2563 d_keep (frame_rec_type);
2564
2565 return frame_rec_type;
2566}
2567
2568/* Closures are implemented by taking the local variables that
2569 need to survive the scope of the function, and copying them
2570 into a GC allocated chuck of memory. That chunk, called the
2571 closure here, is inserted into the linked list of stack
2572 frames instead of the usual stack frame.
2573
2574 If a closure is not required, but FD still needs a frame to lower
2575 nested refs, then instead build custom static chain decl on stack. */
2576
2577void
2578build_closure (FuncDeclaration *fd)
2579{
2580 tree ffi = get_frameinfo (fd);
2581
2582 if (!FRAMEINFO_CREATES_FRAME (ffi))
2583 return;
2584
2585 tree type = FRAMEINFO_TYPE (ffi);
2586 gcc_assert (COMPLETE_TYPE_P (type));
2587
2588 tree decl, decl_ref;
2589
2590 if (FRAMEINFO_IS_CLOSURE (ffi))
2591 {
2592 decl = build_local_temp (build_pointer_type (type));
2593 DECL_NAME (decl) = get_identifier ("__closptr");
2594 decl_ref = build_deref (decl);
2595
2596 /* Allocate memory for closure. */
2597 tree arg = convert (build_ctype (Type::tsize_t), TYPE_SIZE_UNIT (type));
2598 tree init = build_libcall (LIBCALL_ALLOCMEMORY, Type::tvoidptr, 1, arg);
2599
2600 tree init_exp = build_assign (INIT_EXPR, decl,
2601 build_nop (TREE_TYPE (decl), init));
2602 add_stmt (init_exp);
2603 }
2604 else
2605 {
2606 decl = build_local_temp (type);
2607 DECL_NAME (decl) = get_identifier ("__frame");
2608 decl_ref = decl;
2609 }
2610
2611 /* Set the first entry to the parent closure/frame, if any. */
2612 if (fd->vthis)
2613 {
2614 tree chain_field = component_ref (decl_ref, TYPE_FIELDS (type));
2615 tree chain_expr = modify_expr (chain_field,
2616 d_function_chain->static_chain);
2617 add_stmt (chain_expr);
2618 }
2619
2620 /* Copy parameters that are referenced nonlocally. */
2cbc99d1 2621 for (size_t i = 0; i < fd->closureVars.length; i++)
b4c522fa
IB
2622 {
2623 VarDeclaration *v = fd->closureVars[i];
2624
2625 if (!v->isParameter ())
2626 continue;
2627
2628 tree vsym = get_symbol_decl (v);
2629
2630 tree field = component_ref (decl_ref, DECL_LANG_FRAME_FIELD (vsym));
2631 tree expr = modify_expr (field, vsym);
2632 add_stmt (expr);
2633 }
2634
2635 if (!FRAMEINFO_IS_CLOSURE (ffi))
2636 decl = build_address (decl);
2637
2638 d_function_chain->static_chain = decl;
2639}
2640
2641/* Return the frame of FD. This could be a static chain or a closure
cdbf48be 2642 passed via the hidden `this' pointer. */
b4c522fa
IB
2643
2644tree
2645get_frameinfo (FuncDeclaration *fd)
2646{
2647 tree fds = get_symbol_decl (fd);
2648 if (DECL_LANG_FRAMEINFO (fds))
2649 return DECL_LANG_FRAMEINFO (fds);
2650
2651 tree ffi = make_node (FUNCFRAME_INFO);
2652
2653 DECL_LANG_FRAMEINFO (fds) = ffi;
2654
2655 if (fd->needsClosure ())
2656 {
2657 /* Set-up a closure frame, this will be allocated on the heap. */
2658 FRAMEINFO_CREATES_FRAME (ffi) = 1;
2659 FRAMEINFO_IS_CLOSURE (ffi) = 1;
2660 }
2661 else if (fd->hasNestedFrameRefs ())
2662 {
2663 /* Functions with nested refs must create a static frame for local
2664 variables to be referenced from. */
2665 FRAMEINFO_CREATES_FRAME (ffi) = 1;
2666 }
2667 else
2668 {
2669 /* For nested functions, default to creating a frame. Even if there are
2670 no fields to populate the frame, create it anyway, as this will be
2671 used as the record type instead of `void*` for the this parameter. */
2672 if (fd->vthis && fd->vthis->type == Type::tvoidptr)
2673 FRAMEINFO_CREATES_FRAME (ffi) = 1;
2674
2675 /* In checkNestedReference, references from contracts are not added to the
2676 closureVars array, so assume all parameters referenced. */
0cdc55f5
IB
2677 if ((global.params.useIn == CHECKENABLEon && fd->frequire)
2678 || (global.params.useOut == CHECKENABLEon && fd->fensure))
b4c522fa
IB
2679 FRAMEINFO_CREATES_FRAME (ffi) = 1;
2680
2681 /* If however `fd` is nested (deeply) in a function that creates a
2682 closure, then `fd` instead inherits that closure via hidden vthis
2683 pointer, and doesn't create a stack frame at all. */
2684 FuncDeclaration *ff = fd;
2685
2686 while (ff)
2687 {
2688 tree ffo = get_frameinfo (ff);
2689
2690 if (ff != fd && FRAMEINFO_CREATES_FRAME (ffo))
2691 {
2692 gcc_assert (FRAMEINFO_TYPE (ffo));
2693 FRAMEINFO_CREATES_FRAME (ffi) = 0;
2694 FRAMEINFO_STATIC_CHAIN (ffi) = 1;
2695 FRAMEINFO_IS_CLOSURE (ffi) = FRAMEINFO_IS_CLOSURE (ffo);
2696 gcc_assert (COMPLETE_TYPE_P (FRAMEINFO_TYPE (ffo)));
2697 FRAMEINFO_TYPE (ffi) = FRAMEINFO_TYPE (ffo);
2698 break;
2699 }
2700
2701 /* Stop looking if no frame pointer for this function. */
2702 if (ff->vthis == NULL)
2703 break;
2704
2705 AggregateDeclaration *ad = ff->isThis ();
2706 if (ad && ad->isNested ())
2707 {
2708 while (ad->isNested ())
2709 {
2710 Dsymbol *d = ad->toParent2 ();
2711 ad = d->isAggregateDeclaration ();
2712 ff = d->isFuncDeclaration ();
2713
2714 if (ad == NULL)
2715 break;
2716 }
2717 }
2718 else
2719 ff = ff->toParent2 ()->isFuncDeclaration ();
2720 }
2721 }
2722
2723 /* Build type now as may be referenced from another module. */
2724 if (FRAMEINFO_CREATES_FRAME (ffi))
2725 FRAMEINFO_TYPE (ffi) = build_frame_type (ffi, fd);
2726
2727 return ffi;
2728}
2729
2730/* Return a pointer to the frame/closure block of OUTER
2731 so can be accessed from the function INNER. */
2732
2733tree
2734get_framedecl (FuncDeclaration *inner, FuncDeclaration *outer)
2735{
2736 tree result = d_function_chain->static_chain;
2737 FuncDeclaration *fd = inner;
2738
2739 while (fd && fd != outer)
2740 {
2741 AggregateDeclaration *ad;
2742 ClassDeclaration *cd;
2743 StructDeclaration *sd;
2744
2745 /* Parent frame link is the first field. */
2746 if (FRAMEINFO_CREATES_FRAME (get_frameinfo (fd)))
2747 result = indirect_ref (ptr_type_node, result);
2748
2749 if (fd->isNested ())
2750 fd = fd->toParent2 ()->isFuncDeclaration ();
2751 /* The frame/closure record always points to the outer function's
2752 frame, even if there are intervening nested classes or structs.
2753 So, we can just skip over these. */
2754 else if ((ad = fd->isThis ()) && (cd = ad->isClassDeclaration ()))
2755 fd = d_nested_class (cd);
2756 else if ((ad = fd->isThis ()) && (sd = ad->isStructDeclaration ()))
2757 fd = d_nested_struct (sd);
2758 else
2759 break;
2760 }
2761
2b1c2a4b
IB
2762 if (fd != outer)
2763 return error_no_frame_access (outer);
2764
b4c522fa 2765 /* Go get our frame record. */
b4c522fa
IB
2766 tree frame_type = FRAMEINFO_TYPE (get_frameinfo (outer));
2767
2768 if (frame_type != NULL_TREE)
2769 {
2770 result = build_nop (build_pointer_type (frame_type), result);
2771 return result;
2772 }
2773 else
2774 {
2775 error_at (make_location_t (inner->loc),
2776 "forward reference to frame of %qs", outer->toChars ());
2777 return null_pointer_node;
2778 }
2779}