[llvm] r373621 - [BPF] Handle offset reloc endpoint ending in the middle of chain properly

Yonghong Song via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 3 09:30:29 PDT 2019


Author: yhs
Date: Thu Oct  3 09:30:29 2019
New Revision: 373621

URL: http://llvm.org/viewvc/llvm-project?rev=373621&view=rev
Log:
[BPF] Handle offset reloc endpoint ending in the middle of chain properly

During studying support for bitfield, I found an issue for
an example like the one in test offset-reloc-middle-chain.ll.
  struct t1 { int c; };
  struct s1 { struct t1 b; };
  struct r1 { struct s1 a; };
  #define _(x) __builtin_preserve_access_index(x)
  void test1(void *p1, void *p2, void *p3);
  void test(struct r1 *arg) {
    struct s1 *ps = _(&arg->a);
    struct t1 *pt = _(&arg->a.b);
    int *pi = _(&arg->a.b.c);
    test1(ps, pt, pi);
  }

The IR looks like:
  %0 = llvm.preserve.struct.access(base, ...)
  %1 = llvm.preserve.struct.access(%0, ...)
  %2 = llvm.preserve.struct.access(%1, ...)
  using %0, %1 and %2

In this case, we need to generate three relocatiions
corresponding to chains: (%0), (%0, %1) and (%0, %1, %2).
After collecting all the chains, the current implementation
process each chain (in a map) with code generation sequentially.
For example, after (%0) is processed, the code may look like:
  %0 = base + special_global_variable
  // llvm.preserve.struct.access(base, ...) is delisted
  // from the instruction stream.
  %1 = llvm.preserve.struct.access(%0, ...)
  %2 = llvm.preserve.struct.access(%1, ...)
  using %0, %1 and %2

When processing chain (%0, %1), the current implementation
tries to visit intrinsic llvm.preserve.struct.access(base, ...)
to get some of its properties and this caused segfault.

This patch fixed the issue by remembering all necessary
information (kind, metadata, access_index, base) during
analysis phase, so in code generation phase there is
no need to examine the intrinsic call instructions.
This also simplifies the code.

Differential Revision: https://reviews.llvm.org/D68389

Added:
    llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-middle-chain.ll
Modified:
    llvm/trunk/lib/Target/BPF/BPFAbstractMemberAccess.cpp

Modified: llvm/trunk/lib/Target/BPF/BPFAbstractMemberAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BPFAbstractMemberAccess.cpp?rev=373621&r1=373620&r2=373621&view=diff
==============================================================================
--- llvm/trunk/lib/Target/BPF/BPFAbstractMemberAccess.cpp (original)
+++ llvm/trunk/lib/Target/BPF/BPFAbstractMemberAccess.cpp Thu Oct  3 09:30:29 2019
@@ -90,6 +90,13 @@ public:
   static char ID;
   BPFAbstractMemberAccess() : ModulePass(ID) {}
 
+  struct CallInfo {
+    uint32_t Kind;
+    uint32_t AccessIndex;
+    MDNode *Metadata;
+    Value *Base;
+  };
+
 private:
   enum : uint32_t {
     BPFPreserveArrayAI = 1,
@@ -99,34 +106,32 @@ private:
 
   std::map<std::string, GlobalVariable *> GEPGlobals;
   // A map to link preserve_*_access_index instrinsic calls.
-  std::map<CallInst *, std::pair<CallInst *, uint32_t>> AIChain;
+  std::map<CallInst *, std::pair<CallInst *, CallInfo>> AIChain;
   // A map to hold all the base preserve_*_access_index instrinsic calls.
   // The base call is not an input of any other preserve_*_access_index
   // intrinsics.
-  std::map<CallInst *, uint32_t> BaseAICalls;
+  std::map<CallInst *, CallInfo> BaseAICalls;
 
   bool doTransformation(Module &M);
 
-  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 traceAICall(CallInst *Call, CallInfo &ParentInfo);
+  void traceBitCast(BitCastInst *BitCast, CallInst *Parent,
+                    CallInfo &ParentInfo);
+  void traceGEP(GetElementPtrInst *GEP, CallInst *Parent,
+                CallInfo &ParentInfo);
   void collectAICallChains(Module &M, Function &F);
 
-  bool IsPreserveDIAccessIndexCall(const CallInst *Call, uint32_t &Kind,
-                                   const MDNode *&TypeMeta, uint32_t &AccessIndex);
+  bool IsPreserveDIAccessIndexCall(const CallInst *Call, CallInfo &Cinfo);
   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 *&BaseMeta);
