LLVM  10.0.0svn
BPFMIChecking.cpp
Go to the documentation of this file.
1 //===-------------- BPFMIChecking.cpp - MI Checking Legality -------------===//
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 performs checking to signal errors for certain illegal usages at
10 // MachineInstruction layer. Specially, the result of XADD{32,64} insn should
11 // not be used. The pass is done at the PreEmit pass right before the
12 // machine code is emitted at which point the register liveness information
13 // is still available.
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #include "BPF.h"
18 #include "BPFInstrInfo.h"
19 #include "BPFTargetMachine.h"
22 #include "llvm/Support/Debug.h"
23 
24 using namespace llvm;
25 
26 #define DEBUG_TYPE "bpf-mi-checking"
27 
28 namespace {
29 
30 struct BPFMIPreEmitChecking : public MachineFunctionPass {
31 
32  static char ID;
33  MachineFunction *MF;
34  const TargetRegisterInfo *TRI;
35 
36  BPFMIPreEmitChecking() : MachineFunctionPass(ID) {
38  }
39 
40 private:
41  // Initialize class variables.
42  void initialize(MachineFunction &MFParm);
43 
44  void checkingIllegalXADD(void);
45 
46 public:
47 
48  // Main entry point for this pass.
49  bool runOnMachineFunction(MachineFunction &MF) override {
50  if (!skipFunction(MF.getFunction())) {
51  initialize(MF);
52  checkingIllegalXADD();
53  }
54  return false;
55  }
56 };
57 
58 // Initialize class variables.
60  MF = &MFParm;
61  TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
62  LLVM_DEBUG(dbgs() << "*** BPF PreEmit checking pass ***\n\n");
63 }
64 
65 // Make sure all Defs of XADD are dead, meaning any result of XADD insn is not
66 // used.
67 //
68 // NOTE: BPF backend hasn't enabled sub-register liveness track, so when the
69 // source and destination operands of XADD are GPR32, there is no sub-register
70 // dead info. If we rely on the generic MachineInstr::allDefsAreDead, then we
71 // will raise false alarm on GPR32 Def.
72 //
73 // To support GPR32 Def, ideally we could just enable sub-registr liveness track
74 // on BPF backend, then allDefsAreDead could work on GPR32 Def. This requires
75 // implementing TargetSubtargetInfo::enableSubRegLiveness on BPF.
76 //
77 // However, sub-register liveness tracking module inside LLVM is actually
78 // designed for the situation where one register could be split into more than
79 // one sub-registers for which case each sub-register could have their own
80 // liveness and kill one of them doesn't kill others. So, tracking liveness for
81 // each make sense.
82 //
83 // For BPF, each 64-bit register could only have one 32-bit sub-register. This
84 // is exactly the case which LLVM think brings no benefits for doing
85 // sub-register tracking, because the live range of sub-register must always
86 // equal to its parent register, therefore liveness tracking is disabled even
87 // the back-end has implemented enableSubRegLiveness. The detailed information
88 // is at r232695:
89 //
90 // Author: Matthias Braun <matze@braunis.de>
91 // Date: Thu Mar 19 00:21:58 2015 +0000
92 // Do not track subregister liveness when it brings no benefits
93 //
94 // Hence, for BPF, we enhance MachineInstr::allDefsAreDead. Given the solo
95 // sub-register always has the same liveness as its parent register, LLVM is
96 // already attaching a implicit 64-bit register Def whenever the there is
97 // a sub-register Def. The liveness of the implicit 64-bit Def is available.
98 // For example, for "lock *(u32 *)(r0 + 4) += w9", the MachineOperand info could
99 // be:
100 //
101 // $w9 = XADDW32 killed $r0, 4, $w9(tied-def 0),
102 // implicit killed $r9, implicit-def dead $r9
103 //
104 // Even though w9 is not marked as Dead, the parent register r9 is marked as
105 // Dead correctly, and it is safe to use such information or our purpose.
106 static bool hasLiveDefs(const MachineInstr &MI, const TargetRegisterInfo *TRI) {
107  const MCRegisterClass *GPR64RegClass =
108  &BPFMCRegisterClasses[BPF::GPRRegClassID];
109  std::vector<unsigned> GPR32LiveDefs;
110  std::vector<unsigned> GPR64DeadDefs;
111 
112  for (const MachineOperand &MO : MI.operands()) {
113  bool RegIsGPR64;
114 
115  if (!MO.isReg() || MO.isUse())
116  continue;
117 
118  RegIsGPR64 = GPR64RegClass->contains(MO.getReg());
119  if (!MO.isDead()) {
120  // It is a GPR64 live Def, we are sure it is live. */
121  if (RegIsGPR64)
122  return true;
123  // It is a GPR32 live Def, we are unsure whether it is really dead due to
124  // no sub-register liveness tracking. Push it to vector for deferred
125  // check.
126  GPR32LiveDefs.push_back(MO.getReg());
127  continue;
128  }
129 
130  // Record any GPR64 dead Def as some unmarked GPR32 could be alias of its
131  // low 32-bit.
132  if (RegIsGPR64)
133  GPR64DeadDefs.push_back(MO.getReg());
134  }
135 
136  // No GPR32 live Def, safe to return false.
137  if (GPR32LiveDefs.empty())
138  return false;
139 
140  // No GPR64 dead Def, so all those GPR32 live Def can't have alias, therefore
141  // must be truely live, safe to return true.
142  if (GPR64DeadDefs.empty())
143  return true;
144 
145  // Otherwise, return true if any aliased SuperReg of GPR32 is not dead.
146  std::vector<unsigned>::iterator search_begin = GPR64DeadDefs.begin();
147  std::vector<unsigned>::iterator search_end = GPR64DeadDefs.end();
148  for (auto I : GPR32LiveDefs)
149  for (MCSuperRegIterator SR(I, TRI); SR.isValid(); ++SR)
150  if (std::find(search_begin, search_end, *SR) == search_end)
151  return true;
152 
153  return false;
154 }
155 
156 void BPFMIPreEmitChecking::checkingIllegalXADD(void) {
157  for (MachineBasicBlock &MBB : *MF) {
158  for (MachineInstr &MI : MBB) {
159  if (MI.getOpcode() != BPF::XADDW &&
160  MI.getOpcode() != BPF::XADDD &&
161  MI.getOpcode() != BPF::XADDW32)
162  continue;
163 
164  LLVM_DEBUG(MI.dump());
165  if (hasLiveDefs(MI, TRI)) {
166  DebugLoc Empty;
167  const DebugLoc &DL = MI.getDebugLoc();
168  if (DL != Empty)
169  report_fatal_error("line " + std::to_string(DL.getLine()) +
170  ": Invalid usage of the XADD return value", false);
171  else
172  report_fatal_error("Invalid usage of the XADD return value", false);
173  }
174  }
175  }
176 
177  return;
178 }
179 
180 } // end default namespace
181 
182 INITIALIZE_PASS(BPFMIPreEmitChecking, "bpf-mi-pemit-checking",
183  "BPF PreEmit Checking", false, false)
184 
185 char BPFMIPreEmitChecking::ID = 0;
187 {
188  return new BPFMIPreEmitChecking();
189 }
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:139
This class represents lattice values for constants.
Definition: AllocatorList.h:23
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:384
FunctionPass * createBPFMIPreEmitCheckingPass()
void initializeBPFMIPreEmitCheckingPass(PassRegistry &)
unsigned getLine() const
Definition: DebugLoc.cpp:25
unsigned const TargetRegisterInfo * TRI
A debug info location.
Definition: DebugLoc.h:33
iterator_range< mop_iterator > operands()
Definition: MachineInstr.h:476
MCSuperRegIterator enumerates all super-registers of Reg.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:410
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringLiteral > StandardNames)
Initialize the set of available library functions based on the specified target triple.
MCRegisterClass - Base class of TargetRegisterClass.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1186
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:33
MachineOperand class - Representation of each machine instruction operand.
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
bool isValid() const
isValid - returns true if this iterator is not yet at the end.
Representation of each machine instruction.
Definition: MachineInstr.h:63
#define I(x, y, z)
Definition: MD5.cpp:58
const std::string to_string(const T &Value)
Definition: ScopedPrinter.h:61
IRTranslator LLVM IR MI
#define LLVM_DEBUG(X)
Definition: Debug.h:122