mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-14 09:44:26 +00:00
Merge branch 'master' into poly
This commit is contained in:
@@ -1032,9 +1032,9 @@ quo_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {
|
||||
invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3)
|
||||
|
||||
t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2
|
||||
t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2
|
||||
t1 := (r0*q1 - r1*q0 + r2*q3 - r3*q2) * invmag2
|
||||
t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2
|
||||
t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2
|
||||
t3 := (r0*q3 + r1*q2 - r2*q1 - r3*q0) * invmag2
|
||||
|
||||
return quaternion(w=f16(t0), x=f16(t1), y=f16(t2), z=f16(t3))
|
||||
}
|
||||
@@ -1046,9 +1046,9 @@ quo_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {
|
||||
invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3)
|
||||
|
||||
t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2
|
||||
t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2
|
||||
t1 := (r0*q1 - r1*q0 + r2*q3 - r3*q2) * invmag2
|
||||
t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2
|
||||
t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2
|
||||
t3 := (r0*q3 + r1*q2 - r2*q1 - r3*q0) * invmag2
|
||||
|
||||
return quaternion(w=t0, x=t1, y=t2, z=t3)
|
||||
}
|
||||
@@ -1060,9 +1060,9 @@ quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {
|
||||
invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3)
|
||||
|
||||
t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2
|
||||
t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2
|
||||
t1 := (r0*q1 - r1*q0 + r2*q3 - r3*q2) * invmag2
|
||||
t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2
|
||||
t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2
|
||||
t3 := (r0*q3 + r1*q2 - r2*q1 - r3*q0) * invmag2
|
||||
|
||||
return quaternion(w=t0, x=t1, y=t2, z=t3)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ chacha8rand_refill_ref :: proc(r: ^Default_Random_State) {
|
||||
s8 := intrinsics.byte_swap(k[4])
|
||||
s9 := intrinsics.byte_swap(k[5])
|
||||
s10 := intrinsics.byte_swap(k[6])
|
||||
s11 := intrinicss.byte_swap(k[7])
|
||||
s11 := intrinsics.byte_swap(k[7])
|
||||
}
|
||||
s12: u32 // Counter starts at 0.
|
||||
s13, s14, s15: u32 // IV of all 0s.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package _chacha20
|
||||
|
||||
import "base:intrinsics"
|
||||
import "core:crypto"
|
||||
import "core:encoding/endian"
|
||||
import "core:math/bits"
|
||||
@@ -108,11 +109,16 @@ check_counter_limit :: proc(ctx: ^Context, nr_blocks: int) {
|
||||
|
||||
ctr_ok: bool
|
||||
if ctx._is_ietf_flavor {
|
||||
ctr_ok = u64(ctx._s[12]) + u64(nr_blocks) <= MAX_CTR_IETF
|
||||
if intrinsics.unlikely(ctx._s[12] == MAX_CTR_IETF && nr_blocks > 1) {
|
||||
// Allow the final block.
|
||||
ctr_ok = false
|
||||
} else {
|
||||
ctr_ok = u64(ctx._s[12]) + u64(nr_blocks) <= MAX_CTR_IETF
|
||||
}
|
||||
} else {
|
||||
ctr := (u64(ctx._s[13]) << 32) | u64(ctx._s[12])
|
||||
_, carry := bits.add_u64(ctr, u64(nr_blocks), 0)
|
||||
ctr_ok = carry == 0
|
||||
new_ctr, carry := bits.add_u64(ctr, u64(nr_blocks), 0)
|
||||
ctr_ok = carry == 0 || new_ctr != 0 // Allow the final block.
|
||||
}
|
||||
|
||||
ensure(ctr_ok, "crypto/chacha20: maximum (X)ChaCha20 keystream per IV reached")
|
||||
|
||||
@@ -35,6 +35,10 @@ sum :: proc(sec_strength: int, dst, msg, key, domain_sep: []byte) {
|
||||
// strength, key and domain separator over msg and return true if and only if (⟺) the
|
||||
// tag is valid.
|
||||
verify :: proc(sec_strength: int, tag, msg, key, domain_sep: []byte, allocator := context.temp_allocator) -> bool {
|
||||
if len(tag) < MIN_TAG_SIZE {
|
||||
return false
|
||||
}
|
||||
|
||||
derived_tag := make([]byte, len(tag), allocator)
|
||||
defer(delete(derived_tag))
|
||||
|
||||
|
||||
@@ -269,7 +269,7 @@ params :: proc(k: ^$T) -> Parameters where (T == Encapsulation_Key || T == Decap
|
||||
@(require_results)
|
||||
key_size :: proc(k: ^$T) -> int where (T == Encapsulation_Key || T == Decapsulation_Key) {
|
||||
when T == Encapsulation_Key {
|
||||
return ENCAPSULATION_KEY_SIZES[k.pke_ek.k]
|
||||
return ENCAPSULATION_KEY_SIZES[params(k)]
|
||||
} else {
|
||||
return DECAPSULATION_KEY_SEED_SIZE
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ cipherstate_encrypt_with_ad :: proc(self: ^Cipher_State, ad, plaintext, dst: []b
|
||||
}
|
||||
_encrypt(&self.ctx, self.n, ad, plaintext, dst)
|
||||
self.n += 1
|
||||
if self.n == 0 {
|
||||
if self.n == max(u64) {
|
||||
self.n_exhausted = true
|
||||
}
|
||||
} else {
|
||||
@@ -249,7 +249,7 @@ cipherstate_decrypt_with_ad :: proc(self: ^Cipher_State, ad, ciphertext, dst: []
|
||||
return nil, status
|
||||
}
|
||||
self.n += 1
|
||||
if self.n == 0 {
|
||||
if self.n == max(u64) {
|
||||
self.n_exhausted = true
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -19,6 +19,8 @@ derive :: proc(
|
||||
iterations: u32,
|
||||
dst: []byte,
|
||||
) {
|
||||
ensure(iterations > 0, "crypto/pbkdf2: non-zero iterations required")
|
||||
|
||||
h_len := hash.DIGEST_SIZES[hmac_hash]
|
||||
|
||||
// 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long"
|
||||
|
||||
@@ -19,7 +19,6 @@ package net
|
||||
*/
|
||||
|
||||
import "core:strings"
|
||||
import "core:strconv"
|
||||
import "core:unicode/utf8"
|
||||
import "core:encoding/hex"
|
||||
|
||||
@@ -114,6 +113,8 @@ join_url :: proc(scheme, host, path: string, queries: map[string]string, fragmen
|
||||
}
|
||||
|
||||
percent_encode :: proc(s: string, allocator := context.allocator) -> string {
|
||||
HEX_DIGITS_UPPER := "0123456789ABCDEF" // NOTE(michtesar): RFC 3986 §2.1
|
||||
|
||||
b := strings.builder_make(allocator)
|
||||
strings.builder_grow(&b, len(s) + 16) // NOTE(tetra): A reasonable number to allow for the number of things we need to escape.
|
||||
|
||||
@@ -124,10 +125,9 @@ percent_encode :: proc(s: string, allocator := context.allocator) -> string {
|
||||
case:
|
||||
bytes, n := utf8.encode_rune(ch)
|
||||
for byte in bytes[:n] {
|
||||
buf: [2]u8 = ---
|
||||
t := strconv.write_int(buf[:], i64(byte), 16)
|
||||
strings.write_rune(&b, '%')
|
||||
strings.write_string(&b, t)
|
||||
strings.write_byte(&b, '%')
|
||||
strings.write_byte(&b, HEX_DIGITS_UPPER[byte >> 4])
|
||||
strings.write_byte(&b, HEX_DIGITS_UPPER[byte & 0xF])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,13 @@ _remove_all :: proc(path: string) -> Error {
|
||||
}
|
||||
|
||||
temp_allocator := TEMP_ALLOCATOR_GUARD({})
|
||||
dir := win32_utf8_to_wstring(path, temp_allocator) or_return
|
||||
|
||||
// SHFileOperationW is documented as not thread safe with relative paths.
|
||||
abs_path := path
|
||||
if !_is_absolute_path(path) {
|
||||
abs_path = _get_absolute_path(path, temp_allocator) or_return
|
||||
}
|
||||
dir := win32_utf8_to_wstring(abs_path, temp_allocator) or_return
|
||||
|
||||
empty: [1]u16
|
||||
|
||||
|
||||
596
core/simd/arm/neon.odin
Normal file
596
core/simd/arm/neon.odin
Normal file
@@ -0,0 +1,596 @@
|
||||
#+build arm64,arm32
|
||||
package simd_arm
|
||||
|
||||
import "core:simd"
|
||||
|
||||
// Count leading sign bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcls_s8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vcls_s8 :: #force_inline proc "c" (a: int8x8_t) -> int8x8_t {
|
||||
return _vcls_s8(a)
|
||||
}
|
||||
|
||||
// Count leading sign bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcls_s16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vcls_s16 :: #force_inline proc "c" (a: int16x4_t) -> int16x4_t {
|
||||
return _vcls_s16(a)
|
||||
}
|
||||
|
||||
// Count leading sign bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcls_s32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vcls_s32 :: #force_inline proc "c" (a: int32x2_t) -> int32x2_t {
|
||||
return _vcls_s32(a)
|
||||
}
|
||||
|
||||
// Count leading sign bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcls_u8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vcls_u8 :: #force_inline proc "c" (a: uint8x8_t) -> int8x8_t {
|
||||
return vcls_s8(transmute(int8x8_t)a)
|
||||
}
|
||||
|
||||
// Count leading sign bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcls_u16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vcls_u16 :: #force_inline proc "c" (a: uint16x4_t) -> int16x4_t {
|
||||
return vcls_s16(transmute(int16x4_t)a)
|
||||
}
|
||||
|
||||
// Count leading sign bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcls_u32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vcls_u32 :: #force_inline proc "c" (a: uint32x2_t) -> int32x2_t {
|
||||
return vcls_s32(transmute(int32x2_t)a)
|
||||
}
|
||||
|
||||
// Count leading sign bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclsq_s8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclsq_s8 :: #force_inline proc "c" (a: int8x16_t) -> int8x16_t {
|
||||
return _vclsq_s8(a)
|
||||
}
|
||||
|
||||
// Count leading sign bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclsq_s16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclsq_s16 :: #force_inline proc "c" (a: int16x8_t) -> int16x8_t {
|
||||
return _vclsq_s16(a)
|
||||
}
|
||||
|
||||
// Count leading sign bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclsq_s32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclsq_s32 :: #force_inline proc "c" (a: int32x4_t) -> int32x4_t {
|
||||
return _vclsq_s32(a)
|
||||
}
|
||||
|
||||
// Count leading sign bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclsq_u8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclsq_u8 :: #force_inline proc "c" (a: uint8x16_t) -> int8x16_t {
|
||||
return vclsq_s8(transmute(int8x16_t)a)
|
||||
}
|
||||
|
||||
// Count leading sign bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclsq_u16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclsq_u16 :: #force_inline proc "c" (a: uint16x8_t) -> int16x8_t {
|
||||
return vclsq_s16(transmute(int16x8_t)a)
|
||||
}
|
||||
|
||||
// Count leading sign bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclsq_u32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclsq_u32 :: #force_inline proc "c" (a: uint32x4_t) -> int32x4_t {
|
||||
return vclsq_s32(transmute(int32x4_t)a)
|
||||
}
|
||||
|
||||
// Count leading zero bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclz_s8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclz_s8 :: #force_inline proc "c" (a: int8x8_t) -> int8x8_t {
|
||||
return simd.count_leading_zeros(a)
|
||||
}
|
||||
|
||||
// Count leading zero bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclz_s16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclz_s16 :: #force_inline proc "c" (a: int16x4_t) -> int16x4_t {
|
||||
return simd.count_leading_zeros(a)
|
||||
}
|
||||
|
||||
// Count leading zero bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclz_s32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclz_s32 :: #force_inline proc "c" (a: int32x2_t) -> int32x2_t {
|
||||
return simd.count_leading_zeros(a)
|
||||
}
|
||||
|
||||
// Count leading zero bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclz_u8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclz_u8 :: #force_inline proc "c" (a: uint8x8_t) -> uint8x8_t {
|
||||
return transmute(uint8x8_t)vclz_s8(transmute(int8x8_t)a)
|
||||
}
|
||||
|
||||
// Count leading zero bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclz_u16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclz_u16 :: #force_inline proc "c" (a: uint16x4_t) -> uint16x4_t {
|
||||
return transmute(uint16x4_t)vclz_s16(transmute(int16x4_t)a)
|
||||
}
|
||||
|
||||
// Count leading zero bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclz_u32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclz_u32 :: #force_inline proc "c" (a: uint32x2_t) -> uint32x2_t {
|
||||
return transmute(uint32x2_t)vclz_s32(transmute(int32x2_t)a)
|
||||
}
|
||||
|
||||
// Count leading zero bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclzq_s8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclzq_s8 :: #force_inline proc "c" (a: int8x16_t) -> int8x16_t {
|
||||
return simd.count_leading_zeros(a)
|
||||
}
|
||||
|
||||
// Count leading zero bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclzq_s16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclzq_s16 :: #force_inline proc "c" (a: int16x8_t) -> int16x8_t {
|
||||
return simd.count_leading_zeros(a)
|
||||
}
|
||||
|
||||
// Count leading zero bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclzq_s32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclzq_s32 :: #force_inline proc "c" (a: int32x4_t) -> int32x4_t {
|
||||
return simd.count_leading_zeros(a)
|
||||
}
|
||||
|
||||
// Count leading zero bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclzq_u8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclzq_u8 :: #force_inline proc "c" (a: uint8x16_t) -> uint8x16_t {
|
||||
return transmute(uint8x16_t)vclzq_s8(transmute(int8x16_t)a)
|
||||
}
|
||||
|
||||
// Count leading zero bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclzq_u16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclzq_u16 :: #force_inline proc "c" (a: uint16x8_t) -> uint16x8_t {
|
||||
return transmute(uint16x8_t)vclzq_s16(transmute(int16x8_t)a)
|
||||
}
|
||||
|
||||
// Count leading zero bits.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vclzq_u32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vclzq_u32 :: #force_inline proc "c" (a: uint32x4_t) -> uint32x4_t {
|
||||
return transmute(uint32x4_t)vclzq_s32(transmute(int32x4_t)a)
|
||||
}
|
||||
|
||||
// Population count per byte.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcnt_s8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vcnt_s8 :: #force_inline proc "c" (a: int8x8_t) -> int8x8_t {
|
||||
return simd.count_ones(a)
|
||||
}
|
||||
|
||||
// Population count per byte.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcnt_u8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vcnt_u8 :: #force_inline proc "c" (a: uint8x8_t) -> uint8x8_t {
|
||||
return transmute(uint8x8_t)vcnt_s8(transmute(int8x8_t)a)
|
||||
}
|
||||
|
||||
// Population count per byte.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcnt_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vcnt_p8 :: #force_inline proc "c" (a: poly8x8_t) -> poly8x8_t {
|
||||
return transmute(poly8x8_t)vcnt_s8(transmute(int8x8_t)a)
|
||||
}
|
||||
|
||||
// Population count per byte.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcntq_s8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vcntq_s8 :: #force_inline proc "c" (a: int8x16_t) -> int8x16_t {
|
||||
return simd.count_ones(a)
|
||||
}
|
||||
|
||||
// Population count per byte.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcntq_u8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vcntq_u8 :: #force_inline proc "c" (a: uint8x16_t) -> uint8x16_t {
|
||||
return transmute(uint8x16_t)vcntq_s8(transmute(int8x16_t)a)
|
||||
}
|
||||
|
||||
// Population count per byte.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcntq_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vcntq_p8 :: #force_inline proc "c" (a: poly8x16_t) -> poly8x16_t {
|
||||
return transmute(poly8x16_t)vcntq_s8(transmute(int8x16_t)a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbic_s8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbic_s8 :: #force_inline proc "c" (a: int8x8_t, b: int8x8_t) -> int8x8_t {
|
||||
c := int8x8_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbic_s16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbic_s16 :: #force_inline proc "c" (a: int16x4_t, b: int16x4_t) -> int16x4_t {
|
||||
c := int16x4_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbic_s32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbic_s32 :: #force_inline proc "c" (a: int32x2_t, b: int32x2_t) -> int32x2_t {
|
||||
c := int32x2_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbic_s64)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbic_s64 :: #force_inline proc "c" (a: int64x1_t, b: int64x1_t) -> int64x1_t {
|
||||
c := int64x1_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbic_u8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbic_u8 :: #force_inline proc "c" (a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
|
||||
c := int8x8_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, transmute(uint8x8_t)c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbic_u16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbic_u16 :: #force_inline proc "c" (a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
|
||||
c := int16x4_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, transmute(uint16x4_t)c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbic_u32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbic_u32 :: #force_inline proc "c" (a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
|
||||
c := int32x2_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, transmute(uint32x2_t)c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbic_u64)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbic_u64 :: #force_inline proc "c" (a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
|
||||
c := int64x1_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, transmute(uint64x1_t)c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbicq_s8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbicq_s8 :: #force_inline proc "c" (a: int8x16_t, b: int8x16_t) -> int8x16_t {
|
||||
c := int8x16_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbicq_s16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbicq_s16 :: #force_inline proc "c" (a: int16x8_t, b: int16x8_t) -> int16x8_t {
|
||||
c := int16x8_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbicq_s32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbicq_s32 :: #force_inline proc "c" (a: int32x4_t, b: int32x4_t) -> int32x4_t {
|
||||
c := int32x4_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbicq_s64)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbicq_s64 :: #force_inline proc "c" (a: int64x2_t, b: int64x2_t) -> int64x2_t {
|
||||
c := int64x2_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbicq_u8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbicq_u8 :: #force_inline proc "c" (a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
|
||||
c := int8x16_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, transmute(uint8x16_t)c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbicq_u16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbicq_u16 :: #force_inline proc "c" (a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
|
||||
c := int16x8_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, transmute(uint16x8_t)c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbicq_u32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbicq_u32 :: #force_inline proc "c" (a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
|
||||
c := int32x4_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, transmute(uint32x4_t)c), a)
|
||||
}
|
||||
|
||||
// Vector bitwise bit clear.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbicq_u64)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbicq_u64 :: #force_inline proc "c" (a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
|
||||
c := int64x2_t(-1)
|
||||
return simd.bit_and(simd.bit_xor(b, transmute(uint64x2_t)c), a)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbsl_s8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbsl_s8 :: #force_inline proc "c" (a: uint8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t {
|
||||
not := int8x8_t(-1)
|
||||
return transmute(int8x8_t)simd.bit_or(
|
||||
simd.bit_and(a, transmute(uint8x8_t)b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint8x8_t)not), transmute(uint8x8_t)c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbsl_s16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbsl_s16 :: #force_inline proc "c" (a: uint16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t {
|
||||
not := int16x4_t(-1)
|
||||
return transmute(int16x4_t)simd.bit_or(
|
||||
simd.bit_and(a, transmute(uint16x4_t)b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint16x4_t)not), transmute(uint16x4_t)c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbsl_s32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbsl_s32 :: #force_inline proc "c" (a: uint32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t {
|
||||
not := int32x2_t(-1)
|
||||
return transmute(int32x2_t)simd.bit_or(
|
||||
simd.bit_and(a, transmute(uint32x2_t)b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint32x2_t)not), transmute(uint32x2_t)c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbsl_s64)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbsl_s64 :: #force_inline proc "c" (a: uint64x1_t, b: int64x1_t, c: int64x1_t) -> int64x1_t {
|
||||
not := int64x1_t(-1)
|
||||
return transmute(int64x1_t)simd.bit_or(
|
||||
simd.bit_and(a, transmute(uint64x1_t)b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint64x1_t)not), transmute(uint64x1_t)c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbsl_u8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbsl_u8 :: #force_inline proc "c" (a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t {
|
||||
not := int8x8_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint8x8_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbsl_u16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbsl_u16 :: #force_inline proc "c" (a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_t {
|
||||
not := int16x4_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint16x4_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbsl_u32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbsl_u32 :: #force_inline proc "c" (a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_t {
|
||||
not := int32x2_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint32x2_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbsl_u64)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbsl_u64 :: #force_inline proc "c" (a: uint64x1_t, b: uint64x1_t, c: uint64x1_t) -> uint64x1_t {
|
||||
not := int64x1_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint64x1_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbslq_s8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbslq_s8 :: #force_inline proc "c" (a: uint8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t {
|
||||
not := int8x16_t(-1)
|
||||
return transmute(int8x16_t)simd.bit_or(
|
||||
simd.bit_and(a, transmute(uint8x16_t)b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint8x16_t)not), transmute(uint8x16_t)c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbslq_s16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbslq_s16 :: #force_inline proc "c" (a: uint16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t {
|
||||
not := int16x8_t(-1)
|
||||
return transmute(int16x8_t)simd.bit_or(
|
||||
simd.bit_and(a, transmute(uint16x8_t)b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint16x8_t)not), transmute(uint16x8_t)c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbslq_s32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbslq_s32 :: #force_inline proc "c" (a: uint32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t {
|
||||
not := int32x4_t(-1)
|
||||
return transmute(int32x4_t)simd.bit_or(
|
||||
simd.bit_and(a, transmute(uint32x4_t)b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint32x4_t)not), transmute(uint32x4_t)c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbslq_s64)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbslq_s64 :: #force_inline proc "c" (a: uint64x2_t, b: int64x2_t, c: int64x2_t) -> int64x2_t {
|
||||
not := int64x2_t(-1)
|
||||
return transmute(int64x2_t)simd.bit_or(
|
||||
simd.bit_and(a, transmute(uint64x2_t)b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint64x2_t)not), transmute(uint64x2_t)c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbslq_u8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbslq_u8 :: #force_inline proc "c" (a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t {
|
||||
not := int8x16_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint8x16_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbslq_u16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbslq_u16 :: #force_inline proc "c" (a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t {
|
||||
not := int16x8_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint16x8_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbslq_u32)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbslq_u32 :: #force_inline proc "c" (a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t {
|
||||
not := int32x4_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint32x4_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbslq_u64)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbslq_u64 :: #force_inline proc "c" (a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2_t {
|
||||
not := int64x2_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint64x2_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
@(private, default_calling_convention = "none")
|
||||
foreign _ {
|
||||
@(link_name = "llvm.aarch64.neon.cls.v8i8" when ODIN_ARCH == .arm64 else "llvm.arm.neon.vcls.v8i8")
|
||||
_vcls_s8 :: proc(a: int8x8_t) -> int8x8_t ---
|
||||
@(link_name = "llvm.aarch64.neon.cls.v4i16" when ODIN_ARCH == .arm64 else "llvm.arm.neon.vcls.v4i16")
|
||||
_vcls_s16 :: proc(a: int16x4_t) -> int16x4_t ---
|
||||
@(link_name = "llvm.aarch64.neon.cls.v2i32" when ODIN_ARCH == .arm64 else "llvm.arm.neon.vcls.v2i32")
|
||||
_vcls_s32 :: proc(a: int32x2_t) -> int32x2_t ---
|
||||
@(link_name = "llvm.aarch64.neon.cls.v16i8" when ODIN_ARCH == .arm64 else "llvm.arm.neon.vcls.v16i8")
|
||||
_vclsq_s8 :: proc(a: int8x16_t) -> int8x16_t ---
|
||||
@(link_name = "llvm.aarch64.neon.cls.v8i16" when ODIN_ARCH == .arm64 else "llvm.arm.neon.vcls.v8i16")
|
||||
_vclsq_s16 :: proc(a: int16x8_t) -> int16x8_t ---
|
||||
@(link_name = "llvm.aarch64.neon.cls.v4i32" when ODIN_ARCH == .arm64 else "llvm.arm.neon.vcls.v4i32")
|
||||
_vclsq_s32 :: proc(a: int32x4_t) -> int32x4_t ---
|
||||
}
|
||||
@@ -3,6 +3,78 @@ package simd_arm
|
||||
|
||||
import "core:simd"
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbsl_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbsl_p8 :: #force_inline proc "c" (a: uint8x8_t, b: poly8x8_t, c: poly8x8_t) -> poly8x8_t {
|
||||
not := int8x8_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint8x8_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbsl_p16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbsl_p16 :: #force_inline proc "c" (a: uint16x4_t, b: poly16x4_t, c: poly16x4_t) -> poly16x4_t {
|
||||
not := int16x4_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(uint16x4_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbsl_p64)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbsl_p64 :: #force_inline proc "c" (a: poly64x1_t, b: poly64x1_t, c: poly64x1_t) -> poly64x1_t {
|
||||
not := int64x1_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(poly64x1_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbslq_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbslq_p8 :: #force_inline proc "c" (a: uint8x16_t, b: poly8x16_t, c: poly8x16_t) -> poly8x16_t {
|
||||
not := int8x16_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(poly8x16_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbslq_p16)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbslq_p16 :: #force_inline proc "c" (a: uint16x8_t, b: poly16x8_t, c: poly16x8_t) -> poly16x8_t {
|
||||
not := int16x8_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(poly16x8_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Bitwise Select.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vbslq_p64)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vbslq_p64 :: #force_inline proc "c" (a: poly64x2_t, b: poly64x2_t, c: poly64x2_t) -> poly64x2_t {
|
||||
not := int64x2_t(-1)
|
||||
return simd.bit_or(
|
||||
simd.bit_and(a, b),
|
||||
simd.bit_and(simd.bit_xor(a, transmute(poly64x2_t)not), c),
|
||||
)
|
||||
}
|
||||
|
||||
// Join two smaller vectors into a single larger vector
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcombine_p8)
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
package simd_arm
|
||||
|
||||
// Type aliases to match `arm_neon.h`.
|
||||
int8_t :: i8
|
||||
int16_t :: i16
|
||||
int32_t :: i32
|
||||
int64_t :: i64
|
||||
|
||||
uint8_t :: u8
|
||||
uint16_t :: u16
|
||||
uint32_t :: u32
|
||||
@@ -12,12 +17,23 @@ poly16_t :: u16
|
||||
poly64_t :: u64
|
||||
poly128_t :: u128
|
||||
|
||||
uint8x16_t :: #simd[16]u8
|
||||
uint32x4_t :: #simd[4]u32
|
||||
uint64x2_t :: #simd[2]u64
|
||||
int8x8_t :: #simd[8]int8_t
|
||||
int8x16_t :: #simd[16]int8_t
|
||||
int16x4_t :: #simd[4]int16_t
|
||||
int16x8_t :: #simd[8]int16_t
|
||||
int32x2_t :: #simd[2]int32_t
|
||||
int32x4_t :: #simd[4]int32_t
|
||||
int64x1_t :: #simd[1]int64_t
|
||||
int64x2_t :: #simd[2]int64_t
|
||||
|
||||
int32_t :: i32
|
||||
int8x16_t :: #simd[16]i8
|
||||
uint8x8_t :: #simd[8]uint8_t
|
||||
uint8x16_t :: #simd[16]uint8_t
|
||||
uint16x4_t :: #simd[4]uint16_t
|
||||
uint16x8_t :: #simd[8]uint16_t
|
||||
uint32x2_t :: #simd[2]uint32_t
|
||||
uint32x4_t :: #simd[4]uint32_t
|
||||
uint64x1_t :: #simd[1]uint64_t
|
||||
uint64x2_t :: #simd[2]uint64_t
|
||||
|
||||
poly8x8_t :: #simd[8]poly8_t
|
||||
poly8x16_t :: #simd[16]poly8_t
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Cross-platform `SIMD` support types and procedures.
|
||||
|
||||
SIMD (Single Instruction Multiple Data), is a CPU hardware feature that
|
||||
introduce special registers and instructions which operate on multiple units
|
||||
introduces special registers and instructions which operate on multiple units
|
||||
of data at the same time, which enables faster data processing for
|
||||
applications with heavy computational workloads.
|
||||
|
||||
|
||||
@@ -187,6 +187,9 @@ pool_join :: proc(pool: ^Pool) {
|
||||
//
|
||||
// Each task also needs an allocator which it either owns, or which is thread
|
||||
// safe.
|
||||
//
|
||||
// Completed tasks remain in the pool until removed with `pool_pop_done`.
|
||||
// When reusing the pool, call it once for every task added.
|
||||
pool_add_task :: proc(pool: ^Pool, allocator: mem.Allocator, procedure: Task_Proc, data: rawptr, user_index: int = 0) {
|
||||
sync.guard(&pool.mutex)
|
||||
|
||||
@@ -344,7 +347,10 @@ pool_pop_waiting :: proc(pool: ^Pool) -> (task: Task, got_task: bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// Use this to take out finished tasks.
|
||||
// Remove and return the next completed task, if one is available.
|
||||
//
|
||||
// The caller is responsible for processing the result and releasing any
|
||||
// resources associated with the task.
|
||||
pool_pop_done :: proc(pool: ^Pool) -> (task: Task, got_task: bool) {
|
||||
sync.guard(&pool.mutex)
|
||||
|
||||
@@ -374,6 +380,9 @@ pool_do_work :: proc(pool: ^Pool, task: Task) {
|
||||
|
||||
// Process the rest of the tasks, also use this thread for processing, then join
|
||||
// all the pool threads.
|
||||
//
|
||||
// Completed tasks are not removed. Retrieve each one with `pool_pop_done`.
|
||||
// The pool cannot be restarted after this procedure returns.
|
||||
pool_finish :: proc(pool: ^Pool) {
|
||||
for task in pool_pop_waiting(pool) {
|
||||
pool_do_work(pool, task)
|
||||
|
||||
@@ -54,6 +54,9 @@ Grapheme_Iterator :: struct {
|
||||
|
||||
current_sequence: Grapheme_Cluster_Sequence,
|
||||
continue_sequence: bool,
|
||||
|
||||
current_grapheme: Grapheme,
|
||||
continue_grapheme: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -147,13 +150,13 @@ decode_grapheme_iterate :: proc(it: ^Grapheme_Iterator) -> (text: string, graphe
|
||||
|
||||
if it.grapheme_count > it.last_grapheme_count {
|
||||
it.width += normalized_east_asian_width(this_rune)
|
||||
grapheme = Grapheme{
|
||||
byte_index,
|
||||
it.rune_count,
|
||||
it.width - it.last_width,
|
||||
if it.continue_grapheme {
|
||||
grapheme = it.current_grapheme
|
||||
text = it.str[it.current_grapheme.byte_index:byte_index]
|
||||
ok = true
|
||||
}
|
||||
text = it.str[byte_index:][:grapheme.width]
|
||||
ok = true
|
||||
it.current_grapheme = Grapheme{byte_index, it.rune_count, it.width - it.last_width}
|
||||
it.continue_grapheme = true
|
||||
|
||||
|
||||
it.last_grapheme_count = it.grapheme_count
|
||||
@@ -385,5 +388,14 @@ decode_grapheme_iterate :: proc(it: ^Grapheme_Iterator) -> (text: string, graphe
|
||||
it.grapheme_count += 1
|
||||
}
|
||||
|
||||
// Flush the remaining grapheme - the loop only flushes when
|
||||
// a new grapheme is encountered.
|
||||
if !ok && it.continue_grapheme {
|
||||
grapheme = it.current_grapheme
|
||||
text = it.str[it.current_grapheme.byte_index:]
|
||||
ok = true
|
||||
it.continue_grapheme = false
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,7 +694,9 @@ gb_internal String big_int_to_string(gbAllocator allocator, BigInt const *x, u64
|
||||
big_int_dealloc(&r);
|
||||
big_int_dealloc(&b);
|
||||
|
||||
for (isize i = first_word_idx; i < buf.count/2; i++) {
|
||||
// NOTE: only the digits are reversed, not the leading '-'.
|
||||
isize digit_count = buf.count - first_word_idx;
|
||||
for (isize i = first_word_idx; i < first_word_idx + digit_count/2; i++) {
|
||||
isize j = buf.count + first_word_idx - i - 1;
|
||||
char tmp = buf[i];
|
||||
buf[i] = buf[j];
|
||||
|
||||
@@ -410,6 +410,15 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E
|
||||
}
|
||||
|
||||
if (!src->Proc.is_polymorphic || src->Proc.is_poly_specialized) {
|
||||
// NOTE: polymorphic procedure check not idempotent without this
|
||||
if (src->Proc.is_poly_specialized && base_entity->Procedure.generated_from_polymorphic) {
|
||||
if (are_types_identical(src, dst)) {
|
||||
if (poly_proc_data) {
|
||||
poly_proc_data->gen_entity = base_entity;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -457,9 +466,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E
|
||||
scope->flags |= ScopeFlag_Proc;
|
||||
nctx.scope = scope;
|
||||
nctx.allow_polymorphic_types = true;
|
||||
if (nctx.polymorphic_scope == nullptr) {
|
||||
nctx.polymorphic_scope = scope;
|
||||
}
|
||||
nctx.polymorphic_scope = scope;
|
||||
|
||||
|
||||
auto *pt = &src->Proc;
|
||||
@@ -1027,17 +1034,6 @@ gb_internal bool check_is_assignable_to_with_score(CheckerContext *c, Operand *o
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle polymorphic procedure used as default parameter
|
||||
if (operand->mode == Addressing_Value && is_type_proc(type) && is_type_proc(operand->type)) {
|
||||
Entity *e = entity_from_expr(operand->expr);
|
||||
if (e != nullptr && e->kind == Entity_Procedure && is_type_polymorphic(e->type) && !is_type_polymorphic(type)) {
|
||||
// Special case: Allow a polymorphic procedure to be used as default value for concrete proc type
|
||||
// during the initial check. It will be properly instantiated when actually used.
|
||||
if (score_) *score_ = assign_score_function(1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
i64 score = check_distance_between_types(c, operand, type, allow_array_programming);
|
||||
if (score >= 0) {
|
||||
if (score_) *score_ = assign_score_function(score, is_variadic);
|
||||
@@ -4090,7 +4086,7 @@ gb_internal bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type
|
||||
big_int_shl_eq(&umax, &sz_in_bits);
|
||||
|
||||
if (is_type_unsigned(src_t) && !is_type_unsigned(dst_t)) {
|
||||
if (big_int_cmp(&v, &smax) >= 0) {
|
||||
if (big_int_cmp(&v, &smax) > 0) {
|
||||
big_int_sub_eq(&v, &umax);
|
||||
}
|
||||
} else if (!is_type_unsigned(src_t) && is_type_unsigned(dst_t)) {
|
||||
@@ -7637,7 +7633,9 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c,
|
||||
|
||||
if (max_matched_features > 0) {
|
||||
for_array(i, valids) {
|
||||
Entity *p = procs[valids[i].index];
|
||||
// NOTE: A polymorphic candidate appends its instantiated entity to proc_entities above,
|
||||
// so valids[i].index can be >= procs.count.
|
||||
Entity *p = proc_entities[valids[i].index];
|
||||
Type *t = base_type(p->type);
|
||||
GB_ASSERT(t->kind == Type_Proc);
|
||||
|
||||
|
||||
@@ -1791,6 +1791,7 @@ gb_internal ParameterValue handle_parameter_value(CheckerContext *ctx, Type *in_
|
||||
if (e->kind == Entity_Procedure) {
|
||||
param_value.kind = ParameterValue_Constant;
|
||||
param_value.value = exact_value_procedure(e->identifier);
|
||||
param_value.proc_entity = e;
|
||||
add_entity_use(ctx, e->identifier, e);
|
||||
} else {
|
||||
if (e->flags & EntityFlag_Param) {
|
||||
@@ -2143,8 +2144,12 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para
|
||||
// This is just to add the error message to determine_type_from_polymorphic which
|
||||
// depends on valid position information
|
||||
op.expr = _params;
|
||||
op.mode = Addressing_Invalid;
|
||||
op.type = t_invalid;
|
||||
|
||||
// NOTE(taylbr): Can still have valid type with null expr. Needed for resolving
|
||||
if (op.mode == Addressing_Invalid || op.type == nullptr) {
|
||||
op.mode = Addressing_Invalid;
|
||||
op.type = t_invalid;
|
||||
}
|
||||
}
|
||||
if (is_type_polymorphic_type) {
|
||||
type = determine_type_from_polymorphic(ctx, type, op);
|
||||
@@ -2841,9 +2846,14 @@ gb_internal i64 check_array_count(CheckerContext *ctx, Operand *o, Ast *e) {
|
||||
}
|
||||
Type *type = core_type(o->type);
|
||||
if (is_type_untyped(type) || is_type_integer(type)) {
|
||||
if (o->value.kind == ExactValue_Integer) {
|
||||
BigInt count = o->value.value_integer;
|
||||
if (big_int_is_neg(&o->value.value_integer)) {
|
||||
ExactValue value = o->value;
|
||||
if (value.kind == ExactValue_Float) {
|
||||
// NOTE: an integral float is a valid count, but it must be range checked as an integer
|
||||
value = exact_value_to_integer(value);
|
||||
}
|
||||
if (value.kind == ExactValue_Integer) {
|
||||
BigInt count = value.value_integer;
|
||||
if (big_int_is_neg(&count)) {
|
||||
gbAllocator a = heap_allocator();
|
||||
String str = big_int_to_string(a, &count);
|
||||
error(e, "Invalid negative array count, %.*s", LIT(str));
|
||||
@@ -2859,12 +2869,6 @@ gb_internal i64 check_array_count(CheckerContext *ctx, Operand *o, Ast *e) {
|
||||
error(e, "Array count too large, %.*s", LIT(str));
|
||||
gb_free(a, str.text);
|
||||
return 0;
|
||||
} else if (o->value.kind == ExactValue_Float) {
|
||||
u64 u = cast(u64)o->value.value_float;
|
||||
f64 f = cast(f64)u;
|
||||
if (f == o->value.value_float) {
|
||||
return u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2050,18 +2050,26 @@ gb_internal bool redeclaration_error(String name, Entity *prev, Entity *found) {
|
||||
// NOTE(bill): Error should have been handled already
|
||||
return false;
|
||||
}
|
||||
// NOTE: the insertion order is a race between the files of a package, so order the pair by
|
||||
// position; the later declaration stays the anchor, as it is the one being reported
|
||||
TokenPos first = prev->token.pos;
|
||||
TokenPos second = pos;
|
||||
if (second < first) {
|
||||
first = pos;
|
||||
second = prev->token.pos;
|
||||
}
|
||||
if (found->flags & EntityFlag_Result) {
|
||||
error(prev->token,
|
||||
error(second,
|
||||
"Direct shadowing of the named return value '%.*s' in this scope\n"
|
||||
"\tat %s",
|
||||
LIT(name),
|
||||
token_pos_to_string(pos));
|
||||
token_pos_to_string(first));
|
||||
} else {
|
||||
error(prev->token,
|
||||
error(second,
|
||||
"Redeclaration of '%.*s' in this scope\n"
|
||||
"\tat %s",
|
||||
LIT(name),
|
||||
token_pos_to_string(pos));
|
||||
token_pos_to_string(first));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -265,8 +265,12 @@ gb_internal OdinDocPosition odin_doc_token_pos_cast(OdinDocWriter *w, TokenPos c
|
||||
AstFile *file = global_files[pos.file_id];
|
||||
if (file != nullptr) {
|
||||
OdinDocFileIndex *file_index_found = map_get(&w->file_cache, file);
|
||||
GB_ASSERT(file_index_found != nullptr);
|
||||
file_index = *file_index_found;
|
||||
// NOTE: a documented entity may hold a position in a file belonging to an
|
||||
// imported package. Such files are only in file_cache when -all-packages is
|
||||
// used, so fall back to the reserved "no file" index.
|
||||
if (file_index_found != nullptr) {
|
||||
file_index = *file_index_found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ enum ParameterValueKind {
|
||||
struct ParameterValue {
|
||||
ParameterValueKind kind;
|
||||
Ast *original_ast_expr;
|
||||
Entity *proc_entity;
|
||||
union {
|
||||
ExactValue value;
|
||||
Ast *ast_value;
|
||||
|
||||
@@ -419,6 +419,12 @@ gb_internal ExactValue exact_value_to_integer(ExactValue v) {
|
||||
case ExactValue_Integer:
|
||||
return v;
|
||||
case ExactValue_Float: {
|
||||
f64 const min = cast(f64)I64_MIN; // -2^63
|
||||
f64 const max = -min; // 2^63, one past I64_MAX
|
||||
// NOTE: the conversion below is undefined outside of this range, NaN included
|
||||
if (!(v.value_float >= min && v.value_float < max)) {
|
||||
break;
|
||||
}
|
||||
i64 i = cast(i64)v.value_float;
|
||||
f64 f = cast(f64)i;
|
||||
if (f == v.value_float) {
|
||||
|
||||
@@ -155,7 +155,7 @@ try_cross_linking:;
|
||||
String section_name = str_lit("msvc-link");
|
||||
bool is_windows = build_context.metrics.os == TargetOs_windows;
|
||||
#else
|
||||
String section_name = str_lit("lld-link");
|
||||
String section_name = str_lit("ld-link");
|
||||
bool is_windows = false;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1700,7 +1700,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
|
||||
}
|
||||
}
|
||||
|
||||
res.value = lb_build_constant_array_values(m, type, elem_type, cast(isize)type->Array.count, values, cc);
|
||||
res.value = lb_build_constant_array_values(m, type, elem_type, cast(isize)type->EnumeratedArray.count, values, cc);
|
||||
return res;
|
||||
}
|
||||
} else if (is_type_fixed_capacity_dynamic_array(type)) {
|
||||
|
||||
@@ -4924,6 +4924,11 @@ gb_internal void lb_build_addr_compound_lit_populate(lbProcedure *p, Slice<Ast *
|
||||
case Type_SimdVector: et = bt->SimdVector.elem; break;
|
||||
case Type_Matrix: et = bt->Matrix.elem; break;
|
||||
case Type_FixedCapacityDynamicArray: et = bt->FixedCapacityDynamicArray.elem; break;
|
||||
case Type_Struct:
|
||||
if (bt->Struct.soa_kind == StructSoa_Fixed) {
|
||||
et = bt->Struct.soa_elem;
|
||||
}
|
||||
break;
|
||||
}
|
||||
GB_ASSERT(et != nullptr);
|
||||
|
||||
@@ -5038,18 +5043,17 @@ gb_internal void lb_build_addr_compound_lit_populate(lbProcedure *p, Slice<Ast *
|
||||
}
|
||||
gb_internal void lb_build_addr_compound_lit_assign_array(lbProcedure *p, Array<lbCompoundLitElemTempData> const &temp_data) {
|
||||
for (auto const &td : temp_data) {
|
||||
if (td.value.value != nullptr) {
|
||||
if (td.elem_length > 0) {
|
||||
auto loop_data = lb_loop_start(p, cast(isize)td.elem_length, t_i32);
|
||||
{
|
||||
lbValue dst = td.gep;
|
||||
dst = lb_emit_ptr_offset(p, dst, loop_data.idx);
|
||||
lb_emit_store(p, dst, td.value);
|
||||
}
|
||||
lb_loop_end(p, loop_data);
|
||||
} else {
|
||||
lb_emit_store(p, td.gep, td.value);
|
||||
GB_ASSERT(td.value.value != nullptr);
|
||||
if (td.elem_length > 0) {
|
||||
auto loop_data = lb_loop_start(p, cast(isize)td.elem_length, t_i32);
|
||||
{
|
||||
lbValue dst = td.gep;
|
||||
dst = lb_emit_ptr_offset(p, dst, loop_data.idx);
|
||||
lb_emit_store(p, dst, td.value);
|
||||
}
|
||||
lb_loop_end(p, loop_data);
|
||||
} else {
|
||||
lb_emit_store(p, td.gep, td.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6120,7 +6124,35 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
|
||||
}
|
||||
|
||||
case Type_Struct:
|
||||
lb_build_addr_struct_compound_lit_populate(p, expr, type, v);
|
||||
if (is_type_soa_struct(type)) {
|
||||
GB_ASSERT(bt->Struct.soa_kind == StructSoa_Fixed);
|
||||
if (cl->elems.count == 0) {
|
||||
break;
|
||||
}
|
||||
lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
|
||||
|
||||
auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
|
||||
lb_build_addr_compound_lit_populate(p, cl->elems, &temp_data, type);
|
||||
for (auto const &td : temp_data) {
|
||||
GB_ASSERT(td.value.value != nullptr);
|
||||
lbValue offset = lb_const_int(p->module, t_i32, td.elem_index);
|
||||
if (td.elem_length > 0) {
|
||||
auto loop_data = lb_loop_start(p, cast(isize)td.elem_length, t_i32);
|
||||
{
|
||||
lbValue index = lb_emit_arith(p, Token_Add, offset, loop_data.idx, t_i32);
|
||||
lbAddr dst = lb_addr_soa_variable(v.addr, index, td.expr);
|
||||
lb_addr_store(p, dst, td.value);
|
||||
}
|
||||
lb_loop_end(p, loop_data);
|
||||
} else {
|
||||
lbValue index = offset;
|
||||
lbAddr dst = lb_addr_soa_variable(v.addr, index, td.expr);
|
||||
lb_addr_store(p, dst, td.value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lb_build_addr_struct_compound_lit_populate(p, expr, type, v);
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Map: {
|
||||
|
||||
@@ -1024,10 +1024,16 @@ gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue
|
||||
}
|
||||
|
||||
for_array(i, ft->args) {
|
||||
// lbArg_Ignore args are not present in the call arguments, so they must not
|
||||
// advance param_offset (mirrors lb_add_function_type_attributes)
|
||||
if (ft->args[i].kind == lbArg_Ignore) {
|
||||
continue;
|
||||
}
|
||||
LLVMAttributeRef attribute = ft->args[i].attribute;
|
||||
if (attribute != nullptr) {
|
||||
LLVMAddCallSiteAttribute(ret, param_offset + cast(LLVMAttributeIndex)i, attribute);
|
||||
LLVMAddCallSiteAttribute(ret, param_offset, attribute);
|
||||
}
|
||||
param_offset += 1;
|
||||
}
|
||||
|
||||
switch (inlining) {
|
||||
@@ -4785,6 +4791,12 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
|
||||
gb_internal lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterValue const ¶m_value, TypeProc *procedure_type, Ast* call_expression) {
|
||||
switch (param_value.kind) {
|
||||
case ParameterValue_Constant:
|
||||
if (param_value.proc_entity != nullptr && is_type_proc(parameter_type)) {
|
||||
lbValue v = lb_find_procedure_value_from_entity(p->module, param_value.proc_entity);
|
||||
if (v.value != nullptr) {
|
||||
return lb_emit_conv(p, v, parameter_type);
|
||||
}
|
||||
}
|
||||
if (is_type_constant_type(parameter_type)) {
|
||||
auto res = lb_const_value(p->module, parameter_type, param_value.value);
|
||||
return res;
|
||||
@@ -4904,6 +4916,79 @@ gb_internal void lb_add_values_to_array(lbProcedure *p, Array<lbValue> *args, lb
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal lbValue lb_build_variadic_slice(lbProcedure *p, Type *slice_type, Slice<lbValue> var_args) {
|
||||
GB_ASSERT(is_type_slice(slice_type));
|
||||
if (var_args.count == 0) {
|
||||
return lb_const_nil(p->module, slice_type);
|
||||
}
|
||||
|
||||
Type *elem_type = slice_type->Slice.elem;
|
||||
lbAddr slice = {};
|
||||
|
||||
for (auto const &vr : p->variadic_reuses) {
|
||||
if (are_types_identical(vr.slice_type, slice_type)) {
|
||||
slice = vr.slice_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DeclInfo *d = decl_info_of_entity(p->entity);
|
||||
if (d != nullptr && slice.addr.value == nullptr) {
|
||||
for (auto const &vr : d->variadic_reuses) {
|
||||
if (are_types_identical(vr.slice_type, slice_type)) {
|
||||
#if LLVM_VERSION_MAJOR >= 13
|
||||
// NOTE(bill): No point wasting even more memory, just reuse this stack variable too
|
||||
if (p->variadic_reuses.count > 0) {
|
||||
slice = p->variadic_reuses[0].slice_addr;
|
||||
} else {
|
||||
slice = lb_add_local_generated(p, slice_type, true);
|
||||
}
|
||||
// NOTE(bill): Change the underlying type to match the specific type
|
||||
slice.addr.type = alloc_type_pointer(slice_type);
|
||||
#else
|
||||
slice = lb_add_local_generated(p, slice_type, true);
|
||||
#endif
|
||||
array_add(&p->variadic_reuses, lbVariadicReuseSlices{slice_type, slice});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lbValue base_array_ptr = p->variadic_reuse_base_array_ptr.addr;
|
||||
if (base_array_ptr.value == nullptr) {
|
||||
if (d != nullptr) {
|
||||
i64 max_bytes = d->variadic_reuse_max_bytes;
|
||||
i64 max_align = gb_max(d->variadic_reuse_max_align, 16);
|
||||
p->variadic_reuse_base_array_ptr = lb_add_local_generated(p, alloc_type_array(t_u8, max_bytes), true);
|
||||
lb_try_update_alignment(p->variadic_reuse_base_array_ptr.addr, cast(unsigned)max_align);
|
||||
base_array_ptr = p->variadic_reuse_base_array_ptr.addr;
|
||||
} else {
|
||||
base_array_ptr = lb_add_local_generated(p, alloc_type_array(elem_type, var_args.count), true).addr;
|
||||
}
|
||||
}
|
||||
|
||||
if (slice.addr.value == nullptr) {
|
||||
slice = lb_add_local_generated(p, slice_type, true);
|
||||
}
|
||||
|
||||
GB_ASSERT(base_array_ptr.value != nullptr);
|
||||
GB_ASSERT(slice.addr.value != nullptr);
|
||||
|
||||
base_array_ptr = lb_emit_conv(p, base_array_ptr, alloc_type_pointer(alloc_type_array(elem_type, var_args.count)));
|
||||
|
||||
for_array(i, var_args) {
|
||||
lbValue addr = lb_emit_array_epi(p, base_array_ptr, cast(i32)i);
|
||||
lbValue var_arg = lb_emit_conv(p, var_args[i], elem_type);
|
||||
lb_emit_store(p, addr, var_arg);
|
||||
}
|
||||
|
||||
lbValue base_elem = lb_emit_array_epi(p, base_array_ptr, 0);
|
||||
lbValue len = lb_const_int(p->module, t_int, var_args.count);
|
||||
lb_fill_slice(p, slice, base_elem, len);
|
||||
|
||||
return lb_addr_load(p, slice);
|
||||
}
|
||||
|
||||
gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr, lbValue *sret_dst) {
|
||||
lbModule *m = p->module;
|
||||
|
||||
@@ -4989,8 +5074,45 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr, lbVal
|
||||
|
||||
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
||||
bool is_c_vararg = pt->c_vararg;
|
||||
bool has_tuple_positional_arg = false;
|
||||
if (pt->variadic && !is_c_vararg && !vari_expand) {
|
||||
for (Ast *arg : ce->split_args->positional) {
|
||||
TypeAndValue tav = type_and_value_of_expr(arg);
|
||||
if (is_type_tuple(tav.type)) {
|
||||
has_tuple_positional_arg = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for_array(i, ce->split_args->positional) {
|
||||
if (has_tuple_positional_arg) {
|
||||
auto flat_args = array_make<lbValue>(heap_allocator());
|
||||
defer (array_free(&flat_args));
|
||||
|
||||
for_array(i, ce->split_args->positional) {
|
||||
Entity *e = pt->params->Tuple.variables[gb_min(i, cast(isize)pt->variadic_index)];
|
||||
if (e->kind == Entity_TypeName) {
|
||||
array_add(&flat_args, lb_const_nil(p->module, e->type));
|
||||
} else if (e->kind == Entity_Constant) {
|
||||
array_add(&flat_args, lb_const_value(p->module, e->type, e->Constant.value));
|
||||
} else {
|
||||
GB_ASSERT(e->kind == Entity_Variable);
|
||||
lbValue arg = lb_build_expr(p, ce->split_args->positional[i]);
|
||||
lb_add_values_to_array(p, &flat_args, arg);
|
||||
}
|
||||
}
|
||||
|
||||
isize fixed_count = pt->variadic_index;
|
||||
isize supplied_fixed_count = gb_min(fixed_count, flat_args.count);
|
||||
for (isize i = 0; i < supplied_fixed_count; i++) {
|
||||
array_add(&args, flat_args[i]);
|
||||
}
|
||||
array_resize(&args, fixed_count);
|
||||
|
||||
Type *slice_type = pt->params->Tuple.variables[pt->variadic_index]->type;
|
||||
auto var_args = slice(slice_from_array(flat_args), supplied_fixed_count, flat_args.count);
|
||||
array_add(&args, lb_build_variadic_slice(p, slice_type, var_args));
|
||||
} else for_array(i, ce->split_args->positional) {
|
||||
Entity *e = pt->params->Tuple.variables[i];
|
||||
if (e->kind == Entity_TypeName) {
|
||||
array_add(&args, lb_const_nil(p->module, e->type));
|
||||
@@ -5032,82 +5154,13 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr, lbVal
|
||||
variadic_args = lb_build_expr(p, variadic[0]);
|
||||
variadic_args = lb_emit_conv(p, variadic_args, slice_type);
|
||||
} else {
|
||||
Type *elem_type = slice_type->Slice.elem;
|
||||
|
||||
auto var_args = array_make<lbValue>(heap_allocator(), 0, variadic.count);
|
||||
defer (array_free(&var_args));
|
||||
for (Ast *var_arg : variadic) {
|
||||
lbValue v = lb_build_expr(p, var_arg);
|
||||
lb_add_values_to_array(p, &var_args, v);
|
||||
}
|
||||
isize slice_len = var_args.count;
|
||||
if (slice_len > 0) {
|
||||
lbAddr slice = {};
|
||||
|
||||
for (auto const &vr : p->variadic_reuses) {
|
||||
if (are_types_identical(vr.slice_type, slice_type)) {
|
||||
slice = vr.slice_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DeclInfo *d = decl_info_of_entity(p->entity);
|
||||
if (d != nullptr && slice.addr.value == nullptr) {
|
||||
for (auto const &vr : d->variadic_reuses) {
|
||||
if (are_types_identical(vr.slice_type, slice_type)) {
|
||||
#if LLVM_VERSION_MAJOR >= 13
|
||||
// NOTE(bill): No point wasting even more memory, just reuse this stack variable too
|
||||
if (p->variadic_reuses.count > 0) {
|
||||
slice = p->variadic_reuses[0].slice_addr;
|
||||
} else {
|
||||
slice = lb_add_local_generated(p, slice_type, true);
|
||||
}
|
||||
// NOTE(bill): Change the underlying type to match the specific type
|
||||
slice.addr.type = alloc_type_pointer(slice_type);
|
||||
#else
|
||||
slice = lb_add_local_generated(p, slice_type, true);
|
||||
#endif
|
||||
array_add(&p->variadic_reuses, lbVariadicReuseSlices{slice_type, slice});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lbValue base_array_ptr = p->variadic_reuse_base_array_ptr.addr;
|
||||
if (base_array_ptr.value == nullptr) {
|
||||
if (d != nullptr) {
|
||||
i64 max_bytes = d->variadic_reuse_max_bytes;
|
||||
i64 max_align = gb_max(d->variadic_reuse_max_align, 16);
|
||||
p->variadic_reuse_base_array_ptr = lb_add_local_generated(p, alloc_type_array(t_u8, max_bytes), true);
|
||||
lb_try_update_alignment(p->variadic_reuse_base_array_ptr.addr, cast(unsigned)max_align);
|
||||
base_array_ptr = p->variadic_reuse_base_array_ptr.addr;
|
||||
} else {
|
||||
base_array_ptr = lb_add_local_generated(p, alloc_type_array(elem_type, slice_len), true).addr;
|
||||
}
|
||||
}
|
||||
|
||||
if (slice.addr.value == nullptr) {
|
||||
slice = lb_add_local_generated(p, slice_type, true);
|
||||
}
|
||||
|
||||
GB_ASSERT(base_array_ptr.value != nullptr);
|
||||
GB_ASSERT(slice.addr.value != nullptr);
|
||||
|
||||
base_array_ptr = lb_emit_conv(p, base_array_ptr, alloc_type_pointer(alloc_type_array(elem_type, slice_len)));
|
||||
|
||||
for (isize i = 0; i < var_args.count; i++) {
|
||||
lbValue addr = lb_emit_array_epi(p, base_array_ptr, cast(i32)i);
|
||||
lbValue var_arg = var_args[i];
|
||||
var_arg = lb_emit_conv(p, var_arg, elem_type);
|
||||
lb_emit_store(p, addr, var_arg);
|
||||
}
|
||||
|
||||
lbValue base_elem = lb_emit_array_epi(p, base_array_ptr, 0);
|
||||
lbValue len = lb_const_int(p->module, t_int, slice_len);
|
||||
lb_fill_slice(p, slice, base_elem, len);
|
||||
|
||||
variadic_args = lb_addr_load(p, slice);
|
||||
}
|
||||
variadic_args = lb_build_variadic_slice(p, slice_type, slice_from_array(var_args));
|
||||
}
|
||||
}
|
||||
array_add(&args, variadic_args);
|
||||
|
||||
@@ -6,13 +6,35 @@ gb_internal bool in_vet_packages(AstFile *file) {
|
||||
if (file == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (file->pkg == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (file->pkg_decl == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (build_context.vet_packages.entries.count == 0) {
|
||||
return true;
|
||||
}
|
||||
return string_set_exists(&build_context.vet_packages, file->pkg->name);
|
||||
|
||||
String pkg_name = {};
|
||||
|
||||
if (file->pkg->name.len > 0) {
|
||||
pkg_name = file->pkg->name;
|
||||
} else if (file->pkg_decl->kind == Ast_PackageDecl) {
|
||||
Token name_token = file->pkg_decl->PackageDecl.name;
|
||||
if (name_token.kind == Token_Ident) {
|
||||
pkg_name = name_token.string;
|
||||
}
|
||||
}
|
||||
|
||||
if (pkg_name.len == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return string_set_exists(&build_context.vet_packages, pkg_name);
|
||||
}
|
||||
|
||||
gb_internal u64 ast_file_vet_flags(AstFile *f) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#+build !netbsd
|
||||
package test_core_math_rand
|
||||
|
||||
import "core:math"
|
||||
@@ -10,6 +11,9 @@ Generator :: struct {
|
||||
biased: bool,
|
||||
}
|
||||
|
||||
// Disable on NetBSD due to Illegal Instruction on CI, even with `microarch:native`
|
||||
// `@(test, disable="...")` still runs the test.
|
||||
|
||||
@(test)
|
||||
test_prngs :: proc(t: ^testing.T) {
|
||||
gens := []Generator {
|
||||
|
||||
@@ -525,6 +525,36 @@ join_url_test :: proc(t: ^testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
@test
|
||||
percent_encode_test :: proc(t: ^testing.T) {
|
||||
test_cases := []struct{input, expected: string} {
|
||||
// Bytes < 0x10 must be zero-padded to two hex digits
|
||||
{"\n", "%0A"},
|
||||
{"\t", "%09"},
|
||||
{"\r", "%0D"},
|
||||
{"a\nb", "a%0Ab"},
|
||||
{"\x00", "%00"},
|
||||
|
||||
// Bytes >= 0x10
|
||||
{" ", "%20"},
|
||||
{"😃", "%F0%9F%98%83"},
|
||||
|
||||
// Unreserved characters pass through unescaped
|
||||
{"AZaz09-_.~", "AZaz09-_.~"},
|
||||
}
|
||||
|
||||
for test in test_cases {
|
||||
encoded := net.percent_encode(test.input)
|
||||
defer delete(encoded)
|
||||
testing.expectf(t, encoded == test.expected, "Expected `net.percent_encode(%q)` to return %q, got %q", test.input, test.expected, encoded)
|
||||
|
||||
decoded, ok := net.percent_decode(encoded)
|
||||
defer delete(decoded)
|
||||
testing.expectf(t, ok, "Expected `net.percent_decode(%q)` to succeed", encoded)
|
||||
testing.expectf(t, decoded == test.input, "Expected percent-encoding roundtrip for %q, got %q", test.input, decoded)
|
||||
}
|
||||
}
|
||||
|
||||
@test
|
||||
test_udp_echo :: proc(t: ^testing.T) {
|
||||
endpoint := net.Endpoint{address=net.IP4_Address{127, 0, 0, 1}, port=0}
|
||||
|
||||
62
tests/core/slice/not_netbsd.odin
Normal file
62
tests/core/slice/not_netbsd.odin
Normal file
@@ -0,0 +1,62 @@
|
||||
#+build !netbsd
|
||||
package test_core_slice
|
||||
|
||||
import "core:slice"
|
||||
import "core:testing"
|
||||
import "core:math/rand"
|
||||
|
||||
// Disable on NetBSD due to Illegal Instruction on CI, even with `microarch:native`
|
||||
// `@(test, disable="...")` still runs the test.
|
||||
|
||||
@(test)
|
||||
test_unique :: proc(t: ^testing.T) {
|
||||
for v in UNIQUE_TEST_VECTORS {
|
||||
assorted := v[0]
|
||||
expected := v[1]
|
||||
|
||||
uniq := slice.unique(assorted)
|
||||
testing.expectf(t, slice.equal(uniq, expected), "Expected slice.uniq(%v) == %v, got %v", v[0], v[1], uniq)
|
||||
}
|
||||
|
||||
for v in UNIQUE_TEST_VECTORS {
|
||||
assorted := v[0]
|
||||
expected := v[1]
|
||||
|
||||
uniq := slice.unique_proc(assorted, proc(a, b: int) -> bool {
|
||||
return a == b
|
||||
})
|
||||
testing.expectf(t, slice.equal(uniq, expected), "Expected slice.unique_proc(%v, ...) == %v, got %v", v[0], v[1], uniq)
|
||||
}
|
||||
|
||||
r := rand.create(t.seed)
|
||||
context.random_generator = rand.default_random_generator(&r)
|
||||
|
||||
// 10_000 random tests
|
||||
for _ in 0..<10_000 {
|
||||
assorted: [dynamic]i64
|
||||
expected: [dynamic]i64
|
||||
|
||||
// Prime with 1 value
|
||||
old := rand.int63()
|
||||
append(&assorted, old)
|
||||
append(&expected, old)
|
||||
|
||||
// Add 99 additional random values
|
||||
for _ in 1..<100 {
|
||||
new := rand.int63()
|
||||
append(&assorted, new)
|
||||
if old != new {
|
||||
append(&expected, new)
|
||||
}
|
||||
old = new
|
||||
}
|
||||
|
||||
original := slice.clone(assorted[:])
|
||||
uniq := slice.unique(assorted[:])
|
||||
testing.expectf(t, slice.equal(uniq, expected[:]), "Expected slice.uniq(%v) == %v, got %v", original, expected, uniq)
|
||||
|
||||
delete(assorted)
|
||||
delete(original)
|
||||
delete(expected)
|
||||
}
|
||||
}
|
||||
@@ -225,59 +225,6 @@ UNIQUE_TEST_VECTORS :: [][2][]int{
|
||||
{{1,2,4,4,5}, {1,2,4,5}},
|
||||
}
|
||||
|
||||
@test
|
||||
test_unique :: proc(t: ^testing.T) {
|
||||
for v in UNIQUE_TEST_VECTORS {
|
||||
assorted := v[0]
|
||||
expected := v[1]
|
||||
|
||||
uniq := slice.unique(assorted)
|
||||
testing.expectf(t, slice.equal(uniq, expected), "Expected slice.uniq(%v) == %v, got %v", v[0], v[1], uniq)
|
||||
}
|
||||
|
||||
for v in UNIQUE_TEST_VECTORS {
|
||||
assorted := v[0]
|
||||
expected := v[1]
|
||||
|
||||
uniq := slice.unique_proc(assorted, proc(a, b: int) -> bool {
|
||||
return a == b
|
||||
})
|
||||
testing.expectf(t, slice.equal(uniq, expected), "Expected slice.unique_proc(%v, ...) == %v, got %v", v[0], v[1], uniq)
|
||||
}
|
||||
|
||||
r := rand.create(t.seed)
|
||||
context.random_generator = rand.default_random_generator(&r)
|
||||
|
||||
// 10_000 random tests
|
||||
for _ in 0..<10_000 {
|
||||
assorted: [dynamic]i64
|
||||
expected: [dynamic]i64
|
||||
|
||||
// Prime with 1 value
|
||||
old := rand.int63()
|
||||
append(&assorted, old)
|
||||
append(&expected, old)
|
||||
|
||||
// Add 99 additional random values
|
||||
for _ in 1..<100 {
|
||||
new := rand.int63()
|
||||
append(&assorted, new)
|
||||
if old != new {
|
||||
append(&expected, new)
|
||||
}
|
||||
old = new
|
||||
}
|
||||
|
||||
original := slice.clone(assorted[:])
|
||||
uniq := slice.unique(assorted[:])
|
||||
testing.expectf(t, slice.equal(uniq, expected[:]), "Expected slice.uniq(%v) == %v, got %v", original, expected, uniq)
|
||||
|
||||
delete(assorted)
|
||||
delete(original)
|
||||
delete(expected)
|
||||
}
|
||||
}
|
||||
|
||||
@test
|
||||
test_compare_empty :: proc(t: ^testing.T) {
|
||||
a := []int{}
|
||||
|
||||
@@ -9,6 +9,11 @@ Test_Case :: struct {
|
||||
expected_clusters: int,
|
||||
}
|
||||
|
||||
Text_Test_Case :: struct {
|
||||
str: string,
|
||||
expected_output: []string,
|
||||
}
|
||||
|
||||
run_test_cases :: proc(t: ^testing.T, test_cases: []Test_Case, loc := #caller_location) {
|
||||
failed := 0
|
||||
for c, i in test_cases {
|
||||
@@ -132,3 +137,32 @@ test_width :: proc(t: ^testing.T) {
|
||||
testing.expect_value(t, width, 50)
|
||||
}
|
||||
}
|
||||
|
||||
@test
|
||||
test_grapheme_cluster_text :: proc(t: ^testing.T) {
|
||||
|
||||
cases :: []Text_Test_Case {
|
||||
{"abc", {"a", "b", "c"}},
|
||||
{"é", {"é"}},
|
||||
{"中", {"中"}},
|
||||
{"\U0001F1FA\U0001F1F8", {"\U0001F1FA\U0001F1F8"}},
|
||||
{"\U0001F1FA\U0001F1F8\U0001F1EE\U0001F1EA", {"\U0001F1FA\U0001F1F8", "\U0001F1EE\U0001F1EA"}},
|
||||
{"\U0001F468\U0001F469\U0001F467\U0001F466", {"\U0001F468\U0001F469\U0001F467\U0001F466"}},
|
||||
{"\U0001F44D\U0001F3FD", {"\U0001F44D\U0001F3FD"}},
|
||||
{"a\r\nb", {"a", "\r\n", "b"}},
|
||||
}
|
||||
|
||||
for c in cases {
|
||||
it := utf8.decode_grapheme_iterator_make(c.str)
|
||||
i := 0
|
||||
for text, grapheme in utf8.decode_grapheme_iterate(&it) {
|
||||
if !testing.expectf(t, i < len(c.expected_output), "%q: expected %d clusters, got at least %d", c.str, len(c.expected_output), i + 1) {
|
||||
break
|
||||
}
|
||||
testing.expectf(t, text == c.expected_output[i], "%q cluster %d: expected text %q, got %q", c.str, i, c.expected_output[i], text)
|
||||
testing.expectf(t, text == c.str[grapheme.byte_index:][:len(text)], "%q cluster %d: text does not start at byte_index %d", c.str, i, grapheme.byte_index)
|
||||
i += 1
|
||||
}
|
||||
testing.expectf(t, i == len(c.expected_output), "%q: expected %d clusters, got %d", c.str, len(c.expected_output), i)
|
||||
}
|
||||
}
|
||||
|
||||
25
tests/internal/test_array_count.odin
Normal file
25
tests/internal/test_array_count.odin
Normal file
@@ -0,0 +1,25 @@
|
||||
package test_internal
|
||||
|
||||
import "core:testing"
|
||||
|
||||
@(test)
|
||||
array_count_from_integral_float :: proc(t: ^testing.T) {
|
||||
testing.expect_value(t, len([3.0]u8{}), 3)
|
||||
testing.expect_value(t, len([0.0]u8{}), 0)
|
||||
testing.expect_value(t, size_of([3.0]u32), 12)
|
||||
|
||||
// folded constant expressions
|
||||
Halved :: 6.0 / 2.0
|
||||
Summed :: 1.5 + 1.5
|
||||
testing.expect_value(t, len([Halved]u8{}), 3)
|
||||
testing.expect_value(t, len([Summed]u8{}), 3)
|
||||
|
||||
// NOTE: keep below one BigInt limb: 2^28 on windows, 2^60 on linux
|
||||
testing.expect_value(t, len([65536.0]struct{}{}), 1 << 16)
|
||||
|
||||
testing.expect_value(t, size_of(matrix[2.0, 3.0]f32), 24)
|
||||
testing.expect_value(t, size_of(#simd[4.0]u8), 4)
|
||||
|
||||
Sparse :: [2.0]u8
|
||||
testing.expect_value(t, len(Sparse{1, 2}), 2)
|
||||
}
|
||||
@@ -26,6 +26,7 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style -ignore-unused
|
||||
..\..\..\odin build ..\test_issue_5097.odin %COMMON% || exit /b
|
||||
..\..\..\odin build ..\test_issue_5097-2.odin %COMMON% || exit /b
|
||||
..\..\..\odin build ..\test_issue_5265.odin %COMMON% || exit /b
|
||||
..\..\..\odin build ..\test_issue_5573.odin %COMMON% 2>&1 | find /c "Error:" | findstr /x "2" || exit /b
|
||||
..\..\..\odin test ..\test_issue_5699.odin %COMMON% || exit /b
|
||||
..\..\..\odin test ..\test_issue_6068.odin %COMMON% || exit /b
|
||||
..\..\..\odin test ..\test_issue_6101.odin %COMMON% || exit /b
|
||||
@@ -37,9 +38,11 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style -ignore-unused
|
||||
..\..\..\odin test ..\test_pr_6470.odin -define:TEST_EXPECT_FAILURE=true %COMMON% 2>&1 | find /c "Error:" | findstr /x "1" || exit /b
|
||||
..\..\..\odin test ..\test_pr_6476.odin %COMMON% || exit /b
|
||||
..\..\..\odin check ..\test_issue_6484.odin -no-entry-point %COMMON% || exit /b
|
||||
..\..\..\odin test ..\test_issue_6753.odin %COMMON% || exit /b
|
||||
..\..\..\odin check ..\test_issue_6874.odin %COMMON% 2>&1 | find /c "Error:" | findstr /x "1" || exit /b
|
||||
..\..\..\odin check ..\test_issue_6979.odin -no-entry-point %COMMON% || exit /b
|
||||
..\..\..\odin build ..\test_issue_7037.odin %COMMON% -o:none || exit /b
|
||||
..\..\..\odin build ..\test_issue_7188.odin %COMMON% || exit /b
|
||||
..\..\..\odin build ..\test_issue_7073-1.odin %COMMON% 2>&1 | find /c "Error:" | findstr /x "2" || exit /b
|
||||
|
||||
@echo off
|
||||
|
||||
@@ -7,10 +7,9 @@ ODIN=../../../odin
|
||||
COMMON="-define:ODIN_TEST_FANCY=false -file -vet -strict-style -ignore-unused-defineables -microarch:native"
|
||||
COMMON_CHECK="-define:ODIN_TEST_FANCY=false -file -vet -strict-style -ignore-unused-defineables"
|
||||
|
||||
|
||||
set -x
|
||||
|
||||
$ODIN test ../test_issue_829.odin $COMMON
|
||||
$ODIN test ../test_issue_829.odin $COMMON
|
||||
$ODIN test ../test_issue_1592.odin $COMMON
|
||||
$ODIN test ../test_issue_1730.odin $COMMON
|
||||
$ODIN test ../test_issue_2056.odin $COMMON
|
||||
@@ -24,7 +23,7 @@ $ODIN test ../test_issue_3435.odin $COMMON
|
||||
$ODIN test ../test_issue_4210.odin $COMMON
|
||||
$ODIN test ../test_issue_4364.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
|
||||
if [[ $($ODIN build ../test_issue_2395.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
@@ -34,6 +33,12 @@ $ODIN build ../test_issue_5043.odin $COMMON
|
||||
$ODIN build ../test_issue_5097.odin $COMMON
|
||||
$ODIN build ../test_issue_5097-2.odin $COMMON
|
||||
$ODIN build ../test_issue_5265.odin $COMMON
|
||||
if [[ $($ODIN build ../test_issue_5573.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
exit 1
|
||||
fi
|
||||
$ODIN test ../test_issue_5699.odin $COMMON
|
||||
$ODIN test ../test_issue_6068.odin $COMMON
|
||||
$ODIN test ../test_issue_6101.odin $COMMON
|
||||
@@ -43,25 +48,25 @@ $ODIN test ../test_issue_6344.odin $COMMON -o:speed
|
||||
$ODIN test ../test_issue_6396.odin $COMMON
|
||||
$ODIN test ../test_pr_6476.odin $COMMON
|
||||
|
||||
if [[ $($ODIN build ../test_issue_6240.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 3 ]] ; then
|
||||
if [[ $($ODIN build ../test_issue_6240.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 3 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
exit 1
|
||||
fi
|
||||
if [[ $($ODIN build ../test_issue_6401.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 3 ]] ; then
|
||||
if [[ $($ODIN build ../test_issue_6401.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 3 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
exit 1
|
||||
fi
|
||||
if [[ $($ODIN build ../test_issue_6594.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]] ; then
|
||||
if [[ $($ODIN build ../test_issue_6594.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
exit 1
|
||||
fi
|
||||
if [[ $($ODIN build ../test_issue_6621.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]] ; then
|
||||
if [[ $($ODIN build ../test_issue_6621.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
@@ -69,14 +74,15 @@ else
|
||||
fi
|
||||
$ODIN test ../test_issue_6419.odin $COMMON
|
||||
$ODIN test ../test_pr_6470.odin $COMMON
|
||||
if [[ $($ODIN test ../test_pr_6470.odin -define:TEST_EXPECT_FAILURE=true $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]] ; then
|
||||
if [[ $($ODIN test ../test_pr_6470.odin -define:TEST_EXPECT_FAILURE=true $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
exit 1
|
||||
fi
|
||||
$ODIN check ../test_issue_6484.odin -no-entry-point $COMMON_CHECK
|
||||
if [[ $($ODIN check ../test_issue_6874.odin $COMMON_CHECK 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]] ; then
|
||||
$ODIN test ../test_issue_6753.odin $COMMON
|
||||
if [[ $($ODIN check ../test_issue_6874.odin $COMMON_CHECK 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
@@ -84,15 +90,17 @@ else
|
||||
fi
|
||||
$ODIN check ../test_issue_6979.odin -no-entry-point $COMMON_CHECK
|
||||
$ODIN build ../test_issue_7037.odin $COMMON -o:none
|
||||
$ODIN build ../test_issue_7167.odin $COMMON
|
||||
$ODIN build ../test_issue_7188.odin $COMMON
|
||||
|
||||
if [[ $($ODIN build ../test_issue_7108.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]] ; then
|
||||
if [[ $($ODIN build ../test_issue_7108.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $($ODIN build ../test_issue_7073-1.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]] ; then
|
||||
if [[ $($ODIN build ../test_issue_7073-1.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
|
||||
18
tests/issues/test_issue_5573.odin
Normal file
18
tests/issues/test_issue_5573.odin
Normal file
@@ -0,0 +1,18 @@
|
||||
// Tests issue #5573 https://github.com/odin-lang/Odin/issues/5573
|
||||
package test_issues
|
||||
|
||||
poly :: proc(x: $T) -> string {
|
||||
return "poly"
|
||||
}
|
||||
|
||||
takes_concrete :: proc(f: proc(a: int, b: f32, c: rawptr) -> ^int) {
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
// should error - wrong arity, wrong parameter types, wrong return type
|
||||
mismatched: proc(a: int, b: f32, c: rawptr) -> ^int = poly
|
||||
_ = mismatched
|
||||
|
||||
// should error - same, as a procedure argument
|
||||
takes_concrete(poly)
|
||||
}
|
||||
64
tests/issues/test_issue_6753.odin
Normal file
64
tests/issues/test_issue_6753.odin
Normal file
@@ -0,0 +1,64 @@
|
||||
// test issue for #6753 https://github.com/odin-lang/odin/issues/6753
|
||||
package test_issues
|
||||
import "core:testing"
|
||||
import "core:fmt"
|
||||
|
||||
foo_concrete :: proc(x: int, g: proc(int) -> int) -> int {
|
||||
return g(x)
|
||||
}
|
||||
foo_impossible :: proc(x: int, g: proc(int, int) -> string) -> string {
|
||||
return "impossible"
|
||||
}
|
||||
foo_group :: proc {
|
||||
foo_concrete,
|
||||
foo_impossible,
|
||||
}
|
||||
|
||||
f_poly :: proc(x: $T) -> T { return x }
|
||||
foo_poly :: proc(x: $T, g: proc(T) -> T = f_poly) -> T {
|
||||
return g(x)
|
||||
}
|
||||
|
||||
@test
|
||||
test_issue_6753_ambiguous_poly_argument :: proc (t: ^testing.T) {
|
||||
testing.expect_value(t, foo_group(1, f_poly), 1) // should be no ambiguity whether foo_concrete or foo_impossible
|
||||
}
|
||||
|
||||
@test
|
||||
test_issue_6753_default_poly_proc :: proc (t: ^testing.T) {
|
||||
testing.expect_value(t, foo_poly(1), 1)
|
||||
}
|
||||
|
||||
@test
|
||||
test_issue_6753_parapoly_proc_variable :: proc(t: ^testing.T) {
|
||||
p: proc(int) -> int = f_poly
|
||||
testing.expect(t, p != nil, "polymorphic procedure was not instantiated")
|
||||
testing.expect_value(t, p(123), 123)
|
||||
}
|
||||
|
||||
// -- Fixing above led to some new bugs surfacing --
|
||||
@test
|
||||
test_issue_6753_parapoly_proc_as_argument :: proc(t: ^testing.T) {
|
||||
testing.expect(t, foo_concrete(123, f_poly) == 123, "failed to pass poly proc as argument")
|
||||
}
|
||||
|
||||
@test
|
||||
test_issue_6753_parapoly_with_default_proc_same_generic_type_T :: proc(t: ^testing.T) {
|
||||
testing.expect_value(t, foo_poly(123), 123)
|
||||
testing.expect_value(t, foo_poly(123, f_poly), 123)
|
||||
}
|
||||
|
||||
// all together now
|
||||
describe :: proc(x: $T) -> string { return fmt.tprintf("#%v", x) }
|
||||
describe_bytes :: proc(x: []byte) -> string { return "bytes" }
|
||||
|
||||
bar_poly :: proc(x: $T, g: proc(x: T) -> string = describe) -> string { return g(x) }
|
||||
bar_bytes :: proc(x: []byte, g: proc(x: []byte) -> string) -> string { return g(x) }
|
||||
bar_group :: proc { bar_poly, bar_bytes }
|
||||
|
||||
@test
|
||||
test_issue_6753_parapoly_default_in_group :: proc(t: ^testing.T) {
|
||||
testing.expect_value(t, bar_group(123, describe), "#123")
|
||||
testing.expect_value(t, bar_group("hi"), "#hi")
|
||||
testing.expect_value(t, bar_group([]byte{1, 2}, describe_bytes), "bytes")
|
||||
}
|
||||
9
tests/issues/test_issue_7167.odin
Normal file
9
tests/issues/test_issue_7167.odin
Normal file
@@ -0,0 +1,9 @@
|
||||
// Tests issue #7167 https://github.com/odin-lang/Odin/issues/7167
|
||||
package test_issues
|
||||
|
||||
import "core:fmt"
|
||||
import "core:path/filepath"
|
||||
|
||||
main :: proc() {
|
||||
fmt.printf(filepath.join({}))
|
||||
}
|
||||
13
tests/issues/test_issue_7188.odin
Normal file
13
tests/issues/test_issue_7188.odin
Normal file
@@ -0,0 +1,13 @@
|
||||
package test_issues
|
||||
|
||||
main :: proc() {
|
||||
val: f32 = 42.0
|
||||
// unable to broadcast like ([4][4]f32)(1) or (#soa[4][4]f32)(([4]f32)(1))
|
||||
_ = #soa[2][2]f32 {
|
||||
0..<2 = val,
|
||||
}
|
||||
vtxs := #soa[33][2]f32 {
|
||||
0..<33 = val,
|
||||
}
|
||||
_ = vtxs.x[32]
|
||||
}
|
||||
4
vendor/box3d/lib/linux-amd64/libbox3d.a
vendored
4
vendor/box3d/lib/linux-amd64/libbox3d.a
vendored
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d698fbbe655db1d1ec6f52dcc23bfed4a2c981fa88040ba449f9f83609edba88
|
||||
size 3137140
|
||||
oid sha256:ad5491b77cda430ee03adb68bd6b4d56d3f7d8941327643eecc2b636496acda0
|
||||
size 1601114
|
||||
|
||||
15
vendor/box3d/src/build.sh
vendored
15
vendor/box3d/src/build.sh
vendored
@@ -70,12 +70,19 @@ Darwin)
|
||||
;;
|
||||
Linux)
|
||||
LIB_DIR="../lib/linux-$ARCH"
|
||||
mkdir -p "$LIB_DIR"
|
||||
$cc -c -O2 -std=c17 -fPIC -Iinclude src/*.c
|
||||
$ar rcs "$LIB_DIR/$LIB_NAME" ./*.o
|
||||
rm ./*.o
|
||||
mkdir -p "$LIB_DIR" build
|
||||
for src in src/*.c; do
|
||||
obj="build/$(basename "${src%.c}.o")"
|
||||
$cc -c -O2 -std=c17 -fPIC -Iinclude "$src" -o "$obj"
|
||||
done
|
||||
# Clean up old library in case `ar` is tempted to preserve old symbols
|
||||
rm -f "$LIB_DIR/$LIB_NAME"
|
||||
$ar rcs "$LIB_DIR/$LIB_NAME" build/*.o
|
||||
$ranlib "$LIB_DIR/$LIB_NAME"
|
||||
rm -rf build
|
||||
;;
|
||||
*)
|
||||
|
||||
echo "Error: Unsupported operating system: $(uname -s)"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
Reference in New Issue
Block a user