-  bool getAccessIndex(const Value *IndexValue, uint64_t &AccessIndex);
-  bool transformGEPChain(Module &M, CallInst *Call, uint32_t Kind);
+  Value *computeBaseAndAccessKey(CallInst *Call, CallInfo &CInfo,
+                                 std::string &AccessKey, MDNode *&BaseMeta);
+  uint64_t getConstant(const Value *IndexValue);
+  bool transformGEPChain(Module &M, CallInst *Call, CallInfo &CInfo);
 };
 } // End anonymous namespace
 
@@ -192,9 +197,7 @@ static uint32_t calcArraySize(const DICo
 
 /// Check whether a call is a preserve_*_access_index intrinsic call or not.
 bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
-                                                          uint32_t &Kind,
-                                                          const MDNode *&TypeMeta,
-                                                          uint32_t &AccessIndex) {
+                                                          CallInfo &CInfo) {
   if (!Call)
     return false;
 
@@ -202,30 +205,30 @@ bool BPFAbstractMemberAccess::IsPreserve
   if (!GV)
     return false;
   if (GV->getName().startswith("llvm.preserve.array.access.index")) {
-    Kind = BPFPreserveArrayAI;
-    TypeMeta = Call->getMetadata(LLVMContext::MD_preserve_access_index);
-    if (!TypeMeta)
+    CInfo.Kind = BPFPreserveArrayAI;
+    CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index);
+    if (!CInfo.Metadata)
       report_fatal_error("Missing metadata for llvm.preserve.array.access.index intrinsic");
-    AccessIndex = cast<ConstantInt>(Call->getArgOperand(2))
-                      ->getZExtValue();
+    CInfo.AccessIndex = getConstant(Call->getArgOperand(2));
+    CInfo.Base = Call->getArgOperand(0);
     return true;
   }
   if (GV->getName().startswith("llvm.preserve.union.access.index")) {
-    Kind = BPFPreserveUnionAI;
-    TypeMeta = Call->getMetadata(LLVMContext::MD_preserve_access_index);
-    if (!TypeMeta)
+    CInfo.Kind = BPFPreserveUnionAI;
+    CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index);
+    if (!CInfo.Metadata)
       report_fatal_error("Missing metadata for llvm.preserve.union.access.index intrinsic");
-    AccessIndex = cast<ConstantInt>(Call->getArgOperand(1))
-                      ->getZExtValue();
+    CInfo.AccessIndex = getConstant(Call->getArgOperand(1));
+    CInfo.Base = Call->getArgOperand(0);
     return true;
   }
   if (GV->getName().startswith("llvm.preserve.struct.access.index")) {
-    Kind = BPFPreserveStructAI;
-    TypeMeta = Call->getMetadata(LLVMContext::MD_preserve_access_index);
-    if (!TypeMeta)
+    CInfo.Kind = BPFPreserveStructAI;
+    CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index);
+    if (!CInfo.Metadata)
       report_fatal_error("Missing metadata for llvm.preserve.struct.access.index intrinsic");
-    AccessIndex = cast<ConstantInt>(Call->getArgOperand(2))
-                      ->getZExtValue();
+    CInfo.AccessIndex = getConstant(Call->getArgOperand(2));
+    CInfo.Base = Call->getArgOperand(0);
     return true;
   }
 
