Hi Dale, on my machine (x86-32, linux) LLVM considers long double to have a size of 10 bytes and an alignment of 4 bytes. GCC gives it a size of 12 bytes and an alignment of 4 bytes (of course only the first 80 bits (10 bytes) are actually used - the rest is padding).
I can see several problems with a 10 byte size. First, problems that aren't related to gcc. In an array of long double, the elements may not be aligned even if the array is aligned. This is because the usual invariant "the size is a multiple of the alignment" does not hold for size 10, alignment 4. I'm betting that the logic for working out alignments of loads and stores in LLVM is not expecting this! Since this type only exists on x86, which is pretty lenient about unaligned pointer access, I suppose this might not really matter. Isn't unaligned access slower than aligned access though? Anyway, it seems to me much better to avoid this can of worms and have the size be a multiple of the alignment. Second, problems related to gcc. We convert long double to X86_FP80Ty (which I've been referring to as long double). The result is that the size of the gcc type is not equal to the size of the LLVM type. This causes all kinds of problems with arrays and pointer arithmetic. That's the reason for the check that sizes are the same (which you turned off in this case, tut tut!). For example, suppose you declare an array of long doubles, cast to an i8* and start moving around in it based on sizeof(long double). Well you'll end up at the wrong place because sizeof is the gcc size (12) but LLVM will have placed the elements 10 bytes apart! This also has knock-on effects, like LLVM arrays of long doubles having different lengths to the corresponding gcc arrays etc. If you think about it I hope you will agree that it is important to convert gcc types to LLVM types of the same size. By the way, are there any standards that require size to be a multiple of alignment? The solution I would prefer is: make getTypeSize return 12 for long double, have getTypeSizeInBits return 80 (I think this should be renamed to getBitsUsedByType or something like that, see APInt comments below). Make it a requirement that getTypeSize always returns a multiple of the alignment. Document that getTypeSize is the offset between successive elements in arrays of this type, or between fields in a struct; and that loads and stores of this type can write up to this many bytes. Document that getBitsUsedByType returns the minimum number of bits needed to hold all values of this type, and that this can be less than 8*getTypeSize. Correct all places that assume that getBitsUsedByType is 8*getTypeSize (like the check that the gcc type has the same size as the llvm type, which should be using 8*getTypeSize). Note that this is exactly how it is already for APInt. Consider a type like i36. For this, getTypeSize returns 8, i.e. 64 bits, while getTypeSizeInBits returns 36. Thus getTypeSize corresponds to gcc's TYPE_SIZE while getTypeSizeInBits corresponds to TYPE_PRECISION. This seems like a good model to me. That said, other solutions are possible. For example, we could ignore the unaligned array element problem, and alter gcc so that TYPE_SIZE for long double becomes 80 bits. I have no idea what kind of problems this might cause, if any. Or we could convert long double to a struct { X86_FP80Ty, i16 }, and fix up all the floating point stuff in llvm-convert. Chris mentioned to me on IRC that this is a pessimisation in general, and would rather have X86_FP80Ty be used for scalar operations (so you can continue to use registers) but have { X86_FP80Ty, i16 } be used for loads and stores to memory. He also noted that this kind of thing would be also helpful for Darwin's funky 32 bit boolean type (which would be more optimally manipulated as in i1 in scalar expressions, but needs to be stored as 32 bits). Thus he suggested associating two LLVM types with each primitive gcc type: a type used for lvalues (i.e. memory access) and a type used for scalar operations (LLVM register operations). The lvalue type would always have the same size as the gcc type, while the scalar type could differ in size. What do you think? Best wishes, Duncan. _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits