DwarfDebug problems

In a pass I’m working on, I’ve done some manipulation of several functions, replacing them with new copies with different types, etc.

The LLVM IR passes the verifier, but when I have debug symbols enabled (“-g”), I get the following error when Clang generates the Dwarf info (using a very recent build of LLVM/Clang from Git mirror):

Assertion failed: (TheCU && "Unable to find compile unit!"), function beginFunction, file ../lib/CodeGen/AsmPrinter/DwarfDebug.cpp, line 1617.
0 clang-3.4 0x0000000103ff3808 llvm::sys::PrintStackTrace(__sFILE*) + 40
1 clang-3.4 0x0000000103ff3c64 SignalHandler(int) + 388
2 libsystem_platform.dylib 0x00007fff8dd185aa _sigtramp + 26
3 libsystem_platform.dylib 000000000000000000 _sigtramp + 1915648624
4 clang-3.4 0x0000000103ff3ac6 abort + 22
5 clang-3.4 0x0000000103ff3aa1 __assert_rtn + 81
6 clang-3.4 0x00000001038bcb70 llvm::DwarfDebug::endFunction(llvm::MachineFunction const*) + 0
7 clang-3.4 0x0000000103892677 llvm::AsmPrinter::EmitFunctionHeader() + 727
8 clang-3.4 0x00000001036229ea llvm::X86AsmPrinter::runOnMachineFunction(llvm::MachineFunction&) + 170
9 clang-3.4 0x0000000103b0fbec llvm::MachineFunctionPass::runOnFunction(llvm::Function&) + 60
10 clang-3.4 0x0000000103f1244b llvm::FPPassManager::runOnFunction(llvm::Function&) + 347
11 clang-3.4 0x0000000103f126db llvm::FPPassManager::runOnModule(llvm::Module&) + 43
12 clang-3.4 0x0000000103f12b49 llvm::legacy::PassManagerImpl::run(llvm::Module&) + 713
13 clang-3.4 0x0000000103f12f5d llvm::legacy::PassManager::run(llvm::Module&) + 13
14 clang-3.4 0x0000000104230b3e clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::Module*, clang::BackendAction, llvm::raw_ostream*) + 5790
15 clang-3.4 0x000000010431b9a7 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) + 455
16 clang-3.4 0x00000001044a7644 clang::ParseAST(clang::Sema&, bool, bool) + 516
17 clang-3.4 0x000000010431aab8 clang::CodeGenAction::ExecuteAction() + 584
18 clang-3.4 0x000000010441c0b6 clang::FrontendAction::Execute() + 134
19 clang-3.4 0x00000001043f802d clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 973
20 clang-3.4 0x0000000103ff6ab4 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 4276
21 clang-3.4 0x000000010330306d cc1_main(char const**, char const**, char const*, void*) + 925
22 clang-3.4 0x00000001033015c3 main + 7283
23 libdyld.dylib 0x00007fff8e68d5fd start + 1

(note the line number of the assertion is probably different because I’ve added some prints to help me debug this)

When I print the MDNode returned by “FnScope->getScopeNode()”, I get lots of <badref>’s:

!{i32 786478, metadata <badref>, metadata <badref>, metadata !"grappa_wide_get_pointer", metadata !"grappa_wide_get_pointer", metadata !"", i32 53, metadata <badref>, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i8* (i8*)* @grappa_wide_get_pointer, null, null, metadata <badref>, i32 53} ; [ DW_TAG_subprogram ] [line 53] [def] [grappa_wide_get_pointer]

It looks to me like I must be corrupting the lexical scope information somehow, but I don’t think I’m explicitly touching metadata at all. Any idea what may have caused this? Is there something I must be sure to update within the debug metadata?

Thanks,
-Brandon

In a pass I’m working on, I’ve done some manipulation of several functions, replacing them with new copies with different types, etc.

The LLVM IR passes the verifier, but when I have debug symbols enabled (“-g”), I get the following error when Clang generates the Dwarf info (using a very recent build of LLVM/Clang from Git mirror):

Assertion failed: (TheCU && "Unable to find compile unit!"), function beginFunction, file ../lib/CodeGen/AsmPrinter/DwarfDebug.cpp, line 1617.
0 clang-3.4 0x0000000103ff3808 llvm::sys::PrintStackTrace(__sFILE*) + 40
1 clang-3.4 0x0000000103ff3c64 SignalHandler(int) + 388
2 libsystem_platform.dylib 0x00007fff8dd185aa _sigtramp + 26
3 libsystem_platform.dylib 000000000000000000 _sigtramp + 1915648624
4 clang-3.4 0x0000000103ff3ac6 abort + 22
5 clang-3.4 0x0000000103ff3aa1 __assert_rtn + 81
6 clang-3.4 0x00000001038bcb70 llvm::DwarfDebug::endFunction(llvm::MachineFunction const*) + 0
7 clang-3.4 0x0000000103892677 llvm::AsmPrinter::EmitFunctionHeader() + 727
8 clang-3.4 0x00000001036229ea llvm::X86AsmPrinter::runOnMachineFunction(llvm::MachineFunction&) + 170
9 clang-3.4 0x0000000103b0fbec llvm::MachineFunctionPass::runOnFunction(llvm::Function&) + 60
10 clang-3.4 0x0000000103f1244b llvm::FPPassManager::runOnFunction(llvm::Function&) + 347
11 clang-3.4 0x0000000103f126db llvm::FPPassManager::runOnModule(llvm::Module&) + 43
12 clang-3.4 0x0000000103f12b49 llvm::legacy::PassManagerImpl::run(llvm::Module&) + 713
13 clang-3.4 0x0000000103f12f5d llvm::legacy::PassManager::run(llvm::Module&) + 13
14 clang-3.4 0x0000000104230b3e clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::Module*, clang::BackendAction, llvm::raw_ostream*) + 5790
15 clang-3.4 0x000000010431b9a7 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) + 455
16 clang-3.4 0x00000001044a7644 clang::ParseAST(clang::Sema&, bool, bool) + 516
17 clang-3.4 0x000000010431aab8 clang::CodeGenAction::ExecuteAction() + 584
18 clang-3.4 0x000000010441c0b6 clang::FrontendAction::Execute() + 134
19 clang-3.4 0x00000001043f802d clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 973
20 clang-3.4 0x0000000103ff6ab4 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 4276
21 clang-3.4 0x000000010330306d cc1_main(char const**, char const**, char const*, void*) + 925
22 clang-3.4 0x00000001033015c3 main + 7283
23 libdyld.dylib 0x00007fff8e68d5fd start + 1

(note the line number of the assertion is probably different because I’ve added some prints to help me debug this)

When I print the MDNode returned by “FnScope->getScopeNode()”, I get lots of <badref>’s:

The badrefs are a red herring, so far as I know - they're printed that
way even when they're valid references, in my experience.

That being said, given your assertion it does look like /something/ is up.

It appears as if the function being emitted is somehow not visited
when emitting functions in the list of functions on the compilation
units. Somehow it got separated, perhaps.

!{i32 786478, metadata <badref>, metadata <badref>, metadata !"grappa_wide_get_pointer", metadata !"grappa_wide_get_pointer", metadata !"", i32 53, metadata <badref>, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i8* (i8*)* @grappa_wide_get_pointer, null, null, metadata <badref>, i32 53} ; [ DW_TAG_subprogram ] [line 53] [def] [grappa_wide_get_pointer]

It looks to me like I must be corrupting the lexical scope information somehow, but I don’t think I’m explicitly touching metadata at all. Any idea what may have caused this? Is there something I must be sure to update within the debug metadata?

