davidgiven / ack

The Amsterdam Compiler Kit
http://tack.sf.net
Other
420 stars 59 forks source link

Alignment is completely putzed #199

Open davidgiven opened 5 years ago

davidgiven commented 5 years ago

There's something very wrong with the way alignment is handled in the led vs the section alignment emitted by ass, which is manifesting in persistent output section alignment errors in the i80 platform which I haven't been able to track down. This is manifesting as B crashes on i80. It's probably also going to affect i86, but I haven't been able to provoke it there either (which is weird).

The EM alignment restrictions are odd, but what I've figured out so far is:

I think what we need to do is to define how this is supposed to work, and then make sure it actually works this way (with tests). I would like to avoid requiring word alignment completely. This will mean not supporting B for architectures which don't support alignment, but I'm fine with that.

What I'd like here is:

Apart from anything else, this ought to remove padding bytes on i80, leading to smaller CP/M binaries.

kernigh commented 5 years ago

Given this example input,

 mes 2, 2, 2
thing
 rom 11I1, 22I1, 33I1, 4444I2

the output of ack -mcpm -c.s example.e is

.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .rom
.align 2
_thing:
.data2  5643
.data2  33
.data2  4444
.sect .text

Here 5643 is 11 + (22 << 8), which is the bytes 11 and 22 in little-endian order. There is an extra 0 byte after the 33, so the 4444 is word-aligned. A compiler that wanted to load the 4444 would need to load it from thing + 4.

One might edit mach/i80/ncg/mach.c con_part(), so it emits .data1 pseudos and doesn't insert the extra 0 byte. Then the 4444 would move to thing + 3, but if the compiler still loaded it from thing + 4, it would be wrong. The compiler would need to know how each machine aligns data, so the compiler can decide whether to use thing + 3 or thing + 4 in the code. This might require changing all the compilers, or providing a backward-compatible alignment for old compilers.

As EM is now, there is no way to put 4444I2 without 2-byte alignment. (One can split 4444 into bytes, like 99I1, 17I1, but only if one knows the byte order of the machine, and the constant doesn't reference a label.) There is also no way to get more than word alignment; an 8-byte float can't have 8-byte alignment. (The C compiler might provide 8-byte alignment within a struct, but the whole struct might be misaligned.)