D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 8521 - ICE(e2ir.c) when a function uses a template which relies on that function and -release and -inline are used
Summary: ICE(e2ir.c) when a function uses a template which relies on that function and...
Status: RESOLVED WORKSFORME
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 major
Assignee: No Owner
URL:
Keywords: ice
Depends on:
Blocks:
 
Reported: 2012-08-08 00:18 UTC by Jonathan M Davis
Modified: 2020-03-21 03:56 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Jonathan M Davis 2012-08-08 00:18:00 UTC
This is currently a blocker for phobos pull request# 743, which make stride, strideBack, and decode work with arbitrary ranges of code units, which is needed for the D lexer for Phobos that I'm working on.

This is the reduced code:

import std.traits;

void main()
{
    auto tmp = "hello";
    size_t i = 0;
    decode(tmp, i);
}

template isRange(R)
{
    enum bool isRange = is(typeof(
    {
        R r = void;
        auto w = r.front;
    }));
}

@property dchar front(A)(A a)
{
    size_t i = 0;
    return decode(a, i);
}

dchar decode(S)(auto ref S str, ref size_t index)
{
    return decodeImpl(str, index);
}

private dchar decodeImpl(S)(auto ref S str, ref size_t index)
{
    enum canIndex = isRange!S;

    assert(0);
}


It compiles just fine normally, but when you compile with -release and -inline together, it fails to compile, giving this error:

decodeImpl(S)
Internal error: e2ir.c 720

I think that the problem stems from the fact that isRange depends on decode, which in turn depends on isRange, and something about the inlining process screws it up. Moving the line with isRange from decodeImpl into decode makes the problem going away as does removing front from inside of isRange. And using decode inside of isRange makes it go away as well. So, it seems that the number of levels of indirection has to be at at least a certain level before the failure occurs.

The code in pull request# 743 passes its unit tests just fine as long as you don't compile with both -release and -inline, so clearly the code can work, but something about -release and -inline screws it up.
Comment 1 Jonathan M Davis 2012-08-08 12:53:49 UTC
Okay. I was finally able to find a workaround by moving the test inside of decodeImpl to outside of it, which is leaking its implementation details and forcing a bool with the result of the test to be passed to an overload of decodeImpl which doesn't need the test at all, but it does make it so that the code works, and it doesn't affect the public API at all. So, I'm changing this bug to major rather than blocker.
Comment 3 Rainer Schuetze 2012-08-21 00:34:00 UTC
I just hit this bug aswell, but your work-around does not seem to help. With current head from github:

module test;
import std.utf;

dchar foo(string s)
{
	size_t pos;
	return decode(s, pos);
}


I get ICE with -inline:

>m:\s\d\rainers\windows\bin\dmd -c test.d

>m:\s\d\rainers\windows\bin\dmd -c -inline test.d
Statement::doInline()
goto __returnLabel;

Assertion failure: '0' on line 470 in file 'inline.c'

abnormal program termination

>m:\s\d\rainers\windows\bin\dmd -c -inline -release test.d
decodeImpl(bool canIndex,S) if (is(S : const(char[])) || isInputRange!(S) && is(Unqual!(ElementEncod
ingType!(S)) == char))
Internal error: e2ir.c 720
Comment 4 Jonathan M Davis 2012-08-21 00:47:26 UTC
Well, it helps in that the situation is improved enough that dmd's tests passed (which wasn't the case before), but clearly, it doesn't fully get around the problem. Bleh.

I guess that I'll have to take another whack at the workaround. It would be _really_ nice if someone could fix this bug though.
Comment 5 Rainer Schuetze 2012-08-21 15:05:28 UTC
It seems that dmd is unable to generate code for the expression

    return str[index] < codeUnitLimit!S ? str[index++] : decodeImpl!true(str, index);

This workaround compiled for me:

    if(str[index] < codeUnitLimit!S)
        return str[index++];
    return decodeImpl!true(str, index);
Comment 6 github-bugzilla 2012-08-22 02:27:37 UTC
Commit pushed to master at https://github.com/D-Programming-Language/phobos

https://github.com/D-Programming-Language/phobos/commit/038e30c737370d7d0489be2e0e889f0f8f071fad
Minor adjustment to better workaround bug# 8521.

Apparently, using the ternary operator makes it worse, so I switched it
to use if instead. The semantics are identical.
Comment 7 Walter Bright 2013-10-03 18:10:31 UTC
These examples compile successfully with 2.064 head.
Comment 8 basile-z 2019-03-10 21:46:35 UTC
No more ICEs but still a SIGILL when runing the first example, due to assert(0);