[llvm] dc1c43d - [BPF] Add BTF 64bit enum value support
Yonghong Song via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 6 11:36:03 PDT 2022
Author: Yonghong Song
Date: 2022-06-06T11:35:50-07:00
New Revision: dc1c43d726c87e18fae33cb26f2cd05dbd1fdfa5
URL: https://github.com/llvm/llvm-project/commit/dc1c43d726c87e18fae33cb26f2cd05dbd1fdfa5
DIFF: https://github.com/llvm/llvm-project/commit/dc1c43d726c87e18fae33cb26f2cd05dbd1fdfa5.diff
LOG: [BPF] Add BTF 64bit enum value support
Current BTF only supports 32-bit value. For example,
enum T { VAL = 0xffffFFFF00000008 };
the generated BTF looks like
.long 16 # BTF_KIND_ENUM(id = 4)
.long 100663297 # 0x6000001
.long 8
.long 18
.long 8
The encoded value is 8 which equals to (uint32_t)0xffffFFFF00000008
and this is incorrect.
This patch introduced BTF_KIND_ENUM64 which permits to encode
64-bit value. The format for each enumerator looks like:
.long name_offset
.long (uint32_t)value # lower-32 bit value
.long value >> 32 # high-32 bit value
We use two 32-bit values to represent a 64-bit value as current
BTF type subsection has 4-byte alignment and gaps are not permitted
in the subsection.
This patch also added support for kflag (the bit 31 of CommonType.Info)
such that kflag = 1 implies the value is signed and kflag = 0
implies the value is unsigned. The kernel UAPI enumerator definition is
struct btf_enum {
__u32 name_off;
__s32 val;
};
so kflag = 0 with unsigned value provides backward compatability.
With this patch, for
enum T { VAL = 0xffffFFFF00000008 };
the generated BTF looks like
.long 16 # BTF_KIND_ENUM64(id = 4)
.long 3187671053 # 0x13000001
.long 8
.long 18
.long 8 # 0x8
.long 4294967295 # 0xffffffff
and the enumerator value and signedness are encoded correctly.
Differential Revision: https://reviews.llvm.org/D124641
Added:
Modified:
llvm/lib/Target/BPF/BTF.def
llvm/lib/Target/BPF/BTF.h
llvm/lib/Target/BPF/BTFDebug.cpp
llvm/lib/Target/BPF/BTFDebug.h
llvm/test/CodeGen/BPF/BTF/enum-basic.ll
llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-enum-value-opaque-pointer.ll
llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-enum-value.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/BPF/BTF.def b/llvm/lib/Target/BPF/BTF.def
index 0ae4194bc512..1de0e51b4757 100644
--- a/llvm/lib/Target/BPF/BTF.def
+++ b/llvm/lib/Target/BPF/BTF.def
@@ -33,5 +33,6 @@ HANDLE_BTF_KIND(15, DATASEC)
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/BTF.h b/llvm/lib/Target/BPF/BTF.h
index e54b97cd49a9..4540054aaf34 100644
--- a/llvm/lib/Target/BPF/BTF.h
+++ b/llvm/lib/Target/BPF/BTF.h
@@ -60,6 +60,7 @@ enum {
CommonTypeSize = 12,
BTFArraySize = 12,
BTFEnumSize = 8,
+ BTFEnum64Size = 12,
BTFMemberSize = 12,
BTFParamSize = 8,
BTFDataSecVarSize = 12,
@@ -145,6 +146,15 @@ struct BTFEnum {
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/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp
index 03bb1f67992e..4e23180227bd 100644
--- a/llvm/lib/Target/BPF/BTFDebug.cpp
+++ b/llvm/lib/Target/BPF/BTFDebug.cpp
@@ -162,9 +162,10 @@ void BTFTypeInt::emitType(MCStreamer &OS) {
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 @@ void BTFTypeEnum::emitType(MCStreamer &OS) {
}
}
+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<DIEnumerator>(Element);
+
+ struct BTF::BTFEnum64 BTFEnum;
+ BTFEnum.NameOff = BDebug.addString(Enum->getName());
+ uint64_t Value;
+ if (Enum->isUnsigned())
+ Value = static_cast<uint64_t>(Enum->getValue().getZExtValue());
+ else
+ Value = static_cast<uint64_t>(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 @@ void BTFDebug::visitEnumType(const DICompositeType *CTy, uint32_t &TypeId) {
if (VLen > BTF::MAX_VLEN)
return;
- auto TypeEntry = std::make_unique<BTFTypeEnum>(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<DIBasicType>(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<BTFTypeEnum>(CTy, VLen, IsSigned);
+ TypeId = addType(std::move(TypeEntry), CTy);
+ } else {
+ assert(NumBits == 64);
+ auto TypeEntry = std::make_unique<BTFTypeEnum64>(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/lib/Target/BPF/BTFDebug.h b/llvm/lib/Target/BPF/BTFDebug.h
index e328b19e6c9c..1ad8ec5d918c 100644
--- a/llvm/lib/Target/BPF/BTFDebug.h
+++ b/llvm/lib/Target/BPF/BTFDebug.h
@@ -103,7 +103,7 @@ class BTFTypeEnum : public BTFTypeBase {
std::vector<struct BTF::BTFEnum> 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 @@ class BTFTypeDeclTag : public BTFTypeBase {
void emitType(MCStreamer &OS) override;
};
+/// Handle 64-bit enumerate type.
+class BTFTypeEnum64 : public BTFTypeBase {
+ const DICompositeType *ETy;
+ std::vector<struct BTF::BTFEnum64> 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/test/CodeGen/BPF/BTF/enum-basic.ll b/llvm/test/CodeGen/BPF/BTF/enum-basic.ll
index 49114a56c059..9a82a36c8975 100644
--- 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
index 2acf942d3503..b6013bb07590 100644
--- 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 @@ entry:
; 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
index 3fa6ae1b22b3..7692c4c432b2 100644
--- 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 @@ entry:
; 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
More information about the llvm-commits
mailing list