https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94474

--- Comment #12 from Andrew Burgess <andrew.burgess at embecosm dot com> ---
> But what I learned from writing the patch is that gcc cannot
> easily tell if a range will be empty or not.  That is because
> the assembler does emit the line info and the views,
> and the assembler decides how many bytes if any a certain
> construct will take in the binary representation.
>
> That is why this empty range appears, because that was
> supposed to be the start of the inline function, but
> instructions from the function prologue were moved in there.

I think there's some miss-communication here.  In the first paragraph
you say the assembler is responsible for deciding the binary
representation.  I'd agree with that, in the GNU toolchain this is
gas.

Then in the second paragraph you say the assembler is performing
instruction reordering.  Now I don't know every gas optimisation, so
I'm not saying gas doesn't do that, but it's not common, and it
certainly isn't what's happening in this case.  The instruction motion
is entirely within GCC.  I'll offer evidence for this below.

> What causes the problem is the is-stmt line info which
> is the only remaining thing from the original plan.

And here in lies the GCC bug (or one of them).  GCC has performed
instruction motion, and GCC has left behind its marker for the is-stmt
line.

I make no claim about how easy this is to fix, or if (given GCC's code
base) its even reasonably possible to consider fixing it, but that
doesn't mean it isn't a GCC issue.

> But on the other hand, it is not a big issue for gdb to
> ignore those artefacts, when they rarely occur.

GDB already ignores empty ranges.  The DWARF standard specifically
allows empty ranges and states that they are to be ignored.

But that isn't the artefact you're talking about, you mean the is-stmt
markers.

The problem is, the markers are placed at an address, given that every
address eventually contains an instruction[1] eventually, how can GDB
tell if one marker was left by accident or not?

> My gdb-patch does this, by changing the is-stmt bit of
> this line info.

Yes, and I think with this discussion we are getting closer to
understanding the work around you want to introduce to GDB, something
along the lines of:

  - On versions XXX -> YYY of GCC,
  - An is-stmt true marker,
  - At the same address as an empty range, that is
  - Associated with an inline function instance, should
  - Be ignored.

It's this kind of specific identification of the bug you're working
around that (for me at least) is holding back your GDB patch.

But, we shouldn't make a choice between work around the GCC bug in GDB
_or_ fix the bug in GCC.  The ideal solution (for me) would be, fix GCC
_and_ add a work around into GDB targeting the known broken versions
of GCC, then we get the best of both worlds.

---

To back up my claim that this is a GCC issue, you can generate the
assembler file test-v3.s from the reproducer.  The .debug_ranges looks
like this:

         .section        .debug_ranges,"",@progbits
  .Ldebug_ranges0:
          .quad   .LFB21
          .quad   .LHOTE0
          .quad   .LFSB21
          .quad   .LCOLDE0
          .quad   0
          .quad   0
          .quad   .LBB8
          .quad   .LBE8
          .quad   .LBB12
          .quad   .LBE12
          .quad   .LBB17
          .quad   .LBE17
          .quad   0
          .quad   0

The empty range is the first range in the second sequence, so this
one:

          .quad   .LBB8
          .quad   .LBE8

If we then find this in the assembler we see:

  .LBB8:
  .LBI8:
          .file 2 "step-and-next-inline.h"
          .loc 2 32 1 is_stmt 1 view .LVU3
  .LBB9:
          .loc 2 34 3 view .LVU4
  .LBE9:
  .LBE8:
          .loc 1 50 1 is_stmt 0 view .LVU5
          subq    $8, %rsp
          .cfi_def_cfa_offset 16

Notice, no assembler instructions (but there are assembler directives)
between LBB8 and LBE8.

I agree 100% with your diagnosis that this is likely due to
instruction reordering, but I disagree with your analysis that this is
done in the assembler and that therefore GCC has no visibility of
this.

---

[1] I know, not _literally_ every address, but you get the point.

Reply via email to