diff --git a/llvm/lib/Target/BPF/BTFDebug.h b/llvm/lib/Target/BPF/BTFDebug.h --- a/llvm/lib/Target/BPF/BTFDebug.h +++ b/llvm/lib/Target/BPF/BTFDebug.h @@ -255,6 +255,7 @@ std::map>> FixupDerivedTypes; std::setProtoFunctions; + uint32_t ByteTypeId; /// Add types to TypeEntries. /// @{ @@ -262,6 +263,8 @@ uint32_t addType(std::unique_ptr TypeEntry, const DIType *Ty); /// Add types to TypeEntries only and return type id. uint32_t addType(std::unique_ptr TypeEntry); + /// Add unknown types to TypeEntries and DIToIdMap. + uint32_t addUnknownType(const DIType *Ty); /// @} /// IR type visiting functions. @@ -319,6 +322,9 @@ /// Emit the .BTF.ext section. void emitBTFExtSection(); + /// Generate ArrayIndexTypeId unless it's already generated. + void generateArrayIndexTypeId(); + protected: /// Gather pre-function debug information. void beginFunctionImpl(const MachineFunction *MF) override; diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -387,7 +387,7 @@ BTFDebug::BTFDebug(AsmPrinter *AP) : DebugHandlerBase(AP), OS(*Asm->OutStreamer), SkipInstruction(false), LineInfoGenerated(false), SecNameOff(0), ArrayIndexTypeId(0), - MapDefNotCollected(true) { + MapDefNotCollected(true), ByteTypeId(0) { addString("\0"); } @@ -407,14 +407,33 @@ return Id; } +uint32_t BTFDebug::addUnknownType(const DIType *Ty) { + uint64_t SizeInBits = Ty->getSizeInBits(); + assert(SizeInBits % 8 == 0); + uint64_t SizeInBytes = SizeInBits / 8; + llvm::errs() << "Type `" << Ty->getName() + << "` is not supported by BTF, emitting `unsigned char[" + << SizeInBytes << "]` instead\n"; + if (!ByteTypeId) { + auto ByteTypeEntry = std::make_unique( + dwarf::DW_ATE_unsigned_char, 8, 0, "__BYTE_TYPE__"); + ByteTypeId = addType(std::move(ByteTypeEntry)); + } + auto TypeEntry = std::make_unique(ByteTypeId, SizeInBytes); + generateArrayIndexTypeId(); + return addType(std::move(TypeEntry), Ty); +} + void BTFDebug::visitBasicType(const DIBasicType *BTy, uint32_t &TypeId) { // Only int types are supported in BTF. uint32_t Encoding = BTy->getEncoding(); if (Encoding != dwarf::DW_ATE_boolean && Encoding != dwarf::DW_ATE_signed && Encoding != dwarf::DW_ATE_signed_char && Encoding != dwarf::DW_ATE_unsigned && - Encoding != dwarf::DW_ATE_unsigned_char) + Encoding != dwarf::DW_ATE_unsigned_char) { + TypeId = addUnknownType(BTy); return; + } // Create a BTF type instance for this DIBasicType and put it into // DIToIdMap for cross-type reference check. @@ -430,8 +449,10 @@ uint32_t &TypeId) { DITypeRefArray Elements = STy->getTypeArray(); uint32_t VLen = Elements.size() - 1; - if (VLen > BTF::MAX_VLEN) + if (VLen > BTF::MAX_VLEN) { + TypeId = addUnknownType(STy); return; + } // Subprogram has a valid non-zero-length name, and the pointee of // a function pointer has an empty name. The subprogram type will @@ -454,8 +475,10 @@ uint32_t &TypeId) { const DINodeArray Elements = CTy->getElements(); uint32_t VLen = Elements.size(); - if (VLen > BTF::MAX_VLEN) + if (VLen > BTF::MAX_VLEN) { + TypeId = addUnknownType(CTy); return; + } // Check whether we have any bitfield members or not bool HasBitField = false; @@ -509,18 +532,24 @@ // The IR does not have a type for array index while BTF wants one. // So create an array index type if there is none. - if (!ArrayIndexTypeId) { - auto TypeEntry = std::make_unique(dwarf::DW_ATE_unsigned, 32, - 0, "__ARRAY_SIZE_TYPE__"); - ArrayIndexTypeId = addType(std::move(TypeEntry)); - } + generateArrayIndexTypeId(); +} + +void BTFDebug::generateArrayIndexTypeId() { + if (ArrayIndexTypeId) + return; + auto TypeEntry = std::make_unique(dwarf::DW_ATE_unsigned, 32, 0, + "__ARRAY_SIZE_TYPE__"); + ArrayIndexTypeId = addType(std::move(TypeEntry)); } void BTFDebug::visitEnumType(const DICompositeType *CTy, uint32_t &TypeId) { DINodeArray Elements = CTy->getElements(); uint32_t VLen = Elements.size(); - if (VLen > BTF::MAX_VLEN) + if (VLen > BTF::MAX_VLEN) { + addUnknownType(CTy); return; + } auto TypeEntry = std::make_unique(CTy, VLen); TypeId = addType(std::move(TypeEntry), CTy); @@ -589,6 +618,7 @@ auto TypeEntry = std::make_unique(DTy, Tag, false); TypeId = addType(std::move(TypeEntry), DTy); } else if (Tag != dwarf::DW_TAG_member) { + addUnknownType(DTy); return; } diff --git a/llvm/test/CodeGen/BPF/BTF/double.ll b/llvm/test/CodeGen/BPF/BTF/double.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/double.ll @@ -0,0 +1,75 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s 2>&1 | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s 2>&1 | FileCheck -check-prefixes=CHECK %s + +; Source code: +; double a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = dso_local local_unnamed_addr global double 0.000000e+00, align 8, !dbg !0 + +; CHECK: Type `double` is not supported by BTF, emitting `unsigned char[8]` instead + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 96 +; CHECK-NEXT: .long 96 +; CHECK-NEXT: .long 42 +; [1] __BYTE_TYPE__, int, size=1 byte, unsigned, 8 bits +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 8 # 0x8 +; [2] __ARRAY_SIZE_TYPE__, int, size=4 bytes, unsigned, 32 bits +; CHECK-NEXT: .long 15 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 32 # 0x20 +; [3] array, type=__BYTE_TYPE__, index_type=__ARRAY_SIZE_TYPE__, nelems=8 +; CHECK-NEXT: .long 0 # BTF_KIND_ARRAY(id = 3) +; CHECK-NEXT: .long 50331648 # 0x3000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 8 +; [4] a, var, type=__BYTE_TYPE__[8], global +; CHECK-NEXT: .long 35 # BTF_KIND_VAR(id = 4) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 1 +; [5] .bss, datasec, 1 var, {a, offset=&a, size=8 bytes} +; CHECK-NEXT: .long 37 # BTF_KIND_DATASEC(id = 5) +; CHECK-NEXT: .long 251658241 # 0xf000001 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long a +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "__BYTE_TYPE__" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "__ARRAY_SIZE_TYPE__" # string offset=15 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 97 # string offset=35 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii ".bss" # string offset=37 +; CHECK-NEXT: .byte 0 + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 11.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float) +!7 = !{i32 7, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 11.0.0 "} diff --git a/llvm/test/CodeGen/BPF/BTF/float.ll b/llvm/test/CodeGen/BPF/BTF/float.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/float.ll @@ -0,0 +1,75 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s 2>&1 | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s 2>&1 | FileCheck -check-prefixes=CHECK %s + +; Source code: +; float a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = dso_local local_unnamed_addr global float 0.000000e+00, align 4, !dbg !0 + +; CHECK: Type `float` is not supported by BTF, emitting `unsigned char[4]` instead + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 96 +; CHECK-NEXT: .long 96 +; CHECK-NEXT: .long 42 +; [1] __BYTE_TYPE__, int, size=1 byte, unsigned, 8 bits +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 8 # 0x8 +; [2] __ARRAY_SIZE_TYPE__, int, size=4 bytes, unsigned, 32 bits +; CHECK-NEXT: .long 15 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 32 # 0x20 +; [3] array, type=__BYTE_TYPE__, index_type=__ARRAY_SIZE_TYPE__, nelems=4 +; CHECK-NEXT: .long 0 # BTF_KIND_ARRAY(id = 3) +; CHECK-NEXT: .long 50331648 # 0x3000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 4 +; [4] a, var, type=__BYTE_TYPE__[4], global +; CHECK-NEXT: .long 35 # BTF_KIND_VAR(id = 4) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 1 +; [5] .bss, datasec, 1 var, {a, offset=&a, size=4 bytes} +; CHECK-NEXT: .long 37 # BTF_KIND_DATASEC(id = 5) +; CHECK-NEXT: .long 251658241 # 0xf000001 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long a +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "__BYTE_TYPE__" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "__ARRAY_SIZE_TYPE__" # string offset=15 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 97 # string offset=35 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii ".bss" # string offset=37 +; CHECK-NEXT: .byte 0 + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 11.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!7 = !{i32 7, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 11.0.0 "}