From 2920ca8d4c70eb63212c89adb6477e3bbd9295b7 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Mon, 27 Jul 2026 16:09:55 +0000 Subject: [PATCH 11/11] build: replace bool:N bitfields with uint8_t:N across the tree bool is 4 bytes on Darwin/PowerPC (GCC's -mone-byte-bool docs), and a plain enum's default underlying type is (at least) unsigned int everywhere. PowerPC's ABI allocates each bitfield's storage unit sized to match its declared base type, so any bool:N or plain-enum:N bitfield gets its own 4-byte unit there instead of packing into a shared byte with its neighbors -- breaking every size-sensitive struct using this pattern (struct attributes and bits_affecting_ascii_printer in terminal.h both have their own _Static_assert; client_data in client-protocol.h is wire-protocol data between footclient/foot --server with its own size assert; kitty_key_data in kitty-keymap.h likewise). Elsewhere (wayland.h, config.h) there's no hard size assertion, but the same fix keeps these structs at their intended, documented byte budget instead of silently ballooning on this target. uint8_t's size/alignment is 1 byte on every target, sidestepping both the Apple-specific bool quirk and the generic PowerPC bitfield-storage-unit rule. Named bitfield access (.sixels, .osc8, etc.) and the color_source enum values stored in fg_src/bg_src are unaffected; only the storage type changed. Bit-field allocation order differs between big-endian PowerPC and little-endian x86/ARM, but none of these fields are ever serialized or bit-picked by position -- only individual named-field access and whole-value (!=0/==0) comparisons are used, both of which are layout-independent. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01U6fuL1PtRJHhr97gAGyS1h --- client-protocol.h | 14 ++++- config.h | 24 ++++---- kitty-keymap.h | 7 ++- terminal.h | 136 +++++++++++++++++++++++++++------------------- wayland.h | 34 ++++++------ 5 files changed, 126 insertions(+), 89 deletions(-) diff --git a/client-protocol.h b/client-protocol.h index efd601d7..12a6f153 100644 --- a/client-protocol.h +++ b/client-protocol.h @@ -10,9 +10,17 @@ struct client_string { }; struct client_data { - bool hold:1; - bool no_wait:1; - bool xdga_token:1; + /* + * uint8_t, not bool: bool is 4 bytes on Darwin/PowerPC (see + * GCC's -mone-byte-bool docs), which combined with PowerPC's + * bitfield-storage-unit-matches-base-type rule would force each + * bool:1 into its own 4-byte unit instead of packing into the + * same byte as the other bitfields below, breaking the + * _Static_assert on struct size. + */ + uint8_t hold:1; + uint8_t no_wait:1; + uint8_t xdga_token:1; uint8_t reserved:5; uint8_t token_len; diff --git a/config.h b/config.h index f8e99df3..fe2fbede 100644 --- a/config.h +++ b/config.h @@ -184,12 +184,12 @@ struct color_theme { } search_box; struct { - bool cursor:1; - bool jump_label:1; - bool scrollback_indicator:1; - bool url:1; - bool search_box_no_match:1; - bool search_box_match:1; + uint8_t cursor:1; + uint8_t jump_label:1; + uint8_t scrollback_indicator:1; + uint8_t url:1; + uint8_t search_box_no_match:1; + uint8_t search_box_match:1; uint8_t dim; } use_custom; @@ -395,12 +395,12 @@ struct config { bool double_click_to_maximize; struct { - bool title_set:1; - bool buttons_set:1; - bool minimize_set:1; - bool maximize_set:1; - bool close_set:1; - bool border_set:1; + uint8_t title_set:1; + uint8_t buttons_set:1; + uint8_t minimize_set:1; + uint8_t maximize_set:1; + uint8_t close_set:1; + uint8_t border_set:1; uint32_t title; uint32_t buttons; uint32_t minimize; diff --git a/kitty-keymap.h b/kitty-keymap.h index 3420d01f..e5a21f40 100644 --- a/kitty-keymap.h +++ b/kitty-keymap.h @@ -8,7 +8,12 @@ struct kitty_key_data { xkb_keysym_t sym; uint16_t key; uint8_t final:7; - bool is_modifier:1; + /* + * uint8_t, not bool: bool is 4 bytes on Darwin/PowerPC, which + * would force this bitfield into its own storage unit instead of + * sharing a byte with final:7 above, breaking the size assert. + */ + uint8_t is_modifier:1; } __attribute__((packed)); _Static_assert(sizeof(struct kitty_key_data) == 7, "bad size"); diff --git a/terminal.h b/terminal.h index e6a992e3..7424e896 100644 --- a/terminal.h +++ b/terminal.h @@ -74,24 +74,36 @@ enum color_source { * misses) * * Note that the members are laid out optimized for x86 + * + * All single-bit members use uint8_t (not bool, not enum + * color_source) so they pack tightly into a single byte alongside + * the surrounding bitfields on every target: bool is 4 bytes on + * Darwin/PowerPC, and a plain enum's default underlying type is + * always (at least) `unsigned int`; PowerPC's ABI allocates each + * bitfield's storage unit sized to match its declared base type, so + * either would otherwise inflate this struct well past the + * asserted 8 bytes there. fg_src/bg_src still only ever hold + * enum color_source values (COLOR_DEFAULT et al); the field is + * declared uint8_t purely to control storage, not because the + * values stored are no longer semantically an enum color_source. */ struct attributes { - bool bold:1; - bool dim:1; - bool italic:1; - bool underline:1; - bool strikethrough:1; - bool blink:1; - bool conceal:1; - bool reverse:1; + uint8_t bold:1; + uint8_t dim:1; + uint8_t italic:1; + uint8_t underline:1; + uint8_t strikethrough:1; + uint8_t blink:1; + uint8_t conceal:1; + uint8_t reverse:1; uint32_t fg:24; - bool clean:1; - enum color_source fg_src:2; - enum color_source bg_src:2; - bool confined:1; - bool selected:1; - bool url:1; + uint8_t clean:1; + uint8_t fg_src:2; + uint8_t bg_src:2; + uint8_t confined:1; + uint8_t selected:1; + uint8_t url:1; uint32_t bg:24; }; static_assert(sizeof(struct attributes) == 8, "VT attribute struct too large"); @@ -442,12 +454,18 @@ struct terminal { void (*ascii_printer)(struct terminal *term, char32_t c); union { struct { - bool sixels:1; - bool osc8:1; - bool underline_style:1; - bool underline_color:1; - bool insert_mode:1; - bool charset:1; + /* + * uint8_t, not bool: bool is 4 bytes on Darwin/PowerPC, + * which would make this bitfield struct larger than + * uint8_t value below and break term_update_ascii_printer()'s + * _Static_assert. + */ + uint8_t sixels:1; + uint8_t osc8:1; + uint8_t underline_style:1; + uint8_t underline_color:1; + uint8_t insert_mode:1; + uint8_t charset:1; }; uint8_t value; } bits_affecting_ascii_printer; @@ -546,42 +564,48 @@ struct terminal { bool bell_action_enabled; bool report_theme_changes; - /* Saved DECSET modes - we save the SET state */ + /* + * Saved DECSET modes - we save the SET state. + * + * uint8_t, not bool, throughout: bool is 4 bytes on + * Darwin/PowerPC, which would force each bitfield into its own + * storage unit there instead of packing tightly. + */ struct { - bool origin:1; - bool application_cursor_keys:1; - bool application_keypad_keys:1; - bool reverse:1; - bool show_cursor:1; - bool reverse_wrap:1; - bool auto_margin:1; - bool cursor_blink:1; - bool bracketed_paste:1; - bool focus_events:1; - bool alt_scrolling:1; + uint8_t origin:1; + uint8_t application_cursor_keys:1; + uint8_t application_keypad_keys:1; + uint8_t reverse:1; + uint8_t show_cursor:1; + uint8_t reverse_wrap:1; + uint8_t auto_margin:1; + uint8_t cursor_blink:1; + uint8_t bracketed_paste:1; + uint8_t focus_events:1; + uint8_t alt_scrolling:1; //bool mouse_x10:1; - bool mouse_click:1; - bool mouse_drag:1; - bool mouse_motion:1; + uint8_t mouse_click:1; + uint8_t mouse_drag:1; + uint8_t mouse_motion:1; //bool mouse_utf8:1; - bool mouse_sgr:1; - bool mouse_urxvt:1; - bool mouse_sgr_pixels:1; - bool meta_eight_bit:1; - bool meta_esc_prefix:1; - bool num_lock_modifier:1; - bool bell_action_enabled:1; - bool alt_screen:1; - bool ime:1; - bool app_sync_updates:1; - bool grapheme_shaping:1; - bool report_theme_changes:1; - - bool size_notifications:1; - - bool sixel_display_mode:1; - bool sixel_private_palette:1; - bool sixel_cursor_right_of_graphics:1; + uint8_t mouse_sgr:1; + uint8_t mouse_urxvt:1; + uint8_t mouse_sgr_pixels:1; + uint8_t meta_eight_bit:1; + uint8_t meta_esc_prefix:1; + uint8_t num_lock_modifier:1; + uint8_t bell_action_enabled:1; + uint8_t alt_screen:1; + uint8_t ime:1; + uint8_t app_sync_updates:1; + uint8_t grapheme_shaping:1; + uint8_t report_theme_changes:1; + + uint8_t size_notifications:1; + + uint8_t sixel_display_mode:1; + uint8_t sixel_private_palette:1; + uint8_t sixel_cursor_right_of_graphics:1; } xtsave; bool window_title_has_been_set; @@ -810,9 +834,9 @@ struct terminal { int pan; int pad; - bool scrolling:1; /* Private mode 80 */ - bool use_private_palette:1; /* Private mode 1070 */ - bool cursor_right_of_graphics:1; /* Private mode 8452 */ + uint8_t scrolling:1; /* Private mode 80 */ + uint8_t use_private_palette:1; /* Private mode 1070 */ + uint8_t cursor_right_of_graphics:1; /* Private mode 8452 */ unsigned params[5]; /* Collected parameters, for RASTER, COLOR_SPEC */ unsigned param; /* Currently collecting parameter, for RASTER, COLOR_SPEC and REPEAT */ diff --git a/wayland.h b/wayland.h index 9cbd1023..681e8388 100644 --- a/wayland.h +++ b/wayland.h @@ -393,8 +393,8 @@ struct wl_window { } csd; struct { - bool maximize:1; - bool minimize:1; + uint8_t maximize:1; + uint8_t minimize:1; } wm_capabilities; struct wayl_sub_surface search; @@ -425,20 +425,20 @@ struct wl_window { struct { int width; int height; - bool is_activated:1; - bool is_fullscreen:1; - bool is_maximized:1; - bool is_resizing:1; + uint8_t is_activated:1; + uint8_t is_fullscreen:1; + uint8_t is_maximized:1; + uint8_t is_resizing:1; - bool is_tiled_top:1; - bool is_tiled_bottom:1; - bool is_tiled_left:1; - bool is_tiled_right:1; + uint8_t is_tiled_top:1; + uint8_t is_tiled_bottom:1; + uint8_t is_tiled_left:1; + uint8_t is_tiled_right:1; - bool is_constrained_top:1; - bool is_constrained_bottom:1; - bool is_constrained_left:1; - bool is_constrained_right:1; + uint8_t is_constrained_top:1; + uint8_t is_constrained_bottom:1; + uint8_t is_constrained_left:1; + uint8_t is_constrained_right:1; enum csd_mode csd_mode; } configure; @@ -514,9 +514,9 @@ struct wayland { /* WL_SHM >= 2 */ bool use_shm_release; - bool shm_have_argb2101010:1; - bool shm_have_abgr2101010:1; - bool shm_have_abgr161616:1; + uint8_t shm_have_argb2101010:1; + uint8_t shm_have_abgr2101010:1; + uint8_t shm_have_abgr161616:1; }; struct wayland *wayl_init( -- 2.43.0