From 030242d1b20c30e349d477f3b95d3b295468c7ce Mon Sep 17 00:00:00 2001 From: "kj4tmp@gmail.com" Date: Fri, 18 Oct 2024 00:52:56 -0700 Subject: [PATCH 1/5] langref: improve packed struct memory layout description --- doc/langref.html.in | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 225b98303b48..829a6b745120 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2180,16 +2180,20 @@ or Unlike normal structs, {#syntax#}packed{#endsyntax#} structs have guaranteed in-memory layout:

@@ -2200,8 +2204,7 @@ or {#code|test_packed_structs.zig#}

- The backing integer is inferred from the fields' total bit width. - Optionally, it can be explicitly provided and enforced at compile time: + The backing integer can be inferred or explicitly provided. When inferred it will be unsigned, and when explicitly provided, its bit count will be enforced at compile time:

{#code|test_missized_packed_struct.zig#} @@ -2248,9 +2251,6 @@ or {#code|test_packed_struct_equality.zig#}

- Using packed structs with {#link|volatile#} is problematic, and may be a compile error in the future. - For details on this subscribe to - this issue. TODO update these docs with a recommendation on how to use packed structs with MMIO (the use case for volatile packed structs) once this issue is resolved. Don't worry, there will be a good solution for this use case in zig. From d3f1e191239328b0343d831286f9b7eb308aea3f Mon Sep 17 00:00:00 2001 From: "kj4tmp@gmail.com" Date: Fri, 18 Oct 2024 21:11:48 -0700 Subject: [PATCH 2/5] fix missing end tag --- doc/langref.html.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 829a6b745120..f82973c3b768 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2186,9 +2186,9 @@ or having a maximum bit count of 65535, and the host endianness. On a big endian system, the first declared field will have the highest memory address. -

  • The backing integer has the same bit count as the fields' total bit width.
  • +
  • The backing integer has the same bit count as the fields' total bit width.
  • Field access and assignment can be understood as shorthand for bitshifts on the backing integer.
  • -
  • Integers will use exactly as many bits as they have. For example, a {#syntax#}u5{#endsyntax#} will use 5 bits of the backing integer. +
  • Integers will use exactly as many bits as they have. For example, a {#syntax#}u5{#endsyntax#} will use 5 bits of the backing integer.
  • {#syntax#}bool{#endsyntax#} fields use exactly 1 bit.
  • An {#link|enum#} field uses exactly the bit width of its integer tag type.
  • A {#link|packed union#} field uses exactly the bit width of the union field with From 6c330beb093f4862647301d24608889b22a9a614 Mon Sep 17 00:00:00 2001 From: "kj4tmp@gmail.com" Date: Fri, 18 Oct 2024 21:59:16 -0700 Subject: [PATCH 3/5] cleanup tense --- doc/langref.html.in | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index f82973c3b768..b71e44da9b0b 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2186,14 +2186,16 @@ or having a maximum bit count of 65535, and the host endianness. On a big endian system, the first declared field will have the highest memory address.
  • -
  • The backing integer has the same bit count as the fields' total bit width.
  • +
  • The backing integer has the same bit width as the fields' total bit width.
  • Field access and assignment can be understood as shorthand for bitshifts on the backing integer.
  • -
  • Integers will use exactly as many bits as they have. For example, a {#syntax#}u5{#endsyntax#} will use 5 bits of the backing integer.
  • -
  • {#syntax#}bool{#endsyntax#} fields use exactly 1 bit.
  • +
  • An {#link|integer|Integers#} field uses exactly as many bits as its bit width. For example, a {#syntax#}u5{#endsyntax#} will use 5 bits of the backing integer.
  • +
  • A {#link|bool|Primitive Types#} field uses exactly 1 bit.
  • An {#link|enum#} field uses exactly the bit width of its integer tag type.
  • A {#link|packed union#} field uses exactly the bit width of the union field with the largest bit width.
  • -
  • Packed structs, when they themselves are within a packed struct, will only use as many bits as their backing integer.
  • +
  • A {#syntax#}packed struct{#endsyntax#} field, when within a {#syntax#}packed struct{#endsyntax#}, uses exactly the bit width of its backing integer. For example, + a {#syntax#}packed struct{#endsyntax#} field having backing integer {#syntax#}u17{#endsyntax#} uses 17 bits of its parent's backing integer. +
  • Packed structs support equality operators.
  • From ac46d810a31f0db8a48f99cd321acd298ed961be Mon Sep 17 00:00:00 2001 From: "kj4tmp@gmail.com" Date: Fri, 18 Oct 2024 23:28:05 -0700 Subject: [PATCH 4/5] add MMIO example --- doc/langref.html.in | 8 +++++--- doc/langref/packed_struct_mmio.zig | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 doc/langref/packed_struct_mmio.zig diff --git a/doc/langref.html.in b/doc/langref.html.in index b71e44da9b0b..917a1d08ca80 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2253,9 +2253,11 @@ or {#code|test_packed_struct_equality.zig#}

    - TODO update these docs with a recommendation on how to use packed structs with MMIO - (the use case for volatile packed structs) once this issue is resolved. - Don't worry, there will be a good solution for this use case in zig. + Packed structs can be used to interact with memory-mapped input-output (MMIO), which is + common in embedded applications. A pointer of the correct alignment and address to a packed struct + can be constructed to faciltiate manipulation of bit-packed registers without arduous bitshifting. + + {#code|packed_struct_mmio.zig#}

    {#header_close#} diff --git a/doc/langref/packed_struct_mmio.zig b/doc/langref/packed_struct_mmio.zig new file mode 100644 index 000000000000..79236a76eaec --- /dev/null +++ b/doc/langref/packed_struct_mmio.zig @@ -0,0 +1,16 @@ +pub const GPIORegister = packed struct(u8) { + GPIO0: bool, + GPIO1: bool, + GPIO2: bool, + GPIO3: bool, + _reserved: u4 = 0, +}; + +/// Write a new state to the memory-mapped IO. +pub fn writeToGPIO(new_states: GPIORegister) void { + const gpio_register_address = 0x0123; + const raw_ptr: *align(1) volatile GPIORegister = @ptrFromInt(gpio_register_address); + raw_ptr.* = new_states; +} + +// syntax From af40751d5d10d7765c2062a685ff4a08516eaa70 Mon Sep 17 00:00:00 2001 From: "kj4tmp@gmail.com" Date: Sat, 19 Oct 2024 00:05:35 -0700 Subject: [PATCH 5/5] inferred vs explicitly provided backing integer --- doc/langref.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 917a1d08ca80..3d461ddc8455 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2206,7 +2206,7 @@ or {#code|test_packed_structs.zig#}

    - The backing integer can be inferred or explicitly provided. When inferred it will be unsigned, and when explicitly provided, its bit count will be enforced at compile time: + The backing integer can be inferred or explicitly provided. When inferred, it will be unsigned. When explicitly provided, its bit width will be enforced at compile time to exactly match the total bit width of the fields:

    {#code|test_missized_packed_struct.zig#}