Jump to page: 1 2
Thread overview
[Bug 157] using -O{1,2,3} together with -g causes ICE (seg fault)
May 03, 2015
Iain Buclaw
May 03, 2015
http://bugzilla.gdcproject.org/show_bug.cgi?id=157

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |WORKSFORME

--- Comment #1 from Iain Buclaw <ibuclaw@gdcproject.org> ---
I assume this was a bug in 4.10 backend that's since been fixed in the 5.1 release.

-- 
You are receiving this mail because:
You are watching all bug changes.


August 02
https://bugzilla.gdcproject.org/show_bug.cgi?id=157

Johannes Pfau <johannespfau@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |johannespfau@gmail.com

--- Comment #2 from Johannes Pfau <johannespfau@gmail.com> ---
Created attachment 91
  --> https://bugzilla.gdcproject.org/attachment.cgi?id=91&action=edit
Test case

-- 
You are receiving this mail because:
You are watching all bug changes.
August 02
https://bugzilla.gdcproject.org/show_bug.cgi?id=157

Johannes Pfau <johannespfau@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |NEW
         Resolution|WORKSFORME                  |---

--- Comment #3 from Johannes Pfau <johannespfau@gmail.com> ---
Two years later, the bug can be reproduced when compiling phobos with GCC-4.9: https://semaphoreci.com/jpf91/gdc/branches/gdc-4-9/builds/82

I did some debugging and investigation and this is a rather interesting bug (line numbers in the following refer to GCC 4.9.4):

First of all, you need a templated function which contains a nested struct. Then you need -O to inline this function somewhere and the function must be defined outside of the main compilation unit.

What happens is this: GCC wants to generate a DW_TAG_GNU_call_site for the inlined function (so only happens with optimization) and calls resolve_addr. In the code path for this, line 23441, GCC checks for DECL_EXTERNAL, this is why the function needs to be external.

Now it gets interesting: A similar situation can be triggered by LTO, GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65549 . Starting with GCC 5 these cases do no longer generate full dies - avoiding the issue. For GCC 4.9 and 4.8 the new code is backported, but guarded by if(!in_lto_p) which leads to the interesting situation that compiling with -flto actually fixes the bug...

