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]

Re: [PATCH][PR debug/65549] Restore DW_AT_abstract_origin for cross-unit call sites


On Wed, 10 Jun 2015, Pierre-Marie de Rodat wrote:

> On 06/10/2015 03:36 PM, Richard Biener wrote:
> > Hmm, yes.  It meant to break after the first ;)  (without LTO
> > there usually is only one TU decl, apart from Java I think).
> > The hunk isn't in mainline because it was part of an experimental patch I
> > did on the early-debug branch.
> 
> Understood, thanks!
> 
> > Yeah, that looks great!
> > 
> > Of course I wonder about Java (builds multiple ones, one for each
> > input file) and Go (no idea).  I suppose Java would need to build
> > another one where all the "defaults" go (or it doesn't have any
> > such entities).
> 
> Yeah, I'm not familiar with them neither...
> 
> > In theory we could have changed dwarf2out_init to get a
> > translation-unit-decl argument as well.  But your patch looks like
> > we don't have such at the point of dwarf2out_init in all frontends.
> > 
> > Your patch is ok (and ok to backport) IMHO, though please give
> > others the chance to chime in.
> 
> Thank you very much. :-) I will soon become unavailable until July, so I think
> I'll wait until then to commit anyway.

FYI, I decided to backport the fix causing this regression to the
4.8 branch today, guarded with in_lto_p, thus eliminating the effect
on non-LTO links.  The adjusted patch looks like the following and
I'll also adjust the 4.9 branch accordingly, leaving the GCC 5 branch
with the original fix.

Richard.

2015-06-11  Richard Biener  <rguenther@suse.de>

	Backport from mainline, guarded with in_lto_p
	2015-06-02  Richard Biener  <rguenther@suse.de>

	PR debug/65549
	* dwarf2out.c (lookup_context_die): New function.
	(resolve_addr): Avoid forcing a full DIE for the
	target of a DW_TAG_GNU_call_site during late compilation.
	Instead create a stub DIE without a type if we have a
	context DIE present.

	* g++.dg/lto/pr65549_0.C: New testcase.

