diff --git a/build.bat b/build.bat index 8feef3028..d336e0911 100644 --- a/build.bat +++ b/build.bat @@ -47,6 +47,7 @@ pushd %build_dir% /link %linker_settings% -OUT:%exe_name% ^ && call ..\run.bat + :do_not_compile_exe popd :end_of_build diff --git a/examples/basic.odin b/examples/basic.odin index 60a13cce2..8177ca4da 100644 --- a/examples/basic.odin +++ b/examples/basic.odin @@ -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; } diff --git a/examples/main.ll b/examples/main.ll index 4dae460be..7c1ecad8f 100644 --- a/examples/main.ll +++ b/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" diff --git a/examples/main.odin b/examples/main.odin index 1e4274491..de746733a 100644 --- a/examples/main.odin +++ b/examples/main.odin @@ -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"); // } -*/ diff --git a/run.bat b/run.bat index 696a902cf..55767d498 100644 --- a/run.bat +++ b/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 diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index 5eb28eba1..4b2ba78fc 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -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)) { diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index bdae13257..204d27819 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -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; diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index 0c36ca8f3..43957ba76 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -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; diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index 5f2160182..1c0ab89a1 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -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]; diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index f20100a8b..1ccbcf5d6 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -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); diff --git a/src/common.cpp b/src/common.cpp index 02d4f4866..9279c1772 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -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 struct MapEntry { - u64 key; - isize next; - T value; + HashKey key; + isize next; + T value; }; template @@ -79,9 +102,9 @@ struct Map { template void map_init (Map *h, gbAllocator a); template void map_destroy(Map *h); -template T * map_get (Map *h, u64 key); -template void map_set (Map *h, u64 key, T value); -template void map_remove (Map *h, u64 key); +template T * map_get (Map *h, HashKey key); +template void map_set (Map *h, HashKey key, T value); +template void map_remove (Map *h, HashKey key); template void map_clear (Map *h); template void map_grow (Map *h); template void map_rehash (Map *h, isize new_count); @@ -101,7 +124,7 @@ gb_inline void map_destroy(Map *h) { } template -gb_internal isize map__add_entry(Map *h, u64 key) { +gb_internal isize map__add_entry(Map *h, HashKey key) { MapEntry e = {0}; e.key = key; e.next = -1; @@ -110,14 +133,15 @@ gb_internal isize map__add_entry(Map *h, u64 key) { } template -gb_internal MapFindResult map__find(Map *h, u64 key) { +gb_internal MapFindResult map__find(Map *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 *h, isize new_count) { } template -gb_inline T *map_get(Map *h, u64 key) { +gb_inline T *map_get(Map *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 *h, u64 key) { } template -void map_set(Map *h, u64 key, T value) { +void map_set(Map *h, HashKey key, T value) { isize index; MapFindResult fr; if (gb_array_count(h->hashes) == 0) @@ -197,7 +221,7 @@ void map_set(Map *h, u64 key, T value) { } template -void map_remove(Map *h, u64 key) { +void map_remove(Map *h, HashKey key) { MapFindResult fr = map__find(h, key); if (fr.entry_index >= 0) { if (fr.entry_prev < 0) { diff --git a/src/parser.cpp b/src/parser.cpp index 328220cfa..baa2caccd 100644 --- a/src/parser.cpp +++ b/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) { diff --git a/src/string.cpp b/src/string.cpp index 1581feab9..d46700630 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -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; } diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 848dd7ab6..ee8fa7ef5 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -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"), \