So what happens in the non-LTO case? We call force_decl_die which outputs complete debug info for the function. This includes debug info for return or parameter types (so you need to return the nested type). Ultimately this ends up calling gen_tagged_type_die, line 19681:

  else if (TYPE_CONTEXT (type) != NULL_TREE
           && (TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL))
    {
      /* If this type is local to a function that hasn't been written
         out yet, use a NULL context for now; it will be fixed up in
         decls_for_scope.  */

But unfortunately the declaration is never emitted for some reason and decls_for_scope never fixes context!



So this explains why this bug vanished in newer releases. We may still have a template emission bug here though:

Unfortunately dustmite produced something which can't link, but consider this: conv.d: toChars used by toImpl used by to. to & toImpl are emitted, toChars is not. This does not seem right.


Compile like this:
gdc -g -O2 -nostdinc -I druntime_sources -I . std/net/curl.d -c

nm curl.o
0000000000000000 W pure nothrow @nogc immutable(char)[]
conv.to!(immutable(char)[]).to!(int).to(int)
0000000000000000 W pure nothrow @nogc immutable(char)[]
conv.text!(int).text(int)
                 U pure nothrow @nogc immutable(char)[]
conv.text!(uint).text(uint)
                 U pure nothrow @nogc @safe
conv.toChars!(uint).toChars(uint).Result conv.toChars!(uint).toChars(uint)
0000000000000000 W pure nothrow @nogc @safe uint
conv.unsigned!(int).unsigned(int)
0000000000000000 W pure nothrow @nogc immutable(char)[]
conv.toImpl!(immutable(char)[], int).toImpl(int, uint)
0000000000000000 W pure nothrow @nogc immutable(char)[]
conv.toImpl!(immutable(char)[], int).toImpl(int)
0000000000000000 W pure nothrow @nogc immutable(char)[]
conv.textImpl!(immutable(char)[], int).textImpl(int)


@Iain any idea what to do about GCC 4.9 and 4.8? I could probably just amend the GCC patches to bave like GCC 5+ and always use the lto codepath... Or maybe this really is our fault as we're not emitting the toChars function.

-- 
You are receiving this mail because:
You are watching all bug changes.
August 02
https://bugzilla.gdcproject.org/show_bug.cgi?id=157

--- Comment #4 from Johannes Pfau <johannespfau@gmail.com> ---
https://gcc.gnu.org/viewcvs/gcc/branches/gcc-4_8-branch/gcc/dwarf2out.c?r1=224375&r2=224374&pathrev=224375

The GCC-4.8 LTO-only fix

-- 
You are receiving this mail because:
You are watching all bug changes.
August 02
https://bugzilla.gdcproject.org/show_bug.cgi?id=157

--- Comment #5 from Iain Buclaw <ibuclaw@gdcproject.org> ---
> So this explains why this bug vanished in newer releases. We may still have a template emission bug here though:

Are you sure?  I mean, if this is a nested instantiation, then it will be treated as non-public (static in the C sense).  So any unreferenced functions will be removed by the middle-end.


> @Iain any idea what to do about GCC 4.9 and 4.8? I could probably just amend the GCC patches to bave like GCC 5+ and always use the lto codepath... Or maybe this really is our fault as we're not emitting the toChars function.

I guess I see no problem just using backport, so long as it works.  But at the same time, I'd like to minimise just how much effort is put into the older versions.  Granted that they should be effectively in maintenance mode by now. ;-)


Looking at 4.9, I see that the same patch was applied as version 5.  So I was initially unsure why you have a problem.

https://gcc.gnu.org/viewcvs/gcc/branches/gcc-4_9-branch/gcc/dwarf2out.c?r1=224072&r2=224071&pathrev=224072

But then I saw that infact this patch resulted in a regression in both 4.9 and 5, and the fix for that is where the real divergence happened.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66503

So removing the !lto path won't help, it seemss.  The "proper" fix is already done in master (calling register_main_translation_unit), so I assume this is in all branches up to gcc-5 as well.

https://github.com/D-Programming-GDC/GDC/blob/3823c2f71bd7bc10c5184055eb9ee49da18106c0/gcc/d/d-lang.cc#L1380-L1392

Incidentally, done when addressing some other debugging woes.

https://github.com/D-Programming-GDC/GDC/commit/3c59416afa83bb0f2edd85fab3115c589b826306

-- 
You are receiving this mail because:
You are watching all bug changes.
August 02
https://bugzilla.gdcproject.org/show_bug.cgi?id=157

--- Comment #6 from Johannes Pfau <johannespfau@gmail.com> ---
> Are you sure?  I mean, if this is a nested instantiation, then it will be treated as non-public (static in the C sense).  So any unreferenced functions will be removed by the middle-end.

It doesn't even show up in -fdump-tree-original though and I think it should be there? Also the toChars function is not a nasted template (See conv.d in the attached test case). And the backend still emits an 'undefined' reference so this is not a case of completely removing the symbol.

> But at the same time, I'd like to minimise just how much effort is put into the older versions.  Granted that they should be effectively in maintenance mode by now. ;-)

Indeed. 'Usually' such problems don't appear though and backports are a simple git merge.

> Looking at 4.9, I see that the same patch was applied as version 5.  So I was initially unsure why you have a problem.

OK, I see. Removing !lto worked around the problem, but it will then probably trigger the other regression you linked ;-)

> The "proper" fix is already done in master (calling register_main_translation_unit), so I assume this is in all branches up to gcc-5 as well.

register_main_translation_unit is not in gcc 4.9 or 4.8, it was introduced in gcc-5 to fix the follow-up bug you linked. Not sure if I want to introduce such changes into our GCC patches though...

Maybe I'll just disable debug info generation when building phobos and keep this as a won't fix for < 4.9.

-- 
You are receiving this mail because:
You are watching all bug changes.
August 03
https://bugzilla.gdcproject.org/show_bug.cgi?id=157

