]> granicus.if.org Git - clang/commitdiff
Fix for #31362 - ms_abi is implemented incorrectly for values >=16 bytes.
authorAlexander Ivchenko <alexander.ivchenko@intel.com>
Thu, 8 Feb 2018 11:15:21 +0000 (11:15 +0000)
committerAlexander Ivchenko <alexander.ivchenko@intel.com>
Thu, 8 Feb 2018 11:15:21 +0000 (11:15 +0000)
Summary:
This patch is a fix for following issue:
https://bugs.llvm.org/show_bug.cgi?id=31362 The problem was caused by front end
lowering C calling conventions without taking into account calling conventions
enforced by attribute. In this case win64cc was no correctly lowered on targets
other than Windows.

Reviewed By: rnk (Reid Kleckner)

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

Author: belickim <mateusz.belicki@intel.com>

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@324594 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/TargetInfo.cpp
test/CodeGen/ms_abi.c

index f1f24512e8a4dff2224bf7173b38d15f47a92d33..4ca421bb863fe294354dd9371927b916f2b35780 100644 (file)
@@ -3529,7 +3529,17 @@ ABIArgInfo X86_64ABIInfo::classifyRegCallStructType(QualType Ty,
 
 void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
 
-  bool IsRegCall = FI.getCallingConvention() == llvm::CallingConv::X86_RegCall;
+  const unsigned CallingConv = FI.getCallingConvention();
+  // It is possible to force Win64 calling convention on any x86_64 target by
+  // using __attribute__((ms_abi)). In such case to correctly emit Win64
+  // compatible code delegate this call to WinX86_64ABIInfo::computeInfo.
+  if (CallingConv == llvm::CallingConv::Win64) {
+    WinX86_64ABIInfo Win64ABIInfo(CGT);
+    Win64ABIInfo.computeInfo(FI);
+    return;
+  }
+
+  bool IsRegCall = CallingConv == llvm::CallingConv::X86_RegCall;
 
   // Keep track of the number of assigned registers.
   unsigned FreeIntRegs = IsRegCall ? 11 : 6;
index 407087e409166e856d17a1fd2642e8252ea6bfa0..7486166c78d47997c4ef288a871e1a4bfe89e9ae 100644 (file)
@@ -146,3 +146,16 @@ void __attribute__((sysv_abi)) f6(__builtin_ms_va_list ap) {
   // WIN64: %[[AP_VAL:.*]] = load i8*, i8** %[[AP]]
   // WIN64-NEXT: store i8* %[[AP_VAL]], i8** %[[AP2:.*]]
 }
+
+// This test checks if structs are passed according to Win64 calling convention
+// when it's enforced by __attribute((ms_abi)).
+struct i128 {
+  unsigned long long a;
+  unsigned long long b;
+};
+
+__attribute__((ms_abi)) struct i128 f7(struct i128 a) {
+  // WIN64: define void @f7(%struct.i128* noalias sret %agg.result, %struct.i128* %a)
+  // FREEBSD: define win64cc void @f7(%struct.i128* noalias sret %agg.result, %struct.i128* %a)
+  return a;
+}