This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[jit] Support self-referential data structures (API changes).
- From: David Malcolm <dmalcolm at redhat dot com>
- To: jit at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Cc: David Malcolm <dmalcolm at redhat dot com>
- Date: Tue, 18 Feb 2014 16:23:22 -0500
- Subject: [jit] Support self-referential data structures (API changes).
- Authentication-results: sourceware.org; auth=none
Committed to branch dmalcolm/jit:
New API type:
- gcc_jit_struct
New API entrypoints:
- gcc_jit_context_new_opaque_struct
- gcc_jit_struct_as_type
- gcc_jit_struct_set_fields
- gcc_jit_context_null: get the NULL value for a pointer type.
Changed API entrypoint:
- gcc_jit_context_new_struct_type: changed return type from
(gcc_jit_type *) to (gcc_jit_struct *).
Internally, split out populating the fields of a struct from the creation
of said struct.
Also, require conditionals to be of boolean type (so that conversions must,
for now, be explicit), since the implicit behavior of passing in a pointer
didn't match that of C.
gcc/jit/
* libgccjit.h (gcc_jit_struct): New.
(gcc_jit_context_new_struct_type): Change return type from gcc_jit_type
to gcc_jit_struct.
(gcc_jit_context_new_opaque_struct): New.
(gcc_jit_struct_as_type): New.
(gcc_jit_struct_set_fields): New.
(gcc_jit_context_null): New.
* libgccjit.map (gcc_jit_context_new_opaque_struct): New.
(gcc_jit_context_null): New.
(gcc_jit_struct_as_type): New.
(gcc_jit_struct_set_fields): New.
* libgccjit++.h (gccjit::context::new_struct_type): Return a
struct_ rather than a type.
(gccjit::context::new_opaque_struct_type): New.
(gccjit::struct_): New subclass of type.
* libgccjit.c (gcc_jit_struct): New.
(RETURN_VAL_IF_FAIL_PRINTF1): New.
(RETURN_VAL_IF_FAIL_PRINTF2): New.
(RETURN_NULL_IF_FAIL_PRINTF1): New.
(RETURN_IF_FAIL_PRINTF1): New.
(RETURN_IF_FAIL_PRINTF2): New.
(gcc_jit_context_new_struct_type): Return a gcc_jit_struct rather
than a gcc_jit_type; implement by creating the struct, then
setting the fields in it.
(gcc_jit_context_new_opaque_struct): New.
(gcc_jit_struct_as_type): New.
(gcc_jit_struct_set_fields): New.
(gcc_jit_context_null): New.
(gcc_jit_lvalue_access_field): Use the struct's context when
reporting on a NULL field; verify that the field has been placed
in a struct.
(gcc_jit_rvalue_access_field): Likewise.
(is_bool): New.
(gcc_jit_function_add_conditional): Use the function's context
when reporting errors; verify that boolval's type is indeed
boolean.
(gcc_jit_function_new_loop): Likewise.
* internal-api.h (gcc::jit::recording::context::new_struct_type):
Don't accept fields, and return a struct_ rather than a type_, so
that fields can be set later.
(gcc::jit::recording::struct_::struct_): Store a (fields *) rather
than a vec of fields.
(gcc::jit::recording::struct_::as_type): New.
(gcc::jit::recording::struct_::get_fields): New.
(gcc::jit::recording::struct_::set_fields): New.
(gcc::jit::recording::struct_::playback_struct): New.
(gcc::jit::recording::fields): New class.
(gcc::jit::playback::context::new_struct_type): Don't accept
fields, and return a struct_ rather than a type_, so that fields
can be set later.
(gcc::jit::playback::struct_): New subclass of type.
* internal-api.c (gcc::jit::recording::context::get_type): With
nested contexts, create basic types within the ultimate parent
context, allowing for a fast check for the boolean type using
pointer equality.
(gcc::jit::recording::context::new_struct_type): Don't accept
fields, and return a struct_ rather than a type_, so that fields
can be set later.
(gcc::jit::recording::context::get_opaque_FILE_type): Update for
struct-creation changes.
(gcc::jit::recording::struct_::struct_): Store a (fields *) rather
than a vec of fields.
(gcc::jit::recording::struct_::set_fields): New.
(gcc::jit::recording::struct_::replay_into): Don't playback the
fields, as this is now done by a fields instance.
(gcc::jit::recording::fields::fields): New.
(gcc::jit::recording::fields::replay_into): New.
(gcc::jit::recording::fields::make_debug_string): New.
(gcc::jit:: playback::context::new_struct_type): Don't accept
fields, and return a struct_ rather than a type_, so that fields
can be set later.
(gcc::jit::playback::struct_::set_fields): New.
* TODO.rst: Update.
gcc/testsuite/
* jit.dg/test-accessing-struct.c (create_code): Update for change to
return type of gcc_jit_context_new_struct_type.
* jit.dg/test-arrays.c (create_code): Likewise.
* jit.dg/test-error-accessing-field-in-other-struct.c (create_code):
Likewise.
* jit.dg/test-error-dereference-field-of-non-pointer.c (create_code):
Likewise.
* jit.dg/test-fuzzer.c (make_random_type): Likewise.
* jit.dg/test-nested-contexts.c (make_types): Likewise.
* jit.dg/test-quadratic.c (make_types): Likewise.
* jit.dg/test-reading-struct.c (create_code): Likewise.
* jit.dg/test-types.c (create_code): Likewise.
* jit.dg/test-linked-list.c: New selftest, exercising
gcc_jit_context_new_opaque_struct, gcc_jit_type_get_pointer, and
gcc_jit_context_null.
* jit.dg/test-combination.c: Add test-linked-list.c
---
gcc/jit/ChangeLog.jit | 82 ++++++++++++
gcc/jit/TODO.rst | 24 +---
gcc/jit/internal-api.c | 120 +++++++++++------
gcc/jit/internal-api.h | 61 +++++++--
gcc/jit/libgccjit++.h | 55 ++++++--
gcc/jit/libgccjit.c | 143 +++++++++++++++++++--
gcc/jit/libgccjit.h | 27 +++-
gcc/jit/libgccjit.map | 4 +
gcc/testsuite/ChangeLog.jit | 20 +++
gcc/testsuite/jit.dg/test-accessing-struct.c | 5 +-
gcc/testsuite/jit.dg/test-arrays.c | 4 +-
gcc/testsuite/jit.dg/test-combination.c | 9 ++
.../test-error-accessing-field-in-other-struct.c | 7 +-
.../test-error-dereference-field-of-non-pointer.c | 6 +-
gcc/testsuite/jit.dg/test-fuzzer.c | 4 +-
gcc/testsuite/jit.dg/test-linked-list.c | 133 +++++++++++++++++++
gcc/testsuite/jit.dg/test-nested-contexts.c | 5 +-
gcc/testsuite/jit.dg/test-quadratic.c | 5 +-
gcc/testsuite/jit.dg/test-reading-struct.c | 3 +-
gcc/testsuite/jit.dg/test-types.c | 13 +-
20 files changed, 617 insertions(+), 113 deletions(-)
create mode 100644 gcc/testsuite/jit.dg/test-linked-list.c
diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index b0e12b1..860bee6 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,5 +1,87 @@
2014-02-18 David Malcolm <dmalcolm@redhat.com>
+ * libgccjit.h (gcc_jit_struct): New.
+ (gcc_jit_context_new_struct_type): Change return type from gcc_jit_type
+ to gcc_jit_struct.
+ (gcc_jit_context_new_opaque_struct): New.
+ (gcc_jit_struct_as_type): New.
+ (gcc_jit_struct_set_fields): New.
+ (gcc_jit_context_null): New.
+
+ * libgccjit.map (gcc_jit_context_new_opaque_struct): New.
+ (gcc_jit_context_null): New.
+ (gcc_jit_struct_as_type): New.
+ (gcc_jit_struct_set_fields): New.
+
+ * libgccjit++.h (gccjit::context::new_struct_type): Return a
+ struct_ rather than a type.
+ (gccjit::context::new_opaque_struct_type): New.
+ (gccjit::struct_): New subclass of type.
+
+ * libgccjit.c (gcc_jit_struct): New.
+ (RETURN_VAL_IF_FAIL_PRINTF1): New.
+ (RETURN_VAL_IF_FAIL_PRINTF2): New.
+ (RETURN_NULL_IF_FAIL_PRINTF1): New.
+ (RETURN_IF_FAIL_PRINTF1): New.
+ (RETURN_IF_FAIL_PRINTF2): New.
+ (gcc_jit_context_new_struct_type): Return a gcc_jit_struct rather
+ than a gcc_jit_type; implement by creating the struct, then
+ setting the fields in it.
+ (gcc_jit_context_new_opaque_struct): New.
+ (gcc_jit_struct_as_type): New.
+ (gcc_jit_struct_set_fields): New.
+ (gcc_jit_context_null): New.
+ (gcc_jit_lvalue_access_field): Use the struct's context when
+ reporting on a NULL field; verify that the field has been placed
+ in a struct.
+ (gcc_jit_rvalue_access_field): Likewise.
+ (is_bool): New.
+ (gcc_jit_function_add_conditional): Use the function's context
+ when reporting errors; verify that boolval's type is indeed
+ boolean.
+ (gcc_jit_function_new_loop): Likewise.
+
+ * internal-api.h (gcc::jit::recording::context::new_struct_type):
+ Don't accept fields, and return a struct_ rather than a type_, so
+ that fields can be set later.
+ (gcc::jit::recording::struct_::struct_): Store a (fields *) rather
+ than a vec of fields.
+ (gcc::jit::recording::struct_::as_type): New.
+ (gcc::jit::recording::struct_::get_fields): New.
+ (gcc::jit::recording::struct_::set_fields): New.
+ (gcc::jit::recording::struct_::playback_struct): New.
+ (gcc::jit::recording::fields): New class.
+ (gcc::jit::playback::context::new_struct_type): Don't accept
+ fields, and return a struct_ rather than a type_, so that fields
+ can be set later.
+ (gcc::jit::playback::struct_): New subclass of type.
+
+ * internal-api.c (gcc::jit::recording::context::get_type): With
+ nested contexts, create basic types within the ultimate parent
+ context, allowing for a fast check for the boolean type using
+ pointer equality.
+ (gcc::jit::recording::context::new_struct_type): Don't accept
+ fields, and return a struct_ rather than a type_, so that fields
+ can be set later.
+ (gcc::jit::recording::context::get_opaque_FILE_type): Update for
+ struct-creation changes.
+ (gcc::jit::recording::struct_::struct_): Store a (fields *) rather
+ than a vec of fields.
+ (gcc::jit::recording::struct_::set_fields): New.
+ (gcc::jit::recording::struct_::replay_into): Don't playback the
+ fields, as this is now done by a fields instance.
+ (gcc::jit::recording::fields::fields): New.
+ (gcc::jit::recording::fields::replay_into): New.
+ (gcc::jit::recording::fields::make_debug_string): New.
+ (gcc::jit:: playback::context::new_struct_type): Don't accept
+ fields, and return a struct_ rather than a type_, so that fields
+ can be set later.
+ (gcc::jit::playback::struct_::set_fields): New.
+
+ * TODO.rst: Update.
+
+2014-02-18 David Malcolm <dmalcolm@redhat.com>
+
* libgccjit.c (gcc_jit_function_new_local): Use the context of the
function when reporting errors.
(gcc_jit_function_place_forward_label): Likewise.
diff --git a/gcc/jit/TODO.rst b/gcc/jit/TODO.rst
index c149dde..7288aef 100644
--- a/gcc/jit/TODO.rst
+++ b/gcc/jit/TODO.rst
@@ -18,23 +18,6 @@ Initial Release
* more types:
* unions
* function ptrs
- * explicitly opaque structs, perhaps:
-
- extern gcc_jit_type *
- gcc_jit_context_new_opaque_struct (gcc_jit_context *ctxt,
- const char *name);
-
- * ability to create self-referential structs, or cycles in the graph:
-
- struct foo { struct bar *m_bar; }
- struct bar { struct foo *m_foo; }
-
- * get int type with given number of either bits or bytes:
-
- extern gcc_jit_type *
- gcc_jit_context_get_int_type (gcc_jit_context *ctxt,
- int num_bytes,
- int is_signed);
* ability to bind a pre-existing global variable
@@ -109,13 +92,12 @@ Initial Release
* gcc_jit_context_new_rvalue_from_int: must be a numeric type
- * gcc_jit_context_zero: must be a numeric type. If we do this should
- we introduce a gcc_jit_context_null for pointer types? (you can do
- this via gcc_jit_context_new_rvalue_from_ptr, but having an explicit
- hook is friendlier).
+ * gcc_jit_context_zero: must be a numeric type
* gcc_jit_context_one: must be a numeric type
+ * gcc_jit_context_null: must be a pointer type
+
* gcc_jit_context_new_rvalue_from_double: must be a numeric type
* gcc_jit_context_new_rvalue_from_ptr: must be a pointer type
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index dacb55d..37fe70b 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -211,9 +211,15 @@ recording::context::get_type (enum gcc_jit_types kind)
give the same object. */
if (!m_basic_types[kind])
{
- recording::type *result = new memento_of_get_type (this, kind);
- record (result);
- m_basic_types[kind] = result;
+ /* For basic types, use them from the parent ctxt. */
+ if (m_parent_ctxt)
+ m_basic_types[kind] = m_parent_ctxt->get_type (kind);
+ else
+ {
+ recording::type *result = new memento_of_get_type (this, kind);
+ record (result);
+ m_basic_types[kind] = result;
+ }
}
return m_basic_types[kind];
@@ -278,18 +284,11 @@ recording::context::new_field (recording::location *loc,
return result;
}
-recording::type *
+recording::struct_ *
recording::context::new_struct_type (recording::location *loc,
- const char *name,
- int num_fields,
- field **fields)
+ const char *name)
{
- vec<field *> vec_fields;
- vec_fields.create (num_fields);
- for (int i = 0; i < num_fields; i++)
- vec_fields.safe_push (fields[i]);
- recording::type *result = new struct_ (this, loc, new_string (name),
- vec_fields);
+ recording::struct_ *result = new struct_ (this, loc, new_string (name));
record (result);
return result;
}
@@ -545,7 +544,7 @@ recording::type *
recording::context::get_opaque_FILE_type ()
{
if (!m_FILE_type)
- m_FILE_type = new_struct_type (NULL, "FILE", 0, NULL);
+ m_FILE_type = new_struct_type (NULL, "FILE");
return m_FILE_type;
}
@@ -918,19 +917,24 @@ recording::field::make_debug_string ()
/* gcc::jit::recording::struct_:: */
recording::struct_::struct_ (context *ctxt,
location *loc,
- string *name,
- vec<field *> fields)
+ string *name)
: type (ctxt),
m_loc (loc),
m_name (name),
- m_fields (fields)
+ m_fields (NULL)
{
- /* Mark all fields as belonging to the new struct: */
- for (unsigned i = 0; i < fields.length (); i++)
- {
- gcc_assert (m_fields[i]->get_container () == NULL);
- m_fields[i]->set_container (this);
- }
+}
+
+void
+recording::struct_::set_fields (location *loc,
+ int num_fields,
+ field **field_array)
+{
+ m_loc = loc;
+ gcc_assert (NULL == m_fields);
+
+ m_fields = new fields (this, num_fields, field_array);
+ m_ctxt->record (m_fields);
}
recording::type *
@@ -942,15 +946,9 @@ recording::struct_::dereference ()
void
recording::struct_::replay_into (replayer *r)
{
- vec<playback::field *> playback_fields;
- playback_fields.create (m_fields.length ());
- for (unsigned i = 0; i < m_fields.length (); i++)
- playback_fields.safe_push (m_fields[i]->playback_field ());
-
set_playback_obj (
r->new_struct_type (playback_location (m_loc),
- m_name->c_str (),
- &playback_fields));
+ m_name->c_str ()));
}
recording::string *
@@ -960,6 +958,39 @@ recording::struct_::make_debug_string ()
"struct %s", m_name->c_str ());
}
+/* gcc::jit::recording::fields:: */
+recording::fields::fields (struct_ *struct_,
+ int num_fields,
+ field **fields)
+: memento (struct_->m_ctxt),
+ m_struct (struct_),
+ m_fields ()
+{
+ for (int i = 0; i < num_fields; i++)
+ {
+ gcc_assert (fields[i]->get_container () == NULL);
+ fields[i]->set_container (m_struct);
+ m_fields.safe_push (fields[i]);
+ }
+}
+
+void
+recording::fields::replay_into (replayer *)
+{
+ vec<playback::field *> playback_fields;
+ 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);
+}
+
+recording::string *
+recording::fields::make_debug_string ()
+{
+ return string::from_printf (m_ctxt,
+ "fields");
+}
+
/* gcc::jit::recording::rvalue:: */
recording::rvalue *
@@ -1937,25 +1968,35 @@ new_field (location *loc,
return new field (decl);
}
-playback::type *
+playback::struct_ *
playback::context::
new_struct_type (location *loc,
- const char *name,
- vec<field *> *fields)
+ const char *name)
{
gcc_assert (name);
- gcc_assert (fields);
- /* Compare with c/c-decl.c: start_struct and finish_struct. */
+ /* Compare with c/c-decl.c: start_struct. */
tree t = make_node (RECORD_TYPE);
TYPE_NAME (t) = get_identifier (name);
TYPE_SIZE (t) = 0;
+ if (loc)
+ set_tree_location (t, loc);
+
+ return new struct_ (t);
+}
+
+void
+playback::struct_::set_fields (const vec<playback::field *> &fields)
+{
+ /* Compare with c/c-decl.c: finish_struct. */
+ tree t = as_tree ();
+
tree fieldlist = NULL;
- for (unsigned i = 0; i < fields->length (); i++)
+ for (unsigned i = 0; i < fields.length (); i++)
{
- field *f = (*fields)[i];
+ field *f = fields[i];
DECL_CONTEXT (f->as_tree ()) = t;
fieldlist = chainon (f->as_tree (), fieldlist);
}
@@ -1963,11 +2004,6 @@ new_struct_type (location *loc,
TYPE_FIELDS (t) = fieldlist;
layout_type (t);
-
- if (loc)
- set_tree_location (t, loc);
-
- return new type (t);
}
playback::type *
diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h
index 45ab9ea..1be192e 100644
--- a/gcc/jit/internal-api.h
+++ b/gcc/jit/internal-api.h
@@ -85,6 +85,7 @@ namespace recording {
class function_type;
class field;
class struct_;
+ class fields;
class function;
class label;
class rvalue;
@@ -98,6 +99,7 @@ namespace playback {
class location;
class type;
class field;
+ class struct_;
class function;
class label;
class rvalue;
@@ -160,12 +162,9 @@ public:
type *type,
const char *name);
- type *
+ struct_ *
new_struct_type (location *loc,
- const char *name,
- int num_fields,
- field **fields);
-
+ const char *name);
param *
new_param (location *loc,
@@ -619,19 +618,52 @@ class struct_ : public type
public:
struct_ (context *ctxt,
location *loc,
- string *name,
- vec<field *> fields);
+ string *name);
+
+ type *
+ as_type () { return this; }
+
+ fields * get_fields () { return m_fields; }
+
+ void
+ set_fields (location *loc,
+ int num_fields,
+ field **fields);
type *dereference ();
void replay_into (replayer *r);
+ playback::struct_ *
+ playback_struct ()
+ {
+ return static_cast <playback::struct_ *> (m_playback_obj);
+ }
+
private:
string * make_debug_string ();
private:
location *m_loc;
string *m_name;
+ fields *m_fields;
+};
+
+// memento of struct_::set_fields
+class fields : public memento
+{
+public:
+ fields (struct_ *struct_,
+ int num_fields,
+ field **fields);
+
+ void replay_into (replayer *r);
+
+private:
+ string * make_debug_string ();
+
+private:
+ struct_ *m_struct;
vec<field *> m_fields;
};
@@ -1481,10 +1513,9 @@ public:
type *type,
const char *name);
- type *
+ struct_ *
new_struct_type (location *loc,
- const char *name,
- vec<field *> *fields);
+ const char *name);
type *
new_function_type (type *return_type,
@@ -1682,6 +1713,16 @@ private:
tree m_inner;
};
+class struct_ : public type
+{
+public:
+ struct_ (tree inner)
+ : type (inner)
+ {}
+
+ void set_fields (const vec<field *> &fields);
+};
+
class field : public wrapper
{
public:
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index a718d0c..63f8610 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -19,6 +19,7 @@ namespace gccjit
class location;
class field;
class type;
+ class struct_;
class param;
class function;
class label;
@@ -97,9 +98,12 @@ namespace gccjit
field new_field (type type_, const std::string &name,
location loc = location ());
- type new_struct_type (const std::string &name,
- std::vector<field> &fields,
- location loc = location ());
+ struct_ new_struct_type (const std::string &name,
+ std::vector<field> &fields,
+ location loc = location ());
+
+ struct_ new_opaque_struct_type (const std::string &name,
+ location loc = location ());
param new_param (type type_,
const std::string &name,
@@ -264,6 +268,15 @@ namespace gccjit
rvalue one ();
};
+ class struct_ : public type
+ {
+ public:
+ struct_ ();
+ struct_ (gcc_jit_struct *inner);
+
+ gcc_jit_struct *get_inner_struct () const;
+ };
+
class function : public object
{
public:
@@ -525,7 +538,7 @@ context::new_field (type type_, const std::string &name, location loc)
name.c_str ()));
}
-inline type
+inline struct_
context::new_struct_type (const std::string &name,
std::vector<field> &fields,
location loc)
@@ -538,11 +551,21 @@ context::new_struct_type (const std::string &name,
gcc_jit_field **as_array_of_ptrs =
reinterpret_cast<gcc_jit_field **> (as_array_of_wrappers);
- return type (gcc_jit_context_new_struct_type (m_inner_ctxt,
- loc.get_inner_location (),
- name.c_str (),
- fields.size (),
- as_array_of_ptrs));
+ return struct_ (gcc_jit_context_new_struct_type (m_inner_ctxt,
+ loc.get_inner_location (),
+ name.c_str (),
+ fields.size (),
+ as_array_of_ptrs));
+}
+
+inline struct_
+context::new_opaque_struct_type (const std::string &name,
+ location loc)
+{
+ return struct_ (gcc_jit_context_new_opaque_struct (
+ m_inner_ctxt,
+ loc.get_inner_location (),
+ name.c_str ()));
}
inline param
@@ -1020,6 +1043,20 @@ type::one ()
return get_context ().new_rvalue (*this, 1);
}
+// class struct_
+inline struct_::struct_ () : type (NULL) {}
+inline struct_::struct_ (gcc_jit_struct *inner) :
+ type (gcc_jit_struct_as_type (inner))
+{
+}
+
+inline gcc_jit_struct *
+struct_::get_inner_struct () const
+{
+ /* Manual downcast: */
+ return reinterpret_cast<gcc_jit_struct *> (get_inner_object ());
+}
+
// class function
inline function::function () : object (NULL) {}
inline function::function (gcc_jit_function *inner)
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index b5b3968..d089ad5 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -44,6 +44,10 @@ struct gcc_jit_type : public gcc::jit::recording::type
{
};
+struct gcc_jit_struct : public gcc::jit::recording::struct_
+{
+};
+
struct gcc_jit_field : public gcc::jit::recording::field
{
};
@@ -93,6 +97,16 @@ struct gcc_jit_loop : public gcc::jit::recording::loop
} \
JIT_END_STMT
+#define RETURN_VAL_IF_FAIL_PRINTF1(TEST_EXPR, RETURN_EXPR, CTXT, ERR_FMT, A0) \
+ JIT_BEGIN_STMT \
+ if (!(TEST_EXPR)) \
+ { \
+ jit_error ((CTXT), "%s: " ERR_FMT, \
+ __func__, (A0)); \
+ return (RETURN_EXPR); \
+ } \
+ JIT_END_STMT
+
#define RETURN_VAL_IF_FAIL_PRINTF2(TEST_EXPR, RETURN_EXPR, CTXT, ERR_FMT, A0, A1) \
JIT_BEGIN_STMT \
if (!(TEST_EXPR)) \
@@ -136,6 +150,9 @@ struct gcc_jit_loop : public gcc::jit::recording::loop
#define RETURN_NULL_IF_FAIL(TEST_EXPR, CTXT, ERR_MSG) \
RETURN_VAL_IF_FAIL ((TEST_EXPR), NULL, (CTXT), (ERR_MSG))
+#define RETURN_NULL_IF_FAIL_PRINTF1(TEST_EXPR, CTXT, ERR_FMT, A0) \
+ RETURN_VAL_IF_FAIL_PRINTF1 (TEST_EXPR, NULL, CTXT, ERR_FMT, A0)
+
#define RETURN_NULL_IF_FAIL_PRINTF2(TEST_EXPR, CTXT, ERR_FMT, A0, A1) \
RETURN_VAL_IF_FAIL_PRINTF2 (TEST_EXPR, NULL, CTXT, ERR_FMT, A0, A1)
@@ -157,6 +174,26 @@ struct gcc_jit_loop : public gcc::jit::recording::loop
} \
JIT_END_STMT
+#define RETURN_IF_FAIL_PRINTF1(TEST_EXPR, CTXT, ERR_FMT, A0) \
+ JIT_BEGIN_STMT \
+ if (!(TEST_EXPR)) \
+ { \
+ jit_error ((CTXT), "%s: " ERR_FMT, \
+ __func__, (A0)); \
+ return; \
+ } \
+ JIT_END_STMT
+
+#define RETURN_IF_FAIL_PRINTF2(TEST_EXPR, CTXT, ERR_FMT, A0, A1) \
+ JIT_BEGIN_STMT \
+ if (!(TEST_EXPR)) \
+ { \
+ jit_error ((CTXT), "%s: " ERR_FMT, \
+ __func__, (A0), (A1)); \
+ return; \
+ } \
+ JIT_END_STMT
+
#define RETURN_IF_FAIL_PRINTF4(TEST_EXPR, CTXT, ERR_FMT, A0, A1, A2, A3) \
JIT_BEGIN_STMT \
if (!(TEST_EXPR)) \
@@ -330,7 +367,7 @@ gcc_jit_field_as_object (gcc_jit_field *field)
return static_cast <gcc_jit_object *> (field->as_object ());
}
-gcc_jit_type *
+gcc_jit_struct *
gcc_jit_context_new_struct_type (gcc_jit_context *ctxt,
gcc_jit_location *loc,
const char *name,
@@ -352,10 +389,61 @@ gcc_jit_context_new_struct_type (gcc_jit_context *ctxt,
fields[i]->get_container ()->get_debug_string ());
}
- return (gcc_jit_type *)ctxt->new_struct_type (loc, name, num_fields,
- (gcc::jit::recording::field **)fields);
+ gcc::jit::recording::struct_ *result =
+ ctxt->new_struct_type (loc, name);
+ result->set_fields (loc,
+ num_fields,
+ (gcc::jit::recording::field **)fields);
+ return static_cast<gcc_jit_struct *> (result);
+}
+
+gcc_jit_struct *
+gcc_jit_context_new_opaque_struct (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ const char *name)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, "NULL context");
+ RETURN_NULL_IF_FAIL (name, ctxt, "NULL name");
+
+ return (gcc_jit_struct *)ctxt->new_struct_type (loc, name);
}
+gcc_jit_type *
+gcc_jit_struct_as_type (gcc_jit_struct *struct_type)
+{
+ RETURN_NULL_IF_FAIL (struct_type, NULL, "NULL struct_type");
+
+ return static_cast <gcc_jit_type *> (struct_type->as_type ());
+}
+
+void
+gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
+ gcc_jit_location *loc,
+ int num_fields,
+ gcc_jit_field **fields)
+{
+ RETURN_IF_FAIL (struct_type, NULL, "NULL struct_type");
+ gcc::jit::recording::context *ctxt = struct_type->m_ctxt;
+ RETURN_IF_FAIL_PRINTF1 (
+ NULL == struct_type->get_fields (), ctxt,
+ "%s already has had fields set",
+ struct_type->get_debug_string ());
+ if (num_fields)
+ RETURN_IF_FAIL (fields, ctxt, "NULL fields ptr");
+ for (int i = 0; i < num_fields; i++)
+ {
+ RETURN_IF_FAIL (fields[i], ctxt, "NULL field ptr");
+ RETURN_IF_FAIL_PRINTF2 (
+ NULL == fields[i]->get_container (),
+ ctxt,
+ "%s is already a field of %s",
+ fields[i]->get_debug_string (),
+ fields[i]->get_container ()->get_debug_string ());
+ }
+
+ struct_type->set_fields (loc, num_fields,
+ (gcc::jit::recording::field **)fields);
+}
/* Constructing functions. */
gcc_jit_param *
@@ -597,6 +685,16 @@ gcc_jit_context_new_rvalue_from_ptr (gcc_jit_context *ctxt,
}
gcc_jit_rvalue *
+gcc_jit_context_null (gcc_jit_context *ctxt,
+ gcc_jit_type *pointer_type)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, "NULL context");
+ RETURN_NULL_IF_FAIL (pointer_type, ctxt, "NULL type");
+
+ return gcc_jit_context_new_rvalue_from_ptr (ctxt, pointer_type, NULL);
+}
+
+gcc_jit_rvalue *
gcc_jit_context_new_string_literal (gcc_jit_context *ctxt,
const char *value)
{
@@ -751,7 +849,11 @@ gcc_jit_lvalue_access_field (gcc_jit_lvalue *struct_,
gcc_jit_field *field)
{
RETURN_NULL_IF_FAIL (struct_, NULL, "NULL struct");
- RETURN_NULL_IF_FAIL (field, NULL, "NULL field");
+ gcc::jit::recording::context *ctxt = struct_->m_ctxt;
+ RETURN_NULL_IF_FAIL (field, ctxt, "NULL field");
+ RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt,
+ "field %s has not been placed in a struct",
+ field->get_debug_string ());
return (gcc_jit_lvalue *)struct_->access_field (loc, field);
}
@@ -762,7 +864,11 @@ gcc_jit_rvalue_access_field (gcc_jit_rvalue *struct_,
gcc_jit_field *field)
{
RETURN_NULL_IF_FAIL (struct_, NULL, "NULL struct");
- RETURN_NULL_IF_FAIL (field, NULL, "NULL field");
+ gcc::jit::recording::context *ctxt = struct_->m_ctxt;
+ RETURN_NULL_IF_FAIL (field, ctxt, "NULL field");
+ RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt,
+ "field %s has not been placed in a struct",
+ field->get_debug_string ());
return (gcc_jit_rvalue *)struct_->access_field (loc, field);
}
@@ -912,6 +1018,15 @@ gcc_jit_function_add_assignment_op (gcc_jit_function *func,
return func->add_assignment_op (loc, lvalue, op, rvalue);
}
+static bool
+is_bool (gcc_jit_rvalue *boolval)
+{
+ gcc::jit::recording::type *actual_type = boolval->get_type ();
+ gcc::jit::recording::type *bool_type =
+ boolval->m_ctxt->get_type (GCC_JIT_TYPE_BOOL);
+ return actual_type == bool_type;
+}
+
void
gcc_jit_function_add_conditional (gcc_jit_function *func,
gcc_jit_location *loc,
@@ -920,8 +1035,14 @@ gcc_jit_function_add_conditional (gcc_jit_function *func,
gcc_jit_label *on_false)
{
RETURN_IF_NOT_FUNC_DEFINITION (func);
- RETURN_IF_FAIL (boolval, NULL, "NULL boolval");
- RETURN_IF_FAIL (on_true, NULL, "NULL on_true");
+ gcc::jit::recording::context *ctxt = func->m_ctxt;
+ RETURN_IF_FAIL (boolval, ctxt, "NULL boolval");
+ RETURN_IF_FAIL_PRINTF2 (
+ is_bool (boolval), ctxt,
+ "%s (type: %s) is not of boolean type ",
+ boolval->get_debug_string (),
+ boolval->get_type ()->get_debug_string ());
+ RETURN_IF_FAIL (on_true, ctxt, "NULL on_true");
/* on_false can be NULL */
return func->add_conditional (loc, boolval, on_true, on_false);
@@ -980,7 +1101,13 @@ gcc_jit_function_new_loop (gcc_jit_function *func,
gcc_jit_rvalue *boolval)
{
RETURN_NULL_IF_NOT_FUNC_DEFINITION (func);
- RETURN_NULL_IF_FAIL (boolval, NULL, "NULL boolval");
+ gcc::jit::recording::context *ctxt = func->m_ctxt;
+ RETURN_NULL_IF_FAIL (boolval, ctxt, "NULL boolval");
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ is_bool (boolval), ctxt,
+ "%s (type: %s) is not of boolean type ",
+ boolval->get_debug_string (),
+ boolval->get_type ()->get_debug_string ());
return (gcc_jit_loop *)func->new_loop (loc, boolval, NULL, NULL);
}
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 3751bdd..3ea6653 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -36,6 +36,7 @@ typedef struct gcc_jit_result gcc_jit_result;
+- gcc_jit_object
+- gcc_jit_location
+- gcc_jit_type
+ +- gcc_jit_struct
+- gcc_jit_field
+- gcc_jit_function
+- gcc_jit_label
@@ -67,6 +68,10 @@ typedef struct gcc_jit_type gcc_jit_type;
Fields cannot be shared between structs. */
typedef struct gcc_jit_field gcc_jit_field;
+/* A gcc_jit_struct encapsulates a struct type, either one that we have
+ the layout for, or an opaque type. */
+typedef struct gcc_jit_struct gcc_jit_struct;
+
/* A gcc_jit_function encapsulates a function: either one that you're
creating yourself, or a reference to one that you're dynamically
linking to within the rest of the process. */
@@ -385,13 +390,29 @@ gcc_jit_context_new_field (gcc_jit_context *ctxt,
extern gcc_jit_object *
gcc_jit_field_as_object (gcc_jit_field *field);
-extern gcc_jit_type *
+extern gcc_jit_struct *
gcc_jit_context_new_struct_type (gcc_jit_context *ctxt,
gcc_jit_location *loc,
const char *name,
int num_fields,
gcc_jit_field **fields);
+extern gcc_jit_struct *
+gcc_jit_context_new_opaque_struct (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ const char *name);
+
+extern gcc_jit_type *
+gcc_jit_struct_as_type (gcc_jit_struct *struct_type);
+
+/* Populating the fields of a formerly-opaque struct type.
+ This can only be called once on a given struct type. */
+extern void
+gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
+ gcc_jit_location *loc,
+ int num_fields,
+ gcc_jit_field **fields);
+
/**********************************************************************
Constructing functions.
**********************************************************************/
@@ -511,6 +532,10 @@ gcc_jit_context_new_rvalue_from_ptr (gcc_jit_context *ctxt,
gcc_jit_type *pointer_type,
void *value);
+extern gcc_jit_rvalue *
+gcc_jit_context_null (gcc_jit_context *ctxt,
+ gcc_jit_type *pointer_type);
+
/* String literals. */
extern gcc_jit_rvalue *
gcc_jit_context_new_string_literal (gcc_jit_context *ctxt,
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 6dde3a1..fbdca38 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -18,6 +18,7 @@
gcc_jit_context_new_function;
gcc_jit_context_new_global;
gcc_jit_context_new_location;
+ gcc_jit_context_new_opaque_struct;
gcc_jit_context_new_param;
gcc_jit_context_new_rvalue_from_double;
gcc_jit_context_new_rvalue_from_int;
@@ -25,6 +26,7 @@
gcc_jit_context_new_string_literal;
gcc_jit_context_new_struct_type;
gcc_jit_context_new_unary_op;
+ gcc_jit_context_null;
gcc_jit_context_one;
gcc_jit_context_release;
gcc_jit_context_set_bool_option;
@@ -67,6 +69,8 @@
gcc_jit_rvalue_dereference;
gcc_jit_rvalue_dereference_field;
gcc_jit_rvalue_get_type;
+ gcc_jit_struct_as_type;
+ gcc_jit_struct_set_fields;
gcc_jit_type_as_object;
gcc_jit_type_get_const;
gcc_jit_type_get_pointer;
diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit
index ec1d76a..0299115 100644
--- a/gcc/testsuite/ChangeLog.jit
+++ b/gcc/testsuite/ChangeLog.jit
@@ -1,3 +1,23 @@
+2014-02-18 David Malcolm <dmalcolm@redhat.com>
+
+ * jit.dg/test-accessing-struct.c (create_code): Update for change to
+ return type of gcc_jit_context_new_struct_type.
+ * jit.dg/test-arrays.c (create_code): Likewise.
+ * jit.dg/test-error-accessing-field-in-other-struct.c (create_code):
+ Likewise.
+ * jit.dg/test-error-dereference-field-of-non-pointer.c (create_code):
+ Likewise.
+ * jit.dg/test-fuzzer.c (make_random_type): Likewise.
+ * jit.dg/test-nested-contexts.c (make_types): Likewise.
+ * jit.dg/test-quadratic.c (make_types): Likewise.
+ * jit.dg/test-reading-struct.c (create_code): Likewise.
+ * jit.dg/test-types.c (create_code): Likewise.
+
+ * jit.dg/test-linked-list.c: New selftest, exercising
+ gcc_jit_context_new_opaque_struct, gcc_jit_type_get_pointer, and
+ gcc_jit_context_null.
+ * jit.dg/test-combination.c: Add test-linked-list.c
+
2014-02-14 David Malcolm <dmalcolm@redhat.com>
* jit.dg/test-operator-overloading.cc (make_test_quadratic): Use
diff --git a/gcc/testsuite/jit.dg/test-accessing-struct.c b/gcc/testsuite/jit.dg/test-accessing-struct.c
index b28adeb..eb4ecca 100644
--- a/gcc/testsuite/jit.dg/test-accessing-struct.c
+++ b/gcc/testsuite/jit.dg/test-accessing-struct.c
@@ -42,9 +42,10 @@ create_code (gcc_jit_context *ctxt, void *user_data)
int_type,
"z");
gcc_jit_field *fields[] = {x, y, z};
- gcc_jit_type *struct_type =
+ gcc_jit_struct *struct_type =
gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 3, fields);
- gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (struct_type);
+ gcc_jit_type *ptr_type =
+ gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_type));
/* Build the test function. */
gcc_jit_param *param_f =
diff --git a/gcc/testsuite/jit.dg/test-arrays.c b/gcc/testsuite/jit.dg/test-arrays.c
index 2cff561..12ea77e 100644
--- a/gcc/testsuite/jit.dg/test-arrays.c
+++ b/gcc/testsuite/jit.dg/test-arrays.c
@@ -53,7 +53,7 @@ create_code (gcc_jit_context *ctxt, void *user_data)
field_m_after,
};
- gcc_jit_type *struct_type =
+ gcc_jit_struct *struct_type =
gcc_jit_context_new_struct_type (
ctxt,
NULL,
@@ -61,7 +61,7 @@ create_code (gcc_jit_context *ctxt, void *user_data)
3, fields);
gcc_jit_type *struct_ptr_type =
- gcc_jit_type_get_pointer (struct_type);
+ gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_type));
/* Build the test_fn. */
gcc_jit_param *param_ah =
diff --git a/gcc/testsuite/jit.dg/test-combination.c b/gcc/testsuite/jit.dg/test-combination.c
index 7fc07ab..cd8a0f3 100644
--- a/gcc/testsuite/jit.dg/test-combination.c
+++ b/gcc/testsuite/jit.dg/test-combination.c
@@ -66,6 +66,13 @@
#undef create_code
#undef verify_code
+/* test-linked-list.c */
+#define create_code create_code_linked_list
+#define verify_code verify_code_linked_list
+#include "test-linked-list.c"
+#undef create_code
+#undef verify_code
+
/* test-quadratic.c */
#define create_code create_code_quadratic
#define verify_code verify_code_quadratic
@@ -127,6 +134,7 @@ create_code (gcc_jit_context *ctxt, void * user_data)
create_code_fibonacci (ctxt, user_data);
create_code_functions (ctxt, user_data);
create_code_hello_world (ctxt, user_data);
+ create_code_linked_list (ctxt, user_data);
create_code_string_literal (ctxt, user_data);
create_code_sum_of_squares (ctxt, user_data);
create_code_types (ctxt, user_data);
@@ -144,6 +152,7 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
verify_code_fibonacci (ctxt, result);
verify_code_functions (ctxt, result);
verify_code_hello_world (ctxt, result);
+ verify_code_linked_list (ctxt, result);
verify_code_string_literal (ctxt, result);
verify_code_sum_of_squares (ctxt, result);
verify_code_types (ctxt, result);
diff --git a/gcc/testsuite/jit.dg/test-error-accessing-field-in-other-struct.c b/gcc/testsuite/jit.dg/test-error-accessing-field-in-other-struct.c
index 6789195..1cc2cb6 100644
--- a/gcc/testsuite/jit.dg/test-error-accessing-field-in-other-struct.c
+++ b/gcc/testsuite/jit.dg/test-error-accessing-field-in-other-struct.c
@@ -45,7 +45,7 @@ create_code (gcc_jit_context *ctxt, void *user_data)
int_type,
"y");
gcc_jit_field *foo_fields[] = {x, y};
- gcc_jit_type *struct_foo =
+ gcc_jit_struct *struct_foo =
gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, foo_fields);
/* Map "struct bar". */
@@ -62,11 +62,12 @@ create_code (gcc_jit_context *ctxt, void *user_data)
/* We don't actually need a gcc_jit_type for "struct bar" for the test. */
#if 0
gcc_jit_field *bar_fields[] = {p, q};
- gcc_jit_type *struct_bar =
+ gcc_jit_struct *struct_bar =
gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, bar_fields);
#endif
- gcc_jit_type *foo_ptr = gcc_jit_type_get_pointer (struct_foo);
+ gcc_jit_type *foo_ptr =
+ gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_foo));
/* Build the test function. */
gcc_jit_param *param_f =
diff --git a/gcc/testsuite/jit.dg/test-error-dereference-field-of-non-pointer.c b/gcc/testsuite/jit.dg/test-error-dereference-field-of-non-pointer.c
index e69ca8d..287498d 100644
--- a/gcc/testsuite/jit.dg/test-error-dereference-field-of-non-pointer.c
+++ b/gcc/testsuite/jit.dg/test-error-dereference-field-of-non-pointer.c
@@ -40,7 +40,7 @@ create_code (gcc_jit_context *ctxt, void *user_data)
int_type,
"y");
gcc_jit_field *foo_fields[] = {x, y};
- gcc_jit_type *struct_foo =
+ gcc_jit_struct *struct_foo =
gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, foo_fields);
/* Build the test function. */
@@ -52,7 +52,9 @@ create_code (gcc_jit_context *ctxt, void *user_data)
0, NULL,
0);
gcc_jit_lvalue *tmp =
- gcc_jit_function_new_local (test_fn, NULL, struct_foo, "tmp");
+ gcc_jit_function_new_local (test_fn, NULL,
+ gcc_jit_struct_as_type (struct_foo),
+ "tmp");
/* Erroneous: tmp->x = ... */
gcc_jit_lvalue *lvalue =
diff --git a/gcc/testsuite/jit.dg/test-fuzzer.c b/gcc/testsuite/jit.dg/test-fuzzer.c
index 7fbb5a2..11c1db5 100644
--- a/gcc/testsuite/jit.dg/test-fuzzer.c
+++ b/gcc/testsuite/jit.dg/test-fuzzer.c
@@ -212,14 +212,14 @@ make_random_type (fuzzer *f)
}
char struct_name[256];
sprintf (struct_name, "s%i", f->num_types);
- gcc_jit_type *struct_ = \
+ gcc_jit_struct *struct_ = \
gcc_jit_context_new_struct_type (f->ctxt,
get_random_location (f),
struct_name,
num_fields,
fields);
free (fields);
- return struct_;
+ return gcc_jit_struct_as_type (struct_);
}
}
}
diff --git a/gcc/testsuite/jit.dg/test-linked-list.c b/gcc/testsuite/jit.dg/test-linked-list.c
new file mode 100644
index 0000000..b925b9e
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-linked-list.c
@@ -0,0 +1,133 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+/* A doubly-linked list, to ensure that the JIT API can cope with
+ self-referential types. */
+struct node
+{
+ struct node *prev;
+ struct node *next;
+ int value;
+};
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ int
+ test_linked_list (struct node *n)
+ {
+ int total = 0;
+ while (n)
+ {
+ total += n->value;
+ n = n->next;
+ }
+ return total;
+ }
+ */
+ gcc_jit_type *t_int =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_struct *t_node =
+ gcc_jit_context_new_opaque_struct (ctxt, NULL, "node");
+ gcc_jit_type *t_node_ptr =
+ gcc_jit_type_get_pointer (gcc_jit_struct_as_type (t_node));
+
+ gcc_jit_field *f_prev =
+ gcc_jit_context_new_field (ctxt, NULL, t_node_ptr, "prev");
+ gcc_jit_field *f_next =
+ gcc_jit_context_new_field (ctxt, NULL, t_node_ptr, "next");
+ gcc_jit_field *f_value =
+ gcc_jit_context_new_field (ctxt, NULL, t_int, "value");
+ gcc_jit_field *fields[] = {f_prev, f_next, f_value};
+ gcc_jit_struct_set_fields (t_node, NULL, 3, fields);
+
+ /* Build the test function. */
+ gcc_jit_param *param_n =
+ gcc_jit_context_new_param (ctxt, NULL, t_node_ptr, "n");
+ gcc_jit_function *fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ t_int,
+ "test_linked_list",
+ 1, ¶m_n,
+ 0);
+ /* int total; */
+ gcc_jit_lvalue *total =
+ gcc_jit_function_new_local (fn, NULL, t_int, "total");
+
+ /* total = 0; */
+ gcc_jit_function_add_assignment (
+ fn, NULL,
+ total,
+ gcc_jit_context_zero (ctxt, t_int));
+
+ /* while (n) */
+ gcc_jit_loop *loop =
+ gcc_jit_function_new_loop (
+ fn, NULL,
+ gcc_jit_context_new_comparison (ctxt, NULL,
+ GCC_JIT_COMPARISON_NE,
+ gcc_jit_param_as_rvalue (param_n),
+ gcc_jit_context_null (ctxt, t_node_ptr)));
+
+ /* total += n->value; */
+ gcc_jit_function_add_assignment_op (
+ fn, NULL,
+ total,
+ GCC_JIT_BINARY_OP_PLUS,
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_rvalue_dereference_field (
+ gcc_jit_param_as_rvalue (param_n),
+ NULL,
+ f_value)));
+
+ /* n = n->next; */
+ gcc_jit_function_add_assignment (
+ fn, NULL,
+ gcc_jit_param_as_lvalue (param_n),
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_rvalue_dereference_field (
+ gcc_jit_param_as_rvalue (param_n),
+ NULL,
+ f_next)));
+
+ gcc_jit_loop_end (loop, NULL);
+
+ /* return total; */
+ gcc_jit_function_add_return (fn, NULL, gcc_jit_lvalue_as_rvalue (total));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ struct node a, b, c;
+ typedef int (*fn_type) (struct node *n);
+ CHECK_NON_NULL (result);
+
+ fn_type test_linked_list =
+ (fn_type)gcc_jit_result_get_code (result, "test_linked_list");
+ CHECK_NON_NULL (test_linked_list);
+
+ /* Construct a simple linked-list on the stack: a->b->c: */
+ a.prev = NULL;
+ a.next = &b;
+ a.value = 5;
+
+ b.prev = &a;
+ b.next = &c;
+ b.value = 3;
+
+ c.prev = &b;
+ c.next = NULL;
+ c.value = 7;
+
+ CHECK_VALUE (test_linked_list (NULL), 0);
+ CHECK_VALUE (test_linked_list (&a), 15);
+ CHECK_VALUE (test_linked_list (&b), 10);
+ CHECK_VALUE (test_linked_list (&c), 7);
+}
diff --git a/gcc/testsuite/jit.dg/test-nested-contexts.c b/gcc/testsuite/jit.dg/test-nested-contexts.c
index eaedd75..d24a859 100644
--- a/gcc/testsuite/jit.dg/test-nested-contexts.c
+++ b/gcc/testsuite/jit.dg/test-nested-contexts.c
@@ -136,8 +136,9 @@ make_types (struct top_level *top_level)
top_level->c,
top_level->discriminant};
top_level->struct_quadratic =
- gcc_jit_context_new_struct_type (top_level->ctxt, NULL,
- "quadratic", 4, fields);
+ gcc_jit_struct_as_type (
+ gcc_jit_context_new_struct_type (top_level->ctxt, NULL,
+ "quadratic", 4, fields));
top_level->quadratic_ptr =
gcc_jit_type_get_pointer (top_level->struct_quadratic);
}
diff --git a/gcc/testsuite/jit.dg/test-quadratic.c b/gcc/testsuite/jit.dg/test-quadratic.c
index 9b02c06..337bea5 100644
--- a/gcc/testsuite/jit.dg/test-quadratic.c
+++ b/gcc/testsuite/jit.dg/test-quadratic.c
@@ -115,8 +115,9 @@ make_types (struct quadratic_test *testcase)
testcase->c,
testcase->discriminant};
testcase->quadratic =
- gcc_jit_context_new_struct_type (testcase->ctxt, NULL,
- "quadratic", 4, fields);
+ gcc_jit_struct_as_type (
+ gcc_jit_context_new_struct_type (testcase->ctxt, NULL,
+ "quadratic", 4, fields));
testcase->quadratic_ptr = gcc_jit_type_get_pointer (testcase->quadratic);
}
diff --git a/gcc/testsuite/jit.dg/test-reading-struct.c b/gcc/testsuite/jit.dg/test-reading-struct.c
index fd53f84..4214320 100644
--- a/gcc/testsuite/jit.dg/test-reading-struct.c
+++ b/gcc/testsuite/jit.dg/test-reading-struct.c
@@ -45,7 +45,8 @@ create_code (gcc_jit_context *ctxt, void *user_data)
"y");
gcc_jit_field *fields[] = {x, y};
gcc_jit_type *struct_type =
- gcc_jit_context_new_struct_type (ctxt, NULL, "bar", 2, fields);
+ gcc_jit_struct_as_type (
+ gcc_jit_context_new_struct_type (ctxt, NULL, "bar", 2, fields));
gcc_jit_type *const_struct_type = gcc_jit_type_get_const (struct_type);
gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (const_struct_type);
diff --git a/gcc/testsuite/jit.dg/test-types.c b/gcc/testsuite/jit.dg/test-types.c
index f6fc1b2..575176f 100644
--- a/gcc/testsuite/jit.dg/test-types.c
+++ b/gcc/testsuite/jit.dg/test-types.c
@@ -161,12 +161,13 @@ create_code (gcc_jit_context *ctxt, void *user_data)
};
gcc_jit_type *zoo_type =
- gcc_jit_context_new_struct_type (
- ctxt,
- NULL,
- "zoo",
- sizeof (zoo_fields) / sizeof (zoo_fields[0]),
- zoo_fields);
+ gcc_jit_struct_as_type (
+ gcc_jit_context_new_struct_type (
+ ctxt,
+ NULL,
+ "zoo",
+ sizeof (zoo_fields) / sizeof (zoo_fields[0]),
+ zoo_fields));
gcc_jit_type *zoo_ptr_type =
gcc_jit_type_get_pointer (zoo_type);
--
1.7.11.7