What’s Bugging GDC?

Recently, I was asked the question:

Is gdc 4.3 really stable enough to be the default gdc?

As the gdc meta-package in Debian Squeeze and Ubuntu Lucid has been updated to now depend on gdc-4.3 instead of gdc-4.1. And by just playing around with D for a few days the kind fella who asked me that discovered two bugs. So it seems to him that gdc-4.3 is far from being as mature as gdc-4.1 …

I decided to look into this by running dstress against the most recent build. For those of you who don’t know, dstress is a testing suite for D to ensure that the compiler correctly compiles (or in some cases, must not compile) a collection of about 7000+ files with 32 different compiler flag combinations without dying unintentionally, ie: via assertion or a segmentation fault.

From that huge list, I got a total of 10 internal compiler errors produced.

Here is a beautified list of internal errors that I got from the report. This first list consists of GDC back-end errors only, as they will be specific to GDC. Unlike the front-end errors, which will most likely be present in DMD and possibly LDC too.

Update: Some good development has gone into GDC since writing this post, so I’m crossing off each issue as it gets resolved.

________________________________________________________________

Internal Compiler Error 1:

Code?

public struct Color
{
    double red   = 0;
    double green = 0;
    double blue  = 0;

    static Color opCall()
    {
        Color instance;
        return instance;
    }
    Color opAdd(real right){ return Color(); }
    void opAddAssign(real right){ *this = *this + right; }
}

Error?

opAddAssign_A.d: In member function ‘opAddAssign’:
opAddAssign_A.d:13: internal compiler error: in decl_ultimate_origin, at dwarf2out.c:5139

Reproducable?
Only via:

gdc -g -O3 -c opAddAssign_A.d
gdc -g -O2 -frelease -c opAddAssign_A.d
gdc -g -Os -frelease -c opAddAssign_A.d
gdmd -g -O -inline -c opAddAssign_A.d
gdmd -g -O -release -c opAddAssign_A.d

Variants?
Not known.

Workaround?
In all cases, include the compiler option “-fno-inline” to workaround the bug.

Bug seen in gdc-4.1?
No.

________________________________________________________________

Internal Compiler Error 2:

Code?

template thunk(alias fn)
{
    static void thunk(int* arg)
    {
        fn(arg);
    }
}

int main()
{
    int x = 1;
    void inner(int* arg)
    {
        if(!(arg !is &x))
            assert(0);
    }
    thunk!(inner)(&x);
    return 0;
}

Error?

bug_tree_inline_1902_B.d: In function ‘thunk’:
bug_tree_inline_1902_B.d:5: internal compiler error: in estimate_num_insns_1, at tree-inline.c:2494

Reproducable?
Always.

Variants?
Seen also in compiler error 3 and 4, but not known just how related they are.

Workaround?
Using “void thunk” instead of “static void thunk”.

Bug seen in gdc-4.1?
Yes.

________________________________________________________________

Internal Compiler Error 3:

Code?

int main()
{       
    void foo() {}       
    void function() bar = function void()
    {           
        foo();  
    };  
    return 0;
}

Error(s)?

bug_e2ir_299_A.d: In function ‘__funcliteral1’:
bug_e2ir_299_A.d:6: internal compiler error: in estimate_num_insns_1, at tree-inline.c:2494

Reproducable?
Always.

Variants?
Seen also in compiler error 2 and 4, but not known just how related they are.

Workaround?
Is apparently not supposed to be compilable. (comes under nocompile).

Bug seen in gdc-4.1?
Yes.

________________________________________________________________

Internal Compiler Error 4:

Code?

struct A (alias F)
{
    int f() { return F(); }
}

void main()
{
    int f() { return 0; }
    A!(f) a;
}

Error?

template_struct_01_A.d: In member function ‘f’:
template_struct_01_A.d:5: internal compiler error: in estimate_num_insns_1, at tree-inline.c:2494

Reproducable?
Always.

Variants?
Seen also in compiler error 2 and 3, but not known just how related they are.

Workaround?
None.

Bug seen in gdc-4.1?
Yes.

________________________________________________________________

Internal Compiler Error 5:

Code?

class Outer
{
    this()
    {
        Inner i = new Inner();
    }

    class Inner
    {
        Strct str;
    }
}

struct Strct
{
    int i;
}

int main()
{
    Outer o = new Outer();
    return 0;
}

Error?

forward_reference_17_A.d: In member function ‘_ctor’:
forward_reference_17_A.d:5: internal compiler error: Segmentation fault

Reproducable?

Always

Variants?
Not known.

Workaround?
Declare the struct before the class.

Bug seen in gdc-4.1?
Yes

________________________________________________________________

Internal Compiler Error 6:

Code?

bool nextis(void delegate() dgpositive = {})
{
    return true;
}

bool looping(lazy bool condition)
{
    return true;
}

int main()
{
    looping(nextis());
    return 0;
}

Error?

lazy_02_A.d: In member function ‘__dgliteral2’:
lazy_02_A.d:2: internal compiler error: in getFrameForSymbol, at d/d-codegen.cc:2541

Reproducable?
Always.

Variants?
Anything that uses the following as an argument.

void delegate() foo = {}

Workaround?
None.

Bug seen in gdc-4.1?
Yes.

________________________________________________________________

Internal Compiler Error 7:

Code?

int status;

template T(alias a)
{
    int dummy;
}

class C
{
    mixin T!(
            () {
                status++;
            }
        ) mixed;
}

int main()
{
    C c = new C();
    c.mixed.a();
    if(status != 1)
    {
        assert(0);
    }
    return 0;
}

Error?

mixin_23_A.d:11: Error: delegate mixin_23_A.C.__dgliteral1 literals cannot be class members
cc1d: internal compiler error: Segmentation fault

Reproducable?
Always.

Variants?
Also seen when using:

mixin T!( delegate() { status++; } ) mixed;

And:

mixin T!( { status++; } ) mixed;

Workaround?
Using function() works around the problem, but probably not correct due to semantic differences.

mixin T!( function(){ status++; } ) mixed;

Bug seen in gdc-4.1?
No.

________________________________________________________________

In this second list are DMD frontend compiler errors, they aren’t necessarily the fault of GDC’s, and they may well be present in LDC too.

Internal Compiler Error 8:

Code?

char[] testHelper(A ...)()
{
    char[] result;
    foreach(t; a)
    {
        result ~= "int " ~ t ~ ";\n";
    }
    return result;
}

int main()
{
    mixin( testHelper!( "hello", "world" )() );
    return 0;
}

Error?

cc1d: ../../src/gcc/d/dmd/template.c:811: MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc, Objects*, Expression*, Expressions*, Objects*): Assertion `i dim' failed.
cc1d: internal compiler error: Aborted

Reproducable?
Always.

Variants?
Not known.

Workaround?
Code is not supposed to be compilable. (comes under nocompile).

Bug seen in gdc-4.1?
No.

________________________________________________________________

Internal Compiler Error 9:

Code?

void[10] array;

Error?

Error: integral constant must be scalar type, not void
cc1d: ../../src/gcc/d/dmd/todt.c:85: dt_t* createTsarrayDt(dt_t*, Type*): Assertion `tsa->size(0) % eoa_size == 0' failed.
cc1d: internal compiler error: Aborted

Reproducable?
Always.

Variants?
Not known.

Workaround?
Code is not supposed to be compilable. (comes under nocompile).

Bug seen in gdc-4.1?
Yes.

________________________________________________________________

Internal Compiler Error 10:

Code?

int main()
{
    auto arr = [4:"vier", 0:"null", 2:"zwei"];

    if(3 != arr.length)
    {
        assert(0);
    }

    char[][] master_e = ["vier", "null", "zwei"];
    int[] master_i = [4, 0, 2];

    foreach(index, element; arr)
    {
        bool found = false;
        foreach(pos, i; master_i)
        {
            if(index == i && element == master_e[pos])
            {
                master_i = master_i[0 .. pos] ~ master_i[pos+1 .. $];
                master_e = master_e[0 .. pos] ~ master_e[pos+1 .. $];
                found = true;
                break;
            }
        }
        if(!found)
        {
            assert(0);
        }
    }
    if(master_i.length)
    {
        assert(0);
    }
    return 0;
}

Error?

