This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[jit] Check argument types within gcc_jit_context_new_call


Committed to branch dmalcolm/jit:

gcc/jit/
	* internal-api.c (gcc::jit::recording::type::get_pointer):
	Ensure that repeated calls yield the same type.
	(gcc::jit::recording::memento_of_get_pointer::
	accepts_writes_from): New.
	(gcc::jit::recording::context::new_call): Move
	the existing argument checking to...

	* libgccjit.c (gcc_jit_context_new_call): ...here, and add
	checking of the types of the arguments against the function.
	(RETURN_VAL_IF_FAIL_PRINTF6): New.
	(RETURN_NULL_IF_FAIL_PRINTF6): New.

	* internal-api.h (gcc::jit::recording::type): New field
	m_pointer_to_this_type, for use by get_pointer method.
	(gcc::jit::recording::memento_of_get_pointer::
	accepts_writes_from): New.
	(gcc::jit::recording::function::get_param): New.

	* TODO.rst (argument checking of gcc_jit_context_new_call): Done.

gcc/testsuite/
	* jit.dg/test-error-call-with-mismatching-args.c: New test case.
---
 gcc/jit/ChangeLog.jit                              | 22 ++++++
 gcc/jit/TODO.rst                                   |  2 -
 gcc/jit/internal-api.c                             | 37 ++++------
 gcc/jit/internal-api.h                             |  9 ++-
 gcc/jit/libgccjit.c                                | 51 +++++++++++++
 gcc/testsuite/ChangeLog.jit                        |  4 +
 .../jit.dg/test-error-call-with-mismatching-args.c | 85 ++++++++++++++++++++++
 7 files changed, 184 insertions(+), 26 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-error-call-with-mismatching-args.c

diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index de92fbe..58e82eb 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,5 +1,27 @@
 2014-01-30  David Malcolm  <dmalcolm@redhat.com>
 
+	* internal-api.c (gcc::jit::recording::type::get_pointer):
+	Ensure that repeated calls yield the same type.
+	(gcc::jit::recording::memento_of_get_pointer::
+	accepts_writes_from): New.
+	(gcc::jit::recording::context::new_call): Move
+	the existing argument checking to...
+
+	* libgccjit.c (gcc_jit_context_new_call): ...here, and add
+	checking of the types of the arguments against the function.
+	(RETURN_VAL_IF_FAIL_PRINTF6): New.
+	(RETURN_NULL_IF_FAIL_PRINTF6): New.
+
+	* internal-api.h (gcc::jit::recording::type): New field
+	m_pointer_to_this_type, for use by get_pointer method.
+	(gcc::jit::recording::memento_of_get_pointer::
+	accepts_writes_from): New.
+	(gcc::jit::recording::function::get_param): New.
+
+	* TODO.rst (argument checking of gcc_jit_context_new_call): Done.
+
+2014-01-30  David Malcolm  <dmalcolm@redhat.com>
+
 	* TODO.rst: begin a list of error-checking we could do that this
 	commit *doesn't* cover.
 
diff --git a/gcc/jit/TODO.rst b/gcc/jit/TODO.rst
index 79b4efa..4f16ae4 100644
--- a/gcc/jit/TODO.rst
+++ b/gcc/jit/TODO.rst
@@ -118,8 +118,6 @@ Initial Release
 
     * gcc_jit_context_new_comparison: must be numeric or pointer types
 
