Skip to content

Commit 7664770

Browse files
committed
Add support for personality function and try/catch
1 parent 6fc58e0 commit 7664770

File tree

7 files changed

+243
-4
lines changed

7 files changed

+243
-4
lines changed

gcc/jit/jit-playback.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,8 @@ new_function (location *loc,
491491
const char *name,
492492
const auto_vec<param *> *params,
493493
int is_variadic,
494-
enum built_in_function builtin_id)
494+
enum built_in_function builtin_id,
495+
function *personality_function)
495496
{
496497
int i;
497498
param *param;
@@ -515,6 +516,11 @@ new_function (location *loc,
515516
/* FIXME: this uses input_location: */
516517
tree fndecl = build_fn_decl (name, fn_type);
517518

519+
if (personality_function)
520+
{
521+
DECL_FUNCTION_PERSONALITY (fndecl) = personality_function->as_fndecl ();
522+
}
523+
518524
if (loc)
519525
set_tree_location (fndecl, loc);
520526

@@ -1742,6 +1748,10 @@ build_stmt_list ()
17421748
int j;
17431749
tree stmt;
17441750

1751+
if (b->m_is_try_or_finally) {
1752+
continue;
1753+
}
1754+
17451755
b->m_label_expr = build1 (LABEL_EXPR,
17461756
void_type_node,
17471757
b->as_label_decl ());
@@ -1752,6 +1762,42 @@ build_stmt_list ()
17521762
}
17531763
}
17541764

1765+
void
1766+
playback::block::
1767+
add_try_finally (location *loc,
1768+
block *try_block,
1769+
block *finally_block)
1770+
{
1771+
gcc_assert (try_block);
1772+
gcc_assert (finally_block);
1773+
1774+
try_block->m_is_try_or_finally = true;
1775+
finally_block->m_is_try_or_finally = true;
1776+
1777+
if (loc)
1778+
{
1779+
set_tree_location (try_block->as_label_decl (), loc);
1780+
set_tree_location (finally_block->as_label_decl (), loc);
1781+
}
1782+
1783+
tree try_body = alloc_stmt_list ();
1784+
int i;
1785+
tree stmt;
1786+
FOR_EACH_VEC_ELT (try_block->m_stmts, i, stmt) {
1787+
append_to_statement_list (stmt, &try_body);
1788+
}
1789+
1790+
tree finally_body = alloc_stmt_list ();
1791+
int j;
1792+
tree finally_stmt;
1793+
FOR_EACH_VEC_ELT (finally_block->m_stmts, j, finally_stmt) {
1794+
append_to_statement_list (finally_stmt, &finally_body);
1795+
}
1796+
1797+
add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node,
1798+
try_body, finally_body));
1799+
}
1800+
17551801
/* Finish compiling the given function, potentially running the
17561802
garbage-collector.
17571803
The function will have a statement list by now.

gcc/jit/jit-playback.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ class context : public log_user
107107
const char *name,
108108
const auto_vec<param *> *params,
109109
int is_variadic,
110-
enum built_in_function builtin_id);
110+
enum built_in_function builtin_id,
111+
function *personality_function);
111112

112113
lvalue *
113114
new_global (location *loc,
@@ -577,6 +578,11 @@ class block : public wrapper
577578
add_eval (location *loc,
578579
rvalue *rvalue);
579580

581+
void
582+
add_try_finally (location *loc,
583+
block *try_block,
584+
block *finally_block);
585+
580586
void
581587
add_assignment (location *loc,
582588
lvalue *lvalue,
@@ -640,6 +646,7 @@ class block : public wrapper
640646

641647
public: // for now
642648
tree m_label_expr;
649+
bool m_is_try_or_finally = false;
643650

644651
friend class function;
645652
};

gcc/jit/jit-recording.c

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4091,7 +4091,8 @@ recording::function::function (context *ctxt,
40914091
m_builtin_id (builtin_id),
40924092
m_locals (),
40934093
m_blocks (),
4094-
m_fn_ptr_type (NULL)
4094+
m_fn_ptr_type (NULL),
4095+
m_personality_function (NULL)
40954096
{
40964097
for (int i = 0; i< num_params; i++)
40974098
{
@@ -4144,13 +4145,20 @@ recording::function::replay_into (replayer *r)
41444145
FOR_EACH_VEC_ELT (m_params, i, param)
41454146
params.safe_push (param->playback_param ());
41464147

4148+
playback::function *personality_function = NULL;
4149+
if (m_personality_function)
4150+
{
4151+
personality_function = m_personality_function->playback_function ();
4152+
}
4153+
41474154
set_playback_obj (r->new_function (playback_location (r, m_loc),
41484155
m_kind,
41494156
m_return_type->playback_type (),
41504157
m_name->c_str (),
41514158
&params,
41524159
m_is_variadic,
4153-
m_builtin_id));
4160+
m_builtin_id,
4161+
personality_function));
41544162
}
41554163

41564164
/* Create a recording::local instance and add it to
@@ -4295,6 +4303,13 @@ recording::function::validate ()
42954303
/* Iteratively walk the graph of blocks, marking their "m_is_reachable"
42964304
flag, starting at the initial block. */
42974305
auto_vec<block *> worklist (m_blocks.length ());
4306+
int j;
4307+
block *func_block;
4308+
/* Push the blocks used in try/finally because they're not successors of
4309+
other blocks. */
4310+
FOR_EACH_VEC_ELT (m_blocks, j, func_block)
4311+
if (func_block->m_is_reachable)
4312+
worklist.safe_push (func_block);
42984313
worklist.safe_push (m_blocks[0]);
42994314
while (worklist.length () > 0)
43004315
{
@@ -4393,6 +4408,12 @@ recording::function::get_address (recording::location *loc)
43934408
return result;
43944409
}
43954410

