builtins.c revision 122190
1/* Expand builtin functions. 2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 2, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING. If not, write to the Free 19Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2002111-1307, USA. */ 21 22#include "config.h" 23#include "system.h" 24#include "machmode.h" 25#include "real.h" 26#include "rtl.h" 27#include "tree.h" 28#include "flags.h" 29#include "regs.h" 30#include "hard-reg-set.h" 31#include "except.h" 32#include "function.h" 33#include "insn-config.h" 34#include "expr.h" 35#include "optabs.h" 36#include "libfuncs.h" 37#include "recog.h" 38#include "output.h" 39#include "typeclass.h" 40#include "toplev.h" 41#include "predict.h" 42#include "tm_p.h" 43#include "target.h" 44#include "langhooks.h" 45 46#define CALLED_AS_BUILT_IN(NODE) \ 47 (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10)) 48 49/* Register mappings for target machines without register windows. */ 50#ifndef INCOMING_REGNO 51#define INCOMING_REGNO(OUT) (OUT) 52#endif 53#ifndef OUTGOING_REGNO 54#define OUTGOING_REGNO(IN) (IN) 55#endif 56 57#ifndef PAD_VARARGS_DOWN 58#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN 59#endif 60 61/* Define the names of the builtin function types and codes. */ 62const char *const built_in_class_names[4] 63 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"}; 64 65#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT) STRINGX(X), 66const char *const built_in_names[(int) END_BUILTINS] = 67{ 68#include "builtins.def" 69}; 70#undef DEF_BUILTIN 71 72/* Setup an array of _DECL trees, make sure each element is 73 initialized to NULL_TREE. */ 74tree built_in_decls[(int) END_BUILTINS]; 75 76static int get_pointer_alignment PARAMS ((tree, unsigned int)); 77static tree c_strlen PARAMS ((tree)); 78static const char *c_getstr PARAMS ((tree)); 79static rtx c_readstr PARAMS ((const char *, 80 enum machine_mode)); 81static int target_char_cast PARAMS ((tree, char *)); 82static rtx get_memory_rtx PARAMS ((tree)); 83static int apply_args_size PARAMS ((void)); 84static int apply_result_size PARAMS ((void)); 85#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return) 86static rtx result_vector PARAMS ((int, rtx)); 87#endif 88static rtx expand_builtin_setjmp PARAMS ((tree, rtx)); 89static void expand_builtin_prefetch PARAMS ((tree)); 90static rtx expand_builtin_apply_args PARAMS ((void)); 91static rtx expand_builtin_apply_args_1 PARAMS ((void)); 92static rtx expand_builtin_apply PARAMS ((rtx, rtx, rtx)); 93static void expand_builtin_return PARAMS ((rtx)); 94static enum type_class type_to_class PARAMS ((tree)); 95static rtx expand_builtin_classify_type PARAMS ((tree)); 96static rtx expand_builtin_mathfn PARAMS ((tree, rtx, rtx)); 97static rtx expand_builtin_constant_p PARAMS ((tree)); 98static rtx expand_builtin_args_info PARAMS ((tree)); 99static rtx expand_builtin_next_arg PARAMS ((tree)); 100static rtx expand_builtin_va_start PARAMS ((tree)); 101static rtx expand_builtin_va_end PARAMS ((tree)); 102static rtx expand_builtin_va_copy PARAMS ((tree)); 103static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx, 104 enum machine_mode)); 105static rtx expand_builtin_strcmp PARAMS ((tree, rtx, 106 enum machine_mode)); 107static rtx expand_builtin_strncmp PARAMS ((tree, rtx, 108 enum machine_mode)); 109static rtx builtin_memcpy_read_str PARAMS ((PTR, HOST_WIDE_INT, 110 enum machine_mode)); 111static rtx expand_builtin_strcat PARAMS ((tree, rtx, 112 enum machine_mode)); 113static rtx expand_builtin_strncat PARAMS ((tree, rtx, 114 enum machine_mode)); 115static rtx expand_builtin_strspn PARAMS ((tree, rtx, 116 enum machine_mode)); 117static rtx expand_builtin_strcspn PARAMS ((tree, rtx, 118 enum machine_mode)); 119static rtx expand_builtin_memcpy PARAMS ((tree, rtx, 120 enum machine_mode)); 121static rtx expand_builtin_strcpy PARAMS ((tree, rtx, 122 enum machine_mode)); 123static rtx builtin_strncpy_read_str PARAMS ((PTR, HOST_WIDE_INT, 124 enum machine_mode)); 125static rtx expand_builtin_strncpy PARAMS ((tree, rtx, 126 enum machine_mode)); 127static rtx builtin_memset_read_str PARAMS ((PTR, HOST_WIDE_INT, 128 enum machine_mode)); 129static rtx builtin_memset_gen_str PARAMS ((PTR, HOST_WIDE_INT, 130 enum machine_mode)); 131static rtx expand_builtin_memset PARAMS ((tree, rtx, 132 enum machine_mode)); 133static rtx expand_builtin_bzero PARAMS ((tree)); 134static rtx expand_builtin_strlen PARAMS ((tree, rtx)); 135static rtx expand_builtin_strstr PARAMS ((tree, rtx, 136 enum machine_mode)); 137static rtx expand_builtin_strpbrk PARAMS ((tree, rtx, 138 enum machine_mode)); 139static rtx expand_builtin_strchr PARAMS ((tree, rtx, 140 enum machine_mode)); 141static rtx expand_builtin_strrchr PARAMS ((tree, rtx, 142 enum machine_mode)); 143static rtx expand_builtin_alloca PARAMS ((tree, rtx)); 144static rtx expand_builtin_ffs PARAMS ((tree, rtx, rtx)); 145static rtx expand_builtin_frame_address PARAMS ((tree)); 146static rtx expand_builtin_fputs PARAMS ((tree, int, int)); 147static tree stabilize_va_list PARAMS ((tree, int)); 148static rtx expand_builtin_expect PARAMS ((tree, rtx)); 149static tree fold_builtin_constant_p PARAMS ((tree)); 150static tree fold_builtin_classify_type PARAMS ((tree)); 151static tree fold_builtin_inf PARAMS ((tree, int)); 152static tree fold_builtin_nan PARAMS ((tree, tree, int)); 153static tree build_function_call_expr PARAMS ((tree, tree)); 154static int validate_arglist PARAMS ((tree, ...)); 155 156/* Return the alignment in bits of EXP, a pointer valued expression. 157 But don't return more than MAX_ALIGN no matter what. 158 The alignment returned is, by default, the alignment of the thing that 159 EXP points to. If it is not a POINTER_TYPE, 0 is returned. 160 161 Otherwise, look at the expression to see if we can do better, i.e., if the 162 expression is actually pointing at an object whose alignment is tighter. */ 163 164static int 165get_pointer_alignment (exp, max_align) 166 tree exp; 167 unsigned int max_align; 168{ 169 unsigned int align, inner; 170 171 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE) 172 return 0; 173 174 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp))); 175 align = MIN (align, max_align); 176 177 while (1) 178 { 179 switch (TREE_CODE (exp)) 180 { 181 case NOP_EXPR: 182 case CONVERT_EXPR: 183 case NON_LVALUE_EXPR: 184 exp = TREE_OPERAND (exp, 0); 185 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE) 186 return align; 187 188 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp))); 189 align = MIN (inner, max_align); 190 break; 191 192 case PLUS_EXPR: 193 /* If sum of pointer + int, restrict our maximum alignment to that 194 imposed by the integer. If not, we can't do any better than 195 ALIGN. */ 196 if (! host_integerp (TREE_OPERAND (exp, 1), 1)) 197 return align; 198 199 while (((tree_low_cst (TREE_OPERAND (exp, 1), 1)) 200 & (max_align / BITS_PER_UNIT - 1)) 201 != 0) 202 max_align >>= 1; 203 204 exp = TREE_OPERAND (exp, 0); 205 break; 206 207 case ADDR_EXPR: 208 /* See what we are pointing at and look at its alignment. */ 209 exp = TREE_OPERAND (exp, 0); 210 if (TREE_CODE (exp) == FUNCTION_DECL) 211 align = FUNCTION_BOUNDARY; 212 else if (DECL_P (exp)) 213 align = DECL_ALIGN (exp); 214#ifdef CONSTANT_ALIGNMENT 215 else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c') 216 align = CONSTANT_ALIGNMENT (exp, align); 217#endif 218 return MIN (align, max_align); 219 220 default: 221 return align; 222 } 223 } 224} 225 226/* Compute the length of a C string. TREE_STRING_LENGTH is not the right 227 way, because it could contain a zero byte in the middle. 228 TREE_STRING_LENGTH is the size of the character array, not the string. 229 230 The value returned is of type `ssizetype'. 231 232 Unfortunately, string_constant can't access the values of const char 233 arrays with initializers, so neither can we do so here. */ 234 235static tree 236c_strlen (src) 237 tree src; 238{ 239 tree offset_node; 240 HOST_WIDE_INT offset; 241 int max; 242 const char *ptr; 243 244 src = string_constant (src, &offset_node); 245 if (src == 0) 246 return 0; 247 248 max = TREE_STRING_LENGTH (src) - 1; 249 ptr = TREE_STRING_POINTER (src); 250 251 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST) 252 { 253 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't 254 compute the offset to the following null if we don't know where to 255 start searching for it. */ 256 int i; 257 258 for (i = 0; i < max; i++) 259 if (ptr[i] == 0) 260 return 0; 261 262 /* We don't know the starting offset, but we do know that the string 263 has no internal zero bytes. We can assume that the offset falls 264 within the bounds of the string; otherwise, the programmer deserves 265 what he gets. Subtract the offset from the length of the string, 266 and return that. This would perhaps not be valid if we were dealing 267 with named arrays in addition to literal string constants. */ 268 269 return size_diffop (size_int (max), offset_node); 270 } 271 272 /* We have a known offset into the string. Start searching there for 273 a null character if we can represent it as a single HOST_WIDE_INT. */ 274 if (offset_node == 0) 275 offset = 0; 276 else if (! host_integerp (offset_node, 0)) 277 offset = -1; 278 else 279 offset = tree_low_cst (offset_node, 0); 280 281 /* If the offset is known to be out of bounds, warn, and call strlen at 282 runtime. */ 283 if (offset < 0 || offset > max) 284 { 285 warning ("offset outside bounds of constant string"); 286 return 0; 287 } 288 289 /* Use strlen to search for the first zero byte. Since any strings 290 constructed with build_string will have nulls appended, we win even 291 if we get handed something like (char[4])"abcd". 292 293 Since OFFSET is our starting index into the string, no further 294 calculation is needed. */ 295 return ssize_int (strlen (ptr + offset)); 296} 297 298/* Return a char pointer for a C string if it is a string constant 299 or sum of string constant and integer constant. */ 300 301static const char * 302c_getstr (src) 303 tree src; 304{ 305 tree offset_node; 306 307 src = string_constant (src, &offset_node); 308 if (src == 0) 309 return 0; 310 311 if (offset_node == 0) 312 return TREE_STRING_POINTER (src); 313 else if (!host_integerp (offset_node, 1) 314 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0) 315 return 0; 316 317 return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1); 318} 319 320/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading 321 GET_MODE_BITSIZE (MODE) bits from string constant STR. */ 322 323static rtx 324c_readstr (str, mode) 325 const char *str; 326 enum machine_mode mode; 327{ 328 HOST_WIDE_INT c[2]; 329 HOST_WIDE_INT ch; 330 unsigned int i, j; 331 332 if (GET_MODE_CLASS (mode) != MODE_INT) 333 abort (); 334 c[0] = 0; 335 c[1] = 0; 336 ch = 1; 337 for (i = 0; i < GET_MODE_SIZE (mode); i++) 338 { 339 j = i; 340 if (WORDS_BIG_ENDIAN) 341 j = GET_MODE_SIZE (mode) - i - 1; 342 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN 343 && GET_MODE_SIZE (mode) > UNITS_PER_WORD) 344 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1; 345 j *= BITS_PER_UNIT; 346 if (j > 2 * HOST_BITS_PER_WIDE_INT) 347 abort (); 348 if (ch) 349 ch = (unsigned char) str[i]; 350 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT); 351 } 352 return immed_double_const (c[0], c[1], mode); 353} 354 355/* Cast a target constant CST to target CHAR and if that value fits into 356 host char type, return zero and put that value into variable pointed by 357 P. */ 358 359static int 360target_char_cast (cst, p) 361 tree cst; 362 char *p; 363{ 364 unsigned HOST_WIDE_INT val, hostval; 365 366 if (!host_integerp (cst, 1) 367 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT) 368 return 1; 369 370 val = tree_low_cst (cst, 1); 371 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT) 372 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1; 373 374 hostval = val; 375 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT) 376 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1; 377 378 if (val != hostval) 379 return 1; 380 381 *p = hostval; 382 return 0; 383} 384 385/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT 386 times to get the address of either a higher stack frame, or a return 387 address located within it (depending on FNDECL_CODE). */ 388 389rtx 390expand_builtin_return_addr (fndecl_code, count, tem) 391 enum built_in_function fndecl_code; 392 int count; 393 rtx tem; 394{ 395 int i; 396 397 /* Some machines need special handling before we can access 398 arbitrary frames. For example, on the sparc, we must first flush 399 all register windows to the stack. */ 400#ifdef SETUP_FRAME_ADDRESSES 401 if (count > 0) 402 SETUP_FRAME_ADDRESSES (); 403#endif 404 405 /* On the sparc, the return address is not in the frame, it is in a 406 register. There is no way to access it off of the current frame 407 pointer, but it can be accessed off the previous frame pointer by 408 reading the value from the register window save area. */ 409#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME 410 if (fndecl_code == BUILT_IN_RETURN_ADDRESS) 411 count--; 412#endif 413 414 /* Scan back COUNT frames to the specified frame. */ 415 for (i = 0; i < count; i++) 416 { 417 /* Assume the dynamic chain pointer is in the word that the 418 frame address points to, unless otherwise specified. */ 419#ifdef DYNAMIC_CHAIN_ADDRESS 420 tem = DYNAMIC_CHAIN_ADDRESS (tem); 421#endif 422 tem = memory_address (Pmode, tem); 423 tem = gen_rtx_MEM (Pmode, tem); 424 set_mem_alias_set (tem, get_frame_alias_set ()); 425 tem = copy_to_reg (tem); 426 } 427 428 /* For __builtin_frame_address, return what we've got. */ 429 if (fndecl_code == BUILT_IN_FRAME_ADDRESS) 430 return tem; 431 432 /* For __builtin_return_address, Get the return address from that 433 frame. */ 434#ifdef RETURN_ADDR_RTX 435 tem = RETURN_ADDR_RTX (count, tem); 436#else 437 tem = memory_address (Pmode, 438 plus_constant (tem, GET_MODE_SIZE (Pmode))); 439 tem = gen_rtx_MEM (Pmode, tem); 440 set_mem_alias_set (tem, get_frame_alias_set ()); 441#endif 442 return tem; 443} 444 445/* Alias set used for setjmp buffer. */ 446static HOST_WIDE_INT setjmp_alias_set = -1; 447 448/* Construct the leading half of a __builtin_setjmp call. Control will 449 return to RECEIVER_LABEL. This is used directly by sjlj exception 450 handling code. */ 451 452void 453expand_builtin_setjmp_setup (buf_addr, receiver_label) 454 rtx buf_addr; 455 rtx receiver_label; 456{ 457 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); 458 rtx stack_save; 459 rtx mem; 460 461 if (setjmp_alias_set == -1) 462 setjmp_alias_set = new_alias_set (); 463 464#ifdef POINTERS_EXTEND_UNSIGNED 465 if (GET_MODE (buf_addr) != Pmode) 466 buf_addr = convert_memory_address (Pmode, buf_addr); 467#endif 468 469 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX)); 470 471 emit_queue (); 472 473 /* We store the frame pointer and the address of receiver_label in 474 the buffer and use the rest of it for the stack save area, which 475 is machine-dependent. */ 476 477#ifndef BUILTIN_SETJMP_FRAME_VALUE 478#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx 479#endif 480 481 mem = gen_rtx_MEM (Pmode, buf_addr); 482 set_mem_alias_set (mem, setjmp_alias_set); 483 emit_move_insn (mem, BUILTIN_SETJMP_FRAME_VALUE); 484 485 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))), 486 set_mem_alias_set (mem, setjmp_alias_set); 487 488 emit_move_insn (validize_mem (mem), 489 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label))); 490 491 stack_save = gen_rtx_MEM (sa_mode, 492 plus_constant (buf_addr, 493 2 * GET_MODE_SIZE (Pmode))); 494 set_mem_alias_set (stack_save, setjmp_alias_set); 495 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX); 496 497 /* If there is further processing to do, do it. */ 498#ifdef HAVE_builtin_setjmp_setup 499 if (HAVE_builtin_setjmp_setup) 500 emit_insn (gen_builtin_setjmp_setup (buf_addr)); 501#endif 502 503 /* Tell optimize_save_area_alloca that extra work is going to 504 need to go on during alloca. */ 505 current_function_calls_setjmp = 1; 506 507 /* Set this so all the registers get saved in our frame; we need to be 508 able to copy the saved values for any registers from frames we unwind. */ 509 current_function_has_nonlocal_label = 1; 510} 511 512/* Construct the trailing part of a __builtin_setjmp call. 513 This is used directly by sjlj exception handling code. */ 514 515void 516expand_builtin_setjmp_receiver (receiver_label) 517 rtx receiver_label ATTRIBUTE_UNUSED; 518{ 519 /* Clobber the FP when we get here, so we have to make sure it's 520 marked as used by this function. */ 521 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); 522 523 /* Mark the static chain as clobbered here so life information 524 doesn't get messed up for it. */ 525 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx)); 526 527 /* Now put in the code to restore the frame pointer, and argument 528 pointer, if needed. The code below is from expand_end_bindings 529 in stmt.c; see detailed documentation there. */ 530#ifdef HAVE_nonlocal_goto 531 if (! HAVE_nonlocal_goto) 532#endif 533 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx); 534 535#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM 536 if (fixed_regs[ARG_POINTER_REGNUM]) 537 { 538#ifdef ELIMINABLE_REGS 539 size_t i; 540 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS; 541 542 for (i = 0; i < ARRAY_SIZE (elim_regs); i++) 543 if (elim_regs[i].from == ARG_POINTER_REGNUM 544 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM) 545 break; 546 547 if (i == ARRAY_SIZE (elim_regs)) 548#endif 549 { 550 /* Now restore our arg pointer from the address at which it 551 was saved in our stack frame. */ 552 emit_move_insn (virtual_incoming_args_rtx, 553 copy_to_reg (get_arg_pointer_save_area (cfun))); 554 } 555 } 556#endif 557 558#ifdef HAVE_builtin_setjmp_receiver 559 if (HAVE_builtin_setjmp_receiver) 560 emit_insn (gen_builtin_setjmp_receiver (receiver_label)); 561 else 562#endif 563#ifdef HAVE_nonlocal_goto_receiver 564 if (HAVE_nonlocal_goto_receiver) 565 emit_insn (gen_nonlocal_goto_receiver ()); 566 else 567#endif 568 { /* Nothing */ } 569 570 /* @@@ This is a kludge. Not all machine descriptions define a blockage 571 insn, but we must not allow the code we just generated to be reordered 572 by scheduling. Specifically, the update of the frame pointer must 573 happen immediately, not later. So emit an ASM_INPUT to act as blockage 574 insn. */ 575 emit_insn (gen_rtx_ASM_INPUT (VOIDmode, "")); 576} 577 578/* __builtin_setjmp is passed a pointer to an array of five words (not 579 all will be used on all machines). It operates similarly to the C 580 library function of the same name, but is more efficient. Much of 581 the code below (and for longjmp) is copied from the handling of 582 non-local gotos. 583 584 NOTE: This is intended for use by GNAT and the exception handling 585 scheme in the compiler and will only work in the method used by 586 them. */ 587 588static rtx 589expand_builtin_setjmp (arglist, target) 590 tree arglist; 591 rtx target; 592{ 593 rtx buf_addr, next_lab, cont_lab; 594 595 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) 596 return NULL_RTX; 597 598 if (target == 0 || GET_CODE (target) != REG 599 || REGNO (target) < FIRST_PSEUDO_REGISTER) 600 target = gen_reg_rtx (TYPE_MODE (integer_type_node)); 601 602 buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0); 603 604 next_lab = gen_label_rtx (); 605 cont_lab = gen_label_rtx (); 606 607 expand_builtin_setjmp_setup (buf_addr, next_lab); 608 609 /* Set TARGET to zero and branch to the continue label. */ 610 emit_move_insn (target, const0_rtx); 611 emit_jump_insn (gen_jump (cont_lab)); 612 emit_barrier (); 613 emit_label (next_lab); 614 615 expand_builtin_setjmp_receiver (next_lab); 616 617 /* Set TARGET to one. */ 618 emit_move_insn (target, const1_rtx); 619 emit_label (cont_lab); 620 621 /* Tell flow about the strange goings on. Putting `next_lab' on 622 `nonlocal_goto_handler_labels' to indicates that function 623 calls may traverse the arc back to this label. */ 624 625 current_function_has_nonlocal_label = 1; 626 nonlocal_goto_handler_labels 627 = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels); 628 629 return target; 630} 631 632/* __builtin_longjmp is passed a pointer to an array of five words (not 633 all will be used on all machines). It operates similarly to the C 634 library function of the same name, but is more efficient. Much of 635 the code below is copied from the handling of non-local gotos. 636 637 NOTE: This is intended for use by GNAT and the exception handling 638 scheme in the compiler and will only work in the method used by 639 them. */ 640 641void 642expand_builtin_longjmp (buf_addr, value) 643 rtx buf_addr, value; 644{ 645 rtx fp, lab, stack, insn, last; 646 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); 647 648 if (setjmp_alias_set == -1) 649 setjmp_alias_set = new_alias_set (); 650 651#ifdef POINTERS_EXTEND_UNSIGNED 652 if (GET_MODE (buf_addr) != Pmode) 653 buf_addr = convert_memory_address (Pmode, buf_addr); 654#endif 655 656 buf_addr = force_reg (Pmode, buf_addr); 657 658 /* We used to store value in static_chain_rtx, but that fails if pointers 659 are smaller than integers. We instead require that the user must pass 660 a second argument of 1, because that is what builtin_setjmp will 661 return. This also makes EH slightly more efficient, since we are no 662 longer copying around a value that we don't care about. */ 663 if (value != const1_rtx) 664 abort (); 665 666 current_function_calls_longjmp = 1; 667 668 last = get_last_insn (); 669#ifdef HAVE_builtin_longjmp 670 if (HAVE_builtin_longjmp) 671 emit_insn (gen_builtin_longjmp (buf_addr)); 672 else 673#endif 674 { 675 fp = gen_rtx_MEM (Pmode, buf_addr); 676 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr, 677 GET_MODE_SIZE (Pmode))); 678 679 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr, 680 2 * GET_MODE_SIZE (Pmode))); 681 set_mem_alias_set (fp, setjmp_alias_set); 682 set_mem_alias_set (lab, setjmp_alias_set); 683 set_mem_alias_set (stack, setjmp_alias_set); 684 685 /* Pick up FP, label, and SP from the block and jump. This code is 686 from expand_goto in stmt.c; see there for detailed comments. */ 687#if HAVE_nonlocal_goto 688 if (HAVE_nonlocal_goto) 689 /* We have to pass a value to the nonlocal_goto pattern that will 690 get copied into the static_chain pointer, but it does not matter 691 what that value is, because builtin_setjmp does not use it. */ 692 emit_insn (gen_nonlocal_goto (value, lab, stack, fp)); 693 else 694#endif 695 { 696 lab = copy_to_reg (lab); 697 698 emit_move_insn (hard_frame_pointer_rtx, fp); 699 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); 700 701 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); 702 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); 703 emit_indirect_jump (lab); 704 } 705 } 706 707 /* Search backwards and mark the jump insn as a non-local goto. 708 Note that this precludes the use of __builtin_longjmp to a 709 __builtin_setjmp target in the same function. However, we've 710 already cautioned the user that these functions are for 711 internal exception handling use only. */ 712 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn)) 713 { 714 if (insn == last) 715 abort (); 716 if (GET_CODE (insn) == JUMP_INSN) 717 { 718 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx, 719 REG_NOTES (insn)); 720 break; 721 } 722 else if (GET_CODE (insn) == CALL_INSN) 723 break; 724 } 725} 726 727/* Expand a call to __builtin_prefetch. For a target that does not support 728 data prefetch, evaluate the memory address argument in case it has side 729 effects. */ 730 731static void 732expand_builtin_prefetch (arglist) 733 tree arglist; 734{ 735 tree arg0, arg1, arg2; 736 rtx op0, op1, op2; 737 738 if (!validate_arglist (arglist, POINTER_TYPE, 0)) 739 return; 740 741 arg0 = TREE_VALUE (arglist); 742 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to 743 zero (read) and argument 2 (locality) defaults to 3 (high degree of 744 locality). */ 745 if (TREE_CHAIN (arglist)) 746 { 747 arg1 = TREE_VALUE (TREE_CHAIN (arglist)); 748 if (TREE_CHAIN (TREE_CHAIN (arglist))) 749 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); 750 else 751 arg2 = build_int_2 (3, 0); 752 } 753 else 754 { 755 arg1 = integer_zero_node; 756 arg2 = build_int_2 (3, 0); 757 } 758 759 /* Argument 0 is an address. */ 760 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL); 761 762 /* Argument 1 (read/write flag) must be a compile-time constant int. */ 763 if (TREE_CODE (arg1) != INTEGER_CST) 764 { 765 error ("second arg to `__builtin_prefetch' must be a constant"); 766 arg1 = integer_zero_node; 767 } 768 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); 769 /* Argument 1 must be either zero or one. */ 770 if (INTVAL (op1) != 0 && INTVAL (op1) != 1) 771 { 772 warning ("invalid second arg to __builtin_prefetch; using zero"); 773 op1 = const0_rtx; 774 } 775 776 /* Argument 2 (locality) must be a compile-time constant int. */ 777 if (TREE_CODE (arg2) != INTEGER_CST) 778 { 779 error ("third arg to `__builtin_prefetch' must be a constant"); 780 arg2 = integer_zero_node; 781 } 782 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0); 783 /* Argument 2 must be 0, 1, 2, or 3. */ 784 if (INTVAL (op2) < 0 || INTVAL (op2) > 3) 785 { 786 warning ("invalid third arg to __builtin_prefetch; using zero"); 787 op2 = const0_rtx; 788 } 789 790#ifdef HAVE_prefetch 791 if (HAVE_prefetch) 792 { 793 if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate) 794 (op0, 795 insn_data[(int) CODE_FOR_prefetch].operand[0].mode)) 796 || (GET_MODE(op0) != Pmode)) 797 { 798#ifdef POINTERS_EXTEND_UNSIGNED 799 if (GET_MODE(op0) != Pmode) 800 op0 = convert_memory_address (Pmode, op0); 801#endif 802 op0 = force_reg (Pmode, op0); 803 } 804 emit_insn (gen_prefetch (op0, op1, op2)); 805 } 806 else 807#endif 808 op0 = protect_from_queue (op0, 0); 809 /* Don't do anything with direct references to volatile memory, but 810 generate code to handle other side effects. */ 811 if (GET_CODE (op0) != MEM && side_effects_p (op0)) 812 emit_insn (op0); 813} 814 815/* Get a MEM rtx for expression EXP which is the address of an operand 816 to be used to be used in a string instruction (cmpstrsi, movstrsi, ..). */ 817 818static rtx 819get_memory_rtx (exp) 820 tree exp; 821{ 822 rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_SUM); 823 rtx mem; 824 825#ifdef POINTERS_EXTEND_UNSIGNED 826 if (GET_MODE (addr) != Pmode) 827 addr = convert_memory_address (Pmode, addr); 828#endif 829 830 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr)); 831 832 /* Get an expression we can use to find the attributes to assign to MEM. 833 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if 834 we can. First remove any nops. */ 835 while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR 836 || TREE_CODE (exp) == NON_LVALUE_EXPR) 837 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0)))) 838 exp = TREE_OPERAND (exp, 0); 839 840 if (TREE_CODE (exp) == ADDR_EXPR) 841 { 842 exp = TREE_OPERAND (exp, 0); 843 set_mem_attributes (mem, exp, 0); 844 } 845 else if (POINTER_TYPE_P (TREE_TYPE (exp))) 846 { 847 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp); 848 /* memcpy, memset and other builtin stringops can alias with anything. */ 849 set_mem_alias_set (mem, 0); 850 } 851 852 return mem; 853} 854 855/* Built-in functions to perform an untyped call and return. */ 856 857/* For each register that may be used for calling a function, this 858 gives a mode used to copy the register's value. VOIDmode indicates 859 the register is not used for calling a function. If the machine 860 has register windows, this gives only the outbound registers. 861 INCOMING_REGNO gives the corresponding inbound register. */ 862static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER]; 863 864/* For each register that may be used for returning values, this gives 865 a mode used to copy the register's value. VOIDmode indicates the 866 register is not used for returning values. If the machine has 867 register windows, this gives only the outbound registers. 868 INCOMING_REGNO gives the corresponding inbound register. */ 869static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER]; 870 871/* For each register that may be used for calling a function, this 872 gives the offset of that register into the block returned by 873 __builtin_apply_args. 0 indicates that the register is not 874 used for calling a function. */ 875static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER]; 876 877/* Return the offset of register REGNO into the block returned by 878 __builtin_apply_args. This is not declared static, since it is 879 needed in objc-act.c. */ 880 881int 882apply_args_register_offset (regno) 883 int regno; 884{ 885 apply_args_size (); 886 887 /* Arguments are always put in outgoing registers (in the argument 888 block) if such make sense. */ 889#ifdef OUTGOING_REGNO 890 regno = OUTGOING_REGNO (regno); 891#endif 892 return apply_args_reg_offset[regno]; 893} 894 895/* Return the size required for the block returned by __builtin_apply_args, 896 and initialize apply_args_mode. */ 897 898static int 899apply_args_size () 900{ 901 static int size = -1; 902 int align; 903 unsigned int regno; 904 enum machine_mode mode; 905 906 /* The values computed by this function never change. */ 907 if (size < 0) 908 { 909 /* The first value is the incoming arg-pointer. */ 910 size = GET_MODE_SIZE (Pmode); 911 912 /* The second value is the structure value address unless this is 913 passed as an "invisible" first argument. */ 914 if (struct_value_rtx) 915 size += GET_MODE_SIZE (Pmode); 916 917 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 918 if (FUNCTION_ARG_REGNO_P (regno)) 919 { 920 /* Search for the proper mode for copying this register's 921 value. I'm not sure this is right, but it works so far. */ 922 enum machine_mode best_mode = VOIDmode; 923 924 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); 925 mode != VOIDmode; 926 mode = GET_MODE_WIDER_MODE (mode)) 927 if (HARD_REGNO_MODE_OK (regno, mode) 928 && HARD_REGNO_NREGS (regno, mode) == 1) 929 best_mode = mode; 930 931 if (best_mode == VOIDmode) 932 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); 933 mode != VOIDmode; 934 mode = GET_MODE_WIDER_MODE (mode)) 935 if (HARD_REGNO_MODE_OK (regno, mode) 936 && have_insn_for (SET, mode)) 937 best_mode = mode; 938 939 if (best_mode == VOIDmode) 940 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT); 941 mode != VOIDmode; 942 mode = GET_MODE_WIDER_MODE (mode)) 943 if (HARD_REGNO_MODE_OK (regno, mode) 944 && have_insn_for (SET, mode)) 945 best_mode = mode; 946 947 if (best_mode == VOIDmode) 948 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT); 949 mode != VOIDmode; 950 mode = GET_MODE_WIDER_MODE (mode)) 951 if (HARD_REGNO_MODE_OK (regno, mode) 952 && have_insn_for (SET, mode)) 953 best_mode = mode; 954 955 mode = best_mode; 956 if (mode == VOIDmode) 957 abort (); 958 959 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; 960 if (size % align != 0) 961 size = CEIL (size, align) * align; 962 apply_args_reg_offset[regno] = size; 963 size += GET_MODE_SIZE (mode); 964 apply_args_mode[regno] = mode; 965 } 966 else 967 { 968 apply_args_mode[regno] = VOIDmode; 969 apply_args_reg_offset[regno] = 0; 970 } 971 } 972 return size; 973} 974 975/* Return the size required for the block returned by __builtin_apply, 976 and initialize apply_result_mode. */ 977 978static int 979apply_result_size () 980{ 981 static int size = -1; 982 int align, regno; 983 enum machine_mode mode; 984 985 /* The values computed by this function never change. */ 986 if (size < 0) 987 { 988 size = 0; 989 990 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 991 if (FUNCTION_VALUE_REGNO_P (regno)) 992 { 993 /* Search for the proper mode for copying this register's 994 value. I'm not sure this is right, but it works so far. */ 995 enum machine_mode best_mode = VOIDmode; 996 997 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); 998 mode != TImode; 999 mode = GET_MODE_WIDER_MODE (mode)) 1000 if (HARD_REGNO_MODE_OK (regno, mode)) 1001 best_mode = mode; 1002 1003 if (best_mode == VOIDmode) 1004 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); 1005 mode != VOIDmode; 1006 mode = GET_MODE_WIDER_MODE (mode)) 1007 if (HARD_REGNO_MODE_OK (regno, mode) 1008 && have_insn_for (SET, mode)) 1009 best_mode = mode; 1010 1011 if (best_mode == VOIDmode) 1012 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT); 1013 mode != VOIDmode; 1014 mode = GET_MODE_WIDER_MODE (mode)) 1015 if (HARD_REGNO_MODE_OK (regno, mode) 1016 && have_insn_for (SET, mode)) 1017 best_mode = mode; 1018 1019 if (best_mode == VOIDmode) 1020 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT); 1021 mode != VOIDmode; 1022 mode = GET_MODE_WIDER_MODE (mode)) 1023 if (HARD_REGNO_MODE_OK (regno, mode) 1024 && have_insn_for (SET, mode)) 1025 best_mode = mode; 1026 1027 mode = best_mode; 1028 if (mode == VOIDmode) 1029 abort (); 1030 1031 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; 1032 if (size % align != 0) 1033 size = CEIL (size, align) * align; 1034 size += GET_MODE_SIZE (mode); 1035 apply_result_mode[regno] = mode; 1036 } 1037 else 1038 apply_result_mode[regno] = VOIDmode; 1039 1040 /* Allow targets that use untyped_call and untyped_return to override 1041 the size so that machine-specific information can be stored here. */ 1042#ifdef APPLY_RESULT_SIZE 1043 size = APPLY_RESULT_SIZE; 1044#endif 1045 } 1046 return size; 1047} 1048 1049#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return) 1050/* Create a vector describing the result block RESULT. If SAVEP is true, 1051 the result block is used to save the values; otherwise it is used to 1052 restore the values. */ 1053 1054static rtx 1055result_vector (savep, result) 1056 int savep; 1057 rtx result; 1058{ 1059 int regno, size, align, nelts; 1060 enum machine_mode mode; 1061 rtx reg, mem; 1062 rtx *savevec = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx)); 1063 1064 size = nelts = 0; 1065 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 1066 if ((mode = apply_result_mode[regno]) != VOIDmode) 1067 { 1068 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; 1069 if (size % align != 0) 1070 size = CEIL (size, align) * align; 1071 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno)); 1072 mem = adjust_address (result, mode, size); 1073 savevec[nelts++] = (savep 1074 ? gen_rtx_SET (VOIDmode, mem, reg) 1075 : gen_rtx_SET (VOIDmode, reg, mem)); 1076 size += GET_MODE_SIZE (mode); 1077 } 1078 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec)); 1079} 1080#endif /* HAVE_untyped_call or HAVE_untyped_return */ 1081 1082/* Save the state required to perform an untyped call with the same 1083 arguments as were passed to the current function. */ 1084 1085static rtx 1086expand_builtin_apply_args_1 () 1087{ 1088 rtx registers; 1089 int size, align, regno; 1090 enum machine_mode mode; 1091 1092 /* Create a block where the arg-pointer, structure value address, 1093 and argument registers can be saved. */ 1094 registers = assign_stack_local (BLKmode, apply_args_size (), -1); 1095 1096 /* Walk past the arg-pointer and structure value address. */ 1097 size = GET_MODE_SIZE (Pmode); 1098 if (struct_value_rtx) 1099 size += GET_MODE_SIZE (Pmode); 1100 1101 /* Save each register used in calling a function to the block. */ 1102 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 1103 if ((mode = apply_args_mode[regno]) != VOIDmode) 1104 { 1105 rtx tem; 1106 1107 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; 1108 if (size % align != 0) 1109 size = CEIL (size, align) * align; 1110 1111 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno)); 1112 1113 emit_move_insn (adjust_address (registers, mode, size), tem); 1114 size += GET_MODE_SIZE (mode); 1115 } 1116 1117 /* Save the arg pointer to the block. */ 1118 emit_move_insn (adjust_address (registers, Pmode, 0), 1119 copy_to_reg (virtual_incoming_args_rtx)); 1120 size = GET_MODE_SIZE (Pmode); 1121 1122 /* Save the structure value address unless this is passed as an 1123 "invisible" first argument. */ 1124 if (struct_value_incoming_rtx) 1125 { 1126 emit_move_insn (adjust_address (registers, Pmode, size), 1127 copy_to_reg (struct_value_incoming_rtx)); 1128 size += GET_MODE_SIZE (Pmode); 1129 } 1130 1131 /* Return the address of the block. */ 1132 return copy_addr_to_reg (XEXP (registers, 0)); 1133} 1134 1135/* __builtin_apply_args returns block of memory allocated on 1136 the stack into which is stored the arg pointer, structure 1137 value address, static chain, and all the registers that might 1138 possibly be used in performing a function call. The code is 1139 moved to the start of the function so the incoming values are 1140 saved. */ 1141 1142static rtx 1143expand_builtin_apply_args () 1144{ 1145 /* Don't do __builtin_apply_args more than once in a function. 1146 Save the result of the first call and reuse it. */ 1147 if (apply_args_value != 0) 1148 return apply_args_value; 1149 { 1150 /* When this function is called, it means that registers must be 1151 saved on entry to this function. So we migrate the 1152 call to the first insn of this function. */ 1153 rtx temp; 1154 rtx seq; 1155 1156 start_sequence (); 1157 temp = expand_builtin_apply_args_1 (); 1158 seq = get_insns (); 1159 end_sequence (); 1160 1161 apply_args_value = temp; 1162 1163 /* Put the insns after the NOTE that starts the function. 1164 If this is inside a start_sequence, make the outer-level insn 1165 chain current, so the code is placed at the start of the 1166 function. */ 1167 push_topmost_sequence (); 1168 emit_insn_before (seq, NEXT_INSN (get_insns ())); 1169 pop_topmost_sequence (); 1170 return temp; 1171 } 1172} 1173 1174/* Perform an untyped call and save the state required to perform an 1175 untyped return of whatever value was returned by the given function. */ 1176 1177static rtx 1178expand_builtin_apply (function, arguments, argsize) 1179 rtx function, arguments, argsize; 1180{ 1181 int size, align, regno; 1182 enum machine_mode mode; 1183 rtx incoming_args, result, reg, dest, src, call_insn; 1184 rtx old_stack_level = 0; 1185 rtx call_fusage = 0; 1186 1187#ifdef POINTERS_EXTEND_UNSIGNED 1188 if (GET_MODE (arguments) != Pmode) 1189 arguments = convert_memory_address (Pmode, arguments); 1190#endif 1191 1192 /* Create a block where the return registers can be saved. */ 1193 result = assign_stack_local (BLKmode, apply_result_size (), -1); 1194 1195 /* Fetch the arg pointer from the ARGUMENTS block. */ 1196 incoming_args = gen_reg_rtx (Pmode); 1197 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments)); 1198#ifndef STACK_GROWS_DOWNWARD 1199 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize, 1200 incoming_args, 0, OPTAB_LIB_WIDEN); 1201#endif 1202 1203 /* Perform postincrements before actually calling the function. */ 1204 emit_queue (); 1205 1206 /* Push a new argument block and copy the arguments. Do not allow 1207 the (potential) memcpy call below to interfere with our stack 1208 manipulations. */ 1209 do_pending_stack_adjust (); 1210 NO_DEFER_POP; 1211 1212 /* Save the stack with nonlocal if available */ 1213#ifdef HAVE_save_stack_nonlocal 1214 if (HAVE_save_stack_nonlocal) 1215 emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX); 1216 else 1217#endif 1218 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); 1219 1220 /* Push a block of memory onto the stack to store the memory arguments. 1221 Save the address in a register, and copy the memory arguments. ??? I 1222 haven't figured out how the calling convention macros effect this, 1223 but it's likely that the source and/or destination addresses in 1224 the block copy will need updating in machine specific ways. */ 1225 dest = allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT); 1226 dest = gen_rtx_MEM (BLKmode, dest); 1227 set_mem_align (dest, PARM_BOUNDARY); 1228 src = gen_rtx_MEM (BLKmode, incoming_args); 1229 set_mem_align (src, PARM_BOUNDARY); 1230 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL); 1231 1232 /* Refer to the argument block. */ 1233 apply_args_size (); 1234 arguments = gen_rtx_MEM (BLKmode, arguments); 1235 set_mem_align (arguments, PARM_BOUNDARY); 1236 1237 /* Walk past the arg-pointer and structure value address. */ 1238 size = GET_MODE_SIZE (Pmode); 1239 if (struct_value_rtx) 1240 size += GET_MODE_SIZE (Pmode); 1241 1242 /* Restore each of the registers previously saved. Make USE insns 1243 for each of these registers for use in making the call. */ 1244 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 1245 if ((mode = apply_args_mode[regno]) != VOIDmode) 1246 { 1247 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; 1248 if (size % align != 0) 1249 size = CEIL (size, align) * align; 1250 reg = gen_rtx_REG (mode, regno); 1251 emit_move_insn (reg, adjust_address (arguments, mode, size)); 1252 use_reg (&call_fusage, reg); 1253 size += GET_MODE_SIZE (mode); 1254 } 1255 1256 /* Restore the structure value address unless this is passed as an 1257 "invisible" first argument. */ 1258 size = GET_MODE_SIZE (Pmode); 1259 if (struct_value_rtx) 1260 { 1261 rtx value = gen_reg_rtx (Pmode); 1262 emit_move_insn (value, adjust_address (arguments, Pmode, size)); 1263 emit_move_insn (struct_value_rtx, value); 1264 if (GET_CODE (struct_value_rtx) == REG) 1265 use_reg (&call_fusage, struct_value_rtx); 1266 size += GET_MODE_SIZE (Pmode); 1267 } 1268 1269 /* All arguments and registers used for the call are set up by now! */ 1270 function = prepare_call_address (function, NULL_TREE, &call_fusage, 0, 0); 1271 1272 /* Ensure address is valid. SYMBOL_REF is already valid, so no need, 1273 and we don't want to load it into a register as an optimization, 1274 because prepare_call_address already did it if it should be done. */ 1275 if (GET_CODE (function) != SYMBOL_REF) 1276 function = memory_address (FUNCTION_MODE, function); 1277 1278 /* Generate the actual call instruction and save the return value. */ 1279#ifdef HAVE_untyped_call 1280 if (HAVE_untyped_call) 1281 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function), 1282 result, result_vector (1, result))); 1283 else 1284#endif 1285#ifdef HAVE_call_value 1286 if (HAVE_call_value) 1287 { 1288 rtx valreg = 0; 1289 1290 /* Locate the unique return register. It is not possible to 1291 express a call that sets more than one return register using 1292 call_value; use untyped_call for that. In fact, untyped_call 1293 only needs to save the return registers in the given block. */ 1294 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 1295 if ((mode = apply_result_mode[regno]) != VOIDmode) 1296 { 1297 if (valreg) 1298 abort (); /* HAVE_untyped_call required. */ 1299 valreg = gen_rtx_REG (mode, regno); 1300 } 1301 1302 emit_call_insn (GEN_CALL_VALUE (valreg, 1303 gen_rtx_MEM (FUNCTION_MODE, function), 1304 const0_rtx, NULL_RTX, const0_rtx)); 1305 1306 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg); 1307 } 1308 else 1309#endif 1310 abort (); 1311 1312 /* Find the CALL insn we just emitted. */ 1313 for (call_insn = get_last_insn (); 1314 call_insn && GET_CODE (call_insn) != CALL_INSN; 1315 call_insn = PREV_INSN (call_insn)) 1316 ; 1317 1318 if (! call_insn) 1319 abort (); 1320 1321 /* Put the register usage information on the CALL. If there is already 1322 some usage information, put ours at the end. */ 1323 if (CALL_INSN_FUNCTION_USAGE (call_insn)) 1324 { 1325 rtx link; 1326 1327 for (link = CALL_INSN_FUNCTION_USAGE (call_insn); XEXP (link, 1) != 0; 1328 link = XEXP (link, 1)) 1329 ; 1330 1331 XEXP (link, 1) = call_fusage; 1332 } 1333 else 1334 CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage; 1335 1336 /* Restore the stack. */ 1337#ifdef HAVE_save_stack_nonlocal 1338 if (HAVE_save_stack_nonlocal) 1339 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX); 1340 else 1341#endif 1342 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); 1343 1344 OK_DEFER_POP; 1345 1346 /* Return the address of the result block. */ 1347 result = copy_addr_to_reg (XEXP (result, 0)); 1348#ifdef POINTERS_EXTEND_UNSIGNED 1349 if (GET_MODE (result) != ptr_mode) 1350 result = convert_memory_address (ptr_mode, result); 1351#endif 1352 return result; 1353} 1354 1355/* Perform an untyped return. */ 1356 1357static void 1358expand_builtin_return (result) 1359 rtx result; 1360{ 1361 int size, align, regno; 1362 enum machine_mode mode; 1363 rtx reg; 1364 rtx call_fusage = 0; 1365 1366#ifdef POINTERS_EXTEND_UNSIGNED 1367 if (GET_MODE (result) != Pmode) 1368 result = convert_memory_address (Pmode, result); 1369#endif 1370 1371 apply_result_size (); 1372 result = gen_rtx_MEM (BLKmode, result); 1373 1374#ifdef HAVE_untyped_return 1375 if (HAVE_untyped_return) 1376 { 1377 emit_jump_insn (gen_untyped_return (result, result_vector (0, result))); 1378 emit_barrier (); 1379 return; 1380 } 1381#endif 1382 1383 /* Restore the return value and note that each value is used. */ 1384 size = 0; 1385 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 1386 if ((mode = apply_result_mode[regno]) != VOIDmode) 1387 { 1388 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; 1389 if (size % align != 0) 1390 size = CEIL (size, align) * align; 1391 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno)); 1392 emit_move_insn (reg, adjust_address (result, mode, size)); 1393 1394 push_to_sequence (call_fusage); 1395 emit_insn (gen_rtx_USE (VOIDmode, reg)); 1396 call_fusage = get_insns (); 1397 end_sequence (); 1398 size += GET_MODE_SIZE (mode); 1399 } 1400 1401 /* Put the USE insns before the return. */ 1402 emit_insn (call_fusage); 1403 1404 /* Return whatever values was restored by jumping directly to the end 1405 of the function. */ 1406 expand_null_return (); 1407} 1408 1409/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */ 1410 1411static enum type_class 1412type_to_class (type) 1413 tree type; 1414{ 1415 switch (TREE_CODE (type)) 1416 { 1417 case VOID_TYPE: return void_type_class; 1418 case INTEGER_TYPE: return integer_type_class; 1419 case CHAR_TYPE: return char_type_class; 1420 case ENUMERAL_TYPE: return enumeral_type_class; 1421 case BOOLEAN_TYPE: return boolean_type_class; 1422 case POINTER_TYPE: return pointer_type_class; 1423 case REFERENCE_TYPE: return reference_type_class; 1424 case OFFSET_TYPE: return offset_type_class; 1425 case REAL_TYPE: return real_type_class; 1426 case COMPLEX_TYPE: return complex_type_class; 1427 case FUNCTION_TYPE: return function_type_class; 1428 case METHOD_TYPE: return method_type_class; 1429 case RECORD_TYPE: return record_type_class; 1430 case UNION_TYPE: 1431 case QUAL_UNION_TYPE: return union_type_class; 1432 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type) 1433 ? string_type_class : array_type_class); 1434 case SET_TYPE: return set_type_class; 1435 case FILE_TYPE: return file_type_class; 1436 case LANG_TYPE: return lang_type_class; 1437 default: return no_type_class; 1438 } 1439} 1440 1441/* Expand a call to __builtin_classify_type with arguments found in 1442 ARGLIST. */ 1443 1444static rtx 1445expand_builtin_classify_type (arglist) 1446 tree arglist; 1447{ 1448 if (arglist != 0) 1449 return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist)))); 1450 return GEN_INT (no_type_class); 1451} 1452 1453/* Expand expression EXP, which is a call to __builtin_constant_p. */ 1454 1455static rtx 1456expand_builtin_constant_p (exp) 1457 tree exp; 1458{ 1459 tree arglist = TREE_OPERAND (exp, 1); 1460 enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp)); 1461 rtx tmp; 1462 1463 if (arglist == 0) 1464 return const0_rtx; 1465 arglist = TREE_VALUE (arglist); 1466 1467 /* We have taken care of the easy cases during constant folding. This 1468 case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE get a 1469 chance to see if it can deduce whether ARGLIST is constant. */ 1470 1471 tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0); 1472 tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp); 1473 return tmp; 1474} 1475 1476/* Expand a call to one of the builtin math functions (sin, cos, or sqrt). 1477 Return 0 if a normal call should be emitted rather than expanding the 1478 function in-line. EXP is the expression that is a call to the builtin 1479 function; if convenient, the result should be placed in TARGET. 1480 SUBTARGET may be used as the target for computing one of EXP's operands. */ 1481 1482static rtx 1483expand_builtin_mathfn (exp, target, subtarget) 1484 tree exp; 1485 rtx target, subtarget; 1486{ 1487 optab builtin_optab; 1488 rtx op0, insns; 1489 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); 1490 tree arglist = TREE_OPERAND (exp, 1); 1491 enum machine_mode argmode; 1492 1493 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) 1494 return 0; 1495 1496 /* Stabilize and compute the argument. */ 1497 if (TREE_CODE (TREE_VALUE (arglist)) != VAR_DECL 1498 && TREE_CODE (TREE_VALUE (arglist)) != PARM_DECL) 1499 { 1500 exp = copy_node (exp); 1501 TREE_OPERAND (exp, 1) = arglist; 1502 /* Wrap the computation of the argument in a SAVE_EXPR. That 1503 way, if we need to expand the argument again (as in the 1504 flag_errno_math case below where we cannot directly set 1505 errno), we will not perform side-effects more than once. 1506 Note that here we're mutating the original EXP as well as the 1507 copy; that's the right thing to do in case the original EXP 1508 is expanded later. */ 1509 TREE_VALUE (arglist) = save_expr (TREE_VALUE (arglist)); 1510 arglist = copy_node (arglist); 1511 } 1512 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0); 1513 1514 /* Make a suitable register to place result in. */ 1515 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); 1516 1517 emit_queue (); 1518 start_sequence (); 1519 1520 switch (DECL_FUNCTION_CODE (fndecl)) 1521 { 1522 case BUILT_IN_SIN: 1523 case BUILT_IN_SINF: 1524 case BUILT_IN_SINL: 1525 builtin_optab = sin_optab; break; 1526 case BUILT_IN_COS: 1527 case BUILT_IN_COSF: 1528 case BUILT_IN_COSL: 1529 builtin_optab = cos_optab; break; 1530 case BUILT_IN_SQRT: 1531 case BUILT_IN_SQRTF: 1532 case BUILT_IN_SQRTL: 1533 builtin_optab = sqrt_optab; break; 1534 case BUILT_IN_EXP: 1535 case BUILT_IN_EXPF: 1536 case BUILT_IN_EXPL: 1537 builtin_optab = exp_optab; break; 1538 case BUILT_IN_LOG: 1539 case BUILT_IN_LOGF: 1540 case BUILT_IN_LOGL: 1541 builtin_optab = log_optab; break; 1542 default: 1543 abort (); 1544 } 1545 1546 /* Compute into TARGET. 1547 Set TARGET to wherever the result comes back. */ 1548 argmode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))); 1549 target = expand_unop (argmode, builtin_optab, op0, target, 0); 1550 1551 /* If we were unable to expand via the builtin, stop the 1552 sequence (without outputting the insns) and return 0, causing 1553 a call to the library function. */ 1554 if (target == 0) 1555 { 1556 end_sequence (); 1557 return 0; 1558 } 1559 1560 /* If errno must be maintained, we must set it to EDOM for NaN results. */ 1561 1562 if (flag_errno_math && HONOR_NANS (argmode)) 1563 { 1564 rtx lab1; 1565 1566 lab1 = gen_label_rtx (); 1567 1568 /* Test the result; if it is NaN, set errno=EDOM because 1569 the argument was not in the domain. */ 1570 emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target), 1571 0, lab1); 1572 1573#ifdef TARGET_EDOM 1574 { 1575#ifdef GEN_ERRNO_RTX 1576 rtx errno_rtx = GEN_ERRNO_RTX; 1577#else 1578 rtx errno_rtx 1579 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno")); 1580#endif 1581 1582 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM)); 1583 } 1584#else 1585 /* We can't set errno=EDOM directly; let the library call do it. 1586 Pop the arguments right away in case the call gets deleted. */ 1587 NO_DEFER_POP; 1588 expand_call (exp, target, 0); 1589 OK_DEFER_POP; 1590#endif 1591 1592 emit_label (lab1); 1593 } 1594 1595 /* Output the entire sequence. */ 1596 insns = get_insns (); 1597 end_sequence (); 1598 emit_insn (insns); 1599 1600 return target; 1601} 1602 1603/* Expand expression EXP which is a call to the strlen builtin. Return 0 1604 if we failed the caller should emit a normal call, otherwise 1605 try to get the result in TARGET, if convenient. */ 1606 1607static rtx 1608expand_builtin_strlen (exp, target) 1609 tree exp; 1610 rtx target; 1611{ 1612 tree arglist = TREE_OPERAND (exp, 1); 1613 enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp)); 1614 1615 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) 1616 return 0; 1617 else 1618 { 1619 rtx pat; 1620 tree src = TREE_VALUE (arglist); 1621 1622 int align 1623 = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; 1624 1625 rtx result, src_reg, char_rtx, before_strlen; 1626 enum machine_mode insn_mode = value_mode, char_mode; 1627 enum insn_code icode = CODE_FOR_nothing; 1628 1629 /* If SRC is not a pointer type, don't do this operation inline. */ 1630 if (align == 0) 1631 return 0; 1632 1633 /* Bail out if we can't compute strlen in the right mode. */ 1634 while (insn_mode != VOIDmode) 1635 { 1636 icode = strlen_optab->handlers[(int) insn_mode].insn_code; 1637 if (icode != CODE_FOR_nothing) 1638 break; 1639 1640 insn_mode = GET_MODE_WIDER_MODE (insn_mode); 1641 } 1642 if (insn_mode == VOIDmode) 1643 return 0; 1644 1645 /* Make a place to write the result of the instruction. */ 1646 result = target; 1647 if (! (result != 0 1648 && GET_CODE (result) == REG 1649 && GET_MODE (result) == insn_mode 1650 && REGNO (result) >= FIRST_PSEUDO_REGISTER)) 1651 result = gen_reg_rtx (insn_mode); 1652 1653 /* Make a place to hold the source address. We will not expand 1654 the actual source until we are sure that the expansion will 1655 not fail -- there are trees that cannot be expanded twice. */ 1656 src_reg = gen_reg_rtx (Pmode); 1657 1658 /* Mark the beginning of the strlen sequence so we can emit the 1659 source operand later. */ 1660 before_strlen = get_last_insn (); 1661 1662 char_rtx = const0_rtx; 1663 char_mode = insn_data[(int) icode].operand[2].mode; 1664 if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx, 1665 char_mode)) 1666 char_rtx = copy_to_mode_reg (char_mode, char_rtx); 1667 1668 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg), 1669 char_rtx, GEN_INT (align)); 1670 if (! pat) 1671 return 0; 1672 emit_insn (pat); 1673 1674 /* Now that we are assured of success, expand the source. */ 1675 start_sequence (); 1676 pat = memory_address (BLKmode, 1677 expand_expr (src, src_reg, ptr_mode, EXPAND_SUM)); 1678 if (pat != src_reg) 1679 emit_move_insn (src_reg, pat); 1680 pat = get_insns (); 1681 end_sequence (); 1682 1683 if (before_strlen) 1684 emit_insn_after (pat, before_strlen); 1685 else 1686 emit_insn_before (pat, get_insns ()); 1687 1688 /* Return the value in the proper mode for this function. */ 1689 if (GET_MODE (result) == value_mode) 1690 target = result; 1691 else if (target != 0) 1692 convert_move (target, result, 0); 1693 else 1694 target = convert_to_mode (value_mode, result, 0); 1695 1696 return target; 1697 } 1698} 1699 1700/* Expand a call to the strstr builtin. Return 0 if we failed the 1701 caller should emit a normal call, otherwise try to get the result 1702 in TARGET, if convenient (and in mode MODE if that's convenient). */ 1703 1704static rtx 1705expand_builtin_strstr (arglist, target, mode) 1706 tree arglist; 1707 rtx target; 1708 enum machine_mode mode; 1709{ 1710 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) 1711 return 0; 1712 else 1713 { 1714 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); 1715 tree fn; 1716 const char *p1, *p2; 1717 1718 p2 = c_getstr (s2); 1719 if (p2 == NULL) 1720 return 0; 1721 1722 p1 = c_getstr (s1); 1723 if (p1 != NULL) 1724 { 1725 const char *r = strstr (p1, p2); 1726 1727 if (r == NULL) 1728 return const0_rtx; 1729 1730 /* Return an offset into the constant string argument. */ 1731 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1), 1732 s1, ssize_int (r - p1))), 1733 target, mode, EXPAND_NORMAL); 1734 } 1735 1736 if (p2[0] == '\0') 1737 return expand_expr (s1, target, mode, EXPAND_NORMAL); 1738 1739 if (p2[1] != '\0') 1740 return 0; 1741 1742 fn = built_in_decls[BUILT_IN_STRCHR]; 1743 if (!fn) 1744 return 0; 1745 1746 /* New argument list transforming strstr(s1, s2) to 1747 strchr(s1, s2[0]). */ 1748 arglist = 1749 build_tree_list (NULL_TREE, build_int_2 (p2[0], 0)); 1750 arglist = tree_cons (NULL_TREE, s1, arglist); 1751 return expand_expr (build_function_call_expr (fn, arglist), 1752 target, mode, EXPAND_NORMAL); 1753 } 1754} 1755 1756/* Expand a call to the strchr builtin. Return 0 if we failed the 1757 caller should emit a normal call, otherwise try to get the result 1758 in TARGET, if convenient (and in mode MODE if that's convenient). */ 1759 1760static rtx 1761expand_builtin_strchr (arglist, target, mode) 1762 tree arglist; 1763 rtx target; 1764 enum machine_mode mode; 1765{ 1766 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) 1767 return 0; 1768 else 1769 { 1770 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); 1771 const char *p1; 1772 1773 if (TREE_CODE (s2) != INTEGER_CST) 1774 return 0; 1775 1776 p1 = c_getstr (s1); 1777 if (p1 != NULL) 1778 { 1779 char c; 1780 const char *r; 1781 1782 if (target_char_cast (s2, &c)) 1783 return 0; 1784 1785 r = strchr (p1, c); 1786 1787 if (r == NULL) 1788 return const0_rtx; 1789 1790 /* Return an offset into the constant string argument. */ 1791 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1), 1792 s1, ssize_int (r - p1))), 1793 target, mode, EXPAND_NORMAL); 1794 } 1795 1796 /* FIXME: Should use here strchrM optab so that ports can optimize 1797 this. */ 1798 return 0; 1799 } 1800} 1801 1802/* Expand a call to the strrchr builtin. Return 0 if we failed the 1803 caller should emit a normal call, otherwise try to get the result 1804 in TARGET, if convenient (and in mode MODE if that's convenient). */ 1805 1806static rtx 1807expand_builtin_strrchr (arglist, target, mode) 1808 tree arglist; 1809 rtx target; 1810 enum machine_mode mode; 1811{ 1812 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) 1813 return 0; 1814 else 1815 { 1816 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); 1817 tree fn; 1818 const char *p1; 1819 1820 if (TREE_CODE (s2) != INTEGER_CST) 1821 return 0; 1822 1823 p1 = c_getstr (s1); 1824 if (p1 != NULL) 1825 { 1826 char c; 1827 const char *r; 1828 1829 if (target_char_cast (s2, &c)) 1830 return 0; 1831 1832 r = strrchr (p1, c); 1833 1834 if (r == NULL) 1835 return const0_rtx; 1836 1837 /* Return an offset into the constant string argument. */ 1838 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1), 1839 s1, ssize_int (r - p1))), 1840 target, mode, EXPAND_NORMAL); 1841 } 1842 1843 if (! integer_zerop (s2)) 1844 return 0; 1845 1846 fn = built_in_decls[BUILT_IN_STRCHR]; 1847 if (!fn) 1848 return 0; 1849 1850 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */ 1851 return expand_expr (build_function_call_expr (fn, arglist), 1852 target, mode, EXPAND_NORMAL); 1853 } 1854} 1855 1856/* Expand a call to the strpbrk builtin. Return 0 if we failed the 1857 caller should emit a normal call, otherwise try to get the result 1858 in TARGET, if convenient (and in mode MODE if that's convenient). */ 1859 1860static rtx 1861expand_builtin_strpbrk (arglist, target, mode) 1862 tree arglist; 1863 rtx target; 1864 enum machine_mode mode; 1865{ 1866 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) 1867 return 0; 1868 else 1869 { 1870 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); 1871 tree fn; 1872 const char *p1, *p2; 1873 1874 p2 = c_getstr (s2); 1875 if (p2 == NULL) 1876 return 0; 1877 1878 p1 = c_getstr (s1); 1879 if (p1 != NULL) 1880 { 1881 const char *r = strpbrk (p1, p2); 1882 1883 if (r == NULL) 1884 return const0_rtx; 1885 1886 /* Return an offset into the constant string argument. */ 1887 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1), 1888 s1, ssize_int (r - p1))), 1889 target, mode, EXPAND_NORMAL); 1890 } 1891 1892 if (p2[0] == '\0') 1893 { 1894 /* strpbrk(x, "") == NULL. 1895 Evaluate and ignore the arguments in case they had 1896 side-effects. */ 1897 expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL); 1898 return const0_rtx; 1899 } 1900 1901 if (p2[1] != '\0') 1902 return 0; /* Really call strpbrk. */ 1903 1904 fn = built_in_decls[BUILT_IN_STRCHR]; 1905 if (!fn) 1906 return 0; 1907 1908 /* New argument list transforming strpbrk(s1, s2) to 1909 strchr(s1, s2[0]). */ 1910 arglist = 1911 build_tree_list (NULL_TREE, build_int_2 (p2[0], 0)); 1912 arglist = tree_cons (NULL_TREE, s1, arglist); 1913 return expand_expr (build_function_call_expr (fn, arglist), 1914 target, mode, EXPAND_NORMAL); 1915 } 1916} 1917 1918/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE) 1919 bytes from constant string DATA + OFFSET and return it as target 1920 constant. */ 1921 1922static rtx 1923builtin_memcpy_read_str (data, offset, mode) 1924 PTR data; 1925 HOST_WIDE_INT offset; 1926 enum machine_mode mode; 1927{ 1928 const char *str = (const char *) data; 1929 1930 if (offset < 0 1931 || ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode) 1932 > strlen (str) + 1)) 1933 abort (); /* Attempt to read past the end of constant string. */ 1934 1935 return c_readstr (str + offset, mode); 1936} 1937 1938/* Expand a call to the memcpy builtin, with arguments in ARGLIST. 1939 Return 0 if we failed, the caller should emit a normal call, otherwise 1940 try to get the result in TARGET, if convenient (and in mode MODE if 1941 that's convenient). */ 1942 1943static rtx 1944expand_builtin_memcpy (arglist, target, mode) 1945 tree arglist; 1946 rtx target; 1947 enum machine_mode mode; 1948{ 1949 if (!validate_arglist (arglist, 1950 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) 1951 return 0; 1952 else 1953 { 1954 tree dest = TREE_VALUE (arglist); 1955 tree src = TREE_VALUE (TREE_CHAIN (arglist)); 1956 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); 1957 const char *src_str; 1958 1959 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); 1960 unsigned int dest_align 1961 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); 1962 rtx dest_mem, src_mem, dest_addr, len_rtx; 1963 1964 /* If DEST is not a pointer type, call the normal function. */ 1965 if (dest_align == 0) 1966 return 0; 1967 1968 /* If the LEN parameter is zero, return DEST. */ 1969 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0) 1970 { 1971 /* Evaluate and ignore SRC in case it has side-effects. */ 1972 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL); 1973 return expand_expr (dest, target, mode, EXPAND_NORMAL); 1974 } 1975 1976 /* If either SRC is not a pointer type, don't do this 1977 operation in-line. */ 1978 if (src_align == 0) 1979 return 0; 1980 1981 dest_mem = get_memory_rtx (dest); 1982 set_mem_align (dest_mem, dest_align); 1983 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0); 1984 src_str = c_getstr (src); 1985 1986 /* If SRC is a string constant and block move would be done 1987 by pieces, we can avoid loading the string from memory 1988 and only stored the computed constants. */ 1989 if (src_str 1990 && GET_CODE (len_rtx) == CONST_INT 1991 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1 1992 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str, 1993 (PTR) src_str, dest_align)) 1994 { 1995 store_by_pieces (dest_mem, INTVAL (len_rtx), 1996 builtin_memcpy_read_str, 1997 (PTR) src_str, dest_align); 1998 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); 1999#ifdef POINTERS_EXTEND_UNSIGNED 2000 if (GET_MODE (dest_mem) != ptr_mode) 2001 dest_mem = convert_memory_address (ptr_mode, dest_mem); 2002#endif 2003 return dest_mem; 2004 } 2005 2006 src_mem = get_memory_rtx (src); 2007 set_mem_align (src_mem, src_align); 2008 2009 /* Copy word part most expediently. */ 2010 dest_addr = emit_block_move (dest_mem, src_mem, len_rtx, 2011 BLOCK_OP_NORMAL); 2012 2013 if (dest_addr == 0) 2014 { 2015 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX); 2016#ifdef POINTERS_EXTEND_UNSIGNED 2017 if (GET_MODE (dest_addr) != ptr_mode) 2018 dest_addr = convert_memory_address (ptr_mode, dest_addr); 2019#endif 2020 } 2021 2022 return dest_addr; 2023 } 2024} 2025 2026/* Expand expression EXP, which is a call to the strcpy builtin. Return 0 2027 if we failed the caller should emit a normal call, otherwise try to get 2028 the result in TARGET, if convenient (and in mode MODE if that's 2029 convenient). */ 2030 2031static rtx 2032expand_builtin_strcpy (exp, target, mode) 2033 tree exp; 2034 rtx target; 2035 enum machine_mode mode; 2036{ 2037 tree arglist = TREE_OPERAND (exp, 1); 2038 tree fn, len, src, dst; 2039 2040 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) 2041 return 0; 2042 2043 fn = built_in_decls[BUILT_IN_MEMCPY]; 2044 if (!fn) 2045 return 0; 2046 2047 src = TREE_VALUE (TREE_CHAIN (arglist)); 2048 len = c_strlen (src); 2049 if (len == 0 || TREE_SIDE_EFFECTS (len)) 2050 return 0; 2051 2052 dst = TREE_VALUE (arglist); 2053 len = size_binop (PLUS_EXPR, len, ssize_int (1)); 2054 arglist = build_tree_list (NULL_TREE, len); 2055 arglist = tree_cons (NULL_TREE, src, arglist); 2056 arglist = tree_cons (NULL_TREE, dst, arglist); 2057 return expand_expr (build_function_call_expr (fn, arglist), 2058 target, mode, EXPAND_NORMAL); 2059} 2060 2061/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE) 2062 bytes from constant string DATA + OFFSET and return it as target 2063 constant. */ 2064 2065static rtx 2066builtin_strncpy_read_str (data, offset, mode) 2067 PTR data; 2068 HOST_WIDE_INT offset; 2069 enum machine_mode mode; 2070{ 2071 const char *str = (const char *) data; 2072 2073 if ((unsigned HOST_WIDE_INT) offset > strlen (str)) 2074 return const0_rtx; 2075 2076 return c_readstr (str + offset, mode); 2077} 2078 2079/* Expand expression EXP, which is a call to the strncpy builtin. Return 0 2080 if we failed the caller should emit a normal call. */ 2081 2082static rtx 2083expand_builtin_strncpy (arglist, target, mode) 2084 tree arglist; 2085 rtx target; 2086 enum machine_mode mode; 2087{ 2088 if (!validate_arglist (arglist, 2089 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) 2090 return 0; 2091 else 2092 { 2093 tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist))); 2094 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); 2095 tree fn; 2096 2097 /* We must be passed a constant len parameter. */ 2098 if (TREE_CODE (len) != INTEGER_CST) 2099 return 0; 2100 2101 /* If the len parameter is zero, return the dst parameter. */ 2102 if (integer_zerop (len)) 2103 { 2104 /* Evaluate and ignore the src argument in case it has 2105 side-effects. */ 2106 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx, 2107 VOIDmode, EXPAND_NORMAL); 2108 /* Return the dst parameter. */ 2109 return expand_expr (TREE_VALUE (arglist), target, mode, 2110 EXPAND_NORMAL); 2111 } 2112 2113 /* Now, we must be passed a constant src ptr parameter. */ 2114 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST) 2115 return 0; 2116 2117 slen = size_binop (PLUS_EXPR, slen, ssize_int (1)); 2118 2119 /* We're required to pad with trailing zeros if the requested 2120 len is greater than strlen(s2)+1. In that case try to 2121 use store_by_pieces, if it fails, punt. */ 2122 if (tree_int_cst_lt (slen, len)) 2123 { 2124 tree dest = TREE_VALUE (arglist); 2125 unsigned int dest_align 2126 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); 2127 const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist))); 2128 rtx dest_mem; 2129 2130 if (!p || dest_align == 0 || !host_integerp (len, 1) 2131 || !can_store_by_pieces (tree_low_cst (len, 1), 2132 builtin_strncpy_read_str, 2133 (PTR) p, dest_align)) 2134 return 0; 2135 2136 dest_mem = get_memory_rtx (dest); 2137 store_by_pieces (dest_mem, tree_low_cst (len, 1), 2138 builtin_strncpy_read_str, 2139 (PTR) p, dest_align); 2140 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); 2141#ifdef POINTERS_EXTEND_UNSIGNED 2142 if (GET_MODE (dest_mem) != ptr_mode) 2143 dest_mem = convert_memory_address (ptr_mode, dest_mem); 2144#endif 2145 return dest_mem; 2146 } 2147 2148 /* OK transform into builtin memcpy. */ 2149 fn = built_in_decls[BUILT_IN_MEMCPY]; 2150 if (!fn) 2151 return 0; 2152 return expand_expr (build_function_call_expr (fn, arglist), 2153 target, mode, EXPAND_NORMAL); 2154 } 2155} 2156 2157/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE) 2158 bytes from constant string DATA + OFFSET and return it as target 2159 constant. */ 2160 2161static rtx 2162builtin_memset_read_str (data, offset, mode) 2163 PTR data; 2164 HOST_WIDE_INT offset ATTRIBUTE_UNUSED; 2165 enum machine_mode mode; 2166{ 2167 const char *c = (const char *) data; 2168 char *p = alloca (GET_MODE_SIZE (mode)); 2169 2170 memset (p, *c, GET_MODE_SIZE (mode)); 2171 2172 return c_readstr (p, mode); 2173} 2174 2175/* Callback routine for store_by_pieces. Return the RTL of a register 2176 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned 2177 char value given in the RTL register data. For example, if mode is 2178 4 bytes wide, return the RTL for 0x01010101*data. */ 2179 2180static rtx 2181builtin_memset_gen_str (data, offset, mode) 2182 PTR data; 2183 HOST_WIDE_INT offset ATTRIBUTE_UNUSED; 2184 enum machine_mode mode; 2185{ 2186 rtx target, coeff; 2187 size_t size; 2188 char *p; 2189 2190 size = GET_MODE_SIZE (mode); 2191 if (size == 1) 2192 return (rtx) data; 2193 2194 p = alloca (size); 2195 memset (p, 1, size); 2196 coeff = c_readstr (p, mode); 2197 2198 target = convert_to_mode (mode, (rtx) data, 1); 2199 target = expand_mult (mode, target, coeff, NULL_RTX, 1); 2200 return force_reg (mode, target); 2201} 2202 2203/* Expand expression EXP, which is a call to the memset builtin. Return 0 2204 if we failed the caller should emit a normal call, otherwise try to get 2205 the result in TARGET, if convenient (and in mode MODE if that's 2206 convenient). */ 2207 2208static rtx 2209expand_builtin_memset (exp, target, mode) 2210 tree exp; 2211 rtx target; 2212 enum machine_mode mode; 2213{ 2214 tree arglist = TREE_OPERAND (exp, 1); 2215 2216 if (!validate_arglist (arglist, 2217 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)) 2218 return 0; 2219 else 2220 { 2221 tree dest = TREE_VALUE (arglist); 2222 tree val = TREE_VALUE (TREE_CHAIN (arglist)); 2223 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); 2224 char c; 2225 2226 unsigned int dest_align 2227 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); 2228 rtx dest_mem, dest_addr, len_rtx; 2229 2230 /* If DEST is not a pointer type, don't do this 2231 operation in-line. */ 2232 if (dest_align == 0) 2233 return 0; 2234 2235 /* If the LEN parameter is zero, return DEST. */ 2236 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0) 2237 { 2238 /* Evaluate and ignore VAL in case it has side-effects. */ 2239 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL); 2240 return expand_expr (dest, target, mode, EXPAND_NORMAL); 2241 } 2242 2243 if (TREE_CODE (val) != INTEGER_CST) 2244 { 2245 rtx val_rtx; 2246 2247 if (!host_integerp (len, 1)) 2248 return 0; 2249 2250 if (optimize_size && tree_low_cst (len, 1) > 1) 2251 return 0; 2252 2253 /* Assume that we can memset by pieces if we can store the 2254 * the coefficients by pieces (in the required modes). 2255 * We can't pass builtin_memset_gen_str as that emits RTL. */ 2256 c = 1; 2257 if (!can_store_by_pieces (tree_low_cst (len, 1), 2258 builtin_memset_read_str, 2259 (PTR) &c, dest_align)) 2260 return 0; 2261 2262 val = fold (build1 (CONVERT_EXPR, unsigned_char_type_node, val)); 2263 val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0); 2264 val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node), 2265 val_rtx); 2266 dest_mem = get_memory_rtx (dest); 2267 store_by_pieces (dest_mem, tree_low_cst (len, 1), 2268 builtin_memset_gen_str, 2269 (PTR) val_rtx, dest_align); 2270 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); 2271#ifdef POINTERS_EXTEND_UNSIGNED 2272 if (GET_MODE (dest_mem) != ptr_mode) 2273 dest_mem = convert_memory_address (ptr_mode, dest_mem); 2274#endif 2275 return dest_mem; 2276 } 2277 2278 if (target_char_cast (val, &c)) 2279 return 0; 2280 2281 if (c) 2282 { 2283 if (!host_integerp (len, 1)) 2284 return 0; 2285 if (!can_store_by_pieces (tree_low_cst (len, 1), 2286 builtin_memset_read_str, (PTR) &c, 2287 dest_align)) 2288 return 0; 2289 2290 dest_mem = get_memory_rtx (dest); 2291 store_by_pieces (dest_mem, tree_low_cst (len, 1), 2292 builtin_memset_read_str, 2293 (PTR) &c, dest_align); 2294 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); 2295#ifdef POINTERS_EXTEND_UNSIGNED 2296 if (GET_MODE (dest_mem) != ptr_mode) 2297 dest_mem = convert_memory_address (ptr_mode, dest_mem); 2298#endif 2299 return dest_mem; 2300 } 2301 2302 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0); 2303 2304 dest_mem = get_memory_rtx (dest); 2305 set_mem_align (dest_mem, dest_align); 2306 dest_addr = clear_storage (dest_mem, len_rtx); 2307 2308 if (dest_addr == 0) 2309 { 2310 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX); 2311#ifdef POINTERS_EXTEND_UNSIGNED 2312 if (GET_MODE (dest_addr) != ptr_mode) 2313 dest_addr = convert_memory_address (ptr_mode, dest_addr); 2314#endif 2315 } 2316 2317 return dest_addr; 2318 } 2319} 2320 2321/* Expand expression EXP, which is a call to the bzero builtin. Return 0 2322 if we failed the caller should emit a normal call. */ 2323 2324static rtx 2325expand_builtin_bzero (exp) 2326 tree exp; 2327{ 2328 tree arglist = TREE_OPERAND (exp, 1); 2329 tree dest, size, newarglist; 2330 rtx result; 2331 2332 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) 2333 return NULL_RTX; 2334 2335 dest = TREE_VALUE (arglist); 2336 size = TREE_VALUE (TREE_CHAIN (arglist)); 2337 2338 /* New argument list transforming bzero(ptr x, int y) to 2339 memset(ptr x, int 0, size_t y). This is done this way 2340 so that if it isn't expanded inline, we fallback to 2341 calling bzero instead of memset. */ 2342 2343 newarglist = build_tree_list (NULL_TREE, convert (sizetype, size)); 2344 newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist); 2345 newarglist = tree_cons (NULL_TREE, dest, newarglist); 2346 2347 TREE_OPERAND (exp, 1) = newarglist; 2348 result = expand_builtin_memset (exp, const0_rtx, VOIDmode); 2349 2350 /* Always restore the original arguments. */ 2351 TREE_OPERAND (exp, 1) = arglist; 2352 2353 return result; 2354} 2355 2356/* Expand expression EXP, which is a call to the memcmp built-in function. 2357 ARGLIST is the argument list for this call. Return 0 if we failed and the 2358 caller should emit a normal call, otherwise try to get the result in 2359 TARGET, if convenient (and in mode MODE, if that's convenient). */ 2360 2361static rtx 2362expand_builtin_memcmp (exp, arglist, target, mode) 2363 tree exp ATTRIBUTE_UNUSED; 2364 tree arglist; 2365 rtx target; 2366 enum machine_mode mode; 2367{ 2368 tree arg1, arg2, len; 2369 const char *p1, *p2; 2370 2371 if (!validate_arglist (arglist, 2372 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) 2373 return 0; 2374 2375 arg1 = TREE_VALUE (arglist); 2376 arg2 = TREE_VALUE (TREE_CHAIN (arglist)); 2377 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); 2378 2379 /* If the len parameter is zero, return zero. */ 2380 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0) 2381 { 2382 /* Evaluate and ignore arg1 and arg2 in case they have 2383 side-effects. */ 2384 expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL); 2385 expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL); 2386 return const0_rtx; 2387 } 2388 2389 p1 = c_getstr (arg1); 2390 p2 = c_getstr (arg2); 2391 2392 /* If all arguments are constant, and the value of len is not greater 2393 than the lengths of arg1 and arg2, evaluate at compile-time. */ 2394 if (host_integerp (len, 1) && p1 && p2 2395 && compare_tree_int (len, strlen (p1) + 1) <= 0 2396 && compare_tree_int (len, strlen (p2) + 1) <= 0) 2397 { 2398 const int r = memcmp (p1, p2, tree_low_cst (len, 1)); 2399 2400 return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx)); 2401 } 2402 2403 /* If len parameter is one, return an expression corresponding to 2404 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */ 2405 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1) 2406 { 2407 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); 2408 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node); 2409 tree ind1 = 2410 fold (build1 (CONVERT_EXPR, integer_type_node, 2411 build1 (INDIRECT_REF, cst_uchar_node, 2412 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1)))); 2413 tree ind2 = 2414 fold (build1 (CONVERT_EXPR, integer_type_node, 2415 build1 (INDIRECT_REF, cst_uchar_node, 2416 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2)))); 2417 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2)); 2418 return expand_expr (result, target, mode, EXPAND_NORMAL); 2419 } 2420 2421#ifdef HAVE_cmpstrsi 2422 { 2423 rtx arg1_rtx, arg2_rtx, arg3_rtx; 2424 rtx result; 2425 rtx insn; 2426 2427 int arg1_align 2428 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; 2429 int arg2_align 2430 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; 2431 enum machine_mode insn_mode 2432 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode; 2433 2434 /* If we don't have POINTER_TYPE, call the function. */ 2435 if (arg1_align == 0 || arg2_align == 0) 2436 return 0; 2437 2438 /* Make a place to write the result of the instruction. */ 2439 result = target; 2440 if (! (result != 0 2441 && GET_CODE (result) == REG && GET_MODE (result) == insn_mode 2442 && REGNO (result) >= FIRST_PSEUDO_REGISTER)) 2443 result = gen_reg_rtx (insn_mode); 2444 2445 arg1_rtx = get_memory_rtx (arg1); 2446 arg2_rtx = get_memory_rtx (arg2); 2447 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0); 2448 if (!HAVE_cmpstrsi) 2449 insn = NULL_RTX; 2450 else 2451 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx, 2452 GEN_INT (MIN (arg1_align, arg2_align))); 2453 2454 if (insn) 2455 emit_insn (insn); 2456 else 2457 emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK, 2458 TYPE_MODE (integer_type_node), 3, 2459 XEXP (arg1_rtx, 0), Pmode, 2460 XEXP (arg2_rtx, 0), Pmode, 2461 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx, 2462 TREE_UNSIGNED (sizetype)), 2463 TYPE_MODE (sizetype)); 2464 2465 /* Return the value in the proper mode for this function. */ 2466 mode = TYPE_MODE (TREE_TYPE (exp)); 2467 if (GET_MODE (result) == mode) 2468 return result; 2469 else if (target != 0) 2470 { 2471 convert_move (target, result, 0); 2472 return target; 2473 } 2474 else 2475 return convert_to_mode (mode, result, 0); 2476 } 2477#endif 2478 2479 return 0; 2480} 2481 2482/* Expand expression EXP, which is a call to the strcmp builtin. Return 0 2483 if we failed the caller should emit a normal call, otherwise try to get 2484 the result in TARGET, if convenient. */ 2485 2486static rtx 2487expand_builtin_strcmp (exp, target, mode) 2488 tree exp; 2489 rtx target; 2490 enum machine_mode mode; 2491{ 2492 tree arglist = TREE_OPERAND (exp, 1); 2493 tree arg1, arg2; 2494 const char *p1, *p2; 2495 2496 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) 2497 return 0; 2498 2499 arg1 = TREE_VALUE (arglist); 2500 arg2 = TREE_VALUE (TREE_CHAIN (arglist)); 2501 2502 p1 = c_getstr (arg1); 2503 p2 = c_getstr (arg2); 2504 2505 if (p1 && p2) 2506 { 2507 const int i = strcmp (p1, p2); 2508 return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx)); 2509 } 2510 2511 /* If either arg is "", return an expression corresponding to 2512 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */ 2513 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')) 2514 { 2515 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); 2516 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node); 2517 tree ind1 = 2518 fold (build1 (CONVERT_EXPR, integer_type_node, 2519 build1 (INDIRECT_REF, cst_uchar_node, 2520 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1)))); 2521 tree ind2 = 2522 fold (build1 (CONVERT_EXPR, integer_type_node, 2523 build1 (INDIRECT_REF, cst_uchar_node, 2524 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2)))); 2525 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2)); 2526 return expand_expr (result, target, mode, EXPAND_NORMAL); 2527 } 2528 2529#ifdef HAVE_cmpstrsi 2530 if (HAVE_cmpstrsi) 2531 { 2532 tree len, len1, len2; 2533 rtx arg1_rtx, arg2_rtx, arg3_rtx; 2534 rtx result, insn; 2535 2536 int arg1_align 2537 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; 2538 int arg2_align 2539 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; 2540 enum machine_mode insn_mode 2541 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode; 2542 2543 len1 = c_strlen (arg1); 2544 len2 = c_strlen (arg2); 2545 2546 if (len1) 2547 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1); 2548 if (len2) 2549 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2); 2550 2551 /* If we don't have a constant length for the first, use the length 2552 of the second, if we know it. We don't require a constant for 2553 this case; some cost analysis could be done if both are available 2554 but neither is constant. For now, assume they're equally cheap 2555 unless one has side effects. If both strings have constant lengths, 2556 use the smaller. */ 2557 2558 if (!len1) 2559 len = len2; 2560 else if (!len2) 2561 len = len1; 2562 else if (TREE_SIDE_EFFECTS (len1)) 2563 len = len2; 2564 else if (TREE_SIDE_EFFECTS (len2)) 2565 len = len1; 2566 else if (TREE_CODE (len1) != INTEGER_CST) 2567 len = len2; 2568 else if (TREE_CODE (len2) != INTEGER_CST) 2569 len = len1; 2570 else if (tree_int_cst_lt (len1, len2)) 2571 len = len1; 2572 else 2573 len = len2; 2574 2575 /* If both arguments have side effects, we cannot optimize. */ 2576 if (!len || TREE_SIDE_EFFECTS (len)) 2577 return 0; 2578 2579 /* If we don't have POINTER_TYPE, call the function. */ 2580 if (arg1_align == 0 || arg2_align == 0) 2581 return 0; 2582 2583 /* Make a place to write the result of the instruction. */ 2584 result = target; 2585 if (! (result != 0 2586 && GET_CODE (result) == REG 2587 && GET_MODE (result) == insn_mode 2588 && REGNO (result) >= FIRST_PSEUDO_REGISTER)) 2589 result = gen_reg_rtx (insn_mode); 2590 2591 arg1_rtx = get_memory_rtx (arg1); 2592 arg2_rtx = get_memory_rtx (arg2); 2593 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0); 2594 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx, 2595 GEN_INT (MIN (arg1_align, arg2_align))); 2596 if (!insn) 2597 return 0; 2598 2599 emit_insn (insn); 2600 2601 /* Return the value in the proper mode for this function. */ 2602 mode = TYPE_MODE (TREE_TYPE (exp)); 2603 if (GET_MODE (result) == mode) 2604 return result; 2605 if (target == 0) 2606 return convert_to_mode (mode, result, 0); 2607 convert_move (target, result, 0); 2608 return target; 2609 } 2610#endif 2611 return 0; 2612} 2613 2614/* Expand expression EXP, which is a call to the strncmp builtin. Return 0 2615 if we failed the caller should emit a normal call, otherwise try to get 2616 the result in TARGET, if convenient. */ 2617 2618static rtx 2619expand_builtin_strncmp (exp, target, mode) 2620 tree exp; 2621 rtx target; 2622 enum machine_mode mode; 2623{ 2624 tree arglist = TREE_OPERAND (exp, 1); 2625 tree arg1, arg2, arg3; 2626 const char *p1, *p2; 2627 2628 if (!validate_arglist (arglist, 2629 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) 2630 return 0; 2631 2632 arg1 = TREE_VALUE (arglist); 2633 arg2 = TREE_VALUE (TREE_CHAIN (arglist)); 2634 arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); 2635 2636 /* If the len parameter is zero, return zero. */ 2637 if (host_integerp (arg3, 1) && tree_low_cst (arg3, 1) == 0) 2638 { 2639 /* Evaluate and ignore arg1 and arg2 in case they have 2640 side-effects. */ 2641 expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL); 2642 expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL); 2643 return const0_rtx; 2644 } 2645 2646 p1 = c_getstr (arg1); 2647 p2 = c_getstr (arg2); 2648 2649 /* If all arguments are constant, evaluate at compile-time. */ 2650 if (host_integerp (arg3, 1) && p1 && p2) 2651 { 2652 const int r = strncmp (p1, p2, tree_low_cst (arg3, 1)); 2653 return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx)); 2654 } 2655 2656 /* If len == 1 or (either string parameter is "" and (len >= 1)), 2657 return (*(const u_char*)arg1 - *(const u_char*)arg2). */ 2658 if (host_integerp (arg3, 1) 2659 && (tree_low_cst (arg3, 1) == 1 2660 || (tree_low_cst (arg3, 1) > 1 2661 && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))))) 2662 { 2663 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); 2664 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node); 2665 tree ind1 = 2666 fold (build1 (CONVERT_EXPR, integer_type_node, 2667 build1 (INDIRECT_REF, cst_uchar_node, 2668 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1)))); 2669 tree ind2 = 2670 fold (build1 (CONVERT_EXPR, integer_type_node, 2671 build1 (INDIRECT_REF, cst_uchar_node, 2672 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2)))); 2673 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2)); 2674 return expand_expr (result, target, mode, EXPAND_NORMAL); 2675 } 2676 2677 /* If c_strlen can determine an expression for one of the string 2678 lengths, and it doesn't have side effects, then emit cmpstrsi 2679 using length MIN(strlen(string)+1, arg3). */ 2680#ifdef HAVE_cmpstrsi 2681 if (HAVE_cmpstrsi) 2682 { 2683 tree len, len1, len2; 2684 rtx arg1_rtx, arg2_rtx, arg3_rtx; 2685 rtx result, insn; 2686 2687 int arg1_align 2688 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; 2689 int arg2_align 2690 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; 2691 enum machine_mode insn_mode 2692 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode; 2693 2694 len1 = c_strlen (arg1); 2695 len2 = c_strlen (arg2); 2696 2697 if (len1) 2698 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1); 2699 if (len2) 2700 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2); 2701 2702 /* If we don't have a constant length for the first, use the length 2703 of the second, if we know it. We don't require a constant for 2704 this case; some cost analysis could be done if both are available 2705 but neither is constant. For now, assume they're equally cheap, 2706 unless one has side effects. If both strings have constant lengths, 2707 use the smaller. */ 2708 2709 if (!len1) 2710 len = len2; 2711 else if (!len2) 2712 len = len1; 2713 else if (TREE_SIDE_EFFECTS (len1)) 2714 len = len2; 2715 else if (TREE_SIDE_EFFECTS (len2)) 2716 len = len1; 2717 else if (TREE_CODE (len1) != INTEGER_CST) 2718 len = len2; 2719 else if (TREE_CODE (len2) != INTEGER_CST) 2720 len = len1; 2721 else if (tree_int_cst_lt (len1, len2)) 2722 len = len1; 2723 else 2724 len = len2; 2725 2726 /* If both arguments have side effects, we cannot optimize. */ 2727 if (!len || TREE_SIDE_EFFECTS (len)) 2728 return 0; 2729 2730 /* The actual new length parameter is MIN(len,arg3). */ 2731 len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3)); 2732 2733 /* If we don't have POINTER_TYPE, call the function. */ 2734 if (arg1_align == 0 || arg2_align == 0) 2735 return 0; 2736 2737 /* Make a place to write the result of the instruction. */ 2738 result = target; 2739 if (! (result != 0 2740 && GET_CODE (result) == REG 2741 && GET_MODE (result) == insn_mode 2742 && REGNO (result) >= FIRST_PSEUDO_REGISTER)) 2743 result = gen_reg_rtx (insn_mode); 2744 2745 arg1_rtx = get_memory_rtx (arg1); 2746 arg2_rtx = get_memory_rtx (arg2); 2747 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0); 2748 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx, 2749 GEN_INT (MIN (arg1_align, arg2_align))); 2750 if (!insn) 2751 return 0; 2752 2753 emit_insn (insn); 2754 2755 /* Return the value in the proper mode for this function. */ 2756 mode = TYPE_MODE (TREE_TYPE (exp)); 2757 if (GET_MODE (result) == mode) 2758 return result; 2759 if (target == 0) 2760 return convert_to_mode (mode, result, 0); 2761 convert_move (target, result, 0); 2762 return target; 2763 } 2764#endif 2765 return 0; 2766} 2767 2768/* Expand expression EXP, which is a call to the strcat builtin. 2769 Return 0 if we failed the caller should emit a normal call, 2770 otherwise try to get the result in TARGET, if convenient. */ 2771 2772static rtx 2773expand_builtin_strcat (arglist, target, mode) 2774 tree arglist; 2775 rtx target; 2776 enum machine_mode mode; 2777{ 2778 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) 2779 return 0; 2780 else 2781 { 2782 tree dst = TREE_VALUE (arglist), 2783 src = TREE_VALUE (TREE_CHAIN (arglist)); 2784 const char *p = c_getstr (src); 2785 2786 /* If the string length is zero, return the dst parameter. */ 2787 if (p && *p == '\0') 2788 return expand_expr (dst, target, mode, EXPAND_NORMAL); 2789 2790 return 0; 2791 } 2792} 2793 2794/* Expand expression EXP, which is a call to the strncat builtin. 2795 Return 0 if we failed the caller should emit a normal call, 2796 otherwise try to get the result in TARGET, if convenient. */ 2797 2798static rtx 2799expand_builtin_strncat (arglist, target, mode) 2800 tree arglist; 2801 rtx target; 2802 enum machine_mode mode; 2803{ 2804 if (!validate_arglist (arglist, 2805 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) 2806 return 0; 2807 else 2808 { 2809 tree dst = TREE_VALUE (arglist), 2810 src = TREE_VALUE (TREE_CHAIN (arglist)), 2811 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); 2812 const char *p = c_getstr (src); 2813 2814 /* If the requested length is zero, or the src parameter string 2815 length is zero, return the dst parameter. */ 2816 if (integer_zerop (len) || (p && *p == '\0')) 2817 { 2818 /* Evaluate and ignore the src and len parameters in case 2819 they have side-effects. */ 2820 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL); 2821 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL); 2822 return expand_expr (dst, target, mode, EXPAND_NORMAL); 2823 } 2824 2825 /* If the requested len is greater than or equal to the string 2826 length, call strcat. */ 2827 if (TREE_CODE (len) == INTEGER_CST && p 2828 && compare_tree_int (len, strlen (p)) >= 0) 2829 { 2830 tree newarglist 2831 = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src)); 2832 tree fn = built_in_decls[BUILT_IN_STRCAT]; 2833 2834 /* If the replacement _DECL isn't initialized, don't do the 2835 transformation. */ 2836 if (!fn) 2837 return 0; 2838 2839 return expand_expr (build_function_call_expr (fn, newarglist), 2840 target, mode, EXPAND_NORMAL); 2841 } 2842 return 0; 2843 } 2844} 2845 2846/* Expand expression EXP, which is a call to the strspn builtin. 2847 Return 0 if we failed the caller should emit a normal call, 2848 otherwise try to get the result in TARGET, if convenient. */ 2849 2850static rtx 2851expand_builtin_strspn (arglist, target, mode) 2852 tree arglist; 2853 rtx target; 2854 enum machine_mode mode; 2855{ 2856 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) 2857 return 0; 2858 else 2859 { 2860 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); 2861 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2); 2862 2863 /* If both arguments are constants, evaluate at compile-time. */ 2864 if (p1 && p2) 2865 { 2866 const size_t r = strspn (p1, p2); 2867 return expand_expr (size_int (r), target, mode, EXPAND_NORMAL); 2868 } 2869 2870 /* If either argument is "", return 0. */ 2871 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')) 2872 { 2873 /* Evaluate and ignore both arguments in case either one has 2874 side-effects. */ 2875 expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL); 2876 expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL); 2877 return const0_rtx; 2878 } 2879 return 0; 2880 } 2881} 2882 2883/* Expand expression EXP, which is a call to the strcspn builtin. 2884 Return 0 if we failed the caller should emit a normal call, 2885 otherwise try to get the result in TARGET, if convenient. */ 2886 2887static rtx 2888expand_builtin_strcspn (arglist, target, mode) 2889 tree arglist; 2890 rtx target; 2891 enum machine_mode mode; 2892{ 2893 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) 2894 return 0; 2895 else 2896 { 2897 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); 2898 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2); 2899 2900 /* If both arguments are constants, evaluate at compile-time. */ 2901 if (p1 && p2) 2902 { 2903 const size_t r = strcspn (p1, p2); 2904 return expand_expr (size_int (r), target, mode, EXPAND_NORMAL); 2905 } 2906 2907 /* If the first argument is "", return 0. */ 2908 if (p1 && *p1 == '\0') 2909 { 2910 /* Evaluate and ignore argument s2 in case it has 2911 side-effects. */ 2912 expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL); 2913 return const0_rtx; 2914 } 2915 2916 /* If the second argument is "", return __builtin_strlen(s1). */ 2917 if (p2 && *p2 == '\0') 2918 { 2919 tree newarglist = build_tree_list (NULL_TREE, s1), 2920 fn = built_in_decls[BUILT_IN_STRLEN]; 2921 2922 /* If the replacement _DECL isn't initialized, don't do the 2923 transformation. */ 2924 if (!fn) 2925 return 0; 2926 2927 return expand_expr (build_function_call_expr (fn, newarglist), 2928 target, mode, EXPAND_NORMAL); 2929 } 2930 return 0; 2931 } 2932} 2933 2934/* Expand a call to __builtin_saveregs, generating the result in TARGET, 2935 if that's convenient. */ 2936 2937rtx 2938expand_builtin_saveregs () 2939{ 2940 rtx val, seq; 2941 2942 /* Don't do __builtin_saveregs more than once in a function. 2943 Save the result of the first call and reuse it. */ 2944 if (saveregs_value != 0) 2945 return saveregs_value; 2946 2947 /* When this function is called, it means that registers must be 2948 saved on entry to this function. So we migrate the call to the 2949 first insn of this function. */ 2950 2951 start_sequence (); 2952 2953#ifdef EXPAND_BUILTIN_SAVEREGS 2954 /* Do whatever the machine needs done in this case. */ 2955 val = EXPAND_BUILTIN_SAVEREGS (); 2956#else 2957 /* ??? We used to try and build up a call to the out of line function, 2958 guessing about what registers needed saving etc. This became much 2959 harder with __builtin_va_start, since we don't have a tree for a 2960 call to __builtin_saveregs to fall back on. There was exactly one 2961 port (i860) that used this code, and I'm unconvinced it could actually 2962 handle the general case. So we no longer try to handle anything 2963 weird and make the backend absorb the evil. */ 2964 2965 error ("__builtin_saveregs not supported by this target"); 2966 val = const0_rtx; 2967#endif 2968 2969 seq = get_insns (); 2970 end_sequence (); 2971 2972 saveregs_value = val; 2973 2974 /* Put the insns after the NOTE that starts the function. If this 2975 is inside a start_sequence, make the outer-level insn chain current, so 2976 the code is placed at the start of the function. */ 2977 push_topmost_sequence (); 2978 emit_insn_after (seq, get_insns ()); 2979 pop_topmost_sequence (); 2980 2981 return val; 2982} 2983 2984/* __builtin_args_info (N) returns word N of the arg space info 2985 for the current function. The number and meanings of words 2986 is controlled by the definition of CUMULATIVE_ARGS. */ 2987 2988static rtx 2989expand_builtin_args_info (exp) 2990 tree exp; 2991{ 2992 tree arglist = TREE_OPERAND (exp, 1); 2993 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int); 2994 int *word_ptr = (int *) ¤t_function_args_info; 2995#if 0 2996 /* These are used by the code below that is if 0'ed away */ 2997 int i; 2998 tree type, elts, result; 2999#endif 3000 3001 if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0) 3002 abort (); 3003 3004 if (arglist != 0) 3005 { 3006 if (!host_integerp (TREE_VALUE (arglist), 0)) 3007 error ("argument of `__builtin_args_info' must be constant"); 3008 else 3009 { 3010 HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0); 3011 3012 if (wordnum < 0 || wordnum >= nwords) 3013 error ("argument of `__builtin_args_info' out of range"); 3014 else 3015 return GEN_INT (word_ptr[wordnum]); 3016 } 3017 } 3018 else 3019 error ("missing argument in `__builtin_args_info'"); 3020 3021 return const0_rtx; 3022 3023#if 0 3024 for (i = 0; i < nwords; i++) 3025 elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0)); 3026 3027 type = build_array_type (integer_type_node, 3028 build_index_type (build_int_2 (nwords, 0))); 3029 result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts)); 3030 TREE_CONSTANT (result) = 1; 3031 TREE_STATIC (result) = 1; 3032 result = build1 (INDIRECT_REF, build_pointer_type (type), result); 3033 TREE_CONSTANT (result) = 1; 3034 return expand_expr (result, NULL_RTX, VOIDmode, 0); 3035#endif 3036} 3037 3038/* Expand ARGLIST, from a call to __builtin_next_arg. */ 3039 3040static rtx 3041expand_builtin_next_arg (arglist) 3042 tree arglist; 3043{ 3044 tree fntype = TREE_TYPE (current_function_decl); 3045 3046 if (TYPE_ARG_TYPES (fntype) == 0 3047 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) 3048 == void_type_node)) 3049 { 3050 error ("`va_start' used in function with fixed args"); 3051 return const0_rtx; 3052 } 3053 3054 if (arglist) 3055 { 3056 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl)); 3057 tree arg = TREE_VALUE (arglist); 3058 3059 /* Strip off all nops for the sake of the comparison. This 3060 is not quite the same as STRIP_NOPS. It does more. 3061 We must also strip off INDIRECT_EXPR for C++ reference 3062 parameters. */ 3063 while (TREE_CODE (arg) == NOP_EXPR 3064 || TREE_CODE (arg) == CONVERT_EXPR 3065 || TREE_CODE (arg) == NON_LVALUE_EXPR 3066 || TREE_CODE (arg) == INDIRECT_REF) 3067 arg = TREE_OPERAND (arg, 0); 3068 if (arg != last_parm) 3069 warning ("second parameter of `va_start' not last named argument"); 3070 } 3071 else 3072 /* Evidently an out of date version of <stdarg.h>; can't validate 3073 va_start's second argument, but can still work as intended. */ 3074 warning ("`__builtin_next_arg' called without an argument"); 3075 3076 return expand_binop (Pmode, add_optab, 3077 current_function_internal_arg_pointer, 3078 current_function_arg_offset_rtx, 3079 NULL_RTX, 0, OPTAB_LIB_WIDEN); 3080} 3081 3082/* Make it easier for the backends by protecting the valist argument 3083 from multiple evaluations. */ 3084 3085static tree 3086stabilize_va_list (valist, needs_lvalue) 3087 tree valist; 3088 int needs_lvalue; 3089{ 3090 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE) 3091 { 3092 if (TREE_SIDE_EFFECTS (valist)) 3093 valist = save_expr (valist); 3094 3095 /* For this case, the backends will be expecting a pointer to 3096 TREE_TYPE (va_list_type_node), but it's possible we've 3097 actually been given an array (an actual va_list_type_node). 3098 So fix it. */ 3099 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE) 3100 { 3101 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node)); 3102 tree p2 = build_pointer_type (va_list_type_node); 3103 3104 valist = build1 (ADDR_EXPR, p2, valist); 3105 valist = fold (build1 (NOP_EXPR, p1, valist)); 3106 } 3107 } 3108 else 3109 { 3110 tree pt; 3111 3112 if (! needs_lvalue) 3113 { 3114 if (! TREE_SIDE_EFFECTS (valist)) 3115 return valist; 3116 3117 pt = build_pointer_type (va_list_type_node); 3118 valist = fold (build1 (ADDR_EXPR, pt, valist)); 3119 TREE_SIDE_EFFECTS (valist) = 1; 3120 } 3121 3122 if (TREE_SIDE_EFFECTS (valist)) 3123 valist = save_expr (valist); 3124 valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), 3125 valist)); 3126 } 3127 3128 return valist; 3129} 3130 3131/* The "standard" implementation of va_start: just assign `nextarg' to 3132 the variable. */ 3133 3134void 3135std_expand_builtin_va_start (valist, nextarg) 3136 tree valist; 3137 rtx nextarg; 3138{ 3139 tree t; 3140 3141 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, 3142 make_tree (ptr_type_node, nextarg)); 3143 TREE_SIDE_EFFECTS (t) = 1; 3144 3145 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 3146} 3147 3148/* Expand ARGLIST, from a call to __builtin_va_start. */ 3149 3150static rtx 3151expand_builtin_va_start (arglist) 3152 tree arglist; 3153{ 3154 rtx nextarg; 3155 tree chain, valist; 3156 3157 chain = TREE_CHAIN (arglist); 3158 3159 if (TREE_CHAIN (chain)) 3160 error ("too many arguments to function `va_start'"); 3161 3162 nextarg = expand_builtin_next_arg (chain); 3163 valist = stabilize_va_list (TREE_VALUE (arglist), 1); 3164 3165#ifdef EXPAND_BUILTIN_VA_START 3166 EXPAND_BUILTIN_VA_START (valist, nextarg); 3167#else 3168 std_expand_builtin_va_start (valist, nextarg); 3169#endif 3170 3171 return const0_rtx; 3172} 3173 3174/* The "standard" implementation of va_arg: read the value from the 3175 current (padded) address and increment by the (padded) size. */ 3176 3177rtx 3178std_expand_builtin_va_arg (valist, type) 3179 tree valist, type; 3180{ 3181 tree addr_tree, t, type_size = NULL; 3182 tree align, alignm1; 3183 tree rounded_size; 3184 rtx addr; 3185 3186 /* Compute the rounded size of the type. */ 3187 align = size_int (PARM_BOUNDARY / BITS_PER_UNIT); 3188 alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1); 3189 if (type == error_mark_node 3190 || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL 3191 || TREE_OVERFLOW (type_size)) 3192 rounded_size = size_zero_node; 3193 else 3194 rounded_size = fold (build (MULT_EXPR, sizetype, 3195 fold (build (TRUNC_DIV_EXPR, sizetype, 3196 fold (build (PLUS_EXPR, sizetype, 3197 type_size, alignm1)), 3198 align)), 3199 align)); 3200 3201 /* Get AP. */ 3202 addr_tree = valist; 3203 if (PAD_VARARGS_DOWN && ! integer_zerop (rounded_size)) 3204 { 3205 /* Small args are padded downward. */ 3206 addr_tree = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree, 3207 fold (build (COND_EXPR, sizetype, 3208 fold (build (GT_EXPR, sizetype, 3209 rounded_size, 3210 align)), 3211 size_zero_node, 3212 fold (build (MINUS_EXPR, sizetype, 3213 rounded_size, 3214 type_size)))))); 3215 } 3216 3217 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL); 3218 addr = copy_to_reg (addr); 3219 3220 /* Compute new value for AP. */ 3221 if (! integer_zerop (rounded_size)) 3222 { 3223 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, 3224 build (PLUS_EXPR, TREE_TYPE (valist), valist, 3225 rounded_size)); 3226 TREE_SIDE_EFFECTS (t) = 1; 3227 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 3228 } 3229 3230 return addr; 3231} 3232 3233/* Expand __builtin_va_arg, which is not really a builtin function, but 3234 a very special sort of operator. */ 3235 3236rtx 3237expand_builtin_va_arg (valist, type) 3238 tree valist, type; 3239{ 3240 rtx addr, result; 3241 tree promoted_type, want_va_type, have_va_type; 3242 3243 /* Verify that valist is of the proper type. */ 3244 3245 want_va_type = va_list_type_node; 3246 have_va_type = TREE_TYPE (valist); 3247 if (TREE_CODE (want_va_type) == ARRAY_TYPE) 3248 { 3249 /* If va_list is an array type, the argument may have decayed 3250 to a pointer type, e.g. by being passed to another function. 3251 In that case, unwrap both types so that we can compare the 3252 underlying records. */ 3253 if (TREE_CODE (have_va_type) == ARRAY_TYPE 3254 || TREE_CODE (have_va_type) == POINTER_TYPE) 3255 { 3256 want_va_type = TREE_TYPE (want_va_type); 3257 have_va_type = TREE_TYPE (have_va_type); 3258 } 3259 } 3260 if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type)) 3261 { 3262 error ("first argument to `va_arg' not of type `va_list'"); 3263 addr = const0_rtx; 3264 } 3265 3266 /* Generate a diagnostic for requesting data of a type that cannot 3267 be passed through `...' due to type promotion at the call site. */ 3268 else if ((promoted_type = (*lang_hooks.types.type_promotes_to) (type)) 3269 != type) 3270 { 3271 const char *name = "<anonymous type>", *pname = 0; 3272 static bool gave_help; 3273 3274 if (TYPE_NAME (type)) 3275 { 3276 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) 3277 name = IDENTIFIER_POINTER (TYPE_NAME (type)); 3278 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 3279 && DECL_NAME (TYPE_NAME (type))) 3280 name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); 3281 } 3282 if (TYPE_NAME (promoted_type)) 3283 { 3284 if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE) 3285 pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type)); 3286 else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL 3287 && DECL_NAME (TYPE_NAME (promoted_type))) 3288 pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type))); 3289 } 3290 3291 /* Unfortunately, this is merely undefined, rather than a constraint 3292 violation, so we cannot make this an error. If this call is never 3293 executed, the program is still strictly conforming. */ 3294 warning ("`%s' is promoted to `%s' when passed through `...'", 3295 name, pname); 3296 if (! gave_help) 3297 { 3298 gave_help = true; 3299 warning ("(so you should pass `%s' not `%s' to `va_arg')", 3300 pname, name); 3301 } 3302 3303 /* We can, however, treat "undefined" any way we please. 3304 Call abort to encourage the user to fix the program. */ 3305 expand_builtin_trap (); 3306 3307 /* This is dead code, but go ahead and finish so that the 3308 mode of the result comes out right. */ 3309 addr = const0_rtx; 3310 } 3311 else 3312 { 3313 /* Make it easier for the backends by protecting the valist argument 3314 from multiple evaluations. */ 3315 valist = stabilize_va_list (valist, 0); 3316 3317#ifdef EXPAND_BUILTIN_VA_ARG 3318 addr = EXPAND_BUILTIN_VA_ARG (valist, type); 3319#else 3320 addr = std_expand_builtin_va_arg (valist, type); 3321#endif 3322 } 3323 3324#ifdef POINTERS_EXTEND_UNSIGNED 3325 if (GET_MODE (addr) != Pmode) 3326 addr = convert_memory_address (Pmode, addr); 3327#endif 3328 3329 result = gen_rtx_MEM (TYPE_MODE (type), addr); 3330 set_mem_alias_set (result, get_varargs_alias_set ()); 3331 3332 return result; 3333} 3334 3335/* Expand ARGLIST, from a call to __builtin_va_end. */ 3336 3337static rtx 3338expand_builtin_va_end (arglist) 3339 tree arglist; 3340{ 3341 tree valist = TREE_VALUE (arglist); 3342 3343#ifdef EXPAND_BUILTIN_VA_END 3344 valist = stabilize_va_list (valist, 0); 3345 EXPAND_BUILTIN_VA_END (arglist); 3346#else 3347 /* Evaluate for side effects, if needed. I hate macros that don't 3348 do that. */ 3349 if (TREE_SIDE_EFFECTS (valist)) 3350 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL); 3351#endif 3352 3353 return const0_rtx; 3354} 3355 3356/* Expand ARGLIST, from a call to __builtin_va_copy. We do this as a 3357 builtin rather than just as an assignment in stdarg.h because of the 3358 nastiness of array-type va_list types. */ 3359 3360static rtx 3361expand_builtin_va_copy (arglist) 3362 tree arglist; 3363{ 3364 tree dst, src, t; 3365 3366 dst = TREE_VALUE (arglist); 3367 src = TREE_VALUE (TREE_CHAIN (arglist)); 3368 3369 dst = stabilize_va_list (dst, 1); 3370 src = stabilize_va_list (src, 0); 3371 3372 if (TREE_CODE (va_list_type_node) != ARRAY_TYPE) 3373 { 3374 t = build (MODIFY_EXPR, va_list_type_node, dst, src); 3375 TREE_SIDE_EFFECTS (t) = 1; 3376 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 3377 } 3378 else 3379 { 3380 rtx dstb, srcb, size; 3381 3382 /* Evaluate to pointers. */ 3383 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL); 3384 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL); 3385 size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX, 3386 VOIDmode, EXPAND_NORMAL); 3387 3388#ifdef POINTERS_EXTEND_UNSIGNED 3389 if (GET_MODE (dstb) != Pmode) 3390 dstb = convert_memory_address (Pmode, dstb); 3391 3392 if (GET_MODE (srcb) != Pmode) 3393 srcb = convert_memory_address (Pmode, srcb); 3394#endif 3395 3396 /* "Dereference" to BLKmode memories. */ 3397 dstb = gen_rtx_MEM (BLKmode, dstb); 3398 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst)))); 3399 set_mem_align (dstb, TYPE_ALIGN (va_list_type_node)); 3400 srcb = gen_rtx_MEM (BLKmode, srcb); 3401 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src)))); 3402 set_mem_align (srcb, TYPE_ALIGN (va_list_type_node)); 3403 3404 /* Copy. */ 3405 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL); 3406 } 3407 3408 return const0_rtx; 3409} 3410 3411/* Expand a call to one of the builtin functions __builtin_frame_address or 3412 __builtin_return_address. */ 3413 3414static rtx 3415expand_builtin_frame_address (exp) 3416 tree exp; 3417{ 3418 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); 3419 tree arglist = TREE_OPERAND (exp, 1); 3420 3421 /* The argument must be a nonnegative integer constant. 3422 It counts the number of frames to scan up the stack. 3423 The value is the return address saved in that frame. */ 3424 if (arglist == 0) 3425 /* Warning about missing arg was already issued. */ 3426 return const0_rtx; 3427 else if (! host_integerp (TREE_VALUE (arglist), 1)) 3428 { 3429 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS) 3430 error ("invalid arg to `__builtin_frame_address'"); 3431 else 3432 error ("invalid arg to `__builtin_return_address'"); 3433 return const0_rtx; 3434 } 3435 else 3436 { 3437 rtx tem 3438 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl), 3439 tree_low_cst (TREE_VALUE (arglist), 1), 3440 hard_frame_pointer_rtx); 3441 3442 /* Some ports cannot access arbitrary stack frames. */ 3443 if (tem == NULL) 3444 { 3445 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS) 3446 warning ("unsupported arg to `__builtin_frame_address'"); 3447 else 3448 warning ("unsupported arg to `__builtin_return_address'"); 3449 return const0_rtx; 3450 } 3451 3452 /* For __builtin_frame_address, return what we've got. */ 3453 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS) 3454 return tem; 3455 3456 if (GET_CODE (tem) != REG 3457 && ! CONSTANT_P (tem)) 3458 tem = copy_to_mode_reg (Pmode, tem); 3459 return tem; 3460 } 3461} 3462 3463/* Expand a call to the alloca builtin, with arguments ARGLIST. Return 0 if 3464 we failed and the caller should emit a normal call, otherwise try to get 3465 the result in TARGET, if convenient. */ 3466 3467static rtx 3468expand_builtin_alloca (arglist, target) 3469 tree arglist; 3470 rtx target; 3471{ 3472 rtx op0; 3473 rtx result; 3474 3475 if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) 3476 return 0; 3477 3478 /* Compute the argument. */ 3479 op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0); 3480 3481 /* Allocate the desired space. */ 3482 result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT); 3483 3484#ifdef POINTERS_EXTEND_UNSIGNED 3485 if (GET_MODE (result) != ptr_mode) 3486 result = convert_memory_address (ptr_mode, result); 3487#endif 3488 3489 return result; 3490} 3491 3492/* Expand a call to the ffs builtin. The arguments are in ARGLIST. 3493 Return 0 if a normal call should be emitted rather than expanding the 3494 function in-line. If convenient, the result should be placed in TARGET. 3495 SUBTARGET may be used as the target for computing one of EXP's operands. */ 3496 3497static rtx 3498expand_builtin_ffs (arglist, target, subtarget) 3499 tree arglist; 3500 rtx target, subtarget; 3501{ 3502 rtx op0; 3503 if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) 3504 return 0; 3505 3506 /* Compute the argument. */ 3507 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0); 3508 /* Compute ffs, into TARGET if possible. 3509 Set TARGET to wherever the result comes back. */ 3510 target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))), 3511 ffs_optab, op0, target, 1); 3512 if (target == 0) 3513 abort (); 3514 return target; 3515} 3516 3517/* If the string passed to fputs is a constant and is one character 3518 long, we attempt to transform this call into __builtin_fputc(). */ 3519 3520static rtx 3521expand_builtin_fputs (arglist, ignore, unlocked) 3522 tree arglist; 3523 int ignore; 3524 int unlocked; 3525{ 3526 tree len, fn; 3527 tree fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED] 3528 : built_in_decls[BUILT_IN_FPUTC]; 3529 tree fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED] 3530 : built_in_decls[BUILT_IN_FWRITE]; 3531 3532 /* If the return value is used, or the replacement _DECL isn't 3533 initialized, don't do the transformation. */ 3534 if (!ignore || !fn_fputc || !fn_fwrite) 3535 return 0; 3536 3537 /* Verify the arguments in the original call. */ 3538 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) 3539 return 0; 3540 3541 /* Get the length of the string passed to fputs. If the length 3542 can't be determined, punt. */ 3543 if (!(len = c_strlen (TREE_VALUE (arglist))) 3544 || TREE_CODE (len) != INTEGER_CST) 3545 return 0; 3546 3547 switch (compare_tree_int (len, 1)) 3548 { 3549 case -1: /* length is 0, delete the call entirely . */ 3550 { 3551 /* Evaluate and ignore the argument in case it has 3552 side-effects. */ 3553 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx, 3554 VOIDmode, EXPAND_NORMAL); 3555 return const0_rtx; 3556 } 3557 case 0: /* length is 1, call fputc. */ 3558 { 3559 const char *p = c_getstr (TREE_VALUE (arglist)); 3560 3561 if (p != NULL) 3562 { 3563 /* New argument list transforming fputs(string, stream) to 3564 fputc(string[0], stream). */ 3565 arglist = 3566 build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist))); 3567 arglist = 3568 tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist); 3569 fn = fn_fputc; 3570 break; 3571 } 3572 } 3573 /* FALLTHROUGH */ 3574 case 1: /* length is greater than 1, call fwrite. */ 3575 { 3576 tree string_arg; 3577 3578 /* If optimizing for size keep fputs. */ 3579 if (optimize_size) 3580 return 0; 3581 string_arg = TREE_VALUE (arglist); 3582 /* New argument list transforming fputs(string, stream) to 3583 fwrite(string, 1, len, stream). */ 3584 arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist))); 3585 arglist = tree_cons (NULL_TREE, len, arglist); 3586 arglist = tree_cons (NULL_TREE, size_one_node, arglist); 3587 arglist = tree_cons (NULL_TREE, string_arg, arglist); 3588 fn = fn_fwrite; 3589 break; 3590 } 3591 default: 3592 abort (); 3593 } 3594 3595 return expand_expr (build_function_call_expr (fn, arglist), 3596 (ignore ? const0_rtx : NULL_RTX), 3597 VOIDmode, EXPAND_NORMAL); 3598} 3599 3600/* Expand a call to __builtin_expect. We return our argument and emit a 3601 NOTE_INSN_EXPECTED_VALUE note. This is the expansion of __builtin_expect in 3602 a non-jump context. */ 3603 3604static rtx 3605expand_builtin_expect (arglist, target) 3606 tree arglist; 3607 rtx target; 3608{ 3609 tree exp, c; 3610 rtx note, rtx_c; 3611 3612 if (arglist == NULL_TREE 3613 || TREE_CHAIN (arglist) == NULL_TREE) 3614 return const0_rtx; 3615 exp = TREE_VALUE (arglist); 3616 c = TREE_VALUE (TREE_CHAIN (arglist)); 3617 3618 if (TREE_CODE (c) != INTEGER_CST) 3619 { 3620 error ("second arg to `__builtin_expect' must be a constant"); 3621 c = integer_zero_node; 3622 } 3623 3624 target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL); 3625 3626 /* Don't bother with expected value notes for integral constants. */ 3627 if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT) 3628 { 3629 /* We do need to force this into a register so that we can be 3630 moderately sure to be able to correctly interpret the branch 3631 condition later. */ 3632 target = force_reg (GET_MODE (target), target); 3633 3634 rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL); 3635 3636 note = emit_note (NULL, NOTE_INSN_EXPECTED_VALUE); 3637 NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c); 3638 } 3639 3640 return target; 3641} 3642 3643/* Like expand_builtin_expect, except do this in a jump context. This is 3644 called from do_jump if the conditional is a __builtin_expect. Return either 3645 a list of insns to emit the jump or NULL if we cannot optimize 3646 __builtin_expect. We need to optimize this at jump time so that machines 3647 like the PowerPC don't turn the test into a SCC operation, and then jump 3648 based on the test being 0/1. */ 3649 3650rtx 3651expand_builtin_expect_jump (exp, if_false_label, if_true_label) 3652 tree exp; 3653 rtx if_false_label; 3654 rtx if_true_label; 3655{ 3656 tree arglist = TREE_OPERAND (exp, 1); 3657 tree arg0 = TREE_VALUE (arglist); 3658 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); 3659 rtx ret = NULL_RTX; 3660 3661 /* Only handle __builtin_expect (test, 0) and 3662 __builtin_expect (test, 1). */ 3663 if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE 3664 && (integer_zerop (arg1) || integer_onep (arg1))) 3665 { 3666 int num_jumps = 0; 3667 rtx insn; 3668 3669 /* If we fail to locate an appropriate conditional jump, we'll 3670 fall back to normal evaluation. Ensure that the expression 3671 can be re-evaluated. */ 3672 switch (unsafe_for_reeval (arg0)) 3673 { 3674 case 0: /* Safe. */ 3675 break; 3676 3677 case 1: /* Mildly unsafe. */ 3678 arg0 = unsave_expr (arg0); 3679 break; 3680 3681 case 2: /* Wildly unsafe. */ 3682 return NULL_RTX; 3683 } 3684 3685 /* Expand the jump insns. */ 3686 start_sequence (); 3687 do_jump (arg0, if_false_label, if_true_label); 3688 ret = get_insns (); 3689 end_sequence (); 3690 3691 /* Now that the __builtin_expect has been validated, go through and add 3692 the expect's to each of the conditional jumps. If we run into an 3693 error, just give up and generate the 'safe' code of doing a SCC 3694 operation and then doing a branch on that. */ 3695 insn = ret; 3696 while (insn != NULL_RTX) 3697 { 3698 rtx next = NEXT_INSN (insn); 3699 rtx pattern; 3700 3701 if (GET_CODE (insn) == JUMP_INSN && any_condjump_p (insn) 3702 && (pattern = pc_set (insn)) != NULL_RTX) 3703 { 3704 rtx ifelse = SET_SRC (pattern); 3705 rtx label; 3706 int taken; 3707 3708 if (GET_CODE (ifelse) != IF_THEN_ELSE) 3709 goto do_next_insn; 3710 3711 if (GET_CODE (XEXP (ifelse, 1)) == LABEL_REF) 3712 { 3713 taken = 1; 3714 label = XEXP (XEXP (ifelse, 1), 0); 3715 } 3716 /* An inverted jump reverses the probabilities. */ 3717 else if (GET_CODE (XEXP (ifelse, 2)) == LABEL_REF) 3718 { 3719 taken = 0; 3720 label = XEXP (XEXP (ifelse, 2), 0); 3721 } 3722 /* We shouldn't have to worry about conditional returns during 3723 the expansion stage, but handle it gracefully anyway. */ 3724 else if (GET_CODE (XEXP (ifelse, 1)) == RETURN) 3725 { 3726 taken = 1; 3727 label = NULL_RTX; 3728 } 3729 /* An inverted return reverses the probabilities. */ 3730 else if (GET_CODE (XEXP (ifelse, 2)) == RETURN) 3731 { 3732 taken = 0; 3733 label = NULL_RTX; 3734 } 3735 else 3736 goto do_next_insn; 3737 3738 /* If the test is expected to fail, reverse the 3739 probabilities. */ 3740 if (integer_zerop (arg1)) 3741 taken = 1 - taken; 3742 3743 /* If we are jumping to the false label, reverse the 3744 probabilities. */ 3745 if (label == NULL_RTX) 3746 ; /* conditional return */ 3747 else if (label == if_false_label) 3748 taken = 1 - taken; 3749 else if (label != if_true_label) 3750 goto do_next_insn; 3751 3752 num_jumps++; 3753 predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken); 3754 } 3755 3756 do_next_insn: 3757 insn = next; 3758 } 3759 3760 /* If no jumps were modified, fail and do __builtin_expect the normal 3761 way. */ 3762 if (num_jumps == 0) 3763 ret = NULL_RTX; 3764 } 3765 3766 return ret; 3767} 3768 3769void 3770expand_builtin_trap () 3771{ 3772#ifdef HAVE_trap 3773 if (HAVE_trap) 3774 emit_insn (gen_trap ()); 3775 else 3776#endif 3777 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0); 3778 emit_barrier (); 3779} 3780 3781/* Expand an expression EXP that calls a built-in function, 3782 with result going to TARGET if that's convenient 3783 (and in mode MODE if that's convenient). 3784 SUBTARGET may be used as the target for computing one of EXP's operands. 3785 IGNORE is nonzero if the value is to be ignored. */ 3786 3787rtx 3788expand_builtin (exp, target, subtarget, mode, ignore) 3789 tree exp; 3790 rtx target; 3791 rtx subtarget; 3792 enum machine_mode mode; 3793 int ignore; 3794{ 3795 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); 3796 tree arglist = TREE_OPERAND (exp, 1); 3797 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); 3798 3799 /* Perform postincrements before expanding builtin functions. �*/ 3800 emit_queue (); 3801 3802 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) 3803 return (*targetm.expand_builtin) (exp, target, subtarget, mode, ignore); 3804 3805 /* When not optimizing, generate calls to library functions for a certain 3806 set of builtins. */ 3807 if (!optimize && !CALLED_AS_BUILT_IN (fndecl)) 3808 switch (fcode) 3809 { 3810 case BUILT_IN_SQRT: 3811 case BUILT_IN_SQRTF: 3812 case BUILT_IN_SQRTL: 3813 case BUILT_IN_SIN: 3814 case BUILT_IN_SINF: 3815 case BUILT_IN_SINL: 3816 case BUILT_IN_COS: 3817 case BUILT_IN_COSF: 3818 case BUILT_IN_COSL: 3819 case BUILT_IN_EXP: 3820 case BUILT_IN_EXPF: 3821 case BUILT_IN_EXPL: 3822 case BUILT_IN_MEMSET: 3823 case BUILT_IN_MEMCPY: 3824 case BUILT_IN_MEMCMP: 3825 case BUILT_IN_BCMP: 3826 case BUILT_IN_BZERO: 3827 case BUILT_IN_INDEX: 3828 case BUILT_IN_RINDEX: 3829 case BUILT_IN_STRCHR: 3830 case BUILT_IN_STRRCHR: 3831 case BUILT_IN_STRLEN: 3832 case BUILT_IN_STRCPY: 3833 case BUILT_IN_STRNCPY: 3834 case BUILT_IN_STRNCMP: 3835 case BUILT_IN_STRSTR: 3836 case BUILT_IN_STRPBRK: 3837 case BUILT_IN_STRCAT: 3838 case BUILT_IN_STRNCAT: 3839 case BUILT_IN_STRSPN: 3840 case BUILT_IN_STRCSPN: 3841 case BUILT_IN_STRCMP: 3842 case BUILT_IN_FFS: 3843 case BUILT_IN_PUTCHAR: 3844 case BUILT_IN_PUTS: 3845 case BUILT_IN_PRINTF: 3846 case BUILT_IN_FPUTC: 3847 case BUILT_IN_FPUTS: 3848 case BUILT_IN_FWRITE: 3849 case BUILT_IN_PUTCHAR_UNLOCKED: 3850 case BUILT_IN_PUTS_UNLOCKED: 3851 case BUILT_IN_PRINTF_UNLOCKED: 3852 case BUILT_IN_FPUTC_UNLOCKED: 3853 case BUILT_IN_FPUTS_UNLOCKED: 3854 case BUILT_IN_FWRITE_UNLOCKED: 3855 return expand_call (exp, target, ignore); 3856 3857 default: 3858 break; 3859 } 3860 3861 switch (fcode) 3862 { 3863 case BUILT_IN_ABS: 3864 case BUILT_IN_LABS: 3865 case BUILT_IN_LLABS: 3866 case BUILT_IN_IMAXABS: 3867 case BUILT_IN_FABS: 3868 case BUILT_IN_FABSF: 3869 case BUILT_IN_FABSL: 3870 /* build_function_call changes these into ABS_EXPR. */ 3871 abort (); 3872 3873 case BUILT_IN_CONJ: 3874 case BUILT_IN_CONJF: 3875 case BUILT_IN_CONJL: 3876 case BUILT_IN_CREAL: 3877 case BUILT_IN_CREALF: 3878 case BUILT_IN_CREALL: 3879 case BUILT_IN_CIMAG: 3880 case BUILT_IN_CIMAGF: 3881 case BUILT_IN_CIMAGL: 3882 /* expand_tree_builtin changes these into CONJ_EXPR, REALPART_EXPR 3883 and IMAGPART_EXPR. */ 3884 abort (); 3885 3886 case BUILT_IN_SIN: 3887 case BUILT_IN_SINF: 3888 case BUILT_IN_SINL: 3889 case BUILT_IN_COS: 3890 case BUILT_IN_COSF: 3891 case BUILT_IN_COSL: 3892 case BUILT_IN_EXP: 3893 case BUILT_IN_EXPF: 3894 case BUILT_IN_EXPL: 3895 case BUILT_IN_LOG: 3896 case BUILT_IN_LOGF: 3897 case BUILT_IN_LOGL: 3898 /* Treat these like sqrt only if unsafe math optimizations are allowed, 3899 because of possible accuracy problems. */ 3900 if (! flag_unsafe_math_optimizations) 3901 break; 3902 case BUILT_IN_SQRT: 3903 case BUILT_IN_SQRTF: 3904 case BUILT_IN_SQRTL: 3905 target = expand_builtin_mathfn (exp, target, subtarget); 3906 if (target) 3907 return target; 3908 break; 3909 3910 case BUILT_IN_APPLY_ARGS: 3911 return expand_builtin_apply_args (); 3912 3913 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes 3914 FUNCTION with a copy of the parameters described by 3915 ARGUMENTS, and ARGSIZE. It returns a block of memory 3916 allocated on the stack into which is stored all the registers 3917 that might possibly be used for returning the result of a 3918 function. ARGUMENTS is the value returned by 3919 __builtin_apply_args. ARGSIZE is the number of bytes of 3920 arguments that must be copied. ??? How should this value be 3921 computed? We'll also need a safe worst case value for varargs 3922 functions. */ 3923 case BUILT_IN_APPLY: 3924 if (!validate_arglist (arglist, POINTER_TYPE, 3925 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE) 3926 && !validate_arglist (arglist, REFERENCE_TYPE, 3927 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) 3928 return const0_rtx; 3929 else 3930 { 3931 int i; 3932 tree t; 3933 rtx ops[3]; 3934 3935 for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++) 3936 ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0); 3937 3938 return expand_builtin_apply (ops[0], ops[1], ops[2]); 3939 } 3940 3941 /* __builtin_return (RESULT) causes the function to return the 3942 value described by RESULT. RESULT is address of the block of 3943 memory returned by __builtin_apply. */ 3944 case BUILT_IN_RETURN: 3945 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) 3946 expand_builtin_return (expand_expr (TREE_VALUE (arglist), 3947 NULL_RTX, VOIDmode, 0)); 3948 return const0_rtx; 3949 3950 case BUILT_IN_SAVEREGS: 3951 return expand_builtin_saveregs (); 3952 3953 case BUILT_IN_ARGS_INFO: 3954 return expand_builtin_args_info (exp); 3955 3956 /* Return the address of the first anonymous stack arg. */ 3957 case BUILT_IN_NEXT_ARG: 3958 return expand_builtin_next_arg (arglist); 3959 3960 case BUILT_IN_CLASSIFY_TYPE: 3961 return expand_builtin_classify_type (arglist); 3962 3963 case BUILT_IN_CONSTANT_P: 3964 return expand_builtin_constant_p (exp); 3965 3966 case BUILT_IN_FRAME_ADDRESS: 3967 case BUILT_IN_RETURN_ADDRESS: 3968 return expand_builtin_frame_address (exp); 3969 3970 /* Returns the address of the area where the structure is returned. 3971 0 otherwise. */ 3972 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS: 3973 if (arglist != 0 3974 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))) 3975 || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM) 3976 return const0_rtx; 3977 else 3978 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0); 3979 3980 case BUILT_IN_ALLOCA: 3981 target = expand_builtin_alloca (arglist, target); 3982 if (target) 3983 return target; 3984 break; 3985 3986 case BUILT_IN_FFS: 3987 target = expand_builtin_ffs (arglist, target, subtarget); 3988 if (target) 3989 return target; 3990 break; 3991 3992 case BUILT_IN_STRLEN: 3993 target = expand_builtin_strlen (exp, target); 3994 if (target) 3995 return target; 3996 break; 3997 3998 case BUILT_IN_STRCPY: 3999 target = expand_builtin_strcpy (exp, target, mode); 4000 if (target) 4001 return target; 4002 break; 4003 4004 case BUILT_IN_STRNCPY: 4005 target = expand_builtin_strncpy (arglist, target, mode); 4006 if (target) 4007 return target; 4008 break; 4009 4010 case BUILT_IN_STRCAT: 4011 target = expand_builtin_strcat (arglist, target, mode); 4012 if (target) 4013 return target; 4014 break; 4015 4016 case BUILT_IN_STRNCAT: 4017 target = expand_builtin_strncat (arglist, target, mode); 4018 if (target) 4019 return target; 4020 break; 4021 4022 case BUILT_IN_STRSPN: 4023 target = expand_builtin_strspn (arglist, target, mode); 4024 if (target) 4025 return target; 4026 break; 4027 4028 case BUILT_IN_STRCSPN: 4029 target = expand_builtin_strcspn (arglist, target, mode); 4030 if (target) 4031 return target; 4032 break; 4033 4034 case BUILT_IN_STRSTR: 4035 target = expand_builtin_strstr (arglist, target, mode); 4036 if (target) 4037 return target; 4038 break; 4039 4040 case BUILT_IN_STRPBRK: 4041 target = expand_builtin_strpbrk (arglist, target, mode); 4042 if (target) 4043 return target; 4044 break; 4045 4046 case BUILT_IN_INDEX: 4047 case BUILT_IN_STRCHR: 4048 target = expand_builtin_strchr (arglist, target, mode); 4049 if (target) 4050 return target; 4051 break; 4052 4053 case BUILT_IN_RINDEX: 4054 case BUILT_IN_STRRCHR: 4055 target = expand_builtin_strrchr (arglist, target, mode); 4056 if (target) 4057 return target; 4058 break; 4059 4060 case BUILT_IN_MEMCPY: 4061 target = expand_builtin_memcpy (arglist, target, mode); 4062 if (target) 4063 return target; 4064 break; 4065 4066 case BUILT_IN_MEMSET: 4067 target = expand_builtin_memset (exp, target, mode); 4068 if (target) 4069 return target; 4070 break; 4071 4072 case BUILT_IN_BZERO: 4073 target = expand_builtin_bzero (exp); 4074 if (target) 4075 return target; 4076 break; 4077 4078 case BUILT_IN_STRCMP: 4079 target = expand_builtin_strcmp (exp, target, mode); 4080 if (target) 4081 return target; 4082 break; 4083 4084 case BUILT_IN_STRNCMP: 4085 target = expand_builtin_strncmp (exp, target, mode); 4086 if (target) 4087 return target; 4088 break; 4089 4090 case BUILT_IN_BCMP: 4091 case BUILT_IN_MEMCMP: 4092 target = expand_builtin_memcmp (exp, arglist, target, mode); 4093 if (target) 4094 return target; 4095 break; 4096 4097 case BUILT_IN_SETJMP: 4098 target = expand_builtin_setjmp (arglist, target); 4099 if (target) 4100 return target; 4101 break; 4102 4103 /* __builtin_longjmp is passed a pointer to an array of five words. 4104 It's similar to the C library longjmp function but works with 4105 __builtin_setjmp above. */ 4106 case BUILT_IN_LONGJMP: 4107 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) 4108 break; 4109 else 4110 { 4111 rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget, 4112 VOIDmode, 0); 4113 rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), 4114 NULL_RTX, VOIDmode, 0); 4115 4116 if (value != const1_rtx) 4117 { 4118 error ("__builtin_longjmp second argument must be 1"); 4119 return const0_rtx; 4120 } 4121 4122 expand_builtin_longjmp (buf_addr, value); 4123 return const0_rtx; 4124 } 4125 4126 case BUILT_IN_TRAP: 4127 expand_builtin_trap (); 4128 return const0_rtx; 4129 4130 case BUILT_IN_FPUTS: 4131 target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 0); 4132 if (target) 4133 return target; 4134 break; 4135 case BUILT_IN_FPUTS_UNLOCKED: 4136 target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 1); 4137 if (target) 4138 return target; 4139 break; 4140 4141 /* Various hooks for the DWARF 2 __throw routine. */ 4142 case BUILT_IN_UNWIND_INIT: 4143 expand_builtin_unwind_init (); 4144 return const0_rtx; 4145 case BUILT_IN_DWARF_CFA: 4146 return virtual_cfa_rtx; 4147#ifdef DWARF2_UNWIND_INFO 4148 case BUILT_IN_DWARF_SP_COLUMN: 4149 return expand_builtin_dwarf_sp_column (); 4150 case BUILT_IN_INIT_DWARF_REG_SIZES: 4151 expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist)); 4152 return const0_rtx; 4153#endif 4154 case BUILT_IN_FROB_RETURN_ADDR: 4155 return expand_builtin_frob_return_addr (TREE_VALUE (arglist)); 4156 case BUILT_IN_EXTRACT_RETURN_ADDR: 4157 return expand_builtin_extract_return_addr (TREE_VALUE (arglist)); 4158 case BUILT_IN_EH_RETURN: 4159 expand_builtin_eh_return (TREE_VALUE (arglist), 4160 TREE_VALUE (TREE_CHAIN (arglist))); 4161 return const0_rtx; 4162#ifdef EH_RETURN_DATA_REGNO 4163 case BUILT_IN_EH_RETURN_DATA_REGNO: 4164 return expand_builtin_eh_return_data_regno (arglist); 4165#endif 4166 case BUILT_IN_VA_START: 4167 case BUILT_IN_STDARG_START: 4168 return expand_builtin_va_start (arglist); 4169 case BUILT_IN_VA_END: 4170 return expand_builtin_va_end (arglist); 4171 case BUILT_IN_VA_COPY: 4172 return expand_builtin_va_copy (arglist); 4173 case BUILT_IN_EXPECT: 4174 return expand_builtin_expect (arglist, target); 4175 case BUILT_IN_PREFETCH: 4176 expand_builtin_prefetch (arglist); 4177 return const0_rtx; 4178 4179 4180 default: /* just do library call, if unknown builtin */ 4181 if (!DECL_ASSEMBLER_NAME_SET_P (fndecl)) 4182 error ("built-in function `%s' not currently supported", 4183 IDENTIFIER_POINTER (DECL_NAME (fndecl))); 4184 } 4185 4186 /* The switch statement above can drop through to cause the function 4187 to be called normally. */ 4188 return expand_call (exp, target, ignore); 4189} 4190 4191/* Fold a call to __builtin_constant_p, if we know it will evaluate to a 4192 constant. ARGLIST is the argument list of the call. */ 4193 4194static tree 4195fold_builtin_constant_p (arglist) 4196 tree arglist; 4197{ 4198 if (arglist == 0) 4199 return 0; 4200 4201 arglist = TREE_VALUE (arglist); 4202 4203 /* We return 1 for a numeric type that's known to be a constant 4204 value at compile-time or for an aggregate type that's a 4205 literal constant. */ 4206 STRIP_NOPS (arglist); 4207 4208 /* If we know this is a constant, emit the constant of one. */ 4209 if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c' 4210 || (TREE_CODE (arglist) == CONSTRUCTOR 4211 && TREE_CONSTANT (arglist)) 4212 || (TREE_CODE (arglist) == ADDR_EXPR 4213 && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST)) 4214 return integer_one_node; 4215 4216 /* If we aren't going to be running CSE or this expression 4217 has side effects, show we don't know it to be a constant. 4218 Likewise if it's a pointer or aggregate type since in those 4219 case we only want literals, since those are only optimized 4220 when generating RTL, not later. 4221 And finally, if we are compiling an initializer, not code, we 4222 need to return a definite result now; there's not going to be any 4223 more optimization done. */ 4224 if (TREE_SIDE_EFFECTS (arglist) || cse_not_expected 4225 || AGGREGATE_TYPE_P (TREE_TYPE (arglist)) 4226 || POINTER_TYPE_P (TREE_TYPE (arglist)) 4227 || cfun == 0) 4228 return integer_zero_node; 4229 4230 return 0; 4231} 4232 4233/* Fold a call to __builtin_classify_type. */ 4234 4235static tree 4236fold_builtin_classify_type (arglist) 4237 tree arglist; 4238{ 4239 if (arglist == 0) 4240 return build_int_2 (no_type_class, 0); 4241 4242 return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0); 4243} 4244 4245/* Fold a call to __builtin_inf or __builtin_huge_val. */ 4246 4247static tree 4248fold_builtin_inf (type, warn) 4249 tree type; 4250 int warn; 4251{ 4252 REAL_VALUE_TYPE real; 4253 4254 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn) 4255 warning ("target format does not support infinity"); 4256 4257 real_inf (&real); 4258 return build_real (type, real); 4259} 4260 4261/* Fold a call to __builtin_nan or __builtin_nans. */ 4262 4263static tree 4264fold_builtin_nan (arglist, type, quiet) 4265 tree arglist, type; 4266 int quiet; 4267{ 4268 REAL_VALUE_TYPE real; 4269 const char *str; 4270 4271 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) 4272 return 0; 4273 str = c_getstr (TREE_VALUE (arglist)); 4274 if (!str) 4275 return 0; 4276 4277 if (!real_nan (&real, str, quiet, TYPE_MODE (type))) 4278 return 0; 4279 4280 return build_real (type, real); 4281} 4282 4283/* Used by constant folding to eliminate some builtin calls early. EXP is 4284 the CALL_EXPR of a call to a builtin function. */ 4285 4286tree 4287fold_builtin (exp) 4288 tree exp; 4289{ 4290 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); 4291 tree arglist = TREE_OPERAND (exp, 1); 4292 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); 4293 4294 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) 4295 return 0; 4296 4297 switch (fcode) 4298 { 4299 case BUILT_IN_CONSTANT_P: 4300 return fold_builtin_constant_p (arglist); 4301 4302 case BUILT_IN_CLASSIFY_TYPE: 4303 return fold_builtin_classify_type (arglist); 4304 4305 case BUILT_IN_STRLEN: 4306 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) 4307 { 4308 tree len = c_strlen (TREE_VALUE (arglist)); 4309 if (len) 4310 { 4311 /* Convert from the internal "sizetype" type to "size_t". */ 4312 if (size_type_node) 4313 len = convert (size_type_node, len); 4314 return len; 4315 } 4316 } 4317 break; 4318 4319 case BUILT_IN_INF: 4320 case BUILT_IN_INFF: 4321 case BUILT_IN_INFL: 4322 return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), true); 4323 4324 case BUILT_IN_HUGE_VAL: 4325 case BUILT_IN_HUGE_VALF: 4326 case BUILT_IN_HUGE_VALL: 4327 return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), false); 4328 4329 case BUILT_IN_NAN: 4330 case BUILT_IN_NANF: 4331 case BUILT_IN_NANL: 4332 return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), true); 4333 4334 case BUILT_IN_NANS: 4335 case BUILT_IN_NANSF: 4336 case BUILT_IN_NANSL: 4337 return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), false); 4338 4339 default: 4340 break; 4341 } 4342 4343 return 0; 4344} 4345 4346static tree 4347build_function_call_expr (fn, arglist) 4348 tree fn, arglist; 4349{ 4350 tree call_expr; 4351 4352 call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); 4353 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), 4354 call_expr, arglist); 4355 TREE_SIDE_EFFECTS (call_expr) = 1; 4356 return fold (call_expr); 4357} 4358 4359/* This function validates the types of a function call argument list 4360 represented as a tree chain of parameters against a specified list 4361 of tree_codes. If the last specifier is a 0, that represents an 4362 ellipses, otherwise the last specifier must be a VOID_TYPE. */ 4363 4364static int 4365validate_arglist VPARAMS ((tree arglist, ...)) 4366{ 4367 enum tree_code code; 4368 int res = 0; 4369 4370 VA_OPEN (ap, arglist); 4371 VA_FIXEDARG (ap, tree, arglist); 4372 4373 do 4374 { 4375 code = va_arg (ap, enum tree_code); 4376 switch (code) 4377 { 4378 case 0: 4379 /* This signifies an ellipses, any further arguments are all ok. */ 4380 res = 1; 4381 goto end; 4382 case VOID_TYPE: 4383 /* This signifies an endlink, if no arguments remain, return 4384 true, otherwise return false. */ 4385 res = arglist == 0; 4386 goto end; 4387 default: 4388 /* If no parameters remain or the parameter's code does not 4389 match the specified code, return false. Otherwise continue 4390 checking any remaining arguments. */ 4391 if (arglist == 0 4392 || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist)))) 4393 goto end; 4394 break; 4395 } 4396 arglist = TREE_CHAIN (arglist); 4397 } 4398 while (1); 4399 4400 /* We need gotos here since we can only have one VA_CLOSE in a 4401 function. */ 4402 end: ; 4403 VA_CLOSE (ap); 4404 4405 return res; 4406} 4407 4408/* Default version of target-specific builtin setup that does nothing. */ 4409 4410void 4411default_init_builtins () 4412{ 4413} 4414 4415/* Default target-specific builtin expander that does nothing. */ 4416 4417rtx 4418default_expand_builtin (exp, target, subtarget, mode, ignore) 4419 tree exp ATTRIBUTE_UNUSED; 4420 rtx target ATTRIBUTE_UNUSED; 4421 rtx subtarget ATTRIBUTE_UNUSED; 4422 enum machine_mode mode ATTRIBUTE_UNUSED; 4423 int ignore ATTRIBUTE_UNUSED; 4424{ 4425 return NULL_RTX; 4426} 4427