diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp | 371 |
1 files changed, 277 insertions, 94 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp index 0f3f684d61dc..3d8a715b692d 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp @@ -32,6 +32,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" +#include "clang/CodeGen/ModuleBuilder.h" #include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/ModuleMap.h" @@ -58,7 +59,16 @@ using namespace clang::CodeGen; static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) { auto TI = Ctx.getTypeInfo(Ty); - return TI.isAlignRequired() ? TI.Align : 0; + if (TI.isAlignRequired()) + return TI.Align; + + // MaxFieldAlignmentAttr is the attribute added to types + // declared after #pragma pack(n). + if (auto *Decl = Ty->getAsRecordDecl()) + if (Decl->hasAttr<MaxFieldAlignmentAttr>()) + return TI.Align; + + return 0; } static uint32_t getTypeAlignIfRequired(QualType Ty, const ASTContext &Ctx) { @@ -856,7 +866,16 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { return SingletonId; \ } #include "clang/Basic/WebAssemblyReferenceTypes.def" - +#define AMDGPU_OPAQUE_PTR_TYPE(Name, MangledName, AS, Width, Align, Id, \ + SingletonId) \ + case BuiltinType::Id: { \ + if (!SingletonId) \ + SingletonId = \ + DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, \ + MangledName, TheCU, TheCU->getFile(), 0); \ + return SingletonId; \ + } +#include "clang/Basic/AMDGPUTypes.def" case BuiltinType::UChar: case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; @@ -1313,6 +1332,44 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty, return DBuilder.createPointerType(EltTy, Size); } +static llvm::SmallVector<TemplateArgument> +GetTemplateArgs(const TemplateDecl *TD, const TemplateSpecializationType *Ty) { + assert(Ty->isTypeAlias()); + // TemplateSpecializationType doesn't know if its template args are + // being substituted into a parameter pack. We can find out if that's + // the case now by inspecting the TypeAliasTemplateDecl template + // parameters. Insert Ty's template args into SpecArgs, bundling args + // passed to a parameter pack into a TemplateArgument::Pack. It also + // doesn't know the value of any defaulted args, so collect those now + // too. + SmallVector<TemplateArgument> SpecArgs; + ArrayRef SubstArgs = Ty->template_arguments(); + for (const NamedDecl *Param : TD->getTemplateParameters()->asArray()) { + // If Param is a parameter pack, pack the remaining arguments. + if (Param->isParameterPack()) { + SpecArgs.push_back(TemplateArgument(SubstArgs)); + break; + } + + // Skip defaulted args. + // FIXME: Ideally, we wouldn't do this. We can read the default values + // for each parameter. However, defaulted arguments which are dependent + // values or dependent types can't (easily?) be resolved here. + if (SubstArgs.empty()) { + // If SubstArgs is now empty (we're taking from it each iteration) and + // this template parameter isn't a pack, then that should mean we're + // using default values for the remaining template parameters (after + // which there may be an empty pack too which we will ignore). + break; + } + + // Take the next argument. + SpecArgs.push_back(SubstArgs.front()); + SubstArgs = SubstArgs.drop_front(); + } + return SpecArgs; +} + llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, llvm::DIFile *Unit) { assert(Ty->isTypeAlias()); @@ -1332,6 +1389,52 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, auto PP = getPrintingPolicy(); Ty->getTemplateName().print(OS, PP, TemplateName::Qualified::None); + SourceLocation Loc = AliasDecl->getLocation(); + + if (CGM.getCodeGenOpts().DebugTemplateAlias && + // FIXME: This is a workaround for the issue + // https://github.com/llvm/llvm-project/issues/89774 + // The TemplateSpecializationType doesn't contain any instantiation + // information; dependent template arguments can't be resolved. For now, + // fall back to DW_TAG_typedefs for template aliases that are + // instantiation dependent, e.g.: + // ``` + // template <int> + // using A = int; + // + // template<int I> + // struct S { + // using AA = A<I>; // Instantiation dependent. + // AA aa; + // }; + // + // S<0> s; + // ``` + // S::AA's underlying type A<I> is dependent on I so will be emitted as a + // DW_TAG_typedef. + !Ty->isInstantiationDependentType()) { + auto ArgVector = ::GetTemplateArgs(TD, Ty); + TemplateArgs Args = {TD->getTemplateParameters(), ArgVector}; + + // FIXME: Respect DebugTemplateNameKind::Mangled, e.g. by using GetName. + // Note we can't use GetName without additional work: TypeAliasTemplateDecl + // doesn't have instantiation information, so + // TypeAliasTemplateDecl::getNameForDiagnostic wouldn't have access to the + // template args. + std::string Name; + llvm::raw_string_ostream OS(Name); + TD->getNameForDiagnostic(OS, PP, /*Qualified=*/false); + if (CGM.getCodeGenOpts().getDebugSimpleTemplateNames() != + llvm::codegenoptions::DebugTemplateNamesKind::Simple || + !HasReconstitutableArgs(Args.Args)) + printTemplateArgumentList(OS, Args.Args, PP); + + llvm::DIDerivedType *AliasTy = DBuilder.createTemplateAlias( + Src, Name, getOrCreateFile(Loc), getLineNumber(Loc), + getDeclContextDescriptor(AliasDecl), CollectTemplateParams(Args, Unit)); + return AliasTy; + } + // Disable PrintCanonicalTypes here because we want // the DW_AT_name to benefit from the TypePrinter's ability // to skip defaulted template arguments. @@ -1343,8 +1446,6 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, PP.PrintCanonicalTypes = false; printTemplateArgumentList(OS, Ty->template_arguments(), PP, TD->getTemplateParameters()); - - SourceLocation Loc = AliasDecl->getLocation(); return DBuilder.createTypedef(Src, OS.str(), getOrCreateFile(Loc), getLineNumber(Loc), getDeclContextDescriptor(AliasDecl)); @@ -1440,8 +1541,7 @@ static unsigned getDwarfCC(CallingConv CC) { case CC_Swift: return llvm::dwarf::DW_CC_LLVM_Swift; case CC_SwiftAsync: - // [FIXME: swiftasynccc] Update to SwiftAsync once LLVM support lands. - return llvm::dwarf::DW_CC_LLVM_Swift; + return llvm::dwarf::DW_CC_LLVM_SwiftTail; case CC_PreserveMost: return llvm::dwarf::DW_CC_LLVM_PreserveMost; case CC_PreserveAll: @@ -1450,6 +1550,10 @@ static unsigned getDwarfCC(CallingConv CC) { return llvm::dwarf::DW_CC_LLVM_X86RegCall; case CC_M68kRTD: return llvm::dwarf::DW_CC_LLVM_M68kRTD; + case CC_PreserveNone: + return llvm::dwarf::DW_CC_LLVM_PreserveNone; + case CC_RISCVVectorCall: + return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall; } return 0; } @@ -1628,6 +1732,28 @@ llvm::DIType *CGDebugInfo::createFieldType( offsetInBits, flags, debugType, Annotations); } +llvm::DISubprogram * +CGDebugInfo::createInlinedTrapSubprogram(StringRef FuncName, + llvm::DIFile *FileScope) { + // We are caching the subprogram because we don't want to duplicate + // subprograms with the same message. Note that `SPFlagDefinition` prevents + // subprograms from being uniqued. + llvm::DISubprogram *&SP = InlinedTrapFuncMap[FuncName]; + + if (!SP) { + llvm::DISubroutineType *DIFnTy = DBuilder.createSubroutineType(nullptr); + SP = DBuilder.createFunction( + /*Scope=*/FileScope, /*Name=*/FuncName, /*LinkageName=*/StringRef(), + /*File=*/FileScope, /*LineNo=*/0, /*Ty=*/DIFnTy, + /*ScopeLine=*/0, + /*Flags=*/llvm::DINode::FlagArtificial, + /*SPFlags=*/llvm::DISubprogram::SPFlagDefinition, + /*TParams=*/nullptr, /*ThrownTypes=*/nullptr, /*Annotations=*/nullptr); + } + + return SP; +} + void CGDebugInfo::CollectRecordLambdaFields( const CXXRecordDecl *CXXDecl, SmallVectorImpl<llvm::Metadata *> &elements, llvm::DIType *RecordTy) { @@ -2751,7 +2877,7 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { // Collect data fields (including static variables and any initializers). CollectRecordFields(RD, DefUnit, EltTys, FwdDecl); - if (CXXDecl) + if (CXXDecl && !CGM.getCodeGenOpts().DebugOmitUnreferencedMethods) CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl); LexicalBlockStack.pop_back(); @@ -3237,7 +3363,7 @@ llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) { // }; int64_t Count = -1; // Count == -1 is an unbounded array. if (const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) - Count = CAT->getSize().getZExtValue(); + Count = CAT->getZExtSize(); else if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) { if (Expr *Size = VAT->getSizeExpr()) { Expr::EvalResult Result; @@ -3424,6 +3550,23 @@ llvm::DIMacroFile *CGDebugInfo::CreateTempMacroFile(llvm::DIMacroFile *Parent, return DBuilder.createTempMacroFile(Parent, Line, FName); } +llvm::DILocation *CGDebugInfo::CreateTrapFailureMessageFor( + llvm::DebugLoc TrapLocation, StringRef Category, StringRef FailureMsg) { + // Create a debug location from `TrapLocation` that adds an artificial inline + // frame. + SmallString<64> FuncName(ClangTrapPrefix); + + FuncName += "$"; + FuncName += Category; + FuncName += "$"; + FuncName += FailureMsg; + + llvm::DISubprogram *TrapSP = + createInlinedTrapSubprogram(FuncName, TrapLocation->getFile()); + return llvm::DILocation::get(CGM.getLLVMContext(), /*Line=*/0, /*Column=*/0, + /*Scope=*/TrapSP, /*InlinedAt=*/TrapLocation); +} + static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { Qualifiers Quals; do { @@ -3461,6 +3604,9 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { case Type::BTFTagAttributed: T = cast<BTFTagAttributedType>(T)->getWrappedType(); break; + case Type::CountAttributed: + T = cast<CountAttributedType>(T)->desugar(); + break; case Type::Elaborated: T = cast<ElaboratedType>(T)->getNamedType(); break; @@ -3483,6 +3629,10 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { T = DT; break; } + case Type::PackIndexing: { + T = cast<PackIndexingType>(T)->getSelectedType(); + break; + } case Type::Adjusted: case Type::Decayed: // Decayed and adjusted types use the adjusted type in LLVM and DWARF. @@ -3631,6 +3781,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::ConstantArray: case Type::VariableArray: case Type::IncompleteArray: + case Type::ArrayParameter: return CreateType(cast<ArrayType>(Ty), Unit); case Type::LValueReference: @@ -3652,6 +3803,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::TemplateSpecialization: return CreateType(cast<TemplateSpecializationType>(Ty), Unit); + case Type::CountAttributed: case Type::Auto: case Type::Attributed: case Type::BTFTagAttributed: @@ -3666,6 +3818,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::TypeOfExpr: case Type::TypeOf: case Type::Decltype: + case Type::PackIndexing: case Type::UnaryTransform: break; } @@ -4770,40 +4923,6 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, return D; } -llvm::DIType *CGDebugInfo::CreateBindingDeclType(const BindingDecl *BD) { - llvm::DIFile *Unit = getOrCreateFile(BD->getLocation()); - - // If the declaration is bound to a bitfield struct field, its type may have a - // size that is different from its deduced declaration type's. - if (const MemberExpr *ME = dyn_cast<MemberExpr>(BD->getBinding())) { - if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) { - if (FD->isBitField()) { - ASTContext &Context = CGM.getContext(); - const CGRecordLayout &RL = - CGM.getTypes().getCGRecordLayout(FD->getParent()); - const CGBitFieldInfo &Info = RL.getBitFieldInfo(FD); - - // Find an integer type with the same bitwidth as the bitfield size. If - // no suitable type is present in the target, give up on producing debug - // information as it would be wrong. It is certainly possible to produce - // correct debug info, but the logic isn't currently implemented. - uint64_t BitfieldSizeInBits = Info.Size; - QualType IntTy = - Context.getIntTypeForBitwidth(BitfieldSizeInBits, Info.IsSigned); - if (IntTy.isNull()) - return nullptr; - Qualifiers Quals = BD->getType().getQualifiers(); - QualType FinalTy = Context.getQualifiedType(IntTy, Quals); - llvm::DIType *Ty = getOrCreateType(FinalTy, Unit); - assert(Ty); - return Ty; - } - } - } - - return getOrCreateType(BD->getType(), Unit); -} - llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD, llvm::Value *Storage, std::optional<unsigned> ArgNo, @@ -4818,7 +4937,8 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD, if (isa<DeclRefExpr>(BD->getBinding())) return nullptr; - llvm::DIType *Ty = CreateBindingDeclType(BD); + llvm::DIFile *Unit = getOrCreateFile(BD->getLocation()); + llvm::DIType *Ty = getOrCreateType(BD->getType(), Unit); // If there is no debug info for this type then do not emit debug info // for this variable. @@ -4844,7 +4964,6 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD, unsigned Column = getColumnNumber(BD->getLocation()); StringRef Name = BD->getName(); auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back()); - llvm::DIFile *Unit = getOrCreateFile(BD->getLocation()); // Create the descriptor for the variable. llvm::DILocalVariable *D = DBuilder.createAutoVariable( Scope, Name, Unit, Line, Ty, CGM.getLangOpts().Optimize, @@ -4858,13 +4977,29 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD, const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(parent); const uint64_t fieldOffset = layout.getFieldOffset(fieldIndex); - - if (fieldOffset != 0) { - // Currently if the field offset is not a multiple of byte, the produced - // location would not be accurate. Therefore give up. - if (fieldOffset % CGM.getContext().getCharWidth() != 0) - return nullptr; - + if (FD->isBitField()) { + const CGRecordLayout &RL = + CGM.getTypes().getCGRecordLayout(FD->getParent()); + const CGBitFieldInfo &Info = RL.getBitFieldInfo(FD); + // Use DW_OP_plus_uconst to adjust to the start of the bitfield + // storage. + if (!Info.StorageOffset.isZero()) { + Expr.push_back(llvm::dwarf::DW_OP_plus_uconst); + Expr.push_back(Info.StorageOffset.getQuantity()); + } + // Use LLVM_extract_bits to extract the appropriate bits from this + // bitfield. + Expr.push_back(Info.IsSigned + ? llvm::dwarf::DW_OP_LLVM_extract_bits_sext + : llvm::dwarf::DW_OP_LLVM_extract_bits_zext); + Expr.push_back(Info.Offset); + // If we have an oversized bitfield then the value won't be more than + // the size of the type. + const uint64_t TypeSize = CGM.getContext().getTypeSize(BD->getType()); + Expr.push_back(std::min((uint64_t)Info.Size, TypeSize)); + } else if (fieldOffset != 0) { + assert(fieldOffset % CGM.getContext().getCharWidth() == 0 && + "Unexpected non-bitfield with non-byte-aligned offset"); Expr.push_back(llvm::dwarf::DW_OP_plus_uconst); Expr.push_back( CGM.getContext().toCharUnitsFromBits(fieldOffset).getQuantity()); @@ -5350,6 +5485,54 @@ static bool IsReconstitutableType(QualType QT) { return T.Reconstitutable; } +bool CGDebugInfo::HasReconstitutableArgs( + ArrayRef<TemplateArgument> Args) const { + return llvm::all_of(Args, [&](const TemplateArgument &TA) { + switch (TA.getKind()) { + case TemplateArgument::Template: + // Easy to reconstitute - the value of the parameter in the debug + // info is the string name of the template. The template name + // itself won't benefit from any name rebuilding, but that's a + // representational limitation - maybe DWARF could be + // changed/improved to use some more structural representation. + return true; + case TemplateArgument::Declaration: + // Reference and pointer non-type template parameters point to + // variables, functions, etc and their value is, at best (for + // variables) represented as an address - not a reference to the + // DWARF describing the variable/function/etc. This makes it hard, + // possibly impossible to rebuild the original name - looking up + // the address in the executable file's symbol table would be + // needed. + return false; + case TemplateArgument::NullPtr: + // These could be rebuilt, but figured they're close enough to the + // declaration case, and not worth rebuilding. + return false; + case TemplateArgument::Pack: + // A pack is invalid if any of the elements of the pack are + // invalid. + return HasReconstitutableArgs(TA.getPackAsArray()); + case TemplateArgument::Integral: + // Larger integers get encoded as DWARF blocks which are a bit + // harder to parse back into a large integer, etc - so punting on + // this for now. Re-parsing the integers back into APInt is + // probably feasible some day. + return TA.getAsIntegral().getBitWidth() <= 64 && + IsReconstitutableType(TA.getIntegralType()); + case TemplateArgument::StructuralValue: + return false; + case TemplateArgument::Type: + return IsReconstitutableType(TA.getAsType()); + case TemplateArgument::Expression: + return IsReconstitutableType(TA.getAsExpr()->getType()); + default: + llvm_unreachable("Other, unresolved, template arguments should " + "not be seen here"); + } + }); +} + std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { std::string Name; llvm::raw_string_ostream OS(Name); @@ -5376,49 +5559,7 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { } else if (auto *VD = dyn_cast<VarDecl>(ND)) { Args = GetTemplateArgs(VD); } - std::function<bool(ArrayRef<TemplateArgument>)> HasReconstitutableArgs = - [&](ArrayRef<TemplateArgument> Args) { - return llvm::all_of(Args, [&](const TemplateArgument &TA) { - switch (TA.getKind()) { - case TemplateArgument::Template: - // Easy to reconstitute - the value of the parameter in the debug - // info is the string name of the template. (so the template name - // itself won't benefit from any name rebuilding, but that's a - // representational limitation - maybe DWARF could be - // changed/improved to use some more structural representation) - return true; - case TemplateArgument::Declaration: - // Reference and pointer non-type template parameters point to - // variables, functions, etc and their value is, at best (for - // variables) represented as an address - not a reference to the - // DWARF describing the variable/function/etc. This makes it hard, - // possibly impossible to rebuild the original name - looking up the - // address in the executable file's symbol table would be needed. - return false; - case TemplateArgument::NullPtr: - // These could be rebuilt, but figured they're close enough to the - // declaration case, and not worth rebuilding. - return false; - case TemplateArgument::Pack: - // A pack is invalid if any of the elements of the pack are invalid. - return HasReconstitutableArgs(TA.getPackAsArray()); - case TemplateArgument::Integral: - // Larger integers get encoded as DWARF blocks which are a bit - // harder to parse back into a large integer, etc - so punting on - // this for now. Re-parsing the integers back into APInt is probably - // feasible some day. - return TA.getAsIntegral().getBitWidth() <= 64 && - IsReconstitutableType(TA.getIntegralType()); - case TemplateArgument::StructuralValue: - return false; - case TemplateArgument::Type: - return IsReconstitutableType(TA.getAsType()); - default: - llvm_unreachable("Other, unresolved, template arguments should " - "not be seen here"); - } - }); - }; + // A conversion operator presents complications/ambiguity if there's a // conversion to class template that is itself a template, eg: // template<typename T> @@ -5636,6 +5777,48 @@ void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var, Var->addDebugInfo(GVE); } +void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder, + llvm::Instruction *Value, QualType Ty) { + // Only when -g2 or above is specified, debug info for variables will be + // generated. + if (CGM.getCodeGenOpts().getDebugInfo() <= + llvm::codegenoptions::DebugLineTablesOnly) + return; + + llvm::DILocation *DIL = Value->getDebugLoc().get(); + if (!DIL) + return; + + llvm::DIFile *Unit = DIL->getFile(); + llvm::DIType *Type = getOrCreateType(Ty, Unit); + + // Check if Value is already a declared variable and has debug info, in this + // case we have nothing to do. Clang emits a declared variable as alloca, and + // it is loaded upon use, so we identify such pattern here. + if (llvm::LoadInst *Load = dyn_cast<llvm::LoadInst>(Value)) { + llvm::Value *Var = Load->getPointerOperand(); + // There can be implicit type cast applied on a variable if it is an opaque + // ptr, in this case its debug info may not match the actual type of object + // being used as in the next instruction, so we will need to emit a pseudo + // variable for type-casted value. + auto DeclareTypeMatches = [&](auto *DbgDeclare) { + return DbgDeclare->getVariable()->getType() == Type; + }; + if (any_of(llvm::findDbgDeclares(Var), DeclareTypeMatches) || + any_of(llvm::findDVRDeclares(Var), DeclareTypeMatches)) + return; + } + + llvm::DILocalVariable *D = + DBuilder.createAutoVariable(LexicalBlockStack.back(), "", nullptr, 0, + Type, false, llvm::DINode::FlagArtificial); + + if (auto InsertPoint = Value->getInsertionPointAfterDef()) { + DBuilder.insertDbgValueIntrinsic(Value, D, DBuilder.createExpression(), DIL, + &**InsertPoint); + } +} + void CGDebugInfo::EmitGlobalAlias(const llvm::GlobalValue *GV, const GlobalDecl GD) { |