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 "BPFTargetMachine.h" 19 #include "llvm/CodeGen/MachineFunctionPass.h" 20 #include "llvm/IR/DiagnosticInfo.h" 21 #include "llvm/Support/Debug.h" 22 23 using namespace llvm; 24 25 #define DEBUG_TYPE "bpf-mi-checking" 26 27 namespace { 28 29 struct BPFMIPreEmitChecking : public MachineFunctionPass { 30 31 static char ID; 32 MachineFunction *MF; 33 const TargetRegisterInfo *TRI; 34 35 BPFMIPreEmitChecking() : MachineFunctionPass(ID) { 36 initializeBPFMIPreEmitCheckingPass(*PassRegistry::getPassRegistry()); 37 } 38 39 private: 40 // Initialize class variables. 41 void initialize(MachineFunction &MFParm); 42 43 void processAtomicInsts(); 44 45 public: 46 // Main entry point for this pass. 47 bool runOnMachineFunction(MachineFunction &MF) override { 48 if (!skipFunction(MF.getFunction())) { 49 initialize(MF); 50 processAtomicInsts(); 51 } 52 return false; 53 } 54 }; 55 56 // Initialize class variables. 57 void BPFMIPreEmitChecking::initialize(MachineFunction &MFParm) { 58 MF = &MFParm; 59 TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo(); 60 LLVM_DEBUG(dbgs() << "*** BPF PreEmit checking pass ***\n\n"); 61 } 62 63 // Make sure all Defs of XADD are dead, meaning any result of XADD insn is not 64 // used. 65 // 66 // NOTE: BPF backend hasn't enabled sub-register liveness track, so when the 67 // source and destination operands of XADD are GPR32, there is no sub-register 68 // dead info. If we rely on the generic MachineInstr::allDefsAreDead, then we 69 // will raise false alarm on GPR32 Def. 70 // 71 // To support GPR32 Def, ideally we could just enable sub-registr liveness track 72 // on BPF backend, then allDefsAreDead could work on GPR32 Def. This requires 73 // implementing TargetSubtargetInfo::enableSubRegLiveness on BPF. 74 // 75 // However, sub-register liveness tracking module inside LLVM is actually 76 // designed for the situation where one register could be split into more than 77 // one sub-registers for which case each sub-register could have their own 78 // liveness and kill one of them doesn't kill others. So, tracking liveness for 79 // each make sense. 80 // 81 // For BPF, each 64-bit register could only have one 32-bit sub-register. This 82 // is exactly the case which LLVM think brings no benefits for doing 83 // sub-register tracking, because the live range of sub-register must always 84 // equal to its parent register, therefore liveness tracking is disabled even 85 // the back-end has implemented enableSubRegLiveness. The detailed information 86 // is at r232695: 87 // 88 // Author: Matthias Braun <matze@braunis.de> 89 // Date: Thu Mar 19 00:21:58 2015 +0000 90 // Do not track subregister liveness when it brings no benefits 91 // 92 // Hence, for BPF, we enhance MachineInstr::allDefsAreDead. Given the solo 93 // sub-register always has the same liveness as its parent register, LLVM is 94 // already attaching a implicit 64-bit register Def whenever the there is 95 // a sub-register Def. The liveness of the implicit 64-bit Def is available. 96 // For example, for "lock *(u32 *)(r0 + 4) += w9", the MachineOperand info could 97 // be: 98 // 99 // $w9 = XADDW32 killed $r0, 4, $w9(tied-def 0), 100 // implicit killed $r9, implicit-def dead $r9 101 // 102 // Even though w9 is not marked as Dead, the parent register r9 is marked as 103 // Dead correctly, and it is safe to use such information or our purpose. 104 static bool hasLiveDefs(const MachineInstr &MI, const TargetRegisterInfo *TRI) { 105 const MCRegisterClass *GPR64RegClass = 106 &BPFMCRegisterClasses[BPF::GPRRegClassID]; 107 std::vector<unsigned> GPR32LiveDefs; 108 std::vector<unsigned> GPR64DeadDefs; 109 110 for (const MachineOperand &MO : MI.operands()) { 111 bool RegIsGPR64; 112 113 if (!MO.isReg() || MO.isUse()) 114 continue; 115 116 RegIsGPR64 = GPR64RegClass->contains(MO.getReg()); 117 if (!MO.isDead()) { 118 // It is a GPR64 live Def, we are sure it is live. 119 if (RegIsGPR64) 120 return true; 121 // It is a GPR32 live Def, we are unsure whether it is really dead due to 122 // no sub-register liveness tracking. Push it to vector for deferred 123 // check. 124 GPR32LiveDefs.push_back(MO.getReg()); 125 continue; 126 } 127 128 // Record any GPR64 dead Def as some unmarked GPR32 could be alias of its 129 // low 32-bit. 130 if (RegIsGPR64) 131 GPR64DeadDefs.push_back(MO.getReg()); 132 } 133 134 // No GPR32 live Def, safe to return false. 135 if (GPR32LiveDefs.empty()) 136 return false; 137 138 // No GPR64 dead Def, so all those GPR32 live Def can't have alias, therefore 139 // must be truely live, safe to return true. 140 if (GPR64DeadDefs.empty()) 141 return true; 142 143 // Otherwise, return true if any aliased SuperReg of GPR32 is not dead. 144 for (auto I : GPR32LiveDefs) 145 for (MCPhysReg SR : TRI->superregs(I)) 146 if (!llvm::is_contained(GPR64DeadDefs, SR)) 147 return true; 148 149 return false; 150 } 151 152 void BPFMIPreEmitChecking::processAtomicInsts() { 153 if (MF->getSubtarget<BPFSubtarget>().getHasJmp32()) 154 return; 155 156 // Only check for cpu version 1 and 2. 157 for (MachineBasicBlock &MBB : *MF) { 158 for (MachineInstr &MI : MBB) { 159 if (MI.getOpcode() != BPF::XADDW && MI.getOpcode() != BPF::XADDD) 160 continue; 161 162 LLVM_DEBUG(MI.dump()); 163 if (hasLiveDefs(MI, TRI)) { 164 DebugLoc Empty; 165 const DebugLoc &DL = MI.getDebugLoc(); 166 const Function &F = MF->getFunction(); 167 F.getContext().diagnose(DiagnosticInfoUnsupported{ 168 F, "Invalid usage of the XADD return value", DL}); 169 } 170 } 171 } 172 } 173 174 } // namespace 175 176 INITIALIZE_PASS(BPFMIPreEmitChecking, "bpf-mi-pemit-checking", 177 "BPF PreEmit Checking", false, false) 178 179 char BPFMIPreEmitChecking::ID = 0; 180 FunctionPass *llvm::createBPFMIPreEmitCheckingPass() { 181 return new BPFMIPreEmitChecking(); 182 } 183