forked from OSchip/llvm-project
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
This commit is contained in:
parent
9db79f17c0
commit
d253ed6565
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -11,6 +11,10 @@ void f1(int) { }
|
|||
struct foo;
|
||||
struct bar { };
|
||||
typedef bar baz;
|
||||
extern int var_decl;
|
||||
void func_decl(void);
|
||||
extern int var_fwd;
|
||||
void func_fwd(void);
|
||||
}
|
||||
}
|
||||
namespace A {
|
||||
|
@ -33,12 +37,20 @@ int func(bool b) {
|
|||
using B::baz;
|
||||
namespace X = A;
|
||||
namespace Y = X;
|
||||
using B::var_decl;
|
||||
using B::func_decl;
|
||||
using B::var_fwd;
|
||||
using B::func_fwd;
|
||||
return i + X::B::i + Y::B::i;
|
||||
}
|
||||
|
||||
namespace A {
|
||||
using B::i;
|
||||
namespace B {
|
||||
int var_fwd = i;
|
||||
}
|
||||
}
|
||||
void B::func_fwd() {}
|
||||
|
||||
// This should work even if 'i' and 'func' were declarations & not definitions,
|
||||
// but it doesn't yet.
|
||||
|
@ -53,16 +65,19 @@ using B::i;
|
|||
// CHECK: [[F1:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] [line 4] [def] [f1]
|
||||
// CHECK: [[FILE2]]} ; [ DW_TAG_file_type ] [{{.*}}foo.cpp]
|
||||
// CHECK: [[FUNC:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func]
|
||||
// CHECK: [[FUNC_FWD:![0-9]*]] {{.*}} [ DW_TAG_subprogram ] [line 47] [def] [func_fwd]
|
||||
// CHECK: [[I:![0-9]*]] = metadata !{metadata !"0x34\00i\00{{.*}}", metadata [[NS]], {{.*}} ; [ DW_TAG_variable ] [i]
|
||||
// CHECK: [[MODULES]] = metadata !{metadata [[M1:![0-9]*]], metadata [[M2:![0-9]*]], metadata [[M3:![0-9]*]], metadata [[M4:![0-9]*]], metadata [[M5:![0-9]*]], metadata [[M6:![0-9]*]], metadata [[M7:![0-9]*]], metadata [[M8:![0-9]*]], metadata [[M9:![0-9]*]], metadata [[M10:![0-9]*]], metadata [[M11:![0-9]*]], metadata [[M12:![0-9]*]], metadata [[M13:![0-9]*]]}
|
||||
// CHECK: [[M1]] = metadata !{metadata !"0x3a\0011\00", metadata [[CTXT]], metadata [[NS]]} ; [ DW_TAG_imported_module ]
|
||||
// CHECK: [[VAR_FWD:![0-9]*]] = metadata !{metadata !"0x34\00var_fwd\00{{.*}}", metadata [[NS]], {{.*}}} ; [ DW_TAG_variable ] [var_fwd] [line 44] [def]
|
||||
|
||||
// CHECK: [[MODULES]] = metadata !{metadata [[M1:![0-9]*]], metadata [[M2:![0-9]*]], metadata [[M3:![0-9]*]], metadata [[M4:![0-9]*]], metadata [[M5:![0-9]*]], metadata [[M6:![0-9]*]], metadata [[M7:![0-9]*]], metadata [[M8:![0-9]*]], metadata [[M9:![0-9]*]], metadata [[M10:![0-9]*]], metadata [[M11:![0-9]*]], metadata [[M12:![0-9]*]], metadata [[M13:![0-9]*]], metadata [[M14:![0-9]*]], metadata [[M15:![0-9]*]], metadata [[M16:![0-9]*]], metadata [[M17:![0-9]*]]}
|
||||
// CHECK: [[M1]] = metadata !{metadata !"0x3a\0015\00", metadata [[CTXT]], metadata [[NS]]} ; [ DW_TAG_imported_module ]
|
||||
// CHECK: [[M2]] = metadata !{metadata !"0x3a\00{{[0-9]+}}\00", metadata [[CU]], metadata [[CTXT]]} ; [ DW_TAG_imported_module ]
|
||||
// CHECK: [[M3]] = metadata !{metadata !"0x8\0015\00E", metadata [[CU]], metadata [[CTXT]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK: [[M4]] = metadata !{metadata !"0x3a\0019\00", metadata [[LEX2:![0-9]*]], metadata [[NS]]} ; [ DW_TAG_imported_module ]
|
||||
// CHECK: [[M3]] = metadata !{metadata !"0x8\0019\00E", metadata [[CU]], metadata [[CTXT]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK: [[M4]] = metadata !{metadata !"0x3a\0023\00", metadata [[LEX2:![0-9]*]], metadata [[NS]]} ; [ DW_TAG_imported_module ]
|
||||
// CHECK: [[LEX2]] = metadata !{metadata !"0xb\00{{[0-9]*}}\000\00{{.*}}", metadata [[FILE2]], metadata [[LEX1:![0-9]+]]} ; [ DW_TAG_lexical_block ]
|
||||
// CHECK: [[LEX1]] = metadata !{metadata !"0xb\00{{[0-9]*}}\000\00{{.*}}", metadata [[FILE2]], metadata [[FUNC]]} ; [ DW_TAG_lexical_block ]
|
||||
// CHECK: [[M5]] = metadata !{metadata !"0x3a\00{{[0-9]+}}\00", metadata [[FUNC]], metadata [[CTXT]]} ; [ DW_TAG_imported_module ]
|
||||
// CHECK: [[M6]] = metadata !{metadata !"0x8\0023\00", metadata [[FUNC]], metadata [[FOO:!"_ZTSN1A1B3fooE"]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK: [[M6]] = metadata !{metadata !"0x8\0027\00", metadata [[FUNC]], metadata [[FOO:!"_ZTSN1A1B3fooE"]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK: [[M7]] = metadata !{metadata !"0x8\00{{[0-9]+}}\00", metadata [[FUNC]], metadata [[BAR:!"_ZTSN1A1B3barE"]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK: [[M8]] = metadata !{metadata !"0x8\00{{[0-9]+}}\00", metadata [[FUNC]], metadata [[F1]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK: [[M9]] = metadata !{metadata !"0x8\00{{[0-9]+}}\00", metadata [[FUNC]], metadata [[I]]} ; [ DW_TAG_imported_declaration ]
|
||||
|
@ -70,8 +85,13 @@ using B::i;
|
|||
// CHECK: [[BAZ]] = metadata !{metadata !"0x16\00baz\00{{.*}}", metadata [[FOOCPP]], metadata [[NS]], metadata !"_ZTSN1A1B3barE"} ; [ DW_TAG_typedef ] [baz] {{.*}} [from _ZTSN1A1B3barE]
|
||||
// CHECK: [[M11]] = metadata !{metadata !"0x8\00{{[0-9]+}}\00X", metadata [[FUNC]], metadata [[CTXT]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK: [[M12]] = metadata !{metadata !"0x8\00{{[0-9]+}}\00Y", metadata [[FUNC]], metadata [[M11]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK: [[M13]] = metadata !{metadata !"0x8\00{{[0-9]+}}\00", metadata [[CTXT]], metadata [[I]]} ; [ DW_TAG_imported_declaration ]
|
||||
|
||||
// CHECK: [[M13]] = metadata !{metadata !"0x8\00{{[0-9]+}}\00", metadata [[FUNC]], metadata [[VAR_DECL:![0-9]*]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK [[VAR_DECL]] = metadata !{metadata !"0x34\00var_decl\00{{.*}}", metadata [[NS]], {{.*}}} ; [ DW_TAG_variable ] [var_decl] [line 8]
|
||||
// CHECK: [[M14]] = metadata !{metadata !"0x8\00{{[0-9]+}}\00", metadata [[FUNC]], metadata [[FUNC_DECL:![0-9]*]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK: [[FUNC_DECL]] = metadata !{metadata !"0x2e\00func_decl\00{{.*}}", metadata [[FOOCPP]], metadata [[NS]], {{.*}}} ; [ DW_TAG_subprogram ] [line 9] [scope 0] [func_decl]
|
||||
// CHECK: [[M15]] = metadata !{metadata !"0x8\00{{[0-9]+}}\00", metadata [[FUNC]], metadata [[VAR_FWD:![0-9]*]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK: [[M16]] = metadata !{metadata !"0x8\00{{[0-9]+}}\00", metadata [[FUNC]], metadata [[FUNC_FWD:![0-9]*]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK: [[M17]] = metadata !{metadata !"0x8\00{{[0-9]+}}\00", metadata [[CTXT]], metadata [[I]]} ; [ DW_TAG_imported_declaration ]
|
||||
// CHECK-GMLT: [[CU:![0-9]*]] = metadata !{metadata !"0x11\00{{.*}}\002"{{.*}}, metadata [[MODULES:![0-9]*]]} ; [ DW_TAG_compile_unit ]
|
||||
// CHECK-GMLT: [[MODULES]] = metadata !{}
|
||||
|
||||
|
|
Loading…
Reference in New Issue