mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
Teach frame lowering to ignore debug values after the terminators.
llvm-svn: 123399
This commit is contained in:
parent
569cd41943
commit
0f2b9d9dc4
@ -300,6 +300,10 @@ public:
|
|||||||
/// it returns end()
|
/// it returns end()
|
||||||
iterator getFirstTerminator();
|
iterator getFirstTerminator();
|
||||||
|
|
||||||
|
/// getLastNonDebugInstr - returns an iterator to the last non-debug
|
||||||
|
/// instruction in the basic block, or end()
|
||||||
|
iterator getLastNonDebugInstr();
|
||||||
|
|
||||||
/// SplitCriticalEdge - Split the critical edge from this block to the
|
/// SplitCriticalEdge - Split the critical edge from this block to the
|
||||||
/// given successor block, and return the newly created block, or null
|
/// given successor block, and return the newly created block, or null
|
||||||
/// if splitting is not possible.
|
/// if splitting is not possible.
|
||||||
|
@ -162,6 +162,18 @@ MachineBasicBlock::iterator MachineBasicBlock::getFirstTerminator() {
|
|||||||
return I;
|
return I;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MachineBasicBlock::iterator MachineBasicBlock::getLastNonDebugInstr() {
|
||||||
|
iterator B = begin(), I = end();
|
||||||
|
while (I != B) {
|
||||||
|
--I;
|
||||||
|
if (I->isDebugValue())
|
||||||
|
continue;
|
||||||
|
return I;
|
||||||
|
}
|
||||||
|
// The block is all debug values.
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
|
||||||
void MachineBasicBlock::dump() const {
|
void MachineBasicBlock::dump() const {
|
||||||
print(dbgs());
|
print(dbgs());
|
||||||
}
|
}
|
||||||
|
@ -297,7 +297,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const {
|
|||||||
|
|
||||||
void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
|
void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
MachineBasicBlock &MBB) const {
|
MachineBasicBlock &MBB) const {
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
assert(MBBI->getDesc().isReturn() &&
|
assert(MBBI->getDesc().isReturn() &&
|
||||||
"Can only insert epilog into returning blocks");
|
"Can only insert epilog into returning blocks");
|
||||||
unsigned RetOpcode = MBBI->getOpcode();
|
unsigned RetOpcode = MBBI->getOpcode();
|
||||||
@ -378,7 +378,7 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
|
|||||||
if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND ||
|
if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND ||
|
||||||
RetOpcode == ARM::TCRETURNri || RetOpcode == ARM::TCRETURNriND) {
|
RetOpcode == ARM::TCRETURNri || RetOpcode == ARM::TCRETURNriND) {
|
||||||
// Tail call return: adjust the stack pointer and jump to callee.
|
// Tail call return: adjust the stack pointer and jump to callee.
|
||||||
MBBI = prior(MBB.end());
|
MBBI = MBB.getLastNonDebugInstr();
|
||||||
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
||||||
|
|
||||||
// Jump to label or value in register.
|
// Jump to label or value in register.
|
||||||
|
@ -189,7 +189,7 @@ static bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) {
|
|||||||
|
|
||||||
void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF,
|
void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
MachineBasicBlock &MBB) const {
|
MachineBasicBlock &MBB) const {
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
assert((MBBI->getOpcode() == ARM::tBX_RET ||
|
assert((MBBI->getOpcode() == ARM::tBX_RET ||
|
||||||
MBBI->getOpcode() == ARM::tPOP_RET) &&
|
MBBI->getOpcode() == ARM::tPOP_RET) &&
|
||||||
"Can only insert epilog into returning blocks");
|
"Can only insert epilog into returning blocks");
|
||||||
|
@ -104,7 +104,7 @@ void AlphaFrameLowering::emitPrologue(MachineFunction &MF) const {
|
|||||||
void AlphaFrameLowering::emitEpilogue(MachineFunction &MF,
|
void AlphaFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
MachineBasicBlock &MBB) const {
|
MachineBasicBlock &MBB) const {
|
||||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
||||||
|
|
||||||
assert((MBBI->getOpcode() == Alpha::RETDAG ||
|
assert((MBBI->getOpcode() == Alpha::RETDAG ||
|
||||||
|
@ -90,7 +90,7 @@ void BlackfinFrameLowering::emitEpilogue(MachineFunction &MF,
|
|||||||
static_cast<const BlackfinRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
static_cast<const BlackfinRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
const BlackfinInstrInfo &TII =
|
const BlackfinInstrInfo &TII =
|
||||||
*static_cast<const BlackfinInstrInfo*>(MF.getTarget().getInstrInfo());
|
*static_cast<const BlackfinInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
DebugLoc dl = MBBI->getDebugLoc();
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
|
||||||
int FrameSize = MFI->getStackSize();
|
int FrameSize = MFI->getStackSize();
|
||||||
|
@ -187,7 +187,7 @@ void SPUFrameLowering::emitPrologue(MachineFunction &MF) const {
|
|||||||
// sufficient number instructions in the basic block. Note that
|
// sufficient number instructions in the basic block. Note that
|
||||||
// this is just a best guess based on the basic block's size.
|
// this is just a best guess based on the basic block's size.
|
||||||
if (MBB.size() >= (unsigned) SPUFrameLowering::branchHintPenalty()) {
|
if (MBB.size() >= (unsigned) SPUFrameLowering::branchHintPenalty()) {
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
dl = MBBI->getDebugLoc();
|
dl = MBBI->getDebugLoc();
|
||||||
|
|
||||||
// Insert terminator label
|
// Insert terminator label
|
||||||
@ -199,7 +199,7 @@ void SPUFrameLowering::emitPrologue(MachineFunction &MF) const {
|
|||||||
|
|
||||||
void SPUFrameLowering::emitEpilogue(MachineFunction &MF,
|
void SPUFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
MachineBasicBlock &MBB) const {
|
MachineBasicBlock &MBB) const {
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
const SPUInstrInfo &TII =
|
const SPUInstrInfo &TII =
|
||||||
*static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
|
*static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
@ -386,7 +386,7 @@ void MBlazeFrameLowering::emitPrologue(MachineFunction &MF) const {
|
|||||||
|
|
||||||
void MBlazeFrameLowering::emitEpilogue(MachineFunction &MF,
|
void MBlazeFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
MachineBasicBlock &MBB) const {
|
MachineBasicBlock &MBB) const {
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||||
const MBlazeInstrInfo &TII =
|
const MBlazeInstrInfo &TII =
|
||||||
|
@ -110,7 +110,7 @@ void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
|
|||||||
const MSP430InstrInfo &TII =
|
const MSP430InstrInfo &TII =
|
||||||
*static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo());
|
*static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
unsigned RetOpcode = MBBI->getOpcode();
|
unsigned RetOpcode = MBBI->getOpcode();
|
||||||
DebugLoc DL = MBBI->getDebugLoc();
|
DebugLoc DL = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
|
|||||||
|
|
||||||
void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
|
void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
MachineBasicBlock &MBB) const {
|
MachineBasicBlock &MBB) const {
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
||||||
const MipsInstrInfo &TII =
|
const MipsInstrInfo &TII =
|
||||||
|
@ -497,7 +497,8 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const {
|
|||||||
|
|
||||||
void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
|
void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
MachineBasicBlock &MBB) const {
|
MachineBasicBlock &MBB) const {
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
|
assert(MBBI != MBB.end() && "Returning block has no terminator");
|
||||||
const PPCInstrInfo &TII =
|
const PPCInstrInfo &TII =
|
||||||
*static_cast<const PPCInstrInfo*>(MF.getTarget().getInstrInfo());
|
*static_cast<const PPCInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
|
||||||
@ -676,29 +677,29 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
|
|||||||
.addReg(TmpReg);
|
.addReg(TmpReg);
|
||||||
}
|
}
|
||||||
} else if (RetOpcode == PPC::TCRETURNdi) {
|
} else if (RetOpcode == PPC::TCRETURNdi) {
|
||||||
MBBI = prior(MBB.end());
|
MBBI = MBB.getLastNonDebugInstr();
|
||||||
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB)).
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB)).
|
||||||
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset());
|
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset());
|
||||||
} else if (RetOpcode == PPC::TCRETURNri) {
|
} else if (RetOpcode == PPC::TCRETURNri) {
|
||||||
MBBI = prior(MBB.end());
|
MBBI = MBB.getLastNonDebugInstr();
|
||||||
assert(MBBI->getOperand(0).isReg() && "Expecting register operand.");
|
assert(MBBI->getOperand(0).isReg() && "Expecting register operand.");
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR));
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR));
|
||||||
} else if (RetOpcode == PPC::TCRETURNai) {
|
} else if (RetOpcode == PPC::TCRETURNai) {
|
||||||
MBBI = prior(MBB.end());
|
MBBI = MBB.getLastNonDebugInstr();
|
||||||
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA)).addImm(JumpTarget.getImm());
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA)).addImm(JumpTarget.getImm());
|
||||||
} else if (RetOpcode == PPC::TCRETURNdi8) {
|
} else if (RetOpcode == PPC::TCRETURNdi8) {
|
||||||
MBBI = prior(MBB.end());
|
MBBI = MBB.getLastNonDebugInstr();
|
||||||
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB8)).
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB8)).
|
||||||
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset());
|
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset());
|
||||||
} else if (RetOpcode == PPC::TCRETURNri8) {
|
} else if (RetOpcode == PPC::TCRETURNri8) {
|
||||||
MBBI = prior(MBB.end());
|
MBBI = MBB.getLastNonDebugInstr();
|
||||||
assert(MBBI->getOperand(0).isReg() && "Expecting register operand.");
|
assert(MBBI->getOperand(0).isReg() && "Expecting register operand.");
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR8));
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR8));
|
||||||
} else if (RetOpcode == PPC::TCRETURNai8) {
|
} else if (RetOpcode == PPC::TCRETURNai8) {
|
||||||
MBBI = prior(MBB.end());
|
MBBI = MBB.getLastNonDebugInstr();
|
||||||
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA8)).addImm(JumpTarget.getImm());
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA8)).addImm(JumpTarget.getImm());
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ void SparcFrameLowering::emitPrologue(MachineFunction &MF) const {
|
|||||||
|
|
||||||
void SparcFrameLowering::emitEpilogue(MachineFunction &MF,
|
void SparcFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
MachineBasicBlock &MBB) const {
|
MachineBasicBlock &MBB) const {
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
const SparcInstrInfo &TII =
|
const SparcInstrInfo &TII =
|
||||||
*static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo());
|
*static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
DebugLoc dl = MBBI->getDebugLoc();
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
@ -141,7 +141,7 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF) const {
|
|||||||
void SystemZFrameLowering::emitEpilogue(MachineFunction &MF,
|
void SystemZFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
MachineBasicBlock &MBB) const {
|
MachineBasicBlock &MBB) const {
|
||||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
const SystemZInstrInfo &TII =
|
const SystemZInstrInfo &TII =
|
||||||
*static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
|
*static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
SystemZMachineFunctionInfo *SystemZMFI =
|
SystemZMachineFunctionInfo *SystemZMFI =
|
||||||
|
@ -646,7 +646,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
|
|||||||
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
|
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
|
||||||
const X86RegisterInfo *RegInfo = TM.getRegisterInfo();
|
const X86RegisterInfo *RegInfo = TM.getRegisterInfo();
|
||||||
const X86InstrInfo &TII = *TM.getInstrInfo();
|
const X86InstrInfo &TII = *TM.getInstrInfo();
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
|
assert(MBBI != MBB.end() && "Returning block has no instructions");
|
||||||
unsigned RetOpcode = MBBI->getOpcode();
|
unsigned RetOpcode = MBBI->getOpcode();
|
||||||
DebugLoc DL = MBBI->getDebugLoc();
|
DebugLoc DL = MBBI->getDebugLoc();
|
||||||
bool Is64Bit = STI.is64Bit();
|
bool Is64Bit = STI.is64Bit();
|
||||||
@ -709,7 +710,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
|
|||||||
MachineBasicBlock::iterator PI = prior(MBBI);
|
MachineBasicBlock::iterator PI = prior(MBBI);
|
||||||
unsigned Opc = PI->getOpcode();
|
unsigned Opc = PI->getOpcode();
|
||||||
|
|
||||||
if (Opc != X86::POP32r && Opc != X86::POP64r &&
|
if (Opc != X86::POP32r && Opc != X86::POP64r && Opc != X86::DBG_VALUE &&
|
||||||
!PI->getDesc().isTerminator())
|
!PI->getDesc().isTerminator())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -756,7 +757,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
|
|||||||
|
|
||||||
// We're returning from function via eh_return.
|
// We're returning from function via eh_return.
|
||||||
if (RetOpcode == X86::EH_RETURN || RetOpcode == X86::EH_RETURN64) {
|
if (RetOpcode == X86::EH_RETURN || RetOpcode == X86::EH_RETURN64) {
|
||||||
MBBI = prior(MBB.end());
|
MBBI = MBB.getLastNonDebugInstr();
|
||||||
MachineOperand &DestAddr = MBBI->getOperand(0);
|
MachineOperand &DestAddr = MBBI->getOperand(0);
|
||||||
assert(DestAddr.isReg() && "Offset should be in register!");
|
assert(DestAddr.isReg() && "Offset should be in register!");
|
||||||
BuildMI(MBB, MBBI, DL,
|
BuildMI(MBB, MBBI, DL,
|
||||||
@ -768,7 +769,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
|
|||||||
RetOpcode == X86::TCRETURNmi64) {
|
RetOpcode == X86::TCRETURNmi64) {
|
||||||
bool isMem = RetOpcode == X86::TCRETURNmi || RetOpcode == X86::TCRETURNmi64;
|
bool isMem = RetOpcode == X86::TCRETURNmi || RetOpcode == X86::TCRETURNmi64;
|
||||||
// Tail call return: adjust the stack pointer and jump to callee.
|
// Tail call return: adjust the stack pointer and jump to callee.
|
||||||
MBBI = prior(MBB.end());
|
MBBI = MBB.getFirstTerminator();
|
||||||
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
||||||
MachineOperand &StackAdjust = MBBI->getOperand(isMem ? 5 : 1);
|
MachineOperand &StackAdjust = MBBI->getOperand(isMem ? 5 : 1);
|
||||||
assert(StackAdjust.isImm() && "Expecting immediate value.");
|
assert(StackAdjust.isImm() && "Expecting immediate value.");
|
||||||
@ -826,7 +827,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
|
|||||||
(X86FI->getTCReturnAddrDelta() < 0)) {
|
(X86FI->getTCReturnAddrDelta() < 0)) {
|
||||||
// Add the return addr area delta back since we are not tail calling.
|
// Add the return addr area delta back since we are not tail calling.
|
||||||
int delta = -1*X86FI->getTCReturnAddrDelta();
|
int delta = -1*X86FI->getTCReturnAddrDelta();
|
||||||
MBBI = prior(MBB.end());
|
MBBI = MBB.getLastNonDebugInstr();
|
||||||
|
|
||||||
// Check for possible merge with preceeding ADD instruction.
|
// Check for possible merge with preceeding ADD instruction.
|
||||||
delta += mergeSPUpdates(MBB, MBBI, StackPtr, true);
|
delta += mergeSPUpdates(MBB, MBBI, StackPtr, true);
|
||||||
|
Loading…
Reference in New Issue
Block a user