[clang] 46bb4b9 - [X86][fastcall][vectorcall] Move capability check before free register update

Phoebe Wang via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 19 18:37:02 PDT 2022


Author: Phoebe Wang
Date: 2022-09-20T09:18:23+08:00
New Revision: 46bb4b99ae9f7b043c58d0b17df031bd02ccfd01

URL: https://github.com/llvm/llvm-project/commit/46bb4b99ae9f7b043c58d0b17df031bd02ccfd01
DIFF: https://github.com/llvm/llvm-project/commit/46bb4b99ae9f7b043c58d0b17df031bd02ccfd01.diff

LOG: [X86][fastcall][vectorcall] Move capability check before free register update

When passing arguments with `__fastcall` or `__vectorcall` in 32-bit MSVC, the following arguments have chance to be passed by register if the current one failed. `__regcall` from ICC is on the contrary: https://godbolt.org/z/4MPbzhaMG
All the three calling conversions are not supported in GCC.

Fixes: #57737

Reviewed By: rnk

Differential Revision: https://reviews.llvm.org/D133920

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/CodeGen/TargetInfo.cpp
    clang/test/CodeGen/mangle-windows.c
    clang/test/CodeGen/regcall.c
    clang/test/CodeGen/stdcall-fastcall.c
    clang/test/CodeGen/vectorcall.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 96b0c7e363052..1744a8b6f84bf 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -358,6 +358,7 @@ RISC-V Support in Clang
 X86 Support in Clang
 --------------------
 - Support ``-mindirect-branch-cs-prefix`` for call and jmp to indirect thunk.
+- Fix 32-bit ``__fastcall`` and ``__vectorcall`` ABI mismatch with MSVC.
 
 DWARF Support in Clang
 ----------------------

