1343171Sdim//===-------------- BPFMIChecking.cpp - MI Checking Legality -------------===//
2343171Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343171Sdim//
7343171Sdim//===----------------------------------------------------------------------===//
8343171Sdim//
9343171Sdim// This pass performs checking to signal errors for certain illegal usages at
10343171Sdim// MachineInstruction layer. Specially, the result of XADD{32,64} insn should
11343171Sdim// not be used. The pass is done at the PreEmit pass right before the
12343171Sdim// machine code is emitted at which point the register liveness information
13343171Sdim// is still available.
14343171Sdim//
15343171Sdim//===----------------------------------------------------------------------===//
16343171Sdim
17343171Sdim#include "BPF.h"
18343171Sdim#include "BPFInstrInfo.h"
19343171Sdim#include "BPFTargetMachine.h"
20343171Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
21343171Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
22360784Sdim#include "llvm/Support/Debug.h"
23343171Sdim
24343171Sdimusing namespace llvm;
25343171Sdim
26343171Sdim#define DEBUG_TYPE "bpf-mi-checking"
27343171Sdim
28343171Sdimnamespace {
29343171Sdim
30343171Sdimstruct BPFMIPreEmitChecking : public MachineFunctionPass {
31343171Sdim
32343171Sdim  static char ID;
33343171Sdim  MachineFunction *MF;
34343171Sdim  const TargetRegisterInfo *TRI;
35343171Sdim
36343171Sdim  BPFMIPreEmitChecking() : MachineFunctionPass(ID) {
37343171Sdim    initializeBPFMIPreEmitCheckingPass(*PassRegistry::getPassRegistry());
38343171Sdim  }
39343171Sdim
40343171Sdimprivate:
41343171Sdim  // Initialize class variables.
42343171Sdim  void initialize(MachineFunction &MFParm);
43343171Sdim
44343171Sdim  void checkingIllegalXADD(void);
45343171Sdim
46343171Sdimpublic:
47343171Sdim
48343171Sdim  // Main entry point for this pass.
49343171Sdim  bool runOnMachineFunction(MachineFunction &MF) override {
50343171Sdim    if (!skipFunction(MF.getFunction())) {
51343171Sdim      initialize(MF);
52343171Sdim      checkingIllegalXADD();
53343171Sdim    }
54343171Sdim    return false;
55343171Sdim  }
56343171Sdim};
57343171Sdim
58343171Sdim// Initialize class variables.
59343171Sdimvoid BPFMIPreEmitChecking::initialize(MachineFunction &MFParm) {
60343171Sdim  MF = &MFParm;
61343171Sdim  TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
62343171Sdim  LLVM_DEBUG(dbgs() << "*** BPF PreEmit checking pass ***\n\n");
63343171Sdim}
64343171Sdim
65353358Sdim// Make sure all Defs of XADD are dead, meaning any result of XADD insn is not
66353358Sdim// used.
67353358Sdim//
68353358Sdim// NOTE: BPF backend hasn't enabled sub-register liveness track, so when the
69353358Sdim// source and destination operands of XADD are GPR32, there is no sub-register
70353358Sdim// dead info. If we rely on the generic MachineInstr::allDefsAreDead, then we
71353358Sdim// will raise false alarm on GPR32 Def.
72353358Sdim//
73353358Sdim// To support GPR32 Def, ideally we could just enable sub-registr liveness track
74353358Sdim// on BPF backend, then allDefsAreDead could work on GPR32 Def. This requires
75353358Sdim// implementing TargetSubtargetInfo::enableSubRegLiveness on BPF.
76353358Sdim//
77353358Sdim// However, sub-register liveness tracking module inside LLVM is actually
78353358Sdim// designed for the situation where one register could be split into more than
79353358Sdim// one sub-registers for which case each sub-register could have their own
80353358Sdim// liveness and kill one of them doesn't kill others. So, tracking liveness for
81353358Sdim// each make sense.
82353358Sdim//
83353358Sdim// For BPF, each 64-bit register could only have one 32-bit sub-register. This
84353358Sdim// is exactly the case which LLVM think brings no benefits for doing
85353358Sdim// sub-register tracking, because the live range of sub-register must always
86353358Sdim// equal to its parent register, therefore liveness tracking is disabled even
87353358Sdim// the back-end has implemented enableSubRegLiveness. The detailed information
88353358Sdim// is at r232695:
89353358Sdim//
90353358Sdim//   Author: Matthias Braun <matze@braunis.de>
91353358Sdim//   Date:   Thu Mar 19 00:21:58 2015 +0000
92353358Sdim//   Do not track subregister liveness when it brings no benefits
93353358Sdim//
94353358Sdim// Hence, for BPF, we enhance MachineInstr::allDefsAreDead. Given the solo
95353358Sdim// sub-register always has the same liveness as its parent register, LLVM is
96353358Sdim// already attaching a implicit 64-bit register Def whenever the there is
97353358Sdim// a sub-register Def. The liveness of the implicit 64-bit Def is available.
98353358Sdim// For example, for "lock *(u32 *)(r0 + 4) += w9", the MachineOperand info could
99353358Sdim// be:
100353358Sdim//
101353358Sdim//   $w9 = XADDW32 killed $r0, 4, $w9(tied-def 0),
102353358Sdim//                        implicit killed $r9, implicit-def dead $r9
103353358Sdim//
104353358Sdim// Even though w9 is not marked as Dead, the parent register r9 is marked as
105353358Sdim// Dead correctly, and it is safe to use such information or our purpose.
106353358Sdimstatic bool hasLiveDefs(const MachineInstr &MI, const TargetRegisterInfo *TRI) {
107353358Sdim  const MCRegisterClass *GPR64RegClass =
108353358Sdim    &BPFMCRegisterClasses[BPF::GPRRegClassID];
109353358Sdim  std::vector<unsigned> GPR32LiveDefs;
110353358Sdim  std::vector<unsigned> GPR64DeadDefs;
111353358Sdim
112353358Sdim  for (const MachineOperand &MO : MI.operands()) {
113353358Sdim    bool RegIsGPR64;
114353358Sdim
115353358Sdim    if (!MO.isReg() || MO.isUse())
116353358Sdim      continue;
117353358Sdim
118353358Sdim    RegIsGPR64 = GPR64RegClass->contains(MO.getReg());
119353358Sdim    if (!MO.isDead()) {
120353358Sdim      // It is a GPR64 live Def, we are sure it is live. */
121353358Sdim      if (RegIsGPR64)
122353358Sdim        return true;
123353358Sdim      // It is a GPR32 live Def, we are unsure whether it is really dead due to
124353358Sdim      // no sub-register liveness tracking. Push it to vector for deferred
125353358Sdim      // check.
126353358Sdim      GPR32LiveDefs.push_back(MO.getReg());
127353358Sdim      continue;
128353358Sdim    }
129353358Sdim
130353358Sdim    // Record any GPR64 dead Def as some unmarked GPR32 could be alias of its
131353358Sdim    // low 32-bit.
132353358Sdim    if (RegIsGPR64)
133353358Sdim      GPR64DeadDefs.push_back(MO.getReg());
134353358Sdim  }
135353358Sdim
136353358Sdim  // No GPR32 live Def, safe to return false.
137353358Sdim  if (GPR32LiveDefs.empty())
138353358Sdim    return false;
139353358Sdim
140353358Sdim  // No GPR64 dead Def, so all those GPR32 live Def can't have alias, therefore
141353358Sdim  // must be truely live, safe to return true.
142353358Sdim  if (GPR64DeadDefs.empty())
143353358Sdim    return true;
144353358Sdim
145353358Sdim  // Otherwise, return true if any aliased SuperReg of GPR32 is not dead.
146353358Sdim  std::vector<unsigned>::iterator search_begin = GPR64DeadDefs.begin();
147353358Sdim  std::vector<unsigned>::iterator search_end = GPR64DeadDefs.end();
148353358Sdim  for (auto I : GPR32LiveDefs)
149353358Sdim    for (MCSuperRegIterator SR(I, TRI); SR.isValid(); ++SR)
150353358Sdim       if (std::find(search_begin, search_end, *SR) == search_end)
151353358Sdim         return true;
152353358Sdim
153353358Sdim  return false;
154353358Sdim}
155353358Sdim
156343171Sdimvoid BPFMIPreEmitChecking::checkingIllegalXADD(void) {
157343171Sdim  for (MachineBasicBlock &MBB : *MF) {
158343171Sdim    for (MachineInstr &MI : MBB) {
159353358Sdim      if (MI.getOpcode() != BPF::XADDW &&
160353358Sdim          MI.getOpcode() != BPF::XADDD &&
161353358Sdim          MI.getOpcode() != BPF::XADDW32)
162343171Sdim        continue;
163343171Sdim
164343171Sdim      LLVM_DEBUG(MI.dump());
165353358Sdim      if (hasLiveDefs(MI, TRI)) {
166343171Sdim        DebugLoc Empty;
167343171Sdim        const DebugLoc &DL = MI.getDebugLoc();
168343171Sdim        if (DL != Empty)
169343171Sdim          report_fatal_error("line " + std::to_string(DL.getLine()) +
170343171Sdim                             ": Invalid usage of the XADD return value", false);
171343171Sdim        else
172343171Sdim          report_fatal_error("Invalid usage of the XADD return value", false);
173343171Sdim      }
174343171Sdim    }
175343171Sdim  }
176343171Sdim
177343171Sdim  return;
178343171Sdim}
179343171Sdim
180343171Sdim} // end default namespace
181343171Sdim
182343171SdimINITIALIZE_PASS(BPFMIPreEmitChecking, "bpf-mi-pemit-checking",
183343171Sdim                "BPF PreEmit Checking", false, false)
184343171Sdim
185343171Sdimchar BPFMIPreEmitChecking::ID = 0;
186343171SdimFunctionPass* llvm::createBPFMIPreEmitCheckingPass()
187343171Sdim{
188343171Sdim  return new BPFMIPreEmitChecking();
189343171Sdim}
190