summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-08-28 21:55:35 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-08-28 21:55:35 +0000
commitb56b5af4c37e3e00f65e17e40055dc6c4b2f6ade (patch)
tree6035671e7a04416d616261d46da7c1f61ecc0f8e /llvm
parent6eaa8323a887a878f54dfcc65d4fff72c0f5c161 (diff)
downloadbcm5719-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.h12
-rw-r--r--llvm/lib/IR/Metadata.cpp8
-rw-r--r--llvm/lib/IR/Verifier.cpp14
-rw-r--r--llvm/test/Verifier/metadata-function-dbg.ll23
-rw-r--r--llvm/unittests/IR/MetadataTest.cpp12
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));
+}
+
}
OpenPOWER on IntegriCloud