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! :-)

Debian kFreeBSD in QEMU-KVM

Debian GNU/kFreeBSD is a port that consists of GNU userland using the GNU C library on top of FreeBSD‘s kernel, coupled with the regular Debian package set.

Installing

Assuming you don’t have KVM already installed, you’ll need to run:

sudo apt-get install kvm

Then check for the presence of /dev/kvm. If it doesn’t exist, check that virtualisation is turned on in BIOS, else your system does not have the CPU extensions required to use KVM, so will fall back to using qemu instead.

You can get the installation media either from here or grab the daily mini.iso at this location.

wget http://glibc-bsd.alioth.debian.org/install-cd/kfreebsd-i386/current/debian-20090729-kfreebsd-i386-install.iso

Create a hard drive image.

kvm-img create -f qcow kfreebsd.img 10G

And get started.

kvm -drive file=kfreebsd.img,index=0,cache=writeback,media=disk -cdrom debian-20090729-kfreebsd-i386-install.iso

Note: I use -drive instead of -hda because I find that it increases I/O performance of the guest system.

For installing Debian GNU/kFreeBSD and other useful information, refer to the install notes.

You have two ways of running through the installer, Express or Custom, I chose “Express”. This brings you to a command-line partitioner, simply press ‘a‘ to create a slice across the whole hard drive, and ‘q‘ to finish.

Next is the BootMgr, in this program, press ‘c‘ to create a ‘9500M‘ filesystem to mount on ‘/‘, followed by a the creation of a swap to fill the rest. Once done press ‘q‘ to finish.

Next, you’ll be asked what distribution you wish to install. I selected ‘minimal‘, and if you plan to do a CD installation, I suggest the same too. Else with a Network installation, you could get away with what you want.

In the next menu, select the medium you wish to install off, either choose Network or CDROM here, then wait around to let the extraction finish. Then you’ll need to press ‘Alt+F3‘ to proceed with the installation, answering any questions you may be asked.

Once finished, you’ll be prompted to answer ‘No’ to reboot. Don’t do this, instead answer ‘Yes‘ to return to the configuration menu, where you should set the Root Password first, then optionally configure anything else you may wish to. Once done, then exit the install and reboot into your new system.

Configuring for Network

Unfortunately, some of the defaults of the installation aren’t setup correctly for immediately usage.

First thing you’ll notice is no networking, so login to the root account and get that set.

nano /etc/network/interfaces

And put in the file

auto re0
iface re0 inet dhcp

Save, then restart networking

service networking restart

You can now update your system. Before you upgrade though, there is a nasty bug that prevents ‘rm’ working properly on directories on the freebsd 7.x kernels, so we’ll need to put the coreutils package on hold.

echo coreutils hold | dpkg --set-selections
apt-get update
apt-get dist-upgrade

Configuring for X

Install Xorg.

apt-get install xorg

Now to address some issues.

Firstly, if you haven’t already noticed, during the installation of xorg, the package ‘hal’ (as of writing) fails to install properly, leaving xorg in an unconfigured state.

Simply reboot the VM, login, and restart dbus.

service dbus restart

then run the installer again to finish the setup.

apt-get install -f

Secondly, xorg.conf needs to be setup correctly. To create a configuration file run:

X -configure

Allow about a 30-60 seconds for it to finish, then open the generated file for editing.

nano xorg.conf.new

Without going into too much detail, remove ‘Files’ and ‘Modules’ section, then edit the Sections outlined below as seen.

Section "InputDevice"
    Driver        "kbd"
[...]
Section "InputDevice"
    Driver        "mouse"
    Option        "Protocol" "SysMouse"
    Option        "Device" "/dev/sysmouse"
[...]
Section "Device"
    Driver        "vesa"
[...]

Note: If you have support for kvm, you can get away with having Driver “cirrus” instead of “vesa” in your config file. Am not sure of the benefits either or though.

Once done, install the file in it’s proper location.

mv xorg.conf.new /etc/X11/xorg.conf

Lastly, you need to create the mouse and keyboard policies for hal, as without them, will unusable under X.

First is the keyboard policy

nano /etc/hal/fdi/policy/10-x11-input-kbd.fdi

And put into the file:

<?xml version="1.0" encoding="ISO-8859-1"?>
<deviceinfo version="0.2">
  <device>
    <match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" string="GNU/kFreeBSD">
      <match key="info.capabilities" contains="input.keys">
        <merge key="input.x11_driver" type="string">kbd</merge>
      </match>
    </match>
  </device>
</deviceinfo>

Ditto for the mouse policy.

nano /etc/hal/fdi/policy/10-x11-input-mouse.fdi

And put into the file:

<?xml version="1.0" encoding="ISO-8859-1"?>
<deviceinfo version="0.2">
  <device>
    <match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" string="GNU/kFreeBSD">
      <match key="info.capabilities" contains="input.mouse">
        <merge key="input.x11_driver" type="string">mouse</merge>
      </match>
    </match>
  </device>
</deviceinfo>

Graphical Login

Finally, install your favourite Window-Manager and Display-Manager. I chose xfce and gdm.

apt-get install xfce gdm

And reboot once more to be greeted by a graphical login screen.

As you can see, there is still alot of work to go into the port, a lot of work to setup correctly, and even then it is not guarenteed to work everytime. :)

However, hope you find a place for this fun Debian port when you get it stable + working.

debian kfreebsd screenshot

Regards

Follow

Get every new post delivered to your Inbox.