Browse Source

Better name mangler for SSA generation
TODO: Define better name mangling rules and allow for explicit name overload

Ginger Bill 9 years ago
parent
commit
828095afd1

+ 14 - 9
code/demo.odin

@@ -1,14 +1,19 @@
-#import "punity.odin" as pn
+#import "punity.odin"   as pn
+#import "test.odin"     as t1
+#import "sub/test.odin" as t2
 
 
 main :: proc() {
 main :: proc() {
-	init :: proc(c: ^pn.Core) {
-	}
+	t1.thing()
+	t2.thing()
 
 
-	step :: proc(c: ^pn.Core) {
-		if pn.key_down(pn.Key.ESCAPE) {
-			c.running = false
-		}
-	}
+	// init :: proc(c: ^pn.Core) {
+	// }
 
 
-	pn.run(init, step)
+	// step :: proc(c: ^pn.Core) {
+	// 	if pn.key_down(pn.Key.ESCAPE) {
+	// 		c.running = false
+	// 	}
+	// }
+
+	// pn.run(init, step)
 }
 }

+ 19 - 12
code/math.odin

@@ -43,13 +43,25 @@ Mat3 :: type  {9}f32
 Mat4 :: type {16}f32
 Mat4 :: type {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 min(max(x, lower), upper) }
