This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

emit DW_AT_entry_pc for non-contiguous inlined functions


Without this patch, whenever an inlined function is in non-contiguous
blocks, we end up without any hint at its entry point whatsoever.

This patch attempts to address that, but only emitting a
DW_AT_entry_pc when the inlined function hasn't been combined and
rearranged such that different portions thereof can be reached by
independent code paths.

The only hopefully-reliable way I could come up with to identify it
was to check that the first sub-block of the stmt that corresponds to
the inlined function's decl corresponds itself to the abstract
function's entry point.

FWIW, I've bootstrapped the compiler on x86_64-linux-gnu with an
assertion to check that no other block in a chain of fragments could
ever satisfy this condition.  Having got no matches, I dropped the
assertion.

As a result, when we compile this:

typedef int (*fp)(int, int); extern fp f1, f2, f3, f4;
static inline int f0(int i, int j)
{ if (i<j) return f1(i,j); else return f2(i,j); }
int g1(int a, int b)
{ int x; if (a<b) x = f3(a,b); else x = f4(a,b); return x + f0(a,b); }
int g2(int a, int b)
{ int x=0, y; if (a<b) x = f3(a,b); y = f4(a,b); return x+y+f0(a,b); }
int g3(int a, int b)
{ int x = f0(a,b); if (a<b) return x+f3(a,b); else return x+f4(a,b); }
int g4(int a, int b)
{ if (a<b) return f0(a,b)+f3(a,b); else return f0(a,b)+f4(a,b); }

we optimize it to:

g1: if (a<b) return f3(a,b)+f1(a,b); else return f4(a,b)+f2(a,b);
g2: if (a<b) return f3(a,b)+f4(a,b)+f1(a,b); else return f4(a,b)+f2(a,b);
g3: if (a<b) return f1(a,b)+f3(a,b); else return f2(a,b)+f4(a,b);
g4: if (a<b) return f1(a,b)+f3(a,b); else return f2(a,b)+f4(a,b);

So f0's inlined fragments in g1 and g2 do not represent entry points.
In g3, the compare is taken from f0, so it's regarded as an entry
point.  In g4, we get two inlined copies, each one contiguous, thus
represented with low/high rather than ranges, so no explicit
DW_AT_entry_pc is needed/useful.

Ok to install?  Bootstrapped and regression-tested (with an additional
assertion) on x86_64-linux-gnu.

for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* dwarf2out.c (is_inlined_entry_point): New
	(add_high_low_attributes): Emit DW_AT_entry_pc along with
	DW_AT_ranges if the first subblock is the entry point.

Index: trunk/gcc/dwarf2out.c
===================================================================
--- trunk.orig/gcc/dwarf2out.c	2007-02-27 01:59:21.000000000 -0300
+++ trunk/gcc/dwarf2out.c	2007-02-28 01:46:56.000000000 -0300
@@ -12231,6 +12231,36 @@ add_call_src_coords_attributes (tree stm
   add_AT_unsigned (die, DW_AT_call_line, s.line);
 }
 
+
+/* If STMT's abstract origin is a function declaration and STMT's
+   first subblock's abstract origin is the function's outermost block,
+   then we're looking at the main entry point.  */
+static bool
+is_inlined_entry_point (tree stmt)
+{
+  tree decl, block;
+
+  if (!stmt || TREE_CODE (stmt) != BLOCK)
+    return false;
+
+  decl = block_ultimate_origin (stmt);
+
+  if (!decl || TREE_CODE (decl) != FUNCTION_DECL)
+    return false;
+
+  block = BLOCK_SUBBLOCKS (stmt);
+
+  if (block)
+    {
+      if (TREE_CODE (block) != BLOCK)
+	return false;
+
+      block = block_ultimate_origin (block);
+    }
+
+  return block == DECL_INITIAL (decl);
+}
+
 /* A helper function for gen_lexical_block_die and gen_inlined_subroutine_die.
    Add low_pc and high_pc attributes to the DIE for a block STMT.  */
 
@@ -12243,6 +12273,13 @@ add_high_low_attributes (tree stmt, dw_d
     {
       tree chain;
 
+      if (is_inlined_entry_point (stmt))
+	{
+	  ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
+				       BLOCK_NUMBER (stmt));
+	  add_AT_lbl_id (die, DW_AT_entry_pc, label);
+	}
+
       add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt));
 
       chain = BLOCK_FRAGMENT_CHAIN (stmt);
-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
FSF Latin America Board Member         http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]