More work

This commit is contained in:
Johan B.W. de Vries 2026-01-25 15:10:26 +01:00
parent 49e1bf204f
commit 68611b4df3
6 changed files with 486 additions and 45 deletions

View File

@ -1,4 +1,18 @@
registerid id:
registerfunc id:
declare idname
declare newidx
calc idname mapgetkey "REGISTERID" id ""
if idname
return idname
/
declare idnamea
calc idnamea add "@id_" id
return idnamea
/
registervar id:
declare idname
declare newidx
@ -22,8 +36,8 @@ makelocalvar:
declare prevvar
declare newvar
declare result
calc prevvar mapgetkey "localvarused" "" ""
calc newvar add prevvar "1"
calc prevvar mapgetkey "localvarused" "" "0"
calc newvar intinc prevvar
mapsetkey "localvarused" "" newvar
calc result add "%tmp" newvar
return result
@ -33,8 +47,8 @@ makelocallabel:
declare prevlabel
declare newlabel
declare result
calc prevlabel mapgetkey "locallabelused" "" ""
calc newlabel add prevlabel "1"
calc prevlabel mapgetkey "locallabelused" "" "0"
calc newlabel intinc prevlabel
mapsetkey "locallabelused" "" newlabel
calc result add "lbl" newlabel
return result
@ -44,15 +58,15 @@ makestringconst str:
declare constid
declare isempty
calc constid mapgetkey "stringconst" str ""
calc constid mapgetkey "str_to_const_id" str ""
calc isempty eq constid ""
if isempty
calc constid mapgetkey "stringconst" "___count___" "0"
calc constid add constid "1"
mapsetkey "stringconst" "___count___" constid
calc constid mapgetkey "const_id_to_str" "___count___" "0"
calc constid intinc constid
mapsetkey "const_id_to_str" "___count___" constid
/
mapsetkey "stringconst" str constid
mapsetkey "stringconst" constid str
mapsetkey "str_to_const_id" str constid
mapsetkey "const_id_to_str" constid str
return constid
/
@ -130,7 +144,7 @@ parseexprvarref:
declare varid
declare varname
calc varname lexident
calc varid registerid varname
calc varid registervar varname
emit "i8* "
emit varid
return
@ -148,9 +162,9 @@ parseexprcall:
declare isquote
declare isnotquote
calc funcname lexident
calc funcid registerfunc funcname
check mapgetkey "FUNCREG" funcname "" : "Function" funcname "does not exist"
emit "@id_"
emit funcname
emit funcid
emit "("
set first "1"
forever
@ -188,7 +202,7 @@ parsestatdeclare indent:
calc varname lexident
skipchar eol
calc varid registerid varname
calc varid registervar varname
emit indent
emit varid
emitln " = alloca i8*"
@ -204,7 +218,7 @@ parsestatset indent:
skipchar " "
calc varname lexident
calc varid registerid varname
calc varid registervar varname
skipchar " "
emit indent
emit tmpvar
@ -233,7 +247,7 @@ parsestatcalc indent:
skipchar " "
calc varname lexident
calc varid registerid varname
calc varid registervar varname
skipchar " "
emit indent
emit tmpvar
@ -400,7 +414,7 @@ parsestatcheck indent:
skipchar " "
calc funcname lexident
calc funcid registerid funcname
calc funcid registerfunc funcname
emit indent
emit funcresvar
@ -464,7 +478,7 @@ parsestatcheck indent:
emit indent
emit " "
emit stderrvar
emitln " = load %FILE*, %FILE** @stderrvar"
emitln " = load %FILE*, %FILE** @stderr"
emit indent
emit " call i32 @fputs(i8* @str.ERROR, %FILE* "
@ -527,7 +541,7 @@ parsestattrace indent:
skipchar eol
calc callconstid makestringconst varname
calc varid registerid varname
calc varid registervar varname
emit indent
emit "call void @__trace(i8* @str."
@ -551,6 +565,7 @@ parsestat indent:
declare isnotspace
declare isnotquote
calc call lexident
calc callid registerfunc call
trace call
calc iscall eq call "declare"
if iscall
@ -599,8 +614,8 @@ parsestat indent:
/
check mapgetkey "FUNCREG" call "" : "Function" call "does not exist"
emit indent
emit "call i8* @id_"
emit call
emit "call i8* "
emit callid
emit "("
set first "1"
forever
@ -689,10 +704,11 @@ parsefunc:
declare varid
declare varname
calc funcname lexident
calc funcid registerfunc funcname
mapsetkey "FUNCREG" funcname "1"
trace funcname
emit "define i8* @id_"
emit funcname
emit "define i8* "
emit funcid
emit "("
set first "1"
forever
@ -704,7 +720,7 @@ parsefunc:
/
skip
calc varname lexident
calc varid registerid varname
calc varid registervar varname
calc isfirst eq first "1"
calc isnotfirst not isfirst
if isnotfirst
@ -727,6 +743,7 @@ parsefunc:
emitln ")"
emitln "{"
parseblock " "
emitln " ret i8* @__EOF"
emitln "}"
emit eol
return
@ -757,14 +774,51 @@ emitheader:
emit eol
emit "@__BACKSLASH = internal constant [2 x i8] c"
emit quote
emit backslash
emit backslash
emit backslash
emit "00"
emit quote
emitln ""
emit "@__EOF = internal constant [2 x i8] c"
emit quote
emit backslash
emit backslash
emit backslash
emit "FF"
emit quote
emitln ""
emit "@__EOL = internal constant [2 x i8] c"
emit quote
emit "\\0A\\00"
emit backslash
emit "0A"
emit backslash
emit "00"
emitln quote
emit "@__QUOTE = internal constant [2 x i8] c"
emit quote
emit "\\22\\00"
emit backslash
emit "22"
emit backslash
emit "00"
emitln quote
emit "@__FALSE = internal constant [1 x i8] c"
emit quote
emit backslash
emit "00"
emitln quote
emit "@__TRUE = internal constant [2 x i8] c"
emit quote
emit "1"
emit backslash
emit "00"
emitln quote
emit eol
@ -774,6 +828,75 @@ emitheader:
emitln " ret i8* %0"
emitln "}"
emitln "define i8* @__eq(i8* %0, i8* %1)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__lt(i8* %0, i8* %1)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__not(i8* %0)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__add(i8* %0, i8* %1)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__emit(i8* %0)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__trace(i8* %0)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__peek()"
emitln "{"
emitln " ret i8* @__EOL ; STUB"
emitln "}"
emitln "define i8* @__skip()"
emitln "{"
emitln " ret i8* @__EOL ; STUB"
emitln "}"
emitln "define i8* @__stdinlineno()"
emitln "{"
emitln " ret i8* @__EOL ; STUB"
emitln "}"
emitln "define i8* @__stdincolno()"
emitln "{"
emitln " ret i8* @__EOL ; STUB"
emitln "}"
emitln "define i8* @__mapgetkey(i8* %0, i8* %1, i8* %2)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__mapsetkey(i8* %0, i8* %1, i8* %2)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__strlen(i8* %0)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__intinc(i8* %0)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emit eol
@ -782,48 +905,58 @@ emitheader:
emitfooter:
declare constid
declare done
declare len
declare maxconstid
declare str
declare strlenvar
declare dontusethisstr
emitln "define i64 @main() {"
emitln " call i8* @id_main()"
emitln " ret i64 0"
emitln "}"
emit "@str.ERROR = internal constant [7 x i8] c"
emit quote
emit "ERROR:\\00"
emit "ERROR:"
emit backslash
emit "00"
emit quote
emitln ""
emit "@str.EMPTY = internal constant [1 x i8] c"
emit quote
emit "\\00"
emit backslash
emit "00"
emit quote
emitln ""
set dontusethisstr "__dontusethisstr__"
set constid "01"
set constid "0"
calc maxconstid mapgetkey "const_id_to_str" "___count___" "0"
forever
calc str mapgetkey "stringconst" constid dontusethisstr
calc str mapgetkey "const_id_to_str" constid "0"
declare unused
calc unused eq str dontusethisstr
if unused
break
/
calc strlen strlen str
calc len strlen str
calc len intinc len
emit "@str."
emit constid
emit " = internal constant ["
emit strlen
emit len
emit " x i8] c"
emit quote
emit str
emit "\\00"
emit backslash
emit "00"
emitln quote
calc constid add constid "1"
calc done eq constid maxconstid
if done
break
/
calc constid intinc constid
/
emit ""
@ -838,6 +971,7 @@ main:
emitheader
mapsetkey "REGISTERID" "backslash" "@__BACKSLASH"
mapsetkey "REGISTERID" "eof" "@__EOF"
mapsetkey "REGISTERID" "eol" "@__EOL"
mapsetkey "REGISTERID" "quote" "@__QUOTE"
@ -866,6 +1000,10 @@ main:
mapsetkey "REGISTERID" "stdincolno" "@__stdincolno"
mapsetkey "FUNCREG" "stdinlineno" "1"
mapsetkey "REGISTERID" "stdinlineno" "@__stdinlineno"
mapsetkey "FUNCREG" "strlen" "1"
mapsetkey "REGISTERID" "strlen" "@__strlen"
mapsetkey "FUNCREG" "intinc" "1"
mapsetkey "REGISTERID" "intinc" "@__intinc"
forever
calc char peek

