static rtx expand_builtin_expect PARAMS ((tree, rtx));
static tree fold_builtin_constant_p PARAMS ((tree));
static tree build_function_call_expr PARAMS ((tree, tree));
+static int validate_arglist PARAMS ((tree, ...));
/* Return the alignment in bits of EXP, a pointer valued expression.
But don't return more than MAX_ALIGN no matter what.
{
rtx buf_addr, next_lab, cont_lab;
- if (arglist == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
+ if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
return NULL_RTX;
if (target == 0 || GET_CODE (target) != REG
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
tree arglist = TREE_OPERAND (exp, 1);
- if (arglist == 0
- /* Arg could be wrong type if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE)
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
return 0;
/* Stabilize and compute the argument. */
tree arglist = TREE_OPERAND (exp, 1);
enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
+ if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
rtx target;
enum machine_mode mode;
{
- if (arglist == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
|| current_function_check_memory_usage)
return 0;
else
rtx target;
enum machine_mode mode;
{
- if (arglist == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != INTEGER_TYPE
+ if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
|| current_function_check_memory_usage)
return 0;
else
rtx target;
enum machine_mode mode;
{
- if (arglist == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != INTEGER_TYPE
+ if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
|| current_function_check_memory_usage)
return 0;
else
rtx target;
enum machine_mode mode;
{
- if (arglist == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
|| current_function_check_memory_usage)
return 0;
else
expand_builtin_memcpy (arglist)
tree arglist;
{
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
- != POINTER_TYPE)
- || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE
- (TREE_CHAIN (TREE_CHAIN (arglist)))))
- != INTEGER_TYPE))
+ if (!validate_arglist (arglist,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
tree arglist = TREE_OPERAND (exp, 1);
rtx result;
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
- != POINTER_TYPE))
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
rtx target;
enum machine_mode mode;
{
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
- != POINTER_TYPE)
- || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE
- (TREE_CHAIN (TREE_CHAIN (arglist)))))
- != INTEGER_TYPE))
+ if (!validate_arglist (arglist,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
{
tree arglist = TREE_OPERAND (exp, 1);
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
- != INTEGER_TYPE)
- || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
- || (INTEGER_TYPE
- != (TREE_CODE (TREE_TYPE
- (TREE_VALUE
- (TREE_CHAIN (TREE_CHAIN (arglist))))))))
+ if (!validate_arglist (arglist,
+ POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
tree dest, size, newarglist;
rtx result;
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (dest = TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || (TREE_CODE (TREE_TYPE (size = TREE_VALUE (TREE_CHAIN (arglist))))
- != INTEGER_TYPE))
+ if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return NULL_RTX;
+ dest = TREE_VALUE (arglist);
+ size = TREE_VALUE (TREE_CHAIN (arglist));
+
/* New argument list transforming bzero(ptr x, int y) to
memset(ptr x, int 0, size_t y). */
if (current_function_check_memory_usage)
return 0;
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
- || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
+ if (!validate_arglist (arglist,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
{
if (current_function_check_memory_usage)
return 0;
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
- != POINTER_TYPE))
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
arg1 = TREE_VALUE (arglist);
if (current_function_check_memory_usage)
return 0;
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
- || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
+ if (!validate_arglist (arglist,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
arg1 = TREE_VALUE (arglist);
if (current_function_check_memory_usage)
return 0;
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
- != POINTER_TYPE))
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
if (current_function_check_memory_usage)
return 0;
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
- != POINTER_TYPE)
- || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE
- (TREE_CHAIN (TREE_CHAIN (arglist)))))
- != INTEGER_TYPE))
+ if (!validate_arglist (arglist,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
if (current_function_check_memory_usage)
return 0;
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
- != POINTER_TYPE))
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
if (current_function_check_memory_usage)
return 0;
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
- || TREE_CHAIN (arglist) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
- != POINTER_TYPE))
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
{
rtx op0;
- if (arglist == 0
- /* Arg could be non-integer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
+ if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
return 0;
/* Compute the argument. */
rtx target, subtarget;
{
rtx op0;
- if (arglist == 0
- /* Arg could be non-integer if user redeclared this fcn wrong. */
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
+ if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
return 0;
/* Compute the argument. */
return 0;
/* Verify the arguments in the original call. */
- if (arglist == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
- || TREE_CHAIN (arglist) == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
- != POINTER_TYPE)
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
|| current_function_check_memory_usage)
return 0;
computed? We'll also need a safe worst case value for varargs
functions. */
case BUILT_IN_APPLY:
- if (arglist == 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
- || TREE_CHAIN (arglist) == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
- || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
+ if (!validate_arglist (arglist, POINTER_TYPE,
+ POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
+ && !validate_arglist (arglist, REFERENCE_TYPE,
+ POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return const0_rtx;
else
{
value described by RESULT. RESULT is address of the block of
memory returned by __builtin_apply. */
case BUILT_IN_RETURN:
- if (arglist
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE)
+ if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
expand_builtin_return (expand_expr (TREE_VALUE (arglist),
NULL_RTX, VOIDmode, 0));
return const0_rtx;
It's similar to the C library longjmp function but works with
__builtin_setjmp above. */
case BUILT_IN_LONGJMP:
- if (arglist == 0 || TREE_CHAIN (arglist) == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
+ if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
break;
else
{
return fold_builtin_constant_p (arglist);
case BUILT_IN_STRLEN:
- if (arglist != 0
- /* Arg could be non-pointer if user redeclared this fcn wrong. */
- && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE)
+ if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
{
tree len = c_strlen (TREE_VALUE (arglist));
if (len != 0)
TREE_SIDE_EFFECTS (call_expr) = 1;
return fold (call_expr);
}
+
+/* This function validates the types of a function call argument list
+ represented as a tree chain of parameters against a specified list
+ of tree_codes. If the last specifier is a 0, that represents an
+ ellipses, otherwise the last specifier must be a VOID_TYPE. */
+static int
+validate_arglist VPARAMS ((tree arglist, ...))
+{
+#ifndef ANSI_PROTOTYPES
+ tree arglist;
+#endif
+ enum tree_code code;
+ va_list ap;
+
+ VA_START (ap, arglist);
+
+#ifndef ANSI_PROTOTYPES
+ arglist = va_arg (ap, tree);
+#endif
+
+ do {
+ code = va_arg (ap, enum tree_code);
+ switch (code)
+ {
+ case 0:
+ /* This signifies an ellipses, any further arguments are all ok. */
+ va_end (ap);
+ return 1;
+ case VOID_TYPE:
+ /* This signifies an endlink, if no arguments remain, return
+ true, otherwise return false. */
+ va_end (ap);
+ return (arglist == 0);
+ default:
+ /* If no parameters remain or the parameter's code does not
+ match the specified code, return false. Otherwise continue
+ checking any remaining arguments. */
+ if (arglist == 0 || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
+ {
+ va_end (ap);
+ return 0;
+ }
+ break;
+ }
+ arglist = TREE_CHAIN (arglist);
+ } while (1);
+}