[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Tinycc-devel] Mysterious tcc behavior: why does 0.0 takes 12 bytes when
From: |
David A. Wheeler |
Subject: |
[Tinycc-devel] Mysterious tcc behavior: why does 0.0 takes 12 bytes when NOT long double? |
Date: |
Thu, 26 May 2005 00:11:41 -0400 |
User-agent: |
Mozilla Thunderbird 1.0.2-1.3.2 (X11/20050324) |
Here's an odd thing - I've noticed that tcc 0.9.22,
when compiling itself, writes _12_ bytes, not _8_,
for the "0.0" in its source code (the last 4 bytes look
like garbage). It does NOT do this
with a simple test case that just has 0.0 in it.
Why is this? Is this a symptom of something more serious?
Frankly, this looks like a bug of some kind.
Below are test cases so you can reproduce this strange behavior;
it looks like something isn't getting completely initialized/copied.
Thoughts?
--- David A. Wheeler
TEST 1:
First, here's a trivial program you can compile with tcc 0.9.22:
main() {
printf("First");
double a = 0.0;
printf("Second");
}
If you "od -c" its results, at location 0001644 you see "First",
a \0 after First, another \0 padding to align the value,
eight 0x00 bytes for the double, and then string "Second"
results. So here tcc saves 0.0 as an 8-byte double, which is
what I expected.
TEST 2:
Modify tcc as follows so you can this weirdness more directly:
--- tcc-0.9.22-float2/tcc.c 2004-11-08 15:47:16.000000000 -0500
+++ tcc-0.9.22-float/tcc.c 2005-05-25 22:52:56.000000000 -0400
@@ -3261,13 +3261,16 @@
ch = *p++;
tok = TOK_CFLOAT;
tokc.f = strtof(token_buf, NULL);
+ printf("\nDEBUG: type of %s is FLOAT\n", token_buf);
} else if (t == 'L') {
ch = *p++;
tok = TOK_CLDOUBLE;
tokc.ld = strtold(token_buf, NULL);
+ printf("\nDEBUG: type of %s is LONG DOUBLE\n", token_buf);
} else {
tok = TOK_CDOUBLE;
tokc.d = strtod(token_buf, NULL);
+ printf("\nDEBUG: type of %s is DOUBLE\n", token_buf);
}
}
} else {
@@ -4652,10 +4655,13 @@
offset = (data_section->data_offset + align - 1) & -align;
data_section->data_offset = offset;
/* XXX: not portable yet */
+ printf("DEBUG: Constant float in gv(), size=%d, offset=%lx,
type=0x%x\n", size, offset,vtop->type.t);
ptr = section_ptr_add(data_section, size);
size = size >> 2;
- for(i=0;i<size;i++)
+ for(i=0;i<size;i++) {
ptr[i] = vtop->c.tab[i];
+ printf("DEBUG: wrote ptr[%d]=0x%x\n", i, ptr[i]);
+ }
sym = get_sym_ref(&vtop->type, data_section, offset, size
<< 2);
vtop->r |= VT_LVAL | VT_SYM;
vtop->sym = sym;
Compile this with gcc, and then have the resulting
tcc compile itself; the first output
(a double writes two 4-byte words) makes sense, but the second
(a 0.0 double is written as three, not two, 4-byte words)
makes NO sense. Here's the output:
DEBUG: type of 4294967296.0 is DOUBLE
DEBUG: Constant float in gv(), size=8, offset=1774, type=0x9
DEBUG: wrote ptr[0]=0x0
DEBUG: wrote ptr[1]=0x41f00000
DEBUG: type of 0.0 is DOUBLE
DEBUG: Constant float in gv(), size=12, offset=18e4, type=0xa
DEBUG: wrote ptr[0]=0x0
DEBUG: wrote ptr[1]=0x0
DEBUG: wrote ptr[2]=0xc90000
It's not that the value "0.0" is the kicker by itself;
compiling my trivial program above produces the expected results:
DEBUG: type of 0.0 is DOUBLE
DEBUG: Constant float in gv(), size=8, offset=c, type=0x9
DEBUG: wrote ptr[0]=0x0
DEBUG: wrote ptr[1]=0x0
Any ideas?