PR19598: Provide the ability to RAUW a declaration with itself, creating a non-temporary copy and using that to RAUW.

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
This commit is contained in:
David Blaikie 2014-05-06 03:41:57 +00:00
parent 5c34f99911
commit 40a1b74db6
4 changed files with 61 additions and 22 deletions

View File

@ -434,7 +434,7 @@ namespace llvm {
/// flag set. /// flag set.
DIType createObjectPointerType(DIType Ty); DIType createObjectPointerType(DIType Ty);
/// createForwardDecl - Create a temporary forward-declared type. /// \brief Create a permanent forward-declared type.
DICompositeType createForwardDecl(unsigned Tag, StringRef Name, DICompositeType createForwardDecl(unsigned Tag, StringRef Name,
DIDescriptor Scope, DIFile F, DIDescriptor Scope, DIFile F,
unsigned Line, unsigned RuntimeLang = 0, unsigned Line, unsigned RuntimeLang = 0,
@ -442,6 +442,12 @@ namespace llvm {
uint64_t AlignInBits = 0, uint64_t AlignInBits = 0,
StringRef UniqueIdentifier = StringRef()); 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 /// retainType - Retain DIType in a module even if it is not referenced
/// through debug info anchors. /// through debug info anchors.
void retainType(DIType T); void retainType(DIType T);

View File

@ -339,7 +339,7 @@ public:
/// replaceAllUsesWith - Replace all uses of debug info referenced by /// replaceAllUsesWith - Replace all uses of debug info referenced by
/// this descriptor. /// this descriptor.
void replaceAllUsesWith(DIDescriptor &D); void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D);
void replaceAllUsesWith(MDNode *D); void replaceAllUsesWith(MDNode *D);
}; };

View File

@ -901,6 +901,40 @@ DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope,
UniqueIdentifier.empty() ? nullptr UniqueIdentifier.empty() ? nullptr
: MDString::get(VMContext, UniqueIdentifier) : 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); MDNode *Node = MDNode::getTemporary(VMContext, Elts);
DICompositeType RetTy(Node); DICompositeType RetTy(Node);
assert(RetTy.isCompositeType() && assert(RetTy.isCompositeType() &&

View File

@ -335,7 +335,7 @@ unsigned DIArray::getNumElements() const {
/// replaceAllUsesWith - Replace all uses of the MDNode used by this /// replaceAllUsesWith - Replace all uses of the MDNode used by this
/// type with the one in the passed descriptor. /// 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!"); 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 // which, due to uniquing, has merged with the source. We shield clients from
// this detail by allowing a value to be replaced with replaceAllUsesWith() // this detail by allowing a value to be replaced with replaceAllUsesWith()
// itself. // itself.
if (DbgNode != D) { const MDNode *DN = D;
MDNode *Node = const_cast<MDNode *>(DbgNode); if (DbgNode == DN) {
const MDNode *DN = D; SmallVector<Value*, 10> Ops(DbgNode->getNumOperands());
const Value *V = cast_or_null<Value>(DN); for (size_t i = 0; i != Ops.size(); ++i)
Node->replaceAllUsesWith(const_cast<Value *>(V)); Ops[i] = DbgNode->getOperand(i);
MDNode::deleteTemporary(Node); 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 /// replaceAllUsesWith - Replace all uses of the MDNode used by this
@ -358,19 +364,12 @@ void DIType::replaceAllUsesWith(DIDescriptor &D) {
void DIType::replaceAllUsesWith(MDNode *D) { void DIType::replaceAllUsesWith(MDNode *D) {
assert(DbgNode && "Trying to replace an unverified type!"); assert(DbgNode && "Trying to replace an unverified type!");
assert(DbgNode != D && "This replacement should always happen");
// Since we use a TrackingVH for the node, its easy for clients to manufacture MDNode *Node = const_cast<MDNode *>(DbgNode);
// legitimate situations where they want to replaceAllUsesWith() on something const MDNode *DN = D;
// which, due to uniquing, has merged with the source. We shield clients from const Value *V = cast_or_null<Value>(DN);
// this detail by allowing a value to be replaced with replaceAllUsesWith() Node->replaceAllUsesWith(const_cast<Value *>(V));
// itself. MDNode::deleteTemporary(Node);
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);
}
} }
/// Verify - Verify that a compile unit is well formed. /// Verify - Verify that a compile unit is well formed.