[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