aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-nested.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-nested.cc')
-rw-r--r--gcc/tree-nested.cc121
1 files changed, 104 insertions, 17 deletions
diff --git a/gcc/tree-nested.cc b/gcc/tree-nested.cc
index 31c7b60..d2fe3fc 100644
--- a/gcc/tree-nested.cc
+++ b/gcc/tree-nested.cc
@@ -611,6 +611,14 @@ get_trampoline_type (struct nesting_info *info)
if (trampoline_type)
return trampoline_type;
+ /* When trampolines are created off-stack then the only thing we need in the
+ local frame is a single pointer. */
+ if (flag_trampoline_impl == TRAMPOLINE_IMPL_HEAP)
+ {
+ trampoline_type = build_pointer_type (void_type_node);
+ return trampoline_type;
+ }
+
align = TRAMPOLINE_ALIGNMENT;
size = TRAMPOLINE_SIZE;
@@ -2790,17 +2798,27 @@ convert_tramp_reference_op (tree *tp, int *walk_subtrees, void *data)
/* Compute the address of the field holding the trampoline. */
x = get_frame_field (info, target_context, x, &wi->gsi);
- x = build_addr (x);
- x = gsi_gimplify_val (info, x, &wi->gsi);
- /* Do machine-specific ugliness. Normally this will involve
- computing extra alignment, but it can really be anything. */
- if (descr)
- builtin = builtin_decl_implicit (BUILT_IN_ADJUST_DESCRIPTOR);
+ /* APB: We don't need to do the adjustment calls when using off-stack
+ trampolines, any such adjustment will be done when the off-stack
+ trampoline is created. */
+ if (!descr && flag_trampoline_impl == TRAMPOLINE_IMPL_HEAP)
+ x = gsi_gimplify_val (info, x, &wi->gsi);
else
- builtin = builtin_decl_implicit (BUILT_IN_ADJUST_TRAMPOLINE);
- call = gimple_build_call (builtin, 1, x);
- x = init_tmp_var_with_call (info, &wi->gsi, call);
+ {
+ x = build_addr (x);
+
+ x = gsi_gimplify_val (info, x, &wi->gsi);
+
+ /* Do machine-specific ugliness. Normally this will involve
+ computing extra alignment, but it can really be anything. */
+ if (descr)
+ builtin = builtin_decl_implicit (BUILT_IN_ADJUST_DESCRIPTOR);
+ else
+ builtin = builtin_decl_implicit (BUILT_IN_ADJUST_TRAMPOLINE);
+ call = gimple_build_call (builtin, 1, x);
+ x = init_tmp_var_with_call (info, &wi->gsi, call);
+ }
/* Cast back to the proper function type. */
x = build1 (NOP_EXPR, TREE_TYPE (t), x);
@@ -3380,6 +3398,7 @@ build_init_call_stmt (struct nesting_info *info, tree decl, tree field,
static void
finalize_nesting_tree_1 (struct nesting_info *root)
{
+ gimple_seq cleanup_list = NULL;
gimple_seq stmt_list = NULL;
gimple *stmt;
tree context = root->context;
@@ -3511,9 +3530,48 @@ finalize_nesting_tree_1 (struct nesting_info *root)
if (!field)
continue;
- x = builtin_decl_implicit (BUILT_IN_INIT_TRAMPOLINE);
- stmt = build_init_call_stmt (root, i->context, field, x);
- gimple_seq_add_stmt (&stmt_list, stmt);
+ if (flag_trampoline_impl == TRAMPOLINE_IMPL_HEAP)
+ {
+ /* We pass a whole bunch of arguments to the builtin function that
+ creates the off-stack trampoline, these are
+ 1. The nested function chain value (that must be passed to the
+ nested function so it can find the function arguments).
+ 2. A pointer to the nested function implementation,
+ 3. The address in the local stack frame where we should write
+ the address of the trampoline.
+
+ When this code was originally written I just kind of threw
+ everything at the builtin, figuring I'd work out what was
+ actually needed later, I think, the stack pointer could
+ certainly be dropped, arguments #2 and #4 are based off the
+ stack pointer anyway, so #1 doesn't seem to add much value. */
+ tree arg1, arg2, arg3;
+
+ gcc_assert (DECL_STATIC_CHAIN (i->context));
+ arg1 = build_addr (root->frame_decl);
+ arg2 = build_addr (i->context);
+
+ x = build3 (COMPONENT_REF, TREE_TYPE (field),
+ root->frame_decl, field, NULL_TREE);
+ arg3 = build_addr (x);
+
+ x = builtin_decl_implicit (BUILT_IN_NESTED_PTR_CREATED);
+ stmt = gimple_build_call (x, 3, arg1, arg2, arg3);
+ gimple_seq_add_stmt (&stmt_list, stmt);
+
+ /* This call to delete the nested function trampoline is added to
+ the cleanup list, and called when we exit the current scope. */
+ x = builtin_decl_implicit (BUILT_IN_NESTED_PTR_DELETED);
+ stmt = gimple_build_call (x, 0);
+ gimple_seq_add_stmt (&cleanup_list, stmt);
+ }
+ else
+ {
+ /* Original code to initialise the on stack trampoline. */
+ x = builtin_decl_implicit (BUILT_IN_INIT_TRAMPOLINE);
+ stmt = build_init_call_stmt (root, i->context, field, x);
+ gimple_seq_add_stmt (&stmt_list, stmt);
+ }
}
}
@@ -3538,11 +3596,40 @@ finalize_nesting_tree_1 (struct nesting_info *root)
/* If we created initialization statements, insert them. */
if (stmt_list)
{
- gbind *bind;
- annotate_all_with_location (stmt_list, DECL_SOURCE_LOCATION (context));
- bind = gimple_seq_first_stmt_as_a_bind (gimple_body (context));
- gimple_seq_add_seq (&stmt_list, gimple_bind_body (bind));
- gimple_bind_set_body (bind, stmt_list);
+ if (flag_trampoline_impl == TRAMPOLINE_IMPL_HEAP)
+ {
+ /* Handle off-stack trampolines. */
+ gbind *bind;
+ annotate_all_with_location (stmt_list, DECL_SOURCE_LOCATION (context));
+ annotate_all_with_location (cleanup_list, DECL_SOURCE_LOCATION (context));
+ bind = gimple_seq_first_stmt_as_a_bind (gimple_body (context));
+ gimple_seq_add_seq (&stmt_list, gimple_bind_body (bind));
+
+ gimple_seq xxx_list = NULL;
+
+ if (cleanup_list != NULL)
+ {
+ /* Maybe we shouldn't be creating this try/finally if -fno-exceptions is
+ in use. If this is the case, then maybe we should, instead, be
+ inserting the cleanup code onto every path out of this function? Not
+ yet figured out how we would do this. */
+ gtry *t = gimple_build_try (stmt_list, cleanup_list, GIMPLE_TRY_FINALLY);
+ gimple_seq_add_stmt (&xxx_list, t);
+ }
+ else
+ xxx_list = stmt_list;
+
+ gimple_bind_set_body (bind, xxx_list);
+ }
+ else
+ {
+ /* The traditional, on stack trampolines. */
+ gbind *bind;
+ annotate_all_with_location (stmt_list, DECL_SOURCE_LOCATION (context));
+ bind = gimple_seq_first_stmt_as_a_bind (gimple_body (context));
+ gimple_seq_add_seq (&stmt_list, gimple_bind_body (bind));
+ gimple_bind_set_body (bind, stmt_list);
+ }
}
/* If a chain_decl was created, then it needs to be registered with