@@ -238,8 +241,7 @@ void BPFAbstractMemberAccess::replaceWit
   for (auto Call : CallList) {
     uint32_t Dimension = 1;
     if (DimensionIndex > 0)
-      Dimension = cast<ConstantInt>(Call->getArgOperand(DimensionIndex))
-                      ->getZExtValue();
+      Dimension = getConstant(Call->getArgOperand(DimensionIndex));
 
     Constant *Zero =
         ConstantInt::get(Type::getInt32Ty(Call->getParent()->getContext()), 0);
@@ -265,16 +267,14 @@ bool BPFAbstractMemberAccess::removePres
     for (auto &BB : F)
       for (auto &I : BB) {
         auto *Call = dyn_cast<CallInst>(&I);
-        uint32_t Kind;
-        const MDNode *TypeMeta;
-        uint32_t AccessIndex;
-        if (!IsPreserveDIAccessIndexCall(Call, Kind, TypeMeta, AccessIndex))
+        CallInfo CInfo;
+        if (!IsPreserveDIAccessIndexCall(Call, CInfo))
           continue;
 
         Found = true;
-        if (Kind == BPFPreserveArrayAI)
+        if (CInfo.Kind == BPFPreserveArrayAI)
           PreserveArrayIndexCalls.push_back(Call);
-        else if (Kind == BPFPreserveUnionAI)
+        else if (CInfo.Kind == BPFPreserveUnionAI)
           PreserveUnionIndexCalls.push_back(Call);
         else
           PreserveStructIndexCalls.push_back(Call);
@@ -349,99 +349,94 @@ bool BPFAbstractMemberAccess::IsValidAIC
   return dyn_cast<DICompositeType>(stripQualifiers(Ty)) == CTy;
 }
 
-void BPFAbstractMemberAccess::traceAICall(CallInst *Call, uint32_t Kind,
-                                          const MDNode *ParentMeta,
-                                          uint32_t ParentAI) {
+void BPFAbstractMemberAccess::traceAICall(CallInst *Call,
+                                          CallInfo &ParentInfo) {
   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, ParentMeta, ParentAI);
+      traceBitCast(BI, Call, ParentInfo);
     } else if (auto *CI = dyn_cast<CallInst>(Inst)) {
-      uint32_t 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, ChildMeta, ChildAI);
+      CallInfo ChildInfo;
+
+      if (IsPreserveDIAccessIndexCall(CI, ChildInfo) &&
+          IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex,
+                         ChildInfo.Metadata)) {
+        AIChain[CI] = std::make_pair(Call, ParentInfo);
+        traceAICall(CI, ChildInfo);
       } else {
-        BaseAICalls[Call] = Kind;
+        BaseAICalls[Call] = ParentInfo;
       }
     } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
       if (GI->hasAllZeroIndices())
-        traceGEP(GI, Call, Kind, ParentMeta, ParentAI);
+        traceGEP(GI, Call, ParentInfo);
       else
-        BaseAICalls[Call] = Kind;
+        BaseAICalls[Call] = ParentInfo;
     } else {
-      BaseAICalls[Call] = Kind;
+      BaseAICalls[Call] = ParentInfo;
     }
   }
 }
 
 void BPFAbstractMemberAccess::traceBitCast(BitCastInst *BitCast,
-                                           CallInst *Parent, uint32_t Kind,
-                                           const MDNode *ParentMeta,
-                                           uint32_t ParentAI) {
+                                           CallInst *Parent,
+                                           CallInfo &ParentInfo) {
   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, ParentMeta, ParentAI);
+      traceBitCast(BI, Parent, ParentInfo);
     } else if (auto *CI = dyn_cast<CallInst>(Inst)) {
-      uint32_t 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, ChildMeta, ChildAI);
+      CallInfo ChildInfo;
+      if (IsPreserveDIAccessIndexCall(CI, ChildInfo) &&
+          IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex,
+                         ChildInfo.Metadata)) {
+        AIChain[CI] = std::make_pair(Parent, ParentInfo);
+        traceAICall(CI, ChildInfo);
       } else {
-        BaseAICalls[Parent] = Kind;
+        BaseAICalls[Parent] = ParentInfo;
       }
     } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
       if (GI->hasAllZeroIndices())
-        traceGEP(GI, Parent, Kind, ParentMeta, ParentAI);
+        traceGEP(GI, Parent, ParentInfo);
       else
-        BaseAICalls[Parent] = Kind;
+        BaseAICalls[Parent] = ParentInfo;
     } else {
-      BaseAICalls[Parent] = Kind;
+      BaseAICalls[Parent] = ParentInfo;
     }
   }
 }
 
 void BPFAbstractMemberAccess::traceGEP(GetElementPtrInst *GEP, CallInst *Parent,
-                                       uint32_t Kind, const MDNode *ParentMeta,
-                                       uint32_t ParentAI) {
+                                       CallInfo &ParentInfo) {
   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, ParentMeta, ParentAI);
