[llvm] r365503 - [BPF] Support for compile once and run everywhere

Yonghong Song via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 9 08:28:41 PDT 2019


Author: yhs
Date: Tue Jul  9 08:28:41 2019
New Revision: 365503

URL: http://llvm.org/viewvc/llvm-project?rev=365503&view=rev
Log:
[BPF] Support for compile once and run everywhere

Introduction
============

This patch added intial support for bpf program compile once
and run everywhere (CO-RE).

The main motivation is for bpf program which depends on
kernel headers which may vary between different kernel versions.
The initial discussion can be found at https://lwn.net/Articles/773198/.

Currently, bpf program accesses kernel internal data structure
through bpf_probe_read() helper. The idea is to capture the
kernel data structure to be accessed through bpf_probe_read()
and relocate them on different kernel versions.

On each host, right before bpf program load, the bpfloader
will look at the types of the native linux through vmlinux BTF,
calculates proper access offset and patch the instruction.

To accommodate this, three intrinsic functions
   preserve_{array,union,struct}_access_index
are introduced which in clang will preserve the base pointer,
struct/union/array access_index and struct/union debuginfo type
information. Later, bpf IR pass can reconstruct the whole gep
access chains without looking at gep itself.

This patch did the following:
  . An IR pass is added to convert preserve_*_access_index to
    global variable who name encodes the getelementptr
    access pattern. The global variable has metadata
    attached to describe the corresponding struct/union
    debuginfo type.
  . An SimplifyPatchable MachineInstruction pass is added
    to remove unnecessary loads.
  . The BTF output pass is enhanced to generate relocation
    records located in .BTF.ext section.

Typical CO-RE also needs support of global variables which can
be assigned to different values to different hosts. For example,
kernel version can be used to guard different versions of codes.
This patch added the support for patchable externals as well.

Example
=======

The following is an example.

  struct pt_regs {
    long arg1;
    long arg2;
  };
  struct sk_buff {
    int i;
    struct net_device *dev;
  };

  #define _(x) (__builtin_preserve_access_index(x))
  static int (*bpf_probe_read)(void *dst, int size, const void *unsafe_ptr) =
          (void *) 4;
  extern __attribute__((section(".BPF.patchable_externs"))) unsigned __kernel_version;
  int bpf_prog(struct pt_regs *ctx) {
    struct net_device *dev = 0;

    // ctx->arg* does not need bpf_probe_read
    if (__kernel_version >= 41608)
      bpf_probe_read(&dev, sizeof(dev), _(&((struct sk_buff *)ctx->arg1)->dev));
    else
      bpf_probe_read(&dev, sizeof(dev), _(&((struct sk_buff *)ctx->arg2)->dev));
    return dev != 0;
  }

In the above, we want to translate the third argument of
bpf_probe_read() as relocations.

  -bash-4.4$ clang -target bpf -O2 -g -S trace.c

The compiler will generate two new subsections in .BTF.ext,
OffsetReloc and ExternReloc.
OffsetReloc is to record the structure member offset operations,
and ExternalReloc is to record the external globals where
only u8, u16, u32 and u64 are supported.

   BPFOffsetReloc Size
   struct SecLOffsetReloc for ELF section #1
   A number of struct BPFOffsetReloc for ELF section #1
   struct SecOffsetReloc for ELF section #2
   A number of struct BPFOffsetReloc for ELF section #2
   ...
   BPFExternReloc Size
   struct SecExternReloc for ELF section #1
   A number of struct BPFExternReloc for ELF section #1
   struct SecExternReloc for ELF section #2
   A number of struct BPFExternReloc for ELF section #2

  struct BPFOffsetReloc {
    uint32_t InsnOffset;    ///< Byte offset in this section
    uint32_t TypeID;        ///< TypeID for the relocation
    uint32_t OffsetNameOff; ///< The string to traverse types
  };

  struct BPFExternReloc {
    uint32_t InsnOffset;    ///< Byte offset in this section
    uint32_t ExternNameOff; ///< The string for external variable
  };

Note that only externs with attribute section ".BPF.patchable_externs"
are considered for Extern Reloc which will be patched by bpf loader
right before the load.

For the above test case, two offset records and one extern record
will be generated:
  OffsetReloc records:
        .long   .Ltmp12                 # Insn Offset
        .long   7                       # TypeId
        .long   242                     # Type Decode String
        .long   .Ltmp18                 # Insn Offset
        .long   7                       # TypeId
        .long   242                     # Type Decode String

  ExternReloc record:
        .long   .Ltmp5                  # Insn Offset
        .long   165                     # External Variable

  In string table:
        .ascii  "0:1"                   # string offset=242
        .ascii  "__kernel_version"      # string offset=165

The default member offset can be calculated as
    the 2nd member offset (0 representing the 1st member) of struct "sk_buff".

The asm code:
    .Ltmp5:
    .Ltmp6:
            r2 = 0
            r3 = 41608
    .Ltmp7:
    .Ltmp8:
            .loc    1 18 9 is_stmt 0        # t.c:18:9
    .Ltmp9:
            if r3 > r2 goto LBB0_2
    .Ltmp10:
    .Ltmp11:
            .loc    1 0 9                   # t.c:0:9
    .Ltmp12:
            r2 = 8
    .Ltmp13:
            .loc    1 19 66 is_stmt 1       # t.c:19:66
    .Ltmp14:
    .Ltmp15:
            r3 = *(u64 *)(r1 + 0)
            goto LBB0_3
    .Ltmp16:
    .Ltmp17:
    LBB0_2:
            .loc    1 0 66 is_stmt 0        # t.c:0:66
    .Ltmp18:
            r2 = 8
            .loc    1 21 66 is_stmt 1       # t.c:21:66
    .Ltmp19:
            r3 = *(u64 *)(r1 + 8)
    .Ltmp20:
    .Ltmp21:
    LBB0_3:
            .loc    1 0 66 is_stmt 0        # t.c:0:66
            r3 += r2
            r1 = r10
    .Ltmp22:
    .Ltmp23:
    .Ltmp24:
            r1 += -8
            r2 = 8
            call 4

For instruction .Ltmp12 and .Ltmp18, "r2 = 8", the number
8 is the structure offset based on the current BTF.
Loader needs to adjust it if it changes on the host.

For instruction .Ltmp5, "r2 = 0", the external variable
got a default value 0, loader needs to supply an appropriate
value for the particular host.

Compiling to generate object code and disassemble:
   0000000000000000 bpf_prog:
           0:       b7 02 00 00 00 00 00 00         r2 = 0
           1:       7b 2a f8 ff 00 00 00 00         *(u64 *)(r10 - 8) = r2
           2:       b7 02 00 00 00 00 00 00         r2 = 0
           3:       b7 03 00 00 88 a2 00 00         r3 = 41608
           4:       2d 23 03 00 00 00 00 00         if r3 > r2 goto +3 <LBB0_2>
           5:       b7 02 00 00 08 00 00 00         r2 = 8
           6:       79 13 00 00 00 00 00 00         r3 = *(u64 *)(r1 + 0)
           7:       05 00 02 00 00 00 00 00         goto +2 <LBB0_3>

    0000000000000040 LBB0_2:
           8:       b7 02 00 00 08 00 00 00         r2 = 8
           9:       79 13 08 00 00 00 00 00         r3 = *(u64 *)(r1 + 8)

    0000000000000050 LBB0_3:
          10:       0f 23 00 00 00 00 00 00         r3 += r2
          11:       bf a1 00 00 00 00 00 00         r1 = r10
          12:       07 01 00 00 f8 ff ff ff         r1 += -8
          13:       b7 02 00 00 08 00 00 00         r2 = 8
          14:       85 00 00 00 04 00 00 00         call 4

Instructions #2, #5 and #8 need relocation resoutions from the loader.

Signed-off-by: Yonghong Song <yhs at fb.com>

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

Added:
    llvm/trunk/lib/Target/BPF/BPFAbstrctMemberAccess.cpp
    llvm/trunk/lib/Target/BPF/BPFCORE.h
    llvm/trunk/lib/Target/BPF/BPFMISimplifyPatchable.cpp
    llvm/trunk/test/CodeGen/BPF/BTF/map-def.ll
    llvm/trunk/test/CodeGen/BPF/BTF/ptr-prune-type.ll
    llvm/trunk/test/CodeGen/BPF/CORE/
    llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-basic.ll
    llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-multilevel.ll
    llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll
    llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll
    llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-union.ll
    llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-char.ll
      - copied, changed from r365502, llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll
    llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-uint.ll
      - copied, changed from r365502, llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll
    llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-ulonglong.ll
      - copied, changed from r365502, llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll
Modified:
    llvm/trunk/lib/Target/BPF/BPF.h
    llvm/trunk/lib/Target/BPF/BPFAsmPrinter.cpp
    llvm/trunk/lib/Target/BPF/BPFTargetMachine.cpp
    llvm/trunk/lib/Target/BPF/BTF.h
    llvm/trunk/lib/Target/BPF/BTFDebug.cpp
    llvm/trunk/lib/Target/BPF/BTFDebug.h
    llvm/trunk/lib/Target/BPF/CMakeLists.txt
    llvm/trunk/test/CodeGen/BPF/BTF/binary-format.ll
    llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll
    llvm/trunk/test/CodeGen/BPF/BTF/filename.ll
    llvm/trunk/test/CodeGen/BPF/BTF/func-func-ptr.ll
    llvm/trunk/test/CodeGen/BPF/BTF/func-non-void.ll
    llvm/trunk/test/CodeGen/BPF/BTF/func-source.ll
    llvm/trunk/test/CodeGen/BPF/BTF/func-typedef.ll
    llvm/trunk/test/CodeGen/BPF/BTF/func-unused-arg.ll
    llvm/trunk/test/CodeGen/BPF/BTF/func-void.ll
    llvm/trunk/test/CodeGen/BPF/BTF/local-var.ll
    llvm/trunk/test/CodeGen/BPF/BTF/static-var-derived-type.ll
    llvm/trunk/test/CodeGen/BPF/BTF/static-var-inited-sec.ll
    llvm/trunk/test/CodeGen/BPF/BTF/static-var-inited.ll
    llvm/trunk/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll
    llvm/trunk/test/CodeGen/BPF/BTF/static-var-readonly.ll
    llvm/trunk/test/CodeGen/BPF/BTF/static-var-sec.ll
    llvm/trunk/test/CodeGen/BPF/BTF/static-var-zerolen-array.ll
    llvm/trunk/test/CodeGen/BPF/BTF/static-var.ll
    llvm/trunk/test/CodeGen/BPF/reloc-btf-2.ll

