diff --git a/Makefile b/Makefile index c63fa91..304bc59 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CFLAGS = -Wall -std=c99 -O3 CFLAGSDEBUG = -g -Wall -std=c99 -O0 OUTFILE = hac -SOURCES = src/main.c src/lex.c src/grammar.c src/tree.c src/lextest.c src/symbolTable.c src/codeGen.c src/testbfi.c src/compilerFunctions.c src/codeEss.c src/optimizer.c src/expander.c src/highlight.c -OBJS = temp/codeGen.o temp/symbolTable.o temp/grammar.o temp/tree.o temp/main.o temp/lex.o temp/lextest.o temp/testbfi.o temp/compilerFunctions.o temp/codeEss.o temp/optimizer.o temp/expander.o temp/highlight.o +SOURCES = src/main.c src/lex.c src/grammar.c src/tree.c src/lextest.c src/symbolTable.c src/codeGen.c src/testbfi.c src/compilerFunctions.c src/codeEss.c src/optimizer.c src/expander.c src/highlight.c src/codellvm.c +OBJS = temp/codeGen.o temp/symbolTable.o temp/grammar.o temp/tree.o temp/main.o temp/lex.o temp/lextest.o temp/testbfi.o temp/compilerFunctions.o temp/codeEss.o temp/optimizer.o temp/expander.o temp/highlight.o temp/codellvm.o ZIGCC = zig cc WINCC = x86_64-w64-mingw32-gcc-11.1.0 #old one was i686-w64-mingw32-gcc; changed because false positives @@ -55,6 +55,9 @@ expander: src/expander.c bfalgoConverter: src/bfalgoConverter.c cc $(CFLAGS) src/bfalgoConverter.c -o bfalgoConverter +minifier: src/minifier.c + cc $(CFLAGS) src/minifier.c src/testbfi.c -o minifier + bfi.exe: src/testbfi.c $(WINCC) $(CFLAGS) -DSTANDALONE src/testbfi.c -o bfi.exe bfi.linux: src/testbfi.c @@ -189,20 +192,27 @@ temp/grammar.o: src/grammar.c cc -o temp/grammar.o -Wall -O3 -c src/grammar.c temp/tree.o: src/tree.c cc -o temp/tree.o -Wall -O3 -c src/tree.c +temp/lib.o: + cc -DHACLIB -o temp/lib.o -Wall -O3 -c src/main.c temp/main.o: src/main.c cc -o temp/main.o -Wall -O3 -c src/main.c temp/lex.o: src/lex.c cc -o temp/lex.o -Wall -O3 -c src/lex.c temp/highlight.o: src/highlight.c cc -o temp/highlight.o -Wall -O3 -c src/highlight.c +temp/codellvm.o: src/codellvm.c + cc -o temp/codellvm.o -Wall -O3 -c src/codellvm.c ## LIBS -hac.a: $(OBJS) +hac.a: $(OBJS) temp/lib.o + rm -f temp/main.o ar ruv hac.a temp/*.o ranlib hac.a -hac.so: $(OBJS) - cc -shared temp/*.o -o hac.s +hac.so: $(OBJS) temp/lib.o + rm -f temp/main.o + cc -shared temp/*.o -o hac.so + ## ZIG CC EXPERIMENT @@ -224,14 +234,20 @@ hac-release-z-windows.zip: bfi_z.exe hac_z.exe expander_z.exe bfalgoConverter_z. zip -r zipfolder.zip hac_z.exe expander_z.exe bfi_z.exe bfalgoConverter_z.exe mv zipfolder.zip hac-release-z-windows.zip -zig: hac_z bfi_z expander_z bfalgoConverter_z +zig_build: + mkdir zig_build +zig: hac_z bfi_z expander_z bfalgoConverter_z zig_build + mv *_z zig_build bfi_z: src/testbfi.c - $(ZIGCC) $(CFLAGS) -DSTANDALONE src/testbfi.c -o bfi_z -target x86_64-macos-gnu + $(ZIGCC) $(CFLAGS) -DSTANDALONE src/testbfi.c -o bfi_z -target x86_64-macos hac_z: $(SOURCES) - $(ZIGCC) $(CFLAGS) -o hac_z $(SOURCES) -target x86_64-macos-gnu + $(ZIGCC) $(CFLAGS) -o hac_z $(SOURCES) -target x86_64-macos expander_z: src/expander.c - $(ZIGCC) $(CFLAGS) -DSTANDALONE src/expander.c -o expander_z -target x86_64-macos-gnu + $(ZIGCC) $(CFLAGS) -DSTANDALONE src/expander.c -o expander_z -target x86_64-macos bfalgoConverter_z: src/bfalgoConverter.c - $(ZIGCC) $(CFLAGS) src/bfalgoConverter.c -o bfalgoConverter_z -target x86_64-macos-gnu + $(ZIGCC) $(CFLAGS) src/bfalgoConverter.c -o bfalgoConverter_z -target x86_64-macos + +minifier_z: src/minifier.c + $(ZIGCC) $(CFLAGS) src/minifier.c src/testbfi.c -o minifier_z -target x86_64-macos diff --git a/examples/calculator.ha b/examples/calculator.ha index fb81872..286ae5b 100644 --- a/examples/calculator.ha +++ b/examples/calculator.ha @@ -3,7 +3,7 @@ //Interactive Calculator program void main() { char operator; - byte a,b; + short a,b; print "Enter first number:\n"; read a; print "Received number "; print a; print "\n"; diff --git a/examples/collatz.ha b/examples/collatz.ha new file mode 100644 index 0000000..25a2ccd --- /dev/null +++ b/examples/collatz.ha @@ -0,0 +1,32 @@ +short mod2(short a){ + short r,q; + q = a/(2 as short); + r = a - (2 as short)*q; + print "(a,2)"; @"= ("; @a; @","; @2; @")"; + print "(r,q)"; @"= ("; @r; @","; @q; @")"; + return r; +} + +void main() { + short x,y,z; + print "Enter a number:\n"; + + read x; + print "got "; @x; @" \n"; + y = x - (1 as short); + while(y){ + z = mod2(x); + print "z is "; @z; @"\n"; + if(z == 0) { + print "even\n"; + x = x/(2 as short); + } + else { + print "odd\n"; + x = (3 as short)*x+(1 as short); + } + print "=> "; @x; @"\n"; + y--; + + } +} \ No newline at end of file diff --git a/examples/countext.ha b/examples/countext.ha index dea8908..71f736f 100644 --- a/examples/countext.ha +++ b/examples/countext.ha @@ -3,9 +3,11 @@ void main() { @"Enter an limit\n"; #end; @"Start:\n"; - for(i=0;i<=end;i++){ + i=0; + while(i<=end){ @i;@"\n"; + i++; } - //@"End\n"; + @"End\n"; } \ No newline at end of file diff --git a/examples/countext2.ha b/examples/countext2.ha new file mode 100644 index 0000000..71f736f --- /dev/null +++ b/examples/countext2.ha @@ -0,0 +1,13 @@ +void main() { + short i,end; + @"Enter an limit\n"; + #end; + @"Start:\n"; + i=0; + while(i<=end){ + @i;@"\n"; + i++; + } + @"End\n"; + +} \ No newline at end of file diff --git a/examples/example.ha b/examples/example.ha index 7a36313..a64d27e 100644 --- a/examples/example.ha +++ b/examples/example.ha @@ -1,4 +1,4 @@ void main() { - @"Headache compiles to 8 bit Brainfuck\n"; + print "Headache compiles to 8 bit Brainfuck\n"; } \ No newline at end of file diff --git a/examples/experimental/sincos.ha b/examples/experimental/sincos.ha index df8cd45..4fb2a54 100644 --- a/examples/experimental/sincos.ha +++ b/examples/experimental/sincos.ha @@ -44,7 +44,7 @@ short cos(short x){ short i; short sum; - //sum = (x - x*x/2 + pow(x,4)/factorial(4))*100; + sum = (x - x*x/2 + pow(x,4)/factorial(4))*100; return sum; } void main() { diff --git a/examples/factor.ha b/examples/factor.ha new file mode 100644 index 0000000..8be3dda --- /dev/null +++ b/examples/factor.ha @@ -0,0 +1,28 @@ +byte modulus8(byte a, byte b){ + byte r,q; + q = a/b; + r = a - b*q; + return r; +} + +void factor(byte n) { + byte x,i; + print n; @"! = "; + x = n; + i = 2; + while (x > 1) { + if (modulus8(x,i) == 0) { + print " "; @i; + x = x / i; + i = 1; + } + i++; + } + print "\n"; + } +void main() { + byte n; + print "Enter number:\n"; + read n; + factor(n); +} \ No newline at end of file diff --git a/examples/factorial.ha b/examples/factorial.ha index ea94fe9..6d675da 100644 --- a/examples/factorial.ha +++ b/examples/factorial.ha @@ -8,11 +8,10 @@ } return z; } - void main(){ short x; @"Calculate x!\n"; @"Enter x:\n"; read x; - @"x! is "; @factorial(x); @"\n"; -} \ No newline at end of file + @x; @"! is "; @factorial(x); @"\n"; +} diff --git a/examples/foraMaia.ha b/examples/foraMaia.ha deleted file mode 100644 index e78939f..0000000 --- a/examples/foraMaia.ha +++ /dev/null @@ -1,13 +0,0 @@ -void main() { - byte count,c2; - count=1; - c2=1; - while(count){ - c2 = 1; - while(c2) { - print "MORAES DITADOR! FORA!"; - c2++; - } - count++; - } -} \ No newline at end of file diff --git a/examples/masoque.ha b/examples/masoque.ha index daf1013..735c143 100644 --- a/examples/masoque.ha +++ b/examples/masoque.ha @@ -1,4 +1,4 @@ -void main() { +void hello() { print "Hello, World!\n"; } diff --git a/src/codeGen.c b/src/codeGen.c index 80e2324..269a395 100644 --- a/src/codeGen.c +++ b/src/codeGen.c @@ -70,7 +70,7 @@ static int currentBrIndex = 0; static int currentStringConstant = 0; static int declareTop = 0; -char* stringsToDeclare[100]; +static char* stringsToDeclare[100]; extern char forceExpand; @@ -669,6 +669,8 @@ static void codeCellValuePrintAnySize(int start, int end){ popCells(10); } +void outputToBuffer(){} + void setCodeOutput(FILE* out) { setOutput(out); diff --git a/src/codellvm.c b/src/codellvm.c new file mode 100644 index 0000000..f034724 --- /dev/null +++ b/src/codellvm.c @@ -0,0 +1,1325 @@ +#include +#include +#include +#include +#include +#if !defined(tree_h) + #include "tree.h" + #define tree_h +#endif +#if !defined(symbolTable_h) + #include "symbolTable.h" + #define symbolTable_h +#endif + +static void codeDefVar(DefVar* dv); +static void codeDefFunc(DefFunc* df); +static void codeDefVarList(DefVarL* dvl); +static void codeDefList(Def* d); +static void codeNameList(NameL* nl,Type* t,int scope); +static void codeType(Type* t); +static void codeParams(Parameter* params); +static void codeForAllocParams(Parameter* params); +static void codeCommandList(CommandL* cl); +static int codeExpAccess(Exp* e); +static void codeBlock(Block* b); +static int codeExp(Exp* e); +static void codeVar(Var* v); +//static void codeConstant(Constant* c); +static int codeExpOperator(Exp* e); +static void codeExpList(ExpList* el); +static int codeAccessElemPtr(Exp* e); +static char* stringForType(Type* t); +static char* retranslatescape(const char* scape); + +static FILE* output = NULL; +static int currentFunctionTIndex = 0; +static int currentBrIndex = 0; + +static int currentStringConstant = 0; +static int declareTop = 0; +static char* stringsToDeclare[100]; + +static int currentFuncHasReturn = 0; + + +void setCodeOutputLLVM(FILE* out) { + output = out; +} + +static void defaultOutput() { + output = stdout; +} + + +static Parameter* currentParameters = NULL; + +char* stringForType(Type* t) { + printType(t,0); + char* tStr = NULL; + if(t == NULL) + return "void"; + switch(t->tag) { + case base: + switch(t->b) { + case WInt: + return "i32"; + break; + case WFloat: + return "float"; + break; + case WChar: + return "i8"; + break; + case WByte: + return "i8"; + case WShort: + return "i16"; + case WBit: + return "i1"; + } + break; + case array: + + tStr = stringForType(t->of); + int tlen = strlen(tStr); + char* new = malloc(tlen+2); + strcpy(new,tStr); + //free(tStr); // no need anymore + new[tlen] = '*'; + new[tlen+1] = '\0'; + return new; + + break; + } + return "Unknown Type Error"; +} + +static char* stringForDefaultValue(Type* t) { + if(!t) { + printf(";That's probably an error\n"); + return "void"; + } + if(t->tag == base) { + if(t->b == WInt || t->b == WChar || t->b == WByte || t->b == WShort) { + return "0"; + } + else { + return "0.0"; + } + } else { + return "null"; + } + +} +static void codeDefaultReturn(Type* t) { + if(!t) { + fprintf(output, "ret void\n"); + return; + } + char* tStr = stringForType(t); + char* value = stringForDefaultValue(t); + fprintf(output, "ret %s %s\n", tStr,value); +} + +static void pushStringToDeclare(char* str) { + //printf("%s\n",str ); + char* nstr = malloc(strlen(str)+1); + strcpy(nstr,str); + nstr[strlen(str)] = '\0'; + stringsToDeclare[declareTop] = nstr ; + declareTop++; +} +static void declateStringsToDeclare() { + int x = currentStringConstant - declareTop; + for(int i = 0;i= 50) { + printf("SevereError. var name is too big\n"); + } + if(scope == 0) { + sprintf(string,"@g%s",name); + } + else { + sprintf(string,"%%l%d%s",scope,name); + } + + char* str = (char*)malloc(strlen(string)+1); + strcpy(str,string); + str[strlen(string)] = '\0'; + return str; +} +static void codeExtraDeclares() { + //fprintf(output, "declare noalias i8* @malloc(i64)\n" ); + fprintf(output, "; Generated by HAC-LLVM (Headache Awesome Compiler - LLVM Backend)\n" ); + fprintf(output, "; Powered by MongaComp\n" ); + fprintf(output, "declare i8* @malloc(i32)\n" ); //malloc + fprintf(output, "declare i32 @printf(i8* nocapture readonly, ...)\n" ); + fprintf(output, "declare i32 @puts(i8* nocapture readonly)\n" ); + fprintf(output, "declare i32 @scanf(i8*, ...)\n" ); + fprintf(output, "declare i32 @putchar(i32) \n"); + fprintf(output, "@.intprintstr = private unnamed_addr constant [3 x i8] c\"%%u\\00\"\n" ); + fprintf(output, "@.shortprintstr = private unnamed_addr constant [4 x i8] c\"%%hu\\00\"\n" ); + fprintf(output, "@.floatprintstr = private unnamed_addr constant [3 x i8] c\"%%f\\00\"\n" ); + fprintf(output, "@.charprintstr = private unnamed_addr constant [3 x i8] c\"%%c\\00\"\n" ); + fprintf(output, "@.byteprintstr = private unnamed_addr constant [5 x i8] c\"%%hhu\\00\"\n" ); + fprintf(output, "@.strprintstr = private unnamed_addr constant [3 x i8] c\"%%s\\00\"\n" ); + fprintf(output, "@.charreadstr = private unnamed_addr constant [4 x i8] c\" %%c\\00\"\n" ); + fprintf(output, "@.bytereadstr = private unnamed_addr constant [5 x i8] c\"%%hhu\\00\"\n" ); + fprintf(output, "@.intreadstr = private unnamed_addr constant [4 x i8] c\" %%d\\00\"\n" ); + fprintf(output, "@.shortreadstr = private unnamed_addr constant [5 x i8] c\" %%hd\\00\"\n" ); + fprintf(output, "@.floatreadstr = private unnamed_addr constant [4 x i8] c\" %%f\\00\"\n" ); + fprintf(output, "; End of monga dependencies \n" ); +} + +void codeTreeLLVM() { + if(output==NULL) { + defaultOutput(); + } + currentStringConstant = 0; + printf("generating code for tree\n"); + codeExtraDeclares(); + codeDefList(globalTree->next); +} +static void codeDefVar(DefVar* dv) { + + printDefVar(dv,0); + NameL* single = (NameL*)malloc(sizeof(NameL)); + single->next = NULL; + single->name = dv->id; + + fprintf(output, ";not implemented %s \n", dv->id ); + codeNameList(single,dv->t,dv->scope); + free(single); + +} +static void codeDefFunc(DefFunc* df) { + + char* typeStr = stringForType(df->retType); + if(df->b) { + currentFunctionTIndex = 0; + currentParameters = df->params; + declareTop = 0; + currentFuncHasReturn = 0; + currentBrIndex = 0; + fprintf(output, "define %s @%s(", typeStr,df->id); + codeParams(df->params); + fprintf(output, ")\n{\n"); + codeForAllocParams(df->params); + codeBlock(df->b); + if(df->retType == NULL) { + fprintf(output, "ret void\n"); + } //probably missing a ret in the end of void func + else if(currentFuncHasReturn == 0) { + fprintf(stderr, "Warning: missing return in function %s\n",df->id); + fprintf(stderr, "It will be overwritten by the default return\n"); + } + codeDefaultReturn(df->retType); + fprintf(output, "}\n"); + currentFunctionTIndex = 0; + currentParameters = NULL; + declateStringsToDeclare(); + currentFuncHasReturn = 0; + currentBrIndex = 0; + } + else { + fprintf(output, "declare %s @%s(", typeStr,df->id); + codeParams(df->params); + fprintf(output, ")\n"); + } +} +static void codeDefVarList(DefVarL* dvl) { + + DefVarL* p = dvl; + while(p) { + codeDefVar(p->dv); + p=p->next; + } +} +static void codeDefList(Def* d) { + if(!d) + return; + //printf("coding DefList\n"); + switch (d->tag) { + case DVar: + codeDefVarList(d->u.v); + break; + case DFunc: + codeDefFunc(d->u.f); + break; + } + codeDefList(d->next); + +} +static void codeNameList(NameL* nl,Type* t,int scope) { + char* tStr = stringForType(t); + char* vStr = stringForDefaultValue(t); + NameL* p = nl; + if(scope) { + while(p) { + char* string = stringForVarAddress(p->name,scope); + fprintf(output, "%s = alloca %s\n", + string, + tStr ); + free(string); + p=p->next; + } + } else { + while(p) { + char* string = stringForVarAddress(p->name,scope); + + fprintf(output, "%s = global %s %s \n", + string, + tStr, + vStr ); + free(string); + p=p->next; + } + } +} +static void codeType(Type* t); +static void codeParams(Parameter* params) { + if(!params) + return; + char * tStr = stringForType(params->t); + fprintf(output,"%s",tStr); + if(params->next) { + fprintf(output, "," ); + codeParams(params->next); + } +} +static void codeForAllocParams(Parameter* params) { + if(!params) + return; + + int index = currentFunctionTIndex; + Parameter* p = params; + while(p) { + char * tStr = stringForType(p->t); + fprintf(output,"%%t%d = alloca %s\n", currentFunctionTIndex++, tStr); + p = p->next; + } + p = params; + int i=0; + while(p) { + char * tStr = stringForType(p->t); + fprintf(output,"store %s %%%d, %s* %%t%d\n", tStr, i++, tStr, index++); + p = p->next; + } + +} +static void codeForAssign() { + +} +/* + %t315 = getelementptr i32* @g25, i32 0 + ~= i315 = &g25[0]; +*/ +// void getelementptr(char* str) { +// fprintf(output, "%s\n", ); +// } +static char* adressOfLeftAssign(Exp* e) { + //printf("addr left assig\n"); + if(e->tag == ExpVar) { + //printf("e->var.id %s\n",e->var->id); + + if (e->var->declaration == NULL){ + Parameter* p = currentParameters; + int t=0; + while(p) { + if(strcmp(e->var->id,p->id)==0) + break; + p=p->next; + t++; + } + char * str = (char*)malloc(t/10+3); + sprintf(str,"%%t%d",t); + return str; + } + else { + int scope = e->var->declaration->scope; + char* varAddr = stringForVarAddress(e->var->id,scope); + return varAddr; + } + } + else if(e->tag == ExpAccess) { + int i1 = codeExpAccess(e)-1; //received getElemPtr + char * str = (char*)malloc(i1/10+3); + sprintf(str,"%%t%d",i1); + return str; + } + else { + fprintf(output, ";SevereError\n"); + } + return NULL; +} +static int codeCond(Exp* e) { + int i1; + //fprintf(output, ";begin codecond\n"); + i1 = codeExp(e); + + char* tStr = stringForType(e->type); + currentFunctionTIndex++; + fprintf(output, "%%t%d = icmp ne %s %%t%d, 0\n", + currentFunctionTIndex, + tStr, + i1 ); + //fprintf(output, ";end codecond\n"); + i1 = currentFunctionTIndex; + + return i1; +} +static void codeCommandList(CommandL* cl) { + if(!cl) + return; + CommandL* c = cl; + //printf("CommandL\n"); + int i1,i2; + int b1,b2,b3; + while(c) { + //printf("cl\n"); + switch(c->tag) { + case CWhile: + i1 = codeCond(c->condExp); + b1 = currentBrIndex++; + b2 = currentBrIndex++; + fprintf(output, "br i1 %%t%d, label %%b%d, label %%b%d\n", + i1, + b1, + b2); + fprintf(output, "b%d:\n",b1 ); + codeCommandList(c->cmdIf ); + i2 = codeCond(c->condExp); + fprintf(output, "br i1 %%t%d, label %%b%d, label %%b%d\n", + i2, + b1, + b2); + fprintf(output, "b%d:\n",b2 ); + // leaveScope(); + break; + case CIf: + i1 = codeCond(c->condExp); + b1 = currentBrIndex++; + b2 = currentBrIndex++; + fprintf(output, "br i1 %%t%d, label %%b%d, label %%b%d\n", + i1, + b1, + b2); + fprintf(output, "b%d:\n",b1 ); + codeCommandList(c->cmdIf ); + fprintf(output, "br label %%b%d\n",b2 ); + fprintf(output, "b%d:\n",b2 ); // leaveScope(); + break; + case CIfElse: + i1 = codeCond(c->condExp); + b1 = currentBrIndex++; + b2 = currentBrIndex++; + b3 = currentBrIndex++; + fprintf(output, "br i1 %%t%d, label %%b%d, label %%b%d\n", + i1, + b1, + b2); + fprintf(output, "b%d:\n",b1 ); + codeCommandList(c->cmdIf ); + fprintf(output, "br label %%b%d\n",b3 ); + fprintf(output, "b%d:\n",b2 ); + codeCommandList(c->cmdElse ); + fprintf(output, "br label %%b%d\n",b3 ); + fprintf(output, "b%d:\n",b3 ); + break; + case CReturn: + //printf("cret\n"); + currentFuncHasReturn = 1; + if(c->retExp == NULL) { + fprintf(output, "ret void\n"); + } + else { + char * tStr = stringForType(c->retExp->type); + i1 = codeExp(c->retExp); + fprintf(output, "ret %s %%t%d\n",tStr,i1); + } + break; + case CAssign: + i1 = codeExp(c->expRight); + char* tStr = stringForType(c->expLeft->type); + char* addr = adressOfLeftAssign(c->expLeft); + + fprintf(output, "store %s %%t%d, %s* %s \n", + tStr,i1,tStr,addr); + break; + case CBlock: + //printf("cblock\n"); + codeBlock((Block*)c->block ); + // leaveScope(); + break; + case CCall: + //printf("ccall\n"); + codeExp(c->expRight); + break; + case COperator: + codeExp(c->oprExp); + //fprintf(output, ";COperator not implemented\n"); + break; + case CDebug: + fprintf(output, ";CDebug not implemented\n"); + break; + case CFor: + fprintf(output, ";CFor not implemented\n"); + break; + case CRead: + tStr = stringForType(c->printExp->type); + addr = adressOfLeftAssign(c->printExp); + fprintf(output, ";tStr %s\n", tStr); + fprintf(output,";addr %s\n", addr); + if(c->printExp->type == NULL) { + fprintf(output, ";printing void expression is unavaible\n" ); + } + else if(c->printExp->type->tag == base) { + switch(c->printExp->type->b) { + case WChar: + fprintf(output, "call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.charreadstr, i64 0, i64 0), %s* %s)\n", + tStr, + addr); + break; + case WInt: + fprintf(output, "call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.intreadstr, i64 0, i64 0), %s* %s)\n", + tStr, + addr); + break; + case WShort: + fprintf(output, "call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.shortreadstr, i64 0, i64 0), %s* %s)\n", + tStr, + addr); + break; + case WByte: + fprintf(output, "call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.intreadstr, i64 0, i64 0), %s* %s)\n", + tStr, + addr); + break; + default: + fprintf(output, "%s\n", "not implemented" ); + break; + } + } else { + fprintf(output, ";Unknown Error on Read. Not Implemented, %s* %s)\n", + tStr, + addr); + } + + + break; + case CPrint: + i1 = codeExp(c->printExp); + printf("; printexp i1 %d", i1); + printExp(c->printExp,0); + if(c->printExp->type == NULL) { + fprintf(output, ";printing void expression is unavaible\n" ); + } + else if(c->printExp->type->tag == base) { + switch(c->printExp->type->b) { + case WInt: + fprintf(output, "tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.intprintstr, i64 0, i64 0), i32 %%t%d)\n", + i1 ); + break; + case WShort: + fprintf(output, "tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.shortprintstr, i64 0, i64 0), i16 %%t%d)\n", + i1 ); + break; + case WByte: + fprintf(output, "tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.byteprintstr, i64 0, i64 0), i8 %%t%d)\n", + i1 ); + break; + case WFloat: + currentFunctionTIndex++; + fprintf(output, "%%t%d = fpext float %%t%d to double\n", + currentFunctionTIndex, + i1 ); + + fprintf(output, "tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.floatprintstr, i64 0, i64 0), double %%t%d)\n", + currentFunctionTIndex ); + break; + case WChar: + fprintf(output, "tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.charprintstr, i64 0, i64 0), i8 %%t%d)\n", + i1 ); + break; + + default: + fprintf(output, "%s\n", ";not implemented"); + break; + } + } + else if(c->printExp->type->of->tag == base && + (c->printExp->type->of->b == WChar || c->printExp->type->of->b == WByte) ) { + fprintf(output, "tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.strprintstr, i64 0, i64 0), i8* %%t%d)\n", + i1 ); + //fprintf(output, "tail call i32 @puts(i8* %%t%d)\n", i1); + + } + else { + + fprintf(output, "tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.strprintstr, i64 0, i64 0), i8* %%t%d)\n", + i1 ); + fprintf(output, ";printing non string array is unavaible\n" ); + } + // if (!checkPrintability(c->printExp)) { + // typeError("Expression is not printable"); + // } + break; + } + c = c->next; + } +} +static void codeBlock(Block* b) { + codeDefVarList(b->dvl); + codeCommandList(b->cl); +} +static int codeBinExp(Exp* e ,char * cmd) { + int te1,te2; + te1 = codeExp(e->bin.e1 ); + te2 = codeExp(e->bin.e2 ); + // te2 = currentFunctionTIndex-1; + // te1 = te2-1; + char * tStr = stringForType(e->type); + currentFunctionTIndex++; + int index = currentFunctionTIndex; + fprintf(output, "%%t%d = %s %s %%t%d, %%t%d\n", + currentFunctionTIndex++,cmd, tStr, te1,te2); + return index; +} +static int codeCallExp(Exp* e) { + int toCall = -1; + int size=0; + ExpList *p = e->call.expList; + //calculate size + while(p) { + size++; + p = p->next; + } + //generate code for arguments + p = e->call.expList; + int * args = (int*)malloc(sizeof(int)*size); + int i=0; + while(p) { + int index = codeExp(p->e); + args[i] = index; + i++; + p=p->next; + } + + if(e->type == NULL) { + fprintf(output, "call void @%s(", + e->call.id); + } + else { + char* fTypeStr = stringForType(e->type); + toCall = ++currentFunctionTIndex; + fprintf(output, "%%t%d = call %s @%s(", + toCall, + fTypeStr, + e->call.id); + } + p = e->call.expList; + i=0; + while(p) { + char* tStr = stringForType(p->e->type); + fprintf(output, "%s %%t%d",tStr,args[i]); + if(p->next) + fprintf(output, ", "); + p = p->next; + i++; + } + fprintf(output, ")\n" ); + return toCall; +} +static char* hexaStringForFloat(float c) { + double f = (double)c; + int i; + unsigned char buff[sizeof(double)]; + memcpy(buff,&f,sizeof(double)); + + char* string = (char*)malloc(sizeof(double)+3); + char temp[3] = "0x"; + strcpy(string,temp); + for(i = sizeof(double)-1;i >= 0;i--){ + sprintf(temp,"%02X",buff[i]); + strcat(string,temp); + } + return string; + +} +static char* stringForConstant(Constant* c) { + //char str[40] = "no string given"; + char* str; + double nd; + int exponent = 0; + if(!c) + return NULL; + switch(c->tag) { + case KInt: + str = (char*)malloc(40); + sprintf(str, "%d", c->u.i); + break; + case KFloat: + nd = frexp(c->u.d, &exponent); + str = hexaStringForFloat(c->u.d); + break; + case KStr: + str = (char*)c->u.str; + break; + case KBit: + str = c->u.i ? "true" : "false"; + break; + } + return &str[0]; +} +static int codeExpPrim(Exp* e) { + currentFunctionTIndex++; + char* tStr = stringForType(e->type); + if(e->c->tag == KStr) { + currentStringConstant++; + char* cStr = stringForConstant(e->c); + int len = strlen(cStr) + 1; + fprintf(output, "%%t%d = getelementptr inbounds [%d x i8], [%d x i8]* @.cstr.%d, i64 0, i64 0\n", + currentFunctionTIndex, + len, + len, + currentStringConstant ); + + pushStringToDeclare(cStr); + + return currentFunctionTIndex; + } + + char* cStr = stringForConstant(e->c); + // fprintf(output, "%%t%d = alloca %s* \n",currentFunctionTIndex); + // fprintf(output, "store i8* %0, i8** %2, align 8\n", ); + if(e->c->tag == KFloat) { + fprintf(output, "%%t%d= fadd %s 0.0 , %s\n", + currentFunctionTIndex, + tStr, + cStr ); + } else { + fprintf(output, "%%t%d= add nsw %s 0 , %s\n", + currentFunctionTIndex, + tStr, + cStr ); + } + int index = currentFunctionTIndex++; + return index; +} +static int getAddressOfVar(Var* id) { + return -1; +} +static int codeExpVar(Exp* e) { + currentFunctionTIndex++; + char* tStr = stringForType(e->type); + if(e->var->declaration == NULL) + { + //printf(";params\n"); + Parameter* p = currentParameters; + int t=0; + while(p) { + if(strcmp(e->var->id,p->id)==0) + break; + p=p->next; + t++; + } + + fprintf(output,"%%t%d = load %s, %s* %%t%d\n", + currentFunctionTIndex, + tStr, + tStr, + t); + } + else { + int scope = e->var->declaration->scope; + if(scope == 0) { + char* varAddr = stringForVarAddress(e->var->id,scope); + fprintf(output,"%%t%d = load %s, %s* %s\n", + currentFunctionTIndex, + tStr, + tStr, + varAddr); + //fprintf(output, ";global\n"); + } + else { + char* varAddr = stringForVarAddress(e->var->id,scope); + fprintf(output,"%%t%d = load %s, %s* %s\n", + currentFunctionTIndex, + tStr, + tStr, + varAddr); + + //fprintf(output, ";scope not zero\n"); + } + //printType(e->type,0); + } + return currentFunctionTIndex; +} +static int codeExpUnary(Exp* e) { + char* tStr = stringForType(e->type); + int i1,i2; + i1 = codeExp(e->unary.e); + currentFunctionTIndex++; + switch(e->unary.op) { + case MINUS: + if(e->type->b == WFloat) { + fprintf(output, "%%t%d = fsub %s 0.0, %%t%d\n", + currentFunctionTIndex, + tStr, + i1); + + } + else { + fprintf(output, "%%t%d = sub nsw %s 0, %%t%d\n", + currentFunctionTIndex, + tStr, + i1); + } + break; + case NOT: + if(e->type->b == WFloat) { + fprintf(output, "%%t%d = fcmp oeq float %%t%d, 0.0\n", + currentFunctionTIndex, + i1); + i2 = currentFunctionTIndex++; + fprintf(output, "%%t%d = uitofp i1 %%t%d to float\n", + currentFunctionTIndex, + i2); + } + else { + + fprintf(output, "%%t%d = icmp eq %s %%t%d, 0\n", + currentFunctionTIndex, + tStr, + i1); + i2 = currentFunctionTIndex++; + fprintf(output, "%%t%d = zext i1 %%t%d to %s\n", + currentFunctionTIndex, + i2, + tStr ); + } + break; + } + return currentFunctionTIndex; +} +static int typeCompare(Type* a, Type* b){ + int aSize = cellsForType(a); + int bSize = cellsForType(b); + int result = aSize - bSize; + printf("(a-b) = %d - %d = %d\n", + aSize, + bSize, + result ); + return result; +} +static int codeExpCast(Exp* e) { + printf("expCast\n"); + int i1 = codeExp(e->cast.e); + char* orTStr = stringForType(e->cast.e->type); + char* toTStr = stringForType(e->type); + currentFunctionTIndex++; + if(e->type->b == WFloat) { + fprintf(output, "%%t%d = sitofp %s %%t%d to float\n", + currentFunctionTIndex, + orTStr, + i1 ); + } + else if(e->cast.e->type->b == WFloat) { + fprintf(output, "%%t%d = fptosi float %%t%d to %s\n", + currentFunctionTIndex, + i1, + toTStr); + + } + else { + int cmp = typeCompare(e->cast.e->type,e->type); + fprintf(output, ";typecmp = %d\n",cmp); + fprintf(output,";cast: %s to %s \n", orTStr,toTStr); + if(cmp < 0) { //sext + fprintf(output, "%%t%d = sext %s %%t%d to %s\n", + currentFunctionTIndex, + orTStr, + i1, + toTStr + ); + } else if(cmp > 0) { + fprintf(output, "%%t%d = trunc %s %%t%d to %s\n", + currentFunctionTIndex, + orTStr, + i1, + toTStr ); + } else if(cmp == 0){ + fprintf(output, ";cast useless\n"); + return i1; + } + else if(e->cast.e->type->b == e->type->b) { + fprintf(output, ";cast useless\n"); + return i1; + } + else { + printf("Unknown cast: %s to %s \n", orTStr,toTStr); + fprintf(output, ";cast (%s to %s) not implemented\n", orTStr,toTStr); + return -1; + } + } + return currentFunctionTIndex; +} +static char* adressOfParameter(const char* id) { + Parameter* p = currentParameters; + int t=0; + while(p) { + if(strcmp(id,p->id)==0) + break; + p=p->next; + t++; + } + char * str = (char*)malloc(t/10+3); + sprintf(str,"%%t%d",t); + return str; + +} +static char* retranslatescape(const char* scape) { + int len = strlen(scape); + char* result = (char*)malloc(len*2); + char* smallStr; + int i,j; + for(i=0,j=0; itag == ExpAccess) { + //printf("gacr\n"); + return addressOfVector(e->access.varExp); + } + else if(e->tag == ExpVar) { + //printf("gVar\n"); + + if(e->var->declaration == NULL) + { + return adressOfParameter(e->var->id); + } + return adressOfLeftAssign(e); + } + else { + return "%%SevereError"; + } +} +static int codeGetElemPtr(Type* type,int arrayTemp,int indexTemp) { + currentFunctionTIndex++; + char* tStr = stringForType(type); + fprintf(output, "%%t%d = getelementptr %s, %s* %%t%d, i64 %%t%d\n", + currentFunctionTIndex, + tStr, + tStr, + arrayTemp, + indexTemp); + return currentFunctionTIndex; +} +static int codeAccessElemPtr(Exp* e) { + //fprintf(output,";getelementptr\n"); + int i1 = codeExp(e->access.indExp); + currentFunctionTIndex++; + fprintf(output, "%%t%d = sext i32 %%t%d to i64\n", + currentFunctionTIndex, + i1 ); + + char* tStr = stringForType(e->type); + int index = currentFunctionTIndex++; + char* str = addressOfVector(e->access.varExp); + + fprintf(output, "%%t%d = load %s*, %s** %s\n", + currentFunctionTIndex, + tStr, + tStr, + str ); + //fprintf(output,"; %s mark1\n",stringForType(e->type)); + + int startArrayAddress = currentFunctionTIndex++; + fprintf(output, "%%t%d = getelementptr %s, %s* %%t%d, i64 %%t%d\n", + currentFunctionTIndex, + tStr, + tStr, + startArrayAddress, + index); + return currentFunctionTIndex; +} +static int codeExpAccess(Exp* e) { + //fprintf(output,";Exp Access\n"); + + int i1,i2; + char* tStr; + int access; + switch (e->tag) { + case ExpAccess : + i1 = codeExp(e->access.indExp); + currentFunctionTIndex++; + fprintf(output, "%%t%d = sext i32 %%t%d to i64\n", + currentFunctionTIndex, + i1 ); + tStr = stringForType(e->type); + int index = currentFunctionTIndex++; + access = codeExp(e->access.varExp); + currentFunctionTIndex++; + + i2 = codeGetElemPtr(e->type, + access, + index); + // char* str = stringForVarAddress(e->access.varExp); + currentFunctionTIndex++; + fprintf(output, "%%t%d = load %s, %s* %%t%d\n", + currentFunctionTIndex, + tStr, + tStr, + i2 ); + + return currentFunctionTIndex; + break; + default: + //fprintf(output, ";default reached\n" ); + tStr = stringForType(e->type); + char* str = addressOfVector(e); + currentFunctionTIndex++; + fprintf(output, "%%t%d = load %s, %s* %s\n", + currentFunctionTIndex, + tStr, + tStr, + str ); + return currentFunctionTIndex; + break; + } + // i1 = codeAccessElemPtr(e); + // char* tStr = stringForType(e->type); + // currentFunctionTIndex++; + // fprintf(output, "%%t%d = load %s, %s* %%t%d\n", + // currentFunctionTIndex, + // tStr, + // tStr, + // i1); + return currentFunctionTIndex; +} +static int sizeOfType(Type* t) { + if(t->tag == base) { + switch(t->b) { + case WInt: + return sizeof(int); + break; + case WFloat: + return sizeof(float); + break; + case WChar: + return sizeof(char); + case WByte: + return sizeof(char); + case WBit: + return 1; + case WShort: + return sizeof(short); + break; + } + } + else { + return sizeof(int*); //pointer size + } +} +static int codeExpNew(Exp* e) { + int i1 = codeExp(e->eNew.e); + char * tStr = stringForType(e->type); + currentFunctionTIndex++; + fprintf(output, "%%t%d = mul i32 %%t%d, %d\n", + currentFunctionTIndex, + i1, + sizeOfType(e->type)); + i1 = currentFunctionTIndex++; + fprintf(output, " %%t%d = tail call i8* @malloc(i32 %%t%d)\n", + currentFunctionTIndex, + i1); + int i2 = currentFunctionTIndex++; + fprintf(output, "%%t%d = bitcast i8* %%t%d to %s\n", + currentFunctionTIndex, + i2, + tStr ); + return currentFunctionTIndex; +} +static void codeLabel(int label) { + fprintf(output, "b%d:\n",label); +} +static void codeBranches(int cond, int lt,int lf) { + fprintf(output, "br i1 %%t%d, label %%b%d, label %%b%d\n", + cond, + lt, + lf); +} + +static int codeCondToValue(int b1,int b2,int b3) { + fprintf(output, "b%d:\n", b1); + fprintf(output, "br label %%b%d\n", + b3); + fprintf(output, "b%d:\n", b2); + fprintf(output, "br label %%b%d\n", + b3); + fprintf(output, "b%d:\n", b3); + currentFunctionTIndex++; + fprintf(output, "%%t%d = phi i32 [ 1, %%b%d ], [0, %%b%d]\n", + currentFunctionTIndex, + b1, + b2 ); + return currentFunctionTIndex; +} +static int codeSimpleCompare(Exp* e,const char* oprStr ) { + int i1,i2; + const char* tStr = stringForType(e->cmp.e1->type); //Consider undoing symboltable autocast to int + i1 = codeExp(e->cmp.e1); + i2 = codeExp(e->cmp.e2); + currentFunctionTIndex++; + printf("%%t%d = icmp %s %s %%t%d, %%t%d\n", + currentFunctionTIndex, + oprStr, + tStr, + i1, + i2 ); + fprintf(output, "%%t%d = icmp %s %s %%t%d, %%t%d\n", + currentFunctionTIndex, + oprStr, + tStr, + i1, + i2 ); + return currentFunctionTIndex; + +} +static int codeExpCompare(Exp* e) { + int i1,i2; + int b1 = currentBrIndex++; + int b2 = currentBrIndex++; + int b3 = currentBrIndex++; + int ln; + const char* tStr = stringForType(e->type); + switch(e->cmp.op) { + case GT: + codeSimpleCompare(e,"sgt"); + break; + case GTE: + codeSimpleCompare(e,"sge"); + break; + case LS: + codeSimpleCompare(e,"slt"); + break; + case LSE: + codeSimpleCompare(e,"sle"); + break; + case EqEq: + codeSimpleCompare(e,"eq"); + break; + case OR: + i1 = codeExp(e->cmp.e1); + currentFunctionTIndex++; + fprintf(output, "%%t%d = icmp ne %s %%t%d, 0\n", + currentFunctionTIndex, + tStr, + i1); + ln = currentBrIndex++; + codeBranches(currentFunctionTIndex,b1,ln); + codeLabel(ln); + i2 = codeExp(e->cmp.e2); + currentFunctionTIndex++; + fprintf(output, "%%t%d = icmp ne %s %%t%d, 0\n", + currentFunctionTIndex, + tStr, + i2); + codeBranches(currentFunctionTIndex,b1,b2); + return codeCondToValue(b1,b2,b3); + break; + case AND: + i1 = codeExp(e->cmp.e1); + currentFunctionTIndex++; + fprintf(output, "%%t%d = icmp ne %s %%t%d, 0\n", + currentFunctionTIndex, + tStr, + i1); + ln = currentBrIndex++; + codeBranches(currentFunctionTIndex,ln,b2); + codeLabel(ln); + i2 = codeExp(e->cmp.e2); + currentFunctionTIndex++; + fprintf(output, "%%t%d = icmp ne %s %%t%d, 0\n", + currentFunctionTIndex, + tStr, + i2); + codeBranches(currentFunctionTIndex,b1,b2); + return codeCondToValue(b1,b2,b3); + break; + } + codeBranches(currentFunctionTIndex,b1,b2); + return codeCondToValue(b1,b2,b3); +} + +static int codeExpOperator(Exp* e){ + printf("Enter code exp ExpOperator\n"); + + if(!e){ + printf("null\n"); + return currentFunctionTIndex; + } + printExp(e,3); + + int i1 = codeExp(e->opr.e); + printf("get i1 %d\n",i1); + char* tStr = stringForType(e->opr.e->type); + printf("get tStr %s\n",tStr); + char* addr = adressOfLeftAssign(e->opr.e); + printf("get addr %s\n",addr); + currentFunctionTIndex++; + switch(e->opr.op) { + case INC: + fprintf(output, "%%t%d = add nsw %s %%t%d, %d\n", + currentFunctionTIndex, tStr, i1, e->opr.amount ); + fprintf(output, "store %s %%t%d, %s* %s ; align 4\n", tStr, currentFunctionTIndex, tStr, addr); + break; + case DEC: + fprintf(output, "%%t%d = add nsw %s %%t%d, -%d\n", + currentFunctionTIndex, tStr, i1, e->opr.amount ); + fprintf(output, "store %s %%t%d, %s* %s ; align 4\n", tStr, currentFunctionTIndex, tStr, addr); + break; + } + return currentFunctionTIndex; +} + +static int codeExp(Exp* e) { + int result =-1; + if(!e) + return -1; + switch(e->tag) { + case ExpAdd: + if(e->type->b == WFloat) + result = codeBinExp(e,"fadd"); + else + result = codeBinExp(e,"add nsw"); + break; + case ExpSub: + if(e->type->b == WFloat) + result = codeBinExp(e,"fsub"); + else + result =codeBinExp(e,"sub nsw"); + break; + case ExpMul: + if(e->type->b == WFloat) + result = codeBinExp(e,"fmul"); + else + result = codeBinExp(e,"mul nsw"); + break; + case ExpDiv: + if(e->type->b == WFloat) + result = codeBinExp(e,"fdiv"); + else + result = codeBinExp(e,"sdiv"); + break; + case ExpCall: + result = codeCallExp(e); + break; + case ExpVar: + result = codeExpVar(e); + break; + case ExpUnary: + result = codeExpUnary(e); + break; + case ExpOperator: + result = codeExpOperator(e); + //Not Implemented; + //result = codeExpPrim(e); + // e->type = typeOfConstant(e->c); + break; + case ExpPrim: + result = codeExpPrim(e); + // e->type = typeOfConstant(e->c); + break; + case ExpNew: + result = codeExpNew(e); + // if(!checkTypeIndex(e->eNew.e)) { + // typeError("Index of array is not an int"); + // } + // e->type = typeOfNew(e); + break; + case ExpCmp: + result = codeExpCompare(e); + + break; + case ExpAccess: + result = codeExpAccess(e); + // typeExp(e->access.varExp); + // typeExp(e->access.indExp); + // if(!checkTypeIndex(e->access.indExp)) { + // typeError("Index of array is not an int"); + // } + // e->type = e->access.varExp->type->of; + break; + case ExpCast: + result = codeExpCast(e); + // if(!checkTypeCast(e)) { + // // printType(e->type,0); + // // printType(e->cast.type,0); + // // printType(e->cast.e->type,0); + // typeError("Cast not avaible for these types"); + // } + // e->type = e->cast.type; + break; + } + + return result; +} +static void codeVar(Var* v) { + char* tStr = stringForType(v->type); + fprintf(output, "%%L%s = alloca %s\n", + v->id, tStr ); +} +void codeConstant(Constant* c); +static void codeExpList(ExpList* el) { + char * tStr; + if(!el) + return; + ExpList *p = el; + while(p) { + int index = codeExp(p->e); + tStr = stringForType(p->e->type); + fprintf(output, "%s %%t%d",tStr,index); + if(p->next) + fprintf(output, ", "); + p = p->next; + } + return; + +} \ No newline at end of file diff --git a/src/codellvm.h b/src/codellvm.h new file mode 100644 index 0000000..3bff7ad --- /dev/null +++ b/src/codellvm.h @@ -0,0 +1,7 @@ +#include +#include +#include +#include "symbolTable.h" + +void codeTreeLLVM(); +void setCodeOutputLLVM(FILE* out); \ No newline at end of file diff --git a/src/expander.c b/src/expander.c index 3de088f..e83666f 100644 --- a/src/expander.c +++ b/src/expander.c @@ -133,6 +133,7 @@ void runStr(FILE* out,char* str, int mode){ } char* expandedString(const char* str, int mode){ int size = 0; + for(char* p=(char*)str;*p;p++){ size += strlen(expand(*p,mode)); } diff --git a/src/haclib.h b/src/haclib.h new file mode 100644 index 0000000..efeb47f --- /dev/null +++ b/src/haclib.h @@ -0,0 +1,19 @@ +// Receives Headache Program, optization level and a bufferSize +// Generates a BF program and returns. Everything in RAM +char* compileHa2bf(const char* program, int level, int bufferSize); + +// Receives Headache Program, optization level +// Auto calculates the bufferSize +// Generates a BF program and returns. Everything in RAM +char* compileHa2bfAutoBuffer(const char* program, int level); + + +// Uses filepaths for input and output +// Read and write from files +void compileHa2File(const char* input, const char* output, int level); + + +//Same but outputting LLVM +char* compileHa2LLVM(const char* program, int level, int bufferSize); +char* compileHa2LLVMAutoBuffer(const char* program, int level); +void compileHa2FileLLVM(const char* input, const char* output, int level); diff --git a/src/main.c b/src/main.c index 5c58024..9fb4b54 100644 --- a/src/main.c +++ b/src/main.c @@ -44,6 +44,10 @@ #include "optimizer.h" #define optimizer_h #endif +#if !defined(codellvm_h) + #include "codellvm.h" + #define codellvm_h +#endif #include #include @@ -52,6 +56,17 @@ int yy_lines=1; //save one for EOF extern FILE* yyin; +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif +extern YY_BUFFER_STATE yy_scan_string (char *base); + + char forceExpand=0; void lexError(const char* message, int ret) { @@ -84,11 +99,11 @@ static char optimizationOptionsCount = 3; static char* breakingOptions[] = { "--help", "--version", - "--maga" + "--maga", }; static char breakingOptionsCount = 3; -static char hacVersion[] = "v0.72.0b"; +static char hacVersion[] = "v0.80.0b (LLVM)"; static int isOption(const char* candidate){ for (int i=0;i trump.jpg"); system("open trump.jpg"); - return 0; - } + + + } } else { fileName = argv[1]; option = NULL; + yyin = fopen(fileName,"r"); } @@ -301,7 +389,7 @@ int main (int argc, char** argv) printTree(); } char * bf_name = "a.bf"; - //char * bin_name = "a.out"; + char * bin_name = "a.ll"; if(!noCode) { FILE* bf_location = fopen(bf_name,"wt"); setCodeOutput(bf_location); @@ -312,16 +400,24 @@ int main (int argc, char** argv) } if(!noBin) { + FILE* bin_location = fopen(bin_name,"wt"); + setCodeOutputLLVM(bin_location); + codeTreeLLVM(); + fclose(bin_location); + char* str = handleClangOptions(argc,argv); char* buff = (char*)malloc( strlen(str) + strlen("clang") + - strlen(bf_name)+1); + strlen(bin_name)+1); sprintf(buff,"clang %s %s", str, - bf_name); + bin_name); int s = system(buff); - return s; + if(s == 0) + printf("\nLLVM binary generated\n"); + else + printf("something went wrong! clang returned %d\n", s); } if(forceExpand){ printf("should forceExpand %d\n",forceExpand ); @@ -348,3 +444,4 @@ int main (int argc, char** argv) return 0; } +#endif diff --git a/src/minifier.c b/src/minifier.c new file mode 100644 index 0000000..cfa5ec9 --- /dev/null +++ b/src/minifier.c @@ -0,0 +1,108 @@ + +#include +#include +#include +#include +#include "testbfi.h" +void minifyBf(char* bf); +void simplifyBf(char* bf); +int main(int argc, char** argv) { + if(argc < 2) { + printf("Usage %s file.bf\n",argv[0]); + return 1; + } + char* bf = readFileFast(argv[1]); + if(!bf){ + printf("Error: Can't open %s\n",argv[1]); + return 2; + } + //int c1 = clock(); + minifyBf(bf); + //int c2 = clock(); + simplifyBf(bf); + //int c3 = clock(); + printf("%s\n",bf); + //int c4 = clock(); + // printf("minify %d cicles\n", c2 - c1); + //printf("simplify %d cicles\n", c3 - c2); + //printf("print %d cicles\n", c4 - c3); + free(bf); + return 0; +} +void minifyBf(char* bf){ + char* p, *q; + p = bf; + q = bf; + while(*p){ + switch(*p){ + case '>': + case '<': + case '+': + case '-': + case ',': + case '.': + case '[': + case ']': + *q = *p; + q++; + } + p++; + } + q++; + *q = '\0'; +} + +// int shouldCollapse(char* stack, int len) { +// if (len <= 1) return 0; +// char top = stack[len - 1]; +// char subtop = stack[len - 2]; +// return (top == '>' && subtop == '<') || (top == '<' && subtop == '>') +// || (top == '+' && subtop == '-') || (top == '-' && subtop == '+'); +// } + +// void simplifyBf(char* bf) { +// int len = strlen(bf); +// int writeIdx = 0; +// for (int i = 0; i < len; ++i) { +// bf[writeIdx] = bf[i]; +// writeIdx++; +// while (writeIdx > 1 && shouldCollapse(bf, writeIdx)) { +// writeIdx -= 2; +// } +// } +// bf[writeIdx] = '\0'; +// } + + +int shouldCollapse(char *stack){ + int len = strlen(stack); + if(len <= 1) return 0; + char* top = stack + len - 1; + char* subtop = top - 1; + return (*top == '>' && *subtop == '<') || (*top == '<' && *subtop == '>') + || (*top == '+' && *subtop == '-') || (*top == '-' && *subtop == '+'); + +} +void simplifyBf(char* bf){ + char* p; + char* stack = (char*)malloc(strlen(bf)); + char * s = stack; + p = bf; + *s = *p; + while(*p){ + *s = *p; + s++; + while(shouldCollapse(stack)){ + *s = '\0'; + s--; + *s = '\0'; + s--; + } + p++; + } + s++; + *s = '\0'; + p = bf; + strcpy(p,stack); + free(stack); +} diff --git a/src/optimizer.c b/src/optimizer.c index ed5bb2d..32a10a2 100644 --- a/src/optimizer.c +++ b/src/optimizer.c @@ -170,52 +170,40 @@ void optimizeCommandList(CommandL* cl) { } void optimizeCommandPrint(CommandL* cl){ - if(cl->tag == CPrint && cl->printExp->tag == ExpPrim && cl->printExp->c->tag == KStr){ - printf("will opt 1\n"); - if(cl->next != NULL && cl->next->tag == CPrint && cl->next->printExp->tag == ExpPrim && cl->next->printExp->c->tag == KStr){ - printf("will opt 2\n"); - // if((cl->printExp->c == NULL) || (cl->next->printExp->c == NULL)){ - // printf("Fuck off 1\n"); - // return; - // } - // if((cl->printExp->c->u.str == NULL) || (cl->next->printExp->c->u.str == NULL)){ - // printExp(cl->next->printExp,3); - // printf("Fuck off 2\n"); - // return; - // } - // if(cl->printExp->tag == ExpVar || cl->next->printExp->tag == ExpVar){ - // printf("Fuck off 3\n"); - // return; - // } - //printCommandList(cl,1); + if(cl->tag == CPrint && + cl->printExp->tag == ExpPrim && cl->printExp->c->tag == KStr){ + //printf("will opt 1\n"); + if(cl->next != NULL && cl->next->tag == CPrint + && cl->next->printExp->tag == ExpPrim && cl->next->printExp->c->tag == KStr){ + //printf("will opt 2\n"); + cl->next->printExp = optimizeExp(cl->next->printExp); - printf("will opt 3\n"); + //printf("will opt 3\n"); optimizeExpPrint(cl->next->printExp); - printf("will opt 4\n"); + //printf("will opt 4\n"); optimizeCommandPrint(cl->next); //this should be possible, but it was crashing - printf("will opt 5\n"); + //printf("will opt 5\n"); int x = strlen(cl->printExp->c->u.str); - printf("will opt 5.1 %d\n",x); + //printf("will opt 5.1 %d\n",x); - printExp(cl->next->printExp,20); + //printExp(cl->next->printExp,20); int y = strlen(cl->next->printExp->c->u.str); - printf("will opt 5.2 (%d)\n",y); + //printf("will opt 5.2 (%d)\n",y); char* newStr = malloc(strlen(cl->printExp->c->u.str) + strlen(cl->next->printExp->c->u.str)+1); - printf("will opt 6 b\n"); + //printf("will opt 6 b\n"); sprintf(newStr,"%s%s",cl->printExp->c->u.str,cl->next->printExp->c->u.str); - //free(cl->printExp->c->u.str); - //free(cl->next->printExp->c->u.str); - printf("will opt 7\n"); + // free(cl->printExp->c->u.str); + // free(cl->next->printExp->c->u.str); + //printf("will opt 7\n"); cl->printExp->c->u.str = newStr; - printf("will opt 8\n"); + //printf("will opt 8\n"); + //free(cl->next->printExp); cl->next = cl->next->next; - printf("will opt 9\n"); - // free(cl->next->printExp->c); - // free(cl->next->printExp); - // free(cl->next); + //printf("will opt 9\n"); + //free(cl->next); } } } diff --git a/src/rules.lex b/src/rules.lex index f9eb794..105b27b 100644 --- a/src/rules.lex +++ b/src/rules.lex @@ -70,7 +70,6 @@ "byte" {return TK_WBYTE;} "char" {return TK_WCHAR;} "else" {return TK_WELSE; } - "if" {return TK_WIF;} "int" {return TK_WINT;} "new" {return TK_WNEW;} @@ -105,9 +104,9 @@ "/" {return '/';} "," {return ',';} "@" {return '@';} -"print" {return '@';} +"print" {return '@';} "#" {return '#';} -"read" {return '#';} +"read" {return '#';} "%" {return '%';} "0x"([0-9]|[A-F]|[a-f])+ {yylval.int_val = strtol(yytext, NULL, 0); diff --git a/src/symbolTable.c b/src/symbolTable.c index 0a24a8e..d65f0dc 100644 --- a/src/symbolTable.c +++ b/src/symbolTable.c @@ -83,7 +83,7 @@ void raiseError(const char* message,int line) { exit(01); } void raiseWarning(const char* message,int line) { - printf("Warning: %s\n# near line %d",message,line); + printf("Warning: %s\n# near line %d\n",message,line); warningCount++; } void generateStardardDeclares(progNode* prog) { @@ -514,6 +514,15 @@ void promoteType(Exp ** eptr) { performCastToType(t,eptr); } } +void promoteToType(Exp ** eptr, Type* t0) { + Exp* e = *eptr; + if(e->type->tag == base && e->type->b == WByte) { + Type* t = (Type*)malloc(sizeof(Type)); + t->tag = t0->tag; + t->b = t0->b; + performCastToType(t,eptr); + } +} BType BTypeOfArith(Exp* e1,Exp *e2) { if(e1->type->b == WFloat || e2->type->b == WFloat) @@ -809,11 +818,14 @@ void typeExp(Exp* e ) { typeExp(e->cmp.e2); //promoteType(&e->cmp.e1); //promoteType(&e->cmp.e2); + switch(e->cmp.op) { default: if(!checkTypeLogic(e->cmp.e1) || !checkTypeLogic(e->cmp.e2)) { raiseError("Types not suitble for logic",e->dbg_line); + } else { + promoteToType(&e->cmp.e2,e->cmp.e1->type); } break; case EqEq: @@ -822,6 +834,8 @@ void typeExp(Exp* e ) { // printType(e->cmp.e1->type,0); // printType(e->cmp.e2->type,0); raiseError("Not comparable types in ==",e->dbg_line); + } else { + promoteToType(&e->cmp.e2,e->cmp.e1->type); } } break; diff --git a/src/tree.h b/src/tree.h index ec3459a..720d2d7 100644 --- a/src/tree.h +++ b/src/tree.h @@ -53,7 +53,20 @@ typedef struct Parameter -typedef enum CTypes { CWhile, CIf, CIfElse, CReturn, CAssign, CBlock, CCall,CPrint, CDebug, COperator, CRead, CFor } CTypes; +typedef enum CTypes { + CWhile, + CIf, + CIfElse, + CReturn, + CAssign, + CBlock, + CCall, + CPrint, + CDebug, + COperator, + CRead, + CFor +} CTypes;