Committed to branch dmalcolm/jit: gcc/jit/ * libgccjit.c (is_valid_cast): New. (gcc_jit_context_new_cast): Check for compatible types.
* internal-api.c (gcc::jit::recording::memento_of_get_type:: is_int): New. (gcc::jit::recording::memento_of_get_type::is_float): New. (gcc::jit::recording::memento_of_get_type::is_bool): New. * internal-api.h (gcc::jit::recording::type::is_int): New. (gcc::jit::recording::type::is_float): New. (gcc::jit::recording::type::is_bool): New. (gcc::jit::recording::memento_of_get_type::is_int): New. (gcc::jit::recording::memento_of_get_type::is_float): New. (gcc::jit::recording::memento_of_get_type::is_bool): New. (gcc::jit::recording::memento_of_get_pointer::is_int): New. (gcc::jit::recording::memento_of_get_pointer::is_float): New. (gcc::jit::recording::memento_of_get_pointer::is_bool): New. (gcc::jit::recording::memento_of_get_const::is_int): New. (gcc::jit::recording::memento_of_get_const::is_float): New. (gcc::jit::recording::memento_of_get_const::is_bool): New. (gcc::jit::recording::memento_of_get_volatile::is_int): New. (gcc::jit::recording::memento_of_get_volatile::is_float): New. (gcc::jit::recording::memento_of_get_volatile::is_bool): New. (gcc::jit::recording::array_type::is_int): New. (gcc::jit::recording::array_type::is_float): New. (gcc::jit::recording::array_type::is_bool): New. (gcc::jit::recording::function_type::is_int): New. (gcc::jit::recording::function_type::is_float): New. (gcc::jit::recording::function_type::is_bool): New. (gcc::jit::recording::struct_::is_int): New. (gcc::jit::recording::struct_::is_float): New. (gcc::jit::recording::struct_::is_bool): New. gcc/testsuite/ * jit.dg/test-error-bad-cast.c: New test case. --- gcc/jit/ChangeLog.jit | 42 +++++++++ gcc/jit/internal-api.c | 135 +++++++++++++++++++++++++++++ gcc/jit/internal-api.h | 33 +++++++ gcc/jit/libgccjit.c | 33 +++++++ gcc/testsuite/ChangeLog.jit | 4 + gcc/testsuite/jit.dg/test-error-bad-cast.c | 63 ++++++++++++++ 6 files changed, 310 insertions(+) create mode 100644 gcc/testsuite/jit.dg/test-error-bad-cast.c diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit index 87f10a3..260273c 100644 --- a/gcc/jit/ChangeLog.jit +++ b/gcc/jit/ChangeLog.jit @@ -1,5 +1,47 @@ 2014-03-13 David Malcolm <dmalc...@redhat.com> + * libgccjit.c (is_valid_cast): New. + (gcc_jit_context_new_cast): Check for compatible types. + + * internal-api.c (gcc::jit::recording::memento_of_get_type:: + is_int): New. + (gcc::jit::recording::memento_of_get_type::is_float): New. + (gcc::jit::recording::memento_of_get_type::is_bool): New. + + * internal-api.h (gcc::jit::recording::type::is_int): New. + (gcc::jit::recording::type::is_float): New. + (gcc::jit::recording::type::is_bool): New. + + (gcc::jit::recording::memento_of_get_type::is_int): New. + (gcc::jit::recording::memento_of_get_type::is_float): New. + (gcc::jit::recording::memento_of_get_type::is_bool): New. + + (gcc::jit::recording::memento_of_get_pointer::is_int): New. + (gcc::jit::recording::memento_of_get_pointer::is_float): New. + (gcc::jit::recording::memento_of_get_pointer::is_bool): New. + + (gcc::jit::recording::memento_of_get_const::is_int): New. + (gcc::jit::recording::memento_of_get_const::is_float): New. + (gcc::jit::recording::memento_of_get_const::is_bool): New. + + (gcc::jit::recording::memento_of_get_volatile::is_int): New. + (gcc::jit::recording::memento_of_get_volatile::is_float): New. + (gcc::jit::recording::memento_of_get_volatile::is_bool): New. + + (gcc::jit::recording::array_type::is_int): New. + (gcc::jit::recording::array_type::is_float): New. + (gcc::jit::recording::array_type::is_bool): New. + + (gcc::jit::recording::function_type::is_int): New. + (gcc::jit::recording::function_type::is_float): New. + (gcc::jit::recording::function_type::is_bool): New. + + (gcc::jit::recording::struct_::is_int): New. + (gcc::jit::recording::struct_::is_float): New. + (gcc::jit::recording::struct_::is_bool): New. + +2014-03-13 David Malcolm <dmalc...@redhat.com> + * internal-api.c (gcc::jit::recording::context::set_str_option): Provide NULL recording::location to add_error. (gcc::jit::recording::context::set_int_option): Likewise. diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c index 692dffb..062095e 100644 --- a/gcc/jit/internal-api.c +++ b/gcc/jit/internal-api.c @@ -856,6 +856,141 @@ recording::memento_of_get_type::dereference () } } +bool +recording::memento_of_get_type::is_int () const +{ + switch (m_kind) + { + default: gcc_unreachable (); + + case GCC_JIT_TYPE_VOID: + return false; + + case GCC_JIT_TYPE_VOID_PTR: + return false; + + case GCC_JIT_TYPE_BOOL: + return false; + + case GCC_JIT_TYPE_CHAR: + case GCC_JIT_TYPE_SIGNED_CHAR: + case GCC_JIT_TYPE_UNSIGNED_CHAR: + case GCC_JIT_TYPE_SHORT: + case GCC_JIT_TYPE_UNSIGNED_SHORT: + case GCC_JIT_TYPE_INT: + case GCC_JIT_TYPE_UNSIGNED_INT: + case GCC_JIT_TYPE_LONG: + case GCC_JIT_TYPE_UNSIGNED_LONG: + case GCC_JIT_TYPE_LONG_LONG: + case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: + return true; + + case GCC_JIT_TYPE_FLOAT: + case GCC_JIT_TYPE_DOUBLE: + case GCC_JIT_TYPE_LONG_DOUBLE: + return false; + + case GCC_JIT_TYPE_CONST_CHAR_PTR: + return false; + + case GCC_JIT_TYPE_SIZE_T: + return true; + + case GCC_JIT_TYPE_FILE_PTR: + return false; + } +} + +bool +recording::memento_of_get_type::is_float () const +{ + switch (m_kind) + { + default: gcc_unreachable (); + + case GCC_JIT_TYPE_VOID: + return false; + + case GCC_JIT_TYPE_VOID_PTR: + return false; + + case GCC_JIT_TYPE_BOOL: + return false; + + case GCC_JIT_TYPE_CHAR: + case GCC_JIT_TYPE_SIGNED_CHAR: + case GCC_JIT_TYPE_UNSIGNED_CHAR: + case GCC_JIT_TYPE_SHORT: + case GCC_JIT_TYPE_UNSIGNED_SHORT: + case GCC_JIT_TYPE_INT: + case GCC_JIT_TYPE_UNSIGNED_INT: + case GCC_JIT_TYPE_LONG: + case GCC_JIT_TYPE_UNSIGNED_LONG: + case GCC_JIT_TYPE_LONG_LONG: + case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: + return false; + + case GCC_JIT_TYPE_FLOAT: + case GCC_JIT_TYPE_DOUBLE: + case GCC_JIT_TYPE_LONG_DOUBLE: + return true; + + case GCC_JIT_TYPE_CONST_CHAR_PTR: + return false; + + case GCC_JIT_TYPE_SIZE_T: + return false; + + case GCC_JIT_TYPE_FILE_PTR: + return false; + } +} + +bool +recording::memento_of_get_type::is_bool () const +{ + switch (m_kind) + { + default: gcc_unreachable (); + + case GCC_JIT_TYPE_VOID: + return false; + + case GCC_JIT_TYPE_VOID_PTR: + return false; + + case GCC_JIT_TYPE_BOOL: + return true; + + case GCC_JIT_TYPE_CHAR: + case GCC_JIT_TYPE_SIGNED_CHAR: + case GCC_JIT_TYPE_UNSIGNED_CHAR: + case GCC_JIT_TYPE_SHORT: + case GCC_JIT_TYPE_UNSIGNED_SHORT: + case GCC_JIT_TYPE_INT: + case GCC_JIT_TYPE_UNSIGNED_INT: + case GCC_JIT_TYPE_LONG: + case GCC_JIT_TYPE_UNSIGNED_LONG: + case GCC_JIT_TYPE_LONG_LONG: + case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: + return false; + + case GCC_JIT_TYPE_FLOAT: + case GCC_JIT_TYPE_DOUBLE: + case GCC_JIT_TYPE_LONG_DOUBLE: + return false; + + case GCC_JIT_TYPE_CONST_CHAR_PTR: + return false; + + case GCC_JIT_TYPE_SIZE_T: + return false; + + case GCC_JIT_TYPE_FILE_PTR: + return false; + } +} + void recording::memento_of_get_type::replay_into (replayer *r) { diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h index 5048f41..772f828 100644 --- a/gcc/jit/internal-api.h +++ b/gcc/jit/internal-api.h @@ -493,6 +493,9 @@ public: return this; } + virtual bool is_int () const = 0; + virtual bool is_float () const = 0; + virtual bool is_bool () const = 0; playback::type * playback_type () @@ -534,6 +537,10 @@ public: return type::accepts_writes_from (rtype); } + bool is_int () const; + bool is_float () const; + bool is_bool () const; + public: void replay_into (replayer *r); @@ -558,6 +565,10 @@ public: void replay_into (replayer *r); + bool is_int () const { return false; } + bool is_float () const { return false; } + bool is_bool () const { return false; } + private: string * make_debug_string (); @@ -584,6 +595,10 @@ public: /* Strip off the "const", giving the underlying type. */ type *unqualified () { return m_other_type; } + bool is_int () const { return m_other_type->is_int (); } + bool is_float () const { return m_other_type->is_float (); } + bool is_bool () const { return m_other_type->is_bool (); } + void replay_into (replayer *); private: @@ -606,6 +621,10 @@ public: /* Strip off the "volatile", giving the underlying type. */ type *unqualified () { return m_other_type; } + bool is_int () const { return m_other_type->is_int (); } + bool is_float () const { return m_other_type->is_float (); } + bool is_bool () const { return m_other_type->is_bool (); } + void replay_into (replayer *); private: @@ -629,6 +648,11 @@ class array_type : public type {} type *dereference (); + + bool is_int () const { return false; } + bool is_float () const { return false; } + bool is_bool () const { return false; } + void replay_into (replayer *); private: @@ -651,6 +675,11 @@ public: type *dereference (); function_type *as_a_function_type () { return this; } + + bool is_int () const { return false; } + bool is_float () const { return false; } + bool is_bool () const { return false; } + void replay_into (replayer *); type * get_return_type () const { return m_return_type; } @@ -724,6 +753,10 @@ public: type *dereference (); + bool is_int () const { return false; } + bool is_float () const { return false; } + bool is_bool () const { return false; } + void replay_into (replayer *r); playback::struct_ * diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 936576c..baab60d 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -882,6 +882,32 @@ gcc_jit_context_new_call (gcc_jit_context *ctxt, (gcc::jit::recording::rvalue **)args); } +static bool +is_valid_cast (gcc::jit::recording::type *src_type, + gcc_jit_type *dst_type) +{ + bool src_is_int = src_type->is_int (); + bool dst_is_int = dst_type->is_int (); + bool src_is_float = src_type->is_float (); + bool dst_is_float = dst_type->is_float (); + bool src_is_bool = src_type->is_bool (); + bool dst_is_bool = dst_type->is_bool (); + + if (src_is_int) + if (dst_is_int || dst_is_float || dst_is_bool) + return true; + + if (src_is_float) + if (dst_is_int || dst_is_float) + return true; + + if (src_is_bool) + if (dst_is_int || dst_is_bool) + return true; + + return false; +} + gcc_jit_rvalue * gcc_jit_context_new_cast (gcc_jit_context *ctxt, gcc_jit_location *loc, @@ -891,6 +917,13 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt, RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); + RETURN_NULL_IF_FAIL_PRINTF3 ( + is_valid_cast (rvalue->get_type (), type), + ctxt, loc, + "cannot cast %s from type: %s to type: %s", + rvalue->get_debug_string (), + rvalue->get_type ()->get_debug_string (), + type->get_debug_string ()); return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc, rvalue, type)); } diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit index 5a84bfd..b8f1fa8 100644 --- a/gcc/testsuite/ChangeLog.jit +++ b/gcc/testsuite/ChangeLog.jit @@ -1,3 +1,7 @@ +2014-03-13 David Malcolm <dmalc...@redhat.com> + + * jit.dg/test-error-bad-cast.c: New test case. + 2014-03-11 David Malcolm <dmalc...@redhat.com> * jit.dg/harness.h (set_options): Increase optimization level from diff --git a/gcc/testsuite/jit.dg/test-error-bad-cast.c b/gcc/testsuite/jit.dg/test-error-bad-cast.c new file mode 100644 index 0000000..a0ab413 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-bad-cast.c @@ -0,0 +1,63 @@ +#include <stdlib.h> +#include <stdio.h> + +#include "libgccjit.h" + +#include "harness.h" + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + + int + test_fn () + { + struct foo f; + return (int)f; + } + + and verify that the API complains about the bad cast. + */ + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + + + gcc_jit_struct *struct_foo = + gcc_jit_context_new_struct_type (ctxt, NULL, "foo", + 0, NULL); + + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + int_type, + "test_fn", + 0, NULL, + 0); + gcc_jit_lvalue *f = + gcc_jit_function_new_local ( + test_fn, + NULL, + gcc_jit_struct_as_type (struct_foo), "f"); + + gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); + + gcc_jit_block_end_with_return ( + block, NULL, + gcc_jit_context_new_cast (ctxt, NULL, + gcc_jit_lvalue_as_rvalue (f), + int_type)); +} + +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_cast:" + " cannot cast f from type: struct foo" + " to type: int"); +} + -- 1.8.5.3