-fclamp01 :: proc(x: f32) -> f32 { return fclamp(x, 0, 1) }
-fsign    :: proc(x: f32) -> f32 { if x >= 0 { return +1 } return -1 }
+sqrt32    :: proc(x: f32) -> f32 #foreign "llvm.sqrt.f32"
+sqrt64    :: proc(x: f64) -> f64 #foreign "llvm.sqrt.f64"
+
+sin32     :: proc(x: f32) -> f32 #foreign "llvm.sin.f32"
+sin64     :: proc(x: f64) -> f64 #foreign "llvm.sin.f64"
+
+cos64     :: proc(x: f64) -> f64 #foreign "llvm.cos.f64"
+cos32     :: proc(x: f32) -> f32 #foreign "llvm.cos.f32"
+
+lerp32    :: proc(a, b, t: f32) -> f32 { return a*(1-t) + b*t }
+lerp64    :: proc(a, b, t: f64) -> f64 { return a*(1-t) + b*t }
+
+clamp32   :: proc(x, lower, upper: f32) -> f32 { return min(max(x, lower), upper) }
+clamp64   :: proc(x, lower, upper: f64) -> f64 { return min(max(x, lower), upper) }
+
+sign32    :: proc(x: f32) -> f32 { if x >= 0 { return +1 } return -1 }
+sign64    :: proc(x: f64) -> f64 { if x >= 0 { return +1 } return -1 }
+
+
 
 
 copy_sign :: proc(x, y: f32) -> f32 {
 copy_sign :: proc(x, y: f32) -> f32 {
 	ix := x transmute u32
 	ix := x transmute u32
@@ -58,8 +70,6 @@ copy_sign :: proc(x, y: f32) -> f32 {
 	ix |= iy & 0x80000000
 	ix |= iy & 0x80000000
 	return ix transmute f32
 	return ix transmute f32
 }
 }
-
-
 round :: proc(x: f32) -> f32 {
 round :: proc(x: f32) -> f32 {
 	if x >= 0 {
 	if x >= 0 {
 		return floor(x + 0.5)
 		return floor(x + 0.5)
@@ -79,9 +89,6 @@ ceil :: proc(x: f32) -> f32 {
 	return ((x as int)+1) as f32
 	return ((x as int)+1) as f32
 }
 }
 
 
-
-
-
 remainder :: proc(x, y: f32) -> f32 {
 remainder :: proc(x, y: f32) -> f32 {
 	return x - round(x/y) * y
 	return x - round(x/y) * y
 }
 }

+ 0 - 412
code/old_runtime.odin

@@ -1,412 +0,0 @@
-#load "win32.odin"
-
-assume :: proc(cond: bool) #foreign "llvm.assume"
-
-__debug_trap           :: proc()           #foreign "llvm.debugtrap"
-__trap                 :: proc()           #foreign "llvm.trap"
-read_cycle_counter     :: proc() -> u64    #foreign "llvm.readcyclecounter"
-
-bit_reverse16 :: proc(b: u16) -> u16 #foreign "llvm.bitreverse.i16"
-bit_reverse32 :: proc(b: u32) -> u32 #foreign "llvm.bitreverse.i32"
-bit_reverse64 :: proc(b: u64) -> u64 #foreign "llvm.bitreverse.i64"
-
-byte_swap16 :: proc(b: u16) -> u16 #foreign "llvm.bswap.i16"
-byte_swap32 :: proc(b: u32) -> u32 #foreign "llvm.bswap.i32"
-byte_swap64 :: proc(b: u64) -> u64 #foreign "llvm.bswap.i64"
-
-fmuladd_f32 :: proc(a, b, c: f32) -> f32 #foreign "llvm.fmuladd.f32"
-fmuladd_f64 :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64"
-
-// TODO(bill): make custom heap procedures
-heap_alloc   :: proc(len: int)   -> rawptr #foreign "malloc"
-heap_dealloc :: proc(ptr: rawptr)          #foreign "free"
-
-memory_zero :: proc(data: rawptr, len: int) {
-	d := slice_ptr(data as ^byte, len)
-	for i := 0; i < len; i++ {
-		d[i] = 0
-	}
-}
-
-memory_compare :: proc(dst, src: rawptr, len: int) -> int {
-	s1, s2: ^byte = dst, src
-	for i := 0; i < len; i++ {
-		a := ptr_offset(s1, i)^
-		b := ptr_offset(s2, i)^
-		if a != b {
-			return (a - b) as int
-		}
-	}
-	return 0
-}
-
-memory_copy :: proc(dst, src: rawptr, n: int) #inline {
-	if dst == src {
-		return
-	}
-
-	v128b :: type {4}u32
-	compile_assert(align_of(v128b) == 16)
-
-	d, s: ^byte = dst, src
-
-	for ; s as uint % 16 != 0 && n != 0; n-- {
-		d^ = s^
-		d, s = ptr_offset(d, 1), ptr_offset(s, 1)
-	}
-
-	if d as uint % 16 == 0 {
-		for ; n >= 16; d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16 {
-			(d as ^v128b)^ = (s as ^v128b)^
-		}
-
-		if n&8 != 0 {
-			(d as ^u64)^ = (s as ^u64)^
-			d, s = ptr_offset(d, 8), ptr_offset(s, 8)
-		}
-		if n&4 != 0 {
-			(d as ^u32)^ = (s as ^u32)^;
-			d, s = ptr_offset(d, 4), ptr_offset(s, 4)
-		}
-		if n&2 != 0 {
-			(d as ^u16)^ = (s as ^u16)^
-			d, s = ptr_offset(d, 2), ptr_offset(s, 2)
-		}
-		if n&1 != 0 {
-			d^ = s^
-			d, s = ptr_offset(d, 1), ptr_offset(s, 1)
-		}
-		return;
-	}
-
-	// IMPORTANT NOTE(bill): Little endian only
-	LS :: proc(a, b: u32) -> u32 #inline { return a << b }
-	RS :: proc(a, b: u32) -> u32 #inline { return a >> b }
-	/* NOTE(bill): Big endian version
-	LS :: proc(a, b: u32) -> u32 #inline { return a >> b; }
-	RS :: proc(a, b: u32) -> u32 #inline { return a << b; }
-	*/
-
-	w, x: u32
-
-	if d as uint % 4 == 1 {
-		w = (s as ^u32)^
-		d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
-		d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
-		d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
-		n -= 3
-
-		for n > 16 {
-			d32 := d as ^u32
-			s32 := ptr_offset(s, 1) as ^u32
-			x = s32^; d32^ = LS(w, 24) | RS(x, 8)
-			d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-			w = s32^; d32^ = LS(x, 24) | RS(w, 8)
-			d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-			x = s32^; d32^ = LS(w, 24) | RS(x, 8)
-			d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-			w = s32^; d32^ = LS(x, 24) | RS(w, 8)
-			d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-
-			d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16
-		}
-
-	} else if d as uint % 4 == 2 {
-		w = (s as ^u32)^
-		d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
-		d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
-		n -= 2
-
-		for n > 17 {
-			d32 := d as ^u32
-			s32 := ptr_offset(s, 2) as ^u32
-			x = s32^; d32^ = LS(w, 16) | RS(x, 16)
-			d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-			w = s32^; d32^ = LS(x, 16) | RS(w, 16)
-			d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-			x = s32^; d32^ = LS(w, 16) | RS(x, 16)
-			d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-			w = s32^; d32^ = LS(x, 16) | RS(w, 16)
-			d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-
-			d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16
-		}
-
-	} else if d as uint % 4 == 3 {
-		w = (s as ^u32)^
-		d^ = s^
-		n -= 1
-
-		for n > 18 {
-			d32 := d as ^u32
-			s32 := ptr_offset(s, 3) as ^u32
-			x = s32^; d32^ = LS(w, 8) | RS(x, 24)
-			d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-			w = s32^; d32^ = LS(x, 8) | RS(w, 24)
-			d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-			x = s32^; d32^ = LS(w, 8) | RS(x, 24)
-			d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-			w = s32^; d32^ = LS(x, 8) | RS(w, 24)
-			d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-
-			d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16
-		}
-	}
-
-	if n&16 != 0 {
-		(d as ^v128b)^ = (s as ^v128b)^
-		d, s = ptr_offset(d, 16), ptr_offset(s, 16)
-	}
-	if n&8 != 0 {
-		(d as ^u64)^ = (s as ^u64)^
-		d, s = ptr_offset(d, 8), ptr_offset(s, 8)
-	}
-	if n&4 != 0 {
-		(d as ^u32)^ = (s as ^u32)^;
-		d, s = ptr_offset(d, 4), ptr_offset(s, 4)
-	}
-	if n&2 != 0 {
-		(d as ^u16)^ = (s as ^u16)^
-		d, s = ptr_offset(d, 2), ptr_offset(s, 2)
-	}
-	if n&1 != 0 {
-		d^  = s^
-	}
-}
-
-memory_move :: proc(dst, src: rawptr, n: int) #inline {
-	d, s: ^byte = dst, src
-	if d == s {
-		return
-	}
-	if d >= ptr_offset(s, n) || ptr_offset(d, n) <= s {
-		memory_copy(d, s, n)
-		return
-	}
-
-	// TODO(bill): Vectorize the shit out of this
-	if d < s {
-		if s as int % size_of(int) == d as int % size_of(int) {
-			for d as int % size_of(int) != 0 {
-				if n == 0 {
-					return
-				}
-				n--
-				d^ = s^
-				d, s = ptr_offset(d, 1), ptr_offset(s, 1)
-			}
-			di, si := d as ^int, s as ^int
-			for n >= size_of(int) {
-				di^ = si^
-				di, si = ptr_offset(di, 1), ptr_offset(si, 1)
-				n -= size_of(int)
-			}
-		}
-		for ; n > 0; n-- {
-			d^ = s^
-			d, s = ptr_offset(d, 1), ptr_offset(s, 1)
-		}
-	} else {
-		if s as int % size_of(int) == d as int % size_of(int) {
-			for ptr_offset(d, n) as int % size_of(int) != 0 {
-				if n == 0 {
-					return
-				}
-				n--
-				d^ = s^
-				d, s = ptr_offset(d, 1), ptr_offset(s, 1)
-			}
-			for n >= size_of(int) {
-				n -= size_of(int)
-				di := ptr_offset(d, n) as ^int
-				si := ptr_offset(s, n) as ^int
-				di^ = si^
-			}
-			for ; n > 0; n-- {
-				d^ = s^
-				d, s = ptr_offset(d, 1), ptr_offset(s, 1)
-			}
-		}
-		for n > 0 {
-			n--
-			dn := ptr_offset(d, n)
-			sn := ptr_offset(s, n)
-			dn^ = sn^
-		}
-	}
-}
-
-__string_eq :: proc(a, b: string) -> bool {
-	if len(a) != len(b) {
-		return false
-	}
-	if ^a[0] == ^b[0] {
-		return true
-	}
-	return memory_compare(^a[0], ^b[0], len(a)) == 0
-}
-
-__string_cmp :: proc(a, b : string) -> int {
-	min_len := len(a)
-	if len(b) < min_len {
-		min_len = len(b)
-	}
-	for i := 0; i < min_len; i++ {
-		x := a[i]
-		y := b[i]
-		if x < y {
-			return -1
-		} else if x > y {
-			return +1
-		}
-	}
-
-	if len(a) < len(b) {
-		return -1
-	} else if len(a) > len(b) {
-		return +1
-	}
-	return 0
-}
-
-__string_ne :: proc(a, b : string) -> bool #inline { return !__string_eq(a, b) }
-__string_lt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) < 0 }
-__string_gt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) > 0 }
-__string_le :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) <= 0 }
-__string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >= 0 }
-
-
-
-
-Allocation_Mode :: type enum {
-	ALLOC,
-	DEALLOC,
-	DEALLOC_ALL,
-	RESIZE,
-}
-
-
-
-Allocator_Proc :: type proc(allocator_data: rawptr, mode: Allocation_Mode,
-                            size, alignment: int,
-                            old_memory: rawptr, old_size: int, flags: u64) -> rawptr
-
-Allocator :: type struct {
-	procedure: Allocator_Proc;
-	data:      rawptr
-}
-
-
-Context :: type struct {
-	thread_ptr: rawptr
-
-	user_data:  rawptr
-	user_index: int
-
-	allocator: Allocator
-}
-
-#thread_local context: Context
-
-DEFAULT_ALIGNMENT :: 2*size_of(int)
-
-
-__check_context :: proc() {
-	if context.allocator.procedure == null {
-		context.allocator = __default_allocator()
-	}
-	if context.thread_ptr == null {
-		// TODO(bill):
-		// context.thread_ptr = current_thread_pointer()
-	}
-}
-
-
-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_Mode.ALLOC, size, alignment, null, 0, 0)
-}
-
-dealloc :: proc(ptr: rawptr) #inline {
-	__check_context()
-	a := context.allocator
-	_ = a.procedure(a.data, Allocation_Mode.DEALLOC, 0, 0, ptr, 0, 0)
-}
-dealloc_all :: proc(ptr: rawptr) #inline {
-	__check_context()
-	a := context.allocator
-	_ = a.procedure(a.data, Allocation_Mode.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_Mode.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 {
-		return old_memory
-	}
-
-	new_memory := alloc_align(new_size, alignment)
-	if new_memory == null {
-		return null
-	}
-
-	memory_copy(new_memory, old_memory, min(old_size, new_size));
-	dealloc(old_memory)
-	return new_memory
-}
-
-
-__default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocation_Mode,
-                                 size, alignment: int,
-                                 old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
-	using Allocation_Mode
-	match mode {
-	case ALLOC:
-		return heap_alloc(size)
-	case RESIZE:
-		return default_resize_align(old_memory, old_size, size, alignment)
-	case DEALLOC:
-		heap_dealloc(old_memory)
-	case DEALLOC_ALL:
-		// NOTE(bill): Does nothing
-	}
-
-	return null
-}
-
-__default_allocator :: proc() -> Allocator {
-	return Allocator{
-		__default_allocator_proc,
-		null,
-	}
-}
-
-
-
-
-__assert :: proc(msg: string) {
-	file_write(file_get_standard(File_Standard.ERROR), msg as []byte)
-	// TODO(bill): Which is better?
-	// __trap()
-	__debug_trap()
-}

