diff --git a/.gitignore b/.gitignore index 02ad497..7adc32b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/llvm-8.0.1.src.tar.xz +SOURCES/llvm-9.0.1.src.tar.xz diff --git a/.llvm.metadata b/.llvm.metadata index 59cfa37..fe0c8ba 100644 --- a/.llvm.metadata +++ b/.llvm.metadata @@ -1 +1 @@ -09964f9eabc364f221a3caefbdaea28557273b4a SOURCES/llvm-8.0.1.src.tar.xz +f7fcf3bd92d130784513c06efe6910f135372ce3 SOURCES/llvm-9.0.1.src.tar.xz diff --git a/SOURCES/0001-BPF-Handling-type-conversions-correctly-for-CO-RE.patch b/SOURCES/0001-BPF-Handling-type-conversions-correctly-for-CO-RE.patch new file mode 100644 index 0000000..bfde9bc --- /dev/null +++ b/SOURCES/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 +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 + + #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 &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(Ty)) { ++ if (!SkipDIDerivedTag(DTy->getTag())) ++ break; ++ Ty = DTy->getBaseType(); ++ } ++ return Ty; ++} ++ ++static const DIType * stripQualifiers(const DIType *Ty) { ++ while (auto *DTy = dyn_cast(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(Elements[I])) ++ if (Element->getTag() == dwarf::DW_TAG_subrange_type) { ++ const DISubrange *SR = cast(Element); ++ auto *CI = SR->getCount().dyn_cast(); ++ 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(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(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(Call->getArgOperand(2)) ++ ->getZExtValue(); + return true; + } + +@@ -200,7 +266,9 @@ bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Module &M) { + for (auto &I : BB) { + auto *Call = dyn_cast(&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(ParentType)); ++ const DIType *CType = stripQualifiers(cast(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(CType)) ++ return false; ++ ++ // Parent is a pointer type. ++ if (const auto *PtrTy = dyn_cast(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(PType); ++ const auto *CTy = dyn_cast(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(PTy->getElements()[ParentAI]); ++ ++ return dyn_cast(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(U); + if (!Inst) + continue; + + if (auto *BI = dyn_cast(Inst)) { +- traceBitCast(BI, Call, Kind); ++ traceBitCast(BI, Call, Kind, ParentMeta, ParentAI); + } else if (auto *CI = dyn_cast(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(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(U); + if (!Inst) + continue; + + if (auto *BI = dyn_cast(Inst)) { +- traceBitCast(BI, Parent, Kind); ++ traceBitCast(BI, Parent, Kind, ParentMeta, ParentAI); + } else if (auto *CI = dyn_cast(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(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(U); + if (!Inst) + continue; + + if (auto *BI = dyn_cast(Inst)) { +- traceBitCast(BI, Parent, Kind); ++ traceBitCast(BI, Parent, Kind, ParentMeta, ParentAI); + } else if (auto *CI = dyn_cast(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(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(&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 AccessIndices; +- uint64_t TypeNameIndex = 0; +- std::string LastTypeName; ++ std::string TypeName; ++ std::stack> 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(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(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(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(Ty); ++ assert(DTy->getTag() == dwarf::DW_TAG_pointer_type); ++ ++ BaseTy = stripQualifiers(DTy->getBaseType()); ++ CTy = dyn_cast(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(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(stripQualifiers(cast(MDN))); ++ uint32_t Tag = CTy->getTag(); ++ if (Tag == dwarf::DW_TAG_structure_type) { ++ auto *MemberTy = cast(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(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(ElemType, ElemTypeId, 0, 0); +- ArrayTypes.push_back(TypeEntry.get()); ++ auto TypeEntry = llvm::make_unique(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(Element); + auto *CI = SR->getCount().dyn_cast(); + int64_t Count = CI->getSExtValue(); +- const DIType *ArrayElemTy = (I == 0) ? ElemType : nullptr; + + auto TypeEntry = +- llvm::make_unique(ArrayElemTy, ElemTypeId, +- ElemSize, Count); +- ArrayTypes.push_back(TypeEntry.get()); ++ llvm::make_unique(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 Members; +- std::vector 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> FileContent; + std::map> DataSecEntries; + std::vector StructTypes; +- std::vector ArrayTypes; + std::map AccessOffsets; + std::map>> + 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/SOURCES/0001-BPF-annotate-DIType-metadata-for-builtin-preseve_arr.patch b/SOURCES/0001-BPF-annotate-DIType-metadata-for-builtin-preseve_arr.patch new file mode 100644 index 0000000..60ba6d9 --- /dev/null +++ b/SOURCES/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 +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 + +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(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/SOURCES/0001-CMake-Split-static-library-exports-into-their-own-ex.patch b/SOURCES/0001-CMake-Split-static-library-exports-into-their-own-ex.patch new file mode 100644 index 0000000..e780c34 --- /dev/null +++ b/SOURCES/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 +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/SOURCES/0001-CMake-Split-test-binary-exports-into-their-own-expor.patch b/SOURCES/0001-CMake-Split-test-binary-exports-into-their-own-expor.patch new file mode 100644 index 0000000..a3801ff --- /dev/null +++ b/SOURCES/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 +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/SOURCES/0001-Deactivate-markdown-doc.patch b/SOURCES/0001-Deactivate-markdown-doc.patch index 87e3a46..d9e402a 100644 --- a/SOURCES/0001-Deactivate-markdown-doc.patch +++ b/SOURCES/0001-Deactivate-markdown-doc.patch @@ -1,14 +1,14 @@ -From eeb9da2ece9a58448c213b900090b32e6d303bff Mon Sep 17 00:00:00 2001 +From e7bc515182199764b17ab3f5e22047342f9c7514 Mon Sep 17 00:00:00 2001 From: serge-sans-paille Date: Thu, 13 Jun 2019 07:58:59 +0000 -Subject: [PATCH 4/4] Deactivate markdown doc +Subject: [PATCH] Deactivate markdown doc --- llvm/docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/docs/conf.py b/llvm/docs/conf.py -index 7fdcb3d2f52..501b48b540d 100644 +index 4a52df8..340cd07 100644 --- a/llvm/docs/conf.py +++ b/llvm/docs/conf.py @@ -32,9 +32,9 @@ extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo'] @@ -24,5 +24,5 @@ index 7fdcb3d2f52..501b48b540d 100644 # The encoding of source files. #source_encoding = 'utf-8-sig' -- -2.20.1 +1.8.3.1 diff --git a/SOURCES/0001-Docs-llvm-strip-Add-help-text-to-llvm-strip-rst-doc.patch b/SOURCES/0001-Docs-llvm-strip-Add-help-text-to-llvm-strip-rst-doc.patch new file mode 100644 index 0000000..0be06dd --- /dev/null +++ b/SOURCES/0001-Docs-llvm-strip-Add-help-text-to-llvm-strip-rst-doc.patch @@ -0,0 +1,223 @@ +From 8987da9a2cac6c5bd39ba100ffd1aaede94dc6a0 Mon Sep 17 00:00:00 2001 +From: Michael Pozulp +Date: Fri, 9 Aug 2019 19:10:55 +0000 +Subject: [PATCH] [Docs][llvm-strip] Add help text to llvm-strip rst doc + +Summary: Addresses https://bugs.llvm.org/show_bug.cgi?id=42383 + +Reviewers: jhenderson, alexshap, rupprecht + +Reviewed By: jhenderson + +Subscribers: wolfgangp, jakehehrlich, llvm-commits + +Tags: #llvm + +Differential Revision: https://reviews.llvm.org/D65384 + +llvm-svn: 368464 +--- + llvm/docs/CommandGuide/llvm-strip.md | 16 ---- + llvm/docs/CommandGuide/llvm-strip.rst | 167 ++++++++++++++++++++++++++++++++++ + 2 files changed, 167 insertions(+), 16 deletions(-) + delete mode 100644 llvm/docs/CommandGuide/llvm-strip.md + create mode 100644 llvm/docs/CommandGuide/llvm-strip.rst + +diff --git a/llvm/docs/CommandGuide/llvm-strip.md b/llvm/docs/CommandGuide/llvm-strip.md +deleted file mode 100644 +index dd6e859..0000000 +--- a/llvm/docs/CommandGuide/llvm-strip.md ++++ /dev/null +@@ -1,16 +0,0 @@ +-# llvm-strip - object stripping tool +- +-## SYNOPSIS +- +-**llvm-strip** [*options*] +- +-## DESCRIPTION +- +-**llvm-strip** is a tool to strip sections and symbols from object files. +- +-The tool is still in active development, but in most scenarios it works as a +-drop-in replacement for GNU's **strip**. +- +-## SEE ALSO +- +-[llvm-objcopy](llvm-objcopy.html) +diff --git a/llvm/docs/CommandGuide/llvm-strip.rst b/llvm/docs/CommandGuide/llvm-strip.rst +new file mode 100644 +index 0000000..6e02482 +--- /dev/null ++++ b/llvm/docs/CommandGuide/llvm-strip.rst +@@ -0,0 +1,167 @@ ++llvm-strip - object stripping tool ++================================== ++ ++.. program:: llvm-strip ++ ++SYNOPSIS ++-------- ++ ++:program:`llvm-strip` [*options*] *inputs...* ++ ++DESCRIPTION ++----------- ++ ++:program:`llvm-strip` is a tool to strip sections and symbols from object files. ++If no other stripping or remove options are specified, :option:`--strip-all` ++will be enabled by default. ++ ++The input files are modified in-place. If "-" is specified for the input file, ++the input is read from the program's standard input stream. ++ ++If the input is an archive, any requested operations will be applied to each ++archive member individually. ++ ++The tool is still in active development, but in most scenarios it works as a ++drop-in replacement for GNU's :program:`strip`. ++ ++GENERIC AND CROSS-PLATFORM OPTIONS ++---------------------------------- ++ ++The following options are either agnostic of the file format, or apply to ++multiple file formats. ++ ++.. option:: --disable-deterministic-archives, -U ++ ++ Use real values for UIDs, GIDs and timestamps when updating archive member ++ headers. ++ ++.. option:: --discard-all, -x ++ ++ Remove most local symbols from the output. Different file formats may limit ++ this to a subset of the local symbols. For example, file and section symbols in ++ ELF objects will not be discarded. ++ ++.. option:: --enable-deterministic-archives, -D ++ ++ Enable deterministic mode when stripping archives, i.e. use 0 for archive member ++ header UIDs, GIDs and timestamp fields. On by default. ++ ++.. option:: --help, -h ++ ++ Print a summary of command line options. ++ ++.. option:: --no-strip-all ++ ++ Disable --strip-all. ++ ++.. option:: -o ++ ++ Write output to . Multiple input files cannot be used in combination ++ with -o. ++ ++.. option:: --regex ++ ++ If specified, symbol and section names specified by other switches are treated ++ as extended POSIX regular expression patterns. ++ ++.. option:: --remove-section
, -R ++ ++ Remove the specified section from the output. Can be specified multiple times ++ to remove multiple sections simultaneously. ++ ++.. option:: --strip-all-gnu ++ ++ Remove all symbols, debug sections and relocations from the output. This option ++ is equivalent to GNU :program:`strip`'s ``--strip-all`` switch. ++ ++.. option:: --strip-all, -S ++ ++ For ELF objects, remove from the output all symbols and non-alloc sections not ++ within segments, except for .gnu.warning sections and the section name table. ++ ++ For COFF objects, remove all symbols, debug sections, and relocations from the ++ output. ++ ++.. option:: --strip-debug, -g ++ ++ Remove all debug sections. ++ ++.. option:: --strip-sections ++ ++ Remove all section headers and all sections not in segments. ++ ++.. option:: --strip-symbol , -N ++ ++ Remove all symbols named ```` from the output. Can be specified ++ multiple times to remove multiple symbols. ++ ++.. option:: --strip-unneeded ++ ++ Remove all local or undefined symbols that are not required by relocations. ++ ++.. option:: --version, -V ++ ++ Display the version of this program. ++ ++COFF-SPECIFIC OPTIONS ++--------------------- ++ ++The following options are implemented only for COFF objects. If used with other ++objects, :program:`llvm-strip` will either emit an error or silently ignore ++them. ++ ++.. option:: --only-keep-debug ++ ++ Remove the contents of non-debug sections from the output, but keep the section ++ headers. ++ ++ELF-SPECIFIC OPTIONS ++-------------------- ++ ++The following options are implemented only for ELF objects. If used with other ++objects, :program:`llvm-strip` will either emit an error or silently ignore ++them. ++ ++.. option:: --allow-broken-links ++ ++ Allow llvm-strip to remove sections even if it would leave invalid section ++ references. Any invalid sh_link fields will be set to zero. ++ ++.. option:: --discard-locals, -X ++ ++ Remove local symbols starting with ".L" from the output. ++ ++.. option:: --keep-file-symbols ++ ++ Keep symbols of type `STT_FILE`, even if they would otherwise be stripped. ++ ++ .. option:: --keep-section
++ ++ When removing sections from the output, do not remove sections named ++ ``
``. Can be specified multiple times to keep multiple sections. ++ ++.. option:: --keep-symbol , -K ++ ++ Do not remove symbols named ````. Can be specified multiple times to ++ keep multiple symbols. ++ ++.. option:: --preserve-dates, -p ++ ++ Preserve access and modification timestamps. ++ ++ ++EXIT STATUS ++----------- ++ ++:program:`llvm-strip` exits with a non-zero exit code if there is an error. ++Otherwise, it exits with code 0. ++ ++BUGS ++---- ++ ++To report bugs, please visit . ++ ++SEE ALSO ++-------- ++ ++:manpage:`llvm-objcopy(1)` +-- +1.8.3.1 + diff --git a/SOURCES/0001-Filter-out-cxxflags-not-supported-by-clang.patch b/SOURCES/0001-Filter-out-cxxflags-not-supported-by-clang.patch index e2f3b26..1351d2f 100644 --- a/SOURCES/0001-Filter-out-cxxflags-not-supported-by-clang.patch +++ b/SOURCES/0001-Filter-out-cxxflags-not-supported-by-clang.patch @@ -1,82 +1,28 @@ -From e491bb836e530585e4d278b82725e4cefdd14abc Mon Sep 17 00:00:00 2001 -From: serge-sans-paille -Date: Thu, 13 Jun 2019 07:55:37 +0000 -Subject: [PATCH 3/4] Filter-out-cxxflags-not-supported-by-clang +From d15c835028bcc72a8695d047f0acaa530aa54716 Mon Sep 17 00:00:00 2001 +From: Tom Stellard +Date: Wed, 31 Jul 2019 20:43:42 -0700 +Subject: [PATCH] Filter out cxxflags not supported by clang --- - llvm/cmake/modules/AddLLVM.cmake | 6 +++++- - llvm/cmake/modules/CMakeLists.txt | 3 +++ - llvm/cmake/modules/LLVMConfig.cmake.in | 2 ++ - llvm/tools/llvm-config/CMakeLists.txt | 4 ++++ - 4 files changed, 14 insertions(+), 1 deletion(-) + llvm/tools/llvm-config/CMakeLists.txt | 4 ++++ + 1 file changed, 4 insertions(+) -diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake -index 1a417447278..bb10f20cdd6 100644 ---- a/llvm/cmake/modules/AddLLVM.cmake -+++ b/llvm/cmake/modules/AddLLVM.cmake -@@ -664,7 +664,11 @@ macro(add_llvm_library name) - - if(${name} 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 f5cc0006fa0..6605dc729c2 100644 ---- a/llvm/cmake/modules/CMakeLists.txt -+++ b/llvm/cmake/modules/CMakeLists.txt -@@ -97,6 +97,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 -@@ -113,6 +114,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 7ca06381d90..44d042c9b11 100644 ---- a/llvm/cmake/modules/LLVMConfig.cmake.in -+++ b/llvm/cmake/modules/LLVMConfig.cmake.in -@@ -84,6 +84,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 diff --git a/llvm/tools/llvm-config/CMakeLists.txt b/llvm/tools/llvm-config/CMakeLists.txt -index a7db17386fb..8a796d03b5a 100644 +index 8e97a10..9b9b7d1 100644 --- a/llvm/tools/llvm-config/CMakeLists.txt +++ b/llvm/tools/llvm-config/CMakeLists.txt -@@ -42,7 +42,11 @@ set(LLVM_SRC_ROOT ${LLVM_MAIN_SRC_DIR}) +@@ -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} ${COMPILE_FLAGS} ${LLVM_DEFINITIONS}") + 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}") -- -2.20.1 +1.8.3.1 diff --git a/SOURCES/0001-Pass-target-to-gold-linker-to-avoid-faliures-on-i686.patch b/SOURCES/0001-Pass-target-to-gold-linker-to-avoid-faliures-on-i686.patch new file mode 100644 index 0000000..e8dd323 --- /dev/null +++ b/SOURCES/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 +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/SOURCES/0001-Revert-SCEV-add-no-wrap-flag-for-SCEVAddExpr.patch b/SOURCES/0001-Revert-SCEV-add-no-wrap-flag-for-SCEVAddExpr.patch new file mode 100644 index 0000000..caf774c --- /dev/null +++ b/SOURCES/0001-Revert-SCEV-add-no-wrap-flag-for-SCEVAddExpr.patch @@ -0,0 +1,113 @@ +From 58e8c793d0e43150a6452e971a32d7407a8a7401 Mon Sep 17 00:00:00 2001 +From: Tim Northover +Date: Mon, 30 Sep 2019 07:46:52 +0000 +Subject: [PATCH] Revert "[SCEV] add no wrap flag for SCEVAddExpr." + +This reverts r366419 because the analysis performed is within the context of +the loop and it's only valid to add wrapping flags to "global" expressions if +they're always correct. + +llvm-svn: 373184 +--- + llvm/lib/Analysis/ScalarEvolution.cpp | 2 +- + llvm/test/Analysis/ScalarEvolution/limit-depth.ll | 2 +- + llvm/test/Analysis/ScalarEvolution/nsw.ll | 2 +- + llvm/test/Analysis/ScalarEvolution/trip-count12.ll | 2 +- + llvm/test/Analysis/ScalarEvolution/trip-count9.ll | 8 ++++---- + 5 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp +index 354ae05bb841..c29fc5dbccfb 100644 +--- a/llvm/lib/Analysis/ScalarEvolution.cpp ++++ b/llvm/lib/Analysis/ScalarEvolution.cpp +@@ -4992,7 +4992,7 @@ const SCEV *ScalarEvolution::createSimpleAffineAddRec(PHINode *PN, + // overflow. + if (auto *BEInst = dyn_cast(BEValueV)) + if (isLoopInvariant(Accum, L) && isAddRecNeverPoison(BEInst, L)) +- (void)getAddRecExpr(getAddExpr(StartVal, Accum, Flags), Accum, L, Flags); ++ (void)getAddRecExpr(getAddExpr(StartVal, Accum), Accum, L, Flags); + + return PHISCEV; + } +diff --git a/llvm/test/Analysis/ScalarEvolution/limit-depth.ll b/llvm/test/Analysis/ScalarEvolution/limit-depth.ll +index db68a4f84c91..6fdf8c5df974 100644 +--- a/llvm/test/Analysis/ScalarEvolution/limit-depth.ll ++++ b/llvm/test/Analysis/ScalarEvolution/limit-depth.ll +@@ -46,7 +46,7 @@ define void @test_mul(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) { + define void @test_sext(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) { + ; CHECK-LABEL: @test_sext + ; CHECK: %se2 = sext i64 %iv2.inc to i128 +-; CHECK-NEXT: --> {(1 + (sext i64 {(sext i32 (1 + %a) to i64),+,1}<%loop> to i128)),+,1}<%loop2> ++; CHECK-NEXT: --> {(1 + (sext i64 {(sext i32 (1 + %a) to i64),+,1}<%loop> to i128)),+,1}<%loop2> + entry: + br label %loop + +diff --git a/llvm/test/Analysis/ScalarEvolution/nsw.ll b/llvm/test/Analysis/ScalarEvolution/nsw.ll +index 69427368625d..ca24f9d4a04b 100644 +--- a/llvm/test/Analysis/ScalarEvolution/nsw.ll ++++ b/llvm/test/Analysis/ScalarEvolution/nsw.ll +@@ -163,7 +163,7 @@ bb5: ; preds = %bb2 + declare void @f(i32) + + ; CHECK-LABEL: nswnowrap +-; CHECK: --> {(1 + %v),+,1}<%for.body>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (2 + %v) ++; CHECK: --> {(1 + %v),+,1}<%for.body>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (1 + ((1 + %v) smax %v)) + define void @nswnowrap(i32 %v, i32* %buf) { + entry: + %add = add nsw i32 %v, 1 +diff --git a/llvm/test/Analysis/ScalarEvolution/trip-count12.ll b/llvm/test/Analysis/ScalarEvolution/trip-count12.ll +index 5e7d72d5e4f3..d0086ee2e6ac 100644 +--- a/llvm/test/Analysis/ScalarEvolution/trip-count12.ll ++++ b/llvm/test/Analysis/ScalarEvolution/trip-count12.ll +@@ -1,7 +1,7 @@ + ; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s + + ; CHECK: Determining loop execution counts for: @test +-; CHECK: Loop %for.body: backedge-taken count is ((-2 + %len) /u 2) ++; CHECK: Loop %for.body: backedge-taken count is ((-2 + %len) /u 2) + ; CHECK: Loop %for.body: max backedge-taken count is 1073741823 + + define zeroext i16 @test(i16* nocapture %p, i32 %len) nounwind readonly { +diff --git a/llvm/test/Analysis/ScalarEvolution/trip-count9.ll b/llvm/test/Analysis/ScalarEvolution/trip-count9.ll +index c0a1d12fa00e..9a080b34743f 100644 +--- a/llvm/test/Analysis/ScalarEvolution/trip-count9.ll ++++ b/llvm/test/Analysis/ScalarEvolution/trip-count9.ll +@@ -179,7 +179,7 @@ exit: + } + + ; CHECK: Determining loop execution counts for: @nsw_startx +-; CHECK: Loop %loop: backedge-taken count is (-1 + (-1 * %x) + ((1 + %x) smax %n)) ++; CHECK: Loop %loop: backedge-taken count is (-1 + (-1 * %x) + ((1 + %x) smax %n)) + ; CHECK: Loop %loop: max backedge-taken count is -1 + define void @nsw_startx(i4 %n, i4 %x) { + entry: +@@ -195,7 +195,7 @@ exit: + } + + ; CHECK: Determining loop execution counts for: @nsw_startx_step2 +-; CHECK: Loop %loop: backedge-taken count is ((-1 + (-1 * %x) + ((2 + %x) smax %n)) /u 2) ++; CHECK: Loop %loop: backedge-taken count is ((-1 + (-1 * %x) + ((2 + %x) smax %n)) /u 2) + ; CHECK: Loop %loop: max backedge-taken count is 7 + define void @nsw_startx_step2(i4 %n, i4 %x) { + entry: +@@ -381,7 +381,7 @@ exit: + } + + ; CHECK: Determining loop execution counts for: @even_nsw_startx +-; CHECK: Loop %loop: backedge-taken count is (-1 + (-1 * %x) + ((1 + %x) smax (2 * %n))) ++; CHECK: Loop %loop: backedge-taken count is (-1 + (-1 * %x) + ((1 + %x) smax (2 * %n))) + ; CHECK: Loop %loop: max backedge-taken count is -2 + define void @even_nsw_startx(i4 %n, i4 %x) { + entry: +@@ -398,7 +398,7 @@ exit: + } + + ; CHECK: Determining loop execution counts for: @even_nsw_startx_step2 +-; CHECK: Loop %loop: backedge-taken count is ((-1 + (-1 * %x) + ((2 + %x) smax (2 * %n))) /u 2) ++; CHECK: Loop %loop: backedge-taken count is ((-1 + (-1 * %x) + ((2 + %x) smax (2 * %n))) /u 2) + ; CHECK: Loop %loop: max backedge-taken count is 7 + define void @even_nsw_startx_step2(i4 %n, i4 %x) { + entry: +-- +2.24.1 + diff --git a/SOURCES/0001-Selectively-disable-threading-from-gold.patch b/SOURCES/0001-Selectively-disable-threading-from-gold.patch deleted file mode 100644 index ddeadec..0000000 --- a/SOURCES/0001-Selectively-disable-threading-from-gold.patch +++ /dev/null @@ -1,381 +0,0 @@ -From 5fd2c900e90445c6efb7b97f8c663e588bcab81b Mon Sep 17 00:00:00 2001 -From: serge-sans-paille -Date: Tue, 2 Jul 2019 09:25:52 +0000 -Subject: [PATCH] Selectively disable threading from gold - -Related: rhbz#1636479 ---- - llvm/include/llvm/LTO/LTO.h | 3 + - llvm/include/llvm/LTO/LTOBackend.h | 3 + - llvm/include/llvm/Support/ThreadPool.h | 7 ++ - llvm/lib/LTO/LTO.cpp | 134 ++++++++++++++++++++++++- - llvm/lib/LTO/LTOBackend.cpp | 48 ++++++++- - llvm/lib/Support/ThreadPool.cpp | 6 +- - llvm/tools/gold/gold-plugin.cpp | 7 +- - 7 files changed, 197 insertions(+), 11 deletions(-) - -diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h -index 534d9b6f3f2..9dfda126540 100644 ---- a/llvm/include/llvm/LTO/LTO.h -+++ b/llvm/include/llvm/LTO/LTO.h -@@ -212,6 +212,7 @@ typedef std::function( - - /// This ThinBackend runs the individual backend jobs in-process. - ThinBackend createInProcessThinBackend(unsigned ParallelismLevel); -+ThinBackend createInProcessThinBackendNoThread(unsigned ParallelismLevel); - - /// This ThinBackend writes individual module indexes to files, instead of - /// running the individual backend jobs. This backend is for distributed builds -@@ -281,6 +282,7 @@ public: - /// The client will receive at most one callback (via either AddStream or - /// Cache) for each task identifier. - Error run(AddStreamFn AddStream, NativeObjectCache Cache = nullptr); -+ Error runNoThread(AddStreamFn AddStream, NativeObjectCache Cache = nullptr); - - private: - Config Conf; -@@ -397,6 +399,7 @@ private: - const SymbolResolution *&ResI, const SymbolResolution *ResE); - - Error runRegularLTO(AddStreamFn AddStream); -+ Error runRegularLTONoThread(AddStreamFn AddStream); - Error runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache); - - mutable bool CalledGetMaxTasks = false; -diff --git a/llvm/include/llvm/LTO/LTOBackend.h b/llvm/include/llvm/LTO/LTOBackend.h -index d4743f6940f..2d6461fa82e 100644 ---- a/llvm/include/llvm/LTO/LTOBackend.h -+++ b/llvm/include/llvm/LTO/LTOBackend.h -@@ -39,6 +39,9 @@ namespace lto { - Error backend(Config &C, AddStreamFn AddStream, - unsigned ParallelCodeGenParallelismLevel, - std::unique_ptr M, ModuleSummaryIndex &CombinedIndex); -+Error backendNoThread(Config &C, AddStreamFn AddStream, -+ unsigned ParallelCodeGenParallelismLevel, -+ std::unique_ptr M, ModuleSummaryIndex &CombinedIndex); - - /// Runs a ThinLTO backend. - Error thinBackend(Config &C, unsigned Task, AddStreamFn AddStream, Module &M, -diff --git a/llvm/include/llvm/Support/ThreadPool.h b/llvm/include/llvm/Support/ThreadPool.h -index 4fdbd528b21..60ea5097114 100644 ---- a/llvm/include/llvm/Support/ThreadPool.h -+++ b/llvm/include/llvm/Support/ThreadPool.h -@@ -98,4 +98,11 @@ private: - }; - } - -+#ifndef ThreadPool -+#undef LLVM_SUPPORT_THREAD_POOL_H -+#define ThreadPool SequentialThreadPool -+#include "llvm/Support/ThreadPool.h" -+#undef ThreadPool -+#endif -+ - #endif // LLVM_SUPPORT_THREAD_POOL_H -diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp -index 3a955060dea..a7b4f45b18c 100644 ---- a/llvm/lib/LTO/LTO.cpp -+++ b/llvm/lib/LTO/LTO.cpp -@@ -861,6 +861,58 @@ Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) { - return Result; - } - -+Error LTO::runNoThread(AddStreamFn AddStream, NativeObjectCache Cache) { -+ // Compute "dead" symbols, we don't want to import/export these! -+ DenseSet GUIDPreservedSymbols; -+ DenseMap GUIDPrevailingResolutions; -+ for (auto &Res : GlobalResolutions) { -+ // Normally resolution have IR name of symbol. We can do nothing here -+ // otherwise. See comments in GlobalResolution struct for more details. -+ if (Res.second.IRName.empty()) -+ continue; -+ -+ GlobalValue::GUID GUID = GlobalValue::getGUID( -+ GlobalValue::dropLLVMManglingEscape(Res.second.IRName)); -+ -+ if (Res.second.VisibleOutsideSummary && Res.second.Prevailing) -+ GUIDPreservedSymbols.insert(GlobalValue::getGUID( -+ GlobalValue::dropLLVMManglingEscape(Res.second.IRName))); -+ -+ GUIDPrevailingResolutions[GUID] = -+ Res.second.Prevailing ? PrevailingType::Yes : PrevailingType::No; -+ } -+ -+ auto isPrevailing = [&](GlobalValue::GUID G) { -+ auto It = GUIDPrevailingResolutions.find(G); -+ if (It == GUIDPrevailingResolutions.end()) -+ return PrevailingType::Unknown; -+ return It->second; -+ }; -+ computeDeadSymbolsWithConstProp(ThinLTO.CombinedIndex, GUIDPreservedSymbols, -+ isPrevailing, Conf.OptLevel > 0); -+ -+ // Setup output file to emit statistics. -+ std::unique_ptr StatsFile = nullptr; -+ if (!Conf.StatsFile.empty()) { -+ EnableStatistics(false); -+ std::error_code EC; -+ StatsFile = -+ llvm::make_unique(Conf.StatsFile, EC, sys::fs::F_None); -+ if (EC) -+ return errorCodeToError(EC); -+ StatsFile->keep(); -+ } -+ -+ Error Result = runRegularLTONoThread(AddStream); -+ if (!Result) -+ Result = runThinLTO(AddStream, Cache); -+ -+ if (StatsFile) -+ PrintStatisticsJSON(StatsFile->os()); -+ -+ return Result; -+} -+ - Error LTO::runRegularLTO(AddStreamFn AddStream) { - for (auto &M : RegularLTO.ModsWithSummaries) - if (Error Err = linkRegularLTO(std::move(M), -@@ -928,6 +980,73 @@ Error LTO::runRegularLTO(AddStreamFn AddStream) { - std::move(RegularLTO.CombinedModule), ThinLTO.CombinedIndex); - } - -+Error LTO::runRegularLTONoThread(AddStreamFn AddStream) { -+ for (auto &M : RegularLTO.ModsWithSummaries) -+ if (Error Err = linkRegularLTO(std::move(M), -+ /*LivenessFromIndex=*/true)) -+ return Err; -+ -+ // Make sure commons have the right size/alignment: we kept the largest from -+ // all the prevailing when adding the inputs, and we apply it here. -+ const DataLayout &DL = RegularLTO.CombinedModule->getDataLayout(); -+ for (auto &I : RegularLTO.Commons) { -+ if (!I.second.Prevailing) -+ // Don't do anything if no instance of this common was prevailing. -+ continue; -+ GlobalVariable *OldGV = RegularLTO.CombinedModule->getNamedGlobal(I.first); -+ if (OldGV && DL.getTypeAllocSize(OldGV->getValueType()) == I.second.Size) { -+ // Don't create a new global if the type is already correct, just make -+ // sure the alignment is correct. -+ OldGV->setAlignment(I.second.Align); -+ continue; -+ } -+ ArrayType *Ty = -+ ArrayType::get(Type::getInt8Ty(RegularLTO.Ctx), I.second.Size); -+ auto *GV = new GlobalVariable(*RegularLTO.CombinedModule, Ty, false, -+ GlobalValue::CommonLinkage, -+ ConstantAggregateZero::get(Ty), ""); -+ GV->setAlignment(I.second.Align); -+ if (OldGV) { -+ OldGV->replaceAllUsesWith(ConstantExpr::getBitCast(GV, OldGV->getType())); -+ GV->takeName(OldGV); -+ OldGV->eraseFromParent(); -+ } else { -+ GV->setName(I.first); -+ } -+ } -+ -+ if (Conf.PreOptModuleHook && -+ !Conf.PreOptModuleHook(0, *RegularLTO.CombinedModule)) -+ return Error::success(); -+ -+ if (!Conf.CodeGenOnly) { -+ for (const auto &R : GlobalResolutions) { -+ if (!R.second.isPrevailingIRSymbol()) -+ continue; -+ if (R.second.Partition != 0 && -+ R.second.Partition != GlobalResolution::External) -+ continue; -+ -+ GlobalValue *GV = -+ RegularLTO.CombinedModule->getNamedValue(R.second.IRName); -+ // Ignore symbols defined in other partitions. -+ // Also skip declarations, which are not allowed to have internal linkage. -+ if (!GV || GV->hasLocalLinkage() || GV->isDeclaration()) -+ continue; -+ GV->setUnnamedAddr(R.second.UnnamedAddr ? GlobalValue::UnnamedAddr::Global -+ : GlobalValue::UnnamedAddr::None); -+ if (EnableLTOInternalization && R.second.Partition == 0) -+ GV->setLinkage(GlobalValue::InternalLinkage); -+ } -+ -+ if (Conf.PostInternalizeModuleHook && -+ !Conf.PostInternalizeModuleHook(0, *RegularLTO.CombinedModule)) -+ return Error::success(); -+ } -+ return backendNoThread(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel, -+ std::move(RegularLTO.CombinedModule), ThinLTO.CombinedIndex); -+} -+ - /// This class defines the interface to the ThinLTO backend. - class lto::ThinBackendProc { - protected: -@@ -952,8 +1071,9 @@ public: - }; - - namespace { -+template - class InProcessThinBackend : public ThinBackendProc { -- ThreadPool BackendThreadPool; -+ ThreadEngine BackendThreadPool; - AddStreamFn AddStream; - NativeObjectCache Cache; - std::set CfiFunctionDefs; -@@ -1065,9 +1185,19 @@ ThinBackend lto::createInProcessThinBackend(unsigned ParallelismLevel) { - return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex, - const StringMap &ModuleToDefinedGVSummaries, - AddStreamFn AddStream, NativeObjectCache Cache) { -- return llvm::make_unique( -+ return llvm::make_unique>( -+ Conf, CombinedIndex, ParallelismLevel, ModuleToDefinedGVSummaries, -+ AddStream, Cache); -+ }; -+} -+ThinBackend lto::createInProcessThinBackendNoThread(unsigned ParallelismLevel) { -+ return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex, -+ const StringMap &ModuleToDefinedGVSummaries, -+ AddStreamFn AddStream, NativeObjectCache Cache) { -+ ThinBackendProc* Backend = new InProcessThinBackend( - Conf, CombinedIndex, ParallelismLevel, ModuleToDefinedGVSummaries, - AddStream, Cache); -+ return std::unique_ptr(Backend); - }; - } - -diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp -index 926c419e34a..2c263ed86a9 100644 ---- a/llvm/lib/LTO/LTOBackend.cpp -+++ b/llvm/lib/LTO/LTOBackend.cpp -@@ -333,10 +333,11 @@ void codegen(Config &Conf, TargetMachine *TM, AddStreamFn AddStream, - DwoOut->keep(); - } - --void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream, -+template -+static void splitCodeGen_(Config &C, TargetMachine *TM, AddStreamFn AddStream, - unsigned ParallelCodeGenParallelismLevel, - std::unique_ptr Mod) { -- ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel); -+ ThreadPoolEngine CodegenThreadPool(ParallelCodeGenParallelismLevel); - unsigned ThreadCount = 0; - const Target *T = &TM->getTarget(); - -@@ -380,6 +381,17 @@ void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream, - // can leave the function scope. - CodegenThreadPool.wait(); - } -+void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream, -+ unsigned ParallelCodeGenParallelismLevel, -+ std::unique_ptr Mod) { -+ splitCodeGen_(C, TM, AddStream, ParallelCodeGenParallelismLevel, std::move(Mod)); -+} -+ -+void splitCodeGenNoThread(Config &C, TargetMachine *TM, AddStreamFn AddStream, -+ unsigned ParallelCodeGenParallelismLevel, -+ std::unique_ptr Mod) { -+ splitCodeGen_(C, TM, AddStream, ParallelCodeGenParallelismLevel, std::move(Mod)); -+} - - Expected initAndLookupTarget(Config &C, Module &Mod) { - if (!C.OverrideTriple.empty()) -@@ -439,6 +451,38 @@ Error lto::backend(Config &C, AddStreamFn AddStream, - return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); - } - -+Error lto::backendNoThread(Config &C, AddStreamFn AddStream, -+ unsigned ParallelCodeGenParallelismLevel, -+ std::unique_ptr Mod, -+ ModuleSummaryIndex &CombinedIndex) { -+ Expected TOrErr = initAndLookupTarget(C, *Mod); -+ if (!TOrErr) -+ return TOrErr.takeError(); -+ -+ std::unique_ptr TM = createTargetMachine(C, *TOrErr, *Mod); -+ -+ // Setup optimization remarks. -+ auto DiagFileOrErr = lto::setupOptimizationRemarks( -+ Mod->getContext(), C.RemarksFilename, C.RemarksWithHotness); -+ if (!DiagFileOrErr) -+ return DiagFileOrErr.takeError(); -+ auto DiagnosticOutputFile = std::move(*DiagFileOrErr); -+ -+ if (!C.CodeGenOnly) { -+ if (!opt(C, TM.get(), 0, *Mod, /*IsThinLTO=*/false, -+ /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr)) -+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); -+ } -+ -+ if (ParallelCodeGenParallelismLevel == 1) { -+ codegen(C, TM.get(), AddStream, 0, *Mod); -+ } else { -+ splitCodeGenNoThread(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel, -+ std::move(Mod)); -+ } -+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); -+} -+ - static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals, - const ModuleSummaryIndex &Index) { - std::vector DeadGVs; -diff --git a/llvm/lib/Support/ThreadPool.cpp b/llvm/lib/Support/ThreadPool.cpp -index d0212ca1346..3d760edbcb7 100644 ---- a/llvm/lib/Support/ThreadPool.cpp -+++ b/llvm/lib/Support/ThreadPool.cpp -@@ -19,8 +19,6 @@ - - using namespace llvm; - --#if LLVM_ENABLE_THREADS -- - // Default to hardware_concurrency - ThreadPool::ThreadPool() : ThreadPool(hardware_concurrency()) {} - -@@ -107,7 +105,7 @@ ThreadPool::~ThreadPool() { - Worker.join(); - } - --#else // LLVM_ENABLE_THREADS Disabled -+#define ThreadPool SequentialThreadPool - - ThreadPool::ThreadPool() : ThreadPool(0) {} - -@@ -142,5 +140,3 @@ std::shared_future ThreadPool::asyncImpl(TaskTy Task) { - ThreadPool::~ThreadPool() { - wait(); - } -- --#endif -diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp -index 738cafa6cac..8ef75d2589c 100644 ---- a/llvm/tools/gold/gold-plugin.cpp -+++ b/llvm/tools/gold/gold-plugin.cpp -@@ -848,7 +848,7 @@ static std::unique_ptr createLTO(IndexWriteCallback OnIndexWrite, - Conf.DisableVerify = options::DisableVerify; - Conf.OptLevel = options::OptLevel; - if (options::Parallelism) -- Backend = createInProcessThinBackend(options::Parallelism); -+ Backend = createInProcessThinBackendNoThread(options::Parallelism); - if (options::thinlto_index_only) { - std::string OldPrefix, NewPrefix; - getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix); -@@ -856,6 +856,9 @@ static std::unique_ptr createLTO(IndexWriteCallback OnIndexWrite, - options::thinlto_emit_imports_files, - LinkedObjectsFile, OnIndexWrite); - } -+ if(!Backend) -+ Backend = createInProcessThinBackendNoThread(llvm::heavyweight_hardware_concurrency()); -+ - - Conf.OverrideTriple = options::triple; - Conf.DefaultTriple = sys::getDefaultTargetTriple(); -@@ -1039,7 +1042,7 @@ static std::vector, bool>> runLTO() { - if (!options::cache_dir.empty()) - Cache = check(localCache(options::cache_dir, AddBuffer)); - -- check(Lto->run(AddStream, Cache)); -+ check(Lto->runNoThread(AddStream, Cache)); - - // Write empty output files that may be expected by the distributed build - // system. --- -2.20.1 - diff --git a/SOURCES/0001-docs-Convert-remaining-command-guide-entries-from-md.patch b/SOURCES/0001-docs-Convert-remaining-command-guide-entries-from-md.patch new file mode 100644 index 0000000..91b27b2 --- /dev/null +++ b/SOURCES/0001-docs-Convert-remaining-command-guide-entries-from-md.patch @@ -0,0 +1,248 @@ +From e4e77bb8bf741f52b43b90987646f1c118914848 Mon Sep 17 00:00:00 2001 +From: Jordan Rupprecht +Date: Wed, 21 Aug 2019 18:00:17 +0000 +Subject: [PATCH] [docs] Convert remaining command guide entries from md to + rst. + +Summary: +Linking between markdown and rst files is currently not supported very well, e.g. the current llvm-addr2line docs [1] link to "llvm-symbolizer" instead of "llvm-symbolizer.html". This is weirdly broken in different ways depending on which versions of sphinx and recommonmark are being used, so workaround the bug by using rst everywhere. + +[1] http://llvm.org/docs/CommandGuide/llvm-addr2line.html + +Reviewers: jhenderson + +Reviewed By: jhenderson + +Subscribers: lebedev.ri, llvm-commits + +Tags: #llvm + +Differential Revision: https://reviews.llvm.org/D66305 + +llvm-svn: 369553 +--- + llvm/docs/CommandGuide/llvm-addr2line.md | 28 ----------------------- + llvm/docs/CommandGuide/llvm-addr2line.rst | 38 +++++++++++++++++++++++++++++++ + llvm/docs/CommandGuide/llvm-ranlib.md | 17 -------------- + llvm/docs/CommandGuide/llvm-ranlib.rst | 23 +++++++++++++++++++ + llvm/docs/CommandGuide/llvm-size.md | 10 -------- + llvm/docs/CommandGuide/llvm-size.rst | 15 ++++++++++++ + llvm/docs/CommandGuide/llvm-strings.md | 10 -------- + llvm/docs/CommandGuide/llvm-strings.rst | 15 ++++++++++++ + 8 files changed, 91 insertions(+), 65 deletions(-) + delete mode 100644 llvm/docs/CommandGuide/llvm-addr2line.md + create mode 100644 llvm/docs/CommandGuide/llvm-addr2line.rst + delete mode 100644 llvm/docs/CommandGuide/llvm-ranlib.md + create mode 100644 llvm/docs/CommandGuide/llvm-ranlib.rst + delete mode 100644 llvm/docs/CommandGuide/llvm-size.md + create mode 100644 llvm/docs/CommandGuide/llvm-size.rst + delete mode 100644 llvm/docs/CommandGuide/llvm-strings.md + create mode 100644 llvm/docs/CommandGuide/llvm-strings.rst + +diff --git a/llvm/docs/CommandGuide/llvm-addr2line.md b/llvm/docs/CommandGuide/llvm-addr2line.md +deleted file mode 100644 +index 03224c4..0000000 +--- a/llvm/docs/CommandGuide/llvm-addr2line.md ++++ /dev/null +@@ -1,28 +0,0 @@ +-# llvm-addr2line - a drop-in replacement for addr2line +- +-## SYNOPSIS +- +-**llvm-addr2line** [*options*] +- +-## DESCRIPTION +- +-**llvm-addr2line** is an alias for the [llvm-symbolizer](llvm-symbolizer) tool +-with different defaults. The goal is to make it a drop-in replacement for +-GNU's **addr2line**. +- +-Here are some of those differences: +- +-* Defaults not to print function names. Use [-f](llvm-symbolizer-opt-f) +- to enable that. +- +-* Defaults not to demangle function names. Use [-C](llvm-symbolizer-opt-C) +- to switch the demangling on. +- +-* Defaults not to print inlined frames. Use [-i](llvm-symbolizer-opt-i) +- to show inlined frames for a source code location in an inlined function. +- +-* Uses [--output-style=GNU](llvm-symbolizer-opt-output-style) by default. +- +-## SEE ALSO +- +-Refer to [llvm-symbolizer](llvm-symbolizer) for additional information. +diff --git a/llvm/docs/CommandGuide/llvm-addr2line.rst b/llvm/docs/CommandGuide/llvm-addr2line.rst +new file mode 100644 +index 0000000..08f1b69 +--- /dev/null ++++ b/llvm/docs/CommandGuide/llvm-addr2line.rst +@@ -0,0 +1,38 @@ ++llvm-addr2line - a drop-in replacement for addr2line ++==================================================== ++ ++.. program:: llvm-addr2line ++ ++SYNOPSIS ++-------- ++ ++:program:`llvm-addr2line` [*options*] ++ ++DESCRIPTION ++----------- ++ ++:program:`llvm-addr2line` is an alias for the :manpage:`llvm-symbolizer(1)` ++tool with different defaults. The goal is to make it a drop-in replacement for ++GNU's :program:`addr2line`. ++ ++Here are some of those differences: ++ ++- Defaults not to print function names. Use `-f`_ to enable that. ++ ++- Defaults not to demangle function names. Use `-C`_ to switch the ++ demangling on. ++ ++- Defaults not to print inlined frames. Use `-i`_ to show inlined ++ frames for a source code location in an inlined function. ++ ++- Uses `--output-style=GNU`_ by default. ++ ++SEE ALSO ++-------- ++ ++:manpage:`llvm-symbolizer(1)` ++ ++.. _-f: llvm-symbolizer.html#llvm-symbolizer-opt-f ++.. _-C: llvm-symbolizer.html#llvm-symbolizer-opt-c ++.. _-i: llvm-symbolizer.html#llvm-symbolizer-opt-i ++.. _--output-style=GNU: llvm-symbolizer.html#llvm-symbolizer-opt-output-style +diff --git a/llvm/docs/CommandGuide/llvm-ranlib.md b/llvm/docs/CommandGuide/llvm-ranlib.md +deleted file mode 100644 +index 4377364..0000000 +--- a/llvm/docs/CommandGuide/llvm-ranlib.md ++++ /dev/null +@@ -1,17 +0,0 @@ +-# llvm-ranlib - generates an archive index +- +-## SYNOPSIS +- +-**llvm-ranlib** [*options*] +- +-## DESCRIPTION +- +-**llvm-ranlib** is an alias for the [llvm-ar](llvm-ar.html) tool that generates +-an index for an archive. It can be used as a replacement for GNU's **ranlib** +-tool. +- +-Running **llvm-ranlib** is equivalent to running **llvm-ar s**. +- +-## SEE ALSO +- +-Refer to [llvm-ar](llvm-ar.html) for additional information. +diff --git a/llvm/docs/CommandGuide/llvm-ranlib.rst b/llvm/docs/CommandGuide/llvm-ranlib.rst +new file mode 100644 +index 0000000..314a330 +--- /dev/null ++++ b/llvm/docs/CommandGuide/llvm-ranlib.rst +@@ -0,0 +1,23 @@ ++llvm-ranlib - generates an archive index ++======================================== ++ ++.. program:: llvm-ranlib ++ ++SYNOPSIS ++-------- ++ ++:program:`llvm-ranlib` [*options*] ++ ++DESCRIPTION ++----------- ++ ++:program:`llvm-ranlib` is an alias for the :doc:`llvm-ar ` tool that ++generates an index for an archive. It can be used as a replacement for GNU’s ++:program:`ranlib` tool. ++ ++Running :program:`llvm-ranlib` is equivalent to running ``llvm-ar s``. ++ ++SEE ALSO ++-------- ++ ++:manpage:`llvm-ar(1)` +diff --git a/llvm/docs/CommandGuide/llvm-size.md b/llvm/docs/CommandGuide/llvm-size.md +deleted file mode 100644 +index 3952708..0000000 +--- a/llvm/docs/CommandGuide/llvm-size.md ++++ /dev/null +@@ -1,10 +0,0 @@ +-# llvm-size - print segment sizes +- +-## SYNOPSIS +- +-**llvm-size** [*options*] +- +-## DESCRIPTION +- +-**llvm-size** is a tool that prints segment sizes in object files. The goal is +-to make it a drop-in replacement for GNU's **size**. +diff --git a/llvm/docs/CommandGuide/llvm-size.rst b/llvm/docs/CommandGuide/llvm-size.rst +new file mode 100644 +index 0000000..0dce15c +--- /dev/null ++++ b/llvm/docs/CommandGuide/llvm-size.rst +@@ -0,0 +1,15 @@ ++llvm-size - print size information ++================================== ++ ++.. program:: llvm-size ++ ++SYNOPSIS ++-------- ++ ++:program:`llvm-size` [*options*] ++ ++DESCRIPTION ++----------- ++ ++:program:`llvm-size` is a tool that prints size information for object files. ++The goal is to make it a drop-in replacement for GNU’s :program:`size`. +diff --git a/llvm/docs/CommandGuide/llvm-strings.md b/llvm/docs/CommandGuide/llvm-strings.md +deleted file mode 100644 +index b5871c4..0000000 +--- a/llvm/docs/CommandGuide/llvm-strings.md ++++ /dev/null +@@ -1,10 +0,0 @@ +-# llvm-strings - print strings +- +-## SYNOPSIS +- +-**llvm-strings** [*options*] +- +-## DESCRIPTION +- +-**llvm-strings** is a tool that prints strings in object files. The goal is to +-make it a drop-in replacement for GNU's **size**. +diff --git a/llvm/docs/CommandGuide/llvm-strings.rst b/llvm/docs/CommandGuide/llvm-strings.rst +new file mode 100644 +index 0000000..d8ab9cb +--- /dev/null ++++ b/llvm/docs/CommandGuide/llvm-strings.rst +@@ -0,0 +1,15 @@ ++llvm-strings - print strings ++============================ ++ ++.. program:: llvm-strings ++ ++SYNOPSIS ++-------- ++ ++:program:`llvm-strings` [*options*] ++ ++DESCRIPTION ++----------- ++ ++:program:`llvm-strings` is a tool that prints strings in files. The goal is to ++make it a drop-in replacement for GNU’s :program:`strings`. +-- +1.8.3.1 + diff --git a/SOURCES/run-lit-tests b/SOURCES/run-lit-tests index a0f27d8..aed8165 100755 --- a/SOURCES/run-lit-tests +++ b/SOURCES/run-lit-tests @@ -51,8 +51,14 @@ 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 + +# llvm_obj_root is used to determine the directory the tests will run in. +# test/MC/MachO/gen-dwarf.s fails if llvm_obj_root is a parent directory +# of the source file. To workaround this, we set llvm_obj_root to a +# different directory than the one used to store the test sources. +# This also matches better how tests are run from the llvm source tree. lit -v -s $threads_arg test \ - -Dllvm_obj_root=`pwd` \ + -Dllvm_obj_root=$(mktemp -d) \ -Dllvm_test_root=`pwd`/test \ -Dllvm_unittest_bindir=$LIB_DIR/llvm \ -Dllvm_shlib_dir=$LIB_DIR diff --git a/SPECS/llvm.spec b/SPECS/llvm.spec index 90e93b0..2b90e1f 100644 --- a/SPECS/llvm.spec +++ b/SPECS/llvm.spec @@ -6,29 +6,36 @@ %bcond_with gold %endif -%global llvm_srcdir llvm-%{version}%{?rc_ver:rc%{rc_ver}}.src +%bcond_with compat_build -%global build_llvm_bindir %{buildroot}%{_bindir} %global llvm_libdir %{_libdir}/%{name} %global build_llvm_libdir %{buildroot}%{llvm_libdir} -%global maj_ver 8 +%global maj_ver 9 %global min_ver 0 %global patch_ver 1 -#%%global rc_ver 2 -#%%global compat_version 7.0.1 +#%%global rc_ver 3 +%global baserelease 4 +%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} -%global build_pkgdocdir %{buildroot}%{_pkgdocdir} - -#%%ifnarch i686 -%global enable_test_pkg 1 -#%%endif %if !0%{?rhel} # libedit-devel is a buildroot-only package in RHEL8, so we can't have a @@ -38,21 +45,36 @@ Name: %{pkg_name} Version: %{maj_ver}.%{min_ver}.%{patch_ver} -Release: 1%{?rc_ver:.rc%{rc_ver}}%{?dist} +Release: %{baserelease}%{?rc_ver:.rc%{rc_ver}}%{?dist} Summary: The Low Level Virtual Machine License: NCSA URL: http://llvm.org -Source0: https://github.com/llvm/llvm-project/releases/download/llvmorg-%{version}%{?rc_ver:-%{rc_ver}}/%{llvm_srcdir}.tar.xz +Source0: http://%{?rc_ver:pre}releases.llvm.org/%{version}/%{?rc_ver:rc%{rc_ver}}/llvm-%{version}%{?rc_ver:rc%{rc_ver}}.src.tar.xz +%if %{without compat_build} Source1: run-lit-tests Source2: lit.fedora.cfg.py -%if %{defined compat_version} -Source100: http://llvm.org/releases/%{compat_version}/%{name}-%{compat_version}.src.tar.xz %endif -Patch2: 0001-Selectively-disable-threading-from-gold.patch -Patch3: 0001-Filter-out-cxxflags-not-supported-by-clang.patch -Patch4: 0001-Deactivate-markdown-doc.patch +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 +Patch3: 0001-CMake-Split-test-binary-exports-into-their-own-expor.patch + +# RHEL-specific patches. +Patch101: 0001-Deactivate-markdown-doc.patch +# Patches to convert md files to rst since we don't have the md parser in RHEL. +Patch102: 0001-Docs-llvm-strip-Add-help-text-to-llvm-strip-rst-doc.patch +Patch103: 0001-docs-Convert-remaining-command-guide-entries-from-md.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 + +# Fix Rust codegen bug, https://github.com/rust-lang/rust/issues/69225 +Patch7: 0001-Revert-SCEV-add-no-wrap-flag-for-SCEVAddExpr.patch BuildRequires: gcc BuildRequires: gcc-c++ @@ -62,7 +84,9 @@ BuildRequires: zlib-devel BuildRequires: libffi-devel BuildRequires: ncurses-devel BuildRequires: python3-sphinx -#BuildRequires: python3-recommonmark +%if !0%{?rhel} +BuildRequires: python3-recommonmark +%endif BuildRequires: multilib-rpm-config %if %{with gold} BuildRequires: binutils-devel @@ -80,6 +104,8 @@ 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 @@ -89,6 +115,7 @@ tools as well as libraries with equivalent functionality. %package devel Summary: Libraries and header files for LLVM Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: %{name}-libs%{?_isa} = %{version}-%{release} # The installed LLVM cmake files will add -ledit to the linker flags for any # app that requires the libLLVMLineEditor, so we need to make sure # libedit-devel is available. @@ -98,6 +125,8 @@ 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. @@ -123,11 +152,12 @@ Conflicts: %{name}-devel < 8 %description static Static libraries for the LLVM compiler infrastructure. -%if 0%{?enable_test_pkg} +%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 @@ -137,29 +167,21 @@ Requires: %{name}-devel%{?_isa} = %{version}-%{release} Requires: gcc Requires: findutils +Provides: llvm-test(major) = %{maj_ver} + %description test LLVM regression tests. -%endif - %package googletest Summary: LLVM's modified googletest sources %description googletest LLVM's modified googletest sources. -%prep -%if %{defined compat_version} -%setup -T -q -b 100 -n llvm-%{compat_version}.src - -%setup -q -n llvm-%{version}%{?rc_ver:rc%{rc_ver}}.src -%patch2 -p2 -%patch3 -p2 -%patch4 -p2 +%endif -%else +%prep %autosetup -n llvm-%{version}%{?rc_ver:rc%{rc_ver}}.src -p2 -%endif pathfix.py -i %{__python3} -pn \ test/BugPoint/compile-custom.ll.py \ @@ -185,15 +207,17 @@ cd _build -DLLVM_PARALLEL_LINK_JOBS=1 \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_INSTALL_RPATH=";" \ -%ifarch s390 s390x %{arm} %ix86 +%ifarch s390 %{arm} %ix86 -DCMAKE_C_FLAGS_RELWITHDEBINFO="%{optflags} -DNDEBUG" \ -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="%{optflags} -DNDEBUG" \ %endif +%if %{without compat_build} %if 0%{?__isa_bits} == 64 -DLLVM_LIBDIR_SUFFIX=64 \ %else -DLLVM_LIBDIR_SUFFIX= \ %endif +%endif \ -DLLVM_TARGETS_TO_BUILD="X86;AMDGPU;PowerPC;NVPTX;SystemZ;AArch64;ARM;Mips;BPF" \ -DLLVM_ENABLE_LIBCXX:BOOL=OFF \ @@ -216,9 +240,13 @@ cd _build -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=%{build_llvm_bindir} \ + -DLLVM_UTILS_INSTALL_DIR:PATH=%{_bindir} \ -DLLVM_TOOLS_INSTALL_DIR:PATH=bin \ +%endif \ -DLLVM_INCLUDE_DOCS:BOOL=ON \ -DLLVM_BUILD_DOCS:BOOL=ON \ @@ -232,54 +260,35 @@ cd _build -DLLVM_INSTALL_TOOLCHAIN_ONLY:BOOL=OFF \ \ -DSPHINX_WARNINGS_AS_ERRORS=OFF \ - -DCMAKE_INSTALL_PREFIX=%{build_install_prefix} \ - -DLLVM_INSTALL_SPHINX_HTML_DIR=%{build_pkgdocdir}/html \ + -DLLVM_INSTALL_SPHINX_HTML_DIR=%{_pkgdocdir}/html \ -DSPHINX_EXECUTABLE=%{_bindir}/sphinx-build-3 -ninja -v -j2 - -%if %{defined compat_version} -mkdir ../compat-build -cd ../compat-build -%cmake ../../%{name}-%{compat_version}.src \ - -G Ninja \ - -DBUILD_SHARED_LIBS=OFF \ - -DCMAKE_BUILD_TYPE=Release \ - -DLLVM_TARGETS_TO_BUILD="X86;AMDGPU;PowerPC;NVPTX;SystemZ;AArch64;ARM;Mips;BPF" \ - -DLLVM_ENABLE_RTTI:BOOL=ON \ - -DLLVM_ENABLE_ZLIB:BOOL=ON \ - -DLLVM_ENABLE_FFI:BOOL=ON \ - -DLLVM_BUILD_LLVM_DYLIB=ON -ninja -v LLVM - -# Remove files we don't need to save disk space -mv lib/libLLVM-`echo %{compat_version} | cut -f1 -d .`.so .. -rm -Rf * -%endif +# 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 -C _build -v install +%ninja_install -C _build +%if %{without compat_build} mkdir -p %{buildroot}/%{_bindir} mv %{buildroot}/%{_bindir}/llvm-config %{buildroot}/%{_bindir}/llvm-config-%{__isa_bits} -ln -s llvm-config-%{__isa_bits} %{buildroot}/%{_bindir}/llvm-config # 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 -%if 0%{?enable_test_pkg} -%global test_binaries FileCheck count lli-child-target llvm-PerfectShuffle llvm-isel-fuzzer llvm-opt-fuzzer not yaml-bench +%global test_binaries llvm-isel-fuzzer llvm-opt-fuzzer for f in %{test_binaries} do - install -m 0755 ./_build/bin/$f %{build_llvm_bindir} + install -m 0755 ./_build/bin/$f %{buildroot}%{_bindir} done -%endif - %multilib_fix_c_header --file %{_includedir}/llvm/Config/llvm-config.h @@ -302,7 +311,6 @@ install -d %{install_srcdir} install -d %{install_srcdir}/utils/ cp -R utils/unittest %{install_srcdir}/utils/ -%if 0%{?enable_test_pkg} # 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} @@ -337,81 +345,142 @@ install -m 0755 %{build_libdir}/LLVMHello.so %{buildroot}%{_libdir} 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/ -%endif +%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 `ls %{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 -%if %{defined compat_version} -cd compat-build -install ../libLLVM-`echo %{compat_version} | cut -f1 -d .`.so %{buildroot}%{_libdir} %endif -%check -# TODO: Fix arm +%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-%{__isa_bits} + %{_sbindir}/update-alternatives --remove llvm-config %{_bindir}/llvm-config fi +%endif %files -%exclude %{_bindir}/llvm-config* +%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 -%{_bindir}/* - -%exclude %{_mandir}/man1/llvm-config* -%{_mandir}/man1/* - %{_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* -%{pkg_libdir}/libOptRemarks.so* -%if %{defined compat_version} -%{_libdir}/libLLVM-7.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 -%{_bindir}/llvm-config* +%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} -%if 0%{?enable_test_pkg} %files test %{_libexecdir}/tests/llvm/ %{llvm_libdir}/unittests/ @@ -426,14 +495,42 @@ fi %{_bindir}/llvm-opt-fuzzer %{_libdir}/BugpointPasses.so %{_libdir}/LLVMHello.so -%endif +%{_libdir}/cmake/llvm/LLVMTestExports.cmake %files googletest %{_datadir}/llvm/src/utils %{_libdir}/libLLVMTestingSupport.a +%endif %changelog +* Thu Feb 27 2020 Josh Stone - 9.0.1-4 +- Fix a codegen bug for Rust + +* Fri Jan 17 2020 Tom Stellard - 9.0.1-3 +- Add explicit Requires from sub-packages to llvm-libs + +* Fri Jan 10 2020 Tom Stellard - 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 + +* Wed Oct 30 2019 Tom Stellard - 9.0.0-5 +- Remove work-around for threading issue in gold + +* Wed Oct 30 2019 Tom Stellard - 9.0.0-4 +- Build libLLVM.so first to avoid OOM errors + +* Tue Oct 01 2019 Tom Stellard - 9.0.0-3 +- Adjust run-lit-tests script to better match in tree testing + +* Mon Sep 30 2019 Tom Stellard - 9.0.0-2 +- Limit number of build threads using -l option for ninja + +* Thu Sep 26 2019 Tom Stellard - 9.0.0-1 +- 9.0.0 Release + * Thu Aug 1 2019 sguelton@redhat.com - 8.0.1-1 - 8.0.1 release