Modified: llvm/trunk/lib/Target/BPF/BPF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BPF.h?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/lib/Target/BPF/BPF.h (original)
+++ llvm/trunk/lib/Target/BPF/BPF.h Tue Jul  9 08:28:41 2019
@@ -15,11 +15,16 @@
 namespace llvm {
 class BPFTargetMachine;
 
+ModulePass *createBPFAbstractMemberAccess();
+
 FunctionPass *createBPFISelDag(BPFTargetMachine &TM);
+FunctionPass *createBPFMISimplifyPatchablePass();
 FunctionPass *createBPFMIPeepholePass();
 FunctionPass *createBPFMIPreEmitPeepholePass();
 FunctionPass *createBPFMIPreEmitCheckingPass();
 
+void initializeBPFAbstractMemberAccessPass(PassRegistry&);
+void initializeBPFMISimplifyPatchablePass(PassRegistry&);
 void initializeBPFMIPeepholePass(PassRegistry&);
 void initializeBPFMIPreEmitPeepholePass(PassRegistry&);
 void initializeBPFMIPreEmitCheckingPass(PassRegistry&);

Added: llvm/trunk/lib/Target/BPF/BPFAbstrctMemberAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BPFAbstrctMemberAccess.cpp?rev=365503&view=auto
==============================================================================
--- llvm/trunk/lib/Target/BPF/BPFAbstrctMemberAccess.cpp (added)
+++ llvm/trunk/lib/Target/BPF/BPFAbstrctMemberAccess.cpp Tue Jul  9 08:28:41 2019
@@ -0,0 +1,482 @@
+//===------ BPFAbstractMemberAccess.cpp - Abstracting Member Accesses -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass abstracted struct/union member accesses in order to support
+// compile-once run-everywhere (CO-RE). The CO-RE intends to compile the program
+// which can run on different kernels. In particular, if bpf program tries to
+// access a particular kernel data structure member, the details of the
+// intermediate member access will be remembered so bpf loader can do
+// necessary adjustment right before program loading.
+//
+// For example,
+//
+//   struct s {
+//     int a;
+//     int b;
+//   };
+//   struct t {
+//     struct s c;
+//     int d;
+//   };
+//   struct t e;
+//
+// For the member access e.c.b, the compiler will generate code
+//   &e + 4
+//
+// The compile-once run-everywhere instead generates the following code
+//   r = 4
+//   &e + r
+// The "4" in "r = 4" can be changed based on a particular kernel version.
+// For example, on a particular kernel version, if struct s is changed to
+//
+//   struct s {
+//     int new_field;
+//     int a;
+//     int b;
+//   }
+//
+// By repeating the member access on the host, the bpf loader can
+// adjust "r = 4" as "r = 8".
+//
+// This feature relies on the following three intrinsic calls:
+//   addr = preserve_array_access_index(base, dimension, index)
+//   addr = preserve_union_access_index(base, di_index)
+//          !llvm.preserve.access.index <union_ditype>
+//   addr = preserve_struct_access_index(base, gep_index, di_index)
+//          !llvm.preserve.access.index <struct_ditype>
+//
+//===----------------------------------------------------------------------===//
+
+#include "BPF.h"
+#include "BPFCORE.h"
+#include "BPFTargetMachine.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/User.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+
+#define DEBUG_TYPE "bpf-abstract-member-access"
+
+namespace llvm {
+const std::string BPFCoreSharedInfo::AmaAttr = "btf_ama";
+const std::string BPFCoreSharedInfo::PatchableExtSecName =
+    ".BPF.patchable_externs";
+} // namespace llvm
+
+using namespace llvm;
+
+namespace {
+
+class BPFAbstractMemberAccess final : public ModulePass {
+  StringRef getPassName() const override {
+    return "BPF Abstract Member Access";
+  }
+
+  bool runOnModule(Module &M) override;
+
+public:
+  static char ID;
+  BPFAbstractMemberAccess() : ModulePass(ID) {}
+
+private:
+  enum : uint32_t {
+    BPFPreserveArrayAI = 1,
+    BPFPreserveUnionAI = 2,
+    BPFPreserveStructAI = 3,
+  };
+
+  std::map<std::string, GlobalVariable *> GEPGlobals;
+  // A map to link preserve_*_access_index instrinsic calls.
+  std::map<CallInst *, std::pair<CallInst *, uint32_t>> 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;
+
+  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 collectAICallChains(Module &M, Function &F);
+
+  bool IsPreserveDIAccessIndexCall(const CallInst *Call, uint32_t &Kind);
+  bool removePreserveAccessIndexIntrinsic(Module &M);
+  void replaceWithGEP(std::vector<CallInst *> &CallList,
+                      uint32_t NumOfZerosIndex, uint32_t DIIndex);
+
+  Value *computeBaseAndAccessStr(CallInst *Call, std::string &AccessStr,
+                                 std::string &AccessKey, uint32_t Kind,
+                                 MDNode *&TypeMeta);
+  bool getAccessIndex(const Value *IndexValue, uint64_t &AccessIndex);
+  bool transformGEPChain(Module &M, CallInst *Call, uint32_t Kind);
+};
+} // End anonymous namespace
+
+char BPFAbstractMemberAccess::ID = 0;
+INITIALIZE_PASS(BPFAbstractMemberAccess, DEBUG_TYPE,
+                "abstracting struct/union member accessees", false, false)
+
+ModulePass *llvm::createBPFAbstractMemberAccess() {
+  return new BPFAbstractMemberAccess();
+}
+
+bool BPFAbstractMemberAccess::runOnModule(Module &M) {
+  LLVM_DEBUG(dbgs() << "********** Abstract Member Accesses **********\n");
+
+  // Bail out if no debug info.
+  if (empty(M.debug_compile_units()))
+    return false;
+
+  return doTransformation(M);
+}
+
+/// Check whether a call is a preserve_*_access_index intrinsic call or not.
+bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
+                                                          uint32_t &Kind) {
+  if (!Call)
+    return false;
+
+  const auto *GV = dyn_cast<GlobalValue>(Call->getCalledValue());
+  if (!GV)
+    return false;
+  if (GV->getName().startswith("llvm.preserve.array.access.index")) {
+    Kind = BPFPreserveArrayAI;
+    return true;
+  }
+  if (GV->getName().startswith("llvm.preserve.union.access.index")) {
+    Kind = BPFPreserveUnionAI;
+    return true;
+  }
+  if (GV->getName().startswith("llvm.preserve.struct.access.index")) {
+    Kind = BPFPreserveStructAI;
+    return true;
+  }
+
+  return false;
+}
+
+void BPFAbstractMemberAccess::replaceWithGEP(std::vector<CallInst *> &CallList,
+                                             uint32_t DimensionIndex,
+                                             uint32_t GEPIndex) {
+  for (auto Call : CallList) {
+    uint32_t Dimension = 1;
+    if (DimensionIndex > 0)
+      Dimension = cast<ConstantInt>(Call->getArgOperand(DimensionIndex))
+                      ->getZExtValue();
+
+    Constant *Zero =
+        ConstantInt::get(Type::getInt32Ty(Call->getParent()->getContext()), 0);
+    SmallVector<Value *, 4> IdxList;
+    for (unsigned I = 0; I < Dimension; ++I)
+      IdxList.push_back(Zero);
+    IdxList.push_back(Call->getArgOperand(GEPIndex));
+
+    auto *GEP = GetElementPtrInst::CreateInBounds(Call->getArgOperand(0),
+                                                  IdxList, "", Call);
+    Call->replaceAllUsesWith(GEP);
+    Call->eraseFromParent();
+  }
+}
+
+bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Module &M) {
+  std::vector<CallInst *> PreserveArrayIndexCalls;
+  std::vector<CallInst *> PreserveUnionIndexCalls;
+  std::vector<CallInst *> PreserveStructIndexCalls;
+  bool Found = false;
+
+  for (Function &F : M)
+    for (auto &BB : F)
+      for (auto &I : BB) {
+        auto *Call = dyn_cast<CallInst>(&I);
+        uint32_t Kind;
+        if (!IsPreserveDIAccessIndexCall(Call, Kind))
+          continue;
+
+        Found = true;
+        if (Kind == BPFPreserveArrayAI)
+          PreserveArrayIndexCalls.push_back(Call);
+        else if (Kind == BPFPreserveUnionAI)
+          PreserveUnionIndexCalls.push_back(Call);
+        else
+          PreserveStructIndexCalls.push_back(Call);
+      }
+
+  // do the following transformation:
+  // . addr = preserve_array_access_index(base, dimension, index)
+  //   is transformed to
+  //     addr = GEP(base, dimenion's zero's, index)
+  // . addr = preserve_union_access_index(base, di_index)
+  //   is transformed to
+  //     addr = base, i.e., all usages of "addr" are replaced by "base".
+  // . addr = preserve_struct_access_index(base, gep_index, di_index)
+  //   is transformed to
+  //     addr = GEP(base, 0, gep_index)
+  replaceWithGEP(PreserveArrayIndexCalls, 1, 2);
+  replaceWithGEP(PreserveStructIndexCalls, 0, 1);
+  for (auto Call : PreserveUnionIndexCalls) {
+    Call->replaceAllUsesWith(Call->getArgOperand(0));
+    Call->eraseFromParent();
+  }
+
+  return Found;
+}
+
+void BPFAbstractMemberAccess::traceAICall(CallInst *Call, uint32_t Kind) {
+  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);
+    } else if (auto *CI = dyn_cast<CallInst>(Inst)) {
+      uint32_t CIKind;
+      if (IsPreserveDIAccessIndexCall(CI, CIKind)) {
+        AIChain[CI] = std::make_pair(Call, Kind);
+        traceAICall(CI, CIKind);
+      } else {
+        BaseAICalls[Call] = Kind;
+      }
+    } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
+      if (GI->hasAllZeroIndices())
+        traceGEP(GI, Call, Kind);
+      else
+        BaseAICalls[Call] = Kind;
+    }
+  }
+}
+
+void BPFAbstractMemberAccess::traceBitCast(BitCastInst *BitCast,
+                                           CallInst *Parent, uint32_t Kind) {
+  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);
+    } else if (auto *CI = dyn_cast<CallInst>(Inst)) {
+      uint32_t CIKind;
+      if (IsPreserveDIAccessIndexCall(CI, CIKind)) {
+        AIChain[CI] = std::make_pair(Parent, Kind);
+        traceAICall(CI, CIKind);
+      } else {
+        BaseAICalls[Parent] = Kind;
+      }
+    } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
+      if (GI->hasAllZeroIndices())
+        traceGEP(GI, Parent, Kind);
+      else
+        BaseAICalls[Parent] = Kind;
+    }
+  }
+}
+
+void BPFAbstractMemberAccess::traceGEP(GetElementPtrInst *GEP, CallInst *Parent,
+                                       uint32_t Kind) {
+  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);
+    } else if (auto *CI = dyn_cast<CallInst>(Inst)) {
+      uint32_t CIKind;
+      if (IsPreserveDIAccessIndexCall(CI, CIKind)) {
+        AIChain[CI] = std::make_pair(Parent, Kind);
+        traceAICall(CI, CIKind);
+      } else {
+        BaseAICalls[Parent] = Kind;
+      }
+    } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
+      if (GI->hasAllZeroIndices())
+        traceGEP(GI, Parent, Kind);
+      else
+        BaseAICalls[Parent] = Kind;
+    }
+  }
+}
+
+void BPFAbstractMemberAccess::collectAICallChains(Module &M, Function &F) {
+  AIChain.clear();
+  BaseAICalls.clear();
+
+  for (auto &BB : F)
+    for (auto &I : BB) {
+      uint32_t Kind;
+      auto *Call = dyn_cast<CallInst>(&I);
+      if (!IsPreserveDIAccessIndexCall(Call, Kind) ||
+          AIChain.find(Call) != AIChain.end())
+        continue;
+
+      traceAICall(Call, Kind);
+    }
+}
+
+/// Get access index from the preserve_*_access_index intrinsic calls.
+bool BPFAbstractMemberAccess::getAccessIndex(const Value *IndexValue,
+                                             uint64_t &AccessIndex) {
+  const ConstantInt *CV = dyn_cast<ConstantInt>(IndexValue);
+  if (!CV)
+    return false;
+
+  AccessIndex = CV->getValue().getZExtValue();
+  return true;
+}
+
+/// 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::computeBaseAndAccessStr(CallInst *Call,
+                                                        std::string &AccessStr,
+                                                        std::string &AccessKey,
+                                                        uint32_t Kind,
+                                                        MDNode *&TypeMeta) {
+  Value *Base = nullptr;
+  std::vector<uint64_t> AccessIndices;
+  uint64_t TypeNameIndex = 0;
+  std::string LastTypeName;
+
+  while (Call) {
+    // Base of original corresponding GEP
+    Base = Call->getArgOperand(0);
+
+    // Type Name
+    std::string TypeName;
+    MDNode *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;
+
+      TypeName = Ty->getName();
+    }
+
+    // Access Index
+    uint64_t AccessIndex;
+    uint32_t ArgIndex = (Kind == BPFPreserveUnionAI) ? 1 : 2;
+    if (!getAccessIndex(Call->getArgOperand(ArgIndex), AccessIndex))
+      return nullptr;
+
+    AccessIndices.push_back(AccessIndex);
+    if (TypeName.size()) {
+      TypeNameIndex = AccessIndices.size() - 1;
+      LastTypeName = TypeName;
+      TypeMeta = MDN;
+    }
+
+    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 AccessStr.
+  for (unsigned I = 0; I < AccessIndices.size(); ++I)
+    AccessStr = std::to_string(AccessIndices[I]) + ":" + AccessStr;
+
+  if (TypeNameIndex == AccessIndices.size() - 1)
+    AccessStr = "0:" + AccessStr;
+
+  // Access key is the type name + access string, uniquely identifying
+  // one kernel memory access.
+  AccessKey = LastTypeName + ":" + AccessStr;
+
+  return Base;
+}
+
+/// 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) {
+  std::string AccessStr, AccessKey;
+  MDNode *TypeMeta = nullptr;
+  Value *Base =
+      computeBaseAndAccessStr(Call, AccessStr, AccessKey, Kind, TypeMeta);
+  if (!Base)
+    return false;
+
+  // Do the transformation
+  // 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:
+  //   %7 = bitcast %struct.sk_buff* %2 to i8*
+  //   %8 = getelementptr i8, i8* %7, %6
+  //   %9 = bitcast i8* %8 to i64*
+  //   using %9 instead of %4
+  // The original Call inst is removed.
+  BasicBlock *BB = Call->getParent();
+  GlobalVariable *GV;
+
+  if (GEPGlobals.find(AccessKey) == GEPGlobals.end()) {
+    GV = new GlobalVariable(M, Type::getInt64Ty(BB->getContext()), false,
+                            GlobalVariable::ExternalLinkage, NULL, AccessStr);
+    GV->addAttribute(BPFCoreSharedInfo::AmaAttr);
+    // Set the metadata (debuginfo types) for the global.
+    if (TypeMeta)
+      GV->setMetadata(LLVMContext::MD_preserve_access_index, TypeMeta);
+    GEPGlobals[AccessKey] = GV;
+  } else {
+    GV = GEPGlobals[AccessKey];
+  }
+
+  // Load the global variable.
+  auto *LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV);
+  BB->getInstList().insert(Call->getIterator(), LDInst);
+
+  // Generate a BitCast
+  auto *BCInst = new BitCastInst(Base, Type::getInt8PtrTy(BB->getContext()));
+  BB->getInstList().insert(Call->getIterator(), BCInst);
+
+  // Generate a GetElementPtr
+  auto *GEP = GetElementPtrInst::Create(Type::getInt8Ty(BB->getContext()),
+                                        BCInst, LDInst);
+  BB->getInstList().insert(Call->getIterator(), GEP);
+
+  // Generate a BitCast
+  auto *BCInst2 = new BitCastInst(GEP, Call->getType());
+  BB->getInstList().insert(Call->getIterator(), BCInst2);
+
+  Call->replaceAllUsesWith(BCInst2);
+  Call->eraseFromParent();
+
+  return true;
+}
+
+bool BPFAbstractMemberAccess::doTransformation(Module &M) {
+  bool Transformed = false;
+
+  for (Function &F : M) {
+    // Collect PreserveDIAccessIndex Intrinsic call chains.
+    // The call chains will be used to generate the access
+    // patterns similar to GEP.
+    collectAICallChains(M, F);
+
+    for (auto &C : BaseAICalls)
+      Transformed = transformGEPChain(M, C.first, C.second) || Transformed;
+  }
+
+  return removePreserveAccessIndexIntrinsic(M) || Transformed;
+}

Modified: llvm/trunk/lib/Target/BPF/BPFAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BPFAsmPrinter.cpp?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/lib/Target/BPF/BPFAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/BPF/BPFAsmPrinter.cpp Tue Jul  9 08:28:41 2019
@@ -38,7 +38,7 @@ class BPFAsmPrinter : public AsmPrinter
 public:
   explicit BPFAsmPrinter(TargetMachine &TM,
                          std::unique_ptr<MCStreamer> Streamer)
-      : AsmPrinter(TM, std::move(Streamer)) {}
+      : AsmPrinter(TM, std::move(Streamer)), BTF(nullptr) {}
 
   StringRef getPassName() const override { return "BPF Assembly Printer"; }
   bool doInitialization(Module &M) override;
@@ -49,6 +49,9 @@ public:
                              const char *ExtraCode, raw_ostream &O) override;
 
   void EmitInstruction(const MachineInstr *MI) override;
+
+private:
+  BTFDebug *BTF;
 };
 } // namespace
 
@@ -57,8 +60,10 @@ bool BPFAsmPrinter::doInitialization(Mod
 
   // Only emit BTF when debuginfo available.
   if (MAI->doesSupportDebugInformation() && !empty(M.debug_compile_units())) {
-    Handlers.emplace_back(llvm::make_unique<BTFDebug>(this), "emit",
-                          "Debug Info Emission", "BTF", "BTF Emission");
+    BTF = new BTFDebug(this);
+    Handlers.push_back(HandlerInfo(std::unique_ptr<BTFDebug>(BTF), "emit",
+                                   "Debug Info Emission", "BTF",
+                                   "BTF Emission"));
   }
 
   return false;
@@ -133,11 +138,12 @@ bool BPFAsmPrinter::PrintAsmMemoryOperan
 }
 
 void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) {
-
-  BPFMCInstLower MCInstLowering(OutContext, *this);
-
   MCInst TmpInst;
-  MCInstLowering.Lower(MI, TmpInst);
+
+  if (!BTF || !BTF->InstLower(MI, TmpInst)) {
+    BPFMCInstLower MCInstLowering(OutContext, *this);
+    MCInstLowering.Lower(MI, TmpInst);
+  }
   EmitToStreamer(*OutStreamer, TmpInst);
 }
 

Added: llvm/trunk/lib/Target/BPF/BPFCORE.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BPFCORE.h?rev=365503&view=auto
==============================================================================
--- llvm/trunk/lib/Target/BPF/BPFCORE.h (added)
+++ llvm/trunk/lib/Target/BPF/BPFCORE.h Tue Jul  9 08:28:41 2019
@@ -0,0 +1,24 @@
+//===- BPFCORE.h - Common info for Compile-Once Run-EveryWhere  -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_BPF_BPFCORE_H
+#define LLVM_LIB_TARGET_BPF_BPFCORE_H
+
+namespace llvm {
+
+class BPFCoreSharedInfo {
+public:
+  /// The attribute attached to globals representing a member offset
+  static const std::string AmaAttr;
+  /// The section name to identify a patchable external global
+  static const std::string PatchableExtSecName;
+};
+
+} // namespace llvm
+
+#endif

Added: llvm/trunk/lib/Target/BPF/BPFMISimplifyPatchable.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BPFMISimplifyPatchable.cpp?rev=365503&view=auto
==============================================================================
--- llvm/trunk/lib/Target/BPF/BPFMISimplifyPatchable.cpp (added)
+++ llvm/trunk/lib/Target/BPF/BPFMISimplifyPatchable.cpp Tue Jul  9 08:28:41 2019
@@ -0,0 +1,163 @@
+//===----- BPFMISimplifyPatchable.cpp - MI Simplify Patchable Insts -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass targets a subset of instructions like below
+//    ld_imm64 r1, @global
+//    ldd r2, r1, 0
+//    add r3, struct_base_reg, r2
+//
+// Here @global should either present a AMA (abstruct member access) or
+// a patchable extern variable. And these two kinds of accesses
+// are subject to bpf load time patching. After this pass, the
+// code becomes
+//    ld_imm64 r1, @global
+//    add r3, struct_base_reg, r1
+//
+// Eventually, at BTF output stage, a relocation record will be generated
+// for ld_imm64 which should be replaced later by bpf loader:
+//    r1 = <calculated offset> or <to_be_patched_extern_val>
+//    add r3, struct_base_reg, r1
+// or
+//    ld_imm64 r1, <to_be_patched_extern_val>
+//    add r3, struct_base_reg, r1
+//
+//===----------------------------------------------------------------------===//
+
+#include "BPF.h"
+#include "BPFCORE.h"
+#include "BPFInstrInfo.h"
+#include "BPFTargetMachine.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "bpf-mi-simplify-patchable"
+
+namespace {
+
+struct BPFMISimplifyPatchable : public MachineFunctionPass {
+
+  static char ID;
+  const BPFInstrInfo *TII;
+  MachineFunction *MF;
+
+  BPFMISimplifyPatchable() : MachineFunctionPass(ID) {
+    initializeBPFMISimplifyPatchablePass(*PassRegistry::getPassRegistry());
+  }
+
+private:
+  // Initialize class variables.
+  void initialize(MachineFunction &MFParm);
+
+  bool removeLD(void);
+
+public:
+  // Main entry point for this pass.
+  bool runOnMachineFunction(MachineFunction &MF) override {
+    if (!skipFunction(MF.getFunction())) {
+      initialize(MF);
+    }
+    return removeLD();
+  }
+};
+
+// Initialize class variables.
+void BPFMISimplifyPatchable::initialize(MachineFunction &MFParm) {
+  MF = &MFParm;
+  TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
+  LLVM_DEBUG(dbgs() << "*** BPF simplify patchable insts pass ***\n\n");
+}
+
+/// Remove unneeded Load instructions.
+bool BPFMISimplifyPatchable::removeLD() {
+  MachineRegisterInfo *MRI = &MF->getRegInfo();
+  MachineInstr *ToErase = nullptr;
+  bool Changed = false;
+
+  for (MachineBasicBlock &MBB : *MF) {
+    for (MachineInstr &MI : MBB) {
+      if (ToErase) {
+        ToErase->eraseFromParent();
+        ToErase = nullptr;
+      }
+
+      // Ensure the register format is LOAD <reg>, <reg>, 0
+      if (MI.getOpcode() != BPF::LDD && MI.getOpcode() != BPF::LDW &&
+          MI.getOpcode() != BPF::LDH && MI.getOpcode() != BPF::LDB &&
+          MI.getOpcode() != BPF::LDW32 && MI.getOpcode() != BPF::LDH32 &&
+          MI.getOpcode() != BPF::LDB32)
+        continue;
+
+      if (!MI.getOperand(0).isReg() || !MI.getOperand(1).isReg())
+        continue;
+
+      if (!MI.getOperand(2).isImm() || MI.getOperand(2).getImm())
+        continue;
+
+      unsigned DstReg = MI.getOperand(0).getReg();
+      unsigned SrcReg = MI.getOperand(1).getReg();
+      int64_t ImmVal = MI.getOperand(2).getImm();
+
+      MachineInstr *DefInst = MRI->getUniqueVRegDef(SrcReg);
+      if (!DefInst)
+        continue;
+
+      bool IsCandidate = false;
+      if (DefInst->getOpcode() == BPF::LD_imm64) {
+        const MachineOperand &MO = DefInst->getOperand(1);
+        if (MO.isGlobal()) {
+          const GlobalValue *GVal = MO.getGlobal();
+          auto *GVar = dyn_cast<GlobalVariable>(GVal);
+          if (GVar) {
+            // Global variables representing structure offset or
+            // patchable extern globals.
+            if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) {
+              assert(ImmVal == 0);
+              IsCandidate = true;
+            } else if (!GVar->hasInitializer() && GVar->hasExternalLinkage() &&
+                       GVar->getSection() ==
+                           BPFCoreSharedInfo::PatchableExtSecName) {
+              if (ImmVal == 0)
+                IsCandidate = true;
+              else
+                errs() << "WARNING: unhandled patchable extern "
+                       << GVar->getName() << " with load offset " << ImmVal
+                       << "\n";
+            }
+          }
+        }
+      }
+
+      if (!IsCandidate)
+        continue;
+
+      auto Begin = MRI->use_begin(DstReg), End = MRI->use_end();
+      decltype(End) NextI;
+      for (auto I = Begin; I != End; I = NextI) {
+        NextI = std::next(I);
+        I->setReg(SrcReg);
+      }
+
+      ToErase = &MI;
+      Changed = true;
+    }
+  }
+
+  return Changed;
+}
+
+} // namespace
+
+INITIALIZE_PASS(BPFMISimplifyPatchable, DEBUG_TYPE,
+                "BPF PreEmit SimplifyPatchable", false, false)
+
+char BPFMISimplifyPatchable::ID = 0;
+FunctionPass *llvm::createBPFMISimplifyPatchablePass() {
+  return new BPFMISimplifyPatchable();
+}

