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
void gen_setrootnode ( Gen * gen , PNode * rootnode )
{
if ( ! gen | | ! rootnode ) return ;
gen - > rootnode = rootnode ;
}
2024-01-12 17:16:49 -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 ;
}
/* static void gen_print_string(Gen*gen,const PNode*pn,FILE*file,const Str*str) */
/* { */
/* if(!gen)return; */
/* if(!pn)return; */
/* if(!file)return; */
/* if(!str)return; */
/* */
/* for(size_t i=0;i<str->size;++i) */
/* { */
/* switch(str->buffer[i]) */
/* { */
/* */
/* // Escape codes */
/* case '\\': */
/* if(i<str->size-1) */
/* { */
/* switch(str->buffer[i+1]) */
/* { */
/* case 'n':fputc('\n',file);++i;break; */
/* case 't':fputc('\t',file);++i;break; */
/* case '"':fputc('"',file);++i;break; */
/* case '\\':fputc('\\',file);++i;break; */
/* } */
/* } */
/* break; */
/* */
/* default: */
/* fputc(str->buffer[i],file); */
/* break; */
/* */
/* } */
/* } */
/* fprintf(file,"\n"); */
/* } */
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 )
{
if ( pn - > tokens . size > 1 )
{
if ( vec_at ( & pn - > tokens , 1 , const Tok * ) - > type ! = LOPERATOR | | ( strcmp ( vec_at ( & pn - > tokens , 1 , const Tok * ) - > str . buffer , " = " ) ) )
{
2024-01-14 02:47:52 -06:00
err_log ( " %u: expected either ';' 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 ;
}
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 ;
}
}
if ( pn - > tokens . size > 0 )
{
gen - > stackptr - > stacksize + = 4 ;
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-12 19:48:31 -06:00
/* .location=STACK, */
/* .regnum=0, */
. stackloc = gen - > stackptr - > stacksize ,
} ;
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 ) ;
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 19:48:31 -06:00
} ;
vec_push ( ( Vec * ) & gen - > rootnode - > funcs , & func ) ;
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
{
/* bool found=false; */
for ( size_t i = 2 ; i < pn - > tokens . 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); */
/* found=true; */
/* break; */
/* } */
/* if(!found) */
if ( vec_at ( & pn - > tokens , i , const Tok * ) - > type = = LIDENTIFIER )
{
stacksize + = 4 ;
/* printf("push '%s' to %p\n",vec_at(&pn->tokens,i,const Tok*)->str.buffer, */
/* gen->stackptr); */
Var var = {
. name = vec_at ( & pn - > tokens , i , const Tok * ) - > str . buffer ,
. is_arg = true ,
. stackloc = stacksize ,
} ;
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 ) ;
switch ( gen - > buildarch )
{
case M_I386 :
pn - > stacksize + = stacksize ;
2024-01-12 21:49:15 -06:00
stacksize + = gen_stacksize ( 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-01-12 21:49:15 -06:00
stacksize + = gen_stacksize ( pn ) ;
2024-01-12 21:32:42 -06:00
/* gen_x86_64_prolog(pn,file,stacksize); */
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
/* gen_x86_64_epilog(pn,file); */
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 )
{
// TODO: Find function names here and
// evaluate (?) its arglist
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-01-13 10:47:17 -06:00
// Abstraction for different buildarches
2024-01-24 10:14:15 -06:00
LangDef ld = ( gen - > buildarch = = M_X86_64 ) ? gen_x86_64_langdef ( ) : gen_i386_langdef ( ) ;
2024-01-12 21:32:42 -06:00
2024-01-20 06:59:00 -06:00
fprintf ( file , " \t %s %%%s \n " , ld . push_wordsize , ld . bp ) ;
2024-01-12 21:32:42 -06:00
if ( gen - > buildarch = = M_X86_64 )
2024-01-20 06:59:00 -06:00
fprintf ( file , " \t %s %%%s \n " , ld . push_wordsize , ld . registers_abi_wordsize [ 2 ] ) ;
fprintf ( file , " \t %s %%%s,%%%s \n " , ld . mov_wordsize , ld . sp , ld . bp ) ;
2024-01-16 21:38:20 -06:00
if ( stacksize > 0 )
2024-01-20 06:59:00 -06:00
fprintf ( file , " \t %s $%lu,%%%s \n " , ld . sub_wordsize , stacksize , 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 )
for ( size_t i = 0 , j = pn - > vars . size - 1 ; i < pn - > vars . size ; + + i , - - j )
2024-01-20 06:59:00 -06:00
if ( i < 6 & & vec_at ( & pn - > vars , i , Var * ) - > is_arg )
2024-01-24 10:14:15 -06:00
fprintf ( file , " \t %s %%%s,-%lu(%%%s) \n " , ld . mov_32 , ld . registers_abi_32 [ j ] , vec_at ( & pn - > vars , i , Var * ) - > stackloc , 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-01-13 10:47:17 -06:00
// Abstraction for different buildarches
2024-01-24 10:14:15 -06:00
LangDef ld = ( gen - > buildarch = = M_X86_64 ) ? gen_x86_64_langdef ( ) : gen_i386_langdef ( ) ;
2024-01-12 21:32:42 -06:00
2024-01-20 06:59:00 -06:00
fprintf ( file , " \t %s %%%s,%%%s \n " , ld . mov_wordsize , ld . bp , ld . sp ) ;
2024-01-12 21:32:42 -06:00
if ( gen - > buildarch = = M_X86_64 )
2024-01-20 06:59:00 -06:00
fprintf ( file , " \t %s %%%s \n " , ld . pop_wordsize , ld . registers_abi_wordsize [ 2 ] ) ;
fprintf ( file , " \t %s %%%s \n " , ld . pop_wordsize , ld . bp ) ;
2024-01-12 21:32:42 -06:00
}
2024-01-12 21:49:15 -06:00
size_t gen_stacksize ( const PNode * pn )
{
size_t stacksize = 0 ;
if ( pn - > pnodes . size = = 0 )
{
if ( pn - > type = = PVARDECL )
return stacksize + sizeof ( uint32_t ) ;
else return 0 ;
}
for ( size_t i = 0 ; i < pn - > pnodes . size ; + + i )
stacksize + = gen_stacksize ( vec_at ( & pn - > pnodes , i , PNode * ) ) ;
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
fprintf ( file , " \t movl -%s,%%eax \n " , vec_at ( & pn - > tokens , 1 , const Tok * ) - > str . buffer ) ;
}
/* 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-01-12 21:49:15 -06:00
fprintf ( file , " \t cmpl $0,%%eax \n " ) ;
}
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-01-12 21:49:15 -06:00
fprintf ( file , " \t cmpl $0,%%eax \n " ) ;
}
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 } ;
precedence [ ' ( ' ] = 5 ;
precedence [ ' ) ' ] = 5 ;
precedence [ ' + ' ] = 10 ;
precedence [ ' - ' ] = 10 ;
precedence [ ' ! ' ] = 10 ;
precedence [ ' * ' ] = 20 ;
precedence [ ' / ' ] = 20 ;
2024-01-22 16:49:49 -06:00
precedence [ ' , ' ] = 25 ;
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
while ( operators . size > 0 & & precedence [ ( uint32_t ) vec_at ( & operators , operators . size - 1 , const Tok * ) - > str . buffer [ 0 ] ] > = precedence [ ( uint32_t ) vec_at ( tokens , i , const Tok * ) - > str . buffer [ 0 ] ] )
{
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 07:33:28 -06:00
LangDef ld = ( gen - > buildarch = = M_X86_64 ) ? ( gen_x86_64_langdef ( ) ) : ( gen_i386_langdef ( ) ) ;
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-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
if ( stack . size > 1 )
{
eval_elem elem [ 2 ] = { { 0 } } ;
size_t nops = 2 ; // 2 unless unary operator
2024-01-22 16:01:01 -06:00
if ( vec_at ( & rpn_stack , i , const Tok * ) - > subtype = = LSNOT )
nops = 1 ;
if ( vec_at ( & rpn_stack , i , const Tok * ) - > subtype = = LSCOMMA )
2024-01-24 07:26:36 -06:00
nops = 0 ;
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
// TODO: Something is going wrong with copying this eval_elem
// when it is the last elem and it is an EE_FUNC
eval_elem e = * ( vec_at ( & stack , stack . size - 1 , eval_elem * ) ) ;
if ( funarg_max > 0 & & funarg_no = = funarg_max & & e . type = = EE_FUNC )
fprintf ( file , " \t call %s \n " , e . val . name ) ;
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 ;
fprintf ( file , " \t movl $%d,%%eax \n " , value ) ;
}
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 :
fprintf ( file , " \t movl -%lu(%%%s),%%eax \n " , e . vstackloc , ld . bp ) ;
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 )
fprintf ( file , " \t movl %%eax,%%%s \n " , ld . registers_abi_32 [ funarg_no ] ) ;
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 )
{
LangDef ld = ( gen - > buildarch = = M_X86_64 ) ? gen_x86_64_langdef ( ) : gen_i386_langdef ( ) ;
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-01-20 11:11:04 -06:00
case EE_VAR : sprintf ( operands [ i ] , " -%lu(%%%s) " , elem [ i ] . vstackloc , ld . bp ) ; break ;
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 ;
case EE_ACC : sprintf ( operands [ i ] , " %%eax " ) ; break ;
//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-01-20 11:11:04 -06:00
sprintf ( operator , " addl " ) ;
2024-01-21 08:54:09 -06:00
else if ( curtok - > subtype = = LSMINUS )
2024-01-20 11:11:04 -06:00
sprintf ( operator , " subl " ) ;
2024-01-21 08:54:09 -06:00
else if ( curtok - > subtype = = LSMUL )
2024-01-20 11:11:04 -06:00
sprintf ( operator , " imull " ) ;
2024-01-21 08:54:09 -06:00
else if ( curtok - > subtype = = LSDIV )
2024-01-20 11:11:04 -06:00
sprintf ( operator , " idivl " ) ;
2024-01-21 08:54:09 -06:00
else if ( curtok - > subtype = = LASSIGN )
2024-01-20 11:11:04 -06:00
sprintf ( operator , " movl " ) ;
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-01-21 09:11:42 -06:00
printf ( " %s %s, %s \n " , ld . mov_32 , 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 )
{
if ( ! ( elem [ 0 ] . type = = EE_I32 & & elem [ 0 ] . type = = EE_I32 ) )
{
opos + = sprintf ( output_buffer + opos , " \t xorl %%edx,%%edx \n " ) ;
/* opos+=sprintf(output_buffer+opos,"\tmovl %s,%%%s\n",operands[1],ld.scratch1); */
}
}
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-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 :
opos + = sprintf ( output_buffer + opos , " \t cmpl $0,%s \n " , operands [ 0 ] ) ;
break ;
case EE_I32 :
opos + = sprintf ( output_buffer + opos , " \t movl $%s,%%eax \n " , operands [ 0 ] ) ;
opos + = sprintf ( output_buffer + opos , " \t cmpl $0,%%eax \n " ) ;
break ;
case EE_ACC :
opos + = sprintf ( output_buffer + opos , " \t cmpl $0,%%eax \n " ) ;
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 " ) ;
opos + = sprintf ( output_buffer + opos , " \t movzbl %%al,%%eax \n " ) ;
tmpelem = ( eval_elem ) { . type = EE_ACC , . val = { 0 } } ;
2024-01-20 07:33:28 -06:00
break ;
}
}
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 :
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%eax \n " , operator , 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 movl %s,%%%s \n " , operands [ 1 ] , ld . scratch1 ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %%%s \n " , operator , ld . scratch1 ) ;
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-01-26 05:24:38 -06:00
opos + = sprintf ( output_buffer + opos , " \t movl %s,%%eax \n " , operands [ 1 ] ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%eax \n " , operator , operands [ 0 ] ) ;
2024-01-21 10:41:23 -06:00
break ;
case LSMUL :
case LSDIV :
opos + = sprintf ( output_buffer + opos , " \t movl %s,%%%s \n " , operands [ 1 ] , ld . scratch1 ) ;
opos + = sprintf ( output_buffer + opos , " \t movl %s,%%eax \n " , operands [ 0 ] ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %%%s \n " , operator , ld . scratch1 ) ;
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 ] ) ;
opos + = sprintf ( output_buffer + opos , " \t movl %s,%%eax \n " , operands [ 0 ] ) ;
break ;
case LADD :
case LSMINUS :
opos + = sprintf ( output_buffer + opos , " \t movl %s,%%eax \n " , operands [ 1 ] ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%eax \n " , operator , operands [ 0 ] ) ;
break ;
case LSMUL :
case LSDIV :
opos + = sprintf ( output_buffer + opos , " \t movl %s,%%%s \n " , operands [ 0 ] , ld . scratch1 ) ;
opos + = sprintf ( output_buffer + opos , " \t movl %s,%%eax \n " , operands [ 1 ] ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %%%s \n " , operator , ld . scratch1 ) ;
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 :
opos + = sprintf ( output_buffer + opos , " \t %s %%eax,%s \n " , operator , operands [ 1 ] ) ;
2024-01-21 10:53:53 -06:00
opos + = sprintf ( output_buffer + opos , " \t movl %s,%%eax \n " , operands [ 0 ] ) ;
2024-01-21 10:41:23 -06:00
break ;
case LADD :
case LSMINUS :
opos + = sprintf ( output_buffer + opos , " \t movl %s,%%eax \n " , operands [ 1 ] ) ;
opos + = sprintf ( output_buffer + opos , " \t %s %s,%%eax \n " , operator , operands [ 0 ] ) ;
break ;
case LSMUL :
case LSDIV :
opos + = sprintf ( output_buffer + opos , " \t movl %s,%%eax \n " , operands [ 1 ] ) ;
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 :
case LSMINUS :
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-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
}