bin/sdcc -v
SDCC : mcs51/z80/z180/r2k/r2ka/r3ka/r4k/r5k/r6k/sm83/tlcs90/ez80/z80n/r800/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8/pdk13/pdk14/pdk15/mos6502/mos65c02/f8/f8l TD- 4.6.2 #16701 (Linux)
Getting a codegen error on sm83/gbz80 for array indexing with a bool that is bit packed in a struct. Instead of generating a lookup for [1] with true it generates [-1].
Building with:
sdcc -msm83 --no-std-crt0 --fsigned-char --use-stdout -Wa-pogn -c main.c -o main.o
Test case:
#define true ((_Bool)+1)
#define false ((_Bool)+0)
#define bool _Bool
#define __bool_true_false_are_defined 1
#define ICON_CBX "\x18"
#define ICON_CBX_CHECKED "\x19"
typedef struct test_options_t {
bool print_fast : 1;
bool fancy_sgb_border : 1;
bool show_grid : 1;
bool save_confirm : 1;
bool ir_remote_shutter : 1;
bool boot_to_camera_mode : 1;
bool double_speed : 1;
unsigned char shutter_timer;
} test_options_t;
test_options_t test_state;
unsigned char text_buffer_test[4];
const unsigned char * const checkbox[] = {ICON_CBX, ICON_CBX_CHECKED};
void test_array_index_bitpacked_struct_bool(void) {
unsigned char * temp = checkbox[test_state.save_confirm];
*text_buffer_test = *temp;
}
void main(void) {
test_state.save_confirm = true;
test_array_index_bitpacked_struct_bool();
test_state.save_confirm = false;
test_array_index_bitpacked_struct_bool();
}
The relevant output (sm83, but the equivalent z80 output has a similar issue):
_test_array_index_bitpacked_struct_bool::
;main.c:28: unsigned char * temp = checkbox[test_state.save_confirm];
ld bc, #_checkbox+0
ld a, (#_test_state + 0)
swap a
rlca
rra
sbc a, a
ld l, a
rlca
sbc a, a
ld h, a
add hl, hl <-- This ends up being 0xFFFE
add hl, bc <-- Indexing to [-1] instead of [1] here
ld a, (hl+)
Given what it is trying to do, the intended output for the calculation should maybe look more like:
swap a
sla a
ld h, a
rlca
ld h, a
For reference, here is the SDCC ~15267 output that produces a correct index:
ld bc, #_checkbox+0
ld a, (#_test_state + 0)
swap a
rlca
and a, #0x01
ld l, a
ld h, #0x00
add hl, hl
add hl, bc
ld a, (hl+)
yes, this bug is pretty annoying :(
This could potentially be a side effect of [r16144] which intended to make plain
intbit-fields signed to mimic GCC behavior.The change has no special case for
bool.Related
Commit: [r16144]
The change wasn't to mimic GCC; it was because there is simply no reasonable way to make unsigned-by-default int bit-fields work with the C standard. See C defect report 315, C issue 1007, and in particular the discussion at the August 2025 WG14 meeting in Brno (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3815.htm).
Despite the C standard at first sight allowing plain int to be unsigned, trying to actually do so runs into serious issues in particular wrt.
typedefandtypeof.But how does that relate to bool?
That was a change in handling signedness of int bit-fields, this bug is about z80 codegen incorrectly treating bool bit-fields as signed. Might be related or not (not worth looking into more, I'll have a fix later today without looking into the history of this issue anyway).
I can reproduce the issue on my Debian GNU/Linux amd64 testing system. Looks like all z80-related ports are affected, but no other ports.
Fixed in [r16777].
Related
Commit: [r16777]
Thanks, fix looks good here