Modified: llvm/trunk/lib/Target/BPF/BPFTargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BPFTargetMachine.cpp?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/lib/Target/BPF/BPFTargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/BPF/BPFTargetMachine.cpp Tue Jul  9 08:28:41 2019
@@ -34,6 +34,7 @@ extern "C" void LLVMInitializeBPFTarget(
   RegisterTargetMachine<BPFTargetMachine> Z(getTheBPFTarget());
 
   PassRegistry &PR = *PassRegistry::getPassRegistry();
+  initializeBPFAbstractMemberAccessPass(PR);
   initializeBPFMIPeepholePass(PR);
 }
 
@@ -68,6 +69,7 @@ BPFTargetMachine::BPFTargetMachine(const
       static_cast<BPFMCAsmInfo *>(const_cast<MCAsmInfo *>(AsmInfo.get()));
   MAI->setDwarfUsesRelocationsAcrossSections(!Subtarget.getUseDwarfRIS());
 }
+
 namespace {
 // BPF Code Generator Pass Configuration Options.
 class BPFPassConfig : public TargetPassConfig {
@@ -79,6 +81,7 @@ public:
     return getTM<BPFTargetMachine>();
   }
 
+  void addIRPasses() override;
   bool addInstSelector() override;
   void addMachineSSAOptimization() override;
   void addPreEmitPass() override;
@@ -89,6 +92,13 @@ TargetPassConfig *BPFTargetMachine::crea
   return new BPFPassConfig(*this, PM);
 }
 
