summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/BPF/BPFMIChecking.cpp
blob: 0a311378e7774895e172fad5b6676db6a4f98789 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//===-------------- BPFMIChecking.cpp - MI Checking Legality -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass performs checking to signal errors for certain illegal usages at
// MachineInstruction layer. Specially, the result of XADD{32,64} insn should
// not be used. The pass is done at the PreEmit pass right before the
// machine code is emitted at which point the register liveness information
// is still available.
//
//===----------------------------------------------------------------------===//

#include "BPF.h"
#include "BPFInstrInfo.h"
#include "BPFTargetMachine.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"

using namespace llvm;

#define DEBUG_TYPE "bpf-mi-checking"

namespace {

struct BPFMIPreEmitChecking : public MachineFunctionPass {

  static char ID;
  MachineFunction *MF;
  const TargetRegisterInfo *TRI;

  BPFMIPreEmitChecking() : MachineFunctionPass(ID) {
    initializeBPFMIPreEmitCheckingPass(*PassRegistry::getPassRegistry());
  }

private:
  // Initialize class variables.
  void initialize(MachineFunction &MFParm);

  void checkingIllegalXADD(void);

public:

  // Main entry point for this pass.
  bool runOnMachineFunction(MachineFunction &MF) override {
    if (!skipFunction(MF.getFunction())) {
      initialize(MF);
      checkingIllegalXADD();
    }
    return false;
  }
};

// Initialize class variables.
void BPFMIPreEmitChecking::initialize(MachineFunction &MFParm) {
  MF = &MFParm;
  TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
  LLVM_DEBUG(dbgs() << "*** BPF PreEmit checking pass ***\n\n");
}

void BPFMIPreEmitChecking::checkingIllegalXADD(void) {
  for (MachineBasicBlock &MBB : *MF) {
    for (MachineInstr &MI : MBB) {
      if (MI.getOpcode() != BPF::XADD32 && MI.getOpcode() != BPF::XADD64)
        continue;

      LLVM_DEBUG(MI.dump());
      if (!MI.allDefsAreDead()) {
        DebugLoc Empty;
        const DebugLoc &DL = MI.getDebugLoc();
        if (DL != Empty)
          report_fatal_error("line " + std::to_string(DL.getLine()) +
                             ": Invalid usage of the XADD return value", false);
        else
          report_fatal_error("Invalid usage of the XADD return value", false);
      }
    }
  }

  return;
}

} // end default namespace

INITIALIZE_PASS(BPFMIPreEmitChecking, "bpf-mi-pemit-checking",
                "BPF PreEmit Checking", false, false)

char BPFMIPreEmitChecking::ID = 0;
FunctionPass* llvm::createBPFMIPreEmitCheckingPass()
{
  return new BPFMIPreEmitChecking();
}
OpenPOWER on IntegriCloud