4411+
void
4412+
recording::function::set_personality_function (function *function)
4413+
{
4414+
m_personality_function = function;
4415+
}
4416+
43964417
/* Implementation of recording::memento::make_debug_string for
43974418
functions. */
43984419

@@ -4477,6 +4498,29 @@ recording::block::add_eval (recording::location *loc,
44774498
return result;
44784499
}
44794500

4501+
/* The implementation of class gcc::jit::recording::block. */
4502+
4503+
/* Create a recording::try_finally instance and add it to
4504+
the block's context's list of mementos, and to the block's
4505+
list of statements.
4506+
4507+
Implements the heart of gcc_jit_block_add_try_finally. */
4508+
4509+
recording::statement *
4510+
recording::block::add_try_finally (location *loc,
4511+
block *try_block,
4512+
block *finally_block)
4513+
{
4514+
statement *result = new try_finally (this, loc, try_block, finally_block);
4515+
try_block->m_has_been_terminated = true;
4516+
finally_block->m_has_been_terminated = true;
4517+
try_block->m_is_reachable = true;
4518+
finally_block->m_is_reachable = true;
4519+
m_ctxt->record (result);
4520+
m_statements.safe_push (result);
4521+
return result;
4522+
}
4523+
44804524
/* Create a recording::assignment instance and add it to
44814525
the block's context's list of mementos, and to the block's
44824526
list of statements.
@@ -6719,6 +6763,48 @@ recording::eval::write_reproducer (reproducer &r)
67196763
r.get_identifier_as_rvalue (m_rvalue));
67206764
}
67216765

6766+
/* The implementation of class gcc::jit::recording::try_finally. */
6767+
6768+
/* Implementation of pure virtual hook recording::memento::replay_into
6769+
for recording::try_finally. */
6770+
6771+
void
6772+
recording::try_finally::replay_into (replayer *r)
6773+
{
6774+
playback_block (get_block ())
6775+
->add_try_finally (playback_location (r),
6776+
m_try_block->playback_block (),
6777+
m_finally_block->playback_block ());
6778+
}
6779+
6780+
/* Implementation of recording::memento::make_debug_string for
6781+
an eval statement. */
6782+
6783+
recording::string *
6784+
recording::try_finally::make_debug_string ()
6785+
{
6786+
return string::from_printf (m_ctxt,
6787+
"try { %s } finally { %s };",
6788+
m_try_block->get_debug_string (),
6789+
m_finally_block->get_debug_string ());
6790+
}
6791+
6792+
/* Implementation of recording::memento::write_reproducer for
6793+
eval statements. */
6794+
6795+
void
6796+
recording::try_finally::write_reproducer (reproducer &r)
6797+
{
6798+
r.write (" gcc_jit_block_add_try_finally (%s, /*gcc_jit_block *block */\n"
6799+
" %s, /* gcc_jit_location *loc */\n"
6800+
" %s, /* gcc_jit_block *try_block */\n"
6801+
" %s); /* gcc_jit_block *finally_block */\n",
6802+
r.get_identifier (get_block ()),
6803+
r.get_identifier (get_loc ()),
6804+
r.get_identifier (m_try_block),
6805+
r.get_identifier (m_finally_block));
6806+
}
6807+
67226808
/* The implementation of class gcc::jit::recording::assignment. */
67236809

