-
-
Notifications
You must be signed in to change notification settings - Fork 419
core.stdc.math: proper support for Microsoft C Runtime (Visual Studio >= 2013) #968
Conversation
I doubt requiring MSVC >= 2014 is reasonable. |
The MSVC >= 2014 requirement is only relevant for the fpclassify() family (it may even work with VS 2013, I must check this yet). The other 2 commits just provide wrapper implementations for functions which aren't available in any Microsoft runtime version anyway (so all they do is get rid of annoying linking errors). /edit: Okay, the requirement can be dropped to MSVC 2013 as the fpclassify() family is implemented identically (not sure since when exactly). If MS has added some implementations in 2014, there may still be a few unresolved externals when linking to the 2013 runtime; but MSVC 2013 has brought most of the "new" ;) C99 functions, see this MSDN blog. |
//int isfinite(real-floating x); | ||
int isfinite(float x) { return fpclassify(x) <= 0; } | ||
int isfinite(double x) { return fpclassify(x) <= 0; } | ||
int isfinite(real x) { return fpclassify(x) <= 0; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Microsoft's "real" is not the same as D's "real". Use c_long_double instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm that'd be a bigger change and, if done consistently, means replacing all real occurrences in all C header wrappers:
- complex.d
- float_.d
- math.d
- stdlib.d
- wchar_.d
If you think that should be part of this pull request, I'll do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @kinke here, there should be a proper strategy using c_long_double, but not to be decided in this PR. Right now, it would not be used, because you have to add it explicitely at the call site. If there is implicite conversion, it would probably introduce ambiguities.
The problem here is not mangling, but overload resolution for real.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay so how about this as work-around:
-real acoshl(real x);
+extern(D) real acoshl(real x) { return acosh(cast(double) x); }
etc., i.e., adding a dedicated *l wrapper working with proper D reals and using D name mangling so as not to collide with the (hidden) C function in MSVCRT.
All MSVCRT *l functions working with their 64-bit C long double
are completely useless for us as long as D real
remains defined as 80-bit on Windows x64 and including them in druntime would only make sense if we relaxed it to 64-bit.
The proposed D wrappers would at least feature the expected signature for the time being.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the wrappers is what I would do, too. It is what's happening in the C-library anyway.
I just tried what happens if you pass a double to acoshl(real) with "-O -inline": there is no trace of a conversion double->real->double left.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I've just added a commit for these wrappers. This also means that one could safely relax real to 64-bit on Win64 without having to touch core.stdc.math.
I also think that requiring VS2013 or even VS2014 is possible. I suspect Walter is using VS2010, and the build server uses VS2012. |
FP_NORMAL = -1, | ||
FP_ZERO = 0, | ||
FP_INFINITE = 1, | ||
FP_NAN = 2, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't remove existing functionality. The enumerators and the following functions still exist in VS2013, I guess they will be kept by MS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Rainer, I'd prefer getting rid of most existing MS workarounds (I'm not talking about Windows, but the - at least until now - crappy C99 support in their runtime) bloating druntime and forcing D developers to code in a portable way - in this case, by using the standard C99 functions if not something from Phobos.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
People might be using this stuff, so we would have to at least deprecate it for some time.
I'd prefer the Microsoft way here, though: leave it in, it doesn't really hurt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay I've edited the original commit to preserve that legacy stuff (in a version(all)
block with an appropriate comment).
575cffd
to
59190e0
Compare
The wrappers introduced in the last commit unveil the current state wrt. core.stdc.math and MSVCRT < 2013:
These 33 missing functions are currently (druntime head) imported/declared and obviously keen on leading to linking errors as soon as you dare attempt to use them. And these 33 don't even include the *l functions, which are each either not part of the C runtime (more linking errors) or imported with mismatching signature (80-bit D |
Common people, it's been 4 months now. Continuing to neglect the MSVCRT support, essential on Win64 (still hugely popular in the real world!) for both DMD and LDC, is really not gonna help D breaking through. VS 2015 is soon to be released and VS 2013 is offered as free Community edition (not cut down like the previous Express editions). I see no point in continuing the current way of half-heartedly supporting older MS C runtimes. Instead, I strongly recommend requiring VS 2013+, updating the build bots accordingly and considering this and my other PRs (needless to say, all pending too):
I'll rebase once I see some actual commitment; you can't seriously expect contributors to keep rebasing while PRs simply sit there uncommented for months. |
Sorry for the long silence, but I guess we are conservative around here regarding backward compatibility. I think the goal should be to not break linking with VS 2010 or VS2012, but add support for C99, too. AFAICT the float versions are in the MS runtime since VS 2005 or longer, so there is no problem adding these. Why do you version some of these on Win32/Win64? So the problematic cases are the functions needing fpclassify: how about just reimplementing this function here. That could also support reals without conversion. (isnan on real produces a runtime error with this PR, I don't think that is acceptable). |
private int _fdsign(float x); | ||
private int _dsign(double x); | ||
|
||
deprecated("Please use the standard C99 functions instead.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recommend emitting more specific deprecation messages here, but just for functions that have a backward compatible alternative. IMO just a comment would be ok, too.
Well in my opinion there's no backward compatibility. While one is currently able to build druntime with these older runtimes, there's a potential of 100+ undefined symbols, and worse, functions with wrongly imported signature (all *l versions) when trying to actually use C math functions.
MS provides the *f versions of the math functions the runtime supports, i.e., there are 33+ *f functions missing in MSCVRT < 2013. Some are defined inline in the C header and aren't exported by the DLL, so that's why some need to be implemented here in druntime.
That would probably mean duplicating code from Phobos' std.math, I'm not sure that's a good idea. LDC on Win64 defines real as 64-bit double, so this would only be necessary for DMD and of course only if you guys really don't wanna drop the current form of support for older MS runtimes. |
I've tried declaring all 'f' functions without body and produced a main calling all functions. |
extern(D) real fabsl(real x) { return fabs(cast(double) x); } | ||
|
||
private float _hypotf(float x, float y); | ||
double hypot (double x, double y); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should map the double version of hypot to _hypot, too. Otherwise linking against the DLL import library msvcrt.lib fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, iirc hypot() has been introduced with MSVCRT 14. I'll change it.
If all *f functions are really exported by both x86 and x64 runtimes, that is really good news and will simplify the PR. Thanks for checking! |
You could probably emit weakly linked shims to support older runtimes. |
a81ea80
to
91b51cc
Compare
Alright, thanks for your suggestions, I've tried to incorporate all of them in the reworked commits. I think we have a reasonable solution now. |
I am one of those who would really prefer if we don't require the 2013 runtime, as my build scripts all use 2010, but, as long as this is just adding the APIs that are supported in >2010 in a way that doesn't break 2010, then I have no problem with this PR. |
What about the weak link idea? // creates a weakly linked function that forwards to impl
template forward(string name, alias impl)
{
static if (is(typeof(impl) RT == return) && is(typeof(impl) Args == function))
{
pragma(mangle, name) RT forward(Args args) { return impl(args); }
}
else
static assert(0);
}
alias atanf = forward!("atanf", atan);
alias logf = forward!("logf", log); |
@MartinNowak I've dummy-templatized the D wrappers (mostly *l versions for @Orvid We should now have perfect backward compatibility with older runtimes. This now also applies to #969. |
PING! It's been almost half a year now and I don't see any reason not to merge this. |
I like to see this merged, too. It supports the Win64 port of LDC. |
enum | ||
{ | ||
/// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rebasing seems to have removed these comments. I guess these have been added so the symbols are shown in the online documenttion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was actually intentional for these MS specific symbols. They haven't had these ///
comments before 2.067, so I thought it'd be better to leave these non-standard declarations uncommented and only decorate the standard ones while rebasing.
I can add them if you insist. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I'm also not a huge fan of those empty comments. Let's consider this enumerator "internal".
Especially for MSVCRT 12+ (VS 2013).
By implementing functions defined inline in MS math.h header (from VS 2014 CTP3) and using D wrappers for all *l functions. hypot() forwards to _hypot() to support VS <= 2013.
I'm ready to merge this if there are no objections. I tried building this against VS2015 (build 22310), but that failed due to some unrelated missing symbols (_set_output_format, _snprintf and a few more). Did you tried/managed to build against this version? |
Yes I tried and managed (for LDC), see ldc-developers#17 and ldc-developers/phobos#6. |
Ouch, looks like more trouble in the future. Maybe adding some stubs in a library to be added to the command line when linking against a VS runtime might work. |
Auto-merge toggled on |
core.stdc.math: proper support for Microsoft C Runtime (Visual Studio >= 2013)
Thanks for submission and bearing the slow review. |
These commits add proper support for Microsoft C runtimes to core.stdc.math. It is especially useful in combination with MSVCRT v12 (VS 2013) with its greatly improved C99 support (30+ new math functions, in single and double precision).
Microsoft's lacking 80-bit x87 support is approximated by 64-bit double-precision wrappers.