diff options
Diffstat (limited to 'gcc/config/rs6000/rs6000-c.c')
-rw-r--r-- | gcc/config/rs6000/rs6000-c.c | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index ee2db96f2bd..cacaea00bd4 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -846,7 +846,7 @@ altivec_build_resolved_builtin (tree *args, int n, tree impl_fndecl = rs6000_builtin_decls[desc->overloaded_code]; tree ret_type = rs6000_builtin_type (desc->ret_type); tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (impl_fndecl)); - tree arg_type[3]; + tree arg_type[4]; tree call; int i; @@ -895,6 +895,13 @@ altivec_build_resolved_builtin (tree *args, int n, fully_fold_convert (arg_type[1], args[1]), fully_fold_convert (arg_type[2], args[2])); break; + case 4: + call = build_call_expr (impl_fndecl, 4, + fully_fold_convert (arg_type[0], args[0]), + fully_fold_convert (arg_type[1], args[1]), + fully_fold_convert (arg_type[2], args[2]), + fully_fold_convert (arg_type[3], args[3])); + break; default: gcc_unreachable (); } @@ -913,7 +920,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_MD_FUNCTION_CODE (fndecl); tree fnargs = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); - tree types[3], args[3]; + tree types[4], args[4]; const struct altivec_builtin_types *desc; unsigned int n; @@ -1606,7 +1613,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, if (arg == error_mark_node) return error_mark_node; - if (n >= 3) + if (n >= 4) abort (); arg = default_conversion (arg); @@ -1789,6 +1796,40 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, unsupported_builtin = true; } } + else if (fcode == FUTURE_BUILTIN_VEC_XXEVAL) + { + /* Need to special case __builtin_vec_xxeval because this takes + 4 arguments, and the existing infrastructure handles no + more than three. */ + if (nargs != 4) + { + error ("builtin %qs requires 4 arguments", + "__builtin_vec_xxeval"); + return error_mark_node; + } + for ( ; desc->code == fcode; desc++) + { + if (rs6000_builtin_type_compatible (types[0], desc->op1) + && rs6000_builtin_type_compatible (types[1], desc->op2) + && rs6000_builtin_type_compatible (types[2], desc->op3) + && rs6000_builtin_type_compatible (types[3], + RS6000_BTI_UINTQI)) + { + if (rs6000_builtin_decls[desc->overloaded_code] == NULL_TREE) + unsupported_builtin = true; + else + { + result = altivec_build_resolved_builtin (args, n, desc); + if (rs6000_builtin_is_supported_p (desc->overloaded_code)) + return result; + /* Allow loop to continue in case a different + definition is supported. */ + overloaded_code = desc->overloaded_code; + unsupported_builtin = true; + } + } + } + } else { /* For arguments after the last, we have RS6000_BTI_NOT_OPAQUE in |