2511 lines
129 KiB
Diff
2511 lines
129 KiB
Diff
From 20253836fbb1baf5c7cd6fb6558bd12dff682855 Mon Sep 17 00:00:00 2001
|
|
From: Yonghong Song <yhs@fb.com>
|
|
Date: Fri, 2 Aug 2019 23:16:44 +0000
|
|
Subject: [PATCH] [BPF] Handling type conversions correctly for CO-RE
|
|
|
|
With newly added debuginfo type
|
|
metadata for preserve_array_access_index() intrinsic,
|
|
this patch did the following two things:
|
|
(1). checking validity before adding a new access index
|
|
to the access chain.
|
|
(2). calculating access byte offset in IR phase
|
|
BPFAbstractMemberAccess instead of when BTF is emitted.
|
|
|
|
For (1), the metadata provided by all preserve_*_access_index()
|
|
intrinsics are used to check whether the to-be-added type
|
|
is a proper struct/union member or array element.
|
|
|
|
For (2), with all available metadata, calculating access byte
|
|
offset becomes easier in BPFAbstractMemberAccess IR phase.
|
|
This enables us to remove the unnecessary complexity in
|
|
BTFDebug.cpp.
|
|
|
|
New tests are added for
|
|
. user explicit casting to array/structure/union
|
|
. global variable (or its dereference) as the source of base
|
|
. multi demensional arrays
|
|
. array access given a base pointer
|
|
. cases where we won't generate relocation if we cannot find
|
|
type name.
|
|
|
|
Differential Revision: https://reviews.llvm.org/D65618
|
|
|
|
llvm-svn: 367735
|
|
(cherry picked from commit 37d24a696bf74f4830f2582d2f36256ca1b6bb30)
|
|
---
|
|
llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp | 332 +++++++++++++++++----
|
|
llvm/lib/Target/BPF/BTFDebug.cpp | 110 +------
|
|
llvm/lib/Target/BPF/BTFDebug.h | 15 +-
|
|
.../CodeGen/BPF/CORE/offset-reloc-cast-array-1.ll | 124 ++++++++
|
|
.../CodeGen/BPF/CORE/offset-reloc-cast-array-2.ll | 131 ++++++++
|
|
.../CodeGen/BPF/CORE/offset-reloc-cast-struct-1.ll | 112 +++++++
|
|
.../CodeGen/BPF/CORE/offset-reloc-cast-struct-2.ll | 117 ++++++++
|
|
.../CodeGen/BPF/CORE/offset-reloc-cast-struct-3.ll | 116 +++++++
|
|
.../CodeGen/BPF/CORE/offset-reloc-cast-union-1.ll | 117 ++++++++
|
|
.../CodeGen/BPF/CORE/offset-reloc-cast-union-2.ll | 118 ++++++++
|
|
.../test/CodeGen/BPF/CORE/offset-reloc-global-1.ll | 79 +++++
|
|
.../test/CodeGen/BPF/CORE/offset-reloc-global-2.ll | 95 ++++++
|
|
.../test/CodeGen/BPF/CORE/offset-reloc-global-3.ll | 84 ++++++
|
|
llvm/test/CodeGen/BPF/CORE/offset-reloc-ignore.ll | 62 ++++
|
|
.../CodeGen/BPF/CORE/offset-reloc-multi-array-1.ll | 101 +++++++
|
|
.../CodeGen/BPF/CORE/offset-reloc-multi-array-2.ll | 107 +++++++
|
|
.../CodeGen/BPF/CORE/offset-reloc-pointer-1.ll | 83 ++++++
|
|
.../CodeGen/BPF/CORE/offset-reloc-pointer-2.ll | 85 ++++++
|
|
.../BPF/CORE/offset-reloc-struct-anonymous.ll | 2 +-
|
|
.../CodeGen/BPF/CORE/offset-reloc-struct-array.ll | 2 +-
|
|
.../CodeGen/BPF/CORE/offset-reloc-typedef-array.ll | 2 +-
|
|
llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll | 2 +-
|
|
22 files changed, 1812 insertions(+), 184 deletions(-)
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-1.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-2.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-1.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-2.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-3.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-1.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-2.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-global-1.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-global-2.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-global-3.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-ignore.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-1.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-2.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-1.ll
|
|
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-2.ll
|
|
|
|
diff --git a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
|
|
index 509484b..f55f6f9 100644
|
|
--- a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
|
|
+++ b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
|
|
@@ -65,6 +65,7 @@
|
|
#include "llvm/IR/Value.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
|
+#include <stack>
|
|
|
|
#define DEBUG_TYPE "bpf-abstract-member-access"
|
|
|
|
@@ -106,18 +107,24 @@ private:
|
|
|
|
bool doTransformation(Module &M);
|
|
|
|
- void traceAICall(CallInst *Call, uint32_t Kind);
|
|
- void traceBitCast(BitCastInst *BitCast, CallInst *Parent, uint32_t Kind);
|
|
- void traceGEP(GetElementPtrInst *GEP, CallInst *Parent, uint32_t Kind);
|
|
+ void traceAICall(CallInst *Call, uint32_t Kind, const MDNode *ParentMeta,
|
|
+ uint32_t ParentAI);
|
|
+ void traceBitCast(BitCastInst *BitCast, CallInst *Parent, uint32_t Kind,
|
|
+ const MDNode *ParentMeta, uint32_t ParentAI);
|
|
+ void traceGEP(GetElementPtrInst *GEP, CallInst *Parent, uint32_t Kind,
|
|
+ const MDNode *ParentMeta, uint32_t ParentAI);
|
|
void collectAICallChains(Module &M, Function &F);
|
|
|
|
- bool IsPreserveDIAccessIndexCall(const CallInst *Call, uint32_t &Kind);
|
|
+ bool IsPreserveDIAccessIndexCall(const CallInst *Call, uint32_t &Kind,
|
|
+ const MDNode *&TypeMeta, uint32_t &AccessIndex);
|
|
+ bool IsValidAIChain(const MDNode *ParentMeta, uint32_t ParentAI,
|
|
+ const MDNode *ChildMeta);
|
|
bool removePreserveAccessIndexIntrinsic(Module &M);
|
|
void replaceWithGEP(std::vector<CallInst *> &CallList,
|
|
uint32_t NumOfZerosIndex, uint32_t DIIndex);
|
|
|
|
Value *computeBaseAndAccessKey(CallInst *Call, std::string &AccessKey,
|
|
- uint32_t Kind, MDNode *&TypeMeta);
|
|
+ uint32_t Kind, MDNode *&BaseMeta);
|
|
bool getAccessIndex(const Value *IndexValue, uint64_t &AccessIndex);
|
|
bool transformGEPChain(Module &M, CallInst *Call, uint32_t Kind);
|
|
};
|
|
@@ -141,9 +148,53 @@ bool BPFAbstractMemberAccess::runOnModule(Module &M) {
|
|
return doTransformation(M);
|
|
}
|
|
|
|
+static bool SkipDIDerivedTag(unsigned Tag) {
|
|
+ if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type &&
|
|
+ Tag != dwarf::DW_TAG_volatile_type &&
|
|
+ Tag != dwarf::DW_TAG_restrict_type &&
|
|
+ Tag != dwarf::DW_TAG_member)
|
|
+ return false;
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static DIType * stripQualifiers(DIType *Ty) {
|
|
+ while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
|
|
+ if (!SkipDIDerivedTag(DTy->getTag()))
|
|
+ break;
|
|
+ Ty = DTy->getBaseType();
|
|
+ }
|
|
+ return Ty;
|
|
+}
|
|
+
|
|
+static const DIType * stripQualifiers(const DIType *Ty) {
|
|
+ while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
|
|
+ if (!SkipDIDerivedTag(DTy->getTag()))
|
|
+ break;
|
|
+ Ty = DTy->getBaseType();
|
|
+ }
|
|
+ return Ty;
|
|
+}
|
|
+
|
|
+static uint32_t calcArraySize(const DICompositeType *CTy, uint32_t StartDim) {
|
|
+ DINodeArray Elements = CTy->getElements();
|
|
+ uint32_t DimSize = 1;
|
|
+ for (uint32_t I = StartDim; I < Elements.size(); ++I) {
|
|
+ if (auto *Element = dyn_cast_or_null<DINode>(Elements[I]))
|
|
+ if (Element->getTag() == dwarf::DW_TAG_subrange_type) {
|
|
+ const DISubrange *SR = cast<DISubrange>(Element);
|
|
+ auto *CI = SR->getCount().dyn_cast<ConstantInt *>();
|
|
+ DimSize *= CI->getSExtValue();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return DimSize;
|
|
+}
|
|
+
|
|
/// Check whether a call is a preserve_*_access_index intrinsic call or not.
|
|
bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
|
|
- uint32_t &Kind) {
|
|
+ uint32_t &Kind,
|
|
+ const MDNode *&TypeMeta,
|
|
+ uint32_t &AccessIndex) {
|
|
if (!Call)
|
|
return false;
|
|
|
|
@@ -152,14 +203,29 @@ bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
|
|
return false;
|
|
if (GV->getName().startswith("llvm.preserve.array.access.index")) {
|
|
Kind = BPFPreserveArrayAI;
|
|
+ TypeMeta = Call->getMetadata(LLVMContext::MD_preserve_access_index);
|
|
+ if (!TypeMeta)
|
|
+ report_fatal_error("Missing metadata for llvm.preserve.array.access.index intrinsic");
|
|
+ AccessIndex = cast<ConstantInt>(Call->getArgOperand(2))
|
|
+ ->getZExtValue();
|
|
return true;
|
|
}
|
|
if (GV->getName().startswith("llvm.preserve.union.access.index")) {
|
|
Kind = BPFPreserveUnionAI;
|
|
+ TypeMeta = Call->getMetadata(LLVMContext::MD_preserve_access_index);
|
|
+ if (!TypeMeta)
|
|
+ report_fatal_error("Missing metadata for llvm.preserve.union.access.index intrinsic");
|
|
+ AccessIndex = cast<ConstantInt>(Call->getArgOperand(1))
|
|
+ ->getZExtValue();
|
|
return true;
|
|
}
|
|
if (GV->getName().startswith("llvm.preserve.struct.access.index")) {
|
|
Kind = BPFPreserveStructAI;
|
|
+ TypeMeta = Call->getMetadata(LLVMContext::MD_preserve_access_index);
|
|
+ if (!TypeMeta)
|
|
+ report_fatal_error("Missing metadata for llvm.preserve.struct.access.index intrinsic");
|
|
+ AccessIndex = cast<ConstantInt>(Call->getArgOperand(2))
|
|
+ ->getZExtValue();
|
|
return true;
|
|
}
|
|
|
|
@@ -200,7 +266,9 @@ bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Module &M) {
|
|
for (auto &I : BB) {
|
|
auto *Call = dyn_cast<CallInst>(&I);
|
|
uint32_t Kind;
|
|
- if (!IsPreserveDIAccessIndexCall(Call, Kind))
|
|
+ const MDNode *TypeMeta;
|
|
+ uint32_t AccessIndex;
|
|
+ if (!IsPreserveDIAccessIndexCall(Call, Kind, TypeMeta, AccessIndex))
|
|
continue;
|
|
|
|
Found = true;
|
|
@@ -232,25 +300,79 @@ bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Module &M) {
|
|
return Found;
|
|
}
|
|
|
|
-void BPFAbstractMemberAccess::traceAICall(CallInst *Call, uint32_t Kind) {
|
|
+/// Check whether the access index chain is valid. We check
|
|
+/// here because there may be type casts between two
|
|
+/// access indexes. We want to ensure memory access still valid.
|
|
+bool BPFAbstractMemberAccess::IsValidAIChain(const MDNode *ParentType,
|
|
+ uint32_t ParentAI,
|
|
+ const MDNode *ChildType) {
|
|
+ const DIType *PType = stripQualifiers(cast<DIType>(ParentType));
|
|
+ const DIType *CType = stripQualifiers(cast<DIType>(ChildType));
|
|
+
|
|
+ // Child is a derived/pointer type, which is due to type casting.
|
|
+ // Pointer type cannot be in the middle of chain.
|
|
+ if (const auto *PtrTy = dyn_cast<DIDerivedType>(CType))
|
|
+ return false;
|
|
+
|
|
+ // Parent is a pointer type.
|
|
+ if (const auto *PtrTy = dyn_cast<DIDerivedType>(PType)) {
|
|
+ if (PtrTy->getTag() != dwarf::DW_TAG_pointer_type)
|
|
+ return false;
|
|
+ return stripQualifiers(PtrTy->getBaseType()) == CType;
|
|
+ }
|
|
+
|
|
+ // Otherwise, struct/union/array types
|
|
+ const auto *PTy = dyn_cast<DICompositeType>(PType);
|
|
+ const auto *CTy = dyn_cast<DICompositeType>(CType);
|
|
+ assert(PTy && CTy && "ParentType or ChildType is null or not composite");
|
|
+
|
|
+ uint32_t PTyTag = PTy->getTag();
|
|
+ assert(PTyTag == dwarf::DW_TAG_array_type ||
|
|
+ PTyTag == dwarf::DW_TAG_structure_type ||
|
|
+ PTyTag == dwarf::DW_TAG_union_type);
|
|
+
|
|
+ uint32_t CTyTag = CTy->getTag();
|
|
+ assert(CTyTag == dwarf::DW_TAG_array_type ||
|
|
+ CTyTag == dwarf::DW_TAG_structure_type ||
|
|
+ CTyTag == dwarf::DW_TAG_union_type);
|
|
+
|
|
+ // Multi dimensional arrays, base element should be the same
|
|
+ if (PTyTag == dwarf::DW_TAG_array_type && PTyTag == CTyTag)
|
|
+ return PTy->getBaseType() == CTy->getBaseType();
|
|
+
|
|
+ DIType *Ty;
|
|
+ if (PTyTag == dwarf::DW_TAG_array_type)
|
|
+ Ty = PTy->getBaseType();
|
|
+ else
|
|
+ Ty = dyn_cast<DIType>(PTy->getElements()[ParentAI]);
|
|
+
|
|
+ return dyn_cast<DICompositeType>(stripQualifiers(Ty)) == CTy;
|
|
+}
|
|
+
|
|
+void BPFAbstractMemberAccess::traceAICall(CallInst *Call, uint32_t Kind,
|
|
+ const MDNode *ParentMeta,
|
|
+ uint32_t ParentAI) {
|
|
for (User *U : Call->users()) {
|
|
Instruction *Inst = dyn_cast<Instruction>(U);
|
|
if (!Inst)
|
|
continue;
|
|
|
|
if (auto *BI = dyn_cast<BitCastInst>(Inst)) {
|
|
- traceBitCast(BI, Call, Kind);
|
|
+ traceBitCast(BI, Call, Kind, ParentMeta, ParentAI);
|
|
} else if (auto *CI = dyn_cast<CallInst>(Inst)) {
|
|
uint32_t CIKind;
|
|
- if (IsPreserveDIAccessIndexCall(CI, CIKind)) {
|
|
+ const MDNode *ChildMeta;
|
|
+ uint32_t ChildAI;
|
|
+ if (IsPreserveDIAccessIndexCall(CI, CIKind, ChildMeta, ChildAI) &&
|
|
+ IsValidAIChain(ParentMeta, ParentAI, ChildMeta)) {
|
|
AIChain[CI] = std::make_pair(Call, Kind);
|
|
- traceAICall(CI, CIKind);
|
|
+ traceAICall(CI, CIKind, ChildMeta, ChildAI);
|
|
} else {
|
|
BaseAICalls[Call] = Kind;
|
|
}
|
|
} else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
|
|
if (GI->hasAllZeroIndices())
|
|
- traceGEP(GI, Call, Kind);
|
|
+ traceGEP(GI, Call, Kind, ParentMeta, ParentAI);
|
|
else
|
|
BaseAICalls[Call] = Kind;
|
|
}
|
|
@@ -258,25 +380,30 @@ void BPFAbstractMemberAccess::traceAICall(CallInst *Call, uint32_t Kind) {
|
|
}
|
|
|
|
void BPFAbstractMemberAccess::traceBitCast(BitCastInst *BitCast,
|
|
- CallInst *Parent, uint32_t Kind) {
|
|
+ CallInst *Parent, uint32_t Kind,
|
|
+ const MDNode *ParentMeta,
|
|
+ uint32_t ParentAI) {
|
|
for (User *U : BitCast->users()) {
|
|
Instruction *Inst = dyn_cast<Instruction>(U);
|
|
if (!Inst)
|
|
continue;
|
|
|
|
if (auto *BI = dyn_cast<BitCastInst>(Inst)) {
|
|
- traceBitCast(BI, Parent, Kind);
|
|
+ traceBitCast(BI, Parent, Kind, ParentMeta, ParentAI);
|
|
} else if (auto *CI = dyn_cast<CallInst>(Inst)) {
|
|
uint32_t CIKind;
|
|
- if (IsPreserveDIAccessIndexCall(CI, CIKind)) {
|
|
+ const MDNode *ChildMeta;
|
|
+ uint32_t ChildAI;
|
|
+ if (IsPreserveDIAccessIndexCall(CI, CIKind, ChildMeta, ChildAI) &&
|
|
+ IsValidAIChain(ParentMeta, ParentAI, ChildMeta)) {
|
|
AIChain[CI] = std::make_pair(Parent, Kind);
|
|
- traceAICall(CI, CIKind);
|
|
+ traceAICall(CI, CIKind, ChildMeta, ChildAI);
|
|
} else {
|
|
BaseAICalls[Parent] = Kind;
|
|
}
|
|
} else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
|
|
if (GI->hasAllZeroIndices())
|
|
- traceGEP(GI, Parent, Kind);
|
|
+ traceGEP(GI, Parent, Kind, ParentMeta, ParentAI);
|
|
else
|
|
BaseAICalls[Parent] = Kind;
|
|
}
|
|
@@ -284,25 +411,29 @@ void BPFAbstractMemberAccess::traceBitCast(BitCastInst *BitCast,
|
|
}
|
|
|
|
void BPFAbstractMemberAccess::traceGEP(GetElementPtrInst *GEP, CallInst *Parent,
|
|
- uint32_t Kind) {
|
|
+ uint32_t Kind, const MDNode *ParentMeta,
|
|
+ uint32_t ParentAI) {
|
|
for (User *U : GEP->users()) {
|
|
Instruction *Inst = dyn_cast<Instruction>(U);
|
|
if (!Inst)
|
|
continue;
|
|
|
|
if (auto *BI = dyn_cast<BitCastInst>(Inst)) {
|
|
- traceBitCast(BI, Parent, Kind);
|
|
+ traceBitCast(BI, Parent, Kind, ParentMeta, ParentAI);
|
|
} else if (auto *CI = dyn_cast<CallInst>(Inst)) {
|
|
uint32_t CIKind;
|
|
- if (IsPreserveDIAccessIndexCall(CI, CIKind)) {
|
|
+ const MDNode *ChildMeta;
|
|
+ uint32_t ChildAI;
|
|
+ if (IsPreserveDIAccessIndexCall(CI, CIKind, ChildMeta, ChildAI) &&
|
|
+ IsValidAIChain(ParentMeta, ParentAI, ChildMeta)) {
|
|
AIChain[CI] = std::make_pair(Parent, Kind);
|
|
- traceAICall(CI, CIKind);
|
|
+ traceAICall(CI, CIKind, ChildMeta, ChildAI);
|
|
} else {
|
|
BaseAICalls[Parent] = Kind;
|
|
}
|
|
} else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
|
|
if (GI->hasAllZeroIndices())
|
|
- traceGEP(GI, Parent, Kind);
|
|
+ traceGEP(GI, Parent, Kind, ParentMeta, ParentAI);
|
|
else
|
|
BaseAICalls[Parent] = Kind;
|
|
}
|
|
@@ -316,12 +447,14 @@ void BPFAbstractMemberAccess::collectAICallChains(Module &M, Function &F) {
|
|
for (auto &BB : F)
|
|
for (auto &I : BB) {
|
|
uint32_t Kind;
|
|
+ const MDNode *TypeMeta;
|
|
+ uint32_t AccessIndex;
|
|
auto *Call = dyn_cast<CallInst>(&I);
|
|
- if (!IsPreserveDIAccessIndexCall(Call, Kind) ||
|
|
+ if (!IsPreserveDIAccessIndexCall(Call, Kind, TypeMeta, AccessIndex) ||
|
|
AIChain.find(Call) != AIChain.end())
|
|
continue;
|
|
|
|
- traceAICall(Call, Kind);
|
|
+ traceAICall(Call, Kind, TypeMeta, AccessIndex);
|
|
}
|
|
}
|
|
|
|
@@ -344,62 +477,131 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call,
|
|
uint32_t Kind,
|
|
MDNode *&TypeMeta) {
|
|
Value *Base = nullptr;
|
|
- std::vector<uint64_t> AccessIndices;
|
|
- uint64_t TypeNameIndex = 0;
|
|
- std::string LastTypeName;
|
|
+ std::string TypeName;
|
|
+ std::stack<std::pair<CallInst *, uint32_t>> CallStack;
|
|
|
|
+ // Put the access chain into a stack with the top as the head of the chain.
|
|
while (Call) {
|
|
- // Base of original corresponding GEP
|
|
- Base = Call->getArgOperand(0);
|
|
+ CallStack.push(std::make_pair(Call, Kind));
|
|
+ Kind = AIChain[Call].second;
|
|
+ Call = AIChain[Call].first;
|
|
+ }
|
|
|
|
- // Type Name
|
|
- std::string TypeName;
|
|
- MDNode *MDN;
|
|
+ // The access offset from the base of the head of chain is also
|
|
+ // calculated here as all debuginfo types are available.
|
|
+
|
|
+ // Get type name and calculate the first index.
|
|
+ // We only want to get type name from structure or union.
|
|
+ // If user wants a relocation like
|
|
+ // int *p; ... __builtin_preserve_access_index(&p[4]) ...
|
|
+ // or
|
|
+ // int a[10][20]; ... __builtin_preserve_access_index(&a[2][3]) ...
|
|
+ // we will skip them.
|
|
+ uint32_t FirstIndex = 0;
|
|
+ uint32_t AccessOffset = 0;
|
|
+ while (CallStack.size()) {
|
|
+ auto StackElem = CallStack.top();
|
|
+ Call = StackElem.first;
|
|
+ Kind = StackElem.second;
|
|
+
|
|
+ if (!Base)
|
|
+ Base = Call->getArgOperand(0);
|
|
+
|
|
+ MDNode *MDN = Call->getMetadata(LLVMContext::MD_preserve_access_index);
|
|
+ DIType *Ty = stripQualifiers(cast<DIType>(MDN));
|
|
if (Kind == BPFPreserveUnionAI || Kind == BPFPreserveStructAI) {
|
|
- MDN = Call->getMetadata(LLVMContext::MD_preserve_access_index);
|
|
- if (!MDN)
|
|
- return nullptr;
|
|
+ // struct or union type
|
|
+ TypeName = Ty->getName();
|
|
+ TypeMeta = Ty;
|
|
+ AccessOffset += FirstIndex * Ty->getSizeInBits() >> 3;
|
|
+ break;
|
|
+ }
|
|
|
|
- DIType *Ty = dyn_cast<DIType>(MDN);
|
|
- if (!Ty)
|
|
+ // Array entries will always be consumed for accumulative initial index.
|
|
+ CallStack.pop();
|
|
+
|
|
+ // BPFPreserveArrayAI
|
|
+ uint64_t AccessIndex;
|
|
+ if (!getAccessIndex(Call->getArgOperand(2), AccessIndex))
|
|
+ return nullptr;
|
|
+
|
|
+ DIType *BaseTy = nullptr;
|
|
+ bool CheckElemType = false;
|
|
+ if (const auto *CTy = dyn_cast<DICompositeType>(Ty)) {
|
|
+ // array type
|
|
+ assert(CTy->getTag() == dwarf::DW_TAG_array_type);
|
|
+
|
|
+
|
|
+ FirstIndex += AccessIndex * calcArraySize(CTy, 1);
|
|
+ BaseTy = stripQualifiers(CTy->getBaseType());
|
|
+ CheckElemType = CTy->getElements().size() == 1;
|
|
+ } else {
|
|
+ // pointer type
|
|
+ auto *DTy = cast<DIDerivedType>(Ty);
|
|
+ assert(DTy->getTag() == dwarf::DW_TAG_pointer_type);
|
|
+
|
|
+ BaseTy = stripQualifiers(DTy->getBaseType());
|
|
+ CTy = dyn_cast<DICompositeType>(BaseTy);
|
|
+ if (!CTy) {
|
|
+ CheckElemType = true;
|
|
+ } else if (CTy->getTag() != dwarf::DW_TAG_array_type) {
|
|
+ FirstIndex += AccessIndex;
|
|
+ CheckElemType = true;
|
|
+ } else {
|
|
+ FirstIndex += AccessIndex * calcArraySize(CTy, 0);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (CheckElemType) {
|
|
+ auto *CTy = dyn_cast<DICompositeType>(BaseTy);
|
|
+ if (!CTy)
|
|
return nullptr;
|
|
|
|
- TypeName = Ty->getName();
|
|
+ unsigned CTag = CTy->getTag();
|
|
+ if (CTag != dwarf::DW_TAG_structure_type && CTag != dwarf::DW_TAG_union_type)
|
|
+ return nullptr;
|
|
+ else
|
|
+ TypeName = CTy->getName();
|
|
+ TypeMeta = CTy;
|
|
+ AccessOffset += FirstIndex * CTy->getSizeInBits() >> 3;
|
|
+ break;
|
|
}
|
|
+ }
|
|
+ assert(TypeName.size());
|
|
+ AccessKey += std::to_string(FirstIndex);
|
|
+
|
|
+ // Traverse the rest of access chain to complete offset calculation
|
|
+ // and access key construction.
|
|
+ while (CallStack.size()) {
|
|
+ auto StackElem = CallStack.top();
|
|
+ Call = StackElem.first;
|
|
+ Kind = StackElem.second;
|
|
+ CallStack.pop();
|
|
|
|
// Access Index
|
|
uint64_t AccessIndex;
|
|
uint32_t ArgIndex = (Kind == BPFPreserveUnionAI) ? 1 : 2;
|
|
if (!getAccessIndex(Call->getArgOperand(ArgIndex), AccessIndex))
|
|
return nullptr;
|
|
-
|
|
- AccessIndices.push_back(AccessIndex);
|
|
- if (TypeName.size()) {
|
|
- TypeNameIndex = AccessIndices.size() - 1;
|
|
- LastTypeName = TypeName;
|
|
- TypeMeta = MDN;
|
|
+ AccessKey += ":" + std::to_string(AccessIndex);
|
|
+
|
|
+ MDNode *MDN = Call->getMetadata(LLVMContext::MD_preserve_access_index);
|
|
+ // At this stage, it cannot be pointer type.
|
|
+ auto *CTy = cast<DICompositeType>(stripQualifiers(cast<DIType>(MDN)));
|
|
+ uint32_t Tag = CTy->getTag();
|
|
+ if (Tag == dwarf::DW_TAG_structure_type) {
|
|
+ auto *MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]);
|
|
+ AccessOffset += MemberTy->getOffsetInBits() >> 3;
|
|
+ } else if (Tag == dwarf::DW_TAG_array_type) {
|
|
+ auto *EltTy = stripQualifiers(CTy->getBaseType());
|
|
+ AccessOffset += AccessIndex * calcArraySize(CTy, 1) *
|
|
+ EltTy->getSizeInBits() >> 3;
|
|
}
|
|
-
|
|
- Kind = AIChain[Call].second;
|
|
- Call = AIChain[Call].first;
|
|
}
|
|
|
|
- // The intial type name is required.
|
|
- // FIXME: if the initial type access is an array index, e.g.,
|
|
- // &a[3].b.c, only one dimentional array is supported.
|
|
- if (!LastTypeName.size() || AccessIndices.size() > TypeNameIndex + 2)
|
|
- return nullptr;
|
|
-
|
|
- // Construct the type string AccessKey.
|
|
- for (unsigned I = 0; I < AccessIndices.size(); ++I)
|
|
- AccessKey = std::to_string(AccessIndices[I]) + ":" + AccessKey;
|
|
-
|
|
- if (TypeNameIndex == AccessIndices.size() - 1)
|
|
- AccessKey = "0:" + AccessKey;
|
|
-
|
|
// Access key is the type name + access string, uniquely identifying
|
|
// one kernel memory access.
|
|
- AccessKey = LastTypeName + ":" + AccessKey;
|
|
+ AccessKey = TypeName + ":" + std::to_string(AccessOffset) + "$" + AccessKey;
|
|
|
|
return Base;
|
|
}
|
|
@@ -409,7 +611,7 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call,
|
|
bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call,
|
|
uint32_t Kind) {
|
|
std::string AccessKey;
|
|
- MDNode *TypeMeta = nullptr;
|
|
+ MDNode *TypeMeta;
|
|
Value *Base =
|
|
computeBaseAndAccessKey(Call, AccessKey, Kind, TypeMeta);
|
|
if (!Base)
|
|
@@ -419,7 +621,7 @@ bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call,
|
|
// For any original GEP Call and Base %2 like
|
|
// %4 = bitcast %struct.net_device** %dev1 to i64*
|
|
// it is transformed to:
|
|
- // %6 = load __BTF_0:sk_buff:0:0:2:0:
|
|
+ // %6 = load sk_buff:50:$0:0:0:2:0
|
|
// %7 = bitcast %struct.sk_buff* %2 to i8*
|
|
// %8 = getelementptr i8, i8* %7, %6
|
|
// %9 = bitcast i8* %8 to i64*
|
|
@@ -432,9 +634,7 @@ bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call,
|
|
GV = new GlobalVariable(M, Type::getInt64Ty(BB->getContext()), false,
|
|
GlobalVariable::ExternalLinkage, NULL, AccessKey);
|
|
GV->addAttribute(BPFCoreSharedInfo::AmaAttr);
|
|
- // Set the metadata (debuginfo types) for the global.
|
|
- if (TypeMeta)
|
|
- GV->setMetadata(LLVMContext::MD_preserve_access_index, TypeMeta);
|
|
+ GV->setMetadata(LLVMContext::MD_preserve_access_index, TypeMeta);
|
|
GEPGlobals[AccessKey] = GV;
|
|
} else {
|
|
GV = GEPGlobals[AccessKey];
|
|
diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp
|
|
index 5c542e7..9b966eb 100644
|
|
--- a/llvm/lib/Target/BPF/BTFDebug.cpp
|
|
+++ b/llvm/lib/Target/BPF/BTFDebug.cpp
|
|
@@ -30,18 +30,6 @@ static const char *BTFKindStr[] = {
|
|
#include "BTF.def"
|
|
};
|
|
|
|
-static const DIType * stripQualifiers(const DIType *Ty) {
|
|
- while (const auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
|
|
- unsigned Tag = DTy->getTag();
|
|
- if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type &&
|
|
- Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_restrict_type)
|
|
- break;
|
|
- Ty = DTy->getBaseType();
|
|
- }
|
|
-
|
|
- return Ty;
|
|
-}
|
|
-
|
|
/// Emit a BTF common type.
|
|
void BTFTypeBase::emitType(MCStreamer &OS) {
|
|
OS.AddComment(std::string(BTFKindStr[Kind]) + "(id = " + std::to_string(Id) +
|
|
@@ -196,9 +184,7 @@ void BTFTypeEnum::emitType(MCStreamer &OS) {
|
|
}
|
|
}
|
|
|
|
-BTFTypeArray::BTFTypeArray(const DIType *Ty, uint32_t ElemTypeId,
|
|
- uint32_t ElemSize, uint32_t NumElems)
|
|
- : ElemTyNoQual(Ty), ElemSize(ElemSize) {
|
|
+BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems) {
|
|
Kind = BTF::BTF_KIND_ARRAY;
|
|
BTFType.NameOff = 0;
|
|
BTFType.Info = Kind << 24;
|
|
@@ -219,9 +205,6 @@ void BTFTypeArray::completeType(BTFDebug &BDebug) {
|
|
// created during initial type traversal. Just
|
|
// retrieve that type id.
|
|
ArrayInfo.IndexType = BDebug.getArrayIndexTypeId();
|
|
-
|
|
- ElemTypeNoQual = ElemTyNoQual ? BDebug.getTypeId(ElemTyNoQual)
|
|
- : ArrayInfo.ElemType;
|
|
}
|
|
|
|
void BTFTypeArray::emitType(MCStreamer &OS) {
|
|
@@ -231,12 +214,6 @@ void BTFTypeArray::emitType(MCStreamer &OS) {
|
|
OS.EmitIntValue(ArrayInfo.Nelems, 4);
|
|
}
|
|
|
|
-void BTFTypeArray::getLocInfo(uint32_t Loc, uint32_t &LocOffset,
|
|
- uint32_t &ElementTypeId) {
|
|
- ElementTypeId = ElemTypeNoQual;
|
|
- LocOffset = Loc * ElemSize;
|
|
-}
|
|
-
|
|
/// Represent either a struct or a union.
|
|
BTFTypeStruct::BTFTypeStruct(const DICompositeType *STy, bool IsStruct,
|
|
bool HasBitField, uint32_t Vlen)
|
|
@@ -268,7 +245,6 @@ void BTFTypeStruct::completeType(BTFDebug &BDebug) {
|
|
}
|
|
const auto *BaseTy = DDTy->getBaseType();
|
|
BTFMember.Type = BDebug.getTypeId(BaseTy);
|
|
- MemberTypeNoQual.push_back(BDebug.getTypeId(stripQualifiers(BaseTy)));
|
|
Members.push_back(BTFMember);
|
|
}
|
|
}
|
|
@@ -285,15 +261,6 @@ void BTFTypeStruct::emitType(MCStreamer &OS) {
|
|
|
|
std::string BTFTypeStruct::getName() { return STy->getName(); }
|
|
|
|
-void BTFTypeStruct::getMemberInfo(uint32_t Loc, uint32_t &MemberOffset,
|
|
- uint32_t &MemberType) {
|
|
- MemberType = MemberTypeNoQual[Loc];
|
|
- MemberOffset =
|
|
- HasBitField ? Members[Loc].Offset & 0xffffff : Members[Loc].Offset;
|
|
-}
|
|
-
|
|
-uint32_t BTFTypeStruct::getStructSize() { return STy->getSizeInBits() >> 3; }
|
|
-
|
|
/// The Func kind represents both subprogram and pointee of function
|
|
/// pointers. If the FuncName is empty, it represents a pointee of function
|
|
/// pointer. Otherwise, it represents a subprogram. The func arg names
|
|
@@ -511,12 +478,10 @@ void BTFDebug::visitArrayType(const DICompositeType *CTy, uint32_t &TypeId) {
|
|
visitTypeEntry(ElemType, ElemTypeId, false, false);
|
|
|
|
// Strip qualifiers from element type to get accurate element size.
|
|
- ElemType = stripQualifiers(ElemType);
|
|
ElemSize = ElemType->getSizeInBits() >> 3;
|
|
|
|
if (!CTy->getSizeInBits()) {
|
|
- auto TypeEntry = llvm::make_unique<BTFTypeArray>(ElemType, ElemTypeId, 0, 0);
|
|
- ArrayTypes.push_back(TypeEntry.get());
|
|
+ auto TypeEntry = llvm::make_unique<BTFTypeArray>(ElemTypeId, 0);
|
|
ElemTypeId = addType(std::move(TypeEntry), CTy);
|
|
} else {
|
|
// Visit array dimensions.
|
|
@@ -527,12 +492,9 @@ void BTFDebug::visitArrayType(const DICompositeType *CTy, uint32_t &TypeId) {
|
|
const DISubrange *SR = cast<DISubrange>(Element);
|
|
auto *CI = SR->getCount().dyn_cast<ConstantInt *>();
|
|
int64_t Count = CI->getSExtValue();
|
|
- const DIType *ArrayElemTy = (I == 0) ? ElemType : nullptr;
|
|
|
|
auto TypeEntry =
|
|
- llvm::make_unique<BTFTypeArray>(ArrayElemTy, ElemTypeId,
|
|
- ElemSize, Count);
|
|
- ArrayTypes.push_back(TypeEntry.get());
|
|
+ llvm::make_unique<BTFTypeArray>(ElemTypeId, Count);
|
|
if (I == 0)
|
|
ElemTypeId = addType(std::move(TypeEntry), CTy);
|
|
else
|
|
@@ -1002,74 +964,22 @@ unsigned BTFDebug::populateStructType(const DIType *Ty) {
|
|
return Id;
|
|
}
|
|
|
|
-// Find struct/array debuginfo types given a type id.
|
|
-void BTFDebug::setTypeFromId(uint32_t TypeId, BTFTypeStruct **PrevStructType,
|
|
- BTFTypeArray **PrevArrayType) {
|
|
- for (const auto &StructType : StructTypes) {
|
|
- if (StructType->getId() == TypeId) {
|
|
- *PrevStructType = StructType;
|
|
- return;
|
|
- }
|
|
- }
|
|
- for (const auto &ArrayType : ArrayTypes) {
|
|
- if (ArrayType->getId() == TypeId) {
|
|
- *PrevArrayType = ArrayType;
|
|
- return;
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
/// Generate a struct member offset relocation.
|
|
void BTFDebug::generateOffsetReloc(const MachineInstr *MI,
|
|
const MCSymbol *ORSym, DIType *RootTy,
|
|
StringRef AccessPattern) {
|
|
- BTFTypeStruct *PrevStructType = nullptr;
|
|
- BTFTypeArray *PrevArrayType = nullptr;
|
|
unsigned RootId = populateStructType(RootTy);
|
|
- setTypeFromId(RootId, &PrevStructType, &PrevArrayType);
|
|
- unsigned RootTySize = PrevStructType->getStructSize();
|
|
- StringRef IndexPattern = AccessPattern.substr(AccessPattern.find_first_of(':') + 1);
|
|
+ size_t FirstDollar = AccessPattern.find_first_of('$');
|
|
+ size_t FirstColon = AccessPattern.find_first_of(':');
|
|
+ StringRef IndexPattern = AccessPattern.substr(FirstDollar + 1);
|
|
+ StringRef OffsetStr = AccessPattern.substr(FirstColon + 1,
|
|
+ FirstDollar - FirstColon);
|
|
|
|
BTFOffsetReloc OffsetReloc;
|
|
OffsetReloc.Label = ORSym;
|
|
- OffsetReloc.OffsetNameOff = addString(IndexPattern.drop_back());
|
|
+ OffsetReloc.OffsetNameOff = addString(IndexPattern);
|
|
OffsetReloc.TypeID = RootId;
|
|
-
|
|
- uint32_t Start = 0, End = 0, Offset = 0;
|
|
- bool FirstAccess = true;
|
|
- for (auto C : IndexPattern) {
|
|
- if (C != ':') {
|
|
- End++;
|
|
- } else {
|
|
- std::string SubStr = IndexPattern.substr(Start, End - Start);
|
|
- int Loc = std::stoi(SubStr);
|
|
-
|
|
- if (FirstAccess) {
|
|
- Offset = Loc * RootTySize;
|
|
- FirstAccess = false;
|
|
- } else if (PrevStructType) {
|
|
- uint32_t MemberOffset, MemberTypeId;
|
|
- PrevStructType->getMemberInfo(Loc, MemberOffset, MemberTypeId);
|
|
-
|
|
- Offset += MemberOffset >> 3;
|
|
- PrevStructType = nullptr;
|
|
- setTypeFromId(MemberTypeId, &PrevStructType, &PrevArrayType);
|
|
- } else if (PrevArrayType) {
|
|
- uint32_t LocOffset, ElementTypeId;
|
|
- PrevArrayType->getLocInfo(Loc, LocOffset, ElementTypeId);
|
|
-
|
|
- Offset += LocOffset;
|
|
- PrevArrayType = nullptr;
|
|
- setTypeFromId(ElementTypeId, &PrevStructType, &PrevArrayType);
|
|
- } else {
|
|
- llvm_unreachable("Internal Error: BTF offset relocation type traversal error");
|
|
- }
|
|
-
|
|
- Start = End + 1;
|
|
- End = Start;
|
|
- }
|
|
- }
|
|
- AccessOffsets[AccessPattern.str()] = Offset;
|
|
+ AccessOffsets[AccessPattern.str()] = std::stoi(OffsetStr);
|
|
OffsetRelocTable[SecNameOff].push_back(OffsetReloc);
|
|
}
|
|
|
|
diff --git a/llvm/lib/Target/BPF/BTFDebug.h b/llvm/lib/Target/BPF/BTFDebug.h
|
|
index e210d18..a79527d 100644
|
|
--- a/llvm/lib/Target/BPF/BTFDebug.h
|
|
+++ b/llvm/lib/Target/BPF/BTFDebug.h
|
|
@@ -104,18 +104,13 @@ public:
|
|
|
|
/// Handle array type.
|
|
class BTFTypeArray : public BTFTypeBase {
|
|
- const DIType *ElemTyNoQual;
|
|
- uint32_t ElemSize;
|
|
struct BTF::BTFArray ArrayInfo;
|
|
- uint32_t ElemTypeNoQual;
|
|
|
|
public:
|
|
- BTFTypeArray(const DIType *Ty, uint32_t ElemTypeId,
|
|
- uint32_t ElemSize, uint32_t NumElems);
|
|
+ BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems);
|
|
uint32_t getSize() { return BTFTypeBase::getSize() + BTF::BTFArraySize; }
|
|
void completeType(BTFDebug &BDebug);
|
|
void emitType(MCStreamer &OS);
|
|
- void getLocInfo(uint32_t Loc, uint32_t &LocOffset, uint32_t &ElementTypeId);
|
|
};
|
|
|
|
/// Handle struct/union type.
|
|
@@ -123,7 +118,6 @@ class BTFTypeStruct : public BTFTypeBase {
|
|
const DICompositeType *STy;
|
|
bool HasBitField;
|
|
std::vector<struct BTF::BTFMember> Members;
|
|
- std::vector<uint32_t> MemberTypeNoQual;
|
|
|
|
public:
|
|
BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField,
|
|
@@ -134,8 +128,6 @@ public:
|
|
void completeType(BTFDebug &BDebug);
|
|
void emitType(MCStreamer &OS);
|
|
std::string getName();
|
|
- void getMemberInfo(uint32_t Loc, uint32_t &Offset, uint32_t &MemberType);
|
|
- uint32_t getStructSize();
|
|
};
|
|
|
|
/// Handle function pointer.
|
|
@@ -262,7 +254,6 @@ class BTFDebug : public DebugHandlerBase {
|
|
StringMap<std::vector<std::string>> FileContent;
|
|
std::map<std::string, std::unique_ptr<BTFKindDataSec>> DataSecEntries;
|
|
std::vector<BTFTypeStruct *> StructTypes;
|
|
- std::vector<BTFTypeArray *> ArrayTypes;
|
|
std::map<std::string, int64_t> AccessOffsets;
|
|
std::map<StringRef, std::pair<bool, std::vector<BTFTypeDerived *>>>
|
|
FixupDerivedTypes;
|
|
@@ -312,10 +303,6 @@ class BTFDebug : public DebugHandlerBase {
|
|
void generateOffsetReloc(const MachineInstr *MI, const MCSymbol *ORSym,
|
|
DIType *RootTy, StringRef AccessPattern);
|
|
|
|
- /// Set the to-be-traversed Struct/Array Type based on TypeId.
|
|
- void setTypeFromId(uint32_t TypeId, BTFTypeStruct **PrevStructType,
|
|
- BTFTypeArray **PrevArrayType);
|
|
-
|
|
/// Populating unprocessed struct type.
|
|
unsigned populateStructType(const DIType *Ty);
|
|
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-1.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-1.ll
|
|
new file mode 100644
|
|
index 0000000..9e291cd
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-1.ll
|
|
@@ -0,0 +1,124 @@
|
|
+; 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 v1 {int a; int b;};
|
|
+; typedef struct v1 __v1;
|
|
+; typedef __v1 arr[4];
|
|
+; struct v3 { char c; int d[100]; };
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; #define cast_to_arr(x) ((arr *)(x))
|
|
+; int get_value(const int *arg);
|
|
+; int test(struct v3 *arg) {
|
|
+; return get_value(_(&cast_to_arr(&arg->d[0])[0][2].b));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%struct.v3 = type { i8, [100 x i32] }
|
|
+%struct.v1 = type { i32, i32 }
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test(%struct.v3* %arg) local_unnamed_addr #0 !dbg !22 {
|
|
+entry:
|
|
+ call void @llvm.dbg.value(metadata %struct.v3* %arg, metadata !32, metadata !DIExpression()), !dbg !33
|
|
+ %0 = tail call [100 x i32]* @llvm.preserve.struct.access.index.p0a100i32.p0s_struct.v3s(%struct.v3* %arg, i32 1, i32 1), !dbg !34, !llvm.preserve.access.index !26
|
|
+ %1 = tail call i32* @llvm.preserve.array.access.index.p0i32.p0a100i32([100 x i32]* %0, i32 1, i32 0), !dbg !34, !llvm.preserve.access.index !15
|
|
+ %2 = bitcast i32* %1 to [4 x %struct.v1]*, !dbg !34
|
|
+ %3 = tail call [4 x %struct.v1]* @llvm.preserve.array.access.index.p0a4s_struct.v1s.p0a4s_struct.v1s([4 x %struct.v1]* %2, i32 0, i32 0), !dbg !34, !llvm.preserve.access.index !4
|
|
+ %4 = tail call %struct.v1* @llvm.preserve.array.access.index.p0s_struct.v1s.p0a4s_struct.v1s([4 x %struct.v1]* %3, i32 1, i32 2), !dbg !34, !llvm.preserve.access.index !5
|
|
+ %5 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v1s(%struct.v1* %4, i32 1, i32 1), !dbg !34, !llvm.preserve.access.index !8
|
|
+ %call = tail call i32 @get_value(i32* %5) #4, !dbg !35
|
|
+ ret i32 %call, !dbg !36
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 4
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: r2 = 20
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 1 # BTF_KIND_STRUCT(id = [[TID1:[0-9]+]])
|
|
+; CHECK: .long 100 # BTF_KIND_STRUCT(id = [[TID2:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii "v3" # string offset=1
|
|
+; CHECK: .ascii ".text" # string offset=46
|
|
+; CHECK: .ascii "0:1:0" # string offset=52
|
|
+; CHECK: .ascii "2:1" # string offset=107
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 46 # Offset reloc section string offset=46
|
|
+; CHECK-NEXT: .long 2
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 52
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID2]]
|
|
+; CHECK-NEXT: .long 107
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare [100 x i32]* @llvm.preserve.struct.access.index.p0a100i32.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.array.access.index.p0i32.p0a100i32([100 x i32]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare [4 x %struct.v1]* @llvm.preserve.array.access.index.p0a4s_struct.v1s.p0a4s_struct.v1s([4 x %struct.v1]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %struct.v1* @llvm.preserve.array.access.index.p0s_struct.v1s.p0a4s_struct.v1s([4 x %struct.v1]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v1s(%struct.v1*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone speculatable willreturn
|
|
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind readnone speculatable willreturn }
|
|
+attributes #4 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!0}
|
|
+!llvm.module.flags = !{!18, !19, !20}
|
|
+!llvm.ident = !{!21}
|
|
+
|
|
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
|
|
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!2 = !{}
|
|
+!3 = !{!4, !15, !5}
|
|
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
|
|
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "arr", file: !1, line: 3, baseType: !6)
|
|
+!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 256, elements: !13)
|
|
+!7 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v1", file: !1, line: 2, baseType: !8)
|
|
+!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v1", file: !1, line: 1, size: 64, elements: !9)
|
|
+!9 = !{!10, !12}
|
|
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !8, file: !1, line: 1, baseType: !11, size: 32)
|
|
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !8, file: !1, line: 1, baseType: !11, size: 32, offset: 32)
|
|
+!13 = !{!14}
|
|
+!14 = !DISubrange(count: 4)
|
|
+!15 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 3200, elements: !16)
|
|
+!16 = !{!17}
|
|
+!17 = !DISubrange(count: 100)
|
|
+!18 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!19 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!20 = !{i32 1, !"wchar_size", i32 4}
|
|
+!21 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!22 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 8, type: !23, scopeLine: 8, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !31)
|
|
+!23 = !DISubroutineType(types: !24)
|
|
+!24 = !{!11, !25}
|
|
+!25 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !26, size: 64)
|
|
+!26 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v3", file: !1, line: 4, size: 3232, elements: !27)
|
|
+!27 = !{!28, !30}
|
|
+!28 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !26, file: !1, line: 4, baseType: !29, size: 8)
|
|
+!29 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
|
+!30 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !26, file: !1, line: 4, baseType: !15, size: 3200, offset: 32)
|
|
+!31 = !{!32}
|
|
+!32 = !DILocalVariable(name: "arg", arg: 1, scope: !22, file: !1, line: 8, type: !25)
|
|
+!33 = !DILocation(line: 0, scope: !22)
|
|
+!34 = !DILocation(line: 9, column: 20, scope: !22)
|
|
+!35 = !DILocation(line: 9, column: 10, scope: !22)
|
|
+!36 = !DILocation(line: 9, column: 3, scope: !22)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-2.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-2.ll
|
|
new file mode 100644
|
|
index 0000000..7903179
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-2.ll
|
|
@@ -0,0 +1,131 @@
|
|
+; 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 v1 {int a; int b;};
|
|
+; typedef struct v1 __v1;
|
|
+; typedef __v1 arr[4][4];
|
|
+; struct v3 { char c; int d[100]; };
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; #define cast_to_arr(x) ((arr *)(x))
|
|
+; int get_value(const int *arg);
|
|
+; int test(struct v3 *arg) {
|
|
+; return get_value(_(&cast_to_arr(&arg->d[0])[0][2][3].b));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%struct.v3 = type { i8, [100 x i32] }
|
|
+%struct.v1 = type { i32, i32 }
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test(%struct.v3* %arg) local_unnamed_addr #0 !dbg !24 {
|
|
+entry:
|
|
+ call void @llvm.dbg.value(metadata %struct.v3* %arg, metadata !34, metadata !DIExpression()), !dbg !35
|
|
+ %0 = tail call [100 x i32]* @llvm.preserve.struct.access.index.p0a100i32.p0s_struct.v3s(%struct.v3* %arg, i32 1, i32 1), !dbg !36, !llvm.preserve.access.index !28
|
|
+ %1 = tail call i32* @llvm.preserve.array.access.index.p0i32.p0a100i32([100 x i32]* %0, i32 1, i32 0), !dbg !36, !llvm.preserve.access.index !15
|
|
+ %2 = bitcast i32* %1 to [4 x [4 x %struct.v1]]*, !dbg !36
|
|
+ %3 = tail call [4 x [4 x %struct.v1]]* @llvm.preserve.array.access.index.p0a4a4s_struct.v1s.p0a4a4s_struct.v1s([4 x [4 x %struct.v1]]* %2, i32 0, i32 0), !dbg !36, !llvm.preserve.access.index !4
|
|
+ %4 = tail call [4 x %struct.v1]* @llvm.preserve.array.access.index.p0a4s_struct.v1s.p0a4a4s_struct.v1s([4 x [4 x %struct.v1]]* %3, i32 1, i32 2), !dbg !36, !llvm.preserve.access.index !5
|
|
+ %5 = tail call %struct.v1* @llvm.preserve.array.access.index.p0s_struct.v1s.p0a4s_struct.v1s([4 x %struct.v1]* %4, i32 1, i32 3), !dbg !36, !llvm.preserve.access.index !18
|
|
+ %6 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v1s(%struct.v1* %5, i32 1, i32 1), !dbg !36, !llvm.preserve.access.index !8
|
|
+ %call = tail call i32 @get_value(i32* %6) #4, !dbg !37
|
|
+ ret i32 %call, !dbg !38
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 4
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: r2 = 92
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 1 # BTF_KIND_STRUCT(id = [[TID1:[0-9]+]])
|
|
+; CHECK: .long 100 # BTF_KIND_STRUCT(id = [[TID2:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii "v3" # string offset=1
|
|
+; CHECK: .ascii ".text" # string offset=46
|
|
+; CHECK: .ascii "0:1:0" # string offset=52
|
|
+; CHECK: .ascii "v1" # string offset=100
|
|
+; CHECK: .ascii "11:1" # string offset=107
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 46 # Offset reloc section string offset=46
|
|
+; CHECK-NEXT: .long 2
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 52
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID2]]
|
|
+; CHECK-NEXT: .long 107
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare [100 x i32]* @llvm.preserve.struct.access.index.p0a100i32.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.array.access.index.p0i32.p0a100i32([100 x i32]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare [4 x [4 x %struct.v1]]* @llvm.preserve.array.access.index.p0a4a4s_struct.v1s.p0a4a4s_struct.v1s([4 x [4 x %struct.v1]]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare [4 x %struct.v1]* @llvm.preserve.array.access.index.p0a4s_struct.v1s.p0a4a4s_struct.v1s([4 x [4 x %struct.v1]]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %struct.v1* @llvm.preserve.array.access.index.p0s_struct.v1s.p0a4s_struct.v1s([4 x %struct.v1]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v1s(%struct.v1*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone speculatable willreturn
|
|
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind readnone speculatable willreturn }
|
|
+attributes #4 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!0}
|
|
+!llvm.module.flags = !{!20, !21, !22}
|
|
+!llvm.ident = !{!23}
|
|
+
|
|
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
|
|
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!2 = !{}
|
|
+!3 = !{!4, !15, !5, !18}
|
|
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
|
|
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "arr", file: !1, line: 3, baseType: !6)
|
|
+!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 1024, elements: !13)
|
|
+!7 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v1", file: !1, line: 2, baseType: !8)
|
|
+!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v1", file: !1, line: 1, size: 64, elements: !9)
|
|
+!9 = !{!10, !12}
|
|
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !8, file: !1, line: 1, baseType: !11, size: 32)
|
|
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !8, file: !1, line: 1, baseType: !11, size: 32, offset: 32)
|
|
+!13 = !{!14, !14}
|
|
+!14 = !DISubrange(count: 4)
|
|
+!15 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 3200, elements: !16)
|
|
+!16 = !{!17}
|
|
+!17 = !DISubrange(count: 100)
|
|
+!18 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 256, elements: !19)
|
|
+!19 = !{!14}
|
|
+!20 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!21 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!22 = !{i32 1, !"wchar_size", i32 4}
|
|
+!23 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!24 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 8, type: !25, scopeLine: 8, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !33)
|
|
+!25 = !DISubroutineType(types: !26)
|
|
+!26 = !{!11, !27}
|
|
+!27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !28, size: 64)
|
|
+!28 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v3", file: !1, line: 4, size: 3232, elements: !29)
|
|
+!29 = !{!30, !32}
|
|
+!30 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !28, file: !1, line: 4, baseType: !31, size: 8)
|
|
+!31 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
|
+!32 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !28, file: !1, line: 4, baseType: !15, size: 3200, offset: 32)
|
|
+!33 = !{!34}
|
|
+!34 = !DILocalVariable(name: "arg", arg: 1, scope: !24, file: !1, line: 8, type: !27)
|
|
+!35 = !DILocation(line: 0, scope: !24)
|
|
+!36 = !DILocation(line: 9, column: 20, scope: !24)
|
|
+!37 = !DILocation(line: 9, column: 10, scope: !24)
|
|
+!38 = !DILocation(line: 9, column: 3, scope: !24)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-1.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-1.ll
|
|
new file mode 100644
|
|
index 0000000..a97c6a0
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-1.ll
|
|
@@ -0,0 +1,112 @@
|
|
+; 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 v1 { int a; int b; };
|
|
+; struct v2 { int c; int d; };
|
|
+; struct v3 { char c; struct v2 d; };
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; #define cast_to_v1(x) ((struct v1 *)(x))
|
|
+; int get_value(const int *arg);
|
|
+; int test(struct v3 *arg) {
|
|
+; return get_value(_(&cast_to_v1(&arg->d)->b));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%struct.v3 = type { i8, %struct.v2 }
|
|
+%struct.v2 = type { i32, i32 }
|
|
+%struct.v1 = type { i32, i32 }
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test(%struct.v3* %arg) local_unnamed_addr #0 !dbg !14 {
|
|
+entry:
|
|
+ call void @llvm.dbg.value(metadata %struct.v3* %arg, metadata !28, metadata !DIExpression()), !dbg !29
|
|
+ %0 = tail call %struct.v2* @llvm.preserve.struct.access.index.p0s_struct.v2s.p0s_struct.v3s(%struct.v3* %arg, i32 1, i32 1), !dbg !30, !llvm.preserve.access.index !18
|
|
+ %1 = bitcast %struct.v2* %0 to %struct.v1*, !dbg !30
|
|
+ %2 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v1s(%struct.v1* %1, i32 1, i32 1), !dbg !30, !llvm.preserve.access.index !5
|
|
+ %call = tail call i32 @get_value(i32* %2) #4, !dbg !31
|
|
+ ret i32 %call, !dbg !32
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 4
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: r2 = 4
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 1 # BTF_KIND_STRUCT(id = [[V3_TID:[0-9]+]])
|
|
+; CHECK: .long 81 # BTF_KIND_STRUCT(id = [[V1_TID:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii "v3" # string offset=1
|
|
+; CHECK-NEXT: .byte 0
|
|
+; CHECK: .ascii ".text" # string offset=[[SEC_STR:[0-9]+]]
|
|
+; CHECK-NEXT: .byte 0
|
|
+; CHECK: .ascii "0:1" # string offset=[[ACCESS_STR:[0-9]+]]
|
|
+; CHECK-NEXT: .byte 0
|
|
+; CHECK: .ascii "v1" # string offset=81
|
|
+; CHECK-NEXT: .byte 0
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long [[SEC_STR]] # Offset reloc section string offset=[[SEC_STR]]
|
|
+; CHECK-NEXT: .long 2
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[V3_TID]]
|
|
+; CHECK-NEXT: .long [[ACCESS_STR]]
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[V1_TID]]
|
|
+; CHECK-NEXT: .long [[ACCESS_STR]]
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %struct.v2* @llvm.preserve.struct.access.index.p0s_struct.v2s.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v1s(%struct.v1*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone speculatable willreturn
|
|
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind readnone speculatable willreturn }
|
|
+attributes #4 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!0}
|
|
+!llvm.module.flags = !{!10, !11, !12}
|
|
+!llvm.ident = !{!13}
|
|
+
|
|
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
|
|
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!2 = !{}
|
|
+!3 = !{!4}
|
|
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
|
|
+!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v1", file: !1, line: 1, size: 64, elements: !6)
|
|
+!6 = !{!7, !9}
|
|
+!7 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !5, file: !1, line: 1, baseType: !8, size: 32)
|
|
+!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!9 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !5, file: !1, line: 1, baseType: !8, size: 32, offset: 32)
|
|
+!10 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!11 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!12 = !{i32 1, !"wchar_size", i32 4}
|
|
+!13 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!14 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 7, type: !15, scopeLine: 7, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !27)
|
|
+!15 = !DISubroutineType(types: !16)
|
|
+!16 = !{!8, !17}
|
|
+!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !18, size: 64)
|
|
+!18 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v3", file: !1, line: 3, size: 96, elements: !19)
|
|
+!19 = !{!20, !22}
|
|
+!20 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !18, file: !1, line: 3, baseType: !21, size: 8)
|
|
+!21 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
|
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !18, file: !1, line: 3, baseType: !23, size: 64, offset: 32)
|
|
+!23 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v2", file: !1, line: 2, size: 64, elements: !24)
|
|
+!24 = !{!25, !26}
|
|
+!25 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !23, file: !1, line: 2, baseType: !8, size: 32)
|
|
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !23, file: !1, line: 2, baseType: !8, size: 32, offset: 32)
|
|
+!27 = !{!28}
|
|
+!28 = !DILocalVariable(name: "arg", arg: 1, scope: !14, file: !1, line: 7, type: !17)
|
|
+!29 = !DILocation(line: 0, scope: !14)
|
|
+!30 = !DILocation(line: 8, column: 20, scope: !14)
|
|
+!31 = !DILocation(line: 8, column: 10, scope: !14)
|
|
+!32 = !DILocation(line: 8, column: 3, scope: !14)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-2.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-2.ll
|
|
new file mode 100644
|
|
index 0000000..f65b3f3
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-2.ll
|
|
@@ -0,0 +1,117 @@
|
|
+; 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 v1 { int a; int b; };
|
|
+; typedef struct v1 __v1;
|
|
+; struct v2 { int c; int d; };
|
|
+; typedef struct v2 __v2;
|
|
+; struct v3 { char c; volatile const __v2 d; };
|
|
+; typedef struct v3 __v3;
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; #define cast_to_v1(x) ((__v1 *)(x))
|
|
+; int get_value(const int *arg);
|
|
+; int test(__v3 *arg) {
|
|
+; return get_value(_(&cast_to_v1(&arg->d)->b));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%struct.v3 = type { i8, %struct.v2 }
|
|
+%struct.v2 = type { i32, i32 }
|
|
+%struct.v1 = type { i32, i32 }
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test(%struct.v3* %arg) local_unnamed_addr #0 !dbg !15 {
|
|
+entry:
|
|
+ call void @llvm.dbg.value(metadata %struct.v3* %arg, metadata !33, metadata !DIExpression()), !dbg !34
|
|
+ %0 = tail call %struct.v2* @llvm.preserve.struct.access.index.p0s_struct.v2s.p0s_struct.v3s(%struct.v3* %arg, i32 1, i32 1), !dbg !35, !llvm.preserve.access.index !20
|
|
+ %1 = bitcast %struct.v2* %0 to %struct.v1*, !dbg !35
|
|
+ %2 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v1s(%struct.v1* %1, i32 1, i32 1), !dbg !35, !llvm.preserve.access.index !6
|
|
+ %call = tail call i32 @get_value(i32* %2) #4, !dbg !36
|
|
+ ret i32 %call, !dbg !37
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 4
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: r2 = 4
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 6 # BTF_KIND_STRUCT(id = [[TID1:[0-9]+]])
|
|
+; CHECK: .long 91 # BTF_KIND_STRUCT(id = [[TID2:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii "v3" # string offset=6
|
|
+; CHECK: .ascii ".text" # string offset=39
|
|
+; CHECK: .ascii "0:1" # string offset=45
|
|
+; CHECK: .ascii "v1" # string offset=91
|
|
+
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 39 # Offset reloc section string offset=39
|
|
+; CHECK-NEXT: .long 2
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 45
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID2]]
|
|
+; CHECK-NEXT: .long 45
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %struct.v2* @llvm.preserve.struct.access.index.p0s_struct.v2s.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v1s(%struct.v1*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone speculatable willreturn
|
|
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind readnone speculatable willreturn }
|
|
+attributes #4 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!0}
|
|
+!llvm.module.flags = !{!11, !12, !13}
|
|
+!llvm.ident = !{!14}
|
|
+
|
|
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
|
|
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!2 = !{}
|
|
+!3 = !{!4}
|
|
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
|
|
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v1", file: !1, line: 2, baseType: !6)
|
|
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v1", file: !1, line: 1, size: 64, elements: !7)
|
|
+!7 = !{!8, !10}
|
|
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !1, line: 1, baseType: !9, size: 32)
|
|
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !1, line: 1, baseType: !9, size: 32, offset: 32)
|
|
+!11 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!12 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!13 = !{i32 1, !"wchar_size", i32 4}
|
|
+!14 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!15 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 10, type: !16, scopeLine: 10, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !32)
|
|
+!16 = !DISubroutineType(types: !17)
|
|
+!17 = !{!9, !18}
|
|
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
|
|
+!19 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v3", file: !1, line: 6, baseType: !20)
|
|
+!20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v3", file: !1, line: 5, size: 96, elements: !21)
|
|
+!21 = !{!22, !24}
|
|
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !20, file: !1, line: 5, baseType: !23, size: 8)
|
|
+!23 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
|
+!24 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !20, file: !1, line: 5, baseType: !25, size: 64, offset: 32)
|
|
+!25 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !26)
|
|
+!26 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !27)
|
|
+!27 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v2", file: !1, line: 4, baseType: !28)
|
|
+!28 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v2", file: !1, line: 3, size: 64, elements: !29)
|
|
+!29 = !{!30, !31}
|
|
+!30 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !28, file: !1, line: 3, baseType: !9, size: 32)
|
|
+!31 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !28, file: !1, line: 3, baseType: !9, size: 32, offset: 32)
|
|
+!32 = !{!33}
|
|
+!33 = !DILocalVariable(name: "arg", arg: 1, scope: !15, file: !1, line: 10, type: !18)
|
|
+!34 = !DILocation(line: 0, scope: !15)
|
|
+!35 = !DILocation(line: 11, column: 20, scope: !15)
|
|
+!36 = !DILocation(line: 11, column: 10, scope: !15)
|
|
+!37 = !DILocation(line: 11, column: 3, scope: !15)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-3.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-3.ll
|
|
new file mode 100644
|
|
index 0000000..ed78b84
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-3.ll
|
|
@@ -0,0 +1,116 @@
|
|
+; 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 v1 { int a; int b; };
|
|
+; typedef struct v1 __v1;
|
|
+; typedef int __int;
|
|
+; struct v3 { char c; __int d[40]; };
|
|
+; typedef struct v3 __v3;
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; #define cast_to_v1(x) ((__v1 *)(x))
|
|
+; int get_value(const int *arg);
|
|
+; int test(__v3 *arg) {
|
|
+; return get_value(_(&cast_to_v1(&arg->d[4])->b));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%struct.v3 = type { i8, [40 x i32] }
|
|
+%struct.v1 = type { i32, i32 }
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test(%struct.v3* %arg) local_unnamed_addr #0 !dbg !19 {
|
|
+entry:
|
|
+ call void @llvm.dbg.value(metadata %struct.v3* %arg, metadata !30, metadata !DIExpression()), !dbg !31
|
|
+ %0 = tail call [40 x i32]* @llvm.preserve.struct.access.index.p0a40i32.p0s_struct.v3s(%struct.v3* %arg, i32 1, i32 1), !dbg !32, !llvm.preserve.access.index !24
|
|
+ %1 = tail call i32* @llvm.preserve.array.access.index.p0i32.p0a40i32([40 x i32]* %0, i32 1, i32 4), !dbg !32, !llvm.preserve.access.index !11
|
|
+ %2 = bitcast i32* %1 to %struct.v1*, !dbg !32
|
|
+ %3 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v1s(%struct.v1* %2, i32 1, i32 1), !dbg !32, !llvm.preserve.access.index !6
|
|
+ %call = tail call i32 @get_value(i32* %3) #4, !dbg !33
|
|
+ ret i32 %call, !dbg !34
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 20
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: r2 = 4
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 6 # BTF_KIND_STRUCT(id = [[TID1:[0-9]+]])
|
|
+; CHECK: .long 111 # BTF_KIND_STRUCT(id = [[TID2:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii "v3" # string offset=6
|
|
+; CHECK: .ascii ".text" # string offset=57
|
|
+; CHECK: .ascii "0:1:4" # string offset=63
|
|
+; CHECK: .ascii "v1" # string offset=111
|
|
+; CHECK: .ascii "0:1" # string offset=118
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 57 # Offset reloc section string offset=57
|
|
+; CHECK-NEXT: .long 2
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 63
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID2]]
|
|
+; CHECK-NEXT: .long 118
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare [40 x i32]* @llvm.preserve.struct.access.index.p0a40i32.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.array.access.index.p0i32.p0a40i32([40 x i32]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v1s(%struct.v1*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone speculatable willreturn
|
|
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind readnone speculatable willreturn }
|
|
+attributes #4 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!0}
|
|
+!llvm.module.flags = !{!15, !16, !17}
|
|
+!llvm.ident = !{!18}
|
|
+
|
|
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
|
|
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!2 = !{}
|
|
+!3 = !{!4, !11}
|
|
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
|
|
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v1", file: !1, line: 2, baseType: !6)
|
|
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v1", file: !1, line: 1, size: 64, elements: !7)
|
|
+!7 = !{!8, !10}
|
|
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !1, line: 1, baseType: !9, size: 32)
|
|
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !1, line: 1, baseType: !9, size: 32, offset: 32)
|
|
+!11 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 1280, elements: !13)
|
|
+!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !1, line: 3, baseType: !9)
|
|
+!13 = !{!14}
|
|
+!14 = !DISubrange(count: 40)
|
|
+!15 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!16 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!17 = !{i32 1, !"wchar_size", i32 4}
|
|
+!18 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!19 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 9, type: !20, scopeLine: 9, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !29)
|
|
+!20 = !DISubroutineType(types: !21)
|
|
+!21 = !{!9, !22}
|
|
+!22 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !23, size: 64)
|
|
+!23 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v3", file: !1, line: 5, baseType: !24)
|
|
+!24 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v3", file: !1, line: 4, size: 1312, elements: !25)
|
|
+!25 = !{!26, !28}
|
|
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !24, file: !1, line: 4, baseType: !27, size: 8)
|
|
+!27 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
|
+!28 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !24, file: !1, line: 4, baseType: !11, size: 1280, offset: 32)
|
|
+!29 = !{!30}
|
|
+!30 = !DILocalVariable(name: "arg", arg: 1, scope: !19, file: !1, line: 9, type: !22)
|
|
+!31 = !DILocation(line: 0, scope: !19)
|
|
+!32 = !DILocation(line: 10, column: 20, scope: !19)
|
|
+!33 = !DILocation(line: 10, column: 10, scope: !19)
|
|
+!34 = !DILocation(line: 10, column: 3, scope: !19)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-1.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-1.ll
|
|
new file mode 100644
|
|
index 0000000..1e8f99c
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-1.ll
|
|
@@ -0,0 +1,117 @@
|
|
+; 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:
|
|
+; union v1 { int a; int b; };
|
|
+; typedef union v1 __v1;
|
|
+; union v2 { int c; int d; };
|
|
+; typedef union v2 __v2;
|
|
+; union v3 { char c; volatile const __v2 d; };
|
|
+; typedef union v3 __v3;
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; #define cast_to_v1(x) ((__v1 *)(x))
|
|
+; int get_value(const int *arg);
|
|
+; int test(__v3 *arg) {
|
|
+; return get_value(_(&cast_to_v1(&arg->d)->b));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%union.v3 = type { %union.v2 }
|
|
+%union.v2 = type { i32 }
|
|
+%union.v1 = type { i32 }
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test(%union.v3* %arg) local_unnamed_addr #0 !dbg !15 {
|
|
+entry:
|
|
+ call void @llvm.dbg.value(metadata %union.v3* %arg, metadata !33, metadata !DIExpression()), !dbg !34
|
|
+ %0 = tail call %union.v3* @llvm.preserve.union.access.index.p0s_union.v3s.p0s_union.v3s(%union.v3* %arg, i32 1), !dbg !35, !llvm.preserve.access.index !20
|
|
+ %1 = bitcast %union.v3* %0 to %union.v1*, !dbg !35
|
|
+ %2 = tail call %union.v1* @llvm.preserve.union.access.index.p0s_union.v1s.p0s_union.v1s(%union.v1* %1, i32 1), !dbg !35, !llvm.preserve.access.index !6
|
|
+ %b = getelementptr inbounds %union.v1, %union.v1* %2, i64 0, i32 0, !dbg !35
|
|
+ %call = tail call i32 @get_value(i32* %b) #4, !dbg !36
|
|
+ ret i32 %call, !dbg !37
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 0
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: r2 = 0
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 6 # BTF_KIND_UNION(id = [[TID1:[0-9]+]])
|
|
+; CHECK: .long 91 # BTF_KIND_UNION(id = [[TID2:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii "v3" # string offset=6
|
|
+; CHECK: .ascii ".text" # string offset=39
|
|
+; CHECK: .ascii "0:1" # string offset=45
|
|
+; CHECK: .ascii "v1" # string offset=91
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 39 # Offset reloc section string offset=39
|
|
+; CHECK-NEXT: .long 2
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 45
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID2]]
|
|
+; CHECK-NEXT: .long 45
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %union.v3* @llvm.preserve.union.access.index.p0s_union.v3s.p0s_union.v3s(%union.v3*, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %union.v1* @llvm.preserve.union.access.index.p0s_union.v1s.p0s_union.v1s(%union.v1*, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone speculatable willreturn
|
|
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind readnone speculatable willreturn }
|
|
+attributes #4 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!0}
|
|
+!llvm.module.flags = !{!11, !12, !13}
|
|
+!llvm.ident = !{!14}
|
|
+
|
|
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
|
|
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!2 = !{}
|
|
+!3 = !{!4}
|
|
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
|
|
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v1", file: !1, line: 2, baseType: !6)
|
|
+!6 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "v1", file: !1, line: 1, size: 32, elements: !7)
|
|
+!7 = !{!8, !10}
|
|
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !1, line: 1, baseType: !9, size: 32)
|
|
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !1, line: 1, baseType: !9, size: 32)
|
|
+!11 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!12 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!13 = !{i32 1, !"wchar_size", i32 4}
|
|
+!14 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!15 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 10, type: !16, scopeLine: 10, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !32)
|
|
+!16 = !DISubroutineType(types: !17)
|
|
+!17 = !{!9, !18}
|
|
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
|
|
+!19 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v3", file: !1, line: 6, baseType: !20)
|
|
+!20 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "v3", file: !1, line: 5, size: 32, elements: !21)
|
|
+!21 = !{!22, !24}
|
|
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !20, file: !1, line: 5, baseType: !23, size: 8)
|
|
+!23 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
|
+!24 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !20, file: !1, line: 5, baseType: !25, size: 32)
|
|
+!25 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !26)
|
|
+!26 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !27)
|
|
+!27 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v2", file: !1, line: 4, baseType: !28)
|
|
+!28 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "v2", file: !1, line: 3, size: 32, elements: !29)
|
|
+!29 = !{!30, !31}
|
|
+!30 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !28, file: !1, line: 3, baseType: !9, size: 32)
|
|
+!31 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !28, file: !1, line: 3, baseType: !9, size: 32)
|
|
+!32 = !{!33}
|
|
+!33 = !DILocalVariable(name: "arg", arg: 1, scope: !15, file: !1, line: 10, type: !18)
|
|
+!34 = !DILocation(line: 0, scope: !15)
|
|
+!35 = !DILocation(line: 11, column: 20, scope: !15)
|
|
+!36 = !DILocation(line: 11, column: 10, scope: !15)
|
|
+!37 = !DILocation(line: 11, column: 3, scope: !15)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-2.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-2.ll
|
|
new file mode 100644
|
|
index 0000000..320b0a9
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-2.ll
|
|
@@ -0,0 +1,118 @@
|
|
+; 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:
|
|
+; union v1 { int a; int b; };
|
|
+; typedef union v1 __v1;
|
|
+; typedef int __int;
|
|
+; union v3 { char c; __int d[40]; };
|
|
+; typedef union v3 __v3;
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; #define cast_to_v1(x) ((__v1 *)(x))
|
|
+; int get_value(const int *arg);
|
|
+; int test(__v3 *arg) {
|
|
+; return get_value(_(&cast_to_v1(&arg->d[4])->b));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%union.v3 = type { [40 x i32] }
|
|
+%union.v1 = type { i32 }
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test(%union.v3* %arg) local_unnamed_addr #0 !dbg !19 {
|
|
+entry:
|
|
+ call void @llvm.dbg.value(metadata %union.v3* %arg, metadata !30, metadata !DIExpression()), !dbg !31
|
|
+ %0 = tail call %union.v3* @llvm.preserve.union.access.index.p0s_union.v3s.p0s_union.v3s(%union.v3* %arg, i32 1), !dbg !32, !llvm.preserve.access.index !24
|
|
+ %d = getelementptr inbounds %union.v3, %union.v3* %0, i64 0, i32 0, !dbg !32
|
|
+ %1 = tail call i32* @llvm.preserve.array.access.index.p0i32.p0a40i32([40 x i32]* %d, i32 1, i32 4), !dbg !32, !llvm.preserve.access.index !11
|
|
+ %2 = bitcast i32* %1 to %union.v1*, !dbg !32
|
|
+ %3 = tail call %union.v1* @llvm.preserve.union.access.index.p0s_union.v1s.p0s_union.v1s(%union.v1* %2, i32 1), !dbg !32, !llvm.preserve.access.index !6
|
|
+ %b = getelementptr inbounds %union.v1, %union.v1* %3, i64 0, i32 0, !dbg !32
|
|
+ %call = tail call i32 @get_value(i32* %b) #4, !dbg !33
|
|
+ ret i32 %call, !dbg !34
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 16
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: r2 = 0
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 6 # BTF_KIND_UNION(id = [[TID1:[0-9]+]])
|
|
+; CHECK: .long 111 # BTF_KIND_UNION(id = [[TID2:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii "v3" # string offset=6
|
|
+; CHECK: .ascii ".text" # string offset=57
|
|
+; CHECK: .ascii "0:1:4" # string offset=63
|
|
+; CHECK: .ascii "v1" # string offset=111
|
|
+; CHECK: .ascii "0:1" # string offset=118
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 57 # Offset reloc section string offset=57
|
|
+; CHECK-NEXT: .long 2
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 63
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID2]]
|
|
+; CHECK-NEXT: .long 118
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %union.v3* @llvm.preserve.union.access.index.p0s_union.v3s.p0s_union.v3s(%union.v3*, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.array.access.index.p0i32.p0a40i32([40 x i32]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %union.v1* @llvm.preserve.union.access.index.p0s_union.v1s.p0s_union.v1s(%union.v1*, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone speculatable willreturn
|
|
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind readnone speculatable willreturn }
|
|
+attributes #4 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!0}
|
|
+!llvm.module.flags = !{!15, !16, !17}
|
|
+!llvm.ident = !{!18}
|
|
+
|
|
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
|
|
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!2 = !{}
|
|
+!3 = !{!4, !11}
|
|
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
|
|
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v1", file: !1, line: 2, baseType: !6)
|
|
+!6 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "v1", file: !1, line: 1, size: 32, elements: !7)
|
|
+!7 = !{!8, !10}
|
|
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !1, line: 1, baseType: !9, size: 32)
|
|
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !1, line: 1, baseType: !9, size: 32)
|
|
+!11 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 1280, elements: !13)
|
|
+!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !1, line: 3, baseType: !9)
|
|
+!13 = !{!14}
|
|
+!14 = !DISubrange(count: 40)
|
|
+!15 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!16 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!17 = !{i32 1, !"wchar_size", i32 4}
|
|
+!18 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!19 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 9, type: !20, scopeLine: 9, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !29)
|
|
+!20 = !DISubroutineType(types: !21)
|
|
+!21 = !{!9, !22}
|
|
+!22 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !23, size: 64)
|
|
+!23 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v3", file: !1, line: 5, baseType: !24)
|
|
+!24 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "v3", file: !1, line: 4, size: 1280, elements: !25)
|
|
+!25 = !{!26, !28}
|
|
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !24, file: !1, line: 4, baseType: !27, size: 8)
|
|
+!27 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
|
+!28 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !24, file: !1, line: 4, baseType: !11, size: 1280)
|
|
+!29 = !{!30}
|
|
+!30 = !DILocalVariable(name: "arg", arg: 1, scope: !19, file: !1, line: 9, type: !22)
|
|
+!31 = !DILocation(line: 0, scope: !19)
|
|
+!32 = !DILocation(line: 10, column: 20, scope: !19)
|
|
+!33 = !DILocation(line: 10, column: 10, scope: !19)
|
|
+!34 = !DILocation(line: 10, column: 3, scope: !19)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-global-1.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-global-1.ll
|
|
new file mode 100644
|
|
index 0000000..296e2d4
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-global-1.ll
|
|
@@ -0,0 +1,79 @@
|
|
+; 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:
|
|
+; typedef struct v3 { int a; int b; } __v3;
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; int get_value(const int *arg);
|
|
+; __v3 g __attribute__((section("stats")));
|
|
+; int test() {
|
|
+; return get_value(_(&g.b));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%struct.v3 = type { i32, i32 }
|
|
+
|
|
+@g = dso_local global %struct.v3 zeroinitializer, section "stats", align 4, !dbg !0
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test() local_unnamed_addr #0 !dbg !16 {
|
|
+entry:
|
|
+ %0 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v3s(%struct.v3* nonnull @g, i32 1, i32 1), !dbg !19, !llvm.preserve.access.index !7
|
|
+ %call = tail call i32 @get_value(i32* %0) #3, !dbg !20
|
|
+ ret i32 %call, !dbg !21
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 4
|
|
+; CHECK: r1 = g ll
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 16 # BTF_KIND_STRUCT(id = [[TID1:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii ".text" # string offset=10
|
|
+; CHECK: .ascii "v3" # string offset=16
|
|
+; CHECK: .ascii "0:1" # string offset=23
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 10 # Offset reloc section string offset=10
|
|
+; CHECK-NEXT: .long 1
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 23
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!2}
|
|
+!llvm.module.flags = !{!12, !13, !14}
|
|
+!llvm.ident = !{!15}
|
|
+
|
|
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
|
+!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 4, type: !6, isLocal: false, isDefinition: true)
|
|
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
|
|
+!3 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!4 = !{}
|
|
+!5 = !{!0}
|
|
+!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v3", file: !3, line: 1, baseType: !7)
|
|
+!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v3", file: !3, line: 1, size: 64, elements: !8)
|
|
+!8 = !{!9, !11}
|
|
+!9 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !7, file: !3, line: 1, baseType: !10, size: 32)
|
|
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!11 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !7, file: !3, line: 1, baseType: !10, size: 32, offset: 32)
|
|
+!12 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!13 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!14 = !{i32 1, !"wchar_size", i32 4}
|
|
+!15 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!16 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 5, type: !17, scopeLine: 5, isDefinition: true, isOptimized: true, unit: !2, retainedNodes: !4)
|
|
+!17 = !DISubroutineType(types: !18)
|
|
+!18 = !{!10}
|
|
+!19 = !DILocation(line: 6, column: 20, scope: !16)
|
|
+!20 = !DILocation(line: 6, column: 10, scope: !16)
|
|
+!21 = !DILocation(line: 6, column: 3, scope: !16)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-global-2.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-global-2.ll
|
|
new file mode 100644
|
|
index 0000000..721081e
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-global-2.ll
|
|
@@ -0,0 +1,95 @@
|
|
+; 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:
|
|
+; typedef struct v3 { int a; int b; } __v3;
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; int get_value(const int *arg);
|
|
+; __v3 g[4][5] __attribute__((section("stats")));
|
|
+; int test() {
|
|
+; return get_value(_(&g[1][2].b));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%struct.v3 = type { i32, i32 }
|
|
+
|
|
+@g = dso_local global [4 x [5 x %struct.v3]] zeroinitializer, section "stats", align 4, !dbg !0
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test() local_unnamed_addr #0 !dbg !23 {
|
|
+entry:
|
|
+ %0 = tail call [5 x %struct.v3]* @llvm.preserve.array.access.index.p0a5s_struct.v3s.p0a4a5s_struct.v3s([4 x [5 x %struct.v3]]* nonnull @g, i32 1, i32 1), !dbg !26, !llvm.preserve.access.index !6
|
|
+ %1 = tail call %struct.v3* @llvm.preserve.array.access.index.p0s_struct.v3s.p0a5s_struct.v3s([5 x %struct.v3]* %0, i32 1, i32 2), !dbg !26, !llvm.preserve.access.index !16
|
|
+ %2 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v3s(%struct.v3* %1, i32 1, i32 1), !dbg !26, !llvm.preserve.access.index !8
|
|
+ %call = tail call i32 @get_value(i32* %2) #3, !dbg !27
|
|
+ ret i32 %call, !dbg !28
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 60
|
|
+; CHECK: r1 = g ll
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 16 # BTF_KIND_STRUCT(id = [[TID1:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii ".text" # string offset=10
|
|
+; CHECK: .ascii "v3" # string offset=16
|
|
+; CHECK: .ascii "7:1" # string offset=23
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 10 # Offset reloc section string offset=10
|
|
+; CHECK-NEXT: .long 1
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 23
|
|
+
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare [5 x %struct.v3]* @llvm.preserve.array.access.index.p0a5s_struct.v3s.p0a4a5s_struct.v3s([4 x [5 x %struct.v3]]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %struct.v3* @llvm.preserve.array.access.index.p0s_struct.v3s.p0a5s_struct.v3s([5 x %struct.v3]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!2}
|
|
+!llvm.module.flags = !{!19, !20, !21}
|
|
+!llvm.ident = !{!22}
|
|
+
|
|
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
|
+!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 4, type: !6, isLocal: false, isDefinition: true)
|
|
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !18, nameTableKind: None)
|
|
+!3 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!4 = !{}
|
|
+!5 = !{!6, !16}
|
|
+!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 1280, elements: !13)
|
|
+!7 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v3", file: !3, line: 1, baseType: !8)
|
|
+!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v3", file: !3, line: 1, size: 64, elements: !9)
|
|
+!9 = !{!10, !12}
|
|
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !8, file: !3, line: 1, baseType: !11, size: 32)
|
|
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !8, file: !3, line: 1, baseType: !11, size: 32, offset: 32)
|
|
+!13 = !{!14, !15}
|
|
+!14 = !DISubrange(count: 4)
|
|
+!15 = !DISubrange(count: 5)
|
|
+!16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 320, elements: !17)
|
|
+!17 = !{!15}
|
|
+!18 = !{!0}
|
|
+!19 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!20 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!21 = !{i32 1, !"wchar_size", i32 4}
|
|
+!22 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!23 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 5, type: !24, scopeLine: 5, isDefinition: true, isOptimized: true, unit: !2, retainedNodes: !4)
|
|
+!24 = !DISubroutineType(types: !25)
|
|
+!25 = !{!11}
|
|
+!26 = !DILocation(line: 6, column: 20, scope: !23)
|
|
+!27 = !DILocation(line: 6, column: 10, scope: !23)
|
|
+!28 = !DILocation(line: 6, column: 3, scope: !23)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-global-3.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-global-3.ll
|
|
new file mode 100644
|
|
index 0000000..394d04f
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-global-3.ll
|
|
@@ -0,0 +1,84 @@
|
|
+; 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:
|
|
+; typedef struct v3 { int a; int b; } __v3;
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; int get_value(const int *arg);
|
|
+; __v3 *g __attribute__((section("stats")));
|
|
+; int test() {
|
|
+; return get_value(_(&g->b));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%struct.v3 = type { i32, i32 }
|
|
+
|
|
+@g = dso_local local_unnamed_addr global %struct.v3* null, section "stats", align 8, !dbg !0
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test() local_unnamed_addr #0 !dbg !17 {
|
|
+entry:
|
|
+ %0 = load %struct.v3*, %struct.v3** @g, align 8, !dbg !20, !tbaa !21
|
|
+ %1 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v3s(%struct.v3* %0, i32 1, i32 1), !dbg !20, !llvm.preserve.access.index !8
|
|
+ %call = tail call i32 @get_value(i32* %1) #3, !dbg !25
|
|
+ ret i32 %call, !dbg !26
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 4
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 16 # BTF_KIND_STRUCT(id = [[TID1:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii ".text" # string offset=10
|
|
+; CHECK: .ascii "v3" # string offset=16
|
|
+; CHECK: .ascii "0:1" # string offset=23
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 10 # Offset reloc section string offset=10
|
|
+; CHECK-NEXT: .long 1
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 23
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!2}
|
|
+!llvm.module.flags = !{!13, !14, !15}
|
|
+!llvm.ident = !{!16}
|
|
+
|
|
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
|
+!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 4, type: !6, isLocal: false, isDefinition: true)
|
|
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
|
|
+!3 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!4 = !{}
|
|
+!5 = !{!0}
|
|
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
|
|
+!7 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v3", file: !3, line: 1, baseType: !8)
|
|
+!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v3", file: !3, line: 1, size: 64, elements: !9)
|
|
+!9 = !{!10, !12}
|
|
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !8, file: !3, line: 1, baseType: !11, size: 32)
|
|
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !8, file: !3, line: 1, baseType: !11, size: 32, offset: 32)
|
|
+!13 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!14 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!15 = !{i32 1, !"wchar_size", i32 4}
|
|
+!16 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!17 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 5, type: !18, scopeLine: 5, isDefinition: true, isOptimized: true, unit: !2, retainedNodes: !4)
|
|
+!18 = !DISubroutineType(types: !19)
|
|
+!19 = !{!11}
|
|
+!20 = !DILocation(line: 6, column: 20, scope: !17)
|
|
+!21 = !{!22, !22, i64 0}
|
|
+!22 = !{!"any pointer", !23, i64 0}
|
|
+!23 = !{!"omnipotent char", !24, i64 0}
|
|
+!24 = !{!"Simple C/C++ TBAA"}
|
|
+!25 = !DILocation(line: 6, column: 10, scope: !17)
|
|
+!26 = !DILocation(line: 6, column: 3, scope: !17)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-ignore.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-ignore.ll
|
|
new file mode 100644
|
|
index 0000000..2d14e71
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-ignore.ll
|
|
@@ -0,0 +1,62 @@
|
|
+; 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:
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; int get_value(const int *arg);
|
|
+; int test(int *arg) {
|
|
+; return get_value(_(&arg[4]));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test(i32* %arg) local_unnamed_addr #0 !dbg !10 {
|
|
+entry:
|
|
+ call void @llvm.dbg.value(metadata i32* %arg, metadata !14, metadata !DIExpression()), !dbg !15
|
|
+ %0 = tail call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %arg, i32 0, i32 4), !dbg !16, !llvm.preserve.access.index !4
|
|
+ %call = tail call i32 @get_value(i32* %0) #4, !dbg !17
|
|
+ ret i32 %call, !dbg !18
|
|
+}
|
|
+
|
|
+; CHECK: r1 += 16
|
|
+; CHECK: call get_value
|
|
+; CHECK: .section .BTF.ext,"",@progbits
|
|
+; CHECK-NOT: .long 12 # OffsetReloc
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone speculatable willreturn
|
|
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind readnone speculatable willreturn }
|
|
+attributes #4 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!0}
|
|
+!llvm.module.flags = !{!6, !7, !8}
|
|
+!llvm.ident = !{!9}
|
|
+
|
|
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
|
|
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!2 = !{}
|
|
+!3 = !{!4}
|
|
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
|
|
+!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!6 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!7 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!8 = !{i32 1, !"wchar_size", i32 4}
|
|
+!9 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!10 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 3, type: !11, scopeLine: 3, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !13)
|
|
+!11 = !DISubroutineType(types: !12)
|
|
+!12 = !{!5, !4}
|
|
+!13 = !{!14}
|
|
+!14 = !DILocalVariable(name: "arg", arg: 1, scope: !10, file: !1, line: 3, type: !4)
|
|
+!15 = !DILocation(line: 0, scope: !10)
|
|
+!16 = !DILocation(line: 4, column: 20, scope: !10)
|
|
+!17 = !DILocation(line: 4, column: 10, scope: !10)
|
|
+!18 = !DILocation(line: 4, column: 3, scope: !10)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-1.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-1.ll
|
|
new file mode 100644
|
|
index 0000000..7f79196f
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-1.ll
|
|
@@ -0,0 +1,101 @@
|
|
+; 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:
|
|
+; typedef int __int;
|
|
+; typedef struct v3 { int a; __int b[4][4]; } __v3;
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; int get_value(const int *arg);
|
|
+; int test(__v3 *arg) {
|
|
+; return get_value(_(&arg[1].b[2][3]));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%struct.v3 = type { i32, [4 x [4 x i32]] }
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test(%struct.v3* %arg) local_unnamed_addr #0 !dbg !21 {
|
|
+entry:
|
|
+ call void @llvm.dbg.value(metadata %struct.v3* %arg, metadata !25, metadata !DIExpression()), !dbg !26
|
|
+ %0 = tail call %struct.v3* @llvm.preserve.array.access.index.p0s_struct.v3s.p0s_struct.v3s(%struct.v3* %arg, i32 0, i32 1), !dbg !27, !llvm.preserve.access.index !4
|
|
+ %1 = tail call [4 x [4 x i32]]* @llvm.preserve.struct.access.index.p0a4a4i32.p0s_struct.v3s(%struct.v3* %0, i32 1, i32 1), !dbg !27, !llvm.preserve.access.index !6
|
|
+ %2 = tail call [4 x i32]* @llvm.preserve.array.access.index.p0a4i32.p0a4a4i32([4 x [4 x i32]]* %1, i32 1, i32 2), !dbg !27, !llvm.preserve.access.index !11
|
|
+ %3 = tail call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %2, i32 1, i32 3), !dbg !27, !llvm.preserve.access.index !15
|
|
+ %call = tail call i32 @get_value(i32* %3) #4, !dbg !28
|
|
+ ret i32 %call, !dbg !29
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 116
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 6 # BTF_KIND_STRUCT(id = [[TID1:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii "v3" # string offset=6
|
|
+; CHECK: .ascii ".text" # string offset=52
|
|
+; CHECK: .ascii "1:1:2:3" # string offset=58
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 52 # Offset reloc section string offset=52
|
|
+; CHECK-NEXT: .long 1
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 58
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %struct.v3* @llvm.preserve.array.access.index.p0s_struct.v3s.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare [4 x [4 x i32]]* @llvm.preserve.struct.access.index.p0a4a4i32.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare [4 x i32]* @llvm.preserve.array.access.index.p0a4i32.p0a4a4i32([4 x [4 x i32]]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone speculatable willreturn
|
|
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind readnone speculatable willreturn }
|
|
+attributes #4 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!0}
|
|
+!llvm.module.flags = !{!17, !18, !19}
|
|
+!llvm.ident = !{!20}
|
|
+
|
|
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
|
|
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!2 = !{}
|
|
+!3 = !{!4, !11, !15}
|
|
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
|
|
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v3", file: !1, line: 2, baseType: !6)
|
|
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v3", file: !1, line: 2, size: 544, elements: !7)
|
|
+!7 = !{!8, !10}
|
|
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !1, line: 2, baseType: !9, size: 32)
|
|
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !1, line: 2, baseType: !11, size: 512, offset: 32)
|
|
+!11 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 512, elements: !13)
|
|
+!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !1, line: 1, baseType: !9)
|
|
+!13 = !{!14, !14}
|
|
+!14 = !DISubrange(count: 4)
|
|
+!15 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 128, elements: !16)
|
|
+!16 = !{!14}
|
|
+!17 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!18 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!19 = !{i32 1, !"wchar_size", i32 4}
|
|
+!20 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!21 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 5, type: !22, scopeLine: 5, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !24)
|
|
+!22 = !DISubroutineType(types: !23)
|
|
+!23 = !{!9, !4}
|
|
+!24 = !{!25}
|
|
+!25 = !DILocalVariable(name: "arg", arg: 1, scope: !21, file: !1, line: 5, type: !4)
|
|
+!26 = !DILocation(line: 0, scope: !21)
|
|
+!27 = !DILocation(line: 6, column: 20, scope: !21)
|
|
+!28 = !DILocation(line: 6, column: 10, scope: !21)
|
|
+!29 = !DILocation(line: 6, column: 3, scope: !21)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-2.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-2.ll
|
|
new file mode 100644
|
|
index 0000000..a9c29aa
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-2.ll
|
|
@@ -0,0 +1,107 @@
|
|
+; 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:
|
|
+; typedef int __int;
|
|
+; typedef struct v3 { int a; __int b[4][4][4]; } __v3;
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; int get_value(const int *arg);
|
|
+; int test(__v3 *arg) {
|
|
+; return get_value(_(&arg[1].b[2][3][2]));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%struct.v3 = type { i32, [4 x [4 x [4 x i32]]] }
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test(%struct.v3* %arg) local_unnamed_addr #0 !dbg !23 {
|
|
+entry:
|
|
+ call void @llvm.dbg.value(metadata %struct.v3* %arg, metadata !27, metadata !DIExpression()), !dbg !28
|
|
+ %0 = tail call %struct.v3* @llvm.preserve.array.access.index.p0s_struct.v3s.p0s_struct.v3s(%struct.v3* %arg, i32 0, i32 1), !dbg !29, !llvm.preserve.access.index !4
|
|
+ %1 = tail call [4 x [4 x [4 x i32]]]* @llvm.preserve.struct.access.index.p0a4a4a4i32.p0s_struct.v3s(%struct.v3* %0, i32 1, i32 1), !dbg !29, !llvm.preserve.access.index !6
|
|
+ %2 = tail call [4 x [4 x i32]]* @llvm.preserve.array.access.index.p0a4a4i32.p0a4a4a4i32([4 x [4 x [4 x i32]]]* %1, i32 1, i32 2), !dbg !29, !llvm.preserve.access.index !11
|
|
+ %3 = tail call [4 x i32]* @llvm.preserve.array.access.index.p0a4i32.p0a4a4i32([4 x [4 x i32]]* %2, i32 1, i32 3), !dbg !29, !llvm.preserve.access.index !15
|
|
+ %4 = tail call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %3, i32 1, i32 2), !dbg !29, !llvm.preserve.access.index !17
|
|
+ %call = tail call i32 @get_value(i32* %4) #4, !dbg !30
|
|
+ ret i32 %call, !dbg !31
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 448
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 6 # BTF_KIND_STRUCT(id = [[TID1:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii "v3" # string offset=6
|
|
+; CHECK: .ascii ".text" # string offset=52
|
|
+; CHECK: .ascii "1:1:2:3:2" # string offset=58
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 52 # Offset reloc section string offset=52
|
|
+; CHECK-NEXT: .long 1
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 58
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %struct.v3* @llvm.preserve.array.access.index.p0s_struct.v3s.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare [4 x [4 x [4 x i32]]]* @llvm.preserve.struct.access.index.p0a4a4a4i32.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare [4 x [4 x i32]]* @llvm.preserve.array.access.index.p0a4a4i32.p0a4a4a4i32([4 x [4 x [4 x i32]]]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare [4 x i32]* @llvm.preserve.array.access.index.p0a4i32.p0a4a4i32([4 x [4 x i32]]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone speculatable willreturn
|
|
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind readnone speculatable willreturn }
|
|
+attributes #4 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!0}
|
|
+!llvm.module.flags = !{!19, !20, !21}
|
|
+!llvm.ident = !{!22}
|
|
+
|
|
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
|
|
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!2 = !{}
|
|
+!3 = !{!4, !11, !15, !17}
|
|
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
|
|
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v3", file: !1, line: 2, baseType: !6)
|
|
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v3", file: !1, line: 2, size: 2080, elements: !7)
|
|
+!7 = !{!8, !10}
|
|
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !1, line: 2, baseType: !9, size: 32)
|
|
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !1, line: 2, baseType: !11, size: 2048, offset: 32)
|
|
+!11 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 2048, elements: !13)
|
|
+!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !1, line: 1, baseType: !9)
|
|
+!13 = !{!14, !14, !14}
|
|
+!14 = !DISubrange(count: 4)
|
|
+!15 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 512, elements: !16)
|
|
+!16 = !{!14, !14}
|
|
+!17 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 128, elements: !18)
|
|
+!18 = !{!14}
|
|
+!19 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!20 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!21 = !{i32 1, !"wchar_size", i32 4}
|
|
+!22 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!23 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 5, type: !24, scopeLine: 5, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !26)
|
|
+!24 = !DISubroutineType(types: !25)
|
|
+!25 = !{!9, !4}
|
|
+!26 = !{!27}
|
|
+!27 = !DILocalVariable(name: "arg", arg: 1, scope: !23, file: !1, line: 5, type: !4)
|
|
+!28 = !DILocation(line: 0, scope: !23)
|
|
+!29 = !DILocation(line: 6, column: 20, scope: !23)
|
|
+!30 = !DILocation(line: 6, column: 10, scope: !23)
|
|
+!31 = !DILocation(line: 6, column: 3, scope: !23)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-1.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-1.ll
|
|
new file mode 100644
|
|
index 0000000..e85b393
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-1.ll
|
|
@@ -0,0 +1,83 @@
|
|
+; 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:
|
|
+; typedef struct v3 { int a; int b; } __v3;
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; int get_value(const int *arg);
|
|
+; int test(__v3 *arg) {
|
|
+; return get_value(_(&arg[1]));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%struct.v3 = type { i32, i32 }
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test(%struct.v3* %arg) local_unnamed_addr #0 !dbg !15 {
|
|
+entry:
|
|
+ call void @llvm.dbg.value(metadata %struct.v3* %arg, metadata !19, metadata !DIExpression()), !dbg !20
|
|
+ %0 = tail call %struct.v3* @llvm.preserve.array.access.index.p0s_struct.v3s.p0s_struct.v3s(%struct.v3* %arg, i32 0, i32 1), !dbg !21, !llvm.preserve.access.index !4
|
|
+ %1 = getelementptr inbounds %struct.v3, %struct.v3* %0, i64 0, i32 0, !dbg !21
|
|
+ %call = tail call i32 @get_value(i32* %1) #4, !dbg !22
|
|
+ ret i32 %call, !dbg !23
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 8
|
|
+; CHECK: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 6 # BTF_KIND_STRUCT(id = [[TID1:[0-9]+]])
|
|
+
|
|
+; CHECK: .ascii "v3" # string offset=6
|
|
+; CHECK: .ascii ".text" # string offset=26
|
|
+; CHECK: .byte 49 # string offset=32
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 26 # Offset reloc section string offset=26
|
|
+; CHECK-NEXT: .long 1
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 32
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %struct.v3* @llvm.preserve.array.access.index.p0s_struct.v3s.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone speculatable willreturn
|
|
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind readnone speculatable willreturn }
|
|
+attributes #4 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!0}
|
|
+!llvm.module.flags = !{!11, !12, !13}
|
|
+!llvm.ident = !{!14}
|
|
+
|
|
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
|
|
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!2 = !{}
|
|
+!3 = !{!4}
|
|
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
|
|
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v3", file: !1, line: 1, baseType: !6)
|
|
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v3", file: !1, line: 1, size: 64, elements: !7)
|
|
+!7 = !{!8, !10}
|
|
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !1, line: 1, baseType: !9, size: 32)
|
|
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !1, line: 1, baseType: !9, size: 32, offset: 32)
|
|
+!11 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!12 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!13 = !{i32 1, !"wchar_size", i32 4}
|
|
+!14 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!15 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 4, type: !16, scopeLine: 4, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !18)
|
|
+!16 = !DISubroutineType(types: !17)
|
|
+!17 = !{!9, !4}
|
|
+!18 = !{!19}
|
|
+!19 = !DILocalVariable(name: "arg", arg: 1, scope: !15, file: !1, line: 4, type: !4)
|
|
+!20 = !DILocation(line: 0, scope: !15)
|
|
+!21 = !DILocation(line: 5, column: 20, scope: !15)
|
|
+!22 = !DILocation(line: 5, column: 10, scope: !15)
|
|
+!23 = !DILocation(line: 5, column: 3, scope: !15)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-2.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-2.ll
|
|
new file mode 100644
|
|
index 0000000..1c54935
|
|
--- /dev/null
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-2.ll
|
|
@@ -0,0 +1,85 @@
|
|
+; 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:
|
|
+; typedef struct v3 { int a; int b; } __v3;
|
|
+; #define _(x) (__builtin_preserve_access_index(x))
|
|
+; int get_value(const int *arg);
|
|
+; int test(__v3 *arg) {
|
|
+; return get_value(_(&arg[1].b));
|
|
+; }
|
|
+; Compilation flag:
|
|
+; clang -target bpf -O2 -g -S -emit-llvm test.c
|
|
+
|
|
+%struct.v3 = type { i32, i32 }
|
|
+
|
|
+; Function Attrs: nounwind
|
|
+define dso_local i32 @test(%struct.v3* %arg) local_unnamed_addr #0 !dbg !15 {
|
|
+entry:
|
|
+ call void @llvm.dbg.value(metadata %struct.v3* %arg, metadata !19, metadata !DIExpression()), !dbg !20
|
|
+ %0 = tail call %struct.v3* @llvm.preserve.array.access.index.p0s_struct.v3s.p0s_struct.v3s(%struct.v3* %arg, i32 0, i32 1), !dbg !21, !llvm.preserve.access.index !4
|
|
+ %1 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v3s(%struct.v3* %0, i32 1, i32 1), !dbg !21, !llvm.preserve.access.index !6
|
|
+ %call = tail call i32 @get_value(i32* %1) #4, !dbg !22
|
|
+ ret i32 %call, !dbg !23
|
|
+}
|
|
+
|
|
+; CHECK: r2 = 12
|
|
+; CHECK-NEXT: r1 += r2
|
|
+; CHECK: call get_value
|
|
+
|
|
+; CHECK: .long 6 # BTF_KIND_STRUCT(id = [[TID1:[0-9]+]])
|
|
+; CHECK: .ascii "v3" # string offset=6
|
|
+; CHECK: .ascii ".text" # string offset=26
|
|
+; CHECK: .ascii "1:1" # string offset=32
|
|
+
|
|
+; CHECK: .long 12 # OffsetReloc
|
|
+; CHECK-NEXT: .long 26 # Offset reloc section string offset=26
|
|
+; CHECK-NEXT: .long 1
|
|
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
|
|
+; CHECK-NEXT: .long [[TID1]]
|
|
+; CHECK-NEXT: .long 32
|
|
+
|
|
+declare dso_local i32 @get_value(i32*) local_unnamed_addr #1
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare %struct.v3* @llvm.preserve.array.access.index.p0s_struct.v3s.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone
|
|
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.v3s(%struct.v3*, i32, i32) #2
|
|
+
|
|
+; Function Attrs: nounwind readnone speculatable willreturn
|
|
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
|
|
+
|
|
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
+attributes #2 = { nounwind readnone }
|
|
+attributes #3 = { nounwind readnone speculatable willreturn }
|
|
+attributes #4 = { nounwind }
|
|
+
|
|
+!llvm.dbg.cu = !{!0}
|
|
+!llvm.module.flags = !{!11, !12, !13}
|
|
+!llvm.ident = !{!14}
|
|
+
|
|
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
|
|
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
|
|
+!2 = !{}
|
|
+!3 = !{!4}
|
|
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
|
|
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "__v3", file: !1, line: 1, baseType: !6)
|
|
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v3", file: !1, line: 1, size: 64, elements: !7)
|
|
+!7 = !{!8, !10}
|
|
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !1, line: 1, baseType: !9, size: 32)
|
|
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !1, line: 1, baseType: !9, size: 32, offset: 32)
|
|
+!11 = !{i32 2, !"Dwarf Version", i32 4}
|
|
+!12 = !{i32 2, !"Debug Info Version", i32 3}
|
|
+!13 = !{i32 1, !"wchar_size", i32 4}
|
|
+!14 = !{!"clang version 10.0.0 (trunk 367256) (llvm/trunk 367266)"}
|
|
+!15 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 4, type: !16, scopeLine: 4, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !18)
|
|
+!16 = !DISubroutineType(types: !17)
|
|
+!17 = !{!9, !4}
|
|
+!18 = !{!19}
|
|
+!19 = !DILocalVariable(name: "arg", arg: 1, scope: !15, file: !1, line: 4, type: !4)
|
|
+!20 = !DILocation(line: 0, scope: !15)
|
|
+!21 = !DILocation(line: 5, column: 20, scope: !15)
|
|
+!22 = !DILocation(line: 5, column: 10, scope: !15)
|
|
+!23 = !DILocation(line: 5, column: 3, scope: !15)
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll
|
|
index 732187c..08a204f 100644
|
|
--- a/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll
|
|
@@ -30,7 +30,7 @@ define dso_local i32 @bpf_prog(%struct.sk_buff*) local_unnamed_addr #0 !dbg !15
|
|
%3 = bitcast i32* %2 to i8*, !dbg !34
|
|
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #4, !dbg !34
|
|
%4 = tail call [10 x %struct.anon]* @llvm.preserve.struct.access.index.p0a10s_struct.anons.p0s_struct.sk_buffs(%struct.sk_buff* %0, i32 1, i32 1), !dbg !35, !llvm.preserve.access.index !19
|
|
- %5 = tail call %struct.anon* @llvm.preserve.array.access.index.p0s_struct.anons.p0a10s_struct.anons([10 x %struct.anon]* %4, i32 1, i32 5), !dbg !35
|
|
+ %5 = tail call %struct.anon* @llvm.preserve.array.access.index.p0s_struct.anons.p0a10s_struct.anons([10 x %struct.anon]* %4, i32 1, i32 5), !dbg !35, !llvm.preserve.access.index !23
|
|
%6 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.anons(%struct.anon* %5, i32 0, i32 0), !dbg !35, !llvm.preserve.access.index !24
|
|
%7 = bitcast i32* %6 to i8*, !dbg !35
|
|
%8 = call i32 inttoptr (i64 4 to i32 (i8*, i32, i8*)*)(i8* nonnull %3, i32 4, i8* %7) #4, !dbg !36
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll
|
|
index 77d2375..b18a4ab 100644
|
|
--- a/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll
|
|
@@ -31,7 +31,7 @@ define dso_local i32 @bpf_prog(%struct.sk_buff*) local_unnamed_addr #0 !dbg !15
|
|
%3 = bitcast i32* %2 to i8*, !dbg !34
|
|
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #4, !dbg !34
|
|
%4 = tail call [10 x %struct.net_device]* @llvm.preserve.struct.access.index.p0a10s_struct.net_devices.p0s_struct.sk_buffs(%struct.sk_buff* %0, i32 1, i32 1), !dbg !35, !llvm.preserve.access.index !19
|
|
- %5 = tail call %struct.net_device* @llvm.preserve.array.access.index.p0s_struct.net_devices.p0a10s_struct.net_devices([10 x %struct.net_device]* %4, i32 1, i32 5), !dbg !35
|
|
+ %5 = tail call %struct.net_device* @llvm.preserve.array.access.index.p0s_struct.net_devices.p0a10s_struct.net_devices([10 x %struct.net_device]* %4, i32 1, i32 5), !dbg !35, !llvm.preserve.access.index !23
|
|
%6 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.net_devices(%struct.net_device* %5, i32 0, i32 0), !dbg !35, !llvm.preserve.access.index !24
|
|
%7 = bitcast i32* %6 to i8*, !dbg !35
|
|
%8 = call i32 inttoptr (i64 4 to i32 (i8*, i32, i8*)*)(i8* nonnull %3, i32 4, i8* %7) #4, !dbg !36
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-array.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-array.ll
|
|
index 7843c52..d63bc07 100644
|
|
--- a/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-array.ll
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-array.ll
|
|
@@ -21,7 +21,7 @@ define dso_local i32 @test(%struct.__s* %arg) local_unnamed_addr #0 !dbg !7 {
|
|
entry:
|
|
call void @llvm.dbg.value(metadata %struct.__s* %arg, metadata !24, metadata !DIExpression()), !dbg !25
|
|
%0 = tail call [7 x i32]* @llvm.preserve.struct.access.index.p0a7i32.p0s_struct.__ss(%struct.__s* %arg, i32 0, i32 0), !dbg !26, !llvm.preserve.access.index !13
|
|
- %1 = tail call i32* @llvm.preserve.array.access.index.p0i32.p0a7i32([7 x i32]* %0, i32 1, i32 1), !dbg !26
|
|
+ %1 = tail call i32* @llvm.preserve.array.access.index.p0i32.p0a7i32([7 x i32]* %0, i32 1, i32 1), !dbg !26, !llvm.preserve.access.index !19
|
|
%2 = bitcast i32* %1 to i8*, !dbg !26
|
|
%call = tail call i32 @get_value(i8* %2) #4, !dbg !27
|
|
ret i32 %call, !dbg !28
|
|
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll
|
|
index c09d979..8281694 100644
|
|
--- a/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll
|
|
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll
|
|
@@ -24,7 +24,7 @@
|
|
define dso_local i32 @test([7 x %union.u]* %arg) local_unnamed_addr #0 !dbg !7 {
|
|
entry:
|
|
call void @llvm.dbg.value(metadata [7 x %union.u]* %arg, metadata !28, metadata !DIExpression()), !dbg !29
|
|
- %0 = tail call [7 x %union.u]* @llvm.preserve.array.access.index.p0a7s_union.us.p0a7s_union.us([7 x %union.u]* %arg, i32 0, i32 1), !dbg !30
|
|
+ %0 = tail call [7 x %union.u]* @llvm.preserve.array.access.index.p0a7s_union.us.p0a7s_union.us([7 x %union.u]* %arg, i32 0, i32 1), !dbg !30, !llvm.preserve.access.index !14
|
|
%arraydecay = getelementptr inbounds [7 x %union.u], [7 x %union.u]* %0, i64 0, i64 0, !dbg !30
|
|
%1 = tail call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %arraydecay, i32 1), !dbg !30, !llvm.preserve.access.index !16
|
|
%d = getelementptr inbounds %union.u, %union.u* %1, i64 0, i32 0, !dbg !30
|
|
--
|
|
1.8.3.1
|
|
|