summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorFrederic Riss <friss@apple.com>2014-11-18 03:40:51 +0000
committerFrederic Riss <friss@apple.com>2014-11-18 03:40:51 +0000
commitd253ed6565dff2415d4cd923b80ee82ca6ee5534 (patch)
tree9319e5ff10063c87897dc8ebaaafaf71994a0227 /clang/lib/CodeGen
parent9db79f17c09c6f73f2595c4a8adf312c4c769f57 (diff)
downloadbcm5719-llvm-d253ed6565dff2415d4cd923b80ee82ca6ee5534.tar.gz
bcm5719-llvm-d253ed6565dff2415d4cd923b80ee82ca6ee5534.zip
Fully handle globals and functions in CGDebugInfo::getDeclarationOrDefinition()
Currently this function would return nothing for functions or globals that haven't seen a definition yet. Make it return a forward declaration that will get RAUWed with the definition if one is seen at a later point. The strategy used to implement this is similar to what's done for types: the forward declarations are stored in a vector and post processed upon finilization to perform the required RAUWs. For now the only user of getDeclarationOrDefinition() is EmitUsingDecl(), thus this patch allows to emit correct imported declarations even in the absence of an actual definition of the imported entity. (Another user will be the debug info generation for argument default values that I need to resurect). Differential Revision: http://reviews.llvm.org/D6173 llvm-svn: 222220
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp94
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.h12
2 files changed, 95 insertions, 11 deletions
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 8ba69eaa5c5..b2a3f7e0e98 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2374,6 +2374,58 @@ void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile &Unit,
: VD->getDeclContext()));
}
+llvm::DISubprogram
+CGDebugInfo::getFunctionForwardDeclaration(const FunctionDecl *FD) {
+ llvm::DIArray TParamsArray;
+ StringRef Name, LinkageName;
+ unsigned Flags = 0;
+ SourceLocation Loc = FD->getLocation();
+ llvm::DIFile Unit = getOrCreateFile(Loc);
+ llvm::DIDescriptor DContext(Unit);
+ unsigned Line = getLineNumber(Loc);
+
+ collectFunctionDeclProps(FD, Unit, Name, LinkageName, DContext,
+ TParamsArray, Flags);
+ // Build function type.
+ SmallVector<QualType, 16> ArgTypes;
+ for (const ParmVarDecl *Parm: FD->parameters())
+ ArgTypes.push_back(Parm->getType());
+ QualType FnType =
+ CGM.getContext().getFunctionType(FD->getReturnType(), ArgTypes,
+ FunctionProtoType::ExtProtoInfo());
+ llvm::DISubprogram SP =
+ DBuilder.createTempFunctionFwdDecl(DContext, Name, LinkageName, Unit, Line,
+ getOrCreateFunctionType(FD, FnType, Unit),
+ !FD->isExternallyVisible(),
+ false /*declaration*/, 0, Flags,
+ CGM.getLangOpts().Optimize, nullptr,
+ TParamsArray, getFunctionDeclaration(FD));
+ const FunctionDecl *CanonDecl = cast<FunctionDecl>(FD->getCanonicalDecl());
+ FwdDeclReplaceMap.push_back(std::make_pair(CanonDecl,
+ static_cast<llvm::Value *>(SP)));
+ return SP;
+}
+
+llvm::DIGlobalVariable
+CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) {
+ QualType T;
+ StringRef Name, LinkageName;
+ SourceLocation Loc = VD->getLocation();
+ llvm::DIFile Unit = getOrCreateFile(Loc);
+ llvm::DIDescriptor DContext(Unit);
+ unsigned Line = getLineNumber(Loc);
+
+ collectVarDeclProps(VD, Unit, Line, T, Name, LinkageName, DContext);
+ llvm::DIGlobalVariable GV =
+ DBuilder.createTempGlobalVariableFwdDecl(DContext, Name, LinkageName, Unit,
+ Line, getOrCreateType(T, Unit),
+ !VD->isExternallyVisible(),
+ nullptr, nullptr);
+ FwdDeclReplaceMap.push_back(std::make_pair(cast<VarDecl>(VD->getCanonicalDecl()),
+ static_cast<llvm::Value *>(GV)));
+ return GV;
+}
+
llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
// We only need a declaration (not a definition) of the type - so use whatever
// we would otherwise do to get a type for a pointee. (forward declarations in
@@ -2382,19 +2434,22 @@ llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
return getOrCreateType(CGM.getContext().getTypeDeclType(TD),
getOrCreateFile(TD->getLocation()));
- // Otherwise fall back to a fairly rudimentary cache of existing declarations.
- // This doesn't handle providing declarations (for functions or variables) for
- // entities without definitions in this TU, nor when the definition proceeds
- // the call to this function.
- // FIXME: This should be split out into more specific maps with support for
- // emitting forward declarations and merging definitions with declarations,
- // the same way as we do for types.
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator I =
DeclCache.find(D->getCanonicalDecl());
- if (I == DeclCache.end())
- return llvm::DIScope();
- llvm::Value *V = I->second;
- return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));
+
+ if (I != DeclCache.end()) {
+ llvm::Value *V = I->second;
+ return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));
+ }
+
+ // No definition for now. Emit a forward definition that might be
+ // merged with a potential upcoming definition.
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
+ return getFunctionForwardDeclaration(FD);
+ else if (const auto *VD = dyn_cast<VarDecl>(D))
+ return getGlobalVariableForwardDeclaration(VD);
+
+ return llvm::DIDescriptor();
}
/// getFunctionDeclaration - Return debug info descriptor to describe method
@@ -3330,6 +3385,23 @@ void CGDebugInfo::finalize() {
Ty.replaceAllUsesWith(CGM.getLLVMContext(), RepTy);
}
+ for (const auto &p : FwdDeclReplaceMap) {
+ assert(p.second);
+ llvm::DIDescriptor FwdDecl(cast<llvm::MDNode>(p.second));
+ llvm::WeakVH VH;
+
+ auto it = DeclCache.find(p.first);
+ // If there has been no definition for the declaration, call RAUV
+ // with ourselves, that will destroy the temporary MDNode and
+ // replace it with a standard one, avoiding leaking memory.
+ if (it == DeclCache.end())
+ VH = p.second;
+ else
+ VH = it->second;
+ FwdDecl.replaceAllUsesWith(CGM.getLLVMContext(),
+ llvm::DIDescriptor(cast<llvm::MDNode>(VH)));
+ }
+
// We keep our own list of retained types, because we need to look
// up the final type in the type cache.
for (std::vector<void *>::const_iterator RI = RetainedTypes.begin(),
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 896c54f13fd..49d99aac264 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -87,6 +87,10 @@ class CGDebugInfo {
/// compilation.
std::vector<std::pair<const TagType *, llvm::WeakVH>> ReplaceMap;
+ /// \brief Cache of replaceable forward declarartions (functions and
+ /// variables) to RAUW at the end of compilation.
+ std::vector<std::pair<const DeclaratorDecl *, llvm::WeakVH>> FwdDeclReplaceMap;
+
// LexicalBlockStack - Keep track of our current nested lexical block.
std::vector<llvm::TrackingVH<llvm::MDNode> > LexicalBlockStack;
llvm::DenseMap<const Decl *, llvm::WeakVH> RegionMap;
@@ -376,6 +380,14 @@ private:
llvm::DIDerivedType
getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D);
+ /// \brief Create a DISubprogram describing the forward
+ /// decalration represented in the given FunctionDecl.
+ llvm::DISubprogram getFunctionForwardDeclaration(const FunctionDecl *FD);
+
+ /// \brief Create a DIGlobalVariable describing the forward
+ /// decalration represented in the given VarDecl.
+ llvm::DIGlobalVariable getGlobalVariableForwardDeclaration(const VarDecl *VD);
+
/// Return a global variable that represents one of the collection of
/// global variables created for an anonmyous union.
llvm::DIGlobalVariable
OpenPOWER on IntegriCloud