diff --git a/examples/basic.odin b/examples/basic.odin index 1f90efa22..63d30d602 100644 --- a/examples/basic.odin +++ b/examples/basic.odin @@ -1,23 +1,23 @@ -putchar :: proc(c : i32) -> i32 #foreign +putchar :: proc(c: i32) -> i32 #foreign -print_string :: proc(s : string) { +print_string :: proc(s: string) { for i := 0; i < len(s); i++ { c := cast(i32)s[i]; putchar(c); } } -string_byte_reverse :: proc(s : string) { +string_byte_reverse :: proc(s: string) { n := len(s); for i := 0; i < n/2; i++ { s[i], s[n-1-i] = s[n-1-i], s[i]; } } -print_int :: proc(i : int, base : int) { - NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"; +print_int :: proc(i, base: int) { + NUM_TO_CHAR_TABLE :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"; - buf : [21]byte; + buf: [21]u8; len := 0; negative := false; if i < 0 { @@ -26,7 +26,7 @@ print_int :: proc(i : int, base : int) { } if i > 0 { for i > 0 { - c : byte = NUM_TO_CHAR_TABLE[i % base]; + c : u8 = NUM_TO_CHAR_TABLE[i % base]; buf[len] = c; len++; i /= base; diff --git a/examples/main.ll b/examples/main.ll index 2de35bd44..9b6ed5d16 100644 --- a/examples/main.ll +++ b/examples/main.ll @@ -4,16 +4,132 @@ define void @main() { "entry - 0": - call void @print_int(i64 123, i64 10) - %0 = getelementptr inbounds [1 x i8], [1 x i8]* @.str0, i64 0, i64 0 - %1 = alloca %-string, align 8 - store %-string zeroinitializer, %-string* %1 - %2 = getelementptr inbounds %-string, %-string* %1, i64 0, i32 0 - %3 = getelementptr inbounds %-string, %-string* %1, i64 0, i32 1 - store i8* %0, i8** %2 - store i64 1, i64* %3 - %4 = load %-string, %-string* %1 - call void @print_string(%-string %4) + %0 = alloca i64, align 8 ; a + store i64 zeroinitializer, i64* %0 + %1 = getelementptr inbounds [6 x i8], [6 x i8]* @.str0, i64 0, i64 0 + %2 = getelementptr i8, i8* %1, i64 1 + %3 = load i8, i8* %2 + %4 = zext i8 %3 to i64 + store i64 %4, i64* %0 + %5 = load i64, i64* %0 + call void @print_int(i64 %5, i64 10) + %6 = getelementptr inbounds [1 x i8], [1 x i8]* @.str1, i64 0, i64 0 + %7 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %7 + %8 = getelementptr inbounds %-string, %-string* %7, i64 0, i32 0 + %9 = getelementptr inbounds %-string, %-string* %7, i64 0, i32 1 + store i8* %6, i8** %8 + store i64 1, i64* %9 + %10 = load %-string, %-string* %7 + call void @print_string(%-string %10) + %11 = getelementptr inbounds [23 x i8], [23 x i8]* @.str2, i64 0, i64 0 + %12 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %12 + %13 = getelementptr inbounds %-string, %-string* %12, i64 0, i32 0 + %14 = getelementptr inbounds %-string, %-string* %12, i64 0, i32 1 + store i8* %11, i8** %13 + store i64 23, i64* %14 + %15 = load %-string, %-string* %12 + call void @print_string(%-string %15) + %16 = getelementptr inbounds [21 x i8], [21 x i8]* @.str3, i64 0, i64 0 + %17 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %17 + %18 = getelementptr inbounds %-string, %-string* %17, i64 0, i32 0 + %19 = getelementptr inbounds %-string, %-string* %17, i64 0, i32 1 + store i8* %16, i8** %18 + store i64 21, i64* %19 + %20 = load %-string, %-string* %17 + call void @print_string(%-string %20) + %21 = getelementptr inbounds [22 x i8], [22 x i8]* @.str4, i64 0, i64 0 + %22 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %22 + %23 = getelementptr inbounds %-string, %-string* %22, i64 0, i32 0 + %24 = getelementptr inbounds %-string, %-string* %22, i64 0, i32 1 + store i8* %21, i8** %23 + store i64 22, i64* %24 + %25 = load %-string, %-string* %22 + call void @print_string(%-string %25) + %26 = getelementptr inbounds [23 x i8], [23 x i8]* @.str5, i64 0, i64 0 + %27 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %27 + %28 = getelementptr inbounds %-string, %-string* %27, i64 0, i32 0 + %29 = getelementptr inbounds %-string, %-string* %27, i64 0, i32 1 + store i8* %26, i8** %28 + store i64 23, i64* %29 + %30 = load %-string, %-string* %27 + call void @print_string(%-string %30) + %31 = getelementptr inbounds [20 x i8], [20 x i8]* @.str6, i64 0, i64 0 + %32 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %32 + %33 = getelementptr inbounds %-string, %-string* %32, i64 0, i32 0 + %34 = getelementptr inbounds %-string, %-string* %32, i64 0, i32 1 + store i8* %31, i8** %33 + store i64 20, i64* %34 + %35 = load %-string, %-string* %32 + call void @print_string(%-string %35) + %36 = getelementptr inbounds [37 x i8], [37 x i8]* @.str7, i64 0, i64 0 + %37 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %37 + %38 = getelementptr inbounds %-string, %-string* %37, i64 0, i32 0 + %39 = getelementptr inbounds %-string, %-string* %37, i64 0, i32 1 + store i8* %36, i8** %38 + store i64 37, i64* %39 + %40 = load %-string, %-string* %37 + call void @print_string(%-string %40) + %41 = getelementptr inbounds [21 x i8], [21 x i8]* @.str8, i64 0, i64 0 + %42 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %42 + %43 = getelementptr inbounds %-string, %-string* %42, i64 0, i32 0 + %44 = getelementptr inbounds %-string, %-string* %42, i64 0, i32 1 + store i8* %41, i8** %43 + store i64 21, i64* %44 + %45 = load %-string, %-string* %42 + call void @print_string(%-string %45) + %46 = getelementptr inbounds [33 x i8], [33 x i8]* @.str9, i64 0, i64 0 + %47 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %47 + %48 = getelementptr inbounds %-string, %-string* %47, i64 0, i32 0 + %49 = getelementptr inbounds %-string, %-string* %47, i64 0, i32 1 + store i8* %46, i8** %48 + store i64 33, i64* %49 + %50 = load %-string, %-string* %47 + call void @print_string(%-string %50) + %51 = getelementptr inbounds [29 x i8], [29 x i8]* @.stra, i64 0, i64 0 + %52 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %52 + %53 = getelementptr inbounds %-string, %-string* %52, i64 0, i32 0 + %54 = getelementptr inbounds %-string, %-string* %52, i64 0, i32 1 + store i8* %51, i8** %53 + store i64 29, i64* %54 + %55 = load %-string, %-string* %52 + call void @print_string(%-string %55) + %56 = getelementptr inbounds [24 x i8], [24 x i8]* @.strb, i64 0, i64 0 + %57 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %57 + %58 = getelementptr inbounds %-string, %-string* %57, i64 0, i32 0 + %59 = getelementptr inbounds %-string, %-string* %57, i64 0, i32 1 + store i8* %56, i8** %58 + store i64 24, i64* %59 + %60 = load %-string, %-string* %57 + call void @print_string(%-string %60) + %61 = getelementptr inbounds [42 x i8], [42 x i8]* @.strc, i64 0, i64 0 + %62 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %62 + %63 = getelementptr inbounds %-string, %-string* %62, i64 0, i32 0 + %64 = getelementptr inbounds %-string, %-string* %62, i64 0, i32 1 + store i8* %61, i8** %63 + store i64 42, i64* %64 + %65 = load %-string, %-string* %62 + call void @print_string(%-string %65) + %66 = getelementptr inbounds [21 x i8], [21 x i8]* @.strd, i64 0, i64 0 + %67 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %67 + %68 = getelementptr inbounds %-string, %-string* %67, i64 0, i32 0 + %69 = getelementptr inbounds %-string, %-string* %67, i64 0, i32 1 + store i8* %66, i8** %68 + store i64 21, i64* %69 + %70 = load %-string, %-string* %67 + call void @print_string(%-string %70) ret void } @@ -32,10 +148,10 @@ define void @print_string(%-string %s) { "for.body - 1": %2 = alloca i32, align 4 ; c store i32 zeroinitializer, i32* %2 - %3 = load i64, i64* %1 - %4 = getelementptr inbounds %-string, %-string* %0, i64 0, i32 0 - %5 = load i8*, i8** %4 - %6 = getelementptr i8, i8* %5, i64 %3 + %3 = getelementptr inbounds %-string, %-string* %0, i64 0, i32 0 + %4 = load i8*, i8** %3 + %5 = load i64, i64* %1 + %6 = getelementptr i8, i8* %4, i64 %5 %7 = load i8, i8* %6 %8 = zext i8 %7 to i32 store i32 %8, i32* %2 @@ -76,29 +192,29 @@ define void @string_byte_reverse(%-string %s) { br label %"for.loop - 2" "for.body - 1": - %5 = load i64, i64* %4 - %6 = getelementptr inbounds %-string, %-string* %0, i64 0, i32 0 - %7 = load i8*, i8** %6 - %8 = getelementptr i8, i8* %7, i64 %5 - %9 = load i64, i64* %4 - %10 = load i64, i64* %1 - %11 = sub i64 %10, 1 - %12 = sub i64 %11, %9 - %13 = getelementptr inbounds %-string, %-string* %0, i64 0, i32 0 - %14 = load i8*, i8** %13 - %15 = getelementptr i8, i8* %14, i64 %12 - %16 = load i64, i64* %4 - %17 = load i64, i64* %1 - %18 = sub i64 %17, 1 - %19 = sub i64 %18, %16 - %20 = getelementptr inbounds %-string, %-string* %0, i64 0, i32 0 - %21 = load i8*, i8** %20 - %22 = getelementptr i8, i8* %21, i64 %19 + %5 = getelementptr inbounds %-string, %-string* %0, i64 0, i32 0 + %6 = load i8*, i8** %5 + %7 = load i64, i64* %4 + %8 = getelementptr i8, i8* %6, i64 %7 + %9 = getelementptr inbounds %-string, %-string* %0, i64 0, i32 0 + %10 = load i8*, i8** %9 + %11 = load i64, i64* %4 + %12 = load i64, i64* %1 + %13 = sub i64 %12, 1 + %14 = sub i64 %13, %11 + %15 = getelementptr i8, i8* %10, i64 %14 + %16 = getelementptr inbounds %-string, %-string* %0, i64 0, i32 0 + %17 = load i8*, i8** %16 + %18 = load i64, i64* %4 + %19 = load i64, i64* %1 + %20 = sub i64 %19, 1 + %21 = sub i64 %20, %18 + %22 = getelementptr i8, i8* %17, i64 %21 %23 = load i8, i8* %22 - %24 = load i64, i64* %4 - %25 = getelementptr inbounds %-string, %-string* %0, i64 0, i32 0 - %26 = load i8*, i8** %25 - %27 = getelementptr i8, i8* %26, i64 %24 + %24 = getelementptr inbounds %-string, %-string* %0, i64 0, i32 0 + %25 = load i8*, i8** %24 + %26 = load i64, i64* %4 + %27 = getelementptr i8, i8* %25, i64 %26 %28 = load i8, i8* %27 store i8 %23, i8* %8 store i8 %28, i8* %15 @@ -129,139 +245,140 @@ define void @print_int(i64 %i, i64 %base) { %1 = alloca i64, align 8 ; base store i64 zeroinitializer, i64* %1 store i64 %base, i64* %1 - %2 = alloca %-string, align 8 ; NUM_TO_CHAR_TABLE - store %-string zeroinitializer, %-string* %2 - %3 = getelementptr inbounds [64 x i8], [64 x i8]* @.str1, i64 0, i64 0 - %4 = alloca %-string, align 8 - store %-string zeroinitializer, %-string* %4 - %5 = getelementptr inbounds %-string, %-string* %4, i64 0, i32 0 - %6 = getelementptr inbounds %-string, %-string* %4, i64 0, i32 1 - store i8* %3, i8** %5 - store i64 64, i64* %6 - %7 = load %-string, %-string* %4 - store %-string %7, %-string* %2 - %8 = alloca [21 x i8], align 1 ; buf - store [21 x i8] zeroinitializer, [21 x i8]* %8 - %9 = alloca i64, align 8 ; len - store i64 zeroinitializer, i64* %9 - store i64 0, i64* %9 - %10 = alloca i1, align 1 ; negative - store i1 zeroinitializer, i1* %10 - store i1 false, i1* %10 - %11 = load i64, i64* %0 - %12 = icmp slt i64 %11, 0 - br i1 %12, label %"if.then - 1", label %"if.done - 2" + %2 = alloca [21 x i8], align 1 ; buf + store [21 x i8] zeroinitializer, [21 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 + %6 = icmp slt i64 %5, 0 + br i1 %6, label %"if.then - 1", label %"if.done - 2" "if.then - 1": - store i1 true, i1* %10 - %13 = load i64, i64* %0 - %14 = sub i64 0, %13 - store i64 %14, i64* %0 + store i1 true, i1* %4 + %7 = load i64, i64* %0 + %8 = sub i64 0, %7 + store i64 %8, i64* %0 br label %"if.done - 2" "if.done - 2": - %15 = load i64, i64* %0 - %16 = icmp sgt i64 %15, 0 - br i1 %16, label %"if.then - 3", label %"if.else - 4" + %9 = load i64, i64* %0 + %10 = icmp sgt i64 %9, 0 + br i1 %10, label %"if.then - 3", label %"if.else - 4" "if.then - 3": br label %"for.loop - 6" "if.else - 4": - %17 = load i64, i64* %9 - %18 = getelementptr inbounds [21 x i8], [21 x i8]* %8, i64 0, i64 0 - %19 = getelementptr i8, i8* %18, i64 %17 - store i8 0, i8* %19 - %20 = load i64, i64* %9 - %21 = add i64 %20, 1 - store i64 %21, i64* %9 + %11 = getelementptr inbounds [21 x i8], [21 x i8]* %2, i64 0, i64 0 + %12 = load i64, i64* %3 + %13 = getelementptr i8, i8* %11, i64 %12 + store i8 0, i8* %13 + %14 = load i64, i64* %3 + %15 = add i64 %14, 1 + store i64 %15, i64* %3 br label %"if.done - 8" "for.body - 5": - %22 = alloca i8, align 1 ; c - store i8 zeroinitializer, i8* %22 - %23 = load i64, i64* %1 - %24 = load i64, i64* %0 - %25 = srem i64 %24, %23 - %26 = getelementptr inbounds %-string, %-string* %2, i64 0, i32 0 - %27 = load i8*, i8** %26 - %28 = getelementptr i8, i8* %27, i64 %25 - %29 = load i8, i8* %28 - store i8 %29, i8* %22 - %30 = load i64, i64* %9 - %31 = getelementptr inbounds [21 x i8], [21 x i8]* %8, i64 0, i64 0 - %32 = getelementptr i8, i8* %31, i64 %30 - %33 = load i8, i8* %22 - store i8 %33, i8* %32 - %34 = load i64, i64* %9 - %35 = add i64 %34, 1 - store i64 %35, i64* %9 - %36 = load i64, i64* %1 - %37 = load i64, i64* %0 - %38 = sdiv i64 %37, %36 - store i64 %38, i64* %0 + %16 = alloca i8, align 1 ; c + store i8 zeroinitializer, i8* %16 + %17 = getelementptr inbounds [64 x i8], [64 x i8]* @.stre, i64 0, i64 0 + %18 = load i64, i64* %1 + %19 = load i64, i64* %0 + %20 = srem i64 %19, %18 + %21 = getelementptr i8, i8* %17, i64 %20 + %22 = load i8, i8* %21 + store i8 %22, i8* %16 + %23 = getelementptr inbounds [21 x i8], [21 x i8]* %2, i64 0, i64 0 + %24 = load i64, i64* %3 + %25 = getelementptr i8, i8* %23, i64 %24 + %26 = load i8, i8* %16 + store i8 %26, i8* %25 + %27 = load i64, i64* %3 + %28 = add i64 %27, 1 + store i64 %28, i64* %3 + %29 = load i64, i64* %1 + %30 = load i64, i64* %0 + %31 = sdiv i64 %30, %29 + store i64 %31, i64* %0 br label %"for.loop - 6" "for.loop - 6": - %39 = load i64, i64* %0 - %40 = icmp sgt i64 %39, 0 - br i1 %40, label %"for.body - 5", label %"for.done - 7" + %32 = load i64, i64* %0 + %33 = icmp sgt i64 %32, 0 + br i1 %33, label %"for.body - 5", label %"for.done - 7" "for.done - 7": br label %"if.done - 8" "if.done - 8": - %41 = load i1, i1* %10 - br i1 %41, label %"if.then - 9", label %"if.done - 10" + %34 = load i1, i1* %4 + br i1 %34, label %"if.then - 9", label %"if.done - 10" "if.then - 9": - %42 = load i64, i64* %9 - %43 = getelementptr inbounds [21 x i8], [21 x i8]* %8, i64 0, i64 0 - %44 = getelementptr i8, i8* %43, i64 %42 - store i8 0, i8* %44 - %45 = load i64, i64* %9 - %46 = add i64 %45, 1 - store i64 %46, i64* %9 + %35 = getelementptr inbounds [21 x i8], [21 x i8]* %2, i64 0, i64 0 + %36 = load i64, i64* %3 + %37 = getelementptr i8, i8* %35, i64 %36 + store i8 0, i8* %37 + %38 = load i64, i64* %3 + %39 = add i64 %38, 1 + store i64 %39, i64* %3 br label %"if.done - 10" "if.done - 10": - %47 = alloca %-string, align 8 ; str - store %-string zeroinitializer, %-string* %47 - %48 = load i64, i64* %9 - %49 = sub i64 %48, 0 - %50 = sub i64 21, 0 - %51 = getelementptr inbounds [21 x i8], [21 x i8]* %8, 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 - %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 - %61 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %58, i64 0, i32 1 - %62 = load i64, i64* %61 - %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 - store %-string %66, %-string* %47 - %67 = load %-string, %-string* %47 - call void @string_byte_reverse(%-string %67) - %68 = load %-string, %-string* %47 - call void @print_string(%-string %68) + %40 = alloca %-string, align 8 ; str + store %-string zeroinitializer, %-string* %40 + %41 = load i64, i64* %3 + %42 = sub i64 %41, 0 + %43 = sub i64 21, 0 + %44 = getelementptr inbounds [21 x i8], [21 x i8]* %2, i64 0, i64 0 + %45 = getelementptr i8, i8* %44, i64 0 + %46 = alloca {i8*, i64, i64}, align 8 + store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %46 + %47 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %46, i64 0, i32 0 + store i8* %45, i8** %47 + %48 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %46, i64 0, i32 1 + store i64 %42, i64* %48 + %49 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %46, i64 0, i32 2 + store i64 %43, i64* %49 + %50 = load {i8*, i64, i64}, {i8*, i64, i64}* %46 + %51 = alloca {i8*, i64, i64}, align 8 + store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %51 + store {i8*, i64, i64} %50, {i8*, i64, i64}* %51 + %52 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %51, i64 0, i32 0 + %53 = load i8*, i8** %52 + %54 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %51, i64 0, i32 1 + %55 = load i64, i64* %54 + %56 = alloca %-string, align 8 + store %-string zeroinitializer, %-string* %56 + %57 = getelementptr inbounds %-string, %-string* %56, i64 0, i32 0 + %58 = getelementptr inbounds %-string, %-string* %56, i64 0, i32 1 + store i8* %53, i8** %57 + store i64 %55, i64* %58 + %59 = load %-string, %-string* %56 + store %-string %59, %-string* %40 + %60 = load %-string, %-string* %40 + call void @string_byte_reverse(%-string %60) + %61 = load %-string, %-string* %40 + call void @print_string(%-string %61) ret void } -@.str0 = global [1 x i8] c"\0A" -@.str1 = global [64 x i8] c"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\40$" +@.str0 = global [6 x i8] c"Hello\0A" +@.str1 = global [1 x i8] c"\0A" +@.str2 = global [23 x i8] c"Chinese\20-\20\E4\BD\A0\E5\A5\BD\E4\B8\96\E7\95\8C\0A" +@.str3 = global [21 x i8] c"Dutch\20-\20Hello\20wereld\0A" +@.str4 = global [22 x i8] c"English\20-\20Hello\20world\0A" +@.str5 = global [23 x i8] c"French\20-\20Bonjour\20monde\0A" +@.str6 = global [20 x i8] c"German\20-\20Hallo\20Welt\0A" +@.str7 = global [37 x i8] c"Greek\20-\20\CE\B3\CE\B5\CE\B9\CE\AC\20\CF\83\CE\BF\CF\85\20\CE\BA\CF\8C\CF\83\CE\BC\CE\BF\CF\82\0A" +@.str8 = global [21 x i8] c"Italian\20-\20Ciao\20mondo\0A" +@.str9 = global [33 x i8] c"Japanese\20-\20\E3\81\93\E3\82\93\E3\81\AB\E3\81\A1\E3\81\AF\E4\B8\96\E7\95\8C\0A" +@.stra = global [29 x i8] c"Korean\20-\20\EC\97\AC\EB\B3\B4\EC\84\B8\EC\9A\94\20\EC\84\B8\EA\B3\84\0A" +@.strb = global [24 x i8] c"Portuguese\20-\20Ol\C3\A1\20mundo\0A" +@.strc = global [42 x i8] c"Russian\20-\20\D0\97\D0\B4\D1\80\D0\B0\D0\B2\D1\81\D1\82\D0\B2\D1\83\D0\BB\D1\82\D0\B5\20\D0\BC\D0\B8\D1\80\0A" +@.strd = global [21 x i8] c"Spanish\20-\20Hola\20mundo\0A" +@.stre = global [64 x i8] c"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\40$" diff --git a/examples/main.odin b/examples/main.odin index 303dd9e41..c7b4240ca 100644 --- a/examples/main.odin +++ b/examples/main.odin @@ -1,6 +1,20 @@ import "basic" main :: proc() { - print_int(123, 10); + a := cast(int)"Hello\n"[1]; + print_int(a, 10); print_string("\n"); + + print_string("Chinese - 你好世界\n"); + print_string("Dutch - Hello wereld\n"); + print_string("English - Hello world\n"); + print_string("French - Bonjour monde\n"); + print_string("German - Hallo Welt\n"); + print_string("Greek - γειά σου κόσμος\n"); + print_string("Italian - Ciao mondo\n"); + print_string("Japanese - こんにちは世界\n"); + print_string("Korean - 여보세요 세계\n"); + print_string("Portuguese - Olá mundo\n"); + print_string("Russian - Здравствулте мир\n"); + print_string("Spanish - Hola mundo\n"); } diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index 1d402abe9..5ae2ec417 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -456,8 +456,9 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode } TypeAndValue tv = {}; - tv.type = type; + tv.type = type; tv.value = value; + tv.mode = mode; map_set(&i->types, hash_pointer(expression), tv); } @@ -522,7 +523,8 @@ void pop_procedure(Checker *c) { } void add_curr_ast_file(Checker *c, AstFile *file) { - gb_zero_item(&c->error_collector); + TokenPos zero_pos = {}; + c->error_collector.prev = zero_pos; c->curr_ast_file = file; } @@ -672,10 +674,12 @@ void check_parsed_files(Checker *c) { u64 key = entry->key; AstNode *expr = cast(AstNode *)cast(uintptr)key; ExpressionInfo *info = &entry->value; - if (is_type_typed(info->type)) { - GB_PANIC("%s (type %s) is typed!", expr_to_string(expr), info->type); + if (info != NULL && expr != NULL) { + if (is_type_typed(info->type)) { + GB_PANIC("%s (type %s) is typed!", expr_to_string(expr), info->type); + } + add_type_and_value(&c->info, expr, info->mode, info->type, info->value); } - add_type_and_value(&c->info, expr, info->mode, info->type, info->value); } } diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index fc5020f9b..c413eff39 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -11,6 +11,7 @@ void convert_to_typed (Checker *c, Operand *operand, Type *targ gbString expr_to_string (AstNode *expression); void check_entity_decl (Checker *c, Entity *e, DeclInfo *decl, Type *named_type); void check_proc_body (Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body); +void update_expr_type (Checker *c, AstNode *e, Type *type, b32 final); void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { @@ -664,7 +665,10 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) { y->mode == Addressing_Constant) { x->value = make_exact_value_bool(compare_exact_values(op, x->value, y->value)); } else { - // TODO(bill): What should I do? + x->mode = Addressing_Value; + + update_expr_type(c, x->expr, default_type(x->type), true); + update_expr_type(c, y->expr, default_type(y->type), true); } x->type = t_untyped_bool; @@ -770,33 +774,35 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { } -void update_expr_type(Checker *c, AstNode *e, Type *type) { - ExpressionInfo *found = map_get(&c->info.untyped, hash_pointer(e)); - if (!found) +void update_expr_type(Checker *c, AstNode *e, Type *type, b32 final) { + u64 key = hash_pointer(e); + ExpressionInfo *found = map_get(&c->info.untyped, key); + if (found == NULL) return; switch (e->kind) { case_ast_node(ue, UnaryExpr, e); if (found->value.kind != ExactValue_Invalid) break; - update_expr_type(c, ue->expr, type); - break; + update_expr_type(c, ue->expr, type, final); case_end; case_ast_node(be, BinaryExpr, e); if (found->value.kind != ExactValue_Invalid) break; if (!token_is_comparison(be->op)) { - update_expr_type(c, be->left, type); - update_expr_type(c, be->right, type); + update_expr_type(c, be->left, type, final); + update_expr_type(c, be->right, type, final); } case_end; } - if (is_type_untyped(type)) { + if (!final && is_type_untyped(type)) { found->type = get_base_type(type); + map_set(&c->info.untyped, key, *found); } else { - found->type = type; + map_remove(&c->info.untyped, key); + add_type_and_value(&c->info, e, found->mode, type, found->value); } } @@ -838,7 +844,7 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) { if (is_type_numeric(x) && is_type_numeric(y)) { if (x < y) { operand->type = target_type; - update_expr_type(c, operand->expr, target_type); + update_expr_type(c, operand->expr, target_type, false); } } else if (x != y) { convert_untyped_error(c, operand, target_type); @@ -1479,10 +1485,10 @@ b32 check_castable_to(Checker *c, Operand *operand, Type *y) { } // []byte/[]u8 <-> string - if (is_type_byte_slice(xb) && is_type_string(yb)) { + if (is_type_u8_slice(xb) && is_type_string(yb)) { return true; } - if (is_type_string(xb) && is_type_byte_slice(yb)) { + if (is_type_string(xb) && is_type_u8_slice(yb)) { return true; } @@ -1722,6 +1728,8 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ if (o->mode == Addressing_Constant) { max_count = o->value.value_string.len; } + if (o->mode != Addressing_Variable) + o->mode = Addressing_Value; o->type = t_u8; } break; diff --git a/src/checker/type.cpp b/src/checker/type.cpp index fe9df4360..1b0977eec 100644 --- a/src/checker/type.cpp +++ b/src/checker/type.cpp @@ -26,7 +26,7 @@ enum BasicKind { Basic_Count, - Basic_byte = Basic_u8, + // Basic_byte = Basic_u8, Basic_rune = Basic_i32, }; @@ -242,7 +242,7 @@ gb_global Type basic_types[] = { }; gb_global Type basic_type_aliases[] = { - {Type_Basic, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("byte")}}, + // {Type_Basic, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("byte")}}, {Type_Basic, {Basic_rune, BasicFlag_Integer, STR_LIT("rune")}}, }; @@ -268,7 +268,7 @@ gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat]; gb_global Type *t_untyped_pointer = &basic_types[Basic_UntypedPointer]; gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString]; gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune]; -gb_global Type *t_byte = &basic_type_aliases[Basic_byte]; +// gb_global Type *t_byte = &basic_type_aliases[Basic_byte]; gb_global Type *t_rune = &basic_type_aliases[Basic_rune]; @@ -343,9 +343,9 @@ b32 is_type_rawptr(Type *t) { return t->basic.kind == Basic_rawptr; return false; } -b32 is_type_byte(Type *t) { +b32 is_type_u8(Type *t) { if (t->kind == Type_Basic) - return t->basic.kind == Basic_byte; + return t->basic.kind == Basic_u8; return false; } b32 is_type_slice(Type *t) { @@ -353,9 +353,9 @@ b32 is_type_slice(Type *t) { } -b32 is_type_byte_slice(Type *t) { +b32 is_type_u8_slice(Type *t) { if (t->kind == Type_Slice) - return is_type_byte(t->slice.elem); + return is_type_u8(t->slice.elem); return false; } diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index eb05eacc1..420be8ede 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -7,14 +7,14 @@ struct ssaGen { }; b32 ssa_gen_init(ssaGen *s, Checker *c) { - if (c->error_collector.count > 0) + if (c->error_collector.count != 0) return false; gb_for_array(i, c->parser->files) { AstFile *f = &c->parser->files[i]; - if (f->error_collector.count > 0) + if (f->error_collector.count != 0) return false; - if (f->tokenizer.error_count > 0) + if (f->tokenizer.error_count != 0) return false; } diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index 8d7fe3d87..5ae423f41 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -440,12 +440,13 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { case ssaInstr_Call: { auto *call = &instr->call; - if (call->type) { + Type *result_type = call->type->proc.results; + if (result_type) { ssa_fprintf(f, "%%%d = ", value->id); } ssa_fprintf(f, "call "); - if (call->type) { - ssa_print_type(f, m->sizes, call->type); + if (result_type) { + ssa_print_type(f, m->sizes, result_type); } else { ssa_fprintf(f, "void"); } @@ -454,14 +455,17 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { ssa_fprintf(f, "("); + auto *params = &call->type->proc.params->tuple; for (isize i = 0; i < call->arg_count; i++) { - ssaValue *arg = call->args[i]; - Type *t = ssa_value_type(arg); + Entity *e = params->variables[i]; + GB_ASSERT(e != NULL); + Type *t = e->type; if (i > 0) { ssa_fprintf(f, ", "); } ssa_print_type(f, m->sizes, t); ssa_fprintf(f, " "); + ssaValue *arg = call->args[i]; ssa_print_value(f, m, arg, t); } ssa_fprintf(f, ")\n"); diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index a8f48a6c8..310e1c423 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -7,6 +7,7 @@ struct ssaValue; struct ssaModule { CheckerInfo *info; BaseTypeSizes sizes; + gbArena arena; gbAllocator allocator; String layout; @@ -244,7 +245,10 @@ ssaLvalue ssa_make_lvalue_address(ssaValue *value, AstNode *expr) { void ssa_module_init(ssaModule *m, Checker *c) { - m->allocator = gb_heap_allocator(); + isize token_count = c->parser->total_token_count; + isize arena_size = 3 * token_count * gb_size_of(ssaValue); + gb_arena_init_from_allocator(&m->arena, gb_heap_allocator(), arena_size); + m->allocator = gb_arena_allocator(&m->arena); m->info = &c->info; m->sizes = c->sizes; @@ -255,6 +259,7 @@ void ssa_module_init(ssaModule *m, Checker *c) { void ssa_module_destroy(ssaModule *m) { map_destroy(&m->values); map_destroy(&m->members); + gb_arena_free(&m->arena); } void ssa_module_add_value(ssaModule *m, Entity *e, ssaValue *v) { @@ -279,6 +284,8 @@ Type *ssa_instr_type(ssaInstr *instr) { return instr->binary_op.type; case ssaInstr_Conv: return instr->conv.to; + case ssaInstr_Call: + return instr->call.type; } return NULL; } @@ -303,6 +310,9 @@ void ssa_instr_set_type(ssaInstr *instr, Type *type) { case ssaInstr_Conv: instr->conv.to = type; break; + case ssaInstr_Call: + instr->call.type = type; + break; } } @@ -355,8 +365,6 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *a_type); - - ssaValue *ssa_alloc_value(gbAllocator a, ssaValueKind kind) { ssaValue *v = gb_alloc_item(a, ssaValue); v->kind = kind; @@ -733,7 +741,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) { case ssaInstr_Unreachable: continue; case ssaInstr_Call: - if (instr->call.type == NULL) { + if (instr->call.type->proc.results == NULL) { continue; } break; @@ -993,7 +1001,7 @@ ssaValue *ssa_emit_string(ssaProcedure *proc, ssaValue *elem, ssaValue *len) { Type *t_u8_ptr = ssa_value_type(elem); GB_ASSERT(t_u8_ptr->kind == Type_Pointer); - GB_ASSERT(is_type_byte(t_u8_ptr->pointer.elem)); + GB_ASSERT(is_type_u8(t_u8_ptr->pointer.elem)); ssaValue *str = ssa_add_local_generated(proc, t_string); ssaValue *str_elem = ssa_emit_struct_gep(proc, str, v_zero32, t_u8_ptr); @@ -1074,14 +1082,14 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) { // []byte/[]u8 <-> string - if (is_type_byte_slice(src) && is_type_string(dst)) { + if (is_type_u8_slice(src) && is_type_string(dst)) { ssaValue *slice = ssa_add_local_generated(proc, src); ssa_emit_store(proc, slice, value); ssaValue *elem = ssa_slice_elem(proc, slice); ssaValue *len = ssa_slice_len(proc, slice); return ssa_emit_string(proc, elem, len); } - if (is_type_string(src) && is_type_byte_slice(dst)) { + if (is_type_string(src) && is_type_u8_slice(dst)) { ssaValue *str = ssa_add_local_generated(proc, src); ssa_emit_store(proc, str, value); ssaValue *elem = ssa_string_elem(proc, str); @@ -1276,6 +1284,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue #endif ssaValue *call = ssa_make_instr_call(proc, value, args, arg_count, tv->type); + ssa_value_set_type(call, proc_type_); return ssa_emit(proc, call); case_end; @@ -1318,26 +1327,25 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) { expr = unparen_expr(expr); TypeAndValue *tv = map_get(&proc->module->info->types, hash_pointer(expr)); - if (tv) { - if (tv->value.kind != ExactValue_Invalid) { - if (tv->value.kind == ExactValue_String) { - ssaValue *array = ssa_add_global_string_array(proc, tv->value); - ssaValue *elem = ssa_array_elem(proc, array); - return ssa_emit_string(proc, elem, ssa_array_len(proc, array)); - } - return ssa_make_value_constant(proc->module->allocator, tv->type, tv->value); - } + GB_ASSERT_NOT_NULL(tv); - ssaValue *value = NULL; - if (tv->mode == Addressing_Variable) { - value = ssa_lvalue_load(ssa_build_addr(proc, expr), proc); - } else { - value = ssa_build_single_expr(proc, expr, tv); + if (tv->value.kind != ExactValue_Invalid) { + if (tv->value.kind == ExactValue_String) { + ssaValue *array = ssa_add_global_string_array(proc, tv->value); + ssaValue *elem = ssa_array_elem(proc, array); + return ssa_emit_string(proc, elem, ssa_array_len(proc, array)); } - - return value; + return ssa_make_value_constant(proc->module->allocator, tv->type, tv->value); } - return NULL; + + ssaValue *value = NULL; + if (tv->mode == Addressing_Variable) { + value = ssa_lvalue_load(ssa_build_addr(proc, expr), proc); + } else { + value = ssa_build_single_expr(proc, expr, tv); + } + + return value; } @@ -1383,33 +1391,35 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { case_ast_node(ie, IndexExpr, expr); ssaValue *v = NULL; Type *t = get_base_type(type_of_expr(proc->module->info, ie->expr)); + ssaValue *elem = NULL; switch (t->kind) { case Type_Array: { ssaValue *array = ssa_lvalue_address(ssa_build_addr(proc, ie->expr), proc); - ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int); - ssaValue *elem = ssa_array_elem(proc, array); - v = ssa_emit_ptr_offset(proc, elem, index); + elem = ssa_array_elem(proc, array); } break; case Type_Slice: { ssaValue *slice = ssa_lvalue_address(ssa_build_addr(proc, ie->expr), proc); - ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int); - ssaValue *elem = ssa_slice_elem(proc, slice); - v = ssa_emit_ptr_offset(proc, elem, index); + elem = ssa_slice_elem(proc, slice); } break; case Type_Basic: { // Basic_string - ssaValue *str = ssa_lvalue_address(ssa_build_addr(proc, ie->expr), proc); - ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int); - ssaValue *elem = ssa_string_elem(proc, str); - v = ssa_emit_ptr_offset(proc, elem, index); + TypeAndValue *tv = map_get(&proc->module->info->types, hash_pointer(ie->expr)); + if (tv->mode == Addressing_Constant) { + ssaValue *array = ssa_add_global_string_array(proc, tv->value); + elem = ssa_array_elem(proc, array); + } else { + ssaLvalue lval = ssa_build_addr(proc, ie->expr); + ssaValue *str = ssa_lvalue_address(lval, proc); + elem = ssa_string_elem(proc, str); + } } break; case Type_Pointer: { - ssaValue *ptr = ssa_emit_load(proc, ssa_lvalue_address(ssa_build_addr(proc, ie->expr), proc)); - ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int); - v = ssa_emit_ptr_offset(proc, ptr, index); + elem = ssa_emit_load(proc, ssa_lvalue_address(ssa_build_addr(proc, ie->expr), proc)); } break; } - // NOTE(bill): lvalue address encodes the pointer, thus the deref + ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int); + v = ssa_emit_ptr_offset(proc, elem, index); + ssa_value_set_type(v, type_deref(ssa_value_type(v))); return ssa_make_lvalue_address(v, expr); case_end; @@ -1425,7 +1435,8 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { case_end; } - GB_PANIC("Unexpected address expression"); + GB_PANIC("Unexpected address expression\n" + "\tAstNode: %.*s\n", LIT(ast_node_strings[expr->kind])); ssaLvalue blank = {ssaLvalue_Blank}; return blank; diff --git a/src/main.cpp b/src/main.cpp index dbcda7397..85c5912fc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,11 +27,11 @@ int main(int argc, char **argv) { // print_ast(parser.files[0].declarations, 0); Checker checker = {}; + init_checker(&checker, &parser); defer (destroy_checker(&checker)); check_parsed_files(&checker); - ssaGen ssa = {}; if (ssa_gen_init(&ssa, &checker)) { defer (ssa_gen_destroy(&ssa)); diff --git a/src/parser.cpp b/src/parser.cpp index afd8bb3df..ae2162059 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -62,6 +62,7 @@ struct Parser { gbArray(AstFile) files; gbArray(String) imports; isize import_index; + isize total_token_count; }; enum DeclKind { @@ -2137,8 +2138,10 @@ ParseFileError parse_files(Parser *p, char *init_filename) { } parse_file(p, &file); gb_array_append(p->files, file); + p->total_token_count += gb_array_count(file.tokens); } + return ParseFile_None; } diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 7c0565cf2..e34fba9fa 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -26,98 +26,98 @@ b32 rune_is_whitespace(Rune r) { } #define TOKEN_KINDS \ - TOKEN_KIND(Invalid, "Invalid"), \ - TOKEN_KIND(EOF, "EOF"), \ + TOKEN_KIND(Token_Invalid, "Invalid"), \ + TOKEN_KIND(Token_EOF, "EOF"), \ \ -TOKEN_KIND(_LiteralBegin, "_LiteralBegin"), \ - TOKEN_KIND(Identifier, "Identifier"), \ - TOKEN_KIND(Integer, "Integer"), \ - TOKEN_KIND(Float, "Float"), \ - TOKEN_KIND(Rune, "Rune"), \ - TOKEN_KIND(String, "String"), \ -TOKEN_KIND(_LiteralEnd, "_LiteralEnd"), \ +TOKEN_KIND(Token__LiteralBegin, "_LiteralBegin"), \ + TOKEN_KIND(Token_Identifier, "Identifier"), \ + TOKEN_KIND(Token_Integer, "Integer"), \ + TOKEN_KIND(Token_Float, "Float"), \ + TOKEN_KIND(Token_Rune, "Rune"), \ + TOKEN_KIND(Token_String, "String"), \ +TOKEN_KIND(Token__LiteralEnd, "_LiteralEnd"), \ \ -TOKEN_KIND(_OperatorBegin, "_OperatorBegin"), \ - TOKEN_KIND(Eq, "="), \ - TOKEN_KIND(Not, "!"), \ - TOKEN_KIND(Hash, "#"), \ - TOKEN_KIND(At, "@"), \ - TOKEN_KIND(Pointer, "^"), \ - TOKEN_KIND(Add, "+"), \ - TOKEN_KIND(Sub, "-"), \ - TOKEN_KIND(Mul, "*"), \ - TOKEN_KIND(Quo, "/"), \ - TOKEN_KIND(Mod, "%"), \ - TOKEN_KIND(And, "&"), \ - TOKEN_KIND(Or, "|"), \ - TOKEN_KIND(Xor, "~"), \ - TOKEN_KIND(AndNot, "&~"), \ -TOKEN_KIND(_AssignOpBegin, "_AssignOpBegin"), \ - TOKEN_KIND(AddEq, "+="), \ - TOKEN_KIND(SubEq, "-="), \ - TOKEN_KIND(MulEq, "*="), \ - TOKEN_KIND(QuoEq, "/="), \ - TOKEN_KIND(ModEq, "%="), \ - TOKEN_KIND(AndEq, "&="), \ - TOKEN_KIND(OrEq, "|="), \ - TOKEN_KIND(XorEq, "~="), \ - TOKEN_KIND(AndNotEq, "&~="), \ -TOKEN_KIND(_AssignOpEnd, "_AssignOpEnd"), \ - TOKEN_KIND(Increment, "++"), \ - TOKEN_KIND(Decrement, "--"), \ - TOKEN_KIND(ArrowRight, "->"), \ - TOKEN_KIND(ArrowLeft, "<-"), \ - TOKEN_KIND(CmpAnd, "&&"), \ - TOKEN_KIND(CmpOr, "||"), \ - TOKEN_KIND(CmpAndEq, "&&="), \ - TOKEN_KIND(CmpOrEq, "||="), \ +TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \ + TOKEN_KIND(Token_Eq, "="), \ + TOKEN_KIND(Token_Not, "!"), \ + TOKEN_KIND(Token_Hash, "#"), \ + TOKEN_KIND(Token_At, "@"), \ + TOKEN_KIND(Token_Pointer, "^"), \ + TOKEN_KIND(Token_Add, "+"), \ + TOKEN_KIND(Token_Sub, "-"), \ + TOKEN_KIND(Token_Mul, "*"), \ + TOKEN_KIND(Token_Quo, "/"), \ + TOKEN_KIND(Token_Mod, "%"), \ + TOKEN_KIND(Token_And, "&"), \ + TOKEN_KIND(Token_Or, "|"), \ + TOKEN_KIND(Token_Xor, "~"), \ + TOKEN_KIND(Token_AndNot, "&~"), \ +TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \ + TOKEN_KIND(Token_AddEq, "+="), \ + TOKEN_KIND(Token_SubEq, "-="), \ + TOKEN_KIND(Token_MulEq, "*="), \ + TOKEN_KIND(Token_QuoEq, "/="), \ + TOKEN_KIND(Token_ModEq, "%="), \ + TOKEN_KIND(Token_AndEq, "&="), \ + TOKEN_KIND(Token_OrEq, "|="), \ + TOKEN_KIND(Token_XorEq, "~="), \ + TOKEN_KIND(Token_AndNotEq, "&~="), \ +TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \ + TOKEN_KIND(Token_Increment, "++"), \ + TOKEN_KIND(Token_Decrement, "--"), \ + TOKEN_KIND(Token_ArrowRight, "->"), \ + TOKEN_KIND(Token_ArrowLeft, "<-"), \ + TOKEN_KIND(Token_CmpAnd, "&&"), \ + TOKEN_KIND(Token_CmpOr, "||"), \ + TOKEN_KIND(Token_CmpAndEq, "&&="), \ + TOKEN_KIND(Token_CmpOrEq, "||="), \ \ -TOKEN_KIND(_ComparisonBegin, "_ComparisonBegin"), \ - TOKEN_KIND(CmpEq, "=="), \ - TOKEN_KIND(NotEq, "!="), \ - TOKEN_KIND(Lt, "<"), \ - TOKEN_KIND(Gt, ">"), \ - TOKEN_KIND(LtEq, "<="), \ - TOKEN_KIND(GtEq, ">="), \ -TOKEN_KIND(_ComparisonEnd, "_ComparisonEnd"), \ +TOKEN_KIND(Token__ComparisonBegin, "_ComparisonBegin"), \ + TOKEN_KIND(Token_CmpEq, "=="), \ + TOKEN_KIND(Token_NotEq, "!="), \ + TOKEN_KIND(Token_Lt, "<"), \ + TOKEN_KIND(Token_Gt, ">"), \ + TOKEN_KIND(Token_LtEq, "<="), \ + TOKEN_KIND(Token_GtEq, ">="), \ +TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \ \ - TOKEN_KIND(OpenParen, "("), \ - TOKEN_KIND(CloseParen, ")"), \ - TOKEN_KIND(OpenBracket, "["), \ - TOKEN_KIND(CloseBracket, "]"), \ - TOKEN_KIND(OpenBrace, "{"), \ - TOKEN_KIND(CloseBrace, "}"), \ - TOKEN_KIND(Colon, ":"), \ - TOKEN_KIND(Semicolon, ";"), \ - TOKEN_KIND(Period, "."), \ - TOKEN_KIND(Comma, ","), \ - TOKEN_KIND(Ellipsis, "..."), \ -TOKEN_KIND(_OperatorEnd, "_OperatorEnd"), \ + TOKEN_KIND(Token_OpenParen, "("), \ + TOKEN_KIND(Token_CloseParen, ")"), \ + TOKEN_KIND(Token_OpenBracket, "["), \ + TOKEN_KIND(Token_CloseBracket, "]"), \ + TOKEN_KIND(Token_OpenBrace, "{"), \ + TOKEN_KIND(Token_CloseBrace, "}"), \ + TOKEN_KIND(Token_Colon, ":"), \ + TOKEN_KIND(Token_Semicolon, ";"), \ + TOKEN_KIND(Token_Period, "."), \ + TOKEN_KIND(Token_Comma, ","), \ + TOKEN_KIND(Token_Ellipsis, "..."), \ +TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \ \ -TOKEN_KIND(_KeywordBegin, "_KeywordBegin"), \ - TOKEN_KIND(type, "type"), \ - TOKEN_KIND(alias, "alias"), \ - TOKEN_KIND(proc, "proc"), \ - TOKEN_KIND(match, "match"), \ - TOKEN_KIND(break, "break"), \ - TOKEN_KIND(continue, "continue"), \ - TOKEN_KIND(fallthrough, "fallthrough"), \ - TOKEN_KIND(case, "case"), \ - TOKEN_KIND(if, "if"), \ - TOKEN_KIND(else, "else"), \ - TOKEN_KIND(for, "for"), \ - TOKEN_KIND(defer, "defer"), \ - TOKEN_KIND(return, "return"), \ - TOKEN_KIND(import, "import"), \ - TOKEN_KIND(cast, "cast"), \ - TOKEN_KIND(struct, "struct"), \ - TOKEN_KIND(union, "union"), \ - TOKEN_KIND(enum, "enum"), \ -TOKEN_KIND(_KeywordEnd, "_KeywordEnd"), \ - TOKEN_KIND(Count, "") +TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ + TOKEN_KIND(Token_type, "type"), \ + TOKEN_KIND(Token_alias, "alias"), \ + TOKEN_KIND(Token_proc, "proc"), \ + TOKEN_KIND(Token_match, "match"), \ + TOKEN_KIND(Token_break, "break"), \ + TOKEN_KIND(Token_continue, "continue"), \ + TOKEN_KIND(Token_fallthrough, "fallthrough"), \ + TOKEN_KIND(Token_case, "case"), \ + TOKEN_KIND(Token_if, "if"), \ + TOKEN_KIND(Token_else, "else"), \ + TOKEN_KIND(Token_for, "for"), \ + TOKEN_KIND(Token_defer, "defer"), \ + TOKEN_KIND(Token_return, "return"), \ + TOKEN_KIND(Token_import, "import"), \ + TOKEN_KIND(Token_cast, "cast"), \ + TOKEN_KIND(Token_struct, "struct"), \ + TOKEN_KIND(Token_union, "union"), \ + TOKEN_KIND(Token_enum, "enum"), \ +TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \ + TOKEN_KIND(Token_Count, "") enum TokenKind { -#define TOKEN_KIND(e, s) GB_JOIN2(Token_, e) +#define TOKEN_KIND(e, s) e TOKEN_KINDS #undef TOKEN_KIND }; @@ -162,10 +162,10 @@ Token empty_token = {Token_Invalid}; struct ErrorCollector { TokenPos prev; - isize count; + i64 count; }; -void error(ErrorCollector *ec, Token token, char *fmt, ...) { +gb_no_inline void error(ErrorCollector *ec, Token token, char *fmt, ...) { ec->count++; // NOTE(bill): Duplicate error, skip it if (!token_pos_are_equal(ec->prev, token.pos)) { @@ -181,7 +181,7 @@ void error(ErrorCollector *ec, Token token, char *fmt, ...) { } } -void warning(Token token, char *fmt, ...) { +gb_no_inline void warning(Token token, char *fmt, ...) { va_list va; va_start(va, fmt); gb_printf_err("%.*s(%td:%td) Warning: %s\n",