From b59a052e32b1ed84134e31baad86c8e401f796c6 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Wed, 25 Jan 2017 19:19:25 +0000 Subject: [PATCH] Change casting syntax: `cast(T)x` `transmute(T)x` et al. --- code/demo.odin | 6 - core/_preload.odin | 23 +-- core/fmt.odin | 186 ++++++++++---------- core/hash.odin | 62 +++---- core/math.odin | 24 ++- core/mem.odin | 24 +-- core/opengl.odin | 4 +- core/os_windows.odin | 64 +++---- core/sync.odin | 4 +- core/sys/windows.odin | 8 +- core/utf8.odin | 40 ++--- src/check_decl.c | 2 - src/check_expr.c | 390 ++++++++++++++++++++++-------------------- src/check_stmt.c | 21 ++- src/checker.c | 55 +++--- src/common.c | 11 ++ src/entity.c | 4 +- src/ir.c | 123 +++++++------ src/ir_opt.c | 3 - src/ir_print.c | 10 -- src/main.c | 3 +- src/parser.c | 119 +++++++++++-- src/tokenizer.c | 5 +- src/types.c | 4 +- 24 files changed, 655 insertions(+), 540 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index a4081e139..6d57f5440 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -9,14 +9,8 @@ #import "sync.odin"; #import "utf8.odin"; -T :: struct { x, y: int }; -thread_local t: T; main :: proc() { - immutable using t := T{123, 321}; - fmt.println(t); - - // foo :: proc(x: ^i32) -> (int, int) { // fmt.println("^int"); // return 123, int(x^); diff --git a/core/_preload.odin b/core/_preload.odin index 54a3d178f..6199d6e4d 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -91,6 +91,10 @@ Type_Info :: union { }, } +// // NOTE(bill): only the ones that are needed (not all types) +// // This will be set by the compiler +// immutable __type_infos: []Type_Info; + type_info_base :: proc(info: ^Type_Info) -> ^Type_Info { if info == nil { return nil; @@ -111,21 +115,6 @@ __debug_trap :: proc() #foreign "llvm.debugtrap" __trap :: proc() #foreign "llvm.trap" read_cycle_counter :: proc() -> u64 #foreign "llvm.readcyclecounter" -bit_reverse :: proc(b: u16) -> u16 #foreign "llvm.bitreverse.i16" -bit_reverse :: proc(b: u32) -> u32 #foreign "llvm.bitreverse.i32" -bit_reverse :: proc(b: u64) -> u64 #foreign "llvm.bitreverse.i64" - -byte_swap :: proc(b: u16) -> u16 #foreign "llvm.bswap.i16" -byte_swap :: proc(b: u32) -> u32 #foreign "llvm.bswap.i32" -byte_swap :: proc(b: u64) -> u64 #foreign "llvm.bswap.i64" - -fmuladd :: proc(a, b, c: f32) -> f32 #foreign "llvm.fmuladd.f32" -fmuladd :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64" - - - - - Allocator_Mode :: enum u8 { ALLOC, @@ -297,11 +286,11 @@ __string_eq :: proc(a, b: string) -> bool { if a.data == b.data { return true; } - return mem.compare(rawptr(a.data), rawptr(b.data), a.count) == 0; + return mem.compare(cast(rawptr)a.data, cast(rawptr)b.data, a.count) == 0; } __string_cmp :: proc(a, b: string) -> int { - return mem.compare(rawptr(a.data), rawptr(b.data), min(a.count, b.count)); + return mem.compare(cast(rawptr)a.data, cast(rawptr)b.data, min(a.count, b.count)); } __string_ne :: proc(a, b: string) -> bool #inline { return !__string_eq(a, b); } diff --git a/core/fmt.odin b/core/fmt.odin index d23fca9ce..3baa031ca 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -19,7 +19,7 @@ buffer_write :: proc(buf: ^Buffer, b: []byte) { } } buffer_write_string :: proc(buf: ^Buffer, s: string) { - buffer_write(buf, []byte(s)); + buffer_write(buf, cast([]byte)s); } buffer_write_byte :: proc(buf: ^Buffer, b: byte) { if buf.length < buf.data.count { @@ -29,7 +29,7 @@ buffer_write_byte :: proc(buf: ^Buffer, b: byte) { } buffer_write_rune :: proc(buf: ^Buffer, r: rune) { if r < utf8.RUNE_SELF { - buffer_write_byte(buf, byte(r)); + buffer_write_byte(buf, cast(byte)r); return; } @@ -117,7 +117,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { default: buffer_write_string(buf, if info.signed { give "i" } else { give "u"}); fi := Fmt_Info{buf = buf}; - fmt_int(^fi, u64(8*info.size), false, 'd'); + fmt_int(^fi, cast(u64)(8*info.size), false, 'd'); } case Float: @@ -142,7 +142,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { if info.params == nil { buffer_write_string(buf, "()"); } else { - count := (^Tuple)(info.params).fields.count; + count := (cast(^Tuple)info.params).fields.count; if count == 1 { buffer_write_string(buf, "("); } buffer_write_type(buf, info.params); if count == 1 { buffer_write_string(buf, ")"); } @@ -170,7 +170,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { case Array: buffer_write_string(buf, "["); fi := Fmt_Info{buf = buf}; - fmt_int(^fi, u64(info.count), false, 'd'); + fmt_int(^fi, cast(u64)info.count, false, 'd'); buffer_write_string(buf, "]"); buffer_write_type(buf, info.elem); case Slice: @@ -180,7 +180,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { case Vector: buffer_write_string(buf, "[vector "); fi := Fmt_Info{buf = buf}; - fmt_int(^fi, u64(info.count), false, 'd'); + fmt_int(^fi, cast(u64)info.count, false, 'd'); buffer_write_string(buf, "]"); buffer_write_type(buf, info.elem); @@ -221,7 +221,6 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { buffer_write_string(buf, "enum "); buffer_write_type(buf, info.base); buffer_write_string(buf, " {}"); - } } @@ -307,14 +306,14 @@ parse_int :: proc(s: string, offset: int) -> (int, int, bool) { i := 0; for _ : offset.. (int, int, bool) { arg.type_info = type_info_base(arg.type_info); match type i : arg { case int: num = i; - case i8: num = int(i); - case i16: num = int(i); - case i32: num = int(i); - case i64: num = int(i); - case u8: num = int(i); - case u16: num = int(i); - case u32: num = int(i); - case u64: num = int(i); + case i8: num = cast(int)i; + case i16: num = cast(int)i; + case i32: num = cast(int)i; + case i64: num = cast(int)i; + case u8: num = cast(int)i; + case u16: num = cast(int)i; + case u32: num = cast(int)i; + case u64: num = cast(int)i; default: ok = false; } @@ -421,7 +420,7 @@ fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) { } fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: string) { - negative := signed && i64(u) < 0; + negative := signed && cast(i64)u < 0; if negative { u = -u; } @@ -461,7 +460,7 @@ fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: stri panic("fmt_integer: unknown base, whoops"); } - while b := u64(base); u >= b { + while b := cast(u64)base; u >= b { i -= 1; next := u / b; buf[i] = digits[u%b]; @@ -504,7 +503,7 @@ fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: stri if !fi.width_set || fi.width == 0 { buffer_write(fi.buf, buf[i:]); } else { - width := fi.width - utf8.rune_count(string(buf[i:])); + width := fi.width - utf8.rune_count(cast(string)buf[i:]); if fi.minus { // Right pad buffer_write(fi.buf, buf[i:]); @@ -533,9 +532,9 @@ fmt_int :: proc(fi: ^Fmt_Info, u: u64, signed: bool, verb: rune) { case 'd': fmt_integer(fi, u, 10, signed, __DIGITS_LOWER); case 'x': fmt_integer(fi, u, 16, signed, __DIGITS_LOWER); case 'X': fmt_integer(fi, u, 16, signed, __DIGITS_UPPER); - case 'c': fmt_rune(fi, rune(u)); + case 'c': fmt_rune(fi, cast(rune)u); case 'U': - r := rune(u); + r := cast(rune)u; if r < 0 || r > utf8.MAX_RUNE { fmt_bad_verb(fi, verb); } else { @@ -566,24 +565,24 @@ __TEN_TO_19TH :: 1000000000000000000; __ddmulthi :: proc(ol: f64, xh, yh: f64) -> f64 { bt: i64; oh := xh * yh; - bt = transmute(i64, xh); - bt &= i64(~u64(0)<<27); - ahi := transmute(f64, bt); + bt = transmute(i64)xh; + bt &= cast(i64)(~cast(u64)0<<27); + ahi := transmute(f64)bt; alo := xh-ahi; - bt = transmute(i64, yh); - bt &= i64(~u64(0)<<27); - bhi := transmute(f64, bt); + bt = transmute(i64)yh; + bt &= cast(i64)(~cast(u64)0<<27); + bhi := transmute(f64)bt; blo := yh-bhi; return ((ahi*bhi-oh)+ahi*blo+alo*bhi)+alo*blo; } __ddtoi64 :: proc(xh, xl: f64) -> i64 { - ob := i64(xh); - vh := f64(ob); + ob := cast(i64)xh; + vh := cast(f64)ob; ahi := xh-vh; t := ahi-xh; alo := (xh-(ahi-t)) - (vh+t); - ob += i64(ahi+alo+xl); + ob += cast(i64)(ahi+alo+xl); return ob; } @@ -670,9 +669,9 @@ __real_to_string :: proc(start: ^string, out: []byte, decimal_pos: ^i32, val: f6 e, tens: i32; d: f64 = val; - bits := transmute(i64, d); - expo := i32(bits>>52 & 2047); - neg := i32(bits>>63) != 0; + bits := transmute(i64)d; + expo := cast(i32)(bits>>52 & 2047); + neg := cast(i32)(bits>>63) != 0; if neg { d = -d; } @@ -692,7 +691,7 @@ __real_to_string :: proc(start: ^string, out: []byte, decimal_pos: ^i32, val: f6 if bits<<1 == 0 { decimal_pos^ = 1; out[0] = '0'; - start^ = string(out[:1]); + start^ = cast(string)out[:1]; return neg; } // find the right expo for denormals @@ -721,7 +720,7 @@ __real_to_string :: proc(start: ^string, out: []byte, decimal_pos: ^i32, val: f6 bits = __ddtoi64(ph, pl); // check if we undershot - if f64(bits) >= __TEN_TO_19TH { + if cast(f64)bits >= __TEN_TO_19TH { tens += 1; } } @@ -737,10 +736,10 @@ __real_to_string :: proc(start: ^string, out: []byte, decimal_pos: ^i32, val: f6 if frac_digits < 24 { skip := false; dg: u32 = 1; - if u64(bits) >= __powten[9] { + if cast(u64)bits >= __powten[9] { dg = 10; } - while u64(bits) >= __powten[dg] { + while cast(u64)bits >= __powten[dg] { dg += 1; if dg == 20 { skip = true; @@ -751,14 +750,14 @@ __real_to_string :: proc(start: ^string, out: []byte, decimal_pos: ^i32, val: f6 if (!skip) { r: u64; // add 0.5 at the right position and round - e = i32(dg) - frac_digits; - if u32(e) < 24 { + e = cast(i32)dg - frac_digits; + if cast(u32)e < 24 { r = __powten[e]; - bits += i64(r/2); - if u64(bits) >= __powten[dg] { + bits += cast(i64)(r/2); + if cast(u64)bits >= __powten[dg] { tens += 1; } - bits /= i64(r); + bits /= cast(i64)(r); } } } @@ -777,11 +776,11 @@ __real_to_string :: proc(start: ^string, out: []byte, decimal_pos: ^i32, val: f6 bits /= 1000; } if !skip { - n := u32(bits); + n := cast(u32)bits; while n%1000 == 0 { n /= 1000; } - bits = i64(n); + bits = cast(i64)n; } } @@ -793,15 +792,15 @@ __real_to_string :: proc(start: ^string, out: []byte, decimal_pos: ^i32, val: f6 o := outp-8; // do the conversion in chunks of u32s (avoid most 64-bit divides, worth it, constant denomiators be damned) if bits >= 100000000 { - n = u32(bits%100000000); + n = cast(u32)(bits%100000000); bits /= 100000000; } else { - n = u32(bits); + n = cast(u32)bits; bits = 0; } while n != 0 { outp -= 2; - (^u16)(outp)^ = (^u16)(^__digitpair[(n%100)*2])^; + (cast(^u16)outp)^ = (cast(^u16)^__digitpair[(n%100)*2])^; n /= 100; e += 2; } @@ -820,7 +819,7 @@ __real_to_string :: proc(start: ^string, out: []byte, decimal_pos: ^i32, val: f6 } decimal_pos^ = tens; - start^ = string(slice_ptr(outp, e)); + start^ = cast(string)slice_ptr(outp, e); return neg; } @@ -839,18 +838,18 @@ generic_ftoa :: proc(buf: []byte, val: f64, verb: rune, prec, bit_size: int) -> flt: ^Float_Info; match bit_size { case 32: - bits = u64(transmute(u32, f32(val))); + bits = cast(u64)transmute(u32)cast(f32)val; flt = ^f32info; case 64: - bits = u64(val); + bits = cast(u64)val; flt = ^f64info; default: panic("illegal float bit_size"); } neg := bits>>(flt.expbits+flt.mantbits) != 0; - exp := int(bits>>flt.mantbits) & (1<>flt.mantbits) & (1< case neg: s = "-Inf"; default: s = "+Inf"; } - copy(buf, []byte(s)); + copy(buf, cast([]byte)s); return buf[:s.count]; case 0: // denormalized exp+=1; default: // add implicit top bit - mant |= u64(1)< 0 { buffer_write_string(fi.buf, ", "); } data := slice.data + i*info.elem_size; - fmt_arg(fi, any{info.elem, rawptr(data)}, 'v'); + fmt_arg(fi, any{info.elem, cast(rawptr)data}, 'v'); } case Vector: @@ -1106,8 +1104,8 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { buffer_write_string(fi.buf, ", "); } - data := (^byte)(v.data) + i*info.elem_size; - fmt_value(fi, any{info.elem, rawptr(data)}, 'v'); + data := cast(^byte)v.data + i*info.elem_size; + fmt_value(fi, any{info.elem, cast(rawptr)data}, 'v'); } case Struct: @@ -1120,9 +1118,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { } buffer_write_string(fi.buf, f.name); buffer_write_string(fi.buf, " = "); - data := (^byte)(v.data) + f.offset; + data := cast(^byte)v.data + f.offset; ti := f.type_info; - fmt_value(fi, any{ti, rawptr(data)}, 'v'); + fmt_value(fi, any{ti, cast(rawptr)data}, 'v'); } case Union: @@ -1136,7 +1134,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { case Procedure: buffer_write_type(fi.buf, v.type_info); buffer_write_string(fi.buf, " @ "); - fmt_pointer(fi, (^rawptr)(v.data)^, 'p'); + fmt_pointer(fi, (cast(^rawptr)v.data)^, 'p'); } } @@ -1161,19 +1159,19 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { base_arg.type_info = type_info_base(base_arg.type_info); match type a : base_arg { case bool: fmt_bool(fi, a, verb); - case f32: fmt_float(fi, f64(a), 32, verb); + case f32: fmt_float(fi, cast(f64)a, 32, verb); case f64: fmt_float(fi, a, 64, verb); - case int: fmt_int(fi, u64(a), true, verb); - case i8: fmt_int(fi, u64(a), true, verb); - case i16: fmt_int(fi, u64(a), true, verb); - case i32: fmt_int(fi, u64(a), true, verb); - case i64: fmt_int(fi, u64(a), true, verb); - case uint: fmt_int(fi, u64(a), false, verb); - case u8: fmt_int(fi, u64(a), false, verb); - case u16: fmt_int(fi, u64(a), false, verb); - case u32: fmt_int(fi, u64(a), false, verb); - case u64: fmt_int(fi, u64(a), false, verb); + case int: fmt_int(fi, cast(u64)a, true, verb); + case i8: fmt_int(fi, cast(u64)a, true, verb); + case i16: fmt_int(fi, cast(u64)a, true, verb); + case i32: fmt_int(fi, cast(u64)a, true, verb); + case i64: fmt_int(fi, cast(u64)a, true, verb); + case uint: fmt_int(fi, cast(u64)a, false, verb); + case u8: fmt_int(fi, cast(u64)a, false, verb); + case u16: fmt_int(fi, cast(u64)a, false, verb); + case u32: fmt_int(fi, cast(u64)a, false, verb); + case u64: fmt_int(fi, cast(u64)a, false, verb); case string: fmt_string(fi, a, verb); default: fmt_value(fi, arg, verb); } diff --git a/core/hash.odin b/core/hash.odin index e9ca2c5f3..01875442d 100644 --- a/core/hash.odin +++ b/core/hash.odin @@ -1,58 +1,58 @@ crc32 :: proc(data: rawptr, len: int) -> u32 { - result := ~u32(0); - s := slice_ptr((^u8)(data), len); + result := ~cast(u32)0; + s := slice_ptr(cast(^u8)data, len); for i : 0..>8 ~ __CRC32_TABLE[(result ~ b) & 0xff]; } return ~result; } crc64 :: proc(data: rawptr, len: int) -> u64 { - result := ~u64(0); - s := slice_ptr((^u8)(data), len); + result := ~cast(u64)0; + s := slice_ptr(cast(^u8)data, len); for i : 0..>8 ~ __CRC64_TABLE[(result ~ b) & 0xff]; } return ~result; } fnv32 :: proc(data: rawptr, len: int) -> u32 { - s := slice_ptr((^u8)(data), len); + s := slice_ptr(cast(^u8)data, len); h: u32 = 0x811c9dc5; for i : 0.. u64 { - s := slice_ptr((^u8)(data), len); + s := slice_ptr(cast(^u8)data, len); h: u64 = 0xcbf29ce484222325; for i : 0.. u32 { - s := slice_ptr((^u8)(data), len); + s := slice_ptr(cast(^u8)data, len); h: u32 = 0x811c9dc5; for i : 0.. u64 { - s := slice_ptr((^u8)(data), len); + s := slice_ptr(cast(^u8)data, len); h :u64 = 0xcbf29ce484222325; for i : 0.. u64 { m :: 0xc6a4a7935bd1e995; r :: 47; - h: u64 = SEED ~ (u64(len) * m); + h: u64 = SEED ~ (cast(u64)len * m); - data := slice_ptr((^u64)(data_), len/size_of(u64)); - data2 := slice_ptr((^u8)(data_), len); + data := slice_ptr(cast(^u64)data_, len/size_of(u64)); + data2 := slice_ptr(cast(^u8)data_, len); for i : 0 ..< data.count { k := data[i]; @@ -82,14 +82,14 @@ murmur64 :: proc(data_: rawptr, len: int) -> u64 { } match len & 7 { - case 7: h ~= u64(data2[6]) << 48; fallthrough; - case 6: h ~= u64(data2[5]) << 40; fallthrough; - case 5: h ~= u64(data2[4]) << 32; fallthrough; - case 4: h ~= u64(data2[3]) << 24; fallthrough; - case 3: h ~= u64(data2[2]) << 16; fallthrough; - case 2: h ~= u64(data2[1]) << 8; fallthrough; + case 7: h ~= cast(u64)data2[6] << 48; fallthrough; + case 6: h ~= cast(u64)data2[5] << 40; fallthrough; + case 5: h ~= cast(u64)data2[4] << 32; fallthrough; + case 4: h ~= cast(u64)data2[3] << 24; fallthrough; + case 3: h ~= cast(u64)data2[2] << 16; fallthrough; + case 2: h ~= cast(u64)data2[1] << 8; fallthrough; case 1: - h ~= u64(data2[0]); + h ~= cast(u64)data2[0]; h *= m; } @@ -102,10 +102,10 @@ murmur64 :: proc(data_: rawptr, len: int) -> u64 { m :: 0x5bd1e995; r :: 24; - h1: u32 = u32(SEED) ~ u32(len); + h1: u32 = cast(u32)SEED ~ cast(u32)len; h2: u32 = SEED >> 32; - data := slice_ptr((^u32)(data_), len/size_of(u32)); + data := slice_ptr(cast(^u32)data_, len/size_of(u32)); i := 0; while len >= 8 { @@ -138,13 +138,13 @@ murmur64 :: proc(data_: rawptr, len: int) -> u64 { len -= 4; } - data8 := slice_ptr((^u8)(data.data+i), 3); // NOTE(bill): This is unsafe + data8 := slice_ptr(cast(^u8)(data.data+i), 3); // NOTE(bill): This is unsafe match len { - case 3: h2 ~= u32(data8[2]) << 16; fallthrough; - case 2: h2 ~= u32(data8[1]) << 8; fallthrough; + case 3: h2 ~= cast(u32)data8[2] << 16; fallthrough; + case 2: h2 ~= cast(u32)data8[1] << 8; fallthrough; case 1: - h2 ~= u32(data8[0]); + h2 ~= cast(u32)data8[0]; h2 *= m; } @@ -157,7 +157,7 @@ murmur64 :: proc(data_: rawptr, len: int) -> u64 { h2 ~= h1>>19; h2 *= m; - h := u64(h1)<<32 | u64(h2); + h := cast(u64)(h1)<<32 | cast(u64)(h2); return h; } } diff --git a/core/math.odin b/core/math.odin index 479fe920b..f89c004aa 100644 --- a/core/math.odin +++ b/core/math.odin @@ -42,14 +42,24 @@ lerp :: proc(a, b, t: f64) -> f64 { return a*(1-t) + b*t; } sign :: proc(x: f32) -> f32 { if x >= 0 { return +1; } return -1; } sign :: proc(x: f64) -> f64 { if x >= 0 { return +1; } return -1; } +bit_reverse :: proc(b: u16) -> u16 #foreign "llvm.bitreverse.i16" +bit_reverse :: proc(b: u32) -> u32 #foreign "llvm.bitreverse.i32" +bit_reverse :: proc(b: u64) -> u64 #foreign "llvm.bitreverse.i64" + +byte_swap :: proc(b: u16) -> u16 #foreign "llvm.bswap.i16" +byte_swap :: proc(b: u32) -> u32 #foreign "llvm.bswap.i32" +byte_swap :: proc(b: u64) -> u64 #foreign "llvm.bswap.i64" + +fmuladd :: proc(a, b, c: f32) -> f32 #foreign "llvm.fmuladd.f32" +fmuladd :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64" copy_sign :: proc(x, y: f32) -> f32 { - ix := transmute(u32, x); - iy := transmute(u32, y); + ix := transmute(u32)x; + iy := transmute(u32)y; ix &= 0x7fffffff; ix |= iy & 0x80000000; - return transmute(f32, ix); + return transmute(f32)ix; } round :: proc(x: f32) -> f32 { if x >= 0 { @@ -59,15 +69,15 @@ round :: proc(x: f32) -> f32 { } floor :: proc(x: f32) -> f32 { if x >= 0 { - return f32(int(x)); + return cast(f32)cast(int)x; } - return f32(int(x-0.5)); + return cast(f32)cast(int)(x-0.5); } ceil :: proc(x: f32) -> f32 { if x < 0 { - return f32(int(x)); + return cast(f32)cast(int)x; } - return f32(int(x)+1); + return cast(f32)cast(int)(x+1); } remainder32 :: proc(x, y: f32) -> f32 { diff --git a/core/mem.odin b/core/mem.odin index 3aee897e8..79248ca77 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -3,7 +3,7 @@ set :: proc(data: rawptr, value: i32, len: int) -> rawptr #link_name "__mem_set" { llvm_memset_64bit :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) #foreign "llvm.memset.p0i8.i64" - llvm_memset_64bit(data, byte(value), len, 1, false); + llvm_memset_64bit(data, cast(byte)value, len, 1, false); return data; } @@ -26,8 +26,8 @@ copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "_ } compare :: proc(dst, src: rawptr, n: int) -> int #link_name "__mem_compare" { - a := slice_ptr((^byte)(dst), n); - b := slice_ptr((^byte)(src), n); + a := slice_ptr(cast(^byte)dst, n); + b := slice_ptr(cast(^byte)src, n); for i : 0.. bool { align_forward :: proc(ptr: rawptr, align: int) -> rawptr { assert(is_power_of_two(align)); - a := uint(align); - p := uint(ptr); + a := cast(uint)align; + p := cast(uint)ptr; modulo := p & (a-1); if modulo != 0 { p += a - modulo; } - return rawptr(p); + return cast(rawptr)p; } @@ -73,19 +73,19 @@ Allocation_Header :: struct { allocation_header_fill :: proc(header: ^Allocation_Header, data: rawptr, size: int) { header.size = size; - ptr := (^int)(header+1); + ptr := cast(^int)(header+1); - while i := 0; rawptr(ptr) < data { + while i := 0; cast(rawptr)ptr < data { (ptr+i)^ = -1; i += 1; } } allocation_header :: proc(data: rawptr) -> ^Allocation_Header { - p := (^int)(data); + p := cast(^int)data; while (p-1)^ == -1 { p = (p-1); } - return (^Allocation_Header)(p)-1; + return cast(^Allocation_Header)p-1; } @@ -142,7 +142,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, flags: u64) -> rawptr { using Allocator_Mode; - arena := (^Arena)(allocator_data); + arena := cast(^Arena)allocator_data; match mode { case ALLOC: @@ -235,7 +235,7 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int { return WORD_SIZE; case Vector: size := size_of_type_info(info.elem); - count := int(max(prev_pow2(i64(info.count)), 1)); + count := cast(int)max(prev_pow2(cast(i64)info.count), 1); total := size * count; return clamp(total, 1, MAX_ALIGN); case Struct: diff --git a/core/opengl.odin b/core/opengl.odin index 499a28333..2b357d63c 100644 --- a/core/opengl.odin +++ b/core/opengl.odin @@ -30,7 +30,7 @@ GetIntegerv :: proc(name: i32, v: ^i32) #foreign "glGetIntegerv" -_libgl := win32.LoadLibraryA(string("opengl32.dll\x00").data); +_libgl := win32.LoadLibraryA((cast(string)"opengl32.dll\x00").data); GetProcAddress :: proc(name: string) -> proc() #cc_c { assert(name[name.count-1] == 0); @@ -100,7 +100,7 @@ UniformMatrix4fv: proc(loc: i32, count: u32, transpose: i32, value: ^f32) #cc_c GetUniformLocation: proc(program: u32, name: ^byte) -> i32 #cc_c; init :: proc() { - set_proc_address :: proc(p: rawptr, name: string) #inline { (^(proc() #cc_c))(p)^ = GetProcAddress(name); } + set_proc_address :: proc(p: rawptr, name: string) #inline { (cast(^(proc() #cc_c))p)^ = GetProcAddress(name); } set_proc_address(^GenBuffers, "glGenBuffers\x00"); set_proc_address(^GenVertexArrays, "glGenVertexArrays\x00"); diff --git a/core/os_windows.odin b/core/os_windows.odin index fa77e63cf..0dfcebe4a 100644 --- a/core/os_windows.odin +++ b/core/os_windows.odin @@ -73,7 +73,7 @@ open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) { access |= FILE_APPEND_DATA; } - share_mode := u32(FILE_SHARE_READ|FILE_SHARE_WRITE); + share_mode := cast(u32)(FILE_SHARE_READ|FILE_SHARE_WRITE); sa: ^SECURITY_ATTRIBUTES = nil; sa_inherit := SECURITY_ATTRIBUTES{length = size_of(SECURITY_ATTRIBUTES), inherit_handle = 1}; if mode&O_CLOEXEC == 0 { @@ -95,38 +95,38 @@ open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) { } buf: [300]byte; - copy(buf[:], []byte(path)); + copy(buf[:], cast([]byte)path); - handle := Handle(CreateFileA(^buf[0], access, share_mode, sa, create_mode, FILE_ATTRIBUTE_NORMAL, nil)); + handle := cast(Handle)CreateFileA(^buf[0], access, share_mode, sa, create_mode, FILE_ATTRIBUTE_NORMAL, nil); if handle != INVALID_HANDLE { return handle, ERROR_NONE; } err := GetLastError(); - return INVALID_HANDLE, Errno(err); + return INVALID_HANDLE, cast(Errno)err; } close :: proc(fd: Handle) { - win32.CloseHandle(win32.HANDLE(fd)); + win32.CloseHandle(cast(win32.HANDLE)fd); } write :: proc(fd: Handle, data: []byte) -> (int, Errno) { bytes_written: i32; - e := win32.WriteFile(win32.HANDLE(fd), data.data, i32(data.count), ^bytes_written, nil); + e := win32.WriteFile(cast(win32.HANDLE)fd, data.data, cast(i32)data.count, ^bytes_written, nil); if e == win32.FALSE { err := win32.GetLastError(); - return 0, Errno(err); + return 0, cast(Errno)err; } - return int(bytes_written), ERROR_NONE; + return cast(int)bytes_written, ERROR_NONE; } read :: proc(fd: Handle, data: []byte) -> (int, Errno) { bytes_read: i32; - e := win32.ReadFile(win32.HANDLE(fd), data.data, u32(data.count), ^bytes_read, nil); + e := win32.ReadFile(cast(win32.HANDLE)fd, data.data, cast(u32)data.count, ^bytes_read, nil); if e == win32.FALSE { err := win32.GetLastError(); - return 0, Errno(err); + return 0, cast(Errno)err; } - return int(bytes_read), ERROR_NONE; + return cast(int)bytes_read, ERROR_NONE; } seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) { @@ -137,18 +137,18 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) { case 1: w = FILE_CURRENT; case 2: w = FILE_END; } - hi := i32(offset>>32); - lo := i32(offset); - ft := GetFileType(HANDLE(fd)); + hi := cast(i32)(offset>>32); + lo := cast(i32)(offset); + ft := GetFileType(cast(HANDLE)fd); if ft == FILE_TYPE_PIPE { return 0, ERROR_FILE_IS_PIPE; } - dw_ptr := SetFilePointer(HANDLE(fd), lo, ^hi, w); + dw_ptr := SetFilePointer(cast(HANDLE)fd, lo, ^hi, w); if dw_ptr == INVALID_SET_FILE_POINTER { err := GetLastError(); - return 0, Errno(err); + return 0, cast(Errno)err; } - return i64(hi)<<32 + i64(dw_ptr), ERROR_NONE; + return cast(i64)hi<<32 + cast(i64)dw_ptr, ERROR_NONE; } @@ -159,9 +159,9 @@ stderr := get_std_handle(win32.STD_ERROR_HANDLE); get_std_handle :: proc(h: int) -> Handle { - fd := win32.GetStdHandle(i32(h)); + fd := win32.GetStdHandle(cast(i32)h); win32.SetHandleInformation(fd, win32.HANDLE_FLAG_INHERIT, 0); - return Handle(fd); + return cast(Handle)fd; } @@ -171,9 +171,9 @@ get_std_handle :: proc(h: int) -> Handle { last_write_time :: proc(fd: Handle) -> File_Time { file_info: win32.BY_HANDLE_FILE_INFORMATION; - win32.GetFileInformationByHandle(win32.HANDLE(fd), ^file_info); - lo := File_Time(file_info.last_write_time.lo); - hi := File_Time(file_info.last_write_time.hi); + win32.GetFileInformationByHandle(cast(win32.HANDLE)fd, ^file_info); + lo := cast(File_Time)file_info.last_write_time.lo; + hi := cast(File_Time)file_info.last_write_time.hi; return lo | hi << 32; } @@ -184,14 +184,14 @@ last_write_time_by_name :: proc(name: string) -> File_Time { assert(buf.count > name.count); - copy(buf[:], []byte(name)); + copy(buf[:], cast([]byte)name); if win32.GetFileAttributesExA(^buf[0], win32.GetFileExInfoStandard, ^data) != 0 { last_write_time = data.last_write_time; } - l := File_Time(last_write_time.lo); - h := File_Time(last_write_time.hi); + l := cast(File_Time)last_write_time.lo; + h := cast(File_Time)last_write_time.hi; return l | h << 32; } @@ -201,7 +201,7 @@ last_write_time_by_name :: proc(name: string) -> File_Time { read_entire_file :: proc(name: string) -> ([]byte, bool) { buf: [300]byte; - copy(buf[:], []byte(name)); + copy(buf[:], cast([]byte)name); fd, err := open(name, O_RDONLY, 0); if err != ERROR_NONE { @@ -210,7 +210,7 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) { defer close(fd); length: i64; - file_size_ok := win32.GetFileSizeEx(win32.HANDLE(fd), ^length) != 0; + file_size_ok := win32.GetFileSizeEx(cast(win32.HANDLE)fd, ^length) != 0; if !file_size_ok { return nil, false; } @@ -228,18 +228,18 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) { to_read: u32; MAX :: 1<<32-1; if remaining <= MAX { - to_read = u32(remaining); + to_read = cast(u32)remaining; } else { to_read = MAX; } - win32.ReadFile(win32.HANDLE(fd), ^data[total_read], to_read, ^single_read_length, nil); + win32.ReadFile(cast(win32.HANDLE)fd, ^data[total_read], to_read, ^single_read_length, nil); if single_read_length <= 0 { free(data.data); return nil, false; } - total_read += i64(single_read_length); + total_read += cast(i64)single_read_length; } return data, true; @@ -259,14 +259,14 @@ heap_free :: proc(ptr: rawptr) { exit :: proc(code: int) { - win32.ExitProcess(u32(code)); + win32.ExitProcess(cast(u32)code); } current_thread_id :: proc() -> int { GetCurrentThreadId :: proc() -> u32 #foreign #dll_import - return int(GetCurrentThreadId()); + return cast(int)GetCurrentThreadId(); } diff --git a/core/sync.odin b/core/sync.odin index dbab820b4..e346c60d4 100644 --- a/core/sync.odin +++ b/core/sync.odin @@ -13,7 +13,7 @@ Mutex :: struct { } current_thread_id :: proc() -> i32 { - return i32(win32.GetCurrentThreadId()); + return cast(i32)win32.GetCurrentThreadId(); } semaphore_init :: proc(s: ^Semaphore) { @@ -25,7 +25,7 @@ semaphore_destroy :: proc(s: ^Semaphore) { } semaphore_post :: proc(s: ^Semaphore, count: int) { - win32.ReleaseSemaphore(s.handle, i32(count), nil); + win32.ReleaseSemaphore(s.handle, cast(i32)count, nil); } semaphore_release :: proc(s: ^Semaphore) #inline { semaphore_post(s, 1); } diff --git a/core/sys/windows.odin b/core/sys/windows.odin index e9c265231..28ad4df08 100644 --- a/core/sys/windows.odin +++ b/core/sys/windows.odin @@ -19,7 +19,7 @@ BOOL :: i32; WNDPROC :: type proc(HWND, u32, WPARAM, LPARAM) -> LRESULT #cc_c; -INVALID_HANDLE_VALUE :: HANDLE(~int(0)); +INVALID_HANDLE_VALUE :: cast(HANDLE)(~cast(int)0); FALSE: BOOL : 0; TRUE: BOOL : 1; @@ -46,7 +46,7 @@ WM_KEYUP :: 0x0101; PM_REMOVE :: 1; -COLOR_BACKGROUND :: HBRUSH(int(1)); +COLOR_BACKGROUND :: cast(HBRUSH)(cast(int)1); BLACK_BRUSH :: 4; SM_CXSCREEN :: 0; @@ -233,7 +233,7 @@ FILE_TYPE_DISK :: 0x0001; FILE_TYPE_CHAR :: 0x0002; FILE_TYPE_PIPE :: 0x0003; -INVALID_SET_FILE_POINTER :: ~u32(0); +INVALID_SET_FILE_POINTER :: ~cast(u32)0; @@ -402,7 +402,7 @@ wglDeleteContext :: proc(hglrc: HGLRC) -> BOOL #foreign #dll_import GetKeyState :: proc(v_key: i32) -> i16 #foreign #dll_import GetAsyncKeyState :: proc(v_key: i32) -> i16 #foreign #dll_import -is_key_down :: proc(key: Key_Code) -> bool #inline { return GetAsyncKeyState(i32(key)) < 0; } +is_key_down :: proc(key: Key_Code) -> bool #inline { return GetAsyncKeyState(cast(i32)key) < 0; } Key_Code :: enum i32 { LBUTTON = 0x01, diff --git a/core/utf8.odin b/core/utf8.odin index 1cd9f0d8c..a8dd3c19b 100644 --- a/core/utf8.odin +++ b/core/utf8.odin @@ -1,7 +1,7 @@ RUNE_ERROR :: '\ufffd'; RUNE_SELF :: 0x80; RUNE_BOM :: 0xfeff; -RUNE_EOF :: ~rune(0); +RUNE_EOF :: ~cast(rune)0; MAX_RUNE :: '\U0010ffff'; UTF_MAX :: 4; @@ -40,15 +40,15 @@ accept_sizes := [256]byte{ encode_rune :: proc(r: rune) -> ([4]byte, int) { buf: [4]byte; - i := u32(r); + i := cast(u32)r; mask: byte : 0x3f; if i <= 1<<7-1 { - buf[0] = byte(r); + buf[0] = cast(byte)r; return buf, 1; } if i <= 1<<11-1 { - buf[0] = 0xc0 | byte(r>>6); - buf[1] = 0x80 | byte(r) & mask; + buf[0] = 0xc0 | cast(byte)(r>>6); + buf[1] = 0x80 | cast(byte)r & mask; return buf, 2; } @@ -59,16 +59,16 @@ encode_rune :: proc(r: rune) -> ([4]byte, int) { } if i <= 1<<16-1 { - buf[0] = 0xe0 | byte(r>>12); - buf[1] = 0x80 | byte(r>>6) & mask; - buf[2] = 0x80 | byte(r) & mask; + buf[0] = 0xe0 | cast(byte)(r>>12); + buf[1] = 0x80 | cast(byte)(r>>6) & mask; + buf[2] = 0x80 | cast(byte)r & mask; return buf, 3; } - buf[0] = 0xf0 | byte(r>>18); - buf[1] = 0x80 | byte(r>>12) & mask; - buf[2] = 0x80 | byte(r>>6) & mask; - buf[3] = 0x80 | byte(r) & mask; + buf[0] = 0xf0 | cast(byte)(r>>18); + buf[1] = 0x80 | cast(byte)(r>>12) & mask; + buf[2] = 0x80 | cast(byte)(r>>6) & mask; + buf[3] = 0x80 | cast(byte)r & mask; return buf, 4; } @@ -80,12 +80,12 @@ decode_rune :: proc(s: string) -> (rune, int) { b0 := s[0]; x := accept_sizes[b0]; if x >= 0xf0 { - mask := (rune(x) << 31) >> 31; // all zeros or all ones - return rune(b0) &~ mask | RUNE_ERROR&mask, 1; + mask := (cast(rune)x << 31) >> 31; // all zeros or all ones + return cast(rune)b0 &~ mask | RUNE_ERROR&mask, 1; } size := x & 7; ar := accept_ranges[x>>4]; - if n < int(size) { + if n < cast(int)size { return RUNE_ERROR, 1; } b1 := s[1]; @@ -99,20 +99,20 @@ decode_rune :: proc(s: string) -> (rune, int) { MASK_4 :: 0b00000111; if size == 2 { - return rune(b0&MASK_2)<<6 | rune(b1&MASK_X), 2; + return cast(rune)(b0&MASK_2)<<6 | cast(rune)(b1&MASK_X), 2; } b2 := s[2]; if b2 < 0x80 || 0xbf < b2 { return RUNE_ERROR, 1; } if size == 3 { - return rune(b0&MASK_3)<<12 | rune(b1&MASK_X)<<6 | rune(b2&MASK_X), 3; + return cast(rune)(b0&MASK_3)<<12 | cast(rune)(b1&MASK_X)<<6 | cast(rune)(b2&MASK_X), 3; } b3 := s[3]; if b3 < 0x80 || 0xbf < b3 { return RUNE_ERROR, 1; } - return rune(b0&MASK_4)<<18 | rune(b1&MASK_X)<<12 | rune(b3&MASK_X)<<6 | rune(b3&MASK_X), 4; + return cast(rune)(b0&MASK_4)<<18 | cast(rune)(b1&MASK_X)<<12 | cast(rune)(b3&MASK_X)<<6 | cast(rune)(b3&MASK_X), 4; } @@ -141,7 +141,7 @@ valid_string :: proc(s: string) -> bool { if x == 0xf1 { return false; } - size := int(x & 7); + size := cast(int)(x & 7); if i+size > n { return false; } @@ -178,7 +178,7 @@ rune_count :: proc(s: string) -> int { i += 1; continue; } - size := int(x & 7); + size := cast(int)(x & 7); if i+size > n { i += 1; continue; diff --git a/src/check_decl.c b/src/check_decl.c index 600b4c0d6..a97b1b90e 100644 --- a/src/check_decl.c +++ b/src/check_decl.c @@ -372,8 +372,6 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count GB_ASSERT(e->type == NULL); GB_ASSERT(e->kind == Entity_Variable); - u32 flags = c->context.decl->var_decl_flags; - if (e->flags & EntityFlag_Visited) { e->type = t_invalid; return; diff --git a/src/check_expr.c b/src/check_expr.c index 4b26ca990..dd92fc38e 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -1094,10 +1094,10 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { if (ue->op.kind == Token_Pointer) { type = make_type_pointer(c->allocator, check_type(c, ue->expr)); goto end; - } else if (ue->op.kind == Token_Maybe) { + } /* else if (ue->op.kind == Token_Maybe) { type = make_type_maybe(c->allocator, check_type(c, ue->expr)); goto end; - } + } */ case_end; case_ast_node(ht, HelperType, e); @@ -1133,7 +1133,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { Type *elem = check_type(c, vt->elem); Type *be = base_type(elem); i64 count = check_array_count(c, vt->count); - if (!is_type_boolean(be) && !is_type_numeric(be)) { + if (is_type_vector(be) || (!is_type_boolean(be) && !is_type_numeric(be))) { err_str = type_to_string(elem); error_node(vt->elem, "Vector element type must be numerical or a boolean, got `%s`", err_str); } @@ -2589,10 +2589,6 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id case BuiltinProc_align_of: case BuiltinProc_offset_of: case BuiltinProc_type_info: - - case BuiltinProc_transmute: - case BuiltinProc_union_cast: - case BuiltinProc_down_cast: // NOTE(bill): The first arg may be a Type, this will be checked case by case break; default: @@ -2837,186 +2833,6 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id operand->type = t_type_info_ptr; } break; - - case BuiltinProc_transmute: { - Type *type = check_type(c, ce->args.e[0]); - check_expr(c, operand, ce->args.e[1]); - if (operand->mode == Addressing_Invalid) { - return false; - } - - if (operand->mode == Addressing_Constant) { - gbString expr_str = expr_to_string(operand->expr); - error_node(operand->expr, "Cannot transmute constant expression: `%s`", expr_str); - gb_string_free(expr_str); - operand->mode = Addressing_Invalid; - return false; - } - - if (is_type_untyped(operand->type)) { - gbString expr_str = expr_to_string(operand->expr); - error_node(operand->expr, "Cannot transmute untyped expression: `%s`", expr_str); - gb_string_free(expr_str); - operand->mode = Addressing_Invalid; - return false; - } - - i64 srcz = type_size_of(c->sizes, c->allocator, operand->type); - i64 dstz = type_size_of(c->sizes, c->allocator, type); - if (srcz != dstz) { - gbString expr_str = expr_to_string(operand->expr); - gbString type_str = type_to_string(type); - error_node(operand->expr, "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, srcz, dstz); - gb_string_free(type_str); - gb_string_free(expr_str); - operand->mode = Addressing_Invalid; - return false; - } - - operand->type = type; - } break; - case BuiltinProc_union_cast: { - Type *type = check_type(c, ce->args.e[0]); - check_expr(c, operand, ce->args.e[1]); - if (operand->mode == Addressing_Invalid) { - return false; - } - - if (operand->mode == Addressing_Constant) { - gbString expr_str = expr_to_string(operand->expr); - error_node(operand->expr, "Cannot `union_cast` a constant expression: `%s`", expr_str); - gb_string_free(expr_str); - operand->mode = Addressing_Invalid; - return false; - } - - if (is_type_untyped(operand->type)) { - gbString expr_str = expr_to_string(operand->expr); - error_node(operand->expr, "Cannot `union_cast` an untyped expression: `%s`", expr_str); - gb_string_free(expr_str); - operand->mode = Addressing_Invalid; - return false; - } - - bool src_is_ptr = is_type_pointer(operand->type); - bool dst_is_ptr = is_type_pointer(type); - Type *src = type_deref(operand->type); - Type *dst = type_deref(type); - Type *bsrc = base_type(src); - Type *bdst = base_type(dst); - - if (src_is_ptr != dst_is_ptr) { - gbString src_type_str = type_to_string(operand->type); - gbString dst_type_str = type_to_string(type); - error_node(operand->expr, "Invalid `union_cast` types: `%s` and `%s`", src_type_str, dst_type_str); - gb_string_free(dst_type_str); - gb_string_free(src_type_str); - operand->mode = Addressing_Invalid; - return false; - } - - if (!is_type_union(src)) { - error_node(operand->expr, "`union_cast` can only operate on unions"); - operand->mode = Addressing_Invalid; - return false; - } - - bool ok = false; - for (isize i = 1; i < bsrc->Record.field_count; i++) { - Entity *f = bsrc->Record.fields[i]; - if (are_types_identical(f->type, dst)) { - ok = true; - break; - } - } - - if (!ok) { - gbString expr_str = expr_to_string(operand->expr); - gbString dst_type_str = type_to_string(type); - error_node(operand->expr, "Cannot `union_cast` `%s` to `%s`", expr_str, dst_type_str); - gb_string_free(dst_type_str); - gb_string_free(expr_str); - operand->mode = Addressing_Invalid; - return false; - } - - Entity **variables = gb_alloc_array(c->allocator, Entity *, 2); - variables[0] = make_entity_param(c->allocator, NULL, empty_token, type, false, true); - variables[1] = make_entity_param(c->allocator, NULL, empty_token, t_bool, false, true); - - Type *tuple = make_type_tuple(c->allocator); - tuple->Tuple.variables = variables; - tuple->Tuple.variable_count = 2; - - operand->type = tuple; - operand->mode = Addressing_Value; - } break; - case BuiltinProc_down_cast: { - Type *type = check_type(c, ce->args.e[0]); - check_expr(c, operand, ce->args.e[1]); - if (operand->mode == Addressing_Invalid) { - return false; - } - - if (operand->mode == Addressing_Constant) { - gbString expr_str = expr_to_string(operand->expr); - error_node(operand->expr, "Cannot `down_cast` a constant expression: `%s`", expr_str); - gb_string_free(expr_str); - operand->mode = Addressing_Invalid; - return false; - } - - if (is_type_untyped(operand->type)) { - gbString expr_str = expr_to_string(operand->expr); - error_node(operand->expr, "Cannot `down_cast` an untyped expression: `%s`", expr_str); - gb_string_free(expr_str); - operand->mode = Addressing_Invalid; - return false; - } - - if (!(is_type_pointer(operand->type) && is_type_pointer(type))) { - gbString expr_str = expr_to_string(operand->expr); - error_node(operand->expr, "Can only `down_cast` pointers: `%s`", expr_str); - gb_string_free(expr_str); - operand->mode = Addressing_Invalid; - return false; - } - - Type *src = type_deref(operand->type); - Type *dst = type_deref(type); - Type *bsrc = base_type(src); - Type *bdst = base_type(dst); - - if (!(is_type_struct(bsrc) || is_type_raw_union(bsrc))) { - gbString expr_str = expr_to_string(operand->expr); - error_node(operand->expr, "Can only `down_cast` pointer from structs or unions: `%s`", expr_str); - gb_string_free(expr_str); - operand->mode = Addressing_Invalid; - return false; - } - - if (!(is_type_struct(bdst) || is_type_raw_union(bdst))) { - gbString expr_str = expr_to_string(operand->expr); - error_node(operand->expr, "Can only `down_cast` pointer to structs or unions: `%s`", expr_str); - gb_string_free(expr_str); - operand->mode = Addressing_Invalid; - return false; - } - - String param_name = check_down_cast_name(dst, src); - if (param_name.len == 0) { - gbString expr_str = expr_to_string(operand->expr); - error_node(operand->expr, "Illegal `down_cast`: `%s`", expr_str); - gb_string_free(expr_str); - operand->mode = Addressing_Invalid; - return false; - } - - operand->mode = Addressing_Value; - operand->type = type; - } break; - - case BuiltinProc_compile_assert: // compile_assert :: proc(cond: bool) @@ -3835,6 +3651,13 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { } if (operand->mode == Addressing_Type) { + gbString str = type_to_string(operand->type); + error_node(call, "Expected a procedure, got a type `%s`", str); + gb_string_free(str); + operand->mode = Addressing_Invalid; + operand->expr = call; + return Expr_Stmt; + #if 0 Type *t = operand->type; gbString str = type_to_string(t); operand->mode = Addressing_Invalid; @@ -3852,6 +3675,7 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { gb_string_free(str); return Expr_Expr; + #endif } if (operand->mode == Addressing_Builtin) { @@ -3909,6 +3733,17 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { return Expr_Stmt; } + +ExprKind check_macro_call_expr(Checker *c, Operand *operand, AstNode *call) { + GB_ASSERT(call->kind == AstNode_MacroCallExpr); + ast_node(mce, MacroCallExpr, call); + + error_node(call, "Macro call expressions are not yet supported"); + operand->mode = Addressing_Invalid; + operand->expr = call; + return Expr_Stmt; +} + void check_expr_with_type_hint(Checker *c, Operand *o, AstNode *e, Type *t) { check_expr_base(c, o, e, t); check_not_tuple(c, o); @@ -4563,6 +4398,183 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint o->expr = node; case_end; + case_ast_node(ce, CastExpr, node); + Type *t = check_type(c, ce->type); + check_expr(c, o, ce->expr); + if (o->mode == Addressing_Invalid) { + goto error; + } + switch (ce->token.kind) { + case Token_cast: + check_conversion(c, o, t); + break; + case Token_transmute: { + if (o->mode == Addressing_Constant) { + gbString expr_str = expr_to_string(o->expr); + error_node(o->expr, "Cannot transmute constant expression: `%s`", expr_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + goto error; + } + + if (is_type_untyped(o->type)) { + gbString expr_str = expr_to_string(o->expr); + error_node(o->expr, "Cannot transmute untyped expression: `%s`", expr_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + goto error; + } + + i64 srcz = type_size_of(c->sizes, c->allocator, o->type); + i64 dstz = type_size_of(c->sizes, c->allocator, t); + if (srcz != dstz) { + gbString expr_str = expr_to_string(o->expr); + gbString type_str = type_to_string(t); + error_node(o->expr, "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, srcz, dstz); + gb_string_free(type_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + goto error; + } + + o->type = t; + } break; + + case Token_union_cast: { + if (o->mode == Addressing_Constant) { + gbString expr_str = expr_to_string(o->expr); + error_node(o->expr, "Cannot `union_cast` a constant expression: `%s`", expr_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + goto error; + } + + if (is_type_untyped(o->type)) { + gbString expr_str = expr_to_string(o->expr); + error_node(o->expr, "Cannot `union_cast` an untyped expression: `%s`", expr_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + goto error; + } + + bool src_is_ptr = is_type_pointer(o->type); + bool dst_is_ptr = is_type_pointer(t); + Type *src = type_deref(o->type); + Type *dst = type_deref(t); + Type *bsrc = base_type(src); + Type *bdst = base_type(dst); + + if (src_is_ptr != dst_is_ptr) { + gbString src_type_str = type_to_string(o->type); + gbString dst_type_str = type_to_string(t); + error_node(o->expr, "Invalid `union_cast` types: `%s` and `%s`", src_type_str, dst_type_str); + gb_string_free(dst_type_str); + gb_string_free(src_type_str); + o->mode = Addressing_Invalid; + goto error; + } + + if (!is_type_union(src)) { + error_node(o->expr, "`union_cast` can only operate on unions"); + o->mode = Addressing_Invalid; + goto error; + } + + bool ok = false; + for (isize i = 1; i < bsrc->Record.field_count; i++) { + Entity *f = bsrc->Record.fields[i]; + if (are_types_identical(f->type, dst)) { + ok = true; + break; + } + } + + if (!ok) { + gbString expr_str = expr_to_string(o->expr); + gbString dst_type_str = type_to_string(t); + error_node(o->expr, "Cannot `union_cast` `%s` to `%s`", expr_str, dst_type_str); + gb_string_free(dst_type_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + goto error; + } + + Entity **variables = gb_alloc_array(c->allocator, Entity *, 2); + variables[0] = make_entity_param(c->allocator, NULL, empty_token, t, false, true); + variables[1] = make_entity_param(c->allocator, NULL, empty_token, t_bool, false, true); + + Type *tuple = make_type_tuple(c->allocator); + tuple->Tuple.variables = variables; + tuple->Tuple.variable_count = 2; + + o->type = tuple; + o->mode = Addressing_Value; + } break; + case Token_down_cast: { + if (o->mode == Addressing_Constant) { + gbString expr_str = expr_to_string(o->expr); + error_node(o->expr, "Cannot `down_cast` a constant expression: `%s`", expr_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + goto error; + } + + if (is_type_untyped(o->type)) { + gbString expr_str = expr_to_string(o->expr); + error_node(o->expr, "Cannot `down_cast` an untyped expression: `%s`", expr_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + goto error; + } + + if (!(is_type_pointer(o->type) && is_type_pointer(t))) { + gbString expr_str = expr_to_string(o->expr); + error_node(o->expr, "Can only `down_cast` pointers: `%s`", expr_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + goto error; + } + + Type *src = type_deref(o->type); + Type *dst = type_deref(t); + Type *bsrc = base_type(src); + Type *bdst = base_type(dst); + + if (!(is_type_struct(bsrc) || is_type_raw_union(bsrc))) { + gbString expr_str = expr_to_string(o->expr); + error_node(o->expr, "Can only `down_cast` pointer from structs or unions: `%s`", expr_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + goto error; + } + + if (!(is_type_struct(bdst) || is_type_raw_union(bdst))) { + gbString expr_str = expr_to_string(o->expr); + error_node(o->expr, "Can only `down_cast` pointer to structs or unions: `%s`", expr_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + goto error; + } + + String param_name = check_down_cast_name(dst, src); + if (param_name.len == 0) { + gbString expr_str = expr_to_string(o->expr); + error_node(o->expr, "Illegal `down_cast`: `%s`", expr_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + goto error; + } + + o->mode = Addressing_Value; + o->type = t; + } break; + + + default: + GB_PANIC("Unknown cast expression"); + } + case_end; + case_ast_node(ue, UnaryExpr, node); check_expr_base(c, o, ue->expr, type_hint); @@ -4719,6 +4731,10 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint return check_call_expr(c, o, node); case_end; + case_ast_node(ce, MacroCallExpr, node); + return check_macro_call_expr(c, o, node); + case_end; + case_ast_node(de, DerefExpr, node); check_expr_or_type(c, o, de->expr); if (o->mode == Addressing_Invalid) { diff --git a/src/check_stmt.c b/src/check_stmt.c index 1fa16e0ac..be364559d 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -1232,12 +1232,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { case_ast_node(vd, ValueDecl, node); + GB_ASSERT(!c->context.scope->is_file); if (vd->is_var) { Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count); isize entity_count = 0; - if (vd->flags&VarDeclFlag_thread_local && - !c->context.scope->is_file) { + if (vd->flags & VarDeclFlag_thread_local) { + vd->flags &= ~VarDeclFlag_thread_local; error_node(node, "`thread_local` may only be applied to a variable declaration"); } @@ -1256,7 +1257,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { } if (found == NULL) { entity = make_entity_variable(c->allocator, c->context.scope, token, NULL, vd->flags&VarDeclFlag_immutable); - add_entity_definition(&c->info, name, entity); + entity->identifier = name; } else { TokenPos pos = found->token.pos; error(token, @@ -1297,10 +1298,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { check_arity_match(c, vd); check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration")); - for_array(i, vd->names) { - if (entities[i] != NULL) { - add_entity(c, c->context.scope, vd->names.e[i], entities[i]); - } + for (isize i = 0; i < entity_count; i++) { + add_entity(c, c->context.scope, entities[i]->identifier, entities[i]); } if ((vd->flags & VarDeclFlag_using) != 0) { @@ -1315,13 +1314,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (e == NULL) { continue; } - bool is_immutable = false; - if (e->kind == Entity_Variable) { - is_immutable = e->Variable.is_immutable; + if (e->kind != Entity_Variable) { + continue; } - + bool is_immutable = e->Variable.is_immutable; String name = e->token.string; Type *t = base_type(type_deref(e->type)); + if (is_type_struct(t) || is_type_raw_union(t)) { Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node)); GB_ASSERT(found != NULL); diff --git a/src/checker.c b/src/checker.c index cc4f310ed..983198f38 100644 --- a/src/checker.c +++ b/src/checker.c @@ -62,7 +62,6 @@ typedef struct DeclInfo { AstNode *type_expr; AstNode *init_expr; AstNode *proc_lit; // AstNode_ProcLit - u32 var_decl_flags; MapBool deps; // Key: Entity * } DeclInfo; @@ -136,10 +135,6 @@ typedef enum BuiltinProcId { BuiltinProc_type_info, BuiltinProc_type_info_of_val, - BuiltinProc_transmute, - BuiltinProc_union_cast, - BuiltinProc_down_cast, - BuiltinProc_compile_assert, BuiltinProc_assert, BuiltinProc_panic, @@ -183,10 +178,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = { {STR_LIT("type_info"), 1, false, Expr_Expr}, {STR_LIT("type_info_of_val"), 1, false, Expr_Expr}, - {STR_LIT("transmute"), 2, false, Expr_Expr}, - {STR_LIT("union_cast"), 2, false, Expr_Expr}, - {STR_LIT("down_cast"), 2, false, Expr_Expr}, - {STR_LIT("compile_assert"), 1, false, Expr_Stmt}, {STR_LIT("assert"), 1, false, Expr_Stmt}, {STR_LIT("panic"), 1, false, Expr_Stmt}, @@ -524,8 +515,6 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) { Entity *prev = NULL; if (found) { prev = *found; - GB_ASSERT(prev != entity); - if (prev->kind != Entity_Procedure && entity->kind != Entity_Procedure) { return prev; @@ -533,6 +522,9 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) { } if (prev != NULL && entity->kind == Entity_Procedure) { + if (s->is_global) { + return prev; + } map_entity_multi_insert(&s->elements, key, entity); } else { map_entity_set(&s->elements, key, entity); @@ -797,10 +789,15 @@ void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity) bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) { String name = entity->token.string; if (!str_eq(name, str_lit("_"))) { - Entity *insert_entity = scope_insert_entity(scope, entity); - if (insert_entity) { - Entity *up = insert_entity->using_parent; + Entity *ie = scope_insert_entity(scope, entity); + if (ie) { + TokenPos pos = ie->token.pos; + Entity *up = ie->using_parent; if (up != NULL) { + if (token_pos_eq(pos, up->token.pos)) { + // NOTE(bill): Error should have been handled already + return false; + } error(entity->token, "Redeclararation of `%.*s` in this scope through `using`\n" "\tat %.*s(%td:%td)", @@ -808,7 +805,6 @@ bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) { LIT(up->token.pos.file), up->token.pos.line, up->token.pos.column); return false; } else { - TokenPos pos = insert_entity->token.pos; if (token_pos_eq(pos, entity->token.pos)) { // NOTE(bill): Error should have been handled already return false; @@ -1374,14 +1370,13 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope) break; } // NOTE(bill): You need to store the entity information here unline a constant declaration - isize entity_count = vd->names.count; - isize entity_index = 0; - Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count); + isize entity_cap = vd->names.count; + isize entity_count = 0; + Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_cap); DeclInfo *di = NULL; if (vd->values.count > 0) { di = make_declaration_info(heap_allocator(), c->context.scope); di->entities = entities; - di->entity_count = entity_count; di->type_expr = vd->type; di->init_expr = vd->values.e[0]; } @@ -1396,13 +1391,14 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope) error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); continue; } - Entity *e = make_entity_variable(c->allocator, c->context.scope, name->Ident, NULL, vd->flags&VarDeclFlag_immutable); + Entity *e = make_entity_variable(c->allocator, c->context.scope, name->Ident, NULL, vd->flags & VarDeclFlag_immutable); + e->Variable.is_thread_local = vd->flags & VarDeclFlag_thread_local; e->identifier = name; - if (vd->flags&VarDeclFlag_using) { + if (vd->flags & VarDeclFlag_using) { vd->flags &= ~VarDeclFlag_using; // NOTE(bill): This error will be only caught once error_node(name, "`using` is not allowed at the file scope"); } - entities[entity_index++] = e; + entities[entity_count++] = e; DeclInfo *d = di; if (d == NULL) { @@ -1410,12 +1406,15 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope) d = make_declaration_info(heap_allocator(), e->scope); d->type_expr = vd->type; d->init_expr = init_expr; - d->var_decl_flags = vd->flags; } add_entity_and_decl_info(c, name, e, d); } + if (di != NULL) { + di->entity_count = entity_count; + } + check_arity_match(c, vd); } else { for_array(i, vd->names) { @@ -1434,14 +1433,14 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope) Entity *e = NULL; AstNode *up_init = unparen_expr(init); - if (init != NULL && is_ast_node_type(up_init)) { + if (up_init != NULL && is_ast_node_type(up_init)) { e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL); // TODO(bill): What if vd->type != NULL??? How to handle this case? d->type_expr = init; d->init_expr = init; } else if (init != NULL && up_init->kind == AstNode_ProcLit) { e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags); - d->proc_lit = init; + d->proc_lit = up_init; d->type_expr = vd->type; } else { e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, (ExactValue){0}); @@ -1474,7 +1473,11 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope) case_end; case_ast_node(fl, ForeignLibrary, decl); if (!c->context.scope->is_file) { - error_node(decl, "#foreign_library declarations are only allowed in the file scope"); + if (fl->is_system) { + error_node(decl, "#foreign_system_library declarations are only allowed in the file scope"); + } else { + error_node(decl, "#foreign_library declarations are only allowed in the file scope"); + } // NOTE(bill): _Should_ be caught by the parser // TODO(bill): Better error handling if it isn't continue; diff --git a/src/common.c b/src/common.c index a43ee9d32..e2a70f576 100644 --- a/src/common.c +++ b/src/common.c @@ -12,6 +12,17 @@ gbAllocator heap_allocator(void) { gb_global String global_module_path = {0}; gb_global bool global_module_path_set = false; +gb_global gbScratchMemory scratch_memory = {0}; + +void init_scratch_memory(isize size) { + void *memory = gb_alloc(heap_allocator(), size); + gb_scratch_memory_init(&scratch_memory, memory, size); +} + +gbAllocator scratch_allocator(void) { + return gb_scratch_allocator(&scratch_memory); +} + i64 next_pow2(i64 n) { if (n <= 0) { diff --git a/src/entity.c b/src/entity.c index aaccad476..4991c8d37 100644 --- a/src/entity.c +++ b/src/entity.c @@ -66,6 +66,7 @@ struct Entity { i32 field_index; i32 field_src_index; bool is_immutable; + bool is_thread_local; } Variable; i32 TypeName; struct { @@ -111,6 +112,7 @@ Entity *make_entity_variable(gbAllocator a, Scope *scope, Token token, Type *typ Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, Type *type) { GB_ASSERT(parent != NULL); + token.pos = parent->token.pos; Entity *entity = alloc_entity(a, Entity_Variable, parent->scope, token, type); entity->using_parent = parent; entity->flags |= EntityFlag_Anonymous; @@ -132,7 +134,7 @@ Entity *make_entity_type_name(gbAllocator a, Scope *scope, Token token, Type *ty Entity *make_entity_param(gbAllocator a, Scope *scope, Token token, Type *type, bool anonymous, bool is_immutable) { Entity *entity = make_entity_variable(a, scope, token, type, is_immutable); entity->flags |= EntityFlag_Used; - entity->flags |= EntityFlag_Anonymous*(anonymous != 0); + if (anonymous) entity->flags |= EntityFlag_Anonymous; entity->flags |= EntityFlag_Param; return entity; } diff --git a/src/ir.c b/src/ir.c index 5b195958f..81f529d6a 100644 --- a/src/ir.c +++ b/src/ir.c @@ -156,11 +156,6 @@ struct irProcedure { Type * result_type; \ i32 elem_index; \ }) \ - IR_INSTR_KIND(ArrayExtractValue, struct { \ - irValue *address; \ - Type * result_type; \ - i32 index; \ - }) \ IR_INSTR_KIND(StructExtractValue, struct { \ irValue *address; \ Type * result_type; \ @@ -550,8 +545,6 @@ Type *ir_instr_type(irInstr *instr) { return ir_type(instr->PtrOffset.address); case irInstr_Phi: return instr->Phi.type; - case irInstr_ArrayExtractValue: - return instr->ArrayExtractValue.result_type; case irInstr_StructExtractValue: return instr->StructExtractValue.result_type; case irInstr_UnionTagPtr: @@ -851,17 +844,6 @@ irValue *ir_make_instr_ptr_offset(irProcedure *p, irValue *address, irValue *off -irValue *ir_make_instr_array_extract_value(irProcedure *p, irValue *address, i32 index) { - irValue *v = ir_alloc_instr(p, irInstr_ArrayExtractValue); - irInstr *i = &v->Instr; - i->ArrayExtractValue.address = address; - i->ArrayExtractValue.index = index; - Type *t = base_type(ir_type(address)); - GB_ASSERT(is_type_array(t)); - i->ArrayExtractValue.result_type = t->Array.elem; - return v; -} - irValue *ir_make_instr_struct_extract_value(irProcedure *p, irValue *address, i32 index, Type *result_type) { irValue *v = ir_alloc_instr(p, irInstr_StructExtractValue); irInstr *i = &v->Instr; @@ -1646,13 +1628,6 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { } - -irValue *ir_emit_array_ev(irProcedure *proc, irValue *s, i32 index) { - Type *st = base_type(ir_type(s)); - GB_ASSERT(is_type_array(st)); - return ir_emit(proc, ir_make_instr_array_extract_value(proc, s, index)); -} - irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) { // NOTE(bill): For some weird legacy reason in LLVM, structure elements must be accessed as an i32 @@ -1913,6 +1888,12 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) { Type *src = base_type(base_enum_type(src_type)); Type *dst = base_type(base_enum_type(t)); + + // if (is_type_untyped_nil(src) && type_has_nil(dst)) { + if (is_type_untyped_nil(src)) { + return ir_make_value_nil(proc->module->allocator, t); + } + if (value->kind == irValue_Constant) { if (is_type_any(dst)) { irValue *default_value = ir_add_local_generated(proc, default_type(src_type)); @@ -2147,10 +2128,6 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) { return ir_emit_load(proc, result); } - if (is_type_untyped_nil(src) && type_has_nil(dst)) { - return ir_make_value_nil(proc->module->allocator, t); - } - gb_printf_err("ir_emit_conv: src -> dst\n"); gb_printf_err("Not Identical %s != %s\n", type_to_string(src_type), type_to_string(t)); @@ -2718,13 +2695,38 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv return v; case_end; + case_ast_node(ce, CastExpr, expr); + Type *type = tv->type; + irValue *expr = ir_build_expr(proc, ce->expr); + switch (ce->token.kind) { + case Token_cast: + ir_emit_comment(proc, str_lit("cast - cast")); + return ir_emit_conv(proc, expr, type); + + case Token_transmute: + ir_emit_comment(proc, str_lit("cast - transmute")); + return ir_emit_transmute(proc, expr, type); + + case Token_down_cast: + ir_emit_comment(proc, str_lit("cast - down_cast")); + return ir_emit_down_cast(proc, expr, type); + + case Token_union_cast: + ir_emit_comment(proc, str_lit("cast - union_cast")); + return ir_emit_union_cast(proc, expr, type); + + default: + GB_PANIC("Unknown cast expression"); + } + case_end; + case_ast_node(ue, UnaryExpr, expr); switch (ue->op.kind) { case Token_Pointer: return ir_emit_ptr_offset(proc, ir_build_addr(proc, ue->expr).addr, v_zero); // Make a copy of the pointer - case Token_Maybe: - return ir_emit_conv(proc, ir_build_expr(proc, ue->expr), type_of_expr(proc->module->info, expr)); + // case Token_Maybe: + // return ir_emit_conv(proc, ir_build_expr(proc, ue->expr), type_of_expr(proc->module->info, expr)); case Token_Add: return ir_build_expr(proc, ue->expr); @@ -2844,24 +2846,6 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv return ir_type_info(proc, t); } break; - case BuiltinProc_transmute: { - irValue *val = ir_build_expr(proc, ce->args.e[1]); - ir_emit_comment(proc, str_lit("cast - transmute")); - return ir_emit_transmute(proc, val, type_of_expr(proc->module->info, ce->args.e[0])); - } - - case BuiltinProc_down_cast: { - irValue *val = ir_build_expr(proc, ce->args.e[1]); - ir_emit_comment(proc, str_lit("cast - down_cast")); - return ir_emit_down_cast(proc, val, type_of_expr(proc->module->info, ce->args.e[0])); - } - - case BuiltinProc_union_cast: { - irValue *val = ir_build_expr(proc, ce->args.e[1]); - ir_emit_comment(proc, str_lit("cast - union_cast")); - return ir_emit_union_cast(proc, val, type_of_expr(proc->module->info, ce->args.e[0])); - } - case BuiltinProc_new: { ir_emit_comment(proc, str_lit("new")); // new :: proc(Type) -> ^Type @@ -3405,6 +3389,29 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { } case_end; + case_ast_node(ce, CastExpr, expr); + switch (ce->token.kind) { + case Token_cast: { + ir_emit_comment(proc, str_lit("Cast - cast")); + // NOTE(bill): Needed for dereference of pointer conversion + Type *type = type_of_expr(proc->module->info, expr); + irValue *v = ir_add_local_generated(proc, type); + ir_emit_store(proc, v, ir_emit_conv(proc, ir_build_expr(proc, ce->expr), type)); + return ir_make_addr(v, expr); + } + case Token_transmute: { + ir_emit_comment(proc, str_lit("Cast - transmute")); + // NOTE(bill): Needed for dereference of pointer conversion + Type *type = type_of_expr(proc->module->info, expr); + irValue *v = ir_add_local_generated(proc, type); + ir_emit_store(proc, v, ir_emit_transmute(proc, ir_build_expr(proc, ce->expr), type)); + return ir_make_addr(v, expr); + } + default: + GB_PANIC("Unknown cast expression"); + } + case_end; + case_ast_node(ue, UnaryExpr, expr); switch (ue->op.kind) { case Token_Pointer: { @@ -5304,9 +5311,8 @@ void ir_gen_tree(irGen *s) { case Entity_Variable: { irValue *g = ir_make_value_global(a, e, NULL); - if (decl->var_decl_flags & VarDeclFlag_thread_local) { - g->Global.is_thread_local = true; - } + g->Global.is_thread_local = e->Variable.is_thread_local; + irGlobalVariable var = {0}; var.var = g; var.decl = decl; @@ -5509,6 +5515,7 @@ void ir_gen_tree(irGen *s) { map_ir_value_set(&m->values, hash_pointer(e), p); map_ir_value_set(&m->members, hash_string(name), p); + irProcedure *proc = &p->Proc; proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea? @@ -5557,6 +5564,18 @@ void ir_gen_tree(irGen *s) { CheckerInfo *info = proc->module->info; + if (false) { + irValue *global_type_infos = ir_find_global_variable(proc, str_lit("__type_infos")); + Type *type = base_type(type_deref(ir_type(type_info_data))); + GB_ASSERT(is_type_array(type)); + irValue *array_data = ir_emit_array_epi(proc, type_info_data, 0); + irValue *array_count = ir_make_const_int(proc->module->allocator, type->Array.count); + + ir_emit_store(proc, ir_emit_struct_ep(proc, global_type_infos, 0), array_data); + ir_emit_store(proc, ir_emit_struct_ep(proc, global_type_infos, 1), array_count); + } + + // Useful types Type *t_i64_slice_ptr = make_type_pointer(a, make_type_slice(a, t_i64)); Type *t_string_slice_ptr = make_type_pointer(a, make_type_slice(a, t_string)); diff --git a/src/ir_opt.c b/src/ir_opt.c index 66342ee3f..b4c348b2d 100644 --- a/src/ir_opt.c +++ b/src/ir_opt.c @@ -27,9 +27,6 @@ void ir_opt_add_operands(irValueArray *ops, irInstr *i) { array_add(ops, i->PtrOffset.address); array_add(ops, i->PtrOffset.offset); break; - case irInstr_ArrayExtractValue: - array_add(ops, i->ArrayExtractValue.address); - break; case irInstr_StructExtractValue: array_add(ops, i->StructExtractValue.address); break; diff --git a/src/ir_print.c b/src/ir_print.c index 372e7d6fe..7a3032367 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -790,16 +790,6 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { ir_fprintf(f, "\n"); } break; - case irInstr_ArrayExtractValue: { - Type *et = ir_type(instr->ArrayExtractValue.address); - ir_fprintf(f, "%%%d = extractvalue ", value->index); - - ir_print_type(f, m, et); - ir_fprintf(f, " "); - ir_print_value(f, m, instr->ArrayExtractValue.address, et); - ir_fprintf(f, ", %d\n", instr->ArrayExtractValue.index); - } break; - case irInstr_StructExtractValue: { Type *et = ir_type(instr->StructExtractValue.address); ir_fprintf(f, "%%%d = extractvalue ", value->index); diff --git a/src/main.c b/src/main.c index 074b50117..eead1daf3 100644 --- a/src/main.c +++ b/src/main.c @@ -92,6 +92,7 @@ int main(int argc, char **argv) { timings_init(&timings, str_lit("Total Time"), 128); // defer (timings_destroy(&timings)); init_string_buffer_memory(); + init_scratch_memory(gb_megabytes(10)); init_global_error_collector(); #if 1 @@ -234,7 +235,7 @@ int main(int argc, char **argv) { timings_start_section(&timings, str_lit("msvc-link")); - gbString lib_str = gb_string_make(heap_allocator(), "Kernel32.lib"); + gbString lib_str = gb_string_make(heap_allocator(), "\"Kernel32.lib\""); // defer (gb_string_free(lib_str)); char lib_str_buf[1024] = {0}; for_array(i, checker.info.foreign_libraries) { diff --git a/src/parser.c b/src/parser.c index 4223c36fe..7549245f4 100644 --- a/src/parser.c +++ b/src/parser.c @@ -142,17 +142,26 @@ AST_NODE_KIND(_ExprBegin, "", i32) \ AST_NODE_KIND(IndexExpr, "index expression", struct { AstNode *expr, *index; Token open, close; }) \ AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \ AST_NODE_KIND(DemaybeExpr, "demaybe expression", struct { Token op; AstNode *expr; }) \ - AST_NODE_KIND(CallExpr, "call expression", struct { \ - AstNode *proc; \ - AstNodeArray args; \ - Token open, close; \ - Token ellipsis; \ - }) \ AST_NODE_KIND(SliceExpr, "slice expression", struct { \ AstNode *expr; \ Token open, close; \ AstNode *low, *high; \ }) \ + AST_NODE_KIND(CallExpr, "call expression", struct { \ + AstNode * proc; \ + AstNodeArray args; \ + Token open; \ + Token close; \ + Token ellipsis; \ + }) \ + AST_NODE_KIND(MacroCallExpr, "macro call expression", struct { \ + AstNode * macro; \ + Token bang; \ + AstNodeArray args; \ + Token open; \ + Token close; \ + }) \ + AST_NODE_KIND(CastExpr, "cast expression", struct { Token token; AstNode *type, *expr; Token open, close; }) \ AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \ AST_NODE_KIND(BlockExpr, "block expr", struct { \ AstNodeArray stmts; \ @@ -436,6 +445,8 @@ Token ast_node_token(AstNode *node) { return node->ParenExpr.open; case AstNode_CallExpr: return ast_node_token(node->CallExpr.proc); + case AstNode_MacroCallExpr: + return ast_node_token(node->MacroCallExpr.macro); case AstNode_SelectorExpr: if (node->SelectorExpr.selector != NULL) { return ast_node_token(node->SelectorExpr.selector); @@ -447,6 +458,8 @@ Token ast_node_token(AstNode *node) { return node->SliceExpr.open; case AstNode_Ellipsis: return node->Ellipsis.token; + case AstNode_CastExpr: + return node->CastExpr.token; case AstNode_FieldValue: return node->FieldValue.eq; case AstNode_DerefExpr: @@ -655,14 +668,25 @@ AstNode *make_paren_expr(AstFile *f, AstNode *expr, Token open, Token close) { AstNode *make_call_expr(AstFile *f, AstNode *proc, AstNodeArray args, Token open, Token close, Token ellipsis) { AstNode *result = make_node(f, AstNode_CallExpr); - result->CallExpr.proc = proc; - result->CallExpr.args = args; + result->CallExpr.proc = proc; + result->CallExpr.args = args; result->CallExpr.open = open; result->CallExpr.close = close; result->CallExpr.ellipsis = ellipsis; return result; } +AstNode *make_macro_call_expr(AstFile *f, AstNode *macro, Token bang, AstNodeArray args, Token open, Token close) { + AstNode *result = make_node(f, AstNode_MacroCallExpr); + result->MacroCallExpr.macro = macro; + result->MacroCallExpr.bang = bang; + result->MacroCallExpr.args = args; + result->MacroCallExpr.open = open; + result->MacroCallExpr.close = close; + return result; +} + + AstNode *make_selector_expr(AstFile *f, Token token, AstNode *expr, AstNode *selector) { AstNode *result = make_node(f, AstNode_SelectorExpr); result->SelectorExpr.expr = expr; @@ -755,6 +779,16 @@ AstNode *make_field_value(AstFile *f, AstNode *field, AstNode *value, Token eq) return result; } +AstNode *make_cast_expr(AstFile *f, Token token, AstNode *type, AstNode *expr, Token open, Token close) { + AstNode *result = make_node(f, AstNode_CastExpr); + result->CastExpr.token = token; + result->CastExpr.type = type; + result->CastExpr.expr = expr; + result->CastExpr.open = open; + result->CastExpr.close = close; + return result; +} + AstNode *make_compound_lit(AstFile *f, AstNode *type, AstNodeArray elems, Token open, Token close) { AstNode *result = make_node(f, AstNode_CompoundLit); result->CompoundLit.type = type; @@ -1774,8 +1808,12 @@ AstNode *parse_operand(AstFile *f, bool lhs) { return type; } - case Token_OpenBrace: return parse_block_expr(f); - case Token_if: return parse_if_expr(f); + case Token_if: + if (lhs) goto error; + return parse_if_expr(f); + case Token_OpenBrace: + if (lhs) goto error; + return parse_block_expr(f); default: { AstNode *type = parse_identifier_or_type(f); @@ -1790,6 +1828,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) { } } +error: Token begin = f->curr_token; syntax_error(begin, "Expected an operand"); fix_advance_to_next_stmt(f); @@ -1844,6 +1883,36 @@ AstNode *parse_call_expr(AstFile *f, AstNode *operand) { return make_call_expr(f, operand, args, open_paren, close_paren, ellipsis); } + +AstNode *parse_macro_call_expr(AstFile *f, AstNode *operand) { + AstNodeArray args = make_ast_node_array(f); + Token bang, open_paren, close_paren; + + bang = expect_token(f, Token_Not); + + f->expr_level++; + open_paren = expect_token(f, Token_OpenParen); + + while (f->curr_token.kind != Token_CloseParen && + f->curr_token.kind != Token_EOF) { + if (f->curr_token.kind == Token_Comma) { + syntax_error(f->curr_token, "Expected an expression not a ,"); + } + + AstNode *arg = parse_expr(f, false); + array_add(&args, arg); + + if (!allow_token(f, Token_Comma)) { + break; + } + } + + f->expr_level--; + close_paren = expect_closing(f, Token_CloseParen, str_lit("argument list")); + + return make_macro_call_expr(f, operand, bang, args, open_paren, close_paren); +} + AstNode *parse_atom_expr(AstFile *f, bool lhs) { AstNode *operand = parse_operand(f, lhs); @@ -1853,6 +1922,9 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { case Token_OpenParen: operand = parse_call_expr(f, operand); break; + case Token_Not: + operand = parse_macro_call_expr(f, operand); + break; case Token_Period: { Token token = f->curr_token; @@ -1936,6 +2008,20 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { AstNode *parse_unary_expr(AstFile *f, bool lhs) { switch (f->curr_token.kind) { + + case Token_cast: + case Token_transmute: + case Token_down_cast: + case Token_union_cast: + { + Token token = f->curr_token; next_token(f); + Token open = expect_token(f, Token_OpenParen); + AstNode *type = parse_type(f); + Token close = expect_token(f, Token_CloseParen); + AstNode *expr = parse_unary_expr(f, lhs); + return make_cast_expr(f, token, type, expr, open, close); + } break; + case Token_Pointer: { Token op = f->curr_token; next_token(f); @@ -1945,7 +2031,7 @@ AstNode *parse_unary_expr(AstFile *f, bool lhs) { } return make_unary_expr(f, op, expr); } break; - case Token_Maybe: + // case Token_Maybe: case Token_Add: case Token_Sub: case Token_Not: @@ -2432,10 +2518,10 @@ AstNode *parse_identifier_or_type(AstFile *f) { AstNode *sel = parse_identifier(f); e = make_selector_expr(f, token, e, sel); } - // if (f->curr_token.kind == Token_OpenParen) { - // // HACK NOTE(bill): For type_of_val(expr) - // e = parse_call_expr(f, e); - // } + if (f->curr_token.kind == Token_OpenParen) { + // HACK NOTE(bill): For type_of_val(expr) et al. + e = parse_call_expr(f, e); + } return e; } @@ -2464,8 +2550,7 @@ AstNode *parse_identifier_or_type(AstFile *f) { bool is_vector = false; if (f->curr_token.kind == Token_Ellipsis) { - count_expr = make_ellipsis(f, f->curr_token, NULL); - next_token(f); + count_expr = make_ellipsis(f, expect_token(f, Token_Ellipsis), NULL); } else if (f->curr_token.kind == Token_vector) { next_token(f); if (f->curr_token.kind != Token_CloseBracket) { diff --git a/src/tokenizer.c b/src/tokenizer.c index 6f2213ca0..eadfc767d 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -111,6 +111,10 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ TOKEN_KIND(Token_asm, "asm"), \ TOKEN_KIND(Token_push_allocator, "push_allocator"), \ TOKEN_KIND(Token_push_context, "push_context"), \ + TOKEN_KIND(Token_cast, "cast"), \ + TOKEN_KIND(Token_transmute, "transmute"), \ + TOKEN_KIND(Token_down_cast, "down_cast"), \ + TOKEN_KIND(Token_union_cast, "union_cast"), \ TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \ TOKEN_KIND(Token_Count, "") @@ -149,7 +153,6 @@ bool token_pos_eq(TokenPos a, TokenPos b) { return token_pos_cmp(a, b) == 0; } -// NOTE(bill): Text is UTF-8, thus why u8 and not char typedef struct Token { TokenKind kind; String string; diff --git a/src/types.c b/src/types.c index c71f162c4..c49ad4a42 100644 --- a/src/types.c +++ b/src/types.c @@ -509,6 +509,7 @@ bool is_type_numeric(Type *t) { if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Numeric) != 0; } + // TODO(bill): Should this be here? if (t->kind == Type_Vector) { return is_type_numeric(t->Vector.elem); } @@ -1851,8 +1852,7 @@ gbString write_type_to_string(gbString str, Type *type) { gbString type_to_string(Type *type) { - gbString str = gb_string_make(gb_heap_allocator(), ""); - return write_type_to_string(str, type); + return write_type_to_string(gb_string_make(heap_allocator(), ""), type); }