diff options
| author | JF Bastien <jfb@chromium.org> | 2015-06-16 16:28:28 +0200 |
|---|---|---|
| committer | JF Bastien <jfb@chromium.org> | 2015-06-16 16:28:28 +0200 |
| commit | bdf16bf889043114fa496f346ebf83c11e40147b (patch) | |
| tree | 1a15b2ec0aaef6ba089d8e3f68d3054e69ea4021 | |
| parent | c934b7f0936d8bca5780428cbcca6671b7521e69 (diff) | |
| parent | a13d1529d2c2c57b62880b3ec35ab7b1f784414f (diff) | |
| download | nanowasm-design-bdf16bf889043114fa496f346ebf83c11e40147b.tar.gz | |
Merge.
| -rw-r--r-- | AstSemantics.md | 146 | ||||
| -rw-r--r-- | FutureFeatures.md | 6 | ||||
| -rw-r--r-- | Nondeterminism.md | 28 |
3 files changed, 91 insertions, 89 deletions
diff --git a/AstSemantics.md b/AstSemantics.md index 05f4848..72495e0 100644 --- a/AstSemantics.md +++ b/AstSemantics.md @@ -36,60 +36,56 @@ variables, local variables, and parameters. The heap itself is not typed, but all accesses to the heap are annotated with a type. The legal types for global variables and heap accesses are called *Memory types*. - * `sint8`: signed 8-bit integer - * `sint16`: signed 16-bit integer - * `sint32`: signed 32-bit integer - * `sint64`: signed 64-bit integer - * `uint8`: unsigned 8-bit integer - * `uint16`: unsigned 16-bit integer - * `uint32`: unsigned 32-bit integer - * `uint64`: unsigned 64-bit integer - * `float32`: 32-bit floating point - * `float64`: 64-bit floating point + * `int8` - 8-bit integer + * `int16` - 16-bit integer + * `int32` - 32-bit integer + * `int64` - 64-bit integer + * `float32` - 32-bit floating point + * `float64` - 64-bit floating point The legal types for parameters and local variables, called *Local types* are a subset of the Memory types: - * `int32`: 32-bit integer - * `int64`: 64-bit integer - * `float32`: 32-bit floating point - * `float64`: 64-bit floating point - -All IR operations except loads and stores deal with local types. Loads -implicitly convert Memory types to Local types according to the follow rules: - - * `load[sint8]`: sign-extend to int32 - * `load[sint16]`: sign-extend to int32 - * `load[sint32]`: (no conversion) - * `load[sint64]`: (no conversion) - * `load[uint8]`: zero-extend to int32 - * `load[uint16]`: zero-extend to int32 - * `load[uint32]`: reinterpret as int32 - * `load[uint64]`: reinterpret as int64 - * `load[float32]`: (no conversion) - * `load[float64]`: (no conversion) - -Note that the local types int32 and int64 don't technically have a sign; the + * `int32` - 32-bit integer + * `int64` - 64-bit integer + * `float32` - 32-bit floating point + * `float64` - 64-bit floating point + +All operations except loads and stores deal with local types. Loads convert +Memory types to Local types according to the following rules: + + * `int32.load_sx[int8]` - sign-extend to int32 + * `int32.load_sx[int16]` - sign-extend to int32 + * `int32.load_zx[int8]` - zero-extend to int32 + * `int32.load_zx[int16]` - zero-extend to int32 + * `int32.load[int32]` - (no conversion) + * `int64.load_sx[int8]` - sign-extend to int64 + * `int64.load_sx[int16]` - sign-extend to int64 + * `int64.load_sx[int32]` - sign-extend to int64 + * `int64.load_zx[int8]` - zero-extend to int64 + * `int64.load_zx[int16]` - zero-extend to int64 + * `int64.load_zx[int32]` - zero-extend to int64 + * `int64.load[int64]` - (no conversion) + * `float32.load[float32]` - (no conversion) + * `float64.load[float64]` - (no conversion) + +Note that the local types `int32` and `int64` don't technically have a sign; the sign bit is interpreted differently by the operations below. -Note: [issue #139](https://github.com/WebAssembly/design/issues/139) discussed -extending loads and truncating stores in more details. +Similar to loads, stores convert Local types to Memory types according to the +following rules: -Similar to loads, stores implicitly truncate Local types to Memory types -according to the following rules: + * `int32.store[int8]` - wrap int32 to int8 + * `int32.store[int16]` - wrap int32 to int16 + * `int32.store[int32]` - (no conversion) + * `int64.store[int8]` - wrap int64 to int8 + * `int64.store[int16]` - wrap int64 to int16 + * `int64.store[int32]` - wrap int64 to int32 + * `int64.store[int64]` - (no conversion) + * `float32.store[float32]` - (no conversion) + * `float64.store[float64]` - (no conversion) - * `store[sint8]`: truncate int32 to sint8 - * `store[sint16]`: truncate int32 to sint16 - * `store[sint32]`: (no truncation) - * `store[sint64]`: (no truncation) - * `store[uint8]`: truncate int32 to uint8 - * `store[uint16]`: truncate int32 to uint16 - * `store[uint32]`: reinterpret int32 as uint32 - * `store[uint64]`: reinterpret int64 as uint64 - * `store[float32]`: (no truncation) - * `store[float64]`: (no truncation) - -Truncation of integers simply discards any upper bits; i.e. truncation does not +Wrapping of integers simply discards any upper bits; i.e. wrapping does not perform saturation, trap on overflow, etc. ## Addressing local variables @@ -146,9 +142,9 @@ which leads to the following advantages: ## Accessing the heap -Each heap access is annotated with a *Memory type* and the presumed alignment of -the incoming pointer. As discussed previously, loads may include implicit zero- -or sign-extension and stores may include implicit truncation. +Each heap access is annotated with a *Memory type* and +the presumed alignment of the incoming pointer. As discussed previously, loads may +include explicit zero- or sign-extension and stores may include implicit wrapping. Indexes into the heap are always byte indexes. @@ -413,30 +409,34 @@ Floating point arithmetic follows the IEEE-754 standard, except that: ## Datatype conversions, truncations, reinterpretations, promotions, and demotions - * `sint32_from_float64`: truncate a 64-bit float to a signed integer - * `sint32_from_float32`: truncate a 32-bit float to a signed integer - * `uint32_from_float64`: truncate a 64-bit float to an unsigned integer - * `uint32_from_float32`: truncate a 32-bit float to an unsigned integer - * `sint64_from_float64`: truncate a 64-bit float to a signed integer - * `sint64_from_float32`: truncate a 32-bit float to a signed integer - * `uint64_from_float64`: truncate a 64-bit float to an unsigned integer - * `uint64_from_float32`: truncate a 32-bit float to an unsigned integer - * `int32_from_float32_bits`: reinterpret the bits of a 32-bit float as a 32-bit integer - * `int64_from_float64_bits`: reinterpret the bits of a 64-bit float as a 64-bit integer - * `float64_from_float32`: promote a 32-bit float to a 64-bit float - * `float64_from_sint32`: convert a signed integer to a 64-bit float - * `float64_from_uint32`: convert an unsigned integer to a 64-bit float - * `float64_from_sint64`: convert a signed integer to a 64-bit float - * `float64_from_uint64`: convert an unsigned integer to a 64-bit float - * `float32_from_float64`: demote a 64-bit float to a 32-bit float - * `float32_from_sint32`: convert a signed integer to a 32-bit float - * `float32_from_uint32`: convert an unsigned integer to a 32-bit float - * `float32_from_sint64`: convert a signed integer to a 32-bit float - * `float32_from_uint64`: convert an unsigned integer to a 32-bit float - * `float32_from_int32_bits`: reinterpret the bits of a 32-bit integer as a 32-bit float - * `float64_from_int64_bits`: reinterpret the bits of a 64-bit integer as a 64-bit float - -Promotion and demotion of floating point values always succeeds. + * `int32_from_int64` - wrap a 64-bit integer to a 32-bit integer + * `int64_from_sint32` - extend a signed 32-bit integer to a 64-bit integer + * `int64_from_uint32` - extend an unsigned 32-bit integer to a 64-bit integer + * `sint32_from_float64` - truncate a 64-bit float to a signed integer + * `sint32_from_float32` - truncate a 32-bit float to a signed integer + * `uint32_from_float64` - truncate a 64-bit float to an unsigned integer + * `uint32_from_float32` - truncate a 32-bit float to an unsigned integer + * `sint64_from_float64` - truncate a 64-bit float to a signed integer + * `sint64_from_float32` - truncate a 32-bit float to a signed integer + * `uint64_from_float64` - truncate a 64-bit float to an unsigned integer + * `uint64_from_float32` - truncate a 32-bit float to an unsigned integer + * `int32_from_float32_bits` - reinterpret the bits of a 32-bit float as a 32-bit integer + * `int64_from_float64_bits` - reinterpret the bits of a 64-bit float as a 64-bit integer + * `float64_from_float32` - promote a 32-bit float to a 64-bit float + * `float64_from_sint32` - convert a signed integer to a 64-bit float + * `float64_from_uint32` - convert an unsigned integer to a 64-bit float + * `float64_from_sint64` - convert a signed integer to a 64-bit float + * `float64_from_uint64` - convert an unsigned integer to a 64-bit float + * `float32_from_float64` - demote a 64-bit float to a 32-bit float + * `float32_from_sint32` - convert a signed integer to a 32-bit float + * `float32_from_uint32` - convert an unsigned integer to a 32-bit float + * `float32_from_sint64` - convert a signed integer to a 32-bit float + * `float32_from_uint64` - convert an unsigned integer to a 32-bit float + * `float32_from_int32_bits` - reinterpret the bits of a 32-bit integer as a 32-bit float + * `float64_from_int64_bits` - reinterpret the bits of a 64-bit integer as a 64-bit float + +Wrapping and extension of integer values always succeed. +Promotion and demotion of floating point values always succeed. Demotion of floating point values uses round-to-nearest ties-to-even rounding, and may overflow to infinity or negative infinity as specified by IEEE-754. If the operand of promotion or demotion is NaN, the sign bit and significand diff --git a/FutureFeatures.md b/FutureFeatures.md index 1c98bbd..81f392b 100644 --- a/FutureFeatures.md +++ b/FutureFeatures.md @@ -251,9 +251,9 @@ well on all platforms. These should be guarded by These operations would not required to be fully precise, but the specifics would need clarification. -## 16-bit and 128-bit floating-point support +## 16-bit and 128-bit floating point support -For 16-bit floating-point support, it may make sense to split the feature +For 16-bit floating point support, it may make sense to split the feature into two parts: support for just converting between 16-bit and 32-bit or 64-bit formats possibly folded into load and store operations, and full support for actual 16-bit arithmetic. @@ -267,7 +267,7 @@ techniques such as double-double arithmetic. If we standardize 128-bit floating point in WebAssembly, it will probably be standard IEEE-754 quadruple precision. -## Floating-point library intrinsics +## Floating point library intrinsics These operations aren't needed because they can be implemented in WebAssembly code and linked into WebAssembly modules as at small size cost, and this avoids diff --git a/Nondeterminism.md b/Nondeterminism.md index f7c6a13..77fc899 100644 --- a/Nondeterminism.md +++ b/Nondeterminism.md @@ -25,22 +25,24 @@ other practical way to achieve [portable](Portability.md) native performance. The following is a list of the places where the WebAssembly specification currently admits nondeterminism: - - [When threads are added as a feature](PostMVP.md#threads), even without + * [When threads are added as a feature](PostMVP.md#threads), even without shared memory, nondeterminism will be visible through the global sequence of API calls. With shared memory, the result of load operations is nondeterministic. - - - [Out of bounds heap accesses *may* want some flexibility](AstSemantics.md#out-of-bounds) - - - [NaN bit patterns](AstSemantics.md#floating-point-operations) - - - [Fixed-width SIMD may want some flexibility](PostMVP.md#fixed-width-simd) - - In SIMD.js, floating point values may or may not have subnormals flushed to zero. - - In SIMD.js, operations ending in "Approximation" return approximations that may vary between platforms. - - - Environment-dependent resource limits may be exhausted. + * Out of bounds heap accesses *may* want + [some flexibility](AstSemantics.md#out-of-bounds) + * [NaN bit patterns](AstSemantics.md#floating-point-operations) + * [Fixed-width SIMD may want some flexibility](PostMVP.md#fixed-width-simd) + - In SIMD.js, floating point values may or may not have subnormals flushed to + zero. + - In SIMD.js, operations ending in "Approximation" return approximations that + may vary between platforms. + * Environment-dependent resource limits may be exhausted. A few examples: + - Memory allocation may fail. + - Program stack may get exhausted. + - Resources such as handles may get exahusted. Users of C, C++, and similar languages should be aware that operations which -have defined or constrained behavior in WebAssembly itself may nonetheless -still have undefined behavior +have defined or constrained behavior in WebAssembly itself may nonetheless still +have undefined behavior [at the source code level](CAndC++.md#undefined-behavior). |
