Bug 19570 – pragma(inline) is emitting symbols

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2019-01-10T09:24:34Z
Last change time
2024-12-13T19:01:53Z
Assigned to
No Owner
Creator
Manu
Moved to GitHub: dmd#19524 →

Comments

Comment #0 by turkeyman — 2019-01-10T09:24:34Z
pragma(inline) doesn't seem to work right. pragma(inline, true) int foo() { return 10; } Don't make any call to this function, just put it alone in a source file and note that it is still emit to the object file (on linux at least). I understand the compiler may not guarantee that the function was inlined, and it *may* emit a symbol to the object file _when it's called_, but the basic semantic promise of the inline request doesn't seem to work; it should certainly NOT emit a symbol to the object file in cases where the function is never called (and try to inline when it is). There should only be a symbol in the object file in the case it failed to inline, and only if it's actually called. inline functions are useful for things like CTFE, where you want to use a function at compile time, and may _or may not_ use it at runtime, and do not want to eagerly emit it to the binary.
Comment #1 by iamthewilsonator — 2019-01-11T03:26:55Z
Comment #2 by bugzilla — 2019-01-11T04:17:52Z
Why is this marked as critical? Besides, the reason it is emitted to the object file is in the case someone in another module takes the address of it. Also, the linker is supposed to elide unreferenced COMDATs, so it should go away. This needs a better rationale for why it is a bug, let alone critical.
Comment #3 by turkeyman — 2019-01-11T07:02:53Z
I'm not sure why it's critical, I don't recall doing that... Perhaps it was an accident. I created another bug critical yesterday, but that was bad codegen, failing to do the ABI proper. > Besides, the reason it is emitted to the object file is in the case someone in another module takes the address of it. From another module being emit to the same object file, or another module compiled into a separate object file? I would expect taking the address would cause the code to be emit locally to the module that's taking the address, rather than externing to a copy in the module it's declared. > Also, the linker is supposed to elide unreferenced COMDATs, so it should go away. It doesn't. That's motivating this issue. But also I'm upset that it was there in the first place. That's distinctly *not* honouring my "inline" request. > This needs a better rationale for why it is a bug, let alone critical. I mean, I don't feel like I should be presenting an argument here... an explicit inline feature that doesn't do what's written on the tin seems like a bug. I think the rationale needs to support why it wouldn't behave the way you'd expect. Suggesting that we have to emit the function because a 3rd party should be able to link to it is weird, because that's totally self-defeating. Why is it inline then? I expect that if I've explicitly marked it inline, then I can not extern to it, that would be the whole point. Code that calls an inline function should either inline it as preferred, or if it decides not to for some reason, emit the code locally into the referencing module (and perhaps even don't emit a symbol name for the not-inline code).
Comment #4 by turkeyman — 2019-01-11T07:05:00Z
I recall having a big discussion about this when you added it... and I felt like we agreed on this and the semantics were very clear. You were even in favour at the time of requiring a compile error if inline failed, but I think I resisted on a hard error, because other compilers weren't necessarily able to respect that request.
Comment #5 by turkeyman — 2019-01-13T21:02:50Z
It is critical, inline literally does nothing at all, as shows in the comments section of the PR threads: https://github.com/dlang/dmd/pull/9235 Absolutely nothing about inline works, and I'm blocked on it.
Comment #6 by witold.baryluk+d — 2020-05-15T15:54:42Z
I think you are confusing function being marked inline, and about non-emiting object code of it or marking it weak. These are independent. Compiler is free to ignore all `pragma(inline, ...)` statements, at any optimization / flags settings. What you want are `private final` symbol, or way to mark it weak. That would be a better signal to compiler and linker. `pragma(inline, ...)` is used for other things. It even says so in the spec: https://dlang.org/spec/pragma.html#inline """ Implementation defined: 2. Whether a particular function can be inlined or not is implementation defined. 3. What happens for pragma(inline, true) if the function cannot be inlined. An error message is typical. """ DMD default to emitting an error and aborting compilation when -inline flag is used. IMHO that is meh solution, I would like warning and continue with compilation.
Comment #7 by turkeyman — 2020-06-06T01:01:47Z
There's a lot of noise at the start of this chain. Ignore everything else I've said, let me simplify: `inline` should: - emit a copy of the function to each CU it's called from - not emit the function to the CU it's declared (unless it's called, as above) - mark the function with 'internal' linkage (what C++ calls 'static') so it's not in the object's exported symbol table. - *optionally* apply a strong hint to encourage true inlining - this is nice, but it's secondary to the requirements above Practical features: - symbol is not externally linkable - symbols referenced by an inline function that's never called must NOT cause a link error under any circumstances
Comment #8 by bugzilla — 2020-06-06T06:15:20Z
(In reply to Manu from comment #7) > - emit a copy of the function to each CU it's called from But then it's going to be doing code gen for each of them over and over. > - not emit the function to the CU it's declared (unless it's called, as > above) > - mark the function with 'internal' linkage (what C++ calls 'static') so > it's not in the object's exported symbol table. So what if it's in the symbol table? > - symbol is not externally linkable Why not? > - symbols referenced by an inline function that's never called must NOT cause a link error under any circumstances This is a linker problem - the linker is supposed to remove unreferenced functions.
Comment #9 by turkeyman — 2020-06-08T02:06:25Z
(In reply to Walter Bright from comment #8) > (In reply to Manu from comment #7) > > - emit a copy of the function to each CU it's called from > > But then it's going to be doing code gen for each of them over and over. Sure. inline functions are usually very short. Also, most D applications only have one CU. > > - not emit the function to the CU it's declared (unless it's called, as > > above) > > - mark the function with 'internal' linkage (what C++ calls 'static') so > > it's not in the object's exported symbol table. > > So what if it's in the symbol table? Multiple modules with the same symbol will have link collisions. It could be weak, but then you're still inviting 3rd party code to link against it, which is at odds with it's inline-ness. > > - symbol is not externally linkable > > Why not? Because every CU may have its own internal copy. > > - symbols referenced by an inline function that's never called must NOT cause a link error under any circumstances > > This is a linker problem - the linker is supposed to remove unreferenced > functions. It would be extremely simpler for the problem not to exist at all, and more compatible with existing binary ecosystems without unexpected errors or edge cases.
Comment #10 by robert.schadek — 2024-12-13T19:01:53Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19524 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB