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

Fixing your HAL application for Ubuntu 10.04

Ubuntu Lucid Lynx sports full removal of HAL from the boot process, making Ubuntu faster to boot and faster to resume from suspend.

From a developer stance, all what has changed is that Ubuntu has switched over to D-BUS activation. So if a program tries to talk to HAL, but HAL is not running, it triggers it’s startup.

If this isn’t the case when you try to start your application, then the most likely reason is that it is too cautious and checks if HAL is running before trying to connect to it. This is true in the case of lshal, where you probably wouldn’t want HAL starting if it wasn’t already running.

Such an example of this check would be as seen below (taken from pcmanfm).

/* try to initialize the HAL context */
if (!libhal_ctx_init (hal_context, &error)
    goto failed;

What we do differently is simply dropping the check, letting the application connect to hal straight away, checking of course if that failed instead before returning true.

/* try to initialize the HAL context */
libhal_ctx_init (hal_context, &error);

Happy debugging!

Regards

HowTO: Setup Twin Graphics Cards

Some people I have been supporting use twin view with two NViDIA graphics cards. While this is perfectly fine, you may run into problems if your xorg.conf file is setup to handle only one card.

Such a setup will look like this when you go to edit the xorg.conf file.

Section "Device"
    Identifier     "Device0"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
EndSection

To work around the issue, it is best advised to remove the secondary card from the computer, boot up and acquire the output of the following.

lspci | grep VGA

and you should see something like this:

04:00.0 VGA compatible controller: nVidia Corporation GeForce 9800 GX2

Make a note of the Bus ID of the card (04:00.0) , and edit the xorg.conf file.

sudo nano /etc/X11/xorg.conf

Scroll to the Device section and add the Bus ID to the conf file, except remove all leading zeros, replace the period with a colon, and add ‘PCI’ as a prefix.
So, our example of 04:00.0 becomes:

Section "Device"
    BUSID          "PCI:4:0:0"
    Identifier     "Device0"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
EndSection

After doing this, save the file, then shutdown the workstation and reinsert the second GFX card back into the machine.

Regards

HowTO: Manually Compile NViDIA Drivers in Ubuntu

This is the shortened “in a nutshell” version of my guide here.

So, here goes:

Backup your current configuration.

sudo cp /etc/X11/xorg.conf /etc/X11/xorg.xonf.original

Install all build dependencies.

sudo apt-get install build-essential pkg-config linux-headers-$(uname -r)

Remove all traces of the Ubuntu version of NViDIA on your system

sudo aptitude purge $(dpkg -l | grep nvidia | awk '{print $2}')

Download the driver from the  nvidia download site.

For 32bit systems using the 185 Driver:

wget ftp://download.nvidia.com/XFree86/Linux-x86/185.18.36/NVIDIA-Linux-x86-185.18.36-pkg0.run -O NVIDIA-Linux-185.18.pkg.run

For 64bit systems using the 185 Driver:

wget ftp://download.nvidia.com/XFree86/Linux-x86_64/185.18.36/NVIDIA-Linux-x86_64-185.18.36-pkg0.run -O NVIDIA-Linux-185.18.pkg.run

If you use a legacy card that is not supported by the 185 driver, you can download the right one accordingly here for 32bit or here for 64bit.

Install the installer into the /usr/src directory and create an easy link to it.

sudo install NVIDIA-Linux-185.18.pkg.run /usr/src
sudo ln -fs /usr/src/NVIDIA-Linux-185.18.pkg.run /usr/src/nvidia-driver

Save and close all work, then kill X.

sudo service gdm stop

Login to a VT, and run the installer.

sudo sh /usr/src/nvidia-driver

Once the installer finishes, restore the backed up xorg.conf

sudo cp /etc/X11/xorg.conf.original /etc/X11/xorg.conf

And restore X.

sudo service gdm start

Congratulations, you now are running on your own manually compiled drivers.

One caveat with this that you must recompile every time there is a kernel update. For a guide on how to automate this procedure, see here.

To upgrade from your manually compiled the 185 drivers to the latest 190 beta, you would run through the current procedure.

Download

wget ftp://download.nvidia.com/XFree86/Linux-x86/190.32/NVIDIA-Linux-x86-190.32-pkg0.run -O NVIDIA-Linux-190.32.pkg.run

Install into the /usr/src directory, and override your existing symlink

sudo install NVIDIA-Linux-190.32.pkg.run /usr/src
sudo ln -fs /usr/src/NVIDIA-Linux-190.32.pkg.run /usr/src/nvidia-driver

Save and close all work, then kill X.

sudo service gdm stop

Uninstall NViDIA, to ensure a smooth transition.

sudo nvidia-uninstall

Run the installer as per previous method.

sudo sh /usr/src/nvidia-driver

And restore X.

sudo service gdm start

simple, eh?

HowTO: Fix Laptop Battery not Detected in LXDE Applet

Although it is really the fault of the application having a certain location hard coded into them, one way to workaround a problem with the battery not being detected by the battery applet.

First though, to confirm that this fix applies to you, run the following:

ls /proc/acpi/battery

If you get something other than CMB0 in the output, this fix may not apply to you.

First thing we need to do is install the iasl compiler/decompiler

sudo apt-get install iasl

Then obtain a copy of your motherboard’s dsdt

sudo cat /proc/acpi/dsdt > dsdt.dat

Decompile the dsdt

iasl -d dsdt.dat

Then change all instances of CMB0 with BAT0 using sed

sed -i 's/CMB0/BAT0/g' dsdt.ds

and finally compile the dsdt again

iasl -tc dsdt.dsl

You may receive errors/warnings when compiling. If your system runs just fine, you can safely ignore these, else you may want to look into fixing them, as a buggy dsdt can mean that you are unable to suspend/hibernate.

To implement the new dsdt into your system, run the following:

sudo cp dsdt.aml /etc/initramfs-tools/DSDT.aml
sudo update-initramfs -u all

and then just reboot.

To test that dsdt is working, run the following:

ls /proc/acpi/battery

and you will now see BAT0 in the output.

Note: The Kernel Devs will no longer use the patch to enable custom DSDTs for all releases after Karmic. Jaunty will be the last release that this works on.

HowTO: Save and Restore ALSA settings on Startup/Shutdown

First problem of the day. :-)

Incase you are curious, or you find that everytime you reboot, Ubuntu resets your alsa volume settings back to mute or 100%. You don’t have to resort to custom script or cronjobs. Ubuntu has everything setup already, it is just disabled for what appears to be “speed” reasons.

Run the following in a terminal:

sudo mv /etc/rc0.d/K50alsa-utils /etc/rc0.d/S50alsa-utils
sudo mv /etc/rc6.d/K50alsa-utils /etc/rc6.d/S50alsa-utils

and reboot your workstation. All alsa settings will now be saved/restored for you automatically on startup/shutdown.

Follow

Get every new post delivered to your Inbox.