From f471c1023e19ae6be406107c54c750f83c4b4f9d Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Sun, 23 Dec 2018 15:03:04 +0100 Subject: [PATCH 1/3] Fix mangling of extern(C++) function with two `real` arguments. --- dmd/cppmangle.d | 13 +++++++++++-- tests/codegen/mangling_real_real.d | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 tests/codegen/mangling_real_real.d diff --git a/dmd/cppmangle.d b/dmd/cppmangle.d index 05b0418b96b..0458c898337 100644 --- a/dmd/cppmangle.d +++ b/dmd/cppmangle.d @@ -1198,8 +1198,17 @@ extern(C++): case Tfloat64: c = 'd'; break; version (IN_LLVM) { - // there are special cases for D `real`, handled via Target.cppTypeMangle() in the default case - case Tfloat80: goto default; + // There are special cases for D `real` that need to be handled via Target.cppTypeMangle(). + // Don't go to the default case because it would incorrectly substitute subsequent `real` arguments. + case Tfloat80: + auto cptr = Target.cppTypeMangle(t); + if (cptr is null) + return error(t); + // Goto default case if the mangling is longer than one character. + if (cptr[1] != 0) + goto default; + c = cptr[0]; + break; } else { diff --git a/tests/codegen/mangling_real_real.d b/tests/codegen/mangling_real_real.d new file mode 100644 index 00000000000..13477b6371d --- /dev/null +++ b/tests/codegen/mangling_real_real.d @@ -0,0 +1,23 @@ +// Tests that repeated `real` return types are treated as built-in types in C++ mangling (no substitution). + +// REQUIRES: target_X86 + +// RUN: %ldc -mtriple=x86_64-linux -c -output-ll -of=%t.ll %s && FileCheck %s --check-prefix=LINUX < %t.ll +// RUN: %ldc -mtriple=x86_64-android -c -output-ll -of=%t.android.ll %s && FileCheck %s --check-prefix=ANDROID < %t.android.ll +// RUN: %ldc -mtriple=x86_64-windows -c -output-ll -of=%t.windows.ll %s && FileCheck %s --check-prefix=WINDOWS < %t.windows.ll + +import core.stdc.config; + +// LINUX: define {{.*}}Z8withrealee +// ANDROID: define {{.*}}Z8withrealgg +// WINDOWS: define {{.*}}?withreal@@YAX_T0@Z +extern (C++) void withreal(real a, real b) +{ +} + +// LINUX: define {{.*}}Z15withclongdoubleee +// ANDROID: define {{.*}}Z15withclongdoublegg +// WINDOWS: define {{.*}}?withclongdouble@@YAXOO@Z +extern (C++) void withclongdouble(c_long_double a, c_long_double b) +{ +} From 95f7692c7fac7289fb8dd146cad84fb94e1f9736 Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Sun, 23 Dec 2018 15:59:56 +0100 Subject: [PATCH 2/3] Different fix. --- dmd/cppmangle.d | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/dmd/cppmangle.d b/dmd/cppmangle.d index 0458c898337..f30cca74d37 100644 --- a/dmd/cppmangle.d +++ b/dmd/cppmangle.d @@ -1198,17 +1198,8 @@ extern(C++): case Tfloat64: c = 'd'; break; version (IN_LLVM) { - // There are special cases for D `real` that need to be handled via Target.cppTypeMangle(). - // Don't go to the default case because it would incorrectly substitute subsequent `real` arguments. - case Tfloat80: - auto cptr = Target.cppTypeMangle(t); - if (cptr is null) - return error(t); - // Goto default case if the mangling is longer than one character. - if (cptr[1] != 0) - goto default; - c = cptr[0]; - break; + // there are special cases for D `real`, handled via Target.cppTypeMangle() in the default case + case Tfloat80: goto default; } else { @@ -1229,10 +1220,14 @@ else // Handle any target-specific basic types. if (auto tm = Target.cppTypeMangle(t)) { - if (substitute(t)) - return; - else - append(t); + // Only do substitution for mangles that are longer than 1 character. + if (tm[1] != 0 || t.isConst()) + { + if (substitute(t)) + return; + else + append(t); + } CV_qualifiers(t); buf.writestring(tm); return; From 31db68a65db9577130be5a570f1e6c9c5f2efe56 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 23 Dec 2018 16:57:57 +0100 Subject: [PATCH 3/3] Fix C++ mangling of `real` for MSVC targets Mangle as native Visual C++ long double. DMD has to special-case, as it's using 80-bit extended precision. --- dmd/cppmanglewin.d | 12 ++++++++++++ tests/codegen/mangling_real_real.d | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/dmd/cppmanglewin.d b/dmd/cppmanglewin.d index 30844b095d0..fdd2bd8a9cb 100644 --- a/dmd/cppmanglewin.d +++ b/dmd/cppmanglewin.d @@ -178,7 +178,10 @@ public: case Tuns64: case Tint128: case Tuns128: +version (IN_LLVM) {} else +{ case Tfloat80: +} case Twchar: if (checkTypeSaved(type)) return; @@ -241,10 +244,19 @@ public: break; // unsigned int case Tfloat80: +version (IN_LLVM) +{ + // unlike DMD, LDC uses 64-bit `real` for Windows/MSVC targets, + // corresponding to MSVC++ long double + buf.writeByte('O'); // Visual C++ long double +} +else +{ if (flags & IS_DMC) buf.writestring("_Z"); // DigitalMars long double else buf.writestring("_T"); // Intel long double +} break; case Twchar: if (flags & IS_DMC) diff --git a/tests/codegen/mangling_real_real.d b/tests/codegen/mangling_real_real.d index 13477b6371d..641c7ae5f3d 100644 --- a/tests/codegen/mangling_real_real.d +++ b/tests/codegen/mangling_real_real.d @@ -10,7 +10,7 @@ import core.stdc.config; // LINUX: define {{.*}}Z8withrealee // ANDROID: define {{.*}}Z8withrealgg -// WINDOWS: define {{.*}}?withreal@@YAX_T0@Z +// WINDOWS: define {{.*}}?withreal@@YAXOO@Z extern (C++) void withreal(real a, real b) { }