mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 03:46:53 -05:00
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
This commit is contained in:
committed by
David Malcolm
parent
761ad35c86
commit
0ebd1f00b8
@@ -1,3 +1,39 @@
|
||||
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.
|
||||
|
||||
988
gcc/jit/docs/_build/texinfo/libgccjit.texi
vendored
988
gcc/jit/docs/_build/texinfo/libgccjit.texi
vendored
File diff suppressed because it is too large
Load Diff
@@ -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 ();
|
||||
@@ -1285,12 +1287,25 @@ type::get_pointer ()
|
||||
return type (gcc_jit_type_get_pointer (get_inner_type ()));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
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
|
||||
|
||||
@@ -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},
|
||||
|
||||
232
gcc/testsuite/jit.dg/test-alignment.c
Normal file
232
gcc/testsuite/jit.dg/test-alignment.c
Normal file
@@ -0,0 +1,232 @@
|
||||
#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, ¶m_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, ¶m_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");
|
||||
}
|
||||
176
gcc/testsuite/jit.dg/test-alignment.cc
Normal file
176
gcc/testsuite/jit.dg/test-alignment.cc
Normal file
@@ -0,0 +1,176 @@
|
||||
#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");
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#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"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user