mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-31 18:32:12 +00:00
append :: proc(s: ^[]T, i: T) -> bool
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
putchar :: proc(c: i32) -> i32 #foreign
|
||||
|
||||
print_string :: proc(s: string) {
|
||||
for i := 0; i < len(s); i++ {
|
||||
putchar(s[i] as i32);
|
||||
@@ -22,8 +20,8 @@ encode_rune :: proc(r : rune) -> ([4]byte, int) {
|
||||
return buf, 1;
|
||||
}
|
||||
if i <= 1<<11-1 {
|
||||
buf[0] = (0xc0 | r>>6) as byte;
|
||||
buf[1] = (0x80 | r) as byte & mask;
|
||||
buf[0] = 0xc0 | (r>>6) as byte;
|
||||
buf[1] = 0x80 | (r) as byte & mask;
|
||||
return buf, 2;
|
||||
}
|
||||
|
||||
@@ -34,16 +32,16 @@ encode_rune :: proc(r : rune) -> ([4]byte, int) {
|
||||
}
|
||||
|
||||
if i <= 1<<16-1 {
|
||||
buf[0] = (0xe0 | r>>12) as byte ;
|
||||
buf[1] = (0x80 | r>>6) as byte & mask;
|
||||
buf[2] = (0x80 | r) as byte & mask;
|
||||
buf[0] = 0xe0 | (r>>12) as byte;
|
||||
buf[1] = 0x80 | (r>>6) as byte & mask;
|
||||
buf[2] = 0x80 | (r) as byte & mask;
|
||||
return buf, 3;
|
||||
}
|
||||
|
||||
buf[0] = (0xf0 | r>>18) as byte;
|
||||
buf[1] = (0x80 | r>>12) as byte & mask;
|
||||
buf[2] = (0x80 | r>>6) as byte & mask;
|
||||
buf[3] = (0x80 | r) as byte & mask;
|
||||
buf[0] = 0xf0 | (r>>18) as byte;
|
||||
buf[1] = 0x80 | (r>>12) as byte & mask;
|
||||
buf[2] = 0x80 | (r>>6) as byte & mask;
|
||||
buf[3] = 0x80 | (r) as byte & mask;
|
||||
return buf, 4;
|
||||
}
|
||||
|
||||
|
||||
247
examples/main.ll
247
examples/main.ll
@@ -6,62 +6,149 @@ declare void @llvm.memmove.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1)
|
||||
|
||||
define void @main() {
|
||||
"entry - 0":
|
||||
%0 = alloca <8 x float>, align 4 ; a
|
||||
store <8 x float> zeroinitializer, <8 x float>* %0
|
||||
%1 = alloca <8 x float>, align 4 ; b
|
||||
store <8 x float> zeroinitializer, <8 x float>* %1
|
||||
%2 = alloca <8 x float>, align 4
|
||||
store <8 x float> zeroinitializer, <8 x float>* %2
|
||||
%3 = load <8 x float>, <8 x float>* %2
|
||||
%4 = insertelement <8 x float> %3, float 0x3ff0000000000000, i64 0
|
||||
%5 = insertelement <8 x float> %4, float 0x4000000000000000, i64 1
|
||||
%6 = insertelement <8 x float> %5, float 0x4008000000000000, i64 2
|
||||
%7 = insertelement <8 x float> %6, float 0x4010000000000000, i64 3
|
||||
%8 = alloca <8 x float>, align 4
|
||||
store <8 x float> zeroinitializer, <8 x float>* %8
|
||||
%9 = load <8 x float>, <8 x float>* %8
|
||||
%10 = insertelement <8 x float> %9, float 0x3ff0000000000000, i64 0
|
||||
%11 = insertelement <8 x float> %10, float 0x4000000000000000, i64 1
|
||||
%12 = insertelement <8 x float> %11, float 0x4008000000000000, i64 2
|
||||
%13 = insertelement <8 x float> %12, float 0x4010000000000000, i64 3
|
||||
store <8 x float> %7, <8 x float>* %0
|
||||
store <8 x float> %13, <8 x float>* %1
|
||||
%14 = alloca <8 x i1>, align 1 ; c
|
||||
store <8 x i1> zeroinitializer, <8 x i1>* %14
|
||||
%15 = load <8 x float>, <8 x float>* %0
|
||||
%16 = load <8 x float>, <8 x float>* %1
|
||||
%17 = fcmp oeq <8 x float> %15, %16
|
||||
store <8 x i1> %17, <8 x i1>* %14
|
||||
%18 = alloca <32 x i1>, align 1 ; x
|
||||
store <32 x i1> zeroinitializer, <32 x i1>* %18
|
||||
%19 = alloca <32 x i1>, align 1
|
||||
store <32 x i1> zeroinitializer, <32 x i1>* %19
|
||||
%20 = load <32 x i1>, <32 x i1>* %19
|
||||
%21 = insertelement <32 x i1> %20, i1 true, i64 0
|
||||
%22 = insertelement <32 x i1> %21, i1 false, i64 1
|
||||
%23 = insertelement <32 x i1> %22, i1 true, i64 2
|
||||
store <32 x i1> %23, <32 x i1>* %18
|
||||
%24 = alloca i32, align 4 ; d
|
||||
store i32 zeroinitializer, i32* %24
|
||||
%25 = alloca i32*, align 8
|
||||
store i32* zeroinitializer, i32** %25
|
||||
%26 = getelementptr inbounds <32 x i1>, <32 x i1>* %18, i64 0, i32 0
|
||||
%27 = getelementptr i1, i1* %26, i64 0
|
||||
%28 = getelementptr inbounds i1, i1* %27
|
||||
%29 = bitcast i1* %28 to i32*
|
||||
store i32* %29, i32** %25
|
||||
%30 = load i32*, i32** %25
|
||||
%31 = getelementptr i32, i32* %30
|
||||
%32 = load i32, i32* %31
|
||||
store i32 %32, i32* %24
|
||||
%33 = load i32, i32* %24
|
||||
%34 = zext i32 %33 to i64
|
||||
call void @print_int_base(i64 %34, i64 2)
|
||||
%0 = alloca %.rawptr, align 8 ; data
|
||||
store %.rawptr zeroinitializer, %.rawptr* %0
|
||||
%1 = call %.rawptr @malloc(i64 100)
|
||||
store %.rawptr %1, %.rawptr* %0
|
||||
%2 = alloca {i8*, i64, i64}, align 8 ; slice
|
||||
store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %2
|
||||
%3 = alloca i8*, align 8
|
||||
store i8* zeroinitializer, i8** %3
|
||||
%4 = load %.rawptr, %.rawptr* %0
|
||||
%5 = bitcast %.rawptr %4 to i8*
|
||||
store i8* %5, i8** %3
|
||||
%6 = sub i64 0, 0
|
||||
%7 = sub i64 100, 0
|
||||
%8 = load i8*, i8** %3
|
||||
%9 = getelementptr i8, i8* %8, i64 0
|
||||
%10 = alloca {i8*, i64, i64}, align 8
|
||||
store {i8*, i64, i64} zeroinitializer, {i8*, i64, i64}* %10
|
||||
%11 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %10, i64 0, i32 0
|
||||
store i8* %9, i8** %11
|
||||
%12 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %10, i64 0, i32 1
|
||||
store i64 %6, i64* %12
|
||||
%13 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %10, i64 0, i32 2
|
||||
store i64 %7, i64* %13
|
||||
%14 = load {i8*, i64, i64}, {i8*, i64, i64}* %10
|
||||
store {i8*, i64, i64} %14, {i8*, i64, i64}* %2
|
||||
%15 = alloca i64, align 8 ; i
|
||||
store i64 zeroinitializer, i64* %15
|
||||
store i64 0, i64* %15
|
||||
br label %"for.loop - 2"
|
||||
|
||||
"for.body - 1":
|
||||
%16 = alloca i1, align 1 ; ok
|
||||
store i1 zeroinitializer, i1* %16
|
||||
%17 = alloca i8, align 1
|
||||
store i8 zeroinitializer, i8* %17
|
||||
%18 = load i64, i64* %15
|
||||
%19 = load i64, i64* %15
|
||||
%20 = mul i64 %19, %18
|
||||
%21 = trunc i64 %20 to i8
|
||||
store i8 %21, i8* %17
|
||||
%22 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %2, i64 0, i32 0
|
||||
%23 = load i8*, i8** %22
|
||||
%24 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %2, i64 0, i32 1
|
||||
%25 = load i64, i64* %24
|
||||
%26 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %2, i64 0, i32 2
|
||||
%27 = load i64, i64* %26
|
||||
%28 = icmp slt i64 %25, %27
|
||||
br i1 %28, label %"builtin.append.able - 4", label %"builtin.append.done - 5"
|
||||
|
||||
"for.loop - 2":
|
||||
%29 = load i64, i64* %15
|
||||
%30 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %2, i64 0, i32 2
|
||||
%31 = load i64, i64* %30
|
||||
%32 = icmp slt i64 %29, %31
|
||||
br i1 %32, label %"for.body - 1", label %"for.done - 6"
|
||||
|
||||
"for.post - 3":
|
||||
%33 = load i64, i64* %15
|
||||
%34 = add i64 %33, 1
|
||||
store i64 %34, i64* %15
|
||||
br label %"for.loop - 2"
|
||||
|
||||
"builtin.append.able - 4":
|
||||
%35 = getelementptr i8, i8* %23, i64 %25
|
||||
call void @llvm.memmove.p0i8.p0i8.i64(i8* %35, i8* %17, i64 1, i32 1, i1 false)
|
||||
%36 = add i64 %25, 1
|
||||
%37 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %2, i64 0, i32 1
|
||||
store i64 %36, i64* %37
|
||||
br label %"builtin.append.done - 5"
|
||||
|
||||
"builtin.append.done - 5":
|
||||
store i1 %28, i1* %16
|
||||
br label %"for.post - 3"
|
||||
|
||||
"for.done - 6":
|
||||
%38 = alloca i64, align 8 ; i
|
||||
store i64 zeroinitializer, i64* %38
|
||||
store i64 0, i64* %38
|
||||
br label %"for.loop - 8"
|
||||
|
||||
"for.body - 7":
|
||||
%39 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %2, i64 0, i32 0
|
||||
%40 = load i8*, i8** %39
|
||||
%41 = load i64, i64* %38
|
||||
%42 = getelementptr i8, i8* %40, i64 %41
|
||||
%43 = load i8, i8* %42
|
||||
%44 = zext i8 %43 to i64
|
||||
call void @print_int(i64 %44)
|
||||
%45 = getelementptr inbounds [2 x i8], [2 x i8]* @.str0, i64 0, i64 0
|
||||
%46 = alloca %.string, align 8
|
||||
store %.string zeroinitializer, %.string* %46
|
||||
%47 = getelementptr inbounds %.string, %.string* %46, i64 0, i32 0
|
||||
%48 = getelementptr inbounds %.string, %.string* %46, i64 0, i32 1
|
||||
store i8* %45, i8** %47
|
||||
store i64 2, i64* %48
|
||||
%49 = load %.string, %.string* %46
|
||||
call void @print_string(%.string %49)
|
||||
%50 = load i64, i64* %38
|
||||
%51 = add i64 %50, 1
|
||||
%52 = srem i64 %51, 8
|
||||
%53 = icmp eq i64 %52, 0
|
||||
br i1 %53, label %"if.then - 10", label %"if.done - 11"
|
||||
|
||||
"for.loop - 8":
|
||||
%54 = load i64, i64* %38
|
||||
%55 = getelementptr inbounds {i8*, i64, i64}, {i8*, i64, i64}* %2, i64 0, i32 1
|
||||
%56 = load i64, i64* %55
|
||||
%57 = icmp slt i64 %54, %56
|
||||
br i1 %57, label %"for.body - 7", label %"for.done - 12"
|
||||
|
||||
"for.post - 9":
|
||||
%58 = load i64, i64* %38
|
||||
%59 = add i64 %58, 1
|
||||
store i64 %59, i64* %38
|
||||
br label %"for.loop - 8"
|
||||
|
||||
"if.then - 10":
|
||||
%60 = getelementptr inbounds [1 x i8], [1 x i8]* @.str1, i64 0, i64 0
|
||||
%61 = alloca %.string, align 8
|
||||
store %.string zeroinitializer, %.string* %61
|
||||
%62 = getelementptr inbounds %.string, %.string* %61, i64 0, i32 0
|
||||
%63 = getelementptr inbounds %.string, %.string* %61, i64 0, i32 1
|
||||
store i8* %60, i8** %62
|
||||
store i64 1, i64* %63
|
||||
%64 = load %.string, %.string* %61
|
||||
call void @print_string(%.string %64)
|
||||
br label %"if.done - 11"
|
||||
|
||||
"if.done - 11":
|
||||
br label %"for.post - 9"
|
||||
|
||||
"for.done - 12":
|
||||
%65 = load %.rawptr, %.rawptr* %0
|
||||
call void @free(%.rawptr %65)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i32 @putchar(i32 %c) ; foreign procedure
|
||||
|
||||
declare %.rawptr @malloc(i64 %sz) ; foreign procedure
|
||||
|
||||
declare void @free(%.rawptr %ptr) ; foreign procedure
|
||||
|
||||
define void @print_string(%.string %s) {
|
||||
"entry - 0":
|
||||
%0 = alloca %.string, align 8 ; s
|
||||
@@ -201,15 +288,15 @@ define {[4 x i8], i64} @encode_rune(i32 %r) {
|
||||
%18 = getelementptr i8, i8* %17, i64 0
|
||||
%19 = load i32, i32* %0
|
||||
%20 = lshr i32 %19, 6
|
||||
%21 = or i32 192, %20
|
||||
%22 = trunc i32 %21 to i8
|
||||
%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
|
||||
%26 = or i32 128, %25
|
||||
%27 = trunc i32 %26 to i8
|
||||
%28 = and i8 %27, 63
|
||||
%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
|
||||
@@ -250,23 +337,23 @@ define {[4 x i8], i64} @encode_rune(i32 %r) {
|
||||
%43 = getelementptr i8, i8* %42, i64 0
|
||||
%44 = load i32, i32* %0
|
||||
%45 = lshr i32 %44, 12
|
||||
%46 = or i32 224, %45
|
||||
%47 = trunc i32 %46 to i8
|
||||
%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
|
||||
%51 = lshr i32 %50, 6
|
||||
%52 = or i32 128, %51
|
||||
%53 = trunc i32 %52 to i8
|
||||
%54 = and i8 %53, 63
|
||||
%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
|
||||
%58 = or i32 128, %57
|
||||
%59 = trunc i32 %58 to i8
|
||||
%60 = and i8 %59, 63
|
||||
%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
|
||||
@@ -283,31 +370,31 @@ define {[4 x i8], i64} @encode_rune(i32 %r) {
|
||||
%67 = getelementptr i8, i8* %66, i64 0
|
||||
%68 = load i32, i32* %0
|
||||
%69 = lshr i32 %68, 18
|
||||
%70 = or i32 240, %69
|
||||
%71 = trunc i32 %70 to i8
|
||||
%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
|
||||
%75 = lshr i32 %74, 12
|
||||
%76 = or i32 128, %75
|
||||
%77 = trunc i32 %76 to i8
|
||||
%78 = and i8 %77, 63
|
||||
%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
|
||||
%82 = lshr i32 %81, 6
|
||||
%83 = or i32 128, %82
|
||||
%84 = trunc i32 %83 to i8
|
||||
%85 = and i8 %84, 63
|
||||
%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
|
||||
%89 = or i32 128, %88
|
||||
%90 = trunc i32 %89 to i8
|
||||
%91 = and i8 %90, 63
|
||||
%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
|
||||
@@ -430,7 +517,7 @@ define void @print_int_base(i64 %i, i64 %base) {
|
||||
%16 = getelementptr inbounds [65 x i8], [65 x i8]* %2, i64 0, i64 0
|
||||
%17 = load i64, i64* %3
|
||||
%18 = getelementptr i8, i8* %16, i64 %17
|
||||
%19 = getelementptr inbounds [64 x i8], [64 x i8]* @.str0, i64 0, i64 0
|
||||
%19 = getelementptr inbounds [64 x i8], [64 x i8]* @.str2, i64 0, i64 0
|
||||
%20 = load i64, i64* %1
|
||||
%21 = load i64, i64* %0
|
||||
%22 = srem i64 %21, %20
|
||||
@@ -572,7 +659,7 @@ define void @print_uint_base(i64 %i, i64 %base) {
|
||||
%16 = getelementptr inbounds [65 x i8], [65 x i8]* %2, i64 0, i64 0
|
||||
%17 = load i64, i64* %3
|
||||
%18 = getelementptr i8, i8* %16, i64 %17
|
||||
%19 = getelementptr inbounds [64 x i8], [64 x i8]* @.str1, i64 0, i64 0
|
||||
%19 = getelementptr inbounds [64 x i8], [64 x i8]* @.str3, i64 0, i64 0
|
||||
%20 = load i64, i64* %1
|
||||
%21 = load i64, i64* %0
|
||||
%22 = urem i64 %21, %20
|
||||
@@ -688,5 +775,7 @@ define void @print_f64(double %f) {
|
||||
ret void
|
||||
}
|
||||
|
||||
@.str0 = global [64 x i8] c"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\40$"
|
||||
@.str1 = global [64 x i8] c"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\40$"
|
||||
@.str0 = global [2 x i8] c"\2C\20"
|
||||
@.str1 = global [1 x i8] c"\0A"
|
||||
@.str2 = global [64 x i8] c"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\40$"
|
||||
@.str3 = global [64 x i8] c"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\40$"
|
||||
|
||||
@@ -1,36 +1,25 @@
|
||||
import "c_runtime"
|
||||
import "basic"
|
||||
|
||||
TWO_HEARTS :: '💕';
|
||||
|
||||
main :: proc() {
|
||||
a, b := {8}f32{1, 2, 3, 4}, {8}f32{1, 2, 3, 4};
|
||||
c := a == b;
|
||||
x := {32}bool{true, false, true};
|
||||
d := ((^x[0]) as ^u32)^;
|
||||
print_int_base(d as int, 2);
|
||||
// print_string("\n");
|
||||
// print_int(x[0] as int);
|
||||
// print_int(x[1] as int);
|
||||
// print_int(x[2] as int);
|
||||
// print_string("\n");
|
||||
DATA_SIZE :: 100;
|
||||
data := malloc(DATA_SIZE);
|
||||
|
||||
// for i := 0; false && i < len(x); i++ {
|
||||
// v := x[i];
|
||||
// print_int(v);
|
||||
// print_string("\n");
|
||||
// }
|
||||
slice := (data as ^u8)[:0:DATA_SIZE];
|
||||
for i := 0; i < cap(slice); i++ {
|
||||
ok := append(^slice, (i*i) as u8);
|
||||
}
|
||||
|
||||
// for i := 0; i < len(c); i++ {
|
||||
// if i > 0 {
|
||||
// print_string("\n");
|
||||
// }
|
||||
// print_int(a[i] as int);
|
||||
// print_string(" == ");
|
||||
// print_int(b[i] as int);
|
||||
// print_string(" => ");
|
||||
// print_int(c[i] as int);
|
||||
// }
|
||||
// print_rune('\n');
|
||||
for i := 0; i < len(slice); i++ {
|
||||
print_int(slice[i] as int);
|
||||
print_string(", ");
|
||||
if (i+1) % 8 == 0 {
|
||||
print_string("\n");
|
||||
}
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -857,45 +857,6 @@ b32 check_castable_to(Checker *c, Operand *operand, Type *y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void check_cast_expr(Checker *c, Operand *operand, Type *type) {
|
||||
b32 is_const_expr = operand->mode == Addressing_Constant;
|
||||
b32 can_convert = false;
|
||||
|
||||
if (is_const_expr && is_type_constant_type(type)) {
|
||||
Type *t = get_base_type(type);
|
||||
if (t->kind == Type_Basic) {
|
||||
if (check_value_is_expressible(c, operand->value, t, &operand->value)) {
|
||||
can_convert = true;
|
||||
}
|
||||
}
|
||||
} else if (check_castable_to(c, operand, type)) {
|
||||
operand->mode = Addressing_Value;
|
||||
can_convert = true;
|
||||
}
|
||||
|
||||
if (!can_convert) {
|
||||
gbString expr_str = expr_to_string(operand->expr);
|
||||
gbString type_str = type_to_string(type);
|
||||
defer (gb_string_free(expr_str));
|
||||
defer (gb_string_free(type_str));
|
||||
error(&c->error_collector, ast_node_token(operand->expr), "Cannot cast `%s` to `%s`", expr_str, type_str);
|
||||
|
||||
operand->mode = Addressing_Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_type_untyped(operand->type)) {
|
||||
Type *final_type = type;
|
||||
if (is_const_expr && !is_type_constant_type(type)) {
|
||||
final_type = default_type(operand->type);
|
||||
}
|
||||
update_expr_type(c, operand->expr, final_type, true);
|
||||
}
|
||||
|
||||
operand->type = type;
|
||||
}
|
||||
|
||||
|
||||
void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
||||
GB_ASSERT(node->kind == AstNode_BinaryExpr);
|
||||
Operand y_ = {}, *y = &y_;
|
||||
@@ -906,10 +867,82 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
||||
|
||||
if (be->op.kind == Token_as) {
|
||||
check_expr(c, x, be->left);
|
||||
Type *cast_type = check_type(c, be->right);
|
||||
Type *type = check_type(c, be->right);
|
||||
if (x->mode == Addressing_Invalid)
|
||||
return;
|
||||
check_cast_expr(c, x, cast_type);
|
||||
|
||||
b32 is_const_expr = x->mode == Addressing_Constant;
|
||||
b32 can_convert = false;
|
||||
|
||||
if (is_const_expr && is_type_constant_type(type)) {
|
||||
Type *t = get_base_type(type);
|
||||
if (t->kind == Type_Basic) {
|
||||
if (check_value_is_expressible(c, x->value, t, &x->value)) {
|
||||
can_convert = true;
|
||||
}
|
||||
}
|
||||
} else if (check_castable_to(c, x, type)) {
|
||||
x->mode = Addressing_Value;
|
||||
can_convert = true;
|
||||
}
|
||||
|
||||
if (!can_convert) {
|
||||
gbString expr_str = expr_to_string(x->expr);
|
||||
gbString type_str = type_to_string(type);
|
||||
defer (gb_string_free(expr_str));
|
||||
defer (gb_string_free(type_str));
|
||||
error(&c->error_collector, ast_node_token(x->expr), "Cannot cast `%s` to `%s`", expr_str, type_str);
|
||||
|
||||
x->mode = Addressing_Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_type_untyped(x->type)) {
|
||||
Type *final_type = type;
|
||||
if (is_const_expr && !is_type_constant_type(type)) {
|
||||
final_type = default_type(x->type);
|
||||
}
|
||||
update_expr_type(c, x->expr, final_type, true);
|
||||
}
|
||||
|
||||
x->type = type;
|
||||
return;
|
||||
} else if (be->op.kind == Token_transmute) {
|
||||
check_expr(c, x, be->left);
|
||||
Type *type = check_type(c, be->right);
|
||||
if (x->mode == Addressing_Invalid)
|
||||
return;
|
||||
|
||||
if (x->mode == Addressing_Constant) {
|
||||
gbString expr_str = expr_to_string(x->expr);
|
||||
defer (gb_string_free(expr_str));
|
||||
error(&c->error_collector, ast_node_token(x->expr), "Cannot transmute constant expression: `%s`", expr_str);
|
||||
x->mode = Addressing_Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_type_untyped(x->type)) {
|
||||
gbString expr_str = expr_to_string(x->expr);
|
||||
defer (gb_string_free(expr_str));
|
||||
error(&c->error_collector, ast_node_token(x->expr), "Cannot transmute untyped expression: `%s`", expr_str);
|
||||
x->mode = Addressing_Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
i64 otz = type_size_of(c->sizes, c->allocator, x->type);
|
||||
i64 ttz = type_size_of(c->sizes, c->allocator, type);
|
||||
if (otz != ttz) {
|
||||
gbString expr_str = expr_to_string(x->expr);
|
||||
gbString type_str = type_to_string(type);
|
||||
defer (gb_string_free(expr_str));
|
||||
defer (gb_string_free(type_str));
|
||||
error(&c->error_collector, ast_node_token(x->expr), "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, otz, ttz);
|
||||
x->mode = Addressing_Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
x->type = type;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -438,6 +438,11 @@ b32 are_types_identical(Type *x, Type *y) {
|
||||
return (x->vector.count == y->vector.count) && are_types_identical(x->vector.elem, y->vector.elem);
|
||||
break;
|
||||
|
||||
case Type_Slice:
|
||||
if (y->kind == Type_Slice)
|
||||
return are_types_identical(x->slice.elem, y->slice.elem);
|
||||
break;
|
||||
|
||||
case Type_Structure:
|
||||
if (y->kind == Type_Structure) {
|
||||
if (x->structure.field_count == y->structure.field_count) {
|
||||
|
||||
@@ -401,6 +401,7 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr);
|
||||
ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue *tv);
|
||||
ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr);
|
||||
ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *a_type);
|
||||
ssaValue *ssa_emit_transmute(ssaProcedure *proc, ssaValue *value, Type *a_type);
|
||||
void ssa_build_proc(ssaValue *value, ssaProcedure *parent);
|
||||
|
||||
|
||||
@@ -1077,7 +1078,7 @@ ssaValue *ssa_emit_slice(ssaProcedure *proc, Type *slice_type, ssaValue *base, s
|
||||
switch (base_type->kind) {
|
||||
case Type_Array: elem = ssa_array_elem(proc, base); break;
|
||||
case Type_Slice: elem = ssa_slice_elem(proc, base); break;
|
||||
case Type_Pointer: elem = base; break;
|
||||
case Type_Pointer: elem = ssa_emit_load(proc, base); break;
|
||||
}
|
||||
|
||||
elem = ssa_emit_ptr_offset(proc, elem, low);
|
||||
@@ -1176,8 +1177,6 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
|
||||
if (are_types_identical(t, src_type))
|
||||
return value;
|
||||
|
||||
|
||||
|
||||
if (value->kind == ssaValue_Constant) {
|
||||
if (dst->kind == Type_Basic) {
|
||||
ExactValue ev = value->constant.value;
|
||||
@@ -1291,6 +1290,31 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
|
||||
}
|
||||
|
||||
|
||||
ssaValue *ssa_emit_transmute(ssaProcedure *proc, ssaValue *value, Type *t) {
|
||||
Type *src_type = ssa_value_type(value);
|
||||
if (are_types_identical(t, src_type)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
Type *src = get_base_type(src_type);
|
||||
Type *dst = get_base_type(t);
|
||||
if (are_types_identical(t, src_type))
|
||||
return value;
|
||||
|
||||
i64 sz = type_size_of(proc->module->sizes, proc->module->allocator, src);
|
||||
i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst);
|
||||
|
||||
if (sz == dz) {
|
||||
return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst));
|
||||
}
|
||||
|
||||
|
||||
GB_PANIC("Invalid transmute conversion: `%s` to `%s`", type_to_string(src_type), type_to_string(t));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1392,6 +1416,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
case Token_as:
|
||||
return ssa_emit_conv(proc, ssa_build_expr(proc, be->left), tv->type);
|
||||
|
||||
case Token_transmute:
|
||||
return ssa_emit_transmute(proc, ssa_build_expr(proc, be->left), tv->type);
|
||||
|
||||
default:
|
||||
GB_PANIC("Invalid binary expression");
|
||||
break;
|
||||
@@ -1583,8 +1610,44 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
return len;
|
||||
} break;
|
||||
case BuiltinProc_append: {
|
||||
// copy :: proc(s: ^[]Type, value: Type) -> bool
|
||||
GB_PANIC("TODO(bill): BuiltinProc_append");
|
||||
// append :: proc(s: ^[]Type, item: Type) -> bool
|
||||
AstNode *sptr_node = ce->arg_list;
|
||||
AstNode *item_node = ce->arg_list->next;
|
||||
ssaValue *slice = ssa_build_addr(proc, sptr_node).address;
|
||||
ssaValue *item = ssa_build_addr(proc, item_node).address;
|
||||
Type *item_type = type_deref(ssa_value_type(item));
|
||||
|
||||
ssaValue *elem = ssa_slice_elem(proc, slice);
|
||||
ssaValue *len = ssa_slice_len(proc, slice);
|
||||
ssaValue *cap = ssa_slice_cap(proc, slice);
|
||||
|
||||
// NOTE(bill): Check if can append is possible
|
||||
Token lt = {Token_Lt};
|
||||
ssaValue *cond = ssa_emit_comp(proc, lt, len, cap);
|
||||
ssaBlock *able = ssa_add_block(proc, NULL, make_string("builtin.append.able"));
|
||||
ssaBlock *done = ssa__make_block(proc, NULL, make_string("builtin.append.done"));
|
||||
|
||||
ssa_emit_if(proc, cond, able, done);
|
||||
proc->curr_block = able;
|
||||
|
||||
// Add new slice item
|
||||
ssaValue *offset = ssa_emit_ptr_offset(proc, elem, len);
|
||||
i64 item_size = type_size_of(proc->module->sizes, proc->module->allocator, item_type);
|
||||
ssaValue *byte_count = ssa_make_value_constant(proc->module->allocator, t_int,
|
||||
make_exact_value_integer(item_size));
|
||||
ssa_emit(proc, ssa_make_instr_copy_memory(proc, offset, item, byte_count, 1, false));
|
||||
|
||||
// Increment slice length
|
||||
Token add = {Token_Add};
|
||||
ssaValue *new_len = ssa_emit_arith(proc, add, len, v_one, t_int);
|
||||
ssaValue *gep = ssa_emit_struct_gep(proc, slice, v_one32, t_int);
|
||||
ssa_emit_store(proc, gep, new_len);
|
||||
|
||||
ssa_emit_jump(proc, done);
|
||||
gb_array_append(proc->blocks, done);
|
||||
proc->curr_block = done;
|
||||
|
||||
return ssa_emit_conv(proc, cond, t_bool);
|
||||
} break;
|
||||
case BuiltinProc_print: {
|
||||
// print :: proc(...)
|
||||
@@ -1735,12 +1798,21 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
case_ast_node(be, BinaryExpr, expr);
|
||||
switch (be->op.kind) {
|
||||
case Token_as: {
|
||||
// HACK(bill): Do have to make new variable to do this?
|
||||
// NOTE(bill): Needed for dereference of pointer conversion
|
||||
Type *type = type_of_expr(proc->module->info, expr);
|
||||
ssaValue *v = ssa_add_local_generated(proc, type);
|
||||
ssa_emit_store(proc, v, ssa_emit_conv(proc, ssa_build_expr(proc, be->left), type));
|
||||
return ssa_make_lvalue(v, expr);
|
||||
}
|
||||
case Token_transmute: {
|
||||
// HACK(bill): Do have to make new variable to do this?
|
||||
// NOTE(bill): Needed for dereference of pointer conversion
|
||||
Type *type = type_of_expr(proc->module->info, expr);
|
||||
ssaValue *v = ssa_add_local_generated(proc, type);
|
||||
ssa_emit_store(proc, v, ssa_emit_transmute(proc, ssa_build_expr(proc, be->left), type));
|
||||
return ssa_make_lvalue(v, expr);
|
||||
}
|
||||
default:
|
||||
GB_PANIC("Invalid binary expression for ssa_build_addr: %.*s\n", LIT(be->op.string));
|
||||
break;
|
||||
@@ -1971,33 +2043,48 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
if (proc->children == NULL) {
|
||||
gb_array_init(proc->children, gb_heap_allocator());
|
||||
}
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent$name
|
||||
String pd_name = pd->name->Ident.token.string;
|
||||
isize name_len = proc->name.len + 1 + pd_name.len + 1;
|
||||
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
||||
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$%.*s", LIT(proc->name), LIT(pd_name));
|
||||
String name = make_string(name_text, name_len-1);
|
||||
if (pd->body != NULL) {
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent$name-guid
|
||||
String pd_name = pd->name->Ident.token.string;
|
||||
isize name_len = proc->name.len + 1 + pd_name.len + 1 + 10 + 1;
|
||||
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
||||
i32 guid = cast(i32)gb_array_count(proc->children);
|
||||
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$%.*s-%d", LIT(proc->name), LIT(pd_name), guid);
|
||||
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);
|
||||
Entity *e = *found;
|
||||
ssaValue *value = ssa_make_value_procedure(proc->module->allocator,
|
||||
proc->module, e->type, pd->type, pd->body, name);
|
||||
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(pd->name));
|
||||
GB_ASSERT(found != NULL);
|
||||
Entity *e = *found;
|
||||
ssaValue *value = ssa_make_value_procedure(proc->module->allocator,
|
||||
proc->module, e->type, pd->type, pd->body, name);
|
||||
|
||||
ssa_module_add_value(proc->module, e, value);
|
||||
gb_array_append(proc->children, &value->proc);
|
||||
ssa_build_proc(value, proc);
|
||||
ssa_module_add_value(proc->module, e, value);
|
||||
gb_array_append(proc->children, &value->proc);
|
||||
ssa_build_proc(value, proc);
|
||||
} else {
|
||||
String name = pd->name->Ident.token.string;
|
||||
|
||||
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(pd->name));
|
||||
GB_ASSERT(found != NULL);
|
||||
Entity *e = *found;
|
||||
ssaValue *value = ssa_make_value_procedure(proc->module->allocator,
|
||||
proc->module, e->type, pd->type, pd->body, name);
|
||||
ssa_module_add_value(proc->module, e, value);
|
||||
gb_array_append(proc->children, &value->proc);
|
||||
ssa_build_proc(value, proc);
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(td, TypeDecl, node);
|
||||
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent_proc.name
|
||||
// parent_proc.name-guid
|
||||
String td_name = td->name->Ident.token.string;
|
||||
isize name_len = proc->name.len + 1 + td_name.len + 1;
|
||||
isize name_len = proc->name.len + 1 + td_name.len + 1 + 10 + 1;
|
||||
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
||||
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s", LIT(proc->name), LIT(td_name));
|
||||
i32 guid = cast(i32)gb_array_count(proc->module->nested_type_names);
|
||||
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(td_name), guid);
|
||||
String name = make_string(name_text, name_len-1);
|
||||
|
||||
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(td->name));
|
||||
|
||||
@@ -39,6 +39,8 @@ int main(int argc, char **argv) {
|
||||
ssa_gen_code(&ssa);
|
||||
|
||||
success = 0;
|
||||
} else {
|
||||
gb_printf("Failed to build: %s\n", init_filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1212,16 +1212,13 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) {
|
||||
i32 op_prec = token_precedence(op);
|
||||
if (op_prec != prec)
|
||||
break;
|
||||
if (op.kind != Token_as) {
|
||||
expect_operator(f); // NOTE(bill): error checks too
|
||||
}
|
||||
expect_operator(f); // NOTE(bill): error checks too
|
||||
if (lhs) {
|
||||
// TODO(bill): error checking
|
||||
lhs = false;
|
||||
}
|
||||
|
||||
if (op.kind == Token_as) {
|
||||
next_token(f);
|
||||
if (op.kind == Token_as || op.kind == Token_transmute) {
|
||||
right = parse_type(f);
|
||||
} else {
|
||||
right = parse_binary_expr(f, false, prec+1);
|
||||
|
||||
@@ -54,7 +54,10 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \
|
||||
TOKEN_KIND(Token_AndNot, "&~"), \
|
||||
TOKEN_KIND(Token_Shl, "<<"), \
|
||||
TOKEN_KIND(Token_Shr, ">>"), \
|
||||
\
|
||||
TOKEN_KIND(Token_as, "as"), \
|
||||
TOKEN_KIND(Token_transmute, "transmute"), \
|
||||
\
|
||||
TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \
|
||||
TOKEN_KIND(Token_AddEq, "+="), \
|
||||
TOKEN_KIND(Token_SubEq, "-="), \
|
||||
@@ -101,23 +104,23 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
|
||||
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
|
||||
\
|
||||
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_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_struct, "struct"), \
|
||||
TOKEN_KIND(Token_union, "union"), \
|
||||
TOKEN_KIND(Token_enum, "enum"), \
|
||||
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_struct, "struct"), \
|
||||
TOKEN_KIND(Token_union, "union"), \
|
||||
TOKEN_KIND(Token_enum, "enum"), \
|
||||
TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \
|
||||
TOKEN_KIND(Token_Count, "")
|
||||
|
||||
@@ -225,6 +228,7 @@ i32 token_precedence(Token t) {
|
||||
case Token_Shr:
|
||||
return 5;
|
||||
case Token_as:
|
||||
case Token_transmute:
|
||||
return 6;
|
||||
}
|
||||
|
||||
@@ -645,6 +649,8 @@ Token tokenizer_get_token(Tokenizer *t) {
|
||||
if (token.string.len > 1) {
|
||||
if (are_strings_equal(token.string, token_strings[Token_as])) {
|
||||
token.kind = Token_as;
|
||||
} else if (are_strings_equal(token.string, token_strings[Token_transmute])) {
|
||||
token.kind = Token_transmute;
|
||||
} else {
|
||||
for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) {
|
||||
if (are_strings_equal(token.string, token_strings[k])) {
|
||||
@@ -730,6 +736,7 @@ Token tokenizer_get_token(Tokenizer *t) {
|
||||
if (valid && len != 1)
|
||||
tokenizer_err(t, "Illegal rune literal");
|
||||
token.string.len = t->curr - token.string.text;
|
||||
|
||||
i32 success = unquote_string(gb_heap_allocator(), &token.string);
|
||||
if (success > 0) {
|
||||
if (success == 2) {
|
||||
|
||||
Reference in New Issue
Block a user