lr/gen.c

361 lines
7.9 KiB
C
Raw Normal View History

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;
}
// 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;
precedence['*']=20;
precedence['/']=20;
if(tokens->size>0)
{
for(size_t i=0;i<tokens->size;++i)
{
// identifiers
switch(vec_at(tokens,i,const Tok*)->type)
{
// integers, keywords (true/false), identifiers
case LIDENTIFIER:
case LKEYWORD:
case LINTEGER:
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"); */
/* } */
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,"=")))
{
err_log("%u: expected either ';' or '='",vec_at(&pn->tokens,1,const Tok*)->line);
}
}
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)
{
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;
}
}
}
}
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;
stacksize+=gen_i386_stacksize(pn);
gen_i386_prolog(pn,file,stacksize);
for(size_t i=0;i<pn->pnodes.size;++i)
gen_i386(gen,vec_at(&pn->pnodes,i,PNode*),file);
/* gen_i386_epilog(pn,file); */
break;
case M_X86_64:
pn->stacksize+=stacksize;
stacksize+=gen_x86_64_stacksize(pn);
gen_x86_64_prolog(pn,file,stacksize);
for(size_t i=0;i<pn->pnodes.size;++i)
gen_x86_64(gen,vec_at(&pn->pnodes,i,PNode*),file);
/* gen_x86_64_epilog(pn,file); */
break;
}
}
// 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);
}