Skip to content

Layout of vector types #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Nov 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions reference/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@
- [Uninitialized memory](./active_discussion/uninitialized_memory.md)
- [Data representation](./representation.md)
- [Structs and tuples](./representation/structs-and-tuples.md)
- [Vectors](./representation/vectors.md)
- [Optimizations](./optimizations.md)
- [Optimizing immutable memory](./optimizations/immutable_memory.md)
90 changes: 90 additions & 0 deletions reference/src/representation/vectors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Representation of vectors

**Disclaimer:** This chapter represents the consensus from issue
[#38]. The statements in here are not (yet) "guaranteed"
not to change until an RFC ratifies them.

[#38]: https://github.com/rust-rfcs/unsafe-code-guidelines/issues/38

Rust currently exposes vector types like `__m128` to users, but it does not
expose a way for users to construct their own vector types.

The set of currently-exposed vector types is _implementation-defined_ and it is
currently different for each architecture.

## Vector types

Vector types are `repr(simd)` homogeneous tuple-structs containing `N` elements
of type `T` where `N` is a power-of-two:

```rust
#[repr(simd)]
struct Vector<T, N>(T_0, ..., T_(N - 1));
```

The set of supported values of `T` and `N` is _implementation-defined_.

The size of `Vector` is `N * size_of::<T>()` and its alignment is an
_implementation-defined_ function of `T` and `N` greater than or equal to
`align_of::<T>()`. That is:

```rust
assert_eq!(size_of::<Vector<T, N>>(), size_of::<T>() * N);
assert!(align_of::<Vector<T, N>>() >= align_of::<T>());
```

That is, two distinct `repr(simd)` vector types that have the same `T` and the
same `N` have the same size and alignment.

Vector elements are laid out in source field order, enabling random access to
vector elements by reinterpreting the vector as an array:

```rust
union U {
vec: Vector<T, N>,
arr: [T; N]
}

assert_eq!(size_of::<Vector<T, N>>(), size_of::<[T; N]>());
assert!(align_of::<Vector<T, N>>() >= align_of::<[T; N]>());

unsafe {
let u = U { vec: Vector<T, N>(t_0, ..., t_(N - 1)) };

assert_eq!(u.vec.0, u.arr[0]);
// ...
assert_eq!(u.vec.(N - 1), u.arr[N - 1]);
}
```

### Unresolved questions

* **Blocked**: Should the layout of vectors be the same as that of homogeneous
tuples ? Such that:

```rust
union U {
vec: Vector<T, N>,
tup: (T_0, ..., T_(N-1)),
}

assert_eq!(size_of::<Vector<T, N>>(), size_of::<(T_0, ..., T_(N-1))>());
assert!(align_of::<Vector<T, N>>() >= align_of::<(T_0, ..., T_(N-1))>());

unsafe {
let u = U { vec: Vector(t_0, ..., t_(N - 1)) };

assert_eq!(u.vec.0, u.tup.0);
// ...
assert_eq!(u.vec.(N - 1), u.tup.(N - 1));
}
```

This is blocked on the resolution of issue [#36] about the layout of
homogeneous structs and tuples.

[#36]: https://github.com/rust-rfcs/unsafe-code-guidelines/issues/36

* `MaybeUninit<T>` does not have the same `repr` as `T`, so
`MaybeUninit<Vector<T, N>>` are not `repr(simd)`, which has performance
consequences and means that `MaybeUninit<Vector<T, N>>` is not C-FFI safe.