diff --git a/3-lang0ll/Makefile b/3-lang0ll/Makefile index 40b03c4..4a2024c 100644 --- a/3-lang0ll/Makefile +++ b/3-lang0ll/Makefile @@ -25,14 +25,17 @@ lang0ll0.exe: lang0ll0.o lang0ll1.ll: lang0ll.lang0 lang0ll0.exe cat $< | ./lang0ll0.exe > $@ + sed -i '/^.*; pre-declaration$$/d' $@ # Cannot diff on the first iteration - platform change lang0ll2.ll: lang0ll.lang0 lang0ll1.exe cat $< | ./lang0ll1.exe > $@ + sed -i '/^.*; pre-declaration$$/d' $@ -diff lang0ll1.ll lang0ll2.ll lang0ll.ll: lang0ll.lang0 lang0ll2.exe cat $< | ./lang0ll2.exe > $@ + sed -i '/^.*; pre-declaration$$/d' $@ -diff lang0ll2.ll lang0ll.ll foo.ll: foo.c diff --git a/3-lang0ll/lang0ll.lang0 b/3-lang0ll/lang0ll.lang0 index c7ee590..9f2548d 100644 --- a/3-lang0ll/lang0ll.lang0 +++ b/3-lang0ll/lang0ll.lang0 @@ -40,6 +40,23 @@ makelocallabel: return result / +makestringconst str: + declare constid + declare isempty + + calc constid mapgetkey "stringconst" str "" + calc isempty eq constid "" + if isempty + calc constid mapgetkey "stringconst" "___count___" "0" + calc constid add constid "1" + mapsetkey "stringconst" "___count___" constid + / + mapsetkey "stringconst" str constid + mapsetkey "stringconst" constid str + + return constid +/ + lexident: declare char declare isbeforea @@ -71,6 +88,7 @@ skipchar exp: calc colno stdincolno check eq exp act : "Unexpected character" act "expected" exp "at" lineno colno skip + return "" / increaseindent indent: @@ -101,16 +119,7 @@ parseconststring: skipchar quote declare constid - calc constid mapgetkey "stringconst" str "" - declare isempty - calc isempty eq constid "" - if isempty - calc constid mapgetkey "stringconst" "___count___" "0" - calc constid add constid "1" - mapsetkey "stringconst" "___count___" constid - / - mapsetkey "stringconst" str constid - mapsetkey "stringconst" constid str + calc constid makestringconst str emit "i8* @str." emit constid @@ -140,8 +149,8 @@ parseexprcall: declare isnotquote calc funcname lexident check mapgetkey "FUNCREG" funcname "" : "Function" funcname "does not exist" - calc funcid registerid funcname - emit funcid + emit "@id_" + emit funcname emit "(" set first "1" forever @@ -178,43 +187,67 @@ parsestatdeclare indent: skipchar " " calc varname lexident skipchar eol + + calc varid registerid varname + emit indent + emit varid + emitln " = alloca i8*" return / parsestatset indent: + declare tmpvar declare varid declare varname + + calc tmpvar makelocalvar + skipchar " " calc varname lexident calc varid registerid varname skipchar " " emit indent - emit varid + emit tmpvar emit " = call i8* @__drop_i8_type(" parseconststring emit ")" emit eol skipchar eol + + emit indent + emit "store i8* " + emit tmpvar + emit ", i8**" + emit varid + emitln "" + return / parsestatcalc indent: declare varid declare varname - declare varidx + declare tmpvar + + calc tmpvar makelocalvar + skipchar " " calc varname lexident calc varid registerid varname skipchar " " emit indent - emit varid - calc varidx mapgetkey "funcvarused" varid "" - calc varidx add varidx "1" - mapsetkey "funcvarused" varid varidx - emit " = call i8* @" + emit tmpvar + emit " = call i8* " parseexprcall emit eol skipchar eol + + emit indent + emit "store i8* " + emit tmpvar + emit ", i8**" + emit varid + emitln "" return / @@ -260,6 +293,10 @@ parsestatif indent: calc indentt increaseindent indent parseblock indentt + emit indentt + emit "br label %" + emitln labelempty + emit labelempty emitln ":" @@ -328,7 +365,7 @@ parsestatreturn indent: / / if isnotspace - emit "i18* 0" + emit "i8* @str.EMPTY" / emit eol skipchar eol @@ -345,12 +382,29 @@ parsestatcheck indent: declare isquote declare notfirst + declare funcresvar + declare labelfail + declare labelnotfail + declare strlenvar + declare strnotemptyvar + declare stderrvar + + calc funcresvar makelocalvar + calc strlenvar makelocalvar + calc strnotemptyvar makelocalvar + calc stderrvar makelocalvar + + calc labelfail makelocallabel + calc labelnotfail makelocallabel + skipchar " " - emit indent - emit "if( 0 == strlen(" calc funcname lexident calc funcid registerid funcname + + emit indent + emit funcresvar + emit " = call i8* " emit funcid emit "(" @@ -382,26 +436,46 @@ parsestatcheck indent: skipchar ":" - emitln ")) )" - emit indent - emitln "{" + emitln ")" emit indent - emit " fprintf(stderr, " - emit quote - emit "%s" - emit quote - emit ", " - emit quote - emit "ERROR:" - emit quote - emitln ");" + emit strlenvar + emit " = call i64 @__strlen(i8* " + emit funcresvar + emitln ")" + + emit indent + emit strnotemptyvar + emit " = icmp ne i64 " + emit strlenvar + emitln ", 0" + + emit indent + emit "br i1 " + emit strnotemptyvar + emit ", label %" + emit labelnotfail + emit ", label %" + emitln labelfail + + emit labelfail + emitln ":" + + emit indent + emit " " + emit stderrvar + emitln " = load %FILE*, %FILE** @stderrvar" + + emit indent + emit " call i32 @fputs(i8* @str.ERROR, %FILE* " + emit stderrvar + emitln ")" forever skipchar " " emit indent - emit " fprintf(stderr, " + emit " ; fprintf(stderr, " emit quote emit " %s" emit quote @@ -425,7 +499,7 @@ parsestatcheck indent: / emit indent - emit " fprintf(stderr, " + emit " ; fprintf(stderr, " emit quote emit "%s" emit quote @@ -433,26 +507,34 @@ parsestatcheck indent: emitln ");" emit indent - emitln " exit(1);" + emitln " call void @exit(i32 1)" emit indent - emitln "}" + emitln " unreachable" + + emit labelnotfail + emitln ":" + + return / parsestattrace indent: declare varid declare varname - emit indent - emit "__trace(" - emit quote + declare callconstid + skipchar " " calc varname lexident - calc varid registerid varname - emit varname - emit quote - emit ", " - emit varid - emitln ");" skipchar eol + + calc callconstid makestringconst varname + calc varid registerid varname + + emit indent + emit "call void @__trace(i8* @str." + emit callconstid + emit ", i8* " + emit varid + emitln ")" return / @@ -516,10 +598,9 @@ parsestat indent: return / check mapgetkey "FUNCREG" call "" : "Function" call "does not exist" - calc callid registerid call emit indent - emit "call i8* @" - emit callid + emit "call i8* @id_" + emit call emit "(" set first "1" forever @@ -609,9 +690,8 @@ parsefunc: declare varname calc funcname lexident mapsetkey "FUNCREG" funcname "1" - calc funcid registerid funcname trace funcname - emit "define i8* @" + emit "define i8* @id_" emit funcname emit "(" set first "1" @@ -632,7 +712,6 @@ parsefunc: / emit "i8* " emit varid - mapsetkey "funcvarused" varid "0" set first "0" / calc char peek @@ -640,7 +719,7 @@ parsefunc: if iseoblock skipchar "/" skipchar eol - emitln ");" + emitln " ; pre-declaration" return / skipchar ":" @@ -668,11 +747,26 @@ emitheader: emit eol + emitln "%FILE = type opaque" + emitln "@stderr = external global %FILE*" + + emit eol + + emitln "declare void @exit(i32)" + emitln "declare i32 @fputs(i8*, %FILE*)" + + emit eol + emit "@__EOL = internal constant [2 x i8] c" emit quote emit "\\0A\\00" emitln quote + emit "@__QUOTE = internal constant [2 x i8] c" + emit quote + emit "\\22\\00" + emitln quote + emit eol emitln "define i8* @__drop_i8_type(i8* %0) alwaysinline readnone" @@ -689,8 +783,22 @@ emitheader: emitfooter: declare constid declare str + declare strlenvar declare dontusethisstr + emit "@str.ERROR = internal constant [7 x i8] c" + emit quote + emit "ERROR:\\00" + emit quote + emitln "" + + emit "@str.EMPTY = internal constant [1 x i8] c" + emit quote + emit "\\00" + emit quote + emitln "" + + set dontusethisstr "__dontusethisstr__" set constid "01" @@ -703,11 +811,16 @@ emitfooter: break / + calc strlen strlen str + emit "@str." emit constid - emit " = internal constant [33 x i8] c" + emit " = internal constant [" + emit strlen + emit " x i8] c" emit quote emit str + emit "\\00" emitln quote calc constid add constid "1" @@ -730,29 +843,29 @@ main: mapsetkey "REGISTERID" "quote" "@__QUOTE" mapsetkey "FUNCREG" "add" "1" - mapsetkey "REGISTERID" "add" "__add" + mapsetkey "REGISTERID" "add" "@__add" mapsetkey "FUNCREG" "emit" "1" - mapsetkey "REGISTERID" "emit" "__emit" + mapsetkey "REGISTERID" "emit" "@__emit" mapsetkey "FUNCREG" "eq" "1" - mapsetkey "REGISTERID" "eq" "__eq" + mapsetkey "REGISTERID" "eq" "@__eq" mapsetkey "FUNCREG" "lt" "1" - mapsetkey "REGISTERID" "lt" "__lt" + mapsetkey "REGISTERID" "lt" "@__lt" mapsetkey "FUNCREG" "not" "1" - mapsetkey "REGISTERID" "not" "__not" + mapsetkey "REGISTERID" "not" "@__not" mapsetkey "FUNCREG" "mapclear" "1" - mapsetkey "REGISTERID" "mapclear" "__mapclear" + mapsetkey "REGISTERID" "mapclear" "@__mapclear" mapsetkey "FUNCREG" "mapgetkey" "1" - mapsetkey "REGISTERID" "mapgetkey" "__mapgetkey" + mapsetkey "REGISTERID" "mapgetkey" "@__mapgetkey" mapsetkey "FUNCREG" "mapsetkey" "1" - mapsetkey "REGISTERID" "mapsetkey" "__mapsetkey" + mapsetkey "REGISTERID" "mapsetkey" "@__mapsetkey" mapsetkey "FUNCREG" "peek" "1" - mapsetkey "REGISTERID" "peek" "__peek" + mapsetkey "REGISTERID" "peek" "@__peek" mapsetkey "FUNCREG" "skip" "1" - mapsetkey "REGISTERID" "skip" "__skip" + mapsetkey "REGISTERID" "skip" "@__skip" mapsetkey "FUNCREG" "stdincolno" "1" - mapsetkey "REGISTERID" "stdincolno" "__stdincolno" + mapsetkey "REGISTERID" "stdincolno" "@__stdincolno" mapsetkey "FUNCREG" "stdinlineno" "1" - mapsetkey "REGISTERID" "stdinlineno" "__stdinlineno" + mapsetkey "REGISTERID" "stdinlineno" "@__stdinlineno" forever calc char peek