177 lines
5.3 KiB
C++
177 lines
5.3 KiB
C++
|
#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 char (*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");
|
||
|
}
|