c tree inlining vs dwarf2
Richard Henderson
rth@redhat.com
Mon Oct 8 09:42:00 GMT 2001
Dwarf2 expects any function that has been inlined to have the DECL_INLINE
bit set. Failure to do so will get it confused and abort trying to create
a second die for the function.
The C++ front end distinguishes between whether a function is declared
inline, and whether it is inlinable. At -O3, it sets DECL_INLINE on
pretty much all functions.
This changes the C front end to do the same thing.
Bootstrapped on alpha (dwarf2) and i686 (stabs) linux.
r~
* c-common.h (struct c_lang_decl): Add declared_inline.
* c-tree.h (DECL_DECLARED_INLINE_P): New.
* c-lang.c (c_disregard_inline_limits): Use it.
* c-decl.c (duplicate_decls): Likewise.
(pushdecl, redeclaration_error_message): Likewise.
(pushdecl): Allocate DECL_LANG_SPECIFIC if needed.
(grokdeclarator): Likewise. Set DECL_DECLARED_INLINE_P.
Set DECL_INLINE if -finline-functions.
(store_parm_decls): Don't allocate DECL_LANG_SPECIFIC here.
* cp-tree.h (struct lang_decl_flags): Remove declared_inline.
(DECL_DECLARED_INLINE_P): Use the bit in struct c_lang_decl.
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.88
diff -c -p -d -r1.88 c-common.h
*** c-common.h 2001/10/05 02:49:15 1.88
--- c-common.h 2001/10/08 16:27:48
*************** extern void mark_stmt_tree
*** 338,344 ****
DECL_LANG_SPECIFIC field. */
struct c_lang_decl {
! char dummy;
};
/* In a FUNCTION_DECL for which DECL_BUILT_IN does not hold, this is
--- 338,344 ----
DECL_LANG_SPECIFIC field. */
struct c_lang_decl {
! unsigned declared_inline : 1;
};
/* In a FUNCTION_DECL for which DECL_BUILT_IN does not hold, this is
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.250
diff -c -p -d -r1.250 c-decl.c
*** c-decl.c 2001/10/07 18:02:43 1.250
--- c-decl.c 2001/10/08 16:27:48
*************** duplicate_decls (newdecl, olddecl, diffe
*** 1727,1738 ****
/* Warn if function is now inline
but was previously declared not inline and has been called. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
! && ! DECL_INLINE (olddecl) && DECL_INLINE (newdecl)
&& TREE_USED (olddecl))
warning_with_decl (newdecl,
"`%s' declared inline after being called");
if (TREE_CODE (olddecl) == FUNCTION_DECL
! && ! DECL_INLINE (olddecl) && DECL_INLINE (newdecl)
&& DECL_INITIAL (olddecl) != 0)
warning_with_decl (newdecl,
"`%s' declared inline after its definition");
--- 1727,1740 ----
/* Warn if function is now inline
but was previously declared not inline and has been called. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
! && ! DECL_DECLARED_INLINE_P (olddecl)
! && DECL_DECLARED_INLINE_P (newdecl)
&& TREE_USED (olddecl))
warning_with_decl (newdecl,
"`%s' declared inline after being called");
if (TREE_CODE (olddecl) == FUNCTION_DECL
! && ! DECL_DECLARED_INLINE_P (olddecl)
! && DECL_DECLARED_INLINE_P (newdecl)
&& DECL_INITIAL (olddecl) != 0)
warning_with_decl (newdecl,
"`%s' declared inline after its definition");
*************** duplicate_decls (newdecl, olddecl, diffe
*** 1976,1985 ****
{
/* If either decl says `inline', this fn is inline,
unless its definition was passed already. */
! if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
! DECL_INLINE (olddecl) = 1;
! DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
}
if (DECL_BUILT_IN (olddecl))
--- 1978,1988 ----
{
/* If either decl says `inline', this fn is inline,
unless its definition was passed already. */
! if (DECL_DECLARED_INLINE_P (newdecl)
! && DECL_DECLARED_INLINE_P (olddecl) == 0)
! DECL_DECLARED_INLINE_P (olddecl) = 1;
! DECL_DECLARED_INLINE_P (newdecl) = DECL_DECLARED_INLINE_P (olddecl);
}
if (DECL_BUILT_IN (olddecl))
*************** pushdecl (x)
*** 2056,2061 ****
--- 2059,2069 ----
register tree name = DECL_NAME (x);
register struct binding_level *b = current_binding_level;
+ /* Functions need the lang_decl data. */
+ if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
+ DECL_LANG_SPECIFIC (x) = (struct lang_decl *)
+ ggc_alloc_cleared (sizeof (struct lang_decl));
+
DECL_CONTEXT (x) = current_function_decl;
/* A local extern declaration for a function doesn't constitute nesting.
A local auto declaration does, since it's a forward decl
*************** pushdecl (x)
*** 2351,2357 ****
&& oldglobal != 0
&& TREE_CODE (x) == FUNCTION_DECL
&& TREE_CODE (oldglobal) == FUNCTION_DECL
! && DECL_EXTERNAL (x) && ! DECL_INLINE (x))
{
/* We have one. Their types must agree. */
if (! comptypes (TREE_TYPE (x),
--- 2359,2366 ----
&& oldglobal != 0
&& TREE_CODE (x) == FUNCTION_DECL
&& TREE_CODE (oldglobal) == FUNCTION_DECL
! && DECL_EXTERNAL (x)
! && ! DECL_DECLARED_INLINE_P (x))
{
/* We have one. Their types must agree. */
if (! comptypes (TREE_TYPE (x),
*************** pushdecl (x)
*** 2361,2368 ****
{
/* Inner extern decl is inline if global one is.
Copy enough to really inline it. */
! if (DECL_INLINE (oldglobal))
{
DECL_INLINE (x) = DECL_INLINE (oldglobal);
DECL_INITIAL (x) = (current_function_decl == oldglobal
? 0 : DECL_INITIAL (oldglobal));
--- 2370,2379 ----
{
/* Inner extern decl is inline if global one is.
Copy enough to really inline it. */
! if (DECL_DECLARED_INLINE_P (oldglobal))
{
+ DECL_DECLARED_INLINE_P (x)
+ = DECL_DECLARED_INLINE_P (oldglobal);
DECL_INLINE (x) = DECL_INLINE (oldglobal);
DECL_INITIAL (x) = (current_function_decl == oldglobal
? 0 : DECL_INITIAL (oldglobal));
*************** redeclaration_error_message (newdecl, ol
*** 2613,2620 ****
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0
/* However, defining once as extern inline and a second
time in another way is ok. */
! && ! (DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
! && ! (DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
return 1;
return 0;
}
--- 2624,2632 ----
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0
/* However, defining once as extern inline and a second
time in another way is ok. */
! && ! (DECL_DECLARED_INLINE_P (olddecl) && DECL_EXTERNAL (olddecl)
! && ! (DECL_DECLARED_INLINE_P (newdecl)
! && DECL_EXTERNAL (newdecl))))
return 1;
return 0;
}
*************** grokdeclarator (declarator, declspecs, d
*** 4913,4918 ****
--- 4925,4933 ----
decl = build_decl (FUNCTION_DECL, declarator, type);
decl = build_decl_attribute_variant (decl, decl_attr);
+ DECL_LANG_SPECIFIC (decl) = (struct lang_decl *)
+ ggc_alloc_cleared (sizeof (struct lang_decl));
+
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
*************** grokdeclarator (declarator, declspecs, d
*** 4929,4945 ****
= !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
/* Record presence of `inline', if it is reasonable. */
! if (inlinep)
{
! if (MAIN_NAME_P (declarator))
warning ("cannot inline function `main'");
! else
! /* Assume that otherwise the function can be inlined. */
! DECL_INLINE (decl) = 1;
if (specbits & (1 << (int) RID_EXTERN))
current_extern_inline = 1;
}
}
else
{
--- 4944,4971 ----
= !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
/* Record presence of `inline', if it is reasonable. */
! if (MAIN_NAME_P (declarator))
{
! if (inlinep)
warning ("cannot inline function `main'");
! }
! else if (inlinep)
! {
! /* Assume that otherwise the function can be inlined. */
! DECL_INLINE (decl) = 1;
! DECL_DECLARED_INLINE_P (decl) = 1;
if (specbits & (1 << (int) RID_EXTERN))
current_extern_inline = 1;
}
+ /* If -finline-functions, assume it can be inlined. This does
+ two things: let the function be deferred until it is actually
+ needed, and let dwarf2 know that the function is inlinable. */
+ else if (flag_inline_trees == 2)
+ {
+ DECL_INLINE (decl) = 1;
+ DECL_DECLARED_INLINE_P (decl) = 0;
+ }
}
else
{
*************** store_parm_decls ()
*** 6593,6600 ****
init_function_start (fndecl, input_filename, lineno);
/* Begin the statement tree for this function. */
- DECL_LANG_SPECIFIC (current_function_decl)
- =((struct lang_decl *) ggc_alloc_cleared (sizeof (struct lang_decl)));
begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
/* If this is a nested function, save away the sizes of any
--- 6619,6624 ----
Index: c-lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-lang.c,v
retrieving revision 1.55
diff -c -p -d -r1.55 c-lang.c
*** c-lang.c 2001/10/05 04:20:27 1.55
--- c-lang.c 2001/10/08 16:27:48
*************** static int
*** 340,346 ****
c_disregard_inline_limits (fn)
tree fn;
{
! return DECL_INLINE (fn) && DECL_EXTERNAL (fn);
}
static tree inline_forbidden_p PARAMS ((tree *, int *, void *));
--- 340,346 ----
c_disregard_inline_limits (fn)
tree fn;
{
! return DECL_DECLARED_INLINE_P (fn) && DECL_EXTERNAL (fn);
}
static tree inline_forbidden_p PARAMS ((tree *, int *, void *));
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.68
diff -c -p -d -r1.68 c-tree.h
*** c-tree.h 2001/09/06 08:59:36 1.68
--- c-tree.h 2001/10/08 16:27:48
*************** struct lang_decl
*** 98,105 ****
/* In an IDENTIFIER_NODE, nonzero if this identifier is actually a
keyword. C_RID_CODE (node) is then the RID_* value of the keyword,
and C_RID_YYCODE is the token number wanted by Yacc. */
-
#define C_IS_RESERVED_WORD(id) TREE_LANG_FLAG_0 (id)
/* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct lang_type
--- 98,110 ----
/* In an IDENTIFIER_NODE, nonzero if this identifier is actually a
keyword. C_RID_CODE (node) is then the RID_* value of the keyword,
and C_RID_YYCODE is the token number wanted by Yacc. */
#define C_IS_RESERVED_WORD(id) TREE_LANG_FLAG_0 (id)
+
+ /* This function was declared inline. This flag controls the linkage
+ semantics of 'inline'; whether or not the function is inlined is
+ controlled by DECL_INLINE. */
+ #define DECL_DECLARED_INLINE_P(NODE) \
+ (DECL_LANG_SPECIFIC (NODE)->base.declared_inline)
/* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct lang_type
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.645
diff -c -p -d -r1.645 cp-tree.h
*** cp-tree.h 2001/10/05 02:48:44 1.645
--- cp-tree.h 2001/10/08 16:27:52
*************** struct lang_decl_flags
*** 1705,1721 ****
unsigned deferred : 1;
unsigned use_template : 2;
unsigned nonconverting : 1;
- unsigned declared_inline : 1;
unsigned not_really_extern : 1;
unsigned needs_final_overrider : 1;
unsigned initialized_in_class : 1;
-
unsigned pending_inline_p : 1;
unsigned global_ctor_p : 1;
unsigned global_dtor_p : 1;
unsigned assignment_operator_p : 1;
unsigned anticipated_p : 1;
! /* Three unused bits. */
union {
/* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
--- 1705,1720 ----
unsigned deferred : 1;
unsigned use_template : 2;
unsigned nonconverting : 1;
unsigned not_really_extern : 1;
unsigned needs_final_overrider : 1;
unsigned initialized_in_class : 1;
unsigned pending_inline_p : 1;
+
unsigned global_ctor_p : 1;
unsigned global_dtor_p : 1;
unsigned assignment_operator_p : 1;
unsigned anticipated_p : 1;
! /* Four unused bits. */
union {
/* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
*************** enum ptrmemfunc_vbit_where_t
*** 2838,2844 ****
semantics of 'inline'; whether or not the function is inlined is
controlled by DECL_INLINE. */
#define DECL_DECLARED_INLINE_P(NODE) \
! (DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_inline)
/* DECL_EXTERNAL must be set on a decl until the decl is actually emitted,
so that assemble_external will work properly. So we have this flag to
--- 2837,2843 ----
semantics of 'inline'; whether or not the function is inlined is
controlled by DECL_INLINE. */
#define DECL_DECLARED_INLINE_P(NODE) \
! (DECL_LANG_SPECIFIC (NODE)->decl_flags.base.declared_inline)
/* DECL_EXTERNAL must be set on a decl until the decl is actually emitted,
so that assemble_external will work properly. So we have this flag to
More information about the Gcc-patches
mailing list