1 /* runtime.cc -- D runtime functions called by generated code.
2 Copyright (C) 2006-2023 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)
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/>. */
20 #include "coretypes.h"
22 #include "dmd/aggregate.h"
23 #include "dmd/mtype.h"
26 #include "fold-const.h"
27 #include "stringpool.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. */
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) */
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. */
85 get_libcall_type (d_libcall_type type
)
87 if (libcall_types
[type
])
88 return libcall_types
[type
];
93 libcall_types
[type
] = Type::tvoid
;
97 libcall_types
[type
] = Type::tint8
;
101 libcall_types
[type
] = Type::tint32
;
105 libcall_types
[type
] = Type::tuns32
;
109 libcall_types
[type
] = Type::tbool
;
113 libcall_types
[type
] = Type::tdchar
;
117 libcall_types
[type
] = Type::tvoidptr
;
121 libcall_types
[type
] = Type::tstring
;
125 libcall_types
[type
] = Type::twstring
;
129 libcall_types
[type
] = Type::tdstring
;
133 libcall_types
[type
] = Type::tsize_t
;
137 libcall_types
[type
] = TypeAArray::create (Type::tvoid
, Type::tvoid
);
141 libcall_types
[type
] = Type::dtypeinfo
->type
;
145 libcall_types
[type
] = Type::typeinfoclass
->type
;
149 libcall_types
[type
] = get_object_type ();
152 case LCT_CONST_TYPEINFO
:
153 libcall_types
[type
] = Type::dtypeinfo
->type
->constOf ();
156 case LCT_CONST_CLASSINFO
:
157 libcall_types
[type
] = Type::typeinfoclass
->type
->constOf ();
161 libcall_types
[type
] = Type::tvoid
->arrayOf ();
164 case LCT_ARRAY_SIZE_T
:
165 libcall_types
[type
] = Type::tsize_t
->arrayOf ();
169 libcall_types
[type
] = Type::tint8
->arrayOf ();
172 case LCT_ARRAY_STRING
:
173 libcall_types
[type
] = Type::tstring
->arrayOf ();
176 case LCT_ARRAY_WSTRING
:
177 libcall_types
[type
] = Type::twstring
->arrayOf ();
180 case LCT_ARRAY_DSTRING
:
181 libcall_types
[type
] = Type::tdstring
->arrayOf ();
184 case LCT_ARRAYARRAY_BYTE
:
185 libcall_types
[type
] = Type::tint8
->arrayOf ()->arrayOf ();
188 case LCT_POINTER_ASSOCARRAY
:
189 libcall_types
[type
] = get_libcall_type (LCT_ASSOCARRAY
)->pointerTo ();
192 case LCT_POINTER_VOIDPTR
:
193 libcall_types
[type
] = Type::tvoidptr
->arrayOf ();
196 case LCT_ARRAYPTR_VOID
:
197 libcall_types
[type
] = Type::tvoid
->arrayOf ()->pointerTo ();
200 case LCT_ARRAYPTR_BYTE
:
201 libcall_types
[type
] = Type::tint8
->arrayOf ()->pointerTo ();
204 case LCT_IMMUTABLE_CHARPTR
:
205 libcall_types
[type
] = Type::tchar
->pointerTo ()->immutableOf ();
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 `...'. */
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;
227 /* Add parameter types, using `void' as the last parameter type
228 to mean this function accepts a variable list of arguments. */
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
)
243 args
[i
] = build_ctype (type
);
248 /* Build the function. */
249 tree tret
= build_ctype (get_libcall_type (return_type
));
251 fntype
= build_varargs_function_type_array (tret
, nparams
, args
);
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
);
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'. */
276 get_libcall (libcall_fn libcall
)
278 if (libcall_decls
[libcall
])
279 return libcall_decls
[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); \
288 #include "runtime.def"
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. */
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
);
311 va_start (ap
, nargs
);
312 for (int i
= 0; i
< nargs
; i
++)
313 args
[i
] = va_arg (ap
, tree
);
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
);