Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -315,7 +315,8 @@ uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DINode::DIFlags Flags, DIType *DerivedFrom, DINodeArray Elements, DIType *VTableHolder = nullptr, MDNode *TemplateParms = nullptr, - StringRef UniqueIdentifier = ""); + StringRef UniqueIdentifier = "", + dwarf::CallingConvention ArgABI = dwarf::DW_CC_normal); /// Create debugging information entry for a struct. /// \param Scope Scope in which this struct is defined. @@ -332,7 +333,8 @@ DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags, DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang = 0, - DIType *VTableHolder = nullptr, StringRef UniqueIdentifier = ""); + DIType *VTableHolder = nullptr, StringRef UniqueIdentifier = "", + dwarf::CallingConvention ArgABI = dwarf::DW_CC_normal); /// Create debugging information entry for an union. /// \param Scope Scope in which this union is defined. @@ -351,7 +353,9 @@ DINode::DIFlags Flags, DINodeArray Elements, unsigned RunTimeLang = 0, - StringRef UniqueIdentifier = ""); + StringRef UniqueIdentifier = "", + dwarf::CallingConvention ArgABI = + dwarf::DW_CC_normal); /// Create debugging information for template /// type parameter. @@ -462,7 +466,8 @@ unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, uint32_t AlignInBits = 0, DINode::DIFlags Flags = DINode::FlagFwdDecl, - StringRef UniqueIdentifier = ""); + StringRef UniqueIdentifier = "", + dwarf::CallingConvention ArgABI = dwarf::DW_CC_normal); /// Retain DIScope* in a module even if it is not referenced /// through debug info anchors. @@ -762,6 +767,9 @@ void replaceArrays(DICompositeType *&T, DINodeArray Elements, DINodeArray TParams = DINodeArray()); + /// Replace ArgABI on a composite type. + void replaceArgABI(DICompositeType *&T, dwarf::CallingConvention ArgABI); + /// Replace a temporary node. /// /// Call \a MDNode::replaceAllUsesWith() on \c N, replacing it with \c Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -813,23 +813,25 @@ friend class MDNode; unsigned RuntimeLang; + dwarf::CallingConvention ArgABI; DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, - ArrayRef Ops) + dwarf::CallingConvention ArgABI, ArrayRef Ops) : DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops), - RuntimeLang(RuntimeLang) {} + RuntimeLang(RuntimeLang), ArgABI(ArgABI) {} ~DICompositeType() = default; /// Change fields in place. void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang, - uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, DIFlags Flags) { + uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, + DIFlags Flags, dwarf::CallingConvention ArgABI) { assert(isDistinct() && "Only distinct nodes can mutate"); assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate"); this->RuntimeLang = RuntimeLang; + this->ArgABI = ArgABI; DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags); } @@ -839,12 +841,14 @@ uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang, DITypeRef VTableHolder, DITemplateParameterArray TemplateParams, - StringRef Identifier, StorageType Storage, bool ShouldCreate = true) { + StringRef Identifier, dwarf::CallingConvention ArgABI, + StorageType Storage, bool ShouldCreate = true) { return getImpl( Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), RuntimeLang, VTableHolder, TemplateParams.get(), - getCanonicalMDString(Context, Identifier), Storage, ShouldCreate); + getCanonicalMDString(Context, Identifier), ArgABI, Storage, + ShouldCreate); } static DICompositeType * getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, @@ -852,14 +856,15 @@ uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, - MDString *Identifier, StorageType Storage, bool ShouldCreate = true); + MDString *Identifier, dwarf::CallingConvention ArgABI, + StorageType Storage, bool ShouldCreate = true); TempDICompositeType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), getScope(), getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), getFlags(), getElements(), getRuntimeLang(), getVTableHolder(), - getTemplateParams(), getIdentifier()); + getTemplateParams(), getIdentifier(), getArgABI()); } public: @@ -870,10 +875,11 @@ DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang, DITypeRef VTableHolder, DITemplateParameterArray TemplateParams = nullptr, - StringRef Identifier = ""), + StringRef Identifier = "", + dwarf::CallingConvention ArgABI = dwarf::DW_CC_normal), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, - VTableHolder, TemplateParams, Identifier)) + VTableHolder, TemplateParams, Identifier, ArgABI)) DEFINE_MDNODE_GET(DICompositeType, (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, @@ -881,10 +887,11 @@ uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams = nullptr, - MDString *Identifier = nullptr), + MDString *Identifier = nullptr, + dwarf::CallingConvention ArgABI = dwarf::DW_CC_normal), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, - VTableHolder, TemplateParams, Identifier)) + VTableHolder, TemplateParams, Identifier, ArgABI)) TempDICompositeType clone() const { return cloneImpl(); } @@ -901,7 +908,7 @@ Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, - Metadata *TemplateParams); + Metadata *TemplateParams, dwarf::CallingConvention ArgABI); static DICompositeType *getODRTypeIfExists(LLVMContext &Context, MDString &Identifier); @@ -920,7 +927,7 @@ Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, - Metadata *TemplateParams); + Metadata *TemplateParams, dwarf::CallingConvention ArgABI); DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); } DINodeArray getElements() const { @@ -938,6 +945,7 @@ Metadata *getRawVTableHolder() const { return getOperand(5); } Metadata *getRawTemplateParams() const { return getOperand(6); } MDString *getRawIdentifier() const { return getOperandAs(7); } + dwarf::CallingConvention getArgABI() const { return ArgABI; } /// Replace operands. /// @@ -959,6 +967,9 @@ void replaceTemplateParams(DITemplateParameterArray TemplateParams) { replaceOperandWith(6, TemplateParams.get()); } + void replaceArgABI(dwarf::CallingConvention ArgABI) { + this->ArgABI = ArgABI; + } /// @} static bool classof(const Metadata *MD) { Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -3948,17 +3948,20 @@ OPTIONAL(runtimeLang, DwarfLangField, ); \ OPTIONAL(vtableHolder, MDField, ); \ OPTIONAL(templateParams, MDField, ); \ - OPTIONAL(identifier, MDStringField, ); + OPTIONAL(identifier, MDStringField, ); \ + OPTIONAL(argABI, DwarfCCField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS + dwarf::CallingConvention ArgABI = + static_cast(argABI.Val); // If this has an identifier try to build an ODR type. if (identifier.Val) if (auto *CT = DICompositeType::buildODRType( Context, *identifier.Val, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val, size.Val, align.Val, offset.Val, flags.Val, elements.Val, runtimeLang.Val, vtableHolder.Val, - templateParams.Val)) { + templateParams.Val, ArgABI)) { Result = CT; return false; } @@ -3969,7 +3972,8 @@ DICompositeType, (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val, size.Val, align.Val, offset.Val, flags.Val, elements.Val, - runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val)); + runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val, + ArgABI)); return false; } Index: lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- lib/Bitcode/Reader/MetadataLoader.cpp +++ lib/Bitcode/Reader/MetadataLoader.cpp @@ -1127,7 +1127,7 @@ break; } case bitc::METADATA_COMPOSITE_TYPE: { - if (Record.size() != 16) + if (Record.size() < 16) return error("Invalid record"); // If we have a UUID and this is not a forward declaration, lookup the @@ -1151,6 +1151,9 @@ Metadata *VTableHolder = nullptr; Metadata *TemplateParams = nullptr; auto *Identifier = getMDString(Record[15]); + dwarf::CallingConvention ArgABI = dwarf::DW_CC_normal; + if (Record.size() > 16) + ArgABI = static_cast(Record[16]); // If this module is being parsed so that it can be ThinLTO imported // into another module, composite types only need to be imported // as type declarations (unless full type definitions requested). @@ -1176,7 +1179,7 @@ CT = DICompositeType::buildODRType( Context, *Identifier, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, - VTableHolder, TemplateParams); + VTableHolder, TemplateParams, ArgABI); // Create a node if we didn't get a lazy ODR type. if (!CT) @@ -1184,7 +1187,7 @@ (Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, - Identifier)); + Identifier, ArgABI)); if (!IsNotUsedInTypeRef && Identifier) MetadataList.addTypeRef(*Identifier, *cast(CT)); Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1497,6 +1497,7 @@ Record.push_back(VE.getMetadataOrNullID(N->getVTableHolder())); Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams().get())); Record.push_back(VE.getMetadataOrNullID(N->getRawIdentifier())); + Record.push_back(N->getArgABI()); Stream.EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev); Record.clear(); Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -969,6 +969,22 @@ Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) addTemplateParams(Buffer, CTy->getTemplateParams()); + // Add DW_AT_calling_convention attr. + if (DD->getDwarfVersion() >= 5) { + auto ArgABI = CTy->getArgABI(); + // We do not emit DW_CC_normal: it is equivalent to absence of attribute. + // DWARFv5 5.7.1 Structure, Union and Class Type Entries + // If this attribute is not present, or its value is DW_CC_normal, + // the convention to be used for an object of the given type + // is assumed to be unspecified. + // ... + // If unspecified, a consumer may be able to deduce the calling + // convention based on knowledge of the type and the ABI. + if (ArgABI != dwarf::DW_CC_normal) + addSInt(Buffer, dwarf::DW_AT_calling_convention, + dwarf::DW_FORM_implicit_const, ArgABI); + } + break; } default: Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1421,6 +1421,7 @@ void printDwarfEnum(StringRef Name, IntTy Value, Stringifier toString, bool ShouldSkipZero = true); void printEmissionKind(StringRef Name, DICompileUnit::DebugEmissionKind EK); + void printArgABI(StringRef Name, dwarf::CallingConvention ArgABI); }; } // end namespace @@ -1518,6 +1519,12 @@ Out << FS << Name << ": " << DICompileUnit::EmissionKindString(EK); } +void MDFieldPrinter::printArgABI(StringRef Name, + dwarf::CallingConvention ArgABI) { + if (ArgABI == dwarf::DW_CC_normal) + return; + printDwarfEnum(Name, ArgABI, dwarf::ConventionString); +} template void MDFieldPrinter::printDwarfEnum(StringRef Name, IntTy Value, @@ -1638,6 +1645,7 @@ Printer.printMetadata("vtableHolder", N->getRawVTableHolder()); Printer.printMetadata("templateParams", N->getRawTemplateParams()); Printer.printString("identifier", N->getIdentifier()); + Printer.printArgABI("argABI", N->getArgABI()); Out << ")"; } Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -398,7 +398,8 @@ DIScope *Context, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DINode::DIFlags Flags, DIType *DerivedFrom, DINodeArray Elements, - DIType *VTableHolder, MDNode *TemplateParams, StringRef UniqueIdentifier) { + DIType *VTableHolder, MDNode *TemplateParams, StringRef UniqueIdentifier, + dwarf::CallingConvention ArgABI) { assert((!Context || isa(Context)) && "createClassType should be called with a valid Context"); @@ -415,7 +416,8 @@ DIScope *Context, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags, DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang, - DIType *VTableHolder, StringRef UniqueIdentifier) { + DIType *VTableHolder, StringRef UniqueIdentifier, + dwarf::CallingConvention ArgABI) { auto *R = DICompositeType::get( VMContext, dwarf::DW_TAG_structure_type, Name, File, LineNumber, getNonCompileUnitScope(Context), DerivedFrom, SizeInBits, AlignInBits, 0, @@ -427,7 +429,8 @@ DICompositeType *DIBuilder::createUnionType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags, - DINodeArray Elements, unsigned RunTimeLang, StringRef UniqueIdentifier) { + DINodeArray Elements, unsigned RunTimeLang, StringRef UniqueIdentifier, + dwarf::CallingConvention ArgABI) { auto *R = DICompositeType::get( VMContext, dwarf::DW_TAG_union_type, Name, File, LineNumber, getNonCompileUnitScope(Scope), nullptr, SizeInBits, AlignInBits, 0, Flags, @@ -533,12 +536,13 @@ DICompositeType *DIBuilder::createReplaceableCompositeType( unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits, - DINode::DIFlags Flags, StringRef UniqueIdentifier) { + DINode::DIFlags Flags, StringRef UniqueIdentifier, + dwarf::CallingConvention ArgABI) { auto *RetTy = DICompositeType::getTemporary( VMContext, Tag, Name, F, Line, getNonCompileUnitScope(Scope), nullptr, SizeInBits, AlignInBits, 0, Flags, nullptr, RuntimeLang, nullptr, - nullptr, UniqueIdentifier) + nullptr, UniqueIdentifier, ArgABI) .release(); trackIfUnresolved(RetTy); return RetTy; @@ -900,3 +904,10 @@ if (TParams) trackIfUnresolved(TParams.get()); } + +void DIBuilder::replaceArgABI(DICompositeType *&T, + dwarf::CallingConvention ArgABI) { + TypedTrackingMDRef N(T); + N->replaceArgABI(ArgABI); + T = N.get(); +} Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -262,19 +262,20 @@ unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, - Metadata *TemplateParams, MDString *Identifier, StorageType Storage, - bool ShouldCreate) { + Metadata *TemplateParams, MDString *Identifier, + dwarf::CallingConvention ArgABI, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); // Keep this in sync with buildODRType. DEFINE_GETIMPL_LOOKUP( DICompositeType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, - VTableHolder, TemplateParams, Identifier)); + VTableHolder, TemplateParams, Identifier, ArgABI)); Metadata *Ops[] = {File, Scope, Name, BaseType, Elements, VTableHolder, TemplateParams, Identifier}; DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits, - AlignInBits, OffsetInBits, Flags), + AlignInBits, OffsetInBits, Flags, + ArgABI), Ops); } @@ -283,7 +284,8 @@ Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, - Metadata *VTableHolder, Metadata *TemplateParams) { + Metadata *VTableHolder, Metadata *TemplateParams, + dwarf::CallingConvention ArgABI) { assert(!Identifier.getString().empty() && "Expected valid identifier"); if (!Context.isODRUniquingDebugTypes()) return nullptr; @@ -292,7 +294,7 @@ return CT = DICompositeType::getDistinct( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, - VTableHolder, TemplateParams, &Identifier); + VTableHolder, TemplateParams, &Identifier, ArgABI); // Only mutate CT if it's a forward declaration and the new operands aren't. assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?"); @@ -301,7 +303,7 @@ // Mutate CT in place. Keep this in sync with getImpl. CT->mutate(Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, - Flags); + Flags, ArgABI); Metadata *Ops[] = {File, Scope, Name, BaseType, Elements, VTableHolder, TemplateParams, &Identifier}; assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() && @@ -317,7 +319,8 @@ Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, - Metadata *VTableHolder, Metadata *TemplateParams) { + Metadata *VTableHolder, Metadata *TemplateParams, + dwarf::CallingConvention ArgABI) { assert(!Identifier.getString().empty() && "Expected valid identifier"); if (!Context.isODRUniquingDebugTypes()) return nullptr; @@ -326,7 +329,7 @@ CT = DICompositeType::getDistinct( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, - TemplateParams, &Identifier); + TemplateParams, &Identifier, ArgABI); return CT; } Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -439,18 +439,20 @@ Metadata *VTableHolder; Metadata *TemplateParams; MDString *Identifier; + dwarf::CallingConvention ArgABI; MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, - MDString *Identifier) + MDString *Identifier, dwarf::CallingConvention ArgABI) : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope), BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits), AlignInBits(AlignInBits), Flags(Flags), Elements(Elements), RuntimeLang(RuntimeLang), VTableHolder(VTableHolder), - TemplateParams(TemplateParams), Identifier(Identifier) {} + TemplateParams(TemplateParams), Identifier(Identifier), ArgABI(ArgABI) { + } MDNodeKeyImpl(const DICompositeType *N) : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Scope(N->getRawScope()), @@ -459,7 +461,7 @@ Flags(N->getFlags()), Elements(N->getRawElements()), RuntimeLang(N->getRuntimeLang()), VTableHolder(N->getRawVTableHolder()), TemplateParams(N->getRawTemplateParams()), - Identifier(N->getRawIdentifier()) {} + Identifier(N->getRawIdentifier()), ArgABI(N->getArgABI()) {} bool isKeyOf(const DICompositeType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && @@ -472,7 +474,8 @@ RuntimeLang == RHS->getRuntimeLang() && VTableHolder == RHS->getRawVTableHolder() && TemplateParams == RHS->getRawTemplateParams() && - Identifier == RHS->getRawIdentifier(); + Identifier == RHS->getRawIdentifier() && + ArgABI == RHS->getArgABI(); } unsigned getHashValue() const { // Intentionally computes the hash on a subset of the operands for Index: test/DebugInfo/X86/type-calling-convention.ll =================================================================== --- /dev/null +++ test/DebugInfo/X86/type-calling-convention.ll @@ -0,0 +1,92 @@ +; RUN: %llc_dwarf -filetype=obj < %s | llvm-dwarfdump -debug-dump=abbrev - | FileCheck %s +; REQUIRES: object-emission + +; Generated by clang++ -c -gdwarf-5 -std=c++11 -S -emit-llvm from the following C++ source +; +; struct DefaultDtor { +; ~DefaultDtor() = default; +; }; +; +; void f(DefaultDtor arg) {} +; +; class UserDtor { +; public: +; ~UserDtor() {} +; }; +; +; void f(UserDtor arg) {} +; + +; CHECK: DW_TAG_structure_type +; CHECK-NOT: DW_TAG +; CHECK: DW_AT_calling_convention{{[[:space:]]+}}DW_FORM_implicit_const{{[[:space:]]+}}5 +; CHECK: DW_TAG_class_type +; CHECK-NOT: DW_TAG +; CHECK: DW_AT_calling_convention{{[[:space:]]+}}DW_FORM_implicit_const{{[[:space:]]+}}4 + +; ModuleID = './debug-info-type-calling-conventions.cpp' +source_filename = "./debug-info-type-calling-conventions.cpp" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.DefaultDtor = type { i8 } +%class.UserDtor = type { i8 } + +; Function Attrs: noinline nounwind uwtable +define void @_Z1f11DefaultDtor() #0 !dbg !6 { +entry: + %arg = alloca %struct.DefaultDtor, align 1 + call void @llvm.dbg.declare(metadata %struct.DefaultDtor* %arg, metadata !16, metadata !17), !dbg !18 + ret void, !dbg !19 +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: noinline nounwind uwtable +define void @_Z1f8UserDtor(%class.UserDtor* %arg) #0 !dbg !20 { +entry: + call void @llvm.dbg.declare(metadata %class.UserDtor* %arg, metadata !29, metadata !30), !dbg !31 + ret void, !dbg !32 +} + +attributes #0 = { noinline nounwind uwtable } +attributes #1 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} +!llvm.ident = !{!5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (http://llvm.org/git/clang.git 57f502411c1b7567728ffbc60c428261c74fb96f) (http://llvm.org/git/llvm.git 4af197e7d57d3f8efb39c079c7df527f56604770)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "debug-info-type-calling-conventions.cpp", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{!"clang version 5.0.0 (http://llvm.org/git/clang.git 57f502411c1b7567728ffbc60c428261c74fb96f) (http://llvm.org/git/llvm.git 4af197e7d57d3f8efb39c079c7df527f56604770)"} +!6 = distinct !DISubprogram(name: "f", linkageName: "_Z1f11DefaultDtor", scope: !7, file: !7, line: 7, type: !8, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!7 = !DIFile(filename: "./debug-info-type-calling-conventions.cpp", directory: "/tmp") +!8 = !DISubroutineType(types: !9) +!9 = !{null, !10} +!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "DefaultDtor", file: !7, line: 3, size: 8, elements: !11, identifier: "_ZTS11DefaultDtor", argABI: DW_CC_pass_by_value) +!11 = !{!12} +!12 = !DISubprogram(name: "~DefaultDtor", scope: !10, file: !7, line: 4, type: !13, isLocal: false, isDefinition: false, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false) +!13 = !DISubroutineType(types: !14) +!14 = !{null, !15} +!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!16 = !DILocalVariable(name: "arg", arg: 1, scope: !6, file: !7, line: 7, type: !10) +!17 = !DIExpression() +!18 = !DILocation(line: 7, column: 20, scope: !6) +!19 = !DILocation(line: 7, column: 26, scope: !6) +!20 = distinct !DISubprogram(name: "f", linkageName: "_Z1f8UserDtor", scope: !7, file: !7, line: 16, type: !21, isLocal: false, isDefinition: true, scopeLine: 16, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!21 = !DISubroutineType(types: !22) +!22 = !{null, !23} +!23 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "UserDtor", file: !7, line: 11, size: 8, elements: !24, identifier: "_ZTS8UserDtor", argABI: DW_CC_pass_by_reference) +!24 = !{!25} +!25 = !DISubprogram(name: "~UserDtor", scope: !23, file: !7, line: 13, type: !26, isLocal: false, isDefinition: false, scopeLine: 13, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: false) +!26 = !DISubroutineType(types: !27) +!27 = !{null, !28} +!28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !23, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!29 = !DILocalVariable(name: "arg", arg: 1, scope: !20, file: !7, line: 16, type: !23) +!30 = !DIExpression(DW_OP_deref) +!31 = !DILocation(line: 16, column: 17, scope: !20) +!32 = !DILocation(line: 16, column: 23, scope: !20) Index: unittests/IR/DebugTypeODRUniquingTest.cpp =================================================================== --- unittests/IR/DebugTypeODRUniquingTest.cpp +++ unittests/IR/DebugTypeODRUniquingTest.cpp @@ -30,7 +30,8 @@ // Without a type map, this should return null. EXPECT_FALSE(DICompositeType::getODRType( Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, - nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr)); + nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, + dwarf::DW_CC_normal)); // Enable the mapping. There still shouldn't be a type. Context.enableDebugTypeODRUniquing(); @@ -39,7 +40,8 @@ // Create some ODR-uniqued type. auto &CT = *DICompositeType::getODRType( Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, - nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr); + nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, + dwarf::DW_CC_normal); EXPECT_EQ(UUID.getString(), CT.getIdentifier()); // Check that we get it back, even if we change a field. @@ -47,12 +49,13 @@ EXPECT_EQ(&CT, DICompositeType::getODRType( Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, - nullptr, nullptr)); + nullptr, nullptr, dwarf::DW_CC_normal)); EXPECT_EQ(&CT, DICompositeType::getODRType( Context, UUID, dwarf::DW_TAG_class_type, MDString::get(Context, "name"), nullptr, 0, nullptr, nullptr, 0, - 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr)); + 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, + dwarf::DW_CC_normal)); // Check that it's discarded with the type map. Context.disableDebugTypeODRUniquing(); @@ -71,32 +74,35 @@ MDString &UUID = *MDString::get(Context, "Type"); auto &CT = *DICompositeType::buildODRType( Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, - nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr); + nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, + dwarf::DW_CC_normal); EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID)); EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag()); // Update with another forward decl. This should be a no-op. EXPECT_EQ(&CT, DICompositeType::buildODRType( Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr, - nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr)); + nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, + dwarf::DW_CC_normal)); EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag()); // Update with a definition. This time we should see a change. EXPECT_EQ(&CT, DICompositeType::buildODRType( Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, - nullptr, 0, nullptr, nullptr)); + nullptr, 0, nullptr, nullptr, dwarf::DW_CC_normal)); EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag()); // Further updates should be ignored. EXPECT_EQ(&CT, DICompositeType::buildODRType( Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, - nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr)); + nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, + dwarf::DW_CC_normal)); EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag()); EXPECT_EQ(&CT, DICompositeType::buildODRType( Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, - nullptr, nullptr)); + nullptr, nullptr, dwarf::DW_CC_normal)); EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag()); } @@ -108,7 +114,7 @@ MDString &UUID = *MDString::get(Context, "UUID"); auto &CT = *DICompositeType::buildODRType( Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, - DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr); + DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, dwarf::DW_CC_normal); // Create macros for running through all the fields except Identifier and Flags. #define FOR_EACH_MDFIELD() \ @@ -125,7 +131,8 @@ DO_FOR_FIELD(SizeInBits) \ DO_FOR_FIELD(AlignInBits) \ DO_FOR_FIELD(OffsetInBits) \ - DO_FOR_FIELD(RuntimeLang) + DO_FOR_FIELD(RuntimeLang) \ + DO_FOR_FIELD(ArgABI) // Create all the fields. #define DO_FOR_FIELD(X) auto *X = MDString::get(Context, #X); @@ -141,7 +148,8 @@ DICompositeType::buildODRType( Context, UUID, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial, - Elements, RuntimeLang, VTableHolder, TemplateParams)); + Elements, RuntimeLang, VTableHolder, TemplateParams, + static_cast(ArgABI))); // Confirm that all the right fields got updated. #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());