summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorYonghong Song <yhs@fb.com>2018-09-20 22:24:27 +0000
committerYonghong Song <yhs@fb.com>2018-09-20 22:24:27 +0000
commit150ca5143be586e81befc7ab689e1c058ab31710 (patch)
treec50ffdbc836adab4235b004535bc5272aa30d7aa /llvm/lib
parentbb993db080391241b390f8408ff12c16b1e29a84 (diff)
downloadbcm5719-llvm-150ca5143be586e81befc7ab689e1c058ab31710.tar.gz
bcm5719-llvm-150ca5143be586e81befc7ab689e1c058ab31710.zip
bpf: check illegal usage of XADD insn return value
Currently, BPF has XADD (locked add) insn support and the asm looks like: lock *(u32 *)(r1 + 0) += r2 lock *(u64 *)(r1 + 0) += r2 The instruction itself does not have a return value. At the source code level, users often use __sync_fetch_and_add() which eventually translates to XADD. The return value of __sync_fetch_and_add() is supposed to be the old value in the xadd memory location. Since BPF::XADD insn does not support such a return value, this patch added a PreEmit phase to check such a usage. If such an illegal usage pattern is detected, a fatal error will be reported like line 4: Invalid usage of the XADD return value if compiled with -g, or Invalid usage of the XADD return value if compiled without -g. Signed-off-by: Yonghong Song <yhs@fb.com> Acked-by: Alexei Starovoitov <ast@kernel.org> llvm-svn: 342692
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/BPF/BPF.h2
-rw-r--r--llvm/lib/Target/BPF/BPFMIChecking.cpp96
-rw-r--r--llvm/lib/Target/BPF/BPFTargetMachine.cpp1
-rw-r--r--llvm/lib/Target/BPF/CMakeLists.txt1
4 files changed, 100 insertions, 0 deletions
diff --git a/llvm/lib/Target/BPF/BPF.h b/llvm/lib/Target/BPF/BPF.h
index 76d3e1ca5f6..9749e369c2c 100644
--- a/llvm/lib/Target/BPF/BPF.h
+++ b/llvm/lib/Target/BPF/BPF.h
@@ -19,9 +19,11 @@ class BPFTargetMachine;
FunctionPass *createBPFISelDag(BPFTargetMachine &TM);
FunctionPass *createBPFMIPeepholePass();
FunctionPass *createBPFMIPreEmitPeepholePass();
+FunctionPass *createBPFMIPreEmitCheckingPass();
void initializeBPFMIPeepholePass(PassRegistry&);
void initializeBPFMIPreEmitPeepholePass(PassRegistry&);
+void initializeBPFMIPreEmitCheckingPass(PassRegistry&);
}
#endif
diff --git a/llvm/lib/Target/BPF/BPFMIChecking.cpp b/llvm/lib/Target/BPF/BPFMIChecking.cpp
new file mode 100644
index 00000000000..0a311378e77
--- /dev/null
+++ b/llvm/lib/Target/BPF/BPFMIChecking.cpp
@@ -0,0 +1,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();
+}
diff --git a/llvm/lib/Target/BPF/BPFTargetMachine.cpp b/llvm/lib/Target/BPF/BPFTargetMachine.cpp
index 84d89bff74f..ffcb1302533 100644
--- a/llvm/lib/Target/BPF/BPFTargetMachine.cpp
+++ b/llvm/lib/Target/BPF/BPFTargetMachine.cpp
@@ -115,6 +115,7 @@ void BPFPassConfig::addMachineSSAOptimization() {
void BPFPassConfig::addPreEmitPass() {
const BPFSubtarget *Subtarget = getBPFTargetMachine().getSubtargetImpl();
+ addPass(createBPFMIPreEmitCheckingPass());
if (getOptLevel() != CodeGenOpt::None)
if (Subtarget->getHasAlu32() && !DisableMIPeephole)
addPass(createBPFMIPreEmitPeepholePass());
diff --git a/llvm/lib/Target/BPF/CMakeLists.txt b/llvm/lib/Target/BPF/CMakeLists.txt
index ee01b4b7b80..5e2ae533ea6 100644
--- a/llvm/lib/Target/BPF/CMakeLists.txt
+++ b/llvm/lib/Target/BPF/CMakeLists.txt
@@ -24,6 +24,7 @@ add_llvm_target(BPFCodeGen
BPFSubtarget.cpp
BPFTargetMachine.cpp
BPFMIPeephole.cpp
+ BPFMIChecking.cpp
)
add_subdirectory(AsmParser)
OpenPOWER on IntegriCloud