mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 23:28:48 +00:00
Implicit Context and #thread_local
This commit is contained in:
@@ -46,6 +46,7 @@ pushd %build_dir%
|
|||||||
cl %compiler_settings% "..\src\main.cpp" ^
|
cl %compiler_settings% "..\src\main.cpp" ^
|
||||||
/link %linker_settings% -OUT:%exe_name% ^
|
/link %linker_settings% -OUT:%exe_name% ^
|
||||||
&& odin run ..\examples/demo001.odin
|
&& odin run ..\examples/demo001.odin
|
||||||
|
rem odin run ..\examples/demo001.odin
|
||||||
|
|
||||||
|
|
||||||
:do_not_compile_exe
|
:do_not_compile_exe
|
||||||
|
|||||||
+1
-1
@@ -414,7 +414,7 @@ extern "C" {
|
|||||||
#ifdef STB_IMAGE_STATIC
|
#ifdef STB_IMAGE_STATIC
|
||||||
#define STBIDEF static
|
#define STBIDEF static
|
||||||
#else
|
#else
|
||||||
#define STBIDEF extern "C" __declspec(dllexport)
|
#define STBIDEF extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
+135
-57
@@ -1,6 +1,7 @@
|
|||||||
|
// Demo 001
|
||||||
#load "basic.odin"
|
#load "basic.odin"
|
||||||
#load "math.odin"
|
#load "math.odin"
|
||||||
// #load "game.odin"
|
#load "game.odin"
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
_ = hellope();
|
_ = hellope();
|
||||||
@@ -9,7 +10,8 @@ main :: proc() {
|
|||||||
constants();
|
constants();
|
||||||
types();
|
types();
|
||||||
data_control();
|
data_control();
|
||||||
// run_game();
|
|
||||||
|
run_game();
|
||||||
}
|
}
|
||||||
|
|
||||||
hellope :: proc() -> int {
|
hellope :: proc() -> int {
|
||||||
@@ -17,9 +19,22 @@ hellope :: proc() -> int {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Line comment
|
||||||
|
/*
|
||||||
|
Block Comment
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Nested /*
|
||||||
|
Block /*
|
||||||
|
Comment
|
||||||
|
*/
|
||||||
|
*/
|
||||||
|
*/
|
||||||
|
|
||||||
apple, banana, carrot: bool;
|
apple, banana, carrot: bool;
|
||||||
box, carboard: bool = true, false;
|
box, carboard: bool = true, false;
|
||||||
hellope_value := hellope();
|
hellope_value: int = hellope();
|
||||||
|
|
||||||
variables :: proc() {
|
variables :: proc() {
|
||||||
i: int; // initialized with zero value
|
i: int; // initialized with zero value
|
||||||
@@ -39,21 +54,23 @@ variables :: proc() {
|
|||||||
//
|
//
|
||||||
// f32 f64
|
// 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
|
// string
|
||||||
//
|
//
|
||||||
// byte - alias for u8
|
// byte - alias for u8
|
||||||
// rune - alias for i32 // Unicode Codepoint
|
// rune - alias for i32 // Unicode Codepoint
|
||||||
//
|
//
|
||||||
// untyped bool - "untyped" types can implicitly convert to any of the "typed" types
|
// "untyped" types can implicitly convert to any of the "typed" types
|
||||||
// untyped integer
|
// Default Type
|
||||||
// untyped float
|
// untyped bool - bool
|
||||||
// untyped pointer
|
// untyped integer - int
|
||||||
// untyped string
|
// untyped float - f64
|
||||||
// untyped rune
|
// untyped pointer - rawptr
|
||||||
|
// untyped string - string
|
||||||
|
// untyped rune - rune/i32
|
||||||
|
|
||||||
|
|
||||||
// // Zero values
|
// // Zero values
|
||||||
@@ -62,6 +79,7 @@ variables :: proc() {
|
|||||||
zero_pointer := null;
|
zero_pointer := null;
|
||||||
zero_string1 := ""; // Escaped string
|
zero_string1 := ""; // Escaped string
|
||||||
zero_string2 := ``; // Raw string
|
zero_string2 := ``; // Raw string
|
||||||
|
// Compound types have a different kind of zero value
|
||||||
|
|
||||||
// Unary operators
|
// Unary operators
|
||||||
// +a
|
// +a
|
||||||
@@ -70,28 +88,28 @@ variables :: proc() {
|
|||||||
// !a
|
// !a
|
||||||
|
|
||||||
// Binary operators
|
// Binary operators
|
||||||
// a + b
|
// a + b add
|
||||||
// a - b
|
// a - b sub
|
||||||
// a ~ b
|
// a ~ b xor
|
||||||
// a | b
|
// a | b or
|
||||||
|
|
||||||
// a * b
|
// a * b mul
|
||||||
// a / b
|
// a / b quo
|
||||||
// a % b
|
// a % b mod
|
||||||
// a & b
|
// a & b and
|
||||||
// a &~ b == a & (~b)
|
// a &~ b bitclear == a & (~b)
|
||||||
// a << b
|
// a << b shl
|
||||||
// a >> b
|
// a >> b shr
|
||||||
|
|
||||||
// a as Type
|
// a as Type // Type cast
|
||||||
// a transmute Type
|
// a transmute Type // Bit cast
|
||||||
|
|
||||||
// a == b
|
// a == b eq
|
||||||
// a != b
|
// a != b ne
|
||||||
// a < b
|
// a < b lt
|
||||||
// a > b
|
// a > b gt
|
||||||
// a <= b
|
// a <= b le
|
||||||
// a >= b
|
// a >= b ge
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,10 +133,11 @@ procedures :: proc() {
|
|||||||
print_string(b);
|
print_string(b);
|
||||||
|
|
||||||
a, b = b, a; // Quirk of grammar the of multiple assignments
|
a, b = b, a; // Quirk of grammar the of multiple assignments
|
||||||
|
// Swap variables
|
||||||
print_string(a);
|
print_string(a);
|
||||||
print_string(b);
|
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 {
|
proc1 :: proc(a, b: int) #inline {
|
||||||
print_int(a + b);
|
print_int(a + b);
|
||||||
}
|
}
|
||||||
@@ -136,6 +155,16 @@ constants :: proc() {
|
|||||||
|
|
||||||
TAU_32 : f32 : 6.28318530718;
|
TAU_32 : f32 : 6.28318530718;
|
||||||
TAU_AS_32 :: 6.28318530718 as f32;
|
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'); }
|
nl :: proc() { print_rune('\n'); }
|
||||||
@@ -147,13 +176,22 @@ types :: proc() {
|
|||||||
// z: f32 = x; // invalid
|
// z: f32 = x; // invalid
|
||||||
z: f32 = x as f32;
|
z: f32 = x as f32;
|
||||||
|
|
||||||
ptr_z := ^z; // Pascal notation
|
|
||||||
|
ptr_z := ^z; // Pascal notation
|
||||||
ptr_z^ = 123; // Derefence Notation
|
ptr_z^ = 123; // Derefence Notation
|
||||||
|
w: f32 = ptr_z^; // 123
|
||||||
print_f32(z); nl();
|
print_f32(z); nl();
|
||||||
|
|
||||||
// ^z - pointer to z
|
// ^z - pointer to z
|
||||||
// z^ - z from pointer
|
// 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: [12]f32; // Array of 12 f32
|
||||||
f32_array[0] = 2;
|
f32_array[0] = 2;
|
||||||
f32_array[1] = 3;
|
f32_array[1] = 3;
|
||||||
@@ -162,15 +200,28 @@ types :: proc() {
|
|||||||
f32_array_len := len(f32_array); // builtin procedure
|
f32_array_len := len(f32_array); // builtin procedure
|
||||||
f32_array_cap := cap(f32_array); // == len(f32_array)
|
f32_array_cap := cap(f32_array); // == len(f32_array)
|
||||||
|
|
||||||
|
|
||||||
|
mda: [2][3][4]int; // Column-major
|
||||||
|
// mda[x][y][z]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
api: [2]^f32;
|
api: [2]^f32;
|
||||||
papi: ^[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[0:5];
|
||||||
f32_slice = f32_array[:5];
|
f32_slice = f32_array[:5];
|
||||||
f32_slice = f32_array[:]; // f32_array[0:len(f32_array)-1];
|
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_success := append(^f32_slice, 1);
|
||||||
_ = append(^f32_slice, 2);
|
_ = 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
|
_ = copy(f32_array[0:2], f32_array[2:4]); // You can use memcpy/memmove if you want
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
s := "Hellope World";
|
s := "Hellope World";
|
||||||
sub_string := s[5:10];
|
sub_string: string = s[5:10];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
v0: {4}f32; // Vector of 4 f32
|
v0: {4}f32; // Vector of 4 f32
|
||||||
v0[0] = 1;
|
v0[0] = 1;
|
||||||
@@ -199,6 +258,11 @@ types :: proc() {
|
|||||||
// LLVM rant?
|
// LLVM rant?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type Vec4: {4}f32;
|
type Vec4: {4}f32;
|
||||||
type Array3Int: [3]int;
|
type Array3Int: [3]int;
|
||||||
|
|
||||||
@@ -218,7 +282,7 @@ types :: proc() {
|
|||||||
b: u16,
|
b: u16,
|
||||||
c: u32,
|
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
|
// transmute only works if the size of the types are equal
|
||||||
/{
|
/*
|
||||||
// in C
|
// in C
|
||||||
union {
|
union {
|
||||||
i32 i;
|
i32 i;
|
||||||
f32 y;
|
f32 y;
|
||||||
};
|
};
|
||||||
}/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{ // Compound Literals
|
{ // Compound Literals
|
||||||
a := [3]int{1, 2, 3};
|
a := [3]int{1, 2, 3};
|
||||||
b := [3]int{};
|
b := [3]int{};
|
||||||
@@ -293,7 +359,10 @@ types :: proc() {
|
|||||||
print_f32(i[1]); print_rune('\n');
|
print_f32(i[1]); print_rune('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
|
{ // First class procedures
|
||||||
|
|
||||||
do_thing :: proc(p: proc(a, b: int) -> int) {
|
do_thing :: proc(p: proc(a, b: int) -> int) {
|
||||||
print_int(p(3, 4)); nl();
|
print_int(p(3, 4)); nl();
|
||||||
}
|
}
|
||||||
@@ -309,11 +378,13 @@ types :: proc() {
|
|||||||
|
|
||||||
do_thing(add);
|
do_thing(add);
|
||||||
do_thing(add_lambda);
|
do_thing(add_lambda);
|
||||||
do_thing(proc(a, b: int) -> int {
|
do_thing(proc(a, b: int) -> int { // Anonymous
|
||||||
return a * b;
|
return a * b;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{ // strings and runes
|
{ // strings and runes
|
||||||
escaped := "Hellope World\n";
|
escaped := "Hellope World\n";
|
||||||
raw := `Hellope World\n`;
|
raw := `Hellope World\n`;
|
||||||
@@ -346,11 +417,12 @@ void main() {
|
|||||||
}`;
|
}`;
|
||||||
|
|
||||||
|
|
||||||
knot1 := '⌘';
|
hearts1 := '💕';
|
||||||
knot2 := '\u2318'; // 16 bit
|
hearts2 := '\U0001f495'; // 32 bit
|
||||||
knot3 := '\U00002318'; // 32 bit
|
hearts3 := "\xf0\x9f\x92\x95"; // Note it's a string, should I allow untyped string -> untyped rune casts?
|
||||||
knot4 := "\xe2\x8c\x98"; // 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.
|
// 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");
|
defer print_string("日本語\n");
|
||||||
print_string("Japanese\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!
|
// C strings, yuk!
|
||||||
to_c_string :: proc(s: string) -> ^u8 {
|
to_c_string := proc(s: string) -> ^u8 {
|
||||||
c := heap_alloc(len(s)+1) as ^u8;
|
c := alloc(len(s)+1) as ^u8;
|
||||||
mem_copy(c, ^s[0], len(s));
|
mem_copy(c, ^s[0], len(s));
|
||||||
c[len(s)] = 0;
|
c[len(s)] = 0;
|
||||||
return c;
|
return c;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
fopen :: proc(filename, mode: ^u8) -> rawptr #foreign
|
fopen :: proc(filename, mode: ^u8) -> rawptr #foreign
|
||||||
fclose :: proc(f: rawptr) -> i32 #foreign
|
fclose :: proc(f: rawptr) -> i32 #foreign
|
||||||
|
|
||||||
filename := to_c_string("../examples/base.odin");
|
filename := to_c_string("../examples/base.odin");
|
||||||
mode := to_c_string("rb");
|
mode := to_c_string("rb");
|
||||||
defer heap_free(filename);
|
defer dealloc(filename);
|
||||||
defer heap_free(mode);
|
defer dealloc(mode);
|
||||||
|
|
||||||
f := fopen(filename, mode);
|
f := fopen(filename, mode);
|
||||||
if f == null {
|
if f == null {
|
||||||
@@ -478,10 +555,10 @@ data_control :: proc() {
|
|||||||
// rest of code
|
// rest of code
|
||||||
|
|
||||||
// Better version
|
// Better version
|
||||||
/{
|
/*
|
||||||
type File: struct { filename: string }
|
type File: struct { filename: string }
|
||||||
type FileError: int
|
type FileError: int
|
||||||
open_file :: proc(filename: string) -> (File, FileError) { ... }
|
open_file :: proc(filename: string) -> (File, FileError) { ... }
|
||||||
close_file :: proc(f: ^File) { ... }
|
close_file :: proc(f: ^File) { ... }
|
||||||
f, err := open_file("Test");
|
f, err := open_file("Test");
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
@@ -489,17 +566,17 @@ data_control :: proc() {
|
|||||||
}
|
}
|
||||||
defer close_file(^f);
|
defer close_file(^f);
|
||||||
|
|
||||||
}/
|
*/
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < 100; i++ {
|
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 {
|
||||||
defer print_string("!");
|
defer print_string("!");
|
||||||
defer print_string("heap_free");
|
defer print_string("dealloc");
|
||||||
heap_free(blah);
|
dealloc(blah);
|
||||||
}
|
}
|
||||||
|
|
||||||
if i == 3 {
|
if i == 3 {
|
||||||
@@ -509,7 +586,7 @@ data_control :: proc() {
|
|||||||
|
|
||||||
if i == 5 {
|
if i == 5 {
|
||||||
// defers called
|
// defers called
|
||||||
return;
|
return; // End of procedure
|
||||||
}
|
}
|
||||||
|
|
||||||
if i == 8 {
|
if i == 8 {
|
||||||
@@ -523,3 +600,4 @@ data_control :: proc() {
|
|||||||
print_string("It'll never happen, mate 3");
|
print_string("It'll never happen, mate 3");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+49
-23
@@ -35,13 +35,12 @@ to_c_string :: proc(s: string) -> ^u8 {
|
|||||||
|
|
||||||
|
|
||||||
type Window: struct {
|
type Window: struct {
|
||||||
width, height: int,
|
width, height: int,
|
||||||
wc: WNDCLASSEXA,
|
wc: WNDCLASSEXA,
|
||||||
dc: HDC,
|
dc: HDC,
|
||||||
hwnd: HWND,
|
hwnd: HWND,
|
||||||
opengl_context: rawptr,
|
opengl_context, rc: HGLRC,
|
||||||
rc: HGLRC,
|
c_title: ^u8,
|
||||||
c_title: ^u8,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (Window, bool) {
|
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);
|
instance := GetModuleHandleA(null);
|
||||||
|
|
||||||
w.wc = WNDCLASSEXA{
|
w.wc = WNDCLASSEXA{
|
||||||
cbSize = size_of(WNDCLASSEXA) as u32,
|
size = size_of(WNDCLASSEXA) as u32,
|
||||||
style = CS_VREDRAW | CS_HREDRAW,
|
style = CS_VREDRAW | CS_HREDRAW,
|
||||||
hInstance = instance as HINSTANCE,
|
instance = instance as HINSTANCE,
|
||||||
className = c_class_name,
|
class_name = c_class_name,
|
||||||
wndProc = window_proc,
|
wnd_proc = window_proc,
|
||||||
};
|
};
|
||||||
|
|
||||||
if RegisterClassExA(^w.wc) == 0 {
|
if RegisterClassExA(^w.wc) == 0 {
|
||||||
@@ -82,15 +81,15 @@ make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (W
|
|||||||
|
|
||||||
{
|
{
|
||||||
pfd := PIXELFORMATDESCRIPTOR{
|
pfd := PIXELFORMATDESCRIPTOR{
|
||||||
nSize = size_of(PIXELFORMATDESCRIPTOR) as u32,
|
size = size_of(PIXELFORMATDESCRIPTOR) as u32,
|
||||||
nVersion = 1,
|
version = 1,
|
||||||
dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
||||||
iPixelType = PFD_TYPE_RGBA,
|
pixel_type = PFD_TYPE_RGBA,
|
||||||
cColorBits = 32,
|
color_bits = 32,
|
||||||
cAlphaBits = 8,
|
alpha_bits = 8,
|
||||||
cDepthBits = 24,
|
depth_bits = 24,
|
||||||
cStencilBits = 8,
|
stencil_bits = 8,
|
||||||
iLayerType = PFD_MAIN_PLANE,
|
layer_type = PFD_MAIN_PLANE,
|
||||||
};
|
};
|
||||||
|
|
||||||
SetPixelFormat(w.dc, ChoosePixelFormat(w.dc, ^pfd), null);
|
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() {
|
run_game :: proc() {
|
||||||
win32_proc :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #no_inline {
|
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();
|
prev_time := time_now();
|
||||||
running := true;
|
running := true;
|
||||||
|
|
||||||
|
pos := Vec2{100, 100};
|
||||||
|
|
||||||
for running {
|
for running {
|
||||||
curr_time := time_now();
|
curr_time := time_now();
|
||||||
dt := (curr_time - prev_time) as f32;
|
dt := (curr_time - prev_time) as f32;
|
||||||
@@ -157,12 +164,32 @@ run_game :: proc() {
|
|||||||
_ = DispatchMessageA(^msg);
|
_ = 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);
|
glClearColor(0.5, 0.7, 1.0, 1.0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glOrtho(0, window.width as f64,
|
glOrtho(0, window.width as f64,
|
||||||
0, window.height as f64, 0, 1);
|
0, window.height as f64, 0, 1);
|
||||||
|
|
||||||
draw_rect :: proc(x, y, w, h: f32) {
|
draw_rect :: proc(x, y, w, h: f32) {
|
||||||
glBegin(GL_TRIANGLES);
|
glBegin(GL_TRIANGLES);
|
||||||
|
|
||||||
@@ -177,8 +204,7 @@ run_game :: proc() {
|
|||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
x, y : f32 = 100+50*sinf(curr_time as f32), 100;
|
draw_rect(pos[0], pos[1], 50, 50);
|
||||||
draw_rect(x, y, 50, 50);
|
|
||||||
|
|
||||||
display_window(^window);
|
display_window(^window);
|
||||||
ms_to_sleep := (16 - 1000*dt) as i32;
|
ms_to_sleep := (16 - 1000*dt) as i32;
|
||||||
|
|||||||
+142
-7
@@ -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 Vec2: {2}f32
|
||||||
type Vec3: {3}f32
|
type Vec3: {3}f32
|
||||||
type Vec4: {4}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]; }
|
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]; }
|
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)); }
|
vec2_mag :: proc(v: Vec2) -> f32 { return fsqrt(vec2_dot(v, v)); }
|
||||||
vec3_mag :: proc(a: Vec3) -> f32 { return sqrtf(vec3_dot(a, a)); }
|
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
|
||||||
|
|||||||
+127
-3
@@ -1,14 +1,16 @@
|
|||||||
putchar :: proc(c: i32) -> i32 #foreign
|
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_compare :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memcmp"
|
||||||
mem_copy :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memcpy"
|
mem_copy :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memcpy"
|
||||||
mem_move :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memmove"
|
mem_move :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memmove"
|
||||||
|
|
||||||
debug_trap :: proc() #foreign "llvm.debugtrap"
|
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 {
|
__string_eq :: proc(a, b : string) -> bool {
|
||||||
if len(a) != len(b) {
|
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_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_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; }
|
__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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+202
-40
@@ -42,24 +42,24 @@ type POINT: struct { x, y: i32 }
|
|||||||
type WNDPROC: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT
|
type WNDPROC: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT
|
||||||
|
|
||||||
type WNDCLASSEXA: struct {
|
type WNDCLASSEXA: struct {
|
||||||
cbSize, style: u32,
|
size, style: u32,
|
||||||
wndProc: WNDPROC,
|
wnd_proc: WNDPROC,
|
||||||
cbClsExtra, cbWndExtra: i32,
|
cls_extra, wnd_extra: i32,
|
||||||
hInstance: HINSTANCE,
|
instance: HINSTANCE,
|
||||||
hIcon: HICON,
|
icon: HICON,
|
||||||
hCursor: HCURSOR,
|
cursor: HCURSOR,
|
||||||
hbrBackground: HBRUSH,
|
background: HBRUSH,
|
||||||
menuName, className: ^u8,
|
menu_name, class_name: ^u8,
|
||||||
hIconSm: HICON,
|
sm: HICON,
|
||||||
}
|
}
|
||||||
|
|
||||||
type MSG: struct {
|
type MSG: struct {
|
||||||
hwnd: HWND,
|
hwnd: HWND,
|
||||||
message: u32,
|
message: u32,
|
||||||
wparam: WPARAM,
|
wparam: WPARAM,
|
||||||
lparam: LPARAM,
|
lparam: LPARAM,
|
||||||
time: u32,
|
time: u32,
|
||||||
pt: POINT,
|
pt: POINT,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -145,34 +145,34 @@ type wglCreateContextAttribsARBType: proc(hdc: HDC, hshareContext: rawptr, attri
|
|||||||
|
|
||||||
|
|
||||||
type PIXELFORMATDESCRIPTOR: struct {
|
type PIXELFORMATDESCRIPTOR: struct {
|
||||||
nSize,
|
size,
|
||||||
nVersion,
|
version,
|
||||||
dwFlags: u32,
|
flags: u32,
|
||||||
|
|
||||||
iPixelType,
|
pixel_type,
|
||||||
cColorBits,
|
color_bits,
|
||||||
cRedBits,
|
red_bits,
|
||||||
cRedShift,
|
red_shift,
|
||||||
cGreenBits,
|
green_bits,
|
||||||
cGreenShift,
|
green_shift,
|
||||||
cBlueBits,
|
blue_bits,
|
||||||
cBlueShift,
|
blue_shift,
|
||||||
cAlphaBits,
|
alpha_bits,
|
||||||
cAlphaShift,
|
alpha_shift,
|
||||||
cAccumBits,
|
accum_bits,
|
||||||
cAccumRedBits,
|
accum_red_bits,
|
||||||
cAccumGreenBits,
|
accum_green_bits,
|
||||||
cAccumBlueBits,
|
accum_blue_bits,
|
||||||
cAccumAlphaBits,
|
accum_alpha_bits,
|
||||||
cDepthBits,
|
depth_bits,
|
||||||
cStencilBits,
|
stencil_bits,
|
||||||
cAuxBuffers,
|
aux_buffers,
|
||||||
iLayerType,
|
layer_type,
|
||||||
bReserved: byte,
|
reserved: byte,
|
||||||
|
|
||||||
dwLayerMask,
|
layer_mask,
|
||||||
dwVisibleMask,
|
visible_mask,
|
||||||
dwDamageMask: u32,
|
damage_mask: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
GetDC :: proc(h: HANDLE) -> HDC #foreign
|
GetDC :: proc(h: HANDLE) -> HDC #foreign
|
||||||
@@ -190,3 +190,165 @@ wglCreateContext :: proc(hdc: HDC) -> HGLRC #foreign
|
|||||||
wglMakeCurrent :: proc(hdc: HDC, hglrc: HGLRC) -> BOOL #foreign
|
wglMakeCurrent :: proc(hdc: HDC, hglrc: HGLRC) -> BOOL #foreign
|
||||||
wglGetProcAddress :: proc(c_str: ^u8) -> PROC #foreign
|
wglGetProcAddress :: proc(c_str: ^u8) -> PROC #foreign
|
||||||
wglDeleteContext :: proc(hglrc: HGLRC) -> BOOL #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;
|
||||||
|
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ struct DeclInfo {
|
|||||||
AstNode *type_expr;
|
AstNode *type_expr;
|
||||||
AstNode *init_expr;
|
AstNode *init_expr;
|
||||||
AstNode *proc_decl; // AstNode_ProcDecl
|
AstNode *proc_decl; // AstNode_ProcDecl
|
||||||
|
u32 var_decl_tags;
|
||||||
|
|
||||||
Map<b32> deps; // Key: Entity *
|
Map<b32> 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 = make_declaration_info(gb_heap_allocator(), c->global_scope);
|
||||||
d->type_expr = vd->type;
|
d->type_expr = vd->type;
|
||||||
d->init_expr = init_expr;
|
d->init_expr = init_expr;
|
||||||
|
d->var_decl_tags = vd->tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_file_entity(c, name, e, d);
|
add_file_entity(c, name, e, d);
|
||||||
|
|||||||
+25
-2
@@ -874,6 +874,12 @@ b32 check_castable_to(Checker *c, Operand *operand, Type *y) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// proc -> rawptr
|
||||||
|
if (is_type_proc(xb), is_type_rawptr(yb)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -912,7 +918,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
|||||||
gbString type_str = type_to_string(type);
|
gbString type_str = type_to_string(type);
|
||||||
defer (gb_string_free(expr_str));
|
defer (gb_string_free(expr_str));
|
||||||
defer (gb_string_free(type_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;
|
x->mode = Addressing_Invalid;
|
||||||
return;
|
return;
|
||||||
@@ -1199,8 +1205,18 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) {
|
|||||||
convert_untyped_error(c, operand, target_type);
|
convert_untyped_error(c, operand, target_type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Type_Proc:
|
||||||
|
switch (operand->type->basic.kind) {
|
||||||
|
case Basic_UntypedPointer:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
convert_untyped_error(c, operand, target_type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
convert_untyped_error(c, operand, target_type);
|
convert_untyped_error(c, operand, target_type);
|
||||||
return;
|
return;
|
||||||
@@ -1992,6 +2008,13 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
|
|||||||
i64 max = 0;
|
i64 max = 0;
|
||||||
for (AstNode *elem = cl->elem_list; elem != NULL; elem = elem->next, index++) {
|
for (AstNode *elem = cl->elem_list; elem != NULL; elem = elem->next, index++) {
|
||||||
AstNode *e = elem;
|
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 &&
|
if (t->kind == Type_Array &&
|
||||||
t->array.count >= 0 &&
|
t->array.count >= 0 &&
|
||||||
index >= t->array.count) {
|
index >= t->array.count) {
|
||||||
|
|||||||
@@ -119,7 +119,9 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -742,8 +744,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|
||||||
// Declarations
|
|
||||||
case_ast_node(vd, VarDecl, node);
|
case_ast_node(vd, VarDecl, node);
|
||||||
isize entity_count = vd->name_count;
|
isize entity_count = vd->name_count;
|
||||||
isize entity_index = 0;
|
isize entity_index = 0;
|
||||||
|
|||||||
+39
-28
@@ -80,7 +80,13 @@ String const type_strings[] = {
|
|||||||
#undef TYPE_KIND
|
#undef TYPE_KIND
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum TypeFlag {
|
||||||
|
TypeFlag_thread_local = GB_BIT(0),
|
||||||
|
TypeFlag_volatile = GB_BIT(1),
|
||||||
|
};
|
||||||
|
|
||||||
struct Type {
|
struct Type {
|
||||||
|
u32 flags;
|
||||||
TypeKind kind;
|
TypeKind kind;
|
||||||
union {
|
union {
|
||||||
BasicType basic;
|
BasicType basic;
|
||||||
@@ -206,43 +212,46 @@ Type *make_type_proc(gbAllocator a, Scope *scope, Type *params, isize param_coun
|
|||||||
|
|
||||||
|
|
||||||
Type *type_deref(Type *t) {
|
Type *type_deref(Type *t) {
|
||||||
if (t != NULL && t->kind == Type_Pointer)
|
if (t != NULL) {
|
||||||
return t->pointer.elem;
|
Type *bt = get_base_type(t);
|
||||||
|
if (bt != NULL && bt->kind == Type_Pointer)
|
||||||
|
return bt->pointer.elem;
|
||||||
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define STR_LIT(x) {cast(u8 *)(x), gb_size_of(x)-1}
|
#define STR_LIT(x) {cast(u8 *)(x), gb_size_of(x)-1}
|
||||||
gb_global Type basic_types[] = {
|
gb_global Type basic_types[] = {
|
||||||
{Type_Basic, {Basic_Invalid, 0, STR_LIT("invalid type")}},
|
{0, Type_Basic, {Basic_Invalid, 0, STR_LIT("invalid type")}},
|
||||||
{Type_Basic, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}},
|
{0, Type_Basic, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}},
|
||||||
{Type_Basic, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}},
|
{0, Type_Basic, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}},
|
||||||
{Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
|
{0, Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
|
||||||
{Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
|
{0, Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
|
||||||
{Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
|
{0, Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
|
||||||
{Type_Basic, {Basic_i128, BasicFlag_Integer, STR_LIT("i128")}},
|
{0, Type_Basic, {Basic_i128, BasicFlag_Integer, STR_LIT("i128")}},
|
||||||
{Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}},
|
{0, Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}},
|
||||||
{Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}},
|
{0, Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}},
|
||||||
{Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}},
|
{0, Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}},
|
||||||
{Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}},
|
{0, Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}},
|
||||||
{Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u128")}},
|
{0, Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u128")}},
|
||||||
{Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
|
{0, Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
|
||||||
{Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}},
|
{0, Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}},
|
||||||
{Type_Basic, {Basic_int, BasicFlag_Integer, STR_LIT("int")}},
|
{0, Type_Basic, {Basic_int, BasicFlag_Integer, STR_LIT("int")}},
|
||||||
{Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}},
|
{0, Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}},
|
||||||
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, STR_LIT("rawptr")}},
|
{0, Type_Basic, {Basic_rawptr, BasicFlag_Pointer, STR_LIT("rawptr")}},
|
||||||
{Type_Basic, {Basic_string, BasicFlag_String, STR_LIT("string")}},
|
{0, Type_Basic, {Basic_string, BasicFlag_String, STR_LIT("string")}},
|
||||||
{Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}},
|
{0, Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}},
|
||||||
{Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped integer")}},
|
{0, Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped integer")}},
|
||||||
{Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, STR_LIT("untyped float")}},
|
{0, Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, STR_LIT("untyped float")}},
|
||||||
{Type_Basic, {Basic_UntypedPointer, BasicFlag_Pointer | BasicFlag_Untyped, STR_LIT("untyped pointer")}},
|
{0, Type_Basic, {Basic_UntypedPointer, BasicFlag_Pointer | BasicFlag_Untyped, STR_LIT("untyped pointer")}},
|
||||||
{Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, STR_LIT("untyped string")}},
|
{0, 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_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped rune")}},
|
||||||
};
|
};
|
||||||
|
|
||||||
gb_global Type basic_type_aliases[] = {
|
gb_global Type basic_type_aliases[] = {
|
||||||
{Type_Basic, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("byte")}},
|
{0, Type_Basic, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("byte")}},
|
||||||
{Type_Basic, {Basic_rune, BasicFlag_Integer, STR_LIT("rune")}},
|
{0, Type_Basic, {Basic_rune, BasicFlag_Integer, STR_LIT("rune")}},
|
||||||
};
|
};
|
||||||
|
|
||||||
gb_global Type *t_invalid = &basic_types[Basic_Invalid];
|
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);
|
return is_type_comparable(t->array.elem);
|
||||||
case Type_Vector:
|
case Type_Vector:
|
||||||
return is_type_comparable(t->vector.elem);
|
return is_type_comparable(t->vector.elem);
|
||||||
|
case Type_Proc:
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,8 +77,10 @@ void ssa_gen_code(ssaGen *s) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Entity_Variable: {
|
case Entity_Variable: {
|
||||||
// TODO(bill): global runtime initialization
|
|
||||||
ssaValue *g = ssa_make_value_global(a, e, NULL);
|
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 = {};
|
ssaGlobalVariable var = {};
|
||||||
var.var = g;
|
var.var = g;
|
||||||
var.decl = decl;
|
var.decl = decl;
|
||||||
@@ -95,7 +97,7 @@ void ssa_gen_code(ssaGen *s) {
|
|||||||
name = pd->foreign_name;
|
name = pd->foreign_name;
|
||||||
}
|
}
|
||||||
ssaValue *p = ssa_make_value_procedure(a, m, e->type, decl->type_expr, body, 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->values, hash_pointer(e), p);
|
||||||
map_set(&m->members, hash_string(name), 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->values, hash_pointer(e), p);
|
||||||
map_set(&m->members, hash_string(name), 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?
|
proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
|
||||||
|
|
||||||
ssa_begin_procedure_body(proc);
|
ssa_begin_procedure_body(proc);
|
||||||
|
|||||||
+72
-68
@@ -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) {
|
if (is_type_float(type) && type->basic.kind == Basic_f32) {
|
||||||
// IMPORTANT NOTE(bill): LLVM requires all floating point constants to be
|
// IMPORTANT NOTE(bill): LLVM requires all floating point constants to be
|
||||||
// a 64 bit number if bits_of(float type) <= 64.
|
// 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
|
// https://groups.google.com/forum/#!topic/llvm-dev/IlqV3TbSk6M
|
||||||
u >>= 28;
|
u >>= 29;
|
||||||
u <<= 28;
|
u <<= 29;
|
||||||
}
|
}
|
||||||
ssa_fprintf(f, "0x%016llx", u);
|
ssa_fprintf(f, "0x%016llx", u);
|
||||||
} break;
|
} break;
|
||||||
@@ -262,19 +262,19 @@ void ssa_print_value(gbFile *f, ssaModule *m, ssaValue *value, Type *type_hint)
|
|||||||
}
|
}
|
||||||
switch (value->kind) {
|
switch (value->kind) {
|
||||||
case ssaValue_Constant:
|
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;
|
break;
|
||||||
case ssaValue_TypeName:
|
case ssaValue_TypeName:
|
||||||
ssa_print_encoded_local(f, value->type_name.name);
|
ssa_print_encoded_local(f, value->TypeName.name);
|
||||||
break;
|
break;
|
||||||
case ssaValue_Global:
|
case ssaValue_Global:
|
||||||
ssa_print_encoded_global(f, value->global.entity->token.string);
|
ssa_print_encoded_global(f, value->Global.entity->token.string);
|
||||||
break;
|
break;
|
||||||
case ssaValue_Param:
|
case ssaValue_Param:
|
||||||
ssa_print_encoded_local(f, value->param.entity->token.string);
|
ssa_print_encoded_local(f, value->Param.entity->token.string);
|
||||||
break;
|
break;
|
||||||
case ssaValue_Proc:
|
case ssaValue_Proc:
|
||||||
ssa_print_encoded_global(f, value->proc.name);
|
ssa_print_encoded_global(f, value->Proc.name);
|
||||||
break;
|
break;
|
||||||
case ssaValue_Instr:
|
case ssaValue_Instr:
|
||||||
ssa_fprintf(f, "%%%d", value->id);
|
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) {
|
void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
|
||||||
GB_ASSERT(value->kind == ssaValue_Instr);
|
GB_ASSERT(value->kind == ssaValue_Instr);
|
||||||
ssaInstr *instr = &value->instr;
|
ssaInstr *instr = &value->Instr;
|
||||||
|
|
||||||
ssa_fprintf(f, "\t");
|
ssa_fprintf(f, "\t");
|
||||||
|
|
||||||
@@ -294,14 +294,14 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_Local: {
|
case ssaInstr_Local: {
|
||||||
Type *type = instr->local.entity->type;
|
Type *type = instr->Local.entity->type;
|
||||||
ssa_fprintf(f, "%%%d = alloca ", value->id);
|
ssa_fprintf(f, "%%%d = alloca ", value->id);
|
||||||
ssa_print_type(f, m->sizes, type);
|
ssa_print_type(f, m->sizes, type);
|
||||||
ssa_fprintf(f, ", align %lld ", type_align_of(m->sizes, m->allocator, 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)
|
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, "\n");
|
||||||
ssa_fprintf(f, "\tstore ");
|
ssa_fprintf(f, "\tstore ");
|
||||||
@@ -312,33 +312,33 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_Store: {
|
case ssaInstr_Store: {
|
||||||
Type *type = ssa_value_type(instr->store.address);
|
Type *type = ssa_type(instr->Store.address);
|
||||||
ssa_fprintf(f, "store ");
|
ssa_fprintf(f, "store ");
|
||||||
ssa_print_type(f, m->sizes, type);
|
ssa_print_type(f, m->sizes, type);
|
||||||
ssa_fprintf(f, " ");
|
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_fprintf(f, ", ");
|
||||||
ssa_print_type(f, m->sizes, type);
|
ssa_print_type(f, m->sizes, type);
|
||||||
ssa_fprintf(f, "* ");
|
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");
|
ssa_fprintf(f, "\n");
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_Load: {
|
case ssaInstr_Load: {
|
||||||
Type *type = instr->load.type;
|
Type *type = instr->Load.type;
|
||||||
ssa_fprintf(f, "%%%d = load ", value->id);
|
ssa_fprintf(f, "%%%d = load ", value->id);
|
||||||
ssa_print_type(f, m->sizes, type);
|
ssa_print_type(f, m->sizes, type);
|
||||||
ssa_fprintf(f, ", ");
|
ssa_fprintf(f, ", ");
|
||||||
ssa_print_type(f, m->sizes, type);
|
ssa_print_type(f, m->sizes, type);
|
||||||
ssa_fprintf(f, "* ");
|
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));
|
ssa_fprintf(f, ", align %lld\n", type_align_of(m->sizes, m->allocator, type));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_GetElementPtr: {
|
case ssaInstr_GetElementPtr: {
|
||||||
Type *et = instr->get_element_ptr.elem_type;
|
Type *et = instr->GetElementPtr.elem_type;
|
||||||
ssa_fprintf(f, "%%%d = getelementptr ", value->id);
|
ssa_fprintf(f, "%%%d = getelementptr ", value->id);
|
||||||
if (instr->get_element_ptr.inbounds) {
|
if (instr->GetElementPtr.inbounds) {
|
||||||
ssa_fprintf(f, "inbounds ");
|
ssa_fprintf(f, "inbounds ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,10 +346,10 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
ssa_fprintf(f, ", ");
|
ssa_fprintf(f, ", ");
|
||||||
ssa_print_type(f, m->sizes, et);
|
ssa_print_type(f, m->sizes, et);
|
||||||
ssa_fprintf(f, "* ");
|
ssa_fprintf(f, "* ");
|
||||||
ssa_print_value(f, m, instr->get_element_ptr.address, et);
|
ssa_print_value(f, m, instr->GetElementPtr.address, et);
|
||||||
for (isize i = 0; i < instr->get_element_ptr.index_count; i++) {
|
for (isize i = 0; i < instr->GetElementPtr.index_count; i++) {
|
||||||
ssaValue *index = instr->get_element_ptr.indices[i];
|
ssaValue *index = instr->GetElementPtr.indices[i];
|
||||||
Type *t = ssa_value_type(index);
|
Type *t = ssa_type(index);
|
||||||
ssa_fprintf(f, ", ");
|
ssa_fprintf(f, ", ");
|
||||||
ssa_print_type(f, m->sizes, t);
|
ssa_print_type(f, m->sizes, t);
|
||||||
ssa_fprintf(f, " ");
|
ssa_fprintf(f, " ");
|
||||||
@@ -359,13 +359,13 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_ExtractValue: {
|
case ssaInstr_ExtractValue: {
|
||||||
Type *et = instr->extract_value.elem_type;
|
Type *et = instr->ExtractValue.elem_type;
|
||||||
ssa_fprintf(f, "%%%d = extractvalue ", value->id);
|
ssa_fprintf(f, "%%%d = extractvalue ", value->id);
|
||||||
|
|
||||||
ssa_print_type(f, m->sizes, et);
|
ssa_print_type(f, m->sizes, et);
|
||||||
ssa_fprintf(f, " ");
|
ssa_fprintf(f, " ");
|
||||||
ssa_print_value(f, m, instr->extract_value.address, et);
|
ssa_print_value(f, m, instr->ExtractValue.address, et);
|
||||||
ssa_fprintf(f, ", %d\n", instr->extract_value.index);
|
ssa_fprintf(f, ", %d\n", instr->ExtractValue.index);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_NoOp: {;
|
case ssaInstr_NoOp: {;
|
||||||
@@ -374,28 +374,28 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
|
|
||||||
case ssaInstr_Br: {;
|
case ssaInstr_Br: {;
|
||||||
ssa_fprintf(f, "br ");
|
ssa_fprintf(f, "br ");
|
||||||
if (instr->br.cond != NULL) {
|
if (instr->Br.cond != NULL) {
|
||||||
ssa_print_type(f, m->sizes, t_bool);
|
ssa_print_type(f, m->sizes, t_bool);
|
||||||
ssa_fprintf(f, " ");
|
ssa_fprintf(f, " ");
|
||||||
ssa_print_value(f, m, instr->br.cond, t_bool);
|
ssa_print_value(f, m, instr->Br.cond, t_bool);
|
||||||
ssa_fprintf(f, ", ", instr->br.cond->id);
|
ssa_fprintf(f, ", ", instr->Br.cond->id);
|
||||||
}
|
}
|
||||||
ssa_fprintf(f, "label ");
|
ssa_fprintf(f, "label ");
|
||||||
ssa_fprintf(f, "%%"); ssa_print_block_name(f, instr->br.true_block);
|
ssa_fprintf(f, "%%"); ssa_print_block_name(f, instr->Br.true_block);
|
||||||
if (instr->br.false_block != NULL) {
|
if (instr->Br.false_block != NULL) {
|
||||||
ssa_fprintf(f, ", label ");
|
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");
|
ssa_fprintf(f, "\n");
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_Ret: {
|
case ssaInstr_Ret: {
|
||||||
auto *ret = &instr->ret;
|
auto *ret = &instr->Ret;
|
||||||
ssa_fprintf(f, "ret ");
|
ssa_fprintf(f, "ret ");
|
||||||
if (ret->value == NULL) {
|
if (ret->value == NULL) {
|
||||||
ssa_fprintf(f, "void");
|
ssa_fprintf(f, "void");
|
||||||
} else {
|
} else {
|
||||||
Type *t = ssa_value_type(ret->value);
|
Type *t = ssa_type(ret->value);
|
||||||
ssa_print_type(f, m->sizes, t);
|
ssa_print_type(f, m->sizes, t);
|
||||||
ssa_fprintf(f, " ");
|
ssa_fprintf(f, " ");
|
||||||
ssa_print_value(f, m, ret->value, t);
|
ssa_print_value(f, m, ret->value, t);
|
||||||
@@ -406,7 +406,7 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_Conv: {
|
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_fprintf(f, "%%%d = %.*s ", value->id, LIT(ssa_conv_strings[c->kind]));
|
||||||
ssa_print_type(f, m->sizes, c->from);
|
ssa_print_type(f, m->sizes, c->from);
|
||||||
ssa_fprintf(f, " ");
|
ssa_fprintf(f, " ");
|
||||||
@@ -422,8 +422,8 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_BinaryOp: {
|
case ssaInstr_BinaryOp: {
|
||||||
auto *bo = &value->instr.binary_op;
|
auto *bo = &value->Instr.BinaryOp;
|
||||||
Type *type = get_base_type(ssa_value_type(bo->left));
|
Type *type = get_base_type(ssa_type(bo->left));
|
||||||
Type *elem_type = type;
|
Type *elem_type = type;
|
||||||
while (elem_type->kind == Type_Vector) {
|
while (elem_type->kind == Type_Vector) {
|
||||||
elem_type = get_base_type(elem_type->vector.elem);
|
elem_type = get_base_type(elem_type->vector.elem);
|
||||||
@@ -528,7 +528,7 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_Call: {
|
case ssaInstr_Call: {
|
||||||
auto *call = &instr->call;
|
auto *call = &instr->Call;
|
||||||
Type *result_type = call->type;
|
Type *result_type = call->type;
|
||||||
if (result_type) {
|
if (result_type) {
|
||||||
ssa_fprintf(f, "%%%d = ", value->id);
|
ssa_fprintf(f, "%%%d = ", value->id);
|
||||||
@@ -545,7 +545,7 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
|
|
||||||
ssa_fprintf(f, "(");
|
ssa_fprintf(f, "(");
|
||||||
if (call->arg_count > 0) {
|
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);
|
GB_ASSERT(proc_type->kind == Type_Proc);
|
||||||
auto *params = &proc_type->proc.params->tuple;
|
auto *params = &proc_type->proc.params->tuple;
|
||||||
for (isize i = 0; i < call->arg_count; i++) {
|
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: {
|
case ssaInstr_Select: {
|
||||||
ssa_fprintf(f, "%%%d = select i1 ", value->id);
|
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_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_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_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_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");
|
ssa_fprintf(f, "\n");
|
||||||
} break;
|
} 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_fprintf(f, "call void @llvm.memmove.p0i8.p0i8.");
|
||||||
ssa_print_type(f, m->sizes, t_int);
|
ssa_print_type(f, m->sizes, t_int);
|
||||||
ssa_fprintf(f, "(i8* ");
|
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_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_fprintf(f, ", ");
|
||||||
ssa_print_type(f, m->sizes, t_int);
|
ssa_print_type(f, m->sizes, t_int);
|
||||||
ssa_fprintf(f, " ");
|
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";
|
char *vol_str = "false";
|
||||||
if (instr->copy_memory.is_volatile) {
|
if (instr->CopyMemory.is_volatile) {
|
||||||
vol_str = "true";
|
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;
|
} break;
|
||||||
|
|
||||||
|
|
||||||
case ssaInstr_ExtractElement: {
|
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_fprintf(f, "%%%d = extractelement ", value->id);
|
||||||
|
|
||||||
ssa_print_type(f, m->sizes, vt);
|
ssa_print_type(f, m->sizes, vt);
|
||||||
ssa_fprintf(f, " ");
|
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, ", ");
|
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_print_type(f, m->sizes, it);
|
||||||
ssa_fprintf(f, " ");
|
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");
|
ssa_fprintf(f, "\n");
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_InsertElement: {
|
case ssaInstr_InsertElement: {
|
||||||
auto *ie = &instr->insert_element;
|
auto *ie = &instr->InsertElement;
|
||||||
Type *vt = ssa_value_type(ie->vector);
|
Type *vt = ssa_type(ie->vector);
|
||||||
ssa_fprintf(f, "%%%d = insertelement ", value->id);
|
ssa_fprintf(f, "%%%d = insertelement ", value->id);
|
||||||
|
|
||||||
ssa_print_type(f, m->sizes, vt);
|
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_print_value(f, m, ie->vector, vt);
|
||||||
ssa_fprintf(f, ", ");
|
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_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_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_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");
|
ssa_fprintf(f, "\n");
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_ShuffleVector: {
|
case ssaInstr_ShuffleVector: {
|
||||||
auto *sv = &instr->shuffle_vector;
|
auto *sv = &instr->ShuffleVector;
|
||||||
Type *vt = ssa_value_type(sv->vector);
|
Type *vt = ssa_type(sv->vector);
|
||||||
ssa_fprintf(f, "%%%d = shufflevector ", value->id);
|
ssa_fprintf(f, "%%%d = shufflevector ", value->id);
|
||||||
|
|
||||||
ssa_print_type(f, m->sizes, vt);
|
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) {
|
void ssa_print_type_name(gbFile *f, ssaModule *m, ssaValue *v) {
|
||||||
GB_ASSERT(v->kind == ssaValue_TypeName);
|
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_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");
|
ssa_fprintf(f, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,9 +763,9 @@ void ssa_print_llvm_ir(gbFile *f, ssaModule *m) {
|
|||||||
ssaValue *v = entry->value;
|
ssaValue *v = entry->value;
|
||||||
switch (v->kind) {
|
switch (v->kind) {
|
||||||
case ssaValue_TypeName: {
|
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_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");
|
ssa_fprintf(f, "\n");
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@@ -790,16 +790,20 @@ void ssa_print_llvm_ir(gbFile *f, ssaModule *m) {
|
|||||||
ssaValue *v = entry->value;
|
ssaValue *v = entry->value;
|
||||||
switch (v->kind) {
|
switch (v->kind) {
|
||||||
case ssaValue_Global: {
|
case ssaValue_Global: {
|
||||||
auto *g = &v->global;
|
auto *g = &v->Global;
|
||||||
ssa_print_encoded_global(f, g->entity->token.string);
|
ssa_print_encoded_global(f, g->entity->token.string);
|
||||||
ssa_fprintf(f, " = ");
|
ssa_fprintf(f, " = ");
|
||||||
|
if (g->is_thread_local) {
|
||||||
|
ssa_fprintf(f, "thread_local ");
|
||||||
|
}
|
||||||
if (g->is_constant) {
|
if (g->is_constant) {
|
||||||
ssa_fprintf(f, "private constant ");
|
ssa_fprintf(f, "private constant ");
|
||||||
} else {
|
} else {
|
||||||
ssa_fprintf(f, "global ");
|
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, " ");
|
ssa_fprintf(f, " ");
|
||||||
if (g->value != NULL) {
|
if (g->value != NULL) {
|
||||||
ssa_print_value(f, m, g->value, g->entity->type);
|
ssa_print_value(f, m, g->value, g->entity->type);
|
||||||
@@ -810,7 +814,7 @@ void ssa_print_llvm_ir(gbFile *f, ssaModule *m) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaValue_Proc: {
|
case ssaValue_Proc: {
|
||||||
ssa_print_proc(f, m, &v->proc);
|
ssa_print_proc(f, m, &v->Proc);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+334
-378
File diff suppressed because it is too large
Load Diff
+21
-1
@@ -77,6 +77,10 @@ enum ProcTag {
|
|||||||
ProcTag_no_inline = GB_BIT(2),
|
ProcTag_no_inline = GB_BIT(2),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum VarDeclTag {
|
||||||
|
VarDeclTag_thread_local = GB_BIT(0),
|
||||||
|
};
|
||||||
|
|
||||||
#define AST_NODE_KINDS \
|
#define AST_NODE_KINDS \
|
||||||
AST_NODE_KIND(Invalid, struct{}) \
|
AST_NODE_KIND(Invalid, struct{}) \
|
||||||
AST_NODE_KIND(BasicLit, Token) \
|
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(BadDecl, struct { Token begin, end; }) \
|
||||||
AST_NODE_KIND(VarDecl, struct { \
|
AST_NODE_KIND(VarDecl, struct { \
|
||||||
DeclKind kind; \
|
DeclKind kind; \
|
||||||
|
u32 tags; \
|
||||||
AstNode *name_list; \
|
AstNode *name_list; \
|
||||||
AstNode *type; \
|
AstNode *type; \
|
||||||
AstNode *value_list; \
|
AstNode *value_list; \
|
||||||
@@ -177,7 +182,7 @@ AST_NODE_KIND(_DeclBegin, struct{}) \
|
|||||||
u64 tags; \
|
u64 tags; \
|
||||||
String foreign_name; \
|
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(LoadDecl, struct { Token token, filepath; }) \
|
||||||
AST_NODE_KIND(_DeclEnd, struct{}) \
|
AST_NODE_KIND(_DeclEnd, struct{}) \
|
||||||
AST_NODE_KIND(_TypeBegin, 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.");
|
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);
|
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
|
s->TagStmt.stmt = parse_stmt(f); // TODO(bill): Find out why this doesn't work as an argument
|
||||||
return s;
|
return s;
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
+4
-4
@@ -371,25 +371,25 @@ void tokenizer_skip_whitespace(Tokenizer *t) {
|
|||||||
if (t->read_curr[0] == '/') { // Line comment //
|
if (t->read_curr[0] == '/') { // Line comment //
|
||||||
while (t->curr_rune != '\n')
|
while (t->curr_rune != '\n')
|
||||||
advance_to_next_rune(t);
|
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;
|
isize comment_scope = 1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
advance_to_next_rune(t);
|
advance_to_next_rune(t);
|
||||||
if (t->curr_rune == '/') {
|
if (t->curr_rune == '/') {
|
||||||
advance_to_next_rune(t);
|
advance_to_next_rune(t);
|
||||||
if (t->curr_rune == '{') {
|
if (t->curr_rune == '*') {
|
||||||
advance_to_next_rune(t);
|
advance_to_next_rune(t);
|
||||||
comment_scope++;
|
comment_scope++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (t->curr_rune == '}') {
|
if (t->curr_rune == '*') {
|
||||||
advance_to_next_rune(t);
|
advance_to_next_rune(t);
|
||||||
if (t->curr_rune == '/') {
|
if (t->curr_rune == '/') {
|
||||||
advance_to_next_rune(t);
|
advance_to_next_rune(t);
|
||||||
comment_scope--;
|
comment_scope--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (comment_scope == 0)
|
if (comment_scope <= 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user