From a0392dff4d3b7708851d2411b472fb2f8f1abfc1 Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Wed, 26 Jun 2019 12:49:33 +0200 Subject: [PATCH 01/16] Add niches to layout and expand call ABI --- reference/src/glossary.md | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index 3b9cf4f7..20456770 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -53,8 +53,13 @@ For some more information, see [this blog post](https://www.ralfj.de/blog/2018/0 #### Layout -The *layout* of a type defines its size and alignment as well as the offsets of its subobjects (e.g. fields of structs/unions/enum/... or elements of arrays). -Moreover, the layout of a type records its *function call ABI* (or just *ABI* for short): how the type is passed *by value* across a function boundary. +The *layout* of a type defines: + +* its size, +* its alignment, +* its field offsets (e.g. fields of structs, union, enums, arrays, ...) +* its [niches][Niche], +* its call abi. Note: Originally, *layout* and *representation* were treated as synonyms, and Rust language features like the `#[repr]` attribute reflect this. In this document, *layout* and *representation* are not synonyms. @@ -73,6 +78,28 @@ niches. For example, the "all bits uninitialized" is an invalid bit-pattern for `&mut T`, but this bit-pattern cannot be used by layout optimizations, and is not a niche. +#### Call ABI + +The call ABI is how a type is passed *by value* across a function boundary. + +Note: The call ABI is not stable. Currently, it is one of: + +```rust,norun +pub enum Abi { + Uninhabited, + Scalar(Scalar), + Vector { + element: Scalar, + count: u64 + }, + Aggregate { + // If true, the layout size of the aggregate is exact. + // Otherwise, the layout size of the aggregate is + // a lower bound. + sized: bool, + } +} +``` ### TODO From 1d198e684f5eb7febb0f94bf46ae3b533689cbe2 Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Wed, 26 Jun 2019 12:52:42 +0200 Subject: [PATCH 02/16] Add note about why niches need to be part of the layout --- reference/src/glossary.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index 20456770..03645399 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -64,6 +64,7 @@ The *layout* of a type defines: Note: Originally, *layout* and *representation* were treated as synonyms, and Rust language features like the `#[repr]` attribute reflect this. In this document, *layout* and *representation* are not synonyms. +<<<<<<< HEAD #### Niche The *niche* of a type determines invalid bit-patterns that will be used by layout optimizations. @@ -77,6 +78,10 @@ While all niches are invalid bit-patterns, not all invalid bit-patterns are niches. For example, the "all bits uninitialized" is an invalid bit-pattern for `&mut T`, but this bit-pattern cannot be used by layout optimizations, and is not a niche. +======= +Note: due to discriminant-elision optimizations, niches are required to compute +the layout of, e.g., `Option<T>`, from the layout of `T`. +>>>>>>> Add note about why niches need to be part of the layout #### Call ABI From 5b6079b69295471e75cdc580858b0298b6f78fcd Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Wed, 26 Jun 2019 12:56:51 +0200 Subject: [PATCH 03/16] Add call ABI example --- reference/src/glossary.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index 03645399..b86425f0 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -106,6 +106,10 @@ pub enum Abi { } ``` +For example, the call ABI of `i32` is `Scalar`. The call ABI of `struct +Wrapper(i32);` is also `Scalar`. But the call ABI of `#[repr(C)] struct +Wrapper(i32)l` is `Aggregate { sized: true }`. + ### TODO * *tag* From a05fd3ba4d3dd43fbfe5c1e32c79a1dda4c5143f Mon Sep 17 00:00:00 2001 From: gnzlbg <gnzlbg@users.noreply.github.com> Date: Wed, 26 Jun 2019 20:17:47 +0200 Subject: [PATCH 04/16] Update reference/src/glossary.md Co-Authored-By: Ralf Jung <post@ralfj.de> --- reference/src/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index b86425f0..2c753e61 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -85,7 +85,7 @@ the layout of, e.g., `Option<T>`, from the layout of `T`. #### Call ABI -The call ABI is how a type is passed *by value* across a function boundary. +The *call ABI* determines how a type is passed *by value* across a function boundary. Note: The call ABI is not stable. Currently, it is one of: From afebd1cf8252992b79e7ac26e0bab8c8ed7d2387 Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Wed, 26 Jun 2019 20:29:53 +0200 Subject: [PATCH 05/16] Clarify ABI and examples --- reference/src/glossary.md | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index 2c753e61..9cea80d7 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -106,9 +106,34 @@ pub enum Abi { } ``` -For example, the call ABI of `i32` is `Scalar`. The call ABI of `struct -Wrapper(i32);` is also `Scalar`. But the call ABI of `#[repr(C)] struct -Wrapper(i32)l` is `Aggregate { sized: true }`. +where + +```rust,norun +enum Integer { I8, I16, I32, I64, I128, } +enum FloatTy { F32, F64, } + +enum Primitive { + Int(Integer, /*signedness:*/ bool), + Float(FloatTy), + Pointer +} + +struct Scalar { + value: Primitive, + valid_range: RangeInclusive<u128>, +} +``` + +For example, right now, the call ABI of: + +* `i32` is `Scalar`, +* `struct Wrapper(i32);` (without `repr(transparent)`) is also `Scalar` (only larger `struct`s are aggregates), +* `#[repr(C)] struct Wrapper(i32);` is `Aggregate { sized: true }` - required by `repr(C****. + +**NOTE**: the call ABI of `repr(Rust)` types is unspecified, so the "call ABI" +of `repr(Rust)` types is not guaranteed and `unsafe` code shall not rely on it. +That is, code that requires `struct Wrapper(i32);` to have the same ABI as `i32` +needs to use `repr(transparent)`. f ### TODO From bd747eeae8717328a178708544c0b56bb34236dc Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Wed, 26 Jun 2019 21:17:01 +0200 Subject: [PATCH 06/16] Separate guaranteed from non guaranteed behavior in call ABI examples --- reference/src/glossary.md | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index 9cea80d7..e06409a1 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -106,34 +106,30 @@ pub enum Abi { } ``` -where +where: ```rust,norun enum Integer { I8, I16, I32, I64, I128, } enum FloatTy { F32, F64, } -enum Primitive { +enum Scalar { Int(Integer, /*signedness:*/ bool), Float(FloatTy), Pointer } - -struct Scalar { - value: Primitive, - valid_range: RangeInclusive<u128>, -} ``` -For example, right now, the call ABI of: +For example, the call ABI of: * `i32` is `Scalar`, -* `struct Wrapper(i32);` (without `repr(transparent)`) is also `Scalar` (only larger `struct`s are aggregates), -* `#[repr(C)] struct Wrapper(i32);` is `Aggregate { sized: true }` - required by `repr(C****. +* `#[repr(C)] struct Wrapper(i32);` is `Aggregate { sized: true }`. +* `#[repr(transparent)] struct Wrapper(i32);` is `Scalar`. + +The call ABI of `repr(Rust)` types is unspecified. The following is not +guaranteed, but right now the call ABI of: -**NOTE**: the call ABI of `repr(Rust)` types is unspecified, so the "call ABI" -of `repr(Rust)` types is not guaranteed and `unsafe` code shall not rely on it. -That is, code that requires `struct Wrapper(i32);` to have the same ABI as `i32` -needs to use `repr(transparent)`. f +* `/*#[repr(Rust)]*/ struct Wrapper(i32);` (without `repr(transparent)`) is also + `Scalar` - only larger `struct`s are aggregates. ### TODO From b154cb4c553958761d0b0a7e8001721de9dbc3c0 Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Wed, 26 Jun 2019 21:19:10 +0200 Subject: [PATCH 07/16] Specify which scalars in examples --- reference/src/glossary.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index e06409a1..4720a2f4 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -121,15 +121,15 @@ enum Scalar { For example, the call ABI of: -* `i32` is `Scalar`, +* `i32` is `Scalar::Int(I32,true)`, * `#[repr(C)] struct Wrapper(i32);` is `Aggregate { sized: true }`. -* `#[repr(transparent)] struct Wrapper(i32);` is `Scalar`. +* `#[repr(transparent)] struct Wrapper(i32);` is `Scalar::Int(I32,true)`. The call ABI of `repr(Rust)` types is unspecified. The following is not guaranteed, but right now the call ABI of: * `/*#[repr(Rust)]*/ struct Wrapper(i32);` (without `repr(transparent)`) is also - `Scalar` - only larger `struct`s are aggregates. + `Scalar::Int(I32, true)` - only larger `struct`s are aggregates. ### TODO From 4861ff01ed4a3884b406b9da73dfb7952a9061b6 Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Wed, 26 Jun 2019 21:23:16 +0200 Subject: [PATCH 08/16] Simplify further --- reference/src/glossary.md | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index 4720a2f4..c73a40c7 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -106,30 +106,20 @@ pub enum Abi { } ``` -where: - -```rust,norun -enum Integer { I8, I16, I32, I64, I128, } -enum FloatTy { F32, F64, } - -enum Scalar { - Int(Integer, /*signedness:*/ bool), - Float(FloatTy), - Pointer -} -``` +where a `Scalar` is either a primitive integer, floating point, or a pointer to +a sized type. For example, the call ABI of: -* `i32` is `Scalar::Int(I32,true)`, +* `i32` is `Scalar(I32)`, * `#[repr(C)] struct Wrapper(i32);` is `Aggregate { sized: true }`. -* `#[repr(transparent)] struct Wrapper(i32);` is `Scalar::Int(I32,true)`. +* `#[repr(transparent)] struct Wrapper(i32);` is `Scalar(I32)`. The call ABI of `repr(Rust)` types is unspecified. The following is not guaranteed, but right now the call ABI of: * `/*#[repr(Rust)]*/ struct Wrapper(i32);` (without `repr(transparent)`) is also - `Scalar::Int(I32, true)` - only larger `struct`s are aggregates. + `Scalar(I32)` - only larger `struct`s are aggregates. ### TODO From 6c814077ee9eedbf57297ca326c156e74fa5d8b3 Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Sat, 29 Jun 2019 00:01:00 +0200 Subject: [PATCH 09/16] Ignore the Rust snippet --- reference/src/glossary.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index c73a40c7..2b375141 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -89,8 +89,8 @@ The *call ABI* determines how a type is passed *by value* across a function boun Note: The call ABI is not stable. Currently, it is one of: -```rust,norun -pub enum Abi { +```rust,ignore +enum Abi { Uninhabited, Scalar(Scalar), Vector { From 624653458b6481d805d57b130f32a5f92a12e4bb Mon Sep 17 00:00:00 2001 From: gnzlbg <gnzlbg@users.noreply.github.com> Date: Tue, 23 Jul 2019 16:15:03 +0200 Subject: [PATCH 10/16] Update reference/src/glossary.md Co-Authored-By: Ralf Jung <post@ralfj.de> --- reference/src/glossary.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index 2b375141..869f2768 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -61,10 +61,12 @@ The *layout* of a type defines: * its [niches][Niche], * its call abi. +Note: due to discriminant-elision optimizations, niches are required to compute +the layout of, e.g., `Option<T>`, from the layout of `T`. + Note: Originally, *layout* and *representation* were treated as synonyms, and Rust language features like the `#[repr]` attribute reflect this. In this document, *layout* and *representation* are not synonyms. -<<<<<<< HEAD #### Niche The *niche* of a type determines invalid bit-patterns that will be used by layout optimizations. @@ -78,16 +80,12 @@ While all niches are invalid bit-patterns, not all invalid bit-patterns are niches. For example, the "all bits uninitialized" is an invalid bit-pattern for `&mut T`, but this bit-pattern cannot be used by layout optimizations, and is not a niche. -======= -Note: due to discriminant-elision optimizations, niches are required to compute -the layout of, e.g., `Option<T>`, from the layout of `T`. ->>>>>>> Add note about why niches need to be part of the layout #### Call ABI The *call ABI* determines how a type is passed *by value* across a function boundary. -Note: The call ABI is not stable. Currently, it is one of: +Note: The set of possible call ABIs is not stable. Currently, it consists of: ```rust,ignore enum Abi { From 875c32b20c490baa2b1ddb874bfd0fd61784aa10 Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Tue, 23 Jul 2019 17:23:13 +0200 Subject: [PATCH 11/16] Properly link layout components --- reference/src/glossary.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index 869f2768..11e3dca7 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -58,8 +58,8 @@ The *layout* of a type defines: * its size, * its alignment, * its field offsets (e.g. fields of structs, union, enums, arrays, ...) -* its [niches][Niche], -* its call abi. +* its [niches](glossary.html#niche), +* its [call abi](glossary.html#call-abi). Note: due to discriminant-elision optimizations, niches are required to compute the layout of, e.g., `Option<T>`, from the layout of `T`. From 6ad8df6b7e8a30d0273a7d349d287168dc7bf64a Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Tue, 23 Jul 2019 17:26:45 +0200 Subject: [PATCH 12/16] Use short links --- reference/src/glossary.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index 11e3dca7..6a0bdde4 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -58,8 +58,8 @@ The *layout* of a type defines: * its size, * its alignment, * its field offsets (e.g. fields of structs, union, enums, arrays, ...) -* its [niches](glossary.html#niche), -* its [call abi](glossary.html#call-abi). +* its [niches](#niche), +* its [call abi](#call-abi). Note: due to discriminant-elision optimizations, niches are required to compute the layout of, e.g., `Option<T>`, from the layout of `T`. From bd13bcdb5033651fbd813018d9506638573d4c8d Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Tue, 23 Jul 2019 18:31:39 +0200 Subject: [PATCH 13/16] Update layout of arrays and slices --- reference/src/layout/arrays-and-slices.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/reference/src/layout/arrays-and-slices.md b/reference/src/layout/arrays-and-slices.md index 375d1571..bf356fc5 100644 --- a/reference/src/layout/arrays-and-slices.md +++ b/reference/src/layout/arrays-and-slices.md @@ -10,8 +10,9 @@ The _offset_ of the first array element is `0`, that is, a pointer to the array and a pointer to its first element both point to the same memory address. The _alignment_ of array types is greater or equal to the alignment of its -element type. If the element type is `repr(C)` the layout of the array is -guaranteed to be the same as the layout of a C array with the same element type. +element type. If the element type is `repr(C)` the size and alignment of the +array is guaranteed to be the same as the size and alignment of a C array with +the same element type. > **Note**: the type of array arguments in C function signatures, e.g., `void > foo(T x[N])`, decays to a pointer. That is, these functions do not take arrays From 3d71cf6c4e5d726a742e807cb9ed6c58743c979e Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Tue, 23 Jul 2019 18:31:48 +0200 Subject: [PATCH 14/16] Update layout of scalars --- reference/src/layout/scalars.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/src/layout/scalars.md b/reference/src/layout/scalars.md index 7b647cbc..8170dfa9 100644 --- a/reference/src/layout/scalars.md +++ b/reference/src/layout/scalars.md @@ -10,9 +10,9 @@ layout `#[repr()]` flags. ## `bool` -Rust's `bool` has the same layout as C17's` _Bool`, that is, its size and -alignment are implementation-defined. Any `bool` can be cast into an integer, -taking on the values 1 (`true`) or 0 (`false`). +Rust's `bool` has the same layout as C17's` _Bool` which is +implementation-defined. Any `bool` can be cast into an integer, taking on the +values 1 (`true`) or 0 (`false`). > **Note**: on all platforms that Rust's currently supports, its size and > alignment are 1, and its ABI class is `INTEGER` - see [Rust Layout and ABIs]. From 5057e1a5c7aff5fb7e7d416efbe2f10dbf6e319b Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Tue, 23 Jul 2019 18:38:34 +0200 Subject: [PATCH 15/16] Update layout of pointers --- reference/src/layout/pointers.md | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/reference/src/layout/pointers.md b/reference/src/layout/pointers.md index 336651ef..9d965578 100644 --- a/reference/src/layout/pointers.md +++ b/reference/src/layout/pointers.md @@ -28,15 +28,18 @@ and are at least one word. ### Notes -The layouts of `&T`, `&mut T`, `*const T` and `*mut T` are the same. +The size, alignment, and call ABI of `&T`, `&mut T`, `*const T` and `*mut T` are +the same. -If `T` is sized, references and pointers to `T` have a size and alignment of one -word and have therefore the same layout as C pointers. +If `T` is sized, the size, alignment, and call ABI of references and pointers to +`T` is the same as that of C pointers. -> **warning**: while the layout of references and pointers is compatible with -> the layout of C pointers, references come with a _validity_ invariant that -> does not allow them to be used when they could be `NULL`, unaligned, dangling, -> or, in the case of `&mut T`, aliasing. +> **warning**: while the size, alignment, and call ABI of references and +> pointers is compatible with the layout of C pointers, references come with a +> _validity_ invariant that does not allow them to be used when they could be +> `NULL`, unaligned, dangling, or, in the case of `&mut T`, aliasing. Since the +> niches of references and pointers are not the same, these types are not +> layout-compatible with each other. We do not make any guarantees about the layout of multi-trait objects `&(dyn Trait1 + Trait2)` or references to other dynamically sized types, @@ -53,7 +56,7 @@ struct DynObject { > **note**: In the layout of `&dyn mut Trait` the field `data` is of the type `*mut u8`. -The layout of `&[T]` is the same as that of: +The size, alignment, and call ABI of `&[T]` and `&mut [T]` are the same as that of: ```rust #[repr(C)] struct Slice<T> { @@ -62,7 +65,11 @@ struct Slice<T> { } ``` -> **note**: In the layout of `&mut [T]` the field `ptr` is of the type `*mut T`. +> **note**: the field `ptr` is of the type `*mut T` for `&mut [T]`. -The layout of `&str` is the same as that of `&[u8]`, and the layout of `&mut str` is -the same as that of `&mut [u8]`. +The size, alignment, and call ABI of `&str` is the same as that of `&[u8]`, and +the layout of `&mut str` is the same as that of `&mut [u8]`. + +#### Unresolved question + +* Does `&str` have the same niches as `&[u8]` ? From 288441d30787f6222225b9fccff7f4f7e5aeb5a6 Mon Sep 17 00:00:00 2001 From: gnzlbg <gonzalobg88@gmail.com> Date: Tue, 23 Jul 2019 18:39:35 +0200 Subject: [PATCH 16/16] Update layout of function pointers --- reference/src/layout/function-pointers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/src/layout/function-pointers.md b/reference/src/layout/function-pointers.md index 3188fb05..e9fe4782 100644 --- a/reference/src/layout/function-pointers.md +++ b/reference/src/layout/function-pointers.md @@ -25,7 +25,7 @@ or the address of a function. ### Representation -The ABI and layout of `(unsafe)? (extern "ABI")? fn(Args...) -> Ret` +The size, alignment, and call ABI of `(unsafe)? (extern "ABI")? fn(Args...) -> Ret` is exactly that of the corresponding C type -- the lack of a null value does not change this. On common platforms, this means that `*const ()` and `fn(Args...) -> Ret` have