Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp
Line
Count
Source (jump to first uncovered line)
1
//===----- BPFMISimplifyPatchable.cpp - MI Simplify Patchable Insts -------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This pass targets a subset of instructions like below
10
//    ld_imm64 r1, @global
11
//    ldd r2, r1, 0
12
//    add r3, struct_base_reg, r2
13
//
14
// Here @global should either present a AMA (abstruct member access) or
15
// a patchable extern variable. And these two kinds of accesses
16
// are subject to bpf load time patching. After this pass, the
17
// code becomes
18
//    ld_imm64 r1, @global
19
//    add r3, struct_base_reg, r1
20
//
21
// Eventually, at BTF output stage, a relocation record will be generated
22
// for ld_imm64 which should be replaced later by bpf loader:
23
//    r1 = <calculated offset> or <to_be_patched_extern_val>
24
//    add r3, struct_base_reg, r1
25
// or
26
//    ld_imm64 r1, <to_be_patched_extern_val>
27
//    add r3, struct_base_reg, r1
28
//
29
//===----------------------------------------------------------------------===//
30
31
#include "BPF.h"
32
#include "BPFCORE.h"
33
#include "BPFInstrInfo.h"
34
#include "BPFTargetMachine.h"
35
#include "llvm/CodeGen/MachineInstrBuilder.h"
36
#include "llvm/CodeGen/MachineRegisterInfo.h"
37
38
using namespace llvm;
39
40
#define DEBUG_TYPE "bpf-mi-simplify-patchable"
41
42
namespace {
43
44
struct BPFMISimplifyPatchable : public MachineFunctionPass {
45
46
  static char ID;
47
  const BPFInstrInfo *TII;
48
  MachineFunction *MF;
49
50
206
  BPFMISimplifyPatchable() : MachineFunctionPass(ID) {
51
206
    initializeBPFMISimplifyPatchablePass(*PassRegistry::getPassRegistry());
52
206
  }
53
54
private:
55
  // Initialize class variables.
56
  void initialize(MachineFunction &MFParm);
57
58
  bool removeLD(void);
59
60
public:
61
  // Main entry point for this pass.
62
284
  bool runOnMachineFunction(MachineFunction &MF) override {
63
284
    if (!skipFunction(MF.getFunction())) {
64
284
      initialize(MF);
65
284
    }
66
284
    return removeLD();
67
284
  }
68
};
69
70
// Initialize class variables.
71
284
void BPFMISimplifyPatchable::initialize(MachineFunction &MFParm) {
72
284
  MF = &MFParm;
73
284
  TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
74
284
  LLVM_DEBUG(dbgs() << "*** BPF simplify patchable insts pass ***\n\n");
75
284
}
76
77
/// Remove unneeded Load instructions.
78
284
bool BPFMISimplifyPatchable::removeLD() {
79
284
  MachineRegisterInfo *MRI = &MF->getRegInfo();
80
284
  MachineInstr *ToErase = nullptr;
81
284
  bool Changed = false;
82
284
83
489
  for (MachineBasicBlock &MBB : *MF) {
84
3.09k
    for (MachineInstr &MI : MBB) {
85
3.09k
      if (ToErase) {
86
19
        ToErase->eraseFromParent();
87
19
        ToErase = nullptr;
88
19
      }
89
3.09k
90
3.09k
      // Ensure the register format is LOAD <reg>, <reg>, 0
91
3.09k
      if (MI.getOpcode() != BPF::LDD && 
MI.getOpcode() != BPF::LDW3.05k
&&
92
3.09k
          
MI.getOpcode() != BPF::LDH3.01k
&&
MI.getOpcode() != BPF::LDB2.98k
&&
93
3.09k
          
MI.getOpcode() != BPF::LDW322.96k
&&
MI.getOpcode() != BPF::LDH322.96k
&&
94
3.09k
          
MI.getOpcode() != BPF::LDB322.95k
)
95
2.95k
        continue;
96
137
97
137
      if (!MI.getOperand(0).isReg() || !MI.getOperand(1).isReg())
98
14
        continue;
99
123
100
123
      if (!MI.getOperand(2).isImm() || MI.getOperand(2).getImm())
101
4
        continue;
102
119
103
119
      unsigned DstReg = MI.getOperand(0).getReg();
104
119
      unsigned SrcReg = MI.getOperand(1).getReg();
105
119
      int64_t ImmVal = MI.getOperand(2).getImm();
106
119
107
119
      MachineInstr *DefInst = MRI->getUniqueVRegDef(SrcReg);
108
119
      if (!DefInst)
109
0
        continue;
110
119
111
119
      bool IsCandidate = false;
112
119
      if (DefInst->getOpcode() == BPF::LD_imm64) {
113
80
        const MachineOperand &MO = DefInst->getOperand(1);
114
80
        if (MO.isGlobal()) {
115
80
          const GlobalValue *GVal = MO.getGlobal();
116
80
          auto *GVar = dyn_cast<GlobalVariable>(GVal);
117
80
          if (GVar) {
118
80
            // Global variables representing structure offset or
119
80
            // patchable extern globals.
120
80
            if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) {
121
13
              assert(ImmVal == 0);
122
13
              IsCandidate = true;
123
67
            } else if (!GVar->hasInitializer() && 
GVar->hasExternalLinkage()10
&&
124
67
                       GVar->getSection() ==
125
10
                           BPFCoreSharedInfo::PatchableExtSecName) {
126
6
              if (ImmVal == 0)
127
6
                IsCandidate = true;
128
0
              else
129
0
                errs() << "WARNING: unhandled patchable extern "
130
0
                       << GVar->getName() << " with load offset " << ImmVal
131
0
                       << "\n";
132
6
            }
133
80
          }
134
80
        }
135
80
      }
136
119
137
119
      if (!IsCandidate)
138
100
        continue;
139
19
140
19
      auto Begin = MRI->use_begin(DstReg), End = MRI->use_end();
141
19
      decltype(End) NextI;
142
38
      for (auto I = Begin; I != End; 
I = NextI19
) {
143
19
        NextI = std::next(I);
144
19
        I->setReg(SrcReg);
145
19
      }
146
19
147
19
      ToErase = &MI;
148
19
      Changed = true;
149
19
    }
150
489
  }
151
284
152
284
  return Changed;
153
284
}
154
155
} // namespace
156
157
INITIALIZE_PASS(BPFMISimplifyPatchable, DEBUG_TYPE,
158
                "BPF PreEmit SimplifyPatchable", false, false)
159
160
char BPFMISimplifyPatchable::ID = 0;
161
206
FunctionPass *llvm::createBPFMISimplifyPatchablePass() {
162
206
  return new BPFMISimplifyPatchable();
163
206
}