+ 4 - 4
code/punity.odin

@@ -1,5 +1,5 @@
 #import "win32.odin" as win32
 #import "win32.odin" as win32
-#import "fmt.odin" as _
+#import "fmt.odin" as fmt
 
 
 CANVAS_WIDTH  :: 128
 CANVAS_WIDTH  :: 128
 CANVAS_HEIGHT :: 128
 CANVAS_HEIGHT :: 128
@@ -357,7 +357,7 @@ run :: proc(user_init, user_step: proc(c: ^Core)) {
 	}
 	}
 
 
 	if RegisterClassExA(^window_class) == 0 {
 	if RegisterClassExA(^window_class) == 0 {
-		/*fmt.*/println_err("RegisterClassExA failed")
+		fmt.println_err("RegisterClassExA failed")
 		return
 		return
 	}
 	}
 
 
@@ -386,7 +386,7 @@ run :: proc(user_init, user_step: proc(c: ^Core)) {
 	                                null);
 	                                null);
 
 
 	if win32_window == null {
 	if win32_window == null {
-		/*fmt.*/println_err("CreateWindowExA failed")
+		fmt.println_err("CreateWindowExA failed")
 		return
 		return
 	}
 	}
 
 
@@ -434,7 +434,7 @@ run :: proc(user_init, user_step: proc(c: ^Core)) {
 		{
 		{
 			data: [128]byte
 			data: [128]byte
 			buf := data[:0]
 			buf := data[:0]
-			/*fmt.*/print_to_buffer(^buf, "Punity: % ms\x00", dt*1000)
+			fmt.print_to_buffer(^buf, "Punity: % ms\x00", dt*1000)
 			win32.SetWindowTextA(win32_window, buf.data)
 			win32.SetWindowTextA(win32_window, buf.data)
 		}
 		}
 
 

+ 14 - 13
src/checker/checker.cpp

@@ -354,12 +354,13 @@ void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entit
 						continue;
 						continue;
 					}
 					}
 
 
