annotate gcc/d/d-codegen.cc @ 145:1830386684a0

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