forked from OSchip/llvm-project
BPF: provide better error message for unsupported atomic operations
Currently, BPF backend does not support all variants of atomic_load_{add,and,or,xor}, atomic_swap and atomic_cmp_swap For example, it only supports 32bit (with alu32 mode) and 64bit operations for atomic_load_{and,or,xor}, atomic_swap and atomic_cmp_swap. Due to historical reason, atomic_load_add is always supported with 32bit and 64bit. If user used an unsupported atomic operation, currently, codegen selectiondag cannot find bpf support and will issue a fatal error. This is not user friendly as user may mistakenly think this is a compiler bug. This patch added Custom rule for unsupported atomic operations and will emit better error message during ReplaceNodeResults() callback. The following is an example output. $ cat t.c short sync(short *p) { return __sync_val_compare_and_swap (p, 2, 3); } $ clang -target bpf -O2 -g -c t.c t.c:2:11: error: Unsupported atomic operations, please use 64 bit version return __sync_val_compare_and_swap (p, 2, 3); ^ fatal error: error in backend: Cannot select: t19: i64,ch = AtomicCmpSwap<(load store seq_cst seq_cst 2 on %ir.p)> t0, t2, Constant:i64<2>, Constant:i64<3>, t.c:2:11 t2: i64,ch = CopyFromReg t0, Register:i64 %0 t1: i64 = Register %0 t11: i64 = Constant<2> t10: i64 = Constant<3> In function: sync PLEASE submit a bug report ... Fatal error will still happen since we did not really do proper lowering for these unsupported atomic operations. But we do get a much better error message. Differential Revision: https://reviews.llvm.org/D98471
This commit is contained in:
parent
c578508b5b
commit
379d908848
|
@ -78,6 +78,24 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
|
|||
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
|
||||
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
|
||||
|
||||
// Set unsupported atomic operations as Custom so
|
||||
// we can emit better error messages than fatal error
|
||||
// from selectiondag.
|
||||
for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) {
|
||||
if (VT == MVT::i32) {
|
||||
if (STI.getHasAlu32())
|
||||
continue;
|
||||
} else {
|
||||
setOperationAction(ISD::ATOMIC_LOAD_ADD, VT, Custom);
|
||||
}
|
||||
|
||||
setOperationAction(ISD::ATOMIC_LOAD_AND, VT, Custom);
|
||||
setOperationAction(ISD::ATOMIC_LOAD_OR, VT, Custom);
|
||||
setOperationAction(ISD::ATOMIC_LOAD_XOR, VT, Custom);
|
||||
setOperationAction(ISD::ATOMIC_SWAP, VT, Custom);
|
||||
setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, VT, Custom);
|
||||
}
|
||||
|
||||
for (auto VT : { MVT::i32, MVT::i64 }) {
|
||||
if (VT == MVT::i32 && !STI.getHasAlu32())
|
||||
continue;
|
||||
|
@ -218,6 +236,30 @@ BPFTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
|
|||
return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
|
||||
}
|
||||
|
||||
void BPFTargetLowering::ReplaceNodeResults(
|
||||
SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const {
|
||||
const char *err_msg;
|
||||
uint32_t Opcode = N->getOpcode();
|
||||
switch (Opcode) {
|
||||
default:
|
||||
report_fatal_error("Unhandled custom legalization");
|
||||
case ISD::ATOMIC_LOAD_ADD:
|
||||
case ISD::ATOMIC_LOAD_AND:
|
||||
case ISD::ATOMIC_LOAD_OR:
|
||||
case ISD::ATOMIC_LOAD_XOR:
|
||||
case ISD::ATOMIC_SWAP:
|
||||
case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS:
|
||||
if (HasAlu32 || Opcode == ISD::ATOMIC_LOAD_ADD)
|
||||
err_msg = "Unsupported atomic operations, please use 32/64 bit version";
|
||||
else
|
||||
err_msg = "Unsupported atomic operations, please use 64 bit version";
|
||||
break;
|
||||
}
|
||||
|
||||
SDLoc DL(N);
|
||||
fail(DL, DAG, err_msg);
|
||||
}
|
||||
|
||||
SDValue BPFTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
switch (Op.getOpcode()) {
|
||||
case ISD::BR_CC:
|
||||
|
|
|
@ -99,6 +99,9 @@ private:
|
|||
const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
|
||||
SelectionDAG &DAG) const override;
|
||||
|
||||
void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
|
||||
SelectionDAG &DAG) const override;
|
||||
|
||||
EVT getOptimalMemOpType(const MemOp &Op,
|
||||
const AttributeList &FuncAttributes) const override {
|
||||
return Op.size() >= 8 ? MVT::i64 : MVT::i32;
|
||||
|
|
Loading…
Reference in New Issue