272
3-lang0ll/runtimetest.ll Normal file
View File

@ -0,0 +1,272 @@
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"
%FILE = type opaque
@stdout = global %FILE* null
declare void @exit(i32)
declare i32 @fputs(i8*, %FILE*)
declare %FILE* @fdopen(i32, i8*)
declare void @fclose(%FILE*)
@__BACKSLASH = internal constant [2 x i8] c"\\\00"
@__EOF = internal constant [2 x i8] c"\\\FF"
@__EOL = internal constant [2 x i8] c"\0A\00"
@__QUOTE = internal constant [2 x i8] c"\22\00"
@__FALSE = internal constant [1 x i8] c"\00"
@__TRUE = internal constant [2 x i8] c"1\00"
define i8* @__drop_i8_type(i8* %0) alwaysinline readnone
{
ret i8* %0
}
define i8* @__eq(i8* %0, i8* %1)
{
%i = alloca i64, align 8
store i64 0, i64* %i
br label %loop
loop:
%index = load i64, i64* %i
%char0_adr = getelementptr i8, i8* %0, i64 %index
%char1_adr = getelementptr i8, i8* %1, i64 %index
%char0 = load i8, i8* %char0_adr
%char1 = load i8, i8* %char1_adr
%chars_differ = icmp ne i8 %char0, %char1
br i1 %chars_differ, label %lbl_not_equal, label %lbl_equal
lbl_equal:
%string_end = icmp eq i8 %char0, 0
br i1 %string_end, label %string_equal, label %next_char
string_equal:
ret i8* @__TRUE
next_char:
%next_index = add i64 %index, 1
store i64 %next_index, i64* %i
br label %loop
lbl_not_equal:
ret i8* @__FALSE
}
define i8* @__lt(i8* %0, i8* %1)
{
%i = alloca i64, align 8
store i64 0, i64* %i
br label %loop
loop:
%index = load i64, i64* %i
%char0_adr = getelementptr i8, i8* %0, i64 %index
%char1_adr = getelementptr i8, i8* %1, i64 %index
%char0 = load i8, i8* %char0_adr
%char1 = load i8, i8* %char1_adr
%char0_eol = icmp eq i8 %char0, 0
%char1_eol = icmp eq i8 %char1, 0
; if char0 == 0
; if char1 == 0
; return FALSE ; "" < "" === False
; else
; return TRUE ; "" < "." === True
; endif
; else
; if char1 == 0
; return FALSE ; "." < "" === False
; else
; if char0 < char1
; return TRUE ; "a" < "b" === True
; else
; if char0 > char1
; return FALSE ; "b" < "a" === False
; else
; jump next_char
; endif
; endif
; endif
; endif
br i1 %char0_eol, label %lbl_char0_eol, label %lbl_char0_not_eol
lbl_char0_eol:
br i1 %char1_eol, label %lbl_not_smaller, label %lbl_smaller
lbl_char0_not_eol:
br i1 %char1_eol, label %lbl_not_smaller, label %lbl_char0_not_eol_char1_not_eol
lbl_char0_not_eol_char1_not_eol:
%char0_lt_char1 = icmp ult i8 %char0, %char1
br i1 %char0_lt_char1, label %lbl_smaller, label %lbl_char0_ge_char1
lbl_char0_ge_char1:
%char0_gt_char1 = icmp ugt i8 %char0, %char1
br i1 %char0_gt_char1, label %lbl_not_smaller, label %next_char
next_char:
%next_index = add i64 %index, 1
store i64 %next_index, i64* %i
br label %loop
lbl_smaller:
ret i8* @__TRUE
lbl_not_smaller:
ret i8* @__FALSE
}
define i8* @__not(i8* %0)
{
%char0_adr = getelementptr i8, i8* %0, i64 0
%char0 = load i8, i8* %char0_adr
%char0_eol = icmp eq i8 %char0, 0
br i1 %char0_eol, label %lbl_empty, label %lbl_not_empty
lbl_empty:
ret i8* @__TRUE;
lbl_not_empty:
ret i8* @__FALSE;
}
define i8* @__add(i8* %0, i8* %1)
{
ret i8* %0 ; STUB
}
define i8* @__emit(i8* %0)
{
%stdout_ptr = load %FILE*, %FILE** @stdout
call i32 @fputs(i8* %0, %FILE* %stdout_ptr)
ret i8* @__FALSE
}
define i8* @__trace(i8* %0, i8* %1)
{
ret i8* %0 ; STUB
}
define i8* @__peek()
{
ret i8* @__EOL ; STUB
}
define i8* @__skip()
{
ret i8* @__EOL ; STUB
}
define i8* @__stdinlineno()
{
ret i8* @__EOL ; STUB
}
define i8* @__stdincolno()
{
ret i8* @__EOL ; STUB
}
define i8* @__mapgetkey(i8* %0, i8* %1, i8* %2)
{
ret i8* %0 ; STUB
}
define i8* @__mapsetkey(i8* %0, i8* %1, i8* %2)
{
ret i8* %0 ; STUB
}
define i8* @__strlen(i8* %0)
{
ret i8* %0 ; STUB
}
define i8* @__intinc(i8* %0)
{
ret i8* %0 ; STUB
}
define void @test_result_1(i8* %func, i8* %arg0, i8* %result)
{
call i32 @__emit(i8* %func)
call i32 @__emit(i8* @str.bracket)
call i32 @__emit(i8* %arg0)
call i32 @__emit(i8* @str.bracket_colon_space)
call i32 @__emit(i8* %result)
call i32 @__emit(i8* @__EOL)
ret void
}
define void @test_result_2(i8* %func, i8* %arg0, i8* %arg1, i8* %result)
{
call i32 @__emit(i8* %func)
call i32 @__emit(i8* @str.bracket)
call i32 @__emit(i8* %arg0)
call i32 @__emit(i8* @str.comma_space)
call i32 @__emit(i8* %arg1)
call i32 @__emit(i8* @str.bracket_colon_space)
call i32 @__emit(i8* %result)
call i32 @__emit(i8* @__EOL)
ret void
}
define void @test_eq(i8* %0, i8* %1)
{
%result = call i8* @__eq(i8* %0, i8* %1)
call void @test_result_2(i8* @str.eq, i8* %0, i8* %1, i8* %result)
ret void
}
define void @test_lt(i8* %0, i8* %1)
{
%result = call i8* @__lt(i8* %0, i8* %1)
call void @test_result_2(i8* @str.lt, i8* %0, i8* %1, i8* %result)
ret void
}
define void @test_not(i8* %0)
{
%result = call i8* @__not(i8* %0)
call void @test_result_1(i8* @str.not, i8* %0, i8* %result)
ret void
}
define i64 @main()
{
%stdout_ptr = call %FILE* @fdopen(i32 1, i8* @str.w)
store %FILE* %stdout_ptr, %FILE** @stdout
call void @test_eq(i8* @str., i8* @str.0)
call void @test_eq(i8* @str.0, i8* @str.)
call void @test_eq(i8* @str.0, i8* @str.0)
call void @test_eq(i8* @str.a, i8* @str.a)
call void @test_eq(i8* @str.a, i8* @str.b)
call void @test_eq(i8* @str.a, i8* @str.c)
call void @test_eq(i8* @str.b, i8* @str.a)
call void @test_eq(i8* @str.b, i8* @str.b)
call void @test_eq(i8* @str.b, i8* @str.c)
call void @test_eq(i8* @str.c, i8* @str.a)
call void @test_eq(i8* @str.c, i8* @str.b)
call void @test_eq(i8* @str.c, i8* @str.c)
call void @test_eq(i8* @str.left, i8* @str.right)
call void @test_eq(i8* @str.left, i8* @str.left)
call void @test_eq(i8* @str.right, i8* @str.left)
call void @test_eq(i8* @str.right, i8* @str.right)
call void @test_lt(i8* @str.0, i8* @str.0)
call void @test_lt(i8* @str.a, i8* @str.a)
call void @test_lt(i8* @str.a, i8* @str.b)
call void @test_lt(i8* @str.a, i8* @str.c)
call void @test_lt(i8* @str.b, i8* @str.a)
call void @test_lt(i8* @str.b, i8* @str.b)
call void @test_lt(i8* @str.b, i8* @str.c)
call void @test_lt(i8* @str.c, i8* @str.a)
call void @test_lt(i8* @str.c, i8* @str.b)
call void @test_lt(i8* @str.c, i8* @str.c)
; `a` and `b` are expected to have length 1.
call void @test_not(i8* @str.)
call void @test_not(i8* @str.0)
call void @test_not(i8* @str.1)
call i32 @fclose(%FILE* %stdout_ptr)
ret i64 0
}
@str. = internal constant [1 x i8] c"\00"
@str.0 = internal constant [2 x i8] c"0\00"
@str.1 = internal constant [2 x i8] c"1\00"
@str.a = internal constant [2 x i8] c"a\00"
@str.b = internal constant [2 x i8] c"b\00"
@str.c = internal constant [2 x i8] c"c\00"
@str.bracket = internal constant [2 x i8] c"(\00"
@str.bracket_colon_space = internal constant [4 x i8] c"): \00"
@str.comma_space = internal constant [3 x i8] c", \00"
@str.eq = internal constant [3 x i8] c"eq\00"
@str.left = internal constant [5 x i8] c"left\00"
@str.lt = internal constant [3 x i8] c"lt\00"
@str.not = internal constant [4 x i8] c"not\00"
@str.right = internal constant [6 x i8] c"right\00"
@str.w = internal constant [2 x i8] c"w\00"

