move codegen to gen.c

This commit is contained in:
corey 2024-01-12 21:49:15 -06:00
parent 948520f551
commit 358449077b
7 changed files with 254 additions and 411 deletions

254
gen.c
View File

@ -300,21 +300,21 @@ void gen_declare_function(Gen*gen,PNode*pn,FILE*file)
case M_I386:
pn->stacksize+=stacksize;
stacksize+=gen_i386_stacksize(pn);
stacksize+=gen_stacksize(pn);
gen_prolog(gen,pn,file,stacksize);
/* 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_code(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);
stacksize+=gen_stacksize(pn);
/* gen_x86_64_prolog(pn,file,stacksize); */
gen_prolog(gen,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_code(gen,vec_at(&pn->pnodes,i,PNode*),file);
/* gen_x86_64_epilog(pn,file); */
break;
@ -493,3 +493,249 @@ void gen_epilog(Gen*gen,const PNode*pn,FILE*file)
fprintf(file,"\t%s %%%s\n",pop_wordsize[which],gen_bp());
}
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
{
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_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)
{
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;
}
fprintf(file,"\tcmpl $0,%%eax\n");
}
++gen->labelno;
fprintf(file,"\tjz .L%02lu\n",gen->labelno);
for(size_t i=0;i<pn->pnodes.size;++i)
gen_code(gen,vec_at(&pn->pnodes,i,PNode*),file);
fprintf(file,".L%02lu:\n",gen->labelno);
break;
case PWHILE:
++gen->labelno;
fprintf(file,".L%02lu:\n",gen->labelno);
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;
}
fprintf(file,"\tcmpl $0,%%eax\n");
}
fprintf(file,"\tjz .L%02lu\n",++gen->labelno);
for(size_t i=0;i<pn->pnodes.size;++i)
gen_code(gen,vec_at(&pn->pnodes,i,PNode*),file);
fprintf(file,"\tjmp .L%02lu\n",gen->labelno-1);
fprintf(file,".L%02lu:\n",gen->labelno);
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:
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;
}
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);
}

3
gen.h
View File

@ -37,6 +37,9 @@ typedef struct eval_elem
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);
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);

200
i386.c
View File

@ -13,190 +13,6 @@ char*gen_i386_sp(void){return"esp";}
char*gen_i386_bp(void){return"ebp";}
char*gen_i386_scratch1(void){return"e8d";};
void gen_i386(Gen*gen,PNode*pn,FILE*file)
{
if(!pn)
{
err_log("passed NULL PNode to gen_i386");
return;
}
if(!file)
{
err_log("NULL FILE* passed to gen_i386");
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
gen_i386_eval(gen,pn,file);
}
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)
{
gen_i386_eval(gen,pn,file);
fprintf(file,"\tcmpl $0,%%eax\n");
}
++gen->labelno;
fprintf(file,"\tjz .L%02lu\n",gen->labelno);
for(size_t i=0;i<pn->pnodes.size;++i)
gen_i386(gen,vec_at(&pn->pnodes,i,PNode*),file);
fprintf(file,".L%02lu:\n",gen->labelno);
break;
case PWHILE:
++gen->labelno;
fprintf(file,".L%02lu:\n",gen->labelno);
if(pn->tokens.size>1)
{
gen_i386_eval(gen,pn,file);
fprintf(file,"\tcmpl $0,%%eax\n");
}
fprintf(file,"\tjz .L%02lu\n",++gen->labelno);
for(size_t i=0;i<pn->pnodes.size;++i)
gen_i386(gen,vec_at(&pn->pnodes,i,PNode*),file);
fprintf(file,"\tjmp .L%02lu\n",gen->labelno-1);
fprintf(file,".L%02lu:\n",gen->labelno);
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_i386_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_i386(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_i386(gen,vec_at(&pn->pnodes,i,PNode*),file);
}
break;
case PEXPRESSION:
default:
gen_i386_eval(gen,pn,file);
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_i386(gen,vec_at(&pn->pnodes,i,PNode*),file);
}
// Convert to infix, then evaluate
void gen_i386_eval(Gen*gen,const PNode*pn,FILE*file)
{
@ -703,19 +519,3 @@ void gen_i386_eval(Gen*gen,const PNode*pn,FILE*file)
vec_free(&rpn_stack);
vec_free(&stack);
}
size_t gen_i386_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_i386_stacksize(vec_at(&pn->pnodes,i,PNode*));
return stacksize;
}

