summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2018-02-09 09:01:30 +0000
committerHans Wennborg <hans@hanshq.net>2018-02-09 09:01:30 +0000
commit1d5b6bd0b8ee0cad2a92f45245b5fbbf23c48ef3 (patch)
tree044c70cda4d63ec775dfff0a6ef66b597fb79154
parent9524f2ccfe02886a6c211a475c66ebf82f1fbcad (diff)
Merging r324594:
------------------------------------------------------------------------ r324594 | aivchenk | 2018-02-08 12:15:21 +0100 (Thu, 08 Feb 2018) | 17 lines Fix for #31362 - ms_abi is implemented incorrectly for values >=16 bytes. 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/branches/release_60@324718 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/TargetInfo.cpp12
-rw-r--r--test/CodeGen/ms_abi.c13
2 files changed, 24 insertions, 1 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 4b8006428f..abd633280b 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -3543,7 +3543,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;
diff --git a/test/CodeGen/ms_abi.c b/test/CodeGen/ms_abi.c
index 407087e409..7486166c78 100644
--- a/test/CodeGen/ms_abi.c
+++ b/test/CodeGen/ms_abi.c
@@ -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;
+}