+void BPFPassConfig::addIRPasses() {
+
+  addPass(createBPFAbstractMemberAccess());
+
+  TargetPassConfig::addIRPasses();
+}
+
 // Install an instruction selector pass using
 // the ISelDag to gen BPF code.
 bool BPFPassConfig::addInstSelector() {
@@ -98,6 +108,8 @@ bool BPFPassConfig::addInstSelector() {
 }
 
 void BPFPassConfig::addMachineSSAOptimization() {
+  addPass(createBPFMISimplifyPatchablePass());
+
   // The default implementation must be called first as we want eBPF
   // Peephole ran at last.
   TargetPassConfig::addMachineSSAOptimization();

Modified: llvm/trunk/lib/Target/BPF/BTF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BTF.h?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/lib/Target/BPF/BTF.h (original)
+++ llvm/trunk/lib/Target/BPF/BTF.h Tue Jul  9 08:28:41 2019
@@ -17,7 +17,7 @@
 ///
 /// The binary layout for .BTF.ext section:
 ///   struct ExtHeader
-///   FuncInfo and LineInfo subsections
+///   FuncInfo, LineInfo, OffsetReloc and ExternReloc subsections
 /// The FuncInfo subsection is defined as below:
 ///   BTFFuncInfo Size
 ///   struct SecFuncInfo for ELF section #1
@@ -32,6 +32,20 @@
 ///   struct SecLineInfo for ELF section #2
 ///   A number of struct BPFLineInfo for ELF section #2
 ///   ...
+/// The OffsetReloc subsection is defined as below:
+///   BPFOffsetReloc Size
+///   struct SecOffsetReloc for ELF section #1
+///   A number of struct BPFOffsetReloc for ELF section #1
+///   struct SecOffsetReloc for ELF section #2
+///   A number of struct BPFOffsetReloc for ELF section #2
+///   ...
+/// The ExternReloc subsection is defined as below:
+///   BPFExternReloc Size
+///   struct SecExternReloc for ELF section #1
+///   A number of struct BPFExternReloc for ELF section #1
+///   struct SecExternReloc for ELF section #2
+///   A number of struct BPFExternReloc for ELF section #2
+///   ...
 ///
 /// The section formats are also defined at
 ///    https://github.com/torvalds/linux/blob/master/include/uapi/linux/btf.h
@@ -49,7 +63,7 @@ enum : uint32_t { MAGIC = 0xeB9F, VERSIO
 /// Sizes in bytes of various things in the BTF format.
 enum {
   HeaderSize = 24,
-  ExtHeaderSize = 24,
+  ExtHeaderSize = 40,
   CommonTypeSize = 12,
   BTFArraySize = 12,
   BTFEnumSize = 8,
@@ -58,8 +72,12 @@ enum {
   BTFDataSecVarSize = 12,
   SecFuncInfoSize = 8,
   SecLineInfoSize = 8,
+  SecOffsetRelocSize = 8,
+  SecExternRelocSize = 8,
   BPFFuncInfoSize = 8,
-  BPFLineInfoSize = 16
+  BPFLineInfoSize = 16,
+  BPFOffsetRelocSize = 12,
+  BPFExternRelocSize = 8,
 };
 
 /// The .BTF section header definition.
@@ -191,10 +209,14 @@ struct ExtHeader {
   uint8_t Flags;
   uint32_t HdrLen;
 
-  uint32_t FuncInfoOff; ///< Offset of func info section
-  uint32_t FuncInfoLen; ///< Length of func info section
-  uint32_t LineInfoOff; ///< Offset of line info section
-  uint32_t LineInfoLen; ///< Length of line info section
+  uint32_t FuncInfoOff;    ///< Offset of func info section
+  uint32_t FuncInfoLen;    ///< Length of func info section
+  uint32_t LineInfoOff;    ///< Offset of line info section
+  uint32_t LineInfoLen;    ///< Length of line info section
+  uint32_t OffsetRelocOff; ///< Offset of offset reloc section
+  uint32_t OffsetRelocLen; ///< Length of offset reloc section
+  uint32_t ExternRelocOff; ///< Offset of extern reloc section
+  uint32_t ExternRelocLen; ///< Length of extern reloc section
 };
 
 /// Specifying one function info.
@@ -220,10 +242,35 @@ struct BPFLineInfo {
 
 /// Specifying line info's in one section.
 struct SecLineInfo {
-  uint32_t SecNameOff;  ///< Section name index in the .BTF string tble
+  uint32_t SecNameOff;  ///< Section name index in the .BTF string table
   uint32_t NumLineInfo; ///< Number of line info's in this section
 };
 
+/// Specifying one offset relocation.
+struct BPFOffsetReloc {
+  uint32_t InsnOffset;    ///< Byte offset in this section
+  uint32_t TypeID;        ///< TypeID for the relocation
+  uint32_t OffsetNameOff; ///< The string to traverse types
+};
+
+/// Specifying offset relocation's in one section.
+struct SecOffsetReloc {
+  uint32_t SecNameOff;     ///< Section name index in the .BTF string table
+  uint32_t NumOffsetReloc; ///< Number of offset reloc's in this section
+};
+
+/// Specifying one offset relocation.
+struct BPFExternReloc {
+  uint32_t InsnOffset;    ///< Byte offset in this section
+  uint32_t ExternNameOff; ///< The string for external variable
+};
+
+/// Specifying extern relocation's in one section.
+struct SecExternReloc {
+  uint32_t SecNameOff;     ///< Section name index in the .BTF string table
+  uint32_t NumExternReloc; ///< Number of extern reloc's in this section
+};
+
 } // End namespace BTF.
 } // End namespace llvm.
 

Modified: llvm/trunk/lib/Target/BPF/BTFDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BTFDebug.cpp?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/lib/Target/BPF/BTFDebug.cpp (original)
+++ llvm/trunk/lib/Target/BPF/BTFDebug.cpp Tue Jul  9 08:28:41 2019
@@ -11,6 +11,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "BTFDebug.h"
+#include "BPF.h"
+#include "BPFCORE.h"
+#include "MCTargetDesc/BPFMCTargetDesc.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
@@ -37,8 +40,9 @@ void BTFTypeBase::emitType(MCStreamer &O
   OS.EmitIntValue(BTFType.Size, 4);
 }
 
-BTFTypeDerived::BTFTypeDerived(const DIDerivedType *DTy, unsigned Tag)
-    : DTy(DTy) {
+BTFTypeDerived::BTFTypeDerived(const DIDerivedType *DTy, unsigned Tag,
+                               bool NeedsFixup)
+    : DTy(DTy), NeedsFixup(NeedsFixup) {
   switch (Tag) {
   case dwarf::DW_TAG_pointer_type:
     Kind = BTF::BTF_KIND_PTR;
@@ -62,8 +66,15 @@ BTFTypeDerived::BTFTypeDerived(const DID
 }
 
 void BTFTypeDerived::completeType(BTFDebug &BDebug) {
+  if (IsCompleted)
+    return;
+  IsCompleted = true;
+
   BTFType.NameOff = BDebug.addString(DTy->getName());
 
+  if (NeedsFixup)
+    return;
+
   // The base type for PTR/CONST/VOLATILE could be void.
   const DIType *ResolvedType = DTy->getBaseType();
   if (!ResolvedType) {
@@ -78,6 +89,10 @@ void BTFTypeDerived::completeType(BTFDeb
 
 void BTFTypeDerived::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); }
 
+void BTFTypeDerived::setPointeeType(uint32_t PointeeType) {
+  BTFType.Type = PointeeType;
+}
+
 /// Represent a struct/union forward declaration.
 BTFTypeFwd::BTFTypeFwd(StringRef Name, bool IsUnion) : Name(Name) {
   Kind = BTF::BTF_KIND_FWD;
@@ -86,6 +101,10 @@ BTFTypeFwd::BTFTypeFwd(StringRef Name, b
 }
 
 void BTFTypeFwd::completeType(BTFDebug &BDebug) {
+  if (IsCompleted)
+    return;
+  IsCompleted = true;
+
   BTFType.NameOff = BDebug.addString(Name);
 }
 
@@ -119,6 +138,10 @@ BTFTypeInt::BTFTypeInt(uint32_t Encoding
 }
 
 void BTFTypeInt::completeType(BTFDebug &BDebug) {
+  if (IsCompleted)
+    return;
+  IsCompleted = true;
+
   BTFType.NameOff = BDebug.addString(Name);
 }
 
@@ -135,6 +158,10 @@ BTFTypeEnum::BTFTypeEnum(const DIComposi
 }
 
 void BTFTypeEnum::completeType(BTFDebug &BDebug) {
+  if (IsCompleted)
+    return;
+  IsCompleted = true;
+
   BTFType.NameOff = BDebug.addString(ETy->getName());
 
   DINodeArray Elements = ETy->getElements();
@@ -157,7 +184,9 @@ void BTFTypeEnum::emitType(MCStreamer &O
   }
 }
 
-BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems) {
+BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t ElemSize,
+                           uint32_t NumElems)
+    : ElemSize(ElemSize) {
   Kind = BTF::BTF_KIND_ARRAY;
   BTFType.NameOff = 0;
   BTFType.Info = Kind << 24;
@@ -169,6 +198,9 @@ BTFTypeArray::BTFTypeArray(uint32_t Elem
 
 /// Represent a BTF array.
 void BTFTypeArray::completeType(BTFDebug &BDebug) {
+  if (IsCompleted)
+    return;
+  IsCompleted = true;
 
   // The IR does not really have a type for the index.
   // A special type for array index should have been
@@ -184,6 +216,12 @@ void BTFTypeArray::emitType(MCStreamer &
   OS.EmitIntValue(ArrayInfo.Nelems, 4);
 }
 
+void BTFTypeArray::getLocInfo(uint32_t Loc, uint32_t &LocOffset,
+                              uint32_t &ElementTypeId) {
+  ElementTypeId = ArrayInfo.ElemType;
+  LocOffset = Loc * ElemSize;
+}
+
 /// Represent either a struct or a union.
 BTFTypeStruct::BTFTypeStruct(const DICompositeType *STy, bool IsStruct,
                              bool HasBitField, uint32_t Vlen)
@@ -194,6 +232,10 @@ BTFTypeStruct::BTFTypeStruct(const DICom
 }
 
 void BTFTypeStruct::completeType(BTFDebug &BDebug) {
+  if (IsCompleted)
+    return;
+  IsCompleted = true;
+
   BTFType.NameOff = BDebug.addString(STy->getName());
 
   // Add struct/union members.
@@ -224,6 +266,17 @@ void BTFTypeStruct::emitType(MCStreamer
   }
 }
 
+std::string BTFTypeStruct::getName() { return STy->getName(); }
+
+void BTFTypeStruct::getMemberInfo(uint32_t Loc, uint32_t &MemberOffset,
+                                  uint32_t &MemberType) {
+  MemberType = Members[Loc].Type;
+  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
@@ -238,6 +291,10 @@ BTFTypeFuncProto::BTFTypeFuncProto(
 }
 
 void BTFTypeFuncProto::completeType(BTFDebug &BDebug) {
+  if (IsCompleted)
+    return;
+  IsCompleted = true;
+
   DITypeRefArray Elements = STy->getTypeArray();
   auto RetType = Elements[0];
   BTFType.Type = RetType ? BDebug.getTypeId(RetType) : 0;
@@ -275,6 +332,10 @@ BTFTypeFunc::BTFTypeFunc(StringRef FuncN
 }
 
 void BTFTypeFunc::completeType(BTFDebug &BDebug) {
+  if (IsCompleted)
+    return;
+  IsCompleted = true;
+
   BTFType.NameOff = BDebug.addString(Name);
 }
 
@@ -335,7 +396,8 @@ uint32_t BTFStringTable::addString(Strin
 
 BTFDebug::BTFDebug(AsmPrinter *AP)
     : DebugHandlerBase(AP), OS(*Asm->OutStreamer), SkipInstruction(false),
-      LineInfoGenerated(false), SecNameOff(0), ArrayIndexTypeId(0) {
+      LineInfoGenerated(false), SecNameOff(0), ArrayIndexTypeId(0),
+      MapDefNotCollected(true) {
   addString("\0");
 }
 
@@ -417,6 +479,7 @@ void BTFDebug::visitStructType(const DIC
 
   auto TypeEntry =
       llvm::make_unique<BTFTypeStruct>(CTy, IsStruct, HasBitField, VLen);
+  StructTypes.push_back(TypeEntry.get());
   TypeId = addType(std::move(TypeEntry), CTy);
 
   // Visit all struct members.
@@ -426,11 +489,14 @@ void BTFDebug::visitStructType(const DIC
 
 void BTFDebug::visitArrayType(const DICompositeType *CTy, uint32_t &TypeId) {
   // Visit array element type.
-  uint32_t ElemTypeId;
-  visitTypeEntry(CTy->getBaseType(), ElemTypeId);
+  uint32_t ElemTypeId, ElemSize;
+  const DIType *ElemType = CTy->getBaseType();
+  visitTypeEntry(ElemType, ElemTypeId, false, false);
+  ElemSize = ElemType->getSizeInBits() >> 3;
 
   if (!CTy->getSizeInBits()) {
-    auto TypeEntry = llvm::make_unique<BTFTypeArray>(ElemTypeId, 0);
+    auto TypeEntry = llvm::make_unique<BTFTypeArray>(ElemTypeId, 0, 0);
+    ArrayTypes.push_back(TypeEntry.get());
     ElemTypeId = addType(std::move(TypeEntry), CTy);
   } else {
     // Visit array dimensions.
@@ -442,11 +508,14 @@ void BTFDebug::visitArrayType(const DICo
           auto *CI = SR->getCount().dyn_cast<ConstantInt *>();
           int64_t Count = CI->getSExtValue();
 
-          auto TypeEntry = llvm::make_unique<BTFTypeArray>(ElemTypeId, Count);
+          auto TypeEntry =
+              llvm::make_unique<BTFTypeArray>(ElemTypeId, ElemSize, Count);
+          ArrayTypes.push_back(TypeEntry.get());
           if (I == 0)
             ElemTypeId = addType(std::move(TypeEntry), CTy);
           else
             ElemTypeId = addType(std::move(TypeEntry));
+          ElemSize = ElemSize * Count;
         }
     }
   }
@@ -498,13 +567,42 @@ void BTFDebug::visitCompositeType(const
 }
 
 /// Handle pointer, typedef, const, volatile, restrict and member types.
-void BTFDebug::visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId) {
+void BTFDebug::visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,
+                                bool CheckPointer, bool SeenPointer) {
   unsigned Tag = DTy->getTag();
 
+  /// Try to avoid chasing pointees, esp. structure pointees which may
+  /// unnecessary bring in a lot of types.
+  if (CheckPointer && !SeenPointer) {
+    SeenPointer = Tag == dwarf::DW_TAG_pointer_type;
+  }
+
+  if (CheckPointer && SeenPointer) {
+    const DIType *Base = DTy->getBaseType();
+    if (Base) {
+      if (const auto *CTy = dyn_cast<DICompositeType>(Base)) {
+        auto CTag = CTy->getTag();
+        if ((CTag == dwarf::DW_TAG_structure_type ||
+             CTag == dwarf::DW_TAG_union_type) &&
+            !CTy->isForwardDecl()) {
+          /// Find a candidate, generate a fixup. Later on the struct/union
+          /// pointee type will be replaced with either a real type or
+          /// a forward declaration.
+          auto TypeEntry = llvm::make_unique<BTFTypeDerived>(DTy, Tag, true);
+          auto &Fixup = FixupDerivedTypes[CTy->getName()];
+          Fixup.first = CTag == dwarf::DW_TAG_union_type;
+          Fixup.second.push_back(TypeEntry.get());
+          TypeId = addType(std::move(TypeEntry), DTy);
+          return;
+        }
+      }
+    }
+  }
+
   if (Tag == dwarf::DW_TAG_pointer_type || Tag == dwarf::DW_TAG_typedef ||
       Tag == dwarf::DW_TAG_const_type || Tag == dwarf::DW_TAG_volatile_type ||
       Tag == dwarf::DW_TAG_restrict_type) {
-    auto TypeEntry = llvm::make_unique<BTFTypeDerived>(DTy, Tag);
+    auto TypeEntry = llvm::make_unique<BTFTypeDerived>(DTy, Tag, false);
     TypeId = addType(std::move(TypeEntry), DTy);
   } else if (Tag != dwarf::DW_TAG_member) {
     return;
@@ -513,10 +611,14 @@ void BTFDebug::visitDerivedType(const DI
   // Visit base type of pointer, typedef, const, volatile, restrict or
   // struct/union member.
   uint32_t TempTypeId = 0;
-  visitTypeEntry(DTy->getBaseType(), TempTypeId);
+  if (Tag == dwarf::DW_TAG_member)
+    visitTypeEntry(DTy->getBaseType(), TempTypeId, true, false);
+  else
+    visitTypeEntry(DTy->getBaseType(), TempTypeId, CheckPointer, SeenPointer);
 }
 
-void BTFDebug::visitTypeEntry(const DIType *Ty, uint32_t &TypeId) {
+void BTFDebug::visitTypeEntry(const DIType *Ty, uint32_t &TypeId,
+                              bool CheckPointer, bool SeenPointer) {
   if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
     TypeId = DIToIdMap[Ty];
     return;
@@ -530,14 +632,52 @@ void BTFDebug::visitTypeEntry(const DITy
   else if (const auto *CTy = dyn_cast<DICompositeType>(Ty))
     visitCompositeType(CTy, TypeId);
   else if (const auto *DTy = dyn_cast<DIDerivedType>(Ty))
-    visitDerivedType(DTy, TypeId);
+    visitDerivedType(DTy, TypeId, CheckPointer, SeenPointer);
   else
     llvm_unreachable("Unknown DIType");
 }
 
 void BTFDebug::visitTypeEntry(const DIType *Ty) {
   uint32_t TypeId;
-  visitTypeEntry(Ty, TypeId);
+  visitTypeEntry(Ty, TypeId, false, false);
+}
+
+void BTFDebug::visitMapDefType(const DIType *Ty, uint32_t &TypeId) {
+  if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
+    TypeId = DIToIdMap[Ty];
+    return;
+  }
+
+  // MapDef type is a struct type
+  const auto *CTy = dyn_cast<DICompositeType>(Ty);
+  if (!CTy)
+    return;
+
+  auto Tag = CTy->getTag();
+  if (Tag != dwarf::DW_TAG_structure_type || CTy->isForwardDecl())
+    return;
+
+  // Record this type
+  const DINodeArray Elements = CTy->getElements();
+  bool HasBitField = false;
+  for (const auto *Element : Elements) {
+    auto E = cast<DIDerivedType>(Element);
+    if (E->isBitField()) {
+      HasBitField = true;
+      break;
+    }
+  }
+
+  auto TypeEntry =
+      llvm::make_unique<BTFTypeStruct>(CTy, true, HasBitField, Elements.size());
+  StructTypes.push_back(TypeEntry.get());
+  TypeId = addType(std::move(TypeEntry), CTy);
+
+  // Visit all struct members
+  for (const auto *Element : Elements) {
+    const auto *MemberType = cast<DIDerivedType>(Element);
+    visitTypeEntry(MemberType->getBaseType());
+  }
 }
 
 /// Read file contents from the actual file or from the source
@@ -635,7 +775,8 @@ void BTFDebug::emitBTFSection() {
 
 void BTFDebug::emitBTFExtSection() {
   // Do not emit section if empty FuncInfoTable and LineInfoTable.
-  if (!FuncInfoTable.size() && !LineInfoTable.size())
+  if (!FuncInfoTable.size() && !LineInfoTable.size() &&
+      !OffsetRelocTable.size() && !ExternRelocTable.size())
     return;
 
   MCContext &Ctx = OS.getContext();
@@ -647,6 +788,8 @@ void BTFDebug::emitBTFExtSection() {
 
   // Account for FuncInfo/LineInfo record size as well.
   uint32_t FuncLen = 4, LineLen = 4;
+  // Do not account for optional OffsetReloc/ExternReloc.
+  uint32_t OffsetRelocLen = 0, ExternRelocLen = 0;
   for (const auto &FuncSec : FuncInfoTable) {
     FuncLen += BTF::SecFuncInfoSize;
     FuncLen += FuncSec.second.size() * BTF::BPFFuncInfoSize;
@@ -655,11 +798,28 @@ void BTFDebug::emitBTFExtSection() {
     LineLen += BTF::SecLineInfoSize;
     LineLen += LineSec.second.size() * BTF::BPFLineInfoSize;
   }
+  for (const auto &OffsetRelocSec : OffsetRelocTable) {
+    OffsetRelocLen += BTF::SecOffsetRelocSize;
+    OffsetRelocLen += OffsetRelocSec.second.size() * BTF::BPFOffsetRelocSize;
+  }
+  for (const auto &ExternRelocSec : ExternRelocTable) {
+    ExternRelocLen += BTF::SecExternRelocSize;
+    ExternRelocLen += ExternRelocSec.second.size() * BTF::BPFExternRelocSize;
+  }
+
+  if (OffsetRelocLen)
+    OffsetRelocLen += 4;
+  if (ExternRelocLen)
+    ExternRelocLen += 4;
 
   OS.EmitIntValue(0, 4);
   OS.EmitIntValue(FuncLen, 4);
   OS.EmitIntValue(FuncLen, 4);
   OS.EmitIntValue(LineLen, 4);
+  OS.EmitIntValue(FuncLen + LineLen, 4);
+  OS.EmitIntValue(OffsetRelocLen, 4);
+  OS.EmitIntValue(FuncLen + LineLen + OffsetRelocLen, 4);
+  OS.EmitIntValue(ExternRelocLen, 4);
 
   // Emit func_info table.
   OS.AddComment("FuncInfo");
@@ -692,6 +852,39 @@ void BTFDebug::emitBTFExtSection() {
       OS.EmitIntValue(LineInfo.LineNum << 10 | LineInfo.ColumnNum, 4);
     }
   }
+
+  // Emit offset reloc table.
+  if (OffsetRelocLen) {
+    OS.AddComment("OffsetReloc");
+    OS.EmitIntValue(BTF::BPFOffsetRelocSize, 4);
+    for (const auto &OffsetRelocSec : OffsetRelocTable) {
+      OS.AddComment("Offset reloc section string offset=" +
+                    std::to_string(OffsetRelocSec.first));
+      OS.EmitIntValue(OffsetRelocSec.first, 4);
+      OS.EmitIntValue(OffsetRelocSec.second.size(), 4);
+      for (const auto &OffsetRelocInfo : OffsetRelocSec.second) {
+        Asm->EmitLabelReference(OffsetRelocInfo.Label, 4);
+        OS.EmitIntValue(OffsetRelocInfo.TypeID, 4);
+        OS.EmitIntValue(OffsetRelocInfo.OffsetNameOff, 4);
+      }
+    }
+  }
+
+  // Emit extern reloc table.
+  if (ExternRelocLen) {
+    OS.AddComment("ExternReloc");
+    OS.EmitIntValue(BTF::BPFExternRelocSize, 4);
+    for (const auto &ExternRelocSec : ExternRelocTable) {
+      OS.AddComment("Extern reloc section string offset=" +
+                    std::to_string(ExternRelocSec.first));
+      OS.EmitIntValue(ExternRelocSec.first, 4);
+      OS.EmitIntValue(ExternRelocSec.second.size(), 4);
+      for (const auto &ExternRelocInfo : ExternRelocSec.second) {
+        Asm->EmitLabelReference(ExternRelocInfo.Label, 4);
+        OS.EmitIntValue(ExternRelocInfo.ExternNameOff, 4);
+      }
+    }
+  }
 }
 
 void BTFDebug::beginFunctionImpl(const MachineFunction *MF) {
@@ -704,6 +897,30 @@ void BTFDebug::beginFunctionImpl(const M
   }
   SkipInstruction = false;
 
+  // Collect MapDef types. Map definition needs to collect
+  // pointee types. Do it first. Otherwise, for the following
+  // case:
+  //    struct m { ...};
+  //    struct t {
+  //      struct m *key;
+  //    };
+  //    foo(struct t *arg);
+  //
+  //    struct mapdef {
+  //      ...
+  //      struct m *key;
+  //      ...
+  //    } __attribute__((section(".maps"))) hash_map;
+  //
+  // If subroutine foo is traversed first, a type chain
+  // "ptr->struct m(fwd)" will be created and later on
+  // when traversing mapdef, since "ptr->struct m" exists,
+  // the traversal of "struct m" will be omitted.
+  if (MapDefNotCollected) {
+    processGlobals(true);
+    MapDefNotCollected = false;
+  }
+
   // Collect all types locally referenced in this function.
   // Use RetainedNodes so we can collect all argument names
   // even if the argument is not used.
@@ -728,6 +945,9 @@ void BTFDebug::beginFunctionImpl(const M
       llvm::make_unique<BTFTypeFunc>(SP->getName(), ProtoTypeId);
   uint32_t FuncTypeId = addType(std::move(FuncTypeEntry));
 
+  for (const auto &TypeEntry : TypeEntries)
+    TypeEntry->completeType(*this);
+
   // Construct funcinfo and the first lineinfo for the function.
   MCSymbol *FuncLabel = Asm->getFunctionBegin();
   BTFFuncInfo FuncInfo;
@@ -750,6 +970,133 @@ void BTFDebug::endFunctionImpl(const Mac
   SecNameOff = 0;
 }
 
+/// On-demand populate struct types as requested from abstract member
+/// accessing.
+unsigned BTFDebug::populateStructType(const DIType *Ty) {
+  unsigned Id;
+  visitTypeEntry(Ty, Id, false, false);
+  for (const auto &TypeEntry : TypeEntries)
+    TypeEntry->completeType(*this);
+  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();
+
+  BTFOffsetReloc OffsetReloc;
+  OffsetReloc.Label = ORSym;
+  OffsetReloc.OffsetNameOff = addString(AccessPattern.drop_back());
+  OffsetReloc.TypeID = RootId;
+
+  uint32_t Start = 0, End = 0, Offset = 0;
+  bool FirstAccess = true;
+  for (auto C : AccessPattern) {
+    if (C != ':') {
+      End++;
+    } else {
+      std::string SubStr = AccessPattern.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);
+      }
+      Start = End + 1;
+      End = Start;
+    }
+  }
+  AccessOffsets[RootTy->getName().str() + ":" + AccessPattern.str()] = Offset;
+  OffsetRelocTable[SecNameOff].push_back(OffsetReloc);
+}
+
+void BTFDebug::processLDimm64(const MachineInstr *MI) {
+  // If the insn is an LD_imm64, the following two cases
+  // will generate an .BTF.ext record.
+  //
+  // If the insn is "r2 = LD_imm64 @__BTF_...",
+  // add this insn into the .BTF.ext OffsetReloc subsection.
+  // Relocation looks like:
+  //  . SecName:
+  //    . InstOffset
+  //    . TypeID
+  //    . OffSetNameOff
+  // Later, the insn is replaced with "r2 = <offset>"
+  // where "<offset>" equals to the offset based on current
+  // type definitions.
+  //
+  // If the insn is "r2 = LD_imm64 @VAR" and VAR is
+  // a patchable external global, add this insn into the .BTF.ext
+  // ExternReloc subsection.
+  // Relocation looks like:
+  //  . SecName:
+  //    . InstOffset
+  //    . ExternNameOff
+  // Later, the insn is replaced with "r2 = <value>" or
+  // "LD_imm64 r2, <value>" where "<value>" = 0.
+
+  // check whether this is a candidate or not
+  const MachineOperand &MO = MI->getOperand(1);
+  if (MO.isGlobal()) {
+    const GlobalValue *GVal = MO.getGlobal();
+    auto *GVar = dyn_cast<GlobalVariable>(GVal);
+    if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) {
+      MCSymbol *ORSym = OS.getContext().createTempSymbol();
+      OS.EmitLabel(ORSym);
+
+      MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index);
+      DIType *Ty = dyn_cast<DIType>(MDN);
+      generateOffsetReloc(MI, ORSym, Ty, GVar->getName());
+    } else if (GVar && !GVar->hasInitializer() && GVar->hasExternalLinkage() &&
+               GVar->getSection() == BPFCoreSharedInfo::PatchableExtSecName) {
+      MCSymbol *ORSym = OS.getContext().createTempSymbol();
+      OS.EmitLabel(ORSym);
+
+      BTFExternReloc ExternReloc;
+      ExternReloc.Label = ORSym;
+      ExternReloc.ExternNameOff = addString(GVar->getName());
+      ExternRelocTable[SecNameOff].push_back(ExternReloc);
+    }
+  }
+}
+
 void BTFDebug::beginInstruction(const MachineInstr *MI) {
   DebugHandlerBase::beginInstruction(MI);
 
@@ -770,6 +1117,9 @@ void BTFDebug::beginInstruction(const Ma
       return;
   }
 
+  if (MI->getOpcode() == BPF::LD_imm64)
+    processLDimm64(MI);
+
   // Skip this instruction if no DebugLoc or the DebugLoc
   // is the same as the previous instruction.
   const DebugLoc &DL = MI->getDebugLoc();
@@ -798,7 +1148,7 @@ void BTFDebug::beginInstruction(const Ma
   PrevInstLoc = DL;
 }
 
-void BTFDebug::processGlobals() {
+void BTFDebug::processGlobals(bool ProcessingMapDef) {
   // Collect all types referenced by globals.
   const Module *M = MMI->getModule();
   for (const GlobalVariable &Global : M->globals()) {
@@ -806,11 +1156,29 @@ void BTFDebug::processGlobals() {
     if (!Global.hasInitializer() && Global.hasExternalLinkage())
       continue;
 
+    // Decide the section name.
+    StringRef SecName;
+    if (Global.hasSection()) {
+      SecName = Global.getSection();
+    } else {
+      // data, bss, or readonly sections
+      if (Global.isConstant())
+        SecName = ".rodata";
+      else
+        SecName = Global.getInitializer()->isZeroValue() ? ".bss" : ".data";
+    }
+
+    if (ProcessingMapDef != SecName.startswith(".maps"))
+      continue;
+
     SmallVector<DIGlobalVariableExpression *, 1> GVs;
     Global.getDebugInfo(GVs);
     uint32_t GVTypeId = 0;
     for (auto *GVE : GVs) {
-      visitTypeEntry(GVE->getVariable()->getType(), GVTypeId);
+      if (SecName.startswith(".maps"))
+        visitMapDefType(GVE->getVariable()->getType(), GVTypeId);
+      else
+        visitTypeEntry(GVE->getVariable()->getType(), GVTypeId, false, false);
       break;
     }
 
@@ -835,18 +1203,6 @@ void BTFDebug::processGlobals() {
         llvm::make_unique<BTFKindVar>(Global.getName(), GVTypeId, GVarInfo);
     uint32_t VarId = addType(std::move(VarEntry));
 
-    // Decide the section name.
-    std::string SecName;
-    if (Global.hasSection()) {
-      SecName = Global.getSection().str();
-    } else {
-      // data, bss, or readonly sections
-      if (Global.isConstant())
-        SecName += ".rodata";
-      else
-        SecName += Global.getInitializer()->isZeroValue() ? ".bss" : ".data";
-    }
-
     // Find or create a DataSec
     if (DataSecEntries.find(SecName) == DataSecEntries.end()) {
       DataSecEntries[SecName] = llvm::make_unique<BTFKindDataSec>(Asm, SecName);
@@ -858,14 +1214,81 @@ void BTFDebug::processGlobals() {
 
     DataSecEntries[SecName]->addVar(VarId, Asm->getSymbol(&Global), Size);
   }
+}
 
-  for (auto &DataSec : DataSecEntries)
-    addType(std::move(DataSec.second));
+/// Emit proper patchable instructions.
+bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) {
+  if (MI->getOpcode() == BPF::LD_imm64) {
+    const MachineOperand &MO = MI->getOperand(1);
+    if (MO.isGlobal()) {
+      const GlobalValue *GVal = MO.getGlobal();
+      auto *GVar = dyn_cast<GlobalVariable>(GVal);
+      if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) {
+        MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index);
+        DIType *Ty = dyn_cast<DIType>(MDN);
+        std::string TypeName = Ty->getName();
+        int64_t Imm = AccessOffsets[TypeName + ":" + GVar->getName().str()];
+
+        // Emit "mov ri, <imm>" for abstract member accesses.
+        OutMI.setOpcode(BPF::MOV_ri);
+        OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
+        OutMI.addOperand(MCOperand::createImm(Imm));
+        return true;
+      } else if (GVar && !GVar->hasInitializer() &&
+                 GVar->hasExternalLinkage() &&
+                 GVar->getSection() == BPFCoreSharedInfo::PatchableExtSecName) {
+        const IntegerType *IntTy = dyn_cast<IntegerType>(GVar->getValueType());
+        assert(IntTy);
+        // For patchable externals, emit "LD_imm64, ri, 0" if the external
+        // variable is 64bit width, emit "mov ri, 0" otherwise.
+        if (IntTy->getBitWidth() == 64)
+          OutMI.setOpcode(BPF::LD_imm64);
+        else
+          OutMI.setOpcode(BPF::MOV_ri);
+        OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
+        OutMI.addOperand(MCOperand::createImm(0));
+        return true;
+      }
+    }
+  }
+  return false;
 }
 
 void BTFDebug::endModule() {
-  // Collect all global types/variables.
-  processGlobals();
+  // Collect MapDef globals if not collected yet.
+  if (MapDefNotCollected) {
+    processGlobals(true);
+    MapDefNotCollected = false;
+  }
+
+  // Collect global types/variables except MapDef globals.
+  processGlobals(false);
+  for (auto &DataSec : DataSecEntries)
+    addType(std::move(DataSec.second));
+
+  // Fixups
+  for (auto &Fixup : FixupDerivedTypes) {
+    StringRef TypeName = Fixup.first;
+    bool IsUnion = Fixup.second.first;
+
+    // Search through struct types
+    uint32_t StructTypeId = 0;
+    for (const auto &StructType : StructTypes) {
+      if (StructType->getName() == TypeName) {
+        StructTypeId = StructType->getId();
+        break;
+      }
+    }
+
+    if (StructTypeId == 0) {
+      auto FwdTypeEntry = llvm::make_unique<BTFTypeFwd>(TypeName, IsUnion);
+      StructTypeId = addType(std::move(FwdTypeEntry));
+    }
+
+    for (auto &DType : Fixup.second.second) {
+      DType->setPointeeType(StructTypeId);
+    }
+  }
 
   // Complete BTF type cross refereences.
   for (const auto &TypeEntry : TypeEntries)

Modified: llvm/trunk/lib/Target/BPF/BTFDebug.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BTFDebug.h?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/lib/Target/BPF/BTFDebug.h (original)
+++ llvm/trunk/lib/Target/BPF/BTFDebug.h Tue Jul  9 08:28:41 2019
@@ -32,10 +32,12 @@ class MachineFunction;
 class BTFTypeBase {
 protected:
   uint8_t Kind;
+  bool IsCompleted;
   uint32_t Id;
   struct BTF::CommonType BTFType;
 
 public:
+  BTFTypeBase() : IsCompleted(false) {}
   virtual ~BTFTypeBase() = default;
   void setId(uint32_t Id) { this->Id = Id; }
   uint32_t getId() { return Id; }
@@ -54,11 +56,13 @@ public:
 /// volatile, typedef and restrict.
 class BTFTypeDerived : public BTFTypeBase {
   const DIDerivedType *DTy;
+  bool NeedsFixup;
 
 public:
-  BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag);
+  BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag, bool NeedsFixup);
   void completeType(BTFDebug &BDebug);
   void emitType(MCStreamer &OS);
+  void setPointeeType(uint32_t PointeeType);
 };
 
 /// Handle struct or union forward declaration.
@@ -100,13 +104,15 @@ public:
 
 /// Handle array type.
 class BTFTypeArray : public BTFTypeBase {
+  uint32_t ElemSize;
   struct BTF::BTFArray ArrayInfo;
 
 public:
-  BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems);
+  BTFTypeArray(uint32_t ElemTypeId, uint32_t ElemSize, 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,6 +129,9 @@ 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.
@@ -218,6 +227,19 @@ struct BTFLineInfo {
   uint32_t ColumnNum;   ///< the column number
 };
 
+/// Represent one offset relocation.
+struct BTFOffsetReloc {
+  const MCSymbol *Label;  ///< MCSymbol identifying insn for the reloc
+  uint32_t TypeID;        ///< Type ID
+  uint32_t OffsetNameOff; ///< The string to traverse types
+};
+
+/// Represent one extern relocation.
+struct BTFExternReloc {
+  const MCSymbol *Label;  ///< MCSymbol identifying insn for the reloc
+  uint32_t ExternNameOff; ///< The extern variable name
+};
+
 /// Collect and emit BTF information.
 class BTFDebug : public DebugHandlerBase {
   MCStreamer &OS;
@@ -225,14 +247,21 @@ class BTFDebug : public DebugHandlerBase
   bool LineInfoGenerated;
   uint32_t SecNameOff;
   uint32_t ArrayIndexTypeId;
+  bool MapDefNotCollected;
   BTFStringTable StringTable;
   std::vector<std::unique_ptr<BTFTypeBase>> TypeEntries;
   std::unordered_map<const DIType *, uint32_t> DIToIdMap;
   std::map<uint32_t, std::vector<BTFFuncInfo>> FuncInfoTable;
   std::map<uint32_t, std::vector<BTFLineInfo>> LineInfoTable;
+  std::map<uint32_t, std::vector<BTFOffsetReloc>> OffsetRelocTable;
+  std::map<uint32_t, std::vector<BTFExternReloc>> ExternRelocTable;
   StringMap<std::vector<std::string>> FileContent;
-  std::map<std::string, std::unique_ptr<BTFKindDataSec>>
-      DataSecEntries;
+  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;
 
   /// Add types to TypeEntries.
   /// @{
@@ -245,7 +274,8 @@ class BTFDebug : public DebugHandlerBase
   /// IR type visiting functions.
   /// @{
   void visitTypeEntry(const DIType *Ty);
-  void visitTypeEntry(const DIType *Ty, uint32_t &TypeId);
+  void visitTypeEntry(const DIType *Ty, uint32_t &TypeId, bool CheckPointer,
+                      bool SeenPointer);
   void visitBasicType(const DIBasicType *BTy, uint32_t &TypeId);
   void visitSubroutineType(
       const DISubroutineType *STy, bool ForSubprog,
@@ -258,7 +288,9 @@ class BTFDebug : public DebugHandlerBase
                        uint32_t &TypeId);
   void visitArrayType(const DICompositeType *ATy, uint32_t &TypeId);
   void visitEnumType(const DICompositeType *ETy, uint32_t &TypeId);
-  void visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId);
+  void visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,
+                        bool CheckPointer, bool SeenPointer);
+  void visitMapDefType(const DIType *Ty, uint32_t &TypeId);
   /// @}
 
   /// Get the file content for the subprogram. Certain lines of the file
@@ -270,7 +302,21 @@ class BTFDebug : public DebugHandlerBase
                          uint32_t Column);
 
   /// Generate types and variables for globals.
-  void processGlobals(void);
+  void processGlobals(bool ProcessingMapDef);
+
+  /// Generate one offset relocation record.
+  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);
+
+  /// Process LD_imm64 instructions.
+  void processLDimm64(const MachineInstr *MI);
 
   /// Emit common header of .BTF and .BTF.ext sections.
   void emitCommonHeader();
@@ -291,6 +337,9 @@ protected:
 public:
   BTFDebug(AsmPrinter *AP);
 
+  ///
+  bool InstLower(const MachineInstr *MI, MCInst &OutMI);
+
   /// Get the special array index type id.
   uint32_t getArrayIndexTypeId() {
     assert(ArrayIndexTypeId);

Modified: llvm/trunk/lib/Target/BPF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/CMakeLists.txt?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/lib/Target/BPF/CMakeLists.txt (original)
+++ llvm/trunk/lib/Target/BPF/CMakeLists.txt Tue Jul  9 08:28:41 2019
@@ -13,6 +13,7 @@ tablegen(LLVM BPFGenSubtargetInfo.inc -g
 add_public_tablegen_target(BPFCommonTableGen)
 
 add_llvm_target(BPFCodeGen
+  BPFAbstrctMemberAccess.cpp
   BPFAsmPrinter.cpp
   BPFFrameLowering.cpp
   BPFInstrInfo.cpp
@@ -25,6 +26,7 @@ add_llvm_target(BPFCodeGen
   BPFTargetMachine.cpp
   BPFMIPeephole.cpp
   BPFMIChecking.cpp
+  BPFMISimplifyPatchable.cpp
   BTFDebug.cpp
   )
 

Modified: llvm/trunk/test/CodeGen/BPF/BTF/binary-format.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/binary-format.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/binary-format.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/binary-format.ll Tue Jul  9 08:28:41 2019
@@ -15,31 +15,33 @@ entry:
 
 ; CHECK:    '.BTF'
 ; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 30000000
-; CHECK-EL: 0x00000010 30000000 33000000 2b000000 00000001
+; CHECK-EL: 0x00000010 30000000 33000000 01000000 00000001
 ; CHECK-EL: 0x00000020 04000000 20000001 00000000 0100000d
-; CHECK-EL: 0x00000030 01000000 2f000000 01000000 31000000
-; CHECK-EL: 0x00000040 0000000c 02000000 002e7465 7874002f
+; CHECK-EL: 0x00000030 01000000 05000000 01000000 07000000
+; CHECK-EL: 0x00000040 0000000c 02000000 00696e74 00610066
 ; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000030
-; CHECK-EB: 0x00000010 00000030 00000033 0000002b 01000000
+; CHECK-EB: 0x00000010 00000030 00000033 00000001 01000000
 ; CHECK-EB: 0x00000020 00000004 01000020 00000000 0d000001
-; CHECK-EB: 0x00000030 00000001 0000002f 00000001 00000031
-; CHECK-EB: 0x00000040 0c000000 00000002 002e7465 7874002f
-; CHECK:    0x00000050 746d702f 742e6300 696e7420 6628696e
-; CHECK:    0x00000060 74206129 207b2072 65747572 6e20613b
-; CHECK:    0x00000070 207d0069 6e740061 006600
+; CHECK-EB: 0x00000030 00000001 00000005 00000001 00000007
+; CHECK-EB: 0x00000040 0c000000 00000002 00696e74 00610066
+; CHECK:    0x00000050 002e7465 7874002f 746d702f 742e6300
+; CHECK:    0x00000060 696e7420 6628696e 74206129 207b2072
+; CHECK:    0x00000070 65747572 6e20613b 207d00
 ; CHECK:    '.BTF.ext'
-; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 14000000
-; CHECK-EL: 0x00000010 14000000 2c000000 08000000 01000000
-; CHECK-EL: 0x00000020 01000000 00000000 03000000 10000000
-; CHECK-EL: 0x00000030 01000000 02000000 00000000 07000000
-; CHECK-EL: 0x00000040 10000000 00040000 08000000 07000000
-; CHECK-EL: 0x00000050 10000000 10040000
-; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000014
-; CHECK-EB: 0x00000010 00000014 0000002c 00000008 00000001
-; CHECK-EB: 0x00000020 00000001 00000000 00000003 00000010
-; CHECK-EB: 0x00000030 00000001 00000002 00000000 00000007
-; CHECK-EB: 0x00000040 00000010 00000400 00000008 00000007
-; CHECK-EB: 0x00000050 00000010 00000410
+; CHECK-EL: 0x00000000 9feb0100 28000000 00000000 14000000
+; CHECK-EL: 0x00000010 14000000 2c000000 40000000 00000000
+; CHECK-EL: 0x00000020 40000000 00000000 08000000 09000000
+; CHECK-EL: 0x00000030 01000000 00000000 03000000 10000000
+; CHECK-EL: 0x00000040 09000000 02000000 00000000 0f000000
+; CHECK-EL: 0x00000050 18000000 00040000 08000000 0f000000
+; CHECK-EL: 0x00000060 18000000 10040000
+; CHECK-EB: 0x00000000 eb9f0100 00000028 00000000 00000014
+; CHECK-EB: 0x00000010 00000014 0000002c 00000040 00000000
+; CHECK-EB: 0x00000020 00000040 00000000 00000008 00000009
+; CHECK-EB: 0x00000030 00000001 00000000 00000003 00000010
+; CHECK-EB: 0x00000040 00000009 00000002 00000000 0000000f
+; CHECK-EB: 0x00000050 00000018 00000400 00000008 0000000f
+; CHECK-EB: 0x00000060 00000018 00000410
 
 ; Function Attrs: nounwind readnone speculatable
 declare void @llvm.dbg.value(metadata, metadata, metadata) #1

Modified: llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll Tue Jul  9 08:28:41 2019
@@ -28,21 +28,21 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 
 attributes #0 = { norecurse nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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" }

Modified: llvm/trunk/test/CodeGen/BPF/BTF/filename.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/filename.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/filename.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/filename.ll Tue Jul  9 08:28:41 2019
@@ -23,41 +23,45 @@ define dso_local i32 @test() local_unnam
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   26                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   30                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/ttmp/t.c"    # string offset=7
+; CHECK-NEXT:        .ascii  "test"                  # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=26
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=10
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "test"                  # string offset=30
+; CHECK-NEXT:        .ascii  "/home/yhs/ttmp/t.c"    # string offset=16
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   10                      # FuncInfo section string offset=10
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin{{[0-9]+}}
 ; CHECK-NEXT:        .long   3
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   10                      # LineInfo section string offset=10
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   16
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   1038                    # Line 1 Col 14
 

Modified: llvm/trunk/test/CodeGen/BPF/BTF/func-func-ptr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/func-func-ptr.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/func-func-ptr.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/func-func-ptr.ll Tue Jul  9 08:28:41 2019
@@ -29,16 +29,16 @@ entry:
 ; CHECK-NEXT:        .long   104
 ; CHECK-NEXT:        .long   104
 ; CHECK-NEXT:        .long   32
-; CHECK-NEXT:        .long   16                      # BTF_KIND_INT(id = 1)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 1)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 2)
 ; CHECK-NEXT:        .long   218103809               # 0xd000001
 ; CHECK-NEXT:        .long   0
-; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   5
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   23                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   8                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 4)
@@ -54,17 +54,17 @@ entry:
 ; CHECK-NEXT:        .long   8
 ; CHECK-NEXT:        .long   29
 ; CHECK-NEXT:        .long   4
-; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   0                       # 0x0
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=7
+; CHECK-NEXT:        .ascii  "p2"                    # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=16
+; CHECK-NEXT:        .ascii  "f1"                    # string offset=8
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "p2"                    # string offset=20
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=11
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "f1"                    # string offset=23
+; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=17
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "t1"                    # string offset=26
 ; CHECK-NEXT:        .byte   0
@@ -74,21 +74,25 @@ entry:
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   11                      # FuncInfo section string offset=11
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin0
 ; CHECK-NEXT:        .long   3
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   11                      # LineInfo section string offset=11
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   17
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   3091                    # Line 3 Col 19
 

Modified: llvm/trunk/test/CodeGen/BPF/BTF/func-non-void.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/func-non-void.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/func-non-void.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/func-non-void.ll Tue Jul  9 08:28:41 2019
@@ -21,52 +21,56 @@ define dso_local i32 @f1(i32 returned) l
 ; CHECK-NEXT:        .long   48
 ; CHECK-NEXT:        .long   48
 ; CHECK-NEXT:        .long   26
-; CHECK-NEXT:        .long   16                      # BTF_KIND_INT(id = 1)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 1)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 2)
 ; CHECK-NEXT:        .long   218103809               # 0xd000001
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   5
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   23                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   8                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=7
+; CHECK-NEXT:        .ascii  "a1"                    # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=16
+; CHECK-NEXT:        .ascii  "f1"                    # string offset=8
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "a1"                    # string offset=20
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=11
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "f1"                    # string offset=23
+; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=17
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   44
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   11                      # FuncInfo section string offset=11
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin0
 ; CHECK-NEXT:        .long   3
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   11                      # LineInfo section string offset=11
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .long   .Lfunc_begin0
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   17
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   1024                    # Line 1 Col 0
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   17
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   1042                    # Line 1 Col 18
 

Modified: llvm/trunk/test/CodeGen/BPF/BTF/func-source.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/func-source.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/func-source.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/func-source.ll Tue Jul  9 08:28:41 2019
@@ -27,38 +27,42 @@ entry:
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   0
-; CHECK-NEXT:        .long   33                      # BTF_KIND_FUNC(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_FUNC(id = 2)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .byte   102                     # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=7
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=3
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "void f(void) { }"      # string offset=16
+; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .byte   102                     # string offset=33
+; CHECK-NEXT:        .ascii  "void f(void) { }"      # string offset=18
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   3                       # FuncInfo section string offset=3
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin0
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   3                       # LineInfo section string offset=3
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
-; CHECK-NEXT:        .long   16
+; CHECK-NEXT:        .long   9
+; CHECK-NEXT:        .long   18
 ; CHECK-NEXT:        .long   1040                    # Line 1 Col 16
 
 attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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" }

Modified: llvm/trunk/test/CodeGen/BPF/BTF/func-typedef.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/func-typedef.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/func-typedef.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/func-typedef.ll Tue Jul  9 08:28:41 2019
@@ -24,65 +24,70 @@ entry:
 ; CHECK-NEXT:        .long   72
 ; CHECK-NEXT:        .long   72
 ; CHECK-NEXT:        .long   35
-; CHECK-NEXT:        .long   16                      # BTF_KIND_TYPEDEF(id = 1)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_TYPEDEF(id = 1)
 ; CHECK-NEXT:        .long   134217728               # 0x8000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   22                      # BTF_KIND_TYPEDEF(id = 2)
+; CHECK-NEXT:        .long   7                       # BTF_KIND_TYPEDEF(id = 2)
 ; CHECK-NEXT:        .long   134217728               # 0x8000000
 ; CHECK-NEXT:        .long   3
-; CHECK-NEXT:        .long   27                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   12                      # BTF_KIND_INT(id = 3)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 4)
 ; CHECK-NEXT:        .long   218103809               # 0xd000001
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   31
+; CHECK-NEXT:        .long   16
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   33                      # BTF_KIND_FUNC(id = 5)
+; CHECK-NEXT:        .long   18                      # BTF_KIND_FUNC(id = 5)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "__int"                 # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=7
+; CHECK-NEXT:        .ascii  "_int"                  # string offset=7
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "__int"                 # string offset=16
+; CHECK-NEXT:        .ascii  "int"                   # string offset=12
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "_int"                  # string offset=22
+; CHECK-NEXT:        .byte   97                      # string offset=16
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=27
+; CHECK-NEXT:        .byte   102                     # string offset=18
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .byte   97                      # string offset=31
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=20
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .byte   102                     # string offset=33
+; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=26
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   44
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   20                      # FuncInfo section string offset=20
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin0
 ; CHECK-NEXT:        .long   5
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   20                      # LineInfo section string offset=20
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .long   .Lfunc_begin0
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   26
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   3072                    # Line 3 Col 0
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   26
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   3092                    # Line 3 Col 20
 
+
 ; Function Attrs: nounwind readnone speculatable
 declare void @llvm.dbg.value(metadata, metadata, metadata) #1
 

Modified: llvm/trunk/test/CodeGen/BPF/BTF/func-unused-arg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/func-unused-arg.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/func-unused-arg.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/func-unused-arg.ll Tue Jul  9 08:28:41 2019
@@ -21,48 +21,52 @@ define dso_local i32 @f1(i32) local_unna
 ; CHECK-NEXT:        .long   48
 ; CHECK-NEXT:        .long   48
 ; CHECK-NEXT:        .long   26
-; CHECK-NEXT:        .long   16                      # BTF_KIND_INT(id = 1)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 1)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 2)
 ; CHECK-NEXT:        .long   218103809               # 0xd000001
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   5
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   23                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   8                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=7
+; CHECK-NEXT:        .ascii  "a1"                    # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=16
+; CHECK-NEXT:        .ascii  "f1"                    # string offset=8
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "a1"                    # string offset=20
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=11
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "f1"                    # string offset=23
+; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=17
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   11                      # FuncInfo section string offset=11
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin0
 ; CHECK-NEXT:        .long   3
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   11                      # LineInfo section string offset=11
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   17
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   1042                    # Line 1 Col 18
 

Modified: llvm/trunk/test/CodeGen/BPF/BTF/func-void.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/func-void.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/func-void.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/func-void.ll Tue Jul  9 08:28:41 2019
@@ -23,35 +23,39 @@ define dso_local void @f1() local_unname
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   0
-; CHECK-NEXT:        .long   16                      # BTF_KIND_FUNC(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_FUNC(id = 2)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "f1"                    # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=7
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=4
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "f1"                    # string offset=16
+; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=10
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   4                       # FuncInfo section string offset=4
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin0
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   4                       # LineInfo section string offset=4
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   10
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   1040                    # Line 1 Col 16
 

Modified: llvm/trunk/test/CodeGen/BPF/BTF/local-var.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/local-var.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/local-var.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/local-var.ll Tue Jul  9 08:28:41 2019
@@ -29,34 +29,34 @@ define dso_local i32 @foo(i8 signext) lo
 ; CHECK-NEXT:        .long   64
 ; CHECK-NEXT:        .long   64
 ; CHECK-NEXT:        .long   59
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 1)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 1)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   16777224                # 0x1000008
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 2)
 ; CHECK-NEXT:        .long   218103809               # 0xd000001
 ; CHECK-NEXT:        .long   3
-; CHECK-NEXT:        .long   49
+; CHECK-NEXT:        .long   6
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   51                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   8                       # BTF_KIND_INT(id = 3)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   55                      # BTF_KIND_FUNC(id = 4)
+; CHECK-NEXT:        .long   12                      # BTF_KIND_FUNC(id = 4)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "char"                  # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .byte   97                      # string offset=6
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "char"                  # string offset=44
+; CHECK-NEXT:        .ascii  "int"                   # string offset=8
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .byte   97                      # string offset=49
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=12
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=51
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=16
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=55
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=22
 ; CHECK-NEXT:        .byte   0
 
 ; Function Attrs: nounwind readnone speculatable

Added: llvm/trunk/test/CodeGen/BPF/BTF/map-def.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/map-def.ll?rev=365503&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/map-def.ll (added)
+++ llvm/trunk/test/CodeGen/BPF/BTF/map-def.ll Tue Jul  9 08:28:41 2019
@@ -0,0 +1,120 @@
+; 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 key_type {
+;     int a;
+;     int b;
+;   };
+;   struct map_type {
+;     struct key_type *key;
+;     unsigned *value;
+;   };
+;   struct map_type __attribute__((section(".maps"))) hash_map;
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm t.c
+
+%struct.map_type = type { %struct.key_type*, i32* }
+%struct.key_type = type { i32, i32 }
+
+ at hash_map = dso_local local_unnamed_addr global %struct.map_type zeroinitializer, section ".maps", align 8, !dbg !0
+
+; CHECK:             .section        .BTF,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   168
+; CHECK-NEXT:        .long   168
+; CHECK-NEXT:        .long   65
+; CHECK-NEXT:        .long   1                       # BTF_KIND_STRUCT(id = 1)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   16
+; CHECK-NEXT:        .long   10
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   14
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .long   64                      # 0x40
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 2)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   20                      # BTF_KIND_STRUCT(id = 3)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   29
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   31
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   33                      # BTF_KIND_INT(id = 4)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 5)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   6
+; CHECK-NEXT:        .long   37                      # BTF_KIND_INT(id = 6)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   50                      # BTF_KIND_VAR(id = 7)
+; CHECK-NEXT:        .long   234881024               # 0xe000000
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   59                      # BTF_KIND_DATASEC(id = 8)
+; CHECK-NEXT:        .long   251658241               # 0xf000001
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   hash_map
+; CHECK-NEXT:        .long   16
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "map_type"              # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "key"                   # string offset=10
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "value"                 # string offset=14
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "key_type"              # string offset=20
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   97                      # string offset=29
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   98                      # string offset=31
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=33
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "unsigned int"          # string offset=37
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "hash_map"              # string offset=50
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".maps"                 # string offset=59
+; CHECK-NEXT:        .byte   0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!18, !19, !20}
+!llvm.ident = !{!21}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "hash_map", scope: !2, file: !3, line: 9, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 9.0.0 (trunk 364157) (llvm/trunk 364156)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
+!3 = !DIFile(filename: "t.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!4 = !{}
+!5 = !{!0}
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "map_type", file: !3, line: 5, size: 128, elements: !7)
+!7 = !{!8, !15}
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "key", scope: !6, file: !3, line: 6, baseType: !9, size: 64)
+!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64)
+!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "key_type", file: !3, line: 1, size: 64, elements: !11)
+!11 = !{!12, !14}
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !10, file: !3, line: 2, baseType: !13, size: 32)
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !10, file: !3, line: 3, baseType: !13, size: 32, offset: 32)
+!15 = !DIDerivedType(tag: DW_TAG_member, name: "value", scope: !6, file: !3, line: 7, baseType: !16, size: 64, offset: 64)
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !17, size: 64)
+!17 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!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 9.0.0 (trunk 364157) (llvm/trunk 364156)"}

Added: llvm/trunk/test/CodeGen/BPF/BTF/ptr-prune-type.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/ptr-prune-type.ll?rev=365503&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/ptr-prune-type.ll (added)
+++ llvm/trunk/test/CodeGen/BPF/BTF/ptr-prune-type.ll Tue Jul  9 08:28:41 2019
@@ -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:
+;   struct t {
+;     int a;
+;   };
+;   struct t2 {
+;     struct t *f1;
+;   };
+;   struct t2 __attribute__((section("prune_types"))) g;
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm t.c
+
+%struct.t2 = type { %struct.t* }
+%struct.t = type { i32 }
+
+ at g = dso_local local_unnamed_addr global %struct.t2 zeroinitializer, section "prune_types", align 8, !dbg !0
+
+; CHECK:             .section        .BTF,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   88
+; CHECK-NEXT:        .long   88
+; CHECK-NEXT:        .long   23
+; CHECK-NEXT:        .long   1                       # BTF_KIND_STRUCT(id = 1)
+; CHECK-NEXT:        .long   67108865                # 0x4000001
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 2)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .long   7                       # BTF_KIND_VAR(id = 3)
+; CHECK-NEXT:        .long   234881024               # 0xe000000
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   9                       # BTF_KIND_DATASEC(id = 4)
+; CHECK-NEXT:        .long   251658241               # 0xf000001
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   g
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   21                      # BTF_KIND_FWD(id = 5)
+; CHECK-NEXT:        .long   117440512               # 0x7000000
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "t2"                    # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "f1"                    # string offset=4
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   103                     # string offset=7
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "prune_types"           # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   116                     # string offset=21
+; CHECK-NEXT:        .byte   0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!14, !15, !16}
+!llvm.ident = !{!17}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 7, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 9.0.0 (trunk 364157) (llvm/trunk 364156)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
+!3 = !DIFile(filename: "t.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!4 = !{}
+!5 = !{!0}
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t2", file: !3, line: 4, size: 64, elements: !7)
+!7 = !{!8}
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "f1", scope: !6, file: !3, line: 5, baseType: !9, size: 64)
+!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64)
+!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: !3, line: 1, size: 32, elements: !11)
+!11 = !{!12}
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !10, file: !3, line: 2, baseType: !13, size: 32)
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !{i32 2, !"Dwarf Version", i32 4}
+!15 = !{i32 2, !"Debug Info Version", i32 3}
+!16 = !{i32 1, !"wchar_size", i32 4}
+!17 = !{!"clang version 9.0.0 (trunk 364157) (llvm/trunk 364156)"}

Modified: llvm/trunk/test/CodeGen/BPF/BTF/static-var-derived-type.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/static-var-derived-type.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/static-var-derived-type.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/static-var-derived-type.ll Tue Jul  9 08:28:41 2019
@@ -46,11 +46,11 @@ define dso_local i64 @foo() local_unname
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   45                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   8
 ; CHECK-NEXT:        .long   16777280                # 0x1000040
-; CHECK-NEXT:        .long   54                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   10                      # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_VOLATILE(id = 4)
@@ -116,13 +116,13 @@ define dso_local i64 @foo() local_unname
 ; CHECK-NEXT:        .long   v4
 ; CHECK-NEXT:        .long   8
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "long int"              # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bugs/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=10
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "long int"              # string offset=45
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=14
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=54
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bugs/test.c" # string offset=20
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "int"                   # string offset=58
 ; CHECK-NEXT:        .byte   0

Modified: llvm/trunk/test/CodeGen/BPF/BTF/static-var-inited-sec.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/static-var-inited-sec.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/static-var-inited-sec.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/static-var-inited-sec.ll Tue Jul  9 08:28:41 2019
@@ -35,11 +35,11 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_VOLATILE(id = 4)
@@ -74,13 +74,13 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   a
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "short"                 # string offset=52
 ; CHECK-NEXT:        .byte   0

Modified: llvm/trunk/test/CodeGen/BPF/BTF/static-var-inited.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/static-var-inited.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/static-var-inited.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/static-var-inited.ll Tue Jul  9 08:28:41 2019
@@ -35,11 +35,11 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_VOLATILE(id = 4)
@@ -74,13 +74,13 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   a
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "short"                 # string offset=52
 ; CHECK-NEXT:        .byte   0

Modified: llvm/trunk/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll Tue Jul  9 08:28:41 2019
@@ -35,11 +35,11 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_CONST(id = 4)
@@ -80,13 +80,13 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   a
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "short"                 # string offset=52
 ; CHECK-NEXT:        .byte   0

Modified: llvm/trunk/test/CodeGen/BPF/BTF/static-var-readonly.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/static-var-readonly.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/static-var-readonly.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/static-var-readonly.ll Tue Jul  9 08:28:41 2019
@@ -35,11 +35,11 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_CONST(id = 4)
@@ -80,13 +80,13 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   a
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "short"                 # string offset=52
 ; CHECK-NEXT:        .byte   0

Modified: llvm/trunk/test/CodeGen/BPF/BTF/static-var-sec.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/static-var-sec.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/static-var-sec.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/static-var-sec.ll Tue Jul  9 08:28:41 2019
@@ -35,11 +35,11 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_VOLATILE(id = 4)
@@ -74,13 +74,13 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   a
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "short"                 # string offset=52
 ; CHECK-NEXT:        .byte   0

Modified: llvm/trunk/test/CodeGen/BPF/BTF/static-var-zerolen-array.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/static-var-zerolen-array.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/static-var-zerolen-array.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/static-var-zerolen-array.ll Tue Jul  9 08:28:41 2019
@@ -32,11 +32,11 @@ define dso_local i32 @test() local_unnam
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_VOLATILE(id = 4)
@@ -79,13 +79,13 @@ define dso_local i32 @test() local_unnam
 ; CHECK-NEXT:        .long   sv
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "test"                  # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=10
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "test"                  # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=16
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .byte   116                     # string offset=53
 ; CHECK-NEXT:        .byte   0

Modified: llvm/trunk/test/CodeGen/BPF/BTF/static-var.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/BTF/static-var.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/static-var.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/BTF/static-var.ll Tue Jul  9 08:28:41 2019
@@ -35,11 +35,11 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_VOLATILE(id = 4)
@@ -74,13 +74,13 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   a
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "short"                 # string offset=52
 ; CHECK-NEXT:        .byte   0

Added: llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-basic.ll?rev=365503&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-basic.ll (added)
+++ llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-basic.ll Tue Jul  9 08:28:41 2019
@@ -0,0 +1,186 @@
+; 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 sk_buff {
+;      int i;
+;      struct net_device *dev;
+;    };
+;    #define _(x) (__builtin_preserve_access_index(x))
+;    static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr)
+;        = (void *) 4;
+;
+;    int bpf_prog(struct sk_buff *ctx) {
+;      struct net_device *dev = 0;
+;      bpf_probe_read(&dev, sizeof(dev), _(&ctx->dev));
+;      return dev != 0;
+;    }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+%struct.sk_buff = type { i32, %struct.net_device* }
+%struct.net_device = type opaque
+
+; Function Attrs: nounwind
+define dso_local i32 @bpf_prog(%struct.sk_buff*) local_unnamed_addr #0 !dbg !15 {
+  %2 = alloca %struct.net_device*, align 8
+  call void @llvm.dbg.value(metadata %struct.sk_buff* %0, metadata !26, metadata !DIExpression()), !dbg !28
+  %3 = bitcast %struct.net_device** %2 to i8*, !dbg !29
+  call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %3) #4, !dbg !29
+  call void @llvm.dbg.value(metadata %struct.net_device* null, metadata !27, metadata !DIExpression()), !dbg !28
+  store %struct.net_device* null, %struct.net_device** %2, align 8, !dbg !30, !tbaa !31
+  %4 = tail call %struct.net_device** @llvm.preserve.struct.access.index.p0p0s_struct.net_devices.p0s_struct.sk_buffs(%struct.sk_buff* %0, i32 1, i32 1), !dbg !35, !llvm.preserve.access.index !19
+  %5 = bitcast %struct.net_device** %4 to i8*, !dbg !35
+  %6 = call i32 inttoptr (i64 4 to i32 (i8*, i32, i8*)*)(i8* nonnull %3, i32 8, i8* %5) #4, !dbg !36
+  %7 = load %struct.net_device*, %struct.net_device** %2, align 8, !dbg !37, !tbaa !31
+  call void @llvm.dbg.value(metadata %struct.net_device* %7, metadata !27, metadata !DIExpression()), !dbg !28
+  %8 = icmp ne %struct.net_device* %7, null, !dbg !38
+  %9 = zext i1 %8 to i32, !dbg !38
+  call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %3) #4, !dbg !39
+  ret i32 %9, !dbg !40
+}
+
+; CHECK:             .section        .BTF,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   120
+; CHECK-NEXT:        .long   120
+; CHECK-NEXT:        .long   90
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 1)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_STRUCT(id = 2)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   16
+; CHECK-NEXT:        .long   9
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   11
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   64                      # 0x40
+; CHECK-NEXT:        .long   15                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 4)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .long   19                      # BTF_KIND_FWD(id = 5)
+; CHECK-NEXT:        .long   117440512               # 0x7000000
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 6)
+; CHECK-NEXT:        .long   218103809               # 0xd000001
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   30
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   34                      # BTF_KIND_FUNC(id = 7)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   6
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "sk_buff"               # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   105                     # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev"                   # string offset=11
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=15
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "net_device"            # string offset=19
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "ctx"                   # string offset=30
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "bpf_prog"              # string offset=34
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=43
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=49
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "0:1"                   # string offset=86
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   124
+; CHECK-NEXT:        .long   144
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   168
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   8                       # FuncInfo
+
+; CHECK:             .long   12                      # OffsetReloc
+; CHECK-NEXT:        .long   43                      # Offset reloc section string offset=43
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp2
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   86
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone
+declare %struct.net_device** @llvm.preserve.struct.access.index.p0p0s_struct.net_devices.p0s_struct.sk_buffs(%struct.sk_buff*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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 = { argmemonly nounwind }
+attributes #2 = { nounwind readnone }
+attributes #3 = { nounwind readnone speculatable }
+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 9.0.0 (trunk 360739) (llvm/trunk 360747)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = distinct !DIGlobalVariable(name: "bpf_probe_read", scope: !0, file: !1, line: 6, type: !6, isLocal: true, isDefinition: true)
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !10, !9, !10}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!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 9.0.0 (trunk 360739) (llvm/trunk 360747)"}
+!15 = distinct !DISubprogram(name: "bpf_prog", scope: !1, file: !1, line: 9, type: !16, scopeLine: 9, flags: DIFlagPrototyped, isLocal: false, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !25)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!9, !18}
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
+!19 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "sk_buff", file: !1, line: 1, size: 128, elements: !20)
+!20 = !{!21, !22}
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !19, file: !1, line: 2, baseType: !9, size: 32)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "dev", scope: !19, file: !1, line: 3, baseType: !23, size: 64, offset: 64)
+!23 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !24, size: 64)
+!24 = !DICompositeType(tag: DW_TAG_structure_type, name: "net_device", file: !1, line: 3, flags: DIFlagFwdDecl)
+!25 = !{!26, !27}
+!26 = !DILocalVariable(name: "ctx", arg: 1, scope: !15, file: !1, line: 9, type: !18)
+!27 = !DILocalVariable(name: "dev", scope: !15, file: !1, line: 10, type: !23)
+!28 = !DILocation(line: 0, scope: !15)
+!29 = !DILocation(line: 10, column: 3, scope: !15)
+!30 = !DILocation(line: 10, column: 22, scope: !15)
+!31 = !{!32, !32, i64 0}
+!32 = !{!"any pointer", !33, i64 0}
+!33 = !{!"omnipotent char", !34, i64 0}
+!34 = !{!"Simple C/C++ TBAA"}
+!35 = !DILocation(line: 11, column: 37, scope: !15)
+!36 = !DILocation(line: 11, column: 3, scope: !15)
+!37 = !DILocation(line: 12, column: 10, scope: !15)
+!38 = !DILocation(line: 12, column: 14, scope: !15)
+!39 = !DILocation(line: 13, column: 1, scope: !15)
+!40 = !DILocation(line: 12, column: 3, scope: !15)

