Commit 0ebd1f00 by David Malcolm Committed by David Malcolm

types.rst (gccjit::type::get_const): Remove comment.

gcc_jit_type_get_aligned

gcc/jit/ChangeLog:
	* docs/cp/topics/types.rst (gccjit::type::get_const): Remove
	comment.
	(gccjit::type::get_aligned): Add.
	* docs/topics/compatibility.rst: Add LIBGCCJIT_ABI_7.
	* docs/topics/types.rst: Add gcc_jit_type_get_aligned.
	* docs/_build/texinfo/libgccjit.texi: Regenerate.
	* jit-playback.c (gcc::jit::playback::type::get_aligned): New
	method.
	* jit-playback.h (gcc::jit::playback::type::get_aligned): New
	method.
	* jit-recording.c: Within namespace gcc::jit::recording...
	(type::get_aligned): New method.
	(memento_of_get_aligned::replay_into): New method.
	(memento_of_get_aligned::make_debug_string): New method.
	(memento_of_get_aligned::write_reproducer): New method.
	* jit-recording.h: Within namespace gcc::jit::recording...
	(type::get_aligned): New method.
	(type::accepts_writes_from): Strip off qualifications from
	this when comparing pointer equality.
	(decorated_type): New subclass of type, subsuming the
	commonality between memento_of_get_const and
	memento_of_get_volatile.
	(memento_of_get_const): Make a subclass of decorated_type,
	rather than type.
	(memento_of_get_volatile): Likewise.
	(memento_of_get_aligned): Likewise.
	* libgccjit++.h: Within namespace gccjit...
	(type::get_const): New method.
	(type::get_aligned): New method.
	* libgccjit.c (gcc_jit_type_get_aligned): New function.
	* libgccjit.h (gcc_jit_type_get_aligned): New decl.
	* libgccjit.map (LIBGCCJIT_ABI_7): New
	(gcc_jit_type_get_aligned): Add.

gcc/testsuite/ChangeLog:
	* jit.dg/all-non-failing-tests.h: Add test-alignment.c.
	* jit.dg/test-alignment.c: New test case.
	* jit.dg/test-alignment.cc: New test case.
	* jit.dg/test-error-gcc_jit_type_get_aligned-non-power-of-two.c:
	New test case.

