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