@@ -1,3 +1,302 @@
+2014-02-27 David Malcolm <dmalcolm@redhat.com>
+
+ * libgccjit.h (gcc_jit_label): Delete in favor of...
+ (gcc_jit_block): New type.
+ (gcc_jit_loop): Delete.
+
+ (gcc_jit_function_new_forward_label): Delete in favor of...
+ (gcc_jit_function_new_block): New.
+
+ (gcc_jit_label_as_object): Delete in favor of...
+ (gcc_jit_block_as_object): New.
+
+ (gcc_jit_function_add_eval): Delete in favor of...
+ (gcc_jit_block_add_eval): New.
+
+ (gcc_jit_function_add_assignment): Delete in favor of...
+ (gcc_jit_block_add_assignment): New.
+
+ (gcc_jit_function_add_assignment_op): Delete in favor of...
+ (gcc_jit_block_add_assignment_op): New.
+
+ (gcc_jit_function_add_comment): Delete in favor of...
+ (gcc_jit_block_add_comment): New.
+
+ (gcc_jit_label_as_object): Delete in favor of...
+ (gcc_jit_block_as_object): New.
+
+ (gcc_jit_function_add_conditional): Delete in favor of...
+ (gcc_jit_block_end_with_conditional): New.
+
+ (gcc_jit_function_add_jump): Delete in favor of...
+ (gcc_jit_block_end_with_jump): New.
+
+ (gcc_jit_function_add_return): Delete in favor of...
+ (gcc_jit_block_end_with_return): New.
+
+ (gcc_jit_function_add_void_return): Delete in favor of...
+ (gcc_jit_block_end_with_void_return): New.
+
+ (gcc_jit_function_new_loop): Delete.
+ (gcc_jit_function_new_loop_over_range): Delete.
+ (gcc_jit_loop_as_object): Delete.
+ (gcc_jit_loop_end): Delete.
+
+ * libgccjit.map (gcc_jit_function_add_assignment): Delete in favor of...
+ (gcc_jit_block_add_assignment): New.
+
+ (gcc_jit_function_add_assignment_op): Delete in favor of...
+ (gcc_jit_block_add_assignment_op): New.
+
+ (gcc_jit_function_add_comment): Delete in favor of...
+ (gcc_jit_block_add_comment): New.
+
+ (gcc_jit_function_add_eval): Delete in favor of...
+ (gcc_jit_block_add_eval): New.
+
+ (gcc_jit_label_as_object): Delete in favor of...
+ (gcc_jit_block_as_object): New.
+
+ (gcc_jit_function_add_conditional): Delete in favor of...
+ (gcc_jit_block_end_with_conditional): New.
+
+ (gcc_jit_function_add_jump): Delete in favor of...
+ (gcc_jit_block_end_with_jump): New.
+
+ (gcc_jit_function_add_return): Delete in favor of...
+ (gcc_jit_block_end_with_return): New.
+
+ (gcc_jit_function_add_void_return): Delete in favor of...
+ (gcc_jit_block_end_with_void_return): New.
+
+ (gcc_jit_function_add_label): Delete in favor of...
+ (gcc_jit_function_new_block): New.
+ (gcc_jit_function_new_forward_label): Delete.
+ (gcc_jit_function_place_forward_label): Delete.
+
+ (gcc_jit_function_new_loop): Delete.
+ (gcc_jit_function_new_loop_over_range): Delete.
+ (gcc_jit_loop_as_object): Delete.
+ (gcc_jit_loop_end): Delete.
+
+ * libgccjit.c (gcc_jit_label): Delete in favor of...
+ (gcc_jit_block): New type.
+ (gcc_jit_loop): Delete.
+
+ (RETURN_IF_NOT_FUNC_DEFINITION): Delete in favor of...
+ (RETURN_IF_NOT_VALID_BLOCK): New macro.
+ (RETURN_NULL_IF_NOT_FUNC_DEFINITION): Delete in favor of...
+ (RETURN_NULL_IF_NOT_VALID_BLOCK): New macro.
+
+ (gcc_jit_function_new_forward_label): Delete in favor of...
+ (gcc_jit_function_new_block): New.
+
+ (gcc_jit_label_as_object): Delete in favor of...
+ (gcc_jit_block_as_object): New.
+
+ (gcc_jit_rvalue_dereference_field): Ensure that field has been
+ placed.
+
+ (gcc_jit_function_add_label): Delete
+ (gcc_jit_function_place_forward_label): Delete.
+
+ (gcc_jit_function_add_eval): Delete in favor of...
+ (gcc_jit_block_add_eval): New.
+
+ (gcc_jit_function_add_assignment): Delete in favor of...
+ (gcc_jit_block_add_assignment): New.
+
+ (gcc_jit_function_add_assignment_op): Delete in favor of...
+ (gcc_jit_block_add_assignment_op): New.
+
+ (gcc_jit_function_add_conditional): Delete in favor of...
+ (gcc_jit_block_end_with_conditional): New.
+
+ (gcc_jit_function_add_comment): Delete in favor of...
+ (gcc_jit_block_add_comment): New.
+
+ (gcc_jit_function_add_jump): Delete in favor of...
+ (gcc_jit_block_end_with_jump): New.
+
+ (gcc_jit_function_add_return): Delete in favor of...
+ (gcc_jit_block_end_with_return): New.
+
+ (gcc_jit_function_add_void_return): Delete in favor of...
+ (gcc_jit_block_end_with_void_return): New.
+
+ (gcc_jit_function_new_loop): Delete.
+ (gcc_jit_function_new_loop_over_range): Delete.
+ (gcc_jit_loop_as_object): Delete.
+ (gcc_jit_loop_end): Delete.
+
+ * internal-api.h (gcc::jit::recording::label): Delete class in
+ favor of...
+ (gcc::jit::recording::block): New class.
+ (gcc::jit::recording::loop): Delete class.
+ (gcc::jit::recording::loop_end): Delete class.
+
+ (gcc::jit::playback::label): Delete class in favor of...
+ (gcc::jit::playback::block): New class.
+
+ (gcc::jit::playback::loop): Delete class.
+
+ (gcc::jit::recording::playback_label): Delete function in favor of...
+ (gcc::jit::recording::playback_block): New function.
+
+ (gcc::jit::recording::context::validate): New.
+
+ (gcc::jit::recording::function::new_forward_label): Delete method.
+ (gcc::jit::recording::function::add_eval): Delete method in favor
+ of method of new gcc::jit::recording::block class.
+ (gcc::jit::recording::function::add_assignment): Likewise.
+ (gcc::jit::recording::function::add_assignment_op): Likewise.
+ (gcc::jit::recording::function::add_comment): Likewise.
+ (gcc::jit::recording::function::add_conditional): Likewise.
+ (gcc::jit::recording::function::place_forward_label): Likewise.
+ (gcc::jit::recording::function::add_jump): Likewise.
+ (gcc::jit::recording::function::add_return): Likewise.
+
+ (gcc::jit::recording::function::add_label): Delete method in favor of...
+ (gcc::jit::recording::function::new_block): New method.
+
+ (gcc::jit::recording::function::new_loop): Delete method.
+
+ (gcc::jit::recording::function::validate): New method.
+ (gcc::jit::recording::function::m_activity): Delete field in favor of...
+ (gcc::jit::recording::function::m_blocks): New field.
+
+ (gcc::jit::recording::statement::get_successor_blocks): New method.
+ (gcc::jit::recording::statement::write_to_dump): Make public.
+ (gcc::jit::recording::statement::statement): Accept a block rather
+ than a function.
+ (gcc::jit::recording::statement::playback_function): Delete.
+ (gcc::jit::recording::statement::get_block): New.
+ (gcc::jit::recording::statement::m_func): Delete in favor of...
+ (gcc::jit::recording::statement::m_block): ...this.
+
+ (gcc::jit::recording::eval::eval): Accept a block rather than a
+ function.
+ (gcc::jit::recording::assignment::assignment): Likewise.
+ (gcc::jit::recording::assignment_op::assignment_op): Likewise.
+ (gcc::jit::recording::comment::comment): Likewise.
+ (gcc::jit::recording::return::return): Likewise.
+ (gcc::jit::recording::conditional::conditional): Likewise; accept
+ blocks rather than labels.
+ (gcc::jit::recording::jump::jump): Likewise.
+ (gcc::jit::recording::conditional::get_successor_blocks): New.
+ (gcc::jit::recording::jump::get_successor_blocks): New.
+
+ (gcc::jit::playback::function::new_forward_label): Delete method
+ in favor of...
+ (gcc::jit::playback::function::new_block): New method.
+ (gcc::jit::playback::function::build_stmt_list): New method.
+ (gcc::jit::playback::function::m_blocks): New field.
+
+ * libgccjit++.h (gccjit::label): Delete class in favor of...
+ (gccjit::block): New class.
+ (gccjit::function::new_forward_label): Delete methods in favor of...
+ (gccjit::function::new_block): New methods.
+ (gccjit::function::add_comment): Delete methods in favor of methods
+ of new class gccjit::block.
+ (gccjit::function::add_conditional): Likewise.
+ (gccjit::function::add_label): Likewise.
+ (gccjit::function::place_forward_label): Likewise.
+ (gccjit::function::add_jump): Likewise.
+ (gccjit::function::add_return): Likewise.
+ (gccjit::function::add_call): Likewise.
+
+ * internal-api.c (gcc::jit::recording::playback_label): Delete in
+ favor of...
+ (gcc::jit::recording::playback_block): New.
+ (gcc::jit::recording::context::compile): Validate.
+ (gcc::jit::recording::context::validate): New.
+ (gcc::jit::recording::function::function): Update.
+ (gcc::jit::recording::function::new_forward_label): Delete.
+ (gcc::jit::recording::function::add_eval): Delete.
+ (gcc::jit::recording::function::add_assignment): Delete.
+ (gcc::jit::recording::function::add_assignment_op): Delete.
+ (gcc::jit::recording::function::new_block): New.
+ (gcc::jit::recording::function::add_comment): Delete.
+ (gcc::jit::ecording::function::add_conditional): Delete.
+ (gcc::jit::recording::function::add_label): Delete.
+ (gcc::jit::recording::function::place_forward_label): Delete.
+ (gcc::jit::recording::function::add_jump): Delete.
+ (gcc::jit::recording::function::add_return): Delete.
+ (gcc::jit::recording::function::new_loop): Delete.
+ (gcc::jit::recording::function::write_to_dump): Port to block-based
+ representation.
+ (gcc::jit::recording::function::validate): New.
+ (gcc::jit::recording::block::add_eval): New.
+ (gcc::jit::recording::block::add_assignment): New.
+ (gcc::jit::recording::label::replay_into): Delete.
+ (gcc::jit::recording::block::add_assignment_op): New.
+ (gcc::jit::recording::block::add_comment): New.
+ (gcc::jit::recording::block::end_with_conditional): New.
+ (gcc::jit::recording::block::end_with_jump): New.
+ (gcc::jit::recording::block::end_with_return): New.
+ (gcc::jit::recording::block::write_to_dump): New.
+ (gcc::jit::recording::block::validate): New.
+ (gcc::jit::recording::block::get_last_statement): New.
+ (gcc::jit::recording::block::get_successor_blocks): New.
+ (gcc::jit::recording::block::replay_into): New.
+ (gcc::jit::recording::label::make_debug_string): Delete.
+ (gcc::jit::recording::block::make_debug_string): New.
+ (gcc::jit::recording::statement::get_successor_blocks): New.
+ (gcc::jit::recording::eval::replay_into): Port to block-based
+ representation.
+ (gcc::jit::recording::assignment::replay_into): Likewise.
+ (gcc::jit::recording::assignment_op::replay_into): Likewise.
+ (gcc::jit::recording::comment::replay_into): Likewise.
+ (gcc::jit::recording::conditional::replay_into): Likewise.
+ (gcc::jit::recording::jump::replay_into): Likewise.
+ (gcc::jit::recording::return_::replay_into): Likewise.
+
+ (gcc::jit::recording::conditional::get_successor_blocks): New.
+ (gcc::jit::recording::place_label::place_label): Delete.
+ (gcc::jit::recording::place_label::replay_into): Delete.
+ (gcc::jit::recording::place_label::make_debug_string): Delete.
+ (gcc::jit::recording::place_label::write_to_dump): Delete.
+
+ (gcc::jit::recording::jump::get_successor_blocks): New.
+ (gcc::jit::recording::return_::get_successor_blocks): New.
+
+ (gcc::jit::recording::loop::replay_into): Delete.
+ (gcc::jit::recording::loop::make_debug_string): Delete.
+ (gcc::jit::recording::loop::end): Delete.
+ (gcc::jit::recording::loop_end::replay_into): Delete.
+ (gcc::jit::recording::loop_end::make_debug_string): Delete.
+
+ (gcc::jit::playback::function::new_forward_label): Delete.
+ (gcc::jit::playback::function::new_block): New.
+ (gcc::jit::playback::function::build_stmt_list): New.
+ (gcc::jit::playback::function::add_eval): Replace with...
+ (gcc::jit::playback::block::add_eval): New.
+ (gcc::jit::playback::function::add_assignment): Replace with...
+ (gcc::jit::playback::block::add_assignment): New.
+ (gcc::jit::playback::function::add_comment): Replace with...
+ (gcc::jit::playback::block::add_comment): New, reimplementing,
+ given that we no longer have labels.
+ (gcc::jit::playback::function::add_conditional): Replace with...
+ (gcc::jit::playback::block::add_conditional): New, reworking,
+ given that on_false can no longer be NULL.
+ (gcc::jit::playback::function::add_label): Delete.
+ (gcc::jit::playback::function::place_forward_label): Delete.
+ (gcc::jit::playback::function::add_jump): Replace with...
+ (gcc::jit::playback::block::add_jump): New.
+ (gcc::jit::playback::function::add_return): Replace with...
+ (gcc::jit::playback::block::add_return): New.
+ (gcc::jit::playback::function::new_loop): Delete.
+ (gcc::jit::playback::label::label): Replace with...
+ (gcc::jit::playback::block::block): ...this.
+
+ (gcc::jit::playback::loop::loop): Delete.
+ (gcc::jit::playback::loop::end): Delete.
+
+ (gcc::jit::playback::context::replay): Call each function's
+ build_stmt_list.
+
+ * TODO.rst: Update
+
2014-02-25 David Malcolm <dmalcolm@redhat.com>
* libgccjit.h (gcc_jit_function_add_void_return): New.
@@ -63,8 +63,8 @@ Initial Release
though would:
extern void
- gcc_jit_function_set_likelihood (gcc_jit_function *func,
- int hotness);
+ gcc_jit_block_set_likelihood (gcc_jit_block *block,
+ int hotness);
be better? (for expressing how hot the current location is)
@@ -112,9 +112,12 @@ Initial Release
* gcc_jit_function_new_local: type must not be void
- * gcc_jit_function_add_assignment_op: check the types
+ * gcc_jit_block_add_assignment_op: check the types
- * gcc_jit_loop_end: verify that loops are validly nested?
+* Currently each function has a single stmt_list, which is built in
+ postprocessing by walking the list of blocks. Presumably we could
+ have each block have its own stmt_list, avoiding the need for this
+ traversal, and having the block structure show up within tree dumps.
Bugs
====
@@ -143,8 +146,6 @@ Test suite
thread pool working through multiple instances of the various underlying
tests, each thread having a separate gcc_jit_context)
-* verify that nested loops work OK
-
Future milestones
=================
* try porting llvmpipe to gcc
@@ -97,11 +97,11 @@ recording::playback_string (recording::string *str)
return NULL;
}
-playback::label *
-recording::playback_label (recording::label *lab)
+playback::block *
+recording::playback_block (recording::block *b)
{
- if (lab)
- return lab->playback_label ();
+ if (b)
+ return b->playback_block ();
else
return NULL;
}
@@ -534,6 +534,8 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
result *
recording::context::compile ()
{
+ validate ();
+
if (errors_occurred ())
return NULL;
@@ -631,6 +633,18 @@ recording::context::dump_to_file (const char *path, bool update_locations)
}
}
+void
+recording::context::validate ()
+{
+ if (m_parent_ctxt)
+ m_parent_ctxt->validate ();
+
+ int i;
+ function *fn;
+ FOR_EACH_VEC_ELT (m_functions, i, fn)
+ fn->validate ();
+}
+
/* gcc::jit::recording::memento:: */
const char *
@@ -1182,7 +1196,7 @@ recording::function::function (context *ctxt,
m_is_variadic (is_variadic),
m_builtin_id (builtin_id),
m_locals (),
- m_activity ()
+ m_blocks ()
{
for (int i = 0; i< num_params; i++)
m_params.safe_push (params[i]);
@@ -1219,114 +1233,15 @@ recording::function::new_local (recording::location *loc,
return result;
}
-recording::label*
-recording::function::new_forward_label (const char *name)
+recording::block*
+recording::function::new_block (const char *name)
{
- recording::label *result =
- new recording::label (this, new_string (name));
- m_ctxt->record (result);
- return result;
-}
-
-void
-recording::function::add_eval (recording::location *loc,
- recording::rvalue *rvalue)
-{
- statement *result = new eval (this, loc, rvalue);
- m_ctxt->record (result);
- m_activity.safe_push (result);
-}
-
-void
-recording::function::add_assignment (recording::location *loc,
- recording::lvalue *lvalue,
- recording::rvalue *rvalue)
-{
- statement *result = new assignment (this, loc, lvalue, rvalue);
- m_ctxt->record (result);
- m_activity.safe_push (result);
-}
-
-void
-recording::function::add_assignment_op (recording::location *loc,
- recording::lvalue *lvalue,
- enum gcc_jit_binary_op op,
- recording::rvalue *rvalue)
-{
- statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
- m_ctxt->record (result);
- m_activity.safe_push (result);
-}
-
-void
-recording::function::add_comment (recording::location *loc,
- const char *text)
-{
- statement *result = new comment (this, loc, new_string (text));
- m_ctxt->record (result);
- m_activity.safe_push (result);
-}
-
-void
-recording::function::add_conditional (recording::location *loc,
- recording::rvalue *boolval,
- recording::label *on_true,
- recording::label *on_false)
-{
- statement *result = new conditional (this, loc, boolval, on_true, on_false);
- m_ctxt->record (result);
- m_activity.safe_push (result);
-}
-
-recording::label *
-recording::function::add_label (recording::location *loc,
- const char *name)
-{
- recording::label *lab = new_forward_label (name);
- place_forward_label (loc, lab);
- return lab;
-}
-
-void
-recording::function::place_forward_label (recording::location *loc,
- recording::label *lab)
-{
- statement *result = new place_label (this, loc, lab);
- m_ctxt->record (result);
- m_activity.safe_push (result);
-}
-
-void
-recording::function::add_jump (recording::location *loc,
- recording::label *target)
-{
- statement *result = new jump (this, loc, target);
- m_ctxt->record (result);
- m_activity.safe_push (result);
-}
-
-void
-recording::function::add_return (recording::location *loc,
- recording::rvalue *rvalue)
-{
- /* This is used by both gcc_jit_function_add_return and
- gcc_jit_function_add_void_return; rvalue will be non-NULL for
- the former and NULL for the latter. */
- statement *result = new return_ (this, loc, rvalue);
- m_ctxt->record (result);
- m_activity.safe_push (result);
-}
+ gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
-recording::loop *
-recording::function::new_loop (recording::location *loc,
- recording::rvalue *boolval,
- recording::lvalue *iteration_var,
- recording::rvalue *step)
-{
- recording::loop *result = new recording::loop (this, loc, boolval,
- iteration_var, step);
+ recording::block *result =
+ new recording::block (this, new_string (name));
m_ctxt->record (result);
- m_activity.safe_push (result);
+ m_blocks.safe_push (result);
return result;
}
@@ -1370,7 +1285,7 @@ recording::function::write_to_dump (dump &d)
{
int i;
local *var = NULL;
- memento *m;
+ block *b;
d.write ("\n{\n");
/* Write locals: */
@@ -1379,44 +1294,227 @@ recording::function::write_to_dump (dump &d)
if (m_locals.length ())
d.write ("\n");
- /* Write statements and labels: */
- FOR_EACH_VEC_ELT (m_activity, i, m)
- m->write_to_dump (d);
+ /* Write each block: */
+ FOR_EACH_VEC_ELT (m_blocks, i, b)
+ {
+ if (i > 0)
+ d.write ("\n");
+ b->write_to_dump (d);
+ }
d.write ("}\n\n");
}
}
+void
+recording::function::validate ()
+{
+ /* Complain about empty functions with non-void return type. */
+ if (m_kind != GCC_JIT_FUNCTION_IMPORTED
+ && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
+ if (0 == m_blocks.length ())
+ m_ctxt->add_error ("function %s returns non-void (type: %s)"
+ " but has no blocks",
+ get_debug_string (),
+ m_return_type->get_debug_string ());
+
+ /* Check that all blocks are terminated. */
+ int num_invalid_blocks = 0;
+ {
+ int i;
+ block *b;
+
+ FOR_EACH_VEC_ELT (m_blocks, i, b)
+ if (!b->validate ())
+ num_invalid_blocks++;
+ }
+
+ /* Check that all blocks are reachable. */
+ if (m_blocks.length () > 0 && 0 == num_invalid_blocks)
+ {
+ /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
+ flag, starting at the initial block. */
+ vec<block *> worklist;
+ worklist.create (m_blocks.length ());
+ worklist.safe_push (m_blocks[0]);
+ while (worklist.length () > 0)
+ {
+ block *b = worklist.pop ();
+ b->m_is_reachable = true;
+
+ /* Add successor blocks that aren't yet marked to the worklist. */
+ /* We checked that each block has a terminating statement above . */
+ block *next1, *next2;
+ int n = b->get_successor_blocks (&next1, &next2);
+ switch (n)
+ {
+ default:
+ gcc_unreachable ();
+ case 2:
+ if (!next2->m_is_reachable)
+ worklist.safe_push (next2);
+ /* fallthrough */
+ case 1:
+ if (!next1->m_is_reachable)
+ worklist.safe_push (next1);
+ break;
+ case 0:
+ break;
+ }
+ }
+
+ /* Now complain about any blocks that haven't been marked. */
+ {
+ int i;
+ block *b;
+ FOR_EACH_VEC_ELT (m_blocks, i, b)
+ if (!b->m_is_reachable)
+ m_ctxt->add_error ("unreachable block: %s",
+ b->get_debug_string ());
+ }
+ }
+}
+
recording::string *
recording::function::make_debug_string ()
{
return m_name;
}
-/* gcc::jit::recording::label:: */
+/* gcc::jit::recording::block:: */
+
+void
+recording::block::add_eval (recording::location *loc,
+ recording::rvalue *rvalue)
+{
+ statement *result = new eval (this, loc, rvalue);
+ m_ctxt->record (result);
+ m_statements.safe_push (result);
+}
+
+void
+recording::block::add_assignment (recording::location *loc,
+ recording::lvalue *lvalue,
+ recording::rvalue *rvalue)
+{
+ statement *result = new assignment (this, loc, lvalue, rvalue);
+ m_ctxt->record (result);
+ m_statements.safe_push (result);
+}
+
+void
+recording::block::add_assignment_op (recording::location *loc,
+ recording::lvalue *lvalue,
+ enum gcc_jit_binary_op op,
+ recording::rvalue *rvalue)
+{
+ statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
+ m_ctxt->record (result);
+ m_statements.safe_push (result);
+}
+
+void
+recording::block::add_comment (recording::location *loc,
+ const char *text)
+{
+ statement *result = new comment (this, loc, new_string (text));
+ m_ctxt->record (result);
+ m_statements.safe_push (result);
+}
+
+void
+recording::block::end_with_conditional (recording::location *loc,
+ recording::rvalue *boolval,
+ recording::block *on_true,
+ recording::block *on_false)
+{
+ statement *result = new conditional (this, loc, boolval, on_true, on_false);
+ m_ctxt->record (result);
+ m_statements.safe_push (result);
+ m_has_been_terminated = true;
+}
+
+void
+recording::block::end_with_jump (recording::location *loc,
+ recording::block *target)
+{
+ statement *result = new jump (this, loc, target);
+ m_ctxt->record (result);
+ m_statements.safe_push (result);
+ m_has_been_terminated = true;
+}
+
+void
+recording::block::end_with_return (recording::location *loc,
+ recording::rvalue *rvalue)
+{
+ /* This is used by both gcc_jit_function_add_return and
+ gcc_jit_function_add_void_return; rvalue will be non-NULL for
+ the former and NULL for the latter. */
+ statement *result = new return_ (this, loc, rvalue);
+ m_ctxt->record (result);
+ m_statements.safe_push (result);
+ m_has_been_terminated = true;
+}
void
-recording::label::replay_into (replayer *r)
+recording::block::write_to_dump (dump &d)
{
- if (!m_has_been_placed)
+ d.write ("%s:\n", get_debug_string ());
+
+ int i;
+ statement *s;
+ FOR_EACH_VEC_ELT (m_statements, i, s)
+ s->write_to_dump (d);
+}
+
+bool
+recording::block::validate ()
+{
+ if (!has_been_terminated ())
{
- r->add_error ("unplaced label within %s: %s",
- m_func->get_debug_string (),
- get_debug_string ());
- return;
+ m_func->get_context ()->add_error ("unterminated block in %s: %s",
+ m_func->get_debug_string (),
+ get_debug_string ());
+ return false;
}
+
+ return true;
+}
+
+recording::statement *
+recording::block::get_last_statement () const
+{
+ if (m_statements.length ())
+ return m_statements[m_statements.length () - 1];
+ else
+ return NULL;
+}
+
+int
+recording::block::get_successor_blocks (block **next1, block **next2) const
+{
+ gcc_assert (m_has_been_terminated);
+ statement *last_statement = get_last_statement ();
+ gcc_assert (last_statement);
+ return last_statement->get_successor_blocks (next1, next2);
+}
+
+void
+recording::block::replay_into (replayer *)
+{
set_playback_obj (m_func->playback_function ()
- ->new_forward_label (playback_string (m_name)));
+ ->new_block (playback_string (m_name)));
}
recording::string *
-recording::label::make_debug_string ()
+recording::block::make_debug_string ()
{
if (m_name)
return m_name;
else
return string::from_printf (m_ctxt,
- "<UNNAMED LABEL %p>",
+ "<UNNAMED BLOCK %p>",
(void *)this);
}
@@ -1779,6 +1877,16 @@ recording::local::write_to_dump (dump &d)
// gcc::jit::recording::statement
+int
+recording::statement::get_successor_blocks (block **/*out_next1*/,
+ block **/*out_next2*/) const
+{
+ /* The base class implementation is for non-terminating statements,
+ and thus should never be called. */
+ gcc_unreachable ();
+ return 0;
+}
+
void
recording::statement::write_to_dump (dump &d)
{
@@ -1790,7 +1898,7 @@ recording::statement::write_to_dump (dump &d)
void
recording::eval::replay_into (replayer *r)
{
- playback_function ()
+ playback_block (get_block ())
->add_eval (playback_location (r),
m_rvalue->playback_rvalue ());
}
@@ -1806,7 +1914,7 @@ recording::eval::make_debug_string ()
void
recording::assignment::replay_into (replayer *r)
{
- playback_function ()
+ playback_block (get_block ())
->add_assignment (playback_location (r),
m_lvalue->playback_lvalue (),
m_rvalue->playback_rvalue ());
@@ -1834,7 +1942,7 @@ recording::assignment_op::replay_into (replayer *r)
m_lvalue->playback_rvalue (),
m_rvalue->playback_rvalue ());
- playback_function ()
+ playback_block (get_block ())
->add_assignment (playback_location (r),
m_lvalue->playback_lvalue (),
binary_op);
@@ -1853,7 +1961,7 @@ recording::assignment_op::make_debug_string ()
void
recording::comment::replay_into (replayer *r)
{
- playback_function ()
+ playback_block (get_block ())
->add_comment (playback_location (r),
m_text->c_str ());
}
@@ -1869,11 +1977,20 @@ recording::comment::make_debug_string ()
void
recording::conditional::replay_into (replayer *r)
{
- playback_function ()
+ playback_block (get_block ())
->add_conditional (playback_location (r),
m_boolval->playback_rvalue (),
- playback_label (m_on_true),
- playback_label (m_on_false));
+ playback_block (m_on_true),
+ playback_block (m_on_false));
+}
+
+int
+recording::conditional::get_successor_blocks (block **out_next1,
+ block **out_next2) const
+{
+ *out_next1 = m_on_true;
+ *out_next2 = m_on_false;
+ return 2;
}
recording::string *
@@ -1892,46 +2009,20 @@ recording::conditional::make_debug_string ()
m_on_true->get_debug_string ());
}
-recording::place_label::place_label (function *func,
- location *loc,
- label *lab)
-: statement (func, loc),
- m_label (lab)
-{
- if (lab->m_has_been_placed)
- m_ctxt->add_error ("label %s has already been placed",
- lab->get_debug_string ());
- lab->m_has_been_placed = true;
-}
-
void
-recording::place_label::replay_into (replayer *r)
-{
- playback_function ()
- ->place_forward_label (playback_location (r),
- m_label->playback_label ());
-}
-
-recording::string *
-recording::place_label::make_debug_string ()
-{
- return string::from_printf (m_ctxt,
- "%s:",
- m_label->get_debug_string ());
-}
-
-void
-recording::place_label::write_to_dump (dump &d)
+recording::jump::replay_into (replayer *r)
{
- d.write ("\n%s\n", get_debug_string ());
+ playback_block (get_block ())
+ ->add_jump (playback_location (r),
+ m_target->playback_block ());
}
-void
-recording::jump::replay_into (replayer *r)
+int
+recording::jump::get_successor_blocks (block **out_next1,
+ block **/*out_next2*/) const
{
- playback_function ()
- ->add_jump (playback_location (r),
- m_target->playback_label ());
+ *out_next1 = m_target;
+ return 1;
}
recording::string *
@@ -1945,11 +2036,18 @@ recording::jump::make_debug_string ()
void
recording::return_::replay_into (replayer *r)
{
- playback_function ()
+ playback_block (get_block ())
->add_return (playback_location (r),
m_rvalue ? m_rvalue->playback_rvalue () : NULL);
}
+int
+recording::return_::get_successor_blocks (block **/*out_next1*/,
+ block **/*out_next2*/) const
+{
+ return 0;
+}
+
recording::string *
recording::return_::make_debug_string ()
{
@@ -1962,52 +2060,6 @@ recording::return_::make_debug_string ()
"return;");
}
-void
-recording::loop::replay_into (replayer *r)
-{
- set_playback_obj (
- m_func->playback_function ()
- ->new_loop (playback_location (r, m_loc),
- m_boolval->playback_rvalue ()));
-}
-
-recording::string *
-recording::loop::make_debug_string ()
-{
- return string::from_printf (m_ctxt,
- "loop_while (%s)",
- m_boolval->get_debug_string ());
-}
-
-void
-recording::loop::end (location *loc)
-{
- if (m_iteration_var)
- m_func->add_assignment (
- loc,
- m_iteration_var,
- m_ctxt->new_binary_op (loc,
- GCC_JIT_BINARY_OP_PLUS,
- m_iteration_var->get_type (),
- m_iteration_var,
- m_step));
- recording::loop_end *m = new loop_end (this, loc);
- m_ctxt->record (m);
-}
-
-void
-recording::loop_end::replay_into (replayer *r)
-{
- m_loop->playback_loop ()->end (playback_location (r, m_loc));
-}
-
-recording::string *
-recording::loop_end::make_debug_string ()
-{
- return string::from_printf (m_ctxt,
- "end_loop (%p)", (void *)m_loop);
-}
-
/**********************************************************************
Playback.
**********************************************************************/
@@ -2885,12 +2937,37 @@ new_local (location *loc,
return new lvalue (m_ctxt, inner);
}
-playback::label *
+playback::block *
playback::function::
-new_forward_label (const char *name)
+new_block (const char *name)
{
gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
- return new playback::label (this, name);
+
+ block *result = new playback::block (this, name);
+ m_blocks.safe_push (result);
+ return result;
+}
+
+void
+playback::function::
+build_stmt_list ()
+{
+ int i;
+ block *b;
+
+ FOR_EACH_VEC_ELT (m_blocks, i, b)
+ {
+ int j;
+ tree stmt;
+
+ b->m_label_expr = build1 (LABEL_EXPR,
+ void_type_node,
+ b->as_label_decl ());
+ tsi_link_after (&m_stmt_iter, b->m_label_expr, TSI_CONTINUE_LINKING);
+
+ FOR_EACH_VEC_ELT (b->m_stmts, j, stmt)
+ tsi_link_after (&m_stmt_iter, stmt, TSI_CONTINUE_LINKING);
+ }
}
void
@@ -2943,12 +3020,11 @@ postprocess ()
}
void
-playback::function::
+playback::block::
add_eval (location *loc,
rvalue *rvalue)
{
gcc_assert (rvalue);
- gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
if (loc)
set_tree_location (rvalue->as_tree (), loc);
@@ -2957,14 +3033,13 @@ add_eval (location *loc,
}
void
-playback::function::
+playback::block::
add_assignment (location *loc,
lvalue *lvalue,
rvalue *rvalue)
{
gcc_assert (lvalue);
gcc_assert (rvalue);
- gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
tree t_lvalue = lvalue->as_tree ();
tree t_rvalue = rvalue->as_tree ();
@@ -2986,12 +3061,10 @@ add_assignment (location *loc,
}
void
-playback::function::
+playback::block::
add_comment (location *loc,
const char *text)
{
- gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
-
/* Wrap the text in C-style comment delimiters. */
size_t sz =
(3 /* opening delim */
@@ -3003,20 +3076,27 @@ add_comment (location *loc,
/* For now we simply implement this by adding a dummy label with a name
containing the given text. */
- add_label (loc, wrapped);
+ tree identifier = get_identifier (wrapped);
+ tree label_decl = build_decl (UNKNOWN_LOCATION, LABEL_DECL,
+ identifier, void_type_node);
+ DECL_CONTEXT (label_decl) = m_func->as_fndecl ();
+
+ tree label_expr = build1 (LABEL_EXPR, void_type_node, label_decl);
+ if (loc)
+ set_tree_location (label_expr, loc);
+ add_stmt (label_expr);
}
void
-playback::function::
+playback::block::
add_conditional (location *loc,
rvalue *boolval,
- label *on_true,
- label *on_false)
+ block *on_true,
+ block *on_false)
{
gcc_assert (boolval);
gcc_assert (on_true);
- /* on_false can be NULL */
- gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
+ gcc_assert (on_false);
/* COND_EXPR wants statement lists for the true/false operands, but we
want labels.
@@ -3025,16 +3105,11 @@ add_conditional (location *loc,
on_true->as_label_decl ());
if (loc)
set_tree_location (true_jump, loc);
- tree false_jump;
- if (on_false)
- {
- false_jump = build1 (GOTO_EXPR, void_type_node,
- on_false->as_label_decl ());
- if (loc)
- set_tree_location (false_jump, loc);
- }
- else
- false_jump = NULL;
+
+ tree false_jump = build1 (GOTO_EXPR, void_type_node,
+ on_false->as_label_decl ());
+ if (loc)
+ set_tree_location (false_jump, loc);
tree stmt =
build3 (COND_EXPR, void_type_node, boolval->as_tree (),
@@ -3044,41 +3119,12 @@ add_conditional (location *loc,
add_stmt (stmt);
}
-playback::label *
-playback::function::
-add_label (location *loc,
- const char *name)
-{
- gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
-
- label *lab = new label (this, name);
- place_forward_label (loc, lab);
- return lab;
-}
-
void
-playback::function::
-place_forward_label (location *loc, label *lab)
-{
- gcc_assert (lab);
- gcc_assert (NULL == lab->m_label_expr); // must not have already been placed
- gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
-
- lab->m_label_expr = build1 (LABEL_EXPR,
- void_type_node,
- lab->as_label_decl ());
- if (loc)
- set_tree_location (lab->m_label_expr, loc);
- add_stmt (lab->m_label_expr);
-}
-
-void
-playback::function::
+playback::block::
add_jump (location *loc,
- label *target)
+ block *target)
{
gcc_assert (target);
- gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
// see c_finish_loop
//tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
@@ -3111,17 +3157,15 @@ c_finish_goto_label (location_t loc, tree label)
}
void
-playback::function::
+playback::block::
add_return (location *loc,
rvalue *rvalue)
{
- gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
-
tree modify_retval = NULL;
- tree return_type = TREE_TYPE (TREE_TYPE (m_inner_fndecl));
+ tree return_type = m_func->get_return_type_as_tree ();
if (rvalue)
{
- tree t_lvalue = DECL_RESULT (m_inner_fndecl);
+ tree t_lvalue = DECL_RESULT (m_func->as_fndecl ());
tree t_rvalue = rvalue->as_tree ();
if (TREE_TYPE (t_rvalue) != TREE_TYPE (t_lvalue))
t_rvalue = build1 (CONVERT_EXPR,
@@ -3140,17 +3184,11 @@ add_return (location *loc,
add_stmt (return_stmt);
}
-playback::loop *
-playback::function::
-new_loop (location *loc,
- rvalue *boolval)
-{
- return new loop (this, loc, boolval);
-}
-
-playback::label::
-label (function *func,
+playback::block::
+block (function *func,
const char *name)
+: m_func (func),
+ m_stmts ()
{
tree identifier;
@@ -3166,26 +3204,6 @@ label (function *func,
m_label_expr = NULL;
}
-
-playback::loop::
-loop (function *func, location *loc, rvalue *boolval) :
- m_func(func)
-{
- m_label_cond = func->add_label (loc, "loop_cond");
- m_label_body = func->new_forward_label ("loop_body");
- m_label_end = func->new_forward_label ("loop_end");
- func->add_conditional (loc, boolval, m_label_body, m_label_end);
- func->place_forward_label (loc, m_label_body);
-}
-
-void
-playback::loop::
-end (location *loc)
-{
- m_func->add_jump (loc, m_label_cond);
- m_func->place_forward_label (loc, m_label_end);
-}
-
result *
playback::context::
compile ()
@@ -3396,6 +3414,14 @@ replay ()
/* No GC can happen yet; process the cached source locations. */
handle_locations ();
+ /* We've now created tree nodes for the stmts in the various blocks
+ in each function, but we haven't built each function's single stmt
+ list yet. Do so now. */
+ FOR_EACH_VEC_ELT (m_functions, i, func)
+ func->build_stmt_list ();
+
+ /* No GC can have happened yet. */
+
/* Postprocess the functions. This could trigger GC. */
FOR_EACH_VEC_ELT (m_functions, i, func)
{
@@ -88,12 +88,12 @@ namespace recording {
class struct_;
class fields;
class function;
- class label;
+ class block;
class rvalue;
class lvalue;
class local;
class param;
- class loop;
+ class statement;
}
namespace playback {
@@ -103,11 +103,10 @@ namespace playback {
class field;
class struct_;
class function;
- class label;
+ class block;
class rvalue;
class lvalue;
class param;
- class loop;
class source_file;
class source_line;
}
@@ -151,8 +150,8 @@ playback_location (replayer *r, location *loc);
const char *
playback_string (string *str);
-playback::label *
-playback_label (label *lab);
+playback::block *
+playback_block (block *b);
/* A JIT-compilation context. */
class context
@@ -312,6 +311,9 @@ public:
void dump_to_file (const char *path, bool update_locations);
private:
+ void validate ();
+
+private:
context *m_parent_ctxt;
int m_error_count;
@@ -845,53 +847,8 @@ public:
type *type,
const char *name);
- label*
- new_forward_label (const char *name);
-
- void
- add_eval (location *loc,
- rvalue *rvalue);
-
- void
- add_assignment (location *loc,
- lvalue *lvalue,
- rvalue *rvalue);
-
- void
- add_assignment_op (location *loc,
- lvalue *lvalue,
- enum gcc_jit_binary_op op,
- rvalue *rvalue);
-
- void
- add_comment (location *loc,
- const char *text);
-
- void
- add_conditional (location *loc,
- rvalue *boolval,
- label *on_true,
- label *on_false);
-
- label *
- add_label (location *loc,
- const char *name);
-
- void
- place_forward_label (location *loc, label *lab);
-
- void
- add_jump (location *loc,
- label *target);
-
- void
- add_return (location *loc,
- rvalue *rvalue);
-
- loop *
- new_loop (location *loc,
- rvalue *boolval,
- lvalue *iteration_var, rvalue *step);
+ block*
+ new_block (const char *name);
type *get_return_type () const { return m_return_type; }
string * get_name () const { return m_name; }
@@ -901,6 +858,8 @@ public:
void write_to_dump (dump &d);
+ void validate ();
+
private:
string * make_debug_string ();
@@ -912,41 +871,88 @@ private:
vec<param *> m_params;
int m_is_variadic;
enum built_in_function m_builtin_id;
- /* Additional vectors to help when dumping. */
vec<local *> m_locals;
- vec<memento *> m_activity; // statements and labels
+ vec<block *> m_blocks;
};
-class label : public memento
+class block : public memento
{
public:
- label (function *func, string *name)
+ block (function *func, string *name)
: memento (func->m_ctxt),
m_func (func),
m_name (name),
- m_has_been_placed (false)
+ m_statements (),
+ m_has_been_terminated (false),
+ m_is_reachable (false)
{
}
- void replay_into (replayer *r);
+ function *get_function () { return m_func; }
+
+ bool has_been_terminated () { return m_has_been_terminated; }
+ bool is_reachable () { return m_is_reachable; }
+
+ void
+ add_eval (location *loc,
+ rvalue *rvalue);
+
+ void
+ add_assignment (location *loc,
+ lvalue *lvalue,
+ rvalue *rvalue);
+
+ void
+ add_assignment_op (location *loc,
+ lvalue *lvalue,
+ enum gcc_jit_binary_op op,
+ rvalue *rvalue);
+
+ void
+ add_comment (location *loc,
+ const char *text);
+
+ void
+ end_with_conditional (location *loc,
+ rvalue *boolval,
+ block *on_true,
+ block *on_false);
+
+ void
+ end_with_jump (location *loc,
+ block *target);
- playback::label *
- playback_label () const
+ void
+ end_with_return (location *loc,
+ rvalue *rvalue);
+
+ playback::block *
+ playback_block () const
{
- return static_cast <playback::label *> (m_playback_obj);
+ return static_cast <playback::block *> (m_playback_obj);
}
- bool has_been_placed () { return m_has_been_placed; }
+ void write_to_dump (dump &d);
+
+ bool validate ();
+
+ statement *get_last_statement () const;
+
+ int get_successor_blocks (block **next1, block **next2) const;
private:
string * make_debug_string ();
+ void replay_into (replayer *r);
+
private:
function *m_func;
string *m_name;
- bool m_has_been_placed;
+ vec<statement *> m_statements;
+ bool m_has_been_terminated;
+ bool m_is_reachable;
- friend class place_label;
+ friend class function;
};
class global : public lvalue
@@ -1283,17 +1289,19 @@ private:
class statement : public memento
{
+public:
+ virtual int get_successor_blocks (block **out_next1,
+ block **out_next2) const;
+
+ void write_to_dump (dump &d);
+
protected:
- statement (function *func, location *loc)
- : memento (func->m_ctxt),
- m_func (func),
+ statement (block *b, location *loc)
+ : memento (b->m_ctxt),
+ m_block (b),
m_loc (loc) {}
- playback::function *
- playback_function () const
- {
- return m_func->playback_function ();
- }
+ block *get_block () const { return m_block; }
playback::location *
playback_location (replayer *r) const
@@ -1302,20 +1310,17 @@ protected:
}
private:
- void write_to_dump (dump &d);
-
-private:
- function *m_func;
+ block *m_block;
location *m_loc;
};
class eval : public statement
{
public:
- eval (function *func,
+ eval (block *b,
location *loc,
rvalue *rvalue)
- : statement (func, loc),
+ : statement (b, loc),
m_rvalue (rvalue) {}
void replay_into (replayer *r);
@@ -1330,11 +1335,11 @@ private:
class assignment : public statement
{
public:
- assignment (function *func,
+ assignment (block *b,
location *loc,
lvalue *lvalue,
rvalue *rvalue)
- : statement (func, loc),
+ : statement (b, loc),
m_lvalue (lvalue),
m_rvalue (rvalue) {}
@@ -1351,12 +1356,12 @@ private:
class assignment_op : public statement
{
public:
- assignment_op (function *func,
+ assignment_op (block *b,
location *loc,
lvalue *lvalue,
enum gcc_jit_binary_op op,
rvalue *rvalue)
- : statement (func, loc),
+ : statement (b, loc),
m_lvalue (lvalue),
m_op (op),
m_rvalue (rvalue) {}
@@ -1375,10 +1380,10 @@ private:
class comment : public statement
{
public:
- comment (function *func,
+ comment (block *b,
location *loc,
string *text)
- : statement (func, loc),
+ : statement (b, loc),
m_text (text) {}
void replay_into (replayer *r);
@@ -1393,145 +1398,70 @@ private:
class conditional : public statement
{
public:
- conditional (function *func,
+ conditional (block *b,
location *loc,
rvalue *boolval,
- label *on_true,
- label *on_false)
- : statement (func, loc),
+ block *on_true,
+ block *on_false)
+ : statement (b, loc),
m_boolval (boolval),
m_on_true (on_true),
m_on_false (on_false) {}
void replay_into (replayer *r);
-private:
- string * make_debug_string ();
-
-private:
- rvalue *m_boolval;
- label *m_on_true;
- label *m_on_false;
-};
-
-class place_label : public statement
-{
-public:
- place_label (function *func,
- location *loc,
- label *lab);
-
- void replay_into (replayer *r);
+ int get_successor_blocks (block **out_next1,
+ block **out_next2) const;
private:
string * make_debug_string ();
- void write_to_dump (dump &d);
-
private:
- label *m_label;
+ rvalue *m_boolval;
+ block *m_on_true;
+ block *m_on_false;
};
class jump : public statement
{
public:
- jump (function *func,
+ jump (block *b,
location *loc,
- label *target)
- : statement (func, loc),
+ block *target)
+ : statement (b, loc),
m_target (target) {}
void replay_into (replayer *r);
+ int get_successor_blocks (block **out_next1,
+ block **out_next2) const;
+
private:
string * make_debug_string ();
private:
- label *m_target;
+ block *m_target;
};
class return_ : public statement
{
public:
- return_ (function *func,
+ return_ (block *b,
location *loc,
rvalue *rvalue)
- : statement (func, loc),
+ : statement (b, loc),
m_rvalue (rvalue) {}
void replay_into (replayer *r);
-private:
- string * make_debug_string ();
-
-private:
- rvalue *m_rvalue;
-};
-
-class loop : public memento
-{
-public:
- loop (function *func,
- location *loc,
- rvalue *boolval,
- lvalue *iteration_var, rvalue *step)
- : memento (func->m_ctxt),
- m_func (func),
- m_loc (loc),
- m_boolval (boolval),
- m_iteration_var (iteration_var),
- m_step (step)
- {}
-
- void replay_into (replayer *r);
-
- void end (location *loc);
-
- playback::loop *
- playback_loop ()
- {
- return static_cast <playback::loop *> (m_playback_obj);
- }
+ int get_successor_blocks (block **out_next1,
+ block **out_next2) const;
private:
string * make_debug_string ();
private:
- function *m_func;
- location *m_loc;
- rvalue *m_boolval;
-
- /* The following fields are for handling
- gcc_jit_function_new_loop_over_range and are NULL for other loops.
-
- We preserve these from "_over_range" calls so that we can inject a
- += assignment in the correct place immediately before the loop ends.
- This is done within the recording::loop::end () method.
- The corresponding playback::loop class has no special handling for
- this, with the += operation having become a regular assignment by
- that time. */
- lvalue *m_iteration_var;
- rvalue *m_step;
-};
-
-class loop_end : public memento
-{
-public:
- loop_end (loop *loop,
- location *loc)
- : memento (loop->m_ctxt),
- m_loop (loop),
- m_loc (loc)
- {}
-
- void replay_into (replayer *r);
-
-private:
- string * make_debug_string ();
-
-private:
- loop *m_loop;
- location *m_loc;
+ rvalue *m_rvalue;
};
} // namespace gcc::jit::recording
@@ -1826,8 +1756,42 @@ public:
type *type,
const char *name);
- label*
- new_forward_label (const char *name);
+ block*
+ new_block (const char *name);
+
+ void
+ build_stmt_list ();
+
+ void
+ postprocess ();
+
+public:
+ context *m_ctxt;
+
+public:
+ void
+ set_tree_location (tree t, location *loc)
+ {
+ m_ctxt->set_tree_location (t, loc);
+ }
+
+private:
+ tree m_inner_fndecl;
+ tree m_inner_block;
+ tree m_inner_bind_expr;
+ enum gcc_jit_function_kind m_kind;
+ tree m_stmt_list;
+ tree_stmt_iterator m_stmt_iter;
+ vec<block *> m_blocks;
+};
+
+class block : public wrapper
+{
+public:
+ block (function *func,
+ const char *name);
+
+ tree as_label_decl () const { return m_label_decl; }
void
add_eval (location *loc,
@@ -1845,68 +1809,43 @@ public:
void
add_conditional (location *loc,
rvalue *boolval,
- label *on_true,
- label *on_false);
+ block *on_true,
+ block *on_false);
- label *
- add_label (location *loc,
+ block *
+ add_block (location *loc,
const char *name);
void
- place_forward_label (location *loc, label *lab);
-
- void
add_jump (location *loc,
- label *target);
+ block *target);
void
add_return (location *loc,
rvalue *rvalue);
- loop *
- new_loop (location *loc,
- rvalue *boolval);
-
- void
- postprocess ();
-
-public:
- context *m_ctxt;
-
private:
- void add_stmt (tree stmt)
- {
- tsi_link_after (&m_stmt_iter, stmt, TSI_CONTINUE_LINKING);
- }
-
void
set_tree_location (tree t, location *loc)
{
- m_ctxt->set_tree_location (t, loc);
+ m_func->set_tree_location (t, loc);
}
-private:
- tree m_inner_fndecl;
- tree m_inner_block;
- tree m_inner_bind_expr;
- enum gcc_jit_function_kind m_kind;
- tree m_stmt_list;
- tree_stmt_iterator m_stmt_iter;
-};
-
-class label : public wrapper
-{
-public:
- label (function *func,
- const char *name);
-
- tree as_label_decl () const { return m_label_decl; }
+ void add_stmt (tree stmt)
+ {
+ /* TODO: use one stmt_list per block. */
+ m_stmts.safe_push (stmt);
+ }
private:
+ function *m_func;
tree m_label_decl;
+ vec<tree> m_stmts;
public: // for now
tree m_label_expr;
+
+ friend class function;
};
class rvalue : public wrapper
@@ -1970,20 +1909,6 @@ public:
{}
};
-class loop : public wrapper
-{
-public:
- loop (function *func, location *loc, rvalue *boolval);
-
- void end (location *loc);
-
-private:
- function *m_func;
- label *m_label_cond;
- label *m_label_body;
- label *m_label_end;
-};
-
/* Dealing with the linemap API.
It appears that libcpp requires locations to be created as if by
@@ -22,7 +22,7 @@ namespace gccjit
class struct_;
class param;
class function;
- class label;
+ class block;
class rvalue;
class lvalue;
@@ -290,13 +290,32 @@ namespace gccjit
param get_param (int index);
- label new_forward_label ();
- label new_forward_label (const std::string &name);
+ block new_block ();
+ block new_block (const std::string &name);
lvalue new_local (type type_,
const std::string &name,
location loc = location ());
+ /* A series of overloaded operator () with various numbers of arguments
+ for a very terse way of creating a call to this function. The call
+ is created within the same context as the function itself, which may
+ not be what you want. */
+ rvalue operator() (location loc = location ());
+ rvalue operator() (rvalue arg0,
+ location loc = location ());
+ rvalue operator() (rvalue arg0, rvalue arg1,
+ location loc = location ());
+ };
+
+ class block : public object
+ {
+ public:
+ block ();
+ block (gcc_jit_block *inner);
+
+ gcc_jit_block *get_inner_block () const;
+
void add_eval (rvalue rvalue,
location loc = location ());
@@ -309,28 +328,6 @@ namespace gccjit
rvalue rvalue,
location loc = location ());
- void add_comment (const std::string &text,
- location loc = location ());
-
- void add_conditional (rvalue boolval,
- label on_true,
- label on_false,
- location loc = location ());
-
- label add_label (const std::string &name,
- location loc = location ());
- label add_label (location loc = location ());
-
- void place_forward_label (label lab,
- location loc = location ());
-
- void add_jump (label target,
- location loc = location ());
-
- void add_return (rvalue rvalue,
- location loc = location ());
- void add_return (location loc = location ());
-
/* A way to add a function call to the body of a function being
defined, with various numbers of args. */
rvalue add_call (function other,
@@ -345,24 +342,21 @@ namespace gccjit
rvalue arg0, rvalue arg1, rvalue arg2,
location loc = location ());
- /* A series of overloaded operator () with various numbers of arguments
- for a very terse way of creating a call to this function. The call
- is created within the same context as the function itself, which may
- not be what you want. */
- rvalue operator() (location loc = location ());
- rvalue operator() (rvalue arg0,
- location loc = location ());
- rvalue operator() (rvalue arg0, rvalue arg1,
- location loc = location ());
- };
+ void add_comment (const std::string &text,
+ location loc = location ());
- class label : public object
- {
- public:
- label ();
- label (gcc_jit_label *inner);
+ void end_with_conditional (rvalue boolval,
+ block on_true,
+ block on_false,
+ location loc = location ());
+
+ void end_with_jump (block target,
+ location loc = location ());
+
+ void end_with_return (rvalue rvalue,
+ location loc = location ());
+ void end_with_return (location loc = location ());
- gcc_jit_label *get_inner_label () const;
};
class rvalue : public object
@@ -1090,18 +1084,18 @@ function::get_param (int index)
index));
}
-inline label
-function::new_forward_label ()
+inline block
+function::new_block ()
{
- return label (gcc_jit_function_new_forward_label (get_inner_function (),
- NULL));
+ return block (gcc_jit_function_new_block (get_inner_function (),
+ NULL));
}
-inline label
-function::new_forward_label (const std::string &name)
+inline block
+function::new_block (const std::string &name)
{
- return label (gcc_jit_function_new_forward_label (get_inner_function (),
- name.c_str ()));
+ return block (gcc_jit_function_new_block (get_inner_function (),
+ name.c_str ()));
}
inline lvalue
@@ -1116,141 +1110,115 @@ function::new_local (type type_,
}
inline void
-function::add_eval (rvalue rvalue,
- location loc)
-{
- gcc_jit_function_add_eval (get_inner_function (),
- loc.get_inner_location (),
- rvalue.get_inner_rvalue ());
-}
-
-inline void
-function::add_assignment (lvalue lvalue,
- rvalue rvalue,
- location loc)
-{
- gcc_jit_function_add_assignment (get_inner_function (),
- loc.get_inner_location (),
- lvalue.get_inner_lvalue (),
- rvalue.get_inner_rvalue ());
-}
-
-inline void
-function::add_assignment_op (lvalue lvalue,
- enum gcc_jit_binary_op op,
- rvalue rvalue,
- location loc)
+block::add_eval (rvalue rvalue,
+ location loc)
{
- gcc_jit_function_add_assignment_op (get_inner_function (),
- loc.get_inner_location (),
- lvalue.get_inner_lvalue (),
- op,
- rvalue.get_inner_rvalue ());
+ gcc_jit_block_add_eval (get_inner_block (),
+ loc.get_inner_location (),
+ rvalue.get_inner_rvalue ());
}
inline void
-function::add_comment (const std::string &text,
+block::add_assignment (lvalue lvalue,
+ rvalue rvalue,
location loc)
{
- gcc_jit_function_add_comment (get_inner_function (),
+ gcc_jit_block_add_assignment (get_inner_block (),
loc.get_inner_location (),
- text.c_str ());
+ lvalue.get_inner_lvalue (),
+ rvalue.get_inner_rvalue ());
}
inline void
-function::add_conditional (rvalue boolval,
- label on_true,
- label on_false,
- location loc)
-{
- gcc_jit_function_add_conditional (get_inner_function (),
- loc.get_inner_location (),
- boolval.get_inner_rvalue (),
- on_true.get_inner_label (),
- on_false.get_inner_label ());
-}
-
-inline label
-function::add_label (const std::string &name,
- location loc)
+block::add_assignment_op (lvalue lvalue,
+ enum gcc_jit_binary_op op,
+ rvalue rvalue,
+ location loc)
{
- return label (gcc_jit_function_add_label (get_inner_function (),
- loc.get_inner_location (),
- name.c_str ()));
+ gcc_jit_block_add_assignment_op (get_inner_block (),
+ loc.get_inner_location (),
+ lvalue.get_inner_lvalue (),
+ op,
+ rvalue.get_inner_rvalue ());
}
-inline label
-function::add_label (location loc)
+inline void
+block::add_comment (const std::string &text,
+ location loc)
{
- return label (gcc_jit_function_add_label (get_inner_function (),
- loc.get_inner_location (),
- NULL));
+ gcc_jit_block_add_comment (get_inner_block (),
+ loc.get_inner_location (),
+ text.c_str ());
}
inline void
-function::place_forward_label (label lab,
- location loc)
+block::end_with_conditional (rvalue boolval,
+ block on_true,
+ block on_false,
+ location loc)
{
- gcc_jit_function_place_forward_label (get_inner_function (),
- loc.get_inner_location (),
- lab.get_inner_label ());
+ gcc_jit_block_end_with_conditional (get_inner_block (),
+ loc.get_inner_location (),
+ boolval.get_inner_rvalue (),
+ on_true.get_inner_block (),
+ on_false.get_inner_block ());
}
inline void
-function::add_jump (label target,
- location loc)
+block::end_with_jump (block target,
+ location loc)
{
- gcc_jit_function_add_jump (get_inner_function (),
- loc.get_inner_location (),
- target.get_inner_label ());
+ gcc_jit_block_end_with_jump (get_inner_block (),
+ loc.get_inner_location (),
+ target.get_inner_block ());
}
inline void
-function::add_return (rvalue rvalue,
- location loc)
+block::end_with_return (rvalue rvalue,
+ location loc)
{
- gcc_jit_function_add_return (get_inner_function (),
- loc.get_inner_location (),
- rvalue.get_inner_rvalue ());
+ gcc_jit_block_end_with_return (get_inner_block (),
+ loc.get_inner_location (),
+ rvalue.get_inner_rvalue ());
}
inline void
-function::add_return (location loc)
+block::end_with_return (location loc)
{
- gcc_jit_function_add_void_return (get_inner_function (),
- loc.get_inner_location ());
+ gcc_jit_block_end_with_void_return (get_inner_block (),
+ loc.get_inner_location ());
}
inline rvalue
-function::add_call (function other,
- location loc)
+block::add_call (function other,
+ location loc)
{
rvalue c = get_context ().new_call (other, loc);
add_eval (c);
return c;
}
inline rvalue
-function::add_call (function other,
- rvalue arg0,
- location loc)
+block::add_call (function other,
+ rvalue arg0,
+ location loc)
{
rvalue c = get_context ().new_call (other, arg0, loc);
add_eval (c);
return c;
}
inline rvalue
-function::add_call (function other,
- rvalue arg0, rvalue arg1,
- location loc)
+block::add_call (function other,
+ rvalue arg0, rvalue arg1,
+ location loc)
{
rvalue c = get_context ().new_call (other, arg0, arg1, loc);
add_eval (c);
return c;
}
inline rvalue
-function::add_call (function other,
- rvalue arg0, rvalue arg1, rvalue arg2,
- location loc)
+block::add_call (function other,
+ rvalue arg0, rvalue arg1, rvalue arg2,
+ location loc)
{
rvalue c = get_context ().new_call (other, arg0, arg1, arg2, loc);
add_eval (c);
@@ -1279,17 +1247,17 @@ function::operator() (rvalue arg0, rvalue arg1,
loc);
}
-// class label
-inline label::label () : object (NULL) {}
-inline label::label (gcc_jit_label *inner)
- : object (gcc_jit_label_as_object (inner))
+// class block
+inline block::block () : object (NULL) {}
+inline block::block (gcc_jit_block *inner)
+ : object (gcc_jit_block_as_object (inner))
{}
-inline gcc_jit_label *
-label::get_inner_label () const
+inline gcc_jit_block *
+block::get_inner_block () const
{
/* Manual downcast: */
- return reinterpret_cast<gcc_jit_label *> (get_inner_object ());
+ return reinterpret_cast<gcc_jit_block *> (get_inner_object ());
}
// class rvalue
@@ -56,7 +56,7 @@ struct gcc_jit_function : public gcc::jit::recording::function
{
};
-struct gcc_jit_label : public gcc::jit::recording::label
+struct gcc_jit_block : public gcc::jit::recording::block
{
};
@@ -72,10 +72,6 @@ struct gcc_jit_param : public gcc::jit::recording::param
{
};
-struct gcc_jit_loop : public gcc::jit::recording::loop
-{
-};
-
/**********************************************************************
Error-handling.
@@ -204,22 +200,28 @@ struct gcc_jit_loop : public gcc::jit::recording::loop
} \
JIT_END_STMT
-/* Check that FUNC is non-NULL, and that it's OK to add statements to
+/* Check that BLOCK is non-NULL, and that it's OK to add statements to
it. */
-#define RETURN_IF_NOT_FUNC_DEFINITION(FUNC) \
+#define RETURN_IF_NOT_VALID_BLOCK(BLOCK) \
JIT_BEGIN_STMT \
- RETURN_IF_FAIL ((FUNC), NULL, "NULL function"); \
- RETURN_IF_FAIL ((FUNC)->get_kind () != GCC_JIT_FUNCTION_IMPORTED, \
- NULL, \
- "Cannot add code to an imported function"); \
+ RETURN_IF_FAIL ((BLOCK), NULL, "NULL block"); \
+ RETURN_IF_FAIL_PRINTF2 ( \
+ !(BLOCK)->has_been_terminated (), \
+ (BLOCK)->get_context (), \
+ "adding to terminated block: %s (already terminated by: %s)", \
+ (BLOCK)->get_debug_string (), \
+ (BLOCK)->get_last_statement ()->get_debug_string ()); \
JIT_END_STMT
-#define RETURN_NULL_IF_NOT_FUNC_DEFINITION(FUNC) \
+#define RETURN_NULL_IF_NOT_VALID_BLOCK(BLOCK) \
JIT_BEGIN_STMT \
- RETURN_NULL_IF_FAIL ((FUNC), NULL, "NULL function"); \
- RETURN_NULL_IF_FAIL ((FUNC)->get_kind () != GCC_JIT_FUNCTION_IMPORTED,\
- NULL, \
- "Cannot add code to an imported function"); \
+ RETURN_NULL_IF_FAIL ((BLOCK), NULL, "NULL block"); \
+ RETURN_NULL_IF_FAIL_PRINTF2 ( \
+ !(BLOCK)->has_been_terminated (), \
+ (BLOCK)->get_context (), \
+ "adding to terminated block: %s (already terminated by: %s)", \
+ (BLOCK)->get_debug_string (), \
+ (BLOCK)->get_last_statement ()->get_debug_string ()); \
JIT_END_STMT
static void
@@ -568,22 +570,25 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
return static_cast <gcc_jit_param *> (func->get_param (index));
}
-gcc_jit_label*
-gcc_jit_function_new_forward_label (gcc_jit_function *func,
- const char *name)
+gcc_jit_block*
+gcc_jit_function_new_block (gcc_jit_function *func,
+ const char *name)
{
RETURN_NULL_IF_FAIL (func, NULL, "NULL function");
+ RETURN_NULL_IF_FAIL (func->get_kind () != GCC_JIT_FUNCTION_IMPORTED,
+ func->get_context (),
+ "cannot add block to an imported function");
/* name can be NULL. */
- return (gcc_jit_label *)func->new_forward_label (name);
+ return (gcc_jit_block *)func->new_block (name);
}
gcc_jit_object *
-gcc_jit_label_as_object (gcc_jit_label *label)
+gcc_jit_block_as_object (gcc_jit_block *block)
{
- RETURN_NULL_IF_FAIL (label, NULL, "NULL label");
+ RETURN_NULL_IF_FAIL (block, NULL, "NULL block");
- return static_cast <gcc_jit_object *> (label->as_object ());
+ return static_cast <gcc_jit_object *> (block->as_object ());
}
gcc_jit_lvalue *
@@ -895,6 +900,9 @@ gcc_jit_rvalue_dereference_field (gcc_jit_rvalue *ptr,
RETURN_NULL_IF_FAIL (field, NULL, "NULL field");
gcc::jit::recording::type *underlying_type =
ptr->get_type ()->dereference ();
+ 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_NULL_IF_FAIL_PRINTF3 (
underlying_type, ptr->m_ctxt,
"dereference of non-pointer %s (type: %s) when accessing ->%s",
@@ -956,49 +964,26 @@ gcc_jit_function_new_local (gcc_jit_function *func,
return (gcc_jit_lvalue *)func->new_local (loc, type, name);
}
-gcc_jit_label *
-gcc_jit_function_add_label (gcc_jit_function *func,
- gcc_jit_location *loc,
- const char *name)
-{
- RETURN_NULL_IF_NOT_FUNC_DEFINITION (func);
- /* loc and name can be NULL. */
-
- return (gcc_jit_label *)func->add_label (loc, name);
-}
-
void
-gcc_jit_function_place_forward_label (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_label *lab)
-{
- RETURN_IF_NOT_FUNC_DEFINITION (func);
- gcc::jit::recording::context *ctxt = func->m_ctxt;
- RETURN_IF_FAIL (lab, ctxt, "NULL label");
-
- func->place_forward_label (loc, lab);
-}
-
-void
-gcc_jit_function_add_eval (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_rvalue *rvalue)
+gcc_jit_block_add_eval (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue)
{
- RETURN_IF_NOT_FUNC_DEFINITION (func);
- gcc::jit::recording::context *ctxt = func->m_ctxt;
+ RETURN_IF_NOT_VALID_BLOCK (block);
+ gcc::jit::recording::context *ctxt = block->get_context ();
RETURN_IF_FAIL (rvalue, ctxt, "NULL rvalue");
- return func->add_eval (loc, rvalue);
+ return block->add_eval (loc, rvalue);
}
void
-gcc_jit_function_add_assignment (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_lvalue *lvalue,
- gcc_jit_rvalue *rvalue)
+gcc_jit_block_add_assignment (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_lvalue *lvalue,
+ gcc_jit_rvalue *rvalue)
{
- RETURN_IF_NOT_FUNC_DEFINITION (func);
- gcc::jit::recording::context *ctxt = func->m_ctxt;
+ RETURN_IF_NOT_VALID_BLOCK (block);
+ gcc::jit::recording::context *ctxt = block->get_context ();
RETURN_IF_FAIL (lvalue, ctxt, "NULL lvalue");
RETURN_IF_FAIL (rvalue, ctxt, "NULL rvalue");
RETURN_IF_FAIL_PRINTF4 (
@@ -1012,23 +997,23 @@ gcc_jit_function_add_assignment (gcc_jit_function *func,
rvalue->get_debug_string (),
rvalue->get_type ()->get_debug_string ());
- return func->add_assignment (loc, lvalue, rvalue);
+ return block->add_assignment (loc, lvalue, rvalue);
}
void
-gcc_jit_function_add_assignment_op (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_lvalue *lvalue,
- enum gcc_jit_binary_op op,
- gcc_jit_rvalue *rvalue)
+gcc_jit_block_add_assignment_op (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_lvalue *lvalue,
+ enum gcc_jit_binary_op op,
+ gcc_jit_rvalue *rvalue)
{
- RETURN_IF_NOT_FUNC_DEFINITION (func);
- gcc::jit::recording::context *ctxt = func->m_ctxt;
+ RETURN_IF_NOT_VALID_BLOCK (block);
+ gcc::jit::recording::context *ctxt = block->get_context ();
RETURN_IF_FAIL (lvalue, ctxt, "NULL lvalue");
/* FIXME: op is checked by new_binary_op */
RETURN_IF_FAIL (rvalue, ctxt, "NULL rvalue");
- return func->add_assignment_op (loc, lvalue, op, rvalue);
+ return block->add_assignment_op (loc, lvalue, op, rvalue);
}
static bool
@@ -1041,14 +1026,14 @@ is_bool (gcc_jit_rvalue *boolval)
}
void
-gcc_jit_function_add_conditional (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_rvalue *boolval,
- gcc_jit_label *on_true,
- gcc_jit_label *on_false)
+gcc_jit_block_end_with_conditional (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *boolval,
+ gcc_jit_block *on_true,
+ gcc_jit_block *on_false)
{
- RETURN_IF_NOT_FUNC_DEFINITION (func);
- gcc::jit::recording::context *ctxt = func->m_ctxt;
+ RETURN_IF_NOT_VALID_BLOCK (block);
+ gcc::jit::recording::context *ctxt = block->get_context ();
RETURN_IF_FAIL (boolval, ctxt, "NULL boolval");
RETURN_IF_FAIL_PRINTF2 (
is_bool (boolval), ctxt,
@@ -1056,42 +1041,73 @@ gcc_jit_function_add_conditional (gcc_jit_function *func,
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_IF_FAIL (on_true, ctxt, "NULL on_false");
+ RETURN_IF_FAIL_PRINTF4 (
+ block->get_function () == on_true->get_function (),
+ ctxt,
+ "\"on_true\" block is not in same function:"
+ " source block %s is in function %s"
+ " whereas target block %s is in function %s",
+ block->get_debug_string (),
+ block->get_function ()->get_debug_string (),
+ on_true->get_debug_string (),
+ on_true->get_function ()->get_debug_string ());
+ RETURN_IF_FAIL_PRINTF4 (
+ block->get_function () == on_false->get_function (),
+ ctxt,
+ "\"on_false\" block is not in same function:"
+ " source block %s is in function %s"
+ " whereas target block %s is in function %s",
+ block->get_debug_string (),
+ block->get_function ()->get_debug_string (),
+ on_false->get_debug_string (),
+ on_false->get_function ()->get_debug_string ());
- return func->add_conditional (loc, boolval, on_true, on_false);
+ return block->end_with_conditional (loc, boolval, on_true, on_false);
}
void
-gcc_jit_function_add_comment (gcc_jit_function *func,
- gcc_jit_location *loc,
- const char *text)
+gcc_jit_block_add_comment (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ const char *text)
{
- RETURN_IF_NOT_FUNC_DEFINITION (func);
- gcc::jit::recording::context *ctxt = func->m_ctxt;
+ RETURN_IF_NOT_VALID_BLOCK (block);
+ gcc::jit::recording::context *ctxt = block->get_context ();
RETURN_IF_FAIL (text, ctxt, "NULL text");
- func->add_comment (loc, text);
+ block->add_comment (loc, text);
}
void
-gcc_jit_function_add_jump (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_label *target)
+gcc_jit_block_end_with_jump (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_block *target)
{
- RETURN_IF_NOT_FUNC_DEFINITION (func);
- gcc::jit::recording::context *ctxt = func->m_ctxt;
+ RETURN_IF_NOT_VALID_BLOCK (block);
+ gcc::jit::recording::context *ctxt = block->get_context ();
RETURN_IF_FAIL (target, ctxt, "NULL target");
+ RETURN_IF_FAIL_PRINTF4 (
+ block->get_function () == target->get_function (),
+ ctxt,
+ "target block is not in same function:"
+ " source block %s is in function %s"
+ " whereas target block %s is in function %s",
+ block->get_debug_string (),
+ block->get_function ()->get_debug_string (),
+ target->get_debug_string (),
+ target->get_function ()->get_debug_string ());
- func->add_jump (loc, target);
+ block->end_with_jump (loc, target);
}
void
-gcc_jit_function_add_return (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_rvalue *rvalue)
+gcc_jit_block_end_with_return (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue)
{
- RETURN_IF_NOT_FUNC_DEFINITION (func);
- gcc::jit::recording::context *ctxt = func->m_ctxt;
+ RETURN_IF_NOT_VALID_BLOCK (block);
+ gcc::jit::recording::context *ctxt = block->get_context ();
+ gcc::jit::recording::function *func = block->get_function ();
RETURN_IF_FAIL (rvalue, ctxt, "NULL rvalue");
RETURN_IF_FAIL_PRINTF4 (
compatible_types (
@@ -1105,15 +1121,16 @@ gcc_jit_function_add_return (gcc_jit_function *func,
func->get_debug_string (),
func->get_return_type ()->get_debug_string ());
- return func->add_return (loc, rvalue);
+ return block->end_with_return (loc, rvalue);
}
void
-gcc_jit_function_add_void_return (gcc_jit_function *func,
- gcc_jit_location *loc)
+gcc_jit_block_end_with_void_return (gcc_jit_block *block,
+ gcc_jit_location *loc)
{
- RETURN_IF_NOT_FUNC_DEFINITION (func);
- gcc::jit::recording::context *ctxt = func->m_ctxt;
+ RETURN_IF_NOT_VALID_BLOCK (block);
+ gcc::jit::recording::context *ctxt = block->get_context ();
+ gcc::jit::recording::function *func = block->get_function ();
RETURN_IF_FAIL_PRINTF2 (
func->get_return_type () == ctxt->get_type (GCC_JIT_TYPE_VOID),
ctxt,
@@ -1122,81 +1139,7 @@ gcc_jit_function_add_void_return (gcc_jit_function *func,
func->get_debug_string (),
func->get_return_type ()->get_debug_string ());
- return func->add_return (loc, NULL);
-}
-
-gcc_jit_loop *
-gcc_jit_function_new_loop (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_rvalue *boolval)
-{
- RETURN_NULL_IF_NOT_FUNC_DEFINITION (func);
- 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);
-}
-
-gcc_jit_loop *
-gcc_jit_function_new_loop_over_range (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_lvalue *iteration_var,
- gcc_jit_rvalue *start_of_range,
- gcc_jit_rvalue *upper_bound_of_range,
- gcc_jit_rvalue *step)
-{
- RETURN_NULL_IF_NOT_FUNC_DEFINITION (func);
- gcc_jit_context *ctxt = static_cast <gcc_jit_context *> (func->m_ctxt);
- RETURN_NULL_IF_FAIL (iteration_var, ctxt, "NULL iteration_var");
- RETURN_NULL_IF_FAIL (upper_bound_of_range, ctxt,
- "NULL upper_bound_of_range");
- if (!start_of_range)
- start_of_range =
- gcc_jit_context_zero (ctxt,
- static_cast <gcc_jit_type *> (iteration_var->get_type ()));
-
- if (!step)
- step = gcc_jit_context_one (ctxt,
- static_cast <gcc_jit_type *> (iteration_var->get_type ()));
-
- /* "iteration_var = start_of_range;" */
- gcc_jit_function_add_assignment (func,
- loc,
- iteration_var,
- start_of_range);
-
- /* "(iteration_var < upper_bound_of_range)" */
- gcc_jit_rvalue *boolval =
- gcc_jit_context_new_comparison (ctxt,
- loc,
- GCC_JIT_COMPARISON_LT,
- gcc_jit_lvalue_as_rvalue (iteration_var),
- upper_bound_of_range);
-
- /* the += is added when loop_end is called. */
- return (gcc_jit_loop *)func->new_loop (loc, boolval, iteration_var, step);
-}
-
-gcc_jit_object *
-gcc_jit_loop_as_object (gcc_jit_loop *loop)
-{
- RETURN_NULL_IF_FAIL (loop, NULL, "NULL loop");
-
- return static_cast <gcc_jit_object *> (loop->as_object ());
-}
-
-void
-gcc_jit_loop_end (gcc_jit_loop *loop,
- gcc_jit_location *loc)
-{
- RETURN_IF_FAIL (loop, NULL, "NULL loop");
-
- loop->end (loc);
+ return block->end_with_return (loc, NULL);
}
/**********************************************************************
@@ -39,11 +39,10 @@ typedef struct gcc_jit_result gcc_jit_result;
+- gcc_jit_struct
+- gcc_jit_field
+- gcc_jit_function
- +- gcc_jit_label
+ +- gcc_jit_block
+- gcc_jit_rvalue
+- gcc_jit_lvalue
+- gcc_jit_param
- +- gcc_jit_loop
*/
typedef struct gcc_jit_object gcc_jit_object;
@@ -77,8 +76,23 @@ typedef struct gcc_jit_struct gcc_jit_struct;
linking to within the rest of the process. */
typedef struct gcc_jit_function gcc_jit_function;
-/* A gcc_jit_label is a jump target within a function, for control flow. */
-typedef struct gcc_jit_label gcc_jit_label;
+/* A gcc_jit_block encapsulates a "basic block" of statements within a
+ function (i.e. with one entry point and one exit point).
+
+ Every block within a function must be terminated with a conditional,
+ a branch, or a return.
+
+ The blocks within a function form a directed graph.
+
+ The entrypoint to the function is the first block created within
+ it.
+
+ All of the blocks in a function must be reachable via some path from
+ the first block.
+
+ It's OK to have more than one "return" from a function (i.e. multiple
+ blocks that terminate by returning). */
+typedef struct gcc_jit_block gcc_jit_block;
/* A gcc_jit_rvalue is an expression within your code, with some type. */
typedef struct gcc_jit_rvalue gcc_jit_rvalue;
@@ -93,10 +107,6 @@ typedef struct gcc_jit_lvalue gcc_jit_lvalue;
rvalue); use gcc_jit_param_as_lvalue to convert. */
typedef struct gcc_jit_param gcc_jit_param;
-/* A gcc_jit_loop is a pre-canned way of creating loops without needing
- to manually manage gcc_jit_label instances. */
-typedef struct gcc_jit_loop gcc_jit_loop;
-
/*
Acquire a JIT-compilation context.
@@ -269,11 +279,7 @@ gcc_jit_result_release (gcc_jit_result *result);
copied, so you don't need to keep them around. Note that this *isn't*
the case for other parts of the API.
- You create code by adding a sequence of statements to a function.
- Control flow is expressed using labels, rather than by explicitly
- managing blocks. If you have blocks, you can simply create labels
- for the start of each block. You can even create labels for every
- instruction in your language; unused labels will be optimized away.
+ You create code by adding a sequence of statements to blocks.
**********************************************************************/
/**********************************************************************
@@ -484,17 +490,18 @@ gcc_jit_function_as_object (gcc_jit_function *func);
extern gcc_jit_param *
gcc_jit_function_get_param (gcc_jit_function *func, int index);
-/* Create a label, to be placed later.
+/* Create a block.
The name can be NULL, or you can give it a meaningful name, which
- may show up in dumps of the internal representation. */
-extern gcc_jit_label *
-gcc_jit_function_new_forward_label (gcc_jit_function *func,
- const char *name);
+ may show up in dumps of the internal representation, and in error
+ messages. */
+extern gcc_jit_block *
+gcc_jit_function_new_block (gcc_jit_function *func,
+ const char *name);
-/* Upcasting from label to object. */
+/* Upcasting from block to object. */
extern gcc_jit_object *
-gcc_jit_label_as_object (gcc_jit_label *label);
+gcc_jit_block_as_object (gcc_jit_block *block);
/**********************************************************************
lvalues, rvalues and expressions.
@@ -744,9 +751,9 @@ gcc_jit_function_new_local (gcc_jit_function *func,
(void)expression;
*/
extern void
-gcc_jit_function_add_eval (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_rvalue *rvalue);
+gcc_jit_block_add_eval (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue);
/* Add evaluation of an rvalue, assigning the result to the given
lvalue.
@@ -756,10 +763,10 @@ gcc_jit_function_add_eval (gcc_jit_function *func,
lvalue = rvalue;
*/
extern void
-gcc_jit_function_add_assignment (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_lvalue *lvalue,
- gcc_jit_rvalue *rvalue);
+gcc_jit_block_add_assignment (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_lvalue *lvalue,
+ gcc_jit_rvalue *rvalue);
/* Add evaluation of an rvalue, using the result to modify an
lvalue.
@@ -771,11 +778,11 @@ gcc_jit_function_add_assignment (gcc_jit_function *func,
lvalue /= rvalue;
etc */
extern void
-gcc_jit_function_add_assignment_op (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_lvalue *lvalue,
- enum gcc_jit_binary_op op,
- gcc_jit_rvalue *rvalue);
+gcc_jit_block_add_assignment_op (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_lvalue *lvalue,
+ enum gcc_jit_binary_op op,
+ gcc_jit_rvalue *rvalue);
/* Add a no-op textual comment to the internal representation of the
code. It will be optimized away, but will be visible in the dumps
@@ -786,12 +793,12 @@ gcc_jit_function_add_assignment_op (gcc_jit_function *func,
and thus may be of use when debugging how your project's internal
representation gets converted to the libgccjit IR. */
extern void
-gcc_jit_function_add_comment (gcc_jit_function *func,
- gcc_jit_location *loc,
- const char *text);
+gcc_jit_block_add_comment (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ const char *text);
-/* Add evaluation of an rvalue, branching on the result to the
- appropriate label.
+/* Terminate a block by adding evaluation of an rvalue, branching on the
+ result to the appropriate successor block.
This is roughly equivalent to this C code:
@@ -800,119 +807,46 @@ gcc_jit_function_add_comment (gcc_jit_function *func,
else
goto on_false;
- on_true must be non-NULL.
-
- on_false may be NULL, in which case this is roughly equivalent to:
-
- if (boolval)
- goto on_true;
-*/
-extern void
-gcc_jit_function_add_conditional (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_rvalue *boolval,
- gcc_jit_label *on_true,
- gcc_jit_label *on_false);
-
-/* Add a label at the current location in the function.
-
- This is roughly equivalent to this C code:
-
- name:
-
- The name can be NULL, or you can give it a meaningful name, which
- may show up in dumps of the internal representation. */
-extern gcc_jit_label *
-gcc_jit_function_add_label (gcc_jit_function *func,
- gcc_jit_location *loc,
- const char *name);
-
-/* Place a pre-existing label at the current location in the function.
-
- This is roughly equivalent to this C code:
-
- name:
-
- The label must not have already been placed. */
+ block, boolval, on_true, and on_false must be non-NULL. */
extern void
-gcc_jit_function_place_forward_label (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_label *lab);
+gcc_jit_block_end_with_conditional (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *boolval,
+ gcc_jit_block *on_true,
+ gcc_jit_block *on_false);
-/* Add a jump from the current location in the function to the given
- label.
+/* Terminate a block by adding a jump to the given target block.
This is roughly equivalent to this C code:
goto target;
*/
extern void
-gcc_jit_function_add_jump (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_label *target);
+gcc_jit_block_end_with_jump (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_block *target);
-/* Add evaluation of an rvalue, returning the value.
+/* Terminate a block by adding evaluation of an rvalue, returning the value.
This is roughly equivalent to this C code:
return expression;
*/
extern void
-gcc_jit_function_add_return (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_rvalue *rvalue);
+gcc_jit_block_end_with_return (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue);
-/* Add a valueless return, for use within a function with
- "void" return type.
+/* Terminate a block by adding a valueless return, for use within a function
+ with "void" return type.
This is equivalent to this C code:
return;
*/
extern void
-gcc_jit_function_add_void_return (gcc_jit_function *func,
- gcc_jit_location *loc);
-
-/* Helper function for creating a loop:
- while (boolval)
- {
- BODY;
- }
-
- Statements will be added to the body of the loop until
- gcc_jit_loop_end is called. */
-extern gcc_jit_loop *
-gcc_jit_function_new_loop (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_rvalue *boolval);
-
-/* Helper function for creating a loop of this form:
- for (i = start_of_range; i < upper_bound_of_range; i += step)
- {
- BODY;
- }
-
- Statements will be added to the body of the loop until
- gcc_jit_loop_end is called.
-
- "start_of_range" can be NULL, in which case 0 is used.
- "upper_bound_of_range" must be non-NULL.
- "step" can be NULL, in which case 1 is used. */
-extern gcc_jit_loop *
-gcc_jit_function_new_loop_over_range (gcc_jit_function *func,
- gcc_jit_location *loc,
- gcc_jit_lvalue *iteration_var,
- gcc_jit_rvalue *start_of_range,
- gcc_jit_rvalue *upper_bound_of_range,
- gcc_jit_rvalue *step);
-
-/* Upcasting from loop to object. */
-extern gcc_jit_object *
-gcc_jit_loop_as_object (gcc_jit_loop *loop);
-
-extern void
-gcc_jit_loop_end (gcc_jit_loop *loop,
- gcc_jit_location *loc);
+gcc_jit_block_end_with_void_return (gcc_jit_block *block,
+ gcc_jit_location *loc);
/**********************************************************************
Nested contexts.
@@ -2,6 +2,15 @@
{
global:
# Keep this list sorted alphabetically:
+ gcc_jit_block_add_assignment;
+ gcc_jit_block_add_assignment_op;
+ gcc_jit_block_add_comment;
+ gcc_jit_block_add_eval;
+ gcc_jit_block_as_object;
+ gcc_jit_block_end_with_conditional;
+ gcc_jit_block_end_with_jump;
+ gcc_jit_block_end_with_return;
+ gcc_jit_block_end_with_void_return;
gcc_jit_context_acquire;
gcc_jit_context_compile;
gcc_jit_context_dump_to_file;
@@ -35,26 +44,11 @@
gcc_jit_context_set_str_option;
gcc_jit_context_zero;
gcc_jit_field_as_object;
- gcc_jit_function_add_assignment;
- gcc_jit_function_add_assignment_op;
- gcc_jit_function_add_comment;
- gcc_jit_function_add_conditional;
- gcc_jit_function_add_eval;
- gcc_jit_function_add_jump;
- gcc_jit_function_add_label;
- gcc_jit_function_add_return;
- gcc_jit_function_add_void_return;
gcc_jit_function_as_object;
gcc_jit_function_get_param;
- gcc_jit_function_new_forward_label;
+ gcc_jit_function_new_block;
gcc_jit_function_new_local;
- gcc_jit_function_new_loop;
- gcc_jit_function_new_loop_over_range;
- gcc_jit_function_place_forward_label;
- gcc_jit_label_as_object;
gcc_jit_location_as_object;
- gcc_jit_loop_as_object;
- gcc_jit_loop_end;
gcc_jit_lvalue_as_object;
gcc_jit_lvalue_as_rvalue;
gcc_jit_lvalue_access_field;
@@ -1,3 +1,50 @@
+2014-02-27 David Malcolm <dmalcolm@redhat.com>
+
+ * jit.dg/test-accessing-struct.c (create_code): Port to
+ block-based API.
+ * jit.dg/test-calling-external-function.c (create_code): Likewise.
+ * jit.dg/test-error-accessing-field-in-other-struct.c (create_code):
+ Likewise.
+ * jit.dg/test-error-call-with-mismatching-args.c (create_code):
+ Likewise.
+ * jit.dg/test-error-call-with-not-enough-args.c (create_code):
+ Likewise.
+ * jit.dg/test-error-call-with-too-many-args.c (create_code):
+ Likewise.
+ * jit.dg/test-error-dereference-field-of-non-pointer.c (create_code):
+ Likewise.
+ * jit.dg/test-error-dereference-read: Likewise.
+ * jit.dg/test-error-mismatching-types-in-assignment.c: Likewise.
+ * jit.dg/test-error-return-within-void-function.c: Likewise.
+ * jit.dg/test-expressions.c: Likewise.
+ * jit.dg/test-factorial.c: Likewise.
+ * jit.dg/test-functions.c: Likewise.
+ * jit.dg/test-fuzzer.c: Likewise.
+ * jit.dg/test-hello-world.c (create_code): Likewise.
+ * jit.dg/test-nested-contexts.c: Likewise.
+ * jit.dg/test-operator-overloading.cc: Likewise.
+ * jit.dg/test-quadratic.c: Likewise.
+ * jit.dg/test-quadratic.cc: Likewise.
+ * jit.dg/test-reading-struct.c (create_code): Likewise.
+ * jit.dg/test-string-literal.c (create_code): Likewise.
+ * jit.dg/test-sum-of-squares.c (create_code): Likewise.
+ * jit.dg/test-types.c (create_code): Likewise.
+ * jit.dg/test-using-global.c (create_code): Likewise.
+
+ * jit.dg/test-arrays.c (create_code): Likewise, eliminating use of
+ loop API.
+ * jit.dg/test-dot-product.c (create_code): Likewise.
+ * jit.dg/test-linked-list.c (create_code): Likewise.
+
+ * jit.dg/test-error-adding-to-terminated-block.c: New testcase.
+ * jit.dg/test-error-block-in-wrong-function.c: Likewise.
+ * jit.dg/test-error-missing-return.c: Likewise.
+ * jit.dg/test-error-unreachable-block.c: Likewise.
+ * jit.dg/test-error-unterminated-block.c: Likewise.
+
+ * jit.dg/test-error-label-already-placed.c: Delete obsolete testcase.
+ * jit.dg/test-error-unplaced-label.c: Likewise.
+
2014-02-25 David Malcolm <dmalcolm@redhat.com>
* jit.dg/test-functions.c (create_use_of_void_return): New, to add
@@ -76,14 +76,16 @@ create_code (gcc_jit_context *ctxt, void *user_data)
y)));
/* f->z = ... */
- gcc_jit_function_add_assignment (
- test_fn,
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+ gcc_jit_block_add_assignment (
+ block,
NULL,
gcc_jit_rvalue_dereference_field (
gcc_jit_param_as_rvalue (param_f),
NULL,
z),
sum);
+ gcc_jit_block_end_with_void_return (block, NULL);
}
void
@@ -74,27 +74,40 @@ create_code (gcc_jit_context *ctxt, void *user_data)
1, ¶m_ah,
0);
+ gcc_jit_block *initial = gcc_jit_function_new_block (func, "initial");
+ gcc_jit_block *loop_test = gcc_jit_function_new_block (func, "loop_test");
+ gcc_jit_block *loop_body = gcc_jit_function_new_block (func, "loop_body");
+ gcc_jit_block *final = gcc_jit_function_new_block (func, "final");
+
/* "ah->m_before = 4.0f;" */
- gcc_jit_function_add_assignment (
- func, NULL,
+ gcc_jit_block_add_assignment (
+ initial, NULL,
gcc_jit_rvalue_dereference_field (
gcc_jit_param_as_rvalue (param_ah), NULL, field_m_before),
gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 4));
- gcc_jit_function_add_comment (func, NULL,
- "for i in 0 to (ARRAY_SIZE - 1):");
+ gcc_jit_block_add_comment (initial, NULL,
+ "for i in 0 to (ARRAY_SIZE - 1):");
gcc_jit_lvalue *i =
gcc_jit_function_new_local (func, NULL, int_type, "i");
- gcc_jit_loop *loop =
- gcc_jit_function_new_loop_over_range (
- func, NULL, i,
- NULL,
- gcc_jit_context_new_rvalue_from_int (ctxt, int_type, ARRAY_SIZE),
- NULL);
+ gcc_jit_block_add_assignment (initial, NULL,
+ i,
+ gcc_jit_context_zero (ctxt, int_type));
- gcc_jit_function_add_comment (func, NULL, "ah->m_ints[i] = (i * i);");
- gcc_jit_function_add_assignment (
- func, NULL,
+ gcc_jit_block_end_with_jump (initial, NULL, loop_test);
+
+ gcc_jit_block_end_with_conditional (loop_test, NULL,
+ gcc_jit_context_new_comparison (
+ ctxt, NULL,
+ GCC_JIT_COMPARISON_LT,
+ gcc_jit_lvalue_as_rvalue (i),
+ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, ARRAY_SIZE)),
+ loop_body,
+ final);
+
+ gcc_jit_block_add_comment (loop_body, NULL, "ah->m_ints[i] = (i * i);");
+ gcc_jit_block_add_assignment (
+ loop_body, NULL,
gcc_jit_context_new_array_access (
ctxt, NULL,
gcc_jit_lvalue_as_rvalue (gcc_jit_rvalue_dereference_field (
@@ -109,14 +122,22 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_lvalue_as_rvalue (i),
gcc_jit_lvalue_as_rvalue (i)));
- gcc_jit_loop_end (loop, NULL);
+ /* "i++" */
+ gcc_jit_block_add_assignment_op (
+ loop_body, NULL,
+ i,
+ GCC_JIT_BINARY_OP_PLUS,
+ gcc_jit_context_one (ctxt, int_type));
+
+ gcc_jit_block_end_with_jump (loop_body, NULL, loop_test);
/* ah->m_after = 2.0f; */
- gcc_jit_function_add_assignment (
- func, NULL,
+ gcc_jit_block_add_assignment (
+ final, NULL,
gcc_jit_rvalue_dereference_field (
gcc_jit_param_as_rvalue (param_ah), NULL, field_m_after),
gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 2));
+ gcc_jit_block_end_with_void_return (final, NULL);
}
@@ -73,13 +73,14 @@ create_code (gcc_jit_context *ctxt, void *user_data)
ctxt,
int_type,
(i + 3) ));
-
- gcc_jit_function_add_eval (
- test_fn, NULL,
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+ gcc_jit_block_add_eval (
+ block, NULL,
gcc_jit_context_new_call (ctxt,
NULL,
called_fn,
3, args));
+ gcc_jit_block_end_with_void_return (block, NULL);
}
static int called_with[3];
@@ -42,30 +42,42 @@ create_code (gcc_jit_context *ctxt, void *user_data)
"my_dot_product",
3, params, 0);
+ gcc_jit_block *initial = gcc_jit_function_new_block (func, "initial");
+ gcc_jit_block *loop_test = gcc_jit_function_new_block (func, "loop_test");
+ gcc_jit_block *loop_body = gcc_jit_function_new_block (func, "loop_body");
+ gcc_jit_block *final = gcc_jit_function_new_block (func, "final");
+
/* Build: "double result = 0.;" */
gcc_jit_lvalue *result =
gcc_jit_function_new_local (func, NULL, val_type, "result");
- gcc_jit_function_add_assignment (func, NULL,
- result,
- gcc_jit_context_zero (ctxt, val_type));
+ gcc_jit_block_add_assignment (initial, NULL,
+ result, gcc_jit_context_zero (ctxt, val_type));
/* Build: "for (int i = 0; i < n; i++)" */
gcc_jit_lvalue *i =
gcc_jit_function_new_local (func, NULL, int_type, "i");
- gcc_jit_function_add_assignment (func, NULL,
+ gcc_jit_block_add_assignment (initial, NULL,
i, gcc_jit_context_zero (ctxt, int_type));
- gcc_jit_loop *loop = gcc_jit_function_new_loop (func, NULL,
+
+ gcc_jit_block_end_with_jump (initial, NULL, loop_test);
+
+ gcc_jit_block_end_with_conditional (
+ loop_test, NULL,
+
/* (i < n) */
gcc_jit_context_new_comparison (
ctxt, NULL,
GCC_JIT_COMPARISON_LT,
gcc_jit_lvalue_as_rvalue (i),
- gcc_jit_param_as_rvalue (param_n)));
+ gcc_jit_param_as_rvalue (param_n)),
+
+ loop_body,
+ final);
/* Build: "result += a[i] * b[i];" */
- gcc_jit_function_add_assignment_op (
- func, NULL,
+ gcc_jit_block_add_assignment_op (
+ loop_body, NULL,
result,
GCC_JIT_BINARY_OP_PLUS,
gcc_jit_context_new_binary_op (
@@ -84,17 +96,17 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_lvalue_as_rvalue (i)))));
/* Build: "i++" */
- gcc_jit_function_add_assignment_op (
- func, NULL,
+ gcc_jit_block_add_assignment_op (
+ loop_body, NULL,
i,
GCC_JIT_BINARY_OP_PLUS,
gcc_jit_context_one (ctxt, int_type));
- gcc_jit_loop_end (loop, NULL);
+ gcc_jit_block_end_with_jump (loop_body, NULL, loop_test);
/* Build: "return result;" */
- gcc_jit_function_add_return (
- func,
+ gcc_jit_block_end_with_return (
+ final,
NULL,
gcc_jit_lvalue_as_rvalue (result));
}
@@ -60,11 +60,8 @@ create_code (gcc_jit_context *ctxt, void *user_data)
int_type,
"q");
/* 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_struct *struct_bar =
- gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, bar_fields);
-#endif
+ (void)gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, bar_fields);
gcc_jit_type *foo_ptr =
gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_foo));
@@ -95,10 +92,13 @@ create_code (gcc_jit_context *ctxt, void *user_data)
NULL,
q));
- gcc_jit_function_add_assignment (
- test_fn,
+ gcc_jit_block *block =
+ gcc_jit_function_new_block (test_fn, NULL);
+ gcc_jit_block_add_assignment (
+ block,
NULL,
lvalue, rvalue);
+ gcc_jit_block_end_with_void_return (block, NULL);
}
void
new file mode 100644
@@ -0,0 +1,48 @@
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ void
+ test_fn ()
+ {
+ return;
+ return;
+ }
+ */
+ gcc_jit_type *void_t =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+
+ /* Build the test_fn. */
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_t,
+ "test_fn",
+ 0, NULL,
+ 0);
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (test_fn, "initial");
+
+ gcc_jit_block_end_with_void_return (initial, NULL);
+ /* Error: "initial" has already been terminated. */
+ gcc_jit_block_end_with_void_return (initial, NULL);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "gcc_jit_block_end_with_void_return:"
+ " adding to terminated block:"
+ " initial (already terminated by: return;)");
+}
new file mode 100644
@@ -0,0 +1,65 @@
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ void
+ test_fn ()
+ {
+ goto label;
+ }
+
+ void
+ other_fn ()
+ {
+ label:
+ };
+ where the destination block is in another function.
+ */
+ gcc_jit_type *void_t =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+
+ /* Build the test_fn. */
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_t,
+ "test_fn",
+ 0, NULL,
+ 0);
+ /* Build the other_fn. */
+ gcc_jit_function *other_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_t,
+ "other_fn",
+ 0, NULL,
+ 0);
+
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (test_fn, "initial");
+ gcc_jit_block *block_within_other_fn =
+ gcc_jit_function_new_block (other_fn, "block_within_other_fn");
+
+ gcc_jit_block_end_with_jump (initial, NULL, block_within_other_fn);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "gcc_jit_block_end_with_jump:"
+ " target block is not in same function:"
+ " source block initial is in function test_fn"
+ " whereas target block block_within_other_fn"
+ " is in function other_fn");
+}
@@ -60,13 +60,15 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_rvalue *arg =
gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 42);
- gcc_jit_function_add_eval (
- test_fn, NULL,
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+ gcc_jit_block_add_eval (
+ block, NULL,
gcc_jit_context_new_call (ctxt,
NULL,
called_fn,
1, &arg));
/* the above has the wrong type for argument 1. */
+ gcc_jit_block_end_with_void_return (block, NULL);
}
void
@@ -54,15 +54,16 @@ create_code (gcc_jit_context *ctxt, void *user_data)
"test_caller",
0, NULL,
0);
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
/* called_function (); */
- gcc_jit_function_add_eval (
- test_fn, NULL,
+ gcc_jit_block_add_eval (
+ block, NULL,
gcc_jit_context_new_call (ctxt,
NULL,
called_fn,
0, NULL));
/* the above has the wrong arg count. */
-
+ gcc_jit_block_end_with_void_return (block, NULL);
}
extern void
@@ -55,16 +55,17 @@ create_code (gcc_jit_context *ctxt, void *user_data)
"test_caller",
1, ¶m_a,
0);
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
/* called_function (a); */
gcc_jit_rvalue *arg = gcc_jit_param_as_rvalue (param_a);
- gcc_jit_function_add_eval (
- test_fn, NULL,
+ gcc_jit_block_add_eval (
+ block, NULL,
gcc_jit_context_new_call (ctxt,
NULL,
called_fn,
1, &arg));
/* the above has the wrong arg count. */
-
+ gcc_jit_block_end_with_void_return (block, NULL);
}
extern void
@@ -56,6 +56,8 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_struct_as_type (struct_foo),
"tmp");
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+
/* Erroneous: tmp->x = ... */
gcc_jit_lvalue *lvalue =
gcc_jit_rvalue_dereference_field (
@@ -71,10 +73,12 @@ create_code (gcc_jit_context *ctxt, void *user_data)
NULL,
y));
- gcc_jit_function_add_assignment (
- test_fn,
+ gcc_jit_block_add_assignment (
+ block,
NULL,
lvalue, rvalue);
+
+ gcc_jit_block_end_with_void_return (block, NULL);
}
void
@@ -31,9 +31,10 @@ create_code (gcc_jit_context *ctxt, void *user_data)
"test_bogus_dereference_read",
1, ¶m_i,
0);
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
/* Erroneous: "return *i;" */
- gcc_jit_function_add_return (
- test_fn,
+ gcc_jit_block_end_with_return (
+ block,
NULL,
gcc_jit_lvalue_as_rvalue (
gcc_jit_rvalue_dereference (
deleted file mode 100644
@@ -1,59 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "libgccjit.h"
-
-#include "harness.h"
-
-void
-create_code (gcc_jit_context *ctxt, void *user_data)
-{
- /* Let's try to inject the equivalent of:
-
- int
- test_fn (void)
- {
- foo:
- return 0;
-
- foo:
- return 1;
-
- }
-
- and verify that the 2nd attempt to place the label fails.
- */
- gcc_jit_type *int_type =
- gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
-
- gcc_jit_function *func =
- gcc_jit_context_new_function (ctxt, NULL,
- GCC_JIT_FUNCTION_EXPORTED,
- int_type,
- "test_fn",
- 0, NULL, 0);
-
- /* Create forward label: */
- gcc_jit_label *label =
- gcc_jit_function_new_forward_label (func, "foo");
-
- gcc_jit_function_place_forward_label (func, NULL, label);
- gcc_jit_function_add_return (func, NULL,
- gcc_jit_context_zero (ctxt, int_type));
-
- /* Erroneous 2nd placement of label: */
- gcc_jit_function_place_forward_label (func, NULL, label);
- gcc_jit_function_add_return (func, NULL,
- gcc_jit_context_one (ctxt, int_type));
-}
-
-void
-verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
-{
- CHECK_VALUE (result, NULL);
-
- /* Verify that the correct error message was emitted. */
- CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
- "label foo has already been placed");
-}
@@ -36,11 +36,14 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_function_new_local (
test_fn, NULL, int_type, "i");
- gcc_jit_function_add_assignment (
- test_fn, NULL,
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+
+ gcc_jit_block_add_assignment (
+ block, NULL,
i, /* of type int */
gcc_jit_context_new_string_literal (
ctxt, "this is not an int"));
+ gcc_jit_block_end_with_void_return (block, NULL);
}
void
@@ -50,7 +53,7 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
/* Verify that the correct error message was emitted. */
CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
- "gcc_jit_function_add_assignment:"
+ "gcc_jit_block_add_assignment:"
" mismatching types:"
" assignment to i (type: int)"
" from \"this is not an int\" (type: const char *)");
new file mode 100644
@@ -0,0 +1,40 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ int
+ test_fn ()
+ {
+ }
+ and verify that the API complains about the lack of
+ a returned value.
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+ (void)gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "test_fn",
+ 0, NULL,
+ 0);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ /* Verify that the correct error message was emitted. */
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "function test_fn returns non-void (type: int)"
+ " but has no blocks");
+}
+
@@ -30,9 +30,11 @@ create_code (gcc_jit_context *ctxt, void *user_data)
"test_fn",
0, NULL,
0);
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+
/* "return 42;" (i.e. non-void) */
- gcc_jit_function_add_return (
- test_fn, NULL,
+ gcc_jit_block_end_with_return (
+ block, NULL,
gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 42));
}
@@ -45,7 +47,7 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
/* Verify that the correct error message was emitted. */
CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
- "gcc_jit_function_add_return:"
+ "gcc_jit_block_end_with_return:"
" mismatching types: return of (int)42 (type: int)"
" in function test_fn (return type: void)");
}
deleted file mode 100644
@@ -1,50 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "libgccjit.h"
-
-#include "harness.h"
-
-void
-create_code (gcc_jit_context *ctxt, void *user_data)
-{
- /* Let's try to inject the equivalent of:
-
- void
- test_fn (void)
- {
- goto foo;
- }
-
- and verify that an error is issued due to label "foo" not being
- placed.
- */
- gcc_jit_type *void_type =
- gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
-
- gcc_jit_function *func =
- gcc_jit_context_new_function (ctxt, NULL,
- GCC_JIT_FUNCTION_EXPORTED,
- void_type,
- "test_fn",
- 0, NULL, 0);
-
- /* Create forward label: */
- gcc_jit_label *unplaced_label =
- gcc_jit_function_new_forward_label (func, "foo");
-
- /* Use it (but never place it): */
- gcc_jit_function_add_jump (func, NULL, unplaced_label);
-}
-
-void
-verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
-{
- CHECK_VALUE (result, NULL);
-
- /* Verify that the correct error message was emitted. */
- CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
- "unplaced label within test_fn: foo");
-}
-
new file mode 100644
@@ -0,0 +1,50 @@
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ void
+ test_fn ()
+ {
+ return;
+
+ return;
+ }
+ where the second block is unreachable.
+ */
+ gcc_jit_type *void_t =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+
+ /* Build the test_fn. */
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_t,
+ "test_fn",
+ 0, NULL,
+ 0);
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (test_fn, "a");
+ gcc_jit_block *unreachable =
+ gcc_jit_function_new_block (test_fn, "b");
+
+ gcc_jit_block_end_with_void_return (initial, NULL);
+
+ gcc_jit_block_end_with_void_return (unreachable, NULL);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "unreachable block: b");
+}
new file mode 100644
@@ -0,0 +1,42 @@
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ void
+ test_fn ()
+ {
+ initial:
+ }
+ with an unterminated block.
+ */
+ gcc_jit_type *void_t =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+
+ /* Build the test_fn. */
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_t,
+ "test_fn",
+ 0, NULL,
+ 0);
+ (void)gcc_jit_function_new_block (test_fn, "initial");
+ /* Error: the above block isn't terminated. */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "unterminated block in test_fn: initial");
+}
@@ -41,7 +41,8 @@ make_test_of_unary_op (gcc_jit_context *ctxt,
type,
gcc_jit_param_as_rvalue (param_a));
- gcc_jit_function_add_return (test_fn, NULL, unary_op);
+ gcc_jit_block *initial = gcc_jit_function_new_block (test_fn, "initial");
+ gcc_jit_block_end_with_return (initial, NULL, unary_op);
return gcc_jit_object_get_debug_string (
gcc_jit_rvalue_as_object (unary_op));
@@ -142,7 +143,8 @@ make_test_of_binary_op (gcc_jit_context *ctxt,
gcc_jit_param_as_rvalue (param_a),
gcc_jit_param_as_rvalue (param_b));
- gcc_jit_function_add_return (test_fn, NULL, binary_op);
+ gcc_jit_block *initial = gcc_jit_function_new_block (test_fn, "initial");
+ gcc_jit_block_end_with_return (initial, NULL, binary_op);
return gcc_jit_object_get_debug_string (
gcc_jit_rvalue_as_object (binary_op));
@@ -347,7 +349,8 @@ make_test_of_comparison (gcc_jit_context *ctxt,
gcc_jit_param_as_rvalue (param_a),
gcc_jit_param_as_rvalue (param_b));
- gcc_jit_function_add_return (test_fn, NULL, comparison);
+ gcc_jit_block *initial = gcc_jit_function_new_block (test_fn, "initial");
+ gcc_jit_block_end_with_return (initial, NULL, comparison);
return gcc_jit_object_get_debug_string (
gcc_jit_rvalue_as_object (comparison));
@@ -483,8 +486,10 @@ make_tests_of_dereferences (gcc_jit_context *ctxt)
"test_dereference_read",
1, ¶m_ptr,
0);
- gcc_jit_function_add_return (
- test_dereference_read,
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (test_dereference_read, "initial");
+ gcc_jit_block_end_with_return (
+ initial,
NULL,
gcc_jit_lvalue_as_rvalue (
gcc_jit_rvalue_dereference (
@@ -505,13 +510,16 @@ make_tests_of_dereferences (gcc_jit_context *ctxt)
"test_dereference_write",
2, params,
0);
- gcc_jit_function_add_assignment (
- test_dereference_write,
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (test_dereference_write, "initial");
+ gcc_jit_block_add_assignment (
+ initial,
NULL,
gcc_jit_rvalue_dereference (
gcc_jit_param_as_rvalue (param_ptr),
NULL),
gcc_jit_param_as_rvalue (param_i));
+ gcc_jit_block_end_with_void_return (initial, NULL);
}
}
@@ -578,8 +586,10 @@ make_test_of_get_address (gcc_jit_context *ctxt)
"test_get_address",
0, NULL,
0);
- gcc_jit_function_add_return (
- test_get_address,
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (test_get_address, "initial");
+ gcc_jit_block_end_with_return (
+ initial,
NULL,
gcc_jit_lvalue_get_address (
test_global,
@@ -36,16 +36,16 @@ create_code (gcc_jit_context *ctxt, void *user_data)
"my_factorial",
1, params, 0);
- /* Create forward labels: */
- gcc_jit_label *label_true =
- gcc_jit_function_new_forward_label (func, NULL);
-
- gcc_jit_label *label_false =
- gcc_jit_function_new_forward_label (func, NULL);
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (func, "initial");
+ gcc_jit_block *on_true =
+ gcc_jit_function_new_block (func, "on_true");
+ gcc_jit_block *on_false =
+ gcc_jit_function_new_block (func, "on_false");
/* if (x < 2) */
- gcc_jit_function_add_conditional (
- func, NULL,
+ gcc_jit_block_end_with_conditional (
+ initial, NULL,
gcc_jit_context_new_comparison (
ctxt, NULL,
GCC_JIT_COMPARISON_LT,
@@ -54,19 +54,17 @@ create_code (gcc_jit_context *ctxt, void *user_data)
ctxt,
the_type,
2)),
- label_true,
- label_false);
+ on_true,
+ on_false);
/* true branch: */
- gcc_jit_function_place_forward_label (func, NULL, label_true);
/* return x */
- gcc_jit_function_add_return (
- func,
+ gcc_jit_block_end_with_return (
+ on_true,
NULL,
gcc_jit_param_as_rvalue (x));
/* false branch: */
- gcc_jit_function_place_forward_label (func, NULL, label_false);
gcc_jit_rvalue *x_minus_1 =
gcc_jit_context_new_binary_op (
ctxt, NULL,
@@ -76,8 +74,8 @@ create_code (gcc_jit_context *ctxt, void *user_data)
ctxt,
the_type,
1));
- gcc_jit_function_add_return (
- func,
+ gcc_jit_block_end_with_return (
+ on_false,
NULL,
gcc_jit_context_new_binary_op (
ctxt, NULL,
@@ -50,16 +50,16 @@ FIRST_LINE + 7: }
"my_fibonacci",
1, params, 0);
- /* Create forward labels: */
- gcc_jit_label *label_true =
- gcc_jit_function_new_forward_label (func, NULL);
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (func, "initial");
+ gcc_jit_block *on_true =
+ gcc_jit_function_new_block (func, "on_true");
+ gcc_jit_block *on_false =
+ gcc_jit_function_new_block (func, "on_false");
- gcc_jit_label *label_false =
- gcc_jit_function_new_forward_label (func, NULL);
-
- /* if (x < 2) */
- gcc_jit_function_add_conditional (
- func,
+ /* if (x < 2) */
+ gcc_jit_block_end_with_conditional (
+ initial,
gcc_jit_context_new_location (ctxt, __FILE__, FIRST_LINE + 3, 19),
gcc_jit_context_new_comparison (
ctxt,
@@ -70,25 +70,17 @@ FIRST_LINE + 7: }
ctxt,
the_type,
2)),
- label_true,
- label_false);
+ on_true,
+ on_false);
/* true branch: */
- gcc_jit_function_place_forward_label (
- func,
- gcc_jit_context_new_location (ctxt, __FILE__, FIRST_LINE + 4, 21),
- label_true);
/* return x */
- gcc_jit_function_add_return (
- func,
+ gcc_jit_block_end_with_return (
+ on_true,
gcc_jit_context_new_location (ctxt, __FILE__, FIRST_LINE + 4, 21),
gcc_jit_param_as_rvalue (x));
/* false branch: */
- gcc_jit_function_place_forward_label (
- func,
- gcc_jit_context_new_location (ctxt, __FILE__, FIRST_LINE + 6, 21),
- label_false);
gcc_jit_rvalue *x_minus_1 =
gcc_jit_context_new_binary_op (
ctxt,
@@ -109,8 +101,8 @@ FIRST_LINE + 7: }
ctxt,
the_type,
2));
- gcc_jit_function_add_return (
- func,
+ gcc_jit_block_end_with_return (
+ on_false,
gcc_jit_context_new_location (ctxt, __FILE__, FIRST_LINE + 6, 21),
gcc_jit_context_new_binary_op (
ctxt,
@@ -53,7 +53,9 @@ create_test_of_builtin_strcmp (gcc_jit_context *ctxt)
gcc_jit_object_get_debug_string (gcc_jit_rvalue_as_object (call)),
"strcmp (a, b)");
- gcc_jit_function_add_return (test_fn, NULL, call);
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (test_fn, "initial");
+ gcc_jit_block_end_with_return (initial, NULL, call);
}
static void
@@ -109,7 +111,9 @@ create_test_of_builtin_trig (gcc_jit_context *ctxt)
gcc_jit_object_get_debug_string (gcc_jit_rvalue_as_object (ret)),
"(double)2 * sin (theta) * cos (theta)");
- gcc_jit_function_add_return (test_fn, NULL, ret);
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (test_fn, "initial");
+ gcc_jit_block_end_with_return (initial, NULL, ret);
}
static void
@@ -128,9 +132,7 @@ create_use_of_void_return (gcc_jit_context *ctxt)
{
*out = 1;
return;
- *out = 2;
}
- where the second assignment is unreachable.
*/
gcc_jit_type *void_t =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
@@ -149,19 +151,16 @@ create_use_of_void_return (gcc_jit_context *ctxt)
"test_of_void_return",
1, ¶m_out,
0);
- gcc_jit_function_add_assignment (
- test_fn, NULL,
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (test_fn, "initial");
+
+ gcc_jit_block_add_assignment (
+ initial, NULL,
/* "*out = ..." */
gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (param_out),
NULL),
gcc_jit_context_one (ctxt, int_t));
- gcc_jit_function_add_void_return (test_fn, NULL);
- gcc_jit_function_add_assignment (
- test_fn, NULL,
- /* "*out = ..." */
- gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (param_out),
- NULL),
- gcc_jit_context_new_rvalue_from_int (ctxt, int_t, 2));
+ gcc_jit_block_end_with_void_return (initial, NULL);
}
void
@@ -61,6 +61,8 @@ typedef struct function_fuzzer
int num_locals;
gcc_jit_lvalue **locals;
+ gcc_jit_block *block;
+
} function_fuzzer;
static void
@@ -274,6 +276,7 @@ make_random_function (fuzzer *f)
ff->num_params,
ff->params,
fuzzer_randrange (f, 0, 1));
+ ff->block = gcc_jit_function_new_block (ff->fn, NULL);
/* Create locals. */
if (kind != GCC_JIT_FUNCTION_IMPORTED)
@@ -301,6 +304,9 @@ make_random_function (fuzzer *f)
function_fuzzer_add_stmt (ff);
}
+ gcc_jit_block_end_with_return (ff->block, NULL, get_random_rvalue (ff, 3));
+
+
gcc_jit_function *result = ff->fn;
free (ff->params);
@@ -313,13 +319,13 @@ make_random_function (fuzzer *f)
static void function_fuzzer_add_stmt (function_fuzzer *ff)
{
- gcc_jit_function_add_eval (ff->fn,
- get_random_location (ff->f),
- get_random_rvalue (ff, 4));
- gcc_jit_function_add_assignment (ff->fn,
- get_random_location (ff->f),
- get_random_lvalue (ff, 4),
- get_random_rvalue (ff, 4));
+ gcc_jit_block_add_eval (ff->block,
+ get_random_location (ff->f),
+ get_random_rvalue (ff, 4));
+ gcc_jit_block_add_assignment (ff->block,
+ get_random_location (ff->f),
+ get_random_lvalue (ff, 4),
+ get_random_rvalue (ff, 4));
/* TODO: place more kinds of statement */
/* TODO: labels */
}
@@ -44,16 +44,19 @@ create_code (gcc_jit_context *ctxt, void *user_data)
args[0] = gcc_jit_context_new_string_literal (ctxt, "hello %s\n");
args[1] = gcc_jit_param_as_rvalue (param_name);
- gcc_jit_function_add_comment (
- func, NULL,
+ gcc_jit_block *block = gcc_jit_function_new_block (func, NULL);
+
+ gcc_jit_block_add_comment (
+ block, NULL,
"a test comment");
- gcc_jit_function_add_eval (
- func, NULL,
+ gcc_jit_block_add_eval (
+ block, NULL,
gcc_jit_context_new_call (ctxt,
NULL,
printf_func,
2, args));
+ gcc_jit_block_end_with_void_return (block, NULL);
}
extern void
@@ -60,24 +60,31 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_lvalue *total =
gcc_jit_function_new_local (fn, NULL, t_int, "total");
+ gcc_jit_block *initial = gcc_jit_function_new_block (fn, "initial");
+ gcc_jit_block *loop_test = gcc_jit_function_new_block (fn, "loop_test");
+ gcc_jit_block *loop_body = gcc_jit_function_new_block (fn, "loop_body");
+ gcc_jit_block *final = gcc_jit_function_new_block (fn, "final");
+
/* total = 0; */
- gcc_jit_function_add_assignment (
- fn, NULL,
+ gcc_jit_block_add_assignment (
+ initial, NULL,
total,
gcc_jit_context_zero (ctxt, t_int));
+ gcc_jit_block_end_with_jump (initial, NULL, loop_test);
/* 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)));
+ gcc_jit_block_end_with_conditional (
+ loop_test, 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)),
+ loop_body,
+ final);
/* total += n->value; */
- gcc_jit_function_add_assignment_op (
- fn, NULL,
+ gcc_jit_block_add_assignment_op (
+ loop_body, NULL,
total,
GCC_JIT_BINARY_OP_PLUS,
gcc_jit_lvalue_as_rvalue (
@@ -87,8 +94,8 @@ create_code (gcc_jit_context *ctxt, void *user_data)
f_value)));
/* n = n->next; */
- gcc_jit_function_add_assignment (
- fn, NULL,
+ gcc_jit_block_add_assignment (
+ loop_body, NULL,
gcc_jit_param_as_lvalue (param_n),
gcc_jit_lvalue_as_rvalue (
gcc_jit_rvalue_dereference_field (
@@ -96,10 +103,11 @@ create_code (gcc_jit_context *ctxt, void *user_data)
NULL,
f_next)));
- gcc_jit_loop_end (loop, NULL);
+ gcc_jit_block_end_with_jump (loop_body, NULL, loop_test);
/* return total; */
- gcc_jit_function_add_return (fn, NULL, gcc_jit_lvalue_as_rvalue (total));
+ gcc_jit_block_end_with_return (
+ final, NULL, gcc_jit_lvalue_as_rvalue (total));
}
void
@@ -73,6 +73,7 @@ struct top_level
gcc_jit_rvalue *zero;
gcc_jit_type *int_type;
+ gcc_jit_type *void_type;
/* "struct quadratic" */
gcc_jit_type *struct_quadratic;
@@ -110,6 +111,8 @@ make_types (struct top_level *top_level)
top_level->int_type =
gcc_jit_context_get_type (top_level->ctxt, GCC_JIT_TYPE_INT);
+ top_level->void_type =
+ gcc_jit_context_get_type (top_level->ctxt, GCC_JIT_TYPE_VOID);
top_level->a =
gcc_jit_context_new_field (top_level->ctxt,
@@ -169,12 +172,14 @@ make_calc_discriminant (struct top_level *top_level,
middle_level->calc_discriminant =
gcc_jit_context_new_function (middle_level->ctxt, NULL,
GCC_JIT_FUNCTION_EXPORTED,
- top_level->numeric_type,
+ top_level->void_type,
"calc_discriminant",
1, ¶m_q,
0);
- gcc_jit_function_add_comment (
- middle_level->calc_discriminant, NULL,
+ gcc_jit_block *blk =
+ gcc_jit_function_new_block (middle_level->calc_discriminant, NULL);
+ gcc_jit_block_add_comment (
+ blk, NULL,
"(b^2 - 4ac)");
gcc_jit_rvalue *q_a =
@@ -193,8 +198,8 @@ make_calc_discriminant (struct top_level *top_level,
gcc_jit_param_as_rvalue (param_q),
NULL, top_level->c));
- gcc_jit_function_add_assignment (
- middle_level->calc_discriminant, NULL,
+ gcc_jit_block_add_assignment (
+ blk, NULL,
/* q->discriminant =... */
gcc_jit_rvalue_dereference_field (
@@ -231,6 +236,8 @@ make_calc_discriminant (struct top_level *top_level,
GCC_JIT_BINARY_OP_MULT,
top_level->numeric_type,
q_a, q_c)))); /* end of gcc_jit_function_add_assignment call. */
+
+ gcc_jit_block_end_with_void_return (blk, NULL);
}
static void
@@ -268,51 +275,56 @@ make_test_quadratic (struct top_level *top_level,
test_quadratic, NULL,
top_level->struct_quadratic,
"q");
+
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (test_quadratic,
+ "initial");
+ gcc_jit_block *on_positive_discriminant
+ = gcc_jit_function_new_block (test_quadratic,
+ "positive_discriminant");
+
+ gcc_jit_block *on_nonpositive_discriminant
+ = gcc_jit_function_new_block (test_quadratic,
+ "nonpositive_discriminant");
+
+ gcc_jit_block *on_zero_discriminant
+ = gcc_jit_function_new_block (test_quadratic,
+ "zero_discriminant");
+
+ gcc_jit_block *on_negative_discriminant
+ = gcc_jit_function_new_block (test_quadratic,
+ "negative_discriminant");
+
+ /* Initial block. */
/* q.a = a; */
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ initial, NULL,
gcc_jit_lvalue_access_field (q, NULL, top_level->a),
gcc_jit_param_as_rvalue (a));
/* q.b = b; */
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ initial, NULL,
gcc_jit_lvalue_access_field (q, NULL, top_level->b),
gcc_jit_param_as_rvalue (b));
/* q.c = c; */
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ initial, NULL,
gcc_jit_lvalue_access_field (q, NULL, top_level->c),
gcc_jit_param_as_rvalue (c));
/* calc_discriminant (&q); */
gcc_jit_rvalue *address_of_q = gcc_jit_lvalue_get_address (q, NULL);
- gcc_jit_function_add_eval (
- test_quadratic, NULL,
+ gcc_jit_block_add_eval (
+ initial, NULL,
gcc_jit_context_new_call (
bottom_level->ctxt, NULL,
middle_level->calc_discriminant,
1, &address_of_q));
- gcc_jit_label *on_positive_discriminant
- = gcc_jit_function_new_forward_label (test_quadratic,
- "positive_discriminant");
-
- gcc_jit_label *on_nonpositive_discriminant
- = gcc_jit_function_new_forward_label (test_quadratic,
- "nonpositive_discriminant");
-
- gcc_jit_label *on_zero_discriminant
- = gcc_jit_function_new_forward_label (test_quadratic,
- "zero_discriminant");
-
- gcc_jit_label *on_negative_discriminant
- = gcc_jit_function_new_forward_label (test_quadratic,
- "negative_discriminant");
-
- gcc_jit_function_add_comment (
- test_quadratic, NULL,
+ gcc_jit_block_add_comment (
+ initial, NULL,
"if (q.discriminant > 0)");
- gcc_jit_function_add_conditional (
- test_quadratic, NULL,
+ gcc_jit_block_end_with_conditional (
+ initial, NULL,
gcc_jit_context_new_comparison (
bottom_level->ctxt, NULL,
GCC_JIT_COMPARISON_GT,
@@ -324,9 +336,7 @@ make_test_quadratic (struct top_level *top_level,
on_positive_discriminant,
on_nonpositive_discriminant);
- gcc_jit_function_place_forward_label (
- test_quadratic, NULL,
- on_positive_discriminant);
+ /* Block: "on_positive_discriminant" */
/* double s = sqrt (q.discriminant); */
gcc_jit_lvalue *s = gcc_jit_function_new_local (
test_quadratic, NULL,
@@ -336,8 +346,8 @@ make_test_quadratic (struct top_level *top_level,
gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (q),
NULL,
top_level->discriminant);
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ on_positive_discriminant, NULL,
s,
gcc_jit_context_new_call (
bottom_level->ctxt, NULL,
@@ -361,11 +371,11 @@ make_test_quadratic (struct top_level *top_level,
2),
gcc_jit_param_as_rvalue (a));
- gcc_jit_function_add_comment (
- test_quadratic, NULL,
+ gcc_jit_block_add_comment (
+ on_positive_discriminant, NULL,
"*r1 = (-b + s) / (2 * a);");
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ on_positive_discriminant, NULL,
/* "*r1 = ..." */
gcc_jit_rvalue_dereference (
@@ -384,11 +394,11 @@ make_test_quadratic (struct top_level *top_level,
gcc_jit_lvalue_as_rvalue (s)),
two_a));
- gcc_jit_function_add_comment (
- test_quadratic, NULL,
+ gcc_jit_block_add_comment (
+ on_positive_discriminant, NULL,
"*r2 = (-b - s) / (2 * a)");
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ on_positive_discriminant, NULL,
/* "*r2 = ..." */
gcc_jit_rvalue_dereference (
@@ -408,22 +418,19 @@ make_test_quadratic (struct top_level *top_level,
two_a));
/* "return 2;" */
- gcc_jit_function_add_return (
- test_quadratic, NULL,
+ gcc_jit_block_end_with_return (
+ on_positive_discriminant, NULL,
gcc_jit_context_new_rvalue_from_int (
bottom_level->ctxt,
top_level->int_type,
2));
- /* "else if (q.discriminant == 0)" */
- gcc_jit_function_place_forward_label (
- test_quadratic, NULL,
- on_nonpositive_discriminant);
- gcc_jit_function_add_comment (
- test_quadratic, NULL,
+ /* Block: "on_nonpositive_discriminant" */
+ gcc_jit_block_add_comment (
+ on_nonpositive_discriminant, NULL,
"else if (q.discriminant == 0)");
- gcc_jit_function_add_conditional (
- test_quadratic, NULL,
+ gcc_jit_block_end_with_conditional (
+ on_nonpositive_discriminant, NULL,
gcc_jit_context_new_comparison (
bottom_level->ctxt, NULL,
GCC_JIT_COMPARISON_EQ,
@@ -435,16 +442,12 @@ make_test_quadratic (struct top_level *top_level,
on_zero_discriminant,
on_negative_discriminant);
- /* if (q.discriminant == 0) */
- gcc_jit_function_place_forward_label (
- test_quadratic, NULL,
- on_zero_discriminant);
-
- gcc_jit_function_add_comment (
- test_quadratic, NULL,
+ /* Block: "on_zero_discriminant" */
+ gcc_jit_block_add_comment (
+ on_zero_discriminant, NULL,
"*r1 = -b / (2 * a);");
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ on_zero_discriminant, NULL,
/* "*r1 = ..." */
gcc_jit_rvalue_dereference (
@@ -459,16 +462,14 @@ make_test_quadratic (struct top_level *top_level,
two_a));
/* "return 1;" */
- gcc_jit_function_add_return (
- test_quadratic, NULL,
+ gcc_jit_block_end_with_return (
+ on_zero_discriminant, NULL,
gcc_jit_context_one (bottom_level->ctxt, top_level->int_type));
- /* else return 0; */
- gcc_jit_function_place_forward_label (
- test_quadratic, NULL,
- on_negative_discriminant);
- gcc_jit_function_add_return (
- test_quadratic, NULL,
+ /* Block: "on_negative_discriminant" */
+ gcc_jit_block_end_with_return (
+ /* else return 0; */
+ on_negative_discriminant, NULL,
gcc_jit_context_zero (bottom_level->ctxt, top_level->int_type));
}
@@ -70,6 +70,7 @@ struct quadratic_test
gccjit::rvalue zero;
gccjit::type int_type;
+ gccjit::type void_type;
/* "struct quadratic" */
gccjit::type quadratic;
@@ -95,6 +96,7 @@ make_types (quadratic_test &testcase)
testcase.zero = testcase.ctxt.zero (testcase.numeric_type);
testcase.int_type = testcase.ctxt.get_int_type <int> ();
+ testcase.void_type = testcase.ctxt.get_type (GCC_JIT_TYPE_VOID);
testcase.a = testcase.ctxt.new_field (testcase.numeric_type, "a");
testcase.b = testcase.ctxt.new_field (testcase.numeric_type, "b");
@@ -139,11 +141,12 @@ make_calc_discriminant (quadratic_test &testcase)
params[0] = param_q;
testcase.calc_discriminant =
testcase.ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
- testcase.numeric_type,
+ testcase.void_type,
"calc_discriminant",
params,
0);
- testcase.calc_discriminant.add_comment ("(b^2 - 4ac)");
+ gccjit::block block = testcase.calc_discriminant.new_block ();
+ block.add_comment ("(b^2 - 4ac)");
gccjit::rvalue q_a = param_q.dereference_field (testcase.a);
gccjit::rvalue q_b = param_q.dereference_field (testcase.b);
@@ -152,11 +155,12 @@ make_calc_discriminant (quadratic_test &testcase)
gccjit::rvalue four =
testcase.ctxt.new_rvalue (testcase.numeric_type, 4);
- testcase.calc_discriminant.add_assignment (
+ block.add_assignment (
/* q->discriminant =... */
param_q.dereference_field (testcase.discriminant),
/* (q->b * q->b) - (4 * q->a * q->c) */
(q_b * q_b) - (four * q_a * q_c));
+ block.end_with_return ();
}
static void
@@ -186,41 +190,41 @@ make_test_quadratic (quadratic_test &testcase)
/* struct quadratic q; */
gccjit::lvalue q = test_quadratic.new_local (testcase.quadratic, "q");
+
+ gccjit::block initial = test_quadratic.new_block ("initial");
+ gccjit::block on_positive_discriminant
+ = test_quadratic.new_block ("positive_discriminant");
+ gccjit::block on_nonpositive_discriminant
+ = test_quadratic.new_block ("nonpositive_discriminant");
+ gccjit::block on_zero_discriminant
+ = test_quadratic.new_block ("zero_discriminant");
+ gccjit::block on_negative_discriminant
+ = test_quadratic.new_block ("negative_discriminant");
+
+ CHECK_STRING_VALUE (on_zero_discriminant.get_debug_string ().c_str (),
+ "zero_discriminant");
+
/* q.a = a; */
- test_quadratic.add_assignment (q.access_field (testcase.a), a);
+ initial.add_assignment (q.access_field (testcase.a), a);
/* q.b = b; */
- test_quadratic.add_assignment (q.access_field (testcase.b), b);
+ initial.add_assignment (q.access_field (testcase.b), b);
/* q.c = c; */
- test_quadratic.add_assignment (q.access_field (testcase.c), c);
+ initial.add_assignment (q.access_field (testcase.c), c);
/* calc_discriminant (&q); */
gccjit::rvalue address_of_q = q.get_address ();
- test_quadratic.add_eval (testcase.calc_discriminant (address_of_q));
-
- gccjit::label on_positive_discriminant
- = test_quadratic.new_forward_label ("positive_discriminant");
+ initial.add_eval (testcase.calc_discriminant (address_of_q));
- gccjit::label on_nonpositive_discriminant
- = test_quadratic.new_forward_label ("nonpositive_discriminant");
-
- gccjit::label on_zero_discriminant
- = test_quadratic.new_forward_label ("zero_discriminant");
-
- gccjit::label on_negative_discriminant
- = test_quadratic.new_forward_label ("negative_discriminant");
- CHECK_STRING_VALUE (on_zero_discriminant.get_debug_string ().c_str (),
- "zero_discriminant");
-
- test_quadratic.add_comment ("if (q.discriminant > 0)");
- test_quadratic.add_conditional (
+ initial.add_comment ("if (q.discriminant > 0)");
+ initial.end_with_conditional (
q.access_field (testcase.discriminant) > testcase.zero,
on_positive_discriminant,
on_nonpositive_discriminant);
- test_quadratic.place_forward_label (on_positive_discriminant);
+ /* Block: "on_positive_discriminant" */
/* double s = sqrt (q.discriminant); */
gccjit::lvalue s = test_quadratic.new_local (testcase.numeric_type, "s");
gccjit::rvalue discriminant_of_q = q.access_field (testcase.discriminant);
- test_quadratic.add_assignment (s, testcase.sqrt (discriminant_of_q));
+ on_positive_discriminant.add_assignment (s, testcase.sqrt (discriminant_of_q));
gccjit::rvalue minus_b = -b;
gccjit::rvalue two =
@@ -229,35 +233,35 @@ make_test_quadratic (quadratic_test &testcase)
CHECK_STRING_VALUE (two_a.get_debug_string ().c_str (),
"(double)2 * a");
- test_quadratic.add_comment ("*r1 = (-b + s) / (2 * a);");
- test_quadratic.add_assignment (*r1, (minus_b + s) / two_a);
+ on_positive_discriminant.add_comment ("*r1 = (-b + s) / (2 * a);");
+ on_positive_discriminant.add_assignment (*r1, (minus_b + s) / two_a);
- test_quadratic.add_comment ("*r2 = (-b - s) / (2 * a)");
- test_quadratic.add_assignment (*r2, (minus_b - s) / two_a);
+ on_positive_discriminant.add_comment ("*r2 = (-b - s) / (2 * a)");
+ on_positive_discriminant.add_assignment (*r2, (minus_b - s) / two_a);
/* "return 2;" */
- test_quadratic.add_return (testcase.ctxt.new_rvalue (testcase.int_type, 2));
+ on_positive_discriminant.end_with_return (
+ testcase.ctxt.new_rvalue (testcase.int_type, 2));
+ /* Block: "on_nonpositive_discriminant" */
/* "else if (q.discriminant == 0)" */
- test_quadratic.place_forward_label (on_nonpositive_discriminant);
- test_quadratic.add_comment ("else if (q.discriminant == 0)");
- test_quadratic.add_conditional (
+ on_nonpositive_discriminant.add_comment ("else if (q.discriminant == 0)");
+ on_nonpositive_discriminant.end_with_conditional (
q.access_field (testcase.discriminant) == testcase.zero,
on_zero_discriminant,
on_negative_discriminant);
+ /* Block: "on_zero_discriminant" */
/* if (q.discriminant == 0) */
- test_quadratic.place_forward_label (on_zero_discriminant);
-
- test_quadratic.add_comment ("*r1 = -b / (2 * a);");
- test_quadratic.add_assignment (*r1, minus_b / two_a);
+ on_zero_discriminant.add_comment ("*r1 = -b / (2 * a);");
+ on_zero_discriminant.add_assignment (*r1, minus_b / two_a);
/* "return 1;" */
- test_quadratic.add_return (testcase.int_type.one ());
+ on_zero_discriminant.end_with_return (testcase.int_type.one ());
+ /* Block: "on_negative_discriminant" */
/* else return 0; */
- test_quadratic.place_forward_label (on_negative_discriminant);
- test_quadratic.add_return (testcase.int_type.zero ());
+ on_negative_discriminant.end_with_return (testcase.int_type.zero ());
/* Verify that output stream operator << works. */
std::ostringstream os;
@@ -60,6 +60,7 @@ struct quadratic_test
gcc_jit_rvalue *zero;
gcc_jit_type *int_type;
+ gcc_jit_type *void_type;
/* "struct quadratic" */
gcc_jit_type *quadratic;
@@ -90,6 +91,9 @@ make_types (struct quadratic_test *testcase)
testcase->int_type =
gcc_jit_context_get_type (testcase->ctxt, GCC_JIT_TYPE_INT);
+ testcase->void_type =
+ gcc_jit_context_get_type (testcase->ctxt, GCC_JIT_TYPE_VOID);
+
testcase->a =
gcc_jit_context_new_field (testcase->ctxt,
NULL,
@@ -146,12 +150,14 @@ make_calc_discriminant (struct quadratic_test *testcase)
testcase->calc_discriminant =
gcc_jit_context_new_function (testcase->ctxt, NULL,
GCC_JIT_FUNCTION_EXPORTED,
- testcase->numeric_type,
+ testcase->void_type,
"calc_discriminant",
1, ¶m_q,
0);
- gcc_jit_function_add_comment (
- testcase->calc_discriminant, NULL,
+ gcc_jit_block *blk =
+ gcc_jit_function_new_block (testcase->calc_discriminant, NULL);
+ gcc_jit_block_add_comment (
+ blk, NULL,
"(b^2 - 4ac)");
gcc_jit_rvalue *q_a =
@@ -170,8 +176,8 @@ make_calc_discriminant (struct quadratic_test *testcase)
gcc_jit_param_as_rvalue (param_q),
NULL, testcase->c));
- gcc_jit_function_add_assignment (
- testcase->calc_discriminant, NULL,
+ gcc_jit_block_add_assignment (
+ blk, NULL,
/* q->discriminant =... */
gcc_jit_rvalue_dereference_field (
@@ -208,6 +214,8 @@ make_calc_discriminant (struct quadratic_test *testcase)
GCC_JIT_BINARY_OP_MULT,
testcase->numeric_type,
q_a, q_c)))); /* end of gcc_jit_function_add_assignment call. */
+
+ gcc_jit_block_end_with_void_return (blk, NULL);
}
static void
@@ -236,58 +244,62 @@ make_test_quadratic (struct quadratic_test *testcase)
"test_quadratic",
5, params,
0);
-
/* struct quadratic q; */
gcc_jit_lvalue *q =
gcc_jit_function_new_local (
test_quadratic, NULL,
testcase->quadratic,
"q");
+
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (test_quadratic,
+ "initial");
+ gcc_jit_block *on_positive_discriminant
+ = gcc_jit_function_new_block (test_quadratic,
+ "positive_discriminant");
+
+ gcc_jit_block *on_nonpositive_discriminant
+ = gcc_jit_function_new_block (test_quadratic,
+ "nonpositive_discriminant");
+
+ gcc_jit_block *on_zero_discriminant
+ = gcc_jit_function_new_block (test_quadratic,
+ "zero_discriminant");
+
+ gcc_jit_block *on_negative_discriminant
+ = gcc_jit_function_new_block (test_quadratic,
+ "negative_discriminant");
+
+ /* Initial block. */
/* q.a = a; */
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ initial, NULL,
gcc_jit_lvalue_access_field (q, NULL, testcase->a),
gcc_jit_param_as_rvalue (a));
/* q.b = b; */
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ initial, NULL,
gcc_jit_lvalue_access_field (q, NULL, testcase->b),
gcc_jit_param_as_rvalue (b));
/* q.c = c; */
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ initial, NULL,
gcc_jit_lvalue_access_field (q, NULL, testcase->c),
gcc_jit_param_as_rvalue (c));
/* calc_discriminant (&q); */
gcc_jit_rvalue *address_of_q = gcc_jit_lvalue_get_address (q, NULL);
- gcc_jit_function_add_eval (
- test_quadratic, NULL,
+ gcc_jit_block_add_eval (
+ initial, NULL,
gcc_jit_context_new_call (
testcase->ctxt, NULL,
testcase->calc_discriminant,
1, &address_of_q));
- gcc_jit_label *on_positive_discriminant
- = gcc_jit_function_new_forward_label (test_quadratic,
- "positive_discriminant");
-
- gcc_jit_label *on_nonpositive_discriminant
- = gcc_jit_function_new_forward_label (test_quadratic,
- "nonpositive_discriminant");
-
- gcc_jit_label *on_zero_discriminant
- = gcc_jit_function_new_forward_label (test_quadratic,
- "zero_discriminant");
-
- gcc_jit_label *on_negative_discriminant
- = gcc_jit_function_new_forward_label (test_quadratic,
- "negative_discriminant");
-
- gcc_jit_function_add_comment (
- test_quadratic, NULL,
+ gcc_jit_block_add_comment (
+ initial, NULL,
"if (q.discriminant > 0)");
- gcc_jit_function_add_conditional (
- test_quadratic, NULL,
+ gcc_jit_block_end_with_conditional (
+ initial, NULL,
gcc_jit_context_new_comparison (
testcase->ctxt, NULL,
GCC_JIT_COMPARISON_GT,
@@ -299,9 +311,7 @@ make_test_quadratic (struct quadratic_test *testcase)
on_positive_discriminant,
on_nonpositive_discriminant);
- gcc_jit_function_place_forward_label (
- test_quadratic, NULL,
- on_positive_discriminant);
+ /* Block: "on_positive_discriminant" */
/* double s = sqrt (q.discriminant); */
gcc_jit_lvalue *s = gcc_jit_function_new_local (
test_quadratic, NULL,
@@ -311,8 +321,8 @@ make_test_quadratic (struct quadratic_test *testcase)
gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (q),
NULL,
testcase->discriminant);
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ on_positive_discriminant, NULL,
s,
gcc_jit_context_new_call (
testcase->ctxt, NULL,
@@ -336,11 +346,11 @@ make_test_quadratic (struct quadratic_test *testcase)
2),
gcc_jit_param_as_rvalue (a));
- gcc_jit_function_add_comment (
- test_quadratic, NULL,
+ gcc_jit_block_add_comment (
+ on_positive_discriminant, NULL,
"*r1 = (-b + s) / (2 * a);");
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ on_positive_discriminant, NULL,
/* "*r1 = ..." */
gcc_jit_rvalue_dereference (
@@ -359,11 +369,11 @@ make_test_quadratic (struct quadratic_test *testcase)
gcc_jit_lvalue_as_rvalue (s)),
two_a));
- gcc_jit_function_add_comment (
- test_quadratic, NULL,
+ gcc_jit_block_add_comment (
+ on_positive_discriminant, NULL,
"*r2 = (-b - s) / (2 * a)");
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ on_positive_discriminant, NULL,
/* "*r2 = ..." */
gcc_jit_rvalue_dereference (
@@ -383,22 +393,19 @@ make_test_quadratic (struct quadratic_test *testcase)
two_a));
/* "return 2;" */
- gcc_jit_function_add_return (
- test_quadratic, NULL,
+ gcc_jit_block_end_with_return (
+ on_positive_discriminant, NULL,
gcc_jit_context_new_rvalue_from_int (
testcase->ctxt,
testcase->int_type,
2));
- /* "else if (q.discriminant == 0)" */
- gcc_jit_function_place_forward_label (
- test_quadratic, NULL,
- on_nonpositive_discriminant);
- gcc_jit_function_add_comment (
- test_quadratic, NULL,
+ /* Block: "on_nonpositive_discriminant" */
+ gcc_jit_block_add_comment (
+ on_nonpositive_discriminant, NULL,
"else if (q.discriminant == 0)");
- gcc_jit_function_add_conditional (
- test_quadratic, NULL,
+ gcc_jit_block_end_with_conditional (
+ on_nonpositive_discriminant, NULL,
gcc_jit_context_new_comparison (
testcase->ctxt, NULL,
GCC_JIT_COMPARISON_EQ,
@@ -410,16 +417,12 @@ make_test_quadratic (struct quadratic_test *testcase)
on_zero_discriminant,
on_negative_discriminant);
- /* if (q.discriminant == 0) */
- gcc_jit_function_place_forward_label (
- test_quadratic, NULL,
- on_zero_discriminant);
-
- gcc_jit_function_add_comment (
- test_quadratic, NULL,
+ /* Block: "on_zero_discriminant" */
+ gcc_jit_block_add_comment (
+ on_zero_discriminant, NULL,
"*r1 = -b / (2 * a);");
- gcc_jit_function_add_assignment (
- test_quadratic, NULL,
+ gcc_jit_block_add_assignment (
+ on_zero_discriminant, NULL,
/* "*r1 = ..." */
gcc_jit_rvalue_dereference (
@@ -432,18 +435,15 @@ make_test_quadratic (struct quadratic_test *testcase)
testcase->numeric_type,
minus_b,
two_a));
-
- /* "return 1;" */
- gcc_jit_function_add_return (
- test_quadratic, NULL,
+ gcc_jit_block_end_with_return (
+ /* "return 1;" */
+ on_zero_discriminant, NULL,
gcc_jit_context_one (testcase->ctxt, testcase->int_type));
- /* else return 0; */
- gcc_jit_function_place_forward_label (
- test_quadratic, NULL,
- on_negative_discriminant);
- gcc_jit_function_add_return (
- test_quadratic, NULL,
+ /* Block: "on_negative_discriminant" */
+ gcc_jit_block_end_with_return (
+ /* "else return 0;" */
+ on_negative_discriminant, NULL,
gcc_jit_context_zero (testcase->ctxt, testcase->int_type));
}
@@ -69,6 +69,7 @@ struct quadratic_test
gccjit::rvalue zero;
gccjit::type int_type;
+ gccjit::type void_type;
/* "struct quadratic" */
gccjit::type quadratic;
@@ -94,6 +95,7 @@ make_types (quadratic_test &testcase)
testcase.zero = testcase.ctxt.zero (testcase.numeric_type);
testcase.int_type = testcase.ctxt.get_int_type <int> ();
+ testcase.void_type = testcase.ctxt.get_type (GCC_JIT_TYPE_VOID);
testcase.a = testcase.ctxt.new_field (testcase.numeric_type, "a");
testcase.b = testcase.ctxt.new_field (testcase.numeric_type, "b");
@@ -138,17 +140,18 @@ make_calc_discriminant (quadratic_test &testcase)
params[0] = param_q;
testcase.calc_discriminant =
testcase.ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
- testcase.numeric_type,
+ testcase.void_type,
"calc_discriminant",
params,
0);
- testcase.calc_discriminant.add_comment ("(b^2 - 4ac)");
+ gccjit::block block = testcase.calc_discriminant.new_block ();
+ block.add_comment ("(b^2 - 4ac)");
gccjit::rvalue q_a = param_q.dereference_field (testcase.a);
gccjit::rvalue q_b = param_q.dereference_field (testcase.b);
gccjit::rvalue q_c = param_q.dereference_field (testcase.c);
- testcase.calc_discriminant.add_assignment (
+ block.add_assignment (
/* q->discriminant =... */
param_q.dereference_field (testcase.discriminant),
/* (q->b * q->b) - (4 * q->a * q->c) */
@@ -171,6 +174,7 @@ make_calc_discriminant (quadratic_test &testcase)
testcase.ctxt.new_mult (
testcase.numeric_type,
q_a, q_c)))); /* end of add_assignment call. */
+ block.end_with_return ();
}
static void
@@ -200,43 +204,43 @@ make_test_quadratic (quadratic_test &testcase)
/* struct quadratic q; */
gccjit::lvalue q = test_quadratic.new_local (testcase.quadratic, "q");
+
+ gccjit::block initial = test_quadratic.new_block ("initial");
+ gccjit::block on_positive_discriminant
+ = test_quadratic.new_block ("positive_discriminant");
+ gccjit::block on_nonpositive_discriminant
+ = test_quadratic.new_block ("nonpositive_discriminant");
+ gccjit::block on_zero_discriminant
+ = test_quadratic.new_block ("zero_discriminant");
+ gccjit::block on_negative_discriminant
+ = test_quadratic.new_block ("negative_discriminant");
+
+ CHECK_STRING_VALUE (on_zero_discriminant.get_debug_string ().c_str (),
+ "zero_discriminant");
+
/* q.a = a; */
- test_quadratic.add_assignment (q.access_field (testcase.a), a);
+ initial.add_assignment (q.access_field (testcase.a), a);
/* q.b = b; */
- test_quadratic.add_assignment (q.access_field (testcase.b), b);
+ initial.add_assignment (q.access_field (testcase.b), b);
/* q.c = c; */
- test_quadratic.add_assignment (q.access_field (testcase.c), c);
+ initial.add_assignment (q.access_field (testcase.c), c);
/* calc_discriminant (&q); */
gccjit::rvalue address_of_q = q.get_address ();
- test_quadratic.add_call (testcase.calc_discriminant, address_of_q);
-
- gccjit::label on_positive_discriminant
- = test_quadratic.new_forward_label ("positive_discriminant");
+ initial.add_call (testcase.calc_discriminant, address_of_q);
- gccjit::label on_nonpositive_discriminant
- = test_quadratic.new_forward_label ("nonpositive_discriminant");
-
- gccjit::label on_zero_discriminant
- = test_quadratic.new_forward_label ("zero_discriminant");
-
- gccjit::label on_negative_discriminant
- = test_quadratic.new_forward_label ("negative_discriminant");
- CHECK_STRING_VALUE (on_zero_discriminant.get_debug_string ().c_str (),
- "zero_discriminant");
-
- test_quadratic.add_comment ("if (q.discriminant > 0)");
- test_quadratic.add_conditional (
+ initial.add_comment ("if (q.discriminant > 0)");
+ initial.end_with_conditional (
testcase.ctxt.new_gt (
q.access_field (testcase.discriminant),
testcase.zero),
on_positive_discriminant,
on_nonpositive_discriminant);
- test_quadratic.place_forward_label (on_positive_discriminant);
+ /* Block: "on_positive_discriminant" */
/* double s = sqrt (q.discriminant); */
gccjit::lvalue s = test_quadratic.new_local (testcase.numeric_type, "s");
gccjit::rvalue discriminant_of_q = q.access_field (testcase.discriminant);
- test_quadratic.add_assignment (
+ on_positive_discriminant.add_assignment (
s,
testcase.ctxt.new_call (testcase.sqrt, discriminant_of_q));
@@ -252,8 +256,8 @@ make_test_quadratic (quadratic_test &testcase)
CHECK_STRING_VALUE (two_a.get_debug_string ().c_str (),
"(double)2 * a");
- test_quadratic.add_comment ("*r1 = (-b + s) / (2 * a);");
- test_quadratic.add_assignment (
+ on_positive_discriminant.add_comment ("*r1 = (-b + s) / (2 * a);");
+ on_positive_discriminant.add_assignment (
/* "*r1 = ..." */
r1.dereference (),
@@ -266,8 +270,8 @@ make_test_quadratic (quadratic_test &testcase)
s),
two_a));
- test_quadratic.add_comment ("*r2 = (-b - s) / (2 * a)");
- test_quadratic.add_assignment (
+ on_positive_discriminant.add_comment ("*r2 = (-b - s) / (2 * a)");
+ on_positive_discriminant.add_assignment (
/* "*r2 = ..." */
r2.dereference (),
@@ -281,23 +285,22 @@ make_test_quadratic (quadratic_test &testcase)
two_a));
/* "return 2;" */
- test_quadratic.add_return (testcase.ctxt.new_rvalue (testcase.int_type, 2));
+ on_positive_discriminant.end_with_return (
+ testcase.ctxt.new_rvalue (testcase.int_type, 2));
- /* "else if (q.discriminant == 0)" */
- test_quadratic.place_forward_label (on_nonpositive_discriminant);
- test_quadratic.add_comment ("else if (q.discriminant == 0)");
- test_quadratic.add_conditional (
+ /* Block: "on_nonpositive_discriminant" */
+ on_nonpositive_discriminant.add_comment ("else if (q.discriminant == 0)");
+ on_nonpositive_discriminant.end_with_conditional (
testcase.ctxt.new_eq (
q.access_field (testcase.discriminant),
testcase.zero),
on_zero_discriminant,
on_negative_discriminant);
+ /* Block: "on_zero_discriminant" */
/* if (q.discriminant == 0) */
- test_quadratic.place_forward_label (on_zero_discriminant);
-
- test_quadratic.add_comment ("*r1 = -b / (2 * a);");
- test_quadratic.add_assignment (
+ on_zero_discriminant.add_comment ("*r1 = -b / (2 * a);");
+ on_zero_discriminant.add_assignment (
/* "*r1 = ..." */
r1.dereference (),
@@ -308,11 +311,13 @@ make_test_quadratic (quadratic_test &testcase)
two_a));
/* "return 1;" */
- test_quadratic.add_return (testcase.ctxt.one (testcase.int_type));
+ on_zero_discriminant.end_with_return (
+ testcase.ctxt.one (testcase.int_type));
+ /* Block: "on_negative_discriminant" */
/* else return 0; */
- test_quadratic.place_forward_label (on_negative_discriminant);
- test_quadratic.add_return (testcase.ctxt.zero (testcase.int_type));
+ on_negative_discriminant.end_with_return (
+ testcase.ctxt.zero (testcase.int_type));
/* Verify that output stream operator << works. */
std::ostringstream os;
@@ -62,8 +62,9 @@ create_code (gcc_jit_context *ctxt, void *user_data)
0);
/* return f->x * f->y; */
- gcc_jit_function_add_return (
- fn_test_reading,
+ gcc_jit_block *reading_block = gcc_jit_function_new_block (fn_test_reading, NULL);
+ gcc_jit_block_end_with_return (
+ reading_block,
NULL,
gcc_jit_context_new_binary_op (
ctxt, NULL,
@@ -95,21 +96,22 @@ create_code (gcc_jit_context *ctxt, void *user_data)
struct_type,
"tmp");
/* tmp.x = 5; */
- gcc_jit_function_add_assignment (
- fn_test_writing, NULL,
+ gcc_jit_block *writing_block = gcc_jit_function_new_block (fn_test_writing, NULL);
+ gcc_jit_block_add_assignment (
+ writing_block, NULL,
gcc_jit_lvalue_access_field (local_tmp, NULL, x),
gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 5));
/* tmp.y = 7; */
- gcc_jit_function_add_assignment (
- fn_test_writing, NULL,
+ gcc_jit_block_add_assignment (
+ writing_block, NULL,
gcc_jit_lvalue_access_field (local_tmp, NULL, y),
gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 7));
/* return test_reading (&tmp); */
gcc_jit_rvalue *arg = gcc_jit_lvalue_get_address (local_tmp, NULL);
- gcc_jit_function_add_return (
- fn_test_writing,
+ gcc_jit_block_end_with_return (
+ writing_block,
NULL,
gcc_jit_context_new_call (
ctxt, NULL,
@@ -28,9 +28,10 @@ create_code (gcc_jit_context *ctxt, void *user_data)
"test_string_literal",
0, NULL,
0);
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
- gcc_jit_function_add_return (
- test_fn, NULL,
+ gcc_jit_block_end_with_return (
+ block, NULL,
gcc_jit_context_new_string_literal (ctxt, "hello world"));
}
@@ -42,41 +42,43 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_lvalue *sum =
gcc_jit_function_new_local (func, NULL, the_type, "sum");
- /* Create forward label: */
- gcc_jit_label *label_after_loop =
- gcc_jit_function_new_forward_label (func, "after_loop");
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (func, "initial");
+ gcc_jit_block *loop_cond =
+ gcc_jit_function_new_block (func, "loop_cond");
+ gcc_jit_block *loop_body =
+ gcc_jit_function_new_block (func, "loop_body");
+ gcc_jit_block *after_loop =
+ gcc_jit_function_new_block (func, "after_loop");
/* sum = 0; */
- gcc_jit_function_add_assignment (
- func, NULL,
+ gcc_jit_block_add_assignment (
+ initial, NULL,
sum,
gcc_jit_context_new_rvalue_from_int (ctxt, the_type, 0));
/* i = 0; */
- gcc_jit_function_add_assignment (
- func, NULL,
+ gcc_jit_block_add_assignment (
+ initial, NULL,
i,
gcc_jit_context_new_rvalue_from_int (ctxt, the_type, 0));
-
- /* label "cond:" */
- gcc_jit_label *label_cond =
- gcc_jit_function_add_label (func, NULL, "cond");
+ gcc_jit_block_end_with_jump (initial, NULL, loop_cond);
/* if (i >= n) */
- gcc_jit_function_add_conditional (
- func, NULL,
+ gcc_jit_block_end_with_conditional (
+ loop_cond, NULL,
gcc_jit_context_new_comparison (
ctxt, NULL,
GCC_JIT_COMPARISON_GE,
gcc_jit_lvalue_as_rvalue (i),
gcc_jit_param_as_rvalue (n)),
- label_after_loop,
- NULL);
+ after_loop,
+ loop_body);
/* sum += i * i */
- gcc_jit_function_add_assignment (
- func, NULL,
+ gcc_jit_block_add_assignment (
+ loop_body, NULL,
sum,
gcc_jit_context_new_binary_op (
ctxt, NULL,
@@ -89,8 +91,8 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_lvalue_as_rvalue (i))));
/* i++ */
- gcc_jit_function_add_assignment (
- func, NULL,
+ gcc_jit_block_add_assignment (
+ loop_body, NULL,
i,
gcc_jit_context_new_binary_op (
ctxt, NULL,
@@ -101,17 +103,11 @@ create_code (gcc_jit_context *ctxt, void *user_data)
the_type,
1)));
- /* goto label_cond; */
- gcc_jit_function_add_jump (
- func, NULL,
- label_cond);
-
- /* label "after_loop:" */
- gcc_jit_function_place_forward_label (func, NULL, label_after_loop);
+ gcc_jit_block_end_with_jump (loop_body, NULL, loop_cond);
/* return sum */
- gcc_jit_function_add_return (
- func,
+ gcc_jit_block_end_with_return (
+ after_loop,
NULL,
gcc_jit_lvalue_as_rvalue (sum));
}
@@ -182,11 +182,12 @@ create_code (gcc_jit_context *ctxt, void *user_data)
"test_types",
1, ¶m_z,
0);
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
/* Write to the various fields of param "z". */
#define ASSIGN(FIELD, EXPR) \
- gcc_jit_function_add_assignment ( \
- test_fn, NULL, \
+ gcc_jit_block_add_assignment ( \
+ block, NULL, \
gcc_jit_rvalue_dereference_field ( \
gcc_jit_param_as_rvalue (param_z), \
NULL, \
@@ -305,6 +306,8 @@ create_code (gcc_jit_context *ctxt, void *user_data)
stderr))
#undef ASSIGN
+
+ gcc_jit_block_end_with_void_return (block, NULL);
}
void
@@ -40,12 +40,14 @@ create_code (gcc_jit_context *ctxt, void *user_data)
"test_using_global",
0, NULL,
0);
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
- gcc_jit_function_add_assignment_op (
- test_fn, NULL,
+ gcc_jit_block_add_assignment_op (
+ block, NULL,
gcc_jit_context_new_global (ctxt, NULL, int_type, "the_global"),
GCC_JIT_BINARY_OP_PLUS,
gcc_jit_context_one (ctxt, int_type));
+ gcc_jit_block_end_with_void_return (block, NULL);
}
int the_global;