mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-11 18:36:55 +00:00
[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
This commit is contained in:
parent
748dac7389
commit
37d24a696b
@ -65,6 +65,7 @@
|
||||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
#include <stack>
|
||||
|
||||
#define DEBUG_TYPE "bpf-abstract-member-access"
|
||||
|
||||
@ -106,18 +107,24 @@ private:
|
||||
|
||||
bool doTransformation(Module &M);
|
||||
|
||||
void traceAICall(CallInst *Call, uint32_t Kind);
|
||||
void traceBitCast(BitCastInst *BitCast, CallInst *Parent, uint32_t Kind);
|
||||
void traceGEP(GetElementPtrInst *GEP, CallInst *Parent, uint32_t Kind);
|
||||
void traceAICall(CallInst *Call, uint32_t Kind, const MDNode *ParentMeta,
|
||||
uint32_t ParentAI);
|
||||
void traceBitCast(BitCastInst *BitCast, CallInst *Parent, uint32_t Kind,
|
||||
const MDNode *ParentMeta, uint32_t ParentAI);
|
||||
void traceGEP(GetElementPtrInst *GEP, CallInst *Parent, uint32_t Kind,
|
||||
const MDNode *ParentMeta, uint32_t ParentAI);
|
||||
void collectAICallChains(Module &M, Function &F);
|
||||
|
||||
bool IsPreserveDIAccessIndexCall(const CallInst *Call, uint32_t &Kind);
|
||||
bool IsPreserveDIAccessIndexCall(const CallInst *Call, uint32_t &Kind,
|
||||
const MDNode *&TypeMeta, uint32_t &AccessIndex);
|
||||
bool IsValidAIChain(const MDNode *ParentMeta, uint32_t ParentAI,
|
||||
const MDNode *ChildMeta);
|
||||
bool removePreserveAccessIndexIntrinsic(Module &M);
|
||||
void replaceWithGEP(std::vector<CallInst *> &CallList,
|
||||
uint32_t NumOfZerosIndex, uint32_t DIIndex);
|
||||
|
||||
Value *computeBaseAndAccessKey(CallInst *Call, std::string &AccessKey,
|
||||
uint32_t Kind, MDNode *&TypeMeta);
|
||||
uint32_t Kind, MDNode *&BaseMeta);
|
||||
bool getAccessIndex(const Value *IndexValue, uint64_t &AccessIndex);
|
||||
bool transformGEPChain(Module &M, CallInst *Call, uint32_t Kind);
|
||||
};
|
||||
@ -141,9 +148,53 @@ bool BPFAbstractMemberAccess::runOnModule(Module &M) {
|
||||
return doTransformation(M);
|
||||
}
|
||||
|
||||
static bool SkipDIDerivedTag(unsigned Tag) {
|
||||
if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type &&
|
||||
Tag != dwarf::DW_TAG_volatile_type &&
|
||||
Tag != dwarf::DW_TAG_restrict_type &&
|
||||
Tag != dwarf::DW_TAG_member)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static DIType * stripQualifiers(DIType *Ty) {
|
||||
while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
|
||||
if (!SkipDIDerivedTag(DTy->getTag()))
|
||||
break;
|
||||
Ty = DTy->getBaseType();
|
||||
}
|
||||
return Ty;
|
||||
}
|
||||
|
||||
static const DIType * stripQualifiers(const DIType *Ty) {
|
||||
while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
|
||||
if (!SkipDIDerivedTag(DTy->getTag()))
|
||||
break;
|
||||
Ty = DTy->getBaseType();
|
||||
}
|
||||
return Ty;
|
||||
}
|
||||
|
||||
static uint32_t calcArraySize(const DICompositeType *CTy, uint32_t StartDim) {
|
||||
DINodeArray Elements = CTy->getElements();
|
||||
uint32_t DimSize = 1;
|
||||
for (uint32_t I = StartDim; I < Elements.size(); ++I) {
|
||||
if (auto *Element = dyn_cast_or_null<DINode>(Elements[I]))
|
||||
if (Element->getTag() == dwarf::DW_TAG_subrange_type) {
|
||||
const DISubrange *SR = cast<DISubrange>(Element);
|
||||
auto *CI = SR->getCount().dyn_cast<ConstantInt *>();
|
||||
DimSize *= CI->getSExtValue();
|
||||
}
|
||||
}
|
||||
|
||||
return DimSize;
|
||||
}
|
||||
|
||||
/// Check whether a call is a preserve_*_access_index intrinsic call or not.
|
||||
bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
|
||||
uint32_t &Kind) {
|
||||
uint32_t &Kind,
|
||||
const MDNode *&TypeMeta,
|
||||
uint32_t &AccessIndex) {
|
||||
if (!Call)
|
||||
return false;
|
||||
|
||||
@ -152,14 +203,29 @@ bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
|
||||
return false;
|
||||
if (GV->getName().startswith("llvm.preserve.array.access.index")) {
|
||||
Kind = BPFPreserveArrayAI;
|
||||
TypeMeta = Call->getMetadata(LLVMContext::MD_preserve_access_index);
|
||||
if (!TypeMeta)
|
||||
report_fatal_error("Missing metadata for llvm.preserve.array.access.index intrinsic");
|
||||
AccessIndex = cast<ConstantInt>(Call->getArgOperand(2))
|
||||
->getZExtValue();
|
||||
return true;
|
||||
}
|
||||
if (GV->getName().startswith("llvm.preserve.union.access.index")) {
|
||||
Kind = BPFPreserveUnionAI;
|
||||
TypeMeta = Call->getMetadata(LLVMContext::MD_preserve_access_index);
|
||||
if (!TypeMeta)
|
||||
report_fatal_error("Missing metadata for llvm.preserve.union.access.index intrinsic");
|
||||
AccessIndex = cast<ConstantInt>(Call->getArgOperand(1))
|
||||
->getZExtValue();
|
||||
return true;
|
||||
}
|
||||
if (GV->getName().startswith("llvm.preserve.struct.access.index")) {
|
||||
Kind = BPFPreserveStructAI;
|
||||
TypeMeta = Call->getMetadata(LLVMContext::MD_preserve_access_index);
|
||||
if (!TypeMeta)
|
||||
report_fatal_error("Missing metadata for llvm.preserve.struct.access.index intrinsic");
|
||||
AccessIndex = cast<ConstantInt>(Call->getArgOperand(2))
|
||||
->getZExtValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -200,7 +266,9 @@ bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Module &M) {
|
||||
for (auto &I : BB) {
|
||||
auto *Call = dyn_cast<CallInst>(&I);
|
||||
uint32_t Kind;
|
||||
if (!IsPreserveDIAccessIndexCall(Call, Kind))
|
||||
const MDNode *TypeMeta;
|
||||
uint32_t AccessIndex;
|
||||
if (!IsPreserveDIAccessIndexCall(Call, Kind, TypeMeta, AccessIndex))
|
||||
continue;
|
||||
|
||||
Found = true;
|
||||
@ -232,25 +300,79 @@ bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Module &M) {
|
||||
return Found;
|
||||
}
|
||||
|
||||
void BPFAbstractMemberAccess::traceAICall(CallInst *Call, uint32_t Kind) {
|
||||
/// Check whether the access index chain is valid. We check
|
||||
/// here because there may be type casts between two
|
||||
/// access indexes. We want to ensure memory access still valid.
|
||||
bool BPFAbstractMemberAccess::IsValidAIChain(const MDNode *ParentType,
|
||||
uint32_t ParentAI,
|
||||
const MDNode *ChildType) {
|
||||
const DIType *PType = stripQualifiers(cast<DIType>(ParentType));
|
||||
const DIType *CType = stripQualifiers(cast<DIType>(ChildType));
|
||||
|
||||
// Child is a derived/pointer type, which is due to type casting.
|
||||
// Pointer type cannot be in the middle of chain.
|
||||
if (const auto *PtrTy = dyn_cast<DIDerivedType>(CType))
|
||||
return false;
|
||||
|
||||
// Parent is a pointer type.
|
||||
if (const auto *PtrTy = dyn_cast<DIDerivedType>(PType)) {
|
||||
if (PtrTy->getTag() != dwarf::DW_TAG_pointer_type)
|
||||
return false;
|
||||
return stripQualifiers(PtrTy->getBaseType()) == CType;
|
||||
}
|
||||
|
||||
// Otherwise, struct/union/array types
|
||||
const auto *PTy = dyn_cast<DICompositeType>(PType);
|
||||
const auto *CTy = dyn_cast<DICompositeType>(CType);
|
||||
assert(PTy && CTy && "ParentType or ChildType is null or not composite");
|
||||
|
||||
uint32_t PTyTag = PTy->getTag();
|
||||
assert(PTyTag == dwarf::DW_TAG_array_type ||
|
||||
PTyTag == dwarf::DW_TAG_structure_type ||
|
||||
PTyTag == dwarf::DW_TAG_union_type);
|
||||
|
||||
uint32_t CTyTag = CTy->getTag();
|
||||
assert(CTyTag == dwarf::DW_TAG_array_type ||
|
||||
CTyTag == dwarf::DW_TAG_structure_type ||
|
||||
CTyTag == dwarf::DW_TAG_union_type);
|
||||
|
||||
// Multi dimensional arrays, base element should be the same
|
||||
if (PTyTag == dwarf::DW_TAG_array_type && PTyTag == CTyTag)
|
||||
return PTy->getBaseType() == CTy->getBaseType();
|
||||
|
||||
DIType *Ty;
|
||||
if (PTyTag == dwarf::DW_TAG_array_type)
|
||||
Ty = PTy->getBaseType();
|
||||
else
|
||||
Ty = dyn_cast<DIType>(PTy->getElements()[ParentAI]);
|
||||
|
||||
return dyn_cast<DICompositeType>(stripQualifiers(Ty)) == CTy;
|
||||
}
|
||||
|
||||
void BPFAbstractMemberAccess::traceAICall(CallInst *Call, uint32_t Kind,
|
||||
const MDNode *ParentMeta,
|
||||
uint32_t ParentAI) {
|
||||
for (User *U : Call->users()) {
|
||||
Instruction *Inst = dyn_cast<Instruction>(U);
|
||||
if (!Inst)
|
||||
continue;
|
||||
|
||||
if (auto *BI = dyn_cast<BitCastInst>(Inst)) {
|
||||
traceBitCast(BI, Call, Kind);
|
||||
traceBitCast(BI, Call, Kind, ParentMeta, ParentAI);
|
||||
} else if (auto *CI = dyn_cast<CallInst>(Inst)) {
|
||||
uint32_t CIKind;
|
||||
if (IsPreserveDIAccessIndexCall(CI, CIKind)) {
|
||||
const MDNode *ChildMeta;
|
||||
uint32_t ChildAI;
|
||||
if (IsPreserveDIAccessIndexCall(CI, CIKind, ChildMeta, ChildAI) &&
|
||||
IsValidAIChain(ParentMeta, ParentAI, ChildMeta)) {
|
||||
AIChain[CI] = std::make_pair(Call, Kind);
|
||||
traceAICall(CI, CIKind);
|
||||
traceAICall(CI, CIKind, ChildMeta, ChildAI);
|
||||
} else {
|
||||
BaseAICalls[Call] = Kind;
|
||||
}
|
||||
} else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
|
||||
if (GI->hasAllZeroIndices())
|
||||
traceGEP(GI, Call, Kind);
|
||||
traceGEP(GI, Call, Kind, ParentMeta, ParentAI);
|
||||
else
|
||||
BaseAICalls[Call] = Kind;
|
||||
}
|
||||
@ -258,25 +380,30 @@ void BPFAbstractMemberAccess::traceAICall(CallInst *Call, uint32_t Kind) {
|
||||
}
|
||||
|
||||
void BPFAbstractMemberAccess::traceBitCast(BitCastInst *BitCast,
|
||||
CallInst *Parent, uint32_t Kind) {
|
||||
CallInst *Parent, uint32_t Kind,
|
||||
const MDNode *ParentMeta,
|
||||
uint32_t ParentAI) {
|
||||
for (User *U : BitCast->users()) {
|
||||
Instruction *Inst = dyn_cast<Instruction>(U);
|
||||
if (!Inst)
|
||||
continue;
|
||||
|
||||
if (auto *BI = dyn_cast<BitCastInst>(Inst)) {
|
||||
traceBitCast(BI, Parent, Kind);
|
||||
traceBitCast(BI, Parent, Kind, ParentMeta, ParentAI);
|
||||
} else if (auto *CI = dyn_cast<CallInst>(Inst)) {
|
||||
uint32_t CIKind;
|
||||
if (IsPreserveDIAccessIndexCall(CI, CIKind)) {
|
||||
const MDNode *ChildMeta;
|
||||
uint32_t ChildAI;
|
||||
if (IsPreserveDIAccessIndexCall(CI, CIKind, ChildMeta, ChildAI) &&
|
||||
IsValidAIChain(ParentMeta, ParentAI, ChildMeta)) {
|
||||
AIChain[CI] = std::make_pair(Parent, Kind);
|
||||
traceAICall(CI, CIKind);
|
||||
traceAICall(CI, CIKind, ChildMeta, ChildAI);
|
||||
} else {
|
||||
BaseAICalls[Parent] = Kind;
|
||||
}
|
||||
} else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
|
||||
if (GI->hasAllZeroIndices())
|
||||
traceGEP(GI, Parent, Kind);
|
||||
traceGEP(GI, Parent, Kind, ParentMeta, ParentAI);
|
||||
else
|
||||
BaseAICalls[Parent] = Kind;
|
||||
}
|
||||
@ -284,25 +411,29 @@ void BPFAbstractMemberAccess::traceBitCast(BitCastInst *BitCast,
|
||||
}
|
||||
|
||||
void BPFAbstractMemberAccess::traceGEP(GetElementPtrInst *GEP, CallInst *Parent,
|
||||
uint32_t Kind) {
|
||||
uint32_t Kind, const MDNode *ParentMeta,
|
||||
uint32_t ParentAI) {
|
||||
for (User *U : GEP->users()) {
|
||||
Instruction *Inst = dyn_cast<Instruction>(U);
|
||||
if (!Inst)
|
||||
continue;
|
||||
|
||||
if (auto *BI = dyn_cast<BitCastInst>(Inst)) {
|
||||
traceBitCast(BI, Parent, Kind);
|
||||
traceBitCast(BI, Parent, Kind, ParentMeta, ParentAI);
|
||||
} else if (auto *CI = dyn_cast<CallInst>(Inst)) {
|
||||
uint32_t CIKind;
|
||||
if (IsPreserveDIAccessIndexCall(CI, CIKind)) {
|
||||
const MDNode *ChildMeta;
|
||||
uint32_t ChildAI;
|
||||
if (IsPreserveDIAccessIndexCall(CI, CIKind, ChildMeta, ChildAI) &&
|
||||
IsValidAIChain(ParentMeta, ParentAI, ChildMeta)) {
|
||||
AIChain[CI] = std::make_pair(Parent, Kind);
|
||||
traceAICall(CI, CIKind);
|
||||
traceAICall(CI, CIKind, ChildMeta, ChildAI);
|
||||
} else {
|
||||
BaseAICalls[Parent] = Kind;
|
||||
}
|
||||
} else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
|
||||
if (GI->hasAllZeroIndices())
|
||||
traceGEP(GI, Parent, Kind);
|
||||
traceGEP(GI, Parent, Kind, ParentMeta, ParentAI);
|
||||
else
|
||||
BaseAICalls[Parent] = Kind;
|
||||
}
|
||||
@ -316,12 +447,14 @@ void BPFAbstractMemberAccess::collectAICallChains(Module &M, Function &F) {
|
||||
for (auto &BB : F)
|
||||
for (auto &I : BB) {
|
||||
uint32_t Kind;
|
||||
const MDNode *TypeMeta;
|
||||
uint32_t AccessIndex;
|
||||
auto *Call = dyn_cast<CallInst>(&I);
|
||||
if (!IsPreserveDIAccessIndexCall(Call, Kind) ||
|
||||
if (!IsPreserveDIAccessIndexCall(Call, Kind, TypeMeta, AccessIndex) ||
|
||||
AIChain.find(Call) != AIChain.end())
|
||||
continue;
|
||||
|
||||
traceAICall(Call, Kind);
|
||||
traceAICall(Call, Kind, TypeMeta, AccessIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -344,62 +477,131 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call,
|
||||
uint32_t Kind,
|
||||
MDNode *&TypeMeta) {
|
||||
Value *Base = nullptr;
|
||||
std::vector<uint64_t> AccessIndices;
|
||||
uint64_t TypeNameIndex = 0;
|
||||
std::string LastTypeName;
|
||||
std::string TypeName;
|
||||
std::stack<std::pair<CallInst *, uint32_t>> CallStack;
|
||||
|
||||
// Put the access chain into a stack with the top as the head of the chain.
|
||||
while (Call) {
|
||||
// Base of original corresponding GEP
|
||||
Base = Call->getArgOperand(0);
|
||||
CallStack.push(std::make_pair(Call, Kind));
|
||||
Kind = AIChain[Call].second;
|
||||
Call = AIChain[Call].first;
|
||||
}
|
||||
|
||||
// Type Name
|
||||
std::string TypeName;
|
||||
MDNode *MDN;
|
||||
// The access offset from the base of the head of chain is also
|
||||
// calculated here as all debuginfo types are available.
|
||||
|
||||
// Get type name and calculate the first index.
|
||||
// We only want to get type name from structure or union.
|
||||
// If user wants a relocation like
|
||||
// int *p; ... __builtin_preserve_access_index(&p[4]) ...
|
||||
// or
|
||||
// int a[10][20]; ... __builtin_preserve_access_index(&a[2][3]) ...
|
||||
// we will skip them.
|
||||
uint32_t FirstIndex = 0;
|
||||
uint32_t AccessOffset = 0;
|
||||
while (CallStack.size()) {
|
||||
auto StackElem = CallStack.top();
|
||||
Call = StackElem.first;
|
||||
Kind = StackElem.second;
|
||||
|
||||
if (!Base)
|
||||
Base = Call->getArgOperand(0);
|
||||
|
||||
MDNode *MDN = Call->getMetadata(LLVMContext::MD_preserve_access_index);
|
||||
DIType *Ty = stripQualifiers(cast<DIType>(MDN));
|
||||
if (Kind == BPFPreserveUnionAI || Kind == BPFPreserveStructAI) {
|
||||
MDN = Call->getMetadata(LLVMContext::MD_preserve_access_index);
|
||||
if (!MDN)
|
||||
return nullptr;
|
||||
|
||||
DIType *Ty = dyn_cast<DIType>(MDN);
|
||||
if (!Ty)
|
||||
return nullptr;
|
||||
|
||||
// struct or union type
|
||||
TypeName = Ty->getName();
|
||||
TypeMeta = Ty;
|
||||
AccessOffset += FirstIndex * Ty->getSizeInBits() >> 3;
|
||||
break;
|
||||
}
|
||||
|
||||
// Array entries will always be consumed for accumulative initial index.
|
||||
CallStack.pop();
|
||||
|
||||
// BPFPreserveArrayAI
|
||||
uint64_t AccessIndex;
|
||||
if (!getAccessIndex(Call->getArgOperand(2), AccessIndex))
|
||||
return nullptr;
|
||||
|
||||
DIType *BaseTy = nullptr;
|
||||
bool CheckElemType = false;
|
||||
if (const auto *CTy = dyn_cast<DICompositeType>(Ty)) {
|
||||
// array type
|
||||
assert(CTy->getTag() == dwarf::DW_TAG_array_type);
|
||||
|
||||
|
||||
FirstIndex += AccessIndex * calcArraySize(CTy, 1);
|
||||
BaseTy = stripQualifiers(CTy->getBaseType());
|
||||
CheckElemType = CTy->getElements().size() == 1;
|
||||
} else {
|
||||
// pointer type
|
||||
auto *DTy = cast<DIDerivedType>(Ty);
|
||||
assert(DTy->getTag() == dwarf::DW_TAG_pointer_type);
|
||||
|
||||
BaseTy = stripQualifiers(DTy->getBaseType());
|
||||
CTy = dyn_cast<DICompositeType>(BaseTy);
|
||||
if (!CTy) {
|
||||
CheckElemType = true;
|
||||
} else if (CTy->getTag() != dwarf::DW_TAG_array_type) {
|
||||
FirstIndex += AccessIndex;
|
||||
CheckElemType = true;
|
||||
} else {
|
||||
FirstIndex += AccessIndex * calcArraySize(CTy, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (CheckElemType) {
|
||||
auto *CTy = dyn_cast<DICompositeType>(BaseTy);
|
||||
if (!CTy)
|
||||
return nullptr;
|
||||
|
||||
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;
|
||||
AccessKey += ":" + std::to_string(AccessIndex);
|
||||
|
||||
AccessIndices.push_back(AccessIndex);
|
||||
if (TypeName.size()) {
|
||||
TypeNameIndex = AccessIndices.size() - 1;
|
||||
LastTypeName = TypeName;
|
||||
TypeMeta = MDN;
|
||||
MDNode *MDN = Call->getMetadata(LLVMContext::MD_preserve_access_index);
|
||||
// At this stage, it cannot be pointer type.
|
||||
auto *CTy = cast<DICompositeType>(stripQualifiers(cast<DIType>(MDN)));
|
||||
uint32_t Tag = CTy->getTag();
|
||||
if (Tag == dwarf::DW_TAG_structure_type) {
|
||||
auto *MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]);
|
||||
AccessOffset += MemberTy->getOffsetInBits() >> 3;
|
||||
} else if (Tag == dwarf::DW_TAG_array_type) {
|
||||
auto *EltTy = stripQualifiers(CTy->getBaseType());
|
||||
AccessOffset += AccessIndex * calcArraySize(CTy, 1) *
|
||||
EltTy->getSizeInBits() >> 3;
|
||||
}
|
||||
|
||||
Kind = AIChain[Call].second;
|
||||
Call = AIChain[Call].first;
|
||||
}
|
||||
|
||||
// The intial type name is required.
|
||||
// FIXME: if the initial type access is an array index, e.g.,
|
||||
// &a[3].b.c, only one dimentional array is supported.
|
||||
if (!LastTypeName.size() || AccessIndices.size() > TypeNameIndex + 2)
|
||||
return nullptr;
|
||||
|
||||
// Construct the type string AccessKey.
|
||||
for (unsigned I = 0; I < AccessIndices.size(); ++I)
|
||||
AccessKey = std::to_string(AccessIndices[I]) + ":" + AccessKey;
|
||||
|
||||
if (TypeNameIndex == AccessIndices.size() - 1)
|
||||
AccessKey = "0:" + AccessKey;
|
||||
|
||||
// Access key is the type name + access string, uniquely identifying
|
||||
// one kernel memory access.
|
||||
AccessKey = LastTypeName + ":" + AccessKey;
|
||||
AccessKey = TypeName + ":" + std::to_string(AccessOffset) + "$" + AccessKey;
|
||||
|
||||
return Base;
|
||||
}
|
||||
@ -409,7 +611,7 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call,
|
||||
bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call,
|
||||
uint32_t Kind) {
|
||||
std::string AccessKey;
|
||||
MDNode *TypeMeta = nullptr;
|
||||
MDNode *TypeMeta;
|
||||
Value *Base =
|
||||
computeBaseAndAccessKey(Call, AccessKey, Kind, TypeMeta);
|
||||
if (!Base)
|
||||
@ -419,7 +621,7 @@ bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call,
|
||||
// For any original GEP Call and Base %2 like
|
||||
// %4 = bitcast %struct.net_device** %dev1 to i64*
|
||||
// it is transformed to:
|
||||
// %6 = load __BTF_0:sk_buff:0:0:2:0:
|
||||
// %6 = load sk_buff:50:$0:0:0:2:0
|
||||
// %7 = bitcast %struct.sk_buff* %2 to i8*
|
||||
// %8 = getelementptr i8, i8* %7, %6
|
||||
// %9 = bitcast i8* %8 to i64*
|
||||
@ -432,9 +634,7 @@ bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call,
|
||||
GV = new GlobalVariable(M, Type::getInt64Ty(BB->getContext()), false,
|
||||
GlobalVariable::ExternalLinkage, NULL, AccessKey);
|
||||
GV->addAttribute(BPFCoreSharedInfo::AmaAttr);
|
||||
// Set the metadata (debuginfo types) for the global.
|
||||
if (TypeMeta)
|
||||
GV->setMetadata(LLVMContext::MD_preserve_access_index, TypeMeta);
|
||||
GV->setMetadata(LLVMContext::MD_preserve_access_index, TypeMeta);
|
||||
GEPGlobals[AccessKey] = GV;
|
||||
} else {
|
||||
GV = GEPGlobals[AccessKey];
|
||||
|
@ -30,18 +30,6 @@ static const char *BTFKindStr[] = {
|
||||
#include "BTF.def"
|
||||
};
|
||||
|
||||
static const DIType * stripQualifiers(const DIType *Ty) {
|
||||
while (const auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
|
||||
unsigned Tag = DTy->getTag();
|
||||
if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type &&
|
||||
Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_restrict_type)
|
||||
break;
|
||||
Ty = DTy->getBaseType();
|
||||
}
|
||||
|
||||
return Ty;
|
||||
}
|
||||
|
||||
/// Emit a BTF common type.
|
||||
void BTFTypeBase::emitType(MCStreamer &OS) {
|
||||
OS.AddComment(std::string(BTFKindStr[Kind]) + "(id = " + std::to_string(Id) +
|
||||
@ -196,9 +184,7 @@ void BTFTypeEnum::emitType(MCStreamer &OS) {
|
||||
}
|
||||
}
|
||||
|
||||
BTFTypeArray::BTFTypeArray(const DIType *Ty, uint32_t ElemTypeId,
|
||||
uint32_t ElemSize, uint32_t NumElems)
|
||||
: ElemTyNoQual(Ty), ElemSize(ElemSize) {
|
||||
BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems) {
|
||||
Kind = BTF::BTF_KIND_ARRAY;
|
||||
BTFType.NameOff = 0;
|
||||
BTFType.Info = Kind << 24;
|
||||
@ -219,9 +205,6 @@ void BTFTypeArray::completeType(BTFDebug &BDebug) {
|
||||
// created during initial type traversal. Just
|
||||
// retrieve that type id.
|
||||
ArrayInfo.IndexType = BDebug.getArrayIndexTypeId();
|
||||
|
||||
ElemTypeNoQual = ElemTyNoQual ? BDebug.getTypeId(ElemTyNoQual)
|
||||
: ArrayInfo.ElemType;
|
||||
}
|
||||
|
||||
void BTFTypeArray::emitType(MCStreamer &OS) {
|
||||
@ -231,12 +214,6 @@ void BTFTypeArray::emitType(MCStreamer &OS) {
|
||||
OS.EmitIntValue(ArrayInfo.Nelems, 4);
|
||||
}
|
||||
|
||||
void BTFTypeArray::getLocInfo(uint32_t Loc, uint32_t &LocOffset,
|
||||
uint32_t &ElementTypeId) {
|
||||
ElementTypeId = ElemTypeNoQual;
|
||||
LocOffset = Loc * ElemSize;
|
||||
}
|
||||
|
||||
/// Represent either a struct or a union.
|
||||
BTFTypeStruct::BTFTypeStruct(const DICompositeType *STy, bool IsStruct,
|
||||
bool HasBitField, uint32_t Vlen)
|
||||
@ -268,7 +245,6 @@ void BTFTypeStruct::completeType(BTFDebug &BDebug) {
|
||||
}
|
||||
const auto *BaseTy = DDTy->getBaseType();
|
||||
BTFMember.Type = BDebug.getTypeId(BaseTy);
|
||||
MemberTypeNoQual.push_back(BDebug.getTypeId(stripQualifiers(BaseTy)));
|
||||
Members.push_back(BTFMember);
|
||||
}
|
||||
}
|
||||
@ -285,15 +261,6 @@ void BTFTypeStruct::emitType(MCStreamer &OS) {
|
||||
|
||||
std::string BTFTypeStruct::getName() { return STy->getName(); }
|
||||
|
||||
void BTFTypeStruct::getMemberInfo(uint32_t Loc, uint32_t &MemberOffset,
|
||||
uint32_t &MemberType) {
|
||||
MemberType = MemberTypeNoQual[Loc];
|
||||
MemberOffset =
|
||||
HasBitField ? Members[Loc].Offset & 0xffffff : Members[Loc].Offset;
|
||||
}
|
||||
|
||||
uint32_t BTFTypeStruct::getStructSize() { return STy->getSizeInBits() >> 3; }
|
||||
|
||||
/// The Func kind represents both subprogram and pointee of function
|
||||
/// pointers. If the FuncName is empty, it represents a pointee of function
|
||||
/// pointer. Otherwise, it represents a subprogram. The func arg names
|
||||
@ -511,12 +478,10 @@ void BTFDebug::visitArrayType(const DICompositeType *CTy, uint32_t &TypeId) {
|
||||
visitTypeEntry(ElemType, ElemTypeId, false, false);
|
||||
|
||||
// Strip qualifiers from element type to get accurate element size.
|
||||
ElemType = stripQualifiers(ElemType);
|
||||
ElemSize = ElemType->getSizeInBits() >> 3;
|
||||
|
||||
if (!CTy->getSizeInBits()) {
|
||||
auto TypeEntry = llvm::make_unique<BTFTypeArray>(ElemType, ElemTypeId, 0, 0);
|
||||
ArrayTypes.push_back(TypeEntry.get());
|
||||
auto TypeEntry = llvm::make_unique<BTFTypeArray>(ElemTypeId, 0);
|
||||
ElemTypeId = addType(std::move(TypeEntry), CTy);
|
||||
} else {
|
||||
// Visit array dimensions.
|
||||
@ -527,12 +492,9 @@ void BTFDebug::visitArrayType(const DICompositeType *CTy, uint32_t &TypeId) {
|
||||
const DISubrange *SR = cast<DISubrange>(Element);
|
||||
auto *CI = SR->getCount().dyn_cast<ConstantInt *>();
|
||||
int64_t Count = CI->getSExtValue();
|
||||
const DIType *ArrayElemTy = (I == 0) ? ElemType : nullptr;
|
||||
|
||||
auto TypeEntry =
|
||||
llvm::make_unique<BTFTypeArray>(ArrayElemTy, ElemTypeId,
|
||||
ElemSize, Count);
|
||||
ArrayTypes.push_back(TypeEntry.get());
|
||||
llvm::make_unique<BTFTypeArray>(ElemTypeId, Count);
|
||||
if (I == 0)
|
||||
ElemTypeId = addType(std::move(TypeEntry), CTy);
|
||||
else
|
||||
@ -1002,74 +964,22 @@ unsigned BTFDebug::populateStructType(const DIType *Ty) {
|
||||
return Id;
|
||||
}
|
||||
|
||||
// Find struct/array debuginfo types given a type id.
|
||||
void BTFDebug::setTypeFromId(uint32_t TypeId, BTFTypeStruct **PrevStructType,
|
||||
BTFTypeArray **PrevArrayType) {
|
||||
for (const auto &StructType : StructTypes) {
|
||||
if (StructType->getId() == TypeId) {
|
||||
*PrevStructType = StructType;
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (const auto &ArrayType : ArrayTypes) {
|
||||
if (ArrayType->getId() == TypeId) {
|
||||
*PrevArrayType = ArrayType;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a struct member offset relocation.
|
||||
void BTFDebug::generateOffsetReloc(const MachineInstr *MI,
|
||||
const MCSymbol *ORSym, DIType *RootTy,
|
||||
StringRef AccessPattern) {
|
||||
BTFTypeStruct *PrevStructType = nullptr;
|
||||
BTFTypeArray *PrevArrayType = nullptr;
|
||||
unsigned RootId = populateStructType(RootTy);
|
||||
setTypeFromId(RootId, &PrevStructType, &PrevArrayType);
|
||||
unsigned RootTySize = PrevStructType->getStructSize();
|
||||
StringRef IndexPattern = AccessPattern.substr(AccessPattern.find_first_of(':') + 1);
|
||||
size_t FirstDollar = AccessPattern.find_first_of('$');
|
||||
size_t FirstColon = AccessPattern.find_first_of(':');
|
||||
StringRef IndexPattern = AccessPattern.substr(FirstDollar + 1);
|
||||
StringRef OffsetStr = AccessPattern.substr(FirstColon + 1,
|
||||
FirstDollar - FirstColon);
|
||||
|
||||
BTFOffsetReloc OffsetReloc;
|
||||
OffsetReloc.Label = ORSym;
|
||||
OffsetReloc.OffsetNameOff = addString(IndexPattern.drop_back());
|
||||
OffsetReloc.OffsetNameOff = addString(IndexPattern);
|
||||
OffsetReloc.TypeID = RootId;
|
||||
|
||||
uint32_t Start = 0, End = 0, Offset = 0;
|
||||
bool FirstAccess = true;
|
||||
for (auto C : IndexPattern) {
|
||||
if (C != ':') {
|
||||
End++;
|
||||
} else {
|
||||
std::string SubStr = IndexPattern.substr(Start, End - Start);
|
||||
int Loc = std::stoi(SubStr);
|
||||
|
||||
if (FirstAccess) {
|
||||
Offset = Loc * RootTySize;
|
||||
FirstAccess = false;
|
||||
} else if (PrevStructType) {
|
||||
uint32_t MemberOffset, MemberTypeId;
|
||||
PrevStructType->getMemberInfo(Loc, MemberOffset, MemberTypeId);
|
||||
|
||||
Offset += MemberOffset >> 3;
|
||||
PrevStructType = nullptr;
|
||||
setTypeFromId(MemberTypeId, &PrevStructType, &PrevArrayType);
|
||||
} else if (PrevArrayType) {
|
||||
uint32_t LocOffset, ElementTypeId;
|
||||
PrevArrayType->getLocInfo(Loc, LocOffset, ElementTypeId);
|
||||
|
||||
Offset += LocOffset;
|
||||
PrevArrayType = nullptr;
|
||||
setTypeFromId(ElementTypeId, &PrevStructType, &PrevArrayType);
|
||||
} else {
|
||||
llvm_unreachable("Internal Error: BTF offset relocation type traversal error");
|
||||
}
|
||||
|
||||
Start = End + 1;
|
||||
End = Start;
|
||||
}
|
||||
}
|
||||
AccessOffsets[AccessPattern.str()] = Offset;
|
||||
AccessOffsets[AccessPattern.str()] = std::stoi(OffsetStr);
|
||||
OffsetRelocTable[SecNameOff].push_back(OffsetReloc);
|
||||
}
|
||||
|
||||
|
@ -104,18 +104,13 @@ public:
|
||||
|
||||
/// Handle array type.
|
||||
class BTFTypeArray : public BTFTypeBase {
|
||||
const DIType *ElemTyNoQual;
|
||||
uint32_t ElemSize;
|
||||
struct BTF::BTFArray ArrayInfo;
|
||||
uint32_t ElemTypeNoQual;
|
||||
|
||||
public:
|
||||
BTFTypeArray(const DIType *Ty, uint32_t ElemTypeId,
|
||||
uint32_t ElemSize, uint32_t NumElems);
|
||||
BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems);
|
||||
uint32_t getSize() { return BTFTypeBase::getSize() + BTF::BTFArraySize; }
|
||||
void completeType(BTFDebug &BDebug);
|
||||
void emitType(MCStreamer &OS);
|
||||
void getLocInfo(uint32_t Loc, uint32_t &LocOffset, uint32_t &ElementTypeId);
|
||||
};
|
||||
|
||||
/// Handle struct/union type.
|
||||
@ -123,7 +118,6 @@ class BTFTypeStruct : public BTFTypeBase {
|
||||
const DICompositeType *STy;
|
||||
bool HasBitField;
|
||||
std::vector<struct BTF::BTFMember> Members;
|
||||
std::vector<uint32_t> MemberTypeNoQual;
|
||||
|
||||
public:
|
||||
BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField,
|
||||
@ -134,8 +128,6 @@ public:
|
||||
void completeType(BTFDebug &BDebug);
|
||||
void emitType(MCStreamer &OS);
|
||||
std::string getName();
|
||||
void getMemberInfo(uint32_t Loc, uint32_t &Offset, uint32_t &MemberType);
|
||||
uint32_t getStructSize();
|
||||
};
|
||||
|
||||
/// Handle function pointer.
|
||||
@ -262,7 +254,6 @@ class BTFDebug : public DebugHandlerBase {
|
||||
StringMap<std::vector<std::string>> FileContent;
|
||||
std::map<std::string, std::unique_ptr<BTFKindDataSec>> DataSecEntries;
|
||||
std::vector<BTFTypeStruct *> StructTypes;
|
||||
std::vector<BTFTypeArray *> ArrayTypes;
|
||||
std::map<std::string, int64_t> AccessOffsets;
|
||||
std::map<StringRef, std::pair<bool, std::vector<BTFTypeDerived *>>>
|
||||
FixupDerivedTypes;
|
||||
@ -312,10 +303,6 @@ class BTFDebug : public DebugHandlerBase {
|
||||
void generateOffsetReloc(const MachineInstr *MI, const MCSymbol *ORSym,
|
||||
DIType *RootTy, StringRef AccessPattern);
|
||||
|
||||
/// Set the to-be-traversed Struct/Array Type based on TypeId.
|
||||
void setTypeFromId(uint32_t TypeId, BTFTypeStruct **PrevStructType,
|
||||
BTFTypeArray **PrevArrayType);
|
||||
|
||||
/// Populating unprocessed struct type.
|
||||
unsigned populateStructType(const DIType *Ty);
|
||||
|
||||
|
124
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-1.ll
Normal file
124
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-1.ll
Normal file
@ -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)
|
131
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-2.ll
Normal file
131
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-2.ll
Normal file
@ -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)
|
112
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-1.ll
Normal file
112
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-1.ll
Normal file
@ -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)
|
117
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-2.ll
Normal file
117
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-2.ll
Normal file
@ -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)
|
116
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-3.ll
Normal file
116
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-3.ll
Normal file
@ -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)
|
117
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-1.ll
Normal file
117
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-1.ll
Normal file
@ -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)
|
118
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-2.ll
Normal file
118
llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-2.ll
Normal file
@ -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)
|
79
llvm/test/CodeGen/BPF/CORE/offset-reloc-global-1.ll
Normal file
79
llvm/test/CodeGen/BPF/CORE/offset-reloc-global-1.ll
Normal file
@ -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)
|
95
llvm/test/CodeGen/BPF/CORE/offset-reloc-global-2.ll
Normal file
95
llvm/test/CodeGen/BPF/CORE/offset-reloc-global-2.ll
Normal file
@ -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)
|
84
llvm/test/CodeGen/BPF/CORE/offset-reloc-global-3.ll
Normal file
84
llvm/test/CodeGen/BPF/CORE/offset-reloc-global-3.ll
Normal file
@ -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)
|
62
llvm/test/CodeGen/BPF/CORE/offset-reloc-ignore.ll
Normal file
62
llvm/test/CodeGen/BPF/CORE/offset-reloc-ignore.ll
Normal file
@ -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)
|
101
llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-1.ll
Normal file
101
llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-1.ll
Normal file
@ -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)
|
107
llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-2.ll
Normal file
107
llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-2.ll
Normal file
@ -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)
|
83
llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-1.ll
Normal file
83
llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-1.ll
Normal file
@ -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)
|
85
llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-2.ll
Normal file
85
llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-2.ll
Normal file
@ -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)
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user