Remove UB from indeterminate value handling
Move SIMD operations on potentially-indeterminate Node16::index bytes into file-level assembly, where loading and operating on indeterminate values is well-defined (unlike C++). Restructure scalar fallback loops to iterate [0, numChildren) instead of [0, kMaxNodes). Fix TrivialSpan construction from indeterminate pointers in check::Job::init and insertPointWritesOrSorted to only construct when end.len > 0. Add MSan toolchain to the debug CI build to catch these issues going forward.
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#if defined(__x86_64__) && !defined(USE_SIMD_FALLBACK)
|
||||
|
||||
// SIMD operations on potentially-indeterminate Node16::index[16] bytes.
|
||||
// Implemented in file-level assembly (simd_x86_64.S) because loading and
|
||||
// operating on indeterminate values is UB in C++ but well-defined in
|
||||
// assembly. The caller must mask the returned bitfield to
|
||||
// [0, numChildren) before using it.
|
||||
//
|
||||
// Each function returns a 16-bit bitmask in the low 16 bits of a uint32_t
|
||||
// (upper 16 bits are zero). Bit i is set iff the condition holds at index i.
|
||||
|
||||
extern "C" {
|
||||
// Returns bit i set iff idx[i] == key
|
||||
uint32_t find_eq_16(const uint8_t idx[16], uint8_t key);
|
||||
// Returns bit i set iff idx[i] >= child
|
||||
uint32_t find_ge_16(const uint8_t idx[16], uint8_t child);
|
||||
// Returns bit i set iff begin <= idx[i] < end
|
||||
uint32_t mask_in_range_16(const uint8_t idx[16], uint8_t begin, uint8_t end);
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user