[Dlang-internal] Detect CTFE in AssignExp:semantic
Lucia Cojocaru via Dlang-internal
dlang-internal at puremagic.com
Tue Jan 10 04:13:18 PST 2017
Hello,
Brief context description:
I'm trying to replace calls to druntime functions such as
_d_arraycopy [0] with calls to templates. These calls are
generated by the compiler here [1] for array assignments like
below:
int[2] a = [1, 2];
int[2] b;
b[] = a[]; // _d_array_copy call
There are several such druntime functions and the purpose of this
is to avoid pulling druntime as a dependency unless necessary.
The templates don't "exist" if not used and many of them can be
implemented without pulling any dependency.
--------------------------------------------------------------
I implemented a lowering in AssignExp:semantic to a template call
for the use case described above. However compilation fails for
this code (I extracted this bit from druntime code):
1
2 char[] mangle(T)(const(char)[] fqn, char[] dst = null) @safe
pure nothrow
3 {
4 import core.internal.string : numDigits,
unsignedToTempString;
5
6 static struct DotSplitter
7 {
8 @safe pure nothrow:
9 const(char)[] s;
10
11 @property bool empty() const { return !s.length; }
12
13 @property const(char)[] front() const
14 {
15 immutable i = indexOfDot();
16 return i == -1 ? s[0 .. $] : s[0 .. i];
17 }
18
19 void popFront()
20 {
21 }
22
23 private ptrdiff_t indexOfDot() const
24 {
25 foreach (i, c; s) if (c == '.') return i;
26 return -1;
27 }
28 }
29
30 size_t len = "_D".length;
31 foreach (comp; DotSplitter(fqn))
32 len += numDigits(comp.length) + comp.length;
33
34 return ['a', 'b', 'c'];
35 }
36
37 char[] mangleFunc(T:FT*, FT)(const(char)[] fqn, char[] dst =
null) @safe pure nothrow if (is(FT == function))
38 {
39 return mangle!FT(fqn, dst);
40 }
41
42 pragma(mangle, mangleFunc!(int function(int))("a.b"));
43
44 int main() {
45 return 0;
46 }
The error is:
ctfe.d(28): Error: 2 variable __r57 cannot be read at compile time
ctfe.d(28): called from here: _d_arraycopyT(this.s[],
__r57, 1u)
ctfe.d(18): called from here: this.indexOfDot()
ctfe.d(34): called from here: __r58.front()
ctfe.d(42): called from here: mangle(fqn, dst)
ctfe.d(45): called from here: mangleFunc("a.b", null)
This is probably because of an issue with CTFE and the solution
may be to avoid generating calls to the template in a CTFE
context. The code in AssignExp:semantic [2] would look like this:
if (__ctfe)
{
// add template call to AST
}
else
{
// old code
}
However I was not able to detect this situation from
AssignExp:semantic.
1. __ctfe doesn't seem to be set
2. performing similar checks with the ones in dinterpret which
throw the error [3] don't distinguish this situation
3. checking the scope for ctfe doesn't work either: sc.flags &
SCOPEctfe
Is there a way to achieve this? Maybe I am looking at this
problem from a wrong angle.
Thank you,
Lucia
[0]https://github.com/dlang/druntime/blob/2db828bd4f21807254b770b3ec304f14596a9805/src/rt/arraycat.d#L22
[1] https://github.com/dlang/dmd/blob/master/src/e2ir.d#L2702
[2]
https://github.com/dlang/dmd/blob/master/src/expression.d#L13545
[3]
https://github.com/dlang/dmd/blob/master/src/dinterpret.d#L2381
More information about the Dlang-internal
mailing list