1 /* runtime.cc -- D runtime functions called by generated code. 2 Copyright (C) 2006-2022 Free Software Foundation, Inc. 3 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. 8 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. 13 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/>. */ 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 37 enum d_libcall_type 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[] */ 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 69 }; 70 71 /* An array of all types that are used by the runtime functions we need. */ 72 73 static Type *libcall_types[LCT_END]; 74 75 /* Our internal list of library functions. */ 76 77 static 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 84 static Type * 85 get_libcall_type (d_libcall_type type) 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 204 case LCT_IMMUTABLE_CHARPTR: 205 libcall_types[type] = Type::tchar->pointerTo ()->immutableOf (); 206 break; 207 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 219 static tree 220 build_libcall_decl (const char *name, d_libcall_type return_type, 221 int flags, int nparams, ...) 222 { 223 tree *args = XALLOCAVEC (tree, nparams); 224 bool varargs = false; 225 tree fntype; 226 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); 231 232 for (int i = 0; i < nparams; i++) 233 { 234 d_libcall_type ptype = (d_libcall_type) va_arg (ap, int); 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 275 static tree 276 get_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 303 tree 304 build_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 } 321