diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp | 420 |
1 files changed, 267 insertions, 153 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp index f6ee7ee26d4b..cbd524eda9d0 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp @@ -18,8 +18,8 @@ #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "ConstantEmitter.h" -#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -46,6 +46,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/MD5.h" #include "llvm/Support/Path.h" +#include "llvm/Support/TimeProfiler.h" using namespace clang; using namespace clang::CodeGen; @@ -235,8 +236,7 @@ PrintingPolicy CGDebugInfo::getPrintingPolicy() const { PP.MSVCFormatting = true; // Apply -fdebug-prefix-map. - PP.RemapFilePaths = true; - PP.remapPath = [this](StringRef Path) { return remapDIPath(Path); }; + PP.Callbacks = &PrintCB; return PP; } @@ -293,13 +293,6 @@ StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) { } } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) { OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')'; - } else if (isa<ObjCProtocolDecl>(DC)) { - // We can extract the type of the class from the self pointer. - if (ImplicitParamDecl *SelfDecl = OMD->getSelfDecl()) { - QualType ClassTy = - cast<ObjCObjectPointerType>(SelfDecl->getType())->getPointeeType(); - ClassTy.print(OS, PrintingPolicy(LangOptions())); - } } OS << ' ' << OMD->getSelector().getAsString() << ']'; @@ -314,7 +307,9 @@ StringRef CGDebugInfo::getClassName(const RecordDecl *RD) { if (isa<ClassTemplateSpecializationDecl>(RD)) { SmallString<128> Name; llvm::raw_svector_ostream OS(Name); - RD->getNameForDiagnostic(OS, getPrintingPolicy(), + PrintingPolicy PP = getPrintingPolicy(); + PP.PrintCanonicalTypes = true; + RD->getNameForDiagnostic(OS, PP, /*Qualified*/ false); // Copy this name on the side and use its reference. @@ -537,11 +532,11 @@ void CGDebugInfo::CreateCompileUnit() { // file to determine the real absolute path for the file. std::string MainFileDir; if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { - MainFileDir = remapDIPath(MainFile->getDir()->getName()); - if (MainFileDir != ".") { + MainFileDir = MainFile->getDir()->getName(); + if (!llvm::sys::path::is_absolute(MainFileName)) { llvm::SmallString<1024> MainFileDirSS(MainFileDir); llvm::sys::path::append(MainFileDirSS, MainFileName); - MainFileName = MainFileDirSS.str(); + MainFileName = llvm::sys::path::remove_leading_dotslash(MainFileDirSS); } // If the main file name provided is identical to the input file name, and // if the input file is a preprocessed source, use the module name for @@ -561,6 +556,10 @@ void CGDebugInfo::CreateCompileUnit() { if (LO.CPlusPlus) { if (LO.ObjC) LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus; + else if (LO.CPlusPlus14) + LangTag = llvm::dwarf::DW_LANG_C_plus_plus_14; + else if (LO.CPlusPlus11) + LangTag = llvm::dwarf::DW_LANG_C_plus_plus_11; else LangTag = llvm::dwarf::DW_LANG_C_plus_plus; } else if (LO.ObjC) { @@ -592,6 +591,7 @@ void CGDebugInfo::CreateCompileUnit() { case codegenoptions::DebugDirectivesOnly: EmissionKind = llvm::DICompileUnit::DebugDirectivesOnly; break; + case codegenoptions::DebugInfoConstructor: case codegenoptions::LimitedDebugInfo: case codegenoptions::FullDebugInfo: EmissionKind = llvm::DICompileUnit::FullDebug; @@ -697,6 +697,22 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { case BuiltinType::Id: \ return getOrCreateStructPtrType("opencl_" #ExtType, Id##Ty); #include "clang/Basic/OpenCLExtensionTypes.def" + // TODO: real support for SVE types requires more infrastructure + // to be added first. The types have a variable length and are + // represented in debug info as types whose length depends on a + // target-specific pseudo register. +#define SVE_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/Basic/AArch64SVEACLETypes.def" + { + unsigned DiagID = CGM.getDiags().getCustomDiagID( + DiagnosticsEngine::Error, + "cannot yet generate debug info for SVE type '%0'"); + auto Name = BT->getName(CGM.getContext().getPrintingPolicy()); + CGM.getDiags().Report(DiagID) << Name; + // Return something safe. + return CreateType(cast<const BuiltinType>(CGM.getContext().IntTy)); + } case BuiltinType::UChar: case BuiltinType::Char_U: @@ -862,6 +878,8 @@ llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty, static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) { switch (TheCU->getSourceLanguage()) { case llvm::dwarf::DW_LANG_C_plus_plus: + case llvm::dwarf::DW_LANG_C_plus_plus_11: + case llvm::dwarf::DW_LANG_C_plus_plus_14: return true; case llvm::dwarf::DW_LANG_ObjC_plus_plus: return isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD); @@ -1118,10 +1136,11 @@ llvm::DIType *CGDebugInfo::CreateType(const TypedefType *Ty, // declared. SourceLocation Loc = Ty->getDecl()->getLocation(); + uint32_t Align = getDeclAlignIfRequired(Ty->getDecl(), CGM.getContext()); // Typedefs are derived from some other type. return DBuilder.createTypedef(Underlying, Ty->getDecl()->getName(), getOrCreateFile(Loc), getLineNumber(Loc), - getDeclContextDescriptor(Ty->getDecl())); + getDeclContextDescriptor(Ty->getDecl()), Align); } static unsigned getDwarfCC(CallingConv CC) { @@ -1583,6 +1602,31 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction( ContainingType = RecordTy; } + // We're checking for deleted C++ special member functions + // [Ctors,Dtors, Copy/Move] + auto checkAttrDeleted = [&](const auto *Method) { + if (Method->getCanonicalDecl()->isDeleted()) + SPFlags |= llvm::DISubprogram::SPFlagDeleted; + }; + + switch (Method->getKind()) { + + case Decl::CXXConstructor: + case Decl::CXXDestructor: + checkAttrDeleted(Method); + break; + case Decl::CXXMethod: + if (Method->isCopyAssignmentOperator() || + Method->isMoveAssignmentOperator()) + checkAttrDeleted(Method); + break; + default: + break; + } + + if (Method->isNoReturn()) + Flags |= llvm::DINode::FlagNoReturn; + if (Method->isStatic()) Flags |= llvm::DINode::FlagStaticMember; if (Method->isImplicit()) @@ -1604,6 +1648,12 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction( if (CGM.getLangOpts().Optimize) SPFlags |= llvm::DISubprogram::SPFlagOptimized; + // In this debug mode, emit type info for a class when its constructor type + // info is emitted. + if (DebugKind == codegenoptions::DebugInfoConstructor) + if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Method)) + completeClass(CD->getParent()); + llvm::DINodeArray TParamsArray = CollectFunctionTemplateParams(Method, Unit); llvm::DISubprogram *SP = DBuilder.createMethod( RecordTy, MethodName, MethodLinkageName, MethodDefUnit, MethodLine, @@ -1637,7 +1687,7 @@ void CGDebugInfo::CollectCXXMemberFunctions( if (!Method || Method->isImplicit() || Method->hasAttr<NoDebugAttr>()) continue; - if (Method->getType()->getAs<FunctionProtoType>()->getContainedAutoType()) + if (Method->getType()->castAs<FunctionProtoType>()->getContainedAutoType()) continue; // Reuse the existing member function declaration if it exists. @@ -1677,7 +1727,7 @@ void CGDebugInfo::CollectCXXBasesAux( const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); for (const auto &BI : Bases) { const auto *Base = - cast<CXXRecordDecl>(BI.getType()->getAs<RecordType>()->getDecl()); + cast<CXXRecordDecl>(BI.getType()->castAs<RecordType>()->getDecl()); if (!SeenTypes.insert(Base).second) continue; auto *BaseTy = getOrCreateType(BI.getType(), Unit); @@ -1769,6 +1819,7 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList, CGM.getContext().toCharUnitsFromBits((int64_t)fieldOffset); V = CGM.getCXXABI().EmitMemberDataPointer(MPT, chars); } + assert(V && "Failed to find template parameter pointer"); V = V->stripPointerCasts(); } TemplateParams.push_back(DBuilder.createTemplateValueParameter( @@ -1999,7 +2050,7 @@ void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit, llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy, SourceLocation Loc) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); + assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); llvm::DIType *T = getOrCreateType(RTy, getOrCreateFile(Loc)); return T; } @@ -2011,7 +2062,7 @@ llvm::DIType *CGDebugInfo::getOrCreateInterfaceType(QualType D, llvm::DIType *CGDebugInfo::getOrCreateStandaloneType(QualType D, SourceLocation Loc) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); + assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); assert(!D.isNull() && "null type"); llvm::DIType *T = getOrCreateType(D, getOrCreateFile(Loc)); assert(T && "could not create debug info for type"); @@ -2166,6 +2217,17 @@ static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind, !isClassOrMethodDLLImport(CXXDecl)) return true; + // In constructor debug mode, only emit debug info for a class when its + // constructor is emitted. Skip this optimization if the class or any of + // its methods are marked dllimport. + if (DebugKind == codegenoptions::DebugInfoConstructor && + !CXXDecl->isLambda() && !isClassOrMethodDLLImport(CXXDecl)) { + for (const auto *Ctor : CXXDecl->ctors()) { + if (Ctor->isUserProvided()) + return true; + } + } + TemplateSpecializationKind Spec = TSK_Undeclared; if (const auto *SD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) Spec = SD->getSpecializationKind(); @@ -2550,8 +2612,8 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, SourceLocation Loc = PD->getLocation(); llvm::DIFile *PUnit = getOrCreateFile(Loc); unsigned PLine = getLineNumber(Loc); - ObjCMethodDecl *Getter = PD->getGetterMethodDecl(); - ObjCMethodDecl *Setter = PD->getSetterMethodDecl(); + ObjCMethodDecl *Getter = PImpD->getGetterMethodDecl(); + ObjCMethodDecl *Setter = PImpD->getSetterMethodDecl(); PropertyNode = DBuilder.createObjCProperty( PD->getName(), PUnit, PLine, hasDefaultGetterName(PD, Getter) @@ -2684,16 +2746,16 @@ llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty, // Set the MS inheritance model. There is no flag for the unspecified model. if (CGM.getTarget().getCXXABI().isMicrosoft()) { switch (Ty->getMostRecentCXXRecordDecl()->getMSInheritanceModel()) { - case MSInheritanceAttr::Keyword_single_inheritance: + case MSInheritanceModel::Single: Flags |= llvm::DINode::FlagSingleInheritance; break; - case MSInheritanceAttr::Keyword_multiple_inheritance: + case MSInheritanceModel::Multiple: Flags |= llvm::DINode::FlagMultipleInheritance; break; - case MSInheritanceAttr::Keyword_virtual_inheritance: + case MSInheritanceModel::Virtual: Flags |= llvm::DINode::FlagVirtualInheritance; break; - case MSInheritanceAttr::Keyword_unspecified_inheritance: + case MSInheritanceModel::Unspecified: break; } } @@ -2917,6 +2979,13 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) { if (Ty.isNull()) return nullptr; + llvm::TimeTraceScope TimeScope("DebugType", [&]() { + std::string Name; + llvm::raw_string_ostream OS(Name); + Ty.print(OS, getPrintingPolicy()); + return Name; + }); + // Unwrap the type as needed for debug information. Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext()); @@ -2978,7 +3047,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { #define ABSTRACT_TYPE(Class, Base) #define NON_CANONICAL_TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) case Type::Class: -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" llvm_unreachable("Dependent types cannot show up in debug information"); case Type::ExtVector: @@ -3105,7 +3174,8 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); - // Explicitly record the calling convention for C++ records. + // Explicitly record the calling convention and export symbols for C++ + // records. auto Flags = llvm::DINode::FlagZero; if (auto CXXRD = dyn_cast<CXXRecordDecl>(RD)) { if (CGM.getCXXABI().getRecordArgABI(CXXRD) == CGCXXABI::RAA_Indirect) @@ -3116,6 +3186,10 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { // Record if a C++ record is non-trivial type. if (!CXXRD->isTrivial()) Flags |= llvm::DINode::FlagNonTrivial; + + // Record exports it symbols to the containing structure. + if (CXXRD->isAnonymousStructOrUnion()) + Flags |= llvm::DINode::FlagExportSymbols; } llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType( @@ -3214,7 +3288,7 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit, DebugKind <= codegenoptions::DebugLineTablesOnly)) LinkageName = StringRef(); - if (DebugKind >= codegenoptions::LimitedDebugInfo) { + if (CGM.getCodeGenOpts().hasReducedDebugInfo()) { if (const NamespaceDecl *NSDecl = dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext())) FDContext = getOrCreateNamespace(NSDecl); @@ -3247,8 +3321,8 @@ void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit, llvm::APInt ConstVal(32, 1); QualType ET = CGM.getContext().getAsArrayType(T)->getElementType(); - T = CGM.getContext().getConstantArrayType(ET, ConstVal, ArrayType::Normal, - 0); + T = CGM.getContext().getConstantArrayType(ET, ConstVal, nullptr, + ArrayType::Normal, 0); } Name = VD->getName(); @@ -3298,13 +3372,13 @@ llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD, unsigned Line = getLineNumber(Loc); collectFunctionDeclProps(GD, Unit, Name, LinkageName, DContext, TParamsArray, Flags); - auto *FD = dyn_cast<FunctionDecl>(GD.getDecl()); + auto *FD = cast<FunctionDecl>(GD.getDecl()); // Build function type. SmallVector<QualType, 16> ArgTypes; - if (FD) - for (const ParmVarDecl *Parm : FD->parameters()) - ArgTypes.push_back(Parm->getType()); + for (const ParmVarDecl *Parm : FD->parameters()) + ArgTypes.push_back(Parm->getType()); + CallingConv CC = FD->getType()->castAs<FunctionType>()->getCallConv(); QualType FnType = CGM.getContext().getFunctionType( FD->getReturnType(), ArgTypes, FunctionProtoType::ExtProtoInfo(CC)); @@ -3426,6 +3500,42 @@ llvm::DISubprogram *CGDebugInfo::getFunctionDeclaration(const Decl *D) { return nullptr; } +llvm::DISubprogram *CGDebugInfo::getObjCMethodDeclaration( + const Decl *D, llvm::DISubroutineType *FnType, unsigned LineNo, + llvm::DINode::DIFlags Flags, llvm::DISubprogram::DISPFlags SPFlags) { + if (!D || DebugKind <= codegenoptions::DebugLineTablesOnly) + return nullptr; + + const auto *OMD = dyn_cast<ObjCMethodDecl>(D); + if (!OMD) + return nullptr; + + if (CGM.getCodeGenOpts().DwarfVersion < 5 && !OMD->isDirectMethod()) + return nullptr; + + if (OMD->isDirectMethod()) + SPFlags |= llvm::DISubprogram::SPFlagObjCDirect; + + // Starting with DWARF V5 method declarations are emitted as children of + // the interface type. + auto *ID = dyn_cast_or_null<ObjCInterfaceDecl>(D->getDeclContext()); + if (!ID) + ID = OMD->getClassInterface(); + if (!ID) + return nullptr; + QualType QTy(ID->getTypeForDecl(), 0); + auto It = TypeCache.find(QTy.getAsOpaquePtr()); + if (It == TypeCache.end()) + return nullptr; + auto *InterfaceType = cast<llvm::DICompositeType>(It->second); + llvm::DISubprogram *FD = DBuilder.createFunction( + InterfaceType, getObjCMethodName(OMD), StringRef(), + InterfaceType->getFile(), LineNo, FnType, LineNo, Flags, SPFlags); + DBuilder.finalizeSubprogram(FD); + ObjCMethodCache[ID].push_back({FD, OMD->isDirectMethod()}); + return FD; +} + // getOrCreateFunctionType - Construct type. If it is a c++ method, include // implicit parameter "this". llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D, @@ -3568,6 +3678,12 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, unsigned LineNo = getLineNumber(Loc); unsigned ScopeLine = getLineNumber(ScopeLoc); + llvm::DISubroutineType *DIFnType = getOrCreateFunctionType(D, FnType, Unit); + llvm::DISubprogram *Decl = nullptr; + if (D) + Decl = isa<ObjCMethodDecl>(D) + ? getObjCMethodDeclaration(D, DIFnType, LineNo, Flags, SPFlags) + : getFunctionDeclaration(D); // FIXME: The function declaration we're constructing here is mostly reusing // declarations from CXXMethodDecl and not constructing new ones for arbitrary @@ -3575,9 +3691,8 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, // all subprograms instead of the actual context since subprogram definitions // are emitted as CU level entities by the backend. llvm::DISubprogram *SP = DBuilder.createFunction( - FDContext, Name, LinkageName, Unit, LineNo, - getOrCreateFunctionType(D, FnType, Unit), ScopeLine, FlagsForDef, - SPFlagsForDef, TParamsArray.get(), getFunctionDeclaration(D)); + FDContext, Name, LinkageName, Unit, LineNo, DIFnType, ScopeLine, + FlagsForDef, SPFlagsForDef, TParamsArray.get(), Decl); Fn->setSubprogram(SP); // We might get here with a VarDecl in the case we're generating // code for the initialization of globals. Do not record these decls @@ -3585,35 +3700,6 @@ 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. - if (const auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) { - const ObjCInterfaceDecl *ID = OMD->getClassInterface(); - QualType QTy(ID->getTypeForDecl(), 0); - auto It = TypeCache.find(QTy.getAsOpaquePtr()); - if (It != TypeCache.end()) { - llvm::DICompositeType *InterfaceDecl = - cast<llvm::DICompositeType>(It->second); - llvm::DISubprogram *FD = DBuilder.createFunction( - InterfaceDecl, Name, LinkageName, Unit, LineNo, - getOrCreateFunctionType(D, FnType, Unit), ScopeLine, Flags, SPFlags, - TParamsArray.get()); - DBuilder.finalizeSubprogram(FD); - ObjCMethodCache[ID].push_back(FD); - } - } - } - // Push the function onto the lexical block stack. LexicalBlockStack.emplace_back(SP); @@ -3630,6 +3716,15 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, if (!D) return; + llvm::TimeTraceScope TimeScope("DebugFunction", [&]() { + std::string Name; + llvm::raw_string_ostream OS(Name); + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) + ND->getNameForDiagnostic(OS, getPrintingPolicy(), + /*Qualified=*/true); + return Name; + }); + llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; llvm::DIFile *Unit = getOrCreateFile(Loc); bool IsDeclForCallSite = Fn ? true : false; @@ -3675,22 +3770,29 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, 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) + if (!CallOrInvoke) return; - auto *Func = CallOrInvoke->getCalledFunction(); if (!Func) return; + if (Func->getSubprogram()) + return; + + // Do not emit a declaration subprogram for a builtin or if call site info + // isn't required. Also, elide declarations for functions with reserved names, + // as call site-related features aren't interesting in this case (& also, the + // compiler may emit calls to these functions without debug locations, which + // makes the verifier complain). + if (CalleeDecl->getBuiltinID() != 0 || + getCallSiteRelatedAttrs() == llvm::DINode::FlagZero) + return; + if (const auto *Id = CalleeDecl->getIdentifier()) + if (Id->isReservedName()) + 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); } @@ -3844,8 +3946,8 @@ CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, if (NumPaddingBytes.isPositive()) { llvm::APInt pad(32, NumPaddingBytes.getQuantity()); - FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy, - pad, ArrayType::Normal, 0); + FType = CGM.getContext().getConstantArrayType( + CGM.getContext().CharTy, pad, nullptr, ArrayType::Normal, 0); EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset)); } } @@ -3873,7 +3975,7 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Optional<unsigned> ArgNo, CGBuilderTy &Builder, const bool UsePointerValue) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); + assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); if (VD->hasAttr<NoDebugAttr>()) return nullptr; @@ -4000,11 +4102,6 @@ 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; } @@ -4012,12 +4109,12 @@ llvm::DILocalVariable * CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage, CGBuilderTy &Builder, const bool UsePointerValue) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); + assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); return EmitDeclare(VD, Storage, llvm::None, Builder, UsePointerValue); } void CGDebugInfo::EmitLabel(const LabelDecl *D, CGBuilderTy &Builder) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); + assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); if (D->hasAttr<NoDebugAttr>()) @@ -4053,7 +4150,7 @@ llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy, void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( const VarDecl *VD, llvm::Value *Storage, CGBuilderTy &Builder, const CGBlockInfo &blockInfo, llvm::Instruction *InsertPoint) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); + assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); if (Builder.GetInsertBlock() == nullptr) @@ -4124,7 +4221,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI, unsigned ArgNo, CGBuilderTy &Builder) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); + assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); EmitDeclare(VD, AI, ArgNo, Builder); } @@ -4181,7 +4278,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, unsigned ArgNo, llvm::AllocaInst *Alloca, CGBuilderTy &Builder) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); + assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); ASTContext &C = CGM.getContext(); const BlockDecl *blockDecl = block.getBlockDecl(); @@ -4347,10 +4444,18 @@ llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls( void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, const VarDecl *D) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); + assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); if (D->hasAttr<NoDebugAttr>()) return; + llvm::TimeTraceScope TimeScope("DebugGlobalVariable", [&]() { + std::string Name; + llvm::raw_string_ostream OS(Name); + D->getNameForDiagnostic(OS, getPrintingPolicy(), + /*Qualified=*/true); + return Name; + }); + // If we already created a DIGlobalVariable for this declaration, just attach // it to the llvm::GlobalVariable. auto Cached = DeclCache.find(D->getCanonicalDecl()); @@ -4398,7 +4503,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, GVE = DBuilder.createGlobalVariableExpression( DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit), - Var->hasLocalLinkage(), + Var->hasLocalLinkage(), true, Expr.empty() ? nullptr : DBuilder.createExpression(Expr), getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters, Align); @@ -4408,28 +4513,44 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, } void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); + assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); if (VD->hasAttr<NoDebugAttr>()) return; + llvm::TimeTraceScope TimeScope("DebugConstGlobalVariable", [&]() { + std::string Name; + llvm::raw_string_ostream OS(Name); + VD->getNameForDiagnostic(OS, getPrintingPolicy(), + /*Qualified=*/true); + return Name; + }); + auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); // Create the descriptor for the variable. 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?"); - (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())) + + if (CGM.getCodeGenOpts().EmitCodeView) { + // 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 (isa<RecordDecl>(ED->getDeclContext())) + return; + } else { + // If not CodeView, emit DW_TAG_enumeration_type if necessary. For + // example: for "enum { ZERO };", a DW_TAG_enumeration_type is created the + // first time `ZERO` is referenced in a function. + llvm::DIType *EDTy = + getOrCreateType(QualType(ED->getTypeForDecl(), 0), Unit); + assert (EDTy->getTag() == llvm::dwarf::DW_TAG_enumeration_type); + (void)EDTy; return; + } } llvm::DIScope *DContext = nullptr; @@ -4485,10 +4606,29 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { GV.reset(DBuilder.createGlobalVariableExpression( DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty, - true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD), + true, true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD), TemplateParameters, Align)); } +void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var, + const VarDecl *D) { + assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); + if (D->hasAttr<NoDebugAttr>()) + return; + + auto Align = getDeclAlignIfRequired(D, CGM.getContext()); + llvm::DIFile *Unit = getOrCreateFile(D->getLocation()); + StringRef Name = D->getName(); + llvm::DIType *Ty = getOrCreateType(D->getType(), Unit); + + llvm::DIScope *DContext = getDeclContextDescriptor(D); + llvm::DIGlobalVariableExpression *GVE = + DBuilder.createGlobalVariableExpression( + DContext, Name, StringRef(), Unit, getLineNumber(D->getLocation()), + Ty, false, false, nullptr, nullptr, nullptr, Align); + Var->addDebugInfo(GVE); +} + llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) { if (!LexicalBlockStack.empty()) return LexicalBlockStack.back(); @@ -4497,7 +4637,7 @@ llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) { } void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) { - if (CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo) + if (!CGM.getCodeGenOpts().hasReducedDebugInfo()) return; const NamespaceDecl *NSDecl = UD.getNominatedNamespace(); if (!NSDecl->isAnonymousNamespace() || @@ -4510,7 +4650,7 @@ void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) { } void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) { - if (CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo) + if (!CGM.getCodeGenOpts().hasReducedDebugInfo()) return; assert(UD.shadow_size() && "We shouldn't be codegening an invalid UsingDecl containing no decls"); @@ -4524,7 +4664,7 @@ void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) { // return type in the definition) if (const auto *FD = dyn_cast<FunctionDecl>(USD.getUnderlyingDecl())) if (const auto *AT = - FD->getType()->getAs<FunctionProtoType>()->getContainedAutoType()) + FD->getType()->castAs<FunctionProtoType>()->getContainedAutoType()) if (AT->getDeducedType().isNull()) return; if (llvm::DINode *Target = @@ -4551,7 +4691,7 @@ void CGDebugInfo::EmitImportDecl(const ImportDecl &ID) { llvm::DIImportedEntity * CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) { - if (CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo) + if (!CGM.getCodeGenOpts().hasReducedDebugInfo()) return nullptr; auto &VH = NamespaceAliasCache[&NA]; if (VH) @@ -4596,29 +4736,6 @@ 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. @@ -4630,27 +4747,28 @@ void CGDebugInfo::finalize() { DBuilder.replaceTemporary(llvm::TempDIType(E.Decl), Ty); } - if (CGM.getCodeGenOpts().DwarfVersion >= 5) { - // Add methods to interface. - for (const auto &P : ObjCMethodCache) { - if (P.second.empty()) - continue; + // Add methods to interface. + for (const auto &P : ObjCMethodCache) { + if (P.second.empty()) + continue; + + QualType QTy(P.first->getTypeForDecl(), 0); + auto It = TypeCache.find(QTy.getAsOpaquePtr()); + assert(It != TypeCache.end()); - QualType QTy(P.first->getTypeForDecl(), 0); - auto It = TypeCache.find(QTy.getAsOpaquePtr()); - assert(It != TypeCache.end()); + llvm::DICompositeType *InterfaceDecl = + cast<llvm::DICompositeType>(It->second); - llvm::DICompositeType *InterfaceDecl = - cast<llvm::DICompositeType>(It->second); + auto CurElts = InterfaceDecl->getElements(); + SmallVector<llvm::Metadata *, 16> EltTys(CurElts.begin(), CurElts.end()); - SmallVector<llvm::Metadata *, 16> EltTys; - auto CurrenetElts = InterfaceDecl->getElements(); - EltTys.append(CurrenetElts.begin(), CurrenetElts.end()); - for (auto &MD : P.second) - EltTys.push_back(MD); - llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys); - DBuilder.replaceArrays(InterfaceDecl, Elements); - } + // For DWARF v4 or earlier, only add objc_direct methods. + for (auto &SubprogramDirect : P.second) + if (CGM.getCodeGenOpts().DwarfVersion >= 5 || SubprogramDirect.getInt()) + EltTys.push_back(SubprogramDirect.getPointer()); + + llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys); + DBuilder.replaceArrays(InterfaceDecl, Elements); } for (const auto &P : ReplaceMap) { @@ -4691,15 +4809,11 @@ 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(); } void CGDebugInfo::EmitExplicitCastType(QualType Ty) { - if (CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo) + if (!CGM.getCodeGenOpts().hasReducedDebugInfo()) return; if (auto *DieTy = getOrCreateType(Ty, TheCU->getFile())) @@ -4728,10 +4842,10 @@ llvm::DINode::DIFlags CGDebugInfo::getCallSiteRelatedAttrs() const { bool SupportsDWARFv4Ext = CGM.getCodeGenOpts().DwarfVersion == 4 && (CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::LLDB || - (CGM.getCodeGenOpts().EnableDebugEntryValues && - CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::GDB)); + CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::GDB); - if (!SupportsDWARFv4Ext && CGM.getCodeGenOpts().DwarfVersion < 5) + if (!SupportsDWARFv4Ext && CGM.getCodeGenOpts().DwarfVersion < 5 && + !CGM.getCodeGenOpts().EnableDebugEntryValues) return llvm::DINode::FlagZero; return llvm::DINode::FlagAllCallsDescribed; |
