From: Duncan P. N. Exon Smith Date: Thu, 18 Dec 2014 00:46:16 +0000 (+0000) Subject: IR: Handle self-referencing DICompositeTypes in DIBuilder X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a582f1f3967dcfca0adcb976af3b867e75c54e99;p=llvm IR: Handle self-referencing DICompositeTypes in DIBuilder Add API to DIBuilder to handle self-referencing `DICompositeType`s. Self-references aren't expected in the debug info graph, and we take advantage of that by only calling `resolveCycles()` on nodes that were once forward declarations (otherwise, DIBuilder needs an expensive tracking reference to every unresolved node it creates, which in cyclic graphs is *all of them*). However, clang seems to create self-referencing `DICompositeType`s. Add API to manage this safely. The paired commit to clang will include the regression test. I'll make the `DICompositeType` API `private` in a follow-up to prevent misuse (I've separated that to prevent build failures from missing the clang commit). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224482 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 859bd52bda5..5482de87d6c 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -698,6 +698,20 @@ namespace llvm { Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, DIVariable VarInfo, DIExpression Expr, Instruction *InsertBefore); + + /// \brief Replace the vtable holder in the given composite type. + /// + /// If this creates a self reference, it may orphan some unresolved cycles + /// in the operands of \c T, so \a DIBuilder needs to track that. + void replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder); + + /// \brief Replace arrays on a composite type. + /// + /// If \c T is resolved, but the arrays aren't -- which can happen if \c T + /// has a self-reference -- \a DIBuilder needs to track the array to + /// resolve cycles. + void replaceArrays(DICompositeType &T, DIArray Elements, + DIArray TParems = DIArray()); }; } // end namespace llvm diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index ee7e6a2b21b..1874d31e0a5 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -1205,3 +1205,35 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, MetadataAsValue::get(VMContext, Expr)}; return CallInst::Create(ValueFn, Args, "", InsertAtEnd); } + +void DIBuilder::replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder) { + T.setContainingType(VTableHolder); + + // If this didn't create a self-reference, just return. + if (T != VTableHolder) + return; + + // Look for unresolved operands. T has dropped RAUW support and is already + // marked resolved, orphaning any cycles underneath it. + assert(T->isResolved() && "Expected self-reference to be resolved"); + for (const MDOperand &O : T->operands()) + if (auto *N = dyn_cast_or_null(O)) + trackIfUnresolved(N); +} + +void DIBuilder::replaceArrays(DICompositeType &T, DIArray Elements, + DIArray TParams) { + T.setArrays(Elements, TParams); + + // If T isn't resolved, there's no problem. + if (!T->isResolved()) + return; + + // If "T" is resolved, it may be due to a self-reference cycle. Track the + // arrays explicitly if they're unresolved, or else the cycles will be + // orphaned. + if (Elements) + trackIfUnresolved(Elements); + if (TParams) + trackIfUnresolved(TParams); +}