Added: llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-multilevel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-multilevel.ll?rev=365503&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-multilevel.ll (added)
+++ llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-multilevel.ll Tue Jul  9 08:28:41 2019
@@ -0,0 +1,197 @@
+; 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 net_device {
+;     int dev_id;
+;     int others;
+;   };
+;   struct sk_buff {
+;     int i;
+;     struct net_device dev;
+;   };
+;   #define _(x) (__builtin_preserve_access_index(x))
+;   static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr)
+;       = (void *) 4;
+;
+;   int bpf_prog(struct sk_buff *ctx) {
+;     int dev_id;
+;     bpf_probe_read(&dev_id, sizeof(int), _(&ctx->dev.dev_id));
+;     return dev_id;
+;   }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+%struct.sk_buff = type { i32, %struct.net_device }
+%struct.net_device = type { i32, i32 }
+
+; Function Attrs: nounwind
+define dso_local i32 @bpf_prog(%struct.sk_buff*) local_unnamed_addr #0 !dbg !15 {
+  %2 = alloca i32, align 4
+  call void @llvm.dbg.value(metadata %struct.sk_buff* %0, metadata !28, metadata !DIExpression()), !dbg !30
+  %3 = bitcast i32* %2 to i8*, !dbg !31
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #4, !dbg !31
+  %4 = tail call %struct.net_device* @llvm.preserve.struct.access.index.p0s_struct.net_devices.p0s_struct.sk_buffs(%struct.sk_buff* %0, i32 1, i32 1), !dbg !32, !llvm.preserve.access.index !19
+  %5 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.net_devices(%struct.net_device* %4, i32 0, i32 0), !dbg !32, !llvm.preserve.access.index !23
+  %6 = bitcast i32* %5 to i8*, !dbg !32
+  %7 = call i32 inttoptr (i64 4 to i32 (i8*, i32, i8*)*)(i8* nonnull %3, i32 4, i8* %6) #4, !dbg !33
+  %8 = load i32, i32* %2, align 4, !dbg !34, !tbaa !35
+  call void @llvm.dbg.value(metadata i32 %8, metadata !29, metadata !DIExpression()), !dbg !30
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3) #4, !dbg !39
+  ret i32 %8, !dbg !40
+}
+
+; CHECK:             .section        .BTF,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   132
+; CHECK-NEXT:        .long   132
+; CHECK-NEXT:        .long   106
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 1)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_STRUCT(id = 2)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   12
+; CHECK-NEXT:        .long   9
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   11
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   15                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   19                      # BTF_KIND_STRUCT(id = 4)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   30
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   37
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 5)
+; CHECK-NEXT:        .long   218103809               # 0xd000001
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   44
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 6)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "sk_buff"               # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   105                     # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev"                   # string offset=11
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=15
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "net_device"            # string offset=19
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev_id"                # string offset=30
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "others"                # string offset=37
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "ctx"                   # string offset=44
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "bpf_prog"              # string offset=48
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=57
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=63
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "0:1:0"                 # string offset=100
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   76
+; CHECK-NEXT:        .long   96
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   120
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   8                       # FuncInfo
+
+; CHECK:             .long   12                      # OffsetReloc
+; CHECK-NEXT:        .long   57                      # Offset reloc section string offset=57
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp2
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   100
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone
+declare %struct.net_device* @llvm.preserve.struct.access.index.p0s_struct.net_devices.p0s_struct.sk_buffs(%struct.sk_buff*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.net_devices(%struct.net_device*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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 = { argmemonly nounwind }
+attributes #2 = { nounwind readnone }
+attributes #3 = { nounwind readnone speculatable }
+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 9.0.0 (trunk 360739) (llvm/trunk 360747)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = distinct !DIGlobalVariable(name: "bpf_probe_read", scope: !0, file: !1, line: 10, type: !6, isLocal: true, isDefinition: true)
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !10, !9, !10}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!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 9.0.0 (trunk 360739) (llvm/trunk 360747)"}
+!15 = distinct !DISubprogram(name: "bpf_prog", scope: !1, file: !1, line: 13, type: !16, scopeLine: 13, flags: DIFlagPrototyped, isLocal: false, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !27)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!9, !18}
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
+!19 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "sk_buff", file: !1, line: 5, size: 96, elements: !20)
+!20 = !{!21, !22}
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !19, file: !1, line: 6, baseType: !9, size: 32)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "dev", scope: !19, file: !1, line: 7, baseType: !23, size: 64, offset: 32)
+!23 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "net_device", file: !1, line: 1, size: 64, elements: !24)
+!24 = !{!25, !26}
+!25 = !DIDerivedType(tag: DW_TAG_member, name: "dev_id", scope: !23, file: !1, line: 2, baseType: !9, size: 32)
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "others", scope: !23, file: !1, line: 3, baseType: !9, size: 32, offset: 32)
+!27 = !{!28, !29}
+!28 = !DILocalVariable(name: "ctx", arg: 1, scope: !15, file: !1, line: 13, type: !18)
+!29 = !DILocalVariable(name: "dev_id", scope: !15, file: !1, line: 14, type: !9)
+!30 = !DILocation(line: 0, scope: !15)
+!31 = !DILocation(line: 14, column: 3, scope: !15)
+!32 = !DILocation(line: 15, column: 40, scope: !15)
+!33 = !DILocation(line: 15, column: 3, scope: !15)
+!34 = !DILocation(line: 16, column: 10, scope: !15)
+!35 = !{!36, !36, i64 0}
+!36 = !{!"int", !37, i64 0}
+!37 = !{!"omnipotent char", !38, i64 0}
+!38 = !{!"Simple C/C++ TBAA"}
+!39 = !DILocation(line: 17, column: 1, scope: !15)
+!40 = !DILocation(line: 16, column: 3, scope: !15)