2
i386.h
View File

@ -15,6 +15,4 @@ extern const char*const gen_i386_pop_wordsize;
char*gen_i386_bp(void);
char*gen_i386_scratch1(void);
char*gen_i386_sp(void);
size_t gen_i386_stacksize(const PNode*pn);
void gen_i386(struct Gen*gen,PNode*pn,FILE*file);
void gen_i386_eval(struct Gen*gen,const PNode*pn,FILE*file);

5
main.c
View File

@ -205,11 +205,8 @@ int main(int argc,char**argv)
break;
case M_X86_64:
gen_x86_64(&state.gen,&state.parser.root,state.outfile);
break;
case M_I386:
gen_i386(&state.gen,&state.parser.root,state.outfile);
gen_code(&state.gen,&state.parser.root,state.outfile);
break;
}

200
x86_64.c
View File

@ -14,206 +14,6 @@ char*gen_x86_64_sp(void){return"rsp";}
char*gen_x86_64_bp(void){return"rbp";}
char*gen_x86_64_scratch1(void){return"r8d";};
void gen_x86_64(Gen*gen,PNode*pn,FILE*file)
{
if(!pn)
{
err_log("passed NULL PNode to gen_x86_64");
return;
}
if(!file)
{
err_log("NULL FILE* passed to gen_x86_64");
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
gen_x86_64_eval(gen,pn,file);
}
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)
{
gen_x86_64_eval(gen,pn,file);
fprintf(file,"\tcmpl $0,%%eax\n");
}
++gen->labelno;
fprintf(file,"\tjz .L%02lu\n",gen->labelno);
for(size_t i=0;i<pn->pnodes.size;++i)
gen_x86_64(gen,vec_at(&pn->pnodes,i,PNode*),file);
fprintf(file,".L%02lu:\n",gen->labelno);
break;
case PWHILE:
++gen->labelno;
fprintf(file,".L%02lu:\n",gen->labelno);
if(pn->tokens.size>1)
{
gen_x86_64_eval(gen,pn,file);
fprintf(file,"\tcmpl $0,%%eax\n");
}
fprintf(file,"\tjz .L%02lu\n",++gen->labelno);
for(size_t i=0;i<pn->pnodes.size;++i)
gen_x86_64(gen,vec_at(&pn->pnodes,i,PNode*),file);
fprintf(file,"\tjmp .L%02lu\n",gen->labelno-1);
fprintf(file,".L%02lu:\n",gen->labelno);
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_x86_64(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_x86_64(gen,vec_at(&pn->pnodes,i,PNode*),file);
}
break;
case PEXPRESSION:
default:
gen_x86_64_eval(gen,pn,file);
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_x86_64(gen,vec_at(&pn->pnodes,i,PNode*),file);
}
size_t gen_x86_64_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_x86_64_stacksize(vec_at(&pn->pnodes,i,PNode*));
return stacksize;
}
// Convert to infix, then evaluate
void gen_x86_64_eval(Gen*gen,const PNode*pn,FILE*file)
{

View File

@ -15,6 +15,5 @@ extern const char*const gen_x86_64_pop_wordsize;
char*gen_x86_64_bp(void);
char*gen_x86_64_scratch1(void);
char*gen_x86_64_sp(void);
size_t gen_x86_64_stacksize(const PNode*pn);
void gen_x86_64(struct Gen*gen,PNode*pn,FILE*file);
void gen_x86_64_eval(struct Gen*gen,const PNode*pn,FILE*file);