mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 09:22:22 -07:00
Merge remote-tracking branch 'live/master' into macharena
This commit is contained in:
@@ -6,7 +6,7 @@ jobs:
|
||||
name: NetBSD Build, Check, and Test
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
PKGSRC_BRANCH: 2024Q3
|
||||
PKGSRC_BRANCH: 2025Q2
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build, Check, and Test
|
||||
|
||||
@@ -297,3 +297,8 @@ build.sh
|
||||
*.rdi
|
||||
tests/issues/build/*
|
||||
misc/featuregen/featuregen
|
||||
|
||||
# Clangd stuff
|
||||
.cache/
|
||||
.clangd
|
||||
compile_commands.json
|
||||
|
||||
@@ -145,7 +145,7 @@ ODIN_OS_STRING :: ODIN_OS_STRING
|
||||
|
||||
/*
|
||||
An `enum` value indicating the platform subtarget, chosen using the `-subtarget` switch.
|
||||
Possible values are: `.Default` `.iOS`, and `.Android`.
|
||||
Possible values are: `.Default` `.iPhone`, .iPhoneSimulator, and `.Android`.
|
||||
*/
|
||||
ODIN_PLATFORM_SUBTARGET :: ODIN_PLATFORM_SUBTARGET
|
||||
|
||||
|
||||
@@ -213,6 +213,10 @@ type_is_subtype_of :: proc($T, $U: typeid) -> bool ---
|
||||
|
||||
type_field_index_of :: proc($T: typeid, $name: string) -> uintptr ---
|
||||
|
||||
// "Contiguous" means that the set of enum constants, when sorted, have a difference of either 0 or 1 between consecutive values.
|
||||
// This is the exact opposite of "sparse".
|
||||
type_enum_is_contiguous :: proc($T: typeid) -> bool where type_is_enum(T) ---
|
||||
|
||||
type_equal_proc :: proc($T: typeid) -> (equal: proc "contextless" (rawptr, rawptr) -> bool) where type_is_comparable(T) ---
|
||||
type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) where type_is_comparable(T) ---
|
||||
|
||||
@@ -310,6 +314,7 @@ simd_indices :: proc($T: typeid/#simd[$N]$E) -> T where type_is_numeric(T) ---
|
||||
|
||||
simd_shuffle :: proc(a, b: #simd[N]T, indices: ..int) -> #simd[len(indices)]T ---
|
||||
simd_select :: proc(cond: #simd[N]boolean_or_integer, true, false: #simd[N]T) -> #simd[N]T ---
|
||||
simd_runtime_swizzle :: proc(table: #simd[N]T, indices: #simd[N]T) -> #simd[N]T where type_is_integer(T) ---
|
||||
|
||||
// Lane-wise operations
|
||||
simd_ceil :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
|
||||
|
||||
@@ -557,7 +557,8 @@ ALL_ODIN_OS_TYPES :: Odin_OS_Types{
|
||||
// Defined internally by the compiler
|
||||
Odin_Platform_Subtarget_Type :: enum int {
|
||||
Default,
|
||||
iOS,
|
||||
iPhone,
|
||||
iPhoneSimulator
|
||||
Android,
|
||||
}
|
||||
*/
|
||||
@@ -565,6 +566,8 @@ Odin_Platform_Subtarget_Type :: type_of(ODIN_PLATFORM_SUBTARGET)
|
||||
|
||||
Odin_Platform_Subtarget_Types :: bit_set[Odin_Platform_Subtarget_Type]
|
||||
|
||||
@(builtin)
|
||||
ODIN_PLATFORM_SUBTARGET_IOS :: ODIN_PLATFORM_SUBTARGET == .iPhone || ODIN_PLATFORM_SUBTARGET == .iPhoneSimulator
|
||||
|
||||
/*
|
||||
// Defined internally by the compiler
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
package runtime
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -31,5 +31,6 @@ foreign ObjC {
|
||||
class_getInstanceVariable :: proc "c" (cls : objc_Class, name: cstring) -> objc_Ivar ---
|
||||
class_getInstanceSize :: proc "c" (cls : objc_Class) -> uint ---
|
||||
ivar_getOffset :: proc "c" (v: objc_Ivar) -> uintptr ---
|
||||
object_getClass :: proc "c" (obj: objc_id) -> objc_Class ---
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ package libc
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package libc
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ package libc
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import "core:c"
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import "base:intrinsics"
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ package libc
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ package libc
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ when ODIN_OS == .Windows {
|
||||
"system:legacy_stdio_definitions.lib",
|
||||
}
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ package libc
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import "base:runtime"
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ package libc
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ package libc
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ package libc
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ package libc
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@ hash_string :: proc(algorithm: Algorithm, data: string, allocator := context.all
|
||||
// in a newly allocated slice.
|
||||
hash_bytes :: proc(algorithm: Algorithm, data: []byte, allocator := context.allocator) -> []byte {
|
||||
dst := make([]byte, DIGEST_SIZES[algorithm], allocator)
|
||||
hash_bytes_to_buffer(algorithm, data, dst)
|
||||
return dst
|
||||
return hash_bytes_to_buffer(algorithm, data, dst)
|
||||
}
|
||||
|
||||
// hash_string_to_buffer will hash the given input and assign the
|
||||
@@ -46,7 +45,7 @@ hash_bytes_to_buffer :: proc(algorithm: Algorithm, data, hash: []byte) -> []byte
|
||||
update(&ctx, data)
|
||||
final(&ctx, hash)
|
||||
|
||||
return hash
|
||||
return hash[:DIGEST_SIZES[algorithm]]
|
||||
}
|
||||
|
||||
// hash_stream will incrementally fully consume a stream, and return the
|
||||
|
||||
+1
-1
@@ -127,7 +127,7 @@ jenkins :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
|
||||
}
|
||||
|
||||
@(optimization_mode="favor_size")
|
||||
murmur32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
|
||||
murmur32 :: proc "contextless" (data: []byte, seed := u32(0x9747b28c)) -> u32 {
|
||||
c1_32: u32 : 0xcc9e2d51
|
||||
c2_32: u32 : 0x1b873593
|
||||
|
||||
|
||||
@@ -2223,6 +2223,9 @@ Initialize a buddy allocator.
|
||||
|
||||
This procedure initializes the buddy allocator `b` with a backing buffer `data`
|
||||
and block alignment specified by `alignment`.
|
||||
|
||||
`alignment` may be any power of two, but the backing buffer must be aligned to
|
||||
at least `size_of(Buddy_Block)`.
|
||||
*/
|
||||
buddy_allocator_init :: proc(b: ^Buddy_Allocator, data: []byte, alignment: uint, loc := #caller_location) {
|
||||
assert(data != nil)
|
||||
@@ -2233,7 +2236,7 @@ buddy_allocator_init :: proc(b: ^Buddy_Allocator, data: []byte, alignment: uint,
|
||||
alignment = size_of(Buddy_Block)
|
||||
}
|
||||
ptr := raw_data(data)
|
||||
assert(uintptr(ptr) % uintptr(alignment) == 0, "data is not aligned to minimum alignment", loc)
|
||||
assert(uintptr(ptr) % uintptr(alignment) == 0, "The data is not aligned to the minimum alignment, which must be at least `size_of(Buddy_Block)`.", loc)
|
||||
b.head = (^Buddy_Block)(ptr)
|
||||
b.head.size = len(data)
|
||||
b.head.is_free = true
|
||||
|
||||
@@ -89,8 +89,8 @@ memory_block_alloc :: proc(committed, reserved: uint, alignment: uint = 0, flags
|
||||
reserved = align_formula(reserved, page_size)
|
||||
committed = clamp(committed, 0, reserved)
|
||||
|
||||
total_size := uint(reserved + max(alignment, size_of(Platform_Memory_Block)))
|
||||
base_offset := uintptr(max(alignment, size_of(Platform_Memory_Block)))
|
||||
total_size := reserved + alignment + size_of(Platform_Memory_Block)
|
||||
base_offset := mem.align_forward_uintptr(size_of(Platform_Memory_Block), max(uintptr(alignment), align_of(Platform_Memory_Block)))
|
||||
protect_offset := uintptr(0)
|
||||
|
||||
do_protection := false
|
||||
|
||||
@@ -23,7 +23,7 @@ package net
|
||||
import "core:strings"
|
||||
import "core:sys/posix"
|
||||
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
|
||||
@(private)
|
||||
_enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Interfaces_Error) {
|
||||
|
||||
@@ -348,27 +348,30 @@ consume_comment_group :: proc(p: ^Parser, n: int) -> (comments: ^ast.Comment_Gro
|
||||
}
|
||||
|
||||
consume_comment_groups :: proc(p: ^Parser, prev: tokenizer.Token) {
|
||||
if p.curr_tok.kind == .Comment {
|
||||
comment: ^ast.Comment_Group
|
||||
end_line := 0
|
||||
|
||||
if p.curr_tok.pos.line == prev.pos.line {
|
||||
comment, end_line = consume_comment_group(p, 0)
|
||||
if p.curr_tok.pos.line != end_line || p.curr_tok.kind == .EOF {
|
||||
p.line_comment = comment
|
||||
}
|
||||
}
|
||||
|
||||
end_line = -1
|
||||
for p.curr_tok.kind == .Comment {
|
||||
comment, end_line = consume_comment_group(p, 1)
|
||||
}
|
||||
if end_line+1 >= p.curr_tok.pos.line || end_line < 0 {
|
||||
p.lead_comment = comment
|
||||
}
|
||||
|
||||
assert(p.curr_tok.kind != .Comment)
|
||||
if p.curr_tok.kind != .Comment {
|
||||
return
|
||||
}
|
||||
comment: ^ast.Comment_Group
|
||||
end_line := 0
|
||||
|
||||
if p.curr_tok.pos.line == prev.pos.line {
|
||||
comment, end_line = consume_comment_group(p, 0)
|
||||
if p.curr_tok.pos.line != end_line ||
|
||||
p.curr_tok.pos.line == prev.pos.line+1 ||
|
||||
p.curr_tok.kind == .EOF {
|
||||
p.line_comment = comment
|
||||
}
|
||||
}
|
||||
|
||||
end_line = -1
|
||||
for p.curr_tok.kind == .Comment {
|
||||
comment, end_line = consume_comment_group(p, 1)
|
||||
}
|
||||
if end_line+1 >= p.curr_tok.pos.line || end_line < 0 {
|
||||
p.lead_comment = comment
|
||||
}
|
||||
|
||||
assert(p.curr_tok.kind != .Comment)
|
||||
}
|
||||
|
||||
advance_token :: proc(p: ^Parser) -> tokenizer.Token {
|
||||
|
||||
@@ -10,7 +10,7 @@ import "core:sys/posix"
|
||||
import "core:sys/unix"
|
||||
import "core:time"
|
||||
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
|
||||
foreign lib {
|
||||
sysctl :: proc(
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package os
|
||||
|
||||
foreign import dl "system:dl"
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import pthread "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
foreign import pthread "system:System"
|
||||
|
||||
import "base:runtime"
|
||||
import "core:strings"
|
||||
|
||||
@@ -967,8 +967,8 @@ _processor_core_count :: proc() -> int {
|
||||
@(private, require_results)
|
||||
_alloc_command_line_arguments :: proc() -> []string {
|
||||
res := make([]string, len(runtime.args__))
|
||||
for arg, i in runtime.args__ {
|
||||
res[i] = string(arg)
|
||||
for _, i in res {
|
||||
res[i] = string(runtime.args__[i])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -1100,8 +1100,8 @@ _processor_core_count :: proc() -> int {
|
||||
@(private, require_results)
|
||||
_alloc_command_line_arguments :: proc() -> []string {
|
||||
res := make([]string, len(runtime.args__))
|
||||
for arg, i in runtime.args__ {
|
||||
res[i] = string(arg)
|
||||
for _, i in res {
|
||||
res[i] = string(runtime.args__[i])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -1017,8 +1017,8 @@ _processor_core_count :: proc() -> int {
|
||||
@(private, require_results)
|
||||
_alloc_command_line_arguments :: proc() -> []string {
|
||||
res := make([]string, len(runtime.args__))
|
||||
for arg, i in runtime.args__ {
|
||||
res[i] = string(arg)
|
||||
for _, i in res {
|
||||
res[i] = string(runtime.args__[i])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -917,8 +917,8 @@ _processor_core_count :: proc() -> int {
|
||||
@(private, require_results)
|
||||
_alloc_command_line_arguments :: proc() -> []string {
|
||||
res := make([]string, len(runtime.args__))
|
||||
for arg, i in runtime.args__ {
|
||||
res[i] = string(arg)
|
||||
for _, i in res {
|
||||
res[i] = string(runtime.args__[i])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#+build !wasi
|
||||
#+build !js
|
||||
package filepath
|
||||
|
||||
import "core:os"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#+build !wasi
|
||||
#+build !js
|
||||
package filepath
|
||||
|
||||
import "core:os"
|
||||
|
||||
@@ -2440,6 +2440,57 @@ Graphically, the operation looks as follows. The `t` and `f` represent the
|
||||
*/
|
||||
select :: intrinsics.simd_select
|
||||
|
||||
/*
|
||||
Runtime Equivalent to Shuffle.
|
||||
|
||||
Performs element-wise table lookups using runtime indices.
|
||||
Each element in the indices vector selects an element from the table vector.
|
||||
The indices are automatically masked to prevent out-of-bounds access.
|
||||
|
||||
This operation is hardware-accelerated on most platforms when using 8-bit
|
||||
integer vectors. For other element types or unsupported vector sizes, it
|
||||
falls back to software emulation.
|
||||
|
||||
Inputs:
|
||||
- `table`: The lookup table vector (should be power-of-2 size for correct masking).
|
||||
- `indices`: The indices vector (automatically masked to valid range).
|
||||
|
||||
Returns:
|
||||
- A vector where `result[i] = table[indices[i] & (table_size-1)]`.
|
||||
|
||||
Operation:
|
||||
|
||||
for i in 0 ..< len(indices) {
|
||||
masked_index := indices[i] & (len(table) - 1)
|
||||
result[i] = table[masked_index]
|
||||
}
|
||||
return result
|
||||
|
||||
Implementation:
|
||||
|
||||
| Platform | Lane Size | Implementation |
|
||||
|-------------|-------------------------------------------|---------------------|
|
||||
| x86-64 | pshufb (16B), vpshufb (32B), AVX512 (64B) | Single vector |
|
||||
| ARM64 | tbl1 (16B), tbl2 (32B), tbl4 (64B) | Automatic splitting |
|
||||
| ARM32 | vtbl1 (8B), vtbl2 (16B), vtbl4 (32B) | Automatic splitting |
|
||||
| WebAssembly | i8x16.swizzle (16B), Emulation (>16B) | Mixed |
|
||||
| Other | Emulation | Software |
|
||||
|
||||
Example:
|
||||
|
||||
import "core:simd"
|
||||
import "core:fmt"
|
||||
|
||||
runtime_swizzle_example :: proc() {
|
||||
table := simd.u8x16{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
|
||||
indices := simd.u8x16{15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
|
||||
result := simd.runtime_swizzle(table, indices)
|
||||
fmt.println(result) // Expected: {15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
|
||||
}
|
||||
|
||||
*/
|
||||
runtime_swizzle :: intrinsics.simd_runtime_swizzle
|
||||
|
||||
/*
|
||||
Compute the square root of each lane in a SIMD vector.
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,7 @@ import "core:c"
|
||||
import "core:sys/darwin"
|
||||
import "core:time"
|
||||
|
||||
foreign import System "system:System.framework"
|
||||
foreign import System "system:System"
|
||||
|
||||
foreign System {
|
||||
// __ulock_wait is not available on 10.15
|
||||
|
||||
@@ -5,7 +5,7 @@ package sync
|
||||
import "core:c"
|
||||
import "base:intrinsics"
|
||||
|
||||
foreign import pthread "system:System.framework"
|
||||
foreign import pthread "system:System"
|
||||
|
||||
_current_thread_id :: proc "contextless" () -> int {
|
||||
tid: u64
|
||||
|
||||
@@ -62,7 +62,7 @@ global_block_descriptor := Block_Descriptor{
|
||||
size = size_of(Internal_Block_Literal),
|
||||
}
|
||||
|
||||
foreign import libSystem "system:System.framework"
|
||||
foreign import libSystem "system:System"
|
||||
foreign libSystem {
|
||||
_NSConcreteGlobalBlock: intrinsics.objc_class
|
||||
_NSConcreteStackBlock: intrinsics.objc_class
|
||||
|
||||
@@ -4,7 +4,7 @@ package darwin
|
||||
import "core:c"
|
||||
|
||||
@(export)
|
||||
foreign import system "system:System.framework"
|
||||
foreign import system "system:System"
|
||||
|
||||
Bool :: b8
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package darwin
|
||||
|
||||
foreign import mach "system:System.framework"
|
||||
foreign import mach "system:System"
|
||||
|
||||
import "core:c"
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -4,7 +4,7 @@ import "base:intrinsics"
|
||||
|
||||
import "core:sys/posix"
|
||||
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
|
||||
// Incomplete bindings to the proc API on MacOS, add to when needed.
|
||||
|
||||
|
||||
@@ -3,23 +3,13 @@ package darwin
|
||||
// #define OS_WAIT_ON_ADDR_AVAILABILITY \
|
||||
// __API_AVAILABLE(macos(14.4), ios(17.4), tvos(17.4), watchos(10.4))
|
||||
when ODIN_OS == .Darwin {
|
||||
|
||||
when ODIN_PLATFORM_SUBTARGET == .iOS && ODIN_MINIMUM_OS_VERSION >= 17_04_00 {
|
||||
WAIT_ON_ADDRESS_AVAILABLE :: true
|
||||
} else when ODIN_MINIMUM_OS_VERSION >= 14_04_00 {
|
||||
WAIT_ON_ADDRESS_AVAILABLE :: true
|
||||
when ODIN_PLATFORM_SUBTARGET_IOS {
|
||||
WAIT_ON_ADDRESS_AVAILABLE :: ODIN_MINIMUM_OS_VERSION >= 17_04_00
|
||||
ULOCK_WAIT_2_AVAILABLE :: ODIN_MINIMUM_OS_VERSION >= 14_00_00
|
||||
} else {
|
||||
WAIT_ON_ADDRESS_AVAILABLE :: false
|
||||
WAIT_ON_ADDRESS_AVAILABLE :: ODIN_MINIMUM_OS_VERSION >= 14_04_00
|
||||
ULOCK_WAIT_2_AVAILABLE :: ODIN_MINIMUM_OS_VERSION >= 11_00_00
|
||||
}
|
||||
|
||||
when ODIN_PLATFORM_SUBTARGET == .iOS && ODIN_MINIMUM_OS_VERSION >= 14_00_00 {
|
||||
ULOCK_WAIT_2_AVAILABLE :: true
|
||||
} else when ODIN_MINIMUM_OS_VERSION >= 11_00_00 {
|
||||
ULOCK_WAIT_2_AVAILABLE :: true
|
||||
} else {
|
||||
ULOCK_WAIT_2_AVAILABLE :: false
|
||||
}
|
||||
|
||||
} else {
|
||||
WAIT_ON_ADDRESS_AVAILABLE :: false
|
||||
ULOCK_WAIT_2_AVAILABLE :: false
|
||||
|
||||
@@ -28,7 +28,7 @@ init_platform :: proc() {
|
||||
|
||||
macos_version = {int(version.majorVersion), int(version.minorVersion), int(version.patchVersion)}
|
||||
|
||||
when ODIN_PLATFORM_SUBTARGET == .iOS {
|
||||
when ODIN_PLATFORM_SUBTARGET_IOS {
|
||||
os_version.platform = .iOS
|
||||
ws(&b, "iOS")
|
||||
} else {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package kqueue
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else when ODIN_OS == .Haiku {
|
||||
foreign import lib "system:network"
|
||||
} else {
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD {
|
||||
foreign import lib "system:dl"
|
||||
} else {
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package posix
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import "base:intrinsics"
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Linux {
|
||||
foreign import lib "system:pthread"
|
||||
} else {
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import "base:intrinsics"
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import "core:c/libc"
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import lib "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ when ODIN_OS == .Windows {
|
||||
"system:legacy_stdio_definitions.lib",
|
||||
}
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import "base:intrinsics"
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import "core:c/libc"
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import lib "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import lib "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import "base:intrinsics"
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package posix
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import libc "system:System.framework"
|
||||
foreign import libc "system:System"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import "core:c"
|
||||
import "core:c/libc"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import "core:c"
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import lib "system:libucrt.lib"
|
||||
} else when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package posix
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package posix
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
foreign import lib "system:System"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
@@ -25,11 +25,12 @@ COINIT :: enum DWORD {
|
||||
SPEED_OVER_MEMORY = 0x8,
|
||||
}
|
||||
|
||||
IUnknown_UUID_STRING :: "00000000-0000-0000-C000-000000000046"
|
||||
IUnknown_UUID := &IID{0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}
|
||||
IUnknownVtbl :: IUnknown_VTable
|
||||
IUnknown :: struct {
|
||||
using _iunknown_vtable: ^IUnknown_VTable,
|
||||
}
|
||||
|
||||
IUnknownVtbl :: IUnknown_VTable
|
||||
IUnknown_VTable :: struct {
|
||||
QueryInterface: proc "system" (This: ^IUnknown, riid: REFIID, ppvObject: ^rawptr) -> HRESULT,
|
||||
AddRef: proc "system" (This: ^IUnknown) -> ULONG,
|
||||
|
||||
@@ -170,15 +170,15 @@ wstring_to_utf8_alloc :: proc(s: wstring, N: int, allocator := context.temp_allo
|
||||
return string(text[:n]), nil
|
||||
}
|
||||
|
||||
wstring_to_utf8_buf :: proc(buf: []u8, s: wstring) -> (res: string) {
|
||||
n := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, -1, nil, 0, nil, nil)
|
||||
wstring_to_utf8_buf :: proc(buf: []u8, s: wstring, N := -1) -> (res: string) {
|
||||
n := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N), nil, 0, nil, nil)
|
||||
if n == 0 {
|
||||
return
|
||||
} else if int(n) > len(buf) {
|
||||
return
|
||||
}
|
||||
|
||||
n2 := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, -1, raw_data(buf), n, nil, nil)
|
||||
n2 := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N), raw_data(buf), n, nil, nil)
|
||||
if n2 == 0 {
|
||||
return
|
||||
} else if int(n2) > len(buf) {
|
||||
@@ -196,6 +196,21 @@ wstring_to_utf8_buf :: proc(buf: []u8, s: wstring) -> (res: string) {
|
||||
|
||||
wstring_to_utf8 :: proc{wstring_to_utf8_alloc, wstring_to_utf8_buf}
|
||||
|
||||
/*
|
||||
Converts a UTF-16 string into a regular UTF-8 `string` and allocates the result.
|
||||
If the input is null-terminated, only the part of the input string leading up
|
||||
to it will be converted.
|
||||
|
||||
*Allocates Using Provided Allocator*
|
||||
|
||||
Inputs:
|
||||
- s: The string to be converted
|
||||
- allocator: (default: context.allocator)
|
||||
|
||||
Returns:
|
||||
- res: A cloned and converted string
|
||||
- err: An optional allocator error if one occured, `nil` otherwise
|
||||
*/
|
||||
utf16_to_utf8_alloc :: proc(s: []u16, allocator := context.temp_allocator) -> (res: string, err: runtime.Allocator_Error) {
|
||||
if len(s) == 0 {
|
||||
return "", nil
|
||||
@@ -203,11 +218,25 @@ utf16_to_utf8_alloc :: proc(s: []u16, allocator := context.temp_allocator) -> (r
|
||||
return wstring_to_utf8(raw_data(s), len(s), allocator)
|
||||
}
|
||||
|
||||
/*
|
||||
Converts a UTF-16 string into a regular UTF-8 `string`, using `buf` as its backing.
|
||||
If the input is null-terminated, only the part of the input string leading up
|
||||
to it will be converted.
|
||||
|
||||
*Uses `buf` for backing*
|
||||
|
||||
Inputs:
|
||||
- s: The string to be converted
|
||||
- buf: Backing buffer for result string
|
||||
|
||||
Returns:
|
||||
- res: A converted string, backed byu `buf`
|
||||
*/
|
||||
utf16_to_utf8_buf :: proc(buf: []u8, s: []u16) -> (res: string) {
|
||||
if len(s) == 0 {
|
||||
return
|
||||
}
|
||||
return wstring_to_utf8(buf, raw_data(s))
|
||||
return wstring_to_utf8(buf, raw_data(s), len(s))
|
||||
}
|
||||
|
||||
utf16_to_utf8 :: proc{utf16_to_utf8_alloc, utf16_to_utf8_buf}
|
||||
|
||||
+65
-25
@@ -171,15 +171,18 @@ struct TargetMetrics {
|
||||
|
||||
enum Subtarget : u32 {
|
||||
Subtarget_Default,
|
||||
Subtarget_iOS,
|
||||
Subtarget_iPhone,
|
||||
Subtarget_iPhoneSimulator,
|
||||
Subtarget_Android,
|
||||
|
||||
|
||||
Subtarget_COUNT,
|
||||
Subtarget_Invalid, // NOTE(harold): Must appear after _COUNT as this is not a real subtarget
|
||||
};
|
||||
|
||||
gb_global String subtarget_strings[Subtarget_COUNT] = {
|
||||
str_lit(""),
|
||||
str_lit("ios"),
|
||||
str_lit("iphone"),
|
||||
str_lit("iphonesimulator"),
|
||||
str_lit("android"),
|
||||
};
|
||||
|
||||
@@ -306,6 +309,7 @@ enum VetFlags : u64 {
|
||||
VetFlag_Cast = 1u<<8,
|
||||
VetFlag_Tabs = 1u<<9,
|
||||
VetFlag_UnusedProcedures = 1u<<10,
|
||||
VetFlag_ExplicitAllocators = 1u<<11,
|
||||
|
||||
VetFlag_Unused = VetFlag_UnusedVariables|VetFlag_UnusedImports,
|
||||
|
||||
@@ -339,6 +343,8 @@ u64 get_vet_flag_from_name(String const &name) {
|
||||
return VetFlag_Tabs;
|
||||
} else if (name == "unused-procedures") {
|
||||
return VetFlag_UnusedProcedures;
|
||||
} else if (name == "explicit-allocators") {
|
||||
return VetFlag_ExplicitAllocators;
|
||||
}
|
||||
return VetFlag_NONE;
|
||||
}
|
||||
@@ -857,7 +863,7 @@ gb_global NamedTargetMetrics *selected_target_metrics;
|
||||
gb_global Subtarget selected_subtarget;
|
||||
|
||||
|
||||
gb_internal TargetOsKind get_target_os_from_string(String str, Subtarget *subtarget_ = nullptr) {
|
||||
gb_internal TargetOsKind get_target_os_from_string(String str, Subtarget *subtarget_ = nullptr, String *subtarget_str = nullptr) {
|
||||
String os_name = str;
|
||||
String subtarget = {};
|
||||
auto part = string_partition(str, str_lit(":"));
|
||||
@@ -874,18 +880,26 @@ gb_internal TargetOsKind get_target_os_from_string(String str, Subtarget *subtar
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (subtarget_) *subtarget_ = Subtarget_Default;
|
||||
|
||||
if (subtarget.len != 0) {
|
||||
if (str_eq_ignore_case(subtarget, "generic") || str_eq_ignore_case(subtarget, "default")) {
|
||||
if (subtarget_) *subtarget_ = Subtarget_Default;
|
||||
} else {
|
||||
for (isize i = 1; i < Subtarget_COUNT; i++) {
|
||||
if (str_eq_ignore_case(subtarget_strings[i], subtarget)) {
|
||||
if (subtarget_) *subtarget_ = cast(Subtarget)i;
|
||||
break;
|
||||
if (subtarget_str) *subtarget_str = subtarget;
|
||||
|
||||
if (subtarget_) {
|
||||
if (subtarget.len != 0) {
|
||||
*subtarget_ = Subtarget_Invalid;
|
||||
|
||||
if (str_eq_ignore_case(subtarget, "generic") || str_eq_ignore_case(subtarget, "default")) {
|
||||
*subtarget_ = Subtarget_Default;
|
||||
|
||||
} else {
|
||||
for (isize i = 1; i < Subtarget_COUNT; i++) {
|
||||
if (str_eq_ignore_case(subtarget_strings[i], subtarget)) {
|
||||
*subtarget_ = cast(Subtarget)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*subtarget_ = Subtarget_Default;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1824,16 +1838,29 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
|
||||
}
|
||||
}
|
||||
|
||||
if (metrics->os == TargetOs_darwin && subtarget == Subtarget_iOS) {
|
||||
switch (metrics->arch) {
|
||||
case TargetArch_arm64:
|
||||
bc->metrics.target_triplet = str_lit("arm64-apple-ios");
|
||||
break;
|
||||
case TargetArch_amd64:
|
||||
bc->metrics.target_triplet = str_lit("x86_64-apple-ios");
|
||||
break;
|
||||
default:
|
||||
GB_PANIC("Unknown architecture for darwin");
|
||||
if (metrics->os == TargetOs_darwin) {
|
||||
switch (subtarget) {
|
||||
case Subtarget_iPhone:
|
||||
switch (metrics->arch) {
|
||||
case TargetArch_arm64:
|
||||
bc->metrics.target_triplet = str_lit("arm64-apple-ios");
|
||||
break;
|
||||
default:
|
||||
GB_PANIC("Unknown architecture for -subtarget:iphone");
|
||||
}
|
||||
break;
|
||||
case Subtarget_iPhoneSimulator:
|
||||
switch (metrics->arch) {
|
||||
case TargetArch_arm64:
|
||||
bc->metrics.target_triplet = str_lit("arm64-apple-ios-simulator");
|
||||
break;
|
||||
case TargetArch_amd64:
|
||||
bc->metrics.target_triplet = str_lit("x86_64-apple-ios-simulator");
|
||||
break;
|
||||
default:
|
||||
GB_PANIC("Unknown architecture for -subtarget:iphonesimulator");
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (metrics->os == TargetOs_linux && subtarget == Subtarget_Android) {
|
||||
switch (metrics->arch) {
|
||||
@@ -1892,10 +1919,23 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
|
||||
// does not annoy the user with version warnings.
|
||||
if (metrics->os == TargetOs_darwin) {
|
||||
if (!bc->minimum_os_version_string_given) {
|
||||
bc->minimum_os_version_string = str_lit("11.0.0");
|
||||
if (subtarget == Subtarget_Default) {
|
||||
bc->minimum_os_version_string = str_lit("11.0.0");
|
||||
} else if (subtarget == Subtarget_iPhone || subtarget == Subtarget_iPhoneSimulator) {
|
||||
// NOTE(harold): We default to 17.4 on iOS because that's when os_sync_wait_on_address was added and
|
||||
// we'd like to avoid any potential App Store issues by using the private ulock_* there.
|
||||
bc->minimum_os_version_string = str_lit("17.4");
|
||||
}
|
||||
}
|
||||
|
||||
if (subtarget == Subtarget_Default) {
|
||||
if (subtarget == Subtarget_iPhoneSimulator) {
|
||||
// For the iPhoneSimulator subtarget, the version must be between 'ios' and '-simulator'.
|
||||
String suffix = str_lit("-simulator");
|
||||
GB_ASSERT(string_ends_with(bc->metrics.target_triplet, suffix));
|
||||
|
||||
String prefix = substring(bc->metrics.target_triplet, 0, bc->metrics.target_triplet.len - suffix.len);
|
||||
bc->metrics.target_triplet = concatenate3_strings(permanent_allocator(), prefix, bc->minimum_os_version_string, suffix);
|
||||
} else {
|
||||
bc->metrics.target_triplet = concatenate_strings(permanent_allocator(), bc->metrics.target_triplet, bc->minimum_os_version_string);
|
||||
}
|
||||
} else if (selected_subtarget == Subtarget_Android) {
|
||||
|
||||
+110
-1
@@ -1,5 +1,14 @@
|
||||
typedef bool (BuiltinTypeIsProc)(Type *t);
|
||||
|
||||
gb_internal int enum_constant_entity_cmp(void const* a, void const* b) {
|
||||
Entity const *ea = *(cast(Entity const **)a);
|
||||
Entity const *eb = *(cast(Entity const **)b);
|
||||
GB_ASSERT(ea->kind == Entity_Constant && eb->kind == Entity_Constant);
|
||||
GB_ASSERT(ea->Constant.value.kind == ExactValue_Integer && eb->Constant.value.kind == ExactValue_Integer);
|
||||
|
||||
return big_int_cmp(&ea->Constant.value.value_integer, &eb->Constant.value.value_integer);
|
||||
}
|
||||
|
||||
gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_boolean_end - BuiltinProc__type_simple_boolean_begin] = {
|
||||
nullptr, // BuiltinProc__type_simple_boolean_begin
|
||||
|
||||
@@ -1150,6 +1159,58 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan
|
||||
return true;
|
||||
}
|
||||
|
||||
case BuiltinProc_simd_runtime_swizzle:
|
||||
{
|
||||
if (ce->args.count != 2) {
|
||||
error(call, "'%.*s' expected 2 arguments, got %td", LIT(builtin_name), ce->args.count);
|
||||
return false;
|
||||
}
|
||||
|
||||
Operand src = {};
|
||||
Operand indices = {};
|
||||
check_expr(c, &src, ce->args[0]); if (src.mode == Addressing_Invalid) return false;
|
||||
check_expr_with_type_hint(c, &indices, ce->args[1], src.type); if (indices.mode == Addressing_Invalid) return false;
|
||||
|
||||
if (!is_type_simd_vector(src.type)) {
|
||||
error(src.expr, "'%.*s' expected first argument to be a simd vector", LIT(builtin_name));
|
||||
return false;
|
||||
}
|
||||
if (!is_type_simd_vector(indices.type)) {
|
||||
error(indices.expr, "'%.*s' expected second argument (indices) to be a simd vector", LIT(builtin_name));
|
||||
return false;
|
||||
}
|
||||
|
||||
Type *src_elem = base_array_type(src.type);
|
||||
Type *indices_elem = base_array_type(indices.type);
|
||||
|
||||
if (!is_type_integer(src_elem)) {
|
||||
gbString src_str = type_to_string(src.type);
|
||||
error(src.expr, "'%.*s' expected first argument to be a simd vector of integers, got '%s'", LIT(builtin_name), src_str);
|
||||
gb_string_free(src_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_type_integer(indices_elem)) {
|
||||
gbString indices_str = type_to_string(indices.type);
|
||||
error(indices.expr, "'%.*s' expected indices to be a simd vector of integers, got '%s'", LIT(builtin_name), indices_str);
|
||||
gb_string_free(indices_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!are_types_identical(src.type, indices.type)) {
|
||||
gbString src_str = type_to_string(src.type);
|
||||
gbString indices_str = type_to_string(indices.type);
|
||||
error(indices.expr, "'%.*s' expected both arguments to have the same type, got '%s' vs '%s'", LIT(builtin_name), src_str, indices_str);
|
||||
gb_string_free(indices_str);
|
||||
gb_string_free(src_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = src.type;
|
||||
return true;
|
||||
}
|
||||
|
||||
case BuiltinProc_simd_ceil:
|
||||
case BuiltinProc_simd_floor:
|
||||
case BuiltinProc_simd_trunc:
|
||||
@@ -2324,7 +2385,11 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
|
||||
if (mode == Addressing_Invalid) {
|
||||
gbString t = type_to_string(operand->type);
|
||||
error(call, "'%.*s' is not supported for '%s'", LIT(builtin_name), t);
|
||||
if (is_type_bit_set(op_type) && id == BuiltinProc_len) {
|
||||
error(call, "'%.*s' is not supported for '%s', did you mean 'card'?", LIT(builtin_name), t);
|
||||
} else {
|
||||
error(call, "'%.*s' is not supported for '%s'", LIT(builtin_name), t);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -6919,6 +6984,50 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_type_enum_is_contiguous:
|
||||
{
|
||||
Operand op = {};
|
||||
Type *bt = check_type(c, ce->args[0]);
|
||||
Type *type = base_type(bt);
|
||||
if (type == nullptr || type == t_invalid) {
|
||||
error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name));
|
||||
return false;
|
||||
}
|
||||
if (!is_type_enum(type)) {
|
||||
gbString t = type_to_string(type);
|
||||
error(ce->args[0], "Expected an enum type for '%.*s', got %s", LIT(builtin_name), t);
|
||||
gb_string_free(t);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto enum_constants = array_make<Entity *>(temporary_allocator(), type->Enum.fields.count);
|
||||
array_copy(&enum_constants, type->Enum.fields, 0);
|
||||
array_sort(enum_constants, enum_constant_entity_cmp);
|
||||
|
||||
BigInt minus_one = big_int_make_i64(-1);
|
||||
defer (big_int_dealloc(&minus_one));
|
||||
BigInt diff = {};
|
||||
|
||||
bool contiguous = true;
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->type = t_untyped_bool;
|
||||
|
||||
for (isize i = 0; i < enum_constants.count - 1; i++) {
|
||||
BigInt curr = enum_constants[i]->Constant.value.value_integer;
|
||||
BigInt next = enum_constants[i + 1]->Constant.value.value_integer;
|
||||
big_int_sub(&diff, &curr, &next);
|
||||
defer (big_int_dealloc(&diff));
|
||||
|
||||
if (!big_int_is_zero(&diff) && big_int_cmp(&diff, &minus_one) != 0) {
|
||||
contiguous = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
operand->value = exact_value_bool(contiguous);
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_type_equal_proc:
|
||||
{
|
||||
Operand op = {};
|
||||
|
||||
+107
-99
@@ -1001,119 +1001,127 @@ gb_internal String handle_link_name(CheckerContext *ctx, Token token, String lin
|
||||
|
||||
|
||||
gb_internal void check_objc_methods(CheckerContext *ctx, Entity *e, AttributeContext &ac) {
|
||||
if (!(ac.objc_name.len || ac.objc_is_class_method || ac.objc_type)) {
|
||||
if (!ac.objc_type) {
|
||||
return;
|
||||
}
|
||||
if (ac.objc_name.len == 0 && ac.objc_is_class_method) {
|
||||
error(e->token, "@(objc_name) is required with @(objc_is_class_method)");
|
||||
} else if (ac.objc_type == nullptr) {
|
||||
error(e->token, "@(objc_name) requires that @(objc_type) to be set");
|
||||
} else if (ac.objc_name.len == 0 && ac.objc_type) {
|
||||
error(e->token, "@(objc_name) is required with @(objc_type)");
|
||||
} else {
|
||||
Type *t = ac.objc_type;
|
||||
|
||||
GB_ASSERT(t->kind == Type_Named); // NOTE(harold): This is already checked for at the attribute resolution stage.
|
||||
Entity *tn = t->Named.type_name;
|
||||
Type *t = ac.objc_type;
|
||||
GB_ASSERT(t->kind == Type_Named); // NOTE(harold): This is already checked for at the attribute resolution stage.
|
||||
|
||||
GB_ASSERT(tn->kind == Entity_TypeName);
|
||||
// Attempt to infer th objc_name automatically if the proc name contains
|
||||
// the type name objc_type's name, followed by an underscore, as a prefix.
|
||||
if (ac.objc_name.len == 0) {
|
||||
String proc_name = e->token.string;
|
||||
String type_name = t->Named.name;
|
||||
|
||||
if (tn->scope != e->scope) {
|
||||
error(e->token, "@(objc_name) attribute may only be applied to procedures and types within the same scope");
|
||||
if (proc_name.len > type_name.len + 1 &&
|
||||
proc_name[type_name.len] == '_' &&
|
||||
str_eq(type_name, substring(proc_name, 0, type_name.len))
|
||||
) {
|
||||
ac.objc_name = substring(proc_name, type_name.len+1, proc_name.len);
|
||||
} else {
|
||||
error(e->token, "@(objc_name) requires that @(objc_type) be set or inferred "
|
||||
"by prefixing the proc name with the type and underscore: MyObjcType_myProcName :: proc().");
|
||||
}
|
||||
}
|
||||
|
||||
// Enable implementation by default if the class is an implementer too and
|
||||
// @objc_implement was not set to false explicitly in this proc.
|
||||
bool implement = tn->TypeName.objc_is_implementation;
|
||||
if (ac.objc_is_disabled_implement) {
|
||||
implement = false;
|
||||
}
|
||||
Entity *tn = t->Named.type_name;
|
||||
GB_ASSERT(tn->kind == Entity_TypeName);
|
||||
|
||||
if (implement) {
|
||||
GB_ASSERT(e->kind == Entity_Procedure);
|
||||
if (tn->scope != e->scope) {
|
||||
error(e->token, "@(objc_name) attribute may only be applied to procedures and types within the same scope");
|
||||
} else {
|
||||
// Enable implementation by default if the class is an implementer too and
|
||||
// @objc_implement was not set to false explicitly in this proc.
|
||||
bool implement = tn->TypeName.objc_is_implementation;
|
||||
if (ac.objc_is_disabled_implement) {
|
||||
implement = false;
|
||||
}
|
||||
|
||||
auto &proc = e->type->Proc;
|
||||
Type *first_param = proc.param_count > 0 ? proc.params->Tuple.variables[0]->type : t_untyped_nil;
|
||||
if (implement) {
|
||||
GB_ASSERT(e->kind == Entity_Procedure);
|
||||
|
||||
if (!tn->TypeName.objc_is_implementation) {
|
||||
error(e->token, "@(objc_is_implement) attribute may only be applied to procedures whose class also have @(objc_is_implement) applied");
|
||||
} else if (!ac.objc_is_class_method && !(first_param->kind == Type_Pointer && internal_check_is_assignable_to(t, first_param->Pointer.elem))) {
|
||||
error(e->token, "Objective-C instance methods implementations require the first parameter to be a pointer to the class type set by @(objc_type)");
|
||||
} else if (proc.calling_convention == ProcCC_Odin && !tn->TypeName.objc_context_provider) {
|
||||
error(e->token, "Objective-C methods with Odin calling convention can only be used with classes that have @(objc_context_provider) set");
|
||||
} else if (ac.objc_is_class_method && proc.calling_convention != ProcCC_CDecl) {
|
||||
error(e->token, "Objective-C class methods (objc_is_class_method=true) that have @objc_is_implementation can only use \"c\" calling convention");
|
||||
} else if (proc.result_count > 1) {
|
||||
error(e->token, "Objective-C method implementations may return at most 1 value");
|
||||
} else {
|
||||
// Always export unconditionally
|
||||
// NOTE(harold): This means check_objc_methods() MUST be called before
|
||||
// e->Procedure.is_export is set in check_proc_decl()!
|
||||
if (ac.is_export) {
|
||||
error(e->token, "Explicit export not allowed when @(objc_implement) is set. It set exported implicitly");
|
||||
}
|
||||
if (ac.link_name != "") {
|
||||
error(e->token, "Explicit linkage not allowed when @(objc_implement) is set. It set to \"strong\" implicitly");
|
||||
}
|
||||
auto &proc = e->type->Proc;
|
||||
Type *first_param = proc.param_count > 0 ? proc.params->Tuple.variables[0]->type : t_untyped_nil;
|
||||
|
||||
ac.is_export = true;
|
||||
ac.linkage = STR_LIT("strong");
|
||||
|
||||
auto method = ObjcMethodData{ ac, e };
|
||||
method.ac.objc_selector = ac.objc_selector != "" ? ac.objc_selector : ac.objc_name;
|
||||
|
||||
CheckerInfo *info = ctx->info;
|
||||
mutex_lock(&info->objc_method_mutex);
|
||||
defer (mutex_unlock(&info->objc_method_mutex));
|
||||
|
||||
Array<ObjcMethodData>* method_list = map_get(&info->objc_method_implementations, t);
|
||||
if (method_list) {
|
||||
array_add(method_list, method);
|
||||
} else {
|
||||
auto list = array_make<ObjcMethodData>(permanent_allocator(), 1, 8);
|
||||
list[0] = method;
|
||||
|
||||
map_set(&info->objc_method_implementations, t, list);
|
||||
}
|
||||
}
|
||||
} else if (ac.objc_selector != "") {
|
||||
error(e->token, "@(objc_selector) may only be applied to procedures that are Objective-C implementations.");
|
||||
}
|
||||
|
||||
mutex_lock(&global_type_name_objc_metadata_mutex);
|
||||
defer (mutex_unlock(&global_type_name_objc_metadata_mutex));
|
||||
|
||||
if (!tn->TypeName.objc_metadata) {
|
||||
tn->TypeName.objc_metadata = create_type_name_obj_c_metadata();
|
||||
}
|
||||
auto *md = tn->TypeName.objc_metadata;
|
||||
mutex_lock(md->mutex);
|
||||
defer (mutex_unlock(md->mutex));
|
||||
|
||||
if (!ac.objc_is_class_method) {
|
||||
bool ok = true;
|
||||
for (TypeNameObjCMetadataEntry const &entry : md->value_entries) {
|
||||
if (entry.name == ac.objc_name) {
|
||||
error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name));
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
array_add(&md->value_entries, TypeNameObjCMetadataEntry{ac.objc_name, e});
|
||||
}
|
||||
if (!tn->TypeName.objc_is_implementation) {
|
||||
error(e->token, "@(objc_is_implement) attribute may only be applied to procedures whose class also have @(objc_is_implement) applied");
|
||||
} else if (!ac.objc_is_class_method && !(first_param->kind == Type_Pointer && internal_check_is_assignable_to(t, first_param->Pointer.elem))) {
|
||||
error(e->token, "Objective-C instance methods implementations require the first parameter to be a pointer to the class type set by @(objc_type)");
|
||||
} else if (proc.calling_convention == ProcCC_Odin && !tn->TypeName.objc_context_provider) {
|
||||
error(e->token, "Objective-C methods with Odin calling convention can only be used with classes that have @(objc_context_provider) set");
|
||||
} else if (ac.objc_is_class_method && proc.calling_convention != ProcCC_CDecl) {
|
||||
error(e->token, "Objective-C class methods (objc_is_class_method=true) that have @objc_is_implementation can only use \"c\" calling convention");
|
||||
} else if (proc.result_count > 1) {
|
||||
error(e->token, "Objective-C method implementations may return at most 1 value");
|
||||
} else {
|
||||
bool ok = true;
|
||||
for (TypeNameObjCMetadataEntry const &entry : md->type_entries) {
|
||||
if (entry.name == ac.objc_name) {
|
||||
error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name));
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
// Always export unconditionally
|
||||
// NOTE(harold): This means check_objc_methods() MUST be called before
|
||||
// e->Procedure.is_export is set in check_proc_decl()!
|
||||
if (ac.is_export) {
|
||||
error(e->token, "Explicit export not allowed when @(objc_implement) is set. It set exported implicitly");
|
||||
}
|
||||
if (ok) {
|
||||
array_add(&md->type_entries, TypeNameObjCMetadataEntry{ac.objc_name, e});
|
||||
if (ac.link_name != "") {
|
||||
error(e->token, "Explicit linkage not allowed when @(objc_implement) is set. It set to \"strong\" implicitly");
|
||||
}
|
||||
|
||||
ac.is_export = true;
|
||||
ac.linkage = STR_LIT("strong");
|
||||
|
||||
auto method = ObjcMethodData{ ac, e };
|
||||
method.ac.objc_selector = ac.objc_selector != "" ? ac.objc_selector : ac.objc_name;
|
||||
|
||||
CheckerInfo *info = ctx->info;
|
||||
mutex_lock(&info->objc_method_mutex);
|
||||
defer (mutex_unlock(&info->objc_method_mutex));
|
||||
|
||||
Array<ObjcMethodData>* method_list = map_get(&info->objc_method_implementations, t);
|
||||
if (method_list) {
|
||||
array_add(method_list, method);
|
||||
} else {
|
||||
auto list = array_make<ObjcMethodData>(permanent_allocator(), 1, 8);
|
||||
list[0] = method;
|
||||
|
||||
map_set(&info->objc_method_implementations, t, list);
|
||||
}
|
||||
}
|
||||
} else if (ac.objc_selector != "") {
|
||||
error(e->token, "@(objc_selector) may only be applied to procedures that are Objective-C implementations.");
|
||||
}
|
||||
|
||||
mutex_lock(&global_type_name_objc_metadata_mutex);
|
||||
defer (mutex_unlock(&global_type_name_objc_metadata_mutex));
|
||||
|
||||
if (!tn->TypeName.objc_metadata) {
|
||||
tn->TypeName.objc_metadata = create_type_name_obj_c_metadata();
|
||||
}
|
||||
auto *md = tn->TypeName.objc_metadata;
|
||||
mutex_lock(md->mutex);
|
||||
defer (mutex_unlock(md->mutex));
|
||||
|
||||
if (!ac.objc_is_class_method) {
|
||||
bool ok = true;
|
||||
for (TypeNameObjCMetadataEntry const &entry : md->value_entries) {
|
||||
if (entry.name == ac.objc_name) {
|
||||
error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name));
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
array_add(&md->value_entries, TypeNameObjCMetadataEntry{ac.objc_name, e});
|
||||
}
|
||||
} else {
|
||||
bool ok = true;
|
||||
for (TypeNameObjCMetadataEntry const &entry : md->type_entries) {
|
||||
if (entry.name == ac.objc_name) {
|
||||
error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name));
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
array_add(&md->type_entries, TypeNameObjCMetadataEntry{ac.objc_name, e});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+70
-51
@@ -6245,20 +6245,43 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A
|
||||
for (isize i = 0; i < pt->param_count; i++) {
|
||||
if (!visited[i]) {
|
||||
Entity *e = pt->params->Tuple.variables[i];
|
||||
bool context_allocator_error = false;
|
||||
if (e->kind == Entity_Variable) {
|
||||
if (e->Variable.param_value.kind != ParameterValue_Invalid) {
|
||||
ordered_operands[i].mode = Addressing_Value;
|
||||
ordered_operands[i].type = e->type;
|
||||
ordered_operands[i].expr = e->Variable.param_value.original_ast_expr;
|
||||
if (ast_file_vet_explicit_allocators(c->file)) {
|
||||
// NOTE(lucas): check if we are trying to default to context.allocator or context.temp_allocator
|
||||
if (e->Variable.param_value.original_ast_expr->kind == Ast_SelectorExpr) {
|
||||
auto& expr = e->Variable.param_value.original_ast_expr->SelectorExpr.expr;
|
||||
auto& selector = e->Variable.param_value.original_ast_expr->SelectorExpr.selector;
|
||||
if (expr->kind == Ast_Implicit &&
|
||||
expr->Implicit.string == STR_LIT("context") &&
|
||||
selector->kind == Ast_Ident &&
|
||||
(selector->Ident.token.string == STR_LIT("allocator") ||
|
||||
selector->Ident.token.string == STR_LIT("temp_allocator"))) {
|
||||
context_allocator_error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dummy_argument_count += 1;
|
||||
score += assign_score_function(1);
|
||||
continue;
|
||||
if (!context_allocator_error) {
|
||||
ordered_operands[i].mode = Addressing_Value;
|
||||
ordered_operands[i].type = e->type;
|
||||
ordered_operands[i].expr = e->Variable.param_value.original_ast_expr;
|
||||
|
||||
dummy_argument_count += 1;
|
||||
score += assign_score_function(1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (show_error) {
|
||||
if (e->kind == Entity_TypeName) {
|
||||
if (context_allocator_error) {
|
||||
gbString str = type_to_string(e->type);
|
||||
error(call, "Parameter '%.*s' of type '%s' must be explicitly provided in procedure call",
|
||||
LIT(e->token.string), str);
|
||||
gb_string_free(str);
|
||||
} else if (e->kind == Entity_TypeName) {
|
||||
error(call, "Type parameter '%.*s' is missing in procedure call",
|
||||
LIT(e->token.string));
|
||||
} else if (e->kind == Entity_Constant && e->Constant.value.kind != ExactValue_Invalid) {
|
||||
@@ -10312,52 +10335,48 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
|
||||
is_constant = false;
|
||||
}
|
||||
|
||||
if (cl->elems[0]->kind == Ast_FieldValue) {
|
||||
error(cl->elems[0], "'field = value' in a bit_set a literal is not allowed");
|
||||
is_constant = false;
|
||||
} else {
|
||||
for (Ast *elem : cl->elems) {
|
||||
if (elem->kind == Ast_FieldValue) {
|
||||
error(elem, "'field = value' in a bit_set a literal is not allowed");
|
||||
for (Ast *elem : cl->elems) {
|
||||
if (elem->kind == Ast_FieldValue) {
|
||||
error(elem, "'field = value' in a bit_set literal is not allowed");
|
||||
is_constant = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
check_expr_with_type_hint(c, o, elem, et);
|
||||
|
||||
if (is_constant) {
|
||||
is_constant = o->mode == Addressing_Constant;
|
||||
}
|
||||
|
||||
if (elem->kind == Ast_BinaryExpr) {
|
||||
switch (elem->BinaryExpr.op.kind) {
|
||||
case Token_Or:
|
||||
{
|
||||
gbString x = expr_to_string(elem->BinaryExpr.left);
|
||||
gbString y = expr_to_string(elem->BinaryExpr.right);
|
||||
gbString e = expr_to_string(elem);
|
||||
error(elem, "Was the following intended? '%s, %s'; if not, surround the expression with parentheses '(%s)'", x, y, e);
|
||||
gb_string_free(e);
|
||||
gb_string_free(y);
|
||||
gb_string_free(x);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
check_assignment(c, o, t->BitSet.elem, str_lit("bit_set literal"));
|
||||
if (o->mode == Addressing_Constant) {
|
||||
i64 lower = t->BitSet.lower;
|
||||
i64 upper = t->BitSet.upper;
|
||||
i64 v = exact_value_to_i64(o->value);
|
||||
if (lower <= v && v <= upper) {
|
||||
// okay
|
||||
} else {
|
||||
gbString s = expr_to_string(o->expr);
|
||||
error(elem, "Bit field value out of bounds, %s (%lld) not in the range %lld .. %lld", s, v, lower, upper);
|
||||
gb_string_free(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
check_expr_with_type_hint(c, o, elem, et);
|
||||
|
||||
if (is_constant) {
|
||||
is_constant = o->mode == Addressing_Constant;
|
||||
}
|
||||
|
||||
if (elem->kind == Ast_BinaryExpr) {
|
||||
switch (elem->BinaryExpr.op.kind) {
|
||||
case Token_Or:
|
||||
{
|
||||
gbString x = expr_to_string(elem->BinaryExpr.left);
|
||||
gbString y = expr_to_string(elem->BinaryExpr.right);
|
||||
gbString e = expr_to_string(elem);
|
||||
error(elem, "Was the following intended? '%s, %s'; if not, surround the expression with parentheses '(%s)'", x, y, e);
|
||||
gb_string_free(e);
|
||||
gb_string_free(y);
|
||||
gb_string_free(x);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
check_assignment(c, o, t->BitSet.elem, str_lit("bit_set literal"));
|
||||
if (o->mode == Addressing_Constant) {
|
||||
i64 lower = t->BitSet.lower;
|
||||
i64 upper = t->BitSet.upper;
|
||||
i64 v = exact_value_to_i64(o->value);
|
||||
if (lower <= v && v <= upper) {
|
||||
// okay
|
||||
} else {
|
||||
gbString s = expr_to_string(o->expr);
|
||||
error(elem, "Bit field value out of bounds, %s (%lld) not in the range %lld .. %lld", s, v, lower, upper);
|
||||
gb_string_free(s);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2778,6 +2778,10 @@ gb_internal void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags)
|
||||
Ast *stmt = ds->stmt;
|
||||
Ast *original_stmt = stmt;
|
||||
|
||||
if (stmt->kind == Ast_BlockStmt && stmt->BlockStmt.stmts.count == 0) {
|
||||
break; // empty defer statement
|
||||
}
|
||||
|
||||
bool is_singular = true;
|
||||
while (is_singular && stmt->kind == Ast_BlockStmt) {
|
||||
Ast *inner_stmt = nullptr;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user