diff options
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 197 |
1 files changed, 183 insertions, 14 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 5e72df6..bb1f023 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -64,7 +64,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA const char *const built_in_class_names[4] = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"}; -#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT) STRINGX(X), +#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM) STRINGX(X), const char *const built_in_names[(int) END_BUILTINS] = { #include "builtins.def" @@ -74,6 +74,10 @@ const char *const built_in_names[(int) END_BUILTINS] = /* Setup an array of _DECL trees, make sure each element is initialized to NULL_TREE. */ tree built_in_decls[(int) END_BUILTINS]; +/* Declarations used when constructing the builtin implicitly in the compiler. + It may be NULL_TREE when this is invalid (for instance runtime is not + required to implement the function call in all cases. */ +tree implicit_built_in_decls[(int) END_BUILTINS]; static int get_pointer_alignment PARAMS ((tree, unsigned int)); static tree c_strlen PARAMS ((tree)); @@ -153,6 +157,7 @@ static tree fold_builtin_classify_type PARAMS ((tree)); static tree fold_builtin_inf PARAMS ((tree, int)); static tree fold_builtin_nan PARAMS ((tree, tree, int)); static int validate_arglist PARAMS ((tree, ...)); +static tree fold_trunc_transparent_mathfn PARAMS ((tree)); /* Return the alignment in bits of EXP, a pointer valued expression. But don't return more than MAX_ALIGN no matter what. @@ -1469,6 +1474,170 @@ expand_builtin_constant_p (exp) return tmp; } +/* Return mathematic function equivalent to FN but operating directly on TYPE, + if available. */ +tree +mathfn_built_in (type, fn) + tree type; + enum built_in_function fn; +{ + enum built_in_function fcode = NOT_BUILT_IN; + if (TYPE_MODE (type) == TYPE_MODE (double_type_node)) + switch (fn) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTF: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRT; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINF: + case BUILT_IN_SINL: + fcode = BUILT_IN_SIN; + break; + case BUILT_IN_COS: + case BUILT_IN_COSF: + case BUILT_IN_COSL: + fcode = BUILT_IN_COS; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPF: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXP; + break; + case BUILT_IN_FLOOR: + case BUILT_IN_FLOORF: + case BUILT_IN_FLOORL: + fcode = BUILT_IN_FLOOR; + break; + case BUILT_IN_CEIL: + case BUILT_IN_CEILF: + case BUILT_IN_CEILL: + fcode = BUILT_IN_CEIL; + break; + case BUILT_IN_TRUNC: + case BUILT_IN_TRUNCF: + case BUILT_IN_TRUNCL: + fcode = BUILT_IN_TRUNC; + break; + case BUILT_IN_ROUND: + case BUILT_IN_ROUNDF: + case BUILT_IN_ROUNDL: + fcode = BUILT_IN_ROUND; + break; + case BUILT_IN_NEARBYINT: + case BUILT_IN_NEARBYINTF: + case BUILT_IN_NEARBYINTL: + fcode = BUILT_IN_NEARBYINT; + break; + default: + abort (); + } + else if (TYPE_MODE (type) == TYPE_MODE (float_type_node)) + switch (fn) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTF: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRTF; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINF: + case BUILT_IN_SINL: + fcode = BUILT_IN_SINF; + break; + case BUILT_IN_COS: + case BUILT_IN_COSF: + case BUILT_IN_COSL: + fcode = BUILT_IN_COSF; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPF: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXPF; + break; + case BUILT_IN_FLOOR: + case BUILT_IN_FLOORF: + case BUILT_IN_FLOORL: + fcode = BUILT_IN_FLOORF; + break; + case BUILT_IN_CEIL: + case BUILT_IN_CEILF: + case BUILT_IN_CEILL: + fcode = BUILT_IN_CEILF; + break; + case BUILT_IN_TRUNC: + case BUILT_IN_TRUNCF: + case BUILT_IN_TRUNCL: + fcode = BUILT_IN_TRUNCF; + break; + case BUILT_IN_ROUND: + case BUILT_IN_ROUNDF: + case BUILT_IN_ROUNDL: + fcode = BUILT_IN_ROUNDF; + break; + case BUILT_IN_NEARBYINT: + case BUILT_IN_NEARBYINTF: + case BUILT_IN_NEARBYINTL: + fcode = BUILT_IN_NEARBYINTF; + break; + default: + abort (); + } + else if (TYPE_MODE (type) == TYPE_MODE (long_double_type_node)) + switch (fn) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTF: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRTL; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINF: + case BUILT_IN_SINL: + fcode = BUILT_IN_SINL; + break; + case BUILT_IN_COS: + case BUILT_IN_COSF: + case BUILT_IN_COSL: + fcode = BUILT_IN_COSL; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPF: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXPL; + break; + case BUILT_IN_FLOOR: + case BUILT_IN_FLOORF: + case BUILT_IN_FLOORL: + fcode = BUILT_IN_FLOORL; + break; + case BUILT_IN_CEIL: + case BUILT_IN_CEILF: + case BUILT_IN_CEILL: + fcode = BUILT_IN_CEILL; + break; + case BUILT_IN_TRUNC: + case BUILT_IN_TRUNCF: + case BUILT_IN_TRUNCL: + fcode = BUILT_IN_TRUNCL; + break; + case BUILT_IN_ROUND: + case BUILT_IN_ROUNDF: + case BUILT_IN_ROUNDL: + fcode = BUILT_IN_ROUNDL; + break; + case BUILT_IN_NEARBYINT: + case BUILT_IN_NEARBYINTF: + case BUILT_IN_NEARBYINTL: + fcode = BUILT_IN_NEARBYINTL; + break; + default: + abort (); + } + return implicit_built_in_decls[fcode]; +} + /* Expand a call to one of the builtin math functions (sin, cos, or sqrt). Return 0 if a normal call should be emitted rather than expanding the function in-line. EXP is the expression that is a call to the builtin @@ -1756,7 +1925,7 @@ expand_builtin_strstr (arglist, target, mode) if (p2[1] != '\0') return 0; - fn = built_in_decls[BUILT_IN_STRCHR]; + fn = implicit_built_in_decls[BUILT_IN_STRCHR]; if (!fn) return 0; @@ -1860,7 +2029,7 @@ expand_builtin_strrchr (arglist, target, mode) if (! integer_zerop (s2)) return 0; - fn = built_in_decls[BUILT_IN_STRCHR]; + fn = implicit_built_in_decls[BUILT_IN_STRCHR]; if (!fn) return 0; @@ -1918,7 +2087,7 @@ expand_builtin_strpbrk (arglist, target, mode) if (p2[1] != '\0') return 0; /* Really call strpbrk. */ - fn = built_in_decls[BUILT_IN_STRCHR]; + fn = implicit_built_in_decls[BUILT_IN_STRCHR]; if (!fn) return 0; @@ -2057,7 +2226,7 @@ expand_builtin_strcpy (exp, target, mode) if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) return 0; - fn = built_in_decls[BUILT_IN_MEMCPY]; + fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; if (!fn) return 0; @@ -2159,7 +2328,7 @@ expand_builtin_strncpy (arglist, target, mode) } /* OK transform into builtin memcpy. */ - fn = built_in_decls[BUILT_IN_MEMCPY]; + fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; if (!fn) return 0; return expand_expr (build_function_call_expr (fn, arglist), @@ -2575,7 +2744,7 @@ expand_builtin_strcmp (exp, target, mode) if (TREE_SIDE_EFFECTS (len)) return 0; - fn = built_in_decls[BUILT_IN_MEMCMP]; + fn = implicit_built_in_decls[BUILT_IN_MEMCMP]; if (!fn) return 0; @@ -2669,7 +2838,7 @@ expand_builtin_strncmp (exp, target, mode) if (!len) return 0; - fn = built_in_decls[BUILT_IN_MEMCMP]; + fn = implicit_built_in_decls[BUILT_IN_MEMCMP]; if (!fn) return 0; @@ -2750,7 +2919,7 @@ expand_builtin_strncat (arglist, target, mode) { tree newarglist = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src)); - tree fn = built_in_decls[BUILT_IN_STRCAT]; + tree fn = implicit_built_in_decls[BUILT_IN_STRCAT]; /* If the replacement _DECL isn't initialized, don't do the transformation. */ @@ -2838,7 +3007,7 @@ expand_builtin_strcspn (arglist, target, mode) if (p2 && *p2 == '\0') { tree newarglist = build_tree_list (NULL_TREE, s1), - fn = built_in_decls[BUILT_IN_STRLEN]; + fn = implicit_built_in_decls[BUILT_IN_STRLEN]; /* If the replacement _DECL isn't initialized, don't do the transformation. */ @@ -3445,10 +3614,10 @@ expand_builtin_fputs (arglist, ignore, unlocked) int unlocked; { tree len, fn; - tree fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED] - : built_in_decls[BUILT_IN_FPUTC]; - tree fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED] - : built_in_decls[BUILT_IN_FWRITE]; + tree fn_fputc = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED] + : implicit_built_in_decls[BUILT_IN_FPUTC]; + tree fn_fwrite = unlocked ? implicit_built_in_decls[BUILT_IN_FWRITE_UNLOCKED] + : implicit_built_in_decls[BUILT_IN_FWRITE]; /* If the return value is used, or the replacement _DECL isn't initialized, don't do the transformation. */ |