+      traceBitCast(BI, Parent, ParentInfo);
     } else if (auto *CI = dyn_cast<CallInst>(Inst)) {
-      uint32_t 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, ChildMeta, ChildAI);
+      CallInfo ChildInfo;
+      if (IsPreserveDIAccessIndexCall(CI, ChildInfo) &&
+          IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex,
+                         ChildInfo.Metadata)) {
+        AIChain[CI] = std::make_pair(Parent, ParentInfo);
+        traceAICall(CI, ChildInfo);
       } else {
-        BaseAICalls[Parent] = Kind;
+        BaseAICalls[Parent] = ParentInfo;
       }
     } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
       if (GI->hasAllZeroIndices())
-        traceGEP(GI, Parent, Kind, ParentMeta, ParentAI);
+        traceGEP(GI, Parent, ParentInfo);
       else
-        BaseAICalls[Parent] = Kind;
+        BaseAICalls[Parent] = ParentInfo;
     } else {
-      BaseAICalls[Parent] = Kind;
+      BaseAICalls[Parent] = ParentInfo;
     }
   }
 }
@@ -452,44 +447,37 @@ void BPFAbstractMemberAccess::collectAIC
 
   for (auto &BB : F)
     for (auto &I : BB) {
-      uint32_t Kind;
-      const MDNode *TypeMeta;
-      uint32_t AccessIndex;
+      CallInfo CInfo;
       auto *Call = dyn_cast<CallInst>(&I);
-      if (!IsPreserveDIAccessIndexCall(Call, Kind, TypeMeta, AccessIndex) ||
+      if (!IsPreserveDIAccessIndexCall(Call, CInfo) ||
           AIChain.find(Call) != AIChain.end())
         continue;
 
-      traceAICall(Call, Kind, TypeMeta, AccessIndex);
+      traceAICall(Call, CInfo);
     }
 }
 
