[jit] Add support for unions
David Malcolm
dmalcolm@redhat.com
Wed Jan 1 00:00:00 GMT 2014
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 <dmalcolm@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 <dmalcolm@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 <dmalcolm@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 <dmalcolm@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
More information about the Jit
mailing list