LLC crash while handling DEBUG info

Hi-

Here is the simple C++ function:

In theory the LLVM IR verifier (llvm/lib/IR/Verifier.cpp) should catch
this sort of thing. Maybe it isn't running in llc? It probably should
be. It's also likely not exhaustive to completely arbitrary changes to
the debug info IR - but could be improved if there are particular
things folks come across/want to sure it up against.

Hi David

If you look at line https://github.com/llvm/llvm-project/blob/master/llvm/lib/IR/Verifier.cpp#L1160 there is IR verification which asserts that only in case of spFlags = DISPFlagDefinition, the compilation unit (unit field) should be present. Otherwise, it should not be present. In the crash case, spFlags = DISPFlagOptimized. So, I guess, unit field should not be present, though I do not know the difference between DISPFlagDefinition and DISPFlagOptimized. if that is expected, then we may need to check nullity of DISubprogram::getUnit() before accessing it at https://github.com/llvm/llvm-project/blob/master/llvm/lib/CodeGen/LexicalScopes.cpp#L53

Thanks,
Mahesha

definition and optimized are orthogonal (a function could be both, or
neither) - one says this DISubprogram describes a function definition
(rather than a declaration) and the other says this function has been
compiled (so I suppose it must be a definition - though we may not
rely on/verify that/need that to be true at the moment).

Sounds like you're saying the verifier does check the constraint
you're interested in (ie: you only hit the assert in
lib/CodeGen/LexicalScopes if the code is in violation of the
verifier?) - and the verification check sounds correct/reasonable to
me. (declarations are owned by the unit - whereas definitions are
intentionally owned by the llvm::Function and refer to the unit they
are within so they can be implicitly dropped if the Function is
dropped - so, yes, the unit must be present for definitions and must
not be present for non-definitions).

I am bit confused - unit must be present for definitions, and optimized is also a definition, so, unit must be present for optimized too. Am I right?

Mahesha

I am bit confused - `unit` must be present for definitions, and `optimized ` is also a `definition`,

Optimized doesn't make much sense/use for a non-definition, as far as
I understand it - but it's probably a fairly benign that the verifier
doesn't diagnose "optimized specified on a non-definition". The
verifier could be tightened to verify that constraint - and then your
IR would fail verification, you could add the definition flag and be
back with working IR that doesn't crash in LLVM's backend, I think?

It's more "optimized was specified where it's meaningless - we don't
do anything with that flag on a non-definition". The verifier could
diagnose that to avoid producers being confused by why it's being
ignored - but it's probably not super important to do so.

Let’s forget about my malformed IR if it is adding additional confusion here. I mentioned it here to ease the conversation, but if it is causing confusion rather than making the discussion flow easier, then we better ignore it.

The whole triggering point for this email initiative is - one of the applications is crashing with the stack trace that I mentioned earlier. The crash is during the pass - llvm::LiveDebugVariables::runOnMachineFunction(). And, it is because, the function in question is optimized case, and hence unit is null', and we are accessing this null` pointer at the point of crashing.

Naturally, I want to understand the root of this issue. So, many questions are raised within my mind.

(1) Is it because, debug metadata info is wrongly generated by setting optimized instead of definition, and hence unit is missing?
(2) Is it because, we are running lvm::LiveDebugVariables::runOnMachineFunction() without checking if the definition is set or not?
(3) Is it because, we are not treating 'optimized as 'definition and hence not setting 'unit`?
(4) and many more.

However, I do not have detailed knowledge in this area. So, I need to understand certain basics here. First, I would ask:

(1) What is the scenario (testcase) for the ‘optimized’ case?
(2) Should we run the pass llvm::LiveDebugVariables::runOnMachineFunction() for the case where ‘optimized’ is set OR we should not?

I think "optimized" is a red herring here - it's just a minor flag
that's used to add an extra attribute to a DW_TAG_subprogram DIE, if
it's present - so far as I know.

It's not "optimized instead of definition" - if the DISubprogram is
referenced from an llvm::Function definition's "getSubprogram", then
it should have a non-null unit. If it doesn't have a unit - that's I
think the source of the problem. A DISubprogram attached to an
llvm::Function definition's getSubprogram should be a definition and
should have a non-null unit.

Thanks for the clarification. Yes, DISubprogram is referenced from an llvm::Function definition’s “getSubprogram” at the point of crash. Then, it must be an issue with the debug info generation.