Added: llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll?rev=365503&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll (added)
+++ llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll Tue Jul  9 08:28:41 2019
@@ -0,0 +1,213 @@
+; 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 sk_buff {
+;     int i;
+;     struct {
+;       int dev_id;
+;       int others;
+;     } dev[10];
+;   };
+;   #define _(x) (__builtin_preserve_access_index(x))
+;   static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr)
+;       = (void *) 4;
+;
+;   int bpf_prog(struct sk_buff *ctx) {
+;     int dev_id;
+;     bpf_probe_read(&dev_id, sizeof(int), _(&ctx->dev[5].dev_id));
+;     return dev_id;
+;   }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+%struct.sk_buff = type { i32, [10 x %struct.anon] }
+%struct.anon = type { i32, i32 }
+
+; Function Attrs: nounwind
+define dso_local i32 @bpf_prog(%struct.sk_buff*) local_unnamed_addr #0 !dbg !15 {
+  %2 = alloca i32, align 4
+  call void @llvm.dbg.value(metadata %struct.sk_buff* %0, metadata !31, metadata !DIExpression()), !dbg !33
+  %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
+  %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
+  %9 = load i32, i32* %2, align 4, !dbg !37, !tbaa !38
+  call void @llvm.dbg.value(metadata i32 %9, metadata !32, metadata !DIExpression()), !dbg !33
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3) #4, !dbg !42
+  ret i32 %9, !dbg !43
+}
+
+; CHECK:             .section        .BTF,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   172
+; CHECK-NEXT:        .long   172
+; CHECK-NEXT:        .long   117
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 1)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_STRUCT(id = 2)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   84
+; CHECK-NEXT:        .long   9
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   11
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   15                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   0                       # BTF_KIND_STRUCT(id = 4)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   19
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   26
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   0                       # BTF_KIND_ARRAY(id = 5)
+; CHECK-NEXT:        .long   50331648                # 0x3000000
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   6
+; CHECK-NEXT:        .long   10
+; CHECK-NEXT:        .long   33                      # BTF_KIND_INT(id = 6)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 7)
+; CHECK-NEXT:        .long   218103809               # 0xd000001
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   53
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   57                      # BTF_KIND_FUNC(id = 8)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "sk_buff"               # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   105                     # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev"                   # string offset=11
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=15
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev_id"                # string offset=19
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "others"                # string offset=26
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "__ARRAY_SIZE_TYPE__"   # string offset=33
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "ctx"                   # string offset=53
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "bpf_prog"              # string offset=57
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=66
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=72
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "0:1:5:0"               # string offset=109
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   76
+; CHECK-NEXT:        .long   96
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   120
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   8                       # FuncInfo
+
+; CHECK:             .long   12                      # OffsetReloc
+; CHECK-NEXT:        .long   66                      # Offset reloc section string offset=66
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp2
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   109
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone
+declare [10 x %struct.anon]* @llvm.preserve.struct.access.index.p0a10s_struct.anons.p0s_struct.sk_buffs(%struct.sk_buff*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare %struct.anon* @llvm.preserve.array.access.index.p0s_struct.anons.p0a10s_struct.anons([10 x %struct.anon]*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.anons(%struct.anon*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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 = { argmemonly nounwind }
+attributes #2 = { nounwind readnone }
+attributes #3 = { nounwind readnone speculatable }
+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 9.0.0 (trunk 360739) (llvm/trunk 360747)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = distinct !DIGlobalVariable(name: "bpf_probe_read", scope: !0, file: !1, line: 9, type: !6, isLocal: true, isDefinition: true)
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !10, !9, !10}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!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 9.0.0 (trunk 360739) (llvm/trunk 360747)"}
+!15 = distinct !DISubprogram(name: "bpf_prog", scope: !1, file: !1, line: 12, type: !16, scopeLine: 12, flags: DIFlagPrototyped, isLocal: false, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !30)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!9, !18}
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
+!19 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "sk_buff", file: !1, line: 1, size: 672, elements: !20)
+!20 = !{!21, !22}
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !19, file: !1, line: 2, baseType: !9, size: 32)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "dev", scope: !19, file: !1, line: 6, baseType: !23, size: 640, offset: 32)
+!23 = !DICompositeType(tag: DW_TAG_array_type, baseType: !24, size: 640, elements: !28)
+!24 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !19, file: !1, line: 3, size: 64, elements: !25)
+!25 = !{!26, !27}
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "dev_id", scope: !24, file: !1, line: 4, baseType: !9, size: 32)
+!27 = !DIDerivedType(tag: DW_TAG_member, name: "others", scope: !24, file: !1, line: 5, baseType: !9, size: 32, offset: 32)
+!28 = !{!29}
+!29 = !DISubrange(count: 10)
+!30 = !{!31, !32}
+!31 = !DILocalVariable(name: "ctx", arg: 1, scope: !15, file: !1, line: 12, type: !18)
+!32 = !DILocalVariable(name: "dev_id", scope: !15, file: !1, line: 13, type: !9)
+!33 = !DILocation(line: 0, scope: !15)
+!34 = !DILocation(line: 13, column: 3, scope: !15)
+!35 = !DILocation(line: 14, column: 40, scope: !15)
+!36 = !DILocation(line: 14, column: 3, scope: !15)
+!37 = !DILocation(line: 15, column: 10, scope: !15)
+!38 = !{!39, !39, i64 0}
+!39 = !{!"int", !40, i64 0}
+!40 = !{!"omnipotent char", !41, i64 0}
+!41 = !{!"Simple C/C++ TBAA"}
+!42 = !DILocation(line: 16, column: 1, scope: !15)
+!43 = !DILocation(line: 15, column: 3, scope: !15)

