commit 0c76db4d8cfe5fda1ff9ebee84e7eb6cf634e194
parent bf64567e2fb0e616a17ece781e92f1a099607145
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 5 Jul 2023 13:10:15 -0400
comp/c: struct sizes are always aligned to 4b
This prevents unaligned access in struct arrays.
Diffstat:
6 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/fs/comp/c/fgen.fs b/fs/comp/c/fgen.fs
@@ -143,7 +143,7 @@ MAXSWITCHCASES << Stack :new structbind Stack _cases
\ array is a Stack
: _copyArray ( array cdecl -- )
- dup CDecl :elemsize >r >r \ V1=sz V2=cdecl
+ dup CDecl :typesize >r >r \ V1=sz V2=cdecl
dup Stack :count V1 * tuck ( arraysz stack arraysz )
_litarena :[ V1 writeStack _litarena :] ( arraysz a )
litn r> dup, CDecl :halop @, litn compile move rdrop ;
diff --git a/fs/comp/c/gen.fs b/fs/comp/c/gen.fs
@@ -25,7 +25,7 @@ require /sys/scratch.fs
'=' readChar? if ( cdecl )
nextt parseExpression case ( cdecl )
ExprOp :isconst? of r@ ExprOp arg , endof
- ExprOp :isarray? of r@ ExprOp arg over CDecl :elemsize writeStack endof
+ ExprOp :isarray? of r@ ExprOp arg over CDecl :typesize writeStack endof
_err endcase
else to nexttputback dup CDecl :size allot then ( cdecl )
',' readChar? if
diff --git a/fs/comp/c/type.fs b/fs/comp/c/type.fs
@@ -103,13 +103,10 @@ struct[ CDecl
\ Combined size of all fields in the LL.
: :size ( self -- size )
dup :isarg? over :funcsig? or if drop CELLSZ exit then
- 0 swap begin ( res cdecl ) ?dup while
+ r! 0 swap begin ( res cdecl ) ?dup while \ V1=self
tuck dup :typesize ( cdecl res cdecl n )
- swap nbelem 1 max * + swap llnext repeat ( res ) ;
-
- \ When the CDecl is an array, return the size of a single element.
- : :elemsize ( self -- size )
- dup nbelem _assert :typesize ;
+ swap nbelem 1 max * + swap llnext repeat ( res )
+ r> :struct? if align4 then ;
: :argssize ( self -- size ) dup :funcsig? _assert args llcnt CELLSZ * ;
diff --git a/fs/emul/uxn/vm.c b/fs/emul/uxn/vm.c
@@ -17,10 +17,6 @@ typedef void (*VMOP) ();
static uchar ram[$10000];
static Stack wst, rst, *src, *dst;
-// TODO: This is probably broken on ARM. Device's total size is uneven. The
-// fields are aligned, so access to dev[0] is fine, but access to dev[1] will be
-// unaligned. Struct size need to be aligned to 4b, but this will need careful
-// adjustments to CDecl.
static Device dev[$10];
static ushort pc; // Program Counter
static int bs; // byte/short 0=byte 1=short
diff --git a/fs/tests/comp/c/cc.fs b/fs/tests/comp/c/cc.fs
@@ -123,7 +123,7 @@ to' myval ptrari4 #
42 unaryop1 42 #eq
to' myval unaryop2 to' myval #eq
myval 42 #eq
-ptrari5 6 + @ 42 #eq
+ptrari5 8 + @ 42 #eq
123 456 ptrari6 123 456 + #eq
$1234 2 ptrari7 $1238 #eq
ptrari8 @ 42 #eq \ struct that was changed in ptrari5()
diff --git a/fs/tests/comp/c/type.fs b/fs/tests/comp/c/type.fs
@@ -18,7 +18,7 @@ _parse short STOP TYPE_SHORT #eq
_parse void STOP TYPE_VOID #eq
_parse
struct Struct1 { unsigned int foo; short *bar; char baz[2]; } STOP
-( type ) dup typesize 10 #eq
+( type ) dup typesize 12 #eq \ struct sizes are aligned to 4b
S" bar" over CDecl :find
dup CDecl type TYPE_SHORT #eq
dup CDecl lvl 1 #eq