diff --git a/llvm/lib/Target/BPF/BTF.h b/llvm/lib/Target/BPF/BTF.h --- a/llvm/lib/Target/BPF/BTF.h +++ b/llvm/lib/Target/BPF/BTF.h @@ -60,6 +60,7 @@ CommonTypeSize = 12, BTFArraySize = 12, BTFEnumSize = 8, + BTFEnum64Size = 12, BTFMemberSize = 12, BTFParamSize = 8, BTFDataSecVarSize = 12, @@ -145,6 +146,15 @@ int32_t Val; ///< Enum member value }; +/// BTF_KIND_ENUM64 is followed by multiple "struct BTFEnum64". +/// The exact number of BTFEnum64 is stored in the vlen (of the +/// info in "struct CommonType"). +struct BTFEnum64 { + uint32_t NameOff; ///< Enum name offset in the string table + uint32_t Val_Lo32; ///< Enum member lo32 value + uint32_t Val_Hi32; ///< Enum member hi32 value +}; + /// BTF_KIND_ARRAY is followed by one "struct BTFArray". struct BTFArray { uint32_t ElemType; ///< Element type diff --git a/llvm/lib/Target/BPF/BTF.def b/llvm/lib/Target/BPF/BTF.def --- a/llvm/lib/Target/BPF/BTF.def +++ b/llvm/lib/Target/BPF/BTF.def @@ -33,5 +33,6 @@ HANDLE_BTF_KIND(16, FLOAT) HANDLE_BTF_KIND(17, DECL_TAG) HANDLE_BTF_KIND(18, TYPE_TAG) +HANDLE_BTF_KIND(19, ENUM64) #undef HANDLE_BTF_KIND 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 @@ -103,7 +103,7 @@ std::vector EnumValues; public: - BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues); + BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned); uint32_t getSize() override { return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnumSize; } @@ -218,6 +218,20 @@ void emitType(MCStreamer &OS) override; }; +/// Handle 64-bit enumerate type. +class BTFTypeEnum64 : public BTFTypeBase { + const DICompositeType *ETy; + std::vector EnumValues; + +public: + BTFTypeEnum64(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned); + uint32_t getSize() override { + return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnum64Size; + } + void completeType(BTFDebug &BDebug) override; + void emitType(MCStreamer &OS) override; +}; + class BTFTypeTypeTag : public BTFTypeBase { const DIDerivedType *DTy; StringRef Tag; 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 @@ -162,9 +162,10 @@ OS.emitInt32(IntVal); } -BTFTypeEnum::BTFTypeEnum(const DICompositeType *ETy, uint32_t VLen) : ETy(ETy) { +BTFTypeEnum::BTFTypeEnum(const DICompositeType *ETy, uint32_t VLen, + bool IsSigned) : ETy(ETy) { Kind = BTF::BTF_KIND_ENUM; - BTFType.Info = Kind << 24 | VLen; + BTFType.Info = IsSigned << 31 | Kind << 24 | VLen; BTFType.Size = roundupToBytes(ETy->getSizeInBits()); } @@ -200,6 +201,48 @@ } } +BTFTypeEnum64::BTFTypeEnum64(const DICompositeType *ETy, uint32_t VLen, + bool IsSigned) : ETy(ETy) { + Kind = BTF::BTF_KIND_ENUM64; + BTFType.Info = IsSigned << 31 | Kind << 24 | VLen; + BTFType.Size = roundupToBytes(ETy->getSizeInBits()); +} + +void BTFTypeEnum64::completeType(BTFDebug &BDebug) { + if (IsCompleted) + return; + IsCompleted = true; + + BTFType.NameOff = BDebug.addString(ETy->getName()); + + DINodeArray Elements = ETy->getElements(); + for (const auto Element : Elements) { + const auto *Enum = cast(Element); + + struct BTF::BTFEnum64 BTFEnum; + BTFEnum.NameOff = BDebug.addString(Enum->getName()); + uint64_t Value; + if (Enum->isUnsigned()) + Value = static_cast(Enum->getValue().getZExtValue()); + else + Value = static_cast(Enum->getValue().getSExtValue()); + BTFEnum.Val_Lo32 = Value; + BTFEnum.Val_Hi32 = Value >> 32; + EnumValues.push_back(BTFEnum); + } +} + +void BTFTypeEnum64::emitType(MCStreamer &OS) { + BTFTypeBase::emitType(OS); + for (const auto &Enum : EnumValues) { + OS.emitInt32(Enum.NameOff); + OS.AddComment("0x" + Twine::utohexstr(Enum.Val_Lo32)); + OS.emitInt32(Enum.Val_Lo32); + OS.AddComment("0x" + Twine::utohexstr(Enum.Val_Hi32)); + OS.emitInt32(Enum.Val_Hi32); + } +} + BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems) { Kind = BTF::BTF_KIND_ARRAY; BTFType.NameOff = 0; @@ -674,8 +717,25 @@ if (VLen > BTF::MAX_VLEN) return; - auto TypeEntry = std::make_unique(CTy, VLen); - TypeId = addType(std::move(TypeEntry), CTy); + bool IsSigned = false; + unsigned NumBits = 32; + // No BaseType implies forward declaration in which case a + // BTFTypeEnum with Vlen = 0 is emitted. + if (CTy->getBaseType() != nullptr) { + const auto *BTy = cast(CTy->getBaseType()); + IsSigned = BTy->getEncoding() == dwarf::DW_ATE_signed || + BTy->getEncoding() == dwarf::DW_ATE_signed_char; + NumBits = BTy->getSizeInBits(); + } + + if (NumBits <= 32) { + auto TypeEntry = std::make_unique(CTy, VLen, IsSigned); + TypeId = addType(std::move(TypeEntry), CTy); + } else { + assert(NumBits == 64); + auto TypeEntry = std::make_unique(CTy, VLen, IsSigned); + TypeId = addType(std::move(TypeEntry), CTy); + } // No need to visit base type as BTF does not encode it. } diff --git a/llvm/test/CodeGen/BPF/BTF/enum-basic.ll b/llvm/test/CodeGen/BPF/BTF/enum-basic.ll --- a/llvm/test/CodeGen/BPF/BTF/enum-basic.ll +++ b/llvm/test/CodeGen/BPF/BTF/enum-basic.ll @@ -22,7 +22,7 @@ ; CHECK-NEXT: .long 28 ; CHECK-NEXT: .long 5 ; CHECK-NEXT: .long 0 # BTF_KIND_ENUM(id = 1) -; CHECK-NEXT: .long 100663298 # 0x6000002 +; CHECK-NEXT: .long 2248146946 # 0x86000002 ; CHECK-NEXT: .long 4 ; CHECK-NEXT: .long 1 ; CHECK-NEXT: .long -1 diff --git a/llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-enum-value-opaque-pointer.ll b/llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-enum-value-opaque-pointer.ll --- a/llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-enum-value-opaque-pointer.ll +++ b/llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-enum-value-opaque-pointer.ll @@ -36,7 +36,7 @@ ; CHECK: r{{[0-9]+}} = -2147483648 ll ; CHECK: exit -; CHECK: .long 16 # BTF_KIND_ENUM(id = 4) +; CHECK: .long 16 # BTF_KIND_ENUM64(id = 4) ; CHECK: .long 57 # BTF_KIND_TYPEDEF(id = 5) ; CHECK: .ascii ".text" # string offset=10 diff --git a/llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-enum-value.ll b/llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-enum-value.ll --- a/llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-enum-value.ll +++ b/llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-enum-value.ll @@ -36,14 +36,33 @@ ; CHECK: r{{[0-9]+}} = -2147483648 ll ; CHECK: exit -; CHECK: .long 16 # BTF_KIND_ENUM(id = 4) -; CHECK: .long 57 # BTF_KIND_TYPEDEF(id = 5) +; CHECK: .long 16 # BTF_KIND_ENUM64(id = 4) +; CHECK-NEXT: .long 2466250754 # 0x93000002 +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 19 +; CHECK-NEXT: .long 4294967196 # 0xffffff9c +; CHECK-NEXT: .long 4294967295 # 0xffffffff +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 4294934528 # 0xffff8000 +; CHECK-NEXT: .long 0 # 0x0 +; CHECK-NEXT: .long 57 # BTF_KIND_TYPEDEF(id = 5) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 6 +; CHECK-NEXT: .long 0 # BTF_KIND_ENUM64(id = 6) +; CHECK-NEXT: .long 318767105 # 0x13000001 +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 62 +; CHECK-NEXT: .long 2147483648 # 0x80000000 +; CHECK-NEXT: .long 4294967295 # 0xffffffff ; CHECK: .ascii ".text" # string offset=10 ; CHECK: .ascii "AA" # string offset=16 +; CHECK: .ascii "VAL1" # string offset=19 +; CHECK: .ascii "VAL2" # string offset=24 ; CHECK: .byte 48 # string offset=29 ; CHECK: .byte 49 # string offset=55 ; CHECK: .ascii "__BB" # string offset=57 +; CHECK: .ascii "VAL10" # string offset=62 ; CHECK: .long 16 # FieldReloc ; CHECK-NEXT: .long 10 # Field reloc section string offset=10