[llvm] 2c12c1e - [X86] Check if an invoked function clobbers fp or bp (#103446)

via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 14 12:59:41 PDT 2024


Author: weiguozhi
Date: 2024-08-14T12:59:37-07:00
New Revision: 2c12c1e755a1bf453b246027b450b3b8e30fb016

URL: https://github.com/llvm/llvm-project/commit/2c12c1e755a1bf453b246027b450b3b8e30fb016
DIFF: https://github.com/llvm/llvm-project/commit/2c12c1e755a1bf453b246027b450b3b8e30fb016.diff

LOG: [X86] Check if an invoked function clobbers fp or bp (#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.

Added: 
    llvm/test/CodeGen/X86/fp-clobbered-by-eh.ll

Modified: 
    llvm/lib/Target/X86/X86ISelLoweringCall.cpp
    llvm/lib/Target/X86/X86MachineFunctionInfo.h
    llvm/lib/Target/X86/X86RegisterInfo.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
index 1e609a84673a3..ce6b0f9c07dc8 100644
--- a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
+++ b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
@@ -2450,10 +2450,16 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   }();
   assert(Mask && "Missing call preserved mask for calling convention");
 
-  if (MachineOperand::clobbersPhysReg(Mask, RegInfo->getFrameRegister(MF)))
+  if (MachineOperand::clobbersPhysReg(Mask, RegInfo->getFramePtr())) {
     X86Info->setFPClobberedByCall(true);
-  if (MachineOperand::clobbersPhysReg(Mask, RegInfo->getBaseRegister()))
+    if (CLI.CB && isa<InvokeInst>(CLI.CB))
+      X86Info->setFPClobberedByInvoke(true);
+  }
+  if (MachineOperand::clobbersPhysReg(Mask, RegInfo->getBaseRegister())) {
     X86Info->setBPClobberedByCall(true);
+    if (CLI.CB && isa<InvokeInst>(CLI.CB))
+      X86Info->setBPClobberedByInvoke(true);
+  }
 
   // If this is an invoke in a 32-bit function using a funclet-based
   // personality, assume the function clobbers all registers. If an exception

diff  --git a/llvm/lib/Target/X86/X86MachineFunctionInfo.h b/llvm/lib/Target/X86/X86MachineFunctionInfo.h
index 13d57c2fa9dfb..24371369d4a45 100644
--- a/llvm/lib/Target/X86/X86MachineFunctionInfo.h
+++ b/llvm/lib/Target/X86/X86MachineFunctionInfo.h
@@ -173,6 +173,8 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
   // True if a function clobbers FP/BP according to its calling convention.
   bool FPClobberedByCall = false;
   bool BPClobberedByCall = false;
+  bool FPClobberedByInvoke = false;
+  bool BPClobberedByInvoke = false;
 
 private:
   /// ForwardedMustTailRegParms - A list of virtual and physical registers
@@ -338,6 +340,12 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
 
   bool getBPClobberedByCall() const { return BPClobberedByCall; }
   void setBPClobberedByCall(bool C) { BPClobberedByCall = C; }
+
+  bool getFPClobberedByInvoke() const { return FPClobberedByInvoke; }
+  void setFPClobberedByInvoke(bool C) { FPClobberedByInvoke = C; }
+
+  bool getBPClobberedByInvoke() const { return BPClobberedByInvoke; }
+  void setBPClobberedByInvoke(bool C) { BPClobberedByInvoke = C; }
 };
 
 } // End llvm namespace

diff  --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index 3376367cc76b0..638eb1c4f11e4 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -31,6 +31,7 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Type.h"
+#include "llvm/MC/MCContext.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Target/TargetMachine.h"
@@ -565,18 +566,22 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
 
   // Set the frame-pointer register and its aliases as reserved if needed.
   if (TFI->hasFP(MF)) {
+    if (MF.getInfo<X86MachineFunctionInfo>()->getFPClobberedByInvoke())
+      MF.getContext().reportError(
+          SMLoc(),
+          "Frame pointer clobbered by function invoke is not supported.");
+
     for (const MCPhysReg &SubReg : subregs_inclusive(X86::RBP))
       Reserved.set(SubReg);
   }
 
   // Set the base-pointer register and its aliases as reserved if needed.
   if (hasBasePointer(MF)) {
-    CallingConv::ID CC = MF.getFunction().getCallingConv();
-    const uint32_t *RegMask = getCallPreservedMask(MF, CC);
-    if (MachineOperand::clobbersPhysReg(RegMask, getBaseRegister()))
-      report_fatal_error(
-        "Stack realignment in presence of dynamic allocas is not supported with"
-        "this calling convention.");
+    if (MF.getInfo<X86MachineFunctionInfo>()->getBPClobberedByInvoke())
+      MF.getContext().reportError(SMLoc(),
+                                  "Stack realignment in presence of dynamic "
+                                  "allocas is not supported with "
+                                  "this calling convention.");
 
     Register BasePtr = getX86SubSuperRegister(getBaseRegister(), 64);
     for (const MCPhysReg &SubReg : subregs_inclusive(BasePtr))

diff  --git a/llvm/test/CodeGen/X86/fp-clobbered-by-eh.ll b/llvm/test/CodeGen/X86/fp-clobbered-by-eh.ll
new file mode 100644
index 0000000000000..03f227a590d5e
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fp-clobbered-by-eh.ll
@@ -0,0 +1,27 @@
+; RUN: not llc -mtriple=x86_64-unknown-unknown -stackrealign -verify-machineinstrs %s -o - 2>&1 | FileCheck %s
+
+declare ghccc void @may_throw_or_crash()
+declare i32 @_except_handler3(...)
+
+define internal i64 @catchall_filt() {
+  ret i64 1
+}
+
+; If the invoked function clobbers frame pointer and/or base pointer according
+; to its calling convention, we can't handle it currently, so reports an error
+; message.
+
+; CHECK: <unknown>:0: error: Frame pointer clobbered by function invoke is not supported
+; CHECK: <unknown>:0: error: Stack realignment in presence of dynamic allocas is not supported with this calling convention
+define void @use_except_handler3() personality ptr @_except_handler3 {
+entry:
+  invoke ghccc void @may_throw_or_crash()
+      to label %cont unwind label %lpad
+cont:
+  ret void
+lpad:
+  %cs = catchswitch within none [label %catch] unwind to caller
+catch:
+  %p = catchpad within %cs [ptr @catchall_filt]
+  catchret from %p to label %cont
+}


        


More information about the llvm-commits mailing list