Pushed to branch dmalcolm/jit: This adds a new API entrypoint:
gcc_jit_context_new_union_type gcc/jit/ * libgccjit.h (gcc_jit_context_new_union_type): New entrypoint. (gcc_jit_lvalue_access_field): Rename first param from "struct_" to "struct_or_union". (gcc_jit_rvalue_access_field): Likewise. * libgccjit.c (gcc_jit_context_new_union_type): New entrypoint. * libgccjit.map (gcc_jit_context_new_union_type): New entrypoint. * internal-api.h (gcc::jit::recording::compound_type): New class (gcc::jit::recording::union): New class. (gcc::jit::playback::struct_): Rename this class to... (gcc::jit::playback::compound_type): ...this. (gcc::jit::recording::context::new_union_type): New method. (gcc::jit::recording::context): Rename field "m_structs" to "m_compound_types", generalizing from a vec <struct_ *> to a vec<compound_type *>. (gcc::jit::recording::field): Update field m_container from struct * to container_type *. (gcc::jit::recording::field::get_container): Generalize from struct_ * to container_type *. (gcc::jit::recording::field::set_container): Likewise. (gcc::jit::recording::compound_type): New subclass of type, to be a superclass of existing class struct_ and new class union_. (gcc::jit::recording::struct_::get_name): Move to... (gcc::jit::recording::compound_type::get_name): ...here. (gcc::jit::recording::struct_::get_loc): Move to... (gcc::jit::recording::compound_type::get_loc): ...here. (gcc::jit::recording::struct_::set_fields): Move to... (gcc::jit::recording::compound_type::set_fields): ...here. (gcc::jit::recording::struct_::dereference): Move to... (gcc::jit::recording::compound_type::dereference): ...here. (gcc::jit::recording::struct_::is_int): Move to... (gcc::jit::recording::compound_type::is_int): ...here. (gcc::jit::recording::struct_::is_float): Move to... (gcc::jit::recording::compound_type::is_float): ...here. (gcc::jit::recording::struct_::is_bool): Move to... (gcc::jit::recording::compound_type::is_bool): ...here. (gcc::jit::recording::struct_::is_pointer): Move to... (gcc::jit::recording::compound_type::is_pointer): ...here. (gcc::jit::recording::struct_::is_array): Move to... (gcc::jit::recording::compound_type::is_array): ...here. (gcc::jit::recording::struct_::playback_struct): Move to... (gcc::jit::recording::compound_type::playback_compound_type): ...here, renaming and updating return type. (gcc::jit::recording::struct_): Inherit from compound_type, rather than just type. (gcc::jit::recording::fields): Update to work on compound_type * rather than struct_ *, renaming "m_struct" to "m_struct_or_union". (gcc::jit::recording::union): New subclass of compound_type. (gcc::jit::playback::context::new_struct_type): Generalize by renaming to... (gcc::jit::playback::context::new_compound_type): ...this, and and an "is_struct" bool param. (gcc::jit::playback::struct_): Generalize by renaming class to... (gcc::jit::playback::compound_type): ...this. * internal-api.c (gcc::jit::recording::context::context): Rename field "m_structs" to "m_compound_types". (gcc::jit::recording::context::new_struct_type): Likewise. (gcc::jit::recording::context::new_union_type): New method. (gcc::jit::recording::context::dump_to_file): Field "m_structs" is renamed "m_compound_types" and changes type from struct_ * to compound_type *. (gcc::jit::recording::compound_type::compound_type): New ctor, built from old body of gcc::jit::recording::struct_::struct_. (gcc::jit::recording::struct_::set_fields): Move class to... (gcc::jit::recording::compound_type::set_fields): ... here. (gcc::jit::recording::struct_::dereference): Move class to... (gcc::jit::recording::compound_type::dereference): ...here. (gcc::jit::recording::struct_::struct_): Reimplement by calling base class ctor. (gcc::jit::recording::struct_::replay_into): The playback hook is now "new_compound_type" and adds a bool, with true for "is_struct" (vs a union). (gcc::jit::recording::struct_::make_debug_string): "m_name" is now moved to base class and private, so use an accessor. (gcc::jit::recording::union_::union_): New function. (gcc::jit::recording::union_::replay_into): New function. (gcc::jit::recording::union_::make_debug_string): New function. (gcc::jit::recording::fields::fields): Update first param from struct_ * to compound_type *, and rename field "m_struct" to "m_struct_or_union". (gcc::jit::recording::fields::replay_into): "m_struct" is now "m_struct_or_union" and has a playback_compound_type rather than a playback_struct. (gcc::jit::recording::fields::write_to_dump): Update for renaming of m_struct to m_struct_or_union. (gcc::jit::playback::context::new_struct_type): Rename method to... (gcc::jit::playback::context::new_compound_type): this, generalizing so that it can make unions as well as structs; the underlying playback type is now called "compound_type". (gcc::jit::playback::struct_::set_fields): This method's class has changed name, so this is now... (gcc::jit::playback::compound_type::set_fields): ...this method. * TODO.rst: Unions are done. gcc/testsuite/ * jit.dg/test-accessing-union.c: New test case. * jit.dg/test-combination.c: Add test-accessing-union.c. --- gcc/jit/ChangeLog.jit | 101 +++++++++++++++++++++++++++ gcc/jit/TODO.rst | 5 -- gcc/jit/internal-api.c | 102 ++++++++++++++++++++-------- gcc/jit/internal-api.h | 94 +++++++++++++++++-------- gcc/jit/libgccjit.c | 30 ++++++++ gcc/jit/libgccjit.h | 12 +++- gcc/jit/libgccjit.map | 1 + gcc/testsuite/ChangeLog.jit | 5 ++ gcc/testsuite/jit.dg/test-accessing-union.c | 97 ++++++++++++++++++++++++++ gcc/testsuite/jit.dg/test-combination.c | 9 +++ 10 files changed, 391 insertions(+), 65 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-accessing-union.c diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit index f7fd642..cb4ee60 100644 --- a/gcc/jit/ChangeLog.jit +++ b/gcc/jit/ChangeLog.jit @@ -1,5 +1,106 @@ 2014-08-08 David Malcolm <dmalc...@redhat.com> + * libgccjit.h (gcc_jit_context_new_union_type): New entrypoint. + (gcc_jit_lvalue_access_field): Rename first param from "struct_" + to "struct_or_union". + (gcc_jit_rvalue_access_field): Likewise. + + * libgccjit.c (gcc_jit_context_new_union_type): New entrypoint. + + * libgccjit.map (gcc_jit_context_new_union_type): New entrypoint. + + * internal-api.h (gcc::jit::recording::compound_type): New class + (gcc::jit::recording::union): New class. + (gcc::jit::playback::struct_): Rename this class to... + (gcc::jit::playback::compound_type): ...this. + (gcc::jit::recording::context::new_union_type): New method. + (gcc::jit::recording::context): Rename field "m_structs" to + "m_compound_types", generalizing from a vec <struct_ *> to a + vec<compound_type *>. + (gcc::jit::recording::field): Update field m_container from + struct * to container_type *. + (gcc::jit::recording::field::get_container): Generalize from + struct_ * to container_type *. + (gcc::jit::recording::field::set_container): Likewise. + (gcc::jit::recording::compound_type): New subclass of type, to + be a superclass of existing class struct_ and new class union_. + (gcc::jit::recording::struct_::get_name): Move to... + (gcc::jit::recording::compound_type::get_name): ...here. + (gcc::jit::recording::struct_::get_loc): Move to... + (gcc::jit::recording::compound_type::get_loc): ...here. + (gcc::jit::recording::struct_::set_fields): Move to... + (gcc::jit::recording::compound_type::set_fields): ...here. + (gcc::jit::recording::struct_::dereference): Move to... + (gcc::jit::recording::compound_type::dereference): ...here. + (gcc::jit::recording::struct_::is_int): Move to... + (gcc::jit::recording::compound_type::is_int): ...here. + (gcc::jit::recording::struct_::is_float): Move to... + (gcc::jit::recording::compound_type::is_float): ...here. + (gcc::jit::recording::struct_::is_bool): Move to... + (gcc::jit::recording::compound_type::is_bool): ...here. + (gcc::jit::recording::struct_::is_pointer): Move to... + (gcc::jit::recording::compound_type::is_pointer): ...here. + (gcc::jit::recording::struct_::is_array): Move to... + (gcc::jit::recording::compound_type::is_array): ...here. + (gcc::jit::recording::struct_::playback_struct): Move to... + (gcc::jit::recording::compound_type::playback_compound_type): + ...here, renaming and updating return type. + (gcc::jit::recording::struct_): Inherit from compound_type, + rather than just type. + (gcc::jit::recording::fields): Update to work on compound_type * + rather than struct_ *, renaming "m_struct" to "m_struct_or_union". + (gcc::jit::recording::union): New subclass of compound_type. + (gcc::jit::playback::context::new_struct_type): Generalize by + renaming to... + (gcc::jit::playback::context::new_compound_type): ...this, and + and an "is_struct" bool param. + (gcc::jit::playback::struct_): Generalize by renaming class to... + (gcc::jit::playback::compound_type): ...this. + + * internal-api.c (gcc::jit::recording::context::context): Rename + field "m_structs" to "m_compound_types". + (gcc::jit::recording::context::new_struct_type): Likewise. + (gcc::jit::recording::context::new_union_type): New method. + (gcc::jit::recording::context::dump_to_file): Field "m_structs" + is renamed "m_compound_types" and changes type from struct_ * + to compound_type *. + (gcc::jit::recording::compound_type::compound_type): New ctor, + built from old body of gcc::jit::recording::struct_::struct_. + (gcc::jit::recording::struct_::set_fields): Move class to... + (gcc::jit::recording::compound_type::set_fields): ... here. + (gcc::jit::recording::struct_::dereference): Move class to... + (gcc::jit::recording::compound_type::dereference): ...here. + (gcc::jit::recording::struct_::struct_): Reimplement by calling + base class ctor. + (gcc::jit::recording::struct_::replay_into): The playback hook + is now "new_compound_type" and adds a bool, with true for + "is_struct" (vs a union). + (gcc::jit::recording::struct_::make_debug_string): "m_name" is + now moved to base class and private, so use an accessor. + (gcc::jit::recording::union_::union_): New function. + (gcc::jit::recording::union_::replay_into): New function. + (gcc::jit::recording::union_::make_debug_string): New function. + (gcc::jit::recording::fields::fields): Update first param from + struct_ * to compound_type *, and rename field "m_struct" to + "m_struct_or_union". + (gcc::jit::recording::fields::replay_into): "m_struct" is now + "m_struct_or_union" and has a playback_compound_type rather + than a playback_struct. + (gcc::jit::recording::fields::write_to_dump): Update for + renaming of m_struct to m_struct_or_union. + (gcc::jit::playback::context::new_struct_type): Rename method + to... + (gcc::jit::playback::context::new_compound_type): this, + generalizing so that it can make unions as well as structs; the + underlying playback type is now called "compound_type". + (gcc::jit::playback::struct_::set_fields): This method's class has + changed name, so this is now... + (gcc::jit::playback::compound_type::set_fields): ...this method. + + * TODO.rst: Unions are done. + +2014-08-08 David Malcolm <dmalc...@redhat.com> + * TODO.rst: Function ptrs are done. * internal-api.c (gcc::jit::recording::context::new_function_ptr_type): New method. diff --git a/gcc/jit/TODO.rst b/gcc/jit/TODO.rst index d832337..fd7b07c 100644 --- a/gcc/jit/TODO.rst +++ b/gcc/jit/TODO.rst @@ -13,11 +13,6 @@ Initial Release * enums and ABI: give enums specific numbers, in ranges, to make it possible to maintain a logical ordering whilst preserving ABI. -* more language features: - - * more types: - * unions - * expose the statements in the API? (mostly so they can be stringified?) * support more arithmetic ops and comparison modes diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c index cacb526..bc353be 100644 --- a/gcc/jit/internal-api.c +++ b/gcc/jit/internal-api.c @@ -134,7 +134,7 @@ recording::context::context (context *parent_ctxt) : m_parent_ctxt (parent_ctxt), m_error_count (0), m_mementos (), - m_structs (), + m_compound_types (), m_functions (), m_FILE_type (NULL), m_builtins_manager(NULL) @@ -377,7 +377,17 @@ recording::context::new_struct_type (recording::location *loc, { recording::struct_ *result = new struct_ (this, loc, new_string (name)); record (result); - m_structs.safe_push (result); + m_compound_types.safe_push (result); + return result; +} + +recording::union_ * +recording::context::new_union_type (recording::location *loc, + const char *name) +{ + recording::union_ *result = new union_ (this, loc, new_string (name)); + record (result); + m_compound_types.safe_push (result); return result; } @@ -695,15 +705,15 @@ recording::context::dump_to_file (const char *path, bool update_locations) int i; dump d (*this, path, update_locations); - /* Forward declaration of structs. */ - struct_ *st; - FOR_EACH_VEC_ELT (m_structs, i, st) + /* Forward declaration of structs and unions. */ + compound_type *st; + FOR_EACH_VEC_ELT (m_compound_types, i, st) { d.write ("%s;\n\n", st->get_debug_string ()); } /* Content of structs, where set. */ - FOR_EACH_VEC_ELT (m_structs, i, st) + FOR_EACH_VEC_ELT (m_compound_types, i, st) if (st->get_fields ()) { st->get_fields ()->write_to_dump (d); @@ -1294,10 +1304,10 @@ recording::field::make_debug_string () return m_name; } -/* gcc::jit::recording::struct_:: */ -recording::struct_::struct_ (context *ctxt, - location *loc, - string *name) +/* gcc::jit::recording::compound_type */ +recording::compound_type::compound_type (context *ctxt, + location *loc, + string *name) : type (ctxt), m_loc (loc), m_name (name), @@ -1306,9 +1316,9 @@ recording::struct_::struct_ (context *ctxt, } void -recording::struct_::set_fields (location *loc, - int num_fields, - field **field_array) +recording::compound_type::set_fields (location *loc, + int num_fields, + field **field_array) { m_loc = loc; gcc_assert (NULL == m_fields); @@ -1318,38 +1328,71 @@ recording::struct_::set_fields (location *loc, } recording::type * -recording::struct_::dereference () +recording::compound_type::dereference () { return NULL; /* not a pointer */ } +/* gcc::jit::recording::struct_:: */ +recording::struct_::struct_ (context *ctxt, + location *loc, + string *name) +: compound_type (ctxt, loc, name) +{ +} + void recording::struct_::replay_into (replayer *r) { set_playback_obj ( - r->new_struct_type (playback_location (r, m_loc), - m_name->c_str ())); + r->new_compound_type (playback_location (r, get_loc ()), + get_name ()->c_str (), + true /* is_struct */)); } recording::string * recording::struct_::make_debug_string () { return string::from_printf (m_ctxt, - "struct %s", m_name->c_str ()); + "struct %s", get_name ()->c_str ()); +} + +/* gcc::jit::recording::union_:: */ +recording::union_::union_ (context *ctxt, + location *loc, + string *name) +: compound_type (ctxt, loc, name) +{ +} + +void +recording::union_::replay_into (replayer *r) +{ + set_playback_obj ( + r->new_compound_type (playback_location (r, get_loc ()), + get_name ()->c_str (), + false /* is_struct */)); +} + +recording::string * +recording::union_::make_debug_string () +{ + return string::from_printf (m_ctxt, + "union %s", get_name ()->c_str ()); } /* gcc::jit::recording::fields:: */ -recording::fields::fields (struct_ *struct_, +recording::fields::fields (compound_type *struct_or_union, int num_fields, field **fields) -: memento (struct_->m_ctxt), - m_struct (struct_), +: memento (struct_or_union->m_ctxt), + m_struct_or_union (struct_or_union), m_fields () { for (int i = 0; i < num_fields; i++) { gcc_assert (fields[i]->get_container () == NULL); - fields[i]->set_container (m_struct); + fields[i]->set_container (m_struct_or_union); m_fields.safe_push (fields[i]); } } @@ -1361,7 +1404,7 @@ recording::fields::replay_into (replayer *) playback_fields.create (m_fields.length ()); for (unsigned i = 0; i < m_fields.length (); i++) playback_fields.safe_push (m_fields[i]->playback_field ()); - m_struct->playback_struct ()->set_fields (playback_fields); + m_struct_or_union->playback_compound_type ()->set_fields (playback_fields); } void @@ -1370,7 +1413,7 @@ recording::fields::write_to_dump (dump &d) int i; field *f; - d.write ("%s\n{\n", m_struct->get_debug_string ()); + d.write ("%s\n{\n", m_struct_or_union->get_debug_string ()); FOR_EACH_VEC_ELT (m_fields, i, f) f->write_to_dump (d); d.write ("};\n"); @@ -2685,27 +2728,28 @@ new_field (location *loc, return new field (decl); } -playback::struct_ * +playback::compound_type * playback::context:: -new_struct_type (location *loc, - const char *name) +new_compound_type (location *loc, + const char *name, + bool is_struct) /* else is union */ { gcc_assert (name); /* Compare with c/c-decl.c: start_struct. */ - tree t = make_node (RECORD_TYPE); + tree t = make_node (is_struct ? RECORD_TYPE : UNION_TYPE); TYPE_NAME (t) = get_identifier (name); TYPE_SIZE (t) = 0; if (loc) set_tree_location (t, loc); - return new struct_ (t); + return new compound_type (t); } void -playback::struct_::set_fields (const vec<playback::field *> &fields) +playback::compound_type::set_fields (const vec<playback::field *> &fields) { /* Compare with c/c-decl.c: finish_struct. */ tree t = as_tree (); diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h index c4fe2f3..274b6ca 100644 --- a/gcc/jit/internal-api.h +++ b/gcc/jit/internal-api.h @@ -85,7 +85,9 @@ namespace recording { class type; class function_type; class field; + class compound_type; class struct_; + class union_; class fields; class function; class block; @@ -101,7 +103,7 @@ namespace playback { class location; class type; class field; - class struct_; + class compound_type; class function; class block; class rvalue; @@ -192,6 +194,10 @@ public: new_struct_type (location *loc, const char *name); + union_ * + new_union_type (location *loc, + const char *name); + type * new_function_ptr_type (location *loc, type *return_type, @@ -347,7 +353,7 @@ private: vec<memento *> m_mementos; /* Specific recordings, for use by dump_to_file. */ - vec<struct_ *> m_structs; + vec<compound_type *> m_compound_types; vec<function *> m_functions; type *m_basic_types[NUM_GCC_JIT_TYPES]; @@ -748,8 +754,8 @@ public: type * get_type () const { return m_type; } - struct_ * get_container () const { return m_container; } - void set_container (struct_ *c) { m_container = c; } + compound_type * get_container () const { return m_container; } + void set_container (compound_type *c) { m_container = c; } void replay_into (replayer *); @@ -768,22 +774,19 @@ private: location *m_loc; type *m_type; string *m_name; - struct_ *m_container; + compound_type *m_container; }; -class struct_ : public type +/* Base class for struct_ and union_ */ +class compound_type : public type { public: - struct_ (context *ctxt, - location *loc, - string *name); - - struct_ *dyn_cast_struct () { return this; } - - type * - as_type () { return this; } + compound_type (context *ctxt, + location *loc, + string *name); string *get_name () const { return m_name; } + location *get_loc () const { return m_loc; } fields * get_fields () { return m_fields; } void @@ -799,28 +802,42 @@ public: type *is_pointer () { return NULL; } type *is_array () { return NULL; } - void replay_into (replayer *r); - - playback::struct_ * - playback_struct () + playback::compound_type * + playback_compound_type () { - return static_cast <playback::struct_ *> (m_playback_obj); + return static_cast <playback::compound_type *> (m_playback_obj); } private: - string * make_debug_string (); - -private: location *m_loc; string *m_name; fields *m_fields; }; +class struct_ : public compound_type +{ +public: + struct_ (context *ctxt, + location *loc, + string *name); + + struct_ *dyn_cast_struct () { return this; } + + type * + as_type () { return this; } + + void replay_into (replayer *r); + +private: + string * make_debug_string (); + +}; + // memento of struct_::set_fields class fields : public memento { public: - fields (struct_ *struct_, + fields (compound_type *struct_or_union, int num_fields, field **fields); @@ -832,10 +849,28 @@ private: string * make_debug_string (); private: - struct_ *m_struct; + compound_type *m_struct_or_union; vec<field *> m_fields; }; +class union_ : public compound_type +{ +public: + union_ (context *ctxt, + location *loc, + string *name); + + void replay_into (replayer *r); + +private: + string * make_debug_string (); + +private: + location *m_loc; + string *m_name; + fields *m_fields; +}; + class rvalue : public memento { public: @@ -1674,9 +1709,10 @@ public: type *type, const char *name); - struct_ * - new_struct_type (location *loc, - const char *name); + compound_type * + new_compound_type (location *loc, + const char *name, + bool is_struct); /* else is union */ type * new_function_type (type *return_type, @@ -1899,10 +1935,10 @@ private: tree m_inner; }; -class struct_ : public type +class compound_type : public type { public: - struct_ (tree inner) + compound_type (tree inner) : type (inner) {} diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 28deb7d..9550d8f 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -462,6 +462,36 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type, } gcc_jit_type * +gcc_jit_context_new_union_type (gcc_jit_context *ctxt, + gcc_jit_location *loc, + const char *name, + int num_fields, + gcc_jit_field **fields) +{ + RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); + RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); + if (num_fields) + RETURN_NULL_IF_FAIL (fields, ctxt, loc, "NULL fields ptr"); + for (int i = 0; i < num_fields; i++) + { + RETURN_NULL_IF_FAIL (fields[i], ctxt, loc, "NULL field ptr"); + RETURN_NULL_IF_FAIL_PRINTF2 ( + NULL == fields[i]->get_container (), + ctxt, loc, + "%s is already a field of %s", + fields[i]->get_debug_string (), + fields[i]->get_container ()->get_debug_string ()); + } + + gcc::jit::recording::union_ *result = + ctxt->new_union_type (loc, name); + result->set_fields (loc, + num_fields, + (gcc::jit::recording::field **)fields); + return (gcc_jit_type *) (result); +} + +gcc_jit_type * gcc_jit_context_new_function_ptr_type (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_type *return_type, diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index a7e437ed..29d3389 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -436,6 +436,14 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type, int num_fields, gcc_jit_field **fields); +/* Unions work similarly to structs. */ +extern gcc_jit_type * +gcc_jit_context_new_union_type (gcc_jit_context *ctxt, + gcc_jit_location *loc, + const char *name, + int num_fields, + gcc_jit_field **fields); + /* Function pointers. */ extern gcc_jit_type * @@ -753,7 +761,7 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt, (EXPR).field = ...; in C. */ extern gcc_jit_lvalue * -gcc_jit_lvalue_access_field (gcc_jit_lvalue *struct_, +gcc_jit_lvalue_access_field (gcc_jit_lvalue *struct_or_union, gcc_jit_location *loc, gcc_jit_field *field); @@ -761,7 +769,7 @@ gcc_jit_lvalue_access_field (gcc_jit_lvalue *struct_, (EXPR).field in C. */ extern gcc_jit_rvalue * -gcc_jit_rvalue_access_field (gcc_jit_rvalue *struct_, +gcc_jit_rvalue_access_field (gcc_jit_rvalue *struct_or_union, gcc_jit_location *loc, gcc_jit_field *field); diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index d7f5d7c..768e010 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -40,6 +40,7 @@ gcc_jit_context_new_string_literal; gcc_jit_context_new_struct_type; gcc_jit_context_new_unary_op; + gcc_jit_context_new_union_type; gcc_jit_context_null; gcc_jit_context_one; gcc_jit_context_release; diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit index 0842a1b..cdde662 100644 --- a/gcc/testsuite/ChangeLog.jit +++ b/gcc/testsuite/ChangeLog.jit @@ -1,5 +1,10 @@ 2014-08-08 David Malcolm <dmalc...@redhat.com> + * jit.dg/test-accessing-union.c: New test case. + * jit.dg/test-combination.c: Add test-accessing-union.c. + +2014-08-08 David Malcolm <dmalc...@redhat.com> + * jit.dg/test-combination.c (create_code): Add missing calls to create_code_quadratic and create_code_reading_struct. (verify_code): Add missing calls to verify_code_quadratic and diff --git a/gcc/testsuite/jit.dg/test-accessing-union.c b/gcc/testsuite/jit.dg/test-accessing-union.c new file mode 100644 index 0000000..658d1bc --- /dev/null +++ b/gcc/testsuite/jit.dg/test-accessing-union.c @@ -0,0 +1,97 @@ +#include <stdlib.h> +#include <stdio.h> + +#include "libgccjit.h" + +#include "harness.h" + +union int_or_float +{ + int as_int; + float as_float; +}; + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + float + test_union (int i) + { + union int_or_float u; + u.as_int = i; + return u.as_float; + } + */ + 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_field *as_int = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "as_int"); + gcc_jit_field *as_float = + gcc_jit_context_new_field (ctxt, + NULL, + float_type, + "as_float"); + gcc_jit_field *fields[] = {as_int, as_float}; + gcc_jit_type *union_type = + gcc_jit_context_new_union_type (ctxt, NULL, + "int_or_float", 2, fields); + + /* Build the test function. */ + gcc_jit_param *param_i = + gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + float_type, + "test_union", + 1, ¶m_i, + 0); + + gcc_jit_lvalue *u = + gcc_jit_function_new_local (test_fn, NULL, + union_type, "u"); + + gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); + + /* u.as_int = i; */ + gcc_jit_block_add_assignment ( + block, + NULL, + /* "u.as_int = ..." */ + gcc_jit_lvalue_access_field (u, + NULL, + as_int), + gcc_jit_param_as_rvalue (param_i)); + + /* return u.as_float; */ + gcc_jit_block_end_with_return ( + block, NULL, + gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (u), + NULL, + as_float)); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + typedef float (*fn_type) (int i); + CHECK_NON_NULL (result); + + fn_type test_union = + (fn_type)gcc_jit_result_get_code (result, "test_union"); + CHECK_NON_NULL (test_union); + + /* Call the JIT-generated function. */ + float f_result = test_union (42); + + union int_or_float u; + u.as_float = f_result; + + CHECK_VALUE (u.as_int, 42); +} diff --git a/gcc/testsuite/jit.dg/test-combination.c b/gcc/testsuite/jit.dg/test-combination.c index a8bf3bc..a3e3102 100644 --- a/gcc/testsuite/jit.dg/test-combination.c +++ b/gcc/testsuite/jit.dg/test-combination.c @@ -14,6 +14,13 @@ #undef create_code #undef verify_code +/* test-accessing-union.c */ +#define create_code create_code_accessing_union +#define verify_code verify_code_accessing_union +#include "test-accessing-union.c" +#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 @@ -155,6 +162,7 @@ void create_code (gcc_jit_context *ctxt, void * user_data) { create_code_accessing_struct (ctxt, user_data); + create_code_accessing_union (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); @@ -179,6 +187,7 @@ void verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) { verify_code_accessing_struct (ctxt, result); + verify_code_accessing_union (ctxt, result); verify_code_array_as_pointer (ctxt, result); verify_code_arrays (ctxt, result); verify_code_calling_external_function (ctxt, result); -- 1.8.5.3