Skip to content

Commit

Permalink
[PowerPC] Emit warning when SP is clobbered by asm
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Quinn Pham authored and Quinn Pham committed Jan 24, 2022
1 parent 997e128 commit 6a02829
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 17 deletions.
39 changes: 22 additions & 17 deletions clang/lib/Basic/Targets/PPC.cpp
Expand Up @@ -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 {
Expand Down
38 changes: 38 additions & 0 deletions clang/test/Misc/ppc-inline-asm-clobber-warning.c
@@ -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.
12 changes: 12 additions & 0 deletions llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
Expand Up @@ -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();
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/PowerPC/PPCRegisterInfo.h
Expand Up @@ -91,6 +91,8 @@ class PPCRegisterInfo : public PPCGenRegisterInfo {
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;

Expand Down
22 changes: 22 additions & 0 deletions llvm/test/CodeGen/PowerPC/inline-asm-clobber-warning.ll
@@ -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.

0 comments on commit 6a02829

Please sign in to comment.