June 10, 2020
On Wed, Jun 10, 2020 at 7:30 AM Walter Bright via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> On 6/9/2020 4:30 AM, Stanislav Blinov wrote:
> > That is no reason for another [instance of the same] compiler not to
> have access
> > to symbol table,
>
> Since the linker has this information already, there's no reason to not do
> the
> job in the linker.
>

Redundant work, undesired object bloat, and various potential link issues/errors.


June 10, 2020
On Wed, Jun 10, 2020 at 9:30 AM Manu <turkeyman@gmail.com> wrote:

> On Wed, Jun 10, 2020 at 7:15 AM Walter Bright via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>
>> On 6/9/2020 4:31 AM, Atila Neves wrote:
>> > On Monday, 8 June 2020 at 23:19:55 UTC, Jonathan M Davis wrote:
>> >> On Monday, June 8, 2020 8:09:04 AM MDT Manu via Digitalmars-d wrote:
>> >>> On Mon, Jun 8, 2020 at 8:20 PM Walter Bright via Digitalmars-d <
>> >>> > C/C++ inline has always been a hint to the compiler, not a >
>> command.
>> >>>
>> >>> It's not a hint at all. It's a mechanical tool; it marks symbols with internal linkage, and it also doesn't emit them if it's never
>> referenced. The
>> >>> compiler may not choose to ignore that behaviour, it's absolutely
>> necessary,
>> >>> and very important.
>> >>
>> >> It is my understanding that in C++, inline is a hint to the compiler
>> with
>> >> regards to whether a particular function call is actually inlined.
>> >
>> > That's a common misconception, and one that exists due to that being
>> its
>> > original intended purpose. But nowawadays? Nope:
>> >
>> > https://en.cppreference.com/w/cpp/language/inline
>>
>>
>> "Since this meaning of the keyword inline is non-binding, compilers are
>> free to
>> use inline substitution for any function that's not marked inline, and
>> are free
>> to generate function calls to any function marked inline. Those
>> optimization
>> choices do not change the rules regarding multiple definitions and shared
>> statics listed above."
>>
>> I.e. it is a hint.
>>
>
> It's like you skipped over ALL OF THE OTHER TEXT, where it details numerous precise behavioural requirements :/
>

The the sentence that immediately follows your quote is:
"Because the meaning of the keyword inline for functions came to mean
"multiple definitions are permitted" rather than "inlining is preferred",
that meaning was extended to variables."


June 09, 2020
On 6/9/2020 7:21 AM, Manu wrote:
>     The C/C++ inline semantics revolve around the mechanics of .h files because it
>     doesn't have modules. These reasons are irrelevant for D.
> 
> 
> That's completely incorrect. It's 100% as relevant for D as it is for C++ for exactly the same reasons.
> You'll need to support your claim.

Um, because of the way #include works, C++ sees the same inline function definition over and over again, and has no way of knowing if any other files see the same definition or not, or if they have the same implementation or not. The semantics are carefully crafted around the reality that there may be multiple copies of the inline function definition in compilation units that have no clue of the existence of each other. The internal linkage thing is there to support more primitive linkers that have no support for COMDAT sections.

This is completely different from a module system. Also, D relies heavily on linker support for COMDATs.


> Because in this category of use case, inlining is a concept related to native languages with binary linkage, and not really anything to do with the language specifically.

Given all the verbiage about inlines in the C++ spec, it does have to do with the language specifically.


> Any other result is just 'weird', and while it might be workable, it's just asking for trouble. (1 redundant copy in the owning CU despite being un-referenced MIGHT be link-stripped if the surrounding tooling all works as we hope... but it also might not, as I have demonstrated on multiple occasions)
> There's just no reason to invite this problem... and no advantage.
> 
>      > I also want copies to appear locally when it is referenced; inline functions
>      > should NOT require that you link something to get the code... that's not
>     inline
>      > at all.
> 
>     Why? What problem are you solving?
> 
> 
> Literally inline function calling. No-link libs are a really common and extremely useful thing.

At last! You say why! We have that in D with template functions. You get N instantiations. But they all have COMDAT linkage, which means only 1 winds up in the executable instead of N.


>     I know I'm being boring, but why is it important? Also, check out -gc-sections:
> 
>     https://gcc.gnu.org/onlinedocs/gnat_ugn/Compilation-options.html
> 
>     Which is a general solution, not a kludge.
> 
> 
> I guess my key issue is that I have complained before because I have experienced multiple counts of the link stripping not working like you say. There is no reason to invite that problem; we can trivially eliminate the problem at the source. I don't care if it's fixable, I don't want the problem to exist. NOBODY wants to be tasked to solve awkward build ecosystem issues... we already have a working build ecosystem, and this D thing is making it harder than it already is. That's a really bad thing, and I would entertain excuses for this if not for the fact that it's trivially avoidable. We do not need to waste anybodies time this way; we won't win any friends by wasting their time with problems they HATE to have.

If gc-sections isn't working, perhaps there's something else going on. Did you check with the linker support people? gc-sections has been around at least 20 years with gcc. If it fundamentally didn't work somebody would have fixed it by now.

It also may not work with your C++ compiler because it is NOT emitting the functions each into its own section. DMD *does* put each and every function into its own section, so that gc-sections will work.

I.e. C++ has workarounds for bugs it its own implementation, and those workarounds are not features.


