diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -817,40 +817,44 @@ static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, StorageType Storage, - bool ShouldCreate = true) { + DIFlags Flags, DINodeArray Annotations, + StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), - SizeInBits, AlignInBits, Encoding, Flags, Storage, - ShouldCreate); + SizeInBits, AlignInBits, Encoding, Flags, Annotations.get(), + Storage, ShouldCreate); } static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, StorageType Storage, - bool ShouldCreate = true); + DIFlags Flags, Metadata *Annotations, + StorageType Storage, bool ShouldCreate = true); TempDIBasicType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), - getAlignInBits(), getEncoding(), getFlags()); + getAlignInBits(), getEncoding(), getFlags(), + getAnnotations()); } public: DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name), - (Tag, Name, 0, 0, 0, FlagZero)) + (Tag, Name, 0, 0, 0, FlagZero, {})) DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name, uint64_t SizeInBits), - (Tag, Name, SizeInBits, 0, 0, FlagZero)) + (Tag, Name, SizeInBits, 0, 0, FlagZero, {})) DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, MDString *Name, uint64_t SizeInBits), - (Tag, Name, SizeInBits, 0, 0, FlagZero)) + (Tag, Name, SizeInBits, 0, 0, FlagZero, {})) DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), - (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) + uint32_t AlignInBits, unsigned Encoding, DIFlags Flags, + DINodeArray Annotations = {}), + (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, Annotations)) DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, MDString *Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), - (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) + uint32_t AlignInBits, unsigned Encoding, DIFlags Flags, + Metadata *Annotations), + (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, + Annotations)) TempDIBasicType clone() const { return cloneImpl(); } @@ -862,6 +866,16 @@ /// neither signed nor unsigned. std::optional getSignedness() const; + Metadata *getRawAnnotations() const { return getOperand(3); } + + DINodeArray getAnnotations() const { + return cast_or_null(getRawAnnotations()); + } + + void replaceAnnotations(DINodeArray Annotations) { + replaceOperandWith(3, Annotations.get()); + } + static bool classof(const Metadata *MD) { return MD->getMetadataID() == DIBasicTypeKind; } @@ -1054,6 +1068,10 @@ } Metadata *getRawAnnotations() const { return getOperand(5); } + void replaceAnnotations(DINodeArray Annotations) { + replaceOperandWith(5, Annotations.get()); + } + /// Get casted version of extra data. /// @{ DIType *getClassType() const; @@ -1271,6 +1289,10 @@ return cast_or_null(getRawAnnotations()); } + void replaceAnnotations(DINodeArray Annotations) { + replaceOperandWith(13, Annotations.get()); + } + /// Replace operands. /// /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision @@ -1317,26 +1339,32 @@ static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray, + DINodeArray Annotations, StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate); + return getImpl(Context, Flags, CC, TypeArray.get(), Annotations.get(), + Storage, ShouldCreate); } static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, uint8_t CC, Metadata *TypeArray, + Metadata *Annotations, StorageType Storage, bool ShouldCreate = true); TempDISubroutineType cloneImpl() const { - return getTemporary(getContext(), getFlags(), getCC(), getTypeArray()); + return getTemporary(getContext(), getFlags(), getCC(), getTypeArray(), + getAnnotations()); } public: DEFINE_MDNODE_GET(DISubroutineType, - (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray), - (Flags, CC, TypeArray)) + (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray, + DINodeArray Annotations = nullptr), + (Flags, CC, TypeArray, Annotations)) DEFINE_MDNODE_GET(DISubroutineType, - (DIFlags Flags, uint8_t CC, Metadata *TypeArray), - (Flags, CC, TypeArray)) + (DIFlags Flags, uint8_t CC, Metadata *TypeArray, + Metadata *Annotations = nullptr), + (Flags, CC, TypeArray, Annotations)) TempDISubroutineType clone() const { return cloneImpl(); } // Returns a new temporary DISubroutineType with updated CC @@ -1354,6 +1382,15 @@ Metadata *getRawTypeArray() const { return getOperand(3); } + Metadata *getRawAnnotations() const { return getOperand(4); } + DINodeArray getAnnotations() const { + return cast_or_null(getRawAnnotations()); + } + + void replaceAnnotations(DINodeArray Annotations) { + replaceOperandWith(4, Annotations.get()); + } + static bool classof(const Metadata *MD) { return MD->getMetadataID() == DISubroutineTypeKind; } diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -4906,7 +4906,7 @@ /// parseDIBasicType: /// ::= !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, -/// encoding: DW_ATE_encoding, flags: 0) +/// encoding: DW_ATE_encoding, flags: 0, annotations: !1) bool LLParser::parseDIBasicType(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_base_type)); \ @@ -4914,12 +4914,14 @@ OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ OPTIONAL(encoding, DwarfAttEncodingField, ); \ - OPTIONAL(flags, DIFlagField, ); + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(annotations, MDField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val, size.Val, - align.Val, encoding.Val, flags.Val)); + align.Val, encoding.Val, flags.Val, + annotations.Val)); return false; } @@ -5041,12 +5043,14 @@ #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ OPTIONAL(flags, DIFlagField, ); \ OPTIONAL(cc, DwarfCCField, ); \ - REQUIRED(types, MDField, ); + REQUIRED(types, MDField, ); \ + OPTIONAL(annotations, MDField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS Result = GET_OR_DISTINCT(DISubroutineType, - (Context, flags.Val, cc.Val, types.Val)); + (Context, flags.Val, cc.Val, types.Val, + annotations.Val)); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1417,7 +1417,7 @@ break; } case bitc::METADATA_BASIC_TYPE: { - if (Record.size() < 6 || Record.size() > 7) + if (Record.size() < 6 || Record.size() > 8) return error("Invalid record"); IsDistinct = Record[0]; @@ -1425,10 +1425,14 @@ ? static_cast(Record[6]) : DINode::FlagZero; + Metadata *Annotations = nullptr; + if (Record.size() > 7 && Record[7]) + Annotations = getMDOrNull(Record[7]); + MetadataList.assignValue( GET_OR_DISTINCT(DIBasicType, (Context, Record[1], getMDString(Record[2]), Record[3], - Record[4], Record[5], Flags)), + Record[4], Record[5], Flags, Annotations)), NextMetadataNo); NextMetadataNo++; break; @@ -1579,7 +1583,7 @@ break; } case bitc::METADATA_SUBROUTINE_TYPE: { - if (Record.size() < 3 || Record.size() > 4) + if (Record.size() < 3 || Record.size() > 5) return error("Invalid record"); bool IsOldTypeRefArray = Record[0] < 2; unsigned CC = (Record.size() > 3) ? Record[3] : 0; @@ -1589,9 +1593,13 @@ Metadata *Types = getMDOrNull(Record[2]); if (LLVM_UNLIKELY(IsOldTypeRefArray)) Types = MetadataList.upgradeTypeRefArray(Types); + Metadata *Annotations = nullptr; + if (Record.size() > 4 && Record[4]) + Annotations = getMDOrNull(Record[4]); MetadataList.assignValue( - GET_OR_DISTINCT(DISubroutineType, (Context, Flags, CC, Types)), + GET_OR_DISTINCT(DISubroutineType, (Context, Flags, CC, Types, + Annotations)), NextMetadataNo); NextMetadataNo++; break; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1711,6 +1711,7 @@ Record.push_back(N->getAlignInBits()); Record.push_back(N->getEncoding()); Record.push_back(N->getFlags()); + Record.push_back(VE.getMetadataOrNullID(N->getRawAnnotations())); Stream.EmitRecord(bitc::METADATA_BASIC_TYPE, Record, Abbrev); Record.clear(); @@ -1801,6 +1802,7 @@ Record.push_back(N->getFlags()); Record.push_back(VE.getMetadataOrNullID(N->getTypeArray().get())); Record.push_back(N->getCC()); + Record.push_back(VE.getMetadataOrNullID(N->getRawAnnotations())); Stream.EmitRecord(bitc::METADATA_SUBROUTINE_TYPE, Record, Abbrev); Record.clear(); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -710,6 +710,8 @@ addUInt(Buffer, dwarf::DW_AT_endianity, std::nullopt, dwarf::DW_END_big); else if (BTy->isLittleEndian()) addUInt(Buffer, dwarf::DW_AT_endianity, std::nullopt, dwarf::DW_END_little); + + addAnnotation(Buffer, BTy->getAnnotations()); } void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIStringType *STy) { @@ -847,6 +849,8 @@ if (CTy->isRValueReference()) addFlag(Buffer, dwarf::DW_AT_rvalue_reference); + + addAnnotation(Buffer, CTy->getAnnotations()); } void DwarfUnit::addAnnotation(DIE &Buffer, DINodeArray Annotations) { diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1987,9 +1987,9 @@ } static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N, - AsmWriterContext &) { + AsmWriterContext &WriterCtx) { Out << "!DIBasicType("; - MDFieldPrinter Printer(Out); + MDFieldPrinter Printer(Out, WriterCtx); if (N->getTag() != dwarf::DW_TAG_base_type) Printer.printTag(N); Printer.printString("name", N->getName()); @@ -1998,6 +1998,7 @@ Printer.printDwarfEnum("encoding", N->getEncoding(), dwarf::AttributeEncodingString); Printer.printDIFlags("flags", N->getFlags()); + Printer.printMetadata("annotations", N->getRawAnnotations()); Out << ")"; } @@ -2083,6 +2084,7 @@ Printer.printDwarfEnum("cc", N->getCC(), dwarf::ConventionString); Printer.printMetadata("types", N->getRawTypeArray(), /* ShouldSkipNull */ false); + Printer.printMetadata("annotations", N->getRawAnnotations()); Out << ")"; } diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -592,12 +592,12 @@ DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, StorageType Storage, - bool ShouldCreate) { + DIFlags Flags, Metadata *Annotations, + StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIBasicType, (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)); - Metadata *Ops[] = {nullptr, nullptr, Name}; + Metadata *Ops[] = {nullptr, nullptr, Name, Annotations}; DEFINE_GETIMPL_STORE(DIBasicType, (Tag, SizeInBits, AlignInBits, Encoding, Flags), Ops); } @@ -793,10 +793,11 @@ DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags, uint8_t CC, Metadata *TypeArray, + Metadata *Annotations, StorageType Storage, bool ShouldCreate) { - DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, CC, TypeArray)); - Metadata *Ops[] = {nullptr, nullptr, nullptr, TypeArray}; + DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, CC, TypeArray, Annotations)); + Metadata *Ops[] = {nullptr, nullptr, nullptr, TypeArray, Annotations}; DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops); } diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -465,25 +465,27 @@ uint32_t AlignInBits; unsigned Encoding; unsigned Flags; + Metadata *Annotations; MDNodeKeyImpl(unsigned Tag, MDString *Name, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, unsigned Flags) : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits), - Encoding(Encoding), Flags(Flags) {} + Encoding(Encoding), Flags(Flags), Annotations(nullptr) {} MDNodeKeyImpl(const DIBasicType *N) : Tag(N->getTag()), Name(N->getRawName()), SizeInBits(N->getSizeInBits()), AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()), - Flags(N->getFlags()) {} + Flags(N->getFlags()), Annotations(N->getRawAnnotations()) {} bool isKeyOf(const DIBasicType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && SizeInBits == RHS->getSizeInBits() && AlignInBits == RHS->getAlignInBits() && - Encoding == RHS->getEncoding() && Flags == RHS->getFlags(); + Encoding == RHS->getEncoding() && Flags == RHS->getFlags() && + Annotations == RHS->getRawAnnotations(); } unsigned getHashValue() const { - return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding); + return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding, Annotations); } }; @@ -698,18 +700,24 @@ unsigned Flags; uint8_t CC; Metadata *TypeArray; + Metadata *Annotations; - MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray) - : Flags(Flags), CC(CC), TypeArray(TypeArray) {} + MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray, + Metadata *Annotations) + : Flags(Flags), CC(CC), TypeArray(TypeArray), + Annotations(Annotations) {} MDNodeKeyImpl(const DISubroutineType *N) - : Flags(N->getFlags()), CC(N->getCC()), TypeArray(N->getRawTypeArray()) {} + : Flags(N->getFlags()), CC(N->getCC()), TypeArray(N->getRawTypeArray()), + Annotations(N->getRawAnnotations()) {} bool isKeyOf(const DISubroutineType *RHS) const { return Flags == RHS->getFlags() && CC == RHS->getCC() && - TypeArray == RHS->getRawTypeArray(); + TypeArray == RHS->getRawTypeArray() && + Annotations == RHS->getRawAnnotations(); } - unsigned getHashValue() const { return hash_combine(Flags, CC, TypeArray); } + unsigned getHashValue() const { return hash_combine(Flags, CC, TypeArray, + Annotations); } }; template <> struct MDNodeKeyImpl { diff --git a/llvm/test/Bitcode/attr-btf_tag-dibasic.ll b/llvm/test/Bitcode/attr-btf_tag-dibasic.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/attr-btf_tag-dibasic.ll @@ -0,0 +1,36 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s +; +; Source: +; #define __tag1 __attribute__((btf_type_tag("tag1"))) +; int __tag1 g; +; Compilation flag: +; clang -S -g -emit-llvm test.c + +@g = dso_local global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10, !11, !12, !13, !14} +!llvm.ident = !{!15} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 2, type: !5, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "test.c", directory: "/home/eddy/work/tmp", checksumkind: CSK_MD5, checksum: "79feb01d60b549b43abc493c324fe2a8") +!4 = !{!0} +!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed, annotations: !6) +!6 = !{!7} +!7 = !{!"btf_type_tag", !"tag1", i16 24577} + +; CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L1:[0-9]+]], isLocal: false, isDefinition: true) +; CHECK: ![[L1]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L2:[0-9]+]]) +; CHECK: ![[L2]] = !{![[L3:[0-9]+]]} +; CHECK: ![[L3]] = !{!"btf_type_tag", !"tag1", i16 24577} + +!8 = !{i32 7, !"Dwarf Version", i32 5} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 8, !"PIC Level", i32 2} +!12 = !{i32 7, !"PIE Level", i32 2} +!13 = !{i32 7, !"uwtable", i32 2} +!14 = !{i32 7, !"frame-pointer", i32 2} +!15 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)"} diff --git a/llvm/test/Bitcode/attr-btf_tag-disubroutine.ll b/llvm/test/Bitcode/attr-btf_tag-disubroutine.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/attr-btf_tag-disubroutine.ll @@ -0,0 +1,41 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s +; +; Source: +; #define __tag1 __attribute__((btf_type_tag("tag1"))) +; int (__tag1 * g)(void); + +; Compilation flag: +; clang -S -g -emit-llvm test.c + +@g = dso_local global ptr null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!11, !12, !13, !14, !15, !16, !17} +!llvm.ident = !{!18} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 2, type: !5, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "test.c", directory: "/home/eddy/work/tmp", checksumkind: CSK_MD5, checksum: "2ed8742fd12b44b948de1ac5e433bd63") +!4 = !{!0} +!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64) +!6 = !DISubroutineType(types: !7, annotations: !9) +!7 = !{!8} +!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!9 = !{!10} +!10 = !{!"btf_type_tag", !"tag1", i16 24577} + +; CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L1:[0-9]+]], isLocal: false, isDefinition: true) +; CHECK: ![[L1]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L2:[0-9]+]], size: [[#]]) +; CHECK: ![[L2]] = !DISubroutineType(types: ![[#]], annotations: ![[L3:[0-9]+]]) +; CHECK: ![[L3]] = !{![[L4:[0-9]+]]} +; CHECK: ![[L4]] = !{!"btf_type_tag", !"tag1", i16 24577} + +!11 = !{i32 7, !"Dwarf Version", i32 5} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{i32 1, !"wchar_size", i32 4} +!14 = !{i32 8, !"PIC Level", i32 2} +!15 = !{i32 7, !"PIE Level", i32 2} +!16 = !{i32 7, !"uwtable", i32 2} +!17 = !{i32 7, !"frame-pointer", i32 2} +!18 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)"}