diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -152,8 +152,10 @@ llvm::DenseMap DIFileCache; llvm::DenseMap SPCache; /// Cache declarations relevant to DW_TAG_imported_declarations (C++ - /// using declarations) that aren't covered by other more specific caches. + /// using declarations and global alias variables) that aren't covered + /// by other more specific caches. llvm::DenseMap DeclCache; + llvm::DenseMap ImportedDeclCache; llvm::DenseMap NamespaceCache; llvm::DenseMap NamespaceAliasCache; @@ -512,6 +514,9 @@ /// Emit information about an external variable. void EmitExternalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl); + /// Emit information about global variable alias. + void EmitGlobalAlias(const llvm::GlobalValue *GV, const GlobalDecl Decl); + /// Emit C++ using directive. void EmitUsingDirective(const UsingDirectiveDecl &UD); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -3911,6 +3911,17 @@ return dyn_cast_or_null(N); } + // Search imported declaration cache if it is already defined + // as imported declaration. + auto IE = ImportedDeclCache.find(D->getCanonicalDecl()); + + if (IE != ImportedDeclCache.end()) { + auto N = IE->second; + if (auto *GVE = dyn_cast_or_null(N)) + return cast(GVE); + return dyn_cast_or_null(N); + } + // No definition for now. Emit a forward definition that might be // merged with a potential upcoming definition. if (const auto *FD = dyn_cast(D)) @@ -5467,6 +5478,47 @@ Var->addDebugInfo(GVE); } +void CGDebugInfo::EmitGlobalAlias(const llvm::GlobalValue *GV, + const GlobalDecl GD) { + + assert(GV); + + if (!CGM.getCodeGenOpts().hasReducedDebugInfo()) + return; + + const auto *D = cast(GD.getDecl()); + if (D->hasAttr()) + return; + + auto AliaseeDecl = CGM.getMangledNameDecl(GV->getName()); + llvm::DINode *DI; + + if (!AliaseeDecl) + // FIXME: Aliasee not declared yet - possibly declared later + // For example, + // + // 1 extern int newname __attribute__((alias("oldname"))); + // 2 int oldname = 1; + // + // No debug info would be generated for 'newname' in this case. + // + // Fix compiler to generate "newname" as imported_declaration + // pointing to the DIE of "oldname". + return; + else if (!(DI = getDeclarationOrDefinition( + AliaseeDecl.getCanonicalDecl().getDecl()))) + return; + + llvm::DIScope *DContext = getDeclContextDescriptor(D); + auto Loc = D->getLocation(); + + llvm::DIImportedEntity *ImportDI = DBuilder.createImportedDeclaration( + DContext, DI, getOrCreateFile(Loc), getLineNumber(Loc), D->getName()); + + // Record this DIE in the cache for nested declaration reference + ImportedDeclCache[GD.getCanonicalDecl().getDecl()].reset(ImportDI); +} + llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) { if (!LexicalBlockStack.empty()) return LexicalBlockStack.back(); diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1213,6 +1213,7 @@ StringRef getMangledName(GlobalDecl GD); StringRef getBlockMangledName(GlobalDecl GD, const BlockDecl *BD); + const GlobalDecl getMangledNameDecl(StringRef); void EmitTentativeDefinition(const VarDecl *D); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1498,6 +1498,16 @@ return Result.first->first(); } +const GlobalDecl CodeGenModule::getMangledNameDecl(StringRef Name) { + auto it = MangledDeclNames.begin(); + while (it != MangledDeclNames.end()) { + if (it->second == Name) + return it->first; + it++; + } + return GlobalDecl(); +} + llvm::GlobalValue *CodeGenModule::GetGlobalValue(StringRef Name) { return getModule().getNamedValue(Name); } @@ -5164,6 +5174,13 @@ setTLSMode(GA, *VD); SetCommonAttributes(GD, GA); + + // Emit global alias debug information. + if (const auto *VD = dyn_cast(D)) { + if (CGDebugInfo *DI = getModuleDebugInfo()) { + DI->EmitGlobalAlias(cast(GA->getAliasee()), GD); + } + } } void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) { diff --git a/clang/test/CodeGen/debug-info-alias.c b/clang/test/CodeGen/debug-info-alias.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/debug-info-alias.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s + +// CHECK-DAG: [[ENTITY1:![0-9]+]] = distinct !DIGlobalVariable(name: "aliased_global" +// CHECK-DAG: [[ENTITY2:![0-9]+]] = distinct !DIGlobalVariable(name: "aliased_global_2" +// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "__global_alias", scope: !2, entity: [[ENTITY1]] +// CHECK-DAG: [[ENTITY3:![0-9]+]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "global_alias_2", scope: !2, entity: [[ENTITY2]] +// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "__global_alias_2_alias", scope: !2, entity: [[ENTITY3]] + +int aliased_global = 1; +extern int __attribute__((alias("aliased_global"))) __global_alias; + +// Recursive alias: +int aliased_global_2 = 2; +extern int __attribute__((alias("aliased_global_2"))) global_alias_2; +extern int __attribute__((alias("global_alias_2"))) __global_alias_2_alias;