Added: llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll?rev=365503&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll (added)
+++ llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll Tue Jul  9 08:28:41 2019
@@ -0,0 +1,216 @@
+; 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 net_device {
+;     int dev_id;
+;     int others;
+;   };
+;   struct sk_buff {
+;     int i;
+;     struct net_device dev[10];
+;   };
+;   #define _(x) (__builtin_preserve_access_index(x))
+;   static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr)
+;       = (void *) 4;
+;
+;   int bpf_prog(struct sk_buff *ctx) {
+;     int dev_id;
+;     bpf_probe_read(&dev_id, sizeof(int), _(&ctx->dev[5].dev_id));
+;     return dev_id;
+;   }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+%struct.sk_buff = type { i32, [10 x %struct.net_device] }
+%struct.net_device = type { i32, i32 }
+
+; Function Attrs: nounwind
+define dso_local i32 @bpf_prog(%struct.sk_buff*) local_unnamed_addr #0 !dbg !15 {
+  %2 = alloca i32, align 4
+  call void @llvm.dbg.value(metadata %struct.sk_buff* %0, metadata !31, metadata !DIExpression()), !dbg !33
+  %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
+  %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
+  %9 = load i32, i32* %2, align 4, !dbg !37, !tbaa !38
+  call void @llvm.dbg.value(metadata i32 %9, metadata !32, metadata !DIExpression()), !dbg !33
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3) #4, !dbg !42
+  ret i32 %9, !dbg !43
+}
+
+; CHECK:             .section        .BTF,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   172
+; CHECK-NEXT:        .long   172
+; CHECK-NEXT:        .long   128
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 1)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_STRUCT(id = 2)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   84
+; CHECK-NEXT:        .long   9
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   11
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   15                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   19                      # BTF_KIND_STRUCT(id = 4)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   30
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   37
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   0                       # BTF_KIND_ARRAY(id = 5)
+; CHECK-NEXT:        .long   50331648                # 0x3000000
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   6
+; CHECK-NEXT:        .long   10
+; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 6)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 7)
+; CHECK-NEXT:        .long   218103809               # 0xd000001
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   68                      # BTF_KIND_FUNC(id = 8)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "sk_buff"               # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   105                     # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev"                   # string offset=11
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=15
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "net_device"            # string offset=19
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev_id"                # string offset=30
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "others"                # string offset=37
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "__ARRAY_SIZE_TYPE__"   # string offset=44
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "ctx"                   # string offset=64
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "bpf_prog"              # string offset=68
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=77
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=83
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "0:1:5:0"               # string offset=120
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   76
+; CHECK-NEXT:        .long   96
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   120
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   8                       # FuncInfo
+
+; CHECK:             .long   12                      # OffsetReloc
+; CHECK-NEXT:        .long   77                      # Offset reloc section string offset=77
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp2
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   120
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone
+declare [10 x %struct.net_device]* @llvm.preserve.struct.access.index.p0a10s_struct.net_devices.p0s_struct.sk_buffs(%struct.sk_buff*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare %struct.net_device* @llvm.preserve.array.access.index.p0s_struct.net_devices.p0a10s_struct.net_devices([10 x %struct.net_device]*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.net_devices(%struct.net_device*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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 = { argmemonly nounwind }
+attributes #2 = { nounwind readnone }
+attributes #3 = { nounwind readnone speculatable }
+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 9.0.0 (trunk 360739) (llvm/trunk 360747)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = distinct !DIGlobalVariable(name: "bpf_probe_read", scope: !0, file: !1, line: 10, type: !6, isLocal: true, isDefinition: true)
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !10, !9, !10}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!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 9.0.0 (trunk 360739) (llvm/trunk 360747)"}
+!15 = distinct !DISubprogram(name: "bpf_prog", scope: !1, file: !1, line: 13, type: !16, scopeLine: 13, flags: DIFlagPrototyped, isLocal: false, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !30)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!9, !18}
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
+!19 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "sk_buff", file: !1, line: 5, size: 672, elements: !20)
+!20 = !{!21, !22}
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !19, file: !1, line: 6, baseType: !9, size: 32)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "dev", scope: !19, file: !1, line: 7, baseType: !23, size: 640, offset: 32)
+!23 = !DICompositeType(tag: DW_TAG_array_type, baseType: !24, size: 640, elements: !28)
+!24 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "net_device", file: !1, line: 1, size: 64, elements: !25)
+!25 = !{!26, !27}
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "dev_id", scope: !24, file: !1, line: 2, baseType: !9, size: 32)
+!27 = !DIDerivedType(tag: DW_TAG_member, name: "others", scope: !24, file: !1, line: 3, baseType: !9, size: 32, offset: 32)
+!28 = !{!29}
+!29 = !DISubrange(count: 10)
+!30 = !{!31, !32}
+!31 = !DILocalVariable(name: "ctx", arg: 1, scope: !15, file: !1, line: 13, type: !18)
+!32 = !DILocalVariable(name: "dev_id", scope: !15, file: !1, line: 14, type: !9)
+!33 = !DILocation(line: 0, scope: !15)
+!34 = !DILocation(line: 14, column: 3, scope: !15)
+!35 = !DILocation(line: 15, column: 40, scope: !15)
+!36 = !DILocation(line: 15, column: 3, scope: !15)
+!37 = !DILocation(line: 16, column: 10, scope: !15)
+!38 = !{!39, !39, i64 0}
+!39 = !{!"int", !40, i64 0}
+!40 = !{!"omnipotent char", !41, i64 0}
+!41 = !{!"Simple C/C++ TBAA"}
+!42 = !DILocation(line: 17, column: 1, scope: !15)
+!43 = !DILocation(line: 16, column: 3, scope: !15)

