From 54264237dfe4389352e76b1ebaf20af36fb30bcb Mon Sep 17 00:00:00 2001 From: Kinsey Favre Date: Sat, 22 Feb 2020 12:32:09 -0600 Subject: [PATCH 1/4] Fix incorrect pseudocode for #[repr(C)] struct alignment --- src/type-layout.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/type-layout.md b/src/type-layout.md index f6c9ca77e..dd3d58d3f 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -205,14 +205,18 @@ for field in struct.fields_in_declaration_order() { // Increase the current offset so that it's a multiple of the alignment // of this field. For the first field, this will always be zero. // The skipped bytes are called padding bytes. - current_offset += field.alignment % current_offset; + // + // padding_needed_for() is equivalent to + // std::alloc::Layout::padding_needed_for(), but takes an integer rather + // than a Layout as the first argument. + current_offset += padding_needed_for(current_offset, field.alignment); struct[field].offset = current_offset; current_offset += field.size; } -struct.size = current_offset + current_offset % struct.alignment; +struct.size = current_offset + padding_needed_for(current_offset, struct.alignment); ``` > Note: This algorithm can produce zero-sized structs. This differs from From bc5c540419ea98cef349a7869d0d32ef633ebce2 Mon Sep 17 00:00:00 2001 From: Kinsey Favre Date: Mon, 24 Feb 2020 08:57:34 -0600 Subject: [PATCH 2/4] Explicitly describe padding algorithm in pseudocode --- src/type-layout.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/type-layout.md b/src/type-layout.md index dd3d58d3f..7979905f0 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -197,6 +197,17 @@ Here is this algorithm described in pseudocode. ```rust,ignore +fn padding_needed_for(offset: usize, alignment: usize) -> usize { + let misalignment = offset % alignment; + if misalignment > 0 { + // round up to next multiple of `alignment` + alignment - misalignment + } else { + // already a multiple of `alignment` + 0 + } +} + struct.alignment = struct.fields().map(|field| field.alignment).max(); let current_offset = 0; @@ -205,10 +216,6 @@ for field in struct.fields_in_declaration_order() { // Increase the current offset so that it's a multiple of the alignment // of this field. For the first field, this will always be zero. // The skipped bytes are called padding bytes. - // - // padding_needed_for() is equivalent to - // std::alloc::Layout::padding_needed_for(), but takes an integer rather - // than a Layout as the first argument. current_offset += padding_needed_for(current_offset, field.alignment); struct[field].offset = current_offset; From 13e415a71c7e725a4ef32b397d338c83d7f5a9c8 Mon Sep 17 00:00:00 2001 From: Kinsey Favre Date: Mon, 24 Feb 2020 09:58:27 -0600 Subject: [PATCH 3/4] Add warning for #[repr(C)] struct alignment pseudocode --- src/type-layout.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/type-layout.md b/src/type-layout.md index 7979905f0..c572f1efe 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -226,6 +226,14 @@ for field in struct.fields_in_declaration_order() { struct.size = current_offset + padding_needed_for(current_offset, struct.alignment); ``` +
+ +Warning: This pseudocode uses a naive algorithm that ignores overflow issues for +the sake of clarity. To perform memory layout computations in actual code, use +[`Layout`]. + +
+ > Note: This algorithm can produce zero-sized structs. This differs from > C where structs without data still have a size of one byte. @@ -374,3 +382,4 @@ used with any other representation. [`C`]: #the-c-representation [primitive representations]: #primitive-representations [`transparent`]: #the-transparent-representation +[`Layout`]: ../std/alloc/struct.Layout.html From 5d5b233a13100bbde50f7b66652956c86bbb82df Mon Sep 17 00:00:00 2001 From: Kinsey Favre Date: Mon, 24 Feb 2020 10:11:49 -0600 Subject: [PATCH 4/4] Add doc comment for padding_needed_for fn in pseudocode --- src/type-layout.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/type-layout.md b/src/type-layout.md index c572f1efe..967c9ed1e 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -197,6 +197,8 @@ Here is this algorithm described in pseudocode. ```rust,ignore +/// Returns the amount of padding needed after `offset` to ensure that the +/// following address will be aligned to `alignment`. fn padding_needed_for(offset: usize, alignment: usize) -> usize { let misalignment = offset % alignment; if misalignment > 0 {