aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp')
-rw-r--r--llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp50
1 files changed, 33 insertions, 17 deletions
diff --git a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
index 46141e69d9d4..349cdd92ae62 100644
--- a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
+++ b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
@@ -77,6 +77,7 @@
#include "BPF.h"
#include "BPFCORE.h"
#include "BPFTargetMachine.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instruction.h"
@@ -123,7 +124,7 @@ public:
struct CallInfo {
uint32_t Kind;
uint32_t AccessIndex;
- Align RecordAlignment;
+ MaybeAlign RecordAlignment;
MDNode *Metadata;
Value *Base;
};
@@ -142,9 +143,9 @@ private:
Module *M = nullptr;
static std::map<std::string, GlobalVariable *> GEPGlobals;
- // A map to link preserve_*_access_index instrinsic calls.
+ // A map to link preserve_*_access_index intrinsic calls.
std::map<CallInst *, std::pair<CallInst *, CallInfo>> AIChain;
- // A map to hold all the base preserve_*_access_index instrinsic calls.
+ // A map to hold all the base preserve_*_access_index intrinsic calls.
// The base call is not an input of any other preserve_*
// intrinsics.
std::map<CallInst *, CallInfo> BaseAICalls;
@@ -169,7 +170,7 @@ private:
uint32_t &StartBitOffset, uint32_t &EndBitOffset);
uint32_t GetFieldInfo(uint32_t InfoKind, DICompositeType *CTy,
uint32_t AccessIndex, uint32_t PatchImm,
- Align RecordAlignment);
+ MaybeAlign RecordAlignment);
Value *computeBaseAndAccessKey(CallInst *Call, CallInfo &CInfo,
std::string &AccessKey, MDNode *&BaseMeta);
@@ -270,7 +271,7 @@ static uint32_t calcArraySize(const DICompositeType *CTy, uint32_t StartDim) {
static Type *getBaseElementType(const CallInst *Call) {
// Element type is stored in an elementtype() attribute on the first param.
- return Call->getAttributes().getParamElementType(0);
+ return Call->getParamElementType(0);
}
/// Check whether a call is a preserve_*_access_index intrinsic call or not.
@@ -299,8 +300,6 @@ bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
report_fatal_error("Missing metadata for llvm.preserve.union.access.index intrinsic");
CInfo.AccessIndex = getConstant(Call->getArgOperand(1));
CInfo.Base = Call->getArgOperand(0);
- CInfo.RecordAlignment =
- DL->getABITypeAlign(CInfo.Base->getType()->getPointerElementType());
return true;
}
if (GV->getName().startswith("llvm.preserve.struct.access.index")) {
@@ -333,6 +332,8 @@ bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
report_fatal_error("Incorrect flag for llvm.bpf.preserve.type.info intrinsic");
if (Flag == BPFCoreSharedInfo::PRESERVE_TYPE_INFO_EXISTENCE)
CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_EXISTENCE;
+ else if (Flag == BPFCoreSharedInfo::PRESERVE_TYPE_INFO_MATCH)
+ CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_MATCH;
else
CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_SIZE;
return true;
@@ -592,10 +593,20 @@ void BPFAbstractMemberAccess::GetStorageBitRange(DIDerivedType *MemberTy,
uint32_t &EndBitOffset) {
uint32_t MemberBitSize = MemberTy->getSizeInBits();
uint32_t MemberBitOffset = MemberTy->getOffsetInBits();
+
+ if (RecordAlignment > 8) {
+ // If the Bits are within an aligned 8-byte, set the RecordAlignment
+ // to 8, other report the fatal error.
+ if (MemberBitOffset / 64 != (MemberBitOffset + MemberBitSize) / 64)
+ report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, "
+ "requiring too big alignment");
+ RecordAlignment = Align(8);
+ }
+
uint32_t AlignBits = RecordAlignment.value() * 8;
- if (RecordAlignment > 8 || MemberBitSize > AlignBits)
+ if (MemberBitSize > AlignBits)
report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, "
- "requiring too big alignment");
+ "bitfield size greater than record alignment");
StartBitOffset = MemberBitOffset & ~(AlignBits - 1);
if ((StartBitOffset + AlignBits) < (MemberBitOffset + MemberBitSize))
@@ -608,7 +619,7 @@ uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind,
DICompositeType *CTy,
uint32_t AccessIndex,
uint32_t PatchImm,
- Align RecordAlignment) {
+ MaybeAlign RecordAlignment) {
if (InfoKind == BPFCoreSharedInfo::FIELD_EXISTENCE)
return 1;
@@ -624,7 +635,7 @@ uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind,
PatchImm += MemberTy->getOffsetInBits() >> 3;
} else {
unsigned SBitOffset, NextSBitOffset;
- GetStorageBitRange(MemberTy, RecordAlignment, SBitOffset,
+ GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset,
NextSBitOffset);
PatchImm += SBitOffset >> 3;
}
@@ -643,7 +654,8 @@ uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind,
return SizeInBits >> 3;
unsigned SBitOffset, NextSBitOffset;
- GetStorageBitRange(MemberTy, RecordAlignment, SBitOffset, NextSBitOffset);
+ GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset,
+ NextSBitOffset);
SizeInBits = NextSBitOffset - SBitOffset;
if (SizeInBits & (SizeInBits - 1))
report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info");
@@ -703,7 +715,7 @@ uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind,
}
unsigned SBitOffset, NextSBitOffset;
- GetStorageBitRange(MemberTy, RecordAlignment, SBitOffset, NextSBitOffset);
+ GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, NextSBitOffset);
if (NextSBitOffset - SBitOffset > 64)
report_fatal_error("too big field size for llvm.bpf.preserve.field.info");
@@ -734,7 +746,7 @@ uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind,
}
unsigned SBitOffset, NextSBitOffset;
- GetStorageBitRange(MemberTy, RecordAlignment, SBitOffset, NextSBitOffset);
+ GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, NextSBitOffset);
if (NextSBitOffset - SBitOffset > 64)
report_fatal_error("too big field size for llvm.bpf.preserve.field.info");
@@ -923,7 +935,8 @@ MDNode *BPFAbstractMemberAccess::computeAccessKey(CallInst *Call,
int64_t PatchImm;
std::string AccessStr("0");
- if (CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_EXISTENCE) {
+ if (CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_EXISTENCE ||
+ CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_MATCH) {
PatchImm = 1;
} else if (CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_SIZE) {
// typedef debuginfo type has size 0, get the eventual base type.
@@ -933,8 +946,11 @@ MDNode *BPFAbstractMemberAccess::computeAccessKey(CallInst *Call,
// ENUM_VALUE_EXISTENCE and ENUM_VALUE
IsInt32Ret = false;
- const auto *CE = cast<ConstantExpr>(Call->getArgOperand(1));
- const GlobalVariable *GV = cast<GlobalVariable>(CE->getOperand(0));
+ // The argument could be a global variable or a getelementptr with base to
+ // a global variable depending on whether the clang option `opaque-options`
+ // is set or not.
+ const GlobalVariable *GV =
+ cast<GlobalVariable>(Call->getArgOperand(1)->stripPointerCasts());
assert(GV->hasInitializer());
const ConstantDataArray *DA = cast<ConstantDataArray>(GV->getInitializer());
assert(DA->isString());