mirror of
https://github.com/RPCS3/llvm.git
synced 2025-05-14 17:36:29 +00:00

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> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@342692 91177308-0d34-0410-b5e6-96231b3b80d8
97 lines
2.7 KiB
C++
97 lines
2.7 KiB
C++
//===-------------- 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();
|
|
}
|