Compare commits

..

7 Commits

Author SHA1 Message Date
Johan B.W. de Vries
1be24ef771 close, but no sigare 2026-01-18 16:09:21 +01:00
Johan B.W. de Vries
449a89d6b3 More work 2026-01-18 15:05:21 +01:00
Johan B.W. de Vries
c9029b1216 More work 2026-01-18 14:47:57 +01:00
Johan B.W. de Vries
1671ce2285 More testing 2026-01-18 14:21:48 +01:00
Johan B.W. de Vries
098ab080ca Updated llvm with other changes
Started on outputting string constants

Need to:
- Calc string length
- Implement _add (including allocation)
- Everything else
2026-01-18 13:11:17 +01:00
Johan B.W. de Vries
cfae563aef Start on llvm IR target
# Conflicts:
#	README.md
2025-05-04 18:18:45 +02:00
Johan B.W. de Vries
8502abeff6 Start on llvm IR target 2025-05-04 18:10:53 +02:00
7 changed files with 1050 additions and 0 deletions

7
3-lang0ll/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
/lang0ll*.c
/lang0ll*.exe
/lang0ll*.ll
/lang0ll*.o
/lang0ll*.s
/foo.exe
/foo.ll

45
3-lang0ll/Makefile Normal file
View File

@ -0,0 +1,45 @@
.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 -g -c $<
lang0ll0.exe: lang0ll0.o
gcc -g -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
clang -S -emit-llvm $^
clean:
rm -f lang0ll*.c lang0ll*.ll lang0ll*.o lang0ll*.exe foo.ll foo.o foo.exe

71
3-lang0ll/backup.ll Normal file
View File

@ -0,0 +1,71 @@
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"
declare noalias i8* @malloc(i64)
define i8* @__add(i8* %lft, i8* %rgt)
{
%lft_len = call i64 @__strlen(i8* %lft)
%rgt_len = call i64 @__strlen(i8* %rgt)
%new_len = add i64 %lft_len, %rgt_len
%res = call i8* @malloc(i64 %new_len)
; todo: copy lft
; todo: copy rgt
; todo: set 0 byte
ret i8* %res
}
define i64 @__strlen(i8* %str)
{
start:
br label %loop_start
loop_start:
%i.0 = phi i64 [0, %start], [%i.new, %loop]
%c_adr = getelementptr i8, i8* %str, i64 %i.0
%c = load i8, i8* %c_adr
%done = icmp eq i8 %c, 0
br i1 %done, label %exit, label %loop
loop:
%i.new = add i64 %i.0, 1
br label %loop_start
exit:
ret i64 %i.0
}
define i8* @__mapgetkey(i8* %mapname, i8* %key, i8* %def)
{
; todo
ret i8* %def
}
define i8* @addstringchar(i8* %0, i8* %1)
{
; todo
ret i8* %0
}
define i8* @registerid(i8* %id_id)
{
%id_idname = call i8* @__mapgetkey(i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @str.01, i64 0, i64 0), i8* %id_id, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @str.011, i64 0, i64 0))
%1 = call i64 @__strlen(i8* %id_idname)
%11 = icmp ne i64 %1, 0
br i1 %11, label %lbl1, label %lbl11
lbl1:
ret i8* %id_idname
lbl11:
%id_idnamea = call i8* @__add(i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @str.0111, i64 0, i64 0), i8* %id_id)
ret i8* %id_idnamea
}
define i64 @main() {
%res = call i64 @__strlen(i8* @str.01)
ret i64 %res
}
@str.01 = internal constant [11 x i8] c"REGISTERID\00"
@str.011 = internal constant [0 x i8] c""
@str.0111 = internal constant [3 x i8] c"id_"

19
3-lang0ll/foo.c Normal file
View File

@ -0,0 +1,19 @@
#include <stdio.h>
void print(char * x)
{
return;
}
int sum(int a, int b)
{
return a + b;
}
int main()
{
char * foo = "Hello, world!";
printf("This is a test.");
return sum(7, 15);
}

889
3-lang0ll/lang0ll.lang0 Normal file
View File

