1 /* d-target.cc -- Target interface for the D front end. 2 Copyright (C) 2013-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/declaration.h" 24 #include "dmd/expression.h" 25 #include "dmd/mangle.h" 26 #include "dmd/mtype.h" 27 #include "dmd/tokens.h" 28 #include "dmd/target.h" 29 30 #include "tree.h" 31 #include "memmodel.h" 32 #include "fold-const.h" 33 #include "diagnostic.h" 34 #include "stor-layout.h" 35 #include "tm.h" 36 #include "tm_p.h" 37 #include "target.h" 38 #include "calls.h" 39 40 #include "d-tree.h" 41 #include "d-target.h" 42 43 /* Implements the Target interface defined by the front end. 44 Used for retrieving target-specific information. */ 45 46 /* Internal key handlers for `__traits(getTargetInfo)'. */ 47 static tree d_handle_target_cpp_std (void); 48 static tree d_handle_target_cpp_runtime_library (void); 49 static tree d_handle_target_object_format (void); 50 51 /* In [traits/getTargetInfo], a reliable subset of getTargetInfo keys exists 52 which are always available. */ 53 static const struct d_target_info_spec d_language_target_info[] = 54 { 55 /* { name, handler } */ 56 { "cppStd", d_handle_target_cpp_std }, 57 { "cppRuntimeLibrary", d_handle_target_cpp_runtime_library }, 58 { "floatAbi", NULL }, 59 { "objectFormat", d_handle_target_object_format }, 60 { NULL, NULL }, 61 }; 62 63 /* Table `__traits(getTargetInfo)' keys. */ 64 static vec<d_target_info_spec> d_target_info_table; 65 66 67 /* Initialize the floating-point constants for TYPE. */ 68 69 template <typename T> 70 static void 71 define_float_constants (T &f, tree type) 72 { 73 const double log10_2 = 0.30102999566398119521; 74 char buf[128]; 75 76 /* Get back-end real mode format. */ 77 const machine_mode mode = TYPE_MODE (type); 78 const real_format *fmt = REAL_MODE_FORMAT (mode); 79 80 /* The largest representable value that's not infinity. */ 81 get_max_float (fmt, buf, sizeof (buf), false); 82 real_from_string (&f.max.rv (), buf); 83 84 /* The smallest representable normalized value that's not 0. */ 85 snprintf (buf, sizeof (buf), "0x1p%d", fmt->emin - 1); 86 real_from_string (&f.min_normal.rv (), buf); 87 88 /* Floating-point NaN. */ 89 real_nan (&f.nan.rv (), "", 1, mode); 90 91 /* Floating-point +Infinity if the target supports infinities. */ 92 real_inf (&f.infinity.rv ()); 93 94 /* The smallest increment to the value 1. */ 95 if (fmt->pnan < fmt->p) 96 snprintf (buf, sizeof (buf), "0x1p%d", fmt->emin - fmt->p); 97 else 98 snprintf (buf, sizeof (buf), "0x1p%d", 1 - fmt->p); 99 real_from_string (&f.epsilon.rv (), buf); 100 101 /* The number of decimal digits of precision. */ 102 f.dig = (fmt->p - 1) * log10_2; 103 104 /* The number of bits in mantissa. */ 105 f.mant_dig = fmt->p; 106 107 /* The maximum int value such that 2** (value-1) is representable. */ 108 f.max_exp = fmt->emax; 109 110 /* The minimum int value such that 2** (value-1) is representable as a 111 normalized value. */ 112 f.min_exp = fmt->emin; 113 114 /* The maximum int value such that 10**value is representable. */ 115 f.max_10_exp = fmt->emax * log10_2; 116 117 /* The minimum int value such that 10**value is representable as a 118 normalized value. */ 119 f.min_10_exp = (fmt->emin - 1) * log10_2; 120 } 121 122 /* Initialize all variables of the Target structure. */ 123 124 void 125 Target::_init (const Param &) 126 { 127 /* Map D frontend type and sizes to GCC back-end types. */ 128 this->ptrsize = (POINTER_SIZE / BITS_PER_UNIT); 129 this->realsize = int_size_in_bytes (long_double_type_node); 130 this->realpad = (this->realsize - 131 (TYPE_PRECISION (long_double_type_node) / BITS_PER_UNIT)); 132 this->realalignsize = TYPE_ALIGN_UNIT (long_double_type_node); 133 134 /* Much of the dmd front-end uses ints for sizes and offsets, and cannot 135 handle any larger data type without some pervasive rework. */ 136 this->maxStaticDataSize = tree_to_shwi (TYPE_MAX_VALUE (integer_type_node)); 137 138 /* Define what type to use for size_t, ptrdiff_t. */ 139 if (this->ptrsize == 8) 140 { 141 this->isLP64 = true; 142 Type::tsize_t = Type::basic[(int)TY::Tuns64]; 143 Type::tptrdiff_t = Type::basic[(int)TY::Tint64]; 144 } 145 else if (this->ptrsize == 4) 146 { 147 Type::tsize_t = Type::basic[(int)TY::Tuns32]; 148 Type::tptrdiff_t = Type::basic[(int)TY::Tint32]; 149 } 150 else if (this->ptrsize == 2) 151 { 152 Type::tsize_t = Type::basic[(int)TY::Tuns16]; 153 Type::tptrdiff_t = Type::basic[(int)TY::Tint16]; 154 } 155 else 156 sorry ("D does not support pointers on this target."); 157 158 Type::thash_t = Type::tsize_t; 159 160 /* Set-up target C ABI. */ 161 this->c.boolsize = (BOOL_TYPE_SIZE / BITS_PER_UNIT); 162 this->c.shortsize = (SHORT_TYPE_SIZE / BITS_PER_UNIT); 163 this->c.intsize = (INT_TYPE_SIZE / BITS_PER_UNIT); 164 this->c.longsize = (LONG_TYPE_SIZE / BITS_PER_UNIT); 165 this->c.long_longsize = (LONG_LONG_TYPE_SIZE / BITS_PER_UNIT); 166 this->c.long_doublesize = (LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT); 167 this->c.wchar_tsize = (WCHAR_TYPE_SIZE / BITS_PER_UNIT); 168 169 this->c.bitFieldStyle = targetm.ms_bitfield_layout_p (unknown_type_node) 170 ? TargetC::BitFieldStyle::MS : TargetC::BitFieldStyle::Gcc_Clang; 171 172 /* Set-up target C++ ABI. */ 173 this->cpp.reverseOverloads = false; 174 this->cpp.exceptions = true; 175 this->cpp.twoDtorInVtable = true; 176 177 /* Set-up target Objective-C ABI. */ 178 this->objc.supported = false; 179 180 /* Set-up environmental settings. */ 181 this->obj_ext = "o"; 182 this->lib_ext = "a"; 183 this->dll_ext = "so"; 184 this->run_noext = true; 185 186 /* Initialize all compile-time properties for floating-point types. 187 Should ensure that our real_t type is able to represent real_value. */ 188 gcc_assert (sizeof (real_t) >= sizeof (real_value)); 189 190 define_float_constants (this->FloatProperties, float_type_node); 191 define_float_constants (this->DoubleProperties, double_type_node); 192 define_float_constants (this->RealProperties, long_double_type_node); 193 194 /* Commonly used floating-point constants. */ 195 const machine_mode mode = TYPE_MODE (long_double_type_node); 196 real_convert (&CTFloat::zero.rv (), mode, &dconst0); 197 real_convert (&CTFloat::one.rv (), mode, &dconst1); 198 real_convert (&CTFloat::minusone.rv (), mode, &dconstm1); 199 real_convert (&CTFloat::half.rv (), mode, &dconsthalf); 200 201 /* Initialize target info tables, the keys required by the language are added 202 last, so that the OS and CPU handlers can override. */ 203 targetdm.d_register_cpu_target_info (); 204 targetdm.d_register_os_target_info (); 205 d_add_target_info_handlers (d_language_target_info); 206 } 207 208 /* Return GCC memory alignment size for type TYPE. */ 209 210 unsigned 211 Target::alignsize (Type *type) 212 { 213 gcc_assert (type->isTypeBasic ()); 214 return min_align_of_type (build_ctype (type)); 215 } 216 217 /* Return GCC field alignment size for type TYPE. */ 218 219 unsigned 220 Target::fieldalign (Type *type) 221 { 222 /* Work out the correct alignment for the field decl. */ 223 unsigned int align = type->alignsize () * BITS_PER_UNIT; 224 225 #ifdef BIGGEST_FIELD_ALIGNMENT 226 align = MIN (align, (unsigned) BIGGEST_FIELD_ALIGNMENT); 227 #endif 228 229 #ifdef ADJUST_FIELD_ALIGN 230 if (type->isTypeBasic ()) 231 align = ADJUST_FIELD_ALIGN (NULL_TREE, build_ctype (type), align); 232 #endif 233 234 /* Also controlled by -fpack-struct= */ 235 if (maximum_field_alignment) 236 align = MIN (align, maximum_field_alignment); 237 238 return align / BITS_PER_UNIT; 239 } 240 241 /* Returns a Type for the va_list type of the target. */ 242 243 Type * 244 Target::va_listType (const Loc &, Scope *) 245 { 246 if (this->tvalist) 247 return this->tvalist; 248 249 /* Build the "standard" abi va_list. */ 250 this->tvalist = build_frontend_type (va_list_type_node); 251 if (!this->tvalist) 252 sorry ("cannot represent built-in %<va_list%> type in D"); 253 254 /* Map the va_list type to the D frontend Type. This is to prevent both 255 errors in gimplification or an ICE in targetm.canonical_va_list_type. */ 256 this->tvalist->ctype = va_list_type_node; 257 TYPE_LANG_SPECIFIC (va_list_type_node) = build_lang_type (this->tvalist); 258 259 return this->tvalist; 260 } 261 262 /* Checks whether the target supports a vector type with total size SZ 263 (in bytes) and element type TYPE. */ 264 265 int 266 Target::isVectorTypeSupported (int sz, Type *type) 267 { 268 /* Size must be greater than zero, and a power of two. */ 269 if (sz <= 0 || sz & (sz - 1)) 270 return 3; 271 272 /* __vector(void[]) is treated same as __vector(ubyte[]) */ 273 if (type == Type::tvoid) 274 type = Type::tuns8; 275 276 /* No support for non-trivial types, complex types, or booleans. */ 277 if (!type->isTypeBasic () || type->iscomplex () || type->ty == TY::Tbool) 278 return 2; 279 280 /* In [simd/vector extensions], which vector types are supported depends on 281 the target. The implementation is expected to only support the vector 282 types that are implemented in the target's hardware. */ 283 unsigned HOST_WIDE_INT nunits = sz / type->size (); 284 tree ctype = build_vector_type (build_ctype (type), nunits); 285 286 if (!targetm.vector_mode_supported_p (TYPE_MODE (ctype))) 287 return 2; 288 289 return 0; 290 } 291 292 /* Checks whether the target supports operation OP for vectors of type TYPE. 293 For binary ops T2 is the type of the right-hand operand. 294 Returns true if the operation is supported or type is not a vector. */ 295 296 bool 297 Target::isVectorOpSupported (Type *type, EXP op, Type *) 298 { 299 if (type->ty != TY::Tvector) 300 return true; 301 302 /* Don't support if type is non-scalar, such as __vector(void[]). */ 303 if (!type->isscalar ()) 304 return false; 305 306 /* Don't support if expression cannot be represented. */ 307 switch (op) 308 { 309 case EXP::pow: 310 case EXP::powAssign: 311 /* pow() is lowered as a function call. */ 312 return false; 313 314 case EXP::mod: 315 case EXP::modAssign: 316 /* fmod() is lowered as a function call. */ 317 if (type->isfloating ()) 318 return false; 319 break; 320 321 case EXP::andAnd: 322 case EXP::orOr: 323 /* Logical operators must have a result type of bool. */ 324 return false; 325 326 case EXP::lessOrEqual: 327 case EXP::lessThan: 328 case EXP::greaterOrEqual: 329 case EXP::greaterThan: 330 case EXP::equal: 331 case EXP::notEqual: 332 case EXP::identity: 333 case EXP::notIdentity: 334 /* Comparison operators must have a result type of bool. */ 335 return false; 336 337 default: 338 break; 339 } 340 341 return true; 342 } 343 344 /* Return the symbol mangling of S for C++ linkage. */ 345 346 const char * 347 TargetCPP::toMangle (Dsymbol *s) 348 { 349 return toCppMangleItanium (s); 350 } 351 352 /* Return the symbol mangling of CD for C++ linkage. */ 353 354 const char * 355 TargetCPP::typeInfoMangle (ClassDeclaration *cd) 356 { 357 return cppTypeInfoMangleItanium (cd); 358 } 359 360 /* Get mangle name of a this-adjusting thunk to the function declaration FD 361 at call offset OFFSET for C++ linkage. */ 362 363 const char * 364 TargetCPP::thunkMangle (FuncDeclaration *fd, int offset) 365 { 366 return cppThunkMangleItanium (fd, offset); 367 } 368 369 /* For a vendor-specific type, return a string containing the C++ mangling. 370 In all other cases, return NULL. */ 371 372 const char * 373 TargetCPP::typeMangle (Type *type) 374 { 375 if (type->isTypeBasic () || type->ty == TY::Tvector 376 || type->ty == TY::Tstruct) 377 { 378 tree ctype = build_ctype (type); 379 return targetm.mangle_type (ctype); 380 } 381 382 return NULL; 383 } 384 385 /* Return the type that will really be used for passing the given parameter 386 ARG to an extern(C++) function. */ 387 388 Type * 389 TargetCPP::parameterType (Type *type) 390 { 391 /* Could be a va_list, which we mangle as a pointer. */ 392 Type *tvalist = target.va_listType (Loc (), NULL); 393 if (type->ty == TY::Tsarray && tvalist->ty == TY::Tsarray) 394 { 395 Type *tb = type->toBasetype ()->mutableOf (); 396 if (tb == tvalist) 397 { 398 tb = type->nextOf ()->pointerTo (); 399 type = tb->castMod (type->mod); 400 } 401 } 402 403 return type; 404 } 405 406 /* Checks whether TYPE is a vendor-specific fundamental type. Stores the result 407 in IS_FUNDAMENTAL and returns true if the parameter was set. */ 408 409 bool 410 TargetCPP::fundamentalType (const Type *, bool &) 411 { 412 return false; 413 } 414 415 /* Get the starting offset position for fields of an `extern(C++)` class 416 that is derived from the given BASE_CLASS. */ 417 418 unsigned 419 TargetCPP::derivedClassOffset(ClassDeclaration *base_class) 420 { 421 return base_class->structsize; 422 } 423 424 /* Return the default `extern (System)' linkage for the target. */ 425 426 LINK 427 Target::systemLinkage (void) 428 { 429 unsigned link_system, link_windows; 430 431 if (targetdm.d_has_stdcall_convention (&link_system, &link_windows)) 432 { 433 /* In [attribute/linkage], `System' is the same as `Windows' on Windows 434 platforms, and `C' on other platforms. */ 435 if (link_system) 436 return LINK::windows; 437 } 438 439 return LINK::c; 440 } 441 442 /* Generate a TypeTuple of the equivalent types used to determine if a 443 function argument of the given type can be passed in registers. 444 The results of this are highly platform dependent, and intended 445 primarly for use in implementing va_arg() with RTTI. */ 446 447 TypeTuple * 448 Target::toArgTypes (Type *) 449 { 450 /* Not implemented, however this is not currently used anywhere. */ 451 return NULL; 452 } 453 454 /* Determine return style of function, whether in registers or through a 455 hidden pointer to the caller's stack. */ 456 457 bool 458 Target::isReturnOnStack (TypeFunction *tf, bool) 459 { 460 /* Need the back-end type to determine this, but this is called from the 461 frontend before semantic processing is finished. An accurate value 462 is not currently needed anyway. */ 463 if (tf->isref ()) 464 return false; 465 466 Type *tn = tf->next->toBasetype (); 467 if (tn->size () == SIZE_INVALID) 468 return false; 469 470 return (tn->ty == TY::Tstruct || tn->ty == TY::Tsarray); 471 } 472 473 /* Add all target info in HANDLERS to D_TARGET_INFO_TABLE for use by 474 Target::getTargetInfo(). */ 475 476 void 477 d_add_target_info_handlers (const d_target_info_spec *handlers) 478 { 479 gcc_assert (handlers != NULL); 480 481 if (d_target_info_table.is_empty ()) 482 d_target_info_table.create (8); 483 484 for (size_t i = 0; handlers[i].name != NULL; i++) 485 d_target_info_table.safe_push (handlers[i]); 486 } 487 488 /* Handle a call to `__traits(getTargetInfo, "cppStd")'. */ 489 490 tree 491 d_handle_target_cpp_std (void) 492 { 493 return build_integer_cst (global.params.cplusplus); 494 } 495 496 /* Handle a call to `__traits(getTargetInfo, "cppRuntimeLibrary")'. */ 497 498 tree 499 d_handle_target_cpp_runtime_library (void) 500 { 501 /* The driver only ever optionally links to libstdc++. */ 502 const char *libstdcxx = "libstdc++"; 503 return build_string_literal (strlen (libstdcxx) + 1, libstdcxx); 504 } 505 506 /* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ 507 508 tree 509 d_handle_target_object_format (void) 510 { 511 const char *objfmt; 512 513 #ifdef OBJECT_FORMAT_ELF 514 objfmt = "elf"; 515 #else 516 if (TARGET_COFF || TARGET_PECOFF) 517 objfmt = "coff"; 518 else 519 objfmt = ""; 520 #endif 521 522 return build_string_literal (strlen (objfmt) + 1, objfmt); 523 } 524 525 /* Look up the target info KEY in the available getTargetInfo tables, and return 526 the result as an Expression, or NULL if KEY is not found. When the key must 527 always exist, but is not supported, an empty string expression is returned. 528 LOC is the location to use for the returned expression. */ 529 530 Expression * 531 Target::getTargetInfo (const char *key, const Loc &loc) 532 { 533 unsigned ix; 534 d_target_info_spec *spec; 535 536 FOR_EACH_VEC_ELT (d_target_info_table, ix, spec) 537 { 538 tree result; 539 540 if (strcmp (key, spec->name) != 0) 541 continue; 542 543 /* Get the requested information, or empty string if unhandled. */ 544 if (spec->handler) 545 { 546 result = (spec->handler) (); 547 /* Handler didn't return a result, meaning it really does not support 548 the key in the current target configuration. Check whether there 549 are any other handlers which may recognize the key. */ 550 if (result == NULL_TREE) 551 continue; 552 } 553 else 554 result = build_string_literal (1, ""); 555 556 gcc_assert (result); 557 return d_eval_constant_expression (loc, result); 558 } 559 560 return NULL; 561 } 562 563 /* Returns true if the callee invokes destructors for arguments. */ 564 565 bool 566 Target::isCalleeDestroyingArgs (TypeFunction *tf) 567 { 568 return tf->linkage == LINK::d; 569 } 570 571 /* Returns true if the implementation for object monitors is always defined 572 in the D runtime library (rt/monitor_.d). */ 573 574 bool 575 Target::libraryObjectMonitors (FuncDeclaration *, Statement *) 576 { 577 return true; 578 } 579 580 /* Returns true if the target supports `pragma(linkerDirective)'. */ 581 582 bool 583 Target::supportsLinkerDirective (void) const 584 { 585 return false; 586 } 587 588 /* Decides whether an `in' parameter of the specified POD type PARAM_TYPE is to 589 be passed by reference or by value. This is used only when compiling with 590 `-fpreview=in' enabled. */ 591 592 bool 593 Target::preferPassByRef (Type *param_type) 594 { 595 /* See note in Target::isReturnOnStack. */ 596 Type *tb = param_type->toBasetype (); 597 if (tb->size () == SIZE_INVALID) 598 return false; 599 600 return (tb->ty == TY::Tstruct || tb->ty == TY::Tsarray); 601 } 602