From c442dc1fe4984f80dc647f28a8e64c4e836e3b47 Mon Sep 17 00:00:00 2001 From: "Johan B.W. de Vries" Date: Sat, 1 Feb 2025 17:01:27 +0100 Subject: [PATCH] Start on llvm IR target --- .gitignore | 1 + Makefile | 32 +++- foo.c | 17 ++ it3-in.lang0 | 463 +++++++++++++++++++++++++++++++++++++++++++++++++++ notes.ll | 19 +++ 5 files changed, 528 insertions(+), 4 deletions(-) create mode 100644 foo.c create mode 100644 it3-in.lang0 create mode 100644 notes.ll diff --git a/.gitignore b/.gitignore index eda6a78..5e63479 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /it0-out0.diff /it1-out* /it2-out* +/it3-out* diff --git a/Makefile b/Makefile index fe577ff..6519963 100644 --- a/Makefile +++ b/Makefile @@ -40,30 +40,54 @@ it2-out0.py: it1-out.py it2-in.lang0 # No gcc step since the target is still python here it2-out1.c: it2-out0.py it2-in.lang0 - cat it2-in.lang0 | python3 it2-out0.py > it2-out1.c + cat it2-in.lang0 | python3 it2-out0.py > $@ # diff it2-out0.py it2-out1.py Do not diff - the target changed so the output will be different it2-out1: it2-out1.c - gcc it2-out1.c -o it2-out1 $(GCC_FLAGS) + gcc $^ -o #@ $(GCC_FLAGS) it2-out2.c: it2-out1 it2-in.lang0 cat it2-in.lang0 | ./it2-out1 > it2-out2.c diff it2-out1.c it2-out2.c it2-out2: it2-out2.c - gcc it2-out2.c -o it2-out2 $(GCC_FLAGS) + gcc $^ -o #@ $(GCC_FLAGS) it2-out3.c: it2-out2 it2-in.lang0 cat it2-in.lang0 | ./it2-out2 > it2-out3.c diff it2-out2.c it2-out3.c it2-out3: it2-out3.c - gcc it2-out3.c -o it2-out3 $(GCC_FLAGS) + gcc $^ -o #@ $(GCC_FLAGS) it2-out: it2-out3 cp it2-out3 it2-out +it3-out0.c: it2-out it3-in.lang0 + cat it3-in.lang0 | ./it2-out > it3-out0.c + +# gcc step since the target is still python here +it3-out0: it3-out0.c + gcc $^ -o $@ $(GCC_FLAGS) + +it3-out1.ll: it3-out0 it3-in.lang0 + cat it3-in.lang0 | ./it3-out0 > $@ + +it3-out1.s: it3-out1.ll + llc $^ -o $@ + + + +foo.ll: foo.c + clang -S -emit-llvm $^ + +foo.s: foo.ll + llc $^ + +foo: foo.s + clang $^ -o $@ + clean: -rm it1-out* it2-out* diff --git a/foo.c b/foo.c new file mode 100644 index 0000000..b0800e5 --- /dev/null +++ b/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/it3-in.lang0 b/it3-in.lang0 new file mode 100644 index 0000000..f3c8e3f --- /dev/null +++ b/it3-in.lang0 @@ -0,0 +1,463 @@ +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 + skipchar " " + calc var lexident + skipchar " " + emit indent + emit "%" + emit var + 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 + 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 + 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/notes.ll b/notes.ll new file mode 100644 index 0000000..22d8032 --- /dev/null +++ b/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, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)); + %indent.3 = call i8* @addstringchar(i8* %indent, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)); + %indent.4 = call i8* @addstringchar(i8* %indent, 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