Skip to content

Commit c0c560f

Browse files
committed
Add support for try/catch
1 parent c5c3a0d commit c0c560f

14 files changed

+407
-3
lines changed

gcc/dwarf2asm.cc

+10
Original file line numberDiff line numberDiff line change
@@ -1159,4 +1159,14 @@ dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool is_public,
11591159
va_end (ap);
11601160
}
11611161

1162+
void dwarf2asm_cc_finalize (void)
1163+
{
1164+
if (indirect_pool)
1165+
{
1166+
indirect_pool->empty();
1167+
indirect_pool = NULL;
1168+
}
1169+
dw2_const_labelno = 0;
1170+
}
1171+
11621172
#include "gt-dwarf2asm.h"

gcc/dwarf2asm.h

+2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ extern const char *eh_data_format_name (int);
8686
extern rtx dw2_force_const_mem (rtx, bool);
8787
extern void dw2_output_indirect_constants (void);
8888

89+
void dwarf2asm_cc_finalize (void);
90+
8991
/* These are currently unused. */
9092

9193
#if 0

gcc/dwarf2out.cc

+3
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,9 @@ dwarf2out_do_cfi_startproc (bool second)
10031003
if (targetm.asm_out.make_eh_symbol_indirect != NULL)
10041004
ref = targetm.asm_out.make_eh_symbol_indirect (ref, true);
10051005
else
1006+
// TODO: HERE: should not insert multiple times the same personality function.
1007+
// If we don't, we segfault later, possibly because we don't generate the info for the duplicates.
1008+
// I'm not sure why it's attempting to insert multiple times the same personality function.
10061009
ref = dw2_force_const_mem (ref, true);
10071010
}
10081011

gcc/jit/dummy-frontend.cc

+8-1
Original file line numberDiff line numberDiff line change
@@ -605,14 +605,21 @@ jit_langhook_init (void)
605605

606606
build_common_tree_nodes (flag_signed_char);
607607

608+
/* I don't know why this has to be done explicitly. */
609+
void_list_node = build_tree_list (NULL_TREE, void_type_node);
610+
611+
target_builtins.empty ();
608612
build_common_builtin_nodes ();
609613

614+
/* Initialize EH, if we've been told to do so. */
615+
if (flag_exceptions)
616+
using_eh_for_cleanups ();
617+
610618
/* The default precision for floating point numbers. This is used
611619
for floating point constants with abstract type. This may
612620
eventually be controllable by a command line option. */
613621
mpfr_set_default_prec (256);
614622

615-
target_builtins.empty ();
616623
targetm.init_builtins ();
617624

618625
return true;

gcc/jit/jit-playback.cc

+79
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ new_function (location *loc,
568568

569569
/* FIXME: this uses input_location: */
570570
tree fndecl = build_fn_decl (name, fn_type);
571+
TREE_NOTHROW (fndecl) = 0;
571572

572573
if (loc)
573574
set_tree_location (fndecl, loc);
@@ -2153,6 +2154,15 @@ playback::function::get_address (location *loc)
21532154
return new rvalue (m_ctxt, t_fnptr);
21542155
}
21552156

2157+
/* Construct a new local within this playback::function. */
2158+
2159+
void
2160+
playback::function::
2161+
set_personality_function (function *personality_function)
2162+
{
2163+
DECL_FUNCTION_PERSONALITY (m_inner_fndecl) = personality_function->as_fndecl ();
2164+
}
2165+
21562166
/* Build a statement list for the function as a whole out of the
21572167
lists of statements for the individual blocks, building labels
21582168
for each block. */
@@ -2171,6 +2181,11 @@ build_stmt_list ()
21712181
int j;
21722182
tree stmt;
21732183

2184+
// Do not add try/catch block to the function.
2185+
// TODO: explain why.
2186+
if (b->m_is_try_or_catch)
2187+
continue;
2188+
21742189
b->m_label_expr = build1 (LABEL_EXPR,
21752190
void_type_node,
21762191
b->as_label_decl ());
@@ -2269,6 +2284,70 @@ add_eval (location *loc,
22692284
add_stmt (rvalue->as_tree ());
22702285
}
22712286

