Skip to content

Commit

Permalink
[LoongArch] Diagnose the behavior of reading and writing registers th…
Browse files Browse the repository at this point in the history
…at do not conform to the hardware register size

When reading or writing a register that does not conform to the size of a
hardware register, an error message is generated instead of a compiler crash.

Differential Revision: https://reviews.llvm.org/D138008
  • Loading branch information
gonglingqin committed Nov 24, 2022
1 parent 55fceef commit eca62f9
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 0 deletions.
35 changes: 35 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
Expand Up @@ -93,6 +93,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::CTLZ, MVT::i32, Custom);
setOperationAction(ISD::INTRINSIC_VOID, MVT::i32, Custom);
setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i32, Custom);
setOperationAction(ISD::READ_REGISTER, MVT::i32, Custom);
setOperationAction(ISD::WRITE_REGISTER, MVT::i32, Custom);
if (Subtarget.hasBasicF() && !Subtarget.hasBasicD())
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
if (Subtarget.hasBasicF())
Expand All @@ -118,6 +120,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
} else {
setOperationAction(ISD::BITREVERSE, MVT::i32, Legal);
setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom);
setOperationAction(ISD::READ_REGISTER, MVT::i64, Custom);
setOperationAction(ISD::WRITE_REGISTER, MVT::i64, Custom);
}

static const ISD::CondCode FPCCToExpand[] = {
Expand Down Expand Up @@ -244,10 +248,30 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
return lowerFRAMEADDR(Op, DAG);
case ISD::RETURNADDR:
return lowerRETURNADDR(Op, DAG);
case ISD::WRITE_REGISTER:
return lowerWRITE_REGISTER(Op, DAG);
}
return SDValue();
}

SDValue LoongArchTargetLowering::lowerWRITE_REGISTER(SDValue Op,
SelectionDAG &DAG) const {

if (Subtarget.is64Bit() && Op.getOperand(2).getValueType() == MVT::i32) {
DAG.getContext()->emitError(
"On LA64, only 64-bit registers can be written.");
return Op.getOperand(0);
}

if (!Subtarget.is64Bit() && Op.getOperand(2).getValueType() == MVT::i64) {
DAG.getContext()->emitError(
"On LA32, only 32-bit registers can be written.");
return Op.getOperand(0);
}

return Op;
}

SDValue LoongArchTargetLowering::lowerFRAMEADDR(SDValue Op,
SelectionDAG &DAG) const {
if (!isa<ConstantSDNode>(Op.getOperand(0))) {
Expand Down Expand Up @@ -927,6 +951,17 @@ void LoongArchTargetLowering::ReplaceNodeResults(
}
break;
}
case ISD::READ_REGISTER: {
if (Subtarget.is64Bit())
DAG.getContext()->emitError(
"On LA64, only 64-bit registers can be read.");
else
DAG.getContext()->emitError(
"On LA32, only 32-bit registers can be read.");
Results.push_back(DAG.getUNDEF(N->getValueType(0)));
Results.push_back(N->getOperand(0));
break;
}
}
}

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.h
Expand Up @@ -192,6 +192,7 @@ class LoongArchTargetLowering : public TargetLowering {
SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const;

bool isFPImmLegal(const APFloat &Imm, EVT VT,
bool ForCodeSize) const override;
Expand Down
21 changes: 21 additions & 0 deletions llvm/test/CodeGen/LoongArch/get-reg-error-la32.ll
@@ -0,0 +1,21 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: not llc < %s --mtriple=loongarch32 2>&1 | FileCheck %s

define i64 @read_sp() nounwind {
entry:
; CHECK: On LA32, only 32-bit registers can be read.
%a1 = call i64 @llvm.read_register.i64(metadata !0)
ret i64 %a1
}

define void @write_sp(i64 %val) nounwind {
entry:
; CHECK: On LA32, only 32-bit registers can be written.
call void @llvm.write_register.i64(metadata !0, i64 %val)
ret void
}

declare i64 @llvm.read_register.i64(metadata) nounwind
declare void @llvm.write_register.i64(metadata, i64) nounwind

!0 = !{!"$sp\00"}
21 changes: 21 additions & 0 deletions llvm/test/CodeGen/LoongArch/get-reg-error-la64.ll
@@ -0,0 +1,21 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: not llc < %s --mtriple=loongarch64 2>&1 | FileCheck %s

define i32 @read_sp() nounwind {
entry:
; CHECK: On LA64, only 64-bit registers can be read.
%a1 = call i32 @llvm.read_register.i32(metadata !0)
ret i32 %a1
}

define void @write_sp(i32 %val) nounwind {
entry:
; CHECK: On LA64, only 64-bit registers can be written.
call void @llvm.write_register.i32(metadata !0, i32 %val)
ret void
}

declare i32 @llvm.read_register.i32(metadata) nounwind
declare void @llvm.write_register.i32(metadata, i32) nounwind

!0 = !{!"$sp\00"}

0 comments on commit eca62f9

Please sign in to comment.