What does 'inline' mean?

Manu turkeyman at gmail.com
Mon Jun 8 14:09:04 UTC 2020


On Mon, Jun 8, 2020 at 8:20 PM Walter Bright via Digitalmars-d <
digitalmars-d at puremagic.com> wrote:

> On 6/7/2020 11:14 PM, Manu wrote:
> > I think a first part of the conversation to understand, is that since D
> doesn't
> > really have first-class `inline` (just a pragma, assumed to be low-level
> > compiler control), I think most people bring their conceptual definition
> over
> > from C/C++, and that definition is a little odd (although it is
> immensely
> > useful), but it's not like what D does.
>
> 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.

> In C/C++, inline says that a function will be emit to the binary only
> when it is
> > called, and the function is marked with internal linkage (it is not
> visible to
> > the linker from the symbol table)
> > By this definition; what inline REALLY means is that the function is not
> placed
> > in the binary where it is defined, it is placed in the binary where it
> is
> > CALLED, and each CU that calls an inline function receives their own
> copy of the
> > function.
>
> Why does it matter where it is emitted? Why would you want multiple copies
> of
> the same function in the binary?
>

I want zero copies if it's never called. That's very important.
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.

> Another take on inline, and perhaps a more natural take (if your mind is
> not
> > poisoned by other native languages), is that the function is not
> actually emit
> > to an object anywhere, it is rather wired directly inline into the AST
> instead
> > of 'called'. Essentially a form of AST macro.
>
> The problem with this is what is inlined and what isn't is rather fluid,
> i.e. it
> varies depending on circumstances and which compiler you use. For example,
> if
> you recursively call a function, it's going to have to give up on inlining
> it.
> Changes in the compiler can expand or contract inlining opportunities.
> Having it
> inline or issue an error is disaster for compiling existing code without
> constantly breaking it.
>

I understand why this particular take is more complicated; and as such I
wouldn't suggest we do it. I'm just offering it as one possible take on the
concept.
I think to make this form work, it must be handled in the frontend;
essentially an AST macro. Naturally, it would fail on recursive calls,
because that would be a recursive expansion.
I'm not suggesting we do this, except maybe what I describe as the #3 use
case could potentially be this.

> I reach for inline in C/C++ for various different reasons at different
> times,
> > and I'd like it if we were able to express each of them:
> >
> > 1. I only want the function to be present in the CALLING binary. I do
> not want
> > an inline function present in the local binary where it was defined
> (unless it
> > was called internally). I do not want a linker to see the inline
> function
> > symbols and be able to link to them externally. [This is about linkage
> and
> > controlling the binary or distribution environment]
>
> Why? What is the problem with the emission of one copy where it was
> defined?
>

That's the antithesis of inline. If I wanted that, I wouldn't mark it
inline.
I don't want a binary full of code that shouldn't be there. It's very
important to be able to control what code is in your binaries.

If it's not referenced, it doesn't exist.

> 2. I am unhappy that the optimiser chose to not inline a function call,
> and I
> > want to override that judgement. [This is about micro-optimisation]
>
> It's not always possible to inline a function.
>

Sure, but in this #2 case, I know it's possible, but the compiler chose not
to. This #2 case is the 'hint' form.

> 3. I want to treat the function like an AST macro; I want the function
> inserted
> > at the callsite, and I want to have total confidence in this mechanic.
> [This is
> > about articulate mechanical control over code-gen; ie, I know necessary
> facts
> > about the execution context/callstack that I expect to maintain]
>
> The PR I have on this makes it an informational warning. You can choose to
> be
> notified if inlining fails.
>

That's not sufficient though for all use cases. This is a different kind of
inline (I think it's 'force inline').
This #3 mechanic is rare, and #1/2 are overwhelmingly common. You don't
want a sea of warnings to apply to cases of 1/2.
I think it's important to be able to distinguish #3 from the other 2 cases.

> Are there non-theoretical use cases I've missed that people have
> encountered?
>
> At its root, inlining is an optimization, like deciding which variables go
> into
> registers.
>

No, actually... it's not. It's not an 'optimisation' in any case except
maaaaybe #2; it's about control of the binary output and code generation.
Low level control of code generation is important in native languages;
that's why we're here.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20200609/86542572/attachment.htm>


More information about the Digitalmars-d mailing list