-    * gcc_jit_context_new_call: check the types of the args
-
     * gcc_jit_context_new_array_lookup: "ptr" must be of pointer type;
       "index" must be of numeric type.
 
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index 5e72e62..58495ac 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -355,26 +355,6 @@ recording::context::new_call (recording::location *loc,
 			      function *func,
 			      int numargs , recording::rvalue **args)
 {
-  int min_num_params = func->get_params ().length ();
-  bool is_variadic = func->is_variadic ();
-  if (numargs < min_num_params)
-    {
-      add_error (("gcc_jit_context_new_call: "
-		  "not enough arguments to function \"%s\""
-		  " (got %i args, expected %i)"),
-		 func->get_name ()->c_str (),
-		 numargs, min_num_params);
-      return NULL;
-    }
-  if (numargs > min_num_params && !is_variadic)
-    {
-      add_error (("gcc_jit_context_new_call: "
-		  "too many arguments to function \"%s\""
-		  " (got %i args, expected %i)"),
-		 func->get_name ()->c_str (),
-		 numargs, min_num_params);
-      return NULL;
-    }
   recording::rvalue *result = new call (this, loc, func, numargs, args);
   record (result);
   return result;
@@ -590,9 +570,12 @@ recording::location::make_debug_string ()
 recording::type *
 recording::type::get_pointer ()
 {
-  recording::type *result = new memento_of_get_pointer (this);
-  m_ctxt->record (result);
-  return result;
+  if (!m_pointer_to_this_type)
+    {
+      m_pointer_to_this_type = new memento_of_get_pointer (this);
+      m_ctxt->record (m_pointer_to_this_type);
+    }
+  return m_pointer_to_this_type;
 }
 
 recording::type *
@@ -692,6 +675,14 @@ recording::memento_of_get_type::make_debug_string ()
 }
 
 /* gcc::jit::recording::memento_of_get_pointer:: */
+bool
+recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
+{
+  /* It's OK to assign to a (const T *) from a (T *).  */
+  return m_other_type->unqualified ()
+    ->accepts_writes_from (rtype->dereference ());
+}
+
 void
 recording::memento_of_get_pointer::replay_into (replayer *)
 {
diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h
index a2848a8..fce6927 100644
--- a/gcc/jit/internal-api.h
+++ b/gcc/jit/internal-api.h
@@ -408,8 +408,12 @@ public:
 
 protected:
   type (context *ctxt)
-    : memento (ctxt) {}
+    : memento (ctxt),
+    m_pointer_to_this_type (NULL)
+  {}
 
+private:
+  type *m_pointer_to_this_type;
 };
 
 /* Result of "gcc_jit_type_get_type".  */
@@ -456,6 +460,8 @@ public:
 
   type *dereference () { return m_other_type; }
 
+  bool accepts_writes_from (type *rtype);
+
   void replay_into (replayer *r);
 
 private:
@@ -718,6 +724,7 @@ public:
   type *get_return_type () const { return m_return_type; }
   string * get_name () const { return m_name; }
   vec<param *> get_params () const { return m_params; }
+  param *get_param (int i) const { return m_params[i]; }
   bool is_variadic () const { return m_is_variadic; }
 
 private:
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 58037e1..345f74b 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -96,6 +96,16 @@ struct gcc_jit_loop : public gcc::jit::recording::loop
       }								\
   JIT_END_STMT
 
+#define RETURN_VAL_IF_FAIL_PRINTF6(TEST_EXPR, RETURN_EXPR, CTXT, ERR_FMT, A0, A1, A2, A3, A4, A5) \
+  JIT_BEGIN_STMT							\
+    if (!(TEST_EXPR))							\
+      {								\
+	jit_error ((CTXT), "%s: " ERR_FMT,				\
+		   __func__, (A0), (A1), (A2), (A3), (A4), (A5));	\
+	return (RETURN_EXPR);						\
+      }								\
+  JIT_END_STMT
+
 #define RETURN_NULL_IF_FAIL(TEST_EXPR, CTXT, ERR_MSG) \
   RETURN_VAL_IF_FAIL ((TEST_EXPR), NULL, (CTXT), (ERR_MSG))
 
@@ -105,6 +115,9 @@ struct gcc_jit_loop : public gcc::jit::recording::loop
 #define RETURN_NULL_IF_FAIL_PRINTF3(TEST_EXPR, CTXT, ERR_FMT, A0, A1, A2) \
   RETURN_VAL_IF_FAIL_PRINTF3 (TEST_EXPR, NULL, CTXT, ERR_FMT, A0, A1, A2)
 
+#define RETURN_NULL_IF_FAIL_PRINTF6(TEST_EXPR, CTXT, ERR_FMT, A0, A1, A2, A3, A4, A5) \
+  RETURN_VAL_IF_FAIL_PRINTF6 (TEST_EXPR, NULL, CTXT, ERR_FMT, A0, A1, A2, A3, A4, A5)
+
 #define RETURN_IF_FAIL(TEST_EXPR, CTXT, ERR_MSG)			\
   JIT_BEGIN_STMT							\
     if (!(TEST_EXPR))							\
