~sircmpwn/qbe

8f6c5b27bb5dca18fd4a93ee0185329010e5e8c6 — Drew DeVault a month ago d58852a
parsefields: fix padding calculation

This was causing issues with aggregate types. A simple reproduction is:

type :type.1 = align 8 { 24 }
type :type.2 = align 8 { w 1, :type.1 1 }

The size of type.2 should be 32, adding only 4 bytes of padding between
the first and second field. Prior to this patch, 20 bytes of padding was
added instead, causing the type to have a size of 48.

Signed-off-by: Drew DeVault <sir@cmpwn.com>
2 files changed, 23 insertions(+), 2 deletions(-)

M parse.c
A test/abi7.ssa
M parse.c => parse.c +2 -2
@@ 881,9 881,9 @@ parsefields(Field *fld, Typ *ty, int t)
		}
		if (a > al)
			al = a;
		a = sz & (s-1);
		a = (1 << a) - 1;
		a = ((sz + a) & ~a) - sz;
		if (a) {
			a = s - a;
			if (n < NField) {
				/* padding */
				fld[n].type = FPad;

A test/abi7.ssa => test/abi7.ssa +21 -0
@@ 0,0 1,21 @@
# test padding calculation with                                                                     
# embedded struct                                                                                   
                                                                                                    
type :s1 = align 4 { w 3 }                                                                          
type :s2 = align 4 { b 1, :s1 1 }                                                                   
                                                                                                    
export function :s2 $test() {                                                                       
@start                                                                                              
        ret $s                                                                                      
}                                                                                                   
                                                                                                    
# >>> driver                                                                                        
# struct s2 {                                                                                       
#       char x;                                                                                     
#       struct { int a[3]; } s1;                                                                    
# } s = { .x = 123 };                                                                               
# extern struct s2 test(void);                                                                      
# int main(void) {                                                                                  
#       return !(test().x == 123);                                                                  
# }                                                                                                 
# <<<