@ -0,0 +1,889 @@
registerid id:
declare idname
declare newidx
calc idname mapgetkey "REGISTERID" id ""
if idname
return idname
/
declare idnamea
calc idnamea add "%id_" id
return idnamea
/
emitln data:
emit data
emit eol
return ""
/
makelocalvar:
declare prevvar
declare newvar
declare result
calc prevvar mapgetkey "localvarused" "" ""
calc newvar add prevvar "1"
mapsetkey "localvarused" "" newvar
calc result add "%tmp" newvar
return result
/
makelocallabel:
declare prevlabel
declare newlabel
declare result
calc prevlabel mapgetkey "locallabelused" "" ""
calc newlabel add prevlabel "1"
mapsetkey "locallabelused" "" newlabel
calc result add "lbl" newlabel
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
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 add word char
skip
/
return word
/
skipchar exp:
declare act
declare lineno
declare colno
calc act peek
calc lineno stdinlineno
calc colno stdincolno
check eq exp act : "Unexpected character" act "expected" exp "at" lineno colno
skip
return ""
/
increaseindent indent:
calc indent add indent " "
return indent
/
parseconststring:
declare char
declare iseof
declare isquote
declare str
set str ""
skipchar quote
forever
calc char peek
calc iseof eq char eof
if iseof
break
/
calc isquote eq char quote
if isquote
break
/
calc str add str char
skip
/
skipchar quote
declare constid
calc constid makestringconst str
emit "i8* @str."
emit constid
return
/
parseexprvarref:
declare varid
declare varname
calc varname lexident
calc varid registerid varname
emit "i8* "
emit varid
return
/
parseexprcall:
declare char
declare first
declare funcid
declare funcname
declare isspace
declare isnotspace
declare isfirst
declare isnotfirst
declare isquote
declare isnotquote
calc funcname lexident
check mapgetkey "FUNCREG" funcname "" : "Function" funcname "does not exist"
emit "@id_"
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 varid
declare varname
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 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 tmpvar
calc tmpvar makelocalvar
skipchar " "
calc varname lexident
calc varid registerid varname
skipchar " "
emit indent
emit tmpvar
emit " = call i8* "
parseexprcall
emit eol
skipchar eol
emit indent
emit "store i8* "
emit tmpvar
emit ", i8**"
emit varid
emitln ""
return
/
parseblock indent/
parsestatif indent:
declare labelempty
declare labelnotempty
declare strlenvar
declare strnotemptyvar
calc strlenvar makelocalvar
calc strnotemptyvar makelocalvar
calc labelempty makelocallabel
calc labelnotempty makelocallabel
skipchar " "
emit indent
emit strlenvar
emit " = call i64 @__strlen("
parseexprvarref
skipchar eol
emitln ")"
emit indent
emit strnotemptyvar
emit " = icmp ne i64 "
emit strlenvar
emitln ", 0"
emit indent
emit "br i1 "
emit strnotemptyvar
emit ", label %"
emit labelnotempty
emit ", label %"
emitln labelempty
emit labelnotempty
emitln ":"
declare indentt
calc indentt increaseindent indent
parseblock indentt
emit indentt
emit "br label %"
emitln labelempty
emit labelempty
emitln ":"
return
/
parsestatforever indent:
declare endlabel
declare indentt
declare startlabel
calc endlabel makelocallabel
calc startlabel makelocallabel
calc indentt increaseindent indent
mapsetkey "foreverstatendlabel" "" endlabel
emit indent
emit "br label %"
emitln startlabel
emit startlabel
emitln ":"
skipchar eol
parseblock indentt
emit indent
emit "br label %"
emitln startlabel
emit endlabel
emitln ":"
return
/
parsestatbreak indent:
declare endlabel
calc endlabel mapgetkey "foreverstatendlabel" "" "?"
emit indent
emit "br label %"
emitln endlabel
skipchar eol
return
/
parsestatreturn indent:
declare char
declare isspace
declare isnotquote
declare isquote
declare isnotspace
emit indent
emit "ret "
calc char peek
calc isspace eq char " "
calc isnotspace not isspace
if isspace
skip
calc char peek
calc isquote eq char quote
calc isnotquote not isquote
if isquote
parseconststring
/
if isnotquote
parseexprvarref
/
/
if isnotspace
emit "i8* @str.EMPTY"
/
emit eol
skipchar eol
return
/
parsestatcheck indent:
declare char
declare funcid
declare funcname
declare iscolon
declare iseol
declare isnotquote
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 " "
calc funcname lexident
calc funcid registerid funcname
emit indent
emit funcresvar
emit " = call i8* "
emit funcid
emit "("
set notfirst ""
forever
skipchar " "
calc char peek
calc iscolon eq char ":"
if iscolon
break
/
if notfirst
emit ", "
/
calc char peek
calc isquote eq char quote
calc isnotquote not isquote
if isquote
parseconststring
/
if isnotquote
parseexprvarref
/
set notfirst "1"
/
skipchar ":"
emitln ")"
emit indent
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 quote
emit " %s"
emit quote
emit ", "
calc char peek
calc isquote eq char quote
calc isnotquote not isquote
if isquote
parseconststring
/
if isnotquote
parseexprvarref
/
emitln ");"
calc char peek
calc iseol eq char eol
if iseol
break
/
/
emit indent
emit " ; fprintf(stderr, "
emit quote
emit "%s"
emit quote
emit ", __EOL"
emitln ");"
emit indent
emitln " call void @exit(i32 1)"
emit indent
emitln " unreachable"
emit labelnotfail
emitln ":"
return
/
parsestattrace indent:
declare varid
declare varname
declare callconstid
skipchar " "
calc varname lexident
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
/
parsestat indent:
declare call
declare callid
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 "check"
if iscall
parsestatcheck indent
return
/
calc iscall eq call "trace"
if iscall
parsestattrace indent
return
/
check mapgetkey "FUNCREG" call "" : "Function" call "does not exist"
emit indent
emit "call i8* @id_"
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
calc isfirst eq first "1"
calc isnotfirst not isfirst
if isnotfirst
emit ", "
/
if isquote
parseconststring
/
if isnotquote
parseexprvarref
/
set first "0"
/
skipchar eol
emitln ")"
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:
mapsetkey "localvarused" "" "0"
mapsetkey "locallabelused" "" "0"
declare char
declare first
declare funcid
declare funcname
declare iseoblock
declare isfirst
declare ismain
declare isnotmain
declare isspace
declare isnotfirst
declare isnotspace
declare varid
declare varname
calc funcname lexident
mapsetkey "FUNCREG" funcname "1"
trace funcname
emit "define i8* @id_"
emit funcname
emit "("
set first "1"
forever
calc char peek
calc isspace eq char " "
calc isnotspace not isspace
if isnotspace
break
/
skip
calc varname lexident
calc varid registerid varname
calc isfirst eq first "1"
calc isnotfirst not isfirst
if isnotfirst
emit ", "
/
emit "i8* "
emit varid
set first "0"
/
calc char peek
calc iseoblock eq char "/"
if iseoblock
skipchar "/"
skipchar eol
emitln " ; pre-declaration"
return
/
skipchar ":"
skipchar eol
emitln ")"
emitln "{"
parseblock " "
emitln "}"
emit eol
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
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"
emitln "{"
emitln " ret i8* %0"
emitln "}"
emit eol
return
/
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"
forever
calc str mapgetkey "stringconst" constid dontusethisstr
declare unused
calc unused eq str dontusethisstr
if unused
break
/
calc strlen strlen str
emit "@str."
emit constid
emit " = internal constant ["
emit strlen
emit " x i8] c"
emit quote
emit str
emit "\\00"
emitln quote
calc constid add constid "1"
/
emit ""
return
/
main:
declare char
declare iseof
declare iseol
declare isnoteol
emitheader
mapsetkey "REGISTERID" "eof" "@__EOF"
mapsetkey "REGISTERID" "eol" "@__EOL"
mapsetkey "REGISTERID" "quote" "@__QUOTE"
mapsetkey "FUNCREG" "add" "1"
mapsetkey "REGISTERID" "add" "@__add"
mapsetkey "FUNCREG" "emit" "1"
mapsetkey "REGISTERID" "emit" "@__emit"
mapsetkey "FUNCREG" "eq" "1"
mapsetkey "REGISTERID" "eq" "@__eq"
mapsetkey "FUNCREG" "lt" "1"
mapsetkey "REGISTERID" "lt" "@__lt"
mapsetkey "FUNCREG" "not" "1"
mapsetkey "REGISTERID" "not" "@__not"
mapsetkey "FUNCREG" "mapclear" "1"
mapsetkey "REGISTERID" "mapclear" "@__mapclear"
mapsetkey "FUNCREG" "mapgetkey" "1"
mapsetkey "REGISTERID" "mapgetkey" "@__mapgetkey"
mapsetkey "FUNCREG" "mapsetkey" "1"
mapsetkey "REGISTERID" "mapsetkey" "@__mapsetkey"
mapsetkey "FUNCREG" "peek" "1"
mapsetkey "REGISTERID" "peek" "@__peek"
mapsetkey "FUNCREG" "skip" "1"
mapsetkey "REGISTERID" "skip" "@__skip"
mapsetkey "FUNCREG" "stdincolno" "1"
mapsetkey "REGISTERID" "stdincolno" "@__stdincolno"
mapsetkey "FUNCREG" "stdinlineno" "1"
mapsetkey "REGISTERID" "stdinlineno" "@__stdinlineno"
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
/

19
3-lang0ll/notes.ll Normal file
View File

@ -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