gen_eval, remove gen_x86_64_eval

This commit is contained in:
corey 2024-01-18 11:16:36 -06:00
parent 07bc6a1461
commit a0f722750f
5 changed files with 603 additions and 620 deletions

661
gen.c
View File

@ -219,20 +219,7 @@ void gen_declare_variable(Gen*gen,PNode*pn,FILE*file)
// Evaluate initialization expression
if(pn->tokens.size>1)
{
switch(gen->buildarch)
{
case M_I386:
gen_i386_eval(gen,pn,file);
break;
case M_X86_64:
gen_x86_64_eval(gen,pn,file);
break;
}
}
gen_eval(gen,pn,file);
}
}
@ -523,20 +510,7 @@ void gen_code(Gen*gen,PNode*pn,FILE*file)
/* err_log("%u: returning non-integer",vec_at(&pn->tokens,0,const Tok*)->line); */
/* } */
else
{
switch(gen->buildarch)
{
case M_I386:
gen_i386_eval(gen,pn,file);
break;
case M_X86_64:
gen_x86_64_eval(gen,pn,file);
break;
}
}
gen_eval(gen,pn,file);
}
gen_epilog(gen,pn,file);
fprintf(file,"\tret\n");
@ -554,18 +528,7 @@ void gen_code(Gen*gen,PNode*pn,FILE*file)
case PIF:
if(pn->tokens.size>1)
{
switch(gen->buildarch)
{
case M_I386:
gen_i386_eval(gen,pn,file);
break;
case M_X86_64:
gen_x86_64_eval(gen,pn,file);
break;
}
gen_eval(gen,pn,file);
fprintf(file,"\tcmpl $0,%%eax\n");
}
size_t labelno_cache=gen->labelno;
@ -586,18 +549,7 @@ void gen_code(Gen*gen,PNode*pn,FILE*file)
fprintf(file,".L%02lu:\n",pwhile_label1);
if(pn->tokens.size>1)
{
switch(gen->buildarch)
{
case M_I386:
gen_i386_eval(gen,pn,file);
break;
case M_X86_64:
gen_x86_64_eval(gen,pn,file);
break;
}
gen_eval(gen,pn,file);
fprintf(file,"\tcmpl $0,%%eax\n");
}
@ -679,18 +631,7 @@ void gen_code(Gen*gen,PNode*pn,FILE*file)
case PEXPRESSION:
default:
switch(gen->buildarch)
{
case M_I386:
gen_i386_eval(gen,pn,file);
break;
case M_X86_64:
gen_x86_64_eval(gen,pn,file);
break;
}
gen_eval(gen,pn,file);
if(pn->tokens.size>0)
{
fprintf(file,";#PNODE ID: %s ",partype_names[pn->type]);
@ -707,3 +648,595 @@ void gen_code(Gen*gen,PNode*pn,FILE*file)
//for(size_t i=0;i<pn->pnodes.size;++i)
//gen_code(gen,vec_at(&pn->pnodes,i,PNode*),file);
}
// Convert to infix, then evaluate
void gen_eval(Gen*gen,const PNode*pn,FILE*file)
{
if(gen->buildarch==M_I386)
{
gen_i386_eval(gen,pn,file);
return;
}
Vec rpn_stack={0};
Vec stack=vec_new(sizeof(eval_elem));
rpn_stack=gen_i2r(&pn->tokens);
if(gen->showrpn)vec_print_tokens(&rpn_stack);
/* 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)
{
eval_elem e={.type=EI32,.val.i32=1};
vec_push(&stack,&e);
}
else if(strcmp("false",vec_at(&rpn_stack,i,const Tok*)->str.buffer)==0)
{
eval_elem e={.type=EI32,.val.i32=0};
vec_push(&stack,&e);
}
}
break;
case LIDENTIFIER:
{
eval_elem e={.type=EIDENT,.val.name=vec_at(&rpn_stack,i,const Tok*)->str.buffer};
vec_push(&stack,&e);
}
break;
case LINTEGER:
case LFLOAT:
{
int32_t d=atoi(vec_at(&rpn_stack,i,const Tok*)->str.buffer);
eval_elem e={.type=EI32,.val.i32=d};
vec_push(&stack,&e);
}
break;
case LOPERATOR:
// Get operands
if(stack.size>1)
{
eval_elem elem[2]={{0}};
int32_t integers[2]={0};
int32_t res=0;
/* size_t var_stackloc[2]={0}; */
size_t nops=2; // 2 unless unary operator
//if(vec_at(&rpn_stack,i,const Tok*)->str.buffer[0]=='!')
if(strcmp("!",vec_at(&rpn_stack,i,const Tok*)->str.buffer)==0)
nops=1;
// 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);
if(elem[k].type==EIDENT)
{
bool found=false;
// Identify functions
for(size_t j=0;j<gen->rootnode->funcs.size;++j)
{
if(strcmp(vec_at(&gen->rootnode->funcs,j,Func*)->name,elem[k].val.name)==0)
{
elem[k].type=EFUNC;
fprintf(file,"\tcall %s\n",elem[k].val.name);
{
eval_elem e={.type=EACC,.val.i32=0};
vec_push(&stack,&e);
--k;
}
found=true;
break;
}
}
// Identify variables
if(!found)
{
for(size_t j=0;j<gen->stackptr->vars.size;++j)
{
if(strcmp(vec_at(&gen->stackptr->vars,j,Var*)->name,elem[k].val.name)==0)
{
elem[k].type=EVAR;
elem[k].vstackloc=vec_at(&gen->stackptr->vars,j,Var*)->stackloc;
elem[k].vtype=vec_at(&gen->stackptr->vars,j,Var*)->type;
//var_stackloc[k]=vec_at(&gen->stackptr->vars,j,Var*)->stackloc;
found=true;
break;
}
}
if(!found)
err_log("%u: undeclared identifier '%s'",vec_at(&pn->tokens,0,Tok*)->line,elem[k].val.name);
}
}
else if(elem[k].type==EI32)
integers[k]=elem[k].val.i32;
}
/* // Debugging output */
/* if(elem[1].type==EVAR) */
/* printf("'%s' ",elem[1].val.name); */
/* else if(elem[1].type==EI32) */
/* printf("%d ",elem[1].val.i32); */
/* else */
/* printf("acc "); */
/* printf("%s ",vec_at(&rpn_stack,i,Tok*)->str.buffer); */
/* if(elem[0].type==EVAR) */
/* printf("'%s' ",elem[0].val.name); */
/* else if(elem[0].type==EI32) */
/* printf("%d ",elem[0].val.i32); */
/* else */
/* printf("acc "); */
/* puts(""); */
// ----------------------------------------------------------
// Extra debugging output
if(elem[1].type==EVAR)
{
printf("'%s'(%u) ",elem[1].val.name,elem[1].vtype);
}
else if(elem[1].type==EI32)
{
printf("%d ",elem[1].val.i32);
}
else
{
printf("acc ");
}
printf("%s ",vec_at(&rpn_stack,i,Tok*)->str.buffer);
if(elem[0].type==EVAR)
{
printf("'%s'(%u) ",elem[0].val.name,elem[0].vtype);
}
else if(elem[0].type==EI32)
{
printf("%d ",elem[0].val.i32);
}
else
{
printf("acc ");
}
puts("");
// ----------------------------------------------------------
// UNARY OPS
if(nops==1)
{
switch(vec_at(&rpn_stack,i,const Tok*)->str.buffer[0])
{
case '!':
if(elem[0].type==EVAR)
{
fprintf(file,"\tcmpl $0,-%lu(%%%s)\n",elem[0].vstackloc,gen_x86_64_bp);
fprintf(file,"\tsete %%al\n");
fprintf(file,"\tmovzbl %%al,%%eax\n");
/* fprintf(file,"\tmovl %%eax,-%lu(%%%s)\n",elem[0].vstackloc,gen_x86_64_bp); */
eval_elem e={.type=EACC,.val={0}};
vec_push(&stack,&e);
}
else if(elem[0].type==EI32)
{
fprintf(file,"\tmovl $%d,%%eax\n",integers[0]);
fprintf(file,"\tcmpl $0,%%eax\n");
fprintf(file,"\tsete %%al\n");
fprintf(file,"\tmovzbl %%al,%%eax\n");
eval_elem e={.type=EACC,.val={0}};
vec_push(&stack,&e);
}
else if(elem[0].type==EACC)
{
fprintf(file,"\tcmpl $0,%%eax\n");
fprintf(file,"\tsete %%al\n");
fprintf(file,"\tmovzbl %%al,%%eax\n");
//fprintf(file,"\tmovl %%eax,-%lu(%%%s)\n",elem[0].vstackloc,gen_x86_64_bp);
eval_elem e={.type=EACC,.val={0}};
vec_push(&stack,&e);
}
break;
}
}
// INT OP INT
else if(elem[0].type==EI32&&elem[1].type==EI32)
{
switch(vec_at(&rpn_stack,i,const Tok*)->str.buffer[0])
{
case '+':res=integers[1]+integers[0];break;
case '-':res=integers[1]-integers[0];break;
case '*':res=integers[1]*integers[0];break;
case '/':res=integers[1]/integers[0];break;
}
eval_elem e={.type=EI32,.val.i32=res};
vec_push(&stack,&e);
}
// INT OP ACC
else if(
(elem[0].type==EACC && elem[1].type==EI32) ||
(elem[0].type==EI32 && elem[1].type==EACC)
)
{
eval_elem e={.type=EACC,.val={0}};
if(elem[0].type==EI32)
{
eval_elem etmp=elem[0];
elem[0]=elem[1];
elem[1]=etmp;
}
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
err_log("%u: cannot assign to rvalue '%d'",vec_at(&pn->tokens,0,Tok*)->line,elem[1].val.i32);
break;
case '+':
fprintf(file,"\taddl $%d,%%eax\n",elem[1].val.i32);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tsubl $%d,%%eax\n",elem[1].val.i32);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl $%d,%%%s\n",elem[1].val.i32,gen_x86_64_scratch1);
fprintf(file,"\timull %%%s\n",gen_x86_64_scratch1);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl $%d,%%%s\n",elem[1].val.i32,gen_x86_64_scratch1);
fprintf(file,"\tidiv %%%s\n",gen_x86_64_scratch1);
vec_push(&stack,&e);
break;
}
}
// INT OP IDENT
else if(elem[0].type==EVAR && elem[1].type==EI32)
{
eval_elem e={.type=EACC,.val={0}};
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
err_log("%u: cannot assign to rvalue '%d'",vec_at(&pn->tokens,0,Tok*)->line,elem[1].val.i32);
break;
case '+':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[0].vstackloc,gen_x86_64_bp);
fprintf(file,"\taddl $%d,%%eax\n",elem[1].val.i32);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[0].vstackloc,gen_x86_64_bp);
fprintf(file,"\tsubl $%d,%%eax\n",elem[1].val.i32);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[0].vstackloc,gen_x86_64_bp);
fprintf(file,"\tmovl $%d,%%%s\n",elem[1].val.i32,gen_x86_64_scratch1);
fprintf(file,"\timull %%%s\n",gen_x86_64_scratch1);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[0].vstackloc,gen_x86_64_bp);
fprintf(file,"\tmovl $%d,%%%s\n",elem[1].val.i32,gen_x86_64_scratch1);
fprintf(file,"\tidivl %%%s\n",gen_x86_64_scratch1);
vec_push(&stack,&e);
break;
}
}
// IDENT OP INT
else if(elem[0].type==EI32 && elem[1].type==EVAR)
{
eval_elem e={.type=EACC,.val={0}};
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
fprintf(file,"\tmovl $%d,-%lu(%%%s)\n",elem[0].val.i32,elem[1].vstackloc,gen_x86_64_bp);
fprintf(file,"\tmovl $%d,%%eax\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
case '+':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[1].vstackloc,gen_x86_64_bp);
fprintf(file,"\taddl $%d,%%eax\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[1].vstackloc,gen_x86_64_bp);
fprintf(file,"\tsubl $%d,%%eax\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[1].vstackloc,gen_x86_64_bp);
fprintf(file,"\tmovl $%d,%%%s\n",elem[0].val.i32,gen_x86_64_scratch1);
fprintf(file,"\timul %%%s\n",gen_x86_64_scratch1);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[1].vstackloc,gen_x86_64_bp);
fprintf(file,"\tmovl $%d,%%%s\n",elem[0].val.i32,gen_x86_64_scratch1);
fprintf(file,"\tidivl %%%s\n",gen_x86_64_scratch1);
vec_push(&stack,&e);
break;
}
}
// IDENT OP IDENT
else if(elem[0].type==EVAR && elem[1].type==EVAR)
{
eval_elem e={.type=EACC,.val={0}};
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[0].vstackloc,gen_x86_64_bp);
fprintf(file,"\tmovl %%eax,-%lu(%%%s)\n",elem[1].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '+':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[1].vstackloc,gen_x86_64_bp);
fprintf(file,"\taddl -%lu(%%%s),%%eax\n",elem[0].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[1].vstackloc,gen_x86_64_bp);
fprintf(file,"\tsubl -%lu(%%%s),%%eax\n",elem[0].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[1].vstackloc,gen_x86_64_bp);
fprintf(file,"\timull -%lu(%%%s)\n",elem[0].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",elem[1].vstackloc,gen_x86_64_bp);
fprintf(file,"\tidivl -%lu(%%%s)\n",elem[0].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
}
}
// IDENT OP ACC
else if(elem[1].type==EACC && elem[0].type==EVAR)
{
eval_elem e={.type=EACC,.val={0}};
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
fprintf(file,"\tmovl %%eax,-%lu(%%%s)\n",elem[0].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '+':
fprintf(file,"\taddl -%lu(%%%s),%%eax\n",elem[0].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tsubl -%lu(%%%s),%%eax\n",elem[0].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\timull -%lu(%%%s)\n",elem[0].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tidivl -%lu(%%%s)\n",elem[0].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
}
}
// I32 OP ACC
else if(elem[1].type==EACC && elem[0].type==EI32)
{
eval_elem e={.type=EACC,.val={0}};
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
err_log("%u: cannot assign to accumulator",vec_at(&pn->tokens,0,Tok*)->line,e.val.name);
/* vec_push(&stack,&e); */
break;
case '+':
fprintf(file,"\taddl $%d,%%eax\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tsubl $%d,%%eax\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\timull $%d\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tidivl $%d\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
}
}
// ACC OP IDENT
else if(elem[1].type==EVAR && elem[0].type==EACC)
{
eval_elem e={.type=EACC,.val={0}};
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
fprintf(file,"\tmovl %%eax,-%lu(%%%s)\n",elem[1].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '+':
fprintf(file,"\taddl -%lu(%%%s),%%eax\n",elem[1].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tsubl -%lu(%%%s),%%eax\n",elem[1].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\timull -%lu(%%%s)\n",elem[1].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tidivl -%lu(%%%s)\n",elem[1].vstackloc,gen_x86_64_bp);
vec_push(&stack,&e);
break;
}
}
}
break;
}
}
}
// Empty remaining variables/integers on the stack
if(stack.size>0)
{
eval_elem e=*vec_at(&stack,stack.size-1,eval_elem*);
int32_t value=0;
/* size_t var_stackloc=0; */
if(e.type==EI32)
{
value=e.val.i32;
fprintf(file,"\tmovl $%d,%%eax\n",value);
}
else if(e.type==EIDENT)
{
bool found=false;
// Identify functions
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=EFUNC;
fprintf(file,"\tcall %s\n",e.val.name);
found=true;
break;
}
}
// Identify variables
if(!found)
{
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=EVAR;
e.vtype=vec_at(&gen->stackptr->vars,j,Var*)->type;
e.vstackloc=vec_at(&gen->stackptr->vars,j,Var*)->stackloc;
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",e.vstackloc,gen_x86_64_bp);
found=true;
break;
}
}
if(!found)
err_log("%u: undeclared identifier '%s'",vec_at(&pn->tokens,0,Tok*)->line,e.val.name);
}
}
}
vec_free(&rpn_stack);
vec_free(&stack);
}

