I am developing a compiler for a new language in LLVM and am encountering a problem when creating debugging information.
I have not yet found a lot of documentation on how to actually generate debugging information using DIBuilder , so this is very possible. t doing something is terribly wrong.
I mainly look at the Kaleidoscope , as it is the only one I found that uses debugging information. I have yet to hack Clang to see how they use it, but I would like to hear from someone who has it.
I was able to compile and run my language with more complex examples, but I started using some basics to add debugging support. Here is a simple script I'm trying to compile:
double my_main()
{
return 0.0;
}
Here is my conclusion from verifyFunction, verifyModule and module reset.
Edit: Mark in edit below. I indicate that the dump after the call to complete, which correctly removes the temporary.
Failed To Verify Function: my_main error: Expected no forward declarations!
Failed To Verify Module: test.str error: Expected no forward declarations!
; ModuleID = 'test.str'
define double @my_main() !dbg !6 {
entry:
br label %block, !dbg !10
block: ; preds = %entry
ret double 0.000000e+00, !dbg !10
}
A search for the error message in the LLVM code base shows the source in Verifier.cpp:
void Verifier::visitMDNode(const MDNode &MD) {
if (!MDNodes.insert(&MD).second)
return;
switch (MD.getMetadataID()) {
default:
llvm_unreachable("Invalid MDNode subclass");
case Metadata::MDTupleKind:
break;
#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \
case Metadata::CLASS##Kind: \
visit##CLASS(cast<CLASS>(MD)); \
break;
#include "llvm/IR/Metadata.def"
}
for (unsigned i = 0, e = MD.getNumOperands(); i != e; ++i) {
Metadata *Op = MD.getOperand(i);
if (!Op)
continue;
Assert(!isa<LocalAsMetadata>(Op), "Invalid operand for global metadata!",
&MD, Op);
if (auto *N = dyn_cast<MDNode>(Op)) {
visitMDNode(*N);
continue;
}
if (auto *V = dyn_cast<ValueAsMetadata>(Op)) {
visitValueAsMetadata(*V, nullptr);
continue;
}
}
Assert(!MD.isTemporary(), "Expected no forward declarations!", &MD);
Assert(MD.isResolved(), "All nodes should be resolved!", &MD);
}
I assume that I have some metadata that is still considered "temporary", but I would like to know how to track what creates them.
I create my types in the same way as in the example:
dbuilder->createBasicType("double", 64, alignment, dwarf::DW_ATE_float);
My logic for creating a debug function uses this type, among other things, in another call from the example:
dbuilder->createSubroutineType(dbuilder->getOrCreateTypeArray(returnPlusParams));
IRBuilder AST:
_mBuilder->SetCurrentDebugLocation(DebugLoc::get(node->line, node->column, currentDebugScope()));
SourceLevelDebugging, ++ API LLVM , -.
- - - , .
: IR
Clang :
clang -cc1 hello_llvm.c -emit-llvm
: , .
:
double main() {
return 0.0;
}
:
; ModuleID = 'hello_llvm.c'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-darwin15.0.0"
; Function Attrs: nounwind
define double @main() #0 {
entry:
ret double 0.000000e+00
}
attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-features"="+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.ident = !{!0}
!0 = !{!"clang version 3.8.0 (http://llvm.org/git/clang.git 80803f026ba7160f7cfa122c7ef829ab42abc3bf) (http://llvm.org/git/llvm.git 1bb03c5884405c428c3ab54631c0528b6cedeb54)"}
, main int. int, alloca:
; ModuleID = 'hello_llvm.c'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-darwin15.0.0"
; Function Attrs: nounwind
define i32 @main()
entry:
%retval = alloca i32, align 4
store i32 0, i32* %retval, align 4
ret i32 0
}
attributes
!llvm.ident = !{!0}
!0 = !{!"clang version 3.8.0 (http://llvm.org/git/clang.git 80803f026ba7160f7cfa122c7ef829ab42abc3bf) (http://llvm.org/git/llvm.git 1bb03c5884405c428c3ab54631c0528b6cedeb54)"}
. double , int . my_main main argv/argc .
2: ""
IR, verifyModule finalize. -, .
. , .
Failed To Verify Module: test.str error: Expected no forward declarations!
; ModuleID = 'test.str'
define i32 @my_main() !dbg !4 {
entry:
br label %block, !dbg !9
block: ; preds = %entry
ret i32 0, !dbg !9
}
, , ...
-, , ? ? ?