Index: gcc/testsuite/g++.dg/lto/pr65549_0.C
===================================================================
*** gcc/testsuite/g++.dg/lto/pr65549_0.C	(revision 0)
--- gcc/testsuite/g++.dg/lto/pr65549_0.C	(working copy)
***************
*** 0 ****
--- 1,144 ----
+ // { dg-lto-do link }
+ // { dg-lto-options { { -std=gnu++14 -flto -g } { -std=gnu++14 -flto -g -O2 -fno-inline -flto-partition=max } } }
+ // { dg-extra-ld-options "-r -nostdlib" }
+ 
+ namespace std {
+ inline namespace __cxx11 {}
+ template <typename _Tp, _Tp> struct integral_constant {
+   static constexpr _Tp value = 0;
+ };
+ template <typename> struct __and_;
+ struct is_member_object_pointer : integral_constant<bool, false> {};
+ template <typename>
+ struct is_member_function_pointer : integral_constant<bool, false> {};
+ template <typename> struct remove_reference { typedef int type; };
+ template <typename> class C;
+ template <bool, int, typename...> struct __result_of_impl;
+ template <typename _Functor, typename... _ArgTypes>
+ struct __result_of_impl<false, 0, _Functor, _ArgTypes...> {
+   typedef decltype(0) type;
+ };
+ template <typename _Functor, typename... _ArgTypes>
+ struct C<_Functor(_ArgTypes...)>
+     : __result_of_impl<is_member_object_pointer::value,
+                        is_member_function_pointer<
+                            typename remove_reference<_Functor>::type>::value,
+                        _Functor> {};
+ template <typename _Tp> using result_of_t = typename C<_Tp>::type;
+ template <typename> void forward();
+ template <typename _Tp> _Tp move(_Tp) {}
+ namespace __cxx11 {
+ class basic_string typedef string;
+ }
+ template <typename> struct allocator_traits { typedef decltype(0) pointer; };
+ }
+ struct F : std::allocator_traits<int> {};
+ namespace std {
+ namespace __cxx11 {
+ class basic_string {
+ public:
+   struct _Alloc_hider : F {
+     _Alloc_hider(pointer);
+   } _M_dataplus;
+   basic_string(int) : _M_dataplus(0) {}
+   ~basic_string();
+ };
+ }
+ template <typename> class function;
+ template <typename _Functor> class _Base_manager {
+ protected:
+   static _Functor *_M_get_pointer(int) {}
+ };
+ template <typename, typename> class _Function_handler;
+ template <typename _Res, typename _Functor, typename... _ArgTypes>
+ class _Function_handler<_Res(_ArgTypes...), _Functor>
+     : _Base_manager<_Functor> {
+ public:
+   static _Res _M_invoke(const int &) {
+     (*_Base_manager<_Functor>::_M_get_pointer(0))();
+   }
+ };
+ template <typename, typename> using __check_func_return_type = int;
+ template <typename _Res, typename... _ArgTypes>
+ class function<_Res(_ArgTypes...)> {
+   template <typename> using _Invoke = decltype(0);
+   template <typename _Functor>
+   using _Callable = __and_<__check_func_return_type<_Invoke<_Functor>, _Res>>;
+   template <typename, typename> using _Requires = int;
+ 
+ public:
+   template <typename _Functor, typename = _Requires<_Callable<_Functor>, void>>
+   function(_Functor);
+   using _Invoker_type = _Res (*)(const int &);
+   _Invoker_type _M_invoker;
+ };
+ template <typename _Res, typename... _ArgTypes>
+ template <typename _Functor, typename>
+ function<_Res(_ArgTypes...)>::function(_Functor) {
+   _M_invoker = _Function_handler<_Res(), _Functor>::_M_invoke;
+ }
+ class unique_ptr {
+ public:
+   ~unique_ptr();
+ };
+ template <typename _Tp, typename... _Args> _Tp make_unique(_Args... __args) {
+   _Tp(__args...);
+ }
+ }
+ class A {
+ public:
+   template <class T> T as();
+ };
+ class variables_map {
+ public:
+   A operator[](std::basic_string);
+ };
+ class B {
+ public:
+   variables_map configuration();
+   void run(int, int, std::function<void()>);
+ };
+ class H;
+ struct G {
+   enum {} _state;
+ };
+ class D {
+   G _local_state;
+   std::unique_ptr _task;
+   template <typename Func> void schedule(Func func) {
+     struct task_with_state {
+       task_with_state(Func func) : _func(func) {}
+       Func _func;
+     } tws = std::make_unique<task_with_state>(std::move(func));
+   }
+   friend H;
+ };
+ template <typename> using futurize_t = H;
+ class H {
+   D *_promise;
+   template <typename Func> void schedule(Func func) {
+     G __trans_tmp_1;
+     struct task_with_ready_state {
+       task_with_ready_state(Func, G);
+     };
+     std::make_unique<task_with_ready_state>(std::move(func), __trans_tmp_1);
+     _promise->schedule(std::move(func));
+   }
+   template <typename Func, typename Param> void then(Func func, Param) {
+     using P = D;
+     P pr;
+     schedule([ pr = std::move(pr), func, param = std::forward<Param> ]{});
+   }
+ 
+ public:
+   template <typename Func> futurize_t<std::result_of_t<Func()>> then(Func) {
+     then(0, [] {});
+   }
+ } clients;
+ main() {
+   B app;
+   app.run(0, 0, [&] {
+     auto config = app.configuration()[0].as<std::string>();
+     clients.then([] {});
+   });
+ }
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 224363)
+++ gcc/dwarf2out.c	(working copy)
@@ -19697,6 +19697,28 @@ is_naming_typedef_decl (const_tree decl)
 	      != TYPE_NAME (TREE_TYPE (decl))));
 }
 
+/* Looks up the DIE for a context.  */
+
+static inline dw_die_ref
+lookup_context_die (tree context)
+{
+  if (context)
+    {
+      /* Find die that represents this context.  */
+      if (TYPE_P (context))
+	{
+	  context = TYPE_MAIN_VARIANT (context);
+	  dw_die_ref ctx = lookup_type_die (context);
+	  if (!ctx)
+	    return NULL;
+	  return strip_naming_typedef (context, ctx);
+	}
+      else
+	return lookup_decl_die (context);
+    }
+  return comp_unit_die ();
+}
+
 /* Returns the DIE for a context.  */
 
 static inline dw_die_ref
@@ -22751,8 +22773,25 @@ resolve_addr (dw_die_ref die)
 		&& DECL_EXTERNAL (tdecl)
 		&& DECL_ABSTRACT_ORIGIN (tdecl) == NULL_TREE)
 	      {
-		force_decl_die (tdecl);
-		tdie = lookup_decl_die (tdecl);
+		dw_die_ref cdie;
+		if (!in_lto_p)
+		  {
+		    force_decl_die (tdecl);
+		    tdie = lookup_decl_die (tdecl);
+		  }
+		else if ((cdie = lookup_context_die (DECL_CONTEXT (tdecl))))
+		  {
+		    /* Creating a full DIE for tdecl is overly expensive and
+		       at this point even wrong when in the LTO phase
+		       as it can end up generating new type DIEs we didn't
+		       output and thus optimize_external_refs will crash.  */
+		    tdie = new_die (DW_TAG_subprogram, cdie, NULL_TREE);
+		    add_AT_flag (tdie, DW_AT_external, 1);
+		    add_AT_flag (tdie, DW_AT_declaration, 1);
+		    add_linkage_attr (tdie, tdecl);
+		    add_name_and_src_coords_attributes (tdie, tdecl);
+		    equate_decl_number_to_die (tdecl, tdie);
+		  }
 	      }
 	    if (tdie)
 	      {


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