commit 808d2da630e13ff60b4eee260d601eb50789844f
parent 710a8632f153d002f4e04d4e75135f0b784f456d
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Fri, 17 Jun 2022 13:30:08 -0400
cc: allow array declaration and allocate them properly in the SF
Diffstat:
4 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/fs/cc/ast.fs b/fs/cc/ast.fs
@@ -1,5 +1,5 @@
\ C compiler Abstract Syntax Tree
-\ requires cc/tok.fs, cc/tree.fs and cc/ops.fs
+\ requires cc/tok cc/tree cc/type
\ An abstract syntax tree, AST, is a hierarchical structure of nodes
\ representing the nodes found in a C source file. See tree.fs for structure.
@@ -35,7 +35,7 @@ create bopsprectbl 1 c, 1 c, 0 c, 0 c, 2 c, 2 c, 2 c, 2 c,
\ AST node types
15 const ASTIDCNT
-0 const AST_DECLARE \ data1=name data2=type
+0 const AST_DECLARE \ data1=name data2=type data3=nbelem
1 const AST_UNIT
2 const AST_FUNCTION \ data1=name data2=MAP_FUNCTION data3=type
3 const AST_RETURN
@@ -68,7 +68,8 @@ ASTIDCNT stringlist astidnames
ASTIDCNT wordtbl astdatatbl ( node -- node )
:w ( Declare ) _[
dup data2 printtype spc>
- dup data1 stype _] ;
+ dup data1 stype
+ dup data3 dup 1 > if _[ .x _] else drop then _] ;
'w noop ( Unit )
:w ( function ) _[
dup data3 printtype spc>
@@ -186,13 +187,17 @@ alias noop parseExpression ( tok -- node ) \ forward declaration
current to parseExpression
: parseDeclare ( type parentnode -- dnode )
+ AST_DECLARE newnode ( type dnode )
swap begin ( pnode type )
nextt dup S" *" s= if drop type*lvl+ 0 else 1 then until ( pnode type tok )
- expectIdent rot ( type name pnode )
- AST_DECLARE newnode ( type name dnode ) rot> , , ( dnode ) ;
+ expectIdent ( dnode type name ) , , ( dnode )
+ nextt dup S" [" s= if ( dnode tok )
+ drop nextt parse _assert nextt ']' expectChar ( nbelem ) else
+ to nexttputback 1 ( nbelem ) then , ;
: parseDeclarationList ( type stmtsnode -- )
- parseDeclare nextt '=' expectChar dup data1 ( dnode name )
+ parseDeclare nextt dup S" =" s= not if ';' expectChar drop exit then
+ drop ( dnode ) dup data1 ( dnode name )
swap parentnode AST_BINARYOP newnode ( name anode ) 12 ( = ) ,
AST_LVALUE newnode ( name lvnode ) swap , parentnode ( anode )
nextt parseExpression read; ( anode expr ) swap addnode ;
diff --git a/fs/cc/map.fs b/fs/cc/map.fs
@@ -16,19 +16,20 @@
\ Then, each entry in the variable declaration xdict is:
\ 4b SF offset
+\ 4b link to AST_DECLARE node
newxdict curmap
: fmap.astnode @ ;
: fmap.sfsize 4 + @ ;
\ Return fmap Stack Frame size and then increase it by 4.
-: fmap.sfsize+ ( fmap -- sfoff )
- dup fmap.sfsize swap 4 + ( sz a ) 4 swap +! ( sz ) ;
+: fmap.sfsize+ ( n fmap -- ) 4 + +! ;
: fmap.argsize 8 + @ ;
: fmap.argsize+ ( n fmap -- ) 8 + +! ;
: fmap.address 12 + @ ;
: fmap.address! 12 + ! ;
: fmap.vmap 16 + ;
: vmap.sfoff @ ;
+: vmap.decl 4 + @ ;
: _err ( -- ) abort" mapping error" ;
\ print curmap in reverse order of parsing
@@ -45,7 +46,11 @@ newxdict curmap
dup data1 ( name ) curmap xentry ( astnode )
here swap , 16 allot0 ( entry ) ;
-: Variable ( offset name -- ) curmap @ fmap.vmap xentry , ;
+: Variable ( dnode -- )
+ dup data1 curmap @ fmap.vmap xentry ( dnode )
+ curmap @ fmap.sfsize , dup , ( dnode )
+ dup data2 ( dnode type ) typesize swap data3 ( nbelem ) * ( sfsize )
+ curmap @ fmap.sfsize+ ;
: findvarinmap ( name funcentry -- varentry )
fmap.vmap xfind not if _err then ;
@@ -57,7 +62,7 @@ newxdict curmap
AST_DECLARE nextnodeid dup if ( astdecl )
dup parentnode nodeid AST_ARGSPECS = if \ inc argssize field
4 curmap @ fmap.argsize+ then
- dup data1 curmap @ fmap.sfsize+ swap Variable 0 else 1 then
+ dup Variable 0 else 1 then
until ( curnode ) drop ;
\ create a new map from "astunit"
diff --git a/fs/cc/type.fs b/fs/cc/type.fs
@@ -8,12 +8,13 @@
\ b6:4 = *lvl. Indirection levels, from 0 to 7.
4 stringlist typenames "void" "char" "short" "int"
-create _ 0 c, 8 c, 16 c, 32 c,
: typesigned? ( type -- flags ) 2 rshift 1 and ;
: type*lvl ( type -- lvl ) 3 rshift 3 and ;
: type*lvl! ( lvl type -- type ) $f and swap 3 lshift or ;
: type*lvl+ ( type -- type ) dup type*lvl 1+ swap type*lvl! ;
-: typesize ( type -- size-in-bytes ) dup type*lvl if 4 else 3 and _ + c@ then ;
+create _ 0 c, 1 c, 2 c, 4 c,
+: typesize ( type -- size-in-bytes )
+ dup type*lvl if drop 4 else 3 and _ + c@ then ;
\ Unlike ANSI C, "signed" doesn't exist and "unsigned" needs to be before the
\ type name. '*' are not parsed because they are sometimes attached to the
diff --git a/fs/tests/cc/test.c b/fs/tests/cc/test.c
@@ -59,3 +59,8 @@ int exprparens() {
return (1 + 2) * 3;
}
void cnoop() {return;}
+int array() {
+ int a[3];
+ *a = 42;
+ return *a;
+}