duskos

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

commit ad42cd65e112ee557ee0ed5dd93d0290ed96bc7c
parent ae14e7963b3eba512374a5c8819d23be57786cdf
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Fri,  3 Jun 2022 11:28:33 -0400

cc: begin implementing unary ops

Diffstat:
Mfs/asm.fs | 11++++++++---
Mfs/cc/ast.fs | 78+++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Mfs/cc/cc1.fs | 4+++-
Afs/cc/ops.fs | 22++++++++++++++++++++++
Mfs/test.c | 2+-
Mtests/testcc.fs | 4+++-
6 files changed, 84 insertions(+), 37 deletions(-)

diff --git a/fs/asm.fs b/fs/asm.fs @@ -50,11 +50,16 @@ : prefix, ( -- ) exit tgt is16? if $66 c, then src dup isimm? not swap is16? and if $67 c, then ; : inh, ( op -- ) c, asm$ ; -: modrm, ( imm? op -- ) +: modrm1, ( reg op -- ) \ modrm op with 1 argument + prefix, c, ( reg ) 3 lshift tgtid tgt mod or or ( modrm ) c, + disp? if disp c, then asm$ ; +: modrm2, ( imm? op -- ) \ modrm op with 2 arguments prefix, c, tgtid tgt mod or ( modrm ) src isimm? if $28 or ( 5 in reg ) c, , else c, then disp? if disp c, then asm$ ; \ operations -: mov, src isimm? if prefix, $b8 tgtid or c, , asm$ else $89 modrm, then ; -: sub, $81 modrm, ; +: mov, src isimm? if prefix, $b8 tgtid or c, , asm$ else $89 modrm2, then ; +: neg, 3 $f7 modrm1, ; +: not, 2 $f7 modrm1, ; +: sub, $81 modrm2, ; : ret, $c3 inh, ; diff --git a/fs/cc/ast.fs b/fs/cc/ast.fs @@ -7,7 +7,7 @@ \ 1b type id \ 1b flags (see below) -\ 1b parse stage +\ 1b child slots \ 4b addr of parent element (0 if root) \ 4b addr of next element (0 if none) \ ... maybe data @@ -22,22 +22,23 @@ \ 5 Statements \ 6 Arguments \ 7 Expression +\ 8 UnaryOp opid \ Flags \ b0 haschildren this element can contain children -\ b1 autoclose close automatically when a children closes \ b2 int data The 'data section contains a 4b integer \ b3 str data The 'data section contains a 1b str length followed by a \ string of that length. -\ Parse stage -\ Stores the stage at which the element is, parse-wise. For example, a Function -\ starts at 0. When Arguments have been parsed, it becomes 1. When Statements -\ have been parsed, it becomes 2. +\ Child slots +\ Indicate the number of children that this element can have. 0 means none, -1 +\ means unlimited, other numbers indicate the number of slots. Each time a +\ children is added, the slot is decreased. When 0 is reached, we close it. -8 value ASTIDCNT +9 value ASTIDCNT \ 8 chars per name -create astidnames ," -) unit functionreturn constantstmts args expr " +create astidnames +," ) unit functionreturn constantstmts args expr " +," unaryop " 0 value curunit \ points to current Unit, the beginning of the AST 0 value lastelem \ last element of the chain @@ -48,35 +49,40 @@ create astidnames ," : idname ( id -- sa sl ) 8 * astidnames + 8 rtrim ; : astid ( elem -- id ) c@ ; : flags ( elem -- flags ) 1+ c@ ; -: pstage ( elem -- pstage ) 1+ 1+ c@ ; -: pstage+ ( elem -- newpstage ) dup pstage 1+ over 1+ 1+ c! pstage ; +: cslots ( elem -- slots ) 1+ 1+ c@ ; +: cslots! ( slots elem -- ) 1+ 1+ c! ; +: cslots- ( elem -- newslots ) dup cslots 1- tuck swap cslots! ; : haschildren? ( elem -- f ) flags $01 and ; -: autoclose? ( elem -- f ) flags $02 and ; : parentelem ( elem -- parent ) 3 + @ ; : nextelem ( elem -- next ) 7 + @ ; : 'data ( elem -- 'data ) 11 + ; : intdata ( elem -- n ) 'data @ ; : strdata ( elem -- sa sl ) 'data c@+ ; -: newelem ( flags id -- ) - here lastelem 7 + ! here to lastelem c, c, 0 c, activeelem , 0 , +: newelem ( slots flags id -- ) + here lastelem 7 + ! here to lastelem c, c, c, activeelem , 0 , lastelem haschildren? if lastelem to activeelem then ; \ AST elements : SeqClose ( -- ) - 0 0 newelem activeelem + 0 0 0 newelem activeelem ?dup not if abort" can't go beyond root!" then parentelem to activeelem - activeelem autoclose? if SeqClose then ; + activeelem cslots- not if SeqClose then ; : Unit ( -- ) - here to curunit here to lastelem here to activeelem 1 c, $01 c, 9 allot0 ; -: Function ( 'name namelen -- ) $09 2 newelem dup c, move, ; -: Return ( -- ) $03 3 newelem ; -: Constant ( n -- ) $04 4 newelem , ; -: Statements ( -- ) $01 5 newelem ; -: Arguments ( -- ) $01 6 newelem ; -: Expression ( -- ) $01 7 newelem ; + here to curunit here to lastelem here to activeelem + 1 c, $01 c, -1 c, 9 allot0 ; +: Function ( 'name namelen -- ) 2 $09 2 newelem dup c, move, ; +: Return ( -- ) 1 $03 3 newelem ; +: Constant ( n -- ) 0 $04 4 newelem , ; +: Statements ( -- ) -1 $01 5 newelem ; +: Arguments ( -- ) -1 $01 6 newelem ; +: Expression ( -- ) 1 $01 7 newelem ; +: UnaryOp ( opid -- ) 1 $07 8 newelem , ; -: _err ( ta tl -- ) stype abort" parsing error" abort ; +: _err ( ta tl -- ) + stype spc> + activeelem ?dup if astid .x1 spc> then + abort" parsing error" ; : _assert ( ta tl f -- ) not if _err then ; : _nextt nextt ?dup not if abort" expecting token!" then ; @@ -88,25 +94,35 @@ create astidnames ," A>r 2dup >r >A begin Ac@+ identifier? _assert next r>A ; : expectChar ( ta tl c -- ) >r 2dup 1 = not if drop _err then c@ r> = _assert 2drop ; +\ Search the given token in a string list. if found, run the corresponding word +\ in optbl. Otherwise, parse error. +: tokenfromlist ( ta tl list optbl -- ) + >r rot> >s ( list R:optbl ) sfind dup 0< if s> _err then r> swap wexec ; \ Parse words. Each of those words have the signature "ta tl -- ". \ To be clear on the semantincs, the word represents the *context*, not the \ element being parsed. For example, in "Function", we're not parsing the \ Function AST element, but we're parsing its *children*. +create StatementsTList 1 c, ," }" 6 c, ," return" 0 c, +2 wordtbl StatementsOps ( -- ) +'w SeqClose ( } ) +:w ( return ) Return Expression ; + ASTIDCNT wordtbl astparsetbl 'w _err ( SeqClose ) :w ( Unit ) isType? _assert drop _nextt expectIdent Function ; -:w ( Function ) activeelem pstage+ dup 1 = if - drop '(' expectChar Arguments else - 2 = if '{' expectChar Statements else SeqClose then then ; +:w ( Function ) activeelem cslots 2 = if + '(' expectChar Arguments else + '{' expectChar Statements then ; 'w _err ( Return ) 'w _err ( Constant ) -:w ( Statements ) - 2dup S" }" S= if 2drop SeqClose else - 2dup S" return" S= _assert 2drop Return Expression then ; +:w ( Statements ) StatementsTList StatementsOps tokenfromlist ; :w ( Arguments ) ')' expectChar SeqClose ; -:w ( Expression ) expectConst Constant _nextt ';' expectChar SeqClose ; +:w ( Expression ) + 2dup uopid if UnaryOp 2drop Expression else + expectConst Constant _nextt ';' expectChar SeqClose then ; +'w _err ( UnaryOp ) : parseast ( -- ) Unit begin nextt ?dup not if exit then diff --git a/fs/cc/cc1.fs b/fs/cc/cc1.fs @@ -20,9 +20,10 @@ ASTIDCNT wordtbl posttbl :w ( Statements ) ret, ; 'w noop ( Arguments ) 'w noop ( Expression ) +:w ( UnaryOp ) dup intdata genuop ; ASTIDCNT wordtbl pretbl -:w ( SeqClose ) posttbl over parentelem astid wexec ; +:w ( SeqClose ) dup parentelem posttbl over astid wexec drop ; 'w noop ( Unit ) :w ( Function ) dup strdata entry ; 'w noop ( Return ) @@ -30,6 +31,7 @@ ASTIDCNT wordtbl pretbl 'w noop ( Statements ) 'w noop ( Arguments ) 'w noop ( Expression ) +'w noop ( UnaryOp ) \ Compiles input coming from the cc< alias (defaulting to in<) and writes the \ result to here. Aborts on error. diff --git a/fs/cc/ops.fs b/fs/cc/ops.fs @@ -0,0 +1,22 @@ +\ C compiler operators +\ Requires wordtbl.fs and asm.fs +\ Unary operators +\ ID Sym Name +\ 0 - Negate +\ 1 ~ Complement +\ 2 ! Not + +3 value UOPSCNT +create uopssyms ," -~!?" + +: uopid ( ta tl -- opid? f ) + 1 = if c@ uopssyms UOPSCNT [c]? dup 0< if drop 0 else 1 then + else drop 0 then ; +: uopchar ( opid -- c ) UOPSCNT max uopssyms + c@ ; + +UOPSCNT wordtbl opgentbl ( -- ) +:w ( - ) eax neg, ; +:w ( ~ ) eax not, ; +:w ( ! ) abort" TODO" ; + +: genuop ( opid -- ) opgentbl swap wexec ; diff --git a/fs/test.c b/fs/test.c @@ -1,3 +1,3 @@ int main() { - return 42; + return ~42; } diff --git a/tests/testcc.fs b/tests/testcc.fs @@ -1,11 +1,13 @@ \ Tests for the C compiler +f<< str.fs f<< wordtbl.fs f<< asm.fs f<< cc/tok.fs +f<< cc/ops.fs f<< cc/ast.fs f<< cc/cc1.fs : opentestc S" test.c" fopen not if abort" can't open" then ; opentestc ' f< to cc< cc1, -main 42 #eq +main $ffffffd5 #eq