From 680274b6f1f1e36e27c94b4e60895338d413c84a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 19 Aug 2016 23:35:09 +0100 Subject: [PATCH] Implicit Context and #thread_local --- build.bat | 1 + c_libs/stb_image.c | 2 +- examples/demo001.odin | 192 +++++++--- examples/game.odin | 72 ++-- examples/math.odin | 149 +++++++- examples/runtime.odin | 130 ++++++- examples/win32.odin | 242 ++++++++++--- src/checker/checker.cpp | 3 +- src/checker/expr.cpp | 27 +- src/checker/stmt.cpp | 4 +- src/checker/type.cpp | 67 ++-- src/codegen/codegen.cpp | 8 +- src/codegen/print_llvm.cpp | 140 ++++---- src/codegen/ssa.cpp | 712 +++++++++++++++++-------------------- src/parser.cpp | 22 +- src/tokenizer.cpp | 8 +- 16 files changed, 1161 insertions(+), 618 deletions(-) diff --git a/build.bat b/build.bat index aa7124ad0..3707dd6e8 100644 --- a/build.bat +++ b/build.bat @@ -46,6 +46,7 @@ pushd %build_dir% cl %compiler_settings% "..\src\main.cpp" ^ /link %linker_settings% -OUT:%exe_name% ^ && odin run ..\examples/demo001.odin + rem odin run ..\examples/demo001.odin :do_not_compile_exe diff --git a/c_libs/stb_image.c b/c_libs/stb_image.c index 0d5acc7f8..a48cbaec7 100644 --- a/c_libs/stb_image.c +++ b/c_libs/stb_image.c @@ -414,7 +414,7 @@ extern "C" { #ifdef STB_IMAGE_STATIC #define STBIDEF static #else -#define STBIDEF extern "C" __declspec(dllexport) +#define STBIDEF extern #endif ////////////////////////////////////////////////////////////////////////////// diff --git a/examples/demo001.odin b/examples/demo001.odin index fb08ffa8e..f0ac2f4db 100644 --- a/examples/demo001.odin +++ b/examples/demo001.odin @@ -1,6 +1,7 @@ +// Demo 001 #load "basic.odin" #load "math.odin" -// #load "game.odin" +#load "game.odin" main :: proc() { _ = hellope(); @@ -9,7 +10,8 @@ main :: proc() { constants(); types(); data_control(); - // run_game(); + + run_game(); } hellope :: proc() -> int { @@ -17,9 +19,22 @@ hellope :: proc() -> int { return 1; } + +// Line comment +/* + Block Comment +*/ +/* + Nested /* + Block /* + Comment + */ + */ +*/ + apple, banana, carrot: bool; box, carboard: bool = true, false; -hellope_value := hellope(); +hellope_value: int = hellope(); variables :: proc() { i: int; // initialized with zero value @@ -39,21 +54,23 @@ variables :: proc() { // // f32 f64 // - // int uint (size_of(int) = size_of(rawptr)) + // int uint (size_of(int) == size_of(uint) == size_of(rawptr)) // - // rawptr + // rawptr (equivalent to void * in C/C++) // // string // // byte - alias for u8 // rune - alias for i32 // Unicode Codepoint // - // untyped bool - "untyped" types can implicitly convert to any of the "typed" types - // untyped integer - // untyped float - // untyped pointer - // untyped string - // untyped rune + // "untyped" types can implicitly convert to any of the "typed" types + // Default Type + // untyped bool - bool + // untyped integer - int + // untyped float - f64 + // untyped pointer - rawptr + // untyped string - string + // untyped rune - rune/i32 // // Zero values @@ -62,6 +79,7 @@ variables :: proc() { zero_pointer := null; zero_string1 := ""; // Escaped string zero_string2 := ``; // Raw string + // Compound types have a different kind of zero value // Unary operators // +a @@ -70,28 +88,28 @@ variables :: proc() { // !a // Binary operators - // a + b - // a - b - // a ~ b - // a | b + // a + b add + // a - b sub + // a ~ b xor + // a | b or - // a * b - // a / b - // a % b - // a & b - // a &~ b == a & (~b) - // a << b - // a >> b + // a * b mul + // a / b quo + // a % b mod + // a & b and + // a &~ b bitclear == a & (~b) + // a << b shl + // a >> b shr - // a as Type - // a transmute Type + // a as Type // Type cast + // a transmute Type // Bit cast - // a == b - // a != b - // a < b - // a > b - // a <= b - // a >= b + // a == b eq + // a != b ne + // a < b lt + // a > b gt + // a <= b le + // a >= b ge } @@ -115,10 +133,11 @@ procedures :: proc() { print_string(b); a, b = b, a; // Quirk of grammar the of multiple assignments + // Swap variables print_string(a); print_string(b); - // Not hints, it's mandatory + // Not a hint like C/C++, it's mandatory (unless it cannot do it but it will warn) proc1 :: proc(a, b: int) #inline { print_int(a + b); } @@ -136,6 +155,16 @@ constants :: proc() { TAU_32 : f32 : 6.28318530718; TAU_AS_32 :: 6.28318530718 as f32; + + PI :: TAU / 2; + + CLOSE_TO_PI :: 3; + + DIFF :: (PI - CLOSE_TO_PI) / PI; // Evaluated at compile time + + a := TAU; // the constant's value becomes typed as f32 + b := CLOSE_TO_PI; // the constant's value becomes typed as int + c := DIFF; } nl :: proc() { print_rune('\n'); } @@ -147,13 +176,22 @@ types :: proc() { // z: f32 = x; // invalid z: f32 = x as f32; - ptr_z := ^z; // Pascal notation + + ptr_z := ^z; // Pascal notation ptr_z^ = 123; // Derefence Notation + w: f32 = ptr_z^; // 123 print_f32(z); nl(); // ^z - pointer to z // z^ - z from pointer + // Implicit conversion to and from rawptr + r_ptr: rawptr = ptr_z; + ptr_z = r_ptr; + + + + f32_array: [12]f32; // Array of 12 f32 f32_array[0] = 2; f32_array[1] = 3; @@ -162,15 +200,28 @@ types :: proc() { f32_array_len := len(f32_array); // builtin procedure f32_array_cap := cap(f32_array); // == len(f32_array) + + mda: [2][3][4]int; // Column-major + // mda[x][y][z] + + + api: [2]^f32; papi: ^[2]^f32; - f32_slice: []f32; // Array reference + + + + f32_slice: []f32; // Slice / Array reference f32_slice = f32_array[0:5]; f32_slice = f32_array[:5]; f32_slice = f32_array[:]; // f32_array[0:len(f32_array)-1]; - f32_slice = f32_array[1:5:7]; // low:1, high:5, capacity:7 + f32_slice = f32_array[1:5:7]; // low:1, high:5, max:7 + // len: 5-1 == 4 + // cap: 7-1 == 6 + + append_success := append(^f32_slice, 1); _ = append(^f32_slice, 2); @@ -178,8 +229,16 @@ types :: proc() { _ = copy(f32_array[0:2], f32_array[2:4]); // You can use memcpy/memmove if you want + + + + s := "Hellope World"; - sub_string := s[5:10]; + sub_string: string = s[5:10]; + + + + v0: {4}f32; // Vector of 4 f32 v0[0] = 1; @@ -199,6 +258,11 @@ types :: proc() { // LLVM rant? + + + + + type Vec4: {4}f32; type Array3Int: [3]int; @@ -218,7 +282,7 @@ types :: proc() { b: u16, c: u32, } - static_assert(size_of(Packed) == 7); + static_assert(size_of(Packed) == 7); // builtin procedure { @@ -261,15 +325,17 @@ types :: proc() { } // transmute only works if the size of the types are equal - /{ + /* // in C union { i32 i; f32 y; }; - }/ + */ } + + { // Compound Literals a := [3]int{1, 2, 3}; b := [3]int{}; @@ -293,7 +359,10 @@ types :: proc() { print_f32(i[1]); print_rune('\n'); } - { + + + { // First class procedures + do_thing :: proc(p: proc(a, b: int) -> int) { print_int(p(3, 4)); nl(); } @@ -309,11 +378,13 @@ types :: proc() { do_thing(add); do_thing(add_lambda); - do_thing(proc(a, b: int) -> int { + do_thing(proc(a, b: int) -> int { // Anonymous return a * b; }); } + + { // strings and runes escaped := "Hellope World\n"; raw := `Hellope World\n`; @@ -346,11 +417,12 @@ void main() { }`; - knot1 := '⌘'; - knot2 := '\u2318'; // 16 bit - knot3 := '\U00002318'; // 32 bit - knot4 := "\xe2\x8c\x98"; // Note it's a string, should I allow untyped string -> untyped rune casts? + hearts1 := '💕'; + hearts2 := '\U0001f495'; // 32 bit + hearts3 := "\xf0\x9f\x92\x95"; // Note it's a string, should I allow untyped string -> untyped rune casts? + 㐒 := '㐒'; + 㐒16 := '\u4db5'; // 16 bit // String ideas "nicked" from Go, so far. I think I might change how some of it works later. } @@ -439,7 +511,7 @@ data_control :: proc() { - { + { // Defer statement defer print_string("日本語\n"); print_string("Japanese\n"); } @@ -451,21 +523,26 @@ data_control :: proc() { } { + prev_allocator := context.allocator; + context.allocator = __default_allocator(); + defer context.allocator = prev_allocator; + // C strings, yuk! - to_c_string :: proc(s: string) -> ^u8 { - c := heap_alloc(len(s)+1) as ^u8; + to_c_string := proc(s: string) -> ^u8 { + c := alloc(len(s)+1) as ^u8; mem_copy(c, ^s[0], len(s)); c[len(s)] = 0; return c; - } + }; + fopen :: proc(filename, mode: ^u8) -> rawptr #foreign fclose :: proc(f: rawptr) -> i32 #foreign filename := to_c_string("../examples/base.odin"); mode := to_c_string("rb"); - defer heap_free(filename); - defer heap_free(mode); + defer dealloc(filename); + defer dealloc(mode); f := fopen(filename, mode); if f == null { @@ -478,10 +555,10 @@ data_control :: proc() { // rest of code // Better version - /{ + /* type File: struct { filename: string } type FileError: int - open_file :: proc(filename: string) -> (File, FileError) { ... } + open_file :: proc(filename: string) -> (File, FileError) { ... } close_file :: proc(f: ^File) { ... } f, err := open_file("Test"); if err != 0 { @@ -489,17 +566,17 @@ data_control :: proc() { } defer close_file(^f); - }/ + */ } for i := 0; i < 100; i++ { - blah := heap_alloc(100 * size_of(int)) as ^int; + blah := alloc(100 * size_of(int)) as ^int; defer { defer print_string("!"); - defer print_string("heap_free"); - heap_free(blah); + defer print_string("dealloc"); + dealloc(blah); } if i == 3 { @@ -509,7 +586,7 @@ data_control :: proc() { if i == 5 { // defers called - return; + return; // End of procedure } if i == 8 { @@ -523,3 +600,4 @@ data_control :: proc() { print_string("It'll never happen, mate 3"); } + diff --git a/examples/game.odin b/examples/game.odin index 54076af39..7f5ae4e57 100644 --- a/examples/game.odin +++ b/examples/game.odin @@ -35,13 +35,12 @@ to_c_string :: proc(s: string) -> ^u8 { type Window: struct { - width, height: int, - wc: WNDCLASSEXA, - dc: HDC, - hwnd: HWND, - opengl_context: rawptr, - rc: HGLRC, - c_title: ^u8, + width, height: int, + wc: WNDCLASSEXA, + dc: HDC, + hwnd: HWND, + opengl_context, rc: HGLRC, + c_title: ^u8, } make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (Window, bool) { @@ -55,11 +54,11 @@ make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (W instance := GetModuleHandleA(null); w.wc = WNDCLASSEXA{ - cbSize = size_of(WNDCLASSEXA) as u32, - style = CS_VREDRAW | CS_HREDRAW, - hInstance = instance as HINSTANCE, - className = c_class_name, - wndProc = window_proc, + size = size_of(WNDCLASSEXA) as u32, + style = CS_VREDRAW | CS_HREDRAW, + instance = instance as HINSTANCE, + class_name = c_class_name, + wnd_proc = window_proc, }; if RegisterClassExA(^w.wc) == 0 { @@ -82,15 +81,15 @@ make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (W { pfd := PIXELFORMATDESCRIPTOR{ - nSize = size_of(PIXELFORMATDESCRIPTOR) as u32, - nVersion = 1, - dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, - iPixelType = PFD_TYPE_RGBA, - cColorBits = 32, - cAlphaBits = 8, - cDepthBits = 24, - cStencilBits = 8, - iLayerType = PFD_MAIN_PLANE, + size = size_of(PIXELFORMATDESCRIPTOR) as u32, + version = 1, + flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + pixel_type = PFD_TYPE_RGBA, + color_bits = 32, + alpha_bits = 8, + depth_bits = 24, + stencil_bits = 8, + layer_type = PFD_MAIN_PLANE, }; SetPixelFormat(w.dc, ChoosePixelFormat(w.dc, ^pfd), null); @@ -124,6 +123,11 @@ display_window :: proc(w: ^Window) { } +type Entity: struct { + pos: Vec2, + dim: Vec2, +} + run_game :: proc() { win32_proc :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #no_inline { @@ -143,6 +147,9 @@ run_game :: proc() { prev_time := time_now(); running := true; + + pos := Vec2{100, 100}; + for running { curr_time := time_now(); dt := (curr_time - prev_time) as f32; @@ -157,12 +164,32 @@ run_game :: proc() { _ = DispatchMessageA(^msg); } + if is_key_down(VK_ESCAPE) { + running = false; + } + + { + SPEED :: 500; + v: Vec2; + + if is_key_down(VK_RIGHT) { v[0] += 1; } + if is_key_down(VK_LEFT) { v[0] -= 1; } + if is_key_down(VK_UP) { v[1] += 1; } + if is_key_down(VK_DOWN) { v[1] -= 1; } + + v = vec2_norm0(v); + + pos += v * Vec2{SPEED * dt}; + } + + glClearColor(0.5, 0.7, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); glOrtho(0, window.width as f64, 0, window.height as f64, 0, 1); + draw_rect :: proc(x, y, w, h: f32) { glBegin(GL_TRIANGLES); @@ -177,8 +204,7 @@ run_game :: proc() { glEnd(); } - x, y : f32 = 100+50*sinf(curr_time as f32), 100; - draw_rect(x, y, 50, 50); + draw_rect(pos[0], pos[1], 50, 50); display_window(^window); ms_to_sleep := (16 - 1000*dt) as i32; diff --git a/examples/math.odin b/examples/math.odin index 9551c963d..ba0fbc33e 100644 --- a/examples/math.odin +++ b/examples/math.odin @@ -1,19 +1,154 @@ +MATH_TAU :: 6.28318530717958647692528676655900576; +MATH_PI :: 3.14159265358979323846264338327950288; +MATH_ONE_OVER_TAU :: 0.636619772367581343075535053490057448; +MATH_ONE_OVER_PI :: 0.159154943091895335768883763372514362; + +MATH_E :: 2.71828182845904523536; +MATH_SQRT_TWO :: 1.41421356237309504880168872420969808; +MATH_SQRT_THREE :: 1.73205080756887729352744634150587236; +MATH_SQRT_FIVE :: 2.23606797749978969640917366873127623; + +MATH_LOG_TWO :: 0.693147180559945309417232121458176568; +MATH_LOG_TEN :: 2.30258509299404568401799145468436421; + +MATH_EPSILON :: 1.19209290e-7; + + type Vec2: {2}f32 type Vec3: {3}f32 type Vec4: {4}f32 -type Mat2: {4}f32 + +type Mat2: {4}f32 +type Mat3: {9}f32 +type Mat4: {16}f32 + + +fsqrt :: proc(x: f32) -> f32 #foreign "llvm.sqrt.f32" +fsin :: proc(x: f32) -> f32 #foreign "llvm.sin.f32" +fcos :: proc(x: f32) -> f32 #foreign "llvm.cos.f32" +flerp :: proc(a, b, t: f32) -> f32 { return a*(1-t) + b*t; } +fclamp :: proc(x, lower, upper: f32) -> f32 { return fmin(fmax(x, lower), upper); } +fclamp01 :: proc(x: f32) -> f32 { return fclamp(x, 0, 1); } +fabs :: proc(x: f32) -> f32 { if x < 0 { x = -x; } return x; } +fsign :: proc(x: f32) -> f32 { if x >= 0 { return +1; } return -1; } + +fmin :: proc(a, b: f32) -> f32 { if a < b { return a; } return b; } +fmax :: proc(a, b: f32) -> f32 { if a > b { return a; } return b; } +fmin3 :: proc(a, b, c: f32) -> f32 { return fmin(fmin(a, b), c); } +fmax3 :: proc(a, b, c: f32) -> f32 { return fmax(fmax(a, b), c); } + + +copy_sign :: proc(x, y: f32) -> f32 { + ix := x transmute u32; + iy := y transmute u32; + ix &= 0x7fffffff; + ix |= iy & 0x80000000; + return ix transmute f32; +} + + +round :: proc(x: f32) -> f32 { + if x >= 0 { + return floor(x + 0.5); + } + return ceil(x - 0.5); +} +floor :: proc(x: f32) -> f32 { + if x >= 0 { + return x as int as f32; + } + return (x-0.5) as int as f32; +} +ceil :: proc(x: f32) -> f32 { + if x < 0 { + return x as int as f32; + } + return ((x as int)+1) as f32; +} + + + + +remainder :: proc(x, y: f32) -> f32 { + return x - round(x/y) * y; +} + +fmod :: proc(x, y: f32) -> f32 { + y = fabs(y); + result := remainder(fabs(x), y); + if fsign(result) < 0 { + result += y; + } + return copy_sign(result, x); +} + + +to_radians :: proc(degrees: f32) -> f32 { return degrees * MATH_TAU / 360; } +to_degrees :: proc(radians: f32) -> f32 { return radians * 360 / MATH_TAU; } -sqrtf :: proc(x: f32) -> f32 #foreign "llvm.sqrt.f32" -sinf :: proc(x: f32) -> f32 #foreign "llvm.sin.f32" -cosf :: proc(x: f32) -> f32 #foreign "llvm.cos.f32" vec2_dot :: proc(a, b: Vec2) -> f32 { c := a*b; return c[0] + c[1]; } vec3_dot :: proc(a, b: Vec3) -> f32 { c := a*b; return c[0] + c[1] + c[2]; } +vec4_dot :: proc(a, b: Vec4) -> f32 { c := a*b; return c[0] + c[1] + c[2] + c[3]; } -lerp :: proc(a, b, t: f32) -> f32 { return a*(1-t) + b*t; } -vec2_mag :: proc(a: Vec2) -> f32 { return sqrtf(vec2_dot(a, a)); } -vec3_mag :: proc(a: Vec3) -> f32 { return sqrtf(vec3_dot(a, a)); } +vec2_mag :: proc(v: Vec2) -> f32 { return fsqrt(vec2_dot(v, v)); } +vec3_mag :: proc(v: Vec3) -> f32 { return fsqrt(vec3_dot(v, v)); } +vec4_mag :: proc(v: Vec4) -> f32 { return fsqrt(vec4_dot(v, v)); } +vec2_norm :: proc(v: Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)}; } +vec3_norm :: proc(v: Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)}; } +vec4_norm :: proc(v: Vec4) -> Vec4 { return v / Vec4{vec4_mag(v)}; } + +vec2_norm0 :: proc(v: Vec2) -> Vec2 { + m := vec2_mag(v); + if m == 0 { + return Vec2{0}; + } + return v / Vec2{m}; +} + +vec3_norm0 :: proc(v: Vec3) -> Vec3 { + m := vec3_mag(v); + if m == 0 { + return Vec3{0}; + } + return v / Vec3{m}; +} + +vec4_norm0 :: proc(v: Vec4) -> Vec4 { + m := vec4_mag(v); + if m == 0 { + return Vec4{0}; + } + return v / Vec4{m}; +} + + +F32_DIG :: 6; +F32_EPSILON :: 1.192092896e-07; +F32_GUARD :: 0; +F32_MANT_DIG :: 24; +F32_MAX :: 3.402823466e+38; +F32_MAX_10_EXP :: 38; +F32_MAX_EXP :: 128; +F32_MIN :: 1.175494351e-38; +F32_MIN_10_EXP :: -37; +F32_MIN_EXP :: -125; +F32_NORMALIZE :: 0; +F32_RADIX :: 2; +F32_ROUNDS :: 1; + +F64_DIG :: 15; // # of decimal digits of precision +F64_EPSILON :: 2.2204460492503131e-016; // smallest such that 1.0+F64_EPSILON != 1.0 +F64_MANT_DIG :: 53; // # of bits in mantissa +F64_MAX :: 1.7976931348623158e+308; // max value +F64_MAX_10_EXP :: 308; // max decimal exponent +F64_MAX_EXP :: 1024; // max binary exponent +F64_MIN :: 2.2250738585072014e-308; // min positive value +F64_MIN_10_EXP :: -307; // min decimal exponent +F64_MIN_EXP :: -1021; // min binary exponent +F64_RADIX :: 2; // exponent radix +F64_ROUNDS :: 1; // addition rounding: near diff --git a/examples/runtime.odin b/examples/runtime.odin index 17f6ca17b..49dfae29a 100644 --- a/examples/runtime.odin +++ b/examples/runtime.odin @@ -1,14 +1,16 @@ putchar :: proc(c: i32) -> i32 #foreign -heap_alloc :: proc(sz: int) -> rawptr #foreign "malloc" -heap_free :: proc(ptr: rawptr) #foreign "free" - mem_compare :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memcmp" mem_copy :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memcpy" mem_move :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memmove" debug_trap :: proc() #foreign "llvm.debugtrap" +// TODO(bill): make custom heap procedures +heap_realloc :: proc(ptr: rawptr, sz: int) -> rawptr #foreign "realloc" +heap_alloc :: proc(sz: int) -> rawptr { return heap_realloc(null, sz); } +heap_free :: proc(ptr: rawptr) { _ = heap_realloc(ptr, 0); } + __string_eq :: proc(a, b : string) -> bool { if len(a) != len(b) { @@ -50,3 +52,125 @@ __string_lt :: proc(a, b : string) -> bool { return __string_cmp(a, b) < 0; } __string_gt :: proc(a, b : string) -> bool { return __string_cmp(a, b) > 0; } __string_le :: proc(a, b : string) -> bool { return __string_cmp(a, b) <= 0; } __string_ge :: proc(a, b : string) -> bool { return __string_cmp(a, b) >= 0; } + + +type AllocationMode: int; +ALLOCATION_ALLOC :: 0; +ALLOCATION_DEALLOC :: 1; +ALLOCATION_DEALLOC_ALL :: 2; +ALLOCATION_RESIZE :: 3; + + +type AllocatorProc: proc(allocator_data: rawptr, mode: AllocationMode, + size, alignment: int, + old_memory: rawptr, old_size: int, flags: u64) -> rawptr; + +type Allocator: struct { + procedure: AllocatorProc, + data: rawptr, +} + + +type Context: struct { + thread_id: i32, + + user_index: i32, + user_data: rawptr, + + allocator: Allocator, +} + +#thread_local context: Context; + +DEFAULT_ALIGNMENT :: 2*size_of(int); + + +__check_context :: proc() { + if context.allocator.procedure == null { + context.allocator = __default_allocator(); + } + + ptr := __check_context as rawptr; +} + + +alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT); } + +alloc_align :: proc(size, alignment: int) -> rawptr #inline { + __check_context(); + a := context.allocator; + return a.procedure(a.data, ALLOCATION_ALLOC, size, alignment, null, 0, 0); +} + +dealloc :: proc(ptr: rawptr) #inline { + __check_context(); + a := context.allocator; + _ = a.procedure(a.data, ALLOCATION_DEALLOC, 0, 0, ptr, 0, 0); +} +dealloc_all :: proc(ptr: rawptr) #inline { + __check_context(); + a := context.allocator; + _ = a.procedure(a.data, ALLOCATION_DEALLOC_ALL, 0, 0, ptr, 0, 0); +} + + +resize :: proc(ptr: rawptr, old_size, new_size: int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT); } +resize_align :: proc(ptr: rawptr, old_size, new_size, alignment: int) -> rawptr #inline { + __check_context(); + a := context.allocator; + return a.procedure(a.data, ALLOCATION_RESIZE, new_size, alignment, ptr, old_size, 0); +} + + + +default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr { + if old_memory == null { + return alloc_align(new_size, alignment); + } + + if new_size == 0 { + dealloc(old_memory); + return null; + } + + if new_size < old_size { + new_size = old_size; + } + + if old_size == new_size { + return old_memory; + } + + new_memory := alloc_align(new_size, alignment); + if new_memory == null { + return null; + } + _ = copy((new_memory as ^u8)[:new_size], (old_memory as ^u8)[:old_size]); + dealloc(old_memory); + return new_memory; +} + + +__default_allocator_proc :: proc(allocator_data: rawptr, mode: AllocationMode, + size, alignment: int, + old_memory: rawptr, old_size: int, flags: u64) -> rawptr { + if mode == ALLOCATION_ALLOC { + return heap_alloc(size); + } else if mode == ALLOCATION_RESIZE { + return heap_realloc(old_memory, size); + } else if mode == ALLOCATION_DEALLOC { + heap_free(old_memory); + } else if mode == ALLOCATION_DEALLOC_ALL { + // NOTE(bill): Does nothing + } + + return null; +} + +__default_allocator :: proc() -> Allocator { + return Allocator{ + __default_allocator_proc, + null, + }; +} + diff --git a/examples/win32.odin b/examples/win32.odin index 1fdaeb4e8..13bddc4f7 100644 --- a/examples/win32.odin +++ b/examples/win32.odin @@ -42,24 +42,24 @@ type POINT: struct { x, y: i32 } type WNDPROC: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT type WNDCLASSEXA: struct { - cbSize, style: u32, - wndProc: WNDPROC, - cbClsExtra, cbWndExtra: i32, - hInstance: HINSTANCE, - hIcon: HICON, - hCursor: HCURSOR, - hbrBackground: HBRUSH, - menuName, className: ^u8, - hIconSm: HICON, + size, style: u32, + wnd_proc: WNDPROC, + cls_extra, wnd_extra: i32, + instance: HINSTANCE, + icon: HICON, + cursor: HCURSOR, + background: HBRUSH, + menu_name, class_name: ^u8, + sm: HICON, } type MSG: struct { - hwnd: HWND, + hwnd: HWND, message: u32, - wparam: WPARAM, - lparam: LPARAM, - time: u32, - pt: POINT, + wparam: WPARAM, + lparam: LPARAM, + time: u32, + pt: POINT, } @@ -145,34 +145,34 @@ type wglCreateContextAttribsARBType: proc(hdc: HDC, hshareContext: rawptr, attri type PIXELFORMATDESCRIPTOR: struct { - nSize, - nVersion, - dwFlags: u32, + size, + version, + flags: u32, - iPixelType, - cColorBits, - cRedBits, - cRedShift, - cGreenBits, - cGreenShift, - cBlueBits, - cBlueShift, - cAlphaBits, - cAlphaShift, - cAccumBits, - cAccumRedBits, - cAccumGreenBits, - cAccumBlueBits, - cAccumAlphaBits, - cDepthBits, - cStencilBits, - cAuxBuffers, - iLayerType, - bReserved: byte, + pixel_type, + color_bits, + red_bits, + red_shift, + green_bits, + green_shift, + blue_bits, + blue_shift, + alpha_bits, + alpha_shift, + accum_bits, + accum_red_bits, + accum_green_bits, + accum_blue_bits, + accum_alpha_bits, + depth_bits, + stencil_bits, + aux_buffers, + layer_type, + reserved: byte, - dwLayerMask, - dwVisibleMask, - dwDamageMask: u32, + layer_mask, + visible_mask, + damage_mask: u32, } GetDC :: proc(h: HANDLE) -> HDC #foreign @@ -190,3 +190,165 @@ wglCreateContext :: proc(hdc: HDC) -> HGLRC #foreign wglMakeCurrent :: proc(hdc: HDC, hglrc: HGLRC) -> BOOL #foreign wglGetProcAddress :: proc(c_str: ^u8) -> PROC #foreign wglDeleteContext :: proc(hglrc: HGLRC) -> BOOL #foreign + + + +GetAsyncKeyState :: proc(v_key: i32) -> i16 #foreign + +is_key_down :: proc(key: int) -> bool { + return GetAsyncKeyState(key as i32) < 0; +} + + +VK_LBUTTON :: 0x01; +VK_RBUTTON :: 0x02; +VK_CANCEL :: 0x03; +VK_MBUTTON :: 0x04; + +VK_BACK :: 0x08; +VK_TAB :: 0x09; + +VK_CLEAR :: 0x0C; +VK_RETURN :: 0x0D; + +VK_SHIFT :: 0x10; +VK_CONTROL :: 0x11; +VK_MENU :: 0x12; +VK_PAUSE :: 0x13; +VK_CAPITAL :: 0x14; + +VK_KANA :: 0x15; +VK_HANGEUL :: 0x15; +VK_HANGUL :: 0x15; +VK_JUNJA :: 0x17; +VK_FINAL :: 0x18; +VK_HANJA :: 0x19; +VK_KANJI :: 0x19; + +VK_ESCAPE :: 0x1B; + +VK_CONVERT :: 0x1C; +VK_NONCONVERT :: 0x1D; +VK_ACCEPT :: 0x1E; +VK_MODECHANGE :: 0x1F; + +VK_SPACE :: 0x20; +VK_PRIOR :: 0x21; +VK_NEXT :: 0x22; +VK_END :: 0x23; +VK_HOME :: 0x24; +VK_LEFT :: 0x25; +VK_UP :: 0x26; +VK_RIGHT :: 0x27; +VK_DOWN :: 0x28; +VK_SELECT :: 0x29; +VK_PRINT :: 0x2A; +VK_EXECUTE :: 0x2B; +VK_SNAPSHOT :: 0x2C; +VK_INSERT :: 0x2D; +VK_DELETE :: 0x2E; +VK_HELP :: 0x2F; + +VK_0 :: '0'; +VK_1 :: '1'; +VK_2 :: '2'; +VK_3 :: '3'; +VK_4 :: '4'; +VK_5 :: '5'; +VK_6 :: '6'; +VK_7 :: '7'; +VK_8 :: '8'; +VK_9 :: '9'; + +VK_A :: 'A'; +VK_B :: 'B'; +VK_C :: 'C'; +VK_D :: 'D'; +VK_E :: 'E'; +VK_F :: 'F'; +VK_G :: 'G'; +VK_H :: 'H'; +VK_I :: 'I'; +VK_J :: 'J'; +VK_K :: 'K'; +VK_L :: 'L'; +VK_M :: 'M'; +VK_N :: 'N'; +VK_O :: 'O'; +VK_P :: 'P'; +VK_Q :: 'Q'; +VK_R :: 'R'; +VK_S :: 'S'; +VK_T :: 'T'; +VK_U :: 'U'; +VK_V :: 'V'; +VK_W :: 'W'; +VK_X :: 'X'; +VK_Y :: 'Y'; +VK_Z :: 'Z'; + +VK_LWIN :: 0x5B; +VK_RWIN :: 0x5C; +VK_APPS :: 0x5D; + +VK_NUMPAD0 :: 0x60; +VK_NUMPAD1 :: 0x61; +VK_NUMPAD2 :: 0x62; +VK_NUMPAD3 :: 0x63; +VK_NUMPAD4 :: 0x64; +VK_NUMPAD5 :: 0x65; +VK_NUMPAD6 :: 0x66; +VK_NUMPAD7 :: 0x67; +VK_NUMPAD8 :: 0x68; +VK_NUMPAD9 :: 0x69; +VK_MULTIPLY :: 0x6A; +VK_ADD :: 0x6B; +VK_SEPARATOR :: 0x6C; +VK_SUBTRACT :: 0x6D; +VK_DECIMAL :: 0x6E; +VK_DIVIDE :: 0x6F; +VK_F1 :: 0x70; +VK_F2 :: 0x71; +VK_F3 :: 0x72; +VK_F4 :: 0x73; +VK_F5 :: 0x74; +VK_F6 :: 0x75; +VK_F7 :: 0x76; +VK_F8 :: 0x77; +VK_F9 :: 0x78; +VK_F10 :: 0x79; +VK_F11 :: 0x7A; +VK_F12 :: 0x7B; +VK_F13 :: 0x7C; +VK_F14 :: 0x7D; +VK_F15 :: 0x7E; +VK_F16 :: 0x7F; +VK_F17 :: 0x80; +VK_F18 :: 0x81; +VK_F19 :: 0x82; +VK_F20 :: 0x83; +VK_F21 :: 0x84; +VK_F22 :: 0x85; +VK_F23 :: 0x86; +VK_F24 :: 0x87; + +VK_NUMLOCK :: 0x90; +VK_SCROLL :: 0x91; + +VK_LSHIFT :: 0xA0; +VK_RSHIFT :: 0xA1; +VK_LCONTROL :: 0xA2; +VK_RCONTROL :: 0xA3; +VK_LMENU :: 0xA4; +VK_RMENU :: 0xA5; +VK_PROCESSKEY :: 0xE5; +VK_ATTN :: 0xF6; +VK_CRSEL :: 0xF7; +VK_EXSEL :: 0xF8; +VK_EREOF :: 0xF9; +VK_PLAY :: 0xFA; +VK_ZOOM :: 0xFB; +VK_NONAME :: 0xFC; +VK_PA1 :: 0xFD; +VK_OEM_CLEAR :: 0xFE; + diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index e0cacf455..d16cb3ad2 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -38,9 +38,9 @@ struct DeclInfo { AstNode *type_expr; AstNode *init_expr; AstNode *proc_decl; // AstNode_ProcDecl + u32 var_decl_tags; Map deps; // Key: Entity * - i32 mark; }; @@ -605,6 +605,7 @@ void check_parsed_files(Checker *c) { d = make_declaration_info(gb_heap_allocator(), c->global_scope); d->type_expr = vd->type; d->init_expr = init_expr; + d->var_decl_tags = vd->tags; } add_file_entity(c, name, e, d); diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index 8844ce542..415bbe545 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -874,6 +874,12 @@ b32 check_castable_to(Checker *c, Operand *operand, Type *y) { return true; } + + // proc -> rawptr + if (is_type_proc(xb), is_type_rawptr(yb)) { + return true; + } + return false; } @@ -912,7 +918,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { 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); + error(&c->error_collector, ast_node_token(x->expr), "Cannot cast `%s` as `%s`", expr_str, type_str); x->mode = Addressing_Invalid; return; @@ -1199,8 +1205,18 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) { convert_untyped_error(c, operand, target_type); return; } - break; + + case Type_Proc: + switch (operand->type->basic.kind) { + case Basic_UntypedPointer: + break; + default: + convert_untyped_error(c, operand, target_type); + return; + } + break; + default: convert_untyped_error(c, operand, target_type); return; @@ -1992,6 +2008,13 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ i64 max = 0; for (AstNode *elem = cl->elem_list; elem != NULL; elem = elem->next, index++) { AstNode *e = elem; + if (e->kind == AstNode_FieldValue) { + error(&c->error_collector, ast_node_token(e), + "`field = value` is only allowed in structure literals"); + continue; + } + + if (t->kind == Type_Array && t->array.count >= 0 && index >= t->array.count) { diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index 54ef410c4..197ab1bb0 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -119,7 +119,9 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type) { } } + return false; + } @@ -742,8 +744,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { } case_end; - -// Declarations case_ast_node(vd, VarDecl, node); isize entity_count = vd->name_count; isize entity_index = 0; diff --git a/src/checker/type.cpp b/src/checker/type.cpp index 650143ef5..e3af314ae 100644 --- a/src/checker/type.cpp +++ b/src/checker/type.cpp @@ -80,7 +80,13 @@ String const type_strings[] = { #undef TYPE_KIND }; +enum TypeFlag { + TypeFlag_thread_local = GB_BIT(0), + TypeFlag_volatile = GB_BIT(1), +}; + struct Type { + u32 flags; TypeKind kind; union { BasicType basic; @@ -206,43 +212,46 @@ Type *make_type_proc(gbAllocator a, Scope *scope, Type *params, isize param_coun Type *type_deref(Type *t) { - if (t != NULL && t->kind == Type_Pointer) - return t->pointer.elem; + if (t != NULL) { + Type *bt = get_base_type(t); + if (bt != NULL && bt->kind == Type_Pointer) + return bt->pointer.elem; + } return t; } #define STR_LIT(x) {cast(u8 *)(x), gb_size_of(x)-1} gb_global Type basic_types[] = { - {Type_Basic, {Basic_Invalid, 0, STR_LIT("invalid type")}}, - {Type_Basic, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}}, - {Type_Basic, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}}, - {Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}}, - {Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}}, - {Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}}, - {Type_Basic, {Basic_i128, BasicFlag_Integer, STR_LIT("i128")}}, - {Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}}, - {Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}}, - {Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}}, - {Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}}, - {Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u128")}}, - {Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}}, - {Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}}, - {Type_Basic, {Basic_int, BasicFlag_Integer, STR_LIT("int")}}, - {Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}}, - {Type_Basic, {Basic_rawptr, BasicFlag_Pointer, STR_LIT("rawptr")}}, - {Type_Basic, {Basic_string, BasicFlag_String, STR_LIT("string")}}, - {Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}}, - {Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped integer")}}, - {Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, STR_LIT("untyped float")}}, - {Type_Basic, {Basic_UntypedPointer, BasicFlag_Pointer | BasicFlag_Untyped, STR_LIT("untyped pointer")}}, - {Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, STR_LIT("untyped string")}}, - {Type_Basic, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped rune")}}, + {0, Type_Basic, {Basic_Invalid, 0, STR_LIT("invalid type")}}, + {0, Type_Basic, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}}, + {0, Type_Basic, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}}, + {0, Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}}, + {0, Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}}, + {0, Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}}, + {0, Type_Basic, {Basic_i128, BasicFlag_Integer, STR_LIT("i128")}}, + {0, Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}}, + {0, Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}}, + {0, Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}}, + {0, Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}}, + {0, Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u128")}}, + {0, Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}}, + {0, Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}}, + {0, Type_Basic, {Basic_int, BasicFlag_Integer, STR_LIT("int")}}, + {0, Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}}, + {0, Type_Basic, {Basic_rawptr, BasicFlag_Pointer, STR_LIT("rawptr")}}, + {0, Type_Basic, {Basic_string, BasicFlag_String, STR_LIT("string")}}, + {0, Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}}, + {0, Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped integer")}}, + {0, Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, STR_LIT("untyped float")}}, + {0, Type_Basic, {Basic_UntypedPointer, BasicFlag_Pointer | BasicFlag_Untyped, STR_LIT("untyped pointer")}}, + {0, Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, STR_LIT("untyped string")}}, + {0, Type_Basic, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped rune")}}, }; gb_global Type basic_type_aliases[] = { - {Type_Basic, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("byte")}}, - {Type_Basic, {Basic_rune, BasicFlag_Integer, STR_LIT("rune")}}, + {0, Type_Basic, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("byte")}}, + {0, Type_Basic, {Basic_rune, BasicFlag_Integer, STR_LIT("rune")}}, }; gb_global Type *t_invalid = &basic_types[Basic_Invalid]; @@ -392,6 +401,8 @@ b32 is_type_comparable(Type *t) { return is_type_comparable(t->array.elem); case Type_Vector: return is_type_comparable(t->vector.elem); + case Type_Proc: + return true; } return false; } diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index 34933b2a9..795d43a07 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -77,8 +77,10 @@ void ssa_gen_code(ssaGen *s) { } break; case Entity_Variable: { - // TODO(bill): global runtime initialization ssaValue *g = ssa_make_value_global(a, e, NULL); + if (decl->var_decl_tags & VarDeclTag_thread_local) { + g->Global.is_thread_local = true; + } ssaGlobalVariable var = {}; var.var = g; var.decl = decl; @@ -95,7 +97,7 @@ void ssa_gen_code(ssaGen *s) { name = pd->foreign_name; } ssaValue *p = ssa_make_value_procedure(a, m, e->type, decl->type_expr, body, name); - p->proc.tags = pd->tags; + p->Proc.tags = pd->tags; map_set(&m->values, hash_pointer(e), p); map_set(&m->members, hash_string(name), p); @@ -127,7 +129,7 @@ void ssa_gen_code(ssaGen *s) { map_set(&m->values, hash_pointer(e), p); map_set(&m->members, hash_string(name), p); - ssaProcedure *proc = &p->proc; + ssaProcedure *proc = &p->Proc; proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea? ssa_begin_procedure_body(proc); diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index 0790aa7d8..d3974d17c 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -230,10 +230,10 @@ void ssa_print_exact_value(gbFile *f, ssaModule *m, ExactValue value, Type *type if (is_type_float(type) && type->basic.kind == Basic_f32) { // IMPORTANT NOTE(bill): LLVM requires all floating point constants to be // a 64 bit number if bits_of(float type) <= 64. - // For some bizarre reason, you need to clear the bottom 28 bits + // For some bizarre reason, you need to clear the bottom 29 bits // https://groups.google.com/forum/#!topic/llvm-dev/IlqV3TbSk6M - u >>= 28; - u <<= 28; + u >>= 29; + u <<= 29; } ssa_fprintf(f, "0x%016llx", u); } break; @@ -262,19 +262,19 @@ void ssa_print_value(gbFile *f, ssaModule *m, ssaValue *value, Type *type_hint) } switch (value->kind) { case ssaValue_Constant: - ssa_print_exact_value(f, m, value->constant.value, type_hint); + ssa_print_exact_value(f, m, value->Constant.value, type_hint); break; case ssaValue_TypeName: - ssa_print_encoded_local(f, value->type_name.name); + ssa_print_encoded_local(f, value->TypeName.name); break; case ssaValue_Global: - ssa_print_encoded_global(f, value->global.entity->token.string); + ssa_print_encoded_global(f, value->Global.entity->token.string); break; case ssaValue_Param: - ssa_print_encoded_local(f, value->param.entity->token.string); + ssa_print_encoded_local(f, value->Param.entity->token.string); break; case ssaValue_Proc: - ssa_print_encoded_global(f, value->proc.name); + ssa_print_encoded_global(f, value->Proc.name); break; case ssaValue_Instr: ssa_fprintf(f, "%%%d", value->id); @@ -284,7 +284,7 @@ void ssa_print_value(gbFile *f, ssaModule *m, ssaValue *value, Type *type_hint) void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { GB_ASSERT(value->kind == ssaValue_Instr); - ssaInstr *instr = &value->instr; + ssaInstr *instr = &value->Instr; ssa_fprintf(f, "\t"); @@ -294,14 +294,14 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { } break; case ssaInstr_Local: { - Type *type = instr->local.entity->type; + Type *type = instr->Local.entity->type; ssa_fprintf(f, "%%%d = alloca ", value->id); ssa_print_type(f, m->sizes, type); ssa_fprintf(f, ", align %lld ", type_align_of(m->sizes, m->allocator, type)); { - String str = instr->local.entity->token.string; + String str = instr->Local.entity->token.string; if (str.len > 0) - ssa_fprintf(f, "; %.*s", LIT(instr->local.entity->token.string)); + ssa_fprintf(f, "; %.*s", LIT(instr->Local.entity->token.string)); } ssa_fprintf(f, "\n"); ssa_fprintf(f, "\tstore "); @@ -312,33 +312,33 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { } break; case ssaInstr_Store: { - Type *type = ssa_value_type(instr->store.address); + Type *type = ssa_type(instr->Store.address); ssa_fprintf(f, "store "); ssa_print_type(f, m->sizes, type); ssa_fprintf(f, " "); - ssa_print_value(f, m, instr->store.value, type); + ssa_print_value(f, m, instr->Store.value, type); ssa_fprintf(f, ", "); ssa_print_type(f, m->sizes, type); ssa_fprintf(f, "* "); - ssa_print_value(f, m, instr->store.address, type); + ssa_print_value(f, m, instr->Store.address, type); ssa_fprintf(f, "\n"); } break; case ssaInstr_Load: { - Type *type = instr->load.type; + Type *type = instr->Load.type; ssa_fprintf(f, "%%%d = load ", value->id); ssa_print_type(f, m->sizes, type); ssa_fprintf(f, ", "); ssa_print_type(f, m->sizes, type); ssa_fprintf(f, "* "); - ssa_print_value(f, m, instr->load.address, type); + ssa_print_value(f, m, instr->Load.address, type); ssa_fprintf(f, ", align %lld\n", type_align_of(m->sizes, m->allocator, type)); } break; case ssaInstr_GetElementPtr: { - Type *et = instr->get_element_ptr.elem_type; + Type *et = instr->GetElementPtr.elem_type; ssa_fprintf(f, "%%%d = getelementptr ", value->id); - if (instr->get_element_ptr.inbounds) { + if (instr->GetElementPtr.inbounds) { ssa_fprintf(f, "inbounds "); } @@ -346,10 +346,10 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { ssa_fprintf(f, ", "); ssa_print_type(f, m->sizes, et); ssa_fprintf(f, "* "); - ssa_print_value(f, m, instr->get_element_ptr.address, et); - for (isize i = 0; i < instr->get_element_ptr.index_count; i++) { - ssaValue *index = instr->get_element_ptr.indices[i]; - Type *t = ssa_value_type(index); + ssa_print_value(f, m, instr->GetElementPtr.address, et); + for (isize i = 0; i < instr->GetElementPtr.index_count; i++) { + ssaValue *index = instr->GetElementPtr.indices[i]; + Type *t = ssa_type(index); ssa_fprintf(f, ", "); ssa_print_type(f, m->sizes, t); ssa_fprintf(f, " "); @@ -359,13 +359,13 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { } break; case ssaInstr_ExtractValue: { - Type *et = instr->extract_value.elem_type; + Type *et = instr->ExtractValue.elem_type; ssa_fprintf(f, "%%%d = extractvalue ", value->id); ssa_print_type(f, m->sizes, et); ssa_fprintf(f, " "); - ssa_print_value(f, m, instr->extract_value.address, et); - ssa_fprintf(f, ", %d\n", instr->extract_value.index); + ssa_print_value(f, m, instr->ExtractValue.address, et); + ssa_fprintf(f, ", %d\n", instr->ExtractValue.index); } break; case ssaInstr_NoOp: {; @@ -374,28 +374,28 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { case ssaInstr_Br: {; ssa_fprintf(f, "br "); - if (instr->br.cond != NULL) { + if (instr->Br.cond != NULL) { ssa_print_type(f, m->sizes, t_bool); ssa_fprintf(f, " "); - ssa_print_value(f, m, instr->br.cond, t_bool); - ssa_fprintf(f, ", ", instr->br.cond->id); + ssa_print_value(f, m, instr->Br.cond, t_bool); + ssa_fprintf(f, ", ", instr->Br.cond->id); } ssa_fprintf(f, "label "); - ssa_fprintf(f, "%%"); ssa_print_block_name(f, instr->br.true_block); - if (instr->br.false_block != NULL) { + ssa_fprintf(f, "%%"); ssa_print_block_name(f, instr->Br.true_block); + if (instr->Br.false_block != NULL) { ssa_fprintf(f, ", label "); - ssa_fprintf(f, "%%"); ssa_print_block_name(f, instr->br.false_block); + ssa_fprintf(f, "%%"); ssa_print_block_name(f, instr->Br.false_block); } ssa_fprintf(f, "\n"); } break; case ssaInstr_Ret: { - auto *ret = &instr->ret; + auto *ret = &instr->Ret; ssa_fprintf(f, "ret "); if (ret->value == NULL) { ssa_fprintf(f, "void"); } else { - Type *t = ssa_value_type(ret->value); + Type *t = ssa_type(ret->value); ssa_print_type(f, m->sizes, t); ssa_fprintf(f, " "); ssa_print_value(f, m, ret->value, t); @@ -406,7 +406,7 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { } break; case ssaInstr_Conv: { - auto *c = &instr->conv; + auto *c = &instr->Conv; ssa_fprintf(f, "%%%d = %.*s ", value->id, LIT(ssa_conv_strings[c->kind])); ssa_print_type(f, m->sizes, c->from); ssa_fprintf(f, " "); @@ -422,8 +422,8 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { } break; case ssaInstr_BinaryOp: { - auto *bo = &value->instr.binary_op; - Type *type = get_base_type(ssa_value_type(bo->left)); + auto *bo = &value->Instr.BinaryOp; + Type *type = get_base_type(ssa_type(bo->left)); Type *elem_type = type; while (elem_type->kind == Type_Vector) { elem_type = get_base_type(elem_type->vector.elem); @@ -528,7 +528,7 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { } break; case ssaInstr_Call: { - auto *call = &instr->call; + auto *call = &instr->Call; Type *result_type = call->type; if (result_type) { ssa_fprintf(f, "%%%d = ", value->id); @@ -545,7 +545,7 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { ssa_fprintf(f, "("); if (call->arg_count > 0) { - Type *proc_type = get_base_type(ssa_value_type(call->value)); + Type *proc_type = get_base_type(ssa_type(call->value)); GB_ASSERT(proc_type->kind == Type_Proc); auto *params = &proc_type->proc.params->tuple; for (isize i = 0; i < call->arg_count; i++) { @@ -567,15 +567,15 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { case ssaInstr_Select: { ssa_fprintf(f, "%%%d = select i1 ", value->id); - ssa_print_value(f, m, instr->select.cond, t_bool); + ssa_print_value(f, m, instr->Select.cond, t_bool); ssa_fprintf(f, ", "); - ssa_print_type(f, m->sizes, ssa_value_type(instr->select.true_value)); + ssa_print_type(f, m->sizes, ssa_type(instr->Select.true_value)); ssa_fprintf(f, " "); - ssa_print_value(f, m, instr->select.true_value, ssa_value_type(instr->select.true_value)); + ssa_print_value(f, m, instr->Select.true_value, ssa_type(instr->Select.true_value)); ssa_fprintf(f, ", "); - ssa_print_type(f, m->sizes, ssa_value_type(instr->select.false_value)); + ssa_print_type(f, m->sizes, ssa_type(instr->Select.false_value)); ssa_fprintf(f, " "); - ssa_print_value(f, m, instr->select.false_value, ssa_value_type(instr->select.false_value)); + ssa_print_value(f, m, instr->Select.false_value, ssa_type(instr->Select.false_value)); ssa_fprintf(f, "\n"); } break; @@ -583,39 +583,39 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { ssa_fprintf(f, "call void @llvm.memmove.p0i8.p0i8."); ssa_print_type(f, m->sizes, t_int); ssa_fprintf(f, "(i8* "); - ssa_print_value(f, m, instr->copy_memory.dst, t_rawptr); + ssa_print_value(f, m, instr->CopyMemory.dst, t_rawptr); ssa_fprintf(f, ", i8* "); - ssa_print_value(f, m, instr->copy_memory.src, t_rawptr); + ssa_print_value(f, m, instr->CopyMemory.src, t_rawptr); ssa_fprintf(f, ", "); ssa_print_type(f, m->sizes, t_int); ssa_fprintf(f, " "); - ssa_print_value(f, m, instr->copy_memory.len, t_int); + ssa_print_value(f, m, instr->CopyMemory.len, t_int); char *vol_str = "false"; - if (instr->copy_memory.is_volatile) { + if (instr->CopyMemory.is_volatile) { vol_str = "true"; } - ssa_fprintf(f, ", i32 %d, i1 %s)\n", instr->copy_memory.align, vol_str); + ssa_fprintf(f, ", i32 %d, i1 %s)\n", instr->CopyMemory.align, vol_str); } break; case ssaInstr_ExtractElement: { - Type *vt = ssa_value_type(instr->extract_element.vector); + Type *vt = ssa_type(instr->ExtractElement.vector); ssa_fprintf(f, "%%%d = extractelement ", value->id); ssa_print_type(f, m->sizes, vt); ssa_fprintf(f, " "); - ssa_print_value(f, m, instr->extract_element.vector, vt); + ssa_print_value(f, m, instr->ExtractElement.vector, vt); ssa_fprintf(f, ", "); - Type *it = ssa_value_type(instr->extract_element.index); + Type *it = ssa_type(instr->ExtractElement.index); ssa_print_type(f, m->sizes, it); ssa_fprintf(f, " "); - ssa_print_value(f, m, instr->extract_element.index, it); + ssa_print_value(f, m, instr->ExtractElement.index, it); ssa_fprintf(f, "\n"); } break; case ssaInstr_InsertElement: { - auto *ie = &instr->insert_element; - Type *vt = ssa_value_type(ie->vector); + auto *ie = &instr->InsertElement; + Type *vt = ssa_type(ie->vector); ssa_fprintf(f, "%%%d = insertelement ", value->id); ssa_print_type(f, m->sizes, vt); @@ -623,21 +623,21 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { ssa_print_value(f, m, ie->vector, vt); ssa_fprintf(f, ", "); - ssa_print_type(f, m->sizes, ssa_value_type(ie->elem)); + ssa_print_type(f, m->sizes, ssa_type(ie->elem)); ssa_fprintf(f, " "); - ssa_print_value(f, m, ie->elem, ssa_value_type(ie->elem)); + ssa_print_value(f, m, ie->elem, ssa_type(ie->elem)); ssa_fprintf(f, ", "); - ssa_print_type(f, m->sizes, ssa_value_type(ie->index)); + ssa_print_type(f, m->sizes, ssa_type(ie->index)); ssa_fprintf(f, " "); - ssa_print_value(f, m, ie->index, ssa_value_type(ie->index)); + ssa_print_value(f, m, ie->index, ssa_type(ie->index)); ssa_fprintf(f, "\n"); } break; case ssaInstr_ShuffleVector: { - auto *sv = &instr->shuffle_vector; - Type *vt = ssa_value_type(sv->vector); + auto *sv = &instr->ShuffleVector; + Type *vt = ssa_type(sv->vector); ssa_fprintf(f, "%%%d = shufflevector ", value->id); ssa_print_type(f, m->sizes, vt); @@ -738,9 +738,9 @@ void ssa_print_proc(gbFile *f, ssaModule *m, ssaProcedure *proc) { void ssa_print_type_name(gbFile *f, ssaModule *m, ssaValue *v) { GB_ASSERT(v->kind == ssaValue_TypeName); - ssa_print_encoded_local(f, v->type_name.name); + ssa_print_encoded_local(f, v->TypeName.name); ssa_fprintf(f, " = type "); - ssa_print_type(f, m->sizes, get_base_type(v->type_name.type)); + ssa_print_type(f, m->sizes, get_base_type(v->TypeName.type)); ssa_fprintf(f, "\n"); } @@ -763,9 +763,9 @@ void ssa_print_llvm_ir(gbFile *f, ssaModule *m) { ssaValue *v = entry->value; switch (v->kind) { case ssaValue_TypeName: { - ssa_print_encoded_local(f, v->type_name.name); + ssa_print_encoded_local(f, v->TypeName.name); ssa_fprintf(f, " = type "); - ssa_print_type(f, m->sizes, get_base_type(v->type_name.type)); + ssa_print_type(f, m->sizes, get_base_type(v->TypeName.type)); ssa_fprintf(f, "\n"); } break; } @@ -790,16 +790,20 @@ void ssa_print_llvm_ir(gbFile *f, ssaModule *m) { ssaValue *v = entry->value; switch (v->kind) { case ssaValue_Global: { - auto *g = &v->global; + auto *g = &v->Global; ssa_print_encoded_global(f, g->entity->token.string); ssa_fprintf(f, " = "); + if (g->is_thread_local) { + ssa_fprintf(f, "thread_local "); + } if (g->is_constant) { ssa_fprintf(f, "private constant "); } else { ssa_fprintf(f, "global "); } - ssa_print_type(f, m->sizes, get_base_type(g->entity->type)); + + ssa_print_type(f, m->sizes, g->entity->type); ssa_fprintf(f, " "); if (g->value != NULL) { ssa_print_value(f, m, g->value, g->entity->type); @@ -810,7 +814,7 @@ void ssa_print_llvm_ir(gbFile *f, ssaModule *m) { } break; case ssaValue_Proc: { - ssa_print_proc(f, m, &v->proc); + ssa_print_proc(f, m, &v->Proc); } break; } } diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index 271ce3cfb..7760b725e 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -141,15 +141,15 @@ struct ssaInstr { struct { Entity *entity; Type *type; - } local; + } Local; struct { ssaValue *address; ssaValue *value; - } store; + } Store; struct { Type *type; ssaValue *address; - } load; + } Load; struct { ssaValue *address; Type * result_type; @@ -157,65 +157,65 @@ struct ssaInstr { ssaValue *indices[2]; isize index_count; b32 inbounds; - } get_element_ptr; + } GetElementPtr; struct { ssaValue *address; Type * result_type; Type * elem_type; i32 index; - } extract_value; + } ExtractValue; struct { ssaConvKind kind; ssaValue *value; Type *from, *to; - } conv; + } Conv; struct { ssaValue *cond; ssaBlock *true_block; ssaBlock *false_block; - } br; - struct { ssaValue *value; } ret; - struct {} unreachable; + } Br; + struct { ssaValue *value; } Ret; + struct {} Unreachable; struct { ssaValue *cond; ssaValue *true_value; ssaValue *false_value; - } select; + } Select; struct { Type *type; Token op; ssaValue *left, *right; - } binary_op; + } BinaryOp; struct { Type *type; // return type ssaValue *value; ssaValue **args; isize arg_count; - } call; + } Call; struct { ssaValue *dst, *src; ssaValue *len; i32 align; b32 is_volatile; - } copy_memory; + } CopyMemory; struct { ssaValue *vector; ssaValue *index; - } extract_element; + } ExtractElement; struct { ssaValue *vector; ssaValue *elem; ssaValue *index; - } insert_element; + } InsertElement; struct { ssaValue *vector; i32 *indices; isize index_count; Type *type; - } shuffle_vector; + } ShuffleVector; - struct {} startup_runtime; + struct {} StartupRuntime; }; }; @@ -244,25 +244,26 @@ struct ssaValue { struct { Type * type; ExactValue value; - } constant; + } Constant; struct { String name; Type * type; - } type_name; + } TypeName; struct { b32 is_constant; + b32 is_thread_local; Entity * entity; Type * type; ssaValue *value; - } global; + } Global; struct { ssaProcedure *parent; Entity *entity; Type * type; - } param; - ssaProcedure proc; - ssaBlock block; - ssaInstr instr; + } Param; + ssaProcedure Proc; + ssaBlock Block; + ssaInstr Instr; }; }; @@ -274,8 +275,8 @@ gb_global ssaValue *v_two32 = NULL; gb_global ssaValue *v_false = NULL; gb_global ssaValue *v_true = NULL; -struct ssaLvalue { - ssaValue *address; +struct ssaAddr { + ssaValue *addr; AstNode *expr; // NOTE(bill): Just for testing - probably remove later // HACK(bill): Fix how lvalues for vectors work @@ -283,13 +284,13 @@ struct ssaLvalue { ssaValue *index; }; -ssaLvalue ssa_make_lvalue(ssaValue *address, AstNode *expr) { - ssaLvalue v = {address, expr, false, NULL}; +ssaAddr ssa_make_addr(ssaValue *addr, AstNode *expr) { + ssaAddr v = {addr, expr, false, NULL}; return v; } -ssaLvalue ssa_make_lvalue_vector(ssaValue *address, ssaValue *index, AstNode *expr) { - ssaLvalue v = {address, expr, true, index}; +ssaAddr ssa_make_addr_vector(ssaValue *addr, ssaValue *index, AstNode *expr) { + ssaAddr v = {addr, expr, true, index}; return v; } @@ -322,29 +323,29 @@ void ssa_module_add_value(ssaModule *m, Entity *e, ssaValue *v) { } -Type *ssa_value_type(ssaValue *value); -void ssa_value_set_type(ssaValue *value, Type *type); +Type *ssa_type(ssaValue *value); +void ssa_set_type(ssaValue *value, Type *type); -Type *ssa_instr_type(ssaInstr *instr) { +Type *ssa_type(ssaInstr *instr) { switch (instr->kind) { case ssaInstr_Local: - return instr->local.type; + return instr->Local.type; case ssaInstr_Store: - return ssa_value_type(instr->store.address); + return ssa_type(instr->Store.address); case ssaInstr_Load: - return instr->load.type; + return instr->Load.type; case ssaInstr_GetElementPtr: - return instr->get_element_ptr.result_type; + return instr->GetElementPtr.result_type; case ssaInstr_ExtractValue: - return instr->extract_value.result_type; + return instr->ExtractValue.result_type; case ssaInstr_BinaryOp: - return instr->binary_op.type; + return instr->BinaryOp.type; case ssaInstr_Conv: - return instr->conv.to; + return instr->Conv.to; case ssaInstr_Select: - return ssa_value_type(instr->select.true_value); + return ssa_type(instr->Select.true_value); case ssaInstr_Call: { - Type *pt = get_base_type(instr->call.type); + Type *pt = get_base_type(instr->Call.type); if (pt != NULL) { if (pt->kind == Type_Tuple && pt->tuple.variable_count == 1) return pt->tuple.variables[0]->type; @@ -356,81 +357,83 @@ Type *ssa_instr_type(ssaInstr *instr) { return t_int; case ssaInstr_ExtractElement: { - Type *vt = ssa_value_type(instr->extract_element.vector); - return base_vector_type(get_base_type(vt)); + Type *vt = ssa_type(instr->ExtractElement.vector); + Type *bt = base_vector_type(get_base_type(vt)); + GB_ASSERT(!is_type_vector(bt)); + return bt; } break; case ssaInstr_InsertElement: - return ssa_value_type(instr->insert_element.vector); + return ssa_type(instr->InsertElement.vector); case ssaInstr_ShuffleVector: - return instr->shuffle_vector.type; + return instr->ShuffleVector.type; } return NULL; } -void ssa_instr_set_type(ssaInstr *instr, Type *type) { +void ssa_set_type(ssaInstr *instr, Type *type) { switch (instr->kind) { case ssaInstr_Local: - instr->local.type = type; + instr->Local.type = type; break; case ssaInstr_Store: - ssa_value_set_type(instr->store.value, type); + ssa_set_type(instr->Store.value, type); break; case ssaInstr_Load: - instr->load.type = type; + instr->Load.type = type; break; case ssaInstr_GetElementPtr: - instr->get_element_ptr.result_type = type; + instr->GetElementPtr.result_type = type; break; case ssaInstr_ExtractValue: - instr->extract_value.result_type = type; + instr->ExtractValue.result_type = type; break; case ssaInstr_BinaryOp: - instr->binary_op.type = type; + instr->BinaryOp.type = type; break; case ssaInstr_Conv: - instr->conv.to = type; + instr->Conv.to = type; break; case ssaInstr_Call: - instr->call.type = type; + instr->Call.type = type; break; } } -Type *ssa_value_type(ssaValue *value) { +Type *ssa_type(ssaValue *value) { switch (value->kind) { case ssaValue_Constant: - return value->constant.type; + return value->Constant.type; case ssaValue_TypeName: - return value->type_name.type; + return value->TypeName.type; case ssaValue_Global: - return value->global.type; + return value->Global.type; case ssaValue_Param: - return value->param.type; + return value->Param.type; case ssaValue_Proc: - return value->proc.type; + return value->Proc.type; case ssaValue_Instr: - return ssa_instr_type(&value->instr); + return ssa_type(&value->Instr); } return NULL; } -void ssa_value_set_type(ssaValue *value, Type *type) { +void ssa_set_type(ssaValue *value, Type *type) { switch (value->kind) { case ssaValue_TypeName: - value->type_name.type = type; + value->TypeName.type = type; break; case ssaValue_Global: - value->global.type = type; + value->Global.type = type; break; case ssaValue_Proc: - value->proc.type = type; + value->Proc.type = type; break; case ssaValue_Constant: - value->constant.type = type; + value->Constant.type = type; break; case ssaValue_Instr: - ssa_instr_set_type(&value->instr, type); + ssa_set_type(&value->Instr, type); break; } } @@ -439,7 +442,7 @@ void ssa_value_set_type(ssaValue *value, Type *type) { 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); +ssaAddr 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); @@ -453,233 +456,185 @@ ssaValue *ssa_alloc_value(gbAllocator a, ssaValueKind kind) { return v; } -ssaValue *ssa_alloc_instr(gbAllocator a, ssaInstrKind kind) { - ssaValue *v = ssa_alloc_value(a, ssaValue_Instr); - v->instr.kind = kind; +ssaValue *ssa_alloc_instr(ssaProcedure *proc, ssaInstrKind kind) { + ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Instr); + v->Instr.kind = kind; + if (proc->curr_block) { + gb_array_append(proc->curr_block->values, v); + } return v; } ssaValue *ssa_make_value_type_name(gbAllocator a, String name, Type *type) { ssaValue *v = ssa_alloc_value(a, ssaValue_TypeName); - v->type_name.name = name; - v->type_name.type = type; + v->TypeName.name = name; + v->TypeName.type = type; return v; } ssaValue *ssa_make_value_global(gbAllocator a, Entity *e, ssaValue *value) { ssaValue *v = ssa_alloc_value(a, ssaValue_Global); - v->global.entity = e; - v->global.type = e->type; - v->global.value = value; + v->Global.entity = e; + v->Global.type = e->type; + v->Global.value = value; return v; } ssaValue *ssa_make_value_param(gbAllocator a, ssaProcedure *parent, Entity *e) { ssaValue *v = ssa_alloc_value(a, ssaValue_Param); - v->param.parent = parent; - v->param.entity = e; - v->param.type = e->type; + v->Param.parent = parent; + v->Param.entity = e; + v->Param.type = e->type; return v; } ssaValue *ssa_make_instr_local(ssaProcedure *p, Entity *e) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Local); - ssaInstr *i = &v->instr; - i->local.entity = e; - i->local.type = e->type; - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_Local); + ssaInstr *i = &v->Instr; + i->Local.entity = e; + i->Local.type = e->type; ssa_module_add_value(p->module, e, v); return v; } ssaValue *ssa_make_instr_store(ssaProcedure *p, ssaValue *address, ssaValue *value) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Store); - ssaInstr *i = &v->instr; - i->store.address = address; - i->store.value = value; - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_Store); + ssaInstr *i = &v->Instr; + i->Store.address = address; + i->Store.value = value; return v; } ssaValue *ssa_make_instr_load(ssaProcedure *p, ssaValue *address) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Load); - ssaInstr *i = &v->instr; - i->load.address = address; - i->load.type = ssa_value_type(address); - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_Load); + ssaInstr *i = &v->Instr; + i->Load.address = address; + i->Load.type = ssa_type(address); return v; } ssaValue *ssa_make_instr_get_element_ptr(ssaProcedure *p, ssaValue *address, ssaValue *index0, ssaValue *index1, isize index_count, b32 inbounds) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_GetElementPtr); - ssaInstr *i = &v->instr; - i->get_element_ptr.address = address; - i->get_element_ptr.indices[0] = index0; - i->get_element_ptr.indices[1] = index1; - i->get_element_ptr.index_count = index_count; - i->get_element_ptr.elem_type = ssa_value_type(address); - i->get_element_ptr.inbounds = inbounds; - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_GetElementPtr); + ssaInstr *i = &v->Instr; + i->GetElementPtr.address = address; + i->GetElementPtr.indices[0] = index0; + i->GetElementPtr.indices[1] = index1; + i->GetElementPtr.index_count = index_count; + i->GetElementPtr.elem_type = ssa_type(address); + i->GetElementPtr.inbounds = inbounds; return v; } ssaValue *ssa_make_instr_extract_value(ssaProcedure *p, ssaValue *address, i32 index, Type *result_type) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_ExtractValue); - ssaInstr *i = &v->instr; - i->extract_value.address = address; - i->extract_value.index = index; - i->extract_value.result_type = result_type; - Type *et = ssa_value_type(address); - i->extract_value.elem_type = et; + ssaValue *v = ssa_alloc_instr(p, ssaInstr_ExtractValue); + ssaInstr *i = &v->Instr; + i->ExtractValue.address = address; + i->ExtractValue.index = index; + i->ExtractValue.result_type = result_type; + Type *et = ssa_type(address); + i->ExtractValue.elem_type = et; GB_ASSERT(et->kind == Type_Structure || et->kind == Type_Array || et->kind == Type_Tuple); - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } return v; } ssaValue *ssa_make_instr_binary_op(ssaProcedure *p, Token op, ssaValue *left, ssaValue *right) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_BinaryOp); - ssaInstr *i = &v->instr; - i->binary_op.op = op; - i->binary_op.left = left; - i->binary_op.right = right; - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_BinaryOp); + ssaInstr *i = &v->Instr; + i->BinaryOp.op = op; + i->BinaryOp.left = left; + i->BinaryOp.right = right; return v; } ssaValue *ssa_make_instr_br(ssaProcedure *p, ssaValue *cond, ssaBlock *true_block, ssaBlock *false_block) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Br); - ssaInstr *i = &v->instr; - i->br.cond = cond; - i->br.true_block = true_block; - i->br.false_block = false_block; - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_Br); + ssaInstr *i = &v->Instr; + i->Br.cond = cond; + i->Br.true_block = true_block; + i->Br.false_block = false_block; return v; } ssaValue *ssa_make_instr_unreachable(ssaProcedure *p) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Unreachable); - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_Unreachable); return v; } ssaValue *ssa_make_instr_ret(ssaProcedure *p, ssaValue *value) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Ret); - v->instr.ret.value = value; - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_Ret); + v->Instr.Ret.value = value; return v; } ssaValue *ssa_make_instr_select(ssaProcedure *p, ssaValue *cond, ssaValue *t, ssaValue *f) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Select); - v->instr.select.cond = cond; - v->instr.select.true_value = t; - v->instr.select.false_value = f; - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_Select); + v->Instr.Select.cond = cond; + v->Instr.Select.true_value = t; + v->Instr.Select.false_value = f; return v; } ssaValue *ssa_make_instr_call(ssaProcedure *p, ssaValue *value, ssaValue **args, isize arg_count, Type *result_type) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Call); - v->instr.call.value = value; - v->instr.call.args = args; - v->instr.call.arg_count = arg_count; - v->instr.call.type = result_type; - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_Call); + v->Instr.Call.value = value; + v->Instr.Call.args = args; + v->Instr.Call.arg_count = arg_count; + v->Instr.Call.type = result_type; return v; } ssaValue *ssa_make_instr_copy_memory(ssaProcedure *p, ssaValue *dst, ssaValue *src, ssaValue *len, i32 align, b32 is_volatile) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_MemCopy); - v->instr.copy_memory.dst = dst; - v->instr.copy_memory.src = src; - v->instr.copy_memory.len = len; - v->instr.copy_memory.align = align; - v->instr.copy_memory.is_volatile = is_volatile; - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_MemCopy); + v->Instr.CopyMemory.dst = dst; + v->Instr.CopyMemory.src = src; + v->Instr.CopyMemory.len = len; + v->Instr.CopyMemory.align = align; + v->Instr.CopyMemory.is_volatile = is_volatile; return v; } ssaValue *ssa_make_instr_conv(ssaProcedure *p, ssaConvKind kind, ssaValue *value, Type *from, Type *to) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Conv); - v->instr.conv.kind = kind; - v->instr.conv.value = value; - v->instr.conv.from = from; - v->instr.conv.to = to; - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_Conv); + v->Instr.Conv.kind = kind; + v->Instr.Conv.value = value; + v->Instr.Conv.from = from; + v->Instr.Conv.to = to; return v; } ssaValue *ssa_make_instr_extract_element(ssaProcedure *p, ssaValue *vector, ssaValue *index) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_ExtractElement); - v->instr.extract_element.vector = vector; - v->instr.extract_element.index = index; - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_ExtractElement); + v->Instr.ExtractElement.vector = vector; + v->Instr.ExtractElement.index = index; return v; } ssaValue *ssa_make_instr_insert_element(ssaProcedure *p, ssaValue *vector, ssaValue *elem, ssaValue *index) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_InsertElement); - v->instr.insert_element.vector = vector; - v->instr.insert_element.elem = elem; - v->instr.insert_element.index = index; - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_InsertElement); + v->Instr.InsertElement.vector = vector; + v->Instr.InsertElement.elem = elem; + v->Instr.InsertElement.index = index; return v; } ssaValue *ssa_make_instr_shuffle_vector(ssaProcedure *p, ssaValue *vector, i32 *indices, isize index_count) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_ShuffleVector); - v->instr.shuffle_vector.vector = vector; - v->instr.shuffle_vector.indices = indices; - v->instr.shuffle_vector.index_count = index_count; + ssaValue *v = ssa_alloc_instr(p, ssaInstr_ShuffleVector); + v->Instr.ShuffleVector.vector = vector; + v->Instr.ShuffleVector.indices = indices; + v->Instr.ShuffleVector.index_count = index_count; - Type *vt = get_base_type(ssa_value_type(vector)); - v->instr.shuffle_vector.type = make_type_vector(p->module->allocator, vt->vector.elem, index_count); + Type *vt = get_base_type(ssa_type(vector)); + v->Instr.ShuffleVector.type = make_type_vector(p->module->allocator, vt->vector.elem, index_count); - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } return v; } ssaValue *ssa_make_instr_no_op(ssaProcedure *p) { - ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_NoOp); - if (p->curr_block) { - gb_array_append(p->curr_block->values, v); - } + ssaValue *v = ssa_alloc_instr(p, ssaInstr_NoOp); return v; } @@ -689,30 +644,30 @@ ssaValue *ssa_make_instr_no_op(ssaProcedure *p) { ssaValue *ssa_make_value_constant(gbAllocator a, Type *type, ExactValue value) { ssaValue *v = ssa_alloc_value(a, ssaValue_Constant); - v->constant.type = type; - v->constant.value = value; + v->Constant.type = type; + v->Constant.value = value; return v; } ssaValue *ssa_make_value_procedure(gbAllocator a, ssaModule *m, Type *type, AstNode *type_expr, AstNode *body, String name) { ssaValue *v = ssa_alloc_value(a, ssaValue_Proc); - v->proc.module = m; - v->proc.type = type; - v->proc.type_expr = type_expr; - v->proc.body = body; - v->proc.name = name; + v->Proc.module = m; + v->Proc.type = type; + v->Proc.type_expr = type_expr; + v->Proc.body = body; + v->Proc.name = name; return v; } ssaValue *ssa_make_value_block(ssaProcedure *proc, AstNode *node, Scope *scope, String label) { ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Block); - v->block.label = label; - v->block.node = node; - v->block.scope = scope; - v->block.parent = proc; + v->Block.label = label; + v->Block.node = node; + v->Block.scope = scope; + v->Block.parent = proc; - gb_array_init(v->block.instrs, gb_heap_allocator()); - gb_array_init(v->block.values, gb_heap_allocator()); + gb_array_init(v->Block.instrs, gb_heap_allocator()); + gb_array_init(v->Block.values, gb_heap_allocator()); return v; } @@ -735,7 +690,7 @@ ssaInstr *ssa_get_last_instr(ssaBlock *block) { if (len > 0) { ssaValue *v = block->instrs[len-1]; GB_ASSERT(v->kind == ssaValue_Instr); - return &v->instr; + return &v->Instr; } } return NULL; @@ -755,8 +710,9 @@ b32 ssa_is_instr_terminating(ssaInstr *i) { } ssaValue *ssa_emit(ssaProcedure *proc, ssaValue *instr) { + GB_ASSERT(instr->kind == ssaValue_Instr); ssaBlock *b = proc->curr_block; - instr->instr.parent = b; + instr->Instr.parent = b; if (b) { ssaInstr *i = ssa_get_last_instr(b); if (!ssa_is_instr_terminating(i)) { @@ -805,9 +761,9 @@ ssaValue *ssa_add_param(ssaProcedure *proc, Entity *e) { -Type *ssa_lvalue_type(ssaLvalue lval) { - if (lval.address != NULL) { - return type_deref(ssa_value_type(lval.address)); +Type *ssa_type(ssaAddr lval) { + if (lval.addr != NULL) { + return ssa_type(lval.addr); } return NULL; } @@ -824,7 +780,7 @@ ssaBlock *ssa__make_block(ssaProcedure *proc, AstNode *node, String label) { } ssaValue *block = ssa_make_value_block(proc, node, scope, label); - return &block->block; + return &block->Block; } ssaBlock *ssa_add_block(ssaProcedure *proc, AstNode *node, String label) { @@ -903,28 +859,30 @@ void ssa_emit_no_op(ssaProcedure *proc) { -ssaValue *ssa_lvalue_store(ssaProcedure *proc, ssaLvalue lval, ssaValue *value) { - if (lval.address != NULL) { +ssaValue *ssa_lvalue_store(ssaProcedure *proc, ssaAddr lval, ssaValue *value) { + if (lval.addr != NULL) { if (lval.is_vector) { // HACK(bill): Fix how lvalues for vectors work - ssaValue *v = ssa_emit_load(proc, lval.address); - Type *elem_type = get_base_type(ssa_value_type(v))->vector.elem; + ssaValue *v = ssa_emit_load(proc, lval.addr); + Type *elem_type = get_base_type(ssa_type(v))->vector.elem; ssaValue *elem = ssa_emit_conv(proc, value, elem_type); ssaValue *out = ssa_emit(proc, ssa_make_instr_insert_element(proc, v, elem, lval.index)); - return ssa_emit_store(proc, lval.address, out); + return ssa_emit_store(proc, lval.addr, out); + } else { + value = ssa_emit_conv(proc, value, ssa_type(lval)); + return ssa_emit_store(proc, lval.addr, value); } - return ssa_emit_store(proc, lval.address, value); } return NULL; } -ssaValue *ssa_lvalue_load(ssaProcedure *proc, ssaLvalue lval) { - if (lval.address != NULL) { +ssaValue *ssa_lvalue_load(ssaProcedure *proc, ssaAddr lval) { + if (lval.addr != NULL) { if (lval.is_vector) { // HACK(bill): Fix how lvalues for vectors work - ssaValue *v = ssa_emit_load(proc, lval.address); + ssaValue *v = ssa_emit_load(proc, lval.addr); return ssa_emit(proc, ssa_make_instr_extract_element(proc, v, lval.index)); } - return ssa_emit_load(proc, lval.address); + return ssa_emit_load(proc, lval.addr); } GB_PANIC("Illegal lvalue load"); return NULL; @@ -957,12 +915,6 @@ void ssa_end_procedure_body(ssaProcedure *proc) { } -#if 0 - gb_for_array(i, proc->defer_stmts) { - gb_printf("defer %td - %p\n", proc->defer_stmts[i].scope_index, proc->defer_stmts[i].stmt); - } -#endif - // Number blocks and registers i32 reg_id = 0; gb_for_array(i, proc->blocks) { @@ -971,7 +923,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) { gb_for_array(j, b->instrs) { ssaValue *value = b->instrs[j]; GB_ASSERT(value->kind == ssaValue_Instr); - ssaInstr *instr = &value->instr; + ssaInstr *instr = &value->Instr; // NOTE(bill): Ignore non-returning instructions switch (instr->kind) { case ssaInstr_Store: @@ -982,7 +934,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) { case ssaInstr_StartupRuntime: continue; case ssaInstr_Call: - if (instr->call.type == NULL) { + if (instr->Call.type == NULL) { continue; } break; @@ -1016,7 +968,7 @@ ssaValue *ssa_emit_arith(ssaProcedure *proc, Token op, ssaValue *left, ssaValue ssaValue *neg = ssa_make_value_constant(proc->module->allocator, type, make_exact_value_integer(-1)); op.kind = Token_Xor; right = ssa_emit_arith(proc, op, right, neg, type); - ssa_value_set_type(right, type); + ssa_set_type(right, type); op.kind = Token_And; } /* fallthrough */ case Token_Add: @@ -1033,20 +985,20 @@ ssaValue *ssa_emit_arith(ssaProcedure *proc, Token op, ssaValue *left, ssaValue } ssaValue *v = ssa_make_instr_binary_op(proc, op, left, right); - ssa_value_set_type(v, type); + ssa_set_type(v, type); return ssa_emit(proc, v); } ssaValue *ssa_emit_comp(ssaProcedure *proc, Token op, ssaValue *left, ssaValue *right) { - Type *a = get_base_type(ssa_value_type(left)); - Type *b = get_base_type(ssa_value_type(right)); + Type *a = get_base_type(ssa_type(left)); + Type *b = get_base_type(ssa_type(right)); if (are_types_identical(a, b)) { // NOTE(bill): No need for a conversion } else if (left->kind == ssaValue_Constant) { - left = ssa_emit_conv(proc, left, ssa_value_type(right)); + left = ssa_emit_conv(proc, left, ssa_type(right)); } else if (right->kind == ssaValue_Constant) { - right = ssa_emit_conv(proc, right, ssa_value_type(left)); + right = ssa_emit_conv(proc, right, ssa_type(left)); } ssaValue *v = ssa_make_instr_binary_op(proc, op, left, right); @@ -1054,17 +1006,17 @@ ssaValue *ssa_emit_comp(ssaProcedure *proc, Token op, ssaValue *left, ssaValue * if (is_type_vector(a)) { result = make_type_vector(proc->module->allocator, t_bool, a->vector.count); } - ssa_value_set_type(v, result); + ssa_set_type(v, result); return ssa_emit(proc, v); } ssaValue *ssa_emit_ptr_offset(ssaProcedure *proc, ssaValue *ptr, ssaValue *offset) { - Type *type = ssa_value_type(ptr); + Type *type = ssa_type(ptr); ssaValue *gep = NULL; offset = ssa_emit_conv(proc, offset, t_int); gep = ssa_make_instr_get_element_ptr(proc, ptr, offset, NULL, 1, false); - gep->instr.get_element_ptr.elem_type = type_deref(type); - gep->instr.get_element_ptr.result_type = type; + gep->Instr.GetElementPtr.elem_type = type_deref(type); + gep->Instr.GetElementPtr.result_type = type; return ssa_emit(proc, gep); } @@ -1072,8 +1024,8 @@ ssaValue *ssa_emit_zero_gep(ssaProcedure *proc, ssaValue *s) { ssaValue *gep = NULL; // NOTE(bill): For some weird legacy reason in LLVM, structure elements must be accessed as an i32 gep = ssa_make_instr_get_element_ptr(proc, s, NULL, NULL, 0, true); - gep->instr.get_element_ptr.elem_type = ssa_value_type(s); - gep->instr.get_element_ptr.result_type = ssa_value_type(s); + gep->Instr.GetElementPtr.elem_type = ssa_type(s); + gep->Instr.GetElementPtr.result_type = ssa_type(s); return ssa_emit(proc, gep); } @@ -1082,8 +1034,8 @@ ssaValue *ssa_emit_struct_gep(ssaProcedure *proc, ssaValue *s, ssaValue *index, // NOTE(bill): For some weird legacy reason in LLVM, structure elements must be accessed as an i32 index = ssa_emit_conv(proc, index, t_i32); gep = ssa_make_instr_get_element_ptr(proc, s, v_zero, index, 2, true); - gep->instr.get_element_ptr.elem_type = ssa_value_type(s); - gep->instr.get_element_ptr.result_type = result_type; + gep->Instr.GetElementPtr.elem_type = ssa_type(s); + gep->Instr.GetElementPtr.result_type = result_type; return ssa_emit(proc, gep); } @@ -1102,17 +1054,17 @@ ssaValue *ssa_emit_struct_ev(ssaProcedure *proc, ssaValue *s, i32 index, Type *r ssaValue *ssa_array_elem(ssaProcedure *proc, ssaValue *array) { - Type *t = ssa_value_type(array); + Type *t = ssa_type(array); GB_ASSERT(t->kind == Type_Array); Type *base_type = t->array.elem; ssaValue *elem = ssa_make_instr_get_element_ptr(proc, array, v_zero, v_zero, 2, true); Type *result_type = make_type_pointer(proc->module->allocator, base_type); - elem->instr.get_element_ptr.elem_type = t; - elem->instr.get_element_ptr.result_type = result_type; + elem->Instr.GetElementPtr.elem_type = t; + elem->Instr.GetElementPtr.result_type = result_type; return ssa_emit(proc, elem); } ssaValue *ssa_array_len(ssaProcedure *proc, ssaValue *array) { - Type *t = ssa_value_type(array); + Type *t = ssa_type(array); GB_ASSERT(t->kind == Type_Array); return ssa_make_value_constant(proc->module->allocator, t_int, make_exact_value_integer(t->array.count)); } @@ -1121,35 +1073,35 @@ ssaValue *ssa_array_cap(ssaProcedure *proc, ssaValue *array) { } ssaValue *ssa_slice_elem(ssaProcedure *proc, ssaValue *slice) { - Type *t = ssa_value_type(slice); + Type *t = ssa_type(slice); GB_ASSERT(t->kind == Type_Slice); Type *result_type = make_type_pointer(proc->module->allocator, t->slice.elem); return ssa_emit_load(proc, ssa_emit_struct_gep(proc, slice, v_zero32, result_type)); } ssaValue *ssa_slice_len(ssaProcedure *proc, ssaValue *slice) { - Type *t = ssa_value_type(slice); + Type *t = ssa_type(slice); GB_ASSERT(t->kind == Type_Slice); return ssa_emit_load(proc, ssa_emit_struct_gep(proc, slice, v_one32, t_int)); } ssaValue *ssa_slice_cap(ssaProcedure *proc, ssaValue *slice) { - Type *t = ssa_value_type(slice); + Type *t = ssa_type(slice); GB_ASSERT(t->kind == Type_Slice); return ssa_emit_load(proc, ssa_emit_struct_gep(proc, slice, v_two32, t_int)); } ssaValue *ssa_string_elem(ssaProcedure *proc, ssaValue *string) { - Type *t = ssa_value_type(string); + Type *t = ssa_type(string); GB_ASSERT(t->kind == Type_Basic && t->basic.kind == Basic_string); Type *base_type = t_u8; ssaValue *elem = ssa_make_instr_get_element_ptr(proc, string, v_zero, v_zero32, 2, true); Type *result_type = make_type_pointer(proc->module->allocator, base_type); - elem->instr.get_element_ptr.elem_type = t; - elem->instr.get_element_ptr.result_type = result_type; + elem->Instr.GetElementPtr.elem_type = t; + elem->Instr.GetElementPtr.result_type = result_type; return ssa_emit_load(proc, ssa_emit(proc, elem)); } ssaValue *ssa_string_len(ssaProcedure *proc, ssaValue *string) { - Type *t = ssa_value_type(string); + Type *t = ssa_type(string); GB_ASSERT(t->kind == Type_Basic && t->basic.kind == Basic_string); return ssa_emit_load(proc, ssa_emit_struct_gep(proc, string, v_one32, t_int)); } @@ -1160,7 +1112,7 @@ ssaValue *ssa_emit_slice(ssaProcedure *proc, Type *slice_type, ssaValue *base, s // TODO(bill): array bounds checking for slice creation // TODO(bill): check that low < high <= max gbAllocator a = proc->module->allocator; - Type *base_type = get_base_type(ssa_value_type(base)); + Type *base_type = get_base_type(ssa_type(base)); if (low == NULL) { low = v_zero; @@ -1197,7 +1149,7 @@ ssaValue *ssa_emit_slice(ssaProcedure *proc, Type *slice_type, ssaValue *base, s ssaValue *slice = ssa_add_local_generated(proc, slice_type); ssaValue *gep = NULL; - gep = ssa_emit_struct_gep(proc, slice, v_zero32, ssa_value_type(elem)); + gep = ssa_emit_struct_gep(proc, slice, v_zero32, ssa_type(elem)); ssa_emit_store(proc, gep, elem); gep = ssa_emit_struct_gep(proc, slice, v_one32, t_int); @@ -1210,7 +1162,7 @@ ssaValue *ssa_emit_slice(ssaProcedure *proc, Type *slice_type, ssaValue *base, s } ssaValue *ssa_emit_substring(ssaProcedure *proc, ssaValue *base, ssaValue *low, ssaValue *high) { - Type *bt = get_base_type(ssa_value_type(base)); + Type *bt = get_base_type(ssa_type(base)); GB_ASSERT(bt == t_string); if (low == NULL) { low = v_zero; @@ -1228,7 +1180,7 @@ ssaValue *ssa_emit_substring(ssaProcedure *proc, ssaValue *base, ssaValue *low, ssaValue *str, *gep; str = ssa_add_local_generated(proc, t_string); - gep = ssa_emit_struct_gep(proc, str, v_zero32, ssa_value_type(elem)); + gep = ssa_emit_struct_gep(proc, str, v_zero32, ssa_type(elem)); ssa_emit_store(proc, gep, elem); gep = ssa_emit_struct_gep(proc, str, v_one32, t_int); @@ -1261,7 +1213,7 @@ ssaValue *ssa_add_global_string_array(ssaProcedure *proc, ExactValue value) { } ssaValue *ssa_emit_string(ssaProcedure *proc, ssaValue *elem, ssaValue *len) { - Type *t_u8_ptr = ssa_value_type(elem); + Type *t_u8_ptr = ssa_type(elem); GB_ASSERT(t_u8_ptr->kind == Type_Pointer); GB_ASSERT(is_type_u8(t_u8_ptr->pointer.elem)); @@ -1278,7 +1230,7 @@ ssaValue *ssa_emit_string(ssaProcedure *proc, ssaValue *elem, ssaValue *len) { ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) { - Type *src_type = ssa_value_type(value); + Type *src_type = ssa_type(value); if (are_types_identical(t, src_type)) { return value; } @@ -1291,7 +1243,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) { if (value->kind == ssaValue_Constant) { if (dst->kind == Type_Basic) { - ExactValue ev = value->constant.value; + ExactValue ev = value->Constant.value; if (is_type_float(dst)) { ev = exact_value_to_float(ev); } else if (is_type_string(dst)) { @@ -1382,6 +1334,16 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) { return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst)); } + // pointer -> proc + if (is_type_pointer(src) && is_type_proc(dst)) { + return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst)); + } + // proc -> pointer + if (is_type_proc(src) && is_type_pointer(dst)) { + return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst)); + } + + // []byte/[]u8 <-> string if (is_type_u8_slice(src) && is_type_string(dst)) { @@ -1395,7 +1357,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) { ssaValue *str = ssa_add_local_generated(proc, src); ssa_emit_store(proc, str, value); ssaValue *elem = ssa_string_elem(proc, str); - ssaValue *elem_ptr = ssa_add_local_generated(proc, ssa_value_type(elem)); + ssaValue *elem_ptr = ssa_add_local_generated(proc, ssa_type(elem)); ssa_emit_store(proc, elem_ptr, elem); ssaValue *len = ssa_string_len(proc, str); @@ -1403,22 +1365,22 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) { return ssa_emit_load(proc, slice); } - // if (is_type_vector(dst)) { - // Type *dst_elem = dst->vector.elem; - // value = ssa_emit_conv(proc, value, dst_elem); - // ssaValue *v = ssa_add_local_generated(proc, t); - // v = ssa_emit_load(proc, v); - // v = ssa_emit(proc, ssa_make_instr_insert_element(proc, v, value, v_zero32)); - // // NOTE(bill): Broadcast lowest value to all values - // isize index_count = dst->vector.count; - // i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count); - // for (isize i = 0; i < index_count; i++) { - // indices[i] = 0; - // } + if (is_type_vector(dst)) { + Type *dst_elem = dst->vector.elem; + value = ssa_emit_conv(proc, value, dst_elem); + ssaValue *v = ssa_add_local_generated(proc, t); + v = ssa_emit_load(proc, v); + v = ssa_emit(proc, ssa_make_instr_insert_element(proc, v, value, v_zero32)); + // NOTE(bill): Broadcast lowest value to all values + isize index_count = dst->vector.count; + i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count); + for (isize i = 0; i < index_count; i++) { + indices[i] = 0; + } - // v = ssa_emit(proc, ssa_make_instr_shuffle_vector(proc, v, indices, index_count)); - // return v; - // } + v = ssa_emit(proc, ssa_make_instr_shuffle_vector(proc, v, indices, index_count)); + return v; + } gb_printf_err("Not Identical %s != %s\n", type_to_string(src_type), type_to_string(t)); @@ -1432,7 +1394,7 @@ 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); + Type *src_type = ssa_type(value); if (are_types_identical(t, src_type)) { return value; } @@ -1497,8 +1459,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case_ast_node(ue, UnaryExpr, expr); switch (ue->op.kind) { case Token_Pointer: { - ssaValue *v = ssa_emit_zero_gep(proc, ssa_build_addr(proc, ue->expr).address); - ssa_value_set_type(v, type_of_expr(proc->module->info, expr)); + ssaValue *v = ssa_emit_zero_gep(proc, ssa_build_addr(proc, ue->expr).addr); + ssa_set_type(v, type_of_expr(proc->module->info, expr)); return v; } case Token_Add: @@ -1578,9 +1540,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue *value = ssa_make_value_procedure(proc->module->allocator, proc->module, type, pl->type, pl->body, name); - value->proc.tags = pl->tags; + value->Proc.tags = pl->tags; - gb_array_append(proc->children, &value->proc); + gb_array_append(proc->children, &value->Proc); ssa_build_proc(value, proc); return value; @@ -1609,7 +1571,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue elem != NULL; elem = elem->next, index++) { ssaValue *field_elem = ssa_build_expr(proc, elem); - Type *t = ssa_value_type(field_elem); + Type *t = ssa_type(field_elem); GB_ASSERT(t->kind != Type_Tuple); ssaValue *ev = ssa_emit_conv(proc, field_elem, et); ssaValue *i = ssa_make_value_constant(proc->module->allocator, t_int, make_exact_value_integer(index)); @@ -1649,7 +1611,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue field_expr = ssa_build_expr(proc, elem); } - GB_ASSERT(ssa_value_type(field_expr)->kind != Type_Tuple); + GB_ASSERT(ssa_type(field_expr)->kind != Type_Tuple); field = st->fields[field_index]; @@ -1666,7 +1628,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue elem != NULL; elem = elem->next, index++) { ssaValue *field_expr = ssa_build_expr(proc, elem); - Type *t = ssa_value_type(field_expr); + Type *t = ssa_type(field_expr); GB_ASSERT(t->kind != Type_Tuple); ssaValue *ev = ssa_emit_conv(proc, field_expr, et); ssaValue *gep = ssa_emit_struct_gep(proc, v, index, et); @@ -1681,7 +1643,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue elem != NULL; elem = elem->next, index++) { ssaValue *field_expr = ssa_build_expr(proc, elem); - Type *t = ssa_value_type(field_expr); + Type *t = ssa_type(field_expr); GB_ASSERT(t->kind != Type_Tuple); ssaValue *ev = ssa_emit_conv(proc, field_expr, et); ssaValue *gep = ssa_emit_struct_gep(proc, array, index, et); @@ -1692,7 +1654,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue make_type_pointer(proc->module->allocator, et)); ssaValue *len = ssa_array_len(proc, array); ssaValue *gep = NULL; - gep = ssa_emit_struct_gep(proc, v, v_zero32, ssa_value_type(elem)); + gep = ssa_emit_struct_gep(proc, v, v_zero32, ssa_type(elem)); ssa_emit_store(proc, gep, elem); gep = ssa_emit_struct_gep(proc, v, v_one32, t_int); ssa_emit_store(proc, gep, len); @@ -1714,8 +1676,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case BuiltinProc_len: { // len :: proc(Type) -> int // NOTE(bill): len of an array is a constant expression - ssaValue *v = ssa_build_addr(proc, ce->arg_list).address; - Type *t = get_base_type(ssa_value_type(v)); + ssaValue *v = ssa_build_addr(proc, ce->arg_list).addr; + Type *t = get_base_type(ssa_type(v)); if (t == t_string) return ssa_string_len(proc, v); else if (t->kind == Type_Slice) @@ -1724,17 +1686,17 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case BuiltinProc_cap: { // cap :: proc(Type) -> int // NOTE(bill): cap of an array is a constant expression - ssaValue *v = ssa_build_addr(proc, ce->arg_list).address; - Type *t = get_base_type(ssa_value_type(v)); + ssaValue *v = ssa_build_addr(proc, ce->arg_list).addr; + Type *t = get_base_type(ssa_type(v)); return ssa_slice_cap(proc, v); } break; case BuiltinProc_copy: { // copy :: proc(dst, src: []Type) -> int AstNode *dst_node = ce->arg_list; AstNode *src_node = ce->arg_list->next; - ssaValue *dst_slice = ssa_build_addr(proc, dst_node).address; - ssaValue *src_slice = ssa_build_addr(proc, src_node).address; - Type *slice_type = get_base_type(ssa_value_type(dst_slice)); + ssaValue *dst_slice = ssa_build_addr(proc, dst_node).addr; + ssaValue *src_slice = ssa_build_addr(proc, src_node).addr; + Type *slice_type = get_base_type(ssa_type(dst_slice)); GB_ASSERT(slice_type->kind == Type_Slice); Type *elem_type = slice_type->slice.elem; i64 size_of_elem = type_size_of(proc->module->sizes, proc->module->allocator, elem_type); @@ -1764,13 +1726,13 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue // 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 *slice = ssa_build_addr(proc, sptr_node).addr; ssaValue *elem = ssa_slice_elem(proc, slice); ssaValue *len = ssa_slice_len(proc, slice); ssaValue *cap = ssa_slice_cap(proc, slice); - Type *elem_type = type_deref(get_base_type(ssa_value_type(elem))); + Type *elem_type = type_deref(ssa_type(elem)); ssaValue *item_value = ssa_build_expr(proc, item_node); item_value = ssa_emit_conv(proc, item_value, elem_type); @@ -1795,7 +1757,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue make_exact_value_integer(item_size)); offset = ssa_emit_conv(proc, offset, t_rawptr); item = ssa_emit_ptr_offset(proc, item, v_zero); - ssa_value_set_type(item, make_type_pointer(proc->module->allocator, ssa_value_type(item))); + ssa_set_type(item, make_type_pointer(proc->module->allocator, ssa_type(item))); item = ssa_emit_conv(proc, item, t_rawptr); ssa_emit(proc, ssa_make_instr_copy_memory(proc, offset, item, byte_count, 1, false)); @@ -1838,7 +1800,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue // NOTE(bill): Regular call ssaValue *value = ssa_build_expr(proc, ce->proc); - Type *proc_type_ = get_base_type(ssa_value_type(value)); + Type *proc_type_ = get_base_type(ssa_type(value)); GB_ASSERT(proc_type_->kind == Type_Proc); auto *type = &proc_type_->proc; @@ -1848,7 +1810,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue for (AstNode *arg = ce->arg_list; arg != NULL; arg = arg->next) { ssaValue *a = ssa_build_expr(proc, arg); - Type *at = ssa_value_type(a); + Type *at = ssa_type(a); if (at->kind == Type_Tuple) { for (isize i = 0; i < at->tuple.variable_count; i++) { Entity *e = at->tuple.variables[i]; @@ -1870,11 +1832,11 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case_end; case_ast_node(se, SliceExpr, expr); - return ssa_emit_load(proc, ssa_build_addr(proc, expr).address); + return ssa_emit_load(proc, ssa_build_addr(proc, expr).addr); case_end; case_ast_node(ie, IndexExpr, expr); - return ssa_emit_load(proc, ssa_build_addr(proc, expr).address); + return ssa_emit_load(proc, ssa_build_addr(proc, expr).addr); case_end; } @@ -1902,7 +1864,7 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) { ssaValue *value = NULL; if (tv->mode == Addressing_Variable) { - ssaLvalue addr = ssa_build_addr(proc, expr); + ssaAddr addr = ssa_build_addr(proc, expr); value = ssa_lvalue_load(proc, addr); } else { value = ssa_build_single_expr(proc, expr, tv); @@ -1912,11 +1874,11 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) { } -ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { +ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { switch (expr->kind) { case_ast_node(i, Ident, expr); if (ssa_is_blank_ident(expr)) { - ssaLvalue val = {}; + ssaAddr val = {}; return val; } @@ -1928,7 +1890,7 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { } else { GB_PANIC("Unknown value: %s, entity: %p\n", expr_to_string(expr), e); } - return ssa_make_lvalue(v, expr); + return ssa_make_addr(v, expr); case_end; case_ast_node(pe, ParenExpr, expr); @@ -1942,27 +1904,27 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { Entity *entity = lookup_field(type, unparen_expr(se->selector), &field_index); GB_ASSERT(entity != NULL); - ssaValue *e = ssa_build_addr(proc, se->expr).address; + ssaValue *e = ssa_build_addr(proc, se->expr).addr; if (is_type_pointer(type)) { // NOTE(bill): Allow x^.y and x.y to be the same e = ssa_emit_load(proc, e); e = ssa_emit_ptr_offset(proc, e, v_zero); - ssa_value_set_type(e, type_deref(type)); + ssa_set_type(e, type_deref(type)); } ssaValue *v = ssa_emit_struct_gep(proc, e, field_index, entity->type); - return ssa_make_lvalue(v, expr); + return ssa_make_addr(v, expr); case_end; case_ast_node(ue, UnaryExpr, expr); switch (ue->op.kind) { case Token_Pointer: { - ssaLvalue lval = ssa_build_addr(proc, ue->expr); - // ssaValue *v = ssa_emit_zero_gep(proc, lval.address); - // Type *t = ssa_value_type(lval.address); - // ssa_value_set_type(lval.address, make_type_pointer(proc->module->allocator, t)); - // return ssa_make_lvalue(v, expr); + ssaAddr lval = ssa_build_addr(proc, ue->expr); + // ssaValue *v = ssa_emit_zero_gep(proc, lval.addr); + // Type *t = ssa_type(lval.addr); + // ssa_set_type(lval.addr, make_type_pointer(proc->module->allocator, t)); + // return ssa_make_addr(v, expr); return lval; } default: @@ -1978,7 +1940,7 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { 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); + return ssa_make_addr(v, expr); } case Token_transmute: { // HACK(bill): Do have to make new variable to do this? @@ -1986,7 +1948,7 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { 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); + return ssa_make_addr(v, expr); } default: GB_PANIC("Invalid binary expression for ssa_build_addr: %.*s\n", LIT(be->op.string)); @@ -2001,18 +1963,18 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { switch (t->kind) { case Type_Vector: { // HACK(bill): Fix how lvalues for vectors work - ssaValue *vector = ssa_build_addr(proc, ie->expr).address; + ssaValue *vector = ssa_build_addr(proc, ie->expr).addr; ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int); - return ssa_make_lvalue_vector(vector, index, expr); + return ssa_make_addr_vector(vector, index, expr); } break; case Type_Array: { - ssaValue *array = ssa_build_addr(proc, ie->expr).address; + ssaValue *array = ssa_build_addr(proc, ie->expr).addr; elem = ssa_array_elem(proc, array); } break; case Type_Slice: { - ssaValue *slice = ssa_build_addr(proc, ie->expr).address; + ssaValue *slice = ssa_build_addr(proc, ie->expr).addr; elem = ssa_slice_elem(proc, slice); } break; case Type_Basic: { // Basic_string @@ -2021,21 +1983,21 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { ssaValue *array = ssa_add_global_string_array(proc, tv->value); elem = ssa_array_elem(proc, array); } else { - elem = ssa_string_elem(proc, ssa_build_addr(proc, ie->expr).address); + elem = ssa_string_elem(proc, ssa_build_addr(proc, ie->expr).addr); } } break; case Type_Pointer: { - elem = ssa_emit_load(proc, ssa_build_addr(proc, ie->expr).address); + elem = ssa_emit_load(proc, ssa_build_addr(proc, ie->expr).addr); } break; } ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int); v = ssa_emit_ptr_offset(proc, elem, index); - Type *lval_type = type_deref(ssa_value_type(v)); + Type *lval_type = type_deref(ssa_type(v)); // gb_printf("%s\n", type_to_string(lval_type)); - ssa_value_set_type(v, lval_type); - return ssa_make_lvalue(v, expr); + ssa_set_type(v, lval_type); + return ssa_make_addr(v, expr); case_end; case_ast_node(se, SliceExpr, expr); @@ -2051,13 +2013,13 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { switch (type->kind) { case Type_Slice: case Type_Array: { - ssaValue *base = ssa_build_addr(proc, se->expr).address; - return ssa_make_lvalue(ssa_emit_slice(proc, type, base, low, high, max), expr); + ssaValue *base = ssa_build_addr(proc, se->expr).addr; + return ssa_make_addr(ssa_emit_slice(proc, type, base, low, high, max), expr); } break; case Type_Basic: { // NOTE(bill): max is not needed - ssaValue *base = ssa_build_addr(proc, se->expr).address; - return ssa_make_lvalue(ssa_emit_substring(proc, base, low, high), expr); + ssaValue *base = ssa_build_addr(proc, se->expr).addr; + return ssa_make_addr(ssa_emit_substring(proc, base, low, high), expr); } break; } @@ -2065,13 +2027,13 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { case_end; case_ast_node(de, DerefExpr, expr); - ssaValue *e = ssa_emit_load(proc, ssa_build_addr(proc, de->expr).address); + ssaValue *e = ssa_emit_load(proc, ssa_build_addr(proc, de->expr).addr); ssaValue *gep = ssa_make_instr_get_element_ptr(proc, e, NULL, NULL, 0, false); - Type *t = type_deref(get_base_type(ssa_value_type(e))); - gep->instr.get_element_ptr.result_type = t; - gep->instr.get_element_ptr.elem_type = t; + Type *t = type_deref(ssa_type(e)); + gep->Instr.GetElementPtr.result_type = t; + gep->Instr.GetElementPtr.elem_type = t; ssaValue *v = ssa_emit(proc, gep); - return ssa_make_lvalue(v, expr); + return ssa_make_addr(v, expr); case_end; } @@ -2079,13 +2041,13 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { "\tAstNode: %.*s\n", LIT(ast_node_strings[expr->kind])); - return ssa_make_lvalue(NULL, NULL); + return ssa_make_addr(NULL, NULL); } -void ssa_build_assign_op(ssaProcedure *proc, ssaLvalue lhs, ssaValue *value, Token op) { +void ssa_build_assign_op(ssaProcedure *proc, ssaAddr lhs, ssaValue *value, Token op) { ssaValue *old_value = ssa_lvalue_load(proc, lhs); - ssaValue *change = ssa_emit_conv(proc, value, ssa_value_type(old_value)); - ssaValue *new_value = ssa_emit_arith(proc, op, old_value, change, ssa_lvalue_type(lhs)); + ssaValue *change = ssa_emit_conv(proc, value, ssa_type(old_value)); + ssaValue *new_value = ssa_emit_arith(proc, op, old_value, change, ssa_type(old_value)); ssa_lvalue_store(proc, lhs, new_value); } @@ -2139,7 +2101,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_ast_node(vd, VarDecl, node); if (vd->kind == Declaration_Mutable) { if (vd->name_count == vd->value_count) { // 1:1 assigment - gbArray(ssaLvalue) lvals; + gbArray(ssaAddr) lvals; gbArray(ssaValue *) inits; gb_array_init_reserve(lvals, gb_heap_allocator(), vd->name_count); gb_array_init_reserve(inits, gb_heap_allocator(), vd->name_count); @@ -2147,11 +2109,11 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { defer (gb_array_free(inits)); for (AstNode *name = vd->name_list; name != NULL; name = name->next) { - ssaLvalue lval = ssa_make_lvalue(NULL, NULL); + ssaAddr lval = ssa_make_addr(NULL, NULL); if (!ssa_is_blank_ident(name)) { ssa_add_local_for_identifier(proc, name); lval = ssa_build_addr(proc, name); - GB_ASSERT(lval.address != NULL); + GB_ASSERT(lval.addr != NULL); } gb_array_append(lvals, lval); @@ -2164,10 +2126,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { gb_for_array(i, inits) { - if (lvals[i].address != NULL) { - ssaValue *v = ssa_emit_conv(proc, inits[i], ssa_value_type(lvals[i].address)); - ssa_lvalue_store(proc, lvals[i], v); - } + ssaValue *v = ssa_emit_conv(proc, inits[i], ssa_type(lvals[i])); + ssa_lvalue_store(proc, lvals[i], v); } } else if (vd->value_count == 0) { // declared and zero-initialized @@ -2177,7 +2137,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { } } } else { // Tuple(s) - gbArray(ssaLvalue) lvals; + gbArray(ssaAddr) lvals; gbArray(ssaValue *) inits; gb_array_init_reserve(lvals, gb_heap_allocator(), vd->name_count); gb_array_init_reserve(inits, gb_heap_allocator(), vd->name_count); @@ -2185,7 +2145,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { defer (gb_array_free(inits)); for (AstNode *name = vd->name_list; name != NULL; name = name->next) { - ssaLvalue lval = ssa_make_lvalue(NULL, NULL); + ssaAddr lval = ssa_make_addr(NULL, NULL); if (!ssa_is_blank_ident(name)) { ssa_add_local_for_identifier(proc, name); lval = ssa_build_addr(proc, name); @@ -2196,7 +2156,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { for (AstNode *value = vd->value_list; value != NULL; value = value->next) { ssaValue *init = ssa_build_expr(proc, value); - Type *t = ssa_value_type(init); + Type *t = ssa_type(init); if (t->kind == Type_Tuple) { for (isize i = 0; i < t->tuple.variable_count; i++) { Entity *e = t->tuple.variables[i]; @@ -2210,7 +2170,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { gb_for_array(i, inits) { - ssaValue *v = ssa_emit_conv(proc, inits[i], ssa_value_type(lvals[i].address)); + ssaValue *v = ssa_emit_conv(proc, inits[i], ssa_type(lvals[i])); ssa_lvalue_store(proc, lvals[i], v); } } @@ -2239,10 +2199,10 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ssaValue *value = ssa_make_value_procedure(proc->module->allocator, proc->module, e->type, pd->type, pd->body, name); - value->proc.tags = pd->tags; + value->Proc.tags = pd->tags; ssa_module_add_value(proc->module, e, value); - gb_array_append(proc->children, &value->proc); + gb_array_append(proc->children, &value->Proc); ssa_build_proc(value, proc); } else { String name = pd->name->Ident.token.string; @@ -2256,7 +2216,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { 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); + gb_array_append(proc->children, &value->Proc); ssa_build_proc(value, proc); } case_end; @@ -2290,8 +2250,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { } else if (op.kind == Token_Decrement) { op.kind = Token_Sub; } - ssaLvalue lval = ssa_build_addr(proc, ids->expr); - ssaValue *one = ssa_emit_conv(proc, v_one, ssa_lvalue_type(lval)); + ssaAddr lval = ssa_build_addr(proc, ids->expr); + ssaValue *one = ssa_emit_conv(proc, v_one, ssa_type(lval)); ssa_build_assign_op(proc, lval, one, op); case_end; @@ -2299,14 +2259,14 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_ast_node(as, AssignStmt, node); switch (as->op.kind) { case Token_Eq: { - gbArray(ssaLvalue) lvals; + gbArray(ssaAddr) lvals; gb_array_init(lvals, gb_heap_allocator()); defer (gb_array_free(lvals)); for (AstNode *lhs = as->lhs_list; lhs != NULL; lhs = lhs->next) { - ssaLvalue lval = {}; + ssaAddr lval = {}; if (!ssa_is_blank_ident(lhs)) { lval = ssa_build_addr(proc, lhs); } @@ -2339,7 +2299,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { for (AstNode *rhs = as->rhs_list; rhs != NULL; rhs = rhs->next) { ssaValue *init = ssa_build_expr(proc, rhs); - Type *t = ssa_value_type(init); + Type *t = ssa_type(init); // TODO(bill): refactor for code reuse as this is repeated a bit if (t->kind == Type_Tuple) { for (isize i = 0; i < t->tuple.variable_count; i++) { @@ -2366,7 +2326,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { i32 kind = op.kind; kind += Token_Add - Token_AddEq; // Convert += to + op.kind = cast(TokenKind)kind; - ssaLvalue lhs = ssa_build_addr(proc, as->lhs_list); + ssaAddr lhs = ssa_build_addr(proc, as->lhs_list); ssaValue *value = ssa_build_expr(proc, as->rhs_list); ssa_build_assign_op(proc, lhs, value, op); } break; @@ -2402,7 +2362,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { } else if (return_count == 1) { Entity *e = return_type_tuple->variables[0]; v = ssa_build_expr(proc, rs->result_list); - ssa_value_set_type(v, e->type); + ssa_set_type(v, e->type); } else if (return_count == 0) { // No return values } else { @@ -2416,7 +2376,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { i++, r = r->next) { Entity *e = return_type_tuple->variables[i]; ssaValue *res = ssa_build_expr(proc, r); - ssa_value_set_type(res, e->type); + ssa_set_type(res, e->type); ssaValue *field = ssa_emit_struct_gep(proc, v, i, e->type); ssa_emit_store(proc, field, res); } @@ -2547,11 +2507,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { void ssa_emit_startup_runtime(ssaProcedure *proc) { GB_ASSERT(proc->parent == NULL && are_strings_equal(proc->name, make_string("main"))); - ssaValue *v = ssa_alloc_instr(proc->module->allocator, ssaInstr_StartupRuntime); - if (proc->curr_block) { - gb_array_append(proc->curr_block->values, v); - } - ssa_emit(proc, v); + ssa_emit(proc, ssa_alloc_instr(proc, ssaInstr_StartupRuntime)); } void ssa_insert_code_before_proc(ssaProcedure* proc, ssaProcedure *parent) { @@ -2564,7 +2520,7 @@ void ssa_insert_code_before_proc(ssaProcedure* proc, ssaProcedure *parent) { void ssa_build_proc(ssaValue *value, ssaProcedure *parent) { - ssaProcedure *proc = &value->proc; + ssaProcedure *proc = &value->Proc; proc->parent = parent; diff --git a/src/parser.cpp b/src/parser.cpp index 051cd9779..c10c98184 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -77,6 +77,10 @@ enum ProcTag { ProcTag_no_inline = GB_BIT(2), }; +enum VarDeclTag { + VarDeclTag_thread_local = GB_BIT(0), +}; + #define AST_NODE_KINDS \ AST_NODE_KIND(Invalid, struct{}) \ AST_NODE_KIND(BasicLit, Token) \ @@ -165,6 +169,7 @@ AST_NODE_KIND(_DeclBegin, struct{}) \ AST_NODE_KIND(BadDecl, struct { Token begin, end; }) \ AST_NODE_KIND(VarDecl, struct { \ DeclKind kind; \ + u32 tags; \ AstNode *name_list; \ AstNode *type; \ AstNode *value_list; \ @@ -177,7 +182,7 @@ AST_NODE_KIND(_DeclBegin, struct{}) \ u64 tags; \ String foreign_name; \ }) \ - AST_NODE_KIND(TypeDecl, struct { Token token; AstNode *name, *type; }) \ + AST_NODE_KIND(TypeDecl, struct { Token token; AstNode *name, *type; }) \ AST_NODE_KIND(LoadDecl, struct { Token token, filepath; }) \ AST_NODE_KIND(_DeclEnd, struct{}) \ AST_NODE_KIND(_TypeBegin, struct{}) \ @@ -1994,7 +1999,22 @@ AstNode *parse_stmt(AstFile *f) { } ast_file_err(f, token, "You cannot `load` within a procedure. This must be done at the file scope."); return make_bad_decl(f, token, file_path); + } else if (are_strings_equal(s->TagStmt.name.string, make_string("thread_local"))) { + AstNode *var_decl = parse_simple_stmt(f); + if (var_decl->kind != AstNode_VarDecl || + var_decl->VarDecl.kind != Declaration_Mutable) { + ast_file_err(f, token, "#thread_local may only be applied to variable declarations"); + return make_bad_decl(f, token, ast_node_token(var_decl)); + } + if (f->curr_scope != f->file_scope) { + ast_file_err(f, token, "#thread_local is only allowed at the file scope."); + return make_bad_decl(f, token, ast_node_token(var_decl)); + } + var_decl->VarDecl.tags |= VarDeclTag_thread_local; + return var_decl; } + + s->TagStmt.stmt = parse_stmt(f); // TODO(bill): Find out why this doesn't work as an argument return s; } break; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index ceabdc645..68c8918d0 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -371,25 +371,25 @@ void tokenizer_skip_whitespace(Tokenizer *t) { if (t->read_curr[0] == '/') { // Line comment // while (t->curr_rune != '\n') advance_to_next_rune(t); - } else if (t->read_curr[0] == '{') { // (Nested) Block comment /{}/ + } else if (t->read_curr[0] == '*') { // (Nested) Block comment /**/ isize comment_scope = 1; for (;;) { advance_to_next_rune(t); if (t->curr_rune == '/') { advance_to_next_rune(t); - if (t->curr_rune == '{') { + if (t->curr_rune == '*') { advance_to_next_rune(t); comment_scope++; } } - if (t->curr_rune == '}') { + if (t->curr_rune == '*') { advance_to_next_rune(t); if (t->curr_rune == '/') { advance_to_next_rune(t); comment_scope--; } } - if (comment_scope == 0) + if (comment_scope <= 0) break; } } else {