Re: errno is not nothrow

2018-05-12 Thread Neia Neutuladh via Digitalmars-d

On Friday, 11 May 2018 at 19:01:05 UTC, H. S. Teoh wrote:
This sounds scary.  So my (strongly!) pure function that 
returns floating-point can return different results when passed 
the same parameters, if somebody in between changes 
floating-point flags?  That doesn't sound good at all.


This is an ugly problem, and I'm not sure what the best solution 
would be. The current one is simple to understand and only has a 
little surprising behavior (multiple invocations to the same pure 
function with the same parameters might yield the same results, 
even if floating point flags have changed).


I'd like to hear about any reasonable alternatives. Here are a 
few unreasonable ones I thought up:


1. The compiler could have the function store its FPU flag state 
somewhere. It would involve adding a preamble to each pure 
function:


---
static bool fpeInitialized = false;
static fenv_t fpeEnv;
fenv_t previous;
if (fegetenv()) assert(0, "failed to get FPU 
environment");
scope (exit) if (fesetenv()) assert(0, "failed to 
restore FPU environment");

if (fpeInitialized)
{
fesetenv();
}
else
{
fpeEnv = previous;
fpeInitialized = true;
}
---

On my machine, that's an overhead of about 2.5 microseconds per 
function call. On top of a trivial pure function, it's a 47× 
overhead.


But ignoring the performance cost, is that even vaguely 
desirable? Whatever you first call the pure function with, it's 
always going to use the same FPU environment. Accidentally call 
it inside a static constructor and you set your FPU flags in 
main() ? Your intent is silently ignored. And should the FPU 
environment be thread-local? If it isn't, I might see different 
results if I run the same code in different threads. If it is, 
then the compiler might need to use atomic variables or locking, 
and that would be horribly slow. Plus a surprising runtime 
dependency, probably, that prevents pure functions from working 
with -betterC.


2. Pure functions could require you to inform the compiler of 
your desired FPU flags. This means the compiler, not the runtime, 
needs to know about how to set FPU flags on every supported 
architecture. It also means it's a lot harder to use pure 
functions, and they're less portable. They will also all have 
overhead from setting FPU flags and resetting them after, but it 
fixes all  the other problems from the first option.


3. You could tell the compiler to watch out for people changing 
the FPU environment, and then it won't try to omit duplicate 
function calls. This means any function that the compiler is not 
going to emit into the same object file, or that might be 
overridden in another object file. It eats into the promise that 
adding `pure` means your code becomes faster automatically.


Re: errno is not nothrow

2018-05-11 Thread Steven Schveighoffer via Digitalmars-d

On 5/11/18 3:58 PM, Jonathan M Davis wrote:


I don't know why it wouldn't be working for you on Linux, and I
don't have a Linux system to test with at the moment.

void main() nothrow @safe @nogc
{
 import core.stdc.errno;
 errno = 1;
}

works just fine on FreeBSD.


I think we need to wait for more details. As posted earlier in the 
thread, it does work on run.dlang.io which is Linux.


-Steve


Re: errno is not nothrow

2018-05-11 Thread Jonathan M Davis via Digitalmars-d
On Friday, May 11, 2018 12:42:01 Jonathan M Davis via Digitalmars-d wrote:
> On Friday, May 11, 2018 10:05:12 Shachar Shemesh via Digitalmars-d wrote:
> > At least under Linux, you cannot get or set the value of errno from a
> > nothrow function.
> >
> > Is this on purpose, or is this a bug?
>
> In general, the C bindings in druntime haven't ended up with much in the
> way of attributes on them - in part, because many of the predate a lot of
> the attributes, and in part, because it can take some time and effort to
> figure out what the correct attributes are, so they frequently don't get
> put on like they should be.
>
> In the case of errno, it's coming from core.stdc.errno, and it looks like
> on pretty much every system, it's declared as an alias for an extern(C)
> function - e.g.
>
> ref int __error();
>
> and none of them are marked with any attributes. In this particular case,
> I would think that they could be marked with @trusted, nothrow, and
> @nogc. I don't know about pure. Probably not, but I could see it being a
> treated a bit like floating point flags where pure functions are allowed
> to muck with them even though they're arguably global state. So, I don't
> know.
>
> In any case, it's an easy fix, so I created a quick PR to fix it:
>
> https://github.com/dlang/druntime/pull/2180

Okay. I didn't read the code carefully enough. core.stdc.errno does that
annoying thing where attributes are applied with : at the top, making them
really easy to miss. So, errno should already be nothrow, @nogc, and
@trusted. I don't know why it wouldn't be working for you on Linux, and I
don't have a Linux system to test with at the moment.

void main() nothrow @safe @nogc
{
import core.stdc.errno;
errno = 1;
}

works just fine on FreeBSD.

- Jonathan M Davis



Re: errno is not nothrow

2018-05-11 Thread Jonathan M Davis via Digitalmars-d
On Friday, May 11, 2018 12:01:05 H. S. Teoh via Digitalmars-d wrote:
> On Fri, May 11, 2018 at 12:42:01PM -0600, Jonathan M Davis via
> Digitalmars-d wrote: [...]
>
> > In the case of errno, it's coming from core.stdc.errno, and it looks
> > like on pretty much every system, it's declared as an alias for an
> > extern(C) function - e.g.
> >
> > ref int __error();
> >
> > and none of them are marked with any attributes. In this particular
> > case, I would think that they could be marked with @trusted, nothrow,
> > and @nogc. I don't know about pure.  Probably not, but I could see it
> > being a treated a bit like floating point flags where pure functions
> > are allowed to muck with them even though they're arguably global
> > state. So, I don't know.
>
> This sounds scary.  So my (strongly!) pure function that returns
> floating-point can return different results when passed the same
> parameters, if somebody in between changes floating-point flags?  That
> doesn't sound good at all.
>
>   float evil() pure /* ! */ {
>   /* change FP flags, like rounding mode or something */
>   return 0.0;
>   }
>
>   float myfunc(float f) pure { return ...; }
>
>   float result = myfunc(1.23) + evil() + myfunc(1.23);
>
> Since myfunc() is marked pure, the compiler could cache the result of
> the first call and reuse it for the second. But since evil() changes FP
> flags in between, the result will be different from what would have been
> computed had the compiler not cached the return value of the first call.
>
> :-(

Yeah, well. Don't mess with the FP flags. The documentation on pure is quite
clear that it ignores the fact that floating point flags are essentially
global state. So, if you muck with them, it's on you. But unless you're
dealing with strongly pure funtions, function elision isn't a thing, and not
many functions can be strongly pure. So, in practice, I wouldn't expect it
to be an issue, and if you're writing an "evil" function, well you can 
already
be evil by casting away pure.

- Jonathan M Davis



Re: errno is not nothrow

2018-05-11 Thread H. S. Teoh via Digitalmars-d
On Fri, May 11, 2018 at 12:42:01PM -0600, Jonathan M Davis via Digitalmars-d 
wrote:
[...]
> In the case of errno, it's coming from core.stdc.errno, and it looks
> like on pretty much every system, it's declared as an alias for an
> extern(C) function - e.g.
> 
> ref int __error();
> 
> and none of them are marked with any attributes. In this particular
> case, I would think that they could be marked with @trusted, nothrow,
> and @nogc. I don't know about pure.  Probably not, but I could see it
> being a treated a bit like floating point flags where pure functions
> are allowed to muck with them even though they're arguably global
> state. So, I don't know.

This sounds scary.  So my (strongly!) pure function that returns
floating-point can return different results when passed the same
parameters, if somebody in between changes floating-point flags?  That
doesn't sound good at all.

float evil() pure /* ! */ {
/* change FP flags, like rounding mode or something */
return 0.0;
}

float myfunc(float f) pure { return ...; }

float result = myfunc(1.23) + evil() + myfunc(1.23);

Since myfunc() is marked pure, the compiler could cache the result of
the first call and reuse it for the second. But since evil() changes FP
flags in between, the result will be different from what would have been
computed had the compiler not cached the return value of the first call.
:-(


T

-- 
Tech-savvy: euphemism for nerdy.


Re: errno is not nothrow

2018-05-11 Thread Jonathan M Davis via Digitalmars-d
On Friday, May 11, 2018 10:05:12 Shachar Shemesh via Digitalmars-d wrote:
> At least under Linux, you cannot get or set the value of errno from a
> nothrow function.
>
> Is this on purpose, or is this a bug?

In general, the C bindings in druntime haven't ended up with much in the way
of attributes on them - in part, because many of the predate a lot of the
attributes, and in part, because it can take some time and effort to figure
out what the correct attributes are, so they frequently don't get put on
like they should be.

In the case of errno, it's coming from core.stdc.errno, and it looks like on
pretty much every system, it's declared as an alias for an extern(C)
function - e.g.

ref int __error();

and none of them are marked with any attributes. In this particular case, I
would think that they could be marked with @trusted, nothrow, and @nogc. I
don't know about pure. Probably not, but I could see it being a treated a
bit like floating point flags where pure functions are allowed to muck with
them even though they're arguably global state. So, I don't know.

In any case, it's an easy fix, so I created a quick PR to fix it:

https://github.com/dlang/druntime/pull/2180

- Jonathan M Davis



Re: errno is not nothrow

2018-05-11 Thread Uknown via Digitalmars-d

On Friday, 11 May 2018 at 09:10:48 UTC, Cym13 wrote:

On Friday, 11 May 2018 at 07:05:12 UTC, Shachar Shemesh wrote:
At least under Linux, you cannot get or set the value of errno 
from a nothrow function.


Is this on purpose, or is this a bug?

Shachar


It seems I can't reproduce with core.stdc.errno, could you 
please share some code?


Can confirm:

https://run.dlang.io/is/ptkpz0


Re: errno is not nothrow

2018-05-11 Thread Cym13 via Digitalmars-d

On Friday, 11 May 2018 at 07:05:12 UTC, Shachar Shemesh wrote:
At least under Linux, you cannot get or set the value of errno 
from a nothrow function.


Is this on purpose, or is this a bug?

Shachar


It seems I can't reproduce with core.stdc.errno, could you please 
share some code?


errno is not nothrow

2018-05-11 Thread Shachar Shemesh via Digitalmars-d
At least under Linux, you cannot get or set the value of errno from a 
nothrow function.


Is this on purpose, or is this a bug?

Shachar