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