[PATCH] D44582: [Builtins] Fix calling long double math functions on x86_64 mingw

Martin Storsjö via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 16 13:49:29 PDT 2018


mstorsjo created this revision.
mstorsjo added reviewers: rnk, compnerd.

On x86_64 mingw, long doubles are passed as arguments and returned as if they were a struct. For normal functions, this calling convention detail is handled within clang when generating the IR. When a math function is handled as a builtin, it gets emitted as an LLVM intrinsic call, which for x86_64 mingw in most (all?) cases gets emitted as a libcall. When the libcall is lowered in llvm, the long double specifics of the calling convention aren't taken into account (since they're normally taken care of in clang).

Skip emitting intrinsics for the functions that handle long doubles for this target.

While use of long double might be quite rare in general, it's used internally in the implementation of some mingw math functions for other precisions than long double.


Repository:
  rC Clang

https://reviews.llvm.org/D44582

Files:
  lib/CodeGen/CGBuiltin.cpp
  test/CodeGen/mingw-x86_64-long-double-builtins.c


Index: test/CodeGen/mingw-x86_64-long-double-builtins.c
===================================================================
--- /dev/null
+++ test/CodeGen/mingw-x86_64-long-double-builtins.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple x86_64-mingw32 -emit-llvm -o - %s | FileCheck %s
+
+// Check that long double math functions are emitted as direct function
+// calls instead of as intrinsics.
+
+long double floorl(long double);
+
+long double foo(long double a) {
+  return floorl(a);
+// CHECK: call void @floorl(x86_fp80* sret {{.*}}, x86_fp80* {{.*}})
+}
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -945,12 +945,26 @@
                                                Result.Val.getFloat()));
   }
 
+  bool EmitMathIntrinsic = true;
+  const Triple& Triple = getTarget().getTriple();
+  if (Triple.isWindowsGNUEnvironment() &&
+      Triple.getArch() == llvm::Triple::x86_64) {
+    // On x86_64 mingw, the calling convention handles long doubles as
+    // structs. This detail is normally handled within clang, but
+    // intrinsics lowered into libcalls in LLVM don't handle this.
+    // For these cases, skip emitting an intrinsic and emit a normal
+    // function call with the right calling convention instead.
+    const char *TypeStr = getContext().BuiltinInfo.getTypeString(BuiltinID);
+    if (strstr(TypeStr, "Ld")) // long double
+      EmitMathIntrinsic = false;
+  }
+
   // There are LLVM math intrinsics/instructions corresponding to math library
   // functions except the LLVM op will never set errno while the math library
   // might. Also, math builtins have the same semantics as their math library
   // twins. Thus, we can transform math library and builtin calls to their
   // LLVM counterparts if the call is marked 'const' (known to never set errno).
-  if (FD->hasAttr<ConstAttr>()) {
+  if (FD->hasAttr<ConstAttr>() && EmitMathIntrinsic) {
     switch (BuiltinID) {
     case Builtin::BIceil:
     case Builtin::BIceilf:


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D44582.138761.patch
Type: text/x-patch
Size: 2080 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180316/6bf336c2/attachment.bin>


More information about the cfe-commits mailing list