-/// Get access index from the preserve_*_access_index intrinsic calls.
-bool BPFAbstractMemberAccess::getAccessIndex(const Value *IndexValue,
-                                             uint64_t &AccessIndex) {
+uint64_t BPFAbstractMemberAccess::getConstant(const Value *IndexValue) {
   const ConstantInt *CV = dyn_cast<ConstantInt>(IndexValue);
-  if (!CV)
-    return false;
-
-  AccessIndex = CV->getValue().getZExtValue();
-  return true;
+  assert(CV);
+  return CV->getValue().getZExtValue();
 }
 
 /// Compute the base of the whole preserve_*_access_index chains, i.e., the base
 /// pointer of the first preserve_*_access_index call, and construct the access
 /// string, which will be the name of a global variable.
 Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call,
+                                                        CallInfo &CInfo,
                                                         std::string &AccessKey,
-                                                        uint32_t Kind,
                                                         MDNode *&TypeMeta) {
   Value *Base = nullptr;
   std::string TypeName;
-  std::stack<std::pair<CallInst *, uint32_t>> CallStack;
+  std::stack<std::pair<CallInst *, CallInfo>> CallStack;
 
   // Put the access chain into a stack with the top as the head of the chain.
   while (Call) {
-    CallStack.push(std::make_pair(Call, Kind));
-    Kind = AIChain[Call].second;
+    CallStack.push(std::make_pair(Call, CInfo));
+    CInfo = AIChain[Call].second;
     Call = AIChain[Call].first;
   }
 
@@ -508,14 +496,14 @@ Value *BPFAbstractMemberAccess::computeB
   while (CallStack.size()) {
     auto StackElem = CallStack.top();
     Call = StackElem.first;
-    Kind = StackElem.second;
+    CInfo = StackElem.second;
 
     if (!Base)
-      Base = Call->getArgOperand(0);
+      Base = CInfo.Base;
 
-    MDNode *MDN = Call->getMetadata(LLVMContext::MD_preserve_access_index);
-    DIType *Ty = stripQualifiers(cast<DIType>(MDN));
-    if (Kind == BPFPreserveUnionAI || Kind == BPFPreserveStructAI) {
+    DIType *Ty = stripQualifiers(cast<DIType>(CInfo.Metadata));
+    if (CInfo.Kind == BPFPreserveUnionAI ||
+        CInfo.Kind == BPFPreserveStructAI) {
       // struct or union type
       TypeName = Ty->getName();
       TypeMeta = Ty;
@@ -527,9 +515,7 @@ Value *BPFAbstractMemberAccess::computeB
     CallStack.pop();
 
     // BPFPreserveArrayAI
-    uint64_t AccessIndex;
-    if (!getAccessIndex(Call->getArgOperand(2), AccessIndex))
-      return nullptr;
+    uint64_t AccessIndex = CInfo.AccessIndex;
 
     DIType *BaseTy = nullptr;
     bool CheckElemType = false;
@@ -580,18 +566,14 @@ Value *BPFAbstractMemberAccess::computeB
   // and access key construction.
   while (CallStack.size()) {
     auto StackElem = CallStack.top();
-    Call = StackElem.first;
-    Kind = StackElem.second;
+    CInfo = StackElem.second;
     CallStack.pop();
 
     // Access Index
-    uint64_t AccessIndex;
-    uint32_t ArgIndex = (Kind == BPFPreserveUnionAI) ? 1 : 2;
-    if (!getAccessIndex(Call->getArgOperand(ArgIndex), AccessIndex))
-      return nullptr;
+    uint64_t AccessIndex = CInfo.AccessIndex;
     AccessKey += ":" + std::to_string(AccessIndex);
 
-    MDNode *MDN = Call->getMetadata(LLVMContext::MD_preserve_access_index);
+    MDNode *MDN = CInfo.Metadata;
     // At this stage, it cannot be pointer type.
     auto *CTy = cast<DICompositeType>(stripQualifiers(cast<DIType>(MDN)));
     uint32_t Tag = CTy->getTag();
@@ -615,11 +597,11 @@ Value *BPFAbstractMemberAccess::computeB
 /// Call/Kind is the base preserve_*_access_index() call. Attempts to do
 /// transformation to a chain of relocable GEPs.
 bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call,
-                                                uint32_t Kind) {
+                                                CallInfo &CInfo) {
   std::string AccessKey;
   MDNode *TypeMeta;
   Value *Base =
-      computeBaseAndAccessKey(Call, AccessKey, Kind, TypeMeta);
+      computeBaseAndAccessKey(Call, CInfo, AccessKey, TypeMeta);
   if (!Base)
     return false;
 

Added: llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-middle-chain.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-middle-chain.ll?rev=373621&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-middle-chain.ll (added)
+++ llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-middle-chain.ll Thu Oct  3 09:30:29 2019
@@ -0,0 +1,127 @@
+; 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 t1 {
+;     int c;
+;   };
+;   struct s1 {
+;     struct t1 b;
+;   };
+;   struct r1 {
+;     struct s1 a;
+;   };
+;   #define _(x) __builtin_preserve_access_index(x)
+;   void test1(void *p1, void *p2, void *p3);
+;   void test(struct r1 *arg) {
+;     struct s1 *ps = _(&arg->a);
+;     struct t1 *pt = _(&arg->a.b);
+;     int *pi = _(&arg->a.b.c);
+;     test1(ps, pt, pi);
+;   }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+%struct.r1 = type { %struct.s1 }
+%struct.s1 = type { %struct.t1 }
+%struct.t1 = type { i32 }
+
+; Function Attrs: nounwind
+define dso_local void @test(%struct.r1* %arg) local_unnamed_addr #0 !dbg !7 {
+entry:
+  call void @llvm.dbg.value(metadata %struct.r1* %arg, metadata !22, metadata !DIExpression()), !dbg !29
+  %0 = tail call %struct.s1* @llvm.preserve.struct.access.index.p0s_struct.s1s.p0s_struct.r1s(%struct.r1* %arg, i32 0, i32 0), !dbg !30, !llvm.preserve.access.index !11
+  call void @llvm.dbg.value(metadata %struct.s1* %0, metadata !23, metadata !DIExpression()), !dbg !29
+  %1 = tail call %struct.t1* @llvm.preserve.struct.access.index.p0s_struct.t1s.p0s_struct.s1s(%struct.s1* %0, i32 0, i32 0), !dbg !31, !llvm.preserve.access.index !14
+  call void @llvm.dbg.value(metadata %struct.t1* %1, metadata !25, metadata !DIExpression()), !dbg !29
+  %2 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.t1s(%struct.t1* %1, i32 0, i32 0), !dbg !32, !llvm.preserve.access.index !17
+  call void @llvm.dbg.value(metadata i32* %2, metadata !27, metadata !DIExpression()), !dbg !29
+  %3 = bitcast %struct.s1* %0 to i8*, !dbg !33
+  %4 = bitcast %struct.t1* %1 to i8*, !dbg !34
+  %5 = bitcast i32* %2 to i8*, !dbg !35
+  tail call void @test1(i8* %3, i8* %4, i8* %5) #4, !dbg !36
+  ret void, !dbg !37
+}
+
+; CHECK:             .long   1                       # BTF_KIND_STRUCT(id = 2)
+
+; CHECK:             .ascii  "r1"                    # string offset=1
+; CHECK:             .ascii  ".text"                 # string offset=29
+; CHECK:             .ascii  "0:0"                   # string offset=72
+; CHECK:             .ascii  "0:0:0"                 # string offset=76
+; CHECK:             .ascii  "0:0:0:0"               # string offset=82
+
+; CHECK:             .long   12                      # OffsetReloc
+; CHECK-NEXT:        .long   29                      # Offset reloc section string offset=29
+; CHECK-NEXT:        .long   3
+; CHECK_NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK_NEXT:        .long   2
+; CHECK_NEXT:        .long   72
+; CHECK_NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK_NEXT:        .long   2
+; CHECK_NEXT:        .long   76
+; CHECK_NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK_NEXT:        .long   2
+; CHECK_NEXT:        .long   82
+
+; Function Attrs: nounwind readnone
+declare %struct.s1* @llvm.preserve.struct.access.index.p0s_struct.s1s.p0s_struct.r1s(%struct.r1*, i32, i32) #1
+
+; Function Attrs: nounwind readnone
+declare %struct.t1* @llvm.preserve.struct.access.index.p0s_struct.t1s.p0s_struct.s1s(%struct.s1*, i32, i32) #1
+
+; Function Attrs: nounwind readnone
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.t1s(%struct.t1*, i32, i32) #1
+
+declare dso_local void @test1(i8*, i8*, i8*) local_unnamed_addr #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 = { nounwind readnone }
+attributes #2 = { "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 #3 = { nounwind readnone speculatable willreturn }
+attributes #4 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 42b3328a2368b38fba6bdb0c616fe6c5520e3bc5)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/core")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 42b3328a2368b38fba6bdb0c616fe6c5520e3bc5)"}
+!7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 12, type: !8, scopeLine: 12, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !21)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null, !10}
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64)
+!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "r1", file: !1, line: 7, size: 32, elements: !12)
+!12 = !{!13}
+!13 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !11, file: !1, line: 8, baseType: !14, size: 32)
+!14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1", file: !1, line: 4, size: 32, elements: !15)
+!15 = !{!16}
+!16 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !14, file: !1, line: 5, baseType: !17, size: 32)
+!17 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1", file: !1, line: 1, size: 32, elements: !18)
+!18 = !{!19}
+!19 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !17, file: !1, line: 2, baseType: !20, size: 32)
+!20 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!21 = !{!22, !23, !25, !27}
+!22 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 12, type: !10)
+!23 = !DILocalVariable(name: "ps", scope: !7, file: !1, line: 13, type: !24)
+!24 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64)
+!25 = !DILocalVariable(name: "pt", scope: !7, file: !1, line: 14, type: !26)
+!26 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !17, size: 64)
+!27 = !DILocalVariable(name: "pi", scope: !7, file: !1, line: 15, type: !28)
+!28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64)
+!29 = !DILocation(line: 0, scope: !7)
+!30 = !DILocation(line: 13, column: 19, scope: !7)
+!31 = !DILocation(line: 14, column: 19, scope: !7)
+!32 = !DILocation(line: 15, column: 13, scope: !7)
+!33 = !DILocation(line: 16, column: 9, scope: !7)
+!34 = !DILocation(line: 16, column: 13, scope: !7)
+!35 = !DILocation(line: 16, column: 17, scope: !7)
+!36 = !DILocation(line: 16, column: 3, scope: !7)
+!37 = !DILocation(line: 17, column: 1, scope: !7)




More information about the llvm-commits mailing list