summaryrefslogtreecommitdiff
path: root/bfcomp.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfcomp.c')
-rw-r--r--bfcomp.c239
1 files changed, 134 insertions, 105 deletions
diff --git a/bfcomp.c b/bfcomp.c
index 5c4db60..8065fc4 100644
--- a/bfcomp.c
+++ b/bfcomp.c
@@ -6,6 +6,9 @@
#include <time.h>
#include <assert.h>
+#include "prologue.snippet.asm.h"
+#include "epilogue.snippet.asm.h"
+
#define DBGTIME(tag,block) \
do { \
clock_t start=clock(); \
@@ -41,6 +44,8 @@ void usage(const char *argv0){
"in <dstfile>.\n"
"Uses nasm for assembling and gcc for linking.\n"
" -h Show help\n"
+ " -H Calculate heatmap while executing\n"
+ " -L Output last cell reached\n"
" -m <memsize> Specify amount of tape cells (bytes) for the BF code\n"
" -v Show more info about the compile process\n",
argv0);
@@ -54,9 +59,9 @@ __attribute__((noreturn)) void usage1(const char *argv0){
typedef struct Params{
int memsize;
const char *srcfname,*dstfname;
- bool verbose;
+ bool lastcell,verbose,heatmap;
} Params;
-Params params={30000,NULL,NULL,false};
+Params params={30000,NULL,NULL,false,false,false};
void parseargs(int argc,char **argv){
if(argc<2)usage1(argv[0]);
@@ -70,6 +75,14 @@ void parseargs(int argc,char **argv){
usage(argv[0]);
exit(0);
+ case 'H':
+ params.heatmap=true;
+ break;
+
+ case 'L':
+ params.lastcell=true;
+ break;
+
case 'm':{
if(i==argc-1)usage1(argv[0]);
char *endp;
@@ -93,7 +106,31 @@ void parseargs(int argc,char **argv){
if(!params.srcfname||!params.dstfname)usage1(argv[0]);
}
-int runcmd(const char *cmd/*,int in,int out*/){
+typedef struct Range{
+ int from,to; //[from,to); empty range indicates no mapping
+} Range;
+
+typedef struct Sourcemap{
+ int len,origlen;
+ Range *maps;
+} Sourcemap;
+
+Sourcemap* sourcemap_init(int len){
+ Sourcemap *sm=malloc(sizeof(Sourcemap));
+ if(!sm)outofmem();
+ sm->len=len;
+ sm->origlen=-1;
+ sm->maps=calloc(len,sizeof(Range));
+ if(!sm->maps)outofmem();
+ return sm;
+}
+
+void sourcemap_destroy(Sourcemap *sm){
+ if(sm->maps)free(sm->maps);
+ free(sm);
+}
+
+int runcmd(const char *cmd){
clock_t start=clock();
pid_t pid=fork();
if(pid<0){
@@ -101,8 +138,6 @@ int runcmd(const char *cmd/*,int in,int out*/){
exit(1);
}
if(pid==0){
- /*dup2(in,0);
- dup2(out,1);*/
execl("/bin/sh","/bin/sh","-c",cmd,NULL);
__builtin_unreachable();
} else {
@@ -132,55 +167,44 @@ FILE* gettempfilew(char name[20]){
int compilechain(const char *asmfname,const char *dstfname){
char ofname[20];
FILE *f=gettempfilew(ofname);
- assert(strlen(ofname)==19);
fclose(f);
- char buf[25+19+1+strlen(asmfname)+1];
- sprintf(buf,"nasm -f macho64 -w+all -o %s %s",ofname,asmfname);
+
+ char *buf;
+
+ asprintf(&buf,"nasm -f macho64 -w+all -o %s %s",ofname,asmfname);
+ if(!buf)outofmem();
int ret=runcmd(buf);
+ free(buf);
if(ret)return ret;
- char buf2[4+19+4+strlen(dstfname)+1];
- sprintf(buf2,"gcc %s -o %s",ofname,dstfname);
- ret=runcmd(buf2);
+
+ asprintf(&buf,"gcc %s -o %s",ofname,dstfname);
+ if(!buf)outofmem();
+ ret=runcmd(buf);
+ free(buf);
+
unlink(ofname);
if(params.verbose)fprintf(stderr,"unlink(%s) (ofile)\n",ofname);
return ret;
}
+void writesettings(FILE *asmf,Sourcemap *sm){
+ fprintf(asmf,"%%define PARAMS_MEMSIZE %d\n",params.memsize);
+ if(params.lastcell)fprintf(asmf,"%%define OUTPUT_LAST_CELL\n");
+ if(params.heatmap){
+ assert(sm);
+ fprintf(asmf,"%%define HEATMAP\n");
+ fprintf(asmf,"%%define SOURCE_LENGTH %d\n",sm->origlen);
+ }
+ fputc('\n',asmf);
+}
+
void writeprologue(FILE *asmf){
- fprintf(asmf,
- "global _main\n"
- "\n"
- "extern _malloc\n"
- "extern _free\n"
- "extern _printf\n"
- "extern _getchar\n"
- "extern _putchar\n"
- "extern _write\n"
- "extern ___stdoutp\n"
- "extern _fflush\n"
- "\n"
- "default rel\n"
- "\n"
- "section .text\n"
- "\n"
- "_main:\n"
- "\tpush rbp ; prologue\n"
- "\tmov rbp, rsp\n"
- "\tadd rsp, 8\n"
- "\tpush rbx\n"
- "\tmov edi, %d\n"
- "\tcall _malloc\n"
- "\tcmp rax, 0\n"
- "\tjz nomem\n"
- "\tmov rbx, rax ;bufp\n"
- "\tmov [buf], rax ;buf\n"
- "\n",
- params.memsize);
+ fwrite(prologue_snippet_asm,1,prologue_snippet_asm_len,asmf);
}
-void writeprogram(char *source,FILE *asmf){
+void writeprogram(char *source,FILE *asmf,Sourcemap *sm){
int addc=0,shiftc=0;
- //int lastshiftc=0;
+ int lastshiftc=0;
struct stackitem {int id; struct stackitem *next;} *loopstack=NULL;
int i=0;
do {
@@ -194,21 +218,32 @@ void writeprogram(char *source,FILE *asmf){
}
if(shiftc&&c!='>'&&c!='<'){
shiftc=(shiftc%256)+256%256;
- /*if(lastshiftc>0&&shiftc<0){
- int id=uniqid();
- fprintf(asmf,
- "\tcmp [maxp], rbx\n"
- "\tjge skip%d\n"
- "\tmov [maxp], rbx\n"
- "skip%d:\n",
- id,id);
+ if(params.lastcell){
+ if(lastshiftc>0&&shiftc<0){
+ int id=uniqid();
+ fprintf(asmf,
+ "%%ifdef OUTPUT_LAST_CELL\n"
+ "\tcmp [maxp], rbx\n"
+ "\tjge skip%d\n"
+ "\tmov [maxp], rbx\n"
+ "skip%d:\n"
+ "%%endif\n",
+ id,id);
+ }
+ lastshiftc=shiftc;
}
- lastshiftc=shiftc;*/
if(shiftc==1)fprintf(asmf,"\tinc rbx ; 1 >\n");
else if(shiftc==-1)fprintf(asmf,"\tdec rbx ; 1 <\n");
else fprintf(asmf,"\tadd rbx, %d ; %d %c\n",shiftc,shiftc<0?-shiftc:shiftc,shiftc<0?'<':'>');
shiftc=0;
}
+
+ if(sm){
+ for(int j=sm->maps[i].from;j<sm->maps[i].to;j++){
+ fprintf(asmf,"\tinc dword [r12+%d]\n",4*j);
+ }
+ }
+
switch(c){
case '+': addc++; break;
case '-': addc--; break;
@@ -276,79 +311,65 @@ void writeprogram(char *source,FILE *asmf){
}
void writeepilogue(FILE *asmf){
- fprintf(asmf,
- "\n"
- "\tmov rdi, [buf] ; epilogue\n"
- "\tcall _free\n"
- "\n"
- /*"\tlea rdi, [formatstr] ;output last cell reached\n"
- "\tmov rsi, [maxp]\n"
- "\tsub rsi, [buf]\n"
- "\txor eax, eax\n"
- "\tcall _printf\n"
- "\n"*/
- "\txor eax, eax\n"
- "\tjmp mainend\n"
- "\n"
- "nomem:\n"
- "\tmov edi, 2\n"
- "\tlea rsi, [nomemstr]\n"
- "\tmov rdx, nomemstr.len\n"
- "\tcall _write\n"
- "\tmov eax, 1\n"
- "\n"
- "mainend:\n"
- "\tpop rbx\n"
- "\tmov rsp, rbp\n"
- "\tpop rbp\n"
- "\tret\n"
- "\n"
- "\n"
- "section .data\n"
- "sectalign 8\n"
- "\n"
- "nomemstr: db \"Out of memory!\"\n"
- ".len: equ $-nomemstr\n"
- /*"\n"
- "formatstr: db \"Last cell reached: %%d\", 10, 0\n"
- "\n"
- "align 8, db 0\n"
- "maxp: dq 0\n"*/
- "\n"
- "\n"
- "section .bss\n"
- "sectalign 8\n"
- "\n"
- "buf: resq 1\n");
+ fwrite(epilogue_snippet_asm,1,epilogue_snippet_asm_len,asmf);
}
-void readsource(FILE *f,char **sourcep){
+void readsource(FILE *f,char **sourcep,Sourcemap **smp){
int sz=1024;
+ Sourcemap *sm=NULL;
+ if(smp)sm=sourcemap_init(sz);
char *source=malloc(sz);
if(!source)outofmem();
int i=0;
+ int sourcei=0;
while(true){
if(i==sz-1){
sz*=2;
source=realloc(source,sz);
if(!source)outofmem();
+ sm->maps=realloc(sm->maps,sz*sizeof(Range));
+ if(!sm->maps)outofmem();
+ memset(sm->maps+sz/2,0,sz/2*sizeof(Range));
}
char c=fgetc(f);
if(feof(f))break;
- if(!strchr("+-><[].,",c))continue;
+ if(!strchr("+-><[].,",c)){
+ sourcei++;
+ continue;
+ }
+ if(sm)sm->maps[i].from=sourcei;
+ if(sm)sm->maps[i].to=sourcei+1;
source[i++]=c;
+ sourcei++;
}
source[i]='\0';
+ if(sm){
+ sm->len=i;
+ sm->origlen=sourcei;
+ }
*sourcep=source;
+ if(sm)*smp=sm;
}
-void optimise(char *source){
- int j=0;
-#define COPY do {if(j<i)source[j]=source[i]; j++;} while(0)
- for(int i=0;source[i];i++){
+void optimise(char *source,const Sourcemap *srcsm,Sourcemap **dstsm){
+ Sourcemap *sm=NULL;
+ if(dstsm)sm=sourcemap_init(srcsm->len);
+ int i,j=0;
+
+#define COPY do { \
+ if(j<i)source[j]=source[i]; \
+ if(sm)sm->maps[j]=srcsm->maps[i]; \
+ j++; \
+ } while(0)
+
+ for(i=0;source[i];i++){
switch(source[i]){
case '[':
if(source[i+1]=='-'&&source[i+2]==']'){
+ if(sm){
+ sm->maps[j].from=srcsm->maps[i].from;
+ sm->maps[j].to=srcsm->maps[i+2].to;
+ }
source[j++]='0';
i+=2;
} else COPY;
@@ -359,8 +380,13 @@ void optimise(char *source){
break;
}
}
+ if(sm){
+ sm->len=j;
+ sm->origlen=srcsm->origlen;
+ }
source[j]='\0';
#undef COPY
+ if(sm)*dstsm=sm;
}
int main(int argc,char **argv){
@@ -374,25 +400,28 @@ int main(int argc,char **argv){
}
char *source;
- readsource(srcf,&source);
+ Sourcemap *sm1=NULL;
+ readsource(srcf,&source,params.heatmap?&sm1:NULL);
assert(source);
fclose(srcf);
- optimise(source);
+ Sourcemap *sm2=NULL;
+ optimise(source,sm1,params.heatmap?&sm2:NULL);
char asmfname[20];
FILE *asmf=gettempfilew(asmfname);
if(params.verbose)fprintf(stderr,"asm -> %s\n",asmfname);
+ DBGTIME("writesettings",writesettings(asmf,sm2););
DBGTIME("writeprologue",writeprologue(asmf););
- DBGTIME("writeprogram",writeprogram(source,asmf););
+ DBGTIME("writeprogram",writeprogram(source,asmf,sm2););
DBGTIME("writeepilogue",writeepilogue(asmf););
fclose(asmf);
/*char *b;
- asprintf(&b,"cat -n %s",asmfname);
+ asprintf(&b,"cp %s %s.asm",asmfname,params.srcfname);
runcmd(b);
free(b);*/
int ret=compilechain(asmfname,params.dstfname);