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[] = {
|
const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = {
|
||||||
// While some of these aliases do map to different registers
|
// While some of these aliases do map to different registers
|
||||||
// they still share the same register name.
|
// they still share the same register name.
|
||||||
{{"0"}, "r0"}, {{"1"}, "r1"}, {{"2"}, "r2"}, {{"3"}, "r3"},
|
{{"0"}, "r0"}, {{"1", "sp"}, "r1"}, {{"2"}, "r2"},
|
||||||
{{"4"}, "r4"}, {{"5"}, "r5"}, {{"6"}, "r6"}, {{"7"}, "r7"},
|
{{"3"}, "r3"}, {{"4"}, "r4"}, {{"5"}, "r5"},
|
||||||
{{"8"}, "r8"}, {{"9"}, "r9"}, {{"10"}, "r10"}, {{"11"}, "r11"},
|
{{"6"}, "r6"}, {{"7"}, "r7"}, {{"8"}, "r8"},
|
||||||
{{"12"}, "r12"}, {{"13"}, "r13"}, {{"14"}, "r14"}, {{"15"}, "r15"},
|
{{"9"}, "r9"}, {{"10"}, "r10"}, {{"11"}, "r11"},
|
||||||
{{"16"}, "r16"}, {{"17"}, "r17"}, {{"18"}, "r18"}, {{"19"}, "r19"},
|
{{"12"}, "r12"}, {{"13"}, "r13"}, {{"14"}, "r14"},
|
||||||
{{"20"}, "r20"}, {{"21"}, "r21"}, {{"22"}, "r22"}, {{"23"}, "r23"},
|
{{"15"}, "r15"}, {{"16"}, "r16"}, {{"17"}, "r17"},
|
||||||
{{"24"}, "r24"}, {{"25"}, "r25"}, {{"26"}, "r26"}, {{"27"}, "r27"},
|
{{"18"}, "r18"}, {{"19"}, "r19"}, {{"20"}, "r20"},
|
||||||
{{"28"}, "r28"}, {{"29"}, "r29"}, {{"30"}, "r30"}, {{"31"}, "r31"},
|
{{"21"}, "r21"}, {{"22"}, "r22"}, {{"23"}, "r23"},
|
||||||
{{"fr0"}, "f0"}, {{"fr1"}, "f1"}, {{"fr2"}, "f2"}, {{"fr3"}, "f3"},
|
{{"24"}, "r24"}, {{"25"}, "r25"}, {{"26"}, "r26"},
|
||||||
{{"fr4"}, "f4"}, {{"fr5"}, "f5"}, {{"fr6"}, "f6"}, {{"fr7"}, "f7"},
|
{{"27"}, "r27"}, {{"28"}, "r28"}, {{"29"}, "r29"},
|
||||||
{{"fr8"}, "f8"}, {{"fr9"}, "f9"}, {{"fr10"}, "f10"}, {{"fr11"}, "f11"},
|
{{"30"}, "r30"}, {{"31"}, "r31"}, {{"fr0"}, "f0"},
|
||||||
{{"fr12"}, "f12"}, {{"fr13"}, "f13"}, {{"fr14"}, "f14"}, {{"fr15"}, "f15"},
|
{{"fr1"}, "f1"}, {{"fr2"}, "f2"}, {{"fr3"}, "f3"},
|
||||||
{{"fr16"}, "f16"}, {{"fr17"}, "f17"}, {{"fr18"}, "f18"}, {{"fr19"}, "f19"},
|
{{"fr4"}, "f4"}, {{"fr5"}, "f5"}, {{"fr6"}, "f6"},
|
||||||
{{"fr20"}, "f20"}, {{"fr21"}, "f21"}, {{"fr22"}, "f22"}, {{"fr23"}, "f23"},
|
{{"fr7"}, "f7"}, {{"fr8"}, "f8"}, {{"fr9"}, "f9"},
|
||||||
{{"fr24"}, "f24"}, {{"fr25"}, "f25"}, {{"fr26"}, "f26"}, {{"fr27"}, "f27"},
|
{{"fr10"}, "f10"}, {{"fr11"}, "f11"}, {{"fr12"}, "f12"},
|
||||||
{{"fr28"}, "f28"}, {{"fr29"}, "f29"}, {{"fr30"}, "f30"}, {{"fr31"}, "f31"},
|
{{"fr13"}, "f13"}, {{"fr14"}, "f14"}, {{"fr15"}, "f15"},
|
||||||
{{"cc"}, "cr0"},
|
{{"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 {
|
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;
|
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 {
|
bool PPCRegisterInfo::requiresFrameIndexScavenging(const MachineFunction &MF) const {
|
||||||
const PPCSubtarget &Subtarget = MF.getSubtarget<PPCSubtarget>();
|
const PPCSubtarget &Subtarget = MF.getSubtarget<PPCSubtarget>();
|
||||||
const PPCInstrInfo *InstrInfo = Subtarget.getInstrInfo();
|
const PPCInstrInfo *InstrInfo = Subtarget.getInstrInfo();
|
||||||
|
|
|
@ -91,6 +91,8 @@ public:
|
||||||
void adjustStackMapLiveOutMask(uint32_t *Mask) const override;
|
void adjustStackMapLiveOutMask(uint32_t *Mask) const override;
|
||||||
|
|
||||||
BitVector getReservedRegs(const MachineFunction &MF) const override;
|
BitVector getReservedRegs(const MachineFunction &MF) const override;
|
||||||
|
bool isAsmClobberable(const MachineFunction &MF,
|
||||||
|
MCRegister PhysReg) const override;
|
||||||
bool isCallerPreservedPhysReg(MCRegister PhysReg,
|
bool isCallerPreservedPhysReg(MCRegister PhysReg,
|
||||||
const MachineFunction &MF) const override;
|
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