Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Separate safe and unsafe math operations
Mathematic and logical operations are now fully defined by default for every input. This change includes: - Numeric conversions from/to floating point saturate if the value doesn't fit in the destination type - Signed integer division returns 0 on overflow (e.g. I8(-128) / -1) - Left shift by more bits than the type width returns 0 - Logical (unsigned) right shift by more bits than the type width returns 0 - Arithmetic (signed) right shift by more bits than the type width extends the sign bit on the low bits - Left and right bit rotate work correctly for amounts greater than the type width - Signed rotate is removed - Shift and rotate now take an unsigned amount as argument - popcount, clz, ctz and bitwidth now always have an unsigned return type Add unsafe operations that can have undefined results for some inputs but can be faster and allow better optimisations. Unsafe functions are suffixed with _unsafe. This change includes: - Unsafe numeric conversions. If the value doesn't fit in the destination type, the result is undefined - Unsafe addition, substraction, multiplication and negation. For integers, the result is undefined on overflow. For floating points, fast math semantics are enabled - Unsafe division and modulus. For integers, the result is undefined on division/modulus by 0. For floating points, fast math semantics are enabled - Unsafe left shift. On overflow, the result is undefined - Unsafe right shift. If non-zero bits are shifted out, the result is undefined - Unsafe floating point comparisons. Fast math semantics are enabled - Unsafe square root. If the operand is negative, the result is undefined - Unsafe clz/ctz. If the operand is 0, the result is undefined Fast math semantics mean that the result is undefined if the computation involves NaN and/or +/- infinity. In addition, full compliance to IEEE-754 isn't required. For reference, the semantics of undefined results and of the associated as-if rule are defined as follows. As-if rule The compiler is permitted to perform any changes to the program as long as the following remains true for every behaviour in the program. - At the end of a behaviour, the associated actor is exactly in the state it would be if the program was executed as written - If an object has a finaliser, that finaliser will eventually be called exactly once - Messages are sent as if the behaviour was executed as written, in the same order and with the same contents - FFI calls to well-defined C functions are executed as written, in the same order and with the same arguments. The runtime functions (every function prefixed with pony_) are free from this rule and from the following one - Message sends and FFI calls are not reordered with respect to each other - Capability security (both object capability and reference capability) is maintained Undefined results If an expression with undefined results is evaluated: - Every subsequent expression depending on udefined result also has undefined results - If the constructor of an object with a finaliser has undefined results, that finaliser isn't guaranteed to be called - If a message send or a FFI call has undefined results, it is free from the as-if rule - The implementation is allowed to generate platform-specific exceptions (which are not Pony exceptions) - Capability security is always maintained
- Loading branch information