4
gen.h
View File

@ -27,6 +27,8 @@ enum EVAL_ELEM_TYPE {EI32,EIDENT,EVAR,EFUNC,EACC};
typedef struct eval_elem
{
size_t type;
VTYPE vtype;
size_t vstackloc;
union
{
int32_t i32;
@ -37,6 +39,7 @@ typedef struct eval_elem
/* static void gen_print_string(Gen*gen,const PNode*pn,FILE*file,const Str*str) */
Gen gen_new(void);
Vec gen_i2r(const Vec*tokens);
bool gen_findret(const PNode*pn,bool found);
size_t gen_stacksize(const PNode*pn);
void gen(Gen*gen,PNode*pn,FILE*file);
@ -44,6 +47,7 @@ void gen_code(Gen*gen,PNode*pn,FILE*file);
void gen_declare_function(Gen*gen,PNode*pn,FILE*file);
void gen_declare_variable(Gen*gen,PNode*pn,FILE*file);
void gen_epilog(Gen*gen,const PNode*pn,FILE*file);
void gen_eval(Gen*gen,const PNode*pn,FILE*file);
void gen_eval_analyze(const PNode*pn);
void gen_free(Gen*gen);
void gen_prolog(Gen*gen,const PNode*pn,FILE*file,size_t stacksize);

4
mem.h
View File

@ -7,7 +7,7 @@
#include"tok.h"
// Data types
typedef enum{I8,I16,I32,I64,U8,U16,U32,U64,U8P,U16P,U32P,U64P}VTYPE;
typedef enum{I8,I16,I32,I64,U8,U16,U32,U64,U8P,U16P,U32P,U64P,STR}VTYPE;
// Memory location
// "Where do I look to find this value?"
@ -40,7 +40,7 @@ typedef union Mem
typedef struct Var
{
char*name;
// VTYPE type;
VTYPE type;
// VLOC location;
// size_t regnum; // REG: which register?
bool is_arg; // Remember to move arg register to stack

552
x86_64.c
View File

@ -14,555 +14,3 @@ const char*const gen_x86_64_pop_wordsize="popq";
const char*const gen_x86_64_sp="rsp";
const char*const gen_x86_64_bp="rbp";
const char*const gen_x86_64_scratch1="r8d";
// Convert to infix, then evaluate
void gen_x86_64_eval(Gen*gen,const PNode*pn,FILE*file)
{
Vec rpn_stack={0};
Vec stack=vec_new(sizeof(eval_elem));
rpn_stack=gen_i2r(&pn->tokens);
if(gen->showrpn)vec_print_tokens(&rpn_stack);
/* 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)
{
eval_elem e={.type=EI32,.val.i32=1};
vec_push(&stack,&e);
}
else if(strcmp("false",vec_at(&rpn_stack,i,const Tok*)->str.buffer)==0)
{
eval_elem e={.type=EI32,.val.i32=0};
vec_push(&stack,&e);
}
}
break;
case LIDENTIFIER:
{
eval_elem e={.type=EIDENT,.val.name=vec_at(&rpn_stack,i,const Tok*)->str.buffer};
vec_push(&stack,&e);
}
break;
case LINTEGER:
case LFLOAT:
{
int32_t d=atoi(vec_at(&rpn_stack,i,const Tok*)->str.buffer);
eval_elem e={.type=EI32,.val.i32=d};
vec_push(&stack,&e);
}
break;
case LOPERATOR:
// Get operands
if(stack.size>1)
{
eval_elem elem[2]={{0}};
int32_t integers[2]={0};
int32_t res=0;
size_t var_stackloc[2]={0};
size_t nops=2; // 2 unless unary operator
//if(vec_at(&rpn_stack,i,const Tok*)->str.buffer[0]=='!')
if(strcmp("!",vec_at(&rpn_stack,i,const Tok*)->str.buffer)==0)
nops=1;
// 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);
if(elem[k].type==EIDENT)
{
bool found=false;
// Identify functions
for(size_t j=0;j<gen->rootnode->funcs.size;++j)
{
if(strcmp(vec_at(&gen->rootnode->funcs,j,Func*)->name,elem[k].val.name)==0)
{
elem[k].type=EFUNC;
fprintf(file,"\tcall %s\n",elem[k].val.name);
{
eval_elem e={.type=EACC,.val.i32=0};
vec_push(&stack,&e);
--k;
}
found=true;
break;
}
}
// Identify variables
if(!found)
{
for(size_t j=0;j<gen->stackptr->vars.size;++j)
{
if(strcmp(vec_at(&gen->stackptr->vars,j,Var*)->name,elem[k].val.name)==0)
{
elem[k].type=EVAR;
var_stackloc[k]=vec_at(&gen->stackptr->vars,j,Var*)->stackloc;
found=true;
break;
}
}
if(!found)
err_log("%u: undeclared identifier '%s'",vec_at(&pn->tokens,0,Tok*)->line,elem[k].val.name);
}
}
else if(elem[k].type==EI32)
integers[k]=elem[k].val.i32;
}
// Debugging output
/* if(elem[1].type==EVAR) */
/* printf("'%s' ",elem[1].val.name); */
/* else if(elem[1].type==EI32) */
/* printf("%d ",elem[1].val.i32); */
/* else */
/* printf("acc "); */
/* printf("%s ",vec_at(&rpn_stack,i,Tok*)->str.buffer); */
/* if(elem[0].type==EVAR) */
/* printf("'%s' ",elem[0].val.name); */
/* else if(e1.type==EI32) */
/* printf("%d ",e1.val.i32); */
/* else */
/* printf("acc "); */
/* puts(""); */
// UNARY OPS
if(nops==1)
{
switch(vec_at(&rpn_stack,i,const Tok*)->str.buffer[0])
{
case '!':
if(elem[0].type==EVAR)
{
fprintf(file,"\tcmpl $0,-%lu(%%%s)\n",var_stackloc[0],gen_x86_64_bp);
fprintf(file,"\tsete %%al\n");
fprintf(file,"\tmovzbl %%al,%%eax\n");
/* fprintf(file,"\tmovl %%eax,-%lu(%%%s)\n",var_stackloc[0],gen_x86_64_bp); */
eval_elem e={.type=EACC,.val={0}};
vec_push(&stack,&e);
}
else if(elem[0].type==EI32)
{
fprintf(file,"\tmovl $%d,%%eax\n",integers[0]);
fprintf(file,"\tcmpl $0,%%eax\n");
fprintf(file,"\tsete %%al\n");
fprintf(file,"\tmovzbl %%al,%%eax\n");
eval_elem e={.type=EACC,.val={0}};
vec_push(&stack,&e);
}
else if(elem[0].type==EACC)
{
fprintf(file,"\tcmpl $0,%%eax\n");
fprintf(file,"\tsete %%al\n");
fprintf(file,"\tmovzbl %%al,%%eax\n");
//fprintf(file,"\tmovl %%eax,-%lu(%%%s)\n",var_stackloc[0],gen_x86_64_bp);
eval_elem e={.type=EACC,.val={0}};
vec_push(&stack,&e);
}
break;
}
}
// INT OP INT
else if(elem[0].type==EI32&&elem[1].type==EI32)
{
switch(vec_at(&rpn_stack,i,const Tok*)->str.buffer[0])
{
case '+':res=integers[1]+integers[0];break;
case '-':res=integers[1]-integers[0];break;
case '*':res=integers[1]*integers[0];break;
case '/':res=integers[1]/integers[0];break;
}
eval_elem e={.type=EI32,.val.i32=res};
vec_push(&stack,&e);
}
// INT OP ACC
else if(
(elem[0].type==EACC && elem[1].type==EI32) ||
(elem[0].type==EI32 && elem[1].type==EACC)
)
{
eval_elem e={.type=EACC,.val={0}};
if(elem[0].type==EI32)
{
eval_elem etmp=elem[0];
elem[0]=elem[1];
elem[1]=etmp;
}
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
err_log("%u: cannot assign to rvalue '%d'",vec_at(&pn->tokens,0,Tok*)->line,elem[1].val.i32);
break;
case '+':
fprintf(file,"\taddl $%d,%%eax\n",elem[1].val.i32);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tsubl $%d,%%eax\n",elem[1].val.i32);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl $%d,%%%s\n",elem[1].val.i32,gen_x86_64_scratch1);
fprintf(file,"\timull %%%s\n",gen_x86_64_scratch1);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl $%d,%%%s\n",elem[1].val.i32,gen_x86_64_scratch1);
fprintf(file,"\tidiv %%%s\n",gen_x86_64_scratch1);
vec_push(&stack,&e);
break;
}
}
// INT OP IDENT
else if(elem[0].type==EVAR && elem[1].type==EI32)
{
eval_elem e={.type=EACC,.val={0}};
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
err_log("%u: cannot assign to rvalue '%d'",vec_at(&pn->tokens,0,Tok*)->line,elem[1].val.i32);
break;
case '+':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[0],gen_x86_64_bp);
fprintf(file,"\taddl $%d,%%eax\n",elem[1].val.i32);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[0],gen_x86_64_bp);
fprintf(file,"\tsubl $%d,%%eax\n",elem[1].val.i32);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[0],gen_x86_64_bp);
fprintf(file,"\tmovl $%d,%%%s\n",elem[1].val.i32,gen_x86_64_scratch1);
fprintf(file,"\timull %%%s\n",gen_x86_64_scratch1);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[0],gen_x86_64_bp);
fprintf(file,"\tmovl $%d,%%%s\n",elem[1].val.i32,gen_x86_64_scratch1);
fprintf(file,"\tidivl %%%s\n",gen_x86_64_scratch1);
vec_push(&stack,&e);
break;
}
}
// IDENT OP INT
else if(elem[0].type==EI32 && elem[1].type==EVAR)
{
eval_elem e={.type=EACC,.val={0}};
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
fprintf(file,"\tmovl $%d,-%lu(%%%s)\n",elem[0].val.i32,var_stackloc[1],gen_x86_64_bp);
fprintf(file,"\tmovl $%d,%%eax\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
case '+':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[1],gen_x86_64_bp);
fprintf(file,"\taddl $%d,%%eax\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[1],gen_x86_64_bp);
fprintf(file,"\tsubl $%d,%%eax\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[1],gen_x86_64_bp);
fprintf(file,"\tmovl $%d,%%%s\n",elem[0].val.i32,gen_x86_64_scratch1);
fprintf(file,"\timul %%%s\n",gen_x86_64_scratch1);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[1],gen_x86_64_bp);
fprintf(file,"\tmovl $%d,%%%s\n",elem[0].val.i32,gen_x86_64_scratch1);
fprintf(file,"\tidivl %%%s\n",gen_x86_64_scratch1);
vec_push(&stack,&e);
break;
}
}
// IDENT OP IDENT
else if(elem[0].type==EVAR && elem[1].type==EVAR)
{
eval_elem e={.type=EACC,.val={0}};
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[0],gen_x86_64_bp);
fprintf(file,"\tmovl %%eax,-%lu(%%%s)\n",var_stackloc[1],gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '+':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[1],gen_x86_64_bp);
fprintf(file,"\taddl -%lu(%%%s),%%eax\n",var_stackloc[0],gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[1],gen_x86_64_bp);
fprintf(file,"\tsubl -%lu(%%%s),%%eax\n",var_stackloc[0],gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[1],gen_x86_64_bp);
fprintf(file,"\timull -%lu(%%%s)\n",var_stackloc[0],gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc[1],gen_x86_64_bp);
fprintf(file,"\tidivl -%lu(%%%s)\n",var_stackloc[0],gen_x86_64_bp);
vec_push(&stack,&e);
break;
}
}
// IDENT OP ACC
else if(elem[1].type==EACC && elem[0].type==EVAR)
{
eval_elem e={.type=EACC,.val={0}};
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
fprintf(file,"\tmovl %%eax,-%lu(%%%s)\n",var_stackloc[0],gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '+':
fprintf(file,"\taddl -%lu(%%%s),%%eax\n",var_stackloc[0],gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tsubl -%lu(%%%s),%%eax\n",var_stackloc[0],gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\timull -%lu(%%%s)\n",var_stackloc[0],gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tidivl -%lu(%%%s)\n",var_stackloc[0],gen_x86_64_bp);
vec_push(&stack,&e);
break;
}
}
// I32 OP ACC
else if(elem[1].type==EACC && elem[0].type==EI32)
{
eval_elem e={.type=EACC,.val={0}};
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
err_log("%u: cannot assign to accumulator",vec_at(&pn->tokens,0,Tok*)->line,e.val.name);
/* vec_push(&stack,&e); */
break;
case '+':
fprintf(file,"\taddl $%d,%%eax\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tsubl $%d,%%eax\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\timull $%d\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tidivl $%d\n",elem[0].val.i32);
vec_push(&stack,&e);
break;
}
}
// ACC OP IDENT
else if(elem[1].type==EVAR && elem[0].type==EACC)
{
eval_elem e={.type=EACC,.val={0}};
switch(vec_at(&rpn_stack,i,Tok*)->str.buffer[0])
{
case '=':
fprintf(file,"\tmovl %%eax,-%lu(%%%s)\n",var_stackloc[1],gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '+':
fprintf(file,"\taddl -%lu(%%%s),%%eax\n",var_stackloc[1],gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '-':
fprintf(file,"\tsubl -%lu(%%%s),%%eax\n",var_stackloc[1],gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '*':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\timull -%lu(%%%s)\n",var_stackloc[1],gen_x86_64_bp);
vec_push(&stack,&e);
break;
case '/':
fprintf(file,"\txorl %%edx,%%edx\n");
fprintf(file,"\tidivl -%lu(%%%s)\n",var_stackloc[1],gen_x86_64_bp);
vec_push(&stack,&e);
break;
}
}
}
break;
}
}
}
// Empty remaining variables/integers on the stack
if(stack.size>0)
{
eval_elem e=*vec_at(&stack,stack.size-1,eval_elem*);
int32_t value=0;
size_t var_stackloc=0;
if(e.type==EI32)
{
value=e.val.i32;
fprintf(file,"\tmovl $%d,%%eax\n",value);
}
else if(e.type==EIDENT)
{
bool found=false;
// Identify functions
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=EFUNC;
fprintf(file,"\tcall %s\n",e.val.name);
found=true;
break;
}
}
// Identify variables
if(!found)
{
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=EVAR;
var_stackloc=vec_at(&gen->stackptr->vars,j,Var*)->stackloc;
fprintf(file,"\tmovl -%lu(%%%s),%%eax\n",var_stackloc,gen_x86_64_bp);
found=true;
break;
}
}
if(!found)
err_log("%u: undeclared identifier '%s'",vec_at(&pn->tokens,0,Tok*)->line,e.val.name);
}
}
}
vec_free(&rpn_stack);
vec_free(&stack);
}

View File

@ -16,5 +16,3 @@ extern const char*const gen_x86_64_pop_wordsize;
extern const char*const gen_x86_64_sp;
extern const char*const gen_x86_64_bp;
extern const char*const gen_x86_64_scratch1;
void gen_x86_64_eval(struct Gen*gen,const PNode*pn,FILE*file);