2

I'm writing code in a C-like language, and am using an inline function which does actually tend to get inlined. However, the inlining maintains the location in that function's source, in terms of the debugging info added by the compiler (e.g. DWARF added by GCC).

Is it possible to get the compiler to inline the function's code while attributing the instructions to the line at which the function was inlined?

For the sake of discussion, let's assume I'm writing C++ and compiling with GCC on Linux (although a more general answer is appreciated.)

(The motivation has to do with profiling where you only sample the function you're in but don't sample the entire stack.)

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • I believe that's generally hardly possible due to optimizations and the as-if rule. Consider the following example: https://godbolt.org/z/Ee9T1r. All the code was reduced to a single instruction (`mov eax, 3`). How would you determine to which part of the code this instruction belongs? – Daniel Langr Dec 30 '20 at 13:44
  • @DanielLangr: We're talking about changes to debugging information only; it's the same optimizations and the same semantics. In your example, I expect to the code to be associated with line 9. However - that is not a very interesting example. If `add()` in your example issue some system call or something else which does actually get executed, then what I'm asking for is to get line 9 instead of line 3 for that system call. – einpoklum Dec 30 '20 at 14:00
  • I think this is the opposite of what most people try to achieve with debug info, so I doubt you can request it. Maybe you could template the method with a tag of the unnamed namespace, so you get a separate function per compilation unit? – JVApen Dec 30 '20 at 15:14
  • The debug info contains the information if an instruction is an inline function, and where it was inlined. Isn't that what you want? – ssbssa Dec 31 '20 at 14:48
  • @ssbssa: Not exactly. I want the debug information for an instruction to indicate the location it was inlined at, rather than the location in the inlined function's code which resulted in the instruction. – einpoklum Dec 31 '20 at 15:03
  • Yes, as I said, the debug info contains the information where a function was inlined. – ssbssa Dec 31 '20 at 15:08
  • @ssbssa: 1. Perhaps; can you link to an illustration/explanation of this? 2. When some/most profilers show you where you were in the code at various points in time, they won't use that information. They'll just note you were within the inlined function. – einpoklum Dec 31 '20 at 16:43
  • E.g. `addr2line -i` shows inlined function + where it was inlined. And I would expect that at least the modern profilers use this info as well. – ssbssa Dec 31 '20 at 18:19
  • @ssbssa: Can you make your comments into an answer? I might not like it, but I guess it should be one,. – einpoklum Dec 31 '20 at 20:58

1 Answers1

0

The artificial function attribute does this:

artificial

This attribute is useful for small inline wrappers that if possible should appear during debugging as a unit. Depending on the debug info format it either means marking the function as artificial or using the caller location for all instructions within the inlined body.

Placement of the __attribute__ directive is a bit tricky. This is the recommended place:

inline void __attribute__ ((artificial))
increment (int &i)
{
  ++i;
}

This is different from the place in the C++ syntax:

[[gnu::artificial]]
inline void
increment (int &i)
{
  ++i;
}

The artificial attribute is recognized by Clang and compilers derived from it.

Florian Weimer
  • 32,022
  • 3
  • 48
  • 92
  • But does this really do what I need it to? See [this GodBolt example](https://godbolt.org/z/Wj7zMv) - it seems the addition is associated with the inner, not the outer, function. – einpoklum Dec 31 '20 at 12:41
  • How did you check this? – Florian Weimer Dec 31 '20 at 16:20
  • Follow the link. You'll see the color-coding of the `add` instruction is associated with the single line of the inlined `add()` function - not with the line where it was invoked. – einpoklum Dec 31 '20 at 16:31
  • Looks like Godbolt doesn't process `DW_AT_artificial` in this scenario (which is perhaps reasonable). You can work around that using `-gstabs`, but that's not going to work well for C++ debugging in general. – Florian Weimer Dec 31 '20 at 17:53
  • I don't see such a directive/tag when I compile the source of that program to assembly; or when I remove all of the GodBolt filters. Are you sure it's in there? ... Interestingly, if I compile with `-gstabs` there, everything works fine and the `artificial` is respected. – einpoklum Dec 31 '20 at 23:15