Browse Source

Attributes; @(link_name="foo")

gingerBill 7 years ago
parent
commit
1eb9994d88
26 changed files with 825 additions and 603 deletions
  1. 70 53
      core/_preload.odin
  2. 20 10
      core/_soft_numbers.odin
  3. 78 78
      core/bits.odin
  4. 28 31
      core/c.odin
  5. 2 2
      core/fmt.odin
  6. 26 23
      core/math.odin
  7. 12 12
      core/mem.odin
  8. 27 27
      core/opengl.odin
  9. 32 32
      core/os_linux.odin
  10. 2 2
      core/os_windows.odin
  11. 36 36
      core/os_x.odin
  12. 1 1
      core/sync_linux.odin
  13. 3 1
      core/sync_windows.odin
  14. 47 16
      core/sys/wgl.odin
  15. 177 170
      core/sys/windows.odin
  16. 4 4
      core/utf8.odin
  17. 85 12
      src/check_decl.cpp
  18. 4 3
      src/check_expr.cpp
  19. 1 1
      src/check_stmt.cpp
  20. 11 3
      src/checker.cpp
  21. 21 20
      src/ir.cpp
  22. 9 8
      src/ir_print.cpp
  23. 118 52
      src/parser.cpp
  24. 2 2
      src/ssa.cpp
  25. 2 0
      src/tokenizer.cpp
  26. 7 4
      src/types.cpp

+ 70 - 53
core/_preload.odin

@@ -17,8 +17,6 @@ import "core:raw.odin"
 // Constant Variables: SCREAMING_SNAKE_CASE
 
 
-
-
 // IMPORTANT NOTE(bill): `type_info_of` cannot be used within a
 // #shared_global_scope due to  the internals of the compiler.
 // This could change at a later date if the all these data structures are
@@ -237,15 +235,22 @@ type_info_base_without_enum :: proc(info: ^Type_Info) -> ^Type_Info {
 
 
 foreign __llvm_core {
-	assume             :: proc(cond: bool) #cc_c #link_name "llvm.assume"           ---;
-	__debug_trap       :: proc()           #cc_c #link_name "llvm.debugtrap"        ---;
-	__trap             :: proc()           #cc_c #link_name "llvm.trap"             ---;
-	read_cycle_counter :: proc() -> u64    #cc_c #link_name "llvm.readcyclecounter" ---;
+	@(link_name="llvm.assume")
+	assume :: proc(cond: bool) #cc_c ---;
+
+	@(link_name="llvm.debugtrap")
+	__debug_trap :: proc() #cc_c ---;
+
+	@(link_name="llvm.trap")
+	__trap :: proc() #cc_c ---;
+
+	@(link_name="llvm.readcyclecounter")
+	read_cycle_counter :: proc() -> u64 #cc_c ---;
 }
 
 
 
-make_source_code_location :: proc(file: string, line, column: i64, procedure: string) -> Source_Code_Location #cc_contextless #inline {
+make_source_code_location :: inline proc(file: string, line, column: i64, procedure: string) -> Source_Code_Location #cc_contextless {
 	return Source_Code_Location{file, line, column, procedure};
 }
 
@@ -282,32 +287,32 @@ __check_context :: proc() {
 }
 */
 
-alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline {
+alloc :: inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr {
 	a := context.allocator;
 	return a.procedure(a.data, Allocator_Mode.Alloc, size, alignment, nil, 0, 0);
 }
 
-free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline {
+free_ptr_with_allocator :: inline proc(a: Allocator, ptr: rawptr) {
 	if ptr == nil do return;
 	if a.procedure == nil do return;
 	a.procedure(a.data, Allocator_Mode.Free, 0, 0, ptr, 0, 0);
 }
 
-free_ptr :: proc(ptr: rawptr) #inline do free_ptr_with_allocator(context.allocator, ptr);
+free_ptr :: inline proc(ptr: rawptr) do free_ptr_with_allocator(context.allocator, ptr);
 
-free_all :: proc() #inline {
+free_all :: inline proc() {
 	a := context.allocator;
 	a.procedure(a.data, Allocator_Mode.FreeAll, 0, 0, nil, 0, 0);
 }
 
 
-resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline {
+resize :: inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr {
 	a := context.allocator;
 	return a.procedure(a.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, 0);
 }
 
 
-copy :: proc(dst, src: $T/[]$E) -> int #cc_contextless {
+copy :: proc(dst, src: $T/[]$E) -> int {
 	n := max(0, min(len(dst), len(src)));
 	if n > 0 do __mem_copy(&dst[0], &src[0], n*size_of(E));
 	return n;
@@ -384,13 +389,13 @@ pop :: proc(array: ^$T/[dynamic]$E) -> E #cc_contextless {
 	return res;
 }
 
-clear :: proc(slice: ^$T/[]$E) #cc_contextless #inline {
+clear :: inline proc(slice: ^$T/[]$E) #cc_contextless {
 	if slice != nil do (cast(^raw.Slice)slice).len = 0;
 }
-clear :: proc(array: ^$T/[dynamic]$E) #cc_contextless #inline {
+clear :: inline proc(array: ^$T/[dynamic]$E) #cc_contextless {
 	if array != nil do (cast(^raw.Dynamic_Array)array).len = 0;
 }
-clear :: proc(m: ^$T/map[$K]$V) #cc_contextless #inline {
+clear :: inline proc(m: ^$T/map[$K]$V) #cc_contextless {
 	if m == nil do return;
 	raw_map := cast(^raw.Map)m;
 	hashes  := cast(^raw.Dynamic_Array)&raw_map.hashes;
@@ -483,12 +488,12 @@ delete :: proc(m: ^$T/map[$K]$V, key: K) {
 
 
 
-new  :: proc(T: type) -> ^T #inline {
+new  :: inline proc(T: type) -> ^T {
 	ptr := cast(^T)alloc(size_of(T), align_of(T));
 	ptr^ = T{};
 	return ptr;
 }
-new_clone :: proc(data: $T) -> ^T #inline {
+new_clone :: inline proc(data: $T) -> ^T {
 	ptr := cast(^T)alloc(size_of(T), align_of(T));
 	ptr^ = data;
 	return ptr;
@@ -637,18 +642,18 @@ __string_cmp :: proc(a, b: string) -> int #cc_contextless {
 	return __mem_compare(&a[0], &b[0], min(len(a), len(b)));
 }
 
-__string_ne :: proc(a, b: string) -> bool #cc_contextless #inline { return !__string_eq(a, b); }
-__string_lt :: proc(a, b: string) -> bool #cc_contextless #inline { return __string_cmp(a, b) < 0; }
-__string_gt :: proc(a, b: string) -> bool #cc_contextless #inline { return __string_cmp(a, b) > 0; }
-__string_le :: proc(a, b: string) -> bool #cc_contextless #inline { return __string_cmp(a, b) <= 0; }
-__string_ge :: proc(a, b: string) -> bool #cc_contextless #inline { return __string_cmp(a, b) >= 0; }
+__string_ne :: inline proc(a, b: string) -> bool #cc_contextless { return !__string_eq(a, b); }
+__string_lt :: inline proc(a, b: string) -> bool #cc_contextless { return __string_cmp(a, b) < 0; }
+__string_gt :: inline proc(a, b: string) -> bool #cc_contextless { return __string_cmp(a, b) > 0; }
+__string_le :: inline proc(a, b: string) -> bool #cc_contextless { return __string_cmp(a, b) <= 0; }
+__string_ge :: inline proc(a, b: string) -> bool #cc_contextless { return __string_cmp(a, b) >= 0; }
 
 
-__complex64_eq :: proc (a, b: complex64)  -> bool #cc_contextless #inline { return real(a) == real(b) && imag(a) == imag(b); }
-__complex64_ne :: proc (a, b: complex64)  -> bool #cc_contextless #inline { return real(a) != real(b) || imag(a) != imag(b); }
+__complex64_eq :: inline proc (a, b: complex64)  -> bool #cc_contextless { return real(a) == real(b) && imag(a) == imag(b); }
+__complex64_ne :: inline proc (a, b: complex64)  -> bool #cc_contextless { return real(a) != real(b) || imag(a) != imag(b); }
 
-__complex128_eq :: proc(a, b: complex128) -> bool #cc_contextless #inline { return real(a) == real(b) && imag(a) == imag(b); }
-__complex128_ne :: proc(a, b: complex128) -> bool #cc_contextless #inline { return real(a) != real(b) || imag(a) != imag(b); }
+__complex128_eq :: inline proc(a, b: complex128) -> bool #cc_contextless { return real(a) == real(b) && imag(a) == imag(b); }
+__complex128_ne :: inline proc(a, b: complex128) -> bool #cc_contextless { return real(a) != real(b) || imag(a) != imag(b); }
 
 
 __bounds_check_error :: proc(file: string, line, column: int, index, count: int) #cc_contextless {
@@ -678,7 +683,7 @@ __type_assertion_check :: proc(ok: bool, file: string, line, column: int, from,
 	__debug_trap();
 }
 
-__string_decode_rune :: proc(s: string) -> (rune, int) #cc_contextless #inline {
+__string_decode_rune :: inline proc(s: string) -> (rune, int) #cc_contextless {
 	return utf8.decode_rune(s);
 }
 
@@ -694,10 +699,14 @@ __substring_expr_error_loc :: proc(using loc := #caller_location, low, high: int
 
 __mem_set :: proc(data: rawptr, value: i32, len: int) -> rawptr #cc_contextless {
 	if data == nil do return nil;
-	when size_of(rawptr) == 8 {
-		foreign __llvm_core llvm_memset :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #link_name "llvm.memset.p0i8.i64" ---;
-	} else {
-		foreign __llvm_core llvm_memset :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #link_name "llvm.memset.p0i8.i32" ---;
+	foreign __llvm_core {
+		when size_of(rawptr) == 8 {
+			@(link_name="llvm.memset.p0i8.i64")
+			llvm_memset :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) ---;
+		} else {
+			@(link_name="llvm.memset.p0i8.i32")
+			llvm_memset :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) ---;
+		}
 	}
 	llvm_memset(data, u8(value), len, 1, false);
 	return data;
@@ -708,10 +717,14 @@ __mem_zero :: proc(data: rawptr, len: int) -> rawptr #cc_contextless {
 __mem_copy :: proc(dst, src: rawptr, len: int) -> rawptr #cc_contextless {
 	if src == nil do return dst;
 	// NOTE(bill): This _must_ be implemented like C's memmove
-	when size_of(rawptr) == 8 {
-		foreign __llvm_core llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memmove.p0i8.p0i8.i64" ---;
-	} else {
-		foreign __llvm_core llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memmove.p0i8.p0i8.i32" ---;
+	foreign __llvm_core {
+		when size_of(rawptr) == 8 {
+			@(link_name="llvm.memmove.p0i8.p0i8.i64")
+			llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
+		} else {
+			@(link_name="llvm.memmove.p0i8.p0i8.i32")
+			llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
+		}
 	}
 	llvm_memmove(dst, src, len, 1, false);
 	return dst;
@@ -719,10 +732,14 @@ __mem_copy :: proc(dst, src: rawptr, len: int) -> rawptr #cc_contextless {
 __mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #cc_contextless {
 	if src == nil do return dst;
 	// NOTE(bill): This _must_ be implemented like C's memcpy
-	when size_of(rawptr) == 8 {
-		foreign __llvm_core llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i64" ---;
-	} else {
-		foreign __llvm_core llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i32" ---;
+	foreign __llvm_core {
+		when size_of(rawptr) == 8 {
+			@(link_name="llvm.memcpy.p0i8.p0i8.i64")
+	 		llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
+		} else {
+			@(link_name="llvm.memcpy.p0i8.p0i8.i32")
+	 		llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
+		}
 	}
 	llvm_memcpy(dst, src, len, 1, false);
 	return dst;
@@ -737,26 +754,26 @@ __mem_compare :: proc(a, b: ^u8, n: int) -> int #cc_contextless {
 }
 
 foreign __llvm_core {
-	__sqrt_f32 :: proc(x: f32) -> f32        #link_name "llvm.sqrt.f32" ---;
-	__sqrt_f64 :: proc(x: f64) -> f64        #link_name "llvm.sqrt.f64" ---;
+	@(link_name="llvm.sqrt.f32") __sqrt_f32 :: proc(x: f32) -> f32 ---;
+	@(link_name="llvm.sqrt.f64") __sqrt_f64 :: proc(x: f64) -> f64 ---;
 
-	__sin_f32  :: proc(θ: f32) -> f32        #link_name "llvm.sin.f32" ---;
-	__sin_f64  :: proc(θ: f64) -> f64        #link_name "llvm.sin.f64" ---;
+	@(link_name="llvm.sin.f32") __sin_f32  :: proc(θ: f32) -> f32 ---;
+	@(link_name="llvm.sin.f64") __sin_f64  :: proc(θ: f64) -> f64 ---;
 
-	__cos_f32  :: proc(θ: f32) -> f32        #link_name "llvm.cos.f32" ---;
-	__cos_f64  :: proc(θ: f64) -> f64        #link_name "llvm.cos.f64" ---;
+	@(link_name="llvm.cos.f32") __cos_f32  :: proc(θ: f32) -> f32 ---;
+	@(link_name="llvm.cos.f64") __cos_f64  :: proc(θ: f64) -> f64 ---;
 
-	__pow_f32  :: proc(x, power: f32) -> f32 #link_name "llvm.pow.f32" ---;
-	__pow_f64  :: proc(x, power: f64) -> f64 #link_name "llvm.pow.f64" ---;
+	@(link_name="llvm.pow.f32") __pow_f32  :: proc(x, power: f32) -> f32 ---;
+	@(link_name="llvm.pow.f64") __pow_f64  :: proc(x, power: f64) -> f64 ---;
 
-	fmuladd32  :: proc(a, b, c: f32) -> f32 #link_name "llvm.fmuladd.f32" ---;
-	fmuladd64  :: proc(a, b, c: f64) -> f64 #link_name "llvm.fmuladd.f64" ---;
+	@(link_name="llvm.fmuladd.f32") fmuladd32  :: proc(a, b, c: f32) -> f32 ---;
+	@(link_name="llvm.fmuladd.f64") fmuladd64  :: proc(a, b, c: f64) -> f64 ---;
 }
-__abs_complex64 :: proc(x: complex64) -> f32 #inline #cc_contextless {
+__abs_complex64 :: inline proc(x: complex64) -> f32 #cc_contextless {
 	r, i := real(x), imag(x);
 	return __sqrt_f32(r*r + i*i);
 }
-__abs_complex128 :: proc(x: complex128) -> f64 #inline #cc_contextless {
+__abs_complex128 :: inline proc(x: complex128) -> f64 #cc_contextless {
 	r, i := real(x), imag(x);
 	return __sqrt_f64(r*r + i*i);
 }
@@ -971,7 +988,7 @@ __dynamic_map_grow :: proc(using h: __Map_Header) {
 	__dynamic_map_rehash(h, new_count);
 }
 
-__dynamic_map_full :: proc(using h: __Map_Header) -> bool #inline {
+__dynamic_map_full :: inline proc(using h: __Map_Header) -> bool {
 	return int(0.75 * f64(len(m.hashes))) <= m.entries.cap;
 }
 

+ 20 - 10
core/_soft_numbers.odin

@@ -1,6 +1,7 @@
 #shared_global_scope
 
-__multi3 :: proc(a, b: u128) -> u128 #cc_c #link_name "__multi3" {
+@(link_name="__multi3")
+__multi3 :: proc(a, b: u128) -> u128 #cc_c {
 	bits_in_dword_2 :: size_of(i64) * 4;
 	lower_mask :: u128(~u64(0) >> bits_in_dword_2);
 
@@ -35,27 +36,32 @@ __multi3 :: proc(a, b: u128) -> u128 #cc_c #link_name "__multi3" {
 	return r.all;
 }
 
-__u128_mod :: proc(a, b: u128) -> u128 #cc_c #link_name "__umodti3" {
+@(link_name="__umodti3")
+__u128_mod :: proc(a, b: u128) -> u128 #cc_c {
 	r: u128;
 	__u128_quo_mod(a, b, &r);
 	return r;
 }
 
-__u128_quo :: proc(a, b: u128) -> u128 #cc_c #link_name "__udivti3" {
+@(link_name="__udivti3")
+__u128_quo :: proc(a, b: u128) -> u128 #cc_c {
 	return __u128_quo_mod(a, b, nil);
 }
 
-__i128_mod :: proc(a, b: i128) -> i128 #cc_c #link_name "__modti3" {
+@(link_name="__modti3")
+__i128_mod :: proc(a, b: i128) -> i128 #cc_c {
 	r: i128;
 	__i128_quo_mod(a, b, &r);
 	return r;
 }
 
-__i128_quo :: proc(a, b: i128) -> i128 #cc_c #link_name "__divti3" {
+@(link_name="__divti3")
+__i128_quo :: proc(a, b: i128) -> i128 #cc_c {
 	return __i128_quo_mod(a, b, nil);
 }
 
-__i128_quo_mod :: proc(a, b: i128, rem: ^i128) -> (quo: i128) #cc_c #link_name "__divmodti4" {
+@(link_name="__divmodti4")
+__i128_quo_mod :: proc(a, b: i128, rem: ^i128) -> (quo: i128) #cc_c {
 	s: i128;
 	s = b >> 127;
 	b = (b~s) - s;
@@ -74,7 +80,8 @@ __i128_quo_mod :: proc(a, b: i128, rem: ^i128) -> (quo: i128) #cc_c #link_name "
 }
 
 
-__u128_quo_mod :: proc(a, b: u128, rem: ^u128) -> (quo: u128) #cc_c #link_name "__udivmodti4" {
+@(link_name="__udivmodti4")
+__u128_quo_mod :: proc(a, b: u128, rem: ^u128) -> (quo: u128) #cc_c {
 	alo := u64(a);
 	blo := u64(b);
 	if b == 0 {
@@ -103,7 +110,8 @@ __u128_quo_mod :: proc(a, b: u128, rem: ^u128) -> (quo: u128) #cc_c #link_name "
 }
 
 /*
-__f16_to_f32 :: proc(f: f16) -> f32 #cc_c #no_inline #link_name "__gnu_h2f_ieee" {
+@(link_name="__gnu_h2f_ieee")
+__f16_to_f32 :: proc(f: f16) -> f32 #cc_c #no_inline {
 	when true {
 		// Source: https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
 		FP32 :: struct #raw_union {u: u32, f: f32};
@@ -127,7 +135,8 @@ __f16_to_f32 :: proc(f: f16) -> f32 #cc_c #no_inline #link_name "__gnu_h2f_ieee"
 		return 0;
 	}
 }
-__f32_to_f16 :: proc(f_: f32) -> f16 #cc_c #no_inline #link_name "__gnu_f2h_ieee" {
+@(link_name="__gnu_f2h_ieee")
+__f32_to_f16 :: proc(f_: f32) -> f16 #cc_c #no_inline {
 	when false {
 		// Source: https://gist.github.com/rygorous/2156668
 		FP16 :: struct #raw_union {u: u16, f: f16};
@@ -217,7 +226,8 @@ __f32_to_f16 :: proc(f_: f32) -> f16 #cc_c #no_inline #link_name "__gnu_f2h_ieee
 	}
 }
 
-__f64_to_f16 :: proc(f: f64) -> f16 #cc_c #no_inline #link_name "__truncdfhf2" {
+@(link_name="__truncdfhf2")
+__f64_to_f16 :: proc(f: f64) -> f16 #cc_c #no_inline {
 	return __f32_to_f16(f32(f));
 }
 

+ 78 - 78
core/bits.odin

@@ -22,16 +22,16 @@ I32_MAX  ::  i32(0x7fff_ffff);
 I64_MAX  ::  i64(0x7fff_ffff_ffff_ffff);
 I128_MAX :: i128(0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ffff);
 
-count_ones :: proc(i:   u8) ->   u8 { foreign __llvm_core __llvm_ctpop :: proc(u8)   ->   u8 #link_name "llvm.ctpop.i8" ---;  return __llvm_ctpop(i); }
-count_ones :: proc(i:   i8) ->   i8 { foreign __llvm_core __llvm_ctpop :: proc(i8)   ->   i8 #link_name "llvm.ctpop.i8" ---;  return __llvm_ctpop(i); }
-count_ones :: proc(i:  u16) ->  u16 { foreign __llvm_core __llvm_ctpop :: proc(u16)  ->  u16 #link_name "llvm.ctpop.i16" ---; return __llvm_ctpop(i); }
-count_ones :: proc(i:  i16) ->  i16 { foreign __llvm_core __llvm_ctpop :: proc(i16)  ->  i16 #link_name "llvm.ctpop.i16" ---; return __llvm_ctpop(i); }
-count_ones :: proc(i:  u32) ->  u32 { foreign __llvm_core __llvm_ctpop :: proc(u32)  ->  u32 #link_name "llvm.ctpop.i32" ---; return __llvm_ctpop(i); }
-count_ones :: proc(i:  i32) ->  i32 { foreign __llvm_core __llvm_ctpop :: proc(i32)  ->  i32 #link_name "llvm.ctpop.i32" ---; return __llvm_ctpop(i); }
-count_ones :: proc(i:  u64) ->  u64 { foreign __llvm_core __llvm_ctpop :: proc(u64)  ->  u64 #link_name "llvm.ctpop.i64" ---; return __llvm_ctpop(i); }
-count_ones :: proc(i:  i64) ->  i64 { foreign __llvm_core __llvm_ctpop :: proc(i64)  ->  i64 #link_name "llvm.ctpop.i64" ---; return __llvm_ctpop(i); }
-count_ones :: proc(i: u128) -> u128 { foreign __llvm_core __llvm_ctpop :: proc(u128) -> u128 #link_name "llvm.ctpop.i128" ---;return __llvm_ctpop(i); }
-count_ones :: proc(i: i128) -> i128 { foreign __llvm_core __llvm_ctpop :: proc(i128) -> i128 #link_name "llvm.ctpop.i128" ---;return __llvm_ctpop(i); }
+count_ones :: proc(i:   u8) ->   u8 { foreign __llvm_core @(link_name="llvm.ctpop.i8")   __llvm_ctpop :: proc(u8)   ->   u8 ---;  return __llvm_ctpop(i); }
+count_ones :: proc(i:   i8) ->   i8 { foreign __llvm_core @(link_name="llvm.ctpop.i8")   __llvm_ctpop :: proc(i8)   ->   i8 ---;  return __llvm_ctpop(i); }
+count_ones :: proc(i:  u16) ->  u16 { foreign __llvm_core @(link_name="llvm.ctpop.i16")  __llvm_ctpop :: proc(u16)  ->  u16 ---; return __llvm_ctpop(i); }
+count_ones :: proc(i:  i16) ->  i16 { foreign __llvm_core @(link_name="llvm.ctpop.i16")  __llvm_ctpop :: proc(i16)  ->  i16 ---; return __llvm_ctpop(i); }
+count_ones :: proc(i:  u32) ->  u32 { foreign __llvm_core @(link_name="llvm.ctpop.i32")  __llvm_ctpop :: proc(u32)  ->  u32 ---; return __llvm_ctpop(i); }
+count_ones :: proc(i:  i32) ->  i32 { foreign __llvm_core @(link_name="llvm.ctpop.i32")  __llvm_ctpop :: proc(i32)  ->  i32 ---; return __llvm_ctpop(i); }
+count_ones :: proc(i:  u64) ->  u64 { foreign __llvm_core @(link_name="llvm.ctpop.i64")  __llvm_ctpop :: proc(u64)  ->  u64 ---; return __llvm_ctpop(i); }
+count_ones :: proc(i:  i64) ->  i64 { foreign __llvm_core @(link_name="llvm.ctpop.i64")  __llvm_ctpop :: proc(i64)  ->  i64 ---; return __llvm_ctpop(i); }
+count_ones :: proc(i: u128) -> u128 { foreign __llvm_core @(link_name="llvm.ctpop.i128") __llvm_ctpop :: proc(u128) -> u128 ---;return __llvm_ctpop(i); }
+count_ones :: proc(i: i128) -> i128 { foreign __llvm_core @(link_name="llvm.ctpop.i128") __llvm_ctpop :: proc(i128) -> i128 ---;return __llvm_ctpop(i); }
 count_ones :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(count_ones(u32(i))); } else { return uint(count_ones(u64(i))); } }
 count_ones :: proc(i:  int) ->  int { when size_of(int)  == size_of(i32) { return int(count_ones(i32(i)));  } else { return int(count_ones(i64(i))); } }
 
@@ -77,55 +77,55 @@ rotate_right :: proc(i: uint, s: uint) -> uint { when size_of(uint) == size_of(u
 rotate_right :: proc(i:  int, s: uint) ->  int { when size_of(int)  == size_of(i32) { return  int(rotate_right(i32(i), s)); } else { return  int(rotate_right(i64(i), s)); } }
 
 
-leading_zeros :: proc(i:   u8) ->   u8 { foreign __llvm_core __llvm_ctlz :: proc(u8,   bool) ->   u8 #link_name "llvm.ctlz.i8" ---;  return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:   i8) ->   i8 { foreign __llvm_core __llvm_ctlz :: proc(i8,   bool) ->   i8 #link_name "llvm.ctlz.i8" ---;  return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  u16) ->  u16 { foreign __llvm_core __llvm_ctlz :: proc(u16,  bool) ->  u16 #link_name "llvm.ctlz.i16" ---; return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  i16) ->  i16 { foreign __llvm_core __llvm_ctlz :: proc(i16,  bool) ->  i16 #link_name "llvm.ctlz.i16" ---; return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  u32) ->  u32 { foreign __llvm_core __llvm_ctlz :: proc(u32,  bool) ->  u32 #link_name "llvm.ctlz.i32" ---; return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  i32) ->  i32 { foreign __llvm_core __llvm_ctlz :: proc(i32,  bool) ->  i32 #link_name "llvm.ctlz.i32" ---; return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  u64) ->  u64 { foreign __llvm_core __llvm_ctlz :: proc(u64,  bool) ->  u64 #link_name "llvm.ctlz.i64" ---; return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  i64) ->  i64 { foreign __llvm_core __llvm_ctlz :: proc(i64,  bool) ->  i64 #link_name "llvm.ctlz.i64" ---; return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i: u128) -> u128 { foreign __llvm_core __llvm_ctlz :: proc(u128, bool) -> u128 #link_name "llvm.ctlz.i128" ---;return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i: i128) -> i128 { foreign __llvm_core __llvm_ctlz :: proc(i128, bool) -> i128 #link_name "llvm.ctlz.i128" ---;return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:   u8) ->   u8 { foreign __llvm_core @(link_name="llvm.ctlz.i8")   __llvm_ctlz :: proc(u8,   bool) ->   u8 ---;  return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:   i8) ->   i8 { foreign __llvm_core @(link_name="llvm.ctlz.i8")   __llvm_ctlz :: proc(i8,   bool) ->   i8 ---;  return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:  u16) ->  u16 { foreign __llvm_core @(link_name="llvm.ctlz.i16")  __llvm_ctlz :: proc(u16,  bool) ->  u16 ---; return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:  i16) ->  i16 { foreign __llvm_core @(link_name="llvm.ctlz.i16")  __llvm_ctlz :: proc(i16,  bool) ->  i16 ---; return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:  u32) ->  u32 { foreign __llvm_core @(link_name="llvm.ctlz.i32")  __llvm_ctlz :: proc(u32,  bool) ->  u32 ---; return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:  i32) ->  i32 { foreign __llvm_core @(link_name="llvm.ctlz.i32")  __llvm_ctlz :: proc(i32,  bool) ->  i32 ---; return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:  u64) ->  u64 { foreign __llvm_core @(link_name="llvm.ctlz.i64")  __llvm_ctlz :: proc(u64,  bool) ->  u64 ---; return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:  i64) ->  i64 { foreign __llvm_core @(link_name="llvm.ctlz.i64")  __llvm_ctlz :: proc(i64,  bool) ->  i64 ---; return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i: u128) -> u128 { foreign __llvm_core @(link_name="llvm.ctlz.i128") __llvm_ctlz :: proc(u128, bool) -> u128 ---;return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i: i128) -> i128 { foreign __llvm_core @(link_name="llvm.ctlz.i128") __llvm_ctlz :: proc(i128, bool) -> i128 ---;return __llvm_ctlz(i, false); }
 leading_zeros :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(leading_zeros(u32(i))); } else { return uint(leading_zeros(u64(i))); } }
 leading_zeros :: proc(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(leading_zeros(i32(i))); } else { return  int(leading_zeros(i64(i))); } }
 
-trailing_zeros :: proc(i:   u8) ->   u8 { foreign __llvm_core __llvm_cttz :: proc(u8,   bool) ->   u8 #link_name "llvm.cttz.i8" ---;  return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:   i8) ->   i8 { foreign __llvm_core __llvm_cttz :: proc(i8,   bool) ->   i8 #link_name "llvm.cttz.i8" ---;  return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  u16) ->  u16 { foreign __llvm_core __llvm_cttz :: proc(u16,  bool) ->  u16 #link_name "llvm.cttz.i16" ---; return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  i16) ->  i16 { foreign __llvm_core __llvm_cttz :: proc(i16,  bool) ->  i16 #link_name "llvm.cttz.i16" ---; return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  u32) ->  u32 { foreign __llvm_core __llvm_cttz :: proc(u32,  bool) ->  u32 #link_name "llvm.cttz.i32" ---; return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  i32) ->  i32 { foreign __llvm_core __llvm_cttz :: proc(i32,  bool) ->  i32 #link_name "llvm.cttz.i32" ---; return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  u64) ->  u64 { foreign __llvm_core __llvm_cttz :: proc(u64,  bool) ->  u64 #link_name "llvm.cttz.i64" ---; return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  i64) ->  i64 { foreign __llvm_core __llvm_cttz :: proc(i64,  bool) ->  i64 #link_name "llvm.cttz.i64" ---; return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i: u128) -> u128 { foreign __llvm_core __llvm_cttz :: proc(u128, bool) -> u128 #link_name "llvm.cttz.i128" ---;return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i: i128) -> i128 { foreign __llvm_core __llvm_cttz :: proc(i128, bool) -> i128 #link_name "llvm.cttz.i128" ---;return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:   u8) ->   u8 { foreign __llvm_core @(link_name="llvm.cttz.i8")   __llvm_cttz :: proc(u8,   bool) ->   u8 ---;  return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:   i8) ->   i8 { foreign __llvm_core @(link_name="llvm.cttz.i8")   __llvm_cttz :: proc(i8,   bool) ->   i8 ---;  return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:  u16) ->  u16 { foreign __llvm_core @(link_name="llvm.cttz.i16")  __llvm_cttz :: proc(u16,  bool) ->  u16 ---; return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:  i16) ->  i16 { foreign __llvm_core @(link_name="llvm.cttz.i16")  __llvm_cttz :: proc(i16,  bool) ->  i16 ---; return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:  u32) ->  u32 { foreign __llvm_core @(link_name="llvm.cttz.i32")  __llvm_cttz :: proc(u32,  bool) ->  u32 ---; return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:  i32) ->  i32 { foreign __llvm_core @(link_name="llvm.cttz.i32")  __llvm_cttz :: proc(i32,  bool) ->  i32 ---; return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:  u64) ->  u64 { foreign __llvm_core @(link_name="llvm.cttz.i64")  __llvm_cttz :: proc(u64,  bool) ->  u64 ---; return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:  i64) ->  i64 { foreign __llvm_core @(link_name="llvm.cttz.i64")  __llvm_cttz :: proc(i64,  bool) ->  i64 ---; return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i: u128) -> u128 { foreign __llvm_core @(link_name="llvm.cttz.i128") __llvm_cttz :: proc(u128, bool) -> u128 ---;return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i: i128) -> i128 { foreign __llvm_core @(link_name="llvm.cttz.i128") __llvm_cttz :: proc(i128, bool) -> i128 ---;return __llvm_cttz(i, false); }
 trailing_zeros :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(trailing_zeros(u32(i))); } else { return uint(trailing_zeros(u64(i))); } }
 trailing_zeros :: proc(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(trailing_zeros(i32(i))); } else { return  int(trailing_zeros(i64(i))); } }
 
 
-reverse_bits :: proc(i:   u8) ->   u8 { foreign __llvm_core __llvm_bitreverse :: proc(u8)   ->   u8 #link_name "llvm.bitreverse.i8" ---;  return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:   i8) ->   i8 { foreign __llvm_core __llvm_bitreverse :: proc(i8)   ->   i8 #link_name "llvm.bitreverse.i8" ---;  return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  u16) ->  u16 { foreign __llvm_core __llvm_bitreverse :: proc(u16)  ->  u16 #link_name "llvm.bitreverse.i16" ---; return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  i16) ->  i16 { foreign __llvm_core __llvm_bitreverse :: proc(i16)  ->  i16 #link_name "llvm.bitreverse.i16" ---; return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  u32) ->  u32 { foreign __llvm_core __llvm_bitreverse :: proc(u32)  ->  u32 #link_name "llvm.bitreverse.i32" ---; return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  i32) ->  i32 { foreign __llvm_core __llvm_bitreverse :: proc(i32)  ->  i32 #link_name "llvm.bitreverse.i32" ---; return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  u64) ->  u64 { foreign __llvm_core __llvm_bitreverse :: proc(u64)  ->  u64 #link_name "llvm.bitreverse.i64" ---; return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  i64) ->  i64 { foreign __llvm_core __llvm_bitreverse :: proc(i64)  ->  i64 #link_name "llvm.bitreverse.i64" ---; return __llvm_bitreverse(i); }
-reverse_bits :: proc(i: u128) -> u128 { foreign __llvm_core __llvm_bitreverse :: proc(u128) -> u128 #link_name "llvm.bitreverse.i128" ---;return __llvm_bitreverse(i); }
-reverse_bits :: proc(i: i128) -> i128 { foreign __llvm_core __llvm_bitreverse :: proc(i128) -> i128 #link_name "llvm.bitreverse.i128" ---;return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:   u8) ->   u8 { foreign __llvm_core @(link_name="llvm.bitreverse.i8")   __llvm_bitreverse :: proc(u8)   ->   u8 ---;  return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:   i8) ->   i8 { foreign __llvm_core @(link_name="llvm.bitreverse.i8")   __llvm_bitreverse :: proc(i8)   ->   i8 ---;  return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:  u16) ->  u16 { foreign __llvm_core @(link_name="llvm.bitreverse.i16")  __llvm_bitreverse :: proc(u16)  ->  u16 ---; return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:  i16) ->  i16 { foreign __llvm_core @(link_name="llvm.bitreverse.i16")  __llvm_bitreverse :: proc(i16)  ->  i16 ---; return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:  u32) ->  u32 { foreign __llvm_core @(link_name="llvm.bitreverse.i32")  __llvm_bitreverse :: proc(u32)  ->  u32 ---; return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:  i32) ->  i32 { foreign __llvm_core @(link_name="llvm.bitreverse.i32")  __llvm_bitreverse :: proc(i32)  ->  i32 ---; return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:  u64) ->  u64 { foreign __llvm_core @(link_name="llvm.bitreverse.i64")  __llvm_bitreverse :: proc(u64)  ->  u64 ---; return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:  i64) ->  i64 { foreign __llvm_core @(link_name="llvm.bitreverse.i64")  __llvm_bitreverse :: proc(i64)  ->  i64 ---; return __llvm_bitreverse(i); }
+reverse_bits :: proc(i: u128) -> u128 { foreign __llvm_core @(link_name="llvm.bitreverse.i128") __llvm_bitreverse :: proc(u128) -> u128 ---;return __llvm_bitreverse(i); }
+reverse_bits :: proc(i: i128) -> i128 { foreign __llvm_core @(link_name="llvm.bitreverse.i128") __llvm_bitreverse :: proc(i128) -> i128 ---;return __llvm_bitreverse(i); }
 reverse_bits :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(reverse_bits(u32(i))); } else { return uint(reverse_bits(u64(i))); } }
 reverse_bits :: proc(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(reverse_bits(i32(i))); } else { return  int(reverse_bits(i64(i))); } }
 
 foreign __llvm_core {
-	byte_swap :: proc(u16)  ->  u16 #link_name "llvm.bswap.i16" ---;
-	byte_swap :: proc(i16)  ->  i16 #link_name "llvm.bswap.i16" ---;
-	byte_swap :: proc(u32)  ->  u32 #link_name "llvm.bswap.i32" ---;
-	byte_swap :: proc(i32)  ->  i32 #link_name "llvm.bswap.i32" ---;
-	byte_swap :: proc(u64)  ->  u64 #link_name "llvm.bswap.i64" ---;
-	byte_swap :: proc(i64)  ->  i64 #link_name "llvm.bswap.i64" ---;
-	byte_swap :: proc(u128) -> u128 #link_name "llvm.bswap.i128" ---;
-	byte_swap :: proc(i128) -> i128 #link_name "llvm.bswap.i128" ---;
+	@(link_name="llvm.bswap.i16")  byte_swap :: proc(u16)  ->  u16 ---;
+	@(link_name="llvm.bswap.i16")  byte_swap :: proc(i16)  ->  i16 ---;
+	@(link_name="llvm.bswap.i32")  byte_swap :: proc(u32)  ->  u32 ---;
+	@(link_name="llvm.bswap.i32")  byte_swap :: proc(i32)  ->  i32 ---;
+	@(link_name="llvm.bswap.i64")  byte_swap :: proc(u64)  ->  u64 ---;
+	@(link_name="llvm.bswap.i64")  byte_swap :: proc(i64)  ->  i64 ---;
+	@(link_name="llvm.bswap.i128") byte_swap :: proc(u128) -> u128 ---;
+	@(link_name="llvm.bswap.i128") byte_swap :: proc(i128) -> i128 ---;
 }
 byte_swap :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(byte_swap(u32(i))); } else { return uint(byte_swap(u64(i))); } }
 byte_swap :: proc(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(byte_swap(i32(i))); } else { return  int(byte_swap(i64(i))); } }
@@ -184,16 +184,16 @@ to_le :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else
 to_le :: proc(i:  int) ->  int { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
 
 
-overflowing_add :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core op :: proc(u8, u8)     -> (u8, bool)   #link_name "llvm.uadd.with.overflow.i8" ---;   return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core op :: proc(i8, i8)     -> (i8, bool)   #link_name "llvm.sadd.with.overflow.i8" ---;   return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core op :: proc(u16, u16)   -> (u16, bool)  #link_name "llvm.uadd.with.overflow.i16" ---;  return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core op :: proc(i16, i16)   -> (i16, bool)  #link_name "llvm.sadd.with.overflow.i16" ---;  return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core op :: proc(u32, u32)   -> (u32, bool)  #link_name "llvm.uadd.with.overflow.i32" ---;  return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core op :: proc(i32, i32)   -> (i32, bool)  #link_name "llvm.sadd.with.overflow.i32" ---;  return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core op :: proc(u64, u64)   -> (u64, bool)  #link_name "llvm.uadd.with.overflow.i64" ---;  return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core op :: proc(i64, i64)   -> (i64, bool)  #link_name "llvm.sadd.with.overflow.i64" ---;  return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core op :: proc(u128, u128) -> (u128, bool) #link_name "llvm.uadd.with.overflow.i128" ---; return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core op :: proc(i128, i128) -> (i128, bool) #link_name "llvm.sadd.with.overflow.i128" ---; return op(lhs, rhs); }
+overflowing_add :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   ---; return op(lhs, rhs); }
+overflowing_add :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   ---; return op(lhs, rhs); }
+overflowing_add :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  ---; return op(lhs, rhs); }
+overflowing_add :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  ---; return op(lhs, rhs); }
+overflowing_add :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  ---; return op(lhs, rhs); }
+overflowing_add :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  ---; return op(lhs, rhs); }
+overflowing_add :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  ---; return op(lhs, rhs); }
+overflowing_add :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  ---; return op(lhs, rhs); }
+overflowing_add :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i128") op :: proc(u128, u128) -> (u128, bool) ---; return op(lhs, rhs); }
+overflowing_add :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i128") op :: proc(i128, i128) -> (i128, bool) ---; return op(lhs, rhs); }
 overflowing_add :: proc(lhs, rhs: uint) -> (uint, bool) {
 	when size_of(uint) == size_of(u32) {
 		x, ok := overflowing_add(u32(lhs), u32(rhs));
@@ -213,16 +213,16 @@ overflowing_add :: proc(lhs, rhs: int) -> (int, bool) {
 	}
 }
 
-overflowing_sub :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core op :: proc(u8, u8)     -> (u8, bool)   #link_name "llvm.usub.with.overflow.i8" ---;   return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core op :: proc(i8, i8)     -> (i8, bool)   #link_name "llvm.ssub.with.overflow.i8" ---;   return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core op :: proc(u16, u16)   -> (u16, bool)  #link_name "llvm.usub.with.overflow.i16" ---;  return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core op :: proc(i16, i16)   -> (i16, bool)  #link_name "llvm.ssub.with.overflow.i16" ---;  return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core op :: proc(u32, u32)   -> (u32, bool)  #link_name "llvm.usub.with.overflow.i32" ---;  return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core op :: proc(i32, i32)   -> (i32, bool)  #link_name "llvm.ssub.with.overflow.i32" ---;  return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core op :: proc(u64, u64)   -> (u64, bool)  #link_name "llvm.usub.with.overflow.i64" ---;  return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core op :: proc(i64, i64)   -> (i64, bool)  #link_name "llvm.ssub.with.overflow.i64" ---;  return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core op :: proc(u128, u128) -> (u128, bool) #link_name "llvm.usub.with.overflow.i128" ---; return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core op :: proc(i128, i128) -> (i128, bool) #link_name "llvm.ssub.with.overflow.i128" ---; return op(lhs, rhs); }
+overflowing_sub :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   ---; return op(lhs, rhs); }
+overflowing_sub :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   ---; return op(lhs, rhs); }
+overflowing_sub :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  ---; return op(lhs, rhs); }
+overflowing_sub :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  ---; return op(lhs, rhs); }
+overflowing_sub :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  ---; return op(lhs, rhs); }
+overflowing_sub :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  ---; return op(lhs, rhs); }
+overflowing_sub :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  ---; return op(lhs, rhs); }
+overflowing_sub :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  ---; return op(lhs, rhs); }
+overflowing_sub :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i128") op :: proc(u128, u128) -> (u128, bool) ---; return op(lhs, rhs); }
+overflowing_sub :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i128") op :: proc(i128, i128) -> (i128, bool) ---; return op(lhs, rhs); }
 overflowing_sub :: proc(lhs, rhs: uint) -> (uint, bool) {
 	when size_of(uint) == size_of(u32) {
 		x, ok := overflowing_sub(u32(lhs), u32(rhs));
@@ -242,16 +242,16 @@ overflowing_sub :: proc(lhs, rhs: int) -> (int, bool) {
 	}
 }
 
-overflowing_mul :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core op :: proc(u8, u8)     -> (u8, bool)   #link_name "llvm.umul.with.overflow.i8" ---;   return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core op :: proc(i8, i8)     -> (i8, bool)   #link_name "llvm.smul.with.overflow.i8" ---;   return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core op :: proc(u16, u16)   -> (u16, bool)  #link_name "llvm.umul.with.overflow.i16" ---;  return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core op :: proc(i16, i16)   -> (i16, bool)  #link_name "llvm.smul.with.overflow.i16" ---;  return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core op :: proc(u32, u32)   -> (u32, bool)  #link_name "llvm.umul.with.overflow.i32" ---;  return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core op :: proc(i32, i32)   -> (i32, bool)  #link_name "llvm.smul.with.overflow.i32" ---;  return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core op :: proc(u64, u64)   -> (u64, bool)  #link_name "llvm.umul.with.overflow.i64" ---;  return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core op :: proc(i64, i64)   -> (i64, bool)  #link_name "llvm.smul.with.overflow.i64" ---;  return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core op :: proc(u128, u128) -> (u128, bool) #link_name "llvm.umul.with.overflow.i128" ---; return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core op :: proc(i128, i128) -> (i128, bool) #link_name "llvm.smul.with.overflow.i128" ---; return op(lhs, rhs); }
+overflowing_mul :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   ---; return op(lhs, rhs); }
+overflowing_mul :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   ---; return op(lhs, rhs); }
+overflowing_mul :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  ---; return op(lhs, rhs); }
+overflowing_mul :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  ---; return op(lhs, rhs); }
+overflowing_mul :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  ---; return op(lhs, rhs); }
+overflowing_mul :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  ---; return op(lhs, rhs); }
+overflowing_mul :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  ---; return op(lhs, rhs); }
+overflowing_mul :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  ---; return op(lhs, rhs); }
+overflowing_mul :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i128") op :: proc(u128, u128) -> (u128, bool) ---; return op(lhs, rhs); }
+overflowing_mul :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i128") op :: proc(i128, i128) -> (i128, bool) ---; return op(lhs, rhs); }
 overflowing_mul :: proc(lhs, rhs: uint) -> (uint, bool) {
 	when size_of(uint) == size_of(u32) {
 		x, ok := overflowing_mul(u32(lhs), u32(rhs));

+ 28 - 31
core/c.odin

@@ -1,41 +1,38 @@
 CHAR_BIT :: 8;
 
-c_bool           :: bool;
-
-c_char           :: u8;
-
-c_schar          :: i8;
-c_uchar          :: u8;
-
-c_short          :: i16;
-c_ushort         :: u16;
-
-c_int            :: i32;
-c_uint           :: u32;
-
-when ODIN_OS == "windows" || size_of(int) == 4 {
-	c_long :: i32;
+c_bool   :: #alias bool;
+c_char   :: #alias u8;
+c_byte   :: #alias u8;
+c_schar  :: #alias i8;
+c_uchar  :: #alias u8;
+c_short  :: #alias i16;
+c_ushort :: #alias u16;
+c_int    :: #alias i32;
+c_uint   :: #alias u32;
+
+when ODIN_OS == "windows" || size_of(rawptr) == 4 {
+	c_long :: #alias i32;
 } else {
-	c_long :: i64;
+	c_long :: #alias i64;
 }
 
-when ODIN_OS == "windows" || size_of(uint) == 4 {
-	c_ulong :: u32;
+when ODIN_OS == "windows" || size_of(rawptr) == 4 {
+	c_ulong :: #alias u32;
 } else {
-	c_ulong :: u64;
+	c_ulong :: #alias u64;
 }
 
-c_longlong       :: i64;
-c_ulonglong      :: u64;
-
-c_float          :: f32;
-c_double         :: f64;
+c_longlong       :: #alias i64;
+c_ulonglong      :: #alias u64;
+c_float          :: #alias f32;
+c_double         :: #alias f64;
+c_complex_float  :: #alias complex64;
+c_complex_double :: #alias complex128;
 
-c_complex_float  :: complex64;
-c_complex_double :: complex128;
+_ :: compile_assert(size_of(uintptr) == size_of(int));
 
-c_size_t         :: uint;
-c_ssize_t        :: int;
-c_ptrdiff_t      :: int;
-c_uintptr_t      :: uint;
-c_intptr_t       :: int;
+c_size_t    :: #alias uint;
+c_ssize_t   :: #alias int;
+c_ptrdiff_t :: #alias int;
+c_uintptr_t :: #alias uintptr;
+c_intptr_t  :: #alias int;

+ 2 - 2
core/fmt.odin

@@ -331,7 +331,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 
 
 _parse_int :: proc(s: string, offset: int) -> (result: int, offset: int, ok: bool) {
-	is_digit :: proc(r: rune) -> bool #inline {
+	is_digit :: inline proc(r: rune) -> bool{
 		return '0' <= r && r <= '9';
 	}
 
@@ -640,7 +640,7 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
 		fmt_bad_verb(fi, verb);
 		return;
 	}
-	u := u128(uint(p));
+	u := u128(uintptr(p));
 	if !fi.hash || verb == 'v' {
 		write_string(fi.buf, "0x");
 	}

+ 26 - 23
core/math.odin

@@ -28,31 +28,34 @@ Mat4 :: [4][4]f32;
 Complex :: complex64;
 
 foreign __llvm_core {
-	sqrt    :: proc(x: f32) -> f32        #link_name "llvm.sqrt.f32" ---;
-	sqrt    :: proc(x: f64) -> f64        #link_name "llvm.sqrt.f64" ---;
-
-	sin     :: proc(θ: f32) -> f32        #link_name "llvm.sin.f32" ---;
-	sin     :: proc(θ: f64) -> f64        #link_name "llvm.sin.f64" ---;
-
-	cos     :: proc(θ: f32) -> f32        #link_name "llvm.cos.f32" ---;
-	cos     :: proc(θ: f64) -> f64        #link_name "llvm.cos.f64" ---;
-
-	// asin     :: proc(x: f32) -> f32       #link_name "llvm.asin.f32" ---;
-	// asin     :: proc(x: f64) -> f64       #link_name "llvm.asin.f64" ---;
-
-	// acos     :: proc(x: f32) -> f32       #link_name "llvm.acos.f32" ---;
-	// acos     :: proc(x: f64) -> f64       #link_name "llvm.acos.f64" ---;
-
-
-	pow     :: proc(x, power: f32) -> f32 #link_name "llvm.pow.f32" ---;
-	pow     :: proc(x, power: f64) -> f64 #link_name "llvm.pow.f64" ---;
-
-	fmuladd :: proc(a, b, c: f32) -> f32  #link_name "llvm.fmuladd.f32" ---;
-	fmuladd :: proc(a, b, c: f64) -> f64  #link_name "llvm.fmuladd.f64" ---;
+	@(link_name="llvm.sqrt.f32")
+	sqrt :: proc(x: f32) -> f32 ---;
+	@(link_name="llvm.sqrt.f64")
+	sqrt :: proc(x: f64) -> f64 ---;
+
+	@(link_name="llvm.sin.f32")
+	sin :: proc(θ: f32) -> f32 ---;
+	@(link_name="llvm.sin.f64")
+	sin :: proc(θ: f64) -> f64 ---;
+
+	@(link_name="llvm.cos.f32")
+	cos :: proc(θ: f32) -> f32 ---;
+	@(link_name="llvm.cos.f64")
+	cos :: proc(θ: f64) -> f64 ---;
+
+	@(link_name="llvm.pow.f32")
+	pow :: proc(x, power: f32) -> f32 ---;
+	@(link_name="llvm.pow.f64")
+	pow :: proc(x, power: f64) -> f64 ---;
+
+	@(link_name="llvm.fmuladd.f32")
+	fmuladd :: proc(a, b, c: f32) -> f32 ---;
+	@(link_name="llvm.fmuladd.f64")
+	fmuladd :: proc(a, b, c: f64) -> f64 ---;
 }
 
-tan    :: proc(θ: f32) -> f32 #inline do return sin(θ)/cos(θ);
-tan    :: proc(θ: f64) -> f64 #inline do return sin(θ)/cos(θ);
+tan    :: proc(θ: f32) -> f32 do return sin(θ)/cos(θ);
+tan    :: proc(θ: f64) -> f64 do return sin(θ)/cos(θ);
 
 lerp   :: proc(a, b: $T, t: $E) -> (x: T) do return a*(1-t) + b*t;
 

+ 12 - 12
core/mem.odin

@@ -1,9 +1,9 @@
 import "core:raw.odin"
 
 foreign __llvm_core {
-	swap :: proc(b: u16) -> u16 #link_name "llvm.bswap.i16" ---;
-	swap :: proc(b: u32) -> u32 #link_name "llvm.bswap.i32" ---;
-	swap :: proc(b: u64) -> u64 #link_name "llvm.bswap.i64" ---;
+	@(link_name = "llvm.bswap.i16") swap :: proc(b: u16) -> u16  ---;
+	@(link_name = "llvm.bswap.i32") swap :: proc(b: u32) -> u32  ---;
+	@(link_name = "llvm.bswap.i64") swap :: proc(b: u64) -> u64  ---;
 }
 
 set :: proc(data: rawptr, value: i32, len: int) -> rawptr #cc_contextless {
@@ -42,21 +42,21 @@ slice_to_bytes :: proc(slice: []$T) -> []u8 #cc_contextless {
 }
 
 
-kilobytes :: proc(x: int) -> int #inline #cc_contextless { return          (x) * 1024; }
-megabytes :: proc(x: int) -> int #inline #cc_contextless { return kilobytes(x) * 1024; }
-gigabytes :: proc(x: int) -> int #inline #cc_contextless { return megabytes(x) * 1024; }
-terabytes :: proc(x: int) -> int #inline #cc_contextless { return gigabytes(x) * 1024; }
+kilobytes :: inline proc(x: int) -> int #cc_contextless do return          (x) * 1024;
+megabytes :: inline proc(x: int) -> int #cc_contextless do return kilobytes(x) * 1024;
+gigabytes :: inline proc(x: int) -> int #cc_contextless do return megabytes(x) * 1024;
+terabytes :: inline proc(x: int) -> int #cc_contextless do return gigabytes(x) * 1024;
 
-is_power_of_two :: proc(x: int) -> bool {
+is_power_of_two :: proc(x: uintptr) -> bool {
 	if x <= 0 do return false;
 	return (x & (x-1)) == 0;
 }
 
-align_forward :: proc(ptr: rawptr, align: int) -> rawptr {
+align_forward :: proc(ptr: rawptr, align: uintptr) -> rawptr {
 	assert(is_power_of_two(align));
 
-	a := uint(align);
-	p := uint(ptr);
+	a := uintptr(align);
+	p := uintptr(ptr);
 	modulo := p & (a-1);
 	if modulo != 0 do p += a - modulo;
 	return rawptr(p);
@@ -150,7 +150,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 
 		#no_bounds_check end := &arena.memory[len(arena.memory)];
 
-		ptr := align_forward(end, alignment);
+		ptr := align_forward(end, uintptr(alignment));
 		(^raw.Slice)(&arena.memory).len += total_size;
 		return zero(ptr, size);
 

+ 27 - 27
core/opengl.odin

@@ -11,35 +11,35 @@ export "core:opengl_constants.odin"
 _ := compile_assert(ODIN_OS != "osx");
 
 foreign lib {
-	Clear          :: proc(mask: u32)                                #link_name "glClear"         ---;
-	ClearColor     :: proc(r, g, b, a: f32)                          #link_name "glClearColor"    ---;
-	Begin          :: proc(mode: i32)                                #link_name "glBegin"         ---;
-	End            :: proc()                                         #link_name "glEnd"           ---;
-	Finish         :: proc()                                         #link_name "glFinish"        ---;
-	BlendFunc      :: proc(sfactor, dfactor: i32)                    #link_name "glBlendFunc"     ---;
-	Enable         :: proc(cap: i32)                                 #link_name "glEnable"        ---;
-	Disable        :: proc(cap: i32)                                 #link_name "glDisable"       ---;
-	GenTextures    :: proc(count: i32, result: ^u32)                 #link_name "glGenTextures"   ---;
-	DeleteTextures :: proc(count: i32, result: ^u32)                 #link_name "glDeleteTextures"---;
-	TexParameteri  :: proc(target, pname, param: i32)                #link_name "glTexParameteri" ---;
-	TexParameterf  :: proc(target: i32, pname: i32, param: f32)      #link_name "glTexParameterf" ---;
-	BindTexture    :: proc(target: i32, texture: u32)                #link_name "glBindTexture"   ---;
-	LoadIdentity   :: proc()                                         #link_name "glLoadIdentity"  ---;
-	Viewport       :: proc(x, y, width, height: i32)                 #link_name "glViewport"      ---;
-	Ortho          :: proc(left, right, bottom, top, near, far: f64) #link_name "glOrtho"         ---;
-	Color3f        :: proc(r, g, b: f32)                             #link_name "glColor3f"       ---;
-	Vertex3f       :: proc(x, y, z: f32)                             #link_name "glVertex3f"      ---;
-	GetError       :: proc() -> i32                                  #link_name "glGetError"      ---;
-	GetString      :: proc(name: i32) -> ^u8                         #link_name "glGetString"     ---;
-	GetIntegerv    :: proc(name: i32, v: ^i32)                       #link_name "glGetIntegerv"   ---;
-	TexCoord2f     :: proc(x, y: f32)                                #link_name "glTexCoord2f"    ---;
-	TexImage2D     :: proc(target, level, internal_format,
-	                       width, height, border,
-	                       format, type_: i32, pixels: rawptr)       #link_name "glTexImage2D"    ---;
+	@(link_name="glClear")          Clear          :: proc(mask: u32) ---;
+	@(link_name="glClearColor")     ClearColor     :: proc(r, g, b, a: f32) ---;
+	@(link_name="glBegin")          Begin          :: proc(mode: i32) ---;
+	@(link_name="glEnd")            End            :: proc() ---;
+	@(link_name="glFinish")         Finish         :: proc() ---;
+	@(link_name="glBlendFunc")      BlendFunc      :: proc(sfactor, dfactor: i32) ---;
+	@(link_name="glEnable")         Enable         :: proc(cap: i32) ---;
+	@(link_name="glDisable")        Disable        :: proc(cap: i32) ---;
+	@(link_name="glGenTextures")    GenTextures    :: proc(count: i32, result: ^u32) ---;
+	@(link_name="glDeleteTextures") DeleteTextures :: proc(count: i32, result: ^u32) ---;
+	@(link_name="glTexParameteri")  TexParameteri  :: proc(target, pname, param: i32) ---;
+	@(link_name="glTexParameterf")  TexParameterf  :: proc(target: i32, pname: i32, param: f32) ---;
+	@(link_name="glBindTexture")    BindTexture    :: proc(target: i32, texture: u32) ---;
+	@(link_name="glLoadIdentity")   LoadIdentity   :: proc() ---;
+	@(link_name="glViewport")       Viewport       :: proc(x, y, width, height: i32) ---;
+	@(link_name="glOrtho")          Ortho          :: proc(left, right, bottom, top, near, far: f64) ---;
+	@(link_name="glColor3f")        Color3f        :: proc(r, g, b: f32) ---;
+	@(link_name="glVertex3f")       Vertex3f       :: proc(x, y, z: f32) ---;
+	@(link_name="glGetError")       GetError       :: proc() -> i32 ---;
+	@(link_name="glGetString")      GetString      :: proc(name: i32) -> ^u8 ---;
+	@(link_name="glGetIntegerv")    GetIntegerv    :: proc(name: i32, v: ^i32) ---;
+	@(link_name="glTexCoord2f")     TexCoord2f     :: proc(x, y: f32) ---;
+	@(link_name="glTexImage2D")     TexImage2D     :: proc(target, level, internal_format,
+	                                                       width, height, border,
+	                                                       format, type_: i32, pixels: rawptr) ---;
 }
 
 
-_string_data :: proc(s: string) -> ^u8 #inline { return &s[0]; }
+_string_data :: inline proc(s: string) -> ^u8 do return &s[0];
 
 _libgl := win32.load_library_a(_string_data("opengl32.dll\x00"));
 
@@ -119,7 +119,7 @@ get_proc_address :: proc(name: string) -> rawptr {
 
 
 init :: proc() {
-	set_proc_address :: proc(p: rawptr, name: string) #inline {
+	set_proc_address :: proc(p: rawptr, name: string) {
 		x := cast(^rawptr)p;
 		x^ = get_proc_address(name);
 	}

+ 32 - 32
core/os_linux.odin

@@ -108,13 +108,13 @@ S_ISGID :: 0002000; // Set group id on execution
 S_ISVTX :: 0001000; // Directory restrcted delete
 
 
-S_ISLNK  :: proc(m: u32) -> bool #inline  {return (m & S_IFMT) == S_IFLNK; }
-S_ISREG  :: proc(m: u32) -> bool #inline  {return (m & S_IFMT) == S_IFREG; }
-S_ISDIR  :: proc(m: u32) -> bool #inline  {return (m & S_IFMT) == S_IFDIR; }
-S_ISCHR  :: proc(m: u32) -> bool #inline  {return (m & S_IFMT) == S_IFCHR; }
-S_ISBLK  :: proc(m: u32) -> bool #inline  {return (m & S_IFMT) == S_IFBLK; }
-S_ISFIFO :: proc(m: u32) -> bool #inline  {return (m & S_IFMT) == S_IFIFO; }
-S_ISSOCK :: proc(m: u32) -> bool #inline  {return (m & S_IFMT) == S_IFSOCK;}
+S_ISLNK  :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFLNK;
+S_ISREG  :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFREG;
+S_ISDIR  :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFDIR;
+S_ISCHR  :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFCHR;
+S_ISBLK  :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFBLK;
+S_ISFIFO :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFIFO;
+S_ISSOCK :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFSOCK;
 
 F_OK :: 0; // Test for file existance
 X_OK :: 1; // Test for execute permission
@@ -122,28 +122,28 @@ W_OK :: 2; // Test for write permission
 R_OK :: 4; // Test for read permission
 
 foreign libc {
-	_unix_open    :: proc(path: ^u8, mode: int) -> Handle              #link_name "open"    ---;
-	_unix_close   :: proc(fd: Handle) -> i32                           #link_name "close"   ---;
-	_unix_read    :: proc(fd: Handle, buf: rawptr, size: int) -> int   #link_name "read"    ---;
-	_unix_write   :: proc(fd: Handle, buf: rawptr, size: int) -> int   #link_name "write"   ---;
-	_unix_seek    :: proc(fd: Handle, offset: i64, whence: i32) -> i64 #link_name "lseek64" ---;
-	_unix_gettid  :: proc() -> u64                                     #link_name "gettid"  ---;
-	_unix_stat    :: proc(path: ^u8, stat: ^Stat) -> i32               #link_name "stat"    ---;
-	_unix_access  :: proc(path: ^u8, mask: int) -> i32                 #link_name "access"  ---;
-
-	_unix_malloc  :: proc(size: int) -> rawptr                         #link_name "malloc"  ---;
-	_unix_calloc  :: proc(num, size: int) -> rawptr                    #link_name "calloc"  ---;
-	_unix_free    :: proc(ptr: rawptr)                                 #link_name "free"    ---;
-	_unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr            #link_name "realloc" ---;
-	_unix_getenv  :: proc(^u8) -> ^u8                                  #link_name "getenv"  ---;
-
-	_unix_exit    :: proc(status: int)                                 #link_name "exit"    ---;
+	@(link_name="open")    _unix_open    :: proc(path: ^u8, mode: int) -> Handle ---;
+	@(link_name="close")   _unix_close   :: proc(fd: Handle) -> i32 ---;
+	@(link_name="read")    _unix_read    :: proc(fd: Handle, buf: rawptr, size: int) -> int ---;
+	@(link_name="write")   _unix_write   :: proc(fd: Handle, buf: rawptr, size: int) -> int ---;
+	@(link_name="lseek64") _unix_seek    :: proc(fd: Handle, offset: i64, whence: i32) -> i64 ---;
+	@(link_name="gettid")  _unix_gettid  :: proc() -> u64 ---;
+	@(link_name="stat")    _unix_stat    :: proc(path: ^u8, stat: ^Stat) -> i32 ---;
+	@(link_name="access")  _unix_access  :: proc(path: ^u8, mask: int) -> i32 ---;
+
+	@(link_name="malloc")  _unix_malloc  :: proc(size: int) -> rawptr ---;
+	@(link_name="calloc")  _unix_calloc  :: proc(num, size: int) -> rawptr ---;
+	@(link_name="free")    _unix_free    :: proc(ptr: rawptr) ---;
+	@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr ---;
+	@(link_name="getenv")  _unix_getenv  :: proc(^u8) -> ^u8 ---;
+
+	@(link_name="exit")    _unix_exit    :: proc(status: int) ---;
 }
 foreign dl {
-	_unix_dlopen  :: proc(filename: ^u8, flags: int) -> rawptr            #link_name "dlopen"  ---;
-	_unix_dlsym   :: proc(handle: rawptr, symbol: ^u8) ->  (proc() #cc_c) #link_name "dlsym"   ---;
-	_unix_dlclose :: proc(handle: rawptr) -> int                          #link_name "dlclose" ---;
-	_unix_dlerror :: proc() -> ^u8                                        #link_name "dlerror" ---;
+	@(link_name="dlopen")  _unix_dlopen  :: proc(filename: ^u8, flags: int) -> rawptr ---;
+	@(link_name="dlsym")   _unix_dlsym   :: proc(handle: rawptr, symbol: ^u8) -> rawptr ---;
+	@(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> int ---;
+	@(link_name="dlerror") _unix_dlerror :: proc() -> ^u8 ---;
 }
 
 // TODO(zangent): Change this to just `open` when Bill fixes overloading.
@@ -200,7 +200,7 @@ last_write_time :: proc(fd: Handle) -> File_Time {}
 last_write_time_by_name :: proc(name: string) -> File_Time {}
 */
 
