Skip several gcc.dg/builtin-dynamic-object-size tests on hppa*-*-hpux*
[official-gcc.git] / gcc / d / runtime.cc
blob8a47ac1196624c162c6fb2858a75cb41af60859f
1 /* runtime.cc -- D runtime functions called by generated code.
2 Copyright (C) 2006-2024 Free Software Foundation, Inc.
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.
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.
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/>. */
18 #include "config.h"
19 #include "system.h"
20 #include "coretypes.h"
22 #include "dmd/aggregate.h"
23 #include "dmd/mtype.h"
25 #include "tree.h"
26 #include "fold-const.h"
27 #include "stringpool.h"
29 #include "d-tree.h"
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. */
37 enum d_libcall_type
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_IMMUTABLE_CHARPTR, /* immutable(char*) */
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
71 /* An array of all types that are used by the runtime functions we need. */
73 static Type *libcall_types[LCT_END];
75 /* Our internal list of library functions. */
77 static tree libcall_decls[LIBCALL_LAST];
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. */
84 static Type *
85 get_libcall_type (d_libcall_type type)
87 if (libcall_types[type])
88 return libcall_types[type];
90 switch (type)
92 case LCT_VOID:
93 libcall_types[type] = Type::tvoid;
94 break;
96 case LCT_BYTE:
97 libcall_types[type] = Type::tint8;
98 break;
100 case LCT_INT:
101 libcall_types[type] = Type::tint32;
102 break;
104 case LCT_UINT:
105 libcall_types[type] = Type::tuns32;
106 break;
108 case LCT_BOOL:
109 libcall_types[type] = Type::tbool;
110 break;
112 case LCT_DCHAR:
113 libcall_types[type] = Type::tdchar;
114 break;
116 case LCT_VOIDPTR:
117 libcall_types[type] = Type::tvoidptr;
118 break;
120 case LCT_STRING:
121 libcall_types[type] = Type::tstring;
122 break;
124 case LCT_WSTRING:
125 libcall_types[type] = Type::twstring;
126 break;
128 case LCT_DSTRING:
129 libcall_types[type] = Type::tdstring;
130 break;
132 case LCT_SIZE_T:
133 libcall_types[type] = Type::tsize_t;
134 break;
136 case LCT_ASSOCARRAY:
137 libcall_types[type] = TypeAArray::create (Type::tvoid, Type::tvoid);
138 break;
140 case LCT_TYPEINFO:
141 libcall_types[type] = Type::dtypeinfo->type;
142 break;
144 case LCT_CLASSINFO:
145 libcall_types[type] = Type::typeinfoclass->type;
146 break;
148 case LCT_OBJECT:
149 libcall_types[type] = get_object_type ();
150 break;
152 case LCT_CONST_TYPEINFO:
153 libcall_types[type] = Type::dtypeinfo->type->constOf ();
154 break;
156 case LCT_CONST_CLASSINFO:
157 libcall_types[type] = Type::typeinfoclass->type->constOf ();
158 break;
160 case LCT_ARRAY_VOID:
161 libcall_types[type] = Type::tvoid->arrayOf ();
162 break;
164 case LCT_ARRAY_SIZE_T:
165 libcall_types[type] = Type::tsize_t->arrayOf ();
166 break;
168 case LCT_ARRAY_BYTE:
169 libcall_types[type] = Type::tint8->arrayOf ();
170 break;
172 case LCT_ARRAY_STRING:
173 libcall_types[type] = Type::tstring->arrayOf ();
174 break;
176 case LCT_ARRAY_WSTRING:
177 libcall_types[type] = Type::twstring->arrayOf ();
178 break;
180 case LCT_ARRAY_DSTRING:
181 libcall_types[type] = Type::tdstring->arrayOf ();
182 break;
184 case LCT_ARRAYARRAY_BYTE:
185 libcall_types[type] = Type::tint8->arrayOf ()->arrayOf ();
186 break;
188 case LCT_POINTER_ASSOCARRAY:
189 libcall_types[type] = get_libcall_type (LCT_ASSOCARRAY)->pointerTo ();
190 break;
192 case LCT_POINTER_VOIDPTR:
193 libcall_types[type] = Type::tvoidptr->arrayOf ();
194 break;
196 case LCT_ARRAYPTR_VOID:
197 libcall_types[type] = Type::tvoid->arrayOf ()->pointerTo ();
198 break;
200 case LCT_ARRAYPTR_BYTE:
201 libcall_types[type] = Type::tint8->arrayOf ()->pointerTo ();
202 break;
204 case LCT_IMMUTABLE_CHARPTR:
205 libcall_types[type] = Type::tchar->pointerTo ()->immutableOf ();
206 break;
208 default:
209 gcc_unreachable ();
212 return libcall_types[type];
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 `...'. */
219 static tree
220 build_libcall_decl (const char *name, d_libcall_type return_type,
221 int flags, int nparams, ...)
223 tree *args = XALLOCAVEC (tree, nparams);
224 bool varargs = false;
225 tree fntype;
227 /* Add parameter types, using `void' as the last parameter type
228 to mean this function accepts a variable list of arguments. */
229 va_list ap;
230 va_start (ap, nparams);
232 for (int i = 0; i < nparams; i++)
234 d_libcall_type ptype = (d_libcall_type) va_arg (ap, int);
235 Type *type = get_libcall_type (ptype);
237 if (type == Type::tvoid)
239 varargs = true;
240 nparams = i;
242 else
243 args[i] = build_ctype (type);
246 va_end (ap);
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);
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;
263 /* Set any attributes on the function, such as malloc or noreturn. */
264 set_call_expr_flags (decl, flags);
266 return decl;
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'. */
275 static tree
276 get_libcall (libcall_fn libcall)
278 if (libcall_decls[libcall])
279 return libcall_decls[libcall];
281 switch (libcall)
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;
288 #include "runtime.def"
290 #undef DEF_D_RUNTIME
292 default:
293 gcc_unreachable ();
296 return libcall_decls[libcall];
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. */
303 tree
304 build_libcall (libcall_fn libcall, Type *type, int nargs, ...)
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;
311 va_start (ap, nargs);
312 for (int i = 0; i < nargs; i++)
313 args[i] = va_arg (ap, tree);
314 va_end (ap);
316 tree result = build_call_expr_loc_array (input_location, decl, nargs, args);
318 /* Assumes caller knows what it is doing. */
319 return convert (build_ctype (type), result);