diff options
| author | Yonghong Song <yhs@fb.com> | 2018-09-20 22:24:27 +0000 |
|---|---|---|
| committer | Yonghong Song <yhs@fb.com> | 2018-09-20 22:24:27 +0000 |
| commit | 150ca5143be586e81befc7ab689e1c058ab31710 (patch) | |
| tree | c50ffdbc836adab4235b004535bc5272aa30d7aa /llvm/lib | |
| parent | bb993db080391241b390f8408ff12c16b1e29a84 (diff) | |
| download | bcm5719-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.h | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/BPF/BPFMIChecking.cpp | 96 | ||||
| -rw-r--r-- | llvm/lib/Target/BPF/BPFTargetMachine.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/BPF/CMakeLists.txt | 1 |
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) |

