The package rpms/llvm9.0.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/llvm9.0.git/commit/?id=12437586df95e....
Change: +%ifarch %{arm}
Thanks.
Full change: ============
commit 12437586df95e93633b3d3037def8f53367748f3 Author: serge-sans-paille sguelton@redhat.com Date: Thu Feb 6 05:50:01 2020 +0000
Initial push
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@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/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@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::vectorstd::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@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@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/0001-CMake-Split-static-library-exports-into-their-own-ex.patch b/0001-CMake-Split-static-library-exports-into-their-own-ex.patch new file mode 100644 index 0000000..e780c34 --- /dev/null +++ b/0001-CMake-Split-static-library-exports-into-their-own-ex.patch @@ -0,0 +1,66 @@ +From 8f6917ea11bd1bfbfe07f3577756d1c4abfdb916 Mon Sep 17 00:00:00 2001 +From: Tom Stellard tstellar@redhat.com +Date: Fri, 6 Sep 2019 11:03:18 -0700 +Subject: [PATCH] CMake: Split static library exports into their own export + file + +--- + llvm/cmake/modules/AddLLVM.cmake | 6 +++++- + llvm/cmake/modules/CMakeLists.txt | 3 +++ + llvm/cmake/modules/LLVMConfig.cmake.in | 2 ++ + 3 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake +index 619e986..200fc45 100644 +--- a/llvm/cmake/modules/AddLLVM.cmake ++++ b/llvm/cmake/modules/AddLLVM.cmake +@@ -691,7 +691,11 @@ macro(add_llvm_library name) + if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR + (in_llvm_libs AND "llvm-libraries" IN_LIST LLVM_DISTRIBUTION_COMPONENTS) OR + NOT LLVM_DISTRIBUTION_COMPONENTS) +- set(export_to_llvmexports EXPORT LLVMExports) ++ if (ARG_SHARED) ++ set(export_to_llvmexports EXPORT LLVMExports) ++ else() ++ set(export_to_llvmexports EXPORT LLVMStaticExports) ++ endif() + set_property(GLOBAL PROPERTY LLVM_HAS_EXPORTS True) + endif() + +diff --git a/llvm/cmake/modules/CMakeLists.txt b/llvm/cmake/modules/CMakeLists.txt +index 9cf22b4..dc982d2 100644 +--- a/llvm/cmake/modules/CMakeLists.txt ++++ b/llvm/cmake/modules/CMakeLists.txt +@@ -105,6 +105,7 @@ set(LLVM_CONFIG_BINARY_DIR "${LLVM_INSTALL_PREFIX}") + set(LLVM_CONFIG_TOOLS_BINARY_DIR "${LLVM_INSTALL_PREFIX}/bin") + set(LLVM_CONFIG_EXPORTS_FILE "${LLVM_CMAKE_DIR}/LLVMExports.cmake") + set(LLVM_CONFIG_EXPORTS "${LLVM_EXPORTS}") ++set(LLVM_CONFIG_STATIC_EXPORTS_FILE "${LLVM_CMAKE_DIR}/LLVMStaticExports.cmake") + configure_file( + LLVMConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/LLVMConfig.cmake +@@ -121,6 +122,8 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + if(llvm_has_exports) + install(EXPORT LLVMExports DESTINATION ${LLVM_INSTALL_PACKAGE_DIR} + COMPONENT cmake-exports) ++ install(EXPORT LLVMStaticExports DESTINATION ${LLVM_INSTALL_PACKAGE_DIR} ++ COMPONENT cmake-exports) + endif() + + install(FILES +diff --git a/llvm/cmake/modules/LLVMConfig.cmake.in b/llvm/cmake/modules/LLVMConfig.cmake.in +index 536031f..6ef54a0 100644 +--- a/llvm/cmake/modules/LLVMConfig.cmake.in ++++ b/llvm/cmake/modules/LLVMConfig.cmake.in +@@ -89,6 +89,8 @@ if(NOT TARGET LLVMSupport) + set(LLVM_EXPORTED_TARGETS "@LLVM_CONFIG_EXPORTS@") + include("@LLVM_CONFIG_EXPORTS_FILE@") + @llvm_config_include_buildtree_only_exports@ ++ ++ include("@LLVM_CONFIG_STATIC_EXPORTS_FILE@" OPTIONAL) + endif() + + # By creating intrinsics_gen here, subprojects that depend on LLVM's +-- +1.8.3.1 + diff --git a/0001-CMake-Split-test-binary-exports-into-their-own-expor.patch b/0001-CMake-Split-test-binary-exports-into-their-own-expor.patch new file mode 100644 index 0000000..a3801ff --- /dev/null +++ b/0001-CMake-Split-test-binary-exports-into-their-own-expor.patch @@ -0,0 +1,65 @@ +From 9d496e978f59e153bb76e92229d5a524d92dee04 Mon Sep 17 00:00:00 2001 +From: Tom Stellard tstellar@redhat.com +Date: Tue, 10 Sep 2019 13:33:48 -0700 +Subject: [PATCH] CMake: Split test binary exports into their own export file + +--- + llvm/cmake/modules/AddLLVM.cmake | 7 ++++++- + llvm/cmake/modules/CMakeLists.txt | 3 +++ + llvm/cmake/modules/LLVMConfig.cmake.in | 1 + + 3 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake +index 200fc45..9eec7a7 100644 +--- a/llvm/cmake/modules/AddLLVM.cmake ++++ b/llvm/cmake/modules/AddLLVM.cmake +@@ -953,7 +953,12 @@ macro(add_llvm_utility name) + set(export_to_llvmexports) + if (${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR + NOT LLVM_DISTRIBUTION_COMPONENTS) +- set(export_to_llvmexports EXPORT LLVMExports) ++ if (${name} STREQUAL "not" OR ${name} STREQUAL "count" OR ++ ${name} STREQUAL "yaml-bench" OR ${name} STREQUAL "lli-child-target") ++ set(export_to_llvmexports EXPORT LLVMTestExports) ++ else() ++ set(export_to_llvmexports EXPORT LLVMExports) ++ endif() + set_property(GLOBAL PROPERTY LLVM_HAS_EXPORTS True) + endif() + +diff --git a/llvm/cmake/modules/CMakeLists.txt b/llvm/cmake/modules/CMakeLists.txt +index dc982d2..c861f45 100644 +--- a/llvm/cmake/modules/CMakeLists.txt ++++ b/llvm/cmake/modules/CMakeLists.txt +@@ -106,6 +106,7 @@ set(LLVM_CONFIG_TOOLS_BINARY_DIR "${LLVM_INSTALL_PREFIX}/bin") + set(LLVM_CONFIG_EXPORTS_FILE "${LLVM_CMAKE_DIR}/LLVMExports.cmake") + set(LLVM_CONFIG_EXPORTS "${LLVM_EXPORTS}") + set(LLVM_CONFIG_STATIC_EXPORTS_FILE "${LLVM_CMAKE_DIR}/LLVMStaticExports.cmake") ++set(LLVM_CONFIG_TEST_EXPORTS_FILE "${LLVM_CMAKE_DIR}/LLVMTestExports.cmake") + configure_file( + LLVMConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/LLVMConfig.cmake +@@ -124,6 +125,8 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + COMPONENT cmake-exports) + install(EXPORT LLVMStaticExports DESTINATION ${LLVM_INSTALL_PACKAGE_DIR} + COMPONENT cmake-exports) ++ install(EXPORT LLVMTestExports DESTINATION ${LLVM_INSTALL_PACKAGE_DIR} ++ COMPONENT cmake-exports) + endif() + + install(FILES +diff --git a/llvm/cmake/modules/LLVMConfig.cmake.in b/llvm/cmake/modules/LLVMConfig.cmake.in +index 6ef54a0..d81b09a 100644 +--- a/llvm/cmake/modules/LLVMConfig.cmake.in ++++ b/llvm/cmake/modules/LLVMConfig.cmake.in +@@ -91,6 +91,7 @@ if(NOT TARGET LLVMSupport) + @llvm_config_include_buildtree_only_exports@ + + include("@LLVM_CONFIG_STATIC_EXPORTS_FILE@" OPTIONAL) ++ include("@LLVM_CONFIG_TEST_EXPORTS_FILE@" OPTIONAL) + endif() + + # By creating intrinsics_gen here, subprojects that depend on LLVM's +-- +1.8.3.1 + diff --git a/0001-Filter-out-cxxflags-not-supported-by-clang.patch b/0001-Filter-out-cxxflags-not-supported-by-clang.patch new file mode 100644 index 0000000..1351d2f --- /dev/null +++ b/0001-Filter-out-cxxflags-not-supported-by-clang.patch @@ -0,0 +1,28 @@ +From d15c835028bcc72a8695d047f0acaa530aa54716 Mon Sep 17 00:00:00 2001 +From: Tom Stellard tstellar@redhat.com +Date: Wed, 31 Jul 2019 20:43:42 -0700 +Subject: [PATCH] Filter out cxxflags not supported by clang + +--- + llvm/tools/llvm-config/CMakeLists.txt | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/llvm/tools/llvm-config/CMakeLists.txt b/llvm/tools/llvm-config/CMakeLists.txt +index 8e97a10..9b9b7d1 100644 +--- a/llvm/tools/llvm-config/CMakeLists.txt ++++ b/llvm/tools/llvm-config/CMakeLists.txt +@@ -43,7 +43,11 @@ set(LLVM_SRC_ROOT ${LLVM_MAIN_SRC_DIR}) + set(LLVM_OBJ_ROOT ${LLVM_BINARY_DIR}) + set(LLVM_CPPFLAGS "${LLVM_DEFINITIONS}") + set(LLVM_CFLAGS "${LLVM_C_STD_FLAG} ${LLVM_DEFINITIONS}") ++STRING(REGEX REPLACE "-mcet" "" LLVM_CFLAGS ${LLVM_CFLAGS}) ++STRING(REGEX REPLACE "-fcf-protection" "" LLVM_CFLAGS ${LLVM_CFLAGS}) + set(LLVM_CXXFLAGS "${LLVM_CXX_STD_FLAG} ${LLVM_CXX_STDLIB_FLAG} ${COMPILE_FLAGS} ${LLVM_DEFINITIONS}") ++STRING(REGEX REPLACE "-mcet" "" LLVM_CXXFLAGS ${LLVM_CXXFLAGS}) ++STRING(REGEX REPLACE "-fcf-protection" "" LLVM_CXXFLAGS ${LLVM_CXXFLAGS}) + set(LLVM_BUILD_SYSTEM cmake) + set(LLVM_HAS_RTTI ${LLVM_CONFIG_HAS_RTTI}) + set(LLVM_DYLIB_VERSION "${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX}") +-- +1.8.3.1 + diff --git a/0001-Pass-target-to-gold-linker-to-avoid-faliures-on-i686.patch b/0001-Pass-target-to-gold-linker-to-avoid-faliures-on-i686.patch new file mode 100644 index 0000000..e8dd323 --- /dev/null +++ b/0001-Pass-target-to-gold-linker-to-avoid-faliures-on-i686.patch @@ -0,0 +1,34 @@ +From f0762684457a883b6813b48c98a1e94e377bc06b Mon Sep 17 00:00:00 2001 +From: Tom Stellard tstellar@redhat.com +Date: Wed, 28 Aug 2019 19:31:21 -0700 +Subject: [PATCH] Pass target to gold linker to avoid faliures on i686 + +--- + llvm/test/tools/gold/X86/linkonce_odr_unnamed_addr.ll | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/llvm/test/tools/gold/X86/linkonce_odr_unnamed_addr.ll b/llvm/test/tools/gold/X86/linkonce_odr_unnamed_addr.ll +index 525bf2d..01291bd 100644 +--- a/llvm/test/tools/gold/X86/linkonce_odr_unnamed_addr.ll ++++ b/llvm/test/tools/gold/X86/linkonce_odr_unnamed_addr.ll +@@ -3,7 +3,7 @@ + + ; RUN: opt -module-summary %s -o %t.o + ; RUN: opt -module-summary %p/Inputs/linkonce_odr_unnamed_addr.ll -o %t2.o +-; RUN: %gold -plugin %llvmshlibdir/LLVMgold%shlibext \ ++; RUN: %gold -m elf_x86_64 -plugin %llvmshlibdir/LLVMgold%shlibext \ + ; RUN: --plugin-opt=save-temps \ + ; RUN: %t.o %t2.o -o %t3.o + ; RUN: llvm-dis %t.o.1.promote.bc -o - | FileCheck %s +@@ -11,7 +11,7 @@ + ; Now test when one module is a native object. In that case we must be + ; conservative and not auto hide. + ; RUN: llc %p/Inputs/linkonce_odr_unnamed_addr.ll -o %t2native.o -filetype=obj +-; RUN: %gold -plugin %llvmshlibdir/LLVMgold%shlibext \ ++; RUN: %gold -m elf_x86_64 -plugin %llvmshlibdir/LLVMgold%shlibext \ + ; RUN: --plugin-opt=save-temps \ + ; RUN: %t.o %t2native.o -o %t3.o + ; RUN: llvm-dis %t.o.1.promote.bc -o - | FileCheck %s --check-prefix=NOSUMMARY +-- +1.8.3.1 + diff --git a/gating.yaml b/gating.yaml new file mode 100644 index 0000000..219cd2c --- /dev/null +++ b/gating.yaml @@ -0,0 +1,12 @@ +--- !Policy +product_versions: + - fedora-* +decision_context: bodhi_update_push_testing +rules: + - !PassingTestCaseRule {test_case_name: org.centos.prod.ci.pipeline.allpackages-build.package.test.functional.complete} +--- !Policy +product_versions: + - fedora-* +decision_context: bodhi_update_push_stable +rules: + - !PassingTestCaseRule {test_case_name: org.centos.prod.ci.pipeline.allpackages-build.package.test.functional.complete} diff --git a/lit.fedora.cfg.py b/lit.fedora.cfg.py new file mode 100644 index 0000000..1c918b4 --- /dev/null +++ b/lit.fedora.cfg.py @@ -0,0 +1,17 @@ + +config.llvm_tools_dir = '/usr/bin' +config.llvm_shlib_dir = '%(llvm_shlib_dir)s' % lit_config.params + +if hasattr(config, 'host_triple'): + # This means we are running lit regression tests + + # Regression tests write output to this directory, so we need to be able to specify + # a temp directory when invoking lit. e.g. lit -Dllvm_obj_root=/tmp/lit + config.llvm_obj_root = "%(llvm_obj_root)s" % lit_config.params + lit_config.load_config(config, '%(llvm_test_root)s/lit.cfg.py' % lit_config.params) +else: + # This means we are running lit unit tests + + # For unit tests, llvm_obj_root is used to find the unit test binaries. + config.llvm_obj_root = '%(llvm_unittest_bindir)s' % lit_config.params + lit_config.load_config(config, '%(llvm_test_root)s/Unit/lit.cfg.py' % lit_config.params) diff --git a/llvm9.0.spec b/llvm9.0.spec new file mode 100644 index 0000000..7ec6390 --- /dev/null +++ b/llvm9.0.spec @@ -0,0 +1,884 @@ +# Components enabled if supported by target architecture: +%define gold_arches %{ix86} x86_64 %{arm} aarch64 %{power64} s390x +%ifarch %{gold_arches} + %bcond_without gold +%else + %bcond_with gold +%endif + +%bcond_without compat_build + +%global llvm_libdir %{_libdir}/%{name} +%global build_llvm_libdir %{buildroot}%{llvm_libdir} +%global maj_ver 9 +%global min_ver 0 +%global patch_ver 1 +#%%global rc_ver 3 +%global baserelease 6 + + +%if %{with compat_build} +%global pkg_name llvm%{maj_ver}.%{min_ver} +%global exec_suffix -%{maj_ver}.%{min_ver} +%global install_prefix %{_libdir}/%{name} +%global install_bindir %{install_prefix}/bin +%global install_includedir %{install_prefix}/include +%global install_libdir %{install_prefix}/lib + +%global pkg_bindir %{install_bindir} +%global pkg_includedir %{_includedir}/%{name} +%global pkg_libdir %{install_libdir} +%else +%global pkg_name llvm +%global install_prefix /usr +%global install_libdir %{_libdir} +%global pkg_libdir %{install_libdir} +%endif + +%global build_install_prefix %{buildroot}%{install_prefix} + +Name: %{pkg_name} +Version: %{maj_ver}.%{min_ver}.%{patch_ver} +Release: %{baserelease}%{?rc_ver:.rc%{rc_ver}}%{?dist} +Summary: The Low Level Virtual Machine + +License: NCSA +URL: http://llvm.org +Source0: http://%%7B?rc_ver:pre%7Dreleases.llvm.org/%%7Bversion%7D/%%7B?rc_ver:rc%%7B... +%if %{without compat_build} +Source1: run-lit-tests +Source2: lit.fedora.cfg.py +%endif + +Patch0: 0001-Filter-out-cxxflags-not-supported-by-clang.patch +# TODO: I'm not sure why this is needed. Could be a change in newer version +# of gold. +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 +%if %{without compat_build} +Patch3: 0001-CMake-Split-test-binary-exports-into-their-own-expor.patch +%endif +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 +BuildRequires: ninja-build +BuildRequires: zlib-devel +BuildRequires: libffi-devel +BuildRequires: ncurses-devel +BuildRequires: python3-sphinx +BuildRequires: python3-recommonmark +BuildRequires: multilib-rpm-config +%if %{with gold} +BuildRequires: binutils-devel +%endif +%ifarch %{valgrind_arches} +# Enable extra functionality when run the LLVM JIT under valgrind. +BuildRequires: valgrind-devel +%endif +# LLVM's LineEditor library will use libedit if it is available. +BuildRequires: libedit-devel +# We need python3-devel for pathfix.py. +BuildRequires: python3-devel + +Requires: %{name}-libs%{?_isa} = %{version}-%{release} + +Provides: llvm(major) = %{maj_ver} + +%description +LLVM is a compiler infrastructure designed for compile-time, link-time, +runtime, and idle-time optimization of programs from arbitrary programming +languages. The compiler infrastructure includes mirror sets of programming +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. +Requires: libedit-devel +Requires(post): %{_sbindir}/alternatives +Requires(postun): %{_sbindir}/alternatives + +Provides: llvm-devel(major) = %{maj_ver} + +%description devel +This package contains library and header files needed to develop new native +programs that use the LLVM infrastructure. + +%package doc +Summary: Documentation for LLVM +BuildArch: noarch +Requires: %{name} = %{version}-%{release} + +%description doc +Documentation for the LLVM compiler infrastructure. + +%package libs +Summary: LLVM shared libraries + +%description libs +Shared libraries for the LLVM compiler infrastructure. + +%package static +Summary: LLVM static libraries +Conflicts: %{name}-devel < 8 + +%description static +Static libraries for the LLVM compiler infrastructure. + +%if %{without compat_build} + +%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 +# This is for llvm-config +Requires: %{name}-devel%{?_isa} = %{version}-%{release} +# Bugpoint tests require gcc +Requires: gcc +Requires: findutils + +Provides: llvm-test(major) = %{maj_ver} + +%description test +LLVM regression tests. + +%package googletest +Summary: LLVM's modified googletest sources + +%description googletest +LLVM's modified googletest sources. + +%endif + +%prep +%autosetup -n llvm-%{version}%{?rc_ver:rc%{rc_ver}}.src -p2 + +pathfix.py -i %{__python3} -pn \ + test/BugPoint/compile-custom.ll.py \ + tools/opt-viewer/*.py + +%build +mkdir -p _build +cd _build + +%ifarch s390 %{arm} %ix86 +# Decrease debuginfo verbosity to reduce memory consumption during final library linking +%global optflags %(echo %{optflags} | sed 's/-g /-g1 /') +%endif + +# force off shared libs as cmake macros turns it on. +# +# -DCMAKE_INSTALL_RPATH=";" is a workaround for llvm manually setting the +# rpath of libraries and binaries. llvm will skip the manual setting +# if CAMKE_INSTALL_RPATH is set to a value, but cmake interprets this value +# as nothing, so it sets the rpath to "" when installing. +%cmake .. -G Ninja \ + -DBUILD_SHARED_LIBS:BOOL=OFF \ + -DLLVM_PARALLEL_LINK_JOBS=1 \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_INSTALL_RPATH=";" \ +%ifarch s390 %{arm} %ix86 + -DCMAKE_C_FLAGS_RELWITHDEBINFO="%{optflags} -DNDEBUG" \ + -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="%{optflags} -DNDEBUG" \ +%endif +%if %{without compat_build} +%if 0%{?__isa_bits} == 64 + -DLLVM_LIBDIR_SUFFIX=64 \ +%else + -DLLVM_LIBDIR_SUFFIX= \ +%endif +%endif + \ + -DLLVM_TARGETS_TO_BUILD=all \ + -DLLVM_ENABLE_LIBCXX:BOOL=OFF \ + -DLLVM_ENABLE_ZLIB:BOOL=ON \ + -DLLVM_ENABLE_FFI:BOOL=ON \ + -DLLVM_ENABLE_RTTI:BOOL=ON \ +%if %{with gold} + -DLLVM_BINUTILS_INCDIR=%{_includedir} \ +%endif + -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AVR \ + \ + -DLLVM_BUILD_RUNTIME:BOOL=ON \ + \ + -DLLVM_INCLUDE_TOOLS:BOOL=ON \ + -DLLVM_BUILD_TOOLS:BOOL=ON \ + \ + -DLLVM_INCLUDE_TESTS:BOOL=ON \ + -DLLVM_BUILD_TESTS:BOOL=ON \ + \ + -DLLVM_INCLUDE_EXAMPLES:BOOL=ON \ + -DLLVM_BUILD_EXAMPLES:BOOL=OFF \ + \ + -DLLVM_INCLUDE_UTILS:BOOL=ON \ +%if %{with compat_build} + -DLLVM_INSTALL_UTILS:BOOL=OFF \ +%else + -DLLVM_INSTALL_UTILS:BOOL=ON \ + -DLLVM_UTILS_INSTALL_DIR:PATH=%{_bindir} \ + -DLLVM_TOOLS_INSTALL_DIR:PATH=bin \ +%endif + \ + -DLLVM_INCLUDE_DOCS:BOOL=ON \ + -DLLVM_BUILD_DOCS:BOOL=ON \ + -DLLVM_ENABLE_SPHINX:BOOL=ON \ + -DLLVM_ENABLE_DOXYGEN:BOOL=OFF \ + \ + -DLLVM_BUILD_LLVM_DYLIB:BOOL=ON \ + -DLLVM_DYLIB_EXPORT_ALL:BOOL=ON \ + -DLLVM_LINK_LLVM_DYLIB:BOOL=ON \ + -DLLVM_BUILD_EXTERNAL_COMPILER_RT:BOOL=ON \ + -DLLVM_INSTALL_TOOLCHAIN_ONLY:BOOL=OFF \ + \ + -DSPHINX_WARNINGS_AS_ERRORS=OFF \ + -DCMAKE_INSTALL_PREFIX=%{install_prefix} \ + -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 +%ninja_install -C _build + + +%if %{without compat_build} +mkdir -p %{buildroot}/%{_bindir} +mv %{buildroot}/%{_bindir}/llvm-config %{buildroot}/%{_bindir}/llvm-config-%{__isa_bits} + +# Fix some man pages +ln -s llvm-config.1 %{buildroot}%{_mandir}/man1/llvm-config-%{__isa_bits}.1 +mv %{buildroot}%{_mandir}/man1/tblgen.1 %{buildroot}%{_mandir}/man1/llvm-tblgen.1 + +# Install binaries needed for lit tests +%global test_binaries llvm-isel-fuzzer llvm-opt-fuzzer + +for f in %{test_binaries} +do + install -m 0755 ./_build/bin/$f %{buildroot}%{_bindir} +done + + +%multilib_fix_c_header --file %{_includedir}/llvm/Config/llvm-config.h + +# Install libraries needed for unittests +%if 0%{?__isa_bits} == 64 +%global build_libdir _build/lib64 +%else +%global build_libdir _build/lib +%endif + +install %{build_libdir}/libLLVMTestingSupport.a %{buildroot}%{_libdir} + +%global install_srcdir %{buildroot}%{_datadir}/llvm/src +%global lit_cfg test/%{_arch}.site.cfg.py +%global lit_unit_cfg test/Unit/%{_arch}.site.cfg.py +%global lit_fedora_cfg %{_datadir}/llvm/lit.fedora.cfg.py + +# Install gtest sources so clang can use them for gtest +install -d %{install_srcdir} +install -d %{install_srcdir}/utils/ +cp -R utils/unittest %{install_srcdir}/utils/ + +# Generate lit config files. Strip off the last line that initiates the +# test run, so we can customize the configuration. +head -n -1 _build/test/lit.site.cfg.py >> %{lit_cfg} +head -n -1 _build/test/Unit/lit.site.cfg.py >> %{lit_unit_cfg} + +# Install custom fedora config file +cp %{SOURCE2} %{buildroot}%{lit_fedora_cfg} + +# Patch lit config files to load custom fedora config: +for f in %{lit_cfg} %{lit_unit_cfg}; do + echo "lit_config.load_config(config, '%{lit_fedora_cfg}')" >> $f +done + +install -d %{buildroot}%{_libexecdir}/tests/llvm +install -m 0755 %{SOURCE1} %{buildroot}%{_libexecdir}/tests/llvm + +# Install lit tests. We need to put these in a tarball otherwise rpm will complain +# about some of the test inputs having the wrong object file format. +install -d %{buildroot}%{_datadir}/llvm/ +tar -czf %{install_srcdir}/test.tar.gz test/ + +# Install the unit test binaries +mkdir -p %{build_llvm_libdir} +cp -R _build/unittests %{build_llvm_libdir}/ +rm -rf `find %{build_llvm_libdir} -iname 'cmake*'` + +# Install libraries used for testing +install -m 0755 %{build_libdir}/BugpointPasses.so %{buildroot}%{_libdir} +install -m 0755 %{build_libdir}/LLVMHello.so %{buildroot}%{_libdir} + +# Install test inputs for PDB tests +echo "%{_datadir}/llvm/src/unittests/DebugInfo/PDB" > %{build_llvm_libdir}/unittests/DebugInfo/PDB/llvm.srcdir.txt +mkdir -p %{buildroot}%{_datadir}/llvm/src/unittests/DebugInfo/PDB/ +cp -R unittests/DebugInfo/PDB/Inputs %{buildroot}%{_datadir}/llvm/src/unittests/DebugInfo/PDB/ + +%else + +# Add version suffix to binaries +mkdir -p %{buildroot}/%{_bindir} +for f in %{buildroot}/%{install_bindir}/*; do + filename=`basename $f` + ln -s ../../../%{install_bindir}/$filename %{buildroot}/%{_bindir}/$filename%{exec_suffix} +done + +# Move header files +mkdir -p %{buildroot}/%{pkg_includedir} +ln -s ../../../%{install_includedir}/llvm %{buildroot}/%{pkg_includedir}/llvm +ln -s ../../../%{install_includedir}/llvm-c %{buildroot}/%{pkg_includedir}/llvm-c + +# Fix multi-lib +mv %{buildroot}%{_bindir}/llvm-config{%{exec_suffix},%{exec_suffix}-%{__isa_bits}} +%multilib_fix_c_header --file %{install_includedir}/llvm/Config/llvm-config.h + +# Create ld.so.conf.d entry +mkdir -p %{buildroot}%{_sysconfdir}/ld.so.conf.d +cat >> %{buildroot}%{_sysconfdir}/ld.so.conf.d/%{name}-%{_arch}.conf << EOF +%{pkg_libdir} +EOF + +# Add version suffix to man pages and move them to mandir. +mkdir -p %{buildroot}/%{_mandir}/man1 +for f in %{build_install_prefix}/share/man/man1/*; do + filename=`basename $f | cut -f 1 -d '.'` + mv $f %{buildroot}%{_mandir}/man1/$filename%{exec_suffix}.1 +done + +# Remove opt-viewer, since this is just a compatibility package. +rm -Rf %{build_install_prefix}/share/opt-viewer + +%endif + + +%check +# TODO: Fix test failures on arm +ninja check-all -C _build || \ +%ifarch %{arm} + : +%else + false +%endif + +%ldconfig_scriptlets libs + +%if %{without compat_build} + +%post devel +%{_sbindir}/update-alternatives --install %{_bindir}/llvm-config llvm-config %{_bindir}/llvm-config-%{__isa_bits} %{__isa_bits} + +%postun devel +if [ $1 -eq 0 ]; then + %{_sbindir}/update-alternatives --remove llvm-config %{_bindir}/llvm-config +fi + +%endif + +%files +%exclude %{_mandir}/man1/llvm-config* +%{_mandir}/man1/* +%{_bindir}/* + +%if %{without compat_build} +%exclude %{_bindir}/llvm-config-%{__isa_bits} +%exclude %{_bindir}/not +%exclude %{_bindir}/count +%exclude %{_bindir}/yaml-bench +%exclude %{_bindir}/lli-child-target +%exclude %{_bindir}/llvm-isel-fuzzer +%exclude %{_bindir}/llvm-opt-fuzzer +%{_datadir}/opt-viewer +%else +%exclude %{pkg_bindir}/llvm-config +%{pkg_bindir} +%endif + +%files libs +%{pkg_libdir}/libLLVM-%{maj_ver}.so +%if %{without compat_build} +%if %{with gold} +%{_libdir}/LLVMgold.so +%endif +%{_libdir}/libLLVM-%{maj_ver}.%{min_ver}*.so +%{_libdir}/libLTO.so* +%else +%config(noreplace) %{_sysconfdir}/ld.so.conf.d/%{name}-%{_arch}.conf +%if %{with gold} +%{_libdir}/%{name}/lib/LLVMgold.so +%endif +%{pkg_libdir}/libLLVM-%{maj_ver}.%{min_ver}*.so +%{pkg_libdir}/libLTO.so* +%exclude %{pkg_libdir}/libLTO.so +%endif +%{pkg_libdir}/libRemarks.so* + +%files devel +%if %{without compat_build} +%{_bindir}/llvm-config-%{__isa_bits} +%{_mandir}/man1/llvm-config* +%{_includedir}/llvm +%{_includedir}/llvm-c +%{_libdir}/libLLVM.so +%{_libdir}/cmake/llvm +%exclude %{_libdir}/cmake/llvm/LLVMStaticExports.cmake +%exclude %{_libdir}/cmake/llvm/LLVMTestExports.cmake +%else +%{_bindir}/llvm-config%{exec_suffix}-%{__isa_bits} +%{pkg_bindir}/llvm-config +%{_mandir}/man1/llvm-config%{exec_suffix}.1.gz +%{install_includedir}/llvm +%{install_includedir}/llvm-c +%{pkg_includedir}/llvm +%{pkg_includedir}/llvm-c +%{pkg_libdir}/libLTO.so +%{pkg_libdir}/libLLVM.so +%{pkg_libdir}/cmake/llvm +%endif + +%files doc +%doc %{_pkgdocdir}/html + +%files static +%if %{without compat_build} +%{_libdir}/*.a +%exclude %{_libdir}/libLLVMTestingSupport.a +%{_libdir}/cmake/llvm/LLVMStaticExports.cmake +%else +%{_libdir}/%{name}/lib/*.a +%endif + +%if %{without compat_build} + +%files test +%{_libexecdir}/tests/llvm/ +%{llvm_libdir}/unittests/ +%{_datadir}/llvm/src/unittests +%{_datadir}/llvm/src/test.tar.gz +%{_datadir}/llvm/lit.fedora.cfg.py +%{_bindir}/not +%{_bindir}/count +%{_bindir}/yaml-bench +%{_bindir}/lli-child-target +%{_bindir}/llvm-isel-fuzzer +%{_bindir}/llvm-opt-fuzzer +%{_libdir}/BugpointPasses.so +%{_libdir}/LLVMHello.so +%{_libdir}/cmake/llvm/LLVMTestExports.cmake + +%files googletest +%{_datadir}/llvm/src/utils +%{_libdir}/libLLVMTestingSupport.a + +%endif + +%changelog +* Tue Feb 4 2020 sguelton@redhat.com - 9.0.1-6 +- Sync specfile with llvm9.0 package + +* Wed Jan 29 2020 Fedora Release Engineering releng@fedoraproject.org - 9.0.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Tue Jan 21 2020 Tom Stellard tstellar@redhat.com - 9.0.1-4 +- Rebuild after previous build failed to strip binaries + +* Fri Jan 17 2020 Tom Stellard tstellar@redhat.com - 9.0.1-3 +- Add explicit Requires from sub-packages to llvm-libs + +* Fri Jan 10 2020 Tom Stellard tstellar@redhat.com - 9.0.1-2 +- Fix crash with kernel bpf self-tests + +* Thu Dec 19 2019 tstellar@redhat.com - 9.0.1-1 +- 9.0.1 Release + +* Mon Nov 25 2019 sguelton@redhat.com - 9.0.0-4 +- Activate AVR on all architectures + +* Mon Sep 30 2019 Tom Stellard tstellar@redhat.com - 9.0.0-3 +- Build libLLVM.so first to avoid OOM errors + +* Fri Sep 27 2019 Tom Stellard tstellar@redhat.com - 9.0.0-2 +- Remove unneeded BuildRequires: libstdc++-static + +* Thu Sep 19 2019 sguelton@redhat.com - 9.0.0-1 +- 9.0.0 Release + +* Wed Sep 18 2019 sguelton@redhat.com - 9.0.0-0.5.rc3 +- Support avr target, see rhbz#1718492 + +* Tue Sep 10 2019 Tom Stellard tstellar@redhat.com - 9.0.0-0.4.rc3 +- Split out test executables into their own export file + +* Fri Sep 06 2019 Tom Stellard tstellar@redhat.com - 9.0.0-0.3.rc3 +- Fix patch for splitting out static library exports + +* Fri Aug 30 2019 Tom Stellard tstellar@redhat.com - 9.0.0-0.2.rc3 +- 9.0.0-rc3 Release + +* Thu Aug 01 2019 Tom Stellard tstellar@redhat.com - 9.0.0-0.1.rc2 +- 9.0.0-rc2 Release + +* Tue Jul 30 2019 Tom Stellard tstellar@redhat.com - 8.0.0-9 +- Sync with llvm8.0 spec file + +* Thu Jul 25 2019 Fedora Release Engineering releng@fedoraproject.org - 8.0.0-8.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Wed Jul 17 2019 Tom Stellard tstellar@redhat.com - 8.0.0-8 +- Add provides for the major version of sub-packages + +* Fri May 17 2019 sguelton@redhat.com - 8.0.0-7 +- Fix conflicts between llvm-static = 8 and llvm-dev < 8 around LLVMStaticExports.cmake + +* Wed Apr 24 2019 Tom Stellard tstellar@redhat.com - 8.0.0-6 +- Make sure we aren't passing -g on s390x + +* Sat Mar 30 2019 Tom Stellard tstellar@redhat.com - 8.0.0-5 +- Enable build rpath while keeping install rpath disabled + +* Wed Mar 27 2019 Tom Stellard tstellar@redhat.com - 8.0.0-4 +- Backport r351577 from trunk to fix ninja check failures + +* Tue Mar 26 2019 Tom Stellard tstellar@redhat.com - 8.0.0-3 +- Fix ninja check + +* Fri Mar 22 2019 Tom Stellard tstellar@redhat.com - 8.0.0-2 +- llvm-test fixes + +* Wed Mar 20 2019 sguelton@redhat.com - 8.0.0-1 +- 8.0.0 final + +* Fri Mar 15 2019 sguelton@redhat.com - 8.0.0-0.6.rc4 +- Activate all backends (rhbz#1689031) + +* Tue Mar 12 2019 sguelton@redhat.com - 8.0.0-0.5.rc4 +- 8.0.0 Release candidate 4 + +* Mon Mar 4 2019 sguelton@redhat.com - 8.0.0-0.4.rc3 +- Move some binaries to -test package, cleanup specfile + +* Mon Mar 4 2019 sguelton@redhat.com - 8.0.0-0.3.rc3 +- 8.0.0 Release candidate 3 + +* Fri Feb 22 2019 sguelton@redhat.com - 8.0.0-0.2.rc2 +- 8.0.0 Release candidate 2 + +* Sat Feb 9 2019 sguelton@redhat.com - 8.0.0-0.1.rc1 +- 8.0.0 Release candidate 1 + +* Fri Feb 01 2019 Fedora Release Engineering releng@fedoraproject.org - 7.0.1-2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Mon Jan 21 2019 Josh Stone jistone@redhat.com - 7.0.1-2 +- Fix discriminators in metadata, rhbz#1668033 + +* Mon Dec 17 2018 sguelton@redhat.com - 7.0.1-1 +- 7.0.1 release + +* Tue Dec 04 2018 sguelton@redhat.com - 7.0.0-5 +- Ensure rpmlint passes on specfile + +* Sat Nov 17 2018 Tom Stellard tstellar@redhat.com - 7.0.0-4 +- Install testing libraries for unittests + +* Sat Oct 27 2018 Tom Stellard tstellar@redhat.com - 7.0.0-3 +- Fix running unittests as not-root user + +* Thu Sep 27 2018 Tom Stellard tstellar@redhat.com - 7.0.0-2 +- Fixes for llvm-test package: +- Add some missing Requires +- Add --threads option to run-lit-tests script +- Set PATH so lit can find tools like count, not, etc. +- Don't hardcode tools directory to /usr/lib64/llvm +- Fix typo in yaml-bench define +- Only print information about failing tests + +* Fri Sep 21 2018 Tom Stellard tstellar@redhat.com - 7.0.0-1 +- 7.0.0 Release + +* Thu Sep 13 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.15.rc3 +- Disable rpath on install LLVM and related sub-projects + +* Wed Sep 12 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.14.rc3 +- Remove rpath from executables and libraries + +* Tue Sep 11 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.13.rc3 +- Re-enable arm and aarch64 targets on x86_64 + +* Mon Sep 10 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.12.rc3 +- 7.0.0-rc3 Release + +* Fri Sep 07 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.11.rc2 +- Use python3 shebang for opt-viewewr scripts + +* Thu Aug 30 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.10.rc2 +- Drop all uses of python2 from lit tests + +* Thu Aug 30 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.9.rc2 +- Build the gold plugin on all supported architectures + +* Wed Aug 29 2018 Kevin Fenzi kevin@scrye.com - 7.0.0-0.8.rc2 +- Re-enable debuginfo to avoid 25x size increase. + +* Tue Aug 28 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.7.rc2 +- 7.0.0-rc2 Release + +* Tue Aug 28 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.6.rc1 +- Guard valgrind usage with valgrind_arches macro + +* Thu Aug 23 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.5.rc1 +- Package lit tests and googletest sources. + +* Mon Aug 20 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.4.rc1 +- Re-enable AMDGPU target on ARM rhbz#1618922 + +* Mon Aug 13 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.3.rc1 +- Drop references to TestPlugin.so from cmake files + +* Fri Aug 10 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.2.rc1 +- Fixes for lit tests + +* Fri Aug 10 2018 Tom Stellard tstellar@redhat.com - 7.0.0-0.1.rc1 +- 7.0.0-rc1 Release +- Reduce number of enabled targets on all arches. +- Drop s390 detection patch, LLVM does not support s390 codegen. + +* Mon Aug 06 2018 Tom Stellard tstellar@redhat.com - 6.0.1-6 +- Backport some fixes needed by mesa and rust + +* Thu Jul 26 2018 Tom Stellard tstellar@redhat.com - 6.0.1-5 +- Move libLLVM-6.0.so to llvm6.0-libs. + +* Mon Jul 23 2018 Tom Stellard tstellar@redhat.com - 6.0.1-4 +- Rebuild because debuginfo stripping failed with the previous build + +* Fri Jul 13 2018 Tom Stellard tstellar@redhat.com - 6.0.1-3 +- Sync specfile with llvm6.0 package + +* Fri Jul 13 2018 Fedora Release Engineering releng@fedoraproject.org - 6.0.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Mon Jun 25 2018 Tom Stellard tstellar@redhat.com - 6.0.1-1 +- 6.0.1 Release + +* Thu Jun 07 2018 Tom Stellard tstellar@redhat.com - 6.0.1-0.4.rc2 +- 6.0.1-rc2 + +* Wed Jun 06 2018 Tom Stellard tstellar@redhat.com - 6.0.1-0.3.rc1 +- Re-enable all targets to avoid breaking the ABI. + +* Mon Jun 04 2018 Tom Stellard tstellar@redhat.com - 6.0.1-0.2.rc1 +- Reduce the number of enabled targets based on the architecture + +* Thu May 10 2018 Tom Stellard tstellar@redhat.com - 6.0.1-0.1.rc1 +- 6.0.1 rc1 + +* Tue Mar 27 2018 Tom Stellard tstellar@redhat.com - 6.0.0-11 +- Re-enable arm tests that used to hang + +* Thu Mar 22 2018 Tom Stellard tstellar@redhat.com - 6.0.0-10 +- Fix testcase in backported patch + +* Tue Mar 20 2018 Tom Stellard tstellar@redhat.com - 6.0.0-9 +- Prevent external projects from linking against both static and shared + libraries. rhbz#1558657 + +* Mon Mar 19 2018 Tom Stellard tstellar@redhat.com - 6.0.0-8 +- Backport r327651 from trunk rhbz#1554349 + +* Fri Mar 16 2018 Tom Stellard tstellar@redhat.com - 6.0.0-7 +- Filter out cxxflags and cflags from llvm-config that aren't supported by clang +- rhbz#1556980 + +* Wed Mar 14 2018 Tom Stellard tstellar@redhat.com - 6.0.0-6 +- Enable symbol versioning in libLLVM.so + +* Wed Mar 14 2018 Tom Stellard tstellar@redhat.com - 6.0.0-5 +- Stop statically linking libstdc++. This is no longer required by Steam + client, but the steam installer still needs a work-around which should + be handled in the steam package. +* Wed Mar 14 2018 Tom Stellard tstellar@redhat.com - 6.0.0-4 +- s/make check/ninja check/ + +* Fri Mar 09 2018 Tom Stellard tstellar@redhat.com - 6.0.0-3 +- Backport fix for compile time regression on rust rhbz#1552915 + +* Thu Mar 08 2018 Tom Stellard tstellar@redhat.com - 6.0.0-2 +- Build with Ninja: This reduces RPM build time on a 6-core x86_64 builder + from 82 min to 52 min. + +* Thu Mar 08 2018 Tom Stellard tstellar@redhat.com - 6.0.0-1 +- 6.0.0 Release + +* Thu Mar 08 2018 Tom Stellard tstellar@redhat.com - 6.0.0-0.5.rc2 +- Reduce debuginfo size on i686 to avoid OOM errors during linking + +* Fri Feb 09 2018 Tom Stellard tstellar@redhat.com - 6.0.0-0.4.rc2 +- 6.0.1 rc2 + +* Fri Feb 09 2018 Igor Gnatenko ignatenkobrain@fedoraproject.org - 6.0.0-0.3.rc1 +- Escape macros in %%changelog + +* Thu Feb 08 2018 Fedora Release Engineering releng@fedoraproject.org - 6.0.0-0.2.rc1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Fri Jan 19 2018 Tom Stellard tstellar@redhat.com - 6.0.0-0.1.rc1 +- 6.0.1 rc1 + +* Tue Dec 19 2017 Tom Stellard tstellar@redhat.com - 5.0.1-1 +- 5.0.1 Release + +* Mon Nov 20 2017 Tom Stellard tstellar@redhat.com - 5.0.0-5 +- Backport debuginfo fix for rust + +* Fri Nov 03 2017 Tom Stellard tstellar@redhat.com - 5.0.0-4 +- Reduce debuginfo size for ARM + +* Tue Oct 10 2017 Tom Stellard tstellar@redhat.com - 5.0.0-2 +- Reduce memory usage on ARM by disabling debuginfo and some non-ARM targets. + +* Mon Sep 25 2017 Tom Stellard tstellar@redhat.com - 5.0.0-1 +- 5.0.0 Release + +* Mon Sep 18 2017 Tom Stellard tstellar@redhat.com - 4.0.1-6 +- Add Requires: libedit-devel for llvm-devel + +* Fri Sep 08 2017 Tom Stellard tstellar@redhat.com - 4.0.1-5 +- Enable libedit backend for LineEditor API + +* Fri Aug 25 2017 Tom Stellard tstellar@redhat.com - 4.0.1-4 +- Enable extra functionality when run the LLVM JIT under valgrind. + +* Thu Aug 03 2017 Fedora Release Engineering releng@fedoraproject.org - 4.0.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering releng@fedoraproject.org - 4.0.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Wed Jun 21 2017 Tom Stellard tstellar@redhat.com - 4.0.1-1 +- 4.0.1 Release + +* Thu Jun 15 2017 Tom Stellard tstellar@redhat.com - 4.0.0-6 +- Install llvm utils + +* Thu Jun 08 2017 Tom Stellard tstellar@redhat.com - 4.0.0-5 +- Fix docs-llvm-man target + +* Mon May 01 2017 Tom Stellard tstellar@redhat.com - 4.0.0-4 +- Make cmake files no longer depend on static libs (rhbz 1388200) + +* Tue Apr 18 2017 Josh Stone jistone@redhat.com - 4.0.0-3 +- Fix computeKnownBits for ARMISD::CMOV (rust-lang/llvm#67) + +* Mon Apr 03 2017 Tom Stellard tstellar@redhat.com - 4.0.0-2 +- Simplify spec with rpm macros. + +* Thu Mar 23 2017 Tom Stellard tstellar@redhat.com - 4.0.0-1 +- LLVM 4.0.0 Final Release + +* Wed Mar 22 2017 tstellar@redhat.com - 3.9.1-6 +- Fix %%postun sep for -devel package. + +* Mon Mar 13 2017 Tom Stellard tstellar@redhat.com - 3.9.1-5 +- Disable failing tests on ARM. + +* Sun Mar 12 2017 Peter Robinson pbrobinson@fedoraproject.org 3.9.1-4 +- Fix missing mask on relocation for aarch64 (rhbz 1429050) + +* Wed Mar 01 2017 Dave Airlie airlied@redhat.com - 3.9.1-3 +- revert upstream radeonsi breaking change. + +* Thu Feb 23 2017 Josh Stone jistone@redhat.com - 3.9.1-2 +- disable sphinx warnings-as-errors + +* Fri Feb 10 2017 Orion Poplawski orion@cora.nwra.com - 3.9.1-1 +- llvm 3.9.1 + +* Fri Feb 10 2017 Fedora Release Engineering releng@fedoraproject.org - 3.9.0-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Tue Nov 29 2016 Josh Stone jistone@redhat.com - 3.9.0-7 +- Apply backports from rust-lang/llvm#55, #57 + +* Tue Nov 01 2016 Dave Airlie <airlied@gmail.com - 3.9.0-6 +- rebuild for new arches + +* Wed Oct 26 2016 Dave Airlie airlied@redhat.com - 3.9.0-5 +- apply the patch from -4 + +* Wed Oct 26 2016 Dave Airlie airlied@redhat.com - 3.9.0-4 +- add fix for lldb out-of-tree build + +* Mon Oct 17 2016 Josh Stone jistone@redhat.com - 3.9.0-3 +- Apply backports from rust-lang/llvm#47, #48, #53, #54 + +* Sat Oct 15 2016 Josh Stone jistone@redhat.com - 3.9.0-2 +- Apply an InstCombine backport via rust-lang/llvm#51 + +* Wed Sep 07 2016 Dave Airlie airlied@redhat.com - 3.9.0-1 +- llvm 3.9.0 +- upstream moved where cmake files are packaged. +- upstream dropped CppBackend + +* Wed Jul 13 2016 Adam Jackson ajax@redhat.com - 3.8.1-1 +- llvm 3.8.1 +- Add mips target +- Fix some shared library mispackaging + +* Tue Jun 07 2016 Jan Vcelak jvcelak@fedoraproject.org - 3.8.0-2 +- fix color support detection on terminal + +* Thu Mar 10 2016 Dave Airlie airlied@redhat.com 3.8.0-1 +- llvm 3.8.0 release + +* Wed Mar 09 2016 Dan Hork <dan[at][danny.cz> 3.8.0-0.3 +- install back memory consumption workaround for s390 + +* Thu Mar 03 2016 Dave Airlie airlied@redhat.com 3.8.0-0.2 +- llvm 3.8.0 rc3 release + +* Fri Feb 19 2016 Dave Airlie airlied@redhat.com 3.8.0-0.1 +- llvm 3.8.0 rc2 release + +* Tue Feb 16 2016 Dan Hork <dan[at][danny.cz> 3.7.1-7 +- recognize s390 as SystemZ when configuring build + +* Sat Feb 13 2016 Dave Airlie airlied@redhat.com 3.7.1-6 +- export C++ API for mesa. + +* Sat Feb 13 2016 Dave Airlie airlied@redhat.com 3.7.1-5 +- reintroduce llvm-static, clang needs it currently. + +* Fri Feb 12 2016 Dave Airlie airlied@redhat.com 3.7.1-4 +- jump back to single llvm library, the split libs aren't working very well. + +* Fri Feb 05 2016 Dave Airlie airlied@redhat.com 3.7.1-3 +- add missing obsoletes (#1303497) + +* Thu Feb 04 2016 Fedora Release Engineering releng@fedoraproject.org - 3.7.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Thu Jan 07 2016 Jan Vcelak jvcelak@fedoraproject.org 3.7.1-1 +- new upstream release +- enable gold linker + +* Wed Nov 04 2015 Jan Vcelak jvcelak@fedoraproject.org 3.7.0-100 +- fix Requires for subpackages on the main package + +* Tue Oct 06 2015 Jan Vcelak jvcelak@fedoraproject.org 3.7.0-100 +- initial version using cmake build system diff --git a/run-lit-tests b/run-lit-tests new file mode 100755 index 0000000..a0f27d8 --- /dev/null +++ b/run-lit-tests @@ -0,0 +1,58 @@ +#!/bin/bash + +usage() { + echo "usage: `basename $0` [OPTIONS]" + echo " --threads NUM The number of threads to use for running tests." + echo " --multilib-arch ARCH Use this option to test 32-bit libs/binaries on" + echo " 64-bit hosts." +} + +threads_arg='' + +while [ $# -gt 0 ]; do + case $1 in + --threads) + shift + threads_arg="--threads $1" + ;; + --multilib-arch) + shift + ARCH=$1 + ;; + * ) + echo "unknown option: $1" + echo "" + usage + exit 1 + ;; + esac + shift +done + +set -xe + +if [ -z "$ARCH" ]; then + ARCH=`rpm --eval '%_arch'` +fi + +case $ARCH in + arm) + ;& + i686) + LIB_DIR="/usr/lib/" + ;; + *) + LIB_DIR="/usr/lib64/" + ;; +esac + +cd $(mktemp -d) +ln -s /usr/include include +tar -xzf /usr/share/llvm/src/test.tar.gz +ln -s $ARCH.site.cfg.py test/lit.site.cfg.py +ln -s $ARCH.site.cfg.py test/Unit/lit.site.cfg.py +lit -v -s $threads_arg test \ + -Dllvm_obj_root=`pwd` \ + -Dllvm_test_root=`pwd`/test \ + -Dllvm_unittest_bindir=$LIB_DIR/llvm \ + -Dllvm_shlib_dir=$LIB_DIR diff --git a/sources b/sources new file mode 100644 index 0000000..569b8de --- /dev/null +++ b/sources @@ -0,0 +1 @@ +SHA512 (llvm-9.0.1.src.tar.xz) = bfb6960a4dd1e18f4005f324f478a781c69e8ec7c20569d9b243fcb9372dc7733b254f26c683373537990cc9c109c78eaf0f65449629ee17caca1bce9b9ccccd
arch-excludes@lists.fedoraproject.org