From ccda456c0a96f849e408bd707eca0a3baf9202b1 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Mon, 12 Jun 2017 21:21:18 +0100 Subject: [PATCH] `foreign` blocks for procedures --- core/_preload.odin | 24 +- core/bits.odin | 160 +++++----- core/math.odin | 25 +- core/mem.odin | 10 +- core/opengl.odin | 52 ++-- core/os_linux.odin | 39 +-- core/os_x.odin | 39 +-- core/sys/wgl.odin | 34 ++- core/sys/windows.odin | 659 +++++++++++++++++++++--------------------- src/check_decl.cpp | 19 +- src/checker.cpp | 31 +- src/entity.cpp | 1 + src/ir.cpp | 14 +- src/parser.cpp | 181 +++++++----- src/ssa.cpp | 4 +- src/tokenizer.cpp | 1 + 16 files changed, 684 insertions(+), 609 deletions(-) diff --git a/core/_preload.odin b/core/_preload.odin index 1d65cc1c1..6986b0e72 100644 --- a/core/_preload.odin +++ b/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); diff --git a/core/bits.odin b/core/bits.odin index 6bda85488..e65135018 100644 --- a/core/bits.odin +++ b/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)); diff --git a/core/math.odin b/core/math.odin index 1090e6ebe..8a6c492ee 100644 --- a/core/math.odin +++ b/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 { diff --git a/core/mem.odin b/core/mem.odin index 6718d9aeb..dd40fb006 100644 --- a/core/mem.odin +++ b/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); diff --git a/core/opengl.odin b/core/opengl.odin index 1a6e6a38e..2be7b05cc 100644 --- a/core/opengl.odin +++ b/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]; } diff --git a/core/os_linux.odin b/core/os_linux.odin index a9daec277..dd0e6049f 100644 --- a/core/os_linux.odin +++ b/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"; +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 #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_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) #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"; + 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) { diff --git a/core/os_x.odin b/core/os_x.odin index c6b1c6dc2..8a9ab8488 100644 --- a/core/os_x.odin +++ b/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"; +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 #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_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) #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"; + 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) { diff --git a/core/sys/wgl.odin b/core/sys/wgl.odin index 9a082d417..a668790d5 100644 --- a/core/sys/wgl.odin +++ b/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"; +} diff --git a/core/sys/windows.odin b/core/sys/windows.odin index 9d9b812aa..a6b758e5c 100644 --- a/core/sys/windows.odin +++ b/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,50 +283,167 @@ 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 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 set_handle_information(obj: Handle, mask, flags: u32) -> Bool #link_name "SetHandleInformation"; + + 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 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 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 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 post_message(hwnd: Hwnd, msg, wparam, lparam : u32) -> Bool #foreign user32 "PostMessageA"; + 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 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 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"; +} + +foreign gdi32 { + proc get_stock_object(fn_object: i32) -> Hgdiobj #link_name "GetStockObject"; + + 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"; + + 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"; + +} + +foreign shell32 { + proc command_line_to_argv_w(cmd_list: ^u16, num_args: ^i32) -> ^^u16 #link_name "CommandLineToArgvW"; +} + +foreign winmm { + proc time_get_time() -> u32 #link_name "timeGetTime"; +} -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 get_query_performance_frequency() -> i64 { @@ -229,41 +452,14 @@ proc get_query_performance_frequency() -> i64 { return r; } -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"; +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 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 is_key_down(key: KeyCode) -> bool #inline { return get_async_key_state(i32(key)) < 0; } -// File Stuff -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"; - -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"; - -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"; 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, diff --git a/src/check_decl.cpp b/src/check_decl.cpp index c4927bdd6..18c76dd5d 100644 --- a/src/check_decl.cpp +++ b/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); diff --git a/src/checker.cpp b/src/checker.cpp index 518b79e3e..df41c9f86 100644 --- a/src/checker.cpp +++ b/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 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 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 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; } } diff --git a/src/entity.cpp b/src/entity.cpp index db1efd986..32bd3210f 100644 --- a/src/entity.cpp +++ b/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; diff --git a/src/ir.cpp b/src/ir.cpp index da7b052c9..2fafd7a8c 100644 --- a/src/ir.cpp +++ b/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; } diff --git a/src/parser.cpp b/src/parser.cpp index d944e2ee2..747289977 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -139,8 +139,6 @@ Array 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 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 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 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 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 *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 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); diff --git a/src/ssa.cpp b/src/ssa.cpp index 5eef0602d..06da0afa1 100644 --- a/src/ssa.cpp +++ b/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; } diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index fb6e2c779..f5acad5ff 100644 --- a/src/tokenizer.cpp +++ b/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"), \