summaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGDebugInfo.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
commit2298981669bf3bd63335a4be179bc0f96823a8f4 (patch)
tree1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /lib/CodeGen/CGDebugInfo.cpp
parent9a83721404652cea39e9f02ae3e3b5c964602a5c (diff)
Notes
Diffstat (limited to 'lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp417
1 files changed, 325 insertions, 92 deletions
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 41f8721468a3..f6ee7ee26d4b 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1,9 +1,8 @@
//===--- CGDebugInfo.cpp - Emit Debug Information for a Module ------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -19,6 +18,7 @@
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "ConstantEmitter.h"
+#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
@@ -373,7 +373,7 @@ CGDebugInfo::computeChecksum(FileID FID, SmallString<32> &Checksum) const {
SourceManager &SM = CGM.getContext().getSourceManager();
bool Invalid;
- llvm::MemoryBuffer *MemBuffer = SM.getBuffer(FID, &Invalid);
+ const llvm::MemoryBuffer *MemBuffer = SM.getBuffer(FID, &Invalid);
if (Invalid)
return None;
@@ -423,8 +423,12 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
}
SmallString<32> Checksum;
+
+ // Compute the checksum if possible. If the location is affected by a #line
+ // directive that refers to a file, PLoc will have an invalid FileID, and we
+ // will correctly get no checksum.
Optional<llvm::DIFile::ChecksumKind> CSKind =
- computeChecksum(SM.getFileID(Loc), Checksum);
+ computeChecksum(PLoc.getFileID(), Checksum);
Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo;
if (CSKind)
CSInfo.emplace(*CSKind, Checksum);
@@ -451,8 +455,8 @@ CGDebugInfo::createFile(StringRef FileName,
for (; CurDirIt != CurDirE && *CurDirIt == *FileIt; ++CurDirIt, ++FileIt)
llvm::sys::path::append(DirBuf, *CurDirIt);
if (std::distance(llvm::sys::path::begin(CurDir), CurDirIt) == 1) {
- // The common prefix only the root; stripping it would cause
- // LLVM diagnostic locations to be more confusing.
+ // Don't strip the common prefix if it is only the root "/"
+ // since that would make LLVM diagnostic locations confusing.
Dir = {};
File = RemappedFile;
} else {
@@ -610,12 +614,8 @@ void CGDebugInfo::CreateCompileUnit() {
TheCU = DBuilder.createCompileUnit(
LangTag, CUFile, CGOpts.EmitVersionIdentMetadata ? Producer : "",
LO.Optimize || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO,
- CGOpts.DwarfDebugFlags, RuntimeVers,
- (CGOpts.getSplitDwarfMode() != CodeGenOptions::NoFission)
- ? ""
- : CGOpts.SplitDwarfFile,
- EmissionKind, DwoId, CGOpts.SplitDwarfInlining,
- CGOpts.DebugInfoForProfiling,
+ CGOpts.DwarfDebugFlags, RuntimeVers, CGOpts.SplitDwarfFile, EmissionKind,
+ DwoId, CGOpts.SplitDwarfInlining, CGOpts.DebugInfoForProfiling,
CGM.getTarget().getTriple().isNVPTX()
? llvm::DICompileUnit::DebugNameTableKind::None
: static_cast<llvm::DICompileUnit::DebugNameTableKind>(
@@ -916,6 +916,11 @@ static SmallString<256> getTypeIdentifier(const TagType *Ty, CodeGenModule &CGM,
if (!needsTypeIdentifier(TD, CGM, TheCU))
return Identifier;
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(TD))
+ if (RD->getDefinition())
+ if (RD->isDynamicClass() &&
+ CGM.getVTableLinkage(RD) == llvm::GlobalValue::ExternalLinkage)
+ return Identifier;
// TODO: This is using the RTTI name. Is there a better way to get
// a unique string for a type?
@@ -1083,15 +1088,18 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
assert(Ty->isTypeAlias());
llvm::DIType *Src = getOrCreateType(Ty->getAliasedType(), Unit);
+ auto *AliasDecl =
+ cast<TypeAliasTemplateDecl>(Ty->getTemplateName().getAsTemplateDecl())
+ ->getTemplatedDecl();
+
+ if (AliasDecl->hasAttr<NoDebugAttr>())
+ return Src;
+
SmallString<128> NS;
llvm::raw_svector_ostream OS(NS);
Ty->getTemplateName().print(OS, getPrintingPolicy(), /*qualified*/ false);
printTemplateArgumentList(OS, Ty->template_arguments(), getPrintingPolicy());
- auto *AliasDecl =
- cast<TypeAliasTemplateDecl>(Ty->getTemplateName().getAsTemplateDecl())
- ->getTemplatedDecl();
-
SourceLocation Loc = AliasDecl->getLocation();
return DBuilder.createTypedef(Src, OS.str(), getOrCreateFile(Loc),
getLineNumber(Loc),
@@ -1100,15 +1108,20 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
llvm::DIType *CGDebugInfo::CreateType(const TypedefType *Ty,
llvm::DIFile *Unit) {
+ llvm::DIType *Underlying =
+ getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
+
+ if (Ty->getDecl()->hasAttr<NoDebugAttr>())
+ return Underlying;
+
// We don't set size information, but do specify where the typedef was
// declared.
SourceLocation Loc = Ty->getDecl()->getLocation();
// Typedefs are derived from some other type.
- return DBuilder.createTypedef(
- getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit),
- Ty->getDecl()->getName(), getOrCreateFile(Loc), getLineNumber(Loc),
- getDeclContextDescriptor(Ty->getDecl()));
+ return DBuilder.createTypedef(Underlying, Ty->getDecl()->getName(),
+ getOrCreateFile(Loc), getLineNumber(Loc),
+ getDeclContextDescriptor(Ty->getDecl()));
}
static unsigned getDwarfCC(CallingConv CC) {
@@ -1394,6 +1407,9 @@ void CGDebugInfo::CollectRecordFields(
isa<VarTemplateSpecializationDecl>(V))
continue;
+ if (isa<VarTemplatePartialSpecializationDecl>(V))
+ continue;
+
// Reuse the existing static member declaration if one exists
auto MI = StaticDataMemberCache.find(V->getCanonicalDecl());
if (MI != StaticDataMemberCache.end()) {
@@ -1726,31 +1742,37 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
QualType T = TA.getParamTypeForDecl().getDesugaredType(CGM.getContext());
llvm::DIType *TTy = getOrCreateType(T, Unit);
llvm::Constant *V = nullptr;
- const CXXMethodDecl *MD;
- // Variable pointer template parameters have a value that is the address
- // of the variable.
- if (const auto *VD = dyn_cast<VarDecl>(D))
- V = CGM.GetAddrOfGlobalVar(VD);
- // Member function pointers have special support for building them, though
- // this is currently unsupported in LLVM CodeGen.
- else if ((MD = dyn_cast<CXXMethodDecl>(D)) && MD->isInstance())
- V = CGM.getCXXABI().EmitMemberFunctionPointer(MD);
- else if (const auto *FD = dyn_cast<FunctionDecl>(D))
- V = CGM.GetAddrOfFunction(FD);
- // Member data pointers have special handling too to compute the fixed
- // offset within the object.
- else if (const auto *MPT = dyn_cast<MemberPointerType>(T.getTypePtr())) {
- // These five lines (& possibly the above member function pointer
- // handling) might be able to be refactored to use similar code in
- // CodeGenModule::getMemberPointerConstant
- uint64_t fieldOffset = CGM.getContext().getFieldOffset(D);
- CharUnits chars =
- CGM.getContext().toCharUnitsFromBits((int64_t)fieldOffset);
- V = CGM.getCXXABI().EmitMemberDataPointer(MPT, chars);
+ // Skip retrieve the value if that template parameter has cuda device
+ // attribute, i.e. that value is not available at the host side.
+ if (!CGM.getLangOpts().CUDA || CGM.getLangOpts().CUDAIsDevice ||
+ !D->hasAttr<CUDADeviceAttr>()) {
+ const CXXMethodDecl *MD;
+ // Variable pointer template parameters have a value that is the address
+ // of the variable.
+ if (const auto *VD = dyn_cast<VarDecl>(D))
+ V = CGM.GetAddrOfGlobalVar(VD);
+ // Member function pointers have special support for building them,
+ // though this is currently unsupported in LLVM CodeGen.
+ else if ((MD = dyn_cast<CXXMethodDecl>(D)) && MD->isInstance())
+ V = CGM.getCXXABI().EmitMemberFunctionPointer(MD);
+ else if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ V = CGM.GetAddrOfFunction(FD);
+ // Member data pointers have special handling too to compute the fixed
+ // offset within the object.
+ else if (const auto *MPT =
+ dyn_cast<MemberPointerType>(T.getTypePtr())) {
+ // These five lines (& possibly the above member function pointer
+ // handling) might be able to be refactored to use similar code in
+ // CodeGenModule::getMemberPointerConstant
+ uint64_t fieldOffset = CGM.getContext().getFieldOffset(D);
+ CharUnits chars =
+ CGM.getContext().toCharUnitsFromBits((int64_t)fieldOffset);
+ V = CGM.getCXXABI().EmitMemberDataPointer(MPT, chars);
+ }
+ V = V->stripPointerCasts();
}
TemplateParams.push_back(DBuilder.createTemplateValueParameter(
- TheCU, Name, TTy,
- cast_or_null<llvm::Constant>(V->stripPointerCasts())));
+ TheCU, Name, TTy, cast_or_null<llvm::Constant>(V)));
} break;
case TemplateArgument::NullPtr: {
QualType T = TA.getNullPtrType();
@@ -1817,32 +1839,24 @@ CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD,
}
llvm::DINodeArray CGDebugInfo::CollectVarTemplateParams(const VarDecl *VL,
- llvm::DIFile *Unit) {
- if (auto *TS = dyn_cast<VarTemplateSpecializationDecl>(VL)) {
- auto T = TS->getSpecializedTemplateOrPartial();
- auto TA = TS->getTemplateArgs().asArray();
- // Collect parameters for a partial specialization
- if (T.is<VarTemplatePartialSpecializationDecl *>()) {
- const TemplateParameterList *TList =
- T.get<VarTemplatePartialSpecializationDecl *>()
- ->getTemplateParameters();
- return CollectTemplateParams(TList, TA, Unit);
- }
-
- // Collect parameters for an explicit specialization
- if (T.is<VarTemplateDecl *>()) {
- const TemplateParameterList *TList = T.get<VarTemplateDecl *>()
- ->getTemplateParameters();
- return CollectTemplateParams(TList, TA, Unit);
- }
- }
- return llvm::DINodeArray();
+ llvm::DIFile *Unit) {
+ // Always get the full list of parameters, not just the ones from the
+ // specialization. A partial specialization may have fewer parameters than
+ // there are arguments.
+ auto *TS = dyn_cast<VarTemplateSpecializationDecl>(VL);
+ if (!TS)
+ return llvm::DINodeArray();
+ VarTemplateDecl *T = TS->getSpecializedTemplate();
+ const TemplateParameterList *TList = T->getTemplateParameters();
+ auto TA = TS->getTemplateArgs().asArray();
+ return CollectTemplateParams(TList, TA, Unit);
}
llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(
const ClassTemplateSpecializationDecl *TSpecial, llvm::DIFile *Unit) {
- // Always get the full list of parameters, not just the ones from
- // the specialization.
+ // Always get the full list of parameters, not just the ones from the
+ // specialization. A partial specialization may have fewer parameters than
+ // there are arguments.
TemplateParameterList *TPList =
TSpecial->getSpecializedTemplate()->getTemplateParameters();
const TemplateArgumentList &TAList = TSpecial->getTemplateArgs();
@@ -1875,6 +1889,58 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
return internString("_vptr$", RD->getNameAsString());
}
+StringRef CGDebugInfo::getDynamicInitializerName(const VarDecl *VD,
+ DynamicInitKind StubKind,
+ llvm::Function *InitFn) {
+ // If we're not emitting codeview, use the mangled name. For Itanium, this is
+ // arbitrary.
+ if (!CGM.getCodeGenOpts().EmitCodeView)
+ return InitFn->getName();
+
+ // Print the normal qualified name for the variable, then break off the last
+ // NNS, and add the appropriate other text. Clang always prints the global
+ // variable name without template arguments, so we can use rsplit("::") and
+ // then recombine the pieces.
+ SmallString<128> QualifiedGV;
+ StringRef Quals;
+ StringRef GVName;
+ {
+ llvm::raw_svector_ostream OS(QualifiedGV);
+ VD->printQualifiedName(OS, getPrintingPolicy());
+ std::tie(Quals, GVName) = OS.str().rsplit("::");
+ if (GVName.empty())
+ std::swap(Quals, GVName);
+ }
+
+ SmallString<128> InitName;
+ llvm::raw_svector_ostream OS(InitName);
+ if (!Quals.empty())
+ OS << Quals << "::";
+
+ switch (StubKind) {
+ case DynamicInitKind::NoStub:
+ llvm_unreachable("not an initializer");
+ case DynamicInitKind::Initializer:
+ OS << "`dynamic initializer for '";
+ break;
+ case DynamicInitKind::AtExit:
+ OS << "`dynamic atexit destructor for '";
+ break;
+ }
+
+ OS << GVName;
+
+ // Add any template specialization args.
+ if (const auto *VTpl = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
+ printTemplateArgumentList(OS, VTpl->getTemplateArgs().asArray(),
+ getPrintingPolicy());
+ }
+
+ OS << '\'';
+
+ return internString(OS.str());
+}
+
void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit,
SmallVectorImpl<llvm::Metadata *> &EltTys,
llvm::DICompositeType *RecordTy) {
@@ -1954,6 +2020,20 @@ llvm::DIType *CGDebugInfo::getOrCreateStandaloneType(QualType D,
return T;
}
+void CGDebugInfo::addHeapAllocSiteMetadata(llvm::Instruction *CI,
+ QualType D,
+ SourceLocation Loc) {
+ llvm::MDNode *node;
+ if (D.getTypePtr()->isVoidPointerType()) {
+ node = llvm::MDNode::get(CGM.getLLVMContext(), None);
+ } else {
+ QualType PointeeTy = D.getTypePtr()->getPointeeType();
+ node = getOrCreateType(PointeeTy, getOrCreateFile(Loc));
+ }
+
+ CI->setMetadata("heapallocsite", node);
+}
+
void CGDebugInfo::completeType(const EnumDecl *ED) {
if (DebugKind <= codegenoptions::DebugLineTablesOnly)
return;
@@ -2297,7 +2377,14 @@ CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod,
}
bool IsRootModule = M ? !M->Parent : true;
- if (CreateSkeletonCU && IsRootModule) {
+ // When a module name is specified as -fmodule-name, that module gets a
+ // clang::Module object, but it won't actually be built or imported; it will
+ // be textual.
+ if (CreateSkeletonCU && IsRootModule && Mod.getASTFile().empty() && M)
+ assert(StringRef(M->Name).startswith(CGM.getLangOpts().ModuleName) &&
+ "clang module without ASTFile must be specified by -fmodule-name");
+
+ if (CreateSkeletonCU && IsRootModule && !Mod.getASTFile().empty()) {
// PCH files don't have a signature field in the control block,
// but LLVM detects skeleton CUs by looking for a non-zero DWO id.
// We use the lower 64 bits for debug info.
@@ -2314,6 +2401,7 @@ CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod,
Signature);
DIB.finalize();
}
+
llvm::DIModule *Parent =
IsRootModule ? nullptr
: getOrCreateModuleRef(
@@ -2768,6 +2856,9 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
case Type::Paren:
T = cast<ParenType>(T)->getInnerType();
break;
+ case Type::MacroQualified:
+ T = cast<MacroQualifiedType>(T)->getUnderlyingType();
+ break;
case Type::SubstTemplateTypeParm:
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
break;
@@ -2947,6 +3038,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::DeducedTemplateSpecialization:
case Type::Elaborated:
case Type::Paren:
+ case Type::MacroQualified:
case Type::SubstTemplateTypeParm:
case Type::TypeOfExpr:
case Type::TypeOf:
@@ -3021,9 +3113,9 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
else
Flags |= llvm::DINode::FlagTypePassByValue;
- // Record if a C++ record is trivial type.
- if (CXXRD->isTrivial())
- Flags |= llvm::DINode::FlagTrivial;
+ // Record if a C++ record is non-trivial type.
+ if (!CXXRD->isTrivial())
+ Flags |= llvm::DINode::FlagNonTrivial;
}
llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType(
@@ -3443,6 +3535,11 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
} else if (const auto *OMD = dyn_cast<ObjCMethodDecl>(D)) {
Name = getObjCMethodName(OMD);
Flags |= llvm::DINode::FlagPrototyped;
+ } else if (isa<VarDecl>(D) &&
+ GD.getDynamicInitKind() != DynamicInitKind::NoStub) {
+ // This is a global initializer or atexit destructor for a global variable.
+ Name = getDynamicInitializerName(cast<VarDecl>(D), GD.getDynamicInitKind(),
+ Fn);
} else {
// Use llvm function name.
Name = Fn->getName();
@@ -3488,6 +3585,15 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
if (HasDecl && isa<FunctionDecl>(D))
DeclCache[D->getCanonicalDecl()].reset(SP);
+ // We use the SPDefCache only in the case when the debug entry values option
+ // is set, in order to speed up parameters modification analysis.
+ //
+ // FIXME: Use AbstractCallee here to support ObjCMethodDecl.
+ if (CGM.getCodeGenOpts().EnableDebugEntryValues && HasDecl)
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->hasBody() && !FD->param_empty())
+ SPDefCache[FD].reset(SP);
+
if (CGM.getCodeGenOpts().DwarfVersion >= 5) {
// Starting with DWARF V5 method declarations are emitted as children of
// the interface type.
@@ -3516,7 +3622,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
}
void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
- QualType FnType) {
+ QualType FnType, llvm::Function *Fn) {
StringRef Name;
StringRef LinkageName;
@@ -3526,7 +3632,9 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
llvm::DIFile *Unit = getOrCreateFile(Loc);
- llvm::DIScope *FDContext = getDeclContextDescriptor(D);
+ bool IsDeclForCallSite = Fn ? true : false;
+ llvm::DIScope *FDContext =
+ IsDeclForCallSite ? Unit : getDeclContextDescriptor(D);
llvm::DINodeArray TParamsArray;
if (isa<FunctionDecl>(D)) {
// If there is a DISubprogram for this function available then use it.
@@ -3553,10 +3661,38 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
if (CGM.getLangOpts().Optimize)
SPFlags |= llvm::DISubprogram::SPFlagOptimized;
- DBuilder.retainType(DBuilder.createFunction(
+ llvm::DISubprogram *SP = DBuilder.createFunction(
FDContext, Name, LinkageName, Unit, LineNo,
getOrCreateFunctionType(D, FnType, Unit), ScopeLine, Flags, SPFlags,
- TParamsArray.get(), getFunctionDeclaration(D)));
+ TParamsArray.get(), getFunctionDeclaration(D));
+
+ if (IsDeclForCallSite)
+ Fn->setSubprogram(SP);
+
+ DBuilder.retainType(SP);
+}
+
+void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
+ QualType CalleeType,
+ const FunctionDecl *CalleeDecl) {
+ auto &CGOpts = CGM.getCodeGenOpts();
+ if (!CGOpts.EnableDebugEntryValues || !CGM.getLangOpts().Optimize ||
+ !CallOrInvoke ||
+ CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo)
+ return;
+
+ auto *Func = CallOrInvoke->getCalledFunction();
+ if (!Func)
+ return;
+
+ // If there is no DISubprogram attached to the function being called,
+ // create the one describing the function in order to have complete
+ // call site debug info.
+ if (Func->getSubprogram())
+ return;
+
+ if (!CalleeDecl->isStatic() && !CalleeDecl->isInlined())
+ EmitFunctionDecl(CalleeDecl, CalleeDecl->getLocation(), CalleeType, Func);
}
void CGDebugInfo::EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD) {
@@ -3735,7 +3871,8 @@ CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
llvm::Value *Storage,
llvm::Optional<unsigned> ArgNo,
- CGBuilderTy &Builder) {
+ CGBuilderTy &Builder,
+ const bool UsePointerValue) {
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
if (VD->hasAttr<NoDebugAttr>())
@@ -3840,6 +3977,16 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
}
}
+ // Clang stores the sret pointer provided by the caller in a static alloca.
+ // Use DW_OP_deref to tell the debugger to load the pointer and treat it as
+ // the address of the variable.
+ if (UsePointerValue) {
+ assert(std::find(Expr.begin(), Expr.end(), llvm::dwarf::DW_OP_deref) ==
+ Expr.end() &&
+ "Debug info already contains DW_OP_deref.");
+ Expr.push_back(llvm::dwarf::DW_OP_deref);
+ }
+
// Create the descriptor for the variable.
auto *D = ArgNo ? DBuilder.createParameterVariable(
Scope, Name, *ArgNo, Unit, Line, Ty,
@@ -3853,14 +4000,46 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt),
Builder.GetInsertBlock());
+ if (CGM.getCodeGenOpts().EnableDebugEntryValues && ArgNo) {
+ if (auto *PD = dyn_cast<ParmVarDecl>(VD))
+ ParamCache[PD].reset(D);
+ }
+
return D;
}
llvm::DILocalVariable *
CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage,
- CGBuilderTy &Builder) {
+ CGBuilderTy &Builder,
+ const bool UsePointerValue) {
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
- return EmitDeclare(VD, Storage, llvm::None, Builder);
+ return EmitDeclare(VD, Storage, llvm::None, Builder, UsePointerValue);
+}
+
+void CGDebugInfo::EmitLabel(const LabelDecl *D, CGBuilderTy &Builder) {
+ assert(DebugKind >= codegenoptions::LimitedDebugInfo);
+ assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
+
+ if (D->hasAttr<NoDebugAttr>())
+ return;
+
+ auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
+ llvm::DIFile *Unit = getOrCreateFile(D->getLocation());
+
+ // Get location information.
+ unsigned Line = getLineNumber(D->getLocation());
+ unsigned Column = getColumnNumber(D->getLocation());
+
+ StringRef Name = D->getName();
+
+ // Create the descriptor for the label.
+ auto *L =
+ DBuilder.createLabel(Scope, Name, Unit, Line, CGM.getLangOpts().Optimize);
+
+ // Insert an llvm.dbg.label into the current block.
+ DBuilder.insertLabel(L,
+ llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt),
+ Builder.GetInsertBlock());
}
llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy,
@@ -4125,7 +4304,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::DIDerivedType *
CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
- if (!D->isStaticDataMember())
+ if (!D || !D->isStaticDataMember())
return nullptr;
auto MI = StaticDataMemberCache.find(D->getCanonicalDecl());
@@ -4207,6 +4386,14 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
SmallVector<int64_t, 4> Expr;
unsigned AddressSpace =
CGM.getContext().getTargetAddressSpace(D->getType());
+ if (CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) {
+ if (D->hasAttr<CUDASharedAttr>())
+ AddressSpace =
+ CGM.getContext().getTargetAddressSpace(LangAS::cuda_shared);
+ else if (D->hasAttr<CUDAConstantAttr>())
+ AddressSpace =
+ CGM.getContext().getTargetAddressSpace(LangAS::cuda_constant);
+ }
AppendAddressSpaceXDeref(AddressSpace, Expr);
GVE = DBuilder.createGlobalVariableExpression(
@@ -4229,22 +4416,32 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
StringRef Name = VD->getName();
llvm::DIType *Ty = getOrCreateType(VD->getType(), Unit);
+
+ // Do not use global variables for enums, unless in CodeView.
if (const auto *ECD = dyn_cast<EnumConstantDecl>(VD)) {
const auto *ED = cast<EnumDecl>(ECD->getDeclContext());
assert(isa<EnumType>(ED->getTypeForDecl()) && "Enum without EnumType?");
- Ty = getOrCreateType(QualType(ED->getTypeForDecl(), 0), Unit);
+ (void)ED;
+
+ // If CodeView, emit enums as global variables, unless they are defined
+ // inside a class. We do this because MSVC doesn't emit S_CONSTANTs for
+ // enums in classes, and because it is difficult to attach this scope
+ // information to the global variable.
+ if (!CGM.getCodeGenOpts().EmitCodeView ||
+ isa<RecordDecl>(ED->getDeclContext()))
+ return;
}
- // Do not use global variables for enums.
- //
- // FIXME: why not?
- if (Ty->getTag() == llvm::dwarf::DW_TAG_enumeration_type)
- return;
- // Do not emit separate definitions for function local const/statics.
+
+ llvm::DIScope *DContext = nullptr;
+
+ // Do not emit separate definitions for function local consts.
if (isa<FunctionDecl>(VD->getDeclContext()))
return;
+
+ // Emit definition for static members in CodeView.
VD = cast<ValueDecl>(VD->getCanonicalDecl());
- auto *VarD = cast<VarDecl>(VD);
- if (VarD->isStaticDataMember()) {
+ auto *VarD = dyn_cast<VarDecl>(VD);
+ if (VarD && VarD->isStaticDataMember()) {
auto *RD = cast<RecordDecl>(VarD->getDeclContext());
getDeclContextDescriptor(VarD);
// Ensure that the type is retained even though it's otherwise unreferenced.
@@ -4253,10 +4450,16 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
// through its scope.
RetainedTypes.push_back(
CGM.getContext().getRecordType(RD).getAsOpaquePtr());
- return;
- }
- llvm::DIScope *DContext = getDeclContextDescriptor(VD);
+ if (!CGM.getCodeGenOpts().EmitCodeView)
+ return;
+
+ // Use the global scope for static members.
+ DContext = getContextDescriptor(
+ cast<Decl>(CGM.getContext().getTranslationUnitDecl()), TheCU);
+ } else {
+ DContext = getDeclContextDescriptor(VD);
+ }
auto &GV = DeclCache[VD];
if (GV)
@@ -4393,6 +4596,29 @@ void CGDebugInfo::setDwoId(uint64_t Signature) {
TheCU->setDWOId(Signature);
}
+/// Analyzes each function parameter to determine whether it is constant
+/// throughout the function body.
+static void analyzeParametersModification(
+ ASTContext &Ctx,
+ llvm::DenseMap<const FunctionDecl *, llvm::TrackingMDRef> &SPDefCache,
+ llvm::DenseMap<const ParmVarDecl *, llvm::TrackingMDRef> &ParamCache) {
+ for (auto &SP : SPDefCache) {
+ auto *FD = SP.first;
+ assert(FD->hasBody() && "Functions must have body here");
+ const Stmt *FuncBody = (*FD).getBody();
+ for (auto Parm : FD->parameters()) {
+ ExprMutationAnalyzer FuncAnalyzer(*FuncBody, Ctx);
+ if (FuncAnalyzer.isMutated(Parm))
+ continue;
+
+ auto I = ParamCache.find(Parm);
+ assert(I != ParamCache.end() && "Parameters should be already cached");
+ auto *DIParm = cast<llvm::DILocalVariable>(I->second);
+ DIParm->setIsNotModified();
+ }
+ }
+}
+
void CGDebugInfo::finalize() {
// Creating types might create further types - invalidating the current
// element and the size(), so don't cache/reference them.
@@ -4465,6 +4691,10 @@ void CGDebugInfo::finalize() {
if (auto MD = TypeCache[RT])
DBuilder.retainType(cast<llvm::DIType>(MD));
+ if (CGM.getCodeGenOpts().EnableDebugEntryValues)
+ // This will be used to emit debug entry values.
+ analyzeParametersModification(CGM.getContext(), SPDefCache, ParamCache);
+
DBuilder.finalize();
}
@@ -4497,7 +4727,10 @@ llvm::DINode::DIFlags CGDebugInfo::getCallSiteRelatedAttrs() const {
// were part of DWARF v4.
bool SupportsDWARFv4Ext =
CGM.getCodeGenOpts().DwarfVersion == 4 &&
- CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::LLDB;
+ (CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::LLDB ||
+ (CGM.getCodeGenOpts().EnableDebugEntryValues &&
+ CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::GDB));
+
if (!SupportsDWARFv4Ext && CGM.getCodeGenOpts().DwarfVersion < 5)
return llvm::DINode::FlagZero;