I'd look at the cu metadata and the associated subprogram lists to see
what's in there and why your subprogram isn't in that list (if I'm
reading it right, that's the case - but I could be wrong).

Thanks for the quick response.

I wrote some code to search “llvm.dbg.cu” for the function (right before the failed assertion):

if (TheCU == nullptr) {
errs() << "compile unit: " << TheCU << “\n scopeNode(” << FnScope->getScopeNode() << ") => " << *FnScope->getScopeNode() << “\n”;
auto fn = MF->getFunction();
errs() << " fn => " << fn->getName() << “\n”;

MDNode *node = nullptr;
auto mod = fn->getParent();
auto dbg = mod->getNamedMetadata(“llvm.dbg.cu”);
for (unsigned ni = 0; ni < dbg->getNumOperands(); ni++) {
DICompileUnit cu(dbg->getOperand(ni));
auto subs = cu.getSubprograms();
for (unsigned si = 0; si < subs.getNumElements(); si++) {
DISubprogram sp(subs.getElement(si));
if (sp.getFunction() == fn) {
node = sp;
break;
}
}
}
errs() << " (" << node << " ) node => " << *node << “\n”;
}

Strangely, the node my code finds prints the same, but the pointer is different:

scopeNode(0x7fe53dc6c2c0) => !{i32 786478, metadata , metadata , metadata !“grappa_wide_get_pointer”, metadata !“grappa_wide_get_pointer”, metadata !“”, i32 53, metadata , i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i8* (i8*)* @grappa_wide_get_pointer, null, null, metadata , i32 53} ; [ DW_TAG_subprogram ] [line 53] [def] [grappa_wide_get_pointer]

fn => grappa_wide_get_pointer
(0x7fe53bc241b0 ) node => !{i32 786478, metadata , metadata , metadata !“grappa_wide_get_pointer”, metadata !“grappa_wide_get_pointer”, metadata !“”, i32 53, metadata , i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i8* (i8*)* @grappa_wide_get_pointer, null, null, metadata , i32 53} ; [ DW_TAG_subprogram ] [line 53] [def] [grappa_wide_get_pointer]

Any idea what that could mean?

Thanks for the quick response.

I wrote some code to search “llvm.dbg.cu” for the function (right before the
failed assertion):

  if (TheCU == nullptr) {
    errs() << "compile unit: " << TheCU << "\n scopeNode(" <<
FnScope->getScopeNode() << ") => " << *FnScope->getScopeNode() << "\n";
    auto fn = MF->getFunction();
    errs() << " fn => " << fn->getName() << "\n";

    MDNode *node = nullptr;
    auto mod = fn->getParent();
    auto dbg = mod->getNamedMetadata("llvm.dbg.cu");
    for (unsigned ni = 0; ni < dbg->getNumOperands(); ni++) {
      DICompileUnit cu(dbg->getOperand(ni));
      auto subs = cu.getSubprograms();
      for (unsigned si = 0; si < subs.getNumElements(); si++) {
        DISubprogram sp(subs.getElement(si));
        if (sp.getFunction() == fn) {
          node = sp;
          break;
        }
      }
    }
    errs() << " (" << node << " ) node => " << *node << "\n";
  }

Strangely, the node my code finds *prints* the same, but the pointer is
different:

  scopeNode(0x7fe53dc6c2c0) => !{i32 786478, metadata <badref>, metadata
<badref>, metadata !"grappa_wide_get_pointer", metadata
!"grappa_wide_get_pointer", metadata !"", i32 53, metadata <badref>, i1
false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i8* (i8*)*
@grappa_wide_get_pointer, null, null, metadata <badref>, i32 53} ; [
DW_TAG_subprogram ] [line 53] [def] [grappa_wide_get_pointer]

  fn => grappa_wide_get_pointer
  (0x7fe53bc241b0 ) node => !{i32 786478, metadata <badref>, metadata
<badref>, metadata !"grappa_wide_get_pointer", metadata
!"grappa_wide_get_pointer", metadata !"", i32 53, metadata <badref>, i1
false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i8* (i8*)*
@grappa_wide_get_pointer, null, null, metadata <badref>, i32 53} ; [
DW_TAG_subprogram ] [line 53] [def] [grappa_wide_get_pointer]

Any idea what that could mean?

If you duplicated the function and then RAUW'd it, perhaps the
metadata was duplicated in an effort to keep the original metadata in
tact.

I'm really fuzzy on this, but as far as I understand it, identical
metadata nodes are implicitly uniqued - when they become
non-identical, they may be duplicated so that nodes intending to refer
to one node don't end up referring to some mutated node.

I don't know whether this is at all related to what you're seeing, but
I'd consider examining the nodes before and after you replace your
function and you might find that that's when the nodes become
non-identical...

Sorry I'm not more precise/more help here.

- David

In your transform I'd take a look at things like the individual basic
blocks you're replacing and the functions you're replacing and making
sure that the various lexical blocks are being changed at the same
time...

-eric

How do I find and update the lexical blocks? Is, for example, “CloneFunction” doing this in a way I can copy?

I tried finding the subprogram node in “llvm.dbg.cu” and updating the function:

DISubprogram s(*subprog_iter);
if (s.getFunction() == F) {
s.replaceFunction(NF);

}

But this didn’t seem to have any effect. Do I need to do something similar with every basic block or something?

How do I find and update the lexical blocks? Is, for example,
“CloneFunction” doing this in a way I can copy?

I'm not certain, and unlikely.

I tried finding the subprogram node in “llvm.dbg.cu” and updating the
function:

DISubprogram s(*subprog_iter);
if (s.getFunction() == F) {
   s.replaceFunction(NF);
}

But this didn’t seem to have any effect. Do I need to do something similar
with every basic block or something?

I'd have thought that RAUW would have replaced the function pointer in
the metadata.

-eric