From b8889bf37ecffce7946917bb6291d983fcc2d0ce Mon Sep 17 00:00:00 2001 From: jede Date: Fri, 23 Oct 2020 23:47:30 +0200 Subject: [PATCH 01/80] Now getchar works --- libsrc/telestrat/read.s | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/libsrc/telestrat/read.s b/libsrc/telestrat/read.s index 76de9d0ac..0782c4d21 100644 --- a/libsrc/telestrat/read.s +++ b/libsrc/telestrat/read.s @@ -8,21 +8,33 @@ .include "zeropage.inc" .include "telestrat.inc" + .include "fcntl.inc" ;int read (int fd, void* buf, unsigned count); .proc _read - sta ptr1 ; count - stx ptr1+1 ; count - jsr popax ; get buf + sta ptr1 ; count + stx ptr1+1 ; count + jsr popax ; get buf sta PTR_READ_DEST stx PTR_READ_DEST+1 - sta ptr2 ; in order to calculate nb of bytes read + sta ptr2 ; in order to calculate nb of bytes read stx ptr2+1 ; - ; jsr popax ; fp pointer don't care in this version + jsr popax ; fp pointer don't care in this version + cpx #$00 + bne @is_not_stdin + cmp #STDIN_FILENO + bne @is_not_stdin + ; stdin +@L1: + BRK_TELEMON XRD0 ; waits until key is pressed + bcs @L1 + + rts +@is_not_stdin: lda ptr1 ; ldy ptr1+1 ; BRK_TELEMON XFREAD ; calls telemon30 routine From 02e52fe24df3fabc16c4eadb452a2839d0feefc1 Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 1 Mar 2021 22:33:12 +0100 Subject: [PATCH 02/80] Fix many bugs --- include/telestrat.h | 2 ++ libsrc/telestrat/cclear.s | 4 +-- libsrc/telestrat/chline.s | 40 +++++++++++++-------- libsrc/telestrat/clrscr.s | 27 ++++++++------- libsrc/telestrat/cputc.s | 67 ++++++++++++++++++++++++++++++------ libsrc/telestrat/gotox.s | 4 --- libsrc/telestrat/gotoxy.s | 17 +++------ libsrc/telestrat/textcolor.s | 3 +- 8 files changed, 109 insertions(+), 55 deletions(-) diff --git a/include/telestrat.h b/include/telestrat.h index a4648a3dc..5ad1d3bef 100644 --- a/include/telestrat.h +++ b/include/telestrat.h @@ -85,6 +85,8 @@ #define CH_LTEE '+' #define CH_RTEE '+' #define CH_CROSS '+' +#define CH_HLINE '-' +#define CH_VLINE '|' #define CH_CURS_UP 11 #define CH_CURS_DOWN 10 #define CH_CURS_LEFT 8 diff --git a/libsrc/telestrat/cclear.s b/libsrc/telestrat/cclear.s index a32919962..b9fce4708 100644 --- a/libsrc/telestrat/cclear.s +++ b/libsrc/telestrat/cclear.s @@ -6,7 +6,7 @@ ; .export _cclearxy, _cclear - .import update_adscr + .import update_adscr, display_conio .importzp tmp1 .import popax @@ -27,7 +27,7 @@ _cclear: @L1: stx tmp1 ; Save X lda #' ' ; Erase current char - BRK_TELEMON XFWR + jsr display_conio ldx tmp1 dex bne @L1 diff --git a/libsrc/telestrat/chline.s b/libsrc/telestrat/chline.s index 6ead10eee..91f3bdc9f 100644 --- a/libsrc/telestrat/chline.s +++ b/libsrc/telestrat/chline.s @@ -1,22 +1,34 @@ ; -; jede jede@oric.org 2018-04-17 -; - +; void chlinexy (unsigned char x, unsigned char y, unsigned char length); ; void chline (unsigned char length); ; - .export _chline + .export _chlinexy, _chline + + .import rvs, display_conio, update_adscr + .import popax + .include "telestrat.inc" - .include "zeropage.inc" -.proc _chline - sta tmp1 -@loop: - lda #'-' ; horizontal line screen code - BRK_TELEMON XWR0 ; macro send char to screen (channel 0 in telemon terms) - dec tmp1 - bne @loop - rts -.endproc +_chlinexy: + pha ; Save the length + jsr popax ; Get X and Y + sta SCRY ; Store Y + stx SCRX ; Store X + jsr update_adscr + pla ; Restore the length and run into _chline + +_chline: + tax ; Is the length zero? + beq @L9 ; Jump if done +@L1: + lda #'-' ; Horizontal line screen code + ora rvs + + jsr display_conio + +@L2: dex + bne @L1 +@L9: rts diff --git a/libsrc/telestrat/clrscr.s b/libsrc/telestrat/clrscr.s index 39c2f7724..363aa2761 100644 --- a/libsrc/telestrat/clrscr.s +++ b/libsrc/telestrat/clrscr.s @@ -3,7 +3,7 @@ ; .export _clrscr - .import OLD_CHARCOLOR, OLD_BGCOLOR + .import OLD_CHARCOLOR, OLD_BGCOLOR, BGCOLOR, CHARCOLOR .include "telestrat.inc" @@ -23,22 +23,25 @@ ; reset prompt position - lda #<(SCREEN+40) - sta ADSCRL - lda #>(SCREEN+40) - sta ADSCRH + lda #<(SCREEN) + sta ADSCR + lda #>(SCREEN) + sta ADSCR+1 + + lda #$00 + sta SCRDY ; reset display position - ldx #$01 + ldx #$00 stx SCRY - dex stx SCRX - ; At this step X is equal to $00 - dex - ; At this step X is equal to $FF - stx OLD_BGCOLOR + stx OLD_BGCOLOR ; black + stx BGCOLOR + + ldx #$07 ; white stx OLD_CHARCOLOR - + stx CHARCOLOR + rts .endproc diff --git a/libsrc/telestrat/cputc.s b/libsrc/telestrat/cputc.s index 38f8af84b..a1ab145c2 100644 --- a/libsrc/telestrat/cputc.s +++ b/libsrc/telestrat/cputc.s @@ -4,24 +4,50 @@ ; void cputc (char c); ; - .export _cputc, CHARCOLOR, OLD_CHARCOLOR, BGCOLOR, OLD_BGCOLOR + .export _cputc, _cputcxy, display_conio, CHARCOLOR, OLD_CHARCOLOR, BGCOLOR, OLD_BGCOLOR + + + .import update_adscr + .import popax .include "telestrat.inc" +_cputcxy: + pha ; Save C + jsr popax ; Get X and Y + sta SCRY ; Store Y + stx SCRX ; Store X + jsr update_adscr + pla + .proc _cputc + cmp #$0D + bne @not_CR + ldy #$00 + sty SCRX + rts +@not_CR: + cmp #$0A + bne @not_LF + + inc SCRY + jmp update_adscr + + +@not_LF: + ldx CHARCOLOR cpx OLD_CHARCOLOR beq do_not_change_color_foreground stx OLD_CHARCOLOR ; Store CHARCOLOR into OLD_CHARCOLOR - dec SCRX - dec SCRX pha txa ; Swap X to A because, X contains CHARCOLOR - BRK_TELEMON XFWR ; Change color on the screen (foreground) - inc SCRX + + jsr display_conio + pla do_not_change_color_foreground: @@ -31,18 +57,38 @@ do_not_change_color_foreground: stx OLD_BGCOLOR - dec SCRX ; Dec SCRX in order to place attribute before the right position - pha txa ; Swap X to A because, X contains BGCOLOR - ORA #%00010000 ; Add 16 because background color is an attribute between 16 and 23. 17 is red background for example - BRK_TELEMON XFWR ; Change color on the screen (background) + ora #%00010000 ; Add 16 because background color is an attribute between 16 and 23. 17 is red background for example + + jsr display_conio pla do_not_change_color: - BRK_TELEMON XFWR ; Macro send char to screen (channel 0) + ; it continues to display_conio + +.endproc + + + +.proc display_conio + ldy SCRX + sta (ADSCR),y + iny + cpy #SCREEN_XSIZE + bne @no_inc + ldy #$00 + sty SCRX + + jmp update_adscr + +@no_inc: + sty SCRX rts .endproc + + + .bss CHARCOLOR: .res 1 @@ -52,3 +98,4 @@ BGCOLOR: .res 1 OLD_BGCOLOR: .res 1 + diff --git a/libsrc/telestrat/gotox.s b/libsrc/telestrat/gotox.s index 7a172071c..72004bc0a 100644 --- a/libsrc/telestrat/gotox.s +++ b/libsrc/telestrat/gotox.s @@ -8,9 +8,5 @@ .proc _gotox sta SCRX - - lda #$FF - sta OLD_CHARCOLOR - sta OLD_BGCOLOR rts .endproc diff --git a/libsrc/telestrat/gotoxy.s b/libsrc/telestrat/gotoxy.s index 3387efe40..ea7ed5623 100644 --- a/libsrc/telestrat/gotoxy.s +++ b/libsrc/telestrat/gotoxy.s @@ -29,30 +29,23 @@ gotoxy: jsr popa ; Get Y .endproc .proc update_adscr -; Force to set again color if cursor moves -; $FF is used because we know that it's impossible to have this value with a color -; It prevents a bug : If bgcolor or textcolor is set to black for example with no char displays, -; next cputsxy will not set the attribute if y coordinate changes - lda #$FF - sta OLD_CHARCOLOR - sta OLD_BGCOLOR lda #SCREEN - sta ADSCRH + sta ADSCR+1 ldy SCRY beq out loop: - lda ADSCRL + lda ADSCR clc adc #SCREEN_XSIZE bcc skip - inc ADSCRH + inc ADSCR+1 skip: - sta ADSCRL + sta ADSCR dey bne loop out: diff --git a/libsrc/telestrat/textcolor.s b/libsrc/telestrat/textcolor.s index 7d16c9e19..d851aaaab 100644 --- a/libsrc/telestrat/textcolor.s +++ b/libsrc/telestrat/textcolor.s @@ -2,12 +2,13 @@ ; .export _textcolor - .import CHARCOLOR + .import CHARCOLOR, OLD_CHARCOLOR .include "telestrat.inc" .proc _textcolor ldx CHARCOLOR ; Get previous color sta CHARCOLOR + stx OLD_CHARCOLOR txa ; Return previous color rts .endproc From 256b22f1c7017f5f30c3e6046cf4e641825788ef Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 1 Mar 2021 22:36:09 +0100 Subject: [PATCH 03/80] Add bordercolor and cvline --- libsrc/telestrat/bordercolor.s | 15 ++++++++++++++ libsrc/telestrat/cvline.s | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 libsrc/telestrat/bordercolor.s create mode 100644 libsrc/telestrat/cvline.s diff --git a/libsrc/telestrat/bordercolor.s b/libsrc/telestrat/bordercolor.s new file mode 100644 index 000000000..7055e6ba9 --- /dev/null +++ b/libsrc/telestrat/bordercolor.s @@ -0,0 +1,15 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; unsigned char __fastcall__ bordercolor (unsigned char color); +; + + + .export _bordercolor + + .include "telestrat.inc" + +_bordercolor: + ; Nothing to do + ; Oric can't handle his border + rts \ No newline at end of file diff --git a/libsrc/telestrat/cvline.s b/libsrc/telestrat/cvline.s new file mode 100644 index 000000000..159eb9d27 --- /dev/null +++ b/libsrc/telestrat/cvline.s @@ -0,0 +1,36 @@ +; +; Ullrich von Bassewitz, 2003-04-13 +; +; void cvlinexy (unsigned char x, unsigned char y, unsigned char length); +; void cvline (unsigned char length); +; + + .export _cvlinexy, _cvline + + .import rvs, display_conio, update_adscr + + .import popax + + .include "telestrat.inc" + + +_cvlinexy: + pha ; Save the length + jsr popax ; Get X and Y + sta SCRY ; Store Y + stx SCRX ; Store X + jsr update_adscr + pla ; Restore the length and run into _cvline + +_cvline: + tax ; Is the length zero? + beq @L9 ; Jump if done +@L1: + lda #'|' + ora rvs + jsr display_conio +@L2: dex + bne @L1 +@L9: rts + + From 8ec6d28f92d50703f365fac57fa4b95d12f39c74 Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 1 Mar 2021 22:44:06 +0100 Subject: [PATCH 04/80] Revert read.s --- libsrc/telestrat/read.s | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/libsrc/telestrat/read.s b/libsrc/telestrat/read.s index 0782c4d21..76de9d0ac 100644 --- a/libsrc/telestrat/read.s +++ b/libsrc/telestrat/read.s @@ -8,33 +8,21 @@ .include "zeropage.inc" .include "telestrat.inc" - .include "fcntl.inc" ;int read (int fd, void* buf, unsigned count); .proc _read - sta ptr1 ; count - stx ptr1+1 ; count - jsr popax ; get buf + sta ptr1 ; count + stx ptr1+1 ; count + jsr popax ; get buf sta PTR_READ_DEST stx PTR_READ_DEST+1 - sta ptr2 ; in order to calculate nb of bytes read + sta ptr2 ; in order to calculate nb of bytes read stx ptr2+1 ; - jsr popax ; fp pointer don't care in this version - cpx #$00 - bne @is_not_stdin - cmp #STDIN_FILENO - bne @is_not_stdin - ; stdin -@L1: - BRK_TELEMON XRD0 ; waits until key is pressed - bcs @L1 - - rts + ; jsr popax ; fp pointer don't care in this version -@is_not_stdin: lda ptr1 ; ldy ptr1+1 ; BRK_TELEMON XFREAD ; calls telemon30 routine From abef6566e7feaac9287a75b2a3bc177dc7fa3c3f Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 1 Mar 2021 22:45:05 +0100 Subject: [PATCH 05/80] Add revers.s --- libsrc/telestrat/revers.s | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 libsrc/telestrat/revers.s diff --git a/libsrc/telestrat/revers.s b/libsrc/telestrat/revers.s new file mode 100644 index 000000000..ad3e1f909 --- /dev/null +++ b/libsrc/telestrat/revers.s @@ -0,0 +1,37 @@ +; +; Ullrich von Bassewitz, 07.08.1998 +; +; unsigned char revers (unsigned char onoff); +; + + .export _revers + .export rvs + +; ------------------------------------------------------------------------ +; + +.code +.proc _revers + + ldx #$00 ; Assume revers off + tay ; Test onoff + beq L1 ; Jump if off + ldx #$80 ; Load on value + ldy #$00 ; Assume old value is zero +L1: lda rvs ; Load old value + stx rvs ; Set new value + beq L2 ; Jump if old value zero + iny ; Make old value = 1 +L2: ldx #$00 ; Load high byte of result + tya ; Load low byte, set CC + rts + +.endproc + +; ------------------------------------------------------------------------ +; + +.bss +rvs: .res 1 + + From 185c4510005f974980a4725d03c097b0c5d244f5 Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 1 Mar 2021 23:19:30 +0100 Subject: [PATCH 06/80] Fix cputdirect --- libsrc/telestrat/cputc.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsrc/telestrat/cputc.s b/libsrc/telestrat/cputc.s index a1ab145c2..f7bf5e2b6 100644 --- a/libsrc/telestrat/cputc.s +++ b/libsrc/telestrat/cputc.s @@ -4,7 +4,7 @@ ; void cputc (char c); ; - .export _cputc, _cputcxy, display_conio, CHARCOLOR, OLD_CHARCOLOR, BGCOLOR, OLD_BGCOLOR + .export _cputc, _cputcxy, cputdirect, display_conio, CHARCOLOR, OLD_CHARCOLOR, BGCOLOR, OLD_BGCOLOR .import update_adscr @@ -12,6 +12,7 @@ .include "telestrat.inc" +cputdirect: _cputcxy: pha ; Save C jsr popax ; Get X and Y @@ -69,9 +70,8 @@ do_not_change_color: .endproc - - .proc display_conio + ; This routine is used to displays char on screen ldy SCRX sta (ADSCR),y iny From cdbe23c351658d2e2f874ee8dfcbb70e87ebc6f3 Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 1 Mar 2021 23:21:58 +0100 Subject: [PATCH 07/80] Fix missing new line in bordercolr --- libsrc/telestrat/bordercolor.s | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsrc/telestrat/bordercolor.s b/libsrc/telestrat/bordercolor.s index 7055e6ba9..9e49b057f 100644 --- a/libsrc/telestrat/bordercolor.s +++ b/libsrc/telestrat/bordercolor.s @@ -12,4 +12,5 @@ _bordercolor: ; Nothing to do ; Oric can't handle his border - rts \ No newline at end of file + rts + From 872739b5f4d9c91137f49f6a99f27493b6b72bc1 Mon Sep 17 00:00:00 2001 From: jede Date: Wed, 3 Mar 2021 22:14:29 +0100 Subject: [PATCH 08/80] Fix comments, return line and bordercolor return --- include/telestrat.h | 6 ++++++ libsrc/telestrat/bordercolor.s | 5 +---- libsrc/telestrat/clrscr.s | 8 ++++---- libsrc/telestrat/cputc.s | 15 ++++++--------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/telestrat.h b/include/telestrat.h index 5ad1d3bef..465517f30 100644 --- a/include/telestrat.h +++ b/include/telestrat.h @@ -121,3 +121,9 @@ void shoot(); void explode(); void kbdclick1(); + +/* The following #defines will cause the matching functions calls in conio.h +** to be overlaid by macros with the same names, saving the function call +** overhead. +*/ +#define _bordercolor(color) COLOR_BLACK diff --git a/libsrc/telestrat/bordercolor.s b/libsrc/telestrat/bordercolor.s index 9e49b057f..84e167bc9 100644 --- a/libsrc/telestrat/bordercolor.s +++ b/libsrc/telestrat/bordercolor.s @@ -9,8 +9,5 @@ .include "telestrat.inc" -_bordercolor: - ; Nothing to do - ; Oric can't handle his border - rts +_bordercolor := return0 diff --git a/libsrc/telestrat/clrscr.s b/libsrc/telestrat/clrscr.s index 363aa2761..c02c26647 100644 --- a/libsrc/telestrat/clrscr.s +++ b/libsrc/telestrat/clrscr.s @@ -23,9 +23,9 @@ ; reset prompt position - lda #<(SCREEN) + lda #(SCREEN) + lda #>SCREEN sta ADSCR+1 lda #$00 @@ -36,10 +36,10 @@ stx SCRY stx SCRX - stx OLD_BGCOLOR ; black + stx OLD_BGCOLOR ; Black stx BGCOLOR - ldx #$07 ; white + ldx #$07 ; White stx OLD_CHARCOLOR stx CHARCOLOR diff --git a/libsrc/telestrat/cputc.s b/libsrc/telestrat/cputc.s index aa756aaf5..994a2b9d4 100644 --- a/libsrc/telestrat/cputc.s +++ b/libsrc/telestrat/cputc.s @@ -4,7 +4,8 @@ ; void cputc (char c); ; - .export _cputc, _cputcxy, cputdirect, display_conio, CHARCOLOR, OLD_CHARCOLOR, BGCOLOR, OLD_BGCOLOR + .export _cputc, _cputcxy, cputdirect, display_conio + .export CHARCOLOR, OLD_CHARCOLOR, BGCOLOR, OLD_BGCOLOR .import update_adscr @@ -14,10 +15,10 @@ cputdirect: _cputcxy: - pha ; Save C - jsr popax ; Get X and Y - sta SCRY ; Store Y - stx SCRX ; Store X + pha ; Save C + jsr popax ; Get X and Y + sta SCRY ; Store Y + stx SCRX ; Store X jsr update_adscr pla @@ -34,9 +35,7 @@ _cputcxy: inc SCRY jmp update_adscr - @not_LF: - ldx CHARCOLOR cpx OLD_CHARCOLOR beq do_not_change_color_foreground @@ -87,8 +86,6 @@ do_not_change_color: rts .endproc - - .bss CHARCOLOR: .res 1 From 5f145542b05fd08b81dac089757c206159e828c7 Mon Sep 17 00:00:00 2001 From: Greg King Date: Wed, 3 Mar 2021 17:39:53 -0500 Subject: [PATCH 09/80] Exported the Commodore CHRIN and CHROUT Kernal functions, in the CBM libraries. This commit complements commit 98f8064b8311753fab468aaf2c1b6d2e339a4391. --- libsrc/c128/kernal.s | 2 ++ libsrc/c16/kernal.s | 2 ++ libsrc/c64/kernal.s | 2 ++ libsrc/cbm510/kernal.s | 2 ++ libsrc/cbm610/kernal.s | 2 ++ libsrc/pet/kbsout.s | 7 +++++-- libsrc/pet/kernal.s | 1 + libsrc/plus4/kbasin.s | 7 ++++--- libsrc/plus4/kbsout.s | 5 +++-- libsrc/vic20/kernal.s | 2 ++ 10 files changed, 25 insertions(+), 7 deletions(-) diff --git a/libsrc/c128/kernal.s b/libsrc/c128/kernal.s index 138473218..47e80c559 100644 --- a/libsrc/c128/kernal.s +++ b/libsrc/c128/kernal.s @@ -46,7 +46,9 @@ .export CKOUT .export CLRCH .export BASIN + .export CHRIN .export BSOUT + .export CHROUT .export LOAD .export SAVE .export SETTIM diff --git a/libsrc/c16/kernal.s b/libsrc/c16/kernal.s index 15ce35772..5f70123a2 100644 --- a/libsrc/c16/kernal.s +++ b/libsrc/c16/kernal.s @@ -35,7 +35,9 @@ .export CKOUT .export CLRCH .export BASIN + .export CHRIN .export BSOUT + .export CHROUT .export LOAD .export SAVE .export SETTIM diff --git a/libsrc/c64/kernal.s b/libsrc/c64/kernal.s index 771872082..cf5511ce8 100644 --- a/libsrc/c64/kernal.s +++ b/libsrc/c64/kernal.s @@ -38,7 +38,9 @@ .export CKOUT .export CLRCH .export BASIN + .export CHRIN .export BSOUT + .export CHROUT .export LOAD .export SAVE .export SETTIM diff --git a/libsrc/cbm510/kernal.s b/libsrc/cbm510/kernal.s index 7908c40ec..705422709 100644 --- a/libsrc/cbm510/kernal.s +++ b/libsrc/cbm510/kernal.s @@ -28,7 +28,9 @@ .export CKOUT .export CLRCH .export BASIN + .export CHRIN .export BSOUT + .export CHROUT .export LOAD .export SAVE .export STOP diff --git a/libsrc/cbm610/kernal.s b/libsrc/cbm610/kernal.s index 921bf524e..30156e79c 100644 --- a/libsrc/cbm610/kernal.s +++ b/libsrc/cbm610/kernal.s @@ -28,7 +28,9 @@ .export CKOUT .export CLRCH .export BASIN + .export CHRIN .export BSOUT + .export CHROUT .export LOAD .export SAVE .export STOP diff --git a/libsrc/pet/kbsout.s b/libsrc/pet/kbsout.s index 178ac8205..8b21378af 100644 --- a/libsrc/pet/kbsout.s +++ b/libsrc/pet/kbsout.s @@ -1,17 +1,20 @@ ; ; Ullrich von Bassewitz, 19.11.2002 ; -; BSOUT replacement function for the PETs +; BSOUT/CHROUT replacement function for the PETs ; .export BSOUT + .export CHROUT + .import checkst .proc BSOUT - jsr $FFD2 ; Call kernal function + jsr $FFD2 ; Call Kernal function jmp checkst ; Check status, return carry on error .endproc +CHROUT := BSOUT diff --git a/libsrc/pet/kernal.s b/libsrc/pet/kernal.s index ba66c4653..fc8d62c4a 100644 --- a/libsrc/pet/kernal.s +++ b/libsrc/pet/kernal.s @@ -8,6 +8,7 @@ .export CLRCH .export BASIN + .export CHRIN .export STOP .export GETIN .export CLALL diff --git a/libsrc/plus4/kbasin.s b/libsrc/plus4/kbasin.s index 507043866..3bbee9f74 100644 --- a/libsrc/plus4/kbasin.s +++ b/libsrc/plus4/kbasin.s @@ -1,10 +1,11 @@ ; ; Ullrich von Bassewitz, 22.11.2002 ; -; BASIN replacement function +; BASIN/CHRIN replacement function ; - + .export BASIN + .export CHRIN .include "plus4.inc" @@ -17,4 +18,4 @@ rts ; Return to caller .endproc - +CHRIN := BASIN diff --git a/libsrc/plus4/kbsout.s b/libsrc/plus4/kbsout.s index a86a334b2..8b6df19ff 100644 --- a/libsrc/plus4/kbsout.s +++ b/libsrc/plus4/kbsout.s @@ -1,10 +1,11 @@ ; ; Ullrich von Bassewitz, 22.11.2002 ; -; BSOUT replacement function +; BSOUT/CHROUT replacement function ; .export BSOUT + .export CHROUT .include "plus4.inc" @@ -17,4 +18,4 @@ rts ; Return to caller .endproc - +CHROUT := BSOUT diff --git a/libsrc/vic20/kernal.s b/libsrc/vic20/kernal.s index 94a5ec1a4..7c54b205f 100644 --- a/libsrc/vic20/kernal.s +++ b/libsrc/vic20/kernal.s @@ -36,7 +36,9 @@ .export CKOUT .export CLRCH .export BASIN + .export CHRIN .export BSOUT + .export CHROUT .export LOAD .export SAVE .export SETTIM From 1fc16cb9ed6f9a27f4aaa6337b98e27a57a77fcd Mon Sep 17 00:00:00 2001 From: jede Date: Fri, 23 Oct 2020 23:47:30 +0200 Subject: [PATCH 10/80] Now getchar works --- libsrc/telestrat/read.s | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/libsrc/telestrat/read.s b/libsrc/telestrat/read.s index 76de9d0ac..0782c4d21 100644 --- a/libsrc/telestrat/read.s +++ b/libsrc/telestrat/read.s @@ -8,21 +8,33 @@ .include "zeropage.inc" .include "telestrat.inc" + .include "fcntl.inc" ;int read (int fd, void* buf, unsigned count); .proc _read - sta ptr1 ; count - stx ptr1+1 ; count - jsr popax ; get buf + sta ptr1 ; count + stx ptr1+1 ; count + jsr popax ; get buf sta PTR_READ_DEST stx PTR_READ_DEST+1 - sta ptr2 ; in order to calculate nb of bytes read + sta ptr2 ; in order to calculate nb of bytes read stx ptr2+1 ; - ; jsr popax ; fp pointer don't care in this version + jsr popax ; fp pointer don't care in this version + cpx #$00 + bne @is_not_stdin + cmp #STDIN_FILENO + bne @is_not_stdin + ; stdin +@L1: + BRK_TELEMON XRD0 ; waits until key is pressed + bcs @L1 + + rts +@is_not_stdin: lda ptr1 ; ldy ptr1+1 ; BRK_TELEMON XFREAD ; calls telemon30 routine From d83e8a3f0e8f71f627b20639c85e4e7a386cbb32 Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 1 Mar 2021 22:49:20 +0100 Subject: [PATCH 11/80] add syschdir --- libsrc/telestrat/syschdir.s | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 libsrc/telestrat/syschdir.s diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s new file mode 100644 index 000000000..1676f5c88 --- /dev/null +++ b/libsrc/telestrat/syschdir.s @@ -0,0 +1,34 @@ +; +; Jede (jede@oric.org), 2021-02-22 +; +; unsigned char _syschdir (const char* name, ...); +; + + .export __syschdir + .import addysp, popax + .importzp tmp1 + + .include "telestrat.inc" + .include "zeropage.inc" + + +__syschdir: + ; Throw away all parameters except the name + dey + dey + jsr addysp + + ; Get name + jsr popax + + stx tmp1 + ldy tmp1 + + ; Call telemon primitive + + BRK_TELEMON(XPUTCWD) + + rts + + + From 65d5786da564e3937795361cbdc8e1f48f0b0272 Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 1 Mar 2021 22:51:59 +0100 Subject: [PATCH 12/80] revert read.s --- libsrc/telestrat/read.s | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/libsrc/telestrat/read.s b/libsrc/telestrat/read.s index 0782c4d21..76de9d0ac 100644 --- a/libsrc/telestrat/read.s +++ b/libsrc/telestrat/read.s @@ -8,33 +8,21 @@ .include "zeropage.inc" .include "telestrat.inc" - .include "fcntl.inc" ;int read (int fd, void* buf, unsigned count); .proc _read - sta ptr1 ; count - stx ptr1+1 ; count - jsr popax ; get buf + sta ptr1 ; count + stx ptr1+1 ; count + jsr popax ; get buf sta PTR_READ_DEST stx PTR_READ_DEST+1 - sta ptr2 ; in order to calculate nb of bytes read + sta ptr2 ; in order to calculate nb of bytes read stx ptr2+1 ; - jsr popax ; fp pointer don't care in this version - cpx #$00 - bne @is_not_stdin - cmp #STDIN_FILENO - bne @is_not_stdin - ; stdin -@L1: - BRK_TELEMON XRD0 ; waits until key is pressed - bcs @L1 - - rts + ; jsr popax ; fp pointer don't care in this version -@is_not_stdin: lda ptr1 ; ldy ptr1+1 ; BRK_TELEMON XFREAD ; calls telemon30 routine From 973a5337ac29f8fb1c8abfc68f4a4fa632b721d6 Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 1 Mar 2021 22:53:35 +0100 Subject: [PATCH 13/80] remove extra line --- libsrc/telestrat/syschdir.s | 3 --- 1 file changed, 3 deletions(-) diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s index 1676f5c88..37ee0cc81 100644 --- a/libsrc/telestrat/syschdir.s +++ b/libsrc/telestrat/syschdir.s @@ -29,6 +29,3 @@ __syschdir: BRK_TELEMON(XPUTCWD) rts - - - From d417baf826b9a6eae86d4de69f149b9f105954e9 Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 1 Mar 2021 23:26:35 +0100 Subject: [PATCH 14/80] Now we update __cwd --- libsrc/telestrat/initcwd.s | 3 +-- libsrc/telestrat/syschdir.s | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libsrc/telestrat/initcwd.s b/libsrc/telestrat/initcwd.s index dc3c53257..7d38dd563 100644 --- a/libsrc/telestrat/initcwd.s +++ b/libsrc/telestrat/initcwd.s @@ -10,8 +10,7 @@ initcwd: - ldx #PWD_PTR - BRK_TELEMON XVARS + BRK_TELEMON(XGETCWD) sta ptr1 sty ptr1+1 diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s index 37ee0cc81..2437ac80e 100644 --- a/libsrc/telestrat/syschdir.s +++ b/libsrc/telestrat/syschdir.s @@ -7,6 +7,7 @@ .export __syschdir .import addysp, popax .importzp tmp1 + .import initcwd .include "telestrat.inc" .include "zeropage.inc" @@ -27,5 +28,7 @@ __syschdir: ; Call telemon primitive BRK_TELEMON(XPUTCWD) + + jsr initcwd ; Update cwd rts From 17ca09ba9afe520cd88c1c156e6e29d836fc5722 Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 1 Mar 2021 23:37:09 +0100 Subject: [PATCH 15/80] Fix tab --- libsrc/telestrat/syschdir.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s index 2437ac80e..c032fc648 100644 --- a/libsrc/telestrat/syschdir.s +++ b/libsrc/telestrat/syschdir.s @@ -6,7 +6,7 @@ .export __syschdir .import addysp, popax - .importzp tmp1 + .importzp tmp1 .import initcwd .include "telestrat.inc" From 9b365654852a390f00a9521c8d3654c18c68d78b Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 1 Mar 2021 23:37:50 +0100 Subject: [PATCH 16/80] Fix another tab --- libsrc/telestrat/syschdir.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s index c032fc648..1e42bcbab 100644 --- a/libsrc/telestrat/syschdir.s +++ b/libsrc/telestrat/syschdir.s @@ -22,7 +22,7 @@ __syschdir: ; Get name jsr popax - stx tmp1 + stx tmp1 ldy tmp1 ; Call telemon primitive From 2ae41e0a558bfc4b511f17b1df40092a6a0e253a Mon Sep 17 00:00:00 2001 From: jede Date: Tue, 2 Mar 2021 08:21:12 +0100 Subject: [PATCH 17/80] Fix tab --- libsrc/telestrat/syschdir.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s index 1e42bcbab..eef11d9e3 100644 --- a/libsrc/telestrat/syschdir.s +++ b/libsrc/telestrat/syschdir.s @@ -22,7 +22,7 @@ __syschdir: ; Get name jsr popax - stx tmp1 + stx tmp1 ldy tmp1 ; Call telemon primitive From bf9d4ac3bbc0a3f23ec09ba90cfae36289bd7556 Mon Sep 17 00:00:00 2001 From: jede Date: Wed, 3 Mar 2021 22:20:20 +0100 Subject: [PATCH 18/80] Fix tab and jmp --- libsrc/telestrat/syschdir.s | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s index eef11d9e3..149957215 100644 --- a/libsrc/telestrat/syschdir.s +++ b/libsrc/telestrat/syschdir.s @@ -6,7 +6,7 @@ .export __syschdir .import addysp, popax - .importzp tmp1 + .importzp tmp1 .import initcwd .include "telestrat.inc" @@ -29,6 +29,4 @@ __syschdir: BRK_TELEMON(XPUTCWD) - jsr initcwd ; Update cwd - - rts + jmp initcwd ; Update cwd From 1d8479b411633eeda9952805daac23177640b425 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Sat, 6 Mar 2021 11:56:22 +0100 Subject: [PATCH 19/80] Revert "Fix tab and jmp" This reverts commit bf9d4ac3bbc0a3f23ec09ba90cfae36289bd7556. --- libsrc/telestrat/syschdir.s | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s index 149957215..eef11d9e3 100644 --- a/libsrc/telestrat/syschdir.s +++ b/libsrc/telestrat/syschdir.s @@ -6,7 +6,7 @@ .export __syschdir .import addysp, popax - .importzp tmp1 + .importzp tmp1 .import initcwd .include "telestrat.inc" @@ -29,4 +29,6 @@ __syschdir: BRK_TELEMON(XPUTCWD) - jmp initcwd ; Update cwd + jsr initcwd ; Update cwd + + rts From f9ca091bd040b3dd7dd65a4722d9ef0d561b0f28 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Sat, 6 Mar 2021 11:56:22 +0100 Subject: [PATCH 20/80] Revert "Fix tab" This reverts commit 2ae41e0a558bfc4b511f17b1df40092a6a0e253a. --- libsrc/telestrat/syschdir.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s index eef11d9e3..1e42bcbab 100644 --- a/libsrc/telestrat/syschdir.s +++ b/libsrc/telestrat/syschdir.s @@ -22,7 +22,7 @@ __syschdir: ; Get name jsr popax - stx tmp1 + stx tmp1 ldy tmp1 ; Call telemon primitive From 24d63a96b1c7d8418b3f2b7f8c60f8a572738864 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Sat, 6 Mar 2021 11:56:22 +0100 Subject: [PATCH 21/80] Revert "Fix another tab" This reverts commit 9b365654852a390f00a9521c8d3654c18c68d78b. --- libsrc/telestrat/syschdir.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s index 1e42bcbab..c032fc648 100644 --- a/libsrc/telestrat/syschdir.s +++ b/libsrc/telestrat/syschdir.s @@ -22,7 +22,7 @@ __syschdir: ; Get name jsr popax - stx tmp1 + stx tmp1 ldy tmp1 ; Call telemon primitive From 558dfa285e9a768b22860113e083528870d48500 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Sat, 6 Mar 2021 11:56:22 +0100 Subject: [PATCH 22/80] Revert "Fix tab" This reverts commit 17ca09ba9afe520cd88c1c156e6e29d836fc5722. --- libsrc/telestrat/syschdir.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s index c032fc648..2437ac80e 100644 --- a/libsrc/telestrat/syschdir.s +++ b/libsrc/telestrat/syschdir.s @@ -6,7 +6,7 @@ .export __syschdir .import addysp, popax - .importzp tmp1 + .importzp tmp1 .import initcwd .include "telestrat.inc" From ab4ca51848560efdea292837d2dd74ffebd22470 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Sat, 6 Mar 2021 11:56:22 +0100 Subject: [PATCH 23/80] Revert "Now we update __cwd" This reverts commit d417baf826b9a6eae86d4de69f149b9f105954e9. --- libsrc/telestrat/initcwd.s | 3 ++- libsrc/telestrat/syschdir.s | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libsrc/telestrat/initcwd.s b/libsrc/telestrat/initcwd.s index 7d38dd563..dc3c53257 100644 --- a/libsrc/telestrat/initcwd.s +++ b/libsrc/telestrat/initcwd.s @@ -10,7 +10,8 @@ initcwd: - BRK_TELEMON(XGETCWD) + ldx #PWD_PTR + BRK_TELEMON XVARS sta ptr1 sty ptr1+1 diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s index 2437ac80e..37ee0cc81 100644 --- a/libsrc/telestrat/syschdir.s +++ b/libsrc/telestrat/syschdir.s @@ -7,7 +7,6 @@ .export __syschdir .import addysp, popax .importzp tmp1 - .import initcwd .include "telestrat.inc" .include "zeropage.inc" @@ -28,7 +27,5 @@ __syschdir: ; Call telemon primitive BRK_TELEMON(XPUTCWD) - - jsr initcwd ; Update cwd rts From 8ae5a4a1345db0947ed327b9ce4103963b2670e3 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Sat, 6 Mar 2021 11:56:22 +0100 Subject: [PATCH 24/80] Revert "remove extra line" This reverts commit 973a5337ac29f8fb1c8abfc68f4a4fa632b721d6. --- libsrc/telestrat/syschdir.s | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s index 37ee0cc81..1676f5c88 100644 --- a/libsrc/telestrat/syschdir.s +++ b/libsrc/telestrat/syschdir.s @@ -29,3 +29,6 @@ __syschdir: BRK_TELEMON(XPUTCWD) rts + + + From d6f2fda5757ee0786579cd76b6b50f2926e9836e Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Sat, 6 Mar 2021 11:56:22 +0100 Subject: [PATCH 25/80] Revert "revert read.s" This reverts commit 65d5786da564e3937795361cbdc8e1f48f0b0272. --- libsrc/telestrat/read.s | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/libsrc/telestrat/read.s b/libsrc/telestrat/read.s index 76de9d0ac..0782c4d21 100644 --- a/libsrc/telestrat/read.s +++ b/libsrc/telestrat/read.s @@ -8,21 +8,33 @@ .include "zeropage.inc" .include "telestrat.inc" + .include "fcntl.inc" ;int read (int fd, void* buf, unsigned count); .proc _read - sta ptr1 ; count - stx ptr1+1 ; count - jsr popax ; get buf + sta ptr1 ; count + stx ptr1+1 ; count + jsr popax ; get buf sta PTR_READ_DEST stx PTR_READ_DEST+1 - sta ptr2 ; in order to calculate nb of bytes read + sta ptr2 ; in order to calculate nb of bytes read stx ptr2+1 ; - ; jsr popax ; fp pointer don't care in this version + jsr popax ; fp pointer don't care in this version + cpx #$00 + bne @is_not_stdin + cmp #STDIN_FILENO + bne @is_not_stdin + ; stdin +@L1: + BRK_TELEMON XRD0 ; waits until key is pressed + bcs @L1 + + rts +@is_not_stdin: lda ptr1 ; ldy ptr1+1 ; BRK_TELEMON XFREAD ; calls telemon30 routine From f122837955170516c629f5d97c82c984a883b5b8 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Sat, 6 Mar 2021 11:56:22 +0100 Subject: [PATCH 26/80] Revert "add syschdir" This reverts commit d83e8a3f0e8f71f627b20639c85e4e7a386cbb32. --- libsrc/telestrat/syschdir.s | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 libsrc/telestrat/syschdir.s diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s deleted file mode 100644 index 1676f5c88..000000000 --- a/libsrc/telestrat/syschdir.s +++ /dev/null @@ -1,34 +0,0 @@ -; -; Jede (jede@oric.org), 2021-02-22 -; -; unsigned char _syschdir (const char* name, ...); -; - - .export __syschdir - .import addysp, popax - .importzp tmp1 - - .include "telestrat.inc" - .include "zeropage.inc" - - -__syschdir: - ; Throw away all parameters except the name - dey - dey - jsr addysp - - ; Get name - jsr popax - - stx tmp1 - ldy tmp1 - - ; Call telemon primitive - - BRK_TELEMON(XPUTCWD) - - rts - - - From bc8cca9fc48d7da6d93035b38f57b62f6e9a6043 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Sat, 6 Mar 2021 11:56:22 +0100 Subject: [PATCH 27/80] Revert "Now getchar works" This reverts commit 1fc16cb9ed6f9a27f4aaa6337b98e27a57a77fcd. --- libsrc/telestrat/read.s | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/libsrc/telestrat/read.s b/libsrc/telestrat/read.s index 0782c4d21..76de9d0ac 100644 --- a/libsrc/telestrat/read.s +++ b/libsrc/telestrat/read.s @@ -8,33 +8,21 @@ .include "zeropage.inc" .include "telestrat.inc" - .include "fcntl.inc" ;int read (int fd, void* buf, unsigned count); .proc _read - sta ptr1 ; count - stx ptr1+1 ; count - jsr popax ; get buf + sta ptr1 ; count + stx ptr1+1 ; count + jsr popax ; get buf sta PTR_READ_DEST stx PTR_READ_DEST+1 - sta ptr2 ; in order to calculate nb of bytes read + sta ptr2 ; in order to calculate nb of bytes read stx ptr2+1 ; - jsr popax ; fp pointer don't care in this version - cpx #$00 - bne @is_not_stdin - cmp #STDIN_FILENO - bne @is_not_stdin - ; stdin -@L1: - BRK_TELEMON XRD0 ; waits until key is pressed - bcs @L1 - - rts + ; jsr popax ; fp pointer don't care in this version -@is_not_stdin: lda ptr1 ; ldy ptr1+1 ; BRK_TELEMON XFREAD ; calls telemon30 routine From 48badc081679a19bec9ad6edbc1b39f36fd50e79 Mon Sep 17 00:00:00 2001 From: jede Date: Sat, 6 Mar 2021 21:40:26 +0100 Subject: [PATCH 28/80] Fix import return0 --- libsrc/telestrat/bordercolor.s | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsrc/telestrat/bordercolor.s b/libsrc/telestrat/bordercolor.s index 84e167bc9..c29ecc0e7 100644 --- a/libsrc/telestrat/bordercolor.s +++ b/libsrc/telestrat/bordercolor.s @@ -4,9 +4,10 @@ ; unsigned char __fastcall__ bordercolor (unsigned char color); ; - .export _bordercolor + .import return0 + .include "telestrat.inc" _bordercolor := return0 From df64fd859c7477ebd7d0ed8b377c84b0510e5e77 Mon Sep 17 00:00:00 2001 From: jede Date: Sun, 7 Mar 2021 23:00:15 +0100 Subject: [PATCH 29/80] Fix cvline bug --- libsrc/telestrat/cvline.s | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libsrc/telestrat/cvline.s b/libsrc/telestrat/cvline.s index 159eb9d27..0d6086216 100644 --- a/libsrc/telestrat/cvline.s +++ b/libsrc/telestrat/cvline.s @@ -28,7 +28,11 @@ _cvline: @L1: lda #'|' ora rvs - jsr display_conio + ldy SCRX + sta (ADSCR),y + ; compute next line + inc SCRY + jsr update_adscr @L2: dex bne @L1 @L9: rts From facc1b4914425baee3019035189b29beca649cb5 Mon Sep 17 00:00:00 2001 From: jede Date: Mon, 8 Mar 2021 21:16:44 +0100 Subject: [PATCH 30/80] Fix cputdirect --- libsrc/telestrat/cputc.s | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libsrc/telestrat/cputc.s b/libsrc/telestrat/cputc.s index 994a2b9d4..6049d1174 100644 --- a/libsrc/telestrat/cputc.s +++ b/libsrc/telestrat/cputc.s @@ -6,14 +6,13 @@ .export _cputc, _cputcxy, cputdirect, display_conio .export CHARCOLOR, OLD_CHARCOLOR, BGCOLOR, OLD_BGCOLOR - .import update_adscr .import popax .include "telestrat.inc" -cputdirect: + _cputcxy: pha ; Save C jsr popax ; Get X and Y @@ -22,7 +21,7 @@ _cputcxy: jsr update_adscr pla -.proc _cputc +_cputc: cmp #$0D bne @not_CR ldy #$00 @@ -30,12 +29,13 @@ _cputcxy: rts @not_CR: cmp #$0A - bne @not_LF + bne not_LF inc SCRY jmp update_adscr -@not_LF: +cputdirect: +not_LF: ldx CHARCOLOR cpx OLD_CHARCOLOR beq do_not_change_color_foreground @@ -67,7 +67,7 @@ do_not_change_color_foreground: do_not_change_color: ; it continues to display_conio -.endproc + .proc display_conio ; This routine is used to displays char on screen From a05dddd0d6ac759eee695d54a8ef2632e6220108 Mon Sep 17 00:00:00 2001 From: jede Date: Tue, 9 Mar 2021 22:02:26 +0100 Subject: [PATCH 31/80] Fix next column --- libsrc/telestrat/cputc.s | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libsrc/telestrat/cputc.s b/libsrc/telestrat/cputc.s index 6049d1174..16b13f8cd 100644 --- a/libsrc/telestrat/cputc.s +++ b/libsrc/telestrat/cputc.s @@ -78,6 +78,8 @@ do_not_change_color: bne @no_inc ldy #$00 sty SCRX + + inc SCRY jmp update_adscr From 4f26650228506b746fce11895eaa6fa6befb2b31 Mon Sep 17 00:00:00 2001 From: jedeoric Date: Thu, 11 Mar 2021 09:42:14 +0100 Subject: [PATCH 32/80] [Telestrat] chdir management (#1419) * add syschdir * revert read.s * remove extra line * Now we update __cwd * Fix tab * Fix another tab * Fix tab * Fix tab and jmp * fix xgetcwd * Fix comments --- asminc/telestrat.inc | 2 ++ libsrc/telestrat/initcwd.s | 3 +-- libsrc/telestrat/read.s | 12 ++++++------ libsrc/telestrat/syschdir.s | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 libsrc/telestrat/syschdir.s diff --git a/asminc/telestrat.inc b/asminc/telestrat.inc index 2036574a4..556b41f7c 100644 --- a/asminc/telestrat.inc +++ b/asminc/telestrat.inc @@ -284,6 +284,8 @@ XSOUND = $44 XMUSIC = $45 XZAP = $46 ; Send Zap sound to PSG XSHOOT = $47 +XGETCWD = $48 ; Get current CWD +XPUTCWD = $49 ; Chdir XMKDIR = $4B ; Create a folder. Only available in TELEMON 3.x (bank 7 of Orix) XRM = $4D ; Remove a folder or a file. Only available in TELEMON 3.x (bank 7 of Orix) XFWR = $4E ; Put a char on the first screen. Only available in TELEMON 3.x (bank 7 of Orix) diff --git a/libsrc/telestrat/initcwd.s b/libsrc/telestrat/initcwd.s index dc3c53257..7d38dd563 100644 --- a/libsrc/telestrat/initcwd.s +++ b/libsrc/telestrat/initcwd.s @@ -10,8 +10,7 @@ initcwd: - ldx #PWD_PTR - BRK_TELEMON XVARS + BRK_TELEMON(XGETCWD) sta ptr1 sty ptr1+1 diff --git a/libsrc/telestrat/read.s b/libsrc/telestrat/read.s index 76de9d0ac..db764fc84 100644 --- a/libsrc/telestrat/read.s +++ b/libsrc/telestrat/read.s @@ -12,21 +12,21 @@ ;int read (int fd, void* buf, unsigned count); .proc _read - sta ptr1 ; count - stx ptr1+1 ; count - jsr popax ; get buf + + sta ptr1 ; Count + stx ptr1+1 ; Count + jsr popax ; Get buf sta PTR_READ_DEST stx PTR_READ_DEST+1 - sta ptr2 ; in order to calculate nb of bytes read + sta ptr2 ; In order to calculate nb of bytes read stx ptr2+1 ; - ; jsr popax ; fp pointer don't care in this version lda ptr1 ; ldy ptr1+1 ; BRK_TELEMON XFREAD ; calls telemon30 routine - ; compute nb of bytes read + ; Compute nb of bytes read lda PTR_READ_DEST+1 sec sbc ptr2+1 diff --git a/libsrc/telestrat/syschdir.s b/libsrc/telestrat/syschdir.s new file mode 100644 index 000000000..149957215 --- /dev/null +++ b/libsrc/telestrat/syschdir.s @@ -0,0 +1,32 @@ +; +; Jede (jede@oric.org), 2021-02-22 +; +; unsigned char _syschdir (const char* name, ...); +; + + .export __syschdir + .import addysp, popax + .importzp tmp1 + .import initcwd + + .include "telestrat.inc" + .include "zeropage.inc" + + +__syschdir: + ; Throw away all parameters except the name + dey + dey + jsr addysp + + ; Get name + jsr popax + + stx tmp1 + ldy tmp1 + + ; Call telemon primitive + + BRK_TELEMON(XPUTCWD) + + jmp initcwd ; Update cwd From c0d638a26d36152d861b3078444f94852987b34c Mon Sep 17 00:00:00 2001 From: jede Date: Thu, 11 Mar 2021 22:48:05 +0100 Subject: [PATCH 33/80] add clock for Telestrat target and add some Telemon primitives --- asminc/telestrat.inc | 41 ++++++++++++++++++++++++++++++++++++---- libsrc/telestrat/clock.s | 30 +++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 libsrc/telestrat/clock.s diff --git a/asminc/telestrat.inc b/asminc/telestrat.inc index 556b41f7c..f48600b38 100644 --- a/asminc/telestrat.inc +++ b/asminc/telestrat.inc @@ -63,7 +63,7 @@ PTR_READ_DEST := $2C ; Used for XFREAD and XWRITE only in TELEMON 3. ADCLK := $40 ; Address for clock display TIMEUS := $42 -TIMEUD := $44 +TIMEUD := $44 ; Counter clock (1/10 of a second) HRSX := $46 @@ -277,6 +277,7 @@ XRECLK = $3C ; Reset clock XCLCL = $3D ; Close clock XWRCLK = $3E ; Displays clock in the adress in A & Y registers +; Sound primitives XSONPS = $40 ; Send data to PSG register (14 values) XOUPS = $42 ; Send Oups sound into PSG XPLAY = $43 ; Play a sound @@ -284,12 +285,25 @@ XSOUND = $44 XMUSIC = $45 XZAP = $46 ; Send Zap sound to PSG XSHOOT = $47 + +; Path Management XGETCWD = $48 ; Get current CWD XPUTCWD = $49 ; Chdir + +; File management XMKDIR = $4B ; Create a folder. Only available in TELEMON 3.x (bank 7 of Orix) + +XHCHRS = $4C ; Hard copy hires + +; File management XRM = $4D ; Remove a folder or a file. Only available in TELEMON 3.x (bank 7 of Orix) + XFWR = $4E ; Put a char on the first screen. Only available in TELEMON 3.x (bank 7 of Orix) -XGOKBD = $52 + +; Keyboard primitives +XALLKB = $50 ; Read Keyboard, and populate KBDCOL +XKBDAS = $51 ; Ascii conversion +XGOKBD = $52 ; Swap keyboard type (Qwerty, French ...) ; Buffer management XECRBU = $54 ; Write A or AY in the buffer @@ -301,8 +315,27 @@ XDEFBU = $59 ; Reset all value of the buffer XBUSY = $5A ; Test if the buffer is empty XMALLOC = $5B ; Only in TELEMON 3.x (bank 7 of Orix) + +; RS232 primitives +XSDUMP = $5C ; RS232 input dump +XCONSO = $5D ; Swap screen into RS232 terminal +XSLOAD = $5E ; Read a file from RS232 +XSSAVE = $5F ; Write a file to RS232 + +; Minitel primitives +XMLOAD = $60 ; Read a file from Minitel +XMSAVE = $61 ; Write a file to Minitel + XFREE = $62 ; Only in TELEMON 3.x (bank 7 of Orix) + +; Next Minitel primitives +XWCXFI = $63 ; Wait connection +XLIGNE = $64 ; +XDECON = $65 ; Minitel disconnection +XMOUT = $66 ; Send a byte to minitel (from A) + XSOUT = $67 ; Send accumulator value (A) to RS232, available in TELEMON 2.4 & 3.x : if RS232 buffer is full, the Oric Telestrat freezes + XHRSSE = $8C ; Set hires position cursor XDRAWA = $8D ; Draw a line absolute XDRAWR = $8E ; Draw a line (relative) @@ -326,7 +359,7 @@ PWD_PTR = $00 ; --------------------------------------------------------------------------- ; -BUFTRV := $100 +BUFTRV := $100 ; --------------------------------------------------------------------------- @@ -339,7 +372,7 @@ FLGTEL := $20D KOROM := $20E ; Used to compute the size of all rom bank. The result is store here. The value is in KB KORAM := $20F ; Used to compute the size of all ram bank. The result is store here. The value is in KB ; Time management -TIMED := $210 +TIMED := $210 ; Clock (1/10 of seconds) TIMES := $211 TIMEM := $212 TIMEH := $213 diff --git a/libsrc/telestrat/clock.s b/libsrc/telestrat/clock.s new file mode 100644 index 000000000..1e107027f --- /dev/null +++ b/libsrc/telestrat/clock.s @@ -0,0 +1,30 @@ +; +; Jede, 2021-03-10 +; +; clock_t clock (void); +; + + .export _clock + .importzp sreg + + .include "telestrat.inc" + +.proc _clock + +; Clear the timer high 16 bits + + ldy #$00 + sty sreg + sty sreg+1 + +; Read the timer + + sei ; Disable interrupts + lda TIMEUD ; TIMED contains 1/10 of a second from clock. Telestrat main cardridge simulate a clock from VIA6522 timer + ldx TIMEUD+1 + cli ; Reenable interrupts + + rts +.endproc + + From b9fd318985d12904b3facba8f82dc4cb37295f65 Mon Sep 17 00:00:00 2001 From: jede Date: Thu, 11 Mar 2021 22:52:41 +0100 Subject: [PATCH 34/80] fix space/column --- asminc/telestrat.inc | 22 +++++++++++----------- libsrc/telestrat/clock.s | 4 +--- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/asminc/telestrat.inc b/asminc/telestrat.inc index f48600b38..7d4c1e31d 100644 --- a/asminc/telestrat.inc +++ b/asminc/telestrat.inc @@ -48,33 +48,33 @@ TR7 := $13 DEFAFF := $14 -IRQSVA := $21 ; Used to save A when a BRK call occurs -IRQSVX := $22 ; Used to save X when a BRK call occurs -IRQSVY := $23 ; Used to save Y when a BRK call occurs -IRQSVP := $24 ; Used to save P when a BRK call occurs +IRQSVA := $21 ; Used to save A when a BRK call occurs +IRQSVX := $22 ; Used to save X when a BRK call occurs +IRQSVY := $23 ; Used to save Y when a BRK call occurs +IRQSVP := $24 ; Used to save P when a BRK call occurs ADSCR := $26 -SCRNB := $28 ; Id of the current window +SCRNB := $28 ; Id of the current window -ADKBD := $2A ; Address ASCII conversion table +ADKBD := $2A ; Address ASCII conversion table -PTR_READ_DEST := $2C ; Used for XFREAD and XWRITE only in TELEMON 3.x +PTR_READ_DEST := $2C ; Used for XFREAD and XWRITE only in TELEMON 3.x -ADCLK := $40 ; Address for clock display +ADCLK := $40 ; Address for clock display TIMEUS := $42 -TIMEUD := $44 ; Counter clock (1/10 of a second) +TIMEUD := $44 ; Counter clock (1/10 of a second) HRSX := $46 HRSY := $47 -XLPRBI := $48 ; Printer flag (b7) +XLPRBI := $48 ; Printer flag (b7) HRSX40 := $49 HRSX6 := $4A -ADHRS := $4B ; Hires screen address (word) +ADHRS := $4B ; Hires screen address (word) HRS1 := $4D HRS2 := $4F diff --git a/libsrc/telestrat/clock.s b/libsrc/telestrat/clock.s index 1e107027f..c5478c7ac 100644 --- a/libsrc/telestrat/clock.s +++ b/libsrc/telestrat/clock.s @@ -20,11 +20,9 @@ ; Read the timer sei ; Disable interrupts - lda TIMEUD ; TIMED contains 1/10 of a second from clock. Telestrat main cardridge simulate a clock from VIA6522 timer + lda TIMEUD ; TIMED contains 1/10 of a second from clock. Telestrat main cardridge simulate a clock from VIA6522 timer ldx TIMEUD+1 cli ; Reenable interrupts rts .endproc - - From 41f796bbe1a825c3c8ecffc598c484be0304347e Mon Sep 17 00:00:00 2001 From: jede Date: Tue, 16 Mar 2021 00:53:34 +0100 Subject: [PATCH 35/80] left and right mask are inverted : fix in telestrat.h --- include/telestrat.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/telestrat.h b/include/telestrat.h index 465517f30..c1e0996bc 100644 --- a/include/telestrat.h +++ b/include/telestrat.h @@ -100,8 +100,8 @@ /* Masks for joy_read */ #define JOY_UP_MASK 0x10 #define JOY_DOWN_MASK 0x08 -#define JOY_LEFT_MASK 0x01 -#define JOY_RIGHT_MASK 0x02 +#define JOY_LEFT_MASK 0x02 +#define JOY_RIGHT_MASK 0x01 #define JOY_BTN_1_MASK 0x04 #define JOY_FIRE_MASK JOY_BTN_1_MASK From bd5d5b738569f3159c9c7f5632e68c55db105a93 Mon Sep 17 00:00:00 2001 From: acqn Date: Sat, 13 Mar 2021 14:31:23 +0800 Subject: [PATCH 36/80] Removed the prototype of evalexpr() that no longer exists. --- src/cc65/expr.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/cc65/expr.h b/src/cc65/expr.h index 71dbe8e0d..02f9f7a5f 100644 --- a/src/cc65/expr.h +++ b/src/cc65/expr.h @@ -74,13 +74,6 @@ void Store (ExprDesc* Expr, const Type* StoreType); ** is NULL, use lval->Type instead. */ -int evalexpr (unsigned flags, void (*Func) (ExprDesc*), ExprDesc* Expr); -/* Will evaluate an expression via the given function. If the result is a -** constant, 0 is returned and the value is put in the Expr struct. If the -** result is not constant, LoadExpr is called to bring the value into the -** primary register and 1 is returned. -*/ - void Expression0 (ExprDesc* Expr); /* Evaluate an expression via hie0 and put the result into the primary register. ** The expression is completely evaluated and all side effects complete. From 4376b833908d2280aac1df75c0098690ae70d681 Mon Sep 17 00:00:00 2001 From: acqn Date: Sat, 13 Mar 2021 14:31:23 +0800 Subject: [PATCH 37/80] Fixed LoadAAt(). --- src/cc65/codeoptutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/codeoptutil.c b/src/cc65/codeoptutil.c index 2f79b131b..36232bf3a 100644 --- a/src/cc65/codeoptutil.c +++ b/src/cc65/codeoptutil.c @@ -2614,7 +2614,7 @@ static int LoadAAt (CodeSeg* S, int Idx, const LoadRegInfo* LRI, Collection* Ind if (Use == REG_X) { X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, E->LI); CS_InsertEntry (S, X, Idx++); - } else if (Use == REG_A) { + } else if (Use == REG_Y) { X = NewCodeEntry (OP65_TYA, AM65_IMP, 0, 0, E->LI); CS_InsertEntry (S, X, Idx++); } else if (Use == REG_A) { From 0a8ca3041a80768590af5e18f5a6b7763c685cb4 Mon Sep 17 00:00:00 2001 From: acqn Date: Sat, 13 Mar 2021 14:31:23 +0800 Subject: [PATCH 38/80] Changd all Find*Last*InOpenRange() to return the beginning of the open range. Fixed FindArgLastUsageInOpenRange(). --- src/cc65/codeoptutil.c | 16 ++++++++-------- src/cc65/codeoptutil.h | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/cc65/codeoptutil.c b/src/cc65/codeoptutil.c index 36232bf3a..23c759fd1 100644 --- a/src/cc65/codeoptutil.c +++ b/src/cc65/codeoptutil.c @@ -3038,13 +3038,13 @@ int FindArgLastUsageInOpenRange (CodeSeg* S, int First, int Last, CodeEntry* E, /* Find the last index where the arg of E might be used or changed in the range (First, Last). ** ReloadY indicates whether Y is supposed to be reloaded. ** The code block in the range must be basic without any jump backwards. -** Return the index of the found entry, or -1 if not found. +** Return the index of the found entry, or First if not found. */ { LoadRegInfo LRI; CodeEntry* X; unsigned CheckedFlags = LI_SRC_USE | LI_SRC_CHG; - int Found = -1; + int Found = First; CHECK (Last <= (int)CollCount (&S->Entries)); @@ -3066,8 +3066,8 @@ int FindArgLastUsageInOpenRange (CodeSeg* S, int First, int Last, CodeEntry* E, /* TODO: We don't currently check for all cases */ if ((LRI.Flags & (LI_DIRECT | LI_CHECK_ARG | LI_CHECK_Y | LI_RELOAD_Y)) == 0) { - /* Just bail out as if the src would change right away */ - return 0; + /* Just bail out as if the src would change everywhere */ + return First < Last ? Last - 1 : First; } if ((LRI.Flags & LI_CHECK_Y) != 0) { @@ -3145,11 +3145,11 @@ int FindRegLastChangeInOpenRange (CodeSeg* S, int First, int Last, unsigned what /* Find the last possible spot where the queried ZPs, registers and/or processor ** states might be changed in the range (First, Last). The code block in the ** range must be basic without any jump backwards. -** Return the index of the found entry, or -1 if not found. +** Return the index of the found entry, or First if not found. */ { CodeEntry* X; - int Found = -1; + int Found = First; CHECK (Last <= (int)CollCount (&S->Entries)); @@ -3169,11 +3169,11 @@ int FindRegLastUseInOpenRange (CodeSeg* S, int First, int Last, unsigned what) /* Find the last possible spot where the queried ZPs, registers and/or processor ** states might be used in the range (First, Last). The code block in the range ** must be basic without any jump backwards. -** Return the index of the found entry, or -1 if not found. +** Return the index of the found entry, or First if not found. */ { CodeEntry* X; - int Found = -1; + int Found = First; CHECK (Last <= (int)CollCount (&S->Entries)); diff --git a/src/cc65/codeoptutil.h b/src/cc65/codeoptutil.h index c3596acd4..70aa5f462 100644 --- a/src/cc65/codeoptutil.h +++ b/src/cc65/codeoptutil.h @@ -433,7 +433,7 @@ int FindArgLastUsageInOpenRange (CodeSeg* S, int First, int Last, CodeEntry* E, /* Find the last index where the arg of E might be used or changed in the range (First, Last). ** ReloadY indicates whether Y is supposed to be reloaded. ** The code block in the range must be basic without any jump backwards. -** Return the index of the found entry, or -1 if not found. +** Return the index of the found entry, or First if not found. */ int FindRegFirstChangeInOpenRange (CodeSeg* S, int First, int Last, unsigned what); @@ -454,14 +454,14 @@ int FindRegLastChangeInOpenRange (CodeSeg* S, int First, int Last, unsigned what /* Find the last possible spot where the queried ZPs, registers and/or processor ** states might be changed in the range (First, Last). The code block in the ** range must be basic without any jump backwards. -** Return the index of the found entry, or -1 if not found. +** Return the index of the found entry, or First if not found. */ int FindRegLastUseInOpenRange (CodeSeg* S, int First, int Last, unsigned what); /* Find the last possible spot where the queried ZPs, registers and/or processor ** states might be used in the range (First, Last). The code block in the range ** must be basic without any jump backwards. -** Return the index of the found entry, or -1 if not found. +** Return the index of the found entry, or First if not found. */ /* End of codeoptutil.h */ From c4a2620e2925516929cccbe3be532561d282cde7 Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 8 Feb 2021 22:47:51 +0800 Subject: [PATCH 39/80] Added an utility function to check for quasi-constant addresses (of stack variables). --- src/cc65/exprdesc.c | 9 +++++++++ src/cc65/exprdesc.h | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/src/cc65/exprdesc.c b/src/cc65/exprdesc.c index f5d8cd779..aa98e1531 100644 --- a/src/cc65/exprdesc.c +++ b/src/cc65/exprdesc.c @@ -408,6 +408,15 @@ int ED_IsConst (const ExprDesc* Expr) +int ED_IsQuasiConst (const ExprDesc* Expr) +/* Return true if the expression denotes a quasi-constant of some sort. This +** can be a numeric constant, a constant address or a stack variable address. +*/ +{ + return (Expr->Flags & E_MASK_LOC) == E_LOC_NONE || ED_IsQuasiConstAddr (Expr); +} + + int ED_IsConstAddr (const ExprDesc* Expr) /* Return true if the expression denotes a constant address of some sort. This ** can be the address of a global variable (maybe with offset) or similar. diff --git a/src/cc65/exprdesc.h b/src/cc65/exprdesc.h index e1bf3117f..844af1566 100644 --- a/src/cc65/exprdesc.h +++ b/src/cc65/exprdesc.h @@ -649,6 +649,11 @@ int ED_IsConst (const ExprDesc* Expr); ** similar. */ +int ED_IsQuasiConst (const ExprDesc* Expr); +/* Return true if the expression denotes a quasi-constant of some sort. This +** can be a numeric constant, a constant address or a stack variable address. +*/ + int ED_IsConstAddr (const ExprDesc* Expr); /* Return true if the expression denotes a constant address of some sort. This ** can be the address of a global variable (maybe with offset) or similar. From aa6fdf58b8a17b747090fb521f3d9106e0c56d1c Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 8 Feb 2021 09:03:19 +0800 Subject: [PATCH 40/80] Addresses in constant subtraction expressions now work. Fixed codegen for cast type subtraction in constant expressions. --- src/cc65/expr.c | 211 +++++++++++++++++++++++++++++++----------------- 1 file changed, 138 insertions(+), 73 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 09a7a1f39..a38efab53 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -3287,7 +3287,8 @@ static void parsesub (ExprDesc* Expr) Type* rhst; /* Type of right hand side */ CodeMark Mark1; /* Save position of output queue */ CodeMark Mark2; /* Another position in the queue */ - int rscale; /* Scale factor for the result */ + int rscale; /* Scale factor for pointer arithmetics */ + int SubDone; /* No need to generate runtime code */ ED_Init (&Expr2); Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR; @@ -3304,7 +3305,9 @@ static void parsesub (ExprDesc* Expr) /* Get the left hand side type, initialize operation flags */ lhst = Expr->Type; + flags = CF_INT; /* Default result type */ rscale = 1; /* Scale by 1, that is, don't scale */ + SubDone = 0; /* Generate runtime code by default */ /* Remember the output queue position, then bring the value onto the stack */ GetCodePos (&Mark1); @@ -3322,67 +3325,148 @@ static void parsesub (ExprDesc* Expr) Expr2.Type = type_uchar; } - /* Check for a constant rhs expression */ - if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { + /* Get the rhs type */ + rhst = Expr2.Type; - /* The right hand side is constant. Get the rhs type. */ - rhst = Expr2.Type; + /* We can only do constant expressions for: + ** - integer subtraction: + ** - numeric - numeric + ** - (integer)(base + offset) - numeric + ** - (integer)(same_base + offset) - (integer)(same_base + offset) + ** - pointer offset: + ** - (pointer)numeric - numeric * scale + ** - (base + offset) - numeric * scale + ** - (same_base + offset) - (integer)(same_base + offset) * 1 + ** - pointer diff: + ** - (numeric - numeric) / scale + ** - ((same_base + offset) - (same_base + offset)) / scale + ** - ((base + offset) - (pointer)numeric) / 1 + */ + if (IsClassPtr (lhst) && IsClassPtr (rhst)) { - /* Check left hand side */ - if (ED_IsConstAbs (Expr)) { + /* Pointer diff */ + if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { + Error ("Incompatible pointer types"); + } - /* Both sides are constant, remove generated code */ + /* Operate on pointers, result type is an integer */ + flags = CF_PTR; + Expr->Type = type_int; + + /* We'll have to scale the result */ + rscale = CheckedPSizeOf (lhst); + + /* Check for a constant rhs expression */ + if (ED_IsQuasiConst (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { + /* The right hand side is constant. Check left hand side. */ + if (ED_IsQuasiConst (Expr)) { + /* We can't do all 'ptr1 - ptr2' constantly at the moment */ + if (Expr->Sym == Expr2.Sym) { + Expr->IVal = (Expr->IVal - Expr2.IVal) / rscale; + /* Get rid of unneeded flags etc. */ + ED_MakeConstAbsInt (Expr, Expr->IVal); + /* No runtime code */ + SubDone = 1; + } else if (rscale == 1 && ED_IsConstAbs (&Expr2)) { + Expr->IVal = (Expr->IVal - Expr2.IVal) / rscale; + /* No runtime code */ + SubDone = 1; + } + } + } + + if (!SubDone) { + /* We'll do runtime code */ + if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { + /* Remove pushed value from stack */ + RemoveCode (&Mark2); + /* Do the subtraction */ + g_dec (CF_INT | CF_CONST, Expr2.IVal); + } else { + /* load into the primary */ + LoadExpr (CF_NONE, &Expr2); + /* Generate code for the sub */ + g_sub (CF_INT, 0); + } + /* We must scale the result */ + if (rscale != 1) { + g_scale (CF_INT, -rscale); + } + /* Result is an rvalue in the primary register */ + ED_FinalizeRValLoad (Expr); + } else { + /* Remove pushed value from stack */ RemoveCode (&Mark1); + /* The result is always an rvalue */ + ED_MarkExprAsRVal (Expr); + } - /* Check for pointer arithmetic */ + } else if (ED_IsQuasiConst (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { + + /* Right hand side is constant. Check left hand side. */ + if (ED_IsQuasiConst (Expr)) { + + /* Both sides are constant. Check for pointer arithmetic */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ - Expr->IVal -= Expr2.IVal * CheckedPSizeOf (lhst); + rscale = CheckedPSizeOf (lhst); /* Operate on pointers, result type is a pointer */ - } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) { - /* Left is pointer, right is pointer, must scale result */ - if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { - Error ("Incompatible pointer types"); - } else { - Expr->IVal = (Expr->IVal - Expr2.IVal) / - (long)CheckedPSizeOf (lhst); - } - /* Operate on pointers, result type is an integer */ - Expr->Type = type_int; + flags = CF_PTR; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer subtraction */ - typeadjust (Expr, &Expr2, 1); - Expr->IVal -= Expr2.IVal; - - /* Limit the calculated value to the range of its type */ - LimitExprValue (Expr); + flags = typeadjust (Expr, &Expr2, 1); } else { /* OOPS */ Error ("Invalid operands for binary operator '-'"); } + /* We can't make all subtraction expressions constant */ + if (ED_IsConstAbs (&Expr2)) { + Expr->IVal -= Expr2.IVal * rscale; + /* No runtime code */ + SubDone = 1; + } else if (rscale == 1 && Expr->Sym == Expr2.Sym) { + /* The result is the diff of the offsets */ + Expr->IVal -= Expr2.IVal; + /* Get rid of unneeded bases and flags etc. */ + ED_MakeConstAbs (Expr, Expr->IVal, Expr->Type); + /* No runtime code */ + SubDone = 1; + } + + if (SubDone) { + /* Remove pushed value from stack */ + RemoveCode (&Mark1); + if (IsClassInt (lhst)) { + /* Limit the calculated value to the range of its type */ + LimitExprValue (Expr); + } + /* The result is always an rvalue */ + ED_MarkExprAsRVal (Expr); + } else { + if (ED_IsConstAbs (&Expr2)) { + /* Remove pushed value from stack */ + RemoveCode (&Mark2); + /* Do the subtraction */ + g_dec (flags | CF_CONST, Expr2.IVal); + } else { + /* Load into the primary */ + LoadExpr (CF_NONE, &Expr2); + /* Generate code for the sub (the & is a hack here) */ + g_sub (flags & ~CF_CONST, 0); + } + /* Result is an rvalue in the primary register */ + ED_FinalizeRValLoad (Expr); + } + } else { - /* Left hand side is not constant, right hand side is. - ** Remove pushed value from stack. - */ - RemoveCode (&Mark2); - + /* Left hand side is not constant, right hand side is */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ Expr2.IVal *= CheckedPSizeOf (lhst); /* Operate on pointers, result type is a pointer */ flags = CF_PTR; - } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) { - /* Left is pointer, right is pointer, must scale result */ - if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { - Error ("Incompatible pointer types"); - } else { - rscale = CheckedPSizeOf (lhst); - } - /* Operate on pointers, result type is an integer */ - flags = CF_PTR; - Expr->Type = type_int; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer subtraction */ flags = typeadjust (Expr, &Expr2, 1); @@ -3392,12 +3476,16 @@ static void parsesub (ExprDesc* Expr) flags = CF_INT; } - /* Do the subtraction */ - g_dec (flags | CF_CONST, Expr2.IVal); - - /* If this was a pointer subtraction, we must scale the result */ - if (rscale != 1) { - g_scale (flags, -rscale); + if (ED_IsConstAbs (&Expr2)) { + /* Remove pushed value from stack */ + RemoveCode (&Mark2); + /* Do the subtraction */ + g_dec (flags | CF_CONST, Expr2.IVal); + } else { + /* Rhs is not numeric, load into the primary */ + LoadExpr (CF_NONE, &Expr2); + /* Generate code for the sub (the & is a hack here) */ + g_sub (flags & ~CF_CONST, 0); } /* Result is an rvalue in the primary register */ @@ -3406,56 +3494,33 @@ static void parsesub (ExprDesc* Expr) } else { - /* Not constant, load into the primary */ + /* Right hand side is not constant, load into the primary */ LoadExpr (CF_NONE, &Expr2); - /* Right hand side is not constant. Get the rhs type. */ - rhst = Expr2.Type; - /* Check for pointer arithmetic */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ g_scale (CF_INT, CheckedPSizeOf (lhst)); /* Operate on pointers, result type is a pointer */ flags = CF_PTR; - } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) { - /* Left is pointer, right is pointer, must scale result */ - if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { - Error ("Incompatible pointer types"); - } else { - rscale = CheckedPSizeOf (lhst); - } - /* Operate on pointers, result type is an integer */ - flags = CF_PTR; - Expr->Type = type_int; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { - /* Integer subtraction. If the left hand side descriptor says that - ** the lhs is const, we have to remove this mark, since this is no - ** longer true, lhs is on stack instead. - */ - if (ED_IsLocNone (Expr)) { - ED_FinalizeRValLoad (Expr); - } /* Adjust operand types */ flags = typeadjust (Expr, &Expr2, 0); } else { /* OOPS */ Error ("Invalid operands for binary operator '-'"); - flags = CF_INT; } /* Generate code for the sub (the & is a hack here) */ g_sub (flags & ~CF_CONST, 0); - /* If this was a pointer subtraction, we must scale the result */ - if (rscale != 1) { - g_scale (flags, -rscale); - } - /* Result is an rvalue in the primary register */ ED_FinalizeRValLoad (Expr); } + /* Result type is either a pointer or an integer */ + Expr->Type = PtrConversion (Expr->Type); + /* Condition code not set */ ED_MarkAsUntested (Expr); } From f5972dfd084d4669dc4d936b19c52819efcdcbed Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 8 Feb 2021 09:03:13 +0800 Subject: [PATCH 41/80] Made int+pointer work in constant expressions. Fixed codegen for cast type addition in constant expressions. Calls on swapstk in 'i+ptr' is avoided when possible. --- src/cc65/expr.c | 295 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 210 insertions(+), 85 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index a38efab53..2d410581c 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -3045,6 +3045,9 @@ static void parseadd (ExprDesc* Expr) CodeMark Mark; /* Remember code position */ Type* lhst; /* Type of left hand side */ Type* rhst; /* Type of right hand side */ + int lscale; + int rscale; + int AddDone; /* No need to generate runtime code */ ED_Init (&Expr2); Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR; @@ -3055,44 +3058,133 @@ static void parseadd (ExprDesc* Expr) /* Get the left hand side type, initialize operation flags */ lhst = Expr->Type; flags = 0; + lscale = rscale = 1; + AddDone = 0; - /* Check for constness on both sides */ - if (ED_IsConst (Expr)) { + /* We can only do constant expressions for: + ** - integer addition: + ** - numeric + numeric + ** - (integer)(base + offset) + numeric + ** - numeric + (integer)(base + offset) + ** - pointer offset: + ** - (pointer)numeric + numeric * scale + ** - (base + offset) + numeric * scale + ** - (pointer)numeric + (integer)(base + offset) * 1 + ** - numeric * scale + (pointer)numeric + ** - numeric * scale + (base + offset) + ** - (integer)(base + offset) * 1 + (pointer)numeric + */ + if (ED_IsQuasiConst (Expr)) { /* The left hand side is a constant of some sort. Good. Get rhs */ ExprWithCheck (hie9, &Expr2); - if (ED_IsConstAbs (&Expr2)) { - /* Right hand side is a constant numeric value. Get the rhs type */ - rhst = Expr2.Type; + /* Right hand side is constant. Get the rhs type */ + rhst = Expr2.Type; + if (ED_IsQuasiConst (&Expr2)) { /* Both expressions are constants. Check for pointer arithmetic */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ - Expr->IVal += Expr2.IVal * CheckedPSizeOf (lhst); - /* Result type is a pointer */ + rscale = CheckedPSizeOf (lhst); + /* Operate on pointers, result type is a pointer */ + flags = CF_PTR; } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { /* Left is int, right is pointer, must scale lhs */ - Expr->IVal = Expr->IVal * CheckedPSizeOf (rhst) + Expr2.IVal; - /* Result type is a pointer */ - Expr->Type = Expr2.Type; + lscale = CheckedPSizeOf (rhst); + /* Operate on pointers, result type is a pointer */ + flags = CF_PTR; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ - Expr->IVal += Expr2.IVal; - typeadjust (Expr, &Expr2, 1); - - /* Limit the calculated value to the range of its type */ - LimitExprValue (Expr); + flags = CF_INT; } else { /* OOPS */ - Error ("Invalid operands for binary operator '+'"); + AddDone = -1; + } + + if (ED_IsAbs (&Expr2) && + (ED_IsAbs (Expr) || lscale == 1)) { + if (IsClassInt (lhst) && IsClassInt (rhst)) { + typeadjust (Expr, &Expr2, 1); + } + Expr->IVal = Expr->IVal * lscale + Expr2.IVal * rscale; + AddDone = 1; + } else if (ED_IsAbs (Expr) && + (ED_IsAbs (&Expr2) || rscale == 1)) { + if (IsClassInt (lhst) && IsClassInt (rhst)) { + typeadjust (&Expr2, Expr, 1); + } + Expr2.IVal = Expr->IVal * lscale + Expr2.IVal * rscale; + /* Adjust the flags */ + Expr2.Flags |= Expr->Flags & ~E_MASK_KEEP_SUBEXPR; + /* Get the symbol and the name */ + *Expr = Expr2; + AddDone = 1; + } + + if (AddDone) { + /* Adjust the result */ + if (IsClassPtr (lhst)) { + /* Result type is a pointer */ + Expr->Type = PtrConversion (lhst); + } else if (IsClassPtr (rhst)) { + /* Result type is a pointer */ + Expr->Type = PtrConversion (rhst); + } else { + /* Limit the calculated value to the range of its type */ + LimitExprValue (Expr); + } + + /* The result is always an rvalue */ + ED_MarkExprAsRVal (Expr); + } else { + /* Decide the order */ + if (!ED_IsAbs (&Expr2) && rscale > 1) { + /* Rhs needs scaling but is not numeric. Load it. */ + LoadExpr (CF_NONE, &Expr2); + /* Scale rhs */ + g_scale (CF_INT, rscale); + /* Generate the code for the add */ + if (ED_IsAbs (Expr)) { + /* Numeric constant */ + g_inc (flags | CF_CONST, Expr->IVal); + } else if (ED_IsLocStack (Expr)) { + /* Local stack address */ + g_addaddr_local (flags, Expr->IVal); + } else { + /* Static address */ + g_addaddr_static (flags | GlobalModeFlags (Expr), Expr->Name, Expr->IVal); + } + } else { + /* Lhs is not numeric. Load it. */ + LoadExpr (CF_NONE, Expr); + /* Scale lhs if necessary */ + if (lscale != 1) { + g_scale (CF_INT, lscale); + } + /* Generate the code for the add */ + if (ED_IsAbs (&Expr2)) { + /* Numeric constant */ + g_inc (flags | CF_CONST, Expr2.IVal); + } else if (ED_IsLocStack (&Expr2)) { + /* Local stack address */ + g_addaddr_local (flags, Expr2.IVal); + } else { + /* Static address */ + g_addaddr_static (flags | GlobalModeFlags (&Expr2), Expr2.Name, Expr2.IVal); + } + } + + /* Result is an rvalue in primary register */ + ED_FinalizeRValLoad (Expr); } } else { - /* lhs is a constant and rhs is not constant. Load rhs into - ** the primary. + /* lhs is constant and rhs is not constant. Load rhs into the + ** primary. */ + GetCodePos (&Mark); LoadExpr (CF_NONE, &Expr2); /* Beware: The check above (for lhs) lets not only pass numeric @@ -3100,11 +3192,8 @@ static void parseadd (ExprDesc* Expr) ** with an offset. We have to check for that here. */ - /* First, get the rhs type. */ - rhst = Expr2.Type; - /* Setup flags */ - if (ED_IsLocNone (Expr)) { + if (ED_IsAbs (Expr)) { /* A numerical constant */ flags |= CF_CONST; } else { @@ -3115,62 +3204,72 @@ static void parseadd (ExprDesc* Expr) /* Check for pointer arithmetic */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ - g_scale (CF_INT, CheckedPSizeOf (lhst)); + rscale = CheckedPSizeOf (lhst); + g_scale (CF_INT, rscale); /* Operate on pointers, result type is a pointer */ flags |= CF_PTR; - /* Generate the code for the add */ - if (ED_GetLoc (Expr) == E_LOC_NONE) { - /* Numeric constant */ - g_inc (flags, Expr->IVal); - } else { - /* Constant address */ - g_addaddr_static (flags, Expr->Name, Expr->IVal); - } } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { - /* Left is int, right is pointer, must scale lhs. */ - unsigned ScaleFactor = CheckedPSizeOf (rhst); - + lscale = CheckedPSizeOf (rhst); /* Operate on pointers, result type is a pointer */ flags |= CF_PTR; Expr->Type = Expr2.Type; - - /* Since we do already have rhs in the primary, if lhs is - ** not a numeric constant, and the scale factor is not one - ** (no scaling), we must take the long way over the stack. - */ - if (ED_IsLocNone (Expr)) { - /* Numeric constant, scale lhs */ - Expr->IVal *= ScaleFactor; - /* Generate the code for the add */ - g_inc (flags, Expr->IVal); - } else if (ScaleFactor == 1) { - /* Constant address but no need to scale */ - g_addaddr_static (flags, Expr->Name, Expr->IVal); - } else { - /* Constant address that must be scaled */ - g_push (TypeOf (Expr2.Type), 0); /* rhs --> stack */ - g_getimmed (flags, Expr->Name, Expr->IVal); - g_scale (CF_PTR, ScaleFactor); - g_add (CF_PTR, 0); - } } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ flags |= typeadjust (Expr, &Expr2, 1); - /* Generate the code for the add */ - if (ED_IsLocNone (Expr)) { - /* Numeric constant */ - g_inc (flags, Expr->IVal); - } else { - /* Constant address */ - g_addaddr_static (flags, Expr->Name, Expr->IVal); - } } else { /* OOPS */ - Error ("Invalid operands for binary operator '+'"); - flags = CF_INT; + AddDone = -1; } + /* Generate the code for the add */ + if (!AddDone) { + if (ED_IsAbs (Expr) && + Expr->IVal >= 0 && + Expr->IVal * lscale < 256) { + /* Numeric constant */ + g_inc (flags, Expr->IVal * lscale); + AddDone = 1; + } + } + + if (!AddDone) { + if (ED_IsLocQuasiConst (&Expr2) && + rscale == 1 && + CheckedSizeOf (rhst) == SIZEOF_CHAR) { + /* Change the order back */ + RemoveCode (&Mark); + /* Load lhs */ + LoadExpr (CF_NONE, Expr); + /* Use new flags */ + flags = CF_CHAR | GlobalModeFlags (&Expr2); + /* Add the variable */ + if (ED_IsLocStack (&Expr2)) { + g_addlocal (flags, Expr2.IVal); + } else { + g_addstatic (flags, Expr2.Name, Expr2.IVal); + } + } else if (ED_IsAbs (Expr)) { + /* Numeric constant */ + g_inc (flags, Expr->IVal * lscale); + } else if (lscale == 1) { + if (ED_IsLocStack (Expr)) { + /* Constant address */ + g_addaddr_local (flags, Expr->IVal); + } else { + g_addaddr_static (flags, Expr->Name, Expr->IVal); + } + } else { + /* Since we do already have rhs in the primary, if lhs is + ** not a numeric constant, and the scale factor is not one + ** (no scaling), we must take the long way over the stack. + */ + g_push (TypeOf (Expr2.Type), 0); /* rhs --> stack */ + LoadExpr (CF_NONE, Expr); + g_scale (CF_PTR, lscale); + g_add (CF_PTR, 0); + } + } /* Array and function types must be converted to pointer types */ Expr->Type = PtrConversion (Expr->Type); @@ -3181,20 +3280,21 @@ static void parseadd (ExprDesc* Expr) } else { /* Left hand side is not constant. Get the value onto the stack. */ - LoadExpr (CF_NONE, Expr); /* --> primary register */ + LoadExpr (CF_NONE, Expr); /* --> primary register */ GetCodePos (&Mark); - g_push (TypeOf (Expr->Type), 0); /* --> stack */ + flags = TypeOf (Expr->Type); /* default codegen type */ + g_push (flags, 0); /* --> stack */ /* Evaluate the rhs */ MarkedExprWithCheck (hie9, &Expr2); + /* Get the rhs type */ + rhst = Expr2.Type; + /* Check for a constant rhs expression */ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { - /* Right hand side is a constant. Get the rhs type */ - rhst = Expr2.Type; - - /* Remove pushed value from stack */ + /* Rhs is a constant. Remove pushed lhs from stack. */ RemoveCode (&Mark); /* Check for pointer arithmetic */ @@ -3214,8 +3314,7 @@ static void parseadd (ExprDesc* Expr) flags = typeadjust (Expr, &Expr2, 1); } else { /* OOPS */ - Error ("Invalid operands for binary operator '+'"); - flags = CF_INT; + AddDone = -1; } /* Generate code for the add */ @@ -3223,23 +3322,37 @@ static void parseadd (ExprDesc* Expr) } else { - /* Not constant, load into the primary */ - LoadExpr (CF_NONE, &Expr2); - - /* lhs and rhs are not constant. Get the rhs type. */ - rhst = Expr2.Type; - - /* Check for pointer arithmetic */ + /* Lhs and rhs are not so constant. Check for pointer arithmetic. */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ - g_scale (CF_INT, CheckedPSizeOf (lhst)); + rscale = CheckedPSizeOf (lhst); + if (ED_IsAbs (&Expr2)) { + Expr2.IVal *= rscale; + /* Load rhs into the primary */ + LoadExpr (CF_NONE, &Expr2); + } else { + /* Load rhs into the primary */ + LoadExpr (CF_NONE, &Expr2); + g_scale (CF_INT, rscale); + } /* Operate on pointers, result type is a pointer */ flags = CF_PTR; } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { /* Left is int, right is pointer, must scale lhs */ - g_tosint (TypeOf (lhst)); /* Make sure TOS is int */ - g_swap (CF_INT); /* Swap TOS and primary */ - g_scale (CF_INT, CheckedPSizeOf (rhst)); + lscale = CheckedPSizeOf (rhst); + if (ED_CodeRangeIsEmpty (&Expr2)) { + RemoveCode (&Mark); /* Remove pushed value from stack */ + g_scale (CF_INT, lscale); + g_push (CF_PTR, 0); /* --> stack */ + LoadExpr (CF_NONE, &Expr2); /* Load rhs into primary register */ + } else { + g_tosint (TypeOf (lhst)); /* Make sure TOS is int */ + LoadExpr (CF_NONE, &Expr2); /* Load rhs into primary register */ + if (lscale != 1) { + g_swap (CF_INT); /* Swap TOS and primary */ + g_scale (CF_INT, CheckedPSizeOf (rhst)); + } + } /* Operate on pointers, result type is a pointer */ flags = CF_PTR; Expr->Type = Expr2.Type; @@ -3254,10 +3367,12 @@ static void parseadd (ExprDesc* Expr) ** when trying to apply another solution. */ flags = typeadjust (Expr, &Expr2, 0) & ~CF_CONST; + /* Load rhs into the primary */ + LoadExpr (CF_NONE, &Expr2); } else { /* OOPS */ - Error ("Invalid operands for binary operator '+'"); - flags = CF_INT; + AddDone = -1; + /* We can't just goto End as that would leave the stack unbalanced */ } /* Generate code for the add */ @@ -3265,10 +3380,20 @@ static void parseadd (ExprDesc* Expr) } + /* Array and function types must be converted to pointer types */ + Expr->Type = PtrConversion (Expr->Type); + /* Result is an rvalue in primary register */ ED_FinalizeRValLoad (Expr); } + if (AddDone < 0) { + Error ("Invalid operands for binary operator '+'"); + } else { + /* Array and function types must be converted to pointer types */ + Expr->Type = PtrConversion (Expr->Type); + } + /* Condition code not set */ ED_MarkAsUntested (Expr); } From 99c7fe0ada96dd7283e60cc16cc63b23ab919014 Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 8 Feb 2021 09:03:23 +0800 Subject: [PATCH 42/80] Reusing code from parseadd() for ArrayRef(). Now index[ptr] works in constant expressions. Fixed codegen for cast type in constant expressions. Calls on swapstk in 'i[ptr]' is avoided when possible. --- src/cc65/expr.c | 423 +++++++++++------------------------------------- 1 file changed, 98 insertions(+), 325 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 2d410581c..e2cd09468 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -74,11 +74,20 @@ static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or }; /*****************************************************************************/ -/* Helper functions */ +/* Forward declarations */ /*****************************************************************************/ +static void parseadd (ExprDesc* Expr, int DoArrayRef); + + + +/*****************************************************************************/ +/* Helper functions */ +/*****************************************************************************/ + + static unsigned GlobalModeFlags (const ExprDesc* Expr) /* Return the addressing mode flags for the given expression */ { @@ -1333,294 +1342,6 @@ static void Primary (ExprDesc* E) -static void ArrayRef (ExprDesc* Expr) -/* Handle an array reference. This function needs a rewrite. */ -{ - int ConstBaseAddr; - ExprDesc Subscript; - CodeMark Mark1; - CodeMark Mark2; - TypeCode Qualifiers; - Type* ElementType; - Type* tptr1; - - ED_Init (&Subscript); - Subscript.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR; - - /* Skip the bracket */ - NextToken (); - - /* Get the type of left side */ - tptr1 = Expr->Type; - - /* We can apply a special treatment for arrays that have a const base - ** address. This is true for most arrays and will produce a lot better - ** code. Check if this is a "quasi-const base" address. - */ - ConstBaseAddr = ED_IsRVal (Expr) && ED_IsLocQuasiConst (Expr); - - /* If we have a quasi-const base address, we delay the address fetch */ - GetCodePos (&Mark1); - if (!ConstBaseAddr) { - /* Get a pointer to the array into the primary */ - LoadExpr (CF_NONE, Expr); - - /* Get the array pointer on stack. Do not push more than 16 - ** bit, even if this value is greater, since we cannot handle - ** other than 16bit stuff when doing indexing. - */ - GetCodePos (&Mark2); - g_push (CF_PTR, 0); - } - - /* TOS now contains ptr to array elements. Get the subscript. */ - MarkedExprWithCheck (hie0, &Subscript); - - /* Check the types of array and subscript. We can either have a - ** pointer/array to the left, in which case the subscript must be of an - ** integer type, or we have an integer to the left, in which case the - ** subscript must be a pointer/array. - ** Since we do the necessary checking here, we can rely later on the - ** correct types. - */ - Qualifiers = T_QUAL_NONE; - if (IsClassPtr (Expr->Type)) { - if (!IsClassInt (Subscript.Type)) { - Error ("Array subscript is not an integer"); - /* To avoid any compiler errors, make the expression a valid int */ - ED_MakeConstAbsInt (&Subscript, 0); - } - if (IsTypeArray (Expr->Type)) { - Qualifiers = GetQualifier (Expr->Type); - } - ElementType = Indirect (Expr->Type); - } else if (IsClassInt (Expr->Type)) { - if (!IsClassPtr (Subscript.Type)) { - Error ("Subscripted value is neither array nor pointer"); - /* To avoid compiler errors, make the subscript a char[] at - ** address 0. - */ - ED_MakeConstAbs (&Subscript, 0, GetCharArrayType (1)); - } else if (IsTypeArray (Subscript.Type)) { - Qualifiers = GetQualifier (Subscript.Type); - } - ElementType = Indirect (Subscript.Type); - } else { - Error ("Cannot subscript"); - /* To avoid compiler errors, fake both the array and the subscript, so - ** we can just proceed. - */ - ED_MakeConstAbs (Expr, 0, GetCharArrayType (1)); - ED_MakeConstAbsInt (&Subscript, 0); - ElementType = Indirect (Expr->Type); - } - - /* The element type has the combined qualifiers from itself and the array, - ** it is a member of (if any). - */ - if (GetQualifier (ElementType) != (GetQualifier (ElementType) | Qualifiers)) { - ElementType = TypeDup (ElementType); - ElementType->C |= Qualifiers; - } - - /* If the subscript is a bit-field, load it and make it an rvalue */ - if (ED_IsBitField (&Subscript)) { - LoadExpr (CF_NONE, &Subscript); - ED_FinalizeRValLoad (&Subscript); - } - - /* Make the address of the array element from the base and subscript */ - if (ED_IsConstAbs (&Subscript) && ED_CodeRangeIsEmpty (&Subscript)) { - - /* The array subscript is a constant. Since we can have the element - ** address directly as base+offset, we can remove the array address - ** push onto the stack before if loading subscript doesn't tamper that - ** address in the primary. - */ - if (!ConstBaseAddr) { - RemoveCode (&Mark2); - } else { - /* Get an array pointer into the primary */ - LoadExpr (CF_NONE, Expr); - } - - if (IsClassPtr (Expr->Type)) { - - /* Lhs is pointer/array. Scale the subscript value according to - ** the element size. - */ - Subscript.IVal *= CheckedSizeOf (ElementType); - - /* Remove the address load code */ - RemoveCode (&Mark1); - - /* In case of an array, we can adjust the offset of the expression - ** already in Expr. If the base address was a constant, we can even - ** remove the code that loaded the address into the primary. - */ - if (!IsTypeArray (Expr->Type)) { - - /* It's a pointer, so we do have to load it into the primary - ** first (if it's not already there). - */ - if (!ConstBaseAddr && ED_IsLVal (Expr)) { - LoadExpr (CF_NONE, Expr); - ED_FinalizeRValLoad (Expr); - } - } - - /* Adjust the offset */ - Expr->IVal += Subscript.IVal; - - } else { - - /* Scale the lhs value according to the element type */ - g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType)); - - /* Add the subscript. Since arrays are indexed by integers, - ** we will ignore the true type of the subscript here and - ** use always an int. #### Use offset but beware of LoadExpr! - */ - g_inc (CF_INT | CF_CONST, Subscript.IVal); - - } - - } else { - - /* Array subscript is not constant. Load it into the primary */ - GetCodePos (&Mark2); - LoadExpr (CF_NONE, &Subscript); - - /* Do scaling */ - if (IsClassPtr (Expr->Type)) { - - /* Indexing is based on unsigneds, so we will just use the integer - ** portion of the index (which is in (e)ax, so there's no further - ** action required). - */ - g_scale (CF_INT, CheckedSizeOf (ElementType)); - - } else { - - /* Get the int value on top. If we come here, we're sure, both - ** values are 16 bit (the first one was truncated if necessary - ** and the second one is a pointer). Note: If ConstBaseAddr is - ** true, we don't have a value on stack, so to "swap" both, just - ** push the subscript. - */ - if (ConstBaseAddr) { - g_push (CF_INT, 0); - LoadExpr (CF_NONE, Expr); - ConstBaseAddr = 0; - } else { - g_swap (CF_INT); - } - - /* Scale it */ - g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType)); - - } - - /* The offset is now in the primary register. It we didn't have a - ** constant base address for the lhs, the lhs address is already - ** on stack, and we must add the offset. If the base address was - ** constant, we call special functions to add the address to the - ** offset value. - */ - if (!ConstBaseAddr) { - - /* The array base address is on stack and the subscript is in the - ** primary. Add both. - */ - g_add (CF_INT, 0); - - } else { - - /* The subscript is in the primary, and the array base address is - ** in Expr. If the subscript has itself a constant address, it is - ** often a better idea to reverse again the order of the - ** evaluation. This will generate better code if the subscript is - ** a byte sized variable. But beware: This is only possible if the - ** subscript was not scaled, that is, if this was a byte array - ** or pointer. - */ - if (ED_IsLocQuasiConst (&Subscript) && - CheckedSizeOf (ElementType) == SIZEOF_CHAR) { - - unsigned Flags; - - /* Reverse the order of evaluation */ - if (CheckedSizeOf (Subscript.Type) == SIZEOF_CHAR) { - Flags = CF_CHAR; - } else { - Flags = CF_INT; - } - RemoveCode (&Mark2); - - /* Get a pointer to the array into the primary. */ - LoadExpr (CF_NONE, Expr); - - /* Add the variable */ - if (ED_IsLocStack (&Subscript)) { - g_addlocal (Flags, Subscript.IVal); - } else { - Flags |= GlobalModeFlags (&Subscript); - g_addstatic (Flags, Subscript.Name, Subscript.IVal); - } - } else { - - if (ED_IsLocNone (Expr) || - (ED_IsLocAbs (Expr) && ED_IsAddrExpr (Expr))) { - /* Constant numeric address. Just add it */ - g_inc (CF_INT, Expr->IVal); - } else if (ED_IsLocStack (Expr)) { - /* Base address is a local variable address */ - if (ED_IsAddrExpr (Expr)) { - g_addaddr_local (CF_INT, Expr->IVal); - } else { - g_addlocal (CF_PTR, Expr->IVal); - } - } else { - /* Base address is a static variable address */ - unsigned Flags = CF_INT | GlobalModeFlags (Expr); - if (ED_IsAddrExpr (Expr)) { - /* Add the address of the location */ - g_addaddr_static (Flags, Expr->Name, Expr->IVal); - } else { - /* Add the contents of the location */ - g_addstatic (Flags, Expr->Name, Expr->IVal); - } - } - } - } - - /* The address of the element is an rvalue in the primary */ - ED_FinalizeRValLoad (Expr); - - } - - /* The final result is usually an lvalue expression of element type - ** referenced in the primary, unless it is once again an array. We can just - ** assume the usual case first, and change it later if necessary. - */ - ED_IndExpr (Expr); - Expr->Type = ElementType; - - /* An array element is actually a variable. So the rules for variables with - ** respect to the reference type apply: If it's an array, it is virtually - ** an rvalue address, otherwise it's an lvalue reference. (A function would - ** also be an rvalue address, but an array cannot contain functions). - */ - if (IsTypeArray (Expr->Type)) { - ED_AddrExpr (Expr); - } - - /* Consume the closing bracket */ - ConsumeRBrack (); -} - - - static void StructRef (ExprDesc* Expr) /* Process struct/union field after . or ->. */ { @@ -1793,7 +1514,7 @@ static void hie11 (ExprDesc *Expr) case TOK_LBRACK: /* Array reference */ - ArrayRef (Expr); + parseadd (Expr, 1); break; case TOK_LPAREN: @@ -3034,10 +2755,11 @@ static void hie9 (ExprDesc *Expr) -static void parseadd (ExprDesc* Expr) -/* Parse an expression with the binary plus operator. Expr contains the -** unprocessed left hand side of the expression and will contain the -** result of the expression on return. +static void parseadd (ExprDesc* Expr, int DoArrayRef) +/* Parse an expression with the binary plus or subscript operator. Expr contains +** the unprocessed left hand side of the expression and will contain the result +** of the expression on return. If DoArrayRef is zero, this evaluates the binary +** plus operation. Otherwise, this evaluates the subscript operation. */ { ExprDesc Expr2; @@ -3052,7 +2774,7 @@ static void parseadd (ExprDesc* Expr) ED_Init (&Expr2); Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR; - /* Skip the PLUS token */ + /* Skip the PLUS or opening bracket token */ NextToken (); /* Get the left hand side type, initialize operation flags */ @@ -3077,7 +2799,7 @@ static void parseadd (ExprDesc* Expr) if (ED_IsQuasiConst (Expr)) { /* The left hand side is a constant of some sort. Good. Get rhs */ - ExprWithCheck (hie9, &Expr2); + ExprWithCheck (DoArrayRef ? hie0 : hie9, &Expr2); /* Right hand side is constant. Get the rhs type */ rhst = Expr2.Type; @@ -3094,7 +2816,7 @@ static void parseadd (ExprDesc* Expr) lscale = CheckedPSizeOf (rhst); /* Operate on pointers, result type is a pointer */ flags = CF_PTR; - } else if (IsClassInt (lhst) && IsClassInt (rhst)) { + } else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ flags = CF_INT; } else { @@ -3123,20 +2845,22 @@ static void parseadd (ExprDesc* Expr) } if (AddDone) { - /* Adjust the result */ - if (IsClassPtr (lhst)) { - /* Result type is a pointer */ - Expr->Type = PtrConversion (lhst); - } else if (IsClassPtr (rhst)) { - /* Result type is a pointer */ - Expr->Type = PtrConversion (rhst); - } else { - /* Limit the calculated value to the range of its type */ - LimitExprValue (Expr); - } + /* Adjust the result for addition */ + if (!DoArrayRef) { + if (IsClassPtr (lhst)) { + /* Result type is a pointer */ + Expr->Type = lhst; + } else if (IsClassPtr (rhst)) { + /* Result type is a pointer */ + Expr->Type = rhst; + } else { + /* Limit the calculated value to the range of its type */ + LimitExprValue (Expr); + } - /* The result is always an rvalue */ - ED_MarkExprAsRVal (Expr); + /* The result is always an rvalue */ + ED_MarkExprAsRVal (Expr); + } } else { /* Decide the order */ if (!ED_IsAbs (&Expr2) && rscale > 1) { @@ -3214,7 +2938,7 @@ static void parseadd (ExprDesc* Expr) /* Operate on pointers, result type is a pointer */ flags |= CF_PTR; Expr->Type = Expr2.Type; - } else if (IsClassInt (lhst) && IsClassInt (rhst)) { + } else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ flags |= typeadjust (Expr, &Expr2, 1); } else { @@ -3270,8 +2994,6 @@ static void parseadd (ExprDesc* Expr) g_add (CF_PTR, 0); } } - /* Array and function types must be converted to pointer types */ - Expr->Type = PtrConversion (Expr->Type); /* Result is an rvalue in primary register */ ED_FinalizeRValLoad (Expr); @@ -3286,7 +3008,7 @@ static void parseadd (ExprDesc* Expr) g_push (flags, 0); /* --> stack */ /* Evaluate the rhs */ - MarkedExprWithCheck (hie9, &Expr2); + MarkedExprWithCheck (DoArrayRef ? hie0 : hie9, &Expr2); /* Get the rhs type */ rhst = Expr2.Type; @@ -3309,7 +3031,7 @@ static void parseadd (ExprDesc* Expr) /* Operate on pointers, result type is a pointer */ flags = CF_PTR; Expr->Type = Expr2.Type; - } else if (IsClassInt (lhst) && IsClassInt (rhst)) { + } else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ flags = typeadjust (Expr, &Expr2, 1); } else { @@ -3356,7 +3078,7 @@ static void parseadd (ExprDesc* Expr) /* Operate on pointers, result type is a pointer */ flags = CF_PTR; Expr->Type = Expr2.Type; - } else if (IsClassInt (lhst) && IsClassInt (rhst)) { + } else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition. Note: Result is never constant. ** Problem here is that typeadjust does not know if the ** variable is an rvalue or lvalue, so if both operands @@ -3380,18 +3102,69 @@ static void parseadd (ExprDesc* Expr) } - /* Array and function types must be converted to pointer types */ - Expr->Type = PtrConversion (Expr->Type); - /* Result is an rvalue in primary register */ ED_FinalizeRValLoad (Expr); } - if (AddDone < 0) { - Error ("Invalid operands for binary operator '+'"); + /* Deal with array ref */ + if (DoArrayRef) { + TypeCode Qualifiers = T_QUAL_NONE; + Type* ElementType; + + /* Check the types of array and subscript */ + if (IsClassPtr (lhst)) { + if (!IsClassInt (rhst)) { + Error ("Array subscript is not an integer"); + ED_MakeConstAbs (Expr, 0, GetCharArrayType (1)); + } else if (IsTypeArray (lhst)) { + Qualifiers = GetQualifier (lhst); + } + } else if (IsClassInt (lhst)) { + if (!IsClassPtr (rhst)) { + Error ("Subscripted value is neither array nor pointer"); + ED_MakeConstAbs (Expr, 0, GetCharArrayType (1)); + } else if (IsTypeArray (rhst)) { + Qualifiers = GetQualifier (rhst); + } + } else { + Error ("Cannot subscript"); + ED_MakeConstAbs (Expr, 0, GetCharArrayType (1)); + } + + /* The element type has the combined qualifiers from itself and the array, + ** it is a member of (if any). + */ + ElementType = Indirect (Expr->Type); + if (GetQualifier (ElementType) != (GetQualifier (ElementType) | Qualifiers)) { + ElementType = TypeDup (ElementType); + ElementType->C |= Qualifiers; + } + + /* The final result is usually an lvalue expression of element type + ** referenced in the primary, unless it is once again an array. We can just + ** assume the usual case first, and change it later if necessary. + */ + ED_IndExpr (Expr); + Expr->Type = ElementType; + + /* An array element is actually a variable. So the rules for variables with + ** respect to the reference type apply: If it's an array, it is virtually + ** an rvalue address, otherwise it's an lvalue reference. (A function would + ** also be an rvalue address, but an array cannot contain functions). + */ + if (IsTypeArray (Expr->Type)) { + ED_AddrExpr (Expr); + } + + /* Consume the closing bracket */ + ConsumeRBrack (); } else { - /* Array and function types must be converted to pointer types */ - Expr->Type = PtrConversion (Expr->Type); + if (AddDone < 0) { + Error ("Invalid operands for binary operator '+'"); + } else { + /* Array and function types must be converted to pointer types */ + Expr->Type = PtrConversion (Expr->Type); + } } /* Condition code not set */ @@ -3436,7 +3209,7 @@ static void parsesub (ExprDesc* Expr) /* Remember the output queue position, then bring the value onto the stack */ GetCodePos (&Mark1); - LoadExpr (CF_NONE, Expr); /* --> primary register */ + LoadExpr (CF_NONE, Expr); /* --> primary register */ GetCodePos (&Mark2); g_push (TypeOf (lhst), 0); /* --> stack */ @@ -3658,7 +3431,7 @@ void hie8 (ExprDesc* Expr) ExprWithCheck (hie9, Expr); while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) { if (CurTok.Tok == TOK_PLUS) { - parseadd (Expr); + parseadd (Expr, 0); } else { parsesub (Expr); } From 8eeaaa3f36a973fdae29e7c66cc519104376c4d4 Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 15 Feb 2021 09:50:46 +0800 Subject: [PATCH 43/80] Made certain types of comparison between addresses in constant expressions work. --- src/cc65/expr.c | 109 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 36 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index e2cd09468..6684d9c56 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -2361,7 +2361,6 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ void (*hienext) (ExprDesc*)) /* Helper function for the compare operators */ { - CodeMark Mark0; CodeMark Mark1; CodeMark Mark2; const GenDesc* Gen; @@ -2370,7 +2369,6 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ int rconst; /* Operand is a constant */ - GetCodePos (&Mark0); ExprWithCheck (hienext, Expr); while ((Gen = FindGen (CurTok.Tok, Ops)) != 0) { @@ -2395,11 +2393,11 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ GetCodePos (&Mark1); ltype = TypeOf (Expr->Type); if (ED_IsConstAbs (Expr)) { - /* Constant value */ + /* Numeric constant value */ GetCodePos (&Mark2); g_push (ltype | CF_CONST, Expr->IVal); } else { - /* Value not constant */ + /* Value not numeric constant */ LoadExpr (CF_NONE, Expr); GetCodePos (&Mark2); g_push (ltype, 0); @@ -2413,10 +2411,10 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ Expr2.Type = PointerTo (Expr2.Type); } - /* Check for a constant expression */ + /* Check for a numeric constant expression */ rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)); if (!rconst) { - /* Not constant, load into the primary */ + /* Not numeric constant, load into the primary */ LoadExpr (CF_NONE, &Expr2); } @@ -2475,10 +2473,76 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ } } - /* Check for const operands */ - if (ED_IsConstAbs (Expr) && rconst) { + /* Check for numeric constant operands */ + if ((ED_IsAddrExpr (Expr) && ED_IsNullPtr (&Expr2)) || + (ED_IsNullPtr (Expr) && ED_IsAddrExpr (&Expr2))) { - /* Both operands are constant, remove the generated code */ + /* Object addresses are inequal to null pointer */ + Expr->IVal = (Tok != TOK_EQ); + if (ED_IsNullPtr (&Expr2)) { + if (Tok == TOK_LT || Tok == TOK_LE) { + Expr->IVal = 0; + } + } else { + if (Tok == TOK_GT || Tok == TOK_GE) { + Expr->IVal = 0; + } + } + + /* Get rid of unwanted flags */ + ED_MakeConstBool (Expr, Expr->IVal); + + /* The result is constant, this is suspicious when not in + ** preprocessor mode. + */ + WarnConstCompareResult (Expr); + + if (ED_CodeRangeIsEmpty (&Expr2)) { + /* Both operands are static, remove the load code */ + RemoveCode (&Mark1); + } else { + /* Drop pushed lhs */ + g_drop (sizeofarg (ltype)); + pop (ltype); + } + + } else if (ED_IsAddrExpr (Expr) && + ED_IsAddrExpr (&Expr2) && + Expr->Sym == Expr2.Sym) { + + /* Evaluate the result for static addresses */ + unsigned long Val1 = Expr->IVal; + unsigned long Val2 = Expr2.IVal; + switch (Tok) { + case TOK_EQ: Expr->IVal = (Val1 == Val2); break; + case TOK_NE: Expr->IVal = (Val1 != Val2); break; + case TOK_LT: Expr->IVal = (Val1 < Val2); break; + case TOK_LE: Expr->IVal = (Val1 <= Val2); break; + case TOK_GE: Expr->IVal = (Val1 >= Val2); break; + case TOK_GT: Expr->IVal = (Val1 > Val2); break; + default: Internal ("hie_compare: got token 0x%X\n", Tok); + } + + /* Get rid of unwanted flags */ + ED_MakeConstBool (Expr, Expr->IVal); + + /* If the result is constant, this is suspicious when not in + ** preprocessor mode. + */ + WarnConstCompareResult (Expr); + + if (ED_CodeRangeIsEmpty (&Expr2)) { + /* Both operands are static, remove the load code */ + RemoveCode (&Mark1); + } else { + /* Drop pushed lhs */ + g_drop (sizeofarg (ltype)); + pop (ltype); + } + + } else if (ED_IsConstAbs (Expr) && rconst) { + + /* Both operands are numeric constant, remove the generated code */ RemoveCode (&Mark1); /* Determine if this is a signed or unsigned compare */ @@ -2522,33 +2586,6 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ */ WarnConstCompareResult (Expr); - } else if (ED_CodeRangeIsEmpty (&Expr2) && - ((ED_IsAddrExpr (Expr) && ED_IsNullPtr (&Expr2)) || - (ED_IsNullPtr (Expr) && (ED_IsAddrExpr (&Expr2))))) { - - /* Object addresses are inequal to null pointer */ - Expr->IVal = (Tok != TOK_EQ); - if (ED_IsNullPtr (&Expr2)) { - if (Tok == TOK_LT || Tok == TOK_LE) { - Expr->IVal = 0; - } - } else { - if (Tok == TOK_GT || Tok == TOK_GE) { - Expr->IVal = 0; - } - } - - /* Get rid of unwanted flags */ - ED_MakeConstBool (Expr, Expr->IVal); - - /* If the result is constant, this is suspicious when not in - ** preprocessor mode. - */ - WarnConstCompareResult (Expr); - - /* Both operands are static, remove the generated code */ - RemoveCode (&Mark1); - } else { /* Determine the signedness of the operands */ From b02838439c0c4a237e6094b71415193e44485be4 Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 22 Feb 2021 12:33:26 +0800 Subject: [PATCH 44/80] Changed g_addaddr_local() codegen to reduce code size. --- src/cc65/codegen.c | 51 +++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index bf7c900ab..f8a1dcdf6 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -2112,29 +2112,38 @@ void g_addaddr_local (unsigned flags attribute ((unused)), int offs) /* Add the offset */ offs -= StackPtr; - if (offs != 0) { - /* We cannot address more then 256 bytes of locals anyway */ - L = GetLocalLabel(); - CheckLocalOffs (offs); - AddCodeLine ("clc"); - AddCodeLine ("adc #$%02X", offs & 0xFF); - /* Do also skip the CLC insn below */ - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("inx"); - } + if (IS_Get (&CodeSizeFactor) <= 100) { + if (offs != 0) { + /* We cannot address more then 256 bytes of locals anyway */ + g_inc (CF_INT | CF_CONST, offs); + } + /* Add the current stackpointer value */ + AddCodeLine ("jsr leaaxsp"); + } else { + if (offs != 0) { + /* We cannot address more then 256 bytes of locals anyway */ + L = GetLocalLabel(); + CheckLocalOffs (offs); + AddCodeLine ("clc"); + AddCodeLine ("adc #$%02X", offs & 0xFF); + /* Do also skip the CLC insn below */ + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("inx"); + } - /* Add the current stackpointer value */ - AddCodeLine ("clc"); - if (L != 0) { - /* Label was used above */ - g_defcodelabel (L); + /* Add the current stackpointer value */ + AddCodeLine ("clc"); + if (L != 0) { + /* Label was used above */ + g_defcodelabel (L); + } + AddCodeLine ("adc sp"); + AddCodeLine ("tay"); + AddCodeLine ("txa"); + AddCodeLine ("adc sp+1"); + AddCodeLine ("tax"); + AddCodeLine ("tya"); } - AddCodeLine ("adc sp"); - AddCodeLine ("tay"); - AddCodeLine ("txa"); - AddCodeLine ("adc sp+1"); - AddCodeLine ("tax"); - AddCodeLine ("tya"); } From d3c495e8b99a385231720358f5f4464866cd3ea8 Mon Sep 17 00:00:00 2001 From: Christian Groessler Date: Tue, 16 Feb 2021 22:19:34 +0100 Subject: [PATCH 45/80] ar65: fix parallel builds by using a per-process temp file --- src/ar65/library.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ar65/library.c b/src/ar65/library.c index 08fdeb563..fd761d04e 100644 --- a/src/ar65/library.c +++ b/src/ar65/library.c @@ -249,9 +249,10 @@ void LibOpen (const char* Name, int MustExist, int NeedTemp) if (NeedTemp) { /* Create the temporary library name */ - NewLibName = xmalloc (strlen (Name) + strlen (".temp") + 1); + NewLibName = xmalloc (strlen (Name) + strlen (".temp-") + 8 + 1); strcpy (NewLibName, Name); - strcat (NewLibName, ".temp"); + strcat (NewLibName, ".temp-"); + sprintf (NewLibName + strlen (NewLibName), "%X", (unsigned int)getpid()); /* Create the temporary library */ NewLib = fopen (NewLibName, "w+b"); From 64449f0f54496908d183510ac617da8a8b11acca Mon Sep 17 00:00:00 2001 From: Christian Groessler Date: Wed, 17 Feb 2021 00:36:58 +0100 Subject: [PATCH 46/80] ar65: better version of last change --- src/ar65/library.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ar65/library.c b/src/ar65/library.c index fd761d04e..c142df99a 100644 --- a/src/ar65/library.c +++ b/src/ar65/library.c @@ -249,10 +249,8 @@ void LibOpen (const char* Name, int MustExist, int NeedTemp) if (NeedTemp) { /* Create the temporary library name */ - NewLibName = xmalloc (strlen (Name) + strlen (".temp-") + 8 + 1); - strcpy (NewLibName, Name); - strcat (NewLibName, ".temp-"); - sprintf (NewLibName + strlen (NewLibName), "%X", (unsigned int)getpid()); + NewLibName = xmalloc (strlen (Name) + (sizeof (".temp-") - 1) + 2 * sizeof (unsigned int) + 1); + sprintf (NewLibName, "%s.temp-%X", Name, (unsigned int)getpid ()); /* Create the temporary library */ NewLib = fopen (NewLibName, "w+b"); From 358d750b3e8379b3f36d8bf9c514532e4d51743a Mon Sep 17 00:00:00 2001 From: Christian Groessler Date: Tue, 16 Feb 2021 22:19:34 +0100 Subject: [PATCH 47/80] ar65: fix parallel builds by using a per-process temp file --- src/ar65/library.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ar65/library.c b/src/ar65/library.c index c142df99a..991cfe110 100644 --- a/src/ar65/library.c +++ b/src/ar65/library.c @@ -36,6 +36,8 @@ #include #include #include +#include +#include /* common */ #include "cmdline.h" From 9b05fe9982a1c377d224071e4f68a813283a7b50 Mon Sep 17 00:00:00 2001 From: Christian Groessler Date: Thu, 18 Mar 2021 20:08:22 +0100 Subject: [PATCH 48/80] src/ar65/library.c: fix compilation on Windows --- src/ar65/library.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ar65/library.c b/src/ar65/library.c index 991cfe110..342bc25d3 100644 --- a/src/ar65/library.c +++ b/src/ar65/library.c @@ -36,8 +36,12 @@ #include #include #include +#if defined(_WIN32) +#include +#else #include #include +#endif /* common */ #include "cmdline.h" From cd116e5ba06293b1b0dff81b6b3bebaff6b6e765 Mon Sep 17 00:00:00 2001 From: Christian Groessler Date: Thu, 18 Mar 2021 20:18:23 +0100 Subject: [PATCH 49/80] src/ar65/library.c: style fix --- src/ar65/library.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ar65/library.c b/src/ar65/library.c index 342bc25d3..d12fb198a 100644 --- a/src/ar65/library.c +++ b/src/ar65/library.c @@ -37,10 +37,10 @@ #include #include #if defined(_WIN32) -#include +# include #else -#include -#include +# include +# include #endif /* common */ From 6974c1ff12981f29b74ca183ac405edd293360f6 Mon Sep 17 00:00:00 2001 From: acqn Date: Fri, 19 Mar 2021 15:02:53 +0800 Subject: [PATCH 50/80] Fixed and cleaned up codegen logic with arithmetic conversion in addition and subtraction. --- src/cc65/expr.c | 60 +++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 6684d9c56..4f579b7ae 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -2861,17 +2861,18 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef) AddDone = -1; } + /* Do constant calculation if we can */ if (ED_IsAbs (&Expr2) && (ED_IsAbs (Expr) || lscale == 1)) { if (IsClassInt (lhst) && IsClassInt (rhst)) { - typeadjust (Expr, &Expr2, 1); + Expr->Type = ArithmeticConvert (Expr->Type, Expr2.Type); } Expr->IVal = Expr->IVal * lscale + Expr2.IVal * rscale; AddDone = 1; } else if (ED_IsAbs (Expr) && (ED_IsAbs (&Expr2) || rscale == 1)) { if (IsClassInt (lhst) && IsClassInt (rhst)) { - typeadjust (&Expr2, Expr, 1); + Expr2.Type = ArithmeticConvert (Expr2.Type, Expr->Type); } Expr2.IVal = Expr->IVal * lscale + Expr2.IVal * rscale; /* Adjust the flags */ @@ -3053,7 +3054,7 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef) /* Check for a constant rhs expression */ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { - /* Rhs is a constant. Remove pushed lhs from stack. */ + /* Rhs is a numeric constant. Remove pushed lhs from stack. */ RemoveCode (&Mark); /* Check for pointer arithmetic */ @@ -3081,7 +3082,7 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef) } else { - /* Lhs and rhs are not so constant. Check for pointer arithmetic. */ + /* Lhs and rhs are not so "numeric constant". Check for pointer arithmetic. */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ rscale = CheckedPSizeOf (lhst); @@ -3116,16 +3117,8 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef) flags = CF_PTR; Expr->Type = Expr2.Type; } else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) { - /* Integer addition. Note: Result is never constant. - ** Problem here is that typeadjust does not know if the - ** variable is an rvalue or lvalue, so if both operands - ** are dereferenced constant numeric addresses, typeadjust - ** thinks the operation works on constants. Removing - ** CF_CONST here means handling the symptoms, however, the - ** whole parser is such a mess that I fear to break anything - ** when trying to apply another solution. - */ - flags = typeadjust (Expr, &Expr2, 0) & ~CF_CONST; + /* Integer addition */ + flags = typeadjust (Expr, &Expr2, 0); /* Load rhs into the primary */ LoadExpr (CF_NONE, &Expr2); } else { @@ -3134,8 +3127,8 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef) /* We can't just goto End as that would leave the stack unbalanced */ } - /* Generate code for the add */ - g_add (flags, 0); + /* Generate code for the add (the & is a hack here) */ + g_add (flags & ~CF_CONST, 0); } @@ -3348,8 +3341,7 @@ static void parsesub (ExprDesc* Expr) /* Operate on pointers, result type is a pointer */ flags = CF_PTR; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { - /* Integer subtraction */ - flags = typeadjust (Expr, &Expr2, 1); + /* Integer subtraction. We'll adjust the types later */ } else { /* OOPS */ Error ("Invalid operands for binary operator '-'"); @@ -3370,10 +3362,12 @@ static void parsesub (ExprDesc* Expr) } if (SubDone) { - /* Remove pushed value from stack */ + /* Remove loaded and pushed value from stack */ RemoveCode (&Mark1); if (IsClassInt (lhst)) { - /* Limit the calculated value to the range of its type */ + /* Just adjust the result type */ + Expr->Type = ArithmeticConvert (Expr->Type, Expr2.Type); + /* And limit the calculated value to the range of it */ LimitExprValue (Expr); } /* The result is always an rvalue */ @@ -3382,10 +3376,18 @@ static void parsesub (ExprDesc* Expr) if (ED_IsConstAbs (&Expr2)) { /* Remove pushed value from stack */ RemoveCode (&Mark2); + if (IsClassInt (lhst)) { + /* Adjust the types */ + flags = typeadjust (Expr, &Expr2, 1); + } /* Do the subtraction */ g_dec (flags | CF_CONST, Expr2.IVal); } else { - /* Load into the primary */ + if (IsClassInt (lhst)) { + /* Adjust the types */ + flags = typeadjust (Expr, &Expr2, 0); + } + /* Load rhs into the primary */ LoadExpr (CF_NONE, &Expr2); /* Generate code for the sub (the & is a hack here) */ g_sub (flags & ~CF_CONST, 0); @@ -3403,8 +3405,7 @@ static void parsesub (ExprDesc* Expr) /* Operate on pointers, result type is a pointer */ flags = CF_PTR; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { - /* Integer subtraction */ - flags = typeadjust (Expr, &Expr2, 1); + /* Integer subtraction. We'll adjust the types later */ } else { /* OOPS */ Error ("Invalid operands for binary operator '-'"); @@ -3414,10 +3415,18 @@ static void parsesub (ExprDesc* Expr) if (ED_IsConstAbs (&Expr2)) { /* Remove pushed value from stack */ RemoveCode (&Mark2); + if (IsClassInt (lhst)) { + /* Adjust the types */ + flags = typeadjust (Expr, &Expr2, 1); + } /* Do the subtraction */ g_dec (flags | CF_CONST, Expr2.IVal); } else { - /* Rhs is not numeric, load into the primary */ + if (IsClassInt (lhst)) { + /* Adjust the types */ + flags = typeadjust (Expr, &Expr2, 0); + } + /* Load rhs into the primary */ LoadExpr (CF_NONE, &Expr2); /* Generate code for the sub (the & is a hack here) */ g_sub (flags & ~CF_CONST, 0); @@ -3429,6 +3438,9 @@ static void parsesub (ExprDesc* Expr) } else { + /* We'll use the pushed lhs on stack instead of the original source */ + ED_FinalizeRValLoad (Expr); + /* Right hand side is not constant, load into the primary */ LoadExpr (CF_NONE, &Expr2); From 9ec9d1e20c5c730869371766aae6be96e4404db4 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Fri, 19 Mar 2021 20:53:52 +0100 Subject: [PATCH 51/80] test for issue #1431 / pr #1424 --- test/val/bug1431.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 test/val/bug1431.c diff --git a/test/val/bug1431.c b/test/val/bug1431.c new file mode 100644 index 000000000..9eae3bdbd --- /dev/null +++ b/test/val/bug1431.c @@ -0,0 +1,33 @@ +/* +$ cl65 -Osir --codesize 180 -S -o main.s main.c +main.c(9): Internal compiler error: +Code generation messed up: StackPtr is -2, should be -4 + +Input: if (wcnt > btw) { + +$ git bisect bad +aa6fdf58b8a17b747090fb521f3d9106e0c56d1c is the first bad commit +commit aa6fdf58b8a17b747090fb521f3d9106e0c56d1c +Author: acqn +Date: Mon Feb 8 09:03:19 2021 +0800 + + Addresses in constant subtraction expressions now work. + Fixed codegen for cast type subtraction in constant expressions. +*/ + +unsigned long fptr = 0x40001; + +int main(void) +{ + unsigned int btw = 500; + unsigned int wcnt; + + wcnt = 512U - (fptr % 512U); + + if (wcnt > btw) { + wcnt = btw; + } + + return wcnt == 500 ? 0 : 1; +} + From 7d528d9eb0e3e667e198850ce46ca98c7adf0ca7 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Fri, 19 Mar 2021 22:26:49 +0100 Subject: [PATCH 52/80] fix typo --- include/cbm_screen_charmap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cbm_screen_charmap.h b/include/cbm_screen_charmap.h index 76e0d7d7b..5bf4c3f90 100644 --- a/include/cbm_screen_charmap.h +++ b/include/cbm_screen_charmap.h @@ -8,7 +8,7 @@ /* from ASCII to screen-code mapping, so you can write directly */ /* to the screen memory. */ /* */ -/* If this include is used, no additional macroes are needed. */ +/* If this include is used, no additional macros are needed. */ /* */ /*****************************************************************************/ From 57e69d964710593ccdee028104e9a5aa0b04760f Mon Sep 17 00:00:00 2001 From: mrdudz Date: Fri, 19 Mar 2021 23:35:34 +0100 Subject: [PATCH 53/80] test related to pr #1425 --- test/val/pr1425.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 test/val/pr1425.c diff --git a/test/val/pr1425.c b/test/val/pr1425.c new file mode 100644 index 000000000..e3ae23ba3 --- /dev/null +++ b/test/val/pr1425.c @@ -0,0 +1,45 @@ + +/* pr #1425 - Ternary fixes */ + +unsigned char fails = 0; + +void test1(void) +{ + int x = 0; + x ? (void)x-- : (void)1; + if (x != 0) { + fails++; + } +} + +int test2(void) +{ + int x = 0, y = 0; + x ? (void)x--, (void)y++ : (void)1; + if (x != 0) { + fails++; + } + if (y != 0) { + fails++; + } +} + +void test3(void) +{ + int x = 0, y = 0; + x ? ((void)x--, (void)y++) : (void)1; + if (x != 0) { + fails++; + } + if (y != 0) { + fails++; + } +} + +int main(void) +{ + test1(); + test2(); + test3(); + return fails; +} From cc040ca04a861030de751c70a52dc2fcd2c06727 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Fri, 19 Mar 2021 23:39:56 +0100 Subject: [PATCH 54/80] remove, fucking git --- test/val/pr1425.c | 45 --------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 test/val/pr1425.c diff --git a/test/val/pr1425.c b/test/val/pr1425.c deleted file mode 100644 index e3ae23ba3..000000000 --- a/test/val/pr1425.c +++ /dev/null @@ -1,45 +0,0 @@ - -/* pr #1425 - Ternary fixes */ - -unsigned char fails = 0; - -void test1(void) -{ - int x = 0; - x ? (void)x-- : (void)1; - if (x != 0) { - fails++; - } -} - -int test2(void) -{ - int x = 0, y = 0; - x ? (void)x--, (void)y++ : (void)1; - if (x != 0) { - fails++; - } - if (y != 0) { - fails++; - } -} - -void test3(void) -{ - int x = 0, y = 0; - x ? ((void)x--, (void)y++) : (void)1; - if (x != 0) { - fails++; - } - if (y != 0) { - fails++; - } -} - -int main(void) -{ - test1(); - test2(); - test3(); - return fails; -} From a51d6d40de4a6a60d27c472358cd4e1ece5f5986 Mon Sep 17 00:00:00 2001 From: acqn Date: Sun, 14 Mar 2021 02:39:40 +0800 Subject: [PATCH 55/80] Ternary fix for some obscure cases. --- src/cc65/expr.c | 66 +++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 4f579b7ae..422159c4b 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -3987,24 +3987,24 @@ static void hieQuest (ExprDesc* Expr) */ ExprWithCheck (hie1, &Expr2); Expr2IsNULL = ED_IsNullPtr (&Expr2); - if (!IsTypeVoid (Expr2.Type)) { - if (!ConstantCond || !ED_IsConst (&Expr2)) { - /* Load it into the primary */ - LoadExpr (CF_NONE, &Expr2); + if (!IsTypeVoid (Expr2.Type) && + ED_YetToLoad (&Expr2) && + (!ConstantCond || !ED_IsConst (&Expr2))) { + /* Load it into the primary */ + LoadExpr (CF_NONE, &Expr2); - /* Append deferred inc/dec at sequence point */ - DoDeferred (SQP_KEEP_EXPR, &Expr2); + /* Append deferred inc/dec at sequence point */ + DoDeferred (SQP_KEEP_EXPR, &Expr2); - ED_FinalizeRValLoad (&Expr2); - } else { - /* Constant boolean subexpression could still have deferred inc/ - ** dec operations, so just flush their side-effects at this - ** sequence point. - */ - DoDeferred (SQP_KEEP_NONE, &Expr2); - } - Expr2.Type = PtrConversion (Expr2.Type); + ED_FinalizeRValLoad (&Expr2); + } else { + /* Constant boolean subexpression could still have deferred inc/ + ** dec operations, so just flush their side-effects at this + ** sequence point. + */ + DoDeferred (SQP_KEEP_NONE, &Expr2); } + Expr2.Type = PtrConversion (Expr2.Type); if (!ConstantCond) { /* Remember the current code position */ @@ -4021,6 +4021,9 @@ static void hieQuest (ExprDesc* Expr) g_defcodelabel (FalseLab); } else { if (Expr->IVal == 0) { + /* Expr2 is unevaluated when the condition is false */ + Expr2.Flags |= E_EVAL_UNEVAL; + /* Remove the load code of Expr2 */ RemoveCode (&SkippedBranch); } else { @@ -4035,26 +4038,29 @@ static void hieQuest (ExprDesc* Expr) */ ExprWithCheck (hie1, &Expr3); Expr3IsNULL = ED_IsNullPtr (&Expr3); - if (!IsTypeVoid (Expr3.Type)) { - if (!ConstantCond || !ED_IsConst (&Expr3)) { - /* Load it into the primary */ - LoadExpr (CF_NONE, &Expr3); + if (!IsTypeVoid (Expr3.Type) && + ED_YetToLoad (&Expr3) && + (!ConstantCond || !ED_IsConst (&Expr3))) { + /* Load it into the primary */ + LoadExpr (CF_NONE, &Expr3); - /* Append deferred inc/dec at sequence point */ - DoDeferred (SQP_KEEP_EXPR, &Expr3); + /* Append deferred inc/dec at sequence point */ + DoDeferred (SQP_KEEP_EXPR, &Expr3); - ED_FinalizeRValLoad (&Expr3); - } else { - /* Constant boolean subexpression could still have deferred inc/ - ** dec operations, so just flush their side-effects at this - ** sequence point. - */ - DoDeferred (SQP_KEEP_NONE, &Expr3); - } - Expr3.Type = PtrConversion (Expr3.Type); + ED_FinalizeRValLoad (&Expr3); + } else { + /* Constant boolean subexpression could still have deferred inc/ + ** dec operations, so just flush their side-effects at this + ** sequence point. + */ + DoDeferred (SQP_KEEP_NONE, &Expr3); } + Expr3.Type = PtrConversion (Expr3.Type); if (ConstantCond && Expr->IVal != 0) { + /* Expr3 is unevaluated when the condition is true */ + Expr3.Flags |= E_EVAL_UNEVAL; + /* Remove the load code of Expr3 */ RemoveCode (&SkippedBranch); } From 325b7b4ab3cecfafd67efadf1d5ffdc784e4635b Mon Sep 17 00:00:00 2001 From: acqn Date: Sun, 14 Mar 2021 03:25:40 +0800 Subject: [PATCH 56/80] Enabled 'a ? b, c : d'. --- src/cc65/expr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 422159c4b..44b0d17e8 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -3985,7 +3985,7 @@ static void hieQuest (ExprDesc* Expr) /* Parse second expression. Remember for later if it is a NULL pointer ** expression, then load it into the primary. */ - ExprWithCheck (hie1, &Expr2); + ExprWithCheck (hie0, &Expr2); Expr2IsNULL = ED_IsNullPtr (&Expr2); if (!IsTypeVoid (Expr2.Type) && ED_YetToLoad (&Expr2) && From bbfc24770eaa1893da7bf8ae10f7bd9cfa44db65 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Fri, 19 Mar 2021 23:42:25 +0100 Subject: [PATCH 57/80] test related to pr #1425 --- test/val/pr1425.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 test/val/pr1425.c diff --git a/test/val/pr1425.c b/test/val/pr1425.c new file mode 100644 index 000000000..e3ae23ba3 --- /dev/null +++ b/test/val/pr1425.c @@ -0,0 +1,45 @@ + +/* pr #1425 - Ternary fixes */ + +unsigned char fails = 0; + +void test1(void) +{ + int x = 0; + x ? (void)x-- : (void)1; + if (x != 0) { + fails++; + } +} + +int test2(void) +{ + int x = 0, y = 0; + x ? (void)x--, (void)y++ : (void)1; + if (x != 0) { + fails++; + } + if (y != 0) { + fails++; + } +} + +void test3(void) +{ + int x = 0, y = 0; + x ? ((void)x--, (void)y++) : (void)1; + if (x != 0) { + fails++; + } + if (y != 0) { + fails++; + } +} + +int main(void) +{ + test1(); + test2(); + test3(); + return fails; +} From 82fb9aa41847d08556cfe12cc51a54a3ca2e2536 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sat, 20 Mar 2021 00:55:55 +0100 Subject: [PATCH 58/80] testcase related to pr #1423 --- test/val/pr1423.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/val/pr1423.c diff --git a/test/val/pr1423.c b/test/val/pr1423.c new file mode 100644 index 000000000..3135b64a3 --- /dev/null +++ b/test/val/pr1423.c @@ -0,0 +1,41 @@ +/* pr #1423 - Codegen fix for certain cases of object addresses as boolean */ + +unsigned char fails = 0; + +void test1(void) +{ + int a; + while (&a) { + return; + } + fails++; + return; +} + +void test2(void) +{ + int a; + do { + return; + } while (&a); + fails++; + return; +} + +void test3(void) +{ + int a; + for (;&a;) { + return; + } + fails++; + return; +} + +int main(void) +{ + test1(); + test2(); + test3(); + return fails; +} From f8835d2867d428484fd7a300fbbc1213a8af1c70 Mon Sep 17 00:00:00 2001 From: acqn Date: Sat, 13 Mar 2021 14:25:51 +0800 Subject: [PATCH 59/80] Fixed codegen with addresses as boolean test conditions. Fixed warning on unreachable code of if body. --- src/cc65/testexpr.c | 9 +++++++-- src/cc65/testexpr.h | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/cc65/testexpr.c b/src/cc65/testexpr.c index e5db488de..243f3ebf9 100644 --- a/src/cc65/testexpr.c +++ b/src/cc65/testexpr.c @@ -70,7 +70,7 @@ unsigned Test (unsigned Label, int Invert) DoDeferred (SQP_KEEP_NONE, &Expr); /* Result is constant, so we know the outcome */ - Result = (Expr.IVal != 0); + Result = (Expr.IVal != 0) ? TESTEXPR_TRUE : TESTEXPR_FALSE; /* Constant rvalue */ if (!Invert && Expr.IVal == 0) { @@ -86,7 +86,12 @@ unsigned Test (unsigned Label, int Invert) DoDeferred (SQP_KEEP_NONE, &Expr); /* Object addresses are non-NULL */ - Result = 1; + Result = TESTEXPR_TRUE; + + /* Condition is always true */ + if (Invert) { + g_jump (Label); + } } else { diff --git a/src/cc65/testexpr.h b/src/cc65/testexpr.h index 478280a28..84b957af2 100644 --- a/src/cc65/testexpr.h +++ b/src/cc65/testexpr.h @@ -44,9 +44,9 @@ -#define TESTEXPR_UNKNOWN 0 /* Result of expression unknown */ +#define TESTEXPR_UNKNOWN -1 /* Result of expression unknown */ #define TESTEXPR_TRUE 1 /* Expression yields true */ -#define TESTEXPR_FALSE 2 /* Expression yields false */ +#define TESTEXPR_FALSE 0 /* Expression yields false */ From 3c2e7ce41cb54f3a751bbf07a1b84fd51fa89104 Mon Sep 17 00:00:00 2001 From: acqn Date: Sat, 13 Mar 2021 14:27:11 +0800 Subject: [PATCH 60/80] More reliable test for true/false with addresses for AND, OR and ternary operators. Minor comment typo fix. --- src/cc65/expr.c | 17 +++++++++++------ src/cc65/exprdesc.c | 26 +++++++++++++++++++++++++- src/cc65/exprdesc.h | 12 +++++++++++- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 44b0d17e8..048819d50 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -3658,7 +3658,7 @@ static int hieAnd (ExprDesc* Expr, unsigned* TrueLab, int* TrueLabAllocated) */ DoDeferred (SQP_KEEP_NONE, Expr); - if (Expr->IVal == 0 && !ED_IsAddrExpr (Expr)) { + if (ED_IsConstFalse (Expr)) { /* Skip remaining */ Flags |= E_EVAL_UNEVAL; } @@ -3713,7 +3713,7 @@ static int hieAnd (ExprDesc* Expr, unsigned* TrueLab, int* TrueLabAllocated) */ DoDeferred (SQP_KEEP_NONE, &Expr2); - if (Expr2.IVal == 0 && !ED_IsAddrExpr (&Expr2)) { + if (ED_IsConstFalse (&Expr2)) { /* Skip remaining */ Flags |= E_EVAL_UNEVAL; /* The value of the expression will be false */ @@ -3826,7 +3826,7 @@ static void hieOr (ExprDesc *Expr) */ DoDeferred (SQP_KEEP_NONE, Expr); - if (Expr->IVal != 0 || ED_IsAddrExpr (Expr)) { + if (ED_IsConstTrue (Expr)) { /* Skip remaining */ Flags |= E_EVAL_UNEVAL; } @@ -3878,7 +3878,7 @@ static void hieOr (ExprDesc *Expr) */ DoDeferred (SQP_KEEP_NONE, &Expr2); - if (Expr2.IVal != 0 || ED_IsAddrExpr (&Expr2)) { + if (ED_IsConstTrue (&Expr2)) { /* Skip remaining */ Flags |= E_EVAL_UNEVAL; /* The result is always true */ @@ -3945,6 +3945,7 @@ static void hieQuest (ExprDesc* Expr) /* Check if it's a ternary expression */ if (CurTok.Tok == TOK_QUEST) { + /* The constant condition must be compile-time known as well */ int ConstantCond = ED_IsConstBool (Expr); unsigned Flags = Expr->Flags & E_MASK_KEEP_RESULT; @@ -3955,9 +3956,13 @@ static void hieQuest (ExprDesc* Expr) NextToken (); - /* Convert non-integer constant boolean */ - if (ED_IsAddrExpr (Expr)) { + /* Convert non-integer constant to boolean constant, so that we may just + ** check it in the same way. + */ + if (ED_IsConstTrue (Expr)) { ED_MakeConstBool (Expr, 1); + } else if (ED_IsConstFalse (Expr)) { + ED_MakeConstBool (Expr, 0); } if (!ConstantCond) { diff --git a/src/cc65/exprdesc.c b/src/cc65/exprdesc.c index aa98e1531..d1113d9a5 100644 --- a/src/cc65/exprdesc.c +++ b/src/cc65/exprdesc.c @@ -397,6 +397,30 @@ int ED_IsConstBool (const ExprDesc* Expr) +int ED_IsConstTrue (const ExprDesc* Expr) +/* Return true if the constant expression can be evaluated as boolean true at +** compile time. +*/ +{ + /* Non-zero arithmetics and objects addresses are boolean true */ + return (ED_IsConstAbsInt (Expr) && Expr->IVal != 0) || + (ED_IsAddrExpr (Expr)); +} + + + +int ED_IsConstFalse (const ExprDesc* Expr) +/* Return true if the constant expression can be evaluated as boolean false at +** compile time. +*/ +{ + /* Zero arithmetics and null pointers are boolean false */ + return (ED_IsConstAbsInt (Expr) && Expr->IVal == 0) || + ED_IsNullPtr (Expr); +} + + + int ED_IsConst (const ExprDesc* Expr) /* Return true if the expression denotes a constant of some sort. This can be a ** numeric constant, the address of a global variable (maybe with offset) or @@ -449,7 +473,7 @@ int ED_IsNullPtr (const ExprDesc* Expr) int ED_IsBool (const ExprDesc* Expr) -/* Return true of the expression can be treated as a boolean, that is, it can +/* Return true if the expression can be treated as a boolean, that is, it can ** be an operand to a compare operation. */ { diff --git a/src/cc65/exprdesc.h b/src/cc65/exprdesc.h index 844af1566..a4f5eb848 100644 --- a/src/cc65/exprdesc.h +++ b/src/cc65/exprdesc.h @@ -643,6 +643,16 @@ int ED_IsConstAbsInt (const ExprDesc* Expr); int ED_IsConstBool (const ExprDesc* Expr); /* Return true if the expression can be constantly evaluated as a boolean. */ +int ED_IsConstTrue (const ExprDesc* Expr); +/* Return true if the constant expression can be evaluated as boolean true at +** compile time. +*/ + +int ED_IsConstFalse (const ExprDesc* Expr); +/* Return true if the constant expression can be evaluated as boolean false at +** compile time. +*/ + int ED_IsConst (const ExprDesc* Expr); /* Return true if the expression denotes a constant of some sort. This can be a ** numeric constant, the address of a global variable (maybe with offset) or @@ -668,7 +678,7 @@ int ED_IsNullPtr (const ExprDesc* Expr); /* Return true if the given expression is a NULL pointer constant */ int ED_IsBool (const ExprDesc* Expr); -/* Return true of the expression can be treated as a boolean, that is, it can +/* Return true if the expression can be treated as a boolean, that is, it can ** be an operand to a compare operation with 0/NULL. */ From 531a31722e2e6183e060ca4dc7d3c2c56bc9106d Mon Sep 17 00:00:00 2001 From: Christian Groessler Date: Mon, 22 Mar 2021 14:06:40 +0100 Subject: [PATCH 61/80] fix typo --- doc/atari.sgml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/atari.sgml b/doc/atari.sgml index 7fc929f42..f2ced13e1 100644 --- a/doc/atari.sgml +++ b/doc/atari.sgml @@ -1170,7 +1170,7 @@ When using cl65, you can leave it out with this command line: cl65 -Wl -D__SYSTEM_CHECK__=1 -The value you assign to Date: Mon, 22 Mar 2021 19:12:44 +0100 Subject: [PATCH 62/80] test related to issue #1196 and pr #1424 respectively --- test/val/constexpr.c | 112 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 test/val/constexpr.c diff --git a/test/val/constexpr.c b/test/val/constexpr.c new file mode 100644 index 000000000..c92302a58 --- /dev/null +++ b/test/val/constexpr.c @@ -0,0 +1,112 @@ + +/* + +This tests a couple of expressions which yield constant results. While we cant +really check if the compiler figures out they are constant, we can still check +if they are being compiled/evaluated correctly. + +related: + +pr #1424 - More compile-time constant expressions regarding object addresses +issue #1196 - Constant expressions in general + +*/ + +#include + +int fails = 0; + +#define TESTEXPR(expr) \ + if (!(expr)) { \ + printf("fail line %d\n", __LINE__); \ + fails++; \ + } + +#define TESTEXPRFALSE(expr) \ + if (expr) { \ + printf("fail line %d\n", __LINE__); \ + fails++; \ + } + +int a; +volatile int b; +const int c = 1; +#define d 1 +enum { e = 1 }; +int f() { return 1; } + +/* we cant really test these at runtime (because the result is constant, but not + * compile-time known), so compile only */ +void test0(void) +{ + TESTEXPR(a); /* Pure: Yes; Static: No; Immutable: No; Compile-Time-Known: No */ + TESTEXPR(b); /* Pure: No?; Static: No; Immutable: No; Compile-Time-Known: No */ + TESTEXPR(&a > &b); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: No */ +} + +void test1(void) +{ + TESTEXPR(1); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPR(c); /* Pure: Yes; Static: ???; Immutable: ???; Compile-Time-Known: ??? */ + TESTEXPR(d); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPR(e); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPR(c == c); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPRFALSE(c != c); + TESTEXPR(f() == f()); /* Pure: Yes; Static: Yes?; Immutable: Yes; Compile-Time-Known: Yes? */ + TESTEXPRFALSE(f() != f()); + TESTEXPR(&a == &a); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPRFALSE(&a != &a); + TESTEXPR(&a != 0); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes* */ + TESTEXPRFALSE(&a == 0); +/* in a real program we cant rely on these, but in this test we can */ + TESTEXPR(&a); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: No */ + TESTEXPR((int)&a != 0); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: No */ + TESTEXPRFALSE((int)&a == 0); + TESTEXPR(&a != &b); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: ??** */ + TESTEXPRFALSE(&a == &b); +/* this may fail in a real world program, but here we can rely on it anyway */ + TESTEXPR(b == b); /* Pure: No?; Static: No; Immutable: No; Compile-Time-Known: No */ + TESTEXPRFALSE(b != b); +/* NOT detected by the compiler as constant */ + TESTEXPR(a == a); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPRFALSE(a != a); + TESTEXPR(f()); /* Pure: Yes; Static: Yes?; Immutable: Yes; Compile-Time-Known: Yes? */ +} + +/* Taken from #1196 reply */ +struct S { + int a; + int b; +} s[2]; + +void test2(void) +{ + TESTEXPR((void*)&s == (void*)&s[0]); + TESTEXPRFALSE((void*)&s != (void*)&s[0]); + TESTEXPR(&s[0] < &s[1]); + TESTEXPR(&s[0].b > &s[0].a); + TESTEXPR(&s[0].b < &s[1].a); +} + +/* FIXME: how to deal with the extern stuff in the testbench? */ +extern int g(); + +void test3(void) +{ +#if 0 + TESTEXPR(g()); /* Pure: No; Static: No; Immutable: No; Compile-Time-Known: No */ + TESTEXPR(g(), 1); /* Pure: No; Static: No; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPR((void)g()); /* Pure: No; Static: No; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPR(sizeof(g())); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + /* NOT detected by the compiler as constant */ + TESTEXPR(g() * 0); /* Pure: No; Static: No; Immutable: Yes; Compile-Time-Known: Yes */ +#endif +} + +int main(void) +{ + test1(); + test2(); + test3(); + return fails; +} From d3cd668585ab920fd9a6067a4cfce0e336eefbeb Mon Sep 17 00:00:00 2001 From: mrdudz Date: Mon, 22 Mar 2021 23:37:33 +0100 Subject: [PATCH 63/80] also test (some of) the cases with an external function --- test/val/constexpr.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/test/val/constexpr.c b/test/val/constexpr.c index c92302a58..4338717f4 100644 --- a/test/val/constexpr.c +++ b/test/val/constexpr.c @@ -88,19 +88,18 @@ void test2(void) TESTEXPR(&s[0].b < &s[1].a); } -/* FIXME: how to deal with the extern stuff in the testbench? */ -extern int g(); +/* we abuse the close function here, close(-1) will return -1 */ +extern int close(int fd); void test3(void) { -#if 0 - TESTEXPR(g()); /* Pure: No; Static: No; Immutable: No; Compile-Time-Known: No */ - TESTEXPR(g(), 1); /* Pure: No; Static: No; Immutable: Yes; Compile-Time-Known: Yes */ - TESTEXPR((void)g()); /* Pure: No; Static: No; Immutable: Yes; Compile-Time-Known: Yes */ - TESTEXPR(sizeof(g())); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPR(close(-1)); /* Pure: No; Static: No; Immutable: No; Compile-Time-Known: No */ + TESTEXPR((close(-1), 1)) /* Pure: No; Static: No; Immutable: Yes; Compile-Time-Known: Yes */ +/* Error: Scalar expression expected */ +// TESTEXPR((void)close(-1)); /* Pure: No; Static: No; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPR(sizeof(close(-1))); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ /* NOT detected by the compiler as constant */ - TESTEXPR(g() * 0); /* Pure: No; Static: No; Immutable: Yes; Compile-Time-Known: Yes */ -#endif + TESTEXPRFALSE(close(-1) * 0); /* Pure: No; Static: No; Immutable: Yes; Compile-Time-Known: Yes */ } int main(void) From 3755e4a863da973a7de60fa1abd6dde5d4379aef Mon Sep 17 00:00:00 2001 From: acqn Date: Wed, 24 Mar 2021 14:35:44 +0800 Subject: [PATCH 64/80] Replaced checking for __fastcall__ aginst AutoCDecl etc. with IsFastcallFunc(). --- src/cc65/codeinfo.c | 9 +++------ src/cc65/datatype.c | 21 ++++++++++++++++++--- src/cc65/datatype.h | 9 ++++++++- src/cc65/expr.c | 14 ++++---------- src/cc65/function.c | 5 +---- 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/cc65/codeinfo.c b/src/cc65/codeinfo.c index 90d4f4d68..d81f46001 100644 --- a/src/cc65/codeinfo.c +++ b/src/cc65/codeinfo.c @@ -493,17 +493,14 @@ fncls_t GetFuncInfo (const char* Name, unsigned int* Use, unsigned int* Chg) ** registers. */ *Use = REG_EAXY; - } else if ((D->ParamCount > 0 || - (D->Flags & FD_EMPTY) != 0) && - (AutoCDecl ? - IsQualFastcall (E->Type) : - !IsQualCDecl (E->Type))) { + } else if ((D->ParamCount > 0 || (D->Flags & FD_EMPTY) != 0) && + IsFastcallFunc (E->Type)) { /* Will use registers depending on the last param. If the last ** param has incomplete type, or if the function has not been ** prototyped yet, just assume __EAX__. */ if (D->LastParam != 0) { - switch (SizeOf(D->LastParam->Type)) { + switch (SizeOf (D->LastParam->Type)) { case 1u: *Use = REG_A; break; diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 6e42057dc..d29a0d807 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -1085,11 +1085,26 @@ int HasUnknownSize (const Type* T) int IsVariadicFunc (const Type* T) /* Return true if this is a function type or pointer to function type with -** variable parameter list +** variable parameter list. +** Check fails if the type is not a function or a pointer to function. */ { - FuncDesc* F = GetFuncDesc (T); - return (F->Flags & FD_VARIADIC) != 0; + return (GetFuncDesc (T)->Flags & FD_VARIADIC) != 0; +} + + + +int IsFastcallFunc (const Type* T) +/* Return true if this is a function type or pointer to function type by +** __fastcall__ calling convention. +** Check fails if the type is not a function or a pointer to function. +*/ +{ + if (UnqualifiedType (T->C) == T_PTR) { + /* Pointer to function */ + ++T; + } + return !IsVariadicFunc (T) && (AutoCDecl ? IsQualFastcall (T) : !IsQualCDecl (T)); } diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index 5c3e71da5..ac6edeeb5 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -825,7 +825,14 @@ INLINE int IsQualCConv (const Type* T) int IsVariadicFunc (const Type* T) attribute ((const)); /* Return true if this is a function type or pointer to function type with -** variable parameter list +** variable parameter list. +** Check fails if the type is not a function or a pointer to function. +*/ + +int IsFastcallFunc (const Type* T) attribute ((const)); +/* Return true if this is a function type or pointer to function type by +** __fastcall__ calling convention. +** Check fails if the type is not a function or a pointer to function. */ FuncDesc* GetFuncDesc (const Type* T) attribute ((const)); diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 048819d50..9b95efda6 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -863,7 +863,7 @@ static void FunctionCall (ExprDesc* Expr) unsigned ParamSize; /* Number of parameter bytes */ CodeMark Mark; int PtrOffs = 0; /* Offset of function pointer on stack */ - int IsFastcall = 0; /* True if it's a fast-call function */ + int IsFastcall = 0; /* True if we are fast-calling the function */ int PtrOnStack = 0; /* True if a pointer copy is on stack */ Type* ReturnType; @@ -882,11 +882,8 @@ static void FunctionCall (ExprDesc* Expr) ** parameter count is zero. Handle K & R functions as though there are ** parameters. */ - IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && - (Func->ParamCount > 0 || (Func->Flags & FD_EMPTY)) && - (AutoCDecl ? - IsQualFastcall (Expr->Type + 1) : - !IsQualCDecl (Expr->Type + 1)); + IsFastcall = (Func->ParamCount > 0 || (Func->Flags & FD_EMPTY) != 0) && + IsFastcallFunc (Expr->Type + 1); /* Things may be difficult, depending on where the function pointer ** resides. If the function pointer is an expression of some sort @@ -931,10 +928,7 @@ static void FunctionCall (ExprDesc* Expr) } /* If we didn't inline the function, get fastcall info */ - IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && - (AutoCDecl ? - IsQualFastcall (Expr->Type) : - !IsQualCDecl (Expr->Type)); + IsFastcall = IsFastcallFunc (Expr->Type); } /* Parse the parameter list */ diff --git a/src/cc65/function.c b/src/cc65/function.c index 9269d4c62..cad1df629 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -558,10 +558,7 @@ void NewFunc (SymEntry* Func, FuncDesc* D) PushLiteralPool (Func); /* If this is a fastcall function, push the last parameter onto the stack */ - if ((D->Flags & FD_VARIADIC) == 0 && D->ParamCount > 0 && - (AutoCDecl ? - IsQualFastcall (Func->Type) : - !IsQualCDecl (Func->Type))) { + if (D->ParamCount > 0 && IsFastcallFunc (Func->Type)) { unsigned Flags; /* Generate the push */ From 0f1386ff4c0d88a533050138de2f3a4f2796863f Mon Sep 17 00:00:00 2001 From: Greg King Date: Thu, 25 Mar 2021 08:28:15 -0400 Subject: [PATCH 65/80] Added documentation about the slightly different behavior of cpeekcolor() on the cx16 platform. --- doc/cx16.sgml | 69 ++++++++++++++++++++++++++---------------------- doc/funcref.sgml | 2 ++ 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/doc/cx16.sgml b/doc/cx16.sgml index 490d07849..9e743064f 100644 --- a/doc/cx16.sgml +++ b/doc/cx16.sgml @@ -142,13 +142,20 @@ The functions listed below are special for the CX16. See the for declarations and usage. -get_ostype -set_tv -videomode -vpeek -vpoke +get_ostype() +set_tv() +videomode() +vpeek() +vpoke() +CBM-specific functions