diff  --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 2f9adb83ffa2a..a16c3ad6ffa89 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -1771,23 +1771,22 @@ bool X86_32ABIInfo::shouldAggregateUseDirect(QualType Ty, CCState &State,
 }
 
 bool X86_32ABIInfo::shouldPrimitiveUseInReg(QualType Ty, CCState &State) const {
-  if (!updateFreeRegs(Ty, State))
-    return false;
+  bool IsPtrOrInt = (getContext().getTypeSize(Ty) <= 32) &&
+                    (Ty->isIntegralOrEnumerationType() || Ty->isPointerType() ||
+                     Ty->isReferenceType());
 
-  if (IsMCUABI)
+  if (!IsPtrOrInt && (State.CC == llvm::CallingConv::X86_FastCall ||
+                      State.CC == llvm::CallingConv::X86_VectorCall))
     return false;
 
-  if (State.CC == llvm::CallingConv::X86_FastCall ||
-      State.CC == llvm::CallingConv::X86_VectorCall ||
-      State.CC == llvm::CallingConv::X86_RegCall) {
-    if (getContext().getTypeSize(Ty) > 32)
-      return false;
+  if (!updateFreeRegs(Ty, State))
+    return false;
 
-    return (Ty->isIntegralOrEnumerationType() || Ty->isPointerType() ||
-        Ty->isReferenceType());
-  }
+  if (!IsPtrOrInt && State.CC == llvm::CallingConv::X86_RegCall)
+    return false;
 
-  return true;
+  // Return true to apply inreg to all legal parameters except for MCU targets.
+  return !IsMCUABI;
 }
 
 void X86_32ABIInfo::runVectorCallFirstPass(CGFunctionInfo &FI, CCState &State) const {

diff  --git a/clang/test/CodeGen/mangle-windows.c b/clang/test/CodeGen/mangle-windows.c
index 1fcac01fb0552..046b1e8815a8a 100644
--- a/clang/test/CodeGen/mangle-windows.c
+++ b/clang/test/CodeGen/mangle-windows.c
@@ -47,7 +47,7 @@ void __fastcall f8(long long a) {}
 // X64: define dso_local void @f8(
 
 void __fastcall f9(long long a, char b, char c, short d) {}
-// CHECK: define dso_local x86_fastcallcc void @"\01 at f9@20"(i64 noundef %a, i8 noundef signext %b, i8 noundef signext %c, i16 noundef signext %d)
+// CHECK: define dso_local x86_fastcallcc void @"\01 at f9@20"(i64 noundef %a, i8 inreg noundef signext %b, i8 inreg noundef signext %c, i16 noundef signext %d)
 // X64: define dso_local void @f9(
 
 void f12(void) {}
@@ -81,3 +81,6 @@ void __vectorcall v5(long long a) {}
 void __vectorcall v6(char a, char b) {}
 // CHECK: define dso_local x86_vectorcallcc void @"\01v6@@8"(
 // X64: define dso_local x86_vectorcallcc void @"\01v6@@16"(
+
+void __vectorcall v7(long long a, char b, char c, short d) {}
+// CHECK: define dso_local x86_vectorcallcc void @"\01v7@@20"(i64 noundef %a, i8 inreg noundef signext %b, i8 inreg noundef signext %c, i16 noundef signext %d)

diff  --git a/clang/test/CodeGen/regcall.c b/clang/test/CodeGen/regcall.c
index a20671f606f47..d2c7344132b3e 100644
--- a/clang/test/CodeGen/regcall.c
+++ b/clang/test/CodeGen/regcall.c
@@ -31,6 +31,10 @@ void __regcall v4(int a, struct Large b, int c) {}
 // Win64: define dso_local x86_regcallcc void @__regcall3__v4(i32 noundef %a, %struct.Large* noundef %b, i32 noundef %c)
 // Lin64: define dso_local x86_regcallcc void @__regcall3__v4(i32 noundef %a, [5 x i32] %b.coerce, i32 noundef %c)
 
+void __regcall v5(long long a, int b, int c) {}
+// X86: define dso_local x86_regcallcc void @__regcall3__v5(i64 noundef %a, i32 inreg noundef %b, i32 inreg noundef %c)
+// X64: define dso_local x86_regcallcc void @__regcall3__v5(i64 noundef %a, i32 noundef %b, i32 noundef %c)
+
 struct HFA2 { double x, y; };
 struct HFA4 { double w, x, y, z; };
 struct HFA5 { double v, w, x, y, z; };

diff  --git a/clang/test/CodeGen/stdcall-fastcall.c b/clang/test/CodeGen/stdcall-fastcall.c
index 43337f31e3d66..a66bd917342b7 100644
--- a/clang/test/CodeGen/stdcall-fastcall.c
+++ b/clang/test/CodeGen/stdcall-fastcall.c
@@ -144,3 +144,10 @@ void bar12(struct S3 y, int x) {
   // CHECK: call x86_fastcallcc void @foo12(float %{{.*}}, i32 inreg noundef %
   foo12(y, x);
 }
+
+void __attribute__((fastcall)) foo13(long long a, int b, int c);
+void bar13(long long a, int b, int c) {
+  // CHECK-LABEL: define{{.*}} void @bar13
+  // CHECK: call x86_fastcallcc void @foo13(i64 noundef %{{.*}}, i32 inreg noundef %{{.*}}, i32 inreg noundef %
+  foo13(a, b, c);
+}

diff  --git a/clang/test/CodeGen/vectorcall.c b/clang/test/CodeGen/vectorcall.c
index 2296015f70de4..b946ebf35bf73 100644
--- a/clang/test/CodeGen/vectorcall.c
+++ b/clang/test/CodeGen/vectorcall.c
@@ -19,6 +19,10 @@ void __vectorcall v4(int a, struct Large b, int c) {}
 // X86: define dso_local x86_vectorcallcc void @"\01v4@@28"(i32 inreg noundef %a, %struct.Large* noundef byval(%struct.Large) align 4 %b, i32 inreg noundef %c)
 // X64: define dso_local x86_vectorcallcc void @"\01v4@@40"(i32 noundef %a, %struct.Large* noundef %b, i32 noundef %c)
 
+void __vectorcall v5(long long a, int b, int c) {}
+// X86: define dso_local x86_vectorcallcc void @"\01v5@@16"(i64 noundef %a, i32 inreg noundef %b, i32 inreg noundef %c)
+// X64: define dso_local x86_vectorcallcc void @"\01v5@@24"(i64 noundef %a, i32 noundef %b, i32 noundef %c)
+
 struct HFA2 { double x, y; };
 struct HFA4 { double w, x, y, z; };
 struct HFA5 { double v, w, x, y, z; };


        


More information about the cfe-commits mailing list