duskos

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

commit bde754e4c3e25956b7c7afe5e2dc59cec31e8065
parent a0ae72ca1634cf37e5e14ddb4e6dbfedbd037b4b
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Sun, 18 Sep 2022 10:46:51 -0400

cc/vm: make VMOp :compile's width dependent on type

Diffstat:
Mfs/cc/ast.fs | 4++--
Mfs/cc/gen.fs | 7+++++--
Mfs/cc/type.fs | 7+++++++
Mfs/cc/vm/commonlo.fs | 16++++++++++++++--
Mfs/cc/vm/forth.fs | 5++++-
Mfs/cc/vm/i386.fs | 5++++-
Mfs/tests/cc/vm.fs | 14++++++++++++++
7 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/fs/cc/ast.fs b/fs/cc/ast.fs @@ -101,9 +101,9 @@ extends Node struct[ Statements extends DeclOrFunc struct[ Function sfield sfsize - sfield type + sfield type \ type of return value sfield address - sfield cursf \ last SF offset computed + sfield cursf \ last SF offset computed sfield flags : _ ( name args-or-stmts -- dnode-or-0 ) diff --git a/fs/cc/gen.fs b/fs/cc/gen.fs @@ -171,7 +171,10 @@ BOPSCNT wordtbl bopgentblpost ( -- ) 'w vm>>=, : decl>op ( dnode -- ) - dup Declare type to vmop type ( dnode ) + \ if our node is a func, op type is TYPE_VOID, *not* func return type. + dup Node id AST_FUNCTION = if + TYPE_VOID else dup Declare type then + to vmop type ( dnode ) case of Declare :isglobal? r@ Declare address mem>op endof of Declare :isarg? r@ Declare address ps+>op endof @@ -228,7 +231,7 @@ ASTIDCNT wordtbl gentbl ( node -- ) Node parent dup Function :locsize swap to Function cursf ; :w ( Ident ) dup identfind ?dup if ( inode dnode ) nip decl>op else ( inode ) - Ident name sysdict @ find ?dup _assert mem>op then ; + Ident name sysdict @ find ?dup _assert TYPE_VOID to vmop type mem>op then ; :w ( UnaryOp ) _debug if ." unaryop: " dup printast nl> .ops then dup genchildren diff --git a/fs/cc/type.fs b/fs/cc/type.fs @@ -9,8 +9,15 @@ \ b5:3 = *lvl. Indirection levels, from 0 to 7. $0 const TYPE_VOID +$8 const TYPE_VOID* +$1 const TYPE_CHAR +$9 const TYPE_CHAR* +$2 const TYPE_SHORT +$a const TYPE_SHORT* $3 const TYPE_INT +$b const TYPE_INT* $7 const TYPE_UINT +$f const TYPE_UINT* 4 stringlist typenames "void" "char" "short" "int" : typeunsigned? ( type -- flags ) 2 rshift 1 and ; diff --git a/fs/cc/vm/commonlo.fs b/fs/cc/vm/commonlo.fs @@ -4,6 +4,14 @@ \ Loading another VM impl will break the previous one. In Dusk, it's not a \ problem because there is no CC cross-compiling. You'll always want to compile \ with one VM: your CPU's. + +\ Relation between "loc" and type: +\ Location is where the value is stored. We track a level of indirection here +\ for performance reasons: CPUs generally can access locations with a level of +\ indirection. The type contains the "logical" level of indirection of the value +\ stored in the location. If, for example, we have a int* stored in a +\ VM_REGISTER, it's the exact equivalent of having an int stored in a +\ VM_*REGISTER. The number is the same. ?f<< /cc/type.fs : _err abort" vm error" ; @@ -53,7 +61,10 @@ struct[ VMOp >r >r >r \ V1=self V2=loc&type V3=arg V1 :push r> r> ( arg loc&type ) r> :pop ; \ if possible, transform current operand in its reference, f=1 means success. - : :?&op ( -- f ) dup :pointer? if dup :loclo swap to loc 1 else drop 0 then ; + : :?&op ( -- f ) + dup :pointer? if + dup :loclo over to loc dup type type*lvl+ swap to type 1 + else drop 0 then ; : :&op :?&op _assert ; : :*op dup loc case VM_CONSTANT of = endof @@ -61,7 +72,8 @@ struct[ VMOp VM_ARGSFRAME of = endof VM_REGISTER of = endof VM_TOS of = endof - _err endcase dup loc $10 or swap to loc ; + _err endcase + dup loc $10 or over to loc dup type type*lvl- swap to type ; ]struct create operands VMOp SZ 2 * allot diff --git a/fs/cc/vm/forth.fs b/fs/cc/vm/forth.fs @@ -38,9 +38,12 @@ struct+[ VMOp \ VM_*TOS. : :compile& >r r@ :pointer? if r@ :loclo r@ _ r> :>*TOS else r@ loc r@ _ r> :>TOS then ; + : :typesz! + type typesize case + 1 of = [compile] 8b endof 2 of = [compile] 16b endof endcase ; \ Resolve current operand and forces dereferencing. Always yields VM_TOS. : :compile ( -- ) >r - r@ :compile& r@ loc VM_*TOS = if compile @ r@ :>TOS then rdrop ; + r@ :compile& r@ loc VM_*TOS = if r@ :typesz! compile @ r@ :>TOS then rdrop ; : :>reg dup :loclo VM_REGISTER = if drop exit then >r r@ :hasop# r@ :?&op ( f ) r@ :compile& r@ 'arg litn compile ! PS- ( f ) 4 lshift VM_REGISTER or to r> loc ; diff --git a/fs/cc/vm/i386.fs b/fs/cc/vm/i386.fs @@ -69,9 +69,12 @@ struct+[ VMOp \ reinitialize selected op to VM_NONE and dealloc registers if needed : :init dup :loclo VM_REGISTER = if regfree then VMOp :init ; + : :typesz! + type typesize case + 1 of = 8b! endof 2 of = 16b! endof endcase ; \ Resolve current operand as an assembler "src" argument. : :compile - dup arg swap loc case + dup :typesz! dup arg swap loc case VM_CONSTANT of = i) endof VM_STACKFRAME of = abort" can't address VM_STACKFRAME directly" endof VM_REGISTER of = r! endof diff --git a/fs/tests/cc/vm.fs b/fs/tests/cc/vm.fs @@ -177,9 +177,23 @@ code test11 ( n -- n-42 ) 42 const>op vmcallarg, ' test3 mem>op ( a b -- a-b ) + TYPE_VOID to vmop type vmcall, vmpspop, vmret, 54 test11 12 #eq +\ variable op width +ops$ +here ," hello" ( a ) +code test12 ( n -- c ) + 4 0 vmprelude, + selop1 ( a ) const>op + TYPE_CHAR* to vmop type + selop2 0 ps+>op + selop1 vmadd, + vmop :*op + vmret, +0 test12 'h' #eq +1 test12 'e' #eq testend