]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/d-codegen.cc
d: Build TYPE_DECLs for non-numeric enum types.
[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);
2045
2046 /* Enforce left to right evaluation. */
2047 if (tf->linkage == LINKd)
2048 CALL_EXPR_ARGS_ORDERED (result) = 1;
2049
2050 result = maybe_expand_intrinsic (result);
2051
2052 /* Return the value in a temporary slot so that it can be evaluated
2053 multiple times by the caller. */
2054 if (TREE_CODE (result) == CALL_EXPR
2055 && AGGREGATE_TYPE_P (TREE_TYPE (result))
2056 && TREE_ADDRESSABLE (TREE_TYPE (result)))
2057 {
2058 CALL_EXPR_RETURN_SLOT_OPT (result) = true;
2059 result = force_target_expr (result);
2060 }
2061
2062 return compound_expr (saved_args, result);
2063}
2064
2065/* Builds a call to AssertError or AssertErrorMsg. */
2066
2067tree
af3c19f0 2068d_assert_call (const Loc &loc, libcall_fn libcall, tree msg)
b4c522fa
IB
2069{
2070 tree file;
2071 tree line = size_int (loc.linnum);
2072
2073 /* File location is passed as a D string. */
2074 if (loc.filename)
2075 {
2076 unsigned len = strlen (loc.filename);
2077 tree str = build_string (len, loc.filename);
2078 TREE_TYPE (str) = make_array_type (Type::tchar, len);
2079
2080 file = d_array_value (build_ctype (Type::tchar->arrayOf ()),
2081 size_int (len), build_address (str));
2082 }
2083 else
2084 file = null_array_node;
2085
2086 if (msg != NULL)
2087 return build_libcall (libcall, Type::tvoid, 3, msg, file, line);
2088 else
2089 return build_libcall (libcall, Type::tvoid, 2, file, line);
2090}
2091
2092/* Build and return the correct call to fmod depending on TYPE.
2093 ARG0 and ARG1 are the arguments pass to the function. */
2094
2095tree
2096build_float_modulus (tree type, tree arg0, tree arg1)
2097{
2098 tree fmodfn = NULL_TREE;
2099 tree basetype = type;
2100
2101 if (COMPLEX_FLOAT_TYPE_P (basetype))
2102 basetype = TREE_TYPE (basetype);
2103
2104 if (TYPE_MAIN_VARIANT (basetype) == double_type_node
2105 || TYPE_MAIN_VARIANT (basetype) == idouble_type_node)
2106 fmodfn = builtin_decl_explicit (BUILT_IN_FMOD);
2107 else if (TYPE_MAIN_VARIANT (basetype) == float_type_node
2108 || TYPE_MAIN_VARIANT (basetype) == ifloat_type_node)
2109 fmodfn = builtin_decl_explicit (BUILT_IN_FMODF);
2110 else if (TYPE_MAIN_VARIANT (basetype) == long_double_type_node
2111 || TYPE_MAIN_VARIANT (basetype) == ireal_type_node)
2112 fmodfn = builtin_decl_explicit (BUILT_IN_FMODL);
2113
2114 if (!fmodfn)
2115 {
2116 error ("tried to perform floating-point modulo division on %qT", type);
2117 return error_mark_node;
2118 }
2119
2120 if (COMPLEX_FLOAT_TYPE_P (type))
2121 {
2122 tree re = build_call_expr (fmodfn, 2, real_part (arg0), arg1);
2123 tree im = build_call_expr (fmodfn, 2, imaginary_part (arg0), arg1);
2124
2125 return complex_expr (type, re, im);
2126 }
2127
2128 if (SCALAR_FLOAT_TYPE_P (type))
2129 return build_call_expr (fmodfn, 2, arg0, arg1);
2130
2131 /* Should have caught this above. */
2132 gcc_unreachable ();
2133}
2134
2135/* Build a function type whose first argument is a pointer to BASETYPE,
cdbf48be 2136 which is to be used for the `vthis' context parameter for TYPE.
b4c522fa
IB
2137 The base type may be a record for member functions, or a void for
2138 nested functions and delegates. */
2139
2140tree
2141build_vthis_function (tree basetype, tree type)
2142{
2143 gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
2144
2145 tree argtypes = tree_cons (NULL_TREE, build_pointer_type (basetype),
2146 TYPE_ARG_TYPES (type));
2147 tree fntype = build_function_type (TREE_TYPE (type), argtypes);
2148
2149 if (RECORD_OR_UNION_TYPE_P (basetype))
2150 TYPE_METHOD_BASETYPE (fntype) = TYPE_MAIN_VARIANT (basetype);
2151 else
2152 gcc_assert (VOID_TYPE_P (basetype));
2153
2154 return fntype;
2155}
2156
2b1c2a4b
IB
2157/* Raise an error at that the context pointer of the function or object SYM is
2158 not accessible from the current scope. */
2159
2160tree
2161error_no_frame_access (Dsymbol *sym)
2162{
2163 error_at (input_location, "cannot get frame pointer to %qs",
2164 sym->toPrettyChars ());
2165 return null_pointer_node;
2166}
2167
b4c522fa
IB
2168/* If SYM is a nested function, return the static chain to be
2169 used when calling that function from the current function.
2170
2171 If SYM is a nested class or struct, return the static chain
2172 to be used when creating an instance of the class from CFUN. */
2173
2174tree
2175get_frame_for_symbol (Dsymbol *sym)
2176{
2177 FuncDeclaration *thisfd
2178 = d_function_chain ? d_function_chain->function : NULL;
2179 FuncDeclaration *fd = sym->isFuncDeclaration ();
2180 FuncDeclaration *fdparent = NULL;
2181 FuncDeclaration *fdoverride = NULL;
2182
2183 if (fd != NULL)
2184 {
2185 /* Check that the nested function is properly defined. */
2186 if (!fd->fbody)
2187 {
cdbf48be 2188 /* Should instead error on line that references `fd'. */
b4c522fa
IB
2189 error_at (make_location_t (fd->loc), "nested function missing body");
2190 return null_pointer_node;
2191 }
2192
2193 fdparent = fd->toParent2 ()->isFuncDeclaration ();
2194
2195 /* Special case for __ensure and __require. */
2196 if ((fd->ident == Identifier::idPool ("__ensure")
2197 || fd->ident == Identifier::idPool ("__require"))
2198 && fdparent != thisfd)
2199 {
2200 fdoverride = fdparent;
2201 fdparent = thisfd;
2202 }
2203 }
2204 else
2205 {
2206 /* It's a class (or struct). NewExp codegen has already determined its
2207 outer scope is not another class, so it must be a function. */
2208 while (sym && !sym->isFuncDeclaration ())
2209 sym = sym->toParent2 ();
2210
2211 fdparent = (FuncDeclaration *) sym;
2212 }
2213
9fa5d5de
IB
2214 /* Not a nested function, there is no frame pointer to pass. */
2215 if (fdparent == NULL)
2216 {
2217 /* Only delegate literals report as being nested, even if they are in
2218 global scope. */
2219 gcc_assert (fd && fd->isFuncLiteralDeclaration ());
2220 return null_pointer_node;
2221 }
2222
2223 gcc_assert (thisfd != NULL);
b4c522fa
IB
2224
2225 if (thisfd != fdparent)
2226 {
2227 /* If no frame pointer for this function. */
2228 if (!thisfd->vthis)
2229 {
2230 error_at (make_location_t (sym->loc),
9fa5d5de 2231 "%qs is a nested function and cannot be accessed from %qs",
2b1c2a4b 2232 fdparent->toPrettyChars (), thisfd->toPrettyChars ());
b4c522fa
IB
2233 return null_pointer_node;
2234 }
2235
2236 /* Make sure we can get the frame pointer to the outer function.
2237 Go up each nesting level until we find the enclosing function. */
2238 Dsymbol *dsym = thisfd;
2239
2240 while (fd != dsym)
2241 {
2242 /* Check if enclosing function is a function. */
2b1c2a4b
IB
2243 FuncDeclaration *fdp = dsym->isFuncDeclaration ();
2244 Dsymbol *parent = dsym->toParent2 ();
b4c522fa 2245
2b1c2a4b 2246 if (fdp != NULL)
b4c522fa 2247 {
2b1c2a4b 2248 if (fdparent == parent)
b4c522fa
IB
2249 break;
2250
2b1c2a4b
IB
2251 gcc_assert (fdp->isNested () || fdp->vthis);
2252 dsym = parent;
b4c522fa
IB
2253 continue;
2254 }
2255
2256 /* Check if enclosed by an aggregate. That means the current
2257 function must be a member function of that aggregate. */
2b1c2a4b 2258 AggregateDeclaration *adp = dsym->isAggregateDeclaration ();
b4c522fa 2259
2b1c2a4b 2260 if (adp != NULL)
b4c522fa 2261 {
2b1c2a4b
IB
2262 if ((adp->isClassDeclaration () || adp->isStructDeclaration ())
2263 && fdparent == parent)
2264 break;
b4c522fa
IB
2265 }
2266
2b1c2a4b
IB
2267 /* No frame to outer function found. */
2268 if (!adp || !adp->isNested () || !adp->vthis)
2269 return error_no_frame_access (sym);
2270
2271 dsym = parent;
b4c522fa
IB
2272 }
2273 }
2274
2275 tree ffo = get_frameinfo (fdparent);
2276 if (FRAMEINFO_CREATES_FRAME (ffo) || FRAMEINFO_STATIC_CHAIN (ffo))
2277 {
2278 tree frame_ref = get_framedecl (thisfd, fdparent);
2279
cdbf48be 2280 /* If `thisfd' is a derived member function, then `fdparent' is the
b4c522fa
IB
2281 overridden member function in the base class. Even if there's a
2282 closure environment, we should give the original stack data as the
2283 nested function frame. */
2284 if (fdoverride)
2285 {
2286 ClassDeclaration *cdo = fdoverride->isThis ()->isClassDeclaration ();
2287 ClassDeclaration *cd = thisfd->isThis ()->isClassDeclaration ();
2288 gcc_assert (cdo && cd);
2289
2290 int offset;
2291 if (cdo->isBaseOf (cd, &offset) && offset != 0)
2292 {
2293 /* Generate a new frame to pass to the overriden function that
cdbf48be 2294 has the `this' pointer adjusted. */
b4c522fa
IB
2295 gcc_assert (offset != OFFSET_RUNTIME);
2296
2297 tree type = FRAMEINFO_TYPE (get_frameinfo (fdoverride));
2298 tree fields = TYPE_FIELDS (type);
cdbf48be 2299 /* The `this' field comes immediately after the `__chain'. */
b4c522fa 2300 tree thisfield = chain_index (1, fields);
af3c19f0 2301 vec <constructor_elt, va_gc> *ve = NULL;
b4c522fa
IB
2302
2303 tree framefields = TYPE_FIELDS (FRAMEINFO_TYPE (ffo));
2304 frame_ref = build_deref (frame_ref);
2305
2306 for (tree field = fields; field; field = DECL_CHAIN (field))
2307 {
2308 tree value = component_ref (frame_ref, framefields);
2309 if (field == thisfield)
2310 value = build_offset (value, size_int (offset));
2311
2312 CONSTRUCTOR_APPEND_ELT (ve, field, value);
2313 framefields = DECL_CHAIN (framefields);
2314 }
2315
2316 frame_ref = build_address (build_constructor (type, ve));
2317 }
2318 }
2319
2320 return frame_ref;
2321 }
2322
2323 return null_pointer_node;
2324}
2325
2326/* Return the parent function of a nested class CD. */
2327
2328static FuncDeclaration *
2329d_nested_class (ClassDeclaration *cd)
2330{
2331 FuncDeclaration *fd = NULL;
2332 while (cd && cd->isNested ())
2333 {
2334 Dsymbol *dsym = cd->toParent2 ();
2335 if ((fd = dsym->isFuncDeclaration ()))
2336 return fd;
2337 else
2338 cd = dsym->isClassDeclaration ();
2339 }
2340 return NULL;
2341}
2342
2343/* Return the parent function of a nested struct SD. */
2344
2345static FuncDeclaration *
2346d_nested_struct (StructDeclaration *sd)
2347{
2348 FuncDeclaration *fd = NULL;
2349 while (sd && sd->isNested ())
2350 {
2351 Dsymbol *dsym = sd->toParent2 ();
2352 if ((fd = dsym->isFuncDeclaration ()))
2353 return fd;
2354 else
2355 sd = dsym->isStructDeclaration ();
2356 }
2357 return NULL;
2358}
2359
2360
2361/* Starting from the current function FD, try to find a suitable value of
cdbf48be 2362 `this' in nested function instances. A suitable `this' value is an
b4c522fa
IB
2363 instance of OCD or a class that has OCD as a base. */
2364
2365static tree
2366find_this_tree (ClassDeclaration *ocd)
2367{
2368 FuncDeclaration *fd = d_function_chain ? d_function_chain->function : NULL;
2369
2370 while (fd)
2371 {
2372 AggregateDeclaration *ad = fd->isThis ();
2373 ClassDeclaration *cd = ad ? ad->isClassDeclaration () : NULL;
2374
2375 if (cd != NULL)
2376 {
2377 if (ocd == cd)
2378 return get_decl_tree (fd->vthis);
2379 else if (ocd->isBaseOf (cd, NULL))
2380 return convert_expr (get_decl_tree (fd->vthis),
2381 cd->type, ocd->type);
2382
2383 fd = d_nested_class (cd);
2384 }
2385 else
2386 {
2387 if (fd->isNested ())
2388 {
2389 fd = fd->toParent2 ()->isFuncDeclaration ();
2390 continue;
2391 }
2392
2393 fd = NULL;
2394 }
2395 }
2396
2397 return NULL_TREE;
2398}
2399
cdbf48be 2400/* Retrieve the outer class/struct `this' value of DECL from
b4c522fa
IB
2401 the current function. */
2402
2403tree
2404build_vthis (AggregateDeclaration *decl)
2405{
2406 ClassDeclaration *cd = decl->isClassDeclaration ();
2407 StructDeclaration *sd = decl->isStructDeclaration ();
2408
2409 /* If an aggregate nested in a function has no methods and there are no
2410 other nested functions, any static chain created here will never be
2411 translated. Use a null pointer for the link in this case. */
2412 tree vthis_value = null_pointer_node;
2413
2414 if (cd != NULL || sd != NULL)
2415 {
2416 Dsymbol *outer = decl->toParent2 ();
2417
2418 /* If the parent is a templated struct, the outer context is instead
2419 the enclosing symbol of where the instantiation happened. */
2420 if (outer->isStructDeclaration ())
2421 {
2422 gcc_assert (outer->parent && outer->parent->isTemplateInstance ());
2423 outer = ((TemplateInstance *) outer->parent)->enclosing;
2424 }
2425
cdbf48be 2426 /* For outer classes, get a suitable `this' value.
b4c522fa
IB
2427 For outer functions, get a suitable frame/closure pointer. */
2428 ClassDeclaration *cdo = outer->isClassDeclaration ();
2429 FuncDeclaration *fdo = outer->isFuncDeclaration ();
2430
2431 if (cdo)
2432 {
2433 vthis_value = find_this_tree (cdo);
2434 gcc_assert (vthis_value != NULL_TREE);
2435 }
2436 else if (fdo)
2437 {
2438 tree ffo = get_frameinfo (fdo);
2439 if (FRAMEINFO_CREATES_FRAME (ffo) || FRAMEINFO_STATIC_CHAIN (ffo)
2440 || fdo->hasNestedFrameRefs ())
2441 vthis_value = get_frame_for_symbol (decl);
2442 else if (cd != NULL)
2443 {
2444 /* Classes nested in methods are allowed to access any outer
2445 class fields, use the function chain in this case. */
2446 if (fdo->vthis && fdo->vthis->type != Type::tvoidptr)
2447 vthis_value = get_decl_tree (fdo->vthis);
2448 }
2449 }
2450 else
2451 gcc_unreachable ();
2452 }
2453
2454 return vthis_value;
2455}
2456
2457/* Build the RECORD_TYPE that describes the function frame or closure type for
2458 the function FD. FFI is the tree holding all frame information. */
2459
2460static tree
2461build_frame_type (tree ffi, FuncDeclaration *fd)
2462{
2463 if (FRAMEINFO_TYPE (ffi))
2464 return FRAMEINFO_TYPE (ffi);
2465
2466 tree frame_rec_type = make_node (RECORD_TYPE);
2467 char *name = concat (FRAMEINFO_IS_CLOSURE (ffi) ? "CLOSURE." : "FRAME.",
2468 fd->toPrettyChars (), NULL);
2469 TYPE_NAME (frame_rec_type) = get_identifier (name);
2470 free (name);
2471
2472 tree fields = NULL_TREE;
2473
2474 /* Function is a member or nested, so must have field for outer context. */
2475 if (fd->vthis)
2476 {
2477 tree ptr_field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2478 get_identifier ("__chain"), ptr_type_node);
2479 DECL_FIELD_CONTEXT (ptr_field) = frame_rec_type;
2480 fields = chainon (NULL_TREE, ptr_field);
2481 DECL_NONADDRESSABLE_P (ptr_field) = 1;
2482 }
2483
2484 /* The __ensure and __require are called directly, so never make the outer
2485 functions closure, but nevertheless could still be referencing parameters
2486 of the calling function non-locally. So we add all parameters with nested
2487 refs to the function frame, this should also mean overriding methods will
2488 have the same frame layout when inheriting a contract. */
0cdc55f5
IB
2489 if ((global.params.useIn == CHECKENABLEon && fd->frequire)
2490 || (global.params.useOut == CHECKENABLEon && fd->fensure))
b4c522fa
IB
2491 {
2492 if (fd->parameters)
2493 {
2cbc99d1 2494 for (size_t i = 0; fd->parameters && i < fd->parameters->length; i++)
b4c522fa
IB
2495 {
2496 VarDeclaration *v = (*fd->parameters)[i];
2497 /* Remove if already in closureVars so can push to front. */
2cbc99d1 2498 for (size_t j = i; j < fd->closureVars.length; j++)
b4c522fa
IB
2499 {
2500 Dsymbol *s = fd->closureVars[j];
2501 if (s == v)
2502 {
2503 fd->closureVars.remove (j);
2504 break;
2505 }
2506 }
2507 fd->closureVars.insert (i, v);
2508 }
2509 }
2510
cdbf48be 2511 /* Also add hidden `this' to outer context. */
b4c522fa
IB
2512 if (fd->vthis)
2513 {
2cbc99d1 2514 for (size_t i = 0; i < fd->closureVars.length; i++)
b4c522fa
IB
2515 {
2516 Dsymbol *s = fd->closureVars[i];
2517 if (s == fd->vthis)
2518 {
2519 fd->closureVars.remove (i);
2520 break;
2521 }
2522 }
2523 fd->closureVars.insert (0, fd->vthis);
2524 }
2525 }
2526
2cbc99d1 2527 for (size_t i = 0; i < fd->closureVars.length; i++)
b4c522fa
IB
2528 {
2529 VarDeclaration *v = fd->closureVars[i];
2530 tree vsym = get_symbol_decl (v);
2531 tree ident = v->ident
2532 ? get_identifier (v->ident->toChars ()) : NULL_TREE;
2533
2534 tree field = build_decl (make_location_t (v->loc), FIELD_DECL, ident,
2535 TREE_TYPE (vsym));
2536 SET_DECL_LANG_FRAME_FIELD (vsym, field);
2537 DECL_FIELD_CONTEXT (field) = frame_rec_type;
2538 fields = chainon (fields, field);
2539 TREE_USED (vsym) = 1;
2540
2541 TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (vsym);
2542 DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (vsym);
2543 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (vsym);
2544
2545 /* Can't do nrvo if the variable is put in a frame. */
2546 if (fd->nrvo_can && fd->nrvo_var == v)
2547 fd->nrvo_can = 0;
2548
2549 if (FRAMEINFO_IS_CLOSURE (ffi))
2550 {
2551 /* Because the value needs to survive the end of the scope. */
2552 if ((v->edtor && (v->storage_class & STCparameter))
2553 || v->needsScopeDtor ())
2554 error_at (make_location_t (v->loc),
2555 "has scoped destruction, cannot build closure");
2556 }
2557 }
2558
2559 TYPE_FIELDS (frame_rec_type) = fields;
2560 TYPE_READONLY (frame_rec_type) = 1;
2561 layout_type (frame_rec_type);
2562 d_keep (frame_rec_type);
2563
2564 return frame_rec_type;
2565}
2566
2567/* Closures are implemented by taking the local variables that
2568 need to survive the scope of the function, and copying them
2569 into a GC allocated chuck of memory. That chunk, called the
2570 closure here, is inserted into the linked list of stack
2571 frames instead of the usual stack frame.
2572
2573 If a closure is not required, but FD still needs a frame to lower
2574 nested refs, then instead build custom static chain decl on stack. */
2575
2576void
2577build_closure (FuncDeclaration *fd)
2578{
2579 tree ffi = get_frameinfo (fd);
2580
2581 if (!FRAMEINFO_CREATES_FRAME (ffi))
2582 return;
2583
2584 tree type = FRAMEINFO_TYPE (ffi);
2585 gcc_assert (COMPLETE_TYPE_P (type));
2586
2587 tree decl, decl_ref;
2588
2589 if (FRAMEINFO_IS_CLOSURE (ffi))
2590 {
2591 decl = build_local_temp (build_pointer_type (type));
2592 DECL_NAME (decl) = get_identifier ("__closptr");
2593 decl_ref = build_deref (decl);
2594
2595 /* Allocate memory for closure. */
2596 tree arg = convert (build_ctype (Type::tsize_t), TYPE_SIZE_UNIT (type));
2597 tree init = build_libcall (LIBCALL_ALLOCMEMORY, Type::tvoidptr, 1, arg);
2598
2599 tree init_exp = build_assign (INIT_EXPR, decl,
2600 build_nop (TREE_TYPE (decl), init));
2601 add_stmt (init_exp);
2602 }
2603 else
2604 {
2605 decl = build_local_temp (type);
2606 DECL_NAME (decl) = get_identifier ("__frame");
2607 decl_ref = decl;
2608 }
2609
2610 /* Set the first entry to the parent closure/frame, if any. */
2611 if (fd->vthis)
2612 {
2613 tree chain_field = component_ref (decl_ref, TYPE_FIELDS (type));
2614 tree chain_expr = modify_expr (chain_field,
2615 d_function_chain->static_chain);
2616 add_stmt (chain_expr);
2617 }
2618
2619 /* Copy parameters that are referenced nonlocally. */
2cbc99d1 2620 for (size_t i = 0; i < fd->closureVars.length; i++)
b4c522fa
IB
2621 {
2622 VarDeclaration *v = fd->closureVars[i];
2623
2624 if (!v->isParameter ())
2625 continue;
2626
2627 tree vsym = get_symbol_decl (v);
2628
2629 tree field = component_ref (decl_ref, DECL_LANG_FRAME_FIELD (vsym));
2630 tree expr = modify_expr (field, vsym);
2631 add_stmt (expr);
2632 }
2633
2634 if (!FRAMEINFO_IS_CLOSURE (ffi))
2635 decl = build_address (decl);
2636
2637 d_function_chain->static_chain = decl;
2638}
2639
2640/* Return the frame of FD. This could be a static chain or a closure
cdbf48be 2641 passed via the hidden `this' pointer. */
b4c522fa
IB
2642
2643tree
2644get_frameinfo (FuncDeclaration *fd)
2645{
2646 tree fds = get_symbol_decl (fd);
2647 if (DECL_LANG_FRAMEINFO (fds))
2648 return DECL_LANG_FRAMEINFO (fds);
2649
2650 tree ffi = make_node (FUNCFRAME_INFO);
2651
2652 DECL_LANG_FRAMEINFO (fds) = ffi;
2653
2654 if (fd->needsClosure ())
2655 {
2656 /* Set-up a closure frame, this will be allocated on the heap. */
2657 FRAMEINFO_CREATES_FRAME (ffi) = 1;
2658 FRAMEINFO_IS_CLOSURE (ffi) = 1;
2659 }
2660 else if (fd->hasNestedFrameRefs ())
2661 {
2662 /* Functions with nested refs must create a static frame for local
2663 variables to be referenced from. */
2664 FRAMEINFO_CREATES_FRAME (ffi) = 1;
2665 }
2666 else
2667 {
2668 /* For nested functions, default to creating a frame. Even if there are
2669 no fields to populate the frame, create it anyway, as this will be
2670 used as the record type instead of `void*` for the this parameter. */
2671 if (fd->vthis && fd->vthis->type == Type::tvoidptr)
2672 FRAMEINFO_CREATES_FRAME (ffi) = 1;
2673
2674 /* In checkNestedReference, references from contracts are not added to the
2675 closureVars array, so assume all parameters referenced. */
0cdc55f5
IB
2676 if ((global.params.useIn == CHECKENABLEon && fd->frequire)
2677 || (global.params.useOut == CHECKENABLEon && fd->fensure))
b4c522fa
IB
2678 FRAMEINFO_CREATES_FRAME (ffi) = 1;
2679
2680 /* If however `fd` is nested (deeply) in a function that creates a
2681 closure, then `fd` instead inherits that closure via hidden vthis
2682 pointer, and doesn't create a stack frame at all. */
2683 FuncDeclaration *ff = fd;
2684
2685 while (ff)
2686 {
2687 tree ffo = get_frameinfo (ff);
2688
2689 if (ff != fd && FRAMEINFO_CREATES_FRAME (ffo))
2690 {
2691 gcc_assert (FRAMEINFO_TYPE (ffo));
2692 FRAMEINFO_CREATES_FRAME (ffi) = 0;
2693 FRAMEINFO_STATIC_CHAIN (ffi) = 1;
2694 FRAMEINFO_IS_CLOSURE (ffi) = FRAMEINFO_IS_CLOSURE (ffo);
2695 gcc_assert (COMPLETE_TYPE_P (FRAMEINFO_TYPE (ffo)));
2696 FRAMEINFO_TYPE (ffi) = FRAMEINFO_TYPE (ffo);
2697 break;
2698 }
2699
2700 /* Stop looking if no frame pointer for this function. */
2701 if (ff->vthis == NULL)
2702 break;
2703
2704 AggregateDeclaration *ad = ff->isThis ();
2705 if (ad && ad->isNested ())
2706 {
2707 while (ad->isNested ())
2708 {
2709 Dsymbol *d = ad->toParent2 ();
2710 ad = d->isAggregateDeclaration ();
2711 ff = d->isFuncDeclaration ();
2712
2713 if (ad == NULL)
2714 break;
2715 }
2716 }
2717 else
2718 ff = ff->toParent2 ()->isFuncDeclaration ();
2719 }
2720 }
2721
2722 /* Build type now as may be referenced from another module. */
2723 if (FRAMEINFO_CREATES_FRAME (ffi))
2724 FRAMEINFO_TYPE (ffi) = build_frame_type (ffi, fd);
2725
2726 return ffi;
2727}
2728
2729/* Return a pointer to the frame/closure block of OUTER
2730 so can be accessed from the function INNER. */
2731
2732tree
2733get_framedecl (FuncDeclaration *inner, FuncDeclaration *outer)
2734{
2735 tree result = d_function_chain->static_chain;
2736 FuncDeclaration *fd = inner;
2737
2738 while (fd && fd != outer)
2739 {
2740 AggregateDeclaration *ad;
2741 ClassDeclaration *cd;
2742 StructDeclaration *sd;
2743
2744 /* Parent frame link is the first field. */
2745 if (FRAMEINFO_CREATES_FRAME (get_frameinfo (fd)))
2746 result = indirect_ref (ptr_type_node, result);
2747
2748 if (fd->isNested ())
2749 fd = fd->toParent2 ()->isFuncDeclaration ();
2750 /* The frame/closure record always points to the outer function's
2751 frame, even if there are intervening nested classes or structs.
2752 So, we can just skip over these. */
2753 else if ((ad = fd->isThis ()) && (cd = ad->isClassDeclaration ()))
2754 fd = d_nested_class (cd);
2755 else if ((ad = fd->isThis ()) && (sd = ad->isStructDeclaration ()))
2756 fd = d_nested_struct (sd);
2757 else
2758 break;
2759 }
2760
2b1c2a4b
IB
2761 if (fd != outer)
2762 return error_no_frame_access (outer);
2763
b4c522fa 2764 /* Go get our frame record. */
b4c522fa
IB
2765 tree frame_type = FRAMEINFO_TYPE (get_frameinfo (outer));
2766
2767 if (frame_type != NULL_TREE)
2768 {
2769 result = build_nop (build_pointer_type (frame_type), result);
2770 return result;
2771 }
2772 else
2773 {
2774 error_at (make_location_t (inner->loc),
2775 "forward reference to frame of %qs", outer->toChars ());
2776 return null_pointer_node;
2777 }
2778}