Commit 5a47aa2c by David Malcolm Committed by David Malcolm

jit: handle equality of function pointer types

gcc/jit/ChangeLog:
	* jit-recording.c
	(gcc::jit::recording::function_type::is_same_type_as): New function.
	* jit-recording.h: In namespace gcc::jit::recording::
	(type::accepts_writes_from): Use is_same_type_as rather than pointer
	equality.
	(type::is_same_type_as): New virtual function.
	(function_type::is_same_type_as): New override.

gcc/testsuite/ChangeLog:
	* jit.dg/test-error-mismatching-types-in-assignment-fn-ptr.c: New
	test case.
	* jit.dg/test-returning-function-ptr.c (create_code): Update to
	create a function pointer type independently of the call to
	gcc_jit_function_get_address, and assign the pointer to a local
	before returning it, to exercise the function pointer type
	comparison code.

From-SVN: r253255
parent f276c46c
2017-09-28 David Malcolm <dmalcolm@redhat.com>
* jit-recording.c
(gcc::jit::recording::function_type::is_same_type_as): New function.
* jit-recording.h: In namespace gcc::jit::recording::
(type::accepts_writes_from): Use is_same_type_as rather than pointer
equality.
(type::is_same_type_as): New virtual function.
(function_type::is_same_type_as): New override.
2017-09-27 David Malcolm <dmalcolm@redhat.com>
* docs/cp/topics/expressions.rst (Function pointers): New section.
......
......@@ -2643,6 +2643,53 @@ recording::function_type::dereference ()
return NULL;
}
/* Implementation of virtual hook recording::type::is_same_type_as for
recording::function_type.
We override this to avoid requiring identity of function pointer types,
so that if client code has obtained the same signature in
different ways (e.g. via gcc_jit_context_new_function_ptr_type
vs gcc_jit_function_get_address), the different function_type
instances are treated as compatible.
We can't use type::accepts_writes_from for this as we need a stronger
notion of "sameness": if we have a fn_ptr type that has args that are
themselves fn_ptr types, then those args still need to match exactly.
Alternatively, we could consolidate attempts to create identical
function_type instances so that pointer equality works, but that runs
into issues about the lifetimes of the cache (w.r.t. nested contexts). */
bool
recording::function_type::is_same_type_as (type *other)
{
gcc_assert (other);
function_type *other_fn_type = other->dyn_cast_function_type ();
if (!other_fn_type)
return false;
/* Everything must match. */
if (!m_return_type->is_same_type_as (other_fn_type->m_return_type))
return false;
if (m_param_types.length () != other_fn_type->m_param_types.length ())
return false;
unsigned i;
type *param_type;
FOR_EACH_VEC_ELT (m_param_types, i, param_type)
if (!param_type->is_same_type_as (other_fn_type->m_param_types[i]))
return false;
if (m_is_variadic != other_fn_type->m_is_variadic)
return false;
/* Passed all tests. */
return true;
}
/* Implementation of pure virtual hook recording::memento::replay_into
for recording::function_type. */
......
......@@ -491,7 +491,12 @@ public:
virtual bool accepts_writes_from (type *rtype)
{
gcc_assert (rtype);
return this->unqualified () == rtype->unqualified ();
return this->unqualified ()->is_same_type_as (rtype->unqualified ());
}
virtual bool is_same_type_as (type *other)
{
return this == other;
}
/* Strip off "const" etc */
......@@ -751,6 +756,8 @@ public:
function_type *dyn_cast_function_type () FINAL OVERRIDE { return this; }
function_type *as_a_function_type () FINAL OVERRIDE { return this; }
bool is_same_type_as (type *other) FINAL OVERRIDE;
bool is_int () const FINAL OVERRIDE { return false; }
bool is_float () const FINAL OVERRIDE { return false; }
bool is_bool () const FINAL OVERRIDE { return false; }
......
2017-09-28 David Malcolm <dmalcolm@redhat.com>
* jit.dg/test-error-mismatching-types-in-assignment-fn-ptr.c: New
test case.
* jit.dg/test-returning-function-ptr.c (create_code): Update to
create a function pointer type independently of the call to
gcc_jit_function_get_address, and assign the pointer to a local
before returning it, to exercise the function pointer type
comparison code.
2017-09-27 David Malcolm <dmalcolm@redhat.com>
* jit.dg/all-non-failing-tests.h: Add
......
#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:
typedef void (*fn_ptr_iii) (int, int, int);
typedef void (*fn_ptr_ifi) (int, float, int);
void
test_fn (void)
{
fn_ptr_iii iii_ptr;
fn_ptr_ifi ifi_ptr;
iii_ptr = NULL;
ifi_ptr = iii_ptr;
}
and verify that the API complains about the mismatching types
in the second assignment (but not the first).
*/
gcc_jit_type *void_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
gcc_jit_type *int_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
gcc_jit_type *float_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
gcc_jit_type *iii_types[] = {int_type, int_type, int_type};
gcc_jit_type *fn_ptr_type_iii
= gcc_jit_context_new_function_ptr_type (ctxt, NULL,
void_type,
3, iii_types,
0);
gcc_jit_type *ifi_types[] = {int_type, float_type, int_type};
gcc_jit_type *fn_ptr_type_ifi
= gcc_jit_context_new_function_ptr_type (ctxt, NULL,
void_type,
3, ifi_types,
0);
gcc_jit_function *test_fn =
gcc_jit_context_new_function (ctxt, NULL,
GCC_JIT_FUNCTION_EXPORTED,
void_type,
"test_fn",
0, NULL,
0);
gcc_jit_lvalue *iii_ptr =
gcc_jit_function_new_local (
test_fn, NULL, fn_ptr_type_iii, "iii_ptr");
gcc_jit_lvalue *ifi_ptr =
gcc_jit_function_new_local (
test_fn, NULL, fn_ptr_type_ifi, "ifi_ptr");
gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
/* iii_ptr = NULL; */
gcc_jit_block_add_assignment (
block, NULL,
iii_ptr,
gcc_jit_context_null (ctxt, fn_ptr_type_iii));
/* ifi_ptr = iii_ptr; */
gcc_jit_block_add_assignment (
block, NULL,
ifi_ptr,
gcc_jit_lvalue_as_rvalue (iii_ptr));
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_block_add_assignment:"
" mismatching types:"
" assignment to ifi_ptr"
" (type: void (*) (int, float, int))"
" from iii_ptr"
" (type: void (*) (int, int, int))");
}
......@@ -28,10 +28,15 @@ create_code (gcc_jit_context *ctxt, void *user_data)
internally_called_function (a * 3, a * 4, a * 5);
}
void (*) (int)
typedef void (*fn_ptr_type) (int);
fn_ptr_type
get_test_caller (void)
{
return internal_test_caller;
// Verify that we can assign function pointers to variables
fn_ptr_type p;
p = internal_test_caller;
return p;
}
*/
int i;
......@@ -87,11 +92,11 @@ create_code (gcc_jit_context *ctxt, void *user_data)
3, args));
gcc_jit_block_end_with_void_return (block, NULL);
gcc_jit_rvalue *fn_ptr
= gcc_jit_function_get_address (test_caller, NULL);
gcc_jit_type *fn_ptr_type
= gcc_jit_rvalue_get_type (fn_ptr);
= gcc_jit_context_new_function_ptr_type (ctxt, NULL,
void_type,
1, &int_type,
0);
/* Build the get_test_caller fn. */
gcc_jit_function *get_test_caller =
......@@ -102,7 +107,21 @@ create_code (gcc_jit_context *ctxt, void *user_data)
0, NULL,
0);
block = gcc_jit_function_new_block (get_test_caller, NULL);
gcc_jit_block_end_with_return (block, NULL, fn_ptr);
/* fn_ptr_type p; */
gcc_jit_lvalue *local_p
= gcc_jit_function_new_local (get_test_caller, NULL,
fn_ptr_type, "p");
/* p = internal_test_caller; */
gcc_jit_block_add_assignment (block, NULL,
local_p,
gcc_jit_function_get_address (test_caller,
NULL));
/* return p; */
gcc_jit_block_end_with_return (block, NULL,
gcc_jit_lvalue_as_rvalue (local_p));
}
static int called_with[3];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment