duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit d5f09b142346dbaa28e4614dfef045719acdd3f3
parent 784096f1a54f903890fec5c8ae73278e33664fdc
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Tue,  4 Oct 2022 10:14:49 -0400

cc: add function signature type

Diffstat:
Mfs/app/cos/cvm.c | 1-
Mfs/cc/ast.fs | 4++--
Mfs/cc/gen.fs | 3++-
Mfs/cc/type.fs | 29+++++++++++++++++++++++------
Mfs/cc/vm/commonlo.fs | 14++++++--------
Mfs/cc/vm/forth.fs | 2+-
Mfs/cc/vm/i386.fs | 2+-
Mfs/tests/cc/cc.fs | 1+
Mfs/tests/cc/test.c | 10++++++++++
Mfs/tests/cc/type.fs | 2+-
10 files changed, 47 insertions(+), 21 deletions(-)

diff --git a/fs/app/cos/cvm.c b/fs/app/cos/cvm.c @@ -1,5 +1,4 @@ // This doesn't compile. It's a prototype of what it will look like. -// TODO: function pointer arrays (iord iowr). // TODO: %s %x (4b hex) %w (2b hex) %b (1b hex) formatting // TODO: NULL // TODO: typecasting studs (we don't have a checker yet, but support the syntax) diff --git a/fs/cc/ast.fs b/fs/cc/ast.fs @@ -508,8 +508,8 @@ current to parseStatement 0 to curstatic dup S" static" s= if drop nextt 1 to curstatic then dup S" typedef" s= if - drop nextt parseType _assert - nextt expectIdent read; addTypedef drop exit then + drop nextt parseType _assert parseVariable ( ctype ) + read; addTypedef drop exit then parseType _assert ( unode type ) nextt dup ';' isChar? if \ Only a type on a line is fine, carry on 2drop drop exit then diff --git a/fs/cc/gen.fs b/fs/cc/gen.fs @@ -213,7 +213,8 @@ ASTIDCNT wordtbl gentbl ( node -- ) 0 to lastidentfound dup Node firstchild gennode \ op has call address lastidentfound ?dup if - dup Node id AST_FUNCTION = if Function :rettype else drop TYPE_VOID then + dup Node id AST_FUNCTION = if Function :rettype + else Declare ctype CType type dup CType :funcsig? _assert CType type then else vmop loc VM_*CONSTANT = if vmop arg wordfunctype else TYPE_VOID then then ( node type ) vmop :push rot ( type 'copy node ) diff --git a/fs/cc/type.fs b/fs/cc/type.fs @@ -67,6 +67,8 @@ struct[ CType sfield type \ a basic type. Can be a link to a CType sfield flags \ b0=is a struct? if 1, this is an "empty" ctype with the name \ of the struct. First field is nexttype. + \ b1=is a funcsig? if 1, type is func return type and name is + \ the name of the sig. arguments follow in nexttype. sfield offset \ offset, in bytes, of this element within its list sfield nbelem \ number of elements in array. 0 if not an array. sfield storage \ one of the STORAGE_* consts @@ -76,6 +78,7 @@ struct[ CType 0 align4 here rot> 0 , , 0 , 0 , 0 , STORAGE_SF , s, ; : :struct? flags 1 and ; + : :funcsig? flags 2 and ; : :isarg? ( dnode -- f ) storage STORAGE_PS = ; : :isglobal? ( dnode -- f ) storage STORAGE_MEM = ; @@ -95,21 +98,24 @@ struct[ CType : _ 2dup name s= if nip else llnext ?dup if _ else _err then then ; : :find ( name self -- ctype ) llnext _ ; + : _( case of :struct? ." {" endof + of :funcsig? ." (" endof + r@ nexttype if ." , " then endcase ; + : _) case of :struct? ." }" endof of :funcsig? ." )" endof endcase ; : :. ( self -- ) >r r@ offset if '+' emit r@ offset .x? spc> then r@ :struct? if ." struct" else r@ type _printtype then r@ name c@ if spc> r@ name stype then r@ nbelem if '[' emit r@ nbelem . ']' emit then - r@ :struct? if ." { " r@ nexttype ?dup if :. then ." }" - else r@ nexttype ?dup if ." , " :. then - then rdrop ; + r@ _( r@ nexttype ?dup if :. then r@ _) rdrop ; ]struct \ Typedefs are dictionary entries in the "typedefs" dict, which contains a 4b \ value representing the type it aliases. create typedefs 0 , 0 c, \ this is a dict link -: addTypedef ( type name -- ) typedefs swap entry , ; +: addTypedef ( ctype -- ) typedefs over CType name entry + dup CType flags not if CType type then , ; : findTypedef ( name -- type-or-0 ) typedefs find dup if @ then ; : cctypes$ 0 typedefs ! ; @@ -138,10 +144,20 @@ current to _typesize : parseType* ( type -- type tok ) begin nextt dup '*' isChar? while drop type*lvl+ repeat ; +: parseFuncSig ( type -- ctype ) + nextt '*' expectChar nextt expectIdent ( type name ) + swap CType :new ( ctype ) + 2 over to CType flags ( ctype ) + nextt ')' expectChar nextt '(' expectChar begin ( ctype ) + \ TODO: don't ignore funcsig arguments + nextt dup ')' isChar? not while ( ctype tok ) drop + repeat ( ctype tok ) drop ; + \ Given a "type" part that is already parsed from parseType, parse the rest of \ a variable declaration, that is, the indirections (*), the name and nbelem \ ([]). This always returns a CType. : parseVariable ( type -- ctype ) + nextt dup '(' isChar? if drop parseFuncSig exit else to nexttputback then parseType* expectIdent swap CType :new ( ctype ) nextt dup S" [" s= if ( ctype tok ) drop nextt parse _assert nextt ']' expectChar ( ctype nbelem ) @@ -155,8 +171,9 @@ current to _typesize dup S" struct" s= if drop nextt dup isIdent? if nextt else NULLSTR swap then '{' expectChar ( name ) TYPE_VOID CType :new ( res ) - dup CType name c@ if dup dup CType name addTypedef then - 1 over to CType flags 0 >r dup begin ( res prev ) \ V1=offset + 1 over to CType flags + dup CType name c@ if dup addTypedef then + 0 >r dup begin ( res prev ) \ V1=offset nextt dup '}' isChar? not while ( res prev tok ) parseType _assert parseVariable ( res prev new ) tuck swap to CType nexttype ( res new ) diff --git a/fs/cc/vm/commonlo.fs b/fs/cc/vm/commonlo.fs @@ -92,16 +92,14 @@ vmop :self to vmop^ other \ Managing operands -: hasop# vmop :hasop# ; -: isconst? vmop :isconst? ; -: isconst# isconst? _assert ; -: noop# vmop :noop# ; +: isconst# vmop :isconst? _assert ; : const>op ( n -- ) vmop :>const ; -: constarray>op ( a -- ) noop# VM_CONSTARRAY to vmop loc to vmop arg ; -: sf+>op ( off -- ) noop# VM_*STACKFRAME to vmop loc to vmop arg ; -: ps+>op ( off -- ) noop# VM_*ARGSFRAME to vmop loc to vmop arg ; -: mem>op ( n -- ) noop# VM_*CONSTANT to vmop loc to vmop arg ; +: constarray>op ( a -- ) vmop :noop# VM_CONSTARRAY to vmop loc to vmop arg ; +: sf+>op ( off -- ) vmop :noop# VM_*STACKFRAME to vmop loc to vmop arg ; +: ps+>op ( off -- ) vmop :noop# VM_*ARGSFRAME to vmop loc to vmop arg ; +: mem>op ( n -- ) vmop :noop# VM_*CONSTANT to vmop loc to vmop arg ; : ctype>op ( ctype -- ) + vmop :noop# dup CType type to vmop type ( ctype ) case of CType :isglobal? r@ CType offset mem>op endof diff --git a/fs/cc/vm/forth.fs b/fs/cc/vm/forth.fs @@ -111,7 +111,7 @@ struct+[ VMOp 0 to psoff ; \ Allocate a new register for active op and pop 4b from PS into it. -: vmpspop, noop# vmop :>TOS PS+ vmop :>reg ; +: vmpspop, vmop :noop# vmop :>TOS PS+ vmop :>reg ; \ Push active op to PS. : vmpspush, vmop :compile vmop :forgetTOS PS- ; diff --git a/fs/cc/vm/i386.fs b/fs/cc/vm/i386.fs @@ -130,7 +130,7 @@ struct+[ VMOp \ Allocate a new register for active op and pop 4b from PS into it. : vmpspop, - noop# VM_REGISTER to vmop loc regallot dup to vmop arg r! bp 0 d) mov, + vmop :noop# VM_REGISTER to vmop loc regallot dup to vmop arg r! bp 0 d) mov, bp CELLSZ i) add, ; \ Push active op to PS. diff --git a/fs/tests/cc/cc.fs b/fs/tests/cc/cc.fs @@ -35,6 +35,7 @@ global 1234 #eq globalinc 1236 #eq globalinc 1238 #eq 42 142 sysword 142 #eq +42 142 funcsig 142 #eq capture helloworld S" Hello World!" #s= 42 40 50 isinrange 1 #eq 42 30 40 isinrange 0 #eq diff --git a/fs/tests/cc/test.c b/fs/tests/cc/test.c @@ -140,6 +140,14 @@ int globalinc() { int sysword(int a, int b) { return max(a, b); } + +typedef unsigned int (*MaxSig)(unsigned int, unsigned int); +// Same as above, but through a function signature typedef +int funcsig(int a, int b) { + MaxSig fn = &max; + return fn(a, b); +} + void helloworld() { stype("Hello World!"); } @@ -218,6 +226,8 @@ int unaryopmut(int n) { } typedef short MyType; +typedef MyType** MyTypePtr; + struct MyStruct { int foo; MyType bar; diff --git a/fs/tests/cc/type.fs b/fs/tests/cc/type.fs @@ -32,7 +32,7 @@ S" bar" over CType :find \ once defined, parseType will find the struct in typedefs current with-stdin< Struct1 STOP over #eq capture printtype -S" struct Struct1 { unsigned int foo, +04 short* bar, +08 char baz[2] }" #s= +S" struct Struct1 {unsigned int foo, +04 short* bar, +08 char baz[2]}" #s= \ Anonymous structs work too current with-stdin< struct { int foo; } STOP typesize 4 #eq