diff --git a/3-lang0ll/.gitignore b/3-lang0ll/.gitignore new file mode 100644 index 0000000..8ef60f2 --- /dev/null +++ b/3-lang0ll/.gitignore @@ -0,0 +1,4 @@ +/lang0c*.c +/lang0c*.exe +/lang0c*.ll +/lang0c*.o diff --git a/3-lang0ll/Makefile b/3-lang0ll/Makefile new file mode 100644 index 0000000..c5d6266 --- /dev/null +++ b/3-lang0ll/Makefile @@ -0,0 +1,42 @@ +.SUFFIXES: + + + + + +LANG0C=$(CURDIR)/../2-lang0c/lang0c.exe + +all: lang0ll.exe + +%.exe: %.s + clang $^ -o $@ + +%.s: %.ll + llc --relocation-model=pic $^ + +lang0ll0.c: lang0ll.lang0 $(LANG0C) + cat $< | $(LANG0C) > $@ + +lang0ll0.o: lang0ll0.c + gcc -c $< + +lang0ll0.exe: lang0ll0.o + gcc -o $@ $< + +lang0ll1.ll: lang0ll.lang0 lang0ll0.exe + cat $< | ./lang0ll0.exe > $@ +# Cannot diff on the first iteration - platform change + +lang0ll2.ll: lang0ll.lang0 lang0ll1.exe + cat $< | ./lang0ll1.exe > $@ + -diff lang0ll1.ll lang0ll2.ll + +lang0ll.ll: lang0ll.lang0 lang0ll2.exe + cat $< | ./lang0ll2.exe > $@ + -diff lang0ll2.ll lang0ll.ll + +foo.ll: foo.c + clang -S -emit-llvm $^ + +clean: + rm -f lang0ll*.py lang0ll*.ll lang0ll*.o lang0ll*.exe foo.ll foo.o foo.exe diff --git a/3-lang0ll/foo.c b/3-lang0ll/foo.c new file mode 100644 index 0000000..b0800e5 --- /dev/null +++ b/3-lang0ll/foo.c @@ -0,0 +1,17 @@ +void print(char * x) +{ + return; +} + +int sum(int a, int b) +{ + return a + b; +} + +int main() +{ + char * foo = "Hello, world!"; + print("This is a test."); + + return sum(7, 15); +} diff --git a/3-lang0ll/foo.exe b/3-lang0ll/foo.exe new file mode 100755 index 0000000..0d9c015 Binary files /dev/null and b/3-lang0ll/foo.exe differ diff --git a/3-lang0ll/foo.ll b/3-lang0ll/foo.ll new file mode 100644 index 0000000..bf91454 --- /dev/null +++ b/3-lang0ll/foo.ll @@ -0,0 +1,49 @@ +; ModuleID = 'foo.c' +source_filename = "foo.c" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +@.str = private unnamed_addr constant [14 x i8] c"Hello, world!\00", align 1 +@.str.1 = private unnamed_addr constant [16 x i8] c"This is a test.\00", align 1 + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local void @print(i8* noundef %0) #0 { + %2 = alloca i8*, align 8 + store i8* %0, i8** %2, align 8 + ret void +} + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local i32 @sum(i32 noundef %0, i32 noundef %1) #0 { + %3 = alloca i32, align 4 + %4 = alloca i32, align 4 + store i32 %0, i32* %3, align 4 + store i32 %1, i32* %4, align 4 + %5 = load i32, i32* %3, align 4 + %6 = load i32, i32* %4, align 4 + %7 = add nsw i32 %5, %6 + ret i32 %7 +} + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local i32 @main() #0 { + %1 = alloca i32, align 4 + %2 = alloca i8*, align 8 + store i32 0, i32* %1, align 4 + store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0), i8** %2, align 8 + call void @print(i8* noundef getelementptr inbounds ([16 x i8], [16 x i8]* @.str.1, i64 0, i64 0)) + %3 = call i32 @sum(i32 noundef 7, i32 noundef 15) + ret i32 %3 +} + +attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.module.flags = !{!0, !1, !2, !3, !4} +!llvm.ident = !{!5} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 7, !"PIC Level", i32 2} +!2 = !{i32 7, !"PIE Level", i32 2} +!3 = !{i32 7, !"uwtable", i32 1} +!4 = !{i32 7, !"frame-pointer", i32 2} +!5 = !{!"Ubuntu clang version 14.0.0-1ubuntu1.1"} diff --git a/3-lang0ll/lang0ll.lang0 b/3-lang0ll/lang0ll.lang0 new file mode 100644 index 0000000..3be2e41 --- /dev/null +++ b/3-lang0ll/lang0ll.lang0 @@ -0,0 +1,472 @@ +increaseindent indent: + calc indent addstringchar indent " " + calc indent addstringchar indent " " + calc indent addstringchar indent " " + calc indent addstringchar indent " " + return indent +/ + +lexident: + declare char + declare isbeforea + declare isafterz + declare word + set word "" + forever + calc char peek + calc isbeforea lt char "a" + if isbeforea + break + / + calc isafterz lt "z" char + if isafterz + break + / + calc word addstringchar word char + skip + / + return word +/ + +parseconststring: + declare char + declare iseof + declare isquote + skipchar quote + forever + calc char peek + calc iseof eq char eof + if iseof + break + / + calc isquote eq char quote + if isquote + break + / + skip + / + skipchar quote + emit "i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)" + return +/ + +parseexprvarref: + declare varname + calc varname lexident + emit "i8* %" + emit varname + return +/ + +parseexprcall: + declare char + declare first + declare funcname + declare isspace + declare isnotspace + declare isfirst + declare isnotfirst + declare isquote + declare isnotquote + calc funcname lexident + emit funcname + emit "(" + set first "1" + forever + calc char peek + calc isspace eq char " " + calc isnotspace not isspace + if isnotspace + break + / + skip + calc isfirst eq first "1" + calc isnotfirst not isfirst + if isnotfirst + emit ", " + / + calc char peek + calc isquote eq char quote + calc isnotquote not isquote + if isquote + parseconststring + / + if isnotquote + parseexprvarref + / + set first "0" + / + emit ")" + return +/ + +parsestatdeclare indent: + declare var + skipchar " " + calc var lexident + emit indent + emit "char * var_" + emit var + emit ";" + emit eol + skipchar eol + return +/ + +parsestatset indent: + declare var + skipchar " " + calc var lexident + skipchar " " + emit indent + emit "var_" + emit var + emit " = " + parseconststring + emit ";" + emit eol + skipchar eol + return +/ + +parsestatcalc indent: + declare var + declare varidx + skipchar " " + calc var lexident + skipchar " " + emit indent + emit "%" + emit var + calc varidx mapgetkey "funcvarused" var + calc varidx intinc varidx + mapsetkey "funcvarused" var varidx + emit "." + emit varidx + emit " = call i8* @" + parseexprcall + emit ";" + emit eol + skipchar eol + return +/ + +parseblock indent/ + +parsestatif indent: + declare indentt + skipchar " " + emit indent + emit "if ( 0 < strlen(" + parseexprvarref + emit ") )\n" + emit indent + emit "{\n" + skipchar eol + calc indentt increaseindent indent + parseblock indentt + emit indent + emit "}\n" + return +/ + +parsestatforever indent: + declare indentt + emit indent + emit "while (1)\n" + emit indent + emit "{\n" + skipchar eol + calc indentt increaseindent indent + parseblock indentt + emit indent + emit "}\n" + return +/ + +parsestatbreak indent: + emit indent + emit "break;\n" + skipchar eol + return +/ + +parsestatreturn indent: + declare char + declare isspace + declare isnotspace + emit indent + emit "ret " + calc char peek + calc isspace eq char " " + calc isnotspace not isspace + if isspace + skip + parseexprvarref + / + if isnotspace + emit "i18* 0" + / + emit ";" + emit eol + skipchar eol + return +/ + +parsestattrace indent: + declare varname + emit indent + emit "trace(" + emit quote + skipchar " " + calc varname lexident + emit varname + emit quote + emit ", var_" + emit varname + emit ");\n" + skipchar eol + return +/ + +parsestat indent: + declare call + declare char + declare first + declare iscall + declare isfirst + declare isspace + declare isquote + declare isnotfirst + declare isnotspace + declare isnotquote + calc call lexident + trace call + calc iscall eq call "declare" + if iscall + parsestatdeclare indent + return + / + calc iscall eq call "set" + if iscall + parsestatset indent + return + / + calc iscall eq call "calc" + if iscall + parsestatcalc indent + return + / + calc iscall eq call "if" + if iscall + parsestatif indent + return + / + calc iscall eq call "forever" + if iscall + parsestatforever indent + return + / + calc iscall eq call "break" + if iscall + parsestatbreak indent + return + / + calc iscall eq call "return" + if iscall + parsestatreturn indent + return + / + calc iscall eq call "trace" + if iscall + parsestattrace indent + return + / + emit indent + emit call + emit "(" + set first "1" + forever + calc char peek + calc isspace eq char " " + calc isnotspace not isspace + if isnotspace + break + / + skip + calc char peek + calc isquote eq char quote + calc isnotquote not isquote + if isquote + parseconststring + / + if isnotquote + parseexprvarref + / + calc isfirst eq first "1" + calc isnotfirst not isfirst + if isnotfirst + emit ", " + / + set first "0" + / + skipchar eol + emit ");\n" + return +/ + +parseblock indent: + declare char + declare copy + declare iseol + declare isnoteol + declare isdone + declare iseoblock + forever + forever + calc char peek + calc iseol eq char eol + calc isnoteol not iseol + if isnoteol + break + / + skip + / + set copy " " + forever + calc isdone eq copy indent + if isdone + break + / + skipchar "\t" + calc copy increaseindent copy + / + calc char peek + calc iseoblock eq char "/" + if iseoblock + skip + skipchar eol + break + / + skipchar "\t" + parsestat indent + / + return +/ + +parsefunc: + declare char + declare first + declare funcname + declare iseoblock + declare isfirst + declare isspace + declare isnotfirst + declare isnotspace + declare var + mapclear "funcvarused" + calc funcname lexident + trace funcname + emit "define i8* @" + emit funcname + emit "(" + set first "1" + forever + calc char peek + calc isspace eq char " " + calc isnotspace not isspace + if isnotspace + break + / + skip + calc var lexident + calc isfirst eq first "1" + calc isnotfirst not isfirst + if isnotfirst + emit ", " + / + emit "i8* %" + emit var + mapsetkey "funcvarused" "var" "0" + emit "_0" + set first "0" + / + calc char peek + calc iseoblock eq char "/" + if iseoblock + skipchar "/" + skipchar eol + emit ");" + emit "\n" + return + / + skipchar ":" + skipchar eol + emit ")\n{\n" + parseblock " " + emit "}\n\n" + return +/ + +emitheader: + emit "target datalayout = " + emit quote + emit "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + emit quote + emit eol + + emit "target triple = " + emit quote + emit "x86_64-pc-linux-gnu" + emit quote + emit eol + + emit eol + + emit "define i8* @addstringchar(i8* %0, i8* %1)" + emit eol + emit "{" + emit eol + emit " ; todo" + emit eol + emit " ret i8* %0;" + emit eol + emit "}" + emit eol + + emit eol + + return +/ + +emitfooter: + emit "" + return +/ + +main: + declare char + declare iseof + declare iseol + declare isnoteol + emitheader + forever + calc char peek + calc iseof eq char eof + if iseof + break + / + forever + calc char peek + calc iseol eq char eol + calc isnoteol not iseol + if isnoteol + break + / + skip + / + parsefunc + / + emitfooter + return +/ diff --git a/3-lang0ll/lang0ll0.c b/3-lang0ll/lang0ll0.c new file mode 100644 index 0000000..18a3f4a --- /dev/null +++ b/3-lang0ll/lang0ll0.c @@ -0,0 +1,608 @@ +#include +#include +#include +#include + + +char var_eof[2] = {-1, 0}; +char var_eol[2] = {10, 0}; +char var_quote[2] = {34, 0}; +char var_false[1] = {0}; +char var_true[2] = {'1', 0}; + + +char * eq(char * a, char * b) +{ + return (strcmp(a, b) == 0) ? var_true : var_false; +} + +char * lt(char * a, char * b) +{ + return (strcmp(a, b) < 0) ? var_true : var_false; +} +char * not(char * a) +{ + return (strcmp(a, var_true) != 0) ? var_true : var_false; +} + +char * addstringchar(char * str, char * chr) +{ + int str_len = strlen(str); + assert(strlen(chr) == 1); + char * res = malloc((str_len + 2) * sizeof(char)); + strcpy(res, str); + res[str_len + 0] = chr[0]; + res[str_len + 1] = 0; + return res; +} + +char * emit(char * str) +{ + fputs(str, stdout); + return 0; +} + +char * trace(char * var_name, char * var_value) +{ + const char * env_trace = getenv("TRACE"); + if( !env_trace ) return 0; + fputs(var_name, stderr); + fputs("=", stderr); + fputs(var_value, stderr); + fputs(var_eol, stderr); + return 0; +} + +int LINE = 1; + +char * peek() +{ + char * res = malloc(2*sizeof(char)); + res[0] = getc(stdin); + res[1] = 0; + ungetc(res[0], stdin); + return res; +} + +void skip() +{ + char c = getc(stdin); + if( c == 10 ) LINE += 1; +} + +void skipchar(char * chr) +{ + assert(strlen(chr) == 1); + char * act = peek(); + assert(strlen(act) == 1); + if( chr[0] == act[0] ) {skip(); return;}; + fprintf(stderr, "Expected '%c' on line %d but saw '%c' instead%c", chr[0], LINE, act[0], 10); + exit(1); +} + +char * increaseindent(char * var_indent) +{ + var_indent = addstringchar(var_indent, " "); + var_indent = addstringchar(var_indent, " "); + var_indent = addstringchar(var_indent, " "); + var_indent = addstringchar(var_indent, " "); + return var_indent; +} + +char * lexident() +{ + char * var_char; + char * var_isbeforea; + char * var_isafterz; + char * var_word; + var_word = ""; + while (1) + { + var_char = peek(); + var_isbeforea = lt(var_char, "a"); + if ( 0 < strlen(var_isbeforea) ) + { + break; + } + var_isafterz = lt("z", var_char); + if ( 0 < strlen(var_isafterz) ) + { + break; + } + var_word = addstringchar(var_word, var_char); + skip(); + } + return var_word; +} + +char * parseconststring() +{ + char * var_char; + char * var_iseof; + char * var_isquote; + skipchar(var_quote); + while (1) + { + var_char = peek(); + var_iseof = eq(var_char, var_eof); + if ( 0 < strlen(var_iseof) ) + { + break; + } + var_isquote = eq(var_char, var_quote); + if ( 0 < strlen(var_isquote) ) + { + break; + } + skip(); + } + skipchar(var_quote); + emit("i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)"); + return 0; +} + +char * parseexprvarref() +{ + char * var_varname; + var_varname = lexident(); + emit("i8* %"); + emit(var_varname); + return 0; +} + +char * parseexprcall() +{ + char * var_char; + char * var_first; + char * var_funcname; + char * var_isspace; + char * var_isnotspace; + char * var_isfirst; + char * var_isnotfirst; + char * var_isquote; + char * var_isnotquote; + var_funcname = lexident(); + emit(var_funcname); + emit("("); + var_first = "1"; + while (1) + { + var_char = peek(); + var_isspace = eq(var_char, " "); + var_isnotspace = not(var_isspace); + if ( 0 < strlen(var_isnotspace) ) + { + break; + } + skip(); + var_isfirst = eq(var_first, "1"); + var_isnotfirst = not(var_isfirst); + if ( 0 < strlen(var_isnotfirst) ) + { + emit(", "); + } + var_char = peek(); + var_isquote = eq(var_char, var_quote); + var_isnotquote = not(var_isquote); + if ( 0 < strlen(var_isquote) ) + { + parseconststring(); + } + if ( 0 < strlen(var_isnotquote) ) + { + parseexprvarref(); + } + var_first = "0"; + } + emit(")"); + return 0; +} + +char * parsestatdeclare(char * var_indent) +{ + char * var_var; + skipchar(" "); + var_var = lexident(); + emit(var_indent); + emit("char * var_"); + emit(var_var); + emit(";"); + emit(var_eol); + skipchar(var_eol); + return 0; +} + +char * parsestatset(char * var_indent) +{ + char * var_var; + skipchar(" "); + var_var = lexident(); + skipchar(" "); + emit(var_indent); + emit("var_"); + emit(var_var); + emit(" = "); + parseconststring(); + emit(";"); + emit(var_eol); + skipchar(var_eol); + return 0; +} + +char * parsestatcalc(char * var_indent) +{ + char * var_var; + char * var_varidx; + skipchar(" "); + var_var = lexident(); + skipchar(" "); + emit(var_indent); + emit("%"); + emit(var_var); + var_varidx = mapgetkey("funcvarused", var_var); + var_varidx = intinc(var_varidx); + mapsetkey("funcvarused"var_var, var_varidx, ); + emit("."); + emit(var_varidx); + emit(" = call i8* @"); + parseexprcall(); + emit(";"); + emit(var_eol); + skipchar(var_eol); + return 0; +} + +char * parseblock(char * var_indent); +char * parsestatif(char * var_indent) +{ + char * var_indentt; + skipchar(" "); + emit(var_indent); + emit("if ( 0 < strlen("); + parseexprvarref(); + emit(") )\n"); + emit(var_indent); + emit("{\n"); + skipchar(var_eol); + var_indentt = increaseindent(var_indent); + parseblock(var_indentt); + emit(var_indent); + emit("}\n"); + return 0; +} + +char * parsestatforever(char * var_indent) +{ + char * var_indentt; + emit(var_indent); + emit("while (1)\n"); + emit(var_indent); + emit("{\n"); + skipchar(var_eol); + var_indentt = increaseindent(var_indent); + parseblock(var_indentt); + emit(var_indent); + emit("}\n"); + return 0; +} + +char * parsestatbreak(char * var_indent) +{ + emit(var_indent); + emit("break;\n"); + skipchar(var_eol); + return 0; +} + +char * parsestatreturn(char * var_indent) +{ + char * var_char; + char * var_isspace; + char * var_isnotspace; + emit(var_indent); + emit("ret "); + var_char = peek(); + var_isspace = eq(var_char, " "); + var_isnotspace = not(var_isspace); + if ( 0 < strlen(var_isspace) ) + { + skip(); + parseexprvarref(); + } + if ( 0 < strlen(var_isnotspace) ) + { + emit("i18* 0"); + } + emit(";"); + emit(var_eol); + skipchar(var_eol); + return 0; +} + +char * parsestattrace(char * var_indent) +{ + char * var_varname; + emit(var_indent); + emit("trace("); + emit(var_quote); + skipchar(" "); + var_varname = lexident(); + emit(var_varname); + emit(var_quote); + emit(", var_"); + emit(var_varname); + emit(");\n"); + skipchar(var_eol); + return 0; +} + +char * parsestat(char * var_indent) +{ + char * var_call; + char * var_char; + char * var_first; + char * var_iscall; + char * var_isfirst; + char * var_isspace; + char * var_isquote; + char * var_isnotfirst; + char * var_isnotspace; + char * var_isnotquote; + var_call = lexident(); + trace("call", var_call); + var_iscall = eq(var_call, "declare"); + if ( 0 < strlen(var_iscall) ) + { + parsestatdeclare(var_indent); + return 0; + } + var_iscall = eq(var_call, "set"); + if ( 0 < strlen(var_iscall) ) + { + parsestatset(var_indent); + return 0; + } + var_iscall = eq(var_call, "calc"); + if ( 0 < strlen(var_iscall) ) + { + parsestatcalc(var_indent); + return 0; + } + var_iscall = eq(var_call, "if"); + if ( 0 < strlen(var_iscall) ) + { + parsestatif(var_indent); + return 0; + } + var_iscall = eq(var_call, "forever"); + if ( 0 < strlen(var_iscall) ) + { + parsestatforever(var_indent); + return 0; + } + var_iscall = eq(var_call, "break"); + if ( 0 < strlen(var_iscall) ) + { + parsestatbreak(var_indent); + return 0; + } + var_iscall = eq(var_call, "return"); + if ( 0 < strlen(var_iscall) ) + { + parsestatreturn(var_indent); + return 0; + } + var_iscall = eq(var_call, "trace"); + if ( 0 < strlen(var_iscall) ) + { + parsestattrace(var_indent); + return 0; + } + emit(var_indent); + emit(var_call); + emit("("); + var_first = "1"; + while (1) + { + var_char = peek(); + var_isspace = eq(var_char, " "); + var_isnotspace = not(var_isspace); + if ( 0 < strlen(var_isnotspace) ) + { + break; + } + skip(); + var_char = peek(); + var_isquote = eq(var_char, var_quote); + var_isnotquote = not(var_isquote); + if ( 0 < strlen(var_isquote) ) + { + parseconststring(); + } + if ( 0 < strlen(var_isnotquote) ) + { + parseexprvarref(); + } + var_isfirst = eq(var_first, "1"); + var_isnotfirst = not(var_isfirst); + if ( 0 < strlen(var_isnotfirst) ) + { + emit(", "); + } + var_first = "0"; + } + skipchar(var_eol); + emit(");\n"); + return 0; +} + +char * parseblock(char * var_indent) +{ + char * var_char; + char * var_copy; + char * var_iseol; + char * var_isnoteol; + char * var_isdone; + char * var_iseoblock; + while (1) + { + while (1) + { + var_char = peek(); + var_iseol = eq(var_char, var_eol); + var_isnoteol = not(var_iseol); + if ( 0 < strlen(var_isnoteol) ) + { + break; + } + skip(); + } + var_copy = " "; + while (1) + { + var_isdone = eq(var_copy, var_indent); + if ( 0 < strlen(var_isdone) ) + { + break; + } + skipchar("\t"); + var_copy = increaseindent(var_copy); + } + var_char = peek(); + var_iseoblock = eq(var_char, "/"); + if ( 0 < strlen(var_iseoblock) ) + { + skip(); + skipchar(var_eol); + break; + } + skipchar("\t"); + parsestat(var_indent); + } + return 0; +} + +char * parsefunc() +{ + char * var_char; + char * var_first; + char * var_funcname; + char * var_iseoblock; + char * var_isfirst; + char * var_isspace; + char * var_isnotfirst; + char * var_isnotspace; + char * var_var; + mapclear("funcvarused"); + var_funcname = lexident(); + trace("funcname", var_funcname); + emit("define i8* @"); + emit(var_funcname); + emit("("); + var_first = "1"; + while (1) + { + var_char = peek(); + var_isspace = eq(var_char, " "); + var_isnotspace = not(var_isspace); + if ( 0 < strlen(var_isnotspace) ) + { + break; + } + skip(); + var_var = lexident(); + var_isfirst = eq(var_first, "1"); + var_isnotfirst = not(var_isfirst); + if ( 0 < strlen(var_isnotfirst) ) + { + emit(", "); + } + emit("i8* %"); + emit(var_var); + mapsetkey("funcvarused""var", "0", ); + emit("_0"); + var_first = "0"; + } + var_char = peek(); + var_iseoblock = eq(var_char, "/"); + if ( 0 < strlen(var_iseoblock) ) + { + skipchar("/"); + skipchar(var_eol); + emit(");"); + emit("\n"); + return 0; + } + skipchar(":"); + skipchar(var_eol); + emit(")\n{\n"); + parseblock(" "); + emit("}\n\n"); + return 0; +} + +char * emitheader() +{ + emit("target datalayout = "); + emit(var_quote); + emit("e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"); + emit(var_quote); + emit(var_eol); + emit("target triple = "); + emit(var_quote); + emit("x86_64-pc-linux-gnu"); + emit(var_quote); + emit(var_eol); + emit(var_eol); + emit("define i8* @addstringchar(i8* %0, i8* %1)"); + emit(var_eol); + emit("{"); + emit(var_eol); + emit(" ; todo"); + emit(var_eol); + emit(" ret i8* %0;"); + emit(var_eol); + emit("}"); + emit(var_eol); + emit(var_eol); + return 0; +} + +char * emitfooter() +{ + emit(""); + return 0; +} + +char * main() +{ + char * var_char; + char * var_iseof; + char * var_iseol; + char * var_isnoteol; + emitheader(); + while (1) + { + var_char = peek(); + var_iseof = eq(var_char, var_eof); + if ( 0 < strlen(var_iseof) ) + { + break; + } + while (1) + { + var_char = peek(); + var_iseol = eq(var_char, var_eol); + var_isnoteol = not(var_iseol); + if ( 0 < strlen(var_isnoteol) ) + { + break; + } + skip(); + } + parsefunc(); + } + emitfooter(); + return 0; +} + diff --git a/3-lang0ll/notes.ll b/3-lang0ll/notes.ll new file mode 100644 index 0000000..baa573c --- /dev/null +++ b/3-lang0ll/notes.ll @@ -0,0 +1,19 @@ +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +define i8* @addstringchar(i8* %0, i8* %1) +{ + ; todo + ret i8* %0; +} + +define i8* @increaseindent(i8* %indent) +{ + %indent.1 = call i8* @addstringchar(i8* %indent, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)); + %indent.2 = call i8* @addstringchar(i8* %indent.1, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)); + %indent.3 = call i8* @addstringchar(i8* %indent.2, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)); + %indent.4 = call i8* @addstringchar(i8* %indent.3, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)); + ret i8* %indent.4; +} + +@.str = private unnamed_addr constant [14 x i8] c"Hello, world!\00", align 1 diff --git a/README.md b/README.md index d14e8ea..ae4c5bb 100644 --- a/README.md +++ b/README.md @@ -133,12 +133,44 @@ Writes the given string to standard output. Return true if the given strings are the same. +#### intinc a + +Available in it2 runtime and onwards. + +Interprets string `a` as an integer, increases it by one and returns it (as a string). +If `a` cannot be interpreted as an integer, or has additional bytes, this function returns 1. + #### lt a b `a` and `b` are expected to have length 1. Return true if a would sort before b. +#### mapclear mapname + +Available in it2 runtime and onwards. + +Maps are global and can be used from any function. + +Clears all values set in the map named `mapname`. + +#### mapgetkey mapname key + +Available in it2 runtime and onwards. + +Maps are global and can be used from any function. + +Looks up `key` in the map named `mapname` and returns it. +If not found, returns an empty string. + +#### mapsetkey mapname key value + +Available in it2 runtime and onwards. + +Maps are global and can be used from any function. + +Adds a mapping from `key` to `value` to the map named `mapname`. + #### peek Checks stdin for the next character and returns it.