December 07, 2017
On Thursday, 7 December 2017 at 01:21:11 UTC, Nicholas Wilson wrote:
> I'd like to add an attribute to indicate that the annotated function is only available at compile time so that in cases where the operation is invalid at runtime (strings and concatenation on a GPU for instance) but the result is only used at compile time (for a mixin) the compiler is free to not codegen that function.
>
> I can add this to LDC pretty easily, but does anyone else have a use for this (e.g. shrinking binary sizes for mixin heavy codebases) and would benefit having this as a standard thing?

I once tried to use dmd's -vgc option but it is not so useful when all CTFE funtions to generate D code trigger warnings about GC alcoations.

I think such an attribute would silence this warnings, dmd -vgc would be much cleaner then.
December 07, 2017
On Thursday, 7 December 2017 at 09:34:51 UTC, Walter Bright wrote:
> On 12/6/2017 5:21 PM, Nicholas Wilson wrote:
>> I'd like to add an attribute to indicate that the annotated function is only available at compile time so that in cases where the operation is invalid at runtime (strings and concatenation on a GPU for instance) but the result is only used at compile time (for a mixin) the compiler is free to not codegen that function.
>
> Put these functions into a separate import. Then import the file and use the functions at compile time. They will not have code generated for them.

Doesn't work for templates.
December 07, 2017
On 7 December 2017 at 01:34, Walter Bright via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> On 12/6/2017 5:21 PM, Nicholas Wilson wrote:
>
>> I'd like to add an attribute to indicate that the annotated function is only available at compile time so that in cases where the operation is invalid at runtime (strings and concatenation on a GPU for instance) but the result is only used at compile time (for a mixin) the compiler is free to not codegen that function.
>>
>
> Put these functions into a separate import. Then import the file and use the functions at compile time. They will not have code generated for them.
>

Misuse of the API; ie, a runtime call, will result in an unsuspecting user getting a surprising link error, rather than a nice compile-time error explaining what they did wrong...


December 07, 2017
On 12/7/2017 2:07 AM, Nicholas Wilson wrote:
> Doesn't work for templates.

I don't know how your code is organized, but if the template is instantiated in another file, it won't have code generated for it either.

December 07, 2017
On 12/7/2017 11:41 AM, Manu wrote:
> Misuse of the API; ie, a runtime call, will result in an unsuspecting user getting a surprising link error, rather than a nice compile-time error explaining what they did wrong...

I think Nicholas is talking about functions for which code cannot be generated.

In any case, in C/C++/D if you call functions in .h files (or imports) that are not linked in, you'll get a linker error.
December 07, 2017
On 12/6/2017 11:41 PM, Mike Franklin wrote:
> On Thursday, 7 December 2017 at 04:45:15 UTC, Jonathan M Davis wrote:
> 
>> The simplest way to do that is to write a unit test that uses a static assertion. As I understand it, with the way CTFE works, it pretty much can't know whether a function can be called at compile time until it tries, but a unit test can catch it if the function no longer works at compile time.
> 
> Not bad, but that is swaying into the cumbersome category.  If that's the best we can do, a @ctfeonly attribute starts looking pretty good.

More and more attributes to do essentially trivial things is cumbersomeness all on its own.
December 07, 2017
Am Thu, 7 Dec 2017 05:55:54 +0200
schrieb ketmar <ketmar@ketmar.no-ip.org>:

> ketmar wrote:
> 
> > Nicholas Wilson wrote:
> > 
> >> Also not generating the code in the first place means less I/O for the compiler and less work for the linker.
> > this is solvable without any additional flags, tho: compiler should just skip codegen phase for any function that is not referenced by another compiled function (except for library case).
> 
> p.s.: actually, dmd already creates .a files suitable for smartlinking (otherwise any binary would include the whole libphobos2.a ;-). but for "dmd mycode.d" dmd doesn't do this ('cause it is quite compilcated for non-library case). the whole issue prolly can be solved by "generate smart object files for linking" flag (which will create .a files for everything, so linker can do it's smart work).

AFAIK there's a design flaw in D which prevents a compiler from doing any such operations without additional user input:

Currently you can write code like this:
-------------------------------------------------------------------
module mod;

private int thisIsNeverUsed()
{
    return 42;
}

private int thisIsUsed(int a)
{
    return 42 + a;
}

int someTemplate(T)(T t)
{
    return t.thisIsUsed();
}
-------------------------------------------------------------------

Whether thisIsUsed and thisIsNeverUsed actually have to appear in the object file depends on how someTemplate is instantiated. Generally, when compiling module mod you can never know whether thisIsUsed or thisIsNeverUsed are actually required. You can not evaluate the someTemplate template without specifying a concrete type for T.

This means neither the compiler nor the linker can remove seemingly unused, private functions. For GDC this means we simply mark all functions as TREE_PUBLIC in the GCC backend.

Note that this is also an issue for exporting templates from DLLs on windows. I think the DLL DIP which requires to mark private functions as 'export' if they are used outside outside of the module (even via templates) will fix this problem and allow for some nice optimizations. Until then, smart linking isn't really possible.

BTW: The private/export combination probably still wouldn't solve all problems: Maybe you want to mark the whole module as @nogc. @nogc checking is done in semantic phase, so it will still error about GC usage in functions which later turn out to be only used in CTFE. Detecting this in the linker or compiler backend is too late. So we'd have to detect unexported, unused private functions in semantic. I'm not sure if this is feasible or whether a simple @ctfeonly UDA isn't much simpler to implement.

Additionally @ctfeonly documents intended usage and allows for nice error messages when using a function at runtime. Relying on the linker to remove private, unexported functions can break easily.

-- Johannes

December 07, 2017
Am Wed, 06 Dec 2017 20:18:57 -0700
schrieb Jonathan M Davis <newsgroup.d@jmdavisprog.com>:

> Folks have talked about all kinds of template code and stuff being kept around in binaries even though it was only used at compile time (e.g. stuff like isInputRange), but I don't know how much that's actually true.

You probably never call isInputRange at runtime, so the code is likely stripped. However, TypeInfo of structs used only at CTFE is still generated and not stripped. I remember we once had this problem with gcc.attribute, a module which shouldn't generate any code but generated useless TypeInfo.

-- Johannes

December 07, 2017
Am Thu, 07 Dec 2017 01:32:35 -0700
schrieb Jonathan M Davis <newsgroup.d@jmdavisprog.com>:

> 
> In the vast majority of cases, when a function is used for CTFE, it's also used during runtime. So, in most cases, you want to ensure that a function works both with CTFE and without, and in those cases something like @ctfeonly wouldn't make any sense. In my experience, pretty much the only time that something like @ctfeonly would make any sense would be with a function for generating a string mixin.

Not only string mixins. When programming for microcontrollers you want
to do as much in CTFE as possible, as space for executable code is
severely limited. So you may for example want to use CTFE to generate
some lookup tables and similar stuff. Basically the whole
'initialize a variable / constant using CTFE' idiom benefits a lot from
such an attribute.

-- Johannes

December 07, 2017
Am Thu, 7 Dec 2017 13:38:54 -0800
schrieb Walter Bright <newshound2@digitalmars.com>:

> On 12/6/2017 11:41 PM, Mike Franklin wrote:
> > On Thursday, 7 December 2017 at 04:45:15 UTC, Jonathan M Davis wrote:
> >> The simplest way to do that is to write a unit test that uses a static assertion. As I understand it, with the way CTFE works, it pretty much can't know whether a function can be called at compile time until it tries, but a unit test can catch it if the function no longer works at compile time.
> > 
> > Not bad, but that is swaying into the cumbersome category.  If that's the best we can do, a @ctfeonly attribute starts looking pretty good.
> 
> More and more attributes to do essentially trivial things is cumbersomeness all on its own.

I think this is more of an optimization UDA than a standard attribute. So it's similar to all the noinline, forceinline, weak, section etc. attributes: https://wiki.dlang.org/Using_GDC#Attributes

-- Johannes