@@ -476,6 +489,44 @@ gcc_jit_context_new_call (gcc_jit_context *ctxt,
   if (numargs)
     RETURN_NULL_IF_FAIL (args, ctxt, "NULL args");
 
+  int min_num_params = func->get_params ().length ();
+  bool is_variadic = func->is_variadic ();
+
+  RETURN_NULL_IF_FAIL_PRINTF3 (
+    numargs >= min_num_params,
+    ctxt,
+    "not enough arguments to function \"%s\""
+    " (got %i args, expected %i)",
+    func->get_name ()->c_str (),
+    numargs, min_num_params);
+
+  RETURN_NULL_IF_FAIL_PRINTF3 (
+    (numargs == min_num_params || is_variadic),
+    ctxt,
+    "too many arguments to function \"%s\""
+    " (got %i args, expected %i)",
+    func->get_name ()->c_str (),
+    numargs, min_num_params);
+
+  for (int i = 0; i < min_num_params; i++)
+    {
+      gcc::jit::recording::param *param = func->get_param (i);
+      gcc_jit_rvalue *arg = args[i];
+
+      RETURN_NULL_IF_FAIL_PRINTF6 (
+	compatible_types (param->get_type (),
+			  arg->get_type ()),
+	ctxt,
+	"mismatching types for argument %d of function \"%s\":"
+	" assignment to param %s (type: %s) from %s (type: %s)",
+	i + 1,
+	func->get_name ()->c_str (),
+	param->get_debug_string (),
+	param->get_type ()->get_debug_string (),
+	arg->get_debug_string (),
+	arg->get_type ()->get_debug_string ());
+    }
+
   return (gcc_jit_rvalue *)ctxt->new_call (loc,
 					   func,
 					   numargs,
diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit
index bd20f8c..b1ab250 100644
--- a/gcc/testsuite/ChangeLog.jit
+++ b/gcc/testsuite/ChangeLog.jit
@@ -1,5 +1,9 @@
 2014-01-30  David Malcolm  <dmalcolm@redhat.com>
 
+	* jit.dg/test-error-call-with-mismatching-args.c: New test case.
+
+2014-01-30  David Malcolm  <dmalcolm@redhat.com>
+
 	* jit.dg/test-error-accessing-field-in-other-struct.c: New test
 	case.
 	* jit.dg/test-error-dereference-field-of-non-pointer.c: Likewise.
diff --git a/gcc/testsuite/jit.dg/test-error-call-with-mismatching-args.c b/gcc/testsuite/jit.dg/test-error-call-with-mismatching-args.c
new file mode 100644
index 0000000..4f0b105
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-call-with-mismatching-args.c
@@ -0,0 +1,85 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  extern void
+  called_function (void *ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Let's try to inject the equivalent of:
+     extern void called_function (void *ptr);
+
+     void
+     test_fn ()
+     {
+        called_function (42);
+     }
+
+     and verify that the API complains about the mismatching argument
+     type ("int" vs "void *").  */
+  gcc_jit_type *void_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+  gcc_jit_type *void_ptr_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID_PTR);
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+  /* Declare the imported function.  */
+  gcc_jit_param *param =
+    gcc_jit_context_new_param (ctxt, NULL, void_ptr_type, "ptr");
+  gcc_jit_function *called_fn =
+    gcc_jit_context_new_function (ctxt, NULL,
+                                  GCC_JIT_FUNCTION_IMPORTED,
+                                  void_type,
+                                  "called_function",
+                                  1, &param,
+                                  0);
+
+  /* Build the test_fn.  */
+  gcc_jit_function *test_fn =
+    gcc_jit_context_new_function (ctxt, NULL,
+                                  GCC_JIT_FUNCTION_EXPORTED,
+                                  void_type,
+                                  "test_fn",
+                                  0, NULL,
+                                  0);
+  /* called_function (42);  */
+  gcc_jit_rvalue *arg =
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 42);
+
+  gcc_jit_function_add_eval (
+    test_fn, NULL,
+    gcc_jit_context_new_call (ctxt,
+                              NULL,
+                              called_fn,
+                              1, &arg));
+  /* the above has the wrong type for argument 1.  */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted.  */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      ("gcc_jit_context_new_call:"
+		       " mismatching types for argument 1"
+		       " of function \"called_function\":"
+		       " assignment to param ptr (type: void *)"
+		       " from (int)42 (type: int)"));
+}
+
-- 
1.7.11.7


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]