WIP: add support for try/catch
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 4be67e3..bfc2573 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -25,6 +25,7 @@
#include "ipa-ref.h"
#include "plugin-api.h"
#include "ipa-param-manipulation.h"
+#include "print-tree.h"
extern void debuginfo_early_init (void);
extern void debuginfo_init (void);
diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index 7b5be0f..cef7d0b 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -240,9 +240,14 @@
/* Double check that no one output the function into assembly file
early. */
if (!native_rtl_p ())
+ {
+ if (!(!DECL_ASSEMBLER_NAME_SET_P (decl)
+ || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+ debug_tree (decl);
gcc_checking_assert
(!DECL_ASSEMBLER_NAME_SET_P (decl)
|| !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
+ }
if (!definition)
return false;
@@ -1390,7 +1395,7 @@
|| cnode->alias
|| gimple_has_body_p (decl)
|| cnode->native_rtl_p ());
- gcc_assert (cnode->analyzed == cnode->definition);
+ gcc_assert (cnode->analyzed == cnode->definition);
}
node->aux = NULL;
}
diff --git a/gcc/dwarf2asm.cc b/gcc/dwarf2asm.cc
index 274f574..e640a71 100644
--- a/gcc/dwarf2asm.cc
+++ b/gcc/dwarf2asm.cc
@@ -938,7 +938,7 @@
/* The strings are always those from IDENTIFIER_NODEs, and,
therefore, we should never have two copies of the same
string. */
- gcc_assert (ret);
+ //gcc_assert (ret);
return ret;
}
@@ -1159,4 +1159,14 @@
va_end (ap);
}
+void dwarf2asm_cc_finalize (void)
+{
+ if (indirect_pool)
+ {
+ indirect_pool->empty();
+ indirect_pool = NULL;
+ }
+ dw2_const_labelno = 0;
+}
+
#include "gt-dwarf2asm.h"
diff --git a/gcc/dwarf2asm.h b/gcc/dwarf2asm.h
index 871a77b..53720ab 100644
--- a/gcc/dwarf2asm.h
+++ b/gcc/dwarf2asm.h
@@ -86,6 +86,8 @@
extern rtx dw2_force_const_mem (rtx, bool);
extern void dw2_output_indirect_constants (void);
+void dwarf2asm_cc_finalize (void);
+
/* These are currently unused. */
#if 0
diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 28a4ae0..1bf4289 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -1003,6 +1003,9 @@
if (targetm.asm_out.make_eh_symbol_indirect != NULL)
ref = targetm.asm_out.make_eh_symbol_indirect (ref, true);
else
+ // TODO: HERE: should not insert multiple times the same personality function.
+ // If we don't, we segfault later, possibly because we don't generate the info for the duplicates.
+ // I'm not sure why it's attempting to insert multiple times the same personality function.
ref = dw2_force_const_mem (ref, true);
}
diff --git a/gcc/ipa-visibility.cc b/gcc/ipa-visibility.cc
index 8a27e7b..8b1a0a4 100644
--- a/gcc/ipa-visibility.cc
+++ b/gcc/ipa-visibility.cc
@@ -709,6 +709,15 @@
}
node->dissolve_same_comdat_group_list ();
}
+ if (!((!DECL_WEAK (node->decl)
+ && !DECL_COMDAT (node->decl))
+ || TREE_PUBLIC (node->decl)
+ || node->weakref
+ || DECL_EXTERNAL (node->decl)))
+ {
+ fprintf (stderr, "%d, %d, %d, %d, %d\n", DECL_WEAK (node->decl), DECL_COMDAT (node->decl), TREE_PUBLIC (node->decl), node->weakref, DECL_EXTERNAL (node->decl));
+ debug_tree (node->decl);
+ }
gcc_assert ((!DECL_WEAK (node->decl)
&& !DECL_COMDAT (node->decl))
|| TREE_PUBLIC (node->decl)
diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc
index 1110993..a9330f5 100644
--- a/gcc/jit/dummy-frontend.cc
+++ b/gcc/jit/dummy-frontend.cc
@@ -611,6 +611,10 @@
target_builtins.empty ();
build_common_builtin_nodes ();
+ /* Initialize EH, if we've been told to do so. */
+ if (flag_exceptions)
+ using_eh_for_cleanups ();
+
/* The default precision for floating point numbers. This is used
for floating point constants with abstract type. This may
eventually be controllable by a command line option. */
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index 83c8c21..775e08f 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -547,8 +547,7 @@
enum built_in_function builtin_id,
int is_target_builtin,
const std::vector<gcc_jit_fn_attribute> &attributes,
- const std::vector<std::pair<gcc_jit_fn_attribute, std::string>> &string_attributes,
- function *personality_function)
+ const std::vector<std::pair<gcc_jit_fn_attribute, std::string>> &string_attributes)
{
int i;
param *param;
@@ -571,11 +570,7 @@
/* FIXME: this uses input_location: */
tree fndecl = build_fn_decl (name, fn_type);
-
- if (personality_function)
- {
- DECL_FUNCTION_PERSONALITY (fndecl) = personality_function->as_fndecl ();
- }
+ TREE_NOTHROW (fndecl) = 0;
if (loc)
set_tree_location (fndecl, loc);
@@ -659,6 +654,9 @@
break;
case GCC_JIT_FN_ATTRIBUTE_WEAK:
DECL_WEAK (fndecl) = 1;
+ TREE_PUBLIC (fndecl) = 1;
+ //declare_weak (fndecl);
+ //make_decl_one_only(fndecl, DECL_ASSEMBLER_NAME(fndecl));
break;
}
@@ -2164,6 +2162,16 @@
return new rvalue (m_ctxt, t_fnptr);
}
+/* Construct a new local within this playback::function. */
+
+void
+playback::function::
+set_personality_function (function *personality_function)
+{
+ //fprintf (stderr, "************* Setting personality function %s for %s\n", IDENTIFIER_POINTER (DECL_NAME (personality_function->as_fndecl ())), IDENTIFIER_POINTER (DECL_NAME (m_inner_fndecl)));
+ DECL_FUNCTION_PERSONALITY (m_inner_fndecl) = personality_function->as_fndecl ();
+}
+
/* Build a statement list for the function as a whole out of the
lists of statements for the individual blocks, building labels
for each block. */
@@ -2222,8 +2230,11 @@
if (m_kind == GCC_JIT_FUNCTION_INTERNAL
||m_kind == GCC_JIT_FUNCTION_ALWAYS_INLINE)
{
- DECL_EXTERNAL (m_inner_fndecl) = 0;
- TREE_PUBLIC (m_inner_fndecl) = 0;
+ if (!DECL_WEAK (m_inner_fndecl))
+ {
+ DECL_EXTERNAL (m_inner_fndecl) = 0;
+ TREE_PUBLIC (m_inner_fndecl) = 0;
+ }
}
if (m_kind != GCC_JIT_FUNCTION_IMPORTED)
@@ -2290,7 +2301,8 @@
playback::block::
add_try_catch (location *loc,
block *try_block,
- block *catch_block)
+ block *catch_block,
+ bool is_finally)
{
gcc_assert (try_block);
gcc_assert (catch_block);
@@ -2318,8 +2330,38 @@
append_to_statement_list (catch_stmt, &catch_body);
}
- add_stmt (build2 (TRY_CATCH_EXPR, void_type_node,
+ if (is_finally)
+ {
+ tree noop = build_int_cst (integer_type_node, 0);
+ tree stmt = build1 (NOP_EXPR, void_type_node, size_zero_node);
+ tree success_body = alloc_stmt_list ();
+ //append_to_statement_list (stmt, &success_body);
+
+
+ tree t_string = build_string ("nop");
+ tree asm_stmt
+ = build5 (ASM_EXPR, void_type_node, t_string, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
+
+ // asm statements without outputs, including simple ones, are treated
+ // as volatile.
+ ASM_VOLATILE_P (asm_stmt) = 1;
+ ASM_INPUT_P (asm_stmt) = 0;
+ append_to_statement_list (asm_stmt, &success_body);
+ //debug_tree (success_body);
+
+ catch_body = build2 (EH_ELSE_EXPR, void_type_node, success_body, catch_body);
+ add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node,
try_body, catch_body));
+ }
+ else
+ {
+ catch_body = build2(CATCH_EXPR, void_type_node, NULL, catch_body);
+ tree try_catch = build2 (TRY_CATCH_EXPR, void_type_node,
+ try_body, catch_body);
+ //if (is_finally)
+ // TRY_CATCH_IS_CLEANUP (try_catch) = true;
+ add_stmt (try_catch);
+ }
}
/* Add an assignment to the function's statement list. */
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 75fb21b..83021bb 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -113,8 +113,7 @@
enum built_in_function builtin_id,
int is_target_builtin,
const std::vector<gcc_jit_fn_attribute> &attributes,
- const std::vector<std::pair<gcc_jit_fn_attribute, std::string>> &string_attributes,
- function *personality_function);
+ const std::vector<std::pair<gcc_jit_fn_attribute, std::string>> &string_attributes);
lvalue *
new_global (location *loc,
@@ -537,6 +536,9 @@
get_address (location *loc);
void
+ set_personality_function (function *personality_function);
+
+ void
build_stmt_list ();
void
@@ -609,7 +611,8 @@
void
add_try_catch (location *loc,
block *try_block,
- block *catch_block);
+ block *catch_block,
+ bool is_finally);
void
add_assignment (location *loc,
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index ba87421..c5420c5 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -4180,8 +4180,7 @@
m_fn_ptr_type (NULL),
m_is_target_builtin (is_target_builtin),
m_attributes(),
- m_string_attributes(),
- m_personality_function (NULL)
+ m_string_attributes()
{
for (int i = 0; i< num_params; i++)
{
@@ -4234,12 +4233,6 @@
FOR_EACH_VEC_ELT (m_params, i, param)
params.safe_push (param->playback_param ());
- playback::function *personality_function = NULL;
- if (m_personality_function)
- {
- personality_function = m_personality_function->playback_function ();
- }
-
set_playback_obj (r->new_function (playback_location (r, m_loc),
m_kind,
m_return_type->playback_type (),
@@ -4249,14 +4242,37 @@
m_builtin_id,
m_is_target_builtin,
m_attributes,
- m_string_attributes,
- personality_function));
+ m_string_attributes));
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ setting a personality function. */
+
+recording::string *
+recording::memento_of_set_personality_function::make_debug_string ()
+{
+ return string::from_printf (m_ctxt,
+ "%s",
+ m_personality_function->get_debug_string ());
+}
+
+/* Implementation of recording::memento::write_reproducer for setting the personality function. */
+
+void
+recording::memento_of_set_personality_function::write_reproducer (reproducer &r)
+{
+ r.write (" gcc_jit_function_set_personality_function (%s,\n"
+ " %s);\n",
+ r.get_identifier (m_function),
+ r.get_identifier (m_personality_function));
}
void
recording::function::set_personality_function (function *function)
{
- m_personality_function = function;
+ recording::memento_of_set_personality_function *result =
+ new memento_of_set_personality_function (m_ctxt, this, function);
+ m_ctxt->record (result);
}
/* Create a recording::local instance and add it to
@@ -4613,9 +4629,10 @@
recording::statement *
recording::block::add_try_catch (location *loc,
block *try_block,
- block *catch_block)
+ block *catch_block,
+ bool is_finally)
{
- statement *result = new try_catch (this, loc, try_block, catch_block);
+ statement *result = new try_catch (this, loc, try_block, catch_block, is_finally);
//try_block->m_has_been_terminated = true;
//catch_block->m_has_been_terminated = true;
try_block->m_is_reachable = true;
@@ -7041,6 +7058,17 @@
m_loc = d.make_location ();
}
+/* The implementation of class gcc::jit::recording::memento_of_set_personality_function. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_set_personality_function. */
+
+void
+recording::memento_of_set_personality_function::replay_into (replayer *r)
+{
+ m_function->playback_function ()->set_personality_function (m_personality_function->playback_function ());
+}
+
/* The implementation of class gcc::jit::recording::eval. */
/* Implementation of pure virtual hook recording::memento::replay_into
@@ -7090,7 +7118,8 @@
playback_block (get_block ())
->add_try_catch (playback_location (r),
m_try_block->playback_block (),
- m_catch_block->playback_block ());
+ m_catch_block->playback_block (),
+ m_is_finally);
}
/* Implementation of recording::memento::make_debug_string for
@@ -7099,6 +7128,7 @@
recording::string *
recording::try_catch::make_debug_string ()
{
+ // TODO: handle m_is_finally.
return string::from_printf (m_ctxt,
"try { %s } catch { %s };",
m_try_block->get_debug_string (),
@@ -7111,6 +7141,7 @@
void
recording::try_catch::write_reproducer (reproducer &r)
{
+ // TODO: handle m_is_finally.
r.write (" gcc_jit_block_add_try_catch (%s, /*gcc_jit_block *block */\n"
" %s, /* gcc_jit_location *loc */\n"
" %s, /* gcc_jit_block *try_block */\n"
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 246bf3e..547f5de 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -1465,7 +1465,6 @@
int m_is_target_builtin;
std::vector<gcc_jit_fn_attribute> m_attributes;
std::vector<std::pair<gcc_jit_fn_attribute, std::string>> m_string_attributes;
- function *m_personality_function;
};
class block : public memento
@@ -1497,7 +1496,8 @@
statement *
add_try_catch (location *loc,
block *try_block,
- block *catch_block);
+ block *catch_block,
+ bool is_finally = false);
statement *
add_assignment (location *loc,
@@ -1714,6 +1714,27 @@
string *m_value;
};
+class memento_of_set_personality_function : public memento
+{
+public:
+ memento_of_set_personality_function (context *ctx,
+ function *func,
+ function *personality_function)
+ : memento(ctx),
+ m_function (func),
+ m_personality_function (personality_function) {}
+
+ void replay_into (replayer *r) final override;
+
+private:
+ string * make_debug_string () final override;
+ void write_reproducer (reproducer &r) final override;
+
+private:
+ function *m_function;
+ function *m_personality_function;
+};
+
class memento_of_new_rvalue_from_vector : public rvalue
{
public:
@@ -2357,10 +2378,12 @@
try_catch (block *b,
location *loc,
block *try_block,
- block *catch_block)
+ block *catch_block,
+ bool is_finally = false)
: statement (b, loc),
m_try_block (try_block),
- m_catch_block (catch_block) {}
+ m_catch_block (catch_block),
+ m_is_finally (is_finally) {}
void replay_into (replayer *r) final override;
@@ -2371,6 +2394,7 @@
private:
block *m_try_block;
block *m_catch_block;
+ bool m_is_finally;
};
class assignment : public statement
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index 16c8208..98cd254 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -2967,6 +2967,34 @@
}
/* Public entrypoint. See description in libgccjit.h.
+ After error-checking, the real work is done by the
+ gcc::jit::recording::block::add_try_catch method in jit-recording.c. */
+
+void
+gcc_jit_block_add_try_finally (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_block *try_block,
+ gcc_jit_block *finally_block)
+{
+ RETURN_IF_NOT_VALID_BLOCK (block, loc);
+ gcc::jit::recording::context *ctxt = block->get_context ();
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_IF_FAIL (try_block, ctxt, loc, "NULL rvalue");
+ RETURN_IF_FAIL (finally_block, ctxt, loc, "NULL rvalue");
+
+ gcc::jit::recording::statement *stmt = block->add_try_catch (loc, try_block, finally_block, true);
+
+ /* "stmt" should be good enough to be usable in error-messages,
+ but might still not be compilable; perform some more
+ error-checking here. We do this here so that the error messages
+ can contain a stringified version of "stmt", whilst appearing
+ as close as possible to the point of failure. */
+ /*try_block->verify_valid_within_stmt (__func__, stmt);
+ catch_block->verify_valid_within_stmt (__func__, stmt);*/
+}
+
+/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
gcc::jit::recording::block::add_assignment method in
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 1fd5c87..399e5c8 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1427,7 +1427,7 @@
try {
try_block
}
- catch {
+ catch (...) {
catch_block
}
*/
@@ -1438,6 +1438,22 @@
gcc_jit_block *try_block,
gcc_jit_block *catch_block);
+/* Add a try/finally statement.
+ This is equivalent to this C++-like code:
+ try {
+ try_block
+ }
+ finally {
+ finally_block
+ }
+*/
+
+void
+gcc_jit_block_add_try_finally (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_block *try_block,
+ gcc_jit_block *finally_block);
+
/* Add evaluation of an rvalue, assigning the result to the given
lvalue.
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index a1fc114..4d6a6ca 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -314,5 +314,6 @@
LIBGCCJIT_ABI_32 {
global:
gcc_jit_block_add_try_catch;
+ gcc_jit_block_add_try_finally;
gcc_jit_function_set_personality_function;
} LIBGCCJIT_ABI_31;
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 61d234a..9456c95 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -2353,6 +2353,7 @@
cgraphunit_cc_finalize ();
symtab_thunks_cc_finalize ();
dwarf2out_cc_finalize ();
+ dwarf2asm_cc_finalize ();
gcse_cc_finalize ();
ipa_cp_cc_finalize ();
ira_costs_cc_finalize ();
diff --git a/gcc/tree-eh.cc b/gcc/tree-eh.cc
index 076ecd3..38b8ea8 100644
--- a/gcc/tree-eh.cc
+++ b/gcc/tree-eh.cc
@@ -4882,7 +4882,11 @@
and avoids references to a never defined personality routine. */
if (DECL_FUNCTION_PERSONALITY (current_function_decl)
&& function_needs_eh_personality (fun) != eh_personality_lang)
- DECL_FUNCTION_PERSONALITY (current_function_decl) = NULL_TREE;
+ {
+ //fprintf(stderr, "Unset personality function for %s\n", IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
+ // TODO: uncomment:
+ //DECL_FUNCTION_PERSONALITY (current_function_decl) = NULL_TREE;
+ }
return ret;
}
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 007c932..0388284 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -14766,6 +14766,7 @@
tree_cc_finalize (void)
{
clear_nonstandard_integer_type_cache ();
+ gcc_eh_personality_decl = NULL;
}
#if CHECKING_P