Bug 8521 – ICE(e2ir.c) when a function uses a template which relies on that function and -release and -inline are used

Status
RESOLVED
Resolution
WORKSFORME
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-08-08T00:18:00Z
Last change time
2020-03-21T03:56:39Z
Keywords
ice
Assigned to
No Owner
Creator
Jonathan M Davis
See also
https://issues.dlang.org/show_bug.cgi?id=14447

Comments

Comment #0 by issues.dlang — 2012-08-08T00:18:00Z
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 by issues.dlang — 2012-08-08T12:53:49Z
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 #2 by github-bugzilla — 2012-08-19T18:51:50Z
Comment #3 by r.sagitario — 2012-08-21T00:34:00Z
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 by issues.dlang — 2012-08-21T00:47:26Z
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 by r.sagitario — 2012-08-21T15:05:28Z
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 by github-bugzilla — 2012-08-22T02:27:37Z
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 by bugzilla — 2013-10-03T18:10:31Z
These examples compile successfully with 2.064 head.
Comment #8 by b2.temp — 2019-03-10T21:46:35Z
No more ICEs but still a SIGILL when runing the first example, due to assert(0);