associative_array_23_B.d:3: Error: cannot infer type from this array initializer
cc1d: ../../src/gcc/d/dmd/init.c:437: virtual Expression* ArrayInitializer::toExpression(): Assertion `j < edim' failed.
cc1d: internal compiler error: Aborted

Reproducable?
Always.

Variants?
Not known.

Workaround?
None.

Bug seen in gdc-4.1?
No.

________________________________________________________________

So, as far as the dstress testing goes, there are currently 4 regressions – 2 of which are not the fault of gdc – and 6 inherited bugs in gdc-4.3 when compared to gdc-4.1.

So, back to your original question, is gdc 4.3 really stable enough to be the default gdc? Thanks to your help in identifying two underlying problems in the Debianised version, yes, I believe it is!

Despite some outstanding quirks, and the odd ICE or two in this post that would be cool to plumb down and fix. I think we are heading in for a strong release – if and when the GDC upstream developers ever get round to it. In the meantime, I will continue maintaining the Debian and Ubuntu packages, and will love to hear more of your dedicated support and patience in testing.

Got any other show-stopping bugs? Please report! :-)

Advertisements

About ibuclaw
An avant developer and support analyst.

7 Responses to What’s Bugging GDC?

  1. caedes says:

    Hi, I’m the “kind fella” who asked that question. Just stumpled upon this post when I googled for “dstress gdc”, because now that gdc-4.1 is even removed from debian squeeze (testing) I thought about running dstress with gdc-4.3 to find more show-stoppers, because it’d be a shame if people would be turned off from trying D because of a buggy compiler, but fortunately you already did that :-)

    So there are 3 new bugs in gdc-4.3 (1, 7, 10) and 4 bugs that were already present in 4.1 (2, 4, 5, 6) – with more than 7000 files with tests this is indeed good and I’m quite positive that you can fix them like you fixed those other bugs. (I don’t know much about writing compilers and even less about gcc/gdc’s internals, so I can only report bugs, but not fix them :-/).

    Another way to find obvious bugs might be to run the unit tests included in libphobos (at least the MD5/assembler-bug could have been found that way).

    Anyway, it’s great that you maintain and fix gdc in debian, so that the next release (whenever it may happen..) will contain a stable D compiler.

    Cheers,
    – Daniel

    • ibuclaw says:

      Hi there Daniel, so great for you to stumble yourself here. ;)

      First I’d like to say thanks for your enthusiasm, optimism and interaction, it really wouldn’t be fun without it.

      Second, we’ve recently had a bump in the GCC version this weekend – GCC-4.3.5 has been uploaded into Debian – and GDC has been/currently is (as of writing this) being built against it. I anticipate no regressions in the version bump, but I suppose now is a better time than never if you still want to go ahead and test anyway … as soon as it is uploaded (watch this link)
      https://buildd.debian.org/pkg.cgi?pkg=gdc-4.3

      And knowledge of compilers or gcc is not really essential to get your feet wet. When I started out, I couldn’t honestly say I knew anything at all. But, the programmer cliché is true. When it comes to it, don’t do something you can accomplish fairly easily. Take on a project wherein you have no idea where to begin. Throw yourself in the deep end. The benefits of this is that you will learn things you never knew existed and when you do complete it, you will feel an immense pride and satisfaction. This is what keeps me going.

      Regards
      Iain

      • caedes says:

        Yeah, I’ll try the new version when it enters sid (I hope the packages work in squeeze so I don’t have to build the gdc and gcc packages myself ;))

        You’re probably right about taking on a difficult project, but with my limited spare time it’s difficult to get into a complex project before something else that is more important, has to be done (university takes up most of my time).

  2. caedes says:

    Hi Iain,

    I decided today to try out D2 and compiled gdc-4.3 with D2 support.. It did build almost painless (had to change two little things to get it working on my AMD64-Box: internal/object.d has two “alias bool bit;” statements, that’s one to many and std/cpuid.d for non-x86 needs to be fixed in lines 388-391 – the functions should return string instead of char[]), but when I wanted to try it, it seemed horribly outdated (libphobos2 has no ranges for example).
    Is only libphobos2 outdated or also the compiler itself?
    What are the plans regarding future D2 support, now that it’s (almost?) stable and Andrei Alexandrescu’s “The D Programming Language” is available?

    Cheers,
    – Daniel

    • ibuclaw says:

      My initial work will be to get D1 done and dusted for being up to date with upstream. Currently bombing through that, and can expect that done over the next fortnight.

      Only then, I will then turn my attention to D2. And yes, it is horribly outdated in comparison – currently at 2.015, which is about 2-3 years out of date to my watch.

      • caedes says:

        Sounds reasonable, thanks for your great work :-)

        Btw: Would it be difficult to support std.cpuid on AMD64 machines, given that it’s just a pimped i386 so the assembler commands to get the CPU infos are probably similar?

      • ibuclaw says:

        That would require 64bit ASM support I’m afraid. Which is not as difficult as it sounds (LDC’s 64bit inline ASM is forked from GDC’s 32bit implementation, and requires just a few dozen changes to port it back), but will probably wait until later to get the nice features in.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: