Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -4742,6 +4742,15 @@ this property for each DILocalVariable. The flag should be used only in optimized code. +DISPFlags +""""""""""""""" + +These flags encode various properties of DISubprograms. + +The `DeclForCallSite` flag marks a function declaration subprogram created for +call site debug information. The subprogram gets created if a called function +does not have a subprogram attached, which is specific to external functions. + DIObjCProperty """""""""""""" Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -665,7 +665,8 @@ DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagZero, DITemplateParameterArray TParams = nullptr, DISubprogram *Decl = nullptr, - DITypeArray ThrownTypes = nullptr); + DITypeArray ThrownTypes = nullptr, + bool isDeclForCallSite = false); /// Identical to createFunction, /// except that the resulting DbgNode is meant to be RAUWed. Index: include/llvm/IR/DebugInfoFlags.def =================================================================== --- include/llvm/IR/DebugInfoFlags.def +++ include/llvm/IR/DebugInfoFlags.def @@ -88,11 +88,12 @@ HANDLE_DISP_FLAG((1u << 6), Elemental) HANDLE_DISP_FLAG((1u << 7), Recursive) HANDLE_DISP_FLAG((1u << 8), MainSubprogram) +HANDLE_DISP_FLAG((1u << 9), DeclForCallSite) #ifdef DISP_FLAG_LARGEST_NEEDED // Intended to be used with ADT/BitmaskEnum.h. // NOTE: Always must be equal to largest flag, check this when adding new flags. -HANDLE_DISP_FLAG((1 << 8), Largest) +HANDLE_DISP_FLAG((1 << 9), Largest) #undef DISP_FLAG_LARGEST_NEEDED #endif Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -1739,6 +1739,7 @@ bool isDefinition() const { return getSPFlags() & SPFlagDefinition; } bool isOptimized() const { return getSPFlags() & SPFlagOptimized; } bool isMainSubprogram() const { return getSPFlags() & SPFlagMainSubprogram; } + bool isDeclForCallSite() const { return getSPFlags() & SPFlagDeclForCallSite; } bool isArtificial() const { return getFlags() & FlagArtificial; } bool isPrivate() const { Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -669,6 +669,11 @@ NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection()); } + // Create DIEs for function declaraions used for dbg call sites. + for (auto Scope : DIUnit->getRetainedTypes()) + if (auto *SP = dyn_cast_or_null(Scope)) + NewCU.getOrCreateSubprogramDIE(SP); + CUMap.insert({DIUnit, &NewCU}); CUDieMap.insert({&NewCU.getUnitDie(), &NewCU}); return NewCU; Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -753,7 +753,7 @@ unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, DINode::DIFlags Flags, DISubprogram::DISPFlags SPFlags, DITemplateParameterArray TParams, DISubprogram *Decl, - DITypeArray ThrownTypes) { + DITypeArray ThrownTypes, bool isDeclForCallSite) { bool IsDefinition = SPFlags & DISubprogram::SPFlagDefinition; auto *Node = getSubprogram( /*IsDistinct=*/IsDefinition, VMContext, getNonCompileUnitScope(Context), @@ -761,7 +761,7 @@ SPFlags, IsDefinition ? CUNode : nullptr, TParams, Decl, MDTuple::getTemporary(VMContext, None).release(), ThrownTypes); - if (IsDefinition) + if (IsDefinition || isDeclForCallSite) AllSubprograms.push_back(Node); trackIfUnresolved(Node); return Node; Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -2223,8 +2223,10 @@ MDs.empty() ? nullptr : MDs.front().second); } else if (F.isDeclaration()) { for (const auto &I : MDs) { - AssertDI(I.first != LLVMContext::MD_dbg, - "function declaration may not have a !dbg attachment", &F); + AssertDI(I.first != LLVMContext::MD_dbg || + cast(I.second)->isDeclForCallSite(), + "function declaration may not have a !dbg attachment, " + "except function declarations for call site debug info", &F); Assert(I.first != LLVMContext::MD_prof, "function declaration may not have a !prof attachment", &F); Index: test/Verifier/metadata-function-dbg.ll =================================================================== --- test/Verifier/metadata-function-dbg.ll +++ test/Verifier/metadata-function-dbg.ll @@ -3,6 +3,9 @@ ; CHECK: function declaration may not have a !dbg attachment declare !dbg !4 void @f1() +; CHECK-NOT: function declaration may not have a !dbg attachment +declare !dbg !5 void @f5() + ; CHECK: function must have a single !dbg attachment define void @f2() !dbg !4 !dbg !4 { unreachable @@ -35,3 +38,4 @@ !2 = !DIFile(filename: "t.c", directory: "/path/to/dir") !3 = !{} !4 = distinct !DISubprogram(name: "foo", scope: !1, file: !2, unit: !1) +!5 = distinct !DISubprogram(name: "f5", scope: !1, file: !2, unit: !1, spFlags: DISPFlagDeclForCallSite)