duskos

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

commit 6fe12160abed3e3ebc51e913f2650ee3f57c610d
parent 2507af22d83b05bb2c5048011d7401df9f964b5f
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Sun, 19 Mar 2023 16:07:37 -0400

halcc: binopcondeval()

Diffstat:
Mfs/comp/c/egen.fs | 18+++++++++++++++---
Mfs/comp/c/expr.fs | 14+++++++++-----
Mfs/comp/c/fgen.fs | 4++--
Afs/comp/c/glob.fs | 11+++++++++++
Mfs/comp/c/type.fs | 3++-
Mfs/tests/comp/c/cc.fs | 2+-
Mfs/tests/comp/c/test2.c | 3+++
Mposix/dis.c | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
8 files changed, 119 insertions(+), 34 deletions(-)

diff --git a/fs/comp/c/egen.fs b/fs/comp/c/egen.fs @@ -65,7 +65,7 @@ UOPSCNT wordtbl _tbl ( res -- res ) of uopid ( opid ) nextt parseFactor ( opid res ) _tbl rot wexec endof of isIdent? \ lvalue, FunCall or macro - r@ findIdent ?dup _assert CType :halop Result :hal ( parsePostfixOp ) endof + r@ findIdent ?dup _assert Result :ctype ( parsePostfixOp ) endof r@ parse if Result :const else _err then endcase ; current ' parseFactor realias @@ -83,11 +83,23 @@ fixed _<<, <<, fixed _>>, >>, : _=, ( left right ) Result :>W Result :hal# !, Result :W ; -BOPSCNT wordtbl _tbl ( -- ) +\ Our implementation of "x ? y : z" suffers a significant limitation because +\ we're single pass: by the time _? is called, it's possible that code +\ generating the right part of it has already been generated, so the "true" part +\ will always be ran, regardless of the choice. So, we go like this: we generate +\ the "true" hand, push it to PS, then generate the "cond", keep it in W. When +\ we encounter the "false" hand, *then* we generate conditional code which +\ cleans up PS. +: _?, ( left right -- res ) Result :>PS dup Result :>W ; +: _:, ( left right -- res ) + PS- W=0>Z, 0 Z) branchC, + drop, [compile] else nip, swap Result :>W [compile] then ; + +BOPSCNT wordtbl _tbl ( left right -- res ) 'w _+, 'w _-, 'w _*, 'w _/, 'w _%, 'w _<<, 'w _>>, 'w _err 'w _err 'w _err 'w _err 'w _err 'w _err 'w _&, 'w _^, 'w _|, 'w _err 'w _err 'w _=, 'w _err 'w _err 'w _err 'w _err 'w _err -'w _err 'w _err 'w _err 'w _err 'w _err 'w _err 'w _err +'w _err 'w _err 'w _err 'w _err 'w _err 'w _?, 'w _:, : bothconst? ( left right -- f ) Result :isconst? swap Result :isconst? and ; diff --git a/fs/comp/c/expr.fs b/fs/comp/c/expr.fs @@ -1,5 +1,7 @@ \ Expression parsing and constexpr resolving ?f<< /comp/c/op.fs +?f<< /comp/c/type.fs +?f<< /comp/c/glob.fs : _err ( -- ) tokdbg abort" expr error" ; : _assert ( f -- ) not if _err then ; @@ -7,22 +9,23 @@ struct[ Result 0 const CONST \ Is a constant (value in arg) 1 const W \ Value in W register - 2 const HALOP \ Value in memory, HAL operand is in arg. + 2 const CTYPE \ CType pointer is in arg. sfield type - sfield arg \ either HAL operand or constant value + sfield arg \ either CType or constant value : :new ( arg type -- res ) SZ syspad :allot dup >r !+ ! r> ; : :const ( n -- res ) CONST :new ; : :W ( -- res ) 0 W :new ; - : :hal ( operand -- res ) HALOP :new ; + : :ctype ( ctype -- res ) CTYPE :new ; + \ TODO: manage W "locks" so that we push to PS when we need intermediate res. : :>W ( self -- ) dup bi arg | type case ( self arg ) CONST of = LIT>W, endof W of = drop endof - HALOP of = @, endof + CTYPE of = CType :halop @, endof _err endcase W swap to type ; : :hal# ( self -- halop ) dup type case ( self ) - HALOP of = arg endof + CTYPE of = arg CType :halop endof CONST of = arg i) endof _err endcase ; : :isconst? ( self -- f ) type CONST = ; @@ -30,6 +33,7 @@ struct[ Result : :isone? bi arg 1 = | :isconst? and ; : :isW? ( self -- f ) type W = ; : :const# dup :isconst? _assert arg ; + : :>PS :>W dup, PS+ ; ]struct BOPSCNT wordtbl _tbl ( a b -- n ) diff --git a/fs/comp/c/fgen.fs b/fs/comp/c/fgen.fs @@ -9,7 +9,7 @@ : _postlude _curfunc CType :argssize ?dup if ps+, then - _locvars CType :size rs+, ; + _locvars CType :size ?dup if rs+, then ; : emitRet ( res -- ) Result :>W _postlude exit, ; : emitNullRet ( -- ) _postlude drop, exit, ; @@ -72,7 +72,7 @@ current ' parseStatement realias here _curfunc to CType offset ( ) _curfunc ?updateFunctionPrototype _curfunc addSymbol \ prelude: space for stack frame. "dup," is wiggle room for W - dup, _locvars CType :size neg rs+, + dup, _locvars CType :size ?dup if neg rs+, then _initcode ?dup if [compile] again r> [compile] then then 0 to _laststmtid parseStatements _laststmtid 1 <> if emitRet then \ emit implicit return if needed diff --git a/fs/comp/c/glob.fs b/fs/comp/c/glob.fs @@ -0,0 +1,11 @@ +\ Global variables affecting the whole CC + +\ A function prelude always starts a "PS neutral" and should always be at +\ "PS neutral" when exiting from it. When we push something to PS, we increase +\ psoff, when we pop, we decrease it. This allows us to reliably access the +\ argument space of the function which lives in PS. +0 value psoff + +: PS+ CELLSZ to+ psoff ; +: PS- CELLSZ neg to+ psoff ; +: psneutral# psoff if abort" psoff not neutral!" then ; diff --git a/fs/comp/c/type.fs b/fs/comp/c/type.fs @@ -4,6 +4,7 @@ ?f<< /lib/meta.fs ?f<< /lib/ll.fs ?f<< /comp/c/tok.fs +?f<< /comp/c/glob.fs \ When we parse a type, we can almost never write it directly to "here" because \ there's always the chance that we're in the middle of a code generation op. @@ -106,7 +107,7 @@ struct[ CType : :halop ( self -- operand ) dup bi offset | storage case ( self offset ) STORAGE_SF of = RSP) swap +) endof - STORAGE_PS of = PSP) swap +) endof + STORAGE_PS of = PSP) swap psoff + +) endof STORAGE_MEM of = m) endof _err endcase ( self operand ) swap type _typesize case 1 of = 8b) endof 2 of = 16b) endof endcase ; diff --git a/fs/tests/comp/c/cc.fs b/fs/tests/comp/c/cc.fs @@ -16,9 +16,9 @@ binopshl 336 #eq binopshr 10 #eq binopdiv 14 #eq binopmod 1 #eq -testend \s 1 binopcondeval 42 #eq 0 binopcondeval 12 #eq +testend \s assignops 83 #eq boolops 0 #eq funcall 42 #eq diff --git a/fs/tests/comp/c/test2.c b/fs/tests/comp/c/test2.c @@ -52,3 +52,6 @@ int binopmod() { int a=43; return a % 3; } +int binopcondeval(int x) { + return x ? 42 : 12 ; +} diff --git a/posix/dis.c b/posix/dis.c @@ -22,7 +22,7 @@ struct op { int arg; }; -#define OPCNT 0x78 +#define OPCNT 0xa8 static struct op ops[OPCNT] = { {"BR", ARGINT}, {"CALL", ARGINT}, @@ -73,9 +73,9 @@ static struct op ops[OPCNT] = { {"BOOTRD", ARGNONE}, {"STDOUT", ARGNONE}, {"MAYBEKEY", ARGNONE}, - {NULL, ARGERR}, - {NULL, ARGERR}, - {NULL, ARGERR}, + {"HBANKGET", ARGNONE}, + {"MAKEMEM", ARGNONE}, + {"ADDDISP", ARGNONE}, {NULL, ARGERR}, {"MAYBEWORD", ARGNONE}, @@ -94,7 +94,7 @@ static struct op ops[OPCNT] = { {"STARTCOMP", ARGNONE}, {"STOPCOMP", ARGNONE}, {"RSADDWR", ARGNONE}, - {NULL, ARGERR}, + {"COMPOP", ARGNONE}, {"ALIGN4", ARGNONE}, {"ENTRY", ARGNONE}, @@ -105,22 +105,13 @@ static struct op ops[OPCNT] = { {NULL, ARGERR}, {NULL, ARGERR}, - {"SUB", ARGNONE}, - {"MUL", ARGNONE}, - {"DIVMOD", ARGNONE}, - {"LSHIFT", ARGNONE}, - {"RSHIFT", ARGNONE}, - {"LT", ARGNONE}, - {NULL, ARGERR}, - {NULL, ARGERR}, - - {"AND", ARGNONE}, - {"OR", ARGNONE}, - {"XOR", ARGNONE}, {NULL, ARGERR}, {NULL, ARGERR}, {NULL, ARGERR}, + {"DIVMOD", ARGNONE}, {NULL, ARGERR}, + {"LT", ARGNONE}, + {"NEG", ARGNONE}, {NULL, ARGERR}, {"BYE", ARGNONE}, @@ -132,13 +123,76 @@ static struct op ops[OPCNT] = { {NULL, ARGERR}, {NULL, ARGERR}, - {"SHLN", ARGBYTE}, - {"SHRN", ARGBYTE}, - {"ANDN", ARGINT}, - {"ORN", ARGINT}, - {"XORN", ARGINT}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, {"CHECKZ", ARGNONE}, {"STOREZ", ARGNONE}, + {"ACHECKZ", ARGNONE}, + + {"WSUB", ARGOP}, + {"WMUL", ARGOP}, + {"WDIV", ARGOP}, + {"WMOD", ARGOPN}, + {"WSHL", ARGOP}, + {"WSHR", ARGOP}, + {NULL, ARGERR}, + {NULL, ARGERR}, + + {"WSUB16", ARGOP}, + {"WMUL16", ARGOP}, + {"WDIV16", ARGOP}, + {"WMOD16", ARGOPN}, + {"WSHL16", ARGOP}, + {"WSHR16", ARGOP}, + {NULL, ARGERR}, + {NULL, ARGERR}, + + {"WSUB8", ARGOP}, + {"WMUL8", ARGOP}, + {"WDIV8", ARGOP}, + {"WMOD8", ARGOPN}, + {"WSHL8", ARGOP}, + {"WSHR8", ARGOP}, + {NULL, ARGERR}, + {NULL, ARGERR}, + + {"WAND", ARGOP}, + {"WOR", ARGOP}, + {"WXOR", ARGOP}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + + {"WAND16", ARGOP}, + {"WOR16", ARGOP}, + {"WXOR16", ARGOP}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + + {"WAND8", ARGOP}, + {"WOR8", ARGOP}, + {"WXOR8", ARGOP}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, + {NULL, ARGERR}, {NULL, ARGERR}, {"FCHILD", ARGNONE},