Detailed comments for "all signed" and "all unsigned" types.
authorJustin Seyster <jseyster@cs.sunysb.edu>
Tue, 24 Aug 2010 20:04:51 +0000 (16:04 -0400)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Tue, 24 Aug 2010 20:04:51 +0000 (16:04 -0400)
src/aop-pc-fun-call.c

index 04834a5be1575a7c2b3ded3da60d76cff7269d24..f87c587a322326f76fb20104a254640294099bfa 100644 (file)
@@ -73,20 +73,102 @@ get_function_name (gimple call_stmt)
     }
 }
 
-/* Given a GIMPLE_CALL statement, return the type of the nth parameter
-   passed if there is an nth parameter or NULL if there is no nth
-   parameter. */
+/* Given a GIMPLE_CALL statement, return the FUNCTION_TYPE tree node
+   that represents the function prototype. */
 static tree
-get_param_type (gimple call_stmt, int n)
+get_function_prototype (gimple call_stmt)
 {
+  tree func;
+  tree func_type_pointer;
+  tree func_type;
+
   aop_assert (gimple_code (call_stmt) == GIMPLE_CALL);
 
+  func = gimple_call_fn (call_stmt);
+
+  /* Get the function type.  The func tree should have a pointer type,
+     pointing to the actual function type. */
+  func_type_pointer = TREE_TYPE (func);
+  aop_assert (TREE_CODE (func_type_pointer) == POINTER_TYPE);
+  func_type = TREE_TYPE (func_type_pointer);
+  aop_assert (TREE_CODE (func_type) == FUNCTION_TYPE);
+
+  return func_type;
+}
+
+/* Unfortunately, the type for a parameter is encoded in two different
+   places: the _formal_ parameter and the _actual_ parameter.  These
+   two types should always be the same, but in some edge cases they
+   are not.  In general, we give priority to the formal parameter type
+   when possible.
+
+   The formal parameter type is the type that the function expects to
+   be passed as encoded in the function declaration.
+
+   The actual parameter type is the type of the value passed at the
+   call site as encoded in the GIMPLE_CALL statement.
+
+   In particular, when passing a literal integer constant to a
+   function that expects a uint8 or uint16, GCC sometimes incorrectly
+   allows the actual parameter to have a signed type (whereas the
+   formal parameter has an unsigned type).
+
+   C vararg functions are not type safe, so there is no formal
+   parameter for any varargs argument.  In the case of a vararg
+   argument, we must resort to the actual parameter type. */
+static tree
+get_formal_param_type (gimple call_stmt, int n)
+{
+  int i;
+  tree func_type;
+  tree type_list_node;
+  tree formal_type = NULL;
+
+  func_type = get_function_prototype (call_stmt);
+  type_list_node = TYPE_ARG_TYPES (func_type);
+  i = 0;
+  while (type_list_node != void_list_node && type_list_node != NULL)
+    {
+      if (i == n)
+       {
+         formal_type = TREE_VALUE (type_list_node);
+         break;
+       }
+
+      type_list_node = TREE_CHAIN (type_list_node);
+      i++;
+    }
+
+  return formal_type;
+}
+
+/* See comment for get_formal_param_type(). */
+static tree
+get_actual_param_type (gimple call_stmt, int n)
+{
   if (n < gimple_call_num_args (call_stmt))
     return TREE_TYPE (gimple_call_arg (call_stmt, n));
   else
     return NULL;
 }
 
+/* Given a GIMPLE_CALL statement, return the type of the nth parameter
+   passed if there is an nth parameter or NULL if there is no nth
+   parameter. */
+static tree
+get_param_type (gimple call_stmt, int n)
+{
+  tree param_type;
+
+  aop_assert (gimple_code (call_stmt) == GIMPLE_CALL);
+
+  param_type = get_formal_param_type (call_stmt, n);
+  if (param_type == NULL)
+    param_type = get_actual_param_type (call_stmt, n);
+
+  return param_type;
+}
+
 /* Return true if a call statement matches the pointcut's criteria for
    name, return type, and argument types. */
 static bool