From-SVN: r247111
parent 761ad35c
2017-04-24 David Malcolm <dmalcolm@redhat.com>
* docs/cp/topics/types.rst (gccjit::type::get_const): Remove
comment.
(gccjit::type::get_aligned): Add.
* docs/topics/compatibility.rst: Add LIBGCCJIT_ABI_7.
* docs/topics/types.rst: Add gcc_jit_type_get_aligned.
* docs/_build/texinfo/libgccjit.texi: Regenerate.
* jit-playback.c (gcc::jit::playback::type::get_aligned): New
method.
* jit-playback.h (gcc::jit::playback::type::get_aligned): New
method.
* jit-recording.c: Within namespace gcc::jit::recording...
(type::get_aligned): New method.
(memento_of_get_aligned::replay_into): New method.
(memento_of_get_aligned::make_debug_string): New method.
(memento_of_get_aligned::write_reproducer): New method.
* jit-recording.h: Within namespace gcc::jit::recording...
(type::get_aligned): New method.
(type::accepts_writes_from): Strip off qualifications from
this when comparing pointer equality.
(decorated_type): New subclass of type, subsuming the
commonality between memento_of_get_const and
memento_of_get_volatile.
(memento_of_get_const): Make a subclass of decorated_type,
rather than type.
(memento_of_get_volatile): Likewise.
(memento_of_get_aligned): Likewise.
* libgccjit++.h: Within namespace gccjit...
(type::get_const): New method.
(type::get_aligned): New method.
* libgccjit.c (gcc_jit_type_get_aligned): New function.
* libgccjit.h (gcc_jit_type_get_aligned): New decl.
* libgccjit.map (LIBGCCJIT_ABI_7): New
(gcc_jit_type_get_aligned): Add.
2017-01-19 David Malcolm <dmalcolm@redhat.com>
* dummy-frontend.c (jit_langhook_type_for_size): Delete.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -82,8 +82,6 @@ Pointers, `const`, and `volatile`
Given type "T", get type "T*".
.. FIXME: get_const doesn't seem to exist
.. function:: gccjit::type gccjit::type::get_const ()
Given type "T", get type "const T".
......@@ -92,6 +90,16 @@ Pointers, `const`, and `volatile`
Given type "T", get type "volatile T".
.. function:: gccjit::type gccjit::type::get_aligned (size_t alignment_in_bytes)
Given type "T", get type:
.. code-block:: c
T __attribute__ ((aligned (ALIGNMENT_IN_BYTES)))
The alignment must be a power of two.
.. function:: gccjit::type \
gccjit::context::new_array_type (gccjit::type element_type, \
int num_elements, \
......
......@@ -142,3 +142,10 @@ entrypoints:
-------------------
``LIBGCCJIT_ABI_6`` covers the addition of
:func:`gcc_jit_rvalue_set_bool_require_tail_call`
.. _LIBGCCJIT_ABI_7:
``LIBGCCJIT_ABI_7``
-------------------
``LIBGCCJIT_ABI_7`` covers the addition of
:func:`gcc_jit_type_get_aligned`
......@@ -117,6 +117,25 @@ Pointers, `const`, and `volatile`
Given type "T", get type "T[N]" (for a constant N).
.. function:: gcc_jit_type *\
gcc_jit_type_get_aligned (gcc_jit_type *type, \
size_t alignment_in_bytes)
Given type "T", get type:
.. code-block:: c
T __attribute__ ((aligned (ALIGNMENT_IN_BYTES)))
The alignment must be a power of two.
This entrypoint was added in :ref:`LIBGCCJIT_ABI_7`; you can test for
its presence using
.. code-block:: c
#ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_aligned
Structures and unions
---------------------
......
......@@ -1095,6 +1095,21 @@ new_dereference (tree ptr,
return datum;
}
/* Construct a playback::type instance (wrapping a tree)
with the given alignment. */
playback::type *
playback::type::
get_aligned (size_t alignment_in_bytes) const
{
tree t_new_type = build_variant_type_copy (m_inner);
SET_TYPE_ALIGN (t_new_type, alignment_in_bytes * BITS_PER_UNIT);
TYPE_USER_ALIGN (t_new_type) = 1;
return new type (t_new_type);
}
/* Construct a playback::lvalue instance (wrapping a tree) for a
field access. */
......
......@@ -391,6 +391,8 @@ public:
return new type (build_qualified_type (m_inner, TYPE_QUAL_VOLATILE));
}
type *get_aligned (size_t alignment_in_bytes) const;
private:
tree m_inner;
};
......
......@@ -1974,6 +1974,20 @@ recording::type::get_volatile ()
return result;
}
/* Given a type, get an aligned version of the type.
Implements the post-error-checking part of
gcc_jit_type_get_aligned. */
recording::type *
recording::type::get_aligned (size_t alignment_in_bytes)
{
recording::type *result
= new memento_of_get_aligned (this, alignment_in_bytes);
m_ctxt->record (result);
return result;
}
const char *
recording::type::access_as_type (reproducer &r)
{
......@@ -2419,6 +2433,44 @@ recording::memento_of_get_volatile::write_reproducer (reproducer &r)
r.get_identifier_as_type (m_other_type));
}
/* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
/* Implementation of pure virtual hook recording::memento::replay_into
for recording::memento_of_get_aligned. */
void
recording::memento_of_get_aligned::replay_into (replayer *)
{
set_playback_obj
(m_other_type->playback_type ()->get_aligned (m_alignment_in_bytes));
}
/* Implementation of recording::memento::make_debug_string for
results of get_aligned. */
recording::string *
recording::memento_of_get_aligned::make_debug_string ()
{
return string::from_printf (m_ctxt,
"%s __attribute__((aligned(%zi)))",
m_other_type->get_debug_string (),
m_alignment_in_bytes);
}
/* Implementation of recording::memento::write_reproducer for volatile
types. */
void
recording::memento_of_get_aligned::write_reproducer (reproducer &r)
{
const char *id = r.make_identifier (this, "type");
r.write (" gcc_jit_type *%s =\n"
" gcc_jit_type_get_aligned (%s, %zi);\n",
id,
r.get_identifier_as_type (m_other_type),
m_alignment_in_bytes);
}
/* The implementation of class gcc::jit::recording::array_type */
/* Implementation of pure virtual hook recording::type::dereference for
......
......@@ -473,6 +473,7 @@ public:
type *get_pointer ();
type *get_const ();
type *get_volatile ();
type *get_aligned (size_t alignment_in_bytes);
/* Get the type obtained when dereferencing this type.
......@@ -489,7 +490,7 @@ public:
virtual bool accepts_writes_from (type *rtype)
{
gcc_assert (rtype);
return this == rtype->unqualified ();
return this->unqualified () == rtype->unqualified ();
}
/* Strip off "const" etc */
......@@ -599,16 +600,35 @@ private:
type *m_other_type;
};
/* Result of "gcc_jit_type_get_const". */
class memento_of_get_const : public type
/* A decorated version of a type, for get_const, get_volatile and
get_aligned. */
class decorated_type : public type
{
public:
memento_of_get_const (type *other_type)
decorated_type (type *other_type)
: type (other_type->m_ctxt),
m_other_type (other_type) {}
type *dereference () FINAL OVERRIDE { return m_other_type->dereference (); }
bool is_int () const FINAL OVERRIDE { return m_other_type->is_int (); }
bool is_float () const FINAL OVERRIDE { return m_other_type->is_float (); }
bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
protected:
type *m_other_type;
};
/* Result of "gcc_jit_type_get_const". */
class memento_of_get_const : public decorated_type
{
public:
memento_of_get_const (type *other_type)
: decorated_type (other_type) {}
bool accepts_writes_from (type */*rtype*/) FINAL OVERRIDE
{
/* Can't write to a "const". */
......@@ -618,40 +638,40 @@ public:
/* Strip off the "const", giving the underlying type. */
type *unqualified () FINAL OVERRIDE { return m_other_type; }
bool is_int () const FINAL OVERRIDE { return m_other_type->is_int (); }
bool is_float () const FINAL OVERRIDE { return m_other_type->is_float (); }
bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
void replay_into (replayer *) FINAL OVERRIDE;
private:
string * make_debug_string () FINAL OVERRIDE;
void write_reproducer (reproducer &r) FINAL OVERRIDE;
private:
type *m_other_type;
};
/* Result of "gcc_jit_type_get_volatile". */
class memento_of_get_volatile : public type
class memento_of_get_volatile : public decorated_type
{
public:
memento_of_get_volatile (type *other_type)
: type (other_type->m_ctxt),
m_other_type (other_type) {}
type *dereference () FINAL OVERRIDE { return m_other_type->dereference (); }
: decorated_type (other_type) {}
/* Strip off the "volatile", giving the underlying type. */
type *unqualified () FINAL OVERRIDE { return m_other_type; }
bool is_int () const FINAL OVERRIDE { return m_other_type->is_int (); }
bool is_float () const FINAL OVERRIDE { return m_other_type->is_float (); }
bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
void replay_into (replayer *) FINAL OVERRIDE;
private:
string * make_debug_string () FINAL OVERRIDE;
void write_reproducer (reproducer &r) FINAL OVERRIDE;
};
/* Result of "gcc_jit_type_get_aligned". */
class memento_of_get_aligned : public decorated_type
{
public:
memento_of_get_aligned (type *other_type, size_t alignment_in_bytes)
: decorated_type (other_type),
m_alignment_in_bytes (alignment_in_bytes) {}
/* Strip off the alignment, giving the underlying type. */
type *unqualified () FINAL OVERRIDE { return m_other_type; }
void replay_into (replayer *) FINAL OVERRIDE;
......@@ -660,7 +680,7 @@ private:
void write_reproducer (reproducer &r) FINAL OVERRIDE;
private:
type *m_other_type;
size_t m_alignment_in_bytes;
};
class array_type : public type
......
......@@ -330,7 +330,9 @@ namespace gccjit
gcc_jit_type *get_inner_type () const;
type get_pointer ();
type get_const ();
type get_volatile ();
type get_aligned (size_t alignment_in_bytes);
// Shortcuts for getting values of numeric types:
rvalue zero ();
......@@ -1286,11 +1288,24 @@ type::get_pointer ()
}
inline type
type::get_const ()
{
return type (gcc_jit_type_get_const (get_inner_type ()));
}
inline type
type::get_volatile ()
{
return type (gcc_jit_type_get_volatile (get_inner_type ()));
}
inline type
type::get_aligned (size_t alignment_in_bytes)
{
return type (gcc_jit_type_get_aligned (get_inner_type (),
alignment_in_bytes));
}
inline rvalue
type::zero ()
{
......
......@@ -2970,3 +2970,27 @@ gcc_jit_rvalue_set_bool_require_tail_call (gcc_jit_rvalue *rvalue,
call->set_require_tail_call (require_tail_call);
}
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
gcc::jit::recording::type::get_aligned method, in
jit-recording.c. */
gcc_jit_type *
gcc_jit_type_get_aligned (gcc_jit_type *type,
size_t alignment_in_bytes)
{
RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
gcc::jit::recording::context *ctxt = type->m_ctxt;
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL_PRINTF1
(pow2_or_zerop (alignment_in_bytes), ctxt, NULL,
"alignment not a power of two: %zi",
alignment_in_bytes);
return (gcc_jit_type *)type->get_aligned (alignment_in_bytes);
}
......@@ -1387,6 +1387,22 @@ extern void
gcc_jit_rvalue_set_bool_require_tail_call (gcc_jit_rvalue *call,
int require_tail_call);
#define LIBGCCJIT_HAVE_gcc_jit_type_get_aligned
/* Given type "T", get type:
T __attribute__ ((aligned (ALIGNMENT_IN_BYTES)))
The alignment must be a power of two.
This API entrypoint was added in LIBGCCJIT_ABI_7; you can test for its
presence using
#ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_aligned
*/
extern gcc_jit_type *
gcc_jit_type_get_aligned (gcc_jit_type *type,
size_t alignment_in_bytes);
#ifdef __cplusplus
}
#endif /* __cplusplus */
......
......@@ -150,3 +150,8 @@ LIBGCCJIT_ABI_6 {
global:
gcc_jit_rvalue_set_bool_require_tail_call;
} LIBGCCJIT_ABI_5;
LIBGCCJIT_ABI_7 {
global:
gcc_jit_type_get_aligned;
} LIBGCCJIT_ABI_6;
2017-04-24 David Malcolm <dmalcolm@redhat.com>
* jit.dg/all-non-failing-tests.h: Add test-alignment.c.
* jit.dg/test-alignment.c: New test case.
* jit.dg/test-alignment.cc: New test case.
* jit.dg/test-error-gcc_jit_type_get_aligned-non-power-of-two.c:
New test case.
2017-04-24 David Malcolm <dmalcolm@redhat.com>
PR c++/80016
* g++.dg/plugin/diagnostic-test-expressions-1.C (test_sizeof): New
test function.
......
......@@ -22,6 +22,13 @@
#undef create_code
#undef verify_code
/* test-alignment.c */
#define create_code create_code_alignment
#define verify_code verify_code_alignment
#include "test-alignment.c"
#undef create_code
#undef verify_code
/* test-arith-overflow.c */
#define create_code create_code_arith_overflow
#define verify_code verify_code_arith_overflow
......@@ -246,6 +253,9 @@ const struct testcase testcases[] = {
{"accessing_union",
create_code_accessing_union,
verify_code_accessing_union},
{"alignment",
create_code_alignment,
verify_code_alignment},
{"arith_overflow",
create_code_arith_overflow,
verify_code_arith_overflow},
......
#include <stdlib.h>
#include <stdio.h>
#include "libgccjit.h"
#include "harness.h"
struct s2
{
char x __attribute__ ((aligned (2)));
char y __attribute__ ((aligned (2)));
};
struct s4
{
char x __attribute__ ((aligned (4)));
char y __attribute__ ((aligned (4)));
};
struct s8
{
char x __attribute__ ((aligned (8)));
char y __attribute__ ((aligned (8)));
};
struct s16
{
char x __attribute__ ((aligned (16)));
char y __attribute__ ((aligned (16)));
};
struct s32
{
char x __attribute__ ((aligned (32)));
char y __attribute__ ((aligned (32)));
};
struct s64
{
char x __attribute__ ((aligned (64)));
char y __attribute__ ((aligned (64)));
};
struct s128
{
char x __attribute__ ((aligned (128)));
char y __attribute__ ((aligned (128)));
};
static void
create_aligned_code (gcc_jit_context *ctxt, const char *struct_name,
unsigned int alignment, const char *reader_fn_name,
const char *writer_fn_name)
{
/* Let's try to inject the equivalent of:
char
READER_FN_NAME (const struct STRUCT_NAME *f)
{
return f->x * f->y;
}
char
WRITER_FN_NAME (struct STRUCT_NAME *g)
{
g->x = 5;
g->y = 7;
return READER_FN_NAME (g);
}
*/
gcc_jit_type *char_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR);
gcc_jit_type *aligned_char_type =
gcc_jit_type_get_aligned (char_type, alignment);
gcc_jit_field *x =
gcc_jit_context_new_field (ctxt,
NULL,
aligned_char_type,
"x");
gcc_jit_field *y =
gcc_jit_context_new_field (ctxt,
NULL,
aligned_char_type,
"y");
gcc_jit_field *fields[] = {x, y};
gcc_jit_type *struct_type =
gcc_jit_struct_as_type (
gcc_jit_context_new_struct_type (ctxt, NULL, struct_name, 2, fields));
gcc_jit_type *const_struct_type = gcc_jit_type_get_const (struct_type);
gcc_jit_type *const_ptr_type = gcc_jit_type_get_pointer (const_struct_type);
/* Build the reader fn. */
gcc_jit_param *param_f =
gcc_jit_context_new_param (ctxt, NULL, const_ptr_type, "f");
gcc_jit_function *fn_test_reading =
gcc_jit_context_new_function (ctxt, NULL,
GCC_JIT_FUNCTION_EXPORTED,
char_type,
reader_fn_name,
1, &param_f,
0);
/* return f->x * f->y; */
gcc_jit_block *reading_block = gcc_jit_function_new_block (fn_test_reading, NULL);
gcc_jit_block_end_with_return (
reading_block,
NULL,
gcc_jit_context_new_binary_op (
ctxt, NULL,
GCC_JIT_BINARY_OP_MULT,
char_type,
gcc_jit_lvalue_as_rvalue (
gcc_jit_rvalue_dereference_field (
gcc_jit_param_as_rvalue (param_f),
NULL,
x)),
gcc_jit_lvalue_as_rvalue (
gcc_jit_rvalue_dereference_field (
gcc_jit_param_as_rvalue (param_f),
NULL,
y))));
/* Build the writer fn. */
gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (struct_type);
gcc_jit_param *param_g =
gcc_jit_context_new_param (ctxt, NULL, ptr_type, "g");
gcc_jit_function *fn_test_writing =
gcc_jit_context_new_function (ctxt, NULL,
GCC_JIT_FUNCTION_EXPORTED,
char_type,
writer_fn_name,
1, &param_g,
0);
/* g->x = 5; */
gcc_jit_block *writing_block = gcc_jit_function_new_block (fn_test_writing, NULL);
gcc_jit_block_add_assignment (
writing_block, NULL,
gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_g),
NULL, x),
gcc_jit_context_new_rvalue_from_int (ctxt, char_type, 5));
/* g->y = 7; */
gcc_jit_block_add_assignment (
writing_block, NULL,
gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_g),
NULL, y),
gcc_jit_context_new_rvalue_from_int (ctxt, char_type, 7));
/* return READER_FN_NAME (g); */
gcc_jit_rvalue *arg = gcc_jit_param_as_rvalue (param_g);
gcc_jit_block_end_with_return (
writing_block,
NULL,
gcc_jit_context_new_call (
ctxt, NULL,
fn_test_reading,
1, &arg));
}
/* Implement a verifier function for a given struct. */
#define IMPL_VERIFY_ALIGNED_CODE(TYPENAME) \
static void \
verify_aligned_code_ ##TYPENAME (gcc_jit_context *ctxt, \
gcc_jit_result *result, \
const char *writer_fn_name) \
{ \
typedef int (*fn_type) (struct TYPENAME *); \
CHECK_NON_NULL (result); \
\
struct TYPENAME tmp; \
memset (&tmp, 0xac, sizeof (tmp)); \
\
fn_type test_writing = \
(fn_type)gcc_jit_result_get_code (result, writer_fn_name); \
CHECK_NON_NULL (test_writing); \
\
/* Verify that the code correctly returns the product of the fields. */ \
CHECK_VALUE (test_writing (&tmp), 35); \
\
/* Verify the we can read the values of the fields, and thus that the \
struct layout agrees with that of the C frontend. */ \
CHECK_VALUE (tmp.x, 5); \
CHECK_VALUE (tmp.y, 7); \
}
void
create_code (gcc_jit_context *ctxt, void *user_data)
{
create_aligned_code (ctxt, "s2", 2, "test_aligned_reading_s2",
"test_aligned_writing_s2");
create_aligned_code (ctxt, "s4", 4, "test_aligned_reading_s4",
"test_aligned_writing_s4");
create_aligned_code (ctxt, "s8", 8, "test_aligned_reading_s8",
"test_aligned_writing_s8");
create_aligned_code (ctxt, "s16", 16, "test_aligned_reading_s16",
"test_aligned_writing_s16");
create_aligned_code (ctxt, "s32", 32, "test_aligned_reading_s32",
"test_aligned_writing_s32");
create_aligned_code (ctxt, "s64", 64, "test_aligned_reading_s64",
"test_aligned_writing_s64");
create_aligned_code (ctxt, "s128", 128, "test_aligned_reading_s128",
"test_aligned_writing_s128");
}
IMPL_VERIFY_ALIGNED_CODE(s2)
IMPL_VERIFY_ALIGNED_CODE(s4)
IMPL_VERIFY_ALIGNED_CODE(s8)
IMPL_VERIFY_ALIGNED_CODE(s16)
IMPL_VERIFY_ALIGNED_CODE(s32)
IMPL_VERIFY_ALIGNED_CODE(s64)
IMPL_VERIFY_ALIGNED_CODE(s128)
void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
verify_aligned_code_s2 (ctxt, result,
"test_aligned_writing_s2");
verify_aligned_code_s4 (ctxt, result,
"test_aligned_writing_s4");
verify_aligned_code_s8 (ctxt, result,
"test_aligned_writing_s8");
verify_aligned_code_s16 (ctxt, result,
"test_aligned_writing_s16");
verify_aligned_code_s32 (ctxt, result,
"test_aligned_writing_s32");
verify_aligned_code_s64 (ctxt, result,
"test_aligned_writing_s64");
verify_aligned_code_s128 (ctxt, result,
"test_aligned_writing_s128");
}
#include <stdlib.h>
#include <stdio.h>
#include "libgccjit++.h"
#include "harness.h"
struct s2
{
char x __attribute__ ((aligned (2)));
char y __attribute__ ((aligned (2)));
};
struct s4
{
char x __attribute__ ((aligned (4)));
char y __attribute__ ((aligned (4)));
};
struct s8
{
char x __attribute__ ((aligned (8)));
char y __attribute__ ((aligned (8)));
};
struct s16
{
char x __attribute__ ((aligned (16)));
char y __attribute__ ((aligned (16)));
};
struct s32
{
char x __attribute__ ((aligned (32)));
char y __attribute__ ((aligned (32)));
};
struct s64
{
char x __attribute__ ((aligned (64)));
char y __attribute__ ((aligned (64)));
};
struct s128
{
char x __attribute__ ((aligned (128)));
char y __attribute__ ((aligned (128)));
};
static void
create_aligned_code (gcc_jit_context *c_ctxt, const char *struct_name,
unsigned int alignment, const char *reader_fn_name,
const char *writer_fn_name)
{
/* Let's try to inject the equivalent of:
char
READER_FN_NAME (const struct STRUCT_NAME *f)
{
return f->x * f->y;
}
char
WRITER_FN_NAME (struct STRUCT_NAME *g)
{
g->x = 5;
g->y = 7;
return READER_FN_NAME (g);
}
*/
gccjit::context ctxt (c_ctxt);
gccjit::type char_type = ctxt.get_type (GCC_JIT_TYPE_CHAR);
gccjit::type aligned_char_type = char_type.get_aligned (alignment);
gccjit::field x = ctxt.new_field (aligned_char_type, "x");
gccjit::field y = ctxt.new_field (aligned_char_type, "y");
std::vector<gccjit::field> fields = {x, y};
gccjit::type struct_type = ctxt.new_struct_type (struct_name, fields);
gccjit::type const_struct_type = struct_type.get_const ();
gccjit::type const_ptr_type = const_struct_type.get_pointer ();
/* Build the reader fn. */
gccjit::param param_f = ctxt.new_param (const_ptr_type, "f");
std::vector<gccjit::param> params = {param_f};
gccjit::function fn_test_reading
= ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
char_type,
reader_fn_name,
params,
0);
/* return f->x * f->y; */
gccjit::block reading_block = fn_test_reading.new_block ();
reading_block.end_with_return (param_f.dereference_field (x)
* param_f.dereference_field (y));
/* Build the writer fn. */
gccjit::type ptr_type = struct_type.get_pointer ();
gccjit::param param_g = ctxt.new_param (ptr_type, "g");
params = {param_g};
gccjit::function fn_test_writing
= ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
char_type,
writer_fn_name,
params,
0);
/* g->x = 5; */
gccjit::block writing_block = fn_test_writing.new_block ();
writing_block.add_assignment (param_g.dereference_field (x),
ctxt.new_rvalue (char_type, 5));
/* g->y = 7; */
writing_block.add_assignment (param_g.dereference_field (y),
ctxt.new_rvalue (char_type, 7));
/* return READER_FN_NAME (g); */
writing_block.end_with_return (ctxt.new_call (fn_test_reading,
param_g));
}
/* Implement a verifier function for a given struct. */
template <typename T>
static void
verify_aligned_code (gcc_jit_context *ctxt,
gcc_jit_result *result,
const char *writer_fn_name)
{
typedef int (*fn_type) (T *);
CHECK_NON_NULL (result);
T tmp;
memset (&tmp, 0xac, sizeof (tmp));
fn_type test_writing =
(fn_type)gcc_jit_result_get_code (result, writer_fn_name);
CHECK_NON_NULL (test_writing);
/* Verify that the code correctly returns the product of the fields. */
CHECK_VALUE (test_writing (&tmp), 35);
/* Verify the we can read the values of the fields, and thus that the
struct layout agrees with that of the C++ frontend. */
CHECK_VALUE (tmp.x, 5);
CHECK_VALUE (tmp.y, 7);
}
void
create_code (gcc_jit_context *ctxt, void *user_data)
{
create_aligned_code (ctxt, "s2", 2, "test_aligned_reading_s2",
"test_aligned_writing_s2");
create_aligned_code (ctxt, "s4", 4, "test_aligned_reading_s4",
"test_aligned_writing_s4");
create_aligned_code (ctxt, "s8", 8, "test_aligned_reading_s8",
"test_aligned_writing_s8");
create_aligned_code (ctxt, "s16", 16, "test_aligned_reading_s16",
"test_aligned_writing_s16");
create_aligned_code (ctxt, "s32", 32, "test_aligned_reading_s32",
"test_aligned_writing_s32");
create_aligned_code (ctxt, "s64", 64, "test_aligned_reading_s64",
"test_aligned_writing_s64");
create_aligned_code (ctxt, "s128", 128, "test_aligned_reading_s128",
"test_aligned_writing_s128");
}
void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
verify_aligned_code<s2> (ctxt, result, "test_aligned_writing_s2");
verify_aligned_code<s4> (ctxt, result, "test_aligned_writing_s4");
verify_aligned_code<s8> (ctxt, result, "test_aligned_writing_s8");
verify_aligned_code<s16> (ctxt, result, "test_aligned_writing_s16");
verify_aligned_code<s32> (ctxt, result, "test_aligned_writing_s32");
verify_aligned_code<s64> (ctxt, result, "test_aligned_writing_s64");
verify_aligned_code<s128> (ctxt, result, "test_aligned_writing_s128");
}
#include <stdlib.h>
#include <stdio.h>
#include "libgccjit.h"
#include "harness.h"
void
create_code (gcc_jit_context *ctxt, void *user_data)
{
gcc_jit_type *int_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
/* Trigger an API error by passing a bad alignment. */
(void)gcc_jit_type_get_aligned (int_type, 7);
}
void
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_type_get_aligned:"
" alignment not a power of two: 7"));
}
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