News:

Download Pelles C here: http://www.pellesc.se

Main Menu

Recent posts

#71
Bug reports / Re: optimiser emits ud2 (inval...
Last post by KEL26 - September 02, 2026, 06:49:20 PM
Please reply with the information I request. Thank you, TimoVJL.

Your second program is a better test than my checksum,
because it can fail on the exact element that goes wrong, and I have adopted it.

Compiled exactly as you posted it, with no changes, on Pelles C 14.50.0 for x64:

pocc -Tx64-coff -std:C17 -Ze -Zx -W1 -Ot check.c
polink -subsystem:console -machine:x64 check.obj crt64.lib kernel32.lib -out:check.exe
check.exe

it prints

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
error: 44 != 0

The same with -Os and with -Ox. With no -O switch at all it prints all
two hundred values and no error line.

The object code for the store that your check reads back, at -Ot:

mov     dl,2C            ; 0x2C is 44, and 300 mod 256 is 44
mov     al,dil
xor     ah,ah
div     dl               ; the 8-bit divide
mov     al,ah            ; the remainder
mov     byte ptr [rsi],al
cmp     byte ptr [rsi],dil

44 mod 44 is 0, which is the 0 in the error line.

Your first program, the pointer checksum,
behaves the same way here: 4060 at -Ot, -Os and -Ox,
and 19900 with no optimisation.
So the pointer form does not avoid it on this machine,
and neither does the position of the array in the frame.

That leaves exactly one difference between us: the optimisation switch.
Would you run your own check with -Ot given explicitly on the command line, as above,
and say what it prints? If it prints the error line, we have the same result.
If it prints all two hundred values for you at -Ot,
then something differs between our installations that I would very much like to identify,
and the first line of

pocc /?

would help.

For anyone hitting this today, the form I would still suggest is

int t = i % 300;
*pdata = (unsigned char)t;  /* see my note below, just in case any one wants to write to me! */

which keeps the remainder in an int object, so the narrowing to unsigned char
is never part of the same expression and the rewrite has nothing to attach to.

N.B.
Why *pdata is right in TimoVJL's loop

TimoVJL's check walks the array with the pointer itself:
it stores through *pdata, compares, and then does pdata++ at the bottom of the loop.
Inside that loop the current element is *pdata, full stop.
My suggestion keeps his loop shape and changes only the two lines that matter — compute in int,
then narrow — so he can drop it straight into his own program.
I verified it: at -Ot it stores all two hundred elements correctly and the check never fires.


Using pdata[i] inside TimoVJL's loop would compile, but combined with his pdata++ it would
advance twice per iteration and write to the wrong places.
Using *pdata inside an indexed loop would write every value to element zero.
Each form is right in its own loop; *pdata[i] is right in neither.

#73
Bug reports / Re: optimiser emits ud2 (inval...
Last post by John Z - September 02, 2026, 09:58:19 AM
Hi KEL26,

Wow what can I say? Thank you!
Exemplary, superb, an excellent piece of work.
Thanks for your work and help and I appreciate the
time you spent doing the extra extensive documentation.

John Z

#74
Beginner questions / Re: Working Directory woes
Last post by MrBcx - September 02, 2026, 01:37:50 AM
Quote from: John Z on September 01, 2026, 09:24:22 PMDon't delete a good example for others to see to not give up.


That's good advice. 

If you're not making mistakes then you're not learning anything.

... and ...

You gotta break a few eggs, if you wanna make an omelet!


#75
Bug reports / Re: optimiser emits ud2 (inval...
Last post by KEL26 - September 02, 2026, 12:57:34 AM

The defect, stated exactly,

At -Os, -Ot and -Ox, Pelles C 14.50 for Windows x64 can replace the
constant divisor K of an integer remainder by K modulo 256.

I attach a zipped folder (edited) showing how to build a bug/defect free zlib (no source patch is required) and folder of code which shows evidence for this bug and my bug tracing code!

Hope it helps others - and hope soon this excellent IDE and compiler become open source - it would make the process of bug tracking and fixing super-fast - I am from a Linux background.

#76
Beginner questions / Re: Working Directory woes
Last post by John Z - September 01, 2026, 09:24:22 PM
Congratulations PhilG57!,

You stuck it out and figured it out!  That is what counts, and is learning.
Don't delete a good example for others to see to not give up.

Cheers,
John Z
#77
Bug reports / Re: optimiser emits ud2 (inval...
Last post by John Z - September 01, 2026, 09:21:51 PM
Hi KEL26,

QuoteMore than happy to share my code John Z  , I need to know how to do that - anyone guide me or direct me to instructions please?

Thanks very much!

Pelles makes it fairly easy.  Under Projects Menu there is a ZIP File menu selection.  This will ZIP the entire currently open project (zlib) into one file which then can be posted as an attachment, at the bottom of a post.  Up to four attachments can be made on one posting.

If the file is too large delete the object directory from the zip file.

This is also a convenient method to archive and store inactive projects or to keep back-up versions.  Unzip with standard tools and the project continues from where it was.  Also no need to unzip into the same path/structure.

Appreciate the help!

John Z
#78
Bug reports / Re: optimiser emits ud2 (inval...
Last post by KEL26 - September 01, 2026, 09:01:45 PM
Thank you TimoVJL for looking at this again.

I have built your version and I am afraid I cannot reproduce your result. On
Pelles C 14.50.0 it prints 4060, not 19900, and the object code shows why.

pocc -Tx64-coff -std:C17 -Ze -Zx -Ot -W1 timo.c
checksum 4060 (correct 19900)

Unoptimised, the same file prints 19900.


WHAT THE OBJECT CODE SHOWS
--------------------------
podump /DISASM on the -Ot object, x64:

mov     r8b,2C          ; 0x2C is 44
mov     al,dl
xor     ah,ah
div     r8b             ; 8-bit unsigned divide
mov     al,ah           ; take the remainder
mov     byte ptr [rcx],al

and the same file built for x86:

mov     cl,2C           ; 0x2C is 44 here too
mov     al,bl
xor     ah,ah
div     cl
mov     al,ah
mov     byte ptr [esi],al

The source says % 300. The emitted code divides by 44. 300 modulo 256 is 44,
and the divide is the 8-bit form. So the pointer store does not avoid the
rewrite: it is present on both targets and in both spellings.

I also built the array-subscript version with the identical declaration order,
and a pointer version with the array declared first. All three give 4060. So
neither the store form nor the position of the array in the frame changes
anything, and I do not think the stack placement is involved.


WHY I THINK YOUR RUN PRINTED 19900
----------------------------------
Your post mentions that it also gives 19900 with

sum += (*data)++;

That line does not read the array. It reads data[0] two hundred times, adding
the old value and incrementing it each time. Starting from data[0] == 0 it
sums 0+1+2+...+199, which is exactly 19900, whatever the other 199 bytes
contain.

I checked this rather than assuming it. Filling the array with 0xFF on
purpose, setting only data[0] to zero, and then running that loop:

for (i = 0; i < 200; i++) data[i] = 0xFF;   /* deliberately wrong */
data[0] = 0;
for (i = 0; i < 200; i++) sum += (*data)++;
checksum 19900

19900 from an array that is wrong in every byte. So that particular check
cannot distinguish a good build from a bad one, and I suspect it is where the
19900 came from.

If you ran the *pdata++ version with sum += *pdata++ and still saw 19900,
then something in your settings differs from mine in a way I would very much
like to know about, because it would bound the fault further. Would you say
which target and which optimisation setting you used?


WHERE THIS LEAVES THE WORKAROUND
--------------------------------
For anyone hitting this today, the form I would suggest is still

int t = i % 300;
data[i] = (unsigned char)t;

not because it dodges the trigger, but because the remainder is computed in
int and stored in an int object, so the narrowing-to-unsigned-char condition
is never met at all. It is correct at every optimisation level I have tested,
and it stays correct for a reason that does not depend on which shapes this
release happens to recognise.

I would avoid % 256u for the same reason in reverse: it works, but only
because the rewrite does not reach the unsigned-literal path in 14.50, and
that is a property of the release rather than of the language.

Thanks again for minimising the original case. That edit is what moved the
fault to compile time and gave us the #2803 message to work backwards from.
===========================================================================
#79
Bug reports / Re: optimiser emits ud2 (inval...
Last post by TimoVJL - September 01, 2026, 07:42:46 PM
int __cdecl printf(const char * restrict format, ...);
int __cdecl main(void)
{
    int i;
    unsigned long sum = 0;
    unsigned char *pdata;    // pointer to data
    unsigned char data[200];    // safer stack place at end ?

    pdata = data;
    for (i = 0; i < 200; i++)
        *pdata++ = (unsigned char)(i % 300);

    pdata = data;
    for (i = 0; i < 200; i++)
        sum += *pdata++;
        //sum += (*data)++;

    printf("checksum %lu (correct 19900)\n", sum);
    return 0;
}
also with
sum += (*data)++;output
checksum 19900 (correct 19900)
EDIT: a simple checkint __cdecl printf(const char * restrict format, ...);
int __cdecl main(void)
{
unsigned char *pdata; // pointer to data
int i;
unsigned char data[200];

pdata = data;
for (i = 0; i < 200; i++)
{
*pdata = (unsigned char)(i % 300);
if (*pdata != i)
{
printf("\nerror: %u != %u\n", i, *pdata);
break;
}
printf("%u ", *pdata);
pdata++;
}
return 0;
}

#80
Bug reports / Re: optimiser emits ud2 (inval...
Last post by KEL26 - September 01, 2026, 05:54:17 PM
Thank you Vortex, but the [ i ] is still there — the forum ate it.   [ i ] is the BBCode italics tag, so outside a code block 'data [ i ] =' ... renders as 'data = ' .... My source is correct. Reposting inside code tags:

        data[i] = (unsigned char)(i % 300);

Apologies — I should have wrapped the whole report in code tags. Anywhere else in the post that reads 'data = '  should read ' data [ i ] = '

The rest of the thread: every line with data [ i ] outside a code block will have been mangled the same way.


More than happy to share my code John Z  , I need to know how to do that - anyone guide me or direct me to instructions please?