2287+
2288+
void
2289+
playback::block::
2290+
add_try_catch (location *loc,
2291+
block *try_block,
2292+
block *catch_block,
2293+
bool is_finally)
2294+
{
2295+
gcc_assert (try_block);
2296+
gcc_assert (catch_block);
2297+
2298+
try_block->m_is_try_or_catch = true;
2299+
catch_block->m_is_try_or_catch = true;
2300+
2301+
if (loc)
2302+
{
2303+
set_tree_location (try_block->as_label_decl (), loc);
2304+
set_tree_location (catch_block->as_label_decl (), loc);
2305+
}
2306+
2307+
tree try_body = alloc_stmt_list ();
2308+
int i;
2309+
tree stmt;
2310+
FOR_EACH_VEC_ELT (try_block->m_stmts, i, stmt) {
2311+
append_to_statement_list (stmt, &try_body);
2312+
}
2313+
2314+
tree catch_body = alloc_stmt_list ();
2315+
int j;
2316+
tree catch_stmt;
2317+
FOR_EACH_VEC_ELT (catch_block->m_stmts, j, catch_stmt) {
2318+
append_to_statement_list (catch_stmt, &catch_body);
2319+
}
2320+
2321+
if (is_finally)
2322+
{
2323+
tree success_body = alloc_stmt_list ();
2324+
2325+
// TODO: find a better way to keep the EH_ELSE_EXPR than creating an empty inline asm.
2326+
tree t_string = build_string ("");
2327+
tree asm_stmt
2328+
= build5 (ASM_EXPR, void_type_node, t_string, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
2329+
2330+
// asm statements without outputs, including simple ones, are treated
2331+
// as volatile.
2332+
ASM_VOLATILE_P (asm_stmt) = 1;
2333+
ASM_INPUT_P (asm_stmt) = 0;
2334+
append_to_statement_list (asm_stmt, &success_body);
2335+
2336+
// TODO: Don't automatically add the `EH_ELSE_EXPR`. Make an API to create such a node and let the user of libgccjit
2337+
// add it manually.
2338+
catch_body = build2 (EH_ELSE_EXPR, void_type_node, success_body, catch_body);
2339+
add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node,
2340+
try_body, catch_body));
2341+
}
2342+
else
2343+
{
2344+
catch_body = build2(CATCH_EXPR, void_type_node, NULL, catch_body);
2345+
tree try_catch = build2 (TRY_CATCH_EXPR, void_type_node,
2346+
try_body, catch_body);
2347+
add_stmt (try_catch);
2348+
}
2349+
}
2350+
22722351
/* Add an assignment to the function's statement list. */
22732352

22742353
void

gcc/jit/jit-playback.h

+10
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,9 @@ class function : public wrapper
536536
rvalue *
537537
get_address (location *loc);
538538

539+
void
540+
set_personality_function (function *personality_function);
541+
539542
void
540543
build_stmt_list ();
541544

@@ -606,6 +609,12 @@ class block : public wrapper
606609
add_eval (location *loc,
607610
rvalue *rvalue);
608611

612+
void
613+
add_try_catch (location *loc,
614+
block *try_block,
615+
block *catch_block,
616+
bool is_finally);
617+
609618
void
610619
add_assignment (location *loc,
611620
lvalue *lvalue,
@@ -669,6 +678,7 @@ class block : public wrapper
669678

670679
public: // for now
671680
tree m_label_expr;
681+
bool m_is_try_or_catch = false;
672682

673683
friend class function;
674684
};

gcc/jit/jit-recording.cc

+122
Original file line numberDiff line numberDiff line change
@@ -4244,6 +4244,36 @@ recording::function::replay_into (replayer *r)
42444244
m_string_attributes));
42454245
}
42464246

