forked from OSchip/llvm-project
DI: Add Function::getSubprogram()
Add `Function::setSubprogram()` and `Function::getSubprogram()`, convenience methods to forward to `setMetadata()` and `getMetadata()`, respectively, and deal in `DISubprogram` instead of `MDNode`. Also add a verifier check to enforce that `!dbg` attachments are always subprograms. Originally (when I had the llvm-dev discussion back in April) I thought I'd store a pointer directly on `llvm::Function` for these attachments -- we frequently have debug info, and that's much cheaper than using map in the context if there are no other function-level attachments -- but for now I'm just using the generic infrastructure. Let's add the extra complexity only if this shows up in a profile. llvm-svn: 246339
This commit is contained in:
parent
6eaa8323a8
commit
b56b5af4c3
|
@ -32,6 +32,7 @@ namespace llvm {
|
|||
|
||||
class FunctionType;
|
||||
class LLVMContext;
|
||||
class DISubprogram;
|
||||
|
||||
template<> struct ilist_traits<Argument>
|
||||
: public SymbolTableListTraits<Argument, Function> {
|
||||
|
@ -606,6 +607,17 @@ public:
|
|||
/// Drop all metadata from \c this not included in \c KnownIDs.
|
||||
void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs);
|
||||
|
||||
/// \brief Set the attached subprogram.
|
||||
///
|
||||
/// Calls \a setMetadata() with \a LLVMContext::MD_dbg.
|
||||
void setSubprogram(DISubprogram *SP);
|
||||
|
||||
/// \brief Get the attached subprogram.
|
||||
///
|
||||
/// Calls \a getMetadata() with \a LLVMContext::MD_dbg and casts the result
|
||||
/// to \a DISubprogram.
|
||||
DISubprogram *getSubprogram() const;
|
||||
|
||||
private:
|
||||
// Shadow Value::setValueSubclassData with a private forwarding method so that
|
||||
// subclasses cannot accidentally use it.
|
||||
|
|
|
@ -1259,3 +1259,11 @@ void Function::clearMetadata() {
|
|||
getContext().pImpl->FunctionMetadata.erase(this);
|
||||
setHasMetadataHashEntry(false);
|
||||
}
|
||||
|
||||
void Function::setSubprogram(DISubprogram *SP) {
|
||||
setMetadata(LLVMContext::MD_dbg, SP);
|
||||
}
|
||||
|
||||
DISubprogram *Function::getSubprogram() const {
|
||||
return cast_or_null<DISubprogram>(getMetadata(LLVMContext::MD_dbg));
|
||||
}
|
||||
|
|
|
@ -1779,8 +1779,20 @@ void Verifier::visitFunction(const Function &F) {
|
|||
}
|
||||
|
||||
// Visit metadata attachments.
|
||||
for (const auto &I : MDs)
|
||||
for (const auto &I : MDs) {
|
||||
// Verify that the attachment is legal.
|
||||
switch (I.first) {
|
||||
default:
|
||||
break;
|
||||
case LLVMContext::MD_dbg:
|
||||
Assert(isa<DISubprogram>(I.second),
|
||||
"function !dbg attachment must be a subprogram", &F, I.second);
|
||||
break;
|
||||
}
|
||||
|
||||
// Verify the metadata itself.
|
||||
visitMDNode(*I.second);
|
||||
}
|
||||
}
|
||||
|
||||
// If this function is actually an intrinsic, verify that it is only used in
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
; RUN: not llvm-as %s -disable-output 2>&1 | FileCheck %s
|
||||
|
||||
define void @foo() !dbg !4 {
|
||||
unreachable
|
||||
}
|
||||
|
||||
; CHECK-NOT: !dbg
|
||||
; CHECK: function !dbg attachment must be a subprogram
|
||||
; CHECK-NEXT: void ()* @bar
|
||||
; CHECK-NEXT: !{{[0-9]+}} = !{}
|
||||
define void @bar() !dbg !6 {
|
||||
unreachable
|
||||
}
|
||||
|
||||
!llvm.module.flags = !{!0}
|
||||
!0 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
|
||||
!llvm.dbg.cu = !{!1}
|
||||
!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, subprograms: !3)
|
||||
!2 = !DIFile(filename: "t.c", directory: "/path/to/dir")
|
||||
!3 = !{!4}
|
||||
!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !2, function: void ()* @foo)
|
||||
!6 = !{}
|
|
@ -2273,4 +2273,16 @@ TEST_F(FunctionAttachmentTest, EntryCount) {
|
|||
EXPECT_EQ(12304u, *F->getEntryCount());
|
||||
}
|
||||
|
||||
TEST_F(FunctionAttachmentTest, SubprogramAttachment) {
|
||||
Function *F = getFunction("foo");
|
||||
DISubprogram *SP = getSubprogram();
|
||||
F->setSubprogram(SP);
|
||||
|
||||
// Note that the static_cast confirms that F->getSubprogram() actually
|
||||
// returns an DISubprogram.
|
||||
EXPECT_EQ(SP, static_cast<DISubprogram *>(F->getSubprogram()));
|
||||
EXPECT_EQ(SP, F->getMetadata("dbg"));
|
||||
EXPECT_EQ(SP, F->getMetadata(LLVMContext::MD_dbg));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue