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
|
|
|
|
|
|
|
// 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));
|
|
|
|
int precedence[1024]={0};
|
|
|
|
precedence['(']=5;
|
|
|
|
precedence[')']=5;
|
|
|
|
precedence['+']=10;
|
|
|
|
precedence['-']=10;
|
2024-01-17 07:47:04 -06:00
|
|
|
precedence['!']=10;
|
2024-01-12 17:16:49 -06:00
|
|
|
precedence['*']=20;
|
|
|
|
precedence['/']=20;
|
|
|
|
|
|
|
|
if(tokens->size>0)
|
|
|
|
{
|
|
|
|
for(size_t i=0;i<tokens->size;++i)
|
|
|
|
{
|
|
|
|
|
2024-01-14 02:27:30 -06:00
|
|
|
//printf("[[%s]]\n",vec_at(tokens,i,const Tok*)->str.buffer);
|
|
|
|
|
2024-01-12 17:16:49 -06:00
|
|
|
// identifiers
|
|
|
|
switch(vec_at(tokens,i,const Tok*)->type)
|
|
|
|
{
|
|
|
|
|
|
|
|
// integers, keywords (true/false), identifiers
|
|
|
|
case LIDENTIFIER:
|
|
|
|
case LKEYWORD:
|
|
|
|
case LINTEGER:
|
2024-01-14 19:26:22 -06:00
|
|
|
case LFLOAT:
|
2024-01-12 17:16:49 -06:00
|
|
|
vec_push(&stack,vec_at(tokens,i,const Tok*));
|
|
|
|
break;
|
|
|
|
|
|
|
|
// operators
|
|
|
|
case LOPERATOR:
|
|
|
|
{
|
|
|
|
|
|
|
|
// '('
|
|
|
|
if(vec_at(tokens,i,const Tok*)->subtype==LLPAREN)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
vec_pop(&operators);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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*));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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-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-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;
|
|
|
|
Var var={
|
|
|
|
.name=vec_at(&pn->tokens,0,const Tok*)->str.buffer,
|
|
|
|
.is_arg=false,
|
|
|
|
/* .type=I32, */
|
|
|
|
/* .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,
|
|
|
|
/* .type=I32, */
|
|
|
|
};
|
|
|
|
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,
|
|
|
|
/* .type=I32, */
|
|
|
|
/* .location=STACK, */
|
|
|
|
/* .regnum=0, */
|
|
|
|
.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);
|
|
|
|
/* gen_i386_prolog(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_i386_epilog(pn,file); */
|
|
|
|
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-12 21:32:42 -06:00
|
|
|
size_t which=0;
|
|
|
|
|
|
|
|
switch(gen->buildarch)
|
|
|
|
{
|
2024-01-13 10:47:17 -06:00
|
|
|
case M_X86_64: which=0; break;
|
|
|
|
case M_I386: which=1; break;
|
2024-01-12 21:32:42 -06:00
|
|
|
}
|
|
|
|
|
2024-01-13 10:47:17 -06:00
|
|
|
const char*const gen_bp[2]={gen_x86_64_bp,gen_i386_bp};
|
|
|
|
const char*const gen_sp[2]={gen_x86_64_sp,gen_i386_sp};
|
2024-01-12 21:32:42 -06:00
|
|
|
const char*const*registers_abi_wordsize[2]={gen_x86_64_registers_abi_wordsize,
|
|
|
|
gen_i386_registers_abi_wordsize};
|
2024-01-13 19:45:37 -06:00
|
|
|
const char*const*registers_abi_32[2]={gen_x86_64_registers_abi_32,
|
|
|
|
gen_i386_registers_abi_32};
|
2024-01-12 21:32:42 -06:00
|
|
|
const char*const mov_wordsize[2]={gen_x86_64_mov_wordsize,
|
|
|
|
gen_i386_mov_wordsize};
|
2024-01-13 19:45:37 -06:00
|
|
|
const char*const mov_32[2]={gen_x86_64_mov_32,
|
|
|
|
gen_i386_mov_32};
|
2024-01-12 21:32:42 -06:00
|
|
|
const char*const push_wordsize[2]={gen_x86_64_push_wordsize,
|
|
|
|
gen_i386_push_wordsize};
|
|
|
|
const char*const sub_wordsize[2]={gen_x86_64_sub_wordsize,
|
|
|
|
gen_i386_sub_wordsize};
|
|
|
|
|
2024-01-13 10:47:17 -06:00
|
|
|
fprintf(file,"\t%s %%%s\n",push_wordsize[which],gen_bp[which]);
|
2024-01-12 21:32:42 -06:00
|
|
|
if(gen->buildarch==M_X86_64)
|
|
|
|
fprintf(file,"\t%s %%%s\n",push_wordsize[which],registers_abi_wordsize[which][2]);
|
2024-01-13 10:47:17 -06:00
|
|
|
fprintf(file,"\t%s %%%s,%%%s\n",mov_wordsize[which],gen_sp[which],gen_bp[which]);
|
2024-01-16 21:38:20 -06:00
|
|
|
if(stacksize>0)
|
|
|
|
fprintf(file,"\t%s $%lu,%%%s\n",sub_wordsize[which],stacksize,gen_sp[which]);
|
2024-01-12 21:32:42 -06:00
|
|
|
|
|
|
|
// Move argument variables to stack
|
|
|
|
//const char*reg_order_sysv[]={"edi","esi","edx","ecx","r8d","r9d"};
|
|
|
|
for(size_t i=0;i<pn->vars.size;++i)
|
|
|
|
if(i<6&&vec_at(&pn->vars,i,Var*)->is_arg)
|
2024-01-13 19:45:37 -06:00
|
|
|
fprintf(file,"\t%s %%%s,-%lu(%%%s)\n",mov_32[which],registers_abi_32[which][i],vec_at(&pn->vars,i,Var*)->stackloc,gen_bp[which]);
|
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-12 21:32:42 -06:00
|
|
|
size_t which=0;
|
|
|
|
|
|
|
|
switch(gen->buildarch)
|
|
|
|
{
|
2024-01-13 10:47:17 -06:00
|
|
|
case M_X86_64: which=0; break;
|
|
|
|
case M_I386: which=1; break;
|
2024-01-12 21:32:42 -06:00
|
|
|
}
|
|
|
|
|
2024-01-13 10:47:17 -06:00
|
|
|
const char*const gen_sp[2]={gen_x86_64_sp,gen_i386_sp};
|
|
|
|
const char*const gen_bp[2]={gen_x86_64_bp,gen_i386_bp};
|
2024-01-12 21:32:42 -06:00
|
|
|
const char*const*registers_abi_wordsize[2]={gen_x86_64_registers_abi_wordsize,
|
|
|
|
gen_i386_registers_abi_wordsize};
|
|
|
|
const char*const mov_wordsize[2]={gen_x86_64_mov_wordsize,
|
|
|
|
gen_i386_mov_wordsize};
|
|
|
|
const char*const pop_wordsize[2]={gen_x86_64_pop_wordsize,
|
|
|
|
gen_i386_pop_wordsize};
|
|
|
|
|
2024-01-13 10:47:17 -06:00
|
|
|
fprintf(file,"\t%s %%%s,%%%s\n",mov_wordsize[which],gen_bp[which],gen_sp[which]);
|
2024-01-12 21:32:42 -06:00
|
|
|
if(gen->buildarch==M_X86_64)
|
|
|
|
fprintf(file,"\t%s %%%s\n",pop_wordsize[which],registers_abi_wordsize[which][2]);
|
2024-01-13 10:47:17 -06:00
|
|
|
fprintf(file,"\t%s %%%s\n",pop_wordsize[which],gen_bp[which]);
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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,"\tmovl -%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,"\tret\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,"\tcmpl $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,"\tjz .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,"\tcmpl $0,%%eax\n");
|
|
|
|
}
|
2024-01-16 20:58:49 -06:00
|
|
|
|
|
|
|
fprintf(file,"\tjz .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,"\tjmp .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,
|
|
|
|
/* .type=I32, */
|
|
|
|
};
|
|
|
|
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
|
|
|
|
|
|
|
// 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(""); */
|
|
|
|
|
|
|
|
// ----------------------------------------------------------
|
2024-01-18 11:18:05 -06:00
|
|
|
/* // 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(""); */
|
2024-01-18 11:16:36 -06:00
|
|
|
// ----------------------------------------------------------
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|