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@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@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; };