Browse Source

`foreign` blocks for procedures

Ginger Bill 8 years ago
parent
commit
ccda456c0a
16 changed files with 687 additions and 612 deletions
  1. 13 11
      core/_preload.odin
  2. 80 80
      core/bits.odin
  3. 14 11
      core/math.odin
  4. 5 5
      core/mem.odin
  5. 27 25
      core/opengl.odin
  6. 23 20
      core/os_linux.odin
  7. 23 20
      core/os_x.odin
  8. 18 16
      core/sys/wgl.odin
  9. 330 327
      core/sys/windows.odin
  10. 9 10
      src/check_decl.cpp
  11. 28 3
      src/checker.cpp
  12. 1 0
      src/entity.cpp
  13. 9 5
      src/ir.cpp
  14. 105 76
      src/parser.cpp
  15. 1 3
      src/ssa.cpp
  16. 1 0
      src/tokenizer.cpp

+ 13 - 11
core/_preload.odin

@@ -147,12 +147,12 @@ proc type_info_base_without_enum(info: ^TypeInfo) -> ^TypeInfo {
 
 
 
-proc assume(cond: bool) #foreign __llvm_core "llvm.assume";
-
-proc __debug_trap      ()        #foreign __llvm_core "llvm.debugtrap";
-proc __trap            ()        #foreign __llvm_core "llvm.trap";
-proc read_cycle_counter() -> u64 #foreign __llvm_core "llvm.readcyclecounter";
-
+foreign __llvm_core {
+	proc assume            (cond: bool) #link_name "llvm.assume";
+	proc __debug_trap      ()           #link_name "llvm.debugtrap";
+	proc __trap            ()           #link_name "llvm.trap";
+	proc read_cycle_counter() -> u64    #link_name "llvm.readcyclecounter";
+}
 
 // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
 type (
@@ -382,7 +382,7 @@ proc __string_decode_rune(s: string) -> (rune, int) #inline {
 
 
 proc __mem_set(data: rawptr, value: i32, len: int) -> rawptr {
-	proc llvm_memset_64bit(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memset.p0i8.i64";
+	foreign __llvm_core proc llvm_memset_64bit(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #link_name "llvm.memset.p0i8.i64";
 	llvm_memset_64bit(data, u8(value), len, 1, false);
 	return data;
 }
@@ -391,13 +391,13 @@ proc __mem_zero(data: rawptr, len: int) -> rawptr {
 }
 proc __mem_copy(dst, src: rawptr, len: int) -> rawptr {
 	// NOTE(bill): This _must_ be implemented like C's memmove
-	proc llvm_memmove_64bit(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memmove.p0i8.p0i8.i64";
+	foreign __llvm_core proc llvm_memmove_64bit(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memmove.p0i8.p0i8.i64";
 	llvm_memmove_64bit(dst, src, len, 1, false);
 	return dst;
 }
 proc __mem_copy_non_overlapping(dst, src: rawptr, len: int) -> rawptr {
 	// NOTE(bill): This _must_ be implemented like C's memcpy
-	proc llvm_memcpy_64bit(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memcpy.p0i8.p0i8.i64";
+	foreign __llvm_core proc llvm_memcpy_64bit(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i64";
 	llvm_memcpy_64bit(dst, src, len, 1, false);
 	return dst;
 }
@@ -414,8 +414,10 @@ proc __mem_compare(a, b: ^u8, n: int) -> int {
 	return 0;
 }
 
-proc __sqrt_f32(x: f32) -> f32 #foreign __llvm_core "llvm.sqrt.f32";
-proc __sqrt_f64(x: f64) -> f64 #foreign __llvm_core "llvm.sqrt.f64";
+foreign __llvm_core {
+	proc __sqrt_f32(x: f32) -> f32 #link_name "llvm.sqrt.f32";
+	proc __sqrt_f64(x: f64) -> f64 #link_name "llvm.sqrt.f64";
+}
 proc __abs_complex64(x: complex64) -> f32 #inline {
 	var r, i = real(x), imag(x);
 	return __sqrt_f32(r*r + i*i);

+ 80 - 80
core/bits.odin

@@ -24,16 +24,16 @@ const (
 	I128_MAX = i128(0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ffff);
 )
 
-proc count_ones(i:   u8) ->   u8 { proc __llvm_ctpop(u8)   ->   u8 #foreign __llvm_core "llvm.ctpop.i8";  return __llvm_ctpop(i); }
-proc count_ones(i:   i8) ->   i8 { proc __llvm_ctpop(i8)   ->   i8 #foreign __llvm_core "llvm.ctpop.i8";  return __llvm_ctpop(i); }
-proc count_ones(i:  u16) ->  u16 { proc __llvm_ctpop(u16)  ->  u16 #foreign __llvm_core "llvm.ctpop.i16"; return __llvm_ctpop(i); }
-proc count_ones(i:  i16) ->  i16 { proc __llvm_ctpop(i16)  ->  i16 #foreign __llvm_core "llvm.ctpop.i16"; return __llvm_ctpop(i); }
-proc count_ones(i:  u32) ->  u32 { proc __llvm_ctpop(u32)  ->  u32 #foreign __llvm_core "llvm.ctpop.i32"; return __llvm_ctpop(i); }
-proc count_ones(i:  i32) ->  i32 { proc __llvm_ctpop(i32)  ->  i32 #foreign __llvm_core "llvm.ctpop.i32"; return __llvm_ctpop(i); }
-proc count_ones(i:  u64) ->  u64 { proc __llvm_ctpop(u64)  ->  u64 #foreign __llvm_core "llvm.ctpop.i64"; return __llvm_ctpop(i); }
-proc count_ones(i:  i64) ->  i64 { proc __llvm_ctpop(i64)  ->  i64 #foreign __llvm_core "llvm.ctpop.i64"; return __llvm_ctpop(i); }
-proc count_ones(i: u128) -> u128 { proc __llvm_ctpop(u128) -> u128 #foreign __llvm_core "llvm.ctpop.i128";return __llvm_ctpop(i); }
-proc count_ones(i: i128) -> i128 { proc __llvm_ctpop(i128) -> i128 #foreign __llvm_core "llvm.ctpop.i128";return __llvm_ctpop(i); }
+proc count_ones(i:   u8) ->   u8 { foreign __llvm_core proc __llvm_ctpop(u8)   ->   u8 #link_name "llvm.ctpop.i8";  return __llvm_ctpop(i); }
+proc count_ones(i:   i8) ->   i8 { foreign __llvm_core proc __llvm_ctpop(i8)   ->   i8 #link_name "llvm.ctpop.i8";  return __llvm_ctpop(i); }
+proc count_ones(i:  u16) ->  u16 { foreign __llvm_core proc __llvm_ctpop(u16)  ->  u16 #link_name "llvm.ctpop.i16"; return __llvm_ctpop(i); }
+proc count_ones(i:  i16) ->  i16 { foreign __llvm_core proc __llvm_ctpop(i16)  ->  i16 #link_name "llvm.ctpop.i16"; return __llvm_ctpop(i); }
+proc count_ones(i:  u32) ->  u32 { foreign __llvm_core proc __llvm_ctpop(u32)  ->  u32 #link_name "llvm.ctpop.i32"; return __llvm_ctpop(i); }
+proc count_ones(i:  i32) ->  i32 { foreign __llvm_core proc __llvm_ctpop(i32)  ->  i32 #link_name "llvm.ctpop.i32"; return __llvm_ctpop(i); }
+proc count_ones(i:  u64) ->  u64 { foreign __llvm_core proc __llvm_ctpop(u64)  ->  u64 #link_name "llvm.ctpop.i64"; return __llvm_ctpop(i); }
+proc count_ones(i:  i64) ->  i64 { foreign __llvm_core proc __llvm_ctpop(i64)  ->  i64 #link_name "llvm.ctpop.i64"; return __llvm_ctpop(i); }
+proc count_ones(i: u128) -> u128 { foreign __llvm_core proc __llvm_ctpop(u128) -> u128 #link_name "llvm.ctpop.i128";return __llvm_ctpop(i); }
+proc count_ones(i: i128) -> i128 { foreign __llvm_core proc __llvm_ctpop(i128) -> i128 #link_name "llvm.ctpop.i128";return __llvm_ctpop(i); }
 proc count_ones(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(count_ones(u32(i))); } else { return uint(count_ones(u64(i))); } }
 proc count_ones(i:  int) ->  int { when size_of(int)  == size_of(i32) { return int(count_ones(i32(i)));  } else { return int(count_ones(i64(i))); } }
 
@@ -79,59 +79,59 @@ proc rotate_right(i: uint, s: uint) -> uint { when size_of(uint) == size_of(u32)
 proc rotate_right(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)); } }
 
 
-proc leading_zeros(i:   u8) ->   u8 { proc __llvm_ctlz(u8,   bool) ->   u8 #foreign __llvm_core "llvm.ctlz.i8";  return __llvm_ctlz(i, false); }
-proc leading_zeros(i:   i8) ->   i8 { proc __llvm_ctlz(i8,   bool) ->   i8 #foreign __llvm_core "llvm.ctlz.i8";  return __llvm_ctlz(i, false); }
-proc leading_zeros(i:  u16) ->  u16 { proc __llvm_ctlz(u16,  bool) ->  u16 #foreign __llvm_core "llvm.ctlz.i16"; return __llvm_ctlz(i, false); }
-proc leading_zeros(i:  i16) ->  i16 { proc __llvm_ctlz(i16,  bool) ->  i16 #foreign __llvm_core "llvm.ctlz.i16"; return __llvm_ctlz(i, false); }
-proc leading_zeros(i:  u32) ->  u32 { proc __llvm_ctlz(u32,  bool) ->  u32 #foreign __llvm_core "llvm.ctlz.i32"; return __llvm_ctlz(i, false); }
-proc leading_zeros(i:  i32) ->  i32 { proc __llvm_ctlz(i32,  bool) ->  i32 #foreign __llvm_core "llvm.ctlz.i32"; return __llvm_ctlz(i, false); }
-proc leading_zeros(i:  u64) ->  u64 { proc __llvm_ctlz(u64,  bool) ->  u64 #foreign __llvm_core "llvm.ctlz.i64"; return __llvm_ctlz(i, false); }
-proc leading_zeros(i:  i64) ->  i64 { proc __llvm_ctlz(i64,  bool) ->  i64 #foreign __llvm_core "llvm.ctlz.i64"; return __llvm_ctlz(i, false); }
-proc leading_zeros(i: u128) -> u128 { proc __llvm_ctlz(u128, bool) -> u128 #foreign __llvm_core "llvm.ctlz.i128";return __llvm_ctlz(i, false); }
-proc leading_zeros(i: i128) -> i128 { proc __llvm_ctlz(i128, bool) -> i128 #foreign __llvm_core "llvm.ctlz.i128";return __llvm_ctlz(i, false); }
+proc leading_zeros(i:   u8) ->   u8 { foreign __llvm_core proc __llvm_ctlz(u8,   bool) ->   u8 #link_name "llvm.ctlz.i8";  return __llvm_ctlz(i, false); }
+proc leading_zeros(i:   i8) ->   i8 { foreign __llvm_core proc __llvm_ctlz(i8,   bool) ->   i8 #link_name "llvm.ctlz.i8";  return __llvm_ctlz(i, false); }
+proc leading_zeros(i:  u16) ->  u16 { foreign __llvm_core proc __llvm_ctlz(u16,  bool) ->  u16 #link_name "llvm.ctlz.i16"; return __llvm_ctlz(i, false); }
+proc leading_zeros(i:  i16) ->  i16 { foreign __llvm_core proc __llvm_ctlz(i16,  bool) ->  i16 #link_name "llvm.ctlz.i16"; return __llvm_ctlz(i, false); }
+proc leading_zeros(i:  u32) ->  u32 { foreign __llvm_core proc __llvm_ctlz(u32,  bool) ->  u32 #link_name "llvm.ctlz.i32"; return __llvm_ctlz(i, false); }
+proc leading_zeros(i:  i32) ->  i32 { foreign __llvm_core proc __llvm_ctlz(i32,  bool) ->  i32 #link_name "llvm.ctlz.i32"; return __llvm_ctlz(i, false); }
+proc leading_zeros(i:  u64) ->  u64 { foreign __llvm_core proc __llvm_ctlz(u64,  bool) ->  u64 #link_name "llvm.ctlz.i64"; return __llvm_ctlz(i, false); }
+proc leading_zeros(i:  i64) ->  i64 { foreign __llvm_core proc __llvm_ctlz(i64,  bool) ->  i64 #link_name "llvm.ctlz.i64"; return __llvm_ctlz(i, false); }
+proc leading_zeros(i: u128) -> u128 { foreign __llvm_core proc __llvm_ctlz(u128, bool) -> u128 #link_name "llvm.ctlz.i128";return __llvm_ctlz(i, false); }
+proc leading_zeros(i: i128) -> i128 { foreign __llvm_core proc __llvm_ctlz(i128, bool) -> i128 #link_name "llvm.ctlz.i128";return __llvm_ctlz(i, false); }
 proc leading_zeros(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(leading_zeros(u32(i))); } else { return uint(leading_zeros(u64(i))); } }
 proc leading_zeros(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(leading_zeros(i32(i))); } else { return  int(leading_zeros(i64(i))); } }
 
-proc trailing_zeros(i:   u8) ->   u8 { proc __llvm_cttz(u8,   bool) ->   u8 #foreign __llvm_core "llvm.cttz.i8";  return __llvm_cttz(i, false); }
-proc trailing_zeros(i:   i8) ->   i8 { proc __llvm_cttz(i8,   bool) ->   i8 #foreign __llvm_core "llvm.cttz.i8";  return __llvm_cttz(i, false); }
-proc trailing_zeros(i:  u16) ->  u16 { proc __llvm_cttz(u16,  bool) ->  u16 #foreign __llvm_core "llvm.cttz.i16"; return __llvm_cttz(i, false); }
-proc trailing_zeros(i:  i16) ->  i16 { proc __llvm_cttz(i16,  bool) ->  i16 #foreign __llvm_core "llvm.cttz.i16"; return __llvm_cttz(i, false); }
-proc trailing_zeros(i:  u32) ->  u32 { proc __llvm_cttz(u32,  bool) ->  u32 #foreign __llvm_core "llvm.cttz.i32"; return __llvm_cttz(i, false); }
-proc trailing_zeros(i:  i32) ->  i32 { proc __llvm_cttz(i32,  bool) ->  i32 #foreign __llvm_core "llvm.cttz.i32"; return __llvm_cttz(i, false); }
-proc trailing_zeros(i:  u64) ->  u64 { proc __llvm_cttz(u64,  bool) ->  u64 #foreign __llvm_core "llvm.cttz.i64"; return __llvm_cttz(i, false); }
-proc trailing_zeros(i:  i64) ->  i64 { proc __llvm_cttz(i64,  bool) ->  i64 #foreign __llvm_core "llvm.cttz.i64"; return __llvm_cttz(i, false); }
-proc trailing_zeros(i: u128) -> u128 { proc __llvm_cttz(u128, bool) -> u128 #foreign __llvm_core "llvm.cttz.i128";return __llvm_cttz(i, false); }
-proc trailing_zeros(i: i128) -> i128 { proc __llvm_cttz(i128, bool) -> i128 #foreign __llvm_core "llvm.cttz.i128";return __llvm_cttz(i, false); }
+proc trailing_zeros(i:   u8) ->   u8 { foreign __llvm_core proc __llvm_cttz(u8,   bool) ->   u8 #link_name "llvm.cttz.i8";  return __llvm_cttz(i, false); }
+proc trailing_zeros(i:   i8) ->   i8 { foreign __llvm_core proc __llvm_cttz(i8,   bool) ->   i8 #link_name "llvm.cttz.i8";  return __llvm_cttz(i, false); }
+proc trailing_zeros(i:  u16) ->  u16 { foreign __llvm_core proc __llvm_cttz(u16,  bool) ->  u16 #link_name "llvm.cttz.i16"; return __llvm_cttz(i, false); }
+proc trailing_zeros(i:  i16) ->  i16 { foreign __llvm_core proc __llvm_cttz(i16,  bool) ->  i16 #link_name "llvm.cttz.i16"; return __llvm_cttz(i, false); }
+proc trailing_zeros(i:  u32) ->  u32 { foreign __llvm_core proc __llvm_cttz(u32,  bool) ->  u32 #link_name "llvm.cttz.i32"; return __llvm_cttz(i, false); }
+proc trailing_zeros(i:  i32) ->  i32 { foreign __llvm_core proc __llvm_cttz(i32,  bool) ->  i32 #link_name "llvm.cttz.i32"; return __llvm_cttz(i, false); }
+proc trailing_zeros(i:  u64) ->  u64 { foreign __llvm_core proc __llvm_cttz(u64,  bool) ->  u64 #link_name "llvm.cttz.i64"; return __llvm_cttz(i, false); }
+proc trailing_zeros(i:  i64) ->  i64 { foreign __llvm_core proc __llvm_cttz(i64,  bool) ->  i64 #link_name "llvm.cttz.i64"; return __llvm_cttz(i, false); }
+proc trailing_zeros(i: u128) -> u128 { foreign __llvm_core proc __llvm_cttz(u128, bool) -> u128 #link_name "llvm.cttz.i128";return __llvm_cttz(i, false); }
+proc trailing_zeros(i: i128) -> i128 { foreign __llvm_core proc __llvm_cttz(i128, bool) -> i128 #link_name "llvm.cttz.i128";return __llvm_cttz(i, false); }
 proc trailing_zeros(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(trailing_zeros(u32(i))); } else { return uint(trailing_zeros(u64(i))); } }
 proc trailing_zeros(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(trailing_zeros(i32(i))); } else { return  int(trailing_zeros(i64(i))); } }
 
 
-proc reverse_bits(i:   u8) ->   u8 { proc __llvm_bitreverse(u8)   ->   u8 #foreign __llvm_core "llvm.bitreverse.i8";  return __llvm_bitreverse(i); }
-proc reverse_bits(i:   i8) ->   i8 { proc __llvm_bitreverse(i8)   ->   i8 #foreign __llvm_core "llvm.bitreverse.i8";  return __llvm_bitreverse(i); }
-proc reverse_bits(i:  u16) ->  u16 { proc __llvm_bitreverse(u16)  ->  u16 #foreign __llvm_core "llvm.bitreverse.i16"; return __llvm_bitreverse(i); }
-proc reverse_bits(i:  i16) ->  i16 { proc __llvm_bitreverse(i16)  ->  i16 #foreign __llvm_core "llvm.bitreverse.i16"; return __llvm_bitreverse(i); }
-proc reverse_bits(i:  u32) ->  u32 { proc __llvm_bitreverse(u32)  ->  u32 #foreign __llvm_core "llvm.bitreverse.i32"; return __llvm_bitreverse(i); }
-proc reverse_bits(i:  i32) ->  i32 { proc __llvm_bitreverse(i32)  ->  i32 #foreign __llvm_core "llvm.bitreverse.i32"; return __llvm_bitreverse(i); }
-proc reverse_bits(i:  u64) ->  u64 { proc __llvm_bitreverse(u64)  ->  u64 #foreign __llvm_core "llvm.bitreverse.i64"; return __llvm_bitreverse(i); }
-proc reverse_bits(i:  i64) ->  i64 { proc __llvm_bitreverse(i64)  ->  i64 #foreign __llvm_core "llvm.bitreverse.i64"; return __llvm_bitreverse(i); }
-proc reverse_bits(i: u128) -> u128 { proc __llvm_bitreverse(u128) -> u128 #foreign __llvm_core "llvm.bitreverse.i128";return __llvm_bitreverse(i); }
-proc reverse_bits(i: i128) -> i128 { proc __llvm_bitreverse(i128) -> i128 #foreign __llvm_core "llvm.bitreverse.i128";return __llvm_bitreverse(i); }
+proc reverse_bits(i:   u8) ->   u8 { foreign __llvm_core proc __llvm_bitreverse(u8)   ->   u8 #link_name "llvm.bitreverse.i8";  return __llvm_bitreverse(i); }
+proc reverse_bits(i:   i8) ->   i8 { foreign __llvm_core proc __llvm_bitreverse(i8)   ->   i8 #link_name "llvm.bitreverse.i8";  return __llvm_bitreverse(i); }
+proc reverse_bits(i:  u16) ->  u16 { foreign __llvm_core proc __llvm_bitreverse(u16)  ->  u16 #link_name "llvm.bitreverse.i16"; return __llvm_bitreverse(i); }
+proc reverse_bits(i:  i16) ->  i16 { foreign __llvm_core proc __llvm_bitreverse(i16)  ->  i16 #link_name "llvm.bitreverse.i16"; return __llvm_bitreverse(i); }
+proc reverse_bits(i:  u32) ->  u32 { foreign __llvm_core proc __llvm_bitreverse(u32)  ->  u32 #link_name "llvm.bitreverse.i32"; return __llvm_bitreverse(i); }
+proc reverse_bits(i:  i32) ->  i32 { foreign __llvm_core proc __llvm_bitreverse(i32)  ->  i32 #link_name "llvm.bitreverse.i32"; return __llvm_bitreverse(i); }
+proc reverse_bits(i:  u64) ->  u64 { foreign __llvm_core proc __llvm_bitreverse(u64)  ->  u64 #link_name "llvm.bitreverse.i64"; return __llvm_bitreverse(i); }
+proc reverse_bits(i:  i64) ->  i64 { foreign __llvm_core proc __llvm_bitreverse(i64)  ->  i64 #link_name "llvm.bitreverse.i64"; return __llvm_bitreverse(i); }
+proc reverse_bits(i: u128) -> u128 { foreign __llvm_core proc __llvm_bitreverse(u128) -> u128 #link_name "llvm.bitreverse.i128";return __llvm_bitreverse(i); }
+proc reverse_bits(i: i128) -> i128 { foreign __llvm_core proc __llvm_bitreverse(i128) -> i128 #link_name "llvm.bitreverse.i128";return __llvm_bitreverse(i); }
 proc reverse_bits(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(reverse_bits(u32(i))); } else { return uint(reverse_bits(u64(i))); } }
 proc reverse_bits(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(reverse_bits(i32(i))); } else { return  int(reverse_bits(i64(i))); } }
 
-
-proc byte_swap(u16)  ->  u16 #foreign __llvm_core "llvm.bswap.i16";
-proc byte_swap(i16)  ->  i16 #foreign __llvm_core "llvm.bswap.i16";
-proc byte_swap(u32)  ->  u32 #foreign __llvm_core "llvm.bswap.i32";
-proc byte_swap(i32)  ->  i32 #foreign __llvm_core "llvm.bswap.i32";
-proc byte_swap(u64)  ->  u64 #foreign __llvm_core "llvm.bswap.i64";
-proc byte_swap(i64)  ->  i64 #foreign __llvm_core "llvm.bswap.i64";
-proc byte_swap(u128) -> u128 #foreign __llvm_core "llvm.bswap.i128";
-proc byte_swap(i128) -> i128 #foreign __llvm_core "llvm.bswap.i128";
+foreign __llvm_core {
+proc byte_swap(u16)  ->  u16 #link_name "llvm.bswap.i16";
+proc byte_swap(i16)  ->  i16 #link_name "llvm.bswap.i16";
+proc byte_swap(u32)  ->  u32 #link_name "llvm.bswap.i32";
+proc byte_swap(i32)  ->  i32 #link_name "llvm.bswap.i32";
+proc byte_swap(u64)  ->  u64 #link_name "llvm.bswap.i64";
+proc byte_swap(i64)  ->  i64 #link_name "llvm.bswap.i64";
+proc byte_swap(u128) -> u128 #link_name "llvm.bswap.i128";
+proc byte_swap(i128) -> i128 #link_name "llvm.bswap.i128";
+}
 proc byte_swap(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(byte_swap(u32(i))); } else { return uint(byte_swap(u64(i))); } }
 proc byte_swap(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(byte_swap(i32(i))); } else { return  int(byte_swap(i64(i))); } }
 
-
 proc from_be(i:   u8) ->   u8 { return i; }
 proc from_be(i:   i8) ->   i8 { return i; }
 proc from_be(i:  u16) ->  u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
@@ -186,16 +186,16 @@ proc to_le(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else {
 proc to_le(i:  int) ->  int { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
 
 
-proc overflowing_add(lhs, rhs:   u8) -> (u8, bool)   { proc op(u8, u8)     -> (u8, bool)   #foreign __llvm_core "llvm.uadd.with.overflow.i8";   return op(lhs, rhs); }
-proc overflowing_add(lhs, rhs:   i8) -> (i8, bool)   { proc op(i8, i8)     -> (i8, bool)   #foreign __llvm_core "llvm.sadd.with.overflow.i8";   return op(lhs, rhs); }
-proc overflowing_add(lhs, rhs:  u16) -> (u16, bool)  { proc op(u16, u16)   -> (u16, bool)  #foreign __llvm_core "llvm.uadd.with.overflow.i16";  return op(lhs, rhs); }
-proc overflowing_add(lhs, rhs:  i16) -> (i16, bool)  { proc op(i16, i16)   -> (i16, bool)  #foreign __llvm_core "llvm.sadd.with.overflow.i16";  return op(lhs, rhs); }
-proc overflowing_add(lhs, rhs:  u32) -> (u32, bool)  { proc op(u32, u32)   -> (u32, bool)  #foreign __llvm_core "llvm.uadd.with.overflow.i32";  return op(lhs, rhs); }
-proc overflowing_add(lhs, rhs:  i32) -> (i32, bool)  { proc op(i32, i32)   -> (i32, bool)  #foreign __llvm_core "llvm.sadd.with.overflow.i32";  return op(lhs, rhs); }
-proc overflowing_add(lhs, rhs:  u64) -> (u64, bool)  { proc op(u64, u64)   -> (u64, bool)  #foreign __llvm_core "llvm.uadd.with.overflow.i64";  return op(lhs, rhs); }
-proc overflowing_add(lhs, rhs:  i64) -> (i64, bool)  { proc op(i64, i64)   -> (i64, bool)  #foreign __llvm_core "llvm.sadd.with.overflow.i64";  return op(lhs, rhs); }
-proc overflowing_add(lhs, rhs: u128) -> (u128, bool) { proc op(u128, u128) -> (u128, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i128"; return op(lhs, rhs); }
-proc overflowing_add(lhs, rhs: i128) -> (i128, bool) { proc op(i128, i128) -> (i128, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i128"; return op(lhs, rhs); }
+proc overflowing_add(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core proc op(u8, u8)     -> (u8, bool)   #link_name "llvm.uadd.with.overflow.i8";   return op(lhs, rhs); }
+proc overflowing_add(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core proc op(i8, i8)     -> (i8, bool)   #link_name "llvm.sadd.with.overflow.i8";   return op(lhs, rhs); }
+proc overflowing_add(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core proc op(u16, u16)   -> (u16, bool)  #link_name "llvm.uadd.with.overflow.i16";  return op(lhs, rhs); }
+proc overflowing_add(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core proc op(i16, i16)   -> (i16, bool)  #link_name "llvm.sadd.with.overflow.i16";  return op(lhs, rhs); }
+proc overflowing_add(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core proc op(u32, u32)   -> (u32, bool)  #link_name "llvm.uadd.with.overflow.i32";  return op(lhs, rhs); }
+proc overflowing_add(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core proc op(i32, i32)   -> (i32, bool)  #link_name "llvm.sadd.with.overflow.i32";  return op(lhs, rhs); }
+proc overflowing_add(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core proc op(u64, u64)   -> (u64, bool)  #link_name "llvm.uadd.with.overflow.i64";  return op(lhs, rhs); }
+proc overflowing_add(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core proc op(i64, i64)   -> (i64, bool)  #link_name "llvm.sadd.with.overflow.i64";  return op(lhs, rhs); }
+proc overflowing_add(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core proc op(u128, u128) -> (u128, bool) #link_name "llvm.uadd.with.overflow.i128"; return op(lhs, rhs); }
+proc overflowing_add(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core proc op(i128, i128) -> (i128, bool) #link_name "llvm.sadd.with.overflow.i128"; return op(lhs, rhs); }
 proc overflowing_add(lhs, rhs: uint) -> (uint, bool) {
 	when size_of(uint) == size_of(u32) {
 		var x, ok = overflowing_add(u32(lhs), u32(rhs));
@@ -215,16 +215,16 @@ proc overflowing_add(lhs, rhs: int) -> (int, bool) {
 	}
 }
 
-proc overflowing_sub(lhs, rhs:   u8) -> (u8, bool)   { proc op(u8, u8)     -> (u8, bool)   #foreign __llvm_core "llvm.usub.with.overflow.i8";   return op(lhs, rhs); }
-proc overflowing_sub(lhs, rhs:   i8) -> (i8, bool)   { proc op(i8, i8)     -> (i8, bool)   #foreign __llvm_core "llvm.ssub.with.overflow.i8";   return op(lhs, rhs); }
-proc overflowing_sub(lhs, rhs:  u16) -> (u16, bool)  { proc op(u16, u16)   -> (u16, bool)  #foreign __llvm_core "llvm.usub.with.overflow.i16";  return op(lhs, rhs); }
-proc overflowing_sub(lhs, rhs:  i16) -> (i16, bool)  { proc op(i16, i16)   -> (i16, bool)  #foreign __llvm_core "llvm.ssub.with.overflow.i16";  return op(lhs, rhs); }
-proc overflowing_sub(lhs, rhs:  u32) -> (u32, bool)  { proc op(u32, u32)   -> (u32, bool)  #foreign __llvm_core "llvm.usub.with.overflow.i32";  return op(lhs, rhs); }
-proc overflowing_sub(lhs, rhs:  i32) -> (i32, bool)  { proc op(i32, i32)   -> (i32, bool)  #foreign __llvm_core "llvm.ssub.with.overflow.i32";  return op(lhs, rhs); }
-proc overflowing_sub(lhs, rhs:  u64) -> (u64, bool)  { proc op(u64, u64)   -> (u64, bool)  #foreign __llvm_core "llvm.usub.with.overflow.i64";  return op(lhs, rhs); }
-proc overflowing_sub(lhs, rhs:  i64) -> (i64, bool)  { proc op(i64, i64)   -> (i64, bool)  #foreign __llvm_core "llvm.ssub.with.overflow.i64";  return op(lhs, rhs); }
-proc overflowing_sub(lhs, rhs: u128) -> (u128, bool) { proc op(u128, u128) -> (u128, bool) #foreign __llvm_core "llvm.usub.with.overflow.i128"; return op(lhs, rhs); }
-proc overflowing_sub(lhs, rhs: i128) -> (i128, bool) { proc op(i128, i128) -> (i128, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i128"; return op(lhs, rhs); }
+proc overflowing_sub(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core proc op(u8, u8)     -> (u8, bool)   #link_name "llvm.usub.with.overflow.i8";   return op(lhs, rhs); }
+proc overflowing_sub(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core proc op(i8, i8)     -> (i8, bool)   #link_name "llvm.ssub.with.overflow.i8";   return op(lhs, rhs); }
+proc overflowing_sub(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core proc op(u16, u16)   -> (u16, bool)  #link_name "llvm.usub.with.overflow.i16";  return op(lhs, rhs); }
+proc overflowing_sub(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core proc op(i16, i16)   -> (i16, bool)  #link_name "llvm.ssub.with.overflow.i16";  return op(lhs, rhs); }
+proc overflowing_sub(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core proc op(u32, u32)   -> (u32, bool)  #link_name "llvm.usub.with.overflow.i32";  return op(lhs, rhs); }
+proc overflowing_sub(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core proc op(i32, i32)   -> (i32, bool)  #link_name "llvm.ssub.with.overflow.i32";  return op(lhs, rhs); }
+proc overflowing_sub(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core proc op(u64, u64)   -> (u64, bool)  #link_name "llvm.usub.with.overflow.i64";  return op(lhs, rhs); }
+proc overflowing_sub(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core proc op(i64, i64)   -> (i64, bool)  #link_name "llvm.ssub.with.overflow.i64";  return op(lhs, rhs); }
+proc overflowing_sub(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core proc op(u128, u128) -> (u128, bool) #link_name "llvm.usub.with.overflow.i128"; return op(lhs, rhs); }
+proc overflowing_sub(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core proc op(i128, i128) -> (i128, bool) #link_name "llvm.ssub.with.overflow.i128"; return op(lhs, rhs); }
 proc overflowing_sub(lhs, rhs: uint) -> (uint, bool) {
 	when size_of(uint) == size_of(u32) {
 		var x, ok = overflowing_sub(u32(lhs), u32(rhs));
@@ -244,16 +244,16 @@ proc overflowing_sub(lhs, rhs: int) -> (int, bool) {
 	}
 }
 
-proc overflowing_mul(lhs, rhs:   u8) -> (u8, bool)   { proc op(u8, u8)     -> (u8, bool)   #foreign __llvm_core "llvm.umul.with.overflow.i8";   return op(lhs, rhs); }
-proc overflowing_mul(lhs, rhs:   i8) -> (i8, bool)   { proc op(i8, i8)     -> (i8, bool)   #foreign __llvm_core "llvm.smul.with.overflow.i8";   return op(lhs, rhs); }
-proc overflowing_mul(lhs, rhs:  u16) -> (u16, bool)  { proc op(u16, u16)   -> (u16, bool)  #foreign __llvm_core "llvm.umul.with.overflow.i16";  return op(lhs, rhs); }
-proc overflowing_mul(lhs, rhs:  i16) -> (i16, bool)  { proc op(i16, i16)   -> (i16, bool)  #foreign __llvm_core "llvm.smul.with.overflow.i16";  return op(lhs, rhs); }
-proc overflowing_mul(lhs, rhs:  u32) -> (u32, bool)  { proc op(u32, u32)   -> (u32, bool)  #foreign __llvm_core "llvm.umul.with.overflow.i32";  return op(lhs, rhs); }
-proc overflowing_mul(lhs, rhs:  i32) -> (i32, bool)  { proc op(i32, i32)   -> (i32, bool)  #foreign __llvm_core "llvm.smul.with.overflow.i32";  return op(lhs, rhs); }
-proc overflowing_mul(lhs, rhs:  u64) -> (u64, bool)  { proc op(u64, u64)   -> (u64, bool)  #foreign __llvm_core "llvm.umul.with.overflow.i64";  return op(lhs, rhs); }
-proc overflowing_mul(lhs, rhs:  i64) -> (i64, bool)  { proc op(i64, i64)   -> (i64, bool)  #foreign __llvm_core "llvm.smul.with.overflow.i64";  return op(lhs, rhs); }
-proc overflowing_mul(lhs, rhs: u128) -> (u128, bool) { proc op(u128, u128) -> (u128, bool) #foreign __llvm_core "llvm.umul.with.overflow.i128"; return op(lhs, rhs); }
-proc overflowing_mul(lhs, rhs: i128) -> (i128, bool) { proc op(i128, i128) -> (i128, bool) #foreign __llvm_core "llvm.smul.with.overflow.i128"; return op(lhs, rhs); }
+proc overflowing_mul(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core proc op(u8, u8)     -> (u8, bool)   #link_name "llvm.umul.with.overflow.i8";   return op(lhs, rhs); }
+proc overflowing_mul(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core proc op(i8, i8)     -> (i8, bool)   #link_name "llvm.smul.with.overflow.i8";   return op(lhs, rhs); }
+proc overflowing_mul(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core proc op(u16, u16)   -> (u16, bool)  #link_name "llvm.umul.with.overflow.i16";  return op(lhs, rhs); }
+proc overflowing_mul(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core proc op(i16, i16)   -> (i16, bool)  #link_name "llvm.smul.with.overflow.i16";  return op(lhs, rhs); }
+proc overflowing_mul(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core proc op(u32, u32)   -> (u32, bool)  #link_name "llvm.umul.with.overflow.i32";  return op(lhs, rhs); }
+proc overflowing_mul(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core proc op(i32, i32)   -> (i32, bool)  #link_name "llvm.smul.with.overflow.i32";  return op(lhs, rhs); }
+proc overflowing_mul(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core proc op(u64, u64)   -> (u64, bool)  #link_name "llvm.umul.with.overflow.i64";  return op(lhs, rhs); }
+proc overflowing_mul(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core proc op(i64, i64)   -> (i64, bool)  #link_name "llvm.smul.with.overflow.i64";  return op(lhs, rhs); }
+proc overflowing_mul(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core proc op(u128, u128) -> (u128, bool) #link_name "llvm.umul.with.overflow.i128"; return op(lhs, rhs); }
+proc overflowing_mul(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core proc op(i128, i128) -> (i128, bool) #link_name "llvm.smul.with.overflow.i128"; return op(lhs, rhs); }
 proc overflowing_mul(lhs, rhs: uint) -> (uint, bool) {
 	when size_of(uint) == size_of(u32) {
 		var x, ok = overflowing_mul(u32(lhs), u32(rhs));

+ 14 - 11
core/math.odin

@@ -30,21 +30,26 @@ type (
 	Complex complex64;
 )
 
-proc sqrt(x: f32) -> f32 #foreign __llvm_core "llvm.sqrt.f32";
-proc sqrt(x: f64) -> f64 #foreign __llvm_core "llvm.sqrt.f64";
+foreign __llvm_core {
+	proc sqrt(x: f32) -> f32          #link_name "llvm.sqrt.f32";
+	proc sqrt(x: f64) -> f64          #link_name "llvm.sqrt.f64";
 
-proc sin (θ: f32) -> f32 #foreign __llvm_core "llvm.sin.f32";
-proc sin (θ: f64) -> f64 #foreign __llvm_core "llvm.sin.f64";
+	proc sin (θ: f32) -> f32          #link_name "llvm.sin.f32";
+	proc sin (θ: f64) -> f64          #link_name "llvm.sin.f64";
 
-proc cos (θ: f32) -> f32 #foreign __llvm_core "llvm.cos.f32";
-proc cos (θ: f64) -> f64 #foreign __llvm_core "llvm.cos.f64";
+	proc cos (θ: f32) -> f32          #link_name "llvm.cos.f32";
+	proc cos (θ: f64) -> f64          #link_name "llvm.cos.f64";
+
+	proc pow (x, power: f32) -> f32   #link_name "llvm.pow.f32";
+	proc pow (x, power: f64) -> f64   #link_name "llvm.pow.f64";
+
+	proc fmuladd(a, b, c: f32) -> f32 #link_name "llvm.fmuladd.f32";
+	proc fmuladd(a, b, c: f64) -> f64 #link_name "llvm.fmuladd.f64";
+}
 
 proc tan (θ: f32) -> f32 #inline { return sin(θ)/cos(θ); }
 proc tan (θ: f64) -> f64 #inline { return sin(θ)/cos(θ); }
 
-proc pow (x, power: f32) -> f32 #foreign __llvm_core "llvm.pow.f32";
-proc pow (x, power: f64) -> f64 #foreign __llvm_core "llvm.pow.f64";
-
 
 proc lerp  (a, b, t: f32) -> (x: f32) { return a*(1-t) + b*t; }
 proc lerp  (a, b, t: f64) -> (x: f64) { return a*(1-t) + b*t; }
@@ -55,8 +60,6 @@ proc unlerp(a, b, x: f64) -> (t: f64) { return (x-a)/(b-a); }
 proc sign(x: f32) -> f32 { return x >= 0 ? +1 : -1; }
 proc sign(x: f64) -> f64 { return x >= 0 ? +1 : -1; }
 
-proc fmuladd(a, b, c: f32) -> f32 #foreign __llvm_core "llvm.fmuladd.f32";
-proc fmuladd(a, b, c: f64) -> f64 #foreign __llvm_core "llvm.fmuladd.f64";
 
 
 proc copy_sign(x, y: f32) -> f32 {

+ 5 - 5
core/mem.odin

@@ -2,11 +2,11 @@ import (
 	"fmt.odin";
 	"os.odin";
 )
-
-proc swap(b: u16) -> u16 #foreign __llvm_core "llvm.bswap.i16";
-proc swap(b: u32) -> u32 #foreign __llvm_core "llvm.bswap.i32";
-proc swap(b: u64) -> u64 #foreign __llvm_core "llvm.bswap.i64";
-
+foreign __llvm_core {
+	proc swap(b: u16) -> u16 #link_name "llvm.bswap.i16";
+	proc swap(b: u32) -> u32 #link_name "llvm.bswap.i32";
+	proc swap(b: u64) -> u64 #link_name "llvm.bswap.i64";
+}
 
 proc set(data: rawptr, value: i32, len: int) -> rawptr {
 	return __mem_set(data, value, len);

+ 27 - 25
core/opengl.odin

@@ -8,31 +8,33 @@ import (
 )
 import_load "opengl_constants.odin";
 
-proc Clear         (mask: u32)                                #foreign lib "glClear";
-proc ClearColor    (r, g, b, a: f32)                          #foreign lib "glClearColor";
-proc Begin         (mode: i32)                                #foreign lib "glBegin";
-proc End           ()                                         #foreign lib "glEnd";
-proc Finish        ()                                         #foreign lib "glFinish";
-proc BlendFunc     (sfactor, dfactor: i32)                    #foreign lib "glBlendFunc";
-proc Enable        (cap: i32)                                 #foreign lib "glEnable";
-proc Disable       (cap: i32)                                 #foreign lib "glDisable";
-proc GenTextures   (count: i32, result: ^u32)                 #foreign lib "glGenTextures";
-proc DeleteTextures(count: i32, result: ^u32)                 #foreign lib "glDeleteTextures";
-proc TexParameteri (target, pname, param: i32)                #foreign lib "glTexParameteri";
-proc TexParameterf (target: i32, pname: i32, param: f32)      #foreign lib "glTexParameterf";
-proc BindTexture   (target: i32, texture: u32)                #foreign lib "glBindTexture";
-proc LoadIdentity  ()                                         #foreign lib "glLoadIdentity";
-proc Viewport      (x, y, width, height: i32)                 #foreign lib "glViewport";
-proc Ortho         (left, right, bottom, top, near, far: f64) #foreign lib "glOrtho";
-proc Color3f       (r, g, b: f32)                             #foreign lib "glColor3f";
-proc Vertex3f      (x, y, z: f32)                             #foreign lib "glVertex3f";
-proc GetError      () -> i32                                  #foreign lib "glGetError";
-proc GetString     (name: i32) -> ^u8                         #foreign lib "glGetString";
-proc GetIntegerv   (name: i32, v: ^i32)                       #foreign lib "glGetIntegerv";
-proc TexCoord2f    (x, y: f32)                                #foreign lib "glTexCoord2f";
-proc TexImage2D    (target, level, internal_format,
-                    width, height, border,
-                    format, type_: i32, pixels: rawptr)       #foreign lib "glTexImage2D";
+foreign lib {
+	proc Clear         (mask: u32)                                #link_name "glClear";
+	proc ClearColor    (r, g, b, a: f32)                          #link_name "glClearColor";
+	proc Begin         (mode: i32)                                #link_name "glBegin";
+	proc End           ()                                         #link_name "glEnd";
+	proc Finish        ()                                         #link_name "glFinish";
+	proc BlendFunc     (sfactor, dfactor: i32)                    #link_name "glBlendFunc";
+	proc Enable        (cap: i32)                                 #link_name "glEnable";
+	proc Disable       (cap: i32)                                 #link_name "glDisable";
+	proc GenTextures   (count: i32, result: ^u32)                 #link_name "glGenTextures";
+	proc DeleteTextures(count: i32, result: ^u32)                 #link_name "glDeleteTextures";
+	proc TexParameteri (target, pname, param: i32)                #link_name "glTexParameteri";
+	proc TexParameterf (target: i32, pname: i32, param: f32)      #link_name "glTexParameterf";
+	proc BindTexture   (target: i32, texture: u32)                #link_name "glBindTexture";
+	proc LoadIdentity  ()                                         #link_name "glLoadIdentity";
+	proc Viewport      (x, y, width, height: i32)                 #link_name "glViewport";
+	proc Ortho         (left, right, bottom, top, near, far: f64) #link_name "glOrtho";
+	proc Color3f       (r, g, b: f32)                             #link_name "glColor3f";
+	proc Vertex3f      (x, y, z: f32)                             #link_name "glVertex3f";
+	proc GetError      () -> i32                                  #link_name "glGetError";
+	proc GetString     (name: i32) -> ^u8                         #link_name "glGetString";
+	proc GetIntegerv   (name: i32, v: ^i32)                       #link_name "glGetIntegerv";
+	proc TexCoord2f    (x, y: f32)                                #link_name "glTexCoord2f";
+	proc TexImage2D    (target, level, internal_format,
+	                    width, height, border,
+	                    format, type_: i32, pixels: rawptr)       #link_name "glTexImage2D";
+}
 
 
 proc _string_data(s: string) -> ^u8 #inline { return &s[0]; }

+ 23 - 20
core/os_linux.odin

@@ -125,26 +125,29 @@ const (
 	F_OK = 0; // Test for file existance
 )
 
-proc _unix_open  (path: ^u8, mode: int) -> Handle                               #foreign libc "open";
-proc _unix_close (fd: Handle) -> i32                                            #foreign libc "close";
-proc _unix_read  (fd: Handle, buf: rawptr, size: int) -> int                    #foreign libc "read";
-proc _unix_write (fd: Handle, buf: rawptr, size: int) -> int                    #foreign libc "write";
-proc _unix_seek  (fd: Handle, offset: i64, whence: i32) -> i64                  #foreign libc "lseek64";
-proc _unix_gettid() -> u64                                                      #foreign libc "gettid";
-proc _unix_stat  (path: ^u8, stat: ^Stat) -> i32                                #foreign libc "stat";
-proc _unix_access(path: ^u8, mask: int) -> i32                                  #foreign libc "access";
-
-proc _unix_malloc (size: int) -> rawptr                                         #foreign libc "malloc";
-proc _unix_free   (ptr: rawptr)                                                 #foreign libc "free";
-proc _unix_realloc(ptr: rawptr, size: int) -> rawptr                            #foreign libc "realloc";
-proc _unix_getenv (^u8) -> ^u8                                                  #foreign libc "getenv";
-
-proc _unix_exit(status: int)                                                    #foreign libc "exit";
-
-proc _unix_dlopen (filename: ^u8, flags: int) -> rawptr                         #foreign dl   "dlopen";
-proc _unix_dlsym  (handle: rawptr, symbol: ^u8) ->  (proc() #cc_c)              #foreign dl   "dlsym";
-proc _unix_dlclose(handle: rawptr) -> int                                       #foreign dl   "dlclose";
-proc _unix_dlerror() -> ^u8                                                     #foreign dl   "dlerror";
+foreign libc {
+	proc _unix_open  (path: ^u8, mode: int) -> Handle                  #link_name "open";
+	proc _unix_close (fd: Handle) -> i32                               #link_name "close";
+	proc _unix_read  (fd: Handle, buf: rawptr, size: int) -> int       #link_name "read";
+	proc _unix_write (fd: Handle, buf: rawptr, size: int) -> int       #link_name "write";
+	proc _unix_seek  (fd: Handle, offset: i64, whence: i32) -> i64     #link_name "lseek64";
+	proc _unix_gettid() -> u64                                         #link_name "gettid";
+	proc _unix_stat  (path: ^u8, stat: ^Stat) -> i32                   #link_name "stat";
+	proc _unix_access(path: ^u8, mask: int) -> i32                     #link_name "access";
+
+	proc _unix_malloc (size: int) -> rawptr                            #link_name "malloc";
+	proc _unix_free   (ptr: rawptr)                                    #link_name "free";
+	proc _unix_realloc(ptr: rawptr, size: int) -> rawptr               #link_name "realloc";
+	proc _unix_getenv (^u8) -> ^u8                                     #link_name "getenv";
+
+	proc _unix_exit(status: int)                                       #link_name "exit";
+}
+foreign dl {
+	proc _unix_dlopen (filename: ^u8, flags: int) -> rawptr            #link_name "dlopen";
+	proc _unix_dlsym  (handle: rawptr, symbol: ^u8) ->  (proc() #cc_c) #link_name "dlsym";
+	proc _unix_dlclose(handle: rawptr) -> int                          #link_name "dlclose";
+	proc _unix_dlerror() -> ^u8                                        #link_name "dlerror";
+}
 
 // TODO(zangent): Change this to just `open` when Bill fixes overloading.
 proc open_simple(path: string, mode: int) -> (Handle, Errno) {

+ 23 - 20
core/os_x.odin

@@ -125,27 +125,30 @@ const (
 	F_OK = 0; // Test for file existance
 )
 
-proc unix_open  (path: ^u8, mode: int) -> Handle                               #foreign libc "open";
-proc unix_close (handle: Handle)                                               #foreign libc "close";
-proc unix_read  (handle: Handle, buffer: rawptr, count: int) -> AddressSize    #foreign libc "read";
-proc unix_write (handle: Handle, buffer: rawptr, count: int) -> AddressSize    #foreign libc "write";
-proc unix_lseek (fs: Handle, offset: AddressSize, whence: int) -> AddressSize  #foreign libc "lseek";
-proc unix_gettid() -> u64                                                      #foreign libc "gettid";
-proc unix_stat  (path: ^u8, stat: ^Stat) -> int                                #foreign libc "stat";
-proc unix_access(path: ^u8, mask: int) -> int                                  #foreign libc "access";
-
-proc unix_malloc (size: int) -> rawptr                                         #foreign libc "malloc";
-proc unix_free   (ptr: rawptr)                                                 #foreign libc "free";
-proc unix_realloc(ptr: rawptr, size: int) -> rawptr                            #foreign libc "realloc";
-proc unix_getenv (^u8) -> ^u8                                                  #foreign libc "getenv";
-
-proc unix_exit(status: int)                                                    #foreign libc "exit";
-
-proc unix_dlopen (filename: ^u8, flags: int) -> rawptr                         #foreign dl   "dlopen";
-proc unix_dlsym  (handle: rawptr, symbol: ^u8) ->  (proc() #cc_c)              #foreign dl   "dlsym";
-proc unix_dlclose(handle: rawptr) -> int                                       #foreign dl   "dlclose";
-proc unix_dlerror() -> ^u8                                                     #foreign dl   "dlerror";
+foreign libc {
+	proc unix_open  (path: ^u8, mode: int) -> Handle                               #link_name "open";
+	proc unix_close (handle: Handle)                                               #link_name "close";
+	proc unix_read  (handle: Handle, buffer: rawptr, count: int) -> AddressSize    #link_name "read";
+	proc unix_write (handle: Handle, buffer: rawptr, count: int) -> AddressSize    #link_name "write";
+	proc unix_lseek (fs: Handle, offset: AddressSize, whence: int) -> AddressSize  #link_name "lseek";
+	proc unix_gettid() -> u64                                                      #link_name "gettid";
+	proc unix_stat  (path: ^u8, stat: ^Stat) -> int                                #link_name "stat";
+	proc unix_access(path: ^u8, mask: int) -> int                                  #link_name "access";
+
+	proc unix_malloc (size: int) -> rawptr                                         #link_name "malloc";
+	proc unix_free   (ptr: rawptr)                                                 #link_name "free";
+	proc unix_realloc(ptr: rawptr, size: int) -> rawptr                            #link_name "realloc";
+	proc unix_getenv (^u8) -> ^u8                                                  #link_name "getenv";
+
+	proc unix_exit(status: int)                                                    #link_name "exit";
+}
 
+foreign dl {
+	proc unix_dlopen (filename: ^u8, flags: int) -> rawptr                         #link_name "dlopen";
+	proc unix_dlsym  (handle: rawptr, symbol: ^u8) ->  (proc() #cc_c)              #link_name "dlsym";
+	proc unix_dlclose(handle: rawptr) -> int                                       #link_name "dlclose";
+	proc unix_dlerror() -> ^u8                                                     #link_name "dlerror";
+}
 
 // TODO(zangent): Change this to just `open` when Bill fixes overloading.
 proc open_simple(path: string, mode: int) -> (Handle, Errno) {

+ 18 - 16
core/sys/wgl.odin

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

+ 330 - 327
core/sys/windows.odin

@@ -17,82 +17,15 @@ type (
 	Hbrush    Handle;
 	Hgdiobj   Handle;
 	Hmodule   Handle;
+	Hmonitor  Handle;
 	Wparam    uint;
 	Lparam    int;
 	Lresult   int;
 	Bool      i32;
 	WndProc   proc(Hwnd, u32, Wparam, Lparam) -> Lresult #cc_c;
-)
-
-const INVALID_HANDLE = Handle(~int(0));
-const (
-	FALSE: Bool = 0;
-	TRUE        = 1;
-)
-
-const (
-	CS_VREDRAW    = 0x0001;
-	CS_HREDRAW    = 0x0002;
-	CS_OWNDC      = 0x0020;
-	CW_USEDEFAULT = -0x80000000;
-
-	WS_OVERLAPPED       = 0;
-	WS_MAXIMIZEBOX      = 0x00010000;
-	WS_MINIMIZEBOX      = 0x00020000;
-	WS_THICKFRAME       = 0x00040000;
-	WS_SYSMENU          = 0x00080000;
-	WS_BORDER           = 0x00800000;
-	WS_CAPTION          = 0x00C00000;
-	WS_VISIBLE          = 0x10000000;
-	WS_POPUP            = 0x80000000;
-	WS_OVERLAPPEDWINDOW = WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
-	WS_POPUPWINDOW      = WS_POPUP | WS_BORDER | WS_SYSMENU;
-
-	WM_DESTROY           = 0x0002;
-	WM_SIZE	             = 0x0005;
-	WM_CLOSE             = 0x0010;
-	WM_ACTIVATEAPP       = 0x001C;
-	WM_QUIT              = 0x0012;
-	WM_KEYDOWN           = 0x0100;
-	WM_KEYUP             = 0x0101;
-	WM_SIZING            = 0x0214;
-	WM_SYSKEYDOWN        = 0x0104;
-	WM_SYSKEYUP          = 0x0105;
-	WM_WINDOWPOSCHANGED  = 0x0047;
-	WM_SETCURSOR         = 0x0020;
-	WM_CHAR              = 0x0102;
-	WM_ACTIVATE          = 0x0006;
-	WM_SETFOCUS          = 0x0007;
-	WM_KILLFOCUS         = 0x0008;
-	WM_USER              = 0x0400;
-
-	WM_MOUSEWHEEL    = 0x020A;
-	WM_MOUSEMOVE     = 0x0200;
-	WM_LBUTTONDOWN   = 0x0201;
-	WM_LBUTTONUP     = 0x0202;
-	WM_LBUTTONDBLCLK = 0x0203;
-	WM_RBUTTONDOWN   = 0x0204;
-	WM_RBUTTONUP     = 0x0205;
-	WM_RBUTTONDBLCLK = 0x0206;
-	WM_MBUTTONDOWN   = 0x0207;
-	WM_MBUTTONUP     = 0x0208;
-	WM_MBUTTONDBLCLK = 0x0209;
-
-	PM_NOREMOVE = 0x0000;
-	PM_REMOVE   = 0x0001;
-	PM_NOYIELD  = 0x0002;
-
-	BLACK_BRUSH = 4;
 
-	SM_CXSCREEN = 0;
-	SM_CYSCREEN = 1;
-
-	SW_SHOW = 5;
 )
 
-const COLOR_BACKGROUND = Hbrush(int(1));
-
-
 type Point struct #ordered {
 	x, y: i32,
 }
@@ -170,6 +103,179 @@ type FindData struct #ordered {
     alternate_file_name: [14]u8,
 }
 
+type Security_Attributes struct #ordered {
+	length:              u32,
+	security_descriptor: rawptr,
+	inherit_handle:      Bool,
+}
+
+
+
+type PixelFormatDescriptor struct #ordered {
+	size,
+	version,
+	flags: u32,
+
+	pixel_type,
+	color_bits,
+	red_bits,
+	red_shift,
+	green_bits,
+	green_shift,
+	blue_bits,
+	blue_shift,
+	alpha_bits,
+	alpha_shift,
+	accum_bits,
+	accum_red_bits,
+	accum_green_bits,
+	accum_blue_bits,
+	accum_alpha_bits,
+	depth_bits,
+	stencil_bits,
+	aux_buffers,
+	layer_type,
+	reserved: u8,
+
+	layer_mask,
+	visible_mask,
+	damage_mask: u32,
+}
+
+
+
+
+type Proc proc() #cc_c;
+
+const (
+	MAPVK_VK_TO_CHAR   = 2;
+	MAPVK_VK_TO_VSC    = 0;
+	MAPVK_VSC_TO_VK    = 1;
+	MAPVK_VSC_TO_VK_EX = 3;
+)
+
+
+
+const INVALID_HANDLE = Handle(~int(0));
+const (
+	FALSE: Bool = 0;
+	TRUE        = 1;
+)
+
+const (
+	CS_VREDRAW    = 0x0001;
+	CS_HREDRAW    = 0x0002;
+	CS_OWNDC      = 0x0020;
+	CW_USEDEFAULT = -0x80000000;
+
+	WS_OVERLAPPED       = 0;
+	WS_MAXIMIZEBOX      = 0x00010000;
+	WS_MINIMIZEBOX      = 0x00020000;
+	WS_THICKFRAME       = 0x00040000;
+	WS_SYSMENU          = 0x00080000;
+	WS_BORDER           = 0x00800000;
+	WS_CAPTION          = 0x00C00000;
+	WS_VISIBLE          = 0x10000000;
+	WS_POPUP            = 0x80000000;
+	WS_OVERLAPPEDWINDOW = WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
+	WS_POPUPWINDOW      = WS_POPUP | WS_BORDER | WS_SYSMENU;
+
+	WM_DESTROY           = 0x0002;
+	WM_SIZE	             = 0x0005;
+	WM_CLOSE             = 0x0010;
+	WM_ACTIVATEAPP       = 0x001C;
+	WM_QUIT              = 0x0012;
+	WM_KEYDOWN           = 0x0100;
+	WM_KEYUP             = 0x0101;
+	WM_SIZING            = 0x0214;
+	WM_SYSKEYDOWN        = 0x0104;
+	WM_SYSKEYUP          = 0x0105;
+	WM_WINDOWPOSCHANGED  = 0x0047;
+	WM_SETCURSOR         = 0x0020;
+	WM_CHAR              = 0x0102;
+	WM_ACTIVATE          = 0x0006;
+	WM_SETFOCUS          = 0x0007;
+	WM_KILLFOCUS         = 0x0008;
+	WM_USER              = 0x0400;
+
+	WM_MOUSEWHEEL    = 0x020A;
+	WM_MOUSEMOVE     = 0x0200;
+	WM_LBUTTONDOWN   = 0x0201;
+	WM_LBUTTONUP     = 0x0202;
+	WM_LBUTTONDBLCLK = 0x0203;
+	WM_RBUTTONDOWN   = 0x0204;
+	WM_RBUTTONUP     = 0x0205;
+	WM_RBUTTONDBLCLK = 0x0206;
+	WM_MBUTTONDOWN   = 0x0207;
+	WM_MBUTTONUP     = 0x0208;
+	WM_MBUTTONDBLCLK = 0x0209;
+
+	PM_NOREMOVE = 0x0000;
+	PM_REMOVE   = 0x0001;
+	PM_NOYIELD  = 0x0002;
+
+	BLACK_BRUSH = 4;
+
+	SM_CXSCREEN = 0;
+	SM_CYSCREEN = 1;
+
+	SW_SHOW = 5;
+)
+
+const COLOR_BACKGROUND = Hbrush(int(1));
+
+const INVALID_SET_FILE_POINTER = ~u32(0);
+const HEAP_ZERO_MEMORY = 0x00000008;
+const INFINITE = 0xffffffff;
+const GWL_STYLE = -16;
+const Hwnd_TOP = Hwnd(uint(0));
+
+const BI_RGB         = 0;
+const DIB_RGB_COLORS = 0x00;
+const SRCCOPY: u32   = 0x00cc0020;
+
+const (
+	MONITOR_DEFAULTTONULL    = 0x00000000;
+	MONITOR_DEFAULTTOPRIMARY = 0x00000001;
+	MONITOR_DEFAULTTONEAREST = 0x00000002;
+)
+const (
+	SWP_FRAMECHANGED  = 0x0020;
+	SWP_NOOWNERZORDER = 0x0200;
+	SWP_NOZORDER      = 0x0004;
+	SWP_NOSIZE        = 0x0001;
+	SWP_NOMOVE        = 0x0002;
+)
+
+
+
+
+// Windows OpenGL
+const (
+	PFD_TYPE_RGBA             = 0;
+	PFD_TYPE_COLORINDEX       = 1;
+	PFD_MAIN_PLANE            = 0;
+	PFD_OVERLAY_PLANE         = 1;
+	PFD_UNDERLAY_PLANE        = -1;
+	PFD_DOUBLEBUFFER          = 1;
+	PFD_STEREO                = 2;
+	PFD_DRAW_TO_WINDOW        = 4;
+	PFD_DRAW_TO_BITMAP        = 8;
+	PFD_SUPPORT_GDI           = 16;
+	PFD_SUPPORT_OPENGL        = 32;
+	PFD_GENERIC_FORMAT        = 64;
+	PFD_NEED_PALETTE          = 128;
+	PFD_NEED_SYSTEM_PALETTE   = 0x00000100;
+	PFD_SWAP_EXCHANGE         = 0x00000200;
+	PFD_SWAP_COPY             = 0x00000400;
+	PFD_SWAP_LAYER_BUFFERS    = 0x00000800;
+	PFD_GENERIC_ACCELERATED   = 0x00001000;
+	PFD_DEPTH_DONTCARE        = 0x20000000;
+	PFD_DOUBLEBUFFER_DONTCARE = 0x40000000;
+	PFD_STEREO_DONTCARE       = 0x80000000;
+)
+
+
 
 type GET_FILEEX_INFO_LEVELS i32;
 const (
@@ -177,93 +283,183 @@ const (
 	GetFileExMaxInfoLevel                         = 1;
 )
 
-proc get_last_error     () -> i32                            #foreign kernel32 "GetLastError";
-proc exit_process       (exit_code: u32)                     #foreign kernel32 "ExitProcess";
-proc get_desktop_window () -> Hwnd                           #foreign user32   "GetDesktopWindow";
-proc show_cursor        (show : Bool)                        #foreign user32   "ShowCursor";
-proc get_cursor_pos     (p: ^Point) -> i32                   #foreign user32   "GetCursorPos";
-proc screen_to_client   (h: Hwnd, p: ^Point) -> i32          #foreign user32   "ScreenToClient";
-proc get_module_handle_a(module_name: ^u8) -> Hinstance      #foreign kernel32 "GetModuleHandleA";
-proc get_stock_object   (fn_object: i32) -> Hgdiobj          #foreign gdi32    "GetStockObject";
-proc post_quit_message  (exit_code: i32)                     #foreign user32   "PostQuitMessage";
-proc set_window_text_a  (hwnd: Hwnd, c_string: ^u8) -> Bool  #foreign user32   "SetWindowTextA";
+foreign kernel32 {
+	proc get_last_error     () -> i32                                                                                       #link_name "GetLastError";
+	proc exit_process       (exit_code: u32)                                                                                #link_name "ExitProcess";
+	proc get_module_handle_a(module_name: ^u8) -> Hinstance                                                                 #link_name "GetModuleHandleA";
+	proc sleep(ms: i32) -> i32                                                                                              #link_name "Sleep";
+	proc query_performance_frequency(result: ^i64) -> i32                                                                   #link_name "QueryPerformanceFrequency";
+	proc query_performance_counter  (result: ^i64) -> i32                                                                   #link_name "QueryPerformanceCounter";
+	proc output_debug_string_a(c_str: ^u8)                                                                                  #link_name "OutputDebugStringA";
 
-proc query_performance_frequency(result: ^i64) -> i32 #foreign kernel32 "QueryPerformanceFrequency";
-proc query_performance_counter  (result: ^i64) -> i32 #foreign kernel32 "QueryPerformanceCounter";
+	proc get_command_line_a    () -> ^u8                                                                                    #link_name "GetCommandLineA";
+	proc get_command_line_w    () -> ^u16                                                                                   #link_name "GetCommandLineW";
+	proc get_system_metrics    (index: i32) -> i32                                                                          #link_name "GetSystemMetrics";
+	proc get_current_thread_id () -> u32                                                                                    #link_name "GetCurrentThreadId";
 
-proc sleep(ms: i32) -> i32 #foreign kernel32 "Sleep";
+	proc get_system_time_as_file_time(system_time_as_file_time: ^Filetime)                                                  #link_name "GetSystemTimeAsFileTime";
+	proc file_time_to_local_file_time(file_time: ^Filetime, local_file_time: ^Filetime) -> Bool                             #link_name "FileTimeToLocalFileTime";
+	proc file_time_to_system_time    (file_time: ^Filetime, system_time: ^Systemtime) -> Bool                               #link_name "FileTimeToSystemTime";
+	proc system_time_to_file_time    (system_time: ^Systemtime, file_time: ^Filetime) -> Bool                               #link_name "SystemTimeToFileTime";
 
-proc output_debug_string_a(c_str: ^u8) #foreign kernel32 "OutputDebugStringA";
+	proc close_handle  (h: Handle) -> i32                                                                                   #link_name "CloseHandle";
+	proc get_std_handle(h: i32) -> Handle                                                                                   #link_name "GetStdHandle";
+	proc create_file_a (filename: ^u8, desired_access, share_mode: u32,
+	                       security: rawptr,
+	                       creation, flags_and_attribs: u32, template_file: Handle) -> Handle                               #link_name "CreateFileA";
+	proc read_file (h: Handle, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> Bool                     #link_name "ReadFile";
+	proc write_file(h: Handle, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> Bool                     #link_name "WriteFile";
 
+	proc get_file_size_ex              (file_handle: Handle, file_size: ^i64) -> Bool                                       #link_name "GetFileSizeEx";
+	proc get_file_attributes_a         (filename: ^u8) -> u32                                                               #link_name "GetFileAttributesA";
+	proc get_file_attributes_ex_a      (filename: ^u8, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool    #link_name "GetFileAttributesExA";
+	proc get_file_information_by_handle(file_handle: Handle, file_info: ^ByHandleFileInformation) -> Bool                   #link_name "GetFileInformationByHandle";
 
-proc register_class_ex_a(wc: ^WndClassExA) -> i16 #foreign user32 "RegisterClassExA";
-proc create_window_ex_a (ex_style: u32,
-                            class_name, title: ^u8,
-                            style: u32,
-                            x, y, w, h: i32,
-                            parent: Hwnd, menu: Hmenu, instance: Hinstance,
-                            param: rawptr) -> Hwnd #foreign user32 "CreateWindowExA";
+	proc get_file_type   (file_handle: Handle) -> u32                                                                       #link_name "GetFileType";
+	proc set_file_pointer(file_handle: Handle, distance_to_move: i32, distance_to_move_high: ^i32, move_method: u32) -> u32 #link_name "SetFilePointer";
 
-proc show_window       (hwnd: Hwnd, cmd_show: i32) -> Bool #foreign user32 "ShowWindow";
-proc translate_message (msg: ^Msg) -> Bool                 #foreign user32 "TranslateMessage";
-proc dispatch_message_a(msg: ^Msg) -> Lresult              #foreign user32 "DispatchMessageA";
-proc update_window     (hwnd: Hwnd) -> Bool                #foreign user32 "UpdateWindow";
-proc get_message_a     (msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool #foreign user32 "GetMessageA";
-proc peek_message_a    (msg: ^Msg, hwnd: Hwnd,
-                           msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool #foreign user32 "PeekMessageA";
+	proc set_handle_information(obj: Handle, mask, flags: u32) -> Bool                                                      #link_name "SetHandleInformation";
 
-proc post_message(hwnd: Hwnd, msg, wparam, lparam : u32) -> Bool #foreign user32 "PostMessageA";
+	proc find_first_file_a(file_name : ^u8, data : ^FindData) -> Handle                                                     #link_name "FindFirstFileA";
+	proc find_next_file_a (file : Handle, data : ^FindData) -> Bool                                                         #link_name "FindNextFileA";
+	proc find_close       (file : Handle) -> Bool                                                                           #link_name "FindClose";
 
-proc def_window_proc_a(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult #foreign user32 "DefWindowProcA";
 
-proc adjust_window_rect(rect: ^Rect, style: u32, menu: Bool) -> Bool #foreign user32 "AdjustWindowRect";
-proc get_active_window () -> Hwnd                                    #foreign user32 "GetActiveWindow";
+	proc heap_alloc      (h: Handle, flags: u32, bytes: int) -> rawptr                                                      #link_name "HeapAlloc";
+	proc heap_realloc    (h: Handle, flags: u32, memory: rawptr, bytes: int) -> rawptr                                      #link_name "HeapReAlloc";
+	proc heap_free       (h: Handle, flags: u32, memory: rawptr) -> Bool                                                    #link_name "HeapFree";
+	proc get_process_heap() -> Handle                                                                                       #link_name "GetProcessHeap";
 
-proc destroy_window       (wnd: Hwnd) -> Bool                                                           #foreign user32 "DestroyWindow";
-proc describe_pixel_format(dc: Hdc, pixel_format: i32, bytes : u32, pfd: ^PixelFormatDescriptor) -> i32 #foreign user32 "DescribePixelFormat";
 
+	proc create_semaphore_a    (attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: ^u8) -> Handle   #link_name "CreateSemaphoreA";
+	proc release_semaphore     (semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool                        #link_name "ReleaseSemaphore";
+	proc wait_for_single_object(handle: Handle, milliseconds: u32) -> u32                                                   #link_name "WaitForSingleObject";
 
-proc get_query_performance_frequency() -> i64 {
-	var r: i64;
-	query_performance_frequency(&r);
-	return r;
+
+	proc interlocked_compare_exchange  (dst: ^i32, exchange, comparand: i32) -> i32                                         #link_name "InterlockedCompareExchange";
+	proc interlocked_exchange          (dst: ^i32, desired: i32) -> i32                                                     #link_name "InterlockedExchange";
+	proc interlocked_exchange_add      (dst: ^i32, desired: i32) -> i32                                                     #link_name "InterlockedExchangeAdd";
+	proc interlocked_and               (dst: ^i32, desired: i32) -> i32                                                     #link_name "InterlockedAnd";
+	proc interlocked_or                (dst: ^i32, desired: i32) -> i32                                                     #link_name "InterlockedOr";
+
+	proc interlocked_compare_exchange64(dst: ^i64, exchange, comparand: i64) -> i64                                         #link_name "InterlockedCompareExchange64";
+	proc interlocked_exchange64        (dst: ^i64, desired: i64) -> i64                                                     #link_name "InterlockedExchange64";
+	proc interlocked_exchange_add64    (dst: ^i64, desired: i64) -> i64                                                     #link_name "InterlockedExchangeAdd64";
+	proc interlocked_and64             (dst: ^i64, desired: i64) -> i64                                                     #link_name "InterlockedAnd64";
+	proc interlocked_or64              (dst: ^i64, desired: i64) -> i64                                                     #link_name "InterlockedOr64";
+
+	proc mm_pause          ()                                                                                               #link_name "_mm_pause";
+	proc read_write_barrier()                                                                                               #link_name "ReadWriteBarrier";
+	proc write_barrier     ()                                                                                               #link_name "WriteBarrier";
+	proc read_barrier      ()                                                                                               #link_name "ReadBarrier";
+
+
+	proc load_library_a  (c_str: ^u8) -> Hmodule                                                                            #link_name "LoadLibraryA";
+	proc free_library    (h: Hmodule)                                                                                       #link_name "FreeLibrary";
+	proc get_proc_address(h: Hmodule, c_str: ^u8) -> Proc                                                                   #link_name "GetProcAddress";
+
+}
+
+foreign user32 {
+	proc get_desktop_window   () -> Hwnd                                                                    #link_name "GetDesktopWindow";
+	proc show_cursor          (show : Bool)                                                                 #link_name "ShowCursor";
+	proc get_cursor_pos       (p: ^Point) -> i32                                                            #link_name "GetCursorPos";
+	proc screen_to_client     (h: Hwnd, p: ^Point) -> i32                                                   #link_name "ScreenToClient";
+	proc post_quit_message    (exit_code: i32)                                                              #link_name "PostQuitMessage";
+	proc set_window_text_a    (hwnd: Hwnd, c_string: ^u8) -> Bool                                           #link_name "SetWindowTextA";
+	proc register_class_ex_a  (wc: ^WndClassExA) -> i16                                                     #link_name "RegisterClassExA";
+
+	proc create_window_ex_a   (ex_style: u32,
+                               class_name, title: ^u8,
+                               style: u32,
+                               x, y, w, h: i32,
+                               parent: Hwnd, menu: Hmenu, instance: Hinstance,
+                               param: rawptr) -> Hwnd                                                       #link_name "CreateWindowExA";
+
+	proc show_window          (hwnd: Hwnd, cmd_show: i32) -> Bool                                           #link_name "ShowWindow";
+	proc translate_message    (msg: ^Msg) -> Bool                                                           #link_name "TranslateMessage";
+	proc dispatch_message_a   (msg: ^Msg) -> Lresult                                                        #link_name "DispatchMessageA";
+	proc update_window        (hwnd: Hwnd) -> Bool                                                          #link_name "UpdateWindow";
+	proc get_message_a        (msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool         #link_name "GetMessageA";
+	proc peek_message_a       (msg: ^Msg, hwnd: Hwnd,
+	                           msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool                     #link_name "PeekMessageA";
+
+
+	proc post_message         (hwnd: Hwnd, msg, wparam, lparam : u32) -> Bool                               #link_name "PostMessageA";
+
+	proc def_window_proc_a    (hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult             #link_name "DefWindowProcA";
+
+	proc adjust_window_rect   (rect: ^Rect, style: u32, menu: Bool) -> Bool                                 #link_name "AdjustWindowRect";
+	proc get_active_window    () -> Hwnd                                                                    #link_name "GetActiveWindow";
+
+	proc destroy_window       (wnd: Hwnd) -> Bool                                                           #link_name "DestroyWindow";
+	proc describe_pixel_format(dc: Hdc, pixel_format: i32, bytes : u32, pfd: ^PixelFormatDescriptor) -> i32 #link_name "DescribePixelFormat";
+
+	proc get_monitor_info_a   (monitor: Hmonitor, mi: ^MonitorInfo) -> Bool                                 #link_name "GetMonitorInfoA";
+	proc monitor_from_window  (wnd: Hwnd, flags : u32) -> Hmonitor                                          #link_name "MonitorFromWindow";
+
+	proc set_window_pos       (wnd: Hwnd, wndInsertAfter: Hwnd, x, y, width, height: i32, flags: u32)       #link_name "SetWindowPos";
+
+	proc get_window_placement (wnd: Hwnd, wndpl: ^WindowPlacement) -> Bool                                  #link_name "GetWindowPlacement";
+	proc set_window_placement (wnd: Hwnd, wndpl: ^WindowPlacement) -> Bool                                  #link_name "SetWindowPlacement";
+	proc get_window_rect      (wnd: Hwnd, rect: ^Rect) -> Bool                                              #link_name "GetWindowRect";
+
+	proc get_window_long_ptr_a(wnd: Hwnd, index: i32) -> i64                                                #link_name "GetWindowLongPtrA";
+	proc set_window_long_ptr_a(wnd: Hwnd, index: i32, new: i64) -> i64                                      #link_name "SetWindowLongPtrA";
+
+	proc get_window_text      (wnd: Hwnd, str: ^u8, maxCount: i32) -> i32                                   #link_name "GetWindowText";
+
+	proc get_client_rect (hwnd: Hwnd, rect: ^Rect) -> Bool                                                  #link_name "GetClientRect";
+
+	proc get_dc             (h: Hwnd) -> Hdc                                                                #link_name "GetDC";
+	proc release_dc         (wnd: Hwnd, hdc: Hdc) -> i32                                                    #link_name "ReleaseDC";
+
+	proc map_virtual_key(scancode : u32, map_type : u32) -> u32                                             #link_name "MapVirtualKeyA";
+
+	proc get_key_state      (v_key: i32) -> i16                                                             #link_name "GetKeyState";
+	proc get_async_key_state(v_key: i32) -> i16                                                             #link_name "GetAsyncKeyState";
 }
 
-proc get_command_line_a    () -> ^u8                                 #foreign kernel32 "GetCommandLineA";
-proc get_command_line_w    () -> ^u16                                #foreign kernel32 "GetCommandLineW";
-proc get_system_metrics    (index: i32) -> i32                       #foreign kernel32 "GetSystemMetrics";
-proc get_current_thread_id () -> u32                                 #foreign kernel32 "GetCurrentThreadId";
-proc command_line_to_argv_w(cmd_list: ^u16, num_args: ^i32) -> ^^u16 #foreign shell32  "CommandLineToArgvW";
+foreign gdi32 {
+	proc get_stock_object(fn_object: i32) -> Hgdiobj                                           #link_name "GetStockObject";
 
-proc time_get_time               () -> u32                                                  #foreign winmm    "timeGetTime";
-proc get_system_time_as_file_time(system_time_as_file_time: ^Filetime)                      #foreign kernel32 "GetSystemTimeAsFileTime";
-proc file_time_to_local_file_time(file_time: ^Filetime, local_file_time: ^Filetime) -> Bool #foreign kernel32 "FileTimeToLocalFileTime";
-proc file_time_to_system_time    (file_time: ^Filetime, system_time: ^Systemtime) -> Bool   #foreign kernel32 "FileTimeToSystemTime";
-proc system_time_to_file_time    (system_time: ^Systemtime, file_time: ^Filetime) -> Bool   #foreign kernel32 "SystemTimeToFileTime";
+	proc stretch_dibits( hdc: Hdc,
+	                        x_dst, y_dst, width_dst, height_dst: i32,
+	                        x_src, y_src, width_src, header_src: i32,
+	                        bits: rawptr, bits_info: ^BitmapInfo,
+	                        usage: u32,
+	                        rop: u32) -> i32                                                   #link_name "StretchDIBits";
 
-// File Stuff
+	proc set_pixel_format   (hdc: Hdc, pixel_format: i32, pfd: ^PixelFormatDescriptor) -> Bool #link_name "SetPixelFormat";
+	proc choose_pixel_format(hdc: Hdc, pfd: ^PixelFormatDescriptor) -> i32                     #link_name "ChoosePixelFormat";
+	proc swap_buffers       (hdc: Hdc) -> Bool                                                 #link_name "SwapBuffers";
 
-proc close_handle  (h: Handle) -> i32 #foreign kernel32 "CloseHandle";
-proc get_std_handle(h: i32) -> Handle #foreign kernel32 "GetStdHandle";
-proc create_file_a (filename: ^u8, desired_access, share_mode: u32,
-                       security: rawptr,
-                       creation, flags_and_attribs: u32, template_file: Handle) -> Handle #foreign kernel32 "CreateFileA";
-proc read_file (h: Handle, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> Bool #foreign kernel32 "ReadFile";
-proc write_file(h: Handle, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> Bool #foreign kernel32 "WriteFile";
+}
+
+foreign shell32 {
+	proc command_line_to_argv_w(cmd_list: ^u16, num_args: ^i32) -> ^^u16 #link_name "CommandLineToArgvW";
+}
 
-proc get_file_size_ex              (file_handle: Handle, file_size: ^i64) -> Bool                                    #foreign kernel32 "GetFileSizeEx";
-proc get_file_attributes_a         (filename: ^u8) -> u32                                                          #foreign kernel32 "GetFileAttributesA";
-proc get_file_attributes_ex_a      (filename: ^u8, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool #foreign kernel32 "GetFileAttributesExA";
-proc get_file_information_by_handle(file_handle: Handle, file_info: ^ByHandleFileInformation) -> Bool                #foreign kernel32 "GetFileInformationByHandle";
+foreign winmm {
+	proc time_get_time() -> u32 #link_name "timeGetTime";
+}
 
-proc get_file_type   (file_handle: Handle) -> u32                                                                       #foreign kernel32 "GetFileType";
-proc set_file_pointer(file_handle: Handle, distance_to_move: i32, distance_to_move_high: ^i32, move_method: u32) -> u32 #foreign kernel32 "SetFilePointer";
 
-proc set_handle_information(obj: Handle, mask, flags: u32) -> Bool #foreign kernel32 "SetHandleInformation";
 
-proc find_first_file_a(file_name : ^u8, data : ^FindData) -> Handle #foreign kernel32 "FindFirstFileA";
-proc find_next_file_a (file : Handle, data : ^FindData) -> Bool       #foreign kernel32 "FindNextFileA";
-proc find_close       (file : Handle) -> Bool                         #foreign kernel32 "FindClose";
+proc get_query_performance_frequency() -> i64 {
+	var r: i64;
+	query_performance_frequency(&r);
+	return r;
+}
+
+proc HIWORD(wParam: Wparam) -> u16 { return u16((u32(wParam) >> 16) & 0xffff); }
+proc HIWORD(lParam: Lparam) -> u16 { return u16((u32(lParam) >> 16) & 0xffff); }
+proc LOWORD(wParam: Wparam) -> u16 { return u16(wParam); }
+proc LOWORD(lParam: Lparam) -> u16 { return u16(lParam); }
+
+proc is_key_down(key: KeyCode) -> bool #inline { return get_async_key_state(i32(key)) < 0; }
+
+
 
 
 const (
@@ -318,73 +514,6 @@ const (
 	FILE_TYPE_PIPE = 0x0003;
 )
 
-const INVALID_SET_FILE_POINTER = ~u32(0);
-
-
-
-
-proc heap_alloc      ( h: Handle, flags: u32, bytes: int) -> rawptr                 #foreign kernel32 "HeapAlloc";
-proc heap_realloc    ( h: Handle, flags: u32, memory: rawptr, bytes: int) -> rawptr #foreign kernel32 "HeapReAlloc";
-proc heap_free       ( h: Handle, flags: u32, memory: rawptr) -> Bool               #foreign kernel32 "HeapFree";
-proc get_process_heap( ) -> Handle                                                  #foreign kernel32 "GetProcessHeap";
-
-
-const HEAP_ZERO_MEMORY = 0x00000008;
-
-// Synchronization
-
-type Security_Attributes struct #ordered {
-	length:              u32,
-	security_descriptor: rawptr,
-	inherit_handle:      Bool,
-}
-
-const INFINITE = 0xffffffff;
-
-proc create_semaphore_a    (attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: ^u8) -> Handle #foreign kernel32 "CreateSemaphoreA";
-proc release_semaphore     (semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool                        #foreign kernel32 "ReleaseSemaphore";
-proc wait_for_single_object(handle: Handle, milliseconds: u32) -> u32                                                   #foreign kernel32 "WaitForSingleObject";
-
-
-proc interlocked_compare_exchange  (dst: ^i32, exchange, comparand: i32) -> i32   #foreign kernel32 "InterlockedCompareExchange";
-proc interlocked_exchange          (dst: ^i32, desired: i32) -> i32               #foreign kernel32 "InterlockedExchange";
-proc interlocked_exchange_add      (dst: ^i32, desired: i32) -> i32               #foreign kernel32 "InterlockedExchangeAdd";
-proc interlocked_and               (dst: ^i32, desired: i32) -> i32               #foreign kernel32 "InterlockedAnd";
-proc interlocked_or                (dst: ^i32, desired: i32) -> i32               #foreign kernel32 "InterlockedOr";
-
-proc interlocked_compare_exchange64(dst: ^i64, exchange, comparand: i64) -> i64   #foreign kernel32 "InterlockedCompareExchange64";
-proc interlocked_exchange64        (dst: ^i64, desired: i64) -> i64               #foreign kernel32 "InterlockedExchange64";
-proc interlocked_exchange_add64    (dst: ^i64, desired: i64) -> i64               #foreign kernel32 "InterlockedExchangeAdd64";
-proc interlocked_and64             (dst: ^i64, desired: i64) -> i64               #foreign kernel32 "InterlockedAnd64";
-proc interlocked_or64              (dst: ^i64, desired: i64) -> i64               #foreign kernel32 "InterlockedOr64";
-
-proc mm_pause          () #foreign kernel32 "_mm_pause";
-proc read_write_barrier() #foreign kernel32 "ReadWriteBarrier";
-proc write_barrier     () #foreign kernel32 "WriteBarrier";
-proc read_barrier      () #foreign kernel32 "ReadBarrier";
-
-
-
-
-
-type Hmonitor Handle;
-
-const GWL_STYLE = -16;
-
-const Hwnd_TOP = Hwnd(uint(0));
-
-const (
-	MONITOR_DEFAULTTONULL    = 0x00000000;
-	MONITOR_DEFAULTTOPRIMARY = 0x00000001;
-	MONITOR_DEFAULTTONEAREST = 0x00000002;
-)
-const (
-	SWP_FRAMECHANGED  = 0x0020;
-	SWP_NOOWNERZORDER = 0x0200;
-	SWP_NOZORDER      = 0x0004;
-	SWP_NOSIZE        = 0x0001;
-	SWP_NOMOVE        = 0x0002;
-)
 
 type MonitorInfo struct #ordered {
 	size:      u32,
@@ -402,34 +531,6 @@ type WindowPlacement struct #ordered {
 	normal_pos: Rect,
 }
 
-proc get_monitor_info_a   (monitor: Hmonitor, mi: ^MonitorInfo) -> Bool                           #foreign user32 "GetMonitorInfoA";
-proc monitor_from_window  (wnd: Hwnd, flags : u32) -> Hmonitor                                    #foreign user32 "MonitorFromWindow";
-
-proc set_window_pos       (wnd: Hwnd, wndInsertAfter: Hwnd, x, y, width, height: i32, flags: u32) #foreign user32 "SetWindowPos";
-
-proc get_window_placement (wnd: Hwnd, wndpl: ^WindowPlacement) -> Bool                            #foreign user32 "GetWindowPlacement";
-proc set_window_placement (wnd: Hwnd, wndpl: ^WindowPlacement) -> Bool                            #foreign user32 "SetWindowPlacement";
-proc get_window_rect      (wnd: Hwnd, rect: ^Rect) -> Bool                                        #foreign user32 "GetWindowRect";
-
-proc get_window_long_ptr_a(wnd: Hwnd, index: i32) -> i64                                          #foreign user32 "GetWindowLongPtrA";
-proc set_window_long_ptr_a(wnd: Hwnd, index: i32, new: i64) -> i64                                #foreign user32 "SetWindowLongPtrA";
-
-proc get_window_text      (wnd: Hwnd, str: ^u8, maxCount: i32) -> i32                           #foreign user32 "GetWindowText";
-
-proc HIWORD(wParam: Wparam) -> u16 { return u16((u32(wParam) >> 16) & 0xffff); }
-proc HIWORD(lParam: Lparam) -> u16 { return u16((u32(lParam) >> 16) & 0xffff); }
-proc LOWORD(wParam: Wparam) -> u16 { return u16(wParam); }
-proc LOWORD(lParam: Lparam) -> u16 { return u16(lParam); }
-
-
-
-
-
-
-
-
-
-
 type BitmapInfoHeader struct #ordered {
 	size:              u32,
 	width, height:     i32,
@@ -449,104 +550,6 @@ type BitmapInfo struct #ordered {
 
 type RgbQuad struct #ordered { blue, green, red, reserved: u8 }
 
-const BI_RGB         = 0;
-const DIB_RGB_COLORS = 0x00;
-const SRCCOPY: u32   = 0x00cc0020;
-
-
-proc stretch_dibits( hdc: Hdc,
-                        x_dst, y_dst, width_dst, height_dst: i32,
-                        x_src, y_src, width_src, header_src: i32,
-                        bits: rawptr, bits_info: ^BitmapInfo,
-                        usage: u32,
-                        rop: u32) -> i32 #foreign gdi32 "StretchDIBits";
-
-
-
-proc load_library_a  ( c_str: ^u8) -> Hmodule          #foreign kernel32 "LoadLibraryA";
-proc free_library    ( h: Hmodule)                     #foreign kernel32 "FreeLibrary";
-proc get_proc_address( h: Hmodule, c_str: ^u8) -> Proc #foreign kernel32 "GetProcAddress";
-
-proc get_client_rect (hwnd: Hwnd, rect: ^Rect) -> Bool #foreign user32 "GetClientRect";
-
-// Windows OpenGL
-const (
-	PFD_TYPE_RGBA             = 0;
-	PFD_TYPE_COLORINDEX       = 1;
-	PFD_MAIN_PLANE            = 0;
-	PFD_OVERLAY_PLANE         = 1;
-	PFD_UNDERLAY_PLANE        = -1;
-	PFD_DOUBLEBUFFER          = 1;
-	PFD_STEREO                = 2;
-	PFD_DRAW_TO_WINDOW        = 4;
-	PFD_DRAW_TO_BITMAP        = 8;
-	PFD_SUPPORT_GDI           = 16;
-	PFD_SUPPORT_OPENGL        = 32;
-	PFD_GENERIC_FORMAT        = 64;
-	PFD_NEED_PALETTE          = 128;
-	PFD_NEED_SYSTEM_PALETTE   = 0x00000100;
-	PFD_SWAP_EXCHANGE         = 0x00000200;
-	PFD_SWAP_COPY             = 0x00000400;
-	PFD_SWAP_LAYER_BUFFERS    = 0x00000800;
-	PFD_GENERIC_ACCELERATED   = 0x00001000;
-	PFD_DEPTH_DONTCARE        = 0x20000000;
-	PFD_DOUBLEBUFFER_DONTCARE = 0x40000000;
-	PFD_STEREO_DONTCARE       = 0x80000000;
-)
-
-type PixelFormatDescriptor struct #ordered {
-	size,
-	version,
-	flags: u32,
-
-	pixel_type,
-	color_bits,
-	red_bits,
-	red_shift,
-	green_bits,
-	green_shift,
-	blue_bits,
-	blue_shift,
-	alpha_bits,
-	alpha_shift,
-	accum_bits,
-	accum_red_bits,
-	accum_green_bits,
-	accum_blue_bits,
-	accum_alpha_bits,
-	depth_bits,
-	stencil_bits,
-	aux_buffers,
-	layer_type,
-	reserved: u8,
-
-	layer_mask,
-	visible_mask,
-	damage_mask: u32,
-}
-
-proc get_dc             (h: Hwnd) -> Hdc                                                   #foreign user32 "GetDC";
-proc set_pixel_format   (hdc: Hdc, pixel_format: i32, pfd: ^PixelFormatDescriptor) -> Bool #foreign gdi32  "SetPixelFormat";
-proc choose_pixel_format(hdc: Hdc, pfd: ^PixelFormatDescriptor) -> i32                     #foreign gdi32  "ChoosePixelFormat";
-proc swap_buffers       (hdc: Hdc) -> Bool                                                 #foreign gdi32  "SwapBuffers";
-proc release_dc         (wnd: Hwnd, hdc: Hdc) -> i32                                       #foreign user32 "ReleaseDC";
-
-
-type Proc proc() #cc_c;
-
-const (
-	MAPVK_VK_TO_CHAR   = 2;
-	MAPVK_VK_TO_VSC    = 0;
-	MAPVK_VSC_TO_VK    = 1;
-	MAPVK_VSC_TO_VK_EX = 3;
-)
-
-proc map_virtual_key(scancode : u32, map_type : u32) -> u32 #foreign user32 "MapVirtualKeyA";
-
-proc get_key_state      (v_key: i32) -> i16 #foreign user32 "GetKeyState";
-proc get_async_key_state(v_key: i32) -> i16 #foreign user32 "GetAsyncKeyState";
-
-proc is_key_down(key: KeyCode) -> bool #inline { return get_async_key_state(i32(key)) < 0; }
 
 type KeyCode enum i32 {
 	Lbutton    = 0x01,

+ 9 - 10
src/check_decl.cpp

@@ -292,16 +292,14 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 		error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure");
 	}
 
-	if (is_foreign && is_link_name) {
-		error_node(pd->type, "You cannot apply both `foreign` and `link_name` to a procedure");
-	} else if (is_foreign && is_export) {
+	if (is_foreign && is_export) {
 		error_node(pd->type, "You cannot apply both `foreign` and `export` to a procedure");
 	}
 
 
 	if (pd->body != NULL) {
 		if (is_foreign) {
-			error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body");
+			error_node(pd->body, "A procedure tagged as `foreign` cannot have a body");
 		}
 
 		d->scope = c->context.scope;
@@ -323,15 +321,15 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 	if (is_foreign) {
 		auto *fp = &c->info.foreigns;
 		String name = e->token.string;
-		if (pd->foreign_name.len > 0) {
-			name = pd->foreign_name;
+		if (pd->link_name.len > 0) {
+			name = pd->link_name;
 		}
 
-		AstNode *foreign_library = d->proc_decl->ProcDecl.foreign_library;
+		AstNode *foreign_library = e->Procedure.foreign_library_ident;
 		if (foreign_library == NULL) {
-			error(e->token, "#foreign procedures must declare which library they are from");
+			error(e->token, "foreign procedures must declare which library they are from");
 		} else if (foreign_library->kind != AstNode_Ident) {
-			error_node(foreign_library, "#foreign library names must be an identifier");
+			error_node(foreign_library, "foreign library names must be an identifier");
 		} else {
 			String name = foreign_library->Ident.string;
 			Entity *found = scope_lookup_entity(c->context.scope, name);
@@ -342,7 +340,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 					error_node(foreign_library, "Undeclared name: %.*s", LIT(name));
 				}
 			} else if (found->kind != Entity_LibraryName) {
-				error_node(foreign_library, "`_` cannot be used as a library name");
+				error_node(foreign_library, "`%.*s` cannot be used as a library name", LIT(name));
 			} else {
 				// TODO(bill): Extra stuff to do with library names?
 				e->Procedure.foreign_library = found;
@@ -352,6 +350,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 
 		e->Procedure.is_foreign = true;
 		e->Procedure.foreign_name = name;
+		e->Procedure.link_name = name;
 
 		HashKey key = hash_string(name);
 		Entity **found = map_get(fp, key);

+ 28 - 3
src/checker.cpp

@@ -270,6 +270,7 @@ struct CheckerContext {
 	String     proc_name;
 	Type *     type_hint;
 	DeclInfo * curr_proc_decl;
+	AstNode *  curr_foreign_library;
 };
 
 // CheckerInfo stores all the symbol information for a type-checked program
@@ -1626,6 +1627,24 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
 			}
 		case_end;
 
+		case_ast_node(fb, ForeignBlockDecl, decl);
+			AstNode *foreign_library = fb->foreign_library;
+			bool ok = true;
+			if (foreign_library->kind != AstNode_Ident) {
+				error_node(foreign_library, "foreign library name must be an identifier");
+				ok = false;
+			}
+
+			CheckerContext prev_context = c->context;
+			if (ok) {
+				c->context.curr_foreign_library = foreign_library;
+			}
+
+			check_collect_entities(c, fb->decls, is_file_scope);
+
+			c->context = prev_context;
+		case_end;
+
 		case_ast_node(pd, ProcDecl, decl);
 			AstNode *name = pd->name;
 			if (name->kind != AstNode_Ident) {
@@ -1638,6 +1657,12 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
 			Entity *e = NULL;
 
 			e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, pd->tags);
+			AstNode *fl = c->context.curr_foreign_library;
+			if (fl != NULL) {
+				GB_ASSERT(fl->kind == AstNode_Ident);
+				e->Procedure.foreign_library_ident = fl;
+				pd->tags |= ProcTag_foreign;
+			}
 			d->proc_decl = decl;
 			d->type_expr = pd->type;
 			e->identifier = name;
@@ -1652,14 +1677,14 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
 		}
 	}
 
+	// NOTE(bill): `when` stmts need to be handled after the other as the condition may refer to something
+	// declared after this stmt in source
 	if (!c->context.scope->is_file) {
-		// NOTE(bill): `when` stmts need to be handled after the other as the condition may refer to something
-		// declared after this stmt in source
 		for_array(i, nodes) {
 			AstNode *node = nodes[i];
 			switch (node->kind) {
 			case_ast_node(ws, WhenStmt, node);
-				check_collect_entities_from_when_stmt(c, ws, is_file_scope);
+					check_collect_entities_from_when_stmt(c, ws, is_file_scope);
 			case_end;
 			}
 		}

+ 1 - 0
src/entity.cpp

@@ -95,6 +95,7 @@ struct Entity {
 			bool         is_foreign;
 			String       foreign_name;
 			Entity *     foreign_library;
+			AstNode *    foreign_library_ident;
 			String       link_name;
 			u64          tags;
 			OverloadKind overload_kind;

+ 9 - 5
src/ir.cpp

@@ -5790,6 +5790,12 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 	case_ast_node(bs, EmptyStmt, node);
 	case_end;
 
+	case_ast_node(fb, ForeignBlockDecl, node);
+		for_array(i, fb->decls) {
+			ir_build_stmt(proc, fb->decls[i]);
+		}
+	case_end;
+
 	case_ast_node(us, UsingStmt, node);
 		for_array(i, us->list) {
 			AstNode *decl = unparen_expr(us->list[i]);
@@ -5943,8 +5949,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 			// FFI - Foreign function interace
 			String original_name = e->token.string;
 			String name = original_name;
-			if (pd->foreign_name.len > 0) {
-				name = pd->foreign_name;
+			if (pd->link_name.len > 0) {
+				name = pd->link_name;
 			}
 
 			irValue *value = ir_value_procedure(proc->module->allocator,
@@ -7251,9 +7257,7 @@ 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 (pd->foreign_name.len > 0) {
-				name = pd->foreign_name;
-			} else if (pd->link_name.len > 0) {
+			if (pd->link_name.len > 0) {
 				name = pd->link_name;
 			}
 

+ 105 - 76
src/parser.cpp

@@ -139,8 +139,6 @@ Array<AstNode *> make_ast_node_array(AstFile *f) {
 		AstNode *type;            \
 		AstNode *body;            \
 		u64      tags;            \
-		AstNode *foreign_library; \
-		String   foreign_name;    \
 		String   link_name;       \
 	}) \
 	AST_NODE_KIND(CompoundLit, "compound literal", struct { \
@@ -302,16 +300,13 @@ AST_NODE_KIND(_DeclBegin,      "", i32) \
 		AstNode *type;            \
 		AstNode *body;            \
 		u64      tags;            \
-		AstNode *foreign_library; \
-		String   foreign_name;    \
 		String   link_name;       \
 	}) \
-	AST_NODE_KIND(ForeignLibrarySpec, "foreign library specification", struct { \
-		Token    filepath;     \
-		Token    library_name; \
-		String   base_dir;     \
-		AstNode *cond;         \
-		bool     is_system;    \
+	AST_NODE_KIND(ForeignBlockDecl, "foreign block declaration", struct { \
+		Token            token;           \
+		AstNode *        foreign_library; \
+		Token            open, close;     \
+		Array<AstNode *> decls;           \
 	}) \
 	AST_NODE_KIND(Label, "label", struct { 	\
 		Token token; \
@@ -340,12 +335,19 @@ AST_NODE_KIND(_DeclBegin,      "", i32) \
 		Token    import_name; \
 		AstNode *cond;        \
 	}) \
+	AST_NODE_KIND(ForeignLibrarySpec, "foreign library specification", struct { \
+		Token    filepath;     \
+		Token    library_name; \
+		String   base_dir;     \
+		AstNode *cond;         \
+		bool     is_system;    \
+	}) \
 AST_NODE_KIND(_DeclEnd,   "", i32) \
 	AST_NODE_KIND(Field, "field", struct { \
 		Array<AstNode *> names;            \
-		AstNode *    type;                 \
-		AstNode *    default_value;        \
-		u32          flags;                \
+		AstNode *        type;             \
+		AstNode *        default_value;    \
+		u32              flags;            \
 	}) \
 	AST_NODE_KIND(FieldList, "field list", struct { \
 		Token token; \
@@ -609,7 +611,6 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
 	case AstNode_ProcLit:
 		n->ProcLit.type = clone_ast_node(a, n->ProcLit.type);
 		n->ProcLit.body = clone_ast_node(a, n->ProcLit.body);
-		n->ProcLit.foreign_library = clone_ast_node(a, n->ProcLit.foreign_library);
 		break;
 	case AstNode_CompoundLit:
 		n->CompoundLit.type  = clone_ast_node(a, n->CompoundLit.type);
@@ -1040,13 +1041,11 @@ AstNode *ast_ellipsis(AstFile *f, Token token, AstNode *expr) {
 }
 
 
-AstNode *ast_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags, AstNode *foreign_library, String foreign_name, String link_name) {
+AstNode *ast_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags, String link_name) {
 	AstNode *result = make_ast_node(f, AstNode_ProcLit);
 	result->ProcLit.type = type;
 	result->ProcLit.body = body;
 	result->ProcLit.tags = tags;
-	result->ProcLit.foreign_library = foreign_library;
-	result->ProcLit.foreign_name = foreign_name;
 	result->ProcLit.link_name = link_name;
 	return result;
 }
@@ -1424,25 +1423,24 @@ AstNode *ast_map_type(AstFile *f, Token token, AstNode *count, AstNode *key, Ast
 
 
 AstNode *ast_proc_decl(AstFile *f, Token token, AstNode *name, AstNode *type, AstNode *body,
-                       u64 tags, AstNode *foreign_library, String foreign_name, String link_name) {
+                       u64 tags, String link_name) {
 	AstNode *result = make_ast_node(f, AstNode_ProcDecl);
 	result->ProcDecl.token           = token;
 	result->ProcDecl.name            = name;
 	result->ProcDecl.type            = type;
 	result->ProcDecl.body            = body;
 	result->ProcDecl.tags            = tags;
-	result->ProcDecl.foreign_library = foreign_library;
-	result->ProcDecl.foreign_name    = foreign_name;
 	result->ProcDecl.link_name       = link_name;
 	return result;
 }
 
-AstNode *ast_foreign_library_spec(AstFile *f, Token filepath, Token library_name, AstNode *cond, bool is_system) {
-	AstNode *result = make_ast_node(f, AstNode_ForeignLibrarySpec);
-	result->ForeignLibrarySpec.filepath = filepath;
-	result->ForeignLibrarySpec.library_name = library_name;
-	result->ForeignLibrarySpec.cond = cond;
-	result->ForeignLibrarySpec.is_system = is_system;
+AstNode *ast_foreign_block_decl(AstFile *f, Token token, AstNode *foreign_library, Token open, Token close, Array<AstNode *> decls) {
+	AstNode *result = make_ast_node(f, AstNode_ForeignBlockDecl);
+	result->ForeignBlockDecl.token           = token;
+	result->ForeignBlockDecl.foreign_library = foreign_library;
+	result->ForeignBlockDecl.open            = open;
+	result->ForeignBlockDecl.close           = close;
+	result->ForeignBlockDecl.decls           = decls;
 	return result;
 }
 
@@ -1486,6 +1484,15 @@ AstNode *ast_import_spec(AstFile *f, bool is_import, Token relpath, Token import
 	return result;
 }
 
+AstNode *ast_foreign_library_spec(AstFile *f, Token filepath, Token library_name, AstNode *cond, bool is_system) {
+	AstNode *result = make_ast_node(f, AstNode_ForeignLibrarySpec);
+	result->ForeignLibrarySpec.filepath = filepath;
+	result->ForeignLibrarySpec.library_name = library_name;
+	result->ForeignLibrarySpec.cond = cond;
+	result->ForeignLibrarySpec.is_system = is_system;
+	return result;
+}
+
 
 
 
@@ -1731,11 +1738,11 @@ void expect_semicolon(AstFile *f, AstNode *s) {
 }
 
 
-AstNode *    parse_expr(AstFile *f, bool lhs);
-AstNode *    parse_proc_type(AstFile *f, Token proc_token, AstNode **foreign_library, String *foreign_name, String *link_name);
+AstNode *        parse_expr(AstFile *f, bool lhs);
+AstNode *        parse_proc_type(AstFile *f, Token proc_token, String *link_name);
 Array<AstNode *> parse_stmt_list(AstFile *f);
-AstNode *    parse_stmt(AstFile *f);
-AstNode *    parse_body(AstFile *f);
+AstNode *        parse_stmt(AstFile *f);
+AstNode *        parse_body(AstFile *f);
 
 
 
@@ -1753,7 +1760,12 @@ AstNode *parse_ident(AstFile *f) {
 
 AstNode *parse_tag_expr(AstFile *f, AstNode *expression) {
 	Token token = expect_token(f, Token_Hash);
-	Token name  = expect_token(f, Token_Ident);
+	Token name  = {};
+	if (f->curr_token.kind == Token_foreign) {
+		name = expect_token(f, Token_foreign);
+	} else {
+		name = expect_token(f, Token_Ident);
+	}
 	return ast_tag_expr(f, token, name, expression);
 }
 
@@ -1873,11 +1885,10 @@ bool is_foreign_name_valid(String name) {
 	return true;
 }
 
-void parse_proc_tags(AstFile *f, u64 *tags, AstNode **foreign_library_token, String *foreign_name, String *link_name, ProcCallingConvention *calling_convention) {
+void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConvention *calling_convention) {
 	// TODO(bill): Add this to procedure literals too
 	GB_ASSERT(tags         != NULL);
 	GB_ASSERT(link_name    != NULL);
-	GB_ASSERT(link_name    != NULL);
 
 	ProcCallingConvention cc = ProcCC_Invalid;
 
@@ -1891,19 +1902,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, AstNode **foreign_library_token, Str
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_##name, tag_name); \
 		}
 
-		if (tag_name == "foreign") {
-			check_proc_add_tag(f, tag_expr, tags, ProcTag_foreign, tag_name);
-			*foreign_library_token = parse_ident(f);
-			if (f->curr_token.kind == Token_String) {
-				*foreign_name = f->curr_token.string;
-				// TODO(bill): Check if valid string
-				if (!is_foreign_name_valid(*foreign_name)) {
-					syntax_error_node(tag_expr, "Invalid alternative foreign procedure name: `%.*s`", LIT(*foreign_name));
-				}
-
-				next_token(f);
-			}
-		} else if (tag_name == "link_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;
@@ -2081,7 +2080,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 		} else if (name.string == "file") { return ast_basic_directive(f, token, name.string);
 		} else if (name.string == "line") { return ast_basic_directive(f, token, name.string);
 		} else if (name.string == "procedure") { return ast_basic_directive(f, token, name.string);
-		} else if (!lhs && name.string == "alias") { return ast_alias(f, token, parse_expr(f, false));
+		// } else if (!lhs && name.string == "alias") { return ast_alias(f, token, parse_expr(f, false));
 		} else {
 			operand = ast_tag_expr(f, token, name, parse_expr(f, false));
 		}
@@ -2091,10 +2090,8 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 	// Parse Procedure Type or Literal
 	case Token_proc: {
 		Token token = expect_token(f, Token_proc);
-		AstNode *foreign_library = NULL;
-		String foreign_name = {};
 		String link_name = {};
-		AstNode *type = parse_proc_type(f, token, &foreign_library, &foreign_name, &link_name);
+		AstNode *type = parse_proc_type(f, token, &link_name);
 		u64 tags = type->ProcType.tags;
 
 		if (f->curr_token.kind == Token_OpenBrace) {
@@ -2107,11 +2104,11 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 			body = parse_body(f);
 			f->curr_proc = curr_proc;
 
-			return ast_proc_lit(f, type, body, tags, foreign_library, foreign_name, link_name);
+			return ast_proc_lit(f, type, body, tags, link_name);
 		}
 
 		if ((tags & ProcTag_foreign) != 0) {
-			return ast_proc_lit(f, type, NULL, tags, foreign_library, foreign_name, link_name);
+			return ast_proc_lit(f, type, NULL, tags, link_name);
 		}
 		if (tags != 0) {
 			// syntax_error(token, "A procedure type cannot have tags");
@@ -2526,13 +2523,11 @@ AstNode *parse_proc_decl(AstFile *f) {
 
 	Token token = expect_token(f, Token_proc);
 	AstNode *body = NULL;
-	AstNode *foreign_library = NULL;
-	String foreign_name = {};
 	String link_name = {};
 
 
 	AstNode *name = parse_ident(f);
-	AstNode *type = parse_proc_type(f, token, &foreign_library, &foreign_name, &link_name);
+	AstNode *type = parse_proc_type(f, token, &link_name);
 	u64 tags = type->ProcType.tags;
 
 	if (f->curr_token.kind == Token_OpenBrace) {
@@ -2545,7 +2540,9 @@ AstNode *parse_proc_decl(AstFile *f) {
 		f->curr_proc = curr_proc;
 	}
 
-	return ast_proc_decl(f, token, name, type, body, tags, foreign_library, foreign_name, link_name);
+	AstNode *decl = ast_proc_decl(f, token, name, type, body, tags, link_name);
+	expect_semicolon(f, decl);
+	return decl;
 }
 
 
@@ -2791,7 +2788,7 @@ AstNode *parse_decl(AstFile *f) {
 	default: {
 		Token tok = f->curr_token;
 		fix_advance_to_next_stmt(f);
-		syntax_error(tok, "Expected a declaration");
+		syntax_error(tok, "Expected a declaration got %.*s", LIT(token_strings[tok.kind]));
 		return ast_bad_decl(f, tok, f->curr_token);
 	}
 	}
@@ -2940,7 +2937,7 @@ AstNode *parse_results(AstFile *f) {
 	return list;
 }
 
-AstNode *parse_proc_type(AstFile *f, Token proc_token, AstNode **foreign_library_, String *foreign_name_, String *link_name_) {
+AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) {
 	AstNode *params = {};
 	AstNode *results = {};
 
@@ -2950,15 +2947,11 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token, AstNode **foreign_library
 	results = parse_results(f);
 
 	u64 tags = 0;
-	String foreign_name = {};
 	String link_name = {};
-	AstNode *foreign_library = NULL;
 	ProcCallingConvention cc = ProcCC_Odin;
 
-	parse_proc_tags(f, &tags, &foreign_library, &foreign_name, &link_name, &cc);
+	parse_proc_tags(f, &tags, &link_name, &cc);
 
-	if (foreign_library_) *foreign_library_ = foreign_library;
-	if (foreign_name_)    *foreign_name_    = foreign_name;
 	if (link_name_)       *link_name_       = link_name;
 
 	return ast_proc_type(f, proc_token, params, results, tags, cc);
@@ -3245,18 +3238,6 @@ AstNode *parse_type_or_ident(AstFile *f) {
 		return e;
 	}
 
-	case Token_Hash: {
-		Token hash_token = expect_token(f, Token_Hash);
-		Token name = expect_token(f, Token_Ident);
-		String tag = name.string;
-		if (tag == "type") {
-			AstNode *type = parse_type(f);
-			return ast_helper_type(f, hash_token, type);
-		}
-		syntax_error(name, "Expected `type` after #");
-		return ast_bad_expr(f, hash_token, f->curr_token);
-	}
-
 	case Token_Pointer: {
 		Token token = expect_token(f, Token_Pointer);
 		AstNode *elem = parse_type(f);
@@ -3501,7 +3482,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
 
 	case Token_proc: {
 		Token token = f->curr_token; next_token(f);
-		AstNode *pt = parse_proc_type(f, token, NULL, NULL, NULL);
+		AstNode *pt = parse_proc_type(f, token, NULL);
 		if (pt->ProcType.tags != 0) {
 			syntax_error(token, "A procedure type cannot have tags");
 		}
@@ -3866,6 +3847,29 @@ AstNode *parse_asm_stmt(AstFile *f) {
 
 }
 
+void parse_foreign_block_decl(AstFile *f, Array<AstNode *> *decls) {
+	AstNode *decl = parse_decl(f);
+	switch (decl->kind) {
+	case AstNode_BadDecl:
+		break;
+
+	case AstNode_ProcDecl:
+		array_add(decls, decl);
+		break;
+
+	// case AstNode_GenDecl:
+		// if (decl->GenDecl.token.kind == Token_var) {
+			// array_add(decls, decl);
+			// break;
+		// }
+
+		/* fallthrough */
+	default:
+		error_node(decl, "Only procedures declarations are allowed within a foreign block at the moment");
+		break;
+	}
+}
+
 
 AstNode *parse_stmt(AstFile *f) {
 	AstNode *s = NULL;
@@ -3902,6 +3906,31 @@ AstNode *parse_stmt(AstFile *f) {
 	case Token_foreign_system_library:
 		return parse_decl(f);
 
+	case Token_foreign: {
+		Token token = expect_token(f, Token_foreign);
+		AstNode *foreign_library = parse_ident(f);
+		Token open = {};
+		Token close = {};
+		Array<AstNode *> decls = make_ast_node_array(f);
+
+		if (f->curr_token.kind != Token_OpenBrace) {
+			parse_foreign_block_decl(f, &decls);
+		} else {
+			open = expect_token(f, Token_OpenBrace);
+
+			while (f->curr_token.kind != Token_CloseBrace &&
+			       f->curr_token.kind != Token_EOF) {
+				parse_foreign_block_decl(f, &decls);
+			}
+
+			close = expect_token(f, Token_CloseBrace);
+		}
+
+
+		return ast_foreign_block_decl(f, token, foreign_library, open, close, decls);
+	} break;
+
+
 	case Token_if:     return parse_if_stmt(f);
 	case Token_when:   return parse_when_stmt(f);
 	case Token_for:    return parse_for_stmt(f);

+ 1 - 3
src/ssa.cpp

@@ -2504,9 +2504,7 @@ 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 (pd->foreign_name.len > 0) {
-				name = pd->foreign_name;
-			} else if (pd->link_name.len > 0) {
+			if (pd->link_name.len > 0) {
 				name = pd->link_name;
 			}
 

+ 1 - 0
src/tokenizer.cpp

@@ -88,6 +88,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
 	TOKEN_KIND(Token_type,                   "type"),                   \
 	TOKEN_KIND(Token_import,                 "import"),                 \
 	TOKEN_KIND(Token_import_load,            "import_load"),            \
+	TOKEN_KIND(Token_foreign,                "foreign"),                \
 	TOKEN_KIND(Token_foreign_library,        "foreign_library"),        \
 	TOKEN_KIND(Token_foreign_system_library, "foreign_system_library"), \
 	TOKEN_KIND(Token_when,                   "when"),                   \