From 380c3f810e87ab2ee26af7d4196e1d036dd08e1b Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Thu, 5 Mar 2026 18:38:34 +0100 Subject: [PATCH 1/2] Fix an invalid transformation by the optimizer. Introduced by #2811. --- src/cc65/coptmisc.c | 17 ++++++++++------- test/val/bug2937.c | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 test/val/bug2937.c diff --git a/src/cc65/coptmisc.c b/src/cc65/coptmisc.c index deca3fbe5..b9a018899 100644 --- a/src/cc65/coptmisc.c +++ b/src/cc65/coptmisc.c @@ -1213,21 +1213,24 @@ unsigned OptTosPushPop (CodeSeg* S) /* Get the next entry */ const CodeEntry* E = CS_GetEntry (S, I); - /* Check for decspn, incspn, subysp or addysp */ + /* Check for pushax/popax */ if (CE_IsCallTo (E, "pushax") && (N = CS_GetNextEntry (S, I)) != 0 && (CE_IsCallTo (N, "popax") || CE_IsJumpTo (N, "popax")) && !CE_HasLabel (N)) { - /* Insert an rts if jmp popax */ if (N->OPC == OP65_JMP) { - CodeEntry* X = NewCodeEntry (OP65_RTS, AM65_IMP, 0, 0, E->LI); - CS_InsertEntry (S, X, I); + /* If we jumped to popax instead of calling it as a subroutine, + ** add an RTS before removing the sequence. + */ + CodeEntry* X = NewCodeEntry (OP65_RTS, AM65_IMP, 0, 0, E->LI); + CS_InsertEntry (S, X, I); + CS_DelEntries (S, I+1, 2); + } else { + /* Otherwise just remove the sequence */ + CS_DelEntries (S, I, 2); } - /* Delete the old code */ - CS_DelEntries (S, I+1, 2); - /* Remember we had changes */ ++Changes; diff --git a/test/val/bug2937.c b/test/val/bug2937.c new file mode 100644 index 000000000..57f6e927c --- /dev/null +++ b/test/val/bug2937.c @@ -0,0 +1,27 @@ +/* Note: This test is rather fragile since it depends on how the compiler +** handles certain sequences and return codes. It checks for exactly one +** optimizer problem introduced in #2937. If it fails in some future version, +** do not hesitate to remove it. +*/ + +#include + +static unsigned char test(unsigned v) +{ + (void)v; + asm("jsr popax"); + asm("lda #0"); + return __A__; +} + +int main(void) +{ + if (test(1)) { + printf("Test failed\n"); + return 1; + } else { + printf("Test ok\n"); + return 0; + } +} + From 3d26a7e1febc0abed859b21c3ea1cc059f04d24e Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Thu, 5 Mar 2026 18:44:33 +0100 Subject: [PATCH 2/2] Correct test name and test comment. --- test/val/{bug2937.c => bug2811.c} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename test/val/{bug2937.c => bug2811.c} (88%) diff --git a/test/val/bug2937.c b/test/val/bug2811.c similarity index 88% rename from test/val/bug2937.c rename to test/val/bug2811.c index 57f6e927c..8f0ff2e48 100644 --- a/test/val/bug2937.c +++ b/test/val/bug2811.c @@ -1,6 +1,6 @@ /* Note: This test is rather fragile since it depends on how the compiler ** handles certain sequences and return codes. It checks for exactly one -** optimizer problem introduced in #2937. If it fails in some future version, +** optimizer problem introduced in #2811. If it fails in some future version, ** do not hesitate to remove it. */