4247+
/* Implementation of recording::memento::make_debug_string for
4248+
setting a personality function. */
4249+
4250+
recording::string *
4251+
recording::memento_of_set_personality_function::make_debug_string ()
4252+
{
4253+
return string::from_printf (m_ctxt,
4254+
"%s",
4255+
m_personality_function->get_debug_string ());
4256+
}
4257+
4258+
/* Implementation of recording::memento::write_reproducer for setting the personality function. */
4259+
4260+
void
4261+
recording::memento_of_set_personality_function::write_reproducer (reproducer &r)
4262+
{
4263+
r.write (" gcc_jit_function_set_personality_function (%s,\n"
4264+
" %s);\n",
4265+
r.get_identifier (m_function),
4266+
r.get_identifier (m_personality_function));
4267+
}
4268+
4269+
void
4270+
recording::function::set_personality_function (function *function)
4271+
{
4272+
recording::memento_of_set_personality_function *result =
4273+
new memento_of_set_personality_function (m_ctxt, this, function);
4274+
m_ctxt->record (result);
4275+
}
4276+
42474277
/* Create a recording::local instance and add it to
42484278
the functions's context's list of mementos, and to the function's
42494279
list of locals.
@@ -4386,6 +4416,13 @@ recording::function::validate ()
43864416
/* Iteratively walk the graph of blocks, marking their "m_is_reachable"
43874417
flag, starting at the initial block. */
43884418
auto_vec<block *> worklist (m_blocks.length ());
4419+
int j;
4420+
block *func_block;
4421+
/* Push the blocks used in try/catch because they're not successors of
4422+
other blocks. */
4423+
FOR_EACH_VEC_ELT (m_blocks, j, func_block)
4424+
if (func_block->m_is_reachable)
4425+
worklist.safe_push (func_block);
43894426
worklist.safe_push (m_blocks[0]);
43904427
while (worklist.length () > 0)
43914428
{
@@ -4581,6 +4618,27 @@ recording::block::add_eval (recording::location *loc,
45814618
return result;
45824619
}
45834620

4621+
/* The implementation of class gcc::jit::recording::block. */
4622+
4623+
/* Create a recording::try_catch instance and add it to
4624+
the block's context's list of mementos, and to the block's
4625+
list of statements.
4626+
Implements the heart of gcc_jit_block_add_try_catch. */
4627+
4628+
recording::statement *
4629+
recording::block::add_try_catch (location *loc,
4630+
block *try_block,
4631+
block *catch_block,
4632+
bool is_finally)
4633+
{
4634+
statement *result = new try_catch (this, loc, try_block, catch_block, is_finally);
4635+
try_block->m_is_reachable = true;
4636+
catch_block->m_is_reachable = true;
4637+
m_ctxt->record (result);
4638+
m_statements.safe_push (result);
4639+
return result;
4640+
}
4641+
45844642
/* Create a recording::assignment instance and add it to
45854643
the block's context's list of mementos, and to the block's
45864644
list of statements.
@@ -6997,6 +7055,17 @@ recording::statement::write_to_dump (dump &d)
69977055
m_loc = d.make_location ();
69987056
}
69997057

7058+
/* The implementation of class gcc::jit::recording::memento_of_set_personality_function. */
7059+
7060+
/* Implementation of pure virtual hook recording::memento::replay_into
7061+
for recording::memento_of_set_personality_function. */
7062+
7063+
void
7064+
recording::memento_of_set_personality_function::replay_into (replayer *r)
7065+
{
7066+
m_function->playback_function ()->set_personality_function (m_personality_function->playback_function ());
7067+
}
7068+
70007069
/* The implementation of class gcc::jit::recording::eval. */
70017070

70027071
/* Implementation of pure virtual hook recording::memento::replay_into
@@ -7035,6 +7104,59 @@ recording::eval::write_reproducer (reproducer &r)
70357104
r.get_identifier_as_rvalue (m_rvalue));
70367105
}
70377106

7107+
/* The implementation of class gcc::jit::recording::try_catch. */
7108+
7109+
/* Implementation of pure virtual hook recording::memento::replay_into
7110+
for recording::try_catch. */
7111+
7112+
void
7113+
recording::try_catch::replay_into (replayer *r)
7114+
{
7115+
playback_block (get_block ())
7116+
->add_try_catch (playback_location (r),
7117+
m_try_block->playback_block (),
7118+
m_catch_block->playback_block (),
7119+
m_is_finally);
7120+
}
7121+
7122+
/* Implementation of recording::memento::make_debug_string for
7123+
an eval statement. */
7124+
7125+
recording::string *
7126+
recording::try_catch::make_debug_string ()
7127+
{
7128+
if (m_is_finally)
7129+
return string::from_printf (m_ctxt,
7130+
"try { %s } finally { %s };",
7131+
m_try_block->get_debug_string (),
7132+
m_catch_block->get_debug_string ());
7133+
else
7134+
return string::from_printf (m_ctxt,
7135+
"try { %s } catch { %s };",
7136+
m_try_block->get_debug_string (),
7137+
m_catch_block->get_debug_string ());
7138+
}
7139+
7140+
/* Implementation of recording::memento::write_reproducer for
7141+
eval statements. */
7142+
7143+
void
7144+
recording::try_catch::write_reproducer (reproducer &r)
7145+
{
7146+
const char *func_name = "gcc_jit_block_add_try_catch";
7147+
if (m_is_finally)
7148+
func_name = "gcc_jit_block_add_try_finally";
7149+
r.write (" %s (%s, /*gcc_jit_block *block */\n"
7150+
" %s, /* gcc_jit_location *loc */\n"
7151+
" %s, /* gcc_jit_block *try_block */\n"
7152+
" %s); /* gcc_jit_block *catch_block */\n",
7153+
func_name,
7154+
r.get_identifier (get_block ()),
7155+
r.get_identifier (get_loc ()),
7156+
r.get_identifier (m_try_block),
7157+
r.get_identifier (m_catch_block));
7158+
}
7159+
70387160
/* The implementation of class gcc::jit::recording::assignment. */
70397161

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

0 commit comments

Comments
 (0)