The package rpms/llvm.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/llvm.git/commit/?id=8ddd41e8d9076...
https://src.fedoraproject.org/cgit/rpms/llvm.git/commit/?id=acf22be74c375....
Change:
-%ifnarch s390 s390x
+%ifarch s390 %{arm} %ix86
Thanks.
Full change:
============
commit 00a5db5f3a8841eae6489e40313a222d69dd1203
Author: Tom Stellard <tstellar(a)redhat.com>
Date: Tue Jan 21 21:34:25 2020 +0000
Rebuild after previous build failed to strip binaries
diff --git a/llvm.spec b/llvm.spec
index aaac536..4c2d016 100644
--- a/llvm.spec
+++ b/llvm.spec
@@ -14,7 +14,7 @@
%global min_ver 0
%global patch_ver 1
#%%global rc_ver 3
-%global baserelease 3
+%global baserelease 4
%if %{with compat_build}
@@ -485,6 +485,9 @@ fi
%endif
%changelog
+* Tue Jan 21 2020 Tom Stellard <tstellar(a)redhat.com> - 9.0.1-4
+- Rebuild after previous build failed to strip binaries
+
* Fri Jan 17 2020 Tom Stellard <tstellar(a)redhat.com> - 9.0.1-3
- Add explicit Requires from sub-packages to llvm-libs
commit f61fd6e5576ed6ff7904fa695905e580ece2e3e5
Author: Tom Stellard <tstellar(a)redhat.com>
Date: Tue Jan 21 14:22:18 2020 +0000
tests.yml: Add a test to check size of libLLVM.so
There is a bug in the build system that can cause binary stripping
to fail without failing the build, so add a check to ensure that
libLLVM.so is stripped.
https://bugzilla.redhat.com/show_bug.cgi?id=1793250
diff --git a/tests/tests.yml b/tests/tests.yml
index f620568..e17357f 100644
--- a/tests/tests.yml
+++ b/tests/tests.yml
@@ -14,6 +14,15 @@
- rust-sanity:
dir: ./
run: cargo new hello && cd hello && cargo run
+ # There is a bug in the build process when it runs out of disk space
+ # while stripping binaries, which causes the strip to fail, but does
+ # not fail the build. This results in a libLLVM.so that is over 2GB
+ # which breaks the nightly compose. So this test checks that libLLVM.so
+ # is less than 100MB to ensure it was successfully stripped.
+ #
https://bugzilla.redhat.com/show_bug.cgi?id=1793250
+ - libllvm-size:
+ dir: ./
+ run: test `stat -L -c %s /usr/lib64/libLLVM.so` -lt 100000000
# This test ensures that the spec file still builds correctly with
# %global compat_build 1
# FIXME: This fails, because the CI system has a hard-coded timeout of 4
commit 96d4e517c5297d66428983d5f5536f8d6c587d75
Author: Tom Stellard <tstellar(a)redhat.com>
Date: Fri Jan 17 20:06:47 2020 +0000
Add explicit Requires from sub-packages to llvm-libs
RPMDiff complains that these requires are missing.
diff --git a/llvm.spec b/llvm.spec
index 79da708..aaac536 100644
--- a/llvm.spec
+++ b/llvm.spec
@@ -14,7 +14,7 @@
%global min_ver 0
%global patch_ver 1
#%%global rc_ver 3
-%global baserelease 2
+%global baserelease 3
%if %{with compat_build}
@@ -97,6 +97,7 @@ tools as well as libraries with equivalent functionality.
%package devel
Summary: Libraries and header files for LLVM
Requires: %{name}%{?_isa} = %{version}-%{release}
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
# The installed LLVM cmake files will add -ledit to the linker flags for any
# app that requires the libLLVMLineEditor, so we need to make sure
# libedit-devel is available.
@@ -136,6 +137,7 @@ Static libraries for the LLVM compiler infrastructure.
%package test
Summary: LLVM regression tests
Requires: %{name}%{?_isa} = %{version}-%{release}
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
Requires: python3-lit
# The regression tests need gold.
Requires: binutils
@@ -483,6 +485,9 @@ fi
%endif
%changelog
+* Fri Jan 17 2020 Tom Stellard <tstellar(a)redhat.com> - 9.0.1-3
+- Add explicit Requires from sub-packages to llvm-libs
+
* Fri Jan 10 2020 Tom Stellard <tstellar(a)redhat.com> - 9.0.1-2
- Fix crash with kernel bpf self-tests
commit d7b5dc38f6f69f92653a87434b14a094c5a96bff
Author: Tom Stellard <tstellar(a)redhat.com>
Date: Fri Jan 10 01:24:14 2020 +0000
Fix crash with kernel bpf self-tests
diff --git a/0001-BPF-Handling-type-conversions-correctly-for-CO-RE.patch
b/0001-BPF-Handling-type-conversions-correctly-for-CO-RE.patch
new file mode 100644
index 0000000..bfde9bc
--- /dev/null
+++ b/0001-BPF-Handling-type-conversions-correctly-for-CO-RE.patch
@@ -0,0 +1,2510 @@
+From 20253836fbb1baf5c7cd6fb6558bd12dff682855 Mon Sep 17 00:00:00 2001
+From: Yonghong Song <yhs(a)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
+
diff --git a/0001-BPF-annotate-DIType-metadata-for-builtin-preseve_arr.patch
b/0001-BPF-annotate-DIType-metadata-for-builtin-preseve_arr.patch
new file mode 100644
index 0000000..60ba6d9
--- /dev/null
+++ b/0001-BPF-annotate-DIType-metadata-for-builtin-preseve_arr.patch
@@ -0,0 +1,138 @@
+From f2ccdd2700174c717dc55a0f4c3f5a91ae73ff42 Mon Sep 17 00:00:00 2001
+From: Yonghong Song <yhs(a)fb.com>
+Date: Fri, 2 Aug 2019 21:28:28 +0000
+Subject: [PATCH] [BPF] annotate DIType metadata for builtin
+ preseve_array_access_index()
+
+Previously, debuginfo types are annotated to
+IR builtin preserve_struct_access_index() and
+preserve_union_access_index(), but not
+preserve_array_access_index(). The debug info
+is useful to identify the root type name which
+later will be used for type comparison.
+
+For user access without explicit type conversions,
+the previous scheme works as we can ignore intermediate
+compiler generated type conversions (e.g., from union types to
+union members) and still generate correct access index string.
+
+The issue comes with user explicit type conversions, e.g.,
+converting an array to a structure like below:
+ struct t { int a; char b[40]; };
+ struct p { int c; int d; };
+ struct t *var = ...;
+ ... __builtin_preserve_access_index(&(((struct p *)&(var->b[0]))->d))
...
+Although BPF backend can derive the type of &(var->b[0]),
+explicit type annotation make checking more consistent
+and less error prone.
+
+Another benefit is for multiple dimension array handling.
+For example,
+ struct p { int c; int d; } g[8][9][10];
+ ... __builtin_preserve_access_index(&g[2][3][4].d) ...
+It would be possible to calculate the number of "struct p"'s
+before accessing its member "d" if array debug info is
+available as it contains each dimension range.
+
+This patch enables to annotate IR builtin preserve_array_access_index()
+with proper debuginfo type. The unit test case and language reference
+is updated as well.
+
+Signed-off-by: Yonghong Song <yhs(a)fb.com>
+
+Differential Revision:
https://reviews.llvm.org/D65664
+
+llvm-svn: 367724
+(cherry picked from commit d0ea05d5eff475a27a5d3bbe4d9fd389935f9cb2)
+
+Also added back
+Value *CreatePreserveArrayAccessIndex(Value *Base, unsigned Dimension,
+ unsigned LastIndex);
+
+To avoid breaking the ABI.
+---
+ clang/lib/CodeGen/CGExpr.cpp | 12 ++++++++---
+ .../CodeGen/builtin-preserve-access-index-array.c | 18 +++++++++++++++++
+ clang/test/CodeGen/builtin-preserve-access-index.c | 23 +++++++++++-----------
+ llvm/docs/LangRef.rst | 4 ++++
+ llvm/include/llvm/IR/IRBuilder.h | 13 ++++++++++--
+ llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll | 2 +-
+ 6 files changed, 55 insertions(+), 17 deletions(-)
+ create mode 100644 clang/test/CodeGen/builtin-preserve-access-index-array.c
+
+diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
+index 87e8a55..b63e3af 100644
+--- a/llvm/docs/LangRef.rst
++++ b/llvm/docs/LangRef.rst
+@@ -17349,6 +17349,10 @@ based on array base ``base``, array dimension ``dim`` and the
last access index
+ into the array. The return type ``ret_type`` is a pointer type to the array element.
+ The array ``dim`` and ``index`` are preserved which is more robust than
+ getelementptr instruction which may be subject to compiler transformation.
++The ``llvm.preserve.access.index`` type of metadata is attached to this call
instruction
++to provide array or pointer debuginfo type.
++The metadata is a ``DICompositeType`` or ``DIDerivedType`` representing the
++debuginfo version of ``type``.
+
+ Arguments:
+ """"""""""
+diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
+index a74364d..c2fa9a3 100644
+--- a/llvm/include/llvm/IR/IRBuilder.h
++++ b/llvm/include/llvm/IR/IRBuilder.h
+@@ -2455,6 +2455,11 @@ public:
+
+ Value *CreatePreserveArrayAccessIndex(Value *Base, unsigned Dimension,
+ unsigned LastIndex) {
++ return CreatePreserveArrayAccessIndex(Base, Dimension, LastIndex, nullptr);
++ }
++
++ Value *CreatePreserveArrayAccessIndex(Value *Base, unsigned Dimension,
++ unsigned LastIndex, MDNode *DbgInfo) {
+ assert(isa<PointerType>(Base->getType()) &&
+ "Invalid Base ptr type for preserve.array.access.index.");
+ auto *BaseType = Base->getType();
+@@ -2476,6 +2481,8 @@ public:
+ Value *DimV = getInt32(Dimension);
+ CallInst *Fn =
+ CreateCall(FnPreserveArrayAccessIndex, {Base, DimV, LastIndexV});
++ if (DbgInfo)
++ Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
+
+ return Fn;
+ }
+@@ -2493,7 +2500,8 @@ public:
+ Value *DIIndex = getInt32(FieldIndex);
+ CallInst *Fn =
+ CreateCall(FnPreserveUnionAccessIndex, {Base, DIIndex});
+- Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
++ if (DbgInfo)
++ Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
+
+ return Fn;
+ }
+@@ -2516,7 +2524,8 @@ public:
+ Value *DIIndex = getInt32(FieldIndex);
+ CallInst *Fn = CreateCall(FnPreserveStructAccessIndex,
+ {Base, GEPIndex, DIIndex});
+- Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
++ if (DbgInfo)
++ Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
+
+ return Fn;
+ }
+diff --git a/llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll
b/llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll
+index adbcb9f..fe2c196 100644
+--- a/llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll
++++ b/llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll
+@@ -14,7 +14,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 !17, metadata
!DIExpression()), !dbg !18
+- %0 = tail call %struct.s*
@llvm.preserve.array.access.index.p0s_struct.ss.p0s_struct.ss(%struct.s* %arg, i32 0, i32
2), !dbg !19
++ %0 = tail call %struct.s*
@llvm.preserve.array.access.index.p0s_struct.ss.p0s_struct.ss(%struct.s* %arg, i32 0, i32
2), !dbg !19, !llvm.preserve.access.index !11
+ %1 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ss(%struct.s*
%0, i32 1, i32 1), !dbg !19, !llvm.preserve.access.index !12
+ %2 = bitcast i32* %1 to i8*, !dbg !19
+ %call = tail call i32 @get_value(i8* %2) #4, !dbg !20
+--
+1.8.3.1
+
diff --git a/llvm.spec b/llvm.spec
index ef5fc55..79da708 100644
--- a/llvm.spec
+++ b/llvm.spec
@@ -14,7 +14,7 @@
%global min_ver 0
%global patch_ver 1
#%%global rc_ver 3
-%global baserelease 1
+%global baserelease 2
%if %{with compat_build}
@@ -58,6 +58,10 @@
Patch2: 0001-CMake-Split-static-library-exports-into-their-own-ex.patch
Patch3: 0001-CMake-Split-test-binary-exports-into-their-own-expor.patch
Patch4: 0001-AVR-Fix-endianness-handling-in-AVR-MC.patch
+# Fix crash in kernel bpf self-tests
+Patch5: 0001-BPF-Handling-type-conversions-correctly-for-CO-RE.patch
+Patch6: 0001-BPF-annotate-DIType-metadata-for-builtin-preseve_arr.patch
+
BuildRequires: gcc
BuildRequires: gcc-c++
BuildRequires: cmake
@@ -479,6 +483,9 @@ fi
%endif
%changelog
+* Fri Jan 10 2020 Tom Stellard <tstellar(a)redhat.com> - 9.0.1-2
+- Fix crash with kernel bpf self-tests
+
* Thu Dec 19 2019 tstellar(a)redhat.com - 9.0.1-1
- 9.0.1 Release
commit d9ea1b48ed4f665409bb056a63a818c980cbab5e
Author: Tom Stellard <tstellar(a)redhat.com>
Date: Fri Dec 20 02:34:08 2019 +0000
9.0.1 Release
diff --git a/.gitignore b/.gitignore
index 59ee3e1..790740d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,3 +53,4 @@
/llvm-9.0.0rc2.src.tar.xz
/llvm-9.0.0rc3.src.tar.xz
/llvm-9.0.0.src.tar.xz
+/llvm-9.0.1.src.tar.xz
diff --git a/llvm.spec b/llvm.spec
index 39c876c..ef5fc55 100644
--- a/llvm.spec
+++ b/llvm.spec
@@ -12,9 +12,9 @@
%global build_llvm_libdir %{buildroot}%{llvm_libdir}
%global maj_ver 9
%global min_ver 0
-%global patch_ver 0
+%global patch_ver 1
#%%global rc_ver 3
-%global baserelease 4
+%global baserelease 1
%if %{with compat_build}
@@ -479,6 +479,9 @@ fi
%endif
%changelog
+* Thu Dec 19 2019 tstellar(a)redhat.com - 9.0.1-1
+- 9.0.1 Release
+
* Mon Nov 25 2019 sguelton(a)redhat.com - 9.0.0-4
- Activate AVR on all architectures
diff --git a/sources b/sources
index 6a0f67b..569b8de 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-SHA512 (llvm-9.0.0.src.tar.xz) =
1bb3341e1d231559b948f1505b33c2e2e03989f9b8bbfef0e0cdaff5ac43f85574c9ec5ac53399b914f497d6899425d861411024e8d7e1d1a338c1c6951ac658
+SHA512 (llvm-9.0.1.src.tar.xz) =
bfb6960a4dd1e18f4005f324f478a781c69e8ec7c20569d9b243fcb9372dc7733b254f26c683373537990cc9c109c78eaf0f65449629ee17caca1bce9b9ccccd
commit 8ddd41e8d9076ff1913792b40b5f769c2a208f6a
Author: serge-sans-paille <sguelton(a)redhat.com>
Date: Tue Nov 26 06:02:40 2019 +0000
Activate AVR on all architectures
diff --git a/0001-AVR-Fix-endianness-handling-in-AVR-MC.patch
b/0001-AVR-Fix-endianness-handling-in-AVR-MC.patch
new file mode 100644
index 0000000..aba1d2a
--- /dev/null
+++ b/0001-AVR-Fix-endianness-handling-in-AVR-MC.patch
@@ -0,0 +1,42 @@
+From 29b4d8f19e30910c099c5453da258843d6b7869a Mon Sep 17 00:00:00 2001
+From: serge_sans_paille <sguelton(a)redhat.com>
+Date: Tue, 24 Sep 2019 10:20:08 +0200
+Subject: [PATCH] [AVR] Fix endianness handling in AVR MC
+
+Differential Revision:
https://reviews.llvm.org/D67926
+---
+ llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp
b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp
+index bc048877868..db995e24756 100644
+--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp
++++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp
+@@ -25,6 +25,7 @@
+ #include "llvm/MC/MCRegisterInfo.h"
+ #include "llvm/MC/MCSubtargetInfo.h"
+ #include "llvm/Support/Casting.h"
++#include "llvm/Support/EndianStream.h"
+ #include "llvm/Support/raw_ostream.h"
+
+ #define DEBUG_TYPE "mccodeemitter"
+@@ -268,14 +269,11 @@ unsigned AVRMCCodeEmitter::getMachineOpValue(const MCInst &MI,
+ void AVRMCCodeEmitter::emitInstruction(uint64_t Val, unsigned Size,
+ const MCSubtargetInfo &STI,
+ raw_ostream &OS) const {
+- const uint16_t *Words = reinterpret_cast<uint16_t const *>(&Val);
+ size_t WordCount = Size / 2;
+
+ for (int64_t i = WordCount - 1; i >= 0; --i) {
+- uint16_t Word = Words[i];
+-
+- OS << (uint8_t) ((Word & 0x00ff) >> 0);
+- OS << (uint8_t) ((Word & 0xff00) >> 8);
++ uint16_t Word = (Val >> (i * 16)) & 0xFFFF;
++ support::endian::write(OS, Word, support::endianness::little);
+ }
+ }
+
+--
+2.20.1
+
diff --git a/llvm.spec b/llvm.spec
index 1f544f4..39c876c 100644
--- a/llvm.spec
+++ b/llvm.spec
@@ -14,7 +14,7 @@
%global min_ver 0
%global patch_ver 0
#%%global rc_ver 3
-%global baserelease 3
+%global baserelease 4
%if %{with compat_build}
@@ -56,6 +56,7 @@ Patch0: 0001-Filter-out-cxxflags-not-supported-by-clang.patch
Patch1: 0001-Pass-target-to-gold-linker-to-avoid-faliures-on-i686.patch
Patch2: 0001-CMake-Split-static-library-exports-into-their-own-ex.patch
Patch3: 0001-CMake-Split-test-binary-exports-into-their-own-expor.patch
+Patch4: 0001-AVR-Fix-endianness-handling-in-AVR-MC.patch
BuildRequires: gcc
BuildRequires: gcc-c++
@@ -200,9 +201,7 @@ cd _build
%if %{with gold}
-DLLVM_BINUTILS_INCDIR=%{_includedir} \
%endif
-%ifnarch s390 s390x
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AVR \
-%endif
\
-DLLVM_BUILD_RUNTIME:BOOL=ON \
\
@@ -480,6 +479,9 @@ fi
%endif
%changelog
+* Mon Nov 25 2019 sguelton(a)redhat.com - 9.0.0-4
+- Activate AVR on all architectures
+
* Mon Sep 30 2019 Tom Stellard <tstellar(a)redhat.com> - 9.0.0-3
- Build libLLVM.so first to avoid OOM errors
commit acf22be74c3755c2148a1a15743b912b16642154
Author: Tom Stellard <tstellar(a)redhat.com>
Date: Mon Sep 30 20:49:55 2019 +0000
Build libLLVM.so first to avoid OOM errors
Linking libLLVM.so takes a lot of memory and often causes OOM errors
on builders with low memory:cpu ratios.. By building libLLVM.so first,
we can ensure that when libLLVM.so is being linked, there are no other
build threads running which reduces the chances of an OOM error.
diff --git a/llvm.spec b/llvm.spec
index 1cee55c..1f544f4 100644
--- a/llvm.spec
+++ b/llvm.spec
@@ -14,7 +14,7 @@
%global min_ver 0
%global patch_ver 0
#%%global rc_ver 3
-%global baserelease 2
+%global baserelease 3
%if %{with compat_build}
@@ -164,7 +164,7 @@ pathfix.py -i %{__python3} -pn \
mkdir -p _build
cd _build
-%ifarch s390 s390x %{arm} %ix86
+%ifarch s390 %{arm} %ix86
# Decrease debuginfo verbosity to reduce memory consumption during final library linking
%global optflags %(echo %{optflags} | sed 's/-g /-g1 /')
%endif
@@ -180,7 +180,7 @@ cd _build
-DLLVM_PARALLEL_LINK_JOBS=1 \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_INSTALL_RPATH=";" \
-%ifarch s390 s390x %{arm} %ix86
+%ifarch s390 %{arm} %ix86
-DCMAKE_C_FLAGS_RELWITHDEBINFO="%{optflags} -DNDEBUG" \
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO="%{optflags} -DNDEBUG" \
%endif
@@ -239,6 +239,10 @@ cd _build
-DLLVM_INSTALL_SPHINX_HTML_DIR=%{_pkgdocdir}/html \
-DSPHINX_EXECUTABLE=%{_bindir}/sphinx-build-3
+# Build libLLVM.so first. This ensures that when libLLVM.so is linking, there
+# are no other compile jobs running. This will help reduce OOM errors on the
+# builders without having to artificially limit the number of concurrent jobs.
+%ninja_build LLVM
%ninja_build
%install
@@ -476,6 +480,9 @@ fi
%endif
%changelog
+* Mon Sep 30 2019 Tom Stellard <tstellar(a)redhat.com> - 9.0.0-3
+- Build libLLVM.so first to avoid OOM errors
+
* Fri Sep 27 2019 Tom Stellard <tstellar(a)redhat.com> - 9.0.0-2
- Remove unneeded BuildRequires: libstdc++-static
commit 9d70f3b6d943c8025ce950f2eb9851cb0e84620d
Author: Tom Stellard <tstellar(a)redhat.com>
Date: Fri Sep 27 03:28:51 2019 +0000
Remove unneeded BuildRequires: libstdc++-static
diff --git a/llvm.spec b/llvm.spec
index 1a0874e..1cee55c 100644
--- a/llvm.spec
+++ b/llvm.spec
@@ -14,7 +14,7 @@
%global min_ver 0
%global patch_ver 0
#%%global rc_ver 3
-%global baserelease 1
+%global baserelease 2
%if %{with compat_build}
@@ -70,7 +70,6 @@ BuildRequires: multilib-rpm-config
%if %{with gold}
BuildRequires: binutils-devel
%endif
-BuildRequires: libstdc++-static
%ifarch %{valgrind_arches}
# Enable extra functionality when run the LLVM JIT under valgrind.
BuildRequires: valgrind-devel
@@ -477,6 +476,9 @@ fi
%endif
%changelog
+* Fri Sep 27 2019 Tom Stellard <tstellar(a)redhat.com> - 9.0.0-2
+- Remove unneeded BuildRequires: libstdc++-static
+
* Thu Sep 19 2019 sguelton(a)redhat.com - 9.0.0-1
- 9.0.0 Release
commit a49a48122948ed0f237d5bd929ac055d23229a9a
Author: Tom Stellard <tstellar(a)redhat.com>
Date: Tue Sep 24 22:50:13 2019 +0000
Pull llvm-devel-cmake tests from tests/llvm
diff --git a/tests/llvm-devel-cmake/CMakeLists.txt
b/tests/llvm-devel-cmake/CMakeLists.txt
deleted file mode 100644
index e08cd3a..0000000
--- a/tests/llvm-devel-cmake/CMakeLists.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-cmake_minimum_required(VERSION 3.4.3)
-
-find_package(LLVM)
diff --git a/tests/llvm-devel-cmake/runtest.sh b/tests/llvm-devel-cmake/runtest.sh
deleted file mode 100755
index 42d42d3..0000000
--- a/tests/llvm-devel-cmake/runtest.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-set -ex
-
-# This test is meant to ensure that the cmake files in llvm-devel work
-# when only the packages it depends on are installed.
-
-ARCH=`rpm --eval '%_arch'`
-
-llvm_devel_num_deps=`dnf repoquery --nvr --requires --resolve llvm-devel.$ARCH | grep
'^llvm' | wc -l`
-
-llvm_num_sub_packages_installed=`dnf list installed | grep '^llvm' | wc -l`
-
-# Verify that only llvm-devel dependencies are installed.
-test `expr $llvm_devel_num_deps + 1` -eq $llvm_num_sub_packages_installed
-
-# Verify that cmake files can me used without errors.
-cmake -G Ninja .
diff --git a/tests/testsllvm-devel.yml b/tests/testsllvm-devel.yml
index 3109a8e..bb2bd1c 100644
--- a/tests/testsllvm-devel.yml
+++ b/tests/testsllvm-devel.yml
@@ -24,5 +24,8 @@
- ninja-build
- gcc
- gcc-c++
+ repositories:
+ - repo: "https://src.fedoraproject.org/tests/llvm.git"
+ dest: "llvm"
tests:
- - llvm-devel-cmake
+ - llvm/llvm-devel-cmake