From 8502abeff6bb44268175647100ae39ba07332f51 Mon Sep 17 00:00:00 2001 From: "Johan B.W. de Vries" Date: Sun, 2 Feb 2025 15:43:37 +0100 Subject: [PATCH] Start on llvm IR target --- 3-lang0ll/.gitignore | 6 + 3-lang0ll/Makefile | 42 ++++ 3-lang0ll/foo.c | 17 ++ 3-lang0ll/lang0ll.lang0 | 472 ++++++++++++++++++++++++++++++++++++++++ 3-lang0ll/notes.ll | 19 ++ 5 files changed, 556 insertions(+) create mode 100644 3-lang0ll/.gitignore create mode 100644 3-lang0ll/Makefile create mode 100644 3-lang0ll/foo.c create mode 100644 3-lang0ll/lang0ll.lang0 create mode 100644 3-lang0ll/notes.ll diff --git a/3-lang0ll/.gitignore b/3-lang0ll/.gitignore new file mode 100644 index 0000000..c44e039 --- /dev/null +++ b/3-lang0ll/.gitignore @@ -0,0 +1,6 @@ +/lang0ll*.c +/lang0ll*.exe +/lang0ll*.ll +/lang0ll*.o +/foo.exe +/foo.ll 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/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/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