commit c1d807791d62e60fb37ac44355ba30431146d5c0
parent 5d96fd4248507486fa78b0eac5b9c6fd53d96648
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Fri, 24 Mar 2023 15:49:49 -0400
halcc: funcsig()
Diffstat:
6 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/fs/comp/c/egen.fs b/fs/comp/c/egen.fs
@@ -108,14 +108,15 @@ BOPSCNT wordtbl boptbl ( left right -- res )
\ the expected psoff. If it's higher, we need to readjust. After the call, we
\ need to restore psoff to its initial level *without actually adjusting*
\ because it's the callee's responsibility to free its arguments.
+code _callA branchA,
: _funcall ( res -- res ) psoff dup >r >r \ V1=psinitlvl V2=pslvl
dup Result :iscdecl? _assert ')' readChar? not if begin ( funcres tok )
parseExpression Result :?>W
psoff V2 - ?dup if dup ps+, neg to+ psoff then CELLSZ to+ V2
',' readChar? while nextt repeat ')' expectChar then ( funcres )
- dup Result :cdecl# dup CDecl :funcsig? if
+ dup Result :cdecl# dup CDecl :funcsig? if ( funcres cdecl )
nip dup CDecl offset execute,
- else abort" TODO: dynamic calls" then ( cdecl )
+ else swap Result :hal# A>) @, ['] _callA execute, then ( cdecl )
rdrop r> ( psinitlvl ) to psoff
Result currentW ?dup if PS- Result :release then
\ TODO: arilvl of fun rettype isn't properly preserved here
diff --git a/fs/comp/c/expr.fs b/fs/comp/c/expr.fs
@@ -65,13 +65,13 @@ struct[ Result
swap CDecl nbelem if dup :& -1 over to+ blvl then ;
: :cdecl# dup :iscdecl? _assert arg ;
- : :opsz ( halop self -- halop ) dup :.
- bi+ lvl | blvl = if 'B' emit
+ : :opsz ( halop self -- halop )
+ bi+ lvl | blvl = if
basesz case 1 of = 8b) endof 2 of = 16b) endof endcase
else drop then ;
: :hal# ( self -- halop ) dup type case ( self )
CONST of = arg i) endof
- CDECL of = 'C' emit
+ CDECL of =
bi+ arg CDecl :halop | lvl case ( self halop )
0 of = endof
-1 of = A>) lea, A*) endof
@@ -81,7 +81,7 @@ struct[ Result
PS of = arg PSP+) endof
abort" :hal# error" endcase ;
: :>W ( self -- )
- dup :isW? if drop else 'W' emit
+ dup :isW? if drop else
:Wfree# dup :hal# @,
0 over to@! lvl neg over to+ blvl
dup to currentW W swap to type then ;
@@ -95,8 +95,8 @@ struct[ Result
\ Free up W by sending it to A if needed.
: :?>A ( self -- halop )
dup :isW? if :release W>A, A*) else :hal# then ;
- : :* ( self -- ) '*' emit
- 1 over to+ lvl dup :isW? if '!' emit W) swap :opsz @, else drop then 'X' emit ;
+ : :* ( self -- )
+ 1 over to+ lvl dup :isW? if W) swap :opsz @, else drop then ;
: :<<n ( n self -- )
dup :isconst? if
dup arg rot lshift swap to arg else :?>W i) <<, then ;
diff --git a/fs/comp/c/ptype.fs b/fs/comp/c/ptype.fs
@@ -45,10 +45,13 @@ alias _err parseDeclarator ( type -- cdecl ) \ forward declaration
0 begin ( type lvl )
'*' readChar? while ( type lvl tok ) 1+ repeat ( type lvl tok )
dup '(' isChar? if ( type lvl tok )
- abort" TODO: declarator recursion"
+ drop swap _parseDeclarator read) ( lvl cdecl )
+ \ type recursion in C is "inside out". The cdecl we have now is the result.
+ \ We need to apply indirection levels we've already parsed to it.
+ tuck to+ CDecl lvl
else ( type lvl tok )
dup isIdent? not if to nexttputback NULLSTR then ( type lvl name )
- rot CDecl :new ( lvl cdecl ) tuck to CDecl lvl _post then ;
+ rot CDecl :new ( lvl cdecl ) tuck to CDecl lvl then _post ;
current ' parseDeclarator realias
: _parseStruct ( -- cdecl )
diff --git a/fs/comp/c/type.fs b/fs/comp/c/type.fs
@@ -87,7 +87,8 @@ struct[ CDecl
: :halop ( self -- operand ) dup bi offset | storage case ( self offset )
STORAGE_SF of = RSP) swap +) endof
STORAGE_PS of = PSP+) endof
- STORAGE_MEM of = m) endof _err endcase ( self operand )
+ STORAGE_MEM of = over :funcsig? if i) else m) then endof
+ _err endcase ( self operand )
swap type _typesize case 1 of = 8b) endof 2 of = 16b) endof endcase ;
\ Combined size of all fields in the LL.
diff --git a/fs/tests/comp/c/cc.fs b/fs/tests/comp/c/cc.fs
@@ -39,8 +39,8 @@ global 1234 #eq
globalinc 1236 #eq
globalinc 1238 #eq
1 globalshort 2 #eq
-testend \s
42 142 funcsig 184 #eq
+testend \s
capture helloworld S" Hello World!" #s=
create expected ," Null terminated\0"
nullstr expected 16 []= #
diff --git a/fs/tests/comp/c/test2.c b/fs/tests/comp/c/test2.c
@@ -156,3 +156,10 @@ static short shortarray[3] = {1, 2, 3};
short globalshort(int idx) {
return shortarray[idx];
}
+
+typedef unsigned int (*AdderSig)(unsigned int, unsigned int);
+int funcsig(int a, int b) {
+ AdderSig fn = adder;
+ int foo = fn(a, b);
+ return fn(a, b);
+}