mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07:00
Merge branch 'odin-lang:master' into master
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
// This is purely for documentation
|
||||
package builtin
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
nil :: nil
|
||||
false :: 0!=0
|
||||
true :: 0==0
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#+build ignore
|
||||
package intrinsics
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
// Package-Related
|
||||
is_package_imported :: proc(package_name: string) -> bool ---
|
||||
|
||||
@@ -72,7 +74,7 @@ prefetch_write_instruction :: proc(address: rawptr, #const locality: i32 /* 0..=
|
||||
prefetch_write_data :: proc(address: rawptr, #const locality: i32 /* 0..=3 */) ---
|
||||
|
||||
// Compiler Hints
|
||||
expect :: proc(val, expected_val: T) -> T ---
|
||||
expect :: proc(val, expected_val: $T) -> T ---
|
||||
|
||||
// Linux and Darwin Only
|
||||
syscall :: proc(id: uintptr, args: ..uintptr) -> uintptr ---
|
||||
@@ -219,7 +221,7 @@ type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info ---
|
||||
type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) ---
|
||||
type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) ---
|
||||
|
||||
type_has_shared_fields :: proc($U, $V: typeid) -> bool typeid where type_is_struct(U), type_is_struct(V) ---
|
||||
type_has_shared_fields :: proc($U, $V: typeid) -> bool where type_is_struct(U), type_is_struct(V) ---
|
||||
|
||||
constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
|
||||
|
||||
|
||||
@@ -826,10 +826,12 @@ _resize_dynamic_array :: #force_inline proc(a: ^Raw_Dynamic_Array, size_of_elem,
|
||||
return nil
|
||||
}
|
||||
|
||||
if should_zero && a.len < length {
|
||||
num_reused := min(a.cap, length) - a.len
|
||||
intrinsics.mem_zero(([^]byte)(a.data)[a.len*size_of_elem:], num_reused*size_of_elem)
|
||||
}
|
||||
|
||||
if length <= a.cap {
|
||||
if should_zero && a.len < length {
|
||||
intrinsics.mem_zero(([^]byte)(a.data)[a.len*size_of_elem:], (length-a.len)*size_of_elem)
|
||||
}
|
||||
a.len = max(length, 0)
|
||||
return nil
|
||||
}
|
||||
@@ -936,6 +938,32 @@ map_upsert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location)
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
Retrieves a pointer to the key and value for a possibly just inserted entry into the map.
|
||||
|
||||
If the `key` was not in the map `m`, an entry is inserted with the zero value and `just_inserted` will be `true`.
|
||||
Otherwise the existing entry is left untouched and pointers to its key and value are returned.
|
||||
|
||||
If the map has to grow in order to insert the entry and the allocation fails, `err` is set and returned.
|
||||
|
||||
If `err` is `nil`, `key_ptr` and `value_ptr` are valid pointers and will not be `nil`.
|
||||
|
||||
WARN: User modification of the key pointed at by `key_ptr` should only be done if the new key is equal to (in hash) the old key.
|
||||
If that is not the case you will corrupt the map.
|
||||
*/
|
||||
@(builtin, require_results)
|
||||
map_entry :: proc(m: ^$T/map[$K]$V, key: K, loc := #caller_location) -> (key_ptr: ^K, value_ptr: ^V, just_inserted: bool, err: Allocator_Error) {
|
||||
key := key
|
||||
zero: V
|
||||
|
||||
_key_ptr, _value_ptr: rawptr
|
||||
_key_ptr, _value_ptr, just_inserted, err = __dynamic_map_entry((^Raw_Map)(m), map_info(T), &key, &zero, loc)
|
||||
|
||||
key_ptr = (^K)(_key_ptr)
|
||||
value_ptr = (^V)(_value_ptr)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@builtin
|
||||
card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
|
||||
@@ -964,6 +992,24 @@ assert :: proc(condition: bool, message := #caller_expression(condition), loc :=
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluates the condition and aborts the program iff the condition is
|
||||
// false. This routine ignores `ODIN_DISABLE_ASSERT`, and will always
|
||||
// execute.
|
||||
@builtin
|
||||
ensure :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
||||
if !condition {
|
||||
@(cold)
|
||||
internal :: proc(message: string, loc: Source_Code_Location) {
|
||||
p := context.assertion_failure_proc
|
||||
if p == nil {
|
||||
p = default_assertion_failure_proc
|
||||
}
|
||||
p("unsatisfied ensure", message, loc)
|
||||
}
|
||||
internal(message, loc)
|
||||
}
|
||||
}
|
||||
|
||||
@builtin
|
||||
panic :: proc(message: string, loc := #caller_location) -> ! {
|
||||
p := context.assertion_failure_proc
|
||||
@@ -999,6 +1045,17 @@ assert_contextless :: proc "contextless" (condition: bool, message := #caller_ex
|
||||
}
|
||||
}
|
||||
|
||||
@builtin
|
||||
ensure_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
||||
if !condition {
|
||||
@(cold)
|
||||
internal :: proc "contextless" (message: string, loc: Source_Code_Location) {
|
||||
default_assertion_contextless_failure_proc("unsatisfied ensure", message, loc)
|
||||
}
|
||||
internal(message, loc)
|
||||
}
|
||||
}
|
||||
|
||||
@builtin
|
||||
panic_contextless :: proc "contextless" (message: string, loc := #caller_location) -> ! {
|
||||
default_assertion_contextless_failure_proc("panic", message, loc)
|
||||
|
||||
@@ -158,21 +158,21 @@ map_cell_index_static :: #force_inline proc "contextless" (cells: [^]Map_Cell($T
|
||||
} else when (N & (N - 1)) == 0 && N <= 8*size_of(uintptr) {
|
||||
// Likely case, N is a power of two because T is a power of two.
|
||||
|
||||
// Unique case, no need to index data here since only one element.
|
||||
when N == 1 {
|
||||
return &cells[index].data[0]
|
||||
}
|
||||
|
||||
// Compute the integer log 2 of N, this is the shift amount to index the
|
||||
// correct cell. Odin's intrinsics.count_leading_zeros does not produce a
|
||||
// constant, hence this approach. We only need to check up to N = 64.
|
||||
SHIFT :: 1 when N < 2 else
|
||||
2 when N < 4 else
|
||||
3 when N < 8 else
|
||||
4 when N < 16 else
|
||||
5 when N < 32 else 6
|
||||
SHIFT :: 1 when N == 2 else
|
||||
2 when N == 4 else
|
||||
3 when N == 8 else
|
||||
4 when N == 16 else
|
||||
5 when N == 32 else 6
|
||||
#assert(SHIFT <= MAP_CACHE_LINE_LOG2)
|
||||
// Unique case, no need to index data here since only one element.
|
||||
when N == 1 {
|
||||
return &cells[index >> SHIFT].data[0]
|
||||
} else {
|
||||
return &cells[index >> SHIFT].data[index & (N - 1)]
|
||||
}
|
||||
return &cells[index >> SHIFT].data[index & (N - 1)]
|
||||
} else {
|
||||
// Least likely (and worst case), we pay for a division operation but we
|
||||
// assume the compiler does not actually generate a division. N will be in the
|
||||
@@ -941,6 +941,29 @@ __dynamic_map_set_extra :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
|
||||
return nil, rawptr(result)
|
||||
}
|
||||
|
||||
__dynamic_map_entry :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key: rawptr, zero: rawptr, loc := #caller_location) -> (key_ptr: rawptr, value_ptr: rawptr, just_inserted: bool, err: Allocator_Error) {
|
||||
hash := info.key_hasher(key, map_seed(m^))
|
||||
|
||||
if key_ptr, value_ptr = __dynamic_map_get_key_and_value(m, info, hash, key); value_ptr != nil {
|
||||
return
|
||||
}
|
||||
|
||||
has_grown: bool
|
||||
if err, has_grown = __dynamic_map_check_grow(m, info, loc); err != nil {
|
||||
return
|
||||
} else if has_grown {
|
||||
hash = info.key_hasher(key, map_seed(m^))
|
||||
}
|
||||
|
||||
value_ptr = rawptr(map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(zero)))
|
||||
assert(value_ptr != nil)
|
||||
key_ptr = rawptr(map_cell_index_dynamic(map_data(m^), info.ks, map_desired_position(m^, hash)))
|
||||
|
||||
m.len += 1
|
||||
just_inserted = true
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// IMPORTANT: USED WITHIN THE COMPILER
|
||||
@(private)
|
||||
|
||||
+2
-2
@@ -110,8 +110,8 @@ Linux)
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath=\$ORIGIN"
|
||||
;;
|
||||
OpenBSD)
|
||||
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
||||
LDFLAGS="$LDFLAGS -liconv"
|
||||
CXXFLAGS="$CXXFLAGS -I/usr/local/include $($LLVM_CONFIG --cxxflags --ldflags)"
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib -liconv"
|
||||
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
|
||||
;;
|
||||
Haiku)
|
||||
|
||||
+230
-148
@@ -1,148 +1,230 @@
|
||||
package encoding_base32
|
||||
|
||||
// @note(zh): Encoding utility for Base32
|
||||
// A secondary param can be used to supply a custom alphabet to
|
||||
// @link(encode) and a matching decoding table to @link(decode).
|
||||
// If none is supplied it just uses the standard Base32 alphabet.
|
||||
// Incase your specific version does not use padding, you may
|
||||
// truncate it from the encoded output.
|
||||
|
||||
ENC_TABLE := [32]byte {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', '2', '3', '4', '5', '6', '7',
|
||||
}
|
||||
|
||||
PADDING :: '='
|
||||
|
||||
DEC_TABLE := [?]u8 {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
}
|
||||
|
||||
encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> string {
|
||||
out_length := (len(data) + 4) / 5 * 8
|
||||
out := make([]byte, out_length)
|
||||
_encode(out, data)
|
||||
return string(out)
|
||||
}
|
||||
|
||||
@private
|
||||
_encode :: proc(out, data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) {
|
||||
out := out
|
||||
data := data
|
||||
|
||||
for len(data) > 0 {
|
||||
carry: byte
|
||||
switch len(data) {
|
||||
case:
|
||||
out[7] = ENC_TABLE[data[4] & 0x1f]
|
||||
carry = data[4] >> 5
|
||||
fallthrough
|
||||
case 4:
|
||||
out[6] = ENC_TABLE[carry | (data[3] << 3) & 0x1f]
|
||||
out[5] = ENC_TABLE[(data[3] >> 2) & 0x1f]
|
||||
carry = data[3] >> 7
|
||||
fallthrough
|
||||
case 3:
|
||||
out[4] = ENC_TABLE[carry | (data[2] << 1) & 0x1f]
|
||||
carry = (data[2] >> 4) & 0x1f
|
||||
fallthrough
|
||||
case 2:
|
||||
out[3] = ENC_TABLE[carry | (data[1] << 4) & 0x1f]
|
||||
out[2] = ENC_TABLE[(data[1] >> 1) & 0x1f]
|
||||
carry = (data[1] >> 6) & 0x1f
|
||||
fallthrough
|
||||
case 1:
|
||||
out[1] = ENC_TABLE[carry | (data[0] << 2) & 0x1f]
|
||||
out[0] = ENC_TABLE[data[0] >> 3]
|
||||
}
|
||||
|
||||
if len(data) < 5 {
|
||||
out[7] = byte(PADDING)
|
||||
if len(data) < 4 {
|
||||
out[6] = byte(PADDING)
|
||||
out[5] = byte(PADDING)
|
||||
if len(data) < 3 {
|
||||
out[4] = byte(PADDING)
|
||||
if len(data) < 2 {
|
||||
out[3] = byte(PADDING)
|
||||
out[2] = byte(PADDING)
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
data = data[5:]
|
||||
out = out[8:]
|
||||
}
|
||||
}
|
||||
|
||||
decode :: proc(data: string, DEC_TBL := DEC_TABLE, allocator := context.allocator) -> []byte #no_bounds_check{
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
outi := 0
|
||||
data := data
|
||||
|
||||
out := make([]byte, len(data) / 8 * 5, allocator)
|
||||
end := false
|
||||
for len(data) > 0 && !end {
|
||||
dbuf : [8]byte
|
||||
dlen := 8
|
||||
|
||||
for j := 0; j < 8; {
|
||||
if len(data) == 0 {
|
||||
dlen, end = j, true
|
||||
break
|
||||
}
|
||||
input := data[0]
|
||||
data = data[1:]
|
||||
if input == byte(PADDING) && j >= 2 && len(data) < 8 {
|
||||
assert(!(len(data) + j < 8 - 1), "Corrupted input")
|
||||
for k := 0; k < 8-1-j; k +=1 {
|
||||
assert(len(data) < k || data[k] == byte(PADDING), "Corrupted input")
|
||||
}
|
||||
dlen, end = j, true
|
||||
assert(dlen != 1 && dlen != 3 && dlen != 6, "Corrupted input")
|
||||
break
|
||||
}
|
||||
dbuf[j] = DEC_TABLE[input]
|
||||
assert(dbuf[j] != 0xff, "Corrupted input")
|
||||
j += 1
|
||||
}
|
||||
|
||||
switch dlen {
|
||||
case 8:
|
||||
out[outi + 4] = dbuf[6] << 5 | dbuf[7]
|
||||
fallthrough
|
||||
case 7:
|
||||
out[outi + 3] = dbuf[4] << 7 | dbuf[5] << 2 | dbuf[6] >> 3
|
||||
fallthrough
|
||||
case 5:
|
||||
out[outi + 2] = dbuf[3] << 4 | dbuf[4] >> 1
|
||||
fallthrough
|
||||
case 4:
|
||||
out[outi + 1] = dbuf[1] << 6 | dbuf[2] << 1 | dbuf[3] >> 4
|
||||
fallthrough
|
||||
case 2:
|
||||
out[outi + 0] = dbuf[0] << 3 | dbuf[1] >> 2
|
||||
}
|
||||
outi += 5
|
||||
}
|
||||
return out
|
||||
}
|
||||
// Base32 encoding/decoding implementation as specified in RFC 4648.
|
||||
// [[ More; https://www.rfc-editor.org/rfc/rfc4648.html ]]
|
||||
package encoding_base32
|
||||
|
||||
// @note(zh): Encoding utility for Base32
|
||||
// A secondary param can be used to supply a custom alphabet to
|
||||
// @link(encode) and a matching decoding table to @link(decode).
|
||||
// If none is supplied it just uses the standard Base32 alphabet.
|
||||
// In case your specific version does not use padding, you may
|
||||
// truncate it from the encoded output.
|
||||
|
||||
// Error represents errors that can occur during base32 decoding operations.
|
||||
// As per RFC 4648:
|
||||
// - Section 3.3: Invalid character handling
|
||||
// - Section 3.2: Padding requirements
|
||||
// - Section 6: Base32 encoding specifics (including block size requirements)
|
||||
Error :: enum {
|
||||
None,
|
||||
Invalid_Character, // Input contains characters outside the specified alphabet
|
||||
Invalid_Length, // Input length is not valid for base32 (must be a multiple of 8 with proper padding)
|
||||
Malformed_Input, // Input has improper structure (wrong padding position or incomplete groups)
|
||||
}
|
||||
|
||||
Validate_Proc :: #type proc(c: byte) -> bool
|
||||
|
||||
@private
|
||||
_validate_default :: proc(c: byte) -> bool {
|
||||
return (c >= 'A' && c <= 'Z') || (c >= '2' && c <= '7')
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
ENC_TABLE := [32]byte {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', '2', '3', '4', '5', '6', '7',
|
||||
}
|
||||
|
||||
PADDING :: '='
|
||||
|
||||
@(rodata)
|
||||
DEC_TABLE := [256]u8 {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
}
|
||||
|
||||
encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> string {
|
||||
out_length := (len(data) + 4) / 5 * 8
|
||||
out := make([]byte, out_length, allocator)
|
||||
_encode(out, data, ENC_TBL)
|
||||
return string(out[:])
|
||||
}
|
||||
|
||||
@private
|
||||
_encode :: proc(out, data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) {
|
||||
out := out
|
||||
data := data
|
||||
|
||||
for len(data) > 0 {
|
||||
carry: byte
|
||||
switch len(data) {
|
||||
case:
|
||||
out[7] = ENC_TBL[data[4] & 0x1f]
|
||||
carry = data[4] >> 5
|
||||
fallthrough
|
||||
case 4:
|
||||
out[6] = ENC_TBL[carry | (data[3] << 3) & 0x1f]
|
||||
out[5] = ENC_TBL[(data[3] >> 2) & 0x1f]
|
||||
carry = data[3] >> 7
|
||||
fallthrough
|
||||
case 3:
|
||||
out[4] = ENC_TBL[carry | (data[2] << 1) & 0x1f]
|
||||
carry = (data[2] >> 4) & 0x1f
|
||||
fallthrough
|
||||
case 2:
|
||||
out[3] = ENC_TBL[carry | (data[1] << 4) & 0x1f]
|
||||
out[2] = ENC_TBL[(data[1] >> 1) & 0x1f]
|
||||
carry = (data[1] >> 6) & 0x1f
|
||||
fallthrough
|
||||
case 1:
|
||||
out[1] = ENC_TBL[carry | (data[0] << 2) & 0x1f]
|
||||
out[0] = ENC_TBL[data[0] >> 3]
|
||||
}
|
||||
|
||||
if len(data) < 5 {
|
||||
out[7] = byte(PADDING)
|
||||
if len(data) < 4 {
|
||||
out[6] = byte(PADDING)
|
||||
out[5] = byte(PADDING)
|
||||
if len(data) < 3 {
|
||||
out[4] = byte(PADDING)
|
||||
if len(data) < 2 {
|
||||
out[3] = byte(PADDING)
|
||||
out[2] = byte(PADDING)
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
data = data[5:]
|
||||
out = out[8:]
|
||||
}
|
||||
}
|
||||
|
||||
@(optimization_mode="favor_size")
|
||||
decode :: proc(
|
||||
data: string,
|
||||
DEC_TBL := DEC_TABLE,
|
||||
validate: Validate_Proc = _validate_default,
|
||||
allocator := context.allocator) -> (out: []byte, err: Error) {
|
||||
if len(data) == 0 {
|
||||
return nil, .None
|
||||
}
|
||||
|
||||
// Check minimum length requirement first
|
||||
if len(data) < 2 {
|
||||
return nil, .Invalid_Length
|
||||
}
|
||||
|
||||
// Validate characters using provided validation function
|
||||
for i := 0; i < len(data); i += 1 {
|
||||
c := data[i]
|
||||
if c == byte(PADDING) {
|
||||
break
|
||||
}
|
||||
if !validate(c) {
|
||||
return nil, .Invalid_Character
|
||||
}
|
||||
}
|
||||
|
||||
// Validate padding and length
|
||||
data_len := len(data)
|
||||
padding_count := 0
|
||||
for i := data_len - 1; i >= 0; i -= 1 {
|
||||
if data[i] != byte(PADDING) {
|
||||
break
|
||||
}
|
||||
padding_count += 1
|
||||
}
|
||||
|
||||
// Check for proper padding and length combinations
|
||||
if padding_count > 0 {
|
||||
// Verify no padding in the middle
|
||||
for i := 0; i < data_len - padding_count; i += 1 {
|
||||
if data[i] == byte(PADDING) {
|
||||
return nil, .Malformed_Input
|
||||
}
|
||||
}
|
||||
|
||||
content_len := data_len - padding_count
|
||||
mod8 := content_len % 8
|
||||
required_padding: int
|
||||
switch mod8 {
|
||||
case 2: required_padding = 6 // 2 chars need 6 padding chars
|
||||
case 4: required_padding = 4 // 4 chars need 4 padding chars
|
||||
case 5: required_padding = 3 // 5 chars need 3 padding chars
|
||||
case 7: required_padding = 1 // 7 chars need 1 padding char
|
||||
case: required_padding = 0
|
||||
}
|
||||
|
||||
if required_padding > 0 {
|
||||
if padding_count != required_padding {
|
||||
return nil, .Malformed_Input
|
||||
}
|
||||
} else if mod8 != 0 {
|
||||
return nil, .Malformed_Input
|
||||
}
|
||||
} else {
|
||||
// No padding - must be multiple of 8
|
||||
if data_len % 8 != 0 {
|
||||
return nil, .Malformed_Input
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate decoded length: 5 bytes for every 8 input chars
|
||||
input_chars := data_len - padding_count
|
||||
out_len := input_chars * 5 / 8
|
||||
out = make([]byte, out_len, allocator)
|
||||
defer if err != .None {
|
||||
delete(out)
|
||||
}
|
||||
|
||||
// Process input in 8-byte blocks
|
||||
outi := 0
|
||||
for i := 0; i < input_chars; i += 8 {
|
||||
buf: [8]byte
|
||||
block_size := min(8, input_chars - i)
|
||||
|
||||
// Decode block
|
||||
for j := 0; j < block_size; j += 1 {
|
||||
buf[j] = DEC_TBL[data[i + j]]
|
||||
}
|
||||
|
||||
// Convert to output bytes based on block size
|
||||
bytes_to_write := block_size * 5 / 8
|
||||
switch block_size {
|
||||
case 8:
|
||||
out[outi + 4] = (buf[6] << 5) | buf[7]
|
||||
fallthrough
|
||||
case 7:
|
||||
out[outi + 3] = (buf[4] << 7) | (buf[5] << 2) | (buf[6] >> 3)
|
||||
fallthrough
|
||||
case 5:
|
||||
out[outi + 2] = (buf[3] << 4) | (buf[4] >> 1)
|
||||
fallthrough
|
||||
case 4:
|
||||
out[outi + 1] = (buf[1] << 6) | (buf[2] << 1) | (buf[3] >> 4)
|
||||
fallthrough
|
||||
case 2:
|
||||
out[outi] = (buf[0] << 3) | (buf[1] >> 2)
|
||||
}
|
||||
outi += bytes_to_write
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
package encoding_base32
|
||||
|
||||
import "core:testing"
|
||||
import "core:bytes"
|
||||
|
||||
@(test)
|
||||
test_base32_decode_valid :: proc(t: ^testing.T) {
|
||||
// RFC 4648 Section 10 - Test vectors
|
||||
cases := [?]struct {
|
||||
input, expected: string,
|
||||
}{
|
||||
{"", ""},
|
||||
{"MY======", "f"},
|
||||
{"MZXQ====", "fo"},
|
||||
{"MZXW6===", "foo"},
|
||||
{"MZXW6YQ=", "foob"},
|
||||
{"MZXW6YTB", "fooba"},
|
||||
{"MZXW6YTBOI======", "foobar"},
|
||||
}
|
||||
|
||||
for c in cases {
|
||||
output, err := decode(c.input)
|
||||
if output != nil {
|
||||
defer delete(output)
|
||||
}
|
||||
testing.expect_value(t, err, Error.None)
|
||||
expected := transmute([]u8)c.expected
|
||||
if output != nil {
|
||||
testing.expect(t, bytes.equal(output, expected))
|
||||
} else {
|
||||
testing.expect(t, len(c.expected) == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_base32_encode :: proc(t: ^testing.T) {
|
||||
// RFC 4648 Section 10 - Test vectors
|
||||
cases := [?]struct {
|
||||
input, expected: string,
|
||||
}{
|
||||
{"", ""},
|
||||
{"f", "MY======"},
|
||||
{"fo", "MZXQ===="},
|
||||
{"foo", "MZXW6==="},
|
||||
{"foob", "MZXW6YQ="},
|
||||
{"fooba", "MZXW6YTB"},
|
||||
{"foobar", "MZXW6YTBOI======"},
|
||||
}
|
||||
|
||||
for c in cases {
|
||||
output := encode(transmute([]byte)c.input)
|
||||
defer delete(output)
|
||||
testing.expect(t, output == c.expected)
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_base32_decode_invalid :: proc(t: ^testing.T) {
|
||||
// Section 3.3 - Non-alphabet characters
|
||||
{
|
||||
// Characters outside alphabet
|
||||
input := "MZ1W6YTB" // '1' not in alphabet (A-Z, 2-7)
|
||||
output, err := decode(input)
|
||||
if output != nil {
|
||||
defer delete(output)
|
||||
}
|
||||
testing.expect_value(t, err, Error.Invalid_Character)
|
||||
}
|
||||
{
|
||||
// Lowercase not allowed
|
||||
input := "mzxq===="
|
||||
output, err := decode(input)
|
||||
if output != nil {
|
||||
defer delete(output)
|
||||
}
|
||||
testing.expect_value(t, err, Error.Invalid_Character)
|
||||
}
|
||||
|
||||
// Section 3.2 - Padding requirements
|
||||
{
|
||||
// Padding must only be at end
|
||||
input := "MZ=Q===="
|
||||
output, err := decode(input)
|
||||
if output != nil {
|
||||
defer delete(output)
|
||||
}
|
||||
testing.expect_value(t, err, Error.Malformed_Input)
|
||||
}
|
||||
{
|
||||
// Missing padding
|
||||
input := "MZXQ" // Should be MZXQ====
|
||||
output, err := decode(input)
|
||||
if output != nil {
|
||||
defer delete(output)
|
||||
}
|
||||
testing.expect_value(t, err, Error.Malformed_Input)
|
||||
}
|
||||
{
|
||||
// Incorrect padding length
|
||||
input := "MZXQ=" // Needs 4 padding chars
|
||||
output, err := decode(input)
|
||||
if output != nil {
|
||||
defer delete(output)
|
||||
}
|
||||
testing.expect_value(t, err, Error.Malformed_Input)
|
||||
}
|
||||
{
|
||||
// Too much padding
|
||||
input := "MY=========" // Extra padding chars
|
||||
output, err := decode(input)
|
||||
if output != nil {
|
||||
defer delete(output)
|
||||
}
|
||||
testing.expect_value(t, err, Error.Malformed_Input)
|
||||
}
|
||||
|
||||
// Section 6 - Base32 block size requirements
|
||||
{
|
||||
// Single character (invalid block)
|
||||
input := "M"
|
||||
output, err := decode(input)
|
||||
if output != nil {
|
||||
defer delete(output)
|
||||
}
|
||||
testing.expect_value(t, err, Error.Invalid_Length)
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_base32_roundtrip :: proc(t: ^testing.T) {
|
||||
cases := [?]string{
|
||||
"",
|
||||
"f",
|
||||
"fo",
|
||||
"foo",
|
||||
"foob",
|
||||
"fooba",
|
||||
"foobar",
|
||||
}
|
||||
|
||||
for input in cases {
|
||||
encoded := encode(transmute([]byte)input)
|
||||
defer delete(encoded)
|
||||
decoded, err := decode(encoded)
|
||||
if decoded != nil {
|
||||
defer delete(decoded)
|
||||
}
|
||||
testing.expect_value(t, err, Error.None)
|
||||
testing.expect(t, bytes.equal(decoded, transmute([]byte)input))
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_base32_custom_alphabet :: proc(t: ^testing.T) {
|
||||
custom_enc_table := [32]byte{
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
|
||||
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
|
||||
}
|
||||
|
||||
custom_dec_table: [256]u8
|
||||
for i := 0; i < len(custom_enc_table); i += 1 {
|
||||
custom_dec_table[custom_enc_table[i]] = u8(i)
|
||||
}
|
||||
|
||||
/*
|
||||
custom_dec_table := [256]u8{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00-0x0f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10-0x1f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20-0x2f
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // 0x30-0x3f ('0'-'9')
|
||||
0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f ('A'-'O')
|
||||
25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x50-0x5f ('P'-'V')
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60-0x6f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70-0x7f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80-0x8f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90-0x9f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xa0-0xaf
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xb0-0xbf
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xc0-0xcf
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xd0-0xdf
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xe0-0xef
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xf0-0xff
|
||||
}
|
||||
*/
|
||||
|
||||
custom_validate :: proc(c: byte) -> bool {
|
||||
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'V') || c == byte(PADDING)
|
||||
}
|
||||
|
||||
cases := [?]struct {
|
||||
input: string,
|
||||
enc_expected: string,
|
||||
}{
|
||||
{"f", "CO======"},
|
||||
{"fo", "CPNG===="},
|
||||
{"foo", "CPNMU==="},
|
||||
}
|
||||
|
||||
for c in cases {
|
||||
// Test encoding
|
||||
encoded := encode(transmute([]byte)c.input, custom_enc_table)
|
||||
defer delete(encoded)
|
||||
testing.expect(t, encoded == c.enc_expected)
|
||||
|
||||
// Test decoding
|
||||
decoded, err := decode(encoded, custom_dec_table, custom_validate)
|
||||
defer if decoded != nil {
|
||||
delete(decoded)
|
||||
}
|
||||
|
||||
testing.expect_value(t, err, Error.None)
|
||||
testing.expect(t, bytes.equal(decoded, transmute([]byte)c.input))
|
||||
}
|
||||
|
||||
// Test invalid character detection
|
||||
{
|
||||
input := "WXY=====" // Contains chars not in our alphabet
|
||||
output, err := decode(input, custom_dec_table, custom_validate)
|
||||
if output != nil {
|
||||
delete(output)
|
||||
}
|
||||
testing.expect_value(t, err, Error.Invalid_Character)
|
||||
}
|
||||
}
|
||||
@@ -439,7 +439,7 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
|
||||
use_field_idx := -1
|
||||
|
||||
for field, field_idx in fields {
|
||||
tag_value := string(reflect.struct_tag_get(field.tag, "json"))
|
||||
tag_value := reflect.struct_tag_get(field.tag, "json")
|
||||
json_name, _ := json_name_from_tag_value(tag_value)
|
||||
if key == json_name {
|
||||
use_field_idx = field_idx
|
||||
@@ -470,7 +470,7 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
|
||||
}
|
||||
}
|
||||
|
||||
if field.name == key {
|
||||
if field.name == key || (field.tag != "" && reflect.struct_tag_get(field.tag, "json") == key) {
|
||||
offset = field.offset
|
||||
type = field.type
|
||||
found = true
|
||||
|
||||
@@ -146,7 +146,7 @@ which_bytes :: proc(data: []byte) -> Which_File_Type {
|
||||
case s[6:10] == "JFIF", s[6:10] == "Exif":
|
||||
return .JPEG
|
||||
case s[:3] == "\xff\xd8\xff":
|
||||
switch s[4] {
|
||||
switch s[3] {
|
||||
case 0xdb, 0xee, 0xe1, 0xe0:
|
||||
return .JPEG
|
||||
}
|
||||
|
||||
+1
-129
@@ -396,132 +396,4 @@ exif :: proc(c: image.PNG_Chunk) -> (res: Exif, ok: bool) {
|
||||
General helper functions
|
||||
*/
|
||||
|
||||
compute_buffer_size :: image.compute_buffer_size
|
||||
|
||||
/*
|
||||
PNG save helpers
|
||||
*/
|
||||
|
||||
when false {
|
||||
|
||||
make_chunk :: proc(c: any, t: Chunk_Type) -> (res: Chunk) {
|
||||
|
||||
data: []u8
|
||||
if v, ok := c.([]u8); ok {
|
||||
data = v
|
||||
} else {
|
||||
data = mem.any_to_bytes(c)
|
||||
}
|
||||
|
||||
res.header.length = u32be(len(data))
|
||||
res.header.type = t
|
||||
res.data = data
|
||||
|
||||
// CRC the type
|
||||
crc := hash.crc32(mem.any_to_bytes(res.header.type))
|
||||
// Extend the CRC with the data
|
||||
res.crc = u32be(hash.crc32(data, crc))
|
||||
return
|
||||
}
|
||||
|
||||
write_chunk :: proc(fd: os.Handle, chunk: Chunk) {
|
||||
c := chunk
|
||||
// Write length + type
|
||||
os.write_ptr(fd, &c.header, 8)
|
||||
// Write data
|
||||
os.write_ptr(fd, mem.raw_data(c.data), int(c.header.length))
|
||||
// Write CRC32
|
||||
os.write_ptr(fd, &c.crc, 4)
|
||||
}
|
||||
|
||||
write_image_as_png :: proc(filename: string, image: Image) -> (err: Error) {
|
||||
profiler.timed_proc()
|
||||
using image
|
||||
using os
|
||||
flags: int = O_WRONLY|O_CREATE|O_TRUNC
|
||||
|
||||
if len(image.pixels) == 0 || len(image.pixels) < image.width * image.height * int(image.channels) {
|
||||
return .Invalid_Image_Dimensions
|
||||
}
|
||||
|
||||
mode: int = 0
|
||||
when ODIN_OS == .Linux || ODIN_OS == .Darwin {
|
||||
// NOTE(justasd): 644 (owner read, write; group read; others read)
|
||||
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
|
||||
}
|
||||
|
||||
fd, fderr := open(filename, flags, mode)
|
||||
if fderr != nil {
|
||||
return .Cannot_Open_File
|
||||
}
|
||||
defer close(fd)
|
||||
|
||||
magic := Signature
|
||||
|
||||
write_ptr(fd, &magic, 8)
|
||||
|
||||
ihdr := IHDR{
|
||||
width = u32be(width),
|
||||
height = u32be(height),
|
||||
bit_depth = depth,
|
||||
compression_method = 0,
|
||||
filter_method = 0,
|
||||
interlace_method = .None,
|
||||
}
|
||||
|
||||
switch channels {
|
||||
case 1: ihdr.color_type = Color_Type{}
|
||||
case 2: ihdr.color_type = Color_Type{.Alpha}
|
||||
case 3: ihdr.color_type = Color_Type{.Color}
|
||||
case 4: ihdr.color_type = Color_Type{.Color, .Alpha}
|
||||
case:// Unhandled
|
||||
return .Unknown_Color_Type
|
||||
}
|
||||
h := make_chunk(ihdr, .IHDR)
|
||||
write_chunk(fd, h)
|
||||
|
||||
bytes_needed := width * height * int(channels) + height
|
||||
filter_bytes := mem.make_dynamic_array_len_cap([dynamic]u8, bytes_needed, bytes_needed, context.allocator)
|
||||
defer delete(filter_bytes)
|
||||
|
||||
i := 0; j := 0
|
||||
// Add a filter byte 0 per pixel row
|
||||
for y := 0; y < height; y += 1 {
|
||||
filter_bytes[j] = 0; j += 1
|
||||
for x := 0; x < width; x += 1 {
|
||||
for z := 0; z < channels; z += 1 {
|
||||
filter_bytes[j+z] = image.pixels[i+z]
|
||||
}
|
||||
i += channels; j += channels
|
||||
}
|
||||
}
|
||||
assert(j == bytes_needed)
|
||||
|
||||
a: []u8 = filter_bytes[:]
|
||||
|
||||
out_buf: ^[dynamic]u8
|
||||
defer free(out_buf)
|
||||
|
||||
ctx := zlib.ZLIB_Context{
|
||||
in_buf = &a,
|
||||
out_buf = out_buf,
|
||||
}
|
||||
err = zlib.write_zlib_stream_from_memory(&ctx)
|
||||
|
||||
b: []u8
|
||||
if err == nil {
|
||||
b = ctx.out_buf[:]
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
||||
idat := make_chunk(b, .IDAT)
|
||||
|
||||
write_chunk(fd, idat)
|
||||
|
||||
iend := make_chunk([]u8{}, .IEND)
|
||||
write_chunk(fd, iend)
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
compute_buffer_size :: image.compute_buffer_size
|
||||
+7
-3
@@ -132,9 +132,13 @@ write_encoded_rune :: proc(w: Writer, r: rune, write_quote := true, n_written: ^
|
||||
buf: [2]byte
|
||||
s := strconv.append_bits(buf[:], u64(r), 16, true, 64, strconv.digits, nil)
|
||||
switch len(s) {
|
||||
case 0: write_string(w, "00", &n) or_return
|
||||
case 1: write_byte(w, '0', &n) or_return
|
||||
case 2: write_string(w, s, &n) or_return
|
||||
case 0:
|
||||
write_string(w, "00", &n) or_return
|
||||
case 1:
|
||||
write_byte(w, '0', &n) or_return
|
||||
fallthrough
|
||||
case 2:
|
||||
write_string(w, s, &n) or_return
|
||||
}
|
||||
} else {
|
||||
write_rune(w, r, &n) or_return
|
||||
|
||||
@@ -417,6 +417,13 @@ adjugate :: proc{
|
||||
matrix4x4_adjugate,
|
||||
}
|
||||
|
||||
cofactor :: proc{
|
||||
matrix1x1_cofactor,
|
||||
matrix2x2_cofactor,
|
||||
matrix3x3_cofactor,
|
||||
matrix4x4_cofactor,
|
||||
}
|
||||
|
||||
inverse_transpose :: proc{
|
||||
matrix1x1_inverse_transpose,
|
||||
matrix2x2_inverse_transpose,
|
||||
@@ -479,9 +486,9 @@ matrix3x3_determinant :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (det: T) #
|
||||
}
|
||||
@(require_results)
|
||||
matrix4x4_determinant :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) #no_bounds_check {
|
||||
a := adjugate(m)
|
||||
c := cofactor(m)
|
||||
for i in 0..<4 {
|
||||
det += m[0, i] * a[0, i]
|
||||
det += m[0, i] * c[0, i]
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -497,6 +504,47 @@ matrix1x1_adjugate :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) #no_bo
|
||||
|
||||
@(require_results)
|
||||
matrix2x2_adjugate :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) #no_bounds_check {
|
||||
y[0, 0] = +x[1, 1]
|
||||
y[0, 1] = -x[0, 1]
|
||||
y[1, 0] = -x[1, 0]
|
||||
y[1, 1] = +x[0, 0]
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix3x3_adjugate :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
|
||||
y[1, 0] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
|
||||
y[2, 0] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
|
||||
y[0, 1] = -(m[0, 1] * m[2, 2] - m[2, 1] * m[0, 2])
|
||||
y[1, 1] = +(m[0, 0] * m[2, 2] - m[2, 0] * m[0, 2])
|
||||
y[2, 1] = -(m[0, 0] * m[2, 1] - m[2, 0] * m[0, 1])
|
||||
y[0, 2] = +(m[0, 1] * m[1, 2] - m[1, 1] * m[0, 2])
|
||||
y[1, 2] = -(m[0, 0] * m[1, 2] - m[1, 0] * m[0, 2])
|
||||
y[2, 2] = +(m[0, 0] * m[1, 1] - m[1, 0] * m[0, 1])
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix4x4_adjugate :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
sign: T = 1 if (i + j) % 2 == 0 else -1
|
||||
y[i, j] = sign * matrix_minor(x, j, i)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
matrix1x1_cofactor :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) #no_bounds_check {
|
||||
y = x
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix2x2_cofactor :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) #no_bounds_check {
|
||||
y[0, 0] = +x[1, 1]
|
||||
y[0, 1] = -x[1, 0]
|
||||
y[1, 0] = -x[0, 1]
|
||||
@@ -505,7 +553,7 @@ matrix2x2_adjugate :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) #no_bo
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix3x3_adjugate :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
matrix3x3_cofactor :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
|
||||
y[0, 1] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
|
||||
y[0, 2] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
|
||||
@@ -520,7 +568,7 @@ matrix3x3_adjugate :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) #no_bo
|
||||
|
||||
|
||||
@(require_results)
|
||||
matrix4x4_adjugate :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
matrix4x4_cofactor :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
sign: T = 1 if (i + j) % 2 == 0 else -1
|
||||
@@ -556,19 +604,19 @@ matrix2x2_inverse_transpose :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y:
|
||||
|
||||
@(require_results)
|
||||
matrix3x3_inverse_transpose :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
c := cofactor(x)
|
||||
d := determinant(x)
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[i, j] / d
|
||||
y[i, j] = c[i, j] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[i, j] * id
|
||||
y[i, j] = c[i, j] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -577,22 +625,22 @@ matrix3x3_inverse_transpose :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y:
|
||||
|
||||
@(require_results)
|
||||
matrix4x4_inverse_transpose :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
c := cofactor(x)
|
||||
d: T
|
||||
for i in 0..<4 {
|
||||
d += x[0, i] * a[0, i]
|
||||
d += x[0, i] * c[0, i]
|
||||
}
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[i, j] / d
|
||||
y[i, j] = c[i, j] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[i, j] * id
|
||||
y[i, j] = c[i, j] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -625,19 +673,19 @@ matrix2x2_inverse :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) #no_bou
|
||||
|
||||
@(require_results)
|
||||
matrix3x3_inverse :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
c := cofactor(x)
|
||||
d := determinant(x)
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[j, i] / d
|
||||
y[i, j] = c[j, i] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[j, i] * id
|
||||
y[i, j] = c[j, i] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -646,22 +694,22 @@ matrix3x3_inverse :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bou
|
||||
|
||||
@(require_results)
|
||||
matrix4x4_inverse :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
c := cofactor(x)
|
||||
d: T
|
||||
for i in 0..<4 {
|
||||
d += x[0, i] * a[0, i]
|
||||
d += x[0, i] * c[0, i]
|
||||
}
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[j, i] / d
|
||||
y[i, j] = c[j, i] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[j, i] * id
|
||||
y[i, j] = c[j, i] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1882,6 +1882,13 @@ adjugate :: proc{
|
||||
adjugate_matrix4x4,
|
||||
}
|
||||
|
||||
cofactor :: proc{
|
||||
cofactor_matrix1x1,
|
||||
cofactor_matrix2x2,
|
||||
cofactor_matrix3x3,
|
||||
cofactor_matrix4x4,
|
||||
}
|
||||
|
||||
inverse_transpose :: proc{
|
||||
inverse_transpose_matrix1x1,
|
||||
inverse_transpose_matrix2x2,
|
||||
@@ -1944,9 +1951,9 @@ determinant_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (det: T) {
|
||||
}
|
||||
@(require_results)
|
||||
determinant_matrix4x4 :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) {
|
||||
a := adjugate(m)
|
||||
c := cofactor(m)
|
||||
#no_bounds_check for i in 0..<4 {
|
||||
det += m[0, i] * a[0, i]
|
||||
det += m[0, i] * c[0, i]
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1962,6 +1969,47 @@ adjugate_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
y[0, 0] = +x[1, 1]
|
||||
y[0, 1] = -x[0, 1]
|
||||
y[1, 0] = -x[1, 0]
|
||||
y[1, 1] = +x[0, 0]
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
|
||||
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
|
||||
y[1, 0] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
|
||||
y[2, 0] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
|
||||
y[0, 1] = -(m[0, 1] * m[2, 2] - m[2, 1] * m[0, 2])
|
||||
y[1, 1] = +(m[0, 0] * m[2, 2] - m[2, 0] * m[0, 2])
|
||||
y[2, 1] = -(m[0, 0] * m[2, 1] - m[2, 0] * m[0, 1])
|
||||
y[0, 2] = +(m[0, 1] * m[1, 2] - m[1, 1] * m[0, 2])
|
||||
y[1, 2] = -(m[0, 0] * m[1, 2] - m[1, 0] * m[0, 2])
|
||||
y[2, 2] = +(m[0, 0] * m[1, 1] - m[1, 0] * m[0, 1])
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
sign: T = 1 if (i + j) % 2 == 0 else -1
|
||||
y[i, j] = sign * matrix_minor(x, j, i)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
cofactor_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
y = x
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
cofactor_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
y[0, 0] = +x[1, 1]
|
||||
y[0, 1] = -x[1, 0]
|
||||
y[1, 0] = -x[0, 1]
|
||||
@@ -1970,7 +2018,7 @@ adjugate_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
|
||||
cofactor_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
|
||||
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
|
||||
y[0, 1] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
|
||||
y[0, 2] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
|
||||
@@ -1985,7 +2033,7 @@ adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
|
||||
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
|
||||
cofactor_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
sign: T = 1 if (i + j) % 2 == 0 else -1
|
||||
@@ -2021,19 +2069,19 @@ inverse_transpose_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y:
|
||||
|
||||
@(require_results)
|
||||
inverse_transpose_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
c := cofactor(x)
|
||||
d := determinant(x)
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[i, j] / d
|
||||
y[i, j] = c[i, j] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[i, j] * id
|
||||
y[i, j] = c[i, j] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2042,22 +2090,22 @@ inverse_transpose_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y:
|
||||
|
||||
@(require_results)
|
||||
inverse_transpose_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
c := cofactor(x)
|
||||
d: T
|
||||
for i in 0..<4 {
|
||||
d += x[0, i] * a[0, i]
|
||||
d += x[0, i] * c[0, i]
|
||||
}
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[i, j] / d
|
||||
y[i, j] = c[i, j] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[i, j] * id
|
||||
y[i, j] = c[i, j] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2090,19 +2138,19 @@ inverse_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
|
||||
@(require_results)
|
||||
inverse_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
c := cofactor(x)
|
||||
d := determinant(x)
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[j, i] / d
|
||||
y[i, j] = c[j, i] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[j, i] * id
|
||||
y[i, j] = c[j, i] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2111,22 +2159,22 @@ inverse_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bou
|
||||
|
||||
@(require_results)
|
||||
inverse_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
c := cofactor(x)
|
||||
d: T
|
||||
for i in 0..<4 {
|
||||
d += x[0, i] * a[0, i]
|
||||
d += x[0, i] * c[0, i]
|
||||
}
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[j, i] / d
|
||||
y[i, j] = c[j, i] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[j, i] * id
|
||||
y[i, j] = c[j, i] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1514,6 +1514,13 @@ adjugate :: proc{
|
||||
adjugate_matrix4x4,
|
||||
}
|
||||
|
||||
cofactor :: proc{
|
||||
cofactor_matrix1x1,
|
||||
cofactor_matrix2x2,
|
||||
cofactor_matrix3x3,
|
||||
cofactor_matrix4x4,
|
||||
}
|
||||
|
||||
inverse_transpose :: proc{
|
||||
inverse_transpose_matrix1x1,
|
||||
inverse_transpose_matrix2x2,
|
||||
@@ -1568,9 +1575,9 @@ determinant_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (det: T) {
|
||||
}
|
||||
@(require_results)
|
||||
determinant_matrix4x4 :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) {
|
||||
a := adjugate(m)
|
||||
c := cofactor(m)
|
||||
#no_bounds_check for i in 0..<4 {
|
||||
det += m[0, i] * a[0, i]
|
||||
det += m[0, i] * c[0, i]
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1586,6 +1593,47 @@ adjugate_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
y[0, 0] = +x[1, 1]
|
||||
y[0, 1] = -x[0, 1]
|
||||
y[1, 0] = -x[1, 0]
|
||||
y[1, 1] = +x[0, 0]
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
|
||||
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
|
||||
y[1, 0] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
|
||||
y[2, 0] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
|
||||
y[0, 1] = -(m[0, 1] * m[2, 2] - m[2, 1] * m[0, 2])
|
||||
y[1, 1] = +(m[0, 0] * m[2, 2] - m[2, 0] * m[0, 2])
|
||||
y[2, 1] = -(m[0, 0] * m[2, 1] - m[2, 0] * m[0, 1])
|
||||
y[0, 2] = +(m[0, 1] * m[1, 2] - m[1, 1] * m[0, 2])
|
||||
y[1, 2] = -(m[0, 0] * m[1, 2] - m[1, 0] * m[0, 2])
|
||||
y[2, 2] = +(m[0, 0] * m[1, 1] - m[1, 0] * m[0, 1])
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
sign: T = 1 if (i + j) % 2 == 0 else -1
|
||||
y[i, j] = sign * matrix_minor(x, j, i)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
cofactor_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
y = x
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
cofactor_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
y[0, 0] = +x[1, 1]
|
||||
y[0, 1] = -x[1, 0]
|
||||
y[1, 0] = -x[0, 1]
|
||||
@@ -1594,7 +1642,7 @@ adjugate_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
|
||||
cofactor_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
|
||||
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
|
||||
y[0, 1] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
|
||||
y[0, 2] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
|
||||
@@ -1609,7 +1657,7 @@ adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
|
||||
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
|
||||
cofactor_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
sign: T = 1 if (i + j) % 2 == 0 else -1
|
||||
@@ -1645,19 +1693,19 @@ inverse_transpose_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y:
|
||||
|
||||
@(require_results)
|
||||
inverse_transpose_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
c := cofactor(x)
|
||||
d := determinant(x)
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[i, j] / d
|
||||
y[i, j] = c[i, j] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[i, j] * id
|
||||
y[i, j] = c[i, j] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1666,22 +1714,22 @@ inverse_transpose_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y:
|
||||
|
||||
@(require_results)
|
||||
inverse_transpose_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
c := cofactor(x)
|
||||
d: T
|
||||
for i in 0..<4 {
|
||||
d += x[0, i] * a[0, i]
|
||||
d += x[0, i] * c[0, i]
|
||||
}
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[i, j] / d
|
||||
y[i, j] = c[i, j] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[i, j] * id
|
||||
y[i, j] = c[i, j] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1714,19 +1762,19 @@ inverse_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
|
||||
@(require_results)
|
||||
inverse_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
c := cofactor(x)
|
||||
d := determinant(x)
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[j, i] / d
|
||||
y[i, j] = c[j, i] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[j, i] * id
|
||||
y[i, j] = c[j, i] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1735,22 +1783,22 @@ inverse_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bou
|
||||
|
||||
@(require_results)
|
||||
inverse_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
c := cofactor(x)
|
||||
d: T
|
||||
for i in 0..<4 {
|
||||
d += x[0, i] * a[0, i]
|
||||
d += x[0, i] * c[0, i]
|
||||
}
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[j, i] / d
|
||||
y[i, j] = c[j, i] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[j, i] * id
|
||||
y[i, j] = c[j, i] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,30 +29,6 @@ Reset the seed used by the context.random_generator.
|
||||
Inputs:
|
||||
- seed: The seed value
|
||||
|
||||
Example:
|
||||
import "core:math/rand"
|
||||
import "core:fmt"
|
||||
|
||||
set_global_seed_example :: proc() {
|
||||
rand.set_global_seed(1)
|
||||
fmt.println(rand.uint64())
|
||||
}
|
||||
|
||||
Possible Output:
|
||||
|
||||
10
|
||||
*/
|
||||
@(deprecated="Prefer `rand.reset`")
|
||||
set_global_seed :: proc(seed: u64) {
|
||||
runtime.random_generator_reset_u64(context.random_generator, seed)
|
||||
}
|
||||
|
||||
/*
|
||||
Reset the seed used by the context.random_generator.
|
||||
|
||||
Inputs:
|
||||
- seed: The seed value
|
||||
|
||||
Example:
|
||||
import "core:math/rand"
|
||||
import "core:fmt"
|
||||
|
||||
@@ -140,14 +140,6 @@ arena_init :: proc(a: ^Arena, data: []byte) {
|
||||
a.temp_count = 0
|
||||
}
|
||||
|
||||
@(deprecated="prefer 'mem.arena_init'")
|
||||
init_arena :: proc(a: ^Arena, data: []byte) {
|
||||
a.data = data
|
||||
a.offset = 0
|
||||
a.peak_used = 0
|
||||
a.temp_count = 0
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate memory from an arena.
|
||||
|
||||
@@ -786,14 +778,6 @@ stack_init :: proc(s: ^Stack, data: []byte) {
|
||||
s.peak_used = 0
|
||||
}
|
||||
|
||||
@(deprecated="prefer 'mem.stack_init'")
|
||||
init_stack :: proc(s: ^Stack, data: []byte) {
|
||||
s.data = data
|
||||
s.prev_offset = 0
|
||||
s.curr_offset = 0
|
||||
s.peak_used = 0
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate memory from stack.
|
||||
|
||||
@@ -1162,13 +1146,6 @@ small_stack_init :: proc(s: ^Small_Stack, data: []byte) {
|
||||
s.peak_used = 0
|
||||
}
|
||||
|
||||
@(deprecated="prefer 'small_stack_init'")
|
||||
init_small_stack :: proc(s: ^Small_Stack, data: []byte) {
|
||||
s.data = data
|
||||
s.offset = 0
|
||||
s.peak_used = 0
|
||||
}
|
||||
|
||||
/*
|
||||
Small stack allocator.
|
||||
|
||||
|
||||
+1
-8
@@ -685,11 +685,4 @@ calc_padding_with_header :: proc "contextless" (ptr: uintptr, align: uintptr, he
|
||||
}
|
||||
}
|
||||
return int(padding)
|
||||
}
|
||||
|
||||
@(require_results, deprecated="prefer 'slice.clone'")
|
||||
clone_slice :: proc(slice: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> (new_slice: T) {
|
||||
new_slice, _ = make(T, len(slice), allocator, loc)
|
||||
runtime.copy(new_slice, slice)
|
||||
return new_slice
|
||||
}
|
||||
}
|
||||
@@ -204,8 +204,9 @@ arena_free_all :: proc(arena: ^Arena, loc := #caller_location) {
|
||||
}
|
||||
// Zero the first block's memory
|
||||
if arena.curr_block != nil {
|
||||
mem.zero(arena.curr_block.base, int(arena.curr_block.used))
|
||||
curr_block_used := int(arena.curr_block.used)
|
||||
arena.curr_block.used = 0
|
||||
mem.zero(arena.curr_block.base, curr_block_used)
|
||||
}
|
||||
arena.total_used = 0
|
||||
case .Static, .Buffer:
|
||||
|
||||
@@ -115,7 +115,7 @@ open :: proc(name: string, flags := File_Flags{.Read}, perm := 0o777) -> (^File,
|
||||
|
||||
@(require_results)
|
||||
new_file :: proc(handle: uintptr, name: string) -> ^File {
|
||||
file, err := _new_file(handle, name)
|
||||
file, err := _new_file(handle, name, file_allocator())
|
||||
if err != nil {
|
||||
panic(error_string(err))
|
||||
}
|
||||
|
||||
+27
-54
@@ -39,37 +39,23 @@ _stderr := File{
|
||||
|
||||
@init
|
||||
_standard_stream_init :: proc() {
|
||||
@static stdin_impl := File_Impl {
|
||||
name = "/proc/self/fd/0",
|
||||
fd = 0,
|
||||
new_std :: proc(impl: ^File_Impl, fd: linux.Fd, name: string) -> ^File {
|
||||
impl.file.impl = impl
|
||||
impl.fd = linux.Fd(fd)
|
||||
impl.allocator = runtime.nil_allocator()
|
||||
impl.name = name
|
||||
impl.file.stream = {
|
||||
data = impl,
|
||||
procedure = _file_stream_proc,
|
||||
}
|
||||
impl.file.fstat = _fstat
|
||||
return &impl.file
|
||||
}
|
||||
|
||||
@static stdout_impl := File_Impl {
|
||||
name = "/proc/self/fd/1",
|
||||
fd = 1,
|
||||
}
|
||||
|
||||
@static stderr_impl := File_Impl {
|
||||
name = "/proc/self/fd/2",
|
||||
fd = 2,
|
||||
}
|
||||
|
||||
stdin_impl.allocator = file_allocator()
|
||||
stdout_impl.allocator = file_allocator()
|
||||
stderr_impl.allocator = file_allocator()
|
||||
|
||||
_stdin.impl = &stdin_impl
|
||||
_stdout.impl = &stdout_impl
|
||||
_stderr.impl = &stderr_impl
|
||||
|
||||
// cannot define these initially because cyclic reference
|
||||
_stdin.stream.data = &stdin_impl
|
||||
_stdout.stream.data = &stdout_impl
|
||||
_stderr.stream.data = &stderr_impl
|
||||
|
||||
stdin = &_stdin
|
||||
stdout = &_stdout
|
||||
stderr = &_stderr
|
||||
@(static) files: [3]File_Impl
|
||||
stdin = new_std(&files[0], 0, "/proc/self/fd/0")
|
||||
stdout = new_std(&files[1], 1, "/proc/self/fd/1")
|
||||
stderr = new_std(&files[2], 2, "/proc/self/fd/2")
|
||||
}
|
||||
|
||||
_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
|
||||
@@ -80,6 +66,9 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err
|
||||
// terminal would be incredibly rare. This has no effect on files while
|
||||
// allowing us to open serial devices.
|
||||
sys_flags: linux.Open_Flags = {.NOCTTY, .CLOEXEC}
|
||||
when size_of(rawptr) == 4 {
|
||||
sys_flags += {.LARGEFILE}
|
||||
}
|
||||
switch flags & (O_RDONLY|O_WRONLY|O_RDWR) {
|
||||
case O_RDONLY:
|
||||
case O_WRONLY: sys_flags += {.WRONLY}
|
||||
@@ -97,18 +86,18 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err
|
||||
return nil, _get_platform_error(errno)
|
||||
}
|
||||
|
||||
return _new_file(uintptr(fd), name)
|
||||
return _new_file(uintptr(fd), name, file_allocator())
|
||||
}
|
||||
|
||||
_new_file :: proc(fd: uintptr, _: string = "") -> (f: ^File, err: Error) {
|
||||
impl := new(File_Impl, file_allocator()) or_return
|
||||
_new_file :: proc(fd: uintptr, _: string, allocator: runtime.Allocator) -> (f: ^File, err: Error) {
|
||||
impl := new(File_Impl, allocator) or_return
|
||||
defer if err != nil {
|
||||
free(impl, file_allocator())
|
||||
free(impl, allocator)
|
||||
}
|
||||
impl.file.impl = impl
|
||||
impl.fd = linux.Fd(fd)
|
||||
impl.allocator = file_allocator()
|
||||
impl.name = _get_full_path(impl.fd, file_allocator()) or_return
|
||||
impl.allocator = allocator
|
||||
impl.name = _get_full_path(impl.fd, impl.allocator) or_return
|
||||
impl.file.stream = {
|
||||
data = impl,
|
||||
procedure = _file_stream_proc,
|
||||
@@ -272,28 +261,12 @@ _truncate :: proc(f: ^File, size: i64) -> Error {
|
||||
}
|
||||
|
||||
_remove :: proc(name: string) -> Error {
|
||||
is_dir_fd :: proc(fd: linux.Fd) -> bool {
|
||||
s: linux.Stat
|
||||
if linux.fstat(fd, &s) != .NONE {
|
||||
return false
|
||||
}
|
||||
return linux.S_ISDIR(s.mode)
|
||||
}
|
||||
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
name_cstr := temp_cstring(name) or_return
|
||||
|
||||
fd, errno := linux.open(name_cstr, {.NOFOLLOW})
|
||||
#partial switch (errno) {
|
||||
case .ELOOP:
|
||||
/* symlink */
|
||||
case .NONE:
|
||||
defer linux.close(fd)
|
||||
if is_dir_fd(fd) {
|
||||
return _get_platform_error(linux.rmdir(name_cstr))
|
||||
}
|
||||
case:
|
||||
return _get_platform_error(errno)
|
||||
if fd, errno := linux.open(name_cstr, _OPENDIR_FLAGS + {.NOFOLLOW}); errno == .NONE {
|
||||
linux.close(fd)
|
||||
return _get_platform_error(linux.rmdir(name_cstr))
|
||||
}
|
||||
|
||||
return _get_platform_error(linux.unlink(name_cstr))
|
||||
|
||||
+29
-20
@@ -21,23 +21,29 @@ File_Impl :: struct {
|
||||
name: string,
|
||||
cname: cstring,
|
||||
fd: posix.FD,
|
||||
allocator: runtime.Allocator,
|
||||
}
|
||||
|
||||
@(init)
|
||||
init_std_files :: proc() {
|
||||
// NOTE: is this (paths) also the case on non darwin?
|
||||
new_std :: proc(impl: ^File_Impl, fd: posix.FD, name: cstring) -> ^File {
|
||||
impl.file.impl = impl
|
||||
impl.fd = fd
|
||||
impl.allocator = runtime.nil_allocator()
|
||||
impl.cname = name
|
||||
impl.name = string(name)
|
||||
impl.file.stream = {
|
||||
data = impl,
|
||||
procedure = _file_stream_proc,
|
||||
}
|
||||
impl.file.fstat = _fstat
|
||||
return &impl.file
|
||||
}
|
||||
|
||||
stdin = __new_file(posix.STDIN_FILENO)
|
||||
(^File_Impl)(stdin.impl).name = "/dev/stdin"
|
||||
(^File_Impl)(stdin.impl).cname = "/dev/stdin"
|
||||
|
||||
stdout = __new_file(posix.STDIN_FILENO)
|
||||
(^File_Impl)(stdout.impl).name = "/dev/stdout"
|
||||
(^File_Impl)(stdout.impl).cname = "/dev/stdout"
|
||||
|
||||
stderr = __new_file(posix.STDIN_FILENO)
|
||||
(^File_Impl)(stderr.impl).name = "/dev/stderr"
|
||||
(^File_Impl)(stderr.impl).cname = "/dev/stderr"
|
||||
@(static) files: [3]File_Impl
|
||||
stdin = new_std(&files[0], posix.STDIN_FILENO, "/dev/stdin")
|
||||
stdout = new_std(&files[1], posix.STDOUT_FILENO, "/dev/stdout")
|
||||
stderr = new_std(&files[2], posix.STDERR_FILENO, "/dev/stderr")
|
||||
}
|
||||
|
||||
_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
|
||||
@@ -72,10 +78,10 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err
|
||||
return
|
||||
}
|
||||
|
||||
return _new_file(uintptr(fd), name)
|
||||
return _new_file(uintptr(fd), name, file_allocator())
|
||||
}
|
||||
|
||||
_new_file :: proc(handle: uintptr, name: string) -> (f: ^File, err: Error) {
|
||||
_new_file :: proc(handle: uintptr, name: string, allocator: runtime.Allocator) -> (f: ^File, err: Error) {
|
||||
if name == "" {
|
||||
err = .Invalid_Path
|
||||
return
|
||||
@@ -84,10 +90,10 @@ _new_file :: proc(handle: uintptr, name: string) -> (f: ^File, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
crname := _posix_absolute_path(posix.FD(handle), name, file_allocator()) or_return
|
||||
crname := _posix_absolute_path(posix.FD(handle), name, allocator) or_return
|
||||
rname := string(crname)
|
||||
|
||||
f = __new_file(posix.FD(handle))
|
||||
f = __new_file(posix.FD(handle), allocator)
|
||||
impl := (^File_Impl)(f.impl)
|
||||
impl.name = rname
|
||||
impl.cname = crname
|
||||
@@ -95,10 +101,11 @@ _new_file :: proc(handle: uintptr, name: string) -> (f: ^File, err: Error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
__new_file :: proc(handle: posix.FD) -> ^File {
|
||||
impl := new(File_Impl, file_allocator())
|
||||
__new_file :: proc(handle: posix.FD, allocator: runtime.Allocator) -> ^File {
|
||||
impl := new(File_Impl, allocator)
|
||||
impl.file.impl = impl
|
||||
impl.fd = posix.FD(handle)
|
||||
impl.allocator = allocator
|
||||
impl.file.stream = {
|
||||
data = impl,
|
||||
procedure = _file_stream_proc,
|
||||
@@ -114,8 +121,10 @@ _close :: proc(f: ^File_Impl) -> (err: Error) {
|
||||
err = _get_platform_error()
|
||||
}
|
||||
|
||||
delete(f.cname, file_allocator())
|
||||
free(f, file_allocator())
|
||||
allocator := f.allocator
|
||||
|
||||
delete(f.cname, allocator)
|
||||
free(f, allocator)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -44,17 +44,38 @@ File_Impl :: struct {
|
||||
|
||||
@(init)
|
||||
init_std_files :: proc() {
|
||||
stdin = new_file(uintptr(win32.GetStdHandle(win32.STD_INPUT_HANDLE)), "<stdin>")
|
||||
stdout = new_file(uintptr(win32.GetStdHandle(win32.STD_OUTPUT_HANDLE)), "<stdout>")
|
||||
stderr = new_file(uintptr(win32.GetStdHandle(win32.STD_ERROR_HANDLE)), "<stderr>")
|
||||
}
|
||||
@(fini)
|
||||
fini_std_files :: proc() {
|
||||
_destroy((^File_Impl)(stdin.impl))
|
||||
_destroy((^File_Impl)(stdout.impl))
|
||||
_destroy((^File_Impl)(stderr.impl))
|
||||
}
|
||||
new_std :: proc(impl: ^File_Impl, code: u32, name: string) -> ^File {
|
||||
impl.file.impl = impl
|
||||
|
||||
impl.allocator = runtime.nil_allocator()
|
||||
impl.fd = win32.GetStdHandle(code)
|
||||
impl.name = name
|
||||
impl.wname = nil
|
||||
|
||||
handle := _handle(&impl.file)
|
||||
kind := File_Impl_Kind.File
|
||||
if m: u32; win32.GetConsoleMode(handle, &m) {
|
||||
kind = .Console
|
||||
}
|
||||
if win32.GetFileType(handle) == win32.FILE_TYPE_PIPE {
|
||||
kind = .Pipe
|
||||
}
|
||||
impl.kind = kind
|
||||
|
||||
impl.file.stream = {
|
||||
data = impl,
|
||||
procedure = _file_stream_proc,
|
||||
}
|
||||
impl.file.fstat = _fstat
|
||||
|
||||
return &impl.file
|
||||
}
|
||||
|
||||
@(static) files: [3]File_Impl
|
||||
stdin = new_std(&files[0], win32.STD_INPUT_HANDLE, "<stdin>")
|
||||
stdout = new_std(&files[1], win32.STD_OUTPUT_HANDLE, "<stdout>")
|
||||
stderr = new_std(&files[2], win32.STD_ERROR_HANDLE, "<stderr>")
|
||||
}
|
||||
|
||||
_handle :: proc(f: ^File) -> win32.HANDLE {
|
||||
return win32.HANDLE(_fd(f))
|
||||
@@ -132,21 +153,21 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u
|
||||
_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
|
||||
flags := flags if flags != nil else {.Read}
|
||||
handle := _open_internal(name, flags, perm) or_return
|
||||
return _new_file(handle, name)
|
||||
return _new_file(handle, name, file_allocator())
|
||||
}
|
||||
|
||||
_new_file :: proc(handle: uintptr, name: string) -> (f: ^File, err: Error) {
|
||||
_new_file :: proc(handle: uintptr, name: string, allocator: runtime.Allocator) -> (f: ^File, err: Error) {
|
||||
if handle == INVALID_HANDLE {
|
||||
return
|
||||
}
|
||||
impl := new(File_Impl, file_allocator()) or_return
|
||||
impl := new(File_Impl, allocator) or_return
|
||||
defer if err != nil {
|
||||
free(impl, file_allocator())
|
||||
free(impl, allocator)
|
||||
}
|
||||
|
||||
impl.file.impl = impl
|
||||
|
||||
impl.allocator = file_allocator()
|
||||
impl.allocator = allocator
|
||||
impl.fd = rawptr(handle)
|
||||
impl.name = clone_string(name, impl.allocator) or_return
|
||||
impl.wname = win32_utf8_to_wstring(name, impl.allocator) or_return
|
||||
@@ -180,7 +201,7 @@ _open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Rea
|
||||
}
|
||||
|
||||
_new_file_buffered :: proc(handle: uintptr, name: string, buffer_size: uint) -> (f: ^File, err: Error) {
|
||||
f, err = _new_file(handle, name)
|
||||
f, err = _new_file(handle, name, file_allocator())
|
||||
if f != nil && err == nil {
|
||||
impl := (^File_Impl)(f.impl)
|
||||
impl.r_buf = make([]byte, buffer_size, file_allocator())
|
||||
|
||||
@@ -415,7 +415,7 @@ _region_resize :: proc(alloc: ^Allocation_Header, new_size: int, alloc_is_free_l
|
||||
back_idx := -1
|
||||
idx: u16
|
||||
infinite: for {
|
||||
for i := 0; i < len(region_iter.hdr.free_list); i += 1 {
|
||||
for i := 0; i < int(region_iter.hdr.free_list_len); i += 1 {
|
||||
idx = region_iter.hdr.free_list[i]
|
||||
if _get_block_count(region_iter.memory[idx]) >= new_block_count {
|
||||
break infinite
|
||||
|
||||
@@ -77,8 +77,6 @@ _mkdir_all :: proc(path: string, perm: int) -> Error {
|
||||
}
|
||||
|
||||
_remove_all :: proc(path: string) -> Error {
|
||||
DT_DIR :: 4
|
||||
|
||||
remove_all_dir :: proc(dfd: linux.Fd) -> Error {
|
||||
n := 64
|
||||
buf := make([]u8, n)
|
||||
|
||||
@@ -10,8 +10,8 @@ _pipe :: proc() -> (r, w: ^File, err: Error) {
|
||||
return nil, nil,_get_platform_error(errno)
|
||||
}
|
||||
|
||||
r = _new_file(uintptr(fds[0])) or_return
|
||||
w = _new_file(uintptr(fds[1])) or_return
|
||||
r = _new_file(uintptr(fds[0]), "", file_allocator()) or_return
|
||||
w = _new_file(uintptr(fds[1]), "", file_allocator()) or_return
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ _pipe :: proc() -> (r, w: ^File, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
r = __new_file(fds[0])
|
||||
r = __new_file(fds[0], file_allocator())
|
||||
ri := (^File_Impl)(r.impl)
|
||||
|
||||
rname := strings.builder_make(file_allocator())
|
||||
@@ -31,7 +31,7 @@ _pipe :: proc() -> (r, w: ^File, err: Error) {
|
||||
ri.name = strings.to_string(rname)
|
||||
ri.cname = strings.to_cstring(&rname)
|
||||
|
||||
w = __new_file(fds[1])
|
||||
w = __new_file(fds[1], file_allocator())
|
||||
wi := (^File_Impl)(w.impl)
|
||||
|
||||
wname := strings.builder_make(file_allocator())
|
||||
|
||||
@@ -290,12 +290,21 @@ process_open :: proc(pid: int, flags := Process_Open_Flags {}) -> (Process, Erro
|
||||
return _process_open(pid, flags)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
OS-specific process attributes.
|
||||
*/
|
||||
Process_Attributes :: struct {
|
||||
sys_attr: _Sys_Process_Attributes,
|
||||
}
|
||||
|
||||
/*
|
||||
The description of how a process should be created.
|
||||
*/
|
||||
Process_Desc :: struct {
|
||||
// OS-specific attributes.
|
||||
sys_attr: _Sys_Process_Attributes,
|
||||
sys_attr: Process_Attributes,
|
||||
|
||||
// The working directory of the process. If the string has length 0, the
|
||||
// working directory is assumed to be the current working directory of the
|
||||
// current process.
|
||||
|
||||
@@ -384,14 +384,6 @@ _Sys_Process_Attributes :: struct {}
|
||||
|
||||
@(private="package")
|
||||
_process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
||||
has_executable_permissions :: proc(fd: linux.Fd) -> bool {
|
||||
backing: [48]u8
|
||||
b := strings.builder_from_bytes(backing[:])
|
||||
strings.write_string(&b, "/proc/self/fd/")
|
||||
strings.write_int(&b, int(fd))
|
||||
return linux.access(strings.to_cstring(&b), linux.X_OK) == .NONE
|
||||
}
|
||||
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
|
||||
if len(desc.command) == 0 {
|
||||
@@ -411,7 +403,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
||||
}
|
||||
|
||||
// search PATH if just a plain name is provided
|
||||
exe_fd: linux.Fd
|
||||
exe_path: cstring
|
||||
executable_name := desc.command[0]
|
||||
if strings.index_byte(executable_name, '/') < 0 {
|
||||
path_env := get_env("PATH", temp_allocator())
|
||||
@@ -426,16 +418,11 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
||||
strings.write_byte(&exe_builder, '/')
|
||||
strings.write_string(&exe_builder, executable_name)
|
||||
|
||||
exe_path := strings.to_cstring(&exe_builder)
|
||||
if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE {
|
||||
continue
|
||||
exe_path = strings.to_cstring(&exe_builder)
|
||||
if linux.access(exe_path, linux.X_OK) == .NONE {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
if !has_executable_permissions(exe_fd) {
|
||||
linux.close(exe_fd)
|
||||
continue
|
||||
}
|
||||
found = true
|
||||
break
|
||||
}
|
||||
if !found {
|
||||
// check in cwd to match windows behavior
|
||||
@@ -443,29 +430,18 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
||||
strings.write_string(&exe_builder, "./")
|
||||
strings.write_string(&exe_builder, executable_name)
|
||||
|
||||
exe_path := strings.to_cstring(&exe_builder)
|
||||
if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE {
|
||||
exe_path = strings.to_cstring(&exe_builder)
|
||||
if linux.access(exe_path, linux.X_OK) != .NONE {
|
||||
return process, .Not_Exist
|
||||
}
|
||||
if !has_executable_permissions(exe_fd) {
|
||||
linux.close(exe_fd)
|
||||
return process, .Permission_Denied
|
||||
}
|
||||
}
|
||||
} else {
|
||||
exe_path := temp_cstring(executable_name) or_return
|
||||
if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE {
|
||||
return process, _get_platform_error(errno)
|
||||
}
|
||||
if !has_executable_permissions(exe_fd) {
|
||||
linux.close(exe_fd)
|
||||
return process, .Permission_Denied
|
||||
exe_path = temp_cstring(executable_name) or_return
|
||||
if linux.access(exe_path, linux.X_OK) != .NONE {
|
||||
return process, .Not_Exist
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, we have an executable.
|
||||
defer linux.close(exe_fd)
|
||||
|
||||
// args and environment need to be a list of cstrings
|
||||
// that are terminated by a nil pointer.
|
||||
cargs := make([]cstring, len(desc.command) + 1, temp_allocator()) or_return
|
||||
@@ -492,7 +468,6 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
||||
}
|
||||
defer linux.close(child_pipe_fds[READ])
|
||||
|
||||
|
||||
// TODO: This is the traditional textbook implementation with fork.
|
||||
// A more efficient implementation with vfork:
|
||||
//
|
||||
@@ -573,7 +548,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
||||
write_errno_to_parent_and_abort(child_pipe_fds[WRITE], errno)
|
||||
}
|
||||
|
||||
errno = linux.execveat(exe_fd, "", &cargs[0], env, {.AT_EMPTY_PATH})
|
||||
errno = linux.execveat(dir_fd, exe_path, &cargs[0], env)
|
||||
assert(errno != nil)
|
||||
write_errno_to_parent_and_abort(child_pipe_fds[WRITE], errno)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ Example:
|
||||
defer spall.context_destroy(&spall_ctx)
|
||||
|
||||
buffer_backing := make([]u8, spall.BUFFER_DEFAULT_SIZE)
|
||||
defer delete(buffer_backing)
|
||||
|
||||
spall_buffer = spall.buffer_create(buffer_backing, u32(sync.current_thread_id()))
|
||||
defer spall.buffer_destroy(&spall_ctx, &spall_buffer)
|
||||
|
||||
|
||||
+58
-36
@@ -152,43 +152,65 @@ Errno :: enum i32 {
|
||||
RDONLY flag is not present, because it has the value of 0, i.e. it is the
|
||||
default, unless WRONLY or RDWR is specified.
|
||||
*/
|
||||
Open_Flags_Bits :: enum {
|
||||
WRONLY = 0,
|
||||
RDWR = 1,
|
||||
CREAT = 6,
|
||||
EXCL = 7,
|
||||
NOCTTY = 8,
|
||||
TRUNC = 9,
|
||||
APPEND = 10,
|
||||
NONBLOCK = 11,
|
||||
DSYNC = 12,
|
||||
ASYNC = 13,
|
||||
DIRECT = 14,
|
||||
LARGEFILE = 15,
|
||||
DIRECTORY = 16,
|
||||
NOFOLLOW = 17,
|
||||
NOATIME = 18,
|
||||
CLOEXEC = 19,
|
||||
PATH = 21,
|
||||
when ODIN_ARCH != .arm64 && ODIN_ARCH != .arm32 {
|
||||
Open_Flags_Bits :: enum {
|
||||
WRONLY = 0,
|
||||
RDWR = 1,
|
||||
CREAT = 6,
|
||||
EXCL = 7,
|
||||
NOCTTY = 8,
|
||||
TRUNC = 9,
|
||||
APPEND = 10,
|
||||
NONBLOCK = 11,
|
||||
DSYNC = 12,
|
||||
ASYNC = 13,
|
||||
DIRECT = 14,
|
||||
LARGEFILE = 15,
|
||||
DIRECTORY = 16,
|
||||
NOFOLLOW = 17,
|
||||
NOATIME = 18,
|
||||
CLOEXEC = 19,
|
||||
PATH = 21,
|
||||
}
|
||||
// https://github.com/torvalds/linux/blob/7367539ad4b0f8f9b396baf02110962333719a48/include/uapi/asm-generic/fcntl.h#L19
|
||||
#assert(1 << uint(Open_Flags_Bits.WRONLY) == 0o0000000_1)
|
||||
#assert(1 << uint(Open_Flags_Bits.RDWR) == 0o0000000_2)
|
||||
#assert(1 << uint(Open_Flags_Bits.CREAT) == 0o00000_100)
|
||||
#assert(1 << uint(Open_Flags_Bits.EXCL) == 0o00000_200)
|
||||
#assert(1 << uint(Open_Flags_Bits.NOCTTY) == 0o00000_400)
|
||||
#assert(1 << uint(Open_Flags_Bits.TRUNC) == 0o0000_1000)
|
||||
#assert(1 << uint(Open_Flags_Bits.APPEND) == 0o0000_2000)
|
||||
#assert(1 << uint(Open_Flags_Bits.NONBLOCK) == 0o0000_4000)
|
||||
#assert(1 << uint(Open_Flags_Bits.DSYNC) == 0o000_10000)
|
||||
#assert(1 << uint(Open_Flags_Bits.ASYNC) == 0o000_20000)
|
||||
#assert(1 << uint(Open_Flags_Bits.DIRECT) == 0o000_40000)
|
||||
#assert(1 << uint(Open_Flags_Bits.LARGEFILE) == 0o00_100000)
|
||||
#assert(1 << uint(Open_Flags_Bits.DIRECTORY) == 0o00_200000)
|
||||
#assert(1 << uint(Open_Flags_Bits.NOFOLLOW) == 0o00_400000)
|
||||
#assert(1 << uint(Open_Flags_Bits.NOATIME) == 0o0_1000000)
|
||||
#assert(1 << uint(Open_Flags_Bits.CLOEXEC) == 0o0_2000000)
|
||||
#assert(1 << uint(Open_Flags_Bits.PATH) == 0o_10000000)
|
||||
} else {
|
||||
Open_Flags_Bits :: enum {
|
||||
WRONLY = 0,
|
||||
RDWR = 1,
|
||||
CREAT = 6,
|
||||
EXCL = 7,
|
||||
NOCTTY = 8,
|
||||
TRUNC = 9,
|
||||
APPEND = 10,
|
||||
NONBLOCK = 11,
|
||||
DSYNC = 12,
|
||||
ASYNC = 13,
|
||||
DIRECTORY = 14,
|
||||
NOFOLLOW = 15,
|
||||
DIRECT = 16,
|
||||
LARGEFILE = 17,
|
||||
NOATIME = 18,
|
||||
CLOEXEC = 19,
|
||||
PATH = 21,
|
||||
}
|
||||
}
|
||||
// https://github.com/torvalds/linux/blob/7367539ad4b0f8f9b396baf02110962333719a48/include/uapi/asm-generic/fcntl.h#L19
|
||||
#assert(1 << uint(Open_Flags_Bits.WRONLY) == 0o0000000_1)
|
||||
#assert(1 << uint(Open_Flags_Bits.RDWR) == 0o0000000_2)
|
||||
#assert(1 << uint(Open_Flags_Bits.CREAT) == 0o00000_100)
|
||||
#assert(1 << uint(Open_Flags_Bits.EXCL) == 0o00000_200)
|
||||
#assert(1 << uint(Open_Flags_Bits.NOCTTY) == 0o00000_400)
|
||||
#assert(1 << uint(Open_Flags_Bits.TRUNC) == 0o0000_1000)
|
||||
#assert(1 << uint(Open_Flags_Bits.APPEND) == 0o0000_2000)
|
||||
#assert(1 << uint(Open_Flags_Bits.NONBLOCK) == 0o0000_4000)
|
||||
#assert(1 << uint(Open_Flags_Bits.DSYNC) == 0o000_10000)
|
||||
#assert(1 << uint(Open_Flags_Bits.ASYNC) == 0o000_20000)
|
||||
#assert(1 << uint(Open_Flags_Bits.DIRECT) == 0o000_40000)
|
||||
#assert(1 << uint(Open_Flags_Bits.LARGEFILE) == 0o00_100000)
|
||||
#assert(1 << uint(Open_Flags_Bits.DIRECTORY) == 0o00_200000)
|
||||
#assert(1 << uint(Open_Flags_Bits.NOFOLLOW) == 0o00_400000)
|
||||
#assert(1 << uint(Open_Flags_Bits.NOATIME) == 0o0_1000000)
|
||||
#assert(1 << uint(Open_Flags_Bits.CLOEXEC) == 0o0_2000000)
|
||||
#assert(1 << uint(Open_Flags_Bits.PATH) == 0o_10000000)
|
||||
|
||||
/*
|
||||
Bits for FD_Flags bitset
|
||||
|
||||
@@ -138,8 +138,8 @@ errno_unwrap :: proc {errno_unwrap2, errno_unwrap3}
|
||||
when size_of(int) == 4 {
|
||||
// xxx64 system calls take some parameters as pairs of ulongs rather than a single pointer
|
||||
@(private)
|
||||
compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (hi: uint, lo: uint) {
|
||||
no_sign := uint(a)
|
||||
compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (lo: uint, hi: uint) {
|
||||
no_sign := u64(a)
|
||||
hi = uint(no_sign >> 32)
|
||||
lo = uint(no_sign & 0xffff_ffff)
|
||||
return
|
||||
|
||||
+25
-15
@@ -151,7 +151,8 @@ lseek :: proc "contextless" (fd: Fd, off: i64, whence: Seek_Whence) -> (i64, Err
|
||||
return errno_unwrap(ret, i64)
|
||||
} else {
|
||||
result: i64 = ---
|
||||
ret := syscall(SYS__llseek, fd, compat64_arg_pair(off), &result, whence)
|
||||
lo, hi := compat64_arg_pair(off)
|
||||
ret := syscall(SYS__llseek, fd, hi, lo, &result, whence)
|
||||
return result, Errno(-ret)
|
||||
}
|
||||
}
|
||||
@@ -251,7 +252,11 @@ ioctl :: proc "contextless" (fd: Fd, request: u32, arg: uintptr) -> (uintptr) {
|
||||
Available since Linux 2.2.
|
||||
*/
|
||||
pread :: proc "contextless" (fd: Fd, buf: []u8, offset: i64) -> (int, Errno) {
|
||||
ret := syscall(SYS_pread64, fd, raw_data(buf), len(buf), compat64_arg_pair(offset))
|
||||
when ODIN_ARCH == .arm32 {
|
||||
ret := syscall(SYS_pread64, fd, raw_data(buf), len(buf), 0, compat64_arg_pair(offset))
|
||||
} else {
|
||||
ret := syscall(SYS_pread64, fd, raw_data(buf), len(buf), compat64_arg_pair(offset))
|
||||
}
|
||||
return errno_unwrap(ret, int)
|
||||
}
|
||||
|
||||
@@ -261,7 +266,11 @@ pread :: proc "contextless" (fd: Fd, buf: []u8, offset: i64) -> (int, Errno) {
|
||||
Available since Linux 2.2.
|
||||
*/
|
||||
pwrite :: proc "contextless" (fd: Fd, buf: []u8, offset: i64) -> (int, Errno) {
|
||||
ret := syscall(SYS_pwrite64, fd, raw_data(buf), len(buf), compat64_arg_pair(offset))
|
||||
when ODIN_ARCH == .arm32 {
|
||||
ret := syscall(SYS_pwrite64, fd, raw_data(buf), len(buf), 0, compat64_arg_pair(offset))
|
||||
} else {
|
||||
ret := syscall(SYS_pwrite64, fd, raw_data(buf), len(buf), compat64_arg_pair(offset))
|
||||
}
|
||||
return errno_unwrap(ret, int)
|
||||
}
|
||||
|
||||
@@ -1127,7 +1136,10 @@ fdatasync :: proc "contextless" (fd: Fd) -> (Errno) {
|
||||
On 32-bit architectures available since Linux 2.4.
|
||||
*/
|
||||
truncate :: proc "contextless" (name: cstring, length: i64) -> (Errno) {
|
||||
when size_of(int) == 4 {
|
||||
when ODIN_ARCH == .arm32 {
|
||||
ret := syscall(SYS_truncate64, cast(rawptr) name, 0, compat64_arg_pair(length))
|
||||
return Errno(-ret)
|
||||
} else when size_of(int) == 4 {
|
||||
ret := syscall(SYS_truncate64, cast(rawptr) name, compat64_arg_pair(length))
|
||||
return Errno(-ret)
|
||||
} else {
|
||||
@@ -1141,7 +1153,10 @@ truncate :: proc "contextless" (name: cstring, length: i64) -> (Errno) {
|
||||
On 32-bit architectures available since 2.4.
|
||||
*/
|
||||
ftruncate :: proc "contextless" (fd: Fd, length: i64) -> (Errno) {
|
||||
when size_of(int) == 4 {
|
||||
when ODIN_ARCH == .arm32 {
|
||||
ret := syscall(SYS_ftruncate64, fd, 0, compat64_arg_pair(length))
|
||||
return Errno(-ret)
|
||||
} else when size_of(int) == 4 {
|
||||
ret := syscall(SYS_ftruncate64, fd, compat64_arg_pair(length))
|
||||
return Errno(-ret)
|
||||
} else {
|
||||
@@ -1952,10 +1967,10 @@ sigaltstack :: proc "contextless" (stack: ^Sig_Stack, old_stack: ^Sig_Stack) ->
|
||||
*/
|
||||
mknod :: proc "contextless" (name: cstring, mode: Mode, dev: Dev) -> (Errno) {
|
||||
when ODIN_ARCH == .arm64 || ODIN_ARCH == .riscv64 {
|
||||
ret := syscall(SYS_mknodat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode, dev)
|
||||
ret := syscall(SYS_mknodat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode, cast(uint) dev)
|
||||
return Errno(-ret)
|
||||
} else {
|
||||
ret := syscall(SYS_mknod, cast(rawptr) name, transmute(u32) mode, dev)
|
||||
ret := syscall(SYS_mknod, cast(rawptr) name, transmute(u32) mode, cast(uint) dev)
|
||||
return Errno(-ret)
|
||||
}
|
||||
}
|
||||
@@ -2586,7 +2601,7 @@ mkdirat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode) -> (Errno)
|
||||
Available since Linux 2.6.16.
|
||||
*/
|
||||
mknodat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode, dev: Dev) -> (Errno) {
|
||||
ret := syscall(SYS_mknodat, dirfd, cast(rawptr) name, transmute(u32) mode, dev)
|
||||
ret := syscall(SYS_mknodat, dirfd, cast(rawptr) name, transmute(u32) mode, cast(uint) dev)
|
||||
return Errno(-ret)
|
||||
}
|
||||
|
||||
@@ -2684,13 +2699,8 @@ faccessat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK) ->
|
||||
Available since Linux 2.6.16.
|
||||
*/
|
||||
ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_Set) -> (i32, Errno) {
|
||||
when size_of(int) == 8 {
|
||||
ret := syscall(SYS_ppoll, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
|
||||
return errno_unwrap(ret, i32)
|
||||
} else {
|
||||
ret := syscall(SYS_ppoll_time64, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
|
||||
return errno_unwrap(ret, i32)
|
||||
}
|
||||
ret := syscall(SYS_ppoll, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
|
||||
return errno_unwrap(ret, i32)
|
||||
}
|
||||
|
||||
// TODO(flysand): unshare
|
||||
|
||||
+166
-66
@@ -3,7 +3,7 @@ package linux
|
||||
/*
|
||||
Type for storage device handle.
|
||||
*/
|
||||
Dev :: distinct int
|
||||
Dev :: distinct u64
|
||||
|
||||
/*
|
||||
Type for 32-bit User IDs.
|
||||
@@ -153,6 +153,7 @@ when ODIN_ARCH == .amd64 {
|
||||
uid: Uid,
|
||||
gid: Gid,
|
||||
rdev: Dev,
|
||||
_: [4]u8,
|
||||
size: i64,
|
||||
blksize: uint,
|
||||
blocks: u64,
|
||||
@@ -516,79 +517,79 @@ Pid_FD_Flags :: bit_set[Pid_FD_Flags_Bits; i32]
|
||||
Sig_Set :: [_SIGSET_NWORDS]uint
|
||||
|
||||
@private SI_MAX_SIZE :: 128
|
||||
@private SI_ARCH_PREAMBLE :: 4 * size_of(i32)
|
||||
@private SI_ARCH_PREAMBLE :: 4 * size_of(i32) when size_of(rawptr) == 8 else 3 * size_of(i32)
|
||||
@private SI_PAD_SIZE :: SI_MAX_SIZE - SI_ARCH_PREAMBLE
|
||||
|
||||
Sig_Handler_Fn :: #type proc "c" (sig: Signal)
|
||||
Sig_Restore_Fn :: #type proc "c" () -> !
|
||||
|
||||
Sig_Info :: struct #packed {
|
||||
signo: Signal,
|
||||
errno: Errno,
|
||||
code: i32,
|
||||
_pad0: i32,
|
||||
using _union: struct #raw_union {
|
||||
_pad1: [SI_PAD_SIZE]u8,
|
||||
using _kill: struct {
|
||||
pid: Pid, /* sender's pid */
|
||||
uid: Uid, /* sender's uid */
|
||||
},
|
||||
using _timer: struct {
|
||||
timerid: i32, /* timer id */
|
||||
overrun: i32, /* overrun count */
|
||||
value: Sig_Val, /* timer value */
|
||||
},
|
||||
/* POSIX.1b signals */
|
||||
using _rt: struct {
|
||||
_pid0: Pid, /* sender's pid */
|
||||
_uid0: Uid, /* sender's uid */
|
||||
},
|
||||
/* SIGCHLD */
|
||||
using _sigchld: struct {
|
||||
_pid1: Pid, /* which child */
|
||||
_uid1: Uid, /* sender's uid */
|
||||
status: i32, /* exit code */
|
||||
utime: uint,
|
||||
stime: uint, //clock_t
|
||||
},
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
using _sigfault: struct {
|
||||
addr: rawptr, /* faulting insn/memory ref. */
|
||||
using _: struct #raw_union {
|
||||
trapno: i32, /* Trap number that caused signal */
|
||||
addr_lsb: i16, /* LSB of the reported address */
|
||||
using _addr_bnd: struct {
|
||||
_pad2: u64,
|
||||
lower: rawptr, /* lower bound during fault */
|
||||
upper: rawptr, /* upper bound during fault */
|
||||
},
|
||||
using _addr_pkey: struct {
|
||||
_pad3: u64,
|
||||
pkey: u32, /* protection key on PTE that faulted */
|
||||
},
|
||||
using _perf: struct {
|
||||
perf_data: u64,
|
||||
perf_type: u32,
|
||||
perf_flags: u32,
|
||||
when size_of(rawptr) == 8 {
|
||||
Sig_Info :: struct #packed {
|
||||
signo: Signal,
|
||||
errno: Errno,
|
||||
code: i32,
|
||||
_pad0: i32,
|
||||
using _union: struct #raw_union {
|
||||
_pad1: [SI_PAD_SIZE]u8,
|
||||
using _kill: struct {
|
||||
pid: Pid, /* sender's pid */
|
||||
uid: Uid, /* sender's uid */
|
||||
},
|
||||
using _timer: struct {
|
||||
timerid: i32, /* timer id */
|
||||
overrun: i32, /* overrun count */
|
||||
value: Sig_Val, /* timer value */
|
||||
},
|
||||
/* POSIX.1b signals */
|
||||
using _rt: struct {
|
||||
_pid0: Pid, /* sender's pid */
|
||||
_uid0: Uid, /* sender's uid */
|
||||
},
|
||||
/* SIGCHLD */
|
||||
using _sigchld: struct {
|
||||
_pid1: Pid, /* which child */
|
||||
_uid1: Uid, /* sender's uid */
|
||||
status: i32, /* exit code */
|
||||
utime: uint,
|
||||
stime: uint, //clock_t
|
||||
},
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
using _sigfault: struct {
|
||||
addr: rawptr, /* faulting insn/memory ref. */
|
||||
using _: struct #raw_union {
|
||||
trapno: i32, /* Trap number that caused signal */
|
||||
addr_lsb: i16, /* LSB of the reported address */
|
||||
using _addr_bnd: struct {
|
||||
_pad2: u64,
|
||||
lower: rawptr, /* lower bound during fault */
|
||||
upper: rawptr, /* upper bound during fault */
|
||||
},
|
||||
using _addr_pkey: struct {
|
||||
_pad3: u64,
|
||||
pkey: u32, /* protection key on PTE that faulted */
|
||||
},
|
||||
using _perf: struct {
|
||||
perf_data: u64,
|
||||
perf_type: u32,
|
||||
perf_flags: u32,
|
||||
},
|
||||
},
|
||||
},
|
||||
/* SIGPOLL */
|
||||
using _sigpoll: struct {
|
||||
band: int, /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
fd: Fd,
|
||||
},
|
||||
/* SIGSYS */
|
||||
using _sigsys: struct {
|
||||
call_addr: rawptr, /* calling user insn */
|
||||
syscall: i32, /* triggering system call number */
|
||||
arch: u32, /* AUDIT_ARCH_* of syscall */
|
||||
},
|
||||
},
|
||||
/* SIGPOLL */
|
||||
using _sigpoll: struct {
|
||||
band: int, /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
fd: Fd,
|
||||
},
|
||||
/* SIGSYS */
|
||||
using _sigsys: struct {
|
||||
call_addr: rawptr, /* calling user insn */
|
||||
syscall: i32, /* triggering system call number */
|
||||
arch: u32, /* AUDIT_ARCH_* of syscall */
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#assert(size_of(Sig_Info) == 128)
|
||||
when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 {
|
||||
#assert(size_of(Sig_Info) == 128)
|
||||
#assert(offset_of(Sig_Info, signo) == 0x00)
|
||||
#assert(offset_of(Sig_Info, errno) == 0x04)
|
||||
#assert(offset_of(Sig_Info, code) == 0x08)
|
||||
@@ -615,7 +616,96 @@ when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 {
|
||||
#assert(offset_of(Sig_Info, syscall) == 0x18)
|
||||
#assert(offset_of(Sig_Info, arch) == 0x1C)
|
||||
} else {
|
||||
// TODO
|
||||
Sig_Info :: struct {
|
||||
signo: Signal,
|
||||
errno: Errno,
|
||||
code: i32,
|
||||
using _union: struct #raw_union {
|
||||
_pad1: [SI_PAD_SIZE]u8,
|
||||
using _kill: struct {
|
||||
pid: Pid, /* sender's pid */
|
||||
uid: Uid, /* sender's uid */
|
||||
},
|
||||
using _timer: struct {
|
||||
timerid: i32, /* timer id */
|
||||
overrun: i32, /* overrun count */
|
||||
value: Sig_Val, /* timer value */
|
||||
},
|
||||
/* POSIX.1b signals */
|
||||
using _rt: struct {
|
||||
_pid0: Pid, /* sender's pid */
|
||||
_uid0: Uid, /* sender's uid */
|
||||
},
|
||||
/* SIGCHLD */
|
||||
using _sigchld: struct {
|
||||
_pid1: Pid, /* which child */
|
||||
_uid1: Uid, /* sender's uid */
|
||||
status: i32, /* exit code */
|
||||
utime: uint,
|
||||
stime: uint, //clock_t
|
||||
},
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
using _sigfault: struct {
|
||||
addr: rawptr, /* faulting insn/memory ref. */
|
||||
using _: struct #raw_union {
|
||||
trapno: i32, /* Trap number that caused signal */
|
||||
addr_lsb: i16, /* LSB of the reported address */
|
||||
using _addr_bnd: struct {
|
||||
_pad2: u32,
|
||||
lower: rawptr, /* lower bound during fault */
|
||||
upper: rawptr, /* upper bound during fault */
|
||||
},
|
||||
using _addr_pkey: struct {
|
||||
_pad3: u32,
|
||||
pkey: u32, /* protection key on PTE that faulted */
|
||||
},
|
||||
using _perf: struct {
|
||||
perf_data: u32,
|
||||
perf_type: u32,
|
||||
perf_flags: u32,
|
||||
},
|
||||
},
|
||||
},
|
||||
/* SIGPOLL */
|
||||
using _sigpoll: struct {
|
||||
band: int, /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
fd: Fd,
|
||||
},
|
||||
/* SIGSYS */
|
||||
using _sigsys: struct {
|
||||
call_addr: rawptr, /* calling user insn */
|
||||
syscall: i32, /* triggering system call number */
|
||||
arch: u32, /* AUDIT_ARCH_* of syscall */
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
#assert(size_of(Sig_Info) == 128)
|
||||
#assert(offset_of(Sig_Info, signo) == 0x00)
|
||||
#assert(offset_of(Sig_Info, errno) == 0x04)
|
||||
#assert(offset_of(Sig_Info, code) == 0x08)
|
||||
#assert(offset_of(Sig_Info, pid) == 0x0c)
|
||||
#assert(offset_of(Sig_Info, uid) == 0x10)
|
||||
#assert(offset_of(Sig_Info, timerid) == 0x0c)
|
||||
#assert(offset_of(Sig_Info, overrun) == 0x10)
|
||||
#assert(offset_of(Sig_Info, value) == 0x14)
|
||||
#assert(offset_of(Sig_Info, status) == 0x14)
|
||||
#assert(offset_of(Sig_Info, utime) == 0x18)
|
||||
#assert(offset_of(Sig_Info, stime) == 0x1c)
|
||||
#assert(offset_of(Sig_Info, addr) == 0x0c)
|
||||
#assert(offset_of(Sig_Info, addr_lsb) == 0x10)
|
||||
#assert(offset_of(Sig_Info, trapno) == 0x10)
|
||||
#assert(offset_of(Sig_Info, lower) == 0x14)
|
||||
#assert(offset_of(Sig_Info, upper) == 0x18)
|
||||
#assert(offset_of(Sig_Info, pkey) == 0x14)
|
||||
#assert(offset_of(Sig_Info, perf_data) == 0x10)
|
||||
#assert(offset_of(Sig_Info, perf_type) == 0x14)
|
||||
#assert(offset_of(Sig_Info, perf_flags) == 0x18)
|
||||
#assert(offset_of(Sig_Info, band) == 0x0c)
|
||||
#assert(offset_of(Sig_Info, fd) == 0x10)
|
||||
#assert(offset_of(Sig_Info, call_addr) == 0x0c)
|
||||
#assert(offset_of(Sig_Info, syscall) == 0x10)
|
||||
#assert(offset_of(Sig_Info, arch) == 0x14)
|
||||
}
|
||||
|
||||
SIGEV_MAX_SIZE :: 64
|
||||
@@ -684,6 +774,14 @@ Address_Family :: distinct Protocol_Family
|
||||
*/
|
||||
Socket_Msg :: bit_set[Socket_Msg_Bits; i32]
|
||||
|
||||
/*
|
||||
Struct representing a generic socket address.
|
||||
*/
|
||||
Sock_Addr :: struct #packed {
|
||||
sa_family: Address_Family,
|
||||
sa_data: [14]u8,
|
||||
}
|
||||
|
||||
/*
|
||||
Struct representing IPv4 socket address.
|
||||
*/
|
||||
@@ -691,6 +789,7 @@ Sock_Addr_In :: struct #packed {
|
||||
sin_family: Address_Family,
|
||||
sin_port: u16be,
|
||||
sin_addr: [4]u8,
|
||||
sin_zero: [size_of(Sock_Addr) - size_of(Address_Family) - size_of(u16be) - size_of([4]u8)]u8,
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -720,6 +819,7 @@ Sock_Addr_Any :: struct #raw_union {
|
||||
family: Address_Family,
|
||||
port: u16be,
|
||||
},
|
||||
using generic: Sock_Addr,
|
||||
using ipv4: Sock_Addr_In,
|
||||
using ipv6: Sock_Addr_In6,
|
||||
using uds: Sock_Addr_Un,
|
||||
|
||||
@@ -20,6 +20,15 @@ COMMON_LVB_GRID_RVERTICAL :: WORD(0x1000)
|
||||
COMMON_LVB_REVERSE_VIDEO :: WORD(0x4000)
|
||||
COMMON_LVB_UNDERSCORE :: WORD(0x8000)
|
||||
COMMON_LVB_SBCSDBCS :: WORD(0x0300)
|
||||
EV_BREAK :: DWORD(0x0040)
|
||||
EV_CTS :: DWORD(0x0008)
|
||||
EV_DSR :: DWORD(0x0010)
|
||||
EV_ERR :: DWORD(0x0080)
|
||||
EV_RING :: DWORD(0x0100)
|
||||
EV_RLSD :: DWORD(0x0020)
|
||||
EV_RXCHAR :: DWORD(0x0001)
|
||||
EV_RXFLAG :: DWORD(0x0002)
|
||||
EV_TXEMPTY :: DWORD(0x0004)
|
||||
|
||||
@(default_calling_convention="system")
|
||||
foreign kernel32 {
|
||||
@@ -109,7 +118,9 @@ foreign kernel32 {
|
||||
ClearCommError :: proc(hFile: HANDLE, lpErrors: ^Com_Error, lpStat: ^COMSTAT) -> BOOL ---
|
||||
GetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL ---
|
||||
SetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL ---
|
||||
GetCommPorts :: proc(lpPortNumbers: PULONG, uPortNumbersCount: ULONG, puPortNumbersFound: PULONG) -> ULONG ---
|
||||
SetCommMask :: proc(handle: HANDLE, dwEvtMap: DWORD) -> BOOL ---
|
||||
GetCommMask :: proc(handle: HANDLE, lpEvtMask: LPDWORD) -> BOOL ---
|
||||
WaitCommEvent :: proc(handle: HANDLE, lpEvtMask: LPDWORD, lpOverlapped: LPOVERLAPPED) -> BOOL ---
|
||||
GetCommandLineW :: proc() -> LPCWSTR ---
|
||||
GetTempPathW :: proc(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD ---
|
||||
GetCurrentProcess :: proc() -> HANDLE ---
|
||||
@@ -239,6 +250,10 @@ foreign kernel32 {
|
||||
hThread: HANDLE,
|
||||
lpContext: LPCONTEXT,
|
||||
) -> BOOL ---
|
||||
SetThreadContext :: proc(
|
||||
hThread: HANDLE,
|
||||
lpContext: LPCONTEXT,
|
||||
) -> BOOL ---
|
||||
CreateProcessW :: proc(
|
||||
lpApplicationName: LPCWSTR,
|
||||
lpCommandLine: LPWSTR,
|
||||
@@ -1068,6 +1083,11 @@ foreign one_core {
|
||||
PageProtection: ULONG,
|
||||
PreferredNode: ULONG,
|
||||
) -> PVOID ---
|
||||
GetCommPorts :: proc(
|
||||
lpPortNumbers: PULONG,
|
||||
uPortNumbersCount: ULONG,
|
||||
puPortNumbersFound: PULONG,
|
||||
) -> ULONG ---
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ LPWSAPROTOCOL_INFO :: ^WSAPROTOCOL_INFO
|
||||
LPSTR :: ^CHAR
|
||||
LPWSTR :: ^WCHAR
|
||||
OLECHAR :: WCHAR
|
||||
BSTR :: ^OLECHAR
|
||||
LPOLESTR :: ^OLECHAR
|
||||
LPCOLESTR :: LPCSTR
|
||||
LPFILETIME :: ^FILETIME
|
||||
@@ -2694,11 +2695,23 @@ EXCEPTION_MAXIMUM_PARAMETERS :: 15
|
||||
|
||||
EXCEPTION_DATATYPE_MISALIGNMENT :: 0x80000002
|
||||
EXCEPTION_BREAKPOINT :: 0x80000003
|
||||
EXCEPTION_SINGLE_STEP :: 0x80000004
|
||||
EXCEPTION_ACCESS_VIOLATION :: 0xC0000005
|
||||
EXCEPTION_IN_PAGE_ERROR :: 0xC0000006
|
||||
EXCEPTION_ILLEGAL_INSTRUCTION :: 0xC000001D
|
||||
EXCEPTION_NONCONTINUABLE_EXCEPTION :: 0xC0000025
|
||||
EXCEPTION_INVALID_DISPOSITION :: 0xC0000026
|
||||
EXCEPTION_ARRAY_BOUNDS_EXCEEDED :: 0xC000008C
|
||||
EXCEPTION_FLT_DENORMAL_OPERAND :: 0xC000008D
|
||||
EXCEPTION_FLT_DIVIDE_BY_ZERO :: 0xC000008E
|
||||
EXCEPTION_FLT_INEXACT_RESULT :: 0xC000008F
|
||||
EXCEPTION_FLT_INVALID_OPERATION :: 0xC0000090
|
||||
EXCEPTION_FLT_OVERFLOW :: 0xC0000091
|
||||
EXCEPTION_FLT_STACK_CHECK :: 0xC0000092
|
||||
EXCEPTION_FLT_UNDERFLOW :: 0xC0000093
|
||||
EXCEPTION_INT_DIVIDE_BY_ZERO :: 0xC0000094
|
||||
EXCEPTION_INT_OVERFLOW :: 0xC0000095
|
||||
EXCEPTION_PRIV_INSTRUCTION :: 0xC0000096
|
||||
EXCEPTION_STACK_OVERFLOW :: 0xC00000FD
|
||||
STATUS_PRIVILEGED_INSTRUCTION :: 0xC0000096
|
||||
|
||||
@@ -3415,8 +3428,6 @@ TIME_ZONE_INFORMATION :: struct {
|
||||
DaylightBias: LONG,
|
||||
}
|
||||
|
||||
|
||||
@(private="file")
|
||||
IMAGE_DOS_HEADER :: struct {
|
||||
e_magic: WORD,
|
||||
e_cblp: WORD,
|
||||
@@ -3534,6 +3545,19 @@ IMAGE_EXPORT_DIRECTORY :: struct {
|
||||
AddressOfNameOrdinals: DWORD, // RVA from base of image
|
||||
}
|
||||
|
||||
IMAGE_DEBUG_DIRECTORY :: struct {
|
||||
Characteristics: DWORD,
|
||||
TimeDateStamp: DWORD,
|
||||
MajorVersion: WORD,
|
||||
MinorVersion: WORD,
|
||||
Type: DWORD,
|
||||
SizeOfData: DWORD,
|
||||
AddressOfRawData: DWORD,
|
||||
PointerToRawData: DWORD,
|
||||
}
|
||||
|
||||
IMAGE_DEBUG_TYPE_CODEVIEW :: 2
|
||||
|
||||
SICHINTF :: DWORD
|
||||
SHCONTF :: DWORD
|
||||
SFGAOF :: ULONG
|
||||
|
||||
@@ -51,6 +51,7 @@ foreign user32 {
|
||||
IsWindowVisible :: proc(hwnd: HWND) -> BOOL ---
|
||||
IsWindowEnabled :: proc(hwnd: HWND) -> BOOL ---
|
||||
IsIconic :: proc(hwnd: HWND) -> BOOL ---
|
||||
IsZoomed :: proc(hwnd: HWND) -> BOOL ---
|
||||
BringWindowToTop :: proc(hWnd: HWND) -> BOOL ---
|
||||
GetTopWindow :: proc(hWnd: HWND) -> HWND ---
|
||||
SetForegroundWindow :: proc(hWnd: HWND) -> BOOL ---
|
||||
|
||||
+153
-141
@@ -11,146 +11,147 @@ TZ_Abbrev :: struct {
|
||||
dst: string,
|
||||
}
|
||||
|
||||
tz_abbrevs := map[string]TZ_Abbrev {
|
||||
"Egypt Standard Time" = {"EET", "EEST"}, // Africa/Cairo
|
||||
"Morocco Standard Time" = {"+00", "+01"}, // Africa/Casablanca
|
||||
"South Africa Standard Time" = {"SAST", "SAST"}, // Africa/Johannesburg
|
||||
"South Sudan Standard Time" = {"CAT", "CAT"}, // Africa/Juba
|
||||
"Sudan Standard Time" = {"CAT", "CAT"}, // Africa/Khartoum
|
||||
"W. Central Africa Standard Time" = {"WAT", "WAT"}, // Africa/Lagos
|
||||
"E. Africa Standard Time" = {"EAT", "EAT"}, // Africa/Nairobi
|
||||
"Sao Tome Standard Time" = {"GMT", "GMT"}, // Africa/Sao_Tome
|
||||
"Libya Standard Time" = {"EET", "EET"}, // Africa/Tripoli
|
||||
"Namibia Standard Time" = {"CAT", "CAT"}, // Africa/Windhoek
|
||||
"Aleutian Standard Time" = {"HST", "HDT"}, // America/Adak
|
||||
"Alaskan Standard Time" = {"AKST", "AKDT"}, // America/Anchorage
|
||||
"Tocantins Standard Time" = {"-03", "-03"}, // America/Araguaina
|
||||
"Paraguay Standard Time" = {"-04", "-03"}, // America/Asuncion
|
||||
"Bahia Standard Time" = {"-03", "-03"}, // America/Bahia
|
||||
"SA Pacific Standard Time" = {"-05", "-05"}, // America/Bogota
|
||||
"Argentina Standard Time" = {"-03", "-03"}, // America/Buenos_Aires
|
||||
"Eastern Standard Time (Mexico)" = {"EST", "EST"}, // America/Cancun
|
||||
"Venezuela Standard Time" = {"-04", "-04"}, // America/Caracas
|
||||
"SA Eastern Standard Time" = {"-03", "-03"}, // America/Cayenne
|
||||
"Central Standard Time" = {"CST", "CDT"}, // America/Chicago
|
||||
"Central Brazilian Standard Time" = {"-04", "-04"}, // America/Cuiaba
|
||||
"Mountain Standard Time" = {"MST", "MDT"}, // America/Denver
|
||||
"Greenland Standard Time" = {"-03", "-02"}, // America/Godthab
|
||||
"Turks And Caicos Standard Time" = {"EST", "EDT"}, // America/Grand_Turk
|
||||
"Central America Standard Time" = {"CST", "CST"}, // America/Guatemala
|
||||
"Atlantic Standard Time" = {"AST", "ADT"}, // America/Halifax
|
||||
"Cuba Standard Time" = {"CST", "CDT"}, // America/Havana
|
||||
"US Eastern Standard Time" = {"EST", "EDT"}, // America/Indianapolis
|
||||
"SA Western Standard Time" = {"-04", "-04"}, // America/La_Paz
|
||||
"Pacific Standard Time" = {"PST", "PDT"}, // America/Los_Angeles
|
||||
"Mountain Standard Time (Mexico)" = {"MST", "MST"}, // America/Mazatlan
|
||||
"Central Standard Time (Mexico)" = {"CST", "CST"}, // America/Mexico_City
|
||||
"Saint Pierre Standard Time" = {"-03", "-02"}, // America/Miquelon
|
||||
"Montevideo Standard Time" = {"-03", "-03"}, // America/Montevideo
|
||||
"Eastern Standard Time" = {"EST", "EDT"}, // America/New_York
|
||||
"US Mountain Standard Time" = {"MST", "MST"}, // America/Phoenix
|
||||
"Haiti Standard Time" = {"EST", "EDT"}, // America/Port-au-Prince
|
||||
"Magallanes Standard Time" = {"-03", "-03"}, // America/Punta_Arenas
|
||||
"Canada Central Standard Time" = {"CST", "CST"}, // America/Regina
|
||||
"Pacific SA Standard Time" = {"-04", "-03"}, // America/Santiago
|
||||
"E. South America Standard Time" = {"-03", "-03"}, // America/Sao_Paulo
|
||||
"Newfoundland Standard Time" = {"NST", "NDT"}, // America/St_Johns
|
||||
"Pacific Standard Time (Mexico)" = {"PST", "PDT"}, // America/Tijuana
|
||||
"Yukon Standard Time" = {"MST", "MST"}, // America/Whitehorse
|
||||
"Central Asia Standard Time" = {"+06", "+06"}, // Asia/Almaty
|
||||
"Jordan Standard Time" = {"+03", "+03"}, // Asia/Amman
|
||||
"Arabic Standard Time" = {"+03", "+03"}, // Asia/Baghdad
|
||||
"Azerbaijan Standard Time" = {"+04", "+04"}, // Asia/Baku
|
||||
"SE Asia Standard Time" = {"+07", "+07"}, // Asia/Bangkok
|
||||
"Altai Standard Time" = {"+07", "+07"}, // Asia/Barnaul
|
||||
"Middle East Standard Time" = {"EET", "EEST"}, // Asia/Beirut
|
||||
"India Standard Time" = {"IST", "IST"}, // Asia/Calcutta
|
||||
"Transbaikal Standard Time" = {"+09", "+09"}, // Asia/Chita
|
||||
"Sri Lanka Standard Time" = {"+0530", "+0530"}, // Asia/Colombo
|
||||
"Syria Standard Time" = {"+03", "+03"}, // Asia/Damascus
|
||||
"Bangladesh Standard Time" = {"+06", "+06"}, // Asia/Dhaka
|
||||
"Arabian Standard Time" = {"+04", "+04"}, // Asia/Dubai
|
||||
"West Bank Standard Time" = {"EET", "EEST"}, // Asia/Hebron
|
||||
"W. Mongolia Standard Time" = {"+07", "+07"}, // Asia/Hovd
|
||||
"North Asia East Standard Time" = {"+08", "+08"}, // Asia/Irkutsk
|
||||
"Israel Standard Time" = {"IST", "IDT"}, // Asia/Jerusalem
|
||||
"Afghanistan Standard Time" = {"+0430", "+0430"}, // Asia/Kabul
|
||||
"Russia Time Zone 11" = {"+12", "+12"}, // Asia/Kamchatka
|
||||
"Pakistan Standard Time" = {"PKT", "PKT"}, // Asia/Karachi
|
||||
"Nepal Standard Time" = {"+0545", "+0545"}, // Asia/Katmandu
|
||||
"North Asia Standard Time" = {"+07", "+07"}, // Asia/Krasnoyarsk
|
||||
"Magadan Standard Time" = {"+11", "+11"}, // Asia/Magadan
|
||||
"N. Central Asia Standard Time" = {"+07", "+07"}, // Asia/Novosibirsk
|
||||
"Omsk Standard Time" = {"+06", "+06"}, // Asia/Omsk
|
||||
"North Korea Standard Time" = {"KST", "KST"}, // Asia/Pyongyang
|
||||
"Qyzylorda Standard Time" = {"+05", "+05"}, // Asia/Qyzylorda
|
||||
"Myanmar Standard Time" = {"+0630", "+0630"}, // Asia/Rangoon
|
||||
"Arab Standard Time" = {"+03", "+03"}, // Asia/Riyadh
|
||||
"Sakhalin Standard Time" = {"+11", "+11"}, // Asia/Sakhalin
|
||||
"Korea Standard Time" = {"KST", "KST"}, // Asia/Seoul
|
||||
"China Standard Time" = {"CST", "CST"}, // Asia/Shanghai
|
||||
"Singapore Standard Time" = {"+08", "+08"}, // Asia/Singapore
|
||||
"Russia Time Zone 10" = {"+11", "+11"}, // Asia/Srednekolymsk
|
||||
"Taipei Standard Time" = {"CST", "CST"}, // Asia/Taipei
|
||||
"West Asia Standard Time" = {"+05", "+05"}, // Asia/Tashkent
|
||||
"Georgian Standard Time" = {"+04", "+04"}, // Asia/Tbilisi
|
||||
"Iran Standard Time" = {"+0330", "+0330"}, // Asia/Tehran
|
||||
"Tokyo Standard Time" = {"JST", "JST"}, // Asia/Tokyo
|
||||
"Tomsk Standard Time" = {"+07", "+07"}, // Asia/Tomsk
|
||||
"Ulaanbaatar Standard Time" = {"+08", "+08"}, // Asia/Ulaanbaatar
|
||||
"Vladivostok Standard Time" = {"+10", "+10"}, // Asia/Vladivostok
|
||||
"Yakutsk Standard Time" = {"+09", "+09"}, // Asia/Yakutsk
|
||||
"Ekaterinburg Standard Time" = {"+05", "+05"}, // Asia/Yekaterinburg
|
||||
"Caucasus Standard Time" = {"+04", "+04"}, // Asia/Yerevan
|
||||
"Azores Standard Time" = {"-01", "+00"}, // Atlantic/Azores
|
||||
"Cape Verde Standard Time" = {"-01", "-01"}, // Atlantic/Cape_Verde
|
||||
"Greenwich Standard Time" = {"GMT", "GMT"}, // Atlantic/Reykjavik
|
||||
"Cen. Australia Standard Time" = {"ACST", "ACDT"}, // Australia/Adelaide
|
||||
"E. Australia Standard Time" = {"AEST", "AEST"}, // Australia/Brisbane
|
||||
"AUS Central Standard Time" = {"ACST", "ACST"}, // Australia/Darwin
|
||||
"Aus Central W. Standard Time" = {"+0845", "+0845"}, // Australia/Eucla
|
||||
"Tasmania Standard Time" = {"AEST", "AEDT"}, // Australia/Hobart
|
||||
"Lord Howe Standard Time" = {"+1030", "+11"}, // Australia/Lord_Howe
|
||||
"W. Australia Standard Time" = {"AWST", "AWST"}, // Australia/Perth
|
||||
"AUS Eastern Standard Time" = {"AEST", "AEDT"}, // Australia/Sydney
|
||||
"UTC-11" = {"-11", "-11"}, // Etc/GMT+11
|
||||
"Dateline Standard Time" = {"-12", "-12"}, // Etc/GMT+12
|
||||
"UTC-02" = {"-02", "-02"}, // Etc/GMT+2
|
||||
"UTC-08" = {"-08", "-08"}, // Etc/GMT+8
|
||||
"UTC-09" = {"-09", "-09"}, // Etc/GMT+9
|
||||
"UTC+12" = {"+12", "+12"}, // Etc/GMT-12
|
||||
"UTC+13" = {"+13", "+13"}, // Etc/GMT-13
|
||||
"UTC" = {"UTC", "UTC"}, // Etc/UTC
|
||||
"Astrakhan Standard Time" = {"+04", "+04"}, // Europe/Astrakhan
|
||||
"W. Europe Standard Time" = {"CET", "CEST"}, // Europe/Berlin
|
||||
"GTB Standard Time" = {"EET", "EEST"}, // Europe/Bucharest
|
||||
"Central Europe Standard Time" = {"CET", "CEST"}, // Europe/Budapest
|
||||
"E. Europe Standard Time" = {"EET", "EEST"}, // Europe/Chisinau
|
||||
"Turkey Standard Time" = {"+03", "+03"}, // Europe/Istanbul
|
||||
"Kaliningrad Standard Time" = {"EET", "EET"}, // Europe/Kaliningrad
|
||||
"FLE Standard Time" = {"EET", "EEST"}, // Europe/Kiev
|
||||
"GMT Standard Time" = {"GMT", "BST"}, // Europe/London
|
||||
"Belarus Standard Time" = {"+03", "+03"}, // Europe/Minsk
|
||||
"Russian Standard Time" = {"MSK", "MSK"}, // Europe/Moscow
|
||||
"Romance Standard Time" = {"CET", "CEST"}, // Europe/Paris
|
||||
"Russia Time Zone 3" = {"+04", "+04"}, // Europe/Samara
|
||||
"Saratov Standard Time" = {"+04", "+04"}, // Europe/Saratov
|
||||
"Volgograd Standard Time" = {"MSK", "MSK"}, // Europe/Volgograd
|
||||
"Central European Standard Time" = {"CET", "CEST"}, // Europe/Warsaw
|
||||
"Mauritius Standard Time" = {"+04", "+04"}, // Indian/Mauritius
|
||||
"Samoa Standard Time" = {"+13", "+13"}, // Pacific/Apia
|
||||
"New Zealand Standard Time" = {"NZST", "NZDT"}, // Pacific/Auckland
|
||||
"Bougainville Standard Time" = {"+11", "+11"}, // Pacific/Bougainville
|
||||
"Chatham Islands Standard Time" = {"+1245", "+1345"}, // Pacific/Chatham
|
||||
"Easter Island Standard Time" = {"-06", "-05"}, // Pacific/Easter
|
||||
"Fiji Standard Time" = {"+12", "+12"}, // Pacific/Fiji
|
||||
"Central Pacific Standard Time" = {"+11", "+11"}, // Pacific/Guadalcanal
|
||||
"Hawaiian Standard Time" = {"HST", "HST"}, // Pacific/Honolulu
|
||||
"Line Islands Standard Time" = {"+14", "+14"}, // Pacific/Kiritimati
|
||||
"Marquesas Standard Time" = {"-0930", "-0930"}, // Pacific/Marquesas
|
||||
"Norfolk Standard Time" = {"+11", "+12"}, // Pacific/Norfolk
|
||||
"West Pacific Standard Time" = {"+10", "+10"}, // Pacific/Port_Moresby
|
||||
"Tonga Standard Time" = {"+13", "+13"}, // Pacific/Tongatapu
|
||||
@(rodata)
|
||||
tz_abbrevs := [?]struct{key: string, value: TZ_Abbrev}{
|
||||
{"Egypt Standard Time", {"EET", "EEST"}}, // Africa/Cairo
|
||||
{"Morocco Standard Time", {"+00", "+01"}}, // Africa/Casablanca
|
||||
{"South Africa Standard Time", {"SAST", "SAST"}}, // Africa/Johannesburg
|
||||
{"South Sudan Standard Time", {"CAT", "CAT"}}, // Africa/Juba
|
||||
{"Sudan Standard Time", {"CAT", "CAT"}}, // Africa/Khartoum
|
||||
{"W. Central Africa Standard Time", {"WAT", "WAT"}}, // Africa/Lagos
|
||||
{"E. Africa Standard Time", {"EAT", "EAT"}}, // Africa/Nairobi
|
||||
{"Sao Tome Standard Time", {"GMT", "GMT"}}, // Africa/Sao_Tome
|
||||
{"Libya Standard Time", {"EET", "EET"}}, // Africa/Tripoli
|
||||
{"Namibia Standard Time", {"CAT", "CAT"}}, // Africa/Windhoek
|
||||
{"Aleutian Standard Time", {"HST", "HDT"}}, // America/Adak
|
||||
{"Alaskan Standard Time", {"AKST", "AKDT"}}, // America/Anchorage
|
||||
{"Tocantins Standard Time", {"-03", "-03"}}, // America/Araguaina
|
||||
{"Paraguay Standard Time", {"-04", "-03"}}, // America/Asuncion
|
||||
{"Bahia Standard Time", {"-03", "-03"}}, // America/Bahia
|
||||
{"SA Pacific Standard Time", {"-05", "-05"}}, // America/Bogota
|
||||
{"Argentina Standard Time", {"-03", "-03"}}, // America/Buenos_Aires
|
||||
{"Eastern Standard Time (Mexico)", {"EST", "EST"}}, // America/Cancun
|
||||
{"Venezuela Standard Time", {"-04", "-04"}}, // America/Caracas
|
||||
{"SA Eastern Standard Time", {"-03", "-03"}}, // America/Cayenne
|
||||
{"Central Standard Time", {"CST", "CDT"}}, // America/Chicago
|
||||
{"Central Brazilian Standard Time", {"-04", "-04"}}, // America/Cuiaba
|
||||
{"Mountain Standard Time", {"MST", "MDT"}}, // America/Denver
|
||||
{"Greenland Standard Time", {"-03", "-02"}}, // America/Godthab
|
||||
{"Turks And Caicos Standard Time", {"EST", "EDT"}}, // America/Grand_Turk
|
||||
{"Central America Standard Time", {"CST", "CST"}}, // America/Guatemala
|
||||
{"Atlantic Standard Time", {"AST", "ADT"}}, // America/Halifax
|
||||
{"Cuba Standard Time", {"CST", "CDT"}}, // America/Havana
|
||||
{"US Eastern Standard Time", {"EST", "EDT"}}, // America/Indianapolis
|
||||
{"SA Western Standard Time", {"-04", "-04"}}, // America/La_Paz
|
||||
{"Pacific Standard Time", {"PST", "PDT"}}, // America/Los_Angeles
|
||||
{"Mountain Standard Time (Mexico)", {"MST", "MST"}}, // America/Mazatlan
|
||||
{"Central Standard Time (Mexico)", {"CST", "CST"}}, // America/Mexico_City
|
||||
{"Saint Pierre Standard Time", {"-03", "-02"}}, // America/Miquelon
|
||||
{"Montevideo Standard Time", {"-03", "-03"}}, // America/Montevideo
|
||||
{"Eastern Standard Time", {"EST", "EDT"}}, // America/New_York
|
||||
{"US Mountain Standard Time", {"MST", "MST"}}, // America/Phoenix
|
||||
{"Haiti Standard Time", {"EST", "EDT"}}, // America/Port-au-Prince
|
||||
{"Magallanes Standard Time", {"-03", "-03"}}, // America/Punta_Arenas
|
||||
{"Canada Central Standard Time", {"CST", "CST"}}, // America/Regina
|
||||
{"Pacific SA Standard Time", {"-04", "-03"}}, // America/Santiago
|
||||
{"E. South America Standard Time", {"-03", "-03"}}, // America/Sao_Paulo
|
||||
{"Newfoundland Standard Time", {"NST", "NDT"}}, // America/St_Johns
|
||||
{"Pacific Standard Time (Mexico)", {"PST", "PDT"}}, // America/Tijuana
|
||||
{"Yukon Standard Time", {"MST", "MST"}}, // America/Whitehorse
|
||||
{"Central Asia Standard Time", {"+06", "+06"}}, // Asia/Almaty
|
||||
{"Jordan Standard Time", {"+03", "+03"}}, // Asia/Amman
|
||||
{"Arabic Standard Time", {"+03", "+03"}}, // Asia/Baghdad
|
||||
{"Azerbaijan Standard Time", {"+04", "+04"}}, // Asia/Baku
|
||||
{"SE Asia Standard Time", {"+07", "+07"}}, // Asia/Bangkok
|
||||
{"Altai Standard Time", {"+07", "+07"}}, // Asia/Barnaul
|
||||
{"Middle East Standard Time", {"EET", "EEST"}}, // Asia/Beirut
|
||||
{"India Standard Time", {"IST", "IST"}}, // Asia/Calcutta
|
||||
{"Transbaikal Standard Time", {"+09", "+09"}}, // Asia/Chita
|
||||
{"Sri Lanka Standard Time", {"+0530", "+0530"}}, // Asia/Colombo
|
||||
{"Syria Standard Time", {"+03", "+03"}}, // Asia/Damascus
|
||||
{"Bangladesh Standard Time", {"+06", "+06"}}, // Asia/Dhaka
|
||||
{"Arabian Standard Time", {"+04", "+04"}}, // Asia/Dubai
|
||||
{"West Bank Standard Time", {"EET", "EEST"}}, // Asia/Hebron
|
||||
{"W. Mongolia Standard Time", {"+07", "+07"}}, // Asia/Hovd
|
||||
{"North Asia East Standard Time", {"+08", "+08"}}, // Asia/Irkutsk
|
||||
{"Israel Standard Time", {"IST", "IDT"}}, // Asia/Jerusalem
|
||||
{"Afghanistan Standard Time", {"+0430", "+0430"}}, // Asia/Kabul
|
||||
{"Russia Time Zone 11", {"+12", "+12"}}, // Asia/Kamchatka
|
||||
{"Pakistan Standard Time", {"PKT", "PKT"}}, // Asia/Karachi
|
||||
{"Nepal Standard Time", {"+0545", "+0545"}}, // Asia/Katmandu
|
||||
{"North Asia Standard Time", {"+07", "+07"}}, // Asia/Krasnoyarsk
|
||||
{"Magadan Standard Time", {"+11", "+11"}}, // Asia/Magadan
|
||||
{"N. Central Asia Standard Time", {"+07", "+07"}}, // Asia/Novosibirsk
|
||||
{"Omsk Standard Time", {"+06", "+06"}}, // Asia/Omsk
|
||||
{"North Korea Standard Time", {"KST", "KST"}}, // Asia/Pyongyang
|
||||
{"Qyzylorda Standard Time", {"+05", "+05"}}, // Asia/Qyzylorda
|
||||
{"Myanmar Standard Time", {"+0630", "+0630"}}, // Asia/Rangoon
|
||||
{"Arab Standard Time", {"+03", "+03"}}, // Asia/Riyadh
|
||||
{"Sakhalin Standard Time", {"+11", "+11"}}, // Asia/Sakhalin
|
||||
{"Korea Standard Time", {"KST", "KST"}}, // Asia/Seoul
|
||||
{"China Standard Time", {"CST", "CST"}}, // Asia/Shanghai
|
||||
{"Singapore Standard Time", {"+08", "+08"}}, // Asia/Singapore
|
||||
{"Russia Time Zone 10", {"+11", "+11"}}, // Asia/Srednekolymsk
|
||||
{"Taipei Standard Time", {"CST", "CST"}}, // Asia/Taipei
|
||||
{"West Asia Standard Time", {"+05", "+05"}}, // Asia/Tashkent
|
||||
{"Georgian Standard Time", {"+04", "+04"}}, // Asia/Tbilisi
|
||||
{"Iran Standard Time", {"+0330", "+0330"}}, // Asia/Tehran
|
||||
{"Tokyo Standard Time", {"JST", "JST"}}, // Asia/Tokyo
|
||||
{"Tomsk Standard Time", {"+07", "+07"}}, // Asia/Tomsk
|
||||
{"Ulaanbaatar Standard Time", {"+08", "+08"}}, // Asia/Ulaanbaatar
|
||||
{"Vladivostok Standard Time", {"+10", "+10"}}, // Asia/Vladivostok
|
||||
{"Yakutsk Standard Time", {"+09", "+09"}}, // Asia/Yakutsk
|
||||
{"Ekaterinburg Standard Time", {"+05", "+05"}}, // Asia/Yekaterinburg
|
||||
{"Caucasus Standard Time", {"+04", "+04"}}, // Asia/Yerevan
|
||||
{"Azores Standard Time", {"-01", "+00"}}, // Atlantic/Azores
|
||||
{"Cape Verde Standard Time", {"-01", "-01"}}, // Atlantic/Cape_Verde
|
||||
{"Greenwich Standard Time", {"GMT", "GMT"}}, // Atlantic/Reykjavik
|
||||
{"Cen. Australia Standard Time", {"ACST", "ACDT"}}, // Australia/Adelaide
|
||||
{"E. Australia Standard Time", {"AEST", "AEST"}}, // Australia/Brisbane
|
||||
{"AUS Central Standard Time", {"ACST", "ACST"}}, // Australia/Darwin
|
||||
{"Aus Central W. Standard Time", {"+0845", "+0845"}}, // Australia/Eucla
|
||||
{"Tasmania Standard Time", {"AEST", "AEDT"}}, // Australia/Hobart
|
||||
{"Lord Howe Standard Time", {"+1030", "+11"}}, // Australia/Lord_Howe
|
||||
{"W. Australia Standard Time", {"AWST", "AWST"}}, // Australia/Perth
|
||||
{"AUS Eastern Standard Time", {"AEST", "AEDT"}}, // Australia/Sydney
|
||||
{"UTC-11", {"-11", "-11"}}, // Etc/GMT+11
|
||||
{"Dateline Standard Time", {"-12", "-12"}}, // Etc/GMT+12
|
||||
{"UTC-02", {"-02", "-02"}}, // Etc/GMT+2
|
||||
{"UTC-08", {"-08", "-08"}}, // Etc/GMT+8
|
||||
{"UTC-09", {"-09", "-09"}}, // Etc/GMT+9
|
||||
{"UTC+12", {"+12", "+12"}}, // Etc/GMT-12
|
||||
{"UTC+13", {"+13", "+13"}}, // Etc/GMT-13
|
||||
{"UTC", {"UTC", "UTC"}}, // Etc/UTC
|
||||
{"Astrakhan Standard Time", {"+04", "+04"}}, // Europe/Astrakhan
|
||||
{"W. Europe Standard Time", {"CET", "CEST"}}, // Europe/Berlin
|
||||
{"GTB Standard Time", {"EET", "EEST"}}, // Europe/Bucharest
|
||||
{"Central Europe Standard Time", {"CET", "CEST"}}, // Europe/Budapest
|
||||
{"E. Europe Standard Time", {"EET", "EEST"}}, // Europe/Chisinau
|
||||
{"Turkey Standard Time", {"+03", "+03"}}, // Europe/Istanbul
|
||||
{"Kaliningrad Standard Time", {"EET", "EET"}}, // Europe/Kaliningrad
|
||||
{"FLE Standard Time", {"EET", "EEST"}}, // Europe/Kiev
|
||||
{"GMT Standard Time", {"GMT", "BST"}}, // Europe/London
|
||||
{"Belarus Standard Time", {"+03", "+03"}}, // Europe/Minsk
|
||||
{"Russian Standard Time", {"MSK", "MSK"}}, // Europe/Moscow
|
||||
{"Romance Standard Time", {"CET", "CEST"}}, // Europe/Paris
|
||||
{"Russia Time Zone 3", {"+04", "+04"}}, // Europe/Samara
|
||||
{"Saratov Standard Time", {"+04", "+04"}}, // Europe/Saratov
|
||||
{"Volgograd Standard Time", {"MSK", "MSK"}}, // Europe/Volgograd
|
||||
{"Central European Standard Time", {"CET", "CEST"}}, // Europe/Warsaw
|
||||
{"Mauritius Standard Time", {"+04", "+04"}}, // Indian/Mauritius
|
||||
{"Samoa Standard Time", {"+13", "+13"}}, // Pacific/Apia
|
||||
{"New Zealand Standard Time", {"NZST", "NZDT"}}, // Pacific/Auckland
|
||||
{"Bougainville Standard Time", {"+11", "+11"}}, // Pacific/Bougainville
|
||||
{"Chatham Islands Standard Time", {"+1245", "+1345"}}, // Pacific/Chatham
|
||||
{"Easter Island Standard Time", {"-06", "-05"}}, // Pacific/Easter
|
||||
{"Fiji Standard Time", {"+12", "+12"}}, // Pacific/Fiji
|
||||
{"Central Pacific Standard Time", {"+11", "+11"}}, // Pacific/Guadalcanal
|
||||
{"Hawaiian Standard Time", {"HST", "HST"}}, // Pacific/Honolulu
|
||||
{"Line Islands Standard Time", {"+14", "+14"}}, // Pacific/Kiritimati
|
||||
{"Marquesas Standard Time", {"-0930", "-0930"}}, // Pacific/Marquesas
|
||||
{"Norfolk Standard Time", {"+11", "+12"}}, // Pacific/Norfolk
|
||||
{"West Pacific Standard Time", {"+10", "+10"}}, // Pacific/Port_Moresby
|
||||
{"Tonga Standard Time", {"+13", "+13"}}, // Pacific/Tongatapu
|
||||
}
|
||||
|
||||
iana_to_windows_tz :: proc(iana_name: string, allocator := context.allocator) -> (name: string, success: bool) {
|
||||
@@ -269,7 +270,18 @@ _region_load :: proc(reg_str: string, allocator := context.allocator) -> (out_re
|
||||
defer delete(wintz_name, allocator)
|
||||
defer delete(iana_name, allocator)
|
||||
|
||||
abbrevs := tz_abbrevs[wintz_name] or_return
|
||||
abbrevs: TZ_Abbrev
|
||||
abbrevs_ok: bool
|
||||
for pair in tz_abbrevs {
|
||||
if pair.key == wintz_name {
|
||||
abbrevs = pair.value
|
||||
abbrevs_ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !abbrevs_ok {
|
||||
return
|
||||
}
|
||||
if abbrevs.std == "UTC" && abbrevs.dst == abbrevs.std {
|
||||
return nil, true
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#+vet !using-stmt !using-param
|
||||
#+feature dynamic-literals
|
||||
package main
|
||||
|
||||
import "core:fmt"
|
||||
|
||||
+12
-6
@@ -324,6 +324,18 @@ u64 get_vet_flag_from_name(String const &name) {
|
||||
return VetFlag_NONE;
|
||||
}
|
||||
|
||||
enum OptInFeatureFlags : u64 {
|
||||
OptInFeatureFlag_NONE = 0,
|
||||
OptInFeatureFlag_DynamicLiterals = 1u<<0,
|
||||
};
|
||||
|
||||
u64 get_feature_flag_from_name(String const &name) {
|
||||
if (name == "dynamic-literals") {
|
||||
return OptInFeatureFlag_DynamicLiterals;
|
||||
}
|
||||
return OptInFeatureFlag_NONE;
|
||||
}
|
||||
|
||||
|
||||
enum SanitizerFlags : u32 {
|
||||
SanitizerFlag_NONE = 0,
|
||||
@@ -429,7 +441,6 @@ struct BuildContext {
|
||||
bool ignore_unknown_attributes;
|
||||
bool no_bounds_check;
|
||||
bool no_type_assert;
|
||||
bool no_dynamic_literals;
|
||||
bool no_output_files;
|
||||
bool no_crt;
|
||||
bool no_rpath;
|
||||
@@ -1855,11 +1866,6 @@ gb_internal bool init_build_paths(String init_filename) {
|
||||
produces_output_file = true;
|
||||
}
|
||||
|
||||
if (build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR ||
|
||||
build_context.ODIN_DEFAULT_TO_PANIC_ALLOCATOR) {
|
||||
bc->no_dynamic_literals = true;
|
||||
}
|
||||
|
||||
if (!produces_output_file) {
|
||||
// Command doesn't produce output files. We're done.
|
||||
return true;
|
||||
|
||||
+48
-50
@@ -94,12 +94,14 @@ gb_internal Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *o
|
||||
return nullptr;
|
||||
}
|
||||
if (e2->state.load() != EntityState_Resolved) {
|
||||
gbString str = type_to_string(t);
|
||||
defer (gb_string_free(str));
|
||||
error(e->token, "Invalid use of a polymorphic type '%s' in %.*s", str, LIT(context_name));
|
||||
e->type = t_invalid;
|
||||
e->type = t;
|
||||
return nullptr;
|
||||
}
|
||||
gbString str = type_to_string(t);
|
||||
defer (gb_string_free(str));
|
||||
error(operand->expr, "Invalid use of a non-specialized polymorphic type '%s' in %.*s", str, LIT(context_name));
|
||||
e->type = t_invalid;
|
||||
return nullptr;
|
||||
} else if (is_type_empty_union(t)) {
|
||||
gbString str = type_to_string(t);
|
||||
defer (gb_string_free(str));
|
||||
@@ -971,6 +973,43 @@ gb_internal void check_objc_methods(CheckerContext *ctx, Entity *e, AttributeCon
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal void check_foreign_procedure(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
||||
GB_ASSERT(e != nullptr);
|
||||
GB_ASSERT(e->kind == Entity_Procedure);
|
||||
String name = e->Procedure.link_name;
|
||||
|
||||
mutex_lock(&ctx->info->foreign_mutex);
|
||||
|
||||
auto *fp = &ctx->info->foreigns;
|
||||
StringHashKey key = string_hash_string(name);
|
||||
Entity **found = string_map_get(fp, key);
|
||||
if (found && e != *found) {
|
||||
Entity *f = *found;
|
||||
TokenPos pos = f->token.pos;
|
||||
Type *this_type = base_type(e->type);
|
||||
Type *other_type = base_type(f->type);
|
||||
if (is_type_proc(this_type) && is_type_proc(other_type)) {
|
||||
if (!are_signatures_similar_enough(this_type, other_type)) {
|
||||
error(d->proc_lit,
|
||||
"Redeclaration of foreign procedure '%.*s' with different type signatures\n"
|
||||
"\tat %s",
|
||||
LIT(name), token_pos_to_string(pos));
|
||||
}
|
||||
} else if (!signature_parameter_similar_enough(this_type, other_type)) {
|
||||
error(d->proc_lit,
|
||||
"Foreign entity '%.*s' previously declared elsewhere with a different type\n"
|
||||
"\tat %s",
|
||||
LIT(name), token_pos_to_string(pos));
|
||||
}
|
||||
} else if (name == "main") {
|
||||
error(d->proc_lit, "The link name 'main' is reserved for internal use");
|
||||
} else {
|
||||
string_map_set(fp, key, e);
|
||||
}
|
||||
|
||||
mutex_unlock(&ctx->info->foreign_mutex);
|
||||
}
|
||||
|
||||
gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
||||
GB_ASSERT(e->type == nullptr);
|
||||
if (d->proc_lit->kind != Ast_ProcLit) {
|
||||
@@ -1307,57 +1346,16 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
||||
name = e->Procedure.link_name;
|
||||
}
|
||||
Entity *foreign_library = init_entity_foreign_library(ctx, e);
|
||||
|
||||
if (is_arch_wasm() && foreign_library != nullptr) {
|
||||
String module_name = str_lit("env");
|
||||
GB_ASSERT (foreign_library->kind == Entity_LibraryName);
|
||||
if (foreign_library->LibraryName.paths.count != 1) {
|
||||
error(foreign_library->token, "'foreign import' for '%.*s' architecture may only have one path, got %td",
|
||||
LIT(target_arch_names[build_context.metrics.arch]), foreign_library->LibraryName.paths.count);
|
||||
}
|
||||
|
||||
if (foreign_library->LibraryName.paths.count >= 1) {
|
||||
module_name = foreign_library->LibraryName.paths[0];
|
||||
}
|
||||
|
||||
if (!string_ends_with(module_name, str_lit(".o"))) {
|
||||
name = concatenate3_strings(permanent_allocator(), module_name, WASM_MODULE_NAME_SEPARATOR, name);
|
||||
}
|
||||
}
|
||||
|
||||
e->Procedure.is_foreign = true;
|
||||
e->Procedure.link_name = name;
|
||||
e->Procedure.foreign_library = foreign_library;
|
||||
|
||||
mutex_lock(&ctx->info->foreign_mutex);
|
||||
|
||||
auto *fp = &ctx->info->foreigns;
|
||||
StringHashKey key = string_hash_string(name);
|
||||
Entity **found = string_map_get(fp, key);
|
||||
if (found && e != *found) {
|
||||
Entity *f = *found;
|
||||
TokenPos pos = f->token.pos;
|
||||
Type *this_type = base_type(e->type);
|
||||
Type *other_type = base_type(f->type);
|
||||
if (is_type_proc(this_type) && is_type_proc(other_type)) {
|
||||
if (!are_signatures_similar_enough(this_type, other_type)) {
|
||||
error(d->proc_lit,
|
||||
"Redeclaration of foreign procedure '%.*s' with different type signatures\n"
|
||||
"\tat %s",
|
||||
LIT(name), token_pos_to_string(pos));
|
||||
}
|
||||
} else if (!signature_parameter_similar_enough(this_type, other_type)) {
|
||||
error(d->proc_lit,
|
||||
"Foreign entity '%.*s' previously declared elsewhere with a different type\n"
|
||||
"\tat %s",
|
||||
LIT(name), token_pos_to_string(pos));
|
||||
}
|
||||
} else if (name == "main") {
|
||||
error(d->proc_lit, "The link name 'main' is reserved for internal use");
|
||||
if (is_arch_wasm() && foreign_library != nullptr) {
|
||||
// NOTE(bill): this must be delayed because the foreign import paths might not be evaluated yet until much later
|
||||
mpsc_enqueue(&ctx->info->foreign_decls_to_check, e);
|
||||
} else {
|
||||
string_map_set(fp, key, e);
|
||||
check_foreign_procedure(ctx, e, d);
|
||||
}
|
||||
|
||||
mutex_unlock(&ctx->info->foreign_mutex);
|
||||
} else {
|
||||
String name = e->token.string;
|
||||
if (e->Procedure.link_name.len > 0) {
|
||||
|
||||
+53
-10
@@ -3672,6 +3672,13 @@ gb_internal bool check_binary_array_expr(CheckerContext *c, Token op, Operand *x
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_type_simd_vector(x->type) && !is_type_simd_vector(y->type)) {
|
||||
if (check_is_assignable_to(c, y, x->type)) {
|
||||
if (check_binary_op(c, x, op)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4556,6 +4563,19 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_SimdVector: {
|
||||
Type *elem = base_array_type(t);
|
||||
if (check_is_assignable_to(c, operand, elem)) {
|
||||
operand->mode = Addressing_Value;
|
||||
} else {
|
||||
operand->mode = Addressing_Invalid;
|
||||
convert_untyped_error(c, operand, target_type);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Matrix: {
|
||||
Type *elem = base_array_type(t);
|
||||
if (check_is_assignable_to(c, operand, elem)) {
|
||||
@@ -8725,6 +8745,18 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A
|
||||
error(node, "#caller_expression may only be used as a default argument parameter");
|
||||
o->type = t_string;
|
||||
o->mode = Addressing_Value;
|
||||
} else if (name == "branch_location") {
|
||||
if (!c->in_defer) {
|
||||
error(node, "#branch_location may only be used within a 'defer' statement");
|
||||
} else if (c->curr_proc_decl) {
|
||||
Entity *e = c->curr_proc_decl->entity;
|
||||
if (e != nullptr) {
|
||||
GB_ASSERT(e->kind == Entity_Procedure);
|
||||
e->Procedure.uses_branch_location = true;
|
||||
}
|
||||
}
|
||||
o->type = t_source_code_location;
|
||||
o->mode = Addressing_Value;
|
||||
} else {
|
||||
if (name == "location") {
|
||||
init_core_source_code_location(c->checker);
|
||||
@@ -9339,6 +9371,23 @@ gb_internal bool is_expr_inferred_fixed_array(Ast *type_expr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gb_internal bool check_for_dynamic_literals(CheckerContext *c, Ast *node, AstCompoundLit *cl) {
|
||||
if (cl->elems.count > 0 && (check_feature_flags(c, node) & OptInFeatureFlag_DynamicLiterals) == 0) {
|
||||
ERROR_BLOCK();
|
||||
error(node, "Compound literals of dynamic types are disabled by default");
|
||||
error_line("\tSuggestion: If you want to enable them for this specific file, add '#+feature dynamic-literals' at the top of the file\n");
|
||||
error_line("\tWarning: Please understand that dynamic literals will implicitly allocate using the current 'context.allocator' in that scope\n");
|
||||
if (build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR) {
|
||||
error_line("\tWarning: As '-default-to-panic-allocator' has been set, the dynamic compound literal may not be initialized as expected\n");
|
||||
} else if (build_context.ODIN_DEFAULT_TO_PANIC_ALLOCATOR) {
|
||||
error_line("\tWarning: As '-default-to-panic-allocator' has been set, the dynamic compound literal may not be initialized as expected\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return cl->elems.count > 0;
|
||||
}
|
||||
|
||||
gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
|
||||
ExprKind kind = Expr_Expr;
|
||||
ast_node(cl, CompoundLit, node);
|
||||
@@ -9539,11 +9588,6 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
|
||||
elem_type = t->DynamicArray.elem;
|
||||
context_name = str_lit("dynamic array literal");
|
||||
is_constant = false;
|
||||
|
||||
if (!build_context.no_dynamic_literals) {
|
||||
add_package_dependency(c, "runtime", "__dynamic_array_reserve");
|
||||
add_package_dependency(c, "runtime", "__dynamic_array_append");
|
||||
}
|
||||
} else if (t->kind == Type_SimdVector) {
|
||||
elem_type = t->SimdVector.elem;
|
||||
context_name = str_lit("simd vector literal");
|
||||
@@ -9718,8 +9762,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
|
||||
|
||||
|
||||
if (t->kind == Type_DynamicArray) {
|
||||
if (build_context.no_dynamic_literals && cl->elems.count) {
|
||||
error(node, "Compound literals of dynamic types have been disabled");
|
||||
if (check_for_dynamic_literals(c, node, cl)) {
|
||||
add_package_dependency(c, "runtime", "__dynamic_array_reserve");
|
||||
add_package_dependency(c, "runtime", "__dynamic_array_append");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10108,9 +10153,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
|
||||
}
|
||||
}
|
||||
|
||||
if (build_context.no_dynamic_literals && cl->elems.count) {
|
||||
error(node, "Compound literals of dynamic types have been disabled");
|
||||
} else {
|
||||
if (check_for_dynamic_literals(c, node, cl)) {
|
||||
add_map_reserve_dependencies(c);
|
||||
add_map_set_dependencies(c);
|
||||
}
|
||||
|
||||
+8
-1
@@ -2440,8 +2440,12 @@ gb_internal bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc
|
||||
bool success = true;
|
||||
isize specialization_count = 0;
|
||||
Type *params = check_get_params(c, c->scope, pt->params, &variadic, &variadic_index, &success, &specialization_count, operands);
|
||||
Type *results = check_get_results(c, c->scope, pt->results);
|
||||
|
||||
bool no_poly_return = c->disallow_polymorphic_return_types;
|
||||
c->disallow_polymorphic_return_types = c->scope == c->polymorphic_scope;
|
||||
// NOTE(zen3ger): if the parapoly scope is the current proc's scope, then the return types shall not declare new poly vars
|
||||
Type *results = check_get_results(c, c->scope, pt->results);
|
||||
c->disallow_polymorphic_return_types = no_poly_return;
|
||||
|
||||
isize param_count = 0;
|
||||
isize result_count = 0;
|
||||
@@ -3383,6 +3387,9 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T
|
||||
}
|
||||
Type *t = alloc_type_generic(ctx->scope, 0, token.string, specific);
|
||||
if (ctx->allow_polymorphic_types) {
|
||||
if (ctx->disallow_polymorphic_return_types) {
|
||||
error(ident, "Undeclared polymorphic parameter '%.*s' in return type", LIT(token.string));
|
||||
}
|
||||
Scope *ps = ctx->polymorphic_scope;
|
||||
Scope *s = ctx->scope;
|
||||
Scope *entity_scope = s;
|
||||
|
||||
+51
-1
@@ -542,6 +542,23 @@ gb_internal u64 check_vet_flags(Ast *node) {
|
||||
return ast_file_vet_flags(file);
|
||||
}
|
||||
|
||||
gb_internal u64 check_feature_flags(CheckerContext *c, Ast *node) {
|
||||
AstFile *file = c->file;
|
||||
if (file == nullptr &&
|
||||
c->curr_proc_decl &&
|
||||
c->curr_proc_decl->proc_lit) {
|
||||
file = c->curr_proc_decl->proc_lit->file();
|
||||
}
|
||||
if (file == nullptr) {
|
||||
file = node->file();
|
||||
}
|
||||
if (file != nullptr && file->feature_flags_set) {
|
||||
return file->feature_flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
enum VettedEntityKind {
|
||||
VettedEntity_Invalid,
|
||||
|
||||
@@ -1164,7 +1181,6 @@ gb_internal void init_universal(void) {
|
||||
add_global_bool_constant("ODIN_NO_BOUNDS_CHECK", build_context.no_bounds_check);
|
||||
add_global_bool_constant("ODIN_NO_TYPE_ASSERT", build_context.no_type_assert);
|
||||
add_global_bool_constant("ODIN_DEFAULT_TO_PANIC_ALLOCATOR", bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR);
|
||||
add_global_bool_constant("ODIN_NO_DYNAMIC_LITERALS", bc->no_dynamic_literals);
|
||||
add_global_bool_constant("ODIN_NO_CRT", bc->no_crt);
|
||||
add_global_bool_constant("ODIN_USE_SEPARATE_MODULES", bc->use_separate_modules);
|
||||
add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test);
|
||||
@@ -1356,6 +1372,7 @@ gb_internal void init_checker_info(CheckerInfo *i) {
|
||||
mpsc_init(&i->required_global_variable_queue, a); // 1<<10);
|
||||
mpsc_init(&i->required_foreign_imports_through_force_queue, a); // 1<<10);
|
||||
mpsc_init(&i->foreign_imports_to_check_fullpaths, a); // 1<<10);
|
||||
mpsc_init(&i->foreign_decls_to_check, a); // 1<<10);
|
||||
mpsc_init(&i->intrinsics_entry_point_usage, a); // 1<<10); // just waste some memory here, even if it probably never used
|
||||
|
||||
string_map_init(&i->load_directory_cache);
|
||||
@@ -1382,6 +1399,7 @@ gb_internal void destroy_checker_info(CheckerInfo *i) {
|
||||
mpsc_destroy(&i->required_global_variable_queue);
|
||||
mpsc_destroy(&i->required_foreign_imports_through_force_queue);
|
||||
mpsc_destroy(&i->foreign_imports_to_check_fullpaths);
|
||||
mpsc_destroy(&i->foreign_decls_to_check);
|
||||
|
||||
map_destroy(&i->objc_msgSend_types);
|
||||
string_map_destroy(&i->load_file_cache);
|
||||
@@ -5094,6 +5112,38 @@ gb_internal void check_foreign_import_fullpaths(Checker *c) {
|
||||
|
||||
e->LibraryName.paths = fl->fullpaths;
|
||||
}
|
||||
|
||||
for (Entity *e = nullptr; mpsc_dequeue(&c->info.foreign_decls_to_check, &e); /**/) {
|
||||
GB_ASSERT(e != nullptr);
|
||||
if (e->kind != Entity_Procedure) {
|
||||
continue;
|
||||
}
|
||||
if (!is_arch_wasm()) {
|
||||
continue;
|
||||
}
|
||||
Entity *foreign_library = e->Procedure.foreign_library;
|
||||
GB_ASSERT(foreign_library != nullptr);
|
||||
|
||||
String name = e->Procedure.link_name;
|
||||
|
||||
String module_name = str_lit("env");
|
||||
GB_ASSERT (foreign_library->kind == Entity_LibraryName);
|
||||
if (foreign_library->LibraryName.paths.count != 1) {
|
||||
error(foreign_library->token, "'foreign import' for '%.*s' architecture may only have one path, got %td",
|
||||
LIT(target_arch_names[build_context.metrics.arch]), foreign_library->LibraryName.paths.count);
|
||||
}
|
||||
|
||||
if (foreign_library->LibraryName.paths.count >= 1) {
|
||||
module_name = foreign_library->LibraryName.paths[0];
|
||||
}
|
||||
|
||||
if (!string_ends_with(module_name, str_lit(".o"))) {
|
||||
name = concatenate3_strings(permanent_allocator(), module_name, WASM_MODULE_NAME_SEPARATOR, name);
|
||||
}
|
||||
e->Procedure.link_name = name;
|
||||
|
||||
check_foreign_procedure(&ctx, e, e->decl_info);
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
|
||||
|
||||
@@ -461,6 +461,7 @@ struct CheckerInfo {
|
||||
MPSCQueue<Entity *> required_global_variable_queue;
|
||||
MPSCQueue<Entity *> required_foreign_imports_through_force_queue;
|
||||
MPSCQueue<Entity *> foreign_imports_to_check_fullpaths;
|
||||
MPSCQueue<Entity *> foreign_decls_to_check;
|
||||
|
||||
MPSCQueue<Ast *> intrinsics_entry_point_usage;
|
||||
|
||||
@@ -521,6 +522,7 @@ struct CheckerContext {
|
||||
bool in_enum_type;
|
||||
bool collect_delayed_decls;
|
||||
bool allow_polymorphic_types;
|
||||
bool disallow_polymorphic_return_types; // NOTE(zen3ger): no poly type decl in return types
|
||||
bool no_polymorphic_errors;
|
||||
bool hide_polymorphic_errors;
|
||||
bool in_polymorphic_specialization;
|
||||
|
||||
@@ -256,6 +256,7 @@ struct Entity {
|
||||
bool entry_point_only : 1;
|
||||
bool has_instrumentation : 1;
|
||||
bool is_memcpy_like : 1;
|
||||
bool uses_branch_location : 1;
|
||||
} Procedure;
|
||||
struct {
|
||||
Array<Entity *> entities;
|
||||
|
||||
@@ -1096,8 +1096,6 @@ gb_internal void lb_internal_dynamic_map_set(lbProcedure *p, lbValue const &map_
|
||||
}
|
||||
|
||||
gb_internal lbValue lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos) {
|
||||
GB_ASSERT(!build_context.no_dynamic_literals);
|
||||
|
||||
TEMPORARY_ALLOCATOR_GUARD();
|
||||
|
||||
String proc_name = {};
|
||||
|
||||
@@ -359,6 +359,10 @@ struct lbProcedure {
|
||||
bool in_multi_assignment;
|
||||
Array<LLVMValueRef> raw_input_parameters;
|
||||
|
||||
bool uses_branch_location;
|
||||
TokenPos branch_location_pos;
|
||||
TokenPos curr_token_pos;
|
||||
|
||||
Array<lbVariadicReuseSlices> variadic_reuses;
|
||||
lbAddr variadic_reuse_base_array_ptr;
|
||||
|
||||
@@ -444,7 +448,8 @@ gb_internal lbValue lb_emit_matrix_ev(lbProcedure *p, lbValue s, isize row, isiz
|
||||
|
||||
gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type);
|
||||
gb_internal lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *end_type);
|
||||
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block);
|
||||
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, TokenPos pos);
|
||||
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node);
|
||||
gb_internal lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t);
|
||||
gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue right);
|
||||
gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args, ProcInlining inlining = ProcInlining_none);
|
||||
@@ -742,3 +747,5 @@ gb_global char const *llvm_linkage_strings[] = {
|
||||
};
|
||||
|
||||
#define ODIN_METADATA_IS_PACKED str_lit("odin-is-packed")
|
||||
#define ODIN_METADATA_MIN_ALIGN str_lit("odin-min-align")
|
||||
#define ODIN_METADATA_MAX_ALIGN str_lit("odin-max-align")
|
||||
|
||||
@@ -3502,7 +3502,13 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
|
||||
|
||||
case_ast_node(bd, BasicDirective, expr);
|
||||
TokenPos pos = bd->token.pos;
|
||||
GB_PANIC("Non-constant basic literal %s - %.*s", token_pos_to_string(pos), LIT(bd->name.string));
|
||||
String name = bd->name.string;
|
||||
if (name == "branch_location") {
|
||||
GB_ASSERT(p->uses_branch_location);
|
||||
String proc_name = p->entity->token.string;
|
||||
return lb_emit_source_code_location_as_global(p, proc_name, p->branch_location_pos);
|
||||
}
|
||||
GB_PANIC("Non-constant basic literal %s - %.*s", token_pos_to_string(pos), LIT(name));
|
||||
case_end;
|
||||
|
||||
case_ast_node(i, Implicit, expr);
|
||||
@@ -3668,7 +3674,7 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
|
||||
|
||||
lb_emit_if(p, lb_emit_try_has_value(p, rhs), then, else_);
|
||||
lb_start_block(p, else_);
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Branch, block, expr);
|
||||
lb_emit_jump(p, block);
|
||||
lb_start_block(p, then);
|
||||
|
||||
@@ -4807,7 +4813,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
|
||||
if (cl->elems.count == 0) {
|
||||
break;
|
||||
}
|
||||
GB_ASSERT(!build_context.no_dynamic_literals);
|
||||
GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals);
|
||||
|
||||
lbValue err = lb_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos);
|
||||
gb_unused(err);
|
||||
@@ -4896,7 +4902,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
|
||||
if (cl->elems.count == 0) {
|
||||
break;
|
||||
}
|
||||
GB_ASSERT(!build_context.no_dynamic_literals);
|
||||
GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals);
|
||||
|
||||
Type *et = bt->DynamicArray.elem;
|
||||
lbValue size = lb_const_int(p->module, t_int, type_size_of(et));
|
||||
@@ -5493,7 +5499,7 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
|
||||
|
||||
lb_emit_if(p, lb_emit_try_has_value(p, rhs), then, else_);
|
||||
lb_start_block(p, else_);
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Branch, block, expr);
|
||||
lb_emit_jump(p, block);
|
||||
lb_start_block(p, then);
|
||||
|
||||
|
||||
@@ -734,6 +734,17 @@ gb_internal LLVMValueRef OdinLLVMBuildLoad(lbProcedure *p, LLVMTypeRef type, LLV
|
||||
if (is_packed != 0) {
|
||||
LLVMSetAlignment(result, 1);
|
||||
}
|
||||
u64 align = LLVMGetAlignment(result);
|
||||
u64 align_min = lb_get_metadata_custom_u64(p->module, value, ODIN_METADATA_MIN_ALIGN);
|
||||
u64 align_max = lb_get_metadata_custom_u64(p->module, value, ODIN_METADATA_MAX_ALIGN);
|
||||
if (align_min != 0 && align < align_min) {
|
||||
align = align_min;
|
||||
}
|
||||
if (align_max != 0 && align > align_max) {
|
||||
align = align_max;
|
||||
}
|
||||
GB_ASSERT(align <= UINT_MAX);
|
||||
LLVMSetAlignment(result, (unsigned int)align);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -2121,6 +2132,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
}
|
||||
|
||||
i64 prev_offset = 0;
|
||||
bool requires_packing = type->Struct.is_packed;
|
||||
for (i32 field_index : struct_fields_index_by_increasing_offset(temporary_allocator(), type)) {
|
||||
Entity *field = type->Struct.fields[field_index];
|
||||
i64 offset = type->Struct.offsets[field_index];
|
||||
@@ -2141,6 +2153,10 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
field_type = t_rawptr;
|
||||
}
|
||||
|
||||
// max_field_align might misalign items in a way that requires packing
|
||||
// so check the alignment of all fields to see if packing is required.
|
||||
requires_packing = requires_packing || ((offset % type_align_of(field_type)) != 0);
|
||||
|
||||
array_add(&fields, lb_type(m, field_type));
|
||||
|
||||
prev_offset = offset + type_size_of(field->type);
|
||||
@@ -2155,7 +2171,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
GB_ASSERT(fields[i] != nullptr);
|
||||
}
|
||||
|
||||
LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, type->Struct.is_packed);
|
||||
LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, requires_packing);
|
||||
map_set(&m->struct_field_remapping, cast(void *)struct_type, field_remapping);
|
||||
map_set(&m->struct_field_remapping, cast(void *)type, field_remapping);
|
||||
#if 0
|
||||
|
||||
@@ -125,6 +125,10 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i
|
||||
// map_init(&p->selector_addr, 0);
|
||||
// map_init(&p->tuple_fix_map, 0);
|
||||
|
||||
if (p->entity != nullptr && p->entity->Procedure.uses_branch_location) {
|
||||
p->uses_branch_location = true;
|
||||
}
|
||||
|
||||
if (p->is_foreign) {
|
||||
lb_add_foreign_library_path(p->module, entity->Procedure.foreign_library);
|
||||
}
|
||||
@@ -757,7 +761,7 @@ gb_internal void lb_end_procedure_body(lbProcedure *p) {
|
||||
if (p->type->Proc.result_count == 0) {
|
||||
instr = LLVMGetLastInstruction(p->curr_block->block);
|
||||
if (!lb_is_instr_terminating(instr)) {
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, p->body);
|
||||
lb_set_debug_position_to_procedure_end(p);
|
||||
LLVMBuildRetVoid(p->builder);
|
||||
}
|
||||
|
||||
+52
-29
@@ -208,8 +208,8 @@ gb_internal void lb_open_scope(lbProcedure *p, Scope *s) {
|
||||
|
||||
}
|
||||
|
||||
gb_internal void lb_close_scope(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, bool pop_stack=true) {
|
||||
lb_emit_defer_stmts(p, kind, block);
|
||||
gb_internal void lb_close_scope(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node, bool pop_stack=true) {
|
||||
lb_emit_defer_stmts(p, kind, block, node);
|
||||
GB_ASSERT(p->scope_index > 0);
|
||||
|
||||
// NOTE(bill): Remove `context`s made in that scope
|
||||
@@ -721,7 +721,7 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node,
|
||||
|
||||
lb_build_stmt(p, rs->body);
|
||||
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr, node->left);
|
||||
lb_pop_target_list(p);
|
||||
|
||||
if (check != nullptr) {
|
||||
@@ -854,7 +854,7 @@ gb_internal void lb_build_range_tuple(lbProcedure *p, AstRangeStmt *rs, Scope *s
|
||||
|
||||
lb_build_stmt(p, rs->body);
|
||||
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
|
||||
lb_pop_target_list(p);
|
||||
lb_emit_jump(p, loop);
|
||||
lb_start_block(p, done);
|
||||
@@ -976,7 +976,7 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs
|
||||
|
||||
lb_build_stmt(p, rs->body);
|
||||
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
|
||||
lb_pop_target_list(p);
|
||||
lb_emit_jump(p, loop);
|
||||
lb_start_block(p, done);
|
||||
@@ -1192,7 +1192,7 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc
|
||||
|
||||
lb_build_stmt(p, rs->body);
|
||||
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
|
||||
lb_pop_target_list(p);
|
||||
lb_emit_jump(p, loop);
|
||||
lb_start_block(p, done);
|
||||
@@ -1363,7 +1363,7 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *
|
||||
}
|
||||
|
||||
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
|
||||
}
|
||||
|
||||
gb_internal bool lb_switch_stmt_can_be_trivial_jump_table(AstSwitchStmt *ss, bool *default_found_) {
|
||||
@@ -1433,6 +1433,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
|
||||
ast_node(body, BlockStmt, ss->body);
|
||||
|
||||
isize case_count = body->stmts.count;
|
||||
Ast *default_clause = nullptr;
|
||||
Slice<Ast *> default_stmts = {};
|
||||
lbBlock *default_fall = nullptr;
|
||||
lbBlock *default_block = nullptr;
|
||||
@@ -1482,6 +1483,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
|
||||
|
||||
if (cc->list.count == 0) {
|
||||
// default case
|
||||
default_clause = clause;
|
||||
default_stmts = cc->stmts;
|
||||
default_fall = fall;
|
||||
if (switch_instr == nullptr) {
|
||||
@@ -1552,7 +1554,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
|
||||
lb_push_target_list(p, ss->label, done, nullptr, fall);
|
||||
lb_open_scope(p, body->scope);
|
||||
lb_build_stmt_list(p, cc->stmts);
|
||||
lb_close_scope(p, lbDeferExit_Default, body);
|
||||
lb_close_scope(p, lbDeferExit_Default, body, clause);
|
||||
lb_pop_target_list(p);
|
||||
|
||||
lb_emit_jump(p, done);
|
||||
@@ -1570,13 +1572,13 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
|
||||
lb_push_target_list(p, ss->label, done, nullptr, default_fall);
|
||||
lb_open_scope(p, default_block->scope);
|
||||
lb_build_stmt_list(p, default_stmts);
|
||||
lb_close_scope(p, lbDeferExit_Default, default_block);
|
||||
lb_close_scope(p, lbDeferExit_Default, default_block, default_clause);
|
||||
lb_pop_target_list(p);
|
||||
}
|
||||
|
||||
lb_emit_jump(p, done);
|
||||
lb_start_block(p, done);
|
||||
lb_close_scope(p, lbDeferExit_Default, done);
|
||||
lb_close_scope(p, lbDeferExit_Default, done, ss->body);
|
||||
}
|
||||
|
||||
gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value, bool is_default_case) {
|
||||
@@ -1627,7 +1629,7 @@ gb_internal void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBl
|
||||
|
||||
lb_push_target_list(p, label, done, nullptr, nullptr);
|
||||
lb_build_stmt_list(p, cc->stmts);
|
||||
lb_close_scope(p, lbDeferExit_Default, body);
|
||||
lb_close_scope(p, lbDeferExit_Default, body, clause);
|
||||
lb_pop_target_list(p);
|
||||
|
||||
lb_emit_jump(p, done);
|
||||
@@ -1835,7 +1837,7 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss
|
||||
|
||||
lb_emit_jump(p, done);
|
||||
lb_start_block(p, done);
|
||||
lb_close_scope(p, lbDeferExit_Default, done);
|
||||
lb_close_scope(p, lbDeferExit_Default, done, ss->body);
|
||||
}
|
||||
|
||||
|
||||
@@ -1959,7 +1961,7 @@ gb_internal void lb_build_assignment(lbProcedure *p, Array<lbAddr> &lvals, Slice
|
||||
p->in_multi_assignment = prev_in_assignment;
|
||||
}
|
||||
|
||||
gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
|
||||
gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res, TokenPos pos) {
|
||||
lbFunctionType *ft = lb_get_function_type(p->module, p->type);
|
||||
bool return_by_pointer = ft->ret.kind == lbArg_Indirect;
|
||||
bool split_returns = ft->multiple_return_original_type != nullptr;
|
||||
@@ -1982,7 +1984,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
|
||||
LLVMBuildStore(p->builder, LLVMConstNull(p->abi_function_type->ret.type), p->return_ptr.addr.value);
|
||||
}
|
||||
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
|
||||
|
||||
// Check for terminator in the defer stmts
|
||||
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
|
||||
@@ -2012,7 +2014,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
|
||||
ret_val = OdinLLVMBuildTransmute(p, ret_val, ret_type);
|
||||
}
|
||||
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
|
||||
|
||||
// Check for terminator in the defer stmts
|
||||
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
|
||||
@@ -2021,7 +2023,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
|
||||
}
|
||||
}
|
||||
}
|
||||
gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results) {
|
||||
gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results, TokenPos pos) {
|
||||
lb_ensure_abi_function_type(p->module, p);
|
||||
|
||||
isize return_count = p->type->Proc.result_count;
|
||||
@@ -2029,7 +2031,7 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
|
||||
if (return_count == 0) {
|
||||
// No return values
|
||||
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
|
||||
|
||||
// Check for terminator in the defer stmts
|
||||
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
|
||||
@@ -2138,11 +2140,11 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
|
||||
GB_ASSERT(result_values.count-1 == result_eps.count);
|
||||
lb_addr_store(p, p->return_ptr, result_values[result_values.count-1]);
|
||||
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
|
||||
LLVMBuildRetVoid(p->builder);
|
||||
return;
|
||||
} else {
|
||||
return lb_build_return_stmt_internal(p, result_values[result_values.count-1]);
|
||||
return lb_build_return_stmt_internal(p, result_values[result_values.count-1], pos);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -2169,7 +2171,7 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
|
||||
}
|
||||
|
||||
if (return_by_pointer) {
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
|
||||
LLVMBuildRetVoid(p->builder);
|
||||
return;
|
||||
}
|
||||
@@ -2177,13 +2179,13 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
|
||||
res = lb_emit_load(p, res);
|
||||
}
|
||||
}
|
||||
lb_build_return_stmt_internal(p, res);
|
||||
lb_build_return_stmt_internal(p, res, pos);
|
||||
}
|
||||
|
||||
gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
|
||||
ast_node(is, IfStmt, node);
|
||||
lb_open_scope(p, is->scope); // Scope #1
|
||||
defer (lb_close_scope(p, lbDeferExit_Default, nullptr));
|
||||
defer (lb_close_scope(p, lbDeferExit_Default, nullptr, node));
|
||||
|
||||
lbBlock *then = lb_create_block(p, "if.then");
|
||||
lbBlock *done = lb_create_block(p, "if.done");
|
||||
@@ -2234,7 +2236,7 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
|
||||
|
||||
lb_open_scope(p, scope_of_node(is->else_stmt));
|
||||
lb_build_stmt(p, is->else_stmt);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr, is->else_stmt);
|
||||
}
|
||||
lb_emit_jump(p, done);
|
||||
|
||||
@@ -2251,7 +2253,7 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
|
||||
|
||||
lb_open_scope(p, scope_of_node(is->else_stmt));
|
||||
lb_build_stmt(p, is->else_stmt);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr, is->else_stmt);
|
||||
|
||||
lb_emit_jump(p, done);
|
||||
}
|
||||
@@ -2322,7 +2324,7 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) {
|
||||
}
|
||||
|
||||
lb_start_block(p, done);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr, node);
|
||||
}
|
||||
|
||||
gb_internal void lb_build_assign_stmt_array(lbProcedure *p, TokenKind op, lbAddr const &lhs, lbValue const &value) {
|
||||
@@ -2588,7 +2590,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
|
||||
|
||||
lb_open_scope(p, bs->scope);
|
||||
lb_build_stmt_list(p, bs->stmts);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr);
|
||||
lb_close_scope(p, lbDeferExit_Default, nullptr, node);
|
||||
|
||||
if (done != nullptr) {
|
||||
lb_emit_jump(p, done);
|
||||
@@ -2702,7 +2704,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(rs, ReturnStmt, node);
|
||||
lb_build_return_stmt(p, rs->results);
|
||||
lb_build_return_stmt(p, rs->results, ast_token(node).pos);
|
||||
case_end;
|
||||
|
||||
case_ast_node(is, IfStmt, node);
|
||||
@@ -2755,7 +2757,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
|
||||
}
|
||||
}
|
||||
if (block != nullptr) {
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Branch, block, node);
|
||||
}
|
||||
lb_emit_jump(p, block);
|
||||
lb_start_block(p, lb_create_block(p, "unreachable"));
|
||||
@@ -2795,7 +2797,13 @@ gb_internal void lb_build_defer_stmt(lbProcedure *p, lbDefer const &d) {
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block) {
|
||||
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, TokenPos pos) {
|
||||
TokenPos prev_token_pos = p->branch_location_pos;
|
||||
if (p->uses_branch_location) {
|
||||
p->branch_location_pos = pos;
|
||||
}
|
||||
defer (p->branch_location_pos = prev_token_pos);
|
||||
|
||||
isize count = p->defer_stmts.count;
|
||||
isize i = count;
|
||||
while (i --> 0) {
|
||||
@@ -2822,6 +2830,21 @@ gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlo
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node) {
|
||||
TokenPos pos = {};
|
||||
if (node) {
|
||||
if (node->kind == Ast_BlockStmt) {
|
||||
pos = ast_end_token(node).pos;
|
||||
} else if (node->kind == Ast_CaseClause) {
|
||||
pos = ast_end_token(node).pos;
|
||||
} else {
|
||||
pos = ast_token(node).pos;
|
||||
}
|
||||
}
|
||||
return lb_emit_defer_stmts(p, kind, block, pos);
|
||||
}
|
||||
|
||||
|
||||
gb_internal void lb_add_defer_node(lbProcedure *p, isize scope_index, Ast *stmt) {
|
||||
Type *pt = base_type(p->type);
|
||||
GB_ASSERT(pt->kind == Type_Proc);
|
||||
|
||||
@@ -476,8 +476,8 @@ gb_internal lbValue lb_emit_or_else(lbProcedure *p, Ast *arg, Ast *else_expr, Ty
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results);
|
||||
gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res);
|
||||
gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results, TokenPos pos);
|
||||
gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res, TokenPos pos);
|
||||
|
||||
gb_internal lbValue lb_emit_or_return(lbProcedure *p, Ast *arg, TypeAndValue const &tv) {
|
||||
lbValue lhs = {};
|
||||
@@ -506,10 +506,10 @@ gb_internal lbValue lb_emit_or_return(lbProcedure *p, Ast *arg, TypeAndValue con
|
||||
lbValue found = map_must_get(&p->module->values, end_entity);
|
||||
lb_emit_store(p, found, rhs);
|
||||
|
||||
lb_build_return_stmt(p, {});
|
||||
lb_build_return_stmt(p, {}, ast_token(arg).pos);
|
||||
} else {
|
||||
GB_ASSERT(tuple->variables.count == 1);
|
||||
lb_build_return_stmt_internal(p, rhs);
|
||||
lb_build_return_stmt_internal(p, rhs, ast_token(arg).pos);
|
||||
}
|
||||
}
|
||||
lb_start_block(p, continue_block);
|
||||
@@ -1200,9 +1200,22 @@ gb_internal lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
|
||||
lbValue gep = lb_emit_struct_ep_internal(p, s, index, result_type);
|
||||
|
||||
Type *bt = base_type(t);
|
||||
if (bt->kind == Type_Struct && bt->Struct.is_packed) {
|
||||
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED, 1);
|
||||
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED) == 1);
|
||||
if (bt->kind == Type_Struct) {
|
||||
if (bt->Struct.is_packed) {
|
||||
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED, 1);
|
||||
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED) == 1);
|
||||
}
|
||||
u64 align_max = bt->Struct.custom_max_field_align;
|
||||
u64 align_min = bt->Struct.custom_min_field_align;
|
||||
GB_ASSERT(align_min == 0 || align_max == 0 || align_min <= align_max);
|
||||
if (align_max) {
|
||||
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MAX_ALIGN, align_max);
|
||||
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MAX_ALIGN) == align_max);
|
||||
}
|
||||
if (align_min) {
|
||||
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MIN_ALIGN, align_min);
|
||||
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MIN_ALIGN) == align_min);
|
||||
}
|
||||
}
|
||||
|
||||
return gep;
|
||||
|
||||
+3
-3
@@ -1192,7 +1192,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
build_context.no_type_assert = true;
|
||||
break;
|
||||
case BuildFlag_NoDynamicLiterals:
|
||||
build_context.no_dynamic_literals = true;
|
||||
gb_printf_err("Warning: Use of -no-dynamic-literals is now redundant\n");
|
||||
break;
|
||||
case BuildFlag_NoCRT:
|
||||
build_context.no_crt = true;
|
||||
@@ -2120,7 +2120,7 @@ gb_internal void export_dependencies(Checker *c) {
|
||||
for_array(i, files) {
|
||||
AstFile *file = files[i];
|
||||
gb_fprintf(&f, "\t\t\"%.*s\"", LIT(file->fullpath));
|
||||
if (i+1 == files.count) {
|
||||
if (i+1 < files.count) {
|
||||
gb_fprintf(&f, ",");
|
||||
}
|
||||
gb_fprintf(&f, "\n");
|
||||
@@ -2133,7 +2133,7 @@ gb_internal void export_dependencies(Checker *c) {
|
||||
for_array(i, load_files) {
|
||||
LoadFileCache *cache = load_files[i];
|
||||
gb_fprintf(&f, "\t\t\"%.*s\"", LIT(cache->path));
|
||||
if (i+1 == load_files.count) {
|
||||
if (i+1 < load_files.count) {
|
||||
gb_fprintf(&f, ",");
|
||||
}
|
||||
gb_fprintf(&f, "\n");
|
||||
|
||||
+67
-3
@@ -6265,10 +6265,16 @@ gb_internal u64 parse_vet_tag(Token token_for_pos, String s) {
|
||||
syntax_error(token_for_pos, "Invalid vet flag name: %.*s", LIT(p));
|
||||
error_line("\tExpected one of the following\n");
|
||||
error_line("\tunused\n");
|
||||
error_line("\tunused-variables\n");
|
||||
error_line("\tunused-imports\n");
|
||||
error_line("\tunused-procedures\n");
|
||||
error_line("\tshadowing\n");
|
||||
error_line("\tusing-stmt\n");
|
||||
error_line("\tusing-param\n");
|
||||
error_line("\tstyle\n");
|
||||
error_line("\textra\n");
|
||||
error_line("\tcast\n");
|
||||
error_line("\ttabs\n");
|
||||
return build_context.vet_flags;
|
||||
}
|
||||
}
|
||||
@@ -6286,6 +6292,63 @@ gb_internal u64 parse_vet_tag(Token token_for_pos, String s) {
|
||||
return vet_flags &~ vet_not_flags;
|
||||
}
|
||||
|
||||
gb_internal u64 parse_feature_tag(Token token_for_pos, String s) {
|
||||
String const prefix = str_lit("feature");
|
||||
GB_ASSERT(string_starts_with(s, prefix));
|
||||
s = string_trim_whitespace(substring(s, prefix.len, s.len));
|
||||
|
||||
if (s.len == 0) {
|
||||
return OptInFeatureFlag_NONE;
|
||||
}
|
||||
|
||||
u64 feature_flags = 0;
|
||||
u64 feature_not_flags = 0;
|
||||
|
||||
while (s.len > 0) {
|
||||
String p = string_trim_whitespace(vet_tag_get_token(s, &s));
|
||||
if (p.len == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool is_notted = false;
|
||||
if (p[0] == '!') {
|
||||
is_notted = true;
|
||||
p = substring(p, 1, p.len);
|
||||
if (p.len == 0) {
|
||||
syntax_error(token_for_pos, "Expected a feature flag name after '!'");
|
||||
return OptInFeatureFlag_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
u64 flag = get_feature_flag_from_name(p);
|
||||
if (flag != OptInFeatureFlag_NONE) {
|
||||
if (is_notted) {
|
||||
feature_not_flags |= flag;
|
||||
} else {
|
||||
feature_flags |= flag;
|
||||
}
|
||||
} else {
|
||||
ERROR_BLOCK();
|
||||
syntax_error(token_for_pos, "Invalid feature flag name: %.*s", LIT(p));
|
||||
error_line("\tExpected one of the following\n");
|
||||
error_line("\tdynamic-literals\n");
|
||||
return OptInFeatureFlag_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (feature_flags == 0 && feature_not_flags == 0) {
|
||||
return OptInFeatureFlag_NONE;
|
||||
}
|
||||
if (feature_flags == 0 && feature_not_flags != 0) {
|
||||
return OptInFeatureFlag_NONE &~ feature_not_flags;
|
||||
}
|
||||
if (feature_flags != 0 && feature_not_flags == 0) {
|
||||
return feature_flags;
|
||||
}
|
||||
GB_ASSERT(feature_flags != 0 && feature_not_flags != 0);
|
||||
return feature_flags &~ feature_not_flags;
|
||||
}
|
||||
|
||||
gb_internal String dir_from_path(String path) {
|
||||
String base_dir = path;
|
||||
for (isize i = path.len-1; i >= 0; i--) {
|
||||
@@ -6399,6 +6462,9 @@ gb_internal bool parse_file_tag(const String &lc, const Token &tok, AstFile *f)
|
||||
} else if (command == "file") {
|
||||
f->flags |= AstFile_IsPrivateFile;
|
||||
}
|
||||
} else if (string_starts_with(lc, str_lit("feature"))) {
|
||||
f->feature_flags |= parse_feature_tag(tok, lc);
|
||||
f->feature_flags_set = true;
|
||||
} else if (lc == "lazy") {
|
||||
if (build_context.ignore_lazy) {
|
||||
// Ignore
|
||||
@@ -6493,9 +6559,7 @@ gb_internal bool parse_file(Parser *p, AstFile *f) {
|
||||
}
|
||||
f->package_name = package_name.string;
|
||||
|
||||
// TODO: Shouldn't single file only matter for build tags? no-instrumentation for example
|
||||
// should be respected even when in single file mode.
|
||||
if (!f->pkg->is_single_file) {
|
||||
{
|
||||
if (docs != nullptr && docs->list.count > 0) {
|
||||
for (Token const &tok : docs->list) {
|
||||
GB_ASSERT(tok.kind == Token_Comment);
|
||||
|
||||
@@ -108,7 +108,9 @@ struct AstFile {
|
||||
String package_name;
|
||||
|
||||
u64 vet_flags;
|
||||
u64 feature_flags;
|
||||
bool vet_flags_set;
|
||||
bool feature_flags_set;
|
||||
|
||||
// >= 0: In Expression
|
||||
// < 0: In Control Clause
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#+feature dynamic-literals
|
||||
package test_encoding_cbor
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#+feature dynamic-literals
|
||||
package test_core_fmt
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#+feature dynamic-literals
|
||||
package test_core_hash
|
||||
|
||||
import "core:hash/xxhash"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Hash Test Vectors
|
||||
#+feature dynamic-literals
|
||||
package test_core_hash
|
||||
|
||||
XXHASH_Test_Vectors :: struct #packed {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
A test suite for PNG, TGA, NetPBM, QOI and BMP.
|
||||
*/
|
||||
#+feature dynamic-literals
|
||||
package test_core_image
|
||||
|
||||
import "core:testing"
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
#+build !netbsd
|
||||
#+build !openbsd
|
||||
#+feature dynamic-literals
|
||||
package test_core_net
|
||||
|
||||
import "core:testing"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#+feature dynamic-literals
|
||||
package test_core_runtime
|
||||
|
||||
import "base:intrinsics"
|
||||
@@ -63,4 +64,101 @@ test_init_cap_map_dynarray :: proc(t: ^testing.T) {
|
||||
defer delete(d2)
|
||||
testing.expect(t, cap(d2) == 0)
|
||||
testing.expect(t, d2.allocator.procedure == ally.procedure)
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_map_get :: proc(t: ^testing.T) {
|
||||
check :: proc(t: ^testing.T, m: map[$K]$V, loc := #caller_location) {
|
||||
for k, v in m {
|
||||
got_key, got_val, ok := runtime.map_get(m, k)
|
||||
testing.expect_value(t, got_key, k, loc = loc)
|
||||
testing.expect_value(t, got_val, v, loc = loc)
|
||||
testing.expect(t, ok, loc = loc)
|
||||
}
|
||||
}
|
||||
|
||||
// small keys & values
|
||||
{
|
||||
m := map[int]int{
|
||||
1 = 10,
|
||||
2 = 20,
|
||||
3 = 30,
|
||||
}
|
||||
defer delete(m)
|
||||
check(t, m)
|
||||
}
|
||||
|
||||
// small keys; 2 values per cell
|
||||
{
|
||||
m := map[int][3]int{
|
||||
1 = [3]int{10, 100, 1000},
|
||||
2 = [3]int{20, 200, 2000},
|
||||
3 = [3]int{30, 300, 3000},
|
||||
}
|
||||
defer delete(m)
|
||||
check(t, m)
|
||||
}
|
||||
|
||||
// 2 keys per cell; small values
|
||||
{
|
||||
m := map[[3]int]int{
|
||||
[3]int{10, 100, 1000} = 1,
|
||||
[3]int{20, 200, 2000} = 2,
|
||||
[3]int{30, 300, 3000} = 3,
|
||||
}
|
||||
defer delete(m)
|
||||
check(t, m)
|
||||
}
|
||||
|
||||
|
||||
// small keys; 3 values per cell
|
||||
{
|
||||
val :: struct #packed {
|
||||
a, b: int,
|
||||
c: i32,
|
||||
}
|
||||
m := map[int]val{
|
||||
1 = val{10, 100, 1000},
|
||||
2 = val{20, 200, 2000},
|
||||
3 = val{30, 300, 3000},
|
||||
}
|
||||
defer delete(m)
|
||||
check(t, m)
|
||||
}
|
||||
|
||||
// 3 keys per cell; small values
|
||||
{
|
||||
key :: struct #packed {
|
||||
a, b: int,
|
||||
c: i32,
|
||||
}
|
||||
m := map[key]int{
|
||||
key{10, 100, 1000} = 1,
|
||||
key{20, 200, 2000} = 2,
|
||||
key{30, 300, 3000} = 3,
|
||||
}
|
||||
defer delete(m)
|
||||
check(t, m)
|
||||
}
|
||||
|
||||
// small keys; value bigger than a chacheline
|
||||
{
|
||||
m := map[int][9]int{
|
||||
1 = [9]int{10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000},
|
||||
2 = [9]int{20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000},
|
||||
3 = [9]int{30, 300, 3000, 30000, 300000, 3000000, 30000000, 300000000, 3000000000},
|
||||
}
|
||||
defer delete(m)
|
||||
check(t, m)
|
||||
}
|
||||
// keys bigger than a chacheline; small values
|
||||
{
|
||||
m := map[[9]int]int{
|
||||
[9]int{10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000} = 1,
|
||||
[9]int{20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000} = 2,
|
||||
[9]int{30, 300, 3000, 30000, 300000, 3000000, 30000000, 300000000, 3000000000} = 3,
|
||||
}
|
||||
defer delete(m)
|
||||
check(t, m)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#+feature dynamic-literals
|
||||
package test_core_slice
|
||||
|
||||
import "core:slice"
|
||||
|
||||
@@ -16,6 +16,7 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style
|
||||
..\..\..\odin test ..\test_issue_2637.odin %COMMON% || exit /b
|
||||
..\..\..\odin test ..\test_issue_2666.odin %COMMON% || exit /b
|
||||
..\..\..\odin test ..\test_issue_4210.odin %COMMON% || exit /b
|
||||
..\..\..\odin test ..\test_issue_4584.odin %COMMON% || exit /b
|
||||
|
||||
@echo off
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ $ODIN test ../test_issue_2615.odin $COMMON
|
||||
$ODIN test ../test_issue_2637.odin $COMMON
|
||||
$ODIN test ../test_issue_2666.odin $COMMON
|
||||
$ODIN test ../test_issue_4210.odin $COMMON
|
||||
$ODIN test ../test_issue_4584.odin $COMMON
|
||||
if [[ $($ODIN build ../test_issue_2395.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]] ; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
// Tests issue #4584 https://github.com/odin-lang/Odin/issues/4584
|
||||
package test_issues
|
||||
|
||||
import "core:testing"
|
||||
import "core:log"
|
||||
import "core:math/linalg"
|
||||
import glm "core:math/linalg/glsl"
|
||||
import hlm "core:math/linalg/hlsl"
|
||||
|
||||
@test
|
||||
test_adjugate_2x2 :: proc(t: ^testing.T) {
|
||||
I := linalg.identity(matrix[2,2]int)
|
||||
m := matrix[2,2]int {
|
||||
-3, 2,
|
||||
-1, 0,
|
||||
}
|
||||
expected := matrix[2,2]int {
|
||||
0, -2,
|
||||
1, -3,
|
||||
}
|
||||
testing.expect_value(t, linalg.adjugate(m), expected)
|
||||
testing.expect_value(t, linalg.determinant(m), 2)
|
||||
testing.expect_value(t, linalg.adjugate(m) * m, 2 * I)
|
||||
testing.expect_value(t, m * linalg.adjugate(m), 2 * I)
|
||||
|
||||
testing.expect_value(t, glm.adjugate(m), expected)
|
||||
testing.expect_value(t, glm.determinant(m), 2)
|
||||
testing.expect_value(t, glm.adjugate(m) * m, 2 * I)
|
||||
testing.expect_value(t, m * glm.adjugate(m), 2 * I)
|
||||
|
||||
testing.expect_value(t, hlm.adjugate(m), expected)
|
||||
testing.expect_value(t, hlm.determinant(m), 2)
|
||||
testing.expect_value(t, hlm.adjugate(m) * m, 2 * I)
|
||||
testing.expect_value(t, m * hlm.adjugate(m), 2 * I)
|
||||
}
|
||||
|
||||
@test
|
||||
test_adjugate_3x3 :: proc(t: ^testing.T) {
|
||||
I := linalg.identity(matrix[3,3]int)
|
||||
m := matrix[3,3]int {
|
||||
-3, 2, -5,
|
||||
-1, 0, -2,
|
||||
3, -4, 1,
|
||||
}
|
||||
expected := matrix[3,3]int {
|
||||
-8, 18, -4,
|
||||
-5, 12, -1,
|
||||
4, -6, 2,
|
||||
}
|
||||
testing.expect_value(t, linalg.adjugate(m), expected)
|
||||
testing.expect_value(t, linalg.determinant(m), -6)
|
||||
testing.expect_value(t, linalg.adjugate(m) * m, -6 * I)
|
||||
testing.expect_value(t, m * linalg.adjugate(m), -6 * I)
|
||||
|
||||
testing.expect_value(t, glm.adjugate(m), expected)
|
||||
testing.expect_value(t, glm.determinant(m), -6)
|
||||
testing.expect_value(t, glm.adjugate(m) * m, -6 * I)
|
||||
testing.expect_value(t, m * glm.adjugate(m), -6 * I)
|
||||
|
||||
testing.expect_value(t, hlm.adjugate(m), expected)
|
||||
testing.expect_value(t, hlm.determinant(m), -6)
|
||||
testing.expect_value(t, hlm.adjugate(m) * m, -6 * I)
|
||||
testing.expect_value(t, m * hlm.adjugate(m), -6 * I)
|
||||
}
|
||||
|
||||
@test
|
||||
test_adjugate_4x4 :: proc(t: ^testing.T) {
|
||||
I := linalg.identity(matrix[4,4]int)
|
||||
m := matrix[4,4]int {
|
||||
-3, 2, -5, 1,
|
||||
-1, 0, -2, 2,
|
||||
3, -4, 1, 3,
|
||||
4, 5, 6, 7,
|
||||
}
|
||||
expected := matrix[4,4]int {
|
||||
-144, 266, -92, -16,
|
||||
-57, 92, -5, -16,
|
||||
105, -142, 55, 2,
|
||||
33, -96, 9, -6,
|
||||
}
|
||||
testing.expect_value(t, linalg.adjugate(m), expected)
|
||||
testing.expect_value(t, linalg.determinant(m), -174)
|
||||
testing.expect_value(t, linalg.adjugate(m) * m, -174 * I)
|
||||
testing.expect_value(t, m * linalg.adjugate(m), -174 * I)
|
||||
|
||||
testing.expect_value(t, glm.adjugate(m), expected)
|
||||
testing.expect_value(t, glm.determinant(m), -174)
|
||||
testing.expect_value(t, glm.adjugate(m) * m, -174 * I)
|
||||
testing.expect_value(t, m * glm.adjugate(m), -174 * I)
|
||||
|
||||
testing.expect_value(t, hlm.adjugate(m), expected)
|
||||
testing.expect_value(t, hlm.determinant(m), -174)
|
||||
testing.expect_value(t, hlm.adjugate(m) * m, -174 * I)
|
||||
testing.expect_value(t, m * hlm.adjugate(m), -174 * I)
|
||||
}
|
||||
|
||||
@test
|
||||
test_inverse_regression_2x2 :: proc(t: ^testing.T) {
|
||||
I := linalg.identity(matrix[2,2]f32)
|
||||
m := matrix[2,2]f32 {
|
||||
-3, 2,
|
||||
-1, 0,
|
||||
}
|
||||
expected := matrix[2,2]f32 {
|
||||
0.0, -1.0,
|
||||
1.0/2.0, -3.0/2.0,
|
||||
}
|
||||
expect_float_matrix_value(t, linalg.inverse(m), expected)
|
||||
expect_float_matrix_value(t, linalg.inverse_transpose(m), linalg.transpose(expected))
|
||||
expect_float_matrix_value(t, linalg.inverse(m) * m, I)
|
||||
expect_float_matrix_value(t, m * linalg.inverse(m), I)
|
||||
|
||||
expect_float_matrix_value(t, glm.inverse(m), expected)
|
||||
expect_float_matrix_value(t, glm.inverse_transpose(m), glm.transpose(expected))
|
||||
expect_float_matrix_value(t, glm.inverse(m) * m, I)
|
||||
expect_float_matrix_value(t, m * glm.inverse(m), I)
|
||||
|
||||
expect_float_matrix_value(t, hlm.inverse(m), expected)
|
||||
expect_float_matrix_value(t, hlm.inverse_transpose(m), hlm.transpose(expected))
|
||||
expect_float_matrix_value(t, hlm.inverse(m) * m, I)
|
||||
expect_float_matrix_value(t, m * hlm.inverse(m), I)
|
||||
}
|
||||
|
||||
@test
|
||||
test_inverse_regression_3x3 :: proc(t: ^testing.T) {
|
||||
I := linalg.identity(matrix[3,3]f32)
|
||||
m := matrix[3,3]f32 {
|
||||
-3, 2, -5,
|
||||
-1, 0, -2,
|
||||
3, -4, 1,
|
||||
}
|
||||
expected := matrix[3,3]f32 {
|
||||
4.0/3.0, -3.0, 2.0/3.0,
|
||||
5.0/6.0, -2.0, 1.0/6.0,
|
||||
-2.0/3.0, 1.0, -1.0/3.0,
|
||||
}
|
||||
expect_float_matrix_value(t, linalg.inverse(m), expected)
|
||||
expect_float_matrix_value(t, linalg.inverse_transpose(m), linalg.transpose(expected))
|
||||
expect_float_matrix_value(t, linalg.inverse(m) * m, I)
|
||||
expect_float_matrix_value(t, m * linalg.inverse(m), I)
|
||||
|
||||
expect_float_matrix_value(t, glm.inverse(m), expected)
|
||||
expect_float_matrix_value(t, glm.inverse_transpose(m), glm.transpose(expected))
|
||||
expect_float_matrix_value(t, glm.inverse(m) * m, I)
|
||||
expect_float_matrix_value(t, m * glm.inverse(m), I)
|
||||
|
||||
expect_float_matrix_value(t, hlm.inverse(m), expected)
|
||||
expect_float_matrix_value(t, hlm.inverse_transpose(m), hlm.transpose(expected))
|
||||
expect_float_matrix_value(t, hlm.inverse(m) * m, I)
|
||||
expect_float_matrix_value(t, m * hlm.inverse(m), I)
|
||||
}
|
||||
|
||||
@test
|
||||
test_inverse_regression_4x4 :: proc(t: ^testing.T) {
|
||||
I := linalg.identity(matrix[4,4]f32)
|
||||
m := matrix[4,4]f32 {
|
||||
-3, 2, -5, 1,
|
||||
-1, 0, -2, 2,
|
||||
3, -4, 1, 3,
|
||||
4, 5, 6, 7,
|
||||
}
|
||||
expected := matrix[4,4]f32 {
|
||||
24.0/29.0, -133.0/87.0, 46.0/87.0, 8.0/87.0,
|
||||
19.0/58.0, -46.0/87.0, 5.0/174.0, 8.0/87.0,
|
||||
-35.0/58.0, 71.0/87.0, -55.0/174.0, -1.0/87.0,
|
||||
-11.0/58.0, 16.0/29.0, -3.0/58.0, 1.0/29.0,
|
||||
}
|
||||
expect_float_matrix_value(t, linalg.inverse(m), expected)
|
||||
expect_float_matrix_value(t, linalg.inverse_transpose(m), linalg.transpose(expected))
|
||||
expect_float_matrix_value(t, linalg.inverse(m) * m, I)
|
||||
expect_float_matrix_value(t, m * linalg.inverse(m), I)
|
||||
|
||||
expect_float_matrix_value(t, glm.inverse(m), expected)
|
||||
expect_float_matrix_value(t, glm.inverse_transpose(m), glm.transpose(expected))
|
||||
expect_float_matrix_value(t, glm.inverse(m) * m, I)
|
||||
expect_float_matrix_value(t, m * glm.inverse(m), I)
|
||||
|
||||
expect_float_matrix_value(t, hlm.inverse(m), expected)
|
||||
expect_float_matrix_value(t, hlm.inverse_transpose(m), hlm.transpose(expected))
|
||||
expect_float_matrix_value(t, hlm.inverse(m) * m, I)
|
||||
expect_float_matrix_value(t, m * hlm.inverse(m), I)
|
||||
}
|
||||
|
||||
@(private="file")
|
||||
expect_float_matrix_value :: proc(t: ^testing.T, value, expected: $M/matrix[$N, N]f32, loc := #caller_location, value_expr := #caller_expression(value)) -> bool {
|
||||
ok := true
|
||||
outer: for i in 0..<N {
|
||||
for j in 0..<N {
|
||||
diff := abs(value[i, j] - expected[i, j])
|
||||
if diff > 1e-6 {
|
||||
ok = false
|
||||
break outer
|
||||
}
|
||||
}
|
||||
}
|
||||
if !ok do log.errorf("expected %v to be %v, got %v", value_expr, expected, value, location=loc)
|
||||
return ok
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
// Tests issue #829 https://github.com/odin-lang/Odin/issues/829
|
||||
#+feature dynamic-literals
|
||||
package test_issues
|
||||
|
||||
import "core:testing"
|
||||
|
||||
Vendored
+3
-11
@@ -24,19 +24,11 @@ when ODIN_OS == .Windows {
|
||||
}
|
||||
|
||||
when !#exists(LIB_PATH) {
|
||||
#panic("Could not find the compiled box2d libraries at \"" + LIB_PATH + "\", they can be compiled by running the `build.sh` script at `" + ODIN_ROOT + "vendor/box2d/build_box2d.sh\"`")
|
||||
#panic("Could not find the compiled box2d libraries at \"" + LIB_PATH + "\", they can be compiled by running the `build_box2d.sh` script at `" + ODIN_ROOT + "vendor/box2d/build_box2d.sh\"`")
|
||||
}
|
||||
|
||||
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
when VECTOR_EXT == "_simd" {
|
||||
foreign import lib "lib/box2d_wasm_simd.o"
|
||||
} else {
|
||||
foreign import lib "lib/box2d_wasm.o"
|
||||
}
|
||||
} else {
|
||||
foreign import lib {
|
||||
LIB_PATH,
|
||||
}
|
||||
foreign import lib {
|
||||
LIB_PATH,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vendored
+5
@@ -68,7 +68,12 @@ esac
|
||||
|
||||
cd ..
|
||||
|
||||
set +e
|
||||
make -f wasm.Makefile
|
||||
if [[ $? -ne 0 ]]; then
|
||||
printf "\e[30;43mwarning:\e[0m Native Box2D libraries were built successfully, the WASM build failed, likely because your default C compiler and/or linker doesn't support WASM, you can set the CC and LD environment variables to point to a compiler and linker that support it\n"
|
||||
fi
|
||||
set -e
|
||||
|
||||
rm -rf v3.0.0.tar.gz
|
||||
rm -rf box2d-3.0.0
|
||||
|
||||
Vendored
+3
-1
@@ -2,6 +2,8 @@
|
||||
# I tried to make a cmake toolchain file for this / use cmake but this is far easier.
|
||||
# NOTE: We are pretending to be emscripten to box2d so it takes WASM code paths, but we don't actually use emscripten.
|
||||
|
||||
# WARN: wasm is probably not supported by your default C compiler and linker, overwrite the CC and LD environment variables accordingly.
|
||||
# Example for MacOS:
|
||||
# CC = $(shell brew --prefix llvm)/bin/clang
|
||||
# LD = $(shell brew --prefix llvm)/bin/wasm-ld
|
||||
|
||||
@@ -10,7 +12,7 @@ SRCS = $(wildcard box2d-$(VERSION)/src/*.c)
|
||||
OBJS_SIMD = $(SRCS:.c=_simd.o)
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
SYSROOT = $(shell odin root)/vendor/libc
|
||||
CFLAGS = -Ibox2d-$(VERSION)/include -Ibox2d-$(VERSION)/Extern/simde --target=wasm32 -D__EMSCRIPTEN__ -DNDEBUG -O3 --sysroot=$(SYSROOT)
|
||||
CFLAGS = -Ibox2d-$(VERSION)/include -Ibox2d-$(VERSION)/extern/simde --target=wasm32 -D__EMSCRIPTEN__ -DNDEBUG -O3 --sysroot=$(SYSROOT)
|
||||
|
||||
all: lib/box2d_wasm.o lib/box2d_wasm_simd.o clean
|
||||
|
||||
|
||||
Vendored
+58
-13
@@ -105,6 +105,7 @@ type :: enum c.int {
|
||||
}
|
||||
|
||||
primitive_type :: enum c.int {
|
||||
invalid,
|
||||
points,
|
||||
lines,
|
||||
line_loop,
|
||||
@@ -222,15 +223,6 @@ accessor_sparse :: struct {
|
||||
indices_component_type: component_type,
|
||||
values_buffer_view: ^buffer_view,
|
||||
values_byte_offset: uint,
|
||||
extras: extras_t,
|
||||
indices_extras: extras_t,
|
||||
values_extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
indices_extensions_count: uint,
|
||||
indices_extensions: [^]extension `fmt:"v,indices_extensions_count"`,
|
||||
values_extensions_count: uint,
|
||||
values_extensions: [^]extension `fmt:"v,values_extensions_count"`,
|
||||
}
|
||||
|
||||
accessor :: struct {
|
||||
@@ -306,9 +298,6 @@ texture_view :: struct {
|
||||
scale: f32, /* equivalent to strength for occlusion_texture */
|
||||
has_transform: b32,
|
||||
transform: texture_transform,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
pbr_metallic_roughness :: struct {
|
||||
@@ -381,6 +370,16 @@ iridescence :: struct {
|
||||
iridescence_thickness_texture: texture_view,
|
||||
}
|
||||
|
||||
anisotropy :: struct {
|
||||
anisotropy_strength: f32,
|
||||
anisotropy_rotation: f32,
|
||||
anisotropy_texture: texture_view,
|
||||
}
|
||||
|
||||
dispersion :: struct {
|
||||
dispersion: f32,
|
||||
}
|
||||
|
||||
material :: struct {
|
||||
name: cstring,
|
||||
has_pbr_metallic_roughness: b32,
|
||||
@@ -393,6 +392,8 @@ material :: struct {
|
||||
has_sheen: b32,
|
||||
has_emissive_strength: b32,
|
||||
has_iridescence: b32,
|
||||
has_anisotropy: b32,
|
||||
has_dispersion: b32,
|
||||
pbr_metallic_roughness: pbr_metallic_roughness,
|
||||
pbr_specular_glossiness: pbr_specular_glossiness,
|
||||
clearcoat: clearcoat,
|
||||
@@ -403,6 +404,8 @@ material :: struct {
|
||||
volume: volume,
|
||||
emissive_strength: emissive_strength,
|
||||
iridescence: iridescence,
|
||||
anisotropy: anisotropy,
|
||||
dispersion: dispersion,
|
||||
normal_texture: texture_view,
|
||||
occlusion_texture: texture_view,
|
||||
emissive_texture: texture_view,
|
||||
@@ -432,7 +435,6 @@ draco_mesh_compression :: struct {
|
||||
}
|
||||
|
||||
mesh_gpu_instancing :: struct {
|
||||
buffer_view: ^buffer_view,
|
||||
attributes: []attribute,
|
||||
}
|
||||
|
||||
@@ -683,6 +685,9 @@ foreign lib {
|
||||
node_transform_local :: proc(node: ^node, out_matrix: [^]f32) ---
|
||||
node_transform_world :: proc(node: ^node, out_matrix: [^]f32) ---
|
||||
|
||||
@(require_results)
|
||||
buffer_view_data :: proc(view: ^/*const*/buffer_view) -> [^]byte ---
|
||||
|
||||
@(require_results)
|
||||
accessor_read_float :: proc(accessor: ^/*const*/accessor, index: uint, out: [^]f32, element_size: uint) -> b32 ---
|
||||
@(require_results)
|
||||
@@ -693,13 +698,53 @@ foreign lib {
|
||||
@(require_results)
|
||||
num_components :: proc(type: type) -> uint ---
|
||||
|
||||
@(require_results)
|
||||
component_size :: proc(component_type: component_type) -> uint ---
|
||||
@(require_results)
|
||||
calc_size :: proc(type: type, component_type: component_type) -> uint ---
|
||||
|
||||
@(require_results)
|
||||
accessor_unpack_floats :: proc(accessor: ^/*const*/accessor, out: [^]f32, float_count: uint) -> uint ---
|
||||
@(require_results)
|
||||
accessor_unpack_indices :: proc(accessor: ^/*const*/accessor , out: rawptr, out_component_size: uint, index_count: uint) -> uint ---
|
||||
|
||||
/* this function is deprecated and will be removed in the future; use cgltf_extras::data instead */
|
||||
@(require_results)
|
||||
copy_extras_json :: proc(data: ^data, extras: ^extras_t, dest: [^]byte, dest_size: ^uint) -> result ---
|
||||
|
||||
@(require_results)
|
||||
mesh_index :: proc(data: ^/*const*/data, object: ^/*const*/mesh) -> uint ---
|
||||
@(require_results)
|
||||
material_index :: proc(data: ^/*const*/data, object: ^/*const*/material) -> uint ---
|
||||
@(require_results)
|
||||
accessor_index :: proc(data: ^/*const*/data, object: ^/*const*/accessor) -> uint ---
|
||||
@(require_results)
|
||||
buffer_view_index :: proc(data: ^/*const*/data, object: ^/*const*/buffer_view) -> uint ---
|
||||
@(require_results)
|
||||
buffer_index :: proc(data: ^/*const*/data, object: ^/*const*/buffer) -> uint ---
|
||||
@(require_results)
|
||||
image_index :: proc(data: ^/*const*/data, object: ^/*const*/image) -> uint ---
|
||||
@(require_results)
|
||||
texture_index :: proc(data: ^/*const*/data, object: ^/*const*/texture) -> uint ---
|
||||
@(require_results)
|
||||
sampler_index :: proc(data: ^/*const*/data, object: ^/*const*/sampler) -> uint ---
|
||||
@(require_results)
|
||||
skin_index :: proc(data: ^/*const*/data, object: ^/*const*/skin) -> uint ---
|
||||
@(require_results)
|
||||
camera_index :: proc(data: ^/*const*/data, object: ^/*const*/camera) -> uint ---
|
||||
@(require_results)
|
||||
light_index :: proc(data: ^/*const*/data, object: ^/*const*/light) -> uint ---
|
||||
@(require_results)
|
||||
node_index :: proc(data: ^/*const*/data, object: ^/*const*/node) -> uint ---
|
||||
@(require_results)
|
||||
scene_index :: proc(data: ^/*const*/data, object: ^/*const*/scene) -> uint ---
|
||||
@(require_results)
|
||||
animation_index :: proc(data: ^/*const*/data, object: ^/*const*/animation) -> uint ---
|
||||
@(require_results)
|
||||
animation_sampler_index :: proc(animation: ^/*const*/animation, object: ^/*const*/animation_sampler) -> uint ---
|
||||
@(require_results)
|
||||
animation_channel_index :: proc(animation: ^/*const*/animation, object: ^/*const*/animation_channel) -> uint ---
|
||||
|
||||
@(require_results)
|
||||
write_file :: proc(#by_ptr options: options, path: cstring, data: ^data) -> result ---
|
||||
@(require_results)
|
||||
|
||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
+436
-217
File diff suppressed because it is too large
Load Diff
Vendored
+55
-12
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* cgltf_write - a single-file glTF 2.0 writer written in C99.
|
||||
*
|
||||
* Version: 1.13
|
||||
* Version: 1.14
|
||||
*
|
||||
* Website: https://github.com/jkuhlmann/cgltf
|
||||
*
|
||||
@@ -85,6 +85,8 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si
|
||||
#define CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH (1 << 13)
|
||||
#define CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING (1 << 14)
|
||||
#define CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE (1 << 15)
|
||||
#define CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY (1 << 16)
|
||||
#define CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION (1 << 17)
|
||||
|
||||
typedef struct {
|
||||
char* buffer;
|
||||
@@ -152,7 +154,6 @@ typedef struct {
|
||||
context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
|
||||
cgltf_write_texture_transform(context, &info.transform); \
|
||||
} \
|
||||
cgltf_write_extras(context, &info.extras); \
|
||||
cgltf_write_line(context, "}"); }
|
||||
|
||||
#define CGLTF_WRITE_NORMAL_TEXTURE_INFO(label, info) if (info.texture) { \
|
||||
@@ -164,7 +165,6 @@ typedef struct {
|
||||
context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
|
||||
cgltf_write_texture_transform(context, &info.transform); \
|
||||
} \
|
||||
cgltf_write_extras(context, &info.extras); \
|
||||
cgltf_write_line(context, "}"); }
|
||||
|
||||
#define CGLTF_WRITE_OCCLUSION_TEXTURE_INFO(label, info) if (info.texture) { \
|
||||
@@ -176,12 +176,11 @@ typedef struct {
|
||||
context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
|
||||
cgltf_write_texture_transform(context, &info.transform); \
|
||||
} \
|
||||
cgltf_write_extras(context, &info.extras); \
|
||||
cgltf_write_line(context, "}"); }
|
||||
|
||||
#ifndef CGLTF_CONSTS
|
||||
static const cgltf_size GlbHeaderSize = 12;
|
||||
static const cgltf_size GlbChunkHeaderSize = 8;
|
||||
#define GlbHeaderSize 12
|
||||
#define GlbChunkHeaderSize 8
|
||||
static const uint32_t GlbVersion = 2;
|
||||
static const uint32_t GlbMagic = 0x46546C67;
|
||||
static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
|
||||
@@ -360,6 +359,21 @@ static int cgltf_int_from_component_type(cgltf_component_type ctype)
|
||||
}
|
||||
}
|
||||
|
||||
static int cgltf_int_from_primitive_type(cgltf_primitive_type ctype)
|
||||
{
|
||||
switch (ctype)
|
||||
{
|
||||
case cgltf_primitive_type_points: return 0;
|
||||
case cgltf_primitive_type_lines: return 1;
|
||||
case cgltf_primitive_type_line_loop: return 2;
|
||||
case cgltf_primitive_type_line_strip: return 3;
|
||||
case cgltf_primitive_type_triangles: return 4;
|
||||
case cgltf_primitive_type_triangle_strip: return 5;
|
||||
case cgltf_primitive_type_triangle_fan: return 6;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* cgltf_str_from_alpha_mode(cgltf_alpha_mode alpha_mode)
|
||||
{
|
||||
switch (alpha_mode)
|
||||
@@ -455,7 +469,7 @@ static void cgltf_write_asset(cgltf_write_context* context, const cgltf_asset* a
|
||||
|
||||
static void cgltf_write_primitive(cgltf_write_context* context, const cgltf_primitive* prim)
|
||||
{
|
||||
cgltf_write_intprop(context, "mode", (int) prim->type, 4);
|
||||
cgltf_write_intprop(context, "mode", cgltf_int_from_primitive_type(prim->type), 4);
|
||||
CGLTF_WRITE_IDXPROP("indices", prim->indices, context->data->accessors);
|
||||
CGLTF_WRITE_IDXPROP("material", prim->material, context->data->materials);
|
||||
cgltf_write_line(context, "\"attributes\": {");
|
||||
@@ -641,6 +655,16 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater
|
||||
context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE;
|
||||
}
|
||||
|
||||
if (material->has_anisotropy)
|
||||
{
|
||||
context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY;
|
||||
}
|
||||
|
||||
if (material->has_dispersion)
|
||||
{
|
||||
context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION;
|
||||
}
|
||||
|
||||
if (material->has_pbr_metallic_roughness)
|
||||
{
|
||||
const cgltf_pbr_metallic_roughness* params = &material->pbr_metallic_roughness;
|
||||
@@ -656,7 +680,7 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater
|
||||
cgltf_write_line(context, "}");
|
||||
}
|
||||
|
||||
if (material->unlit || material->has_pbr_specular_glossiness || material->has_clearcoat || material->has_ior || material->has_specular || material->has_transmission || material->has_sheen || material->has_volume || material->has_emissive_strength || material->has_iridescence)
|
||||
if (material->unlit || material->has_pbr_specular_glossiness || material->has_clearcoat || material->has_ior || material->has_specular || material->has_transmission || material->has_sheen || material->has_volume || material->has_emissive_strength || material->has_iridescence || material->has_anisotropy || material->has_dispersion)
|
||||
{
|
||||
cgltf_write_line(context, "\"extensions\": {");
|
||||
if (material->has_clearcoat)
|
||||
@@ -767,6 +791,22 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater
|
||||
CGLTF_WRITE_TEXTURE_INFO("iridescenceThicknessTexture", params->iridescence_thickness_texture);
|
||||
cgltf_write_line(context, "}");
|
||||
}
|
||||
if (material->has_anisotropy)
|
||||
{
|
||||
cgltf_write_line(context, "\"KHR_materials_anisotropy\": {");
|
||||
const cgltf_anisotropy* params = &material->anisotropy;
|
||||
cgltf_write_floatprop(context, "anisotropyFactor", params->anisotropy_strength, 0.f);
|
||||
cgltf_write_floatprop(context, "anisotropyRotation", params->anisotropy_rotation, 0.f);
|
||||
CGLTF_WRITE_TEXTURE_INFO("anisotropyTexture", params->anisotropy_texture);
|
||||
cgltf_write_line(context, "}");
|
||||
}
|
||||
if (material->has_dispersion)
|
||||
{
|
||||
cgltf_write_line(context, "\"KHR_materials_dispersion\": {");
|
||||
const cgltf_dispersion* params = &material->dispersion;
|
||||
cgltf_write_floatprop(context, "dispersion", params->dispersion, 0.f);
|
||||
cgltf_write_line(context, "}");
|
||||
}
|
||||
cgltf_write_line(context, "}");
|
||||
}
|
||||
|
||||
@@ -977,7 +1017,6 @@ static void cgltf_write_node(cgltf_write_context* context, const cgltf_node* nod
|
||||
|
||||
cgltf_write_line(context, "\"EXT_mesh_gpu_instancing\": {");
|
||||
{
|
||||
CGLTF_WRITE_IDXPROP("bufferView", node->mesh_gpu_instancing.buffer_view, context->data->buffer_views);
|
||||
cgltf_write_line(context, "\"attributes\": {");
|
||||
{
|
||||
for (cgltf_size i = 0; i < node->mesh_gpu_instancing.attributes_count; ++i)
|
||||
@@ -1044,14 +1083,11 @@ static void cgltf_write_accessor(cgltf_write_context* context, const cgltf_acces
|
||||
cgltf_write_sizeprop(context, "byteOffset", (int)accessor->sparse.indices_byte_offset, 0);
|
||||
CGLTF_WRITE_IDXPROP("bufferView", accessor->sparse.indices_buffer_view, context->data->buffer_views);
|
||||
cgltf_write_intprop(context, "componentType", cgltf_int_from_component_type(accessor->sparse.indices_component_type), 0);
|
||||
cgltf_write_extras(context, &accessor->sparse.indices_extras);
|
||||
cgltf_write_line(context, "}");
|
||||
cgltf_write_line(context, "\"values\": {");
|
||||
cgltf_write_sizeprop(context, "byteOffset", (int)accessor->sparse.values_byte_offset, 0);
|
||||
CGLTF_WRITE_IDXPROP("bufferView", accessor->sparse.values_buffer_view, context->data->buffer_views);
|
||||
cgltf_write_extras(context, &accessor->sparse.values_extras);
|
||||
cgltf_write_line(context, "}");
|
||||
cgltf_write_extras(context, &accessor->sparse.extras);
|
||||
cgltf_write_line(context, "}");
|
||||
}
|
||||
cgltf_write_extras(context, &accessor->extras);
|
||||
@@ -1123,6 +1159,7 @@ static void cgltf_write_light(cgltf_write_context* context, const cgltf_light* l
|
||||
cgltf_write_floatprop(context, "outerConeAngle", light->spot_outer_cone_angle, 3.14159265358979323846f/4.0f);
|
||||
cgltf_write_line(context, "}");
|
||||
}
|
||||
cgltf_write_extras( context, &light->extras );
|
||||
cgltf_write_line(context, "}");
|
||||
}
|
||||
|
||||
@@ -1249,9 +1286,15 @@ static void cgltf_write_extensions(cgltf_write_context* context, uint32_t extens
|
||||
if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE) {
|
||||
cgltf_write_stritem(context, "KHR_materials_iridescence");
|
||||
}
|
||||
if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY) {
|
||||
cgltf_write_stritem(context, "KHR_materials_anisotropy");
|
||||
}
|
||||
if (extension_flags & CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING) {
|
||||
cgltf_write_stritem(context, "EXT_mesh_gpu_instancing");
|
||||
}
|
||||
if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION) {
|
||||
cgltf_write_stritem(context, "KHR_materials_dispersion");
|
||||
}
|
||||
}
|
||||
|
||||
cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size size, const cgltf_data* data)
|
||||
|
||||
Vendored
+2
-2
@@ -17,5 +17,5 @@ double fabs(double x);
|
||||
int abs(int);
|
||||
double ldexp(double, int);
|
||||
double exp(double);
|
||||
float log(float);
|
||||
float sin(float);
|
||||
double log(double);
|
||||
double sin(double);
|
||||
|
||||
Vendored
+2
-2
@@ -90,11 +90,11 @@ exp :: proc "c" (x: f64) -> f64 {
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="log")
|
||||
log :: proc "c" (x: f32) -> f32 {
|
||||
log :: proc "c" (x: f64) -> f64 {
|
||||
return math.ln(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="sin")
|
||||
sin :: proc "c" (x: f32) -> f32 {
|
||||
sin :: proc "c" (x: f64) -> f64 {
|
||||
return math.sin(x)
|
||||
}
|
||||
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
#+build !freestanding
|
||||
package odin_libc
|
||||
|
||||
import "core:c"
|
||||
|
||||
Vendored
+5
@@ -3,6 +3,7 @@ package raylib
|
||||
import "core:c"
|
||||
|
||||
RAYGUI_SHARED :: #config(RAYGUI_SHARED, false)
|
||||
RAYGUI_WASM_LIB :: #config(RAYGUI_WASM_LIB, "wasm/libraygui.a")
|
||||
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import lib {
|
||||
@@ -22,6 +23,10 @@ when ODIN_OS == .Windows {
|
||||
"macos/libraygui.dylib" when RAYGUI_SHARED else "macos/libraygui.a",
|
||||
}
|
||||
}
|
||||
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
foreign import lib {
|
||||
RAYGUI_WASM_LIB,
|
||||
}
|
||||
} else {
|
||||
foreign import lib "system:raygui"
|
||||
}
|
||||
|
||||
Vendored
+5
@@ -100,6 +100,7 @@ MAX_TEXT_BUFFER_LENGTH :: #config(RAYLIB_MAX_TEXT_BUFFER_LENGTH, 1024)
|
||||
#assert(size_of(rune) == size_of(c.int))
|
||||
|
||||
RAYLIB_SHARED :: #config(RAYLIB_SHARED, false)
|
||||
RAYLIB_WASM_LIB :: #config(RAYLIB_WASM_LIB, "wasm/libraylib.a")
|
||||
|
||||
when ODIN_OS == .Windows {
|
||||
@(extra_linker_flags="/NODEFAULTLIB:" + ("msvcrt" when RAYLIB_SHARED else "libcmt"))
|
||||
@@ -127,6 +128,10 @@ when ODIN_OS == .Windows {
|
||||
"system:OpenGL.framework",
|
||||
"system:IOKit.framework",
|
||||
}
|
||||
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
foreign import lib {
|
||||
RAYLIB_WASM_LIB,
|
||||
}
|
||||
} else {
|
||||
foreign import lib "system:raylib"
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -523,7 +523,7 @@ Vector3Unproject :: proc "c" (source: Vector3, projection: Matrix, view: Matrix)
|
||||
|
||||
quat: Quaternion
|
||||
quat.x = source.x
|
||||
quat.y = source.z
|
||||
quat.y = source.y
|
||||
quat.z = source.z
|
||||
quat.w = 1
|
||||
|
||||
|
||||
Vendored
+6
-1
@@ -113,6 +113,7 @@ import rl "../."
|
||||
VERSION :: "5.0"
|
||||
|
||||
RAYLIB_SHARED :: #config(RAYLIB_SHARED, false)
|
||||
RAYLIB_WASM_LIB :: #config(RAYLIB_WASM_LIB, "../wasm/libraylib.a")
|
||||
|
||||
// Note: We pull in the full raylib library. If you want a truly stand-alone rlgl, then:
|
||||
// - Compile a separate rlgl library and use that in the foreign import blocks below.
|
||||
@@ -145,6 +146,10 @@ when ODIN_OS == .Windows {
|
||||
"system:OpenGL.framework",
|
||||
"system:IOKit.framework",
|
||||
}
|
||||
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
foreign import lib {
|
||||
RAYLIB_WASM_LIB,
|
||||
}
|
||||
} else {
|
||||
foreign import lib "system:raylib"
|
||||
}
|
||||
@@ -509,7 +514,7 @@ foreign lib {
|
||||
UpdateVertexBufferElements :: proc(id: c.uint, data: rawptr, dataSize: c.int, offset: c.int) --- // Update vertex buffer elements with new data
|
||||
UnloadVertexArray :: proc(vaoId: c.uint) ---
|
||||
UnloadVertexBuffer :: proc(vboId: c.uint) ---
|
||||
SetVertexAttribute :: proc(index: c.uint, compSize: c.int, type: c.int, normalized: bool, stride: c.int, pointer: rawptr) ---
|
||||
SetVertexAttribute :: proc(index: c.uint, compSize: c.int, type: c.int, normalized: bool, stride: c.int, offset: c.int) ---
|
||||
SetVertexAttributeDivisor :: proc(index: c.uint, divisor: c.int) ---
|
||||
SetVertexAttributeDefault :: proc(locIndex: c.int, value: rawptr, attribType: c.int, count: c.int) --- // Set vertex attribute default value
|
||||
DrawVertexArray :: proc(offset: c.int, count: c.int) ---
|
||||
|
||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
+34
-12
@@ -16,6 +16,8 @@ file_and_urls = [
|
||||
("vulkan_macos.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_macos.h', False),
|
||||
("vulkan_ios.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_ios.h', False),
|
||||
("vulkan_wayland.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_wayland.h', False),
|
||||
("vulkan_xlib.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_xlib.h', False),
|
||||
("vulkan_xcb.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_xcb.h', False),
|
||||
# Vulkan Video
|
||||
("vulkan_video_codec_av1std.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_av1std.h', False),
|
||||
("vulkan_video_codec_av1std_decode.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_av1std_decode.h', False),
|
||||
@@ -46,17 +48,18 @@ def no_vk(t):
|
||||
t = t.replace('PFN_', 'Proc')
|
||||
t = t.replace('PFN_', 'Proc')
|
||||
|
||||
t = re.sub('(?:Vk|VK_)?(\w+)', '\\1', t)
|
||||
t = re.sub('(?:Vk|VK_)?(\\w+)', '\\1', t)
|
||||
|
||||
# Vulkan Video
|
||||
t = re.sub('(?:Std|STD_|VK_STD)?(\w+)', '\\1', t)
|
||||
t = re.sub('(?:Std|STD_|VK_STD)?(\\w+)', '\\1', t)
|
||||
return t
|
||||
|
||||
OPAQUE_STRUCTS = """
|
||||
wl_surface :: struct {} // Opaque struct defined by Wayland
|
||||
wl_display :: struct {} // Opaque struct defined by Wayland
|
||||
IOSurfaceRef :: struct {} // Opaque struct defined by Apple’s CoreGraphics framework
|
||||
"""
|
||||
wl_surface :: struct {} // Opaque struct defined by Wayland
|
||||
wl_display :: struct {} // Opaque struct defined by Wayland
|
||||
xcb_connection_t :: struct {} // Opaque struct defined by xcb
|
||||
IOSurfaceRef :: struct {} // Opaque struct defined by Apple’s CoreGraphics framework
|
||||
"""
|
||||
|
||||
def convert_type(t, prev_name, curr_name):
|
||||
table = {
|
||||
@@ -91,6 +94,9 @@ def convert_type(t, prev_name, curr_name):
|
||||
"struct BaseInStructure": "BaseInStructure",
|
||||
"struct wl_display": "wl_display",
|
||||
"struct wl_surface": "wl_surface",
|
||||
"Display": "XlibDisplay",
|
||||
"Window": "XlibWindow",
|
||||
"VisualID": "XlibVisualID",
|
||||
'v': '',
|
||||
}
|
||||
|
||||
@@ -106,7 +112,7 @@ def convert_type(t, prev_name, curr_name):
|
||||
elif t.endswith("*"):
|
||||
pointer = "^"
|
||||
ttype = t[:len(t)-1]
|
||||
elem = convert_type(ttype, prev_name, curr_name)
|
||||
elem = convert_type(ttype, prev_name, curr_name)
|
||||
|
||||
if curr_name.endswith("s") or curr_name.endswith("Table"):
|
||||
if prev_name.endswith("Count") or prev_name.endswith("Counts"):
|
||||
@@ -445,7 +451,7 @@ def parse_enums(f):
|
||||
|
||||
def parse_fake_enums(f):
|
||||
data = re.findall(r"static const Vk(\w+FlagBits2) VK_(\w+?) = (\w+);", src, re.S)
|
||||
|
||||
|
||||
data.sort(key=lambda x: x[0])
|
||||
|
||||
fake_enums = {}
|
||||
@@ -507,7 +513,7 @@ def parse_fake_enums(f):
|
||||
continue
|
||||
|
||||
ff.append((n, v))
|
||||
|
||||
|
||||
max_flag_value = max([int(v) for n, v in ff if is_int(v)] + [0])
|
||||
max_group_value = max([int(v) for n, v in groups if is_int(v)] + [0])
|
||||
if max_flag_value < max_group_value:
|
||||
@@ -575,13 +581,13 @@ def parse_structs(f):
|
||||
ffields.append(tuple([bit_field_name, bit_field_type, comment]))
|
||||
prev_name = ""
|
||||
continue
|
||||
|
||||
|
||||
# The second way has many fields that are each 1 bit
|
||||
elif int(fname) == 1:
|
||||
bit_field_type = do_type(bit_field[0], prev_name, fname)
|
||||
ffields.append(tuple(["bitfield", bit_field_type, comment]))
|
||||
break
|
||||
|
||||
|
||||
|
||||
|
||||
if '[' in fname:
|
||||
@@ -894,6 +900,10 @@ import "core:c"
|
||||
|
||||
import win32 "core:sys/windows"
|
||||
_ :: win32
|
||||
|
||||
import "vendor:x11/xlib"
|
||||
_ :: xlib
|
||||
|
||||
when ODIN_OS == .Windows {
|
||||
\tHINSTANCE :: win32.HINSTANCE
|
||||
\tHWND :: win32.HWND
|
||||
@@ -919,7 +929,19 @@ when ODIN_OS == .Windows {
|
||||
\t}
|
||||
}
|
||||
|
||||
CAMetalLayer :: struct {}
|
||||
when xlib.IS_SUPPORTED {
|
||||
\tXlibDisplay :: xlib.Display
|
||||
\tXlibWindow :: xlib.Window
|
||||
\tXlibVisualID :: xlib.VisualID
|
||||
} else {
|
||||
\tXlibDisplay :: struct {} // Opaque struct defined by Xlib
|
||||
\tXlibWindow :: c.ulong
|
||||
\tXlibVisualID :: c.ulong
|
||||
}
|
||||
|
||||
xcb_visualid_t :: u32
|
||||
xcb_window_t :: u32
|
||||
CAMetalLayer :: struct {}
|
||||
|
||||
MTLBuffer_id :: rawptr
|
||||
MTLTexture_id :: rawptr
|
||||
|
||||
Vendored
+56
@@ -0,0 +1,56 @@
|
||||
#ifndef VULKAN_XCB_H_
|
||||
#define VULKAN_XCB_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2024 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// VK_KHR_xcb_surface is a preprocessor guard. Do not pass it to API calls.
|
||||
#define VK_KHR_xcb_surface 1
|
||||
#define VK_KHR_XCB_SURFACE_SPEC_VERSION 6
|
||||
#define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface"
|
||||
typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
|
||||
typedef struct VkXcbSurfaceCreateInfoKHR {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkXcbSurfaceCreateFlagsKHR flags;
|
||||
xcb_connection_t* connection;
|
||||
xcb_window_t window;
|
||||
} VkXcbSurfaceCreateInfoKHR;
|
||||
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateXcbSurfaceKHR)(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
||||
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id);
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
|
||||
VkInstance instance,
|
||||
const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkSurfaceKHR* pSurface);
|
||||
|
||||
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
uint32_t queueFamilyIndex,
|
||||
xcb_connection_t* connection,
|
||||
xcb_visualid_t visual_id);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Vendored
+56
@@ -0,0 +1,56 @@
|
||||
#ifndef VULKAN_XLIB_H_
|
||||
#define VULKAN_XLIB_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2024 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// VK_KHR_xlib_surface is a preprocessor guard. Do not pass it to API calls.
|
||||
#define VK_KHR_xlib_surface 1
|
||||
#define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6
|
||||
#define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface"
|
||||
typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
|
||||
typedef struct VkXlibSurfaceCreateInfoKHR {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkXlibSurfaceCreateFlagsKHR flags;
|
||||
Display* dpy;
|
||||
Window window;
|
||||
} VkXlibSurfaceCreateInfoKHR;
|
||||
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateXlibSurfaceKHR)(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
||||
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID);
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
|
||||
VkInstance instance,
|
||||
const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkSurfaceKHR* pSurface);
|
||||
|
||||
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
uint32_t queueFamilyIndex,
|
||||
Display* dpy,
|
||||
VisualID visualID);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Vendored
+6
@@ -1161,6 +1161,12 @@ EXT_METAL_OBJECTS_EXTENSION_NAME :: "VK_EXT_metal_objec
|
||||
KHR_wayland_surface :: 1
|
||||
KHR_WAYLAND_SURFACE_SPEC_VERSION :: 6
|
||||
KHR_WAYLAND_SURFACE_EXTENSION_NAME :: "VK_KHR_wayland_surface"
|
||||
KHR_xlib_surface :: 1
|
||||
KHR_XLIB_SURFACE_SPEC_VERSION :: 6
|
||||
KHR_XLIB_SURFACE_EXTENSION_NAME :: "VK_KHR_xlib_surface"
|
||||
KHR_xcb_surface :: 1
|
||||
KHR_XCB_SURFACE_SPEC_VERSION :: 6
|
||||
KHR_XCB_SURFACE_EXTENSION_NAME :: "VK_KHR_xcb_surface"
|
||||
|
||||
// Handles types
|
||||
Instance :: distinct Handle
|
||||
|
||||
Vendored
+4
@@ -4585,6 +4585,10 @@ WaylandSurfaceCreateFlagsKHR :: distinct bit_set[Wayland
|
||||
WaylandSurfaceCreateFlagKHR :: enum u32 {}
|
||||
Win32SurfaceCreateFlagsKHR :: distinct bit_set[Win32SurfaceCreateFlagKHR; Flags]
|
||||
Win32SurfaceCreateFlagKHR :: enum u32 {}
|
||||
XcbSurfaceCreateFlagsKHR :: distinct bit_set[XcbSurfaceCreateFlagKHR; Flags]
|
||||
XcbSurfaceCreateFlagKHR :: enum u32 {}
|
||||
XlibSurfaceCreateFlagsKHR :: distinct bit_set[XlibSurfaceCreateFlagKHR; Flags]
|
||||
XlibSurfaceCreateFlagKHR :: enum u32 {}
|
||||
AccessFlags2 :: distinct bit_set[AccessFlag2; Flags64]
|
||||
AccessFlag2 :: enum Flags64 {
|
||||
INDIRECT_COMMAND_READ = 0,
|
||||
|
||||
Vendored
+16
@@ -36,6 +36,8 @@ ProcCreateMacOSSurfaceMVK :: #type pr
|
||||
ProcCreateMetalSurfaceEXT :: #type proc "system" (instance: Instance, pCreateInfo: ^MetalSurfaceCreateInfoEXT, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result
|
||||
ProcCreateWaylandSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^WaylandSurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result
|
||||
ProcCreateWin32SurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^Win32SurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result
|
||||
ProcCreateXcbSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^XcbSurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result
|
||||
ProcCreateXlibSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^XlibSurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result
|
||||
ProcDebugReportMessageEXT :: #type proc "system" (instance: Instance, flags: DebugReportFlagsEXT, objectType: DebugReportObjectTypeEXT, object: u64, location: int, messageCode: i32, pLayerPrefix: cstring, pMessage: cstring)
|
||||
ProcDestroyDebugReportCallbackEXT :: #type proc "system" (instance: Instance, callback: DebugReportCallbackEXT, pAllocator: ^AllocationCallbacks)
|
||||
ProcDestroyDebugUtilsMessengerEXT :: #type proc "system" (instance: Instance, messenger: DebugUtilsMessengerEXT, pAllocator: ^AllocationCallbacks)
|
||||
@@ -113,6 +115,8 @@ ProcGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR :: #type pr
|
||||
ProcGetPhysicalDeviceVideoFormatPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pVideoFormatInfo: ^PhysicalDeviceVideoFormatInfoKHR, pVideoFormatPropertyCount: ^u32, pVideoFormatProperties: [^]VideoFormatPropertiesKHR) -> Result
|
||||
ProcGetPhysicalDeviceWaylandPresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, display: ^wl_display) -> b32
|
||||
ProcGetPhysicalDeviceWin32PresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32) -> b32
|
||||
ProcGetPhysicalDeviceXcbPresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, connection: ^xcb_connection_t, visual_id: xcb_visualid_t) -> b32
|
||||
ProcGetPhysicalDeviceXlibPresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, dpy: ^XlibDisplay, visualID: XlibVisualID) -> b32
|
||||
ProcGetWinrtDisplayNV :: #type proc "system" (physicalDevice: PhysicalDevice, deviceRelativeId: u32, pDisplay: ^DisplayKHR) -> Result
|
||||
ProcReleaseDisplayEXT :: #type proc "system" (physicalDevice: PhysicalDevice, display: DisplayKHR) -> Result
|
||||
ProcSubmitDebugUtilsMessageEXT :: #type proc "system" (instance: Instance, messageSeverity: DebugUtilsMessageSeverityFlagsEXT, messageTypes: DebugUtilsMessageTypeFlagsEXT, pCallbackData: ^DebugUtilsMessengerCallbackDataEXT)
|
||||
@@ -730,6 +734,8 @@ CreateMacOSSurfaceMVK: ProcCreateMacO
|
||||
CreateMetalSurfaceEXT: ProcCreateMetalSurfaceEXT
|
||||
CreateWaylandSurfaceKHR: ProcCreateWaylandSurfaceKHR
|
||||
CreateWin32SurfaceKHR: ProcCreateWin32SurfaceKHR
|
||||
CreateXcbSurfaceKHR: ProcCreateXcbSurfaceKHR
|
||||
CreateXlibSurfaceKHR: ProcCreateXlibSurfaceKHR
|
||||
DebugReportMessageEXT: ProcDebugReportMessageEXT
|
||||
DestroyDebugReportCallbackEXT: ProcDestroyDebugReportCallbackEXT
|
||||
DestroyDebugUtilsMessengerEXT: ProcDestroyDebugUtilsMessengerEXT
|
||||
@@ -806,6 +812,8 @@ GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR: ProcGetPhysica
|
||||
GetPhysicalDeviceVideoFormatPropertiesKHR: ProcGetPhysicalDeviceVideoFormatPropertiesKHR
|
||||
GetPhysicalDeviceWaylandPresentationSupportKHR: ProcGetPhysicalDeviceWaylandPresentationSupportKHR
|
||||
GetPhysicalDeviceWin32PresentationSupportKHR: ProcGetPhysicalDeviceWin32PresentationSupportKHR
|
||||
GetPhysicalDeviceXcbPresentationSupportKHR: ProcGetPhysicalDeviceXcbPresentationSupportKHR
|
||||
GetPhysicalDeviceXlibPresentationSupportKHR: ProcGetPhysicalDeviceXlibPresentationSupportKHR
|
||||
GetWinrtDisplayNV: ProcGetWinrtDisplayNV
|
||||
ReleaseDisplayEXT: ProcReleaseDisplayEXT
|
||||
SubmitDebugUtilsMessageEXT: ProcSubmitDebugUtilsMessageEXT
|
||||
@@ -1423,6 +1431,8 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) {
|
||||
set_proc_address(&CreateMetalSurfaceEXT, "vkCreateMetalSurfaceEXT")
|
||||
set_proc_address(&CreateWaylandSurfaceKHR, "vkCreateWaylandSurfaceKHR")
|
||||
set_proc_address(&CreateWin32SurfaceKHR, "vkCreateWin32SurfaceKHR")
|
||||
set_proc_address(&CreateXcbSurfaceKHR, "vkCreateXcbSurfaceKHR")
|
||||
set_proc_address(&CreateXlibSurfaceKHR, "vkCreateXlibSurfaceKHR")
|
||||
set_proc_address(&DebugReportMessageEXT, "vkDebugReportMessageEXT")
|
||||
set_proc_address(&DestroyDebugReportCallbackEXT, "vkDestroyDebugReportCallbackEXT")
|
||||
set_proc_address(&DestroyDebugUtilsMessengerEXT, "vkDestroyDebugUtilsMessengerEXT")
|
||||
@@ -1499,6 +1509,8 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) {
|
||||
set_proc_address(&GetPhysicalDeviceVideoFormatPropertiesKHR, "vkGetPhysicalDeviceVideoFormatPropertiesKHR")
|
||||
set_proc_address(&GetPhysicalDeviceWaylandPresentationSupportKHR, "vkGetPhysicalDeviceWaylandPresentationSupportKHR")
|
||||
set_proc_address(&GetPhysicalDeviceWin32PresentationSupportKHR, "vkGetPhysicalDeviceWin32PresentationSupportKHR")
|
||||
set_proc_address(&GetPhysicalDeviceXcbPresentationSupportKHR, "vkGetPhysicalDeviceXcbPresentationSupportKHR")
|
||||
set_proc_address(&GetPhysicalDeviceXlibPresentationSupportKHR, "vkGetPhysicalDeviceXlibPresentationSupportKHR")
|
||||
set_proc_address(&GetWinrtDisplayNV, "vkGetWinrtDisplayNV")
|
||||
set_proc_address(&ReleaseDisplayEXT, "vkReleaseDisplayEXT")
|
||||
set_proc_address(&SubmitDebugUtilsMessageEXT, "vkSubmitDebugUtilsMessageEXT")
|
||||
@@ -3879,6 +3891,8 @@ load_proc_addresses_instance :: proc(instance: Instance) {
|
||||
CreateMetalSurfaceEXT = auto_cast GetInstanceProcAddr(instance, "vkCreateMetalSurfaceEXT")
|
||||
CreateWaylandSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR")
|
||||
CreateWin32SurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR")
|
||||
CreateXcbSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR")
|
||||
CreateXlibSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR")
|
||||
DebugReportMessageEXT = auto_cast GetInstanceProcAddr(instance, "vkDebugReportMessageEXT")
|
||||
DestroyDebugReportCallbackEXT = auto_cast GetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT")
|
||||
DestroyDebugUtilsMessengerEXT = auto_cast GetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT")
|
||||
@@ -3955,6 +3969,8 @@ load_proc_addresses_instance :: proc(instance: Instance) {
|
||||
GetPhysicalDeviceVideoFormatPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoFormatPropertiesKHR")
|
||||
GetPhysicalDeviceWaylandPresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR")
|
||||
GetPhysicalDeviceWin32PresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR")
|
||||
GetPhysicalDeviceXcbPresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR")
|
||||
GetPhysicalDeviceXlibPresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR")
|
||||
GetWinrtDisplayNV = auto_cast GetInstanceProcAddr(instance, "vkGetWinrtDisplayNV")
|
||||
ReleaseDisplayEXT = auto_cast GetInstanceProcAddr(instance, "vkReleaseDisplayEXT")
|
||||
SubmitDebugUtilsMessageEXT = auto_cast GetInstanceProcAddr(instance, "vkSubmitDebugUtilsMessageEXT")
|
||||
|
||||
Vendored
+37
-4
@@ -7,6 +7,10 @@ import "core:c"
|
||||
|
||||
import win32 "core:sys/windows"
|
||||
_ :: win32
|
||||
|
||||
import "vendor:x11/xlib"
|
||||
_ :: xlib
|
||||
|
||||
when ODIN_OS == .Windows {
|
||||
HINSTANCE :: win32.HINSTANCE
|
||||
HWND :: win32.HWND
|
||||
@@ -32,7 +36,19 @@ when ODIN_OS == .Windows {
|
||||
}
|
||||
}
|
||||
|
||||
CAMetalLayer :: struct {}
|
||||
when xlib.IS_SUPPORTED {
|
||||
XlibDisplay :: xlib.Display
|
||||
XlibWindow :: xlib.Window
|
||||
XlibVisualID :: xlib.VisualID
|
||||
} else {
|
||||
XlibDisplay :: struct {} // Opaque struct defined by Xlib
|
||||
XlibWindow :: c.ulong
|
||||
XlibVisualID :: c.ulong
|
||||
}
|
||||
|
||||
xcb_visualid_t :: u32
|
||||
xcb_window_t :: u32
|
||||
CAMetalLayer :: struct {}
|
||||
|
||||
MTLBuffer_id :: rawptr
|
||||
MTLTexture_id :: rawptr
|
||||
@@ -8910,6 +8926,22 @@ WaylandSurfaceCreateInfoKHR :: struct {
|
||||
surface: ^wl_surface,
|
||||
}
|
||||
|
||||
XlibSurfaceCreateInfoKHR :: struct {
|
||||
sType: StructureType,
|
||||
pNext: rawptr,
|
||||
flags: XlibSurfaceCreateFlagsKHR,
|
||||
dpy: ^XlibDisplay,
|
||||
window: XlibWindow,
|
||||
}
|
||||
|
||||
XcbSurfaceCreateInfoKHR :: struct {
|
||||
sType: StructureType,
|
||||
pNext: rawptr,
|
||||
flags: XcbSurfaceCreateFlagsKHR,
|
||||
connection: ^xcb_connection_t,
|
||||
window: xcb_window_t,
|
||||
}
|
||||
|
||||
VideoAV1ColorConfigFlags :: struct {
|
||||
bitfield: u32,
|
||||
}
|
||||
@@ -9753,9 +9785,10 @@ VideoEncodeH265ReferenceInfo :: struct {
|
||||
|
||||
// Opaque structs
|
||||
|
||||
wl_surface :: struct {} // Opaque struct defined by Wayland
|
||||
wl_display :: struct {} // Opaque struct defined by Wayland
|
||||
IOSurfaceRef :: struct {} // Opaque struct defined by Apple’s CoreGraphics framework
|
||||
wl_surface :: struct {} // Opaque struct defined by Wayland
|
||||
wl_display :: struct {} // Opaque struct defined by Wayland
|
||||
xcb_connection_t :: struct {} // Opaque struct defined by xcb
|
||||
IOSurfaceRef :: struct {} // Opaque struct defined by Apple’s CoreGraphics framework
|
||||
// Aliases
|
||||
PhysicalDeviceVariablePointerFeatures :: PhysicalDeviceVariablePointersFeatures
|
||||
PhysicalDeviceShaderDrawParameterFeatures :: PhysicalDeviceShaderDrawParametersFeatures
|
||||
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
package xlib
|
||||
|
||||
// Value, specifying whether `vendor:x11/xlib` is available on the current platform.
|
||||
IS_SUPPORTED :: ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD
|
||||
Reference in New Issue
Block a user