@@ -157,32 +164,32 @@ machines. See the for declarations and usage. -cbm_close -cbm_closedir -cbm_k_basin -cbm_k_bsout -cbm_k_chkin -cbm_k_ckout -cbm_k_close -cbm_k_clrch -cbm_k_getin -cbm_k_load -cbm_k_open -cbm_k_readst -cbm_k_save -cbm_k_second -cbm_k_setlfs -cbm_k_setnam -cbm_k_tksa -cbm_load -cbm_open -cbm_opendir -cbm_read -cbm_readdir -cbm_save -cbm_write -get_tv -waitvsync +cbm_close() +cbm_closedir() +cbm_k_basin() +cbm_k_bsout() +cbm_k_chkin() +cbm_k_ckout() +cbm_k_close() +cbm_k_clrch() +cbm_k_getin() +cbm_k_load() +cbm_k_open() +cbm_k_readst() +cbm_k_save() +cbm_k_second() +cbm_k_setlfs() +cbm_k_setnam() +cbm_k_tksa() +cbm_load() +cbm_open() +cbm_opendir() +cbm_read() +cbm_readdir() +cbm_save() +cbm_write() +get_tv() +waitvsync() diff --git a/doc/funcref.sgml b/doc/funcref.sgml index a954c6581..3b3db2e09 100644 --- a/doc/funcref.sgml +++ b/doc/funcref.sgml @@ -2813,6 +2813,8 @@ location of the cursor in the display screen RAM. That number can be passed to done to make it obvious that peeking doesn't move the cursor in any way. Your program must place the cursor where it wants to peek before it calls any of those functions. +On the cx16 (Commander X16) target, this function returns two values: the +background color, in the high nybble, and the text color, in the low nybble. Date: Wed, 13 Jan 2021 03:20:19 -0500 Subject: [PATCH 66/80] Fixed cbm_k_readst() to work around a VIC-20 Kernal bug. It properly returns the RS-232 device's status. --- asminc/vic20.inc | 9 +++++---- libsrc/cbm/c_readst.s | 8 ++++---- libsrc/vic20/c_readst.s | 28 ++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 libsrc/vic20/c_readst.s diff --git a/asminc/vic20.inc b/asminc/vic20.inc index fa9fdfa8d..91da083f1 100644 --- a/asminc/vic20.inc +++ b/asminc/vic20.inc @@ -1,8 +1,7 @@ ; -; Vic20 generic definitions. Stolen mostly from c64.inc - Steve Schmidtke +; VIC-20 generic definitions. Stolen mostly from c64.inc -- Steve Schmidtke ; - ; --------------------------------------------------------------------------- ; Zero page, Commodore stuff @@ -12,8 +11,8 @@ TXTPTR := $7A ; Pointer into BASIC source code STATUS := $90 ; Kernal I/O completion status TIME := $A0 ; 60HZ clock FNAM_LEN := $B7 ; Length of filename -SECADR := $B9 ; Secondary address -DEVNUM := $BA ; Device number +SECADR := $B9 ; Second address +DEVNUM := $BA ; Device number (first address) FNAM := $BB ; Pointer to filename KEY_COUNT := $C6 ; Number of keys in input buffer RVS := $C7 ; Reverse flag @@ -36,6 +35,8 @@ KBDREPEAT := $28a KBDREPEATRATE := $28b KBDREPEATDELAY := $28c +RSSTAT := $297 ; RS-232 device driver status + ; --------------------------------------------------------------------------- ; Screen size diff --git a/libsrc/cbm/c_readst.s b/libsrc/cbm/c_readst.s index 85211dd2f..bcaacbbae 100644 --- a/libsrc/cbm/c_readst.s +++ b/libsrc/cbm/c_readst.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 03.06.1999 +; 1999-06-03, Ullrich von Bassewitz +; 2021-01-12, Greg King ; ; unsigned char cbm_k_readst (void); ; @@ -10,6 +11,5 @@ _cbm_k_readst: - jsr READST - ldx #0 ; Clear high byte - rts + ldx #>$0000 + jmp READST diff --git a/libsrc/vic20/c_readst.s b/libsrc/vic20/c_readst.s new file mode 100644 index 000000000..2cb11bb21 --- /dev/null +++ b/libsrc/vic20/c_readst.s @@ -0,0 +1,28 @@ +; +; 1999-06-03, Ullrich von Bassewitz +; 2021-01-12, Greg King +; +; unsigned char cbm_k_readst (void); +; +; This version works around a bug in VIC-20 Kernal's READST function. +; + + .include "vic20.inc" + .include "../cbm/cbm.inc" + + .export _cbm_k_readst + + +_cbm_k_readst: + ldx #>$0000 + lda DEVNUM + cmp #CBMDEV_RS232 + beq @L1 + + jmp READST + +; Work-around: Read the RS-232 status variable directly. + +@L1: lda RSSTAT + stx RSSTAT ; reset the status bits + rts From f273b1ebcb578a936ba19924fdc233f51607f1d6 Mon Sep 17 00:00:00 2001 From: acqn Date: Fri, 26 Mar 2021 11:02:46 +0800 Subject: [PATCH 67/80] Fixed crash with non-inlined __fastcall__ function invocation with no arguments. --- src/cc65/expr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 9b95efda6..0bb393cf1 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -835,7 +835,7 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall, ExprDesc* ED) /* Append last deferred inc/dec before the function is called. ** The last parameter needs to be preserved if it is passed in AX/EAX Regs. */ - DoDeferred (IsFastcall ? SQP_KEEP_EAX : SQP_KEEP_NONE, &Expr); + DoDeferred (IsFastcall && PushedCount > 0 ? SQP_KEEP_EAX : SQP_KEEP_NONE, &Expr); /* Check if we had enough arguments */ if (PushedCount < Func->ParamCount) { @@ -928,7 +928,8 @@ static void FunctionCall (ExprDesc* Expr) } /* If we didn't inline the function, get fastcall info */ - IsFastcall = IsFastcallFunc (Expr->Type); + IsFastcall = (Func->ParamCount > 0 || (Func->Flags & FD_EMPTY) != 0) && + IsFastcallFunc (Expr->Type); } /* Parse the parameter list */ From 02392d62207ee63dc332daf4dafc6e9eff0b163f Mon Sep 17 00:00:00 2001 From: mrdudz Date: Fri, 26 Mar 2021 22:18:05 +0100 Subject: [PATCH 68/80] added test related to issue #1437 --- test/misc/Makefile | 5 +++++ test/misc/bug1437.c | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 test/misc/bug1437.c diff --git a/test/misc/Makefile b/test/misc/Makefile index 7a1b82d5f..397635afd 100644 --- a/test/misc/Makefile +++ b/test/misc/Makefile @@ -64,6 +64,11 @@ $(WORKDIR)/bug760.$1.$2.prg: bug760.c | $(WORKDIR) $(if $(QUIET),echo misc/bug760.$1.$2.prg) $(NOT) $(CC65) -t sim$2 -$1 -o $$@ $$< $(NULLERR) +$(WORKDIR)/bug1437.$1.$2.prg: bug1437.c | $(WORKDIR) + @echo "FIXME: " $$@ "currently does not compile." + $(if $(QUIET),echo misc/bug1437.$1.$2.prg) + $(NOT) $(CC65) -t sim$2 -$1 -o $$@ $$< $(NULLERR) + # should compile, but gives an error $(WORKDIR)/bug1209-ind-goto-rev.$1.$2.prg: bug1209-ind-goto-rev.c | $(WORKDIR) @echo "FIXME: " $$@ "currently does not compile." diff --git a/test/misc/bug1437.c b/test/misc/bug1437.c new file mode 100644 index 000000000..de6c7008d --- /dev/null +++ b/test/misc/bug1437.c @@ -0,0 +1,23 @@ + +/* bug #1437 enum declaration in struct does not compile */ + +struct nodelist1 { + enum { DEAD1, LIVE1, ONCE1, TWICE1 } live1; +} firstnode1 = {ONCE1}; + +enum nodestate2 { DEAD2, LIVE2, ONCE2, TWICE2 } live2; + +struct nodelist2 { + enum nodestate2 live2; +} firstnode2 = {TWICE2}; + +int main (void) +{ + if (firstnode1.live1 != ONCE1) { + return 1; + } + if (firstnode2.live2 != TWICE2) { + return 1; + } + return 0; +} From 54920193e5e00574179a27abf9b4fc39f71b7a89 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sat, 27 Mar 2021 15:11:47 +0100 Subject: [PATCH 69/80] added test for issue #1438 --- test/val/bug1438.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 test/val/bug1438.c diff --git a/test/val/bug1438.c b/test/val/bug1438.c new file mode 100644 index 000000000..93addb877 --- /dev/null +++ b/test/val/bug1438.c @@ -0,0 +1,35 @@ + +/* Issue #1438 fix #1439 - crash in cc65, related to delayed post-counting + + this is an odd issue, the compile would crash *sometimes*, perhaps in one + of ten compilation runs. +*/ + +#define __fastcall__ + +unsigned short a[10] = {0,1,2,3,4,5,6,7,8,9}; + +unsigned short __fastcall__ func2(void) +{ + return 42; +} + +void func1(unsigned short *wp) +{ + *wp++ = func2(); +} + +int main(void) +{ + func1(&a[3]); + if (a[2] != 2) { + return 1; + } + if (a[3] != 42) { + return 1; + } + if (a[4] != 4) { + return 1; + } + return 0; +} From bf1bb7a0325d91712a724cb369cf34505bed7a8a Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sat, 27 Mar 2021 15:13:32 +0100 Subject: [PATCH 70/80] ooopsie :) --- test/val/bug1438.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/val/bug1438.c b/test/val/bug1438.c index 93addb877..3894f87f1 100644 --- a/test/val/bug1438.c +++ b/test/val/bug1438.c @@ -5,7 +5,7 @@ of ten compilation runs. */ -#define __fastcall__ +/* #define __fastcall__ */ unsigned short a[10] = {0,1,2,3,4,5,6,7,8,9}; From edecbc86b84dcf75edf21725d9cc3ff791ce1262 Mon Sep 17 00:00:00 2001 From: Greg King Date: Sat, 27 Mar 2021 13:34:39 -0400 Subject: [PATCH 71/80] Reverted "Second address" back to "Secondary address". --- asminc/vic20.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/asminc/vic20.inc b/asminc/vic20.inc index 91da083f1..41a935238 100644 --- a/asminc/vic20.inc +++ b/asminc/vic20.inc @@ -11,8 +11,8 @@ TXTPTR := $7A ; Pointer into BASIC source code STATUS := $90 ; Kernal I/O completion status TIME := $A0 ; 60HZ clock FNAM_LEN := $B7 ; Length of filename -SECADR := $B9 ; Second address -DEVNUM := $BA ; Device number (first address) +SECADR := $B9 ; Secondary address +DEVNUM := $BA ; Device number FNAM := $BB ; Pointer to filename KEY_COUNT := $C6 ; Number of keys in input buffer RVS := $C7 ; Reverse flag From cb8fbf4772a0f2bbb1c04393662a5cacaaeea4f4 Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 29 Mar 2021 12:35:29 +0800 Subject: [PATCH 72/80] Removed the non-existing-in-C "struct/union scope" for structs/unions. Fixed handling of struct/union field declarations without identifiers, which do nothing. --- src/cc65/declare.c | 8 ++++---- src/cc65/symtab.c | 27 +++++++++++++++++++-------- src/cc65/symtab.h | 5 ++++- test/misc/bug1437.c | 23 ----------------------- test/val/bug1437.c | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 36 deletions(-) delete mode 100644 test/misc/bug1437.c create mode 100644 test/val/bug1437.c diff --git a/src/cc65/declare.c b/src/cc65/declare.c index d952d1049..787ed62b7 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -965,7 +965,7 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags) */ AddBitField (Decl.Ident, Decl.Type, 0, 0, FieldWidth, SignednessSpecified); - } else { + } else if (Decl.Ident[0] != '\0') { Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0); if (IsAnonName (Decl.Ident)) { Entry->V.A.ANumber = UnionTagEntry->V.S.ACount++; @@ -994,7 +994,7 @@ NextMember: if (CurTok.Tok != TOK_COMMA) { NextToken (); /* Remember the symbol table and leave the struct level */ - FieldTab = GetSymTab (); + FieldTab = GetFieldSymTab (); LeaveStructLevel (); /* Return a fictitious symbol if errors occurred during parsing */ @@ -1167,7 +1167,7 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags) /* Add any full bytes to the struct size. */ StructSize += BitOffs / CHAR_BITS; BitOffs %= CHAR_BITS; - } else { + } else if (Decl.Ident[0] != '\0') { Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize); if (IsAnonName (Decl.Ident)) { Entry->V.A.ANumber = StructTagEntry->V.S.ACount++; @@ -1208,7 +1208,7 @@ NextMember: if (CurTok.Tok != TOK_COMMA) { NextToken (); /* Remember the symbol table and leave the struct level */ - FieldTab = GetSymTab (); + FieldTab = GetFieldSymTab (); LeaveStructLevel (); /* Return a fictitious symbol if errors occurred during parsing */ diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index db2b04f17..3d7176a83 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -92,6 +92,7 @@ static SymTable* SymTab0 = 0; static SymTable* SymTab = 0; static SymTable* TagTab0 = 0; static SymTable* TagTab = 0; +static SymTable* FieldTab = 0; static SymTable* LabelTab = 0; static SymTable* SPAdjustTab = 0; static SymTable* FailSafeTab = 0; /* For errors */ @@ -390,9 +391,9 @@ void EnterStructLevel (void) ** nested in struct scope are NOT local to the struct but visible in the ** outside scope. So we will NOT create a new struct or enum table. */ - S = NewSymTable (SYMTAB_SIZE_BLOCK); - S->PrevTab = SymTab; - SymTab = S; + S = NewSymTable (SYMTAB_SIZE_STRUCT); + S->PrevTab = FieldTab; + FieldTab = S; } @@ -401,7 +402,7 @@ void LeaveStructLevel (void) /* Leave a nested block for a struct definition */ { /* Don't delete the table */ - SymTab = SymTab->PrevTab; + FieldTab = FieldTab->PrevTab; } @@ -850,7 +851,7 @@ SymEntry* AddBitField (const char* Name, const Type* T, unsigned Offs, /* Add a bit field to the local symbol table and return the symbol entry */ { /* Do we have an entry with this name already? */ - SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name)); + SymEntry* Entry = FindSymInTable (FieldTab, Name, HashStr (Name)); if (Entry) { /* We have a symbol with this name already */ @@ -882,7 +883,7 @@ SymEntry* AddBitField (const char* Name, const Type* T, unsigned Offs, } /* Add the entry to the symbol table */ - AddSymEntry (SymTab, Entry); + AddSymEntry (FieldTab, Entry); } @@ -1070,9 +1071,9 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags) SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs) -/* Add a local symbol and return the symbol entry */ +/* Add a local or struct/union field symbol and return the symbol entry */ { - SymTable* Tab = SymTab; + SymTable* Tab = (Flags & SC_STRUCTFIELD) == 0 ? SymTab : FieldTab; ident Ident; /* Do we have an entry with this name already? */ @@ -1267,6 +1268,16 @@ SymTable* GetGlobalSymTab (void) return SymTab0; } + + +SymTable* GetFieldSymTab (void) +/* Return the current field symbol table */ +{ + return FieldTab; +} + + + SymTable* GetLabelSymTab (void) /* Return the global symbol table */ { diff --git a/src/cc65/symtab.h b/src/cc65/symtab.h index 1231eb528..469a4ba77 100644 --- a/src/cc65/symtab.h +++ b/src/cc65/symtab.h @@ -166,7 +166,7 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags); /* Add a goto label to the symbol table */ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs); -/* Add a local symbol and return the symbol entry */ +/* Add a local or struct/union field symbol and return the symbol entry */ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags); /* Add an external or global symbol to the symbol table and return the entry */ @@ -185,6 +185,9 @@ SymTable* GetSymTab (void); SymTable* GetGlobalSymTab (void); /* Return the global symbol table */ +SymTable* GetFieldSymTab (void); +/* Return the current field symbol table */ + SymTable* GetLabelSymTab (void); /* Return the label symbol table */ diff --git a/test/misc/bug1437.c b/test/misc/bug1437.c deleted file mode 100644 index de6c7008d..000000000 --- a/test/misc/bug1437.c +++ /dev/null @@ -1,23 +0,0 @@ - -/* bug #1437 enum declaration in struct does not compile */ - -struct nodelist1 { - enum { DEAD1, LIVE1, ONCE1, TWICE1 } live1; -} firstnode1 = {ONCE1}; - -enum nodestate2 { DEAD2, LIVE2, ONCE2, TWICE2 } live2; - -struct nodelist2 { - enum nodestate2 live2; -} firstnode2 = {TWICE2}; - -int main (void) -{ - if (firstnode1.live1 != ONCE1) { - return 1; - } - if (firstnode2.live2 != TWICE2) { - return 1; - } - return 0; -} diff --git a/test/val/bug1437.c b/test/val/bug1437.c new file mode 100644 index 000000000..3424079e1 --- /dev/null +++ b/test/val/bug1437.c @@ -0,0 +1,35 @@ + +/* bug #1437 enum declaration in a struct/union is invisible in the scope where the struct/union is declared */ + +struct nodelist1 { + struct { + enum { DEAD1, LIVE1, ONCE1, TWICE1 } live1; + } s; +} firstnode1 = {ONCE1}; + +enum nodestate2 { DEAD2, LIVE2, ONCE2, TWICE2 } live2; + +union nodelist2 { + enum nodestate2 live2; +} firstnode2 = { {TWICE2} }; + +struct T { + int I; + int; + enum E { + I + }; +}; + +int failures = 0; + +int main (void) +{ + if (firstnode1.s.live1 != ONCE1) { + ++failures; + } + if (firstnode2.live2 != TWICE2) { + ++failures; + } + return failures; +} From 31c1172a3aad97f9adbf127caca7dc74db01ffc0 Mon Sep 17 00:00:00 2001 From: acqn Date: Tue, 23 Mar 2021 15:30:08 +0800 Subject: [PATCH 73/80] zlib: Use correct (un)signedness of char in prototypes and functions. Also ensure we are using the same constness qualifiers. --- include/zlib.h | 6 ++++-- libsrc/zlib/adler32.s | 3 ++- libsrc/zlib/crc32.s | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/zlib.h b/include/zlib.h index 3f6c2b27b..68439b290 100644 --- a/include/zlib.h +++ b/include/zlib.h @@ -114,7 +114,8 @@ int __fastcall__ uncompress (unsigned char* dest, unsigned* destLen, */ -unsigned long __fastcall__ adler32 (unsigned long adler, const char* buf, +unsigned long __fastcall__ adler32 (unsigned long adler, + const unsigned char* buf, unsigned len); /* @@ -140,7 +141,8 @@ unsigned long __fastcall__ adler32 (unsigned long adler, const char* buf, */ -unsigned long __fastcall__ crc32 (unsigned long crc, const char* buf, +unsigned long __fastcall__ crc32 (unsigned long crc, + const unsigned char* buf, unsigned len); /* Original zlib description: diff --git a/libsrc/zlib/adler32.s b/libsrc/zlib/adler32.s index 8aa641a13..1bb5588db 100644 --- a/libsrc/zlib/adler32.s +++ b/libsrc/zlib/adler32.s @@ -2,7 +2,8 @@ ; 2001-11-18, Piotr Fusik ; 2018-05-20, Christian Kruger ; -; unsigned long __fastcall__ adler32 (unsigned long adler, unsigned char* buf, +; unsigned long __fastcall__ adler32 (unsigned long adler, +; const unsigned char* buf, ; unsigned len); ; diff --git a/libsrc/zlib/crc32.s b/libsrc/zlib/crc32.s index f019736ad..41b5fe9db 100644 --- a/libsrc/zlib/crc32.s +++ b/libsrc/zlib/crc32.s @@ -2,7 +2,8 @@ ; 2001-11-14, Piotr Fusik ; 2018-05-20, Christian Kruger ; -; unsigned long __fastcall__ crc32 (unsigned long crc, unsigned char* buf, +; unsigned long __fastcall__ crc32 (unsigned long crc, +; const unsigned char* buf, ; unsigned len); ; From b802efde5446433af827dd46241dc7cf18b6a83b Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 15 Mar 2021 16:59:08 +0800 Subject: [PATCH 74/80] Fixed ternary result type detection with pointer types. Fixed pointer type comparison and conversion, especially regarding qualifiers. Improved diagnostics about type comparison and conversion. Reorganized some type-comparison/conversion functions. --- src/cc65/assignment.c | 2 +- src/cc65/datatype.h | 1 + src/cc65/declare.c | 2 +- src/cc65/expr.c | 78 +++++--- src/cc65/symtab.c | 22 ++- src/cc65/typecmp.c | 403 +++++++++++++++++++----------------------- src/cc65/typecmp.h | 48 +++-- src/cc65/typeconv.c | 235 +++++++++++++++++------- src/cc65/typeconv.h | 11 +- 9 files changed, 466 insertions(+), 336 deletions(-) diff --git a/src/cc65/assignment.c b/src/cc65/assignment.c index 737d059a0..c642b4ce9 100644 --- a/src/cc65/assignment.c +++ b/src/cc65/assignment.c @@ -78,7 +78,7 @@ static int CopyStruct (ExprDesc* LExpr, ExprDesc* RExpr) hie1 (RExpr); /* Check for equality of the structs/unions */ - if (TypeCmp (ltype, RExpr->Type) < TC_STRICT_COMPATIBLE) { + if (TypeCmp (ltype, RExpr->Type).C < TC_STRICT_COMPATIBLE) { TypeCompatibilityDiagnostic (ltype, RExpr->Type, 1, "Incompatible types in assignment to '%s' from '%s'"); } diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index ac6edeeb5..e6ff9b7ce 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -108,6 +108,7 @@ enum { T_QUAL_CONST = 0x001000, T_QUAL_VOLATILE = 0x002000, T_QUAL_RESTRICT = 0x004000, + T_QUAL_CVR = T_QUAL_CONST | T_QUAL_VOLATILE | T_QUAL_RESTRICT, T_QUAL_NEAR = 0x008000, T_QUAL_FAR = 0x010000, T_QUAL_ADDRSIZE = T_QUAL_NEAR | T_QUAL_FAR, diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 787ed62b7..0c00f56d4 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -1821,7 +1821,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) NextToken (); /* Allow const, restrict, and volatile qualifiers */ - Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE | T_QUAL_RESTRICT); + Qualifiers |= OptionalQualifiers (T_QUAL_CVR); /* Parse the type that the pointer points to */ Declarator (Spec, D, Mode); diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 0bb393cf1..be53b22f9 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -2447,15 +2447,11 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ } } else if (IsClassPtr (Expr->Type)) { if (IsClassPtr (Expr2.Type)) { - /* Both pointers are allowed in comparison if they point to - ** the same type, or if one of them is a void pointer. - */ - Type* left = Indirect (Expr->Type); - Type* right = Indirect (Expr2.Type); - if (TypeCmp (left, right) < TC_QUAL_DIFF && left->C != T_VOID && right->C != T_VOID) { - /* Incompatible pointers */ + /* Pointers are allowed in comparison */ + if (TypeCmp (Expr->Type, Expr2.Type).C < TC_STRICT_COMPATIBLE) { + /* Warn about distinct pointer types */ TypeCompatibilityDiagnostic (PtrConversion (Expr->Type), PtrConversion (Expr2.Type), 0, - "Incompatible pointer types comparing '%s' with '%s'"); + "Distinct pointer types comparing '%s' with '%s'"); } } else if (!ED_IsNullPtr (&Expr2)) { if (IsClassInt (Expr2.Type)) { @@ -3268,17 +3264,25 @@ static void parsesub (ExprDesc* Expr) if (IsClassPtr (lhst) && IsClassPtr (rhst)) { /* Pointer diff */ - if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { - Error ("Incompatible pointer types"); + if (TypeCmp (lhst, rhst).C >= TC_STRICT_COMPATIBLE) { + /* We'll have to scale the result */ + rscale = PSizeOf (lhst); + /* We cannot scale by 0-size or unknown-size */ + if (rscale == 0) { + TypeCompatibilityDiagnostic (lhst, rhst, + 1, "Invalid pointer types in subtraction: '%s' and '%s'"); + /* Avoid further errors */ + rscale = 1; + } + } else { + TypeCompatibilityDiagnostic (lhst, rhst, + 1, "Incompatible pointer types in subtraction: '%s' and '%s'"); } /* Operate on pointers, result type is an integer */ flags = CF_PTR; Expr->Type = type_int; - /* We'll have to scale the result */ - rscale = CheckedPSizeOf (lhst); - /* Check for a constant rhs expression */ if (ED_IsQuasiConst (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { /* The right hand side is constant. Check left hand side. */ @@ -4069,13 +4073,17 @@ static void hieQuest (ExprDesc* Expr) ** Conversion rules for ?: expression are: ** - if both expressions are int expressions, default promotion ** rules for ints apply. - ** - if both expressions are pointers of the same type, the - ** result of the expression is of this type. + ** - if both expressions have the same structure, union or void type, + ** the result has the same type. + ** - if both expressions are pointers to compatible types (possibly + ** qualified differently), the result of the expression is an + ** appropriately qualified version of the composite type. + ** - if one of the expressions is a pointer and the other is a + ** pointer to (possibly qualified) void, the resulting type is a + ** pointer to appropriately qualified void. ** - if one of the expressions is a pointer and the other is - ** a zero constant, the resulting type is that of the pointer - ** type. - ** - if both expressions are void expressions, the result is of - ** type void. + ** a null pointer constant, the resulting type is that of the + ** pointer type. ** - all other cases are flagged by an error. */ if (IsClassInt (Expr2.Type) && IsClassInt (Expr3.Type)) { @@ -4105,12 +4113,28 @@ static void hieQuest (ExprDesc* Expr) } } else if (IsClassPtr (Expr2.Type) && IsClassPtr (Expr3.Type)) { - /* Must point to same type */ - if (TypeCmp (Indirect (Expr2.Type), Indirect (Expr3.Type)) < TC_EQUAL) { - Error ("Incompatible pointer types"); + /* If one of the two is 'void *', the result type is a pointer to + ** appropriately qualified void. + */ + if (IsTypeVoid (Indirect (Expr2.Type))) { + ResultType = PointerTo (Indirect (Expr2.Type)); + ResultType[1].C |= GetQualifier (Indirect (Expr3.Type)); + } else if (IsTypeVoid (Indirect (Expr3.Type))) { + ResultType = PointerTo (Indirect (Expr3.Type)); + ResultType[1].C |= GetQualifier (Indirect (Expr2.Type)); + } else { + /* Must point to compatible types */ + if (TypeCmp (Expr2.Type, Expr3.Type).C < TC_VOID_PTR) { + TypeCompatibilityDiagnostic (Expr2.Type, Expr3.Type, + 1, "Incompatible pointer types in ternary: '%s' and '%s'"); + /* Avoid further errors */ + ResultType = PointerTo (type_void); + } else { + /* Result has the composite type */ + ResultType = TypeDup (Expr2.Type); + TypeComposition (ResultType, Expr3.Type); + } } - /* Result has the common type */ - ResultType = Expr2.Type; } else if (IsClassPtr (Expr2.Type) && Expr3IsNULL) { /* Result type is pointer, no cast needed */ ResultType = Expr2.Type; @@ -4119,10 +4143,10 @@ static void hieQuest (ExprDesc* Expr) ResultType = Expr3.Type; } else if (IsTypeVoid (Expr2.Type) && IsTypeVoid (Expr3.Type)) { /* Result type is void */ - ResultType = Expr3.Type; + ResultType = type_void; } else { if (IsClassStruct (Expr2.Type) && IsClassStruct (Expr3.Type) && - TypeCmp (Expr2.Type, Expr3.Type) == TC_IDENTICAL) { + TypeCmp (Expr2.Type, Expr3.Type).C == TC_IDENTICAL) { /* Result type is struct/union */ ResultType = Expr2.Type; } else { @@ -4148,7 +4172,7 @@ static void hieQuest (ExprDesc* Expr) } /* Setup the target expression */ - Expr->Type = ResultType; + Expr->Type = ResultType; } } diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 3d7176a83..6ec255497 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -59,6 +59,7 @@ #include "stackptr.h" #include "symentry.h" #include "typecmp.h" +#include "typeconv.h" #include "symtab.h" @@ -549,6 +550,19 @@ SymEntry FindStructField (const Type* T, const char* Name) +static int IsDistinctRedef (const Type* lhst, const Type* rhst, typecmpcode_t Code, typecmpflag_t Flags) +/* Return if type compatibility result is "worse" than Code or if any bit of +** qualifier Flags is set. +*/ +{ + typecmp_t Result = TypeCmp (lhst, rhst); + if (Result.C < Code || (Result.F & TCF_MASK_QUAL & Flags) != 0) { + return 1; + } + return 0; +} + + static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags) /* Check and handle redefinition of existing symbols. ** Complete array sizes and function descriptors as well. @@ -565,7 +579,7 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags /* Existing typedefs cannot be redeclared as anything different */ if (SCType == SC_TYPEDEF) { - if (TypeCmp (E_Type, T) < TC_IDENTICAL) { + if (IsDistinctRedef (E_Type, T, TC_IDENTICAL, TCF_MASK_QUAL)) { Error ("Conflicting types for typedef '%s'", Entry->Name); Entry = 0; } @@ -591,7 +605,7 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags Entry = 0; } else { /* New type must be compatible with the composite prototype */ - if (TypeCmp (Entry->Type, T) < TC_EQUAL) { + if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) { Error ("Conflicting function types for '%s'", Entry->Name); Entry = 0; } else { @@ -621,7 +635,7 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags ** is incomplete, complete it. */ if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) || - TypeCmp (T + 1, E_Type + 1) < TC_EQUAL) { + IsDistinctRedef (E_Type + 1, T + 1, TC_IDENTICAL, TCF_MASK_QUAL)) { /* Conflicting element types */ Error ("Conflicting array types for '%s[]'", Entry->Name); Entry = 0; @@ -639,7 +653,7 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags if (SCType != E_SCType) { Error ("Redefinition of '%s' as different kind of symbol", Entry->Name); Entry = 0; - } else if (TypeCmp (E_Type, T) < TC_EQUAL) { + } else if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) { Error ("Conflicting types for '%s'", Entry->Name); Entry = 0; } else if (E_SCType == SC_ENUMERATOR) { diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index f204b9a0b..7aae7fefe 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -36,7 +36,7 @@ #include /* cc65 */ -#include "funcdesc.h" +#include "error.h" #include "global.h" #include "symtab.h" #include "typecmp.h" @@ -49,17 +49,6 @@ -static void SetResult (typecmp_t* Result, typecmp_t Val) -/* Set a new result value if it is less than the existing one */ -{ - if (Val < *Result) { - /* printf ("SetResult = %d\n", Val); */ - *Result = Val; - } -} - - - static int ParamsHaveDefaultPromotions (const FuncDesc* F) /* Check if any of the parameters of function F has a default promotion. In ** this case, the function is not compatible with an empty parameter name list @@ -129,7 +118,7 @@ static int EqualFuncParams (const FuncDesc* F1, const FuncDesc* F2) } /* Compare this field */ - if (TypeCmp (Type1, Type2) < TC_EQUAL) { + if (TypeCmp (Type1, Type2).C < TC_EQUAL) { /* Field types not equal */ return 0; } @@ -148,48 +137,169 @@ static int EqualFuncParams (const FuncDesc* F1, const FuncDesc* F2) +static void SetResult (typecmp_t* Result, typecmpcode_t Val) +/* Set a new result value if it is less than the existing one */ +{ + if (Val < Result->C) { + if (Result->Indirections > 0) { + if (Val >= TC_STRICT_COMPATIBLE) { + Result->C = Val; + } else if (Result->Indirections == 1) { + /* C Standard allows implicit conversion as long as one side is + ** a pointer to void type, but doesn't care which side is. + */ + if ((Result->F & TCF_MASK_VOID_PTR) != 0) { + Result->C = TC_VOID_PTR; + } else { + Result->C = TC_PTR_INCOMPATIBLE; + } + } else { + Result->C = TC_PTR_INCOMPATIBLE; + } + } else { + Result->C = Val; + } + /* printf ("SetResult = %d\n", Val); */ + } +} + + + +static typecmp_t* CmpQuals (const Type* lhst, const Type* rhst, typecmp_t* Result) +/* Copare the types regarding thier qualifiers. Return the Result */ +{ + TypeCode LeftQual, RightQual; + + /* Get the left and right qualifiers */ + LeftQual = GetQualifier (lhst); + RightQual = GetQualifier (rhst); + + /* If type is function without a calling convention set explicitly, + ** then assume the default one. + */ + if (IsTypeFunc (lhst)) { + if ((LeftQual & T_QUAL_CCONV) == T_QUAL_NONE) { + LeftQual |= (AutoCDecl || IsVariadicFunc (lhst)) ? T_QUAL_CDECL : T_QUAL_FASTCALL; + } + } + if (IsTypeFunc (rhst)) { + if ((RightQual & T_QUAL_CCONV) == T_QUAL_NONE) { + RightQual |= (AutoCDecl || IsVariadicFunc (rhst)) ? T_QUAL_CDECL : T_QUAL_FASTCALL; + } + } + + /* Default address size qualifiers */ + if ((LeftQual & T_QUAL_ADDRSIZE) == T_QUAL_NONE) { + LeftQual |= (IsTypeFunc (lhst) ? CodeAddrSizeQualifier () : DataAddrSizeQualifier ()); + } + if ((RightQual & T_QUAL_ADDRSIZE) == T_QUAL_NONE) { + RightQual |= (IsTypeFunc (rhst) ? CodeAddrSizeQualifier () : DataAddrSizeQualifier ()); + } + + /* Just return if nothing to do */ + if (LeftQual == RightQual) { + return Result; + } + + /* On the first indirection level, different qualifiers mean that the types + ** are still compatible. On the second level, that is a (maybe minor) error. + ** We create a special return-code if a qualifier is dropped from a pointer. + ** But, different calling conventions are incompatible. Starting from the + ** next level, the types are incompatible if the qualifiers differ. + */ + /* (Debugging statement) */ + /* printf ("Ind = %d %06X != %06X\n", Result->Indirections, LeftQual, RightQual); */ + switch (Result->Indirections) { + case 0: + /* Compare C qualifiers */ + if ((LeftQual & T_QUAL_CVR) > (RightQual & T_QUAL_CVR)) { + Result->F |= TCF_QUAL_IMPLICIT; + } else if ((LeftQual & T_QUAL_CVR) != (RightQual & T_QUAL_CVR)) { + Result->F |= TCF_QUAL_DIFF; + } + + /* Compare address size qualifiers */ + if ((LeftQual & T_QUAL_ADDRSIZE) != (RightQual & T_QUAL_ADDRSIZE)) { + Result->F |= TCF_ADDRSIZE_QUAL_DIFF; + } + + /* Compare function calling conventions */ + if ((LeftQual & T_QUAL_CCONV) != (RightQual & T_QUAL_CCONV)) { + SetResult (Result, TC_INCOMPATIBLE); + } + break; + + case 1: + /* A non-const value on the right is compatible to a + ** const one to the left, same for volatile. + */ + if ((LeftQual & T_QUAL_CVR) > (RightQual & T_QUAL_CVR)) { + Result->F |= TCF_PTR_QUAL_IMPLICIT; + } else if ((LeftQual & T_QUAL_CVR) != (RightQual & T_QUAL_CVR)) { + Result->F |= TCF_PTR_QUAL_DIFF; + } + + /* Compare address size qualifiers */ + if ((LeftQual & T_QUAL_ADDRSIZE) != (RightQual & T_QUAL_ADDRSIZE)) { + Result->F |= TCF_ADDRSIZE_QUAL_DIFF; + } + + /* Compare function calling conventions */ + if ((!IsTypeFunc (lhst) && !IsTypeFunc (rhst)) || + (LeftQual & T_QUAL_CCONV) == (RightQual & T_QUAL_CCONV)) { + break; + } + /* else fall through */ + + default: + /* Pointer types mismatch */ + SetResult (Result, TC_INCOMPATIBLE); + break; + } + + return Result; +} + + + static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) /* Recursively compare two types. */ { - unsigned Indirections; - unsigned ElementCount; SymEntry* Sym1; SymEntry* Sym2; FuncDesc* F1; FuncDesc* F2; + TypeCode LeftType, RightType; + long LeftCount, RightCount; - /* Initialize stuff */ - Indirections = 0; - ElementCount = 0; - /* Compare two types. Determine, where they differ */ while (lhs->C != T_END) { - TypeCode LeftType, RightType; - TypeCode LeftSign, RightSign; - TypeCode LeftQual, RightQual; - long LeftCount, RightCount; - /* Check if the end of the type string is reached */ if (rhs->C == T_END) { /* End of comparison reached */ + break; + } + + /* Compare qualifiers */ + if (CmpQuals (lhs, rhs, Result)->C == TC_INCOMPATIBLE) { return; } - /* Get the left and right types, signs and qualifiers */ + /* Get the left and right types */ LeftType = (GetUnderlyingTypeCode (lhs) & T_MASK_TYPE); RightType = (GetUnderlyingTypeCode (rhs) & T_MASK_TYPE); - LeftSign = GetSignedness (lhs); - RightSign = GetSignedness (rhs); - LeftQual = GetQualifier (lhs); - RightQual = GetQualifier (rhs); - /* If the left type is a pointer and the right is an array, both - ** are compatible. + /* If one side is a pointer and the other side is an array, both are + ** compatible. */ if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) { RightType = T_TYPE_PTR; + SetResult (Result, TC_PTR_DECAY); + } + if (LeftType == T_TYPE_ARRAY && RightType == T_TYPE_PTR) { + LeftType = T_TYPE_PTR; SetResult (Result, TC_STRICT_COMPATIBLE); } @@ -236,74 +346,30 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) /* 'char' is neither 'signed char' nor 'unsigned char' */ if ((IsISOChar (lhs) && !IsISOChar (rhs)) || (!IsISOChar (lhs) && IsISOChar (rhs))) { - SetResult (Result, TC_COMPATIBLE); + SetResult (Result, TC_SIGN_DIFF); } - /* On indirection level zero, a qualifier or sign difference is - ** accepted. The types are no longer equal, but compatible. + /* On indirection level zero, a sign difference is accepted. + ** The types are no longer equal, but compatible. */ - if (LeftSign != RightSign) { - if (ElementCount == 0) { - SetResult (Result, TC_SIGN_DIFF); - } else { - SetResult (Result, TC_INCOMPATIBLE); - return; - } - } - - if (LeftType == T_TYPE_FUNC) { - /* If a calling convention wasn't set explicitly, - ** then assume the default one. - */ - if ((LeftQual & T_QUAL_CCONV) == T_QUAL_NONE) { - LeftQual |= (AutoCDecl || IsVariadicFunc (lhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL; - } - if ((RightQual & T_QUAL_CCONV) == T_QUAL_NONE) { - RightQual |= (AutoCDecl || IsVariadicFunc (rhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL; - } - } - - if (LeftQual != RightQual) { - /* On the first indirection level, different qualifiers mean - ** that the types still are compatible. On the second level, - ** that is a (maybe minor) error. We create a special return-code - ** if a qualifier is dropped from a pointer. But, different calling - ** conventions are incompatible. Starting from the next level, - ** the types are incompatible if the qualifiers differ. - */ - /* (Debugging statement) */ - /* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */ - switch (Indirections) { - case 0: - SetResult (Result, TC_STRICT_COMPATIBLE); - break; - - case 1: - /* A non-const value on the right is compatible to a - ** const one to the left, same for volatile. - */ - if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) || - (LeftQual & T_QUAL_VOLATILE) < (RightQual & T_QUAL_VOLATILE)) { - SetResult (Result, TC_QUAL_DIFF); - } else { - SetResult (Result, TC_STRICT_COMPATIBLE); - } - - if (LeftType != T_TYPE_FUNC || (LeftQual & T_QUAL_CCONV) == (RightQual & T_QUAL_CCONV)) { - break; - } - /* else fall through */ - - default: - SetResult (Result, TC_INCOMPATIBLE); - return; - } + if (GetSignedness (lhs) != GetSignedness (rhs)) { + SetResult (Result, TC_SIGN_DIFF); } /* Check for special type elements */ switch (LeftType) { case T_TYPE_PTR: - ++Indirections; + ++Result->Indirections; + if (Result->Indirections == 1) { + if ((GetUnderlyingTypeCode (lhs + 1) & T_MASK_TYPE) == T_TYPE_VOID) { + Result->F |= TCF_VOID_PTR_ON_LEFT; + } + if ((GetUnderlyingTypeCode (rhs + 1) & T_MASK_TYPE) == T_TYPE_VOID) { + Result->F |= TCF_VOID_PTR_ON_RIGHT; + } + } else { + Result->F &= ~TCF_MASK_VOID_PTR; + } break; case T_TYPE_FUNC: @@ -364,7 +430,13 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) SetResult (Result, TC_INCOMPATIBLE); return; } - SetResult (Result, TC_EQUAL); + + /* We take into account which side is more specified */ + if (LeftCount == UNSPECIFIED) { + SetResult (Result, TC_UNSPECIFY); + } else { + SetResult (Result, TC_EQUAL); + } } break; @@ -397,11 +469,10 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) /* Next type string element */ ++lhs; ++rhs; - ++ElementCount; } - /* Check if end of rhs reached */ - if (rhs->C == T_END) { + /* Check if lhs and rhs both reached ends */ + if (lhs->C == T_END && rhs->C == T_END) { SetResult (Result, TC_IDENTICAL); } else { SetResult (Result, TC_INCOMPATIBLE); @@ -414,7 +485,7 @@ typecmp_t TypeCmp (const Type* lhs, const Type* rhs) /* Compare two types and return the result */ { /* Assume the types are identical */ - typecmp_t Result = TC_IDENTICAL; + typecmp_t Result = TYPECMP_INITIALIZER; #if 0 printf ("Left : "); PrintRawType (stdout, lhs); @@ -432,134 +503,18 @@ typecmp_t TypeCmp (const Type* lhs, const Type* rhs) -static Type* DoComposite (Type* lhs, const Type* rhs); - -static void CompositeFuncParams (const FuncDesc* F1, const FuncDesc* F2) -/* Composite two function symbol tables regarding function parameters */ +void TypeCompatibilityDiagnostic (const Type* NewType, const Type* OldType, int IsError, const char* Msg) +/* Print error or warning message about type compatibility with proper type names */ { - /* Get the symbol tables */ - const SymTable* Tab1 = F1->SymTab; - const SymTable* Tab2 = F2->SymTab; - - /* Composite the parameter lists */ - const SymEntry* Sym1 = Tab1->SymHead; - const SymEntry* Sym2 = Tab2->SymHead; - - /* Composite the fields */ - while (Sym1 && (Sym1->Flags & SC_PARAM) && Sym2 && (Sym2->Flags & SC_PARAM)) { - - /* Get the symbol types */ - Type* Type1 = Sym1->Type; - Type* Type2 = Sym2->Type; - - /* If either of both functions is old style, apply the default - ** promotions to the parameter type. - */ - if (F1->Flags & FD_OLDSTYLE) { - if (IsClassInt (Type1)) { - Type1 = IntPromotion (Type1); - } - } - if (F2->Flags & FD_OLDSTYLE) { - if (IsClassInt (Type2)) { - Type2 = IntPromotion (Type2); - } - } - - /* Composite this field */ - DoComposite (Type1, Type2); - - /* Get the pointers to the next fields */ - Sym1 = Sym1->NextSym; - Sym2 = Sym2->NextSym; + StrBuf NewTypeName = STATIC_STRBUF_INITIALIZER; + StrBuf OldTypeName = STATIC_STRBUF_INITIALIZER; + GetFullTypeNameBuf (&NewTypeName, NewType); + GetFullTypeNameBuf (&OldTypeName, OldType); + if (IsError) { + Error (Msg, SB_GetConstBuf (&NewTypeName), SB_GetConstBuf (&OldTypeName)); + } else { + Warning (Msg, SB_GetConstBuf (&NewTypeName), SB_GetConstBuf (&OldTypeName)); } -} - - - -static Type* DoComposite (Type* lhs, const Type* rhs) -/* Recursively composite two types into lhs */ -{ - FuncDesc* F1; - FuncDesc* F2; - long LeftCount, RightCount; - - /* Composite two types */ - while (lhs->C != T_END) { - - /* Check if the end of the type string is reached */ - if (rhs->C == T_END) { - return lhs; - } - - /* Check for sanity */ - CHECK (GetUnderlyingTypeCode (lhs) == GetUnderlyingTypeCode (rhs)); - - /* Check for special type elements */ - - if (IsTypeFunc (lhs)) { - /* Composite the function descriptors */ - F1 = GetFuncDesc (lhs); - F2 = GetFuncDesc (rhs); - - /* If one of both functions has an empty parameter list (which - ** does also mean, it is not a function definition, because the - ** flag is reset in this case), it is replaced by the other - ** definition, provided that the other has no default - ** promotions in the parameter list. If none of both parameter - ** lists is empty, we have to composite the parameter lists and - ** other attributes. - */ - if ((F1->Flags & FD_EMPTY) == FD_EMPTY) { - if ((F2->Flags & FD_EMPTY) == 0) { - /* Copy the parameters and flags */ - TypeCopy (lhs, rhs); - F1->Flags = F2->Flags; - } - } else if ((F2->Flags & FD_EMPTY) == 0) { - /* Composite the parameter lists */ - CompositeFuncParams (F1, F2); - } - - } else if (IsTypeArray (lhs)) { - /* Check member count */ - LeftCount = GetElementCount (lhs); - RightCount = GetElementCount (rhs); - - /* Set composite type if it is requested */ - if (LeftCount != UNSPECIFIED) { - SetElementCount (lhs, LeftCount); - } else if (RightCount != UNSPECIFIED) { - SetElementCount (lhs, RightCount); - } - } - - /* Next type string element */ - ++lhs; - ++rhs; - } - - return lhs; -} - - - -FuncDesc* RefineFuncDesc (Type* OldType, const Type* NewType) -/* Refine the existing function descriptor with a new one */ -{ - FuncDesc* Old = GetFuncDesc (OldType); - FuncDesc* New = GetFuncDesc (NewType); - - CHECK (Old != 0 && New != 0); - - if ((New->Flags & FD_EMPTY) == 0) { - if ((Old->Flags & FD_EMPTY) == 0) { - DoComposite (OldType, NewType); - } else { - TypeCopy (OldType, NewType); - Old->Flags &= ~FD_EMPTY; - } - } - - return Old; + SB_Done (&OldTypeName); + SB_Done (&NewTypeName); } diff --git a/src/cc65/typecmp.h b/src/cc65/typecmp.h index f4a87bcf6..e1ca699cf 100644 --- a/src/cc65/typecmp.h +++ b/src/cc65/typecmp.h @@ -48,18 +48,43 @@ -/* Degree of type compatibility. Must be in ascending order */ +/* Degree of type compatibility affected. Must be in ascending order */ typedef enum { - TC_INCOMPATIBLE, /* Distinct types */ - TC_SIGN_DIFF, /* Signedness differs */ - TC_COMPATIBLE = TC_SIGN_DIFF, /* Compatible types */ - TC_QUAL_DIFF, /* Types differ in qualifier of pointer */ - TC_STRICT_COMPATIBLE, /* Strict compatibility */ - TC_EQUAL, /* Types are equivalent */ - TC_IDENTICAL /* Types are identical */ + TC_INCOMPATIBLE, /* Distinct types */ + TC_SIGN_DIFF, /* Signedness differs */ + TC_PTR_INCOMPATIBLE, /* Distinct pointer types */ + TC_VOID_PTR, /* Non-void and void pointers */ + TC_STRICT_COMPATIBLE, /* Strict compatibility according to the C Standard */ + TC_PTR_DECAY, /* rhs is an array and lhs is a pointer */ + TC_EQUAL, /* Array types with unspecified lengths */ + TC_UNSPECIFY, /* lhs has unspecified length while rhs has specified length */ + TC_IDENTICAL /* Types are identical */ +} typecmpcode_t; + +/* Degree of type compatibility affected by qualifiers as well as some extra info */ +typedef enum { + TCF_NONE = 0x00, /* None of the below */ + TCF_VOID_PTR_ON_LEFT = 0x01, /* lhs is a void pointer */ + TCF_VOID_PTR_ON_RIGHT = 0x02, /* rhs is a void pointer */ + TCF_MASK_VOID_PTR = TCF_VOID_PTR_ON_LEFT | TCF_VOID_PTR_ON_RIGHT, + TCF_QUAL_DIFF = 0x04, /* CVR qualifiers differ in a way that doesn't matter */ + TCF_QUAL_IMPLICIT = 0x08, /* CVR qualifiers of lhs are stricter than those of rhs */ + TCF_PTR_QUAL_DIFF = 0x10, /* CVR qualifiers of pointers differ */ + TCF_PTR_QUAL_IMPLICIT = 0x20, /* CVR qualifiers of pointers are stricter on lhs than those on rhs */ + TCF_MASK_C_QUAL_DIFF = 0x3C, /* All C Standard qualifiers */ + TCF_ADDRSIZE_QUAL_DIFF = 0x40, /* Address size qualifiers differ */ + TCF_CCONV_QUAL_DIFF = 0x80, /* Function calling conventions differ. Unused now */ + TCF_INCOMPATIBLE_QUAL = TCF_ADDRSIZE_QUAL_DIFF | TCF_CCONV_QUAL_DIFF, + TCF_MASK_QUAL = TCF_MASK_C_QUAL_DIFF | TCF_INCOMPATIBLE_QUAL, +} typecmpflag_t; + +typedef struct { + typecmpcode_t C; + typecmpflag_t F; + int Indirections; } typecmp_t; - +#define TYPECMP_INITIALIZER { TC_IDENTICAL, TCF_NONE, 0 } /*****************************************************************************/ /* Code */ @@ -70,8 +95,9 @@ typedef enum { typecmp_t TypeCmp (const Type* lhs, const Type* rhs); /* Compare two types and return the result */ -FuncDesc* RefineFuncDesc (Type* OldType, const Type* NewType); -/* Refine the existing function descriptor with a new one */ +void TypeCompatibilityDiagnostic (const Type* NewType, const Type* OldType, int IsError, const char* Msg); +/* Print error or warning message about type compatibility with proper type names */ + /* End of typecmp.h */ diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index 930aef8d4..d75d13cd1 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -43,7 +43,6 @@ #include "error.h" #include "expr.h" #include "loadexpr.h" -#include "scanner.h" #include "typecmp.h" #include "typeconv.h" @@ -55,24 +54,6 @@ -void TypeCompatibilityDiagnostic (const Type* NewType, const Type* OldType, int IsError, const char* Msg) -/* Print error or warning message about type conversion with proper type names */ -{ - StrBuf NewTypeName = STATIC_STRBUF_INITIALIZER; - StrBuf OldTypeName = STATIC_STRBUF_INITIALIZER; - GetFullTypeNameBuf (&NewTypeName, NewType); - GetFullTypeNameBuf (&OldTypeName, OldType); - if (IsError) { - Error (Msg, SB_GetConstBuf (&NewTypeName), SB_GetConstBuf (&OldTypeName)); - } else { - Warning (Msg, SB_GetConstBuf (&NewTypeName), SB_GetConstBuf (&OldTypeName)); - } - SB_Done (&OldTypeName); - SB_Done (&NewTypeName); -} - - - static void DoConversion (ExprDesc* Expr, const Type* NewType) /* Emit code to convert the given expression to a new type. */ { @@ -208,9 +189,10 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType) PrintRawType (stdout, NewType); #endif /* First, do some type checking */ - int HasWarning = 0; - int HasError = 0; - const char* Msg = 0; + typecmp_t Result = TYPECMP_INITIALIZER; + int HasWarning = 0; + int HasError = 0; + const char* Msg = 0; const Type* OldType = Expr->Type; @@ -219,20 +201,13 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType) HasError = 1; } - /* If both types are strictly compatible, no conversion is needed */ - if (TypeCmp (NewType, OldType) >= TC_STRICT_COMPATIBLE) { - /* We're already done */ - return; - } - - /* If Expr is an array or a function, convert it to a pointer */ - Expr->Type = PtrConversion (Expr->Type); - - /* If we have changed the type, check again for strictly compatibility */ - if (Expr->Type != OldType && - TypeCmp (NewType, Expr->Type) >= TC_STRICT_COMPATIBLE) { - /* We're already done */ - return; + /* If both types are the same, no conversion is needed */ + Result = TypeCmp (NewType, OldType); + if (Result.C < TC_IDENTICAL && (IsTypeArray (OldType) || IsTypeFunc (OldType))) { + /* If Expr is an array or a function, convert it to a pointer */ + Expr->Type = PtrConversion (Expr->Type); + /* Recompare */ + Result = TypeCmp (NewType, Expr->Type); } /* Check for conversion problems */ @@ -253,37 +228,27 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType) /* Handle conversions to pointer type */ if (IsClassPtr (Expr->Type)) { - /* Pointer to pointer assignment is valid, if: + /* Implicit pointer-to-pointer conversion is valid, if: ** - both point to the same types, or ** - the rhs pointer is a void pointer, or ** - the lhs pointer is a void pointer. */ - if (!IsTypeVoid (IndirectConst (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) { - /* Compare the types */ - switch (TypeCmp (NewType, Expr->Type)) { - - case TC_INCOMPATIBLE: - HasWarning = 1; - Msg = "Incompatible pointer assignment to '%s' from '%s'"; - /* Use the pointer type in the diagnostic */ - OldType = Expr->Type; - break; - - case TC_QUAL_DIFF: - HasWarning = 1; - Msg = "Pointer assignment to '%s' from '%s' discards qualifiers"; - /* Use the pointer type in the diagnostic */ - OldType = Expr->Type; - break; - - default: - /* Ok */ - break; - } + if (Result.C <= TC_PTR_INCOMPATIBLE || + (Result.F & TCF_INCOMPATIBLE_QUAL) != 0) + { + HasWarning = 1; + Msg = "Incompatible pointer conversion to '%s' from '%s'"; + /* Use the pointer type in the diagnostic */ + OldType = Expr->Type; + } else if ((Result.F & TCF_PTR_QUAL_DIFF) != 0) { + HasWarning = 1; + Msg = "Pointer conversion to '%s' from '%s' discards qualifiers"; + /* Use the pointer type in the diagnostic */ + OldType = Expr->Type; } } else if (IsClassInt (Expr->Type)) { - /* Int to pointer assignment is valid only for constant zero */ + /* Int to pointer conversion is valid only for constant zero */ if (!ED_IsConstAbsInt (Expr) || Expr->IVal != 0) { Warning ("Converting integer to pointer without a cast"); } @@ -291,11 +256,12 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType) HasError = 1; } - } else { + } else if (Result.C < TC_IDENTICAL) { /* Invalid automatic conversion */ HasError = 1; } + /* Set default diagnostic message */ if (Msg == 0) { Msg = "Converting to '%s' from '%s'"; } @@ -350,13 +316,13 @@ void TypeCast (ExprDesc* Expr) /* Convert functions and arrays to "pointer to" object */ Expr->Type = PtrConversion (Expr->Type); - if (TypeCmp (NewType, Expr->Type) >= TC_QUAL_DIFF) { - /* If the new type only differs in qualifiers, just use it to - ** replace the old one. + if (TypeCmp (NewType, Expr->Type).C >= TC_PTR_INCOMPATIBLE) { + /* If the new type has the same underlying presentation, just + ** use it to replace the old one. */ ReplaceType (Expr, NewType); } else if (IsCastType (Expr->Type)) { - /* Convert the value. The rsult has always the new type */ + /* Convert the value. The result has always the new type */ DoConversion (Expr, NewType); } else { TypeCompatibilityDiagnostic (NewType, Expr->Type, 1, @@ -379,3 +345,142 @@ void TypeCast (ExprDesc* Expr) /* The result is always an rvalue */ ED_MarkExprAsRVal (Expr); } + + + +static void CompositeFuncParamList (const FuncDesc* F1, const FuncDesc* F2) +/* Composite two function symbol tables regarding function parameters */ +{ + /* Get the symbol tables */ + const SymTable* Tab1 = F1->SymTab; + const SymTable* Tab2 = F2->SymTab; + + /* Composite the parameter lists */ + const SymEntry* Sym1 = Tab1->SymHead; + const SymEntry* Sym2 = Tab2->SymHead; + + /* Composite the fields */ + while (Sym1 && (Sym1->Flags & SC_PARAM) && Sym2 && (Sym2->Flags & SC_PARAM)) { + + /* Get the symbol types */ + Type* Type1 = Sym1->Type; + Type* Type2 = Sym2->Type; + + /* If either of both functions is old style, apply the default + ** promotions to the parameter type. + */ + if (F1->Flags & FD_OLDSTYLE) { + if (IsClassInt (Type1)) { + Type1 = IntPromotion (Type1); + } + } + if (F2->Flags & FD_OLDSTYLE) { + if (IsClassInt (Type2)) { + Type2 = IntPromotion (Type2); + } + } + + /* Compose this field */ + TypeComposition (Type1, Type2); + + /* Get the pointers to the next fields */ + Sym1 = Sym1->NextSym; + Sym2 = Sym2->NextSym; + } +} + + + +void TypeComposition (Type* lhs, const Type* rhs) +/* Recursively compose two types into lhs. The two types must have compatible +** type or this fails with a critical check. +*/ +{ + FuncDesc* F1; + FuncDesc* F2; + long LeftCount, RightCount; + + /* Composite two types */ + while (lhs->C != T_END) { + + /* Check if the end of the type string is reached */ + if (rhs->C == T_END) { + break; + } + + /* Check for sanity */ + CHECK (GetUnderlyingTypeCode (lhs) == GetUnderlyingTypeCode (rhs)); + + /* Check for special type elements */ + if (IsTypeFunc (lhs)) { + /* Composite the function descriptors */ + F1 = GetFuncDesc (lhs); + F2 = GetFuncDesc (rhs); + + /* If one of both functions has an empty parameter list (which + ** does also mean, it is not a function definition, because the + ** flag is reset in this case), it is replaced by the other + ** definition, provided that the other has no default + ** promotions in the parameter list. If none of both parameter + ** lists is empty, we have to composite the parameter lists and + ** other attributes. + */ + if ((F1->Flags & FD_EMPTY) == FD_EMPTY) { + if ((F2->Flags & FD_EMPTY) == 0) { + /* Copy the parameters and flags */ + TypeCopy (lhs, rhs); + F1->Flags = F2->Flags; + } + } else if ((F2->Flags & FD_EMPTY) == 0) { + /* Composite the parameter lists */ + CompositeFuncParamList (F1, F2); + } + } else if (IsTypeArray (lhs)) { + /* Check member count */ + LeftCount = GetElementCount (lhs); + RightCount = GetElementCount (rhs); + + /* Set composite type if it is requested */ + if (LeftCount != UNSPECIFIED) { + SetElementCount (lhs, LeftCount); + } else if (RightCount != UNSPECIFIED) { + SetElementCount (lhs, RightCount); + } + } else { + /* Combine the qualifiers */ + if (IsClassPtr (lhs)) { + ++lhs; + ++rhs; + lhs->C |= GetQualifier (rhs); + } + } + + /* Next type string element */ + ++lhs; + ++rhs; + } + + return; +} + + + +FuncDesc* RefineFuncDesc (Type* OldType, const Type* NewType) +/* Refine the existing function descriptor with a new one */ +{ + FuncDesc* Old = GetFuncDesc (OldType); + FuncDesc* New = GetFuncDesc (NewType); + + CHECK (Old != 0 && New != 0); + + if ((New->Flags & FD_EMPTY) == 0) { + if ((Old->Flags & FD_EMPTY) == 0) { + TypeComposition (OldType, NewType); + } else { + TypeCopy (OldType, NewType); + Old->Flags &= ~FD_EMPTY; + } + } + + return Old; +} diff --git a/src/cc65/typeconv.h b/src/cc65/typeconv.h index 0a82eac27..839c5e43e 100644 --- a/src/cc65/typeconv.h +++ b/src/cc65/typeconv.h @@ -49,9 +49,6 @@ -void TypeCompatibilityDiagnostic (const Type* NewType, const Type* OldType, int IsError, const char* Msg); -/* Print error or warning message about type conversion with proper type names */ - void TypeConversion (ExprDesc* Expr, const Type* NewType); /* Do an automatic conversion of the given expression to the new type. Output ** warnings or errors where this automatic conversion is suspicious or @@ -61,6 +58,14 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType); void TypeCast (ExprDesc* Expr); /* Handle an explicit cast. */ +void TypeComposition (Type* lhs, const Type* rhs); +/* Recursively compose two types into lhs. The two types must have compatible +** type or this fails with a critical check. +*/ + +FuncDesc* RefineFuncDesc (Type* OldType, const Type* NewType); +/* Refine the existing function descriptor with a new one */ + /* End of typeconv.h */ From 4a3896538409ec6a186bbabbd3f94e9dec7e70b4 Mon Sep 17 00:00:00 2001 From: acqn Date: Thu, 25 Mar 2021 13:32:46 +0800 Subject: [PATCH 75/80] Warnings on discarding pointer qualifiers always. Added new -W options to turn on/off warnings on certain pointer conversion cases: - pointer-sign: to a pointer type differing in pointee signedness. Default on. - pointer-types: to a pointer type incompatible. Default on. --- src/cc65/error.c | 4 ++++ src/cc65/error.h | 2 ++ src/cc65/typecmp.c | 8 ++++++++ src/cc65/typecmp.h | 1 + src/cc65/typeconv.c | 38 +++++++++++++++++++++----------------- 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/cc65/error.c b/src/cc65/error.c index feb43565d..ec665b319 100644 --- a/src/cc65/error.c +++ b/src/cc65/error.c @@ -68,6 +68,8 @@ IntStack WarningsAreErrors = INTSTACK(0); /* Treat warnings as errors */ /* Warn about: */ IntStack WarnConstComparison= INTSTACK(1); /* - constant comparison results */ IntStack WarnNoEffect = INTSTACK(1); /* - statements without an effect */ +IntStack WarnPointerSign = INTSTACK(1); /* - pointer conversion to pointer differing in signedness */ +IntStack WarnPointerTypes = INTSTACK(1); /* - pointer conversion to incompatible pointer type */ IntStack WarnRemapZero = INTSTACK(1); /* - remapping character code zero */ IntStack WarnStructParam = INTSTACK(0); /* - structs passed by val */ IntStack WarnUnknownPragma = INTSTACK(1); /* - unknown #pragmas */ @@ -87,6 +89,8 @@ static WarnMapEntry WarnMap[] = { { &WarnConstComparison, "const-comparison" }, { &WarningsAreErrors, "error" }, { &WarnNoEffect, "no-effect" }, + { &WarnPointerSign, "pointer-sign" }, + { &WarnPointerTypes, "pointer-types" }, { &WarnRemapZero, "remap-zero" }, { &WarnStructParam, "struct-param" }, { &WarnUnknownPragma, "unknown-pragma" }, diff --git a/src/cc65/error.h b/src/cc65/error.h index 898793651..a7592b366 100644 --- a/src/cc65/error.h +++ b/src/cc65/error.h @@ -64,6 +64,8 @@ extern IntStack WarnEnable; /* Enable warnings */ extern IntStack WarningsAreErrors; /* Treat warnings as errors */ /* Warn about: */ extern IntStack WarnConstComparison; /* - constant comparison results */ +extern IntStack WarnPointerSign; /* - pointer conversion to pointer differing in signedness */ +extern IntStack WarnPointerTypes; /* - pointer conversion to incompatible pointer type */ extern IntStack WarnNoEffect; /* - statements without an effect */ extern IntStack WarnRemapZero; /* - remapping character code zero */ extern IntStack WarnStructParam; /* - structs passed by val */ diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index 7aae7fefe..567ab4e87 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -143,6 +143,7 @@ static void SetResult (typecmp_t* Result, typecmpcode_t Val) if (Val < Result->C) { if (Result->Indirections > 0) { if (Val >= TC_STRICT_COMPATIBLE) { + /* Arrays etc. */ Result->C = Val; } else if (Result->Indirections == 1) { /* C Standard allows implicit conversion as long as one side is @@ -150,10 +151,17 @@ static void SetResult (typecmp_t* Result, typecmpcode_t Val) */ if ((Result->F & TCF_MASK_VOID_PTR) != 0) { Result->C = TC_VOID_PTR; + } else if (Val == TC_SIGN_DIFF) { + /* Special treatment with pointee signedness difference */ + Result->C = TC_PTR_SIGN_DIFF; } else { + /* Incompatible */ Result->C = TC_PTR_INCOMPATIBLE; } } else { + /* Pointer-to-pointer types must have compatible pointte types, + ** or they are just incompatible. + */ Result->C = TC_PTR_INCOMPATIBLE; } } else { diff --git a/src/cc65/typecmp.h b/src/cc65/typecmp.h index e1ca699cf..367df5245 100644 --- a/src/cc65/typecmp.h +++ b/src/cc65/typecmp.h @@ -52,6 +52,7 @@ typedef enum { TC_INCOMPATIBLE, /* Distinct types */ TC_SIGN_DIFF, /* Signedness differs */ + TC_PTR_SIGN_DIFF, /* Pointee signedness differs */ TC_PTR_INCOMPATIBLE, /* Distinct pointer types */ TC_VOID_PTR, /* Non-void and void pointers */ TC_STRICT_COMPATIBLE, /* Strict compatibility according to the C Standard */ diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index d75d13cd1..91a1f022d 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -190,7 +190,6 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType) #endif /* First, do some type checking */ typecmp_t Result = TYPECMP_INITIALIZER; - int HasWarning = 0; int HasError = 0; const char* Msg = 0; const Type* OldType = Expr->Type; @@ -232,19 +231,28 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType) ** - both point to the same types, or ** - the rhs pointer is a void pointer, or ** - the lhs pointer is a void pointer. + ** Note: We additionally allow converting function pointers to and from + ** void pointers, just with warnings. */ - if (Result.C <= TC_PTR_INCOMPATIBLE || - (Result.F & TCF_INCOMPATIBLE_QUAL) != 0) - { - HasWarning = 1; - Msg = "Incompatible pointer conversion to '%s' from '%s'"; - /* Use the pointer type in the diagnostic */ - OldType = Expr->Type; - } else if ((Result.F & TCF_PTR_QUAL_DIFF) != 0) { - HasWarning = 1; - Msg = "Pointer conversion to '%s' from '%s' discards qualifiers"; - /* Use the pointer type in the diagnostic */ - OldType = Expr->Type; + if (Result.C == TC_PTR_SIGN_DIFF) { + /* Specific warning for pointee signedness difference */ + if (IS_Get (&WarnPointerSign)) { + TypeCompatibilityDiagnostic (NewType, Expr->Type, + 0, "Pointer conversion to '%s' from '%s' changes pointee signedness"); + } + } else if ((Result.C <= TC_PTR_INCOMPATIBLE || + (Result.F & TCF_INCOMPATIBLE_QUAL) != 0)) { + /* Incompatible pointee types or qualifiers */ + if (IS_Get (&WarnPointerTypes)) { + TypeCompatibilityDiagnostic (NewType, Expr->Type, + 0, "Incompatible pointer conversion to '%s' from '%s'"); + } + } + + if ((Result.F & TCF_PTR_QUAL_DIFF) != 0) { + /* Discarding qualifiers is a bad thing and we always warn */ + TypeCompatibilityDiagnostic (NewType, Expr->Type, + 0, "Pointer conversion to '%s' from '%s' discards qualifiers"); } } else if (IsClassInt (Expr->Type)) { @@ -269,10 +277,6 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType) if (HasError) { TypeCompatibilityDiagnostic (NewType, OldType, 1, Msg); } else { - if (HasWarning) { - TypeCompatibilityDiagnostic (NewType, OldType, 0, Msg); - } - /* Both types must be complete */ if (!IsIncompleteESUType (NewType) && !IsIncompleteESUType (Expr->Type)) { /* Do the actual conversion */ From 200b42056216457a4f79097bf76195ef5bbb3da2 Mon Sep 17 00:00:00 2001 From: Christian Groessler Date: Thu, 1 Apr 2021 15:06:47 +0200 Subject: [PATCH 76/80] Export LMARGN_save to C. People might want to preserve this setting in their program. In turn rearrange startup code in order that LMARGN can be set by a 'constructor' (Do "initlib" later.) --- libsrc/atari/crt0.s | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libsrc/atari/crt0.s b/libsrc/atari/crt0.s index 97b7d7e95..381aa699f 100644 --- a/libsrc/atari/crt0.s +++ b/libsrc/atari/crt0.s @@ -10,6 +10,7 @@ .export __STARTUP__ : absolute = 1 ; Mark as startup .export _exit, start, excexit, SP_save + .export __LMARGN_save ; original LMARGN setting .import initlib, donelib .import callmain, zerobss @@ -82,14 +83,10 @@ start: .endif -; Call the module constructors. - - jsr initlib - ; Set the left margin to 0. lda LMARGN - sta LMARGN_save + sta __LMARGN_save ldy #0 sty LMARGN @@ -104,6 +101,10 @@ start: dey ; Set Y to $FF sty CH ; remove keypress which might be in the input buffer +; Call the module constructors. + + jsr initlib + ; Push the command-line arguments; and, call main(). jsr callmain @@ -119,7 +120,7 @@ excexit:jsr donelib ; Run module destructors; 'excexit' is called fr ; Restore the left margin. - lda LMARGN_save + lda __LMARGN_save sta LMARGN ; Restore the kb mode. @@ -196,7 +197,7 @@ excexit:jsr donelib ; Run module destructors; 'excexit' is called fr SP_save: .res 1 SHFLOK_save: .res 1 -LMARGN_save: .res 1 +__LMARGN_save: .res 1 .ifndef __ATARIXL__ APPMHI_save: .res 2 .endif From 91fd30611a3e24a8d0702d5345812cdbf1a79671 Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 29 Mar 2021 14:30:44 +0800 Subject: [PATCH 77/80] Fixed ICE on error cases such as '&func + int a'. --- src/cc65/expr.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index be53b22f9..58de0d891 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -2850,27 +2850,31 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef) } else { /* OOPS */ AddDone = -1; + /* Avoid further errors */ + ED_MakeConstAbsInt (Expr, 0); } - /* Do constant calculation if we can */ - if (ED_IsAbs (&Expr2) && - (ED_IsAbs (Expr) || lscale == 1)) { - if (IsClassInt (lhst) && IsClassInt (rhst)) { - Expr->Type = ArithmeticConvert (Expr->Type, Expr2.Type); + if (!AddDone) { + /* Do constant calculation if we can */ + if (ED_IsAbs (&Expr2) && + (ED_IsAbs (Expr) || lscale == 1)) { + if (IsClassInt (lhst) && IsClassInt (rhst)) { + Expr->Type = ArithmeticConvert (Expr->Type, Expr2.Type); + } + Expr->IVal = Expr->IVal * lscale + Expr2.IVal * rscale; + AddDone = 1; + } else if (ED_IsAbs (Expr) && + (ED_IsAbs (&Expr2) || rscale == 1)) { + if (IsClassInt (lhst) && IsClassInt (rhst)) { + Expr2.Type = ArithmeticConvert (Expr2.Type, Expr->Type); + } + Expr2.IVal = Expr->IVal * lscale + Expr2.IVal * rscale; + /* Adjust the flags */ + Expr2.Flags |= Expr->Flags & ~E_MASK_KEEP_SUBEXPR; + /* Get the symbol and the name */ + *Expr = Expr2; + AddDone = 1; } - Expr->IVal = Expr->IVal * lscale + Expr2.IVal * rscale; - AddDone = 1; - } else if (ED_IsAbs (Expr) && - (ED_IsAbs (&Expr2) || rscale == 1)) { - if (IsClassInt (lhst) && IsClassInt (rhst)) { - Expr2.Type = ArithmeticConvert (Expr2.Type, Expr->Type); - } - Expr2.IVal = Expr->IVal * lscale + Expr2.IVal * rscale; - /* Adjust the flags */ - Expr2.Flags |= Expr->Flags & ~E_MASK_KEEP_SUBEXPR; - /* Get the symbol and the name */ - *Expr = Expr2; - AddDone = 1; } if (AddDone) { From 2864b3ef8a1722b4eda017a74ac964136279f82a Mon Sep 17 00:00:00 2001 From: acqn Date: Tue, 30 Mar 2021 10:59:44 +0800 Subject: [PATCH 78/80] Fixed composition of prototypes and old-style function definitions with default promotions. Fixed function parameter list comparison with empty ones. --- src/cc65/typecmp.c | 65 +++++++-------------------------------------- src/cc65/typeconv.c | 52 +++++++++++++++++++++++------------- 2 files changed, 43 insertions(+), 74 deletions(-) diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index 567ab4e87..58f41d3ca 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -49,40 +49,6 @@ -static int ParamsHaveDefaultPromotions (const FuncDesc* F) -/* Check if any of the parameters of function F has a default promotion. In -** this case, the function is not compatible with an empty parameter name list -** declaration. -*/ -{ - /* Get the symbol table */ - const SymTable* Tab = F->SymTab; - - /* Get the first parameter in the list */ - const SymEntry* Sym = Tab->SymHead; - - /* Walk over all parameters */ - while (Sym && (Sym->Flags & SC_PARAM)) { - - /* If this is an integer type, check if the promoted type is equal - ** to the original type. If not, we have a default promotion. - */ - if (IsClassInt (Sym->Type)) { - if (IntPromotion (Sym->Type) != Sym->Type) { - return 1; - } - } - - /* Get the pointer to the next param */ - Sym = Sym->NextSym; - } - - /* No default promotions in the parameter list */ - return 0; -} - - - static int EqualFuncParams (const FuncDesc* F1, const FuncDesc* F2) /* Compare two function symbol tables regarding function parameters. Return 1 ** if they are equal and 0 otherwise. @@ -385,29 +351,16 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) F1 = GetFuncDesc (lhs); F2 = GetFuncDesc (rhs); - /* If one of both functions has an empty parameter list (which - ** does also mean, it is not a function definition, because the - ** flag is reset in this case), it is considered equal to any - ** other definition, provided that the other has no default - ** promotions in the parameter list. If none of both parameter - ** lists is empty, we have to check the parameter lists and - ** other attributes. + /* If one of both function declarations has an empty parameter + ** list (which does also mean, it is not a function definition, + ** because the flag is reset in this case), it is ignored for + ** parameter comparison and considered equal to the other one, + ** provided both have the same return type and other attributes. + ** If neither of both parameter lists is empty, we have to check + ** the parameter lists. */ - if (F1->Flags & FD_EMPTY) { - if ((F2->Flags & FD_EMPTY) == 0) { - if (ParamsHaveDefaultPromotions (F2)) { - /* Flags differ */ - SetResult (Result, TC_INCOMPATIBLE); - return; - } - } - } else if (F2->Flags & FD_EMPTY) { - if (ParamsHaveDefaultPromotions (F1)) { - /* Flags differ */ - SetResult (Result, TC_INCOMPATIBLE); - return; - } - } else { + if ((F1->Flags & FD_EMPTY) == 0 && + (F2->Flags & FD_EMPTY) == 0) { /* Check the remaining flags */ if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) { diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index 91a1f022d..8bdef8d03 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -352,18 +352,21 @@ void TypeCast (ExprDesc* Expr) -static void CompositeFuncParamList (const FuncDesc* F1, const FuncDesc* F2) -/* Composite two function symbol tables regarding function parameters */ +static void ComposeFuncParamList (const FuncDesc* F1, const FuncDesc* F2) +/* Compose two function symbol tables regarding function parameters into F1 */ { /* Get the symbol tables */ const SymTable* Tab1 = F1->SymTab; const SymTable* Tab2 = F2->SymTab; - /* Composite the parameter lists */ - const SymEntry* Sym1 = Tab1->SymHead; - const SymEntry* Sym2 = Tab2->SymHead; + /* Compose the parameter lists */ + SymEntry* Sym1 = Tab1->SymHead; + SymEntry* Sym2 = Tab2->SymHead; - /* Composite the fields */ + /* Sanity check */ + CHECK ((F1->Flags & FD_EMPTY) == 0 && (F2->Flags & FD_EMPTY) == 0); + + /* Compose the fields */ while (Sym1 && (Sym1->Flags & SC_PARAM) && Sym2 && (Sym2->Flags & SC_PARAM)) { /* Get the symbol types */ @@ -384,8 +387,19 @@ static void CompositeFuncParamList (const FuncDesc* F1, const FuncDesc* F2) } } + /* When we compose two function parameter lists with any FD_OLDSTYLE + ** flags set, we are either refining the declaration of the function + ** with its definition seen, or determining the result type of a + ** ternary operation. In either case, we can just replace the types + ** with the promoted ones since the original types of the parameters + ** only matters inside the function definition. + */ + if (Type1 != Sym1->Type) { + Sym1->Type = TypeDup (Type1); + } + /* Compose this field */ - TypeComposition (Type1, Type2); + TypeComposition (Sym1->Type, Type2); /* Get the pointers to the next fields */ Sym1 = Sym1->NextSym; @@ -404,7 +418,7 @@ void TypeComposition (Type* lhs, const Type* rhs) FuncDesc* F2; long LeftCount, RightCount; - /* Composite two types */ + /* Compose two types */ while (lhs->C != T_END) { /* Check if the end of the type string is reached */ @@ -417,17 +431,15 @@ void TypeComposition (Type* lhs, const Type* rhs) /* Check for special type elements */ if (IsTypeFunc (lhs)) { - /* Composite the function descriptors */ + /* Compose the function descriptors */ F1 = GetFuncDesc (lhs); F2 = GetFuncDesc (rhs); - /* If one of both functions has an empty parameter list (which - ** does also mean, it is not a function definition, because the - ** flag is reset in this case), it is replaced by the other - ** definition, provided that the other has no default - ** promotions in the parameter list. If none of both parameter - ** lists is empty, we have to composite the parameter lists and - ** other attributes. + /* If F1 has an empty parameter list (which does also mean, it is + ** not a function definition, because the flag is reset in this + ** case), its declaration is replaced by the other declaration. If + ** neither of the parameter lists is empty, we have to compose them + ** as well as other attributes. */ if ((F1->Flags & FD_EMPTY) == FD_EMPTY) { if ((F2->Flags & FD_EMPTY) == 0) { @@ -436,8 +448,12 @@ void TypeComposition (Type* lhs, const Type* rhs) F1->Flags = F2->Flags; } } else if ((F2->Flags & FD_EMPTY) == 0) { - /* Composite the parameter lists */ - CompositeFuncParamList (F1, F2); + /* Compose the parameter lists */ + ComposeFuncParamList (F1, F2); + /* Prefer non-old-style */ + if ((F2->Flags & FD_OLDSTYLE) == 0) { + F1->Flags &= ~FD_OLDSTYLE; + } } } else if (IsTypeArray (lhs)) { /* Check member count */ From 1a3628df1a6417156feefcbdf19dd24856d5e073 Mon Sep 17 00:00:00 2001 From: acqn Date: Tue, 30 Mar 2021 10:59:44 +0800 Subject: [PATCH 79/80] Fixed the term 'argument' vs 'parameter' in function parser. --- src/cc65/expr.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 58de0d891..9e08faeeb 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -651,11 +651,11 @@ void DoDeferred (unsigned Flags, ExprDesc* Expr) } -static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall, ExprDesc* ED) -/* Parse a function parameter list, and pass the arguments to the called -** function. Depending on several criteria, this may be done by just pushing -** into each parameter separately, or creating the parameter frame once, and -** then storing into this frame. +static unsigned FunctionArgList (FuncDesc* Func, int IsFastcall, ExprDesc* ED) +/* Parse the argument list of the called function and pass the arguments to it. +** Depending on several criteria, this may be done by just pushing into each +** parameter separately, or creating the parameter frame once and then storing +** arguments into this frame one by one. ** The function returns the size of the arguments pushed in bytes. */ { @@ -860,7 +860,7 @@ static void FunctionCall (ExprDesc* Expr) { FuncDesc* Func; /* Function descriptor */ int IsFuncPtr; /* Flag */ - unsigned ParamSize; /* Number of parameter bytes */ + unsigned ArgSize; /* Number of arguments bytes */ CodeMark Mark; int PtrOffs = 0; /* Offset of function pointer on stack */ int IsFastcall = 0; /* True if we are fast-calling the function */ @@ -932,8 +932,8 @@ static void FunctionCall (ExprDesc* Expr) IsFastcallFunc (Expr->Type); } - /* Parse the parameter list */ - ParamSize = FunctionParamList (Func, IsFastcall, Expr); + /* Parse the argument list and pass them to the called function */ + ArgSize = FunctionArgList (Func, IsFastcall, Expr); /* We need the closing paren here */ ConsumeRParen (); @@ -952,11 +952,11 @@ static void FunctionCall (ExprDesc* Expr) /* Not a fastcall function - we may use the primary */ if (PtrOnStack) { - /* If we have no parameters, the pointer is still in the + /* If we have no arguments, the pointer is still in the ** primary. Remove the code to push it and correct the ** stack pointer. */ - if (ParamSize == 0) { + if (ArgSize == 0) { RemoveCode (&Mark); PtrOnStack = 0; } else { @@ -969,7 +969,7 @@ static void FunctionCall (ExprDesc* Expr) } /* Call the function */ - g_callind (FuncTypeOf (Expr->Type+1), ParamSize, PtrOffs); + g_callind (FuncTypeOf (Expr->Type+1), ArgSize, PtrOffs); } else { @@ -978,7 +978,7 @@ static void FunctionCall (ExprDesc* Expr) ** Since fastcall functions may never be variadic, we can use the ** index register for this purpose. */ - g_callind (CF_STACK, ParamSize, PtrOffs); + g_callind (CF_STACK, ArgSize, PtrOffs); } /* If we have a pointer on stack, remove it */ @@ -1030,9 +1030,9 @@ static void FunctionCall (ExprDesc* Expr) SB_Done (&S); - g_call (FuncTypeOf (Expr->Type), Func->WrappedCall->Name, ParamSize); + g_call (FuncTypeOf (Expr->Type), Func->WrappedCall->Name, ArgSize); } else { - g_call (FuncTypeOf (Expr->Type), (const char*) Expr->Name, ParamSize); + g_call (FuncTypeOf (Expr->Type), (const char*) Expr->Name, ArgSize); } } From 5d05451ab2e5e4b9e52c99a5d6d04dfb5ac7ca7e Mon Sep 17 00:00:00 2001 From: acqn Date: Thu, 1 Apr 2021 11:41:55 +0800 Subject: [PATCH 80/80] Fixed test case for Issue #1263. --- test/{misc => val}/bug1263.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) rename test/{misc => val}/bug1263.c (59%) diff --git a/test/misc/bug1263.c b/test/val/bug1263.c similarity index 59% rename from test/misc/bug1263.c rename to test/val/bug1263.c index 4e5987c58..740b19250 100644 --- a/test/misc/bug1263.c +++ b/test/val/bug1263.c @@ -1,15 +1,22 @@ /* bug #1263 - erroneous error for K & R function declaration */ enum E { I = 0 }; -extern int f(enum E); +extern int f(); int f(e) enum E e; { return e; } +extern int g(int); +int g(e) + enum E e; +{ + return e; +} + int main(void) { - return f(I); + return f(I) + g(I); }