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