-					if (e->scope == shared) {
-						// Do not return imported entities
-						if (entity_) *entity_ = e;
-						if (scope_) *scope_ = shared;
-						return;
+					if (e->scope != shared) {
+						// Do not return imported entities even #load ones
+						continue;
 					}
 					}
+					if (entity_) *entity_ = e;
+					if (scope_) *scope_ = shared;
+					return;
 				}
 				}
 			}
 			}
 		}
 		}
@@ -529,13 +530,12 @@ void destroy_checker_info(CheckerInfo *i) {
 }
 }
 
 
 
 
-void init_checker(Checker *c, Parser *parser) {
+void init_checker(Checker *c, Parser *parser, BaseTypeSizes sizes) {
 	gbAllocator a = gb_heap_allocator();
 	gbAllocator a = gb_heap_allocator();
 
 
 	c->parser = parser;
 	c->parser = parser;
 	init_checker_info(&c->info);
 	init_checker_info(&c->info);
-	c->sizes.word_size = 8;
-	c->sizes.max_align = 8;
+	c->sizes = sizes;
 
 
 	gb_array_init(c->proc_stack, a);
 	gb_array_init(c->proc_stack, a);
 	gb_array_init(c->procs, a);
 	gb_array_init(c->procs, a);
@@ -832,6 +832,7 @@ void check_type_name_cycles(Checker *c, CycleCheck *cc, Entity *e) {
 	// if (t->kind == Type_Named) {
 	// if (t->kind == Type_Named) {
 	// 	if (t->Named.type_name == e) {
 	// 	if (t->Named.type_name == e) {
 	// 		gb_printf("Illegal cycle %.*s!!!\n", LIT(e->token.string));
 	// 		gb_printf("Illegal cycle %.*s!!!\n", LIT(e->token.string));
+	// 		GB_PANIC("!!!");
 	// 	}
 	// 	}
 	// }
 	// }
 }
 }
@@ -841,9 +842,8 @@ void init_type_info_types(Checker *c) {
 		String type_info_str = make_string("Type_Info");
 		String type_info_str = make_string("Type_Info");
 		Entity *e = current_scope_lookup_entity(c->global_scope, type_info_str);
 		Entity *e = current_scope_lookup_entity(c->global_scope, type_info_str);
 		if (e == NULL) {
 		if (e == NULL) {
-			gb_printf_err("Internal Compiler Error: Could not find type declaration for `Type_Info`\n");
-			gb_printf_err("Is `runtime.odin` missing from the `core` directory?\n");
-			gb_exit(1);
+			compiler_error("Could not find type declaration for `Type_Info`\n"
+			               "Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
 		}
 		}
 		t_type_info = e->type;
 		t_type_info = e->type;
 		t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
 		t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
@@ -854,8 +854,7 @@ void init_type_info_types(Checker *c) {
 		t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
 		t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
 
 
 		if (record->field_count != 16) {
 		if (record->field_count != 16) {
-			gb_printf_err("Internal Compiler Error: Invalid `Type_Info` layout\n");
-			gb_exit(1);
+			compiler_error("Invalid `Type_Info` layout");
 		}
 		}
 		t_type_info_named     = record->fields[ 1]->type;
 		t_type_info_named     = record->fields[ 1]->type;
 		t_type_info_integer   = record->fields[ 2]->type;
 		t_type_info_integer   = record->fields[ 2]->type;
@@ -1042,6 +1041,8 @@ void check_parsed_files(Checker *c) {
 			}
 			}
 			if (!previously_added) {
 			if (!previously_added) {
 				gb_array_append(file_scope->imported, scope);
 				gb_array_append(file_scope->imported, scope);
+			} else {
+				warning(id->token, "Multiple #import of the same file within this scope");
 			}
 			}
 
 
 			if (are_strings_equal(id->import_name.string, make_string("_"))) {
 			if (are_strings_equal(id->import_name.string, make_string("_"))) {

+ 15 - 21
src/checker/entity.cpp

@@ -26,37 +26,37 @@ String const entity_strings[] = {
 };
 };
 
 
 
 
-typedef i64 EntityGuid;
 typedef struct Type Type;
 typedef struct Type Type;
 
 
 struct Entity {
 struct Entity {
 	EntityKind kind;
 	EntityKind kind;
-	EntityGuid guid;
 
 
-	Scope *scope;
-	Token token;
-	Type *type;
-	Entity *using_parent;
-	AstNode *using_expr;
+	Scope *    scope;
+	Token      token;
+	Type *     type;
+	Entity *   using_parent;
+	AstNode *  using_expr;
 
 
 	union {
 	union {
-		struct { ExactValue value; } Constant;
 		struct {
 		struct {
-			b8  visited;   // Cycle detection
-			b8  used;      // Variable is used
-			b8  anonymous; // Variable is an anonymous
-			b8  is_using;  // `using` variable
+			ExactValue value;
+		} Constant;
+		struct {
+			b8  visited;     // Cycle detection
+			b8  used;        // Variable is used
+			b8  anonymous;   // Variable is an anonymous
+			b8  is_using;    // `using` variable
 
 
 			i32 field_index; // Order in source
 			i32 field_index; // Order in source
 			b8  is_field;    // Is struct field
 			b8  is_field;    // Is struct field
 		} Variable;
 		} Variable;
 		struct {
 		struct {
-			// struct DeclInfo *decl; // Usually NULL
 		} TypeName;
 		} TypeName;
 		struct {
 		struct {
-			b8 pure;
 		} Procedure;
 		} Procedure;
-		struct { BuiltinProcId id; } Builtin;
+		struct {
+			BuiltinProcId id;
+		} Builtin;
 		struct {
 		struct {
 			String path;
 			String path;
 			String name;
 			String name;
@@ -78,16 +78,10 @@ b32 is_entity_exported(Entity *e) {
 	return true;
 	return true;
 }
 }
 
 
-gb_global gbAtomic64 entity_guid_counter = {0};
-
-EntityGuid next_entity_guid(void) {
-	return cast(EntityGuid)gb_atomic64_fetch_add(&entity_guid_counter, 1);
-}
 
 
 Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token, Type *type) {
 Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token, Type *type) {
 	Entity *entity = gb_alloc_item(a, Entity);
 	Entity *entity = gb_alloc_item(a, Entity);
 	entity->kind   = kind;
 	entity->kind   = kind;
-	entity->guid   = next_entity_guid();
 	entity->scope  = scope;
 	entity->scope  = scope;
 	entity->token  = token;
 	entity->token  = token;
 	entity->type   = type;
 	entity->type   = type;

+ 5 - 5
src/checker/stmt.cpp

@@ -668,7 +668,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
 
 
 
 
 
 
-void check_var_decl(Checker *c, AstNode *node) {
+void check_var_decl_node(Checker *c, AstNode *node) {
 	ast_node(vd, VarDecl, node);
 	ast_node(vd, VarDecl, node);
 	isize entity_count = gb_array_count(vd->names);
 	isize entity_count = gb_array_count(vd->names);
 	isize entity_index = 0;
 	isize entity_index = 0;
@@ -736,7 +736,7 @@ void check_var_decl(Checker *c, AstNode *node) {
 }
 }
 
 
 
 
-void check_const_decl(Checker *c, AstNode *node) {
+void check_const_decl_node(Checker *c, AstNode *node) {
 	ast_node(vd, ConstDecl, node);
 	ast_node(vd, ConstDecl, node);
 	isize entity_count = gb_array_count(vd->names);
 	isize entity_count = gb_array_count(vd->names);
 	isize entity_index = 0;
 	isize entity_index = 0;
@@ -1425,7 +1425,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 			if (gb_array_count(vd->names) > 1 && vd->type != NULL) {
 			if (gb_array_count(vd->names) > 1 && vd->type != NULL) {
 				error(us->token, "`using` can only be applied to one variable of the same type");
 				error(us->token, "`using` can only be applied to one variable of the same type");
 			}
 			}
-			check_var_decl(c, us->node);
+			check_var_decl_node(c, us->node);
 
 
 			gb_for_array(name_index, vd->names) {
 			gb_for_array(name_index, vd->names) {
 				AstNode *item = vd->names[name_index];
 				AstNode *item = vd->names[name_index];
@@ -1467,11 +1467,11 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 
 
 
 
 	case_ast_node(vd, VarDecl, node);
 	case_ast_node(vd, VarDecl, node);
-		check_var_decl(c, node);
+		check_var_decl_node(c, node);
 	case_end;
 	case_end;
 
 
 	case_ast_node(cd, ConstDecl, node);
 	case_ast_node(cd, ConstDecl, node);
-		check_const_decl(c, node);
+		check_const_decl_node(c, node);
 	case_end;
 	case_end;
 
 
 	case_ast_node(pd, ProcDecl, node);
 	case_ast_node(pd, ProcDecl, node);

+ 11 - 8
src/checker/type.cpp

@@ -96,7 +96,7 @@ enum TypeRecordKind {
 };
 };
 
 
 struct Type {
 struct Type {
-	u32 flags;
+	u32 flags; // See parser.cpp `enum TypeFlag`
 	TypeKind kind;
 	TypeKind kind;
 	union {
 	union {
 		BasicType Basic;
 		BasicType Basic;
@@ -908,9 +908,9 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 	case Type_Vector: {
 	case Type_Vector: {
 		i64 size = type_size_of(s, allocator, t->Vector.elem);
 		i64 size = type_size_of(s, allocator, t->Vector.elem);
 		size *= t->Vector.count;
 		size *= t->Vector.count;
-		size = next_pow2(size);
+		size = prev_pow2(size);
 		// TODO(bill): Type_Vector type_align_of
 		// TODO(bill): Type_Vector type_align_of
-		return gb_clamp(size, s.max_align, 4*s.max_align);
+		return gb_clamp(size, 1, s.max_align);
 	} break;
 	} break;
 
 
 	case Type_Record: {
 	case Type_Record: {
@@ -920,8 +920,9 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 				i64 max = 1;
 				i64 max = 1;
 				for (isize i = 0; i < t->Record.field_count; i++) {
 				for (isize i = 0; i < t->Record.field_count; i++) {
 					i64 align = type_align_of(s, allocator, t->Record.fields[i]->type);
 					i64 align = type_align_of(s, allocator, t->Record.fields[i]->type);
-					if (max < align)
+					if (max < align) {
 						max = align;
 						max = align;
+					}
 				}
 				}
 				return max;
 				return max;
 			}
 			}
@@ -931,8 +932,9 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 			for (isize i = 1; i < t->Record.field_count; i++) {
 			for (isize i = 1; i < t->Record.field_count; i++) {
 				// NOTE(bill): field zero is null
 				// NOTE(bill): field zero is null
 				i64 align = type_align_of(s, allocator, t->Record.fields[i]->type);
 				i64 align = type_align_of(s, allocator, t->Record.fields[i]->type);
-				if (max < align)
+				if (max < align) {
 					max = align;
 					max = align;
+				}
 			}
 			}
 			return max;
 			return max;
 		} break;
 		} break;
@@ -940,8 +942,9 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 			i64 max = 1;
 			i64 max = 1;
 			for (isize i = 0; i < t->Record.field_count; i++) {
 			for (isize i = 0; i < t->Record.field_count; i++) {
 				i64 align = type_align_of(s, allocator, t->Record.fields[i]->type);
 				i64 align = type_align_of(s, allocator, t->Record.fields[i]->type);
-				if (max < align)
+				if (max < align) {
 					max = align;
 					max = align;
+				}
 			}
 			}
 			return max;
 			return max;
 		} break;
 		} break;
@@ -955,7 +958,6 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 }
 }
 
 
 i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields, isize field_count, b32 is_packed) {
 i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields, isize field_count, b32 is_packed) {
-	// TODO(bill): use arena allocation
 	i64 *offsets = gb_alloc_array(allocator, i64, field_count);
 	i64 *offsets = gb_alloc_array(allocator, i64, field_count);
 	i64 curr_offset = 0;
 	i64 curr_offset = 0;
 	if (is_packed) {
 	if (is_packed) {
@@ -1040,8 +1042,9 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 		switch (t->Record.kind) {
 		switch (t->Record.kind) {
 		case TypeRecord_Struct: {
 		case TypeRecord_Struct: {
 			i64 count = t->Record.field_count;
 			i64 count = t->Record.field_count;
-			if (count == 0)
+			if (count == 0) {
 				return 0;
 				return 0;
+			}
 			type_set_offsets(s, allocator, t);
 			type_set_offsets(s, allocator, t);
 			return t->Record.struct_offsets[count-1] + type_size_of(s, allocator, t->Record.fields[count-1]->type);
 			return t->Record.struct_offsets[count-1] + type_size_of(s, allocator, t->Record.fields[count-1]->type);
 		} break;
 		} break;

+ 36 - 28
src/codegen/codegen.cpp

@@ -31,6 +31,40 @@ void ssa_gen_destroy(ssaGen *s) {
 	gb_file_close(&s->output_file);
 	gb_file_close(&s->output_file);
 }
 }
 
 
+String ssa_mangle_name(ssaGen *s, String path, String name) {
+	// NOTE(bill): prefix names not in the init scope
+	// TODO(bill): make robust and not just rely on the file's name
+
+	ssaModule *m = &s->module;
+	CheckerInfo *info = m->info;
+	gbAllocator a = m->allocator;
+	AstFile *file = *map_get(&info->files, hash_string(path));
+
+	char *str = gb_alloc_array(a, char, path.len+1);
+	gb_memcopy(str, path.text, path.len);
+	str[path.len] = 0;
+	for (isize i = 0; i < path.len; i++) {
+		if (str[i] == '\\') {
+			str[i] = '/';
+		}
+
+	}
+
+	char const *base = gb_path_base_name(str);
+	char const *ext = gb_path_extension(base);
+	isize base_len = ext-1-base;
+
+	isize max_len = base_len + 1 + 10 + 1 + name.len;
+	u8 *new_name = gb_alloc_array(a, u8, max_len);
+	isize new_name_len = gb_snprintf(
+		cast(char *)new_name, max_len,
+		"%.*s$%u.%.*s",
+		base_len, base,
+		file->id,
+		LIT(name));
+
+	return make_string(new_name, new_name_len-1);
+}
 
 
 void ssa_gen_tree(ssaGen *s) {
 void ssa_gen_tree(ssaGen *s) {
 	if (v_zero == NULL) {
 	if (v_zero == NULL) {
@@ -62,34 +96,8 @@ void ssa_gen_tree(ssaGen *s) {
 
 
 		DeclInfo *decl = entry->value;
 		DeclInfo *decl = entry->value;
 		Scope *scope = e->scope;
 		Scope *scope = e->scope;
-		if (scope->is_global ||
-		    scope->is_init) {
-
-		} else {
-			// NOTE(bill): prefix names not in the init scope
-			// TODO(bill): make robust and not just rely on the file's name
-			String path = e->token.pos.file;
-			char *str = gb_alloc_array(a, char, path.len+1);
-			gb_memcopy(str, path.text, path.len);
-			str[path.len] = 0;
-			for (isize i = 0; i < path.len; i++) {
-				if (str[i] == '\\') {
-					str[i] = '/';
-				}
-
-			}
-			char const *base = gb_path_base_name(str);
-			char const *ext = gb_path_extension(base);
-			isize base_len = ext-1-base;
-
-			isize new_len = base_len + 1 + name.len;
-			u8 *new_name = gb_alloc_array(a, u8, new_len);
-			gb_memcopy(new_name, base, base_len);
-			new_name[base_len] = '.';
-			gb_memcopy(new_name+base_len+1, name.text, name.len);
-
-			name = make_string(new_name, new_len);
-			// gb_printf("%.*s\n", new_len, new_name);
+		if (!scope->is_global && !scope->is_init) {
+			name = ssa_mangle_name(s, e->token.pos.file, name);
 		}
 		}
 
 
 
 

+ 15 - 9
src/codegen/print_llvm.cpp

@@ -119,7 +119,7 @@ void ssa_print_encoded_local(ssaFileBuffer *f, String name) {
 	ssa_print_escape_string(f, name, true);
 	ssa_print_escape_string(f, name, true);
 }
 }
 
 
-void ssa_print_encoded_global(ssaFileBuffer *f, String name, b32 global_scope = false) {
+void ssa_print_encoded_global(ssaFileBuffer *f, String name, b32 global_scope) {
 	ssa_fprintf(f, "@");
 	ssa_fprintf(f, "@");
 	if (!global_scope && !are_strings_equal(name, make_string("main"))) {
 	if (!global_scope && !are_strings_equal(name, make_string("main"))) {
 		ssa_fprintf(f, ".");
 		ssa_fprintf(f, ".");
@@ -337,20 +337,25 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type
 		ssa_print_encoded_local(f, value->TypeName.name);
 		ssa_print_encoded_local(f, value->TypeName.name);
 		break;
 		break;
 	case ssaValue_Global: {
 	case ssaValue_Global: {
+		Scope *scope = value->Global.entity->scope;
+		b32 in_global_scope = false;
+		if (scope != NULL) {
+			in_global_scope = scope->is_global || scope->is_init;
+		}
 		if (type_hint != NULL && is_type_string(type_hint)) {
 		if (type_hint != NULL && is_type_string(type_hint)) {
 			ssa_fprintf(f, "{i8* getelementptr inbounds (");
 			ssa_fprintf(f, "{i8* getelementptr inbounds (");
 			ssa_print_type(f, m->sizes, value->Global.entity->type);
 			ssa_print_type(f, m->sizes, value->Global.entity->type);
 			ssa_fprintf(f, ", ");
 			ssa_fprintf(f, ", ");
 			ssa_print_type(f, m->sizes, value->Global.entity->type);
 			ssa_print_type(f, m->sizes, value->Global.entity->type);
 			ssa_fprintf(f, "* ");
 			ssa_fprintf(f, "* ");
-			ssa_print_encoded_global(f, value->Global.entity->token.string);
+			ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope);
 			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, " 0, i32 0), ");
 			ssa_fprintf(f, " 0, i32 0), ");
 			ssa_print_type(f, m->sizes, t_int);
 			ssa_print_type(f, m->sizes, t_int);
 			ssa_fprintf(f, " %lld}", 0);
 			ssa_fprintf(f, " %lld}", 0);
 		} else {
 		} else {
-			ssa_print_encoded_global(f, value->Global.entity->token.string);
+			ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope);
 		}
 		}
 	} break;
 	} break;
 	case ssaValue_Param:
 	case ssaValue_Param:
@@ -374,7 +379,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
 	switch (instr->kind) {
 	switch (instr->kind) {
 	case ssaInstr_StartupRuntime: {
 	case ssaInstr_StartupRuntime: {
 		ssa_fprintf(f, "call void ");
 		ssa_fprintf(f, "call void ");
-		ssa_print_encoded_global(f, make_string(SSA_STARTUP_RUNTIME_PROC_NAME));
+		ssa_print_encoded_global(f, make_string(SSA_STARTUP_RUNTIME_PROC_NAME), false);
 		ssa_fprintf(f, "()\n");
 		ssa_fprintf(f, "()\n");
 	} break;
 	} break;
 
 
@@ -823,10 +828,6 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
 	}
 	}
 
 
 
 
-	if (proc->tags & ProcTag_foreign) {
-		ssa_fprintf(f, "; foreign\n");
-	}
-
 	if (proc->body != NULL) {
 	if (proc->body != NULL) {
 		// ssa_fprintf(f, "nounwind uwtable {\n");
 		// ssa_fprintf(f, "nounwind uwtable {\n");
 
 
@@ -915,7 +916,12 @@ void ssa_print_llvm_ir(ssaFileBuffer *f, ssaModule *m) {
 			continue;
 			continue;
 		}
 		}
 		auto *g = &v->Global;
 		auto *g = &v->Global;
-		ssa_print_encoded_global(f, g->entity->token.string);
+		Scope *scope = g->entity->scope;
+		b32 in_global_scope = false;
+		if (scope != NULL) {
+			in_global_scope = scope->is_global || scope->is_init;
+		}
+		ssa_print_encoded_global(f, g->entity->token.string, in_global_scope);
 		ssa_fprintf(f, " = ");
 		ssa_fprintf(f, " = ");
 		if (g->is_thread_local) {
 		if (g->is_thread_local) {
 			ssa_fprintf(f, "thread_local ");
 			ssa_fprintf(f, "thread_local ");

+ 31 - 0
src/common.cpp

@@ -4,6 +4,21 @@
 
 
 #include "string.cpp"
 #include "string.cpp"
 
 
+
+struct BlockTimer {
+	u64 start;
+	u64 finish;
+	char *msg;
+	BlockTimer(char *msg) : msg(msg) {
+		start = gb_utc_time_now();
+	}
+	~BlockTimer() {
+		finish = gb_utc_time_now();
+		gb_printf_err("%s - %llu us\n", finish-start);
+	}
+};
+
+
 // Hasing
 // Hasing
 
 
 struct HashKey {
 struct HashKey {
@@ -45,6 +60,9 @@ b32 hash_key_equal(HashKey a, HashKey b) {
 }
 }
 
 
 i64 next_pow2(i64 n) {
 i64 next_pow2(i64 n) {
+	if (n <= 0) {
+		return 0;
+	}
 	n--;
 	n--;
 	n |= n >> 1;
 	n |= n >> 1;
 	n |= n >> 2;
 	n |= n >> 2;
@@ -56,6 +74,19 @@ i64 next_pow2(i64 n) {
 	return n;
 	return n;
 }
 }
 
 
+i64 prev_pow2(i64 n) {
+	if (n <= 0) {
+		return 0;
+	}
+	n |= n >> 1;
+	n |= n >> 2;
+	n |= n >> 4;
+	n |= n >> 8;
+	n |= n >> 16;
+	n |= n >> 32;
+	return n - (n >> 1);
+}
+
 
 
 #define gb_for_array(index_, array_) for (isize index_ = 0; (array_) != NULL && index_ < gb_array_count(array_); index_++)
 #define gb_for_array(index_, array_) for (isize index_ = 0; (array_) != NULL && index_ < gb_array_count(array_); index_++)
 
 

+ 11 - 8
src/main.cpp

@@ -40,20 +40,19 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
 	}
 	}
 }
 }
 
 
-
 #if defined(DISPLAY_TIMING)
 #if defined(DISPLAY_TIMING)
-#define INIT_TIMER() u64 start_time, end_time = 0, total_time = 0; start_time = gb_utc_time_now()
+#define INIT_TIMER() f64 start_time = gb_time_now(), end_time = 0, total_time = 0
 #define PRINT_TIMER(section) do { \
 #define PRINT_TIMER(section) do { \
-	u64 diff; \
-	end_time = gb_utc_time_now(); \
+	f64 diff; \
+	end_time = gb_time_now(); \
 	diff = end_time - start_time; \
 	diff = end_time - start_time; \
 	total_time += diff; \
 	total_time += diff; \
-	gb_printf_err("%s: %.1f ms\n", section, diff/1000.0f); \
-	start_time = gb_utc_time_now(); \
+	gb_printf_err("%s: %.1f ms\n", section, diff*1000.0); \
+	start_time = gb_time_now(); \
 } while (0)
 } while (0)
 
 
 #define PRINT_ACCUMULATION() do { \
 #define PRINT_ACCUMULATION() do { \
-	gb_printf_err("Total compilation time: %lld ms\n", total_time/1000); \
+	gb_printf_err("Total compilation time: %.1f ms\n", total_time*1000.0); \
 } while (0)
 } while (0)
 #else
 #else
 #define INIT_TIMER()
 #define INIT_TIMER()
@@ -94,8 +93,12 @@ int main(int argc, char **argv) {
 
 
 #if 1
 #if 1
 	Checker checker = {};
 	Checker checker = {};
+	BaseTypeSizes sizes = {};
+	// NOTE(bill): x64
+	sizes.word_size = 8;
+	sizes.max_align = 16;
 
 
-	init_checker(&checker, &parser);
+	init_checker(&checker, &parser, sizes);
 	defer (destroy_checker(&checker));
 	defer (destroy_checker(&checker));
 
 
 	check_parsed_files(&checker);
 	check_parsed_files(&checker);

+ 8 - 18
src/parser.cpp

@@ -17,6 +17,7 @@ enum ParseFileError {
 typedef gbArray(AstNode *) AstNodeArray;
 typedef gbArray(AstNode *) AstNodeArray;
 
 
 struct AstFile {
 struct AstFile {
+	u32            id;
 	gbArena        arena;
 	gbArena        arena;
 	Tokenizer      tokenizer;
 	Tokenizer      tokenizer;
 	gbArray(Token) tokens;
 	gbArray(Token) tokens;
@@ -2661,12 +2662,14 @@ ParseFileError init_ast_file(AstFile *f, String fullpath) {
 		gb_array_init(f->tokens, gb_heap_allocator());
 		gb_array_init(f->tokens, gb_heap_allocator());
 		for (;;) {
 		for (;;) {
 			Token token = tokenizer_get_token(&f->tokenizer);
 			Token token = tokenizer_get_token(&f->tokenizer);
-			if (token.kind == Token_Invalid)
+			if (token.kind == Token_Invalid) {
 				return ParseFile_InvalidToken;
 				return ParseFile_InvalidToken;
+			}
 			gb_array_append(f->tokens, token);
 			gb_array_append(f->tokens, token);
 
 
-			if (token.kind == Token_EOF)
+			if (token.kind == Token_EOF) {
 				break;
 				break;
+			}
 		}
 		}
 
 
 		f->cursor = &f->tokens[0];
 		f->cursor = &f->tokens[0];
@@ -2842,6 +2845,7 @@ void parse_file(Parser *p, AstFile *f) {
 		}
 		}
 		base_dir.len--;
 		base_dir.len--;
 	}
 	}
+
 	gbAllocator allocator = gb_heap_allocator(); // TODO(bill): Change this allocator
 	gbAllocator allocator = gb_heap_allocator(); // TODO(bill): Change this allocator
 
 
 	f->decls = parse_stmt_list(f);
 	f->decls = parse_stmt_list(f);
@@ -2917,26 +2921,11 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
 		AstFile file = {};
 		AstFile file = {};
 		ParseFileError err = init_ast_file(&file, import_path);
 		ParseFileError err = init_ast_file(&file, import_path);
 
 
-		// if (err == ParseFile_NotFound) {
-		// 	// HACK(bill): Check core directory
-		// 	char buf[300] = {};
-		// 	char core[] = "W:/Odin/core/";
-		// 	isize len = gb_size_of(core)-1;
-		// 	gb_memcopy(buf, core, len);
-		// 	gb_memcopy(buf+len, import_rel_path.text, import_rel_path.len);
-		// 	char *path = gb_path_get_full_name(gb_heap_allocator(), buf);
-		// 	gb_printf_err("%s\n", path);
-
-		// 	import_path = make_string(path);
-		// 	err = init_ast_file(&file, import_path);
-		// 	p->imports[i].path = import_path;
-		// }
-
 		if (err != ParseFile_None) {
 		if (err != ParseFile_None) {
 			if (pos.line != 0) {
 			if (pos.line != 0) {
 				gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column);
 				gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column);
 			}
 			}
-			gb_printf_err("Failed to parse file: %.*s\n", LIT(import_path));
+			gb_printf_err("Failed to parse file: %.*s\n", LIT(import_rel_path));
 			switch (err) {
 			switch (err) {
 			case ParseFile_WrongExtension:
 			case ParseFile_WrongExtension:
 				gb_printf_err("\tInvalid file extension\n");
 				gb_printf_err("\tInvalid file extension\n");
@@ -2960,6 +2949,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
 			return err;
 			return err;
 		}
 		}
 		parse_file(p, &file);
 		parse_file(p, &file);
+		file.id = gb_array_count(p->files);
 		gb_array_append(p->files, file);
 		gb_array_append(p->files, file);
 		p->total_token_count += gb_array_count(file.tokens);
 		p->total_token_count += gb_array_count(file.tokens);
 	}
 	}

+ 12 - 0
src/tokenizer.cpp

@@ -210,6 +210,17 @@ void syntax_error(Token token, char *fmt, ...) {
 }
 }
 
 
 
 
+void compiler_error(char *fmt, ...) {
+	va_list va;
+
+	va_start(va, fmt);
+	gb_printf_err("Internal Compiler Error: %s\n",
+	              gb_bprintf_va(fmt, va));
+	va_end(va);
+	gb_exit(1);
+}
+
+
 
 
 // NOTE(bill): result == priority
 // NOTE(bill): result == priority
 i32 token_precedence(Token t) {
 i32 token_precedence(Token t) {
@@ -354,6 +365,7 @@ TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
 
 
 	defer (gb_free(gb_heap_allocator(), c_str));
 	defer (gb_free(gb_heap_allocator(), c_str));
 
 
+
 	gbFileContents fc = gb_file_read_contents(gb_heap_allocator(), true, c_str);
 	gbFileContents fc = gb_file_read_contents(gb_heap_allocator(), true, c_str);
 	gb_zero_item(t);
 	gb_zero_item(t);
 	if (fc.data != NULL) {
 	if (fc.data != NULL) {