1 /* strub (stack scrubbing) support. 2 Copyright (C) 2021-2024 Free Software Foundation, Inc. 3 Contributed by Alexandre Oliva <oliva (at) adacore.com>. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 3, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #include "config.h" 22 #include "system.h" 23 #include "coretypes.h" 24 #include "backend.h" 25 #include "tree.h" 26 #include "gimple.h" 27 #include "gimplify.h" 28 #include "tree-pass.h" 29 #include "ssa.h" 30 #include "gimple-iterator.h" 31 #include "gimplify-me.h" 32 #include "tree-into-ssa.h" 33 #include "tree-ssa.h" 34 #include "tree-cfg.h" 35 #include "cfghooks.h" 36 #include "cfgloop.h" 37 #include "cfgcleanup.h" 38 #include "tree-eh.h" 39 #include "except.h" 40 #include "builtins.h" 41 #include "attribs.h" 42 #include "tree-inline.h" 43 #include "cgraph.h" 44 #include "alloc-pool.h" 45 #include "symbol-summary.h" 46 #include "sreal.h" 47 #include "ipa-cp.h" 48 #include "ipa-prop.h" 49 #include "ipa-fnsummary.h" 50 #include "gimple-fold.h" 51 #include "fold-const.h" 52 #include "gimple-walk.h" 53 #include "tree-dfa.h" 54 #include "langhooks.h" 55 #include "calls.h" 56 #include "vec.h" 57 #include "stor-layout.h" 58 #include "varasm.h" 59 #include "alias.h" 60 #include "diagnostic.h" 61 #include "intl.h" 62 #include "ipa-strub.h" 63 #include "symtab-thunks.h" 64 #include "attr-fnspec.h" 65 #include "target.h" 66 67 /* This file introduces two passes that, together, implement 68 machine-independent stack scrubbing, strub for short. It arranges 69 for stack frames that have strub enabled to be zeroed-out after 70 relinquishing control to a caller, whether by returning or by 71 propagating an exception. This admittedly unusual design decision 72 was driven by exception support (one needs a stack frame to be 73 active to propagate exceptions out of it), and it enabled an 74 implementation that is entirely machine-independent (no custom 75 epilogue code is required). 76 77 Strub modes can be selected for stack frames by attaching attribute 78 strub to functions or to variables (to their types, actually). 79 Different strub modes, with different implementation details, are 80 available, and they can be selected by an argument to the strub 81 attribute. When enabled by strub-enabled variables, whether by 82 accessing (as in reading from) statically-allocated ones, or by 83 introducing (as in declaring) automatically-allocated ones, a 84 suitable mode is selected automatically. 85 86 At-calls mode modifies the interface of a function, adding a stack 87 watermark argument, that callers use to clean up the stack frame of 88 the called function. Because of the interface change, it can only 89 be used when explicitly selected, or when a function is internal to 90 a translation unit. Strub-at-calls function types are distinct 91 from their original types (they're not modified in-place), and they 92 are not interchangeable with other function types. 93 94 Internal mode, in turn, does not modify the type or the interface 95 of a function. It is currently implemented by turning the function 96 into a wrapper, moving the function body to a separate wrapped 97 function, and scrubbing the wrapped body's stack in the wrapper. 98 Internal-strub function types are mostly interface-compatible with 99 other strub modes, namely callable (from strub functions, though 100 not strub-enabled) and disabled (not callable from strub 101 functions). 102 103 Always_inline functions can be strub functions, but they can only 104 be called from other strub functions, because strub functions must 105 never be inlined into non-strub functions. Internal and at-calls 106 modes are indistinguishable when it comes to always_inline 107 functions: they will necessarily be inlined into another strub 108 function, and will thus be integrated into the caller's stack 109 frame, whatever the mode. (Contrast with non-always_inline strub 110 functions: an at-calls function can be called from other strub 111 functions, ensuring no discontinuity in stack erasing, whereas an 112 internal-strub function can only be called from other strub 113 functions if it happens to be inlined, or if -fstrub=relaxed mode 114 is in effect (that's the default). In -fstrub=strict mode, 115 internal-strub functions are not callable from strub functions, 116 because the wrapper itself is not strubbed. 117 118 The implementation involves two simple-IPA passes. The earliest 119 one, strub-mode, assigns strub modes to functions. It needs to run 120 before any inlining, so that we can prevent inlining of strub 121 functions into non-strub functions. It notes explicit strub mode 122 requests, enables strub in response to strub variables and testing 123 options, and flags unsatisfiable requests. 124 125 Three possibilities of unsatisfiable requests come to mind: (a) 126 when a strub mode is explicitly selected, but the function uses 127 features that make it ineligible for that mode (e.g. at-calls rules 128 out calling __builtin_apply_args, because of the interface changes, 129 and internal mode rules out noclone or otherwise non-versionable 130 functions, non-default varargs, non-local or forced labels, and 131 functions with far too many arguments); (b) when some strub mode 132 must be enabled because of a strub variable, but the function is 133 not eligible or not viable for any mode; and (c) when 134 -fstrub=strict is enabled, and calls are found in strub functions 135 to functions that are not callable from strub contexts. 136 compute_strub_mode implements (a) and (b), and verify_strub 137 implements (c). 138 139 The second IPA pass modifies interfaces of at-calls-strub functions 140 and types, introduces strub calls in and around them. and splits 141 internal-strub functions. It is placed after early inlining, so 142 that even internal-strub functions get a chance of being inlined 143 into other strub functions, but before non-early inlining, so that 144 internal-strub wrapper functions still get a chance of inlining 145 after splitting. 146 147 Wrappers avoid duplicating the copying of large arguments again by 148 passing them by reference to the wrapped bodies. This involves 149 occasional SSA rewriting of address computations, because of the 150 additional indirection. Besides these changes, and the 151 introduction of the stack watermark parameter, wrappers and wrapped 152 functions cooperate to handle variable argument lists (performing 153 va_start in the wrapper, passing the list as an argument, and 154 replacing va_start calls in the wrapped body with va_copy), and 155 __builtin_apply_args (also called in the wrapper and passed to the 156 wrapped body as an argument). 157 158 Strub bodies (both internal-mode wrapped bodies, and at-calls 159 functions) always start by adjusting the watermark parameter, by 160 calling __builtin___strub_update. The compiler inserts them in the 161 main strub pass. Allocations of additional stack space for the 162 frame (__builtin_alloca) are also followed by watermark updates. 163 Stack space temporarily allocated to pass arguments to other 164 functions, released right after the call, is not regarded as part 165 of the frame. Around calls to them, i.e., in internal-mode 166 wrappers and at-calls callers (even calls through pointers), calls 167 to __builtin___strub_enter and __builtin___strub_leave are 168 inserted, the latter as a __finally block, so that it runs at 169 regular and exceptional exit paths. strub_enter only initializes 170 the stack watermark, and strub_leave is where the scrubbing takes 171 place, overwriting with zeros the stack space from the top of the 172 stack to the watermark. 173 174 These calls can be optimized in various cases. In 175 pass_ipa_strub::adjust_at_calls_call, for example, we enable 176 tail-calling and other optimized calls from one strub body to 177 another by passing on the watermark parameter. The builtins 178 themselves may undergo inline substitution during expansion, 179 dependign on optimization levels. This involves dealing with stack 180 red zones (when the builtins are called out-of-line, the red zone 181 cannot be used) and other ugly details related with inlining strub 182 bodies into other strub bodies (see expand_builtin_strub_update). 183 expand_builtin_strub_leave may even perform partial inline 184 substitution. */ 185 186 /* Const and pure functions that gain a watermark parameter for strub purposes 187 are still regarded as such, which may cause the inline expansions of the 188 __strub builtins to malfunction. Ideally, attribute "fn spec" would enable 189 us to inform the backend about requirements and side effects of the call, but 190 call_fusage building in calls.c:expand_call does not even look at 191 attr_fnspec, so we resort to asm loads and updates to attain an equivalent 192 effect. Once expand_call gains the ability to issue extra memory uses and 193 clobbers based on pure/const function's fnspec, we can define this to 1. */ 194 #define ATTR_FNSPEC_DECONST_WATERMARK 0 195 196 enum strub_mode { 197 /* This mode denotes a regular function, that does not require stack 198 scrubbing (strubbing). It may call any other functions, but if 199 it calls AT_CALLS (or WRAPPED) ones, strubbing logic is 200 automatically introduced around those calls (the latter, by 201 inlining INTERNAL wrappers). */ 202 STRUB_DISABLED = 0, 203 204 /* This denotes a function whose signature is (to be) modified to 205 take an extra parameter, for stack use annotation, and its 206 callers must initialize and pass that argument, and perform the 207 strubbing. Functions that are explicitly marked with attribute 208 strub must have the mark visible wherever the function is, 209 including aliases, and overriders and overriding methods. 210 Functions that are implicitly marked for strubbing, for accessing 211 variables explicitly marked as such, will only select this 212 strubbing method if they are internal to a translation unit. It 213 can only be inlined into other strubbing functions, i.e., 214 STRUB_AT_CALLS or STRUB_WRAPPED. */ 215 STRUB_AT_CALLS = 1, 216 217 /* This denotes a function that is to perform strubbing internally, 218 without any changes to its interface (the function is turned into 219 a strubbing wrapper, and its original body is moved to a separate 220 STRUB_WRAPPED function, with a modified interface). Functions 221 may be explicitly marked with attribute strub(2), and the 222 attribute must be visible at the point of definition. Functions 223 that are explicitly marked for strubbing, for accessing variables 224 explicitly marked as such, may select this strubbing mode if 225 their interface cannot change, e.g. because its interface is 226 visible to other translation units, directly, by indirection 227 (having its address taken), inheritance, etc. Functions that use 228 this method must not have the noclone attribute, nor the noipa 229 one. Functions marked as always_inline may select this mode, but 230 they are NOT wrapped, they remain unchanged, and are only inlined 231 into strubbed contexts. Once non-always_inline functions are 232 wrapped, the wrapper becomes STRUB_WRAPPER, and the wrapped becomes 233 STRUB_WRAPPED. */ 234 STRUB_INTERNAL = 2, 235 236 /* This denotes a function whose stack is not strubbed, but that is 237 nevertheless explicitly or implicitly marked as callable from strubbing 238 functions. Normally, only STRUB_AT_CALLS (and STRUB_INTERNAL -> 239 STRUB_WRAPPED) functions can be called from strubbing contexts (bodies of 240 STRUB_AT_CALLS, STRUB_INTERNAL and STRUB_WRAPPED functions), but attribute 241 strub(3) enables other functions to be (indirectly) called from these 242 contexts. Some builtins and internal functions may be implicitly marked as 243 STRUB_CALLABLE. */ 244 STRUB_CALLABLE = 3, 245 246 /* This denotes the function that took over the body of a 247 STRUB_INTERNAL function. At first, it's only called by its 248 wrapper, but the wrapper may be inlined. The wrapped function, 249 in turn, can only be inlined into other functions whose stack 250 frames are strubbed, i.e., that are STRUB_WRAPPED or 251 STRUB_AT_CALLS. */ 252 STRUB_WRAPPED = -1, 253 254 /* This denotes the wrapper function that replaced the STRUB_INTERNAL 255 function. This mode overrides the STRUB_INTERNAL mode at the time the 256 internal to-be-wrapped function becomes a wrapper, so that inlining logic 257 can tell one from the other. */ 258 STRUB_WRAPPER = -2, 259 260 /* This denotes an always_inline function that requires strubbing. It can 261 only be called from, and inlined into, other strubbing contexts. */ 262 STRUB_INLINABLE = -3, 263 264 /* This denotes a function that accesses strub variables, so it would call for 265 internal strubbing (whether or not it's eligible for that), but since 266 at-calls strubbing is viable, that's selected as an optimization. This 267 mode addresses the inconvenience that such functions may have different 268 modes selected depending on optimization flags, and get a different 269 callable status depending on that choice: if we assigned them 270 STRUB_AT_CALLS mode, they would be callable when optimizing, whereas 271 STRUB_INTERNAL would not be callable. */ 272 STRUB_AT_CALLS_OPT = -4, 273 274 }; 275 276 /* Look up a strub attribute in TYPE, and return it. */ 277 278 static tree 279 get_strub_attr_from_type (tree type) 280 { 281 return lookup_attribute ("strub", TYPE_ATTRIBUTES (type)); 282 } 283 284 /* Look up a strub attribute in DECL or in its type, and return it. */ 285 286 static tree 287 get_strub_attr_from_decl (tree decl) 288 { 289 tree ret = lookup_attribute ("strub", DECL_ATTRIBUTES (decl)); 290 if (ret) 291 return ret; 292 return get_strub_attr_from_type (TREE_TYPE (decl)); 293 } 294 295 #define STRUB_ID_COUNT 8 296 #define STRUB_IDENT_COUNT 3 297 #define STRUB_TYPE_COUNT 5 298 299 #define STRUB_ID_BASE 0 300 #define STRUB_IDENT_BASE (STRUB_ID_BASE + STRUB_ID_COUNT) 301 #define STRUB_TYPE_BASE (STRUB_IDENT_BASE + STRUB_IDENT_COUNT) 302 #define STRUB_CACHE_SIZE (STRUB_TYPE_BASE + STRUB_TYPE_COUNT) 303 304 /* Keep the strub mode and temp identifiers and types from being GC'd. */ 305 static GTY((deletable)) tree strub_cache[STRUB_CACHE_SIZE]; 306 307 /* Define a function to cache identifier ID, to be used as a strub attribute 308 parameter for a strub mode named after NAME. */ 309 #define DEF_STRUB_IDS(IDX, NAME, ID) \ 310 static inline tree get_strub_mode_id_ ## NAME () { \ 311 int idx = STRUB_ID_BASE + IDX; \ 312 tree identifier = strub_cache[idx]; \ 313 if (!identifier) \ 314 strub_cache[idx] = identifier = get_identifier (ID); \ 315 return identifier; \ 316 } 317 /* Same as DEF_STRUB_IDS, but use the string expansion of NAME as ID. */ 318 #define DEF_STRUB_ID(IDX, NAME) \ 319 DEF_STRUB_IDS (IDX, NAME, #NAME) 320 321 /* Define functions for each of the strub mode identifiers. 322 Expose dashes rather than underscores. */ 323 DEF_STRUB_ID (0, disabled) 324 DEF_STRUB_IDS (1, at_calls, "at-calls") 325 DEF_STRUB_ID (2, internal) 326 DEF_STRUB_ID (3, callable) 327 DEF_STRUB_ID (4, wrapped) 328 DEF_STRUB_ID (5, wrapper) 329 DEF_STRUB_ID (6, inlinable) 330 DEF_STRUB_IDS (7, at_calls_opt, "at-calls-opt") 331 332 /* Release the temporary macro names. */ 333 #undef DEF_STRUB_IDS 334 #undef DEF_STRUB_ID 335 336 /* Return the identifier corresponding to strub MODE. */ 337 338 static tree 339 get_strub_mode_attr_parm (enum strub_mode mode) 340 { 341 switch (mode) 342 { 343 case STRUB_DISABLED: 344 return get_strub_mode_id_disabled (); 345 346 case STRUB_AT_CALLS: 347 return get_strub_mode_id_at_calls (); 348 349 case STRUB_INTERNAL: 350 return get_strub_mode_id_internal (); 351 352 case STRUB_CALLABLE: 353 return get_strub_mode_id_callable (); 354 355 case STRUB_WRAPPED: 356 return get_strub_mode_id_wrapped (); 357 358 case STRUB_WRAPPER: 359 return get_strub_mode_id_wrapper (); 360 361 case STRUB_INLINABLE: 362 return get_strub_mode_id_inlinable (); 363 364 case STRUB_AT_CALLS_OPT: 365 return get_strub_mode_id_at_calls_opt (); 366 367 default: 368 gcc_unreachable (); 369 } 370 } 371 372 /* Return the parmeters (TREE_VALUE) for a strub attribute of MODE. 373 We know we use a single parameter, so we bypass the creation of a 374 tree list. */ 375 376 static tree 377 get_strub_mode_attr_value (enum strub_mode mode) 378 { 379 return get_strub_mode_attr_parm (mode); 380 } 381 382 /* Determine whether ID is a well-formed strub mode-specifying attribute 383 parameter for a function (type). Only user-visible modes are accepted, and 384 ID must be non-NULL. 385 386 For unacceptable parms, return 0, otherwise a nonzero value as below. 387 388 If the parm enables strub, return positive, otherwise negative. 389 390 If the affected type must be a distinct, incompatible type,return an integer 391 of absolute value 2, otherwise 1. */ 392 393 int 394 strub_validate_fn_attr_parm (tree id) 395 { 396 int ret; 397 const char *s = NULL; 398 size_t len = 0; 399 400 /* do NOT test for NULL. This is only to be called with non-NULL arguments. 401 We assume that the strub parameter applies to a function, because only 402 functions accept an explicit argument. If we accepted NULL, and we 403 happened to be called to verify the argument for a variable, our return 404 values would be wrong. */ 405 if (TREE_CODE (id) == STRING_CST) 406 { 407 s = TREE_STRING_POINTER (id); 408 len = TREE_STRING_LENGTH (id) - 1; 409 } 410 else if (TREE_CODE (id) == IDENTIFIER_NODE) 411 { 412 s = IDENTIFIER_POINTER (id); 413 len = IDENTIFIER_LENGTH (id); 414 } 415 else 416 return 0; 417 418 enum strub_mode mode; 419 420 if (len != 8) 421 return 0; 422 423 switch (s[0]) 424 { 425 case 'd': 426 mode = STRUB_DISABLED; 427 ret = -1; 428 break; 429 430 case 'a': 431 mode = STRUB_AT_CALLS; 432 ret = 2; 433 break; 434 435 case 'i': 436 mode = STRUB_INTERNAL; 437 ret = 1; 438 break; 439 440 case 'c': 441 mode = STRUB_CALLABLE; 442 ret = -2; 443 break; 444 445 default: 446 /* Other parms are for internal use only. */ 447 return 0; 448 } 449 450 tree mode_id = get_strub_mode_attr_parm (mode); 451 452 if (TREE_CODE (id) == IDENTIFIER_NODE 453 ? id != mode_id 454 : strncmp (s, IDENTIFIER_POINTER (mode_id), len) != 0) 455 return 0; 456 457 return ret; 458 } 459 460 /* Return the strub mode from STRUB_ATTR. VAR_P should be TRUE if the attribute 461 is taken from a variable, rather than from a function, or a type thereof. */ 462 463 static enum strub_mode 464 get_strub_mode_from_attr (tree strub_attr, bool var_p = false) 465 { 466 enum strub_mode mode = STRUB_DISABLED; 467 468 if (strub_attr) 469 { 470 if (!TREE_VALUE (strub_attr)) 471 mode = !var_p ? STRUB_AT_CALLS : STRUB_INTERNAL; 472 else 473 { 474 gcc_checking_assert (!var_p); 475 tree id = TREE_VALUE (strub_attr); 476 if (TREE_CODE (id) == TREE_LIST) 477 id = TREE_VALUE (id); 478 const char *s = (TREE_CODE (id) == STRING_CST 479 ? TREE_STRING_POINTER (id) 480 : IDENTIFIER_POINTER (id)); 481 size_t len = (TREE_CODE (id) == STRING_CST 482 ? TREE_STRING_LENGTH (id) - 1 483 : IDENTIFIER_LENGTH (id)); 484 485 switch (len) 486 { 487 case 7: 488 switch (s[6]) 489 { 490 case 'r': 491 mode = STRUB_WRAPPER; 492 break; 493 494 case 'd': 495 mode = STRUB_WRAPPED; 496 break; 497 498 default: 499 gcc_unreachable (); 500 } 501 break; 502 503 case 8: 504 switch (s[0]) 505 { 506 case 'd': 507 mode = STRUB_DISABLED; 508 break; 509 510 case 'a': 511 mode = STRUB_AT_CALLS; 512 break; 513 514 case 'i': 515 mode = STRUB_INTERNAL; 516 break; 517 518 case 'c': 519 mode = STRUB_CALLABLE; 520 break; 521 522 default: 523 gcc_unreachable (); 524 } 525 break; 526 527 case 9: 528 mode = STRUB_INLINABLE; 529 break; 530 531 case 12: 532 mode = STRUB_AT_CALLS_OPT; 533 break; 534 535 default: 536 gcc_unreachable (); 537 } 538 539 gcc_checking_assert (TREE_CODE (id) == IDENTIFIER_NODE 540 ? id == get_strub_mode_attr_parm (mode) 541 : strncmp (IDENTIFIER_POINTER 542 (get_strub_mode_attr_parm (mode)), 543 s, len) == 0); 544 } 545 } 546 547 return mode; 548 } 549 550 /* Look up, decode and return the strub mode associated with FNDECL. */ 551 552 static enum strub_mode 553 get_strub_mode_from_fndecl (tree fndecl) 554 { 555 return get_strub_mode_from_attr (get_strub_attr_from_decl (fndecl)); 556 } 557 558 /* Look up, decode and return the strub mode associated with NODE. */ 559 560 static enum strub_mode 561 get_strub_mode (cgraph_node *node) 562 { 563 return get_strub_mode_from_fndecl (node->decl); 564 } 565 566 /* Look up, decode and return the strub mode associated with TYPE. */ 567 568 static enum strub_mode 569 get_strub_mode_from_type (tree type) 570 { 571 bool var_p = !FUNC_OR_METHOD_TYPE_P (type); 572 tree attr = get_strub_attr_from_type (type); 573 574 if (attr) 575 return get_strub_mode_from_attr (attr, var_p); 576 577 if (flag_strub >= -1 && !var_p) 578 return STRUB_CALLABLE; 579 580 return STRUB_DISABLED; 581 } 582 583 584 /* Return TRUE iff NODE calls builtin va_start. */ 586 587 static bool 588 calls_builtin_va_start_p (cgraph_node *node) 589 { 590 bool result = false; 591 592 for (cgraph_edge *e = node->callees; e; e = e->next_callee) 593 { 594 tree cdecl = e->callee->decl; 595 if (fndecl_built_in_p (cdecl, BUILT_IN_VA_START)) 596 return true; 597 } 598 599 return result; 600 } 601 602 /* Return TRUE iff NODE calls builtin apply_args, and optionally REPORT it. */ 603 604 static bool 605 calls_builtin_apply_args_p (cgraph_node *node, bool report = false) 606 { 607 bool result = false; 608 609 for (cgraph_edge *e = node->callees; e; e = e->next_callee) 610 { 611 tree cdecl = e->callee->decl; 612 if (!fndecl_built_in_p (cdecl, BUILT_IN_APPLY_ARGS)) 613 continue; 614 615 result = true; 616 617 if (!report) 618 break; 619 620 sorry_at (e->call_stmt 621 ? gimple_location (e->call_stmt) 622 : DECL_SOURCE_LOCATION (node->decl), 623 "at-calls %<strub%> does not support call to %qD", 624 cdecl); 625 } 626 627 return result; 628 } 629 630 /* Return TRUE iff NODE carries the always_inline attribute. */ 631 632 static inline bool 633 strub_always_inline_p (cgraph_node *node) 634 { 635 return lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl)); 636 } 637 638 /* Return TRUE iff the target has strub support for T, a function 639 decl, or a type used in an indirect call, and optionally REPORT the 640 reasons for ineligibility. If T is a type and error REPORTing is 641 enabled, the LOCation (of the indirect call) should be provided. */ 642 static inline bool 643 strub_target_support_p (tree t, bool report = false, 644 location_t loc = UNKNOWN_LOCATION) 645 { 646 bool result = true; 647 648 if (!targetm.have_strub_support_for (t)) 649 { 650 result = false; 651 652 if (!report) 653 return result; 654 655 if (DECL_P (t)) 656 sorry_at (DECL_SOURCE_LOCATION (t), 657 "%qD is not eligible for %<strub%>" 658 " on the target system", t); 659 else 660 sorry_at (loc, 661 "unsupported %<strub%> call" 662 " on the target system"); 663 } 664 665 return result; 666 } 667 668 /* Return TRUE iff NODE is potentially eligible for any strub-enabled mode, and 669 optionally REPORT the reasons for ineligibility. */ 670 671 static inline bool 672 can_strub_p (cgraph_node *node, bool report = false) 673 { 674 bool result = strub_target_support_p (node->decl, report); 675 676 if (!report && (!result || strub_always_inline_p (node))) 677 return result; 678 679 if (flag_split_stack) 680 { 681 result = false; 682 683 if (!report) 684 return result; 685 686 sorry_at (DECL_SOURCE_LOCATION (node->decl), 687 "%qD is not eligible for %<strub%>" 688 " because %<-fsplit-stack%> is enabled", 689 node->decl); 690 } 691 692 if (lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl))) 693 { 694 result = false; 695 696 if (!report) 697 return result; 698 699 sorry_at (DECL_SOURCE_LOCATION (node->decl), 700 "%qD is not eligible for %<strub%>" 701 " because of attribute %<noipa%>", 702 node->decl); 703 } 704 705 /* We can't, and don't want to vectorize the watermark and other 706 strub-introduced parms. */ 707 if (lookup_attribute ("simd", DECL_ATTRIBUTES (node->decl))) 708 { 709 result = false; 710 711 if (!report) 712 return result; 713 714 sorry_at (DECL_SOURCE_LOCATION (node->decl), 715 "%qD is not eligible for %<strub%>" 716 " because of attribute %<simd%>", 717 node->decl); 718 } 719 720 return result; 721 } 722 723 /* Return TRUE iff NODE is eligible for at-calls strub, and optionally REPORT 724 the reasons for ineligibility. Besides general non-eligibility for 725 strub-enabled modes, at-calls rules out calling builtin apply_args. */ 726 727 static bool 728 can_strub_at_calls_p (cgraph_node *node, bool report = false) 729 { 730 bool result = !report || can_strub_p (node, report); 731 732 if (!result && !report) 733 return result; 734 735 return !calls_builtin_apply_args_p (node, report); 736 } 737 738 /* Return TRUE iff the called function (pointer or, if available, 739 decl) undergoes a significant type conversion for the call. Strub 740 mode changes between function types, and other non-useless type 741 conversions, are regarded as significant. When the function type 742 is overridden, the effective strub mode for the call is that of the 743 call fntype, rather than that of the pointer or of the decl. 744 Functions called with type overrides cannot undergo type changes; 745 it's as if their address was taken, so they're considered 746 non-viable for implicit at-calls strub mode. */ 747 748 static inline bool 749 strub_call_fntype_override_p (const gcall *gs) 750 { 751 if (gimple_call_internal_p (gs)) 752 return false; 753 tree fn_type = TREE_TYPE (TREE_TYPE (gimple_call_fn (gs))); 754 if (tree decl = gimple_call_fndecl (gs)) 755 fn_type = TREE_TYPE (decl); 756 757 /* We do NOT want to take the mode from the decl here. This 758 function is used to tell whether we can change the strub mode of 759 a function, and whether the effective mode for the call is to be 760 taken from the decl or from an overrider type. When the strub 761 mode is explicitly declared, or overridden with a type cast, the 762 difference will be noticed in function types. However, if the 763 strub mode is implicit due to e.g. strub variables or -fstrub=* 764 command-line flags, we will adjust call types along with function 765 types. In either case, the presence of type or strub mode 766 overriders in calls will prevent a function from having its strub 767 modes changed in ways that would imply type changes, but taking 768 strub modes from decls would defeat this, since we set strub 769 modes and then call this function to tell whether the original 770 type was overridden to decide whether to adjust the call. We 771 need the answer to be about the type, not the decl. */ 772 enum strub_mode mode = get_strub_mode_from_type (fn_type); 773 return (get_strub_mode_from_type (gs->u.fntype) != mode 774 || !useless_type_conversion_p (gs->u.fntype, fn_type)); 775 } 776 777 /* Return TRUE iff NODE is called directly with a type override. */ 778 779 static bool 780 called_directly_with_type_override_p (cgraph_node *node, void *) 781 { 782 for (cgraph_edge *e = node->callers; e; e = e->next_caller) 783 if (e->call_stmt && strub_call_fntype_override_p (e->call_stmt)) 784 return true; 785 786 return false; 787 } 788 789 /* Return TRUE iff NODE or any other nodes aliased to it are called 790 with type overrides. We can't safely change the type of such 791 functions. */ 792 793 static bool 794 called_with_type_override_p (cgraph_node *node) 795 { 796 return (node->call_for_symbol_thunks_and_aliases 797 (called_directly_with_type_override_p, NULL, true, true)); 798 } 799 800 /* Symbolic macro for the max number of arguments that internal strub may add to 801 a function. */ 802 803 #define STRUB_INTERNAL_MAX_EXTRA_ARGS 3 804 805 /* We can't perform internal strubbing if the function body involves certain 806 features: 807 808 - a non-default __builtin_va_start (e.g. x86's __builtin_ms_va_start) is 809 currently unsupported because we can't discover the corresponding va_copy and 810 va_end decls in the wrapper, and we don't convey the alternate variable 811 arguments ABI to the modified wrapped function. The default 812 __builtin_va_start is supported by calling va_start/va_end at the wrapper, 813 that takes variable arguments, passing a pointer to the va_list object to the 814 wrapped function, that runs va_copy from it where the original function ran 815 va_start. 816 817 __builtin_next_arg is currently unsupported because the wrapped function 818 won't be a variable argument function. We could process it in the wrapper, 819 that remains a variable argument function, and replace calls in the wrapped 820 body, but we currently don't. 821 822 __builtin_return_address is rejected because it's generally used when the 823 actual caller matters, and introducing a wrapper breaks such uses as those in 824 the unwinder. */ 825 826 static bool 827 can_strub_internally_p (cgraph_node *node, bool report = false) 828 { 829 bool result = !report || can_strub_p (node, report); 830 831 if (!result && !report) 832 return result; 833 834 if (!report && strub_always_inline_p (node)) 835 return result; 836 837 /* Since we're not changing the function identity proper, just 838 moving its full implementation, we *could* disable 839 fun->cannot_be_copied_reason and/or temporarily drop a noclone 840 attribute, but we'd have to prevent remapping of the labels. */ 841 if (lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl))) 842 { 843 result = false; 844 845 if (!report) 846 return result; 847 848 sorry_at (DECL_SOURCE_LOCATION (node->decl), 849 "%qD is not eligible for internal %<strub%>" 850 " because of attribute %<noclone%>", 851 node->decl); 852 } 853 854 if (node->has_gimple_body_p ()) 855 { 856 for (cgraph_edge *e = node->callees; e; e = e->next_callee) 857 { 858 tree cdecl = e->callee->decl; 859 if (!((fndecl_built_in_p (cdecl, BUILT_IN_VA_START) 860 && cdecl != builtin_decl_explicit (BUILT_IN_VA_START)) 861 || fndecl_built_in_p (cdecl, BUILT_IN_NEXT_ARG) 862 || fndecl_built_in_p (cdecl, BUILT_IN_RETURN_ADDRESS))) 863 continue; 864 865 result = false; 866 867 if (!report) 868 return result; 869 870 sorry_at (e->call_stmt 871 ? gimple_location (e->call_stmt) 872 : DECL_SOURCE_LOCATION (node->decl), 873 "%qD is not eligible for internal %<strub%> " 874 "because it calls %qD", 875 node->decl, cdecl); 876 } 877 878 struct function *fun = DECL_STRUCT_FUNCTION (node->decl); 879 if (fun->has_nonlocal_label) 880 { 881 result = false; 882 883 if (!report) 884 return result; 885 886 sorry_at (DECL_SOURCE_LOCATION (node->decl), 887 "%qD is not eligible for internal %<strub%> " 888 "because it contains a non-local goto target", 889 node->decl); 890 } 891 892 if (fun->has_forced_label_in_static) 893 { 894 result = false; 895 896 if (!report) 897 return result; 898 899 sorry_at (DECL_SOURCE_LOCATION (node->decl), 900 "%qD is not eligible for internal %<strub%> " 901 "because the address of a local label escapes", 902 node->decl); 903 } 904 905 /* Catch any other case that would prevent versioning/cloning 906 so as to also have it covered above. */ 907 gcc_checking_assert (!result /* || !node->has_gimple_body_p () */ 908 || tree_versionable_function_p (node->decl)); 909 910 911 /* Label values references are not preserved when copying. If referenced 912 in nested functions, as in 920415-1.c and 920721-4.c their decls get 913 remapped independently. The exclusion below might be too broad, in 914 that we might be able to support correctly cases in which the labels 915 are only used internally in a function, but disconnecting forced labels 916 from their original declarations is undesirable in general. */ 917 basic_block bb; 918 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl)) 919 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); 920 !gsi_end_p (gsi); gsi_next (&gsi)) 921 { 922 glabel *label_stmt = dyn_cast <glabel *> (gsi_stmt (gsi)); 923 tree target; 924 925 if (!label_stmt) 926 break; 927 928 target = gimple_label_label (label_stmt); 929 930 if (!FORCED_LABEL (target)) 931 continue; 932 933 result = false; 934 935 if (!report) 936 return result; 937 938 sorry_at (gimple_location (label_stmt), 939 "internal %<strub%> does not support forced labels"); 940 } 941 } 942 943 if (list_length (TYPE_ARG_TYPES (TREE_TYPE (node->decl))) 944 >= ((HOST_WIDE_INT_1 << IPA_PARAM_MAX_INDEX_BITS) 945 - STRUB_INTERNAL_MAX_EXTRA_ARGS)) 946 { 947 result = false; 948 949 if (!report) 950 return result; 951 952 sorry_at (DECL_SOURCE_LOCATION (node->decl), 953 "%qD has too many arguments for internal %<strub%>", 954 node->decl); 955 } 956 957 return result; 958 } 959 960 /* Return TRUE iff NODE has any strub-requiring local variable, or accesses (as 961 in reading) any variable through a strub-requiring type. */ 962 963 static bool 964 strub_from_body_p (cgraph_node *node) 965 { 966 if (!node->has_gimple_body_p ()) 967 return false; 968 969 /* If any local variable is marked for strub... */ 970 unsigned i; 971 tree var; 972 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (node->decl), 973 i, var) 974 if (get_strub_mode_from_type (TREE_TYPE (var)) 975 != STRUB_DISABLED) 976 return true; 977 978 /* Now scan the body for loads with strub-requiring types. 979 ??? Compound types don't propagate the strub requirement to 980 component types. */ 981 basic_block bb; 982 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl)) 983 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); 984 !gsi_end_p (gsi); gsi_next (&gsi)) 985 { 986 gimple *stmt = gsi_stmt (gsi); 987 988 if (!gimple_assign_load_p (stmt)) 989 continue; 990 991 tree rhs = gimple_assign_rhs1 (stmt); 992 if (get_strub_mode_from_type (TREE_TYPE (rhs)) 993 != STRUB_DISABLED) 994 return true; 995 } 996 997 return false; 998 } 999 1000 /* Return TRUE iff node is associated with a builtin that should be callable 1001 from strub contexts. */ 1002 1003 static inline bool 1004 strub_callable_builtin_p (cgraph_node *node) 1005 { 1006 if (DECL_BUILT_IN_CLASS (node->decl) != BUILT_IN_NORMAL) 1007 return false; 1008 1009 enum built_in_function fcode = DECL_FUNCTION_CODE (node->decl); 1010 1011 switch (fcode) 1012 { 1013 case BUILT_IN_NONE: 1014 gcc_unreachable (); 1015 1016 /* This temporarily allocates stack for the call, and we can't reasonably 1017 update the watermark for that. Besides, we don't check the actual call 1018 target, nor its signature, and it seems to be overkill to as much as 1019 try to do so. */ 1020 case BUILT_IN_APPLY: 1021 return false; 1022 1023 /* Conversely, this shouldn't be called from within strub contexts, since 1024 the caller may have had its signature modified. STRUB_INTERNAL is ok, 1025 the call will remain in the STRUB_WRAPPER, and removed from the 1026 STRUB_WRAPPED clone. */ 1027 case BUILT_IN_APPLY_ARGS: 1028 return false; 1029 1030 /* ??? Make all other builtins callable. We wish to make any builtin call 1031 the compiler might introduce on its own callable. Anything that is 1032 predictable enough as to be known not to allow stack data that should 1033 be strubbed to unintentionally escape to non-strub contexts can be 1034 allowed, and pretty much every builtin appears to fit this description. 1035 The exceptions to this rule seem to be rare, and only available as 1036 explicit __builtin calls, so let's keep it simple and allow all of 1037 them... */ 1038 default: 1039 return true; 1040 } 1041 } 1042 1043 /* Compute the strub mode to be used for NODE. STRUB_ATTR should be the strub 1044 attribute,found for NODE, if any. */ 1045 1046 static enum strub_mode 1047 compute_strub_mode (cgraph_node *node, tree strub_attr) 1048 { 1049 enum strub_mode req_mode = get_strub_mode_from_attr (strub_attr); 1050 1051 gcc_checking_assert (flag_strub >= -2 && flag_strub <= 3); 1052 1053 /* Symbolic encodings of the -fstrub-* flags. */ 1054 /* Enable strub when explicitly requested through attributes to functions or 1055 variables, reporting errors if the requests cannot be satisfied. */ 1056 const bool strub_flag_auto = flag_strub < 0; 1057 /* strub_flag_auto with strub call verification; without this, functions are 1058 implicitly callable. */ 1059 const bool strub_flag_strict = flag_strub < -1; 1060 /* Disable strub altogether, ignore attributes entirely. */ 1061 const bool strub_flag_disabled = flag_strub == 0; 1062 /* On top of _auto, also enable strub implicitly for functions that can 1063 safely undergo at-calls strubbing. Internal mode will still be used in 1064 functions that request it explicitly with attribute strub(2), or when the 1065 function body requires strubbing and at-calls strubbing is not viable. */ 1066 const bool strub_flag_at_calls = flag_strub == 1; 1067 /* On top of default, also enable strub implicitly for functions that can 1068 safely undergo internal strubbing. At-calls mode will still be used in 1069 functions that requiest it explicitly with attribute strub() or strub(1), 1070 or when the function body requires strubbing and internal strubbing is not 1071 viable. */ 1072 const bool strub_flag_internal = flag_strub == 2; 1073 /* On top of default, also enable strub implicitly for functions that can 1074 safely undergo strubbing in either mode. When both modes are viable, 1075 at-calls is preferred. */ 1076 const bool strub_flag_either = flag_strub == 3; 1077 /* Besides the default behavior, enable strub implicitly for all viable 1078 functions. */ 1079 const bool strub_flag_viable = flag_strub > 0; 1080 1081 /* The consider_* variables should be TRUE if selecting the corresponding 1082 strub modes would be consistent with requests from attributes and command 1083 line flags. Attributes associated with functions pretty much mandate a 1084 selection, and should report an error if not satisfied; strub_flag_auto 1085 implicitly enables some viable strub mode if that's required by references 1086 to variables marked for strub; strub_flag_viable enables strub if viable 1087 (even when favoring one mode, body-requested strub can still be satisfied 1088 by either mode), and falls back to callable, silently unless variables 1089 require strubbing. */ 1090 1091 const bool consider_at_calls 1092 = (!strub_flag_disabled 1093 && (strub_attr 1094 ? req_mode == STRUB_AT_CALLS 1095 : true)); 1096 const bool consider_internal 1097 = (!strub_flag_disabled 1098 && (strub_attr 1099 ? req_mode == STRUB_INTERNAL 1100 : true)); 1101 1102 const bool consider_callable 1103 = (!strub_flag_disabled 1104 && (strub_attr 1105 ? req_mode == STRUB_CALLABLE 1106 : (!strub_flag_strict 1107 || strub_callable_builtin_p (node)))); 1108 1109 /* This is a shorthand for either strub-enabled mode. */ 1110 const bool consider_strub 1111 = (consider_at_calls || consider_internal); 1112 1113 /* We can cope with always_inline functions even with noipa and noclone, 1114 because we just leave them alone. */ 1115 const bool is_always_inline 1116 = strub_always_inline_p (node); 1117 1118 /* Strubbing in general, and each specific strub mode, may have its own set of 1119 requirements. We require noipa for strubbing, either because of cloning 1120 required for internal strub, or because of caller enumeration required for 1121 at-calls strub. We don't consider the at-calls mode eligible if it's not 1122 even considered, it has no further requirements. Internal mode requires 1123 cloning and the absence of certain features in the body and, like at-calls, 1124 it's not eligible if it's not even under consideration. 1125 1126 ??? Do we need target hooks for further constraints? E.g., x86's 1127 "interrupt" attribute breaks internal strubbing because the wrapped clone 1128 carries the attribute and thus isn't callable; in this case, we could use a 1129 target hook to adjust the clone instead. */ 1130 const bool strub_eligible 1131 = (consider_strub 1132 && (is_always_inline || can_strub_p (node))); 1133 const bool at_calls_eligible 1134 = (consider_at_calls && strub_eligible 1135 && can_strub_at_calls_p (node)); 1136 const bool internal_eligible 1137 = (consider_internal && strub_eligible 1138 && (is_always_inline 1139 || can_strub_internally_p (node))); 1140 1141 /* In addition to the strict eligibility requirements, some additional 1142 constraints are placed on implicit selection of certain modes. These do 1143 not prevent the selection of a mode if explicitly specified as part of a 1144 function interface (the strub attribute), but they may prevent modes from 1145 being selected by the command line or by function bodies. The only actual 1146 constraint is on at-calls mode: since we change the function's exposed 1147 signature, we won't do it implicitly if the function can possibly be used 1148 in ways that do not expect the signature change, e.g., if the function is 1149 available to or interposable by other units, if its address is taken, 1150 etc. */ 1151 const bool at_calls_viable 1152 = (at_calls_eligible 1153 && (strub_attr 1154 || (node->has_gimple_body_p () 1155 && (!node->externally_visible 1156 || (node->binds_to_current_def_p () 1157 && node->can_be_local_p ())) 1158 && node->only_called_directly_p () 1159 && !called_with_type_override_p (node)))); 1160 const bool internal_viable 1161 = (internal_eligible); 1162 1163 /* Shorthand. */ 1164 const bool strub_viable 1165 = (at_calls_viable || internal_viable); 1166 1167 /* We wish to analyze the body, to look for implicit requests for strub, both 1168 to implicitly enable it when the body calls for it, and to report errors if 1169 the body calls for it but neither mode is viable (even if that follows from 1170 non-eligibility because of the explicit specification of some non-strubbing 1171 mode). We can refrain from scanning the body only in rare circumstances: 1172 when strub is enabled by a function attribute (scanning might be redundant 1173 in telling us to also enable it), and when we are enabling strub implicitly 1174 but there are non-viable modes: we want to know whether strubbing is 1175 required, to fallback to another mode, even if we're only enabling a 1176 certain mode, or, when either mode would do, to report an error if neither 1177 happens to be viable. */ 1178 const bool analyze_body 1179 = (strub_attr 1180 ? !consider_strub 1181 : (strub_flag_auto 1182 || (strub_flag_viable && (!at_calls_viable && !internal_viable)) 1183 || (strub_flag_either && !strub_viable))); 1184 1185 /* Cases in which strubbing is enabled or disabled by strub_flag_auto. 1186 Unsatisfiable requests ought to be reported. */ 1187 const bool strub_required 1188 = ((strub_attr && consider_strub) 1189 || (analyze_body && strub_from_body_p (node))); 1190 1191 /* Besides the required cases, we want to abide by the requests to enabling on 1192 an if-viable basis. */ 1193 const bool strub_enable 1194 = (strub_required 1195 || (strub_flag_at_calls && at_calls_viable) 1196 || (strub_flag_internal && internal_viable) 1197 || (strub_flag_either && strub_viable)); 1198 1199 /* And now we're finally ready to select a mode that abides by the viability 1200 and eligibility constraints, and that satisfies the strubbing requirements 1201 and requests, subject to the constraints. If both modes are viable and 1202 strub is to be enabled, pick STRUB_AT_CALLS unless STRUB_INTERNAL was named 1203 as preferred. */ 1204 const enum strub_mode mode 1205 = ((strub_enable && is_always_inline) 1206 ? (strub_required ? STRUB_INLINABLE : STRUB_CALLABLE) 1207 : (strub_enable && internal_viable 1208 && (strub_flag_internal || !at_calls_viable)) 1209 ? STRUB_INTERNAL 1210 : (strub_enable && at_calls_viable) 1211 ? (strub_required && !strub_attr 1212 ? STRUB_AT_CALLS_OPT 1213 : STRUB_AT_CALLS) 1214 : consider_callable 1215 ? STRUB_CALLABLE 1216 : STRUB_DISABLED); 1217 1218 switch (mode) 1219 { 1220 case STRUB_CALLABLE: 1221 if (is_always_inline) 1222 break; 1223 /* Fall through. */ 1224 1225 case STRUB_DISABLED: 1226 if (strub_enable && !strub_attr) 1227 { 1228 gcc_checking_assert (analyze_body); 1229 error_at (DECL_SOURCE_LOCATION (node->decl), 1230 "%qD requires %<strub%>," 1231 " but no viable %<strub%> mode was found", 1232 node->decl); 1233 break; 1234 } 1235 /* Fall through. */ 1236 1237 case STRUB_AT_CALLS: 1238 case STRUB_INTERNAL: 1239 case STRUB_INLINABLE: 1240 /* Differences from an mode requested through a function attribute are 1241 reported in set_strub_mode_to. */ 1242 break; 1243 1244 case STRUB_AT_CALLS_OPT: 1245 /* Functions that select this mode do so because of references to strub 1246 variables. Even if we choose at-calls as an optimization, the 1247 requirements for internal strub must still be satisfied. Optimization 1248 options may render implicit at-calls strub not viable (-O0 sets 1249 force_output for static non-inline functions), and it would not be good 1250 if changing optimization options turned a well-formed into an 1251 ill-formed one. */ 1252 if (!internal_viable) 1253 can_strub_internally_p (node, true); 1254 break; 1255 1256 case STRUB_WRAPPED: 1257 case STRUB_WRAPPER: 1258 default: 1259 gcc_unreachable (); 1260 } 1261 1262 return mode; 1263 } 1264 1265 /* Set FNDT's strub mode to MODE; FNDT may be a function decl or 1266 function type. If OVERRIDE, do not check whether a mode is already 1267 set. */ 1268 1269 static void 1270 strub_set_fndt_mode_to (tree fndt, enum strub_mode mode, bool override) 1271 { 1272 gcc_checking_assert (override 1273 || !(DECL_P (fndt) 1274 ? get_strub_attr_from_decl (fndt) 1275 : get_strub_attr_from_type (fndt))); 1276 1277 tree attr = tree_cons (get_identifier ("strub"), 1278 get_strub_mode_attr_value (mode), 1279 NULL_TREE); 1280 tree *attrp = NULL; 1281 if (DECL_P (fndt)) 1282 { 1283 gcc_checking_assert (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (fndt))); 1284 attrp = &DECL_ATTRIBUTES (fndt); 1285 } 1286 else if (FUNC_OR_METHOD_TYPE_P (fndt)) 1287 attrp = &TYPE_ATTRIBUTES (fndt); 1288 else 1289 gcc_unreachable (); 1290 1291 TREE_CHAIN (attr) = *attrp; 1292 *attrp = attr; 1293 } 1294 1295 /* Set FNDT's strub mode to callable. 1296 FNDT may be a function decl or a function type. */ 1297 1298 void 1299 strub_make_callable (tree fndt) 1300 { 1301 strub_set_fndt_mode_to (fndt, STRUB_CALLABLE, false); 1302 } 1303 1304 /* Set NODE to strub MODE. Report incompatibilities between MODE and the mode 1305 requested through explicit attributes, and cases of non-eligibility. */ 1306 1307 static void 1308 set_strub_mode_to (cgraph_node *node, enum strub_mode mode) 1309 { 1310 tree attr = get_strub_attr_from_decl (node->decl); 1311 enum strub_mode req_mode = get_strub_mode_from_attr (attr); 1312 1313 if (attr) 1314 { 1315 /* Check for and report incompatible mode changes. */ 1316 if (mode != req_mode 1317 && !(req_mode == STRUB_INTERNAL 1318 && (mode == STRUB_WRAPPED 1319 || mode == STRUB_WRAPPER)) 1320 && !((req_mode == STRUB_INTERNAL 1321 || req_mode == STRUB_AT_CALLS 1322 || req_mode == STRUB_CALLABLE) 1323 && mode == STRUB_INLINABLE)) 1324 { 1325 error_at (DECL_SOURCE_LOCATION (node->decl), 1326 "%<strub%> mode %qE selected for %qD, when %qE was requested", 1327 get_strub_mode_attr_parm (mode), 1328 node->decl, 1329 get_strub_mode_attr_parm (req_mode)); 1330 if (node->alias) 1331 { 1332 cgraph_node *target = node->ultimate_alias_target (); 1333 if (target != node) 1334 error_at (DECL_SOURCE_LOCATION (target->decl), 1335 "the incompatible selection was determined" 1336 " by ultimate alias target %qD", 1337 target->decl); 1338 } 1339 1340 /* Report any incompatibilities with explicitly-requested strub. */ 1341 switch (req_mode) 1342 { 1343 case STRUB_AT_CALLS: 1344 can_strub_at_calls_p (node, true); 1345 break; 1346 1347 case STRUB_INTERNAL: 1348 can_strub_internally_p (node, true); 1349 break; 1350 1351 default: 1352 break; 1353 } 1354 } 1355 1356 /* Drop any incompatible strub attributes leading the decl attribute 1357 chain. Return if we find one with the mode we need. */ 1358 for (;;) 1359 { 1360 if (mode == req_mode) 1361 return; 1362 1363 if (DECL_ATTRIBUTES (node->decl) != attr) 1364 break; 1365 1366 DECL_ATTRIBUTES (node->decl) = TREE_CHAIN (attr); 1367 attr = get_strub_attr_from_decl (node->decl); 1368 if (!attr) 1369 break; 1370 1371 req_mode = get_strub_mode_from_attr (attr); 1372 } 1373 } 1374 else if (mode == req_mode) 1375 return; 1376 1377 strub_set_fndt_mode_to (node->decl, mode, attr); 1378 } 1379 1380 /* Compute and set NODE's strub mode. */ 1381 1382 static void 1383 set_strub_mode (cgraph_node *node) 1384 { 1385 tree attr = get_strub_attr_from_decl (node->decl); 1386 1387 if (attr) 1388 switch (get_strub_mode_from_attr (attr)) 1389 { 1390 /* These can't have been requested through user attributes, so we must 1391 have already gone through them. */ 1392 case STRUB_WRAPPER: 1393 case STRUB_WRAPPED: 1394 case STRUB_INLINABLE: 1395 case STRUB_AT_CALLS_OPT: 1396 return; 1397 1398 case STRUB_DISABLED: 1399 case STRUB_AT_CALLS: 1400 case STRUB_INTERNAL: 1401 case STRUB_CALLABLE: 1402 break; 1403 1404 default: 1405 gcc_unreachable (); 1406 } 1407 1408 cgraph_node *xnode = node; 1409 if (node->alias) 1410 xnode = node->ultimate_alias_target (); 1411 /* Weakrefs may remain unresolved (the above will return node) if 1412 their targets are not defined, so make sure we compute a strub 1413 mode for them, instead of defaulting to STRUB_DISABLED and 1414 rendering them uncallable. */ 1415 enum strub_mode mode = (xnode != node && !xnode->alias 1416 ? get_strub_mode (xnode) 1417 : compute_strub_mode (node, attr)); 1418 1419 set_strub_mode_to (node, mode); 1420 } 1421 1422 1423 /* Non-strub functions shouldn't be called from within strub contexts, 1425 except through callable ones. Always inline strub functions can 1426 only be called from strub functions. */ 1427 1428 static bool 1429 strub_callable_from_p (strub_mode caller_mode, strub_mode callee_mode) 1430 { 1431 switch (caller_mode) 1432 { 1433 case STRUB_WRAPPED: 1434 case STRUB_AT_CALLS_OPT: 1435 case STRUB_AT_CALLS: 1436 case STRUB_INTERNAL: 1437 case STRUB_INLINABLE: 1438 break; 1439 1440 case STRUB_WRAPPER: 1441 case STRUB_DISABLED: 1442 case STRUB_CALLABLE: 1443 return callee_mode != STRUB_INLINABLE; 1444 1445 default: 1446 gcc_unreachable (); 1447 } 1448 1449 switch (callee_mode) 1450 { 1451 case STRUB_WRAPPED: 1452 case STRUB_AT_CALLS: 1453 case STRUB_INLINABLE: 1454 break; 1455 1456 case STRUB_AT_CALLS_OPT: 1457 case STRUB_INTERNAL: 1458 case STRUB_WRAPPER: 1459 return (flag_strub >= -1); 1460 1461 case STRUB_DISABLED: 1462 return false; 1463 1464 case STRUB_CALLABLE: 1465 break; 1466 1467 default: 1468 gcc_unreachable (); 1469 } 1470 1471 return true; 1472 } 1473 1474 /* Return TRUE iff CALLEE can be inlined into CALLER. We wish to avoid inlining 1475 WRAPPED functions back into their WRAPPERs. More generally, we wish to avoid 1476 inlining strubbed functions into non-strubbed ones. CALLER doesn't have to 1477 be an immediate caller of CALLEE: the immediate caller may have already been 1478 cloned for inlining, and then CALLER may be further up the original call 1479 chain. ??? It would be nice if our own caller would retry inlining callee 1480 if caller gets inlined. */ 1481 1482 bool 1483 strub_inlinable_to_p (cgraph_node *callee, cgraph_node *caller) 1484 { 1485 strub_mode callee_mode = get_strub_mode (callee); 1486 1487 switch (callee_mode) 1488 { 1489 case STRUB_WRAPPED: 1490 case STRUB_AT_CALLS: 1491 case STRUB_INTERNAL: 1492 case STRUB_INLINABLE: 1493 case STRUB_AT_CALLS_OPT: 1494 break; 1495 1496 case STRUB_WRAPPER: 1497 case STRUB_DISABLED: 1498 case STRUB_CALLABLE: 1499 /* When we consider inlining, we've already verified callability, so we 1500 can even inline callable and then disabled into a strub context. That 1501 will get strubbed along with the context, so it's hopefully not a 1502 problem. */ 1503 return true; 1504 1505 default: 1506 gcc_unreachable (); 1507 } 1508 1509 strub_mode caller_mode = get_strub_mode (caller); 1510 1511 switch (caller_mode) 1512 { 1513 case STRUB_WRAPPED: 1514 case STRUB_AT_CALLS: 1515 case STRUB_INTERNAL: 1516 case STRUB_INLINABLE: 1517 case STRUB_AT_CALLS_OPT: 1518 return true; 1519 1520 case STRUB_WRAPPER: 1521 case STRUB_DISABLED: 1522 case STRUB_CALLABLE: 1523 break; 1524 1525 default: 1526 gcc_unreachable (); 1527 } 1528 1529 return false; 1530 } 1531 1532 /* Check that types T1 and T2 are strub-compatible. Return 1 if the strub modes 1533 are the same, 2 if they are interchangeable, and 0 otherwise. */ 1534 1535 int 1536 strub_comptypes (tree t1, tree t2) 1537 { 1538 if (TREE_CODE (t1) != TREE_CODE (t2)) 1539 return 0; 1540 1541 enum strub_mode m1 = get_strub_mode_from_type (t1); 1542 enum strub_mode m2 = get_strub_mode_from_type (t2); 1543 1544 if (m1 == m2) 1545 return 1; 1546 1547 /* We're dealing with types, so only strub modes that can be selected by 1548 attributes in the front end matter. If either mode is at-calls (for 1549 functions) or internal (for variables), the conversion is not 1550 compatible. */ 1551 bool var_p = !FUNC_OR_METHOD_TYPE_P (t1); 1552 enum strub_mode mr = var_p ? STRUB_INTERNAL : STRUB_AT_CALLS; 1553 if (m1 == mr || m2 == mr) 1554 return 0; 1555 1556 return 2; 1557 } 1558 1559 /* Return the effective strub mode used for CALL, and set *TYPEP to 1560 the effective type used for the call. The effective type and mode 1561 are those of the callee, unless the call involves a typecast. */ 1562 1563 static enum strub_mode 1564 effective_strub_mode_for_call (gcall *call, tree *typep) 1565 { 1566 tree type; 1567 enum strub_mode mode; 1568 1569 if (strub_call_fntype_override_p (call)) 1570 { 1571 type = gimple_call_fntype (call); 1572 mode = get_strub_mode_from_type (type); 1573 } 1574 else 1575 { 1576 type = TREE_TYPE (TREE_TYPE (gimple_call_fn (call))); 1577 tree decl = gimple_call_fndecl (call); 1578 if (decl) 1579 mode = get_strub_mode_from_fndecl (decl); 1580 else 1581 mode = get_strub_mode_from_type (type); 1582 } 1583 1584 if (typep) 1585 *typep = type; 1586 1587 return mode; 1588 } 1589 1590 /* Create a distinct copy of the type of NODE's function, and change 1591 the fntype of all calls to it with the same main type to the new 1592 type. */ 1593 1594 static void 1595 distinctify_node_type (cgraph_node *node) 1596 { 1597 tree old_type = TREE_TYPE (node->decl); 1598 tree new_type = build_distinct_type_copy (old_type); 1599 tree new_ptr_type = NULL_TREE; 1600 1601 /* Remap any calls to node->decl that use old_type, or a variant 1602 thereof, to new_type as well. We don't look for aliases, their 1603 declarations will have their types changed independently, and 1604 we'll adjust their fntypes then. */ 1605 for (cgraph_edge *e = node->callers; e; e = e->next_caller) 1606 { 1607 if (!e->call_stmt) 1608 continue; 1609 tree fnaddr = gimple_call_fn (e->call_stmt); 1610 gcc_checking_assert (TREE_CODE (fnaddr) == ADDR_EXPR 1611 && TREE_OPERAND (fnaddr, 0) == node->decl); 1612 if (strub_call_fntype_override_p (e->call_stmt)) 1613 continue; 1614 if (!new_ptr_type) 1615 new_ptr_type = build_pointer_type (new_type); 1616 TREE_TYPE (fnaddr) = new_ptr_type; 1617 gimple_call_set_fntype (e->call_stmt, new_type); 1618 } 1619 1620 TREE_TYPE (node->decl) = new_type; 1621 } 1622 1623 /* Return TRUE iff TYPE and any variants have the same strub mode. */ 1624 1625 static bool 1626 same_strub_mode_in_variants_p (tree type) 1627 { 1628 enum strub_mode mode = get_strub_mode_from_type (type); 1629 1630 for (tree other = TYPE_MAIN_VARIANT (type); 1631 other != NULL_TREE; other = TYPE_NEXT_VARIANT (other)) 1632 if (type != other && mode != get_strub_mode_from_type (other)) 1633 return false; 1634 1635 /* Check that the canonical type, if set, either is in the same 1636 variant chain, or has the same strub mode as type. Also check 1637 the variants of the canonical type. */ 1638 if (TYPE_CANONICAL (type) 1639 && (TYPE_MAIN_VARIANT (TYPE_CANONICAL (type)) 1640 != TYPE_MAIN_VARIANT (type))) 1641 { 1642 if (mode != get_strub_mode_from_type (TYPE_CANONICAL (type))) 1643 return false; 1644 else 1645 return same_strub_mode_in_variants_p (TYPE_CANONICAL (type)); 1646 } 1647 1648 return true; 1649 } 1650 1651 /* Check that strub functions don't call non-strub functions, and that 1652 always_inline strub functions are only called by strub 1653 functions. */ 1654 1655 static void 1656 verify_strub () 1657 { 1658 cgraph_node *node; 1659 1660 /* It's expected that check strub-wise pointer type compatibility of variables 1661 and of functions is already taken care of by front-ends, on account of the 1662 attribute's being marked as affecting type identity and of the creation of 1663 distinct types. */ 1664 1665 /* Check that call targets in strub contexts have strub-callable types. */ 1666 1667 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) 1668 { 1669 enum strub_mode caller_mode = get_strub_mode (node); 1670 1671 for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee) 1672 { 1673 gcc_checking_assert (e->indirect_unknown_callee); 1674 1675 if (!e->call_stmt) 1676 continue; 1677 1678 enum strub_mode callee_mode 1679 = effective_strub_mode_for_call (e->call_stmt, NULL); 1680 1681 if (!strub_callable_from_p (caller_mode, callee_mode)) 1682 error_at (gimple_location (e->call_stmt), 1683 "indirect non-%<strub%> call in %<strub%> context %qD", 1684 node->decl); 1685 } 1686 1687 for (cgraph_edge *e = node->callees; e; e = e->next_callee) 1688 { 1689 gcc_checking_assert (!e->indirect_unknown_callee); 1690 1691 if (!e->call_stmt) 1692 continue; 1693 1694 tree callee_fntype; 1695 enum strub_mode callee_mode 1696 = effective_strub_mode_for_call (e->call_stmt, &callee_fntype); 1697 1698 if (!strub_callable_from_p (caller_mode, callee_mode)) 1699 { 1700 if (callee_mode == STRUB_INLINABLE) 1701 error_at (gimple_location (e->call_stmt), 1702 "calling %<always_inline%> %<strub%> %qD" 1703 " in non-%<strub%> context %qD", 1704 e->callee->decl, node->decl); 1705 else if (fndecl_built_in_p (e->callee->decl, BUILT_IN_APPLY_ARGS) 1706 && caller_mode == STRUB_INTERNAL) 1707 /* This is ok, it will be kept in the STRUB_WRAPPER, and removed 1708 from the STRUB_WRAPPED's strub context. */ 1709 continue; 1710 else if (!strub_call_fntype_override_p (e->call_stmt)) 1711 error_at (gimple_location (e->call_stmt), 1712 "calling non-%<strub%> %qD in %<strub%> context %qD", 1713 e->callee->decl, node->decl); 1714 else 1715 error_at (gimple_location (e->call_stmt), 1716 "calling %qD using non-%<strub%> type %qT" 1717 " in %<strub%> context %qD", 1718 e->callee->decl, callee_fntype, node->decl); 1719 } 1720 } 1721 } 1722 } 1723 1724 namespace { 1725 1726 /* Define a pass to compute strub modes. */ 1727 const pass_data pass_data_ipa_strub_mode = { 1728 SIMPLE_IPA_PASS, 1729 "strubm", 1730 OPTGROUP_NONE, 1731 TV_NONE, 1732 PROP_cfg, // properties_required 1733 0, // properties_provided 1734 0, // properties_destroyed 1735 0, // properties_start 1736 0, // properties_finish 1737 }; 1738 1739 class pass_ipa_strub_mode : public simple_ipa_opt_pass 1740 { 1741 public: 1742 pass_ipa_strub_mode (gcc::context *ctxt) 1743 : simple_ipa_opt_pass (pass_data_ipa_strub_mode, ctxt) 1744 {} 1745 opt_pass *clone () { return new pass_ipa_strub_mode (m_ctxt); } 1746 virtual bool gate (function *) { 1747 /* In relaxed (-3) and strict (-4) settings, that only enable strub at a 1748 function or variable attribute's request, the attribute handler changes 1749 flag_strub to -1 or -2, respectively, if any strub-enabling occurence of 1750 the attribute is found. Therefore, if it remains at -3 or -4, nothing 1751 that would enable strub was found, so we can disable it and avoid the 1752 overhead. */ 1753 if (flag_strub < -2) 1754 flag_strub = 0; 1755 return flag_strub; 1756 } 1757 virtual unsigned int execute (function *); 1758 }; 1759 1760 /* Define a pass to introduce strub transformations. */ 1761 const pass_data pass_data_ipa_strub = { 1762 SIMPLE_IPA_PASS, 1763 "strub", 1764 OPTGROUP_NONE, 1765 TV_NONE, 1766 PROP_cfg | PROP_ssa, // properties_required 1767 0, // properties_provided 1768 0, // properties_destroyed 1769 0, // properties_start 1770 TODO_update_ssa 1771 | TODO_cleanup_cfg 1772 | TODO_rebuild_cgraph_edges 1773 | TODO_verify_il, // properties_finish 1774 }; 1775 1776 class pass_ipa_strub : public simple_ipa_opt_pass 1777 { 1778 public: 1779 pass_ipa_strub (gcc::context *ctxt) 1780 : simple_ipa_opt_pass (pass_data_ipa_strub, ctxt) 1781 {} 1782 opt_pass *clone () { return new pass_ipa_strub (m_ctxt); } 1783 virtual bool gate (function *) { return flag_strub && !seen_error (); } 1784 virtual unsigned int execute (function *); 1785 1786 /* Define on demand and cache some types we use often. */ 1787 #define DEF_TYPE(IDX, NAME, INIT) \ 1788 static inline tree get_ ## NAME () { \ 1789 int idx = STRUB_TYPE_BASE + IDX; \ 1790 static tree type = strub_cache[idx]; \ 1791 if (!type) \ 1792 strub_cache[idx] = type = (INIT); \ 1793 return type; \ 1794 } 1795 1796 /* Use a distinct ptr_type_node to denote the watermark, so that we can 1797 recognize it in arg lists and avoid modifying types twice. */ 1798 DEF_TYPE (0, wmt, build_variant_type_copy (ptr_type_node)) 1799 1800 DEF_TYPE (1, pwmt, build_reference_type (get_wmt ())) 1801 1802 DEF_TYPE (2, qpwmt, 1803 build_qualified_type (get_pwmt (), 1804 TYPE_QUAL_RESTRICT 1805 /* | TYPE_QUAL_CONST */)) 1806 1807 DEF_TYPE (3, qptr, 1808 build_qualified_type (ptr_type_node, 1809 TYPE_QUAL_RESTRICT 1810 | TYPE_QUAL_CONST)) 1811 1812 DEF_TYPE (4, qpvalst, 1813 build_qualified_type (build_reference_type 1814 (va_list_type_node), 1815 TYPE_QUAL_RESTRICT 1816 /* | TYPE_QUAL_CONST */)) 1817 1818 #undef DEF_TYPE 1819 1820 /* Define non-strub builtins on demand. */ 1821 #define DEF_NM_BUILTIN(NAME, CODE, FNTYPELIST) \ 1822 static tree get_ ## NAME () { \ 1823 tree decl = builtin_decl_explicit (CODE); \ 1824 if (!decl) \ 1825 { \ 1826 tree type = build_function_type_list FNTYPELIST; \ 1827 decl = add_builtin_function \ 1828 ("__builtin_" #NAME, \ 1829 type, CODE, BUILT_IN_NORMAL, \ 1830 NULL, NULL); \ 1831 TREE_NOTHROW (decl) = true; \ 1832 set_builtin_decl ((CODE), decl, true); \ 1833 } \ 1834 return decl; \ 1835 } 1836 1837 DEF_NM_BUILTIN (stack_address, 1838 BUILT_IN_STACK_ADDRESS, 1839 (ptr_type_node, NULL)) 1840 1841 #undef DEF_NM_BUILTIN 1842 1843 /* Define strub builtins on demand. */ 1844 #define DEF_SS_BUILTIN(NAME, FNSPEC, CODE, FNTYPELIST) \ 1845 static tree get_ ## NAME () { \ 1846 tree decl = builtin_decl_explicit (CODE); \ 1847 if (!decl) \ 1848 { \ 1849 tree type = build_function_type_list FNTYPELIST; \ 1850 tree attrs = NULL; \ 1851 if (FNSPEC) \ 1852 attrs = tree_cons (get_identifier ("fn spec"), \ 1853 build_tree_list \ 1854 (NULL_TREE, \ 1855 build_string (strlen (FNSPEC), \ 1856 (FNSPEC))), \ 1857 attrs); \ 1858 decl = add_builtin_function_ext_scope \ 1859 ("__builtin___strub_" #NAME, \ 1860 type, CODE, BUILT_IN_NORMAL, \ 1861 "__strub_" #NAME, attrs); \ 1862 TREE_NOTHROW (decl) = true; \ 1863 set_builtin_decl ((CODE), decl, true); \ 1864 } \ 1865 return decl; \ 1866 } 1867 1868 DEF_SS_BUILTIN (enter, ". Ot", 1869 BUILT_IN___STRUB_ENTER, 1870 (void_type_node, get_qpwmt (), NULL)) 1871 DEF_SS_BUILTIN (update, ". Wt", 1872 BUILT_IN___STRUB_UPDATE, 1873 (void_type_node, get_qpwmt (), NULL)) 1874 DEF_SS_BUILTIN (leave, ". w ", 1875 BUILT_IN___STRUB_LEAVE, 1876 (void_type_node, get_qpwmt (), NULL)) 1877 1878 #undef DEF_SS_BUILTIN 1879 1880 /* Define strub identifiers on demand. */ 1881 #define DEF_IDENT(IDX, NAME) \ 1882 static inline tree get_ ## NAME () { \ 1883 int idx = STRUB_IDENT_BASE + IDX; \ 1884 tree identifier = strub_cache[idx]; \ 1885 if (!identifier) \ 1886 strub_cache[idx] = identifier = get_identifier (".strub." #NAME); \ 1887 return identifier; \ 1888 } 1889 1890 DEF_IDENT (0, watermark_ptr) 1891 DEF_IDENT (1, va_list_ptr) 1892 DEF_IDENT (2, apply_args) 1893 1894 #undef DEF_IDENT 1895 1896 static inline int adjust_at_calls_type (tree); 1897 static inline void adjust_at_calls_call (cgraph_edge *, int, tree); 1898 static inline void adjust_at_calls_calls (cgraph_node *); 1899 1900 /* Add to SEQ a call to the strub watermark update builtin, taking NODE's 1901 location if given. Optionally add the corresponding edge from NODE, with 1902 execution frequency COUNT. Return the modified SEQ. */ 1903 1904 static inline gimple_seq 1905 call_update_watermark (tree wmptr, cgraph_node *node, profile_count count, 1906 gimple_seq seq = NULL) 1907 { 1908 tree uwm = get_update (); 1909 gcall *update = gimple_build_call (uwm, 1, wmptr); 1910 if (node) 1911 gimple_set_location (update, DECL_SOURCE_LOCATION (node->decl)); 1912 gimple_seq_add_stmt (&seq, update); 1913 if (node) 1914 node->create_edge (cgraph_node::get_create (uwm), update, count, false); 1915 return seq; 1916 } 1917 1918 }; 1919 1920 } // anon namespace 1921 1922 /* Gather with this type a collection of parameters that we're turning into 1923 explicit references. */ 1924 1925 typedef hash_set<tree> indirect_parms_t; 1926 1927 /* Dereference OP's incoming turned-into-reference parm if it's an 1928 INDIRECT_PARMS or an ADDR_EXPR thereof. Set *REC and return according to 1929 gimple-walking expectations. */ 1930 1931 static tree 1932 maybe_make_indirect (indirect_parms_t &indirect_parms, tree op, int *rec) 1933 { 1934 if (DECL_P (op)) 1935 { 1936 *rec = 0; 1937 if (indirect_parms.contains (op)) 1938 { 1939 tree ret = gimple_fold_indirect_ref (op); 1940 if (!ret) 1941 ret = build2 (MEM_REF, 1942 TREE_TYPE (TREE_TYPE (op)), 1943 op, 1944 build_int_cst (TREE_TYPE (op), 0)); 1945 if (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (op))) 1946 && !TREE_THIS_VOLATILE (ret)) 1947 TREE_SIDE_EFFECTS (ret) = TREE_THIS_VOLATILE (ret) = 1; 1948 return ret; 1949 } 1950 } 1951 else if (TREE_CODE (op) == ADDR_EXPR 1952 && DECL_P (TREE_OPERAND (op, 0))) 1953 { 1954 *rec = 0; 1955 if (indirect_parms.contains (TREE_OPERAND (op, 0))) 1956 { 1957 op = TREE_OPERAND (op, 0); 1958 return op; 1959 } 1960 } 1961 1962 return NULL_TREE; 1963 } 1964 1965 /* A gimple-walking function that adds dereferencing to indirect parms. */ 1966 1967 static tree 1968 walk_make_indirect (tree *op, int *rec, void *arg) 1969 { 1970 walk_stmt_info *wi = (walk_stmt_info *)arg; 1971 indirect_parms_t &indirect_parms = *(indirect_parms_t *)wi->info; 1972 1973 if (!*op || TYPE_P (*op)) 1974 { 1975 *rec = 0; 1976 return NULL_TREE; 1977 } 1978 1979 if (tree repl = maybe_make_indirect (indirect_parms, *op, rec)) 1980 { 1981 *op = repl; 1982 wi->changed = true; 1983 } 1984 1985 return NULL_TREE; 1986 } 1987 1988 /* A gimple-walking function that turns any non-gimple-val ADDR_EXPRs into a 1989 separate SSA. Though addresses of e.g. parameters, and of members thereof, 1990 are gimple vals, turning parameters into references, with an extra layer of 1991 indirection and thus explicit dereferencing, need to be regimplified. */ 1992 1993 static tree 1994 walk_regimplify_addr_expr (tree *op, int *rec, void *arg) 1995 { 1996 walk_stmt_info *wi = (walk_stmt_info *)arg; 1997 gimple_stmt_iterator &gsi = *(gimple_stmt_iterator *)wi->info; 1998 1999 *rec = 0; 2000 2001 if (!*op || TREE_CODE (*op) != ADDR_EXPR) 2002 return NULL_TREE; 2003 2004 if (!is_gimple_val (*op)) 2005 { 2006 tree ret = force_gimple_operand_gsi (&gsi, *op, true, 2007 NULL_TREE, true, GSI_SAME_STMT); 2008 gcc_assert (ret != *op); 2009 *op = ret; 2010 wi->changed = true; 2011 } 2012 2013 return NULL_TREE; 2014 } 2015 2016 /* Turn STMT's PHI arg defs into separate SSA defs if they've become 2017 non-gimple_val. Return TRUE if any edge insertions need to be committed. */ 2018 2019 static bool 2020 walk_regimplify_phi (gphi *stmt) 2021 { 2022 bool needs_commit = false; 2023 2024 for (unsigned i = 0, n = gimple_phi_num_args (stmt); i < n; i++) 2025 { 2026 tree op = gimple_phi_arg_def (stmt, i); 2027 if ((TREE_CODE (op) == ADDR_EXPR 2028 && !is_gimple_val (op)) 2029 /* ??? A PARM_DECL that was addressable in the original function and 2030 had its address in PHI nodes, but that became a reference in the 2031 wrapped clone would NOT be updated by update_ssa in PHI nodes. 2032 Alas, if we were to create a default def for it now, update_ssa 2033 would complain that the symbol that needed rewriting already has 2034 SSA names associated with it. OTOH, leaving the PARM_DECL alone, 2035 it eventually causes errors because it remains unchanged in PHI 2036 nodes, but it gets rewritten as expected if it appears in other 2037 stmts. So we cheat a little here, and force the PARM_DECL out of 2038 the PHI node and into an assignment. It's a little expensive, 2039 because we insert it at the edge, which introduces a basic block 2040 that's entirely unnecessary, but it works, and the block will be 2041 removed as the default def gets propagated back into the PHI node, 2042 so the final optimized code looks just as expected. */ 2043 || (TREE_CODE (op) == PARM_DECL 2044 && !TREE_ADDRESSABLE (op))) 2045 { 2046 tree temp = make_ssa_name (TREE_TYPE (op), stmt); 2047 if (TREE_CODE (op) == PARM_DECL) 2048 SET_SSA_NAME_VAR_OR_IDENTIFIER (temp, DECL_NAME (op)); 2049 SET_PHI_ARG_DEF (stmt, i, temp); 2050 2051 gimple *assign = gimple_build_assign (temp, op); 2052 if (gimple_phi_arg_has_location (stmt, i)) 2053 gimple_set_location (assign, gimple_phi_arg_location (stmt, i)); 2054 gsi_insert_on_edge (gimple_phi_arg_edge (stmt, i), assign); 2055 needs_commit = true; 2056 } 2057 } 2058 2059 return needs_commit; 2060 } 2061 2062 /* Create a reference type to use for PARM when turning it into a 2063 reference. */ 2064 2065 static tree 2066 build_ref_type_for (tree parm) 2067 { 2068 gcc_checking_assert (TREE_CODE (parm) == PARM_DECL); 2069 2070 tree ref_type = build_reference_type (TREE_TYPE (parm)); 2071 2072 return ref_type; 2073 } 2074 2075 /* Add cgraph edges from current_function_decl to callees in SEQ with frequency 2076 COUNT, assuming all calls in SEQ are direct. */ 2077 2078 static void 2079 add_call_edges_for_seq (gimple_seq seq, profile_count count) 2080 { 2081 cgraph_node *node = cgraph_node::get_create (current_function_decl); 2082 2083 for (gimple_stmt_iterator gsi = gsi_start (seq); 2084 !gsi_end_p (gsi); gsi_next (&gsi)) 2085 { 2086 gimple *stmt = gsi_stmt (gsi); 2087 2088 gcall *call = dyn_cast <gcall *> (stmt); 2089 if (!call) 2090 continue; 2091 2092 tree callee = gimple_call_fndecl (call); 2093 gcc_checking_assert (callee); 2094 node->create_edge (cgraph_node::get_create (callee), call, count, false); 2095 } 2096 } 2097 2098 /* Insert SEQ after the call at GSI, as if the call was in a try block with SEQ 2099 as finally, i.e., SEQ will run after the call whether it returns or 2100 propagates an exception. This handles block splitting, EH edge and block 2101 creation, noreturn and nothrow optimizations, and even throwing calls without 2102 preexisting local handlers. */ 2103 2104 static void 2105 gsi_insert_finally_seq_after_call (gimple_stmt_iterator gsi, gimple_seq seq) 2106 { 2107 if (!seq) 2108 return; 2109 2110 gimple *stmt = gsi_stmt (gsi); 2111 2112 if (gimple_has_location (stmt)) 2113 annotate_all_with_location (seq, gimple_location (stmt)); 2114 2115 gcall *call = dyn_cast <gcall *> (stmt); 2116 bool noreturn_p = call && gimple_call_noreturn_p (call); 2117 int eh_lp = lookup_stmt_eh_lp (stmt); 2118 bool must_not_throw_p = eh_lp < 0; 2119 bool nothrow_p = (must_not_throw_p 2120 || (call && gimple_call_nothrow_p (call)) 2121 || (eh_lp <= 0 2122 && (TREE_NOTHROW (cfun->decl) 2123 || !opt_for_fn (cfun->decl, flag_exceptions)))); 2124 2125 if (noreturn_p && nothrow_p) 2126 return; 2127 2128 /* Don't expect an EH edge if we're not to throw, or if we're not in an EH 2129 region yet. */ 2130 bool no_eh_edge_p = (nothrow_p || !eh_lp); 2131 bool must_end_bb = stmt_ends_bb_p (stmt); 2132 2133 edge eft = NULL, eeh = NULL; 2134 if (must_end_bb && !(noreturn_p && no_eh_edge_p)) 2135 { 2136 gcc_checking_assert (gsi_one_before_end_p (gsi)); 2137 2138 edge e; 2139 edge_iterator ei; 2140 FOR_EACH_EDGE (e, ei, gsi_bb (gsi)->succs) 2141 { 2142 if ((e->flags & EDGE_EH)) 2143 { 2144 gcc_checking_assert (!eeh); 2145 eeh = e; 2146 #if !CHECKING_P 2147 if (eft || noreturn_p) 2148 break; 2149 #endif 2150 } 2151 if ((e->flags & EDGE_FALLTHRU)) 2152 { 2153 gcc_checking_assert (!eft); 2154 eft = e; 2155 #if !CHECKING_P 2156 if (eeh || no_eh_edge_p) 2157 break; 2158 #endif 2159 } 2160 } 2161 2162 gcc_checking_assert (!(eft && (eft->flags & EDGE_FALLTHRU)) 2163 == noreturn_p); 2164 gcc_checking_assert (!(eeh && (eeh->flags & EDGE_EH)) 2165 == no_eh_edge_p); 2166 gcc_checking_assert (eft != eeh); 2167 } 2168 2169 if (!noreturn_p) 2170 { 2171 gimple_seq nseq = nothrow_p ? seq : gimple_seq_copy (seq); 2172 2173 if (must_end_bb) 2174 { 2175 gcc_checking_assert (gsi_one_before_end_p (gsi)); 2176 add_call_edges_for_seq (nseq, eft->count ()); 2177 gsi_insert_seq_on_edge_immediate (eft, nseq); 2178 } 2179 else 2180 { 2181 add_call_edges_for_seq (nseq, gsi_bb (gsi)->count); 2182 gsi_insert_seq_after (&gsi, nseq, GSI_SAME_STMT); 2183 } 2184 } 2185 2186 if (nothrow_p) 2187 return; 2188 2189 if (eh_lp) 2190 { 2191 add_call_edges_for_seq (seq, eeh->count ()); 2192 gsi_insert_seq_on_edge_immediate (eeh, seq); 2193 return; 2194 } 2195 2196 /* A throwing call may appear within a basic block in a function that doesn't 2197 have any EH regions. We're going to add a cleanup if so, therefore the 2198 block will have to be split. */ 2199 basic_block bb = gsi_bb (gsi); 2200 if (!gsi_one_before_end_p (gsi)) 2201 split_block (bb, stmt); 2202 2203 /* Create a new block for the EH cleanup. */ 2204 basic_block bb_eh_cleanup = create_empty_bb (bb); 2205 if (dom_info_available_p (CDI_DOMINATORS)) 2206 set_immediate_dominator (CDI_DOMINATORS, bb_eh_cleanup, bb); 2207 if (current_loops) 2208 add_bb_to_loop (bb_eh_cleanup, current_loops->tree_root); 2209 2210 /* Make the new block an EH cleanup for the call. */ 2211 eh_region new_r = gen_eh_region_cleanup (NULL); 2212 eh_landing_pad lp = gen_eh_landing_pad (new_r); 2213 tree label = gimple_block_label (bb_eh_cleanup); 2214 lp->post_landing_pad = label; 2215 EH_LANDING_PAD_NR (label) = lp->index; 2216 add_stmt_to_eh_lp (stmt, lp->index); 2217 2218 /* Add the cleanup code to the EH cleanup block. */ 2219 gsi = gsi_after_labels (bb_eh_cleanup); 2220 gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT); 2221 2222 /* And then propagate the exception further. */ 2223 gresx *resx = gimple_build_resx (new_r->index); 2224 if (gimple_has_location (stmt)) 2225 gimple_set_location (resx, gimple_location (stmt)); 2226 gsi_insert_before (&gsi, resx, GSI_SAME_STMT); 2227 2228 /* Finally, wire the EH cleanup block into the CFG. */ 2229 edge neeh = make_eh_edge (stmt); 2230 neeh->probability = profile_probability::never (); 2231 gcc_checking_assert (neeh->dest == bb_eh_cleanup); 2232 gcc_checking_assert (!neeh->dest->count.initialized_p ()); 2233 neeh->dest->count = neeh->count (); 2234 add_call_edges_for_seq (seq, neeh->dest->count); 2235 } 2236 2237 /* Copy the attribute list at *ATTRS, minus any NAME attributes, leaving 2238 shareable trailing nodes alone. */ 2239 2240 static inline void 2241 remove_named_attribute_unsharing (const char *name, tree *attrs) 2242 { 2243 while (tree found = lookup_attribute (name, *attrs)) 2244 { 2245 /* Copy nodes up to the next NAME attribute. */ 2246 while (*attrs != found) 2247 { 2248 *attrs = tree_cons (TREE_PURPOSE (*attrs), 2249 TREE_VALUE (*attrs), 2250 TREE_CHAIN (*attrs)); 2251 attrs = &TREE_CHAIN (*attrs); 2252 } 2253 /* Then drop it. */ 2254 gcc_checking_assert (*attrs == found); 2255 *attrs = TREE_CHAIN (*attrs); 2256 } 2257 } 2258 2259 /* Record the order of the last cgraph entry whose mode we've already set, so 2260 that we can perform mode setting incrementally without duplication. */ 2261 static int last_cgraph_order; 2262 2263 /* Set strub modes for functions introduced since the last call. */ 2264 2265 static void 2266 ipa_strub_set_mode_for_new_functions () 2267 { 2268 if (symtab->order == last_cgraph_order) 2269 return; 2270 2271 cgraph_node *node; 2272 2273 /* Go through the functions twice, once over non-aliases, and then over 2274 aliases, so that aliases can reuse the mode computation of their ultimate 2275 targets. */ 2276 for (int aliases = 0; aliases <= 1; aliases++) 2277 FOR_EACH_FUNCTION (node) 2278 { 2279 if (!node->alias != !aliases) 2280 continue; 2281 2282 /* Already done. */ 2283 if (node->order < last_cgraph_order) 2284 continue; 2285 2286 set_strub_mode (node); 2287 } 2288 2289 last_cgraph_order = symtab->order; 2290 } 2291 2292 /* Return FALSE if NODE is a strub context, and TRUE otherwise. */ 2293 2294 bool 2295 strub_splittable_p (cgraph_node *node) 2296 { 2297 switch (get_strub_mode (node)) 2298 { 2299 case STRUB_WRAPPED: 2300 case STRUB_AT_CALLS: 2301 case STRUB_AT_CALLS_OPT: 2302 case STRUB_INLINABLE: 2303 case STRUB_INTERNAL: 2304 case STRUB_WRAPPER: 2305 return false; 2306 2307 case STRUB_CALLABLE: 2308 case STRUB_DISABLED: 2309 break; 2310 2311 default: 2312 gcc_unreachable (); 2313 } 2314 2315 return true; 2316 } 2317 2318 /* Return the PARM_DECL of the incoming watermark pointer, if there is one. */ 2319 2320 tree 2321 strub_watermark_parm (tree fndecl) 2322 { 2323 switch (get_strub_mode_from_fndecl (fndecl)) 2324 { 2325 case STRUB_WRAPPED: 2326 case STRUB_AT_CALLS: 2327 case STRUB_AT_CALLS_OPT: 2328 break; 2329 2330 case STRUB_INTERNAL: 2331 case STRUB_WRAPPER: 2332 case STRUB_CALLABLE: 2333 case STRUB_DISABLED: 2334 case STRUB_INLINABLE: 2335 return NULL_TREE; 2336 2337 default: 2338 gcc_unreachable (); 2339 } 2340 2341 for (tree parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm)) 2342 /* The type (variant) compare finds the parameter even in a just-created 2343 clone, before we set its name, but the type-based compare doesn't work 2344 during builtin expansion within the lto compiler, because we'll have 2345 created a separate variant in that run. */ 2346 if (TREE_TYPE (parm) == pass_ipa_strub::get_qpwmt () 2347 || DECL_NAME (parm) == pass_ipa_strub::get_watermark_ptr ()) 2348 return parm; 2349 2350 gcc_unreachable (); 2351 } 2352 2353 /* Adjust a STRUB_AT_CALLS function TYPE, adding a watermark pointer if it 2354 hasn't been added yet. Return the named argument count. */ 2355 2356 int 2357 pass_ipa_strub::adjust_at_calls_type (tree type) 2358 { 2359 int named_args = 0; 2360 2361 gcc_checking_assert (same_strub_mode_in_variants_p (type)); 2362 2363 if (!TYPE_ARG_TYPES (type)) 2364 return named_args; 2365 2366 tree *tlist = &TYPE_ARG_TYPES (type); 2367 tree qpwmptrt = get_qpwmt (); 2368 while (*tlist && TREE_VALUE (*tlist) != void_type_node) 2369 { 2370 /* The type has already been adjusted. */ 2371 if (TREE_VALUE (*tlist) == qpwmptrt) 2372 return named_args; 2373 named_args++; 2374 *tlist = tree_cons (TREE_PURPOSE (*tlist), 2375 TREE_VALUE (*tlist), 2376 TREE_CHAIN (*tlist)); 2377 tlist = &TREE_CHAIN (*tlist); 2378 } 2379 2380 /* Add the new argument after all named arguments, so as to not mess with 2381 attributes that reference parameters. */ 2382 *tlist = tree_cons (NULL_TREE, get_qpwmt (), *tlist); 2383 2384 #if ATTR_FNSPEC_DECONST_WATERMARK 2385 if (!type_already_adjusted) 2386 { 2387 int flags = flags_from_decl_or_type (type); 2388 tree fnspec = lookup_attribute ("fn spec", type); 2389 2390 if ((flags & (ECF_CONST | ECF_PURE | ECF_NOVOPS)) || fnspec) 2391 { 2392 size_t xargs = 1; 2393 size_t curlen = 0, tgtlen = 2 + 2 * (named_args + xargs); 2394 auto_vec<char> nspecv (tgtlen); 2395 char *nspec = &nspecv[0]; /* It will *not* be NUL-terminated! */ 2396 if (fnspec) 2397 { 2398 tree fnspecstr = TREE_VALUE (TREE_VALUE (fnspec)); 2399 curlen = TREE_STRING_LENGTH (fnspecstr); 2400 memcpy (nspec, TREE_STRING_POINTER (fnspecstr), curlen); 2401 } 2402 if (!curlen) 2403 { 2404 nspec[curlen++] = '.'; 2405 nspec[curlen++] = ((flags & ECF_CONST) 2406 ? 'c' 2407 : (flags & ECF_PURE) 2408 ? 'p' 2409 : ' '); 2410 } 2411 while (curlen < tgtlen - 2 * xargs) 2412 { 2413 nspec[curlen++] = '.'; 2414 nspec[curlen++] = ' '; 2415 } 2416 nspec[curlen++] = 'W'; 2417 nspec[curlen++] = 't'; 2418 2419 /* The type has already been copied, if needed, before adding 2420 parameters. */ 2421 TYPE_ATTRIBUTES (type) 2422 = tree_cons (get_identifier ("fn spec"), 2423 build_tree_list (NULL_TREE, 2424 build_string (tgtlen, nspec)), 2425 TYPE_ATTRIBUTES (type)); 2426 } 2427 } 2428 #endif 2429 2430 return named_args; 2431 } 2432 2433 /* Adjust a call to an at-calls call target. Create a watermark local variable 2434 if needed, initialize it before, pass it to the callee according to the 2435 modified at-calls interface, and release the callee's stack space after the 2436 call, if not deferred. If the call is const or pure, arrange for the 2437 watermark to not be assumed unused or unchanged. */ 2438 2439 void 2440 pass_ipa_strub::adjust_at_calls_call (cgraph_edge *e, int named_args, 2441 tree callee_fntype) 2442 { 2443 gcc_checking_assert (e->call_stmt); 2444 gcall *ocall = e->call_stmt; 2445 gimple_stmt_iterator gsi = gsi_for_stmt (ocall); 2446 2447 /* Make sure we haven't modified this call yet. */ 2448 gcc_checking_assert (!(int (gimple_call_num_args (ocall)) > named_args 2449 && (TREE_TYPE (gimple_call_arg (ocall, named_args)) 2450 == get_pwmt ()))); 2451 2452 tree tsup; 2453 if (!(tsup = gimple_call_fndecl (ocall))) 2454 tsup = TREE_TYPE (TREE_TYPE (gimple_call_fn (ocall))); 2455 if (!strub_target_support_p (tsup, true, gimple_location (ocall))) 2456 return; 2457 2458 /* If we're already within a strub context, pass on the incoming watermark 2459 pointer, and omit the enter and leave calls around the modified call, as an 2460 optimization, or as a means to satisfy a tail-call requirement. */ 2461 tree swmp = ((opt_for_fn (e->caller->decl, optimize_size) 2462 || opt_for_fn (e->caller->decl, optimize) > 2 2463 || gimple_call_must_tail_p (ocall) 2464 || (opt_for_fn (e->caller->decl, optimize) == 2 2465 && gimple_call_tail_p (ocall))) 2466 ? strub_watermark_parm (e->caller->decl) 2467 : NULL_TREE); 2468 bool omit_own_watermark = swmp; 2469 tree swm = NULL_TREE; 2470 if (!omit_own_watermark) 2471 { 2472 swm = create_tmp_var (get_wmt (), ".strub.watermark"); 2473 TREE_ADDRESSABLE (swm) = true; 2474 swmp = build1 (ADDR_EXPR, get_pwmt (), swm); 2475 2476 /* Initialize the watermark before the call. */ 2477 tree enter = get_enter (); 2478 gcall *stptr = gimple_build_call (enter, 1, 2479 unshare_expr (swmp)); 2480 if (gimple_has_location (ocall)) 2481 gimple_set_location (stptr, gimple_location (ocall)); 2482 gsi_insert_before (&gsi, stptr, GSI_SAME_STMT); 2483 e->caller->create_edge (cgraph_node::get_create (enter), 2484 stptr, gsi_bb (gsi)->count, false); 2485 } 2486 2487 2488 /* Replace the call with one that passes the swmp argument first. */ 2489 gcall *wrcall; 2490 { gcall *stmt = ocall; 2491 // Mostly copied from gimple_call_copy_skip_args. 2492 int i = 0; 2493 int nargs = gimple_call_num_args (stmt); 2494 auto_vec<tree> vargs (MAX (nargs, named_args) + 1); 2495 gcall *new_stmt; 2496 2497 /* pr71109.c calls a prototypeless function, then defines it with 2498 additional arguments. It's ill-formed, but after it's inlined, 2499 it somehow works out. */ 2500 for (; i < named_args && i < nargs; i++) 2501 vargs.quick_push (gimple_call_arg (stmt, i)); 2502 for (; i < named_args; i++) 2503 vargs.quick_push (null_pointer_node); 2504 2505 vargs.quick_push (unshare_expr (swmp)); 2506 2507 for (; i < nargs; i++) 2508 vargs.quick_push (gimple_call_arg (stmt, i)); 2509 2510 if (gimple_call_internal_p (stmt)) 2511 gcc_unreachable (); 2512 else 2513 new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs); 2514 gimple_call_set_fntype (new_stmt, callee_fntype); 2515 2516 if (gimple_call_lhs (stmt)) 2517 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt)); 2518 2519 gimple_move_vops (new_stmt, stmt); 2520 2521 if (gimple_has_location (stmt)) 2522 gimple_set_location (new_stmt, gimple_location (stmt)); 2523 gimple_call_copy_flags (new_stmt, stmt); 2524 gimple_call_set_chain (new_stmt, gimple_call_chain (stmt)); 2525 2526 gimple_set_modified (new_stmt, true); 2527 2528 wrcall = new_stmt; 2529 } 2530 2531 update_stmt (wrcall); 2532 gsi_replace (&gsi, wrcall, true); 2533 cgraph_edge::set_call_stmt (e, wrcall, false); 2534 2535 /* Insert the strub code after the call. */ 2536 gimple_seq seq = NULL; 2537 2538 #if !ATTR_FNSPEC_DECONST_WATERMARK 2539 /* If the call will be assumed to not modify or even read the 2540 watermark, make it read and modified ourselves. */ 2541 if ((gimple_call_flags (wrcall) 2542 & (ECF_CONST | ECF_PURE | ECF_NOVOPS))) 2543 { 2544 if (!swm) 2545 swm = build2 (MEM_REF, 2546 TREE_TYPE (TREE_TYPE (swmp)), 2547 swmp, 2548 build_int_cst (TREE_TYPE (swmp), 0)); 2549 2550 vec<tree, va_gc> *inputs = NULL; 2551 vec<tree, va_gc> *outputs = NULL; 2552 vec_safe_push (outputs, 2553 build_tree_list 2554 (build_tree_list 2555 (NULL_TREE, build_string (2, "=m")), 2556 unshare_expr (swm))); 2557 vec_safe_push (inputs, 2558 build_tree_list 2559 (build_tree_list 2560 (NULL_TREE, build_string (1, "m")), 2561 unshare_expr (swm))); 2562 gasm *forcemod = gimple_build_asm_vec ("", inputs, outputs, 2563 NULL, NULL); 2564 gimple_seq_add_stmt (&seq, forcemod); 2565 2566 /* If the call will be assumed to not even read the watermark, 2567 make sure it is already in memory before the call. */ 2568 if ((gimple_call_flags (wrcall) & ECF_CONST)) 2569 { 2570 vec<tree, va_gc> *inputs = NULL; 2571 vec_safe_push (inputs, 2572 build_tree_list 2573 (build_tree_list 2574 (NULL_TREE, build_string (1, "m")), 2575 unshare_expr (swm))); 2576 gasm *force_store = gimple_build_asm_vec ("", inputs, NULL, 2577 NULL, NULL); 2578 if (gimple_has_location (wrcall)) 2579 gimple_set_location (force_store, gimple_location (wrcall)); 2580 gsi_insert_before (&gsi, force_store, GSI_SAME_STMT); 2581 } 2582 } 2583 #endif 2584 2585 if (!omit_own_watermark) 2586 { 2587 gcall *sleave = gimple_build_call (get_leave (), 1, 2588 unshare_expr (swmp)); 2589 gimple_seq_add_stmt (&seq, sleave); 2590 2591 gassign *clobber = gimple_build_assign (swm, 2592 build_clobber 2593 (TREE_TYPE (swm))); 2594 gimple_seq_add_stmt (&seq, clobber); 2595 } 2596 2597 gsi_insert_finally_seq_after_call (gsi, seq); 2598 } 2599 2600 /* Adjust all at-calls calls in NODE. */ 2601 2602 void 2603 pass_ipa_strub::adjust_at_calls_calls (cgraph_node *node) 2604 { 2605 /* Adjust unknown-callee indirect calls with STRUB_AT_CALLS types within 2606 onode. */ 2607 if (node->indirect_calls) 2608 { 2609 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); 2610 for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee) 2611 { 2612 gcc_checking_assert (e->indirect_unknown_callee); 2613 2614 if (!e->call_stmt) 2615 continue; 2616 2617 tree callee_fntype; 2618 enum strub_mode callee_mode 2619 = effective_strub_mode_for_call (e->call_stmt, &callee_fntype); 2620 2621 if (callee_mode != STRUB_AT_CALLS 2622 && callee_mode != STRUB_AT_CALLS_OPT) 2623 continue; 2624 2625 int named_args = adjust_at_calls_type (callee_fntype); 2626 2627 adjust_at_calls_call (e, named_args, callee_fntype); 2628 } 2629 pop_cfun (); 2630 } 2631 2632 if (node->callees) 2633 { 2634 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); 2635 for (cgraph_edge *e = node->callees; e; e = e->next_callee) 2636 { 2637 gcc_checking_assert (!e->indirect_unknown_callee); 2638 2639 if (!e->call_stmt) 2640 continue; 2641 2642 tree callee_fntype; 2643 enum strub_mode callee_mode 2644 = effective_strub_mode_for_call (e->call_stmt, &callee_fntype); 2645 2646 if (callee_mode != STRUB_AT_CALLS 2647 && callee_mode != STRUB_AT_CALLS_OPT) 2648 continue; 2649 2650 int named_args = adjust_at_calls_type (callee_fntype); 2651 2652 adjust_at_calls_call (e, named_args, callee_fntype); 2653 } 2654 pop_cfun (); 2655 } 2656 } 2657 2658 /* The strubm (strub mode) pass computes a strub mode for each function in the 2659 call graph, and checks, before any inlining, that strub callability 2660 requirements in effect are satisfied. */ 2661 2662 unsigned int 2663 pass_ipa_strub_mode::execute (function *) 2664 { 2665 last_cgraph_order = 0; 2666 ipa_strub_set_mode_for_new_functions (); 2667 2668 /* Verify before any inlining or other transformations. */ 2669 verify_strub (); 2670 2671 return 0; 2672 } 2673 2674 /* Create a strub mode pass. */ 2675 2676 simple_ipa_opt_pass * 2677 make_pass_ipa_strub_mode (gcc::context *ctxt) 2678 { 2679 return new pass_ipa_strub_mode (ctxt); 2680 } 2681 2682 /* The strub pass proper adjusts types, signatures, and at-calls calls, and 2683 splits internal-strub functions. */ 2684 2685 unsigned int 2686 pass_ipa_strub::execute (function *) 2687 { 2688 cgraph_node *onode; 2689 2690 ipa_strub_set_mode_for_new_functions (); 2691 2692 /* First, adjust the signature of at-calls functions. We adjust types of 2693 at-calls functions first, so that we don't modify types in place unless 2694 strub is explicitly requested. */ 2695 FOR_EACH_FUNCTION (onode) 2696 { 2697 enum strub_mode mode = get_strub_mode (onode); 2698 2699 if (mode == STRUB_AT_CALLS 2700 || mode == STRUB_AT_CALLS_OPT) 2701 { 2702 /* Create a type variant if strubbing was not explicitly requested in 2703 the function type. */ 2704 if (get_strub_mode_from_type (TREE_TYPE (onode->decl)) != mode) 2705 distinctify_node_type (onode); 2706 2707 int named_args = adjust_at_calls_type (TREE_TYPE (onode->decl)); 2708 2709 /* An external function explicitly declared with strub won't have a 2710 body. Even with implicit at-calls strub, a function may have had its 2711 body removed after we selected the mode, and then we have nothing 2712 further to do. */ 2713 if (!onode->has_gimple_body_p ()) 2714 continue; 2715 2716 tree *pargs = &DECL_ARGUMENTS (onode->decl); 2717 2718 /* A noninterposable_alias reuses the same parm decl chain, don't add 2719 the parm twice. */ 2720 bool aliased_parms = (onode->alias && *pargs 2721 && DECL_CONTEXT (*pargs) != onode->decl); 2722 2723 if (aliased_parms) 2724 continue; 2725 2726 for (int i = 0; i < named_args; i++) 2727 pargs = &DECL_CHAIN (*pargs); 2728 2729 tree wmptr = build_decl (DECL_SOURCE_LOCATION (onode->decl), 2730 PARM_DECL, 2731 get_watermark_ptr (), 2732 get_qpwmt ()); 2733 DECL_ARTIFICIAL (wmptr) = 1; 2734 DECL_ARG_TYPE (wmptr) = get_qpwmt (); 2735 DECL_CONTEXT (wmptr) = onode->decl; 2736 TREE_USED (wmptr) = 1; 2737 DECL_CHAIN (wmptr) = *pargs; 2738 *pargs = wmptr; 2739 2740 if (onode->alias) 2741 continue; 2742 2743 cgraph_node *nnode = onode; 2744 push_cfun (DECL_STRUCT_FUNCTION (nnode->decl)); 2745 2746 { 2747 edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)); 2748 gimple_seq seq = call_update_watermark (wmptr, nnode, e->src->count); 2749 gsi_insert_seq_on_edge_immediate (e, seq); 2750 } 2751 2752 if (DECL_STRUCT_FUNCTION (nnode->decl)->calls_alloca) 2753 { 2754 basic_block bb; 2755 FOR_EACH_BB_FN (bb, cfun) 2756 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); 2757 !gsi_end_p (gsi); gsi_next (&gsi)) 2758 { 2759 gimple *stmt = gsi_stmt (gsi); 2760 2761 gcall *call = dyn_cast <gcall *> (stmt); 2762 2763 if (!call) 2764 continue; 2765 2766 if (gimple_alloca_call_p (call)) 2767 { 2768 /* Capture stack growth. */ 2769 gimple_seq seq = call_update_watermark (wmptr, NULL, 2770 gsi_bb (gsi) 2771 ->count); 2772 gsi_insert_finally_seq_after_call (gsi, seq); 2773 } 2774 } 2775 } 2776 2777 pop_cfun (); 2778 } 2779 } 2780 2781 FOR_EACH_FUNCTION (onode) 2782 { 2783 if (!onode->has_gimple_body_p ()) 2784 continue; 2785 2786 enum strub_mode mode = get_strub_mode (onode); 2787 2788 if (mode != STRUB_INTERNAL) 2789 { 2790 adjust_at_calls_calls (onode); 2791 continue; 2792 } 2793 2794 bool is_stdarg = calls_builtin_va_start_p (onode);; 2795 bool apply_args = calls_builtin_apply_args_p (onode); 2796 2797 vec<ipa_adjusted_param, va_gc> *nparms = NULL; 2798 unsigned j = 0; 2799 { 2800 // The following loop copied from ipa-split.c:split_function. 2801 for (tree parm = DECL_ARGUMENTS (onode->decl); 2802 parm; parm = DECL_CHAIN (parm), j++) 2803 { 2804 ipa_adjusted_param adj = {}; 2805 adj.op = IPA_PARAM_OP_COPY; 2806 adj.base_index = j; 2807 adj.prev_clone_index = j; 2808 vec_safe_push (nparms, adj); 2809 } 2810 2811 if (apply_args) 2812 { 2813 ipa_adjusted_param aaadj = {}; 2814 aaadj.op = IPA_PARAM_OP_NEW; 2815 aaadj.type = get_qptr (); 2816 vec_safe_push (nparms, aaadj); 2817 } 2818 2819 if (is_stdarg) 2820 { 2821 ipa_adjusted_param vladj = {}; 2822 vladj.op = IPA_PARAM_OP_NEW; 2823 vladj.type = get_qpvalst (); 2824 vec_safe_push (nparms, vladj); 2825 } 2826 2827 ipa_adjusted_param wmadj = {}; 2828 wmadj.op = IPA_PARAM_OP_NEW; 2829 wmadj.type = get_qpwmt (); 2830 vec_safe_push (nparms, wmadj); 2831 } 2832 ipa_param_adjustments adj (nparms, -1, false); 2833 2834 cgraph_node *nnode = onode->create_version_clone_with_body 2835 (auto_vec<cgraph_edge *> (0), 2836 NULL, &adj, NULL, NULL, "strub", NULL); 2837 2838 if (!nnode) 2839 { 2840 error_at (DECL_SOURCE_LOCATION (onode->decl), 2841 "failed to split %qD for %<strub%>", 2842 onode->decl); 2843 continue; 2844 } 2845 2846 onode->split_part = true; 2847 if (onode->calls_comdat_local) 2848 nnode->add_to_same_comdat_group (onode); 2849 2850 set_strub_mode_to (onode, STRUB_WRAPPER); 2851 set_strub_mode_to (nnode, STRUB_WRAPPED); 2852 2853 adjust_at_calls_calls (nnode); 2854 2855 /* Decide which of the wrapped function's parms we want to turn into 2856 references to the argument passed to the wrapper. In general, we want to 2857 copy small arguments, and avoid copying large ones. Variable-sized array 2858 lengths given by other arguments, as in 20020210-1.c, would lead to 2859 problems if passed by value, after resetting the original function and 2860 dropping the length computation; passing them by reference works. 2861 DECL_BY_REFERENCE is *not* a substitute for this: it involves copying 2862 anyway, but performed at the caller. */ 2863 indirect_parms_t indirect_nparms (3, false); 2864 unsigned adjust_ftype = 0; 2865 unsigned named_args = 0; 2866 for (tree parm = DECL_ARGUMENTS (onode->decl), 2867 nparm = DECL_ARGUMENTS (nnode->decl), 2868 nparmt = TYPE_ARG_TYPES (TREE_TYPE (nnode->decl)); 2869 parm; 2870 named_args++, 2871 parm = DECL_CHAIN (parm), 2872 nparm = DECL_CHAIN (nparm), 2873 nparmt = nparmt ? TREE_CHAIN (nparmt) : NULL_TREE) 2874 if (TREE_THIS_VOLATILE (parm) 2875 || !(0 /* DECL_BY_REFERENCE (narg) */ 2876 || is_gimple_reg_type (TREE_TYPE (nparm)) 2877 || VECTOR_TYPE_P (TREE_TYPE (nparm)) 2878 || TREE_CODE (TREE_TYPE (nparm)) == COMPLEX_TYPE 2879 || (tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (nparm))) 2880 && (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (nparm))) 2881 <= 4 * UNITS_PER_WORD)))) 2882 { 2883 /* No point in indirecting pointer types. Presumably they 2884 won't ever pass the size-based test above, but check the 2885 assumption here, because getting this wrong would mess 2886 with attribute access and possibly others. We deal with 2887 fn spec below. */ 2888 gcc_checking_assert (!POINTER_TYPE_P (TREE_TYPE (nparm))); 2889 2890 indirect_nparms.add (nparm); 2891 2892 /* ??? Is there any case in which it is not safe to suggest the parms 2893 turned indirect don't alias anything else? They are distinct, 2894 unaliased memory in the wrapper, and the wrapped can't possibly 2895 take pointers into them because none of the pointers passed to the 2896 wrapper can alias other incoming parameters passed by value, even 2897 if with transparent reference, and the wrapper doesn't take any 2898 extra parms that could point into wrapper's parms. So we can 2899 probably drop the TREE_ADDRESSABLE and keep the TRUE. */ 2900 tree ref_type = build_ref_type_for (nparm); 2901 2902 if (TREE_THIS_VOLATILE (nparm) 2903 && TYPE_VOLATILE (TREE_TYPE (nparm)) 2904 && !TYPE_VOLATILE (ref_type)) 2905 TREE_SIDE_EFFECTS (nparm) = TREE_THIS_VOLATILE (nparm) = 0; 2906 DECL_ARG_TYPE (nparm) = TREE_TYPE (nparm) = ref_type; 2907 relayout_decl (nparm); 2908 TREE_ADDRESSABLE (nparm) = 0; 2909 DECL_BY_REFERENCE (nparm) = 0; 2910 DECL_NOT_GIMPLE_REG_P (nparm) = 0; 2911 /* ??? This avoids mismatches in debug info bind stmts in 2912 e.g. a-chahan . */ 2913 DECL_ABSTRACT_ORIGIN (nparm) = NULL; 2914 2915 if (nparmt) 2916 adjust_ftype++; 2917 } 2918 2919 /* Also adjust the wrapped function type, if needed. */ 2920 if (adjust_ftype) 2921 { 2922 tree nftype = TREE_TYPE (nnode->decl); 2923 2924 /* We always add at least one argument at the end of the signature, when 2925 cloning the function, so we don't expect to need to duplicate the 2926 type here. */ 2927 gcc_checking_assert (TYPE_ARG_TYPES (nftype) 2928 != TYPE_ARG_TYPES (TREE_TYPE (onode->decl))); 2929 2930 /* Check that fnspec still works for the modified function signature, 2931 and drop it otherwise. */ 2932 bool drop_fnspec = false; 2933 tree fnspec = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (nftype)); 2934 attr_fnspec spec = fnspec ? attr_fnspec (fnspec) : attr_fnspec (""); 2935 2936 unsigned retcopy; 2937 if (!(fnspec && spec.returns_arg (&retcopy))) 2938 retcopy = (unsigned) -1; 2939 2940 unsigned i = 0; 2941 for (tree nparm = DECL_ARGUMENTS (nnode->decl), 2942 nparmt = TYPE_ARG_TYPES (nftype); 2943 adjust_ftype > 0; 2944 i++, nparm = DECL_CHAIN (nparm), nparmt = TREE_CHAIN (nparmt)) 2945 if (indirect_nparms.contains (nparm)) 2946 { 2947 TREE_VALUE (nparmt) = TREE_TYPE (nparm); 2948 adjust_ftype--; 2949 2950 if (fnspec && !drop_fnspec) 2951 { 2952 if (i == retcopy) 2953 drop_fnspec = true; 2954 else if (spec.arg_specified_p (i)) 2955 { 2956 /* Properties that apply to pointers only must not be 2957 present, because we don't make pointers further 2958 indirect. */ 2959 gcc_checking_assert 2960 (!spec.arg_max_access_size_given_by_arg_p (i, NULL)); 2961 gcc_checking_assert (!spec.arg_copied_to_arg_p (i, NULL)); 2962 2963 /* Any claim of direct access only is invalidated by 2964 adding an indirection level. */ 2965 if (spec.arg_direct_p (i)) 2966 drop_fnspec = true; 2967 2968 /* If there's a claim the argument is not read from, the 2969 added indirection invalidates it: if the argument is 2970 used at all, then the pointer will necessarily be 2971 read. */ 2972 if (!spec.arg_maybe_read_p (i) 2973 && spec.arg_used_p (i)) 2974 drop_fnspec = true; 2975 } 2976 } 2977 } 2978 2979 /* ??? Maybe we could adjust it instead. Note we don't need 2980 to mess with attribute access: pointer-typed parameters are 2981 not modified, so they can remain unchanged. */ 2982 if (drop_fnspec) 2983 remove_named_attribute_unsharing ("fn spec", 2984 &TYPE_ATTRIBUTES (nftype)); 2985 2986 TREE_TYPE (nnode->decl) = nftype; 2987 } 2988 2989 #if ATTR_FNSPEC_DECONST_WATERMARK 2990 { 2991 int flags = flags_from_decl_or_type (nnode->decl); 2992 tree fnspec = lookup_attribute ("fn spec", TREE_TYPE (nnode->decl)); 2993 2994 if ((flags & (ECF_CONST | ECF_PURE | ECF_NOVOPS)) || fnspec) 2995 { 2996 size_t xargs = 1 + int (is_stdarg) + int (apply_args); 2997 size_t curlen = 0, tgtlen = 2 + 2 * (named_args + xargs); 2998 auto_vec<char> nspecv (tgtlen); 2999 char *nspec = &nspecv[0]; /* It will *not* be NUL-terminated! */ 3000 bool no_writes_p = true; 3001 if (fnspec) 3002 { 3003 tree fnspecstr = TREE_VALUE (TREE_VALUE (fnspec)); 3004 curlen = TREE_STRING_LENGTH (fnspecstr); 3005 memcpy (nspec, TREE_STRING_POINTER (fnspecstr), curlen); 3006 if (!(flags & (ECF_CONST | ECF_PURE | ECF_NOVOPS)) 3007 && curlen >= 2 3008 && nspec[1] != 'c' && nspec[1] != 'C' 3009 && nspec[1] != 'p' && nspec[1] != 'P') 3010 no_writes_p = false; 3011 } 3012 if (!curlen) 3013 { 3014 nspec[curlen++] = '.'; 3015 nspec[curlen++] = ((flags & ECF_CONST) 3016 ? 'c' 3017 : (flags & ECF_PURE) 3018 ? 'p' 3019 : ' '); 3020 } 3021 while (curlen < tgtlen - 2 * xargs) 3022 { 3023 nspec[curlen++] = '.'; 3024 nspec[curlen++] = ' '; 3025 } 3026 3027 /* These extra args are unlikely to be present in const or pure 3028 functions. It's conceivable that a function that takes variable 3029 arguments, or that passes its arguments on to another function, 3030 could be const or pure, but it would not modify the arguments, and, 3031 being pure or const, it couldn't possibly modify or even access 3032 memory referenced by them. But it can read from these internal 3033 data structures created by the wrapper, and from any 3034 argument-passing memory referenced by them, so we denote the 3035 possibility of reading from multiple levels of indirection, but 3036 only of reading because const/pure. */ 3037 if (apply_args) 3038 { 3039 nspec[curlen++] = 'r'; 3040 nspec[curlen++] = ' '; 3041 } 3042 if (is_stdarg) 3043 { 3044 nspec[curlen++] = (no_writes_p ? 'r' : '.'); 3045 nspec[curlen++] = (no_writes_p ? 't' : ' '); 3046 } 3047 3048 nspec[curlen++] = 'W'; 3049 nspec[curlen++] = 't'; 3050 3051 /* The type has already been copied before adding parameters. */ 3052 gcc_checking_assert (TYPE_ARG_TYPES (TREE_TYPE (nnode->decl)) 3053 != TYPE_ARG_TYPES (TREE_TYPE (onode->decl))); 3054 TYPE_ATTRIBUTES (TREE_TYPE (nnode->decl)) 3055 = tree_cons (get_identifier ("fn spec"), 3056 build_tree_list (NULL_TREE, 3057 build_string (tgtlen, nspec)), 3058 TYPE_ATTRIBUTES (TREE_TYPE (nnode->decl))); 3059 } 3060 } 3061 #endif 3062 3063 { 3064 tree decl = onode->decl; 3065 cgraph_node *target = nnode; 3066 3067 { // copied from create_wrapper 3068 3069 /* Preserve DECL_RESULT so we get right by reference flag. */ 3070 tree decl_result = DECL_RESULT (decl); 3071 3072 /* Remove the function's body but keep arguments to be reused 3073 for thunk. */ 3074 onode->release_body (true); 3075 onode->reset (/* unlike create_wrapper: preserve_comdat_group = */true); 3076 3077 DECL_UNINLINABLE (decl) = false; 3078 DECL_RESULT (decl) = decl_result; 3079 DECL_INITIAL (decl) = NULL; 3080 allocate_struct_function (decl, false); 3081 set_cfun (NULL); 3082 3083 /* Turn alias into thunk and expand it into GIMPLE representation. */ 3084 onode->definition = true; 3085 3086 thunk_info::get_create (onode); 3087 onode->thunk = true; 3088 onode->create_edge (target, NULL, onode->count); 3089 onode->callees->can_throw_external = !TREE_NOTHROW (target->decl); 3090 3091 tree arguments = DECL_ARGUMENTS (decl); 3092 3093 while (arguments) 3094 { 3095 TREE_ADDRESSABLE (arguments) = false; 3096 arguments = TREE_CHAIN (arguments); 3097 } 3098 3099 { 3100 tree alias = onode->callees->callee->decl; 3101 tree thunk_fndecl = decl; 3102 tree a; 3103 3104 int nxargs = 1 + is_stdarg + apply_args; 3105 3106 { // Simplified from expand_thunk. 3107 tree restype; 3108 basic_block bb, then_bb, else_bb, return_bb; 3109 gimple_stmt_iterator bsi; 3110 int nargs = 0; 3111 tree arg; 3112 int i; 3113 tree resdecl; 3114 tree restmp = NULL; 3115 3116 gcall *call; 3117 greturn *ret; 3118 bool alias_is_noreturn = TREE_THIS_VOLATILE (alias); 3119 3120 a = DECL_ARGUMENTS (thunk_fndecl); 3121 3122 current_function_decl = thunk_fndecl; 3123 3124 /* Ensure thunks are emitted in their correct sections. */ 3125 resolve_unique_section (thunk_fndecl, 0, 3126 flag_function_sections); 3127 3128 bitmap_obstack_initialize (NULL); 3129 3130 /* Build the return declaration for the function. */ 3131 restype = TREE_TYPE (TREE_TYPE (thunk_fndecl)); 3132 if (DECL_RESULT (thunk_fndecl) == NULL_TREE) 3133 { 3134 resdecl = build_decl (input_location, RESULT_DECL, 0, restype); 3135 DECL_ARTIFICIAL (resdecl) = 1; 3136 DECL_IGNORED_P (resdecl) = 1; 3137 DECL_CONTEXT (resdecl) = thunk_fndecl; 3138 DECL_RESULT (thunk_fndecl) = resdecl; 3139 } 3140 else 3141 resdecl = DECL_RESULT (thunk_fndecl); 3142 3143 profile_count cfg_count = onode->count; 3144 if (!cfg_count.initialized_p ()) 3145 cfg_count = profile_count::from_gcov_type (BB_FREQ_MAX).guessed_local (); 3146 3147 bb = then_bb = else_bb = return_bb 3148 = init_lowered_empty_function (thunk_fndecl, true, cfg_count); 3149 3150 bsi = gsi_start_bb (bb); 3151 3152 /* Build call to the function being thunked. */ 3153 if (!VOID_TYPE_P (restype) 3154 && (!alias_is_noreturn 3155 || TREE_ADDRESSABLE (restype) 3156 || TREE_CODE (TYPE_SIZE_UNIT (restype)) != INTEGER_CST)) 3157 { 3158 if (DECL_BY_REFERENCE (resdecl)) 3159 { 3160 restmp = gimple_fold_indirect_ref (resdecl); 3161 if (!restmp) 3162 restmp = build2 (MEM_REF, 3163 TREE_TYPE (TREE_TYPE (resdecl)), 3164 resdecl, 3165 build_int_cst (TREE_TYPE (resdecl), 0)); 3166 } 3167 else if (aggregate_value_p (resdecl, TREE_TYPE (thunk_fndecl))) 3168 { 3169 restmp = resdecl; 3170 3171 if (VAR_P (restmp)) 3172 { 3173 add_local_decl (cfun, restmp); 3174 BLOCK_VARS (DECL_INITIAL (current_function_decl)) 3175 = restmp; 3176 } 3177 } 3178 else 3179 restmp = create_tmp_reg (restype, "retval"); 3180 } 3181 3182 for (arg = a; arg; arg = DECL_CHAIN (arg)) 3183 nargs++; 3184 auto_vec<tree> vargs (nargs + nxargs); 3185 i = 0; 3186 arg = a; 3187 3188 if (nargs) 3189 for (tree nparm = DECL_ARGUMENTS (nnode->decl); 3190 i < nargs; 3191 i++, arg = DECL_CHAIN (arg), nparm = DECL_CHAIN (nparm)) 3192 { 3193 tree save_arg = arg; 3194 3195 /* Arrange to pass indirectly the parms, if we decided to do 3196 so, and revert its type in the wrapper. */ 3197 if (indirect_nparms.contains (nparm)) 3198 { 3199 tree ref_type = TREE_TYPE (nparm); 3200 TREE_ADDRESSABLE (arg) = true; 3201 arg = build1 (ADDR_EXPR, ref_type, arg); 3202 } 3203 else if (!TREE_THIS_VOLATILE (arg)) 3204 DECL_NOT_GIMPLE_REG_P (arg) = 0; 3205 3206 /* Convert the argument back to the type used by the calling 3207 conventions, e.g. a non-prototyped float type is passed as 3208 double, as in 930603-1.c, and needs to be converted back to 3209 double to be passed on unchanged to the wrapped 3210 function. */ 3211 if (TREE_TYPE (nparm) != DECL_ARG_TYPE (nparm)) 3212 { 3213 tree tmp = arg; 3214 /* If ARG is e.g. volatile, we must copy and 3215 convert in separate statements. */ 3216 if (!is_gimple_val (arg)) 3217 { 3218 tmp = create_tmp_reg (TYPE_MAIN_VARIANT 3219 (TREE_TYPE (arg)), "arg"); 3220 gimple *stmt = gimple_build_assign (tmp, arg); 3221 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT); 3222 } 3223 arg = fold_convert (DECL_ARG_TYPE (nparm), tmp); 3224 } 3225 3226 if (!is_gimple_val (arg)) 3227 { 3228 tree tmp = create_tmp_reg (TYPE_MAIN_VARIANT 3229 (TREE_TYPE (arg)), "arg"); 3230 gimple *stmt = gimple_build_assign (tmp, arg); 3231 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT); 3232 arg = tmp; 3233 } 3234 vargs.quick_push (arg); 3235 arg = save_arg; 3236 } 3237 /* These strub arguments are adjusted later. */ 3238 if (apply_args) 3239 vargs.quick_push (null_pointer_node); 3240 if (is_stdarg) 3241 vargs.quick_push (null_pointer_node); 3242 vargs.quick_push (null_pointer_node); 3243 call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), 3244 vargs); 3245 onode->callees->call_stmt = call; 3246 // gimple_call_set_from_thunk (call, true); 3247 if (DECL_STATIC_CHAIN (alias)) 3248 { 3249 tree p = DECL_STRUCT_FUNCTION (alias)->static_chain_decl; 3250 tree type = TREE_TYPE (p); 3251 tree decl = build_decl (DECL_SOURCE_LOCATION (thunk_fndecl), 3252 PARM_DECL, create_tmp_var_name ("CHAIN"), 3253 type); 3254 DECL_ARTIFICIAL (decl) = 1; 3255 DECL_IGNORED_P (decl) = 1; 3256 TREE_USED (decl) = 1; 3257 DECL_CONTEXT (decl) = thunk_fndecl; 3258 DECL_ARG_TYPE (decl) = type; 3259 TREE_READONLY (decl) = 1; 3260 3261 struct function *sf = DECL_STRUCT_FUNCTION (thunk_fndecl); 3262 sf->static_chain_decl = decl; 3263 3264 gimple_call_set_chain (call, decl); 3265 } 3266 3267 /* Return slot optimization is always possible and in fact required to 3268 return values with DECL_BY_REFERENCE. */ 3269 if (aggregate_value_p (resdecl, TREE_TYPE (thunk_fndecl)) 3270 && (!is_gimple_reg_type (TREE_TYPE (resdecl)) 3271 || DECL_BY_REFERENCE (resdecl))) 3272 gimple_call_set_return_slot_opt (call, true); 3273 3274 if (restmp) 3275 { 3276 gimple_call_set_lhs (call, restmp); 3277 gcc_assert (useless_type_conversion_p (TREE_TYPE (restmp), 3278 TREE_TYPE (TREE_TYPE (alias)))); 3279 } 3280 gsi_insert_after (&bsi, call, GSI_NEW_STMT); 3281 if (!alias_is_noreturn) 3282 { 3283 /* Build return value. */ 3284 if (!DECL_BY_REFERENCE (resdecl)) 3285 ret = gimple_build_return (restmp); 3286 else 3287 ret = gimple_build_return (resdecl); 3288 3289 gsi_insert_after (&bsi, ret, GSI_NEW_STMT); 3290 } 3291 else 3292 { 3293 remove_edge (single_succ_edge (bb)); 3294 } 3295 3296 cfun->gimple_df->in_ssa_p = true; 3297 update_max_bb_count (); 3298 profile_status_for_fn (cfun) 3299 = cfg_count.initialized_p () && cfg_count.ipa_p () 3300 ? PROFILE_READ : PROFILE_GUESSED; 3301 /* FIXME: C++ FE should stop setting TREE_ASM_WRITTEN on thunks. */ 3302 // TREE_ASM_WRITTEN (thunk_fndecl) = false; 3303 delete_unreachable_blocks (); 3304 update_ssa (TODO_update_ssa); 3305 checking_verify_flow_info (); 3306 free_dominance_info (CDI_DOMINATORS); 3307 3308 /* Since we want to emit the thunk, we explicitly mark its name as 3309 referenced. */ 3310 onode->thunk = false; 3311 onode->lowered = true; 3312 bitmap_obstack_release (NULL); 3313 } 3314 current_function_decl = NULL; 3315 set_cfun (NULL); 3316 } 3317 3318 thunk_info::remove (onode); 3319 3320 // some more of create_wrapper at the end of the next block. 3321 } 3322 } 3323 3324 { 3325 tree aaval = NULL_TREE; 3326 tree vaptr = NULL_TREE; 3327 tree wmptr = NULL_TREE; 3328 for (tree arg = DECL_ARGUMENTS (nnode->decl); arg; arg = DECL_CHAIN (arg)) 3329 { 3330 aaval = vaptr; 3331 vaptr = wmptr; 3332 wmptr = arg; 3333 } 3334 3335 if (!apply_args) 3336 aaval = NULL_TREE; 3337 /* The trailing args are [apply_args], [va_list_ptr], and 3338 watermark. If we don't have a va_list_ptr, the penultimate 3339 argument is apply_args. 3340 */ 3341 else if (!is_stdarg) 3342 aaval = vaptr; 3343 3344 if (!is_stdarg) 3345 vaptr = NULL_TREE; 3346 3347 DECL_NAME (wmptr) = get_watermark_ptr (); 3348 DECL_ARTIFICIAL (wmptr) = 1; 3349 DECL_IGNORED_P (wmptr) = 1; 3350 TREE_USED (wmptr) = 1; 3351 3352 if (is_stdarg) 3353 { 3354 DECL_NAME (vaptr) = get_va_list_ptr (); 3355 DECL_ARTIFICIAL (vaptr) = 1; 3356 DECL_IGNORED_P (vaptr) = 1; 3357 TREE_USED (vaptr) = 1; 3358 } 3359 3360 if (apply_args) 3361 { 3362 DECL_NAME (aaval) = get_apply_args (); 3363 DECL_ARTIFICIAL (aaval) = 1; 3364 DECL_IGNORED_P (aaval) = 1; 3365 TREE_USED (aaval) = 1; 3366 } 3367 3368 push_cfun (DECL_STRUCT_FUNCTION (nnode->decl)); 3369 3370 { 3371 edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)); 3372 gimple_seq seq = call_update_watermark (wmptr, nnode, e->src->count); 3373 gsi_insert_seq_on_edge_immediate (e, seq); 3374 } 3375 3376 bool any_indirect = !indirect_nparms.is_empty (); 3377 3378 if (any_indirect) 3379 { 3380 basic_block bb; 3381 bool needs_commit = false; 3382 FOR_EACH_BB_FN (bb, cfun) 3383 { 3384 for (gphi_iterator gsi = gsi_start_nonvirtual_phis (bb); 3385 !gsi_end_p (gsi); 3386 gsi_next_nonvirtual_phi (&gsi)) 3387 { 3388 gphi *stmt = gsi.phi (); 3389 3390 walk_stmt_info wi = {}; 3391 wi.info = &indirect_nparms; 3392 walk_gimple_op (stmt, walk_make_indirect, &wi); 3393 if (wi.changed && !is_gimple_debug (gsi_stmt (gsi))) 3394 if (walk_regimplify_phi (stmt)) 3395 needs_commit = true; 3396 } 3397 3398 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); 3399 !gsi_end_p (gsi); gsi_next (&gsi)) 3400 { 3401 gimple *stmt = gsi_stmt (gsi); 3402 3403 walk_stmt_info wi = {}; 3404 wi.info = &indirect_nparms; 3405 walk_gimple_op (stmt, walk_make_indirect, &wi); 3406 if (wi.changed) 3407 { 3408 if (!is_gimple_debug (stmt)) 3409 { 3410 wi.info = &gsi; 3411 walk_gimple_op (stmt, walk_regimplify_addr_expr, 3412 &wi); 3413 } 3414 update_stmt (stmt); 3415 } 3416 } 3417 } 3418 if (needs_commit) 3419 gsi_commit_edge_inserts (); 3420 } 3421 3422 if (DECL_STRUCT_FUNCTION (nnode->decl)->calls_alloca 3423 || is_stdarg || apply_args) 3424 for (cgraph_edge *e = nnode->callees, *enext; e; e = enext) 3425 { 3426 if (!e->call_stmt) 3427 continue; 3428 3429 gcall *call = e->call_stmt; 3430 gimple_stmt_iterator gsi = gsi_for_stmt (call); 3431 tree fndecl = e->callee->decl; 3432 3433 enext = e->next_callee; 3434 3435 if (gimple_alloca_call_p (call)) 3436 { 3437 gimple_seq seq = call_update_watermark (wmptr, NULL, 3438 gsi_bb (gsi)->count); 3439 gsi_insert_finally_seq_after_call (gsi, seq); 3440 } 3441 else if (fndecl && is_stdarg 3442 && fndecl_built_in_p (fndecl, BUILT_IN_VA_START)) 3443 { 3444 /* Using a non-default stdarg ABI makes the function ineligible 3445 for internal strub. */ 3446 gcc_checking_assert (builtin_decl_explicit (BUILT_IN_VA_START) 3447 == fndecl); 3448 tree bvacopy = builtin_decl_explicit (BUILT_IN_VA_COPY); 3449 gimple_call_set_fndecl (call, bvacopy); 3450 tree arg = vaptr; 3451 /* The va_copy source must be dereferenced, unless it's an array 3452 type, that would have decayed to a pointer. */ 3453 if (TREE_CODE (TREE_TYPE (TREE_TYPE (vaptr))) != ARRAY_TYPE) 3454 { 3455 arg = gimple_fold_indirect_ref (vaptr); 3456 if (!arg) 3457 arg = build2 (MEM_REF, 3458 TREE_TYPE (TREE_TYPE (vaptr)), 3459 vaptr, 3460 build_int_cst (TREE_TYPE (vaptr), 0)); 3461 if (!is_gimple_val (arg)) 3462 arg = force_gimple_operand_gsi (&gsi, arg, true, 3463 NULL_TREE, true, GSI_SAME_STMT); 3464 } 3465 gimple_call_set_arg (call, 1, arg); 3466 update_stmt (call); 3467 e->redirect_callee (cgraph_node::get_create (bvacopy)); 3468 } 3469 else if (fndecl && apply_args 3470 && fndecl_built_in_p (fndecl, BUILT_IN_APPLY_ARGS)) 3471 { 3472 tree lhs = gimple_call_lhs (call); 3473 gimple *assign = (lhs 3474 ? gimple_build_assign (lhs, aaval) 3475 : gimple_build_nop ()); 3476 gsi_replace (&gsi, assign, true); 3477 cgraph_edge::remove (e); 3478 } 3479 } 3480 3481 { // a little more copied from create_wrapper 3482 3483 /* Inline summary set-up. */ 3484 nnode->analyze (); 3485 // inline_analyze_function (nnode); 3486 } 3487 3488 pop_cfun (); 3489 } 3490 3491 { 3492 push_cfun (DECL_STRUCT_FUNCTION (onode->decl)); 3493 gimple_stmt_iterator gsi 3494 = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun))); 3495 3496 gcall *wrcall; 3497 while (!(wrcall = dyn_cast <gcall *> (gsi_stmt (gsi)))) 3498 gsi_next (&gsi); 3499 3500 tree swm = create_tmp_var (get_wmt (), ".strub.watermark"); 3501 TREE_ADDRESSABLE (swm) = true; 3502 tree swmp = build1 (ADDR_EXPR, get_pwmt (), swm); 3503 3504 tree enter = get_enter (); 3505 gcall *stptr = gimple_build_call (enter, 1, unshare_expr (swmp)); 3506 gimple_set_location (stptr, gimple_location (wrcall)); 3507 gsi_insert_before (&gsi, stptr, GSI_SAME_STMT); 3508 onode->create_edge (cgraph_node::get_create (enter), 3509 stptr, gsi_bb (gsi)->count, false); 3510 3511 int nargs = gimple_call_num_args (wrcall); 3512 3513 gimple_seq seq = NULL; 3514 3515 if (apply_args) 3516 { 3517 tree aalst = create_tmp_var (ptr_type_node, ".strub.apply_args"); 3518 tree bappargs = builtin_decl_explicit (BUILT_IN_APPLY_ARGS); 3519 gcall *appargs = gimple_build_call (bappargs, 0); 3520 gimple_call_set_lhs (appargs, aalst); 3521 gimple_set_location (appargs, gimple_location (wrcall)); 3522 gsi_insert_before (&gsi, appargs, GSI_SAME_STMT); 3523 gimple_call_set_arg (wrcall, nargs - 2 - is_stdarg, aalst); 3524 onode->create_edge (cgraph_node::get_create (bappargs), 3525 appargs, gsi_bb (gsi)->count, false); 3526 } 3527 3528 if (is_stdarg) 3529 { 3530 tree valst = create_tmp_var (va_list_type_node, ".strub.va_list"); 3531 TREE_ADDRESSABLE (valst) = true; 3532 tree vaptr = build1 (ADDR_EXPR, 3533 build_pointer_type (va_list_type_node), 3534 valst); 3535 gimple_call_set_arg (wrcall, nargs - 2, unshare_expr (vaptr)); 3536 3537 tree bvastart = builtin_decl_explicit (BUILT_IN_VA_START); 3538 gcall *vastart = gimple_build_call (bvastart, 2, 3539 unshare_expr (vaptr), 3540 integer_zero_node); 3541 gimple_set_location (vastart, gimple_location (wrcall)); 3542 gsi_insert_before (&gsi, vastart, GSI_SAME_STMT); 3543 onode->create_edge (cgraph_node::get_create (bvastart), 3544 vastart, gsi_bb (gsi)->count, false); 3545 3546 tree bvaend = builtin_decl_explicit (BUILT_IN_VA_END); 3547 gcall *vaend = gimple_build_call (bvaend, 1, unshare_expr (vaptr)); 3548 gimple_set_location (vaend, gimple_location (wrcall)); 3549 gimple_seq_add_stmt (&seq, vaend); 3550 } 3551 3552 gimple_call_set_arg (wrcall, nargs - 1, unshare_expr (swmp)); 3553 // gimple_call_set_tail (wrcall, false); 3554 update_stmt (wrcall); 3555 3556 { 3557 #if !ATTR_FNSPEC_DECONST_WATERMARK 3558 /* If the call will be assumed to not modify or even read the 3559 watermark, make it read and modified ourselves. */ 3560 if ((gimple_call_flags (wrcall) 3561 & (ECF_CONST | ECF_PURE | ECF_NOVOPS))) 3562 { 3563 vec<tree, va_gc> *inputs = NULL; 3564 vec<tree, va_gc> *outputs = NULL; 3565 vec_safe_push (outputs, 3566 build_tree_list 3567 (build_tree_list 3568 (NULL_TREE, build_string (2, "=m")), 3569 swm)); 3570 vec_safe_push (inputs, 3571 build_tree_list 3572 (build_tree_list 3573 (NULL_TREE, build_string (1, "m")), 3574 swm)); 3575 gasm *forcemod = gimple_build_asm_vec ("", inputs, outputs, 3576 NULL, NULL); 3577 gimple_seq_add_stmt (&seq, forcemod); 3578 3579 /* If the call will be assumed to not even read the watermark, 3580 make sure it is already in memory before the call. */ 3581 if ((gimple_call_flags (wrcall) & ECF_CONST)) 3582 { 3583 vec<tree, va_gc> *inputs = NULL; 3584 vec_safe_push (inputs, 3585 build_tree_list 3586 (build_tree_list 3587 (NULL_TREE, build_string (1, "m")), 3588 swm)); 3589 gasm *force_store = gimple_build_asm_vec ("", inputs, NULL, 3590 NULL, NULL); 3591 gimple_set_location (force_store, gimple_location (wrcall)); 3592 gsi_insert_before (&gsi, force_store, GSI_SAME_STMT); 3593 } 3594 } 3595 #endif 3596 3597 gcall *sleave = gimple_build_call (get_leave (), 1, 3598 unshare_expr (swmp)); 3599 gimple_seq_add_stmt (&seq, sleave); 3600 3601 gassign *clobber = gimple_build_assign (swm, 3602 build_clobber 3603 (TREE_TYPE (swm))); 3604 gimple_seq_add_stmt (&seq, clobber); 3605 } 3606 3607 gsi_insert_finally_seq_after_call (gsi, seq); 3608 3609 /* For nnode, we don't rebuild edges because we wish to retain 3610 any redirections copied to it from earlier passes, so we add 3611 call graph edges explicitly there, but for onode, we create a 3612 fresh function, so we may as well just issue the calls and 3613 then rebuild all cgraph edges. */ 3614 // cgraph_edge::rebuild_edges (); 3615 onode->analyze (); 3616 // inline_analyze_function (onode); 3617 3618 pop_cfun (); 3619 } 3620 } 3621 3622 return 0; 3623 } 3624 3625 simple_ipa_opt_pass * 3626 make_pass_ipa_strub (gcc::context *ctxt) 3627 { 3628 return new pass_ipa_strub (ctxt); 3629 } 3630 3631 #include "gt-ipa-strub.h" 3632