comparison gcc/d/runtime.cc @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
1 /* runtime.cc -- D runtime functions called by generated code.
2 Copyright (C) 2006-2020 Free Software Foundation, Inc.
3
4 GCC is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GCC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GCC; see the file COPYING3. If not see
16 <http://www.gnu.org/licenses/>. */
17
18 #include "config.h"
19 #include "system.h"
20 #include "coretypes.h"
21
22 #include "dmd/aggregate.h"
23 #include "dmd/mtype.h"
24
25 #include "tree.h"
26 #include "fold-const.h"
27 #include "stringpool.h"
28
29 #include "d-tree.h"
30
31
32 /* During the codegen pass, the compiler may do lowering of expressions to call
33 various runtime library functions. Most are implemented in the `rt' package.
34 We represent them in the frontend here, however there's no guarantee that
35 the compiler implementation actually matches the actual implementation. */
36
37 enum d_libcall_type
38 {
39 LCT_VOID, /* void */
40 LCT_BYTE, /* byte */
41 LCT_INT, /* int */
42 LCT_UINT, /* uint */
43 LCT_BOOL, /* bool */
44 LCT_DCHAR, /* dchar */
45 LCT_VOIDPTR, /* void* */
46 LCT_STRING, /* string */
47 LCT_WSTRING, /* wstring */
48 LCT_DSTRING, /* dstring */
49 LCT_SIZE_T, /* size_t */
50 LCT_ASSOCARRAY, /* void[void] */
51 LCT_ARRAY_VOID, /* void[] */
52 LCT_ARRAY_SIZE_T, /* size_t[] */
53 LCT_ARRAY_BYTE, /* byte[] */
54 LCT_ARRAY_STRING, /* string[] */
55 LCT_ARRAY_WSTRING, /* wstring[] */
56 LCT_ARRAY_DSTRING, /* dstring[] */
57 LCT_ARRAYARRAY_BYTE, /* byte[][] */
58 LCT_POINTER_ASSOCARRAY, /* void[void]* */
59 LCT_POINTER_VOIDPTR, /* void** */
60 LCT_ARRAYPTR_VOID, /* void[]* */
61 LCT_ARRAYPTR_BYTE, /* byte[]* */
62 LCT_TYPEINFO, /* TypeInfo */
63 LCT_CLASSINFO, /* TypeInfo_Class */
64 LCT_OBJECT, /* Object */
65 LCT_CONST_TYPEINFO, /* const(TypeInfo) */
66 LCT_CONST_CLASSINFO, /* const(ClassInfo) */
67 LCT_END
68 };
69
70 /* An array of all types that are used by the runtime functions we need. */
71
72 static Type *libcall_types[LCT_END];
73
74 /* Our internal list of library functions. */
75
76 static tree libcall_decls[LIBCALL_LAST];
77
78
79 /* Return the frontend Type that is described by TYPE. Most are readily cached
80 by the frontend proper, and likewise the use of pointerTo(), constOf(), and
81 arrayOf() will return cached types if they have been requested before. */
82
83 static Type *
84 get_libcall_type (d_libcall_type type)
85 {
86 if (libcall_types[type])
87 return libcall_types[type];
88
89 switch (type)
90 {
91 case LCT_VOID:
92 libcall_types[type] = Type::tvoid;
93 break;
94
95 case LCT_BYTE:
96 libcall_types[type] = Type::tint8;
97 break;
98
99 case LCT_INT:
100 libcall_types[type] = Type::tint32;
101 break;
102
103 case LCT_UINT:
104 libcall_types[type] = Type::tuns32;
105 break;
106
107 case LCT_BOOL:
108 libcall_types[type] = Type::tbool;
109 break;
110
111 case LCT_DCHAR:
112 libcall_types[type] = Type::tdchar;
113 break;
114
115 case LCT_VOIDPTR:
116 libcall_types[type] = Type::tvoidptr;
117 break;
118
119 case LCT_STRING:
120 libcall_types[type] = Type::tstring;
121 break;
122
123 case LCT_WSTRING:
124 libcall_types[type] = Type::twstring;
125 break;
126
127 case LCT_DSTRING:
128 libcall_types[type] = Type::tdstring;
129 break;
130
131 case LCT_SIZE_T:
132 libcall_types[type] = Type::tsize_t;
133 break;
134
135 case LCT_ASSOCARRAY:
136 libcall_types[type] = TypeAArray::create (Type::tvoid, Type::tvoid);
137 break;
138
139 case LCT_TYPEINFO:
140 libcall_types[type] = Type::dtypeinfo->type;
141 break;
142
143 case LCT_CLASSINFO:
144 libcall_types[type] = Type::typeinfoclass->type;
145 break;
146
147 case LCT_OBJECT:
148 libcall_types[type] = get_object_type ();
149 break;
150
151 case LCT_CONST_TYPEINFO:
152 libcall_types[type] = Type::dtypeinfo->type->constOf ();
153 break;
154
155 case LCT_CONST_CLASSINFO:
156 libcall_types[type] = Type::typeinfoclass->type->constOf ();
157 break;
158
159 case LCT_ARRAY_VOID:
160 libcall_types[type] = Type::tvoid->arrayOf ();
161 break;
162
163 case LCT_ARRAY_SIZE_T:
164 libcall_types[type] = Type::tsize_t->arrayOf ();
165 break;
166
167 case LCT_ARRAY_BYTE:
168 libcall_types[type] = Type::tint8->arrayOf ();
169 break;
170
171 case LCT_ARRAY_STRING:
172 libcall_types[type] = Type::tstring->arrayOf ();
173 break;
174
175 case LCT_ARRAY_WSTRING:
176 libcall_types[type] = Type::twstring->arrayOf ();
177 break;
178
179 case LCT_ARRAY_DSTRING:
180 libcall_types[type] = Type::tdstring->arrayOf ();
181 break;
182
183 case LCT_ARRAYARRAY_BYTE:
184 libcall_types[type] = Type::tint8->arrayOf ()->arrayOf ();
185 break;
186
187 case LCT_POINTER_ASSOCARRAY:
188 libcall_types[type] = get_libcall_type (LCT_ASSOCARRAY)->pointerTo ();
189 break;
190
191 case LCT_POINTER_VOIDPTR:
192 libcall_types[type] = Type::tvoidptr->arrayOf ();
193 break;
194
195 case LCT_ARRAYPTR_VOID:
196 libcall_types[type] = Type::tvoid->arrayOf ()->pointerTo ();
197 break;
198
199 case LCT_ARRAYPTR_BYTE:
200 libcall_types[type] = Type::tint8->arrayOf ()->pointerTo ();
201 break;
202
203 default:
204 gcc_unreachable ();
205 }
206
207 return libcall_types[type];
208 }
209
210 /* Builds and returns function declaration named NAME. The RETURN_TYPE is
211 the type returned, FLAGS are the expression call flags, and NPARAMS is
212 the number of arguments, the types of which are provided in `...'. */
213
214 static tree
215 build_libcall_decl (const char *name, d_libcall_type return_type,
216 int flags, int nparams, ...)
217 {
218 tree *args = XALLOCAVEC (tree, nparams);
219 bool varargs = false;
220 tree fntype;
221
222 /* Add parameter types, using 'void' as the last parameter type
223 to mean this function accepts a variable list of arguments. */
224 va_list ap;
225 va_start (ap, nparams);
226
227 for (int i = 0; i < nparams; i++)
228 {
229 d_libcall_type ptype = (d_libcall_type) va_arg (ap, int);
230 Type *type = get_libcall_type (ptype);
231
232 if (type == Type::tvoid)
233 {
234 varargs = true;
235 nparams = i;
236 }
237 else
238 args[i] = build_ctype (type);
239 }
240
241 va_end (ap);
242
243 /* Build the function. */
244 tree tret = build_ctype (get_libcall_type (return_type));
245 if (varargs)
246 fntype = build_varargs_function_type_array (tret, nparams, args);
247 else
248 fntype = build_function_type_array (tret, nparams, args);
249
250 tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
251 get_identifier (name), fntype);
252 DECL_EXTERNAL (decl) = 1;
253 TREE_PUBLIC (decl) = 1;
254 DECL_ARTIFICIAL (decl) = 1;
255 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
256 DECL_VISIBILITY_SPECIFIED (decl) = 1;
257
258 /* Set any attributes on the function, such as malloc or noreturn. */
259 set_call_expr_flags (decl, flags);
260
261 return decl;
262 }
263
264 /* Return or create the runtime library function declaration for LIBCALL.
265 Library functions are generated as needed. This could probably be changed in
266 the future to be done in the compiler init stage, like GCC builtin trees are,
267 however we depend on run-time initialization of types whose definitions are
268 in the library such as `Object' or `TypeInfo'. */
269
270 static tree
271 get_libcall (libcall_fn libcall)
272 {
273 if (libcall_decls[libcall])
274 return libcall_decls[libcall];
275
276 switch (libcall)
277 {
278 #define DEF_D_RUNTIME(CODE, NAME, TYPE, PARAMS, FLAGS) \
279 case LIBCALL_ ## CODE: \
280 libcall_decls[libcall] = build_libcall_decl (NAME, TYPE, FLAGS, PARAMS); \
281 break;
282
283 #include "runtime.def"
284
285 #undef DEF_D_RUNTIME
286
287 default:
288 gcc_unreachable ();
289 }
290
291 return libcall_decls[libcall];
292 }
293
294 /* Generate a call to LIBCALL, returning the result as TYPE. NARGS is the
295 number of call arguments, the expressions of which are provided in `...'.
296 This does not perform conversions or promotions on the arguments. */
297
298 tree
299 build_libcall (libcall_fn libcall, Type *type, int nargs, ...)
300 {
301 /* Build the call expression to the runtime function. */
302 tree decl = get_libcall (libcall);
303 tree *args = XALLOCAVEC (tree, nargs);
304 va_list ap;
305
306 va_start (ap, nargs);
307 for (int i = 0; i < nargs; i++)
308 args[i] = va_arg (ap, tree);
309 va_end (ap);
310
311 tree result = build_call_expr_loc_array (input_location, decl, nargs, args);
312
313 /* Assumes caller knows what it is doing. */
314 return convert (build_ctype (type), result);
315 }