This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[jit] Add gcc_jit_context_get_first_error
- From: David Malcolm <dmalcolm at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org, jit at gcc dot gnu dot org
- Cc: David Malcolm <dmalcolm at redhat dot com>
- Date: Tue, 22 Oct 2013 13:08:33 -0400
- Subject: [jit] Add gcc_jit_context_get_first_error
- Authentication-results: sourceware.org; auth=none
Committed to dmalcolm/jit:
Add a way to query the first error message that occurred on a context.
I expect there often will be a cascade of followup errors: the first
error will often lead to a NULL return from an API call, which will then
erroneously (but safely) be used for further API calls. Under such
circumstances I believe the first error message will be the one that the
user cares about.
gcc/jit/
* internal-api.c (gcc::jit::context::add_error_va): Record the
first error that occurs on a context.
(gcc::jit::context::get_first_error): New.
* internal-api.h (gcc::jit::context::get_first_error): New.
(gcc::jit::context::m_first_error_str): New.
* libgccjit.c (gcc_jit_context_get_first_error): New.
* libgccjit.h (gcc_jit_context_get_first_error): New.
* libgccjit.map (gcc_jit_context_get_first_error): New.
gcc/testsuite/
* jit.dg/harness.h (verify_code): Add context param so that
test cases of failure can query errors on it.
(CHECK_STRING_VALUE): New.
(check_string_value): New.
(test_jit): Add user_data param and pass it to the code factory.
Pass context to verify_code, calling it before releasing said
context.
(main): Add NULL user_data to test_jit call.
* jit.dg/test-accessing-struct.c (verify_code): Add context
param.
* jit.dg/test-calling-external-function.c (verify_code):
Likewise.
* jit.dg/test-combination.c (verify_code): Likewise.
* jit.dg/test-dot-product.c (verify_code): Likewise.
* jit.dg/test-expressions.c (verify_code): Likewise.
* jit.dg/test-factorial.c (verify_code): Likewise.
* jit.dg/test-failure.c (verify_code): Likewise.
* jit.dg/test-fibonacci.c (verify_code): Likewise.
* jit.dg/test-hello-world.c (verify_code): Likewise.
* jit.dg/test-string-literal.c (verify_code): Likewise.
* jit.dg/test-sum-of-squares.c (verify_code): Likewise.
* jit.dg/test-types.c (verify_code): Likewise.
* jit.dg/test-using-global.c (verify_code): Likewise.
* jit.dg/test-null-passed-to-api.c (verify_code): Likewise;
use context to verify that the library provides a sane error
message to the client code.
---
gcc/jit/ChangeLog.jit | 11 ++++++
gcc/jit/internal-api.c | 16 ++++++++
gcc/jit/internal-api.h | 6 ++-
gcc/jit/libgccjit.c | 8 ++++
gcc/jit/libgccjit.h | 9 +++++
gcc/jit/libgccjit.map | 1 +
gcc/testsuite/ChangeLog.jit | 29 ++++++++++++++
gcc/testsuite/jit.dg/harness.h | 45 ++++++++++++++++++----
gcc/testsuite/jit.dg/test-accessing-struct.c | 2 +-
.../jit.dg/test-calling-external-function.c | 2 +-
gcc/testsuite/jit.dg/test-combination.c | 24 ++++++------
gcc/testsuite/jit.dg/test-dot-product.c | 2 +-
gcc/testsuite/jit.dg/test-expressions.c | 2 +-
gcc/testsuite/jit.dg/test-factorial.c | 2 +-
gcc/testsuite/jit.dg/test-failure.c | 2 +-
gcc/testsuite/jit.dg/test-fibonacci.c | 2 +-
gcc/testsuite/jit.dg/test-hello-world.c | 2 +-
gcc/testsuite/jit.dg/test-null-passed-to-api.c | 6 ++-
gcc/testsuite/jit.dg/test-string-literal.c | 2 +-
gcc/testsuite/jit.dg/test-sum-of-squares.c | 2 +-
gcc/testsuite/jit.dg/test-types.c | 2 +-
gcc/testsuite/jit.dg/test-using-global.c | 2 +-
22 files changed, 146 insertions(+), 33 deletions(-)
diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index 2cf5c8d..5e8d0f9 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,3 +1,14 @@
+2013-10-22 David Malcolm <dmalcolm@redhat.com>
+
+ * internal-api.c (gcc::jit::context::add_error_va): Record the
+ first error that occurs on a context.
+ (gcc::jit::context::get_first_error): New.
+ * internal-api.h (gcc::jit::context::get_first_error): New.
+ (gcc::jit::context::m_first_error_str): New.
+ * libgccjit.c (gcc_jit_context_get_first_error): New.
+ * libgccjit.h (gcc_jit_context_get_first_error): New.
+ * libgccjit.map (gcc_jit_context_get_first_error): New.
+
2013-10-21 David Malcolm <dmalcolm@redhat.com>
* internal-api.c (gcc::jit::context::compile): Correctly cleanup
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index d90f001..639cd49 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -1478,9 +1478,25 @@ add_error_va (const char *fmt, va_list ap)
error ("%s\n", buf);
+ if (!m_error_count)
+ {
+ strncpy (m_first_error_str, buf, sizeof(m_first_error_str));
+ m_first_error_str[sizeof(m_first_error_str) - 1] = '\0';
+ }
+
m_error_count++;
}
+const char *
+gcc::jit::context::
+get_first_error () const
+{
+ if (m_error_count)
+ return m_first_error_str;
+ else
+ return NULL;
+}
+
gcc::jit::result::
result(void *dso_handle)
: m_dso_handle(dso_handle)
diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h
index 1a8499f..01f0bb3 100644
--- a/gcc/jit/internal-api.h
+++ b/gcc/jit/internal-api.h
@@ -158,6 +158,9 @@ public:
add_error_va (const char *fmt, va_list ap)
GNU_PRINTF(2, 0);
+ const char *
+ get_first_error () const;
+
void
set_tree_location (tree t, location *loc);
@@ -193,6 +196,8 @@ private:
void *m_user_data;
int m_error_count;
+ char m_first_error_str[1024];
+ int m_cb_result; /* Result from client-provided code factory. */
/* Allocated using xmalloc (by xstrdup). */
char *m_path_template;
@@ -205,7 +210,6 @@ private:
char *m_path_s_file;
char *m_path_so_file;
- int m_cb_result; /* Result from client-provided code factory. */
vec<function *> m_functions;
const char *m_str_options[GCC_JIT_NUM_STR_OPTIONS];
int m_int_options[GCC_JIT_NUM_INT_OPTIONS];
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 40ac98d..3222144 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -726,6 +726,14 @@ gcc_jit_context_compile (gcc_jit_context *ctxt)
return (gcc_jit_result *)ctxt->compile ();
}
+const char *
+gcc_jit_context_get_first_error (gcc_jit_context *ctxt)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, "NULL context");
+
+ return ctxt->get_first_error ();
+}
+
void *
gcc_jit_result_get_code (gcc_jit_result *result,
const char *fnname)
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 12a715d..f058162 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -216,6 +216,15 @@ gcc_jit_context_set_bool_option (gcc_jit_context *ctxt,
extern gcc_jit_result *
gcc_jit_context_compile (gcc_jit_context *ctxt);
+/* To be called after a compile, this gives the first error message
+ that occurred on the context.
+
+ The returned string is valid for the rest of the lifetime of the
+ context.
+
+ If no errors occurred, this will be NULL. */
+extern const char *
+gcc_jit_context_get_first_error (gcc_jit_context *ctxt);
/* Locate a given function within the built machine code.
This will need to be cast to a function pointer of the
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index e2503e4..aaa2112 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -4,6 +4,7 @@
# Keep this list sorted alphabetically:
gcc_jit_context_acquire;
gcc_jit_context_compile;
+ gcc_jit_context_get_first_error;
gcc_jit_context_get_type;
gcc_jit_context_new_array_lookup;
gcc_jit_context_new_binary_op;
diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit
index 7190e09..0476507 100644
--- a/gcc/testsuite/ChangeLog.jit
+++ b/gcc/testsuite/ChangeLog.jit
@@ -1,3 +1,32 @@
+2013-10-22 David Malcolm <dmalcolm@redhat.com>
+
+ * jit.dg/harness.h (verify_code): Add context param so that
+ test cases of failure can query errors on it.
+ (CHECK_STRING_VALUE): New.
+ (check_string_value): New.
+ (test_jit): Add user_data param and pass it to the code factory.
+ Pass context to verify_code, calling it before releasing said
+ context.
+ (main): Add NULL user_data to test_jit call.
+ * jit.dg/test-accessing-struct.c (verify_code): Add context
+ param.
+ * jit.dg/test-calling-external-function.c (verify_code):
+ Likewise.
+ * jit.dg/test-combination.c (verify_code): Likewise.
+ * jit.dg/test-dot-product.c (verify_code): Likewise.
+ * jit.dg/test-expressions.c (verify_code): Likewise.
+ * jit.dg/test-factorial.c (verify_code): Likewise.
+ * jit.dg/test-failure.c (verify_code): Likewise.
+ * jit.dg/test-fibonacci.c (verify_code): Likewise.
+ * jit.dg/test-hello-world.c (verify_code): Likewise.
+ * jit.dg/test-string-literal.c (verify_code): Likewise.
+ * jit.dg/test-sum-of-squares.c (verify_code): Likewise.
+ * jit.dg/test-types.c (verify_code): Likewise.
+ * jit.dg/test-using-global.c (verify_code): Likewise.
+ * jit.dg/test-null-passed-to-api.c (verify_code): Likewise;
+ use context to verify that the library provides a sane error
+ message to the client code.
+
2013-10-21 David Malcolm <dmalcolm@redhat.com>
* jit.dg/test-expressions.c (test_global): New.
diff --git a/gcc/testsuite/jit.dg/harness.h b/gcc/testsuite/jit.dg/harness.h
index 4ffbcbf..8e75924 100644
--- a/gcc/testsuite/jit.dg/harness.h
+++ b/gcc/testsuite/jit.dg/harness.h
@@ -8,7 +8,7 @@
code_making_callback (gcc_jit_context *ctxt, void * user_data);
extern void
- verify_code (gcc_jit_result *result);
+ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result);
*/
#include <stdlib.h>
@@ -47,12 +47,15 @@ static char test[1024];
} \
} while (0)
+#define CHECK_STRING_VALUE(ACTUAL, EXPECTED) \
+ check_string_value ((ACTUAL), (EXPECTED));
+
/* Hooks that testcases should provide. */
extern int
code_making_callback (gcc_jit_context *ctxt, void * user_data);
extern void
-verify_code (gcc_jit_result *result);
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result);
/* Implement framework needed for turning the testcase hooks into an
executable. test-combination.c combines multiple testcases into one
@@ -60,9 +63,37 @@ verify_code (gcc_jit_result *result);
off this part of harness.h. */
#ifndef TEST_COMBINATION
+void check_string_value (const char *actual, const char *expected)
+{
+ if (actual && !expected)
+ {
+ fail ("%s: actual: \"%s\" != expected: NULL", test, actual);
+ fprintf (stderr, "incorrect value\n");
+ abort ();
+ }
+ if (expected && !actual)
+ {
+ fail ("%s: actual: NULL != expected: \"%s\"", test, expected);
+ fprintf (stderr, "incorrect value\n");
+ abort ();
+ }
+ if (actual && expected)
+ {
+ if (strcmp (actual, expected))
+ {
+ fail ("%s: actual: \"%s\" != expected: \"%s\"", test, actual, expected);
+ fprintf (stderr, "incorrect valuen");
+ abort ();
+ }
+ pass ("%s: actual: \"%s\" == expected: \"%s\"", test, actual, expected);
+ }
+ else
+ pass ("%s: actual: NULL == expected: NULL");
+}
+
/* Run one iteration of the test. */
static void
-test_jit (const char *argv0)
+test_jit (const char *argv0, void *user_data)
{
gcc_jit_context *ctxt;
gcc_jit_result *result;
@@ -70,7 +101,7 @@ test_jit (const char *argv0)
ctxt = gcc_jit_context_acquire ();
/* FIXME: error-handling */
- gcc_jit_context_set_code_factory (ctxt, code_making_callback, NULL);
+ gcc_jit_context_set_code_factory (ctxt, code_making_callback, user_data);
/* Set up options. */
gcc_jit_context_set_str_option (
@@ -106,9 +137,9 @@ test_jit (const char *argv0)
in a mutex for now. */
result = gcc_jit_context_compile (ctxt);
- gcc_jit_context_release (ctxt);
+ verify_code (ctxt, result);
- verify_code (result);
+ gcc_jit_context_release (ctxt);
/* Once we're done with the code, this unloads the built .so file: */
gcc_jit_result_release (result);
@@ -144,7 +175,7 @@ main (int argc, char **argv)
i, 5);
//printf ("ITERATION %d\n", i);
- test_jit (argv[0]);
+ test_jit (argv[0], NULL);
//printf ("\n");
}
diff --git a/gcc/testsuite/jit.dg/test-accessing-struct.c b/gcc/testsuite/jit.dg/test-accessing-struct.c
index 4e197c5..46c6f5b 100644
--- a/gcc/testsuite/jit.dg/test-accessing-struct.c
+++ b/gcc/testsuite/jit.dg/test-accessing-struct.c
@@ -88,7 +88,7 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data)
}
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
typedef void (*fn_type) (struct foo *);
CHECK_NON_NULL (result);
diff --git a/gcc/testsuite/jit.dg/test-calling-external-function.c b/gcc/testsuite/jit.dg/test-calling-external-function.c
index 6e5dd7d..bfc0641 100644
--- a/gcc/testsuite/jit.dg/test-calling-external-function.c
+++ b/gcc/testsuite/jit.dg/test-calling-external-function.c
@@ -95,7 +95,7 @@ called_function (int i, int j, int k)
}
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
typedef void (*fn_type) (int);
CHECK_NON_NULL (result);
diff --git a/gcc/testsuite/jit.dg/test-combination.c b/gcc/testsuite/jit.dg/test-combination.c
index 3338d94..00fbee6 100644
--- a/gcc/testsuite/jit.dg/test-combination.c
+++ b/gcc/testsuite/jit.dg/test-combination.c
@@ -115,17 +115,17 @@ code_making_callback (gcc_jit_context *ctxt, void * user_data)
}
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
- verify_code_accessing_struct (result);
- verify_code_calling_external_function (result);
- verify_code_dot_product (result);
- verify_code_expressions (result);
- verify_code_factorial (result);
- verify_code_fibonacci (result);
- verify_code_hello_world (result);
- verify_code_string_literal (result);
- verify_code_sum_of_squares (result);
- verify_code_types (result);
- verify_code_using_global (result);
+ verify_code_accessing_struct (ctxt, result);
+ verify_code_calling_external_function (ctxt, result);
+ verify_code_dot_product (ctxt, result);
+ verify_code_expressions (ctxt, result);
+ verify_code_factorial (ctxt, result);
+ verify_code_fibonacci (ctxt, result);
+ verify_code_hello_world (ctxt, result);
+ verify_code_string_literal (ctxt, result);
+ verify_code_sum_of_squares (ctxt, result);
+ verify_code_types (ctxt, result);
+ verify_code_using_global (ctxt, result);
}
diff --git a/gcc/testsuite/jit.dg/test-dot-product.c b/gcc/testsuite/jit.dg/test-dot-product.c
index 3a8a59a..dffccae 100644
--- a/gcc/testsuite/jit.dg/test-dot-product.c
+++ b/gcc/testsuite/jit.dg/test-dot-product.c
@@ -99,7 +99,7 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data)
}
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
typedef double (*my_dot_product_fn_type) (int n, double *a, double *b);
CHECK_NON_NULL (result);
diff --git a/gcc/testsuite/jit.dg/test-expressions.c b/gcc/testsuite/jit.dg/test-expressions.c
index aaaf394..c270082 100644
--- a/gcc/testsuite/jit.dg/test-expressions.c
+++ b/gcc/testsuite/jit.dg/test-expressions.c
@@ -560,7 +560,7 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data)
}
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
CHECK_NON_NULL (result);
diff --git a/gcc/testsuite/jit.dg/test-factorial.c b/gcc/testsuite/jit.dg/test-factorial.c
index 5c3b237..758cd2d 100644
--- a/gcc/testsuite/jit.dg/test-factorial.c
+++ b/gcc/testsuite/jit.dg/test-factorial.c
@@ -92,7 +92,7 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data)
}
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
typedef int (*my_factorial_fn_type) (int);
CHECK_NON_NULL (result);
diff --git a/gcc/testsuite/jit.dg/test-failure.c b/gcc/testsuite/jit.dg/test-failure.c
index ac31964..4a7b788 100644
--- a/gcc/testsuite/jit.dg/test-failure.c
+++ b/gcc/testsuite/jit.dg/test-failure.c
@@ -12,7 +12,7 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data)
}
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
CHECK_VALUE (result, NULL);
}
diff --git a/gcc/testsuite/jit.dg/test-fibonacci.c b/gcc/testsuite/jit.dg/test-fibonacci.c
index 16d8a46..23903fa 100644
--- a/gcc/testsuite/jit.dg/test-fibonacci.c
+++ b/gcc/testsuite/jit.dg/test-fibonacci.c
@@ -132,7 +132,7 @@ FIRST_LINE + 7: }
}
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
typedef int (*my_fibonacci_fn_type) (int);
CHECK_NON_NULL (result);
diff --git a/gcc/testsuite/jit.dg/test-hello-world.c b/gcc/testsuite/jit.dg/test-hello-world.c
index 0e3af81..1c18ce1b 100644
--- a/gcc/testsuite/jit.dg/test-hello-world.c
+++ b/gcc/testsuite/jit.dg/test-hello-world.c
@@ -53,7 +53,7 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data)
}
extern void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
typedef void (*fn_type) (const char *);
CHECK_NON_NULL (result);
diff --git a/gcc/testsuite/jit.dg/test-null-passed-to-api.c b/gcc/testsuite/jit.dg/test-null-passed-to-api.c
index 245fde0..1e9d89c 100644
--- a/gcc/testsuite/jit.dg/test-null-passed-to-api.c
+++ b/gcc/testsuite/jit.dg/test-null-passed-to-api.c
@@ -21,10 +21,14 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data)
}
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
/* Ensure that the bad API usage prevents the API giving a bogus
result back. */
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_function: NULL return_type");
}
diff --git a/gcc/testsuite/jit.dg/test-string-literal.c b/gcc/testsuite/jit.dg/test-string-literal.c
index cd373ad..b9ba895 100644
--- a/gcc/testsuite/jit.dg/test-string-literal.c
+++ b/gcc/testsuite/jit.dg/test-string-literal.c
@@ -37,7 +37,7 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data)
}
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
typedef const char *(*fn_type) (void);
CHECK_NON_NULL (result);
diff --git a/gcc/testsuite/jit.dg/test-sum-of-squares.c b/gcc/testsuite/jit.dg/test-sum-of-squares.c
index 48ac93f..934d58d 100644
--- a/gcc/testsuite/jit.dg/test-sum-of-squares.c
+++ b/gcc/testsuite/jit.dg/test-sum-of-squares.c
@@ -119,7 +119,7 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data)
}
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
typedef int (*loop_test_fn_type) (int);
CHECK_NON_NULL (result);
diff --git a/gcc/testsuite/jit.dg/test-types.c b/gcc/testsuite/jit.dg/test-types.c
index 819c40a..e4a042e 100644
--- a/gcc/testsuite/jit.dg/test-types.c
+++ b/gcc/testsuite/jit.dg/test-types.c
@@ -241,7 +241,7 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data)
}
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
typedef void (*fn_type) (struct zoo *);
CHECK_NON_NULL (result);
diff --git a/gcc/testsuite/jit.dg/test-using-global.c b/gcc/testsuite/jit.dg/test-using-global.c
index 8eabc31..f9390f8 100644
--- a/gcc/testsuite/jit.dg/test-using-global.c
+++ b/gcc/testsuite/jit.dg/test-using-global.c
@@ -53,7 +53,7 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data)
int the_global;
void
-verify_code (gcc_jit_result *result)
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
typedef void (*fn_type) (void);
CHECK_NON_NULL (result);
--
1.7.11.7