PR19598: Provide the ability to RAUW a declaration with itself, creating a non-tempor...
authorDavid Blaikie <dblaikie@gmail.com>
Tue, 6 May 2014 03:41:57 +0000 (03:41 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Tue, 6 May 2014 03:41:57 +0000 (03:41 +0000)
Also, provide the ability to create temporary and non-temporary
declarations, as not all declarations may be replaced by definitions
later on.

This provides the necessary infrastructure for Clang to fix PR19598,
leaking temporary MDNodes in Clang's debug info generation.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208054 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/DIBuilder.h
include/llvm/IR/DebugInfo.h
lib/IR/DIBuilder.cpp
lib/IR/DebugInfo.cpp

index df8cd75de12b953132c05312b78cc1bd5879f3b7..8b05bbb4fdb7ed2778d0cfa2f5768a31969c26d0 100644 (file)
@@ -434,7 +434,7 @@ namespace llvm {
     /// flag set.
     DIType createObjectPointerType(DIType Ty);
 
-    /// createForwardDecl - Create a temporary forward-declared type.
+    /// \brief Create a permanent forward-declared type.
     DICompositeType createForwardDecl(unsigned Tag, StringRef Name,
                                       DIDescriptor Scope, DIFile F,
                                       unsigned Line, unsigned RuntimeLang = 0,
@@ -442,6 +442,12 @@ namespace llvm {
                                       uint64_t AlignInBits = 0,
                                       StringRef UniqueIdentifier = StringRef());
 
+    /// \brief Create a temporary forward-declared type.
+    DICompositeType createReplaceableForwardDecl(
+        unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F,
+        unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0,
+        uint64_t AlignInBits = 0, StringRef UniqueIdentifier = StringRef());
+
     /// retainType - Retain DIType in a module even if it is not referenced
     /// through debug info anchors.
     void retainType(DIType T);
index 82b25ace449640c3a98bba629e5503b1049d6e01..1b97f6254215ad1dcc46c7223cb7560dd0b05fb8 100644 (file)
@@ -339,7 +339,7 @@ public:
 
   /// replaceAllUsesWith - Replace all uses of debug info referenced by
   /// this descriptor.
-  void replaceAllUsesWith(DIDescriptor &D);
+  void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D);
   void replaceAllUsesWith(MDNode *D);
 };
 
index 8d7d21eb1680709f74df388f8cebf8d6016a52d7..528b43cdc882e4f9eca86b6481d75243773fef5c 100644 (file)
@@ -901,6 +901,40 @@ DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope,
     UniqueIdentifier.empty() ? nullptr
                              : MDString::get(VMContext, UniqueIdentifier)
   };
+  MDNode *Node = MDNode::get(VMContext, Elts);
+  DICompositeType RetTy(Node);
+  assert(RetTy.isCompositeType() &&
+         "createForwardDecl result should be a DIType");
+  if (!UniqueIdentifier.empty())
+    retainType(RetTy);
+  return RetTy;
+}
+
+/// createForwardDecl - Create a temporary forward-declared type that
+/// can be RAUW'd if the full type is seen.
+DICompositeType DIBuilder::createReplaceableForwardDecl(
+    unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line,
+    unsigned RuntimeLang, uint64_t SizeInBits, uint64_t AlignInBits,
+    StringRef UniqueIdentifier) {
+  // Create a temporary MDNode.
+  Value *Elts[] = {
+    GetTagConstant(VMContext, Tag),
+    F.getFileNode(),
+    DIScope(getNonCompileUnitScope(Scope)).getRef(),
+    MDString::get(VMContext, Name),
+    ConstantInt::get(Type::getInt32Ty(VMContext), Line),
+    ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
+    ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
+    ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset
+    ConstantInt::get(Type::getInt32Ty(VMContext), DIDescriptor::FlagFwdDecl),
+    nullptr,
+    DIArray(),
+    ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang),
+    nullptr,
+    nullptr, //TemplateParams
+    UniqueIdentifier.empty() ? nullptr
+                             : MDString::get(VMContext, UniqueIdentifier)
+  };
   MDNode *Node = MDNode::getTemporary(VMContext, Elts);
   DICompositeType RetTy(Node);
   assert(RetTy.isCompositeType() &&
index cf8afe251ad46fa91bb374a473cb53322fed3e81..db9e56defa12d5680765d8c8d7caaa0fc9c52993 100644 (file)
@@ -335,7 +335,7 @@ unsigned DIArray::getNumElements() const {
 
 /// replaceAllUsesWith - Replace all uses of the MDNode used by this
 /// type with the one in the passed descriptor.
-void DIType::replaceAllUsesWith(DIDescriptor &D) {
+void DIType::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) {
 
   assert(DbgNode && "Trying to replace an unverified type!");
 
@@ -344,13 +344,19 @@ void DIType::replaceAllUsesWith(DIDescriptor &D) {
   // which, due to uniquing, has merged with the source. We shield clients from
   // this detail by allowing a value to be replaced with replaceAllUsesWith()
   // itself.
-  if (DbgNode != D) {
-    MDNode *Node = const_cast<MDNode *>(DbgNode);
-    const MDNode *DN = D;
-    const Value *V = cast_or_null<Value>(DN);
-    Node->replaceAllUsesWith(const_cast<Value *>(V));
-    MDNode::deleteTemporary(Node);
+  const MDNode *DN = D;
+  if (DbgNode == DN) {
+    SmallVector<Value*, 10> Ops(DbgNode->getNumOperands());
+    for (size_t i = 0; i != Ops.size(); ++i)
+      Ops[i] = DbgNode->getOperand(i);
+    DN = MDNode::get(VMContext, Ops);
   }
+
+  MDNode *Node = const_cast<MDNode *>(DbgNode);
+  const Value *V = cast_or_null<Value>(DN);
+  Node->replaceAllUsesWith(const_cast<Value *>(V));
+  MDNode::deleteTemporary(Node);
+  DbgNode = D;
 }
 
 /// replaceAllUsesWith - Replace all uses of the MDNode used by this
@@ -358,19 +364,12 @@ void DIType::replaceAllUsesWith(DIDescriptor &D) {
 void DIType::replaceAllUsesWith(MDNode *D) {
 
   assert(DbgNode && "Trying to replace an unverified type!");
-
-  // Since we use a TrackingVH for the node, its easy for clients to manufacture
-  // legitimate situations where they want to replaceAllUsesWith() on something
-  // which, due to uniquing, has merged with the source. We shield clients from
-  // this detail by allowing a value to be replaced with replaceAllUsesWith()
-  // itself.
-  if (DbgNode != D) {
-    MDNode *Node = const_cast<MDNode *>(DbgNode);
-    const MDNode *DN = D;
-    const Value *V = cast_or_null<Value>(DN);
-    Node->replaceAllUsesWith(const_cast<Value *>(V));
-    MDNode::deleteTemporary(Node);
-  }
+  assert(DbgNode != D && "This replacement should always happen");
+  MDNode *Node = const_cast<MDNode *>(DbgNode);
+  const MDNode *DN = D;
+  const Value *V = cast_or_null<Value>(DN);
+  Node->replaceAllUsesWith(const_cast<Value *>(V));
+  MDNode::deleteTemporary(Node);
 }
 
 /// Verify - Verify that a compile unit is well formed.