debug stoppoints and control flow

Hi, I'm just getting back to working on the cfe debug info after a brief hiatus.

It appears that the appropriate place to be inserting stoppoints is
starting in llvm_expand_stmt, using STMT_LINENO(t) . If that's not the
best place, comments would be appreciated.

Using the debug_hooks seems to be a non-starter, because they're
called during rtl generation, which apparently isn't done when
EMIT_LLVM is set.

A more pressing question is how to chain the debug intrinsics together
around control flow.
The current examples of debug info have no control flow except for
calls. I started with a simplistic version that chained them in file
order:

%1 = stoppoint(%0)
...
%2 = stoppoint(%1)
etc..

However, doing this obviously won't work with control flow, since an
instruction generated for one side of a branch may get linked to one
on the other side, resulting in instructions that don't dominate their
uses.

I wanted to ask if there was already a good explanation of what to do
somewhere (or off the top of someone's head) before I came up with one
on my own.

Thanks,
-mike

Hi, I'm just getting back to working on the cfe debug info after a brief hiatus.

Great!

It appears that the appropriate place to be inserting stoppoints is
starting in llvm_expand_stmt, using STMT_LINENO(t) . If that's not the
best place, comments would be appreciated.

I think that makes sense, along with EXPR_WITH_FILE_LOCATION. You might
also want to only emit a line number if the previously emitted line number
is not the same as the current one. This would allow us to only emit one
for:

   --x; ++y;

Using the debug_hooks seems to be a non-starter, because they're
called during rtl generation, which apparently isn't done when
EMIT_LLVM is set.

Correct.

A more pressing question is how to chain the debug intrinsics together
around control flow.
The current examples of debug info have no control flow except for
calls. I started with a simplistic version that chained them in file
order:

%1 = stoppoint(%0)
...
%2 = stoppoint(%1)
etc..

However, doing this obviously won't work with control flow, since an
instruction generated for one side of a branch may get linked to one
on the other side, resulting in instructions that don't dominate their
uses.

Yes. This is equivalent to fully constructing SSA, which you don't want
to do. :slight_smile:

I wanted to ask if there was already a good explanation of what to do
somewhere (or off the top of someone's head) before I came up with one
on my own.

Basically you need to use the 'alloca trick'. Basically, memory in LLVM
is not in SSA form, so do something like this:

   %dbg = alloca {}* ;; In the entry block.

   %tmp = call {}* %llvm.db.func.start(...)
   store {}* %tmp, {}** %dbg

   ...
   %tmp.1 = load {}** %dbg
   %tmp.2 = call {}* %llvm.dbg.stoppoint({}* %tmp.1, ...
   store {}* %tmp.2, {}** %dbg

When the -mem2reg pass is run, it will promote this to SSA form.

-Chris