mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 13:00:28 +00:00
string comparisons
This commit is contained in:
@@ -47,6 +47,7 @@ pushd %build_dir%
|
||||
/link %linker_settings% -OUT:%exe_name% ^
|
||||
&& call ..\run.bat
|
||||
|
||||
|
||||
:do_not_compile_exe
|
||||
popd
|
||||
:end_of_build
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
// C Runtime procedures
|
||||
putchar :: proc(c: i32) -> i32 #foreign
|
||||
malloc :: proc(sz: int) -> rawptr #foreign;
|
||||
free :: proc(ptr: rawptr) #foreign;
|
||||
// CRT
|
||||
putchar :: proc(c: i32) -> i32 #foreign
|
||||
heap_alloc :: proc(sz: int) -> rawptr #foreign "malloc"
|
||||
heap_free :: proc(ptr: rawptr) #foreign "free"
|
||||
mem_compare :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memcmp"
|
||||
mem_copy :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memcpy"
|
||||
mem_move :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memmove"
|
||||
|
||||
|
||||
print_string :: proc(s: string) {
|
||||
@@ -129,3 +132,48 @@ print_bool :: proc(b : bool) {
|
||||
print_string("false");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Runtime procedures
|
||||
|
||||
__string_eq :: proc(a, b : string) -> bool {
|
||||
if len(a) != len(b) {
|
||||
return false;
|
||||
}
|
||||
if ^a[0] == ^b[0] {
|
||||
return true;
|
||||
}
|
||||
return mem_compare(^a[0], ^b[0], len(a)) == 0;
|
||||
}
|
||||
|
||||
__string_ne :: proc(a, b : string) -> bool {
|
||||
return !__string_eq(a, b);
|
||||
}
|
||||
|
||||
__string_cmp :: proc(a, b : string) -> int {
|
||||
min_len := len(a);
|
||||
if len(b) < min_len {
|
||||
min_len = len(b);
|
||||
}
|
||||
for i := 0; i < min_len; i++ {
|
||||
x := a[i];
|
||||
y := b[i];
|
||||
if x < y {
|
||||
return -1;
|
||||
} else if x > y {
|
||||
return +1;
|
||||
}
|
||||
}
|
||||
if len(a) < len(b) {
|
||||
return -1;
|
||||
} else if len(a) > len(b) {
|
||||
return +1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__string_lt :: proc(a, b : string) -> bool { return __string_cmp(a, b) < 0; }
|
||||
__string_gt :: proc(a, b : string) -> bool { return __string_cmp(a, b) > 0; }
|
||||
__string_le :: proc(a, b : string) -> bool { return __string_cmp(a, b) <= 0; }
|
||||
__string_ge :: proc(a, b : string) -> bool { return __string_cmp(a, b) >= 0; }
|
||||
|
||||
990
examples/main.ll
990
examples/main.ll
@@ -1,48 +1,960 @@
|
||||
%.string = type {i8*, i64} ; Basic_string
|
||||
|
||||
%.rawptr = type i8* ; Basic_rawptr
|
||||
|
||||
declare void @llvm.memmove.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1)
|
||||
|
||||
declare void @putchar(i32 %c) ; foreign procedure
|
||||
declare void @llvm.memmove.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1) argmemonly nounwind
|
||||
|
||||
define void @main() {
|
||||
entry.-.0:
|
||||
%0 = alloca <8 x i1>, align 8 ; v
|
||||
store <8 x i1> zeroinitializer, <8 x i1>* %0
|
||||
%1 = alloca <8 x i1>, align 8
|
||||
store <8 x i1> zeroinitializer, <8 x i1>* %1
|
||||
%2 = load <8 x i1>, <8 x i1>* %1, align 8
|
||||
%3 = insertelement <8 x i1> %2, i1 true, i64 0
|
||||
%4 = insertelement <8 x i1> %3, i1 false, i64 1
|
||||
%5 = insertelement <8 x i1> %4, i1 true, i64 2
|
||||
%6 = insertelement <8 x i1> %5, i1 false, i64 3
|
||||
%7 = insertelement <8 x i1> %6, i1 true, i64 4
|
||||
%8 = insertelement <8 x i1> %7, i1 false, i64 5
|
||||
%9 = insertelement <8 x i1> %8, i1 true, i64 6
|
||||
%10 = insertelement <8 x i1> %9, i1 false, i64 7
|
||||
store <8 x i1> %10, <8 x i1>* %0
|
||||
%11 = load <8 x i1>, <8 x i1>* %0, align 8
|
||||
%12 = extractelement <8 x i1> %11, i64 0
|
||||
%13 = zext i1 %12 to i32
|
||||
%14 = add i32 %13, 65
|
||||
call void @putchar(i32 %14)
|
||||
%15 = load <8 x i1>, <8 x i1>* %0, align 8
|
||||
%16 = extractelement <8 x i1> %15, i64 1
|
||||
%17 = zext i1 %16 to i32
|
||||
%18 = add i32 %17, 65
|
||||
call void @putchar(i32 %18)
|
||||
%19 = load <8 x i1>, <8 x i1>* %0, align 8
|
||||
%20 = extractelement <8 x i1> %19, i64 2
|
||||
%21 = zext i1 %20 to i32
|
||||
%22 = add i32 %21, 65
|
||||
call void @putchar(i32 %22)
|
||||
%23 = load <8 x i1>, <8 x i1>* %0, align 8
|
||||
%24 = extractelement <8 x i1> %23, i64 3
|
||||
%25 = zext i1 %24 to i32
|
||||
%26 = add i32 %25, 65
|
||||
call void @putchar(i32 %26)
|
||||
call void @putchar(i32 10)
|
||||
%0 = alloca %.string, align 8 ; a
|
||||
store %.string zeroinitializer, %.string* %0
|
||||
%1 = getelementptr inbounds [5 x i8], [5 x i8]* @.str0, i64 0, i64 0
|
||||
%2 = alloca %.string, align 8
|
||||
store %.string zeroinitializer, %.string* %2
|
||||
%3 = getelementptr inbounds %.string, %.string* %2, i64 0, i32 0
|
||||
%4 = getelementptr inbounds %.string, %.string* %2, i64 0, i32 1
|
||||
store i8* %1, i8** %3
|
||||
store i64 5, i64* %4
|
||||
%5 = load %.string, %.string* %2, align 8
|
||||
store %.string %5, %.string* %0
|
||||
%6 = load %.string, %.string* %0, align 8
|
||||
%7 = getelementptr inbounds [5 x i8], [5 x i8]* @.str1, i64 0, i64 0
|
||||
%8 = alloca %.string, align 8
|
||||
store %.string zeroinitializer, %.string* %8
|
||||
%9 = getelementptr inbounds %.string, %.string* %8, i64 0, i32 0
|
||||
%10 = getelementptr inbounds %.string, %.string* %8, i64 0, i32 1
|
||||
store i8* %7, i8** %9
|
||||
store i64 5, i64* %10
|
||||
%11 = load %.string, %.string* %8, align 8
|
||||
%12 = call i1 @__string_gt(%.string %6, %.string %11)
|
||||
br i1 %12, label %if.then.-.1, label %if.else.-.2
|
||||
|
||||
if.then.-.1:
|
||||
%13 = getelementptr inbounds [2 x i8], [2 x i8]* @.str2, i64 0, i64 0
|
||||
%14 = alloca %.string, align 8
|
||||
store %.string zeroinitializer, %.string* %14
|
||||
%15 = getelementptr inbounds %.string, %.string* %14, i64 0, i32 0
|
||||
%16 = getelementptr inbounds %.string, %.string* %14, i64 0, i32 1
|
||||
store i8* %13, i8** %15
|
||||
store i64 2, i64* %16
|
||||
%17 = load %.string, %.string* %14, align 8
|
||||
call void @print_string(%.string %17)
|
||||
call void @main$nl-0()
|
||||
br label %if.done.-.3
|
||||
|
||||
if.else.-.2:
|
||||
%18 = getelementptr inbounds [3 x i8], [3 x i8]* @.str3, i64 0, i64 0
|
||||
%19 = alloca %.string, align 8
|
||||
store %.string zeroinitializer, %.string* %19
|
||||
%20 = getelementptr inbounds %.string, %.string* %19, i64 0, i32 0
|
||||
%21 = getelementptr inbounds %.string, %.string* %19, i64 0, i32 1
|
||||
store i8* %18, i8** %20
|
||||
store i64 3, i64* %21
|
||||
%22 = load %.string, %.string* %19, align 8
|
||||
call void @print_string(%.string %22)
|
||||
call void @main$nl-0()
|
||||
br label %if.done.-.3
|
||||
|
||||
if.done.-.3:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @main$nl-0() {
|
||||
entry.-.0:
|
||||
call void @print_rune(i32 10)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i32 @putchar(i32 %c) ; foreign procedure
|
||||
|
||||
declare %.rawptr @malloc(i64 %sz) ; foreign procedure
|
||||
|
||||
declare void @free(%.rawptr %ptr) ; foreign procedure
|
||||
|
||||
declare i32 @memcmp(%.rawptr %dst, %.rawptr %src, i64 %len) ; foreign procedure
|
||||
|
||||
declare i32 @memcpy(%.rawptr %dst, %.rawptr %src, i64 %len) ; foreign procedure
|
||||
|
||||
declare i32 @memmove(%.rawptr %dst, %.rawptr %src, i64 %len) ; foreign procedure
|
||||
|
||||
define void @print_string(%.string %s) {
|
||||
entry.-.0:
|
||||
%0 = alloca %.string, align 8 ; s
|
||||
store %.string zeroinitializer, %.string* %0
|
||||
store %.string %s, %.string* %0
|
||||
br label %for.init.-.1
|
||||
|
||||
for.init.-.1:
|
||||
%1 = alloca i64, align 8 ; i
|
||||
store i64 zeroinitializer, i64* %1
|
||||
store i64 0, i64* %1
|
||||
br label %for.loop.-.2
|
||||
|
||||
for.loop.-.2:
|
||||
%2 = load i64, i64* %1, align 8
|
||||
%3 = getelementptr inbounds %.string, %.string* %0, i64 0, i32 1
|
||||
%4 = load i64, i64* %3, align 8
|
||||
%5 = icmp slt i64 %2, %4
|
||||
br i1 %5, label %for.body.-.4, label %for.done.-.5
|
||||
|
||||
for.post.-.3:
|
||||
%6 = load i64, i64* %1, align 8
|
||||
%7 = add i64 %6, 1
|
||||
store i64 %7, i64* %1
|
||||
br label %for.loop.-.2
|
||||
|
||||
for.body.-.4:
|
||||
%8 = getelementptr inbounds %.string, %.string* %0, i64 0, i32 0
|
||||
%9 = load i8*, i8** %8, align 8
|
||||
%10 = load i64, i64* %1, align 8
|
||||
%11 = getelementptr i8, i8* %9, i64 %10
|
||||
%12 = load i8, i8* %11, align 1
|
||||
%13 = zext i8 %12 to i32
|
||||
%14 = call i32 @putchar(i32 %13)
|
||||
br label %for.post.-.3
|
||||
|
||||
for.done.-.5:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @byte_reverse({i8*, i64, i64} %b) {
|
||||
entry.-.0:
|
||||
%0 = alloca {i8*, i64, i64}, align 8 ; b
|
||||
store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %0
|
||||
store {i8*, i64, i64} %b, {i8*, i64, i64}* %0
|
||||
%1 = alloca i64, align 8 ; n
|
||||
store i64 zeroinitializer, i64* %1
|
||||
%2 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %0, i64 0, i32 1
|
||||
%3 = load i64, i64* %2, align 8
|
||||
store i64 %3, i64* %1
|
||||
br label %for.init.-.1
|
||||
|
||||
for.init.-.1:
|
||||
%4 = alloca i64, align 8 ; i
|
||||
store i64 zeroinitializer, i64* %4
|
||||
store i64 0, i64* %4
|
||||
br label %for.loop.-.2
|
||||
|
||||
for.loop.-.2:
|
||||
%5 = load i64, i64* %4, align 8
|
||||
%6 = load i64, i64* %1, align 8
|
||||
%7 = sdiv i64 %6, 2
|
||||
%8 = icmp slt i64 %5, %7
|
||||
br i1 %8, label %for.body.-.4, label %for.done.-.5
|
||||
|
||||
for.post.-.3:
|
||||
%9 = load i64, i64* %4, align 8
|
||||
%10 = add i64 %9, 1
|
||||
store i64 %10, i64* %4
|
||||
br label %for.loop.-.2
|
||||
|
||||
for.body.-.4:
|
||||
%11 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %0, i64 0, i32 0
|
||||
%12 = load i8*, i8** %11, align 8
|
||||
%13 = load i64, i64* %4, align 8
|
||||
%14 = getelementptr i8, i8* %12, i64 %13
|
||||
%15 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %0, i64 0, i32 0
|
||||
%16 = load i8*, i8** %15, align 8
|
||||
%17 = load i64, i64* %4, align 8
|
||||
%18 = load i64, i64* %1, align 8
|
||||
%19 = sub i64 %18, 1
|
||||
%20 = sub i64 %19, %17
|
||||
%21 = getelementptr i8, i8* %16, i64 %20
|
||||
%22 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %0, i64 0, i32 0
|
||||
%23 = load i8*, i8** %22, align 8
|
||||
%24 = load i64, i64* %4, align 8
|
||||
%25 = load i64, i64* %1, align 8
|
||||
%26 = sub i64 %25, 1
|
||||
%27 = sub i64 %26, %24
|
||||
%28 = getelementptr i8, i8* %23, i64 %27
|
||||
%29 = load i8, i8* %28, align 1
|
||||
%30 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %0, i64 0, i32 0
|
||||
%31 = load i8*, i8** %30, align 8
|
||||
%32 = load i64, i64* %4, align 8
|
||||
%33 = getelementptr i8, i8* %31, i64 %32
|
||||
%34 = load i8, i8* %33, align 1
|
||||
store i8 %29, i8* %14
|
||||
store i8 %34, i8* %21
|
||||
br label %for.post.-.3
|
||||
|
||||
for.done.-.5:
|
||||
ret void
|
||||
}
|
||||
|
||||
define {[4 x i8], i64} @encode_rune(i32 %r) {
|
||||
entry.-.0:
|
||||
%0 = alloca i32, align 4 ; r
|
||||
store i32 zeroinitializer, i32* %0
|
||||
store i32 %r, i32* %0
|
||||
%1 = alloca [4 x i8], align 1 ; buf
|
||||
store [4 x i8] zeroinitializer, [4 x i8]* %1
|
||||
%2 = alloca i32, align 4 ; i
|
||||
store i32 zeroinitializer, i32* %2
|
||||
%3 = load i32, i32* %0, align 4
|
||||
store i32 %3, i32* %2
|
||||
%4 = load i32, i32* %2, align 4
|
||||
%5 = icmp ule i32 %4, 127
|
||||
br i1 %5, label %if.then.-.1, label %if.done.-.2
|
||||
|
||||
if.then.-.1:
|
||||
%6 = getelementptr inbounds [4 x i8], [4 x i8]* %1, i64 0, i64 0
|
||||
%7 = getelementptr i8, i8* %6, i64 0
|
||||
%8 = load i32, i32* %0, align 4
|
||||
%9 = trunc i32 %8 to i8
|
||||
store i8 %9, i8* %7
|
||||
%10 = alloca {[4 x i8], i64}, align 8
|
||||
store {[4 x i8], i64} zeroinitializer, {[4 x i8], i64}* %10
|
||||
%11 = load [4 x i8], [4 x i8]* %1, align 1
|
||||
%12 = getelementptr inbounds {[4 x i8], i64}, {[4 x i8], i64}* %10, i64 0, i32 0
|
||||
store [4 x i8] %11, [4 x i8]* %12
|
||||
%13 = getelementptr inbounds {[4 x i8], i64}, {[4 x i8], i64}* %10, i64 0, i32 1
|
||||
store i64 1, i64* %13
|
||||
%14 = load {[4 x i8], i64}, {[4 x i8], i64}* %10, align 8
|
||||
ret {[4 x i8], i64} %14
|
||||
|
||||
if.done.-.2:
|
||||
%15 = load i32, i32* %2, align 4
|
||||
%16 = icmp ule i32 %15, 2047
|
||||
br i1 %16, label %if.then.-.3, label %if.done.-.4
|
||||
|
||||
if.then.-.3:
|
||||
%17 = getelementptr inbounds [4 x i8], [4 x i8]* %1, i64 0, i64 0
|
||||
%18 = getelementptr i8, i8* %17, i64 0
|
||||
%19 = load i32, i32* %0, align 4
|
||||
%20 = lshr i32 %19, 6
|
||||
%21 = trunc i32 %20 to i8
|
||||
%22 = or i8 192, %21
|
||||
store i8 %22, i8* %18
|
||||
%23 = getelementptr inbounds [4 x i8], [4 x i8]* %1, i64 0, i64 0
|
||||
%24 = getelementptr i8, i8* %23, i64 1
|
||||
%25 = load i32, i32* %0, align 4
|
||||
%26 = trunc i32 %25 to i8
|
||||
%27 = and i8 %26, 63
|
||||
%28 = or i8 128, %27
|
||||
store i8 %28, i8* %24
|
||||
%29 = alloca {[4 x i8], i64}, align 8
|
||||
store {[4 x i8], i64} zeroinitializer, {[4 x i8], i64}* %29
|
||||
%30 = load [4 x i8], [4 x i8]* %1, align 1
|
||||
%31 = getelementptr inbounds {[4 x i8], i64}, {[4 x i8], i64}* %29, i64 0, i32 0
|
||||
store [4 x i8] %30, [4 x i8]* %31
|
||||
%32 = getelementptr inbounds {[4 x i8], i64}, {[4 x i8], i64}* %29, i64 0, i32 1
|
||||
store i64 2, i64* %32
|
||||
%33 = load {[4 x i8], i64}, {[4 x i8], i64}* %29, align 8
|
||||
ret {[4 x i8], i64} %33
|
||||
|
||||
if.done.-.4:
|
||||
%34 = load i32, i32* %2, align 4
|
||||
%35 = icmp ugt i32 %34, 1114111
|
||||
br i1 %35, label %if.then.-.5, label %cmp-or.-.6
|
||||
|
||||
if.then.-.5:
|
||||
store i32 65533, i32* %0
|
||||
br label %if.done.-.8
|
||||
|
||||
cmp-or.-.6:
|
||||
%36 = load i32, i32* %2, align 4
|
||||
%37 = icmp uge i32 %36, 55296
|
||||
br i1 %37, label %cmp-and.-.7, label %if.done.-.8
|
||||
|
||||
cmp-and.-.7:
|
||||
%38 = load i32, i32* %2, align 4
|
||||
%39 = icmp ule i32 %38, 57343
|
||||
br i1 %39, label %if.then.-.5, label %if.done.-.8
|
||||
|
||||
if.done.-.8:
|
||||
%40 = load i32, i32* %2, align 4
|
||||
%41 = icmp ule i32 %40, 65535
|
||||
br i1 %41, label %if.then.-.9, label %if.done.-.10
|
||||
|
||||
if.then.-.9:
|
||||
%42 = getelementptr inbounds [4 x i8], [4 x i8]* %1, i64 0, i64 0
|
||||
%43 = getelementptr i8, i8* %42, i64 0
|
||||
%44 = load i32, i32* %0, align 4
|
||||
%45 = lshr i32 %44, 12
|
||||
%46 = trunc i32 %45 to i8
|
||||
%47 = or i8 224, %46
|
||||
store i8 %47, i8* %43
|
||||
%48 = getelementptr inbounds [4 x i8], [4 x i8]* %1, i64 0, i64 0
|
||||
%49 = getelementptr i8, i8* %48, i64 1
|
||||
%50 = load i32, i32* %0, align 4
|
||||
%51 = lshr i32 %50, 6
|
||||
%52 = trunc i32 %51 to i8
|
||||
%53 = and i8 %52, 63
|
||||
%54 = or i8 128, %53
|
||||
store i8 %54, i8* %49
|
||||
%55 = getelementptr inbounds [4 x i8], [4 x i8]* %1, i64 0, i64 0
|
||||
%56 = getelementptr i8, i8* %55, i64 2
|
||||
%57 = load i32, i32* %0, align 4
|
||||
%58 = trunc i32 %57 to i8
|
||||
%59 = and i8 %58, 63
|
||||
%60 = or i8 128, %59
|
||||
store i8 %60, i8* %56
|
||||
%61 = alloca {[4 x i8], i64}, align 8
|
||||
store {[4 x i8], i64} zeroinitializer, {[4 x i8], i64}* %61
|
||||
%62 = load [4 x i8], [4 x i8]* %1, align 1
|
||||
%63 = getelementptr inbounds {[4 x i8], i64}, {[4 x i8], i64}* %61, i64 0, i32 0
|
||||
store [4 x i8] %62, [4 x i8]* %63
|
||||
%64 = getelementptr inbounds {[4 x i8], i64}, {[4 x i8], i64}* %61, i64 0, i32 1
|
||||
store i64 3, i64* %64
|
||||
%65 = load {[4 x i8], i64}, {[4 x i8], i64}* %61, align 8
|
||||
ret {[4 x i8], i64} %65
|
||||
|
||||
if.done.-.10:
|
||||
%66 = getelementptr inbounds [4 x i8], [4 x i8]* %1, i64 0, i64 0
|
||||
%67 = getelementptr i8, i8* %66, i64 0
|
||||
%68 = load i32, i32* %0, align 4
|
||||
%69 = lshr i32 %68, 18
|
||||
%70 = trunc i32 %69 to i8
|
||||
%71 = or i8 240, %70
|
||||
store i8 %71, i8* %67
|
||||
%72 = getelementptr inbounds [4 x i8], [4 x i8]* %1, i64 0, i64 0
|
||||
%73 = getelementptr i8, i8* %72, i64 1
|
||||
%74 = load i32, i32* %0, align 4
|
||||
%75 = lshr i32 %74, 12
|
||||
%76 = trunc i32 %75 to i8
|
||||
%77 = and i8 %76, 63
|
||||
%78 = or i8 128, %77
|
||||
store i8 %78, i8* %73
|
||||
%79 = getelementptr inbounds [4 x i8], [4 x i8]* %1, i64 0, i64 0
|
||||
%80 = getelementptr i8, i8* %79, i64 2
|
||||
%81 = load i32, i32* %0, align 4
|
||||
%82 = lshr i32 %81, 6
|
||||
%83 = trunc i32 %82 to i8
|
||||
%84 = and i8 %83, 63
|
||||
%85 = or i8 128, %84
|
||||
store i8 %85, i8* %80
|
||||
%86 = getelementptr inbounds [4 x i8], [4 x i8]* %1, i64 0, i64 0
|
||||
%87 = getelementptr i8, i8* %86, i64 3
|
||||
%88 = load i32, i32* %0, align 4
|
||||
%89 = trunc i32 %88 to i8
|
||||
%90 = and i8 %89, 63
|
||||
%91 = or i8 128, %90
|
||||
store i8 %91, i8* %87
|
||||
%92 = alloca {[4 x i8], i64}, align 8
|
||||
store {[4 x i8], i64} zeroinitializer, {[4 x i8], i64}* %92
|
||||
%93 = load [4 x i8], [4 x i8]* %1, align 1
|
||||
%94 = getelementptr inbounds {[4 x i8], i64}, {[4 x i8], i64}* %92, i64 0, i32 0
|
||||
store [4 x i8] %93, [4 x i8]* %94
|
||||
%95 = getelementptr inbounds {[4 x i8], i64}, {[4 x i8], i64}* %92, i64 0, i32 1
|
||||
store i64 4, i64* %95
|
||||
%96 = load {[4 x i8], i64}, {[4 x i8], i64}* %92, align 8
|
||||
ret {[4 x i8], i64} %96
|
||||
}
|
||||
|
||||
define void @print_rune(i32 %r) {
|
||||
entry.-.0:
|
||||
%0 = alloca i32, align 4 ; r
|
||||
store i32 zeroinitializer, i32* %0
|
||||
store i32 %r, i32* %0
|
||||
%1 = alloca [4 x i8], align 1 ; buf
|
||||
store [4 x i8] zeroinitializer, [4 x i8]* %1
|
||||
%2 = alloca i64, align 8 ; n
|
||||
store i64 zeroinitializer, i64* %2
|
||||
%3 = load i32, i32* %0, align 4
|
||||
%4 = call {[4 x i8], i64} @encode_rune(i32 %3)
|
||||
%5 = extractvalue {[4 x i8], i64} %4, 0
|
||||
%6 = extractvalue {[4 x i8], i64} %4, 1
|
||||
store [4 x i8] %5, [4 x i8]* %1
|
||||
store i64 %6, i64* %2
|
||||
%7 = alloca %.string, align 8 ; str
|
||||
store %.string zeroinitializer, %.string* %7
|
||||
%8 = load i64, i64* %2, align 8
|
||||
%9 = sub i64 %8, 0
|
||||
%10 = sub i64 4, 0
|
||||
%11 = getelementptr inbounds [4 x i8], [4 x i8]* %1, i64 0, i64 0
|
||||
%12 = getelementptr i8, i8* %11, i64 0
|
||||
%13 = alloca {i8*, i64, i64}, align 8
|
||||
store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %13
|
||||
%14 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %13, i64 0, i32 0
|
||||
store i8* %12, i8** %14
|
||||
%15 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %13, i64 0, i32 1
|
||||
store i64 %9, i64* %15
|
||||
%16 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %13, i64 0, i32 2
|
||||
store i64 %10, i64* %16
|
||||
%17 = load {i8*, i64, i64}, {i8*, i64, i64}* %13, align 8
|
||||
%18 = alloca {i8*, i64, i64}, align 8
|
||||
store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %18
|
||||
store {i8*, i64, i64} %17, {i8*, i64, i64}* %18
|
||||
%19 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %18, i64 0, i32 0
|
||||
%20 = load i8*, i8** %19, align 8
|
||||
%21 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %18, i64 0, i32 1
|
||||
%22 = load i64, i64* %21, align 8
|
||||
%23 = alloca %.string, align 8
|
||||
store %.string zeroinitializer, %.string* %23
|
||||
%24 = getelementptr inbounds %.string, %.string* %23, i64 0, i32 0
|
||||
%25 = getelementptr inbounds %.string, %.string* %23, i64 0, i32 1
|
||||
store i8* %20, i8** %24
|
||||
store i64 %22, i64* %25
|
||||
%26 = load %.string, %.string* %23, align 8
|
||||
store %.string %26, %.string* %7
|
||||
%27 = load %.string, %.string* %7, align 8
|
||||
call void @print_string(%.string %27)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @print_int(i64 %i) {
|
||||
entry.-.0:
|
||||
%0 = alloca i64, align 8 ; i
|
||||
store i64 zeroinitializer, i64* %0
|
||||
store i64 %i, i64* %0
|
||||
%1 = load i64, i64* %0, align 8
|
||||
call void @print_int_base(i64 %1, i64 10)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @print_int_base(i64 %i, i64 %base) {
|
||||
entry.-.0:
|
||||
%0 = alloca i64, align 8 ; i
|
||||
store i64 zeroinitializer, i64* %0
|
||||
store i64 %i, i64* %0
|
||||
%1 = alloca i64, align 8 ; base
|
||||
store i64 zeroinitializer, i64* %1
|
||||
store i64 %base, i64* %1
|
||||
%2 = alloca [65 x i8], align 1 ; buf
|
||||
store [65 x i8] zeroinitializer, [65 x i8]* %2
|
||||
%3 = alloca i64, align 8 ; len
|
||||
store i64 zeroinitializer, i64* %3
|
||||
store i64 0, i64* %3
|
||||
%4 = alloca i1, align 1 ; negative
|
||||
store i1 zeroinitializer, i1* %4
|
||||
store i1 false, i1* %4
|
||||
%5 = load i64, i64* %0, align 8
|
||||
%6 = icmp slt i64 %5, 0
|
||||
br i1 %6, label %if.then.-.1, label %if.done.-.2
|
||||
|
||||
if.then.-.1:
|
||||
store i1 true, i1* %4
|
||||
%7 = load i64, i64* %0, align 8
|
||||
%8 = sub i64 0, %7
|
||||
store i64 %8, i64* %0
|
||||
br label %if.done.-.2
|
||||
|
||||
if.done.-.2:
|
||||
%9 = load i64, i64* %0, align 8
|
||||
%10 = icmp eq i64 %9, 0
|
||||
br i1 %10, label %if.then.-.3, label %if.done.-.4
|
||||
|
||||
if.then.-.3:
|
||||
%11 = getelementptr inbounds [65 x i8], [65 x i8]* %2, i64 0, i64 0
|
||||
%12 = load i64, i64* %3, align 8
|
||||
%13 = getelementptr i8, i8* %11, i64 %12
|
||||
store i8 48, i8* %13
|
||||
%14 = load i64, i64* %3, align 8
|
||||
%15 = add i64 %14, 1
|
||||
store i64 %15, i64* %3
|
||||
br label %if.done.-.4
|
||||
|
||||
if.done.-.4:
|
||||
br label %for.loop.-.5
|
||||
|
||||
for.loop.-.5:
|
||||
%16 = load i64, i64* %0, align 8
|
||||
%17 = icmp sgt i64 %16, 0
|
||||
br i1 %17, label %for.body.-.6, label %for.done.-.7
|
||||
|
||||
for.body.-.6:
|
||||
%18 = getelementptr inbounds [65 x i8], [65 x i8]* %2, i64 0, i64 0
|
||||
%19 = load i64, i64* %3, align 8
|
||||
%20 = getelementptr i8, i8* %18, i64 %19
|
||||
%21 = getelementptr inbounds [64 x i8], [64 x i8]* @.str4, i64 0, i64 0
|
||||
%22 = load i64, i64* %1, align 8
|
||||
%23 = load i64, i64* %0, align 8
|
||||
%24 = srem i64 %23, %22
|
||||
%25 = getelementptr i8, i8* %21, i64 %24
|
||||
%26 = load i8, i8* %25, align 1
|
||||
store i8 %26, i8* %20
|
||||
%27 = load i64, i64* %3, align 8
|
||||
%28 = add i64 %27, 1
|
||||
store i64 %28, i64* %3
|
||||
%29 = load i64, i64* %1, align 8
|
||||
%30 = load i64, i64* %0, align 8
|
||||
%31 = sdiv i64 %30, %29
|
||||
store i64 %31, i64* %0
|
||||
br label %for.loop.-.5
|
||||
|
||||
for.done.-.7:
|
||||
%32 = load i1, i1* %4, align 1
|
||||
br i1 %32, label %if.then.-.8, label %if.done.-.9
|
||||
|
||||
if.then.-.8:
|
||||
%33 = getelementptr inbounds [65 x i8], [65 x i8]* %2, i64 0, i64 0
|
||||
%34 = load i64, i64* %3, align 8
|
||||
%35 = getelementptr i8, i8* %33, i64 %34
|
||||
store i8 45, i8* %35
|
||||
%36 = load i64, i64* %3, align 8
|
||||
%37 = add i64 %36, 1
|
||||
store i64 %37, i64* %3
|
||||
br label %if.done.-.9
|
||||
|
||||
if.done.-.9:
|
||||
%38 = load i64, i64* %3, align 8
|
||||
%39 = sub i64 %38, 0
|
||||
%40 = sub i64 65, 0
|
||||
%41 = getelementptr inbounds [65 x i8], [65 x i8]* %2, i64 0, i64 0
|
||||
%42 = getelementptr i8, i8* %41, i64 0
|
||||
%43 = alloca {i8*, i64, i64}, align 8
|
||||
store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %43
|
||||
%44 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %43, i64 0, i32 0
|
||||
store i8* %42, i8** %44
|
||||
%45 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %43, i64 0, i32 1
|
||||
store i64 %39, i64* %45
|
||||
%46 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %43, i64 0, i32 2
|
||||
store i64 %40, i64* %46
|
||||
%47 = load {i8*, i64, i64}, {i8*, i64, i64}* %43, align 8
|
||||
call void @byte_reverse({i8*, i64, i64} %47)
|
||||
%48 = load i64, i64* %3, align 8
|
||||
%49 = sub i64 %48, 0
|
||||
%50 = sub i64 65, 0
|
||||
%51 = getelementptr inbounds [65 x i8], [65 x i8]* %2, i64 0, i64 0
|
||||
%52 = getelementptr i8, i8* %51, i64 0
|
||||
%53 = alloca {i8*, i64, i64}, align 8
|
||||
store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %53
|
||||
%54 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %53, i64 0, i32 0
|
||||
store i8* %52, i8** %54
|
||||
%55 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %53, i64 0, i32 1
|
||||
store i64 %49, i64* %55
|
||||
%56 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %53, i64 0, i32 2
|
||||
store i64 %50, i64* %56
|
||||
%57 = load {i8*, i64, i64}, {i8*, i64, i64}* %53, align 8
|
||||
%58 = alloca {i8*, i64, i64}, align 8
|
||||
store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %58
|
||||
store {i8*, i64, i64} %57, {i8*, i64, i64}* %58
|
||||
%59 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %58, i64 0, i32 0
|
||||
%60 = load i8*, i8** %59, align 8
|
||||
%61 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %58, i64 0, i32 1
|
||||
%62 = load i64, i64* %61, align 8
|
||||
%63 = alloca %.string, align 8
|
||||
store %.string zeroinitializer, %.string* %63
|
||||
%64 = getelementptr inbounds %.string, %.string* %63, i64 0, i32 0
|
||||
%65 = getelementptr inbounds %.string, %.string* %63, i64 0, i32 1
|
||||
store i8* %60, i8** %64
|
||||
store i64 %62, i64* %65
|
||||
%66 = load %.string, %.string* %63, align 8
|
||||
call void @print_string(%.string %66)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @print_uint(i64 %i) {
|
||||
entry.-.0:
|
||||
%0 = alloca i64, align 8 ; i
|
||||
store i64 zeroinitializer, i64* %0
|
||||
store i64 %i, i64* %0
|
||||
%1 = load i64, i64* %0, align 8
|
||||
call void @print_uint_base(i64 %1, i64 10)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @print_uint_base(i64 %i, i64 %base) {
|
||||
entry.-.0:
|
||||
%0 = alloca i64, align 8 ; i
|
||||
store i64 zeroinitializer, i64* %0
|
||||
store i64 %i, i64* %0
|
||||
%1 = alloca i64, align 8 ; base
|
||||
store i64 zeroinitializer, i64* %1
|
||||
store i64 %base, i64* %1
|
||||
%2 = alloca [65 x i8], align 1 ; buf
|
||||
store [65 x i8] zeroinitializer, [65 x i8]* %2
|
||||
%3 = alloca i64, align 8 ; len
|
||||
store i64 zeroinitializer, i64* %3
|
||||
store i64 0, i64* %3
|
||||
%4 = alloca i1, align 1 ; negative
|
||||
store i1 zeroinitializer, i1* %4
|
||||
store i1 false, i1* %4
|
||||
%5 = load i64, i64* %0, align 8
|
||||
%6 = icmp ult i64 %5, 0
|
||||
br i1 %6, label %if.then.-.1, label %if.done.-.2
|
||||
|
||||
if.then.-.1:
|
||||
store i1 true, i1* %4
|
||||
%7 = load i64, i64* %0, align 8
|
||||
%8 = sub i64 0, %7
|
||||
store i64 %8, i64* %0
|
||||
br label %if.done.-.2
|
||||
|
||||
if.done.-.2:
|
||||
%9 = load i64, i64* %0, align 8
|
||||
%10 = icmp eq i64 %9, 0
|
||||
br i1 %10, label %if.then.-.3, label %if.done.-.4
|
||||
|
||||
if.then.-.3:
|
||||
%11 = getelementptr inbounds [65 x i8], [65 x i8]* %2, i64 0, i64 0
|
||||
%12 = load i64, i64* %3, align 8
|
||||
%13 = getelementptr i8, i8* %11, i64 %12
|
||||
store i8 48, i8* %13
|
||||
%14 = load i64, i64* %3, align 8
|
||||
%15 = add i64 %14, 1
|
||||
store i64 %15, i64* %3
|
||||
br label %if.done.-.4
|
||||
|
||||
if.done.-.4:
|
||||
br label %for.loop.-.5
|
||||
|
||||
for.loop.-.5:
|
||||
%16 = load i64, i64* %0, align 8
|
||||
%17 = icmp ugt i64 %16, 0
|
||||
br i1 %17, label %for.body.-.6, label %for.done.-.7
|
||||
|
||||
for.body.-.6:
|
||||
%18 = getelementptr inbounds [65 x i8], [65 x i8]* %2, i64 0, i64 0
|
||||
%19 = load i64, i64* %3, align 8
|
||||
%20 = getelementptr i8, i8* %18, i64 %19
|
||||
%21 = getelementptr inbounds [64 x i8], [64 x i8]* @.str5, i64 0, i64 0
|
||||
%22 = load i64, i64* %1, align 8
|
||||
%23 = load i64, i64* %0, align 8
|
||||
%24 = urem i64 %23, %22
|
||||
%25 = getelementptr i8, i8* %21, i64 %24
|
||||
%26 = load i8, i8* %25, align 1
|
||||
store i8 %26, i8* %20
|
||||
%27 = load i64, i64* %3, align 8
|
||||
%28 = add i64 %27, 1
|
||||
store i64 %28, i64* %3
|
||||
%29 = load i64, i64* %1, align 8
|
||||
%30 = load i64, i64* %0, align 8
|
||||
%31 = udiv i64 %30, %29
|
||||
store i64 %31, i64* %0
|
||||
br label %for.loop.-.5
|
||||
|
||||
for.done.-.7:
|
||||
%32 = load i1, i1* %4, align 1
|
||||
br i1 %32, label %if.then.-.8, label %if.done.-.9
|
||||
|
||||
if.then.-.8:
|
||||
%33 = getelementptr inbounds [65 x i8], [65 x i8]* %2, i64 0, i64 0
|
||||
%34 = load i64, i64* %3, align 8
|
||||
%35 = getelementptr i8, i8* %33, i64 %34
|
||||
store i8 45, i8* %35
|
||||
%36 = load i64, i64* %3, align 8
|
||||
%37 = add i64 %36, 1
|
||||
store i64 %37, i64* %3
|
||||
br label %if.done.-.9
|
||||
|
||||
if.done.-.9:
|
||||
%38 = load i64, i64* %3, align 8
|
||||
%39 = sub i64 %38, 0
|
||||
%40 = sub i64 65, 0
|
||||
%41 = getelementptr inbounds [65 x i8], [65 x i8]* %2, i64 0, i64 0
|
||||
%42 = getelementptr i8, i8* %41, i64 0
|
||||
%43 = alloca {i8*, i64, i64}, align 8
|
||||
store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %43
|
||||
%44 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %43, i64 0, i32 0
|
||||
store i8* %42, i8** %44
|
||||
%45 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %43, i64 0, i32 1
|
||||
store i64 %39, i64* %45
|
||||
%46 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %43, i64 0, i32 2
|
||||
store i64 %40, i64* %46
|
||||
%47 = load {i8*, i64, i64}, {i8*, i64, i64}* %43, align 8
|
||||
call void @byte_reverse({i8*, i64, i64} %47)
|
||||
%48 = load i64, i64* %3, align 8
|
||||
%49 = sub i64 %48, 0
|
||||
%50 = sub i64 65, 0
|
||||
%51 = getelementptr inbounds [65 x i8], [65 x i8]* %2, i64 0, i64 0
|
||||
%52 = getelementptr i8, i8* %51, i64 0
|
||||
%53 = alloca {i8*, i64, i64}, align 8
|
||||
store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %53
|
||||
%54 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %53, i64 0, i32 0
|
||||
store i8* %52, i8** %54
|
||||
%55 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %53, i64 0, i32 1
|
||||
store i64 %49, i64* %55
|
||||
%56 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %53, i64 0, i32 2
|
||||
store i64 %50, i64* %56
|
||||
%57 = load {i8*, i64, i64}, {i8*, i64, i64}* %53, align 8
|
||||
%58 = alloca {i8*, i64, i64}, align 8
|
||||
store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %58
|
||||
store {i8*, i64, i64} %57, {i8*, i64, i64}* %58
|
||||
%59 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %58, i64 0, i32 0
|
||||
%60 = load i8*, i8** %59, align 8
|
||||
%61 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %58, i64 0, i32 1
|
||||
%62 = load i64, i64* %61, align 8
|
||||
%63 = alloca %.string, align 8
|
||||
store %.string zeroinitializer, %.string* %63
|
||||
%64 = getelementptr inbounds %.string, %.string* %63, i64 0, i32 0
|
||||
%65 = getelementptr inbounds %.string, %.string* %63, i64 0, i32 1
|
||||
store i8* %60, i8** %64
|
||||
store i64 %62, i64* %65
|
||||
%66 = load %.string, %.string* %63, align 8
|
||||
call void @print_string(%.string %66)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @print_bool(i1 %b) {
|
||||
entry.-.0:
|
||||
%0 = alloca i1, align 1 ; b
|
||||
store i1 zeroinitializer, i1* %0
|
||||
store i1 %b, i1* %0
|
||||
%1 = load i1, i1* %0, align 1
|
||||
br i1 %1, label %if.then.-.1, label %if.else.-.2
|
||||
|
||||
if.then.-.1:
|
||||
%2 = getelementptr inbounds [4 x i8], [4 x i8]* @.str6, i64 0, i64 0
|
||||
%3 = alloca %.string, align 8
|
||||
store %.string zeroinitializer, %.string* %3
|
||||
%4 = getelementptr inbounds %.string, %.string* %3, i64 0, i32 0
|
||||
%5 = getelementptr inbounds %.string, %.string* %3, i64 0, i32 1
|
||||
store i8* %2, i8** %4
|
||||
store i64 4, i64* %5
|
||||
%6 = load %.string, %.string* %3, align 8
|
||||
call void @print_string(%.string %6)
|
||||
br label %if.done.-.3
|
||||
|
||||
if.else.-.2:
|
||||
%7 = getelementptr inbounds [5 x i8], [5 x i8]* @.str7, i64 0, i64 0
|
||||
%8 = alloca %.string, align 8
|
||||
store %.string zeroinitializer, %.string* %8
|
||||
%9 = getelementptr inbounds %.string, %.string* %8, i64 0, i32 0
|
||||
%10 = getelementptr inbounds %.string, %.string* %8, i64 0, i32 1
|
||||
store i8* %7, i8** %9
|
||||
store i64 5, i64* %10
|
||||
%11 = load %.string, %.string* %8, align 8
|
||||
call void @print_string(%.string %11)
|
||||
br label %if.done.-.3
|
||||
|
||||
if.done.-.3:
|
||||
ret void
|
||||
}
|
||||
|
||||
define i1 @__string_eq(%.string %a, %.string %b) {
|
||||
entry.-.0:
|
||||
%0 = alloca %.string, align 8 ; a
|
||||
store %.string zeroinitializer, %.string* %0
|
||||
store %.string %a, %.string* %0
|
||||
%1 = alloca %.string, align 8 ; b
|
||||
store %.string zeroinitializer, %.string* %1
|
||||
store %.string %b, %.string* %1
|
||||
%2 = getelementptr inbounds %.string, %.string* %0, i64 0, i32 1
|
||||
%3 = load i64, i64* %2, align 8
|
||||
%4 = getelementptr inbounds %.string, %.string* %1, i64 0, i32 1
|
||||
%5 = load i64, i64* %4, align 8
|
||||
%6 = icmp ne i64 %3, %5
|
||||
br i1 %6, label %if.then.-.1, label %if.done.-.2
|
||||
|
||||
if.then.-.1:
|
||||
ret i1 false
|
||||
|
||||
if.done.-.2:
|
||||
%7 = getelementptr inbounds %.string, %.string* %0, i64 0, i32 0
|
||||
%8 = load i8*, i8** %7, align 8
|
||||
%9 = getelementptr i8, i8* %8, i64 0
|
||||
%10 = getelementptr inbounds i8, i8* %9
|
||||
%11 = getelementptr inbounds %.string, %.string* %1, i64 0, i32 0
|
||||
%12 = load i8*, i8** %11, align 8
|
||||
%13 = getelementptr i8, i8* %12, i64 0
|
||||
%14 = getelementptr inbounds i8, i8* %13
|
||||
%15 = icmp eq i8* %10, %14
|
||||
br i1 %15, label %if.then.-.3, label %if.done.-.4
|
||||
|
||||
if.then.-.3:
|
||||
ret i1 true
|
||||
|
||||
if.done.-.4:
|
||||
%16 = getelementptr inbounds %.string, %.string* %0, i64 0, i32 0
|
||||
%17 = load i8*, i8** %16, align 8
|
||||
%18 = getelementptr i8, i8* %17, i64 0
|
||||
%19 = getelementptr inbounds i8, i8* %18
|
||||
%20 = getelementptr inbounds %.string, %.string* %1, i64 0, i32 0
|
||||
%21 = load i8*, i8** %20, align 8
|
||||
%22 = getelementptr i8, i8* %21, i64 0
|
||||
%23 = getelementptr inbounds i8, i8* %22
|
||||
%24 = getelementptr inbounds %.string, %.string* %0, i64 0, i32 1
|
||||
%25 = load i64, i64* %24, align 8
|
||||
%26 = call i32 @memcmp(%.rawptr %19, %.rawptr %23, i64 %25)
|
||||
%27 = icmp eq i32 %26, 0
|
||||
ret i1 %27
|
||||
}
|
||||
|
||||
define i1 @__string_ne(%.string %a, %.string %b) {
|
||||
entry.-.0:
|
||||
%0 = alloca %.string, align 8 ; a
|
||||
store %.string zeroinitializer, %.string* %0
|
||||
store %.string %a, %.string* %0
|
||||
%1 = alloca %.string, align 8 ; b
|
||||
store %.string zeroinitializer, %.string* %1
|
||||
store %.string %b, %.string* %1
|
||||
%2 = load %.string, %.string* %0, align 8
|
||||
%3 = load %.string, %.string* %1, align 8
|
||||
%4 = call i1 @__string_eq(%.string %2, %.string %3)
|
||||
%5 = xor i1 %4, -1
|
||||
ret i1 %5
|
||||
}
|
||||
|
||||
define i64 @__string_cmp(%.string %a, %.string %b) {
|
||||
entry.-.0:
|
||||
%0 = alloca %.string, align 8 ; a
|
||||
store %.string zeroinitializer, %.string* %0
|
||||
store %.string %a, %.string* %0
|
||||
%1 = alloca %.string, align 8 ; b
|
||||
store %.string zeroinitializer, %.string* %1
|
||||
store %.string %b, %.string* %1
|
||||
%2 = alloca i64, align 8 ; min_len
|
||||
store i64 zeroinitializer, i64* %2
|
||||
%3 = getelementptr inbounds %.string, %.string* %0, i64 0, i32 1
|
||||
%4 = load i64, i64* %3, align 8
|
||||
store i64 %4, i64* %2
|
||||
%5 = getelementptr inbounds %.string, %.string* %1, i64 0, i32 1
|
||||
%6 = load i64, i64* %5, align 8
|
||||
%7 = load i64, i64* %2, align 8
|
||||
%8 = icmp slt i64 %6, %7
|
||||
br i1 %8, label %if.then.-.1, label %if.done.-.2
|
||||
|
||||
if.then.-.1:
|
||||
%9 = getelementptr inbounds %.string, %.string* %1, i64 0, i32 1
|
||||
%10 = load i64, i64* %9, align 8
|
||||
store i64 %10, i64* %2
|
||||
br label %if.done.-.2
|
||||
|
||||
if.done.-.2:
|
||||
br label %for.init.-.3
|
||||
|
||||
for.init.-.3:
|
||||
%11 = alloca i64, align 8 ; i
|
||||
store i64 zeroinitializer, i64* %11
|
||||
store i64 0, i64* %11
|
||||
br label %for.loop.-.4
|
||||
|
||||
for.loop.-.4:
|
||||
%12 = load i64, i64* %11, align 8
|
||||
%13 = load i64, i64* %2, align 8
|
||||
%14 = icmp slt i64 %12, %13
|
||||
br i1 %14, label %for.body.-.6, label %for.done.-.12
|
||||
|
||||
for.post.-.5:
|
||||
%15 = load i64, i64* %11, align 8
|
||||
%16 = add i64 %15, 1
|
||||
store i64 %16, i64* %11
|
||||
br label %for.loop.-.4
|
||||
|
||||
for.body.-.6:
|
||||
%17 = alloca i8, align 1 ; x
|
||||
store i8 zeroinitializer, i8* %17
|
||||
%18 = getelementptr inbounds %.string, %.string* %0, i64 0, i32 0
|
||||
%19 = load i8*, i8** %18, align 8
|
||||
%20 = load i64, i64* %11, align 8
|
||||
%21 = getelementptr i8, i8* %19, i64 %20
|
||||
%22 = load i8, i8* %21, align 1
|
||||
store i8 %22, i8* %17
|
||||
%23 = alloca i8, align 1 ; y
|
||||
store i8 zeroinitializer, i8* %23
|
||||
%24 = getelementptr inbounds %.string, %.string* %1, i64 0, i32 0
|
||||
%25 = load i8*, i8** %24, align 8
|
||||
%26 = load i64, i64* %11, align 8
|
||||
%27 = getelementptr i8, i8* %25, i64 %26
|
||||
%28 = load i8, i8* %27, align 1
|
||||
store i8 %28, i8* %23
|
||||
%29 = load i8, i8* %17, align 1
|
||||
%30 = load i8, i8* %23, align 1
|
||||
%31 = icmp ult i8 %29, %30
|
||||
br i1 %31, label %if.then.-.7, label %if.else.-.8
|
||||
|
||||
if.then.-.7:
|
||||
ret i64 -1
|
||||
|
||||
if.else.-.8:
|
||||
%32 = load i8, i8* %17, align 1
|
||||
%33 = load i8, i8* %23, align 1
|
||||
%34 = icmp ugt i8 %32, %33
|
||||
br i1 %34, label %if.then.-.9, label %if.done.-.10
|
||||
|
||||
if.then.-.9:
|
||||
ret i64 1
|
||||
|
||||
if.done.-.10:
|
||||
br label %if.done.-.11
|
||||
|
||||
if.done.-.11:
|
||||
br label %for.post.-.5
|
||||
|
||||
for.done.-.12:
|
||||
%35 = getelementptr inbounds %.string, %.string* %0, i64 0, i32 1
|
||||
%36 = load i64, i64* %35, align 8
|
||||
%37 = getelementptr inbounds %.string, %.string* %1, i64 0, i32 1
|
||||
%38 = load i64, i64* %37, align 8
|
||||
%39 = icmp slt i64 %36, %38
|
||||
br i1 %39, label %if.then.-.13, label %if.else.-.14
|
||||
|
||||
if.then.-.13:
|
||||
ret i64 -1
|
||||
|
||||
if.else.-.14:
|
||||
%40 = getelementptr inbounds %.string, %.string* %0, i64 0, i32 1
|
||||
%41 = load i64, i64* %40, align 8
|
||||
%42 = getelementptr inbounds %.string, %.string* %1, i64 0, i32 1
|
||||
%43 = load i64, i64* %42, align 8
|
||||
%44 = icmp sgt i64 %41, %43
|
||||
br i1 %44, label %if.then.-.15, label %if.done.-.16
|
||||
|
||||
if.then.-.15:
|
||||
ret i64 1
|
||||
|
||||
if.done.-.16:
|
||||
br label %if.done.-.17
|
||||
|
||||
if.done.-.17:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
define i1 @__string_lt(%.string %a, %.string %b) {
|
||||
entry.-.0:
|
||||
%0 = alloca %.string, align 8 ; a
|
||||
store %.string zeroinitializer, %.string* %0
|
||||
store %.string %a, %.string* %0
|
||||
%1 = alloca %.string, align 8 ; b
|
||||
store %.string zeroinitializer, %.string* %1
|
||||
store %.string %b, %.string* %1
|
||||
%2 = load %.string, %.string* %0, align 8
|
||||
%3 = load %.string, %.string* %1, align 8
|
||||
%4 = call i64 @__string_cmp(%.string %2, %.string %3)
|
||||
%5 = icmp slt i64 %4, 0
|
||||
ret i1 %5
|
||||
}
|
||||
|
||||
define i1 @__string_gt(%.string %a, %.string %b) {
|
||||
entry.-.0:
|
||||
%0 = alloca %.string, align 8 ; a
|
||||
store %.string zeroinitializer, %.string* %0
|
||||
store %.string %a, %.string* %0
|
||||
%1 = alloca %.string, align 8 ; b
|
||||
store %.string zeroinitializer, %.string* %1
|
||||
store %.string %b, %.string* %1
|
||||
%2 = load %.string, %.string* %0, align 8
|
||||
%3 = load %.string, %.string* %1, align 8
|
||||
%4 = call i64 @__string_cmp(%.string %2, %.string %3)
|
||||
%5 = icmp sgt i64 %4, 0
|
||||
ret i1 %5
|
||||
}
|
||||
|
||||
define i1 @__string_le(%.string %a, %.string %b) {
|
||||
entry.-.0:
|
||||
%0 = alloca %.string, align 8 ; a
|
||||
store %.string zeroinitializer, %.string* %0
|
||||
store %.string %a, %.string* %0
|
||||
%1 = alloca %.string, align 8 ; b
|
||||
store %.string zeroinitializer, %.string* %1
|
||||
store %.string %b, %.string* %1
|
||||
%2 = load %.string, %.string* %0, align 8
|
||||
%3 = load %.string, %.string* %1, align 8
|
||||
%4 = call i64 @__string_cmp(%.string %2, %.string %3)
|
||||
%5 = icmp sle i64 %4, 0
|
||||
ret i1 %5
|
||||
}
|
||||
|
||||
define i1 @__string_ge(%.string %a, %.string %b) {
|
||||
entry.-.0:
|
||||
%0 = alloca %.string, align 8 ; a
|
||||
store %.string zeroinitializer, %.string* %0
|
||||
store %.string %a, %.string* %0
|
||||
%1 = alloca %.string, align 8 ; b
|
||||
store %.string zeroinitializer, %.string* %1
|
||||
store %.string %b, %.string* %1
|
||||
%2 = load %.string, %.string* %0, align 8
|
||||
%3 = load %.string, %.string* %1, align 8
|
||||
%4 = call i64 @__string_cmp(%.string %2, %.string %3)
|
||||
%5 = icmp sge i64 %4, 0
|
||||
ret i1 %5
|
||||
}
|
||||
|
||||
@.str0 = global [5 x i8] c"Hello"
|
||||
@.str1 = global [5 x i8] c"Hello"
|
||||
@.str2 = global [2 x i8] c"\3AD"
|
||||
@.str3 = global [3 x i8] c"\3A\27\28"
|
||||
@.str4 = global [64 x i8] c"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\40$"
|
||||
@.str5 = global [64 x i8] c"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\40$"
|
||||
@.str6 = global [4 x i8] c"true"
|
||||
@.str7 = global [5 x i8] c"false"
|
||||
|
||||
@@ -1,57 +1,18 @@
|
||||
pc :: proc(c: i32) #foreign "putchar"
|
||||
|
||||
main :: proc() {
|
||||
f :: false;
|
||||
t :: true;
|
||||
v := {8}bool{t, f, t, f, t, f, t, f};
|
||||
pc(v[0] as rune + 'A');
|
||||
pc(v[1] as rune + 'A');
|
||||
pc(v[2] as rune + 'A');
|
||||
pc(v[3] as rune + 'A');
|
||||
pc('\n');
|
||||
}
|
||||
|
||||
/*
|
||||
import "basic"
|
||||
#load "basic.odin"
|
||||
|
||||
TWO_HEARTS :: '💕';
|
||||
|
||||
main :: proc() {
|
||||
nl :: proc() { print_rune('\n'); }
|
||||
|
||||
t :: true;
|
||||
f :: false;
|
||||
|
||||
// v := {8}bool{t, t, t, f, f, f, t, t};
|
||||
v : {8}bool;
|
||||
v[0] = true;
|
||||
v[1] = false;
|
||||
v[2] = true;
|
||||
|
||||
for i := 0; i < len(v); i++ {
|
||||
b := v[i];
|
||||
if b {
|
||||
print_rune('t');
|
||||
} else {
|
||||
print_rune('f');
|
||||
}
|
||||
nl();
|
||||
a := "Hello";
|
||||
if a >= "Hello" {
|
||||
print_string(":D"); nl();
|
||||
} else {
|
||||
print_string(":'("); nl();
|
||||
}
|
||||
// v[1] = false;
|
||||
// v[2] = true;
|
||||
// print_rune(v[0] as rune + 65); nl();
|
||||
// print_rune(v[1] as rune + 65); nl();
|
||||
// print_rune(v[2] as rune + 65); nl();
|
||||
|
||||
|
||||
// for i := 0; i < len(v); i++ {
|
||||
// v[i] = (i%2) == 0;
|
||||
// }
|
||||
// for i := 0; i < len(v); i++ {
|
||||
// print_bool(v[i]); nl();
|
||||
// }
|
||||
|
||||
// print_int(v transmute u8 as int);
|
||||
/*
|
||||
DATA_SIZE :: 100;
|
||||
data := malloc(DATA_SIZE);
|
||||
@@ -89,4 +50,3 @@ main :: proc() {
|
||||
// print_string("Russian - Здравствулте мир\n");
|
||||
// print_string("Spanish - Hola mundo\n");
|
||||
// }
|
||||
*/
|
||||
|
||||
8
run.bat
8
run.bat
@@ -1,9 +1,13 @@
|
||||
@echo off
|
||||
|
||||
|
||||
call ..\bin\odin.exe ..\examples/main.odin ^
|
||||
&& ..\misc\llvm-bin\lli.exe ..\examples/main.ll
|
||||
rem call clang -c -emit-llvm -DGB_IMPLEMENTATION -DGB_DEF=GB_DLL_EXPORT ..\src\gb\gb.h
|
||||
|
||||
call ..\bin\odin.exe ..\examples/main.odin ^
|
||||
&& ..\misc\llvm-bin\opt.exe -mem2reg ..\examples/main.ll -o ..\examples/main.bc ^
|
||||
&& ..\misc\llvm-bin\lli.exe ..\examples/main.bc
|
||||
|
||||
rem && llvm-dis ..\examples/main.bc -o - ^
|
||||
rem call ..\misc\llvm-bin\opt.exe -mem2reg ..\examples/output.ll > ..\examples/main.bc
|
||||
rem call llc ..\examples/main.bc
|
||||
rem call llvm-dis ..\examples/main.bc -o ..\examples/output.ll
|
||||
|
||||
@@ -242,7 +242,7 @@ void check_close_scope(Checker *c) {
|
||||
}
|
||||
|
||||
void scope_lookup_parent_entity(Scope *s, String name, Scope **scope, Entity **entity) {
|
||||
u64 key = hash_string(name);
|
||||
HashKey key = hash_string(name);
|
||||
for (; s != NULL; s = s->parent) {
|
||||
Entity **found = map_get(&s->elements, key);
|
||||
if (found) {
|
||||
@@ -262,7 +262,7 @@ Entity *scope_lookup_entity(Scope *s, String name) {
|
||||
}
|
||||
|
||||
Entity *current_scope_lookup_entity(Scope *s, String name) {
|
||||
u64 key = hash_string(name);
|
||||
HashKey key = hash_string(name);
|
||||
Entity **found = map_get(&s->elements, key);
|
||||
if (found)
|
||||
return *found;
|
||||
@@ -273,7 +273,7 @@ Entity *current_scope_lookup_entity(Scope *s, String name) {
|
||||
|
||||
Entity *scope_insert_entity(Scope *s, Entity *entity) {
|
||||
String name = entity->token.string;
|
||||
u64 key = hash_string(name);
|
||||
HashKey key = hash_string(name);
|
||||
Entity **found = map_get(&s->elements, key);
|
||||
if (found)
|
||||
return *found;
|
||||
@@ -465,7 +465,7 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode
|
||||
void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity) {
|
||||
GB_ASSERT(identifier != NULL);
|
||||
GB_ASSERT(identifier->kind == AstNode_Ident);
|
||||
u64 key = hash_pointer(identifier);
|
||||
HashKey key = hash_pointer(identifier);
|
||||
map_set(&i->definitions, key, entity);
|
||||
}
|
||||
|
||||
@@ -484,7 +484,7 @@ void add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
|
||||
void add_entity_use(CheckerInfo *i, AstNode *identifier, Entity *entity) {
|
||||
GB_ASSERT(identifier != NULL);
|
||||
GB_ASSERT(identifier->kind == AstNode_Ident);
|
||||
u64 key = hash_pointer(identifier);
|
||||
HashKey key = hash_pointer(identifier);
|
||||
map_set(&i->uses, key, entity);
|
||||
}
|
||||
|
||||
@@ -648,7 +648,7 @@ void check_parsed_files(Checker *c) {
|
||||
|
||||
case_end;
|
||||
|
||||
case_ast_node(id, ImportDecl, decl);
|
||||
case_ast_node(ld, LoadDecl, decl);
|
||||
// NOTE(bill): ignore
|
||||
case_end;
|
||||
|
||||
@@ -662,7 +662,7 @@ void check_parsed_files(Checker *c) {
|
||||
|
||||
gb_for_array(i, c->info.entities.entries) {
|
||||
auto *entry = &c->info.entities.entries[i];
|
||||
Entity *e = cast(Entity *)cast(uintptr)entry->key;
|
||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
||||
DeclInfo *d = entry->value;
|
||||
check_entity_decl(c, e, d, NULL);
|
||||
}
|
||||
@@ -679,8 +679,8 @@ void check_parsed_files(Checker *c) {
|
||||
// Add untyped expression values
|
||||
gb_for_array(i, c->info.untyped.entries) {
|
||||
auto *entry = c->info.untyped.entries + i;
|
||||
u64 key = entry->key;
|
||||
AstNode *expr = cast(AstNode *)cast(uintptr)key;
|
||||
HashKey key = entry->key;
|
||||
AstNode *expr = cast(AstNode *)cast(uintptr)key.key;
|
||||
ExpressionInfo *info = &entry->value;
|
||||
if (info != NULL && expr != NULL) {
|
||||
if (is_type_typed(info->type)) {
|
||||
|
||||
@@ -41,7 +41,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
|
||||
Token name_token = i->token;
|
||||
// TODO(bill): is the curr_scope correct?
|
||||
Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type);
|
||||
u64 key = hash_string(name_token.string);
|
||||
HashKey key = hash_string(name_token.string);
|
||||
if (map_get(&entity_map, key)) {
|
||||
// TODO(bill): Scope checking already checks the declaration
|
||||
error(&c->error_collector, name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
|
||||
@@ -615,8 +615,10 @@ b32 check_is_expr_vector_index(Checker *c, AstNode *expr) {
|
||||
expr = unparen_expr(expr);
|
||||
if (expr->kind == AstNode_IndexExpr) {
|
||||
ast_node(ie, IndexExpr, expr);
|
||||
Type *t = get_base_type(type_of_expr(&c->info, ie->expr));
|
||||
return is_type_vector(t);
|
||||
Type *t = type_of_expr(&c->info, ie->expr);
|
||||
if (t != NULL) {
|
||||
return is_type_vector(get_base_type(t));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1057,7 +1059,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
||||
|
||||
|
||||
void update_expr_type(Checker *c, AstNode *e, Type *type, b32 final) {
|
||||
u64 key = hash_pointer(e);
|
||||
HashKey key = hash_pointer(e);
|
||||
ExpressionInfo *found = map_get(&c->info.untyped, key);
|
||||
if (found == NULL)
|
||||
return;
|
||||
|
||||
@@ -58,7 +58,7 @@ void ssa_gen_code(ssaGen *s) {
|
||||
|
||||
gb_for_array(i, info->entities.entries) {
|
||||
auto *entry = &info->entities.entries[i];
|
||||
Entity *e = cast(Entity *)cast(uintptr)entry->key;
|
||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
||||
DeclInfo *decl = entry->value;
|
||||
|
||||
String name = e->token.string;
|
||||
|
||||
@@ -400,7 +400,32 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
|
||||
ssa_fprintf(f, "%%%d = ", value->id);
|
||||
|
||||
if (gb_is_between(bo->op.kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) {
|
||||
if (is_type_float(elem_type)) {
|
||||
|
||||
if (is_type_string(elem_type)) {
|
||||
ssa_fprintf(f, "call ");
|
||||
ssa_print_type(f, m->sizes, t_bool);
|
||||
char *runtime_proc = "";
|
||||
switch (bo->op.kind) {
|
||||
case Token_CmpEq: runtime_proc = "__string_eq"; break;
|
||||
case Token_NotEq: runtime_proc = "__string_ne"; break;
|
||||
case Token_Lt: runtime_proc = "__string_lt"; break;
|
||||
case Token_Gt: runtime_proc = "__string_gt"; break;
|
||||
case Token_LtEq: runtime_proc = "__string_le"; break;
|
||||
case Token_GtEq: runtime_proc = "__string_gt"; break;
|
||||
}
|
||||
|
||||
ssa_fprintf(f, " @%s(", runtime_proc);
|
||||
ssa_print_type(f, m->sizes, type);
|
||||
ssa_fprintf(f, " ");
|
||||
ssa_print_value(f, m, bo->left, type);
|
||||
ssa_fprintf(f, ", ");
|
||||
ssa_print_type(f, m->sizes, type);
|
||||
ssa_fprintf(f, " ");
|
||||
ssa_print_value(f, m, bo->right, type);
|
||||
ssa_fprintf(f, ")\n");
|
||||
return;
|
||||
|
||||
} else if (is_type_float(elem_type)) {
|
||||
ssa_fprintf(f, "fcmp ");
|
||||
switch (bo->op.kind) {
|
||||
case Token_CmpEq: ssa_fprintf(f, "oeq"); break;
|
||||
@@ -434,14 +459,15 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
|
||||
ssa_fprintf(f, "f");
|
||||
|
||||
switch (bo->op.kind) {
|
||||
case Token_Add: ssa_fprintf(f, "add"); break;
|
||||
case Token_Sub: ssa_fprintf(f, "sub"); break;
|
||||
case Token_And: ssa_fprintf(f, "and"); break;
|
||||
case Token_Or: ssa_fprintf(f, "or"); break;
|
||||
case Token_Xor: ssa_fprintf(f, "xor"); break;
|
||||
case Token_Shl: ssa_fprintf(f, "shl"); break;
|
||||
case Token_Add: ssa_fprintf(f, "add"); break;
|
||||
case Token_Sub: ssa_fprintf(f, "sub"); break;
|
||||
case Token_And: ssa_fprintf(f, "and"); break;
|
||||
case Token_Or: ssa_fprintf(f, "or"); break;
|
||||
case Token_Xor: ssa_fprintf(f, "xor"); break;
|
||||
case Token_Shl: ssa_fprintf(f, "shl"); break;
|
||||
case Token_Shr: ssa_fprintf(f, "lshr"); break;
|
||||
case Token_Mul: ssa_fprintf(f, "mul"); break;
|
||||
case Token_Mul: ssa_fprintf(f, "mul"); break;
|
||||
case Token_Not: ssa_fprintf(f, "xor"); break;
|
||||
|
||||
case Token_AndNot: GB_PANIC("Token_AndNot Should never be called");
|
||||
|
||||
@@ -655,15 +681,16 @@ void ssa_print_llvm_ir(gbFile *f, ssaModule *m) {
|
||||
ssa_print_encoded_local(f, make_string(".string"));
|
||||
ssa_fprintf(f, " = type {i8*, ");
|
||||
ssa_print_type(f, m->sizes, t_int);
|
||||
ssa_fprintf(f, "} ; Basic_string\n\n");
|
||||
ssa_fprintf(f, "} ; Basic_string\n");
|
||||
|
||||
ssa_print_encoded_local(f, make_string(".rawptr"));
|
||||
ssa_fprintf(f, " = type i8* ; Basic_rawptr\n\n");
|
||||
|
||||
ssa_fprintf(f, "declare void @llvm.memmove.p0i8.p0i8.");
|
||||
ssa_print_type(f, m->sizes, t_int);
|
||||
ssa_fprintf(f, "(i8*, i8*, ");
|
||||
ssa_print_type(f, m->sizes, t_int);
|
||||
ssa_fprintf(f, ", i32, i1)\n\n");
|
||||
ssa_fprintf(f, ", i32, i1) argmemonly nounwind \n\n");
|
||||
|
||||
gb_for_array(i, m->nested_type_names) {
|
||||
ssaValue *v = m->nested_type_names[i];
|
||||
|
||||
@@ -670,7 +670,7 @@ ssaValue *ssa_make_value_block(ssaProcedure *proc, AstNode *node, Scope *scope,
|
||||
b32 ssa_is_blank_ident(AstNode *node) {
|
||||
if (node->kind == AstNode_Ident) {
|
||||
ast_node(i, Ident, node);
|
||||
return are_strings_equal(i->token.string, make_string("_"));
|
||||
return is_blank_ident(i->token.string);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1390,6 +1390,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
ssaValue *right = ssa_build_expr(proc, ue->expr);
|
||||
return ssa_emit_arith(proc, ue->op, left, right, tv->type);
|
||||
} break;
|
||||
case Token_Not: // Boolean not
|
||||
case Token_Xor: { // Bitwise not
|
||||
// NOTE(bill): "not" `x` == `x` "xor" `-1`
|
||||
ExactValue neg_one = make_exact_value_integer(-1);
|
||||
@@ -1397,10 +1398,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
ssaValue *right = ssa_make_value_constant(proc->module->allocator, tv->type, neg_one);
|
||||
return ssa_emit_arith(proc, ue->op, left, right, tv->type);
|
||||
} break;
|
||||
case Token_Not: // Boolean not
|
||||
GB_PANIC("Token_Not");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
case_end;
|
||||
|
||||
@@ -2057,7 +2054,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
String name = make_string(name_text, name_len-1);
|
||||
|
||||
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(pd->name));
|
||||
GB_ASSERT(found != NULL);
|
||||
GB_ASSERT_MSG(found != NULL, "Unable to find: %.*s", LIT(pd->name->Ident.token.string));
|
||||
Entity *e = *found;
|
||||
ssaValue *value = ssa_make_value_procedure(proc->module->allocator,
|
||||
proc->module, e->type, pd->type, pd->body, name);
|
||||
|
||||
@@ -6,18 +6,41 @@
|
||||
|
||||
// Hasing
|
||||
|
||||
gb_inline u64 hashing_proc(void const *data, isize len) {
|
||||
return gb_murmur64(data, len);
|
||||
struct HashKey {
|
||||
u64 key;
|
||||
b32 is_string;
|
||||
String string; // if String, s.len > 0
|
||||
};
|
||||
|
||||
gb_inline HashKey hashing_proc(void const *data, isize len) {
|
||||
HashKey h = {};
|
||||
h.key = gb_murmur64(data, len);
|
||||
// h.key = gb_fnv64a(data, len);
|
||||
return h;
|
||||
}
|
||||
|
||||
gb_inline u64 hash_string(String s) {
|
||||
return hashing_proc(s.text, s.len);
|
||||
gb_inline HashKey hash_string(String s) {
|
||||
HashKey h = hashing_proc(s.text, s.len);
|
||||
h.is_string = true;
|
||||
h.string = s;
|
||||
return h;
|
||||
}
|
||||
|
||||
gb_inline u64 hash_pointer(void *ptr) {
|
||||
uintptr u = cast(uintptr)ptr;
|
||||
u64 p = cast(u64)u;
|
||||
return p;
|
||||
gb_inline HashKey hash_pointer(void *ptr) {
|
||||
uintptr p = cast(uintptr)ptr;
|
||||
HashKey h = {cast(u64)p};
|
||||
return h;
|
||||
}
|
||||
|
||||
b32 hash_key_equal(HashKey a, HashKey b) {
|
||||
if (a.key == b.key) {
|
||||
if (a.is_string) {
|
||||
if (b.is_string) return are_strings_equal(a.string, b.string);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
i64 next_pow2(i64 n) {
|
||||
@@ -58,17 +81,17 @@ i64 next_pow2(i64 n) {
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
typedef struct MapFindResult {
|
||||
struct MapFindResult {
|
||||
isize hash_index;
|
||||
isize entry_prev;
|
||||
isize entry_index;
|
||||
} MapFindResult;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MapEntry {
|
||||
u64 key;
|
||||
isize next;
|
||||
T value;
|
||||
HashKey key;
|
||||
isize next;
|
||||
T value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -79,9 +102,9 @@ struct Map {
|
||||
|
||||
template <typename T> void map_init (Map<T> *h, gbAllocator a);
|
||||
template <typename T> void map_destroy(Map<T> *h);
|
||||
template <typename T> T * map_get (Map<T> *h, u64 key);
|
||||
template <typename T> void map_set (Map<T> *h, u64 key, T value);
|
||||
template <typename T> void map_remove (Map<T> *h, u64 key);
|
||||
template <typename T> T * map_get (Map<T> *h, HashKey key);
|
||||
template <typename T> void map_set (Map<T> *h, HashKey key, T value);
|
||||
template <typename T> void map_remove (Map<T> *h, HashKey key);
|
||||
template <typename T> void map_clear (Map<T> *h);
|
||||
template <typename T> void map_grow (Map<T> *h);
|
||||
template <typename T> void map_rehash (Map<T> *h, isize new_count);
|
||||
@@ -101,7 +124,7 @@ gb_inline void map_destroy(Map<T> *h) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
gb_internal isize map__add_entry(Map<T> *h, u64 key) {
|
||||
gb_internal isize map__add_entry(Map<T> *h, HashKey key) {
|
||||
MapEntry<T> e = {0};
|
||||
e.key = key;
|
||||
e.next = -1;
|
||||
@@ -110,14 +133,15 @@ gb_internal isize map__add_entry(Map<T> *h, u64 key) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
gb_internal MapFindResult map__find(Map<T> *h, u64 key) {
|
||||
gb_internal MapFindResult map__find(Map<T> *h, HashKey key) {
|
||||
MapFindResult fr = {-1, -1, -1};
|
||||
if (gb_array_count(h->hashes) > 0) {
|
||||
fr.hash_index = key % gb_array_count(h->hashes);
|
||||
fr.hash_index = key.key % gb_array_count(h->hashes);
|
||||
fr.entry_index = h->hashes[fr.hash_index];
|
||||
while (fr.entry_index >= 0) {
|
||||
if (h->entries[fr.entry_index].key == key)
|
||||
if (hash_key_equal(h->entries[fr.entry_index].key, key)) {
|
||||
return fr;
|
||||
}
|
||||
fr.entry_prev = fr.entry_index;
|
||||
fr.entry_index = h->entries[fr.entry_index].next;
|
||||
}
|
||||
@@ -166,7 +190,7 @@ void map_rehash(Map<T> *h, isize new_count) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
gb_inline T *map_get(Map<T> *h, u64 key) {
|
||||
gb_inline T *map_get(Map<T> *h, HashKey key) {
|
||||
isize index = map__find(h, key).entry_index;
|
||||
if (index >= 0)
|
||||
return &h->entries[index].value;
|
||||
@@ -174,7 +198,7 @@ gb_inline T *map_get(Map<T> *h, u64 key) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void map_set(Map<T> *h, u64 key, T value) {
|
||||
void map_set(Map<T> *h, HashKey key, T value) {
|
||||
isize index;
|
||||
MapFindResult fr;
|
||||
if (gb_array_count(h->hashes) == 0)
|
||||
@@ -197,7 +221,7 @@ void map_set(Map<T> *h, u64 key, T value) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void map_remove(Map<T> *h, u64 key) {
|
||||
void map_remove(Map<T> *h, HashKey key) {
|
||||
MapFindResult fr = map__find(h, key);
|
||||
if (fr.entry_index >= 0) {
|
||||
if (fr.entry_prev < 0) {
|
||||
|
||||
100
src/parser.cpp
100
src/parser.cpp
@@ -59,8 +59,8 @@ struct AstScope {
|
||||
struct Parser {
|
||||
String init_fullpath;
|
||||
gbArray(AstFile) files;
|
||||
gbArray(String) imports;
|
||||
isize import_index;
|
||||
gbArray(String) loads;
|
||||
isize load_index;
|
||||
isize total_token_count;
|
||||
};
|
||||
|
||||
@@ -177,7 +177,7 @@ AST_NODE_KIND(_DeclBegin, struct{}) \
|
||||
}) \
|
||||
AST_NODE_KIND(TypeDecl, struct { Token token; AstNode *name, *type; }) \
|
||||
AST_NODE_KIND(AliasDecl, struct { Token token; AstNode *name, *type; }) \
|
||||
AST_NODE_KIND(ImportDecl, struct { Token token, filepath; }) \
|
||||
AST_NODE_KIND(LoadDecl, struct { Token token, filepath; }) \
|
||||
AST_NODE_KIND(_DeclEnd, struct{}) \
|
||||
AST_NODE_KIND(_TypeBegin, struct{}) \
|
||||
AST_NODE_KIND(Field, struct { \
|
||||
@@ -337,8 +337,8 @@ Token ast_node_token(AstNode *node) {
|
||||
return node->TypeDecl.token;
|
||||
case AstNode_AliasDecl:
|
||||
return node->AliasDecl.token;
|
||||
case AstNode_ImportDecl:
|
||||
return node->ImportDecl.token;
|
||||
case AstNode_LoadDecl:
|
||||
return node->LoadDecl.token;
|
||||
case AstNode_Field: {
|
||||
if (node->Field.name_list)
|
||||
return ast_node_token(node->Field.name_list);
|
||||
@@ -394,7 +394,7 @@ AstEntity *make_ast_entity(AstFile *f, Token token, AstNode *decl, AstScope *par
|
||||
return entity;
|
||||
}
|
||||
|
||||
u64 hash_token(Token t) {
|
||||
HashKey hash_token(Token t) {
|
||||
return hash_string(t.string);
|
||||
}
|
||||
|
||||
@@ -766,10 +766,10 @@ gb_inline AstNode *make_alias_decl(AstFile *f, Token token, AstNode *name, AstNo
|
||||
}
|
||||
|
||||
|
||||
gb_inline AstNode *make_import_decl(AstFile *f, Token token, Token filepath) {
|
||||
AstNode *result = make_node(f, AstNode_ImportDecl);
|
||||
result->ImportDecl.token = token;
|
||||
result->ImportDecl.filepath = filepath;
|
||||
gb_inline AstNode *make_load_decl(AstFile *f, Token token, Token filepath) {
|
||||
AstNode *result = make_node(f, AstNode_LoadDecl);
|
||||
result->LoadDecl.token = token;
|
||||
result->LoadDecl.filepath = filepath;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -825,6 +825,13 @@ gb_inline b32 allow_token(AstFile *f, TokenKind kind) {
|
||||
}
|
||||
|
||||
|
||||
b32 is_blank_ident(String str) {
|
||||
if (str.len == 1) {
|
||||
return str.text[0] == '_';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
gb_internal void add_ast_entity(AstFile *f, AstScope *scope, AstNode *declaration, AstNode *name_list) {
|
||||
for (AstNode *n = name_list; n != NULL; n = n->next) {
|
||||
if (n->kind != AstNode_Ident) {
|
||||
@@ -836,8 +843,7 @@ gb_internal void add_ast_entity(AstFile *f, AstScope *scope, AstNode *declaratio
|
||||
n->Ident.entity = entity;
|
||||
|
||||
AstEntity *insert_entity = ast_scope_insert(scope, *entity);
|
||||
if (insert_entity != NULL &&
|
||||
!are_strings_equal(insert_entity->token.string, make_string("_"))) {
|
||||
if (insert_entity != NULL && !is_blank_ident(insert_entity->token.string)) {
|
||||
ast_file_err(f, entity->token,
|
||||
"There is already a previous declaration of `%.*s` in the current scope at\n"
|
||||
"\t%.*s(%td:%td)",
|
||||
@@ -845,6 +851,10 @@ gb_internal void add_ast_entity(AstFile *f, AstScope *scope, AstNode *declaratio
|
||||
LIT(insert_entity->token.pos.file),
|
||||
insert_entity->token.pos.line,
|
||||
insert_entity->token.pos.column);
|
||||
|
||||
gb_printf_err("Hashes\n");
|
||||
gb_printf_err("%16llx - %.*s\n", hash_string(insert_entity->token.string), LIT(insert_entity->token.string));
|
||||
gb_printf_err("%16llx - %.*s\n\n", hash_string(entity->token.string), LIT(entity->token.string));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1898,16 +1908,6 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
return alias_decl;
|
||||
} break;
|
||||
|
||||
case Token_import: {
|
||||
Token token = expect_token(f, Token_import);
|
||||
Token filepath = expect_token(f, Token_String);
|
||||
if (f->curr_scope == f->file_scope) {
|
||||
return make_import_decl(f, token, filepath);
|
||||
}
|
||||
ast_file_err(f, token, "You cannot `import` within a procedure. This must be done at the file scope.");
|
||||
return make_bad_decl(f, token, filepath);
|
||||
} break;
|
||||
|
||||
// Operands
|
||||
case Token_Identifier:
|
||||
case Token_Integer:
|
||||
@@ -1944,10 +1944,20 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
expect_token(f, Token_Semicolon);
|
||||
return make_branch_stmt(f, token);
|
||||
|
||||
case Token_Hash:
|
||||
case Token_Hash: {
|
||||
s = parse_tag_stmt(f, NULL);
|
||||
|
||||
if (are_strings_equal(s->TagStmt.name.string, make_string("load"))) {
|
||||
Token file_path = expect_token(f, Token_String);
|
||||
if (f->curr_scope == f->file_scope) {
|
||||
return make_load_decl(f, s->TagStmt.token, file_path);
|
||||
}
|
||||
ast_file_err(f, token, "You cannot `load` within a procedure. This must be done at the file scope.");
|
||||
return make_bad_decl(f, token, file_path);
|
||||
}
|
||||
s->TagStmt.stmt = parse_stmt(f); // TODO(bill): Find out why this doesn't work as an argument
|
||||
return s;
|
||||
} break;
|
||||
|
||||
case Token_OpenBrace: return parse_block_stmt(f);
|
||||
|
||||
@@ -2036,7 +2046,7 @@ void destroy_ast_file(AstFile *f) {
|
||||
|
||||
b32 init_parser(Parser *p) {
|
||||
gb_array_init(p->files, gb_heap_allocator());
|
||||
gb_array_init(p->imports, gb_heap_allocator());
|
||||
gb_array_init(p->loads, gb_heap_allocator());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2046,24 +2056,24 @@ void destroy_parser(Parser *p) {
|
||||
destroy_ast_file(&p->files[i]);
|
||||
}
|
||||
#if 1
|
||||
gb_for_array(i, p->imports) {
|
||||
// gb_free(gb_heap_allocator(), p->imports[i].text);
|
||||
gb_for_array(i, p->loads) {
|
||||
// gb_free(gb_heap_allocator(), p->loads[i].text);
|
||||
}
|
||||
#endif
|
||||
gb_array_free(p->files);
|
||||
gb_array_free(p->imports);
|
||||
gb_array_free(p->loads);
|
||||
}
|
||||
|
||||
// NOTE(bill): Returns true if it's added
|
||||
b32 try_add_import_path(Parser *p, String import_file) {
|
||||
gb_for_array(i, p->imports) {
|
||||
String import = p->imports[i];
|
||||
b32 try_add_load_path(Parser *p, String import_file) {
|
||||
gb_for_array(i, p->loads) {
|
||||
String import = p->loads[i];
|
||||
if (are_strings_equal(import, import_file)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
gb_array_append(p->imports, import_file);
|
||||
gb_array_append(p->loads, import_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2076,7 +2086,7 @@ gb_global Rune illegal_import_runes[] = {
|
||||
'|', ',', '<', '>', '?',
|
||||
};
|
||||
|
||||
b32 is_import_path_valid(String path) {
|
||||
b32 is_load_path_valid(String path) {
|
||||
if (path.len > 0) {
|
||||
u8 *start = path.text;
|
||||
u8 *end = path.text + path.len;
|
||||
@@ -2125,37 +2135,29 @@ void parse_file(Parser *p, AstFile *f) {
|
||||
// NOTE(bill): Sanity check
|
||||
ast_file_err(f, ast_node_token(node), "Only declarations are allowed at file scope");
|
||||
} else {
|
||||
if (node->kind == AstNode_ImportDecl) {
|
||||
auto *id = &node->ImportDecl;
|
||||
if (node->kind == AstNode_LoadDecl) {
|
||||
auto *id = &node->LoadDecl;
|
||||
String file_str = id->filepath.string;
|
||||
|
||||
char ext[] = ".odin";
|
||||
isize ext_len = gb_size_of(ext)-1;
|
||||
b32 append_ext = false;
|
||||
|
||||
if (!is_import_path_valid(file_str)) {
|
||||
if (!is_load_path_valid(file_str)) {
|
||||
ast_file_err(f, ast_node_token(node), "Invalid import path");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (string_extension_position(file_str) < 0)
|
||||
append_ext = true;
|
||||
|
||||
isize str_len = base_dir.len+file_str.len;
|
||||
if (append_ext)
|
||||
str_len += ext_len;
|
||||
u8 *str = gb_alloc_array(gb_heap_allocator(), u8, str_len+1);
|
||||
defer (gb_free(gb_heap_allocator(), str));
|
||||
|
||||
gb_memcopy(str, base_dir.text, base_dir.len);
|
||||
gb_memcopy(str+base_dir.len, file_str.text, file_str.len);
|
||||
if (append_ext)
|
||||
gb_memcopy(str+base_dir.len+file_str.len, ext, ext_len+1);
|
||||
str[str_len] = '\0';
|
||||
char *path_str = gb_path_get_full_name(gb_heap_allocator(), cast(char *)str);
|
||||
String import_file = make_string(path_str);
|
||||
|
||||
if (!try_add_import_path(p, import_file)) {
|
||||
gb_printf_err("load path: %.*s\n", LIT(import_file));
|
||||
|
||||
if (!try_add_load_path(p, import_file)) {
|
||||
gb_free(gb_heap_allocator(), import_file.text);
|
||||
}
|
||||
}
|
||||
@@ -2167,11 +2169,11 @@ void parse_file(Parser *p, AstFile *f) {
|
||||
ParseFileError parse_files(Parser *p, char *init_filename) {
|
||||
char *fullpath_str = gb_path_get_full_name(gb_heap_allocator(), init_filename);
|
||||
String init_fullpath = make_string(fullpath_str);
|
||||
gb_array_append(p->imports, init_fullpath);
|
||||
gb_array_append(p->loads, init_fullpath);
|
||||
p->init_fullpath = init_fullpath;
|
||||
|
||||
gb_for_array(i, p->imports) {
|
||||
String import_path = p->imports[i];
|
||||
gb_for_array(i, p->loads) {
|
||||
String import_path = p->loads[i];
|
||||
AstFile file = {};
|
||||
ParseFileError err = init_ast_file(&file, import_path);
|
||||
if (err != ParseFile_None) {
|
||||
|
||||
@@ -25,7 +25,12 @@ gb_inline String make_string(char *text) {
|
||||
|
||||
gb_inline b32 are_strings_equal(String a, String b) {
|
||||
if (a.len == b.len) {
|
||||
return gb_memcompare(a.text, b.text, a.len) == 0;
|
||||
for (isize i = 0; i < a.len; i++) {
|
||||
if (a.text[i] != b.text[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -117,7 +117,6 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
||||
TOKEN_KIND(Token_for, "for"), \
|
||||
TOKEN_KIND(Token_defer, "defer"), \
|
||||
TOKEN_KIND(Token_return, "return"), \
|
||||
TOKEN_KIND(Token_import, "import"), \
|
||||
TOKEN_KIND(Token_struct, "struct"), \
|
||||
TOKEN_KIND(Token_union, "union"), \
|
||||
TOKEN_KIND(Token_enum, "enum"), \
|
||||
|
||||
Reference in New Issue
Block a user