April 06, 2020
On Monday, 6 April 2020 at 13:49:19 UTC, Atila Neves wrote:
> On Monday, 6 April 2020 at 13:41:52 UTC, Stefan Koch wrote:
>> On Monday, 6 April 2020 at 10:14:24 UTC, Atila Neves wrote:
>>> On Sunday, 5 April 2020 at 12:11:23 UTC, Stefan Koch wrote:
>>>> [...]
>>>
>>> Wouldn't it be easier to skip codegen for private functions that are never called from non CTFE contexts?
>>
>> Easier from the user-perspective yes.
>> From the compiler perspective,
>> That's another step which may take quite a while to do correctly.
>> The easy thing would be (Essentially an (N*M) loop over all calls and functions),
>
> Where N and M are all calls and private functions in one module, not all code in a project.
>
>> For now assert(__ctfe); enables people to manually mark their ctfe-only, functions.
>
> What about `in(__ctfe)` instead?

in (__ctfe) is already supported.
April 06, 2020
On Monday, 6 April 2020 at 13:49:19 UTC, Atila Neves wrote:
> On Monday, 6 April 2020 at 13:41:52 UTC, Stefan Koch wrote:
>> For now assert(__ctfe); enables people to manually mark their ctfe-only, functions.
>
> What about `in(__ctfe)` instead?
It was already explained, this will expand to the same code, so yes, both will work.

April 06, 2020
On Monday, 6 April 2020 at 14:14:48 UTC, Dominikus Dittes Scherkl wrote:
> On Monday, 6 April 2020 at 13:49:19 UTC, Atila Neves wrote:
>> On Monday, 6 April 2020 at 13:41:52 UTC, Stefan Koch wrote:
>>> For now assert(__ctfe); enables people to manually mark their ctfe-only, functions.
>>
>> What about `in(__ctfe)` instead?
> It was already explained, this will expand to the same code, so yes, both will work.

Well technically I had to do a bit of work for InContracts ("Requires" in dmd lingo), because for them you need to unwrap the scopeStatements.
April 06, 2020
On 4/5/2020 5:13 AM, Stefan Koch wrote:
> (just in case you're getting trigger happy Walter. )

I'll try not to shoot myself in the foot.
April 06, 2020
On 4/6/2020 3:14 AM, Atila Neves wrote:
> Wouldn't it be easier to skip codegen for private functions that are never called from non CTFE contexts?

There's no reason the CTFE-only function can't be global.
April 06, 2020
Sounds ok to me, as long as the assert(__ctfe) is the first statement in the function body.

Though I would check the linker map file to see if the linker didn't already omit functions that were never called.
April 07, 2020
On Tuesday, 7 April 2020 at 06:55:59 UTC, Walter Bright wrote:
> Sounds ok to me, as long as the assert(__ctfe) is the first statement in the function body.
>
> Though I would check the linker map file to see if the linker didn't already omit functions that were never called.

In order to support contracts we need to go through all the statements in the merged contract .... but I can split that out.
April 07, 2020
On Tuesday, 7 April 2020 at 06:53:18 UTC, Walter Bright wrote:
> On 4/6/2020 3:14 AM, Atila Neves wrote:
>> Wouldn't it be easier to skip codegen for private functions that are never called from non CTFE contexts?
>
> There's no reason the CTFE-only function can't be global.

No, there isn't. But in my experience nearly all functions I write that are only ever called from CTFE returning a string to be mixed in are private.
April 07, 2020
On Tuesday, 7 April 2020 at 06:55:59 UTC, Walter Bright wrote:
> Sounds ok to me, as long as the assert(__ctfe) is the first statement in the function body.
>
> Though I would check the linker map file to see if the linker didn't already omit functions that were never called.

I think the problem with relying on the linker is that the user still pays with longer compile times for codegen that isn't needed.
April 07, 2020
Am Mon, 06 Apr 2020 23:55:59 -0700 schrieb Walter Bright:

> Sounds ok to me, as long as the assert(__ctfe) is the first statement in
> the function body.
> 
> Though I would check the linker map file to see if the linker didn't already omit functions that were never called.


Very nice work, Stefan!

This has multiple benefits which have not been mentioned yet:

Yes, the linker might eliminate such functions. In some cases it can't do that though, most importantly when building shared libraries. So you may end up with useless mixin helpers in shared libraries. Now when we ever get a proper export implementation, the linker might be able to remove these as well.


As mentioned earlier, no doing codegen might reduce compile times. I guess this can be more important for GDC and LDC than for DMD, as we spent quite some time in backend optimizer phases. I remember Mike doing template heavy embedded stuff which lead to compile times of minutes for a hello world with gdc. And IIRC the main issue was the optimizer working on hundreds of unused template instances.


And the most important thing: This will vastly improve betterC / nogc code:

--------------------
string generateMixin(T)(string b)
{
    assert(__ctfe);
    return T.stringof ~ " " ~ b ~ ";";
}

void main() @nogc
{
    mixin(generateMixin!string("b"));
}
--------------------


Here emitting generateMixin means that at least some of the array appending infrastructure needs to be there. If we don't emit the function at all, we can probably get rid of all related issues.


However, to also enable these benefits for betterC and not only for @nogc, we have to disable the betterC semantic check for such CTFE-only functions:

test.d(4): Error: array concatenation of expression "string " ~ b ~ ";" requires the GC which is not available with -betterC

@Stefan can you add that to your PR?




Also a comment regarding @ctfe UDA vs assert(__ctfe): Although @ctfe adds clutter to function signatures, that actually has it's benefits. With @ctfe it would be trivial to check that @ctfe functions are only called from other @ctfe functions or a CTFE context instead of letting users run into linker errors. Also the information would be available early, I'm not sure if the check in semantic3 might be too late for some things (e.g. to disable betterC checks)?

This is especially a problem if you link to external libraries where you don't have source code: The .di and docs could only include the signature and the compiler and user just can't know that this is a ctfe-only function. OTOH it doesn't make sense to have only the signature of such a function, so you'd probably include the function body for CTFE in the .di file anyway. But this would still require the compiler to do an complete semantic on all imported modules, only to warn the user if he tried to use a @ctfe function in non-ctfe context.


So I guess all things considered I'd prefer @ctfe. But as long as whatever syntax is chosen works with -betterC, I'll be very happy either way :-)

-- 
Johannes