-stat :: proc(path: string) -> (Stat, int) #inline {
+stat :: inline proc(path: string) -> (Stat, int) {
 	s: Stat;
 	cstr := strings.new_c_string(path);
 	defer free(cstr);
@@ -208,7 +208,7 @@ stat :: proc(path: string) -> (Stat, int) #inline {
 	return s, int(ret_int);
 }
 
-access :: proc(path: string, mask: int) -> bool #inline {
+access :: inline proc(path: string, mask: int) -> bool {
 	cstr := strings.new_c_string(path);
 	defer free(cstr);
 	return _unix_access(cstr, mask) == 0;
@@ -246,20 +246,20 @@ current_thread_id :: proc() -> int {
 	return 0;
 }
 
-dlopen :: proc(filename: string, flags: int) -> rawptr #inline {
+dlopen :: inline proc(filename: string, flags: int) -> rawptr {
 	cstr := strings.new_c_string(filename);
 	handle := _unix_dlopen(cstr, flags);
 	free(cstr);
 	return handle;
 }
-dlsym :: proc(handle: rawptr, symbol: string) -> (proc() #cc_c) #inline {
+dlsym :: inline proc(handle: rawptr, symbol: string) -> (proc() #cc_c) {
 	assert(handle != nil);
 	cstr := strings.new_c_string(symbol);
 	proc_handle := _unix_dlsym(handle, cstr);
 	free(cstr);
 	return proc_handle;
 }
-dlclose :: proc(handle: rawptr) -> bool #inline {
+dlclose :: inline proc(handle: rawptr) -> bool {
 	assert(handle != nil);
 	return _unix_dlclose(handle) == 0;
 }

+ 2 - 2
core/os_windows.odin

@@ -1,11 +1,11 @@
 import win32 "core:sys/windows.odin"
 import "core:mem.odin"
 
-Handle    :: int;
+Handle    :: uintptr;
 File_Time :: u64;
 
 
-INVALID_HANDLE: Handle : -1;
+INVALID_HANDLE :: ~Handle(0);
 
 
 

+ 36 - 36
core/os_x.odin

@@ -108,13 +108,13 @@ S_ISUID :: 0004000; // Set user id on execution
 S_ISGID :: 0002000; // Set group id on execution
 S_ISVTX :: 0001000; // Directory restrcted delete
 
-S_ISLNK  :: proc(m: u32) -> bool #inline do return (m & S_IFMT) == S_IFLNK;
-S_ISREG  :: proc(m: u32) -> bool #inline do return (m & S_IFMT) == S_IFREG;
-S_ISDIR  :: proc(m: u32) -> bool #inline do return (m & S_IFMT) == S_IFDIR;
-S_ISCHR  :: proc(m: u32) -> bool #inline do return (m & S_IFMT) == S_IFCHR;
-S_ISBLK  :: proc(m: u32) -> bool #inline do return (m & S_IFMT) == S_IFBLK;
-S_ISFIFO :: proc(m: u32) -> bool #inline do return (m & S_IFMT) == S_IFIFO;
-S_ISSOCK :: proc(m: u32) -> bool #inline do return (m & S_IFMT) == S_IFSOCK;
+S_ISLNK  :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFLNK;
+S_ISREG  :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFREG;
+S_ISDIR  :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFDIR;
+S_ISCHR  :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFCHR;
+S_ISBLK  :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFBLK;
+S_ISFIFO :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFIFO;
+S_ISSOCK :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFSOCK;
 
 R_OK :: 4; // Test for read permission
 W_OK :: 2; // Test for write permission
@@ -122,29 +122,29 @@ X_OK :: 1; // Test for execute permission
 F_OK :: 0; // Test for file existance
 
 foreign libc {
-	_unix_open    :: proc(path: ^u8, mode: int) -> Handle                    #link_name "open"    ---;
-	_unix_close   :: proc(handle: Handle)                                    #link_name "close"   ---;
-	_unix_read    :: proc(handle: Handle, buffer: rawptr, count: int) -> int #link_name "read"    ---;
-	_unix_write   :: proc(handle: Handle, buffer: rawptr, count: int) -> int #link_name "write"   ---;
-	_unix_lseek   :: proc(fs: Handle, offset: int, whence: int) -> int       #link_name "lseek"   ---;
-	_unix_gettid  :: proc() -> u64                                           #link_name "gettid"  ---;
-	_unix_stat    :: proc(path: ^u8, stat: ^Stat) -> int                     #link_name "stat"    ---;
-	_unix_access  :: proc(path: ^u8, mask: int) -> int                       #link_name "access"  ---;
-
-	_unix_malloc  :: proc(size: int) -> rawptr                               #link_name "malloc"  ---;
-	_unix_calloc  :: proc(num, size: int) -> rawptr                          #link_name "calloc"  ---;
-	_unix_free    :: proc(ptr: rawptr)                                       #link_name "free"    ---;
-	_unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr                  #link_name "realloc" ---;
-	_unix_getenv  :: proc(^u8) -> ^u8                                        #link_name "getenv"  ---;
-
-	_unix_exit    :: proc(status: int)                                       #link_name "exit"    ---;
+	@(link_name="open")    _unix_open    :: proc(path: ^u8, mode: int) -> Handle ---;
+	@(link_name="close")   _unix_close   :: proc(handle: Handle) ---;
+	@(link_name="read")    _unix_read    :: proc(handle: Handle, buffer: rawptr, count: int) -> int ---;
+	@(link_name="write")   _unix_write   :: proc(handle: Handle, buffer: rawptr, count: int) -> int ---;
+	@(link_name="lseek")   _unix_lseek   :: proc(fs: Handle, offset: int, whence: int) -> int ---;
+	@(link_name="gettid")  _unix_gettid  :: proc() -> u64 ---;
+	@(link_name="stat")    _unix_stat    :: proc(path: ^u8, stat: ^Stat) -> int ---;
+	@(link_name="access")  _unix_access  :: proc(path: ^u8, mask: int) -> int ---;
+
+	@(link_name="malloc")  _unix_malloc  :: proc(size: int) -> rawptr ---;
+	@(link_name="calloc")  _unix_calloc  :: proc(num, size: int) -> rawptr ---;
+	@(link_name="free")    _unix_free    :: proc(ptr: rawptr) ---;
+	@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr ---;
+	@(link_name="getenv")  _unix_getenv  :: proc(^u8) -> ^u8 ---;
+
+	@(link_name="exit")    _unix_exit    :: proc(status: int) ---;
 }
 
 foreign dl {
-	_unix_dlopen  :: proc(filename: ^u8, flags: int) -> rawptr               #link_name "dlopen"  ---;
-	_unix_dlsym   :: proc(handle: rawptr, symbol: ^u8) ->  (proc() #cc_c)    #link_name "dlsym"   ---;
-	_unix_dlclose :: proc(handle: rawptr) -> int                             #link_name "dlclose" ---;
-	_unix_dlerror :: proc() -> ^u8                                           #link_name "dlerror" ---;
+	@(link_name="dlopen")  _unix_dlopen  :: proc(filename: ^u8, flags: int) -> rawptr ---;
+	@(link_name="dlsym")   _unix_dlsym   :: proc(handle: rawptr, symbol: ^u8) ->  (proc() #cc_c) ---;
+	@(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> int ---;
+	@(link_name="dlerror") _unix_dlerror :: proc() -> ^u8 ---;
 }
 
 // TODO(zangent): Change this to just `open` when Bill fixes overloading.
@@ -217,7 +217,7 @@ last_write_time :: proc(fd: Handle) -> File_Time {}
 last_write_time_by_name :: proc(name: string) -> File_Time {}
 */
 
-stat :: proc(path: string) -> (Stat, bool) #inline {
+stat :: inline proc(path: string) -> (Stat, bool) {
 	s: Stat;
 	cstr := strings.new_c_string(path);
 	defer free(cstr);
@@ -225,20 +225,20 @@ stat :: proc(path: string) -> (Stat, bool) #inline {
 	return s, ret_int==0;
 }
 
-access :: proc(path: string, mask: int) -> bool #inline {
+access :: inline proc(path: string, mask: int) -> bool {
 	cstr := strings.new_c_string(path);
 	defer free(cstr);
 	return _unix_access(cstr, mask) == 0;
 }
 
-heap_alloc :: proc(size: int) -> rawptr #inline {
+heap_alloc :: inline proc(size: int) -> rawptr {
 	assert(size > 0);
 	return _unix_calloc(1, size);
 }
-heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr #inline {
+heap_resize :: inline proc(ptr: rawptr, new_size: int) -> rawptr {
 	return _unix_realloc(ptr, new_size);
 }
-heap_free :: proc(ptr: rawptr) #inline {
+heap_free :: inline proc(ptr: rawptr) {
 	_unix_free(ptr);
 }
 
@@ -252,7 +252,7 @@ getenv :: proc(name: string) -> (string, bool) {
 	return strings.to_odin_string(cstr), true;
 }
 
-exit :: proc(code: int) #inline {
+exit :: inline proc(code: int) {
 	_unix_exit(code);
 }
 
@@ -262,20 +262,20 @@ current_thread_id :: proc() -> int {
 	return 0;
 }
 
-dlopen :: proc(filename: string, flags: int) -> rawptr #inline {
+dlopen :: inline proc(filename: string, flags: int) -> rawptr {
 	cstr := strings.new_c_string(filename);
 	handle := _unix_dlopen(cstr, flags);
 	free(cstr);
 	return handle;
 }
-dlsym :: proc(handle: rawptr, symbol: string) -> (proc() #cc_c) #inline {
+dlsym :: inline proc(handle: rawptr, symbol: string) -> (proc() #cc_c) {
 	assert(handle != nil);
 	cstr := strings.new_c_string(symbol);
 	proc_handle := _unix_dlsym(handle, cstr);
 	free(cstr);
 	return proc_handle;
 }
-dlclose :: proc(handle: rawptr) -> bool #inline {
+dlclose :: inline proc(handle: rawptr) -> bool {
 	assert(handle != nil);
 	return _unix_dlclose(handle) == 0;
 }

+ 1 - 1
core/sync_linux.odin

@@ -28,7 +28,7 @@ semaphore_post :: proc(s: ^Semaphore, count: int) {
 	// win32.ReleaseSemaphore(s._handle, cast(i32)count, nil);
 }
 
-semaphore_release :: proc(s: ^Semaphore) #inline {
+semaphore_release :: inline proc(s: ^Semaphore) {
 	semaphore_post(s, 1);
 }
 

+ 3 - 1
core/sync_windows.odin

@@ -36,7 +36,9 @@ semaphore_post :: proc(s: ^Semaphore, count: int) {
 	win32.release_semaphore(s._handle, i32(count), nil);
 }
 
-semaphore_release :: proc(s: ^Semaphore) #inline { semaphore_post(s, 1); }
+semaphore_release :: inline proc(s: ^Semaphore) {
+	semaphore_post(s, 1);
+}
 
 semaphore_wait :: proc(s: ^Semaphore) {
 	win32.wait_for_single_object(s._handle, win32.INFINITE);

+ 47 - 16
core/sys/wgl.odin

@@ -66,20 +66,51 @@ Get_Extensions_String_ARB_Type  :: #type proc(Hdc) -> ^u8 #cc_c;
 
 
 foreign opengl32 {
-	create_context            :: proc(hdc: Hdc) -> Hglrc                                                                                                 #link_name "wglCreateContext"          ---;
-	make_current              :: proc(hdc: Hdc, hglrc: Hglrc) -> Bool                                                                                    #link_name "wglMakeCurrent"            ---;
-	get_proc_address          :: proc(c_str: ^u8) -> rawptr                                                                                              #link_name "wglGetProcAddress"         ---;
-	delete_context            :: proc(hglrc: Hglrc) -> Bool                                                                                              #link_name "wglDeleteContext"          ---;
-	copy_context              :: proc(src, dst: Hglrc, mask: u32) -> Bool                                                                                #link_name "wglCopyContext"            ---;
-	create_layer_context      :: proc(hdc: Hdc, layer_plane: i32) -> Hglrc                                                                               #link_name "wglCreateLayerContext"     ---;
-	describe_layer_plane      :: proc(hdc: Hdc, pixel_format, layer_plane: i32, bytes: u32, pd: ^Layer_Plane_Descriptor) -> Bool                         #link_name "wglDescribeLayerPlane"     ---;
-	get_current_context       :: proc() -> Hglrc                                                                                                         #link_name "wglGetCurrentContext"      ---;
-	get_current_dc            :: proc() -> Hdc                                                                                                           #link_name "wglGetCurrentDC"           ---;
-	get_layer_palette_entries :: proc(hdc: Hdc, layer_plane, start, entries: i32, cr: ^Color_Ref) -> i32                                                 #link_name "wglGetLayerPaletteEntries" ---;
-	realize_layer_palette     :: proc(hdc: Hdc, layer_plane: i32, realize: Bool) -> Bool                                                                 #link_name "wglRealizeLayerPalette"    ---;
-	set_layer_palette_entries :: proc(hdc: Hdc, layer_plane, start, entries: i32, cr: ^Color_Ref) -> i32                                                 #link_name "wglSetLayerPaletteEntries" ---;
-	share_lists               :: proc(hglrc1, hglrc2: Hglrc) -> Bool                                                                                     #link_name "wglShareLists"             ---;
-	swap_layer_buffers        :: proc(hdc: Hdc, planes: u32) -> Bool                                                                                     #link_name "wglSwapLayerBuffers"       ---;
-	use_font_bitmaps          :: proc(hdc: Hdc, first, count, list_base: u32) -> Bool                                                                    #link_name "wglUseFontBitmaps"         ---;
-	use_font_outlines         :: proc(hdc: Hdc, first, count, list_base: u32, deviation, extrusion: f32, format: i32, gmf: ^Glyph_Metrics_Float) -> Bool #link_name "wglUseFontOutlines"        ---;
+	@(link_name="wglCreateContext")
+	create_context :: proc(hdc: Hdc) -> Hglrc ---;
+
+	@(link_name="wglMakeCurrent")
+	make_current :: proc(hdc: Hdc, hglrc: Hglrc) -> Bool ---;
+
+	@(link_name="wglGetProcAddress")
+	get_proc_address :: proc(c_str: ^u8) -> rawptr ---;
+
+	@(link_name="wglDeleteContext")
+	delete_context :: proc(hglrc: Hglrc) -> Bool ---;
+
+	@(link_name="wglCopyContext")
+	copy_context :: proc(src, dst: Hglrc, mask: u32) -> Bool ---;
+
+	@(link_name="wglCreateLayerContext")
+	create_layer_context :: proc(hdc: Hdc, layer_plane: i32) -> Hglrc ---;
+
+	@(link_name="wglDescribeLayerPlane")
+	describe_layer_plane :: proc(hdc: Hdc, pixel_format, layer_plane: i32, bytes: u32, pd: ^Layer_Plane_Descriptor) -> Bool ---;
+
+	@(link_name="wglGetCurrentContext")
+	get_current_context :: proc() -> Hglrc ---;
+
+	@(link_name="wglGetCurrentDC")
+	get_current_dc :: proc() -> Hdc ---;
+
+	@(link_name="wglGetLayerPaletteEntries")
+	get_layer_palette_entries :: proc(hdc: Hdc, layer_plane, start, entries: i32, cr: ^Color_Ref) -> i32 ---;
+
+	@(link_name="wglRealizeLayerPalette")
+	realize_layer_palette :: proc(hdc: Hdc, layer_plane: i32, realize: Bool) -> Bool ---;
+
+	@(link_name="wglSetLayerPaletteEntries")
+	set_layer_palette_entries :: proc(hdc: Hdc, layer_plane, start, entries: i32, cr: ^Color_Ref) -> i32 ---;
+
+	@(link_name="wglShareLists")
+	share_lists :: proc(hglrc1, hglrc2: Hglrc) -> Bool ---;
+
+	@(link_name="wglSwapLayerBuffers")
+	swap_layer_buffers :: proc(hdc: Hdc, planes: u32) -> Bool ---;
+
+	@(link_name="wglUseFontBitmaps")
+	use_font_bitmaps :: proc(hdc: Hdc, first, count, list_base: u32) -> Bool ---;
+
+	@(link_name="wglUseFontOutlines")
+	use_font_outlines :: proc(hdc: Hdc, first, count, list_base: u32, deviation, extrusion: f32, format: i32, gmf: ^Glyph_Metrics_Float) -> Bool ---;
 }

+ 177 - 170
core/sys/windows.odin

@@ -22,7 +22,7 @@ HKL       :: Handle;
 Wparam    :: uint;
 Lparam    :: int;
 Lresult   :: int;
-Wnd_Proc  :: proc(Hwnd, u32, Wparam, Lparam) -> Lresult #cc_c;
+Wnd_Proc  :: #type proc(Hwnd, u32, Wparam, Lparam) -> Lresult #cc_c;
 
 Long_Ptr :: int;
 
@@ -246,7 +246,7 @@ MAPVK_VSC_TO_VK_EX :: 3;
 
 
 
-INVALID_HANDLE :: Handle(~int(0));
+INVALID_HANDLE :: Handle(~uintptr(0));
 
 CREATE_SUSPENDED                  :: 0x00000004;
 STACK_SIZE_PARAM_IS_A_RESERVATION :: 0x00010000;
@@ -317,7 +317,7 @@ SM_CYSCREEN :: 1;
 
 SW_SHOW :: 5;
 
-COLOR_BACKGROUND :: Hbrush(int(1));
+COLOR_BACKGROUND :: Hbrush(uintptr(1));
 
 INVALID_SET_FILE_POINTER :: ~u32(0);
 HEAP_ZERO_MEMORY         :: 0x00000008;
@@ -328,7 +328,7 @@ GWLP_ID                  :: -12;
 GWL_STYLE                :: -16;
 GWLP_USERDATA            :: -21;
 GWLP_WNDPROC             :: -4;
-Hwnd_TOP                 :: Hwnd(uint(0));
+Hwnd_TOP                 :: Hwnd(uintptr(0));
 
 BI_RGB         :: 0;
 DIB_RGB_COLORS :: 0x00;
@@ -433,210 +433,217 @@ GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1;
 
 
 foreign kernel32 {
-	get_last_error              :: proc() -> i32                                                                               #cc_std #link_name "GetLastError"                 ---;
-	exit_process                :: proc(exit_code: u32)                                                                        #cc_std #link_name "ExitProcess"                  ---;
-	get_module_handle_a         :: proc(module_name: ^u8) -> Hinstance                                                         #cc_std #link_name "GetModuleHandleA"             ---;
-	get_module_handle_w         :: proc(module_name: ^u16) -> Hinstance                                                        #cc_std #link_name "GetModuleHandleW"             ---;
-	sleep                       :: proc(ms: i32) -> i32                                                                        #cc_std #link_name "Sleep"                        ---;
-	query_performance_frequency :: proc(result: ^i64) -> i32                                                                   #cc_std #link_name "QueryPerformanceFrequency"    ---;
-	query_performance_counter   :: proc(result: ^i64) -> i32                                                                   #cc_std #link_name "QueryPerformanceCounter"      ---;
-	output_debug_string_a       :: proc(c_str: ^u8)                                                                            #cc_std #link_name "OutputDebugStringA"           ---;
-
-	get_command_line_a    :: proc() -> ^u8                                                                                     #cc_std #link_name "GetCommandLineA"              ---;
-	get_command_line_w    :: proc() -> ^u16                                                                                    #cc_std #link_name "GetCommandLineW"              ---;
-	get_system_metrics    :: proc(index: i32) -> i32                                                                           #cc_std #link_name "GetSystemMetrics"             ---;
-	get_current_thread_id :: proc() -> u32                                                                                     #cc_std #link_name "GetCurrentThreadId"           ---;
-
-	get_system_time_as_file_time :: proc(system_time_as_file_time: ^Filetime)                                                  #cc_std #link_name "GetSystemTimeAsFileTime"      ---;
-	file_time_to_local_file_time :: proc(file_time: ^Filetime, local_file_time: ^Filetime) -> Bool                             #cc_std #link_name "FileTimeToLocalFileTime"      ---;
-	file_time_to_system_time     :: proc(file_time: ^Filetime, system_time: ^Systemtime) -> Bool                               #cc_std #link_name "FileTimeToSystemTime"         ---;
-	system_time_to_file_time     :: proc(system_time: ^Systemtime, file_time: ^Filetime) -> Bool                               #cc_std #link_name "SystemTimeToFileTime"         ---;
-
-	close_handle   :: proc(h: Handle) -> i32                                                                                   #cc_std #link_name "CloseHandle"                  ---;
-	get_std_handle :: proc(h: i32) -> Handle                                                                                   #cc_std #link_name "GetStdHandle"                 ---;
-	create_file_a  :: proc(filename: ^u8, desired_access, share_mode: u32,
-		                   security: rawptr,
-		                   creation, flags_and_attribs: u32, template_file: Handle) -> Handle                                  #cc_std #link_name "CreateFileA"                  ---;
-	read_file  :: proc(h: Handle, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> Bool                     #cc_std #link_name "ReadFile"                     ---;
-	write_file :: proc(h: Handle, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> Bool                     #cc_std #link_name "WriteFile"                    ---;
-
-	get_file_size_ex               :: proc(file_handle: Handle, file_size: ^i64) -> Bool                                       #cc_std #link_name "GetFileSizeEx"                ---;
-	get_file_attributes_a          :: proc(filename: ^u8) -> u32                                                               #cc_std #link_name "GetFileAttributesA"           ---;
-	get_file_attributes_ex_a       :: proc(filename: ^u8, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool    #cc_std #link_name "GetFileAttributesExA"         ---;
-	get_file_information_by_handle :: proc(file_handle: Handle, file_info: ^By_Handle_File_Information) -> Bool                #cc_std #link_name "GetFileInformationByHandle"   ---;
-
-	get_file_type    :: proc(file_handle: Handle) -> u32                                                                       #cc_std #link_name "GetFileType"                  ---;
-	set_file_pointer :: proc(file_handle: Handle, distance_to_move: i32, distance_to_move_high: ^i32, move_method: u32) -> u32 #cc_std #link_name "SetFilePointer"               ---;
-
-	set_handle_information :: proc(obj: Handle, mask, flags: u32) -> Bool                                                      #cc_std #link_name "SetHandleInformation"         ---;
-
-	find_first_file_a :: proc(file_name : ^u8, data : ^Find_Data) -> Handle                                                    #cc_std #link_name "FindFirstFileA"               ---;
-	find_next_file_a  :: proc(file : Handle, data : ^Find_Data) -> Bool                                                        #cc_std #link_name "FindNextFileA"                ---;
-	find_close        :: proc(file : Handle) -> Bool                                                                           #cc_std #link_name "FindClose"                    ---;
-
-
-	heap_alloc       :: proc(h: Handle, flags: u32, bytes: int) -> rawptr                                                      #cc_std #link_name "HeapAlloc"                    ---;
-	heap_realloc     :: proc(h: Handle, flags: u32, memory: rawptr, bytes: int) -> rawptr                                      #cc_std #link_name "HeapReAlloc"                  ---;
-	heap_free        :: proc(h: Handle, flags: u32, memory: rawptr) -> Bool                                                    #cc_std #link_name "HeapFree"                     ---;
-	get_process_heap :: proc() -> Handle                                                                                       #cc_std #link_name "GetProcessHeap"               ---;
-
-
-	create_semaphore_a     :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: ^u8) -> Handle   #cc_std #link_name "CreateSemaphoreA"             ---;
-	release_semaphore      :: proc(semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool                        #cc_std #link_name "ReleaseSemaphore"             ---;
-	wait_for_single_object :: proc(handle: Handle, milliseconds: u32) -> u32                                                   #cc_std #link_name "WaitForSingleObject"          ---;
-
-
-	interlocked_compare_exchange :: proc(dst: ^i32, exchange, comparand: i32) -> i32                                           #cc_c   #link_name "InterlockedCompareExchange"   ---;
-	interlocked_exchange         :: proc(dst: ^i32, desired: i32) -> i32                                                       #cc_c   #link_name "InterlockedExchange"          ---;
-	interlocked_exchange_add     :: proc(dst: ^i32, desired: i32) -> i32                                                       #cc_c   #link_name "InterlockedExchangeAdd"       ---;
-	interlocked_and              :: proc(dst: ^i32, desired: i32) -> i32                                                       #cc_c   #link_name "InterlockedAnd"               ---;
-	interlocked_or               :: proc(dst: ^i32, desired: i32) -> i32                                                       #cc_c   #link_name "InterlockedOr"                ---;
-
-	interlocked_compare_exchange64 :: proc(dst: ^i64, exchange, comparand: i64) -> i64                                         #cc_c   #link_name "InterlockedCompareExchange64" ---;
-	interlocked_exchange64         :: proc(dst: ^i64, desired: i64) -> i64                                                     #cc_c   #link_name "InterlockedExchange64"        ---;
-	interlocked_exchange_add64     :: proc(dst: ^i64, desired: i64) -> i64                                                     #cc_c   #link_name "InterlockedExchangeAdd64"     ---;
-	interlocked_and64              :: proc(dst: ^i64, desired: i64) -> i64                                                     #cc_c   #link_name "InterlockedAnd64"             ---;
-	interlocked_or64               :: proc(dst: ^i64, desired: i64) -> i64                                                     #cc_c   #link_name "InterlockedOr64"              ---;
-
-	mm_pause           :: proc()                                                                                               #cc_std #link_name "_mm_pause"                    ---;
-	read_write_barrier :: proc()                                                                                               #cc_std #link_name "ReadWriteBarrier"             ---;
-	write_barrier      :: proc()                                                                                               #cc_std #link_name "WriteBarrier"                 ---;
-	read_barrier       :: proc()                                                                                               #cc_std #link_name "ReadBarrier"                  ---;
-
-	create_thread        :: proc(thread_attributes: ^Security_Attributes, stack_size: int, start_routine: rawptr,
-	                             parameter: rawptr, creation_flags: u32, thread_id: ^u32) -> Handle                            #cc_std #link_name "CreateThread"                 ---;
-	resume_thread        :: proc(thread: Handle) -> u32                                                                        #cc_std #link_name "ResumeThread"                 ---;
-	get_thread_priority  :: proc(thread: Handle) -> i32                                                                        #cc_std #link_name "GetThreadPriority"            ---;
-	set_thread_priority  :: proc(thread: Handle, priority: i32) -> Bool                                                        #cc_std #link_name "SetThreadPriority"            ---;
-	get_exit_code_thread :: proc(thread: Handle, exit_code: ^u32) -> Bool                                                      #cc_std #link_name "GetExitCodeThread"            ---;
-
-	initialize_critical_section                :: proc(critical_section: ^Critical_Section)                                    #cc_std #link_name "InitializeCriticalSection"             ---;
-	initialize_critical_section_and_spin_count :: proc(critical_section: ^Critical_Section, spin_count: u32)                   #cc_std #link_name "InitializeCriticalSectionAndSpinCount" ---;
-	delete_critical_section                    :: proc(critical_section: ^Critical_Section)                                    #cc_std #link_name "DeleteCriticalSection"                 ---;
-	set_critical_section_spin_count            :: proc(critical_section: ^Critical_Section, spin_count: u32) -> u32            #cc_std #link_name "SetCriticalSectionSpinCount"           ---;
-	try_enter_critical_section                 :: proc(critical_section: ^Critical_Section) -> Bool                            #cc_std #link_name "TryEnterCriticalSection"               ---;
-	enter_critical_section                     :: proc(critical_section: ^Critical_Section)                                    #cc_std #link_name "EnterCriticalSection"                  ---;
-	leave_critical_section                     :: proc(critical_section: ^Critical_Section)                                    #cc_std #link_name "LeaveCriticalSection"                  ---;
-
-	create_event_a :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: ^u8) -> Handle     #cc_std #link_name "CreateEventA"                 ---;
-
-	load_library_a   :: proc(c_str: ^u8) -> Hmodule                                                                            #cc_std #link_name "LoadLibraryA"                 ---;
-	free_library     :: proc(h: Hmodule)                                                                                       #cc_std #link_name "FreeLibrary"                  ---;
-	get_proc_address :: proc(h: Hmodule, c_str: ^u8) -> rawptr                                                                 #cc_std #link_name "GetProcAddress"               ---;
+	@(link_name="GetLastError")              get_last_error              :: proc() -> i32 #cc_std ---;
+	@(link_name="ExitProcess")               exit_process                :: proc(exit_code: u32) #cc_std ---;
+	@(link_name="GetModuleHandleA")          get_module_handle_a         :: proc(module_name: ^u8) -> Hinstance #cc_std ---;
+	@(link_name="GetModuleHandleW")          get_module_handle_w         :: proc(module_name: ^u16) -> Hinstance #cc_std ---;
+	@(link_name="Sleep")                     sleep                       :: proc(ms: i32) -> i32 #cc_std ---;
+	@(link_name="QueryPerformanceFrequency") query_performance_frequency :: proc(result: ^i64) -> i32 #cc_std ---;
+	@(link_name="QueryPerformanceCounter")   query_performance_counter   :: proc(result: ^i64) -> i32 #cc_std ---;
+	@(link_name="OutputDebugStringA")        output_debug_string_a       :: proc(c_str: ^u8) #cc_std ---;
+
+	@(link_name="GetCommandLineA")    get_command_line_a    :: proc() -> ^u8 #cc_std ---;
+	@(link_name="GetCommandLineW")    get_command_line_w    :: proc() -> ^u16 #cc_std ---;
+	@(link_name="GetSystemMetrics")   get_system_metrics    :: proc(index: i32) -> i32 #cc_std ---;
+	@(link_name="GetCurrentThreadId") get_current_thread_id :: proc() -> u32 #cc_std ---;
+
+	@(link_name="GetSystemTimeAsFileTime") get_system_time_as_file_time :: proc(system_time_as_file_time: ^Filetime) #cc_std ---;
+	@(link_name="FileTimeToLocalFileTime") file_time_to_local_file_time :: proc(file_time: ^Filetime, local_file_time: ^Filetime) -> Bool #cc_std ---;
+	@(link_name="FileTimeToSystemTime")    file_time_to_system_time     :: proc(file_time: ^Filetime, system_time: ^Systemtime) -> Bool #cc_std ---;
+	@(link_name="SystemTimeToFileTime")    system_time_to_file_time     :: proc(system_time: ^Systemtime, file_time: ^Filetime) -> Bool #cc_std ---;
+
+	@(link_name="CloseHandle")  close_handle   :: proc(h: Handle) -> i32 #cc_std ---;
+	@(link_name="GetStdHandle") get_std_handle :: proc(h: i32) -> Handle #cc_std ---;
+
+	@(link_name="CreateFileA")
+	create_file_a :: proc(filename: ^u8, desired_access, share_mode: u32,
+	                      security: rawptr,
+	                      creation, flags_and_attribs: u32, template_file: Handle) -> Handle #cc_std ---;
+
+	@(link_name="ReadFile")  read_file  :: proc(h: Handle, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> Bool #cc_std ---;
+	@(link_name="WriteFile") write_file :: proc(h: Handle, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> Bool #cc_std ---;
+
+	@(link_name="GetFileSizeEx")              get_file_size_ex               :: proc(file_handle: Handle, file_size: ^i64) -> Bool #cc_std ---;
+	@(link_name="GetFileAttributesA")         get_file_attributes_a          :: proc(filename: ^u8) -> u32 #cc_std ---;
+	@(link_name="GetFileAttributesExA")       get_file_attributes_ex_a       :: proc(filename: ^u8, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool #cc_std ---;
+	@(link_name="GetFileInformationByHandle") get_file_information_by_handle :: proc(file_handle: Handle, file_info: ^By_Handle_File_Information) -> Bool #cc_std ---;
+
+	@(link_name="GetFileType")    get_file_type    :: proc(file_handle: Handle) -> u32 #cc_std ---;
+	@(link_name="SetFilePointer") set_file_pointer :: proc(file_handle: Handle, distance_to_move: i32, distance_to_move_high: ^i32, move_method: u32) -> u32 #cc_std ---;
+
+	@(link_name="SetHandleInformation") set_handle_information :: proc(obj: Handle, mask, flags: u32) -> Bool #cc_std ---;
+
+	@(link_name="FindFirstFileA") find_first_file_a :: proc(file_name : ^u8, data : ^Find_Data) -> Handle #cc_std ---;
+	@(link_name="FindNextFileA")  find_next_file_a  :: proc(file : Handle, data : ^Find_Data) -> Bool #cc_std ---;
+	@(link_name="FindClose")      find_close        :: proc(file : Handle) -> Bool #cc_std ---;
+
+
+	@(link_name="HeapAlloc")      heap_alloc       :: proc(h: Handle, flags: u32, bytes: int) -> rawptr #cc_std ---;
+	@(link_name="HeapReAlloc")    heap_realloc     :: proc(h: Handle, flags: u32, memory: rawptr, bytes: int) -> rawptr #cc_std ---;
+	@(link_name="HeapFree")       heap_free        :: proc(h: Handle, flags: u32, memory: rawptr) -> Bool #cc_std ---;
+	@(link_name="GetProcessHeap") get_process_heap :: proc() -> Handle #cc_std ---;
+
+
+	@(link_name="CreateSemaphoreA")    create_semaphore_a     :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: ^u8) -> Handle #cc_std ---;
+	@(link_name="ReleaseSemaphore")    release_semaphore      :: proc(semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool #cc_std ---;
+	@(link_name="WaitForSingleObject") wait_for_single_object :: proc(handle: Handle, milliseconds: u32) -> u32 #cc_std ---;
+
+
+	@(link_name="InterlockedCompareExchange") interlocked_compare_exchange :: proc(dst: ^i32, exchange, comparand: i32) -> i32 #cc_c ---;
+	@(link_name="InterlockedExchange")        interlocked_exchange         :: proc(dst: ^i32, desired: i32) -> i32 #cc_c ---;
+	@(link_name="InterlockedExchangeAdd")     interlocked_exchange_add     :: proc(dst: ^i32, desired: i32) -> i32 #cc_c ---;
+	@(link_name="InterlockedAnd")             interlocked_and              :: proc(dst: ^i32, desired: i32) -> i32 #cc_c ---;
+	@(link_name="InterlockedOr")              interlocked_or               :: proc(dst: ^i32, desired: i32) -> i32 #cc_c ---;
+
+	@(link_name="InterlockedCompareExchange64") interlocked_compare_exchange64 :: proc(dst: ^i64, exchange, comparand: i64) -> i64 #cc_c ---;
+	@(link_name="InterlockedExchange64")        interlocked_exchange64         :: proc(dst: ^i64, desired: i64) -> i64 #cc_c ---;
+	@(link_name="InterlockedExchangeAdd64")     interlocked_exchange_add64     :: proc(dst: ^i64, desired: i64) -> i64 #cc_c ---;
+	@(link_name="InterlockedAnd64")             interlocked_and64              :: proc(dst: ^i64, desired: i64) -> i64 #cc_c ---;
+	@(link_name="InterlockedOr64")              interlocked_or64               :: proc(dst: ^i64, desired: i64) -> i64 #cc_c ---;
+
+	@(link_name="_mm_pause")        mm_pause           :: proc() #cc_std ---;
+	@(link_name="ReadWriteBarrier") read_write_barrier :: proc() #cc_std ---;
+	@(link_name="WriteBarrier")     write_barrier      :: proc() #cc_std ---;
+	@(link_name="ReadBarrier")      read_barrier       :: proc() #cc_std ---;
+
+	@(link_name="CreateThread")
+	create_thread :: proc(thread_attributes: ^Security_Attributes, stack_size: int, start_routine: rawptr,
+	                      parameter: rawptr, creation_flags: u32, thread_id: ^u32) -> Handle #cc_std ---;
+	@(link_name="ResumeThread")      resume_thread        :: proc(thread: Handle) -> u32 #cc_std ---;
+	@(link_name="GetThreadPriority") get_thread_priority  :: proc(thread: Handle) -> i32 #cc_std ---;
+	@(link_name="SetThreadPriority") set_thread_priority  :: proc(thread: Handle, priority: i32) -> Bool #cc_std ---;
+	@(link_name="GetExitCodeThread") get_exit_code_thread :: proc(thread: Handle, exit_code: ^u32) -> Bool #cc_std ---;
+
+	@(link_name="InitializeCriticalSection")             initialize_critical_section                :: proc(critical_section: ^Critical_Section) #cc_std ---;
+	@(link_name="InitializeCriticalSectionAndSpinCount") initialize_critical_section_and_spin_count :: proc(critical_section: ^Critical_Section, spin_count: u32) #cc_std ---;
+	@(link_name="DeleteCriticalSection")                 delete_critical_section                    :: proc(critical_section: ^Critical_Section) #cc_std ---;
+	@(link_name="SetCriticalSectionSpinCount")           set_critical_section_spin_count            :: proc(critical_section: ^Critical_Section, spin_count: u32) -> u32 #cc_std ---;
+	@(link_name="TryEnterCriticalSection")               try_enter_critical_section                 :: proc(critical_section: ^Critical_Section) -> Bool #cc_std ---;
+	@(link_name="EnterCriticalSection")                  enter_critical_section                     :: proc(critical_section: ^Critical_Section) #cc_std ---;
+	@(link_name="LeaveCriticalSection")                  leave_critical_section                     :: proc(critical_section: ^Critical_Section) #cc_std ---;
+
+	@(link_name="CreateEventA") create_event_a :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: ^u8) -> Handle #cc_std ---;
+
+	@(link_name="LoadLibraryA")   load_library_a   :: proc(c_str: ^u8)  -> Hmodule #cc_std ---;
+	@(link_name="LoadLibraryW")   load_library_a   :: proc(c_str: ^u16) -> Hmodule #cc_std ---;
+	@(link_name="FreeLibrary")    free_library     :: proc(h: Hmodule) #cc_std ---;
+	@(link_name="GetProcAddress") get_proc_address :: proc(h: Hmodule, c_str: ^u8) -> rawptr #cc_std ---;
 
 }
 
 foreign user32 {
-	get_desktop_window  :: proc() -> Hwnd                                                                       #cc_std #link_name "GetDesktopWindow"    ---;
-	show_cursor         :: proc(show : Bool)                                                                    #cc_std #link_name "ShowCursor"          ---;
-	get_cursor_pos      :: proc(p: ^Point) -> Bool                                                              #cc_std #link_name "GetCursorPos"        ---;
-	set_cursor_pos      :: proc(x, y: i32) -> Bool                                                              #cc_std #link_name "SetCursorPos"        ---;
-	screen_to_client    :: proc(h: Hwnd, p: ^Point) -> Bool                                                     #cc_std #link_name "ScreenToClient"      ---;
-	client_to_screen    :: proc(h: Hwnd, p: ^Point) -> Bool                                                     #cc_std #link_name "ClientToScreen"      ---;
-	post_quit_message   :: proc(exit_code: i32)                                                                 #cc_std #link_name "PostQuitMessage"     ---;
-	set_window_text_a   :: proc(hwnd: Hwnd, c_string: ^u8) -> Bool                                              #cc_std #link_name "SetWindowTextA"      ---;
-	register_class_ex_a :: proc(wc: ^Wnd_Class_Ex_A) -> i16                                                     #cc_std #link_name "RegisterClassExA"    ---;
-	register_class_ex_w :: proc(wc: ^Wnd_Class_Ex_W) -> i16                                                     #cc_std #link_name "RegisterClassExW"    ---;
+	@(link_name="GetDesktopWindow") get_desktop_window  :: proc() -> Hwnd #cc_std ---;
+	@(link_name="ShowCursor")       show_cursor         :: proc(show : Bool) #cc_std ---;
+	@(link_name="GetCursorPos")     get_cursor_pos      :: proc(p: ^Point) -> Bool #cc_std ---;
+	@(link_name="SetCursorPos")     set_cursor_pos      :: proc(x, y: i32) -> Bool #cc_std ---;
+	@(link_name="ScreenToClient")   screen_to_client    :: proc(h: Hwnd, p: ^Point) -> Bool #cc_std ---;
+	@(link_name="ClientToScreen")   client_to_screen    :: proc(h: Hwnd, p: ^Point) -> Bool #cc_std ---;
+	@(link_name="PostQuitMessage")  post_quit_message   :: proc(exit_code: i32) #cc_std ---;
+	@(link_name="SetWindowTextA")   set_window_text_a   :: proc(hwnd: Hwnd, c_string: ^u8) -> Bool #cc_std ---;
+	@(link_name="RegisterClassExA") register_class_ex_a :: proc(wc: ^Wnd_Class_Ex_A) -> i16 #cc_std ---;
+	@(link_name="RegisterClassExW") register_class_ex_w :: proc(wc: ^Wnd_Class_Ex_W) -> i16 #cc_std ---;
+
+	@(link_name="CreateWindowExA")
+	create_window_ex_a :: proc(ex_style: u32,
+	                           class_name, title: ^u8,
+	                           style: u32,
+	                           x, y, w, h: i32,
+	                           parent: Hwnd, menu: Hmenu, instance: Hinstance,
+	                           param: rawptr) -> Hwnd #cc_std ---;
 
-	create_window_ex_a  :: proc(ex_style: u32,
-	                            class_name, title: ^u8,
-	                            style: u32,
-	                            x, y, w, h: i32,
-	                            parent: Hwnd, menu: Hmenu, instance: Hinstance,
-	                            param: rawptr) -> Hwnd                                                          #cc_std #link_name "CreateWindowExA"     ---;
+	@(link_name="CreateWindowExW")
+	create_window_ex_w :: proc(ex_style: u32,
+	                           class_name, title: ^u16,
+	                           style: u32,
+	                           x, y, w, h: i32,
+	                           parent: Hwnd, menu: Hmenu, instance: Hinstance,
+	                           param: rawptr) -> Hwnd #cc_std ---;
 
-	create_window_ex_w  :: proc(ex_style: u32,
-	                            class_name, title: ^u16,
-	                            style: u32,
-	                            x, y, w, h: i32,
-	                            parent: Hwnd, menu: Hmenu, instance: Hinstance,
-	                            param: rawptr) -> Hwnd                                                          #cc_std #link_name "CreateWindowExW"     ---;
+	@(link_name="ShowWindow")       show_window        :: proc(hwnd: Hwnd, cmd_show: i32) -> Bool #cc_std ---;
+	@(link_name="TranslateMessage") translate_message  :: proc(msg: ^Msg) -> Bool #cc_std ---;
+	@(link_name="DispatchMessageA") dispatch_message_a :: proc(msg: ^Msg) -> Lresult #cc_std ---;
+	@(link_name="DispatchMessageW") dispatch_message_w :: proc(msg: ^Msg) -> Lresult #cc_std ---;
+	@(link_name="UpdateWindow")     update_window      :: proc(hwnd: Hwnd) -> Bool #cc_std ---;
+	@(link_name="GetMessageA")      get_message_a      :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool #cc_std ---;
+	@(link_name="GetMessageW")      get_message_w      :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool #cc_std ---;
 
-	show_window        :: proc(hwnd: Hwnd, cmd_show: i32) -> Bool                                               #cc_std #link_name "ShowWindow"          ---;
-	translate_message  :: proc(msg: ^Msg) -> Bool                                                               #cc_std #link_name "TranslateMessage"    ---;
-	dispatch_message_a :: proc(msg: ^Msg) -> Lresult                                                            #cc_std #link_name "DispatchMessageA"    ---;
-	dispatch_message_w :: proc(msg: ^Msg) -> Lresult                                                            #cc_std #link_name "DispatchMessageW"    ---;
-	update_window      :: proc(hwnd: Hwnd) -> Bool                                                              #cc_std #link_name "UpdateWindow"        ---;
-	get_message_a      :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool             #cc_std #link_name "GetMessageA"         ---;
-	get_message_w      :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool             #cc_std #link_name "GetMessageW"         ---;
-	peek_message_a     :: proc(msg: ^Msg, hwnd: Hwnd,
-	                           msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool                         #cc_std #link_name "PeekMessageA"        ---;
-	peek_message_w     :: proc(msg: ^Msg, hwnd: Hwnd,
-	                           msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool                         #cc_std #link_name "PeekMessageW"        ---;
+	@(link_name="PeekMessageA") peek_message_a     :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool #cc_std ---;
+	@(link_name="PeekMessageW") peek_message_w     :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool #cc_std ---;
 
 
-	post_message          :: proc(hwnd: Hwnd, msg, wparam, lparam : u32) -> Bool                                #cc_std #link_name "PostMessageA"        ---;
+	@(link_name="PostMessageA") post_message :: proc(hwnd: Hwnd, msg, wparam, lparam : u32) -> Bool #cc_std ---;
 
-	def_window_proc_a     :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult              #cc_std #link_name "DefWindowProcA"      ---;
+	@(link_name="DefWindowProcA") def_window_proc_a :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult #cc_std ---;
 
-	adjust_window_rect    :: proc(rect: ^Rect, style: u32, menu: Bool) -> Bool                                  #cc_std #link_name "AdjustWindowRect"    ---;
-	get_active_window     :: proc() -> Hwnd                                                                     #cc_std #link_name "GetActiveWindow"     ---;
+	@(link_name="AdjustWindowRect") adjust_window_rect :: proc(rect: ^Rect, style: u32, menu: Bool) -> Bool #cc_std ---;
+	@(link_name="GetActiveWindow")  get_active_window  :: proc() -> Hwnd #cc_std ---;
 
-	destroy_window        :: proc(wnd: Hwnd) -> Bool                                                            #cc_std #link_name "DestroyWindow"       ---;
-	describe_pixel_format :: proc(dc: Hdc, pixel_format: i32, bytes: u32, pfd: ^Pixel_Format_Descriptor) -> i32 #cc_std #link_name "DescribePixelFormat" ---;
+	@(link_name="DestroyWindow")       destroy_window        :: proc(wnd: Hwnd) -> Bool #cc_std ---;
+	@(link_name="DescribePixelFormat") describe_pixel_format :: proc(dc: Hdc, pixel_format: i32, bytes: u32, pfd: ^Pixel_Format_Descriptor) -> i32 #cc_std ---;
 
-	get_monitor_info_a    :: proc(monitor: Hmonitor, mi: ^Monitor_Info) -> Bool                                 #cc_std #link_name "GetMonitor_InfoA"     ---;
-	monitor_from_window   :: proc(wnd: Hwnd, flags : u32) -> Hmonitor                                           #cc_std #link_name "MonitorFromWindow"   ---;
+	@(link_name="GetMonitor_InfoA")  get_monitor_info_a  :: proc(monitor: Hmonitor, mi: ^Monitor_Info) -> Bool #cc_std ---;
+	@(link_name="MonitorFromWindow") monitor_from_window :: proc(wnd: Hwnd, flags : u32) -> Hmonitor #cc_std ---;
 
-	set_window_pos        :: proc(wnd: Hwnd, wndInsertAfter: Hwnd, x, y, width, height: i32, flags: u32)        #cc_std #link_name "SetWindowPos"        ---;
+	@(link_name="SetWindowPos") set_window_pos        :: proc(wnd: Hwnd, wndInsertAfter: Hwnd, x, y, width, height: i32, flags: u32) #cc_std ---;
 
-	get_window_placement  :: proc(wnd: Hwnd, wndpl: ^Window_Placement) -> Bool                                  #cc_std #link_name "GetWindowPlacement"  ---;
-	set_window_placement  :: proc(wnd: Hwnd, wndpl: ^Window_Placement) -> Bool                                  #cc_std #link_name "SetWindowPlacement"  ---;
-	get_window_rect       :: proc(wnd: Hwnd, rect: ^Rect) -> Bool                                               #cc_std #link_name "GetWindowRect"       ---;
+	@(link_name="GetWindowPlacement") get_window_placement  :: proc(wnd: Hwnd, wndpl: ^Window_Placement) -> Bool #cc_std ---;
+	@(link_name="SetWindowPlacement") set_window_placement  :: proc(wnd: Hwnd, wndpl: ^Window_Placement) -> Bool #cc_std ---;
+	@(link_name="GetWindowRect")      get_window_rect       :: proc(wnd: Hwnd, rect: ^Rect) -> Bool #cc_std ---;
 
-	get_window_long_ptr_a :: proc(wnd: Hwnd, index: i32) -> Long_Ptr                                            #cc_std #link_name "GetWindowLongPtrA"   ---;
-	set_window_long_ptr_a :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr                             #cc_std #link_name "SetWindowLongPtrA"   ---;
-	get_window_long_ptr_w :: proc(wnd: Hwnd, index: i32) -> Long_Ptr                                            #cc_std #link_name "GetWindowLongPtrW"   ---;
-	set_window_long_ptr_w :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr                             #cc_std #link_name "SetWindowLongPtrW"   ---;
+	@(link_name="GetWindowLongPtrA") get_window_long_ptr_a :: proc(wnd: Hwnd, index: i32) -> Long_Ptr #cc_std ---;
+	@(link_name="SetWindowLongPtrA") set_window_long_ptr_a :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr #cc_std ---;
+	@(link_name="GetWindowLongPtrW") get_window_long_ptr_w :: proc(wnd: Hwnd, index: i32) -> Long_Ptr #cc_std ---;
+	@(link_name="SetWindowLongPtrW") set_window_long_ptr_w :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr #cc_std ---;
 
-	get_window_text       :: proc(wnd: Hwnd, str: ^u8, maxCount: i32) -> i32                                    #cc_std #link_name "GetWindowText"       ---;
+	@(link_name="GetWindowText") get_window_text :: proc(wnd: Hwnd, str: ^u8, maxCount: i32) -> i32 #cc_std ---;
 
-	get_client_rect       :: proc(hwnd: Hwnd, rect: ^Rect) -> Bool                                              #cc_std #link_name "GetClientRect"       ---;
+	@(link_name="GetClientRect") get_client_rect :: proc(hwnd: Hwnd, rect: ^Rect) -> Bool #cc_std ---;
 
-	get_dc                :: proc(h: Hwnd) -> Hdc                                                               #cc_std #link_name "GetDC"               ---;
-	release_dc            :: proc(wnd: Hwnd, hdc: Hdc) -> i32                                                   #cc_std #link_name "ReleaseDC"           ---;
+	@(link_name="GetDC")     get_dc     :: proc(h: Hwnd) -> Hdc #cc_std ---;
+	@(link_name="ReleaseDC") release_dc :: proc(wnd: Hwnd, hdc: Hdc) -> i32 #cc_std ---;
 
-	map_virtual_key_a     :: proc(scancode : u32, map_type : u32) -> u32                                        #cc_std #link_name "MapVirtualKeyA"      ---;
-	map_virtual_key_w     :: proc(scancode : u32, map_type : u32) -> u32                                        #cc_std #link_name "MapVirtualKeyW"      ---;
+	@(link_name="MapVirtualKeyA") map_virtual_key_a :: proc(scancode : u32, map_type : u32) -> u32 #cc_std ---;
+	@(link_name="MapVirtualKeyW") map_virtual_key_w :: proc(scancode : u32, map_type : u32) -> u32 #cc_std ---;
 
-	get_key_state         :: proc(v_key: i32) -> i16                                                            #cc_std #link_name "GetKeyState"         ---;
-	get_async_key_state   :: proc(v_key: i32) -> i16                                                            #cc_std #link_name "GetAsyncKeyState"    ---;
+	@(link_name="GetKeyState")      get_key_state       :: proc(v_key: i32) -> i16 #cc_std ---;
+	@(link_name="GetAsyncKeyState") get_async_key_state :: proc(v_key: i32) -> i16 #cc_std ---;
 
-	set_foreground_window :: proc(h: Hwnd) -> Bool                                                              #cc_std #link_name "SetForegroundWindow" ---;
-	set_focus             :: proc(h: Hwnd) -> Hwnd                                                              #cc_std #link_name "SetFocus"            ---;
+	@(link_name="SetForegroundWindow") set_foreground_window :: proc(h: Hwnd) -> Bool #cc_std ---;
+	@(link_name="SetFocus")            set_focus             :: proc(h: Hwnd) -> Hwnd #cc_std ---;
 
 
 
-	register_raw_input_devices :: proc(raw_input_device: ^Raw_Input_Device, num_devices, size: u32) -> Bool #cc_std #link_name "RegisterRawInputDevices" ---;
+	@(link_name="RegisterRawInputDevices") register_raw_input_devices :: proc(raw_input_device: ^Raw_Input_Device, num_devices, size: u32) -> Bool #cc_std ---;
 
-	get_raw_input_data         :: proc(raw_input: Hrawinput, command: u32, data: rawptr, size: ^u32, size_header: u32) -> u32 #cc_std #link_name "GetRawInputData" ---;
+	@(link_name="GetRawInputData") get_raw_input_data         :: proc(raw_input: Hrawinput, command: u32, data: rawptr, size: ^u32, size_header: u32) -> u32 #cc_std ---;
 
-	map_virtual_key_ex_w       :: proc(code, map_type: u32, hkl: HKL) #cc_std #link_name "MapVirtualKeyExW" ---;
-	map_virtual_key_ex_a       :: proc(code, map_type: u32, hkl: HKL) #cc_std #link_name "MapVirtualKeyExA" ---;
+	@(link_name="MapVirtualKeyExW") map_virtual_key_ex_w       :: proc(code, map_type: u32, hkl: HKL) #cc_std ---;
+	@(link_name="MapVirtualKeyExA") map_virtual_key_ex_a       :: proc(code, map_type: u32, hkl: HKL) #cc_std ---;
 }
 
 foreign gdi32 {
-	get_stock_object :: proc(fn_object: i32) -> Hgdiobj                                                         #cc_std #link_name "GetStockObject"    ---;
+	@(link_name="GetStockObject") get_stock_object :: proc(fn_object: i32) -> Hgdiobj #cc_std ---;
 
-	stretch_dibits   :: proc(hdc: Hdc,
-	                        x_dst, y_dst, width_dst, height_dst: i32,
-	                        x_src, y_src, width_src, header_src: i32,
-	                        bits: rawptr, bits_info: ^Bitmap_Info,
-	                        usage: u32,
-	                        rop: u32) -> i32                                                                    #cc_std #link_name "StretchDIBits"     ---;
+	@(link_name="StretchDIBits")
+	stretch_dibits :: proc(hdc: Hdc,
+	                       x_dst, y_dst, width_dst, height_dst: i32,
+	                       x_src, y_src, width_src, header_src: i32,
+	                       bits: rawptr, bits_info: ^Bitmap_Info,
+	                       usage: u32,
+	                       rop: u32) -> i32 #cc_std ---;
 
-	set_pixel_format    :: proc(hdc: Hdc, pixel_format: i32, pfd: ^Pixel_Format_Descriptor) -> Bool             #cc_std #link_name "SetPixelFormat"    ---;
-	choose_pixel_format :: proc(hdc: Hdc, pfd: ^Pixel_Format_Descriptor) -> i32                                 #cc_std #link_name "ChoosePixelFormat" ---;
-	swap_buffers        :: proc(hdc: Hdc) -> Bool                                                               #cc_std #link_name "SwapBuffers"       ---;
+	@(link_name="SetPixelFormat")    set_pixel_format    :: proc(hdc: Hdc, pixel_format: i32, pfd: ^Pixel_Format_Descriptor) -> Bool #cc_std ---;
+	@(link_name="ChoosePixelFormat") choose_pixel_format :: proc(hdc: Hdc, pfd: ^Pixel_Format_Descriptor) -> i32 #cc_std ---;
+	@(link_name="SwapBuffers")       swap_buffers        :: proc(hdc: Hdc) -> Bool #cc_std ---;
 
 }
 
 foreign shell32 {
-	command_line_to_argv_w :: proc(cmd_list: ^u16, num_args: ^i32) -> ^^u16 #cc_std #link_name "CommandLineToArgvW" ---;
+	@(link_name="CommandLineToArgvW") command_line_to_argv_w :: proc(cmd_list: ^u16, num_args: ^i32) -> ^^u16 #cc_std ---;
 }
 
 foreign winmm {
-	time_get_time :: proc() -> u32 #cc_std #link_name "timeGetTime" ---;
+	@(link_name="timeGetTime") time_get_time :: proc() -> u32 #cc_std ---;
 }
 
 
@@ -652,7 +659,7 @@ HIWORD :: proc(lParam: Lparam) -> u16 { return u16((u32(lParam) >> 16) & 0xffff)
 LOWORD :: proc(wParam: Wparam) -> u16 { return u16(wParam); }
 LOWORD :: proc(lParam: Lparam) -> u16 { return u16(lParam); }
 
-is_key_down :: proc(key: Key_Code) -> bool #inline { return get_async_key_state(i32(key)) < 0; }
+is_key_down :: inline proc(key: Key_Code) -> bool do return get_async_key_state(i32(key)) < 0;
 
 
 

+ 4 - 4
core/utf8.odin

@@ -92,7 +92,7 @@ encode_rune :: proc(r: rune) -> ([4]u8, int) {
 	return buf, 4;
 }
 
-decode_rune :: proc(s: string) -> (rune, int) #inline { return decode_rune(cast([]u8)s); }
+decode_rune :: inline proc(s: string) -> (rune, int) do return decode_rune(cast([]u8)s);
 decode_rune :: proc(s: []u8) -> (rune, int) {
 	n := len(s);
 	if n < 1 {
@@ -132,7 +132,7 @@ decode_rune :: proc(s: []u8) -> (rune, int) {
 
 
 
-decode_last_rune :: proc(s: string) -> (rune, int) #inline { return decode_last_rune(cast([]u8)s); }
+decode_last_rune :: inline proc(s: string) -> (rune, int) do return decode_last_rune(cast([]u8)s);
 decode_last_rune :: proc(s: []u8) -> (rune, int) {
 	r: rune;
 	size: int;
@@ -211,9 +211,9 @@ valid_string :: proc(s: string) -> bool {
 	return true;
 }
 
-rune_start :: proc(b: u8) -> bool #inline { return b&0xc0 != 0x80; }
+rune_start :: inline proc(b: u8) -> bool do return b&0xc0 != 0x80;
 
-rune_count :: proc(s: string) -> int #inline { return rune_count(cast([]u8)s); }
+rune_count :: inline proc(s: string) -> int do return rune_count(cast([]u8)s);
 rune_count :: proc(s: []u8) -> int {
 	count := 0;
 	n := len(s);

+ 85 - 12
src/check_decl.cpp

@@ -187,8 +187,13 @@ AstNode *remove_type_alias(AstNode *node) {
 
 void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, bool is_alias) {
 	GB_ASSERT(e->type == nullptr);
-	AstNode *te = remove_type_alias(type_expr);
 
+	DeclInfo *decl = decl_info_of_entity(&c->info, e);
+	if (decl != nullptr && decl->attributes.count > 0) {
+		error(decl->attributes[0], "Attributes are not allowed on type declarations");
+	}
+
+	AstNode *te = remove_type_alias(type_expr);
 	e->type = t_invalid;
 	String name = e->token.string;
 	Type *named = make_type_named(c->allocator, name, nullptr, e);
@@ -203,8 +208,11 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, bool
 	if (is_alias) {
 		if (is_type_named(bt)) {
 			e->type = bt;
+			e->TypeName.is_type_alias = true;
 		} else {
-			warning(type_expr, "Type declaration will not be an alias type");
+			gbString str = type_to_string(bt);
+			error(type_expr, "Type alias declaration with a non-named type `%s`", str);
+			gb_string_free(str);
 		}
 	}
 }
@@ -319,6 +327,12 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
 		error(e->token, "Invalid declaration type `%s`", str);
 		gb_string_free(str);
 	}
+
+
+	DeclInfo *decl = decl_info_of_entity(&c->info, e);
+	if (decl != nullptr && decl->attributes.count > 0) {
+		error(decl->attributes[0], "Attributes are not allowed on constant value declarations");
+	}
 }
 
 
@@ -436,8 +450,6 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 	defer (check_close_scope(c));
 
 
-
-
 	auto prev_context = c->context;
 	c->context.allow_polymorphic_types = true;
 	check_procedure_type(c, proc_type, pl->type);
@@ -447,11 +459,65 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 
 	bool is_foreign         = e->Procedure.is_foreign;
 	bool is_export          = e->Procedure.is_export;
-	bool is_link_name       = (pl->tags & ProcTag_link_name) != 0;
 	bool is_inline          = (pl->tags & ProcTag_inline)    != 0;
 	bool is_no_inline       = (pl->tags & ProcTag_no_inline) != 0;
 	bool is_require_results = (pl->tags & ProcTag_require_results) != 0;
 
+	String link_name = {};
+
+
+	if (d != nullptr && d->attributes.count > 0) {
+		for_array(i, d->attributes) {
+			AstNode *attr = d->attributes[i];
+			if (attr->kind != AstNode_Attribute) continue;
+			for_array(j, attr->Attribute.elems) {
+				AstNode *elem = attr->Attribute.elems[j];
+				String name = {};
+				AstNode *value = nullptr;
+
+				switch (elem->kind) {
+				case_ast_node(i, Ident, elem);
+					name = i->token.string;
+				case_end;
+				case_ast_node(fv, FieldValue, elem);
+					GB_ASSERT(fv->field->kind == AstNode_Ident);
+					name = fv->field->Ident.token.string;
+					value = fv->value;
+				case_end;
+				default:
+					error(elem, "Invalid attribute element");
+					continue;
+				}
+
+				ExactValue ev = {};
+				if (value != nullptr) {
+					Operand op = {};
+					check_expr(c, &op, value);
+					if (op.mode != Addressing_Constant) {
+						error(value, "An attribute element must be constant");
+					} else {
+						ev = op.value;
+					}
+				}
+
+				if (name == "link_name") {
+					if (link_name.len > 0) {
+						error(elem, "Previous declaration of `link_name`");
+					}
+					if (ev.kind == ExactValue_String) {
+						link_name = ev.value_string;
+					} else {
+						error(elem, "Expected a string value for `link_name`");
+					}
+				} else {
+					error(elem, "Unknown attribute element name `%.*s`", LIT(name));
+				}
+			}
+		}
+	}
+
+
+
 
 
 	if (d->scope->file != nullptr && e->token.string == "main") {
@@ -526,8 +592,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 
 	if (is_foreign) {
 		String name = e->token.string;
-		if (pl->link_name.len > 0) {
-			name = pl->link_name;
+		if (link_name.len > 0) {
+			name = link_name;
 		}
 		e->Procedure.is_foreign = true;
 		e->Procedure.link_name = name;
@@ -562,11 +628,11 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 		}
 	} else {
 		String name = e->token.string;
-		if (is_link_name) {
-			name = pl->link_name;
+		if (link_name.len > 0) {
+			name = link_name;
 		}
 
-		if (is_link_name || is_export) {
+		if (link_name.len > 0 || is_export) {
 			auto *fp = &c->info.foreigns;
 
 			e->Procedure.link_name = name;
@@ -600,6 +666,11 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
 	}
 	e->flags |= EntityFlag_Visited;
 
+	DeclInfo *decl = decl_info_of_entity(&c->info, e);
+	if (decl != nullptr && decl->attributes.count > 0) {
+		error(decl->attributes[0], "Attributes are not allowed on variable declarations, yet");
+	}
+
 	String context_name = str_lit("variable declaration");
 
 	if (type_expr != nullptr) {
@@ -692,9 +763,11 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
 	case Entity_Constant:
 		check_const_decl(c, e, d->type_expr, d->init_expr, named_type);
 		break;
-	case Entity_TypeName:
-		check_type_decl(c, e, d->type_expr, named_type, d->type_expr->kind == AstNode_AliasType);
+	case Entity_TypeName: {
+		bool is_alias = unparen_expr(d->type_expr)->kind == AstNode_AliasType;
+		check_type_decl(c, e, d->type_expr, named_type, is_alias);
 		break;
+	}
 	case Entity_Procedure:
 		check_proc_decl(c, e, d);
 		break;

+ 4 - 3
src/check_expr.cpp

@@ -1238,6 +1238,7 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
 		case Basic_u64:
 		case Basic_u128:
 		case Basic_uint:
+		case Basic_uintptr:
 			return !(u128_lt(u, U128_ZERO) || u128_gt(u, umax));
 
 		case Basic_UntypedInteger:
@@ -1759,10 +1760,10 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
 	}
 
 	// (u)int <-> rawptr
-	if (is_type_int_or_uint(src) && is_type_rawptr(dst)) {
+	if (is_type_uintptr(src) && is_type_rawptr(dst)) {
 		return true;
 	}
-	if (is_type_rawptr(src) && is_type_int_or_uint(dst)) {
+	if (is_type_rawptr(src) && is_type_uintptr(dst)) {
 		return true;
 	}
 
@@ -2520,7 +2521,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 			bool is_declared = entity != nullptr;
 			if (is_declared) {
 				if (entity->kind == Entity_Builtin) {
-					// NOTE(bill): Builtin's are in the universe scope which is part of every scopes hierarchy
+					// NOTE(bill): Builtin's are in the universal scope which is part of every scopes hierarchy
 					// This means that we should just ignore the found result through it
 					is_declared = false;
 				} else if (entity->scope->is_global && !import_scope->is_global) {

+ 1 - 1
src/check_stmt.cpp

@@ -206,7 +206,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
 
 	check_expr(c, &lhs, lhs_node);
 	if (lhs.mode == Addressing_Invalid ||
-	    lhs.type == t_invalid) {
+	    (lhs.type == t_invalid && lhs.mode != Addressing_Overload)) {
 		return nullptr;
 	}
 

+ 11 - 3
src/checker.cpp

@@ -182,6 +182,7 @@ struct DeclInfo {
 	AstNode *         type_expr;
 	AstNode *         init_expr;
 	Array<AstNode *>  init_expr_list;
+	Array<AstNode *>  attributes;
 	AstNode *         proc_lit;      // AstNode_ProcLit
 	Type *            gen_proc_type; // Precalculated
 
@@ -1720,11 +1721,14 @@ void init_preload(Checker *c) {
 	{
 		String _global = str_lit("_global");
 
-		Entity *e = make_entity_import_name(c->allocator, c->global_scope->parent, make_token_ident(_global), t_invalid,
+		Entity *type_info_entity = find_core_entity(c, str_lit("Type_Info"));
+		Scope *preload_scope = type_info_entity->scope;
+
+		Entity *e = make_entity_import_name(c->allocator, preload_scope, make_token_ident(_global), t_invalid,
 		                                    str_lit(""), _global,
-		                                    c->global_scope);
+		                                    preload_scope);
 
-		add_entity(c, c->global_scope, nullptr, e);
+		add_entity(c, universal_scope, nullptr, e);
 	}
 
 	c->done_preload = true;
@@ -1999,6 +2003,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
 				d->type_expr = vd->type;
 				d->init_expr = init_expr;
 			}
+			d->attributes = vd->attributes;
 
 			add_entity_and_decl_info(c, name, e, d);
 		}
@@ -2028,6 +2033,8 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
 			DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
 			Entity *e = nullptr;
 
+			d->attributes = vd->attributes;
+
 			if (is_ast_node_type(init) ||
 				(vd->type != nullptr && vd->type->kind == AstNode_TypeType)) {
 				e = make_entity_type_name(c->allocator, d->scope, token, nullptr);
@@ -2069,6 +2076,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
 				}
 			}
 
+
 			add_entity_and_decl_info(c, name, e, d);
 		}
 

+ 21 - 20
src/ir.cpp

@@ -2852,19 +2852,19 @@ String ir_lookup_subtype_polymorphic_field(CheckerInfo *info, Type *dst, Type *s
 }
 
 
-irValue *ir_emit_ptr_to_int(irProcedure *proc, irValue *value, Type *t, bool allow_type_type = false) {
+irValue *ir_emit_ptr_to_uintptr(irProcedure *proc, irValue *value, Type *t, bool allow_type_type = false) {
 	Type *vt = core_type(ir_type(value));
 	GB_ASSERT(is_type_pointer(vt));
 	if (allow_type_type) {
-		GB_ASSERT(is_type_int_or_uint(core_type(t)));
+		GB_ASSERT(is_type_uintptr(core_type(t)));
 	} else {
-		GB_ASSERT(is_type_int_or_uint(core_type(t)));
+		GB_ASSERT(is_type_uintptr(core_type(t)));
 	}
 	return ir_emit(proc, ir_instr_conv(proc, irConv_ptrtoint, value, vt, t));
 }
-irValue *ir_emit_int_to_ptr(irProcedure *proc, irValue *value, Type *t) {
+irValue *ir_emit_uintptr_to_ptr(irProcedure *proc, irValue *value, Type *t) {
 	Type *vt = core_type(ir_type(value));
-	GB_ASSERT(is_type_int_or_uint(vt));
+	GB_ASSERT(is_type_uintptr(vt));
 	GB_ASSERT(is_type_pointer(core_type(t)));
 	return ir_emit(proc, ir_instr_conv(proc, irConv_inttoptr, value, vt, t));
 }
@@ -3028,11 +3028,11 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
 	}
 
 	// Pointer <-> int
-	if (is_type_pointer(src) && is_type_int_or_uint(dst)) {
-		return ir_emit_ptr_to_int(proc, value, t);
+	if (is_type_pointer(src) && is_type_uintptr(dst)) {
+		return ir_emit_ptr_to_uintptr(proc, value, t);
 	}
-	if (is_type_int_or_uint(src) && is_type_pointer(dst)) {
-		return ir_emit_int_to_ptr(proc, value, t);
+	if (is_type_uintptr(src) && is_type_pointer(dst)) {
+		return ir_emit_uintptr_to_ptr(proc, value, t);
 	}
 
 	if (is_type_union(dst)) {
@@ -3250,11 +3250,11 @@ irValue *ir_emit_transmute(irProcedure *proc, irValue *value, Type *t) {
 	GB_ASSERT_MSG(sz == dz, "Invalid transmute conversion: `%s` to `%s`", type_to_string(src_type), type_to_string(t));
 
 	// NOTE(bill): Casting between an integer and a pointer cannot be done through a bitcast
-	if (is_type_int_or_uint(src) && is_type_pointer(dst)) {
-		return ir_emit_int_to_ptr(proc, value, t);
+	if (is_type_uintptr(src) && is_type_pointer(dst)) {
+		return ir_emit_uintptr_to_ptr(proc, value, t);
 	}
-	if (is_type_pointer(src) && is_type_int_or_uint(dst)) {
-		return ir_emit_ptr_to_int(proc, value, t);
+	if (is_type_pointer(src) && is_type_uintptr(dst)) {
+		return ir_emit_ptr_to_uintptr(proc, value, t);
 	}
 
 	if (ir_is_type_aggregate(src) || ir_is_type_aggregate(dst)) {
@@ -5886,8 +5886,8 @@ void ir_build_poly_proc(irProcedure *proc, AstNodeProcLit *pd, Entity *e) {
 	// parent.name-guid
 	String original_name = e->token.string;
 	String pd_name = original_name;
-	if (pd->link_name.len > 0) {
-		pd_name = pd->link_name;
+	if (e->Procedure.link_name.len > 0) {
+		pd_name = e->Procedure.link_name;
 	}
 
 	isize name_len = proc->name.len + 1 + pd_name.len + 1 + 10 + 1;
@@ -5978,8 +5978,8 @@ void ir_build_constant_value_decl(irProcedure *proc, AstNodeValueDecl *vd) {
 				// FFI - Foreign function interace
 				String original_name = e->token.string;
 				String name = original_name;
-				if (pl->link_name.len > 0) {
-					name = pl->link_name;
+				if (e->Procedure.link_name.len > 0) {
+					name = e->Procedure.link_name;
 				}
 
 				irValue *value = ir_value_procedure(proc->module->allocator,
@@ -7749,7 +7749,8 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
 			case Basic_i128:
 			case Basic_u128:
 			case Basic_int:
-			case Basic_uint: {
+			case Basic_uint:
+			case Basic_uintptr: {
 				tag = ir_emit_conv(proc, variant_ptr, t_type_info_integer_ptr);
 				irValue *is_signed = ir_const_bool(a, (t->Basic.flags & BasicFlag_Unsigned) == 0);
 				ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), is_signed);
@@ -8286,8 +8287,8 @@ void ir_gen_tree(irGen *s) {
 				name = e->token.string; // NOTE(bill): Don't use the mangled name
 				ir_add_foreign_library_path(m, e->Procedure.foreign_library);
 			}
-			if (pl->link_name.len > 0) {
-				name = pl->link_name;
+			if (e->Procedure.link_name.len > 0) {
+				name = e->Procedure.link_name;
 			}
 
 			AstNode *type_expr = pl->type;

+ 9 - 8
src/ir_print.cpp

@@ -245,14 +245,15 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
 		case Basic_f64:    ir_write_string(f, "double");               return;
 
 		// case Basic_complex32:  ir_write_string(f, "%%..complex32"); return;
-		case Basic_complex64:  ir_write_string(f, "%..complex64");    return;
-		case Basic_complex128: ir_write_string(f, "%..complex128");   return;
-
-		case Basic_rawptr: ir_write_string(f, "%..rawptr");           return;
-		case Basic_string: ir_write_string(f, "%..string");           return;
-		case Basic_uint:   ir_fprintf(f, "i%lld", word_bits);          return;
-		case Basic_int:    ir_fprintf(f, "i%lld", word_bits);          return;
-		case Basic_any:    ir_write_string(f, "%..any");              return;
+		case Basic_complex64:  ir_write_string(f, "%..complex64");     return;
+		case Basic_complex128: ir_write_string(f, "%..complex128");    return;
+
+		case Basic_rawptr:  ir_write_string(f, "%..rawptr");           return;
+		case Basic_string:  ir_write_string(f, "%..string");           return;
+		case Basic_uint:    ir_fprintf(f, "i%lld", word_bits);         return;
+		case Basic_int:     ir_fprintf(f, "i%lld", word_bits);         return;
+		case Basic_uintptr: ir_fprintf(f, "i%lld", word_bits);         return;
+		case Basic_any:     ir_write_string(f, "%..any");              return;
 		}
 		break;
 	case Type_Pointer: {

+ 118 - 52
src/parser.cpp

@@ -167,10 +167,9 @@ Array<AstNode *> make_ast_node_array(AstFile *f, isize init_capacity = 8) {
 		AstNode *expr; \
 	}) \
 	AST_NODE_KIND(ProcLit, "procedure literal", struct { \
-		AstNode *type;            \
-		AstNode *body;            \
-		u64      tags;            \
-		String   link_name;       \
+		AstNode *type; \
+		AstNode *body; \
+		u64      tags; \
 	}) \
 	AST_NODE_KIND(CompoundLit, "compound literal", struct { \
 		AstNode *type; \
@@ -347,6 +346,7 @@ AST_NODE_KIND(_DeclBegin,      "", i32) \
 		u64              flags;        \
 		bool             is_mutable;   \
 		bool             been_handled; \
+		Array<AstNode *> attributes;   \
 		CommentGroup     docs;         \
 		CommentGroup     comment;      \
 	}) \
@@ -382,12 +382,18 @@ AST_NODE_KIND(_DeclBegin,      "", i32) \
 		CommentGroup comment;     \
 	}) \
 AST_NODE_KIND(_DeclEnd,   "", i32) \
+	AST_NODE_KIND(Attribute, "attribute", struct { \
+		Token    token;         \
+		AstNode *type;          \
+		Array<AstNode *> elems; \
+		Token open, close;      \
+	}) \
 	AST_NODE_KIND(Field, "field", struct { \
 		Array<AstNode *> names;            \
 		AstNode *        type;             \
 		AstNode *        default_value;    \
 		u32              flags;            \
-		CommentGroup     docs;    \
+		CommentGroup     docs;             \
 		CommentGroup     comment;          \
 	}) \
 	AST_NODE_KIND(FieldList, "field list", struct { \
@@ -602,6 +608,8 @@ Token ast_node_token(AstNode *node) {
 
 	case AstNode_ForeignBlockDecl:   return node->ForeignBlockDecl.token;
 
+	case AstNode_Attribute:
+		return node->Attribute.token;
 
 	case AstNode_Field:
 		if (node->Field.names.count > 0) {
@@ -842,8 +850,12 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
 		n->ValueDecl.names  = clone_ast_node_array(a, n->ValueDecl.names);
 		n->ValueDecl.type   = clone_ast_node(a, n->ValueDecl.type);
 		n->ValueDecl.values = clone_ast_node_array(a, n->ValueDecl.values);
+		n->ValueDecl.attributes = clone_ast_node_array(a, n->ValueDecl.attributes);
 		break;
 
+	case AstNode_Attribute:
+		n->Attribute.elems = clone_ast_node_array(a, n->Attribute.elems);
+		break;
 	case AstNode_Field:
 		n->Field.names = clone_ast_node_array(a, n->Field.names);
 		n->Field.type  = clone_ast_node(a, n->Field.type);
@@ -937,7 +949,7 @@ void syntax_error(AstNode *node, char *fmt, ...) {
 
 bool ast_node_expect(AstNode *node, AstNodeKind kind) {
 	if (node->kind != kind) {
-		error(node, "Expected %.*s, got %.*s", LIT(ast_node_strings[node->kind]));
+		syntax_error(node, "Expected %.*s, got %.*s", LIT(ast_node_strings[node->kind]));
 		return false;
 	}
 	return true;
@@ -1124,12 +1136,11 @@ AstNode *ast_ellipsis(AstFile *f, Token token, AstNode *expr) {
 }
 
 
-AstNode *ast_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags, String link_name) {
+AstNode *ast_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags) {
 	AstNode *result = make_ast_node(f, AstNode_ProcLit);
 	result->ProcLit.type = type;
 	result->ProcLit.body = body;
 	result->ProcLit.tags = tags;
-	result->ProcLit.link_name = link_name;
 	return result;
 }
 
@@ -1556,6 +1567,8 @@ AstNode *ast_value_decl(AstFile *f, Array<AstNode *> names, AstNode *type, Array
 	result->ValueDecl.is_mutable = is_mutable;
 	result->ValueDecl.docs       = docs;
 	result->ValueDecl.comment    = comment;
+
+	result->ValueDecl.attributes.allocator = heap_allocator();
 	return result;
 }
 
@@ -1593,6 +1606,16 @@ AstNode *ast_foreign_import_decl(AstFile *f, Token token, Token filepath, Token
 }
 
 
+AstNode *ast_attribute(AstFile *f, Token token, Token open, Token close, Array<AstNode *> elems) {
+	AstNode *result = make_ast_node(f, AstNode_Attribute);
+	result->Attribute.token = token;
+	result->Attribute.open  = open;
+	result->Attribute.elems = elems;
+	result->Attribute.close = close;
+	return result;
+}
+
+
 bool next_token0(AstFile *f) {
 	// Token prev = f->curr_token;
 	if (f->curr_token_index+1 < f->tokens.count) {
@@ -1831,7 +1854,7 @@ Token expect_closing(AstFile *f, TokenKind kind, String context) {
 	if (f->curr_token.kind != kind &&
 	    f->curr_token.kind == Token_Semicolon &&
 	    f->curr_token.string == "\n") {
-		error(f->curr_token, "Missing `,` before newline in %.*s", LIT(context));
+		syntax_error(f->curr_token, "Missing `,` before newline in %.*s", LIT(context));
 		advance_token(f);
 	}
 	return expect_token(f, kind);
@@ -1854,6 +1877,11 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
 	case AstNode_TypeSwitchStmt:
 		return true;
 
+	case AstNode_HelperType:
+		return is_semicolon_optional_for_node(f, s->HelperType.type);
+	case AstNode_AliasType:
+		return is_semicolon_optional_for_node(f, s->AliasType.type);
+
 	case AstNode_PointerType:
 		return is_semicolon_optional_for_node(f, s->PointerType.type);
 
@@ -1925,7 +1953,7 @@ void expect_semicolon(AstFile *f, AstNode *s) {
 
 
 AstNode *        parse_expr(AstFile *f, bool lhs);
-AstNode *        parse_proc_type(AstFile *f, Token proc_token, String *link_name);
+AstNode *        parse_proc_type(AstFile *f, Token proc_token);
 Array<AstNode *> parse_stmt_list(AstFile *f);
 AstNode *        parse_stmt(AstFile *f);
 AstNode *        parse_body(AstFile *f);
@@ -2066,9 +2094,8 @@ bool is_foreign_name_valid(String name) {
 	return true;
 }
 
-void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConvention *calling_convention) {
-	GB_ASSERT(tags         != nullptr);
-	GB_ASSERT(link_name    != nullptr);
+void parse_proc_tags(AstFile *f, u64 *tags, ProcCallingConvention *calling_convention) {
+	GB_ASSERT(tags != nullptr);
 
 	ProcCallingConvention cc = ProcCC_Invalid;
 
@@ -2082,24 +2109,10 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_##name, tag_name); \
 		}
 
-		if (tag_name == "link_name") {
-			check_proc_add_tag(f, tag_expr, tags, ProcTag_link_name, tag_name);
-			if (f->curr_token.kind == Token_String) {
-				*link_name = f->curr_token.string;
-				if (!is_foreign_name_valid(*link_name)) {
-					syntax_error(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*link_name));
-				}
-
-				advance_token(f);
-			} else {
-				expect_token(f, Token_String);
-			}
-		}
+		if (false) {}
 		ELSE_IF_ADD_TAG(require_results)
 		ELSE_IF_ADD_TAG(bounds_check)
 		ELSE_IF_ADD_TAG(no_bounds_check)
-		ELSE_IF_ADD_TAG(inline)
-		ELSE_IF_ADD_TAG(no_inline)
 		else if (tag_name == "cc_odin") {
 			if (cc == ProcCC_Invalid) {
 				cc = ProcCC_Odin;
@@ -2278,7 +2291,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 			AstNode *expr = parse_expr(f, false);
 			operand = ast_run_expr(f, token, name, expr);
 			if (unparen_expr(expr)->kind != AstNode_CallExpr) {
-				error(expr, "#run can only be applied to procedure calls");
+				syntax_error(expr, "#run can only be applied to procedure calls");
 				operand = ast_bad_expr(f, token, f->curr_token);
 			}
 			warning(token, "#run is not yet implemented");
@@ -2295,11 +2308,27 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 		return operand;
 	}
 
+	case Token_inline:
+	case Token_no_inline:
+	{
+		Token token = advance_token(f);
+		AstNode *expr = parse_operand(f, false);
+		if (expr->kind != AstNode_ProcLit) {
+			syntax_error(expr, "%.*s must be followed by a procedure literal, got %.*s", LIT(token.string), LIT(ast_node_strings[expr->kind]));
+			return ast_bad_expr(f, token, f->curr_token);
+		}
+		if (token.kind == Token_inline) {
+			expr->ProcLit.tags |= ProcTag_inline;
+		} else if (token.kind == Token_no_inline) {
+			expr->ProcLit.tags |= ProcTag_no_inline;
+		}
+		return expr;
+	} break;
+
 	// Parse Procedure Type or Literal
 	case Token_proc: {
 		Token token = expect_token(f, Token_proc);
-		String link_name = {};
-		AstNode *type = parse_proc_type(f, token, &link_name);
+		AstNode *type = parse_proc_type(f, token);
 
 		if (f->allow_type && f->expr_level < 0) {
 			return type;
@@ -2308,7 +2337,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 		u64 tags = type->ProcType.tags;
 
 		if (allow_token(f, Token_Undef)) {
-			return ast_proc_lit(f, type, nullptr, tags, link_name);
+			return ast_proc_lit(f, type, nullptr, tags);
 		} else if (f->curr_token.kind == Token_OpenBrace) {
 			AstNode *curr_proc = f->curr_proc;
 			AstNode *body = nullptr;
@@ -2316,7 +2345,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 			body = parse_body(f);
 			f->curr_proc = curr_proc;
 
-			return ast_proc_lit(f, type, body, tags, link_name);
+			return ast_proc_lit(f, type, body, tags);
 		} else if (allow_token(f, Token_do)) {
 			AstNode *curr_proc = f->curr_proc;
 			AstNode *body = nullptr;
@@ -2324,7 +2353,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 			body = convert_stmt_to_body(f, parse_stmt(f));
 			f->curr_proc = curr_proc;
 
-			return ast_proc_lit(f, type, body, tags, link_name);
+			return ast_proc_lit(f, type, body, tags);
 		}
 
 		if (tags != 0) {
@@ -2791,11 +2820,11 @@ AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) {
 					index3 = true;
 					// 2nd and 3rd index must be present
 					if (indices[1] == nullptr) {
-						error(ellipses[0], "2nd index required in 3-index slice expression");
+						syntax_error(ellipses[0], "2nd index required in 3-index slice expression");
 						indices[1] = ast_bad_expr(f, ellipses[0], ellipses[1]);
 					}
 					if (indices[2] == nullptr) {
-						error(ellipses[1], "3rd index required in 3-index slice expression");
+						syntax_error(ellipses[1], "3rd index required in 3-index slice expression");
 						indices[2] = ast_bad_expr(f, ellipses[1], close);
 					}
 				}
@@ -3020,13 +3049,13 @@ void parse_foreign_block_decl(AstFile *f, Array<AstNode *> *decls) {
 	case AstNode_BadDecl:
 		return;
 
+	case AstNode_WhenStmt:
 	case AstNode_ValueDecl:
 		array_add(decls, decl);
 		return;
 
-		/* fallthrough */
 	default:
-		error(decl, "Foreign blocks only allow procedure and variable declarations");
+		syntax_error(decl, "Foreign blocks only allow procedure and variable declarations");
 		return;
 	}
 }
@@ -3266,7 +3295,7 @@ AstNode *parse_results(AstFile *f) {
 	return list;
 }
 
-AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) {
+AstNode *parse_proc_type(AstFile *f, Token proc_token) {
 	AstNode *params = nullptr;
 	AstNode *results = nullptr;
 
@@ -3276,11 +3305,8 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) {
 	results = parse_results(f);
 
 	u64 tags = 0;
-	String link_name = {};
 	ProcCallingConvention cc = ProcCC_Invalid;
-	parse_proc_tags(f, &tags, &link_name, &cc);
-
-	if (link_name_) *link_name_ = link_name;
+	parse_proc_tags(f, &tags, &cc);
 
 	bool is_generic = false;
 
@@ -3304,7 +3330,7 @@ AstNode *parse_var_type(AstFile *f, bool allow_ellipsis, bool allow_type_token)
 		Token tok = advance_token(f);
 		AstNode *type = parse_type_or_ident(f);
 		if (type == nullptr) {
-			error(tok, "variadic field missing type after `...`");
+			syntax_error(tok, "variadic field missing type after `...`");
 			type = ast_bad_expr(f, tok, f->curr_token);
 		}
 		return ast_ellipsis(f, tok, type);
@@ -3323,7 +3349,7 @@ AstNode *parse_var_type(AstFile *f, bool allow_ellipsis, bool allow_type_token)
 	}
 	if (type == nullptr) {
 		Token tok = f->curr_token;
-		error(tok, "Expected a type");
+		syntax_error(tok, "Expected a type");
 		type = ast_bad_expr(f, tok, f->curr_token);
 	}
 	return type;
@@ -3426,7 +3452,7 @@ Array<AstNode *> convert_to_ident_list(AstFile *f, Array<AstNodeAndFlags> list,
 
 		if (!ignore_flags) {
 			if (i != 0) {
-				error(ident, "Illegal use of prefixes in parameter list");
+				syntax_error(ident, "Illegal use of prefixes in parameter list");
 			}
 		}
 
@@ -3435,7 +3461,7 @@ Array<AstNode *> convert_to_ident_list(AstFile *f, Array<AstNodeAndFlags> list,
 		case AstNode_BadExpr:
 			break;
 		default:
-			error(ident, "Expected an identifier");
+			syntax_error(ident, "Expected an identifier");
 			ident = ast_ident(f, blank_token);
 			break;
 		}
@@ -3451,7 +3477,7 @@ bool parse_expect_field_separator(AstFile *f, AstNode *param) {
 		return true;
 	}
 	if (token.kind == Token_Semicolon) {
-		error(f->curr_token, "Expected a comma, got a semicolon");
+		syntax_error(f->curr_token, "Expected a comma, got a semicolon");
 		advance_token(f);
 		return true;
 	}
@@ -3465,7 +3491,7 @@ bool parse_expect_struct_separator(AstFile *f, AstNode *param) {
 	}
 
 	if (token.kind == Token_Colon) {
-		error(f->curr_token, "Expected a semicolon, got a comma");
+		syntax_error(f->curr_token, "Expected a semicolon, got a comma");
 		advance_token(f);
 		return true;
 	}
@@ -3506,7 +3532,7 @@ AstNode *parse_struct_field_list(AstFile *f, isize *name_count_) {
 		case_ast_node(vd, ValueDecl, decl);
 			if (vd->flags&VarDeclFlag_thread_local) {
 				vd->flags &= ~VarDeclFlag_thread_local;
-				error(decl, "Field values cannot be #thread_local");
+				syntax_error(decl, "Field values cannot be #thread_local");
 			}
 			array_add(&decls, decl);
 			total_name_count += vd->names.count;
@@ -3517,7 +3543,7 @@ AstNode *parse_struct_field_list(AstFile *f, isize *name_count_) {
 			break;
 
 		default:
-			error(decl, "Expected a value declaration, got %.*s", LIT(ast_node_strings[decl->kind]));
+			syntax_error(decl, "Expected a value declaration, got %.*s", LIT(ast_node_strings[decl->kind]));
 			break;
 		}
 	}
@@ -4209,7 +4235,7 @@ AstNode *parse_for_stmt(AstFile *f) {
 			index = cond->AssignStmt.lhs[1];
 			break;
 		default:
-			error(cond, "Expected either 1 or 2 identifiers");
+			syntax_error(cond, "Expected either 1 or 2 identifiers");
 			return ast_bad_stmt(f, token, f->curr_token);
 		}
 
@@ -4566,6 +4592,46 @@ AstNode *parse_stmt(AstFile *f) {
 		return ast_push_context(f, token, expr, body);
 	} break;
 
+	case Token_At: {
+		advance_token(f);
+
+		Array<AstNode *> elems = {};
+		Token open = expect_token(f, Token_OpenParen);
+		f->expr_level++;
+		if (f->curr_token.kind != Token_CloseParen) {
+			elems = make_ast_node_array(f);
+
+			while (f->curr_token.kind != Token_CloseParen &&
+			       f->curr_token.kind != Token_EOF) {
+				AstNode *elem = parse_ident(f);
+				if (f->curr_token.kind == Token_Eq) {
+					Token eq = expect_token(f, Token_Eq);
+					AstNode *value = parse_value(f);
+					elem = ast_field_value(f, elem, value, eq);
+				}
+
+				array_add(&elems, elem);
+
+				if (!allow_token(f, Token_Comma)) {
+					break;
+				}
+			}
+		}
+		f->expr_level--;
+		Token close = expect_closing(f, Token_CloseParen, str_lit("attribute"));
+
+		AstNode *attribute = ast_attribute(f, token, open, close, elems);
+
+		AstNode *decl = parse_stmt(f);
+		if (decl->kind != AstNode_ValueDecl) {
+			syntax_error(decl, "Expected a value declaration after an attribute, got %.*s", LIT(ast_node_strings[decl->kind]));
+			return ast_bad_stmt(f, token, f->curr_token);
+		}
+
+		array_add(&decl->ValueDecl.attributes, attribute);
+		return decl;
+	}
+
 	case Token_Hash: {
 		AstNode *s = nullptr;
 		Token hash_token = expect_token(f, Token_Hash);

+ 2 - 2
src/ssa.cpp

@@ -2490,8 +2490,8 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
 			if (e->Procedure.is_foreign) {
 				name = e->token.string; // NOTE(bill): Don't use the mangled name
 			}
-			if (pl->link_name.len > 0) {
-				name = pl->link_name;
+			if (e->Procedure.link_name.len > 0) {
+				name = e->Procedure.link_name;
 			}
 
 			if (e == entry_point) {

+ 2 - 0
src/tokenizer.cpp

@@ -114,6 +114,8 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
 	TOKEN_KIND(Token_cast,                   "cast"),                   \
 	TOKEN_KIND(Token_transmute,              "transmute"),              \
 	TOKEN_KIND(Token_using,                  "using"),                  \
+	TOKEN_KIND(Token_inline,                 "inline"),                 \
+	TOKEN_KIND(Token_no_inline,              "no_inline"),              \
 	TOKEN_KIND(Token_context,                "context"),                \
 	TOKEN_KIND(Token_push_context,           "push_context"),           \
 	TOKEN_KIND(Token_push_allocator,         "push_allocator"),         \

+ 7 - 4
src/types.cpp

@@ -28,6 +28,7 @@ enum BasicKind {
 
 	Basic_int,
 	Basic_uint,
+	Basic_uintptr,
 	Basic_rawptr,
 	Basic_string, // ^u8 + int
 	Basic_any,    // ^Type_Info + rawptr
@@ -254,6 +255,7 @@ gb_global Type basic_types[] = {
 
 	{Type_Basic, {Basic_int,               BasicFlag_Integer,                         -1, STR_LIT("int")}},
 	{Type_Basic, {Basic_uint,              BasicFlag_Integer | BasicFlag_Unsigned,    -1, STR_LIT("uint")}},
+	{Type_Basic, {Basic_uintptr,           BasicFlag_Integer | BasicFlag_Unsigned,    -1, STR_LIT("uintptr")}},
 
 	{Type_Basic, {Basic_rawptr,            BasicFlag_Pointer,                         -1, STR_LIT("rawptr")}},
 	{Type_Basic, {Basic_string,            BasicFlag_String,                          -1, STR_LIT("string")}},
@@ -299,6 +301,7 @@ gb_global Type *t_complex128      = &basic_types[Basic_complex128];
 
 gb_global Type *t_int             = &basic_types[Basic_int];
 gb_global Type *t_uint            = &basic_types[Basic_uint];
+gb_global Type *t_uintptr         = &basic_types[Basic_uintptr];
 
 gb_global Type *t_rawptr          = &basic_types[Basic_rawptr];
 gb_global Type *t_string          = &basic_types[Basic_string];
@@ -745,9 +748,9 @@ bool is_type_tuple(Type *t) {
 }
 
 
-bool is_type_int_or_uint(Type *t) {
+bool is_type_uintptr(Type *t) {
 	if (t->kind == Type_Basic) {
-		return (t->Basic.kind == Basic_int) || (t->Basic.kind == Basic_uint);
+		return (t->Basic.kind == Basic_uintptr);
 	}
 	return false;
 }
@@ -1813,7 +1816,7 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 		case Basic_string: return build_context.word_size;
 		case Basic_any:    return build_context.word_size;
 
-		case Basic_int: case Basic_uint: case Basic_rawptr:
+		case Basic_int: case Basic_uint: case Basic_uintptr: case Basic_rawptr:
 			return build_context.word_size;
 
 		case Basic_complex64: case Basic_complex128:
@@ -2023,7 +2026,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 		case Basic_string: return 2*build_context.word_size;
 		case Basic_any:    return 2*build_context.word_size;
 
-		case Basic_int: case Basic_uint: case Basic_rawptr:
+		case Basic_int: case Basic_uint: case Basic_uintptr: case Basic_rawptr:
 			return build_context.word_size;
 		}
 	} break;