mstorsjo created this revision.
mstorsjo added reviewers: rnk, mati865.
Herald added a subscriber: pengfei.
mstorsjo requested review of this revision.
Herald added a project: clang.

On x86_64 mingw, long doubles are always passed indirectly as
arguments (see an existing case in WinX86_64ABIInfo::classify); we
need to take this into account when manually reading back arguments
with `va_arg` too.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D103452

Files:
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGen/mingw-long-double.c


Index: clang/test/CodeGen/mingw-long-double.c
===================================================================
--- clang/test/CodeGen/mingw-long-double.c
+++ clang/test/CodeGen/mingw-long-double.c
@@ -45,3 +45,16 @@
 // GNU32: declare dso_local void @__mulxc3
 // GNU64: declare dso_local void @__mulxc3
 // MSC64: declare dso_local void @__muldc3
+
+void VarArgLD(int a, ...) {
+  // GNU32-LABEL: define{{.*}} void @VarArgLD
+  // GNU64-LABEL: define{{.*}} void @VarArgLD
+  // MSC64-LABEL: define{{.*}} void @VarArgLD
+  __builtin_va_list ap;
+  __builtin_va_start(ap, a);
+  long double LD = __builtin_va_arg(ap, long double);
+  // GNU32: bitcast i8* %argp.cur to x86_fp80*
+  // GNU64: bitcast i8* %argp.cur to x86_fp80**
+  // MSC64: bitcast i8* %argp.cur to double*
+  __builtin_va_end(ap);
+}
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -4366,6 +4366,16 @@
   if (isAggregateTypeForABI(Ty) || Ty->isMemberPointerType()) {
     uint64_t Width = getContext().getTypeSize(Ty);
     IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
+  } else if (IsMingw64) {
+    if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) {
+      if (BT->getKind() == BuiltinType::LongDouble) {
+        // Mingw64 GCC uses the old 80 bit extended precision floating point
+        // unit. It passes them indirectly through memory.
+        const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
+        if (LDF == &llvm::APFloat::x87DoubleExtended())
+          IsIndirect = true;
+      }
+    }
   }
 
   return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,


Index: clang/test/CodeGen/mingw-long-double.c
===================================================================
--- clang/test/CodeGen/mingw-long-double.c
+++ clang/test/CodeGen/mingw-long-double.c
@@ -45,3 +45,16 @@
 // GNU32: declare dso_local void @__mulxc3
 // GNU64: declare dso_local void @__mulxc3
 // MSC64: declare dso_local void @__muldc3
+
+void VarArgLD(int a, ...) {
+  // GNU32-LABEL: define{{.*}} void @VarArgLD
+  // GNU64-LABEL: define{{.*}} void @VarArgLD
+  // MSC64-LABEL: define{{.*}} void @VarArgLD
+  __builtin_va_list ap;
+  __builtin_va_start(ap, a);
+  long double LD = __builtin_va_arg(ap, long double);
+  // GNU32: bitcast i8* %argp.cur to x86_fp80*
+  // GNU64: bitcast i8* %argp.cur to x86_fp80**
+  // MSC64: bitcast i8* %argp.cur to double*
+  __builtin_va_end(ap);
+}
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -4366,6 +4366,16 @@
   if (isAggregateTypeForABI(Ty) || Ty->isMemberPointerType()) {
     uint64_t Width = getContext().getTypeSize(Ty);
     IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
+  } else if (IsMingw64) {
+    if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) {
+      if (BT->getKind() == BuiltinType::LongDouble) {
+        // Mingw64 GCC uses the old 80 bit extended precision floating point
+        // unit. It passes them indirectly through memory.
+        const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
+        if (LDF == &llvm::APFloat::x87DoubleExtended())
+          IsIndirect = true;
+      }
+    }
   }
 
   return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to