Index: llvm/lib/Target/BPF/BTFDebug.h =================================================================== --- llvm/lib/Target/BPF/BTFDebug.h +++ llvm/lib/Target/BPF/BTFDebug.h @@ -337,6 +337,8 @@ void visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId, bool CheckPointer, bool SeenPointer); void visitMapDefType(const DIType *Ty, uint32_t &TypeId); + void visitMapDefType(const DIType *Ty); + bool maybeVisitInnerMapDefType(const DIDerivedType *DTy); /// @} /// Check whether the type is a forward declaration candidate or not. Index: llvm/lib/Target/BPF/BTFDebug.cpp =================================================================== --- llvm/lib/Target/BPF/BTFDebug.cpp +++ llvm/lib/Target/BPF/BTFDebug.cpp @@ -944,6 +944,25 @@ visitTypeEntry(Ty, TypeId, false, false); } +void BTFDebug::visitMapDefType(const DIType *Ty) { + uint32_t TypeId; + visitMapDefType(Ty, TypeId); +} + +bool BTFDebug::maybeVisitInnerMapDefType(const DIDerivedType *DTy) { + auto *ValuesTy = dyn_cast(DTy->getBaseType()); + if (!ValuesTy) + return false; + + auto *InnerMapDerivedTy = dyn_cast(ValuesTy->getBaseType()); + if (!InnerMapDerivedTy) + return false; + + auto *InnerMapTy = InnerMapDerivedTy->getBaseType(); + visitMapDefType(InnerMapTy); + return true; +} + void BTFDebug::visitMapDefType(const DIType *Ty, uint32_t &TypeId) { if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) { TypeId = DIToIdMap[Ty]; @@ -973,6 +992,10 @@ const DINodeArray Elements = CTy->getElements(); for (const auto *Element : Elements) { const auto *MemberType = cast(Element); + if (MemberType->getName().equals("values") && + maybeVisitInnerMapDefType(MemberType)) + continue; + visitTypeEntry(MemberType->getBaseType()); } Index: llvm/test/CodeGen/BPF/BTF/inner-map-def.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/BPF/BTF/inner-map-def.ll @@ -0,0 +1,175 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; +; Source code: +; struct keyval { +; u64 key; +; char whatever[16]; +; }; +; +; struct { +; __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); +; __uint(max_entries, 1000); +; __type(key, int); +; __type(value, int); +; __array(values, struct { +; __uint(type, BPF_MAP_TYPE_HASH); +; __uint(max_entries, 1000); +; __type(key, struct keyval); +; __type(value, int); +; }); +; } array_of_hash_maps __attribute__((section(".maps"))); +; Compilation Flags: +; clang -target bpf -O2 -mcpu=v3 -g -S -emit-llvm davemarchevsky_testcase.c +; +; CHECK: .long 25 # BTF_KIND_STRUCT( +; CHECK-SAME: id = 11 +; CHECK-SAME: name = keyval +; CHECK-NEXT: .long 67108866 # 0x4000002 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 32 +; CHECK-NEXT: .long 12 +; CHECK-NEXT: .long 0 # 0x0 +; CHECK-NEXT: .long 36 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 64 # 0x40 +; CHECK-NEXT: .long 45 # BTF_KIND_TYPEDEF( +; CHECK-SAME: id = 12 +; CHECK-SAME: name = u64 +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 13 +; CHECK-NEXT: .long 49 # BTF_KIND_TYPEDEF( +; CHECK-SAME: id = 13 +; CHECK-SAME: name = __u64 +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 14 +; CHECK-NEXT: .long 55 # BTF_KIND_INT( +; CHECK-SAME: id = 14 +; CHECK-SAME: name = unsigned long long +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 64 # 0x40 +; CHECK-NEXT: .long 74 # BTF_KIND_INT( +; CHECK-SAME: id = 15 +; CHECK-SAME: name = char +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK-NEXT: .long 0 # BTF_KIND_ARRAY( +; CHECK-SAME: id = 16 +; CHECK-SAME: name_off = 0 +; CHECK-NEXT: .long 50331648 # 0x3000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 15 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16 +; +; CHECK: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "__ARRAY_SIZE_TYPE__" # string offset=5 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "keyval" # string offset=25 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "key" # string offset=32 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "whatever" # string offset=36 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "u64" # string offset=45 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "__u64" # string offset=49 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "unsigned long long" # string offset=55 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "char" # string offset=74 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "type" # string offset=79 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "max_entries" # string offset=84 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "value" # string offset=96 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "values" # string offset=102 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "array_of_hash_maps" # string offset=109 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "_license" # string offset=128 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii ".maps" # string offset=137 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "license" # string offset=143 +; CHECK-NEXT: .byte 0 + +source_filename = "davemarchevsky_testcase.c" +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" +target triple = "bpf" + +%struct.anon = type { ptr, ptr, ptr, ptr, [0 x ptr] } + +@_license = dso_local global [4 x i8] c"GPL\00", section "license", align 1, !dbg !0 +@array_of_hash_maps = dso_local global %struct.anon zeroinitializer, section ".maps", align 8, !dbg !5 +@llvm.compiler.used = appending global [2 x ptr] [ptr @_license, ptr @array_of_hash_maps], section "llvm.metadata" + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!54, !55, !56, !57} +!llvm.ident = !{!58} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "_license", scope: !2, file: !3, line: 22, type: !51, 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 cd9cdc6837deddedb11d04174d6dceaa18a38395)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "davemarchevsky_testcase.c", directory: "tools/testing/selftests/bpf", checksumkind: CSK_MD5, checksum: "5267ac17a879d4b18cd30e84998cc810") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "array_of_hash_maps", scope: !2, file: !3, line: 20, type: !7, isLocal: false, isDefinition: true) +!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !3, line: 9, size: 256, elements: !8) +!8 = !{!9, !15, !20, !22, !23} +!9 = !DIDerivedType(tag: DW_TAG_member, name: "type", scope: !7, file: !3, line: 10, baseType: !10, size: 64) +!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64) +!11 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 384, elements: !13) +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !{!14} +!14 = !DISubrange(count: 12) +!15 = !DIDerivedType(tag: DW_TAG_member, name: "max_entries", scope: !7, file: !3, line: 11, baseType: !16, size: 64, offset: 64) +!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !17, size: 64) +!17 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 32000, elements: !18) +!18 = !{!19} +!19 = !DISubrange(count: 1000) +!20 = !DIDerivedType(tag: DW_TAG_member, name: "key", scope: !7, file: !3, line: 12, baseType: !21, size: 64, offset: 128) +!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!22 = !DIDerivedType(tag: DW_TAG_member, name: "value", scope: !7, file: !3, line: 13, baseType: !21, size: 64, offset: 192) +!23 = !DIDerivedType(tag: DW_TAG_member, name: "values", scope: !7, file: !3, line: 14, baseType: !24, offset: 256) +!24 = !DICompositeType(tag: DW_TAG_array_type, baseType: !25, elements: !49) +!25 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !26, size: 64) +!26 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !7, file: !3, line: 14, size: 256, elements: !27) +!27 = !{!28, !33, !34, !48} +!28 = !DIDerivedType(tag: DW_TAG_member, name: "type", scope: !26, file: !3, line: 14, baseType: !29, size: 64) +!29 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !30, size: 64) +!30 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 32, elements: !31) +!31 = !{!32} +!32 = !DISubrange(count: 1) +!33 = !DIDerivedType(tag: DW_TAG_member, name: "max_entries", scope: !26, file: !3, line: 14, baseType: !16, size: 64, offset: 64) +!34 = !DIDerivedType(tag: DW_TAG_member, name: "key", scope: !26, file: !3, line: 14, baseType: !35, size: 64, offset: 128) +!35 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !36, size: 64) +!36 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "keyval", file: !3, line: 4, size: 192, elements: !37) +!37 = !{!38, !43} +!38 = !DIDerivedType(tag: DW_TAG_member, name: "key", scope: !36, file: !3, line: 5, baseType: !39, size: 64) +!39 = !DIDerivedType(tag: DW_TAG_typedef, name: "u64", file: !40, line: 38, baseType: !41) +!40 = !DIFile(filename: "tools/testing/selftests/bpf/tools/include/vmlinux.h", directory: "", checksumkind: CSK_MD5, checksum: "5c0d4b3dbcb30687ab77c483aa5ed826") +!41 = !DIDerivedType(tag: DW_TAG_typedef, name: "__u64", file: !40, line: 22, baseType: !42) +!42 = !DIBasicType(name: "unsigned long long", size: 64, encoding: DW_ATE_unsigned) +!43 = !DIDerivedType(tag: DW_TAG_member, name: "whatever", scope: !36, file: !3, line: 6, baseType: !44, size: 128, offset: 64) +!44 = !DICompositeType(tag: DW_TAG_array_type, baseType: !45, size: 128, elements: !46) +!45 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!46 = !{!47} +!47 = !DISubrange(count: 16) +!48 = !DIDerivedType(tag: DW_TAG_member, name: "value", scope: !26, file: !3, line: 14, baseType: !21, size: 64, offset: 192) +!49 = !{!50} +!50 = !DISubrange(count: -1) +!51 = !DICompositeType(tag: DW_TAG_array_type, baseType: !45, size: 32, elements: !52) +!52 = !{!53} +!53 = !DISubrange(count: 4) +!54 = !{i32 7, !"Dwarf Version", i32 5} +!55 = !{i32 2, !"Debug Info Version", i32 3} +!56 = !{i32 1, !"wchar_size", i32 4} +!57 = !{i32 7, !"frame-pointer", i32 2} +!58 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git cd9cdc6837deddedb11d04174d6dceaa18a38395)"}