mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-19 11:51:33 +00:00
Merge branch 'master' into pr/7345
This commit is contained in:
@@ -125,7 +125,7 @@ NetBSD)
|
||||
;;
|
||||
Linux)
|
||||
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
||||
LDFLAGS="$LDFLAGS -lstdc++ -ldl $($LLVM_CONFIG --libs core native --system-libs --libfiles)"
|
||||
LDFLAGS="$LDFLAGS -lstdc++ -ldl $($LLVM_CONFIG --libs core native passes arm aarch64 x86 webassembly riscv --system-libs --libfiles)"
|
||||
# Copy libLLVM*.so into current directory for linking
|
||||
# NOTE: This is needed by the Linux release pipeline!
|
||||
# cp $(readlink -f $($LLVM_CONFIG --libfiles)) ./
|
||||
|
||||
@@ -95,12 +95,12 @@ Decodes a hex sequence into a byte slice
|
||||
*Allocates Using Provided Allocator*
|
||||
|
||||
Inputs:
|
||||
- dst: The hex sequence decoded into bytes
|
||||
- src: The `[]byte` to be hex-decoded
|
||||
- allocator: (default: context.allocator)
|
||||
- loc: The caller location for debugging purposes (default: #caller_location)
|
||||
|
||||
Returns:
|
||||
- dst: The hex sequence decoded into bytes
|
||||
- ok: A bool, `true` if decoding succeeded, `false` otherwise
|
||||
*/
|
||||
decode :: proc(src: []byte, allocator := context.allocator, loc := #caller_location) -> (dst: []byte, ok: bool) {
|
||||
@@ -123,6 +123,40 @@ decode :: proc(src: []byte, allocator := context.allocator, loc := #caller_locat
|
||||
return dst, true
|
||||
}
|
||||
|
||||
/*
|
||||
Decodes a hex sequence into a byte slice
|
||||
|
||||
Inputs:
|
||||
- src: The `[]byte` to be hex-decoded
|
||||
- buf: A buffer large enough to hold the decoded sequence
|
||||
|
||||
Returns:
|
||||
- dst: The hex sequence decoded into bytes
|
||||
- ok: A bool, `true` if decoding succeeded, `false` otherwise
|
||||
*/
|
||||
decode_into_buffer :: proc(src: []byte, buf: []byte) -> (dst: []byte, ok: bool) #optional_ok {
|
||||
if len(src) % 2 == 1 {
|
||||
return
|
||||
}
|
||||
dst_len := len(src) / 2
|
||||
if len(buf) < dst_len {
|
||||
return
|
||||
}
|
||||
|
||||
#no_bounds_check for i, j := 0, 1; j < len(src); j += 2 {
|
||||
p := src[j-1]
|
||||
q := src[j]
|
||||
|
||||
a := hex_digit(p) or_return
|
||||
b := hex_digit(q) or_return
|
||||
|
||||
buf[i] = (a << 4) | b
|
||||
i += 1
|
||||
}
|
||||
|
||||
return buf[:dst_len], true
|
||||
}
|
||||
|
||||
/*
|
||||
Decodes the first byte in a hex sequence to a byte
|
||||
|
||||
@@ -173,4 +207,4 @@ hex_digit :: proc(char: byte) -> (u8, bool) {
|
||||
case 'A' ..= 'F': return char - 'A' + 10, true
|
||||
case: return 0, false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ write :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string {
|
||||
}
|
||||
}
|
||||
|
||||
n := copy(dst, buf[:i])
|
||||
copy(dst, buf[:i])
|
||||
return string(dst[:i])
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -502,6 +502,134 @@ vtbl4_p8 :: #force_inline proc "c" (t: poly8x8x4_t, idx: poly8x8_t) -> poly8x8_t
|
||||
}
|
||||
}
|
||||
|
||||
// Extended Table Lookup.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vtbx1_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vtbx1_p8 :: #force_inline proc "c" (v: poly8x8_t, t: poly8x8_t, idx: uint8x8_t) -> poly8x8_t {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
return simd.select(
|
||||
simd.lanes_lt(idx, uint8x8_t(8)),
|
||||
vqtbx1_p8(v, vcombine_p8(t, poly8x8_t{}), idx),
|
||||
v,
|
||||
)
|
||||
} else {
|
||||
return transmute(poly8x8_t)_vtbx1(
|
||||
transmute(int8x8_t)v,
|
||||
transmute(int8x8_t)t,
|
||||
transmute(int8x8_t)idx,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Extended Table Lookup.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vtbx2_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vtbx2_p8 :: #force_inline proc "c" (v: poly8x8_t, t: poly8x8x2_t, idx: uint8x8_t) -> poly8x8_t {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
return simd.select(
|
||||
simd.lanes_lt(idx, uint8x8_t(16)),
|
||||
vqtbx1_p8(v, vcombine_p8(t.x, t.y), idx),
|
||||
v,
|
||||
)
|
||||
} else {
|
||||
return transmute(poly8x8_t)_vtbx2(
|
||||
transmute(int8x8_t)v,
|
||||
transmute(int8x8_t)t.x,
|
||||
transmute(int8x8_t)t.y,
|
||||
transmute(int8x8_t)idx,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Extended Table Lookup.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vtbx3_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vtbx3_p8 :: #force_inline proc "c" (v: poly8x8_t, t: poly8x8x3_t, idx: uint8x8_t) -> poly8x8_t {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
x := poly8x16x2_t {
|
||||
vcombine_p8(t.x, t.y),
|
||||
vcombine_p8(t.z, poly8x8_t{}),
|
||||
}
|
||||
return simd.select(
|
||||
simd.lanes_lt(idx, uint8x8_t(24)),
|
||||
vqtbx2_p8(v, x, idx),
|
||||
v,
|
||||
)
|
||||
} else {
|
||||
return transmute(poly8x8_t)_vtbx3(
|
||||
transmute(int8x8_t)v,
|
||||
transmute(int8x8_t)t.x,
|
||||
transmute(int8x8_t)t.y,
|
||||
transmute(int8x8_t)t.z,
|
||||
transmute(int8x8_t)idx,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Extended Table Lookup.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vtbx4_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vtbx4_p8 :: #force_inline proc "c" (v: poly8x8_t, t: poly8x8x4_t, idx: uint8x8_t) -> poly8x8_t {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
x := poly8x16x2_t {
|
||||
vcombine_p8(t.x, t.y),
|
||||
vcombine_p8(t.z, t.w),
|
||||
}
|
||||
return simd.select(
|
||||
simd.lanes_lt(idx, uint8x8_t(32)),
|
||||
vqtbx2_p8(v, x, idx),
|
||||
v,
|
||||
)
|
||||
} else {
|
||||
return transmute(poly8x8_t)_vtbx4(
|
||||
transmute(int8x8_t)v,
|
||||
transmute(int8x8_t)t.x,
|
||||
transmute(int8x8_t)t.y,
|
||||
transmute(int8x8_t)t.z,
|
||||
transmute(int8x8_t)t.w,
|
||||
transmute(int8x8_t)idx,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 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_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)
|
||||
}
|
||||
|
||||
// Bitwise Not.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vmvn_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vmvn_p8 :: #force_inline proc "c" (a: poly8x8_t) -> poly8x8_t {
|
||||
b := poly8x8_t(max(poly8_t))
|
||||
return simd.bit_xor(a, b)
|
||||
}
|
||||
|
||||
// Bitwise Not.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vmvnq_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vmvnq_p8 :: #force_inline proc "c" (a: poly8x16_t) -> poly8x16_t {
|
||||
b := poly8x16_t(max(poly8_t))
|
||||
return simd.bit_xor(a, b)
|
||||
}
|
||||
|
||||
when ODIN_ARCH == .arm64 {
|
||||
// Polynomial multiply long
|
||||
//
|
||||
@@ -732,6 +860,246 @@ when ODIN_ARCH == .arm64 {
|
||||
return simd.shuffle(c, c, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Extended Table Lookup.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbx1_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vqtbx1_p8 :: #force_inline proc "c" (v: poly8x8_t, t: poly8x16_t, idx: uint8x8_t) -> poly8x8_t {
|
||||
when ODIN_ENDIAN == .Little {
|
||||
return transmute(poly8x8_t)_vqtbx1(
|
||||
transmute(int8x8_t)v,
|
||||
transmute(int8x16_t)t,
|
||||
idx,
|
||||
)
|
||||
} else {
|
||||
v := simd.shuffle(v, v, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
t := simd.shuffle(t, t, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
idx := simd.shuffle(idx, idx, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
c := transmute(poly8x8_t)_vqtbx1(
|
||||
transmute(int8x8_t)v,
|
||||
transmute(int8x16_t)t,
|
||||
idx,
|
||||
)
|
||||
return simd.shuffle(c, c, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Extended Table Lookup.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbx1q_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vqtbx1q_p8 :: #force_inline proc "c" (v: poly8x16_t, t: poly8x16_t, idx: uint8x16_t) -> poly8x16_t {
|
||||
when ODIN_ENDIAN == .Little {
|
||||
return transmute(poly8x16_t)_vqtbx1q(
|
||||
transmute(int8x16_t)v,
|
||||
transmute(int8x16_t)t,
|
||||
idx,
|
||||
)
|
||||
} else {
|
||||
v := simd.shuffle(v, v, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
t := simd.shuffle(t, t, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
idx := simd.shuffle(idx, idx, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
c := transmute(poly8x16_t)_vqtbx1q(
|
||||
transmute(int8x16_t)v,
|
||||
transmute(int8x16_t)t,
|
||||
idx,
|
||||
)
|
||||
return simd.shuffle(c, c, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Extended Table Lookup.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbx2_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vqtbx2_p8 :: #force_inline proc "c" (v: poly8x8_t, t: poly8x16x2_t, idx: uint8x8_t) -> poly8x8_t {
|
||||
when ODIN_ENDIAN == .Little {
|
||||
return transmute(poly8x8_t)_vqtbx2(
|
||||
transmute(int8x8_t)v,
|
||||
transmute(int8x16_t)t.x,
|
||||
transmute(int8x16_t)t.y,
|
||||
idx,
|
||||
)
|
||||
} else {
|
||||
v := simd.shuffle(v, v, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
t := poly8x16x2_t {
|
||||
simd.shuffle(t.x, t.x, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
simd.shuffle(t.y, t.y, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
}
|
||||
idx := simd.shuffle(idx, idx, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
c := transmute(poly8x8_t)_vqtbx2(
|
||||
transmute(int8x8_t)v,
|
||||
transmute(int8x16_t)t.x,
|
||||
transmute(int8x16_t)t.y,
|
||||
idx,
|
||||
)
|
||||
return simd.shuffle(c, c, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Extended Table Lookup.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbx2q_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vqtbx2q_p8 :: #force_inline proc "c" (v: poly8x16_t, t: poly8x16x2_t, idx: uint8x16_t) -> poly8x16_t {
|
||||
when ODIN_ENDIAN == .Little {
|
||||
return transmute(poly8x16_t)_vqtbx2q(
|
||||
transmute(int8x16_t)v,
|
||||
transmute(int8x16_t)t.x,
|
||||
transmute(int8x16_t)t.y,
|
||||
idx,
|
||||
)
|
||||
} else {
|
||||
v := simd.shuffle(v, v, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
t := poly8x16x2_t {
|
||||
simd.shuffle(t.x, t.x, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
simd.shuffle(t.y, t.y, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
}
|
||||
idx := simd.shuffle(idx, idx, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
c := transmute(poly8x16_t)_vqtbx2q(
|
||||
transmute(int8x16_t)v,
|
||||
transmute(int8x16_t)t.x,
|
||||
transmute(int8x16_t)t.y,
|
||||
idx,
|
||||
)
|
||||
return simd.shuffle(c, c, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Extended Table Lookup.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbx3_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vqtbx3_p8 :: #force_inline proc "c" (v: poly8x8_t, t: poly8x16x3_t, idx: uint8x8_t) -> poly8x8_t {
|
||||
when ODIN_ENDIAN == .Little {
|
||||
return transmute(poly8x8_t)_vqtbx3(
|
||||
transmute(int8x8_t)v,
|
||||
transmute(int8x16_t)t.x,
|
||||
transmute(int8x16_t)t.y,
|
||||
transmute(int8x16_t)t.z,
|
||||
idx,
|
||||
)
|
||||
} else {
|
||||
v := simd.shuffle(v, v, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
t := poly8x16x3_t {
|
||||
simd.shuffle(t.x, t.x, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
simd.shuffle(t.y, t.y, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
simd.shuffle(t.z, t.z, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
}
|
||||
idx := simd.shuffle(idx, idx, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
c := transmute(poly8x8_t)_vqtbx3(
|
||||
transmute(int8x8_t)v,
|
||||
transmute(int8x16_t)t.x,
|
||||
transmute(int8x16_t)t.y,
|
||||
transmute(int8x16_t)t.z,
|
||||
idx,
|
||||
)
|
||||
return simd.shuffle(c, c, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Extended Table Lookup.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbx3q_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vqtbx3q_p8 :: #force_inline proc "c" (v: poly8x16_t, t: poly8x16x3_t, idx: uint8x16_t) -> poly8x16_t {
|
||||
when ODIN_ENDIAN == .Little {
|
||||
return transmute(poly8x16_t)_vqtbx3q(
|
||||
transmute(int8x16_t)v,
|
||||
transmute(int8x16_t)t.x,
|
||||
transmute(int8x16_t)t.y,
|
||||
transmute(int8x16_t)t.z,
|
||||
idx,
|
||||
)
|
||||
} else {
|
||||
v := simd.shuffle(v, v, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
t := poly8x16x3_t {
|
||||
simd.shuffle(t.x, t.x, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
simd.shuffle(t.y, t.y, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
simd.shuffle(t.z, t.z, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
}
|
||||
idx := simd.shuffle(idx, idx, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
c := transmute(poly8x16_t)_vqtbx3q(
|
||||
transmute(int8x16_t)v,
|
||||
transmute(int8x16_t)t.x,
|
||||
transmute(int8x16_t)t.y,
|
||||
transmute(int8x16_t)t.z,
|
||||
idx,
|
||||
)
|
||||
return simd.shuffle(c, c, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Extended Table Lookup.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbx4_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vqtbx4_p8 :: #force_inline proc "c" (v: poly8x8_t, t: poly8x16x4_t, idx: uint8x8_t) -> poly8x8_t {
|
||||
when ODIN_ENDIAN == .Little {
|
||||
return transmute(poly8x8_t)_vqtbx4(
|
||||
transmute(int8x8_t)v,
|
||||
transmute(int8x16_t)t.x,
|
||||
transmute(int8x16_t)t.y,
|
||||
transmute(int8x16_t)t.z,
|
||||
transmute(int8x16_t)t.w,
|
||||
idx,
|
||||
)
|
||||
} else {
|
||||
v := simd.shuffle(v, v, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
t := poly8x16x4_t {
|
||||
simd.shuffle(t.x, t.x, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
simd.shuffle(t.y, t.y, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
simd.shuffle(t.z, t.z, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
simd.shuffle(t.w, t.w, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
}
|
||||
idx := simd.shuffle(idx, idx, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
c := transmute(poly8x8_t)_vqtbx4(
|
||||
transmute(int8x8_t)v,
|
||||
transmute(int8x16_t)t.x,
|
||||
transmute(int8x16_t)t.y,
|
||||
transmute(int8x16_t)t.z,
|
||||
transmute(int8x16_t)t.w,
|
||||
idx,
|
||||
)
|
||||
return simd.shuffle(c, c, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Extended Table Lookup.
|
||||
//
|
||||
// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbx4q_p8)
|
||||
@(require_results, enable_target_feature = "neon")
|
||||
vqtbx4q_p8 :: #force_inline proc "c" (v: poly8x16_t, t: poly8x16x4_t, idx: uint8x16_t) -> poly8x16_t {
|
||||
when ODIN_ENDIAN == .Little {
|
||||
return transmute(poly8x16_t)_vqtbx4q(
|
||||
transmute(int8x16_t)v,
|
||||
transmute(int8x16_t)t.x,
|
||||
transmute(int8x16_t)t.y,
|
||||
transmute(int8x16_t)t.z,
|
||||
transmute(int8x16_t)t.w,
|
||||
idx,
|
||||
)
|
||||
} else {
|
||||
v := simd.shuffle(v, v, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
t := poly8x16x4_t {
|
||||
simd.shuffle(t.x, t.x, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
simd.shuffle(t.y, t.y, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
simd.shuffle(t.z, t.z, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
simd.shuffle(t.w, t.w, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
|
||||
}
|
||||
idx := simd.shuffle(idx, idx, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
c := transmute(poly8x16_t)_vqtbx4q(
|
||||
transmute(int8x16_t)v,
|
||||
transmute(int8x16_t)t.x,
|
||||
transmute(int8x16_t)t.y,
|
||||
transmute(int8x16_t)t.z,
|
||||
transmute(int8x16_t)t.w,
|
||||
idx,
|
||||
)
|
||||
return simd.shuffle(c, c, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@(private, default_calling_convention = "none")
|
||||
|
||||
@@ -2244,7 +2244,10 @@ gb_internal LoadDirectiveResult check_load_directory_directive(CheckerContext *c
|
||||
String name = bd->name.string;
|
||||
GB_ASSERT(name == "load_directory");
|
||||
|
||||
if (ce->args.count != 1) {
|
||||
if (ce->args.count == 0) {
|
||||
error(ce->close, "'#%.*s' expects 1 argument, got 0", LIT(name));
|
||||
return LoadDirective_Error;
|
||||
} else if (ce->args.count != 1) {
|
||||
error(ce->args[0], "'#%.*s' expects 1 argument, got %td", LIT(name), ce->args.count);
|
||||
return LoadDirective_Error;
|
||||
}
|
||||
|
||||
@@ -3343,27 +3343,29 @@ gb_internal void check_comparison(CheckerContext *c, Ast *node, Operand *x, Oper
|
||||
case Token_Lt:
|
||||
case Token_LtEq:
|
||||
{
|
||||
// subset: (lhs & rhs) == lhs. a proper subset also requires lhs != rhs
|
||||
ExactValue lhs = x->value;
|
||||
ExactValue rhs = y->value;
|
||||
ExactValue res = exact_binary_operator_value(Token_And, lhs, rhs);
|
||||
res = exact_value_bool(compare_exact_values(op, res, lhs));
|
||||
ExactValue both = exact_binary_operator_value(Token_And, lhs, rhs);
|
||||
bool res = compare_exact_values(Token_CmpEq, both, lhs);
|
||||
if (op == Token_Lt) {
|
||||
res = exact_binary_operator_value(Token_And, res, exact_value_bool(compare_exact_values(op, lhs, rhs)));
|
||||
res = res && compare_exact_values(Token_NotEq, lhs, rhs);
|
||||
}
|
||||
x->value = res;
|
||||
x->value = exact_value_bool(res);
|
||||
break;
|
||||
}
|
||||
case Token_Gt:
|
||||
case Token_GtEq:
|
||||
{
|
||||
// superset: (lhs & rhs) == rhs
|
||||
ExactValue lhs = x->value;
|
||||
ExactValue rhs = y->value;
|
||||
ExactValue res = exact_binary_operator_value(Token_And, lhs, rhs);
|
||||
res = exact_value_bool(compare_exact_values(op, res, rhs));
|
||||
ExactValue both = exact_binary_operator_value(Token_And, lhs, rhs);
|
||||
bool res = compare_exact_values(Token_CmpEq, both, rhs);
|
||||
if (op == Token_Gt) {
|
||||
res = exact_binary_operator_value(Token_And, res, exact_value_bool(compare_exact_values(op, lhs, rhs)));
|
||||
res = res && compare_exact_values(Token_NotEq, lhs, rhs);
|
||||
}
|
||||
x->value = res;
|
||||
x->value = exact_value_bool(res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1368,7 +1368,7 @@ gb_internal void check_bit_set_type(CheckerContext *c, Type *type, Type *named_t
|
||||
gb_free(a, s.text);
|
||||
return;
|
||||
}
|
||||
if (!check_representable_as_constant(c, iv, t, nullptr)) {
|
||||
if (!check_representable_as_constant(c, jv, t, nullptr)) {
|
||||
gbAllocator a = heap_allocator();
|
||||
String s = big_int_to_string(a, &j);
|
||||
gbString ts = type_to_string(t);
|
||||
|
||||
@@ -1740,7 +1740,13 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *
|
||||
slice = lb_emit_load(p, slice);
|
||||
} else {
|
||||
count_ptr = lb_add_local_generated(p, t_int, false).addr;
|
||||
lb_emit_store(p, count_ptr, lb_slice_len(p, slice));
|
||||
if (t->kind == Type_Slice) {
|
||||
lb_emit_store(p, count_ptr, lb_slice_len(p, slice));
|
||||
} else if (t->kind == Type_DynamicArray) {
|
||||
lb_emit_store(p, count_ptr, lb_dynamic_array_len(p, slice));
|
||||
} else {
|
||||
GB_ASSERT_MSG(false, "Need to add support for this type.");
|
||||
}
|
||||
}
|
||||
data_ptr = lb_emit_struct_ev(p, slice, 0);
|
||||
break;
|
||||
|
||||
@@ -1446,11 +1446,13 @@ gb_internal bool is_type_ordered(Type *t) {
|
||||
return false;
|
||||
}
|
||||
gb_internal bool is_type_ordered_numeric(Type *t) {
|
||||
t = core_type(t);
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
switch (t->kind) {
|
||||
case Type_Basic:
|
||||
return (t->Basic.flags & BasicFlag_OrderedNumeric) != 0;
|
||||
case Type_Enum:
|
||||
return is_type_ordered_numeric(t->Enum.base_type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,60 @@ hex_decode :: proc(t: ^testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
hex_decode_into_buffer :: proc(t: ^testing.T) {
|
||||
for test in CASES {
|
||||
buffer := make([]u8, len(test[1]) / 2)
|
||||
defer delete(buffer)
|
||||
decoded, ok := hex.decode_into_buffer(transmute([]byte)test[1], buffer)
|
||||
testing.expect(t, ok, "decode_into_buffer: not ok")
|
||||
testing.expectf(
|
||||
t,
|
||||
ok,
|
||||
"decode: %q not ok",
|
||||
test[1],
|
||||
)
|
||||
testing.expectf(
|
||||
t,
|
||||
string(decoded) == test[0],
|
||||
"decode: %q -> %q (should be: %q)",
|
||||
test[1],
|
||||
string(decoded),
|
||||
test[0],
|
||||
)
|
||||
}
|
||||
|
||||
// destination buffer is larger
|
||||
for test in CASES {
|
||||
buffer := make([]u8, len(test[1]) / 2 + 1)
|
||||
defer delete(buffer)
|
||||
decoded, ok := hex.decode_into_buffer(transmute([]byte)test[1], buffer)
|
||||
testing.expect(t, ok, "decode_into_buffer: not ok")
|
||||
testing.expectf(
|
||||
t,
|
||||
ok,
|
||||
"decode: %q not ok",
|
||||
test[1],
|
||||
)
|
||||
testing.expectf(
|
||||
t,
|
||||
string(decoded) == test[0],
|
||||
"decode: %q -> %q (should be: %q)",
|
||||
test[1],
|
||||
string(decoded),
|
||||
test[0],
|
||||
)
|
||||
}
|
||||
|
||||
// destination buffer is too small
|
||||
for test in CASES {
|
||||
buffer := make([]u8, len(test[1]) / 2 - 1)
|
||||
defer delete(buffer)
|
||||
_, ok := hex.decode_into_buffer(transmute([]byte)test[1], buffer)
|
||||
testing.expect(t, !ok, "decode_into_buffer: should not be ok")
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
hex_decode_sequence :: proc(t: ^testing.T) {
|
||||
b, ok := hex.decode_sequence("0x23")
|
||||
@@ -83,4 +137,4 @@ hex_decode_sequence :: proc(t: ^testing.T) {
|
||||
|
||||
_, ok = hex.decode_sequence("123")
|
||||
testing.expect(t, !ok, "decode_sequence: 123 should be too long")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,4 +136,78 @@ bitwise_constant_folding_matches_runtime :: proc(t: ^testing.T) {
|
||||
testing.expect_value(t, 0 | -3, a | b)
|
||||
testing.expect_value(t, 0 ~ -3, a ~ b)
|
||||
}
|
||||
// `<=` and `<` on a `bit_set` are subset and proper subset, `>=` and `>` superset. The folder
|
||||
// asked `(lhs & rhs) <= lhs` where the definition is `(lhs & rhs) == lhs`, which is true for
|
||||
// any operands, so `<=` folded true unconditionally; `<` compounded it by requiring `lhs < rhs`
|
||||
// where it needs `lhs != rhs`. Under `when` this decides which declarations exist.
|
||||
}
|
||||
|
||||
@(test)
|
||||
bit_set_subset_folding_matches_runtime :: proc(t: ^testing.T) {
|
||||
B :: bit_set[0..<4]
|
||||
|
||||
{ // disjoint: neither a subset nor a superset
|
||||
a, b := B{0, 3}, B{0, 1}
|
||||
testing.expect_value(t, B{0, 3} <= B{0, 1}, a <= b)
|
||||
testing.expect_value(t, B{0, 3} <= B{0, 1}, false)
|
||||
testing.expect_value(t, B{0, 3} >= B{0, 1}, a >= b)
|
||||
testing.expect_value(t, B{0, 3} >= B{0, 1}, false)
|
||||
}
|
||||
{ // proper subset
|
||||
a, b := B{0}, B{0, 1}
|
||||
testing.expect_value(t, B{0} <= B{0, 1}, a <= b)
|
||||
testing.expect_value(t, B{0} <= B{0, 1}, true)
|
||||
testing.expect_value(t, B{0} < B{0, 1}, a < b)
|
||||
testing.expect_value(t, B{0} < B{0, 1}, true)
|
||||
}
|
||||
{ // equal: a subset but not a proper one
|
||||
a, b := B{0, 1}, B{0, 1}
|
||||
testing.expect_value(t, B{0, 1} <= B{0, 1}, a <= b)
|
||||
testing.expect_value(t, B{0, 1} <= B{0, 1}, true)
|
||||
testing.expect_value(t, B{0, 1} < B{0, 1}, a < b)
|
||||
testing.expect_value(t, B{0, 1} < B{0, 1}, false)
|
||||
}
|
||||
{ // superset
|
||||
a, b := B{0, 1}, B{0}
|
||||
testing.expect_value(t, B{0, 1} <= B{0}, a <= b)
|
||||
testing.expect_value(t, B{0, 1} <= B{0}, false)
|
||||
testing.expect_value(t, B{0, 1} > B{0}, a > b)
|
||||
testing.expect_value(t, B{0, 1} > B{0}, true)
|
||||
}
|
||||
{ // the empty set is a subset of everything, and a proper one unless both are empty
|
||||
a, b := B{}, B{0}
|
||||
testing.expect_value(t, B{} < B{0}, a < b)
|
||||
testing.expect_value(t, B{} < B{0}, true)
|
||||
}
|
||||
{
|
||||
a, b := B{}, B{}
|
||||
testing.expect_value(t, B{} <= B{}, a <= b)
|
||||
testing.expect_value(t, B{} <= B{}, true)
|
||||
testing.expect_value(t, B{} < B{}, a < b)
|
||||
testing.expect_value(t, B{} < B{}, false)
|
||||
}
|
||||
|
||||
// equality was never affected, so a fix here must not disturb it
|
||||
{
|
||||
a, b := B{0, 1}, B{1, 0}
|
||||
testing.expect_value(t, B{0, 1} == B{1, 0}, a == b)
|
||||
testing.expect_value(t, B{0, 1} == B{1, 0}, true)
|
||||
testing.expect_value(t, B{0, 1} != B{0}, a != B{0})
|
||||
}
|
||||
}
|
||||
|
||||
// a mis-folded subset test selects the wrong `when` arm, which changes which declarations exist
|
||||
@(test)
|
||||
bit_set_subset_folding_selects_the_right_when_arm :: proc(t: ^testing.T) {
|
||||
B :: bit_set[0..<4]
|
||||
|
||||
when (B{0} < B{0, 1}) { W1 :: 1 } else { W1 :: 0 }
|
||||
when (B{0, 3} <= B{0, 1}) { W2 :: 0 } else { W2 :: 1 }
|
||||
when (B{0, 1} <= B{0, 1}) { W3 :: 1 } else { W3 :: 0 }
|
||||
when (B{0, 1} > B{0}) { W4 :: 1 } else { W4 :: 0 }
|
||||
|
||||
testing.expect_value(t, W1, 1)
|
||||
testing.expect_value(t, W2, 1)
|
||||
testing.expect_value(t, W3, 1)
|
||||
testing.expect_value(t, W4, 1)
|
||||
}
|
||||
@@ -107,6 +107,13 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $($ODIN check ../test_issue_7304.odin -no-entry-point $COMMON_CHECK 2>&1 >/dev/null | grep -c "9223372036854775808 is not representable by int") -eq 1 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
clang -c ../test_issue_7010.c -o test_issue_7010_c.o
|
||||
$ODIN test ../test_issue_7010.odin $COMMON
|
||||
|
||||
|
||||
4
tests/issues/test_issue_7304.odin
Normal file
4
tests/issues/test_issue_7304.odin
Normal file
@@ -0,0 +1,4 @@
|
||||
// Tests issue #7304 https://github.com/odin-lang/Odin/issues/7304
|
||||
package test_issues
|
||||
|
||||
Bad_Bit_Set :: bit_set[-1 ..< 9223372036854775808]
|
||||
Reference in New Issue
Block a user