#include "timevar.h"
#include "vecprim.h"
+/* So we can assign to cfun in this file. */
+#undef cfun
+
#ifndef LOCAL_ALIGNMENT
#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
#endif
struct function *p;
if (cfun == 0)
- allocate_struct_function (NULL);
+ allocate_struct_function (NULL, false);
p = cfun;
p->outer = outer_function_chain;
/* Subroutine of instantiate_decls. Given RTL representing a decl,
do any instantiation required. */
-static void
-instantiate_decl (rtx x)
+void
+instantiate_decl_rtl (rtx x)
{
rtx addr;
/* If this is a CONCAT, recurse for the pieces. */
if (GET_CODE (x) == CONCAT)
{
- instantiate_decl (XEXP (x, 0));
- instantiate_decl (XEXP (x, 1));
+ instantiate_decl_rtl (XEXP (x, 0));
+ instantiate_decl_rtl (XEXP (x, 1));
return;
}
{
*walk_subtrees = 0;
if (DECL_P (t) && DECL_RTL_SET_P (t))
- instantiate_decl (DECL_RTL (t));
+ instantiate_decl_rtl (DECL_RTL (t));
}
return NULL;
}
for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
{
if (DECL_RTL_SET_P (t))
- instantiate_decl (DECL_RTL (t));
+ instantiate_decl_rtl (DECL_RTL (t));
if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
{
tree v = DECL_VALUE_EXPR (t);
}
/* Process all subblocks. */
- for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
+ for (t = BLOCK_SUBBLOCKS (let); t; t = BLOCK_CHAIN (t))
instantiate_decls_1 (t);
}
/* Process all parameters of the function. */
for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
{
- instantiate_decl (DECL_RTL (decl));
- instantiate_decl (DECL_INCOMING_RTL (decl));
+ instantiate_decl_rtl (DECL_RTL (decl));
+ instantiate_decl_rtl (DECL_INCOMING_RTL (decl));
if (DECL_HAS_VALUE_EXPR_P (decl))
{
tree v = DECL_VALUE_EXPR (decl);
/* Instantiate the virtual registers in the DECLs for debugging purposes. */
instantiate_decls (current_function_decl);
+ targetm.instantiate_decls ();
+
/* Indicate that, from now on, assign_stack_local should use
frame_pointer_rtx. */
virtuals_instantiated = 1;
imag = gen_lowpart_SUBREG (inner, imag);
}
tmp = gen_rtx_CONCAT (DECL_MODE (parm), real, imag);
- set_decl_incoming_rtl (parm, tmp);
+ set_decl_incoming_rtl (parm, tmp, false);
fnargs = TREE_CHAIN (fnargs);
}
else
{
SET_DECL_RTL (parm, DECL_RTL (fnargs));
- set_decl_incoming_rtl (parm, DECL_INCOMING_RTL (fnargs));
+ set_decl_incoming_rtl (parm, DECL_INCOMING_RTL (fnargs), false);
/* Set MEM_EXPR to the original decl, i.e. to PARM,
instead of the copy of decl, i.e. FNARGS. */
}
/* Record permanently how this parm was passed. */
- set_decl_incoming_rtl (parm, data.entry_parm);
+ set_decl_incoming_rtl (parm, data.entry_parm, data.passed_pointer);
/* Update info on where next arg arrives in registers. */
FUNCTION_ARG_ADVANCE (all.args_so_far, data.promoted_mode,
" %<longjmp%> or %<vfork%>", decl);
}
- for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
+ for (sub = BLOCK_SUBBLOCKS (block); sub; sub = BLOCK_CHAIN (sub))
setjmp_vars_warning (setjmp_crosses, sub);
}
static VEC(function_p,heap) *cfun_stack;
+/* We save the value of in_system_header here when pushing the first
+ function on the cfun stack, and we restore it from here when
+ popping the last function. */
+
+static bool saved_in_system_header;
+
/* Push the current cfun onto the stack, and set cfun to new_cfun. */
void
push_cfun (struct function *new_cfun)
{
+ if (cfun == NULL)
+ saved_in_system_header = in_system_header;
VEC_safe_push (function_p, heap, cfun_stack, cfun);
+ if (new_cfun)
+ in_system_header = DECL_IN_SYSTEM_HEADER (new_cfun->decl);
set_cfun (new_cfun);
}
void
pop_cfun (void)
{
- set_cfun (VEC_pop (function_p, cfun_stack));
+ struct function *new_cfun = VEC_pop (function_p, cfun_stack);
+ in_system_header = ((new_cfun == NULL) ? saved_in_system_header
+ : DECL_IN_SYSTEM_HEADER (new_cfun->decl));
+ set_cfun (new_cfun);
}
/* Return value of funcdef and increase it. */
directly into cfun and invoke the back end hook explicitly at the
very end, rather than initializing a temporary and calling set_cfun
on it.
-*/
+
+ ABSTRACT_P is true if this is a function that will never be seen by
+ the middle-end. Such functions are front-end concepts (like C++
+ function templates) that do not correspond directly to functions
+ placed in object files. */
void
-allocate_struct_function (tree fndecl)
+allocate_struct_function (tree fndecl, bool abstract_p)
{
tree result;
tree fntype = fndecl ? TREE_TYPE (fndecl) : NULL_TREE;
cfun->decl = fndecl;
result = DECL_RESULT (fndecl);
- if (aggregate_value_p (result, fndecl))
+ if (!abstract_p && aggregate_value_p (result, fndecl))
{
#ifdef PCC_STATIC_STRUCT_RETURN
current_function_returns_pcc_struct = 1;
void
push_struct_function (tree fndecl)
{
+ if (cfun == NULL)
+ saved_in_system_header = in_system_header;
VEC_safe_push (function_p, heap, cfun_stack, cfun);
- allocate_struct_function (fndecl);
+ if (fndecl)
+ in_system_header = DECL_IN_SYSTEM_HEADER (fndecl);
+ allocate_struct_function (fndecl, false);
}
/* Reset cfun, and other non-struct-function variables to defaults as
if (subr && DECL_STRUCT_FUNCTION (subr))
set_cfun (DECL_STRUCT_FUNCTION (subr));
else
- allocate_struct_function (subr);
+ allocate_struct_function (subr, false);
prepare_function_start ();
/* Warn if this value is an aggregate type,
tree parm = cfun->static_chain_decl;
rtx local = gen_reg_rtx (Pmode);
- set_decl_incoming_rtl (parm, static_chain_incoming_rtx);
+ set_decl_incoming_rtl (parm, static_chain_incoming_rtx, false);
SET_DECL_RTL (parm, local);
mark_reg_pointer (local, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm))));
asm ("" : "=r" (output), "=m" (input) : "0" (input))
- Here 'input' is used in two occurences as input (once for the
+ Here 'input' is used in two occurrences as input (once for the
input operand, once for the address in the second output operand).
If we would replace only the occurence of the input operand (to
make the matching) we would be left with this:
value, but different pseudos) where we formerly had only one.
With more complicated asms this might lead to reload failures
which wouldn't have happen without this pass. So, iterate over
- all operands and replace all occurences of the register used. */
+ all operands and replace all occurrences of the register used. */
for (j = 0; j < noutputs; j++)
- if (!rtx_equal_p (SET_DEST (p_sets[j]), output)
+ if (!rtx_equal_p (SET_DEST (p_sets[j]), input)
&& reg_overlap_mentioned_p (input, SET_DEST (p_sets[j])))
SET_DEST (p_sets[j]) = replace_rtx (SET_DEST (p_sets[j]),
input, output);