> The secondary issue is, I want my binaries to contain what I put in there, and not what I don't. Rogue symbols that I specified shouldn't exist only bloat the binary, invite possibility of link collision, and raise the probability of the issues I mentioned above.

But you're happy with (and require) N useless redundant copies of inline functions.


> I suggest, the default should model the common case, and the rare niche case can be the 3rd 'force' state by explicit request.

The upcoming case is pragma(inline,true) (in my PR) is that the compiler attempts to inline them regardless of the -inline switch, and lists an informational warning (-wi) if they can't be inlined.


> This isn't about optimisation, it's about controlling the output of the compiler. Taking that control away and forcing us to try and reproduce that expected functionality with external tooling within a deeply complex build ecosystem is wasting our valuable time.

C++'s inline semantics are rooted in accommodation for:

1. .h files rather than modules
2. object file formats that don't support COMDATs
3. linkers that don't support COMDATs

It's a collection of hacks, not features. D is free'd from those constraints.
June 09, 2020
On 6/9/2020 2:54 PM, Stanislav Blinov wrote:
> So, "linkers have to do it because linkers have to do it". Let's just stick to outdated tech forever.

I have seriously considered building the linker into DMD, but don't have the resources to do it. If you want to do it, feel free to.
June 09, 2020
On Tue, Jun 09, 2020 at 04:48:17PM -0700, Walter Bright via Digitalmars-d wrote:
> On 6/9/2020 7:21 AM, Manu wrote:
[...]
> > >   Why? What problem are you solving?
> > 
> > 
> > Literally inline function calling. No-link libs are a really common and extremely useful thing.
> 
> At last! You say why! We have that in D with template functions. You get N instantiations. But they all have COMDAT linkage, which means only 1 winds up in the executable instead of N.
[...]

Yeah, I was about to say, judging from what Manu has written several times in this thread, his concept of 'inline' bears striking resemblance to a template function:

- The template function is not instantiated in its defining module
  (unless something else instantiates it there);

- A template function is instantiated in the invoking module, just like
  how Manu described his 'inline' functions;

- A template function is more likely to be actually inlined (recently
  I've been adding () to some of my functions in order to prod the
  compiler to inline them).  Manu has even stated that whether or not
  the 'inline' function is actually inlined isn't even that important
  anymore; given that, I'd say template functions are what he's looking
  for all this time!


T

-- 
Why ask rhetorical questions? -- JC
June 10, 2020
On Wednesday, 10 June 2020 at 00:02:09 UTC, H. S. Teoh wrote:
> On Tue, Jun 09, 2020 at 04:48:17PM -0700, Walter Bright via Digitalmars-d wrote:
>> [...]
> [...]
>> [...]
> [...]
>
> Yeah, I was about to say, judging from what Manu has written several times in this thread, his concept of 'inline' bears striking resemblance to a template function:
>
> [...]

Yes making the function a function template will do that.
And Manu is fully aware of it.

It's a nasty hack.
And in certain cases it screws with overload-resolution.
June 09, 2020
On 6/9/2020 4:30 PM, Manu wrote:
> It's like you skipped over ALL OF THE OTHER TEXT, where it details numerous precise behavioural requirements :/

As I replied elsewhere to you, those other requirements are there to deal with .h files, obsolete linkers, and ancient object file formats.

> "Because the meaning of the keyword inline for functions came to mean "multiple definitions are permitted" rather than "inlining is preferred", that meaning was extended to variables."

It's a hack for the the same problem - .h files, etc. There's no reason for that in D.
June 09, 2020
On 6/9/2020 4:31 PM, Manu wrote:
> Redundant work,

It isn't redundant work to do it in the linker. It is redundant to do half of the linker's job in the compiler, throw away the other half of it, and re-do it in the linker.

> undesired object bloat,

Not a problem since we moved on from floppy disks.

> and various potential link issues/errors.

I suppose that fits in with the common notion that the linker is black magic full of trolls and dragons. It isn't, it's a boringly simple program. Although it is true that probably only 1 in 100 programmers can explain what a linker does.

(Most of the complexity of linkers is not inherent, it is the result of file formats designed by hamsters and workarounds for compiler and loader bugs. You have to pity the linker developer - there's no glamor, nobody understands what they do, nobody praises them, they just dump on them with "what does 'undefined symbol mean' - must be a bug in the linker" questions.)
June 10, 2020
On 6/8/2020 3:19 AM, Walter Bright wrote:
> The PR I have on this makes it an informational warning. You can choose to be notified if inlining fails.

https://github.com/dlang/dmd/pull/11236
June 10, 2020
On 6/9/20 8:20 PM, Stefan Koch wrote:
> On Wednesday, 10 June 2020 at 00:02:09 UTC, H. S. Teoh wrote:
>> On Tue, Jun 09, 2020 at 04:48:17PM -0700, Walter Bright via Digitalmars-d wrote:
>>> [...]
>> [...]
>>> [...]
>> [...]
>>
>> Yeah, I was about to say, judging from what Manu has written several times in this thread, his concept of 'inline' bears striking resemblance to a template function:
>>
>> [...]
> 
> Yes making the function a function template will do that.
> And Manu is fully aware of it.
> 
> It's a nasty hack.
> And in certain cases it screws with overload-resolution.

It's not exactly the same. If the compiler thinks an imported module has instantiated it, it will not include it in the object file (unless you use -allinst).

-Steve