forked from OSchip/llvm-project
[PowerPC] Emit warning when SP is clobbered by asm
This patch emits a warning when the stack pointer register (`R1`) is found in the clobber list of an inline asm statement. Clobbering the stack pointer is not supported. Reviewed By: #powerpc, nemanjai Differential Revision: https://reviews.llvm.org/D112073
This commit is contained in:
parent
997e128e2a
commit
6a028296fe
|
@ -734,23 +734,28 @@ ArrayRef<const char *> PPCTargetInfo::getGCCRegNames() const {
|
|||
const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = {
|
||||
// While some of these aliases do map to different registers
|
||||
// they still share the same register name.
|
||||
{{"0"}, "r0"}, {{"1"}, "r1"}, {{"2"}, "r2"}, {{"3"}, "r3"},
|
||||
{{"4"}, "r4"}, {{"5"}, "r5"}, {{"6"}, "r6"}, {{"7"}, "r7"},
|
||||
{{"8"}, "r8"}, {{"9"}, "r9"}, {{"10"}, "r10"}, {{"11"}, "r11"},
|
||||
{{"12"}, "r12"}, {{"13"}, "r13"}, {{"14"}, "r14"}, {{"15"}, "r15"},
|
||||
{{"16"}, "r16"}, {{"17"}, "r17"}, {{"18"}, "r18"}, {{"19"}, "r19"},
|
||||
{{"20"}, "r20"}, {{"21"}, "r21"}, {{"22"}, "r22"}, {{"23"}, "r23"},
|
||||
{{"24"}, "r24"}, {{"25"}, "r25"}, {{"26"}, "r26"}, {{"27"}, "r27"},
|
||||
{{"28"}, "r28"}, {{"29"}, "r29"}, {{"30"}, "r30"}, {{"31"}, "r31"},
|
||||
{{"fr0"}, "f0"}, {{"fr1"}, "f1"}, {{"fr2"}, "f2"}, {{"fr3"}, "f3"},
|
||||
{{"fr4"}, "f4"}, {{"fr5"}, "f5"}, {{"fr6"}, "f6"}, {{"fr7"}, "f7"},
|
||||
{{"fr8"}, "f8"}, {{"fr9"}, "f9"}, {{"fr10"}, "f10"}, {{"fr11"}, "f11"},
|
||||
{{"fr12"}, "f12"}, {{"fr13"}, "f13"}, {{"fr14"}, "f14"}, {{"fr15"}, "f15"},
|
||||
{{"fr16"}, "f16"}, {{"fr17"}, "f17"}, {{"fr18"}, "f18"}, {{"fr19"}, "f19"},
|
||||
{{"fr20"}, "f20"}, {{"fr21"}, "f21"}, {{"fr22"}, "f22"}, {{"fr23"}, "f23"},
|
||||
{{"fr24"}, "f24"}, {{"fr25"}, "f25"}, {{"fr26"}, "f26"}, {{"fr27"}, "f27"},
|
||||
{{"fr28"}, "f28"}, {{"fr29"}, "f29"}, {{"fr30"}, "f30"}, {{"fr31"}, "f31"},
|
||||
{{"cc"}, "cr0"},
|
||||
{{"0"}, "r0"}, {{"1", "sp"}, "r1"}, {{"2"}, "r2"},
|
||||
{{"3"}, "r3"}, {{"4"}, "r4"}, {{"5"}, "r5"},
|
||||
{{"6"}, "r6"}, {{"7"}, "r7"}, {{"8"}, "r8"},
|
||||
{{"9"}, "r9"}, {{"10"}, "r10"}, {{"11"}, "r11"},
|
||||
{{"12"}, "r12"}, {{"13"}, "r13"}, {{"14"}, "r14"},
|
||||
{{"15"}, "r15"}, {{"16"}, "r16"}, {{"17"}, "r17"},
|
||||
{{"18"}, "r18"}, {{"19"}, "r19"}, {{"20"}, "r20"},
|
||||
{{"21"}, "r21"}, {{"22"}, "r22"}, {{"23"}, "r23"},
|
||||
{{"24"}, "r24"}, {{"25"}, "r25"}, {{"26"}, "r26"},
|
||||
{{"27"}, "r27"}, {{"28"}, "r28"}, {{"29"}, "r29"},
|
||||
{{"30"}, "r30"}, {{"31"}, "r31"}, {{"fr0"}, "f0"},
|
||||
{{"fr1"}, "f1"}, {{"fr2"}, "f2"}, {{"fr3"}, "f3"},
|
||||
{{"fr4"}, "f4"}, {{"fr5"}, "f5"}, {{"fr6"}, "f6"},
|
||||
{{"fr7"}, "f7"}, {{"fr8"}, "f8"}, {{"fr9"}, "f9"},
|
||||
{{"fr10"}, "f10"}, {{"fr11"}, "f11"}, {{"fr12"}, "f12"},
|
||||
{{"fr13"}, "f13"}, {{"fr14"}, "f14"}, {{"fr15"}, "f15"},
|
||||
{{"fr16"}, "f16"}, {{"fr17"}, "f17"}, {{"fr18"}, "f18"},
|
||||
{{"fr19"}, "f19"}, {{"fr20"}, "f20"}, {{"fr21"}, "f21"},
|
||||
{{"fr22"}, "f22"}, {{"fr23"}, "f23"}, {{"fr24"}, "f24"},
|
||||
{{"fr25"}, "f25"}, {{"fr26"}, "f26"}, {{"fr27"}, "f27"},
|
||||
{{"fr28"}, "f28"}, {{"fr29"}, "f29"}, {{"fr30"}, "f30"},
|
||||
{{"fr31"}, "f31"}, {{"cc"}, "cr0"},
|
||||
};
|
||||
|
||||
ArrayRef<TargetInfo::GCCRegAlias> PPCTargetInfo::getGCCRegAliases() const {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/// This test checks that the warning includes the location in the C source
|
||||
/// file that contains the inline asm. Although this warning is emitted in llvm
|
||||
/// it cannot be tested from IR as it does not have that location information at
|
||||
/// that stage.
|
||||
|
||||
// REQUIRES: powerpc-registered-target
|
||||
|
||||
// RUN: %clang --target=powerpc-unknown-unknown -mcpu=pwr7 \
|
||||
// RUN: -c %s -o /dev/null 2>&1 | FileCheck %s
|
||||
// RUN: %clang --target=powerpc64-unknown-unknown -mcpu=pwr7 \
|
||||
// RUN: -c %s -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
void test_r1_clobber() {
|
||||
__asm__("nop":::"r1");
|
||||
}
|
||||
|
||||
// CHECK: ppc-inline-asm-clobber-warning.c:14:11: warning: inline asm clobber list contains reserved registers: R1 [-Winline-asm]
|
||||
// CHECK-NEXT: __asm__("nop":::"r1");
|
||||
// CHECK-NEXT: ^
|
||||
// CHECK-NEXT: ppc-inline-asm-clobber-warning.c:14:11: note: Reserved registers on the clobber list may not be preserved across the asm statement, and clobbering them may lead to undefined behaviour.
|
||||
|
||||
void test_1_clobber() {
|
||||
__asm__("nop":::"1");
|
||||
}
|
||||
|
||||
// CHECK: ppc-inline-asm-clobber-warning.c:23:11: warning: inline asm clobber list contains reserved registers: R1 [-Winline-asm]
|
||||
// CHECK-NEXT: __asm__("nop":::"1");
|
||||
// CHECK-NEXT: ^
|
||||
// CHECK-NEXT: ppc-inline-asm-clobber-warning.c:23:11: note: Reserved registers on the clobber list may not be preserved across the asm statement, and clobbering them may lead to undefined behaviour.
|
||||
|
||||
void test_sp_clobber() {
|
||||
__asm__("nop":::"sp");
|
||||
}
|
||||
|
||||
// CHECK: ppc-inline-asm-clobber-warning.c:32:11: warning: inline asm clobber list contains reserved registers: R1 [-Winline-asm]
|
||||
// CHECK-NEXT: __asm__("nop":::"sp");
|
||||
// CHECK-NEXT: ^
|
||||
// CHECK-NEXT: ppc-inline-asm-clobber-warning.c:32:11: note: Reserved registers on the clobber list may not be preserved across the asm statement, and clobbering them may lead to undefined behaviour.
|
|
@ -390,6 +390,18 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
|||
return Reserved;
|
||||
}
|
||||
|
||||
bool PPCRegisterInfo::isAsmClobberable(const MachineFunction &MF,
|
||||
MCRegister PhysReg) const {
|
||||
// We cannot use getReservedRegs() to find the registers that are not asm
|
||||
// clobberable because there are some reserved registers which can be
|
||||
// clobbered by inline asm. For example, when LR is clobbered, the register is
|
||||
// saved and restored. We will hardcode the registers that are not asm
|
||||
// cloberable in this function.
|
||||
|
||||
// The stack pointer (R1/X1) is not clobberable by inline asm
|
||||
return PhysReg != PPC::R1 && PhysReg != PPC::X1;
|
||||
}
|
||||
|
||||
bool PPCRegisterInfo::requiresFrameIndexScavenging(const MachineFunction &MF) const {
|
||||
const PPCSubtarget &Subtarget = MF.getSubtarget<PPCSubtarget>();
|
||||
const PPCInstrInfo *InstrInfo = Subtarget.getInstrInfo();
|
||||
|
|
|
@ -91,6 +91,8 @@ public:
|
|||
void adjustStackMapLiveOutMask(uint32_t *Mask) const override;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const override;
|
||||
bool isAsmClobberable(const MachineFunction &MF,
|
||||
MCRegister PhysReg) const override;
|
||||
bool isCallerPreservedPhysReg(MCRegister PhysReg,
|
||||
const MachineFunction &MF) const override;
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
; RUN: llc < %s -verify-machineinstrs -mtriple=powerpc-unknown-unkown \
|
||||
; RUN: -mcpu=pwr7 2>&1 | FileCheck %s
|
||||
; RUN: llc < %s -verify-machineinstrs -mtriple=powerpc64-unknown-unkown \
|
||||
; RUN: -mcpu=pwr7 2>&1 | FileCheck %s
|
||||
|
||||
define void @test_r1_clobber() {
|
||||
entry:
|
||||
call void asm sideeffect "nop", "~{r1}"()
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: warning: inline asm clobber list contains reserved registers: R1
|
||||
; CHECK-NEXT: note: Reserved registers on the clobber list may not be preserved across the asm statement, and clobbering them may lead to undefined behaviour.
|
||||
|
||||
define void @test_x1_clobber() {
|
||||
entry:
|
||||
call void asm sideeffect "nop", "~{x1}"()
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: warning: inline asm clobber list contains reserved registers: X1
|
||||
; CHECK-NEXT: note: Reserved registers on the clobber list may not be preserved across the asm statement, and clobbering them may lead to undefined behaviour.
|
Loading…
Reference in New Issue