diff options
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 192 |
1 files changed, 135 insertions, 57 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index afeb9bc5ce6..6b131543e1e 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -124,10 +124,10 @@ static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode); static rtx expand_builtin_memset (tree, rtx, enum machine_mode); static rtx expand_builtin_bzero (tree); static rtx expand_builtin_strlen (tree, rtx, enum machine_mode); -static rtx expand_builtin_strstr (tree, rtx, enum machine_mode); -static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode); -static rtx expand_builtin_strchr (tree, rtx, enum machine_mode); -static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode); +static rtx expand_builtin_strstr (tree, tree, rtx, enum machine_mode); +static rtx expand_builtin_strpbrk (tree, tree, rtx, enum machine_mode); +static rtx expand_builtin_strchr (tree, tree, rtx, enum machine_mode); +static rtx expand_builtin_strrchr (tree, tree, rtx, enum machine_mode); static rtx expand_builtin_alloca (tree, rtx); static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab); static rtx expand_builtin_frame_address (tree, tree); @@ -165,7 +165,7 @@ static tree fold_builtin_bitop (tree); static tree fold_builtin_memcpy (tree); static tree fold_builtin_mempcpy (tree, tree, int); static tree fold_builtin_memmove (tree, tree); -static tree fold_builtin_strchr (tree); +static tree fold_builtin_strchr (tree, tree); static tree fold_builtin_memcmp (tree); static tree fold_builtin_strcmp (tree); static tree fold_builtin_strncmp (tree); @@ -179,9 +179,9 @@ static tree fold_builtin_abs (tree, tree); static tree fold_builtin_unordered_cmp (tree, enum tree_code, enum tree_code); static tree fold_builtin_1 (tree, bool); -static tree fold_builtin_strpbrk (tree); -static tree fold_builtin_strstr (tree); -static tree fold_builtin_strrchr (tree); +static tree fold_builtin_strpbrk (tree, tree); +static tree fold_builtin_strstr (tree, tree); +static tree fold_builtin_strrchr (tree, tree); static tree fold_builtin_strcat (tree); static tree fold_builtin_strncat (tree); static tree fold_builtin_strspn (tree); @@ -453,11 +453,16 @@ builtin_save_expr (tree exp) address located within it (depending on FNDECL_CODE). */ static rtx -expand_builtin_return_addr (enum built_in_function fndecl_code, int count, - rtx tem) +expand_builtin_return_addr (enum built_in_function fndecl_code, int count) { int i; +#ifdef INITIAL_FRAME_ADDRESS_RTX + rtx tem = INITIAL_FRAME_ADDRESS_RTX; +#else + rtx tem = hard_frame_pointer_rtx; +#endif + /* Some machines need special handling before we can access arbitrary frames. For example, on the sparc, we must first flush all register windows to the stack. */ @@ -973,12 +978,8 @@ expand_builtin_prefetch (tree arglist) static rtx get_memory_rtx (tree exp) { - rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_SUM); - rtx mem; - - addr = convert_memory_address (Pmode, addr); - - mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr)); + rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_NORMAL); + rtx mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr)); /* Get an expression we can use to find the attributes to assign to MEM. If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if @@ -2373,6 +2374,8 @@ expand_builtin_powi (tree exp, rtx target, rtx subtarget) tree arg0, arg1; rtx op0, op1; enum machine_mode mode; + /* APPLE LOCAL mainline 2005-03-30 */ + enum machine_mode mode2; if (! validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE)) return 0; @@ -2404,19 +2407,24 @@ expand_builtin_powi (tree exp, rtx target, rtx subtarget) /* Emit a libcall to libgcc. */ + /* APPLE LOCAL begin mainline 2005-03-30 */ + /* Mode of the 2nd argument must match that of an int. */ + mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0); + if (target == NULL_RTX) target = gen_reg_rtx (mode); op0 = expand_expr (arg0, subtarget, mode, 0); if (GET_MODE (op0) != mode) op0 = convert_to_mode (mode, op0, 0); - op1 = expand_expr (arg1, 0, word_mode, 0); - if (GET_MODE (op1) != word_mode) - op1 = convert_to_mode (word_mode, op1, 0); + op1 = expand_expr (arg1, 0, mode2, 0); + if (GET_MODE (op1) != mode2) + op1 = convert_to_mode (mode2, op1, 0); target = emit_library_call_value (powi_optab->handlers[(int) mode].libfunc, target, LCT_CONST_MAKE_BLOCK, mode, 2, - op0, mode, op1, word_mode); + op0, mode, op1, mode2); + /* APPLE LOCAL end mainline 2005-03-30 */ return target; } @@ -2534,11 +2542,11 @@ expand_builtin_strlen (tree arglist, rtx target, in TARGET, if convenient (and in mode MODE if that's convenient). */ static rtx -expand_builtin_strstr (tree arglist, rtx target, enum machine_mode mode) +expand_builtin_strstr (tree arglist, tree type, rtx target, enum machine_mode mode) { if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) { - tree result = fold_builtin_strstr (arglist); + tree result = fold_builtin_strstr (arglist, type); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); } @@ -2550,11 +2558,11 @@ expand_builtin_strstr (tree arglist, rtx target, enum machine_mode mode) in TARGET, if convenient (and in mode MODE if that's convenient). */ static rtx -expand_builtin_strchr (tree arglist, rtx target, enum machine_mode mode) +expand_builtin_strchr (tree arglist, tree type, rtx target, enum machine_mode mode) { if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) { - tree result = fold_builtin_strchr (arglist); + tree result = fold_builtin_strchr (arglist, type); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); @@ -2568,11 +2576,11 @@ expand_builtin_strchr (tree arglist, rtx target, enum machine_mode mode) in TARGET, if convenient (and in mode MODE if that's convenient). */ static rtx -expand_builtin_strrchr (tree arglist, rtx target, enum machine_mode mode) +expand_builtin_strrchr (tree arglist, tree type, rtx target, enum machine_mode mode) { if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) { - tree result = fold_builtin_strrchr (arglist); + tree result = fold_builtin_strrchr (arglist, type); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); } @@ -2584,11 +2592,11 @@ expand_builtin_strrchr (tree arglist, rtx target, enum machine_mode mode) in TARGET, if convenient (and in mode MODE if that's convenient). */ static rtx -expand_builtin_strpbrk (tree arglist, rtx target, enum machine_mode mode) +expand_builtin_strpbrk (tree arglist, tree type, rtx target, enum machine_mode mode) { if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) { - tree result = fold_builtin_strpbrk (arglist); + tree result = fold_builtin_strpbrk (arglist, type); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); } @@ -4221,8 +4229,7 @@ expand_builtin_frame_address (tree fndecl, tree arglist) { rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl), - tree_low_cst (TREE_VALUE (arglist), 1), - hard_frame_pointer_rtx); + tree_low_cst (TREE_VALUE (arglist), 1)); /* Some ports cannot access arbitrary stack frames. */ if (tem == NULL) @@ -4855,7 +4862,7 @@ expand_builtin_profile_func (bool exitp) emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this, Pmode, expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS, - 0, hard_frame_pointer_rtx), + 0), Pmode); return const0_rtx; @@ -5482,27 +5489,27 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, break; case BUILT_IN_STRSTR: - target = expand_builtin_strstr (arglist, target, mode); + target = expand_builtin_strstr (arglist, TREE_TYPE (exp), target, mode); if (target) return target; break; case BUILT_IN_STRPBRK: - target = expand_builtin_strpbrk (arglist, target, mode); + target = expand_builtin_strpbrk (arglist, TREE_TYPE (exp), target, mode); if (target) return target; break; case BUILT_IN_INDEX: case BUILT_IN_STRCHR: - target = expand_builtin_strchr (arglist, target, mode); + target = expand_builtin_strchr (arglist, TREE_TYPE (exp), target, mode); if (target) return target; break; case BUILT_IN_RINDEX: case BUILT_IN_STRRCHR: - target = expand_builtin_strrchr (arglist, target, mode); + target = expand_builtin_strrchr (arglist, TREE_TYPE (exp), target, mode); if (target) return target; break; @@ -5726,6 +5733,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, return target; break; + /* APPLE LOCAL begin lno */ + case BUILT_IN_MAYBE_INFINITE_LOOP: + /* This is just a fake statement that expands to nothing. */ + return const0_rtx; + /* APPLE LOCAL end lno */ + default: /* just do library call, if unknown builtin */ break; } @@ -7619,11 +7632,18 @@ fold_builtin_isdigit (tree arglist) else { /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */ - /* According to the C standard, isdigit is unaffected by locale. */ - tree arg = TREE_VALUE (arglist); - arg = fold_convert (unsigned_type_node, arg); + /* According to the C standard, isdigit is unaffected by locale. + However, it definitely is affected by the target character set. */ + tree arg; + unsigned HOST_WIDE_INT target_digit0 + = lang_hooks.to_target_charset ('0'); + + if (target_digit0 == 0) + return NULL_TREE; + + arg = fold_convert (unsigned_type_node, TREE_VALUE (arglist)); arg = build2 (MINUS_EXPR, unsigned_type_node, arg, - build_int_cst (unsigned_type_node, TARGET_DIGIT0)); + build_int_cst (unsigned_type_node, target_digit0)); arg = build2 (LE_EXPR, integer_type_node, arg, build_int_cst (unsigned_type_node, 9)); arg = fold (arg); @@ -7832,6 +7852,44 @@ fold_builtin_unordered_cmp (tree exp, fold (build2 (code, type, arg0, arg1)))); } +/* Fold a call to one of the external complex multiply libcalls. */ + +static tree +fold_builtin_complex_mul (tree type, tree arglist) +{ + tree ar, ai, br, bi; + + if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, REAL_TYPE, + REAL_TYPE, VOID_TYPE)) + return NULL; + + ar = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist); + ai = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist); + br = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist); + bi = TREE_VALUE (arglist); + + return fold_complex_mult_parts (type, ar, ai, br, bi); +} + +/* Fold a call to one of the external complex division libcalls. */ + +static tree +fold_builtin_complex_div (tree type, tree arglist) +{ + tree ar, ai, br, bi; + + if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, REAL_TYPE, + REAL_TYPE, VOID_TYPE)) + return NULL; + + ar = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist); + ai = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist); + br = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist); + bi = TREE_VALUE (arglist); + + return fold_complex_div_parts (type, ar, ai, br, bi, RDIV_EXPR); +} + /* Used by constant folding to simplify calls to builtin functions. EXP is the CALL_EXPR of a call to a builtin function. IGNORE is true if the result of the function call is ignored. This function returns NULL_TREE @@ -7843,11 +7901,13 @@ fold_builtin_1 (tree exp, bool ignore) tree fndecl = get_callee_fndecl (exp); tree arglist = TREE_OPERAND (exp, 1); tree type = TREE_TYPE (TREE_TYPE (fndecl)); + enum built_in_function fcode; if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) return targetm.fold_builtin (exp, ignore); - switch (DECL_FUNCTION_CODE (fndecl)) + fcode = DECL_FUNCTION_CODE (fndecl); + switch (fcode) { case BUILT_IN_FPUTS: return fold_builtin_fputs (arglist, ignore, false, NULL_TREE); @@ -7856,7 +7916,7 @@ fold_builtin_1 (tree exp, bool ignore) return fold_builtin_fputs (arglist, ignore, true, NULL_TREE); case BUILT_IN_STRSTR: - return fold_builtin_strstr (arglist); + return fold_builtin_strstr (arglist, type); case BUILT_IN_STRCAT: return fold_builtin_strcat (arglist); @@ -7872,11 +7932,11 @@ fold_builtin_1 (tree exp, bool ignore) case BUILT_IN_STRCHR: case BUILT_IN_INDEX: - return fold_builtin_strchr (arglist); + return fold_builtin_strchr (arglist, type); case BUILT_IN_STRRCHR: case BUILT_IN_RINDEX: - return fold_builtin_strrchr (arglist); + return fold_builtin_strrchr (arglist, type); case BUILT_IN_STRCPY: return fold_builtin_strcpy (exp, NULL_TREE); @@ -7891,7 +7951,7 @@ fold_builtin_1 (tree exp, bool ignore) return fold_builtin_strncmp (arglist); case BUILT_IN_STRPBRK: - return fold_builtin_strpbrk (arglist); + return fold_builtin_strpbrk (arglist, type); case BUILT_IN_BCMP: case BUILT_IN_MEMCMP: @@ -8177,7 +8237,17 @@ fold_builtin_1 (tree exp, bool ignore) break; default: - break; + if (fcode >= BUILT_IN_COMPLEX_MUL_MIN + && fcode <= BUILT_IN_COMPLEX_MUL_MAX) + return fold_builtin_complex_mul (type, arglist); + if (fcode >= BUILT_IN_COMPLEX_DIV_MIN + && fcode <= BUILT_IN_COMPLEX_DIV_MAX) + return fold_builtin_complex_div (type, arglist); + /* APPLE LOCAL begin constant cfstrings */ + /* Don't just do the library call if it's unknown, try using + our target version, then call the library call if that doesn't work. */ + return (*targetm.expand_tree_builtin) (fndecl, arglist,NULL_TREE); + /* APPLE LOCAL end constant cfstrings */ } return 0; @@ -8326,7 +8396,7 @@ readonly_data_expr (tree exp) form of the builtin function call. */ static tree -fold_builtin_strstr (tree arglist) +fold_builtin_strstr (tree arglist, tree type) { if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) return 0; @@ -8344,13 +8414,15 @@ fold_builtin_strstr (tree arglist) if (p1 != NULL) { const char *r = strstr (p1, p2); + tree tem; if (r == NULL) return build_int_cst (TREE_TYPE (s1), 0); /* Return an offset into the constant string argument. */ - return fold (build2 (PLUS_EXPR, TREE_TYPE (s1), - s1, build_int_cst (TREE_TYPE (s1), r - p1))); + tem = fold (build2 (PLUS_EXPR, TREE_TYPE (s1), + s1, build_int_cst (TREE_TYPE (s1), r - p1))); + return fold_convert (type, tem); } if (p2[0] == '\0') @@ -8390,7 +8462,7 @@ fold_builtin_strstr (tree arglist) form of the builtin function call. */ static tree -fold_builtin_strchr (tree arglist) +fold_builtin_strchr (tree arglist, tree type) { if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) return 0; @@ -8407,6 +8479,7 @@ fold_builtin_strchr (tree arglist) { char c; const char *r; + tree tem; if (target_char_cast (s2, &c)) return 0; @@ -8417,8 +8490,9 @@ fold_builtin_strchr (tree arglist) return build_int_cst (TREE_TYPE (s1), 0); /* Return an offset into the constant string argument. */ - return fold (build2 (PLUS_EXPR, TREE_TYPE (s1), - s1, build_int_cst (TREE_TYPE (s1), r - p1))); + tem = fold (build2 (PLUS_EXPR, TREE_TYPE (s1), + s1, build_int_cst (TREE_TYPE (s1), r - p1))); + return fold_convert (type, tem); } return 0; } @@ -8442,7 +8516,7 @@ fold_builtin_strchr (tree arglist) form of the builtin function call. */ static tree -fold_builtin_strrchr (tree arglist) +fold_builtin_strrchr (tree arglist, tree type) { if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) return 0; @@ -8460,6 +8534,7 @@ fold_builtin_strrchr (tree arglist) { char c; const char *r; + tree tem; if (target_char_cast (s2, &c)) return 0; @@ -8470,8 +8545,9 @@ fold_builtin_strrchr (tree arglist) return build_int_cst (TREE_TYPE (s1), 0); /* Return an offset into the constant string argument. */ - return fold (build2 (PLUS_EXPR, TREE_TYPE (s1), - s1, build_int_cst (TREE_TYPE (s1), r - p1))); + tem = fold (build2 (PLUS_EXPR, TREE_TYPE (s1), + s1, build_int_cst (TREE_TYPE (s1), r - p1))); + return fold_convert (type, tem); } if (! integer_zerop (s2)) @@ -8504,7 +8580,7 @@ fold_builtin_strrchr (tree arglist) form of the builtin function call. */ static tree -fold_builtin_strpbrk (tree arglist) +fold_builtin_strpbrk (tree arglist, tree type) { if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) return 0; @@ -8522,13 +8598,15 @@ fold_builtin_strpbrk (tree arglist) if (p1 != NULL) { const char *r = strpbrk (p1, p2); + tree tem; if (r == NULL) return build_int_cst (TREE_TYPE (s1), 0); /* Return an offset into the constant string argument. */ - return fold (build2 (PLUS_EXPR, TREE_TYPE (s1), - s1, build_int_cst (TREE_TYPE (s1), r - p1))); + tem = fold (build2 (PLUS_EXPR, TREE_TYPE (s1), + s1, build_int_cst (TREE_TYPE (s1), r - p1))); + return fold_convert (type, tem); } if (p2[0] == '\0') |