-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hello,
While trying to find out the famous gcc 4.x bug that makes it
incompatible with SE >= 2.3 at optimization levels > -O0, it appears
that some generated C code makes assumptions that are not true.
Let's take the C represnetation generated for STRING_RECYCLING_ITEM of
SE 2.3, and the associated comparator :
==>
struct S580{T2 _capacity;T0* _item_memory;};
typedef struct S580 T580;
int se_cmpT580(T580 o1,T580 o2){
return memcmp(&o1,&o2,sizeof(o1));}/*--*/
<==
As anybody can see, se_cmpT580 uses by-value arguments instead of
by-reference, and then makes clear assumption on T580 representation as
it considers two instances can be compared with memcmp.
On my x86/64 architecture, there is a 4-byte long padding between
_capacity and _item_memory. This wouldn't be a big deal if o1 and o2
where passed by-reference to se_cmpT580, but they're passed by-value. I
have inspected the asm generated by gcc (even latest 3.x version), and
T580 structures are managed field by field, not globally.
So that even though the padding bytes are set to 0 at creation time
(which is also not the case, regarding current implementation of default
constructor), by the game of splitting/gathering structures when they
are passed by-value, there is no guarantee that those padding bytes stay
the same all along the instance life-cycle.
I think anybody can reach the same conclusion by compiling compile_to_c
with -debug and -all_check options on x86/64 architecture.
Furthermore, the C reference in §6.2.6.1 sentence 6 says "the bytes of
the object representation that correspond to any padding padding bytes
take unspecified values". This can be interpreted as saying that gcc is
in its own right, and the issue is on the code-generation side.
According to me, there are two ways to fix this issue:
- Add __attribute__((packed)) after any declaration of a structure
definition corresponding to an Eiffel expanded class.
- Change comparator definition to no more use memcmp and do a
field-by-field comparision.
I've wrote a patch for the former way, even though I don't know if some
other parts of the generator makes assumptions on the struct
representations. To me, the best way to do is the latter one, but I
didn't have time at this time being to write such a patch.
I provide my patch for inspection, and why not, integration in the
official trunk?
Regards,
Guillaume
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
iEYEARECAAYFAkmDMHsACgkQGl8D2UjaRECRNgCghbXtFS3hQCR+9ngVLr15/CXz
Gg8AnRhTp4uiCszmgcVFj0lGpIi3zsC/
=44/t
-----END PGP SIGNATURE-----
diff -Naur SmartEiffel/tools/type_mark.e SmartEiffel_patch/tools/type_mark.e
--- SmartEiffel/tools/type_mark.e 2007-07-11 19:23:29.000000000 +0200
+++ SmartEiffel_patch/tools/type_mark.e 2009-01-26 21:57:54.000000000 +0100
@@ -1323,7 +1323,7 @@
i := i - 1
end
end
- cpp.out_h_buffer.append(once "};%N")
+ cpp.out_h_buffer.append(once "} __attribute__((packed));%N")
cpp.write_out_h_buffer
if is_expanded then
-- For expanded comparison: