static tree cp_protect_cleanup_actions (void) { /* [except.terminate] When the destruction of an object during stack unwinding exits using an exception ... void terminate(); is called. */ return build_call (terminate_node, NULL_TREE); }
static void genericize_eh_spec_block (tree *stmt_p) { tree body = EH_SPEC_STMTS (*stmt_p); tree allowed = EH_SPEC_RAISES (*stmt_p); tree failure = build_call (call_unexpected_node, tree_cons (NULL_TREE, build_exc_ptr (), NULL_TREE)); gimplify_stmt (&body); *stmt_p = gimple_build_eh_filter (body, allowed, failure); }
Psc synint_proc(CTXTdeclc Psc psc, int intcode) { if (pflags[intcode+INT_HANDLERS_FLAGS_START]==(Cell)0) { /* default hard handler */ default_inthandler(CTXTc intcode); psc = 0; } else { /* call Prolog handler */ switch (intcode) { case MYSIG_UNDEF: /* 0 */ SYS_MUTEX_LOCK( MUTEX_LOAD_UNDEF ) ; case MYSIG_KEYB: /* 1 */ case MYSIG_SPY: /* 3 */ case MYSIG_TRACE: /* 4 */ case THREADSIG_CANCEL: /* f */ case MYSIG_CLAUSE: /* 16 */ if (psc) bld_cs(reg+1, build_call(CTXTc psc)); psc = (Psc)pflags[intcode+INT_HANDLERS_FLAGS_START]; bld_int(reg+2, asynint_code); pcreg = get_ep(psc); break; case MYSIG_ATTV: /* 8 */ /* the old call must be built first */ if (psc) bld_cs(reg+2, build_call(CTXTc psc)); psc = (Psc)pflags[intcode+INT_HANDLERS_FLAGS_START]; /* * Pass the interrupt chain to reg 1. The interrupt chain * will be reset to 0 in build_interrupt_chain()). */ bld_copy(reg + 1, build_interrupt_chain(CTXT)); /* bld_int(reg + 3, intcode); */ /* Not really needed */ pcreg = get_ep(psc); break; default: xsb_abort("Unknown intcode in synint_proc()"); } /* switch */ } return psc; }
static void gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p) { tree stmt = *expr_p; tree temp = voidify_wrapper_expr (stmt, NULL); tree body = TREE_OPERAND (stmt, 0); gimplify_stmt (&body); stmt = gimple_build_eh_filter (body, NULL_TREE, build_call (terminate_node, NULL_TREE)); if (temp) { append_to_statement_list (stmt, pre_p); *expr_p = temp; } else *expr_p = stmt; }
void use_thunk (tree thunk_fndecl, bool emit_p) { tree a, t, function, alias; tree virtual_offset; HOST_WIDE_INT fixed_offset, virtual_value; bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl); /* We should have called finish_thunk to give it a name. */ gcc_assert (DECL_NAME (thunk_fndecl)); /* We should never be using an alias, always refer to the aliased thunk. */ gcc_assert (!THUNK_ALIAS (thunk_fndecl)); if (TREE_ASM_WRITTEN (thunk_fndecl)) return; function = THUNK_TARGET (thunk_fndecl); if (DECL_RESULT (thunk_fndecl)) /* We already turned this thunk into an ordinary function. There's no need to process this thunk again. */ return; if (DECL_THUNK_P (function)) /* The target is itself a thunk, process it now. */ use_thunk (function, emit_p); /* Thunks are always addressable; they only appear in vtables. */ TREE_ADDRESSABLE (thunk_fndecl) = 1; /* Figure out what function is being thunked to. It's referenced in this translation unit. */ TREE_ADDRESSABLE (function) = 1; mark_used (function); if (!emit_p) return; if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function)) alias = make_alias_for_thunk (function); else alias = function; fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl); virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl); if (virtual_offset) { if (!this_adjusting) virtual_offset = BINFO_VPTR_FIELD (virtual_offset); virtual_value = tree_low_cst (virtual_offset, /*pos=*/0); gcc_assert (virtual_value); } else virtual_value = 0; /* And, if we need to emit the thunk, it's used. */ mark_used (thunk_fndecl); /* This thunk is actually defined. */ DECL_EXTERNAL (thunk_fndecl) = 0; /* The linkage of the function may have changed. FIXME in linkage rewrite. */ TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function); DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function); DECL_VISIBILITY_SPECIFIED (thunk_fndecl) = DECL_VISIBILITY_SPECIFIED (function); if (DECL_ONE_ONLY (function)) make_decl_one_only (thunk_fndecl); if (flag_syntax_only) { TREE_ASM_WRITTEN (thunk_fndecl) = 1; return; } push_to_top_level (); if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function) && targetm.have_named_sections) { resolve_unique_section (function, 0, flag_function_sections); if (DECL_SECTION_NAME (function) != NULL && DECL_ONE_ONLY (function)) { resolve_unique_section (thunk_fndecl, 0, flag_function_sections); /* Output the thunk into the same section as function. */ DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function); } } /* The back-end expects DECL_INITIAL to contain a BLOCK, so we create one. */ DECL_INITIAL (thunk_fndecl) = make_node (BLOCK); /* Set up cloned argument trees for the thunk. */ t = NULL_TREE; for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) { tree x = copy_node (a); TREE_CHAIN (x) = t; DECL_CONTEXT (x) = thunk_fndecl; SET_DECL_RTL (x, NULL_RTX); DECL_HAS_VALUE_EXPR_P (x) = 0; t = x; } a = nreverse (t); DECL_ARGUMENTS (thunk_fndecl) = a; BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = a; if (this_adjusting && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, virtual_value, alias)) { const char *fnname; current_function_decl = thunk_fndecl; DECL_RESULT (thunk_fndecl) = build_decl (RESULT_DECL, 0, integer_type_node); fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); init_function_start (thunk_fndecl); current_function_is_thunk = 1; assemble_start_function (thunk_fndecl, fnname); targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, fixed_offset, virtual_value, alias); assemble_end_function (thunk_fndecl, fnname); init_insn_lengths (); current_function_decl = 0; cfun = 0; TREE_ASM_WRITTEN (thunk_fndecl) = 1; } else { /* If this is a covariant thunk, or we don't have the necessary code for efficient thunks, generate a thunk function that just makes a call to the real function. Unfortunately, this doesn't work for varargs. */ if (varargs_function_p (function)) error ("generic thunk code fails for method %q#D which uses %<...%>", function); DECL_RESULT (thunk_fndecl) = NULL_TREE; start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED); /* We don't bother with a body block for thunks. */ /* There's no need to check accessibility inside the thunk body. */ push_deferring_access_checks (dk_no_check); t = a; if (this_adjusting) t = thunk_adjust (t, /*this_adjusting=*/1, fixed_offset, virtual_offset); /* Build up the call to the real function. */ t = tree_cons (NULL_TREE, t, NULL_TREE); for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a)) t = tree_cons (NULL_TREE, a, t); t = nreverse (t); t = build_call (alias, t); CALL_FROM_THUNK_P (t) = 1; if (VOID_TYPE_P (TREE_TYPE (t))) finish_expr_stmt (t); else { if (!this_adjusting) { tree cond = NULL_TREE; if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE) { /* If the return type is a pointer, we need to protect against NULL. We know there will be an adjustment, because that's why we're emitting a thunk. */ t = save_expr (t); cond = cp_convert (boolean_type_node, t); } t = thunk_adjust (t, /*this_adjusting=*/0, fixed_offset, virtual_offset); if (cond) t = build3 (COND_EXPR, TREE_TYPE (t), cond, t, cp_convert (TREE_TYPE (t), integer_zero_node)); } if (IS_AGGR_TYPE (TREE_TYPE (t))) t = build_cplus_new (TREE_TYPE (t), t); finish_return_stmt (t); } /* Since we want to emit the thunk, we explicitly mark its name as referenced. */ mark_decl_referenced (thunk_fndecl); /* But we don't want debugging information about it. */ DECL_IGNORED_P (thunk_fndecl) = 1; /* Re-enable access control. */ pop_deferring_access_checks (); thunk_fndecl = finish_function (0); tree_lowering_passes (thunk_fndecl); expand_body (thunk_fndecl); } pop_from_top_level (); }
static tree cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2) { tree defparm, parm; int i; if (fn == NULL) return NULL; defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))); if (arg2) defparm = TREE_CHAIN (defparm); if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE) { tree inner_type = TREE_TYPE (arg1); tree start1, end1, p1; tree start2 = NULL, p2 = NULL; tree ret = NULL, lab, t; start1 = arg1; start2 = arg2; do { inner_type = TREE_TYPE (inner_type); start1 = build4 (ARRAY_REF, inner_type, start1, size_zero_node, NULL, NULL); if (arg2) start2 = build4 (ARRAY_REF, inner_type, start2, size_zero_node, NULL, NULL); } while (TREE_CODE (inner_type) == ARRAY_TYPE); start1 = build_fold_addr_expr (start1); if (arg2) start2 = build_fold_addr_expr (start2); end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1)); end1 = fold_convert (TREE_TYPE (start1), end1); end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1); p1 = create_tmp_var (TREE_TYPE (start1), NULL); t = build2 (MODIFY_EXPR, void_type_node, p1, start1); append_to_statement_list (t, &ret); if (arg2) { p2 = create_tmp_var (TREE_TYPE (start2), NULL); t = build2 (MODIFY_EXPR, void_type_node, p2, start2); append_to_statement_list (t, &ret); } lab = create_artificial_label (); t = build1 (LABEL_EXPR, void_type_node, lab); append_to_statement_list (t, &ret); t = tree_cons (NULL, p1, NULL); if (arg2) t = tree_cons (NULL, p2, t); /* Handle default arguments. */ i = 1 + (arg2 != NULL); for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), TREE_PURPOSE (parm), fn, i++), t); t = build_call (fn, nreverse (t)); append_to_statement_list (t, &ret); t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type)); t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t); t = build2 (MODIFY_EXPR, void_type_node, p1, t); append_to_statement_list (t, &ret); if (arg2) { t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type)); t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t); t = build2 (MODIFY_EXPR, void_type_node, p2, t); append_to_statement_list (t, &ret); } t = build2 (NE_EXPR, boolean_type_node, p1, end1); t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL); append_to_statement_list (t, &ret); return ret; } else { tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL); if (arg2) t = tree_cons (NULL, build_fold_addr_expr (arg2), t); /* Handle default arguments. */ i = 1 + (arg2 != NULL); for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), TREE_PURPOSE (parm), fn, i++), t); return build_call (fn, nreverse (t)); } }