2023-11-09 13:00:58 -06:00
# include "gen.h"
2024-01-12 19:48:31 -06:00
# include "err.h"
2023-11-09 13:00:58 -06:00
Gen gen_new ( void )
{
2023-11-12 07:14:56 -06:00
Gen gen = {
. labelno = 0 ,
. stackptr = NULL ,
2024-01-12 19:48:31 -06:00
. buildarch = M_X86_64 ,
2023-11-12 07:14:56 -06:00
} ;
2023-11-09 13:00:58 -06:00
return gen ;
}
2023-11-10 05:21:58 -06:00
void gen_free ( Gen * gen )
{
2023-11-12 06:59:42 -06:00
if ( ! gen ) return ;
2023-11-10 05:21:58 -06:00
}
2023-11-16 12:54:50 -06:00
2024-01-12 19:48:31 -06:00
bool gen_findret ( const PNode * pn , bool found )
{
if ( found ) return true ;
if ( ! pn ) return found ;
if ( pn - > type = = PRET ) return true ;
for ( size_t i = 0 ; i < pn - > pnodes . size ; + + i )
if ( gen_findret ( vec_at ( & pn - > pnodes , i , const PNode * ) , found ) )
return true ;
return false ;
}
2024-01-12 20:04:27 -06:00
void vec_print_tokens ( Vec * tokens )
{
if ( ! tokens ) return ;
if ( tokens - > size < 1 ) return ;
printf ( " %p (%lu/%lu): [ " , tokens , tokens - > size , tokens - > capacity ) ;
for ( size_t i = 0 ; i < tokens - > size ; + + i )
{
printf ( " %s " , vec_at ( tokens , i , const Tok * ) - > str . buffer ) ;
if ( i < tokens - > size - 1 )
printf ( " , " ) ;
}
printf ( " ] \n " ) ;
}
2024-01-24 07:26:36 -06:00
void vec_print_eval_elems ( Vec * stack )
{
if ( ! stack ) return ;
printf ( " %p stack: [ " , & stack ) ;
for ( size_t i = 0 ; i < stack - > size ; + + i )
{
eval_elem t = * vec_at ( stack , i , eval_elem * ) ;
switch ( t . type )
{
case EE_I32 : printf ( " %d " , t . val . i32 ) ; break ;
case EE_IDENT :
case EE_VAR :
case EE_FUNC : printf ( " %s " , t . val . name ) ; break ;
2024-01-24 09:28:05 -06:00
case EE_ACC : printf ( " acc " ) ; break ;
2024-01-24 07:26:36 -06:00
default : printf ( " . " ) ; break ;
}
if ( i < stack - > size - 1 ) printf ( " , " ) ;
}
printf ( " ] \n " ) ;
}
2024-01-12 19:48:31 -06:00
void gen_declare_variable ( Gen * gen , PNode * pn , FILE * file )
{
2024-01-28 16:53:41 -06:00
if ( ! gen ) return ;
if ( ! pn ) return ;
if ( ! file ) return ;
// Check syntax
2024-01-12 19:48:31 -06:00
if ( pn - > tokens . size > 1 )
{
2024-01-29 21:04:49 -06:00
if ( vec_at ( & pn - > tokens , 1 , const Tok * ) - > type ! = LOPERATOR & &
vec_at ( & pn - > tokens , 1 , const Tok * ) - > type ! = LASSIGN & &
vec_at ( & pn - > tokens , 1 , const Tok * ) - > type ! = LSCOLON )
2024-01-12 19:48:31 -06:00
{
2024-01-29 21:04:49 -06:00
err_log ( " %u: expected either ';', type specifier, or initializer " , vec_at ( & pn - > tokens , 1 , const Tok * ) - > line ) ;
2024-01-12 19:48:31 -06:00
}
}
else if ( pn - > tokens . size = = 0 )
{
err_log ( " %u: expected identifier " , pn - > firstline ) ;
return ;
}
2024-01-28 16:53:41 -06:00
// Check for re-declaration
2024-01-12 19:48:31 -06:00
for ( size_t i = 0 ; i < gen - > stackptr - > vars . size ; + + i )
{
if ( strcmp ( vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer , vec_at ( & gen - > stackptr - > vars , i , Var * ) - > name ) = = 0 )
{
err_log ( " %u: '%s' already declared " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > line , vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer ) ;
break ;
}
}
2024-01-28 16:53:41 -06:00
// Add var to PNode, parse tokens
2024-01-12 19:48:31 -06:00
if ( pn - > tokens . size > 0 )
{
2024-02-02 08:23:49 -06:00
gen - > stackptr - > stacksize + = gen - > ld . wordsize ;
2024-01-18 13:19:27 -06:00
const Tok * vartok = vec_at ( & pn - > tokens , 0 , const Tok * ) ;
2024-01-12 19:48:31 -06:00
Var var = {
2024-01-18 13:19:27 -06:00
. name = vartok - > str . buffer ,
2024-01-12 19:48:31 -06:00
. is_arg = false ,
2024-01-18 13:19:27 -06:00
. type = I32 ,
2024-01-26 09:25:08 -06:00
. stackloc = - gen - > stackptr - > stacksize ,
2024-01-12 19:48:31 -06:00
} ;
vec_push ( ( Vec * ) & gen - > stackptr - > vars , & var ) ;
// Evaluate initialization expression
if ( pn - > tokens . size > 1 )
2024-01-18 11:16:36 -06:00
gen_eval ( gen , pn , file ) ;
2024-01-12 19:48:31 -06:00
}
}
void gen_declare_function ( Gen * gen , PNode * pn , FILE * file )
{
if ( ! gen ) return ;
if ( ! pn ) return ;
if ( ! file ) return ;
size_t stacksize = 0 ;
gen - > stackptr = pn ;
if ( pn - > parentnode & & pn - > parentnode - > parentnode ! = NULL )
err_log ( " %u: nested function declaration " , pn - > firstline ) ;
2024-01-28 16:53:41 -06:00
// Check for re-declaration
2024-01-12 19:48:31 -06:00
for ( size_t i = 0 ; i < gen - > rootnode - > funcs . size ; + + i )
{
if ( strcmp ( vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer , vec_at ( & gen - > rootnode - > funcs , i , Func * ) - > name ) = = 0 )
{
err_log ( " %u: '%s' already declared " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > line , vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer ) ;
break ;
}
}
2024-01-28 16:53:41 -06:00
// Create Func struct
2024-01-12 19:48:31 -06:00
Func func = {
. name = vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer ,
2024-01-24 13:19:51 -06:00
. no_args = 0 ,
2024-01-12 19:48:31 -06:00
} ;
vec_push ( ( Vec * ) & gen - > rootnode - > funcs , & func ) ;
2024-02-02 08:23:49 -06:00
2024-01-28 16:53:41 -06:00
// Setup stack, find variables
2024-01-12 19:48:31 -06:00
if ( pn - > tokens . size < 2 | |
vec_at ( & pn - > tokens , 1 , Tok * ) - > subtype ! = LLPAREN )
err_log ( " %u: expected '(' " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > line ) ;
else
{
for ( size_t i = 2 ; i < pn - > tokens . size ; + + i )
{
if ( vec_at ( & pn - > tokens , i , const Tok * ) - > type = = LIDENTIFIER )
{
2024-02-02 08:23:49 -06:00
stacksize + = gen - > ld . wordsize ;
2024-01-12 19:48:31 -06:00
Var var = {
. name = vec_at ( & pn - > tokens , i , const Tok * ) - > str . buffer ,
. is_arg = true ,
2024-01-26 09:25:08 -06:00
. stackloc = - stacksize ,
2024-01-12 19:48:31 -06:00
} ;
2024-01-28 08:19:09 -06:00
// Use the previous stack frame for i386 function arguments
if ( gen - > buildarch = = M_I386 )
{
var . stackloc = - var . stackloc ;
2024-02-02 08:23:49 -06:00
var . stackloc + = gen - > ld . wordsize ;
2024-01-28 08:19:09 -06:00
}
2024-01-12 19:48:31 -06:00
vec_push ( ( Vec * ) & gen - > stackptr - > vars , & var ) ;
}
}
}
fprintf ( file , " .global %s \n %s: \n " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer , vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer ) ;
2024-01-28 16:53:41 -06:00
// Function stack settings
2024-01-12 19:48:31 -06:00
switch ( gen - > buildarch )
{
case M_I386 :
2024-02-02 08:23:49 -06:00
stacksize + = gen_stacksize ( gen , pn ) ;
2024-01-12 21:32:42 -06:00
gen_prolog ( gen , pn , file , stacksize ) ;
2024-01-12 19:48:31 -06:00
for ( size_t i = 0 ; i < pn - > pnodes . size ; + + i )
2024-01-12 21:49:15 -06:00
gen_code ( gen , vec_at ( & pn - > pnodes , i , PNode * ) , file ) ;
2024-01-12 19:48:31 -06:00
break ;
case M_X86_64 :
pn - > stacksize + = stacksize ;
2024-02-02 08:23:49 -06:00
stacksize + = gen_stacksize ( gen , pn ) ;
2024-01-12 21:32:42 -06:00
gen_prolog ( gen , pn , file , stacksize ) ;
2024-01-12 19:48:31 -06:00
for ( size_t i = 0 ; i < pn - > pnodes . size ; + + i )
2024-01-12 21:49:15 -06:00
gen_code ( gen , vec_at ( & pn - > pnodes , i , PNode * ) , file ) ;
2024-01-12 19:48:31 -06:00
break ;
}
}
2024-01-12 20:04:27 -06:00
// For function invocation arglist evaluation
// testing
void gen_eval_analyze ( const PNode * pn )
{
Vec rpn_stack = { 0 } ;
Vec stack = vec_new ( sizeof ( eval_elem ) ) ;
rpn_stack = gen_i2r ( & pn - > tokens ) ;
// Evaluate RPN
if ( rpn_stack . buffer & & rpn_stack . size > 0 )
{
for ( size_t i = 0 ; i < rpn_stack . size ; + + i )
{
switch ( vec_at ( & rpn_stack , i , const Tok * ) - > type )
{
case LIDENTIFIER :
printf ( " !%s " , vec_at ( & rpn_stack , i , const Tok * ) - > str . buffer ) ;
break ;
default :
printf ( " %s " , vec_at ( & rpn_stack , i , const Tok * ) - > str . buffer ) ;
break ;
}
}
printf ( " ; \n " ) ;
}
vec_free ( & rpn_stack ) ;
vec_free ( & stack ) ;
}
2024-01-12 21:32:42 -06:00
void gen_prolog ( Gen * gen , const PNode * pn , FILE * file , size_t stacksize )
{
if ( ! pn )
{
err_log ( " NULL PNode passed to gen_prolog " ) ;
return ;
}
if ( ! file )
{
err_log ( " NULL FILE* passed to gen_prolog " ) ;
return ;
}
2024-02-02 05:56:24 -06:00
fprintf ( file , " \t %s %%%s \n " , gen - > ld . push_wordsize , gen - > ld . bp ) ;
2024-01-12 21:32:42 -06:00
if ( gen - > buildarch = = M_X86_64 )
2024-02-02 05:56:24 -06:00
fprintf ( file , " \t %s %%%s \n " , gen - > ld . push_wordsize , gen - > ld . registers_abi_wordsize [ 2 ] ) ;
fprintf ( file , " \t %s %%%s,%%%s \n " , gen - > ld . mov_wordsize , gen - > ld . sp , gen - > ld . bp ) ;
2024-01-16 21:38:20 -06:00
if ( stacksize > 0 )
2024-02-02 05:56:24 -06:00
fprintf ( file , " \t %s $%lu,%%%s \n " , gen - > ld . sub_wordsize , stacksize , gen - > ld . sp ) ;
2024-01-12 21:32:42 -06:00
// Move argument variables to stack
2024-01-24 10:14:15 -06:00
if ( gen - > buildarch = = M_X86_64 )
2024-01-28 07:14:21 -06:00
for ( size_t i = 0 ; i < pn - > vars . size ; + + i )
2024-01-20 06:59:00 -06:00
if ( i < 6 & & vec_at ( & pn - > vars , i , Var * ) - > is_arg )
2024-02-02 08:23:49 -06:00
fprintf ( file , " \t %s %%%s,%d(%%%s) \n " , gen - > ld . mov_wordsize , gen - > ld . registers_abi_wordsize [ i ] , vec_at ( & pn - > vars , i , Var * ) - > stackloc , gen - > ld . bp ) ;
2024-01-12 21:32:42 -06:00
}
void gen_epilog ( Gen * gen , const PNode * pn , FILE * file )
{
if ( ! pn )
{
err_log ( " NULL PNode passed to gen_epilog " ) ;
return ;
}
if ( ! file )
{
err_log ( " NULL FILE* passed to gen_epilog " ) ;
return ;
}
2024-02-02 05:56:24 -06:00
fprintf ( file , " \t %s %%%s,%%%s \n " , gen - > ld . mov_wordsize , gen - > ld . bp , gen - > ld . sp ) ;
2024-01-12 21:32:42 -06:00
if ( gen - > buildarch = = M_X86_64 )
2024-02-02 05:56:24 -06:00
fprintf ( file , " \t %s %%%s \n " , gen - > ld . pop_wordsize , gen - > ld . registers_abi_wordsize [ 2 ] ) ;
fprintf ( file , " \t %s %%%s \n " , gen - > ld . pop_wordsize , gen - > ld . bp ) ;
2024-01-12 21:32:42 -06:00
}
2024-01-12 21:49:15 -06:00
2024-02-02 08:23:49 -06:00
size_t gen_stacksize ( const Gen * gen , const PNode * pn )
2024-01-12 21:49:15 -06:00
{
size_t stacksize = 0 ;
if ( pn - > pnodes . size = = 0 )
{
if ( pn - > type = = PVARDECL )
2024-02-02 08:23:49 -06:00
return stacksize + gen - > ld . wordsize ;
2024-01-12 21:49:15 -06:00
else return 0 ;
}
for ( size_t i = 0 ; i < pn - > pnodes . size ; + + i )
2024-02-02 08:23:49 -06:00
stacksize + = gen_stacksize ( gen , vec_at ( & pn - > pnodes , i , PNode * ) ) ;
2024-01-12 21:49:15 -06:00
return stacksize ;
}
2024-01-19 10:34:13 -06:00
// Identify functions
bool gen_findfunc ( const Gen * const gen , eval_elem * e )
{
if ( ! gen ) { err_log ( " gen_findfunc: bad gen " ) ; return false ; } if ( ! e ) { err_log ( " gen_findfunc: bad eval_elem " ) ; return false ; } if ( ! e - > val . name ) { err_log ( " gen_findfunc: bad eval_elem name " ) ; return false ; }
2024-01-24 09:28:05 -06:00
if ( ! e ) return false ;
2024-01-19 10:34:13 -06:00
for ( size_t j = 0 ; j < gen - > rootnode - > funcs . size ; + + j )
{
if ( strcmp ( vec_at ( & gen - > rootnode - > funcs , j , Func * ) - > name , e - > val . name ) = = 0 )
{
e - > type = EE_FUNC ;
2024-01-24 09:28:05 -06:00
/* e->val.name=vec_at(&gen->stackptr->funcs,j,Func*)->name; */
2024-01-19 10:34:13 -06:00
return true ;
}
}
return false ;
}
bool gen_findvar ( const Gen * const gen , eval_elem * e )
{
2024-01-24 09:28:05 -06:00
if ( ! gen ) { err_log ( " gen_findvar: bad gen " ) ; return false ; }
if ( ! e ) { err_log ( " gen_findfunc: bad eval_elem " ) ; return false ; }
if ( ! e - > val . name ) { err_log ( " gen_findfunc: bad eval_elem name " ) ; return false ; }
2024-01-19 10:34:13 -06:00
for ( size_t j = 0 ; j < gen - > stackptr - > vars . size ; + + j )
{
if ( strcmp ( vec_at ( & gen - > stackptr - > vars , j , Var * ) - > name , e - > val . name ) = = 0 )
{
e - > type = EE_VAR ;
e - > vstackloc = vec_at ( & gen - > stackptr - > vars , j , Var * ) - > stackloc ;
e - > vtype = vec_at ( & gen - > stackptr - > vars , j , Var * ) - > type ;
2024-01-24 09:28:05 -06:00
/* e->val.name=vec_at(&gen->stackptr->vars,j,Var*)->name; */
2024-01-19 10:34:13 -06:00
//var_stackloc[k]=vec_at(&gen->stackptr->vars,j,Var*)->stackloc;
return true ;
}
}
return false ;
}
2024-01-12 21:49:15 -06:00
void gen_code ( Gen * gen , PNode * pn , FILE * file )
{
if ( ! pn )
{
err_log ( " passed NULL PNode to gen_code " ) ;
return ;
}
if ( ! file )
{
err_log ( " NULL FILE* passed to gen_code " ) ;
return ;
}
if ( gen - > rootnode = = pn )
fprintf ( file , " .text \n " ) ;
switch ( pn - > type )
{
case PFUNDECL :
{
bool found = false ;
gen_declare_function ( gen , pn , file ) ;
found = gen_findret ( pn , false ) ;
if ( ! found )
err_log ( " %u: no return in function '%s' " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > line ,
vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer ) ;
}
break ;
case PVARDECL :
gen_declare_variable ( gen , pn , file ) ;
break ;
case PRET :
if ( pn - > tokens . size > 0 )
{
if ( vec_at ( & pn - > tokens , 0 , const Tok * ) - > type = = LOPERATOR & & vec_at ( & pn - > tokens , 0 , const Tok * ) - > subtype = = LSMINUS )
{
if ( pn - > tokens . size < 2 )
err_log ( " %u: expected integer " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > line ) ;
else
2024-02-02 08:23:49 -06:00
fprintf ( file , " \t %s -%s,%%%s \n " , gen - > ld . mov_wordsize , vec_at ( & pn - > tokens , 1 , const Tok * ) - > str . buffer , gen - > ld . acc_wordsize ) ;
2024-01-12 21:49:15 -06:00
}
/* else if(vec_at(&pn->tokens,0,const Tok*)->type!=LINTEGER) */
/* { */
/* err_log("%u: returning non-integer",vec_at(&pn->tokens,0,const Tok*)->line); */
/* } */
else
2024-01-18 11:16:36 -06:00
gen_eval ( gen , pn , file ) ;
2024-01-12 21:49:15 -06:00
}
gen_epilog ( gen , pn , file ) ;
fprintf ( file , " \t ret \n " ) ;
/*****
* IMPORTANT :
* This return exits the ( recursive )
* code generation call and ceases
* reading further PNodes belonging
* to its parent node ( i . e . , on the
* same level ) ! !
* * * * */
return ;
break ;
case PIF :
if ( pn - > tokens . size > 1 )
{
2024-01-18 11:16:36 -06:00
gen_eval ( gen , pn , file ) ;
2024-02-02 08:23:49 -06:00
fprintf ( file , " \t %s $0,%%%s \n " , gen - > ld . cmp_wordsize , gen - > ld . acc_wordsize ) ;
2024-01-12 21:49:15 -06:00
}
2024-01-16 20:58:49 -06:00
size_t labelno_cache = gen - > labelno ;
2024-01-12 21:49:15 -06:00
+ + gen - > labelno ;
2024-01-16 20:58:49 -06:00
fprintf ( file , " \t jz .L%02lu \n " , labelno_cache ) ;
2024-01-12 21:49:15 -06:00
for ( size_t i = 0 ; i < pn - > pnodes . size ; + + i )
gen_code ( gen , vec_at ( & pn - > pnodes , i , PNode * ) , file ) ;
2024-01-16 20:58:49 -06:00
fprintf ( file , " .L%02lu: \n " , labelno_cache ) ;
2024-01-12 21:49:15 -06:00
break ;
case PWHILE :
2024-01-16 20:58:49 -06:00
{
size_t pwhile_label1 = gen - > labelno + + ;
size_t pwhile_label2 = gen - > labelno + + ;
fprintf ( file , " .L%02lu: \n " , pwhile_label1 ) ;
2024-01-12 21:49:15 -06:00
if ( pn - > tokens . size > 1 )
{
2024-01-18 11:16:36 -06:00
gen_eval ( gen , pn , file ) ;
2024-02-04 11:47:02 -06:00
fprintf ( file , " \t %s $0,%%%s \n " , gen - > ld . cmp_wordsize , gen - > ld . acc_wordsize ) ;
2024-01-12 21:49:15 -06:00
}
2024-01-16 20:58:49 -06:00
fprintf ( file , " \t jz .L%02lu \n " , pwhile_label2 ) ;
2024-01-12 21:49:15 -06:00
for ( size_t i = 0 ; i < pn - > pnodes . size ; + + i )
gen_code ( gen , vec_at ( & pn - > pnodes , i , PNode * ) , file ) ;
2024-01-16 20:58:49 -06:00
fprintf ( file , " \t jmp .L%02lu \n " , pwhile_label1 ) ;
fprintf ( file , " .L%02lu: \n " , pwhile_label2 ) ;
}
2024-01-12 21:49:15 -06:00
break ;
case PASM :
{
if ( pn - > tokens . size < 1 )
err_log ( " %u: expected string after keyword 'asm' " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > line ) ;
else
{
if ( pn - > tokens . size > 2 )
err_log ( " %u: unexpected token after 'asm' statement " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > line ) ;
/* gen_x86_64_print_string(gen,pn,file, */
/* &vec_at(&pn->tokens,0,const Tok*)->str); */
fprintf ( file , " \t %s \n " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer ) ;
}
}
break ;
case PEXTERN :
{
if ( pn - > tokens . size < 1 )
err_log ( " %u: expected identifier after keyword 'ext' " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > line ) ;
else
{
if ( vec_at ( & pn - > tokens , 0 , const Tok * ) - > type ! = LIDENTIFIER )
err_log ( " %u: expected identifier after keyword 'ext' " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > line ) ;
if ( pn - > tokens . size > 1 & & vec_at ( & pn - > tokens , 1 , const Tok * ) - > subtype = = LLPAREN )
{
for ( size_t i = 0 ; i < gen - > rootnode - > funcs . size ; + + i )
{
if ( strcmp ( vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer , vec_at ( & gen - > rootnode - > funcs , i , Func * ) - > name ) = = 0 )
{
err_log ( " %u: '%s' already declared " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > line , vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer ) ;
break ;
}
}
Func func = {
. name = vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer ,
2024-01-24 13:19:51 -06:00
. no_args = 0 ,
2024-01-12 21:49:15 -06:00
} ;
vec_push ( ( Vec * ) & gen - > rootnode - > funcs , & func ) ;
}
else
gen_declare_variable ( gen , pn , file ) ;
fprintf ( file , " .extern %s \n " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer ) ;
}
}
break ;
case PCOMMENT :
fprintf ( file , " \t ;%s \n " , vec_at ( & pn - > tokens , 0 , const Tok * ) - > str . buffer ) ;
break ;
case PBLOCK :
for ( size_t i = 0 ; i < pn - > pnodes . size ; + + i )
gen_code ( gen , vec_at ( & pn - > pnodes , i , PNode * ) , file ) ;
break ;
case PEMPTY :
// Root node, otherwise ignore
if ( pn - > parentnode = = NULL )
{
for ( size_t i = 0 ; i < pn - > pnodes . size ; + + i )
gen_code ( gen , vec_at ( & pn - > pnodes , i , PNode * ) , file ) ;
}
break ;
case PEXPRESSION :
default :
2024-01-18 11:16:36 -06:00
gen_eval ( gen , pn , file ) ;
2024-01-12 21:49:15 -06:00
if ( pn - > tokens . size > 0 )
{
fprintf ( file , " ;#PNODE ID: %s " , partype_names [ pn - > type ] ) ;
for ( size_t i = 0 ; i < pn - > tokens . size ; + + i )
{
fprintf ( file , " %s " , vec_at ( & pn - > tokens , i , const Tok * ) - > str . buffer ) ;
}
fprintf ( file , " \n " ) ;
}
break ;
}
//for(size_t i=0;i<pn->pnodes.size;++i)
//gen_code(gen,vec_at(&pn->pnodes,i,PNode*),file);
}
2024-01-18 11:16:36 -06:00
2024-01-19 10:34:13 -06:00
// Convert infix to RPN
// Vec<Tok>
Vec gen_i2r ( const Vec * tokens )
{
Vec stack = vec_new ( sizeof ( const Tok ) ) ;
Vec operators = vec_new ( sizeof ( const Tok ) ) ;
2024-01-22 16:01:01 -06:00
size_t parenlvl = 0 ;
2024-01-19 10:34:13 -06:00
int precedence [ 1024 ] = { 0 } ;
2024-02-03 13:59:28 -06:00
precedence [ LASSIGN ] = 3 ;
precedence [ LLPAREN ] = 5 ;
precedence [ LRPAREN ] = 5 ;
precedence [ LADD ] = 10 ;
precedence [ LSMINUS ] = 10 ;
precedence [ LSNOT ] = 10 ;
precedence [ LSREF ] = 10 ;
precedence [ LSMUL ] = 20 ;
precedence [ LSDIV ] = 20 ;
precedence [ LSDEREF ] = 25 ;
precedence [ LSCOMMA ] = 30 ;
2024-01-19 10:34:13 -06:00
if ( tokens - > size > 0 )
{
for ( size_t i = 0 ; i < tokens - > size ; + + i )
{
2024-01-24 09:28:05 -06:00
/* printf("[[%s]]\n",vec_at(tokens,i,const Tok*)->str.buffer); */
2024-01-19 10:34:13 -06:00
// identifiers
switch ( vec_at ( tokens , i , const Tok * ) - > type )
{
// integers, keywords (true/false), identifiers
case LIDENTIFIER :
case LKEYWORD :
case LINTEGER :
case LFLOAT :
vec_push ( & stack , vec_at ( tokens , i , const Tok * ) ) ;
break ;
// operators
case LOPERATOR :
{
// '('
if ( vec_at ( tokens , i , const Tok * ) - > subtype = = LLPAREN )
{
2024-01-22 16:01:01 -06:00
+ + parenlvl ;
2024-01-19 10:34:13 -06:00
vec_push ( & operators , vec_at ( tokens , i , const Tok * ) ) ;
}
// ')'
else if ( vec_at ( tokens , i , const Tok * ) - > subtype = = LRPAREN )
{
while ( operators . size > 0 & & vec_at ( & operators , operators . size - 1 , const Tok * ) - > subtype ! = LLPAREN )
{
const Tok * newtok = vec_at ( & operators , operators . size - 1 , const Tok * ) ;
vec_push ( & stack , newtok ) ;
vec_pop ( & operators ) ;
}
2024-01-22 16:01:01 -06:00
- - parenlvl ;
2024-01-19 10:34:13 -06:00
vec_pop ( & operators ) ;
}
2024-01-22 16:01:01 -06:00
// ','
else if ( vec_at ( tokens , i , const Tok * ) - > subtype = = LSCOMMA )
2024-01-22 16:49:49 -06:00
{
// TODO: Verify edge cases here. This is a rough test
// that could use more rigorous definition
while ( operators . size > 0 & & vec_at ( & operators , operators . size - 1 , const Tok * ) - > subtype ! = LLPAREN )
{
const Tok * newtok = vec_at ( & operators , operators . size - 1 , const Tok * ) ;
vec_push ( & stack , newtok ) ;
vec_pop ( & operators ) ;
}
/* const Tok*newtok=vec_at(&operators,operators.size-1,const Tok*); */
/* vec_push(&stack,newtok); */
/* vec_pop(&operators); */
vec_push ( & stack , vec_at ( tokens , i , const Tok * ) ) ;
}
2024-01-22 16:01:01 -06:00
2024-01-19 10:34:13 -06:00
// Default operators
else
{
// Pop operators from operators ==> stack
// who have higher precedence than current
// operator
2024-02-03 13:59:28 -06:00
while ( operators . size > 0 & & precedence [ ( uint32_t ) vec_at ( & operators , operators . size - 1 , const Tok * ) - > subtype ] > = precedence [ ( uint32_t ) vec_at ( tokens , i , const Tok * ) - > subtype ] )
2024-01-19 10:34:13 -06:00
{
const Tok * newtok = vec_at ( & operators , operators . size - 1 , const Tok * ) ;
vec_push ( & stack , newtok ) ;
vec_pop ( & operators ) ;
}
vec_push ( & operators , vec_at ( tokens , i , const Tok * ) ) ;
}
}
2024-01-24 09:28:05 -06:00
break ;
2024-01-24 09:54:39 -06:00
/* default: */
/* err_log("unrecognized token type\n"); */
/* break; */
2024-01-24 09:28:05 -06:00
2024-01-19 10:34:13 -06:00
}
}
}
while ( operators . size > 0 )
{
const Tok * newtok = vec_at ( & operators , operators . size - 1 , const Tok * ) ;
vec_push ( & stack , newtok ) ;
vec_pop ( & operators ) ;
}
/* printf("s:"); */
/* vec_print_tokens(&stack); */
/* printf("o:"); */
/* vec_print_tokens(&operators); */
/* vec_free(&stack); */
vec_free ( & operators ) ;
// move ownership to caller
return stack ;
}
2024-01-18 11:16:36 -06:00
// Convert to infix, then evaluate
void gen_eval ( Gen * gen , const PNode * pn , FILE * file )
{
Vec rpn_stack = { 0 } ;
Vec stack = vec_new ( sizeof ( eval_elem ) ) ;
2024-01-20 11:11:04 -06:00
eval_elem tmpelem = { 0 } ;
2024-01-22 10:43:57 -06:00
size_t funarg_max = 0 ; // How many function arguments are we looking for?
size_t funarg_no = 0 ; // Out of funarg_max, which arg are we finding now?
2024-01-18 11:16:36 -06:00
2024-01-22 10:14:39 -06:00
// Find function invocations in pn->tokens
2024-01-22 09:26:00 -06:00
// and count their number of arguments. This
// will be used to pop the right number of
// values from the stack.
2024-01-22 10:14:39 -06:00
for ( size_t i = 0 ; i < pn - > tokens . size ; + + i )
{
for ( size_t j = 0 ; j < gen - > rootnode - > funcs . size ; + + j )
{
// Identified a function
if ( strcmp ( vec_at ( & pn - > tokens , i , const Tok * ) - > str . buffer ,
vec_at ( & gen - > rootnode - > funcs , j , const Func * ) - > name ) = = 0 )
{
Tok * functok = vec_at ( & pn - > tokens , i , Tok * ) ;
/* printf("func '%s': [",functok->str.buffer); */
functok - > fn_no_args = 0 ;
size_t parenlvl = 0 ;
bool foundone = false ;
// Find function tokens, record number of
// arguments passed to them
for ( size_t k = i + 1 ; k < pn - > tokens . size ; + + k )
{
Tok * curtok = vec_at ( & pn - > tokens , k , Tok * ) ;
switch ( curtok - > subtype )
{
case LLPAREN :
+ + parenlvl ;
break ;
case LRPAREN :
{
if ( foundone )
{
+ + functok - > fn_no_args ;
foundone = false ;
}
- - parenlvl ;
if ( parenlvl = = 0 )
k = pn - > tokens . size ;
}
break ;
case LSCOMMA :
if ( foundone )
{
+ + functok - > fn_no_args ;
foundone = false ;
}
break ;
default :
foundone = true ;
break ;
}
/* printf("%s%s",curtok->str.buffer,k<pn->tokens.size-1?" ":""); */
}
2024-01-22 10:43:57 -06:00
/* printf("%p '%s': %lu\n",functok->str.buffer,functok->str.buffer,functok->fn_no_args); */
2024-01-22 10:14:39 -06:00
}
}
}
2024-01-22 09:26:00 -06:00
2024-01-30 12:16:12 -06:00
// Find LSMUL, analyze context, convert
// to LSDEREF if used as unary op
for ( size_t i = 0 ; i < pn - > tokens . size ; + + i )
{
if ( vec_at ( & pn - > tokens , i , Tok * ) - > subtype = = LSMUL )
{
Tok * prev = vec_at ( & pn - > tokens , i - 1 , Tok * ) ;
if ( i = = 0 | | ( prev - > type = = LOPERATOR & & prev - > subtype ! = LRPAREN & & prev - > subtype ! = LLPAREN ) )
vec_at ( & pn - > tokens , i , Tok * ) - > subtype = LSDEREF ;
}
}
2024-01-22 10:43:57 -06:00
rpn_stack = gen_i2r ( & pn - > tokens ) ;
if ( gen - > showrpn ) vec_print_tokens ( & rpn_stack ) ;
2024-01-18 11:16:36 -06:00
/* gen_eval_analyze(pn); */
// Evaluate RPN
if ( rpn_stack . buffer & & rpn_stack . size > 0 )
{
for ( size_t i = 0 ; i < rpn_stack . size ; + + i )
{
switch ( vec_at ( & rpn_stack , i , const Tok * ) - > type )
{
case LKEYWORD :
{
if ( strcmp ( " true " , vec_at ( & rpn_stack , i , const Tok * ) - > str . buffer ) = = 0 )
{
2024-01-20 11:11:04 -06:00
tmpelem = ( eval_elem ) { . type = EE_I32 , . val . i32 = 1 } ;
2024-01-18 13:19:27 -06:00
vec_push ( & stack , & tmpelem ) ;
2024-01-18 11:16:36 -06:00
}
else if ( strcmp ( " false " , vec_at ( & rpn_stack , i , const Tok * ) - > str . buffer ) = = 0 )
{
2024-01-20 11:11:04 -06:00
tmpelem = ( eval_elem ) { . type = EE_I32 , . val . i32 = 0 } ;
2024-01-18 13:19:27 -06:00
vec_push ( & stack , & tmpelem ) ;
2024-01-18 11:16:36 -06:00
}
}
break ;
case LIDENTIFIER :
{
2024-01-19 15:59:05 -06:00
// Convert identifiers into functions or vars
// Otherwise it is an error
2024-01-20 11:11:04 -06:00
tmpelem = ( eval_elem ) { . type = EE_IDENT , . val . name = vec_at ( & rpn_stack , i , const Tok * ) - > str . buffer } ;
2024-01-19 15:59:05 -06:00
if ( ! gen_findfunc ( gen , & tmpelem ) )
if ( ! gen_findvar ( gen , & tmpelem ) )
err_log ( " %u: undeclared identifier '%s' " , vec_at ( & pn - > tokens , 0 , Tok * ) - > line , tmpelem . val . name ) ;
2024-01-22 10:43:57 -06:00
if ( tmpelem . type = = EE_FUNC )
{
funarg_max = vec_at ( & rpn_stack , i , const Tok * ) - > fn_no_args ;
funarg_no = 0 ;
2024-01-24 09:46:27 -06:00
if ( funarg_max = = 0 )
fprintf ( file , " \t call %s \n " , tmpelem . val . name ) ;
2024-01-22 10:43:57 -06:00
}
2024-01-19 16:01:48 -06:00
/* printf("[[%s:%lu]]\n",tmpelem.val.name,tmpelem.type); */
2024-01-18 13:19:27 -06:00
vec_push ( & stack , & tmpelem ) ;
2024-01-18 11:16:36 -06:00
}
break ;
case LINTEGER :
case LFLOAT :
{
int32_t d = atoi ( vec_at ( & rpn_stack , i , const Tok * ) - > str . buffer ) ;
2024-01-20 11:11:04 -06:00
tmpelem = ( eval_elem ) { . type = EE_I32 , . val . i32 = d } ;
2024-01-18 13:19:27 -06:00
vec_push ( & stack , & tmpelem ) ;
2024-01-18 11:16:36 -06:00
}
break ;
case LOPERATOR :
// Get operands
2024-02-01 08:17:02 -06:00
if ( stack . size > 0 )
2024-01-18 11:16:36 -06:00
{
eval_elem elem [ 2 ] = { { 0 } } ;
size_t nops = 2 ; // 2 unless unary operator
2024-01-30 12:16:12 -06:00
// Find operators with nops != 2
switch ( vec_at ( & rpn_stack , i , const Tok * ) - > subtype )
{
case LSNOT : case LSREF : case LSDEREF : nops = 1 ; break ;
case LSCOMMA : nops = 0 ; break ;
}
2024-01-29 21:04:49 -06:00
2024-01-18 11:16:36 -06:00
// Get top two stack elements (variables, integers, etc.)
for ( size_t k = 0 ; k < nops ; + + k )
{
elem [ k ] = * vec_at ( & stack , stack . size - 1 , eval_elem * ) ;
vec_pop ( & stack ) ;
2024-01-19 15:59:05 -06:00
if ( elem [ k ] . type = = EE_FUNC )
2024-01-18 11:16:36 -06:00
{
2024-01-19 15:59:05 -06:00
fprintf ( file , " \t call %s \n " , elem [ k ] . val . name ) ;
2024-01-18 11:16:36 -06:00
{
2024-01-20 11:11:04 -06:00
tmpelem = ( eval_elem ) { . type = EE_ACC , . val . i32 = 0 } ;
2024-01-19 15:59:05 -06:00
vec_push ( & stack , & tmpelem ) ;
- - k ;
2024-01-18 11:16:36 -06:00
}
}
2024-01-19 15:59:05 -06:00
// Still not categorized as func or var
else if ( elem [ k ] . type = = EE_IDENT )
err_log ( " %u: undeclared identifier '%s' " , vec_at ( & pn - > tokens , 0 , Tok * ) - > line , elem [ k ] . val . name ) ;
2024-01-18 11:16:36 -06:00
}
2024-01-20 07:33:28 -06:00
gen_evalop ( gen , ( PNode * ) pn , elem , nops , vec_at ( & rpn_stack , i , Tok * ) , file , & stack ) ;
2024-01-18 11:16:36 -06:00
}
break ;
2024-01-24 09:28:05 -06:00
default :
err_log ( " unrecognized token type \n " ) ;
break ;
2024-01-18 11:16:36 -06:00
}
}
}
// Empty remaining variables/integers on the stack
2024-01-24 09:28:05 -06:00
eval_lastelem :
2024-01-18 11:16:36 -06:00
if ( stack . size > 0 )
{
2024-01-24 09:28:05 -06:00
eval_elem e = * ( vec_at ( & stack , stack . size - 1 , eval_elem * ) ) ;
if ( funarg_max > 0 & & funarg_no = = funarg_max & & e . type = = EE_FUNC )
2024-01-28 08:19:09 -06:00
{
2024-01-24 09:28:05 -06:00
fprintf ( file , " \t call %s \n " , e . val . name ) ;
2024-01-28 08:19:09 -06:00
if ( gen - > buildarch = = M_I386 )
2024-02-02 08:23:49 -06:00
fprintf ( file , " \t %s $%lu,%%%s \n " , gen - > ld . sub_wordsize , funarg_max * gen - > ld . wordsize , gen - > ld . sp ) ;
2024-01-28 08:19:09 -06:00
}
2024-01-24 09:28:05 -06:00
vec_pop ( & stack ) ;
int32_t value = 0 ;
if ( e . type = = EE_I32 )
2024-01-18 11:16:36 -06:00
{
2024-01-24 09:28:05 -06:00
value = e . val . i32 ;
2024-02-02 08:23:49 -06:00
fprintf ( file , " \t %s $%d,%%%s \n " , gen - > ld . mov_wordsize , value , gen - > ld . acc_wordsize ) ;
2024-01-24 09:28:05 -06:00
}
2024-01-18 11:16:36 -06:00
2024-01-24 09:28:05 -06:00
else if ( e . type = = EE_IDENT | |
e . type = = EE_FUNC | |
e . type = = EE_VAR )
{
2024-01-18 11:16:36 -06:00
2024-01-24 09:28:05 -06:00
// Find identifiers
if ( e . type = = EE_IDENT )
2024-01-24 07:26:36 -06:00
{
2024-01-24 09:28:05 -06:00
// Convert identifiers into functions or vars
// Otherwise it is an error
if ( ! gen_findfunc ( gen , & e ) )
if ( ! gen_findvar ( gen , & e ) )
err_log ( " %u: undeclared identifier '%s' " , vec_at ( & pn - > tokens , 0 , Tok * ) - > line , tmpelem . val . name ) ;
2024-01-24 07:26:36 -06:00
}
2024-01-19 15:59:05 -06:00
2024-01-24 09:28:05 -06:00
switch ( e . type )
2024-01-18 11:16:36 -06:00
{
2024-01-24 09:28:05 -06:00
// This call should be done after all arguments are popped off the stack
case EE_FUNC :
{
2024-01-24 09:54:39 -06:00
/* fprintf(file,"\tcall %s\n",e.val.name); */
///* { */
///* tmpelem=(eval_elem){.type=EE_ACC,.val.i32=0}; */
///* vec_push(&stack,&tmpelem); */
///* } */
2024-01-24 09:28:05 -06:00
}
break ;
2024-01-22 10:43:57 -06:00
2024-01-24 09:28:05 -06:00
// Still not categorized as func or var
case EE_IDENT :
err_log ( " %u: undeclared identifier '%s' " , vec_at ( & pn - > tokens , 0 , Tok * ) - > line , e . val . name ) ;
break ;
2024-01-24 07:26:36 -06:00
2024-01-24 09:28:05 -06:00
case EE_VAR :
2024-02-02 08:23:49 -06:00
fprintf ( file , " \t %s %d(%%%s),%%%s \n " , gen - > ld . mov_wordsize , e . vstackloc , gen - > ld . bp , gen - > ld . acc_wordsize ) ;
2024-01-24 09:28:05 -06:00
break ;
2024-01-18 11:16:36 -06:00
2024-01-24 09:28:05 -06:00
default :
err_log ( " unrecognized eval_elem type \n " ) ;
break ;
2024-01-22 10:43:57 -06:00
}
2024-01-18 11:16:36 -06:00
2024-01-24 09:28:05 -06:00
}
// Parse function arglist eval_elems left on stack
if ( funarg_max > 0 )
{
if ( funarg_no < funarg_max )
2024-01-28 08:19:09 -06:00
{
if ( gen - > buildarch = = M_X86_64 )
2024-02-02 08:23:49 -06:00
fprintf ( file , " \t %s %%%s,%%%s \n " , gen - > ld . mov_wordsize , gen - > ld . acc_wordsize , gen - > ld . registers_abi_wordsize [ funarg_max - funarg_no - 1 ] ) ;
2024-01-28 08:19:09 -06:00
else if ( gen - > buildarch = = M_I386 )
2024-02-02 08:23:49 -06:00
fprintf ( file , " \t pushl %%%s \n " , gen - > ld . acc_wordsize ) ;
2024-01-28 08:19:09 -06:00
}
2024-01-24 09:54:39 -06:00
/* else */
/* { */
/* if(e.type==EE_FUNC) */
/* err_log("expression contains arglist with no function"); */
/* } */
2024-01-24 09:28:05 -06:00
+ + funarg_no ;
2024-01-18 11:16:36 -06:00
}
2024-01-24 09:28:05 -06:00
// End arglist mode
if ( funarg_max > 0 & & funarg_no > funarg_max )
funarg_max = 0 ;
if ( funarg_max > 0 & & funarg_no < = funarg_max )
goto eval_lastelem ;
2024-01-18 11:16:36 -06:00
}
vec_free ( & rpn_stack ) ;
vec_free ( & stack ) ;
}
2024-01-20 07:33:28 -06:00
// Evaluate one operation
void gen_evalop ( Gen * gen , PNode * pn , eval_elem * elem , size_t nops , Tok * curtok , FILE * file , Vec * stack )
{
2024-01-21 11:06:37 -06:00
bool push_elem = true ;
2024-01-20 11:11:04 -06:00
char operands [ 2 ] [ 1024 ] ;
2024-01-20 12:05:48 -06:00
char operator [ 1024 ] ;
char output_buffer [ 4096 ] ;
eval_elem tmpelem = { 0 } ;
size_t opos = 0 ;
2024-01-21 10:34:50 -06:00
uint32_t addrmode = 0 ;
2024-01-21 11:06:37 -06:00
uint32_t res = 0 ;
2024-01-20 07:33:28 -06:00
// TODO: refactor this function to be smarter,
// removing special cases and pendantic-ness
// Create strings of operands, operators
2024-01-20 12:05:48 -06:00
// Construct operand strings
2024-01-20 09:53:08 -06:00
{
// Create operand eval_elems
for ( size_t i = 0 ; i < nops ; + + i )
{
switch ( elem [ i ] . type )
{
2024-02-02 05:56:24 -06:00
case EE_VAR : sprintf ( operands [ i ] , " %d(%%%s) " , elem [ i ] . vstackloc , gen - > ld . bp ) ; break ;
2024-01-20 11:11:04 -06:00
case EE_FUNC : sprintf ( operands [ i ] , " %s " , elem [ i ] . val . name ) ; break ;
case EE_IDENT : sprintf ( operands [ i ] , " %s " , elem [ i ] . val . name ) ; break ;
case EE_I32 : sprintf ( operands [ i ] , " $%d " , elem [ i ] . val . i32 ) ; break ;
2024-02-02 08:23:49 -06:00
case EE_ACC : sprintf ( operands [ i ] , " %%%s " , gen - > ld . acc_wordsize ) ; break ;
2024-01-20 11:11:04 -06:00
//ERROR
//default: sprintf(operands[i],"???"); break;
2024-01-20 09:53:08 -06:00
}
}
/* if(nops>1&&elem[0].type==EE_I32&&elem[1].type==EE_I32) */
/* printf("[[[%d+%d=%d]]]\n",elem[1].val.i32,elem[0].val.i32,elem[1].val.i32+elem[0].val.i32); */
// Convert operator name to instruction name
2024-01-21 08:54:09 -06:00
if ( curtok - > subtype = = LADD )
2024-02-02 08:23:49 -06:00
sprintf ( operator , " %s " , gen - > ld . add_wordsize ) ;
2024-01-21 08:54:09 -06:00
else if ( curtok - > subtype = = LSMINUS )
2024-02-02 08:23:49 -06:00
sprintf ( operator , " %s " , gen - > ld . sub_wordsize ) ;
2024-01-21 08:54:09 -06:00
else if ( curtok - > subtype = = LSMUL )
2024-02-02 08:23:49 -06:00
sprintf ( operator , " %s " , gen - > ld . mul_wordsize ) ;
2024-01-21 08:54:09 -06:00
else if ( curtok - > subtype = = LSDIV )
2024-02-02 08:23:49 -06:00
sprintf ( operator , " %s " , gen - > ld . div_wordsize ) ;
2024-01-21 08:54:09 -06:00
else if ( curtok - > subtype = = LASSIGN )
2024-02-02 08:23:49 -06:00
sprintf ( operator , " %s " , gen - > ld . mov_wordsize ) ;
2024-01-29 21:04:49 -06:00
else if ( curtok - > subtype = = LSREF )
2024-02-02 05:56:24 -06:00
sprintf ( operator , " %s " , gen - > ld . lea_wordsize ) ;
2024-01-30 12:16:12 -06:00
else if ( curtok - > subtype = = LSDEREF )
2024-02-02 08:23:49 -06:00
sprintf ( operator , " %s " , gen - > ld . mov_wordsize ) ;
2024-01-20 09:53:08 -06:00
// Print output
2024-01-20 11:11:04 -06:00
if ( gen - > showeval )
{
if ( nops > 1 )
printf ( " %s %s, %s \n " , operator , operands [ 0 ] , operands [ 1 ] ) ;
else
printf ( " %s %s \n " , operator , operands [ 0 ] ) ;
// Move result to accumulator
if ( elem [ 1 ] . type ! = EE_ACC )
2024-02-02 08:23:49 -06:00
printf ( " %s %s, %s \n " , gen - > ld . mov_wordsize , operands [ 0 ] , operands [ 1 ] ) ;
2024-01-20 11:11:04 -06:00
}
2024-01-20 09:53:08 -06:00
}
2024-01-20 07:33:28 -06:00
2024-01-21 08:54:09 -06:00
// Set up for multiply/divide instructions
if ( curtok - > subtype = = LSDIV | | curtok - > subtype = = LSMUL )
2024-02-04 11:11:09 -06:00
{
/* if(!((elem[0].type==EE_I32)&&(elem[0].type==EE_I32))) */
{
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %%%s,%%%s \n " , gen - > ld . xor_wordsize , gen - > ld . registers_abi_wordsize [ 2 ] , gen - > ld . registers_abi_wordsize [ 2 ] ) ;
2024-02-04 11:11:09 -06:00
}
}
2024-01-21 08:54:09 -06:00
2024-01-21 10:34:50 -06:00
// Set up addressing mode
addrmode = AM ( elem [ 0 ] . type , elem [ 1 ] . type ) ;
/* printf("addrmode: %x (%x) (%x)\n",addrmode,elem[0].type,elem[1].type); */
2024-01-20 07:33:28 -06:00
// UNARY OPS
if ( nops = = 1 )
{
2024-01-21 08:09:30 -06:00
switch ( curtok - > subtype )
2024-01-20 07:33:28 -06:00
{
2024-01-29 21:04:49 -06:00
2024-01-21 08:09:30 -06:00
case LSNOT :
2024-01-21 09:11:42 -06:00
switch ( elem [ 0 ] . type )
2024-01-20 07:33:28 -06:00
{
2024-01-21 11:06:37 -06:00
case EE_VAR :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s $0,%s \n " , gen - > ld . cmp_wordsize , operands [ 0 ] ) ;
2024-01-21 11:06:37 -06:00
break ;
case EE_I32 :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 0 ] , gen - > ld . acc_wordsize ) ;
opos + = sprintf ( output_buffer + opos , " \t %s $0,%%%s \n " , gen - > ld . cmp_wordsize , gen - > ld . acc_wordsize ) ;
2024-01-21 11:06:37 -06:00
break ;
case EE_ACC :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s $0,%%%s \n " , gen - > ld . cmp_wordsize , gen - > ld . acc_wordsize ) ;
2024-01-21 11:06:37 -06:00
break ;
2024-01-20 07:33:28 -06:00
}
2024-01-21 11:06:37 -06:00
opos + = sprintf ( output_buffer + opos , " \t sete %%al \n " ) ;
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t movzbl %%al,%%%s \n " , gen - > ld . acc_wordsize ) ;
2024-01-21 11:06:37 -06:00
tmpelem = ( eval_elem ) { . type = EE_ACC , . val = { 0 } } ;
2024-01-20 07:33:28 -06:00
break ;
2024-01-29 21:04:49 -06:00
// Create reference from var
case LSREF :
switch ( elem [ 0 ] . type )
{
case EE_VAR :
2024-02-02 05:56:24 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , operator , operands [ 0 ] , gen - > ld . scratch1_wordsize ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %%%s,%%%s \n " , gen - > ld . mov_wordsize , gen - > ld . scratch1_wordsize , gen - > ld . acc_wordsize ) ;
2024-01-29 21:04:49 -06:00
break ;
default :
err_log ( " %u: cannot take reference of '%s' " , vec_at ( & pn - > tokens , 0 , Tok * ) - > line , operands [ 0 ] ) ;
break ;
}
tmpelem = ( eval_elem ) { . type = EE_ACC , . val = { 0 } } ;
break ;
2024-01-30 12:16:12 -06:00
// Dereference
case LSDEREF :
switch ( elem [ 0 ] . type )
{
2024-02-01 08:37:08 -06:00
default :
/* FALL THROUGH */
2024-01-30 12:16:12 -06:00
case EE_VAR :
2024-02-02 05:56:24 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 0 ] , gen - > ld . scratch1_wordsize ) ;
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s (%%%s),%%%s \n " , operator , gen - > ld . scratch1_wordsize , gen - > ld . acc_wordsize ) ;
2024-01-30 12:16:12 -06:00
break ;
}
tmpelem = ( eval_elem ) { . type = EE_ACC , . val = { 0 } } ;
break ;
2024-01-20 07:33:28 -06:00
}
2024-01-29 21:04:49 -06:00
if ( push_elem )
vec_push ( stack , & tmpelem ) ;
fwrite ( output_buffer , 1 , opos , file ) ;
2024-01-20 07:33:28 -06:00
}
2024-01-21 11:14:20 -06:00
// TWO OPERANDS -------------------------------
2024-01-21 10:53:53 -06:00
// (or more [funcs])
2024-01-21 10:41:23 -06:00
else if ( nops > 1 )
2024-01-20 07:33:28 -06:00
{
2024-01-21 10:41:23 -06:00
switch ( addrmode )
2024-01-20 07:33:28 -06:00
{
2024-01-21 10:53:53 -06:00
// INT INT
2024-01-21 10:41:23 -06:00
case AM ( EE_I32 , EE_I32 ) :
{
switch ( curtok - > subtype )
{
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
case LADD : res = elem [ 1 ] . val . i32 + elem [ 0 ] . val . i32 ; break ;
case LSMINUS : res = elem [ 1 ] . val . i32 - elem [ 0 ] . val . i32 ; break ;
case LSMUL : res = elem [ 1 ] . val . i32 * elem [ 0 ] . val . i32 ; break ;
case LSDIV : res = elem [ 1 ] . val . i32 / elem [ 0 ] . val . i32 ; break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
}
tmpelem = ( eval_elem ) { . type = EE_I32 , . val . i32 = res } ;
}
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:53:53 -06:00
// INT ACC
// ACC INT
2024-01-21 10:41:23 -06:00
case AM ( EE_I32 , EE_ACC ) :
case AM ( EE_ACC , EE_I32 ) :
{
tmpelem = ( eval_elem ) { . type = EE_ACC , . val = { 0 } } ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
if ( elem [ 0 ] . type = = EE_I32 )
{
eval_elem etmp = elem [ 0 ] ;
elem [ 0 ] = elem [ 1 ] ;
elem [ 1 ] = etmp ;
char btmp [ 64 ] = { 0 } ;
strcpy ( btmp , operands [ 0 ] ) ;
strcpy ( operands [ 0 ] , operands [ 1 ] ) ;
strcpy ( operands [ 1 ] , btmp ) ;
}
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
switch ( curtok - > subtype )
{
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
case LASSIGN :
err_log ( " %u: cannot assign to rvalue '%d' " , vec_at ( & pn - > tokens , 0 , Tok * ) - > line , operands [ 1 ] ) ;
2024-01-21 11:06:37 -06:00
push_elem = false ;
2024-01-21 10:41:23 -06:00
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
case LADD :
case LSMINUS :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , operator , operands [ 1 ] , gen - > ld . acc_wordsize ) ;
2024-01-21 10:41:23 -06:00
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
case LSMUL :
case LSDIV :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 1 ] , gen - > ld . scratch1_wordsize ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %%%s \n " , operator , gen - > ld . scratch1_wordsize ) ;
2024-01-21 10:41:23 -06:00
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
}
}
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:53:53 -06:00
// INT VAR
2024-01-21 10:41:23 -06:00
case AM ( EE_VAR , EE_I32 ) :
{
tmpelem = ( eval_elem ) { . type = EE_ACC , . val = { 0 } } ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
switch ( curtok - > subtype )
{
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
case LASSIGN :
err_log ( " %u: cannot assign to rvalue '%s' " , vec_at ( & pn - > tokens , 0 , Tok * ) - > line , operands [ 1 ] ) ;
2024-01-21 11:06:37 -06:00
push_elem = false ;
2024-01-21 10:41:23 -06:00
break ;
case LADD :
case LSMINUS :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 1 ] , gen - > ld . acc_wordsize ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , operator , operands [ 0 ] , gen - > ld . acc_wordsize ) ;
2024-01-21 10:41:23 -06:00
break ;
case LSMUL :
case LSDIV :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 1 ] , gen - > ld . scratch1_wordsize ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 0 ] , gen - > ld . acc_wordsize ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %%%s \n " , operator , gen - > ld . scratch1_wordsize ) ;
2024-01-21 10:41:23 -06:00
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
}
}
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:53:53 -06:00
// VAR INT
2024-01-21 10:41:23 -06:00
case AM ( EE_I32 , EE_VAR ) :
{
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
tmpelem = ( eval_elem ) { . type = EE_ACC , . val = { 0 } } ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
switch ( curtok - > subtype )
{
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
case LASSIGN :
opos + = sprintf ( output_buffer + opos , " \t %s %s,%s \n " , operator , operands [ 0 ] , operands [ 1 ] ) ;
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 0 ] , gen - > ld . acc_wordsize ) ;
2024-01-21 10:41:23 -06:00
break ;
case LADD :
case LSMINUS :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 1 ] , gen - > ld . acc_wordsize ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , operator , operands [ 0 ] , gen - > ld . acc_wordsize ) ;
2024-01-21 10:41:23 -06:00
break ;
case LSMUL :
case LSDIV :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 0 ] , gen - > ld . scratch1_wordsize ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 1 ] , gen - > ld . acc_wordsize ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %%%s \n " , operator , gen - > ld . scratch1_wordsize ) ;
2024-01-21 10:41:23 -06:00
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
}
}
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:53:53 -06:00
// VAR VAR
2024-01-21 10:41:23 -06:00
case AM ( EE_VAR , EE_VAR ) :
{
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
tmpelem = ( eval_elem ) { . type = EE_ACC , . val = { 0 } } ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
switch ( curtok - > subtype )
{
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
case LASSIGN :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %%%s,%s \n " , operator , gen - > ld . acc_wordsize , operands [ 1 ] ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 0 ] , gen - > ld . acc_wordsize ) ;
2024-01-21 10:41:23 -06:00
break ;
case LADD :
case LSMINUS :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 1 ] , gen - > ld . acc_wordsize ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , operator , operands [ 0 ] , gen - > ld . acc_wordsize ) ;
2024-01-21 10:41:23 -06:00
break ;
case LSMUL :
case LSDIV :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 1 ] , gen - > ld . acc_wordsize ) ;
2024-01-21 10:41:23 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s \n " , operator , operands [ 0 ] ) ;
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
}
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
}
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:53:53 -06:00
// VAR ACC
2024-01-21 10:41:23 -06:00
case AM ( EE_VAR , EE_ACC ) :
{
tmpelem = ( eval_elem ) { . type = EE_ACC , . val = { 0 } } ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
switch ( curtok - > subtype )
{
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
case LASSIGN :
case LADD :
case LSMINUS :
opos + = sprintf ( output_buffer + opos , " \t %s %s,%s \n " , operator , operands [ 0 ] , operands [ 1 ] ) ;
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
case LSMUL :
case LSDIV :
opos + = sprintf ( output_buffer + opos , " \t %s %s \n " , operator , operands [ 0 ] ) ;
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
}
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
}
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:53:53 -06:00
// ACC VAR
2024-01-21 10:41:23 -06:00
case AM ( EE_ACC , EE_VAR ) :
{
tmpelem = ( eval_elem ) { . type = EE_ACC , . val = { 0 } } ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
switch ( curtok - > subtype )
{
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
case LASSIGN :
opos + = sprintf ( output_buffer + opos , " \t %s %s,%s \n " , operator , operands [ 0 ] , operands [ 1 ] ) ;
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
case LADD :
opos + = sprintf ( output_buffer + opos , " \t %s %s,%s \n " , operator , operands [ 1 ] , operands [ 0 ] ) ;
break ;
2024-01-20 07:33:28 -06:00
2024-01-28 07:04:43 -06:00
case LSMINUS :
2024-02-02 08:23:49 -06:00
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%%s \n " , gen - > ld . mov_wordsize , operands [ 0 ] , gen - > ld . scratch1_wordsize ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %s,%s \n " , gen - > ld . mov_wordsize , operands [ 1 ] , operands [ 0 ] ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %%%s,%s \n " , gen - > ld . sub_wordsize , gen - > ld . scratch1_wordsize , operands [ 0 ] ) ;
2024-01-28 07:04:43 -06:00
break ;
2024-01-21 10:41:23 -06:00
case LSMUL :
case LSDIV :
opos + = sprintf ( output_buffer + opos , " \t %s %s \n " , operator , operands [ 1 ] ) ;
break ;
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
}
2024-01-20 07:33:28 -06:00
2024-01-21 10:41:23 -06:00
}
break ;
2024-01-20 07:33:28 -06:00
}
2024-01-21 11:06:37 -06:00
if ( push_elem )
vec_push ( stack , & tmpelem ) ;
2024-01-21 10:41:23 -06:00
fwrite ( output_buffer , 1 , opos , file ) ;
2024-01-20 12:05:48 -06:00
2024-01-21 10:41:23 -06:00
}
2024-01-20 07:33:28 -06:00
}