diff options
author | tomsmeding <tom.smeding@gmail.com> | 2016-08-14 16:56:54 +0200 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2016-08-14 16:56:54 +0200 |
commit | a7d52eef038d25b83ab7d7e8730749d877b6a73c (patch) | |
tree | d5f0212d9344e42fc3065ad6b34c27ebe7ef6ea1 /bfcomp.c | |
parent | f30ff2240932d4d03984bd16cc8b9bb2b5427a53 (diff) |
Heatmap, etc.
- factor out prologue and epilogue
- -H, -L
- sourcemapping
- separate settings
- heatmap.py
Diffstat (limited to 'bfcomp.c')
-rw-r--r-- | bfcomp.c | 239 |
1 files changed, 134 insertions, 105 deletions
@@ -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); |