Added: llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-union.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-union.ll?rev=365503&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-union.ll (added)
+++ llvm/trunk/test/CodeGen/BPF/CORE/offset-reloc-union.ll Tue Jul  9 08:28:41 2019
@@ -0,0 +1,220 @@
+; 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 sk_buff {
+;     int i;
+;     struct {
+;       int netid;
+;       union {
+;         int dev_id;
+;         int others;
+;       } dev;
+;     } u;
+;   };
+;   #define _(x) (__builtin_preserve_access_index(x))
+;   static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr)
+;       = (void *) 4;
+;
+;   int bpf_prog(union sk_buff *ctx) {
+;     int dev_id;
+;     bpf_probe_read(&dev_id, sizeof(int), _(&ctx->u.dev.dev_id));
+;     return dev_id;
+;   }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+%union.sk_buff = type { %struct.anon }
+%struct.anon = type { i32, %union.anon }
+%union.anon = type { i32 }
+
+; Function Attrs: nounwind
+define dso_local i32 @bpf_prog(%union.sk_buff*) local_unnamed_addr #0 !dbg !15 {
+  %2 = alloca i32, align 4
+  call void @llvm.dbg.value(metadata %union.sk_buff* %0, metadata !32, metadata !DIExpression()), !dbg !34
+  %3 = bitcast i32* %2 to i8*, !dbg !35
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #4, !dbg !35
+  %4 = tail call %union.sk_buff* @llvm.preserve.union.access.index.p0s_union.sk_buffs.p0s_union.sk_buffs(%union.sk_buff* %0, i32 1), !dbg !36, !llvm.preserve.access.index !19
+  %5 = getelementptr inbounds %union.sk_buff, %union.sk_buff* %4, i64 0, i32 0, !dbg !36
+  %6 = tail call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.anons(%struct.anon* %5, i32 1, i32 1), !dbg !36, !llvm.preserve.access.index !23
+  %7 = tail call %union.anon* @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(%union.anon* %6, i32 0), !dbg !36, !llvm.preserve.access.index !27
+  %8 = bitcast %union.anon* %7 to i8*, !dbg !36
+  %9 = call i32 inttoptr (i64 4 to i32 (i8*, i32, i8*)*)(i8* nonnull %3, i32 4, i8* %8) #4, !dbg !37
+  %10 = load i32, i32* %2, align 4, !dbg !38, !tbaa !39
+  call void @llvm.dbg.value(metadata i32 %10, metadata !33, metadata !DIExpression()), !dbg !34
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3) #4, !dbg !43
+  ret i32 %10, !dbg !44
+}
+
+; CHECK:             .section        .BTF,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   168
+; CHECK-NEXT:        .long   168
+; CHECK-NEXT:        .long   105
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 1)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_UNION(id = 2)
+; CHECK-NEXT:        .long   83886082                # 0x5000002
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   9
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   11
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   13                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   0                       # BTF_KIND_STRUCT(id = 4)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   17
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   23
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   0                       # BTF_KIND_UNION(id = 5)
+; CHECK-NEXT:        .long   83886082                # 0x5000002
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   27
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   34
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 6)
+; CHECK-NEXT:        .long   218103809               # 0xd000001
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   41
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   45                      # BTF_KIND_FUNC(id = 7)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   6
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "sk_buff"               # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   105                     # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   117                     # string offset=11
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=13
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "netid"                 # string offset=17
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev"                   # string offset=23
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev_id"                # string offset=27
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "others"                # string offset=34
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "ctx"                   # string offset=41
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "bpf_prog"              # string offset=45
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=54
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=60
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "0:1:1:0"               # string offset=97
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   76
+; CHECK-NEXT:        .long   96
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   120
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   8                       # FuncInfo
+
+; CHECK:             .long   12                      # OffsetReloc
+; CHECK-NEXT:        .long   54                      # Offset reloc section string offset=54
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp2
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   97
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone
+declare %union.sk_buff* @llvm.preserve.union.access.index.p0s_union.sk_buffs.p0s_union.sk_buffs(%union.sk_buff*, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.anons(%struct.anon*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare %union.anon* @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(%union.anon*, i32 immarg) #2
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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 = { argmemonly nounwind }
+attributes #2 = { nounwind readnone }
+attributes #3 = { nounwind readnone speculatable }
+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 9.0.0 (trunk 360739) (llvm/trunk 360747)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = distinct !DIGlobalVariable(name: "bpf_probe_read", scope: !0, file: !1, line: 12, type: !6, isLocal: true, isDefinition: true)
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !10, !9, !10}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!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 9.0.0 (trunk 360739) (llvm/trunk 360747)"}
+!15 = distinct !DISubprogram(name: "bpf_prog", scope: !1, file: !1, line: 15, type: !16, scopeLine: 15, flags: DIFlagPrototyped, isLocal: false, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !31)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!9, !18}
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
+!19 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "sk_buff", file: !1, line: 1, size: 64, elements: !20)
+!20 = !{!21, !22}
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !19, file: !1, line: 2, baseType: !9, size: 32)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "u", scope: !19, file: !1, line: 9, baseType: !23, size: 64)
+!23 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !19, file: !1, line: 3, size: 64, elements: !24)
+!24 = !{!25, !26}
+!25 = !DIDerivedType(tag: DW_TAG_member, name: "netid", scope: !23, file: !1, line: 4, baseType: !9, size: 32)
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "dev", scope: !23, file: !1, line: 8, baseType: !27, size: 32, offset: 32)
+!27 = distinct !DICompositeType(tag: DW_TAG_union_type, scope: !23, file: !1, line: 5, size: 32, elements: !28)
+!28 = !{!29, !30}
+!29 = !DIDerivedType(tag: DW_TAG_member, name: "dev_id", scope: !27, file: !1, line: 6, baseType: !9, size: 32)
+!30 = !DIDerivedType(tag: DW_TAG_member, name: "others", scope: !27, file: !1, line: 7, baseType: !9, size: 32)
+!31 = !{!32, !33}
+!32 = !DILocalVariable(name: "ctx", arg: 1, scope: !15, file: !1, line: 15, type: !18)
+!33 = !DILocalVariable(name: "dev_id", scope: !15, file: !1, line: 16, type: !9)
+!34 = !DILocation(line: 0, scope: !15)
+!35 = !DILocation(line: 16, column: 3, scope: !15)
+!36 = !DILocation(line: 17, column: 40, scope: !15)
+!37 = !DILocation(line: 17, column: 3, scope: !15)
+!38 = !DILocation(line: 18, column: 10, scope: !15)
+!39 = !{!40, !40, i64 0}
+!40 = !{!"int", !41, i64 0}
+!41 = !{!"omnipotent char", !42, i64 0}
+!42 = !{!"Simple C/C++ TBAA"}
+!43 = !DILocation(line: 19, column: 1, scope: !15)
+!44 = !DILocation(line: 18, column: 3, scope: !15)

Copied: llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-char.ll (from r365502, llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-char.ll?p2=llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-char.ll&p1=llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll&r1=365502&r2=365503&rev=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-char.ll Tue Jul  9 08:28:41 2019
@@ -1,18 +1,20 @@
 ; 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:
-;   extern char a;
+;   extern __attribute__((section(".BPF.patchable_externs"))) char a;
 ;   int foo() { return a; }
 ; Compilation flag:
 ;   clang -target bpf -O2 -g -S -emit-llvm test.c
 
- at a = external dso_local local_unnamed_addr global i8, align 1
+ at a = external dso_local local_unnamed_addr global i8, section ".BPF.patchable_externs", align 1
 
 ; Function Attrs: norecurse nounwind readonly
 define dso_local i32 @foo() local_unnamed_addr #0 !dbg !7 {
   %1 = load i8, i8* @a, align 1, !dbg !11, !tbaa !12
   %2 = sext i8 %1 to i32, !dbg !11
+; CHECK:             r0 = 0
+; CHECK-NEXT:        r0 <<= 56
+; CHECK-NEXT:        r0 s>>= 56
   ret i32 %2, !dbg !15
 }
 
@@ -24,26 +26,62 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   40
-; CHECK-NEXT:        .long   52
+; CHECK-NEXT:        .long   54
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .byte   97                      # string offset=15
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=17
 ; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   44
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   8                       # FuncInfo
+; CHECK-NEXT:        .long   9                       # FuncInfo section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Lfunc_begin0
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   16                      # LineInfo
+; CHECK-NEXT:        .long   9                       # LineInfo section string offset=9
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   17
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   2068                    # Line 2 Col 20
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   17
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   2061                    # Line 2 Col 13
+; CHECK-NEXT:        .long   8                       # ExternReloc
+; CHECK-NEXT:        .long   9                       # Extern reloc section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   15
 
 attributes #0 = { norecurse nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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" }
 
@@ -52,7 +90,7 @@ attributes #0 = { norecurse nounwind rea
 !llvm.ident = !{!6}
 
 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
-!1 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug")
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
 !2 = !{}
 !3 = !{i32 2, !"Dwarf Version", i32 4}
 !4 = !{i32 2, !"Debug Info Version", i32 3}

Copied: llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-uint.ll (from r365502, llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-uint.ll?p2=llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-uint.ll&p1=llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll&r1=365502&r2=365503&rev=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-uint.ll Tue Jul  9 08:28:41 2019
@@ -1,19 +1,19 @@
 ; 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:
-;   extern char a;
+;   extern __attribute__((section(".BPF.patchable_externs"))) unsigned a;
 ;   int foo() { return a; }
 ; Compilation flag:
 ;   clang -target bpf -O2 -g -S -emit-llvm test.c
 
- at a = external dso_local local_unnamed_addr global i8, align 1
+ at a = external dso_local local_unnamed_addr global i32, section ".BPF.patchable_externs", align 4
 
 ; Function Attrs: norecurse nounwind readonly
 define dso_local i32 @foo() local_unnamed_addr #0 !dbg !7 {
-  %1 = load i8, i8* @a, align 1, !dbg !11, !tbaa !12
-  %2 = sext i8 %1 to i32, !dbg !11
-  ret i32 %2, !dbg !15
+  %1 = load i32, i32* @a, align 4, !dbg !11, !tbaa !12
+; CHECK:             r0 = 0
+; CHECK-NEXT:        exit
+  ret i32 %1, !dbg !16
 }
 
 ; CHECK:             .section        .BTF,"", at progbits
@@ -24,26 +24,58 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   40
-; CHECK-NEXT:        .long   52
+; CHECK-NEXT:        .long   49
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .byte   97                      # string offset=15
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  "/tmp/yhs/work/tests/llvm/test.c" # string offset=17
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   8                       # FuncInfo
+; CHECK-NEXT:        .long   9                       # FuncInfo section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Lfunc_begin0
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   16                      # LineInfo
+; CHECK-NEXT:        .long   9                       # LineInfo section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   17
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   2061                    # Line 2 Col 13
+; CHECK-NEXT:        .long   8                       # ExternReloc
+; CHECK-NEXT:        .long   9                       # Extern reloc section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   15
 
 attributes #0 = { norecurse nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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" }
 
@@ -52,7 +84,7 @@ attributes #0 = { norecurse nounwind rea
 !llvm.ident = !{!6}
 
 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
-!1 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug")
+!1 = !DIFile(filename: "test.c", directory: "/tmp/yhs/work/tests/llvm")
 !2 = !{}
 !3 = !{i32 2, !"Dwarf Version", i32 4}
 !4 = !{i32 2, !"Debug Info Version", i32 3}
@@ -64,6 +96,7 @@ attributes #0 = { norecurse nounwind rea
 !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 !11 = !DILocation(line: 2, column: 20, scope: !7)
 !12 = !{!13, !13, i64 0}
-!13 = !{!"omnipotent char", !14, i64 0}
-!14 = !{!"Simple C/C++ TBAA"}
-!15 = !DILocation(line: 2, column: 13, scope: !7)
+!13 = !{!"int", !14, i64 0}
+!14 = !{!"omnipotent char", !15, i64 0}
+!15 = !{!"Simple C/C++ TBAA"}
+!16 = !DILocation(line: 2, column: 13, scope: !7)

Copied: llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-ulonglong.ll (from r365502, llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-ulonglong.ll?p2=llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-ulonglong.ll&p1=llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll&r1=365502&r2=365503&rev=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/BTF/extern-global-var.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/CORE/patchable-extern-ulonglong.ll Tue Jul  9 08:28:41 2019
@@ -1,19 +1,20 @@
 ; 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:
-;   extern char a;
+;   extern __attribute__((section(".BPF.patchable_externs"))) unsigned long long a;
 ;   int foo() { return a; }
 ; Compilation flag:
 ;   clang -target bpf -O2 -g -S -emit-llvm test.c
 
- at a = external dso_local local_unnamed_addr global i8, align 1
+ at a = external dso_local local_unnamed_addr global i64, section ".BPF.patchable_externs", align 8
 
 ; Function Attrs: norecurse nounwind readonly
 define dso_local i32 @foo() local_unnamed_addr #0 !dbg !7 {
-  %1 = load i8, i8* @a, align 1, !dbg !11, !tbaa !12
-  %2 = sext i8 %1 to i32, !dbg !11
-  ret i32 %2, !dbg !15
+  %1 = load i64, i64* @a, align 8, !dbg !11, !tbaa !12
+  %2 = trunc i64 %1 to i32, !dbg !11
+; CHECK:             r0 = 0 ll
+; CHECK-NEXT:        exit
+  ret i32 %2, !dbg !16
 }
 
 ; CHECK:             .section        .BTF,"", at progbits
@@ -24,26 +25,58 @@ define dso_local i32 @foo() local_unname
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   40
-; CHECK-NEXT:        .long   52
+; CHECK-NEXT:        .long   54
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .byte   97                      # string offset=15
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=17
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .section        .BTF.ext,"", at progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   8                       # FuncInfo
+; CHECK-NEXT:        .long   9                       # FuncInfo section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Lfunc_begin0
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   16                      # LineInfo
+; CHECK-NEXT:        .long   9                       # LineInfo section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   17
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   2061                    # Line 2 Col 13
+; CHECK-NEXT:        .long   8                       # ExternReloc
+; CHECK-NEXT:        .long   9                       # Extern reloc section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   15
 
 attributes #0 = { norecurse nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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" }
 
@@ -52,7 +85,7 @@ attributes #0 = { norecurse nounwind rea
 !llvm.ident = !{!6}
 
 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
-!1 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug")
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
 !2 = !{}
 !3 = !{i32 2, !"Dwarf Version", i32 4}
 !4 = !{i32 2, !"Debug Info Version", i32 3}
@@ -64,6 +97,7 @@ attributes #0 = { norecurse nounwind rea
 !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 !11 = !DILocation(line: 2, column: 20, scope: !7)
 !12 = !{!13, !13, i64 0}
-!13 = !{!"omnipotent char", !14, i64 0}
-!14 = !{!"Simple C/C++ TBAA"}
-!15 = !DILocation(line: 2, column: 13, scope: !7)
+!13 = !{!"long long", !14, i64 0}
+!14 = !{!"omnipotent char", !15, i64 0}
+!15 = !{!"Simple C/C++ TBAA"}
+!16 = !DILocation(line: 2, column: 13, scope: !7)

Modified: llvm/trunk/test/CodeGen/BPF/reloc-btf-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/reloc-btf-2.ll?rev=365503&r1=365502&r2=365503&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/reloc-btf-2.ll (original)
+++ llvm/trunk/test/CodeGen/BPF/reloc-btf-2.ll Tue Jul  9 08:28:41 2019
@@ -47,7 +47,7 @@ attributes #0 = { norecurse nounwind "co
 !11 = !{i32 2, !"Debug Info Version", i32 3}
 !12 = !{i32 1, !"wchar_size", i32 4}
 !13 = !{!"clang version 9.0.0 (trunk 360739) (llvm/trunk 360747)"}
-!14 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 3, type: !15, scopeLine: 3, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
+!14 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 3, type: !15, scopeLine: 3, isLocal: false, isDefinition: true, isOptimized: true, unit: !2, retainedNodes: !4)
 !15 = !DISubroutineType(types: !16)
 !16 = !{!9}
 !17 = !DILocation(line: 4, column: 10, scope: !14)




More information about the llvm-commits mailing list