Fix build on sparc64-linux-gnu.
[official-gcc.git] / gcc / d / runtime.cc
blob7f1e9100a73713382490b739eb2290b0b7c3016b
1 /* runtime.cc -- D runtime functions called by generated code.
2 Copyright (C) 2006-2018 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 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_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
70 /* An array of all types that are used by the runtime functions we need. */
72 static Type *libcall_types[LCT_END];
74 /* Our internal list of library functions. */
76 static tree libcall_decls[LIBCALL_LAST];
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. */
83 static Type *
84 get_libcall_type (libcall_type type)
86 if (libcall_types[type])
87 return libcall_types[type];
89 switch (type)
91 case LCT_VOID:
92 libcall_types[type] = Type::tvoid;
93 break;
95 case LCT_BYTE:
96 libcall_types[type] = Type::tint8;
97 break;
99 case LCT_INT:
100 libcall_types[type] = Type::tint32;
101 break;
103 case LCT_UINT:
104 libcall_types[type] = Type::tuns32;
105 break;
107 case LCT_BOOL:
108 libcall_types[type] = Type::tbool;
109 break;
111 case LCT_DCHAR:
112 libcall_types[type] = Type::tdchar;
113 break;
115 case LCT_VOIDPTR:
116 libcall_types[type] = Type::tvoidptr;
117 break;
119 case LCT_STRING:
120 libcall_types[type] = Type::tstring;
121 break;
123 case LCT_WSTRING:
124 libcall_types[type] = Type::twstring;
125 break;
127 case LCT_DSTRING:
128 libcall_types[type] = Type::tdstring;
129 break;
131 case LCT_SIZE_T:
132 libcall_types[type] = Type::tsize_t;
133 break;
135 case LCT_ASSOCARRAY:
136 libcall_types[type] = TypeAArray::create (Type::tvoid, Type::tvoid);
137 break;
139 case LCT_TYPEINFO:
140 libcall_types[type] = Type::dtypeinfo->type;
141 break;
143 case LCT_CLASSINFO:
144 libcall_types[type] = Type::typeinfoclass->type;
145 break;
147 case LCT_OBJECT:
148 libcall_types[type] = get_object_type ();
149 break;
151 case LCT_CONST_TYPEINFO:
152 libcall_types[type] = Type::dtypeinfo->type->constOf ();
153 break;
155 case LCT_CONST_CLASSINFO:
156 libcall_types[type] = Type::typeinfoclass->type->constOf ();
157 break;
159 case LCT_ARRAY_VOID:
160 libcall_types[type] = Type::tvoid->arrayOf ();
161 break;
163 case LCT_ARRAY_SIZE_T:
164 libcall_types[type] = Type::tsize_t->arrayOf ();
165 break;
167 case LCT_ARRAY_BYTE:
168 libcall_types[type] = Type::tint8->arrayOf ();
169 break;
171 case LCT_ARRAY_STRING:
172 libcall_types[type] = Type::tstring->arrayOf ();
173 break;
175 case LCT_ARRAY_WSTRING:
176 libcall_types[type] = Type::twstring->arrayOf ();
177 break;
179 case LCT_ARRAY_DSTRING:
180 libcall_types[type] = Type::tdstring->arrayOf ();
181 break;
183 case LCT_ARRAYARRAY_BYTE:
184 libcall_types[type] = Type::tint8->arrayOf ()->arrayOf ();
185 break;
187 case LCT_POINTER_ASSOCARRAY:
188 libcall_types[type] = get_libcall_type (LCT_ASSOCARRAY)->pointerTo ();
189 break;
191 case LCT_POINTER_VOIDPTR:
192 libcall_types[type] = Type::tvoidptr->arrayOf ();
193 break;
195 case LCT_ARRAYPTR_VOID:
196 libcall_types[type] = Type::tvoid->arrayOf ()->pointerTo ();
197 break;
199 case LCT_ARRAYPTR_BYTE:
200 libcall_types[type] = Type::tint8->arrayOf ()->pointerTo ();
201 break;
203 default:
204 gcc_unreachable ();
207 return libcall_types[type];
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 `...'. */
214 static tree
215 build_libcall_decl (const char *name, libcall_type return_type,
216 int flags, int nparams, ...)
218 tree *args = XALLOCAVEC (tree, nparams);
219 bool varargs = false;
220 tree fntype;
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);
227 for (int i = 0; i < nparams; i++)
229 libcall_type ptype = (libcall_type) va_arg (ap, int);
230 Type *type = get_libcall_type (ptype);
232 if (type == Type::tvoid)
234 varargs = true;
235 nparams = i;
237 else
238 args[i] = build_ctype (type);
241 va_end (ap);
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);
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;
258 /* Set any attributes on the function, such as malloc or noreturn. */
259 set_call_expr_flags (decl, flags);
261 return decl;
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'. */
270 static tree
271 get_libcall (libcall_fn libcall)
273 if (libcall_decls[libcall])
274 return libcall_decls[libcall];
276 switch (libcall)
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;
283 #include "runtime.def"
285 #undef DEF_D_RUNTIME
287 default:
288 gcc_unreachable ();
291 return libcall_decls[libcall];
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. */
298 tree
299 build_libcall (libcall_fn libcall, Type *type, int nargs, ...)
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;
306 va_start (ap, nargs);
307 for (int i = 0; i < nargs; i++)
308 args[i] = va_arg (ap, tree);
309 va_end (ap);
311 tree result = build_call_expr_loc_array (input_location, decl, nargs, args);
313 /* Assumes caller knows what it is doing. */
314 return convert (build_ctype (type), result);