I have come across a case where certain 64-bit long long (or int64_t) static constant values are not being written in to the CONST code segment with the correct value.
I'm not sure what it is about the specific values in question. I only came across this at random. The only hypothesis I can make is that they are distinguished by being very large negative decimal values, so perhaps there is a bug in the parsing of values below a certain negative range?
Target architecture does not seem to be a factor. I tried compiling with -mstm8, -mz80, and -mmcs51, and all had the same result.
Reproducable with both version 4.0.0 #11528 on Windows and 4.0.3 #11773 on Linux (self-built from SVN).
Test program:
/* Compiled with: sdcc -mstm8 --nostdlib -S main.c */
void main(void) {
static const struct {
long long a;
long long b;
long long c;
} foo[] = {
{ 1000000LL, 5LL, 5000000LL },
{ 9LL, -9LL, -81LL },
{ 76348LL, 243816LL, 18614863968LL },
{ 9223372036854775807LL, 1LL, 9223372036854775807LL },
{ 463874348LL, 0LL, 0LL },
{ -73943416394LL, 1387545LL, -102599817700412730LL },
/* Constants below not being written into CONST segment correctly! */
/* Should be: FFFF FFC6 9C5B C0BB, FFFF FFFD B082 AC19, 9920 A45A 5969 7643 */
{ -246484844357LL -9923548135LL -7412744278697740733LL },
};
}
Excerpt from the output .asm file, showing the incorrect data for the last three values:
.byte #0x00, #0x00, #0x00, #0x00, #0x00, #0x0f, #0x42, #0x40
.byte #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x05
.byte #0x00, #0x00, #0x00, #0x00, #0x00, #0x4c, #0x4b, #0x40
.byte #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x09
.byte #0xff, #0xff, #0xff, #0xff, #0xff, #0xff, #0xff, #0xf7
.byte #0xff, #0xff, #0xff, #0xff, #0xff, #0xff, #0xff, #0xaf
.byte #0x00, #0x00, #0x00, #0x00, #0x00, #0x01, #0x2a, #0x3c
.byte #0x00, #0x00, #0x00, #0x00, #0x00, #0x03, #0xb8, #0x68
.byte #0x00, #0x00, #0x00, #0x04, #0x55, #0x88, #0x48, #0x60
.byte #0x7f, #0xff, #0xff, #0xff, #0xff, #0xff, #0xff, #0xff
.byte #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x01
.byte #0x7f, #0xff, #0xff, #0xff, #0xff, #0xff, #0xff, #0xff
.byte #0x00, #0x00, #0x00, #0x00, #0x1b, #0xa6, #0x29, #0x2c
.byte #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x00
.byte #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x00
.byte #0xff, #0xff, #0xff, #0xee, #0xc8, #0xa1, #0x01, #0xb6
.byte #0x00, #0x00, #0x00, #0x00, #0x00, #0x15, #0x2c, #0x19
.byte #0xfe, #0x93, #0x7e, #0x02, #0x67, #0xf2, #0x72, #0xc6
.byte #0x99, #0x20, #0xa4, #0x1e, #0xa6, #0x47, #0xe3, #0x17 ; <---
.byte #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x00 ; <--- WRONG!
.byte #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x00, #0x00 ; <---
Back before long long support was added to SDCC, some parts of SDCC assumed that any value can be represented exactly in a double on the host (and sometimes did so).
I suspect that there still is some corner case, where SDCC behaves this way.
Last edit: Philipp Klaus Krause 2020-08-14
There is no bug here. The generated code is correct:
The initializer initializes foo[6].a to -246484844357LL -9923548135LL -7412744278697740733LL as it should. There are no explicit initalialization values for foo[6].b and foo[6].c, so they get default-initialized to 0, as they should.
Last edit: Maarten Brock 2020-08-17
Dammit, how the @#%& did I not notice the lack of comma separators in the initialiser!
I suppose I was fooled by the three numbers being a valid expression when the negations are interpreted as subtraction operators. The value that did go into foo[6].a was the result of that expression, which I didn't notice either.
Is there some way SDCC could emit a warning about "lack of comma separators in the initialiser" in situations like this?
(Something like the way the compiler should warn me about an "assignment inside condition statement" in "The World's Last Bug":
).
I don't think so:
Getting such a warning right would be very hard. I don't think it would be worth the effort, given that there are a lot of much more important issues in SDCC that need fixing or improving.