View File

@ -2,10 +2,12 @@ all:
$(MAKE) -C 0-lang0py all
$(MAKE) -C 1-lang0py all
$(MAKE) -C 2-lang0c all
$(MAKE) -C 3-lang0ll all
$(MAKE) -C tests all
clean:
$(MAKE) -C 0-lang0py clean
$(MAKE) -C 1-lang0py clean
$(MAKE) -C 2-lang0c clean
$(MAKE) -C 3-lang0ll clean
$(MAKE) -C tests clean

View File

@ -11,7 +11,7 @@ CFLAGS=-ggdb
all: verify-results
Makefile.mk: generate-recipes.py $(wildcard test_*/test_*)
python3 generate-recipes.py Makefile.mk it0 it1 it2
python3 generate-recipes.py Makefile.mk it0 it1 it2 it3
include Makefile.mk
@ -29,6 +29,10 @@ clean:
find build -name '*.it2.result' -delete
find build -name '*.it2.stderr' -delete
find build -name '*.it2.stdout' -delete
find build -name '*.it3' -delete
find build -name '*.it3.result' -delete
find build -name '*.it3.stderr' -delete
find build -name '*.it3.stdout' -delete
find build -name '*.py' -delete
find build -name '*.tmp' -delete
@ -85,3 +89,19 @@ build/%.it2.o: build/%.it2.c
build/%.it2: build/%.it2.o
$(CC) $(CFLAGS) -o $@ $^ -lpython$(PYVERSION)
###
# it3
../3-lang0ll/lang0ll.exe: ../0-lang0py/lang0py.exe ../1-lang0py/lang0py.exe ../2-lang0c/lang0c.exe ../3-lang0ll/lang0ll.lang0
$(MAKE) -C ../3-lang0ll
build/%.it3.ll: %.lang0 ../3-lang0ll/lang0ll.exe
-cat $< | ../3-lang0ll/lang0ll.exe > $@.tmp 2> build/$*.it3.cmperr
mv $@.tmp $@
build/%.it3.s: build/%.it3.ll
llc --relocation-model=pic $^
build/%.it3: build/%.it3.s
clang $^ -o $@

View File

@ -24,3 +24,11 @@
/*.it2.result
/*.it2.stderr
/*.it2.stdout
/*.it3
/*.it3.ll
/*.it3.cmperr
/*.it3.ll.tmp
/*.it3.o
/*.it3.result
/*.it3.stderr
/*.it3.stdout

View File

@ -6,6 +6,7 @@ STAGE0_MAP = {
'it0': '.py',
'it1': '.py',
'it2': '.c',
'it3': '.ll',
}
class Rule: