1 //===-------------- BPFMIChecking.cpp - MI Checking Legality -------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This pass performs checking to signal errors for certain illegal usages at
11 // MachineInstruction layer. Specially, the result of XADD{32,64} insn should
12 // not be used. The pass is done at the PreEmit pass right before the
13 // machine code is emitted at which point the register liveness information
14 // is still available.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #include "BPF.h"
19 #include "BPFInstrInfo.h"
20 #include "BPFTargetMachine.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.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 
BPFMIPreEmitChecking__anonffca4bdc0111::BPFMIPreEmitChecking36   BPFMIPreEmitChecking() : MachineFunctionPass(ID) {
37     initializeBPFMIPreEmitCheckingPass(*PassRegistry::getPassRegistry());
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.
runOnMachineFunction__anonffca4bdc0111::BPFMIPreEmitChecking49   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.
initialize(MachineFunction & MFParm)59 void BPFMIPreEmitChecking::initialize(MachineFunction &MFParm) {
60   MF = &MFParm;
61   TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
62   LLVM_DEBUG(dbgs() << "*** BPF PreEmit checking pass ***\n\n");
63 }
64 
checkingIllegalXADD(void)65 void BPFMIPreEmitChecking::checkingIllegalXADD(void) {
66   for (MachineBasicBlock &MBB : *MF) {
67     for (MachineInstr &MI : MBB) {
68       if (MI.getOpcode() != BPF::XADD32 && MI.getOpcode() != BPF::XADD64)
69         continue;
70 
71       LLVM_DEBUG(MI.dump());
72       if (!MI.allDefsAreDead()) {
73         DebugLoc Empty;
74         const DebugLoc &DL = MI.getDebugLoc();
75         if (DL != Empty)
76           report_fatal_error("line " + std::to_string(DL.getLine()) +
77                              ": Invalid usage of the XADD return value", false);
78         else
79           report_fatal_error("Invalid usage of the XADD return value", false);
80       }
81     }
82   }
83 
84   return;
85 }
86 
87 } // end default namespace
88 
89 INITIALIZE_PASS(BPFMIPreEmitChecking, "bpf-mi-pemit-checking",
90                 "BPF PreEmit Checking", false, false)
91 
92 char BPFMIPreEmitChecking::ID = 0;
createBPFMIPreEmitCheckingPass()93 FunctionPass* llvm::createBPFMIPreEmitCheckingPass()
94 {
95   return new BPFMIPreEmitChecking();
96 }
97