@@ -1,3 +1,38 @@
+2014-03-19 David Malcolm <dmalcolm@redhat.com>
+
+ * internal-api.c (gcc::jit::recording::memento_of_get_pointer::
+ accepts_writes_from): Accept writes from pointers, but not arrays.
+
+ * internal-api.h (gcc::jit::recording::type::is_pointer): New.
+ (gcc::jit::recording::type::is_array): New.
+ (gcc::jit::recording::memento_of_get_type::accepts_writes_from):
+ Allow (void *) to accept writes of pointers, but not arrays.
+ (gcc::jit::recording::memento_of_get_type::is_pointer): New.
+ (gcc::jit::recording::memento_of_get_type::is_array): New.
+ (gcc::jit::recording::memento_of_get_pointer::is_pointer): New.
+ (gcc::jit::recording::memento_of_get_pointer::is_array): New.
+ (gcc::jit::recording::memento_of_get_const::is_pointer): New.
+ (gcc::jit::recording::memento_of_get_const::is_array): New.
+ (gcc::jit::recording::memento_of_get_volatile::is_pointer): New.
+ (gcc::jit::recording::memento_of_get_volatile::is_array): New.
+ (gcc::jit::recording::array_type::is_pointer): New.
+ (gcc::jit::recording::array_type::is_array): New.
+ (gcc::jit::recording::function_type::is_pointer): New.
+ (gcc::jit::recording::function_type::is_array): New.
+ (gcc::jit::recording::struct_::is_pointer): New.
+ (gcc::jit::recording::struct_::is_array): New.
+
+ * libgccjit.c (gcc_jit_context_new_rvalue_from_ptr): Require the
+ pointer_type to be a pointer, not an array.
+ (gcc_jit_context_null): Likewise.
+ (is_valid_cast): Require pointer casts to be between pointer types,
+ not arrays.
+ (gcc_jit_context_new_array_access): Update error message from "not
+ a pointer" to "not a pointer or array".
+ (gcc_jit_rvalue_dereference_field): Require the pointer arg to be
+ of pointer type, not an array.
+ (gcc_jit_rvalue_dereference): Likewise.
+
2014-03-14 David Malcolm <dmalcolm@redhat.com>
* libgccjit.c (is_valid_cast): Permit casts between pointer types.
@@ -1048,7 +1048,7 @@ bool
recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
{
/* Must be a pointer type: */
- type *rtype_points_to = rtype->dereference ();
+ type *rtype_points_to = rtype->is_pointer ();
if (!rtype_points_to)
return false;
@@ -496,6 +496,8 @@ public:
virtual bool is_int () const = 0;
virtual bool is_float () const = 0;
virtual bool is_bool () const = 0;
+ virtual type *is_pointer () = 0;
+ virtual type *is_array () = 0;
playback::type *
playback_type ()
@@ -527,7 +529,7 @@ public:
bool accepts_writes_from (type *rtype)
{
if (m_kind == GCC_JIT_TYPE_VOID_PTR)
- if (rtype->dereference ())
+ if (rtype->is_pointer ())
{
/* LHS (this) is type (void *), and the RHS is a pointer:
accept it: */
@@ -540,6 +542,8 @@ public:
bool is_int () const;
bool is_float () const;
bool is_bool () const;
+ type *is_pointer () { return dereference (); }
+ type *is_array () { return NULL; }
public:
void replay_into (replayer *r);
@@ -568,6 +572,8 @@ public:
bool is_int () const { return false; }
bool is_float () const { return false; }
bool is_bool () const { return false; }
+ type *is_pointer () { return m_other_type; }
+ type *is_array () { return NULL; }
private:
string * make_debug_string ();
@@ -598,6 +604,8 @@ public:
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 (); }
+ type *is_pointer () { return m_other_type->is_pointer (); }
+ type *is_array () { return m_other_type->is_array (); }
void replay_into (replayer *);
@@ -624,6 +632,8 @@ public:
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 (); }
+ type *is_pointer () { return m_other_type->is_pointer (); }
+ type *is_array () { return m_other_type->is_array (); }
void replay_into (replayer *);
@@ -652,6 +662,8 @@ class array_type : public type
bool is_int () const { return false; }
bool is_float () const { return false; }
bool is_bool () const { return false; }
+ type *is_pointer () { return NULL; }
+ type *is_array () { return m_element_type; }
void replay_into (replayer *);
@@ -679,6 +691,8 @@ public:
bool is_int () const { return false; }
bool is_float () const { return false; }
bool is_bool () const { return false; }
+ type *is_pointer () { return NULL; }
+ type *is_array () { return NULL; }
void replay_into (replayer *);
@@ -756,6 +770,8 @@ public:
bool is_int () const { return false; }
bool is_float () const { return false; }
bool is_bool () const { return false; }
+ type *is_pointer () { return NULL; }
+ type *is_array () { return NULL; }
void replay_into (replayer *r);
@@ -721,7 +721,7 @@ gcc_jit_context_new_rvalue_from_ptr (gcc_jit_context *ctxt,
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
RETURN_NULL_IF_FAIL (pointer_type, ctxt, NULL, "NULL type");
RETURN_NULL_IF_FAIL_PRINTF1 (
- pointer_type->dereference (),
+ pointer_type->is_pointer (),
ctxt, NULL,
"not a pointer type (type: %s)",
pointer_type->get_debug_string ());
@@ -736,7 +736,7 @@ gcc_jit_context_null (gcc_jit_context *ctxt,
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
RETURN_NULL_IF_FAIL (pointer_type, ctxt, NULL, "NULL type");
RETURN_NULL_IF_FAIL_PRINTF1 (
- pointer_type->dereference (),
+ pointer_type->is_pointer (),
ctxt, NULL,
"not a pointer type (type: %s)",
pointer_type->get_debug_string ());
@@ -906,8 +906,8 @@ is_valid_cast (gcc::jit::recording::type *src_type,
return true;
/* Permit casts between pointer types. */
- gcc::jit::recording::type *deref_src_type = src_type->dereference ();
- gcc::jit::recording::type *deref_dst_type = dst_type->dereference ();
+ gcc::jit::recording::type *deref_src_type = src_type->is_pointer ();
+ gcc::jit::recording::type *deref_dst_type = dst_type->is_pointer ();
if (deref_src_type && deref_dst_type)
return true;
@@ -946,7 +946,7 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
RETURN_NULL_IF_FAIL_PRINTF2 (
ptr->get_type ()->dereference (),
ctxt, loc,
- "%s (type: %s) is not a pointer",
+ "%s (type: %s) is not a pointer or array",
ptr->get_debug_string (),
ptr->get_type ()->get_debug_string ());
@@ -1007,7 +1007,7 @@ gcc_jit_rvalue_dereference_field (gcc_jit_rvalue *ptr,
RETURN_NULL_IF_FAIL (ptr, NULL, loc, "NULL ptr");
RETURN_NULL_IF_FAIL (field, NULL, loc, "NULL field");
gcc::jit::recording::type *underlying_type =
- ptr->get_type ()->dereference ();
+ ptr->get_type ()->is_pointer ();
RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt, loc,
"field %s has not been placed in a struct",
field->get_debug_string ());
@@ -1036,7 +1036,7 @@ gcc_jit_rvalue_dereference (gcc_jit_rvalue *rvalue,
RETURN_NULL_IF_FAIL (rvalue, NULL, loc, "NULL rvalue");
gcc::jit::recording::type *underlying_type =
- rvalue->get_type ()->dereference ();
+ rvalue->get_type ()->is_pointer ();
RETURN_NULL_IF_FAIL_PRINTF2 (
underlying_type,
@@ -1,3 +1,16 @@
+2014-03-19 David Malcolm <dmalcolm@redhat.com>
+
+ * jit.dg/test-array-as-pointer.c: New test case, verifying that
+ there's a way to treat arrays as pointers.
+ * jit.dg/test-combination.c: Add test-array-as-pointer.c...
+ (create_code): ...here and...
+ (verify_code): ...here.
+
+ * jit.dg/test-error-array-as-pointer.c: New test case, verifying
+ that bogus casts from array to pointer are caught by the type
+ system, rather than leading to ICEs seen in:
+ https://github.com/davidmalcolm/pygccjit/pull/3#issuecomment-37883129
+
2014-03-18 David Malcolm <dmalcolm@redhat.com>
* jit.dg/test-combination.c: Add test-arrays.c and test-volatile.c.
new file mode 100644
@@ -0,0 +1,101 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+#define BUFFER_SIZE (1024)
+
+char test_buffer[1024];
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ void test_of_array_as_pointer (const char *name)
+ {
+ snprintf (test_buffer, sizeof (test_buffer),
+ "hello %s", name);
+ }
+ */
+ gcc_jit_type *void_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+ gcc_jit_type *const_char_ptr_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR);
+ gcc_jit_type *char_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR);
+ gcc_jit_type *char_ptr_type =
+ gcc_jit_type_get_pointer (char_type);
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *size_t_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_SIZE_T);
+ gcc_jit_type *buf_type =
+ gcc_jit_context_new_array_type (ctxt, NULL, char_type, BUFFER_SIZE);
+
+ /* extern int snprintf(char *str, size_t size, const char *format, ...); */
+ gcc_jit_param *param_s =
+ gcc_jit_context_new_param (ctxt, NULL, char_ptr_type, "s");
+ gcc_jit_param *param_n =
+ gcc_jit_context_new_param (ctxt, NULL, size_t_type, "n");
+ gcc_jit_param *param_format =
+ gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "format");
+ gcc_jit_param *snprintf_params[3] = {param_s, param_n, param_format};
+ gcc_jit_function *snprintf =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_IMPORTED,
+ int_type,
+ "snprintf",
+ 3, snprintf_params,
+ 1);
+
+ gcc_jit_param *param_name =
+ gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "name");
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_type,
+ "test_of_array_as_pointer",
+ 1, ¶m_name,
+ 0);
+
+ gcc_jit_lvalue *buffer =
+ gcc_jit_context_new_global (ctxt, NULL, buf_type, "test_buffer");
+
+ gcc_jit_block *block = gcc_jit_function_new_block(test_fn, "entry");
+
+ /* snprintf(buffer, sizeof(buffer), "hello %s", name); */
+ gcc_jit_rvalue *args[4];
+ args[0] = gcc_jit_context_new_cast (
+ ctxt, NULL,
+ /* Here's the difference with test-error-array-as-pointer.c: */
+ gcc_jit_lvalue_get_address (buffer,
+ NULL),
+ char_ptr_type);
+ args[1] = gcc_jit_context_new_rvalue_from_int (ctxt,
+ size_t_type,
+ BUFFER_SIZE);
+ args[2] = gcc_jit_context_new_string_literal (ctxt, "hello %s");
+ args[3] = gcc_jit_param_as_rvalue (param_name);
+
+ gcc_jit_block_add_eval (
+ block, NULL,
+ gcc_jit_context_new_call (ctxt, NULL, snprintf, 4, args));
+ gcc_jit_block_end_with_void_return (block, NULL);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_NON_NULL (result);
+
+ typedef void (*fn_type) (const char *);
+ fn_type test_of_array_as_pointer =
+ (fn_type)gcc_jit_result_get_code (result, "test_of_array_as_pointer");
+ CHECK_NON_NULL (test_of_array_as_pointer);
+
+ test_of_array_as_pointer ("world");
+ CHECK_STRING_VALUE (test_buffer, "hello world");
+}
@@ -14,6 +14,13 @@
#undef create_code
#undef verify_code
+/* test-array-as-pointer.c */
+#define create_code create_code_array_as_pointer
+#define verify_code verify_code_array_as_pointer
+#include "test-array-as-pointer.c"
+#undef create_code
+#undef verify_code
+
/* test-arrays.c */
#define create_code create_code_arrays
#define verify_code verify_code_arrays
@@ -141,6 +148,7 @@ void
create_code (gcc_jit_context *ctxt, void * user_data)
{
create_code_accessing_struct (ctxt, user_data);
+ create_code_array_as_pointer (ctxt, user_data);
create_code_arrays (ctxt, user_data);
create_code_calling_external_function (ctxt, user_data);
create_code_dot_product (ctxt, user_data);
@@ -161,6 +169,7 @@ void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
verify_code_accessing_struct (ctxt, result);
+ verify_code_array_as_pointer (ctxt, result);
verify_code_arrays (ctxt, result);
verify_code_calling_external_function (ctxt, result);
verify_code_dot_product (ctxt, result);
new file mode 100644
@@ -0,0 +1,99 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+#define BUFFER_SIZE (1024)
+
+char test_buffer[1024];
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ void test_of_array_as_pointer (const char *name)
+ {
+ snprintf (test_buffer, sizeof (test_buffer),
+ "hello %s", name);
+ }
+ */
+ gcc_jit_type *void_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+ gcc_jit_type *const_char_ptr_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR);
+ gcc_jit_type *char_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR);
+ gcc_jit_type *char_ptr_type =
+ gcc_jit_type_get_pointer (char_type);
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *size_t_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_SIZE_T);
+ gcc_jit_type *buf_type =
+ gcc_jit_context_new_array_type (ctxt, NULL, char_type, BUFFER_SIZE);
+
+ /* extern int snprintf(char *str, size_t size, const char *format, ...); */
+ gcc_jit_param *param_s =
+ gcc_jit_context_new_param (ctxt, NULL, char_ptr_type, "s");
+ gcc_jit_param *param_n =
+ gcc_jit_context_new_param (ctxt, NULL, size_t_type, "n");
+ gcc_jit_param *param_format =
+ gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "format");
+ gcc_jit_param *snprintf_params[3] = {param_s, param_n, param_format};
+ gcc_jit_function *snprintf =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_IMPORTED,
+ int_type,
+ "snprintf",
+ 3, snprintf_params,
+ 1);
+
+ gcc_jit_param *param_name =
+ gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "name");
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_type,
+ "test_of_array_as_pointer",
+ 1, ¶m_name,
+ 0);
+
+ gcc_jit_lvalue *buffer =
+ gcc_jit_context_new_global (ctxt, NULL, buf_type, "test_buffer");
+
+ gcc_jit_block *block = gcc_jit_function_new_block(test_fn, "entry");
+
+ /* snprintf(buffer, sizeof(buffer), "hello %s", name); */
+ gcc_jit_rvalue *args[4];
+ args[0] = gcc_jit_context_new_cast (
+ ctxt, NULL,
+ /* Here's the difference with test-array-as-pointer.c: */
+ gcc_jit_lvalue_as_rvalue (buffer),
+ char_ptr_type);
+ args[1] = gcc_jit_context_new_rvalue_from_int (ctxt,
+ size_t_type,
+ BUFFER_SIZE);
+ args[2] = gcc_jit_context_new_string_literal (ctxt, "hello %s");
+ args[3] = gcc_jit_param_as_rvalue (param_name);
+
+ gcc_jit_block_add_eval (
+ block, NULL,
+ gcc_jit_context_new_call (ctxt, NULL, snprintf, 4, args));
+ gcc_jit_block_end_with_void_return (block, NULL);
+}
+
+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 test_buffer"
+ " from type: char[1024]"
+ " to type: char *");
+}