--- Comment #7 from Iain Buclaw <ibuclaw@gdcproject.org> ---
(In reply to Johannes Pfau from comment #6)
> It doesn't even show up in -fdump-tree-original though and I think it should be there? Also the toChars function is not a nasted template (See conv.d in the attached test case). And the backend still emits an 'undefined' reference so this is not a case of completely removing the symbol.
> 


OK, I've managed to unearth this in 2.074 I think.
---
$ nm src/.libs/libgphobos.so.74 | grep " U " | grep _D3std
                 U
_D3std4conv47__T7toCharsVii10TaVE3std5ascii10LetterCasei1TkZ7toCharsFNaNbNiNfkZ6Result5emptyMFNaNbNdNiNfZb
                 U
_D3std4conv47__T7toCharsVii10TaVE3std5ascii10LetterCasei1TkZ7toCharsFNaNbNiNfkZ6Result5frontMFNaNbNdNiNfZa
                 U
_D3std4conv47__T7toCharsVii10TaVE3std5ascii10LetterCasei1TkZ7toCharsFNaNbNiNfkZ6Result6lengthMFNaNbNdNiNfZm
                 U
_D3std4conv47__T7toCharsVii10TaVE3std5ascii10LetterCasei1TkZ7toCharsFNaNbNiNfkZ6Result8popFrontMFNaNbNiNfZv
                 U
_D3std4conv47__T7toCharsVii10TaVE3std5ascii10LetterCasei1TkZ7toCharsFNaNbNiNfkZS3std4conv47__T7toCharsVii10TaVE3std5ascii10LetterCasei1TkZ7toCharsFNaNbNiNfkZ6Result
---

Having a quick grep, in this case, the symbol is coming from regex.internal.backtrace.  Compiling with -funittest and the problem goes away - possibly because *all* symbols are emitted in this mode.

https://github.com/D-Programming-GDC/GDC/blob/7de3bf8fb18aa3f1ef4e3363b80b50ed1212d190/gcc/d/dfrontend/dtemplate.c#L7445-L7451

-- 
You are receiving this mail because:
You are watching all bug changes.
August 03
https://bugzilla.gdcproject.org/show_bug.cgi?id=157

--- Comment #8 from Iain Buclaw <ibuclaw@gdcproject.org> ---
Reduced test (uses two imports):
---
struct Bytecode
{
    uint data;
}

@trusted ctSub(U)(string format, U args)
{
    import std.conv : to;
    foreach (i; format)
        return  format~ to!string(args);
    return format;
}

struct CtContext
{
    import std.uni : CodepointSet;

    CodepointSet[] charsets;

    string ctAtomCode(Bytecode[] ir)
    {
        string code;
        switch (code)
        {
            OrChar:
                code ~=  ``;
                for (uint i ; i ;)
                    code ~= ctSub(``, ir[i].data);
                charsets[ir[0].data].toSourceCode;
                break;

            default:
                assert(0);
        }
        return code;
    }
}
---

And compiling:
---
$ gdc backtracking.d -v 2>&1 | grep -E ".toChars$"
function  std.conv.toChars!(16, char, cast(LetterCase)false, uint).toChars
function  std.conv.toChars!(16, char, cast(LetterCase)true, uint).toChars
function  std.conv.toChars!(2, char, cast(LetterCase)true, uint).toChars
function  std.conv.toChars!(8, char, cast(LetterCase)true, uint).toChars

$ dmd backtracking.d -v 2>&1 | grep -E ".toChars$"
function  std.conv.toChars!(10, char, cast(LetterCase)true, uint).toChars
function  std.conv.toChars!(16, char, cast(LetterCase)false, uint).toChars
function  std.conv.toChars!(16, char, cast(LetterCase)true, uint).toChars
function  std.conv.toChars!(2, char, cast(LetterCase)true, uint).toChars
function  std.conv.toChars!(8, char, cast(LetterCase)true, uint).toChars
---

Yes, it seems that there is something not quite aligned between the frontends here.

Though not sure if this is related to this particular bug just yet. ;-)

-- 
You are receiving this mail because:
You are watching all bug changes.
August 03
https://bugzilla.gdcproject.org/show_bug.cgi?id=157

--- Comment #9 from Iain Buclaw <ibuclaw@gdcproject.org> ---
(In reply to Iain Buclaw from comment #8)
> Though not sure if this is related to this particular bug just yet. ;-)

Not related, I was testing an older version of dmd v2.074.1 has the problem, but it looks like a library change caused it, rather than a compiler.

-- 
You are receiving this mail because:
You are watching all bug changes.
August 03
https://bugzilla.gdcproject.org/show_bug.cgi?id=157

--- Comment #10 from Johannes Pfau <johannespfau@gmail.com> ---
FYI -femit-templates fixes the build for GCC-4.9, so it's really the missing toChars symbol causing a backend ICE in gcc <= 4.9. So this is really a frontend problem manifesting differently for older GCC versions.

I'll just hope for a DMD frontend fix or adjust one of the -g -O2 or --femit-templates flags to make GCC 4.9 pass the build.

-- 
You are receiving this mail because:
You are watching all bug changes.
« First   ‹ Prev
1 2