67246810
/* Implementation of pure virtual hook recording::memento::replay_into

gcc/jit/jit-recording.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,7 @@ class function : public memento
13241324
void dump_to_dot (const char *path);
13251325

13261326
rvalue *get_address (location *loc);
1327+
void set_personality_function (function *function);
13271328

13281329
private:
13291330
string * make_debug_string () FINAL OVERRIDE;
@@ -1340,6 +1341,7 @@ class function : public memento
13401341
auto_vec<local *> m_locals;
13411342
auto_vec<block *> m_blocks;
13421343
type *m_fn_ptr_type;
1344+
function *m_personality_function;
13431345
};
13441346

13451347
class block : public memento
@@ -1368,6 +1370,11 @@ class block : public memento
13681370
add_eval (location *loc,
13691371
rvalue *rvalue);
13701372

1373+
statement *
1374+
add_try_finally (location *loc,
1375+
block *try_block,
1376+
block *finally_block);
1377+
13711378
statement *
13721379
add_assignment (location *loc,
13731380
lvalue *lvalue,
@@ -2170,6 +2177,28 @@ class statement : public memento
21702177
location *m_loc;
21712178
};
21722179

2180+
class try_finally : public statement
2181+
{
2182+
public:
2183+
try_finally (block *b,
2184+
location *loc,
2185+
block *try_block,
2186+
block *finally_block)
2187+
: statement (b, loc),
2188+
m_try_block (try_block),
2189+
m_finally_block (finally_block) {}
2190+
2191+
void replay_into (replayer *r) FINAL OVERRIDE;
2192+
2193+
private:
2194+
string * make_debug_string () FINAL OVERRIDE;
2195+
void write_reproducer (reproducer &r) FINAL OVERRIDE;
2196+
2197+
private:
2198+
block *m_try_block;
2199+
block *m_finally_block;
2200+
};
2201+
21732202
class eval : public statement
21742203
{
21752204
public:

gcc/jit/libgccjit.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2509,6 +2509,35 @@ gcc_jit_block_add_eval (gcc_jit_block *block,
25092509
rvalue->verify_valid_within_stmt (__func__, stmt);
25102510
}
25112511

2512+
/* Public entrypoint. See description in libgccjit.h.
2513+
2514+
After error-checking, the real work is done by the
2515+
gcc::jit::recording::block::add_try_finally method in jit-recording.c. */
2516+
2517+
void
2518+
gcc_jit_block_add_try_finally (gcc_jit_block *block,
2519+
gcc_jit_location *loc,
2520+
gcc_jit_block *try_block,
2521+
gcc_jit_block *finally_block)
2522+
{
2523+
RETURN_IF_NOT_VALID_BLOCK (block, loc);
2524+
gcc::jit::recording::context *ctxt = block->get_context ();
2525+
JIT_LOG_FUNC (ctxt->get_logger ());
2526+
/* LOC can be NULL. */
2527+
RETURN_IF_FAIL (try_block, ctxt, loc, "NULL rvalue");
2528+
RETURN_IF_FAIL (finally_block, ctxt, loc, "NULL rvalue");
2529+
2530+
gcc::jit::recording::statement *stmt = block->add_try_finally (loc, try_block, finally_block);
2531+
2532+
/* "stmt" should be good enough to be usable in error-messages,
2533+
but might still not be compilable; perform some more
2534+
error-checking here. We do this here so that the error messages
2535+
can contain a stringified version of "stmt", whilst appearing
2536+
as close as possible to the point of failure. */
2537+
/*try_block->verify_valid_within_stmt (__func__, stmt);
2538+
finally_block->verify_valid_within_stmt (__func__, stmt);*/
2539+
}
2540+
25122541
/* Public entrypoint. See description in libgccjit.h.
25132542
25142543
After error-checking, the real work is done by the
@@ -3689,6 +3718,21 @@ gcc_jit_function_get_address (gcc_jit_function *fn,
36893718
return (gcc_jit_rvalue *)fn->get_address (loc);
36903719
}
36913720

3721+
/* Public entrypoint. See description in libgccjit.h.
3722+
3723+
After error-checking, the real work is done by the
3724+
gcc::jit::recording::function::set_personality_function method, in
3725+
jit-recording.c. */
3726+
3727+
void
3728+
gcc_jit_function_set_personality_function (gcc_jit_function *fn,
3729+
gcc_jit_function *personality_func)
3730+
{
3731+
RETURN_IF_FAIL (fn, NULL, NULL, "NULL function");
3732+
3733+
fn->set_personality_function (personality_func);
3734+
}
3735+
36923736
/* Public entrypoint. See description in libgccjit.h.
36933737
36943738
After error-checking, the real work is done by the

gcc/jit/libgccjit.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,24 @@ gcc_jit_block_add_eval (gcc_jit_block *block,
12061206
gcc_jit_location *loc,
12071207
gcc_jit_rvalue *rvalue);
12081208

1209+
/* Add a try/finally statement.
1210+
1211+
This is equivalent to this C++ code:
1212+
1213+
try {
1214+
try_block
1215+
}
1216+
finally {
1217+
finally_block
1218+
}
1219+
*/
1220+
1221+
void
1222+
gcc_jit_block_add_try_finally (gcc_jit_block *block,
1223+
gcc_jit_location *loc,
1224+
gcc_jit_block *try_block,
1225+
gcc_jit_block *finally_block);
1226+
12091227
/* Add evaluation of an rvalue, assigning the result to the given
12101228
lvalue.
12111229
@@ -1603,6 +1621,9 @@ extern gcc_jit_rvalue *
16031621
gcc_jit_function_get_address (gcc_jit_function *fn,
16041622
gcc_jit_location *loc);
16051623

1624+
void
1625+
gcc_jit_function_set_personality_function (gcc_jit_function *fn,
1626+
gcc_jit_function *personality_func);
16061627

16071628
#define LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
16081629

0 commit comments

Comments
 (0)