diff options
-rw-r--r-- | llvm/include/llvm-c/DebugInfo.h | 71 | ||||
-rw-r--r-- | llvm/lib/IR/DebugInfo.cpp | 57 | ||||
-rw-r--r-- | llvm/test/Bindings/llvm-c/debug_info_new_format.ll | 70 | ||||
-rw-r--r-- | llvm/tools/llvm-c-test/debuginfo.c | 47 |
4 files changed, 217 insertions, 28 deletions
diff --git a/llvm/include/llvm-c/DebugInfo.h b/llvm/include/llvm-c/DebugInfo.h index 7d1caa6..212c2e1 100644 --- a/llvm/include/llvm-c/DebugInfo.h +++ b/llvm/include/llvm-c/DebugInfo.h @@ -689,6 +689,77 @@ LLVM_C_ABI LLVMMetadataRef LLVMDIBuilderCreateArrayType( LLVMMetadataRef Ty, LLVMMetadataRef *Subscripts, unsigned NumSubscripts); /** + * Create debugging information entry for a set. + * \param Builder The DIBuilder. + * \param Scope The scope in which the set is defined. + * \param Name A name that uniquely identifies this set. + * \param NameLen The length of the C string passed to \c Name. + * \param File File where the set is located. + * \param Line Line number of the declaration. + * \param SizeInBits Set size. + * \param AlignInBits Set alignment. + * \param BaseTy The base type of the set. + */ +LLVMMetadataRef LLVMDIBuilderCreateSetType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef BaseTy); + +/** + * Create a descriptor for a subrange with dynamic bounds. + * \param Builder The DIBuilder. + * \param Scope The scope in which the subrange is defined. + * \param Name A name that uniquely identifies this subrange. + * \param NameLen The length of the C string passed to \c Name. + * \param LineNo Line number. + * \param File File where the subrange is located. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param Flags Flags. + * \param BaseTy The base type of the subrange. eg integer or enumeration + * \param LowerBound Lower bound of the subrange. + * \param UpperBound Upper bound of the subrange. + * \param Stride Stride of the subrange. + * \param Bias Bias of the subrange. + */ +LLVMMetadataRef LLVMDIBuilderCreateSubrangeType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, unsigned LineNo, LLVMMetadataRef File, uint64_t SizeInBits, + uint32_t AlignInBits, LLVMDIFlags Flags, LLVMMetadataRef BaseTy, + LLVMMetadataRef LowerBound, LLVMMetadataRef UpperBound, + LLVMMetadataRef Stride, LLVMMetadataRef Bias); + +/** + * Create debugging information entry for a dynamic array. + * \param Builder The DIBuilder. + * \param Size Array size. + * \param AlignInBits Alignment. + * \param Ty Element type. + * \param Subscripts Subscripts. + * \param NumSubscripts Number of subscripts. + * \param DataLocation DataLocation. (DIVariable, DIExpression or NULL) + * \param Associated Associated. (DIVariable, DIExpression or NULL) + * \param Allocated Allocated. (DIVariable, DIExpression or NULL) + * \param Rank Rank. (DIVariable, DIExpression or NULL) + * \param BitStride BitStride. + */ +LLVMMetadataRef LLVMDIBuilderCreateDynamicArrayType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, unsigned LineNo, LLVMMetadataRef File, uint64_t Size, + uint32_t AlignInBits, LLVMMetadataRef Ty, LLVMMetadataRef *Subscripts, + unsigned NumSubscripts, LLVMMetadataRef DataLocation, + LLVMMetadataRef Associated, LLVMMetadataRef Allocated, LLVMMetadataRef Rank, + LLVMMetadataRef BitStride); + +/** + * Replace arrays. + * + * @see DIBuilder::replaceArrays() + */ +void LLVMReplaceArrays(LLVMDIBuilderRef Builder, LLVMMetadataRef *T, + LLVMMetadataRef *Elements, unsigned NumElements); + +/** * Create debugging information entry for a vector type. * \param Builder The DIBuilder. * \param Size Vector size. diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 4e09f84..84a56058 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -1325,6 +1325,63 @@ return wrap(unwrap(Builder)->createEnumerationType( LineNumber, SizeInBits, AlignInBits, Elts, unwrapDI<DIType>(ClassTy))); } +LLVMMetadataRef LLVMDIBuilderCreateSetType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef BaseTy) { + return wrap(unwrap(Builder)->createSetType( + unwrapDI<DIScope>(Scope), {Name, NameLen}, unwrapDI<DIFile>(File), + LineNumber, SizeInBits, AlignInBits, unwrapDI<DIType>(BaseTy))); +} + +LLVMMetadataRef LLVMDIBuilderCreateSubrangeType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, unsigned LineNo, LLVMMetadataRef File, uint64_t SizeInBits, + uint32_t AlignInBits, LLVMDIFlags Flags, LLVMMetadataRef BaseTy, + LLVMMetadataRef LowerBound, LLVMMetadataRef UpperBound, + LLVMMetadataRef Stride, LLVMMetadataRef Bias) { + return wrap(unwrap(Builder)->createSubrangeType( + {Name, NameLen}, unwrapDI<DIFile>(File), LineNo, unwrapDI<DIScope>(Scope), + SizeInBits, AlignInBits, map_from_llvmDIFlags(Flags), + unwrapDI<DIType>(BaseTy), unwrap(LowerBound), unwrap(UpperBound), + unwrap(Stride), unwrap(Bias))); +} + +/// MD may be nullptr, a DIExpression or DIVariable. +PointerUnion<DIExpression *, DIVariable *> unwrapExprVar(LLVMMetadataRef MD) { + if (!MD) + return nullptr; + MDNode *MDN = unwrapDI<MDNode>(MD); + if (auto *E = dyn_cast<DIExpression>(MDN)) + return E; + assert(isa<DIVariable>(MDN) && "Expected DIExpression or DIVariable"); + return cast<DIVariable>(MDN); +} + +LLVMMetadataRef LLVMDIBuilderCreateDynamicArrayType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, unsigned LineNo, LLVMMetadataRef File, uint64_t Size, + uint32_t AlignInBits, LLVMMetadataRef Ty, LLVMMetadataRef *Subscripts, + unsigned NumSubscripts, LLVMMetadataRef DataLocation, + LLVMMetadataRef Associated, LLVMMetadataRef Allocated, LLVMMetadataRef Rank, + LLVMMetadataRef BitStride) { + auto Subs = + unwrap(Builder)->getOrCreateArray({unwrap(Subscripts), NumSubscripts}); + return wrap(unwrap(Builder)->createArrayType( + unwrapDI<DIScope>(Scope), {Name, NameLen}, unwrapDI<DIFile>(File), LineNo, + Size, AlignInBits, unwrapDI<DIType>(Ty), Subs, + unwrapExprVar(DataLocation), unwrapExprVar(Associated), + unwrapExprVar(Allocated), unwrapExprVar(Rank), unwrap(BitStride))); +} + +void LLVMReplaceArrays(LLVMDIBuilderRef Builder, LLVMMetadataRef *T, + LLVMMetadataRef *Elements, unsigned NumElements) { + auto CT = unwrap<DICompositeType>(*T); + auto Elts = + unwrap(Builder)->getOrCreateArray({unwrap(Elements), NumElements}); + unwrap(Builder)->replaceArrays(CT, Elts); +} + LLVMMetadataRef LLVMDIBuilderCreateUnionType( LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, diff --git a/llvm/test/Bindings/llvm-c/debug_info_new_format.ll b/llvm/test/Bindings/llvm-c/debug_info_new_format.ll index 86ec915..83b37da 100644 --- a/llvm/test/Bindings/llvm-c/debug_info_new_format.ll +++ b/llvm/test/Bindings/llvm-c/debug_info_new_format.ll @@ -3,30 +3,36 @@ ; CHECK: ; ModuleID = 'debuginfo.c' ; CHECK-NEXT: source_filename = "debuginfo.c" - -; CHECK: define i64 @foo(i64 %0, i64 %1, <10 x i64> %2) !dbg !36 { + +; CHECK: define i64 @foo(i64 %0, i64 %1, <10 x i64> %2) !dbg !44 { ; CHECK-NEXT: entry: -; CHECK-NEXT: #dbg_declare(i64 0, !43, !DIExpression(), !50) -; CHECK-NEXT: #dbg_declare(i64 0, !44, !DIExpression(), !50) -; CHECK-NEXT: #dbg_declare(i64 0, !45, !DIExpression(), !50) -; CHECK-NEXT: #dbg_label(!51, !50) +; CHECK-NEXT: #dbg_declare(i64 0, !49, !DIExpression(), !58) +; CHECK-NEXT: #dbg_declare(i64 0, !50, !DIExpression(), !58) +; CHECK-NEXT: #dbg_declare(i64 0, !51, !DIExpression(), !58) +; CHECK-NEXT: #dbg_label(!59, !58) ; CHECK-NEXT: br label %vars -; CHECK-NEXT: #dbg_label(!52, !50) +; CHECK-NEXT: #dbg_label(!60, !58) ; CHECK-NEXT: br label %vars -; CHECK: vars: + +; CHECK: vars: ; preds = %entry, %entry ; CHECK-NEXT: %p1 = phi i64 [ 0, %entry ] ; CHECK-NEXT: %p2 = phi i64 [ 0, %entry ] -; CHECK-NEXT: #dbg_value(i64 0, !46, !DIExpression(DW_OP_constu, 0, DW_OP_stack_value), !53) -; CHECK-NEXT: #dbg_value(i64 1, !48, !DIExpression(DW_OP_constu, 1, DW_OP_stack_value), !53) +; CHECK-NEXT: #dbg_value(i64 0, !42, !DIExpression(DW_OP_constu, 0, DW_OP_stack_value), !61) +; CHECK-NEXT: #dbg_value(i64 1, !52, !DIExpression(DW_OP_constu, 1, DW_OP_stack_value), !61) ; CHECK-NEXT: %a = add i64 %p1, %p2 ; CHECK-NEXT: ret i64 0 ; CHECK-NEXT: } - + ; CHECK: !llvm.dbg.cu = !{!0} ; CHECK-NEXT: !FooType = !{!33} ; CHECK-NEXT: !EnumTest = !{!3} ; CHECK-NEXT: !LargeEnumTest = !{!11} - +; CHECK-NEXT: !SubrangeType = !{!36} +; CHECK-NEXT: !SetType1 = !{!37} +; CHECK-NEXT: !SetType2 = !{!38} +; CHECK-NEXT: !DynType = !{!39} +; CHECK-NEXT: !ClassType = !{!54} + ; CHECK: !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "llvm-c-test", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !16, imports: !24, macros: !28, splitDebugInlining: false, sysroot: "/") ; CHECK-NEXT: !1 = !DIFile(filename: "debuginfo.c", directory: ".") ; CHECK-NEXT: !2 = !{!3, !11} @@ -63,21 +69,29 @@ ; CHECK-NEXT: !33 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !34, size: 192, dwarfAddressSpace: 0) ; CHECK-NEXT: !34 = !DICompositeType(tag: DW_TAG_structure_type, name: "MyStruct", scope: !4, file: !1, size: 192, elements: !35, runtimeLang: DW_LANG_C89, identifier: "MyStruct") ; CHECK-NEXT: !35 = !{!6, !6, !6} -; CHECK-NEXT: !36 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !1, file: !1, line: 42, type: !37, scopeLine: 42, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !42) -; CHECK-NEXT: !37 = !DISubroutineType(types: !38) -; CHECK-NEXT: !38 = !{!6, !6, !39} -; CHECK-NEXT: !39 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 640, flags: DIFlagVector, elements: !40) +; CHECK-NEXT: !36 = !DISubrangeType(name: "foo", scope: !1, file: !1, line: 42, size: 64, baseType: !6, lowerBound: i64 0, upperBound: i64 1, stride: i64 8, bias: i64 4) +; CHECK-NEXT: !37 = !DIDerivedType(tag: DW_TAG_set_type, name: "enumset", scope: !1, file: !1, line: 42, baseType: !3, size: 64) +; CHECK-NEXT: !38 = !DIDerivedType(tag: DW_TAG_set_type, name: "subrangeset", scope: !1, file: !1, line: 42, baseType: !36, size: 64) +; CHECK-NEXT: !39 = !DICompositeType(tag: DW_TAG_array_type, name: "foo", scope: !1, file: !1, line: 42, baseType: !6, size: 640, elements: !40, dataLocation: !DIExpression(), associated: !42, rank: !DIExpression()) ; CHECK-NEXT: !40 = !{!41} ; CHECK-NEXT: !41 = !DISubrange(count: 10, lowerBound: 0) -; CHECK-NEXT: !42 = !{!43, !44, !45, !46, !48, !49} -; CHECK-NEXT: !43 = !DILocalVariable(name: "a", arg: 1, scope: !36, file: !1, line: 42, type: !6) -; CHECK-NEXT: !44 = !DILocalVariable(name: "b", arg: 2, scope: !36, file: !1, line: 42, type: !6) -; CHECK-NEXT: !45 = !DILocalVariable(name: "c", arg: 3, scope: !36, file: !1, line: 42, type: !39) -; CHECK-NEXT: !46 = !DILocalVariable(name: "d", scope: !47, file: !1, line: 43, type: !6) -; CHECK-NEXT: !47 = distinct !DILexicalBlock(scope: !36, file: !1, line: 42) -; CHECK-NEXT: !48 = !DILocalVariable(name: "e", scope: !47, file: !1, line: 44, type: !6) -; CHECK-NEXT: !49 = !DILabel(scope: !36, name: "label3", file: !1, line: 42) -; CHECK-NEXT: !50 = !DILocation(line: 42, scope: !36) -; CHECK-NEXT: !51 = !DILabel(scope: !36, name: "label1", file: !1, line: 42) -; CHECK-NEXT: !52 = !DILabel(scope: !36, name: "label2", file: !1, line: 42) -; CHECK-NEXT: !53 = !DILocation(line: 43, scope: !36) +; CHECK-NEXT: !42 = !DILocalVariable(name: "d", scope: !43, file: !1, line: 43, type: !6) +; CHECK-NEXT: !43 = distinct !DILexicalBlock(scope: !44, file: !1, line: 42) +; CHECK-NEXT: !44 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !1, file: !1, line: 42, type: !45, scopeLine: 42, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !48) +; CHECK-NEXT: !45 = !DISubroutineType(types: !46) +; CHECK-NEXT: !46 = !{!6, !6, !47} +; CHECK-NEXT: !47 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 640, flags: DIFlagVector, elements: !40) +; CHECK-NEXT: !48 = !{!49, !50, !51, !42, !52, !53} +; CHECK-NEXT: !49 = !DILocalVariable(name: "a", arg: 1, scope: !44, file: !1, line: 42, type: !6) +; CHECK-NEXT: !50 = !DILocalVariable(name: "b", arg: 2, scope: !44, file: !1, line: 42, type: !6) +; CHECK-NEXT: !51 = !DILocalVariable(name: "c", arg: 3, scope: !44, file: !1, line: 42, type: !47) +; CHECK-NEXT: !52 = !DILocalVariable(name: "e", scope: !43, file: !1, line: 44, type: !6) +; CHECK-NEXT: !53 = !DILabel(scope: !44, name: "label3", file: !1, line: 42) +; CHECK-NEXT: !54 = !DICompositeType(tag: DW_TAG_class_type, name: "Class", scope: !4, file: !1, size: 192, flags: DIFlagFwdDecl, elements: !55, identifier: "FooClass") +; CHECK-NEXT: !55 = !{!56} +; CHECK-NEXT: !56 = !{!6, !6, !57} +; CHECK-NEXT: !57 = !DIBasicType(name: "Int32", size: 32) +; CHECK-NEXT: !58 = !DILocation(line: 42, scope: !44) +; CHECK-NEXT: !59 = !DILabel(scope: !44, name: "label1", file: !1, line: 42) +; CHECK-NEXT: !60 = !DILabel(scope: !44, name: "label2", file: !1, line: 42) +; CHECK-NEXT: !61 = !DILocation(line: 43, scope: !44) diff --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c index 8c6f643..e73f697 100644 --- a/llvm/tools/llvm-c-test/debuginfo.c +++ b/llvm/tools/llvm-c-test/debuginfo.c @@ -235,6 +235,53 @@ int llvm_test_dibuilder(void) { M, "LargeEnumTest", LLVMMetadataAsValue(LLVMGetModuleContext(M), LargeEnumTest)); + LLVMValueRef FooVal3 = LLVMConstInt(LLVMInt64Type(), 8, false); + LLVMValueRef FooVal4 = LLVMConstInt(LLVMInt64Type(), 4, false); + LLVMMetadataRef lo = LLVMValueAsMetadata(FooVal1); + LLVMMetadataRef hi = LLVMValueAsMetadata(FooVal2); + LLVMMetadataRef strd = LLVMValueAsMetadata(FooVal3); + LLVMMetadataRef bias = LLVMValueAsMetadata(FooVal4); + LLVMMetadataRef SubrangeMetadataTy = LLVMDIBuilderCreateSubrangeType( + DIB, File, "foo", 3, 42, File, 64, 0, 0, Int64Ty, lo, hi, strd, bias); + LLVMAddNamedMetadataOperand( + M, "SubrangeType", + LLVMMetadataAsValue(LLVMGetModuleContext(M), SubrangeMetadataTy)); + + LLVMMetadataRef SetMetadataTy1 = LLVMDIBuilderCreateSetType( + DIB, File, "enumset", 7, File, 42, 64, 0, EnumTest); + LLVMMetadataRef SetMetadataTy2 = LLVMDIBuilderCreateSetType( + DIB, File, "subrangeset", 11, File, 42, 64, 0, SubrangeMetadataTy); + LLVMAddNamedMetadataOperand( + M, "SetType1", + LLVMMetadataAsValue(LLVMGetModuleContext(M), SetMetadataTy1)); + LLVMAddNamedMetadataOperand( + M, "SetType2", + LLVMMetadataAsValue(LLVMGetModuleContext(M), SetMetadataTy2)); + + LLVMMetadataRef DynSubscripts[] = { + LLVMDIBuilderGetOrCreateSubrange(DIB, 0, 10), + }; + LLVMMetadataRef Loc = LLVMDIBuilderCreateExpression(DIB, NULL, 0); + LLVMMetadataRef Rank = LLVMDIBuilderCreateExpression(DIB, NULL, 0); + LLVMMetadataRef DynamicArrayMetadataTy = LLVMDIBuilderCreateDynamicArrayType( + DIB, File, "foo", 3, 42, File, 64 * 10, 0, Int64Ty, DynSubscripts, 1, Loc, + FooVar1, NULL, Rank, NULL); + LLVMAddNamedMetadataOperand( + M, "DynType", + LLVMMetadataAsValue(LLVMGetModuleContext(M), DynamicArrayMetadataTy)); + + LLVMMetadataRef StructPTy = LLVMDIBuilderCreateForwardDecl( + DIB, 2 /*DW_TAG_class_type*/, "Class1", 5, NameSpace, File, 0, 0, 192, 0, + "FooClass", 8); + + LLVMMetadataRef Int32Ty = + LLVMDIBuilderCreateBasicType(DIB, "Int32", 5, 32, 0, LLVMDIFlagZero); + LLVMMetadataRef StructElts[] = {Int64Ty, Int64Ty, Int32Ty}; + LLVMMetadataRef ClassArr = LLVMDIBuilderGetOrCreateArray(DIB, StructElts, 3); + LLVMReplaceArrays(DIB, &StructPTy, &ClassArr, 1); + LLVMAddNamedMetadataOperand( + M, "ClassType", LLVMMetadataAsValue(LLVMGetModuleContext(M), StructPTy)); + // Using the new debug format, debug records get attached to instructions. // Insert a `br` and `ret` now to absorb the debug records which are // currently "trailing", meaning that they're associated with a block |