Skip to content

Commit 2c12c1e

Browse files
authored
[X86] Check if an invoked function clobbers fp or bp (llvm#103446)
In most cases when an instruction or function call clobbers fp and/or bp register, we can fix it by save/restore the clobbered register. But we still can't handle it when an invoked function clobbers fp and/or bp according to its calling convention. This patch detects this case and reports error instead of silently generating wrong code.
1 parent 00ab8a6 commit 2c12c1e

File tree

4 files changed

+54
-8
lines changed

4 files changed

+54
-8
lines changed

llvm/lib/Target/X86/X86ISelLoweringCall.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2450,10 +2450,16 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
24502450
}();
24512451
assert(Mask && "Missing call preserved mask for calling convention");
24522452

2453-
if (MachineOperand::clobbersPhysReg(Mask, RegInfo->getFrameRegister(MF)))
2453+
if (MachineOperand::clobbersPhysReg(Mask, RegInfo->getFramePtr())) {
24542454
X86Info->setFPClobberedByCall(true);
2455-
if (MachineOperand::clobbersPhysReg(Mask, RegInfo->getBaseRegister()))
2455+
if (CLI.CB && isa<InvokeInst>(CLI.CB))
2456+
X86Info->setFPClobberedByInvoke(true);
2457+
}
2458+
if (MachineOperand::clobbersPhysReg(Mask, RegInfo->getBaseRegister())) {
24562459
X86Info->setBPClobberedByCall(true);
2460+
if (CLI.CB && isa<InvokeInst>(CLI.CB))
2461+
X86Info->setBPClobberedByInvoke(true);
2462+
}
24572463

24582464
// If this is an invoke in a 32-bit function using a funclet-based
24592465
// personality, assume the function clobbers all registers. If an exception

llvm/lib/Target/X86/X86MachineFunctionInfo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
173173
// True if a function clobbers FP/BP according to its calling convention.
174174
bool FPClobberedByCall = false;
175175
bool BPClobberedByCall = false;
176+
bool FPClobberedByInvoke = false;
177+
bool BPClobberedByInvoke = false;
176178

177179
private:
178180
/// ForwardedMustTailRegParms - A list of virtual and physical registers
@@ -338,6 +340,12 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
338340

339341
bool getBPClobberedByCall() const { return BPClobberedByCall; }
340342
void setBPClobberedByCall(bool C) { BPClobberedByCall = C; }
343+
344+
bool getFPClobberedByInvoke() const { return FPClobberedByInvoke; }
345+
void setFPClobberedByInvoke(bool C) { FPClobberedByInvoke = C; }
346+
347+
bool getBPClobberedByInvoke() const { return BPClobberedByInvoke; }
348+
void setBPClobberedByInvoke(bool C) { BPClobberedByInvoke = C; }
341349
};
342350

343351
} // End llvm namespace

llvm/lib/Target/X86/X86RegisterInfo.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "llvm/IR/Constants.h"
3232
#include "llvm/IR/Function.h"
3333
#include "llvm/IR/Type.h"
34+
#include "llvm/MC/MCContext.h"
3435
#include "llvm/Support/CommandLine.h"
3536
#include "llvm/Support/ErrorHandling.h"
3637
#include "llvm/Target/TargetMachine.h"
@@ -565,18 +566,22 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
565566

566567
// Set the frame-pointer register and its aliases as reserved if needed.
567568
if (TFI->hasFP(MF)) {
569+
if (MF.getInfo<X86MachineFunctionInfo>()->getFPClobberedByInvoke())
570+
MF.getContext().reportError(
571+
SMLoc(),
572+
"Frame pointer clobbered by function invoke is not supported.");
573+
568574
for (const MCPhysReg &SubReg : subregs_inclusive(X86::RBP))
569575
Reserved.set(SubReg);
570576
}
571577

572578
// Set the base-pointer register and its aliases as reserved if needed.
573579
if (hasBasePointer(MF)) {
574-
CallingConv::ID CC = MF.getFunction().getCallingConv();
575-
const uint32_t *RegMask = getCallPreservedMask(MF, CC);
576-
if (MachineOperand::clobbersPhysReg(RegMask, getBaseRegister()))
577-
report_fatal_error(
578-
"Stack realignment in presence of dynamic allocas is not supported with"
579-
"this calling convention.");
580+
if (MF.getInfo<X86MachineFunctionInfo>()->getBPClobberedByInvoke())
581+
MF.getContext().reportError(SMLoc(),
582+
"Stack realignment in presence of dynamic "
583+
"allocas is not supported with "
584+
"this calling convention.");
580585

581586
Register BasePtr = getX86SubSuperRegister(getBaseRegister(), 64);
582587
for (const MCPhysReg &SubReg : subregs_inclusive(BasePtr))
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
; RUN: not llc -mtriple=x86_64-unknown-unknown -stackrealign -verify-machineinstrs %s -o - 2>&1 | FileCheck %s
2+
3+
declare ghccc void @may_throw_or_crash()
4+
declare i32 @_except_handler3(...)
5+
6+
define internal i64 @catchall_filt() {
7+
ret i64 1
8+
}
9+
10+
; If the invoked function clobbers frame pointer and/or base pointer according
11+
; to its calling convention, we can't handle it currently, so reports an error
12+
; message.
13+
14+
; CHECK: <unknown>:0: error: Frame pointer clobbered by function invoke is not supported
15+
; CHECK: <unknown>:0: error: Stack realignment in presence of dynamic allocas is not supported with this calling convention
16+
define void @use_except_handler3() personality ptr @_except_handler3 {
17+
entry:
18+
invoke ghccc void @may_throw_or_crash()
19+
to label %cont unwind label %lpad
20+
cont:
21+
ret void
22+
lpad:
23+
%cs = catchswitch within none [label %catch] unwind to caller
24+
catch:
25+
%p = catchpad within %cs [ptr @catchall_filt]
26+
catchret from %p to label %cont
27+
}

0 commit comments

Comments
 (0)