diff options
author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2015-08-28 21:55:35 +0000 |
---|---|---|
committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2015-08-28 21:55:35 +0000 |
commit | b56b5af4c37e3e00f65e17e40055dc6c4b2f6ade (patch) | |
tree | 6035671e7a04416d616261d46da7c1f61ecc0f8e /llvm | |
parent | 6eaa8323a887a878f54dfcc65d4fff72c0f5c161 (diff) | |
download | bcm5719-llvm-b56b5af4c37e3e00f65e17e40055dc6c4b2f6ade.tar.gz bcm5719-llvm-b56b5af4c37e3e00f65e17e40055dc6c4b2f6ade.zip |
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
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/IR/Function.h | 12 | ||||
-rw-r--r-- | llvm/lib/IR/Metadata.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 14 | ||||
-rw-r--r-- | llvm/test/Verifier/metadata-function-dbg.ll | 23 | ||||
-rw-r--r-- | llvm/unittests/IR/MetadataTest.cpp | 12 |
5 files changed, 68 insertions, 1 deletions
diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index ef7274b4bc6..69c622cc9a8 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -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. diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp index 431fee1b7b7..7d8c3523743 100644 --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -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)); +} diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index c8aba14e813..bcf8c0ffa1e 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -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 diff --git a/llvm/test/Verifier/metadata-function-dbg.ll b/llvm/test/Verifier/metadata-function-dbg.ll new file mode 100644 index 00000000000..43c632babda --- /dev/null +++ b/llvm/test/Verifier/metadata-function-dbg.ll @@ -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 = !{} diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp index b3c26eb407f..6741c79afc9 100644 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -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)); +} + } |