Made compilation with gcc and clang more strict.
Added additional compilation flags to gcc and clang builds. Adds -Wall -Wextra -Wno-long-long -Wshadow -Wundef -Wconversion -WNo-sign-conversion and -Wno-missing-field-initializers where appropriate. Does not add -Wundef to tests, because GTEST tests undefined macros all over the place.
This commit is contained in:
Родитель
43401d2ed0
Коммит
7a35473573
|
@ -81,6 +81,9 @@ function(default_compile_options TARGET)
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
target_compile_options(${TARGET} PRIVATE
|
target_compile_options(${TARGET} PRIVATE
|
||||||
-std=c++11 -fno-exceptions -fno-rtti)
|
-std=c++11 -fno-exceptions -fno-rtti)
|
||||||
|
target_compile_options(${TARGET} PRIVATE
|
||||||
|
-Wall -Wextra -Wno-long-long -Wshadow -Wundef -Wconversion
|
||||||
|
-Wno-sign-conversion)
|
||||||
# For good call stacks in profiles, keep the frame pointers.
|
# For good call stacks in profiles, keep the frame pointers.
|
||||||
if(NOT "${SPIRV_PERF}" STREQUAL "")
|
if(NOT "${SPIRV_PERF}" STREQUAL "")
|
||||||
target_compile_options(${TARGET} PRIVATE -fno-omit-frame-pointer)
|
target_compile_options(${TARGET} PRIVATE -fno-omit-frame-pointer)
|
||||||
|
@ -92,6 +95,9 @@ function(default_compile_options TARGET)
|
||||||
target_compile_options(${TARGET} PRIVATE
|
target_compile_options(${TARGET} PRIVATE
|
||||||
-fsanitize=${SPIRV_USE_SANITIZER})
|
-fsanitize=${SPIRV_USE_SANITIZER})
|
||||||
endif()
|
endif()
|
||||||
|
else()
|
||||||
|
target_compile_options(${TARGET} PRIVATE
|
||||||
|
-Wno-missing-field-initializers)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@ -231,6 +237,10 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES})
|
||||||
|
|
||||||
add_executable(UnitSPIRV ${TEST_SOURCES})
|
add_executable(UnitSPIRV ${TEST_SOURCES})
|
||||||
default_compile_options(UnitSPIRV)
|
default_compile_options(UnitSPIRV)
|
||||||
|
if(UNIX)
|
||||||
|
target_compile_options(UnitSPIRV PRIVATE
|
||||||
|
-Wno-undef)
|
||||||
|
endif()
|
||||||
target_include_directories(UnitSPIRV PRIVATE
|
target_include_directories(UnitSPIRV PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${gmock_SOURCE_DIR}/include ${gtest_SOURCE_DIR}/include)
|
${gmock_SOURCE_DIR}/include ${gtest_SOURCE_DIR}/include)
|
||||||
|
|
|
@ -102,7 +102,8 @@ class FloatProxy {
|
||||||
|
|
||||||
// This is helpful to have and is guaranteed not to stomp bits.
|
// This is helpful to have and is guaranteed not to stomp bits.
|
||||||
FloatProxy<T> operator-() const {
|
FloatProxy<T> operator-() const {
|
||||||
return data_ ^ (uint_type(0x1) << (sizeof(T) * 8 - 1));
|
return static_cast<uint_type>(data_ ^
|
||||||
|
(uint_type(0x1) << (sizeof(T) * 8 - 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the data as a floating point value.
|
// Returns the data as a floating point value.
|
||||||
|
@ -287,19 +288,21 @@ class HexFloat {
|
||||||
|
|
||||||
// Returns the bits associated with the value, without the leading sign bit.
|
// Returns the bits associated with the value, without the leading sign bit.
|
||||||
uint_type getUnsignedBits() const {
|
uint_type getUnsignedBits() const {
|
||||||
return spvutils::BitwiseCast<uint_type>(value_) & ~sign_mask;
|
return static_cast<uint_type>(spvutils::BitwiseCast<uint_type>(value_) &
|
||||||
|
~sign_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the bits associated with the exponent, shifted to start at the
|
// Returns the bits associated with the exponent, shifted to start at the
|
||||||
// lsb of the type.
|
// lsb of the type.
|
||||||
const uint_type getExponentBits() const {
|
const uint_type getExponentBits() const {
|
||||||
return (getBits() & exponent_mask) >> num_fraction_bits;
|
return static_cast<uint_type>((getBits() & exponent_mask) >>
|
||||||
|
num_fraction_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the exponent in unbiased form. This is the exponent in the
|
// Returns the exponent in unbiased form. This is the exponent in the
|
||||||
// human-friendly form.
|
// human-friendly form.
|
||||||
const int_type getUnbiasedExponent() const {
|
const int_type getUnbiasedExponent() const {
|
||||||
return (static_cast<int_type>(getExponentBits()) - exponent_bias);
|
return static_cast<int_type>(getExponentBits() - exponent_bias);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns just the significand bits from the value.
|
// Returns just the significand bits from the value.
|
||||||
|
@ -317,8 +320,8 @@ class HexFloat {
|
||||||
if (exp == min_exponent) { // We are in denorm land.
|
if (exp == min_exponent) { // We are in denorm land.
|
||||||
uint_type significand_bits = getSignificandBits();
|
uint_type significand_bits = getSignificandBits();
|
||||||
while ((significand_bits & (first_exponent_bit >> 1)) == 0) {
|
while ((significand_bits & (first_exponent_bit >> 1)) == 0) {
|
||||||
significand_bits <<= 1;
|
significand_bits = static_cast<uint_type>(significand_bits << 1);
|
||||||
exp -= 1;
|
exp = static_cast<int_type>(exp - 1);
|
||||||
}
|
}
|
||||||
significand_bits &= fraction_encode_mask;
|
significand_bits &= fraction_encode_mask;
|
||||||
}
|
}
|
||||||
|
@ -330,7 +333,7 @@ class HexFloat {
|
||||||
int_type unbiased_exponent = getUnbiasedNormalizedExponent();
|
int_type unbiased_exponent = getUnbiasedNormalizedExponent();
|
||||||
uint_type significand = getSignificandBits();
|
uint_type significand = getSignificandBits();
|
||||||
for (int_type i = unbiased_exponent; i <= min_exponent; ++i) {
|
for (int_type i = unbiased_exponent; i <= min_exponent; ++i) {
|
||||||
significand <<= 1;
|
significand = static_cast<uint_type>(significand << 1);
|
||||||
}
|
}
|
||||||
significand &= fraction_encode_mask;
|
significand &= fraction_encode_mask;
|
||||||
return significand;
|
return significand;
|
||||||
|
@ -361,31 +364,32 @@ class HexFloat {
|
||||||
// the significand is not zero.
|
// the significand is not zero.
|
||||||
significand_is_zero = false;
|
significand_is_zero = false;
|
||||||
significand |= first_exponent_bit;
|
significand |= first_exponent_bit;
|
||||||
significand >>= 1;
|
significand = static_cast<uint_type>(significand >> 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (exponent < min_exponent) {
|
while (exponent < min_exponent) {
|
||||||
significand >>= 1;
|
significand = static_cast<uint_type>(significand >> 1);
|
||||||
++exponent;
|
++exponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exponent == min_exponent) {
|
if (exponent == min_exponent) {
|
||||||
if (significand == 0 && !significand_is_zero && round_denorm_up) {
|
if (significand == 0 && !significand_is_zero && round_denorm_up) {
|
||||||
significand = 0x1;
|
significand = static_cast<uint_type>(0x1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint_type new_value = 0;
|
uint_type new_value = 0;
|
||||||
if (negative) {
|
if (negative) {
|
||||||
new_value |= sign_mask;
|
new_value = static_cast<uint_type>(new_value | sign_mask);
|
||||||
}
|
}
|
||||||
exponent += exponent_bias;
|
exponent = static_cast<int_type>(exponent + exponent_bias);
|
||||||
assert(exponent >= 0);
|
assert(exponent >= 0);
|
||||||
|
|
||||||
// put it all together
|
// put it all together
|
||||||
exponent = (exponent << exponent_left_shift) & exponent_mask;
|
exponent = static_cast<uint_type>((exponent << exponent_left_shift) &
|
||||||
significand &= fraction_encode_mask;
|
exponent_mask);
|
||||||
new_value |= exponent | significand;
|
significand = static_cast<uint_type>(significand & fraction_encode_mask);
|
||||||
|
new_value = static_cast<uint_type>(new_value | (exponent | significand));
|
||||||
value_ = BitwiseCast<T>(new_value);
|
value_ = BitwiseCast<T>(new_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,14 +401,14 @@ class HexFloat {
|
||||||
// for a valid significand.
|
// for a valid significand.
|
||||||
static uint_type incrementSignificand(uint_type significand,
|
static uint_type incrementSignificand(uint_type significand,
|
||||||
uint_type to_increment, bool* carry) {
|
uint_type to_increment, bool* carry) {
|
||||||
significand += to_increment;
|
significand = static_cast<uint_type>(significand + to_increment);
|
||||||
*carry = false;
|
*carry = false;
|
||||||
if (significand & first_exponent_bit) {
|
if (significand & first_exponent_bit) {
|
||||||
*carry = true;
|
*carry = true;
|
||||||
// The implicit 1-bit will have carried, so we should zero-out the
|
// The implicit 1-bit will have carried, so we should zero-out the
|
||||||
// top bit and shift back.
|
// top bit and shift back.
|
||||||
significand &= ~first_exponent_bit;
|
significand = static_cast<uint_type>(significand & ~first_exponent_bit);
|
||||||
significand >>= 1;
|
significand = static_cast<uint_type>(significand >> 1);
|
||||||
}
|
}
|
||||||
return significand;
|
return significand;
|
||||||
}
|
}
|
||||||
|
@ -416,22 +420,30 @@ class HexFloat {
|
||||||
|
|
||||||
template <int_type N, typename enable = void>
|
template <int_type N, typename enable = void>
|
||||||
struct negatable_left_shift {
|
struct negatable_left_shift {
|
||||||
static uint_type val(uint_type val) { return val >> -N; }
|
static uint_type val(uint_type val) {
|
||||||
|
return static_cast<uint_type>(val >> -N);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int_type N>
|
template <int_type N>
|
||||||
struct negatable_left_shift<N, typename std::enable_if<N >= 0>::type> {
|
struct negatable_left_shift<N, typename std::enable_if<N >= 0>::type> {
|
||||||
static uint_type val(uint_type val) { return val << N; }
|
static uint_type val(uint_type val) {
|
||||||
|
return static_cast<uint_type>(val << N);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int_type N, typename enable = void>
|
template <int_type N, typename enable = void>
|
||||||
struct negatable_right_shift {
|
struct negatable_right_shift {
|
||||||
static uint_type val(uint_type val) { return val << -N; }
|
static uint_type val(uint_type val) {
|
||||||
|
return static_cast<uint_type>(val << -N);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int_type N>
|
template <int_type N>
|
||||||
struct negatable_right_shift<N, typename std::enable_if<N >= 0>::type> {
|
struct negatable_right_shift<N, typename std::enable_if<N >= 0>::type> {
|
||||||
static uint_type val(uint_type val) { return val >> N; }
|
static uint_type val(uint_type val) {
|
||||||
|
return static_cast<uint_type>(val >> N);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns the significand, rounded to fit in a significand in
|
// Returns the significand, rounded to fit in a significand in
|
||||||
|
@ -465,9 +477,9 @@ class HexFloat {
|
||||||
uint_type significand = getNormalizedSignificand();
|
uint_type significand = getNormalizedSignificand();
|
||||||
// If we are up-casting, then we just have to shift to the right location.
|
// If we are up-casting, then we just have to shift to the right location.
|
||||||
if (num_throwaway_bits <= 0) {
|
if (num_throwaway_bits <= 0) {
|
||||||
out_val = significand;
|
out_val = static_cast<other_uint_type>(significand);
|
||||||
uint_type shift_amount = -num_throwaway_bits;
|
uint_type shift_amount = -num_throwaway_bits;
|
||||||
out_val <<= shift_amount;
|
out_val = static_cast<other_uint_type>(out_val << shift_amount);
|
||||||
return out_val;
|
return out_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,10 +560,10 @@ class HexFloat {
|
||||||
if (exponent == min_exponent) {
|
if (exponent == min_exponent) {
|
||||||
// If we are denormal, normalize the exponent, so that we can encode
|
// If we are denormal, normalize the exponent, so that we can encode
|
||||||
// easily.
|
// easily.
|
||||||
exponent += 1;
|
exponent = static_cast<int_type>(exponent + 1);
|
||||||
for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0;
|
for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0;
|
||||||
check_bit >>= 1) {
|
check_bit = static_cast<uint_type>(check_bit >> 1)) {
|
||||||
exponent -= 1;
|
exponent = static_cast<int_type>(exponent - 1);
|
||||||
if (check_bit & significand) break;
|
if (check_bit & significand) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -590,11 +602,12 @@ class HexFloat {
|
||||||
bool round_underflow_up =
|
bool round_underflow_up =
|
||||||
isNegative() ? round_dir == round_direction::kToNegativeInfinity
|
isNegative() ? round_dir == round_direction::kToNegativeInfinity
|
||||||
: round_dir == round_direction::kToPositiveInfinity;
|
: round_dir == round_direction::kToPositiveInfinity;
|
||||||
|
using other_int_type = typename other_T::int_type;
|
||||||
// setFromSignUnbiasedExponentAndNormalizedSignificand will
|
// setFromSignUnbiasedExponentAndNormalizedSignificand will
|
||||||
// zero out any underflowing value (but retain the sign).
|
// zero out any underflowing value (but retain the sign).
|
||||||
other.setFromSignUnbiasedExponentAndNormalizedSignificand(
|
other.setFromSignUnbiasedExponentAndNormalizedSignificand(
|
||||||
negate, exponent, rounded_significand, round_underflow_up);
|
negate, static_cast<other_int_type>(exponent), rounded_significand,
|
||||||
|
round_underflow_up);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,18 +654,18 @@ std::ostream& operator<<(std::ostream& os, const HexFloat<T, Traits>& value) {
|
||||||
|
|
||||||
const uint_type bits = spvutils::BitwiseCast<uint_type>(value.value());
|
const uint_type bits = spvutils::BitwiseCast<uint_type>(value.value());
|
||||||
const char* const sign = (bits & HF::sign_mask) ? "-" : "";
|
const char* const sign = (bits & HF::sign_mask) ? "-" : "";
|
||||||
const uint_type exponent =
|
const uint_type exponent = static_cast<uint_type>(
|
||||||
(bits & HF::exponent_mask) >> HF::num_fraction_bits;
|
(bits & HF::exponent_mask) >> HF::num_fraction_bits);
|
||||||
|
|
||||||
uint_type fraction = (bits & HF::fraction_encode_mask)
|
uint_type fraction = static_cast<uint_type>((bits & HF::fraction_encode_mask)
|
||||||
<< HF::num_overflow_bits;
|
<< HF::num_overflow_bits);
|
||||||
|
|
||||||
const bool is_zero = exponent == 0 && fraction == 0;
|
const bool is_zero = exponent == 0 && fraction == 0;
|
||||||
const bool is_denorm = exponent == 0 && !is_zero;
|
const bool is_denorm = exponent == 0 && !is_zero;
|
||||||
|
|
||||||
// exponent contains the biased exponent we have to convert it back into
|
// exponent contains the biased exponent we have to convert it back into
|
||||||
// the normal range.
|
// the normal range.
|
||||||
int_type int_exponent = static_cast<int_type>(exponent) - HF::exponent_bias;
|
int_type int_exponent = static_cast<int_type>(exponent - HF::exponent_bias);
|
||||||
// If the number is all zeros, then we actually have to NOT shift the
|
// If the number is all zeros, then we actually have to NOT shift the
|
||||||
// exponent.
|
// exponent.
|
||||||
int_exponent = is_zero ? 0 : int_exponent;
|
int_exponent = is_zero ? 0 : int_exponent;
|
||||||
|
@ -662,12 +675,12 @@ std::ostream& operator<<(std::ostream& os, const HexFloat<T, Traits>& value) {
|
||||||
|
|
||||||
if (is_denorm) {
|
if (is_denorm) {
|
||||||
while ((fraction & HF::fraction_top_bit) == 0) {
|
while ((fraction & HF::fraction_top_bit) == 0) {
|
||||||
fraction <<= 1;
|
fraction = static_cast<uint_type>(fraction << 1);
|
||||||
int_exponent -= 1;
|
int_exponent = static_cast<int_type>(int_exponent - 1);
|
||||||
}
|
}
|
||||||
// Since this is denormalized, we have to consume the leading 1 since it
|
// Since this is denormalized, we have to consume the leading 1 since it
|
||||||
// will end up being implicit.
|
// will end up being implicit.
|
||||||
fraction <<= 1; // eat the leading 1
|
fraction = static_cast<uint_type>(fraction << 1); // eat the leading 1
|
||||||
fraction &= HF::fraction_represent_mask;
|
fraction &= HF::fraction_represent_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,7 +689,7 @@ std::ostream& operator<<(std::ostream& os, const HexFloat<T, Traits>& value) {
|
||||||
// fractional part.
|
// fractional part.
|
||||||
while (fraction_nibbles > 0 && (fraction & 0xF) == 0) {
|
while (fraction_nibbles > 0 && (fraction & 0xF) == 0) {
|
||||||
// Shift off any trailing values;
|
// Shift off any trailing values;
|
||||||
fraction >>= 4;
|
fraction = static_cast<uint_type>(fraction >> 4);
|
||||||
--fraction_nibbles;
|
--fraction_nibbles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -828,8 +841,11 @@ std::istream& operator>>(std::istream& is, HexFloat<T, Traits>& value) {
|
||||||
if (bits_written) {
|
if (bits_written) {
|
||||||
// If we are here the bits represented belong in the fractional
|
// If we are here the bits represented belong in the fractional
|
||||||
// part of the float, and we have to adjust the exponent accordingly.
|
// part of the float, and we have to adjust the exponent accordingly.
|
||||||
fraction |= write_bit << (HF::top_bit_left_shift - fraction_index++);
|
fraction =
|
||||||
exponent += 1;
|
fraction |
|
||||||
|
static_cast<uint_type>(
|
||||||
|
write_bit << (HF::top_bit_left_shift - fraction_index++));
|
||||||
|
exponent = static_cast<int_type>(exponent + 1);
|
||||||
}
|
}
|
||||||
bits_written |= write_bit != 0;
|
bits_written |= write_bit != 0;
|
||||||
}
|
}
|
||||||
|
@ -855,9 +871,12 @@ std::istream& operator>>(std::istream& is, HexFloat<T, Traits>& value) {
|
||||||
// Handle modifying the exponent here this way we can handle
|
// Handle modifying the exponent here this way we can handle
|
||||||
// an arbitrary number of hex values without overflowing our
|
// an arbitrary number of hex values without overflowing our
|
||||||
// integer.
|
// integer.
|
||||||
exponent -= 1;
|
exponent = static_cast<int_type>(exponent - 1);
|
||||||
} else {
|
} else {
|
||||||
fraction |= write_bit << (HF::top_bit_left_shift - fraction_index++);
|
fraction =
|
||||||
|
fraction |
|
||||||
|
static_cast<uint_type>(
|
||||||
|
write_bit << (HF::top_bit_left_shift - fraction_index++));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -883,8 +902,9 @@ std::istream& operator>>(std::istream& is, HexFloat<T, Traits>& value) {
|
||||||
exponent_sign = (next_char == '-') ? -1 : 1;
|
exponent_sign = (next_char == '-') ? -1 : 1;
|
||||||
} else if (::isdigit(next_char)) {
|
} else if (::isdigit(next_char)) {
|
||||||
// Hex-floats express their exponent as decimal.
|
// Hex-floats express their exponent as decimal.
|
||||||
written_exponent *= 10;
|
written_exponent = static_cast<int_type>(written_exponent * 10);
|
||||||
written_exponent += next_char - '0';
|
written_exponent =
|
||||||
|
static_cast<int_type>(written_exponent + (next_char - '0'));
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -892,19 +912,19 @@ std::istream& operator>>(std::istream& is, HexFloat<T, Traits>& value) {
|
||||||
next_char = is.peek();
|
next_char = is.peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
written_exponent *= exponent_sign;
|
written_exponent = static_cast<int_type>(written_exponent * exponent_sign);
|
||||||
exponent += written_exponent;
|
exponent = static_cast<int_type>(exponent + written_exponent);
|
||||||
|
|
||||||
bool is_zero = is_denorm && (fraction == 0);
|
bool is_zero = is_denorm && (fraction == 0);
|
||||||
if (is_denorm && !is_zero) {
|
if (is_denorm && !is_zero) {
|
||||||
fraction <<= 1;
|
fraction = static_cast<uint_type>(fraction << 1);
|
||||||
exponent -= 1;
|
exponent = static_cast<int_type>(exponent - 1);
|
||||||
} else if (is_zero) {
|
} else if (is_zero) {
|
||||||
exponent = 0;
|
exponent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exponent <= 0 && !is_zero) {
|
if (exponent <= 0 && !is_zero) {
|
||||||
fraction >>= 1;
|
fraction = static_cast<uint_type>(fraction >> 1);
|
||||||
fraction |= static_cast<uint_type>(1) << HF::top_bit_left_shift;
|
fraction |= static_cast<uint_type>(1) << HF::top_bit_left_shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -915,8 +935,8 @@ std::istream& operator>>(std::istream& is, HexFloat<T, Traits>& value) {
|
||||||
|
|
||||||
// Handle actual denorm numbers
|
// Handle actual denorm numbers
|
||||||
while (exponent < 0 && !is_zero) {
|
while (exponent < 0 && !is_zero) {
|
||||||
fraction >>= 1;
|
fraction = static_cast<uint_type>(fraction >> 1);
|
||||||
exponent += 1;
|
exponent = static_cast<int_type>(exponent + 1);
|
||||||
|
|
||||||
fraction &= HF::fraction_encode_mask;
|
fraction &= HF::fraction_encode_mask;
|
||||||
if (fraction == 0) {
|
if (fraction == 0) {
|
||||||
|
@ -932,10 +952,14 @@ std::istream& operator>>(std::istream& is, HexFloat<T, Traits>& value) {
|
||||||
fraction = 0;
|
fraction = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint_type output_bits = static_cast<uint_type>(negate_value ? 1 : 0)
|
uint_type output_bits = static_cast<uint_type>(
|
||||||
<< HF::top_bit_left_shift;
|
static_cast<uint_type>(negate_value ? 1 : 0) << HF::top_bit_left_shift);
|
||||||
output_bits |= fraction;
|
output_bits |= fraction;
|
||||||
output_bits |= (exponent << HF::exponent_left_shift) & HF::exponent_mask;
|
|
||||||
|
uint_type shifted_exponent = static_cast<uint_type>(
|
||||||
|
static_cast<uint_type>(exponent << HF::exponent_left_shift) &
|
||||||
|
HF::exponent_mask);
|
||||||
|
output_bits |= shifted_exponent;
|
||||||
|
|
||||||
T output_float = spvutils::BitwiseCast<T>(output_bits);
|
T output_float = spvutils::BitwiseCast<T>(output_bits);
|
||||||
value.set_value(output_float);
|
value.set_value(output_float);
|
||||||
|
|
|
@ -40,7 +40,6 @@ using BinaryDestroySomething = spvtest::TextToBinaryTest;
|
||||||
|
|
||||||
// Checks safety of destroying a validly constructed binary.
|
// Checks safety of destroying a validly constructed binary.
|
||||||
TEST_F(BinaryDestroySomething, Default) {
|
TEST_F(BinaryDestroySomething, Default) {
|
||||||
spv_context context = spvContextCreate();
|
|
||||||
// Use a binary object constructed by the API instead of rolling our own.
|
// Use a binary object constructed by the API instead of rolling our own.
|
||||||
SetText("OpSource OpenCL_C 120");
|
SetText("OpSource OpenCL_C 120");
|
||||||
spv_binary my_binary = nullptr;
|
spv_binary my_binary = nullptr;
|
||||||
|
@ -48,7 +47,6 @@ TEST_F(BinaryDestroySomething, Default) {
|
||||||
&my_binary, &diagnostic));
|
&my_binary, &diagnostic));
|
||||||
ASSERT_NE(nullptr, my_binary);
|
ASSERT_NE(nullptr, my_binary);
|
||||||
spvBinaryDestroy(my_binary);
|
spvBinaryDestroy(my_binary);
|
||||||
spvContextDestroy(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
|
@ -70,10 +70,10 @@ TEST_F(BinaryHeaderGet, Default) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BinaryHeaderGet, InvalidCode) {
|
TEST_F(BinaryHeaderGet, InvalidCode) {
|
||||||
spv_const_binary_t binary = {nullptr, 0};
|
spv_const_binary_t my_binary = {nullptr, 0};
|
||||||
spv_header_t header;
|
spv_header_t header;
|
||||||
ASSERT_EQ(SPV_ERROR_INVALID_BINARY,
|
ASSERT_EQ(SPV_ERROR_INVALID_BINARY,
|
||||||
spvBinaryHeaderGet(&binary, SPV_ENDIANNESS_LITTLE, &header));
|
spvBinaryHeaderGet(&my_binary, SPV_ENDIANNESS_LITTLE, &header));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BinaryHeaderGet, InvalidPointerHeader) {
|
TEST_F(BinaryHeaderGet, InvalidPointerHeader) {
|
||||||
|
|
|
@ -204,9 +204,9 @@ ParsedInstruction MakeParsedInt32TypeInstruction(uint32_t result_id) {
|
||||||
|
|
||||||
class BinaryParseTest : public spvtest::TextToBinaryTestBase<::testing::Test> {
|
class BinaryParseTest : public spvtest::TextToBinaryTestBase<::testing::Test> {
|
||||||
protected:
|
protected:
|
||||||
void Parse(const SpirvVector& binary, spv_result_t expected_result) {
|
void Parse(const SpirvVector& words, spv_result_t expected_result) {
|
||||||
EXPECT_EQ(expected_result,
|
EXPECT_EQ(expected_result,
|
||||||
spvBinaryParse(context, &client_, binary.data(), binary.size(),
|
spvBinaryParse(context, &client_, words.data(), words.size(),
|
||||||
invoke_header, invoke_instruction, &diagnostic_));
|
invoke_header, invoke_instruction, &diagnostic_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,42 +224,42 @@ class BinaryParseTest : public spvtest::TextToBinaryTestBase<::testing::Test> {
|
||||||
bound, 0 /*reserved*/))
|
bound, 0 /*reserved*/))
|
||||||
|
|
||||||
TEST_F(BinaryParseTest, EmptyModuleHasValidHeaderAndNoInstructionCallbacks) {
|
TEST_F(BinaryParseTest, EmptyModuleHasValidHeaderAndNoInstructionCallbacks) {
|
||||||
const auto binary = CompileSuccessfully("");
|
const auto words= CompileSuccessfully("");
|
||||||
EXPECT_HEADER(1).WillOnce(Return(SPV_SUCCESS));
|
EXPECT_HEADER(1).WillOnce(Return(SPV_SUCCESS));
|
||||||
EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback.
|
EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback.
|
||||||
Parse(binary, SPV_SUCCESS);
|
Parse(words, SPV_SUCCESS);
|
||||||
EXPECT_EQ(nullptr, diagnostic_);
|
EXPECT_EQ(nullptr, diagnostic_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BinaryParseTest,
|
TEST_F(BinaryParseTest,
|
||||||
ModuleWithSingleInstructionHasValidHeaderAndInstructionCallback) {
|
ModuleWithSingleInstructionHasValidHeaderAndInstructionCallback) {
|
||||||
const auto binary = CompileSuccessfully("%1 = OpTypeVoid");
|
const auto words = CompileSuccessfully("%1 = OpTypeVoid");
|
||||||
InSequence calls_expected_in_specific_order;
|
InSequence calls_expected_in_specific_order;
|
||||||
EXPECT_HEADER(2).WillOnce(Return(SPV_SUCCESS));
|
EXPECT_HEADER(2).WillOnce(Return(SPV_SUCCESS));
|
||||||
EXPECT_CALL(client_, Instruction(MakeParsedVoidTypeInstruction(1)))
|
EXPECT_CALL(client_, Instruction(MakeParsedVoidTypeInstruction(1)))
|
||||||
.WillOnce(Return(SPV_SUCCESS));
|
.WillOnce(Return(SPV_SUCCESS));
|
||||||
Parse(binary, SPV_SUCCESS);
|
Parse(words, SPV_SUCCESS);
|
||||||
EXPECT_EQ(nullptr, diagnostic_);
|
EXPECT_EQ(nullptr, diagnostic_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BinaryParseTest, NullHeaderCallbackIsIgnored) {
|
TEST_F(BinaryParseTest, NullHeaderCallbackIsIgnored) {
|
||||||
const auto binary = CompileSuccessfully("%1 = OpTypeVoid");
|
const auto words = CompileSuccessfully("%1 = OpTypeVoid");
|
||||||
EXPECT_CALL(client_, Header(_, _, _, _, _, _))
|
EXPECT_CALL(client_, Header(_, _, _, _, _, _))
|
||||||
.Times(0); // No header callback.
|
.Times(0); // No header callback.
|
||||||
EXPECT_CALL(client_, Instruction(MakeParsedVoidTypeInstruction(1)))
|
EXPECT_CALL(client_, Instruction(MakeParsedVoidTypeInstruction(1)))
|
||||||
.WillOnce(Return(SPV_SUCCESS));
|
.WillOnce(Return(SPV_SUCCESS));
|
||||||
EXPECT_EQ(SPV_SUCCESS,
|
EXPECT_EQ(SPV_SUCCESS,
|
||||||
spvBinaryParse(context, &client_, binary.data(), binary.size(),
|
spvBinaryParse(context, &client_, words.data(), words.size(),
|
||||||
nullptr, invoke_instruction, &diagnostic_));
|
nullptr, invoke_instruction, &diagnostic_));
|
||||||
EXPECT_EQ(nullptr, diagnostic_);
|
EXPECT_EQ(nullptr, diagnostic_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BinaryParseTest, NullInstructionCallbackIsIgnored) {
|
TEST_F(BinaryParseTest, NullInstructionCallbackIsIgnored) {
|
||||||
const auto binary = CompileSuccessfully("%1 = OpTypeVoid");
|
const auto words = CompileSuccessfully("%1 = OpTypeVoid");
|
||||||
EXPECT_HEADER((2)).WillOnce(Return(SPV_SUCCESS));
|
EXPECT_HEADER((2)).WillOnce(Return(SPV_SUCCESS));
|
||||||
EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback.
|
EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback.
|
||||||
EXPECT_EQ(SPV_SUCCESS,
|
EXPECT_EQ(SPV_SUCCESS,
|
||||||
spvBinaryParse(context, &client_, binary.data(), binary.size(),
|
spvBinaryParse(context, &client_, words.data(), words.size(),
|
||||||
invoke_header, nullptr, &diagnostic_));
|
invoke_header, nullptr, &diagnostic_));
|
||||||
EXPECT_EQ(nullptr, diagnostic_);
|
EXPECT_EQ(nullptr, diagnostic_);
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ TEST_F(BinaryParseTest, NullInstructionCallbackIsIgnored) {
|
||||||
// spv_parsed_instruction_t struct: words, num_words, opcode, result_id,
|
// spv_parsed_instruction_t struct: words, num_words, opcode, result_id,
|
||||||
// operands, num_operands.
|
// operands, num_operands.
|
||||||
TEST_F(BinaryParseTest, TwoScalarTypesGenerateTwoInstructionCallbacks) {
|
TEST_F(BinaryParseTest, TwoScalarTypesGenerateTwoInstructionCallbacks) {
|
||||||
const auto binary = CompileSuccessfully(
|
const auto words = CompileSuccessfully(
|
||||||
"%1 = OpTypeVoid "
|
"%1 = OpTypeVoid "
|
||||||
"%2 = OpTypeInt 32 1");
|
"%2 = OpTypeInt 32 1");
|
||||||
InSequence calls_expected_in_specific_order;
|
InSequence calls_expected_in_specific_order;
|
||||||
|
@ -279,40 +279,40 @@ TEST_F(BinaryParseTest, TwoScalarTypesGenerateTwoInstructionCallbacks) {
|
||||||
.WillOnce(Return(SPV_SUCCESS));
|
.WillOnce(Return(SPV_SUCCESS));
|
||||||
EXPECT_CALL(client_, Instruction(MakeParsedInt32TypeInstruction(2)))
|
EXPECT_CALL(client_, Instruction(MakeParsedInt32TypeInstruction(2)))
|
||||||
.WillOnce(Return(SPV_SUCCESS));
|
.WillOnce(Return(SPV_SUCCESS));
|
||||||
Parse(binary, SPV_SUCCESS);
|
Parse(words, SPV_SUCCESS);
|
||||||
EXPECT_EQ(nullptr, diagnostic_);
|
EXPECT_EQ(nullptr, diagnostic_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BinaryParseTest, EarlyReturnWithZeroPassingCallbacks) {
|
TEST_F(BinaryParseTest, EarlyReturnWithZeroPassingCallbacks) {
|
||||||
const auto binary = CompileSuccessfully(
|
const auto words = CompileSuccessfully(
|
||||||
"%1 = OpTypeVoid "
|
"%1 = OpTypeVoid "
|
||||||
"%2 = OpTypeInt 32 1");
|
"%2 = OpTypeInt 32 1");
|
||||||
InSequence calls_expected_in_specific_order;
|
InSequence calls_expected_in_specific_order;
|
||||||
EXPECT_HEADER(3).WillOnce(Return(SPV_ERROR_INVALID_BINARY));
|
EXPECT_HEADER(3).WillOnce(Return(SPV_ERROR_INVALID_BINARY));
|
||||||
// Early exit means no calls to Instruction().
|
// Early exit means no calls to Instruction().
|
||||||
EXPECT_CALL(client_, Instruction(_)).Times(0);
|
EXPECT_CALL(client_, Instruction(_)).Times(0);
|
||||||
Parse(binary, SPV_ERROR_INVALID_BINARY);
|
Parse(words, SPV_ERROR_INVALID_BINARY);
|
||||||
// On error, the binary parser doesn't generate its own diagnostics.
|
// On error, the binary parser doesn't generate its own diagnostics.
|
||||||
EXPECT_EQ(nullptr, diagnostic_);
|
EXPECT_EQ(nullptr, diagnostic_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BinaryParseTest,
|
TEST_F(BinaryParseTest,
|
||||||
EarlyReturnWithZeroPassingCallbacksAndSpecifiedResultCode) {
|
EarlyReturnWithZeroPassingCallbacksAndSpecifiedResultCode) {
|
||||||
const auto binary = CompileSuccessfully(
|
const auto words = CompileSuccessfully(
|
||||||
"%1 = OpTypeVoid "
|
"%1 = OpTypeVoid "
|
||||||
"%2 = OpTypeInt 32 1");
|
"%2 = OpTypeInt 32 1");
|
||||||
InSequence calls_expected_in_specific_order;
|
InSequence calls_expected_in_specific_order;
|
||||||
EXPECT_HEADER(3).WillOnce(Return(SPV_REQUESTED_TERMINATION));
|
EXPECT_HEADER(3).WillOnce(Return(SPV_REQUESTED_TERMINATION));
|
||||||
// Early exit means no calls to Instruction().
|
// Early exit means no calls to Instruction().
|
||||||
EXPECT_CALL(client_, Instruction(_)).Times(0);
|
EXPECT_CALL(client_, Instruction(_)).Times(0);
|
||||||
Parse(binary, SPV_REQUESTED_TERMINATION);
|
Parse(words, SPV_REQUESTED_TERMINATION);
|
||||||
// On early termination, the binary parser doesn't generate its own
|
// On early termination, the binary parser doesn't generate its own
|
||||||
// diagnostics.
|
// diagnostics.
|
||||||
EXPECT_EQ(nullptr, diagnostic_);
|
EXPECT_EQ(nullptr, diagnostic_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BinaryParseTest, EarlyReturnWithOnePassingCallback) {
|
TEST_F(BinaryParseTest, EarlyReturnWithOnePassingCallback) {
|
||||||
const auto binary = CompileSuccessfully(
|
const auto words = CompileSuccessfully(
|
||||||
"%1 = OpTypeVoid "
|
"%1 = OpTypeVoid "
|
||||||
"%2 = OpTypeInt 32 1 "
|
"%2 = OpTypeInt 32 1 "
|
||||||
"%3 = OpTypeFloat 32");
|
"%3 = OpTypeFloat 32");
|
||||||
|
@ -320,14 +320,14 @@ TEST_F(BinaryParseTest, EarlyReturnWithOnePassingCallback) {
|
||||||
EXPECT_HEADER(4).WillOnce(Return(SPV_SUCCESS));
|
EXPECT_HEADER(4).WillOnce(Return(SPV_SUCCESS));
|
||||||
EXPECT_CALL(client_, Instruction(MakeParsedVoidTypeInstruction(1)))
|
EXPECT_CALL(client_, Instruction(MakeParsedVoidTypeInstruction(1)))
|
||||||
.WillOnce(Return(SPV_REQUESTED_TERMINATION));
|
.WillOnce(Return(SPV_REQUESTED_TERMINATION));
|
||||||
Parse(binary, SPV_REQUESTED_TERMINATION);
|
Parse(words, SPV_REQUESTED_TERMINATION);
|
||||||
// On early termination, the binary parser doesn't generate its own
|
// On early termination, the binary parser doesn't generate its own
|
||||||
// diagnostics.
|
// diagnostics.
|
||||||
EXPECT_EQ(nullptr, diagnostic_);
|
EXPECT_EQ(nullptr, diagnostic_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BinaryParseTest, EarlyReturnWithTwoPassingCallbacks) {
|
TEST_F(BinaryParseTest, EarlyReturnWithTwoPassingCallbacks) {
|
||||||
const auto binary = CompileSuccessfully(
|
const auto words = CompileSuccessfully(
|
||||||
"%1 = OpTypeVoid "
|
"%1 = OpTypeVoid "
|
||||||
"%2 = OpTypeInt 32 1 "
|
"%2 = OpTypeInt 32 1 "
|
||||||
"%3 = OpTypeFloat 32");
|
"%3 = OpTypeFloat 32");
|
||||||
|
@ -337,7 +337,7 @@ TEST_F(BinaryParseTest, EarlyReturnWithTwoPassingCallbacks) {
|
||||||
.WillOnce(Return(SPV_SUCCESS));
|
.WillOnce(Return(SPV_SUCCESS));
|
||||||
EXPECT_CALL(client_, Instruction(MakeParsedInt32TypeInstruction(2)))
|
EXPECT_CALL(client_, Instruction(MakeParsedInt32TypeInstruction(2)))
|
||||||
.WillOnce(Return(SPV_REQUESTED_TERMINATION));
|
.WillOnce(Return(SPV_REQUESTED_TERMINATION));
|
||||||
Parse(binary, SPV_REQUESTED_TERMINATION);
|
Parse(words, SPV_REQUESTED_TERMINATION);
|
||||||
// On early termination, the binary parser doesn't generate its own
|
// On early termination, the binary parser doesn't generate its own
|
||||||
// diagnostics.
|
// diagnostics.
|
||||||
EXPECT_EQ(nullptr, diagnostic_);
|
EXPECT_EQ(nullptr, diagnostic_);
|
||||||
|
@ -348,7 +348,7 @@ TEST_F(BinaryParseTest, InstructionWithStringOperand) {
|
||||||
"the future is already here, it's just not evenly distributed";
|
"the future is already here, it's just not evenly distributed";
|
||||||
const auto str_words = MakeVector(str);
|
const auto str_words = MakeVector(str);
|
||||||
const auto instruction = MakeInstruction(SpvOpName, {99}, str_words);
|
const auto instruction = MakeInstruction(SpvOpName, {99}, str_words);
|
||||||
const auto binary = Concatenate({ExpectedHeaderForBound(100), instruction});
|
const auto words = Concatenate({ExpectedHeaderForBound(100), instruction});
|
||||||
InSequence calls_expected_in_specific_order;
|
InSequence calls_expected_in_specific_order;
|
||||||
EXPECT_HEADER(100).WillOnce(Return(SPV_SUCCESS));
|
EXPECT_HEADER(100).WillOnce(Return(SPV_SUCCESS));
|
||||||
const auto operands = std::vector<spv_parsed_operand_t>{
|
const auto operands = std::vector<spv_parsed_operand_t>{
|
||||||
|
@ -361,14 +361,14 @@ TEST_F(BinaryParseTest, InstructionWithStringOperand) {
|
||||||
0 /* No result id for OpName*/, operands.data(),
|
0 /* No result id for OpName*/, operands.data(),
|
||||||
static_cast<uint16_t>(operands.size())})))
|
static_cast<uint16_t>(operands.size())})))
|
||||||
.WillOnce(Return(SPV_SUCCESS));
|
.WillOnce(Return(SPV_SUCCESS));
|
||||||
Parse(binary, SPV_SUCCESS);
|
Parse(words, SPV_SUCCESS);
|
||||||
EXPECT_EQ(nullptr, diagnostic_);
|
EXPECT_EQ(nullptr, diagnostic_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks for non-zero values for the result_id and ext_inst_type members
|
// Checks for non-zero values for the result_id and ext_inst_type members
|
||||||
// spv_parsed_instruction_t.
|
// spv_parsed_instruction_t.
|
||||||
TEST_F(BinaryParseTest, ExtendedInstruction) {
|
TEST_F(BinaryParseTest, ExtendedInstruction) {
|
||||||
const auto binary = CompileSuccessfully(
|
const auto words = CompileSuccessfully(
|
||||||
"%extcl = OpExtInstImport \"OpenCL.std\" "
|
"%extcl = OpExtInstImport \"OpenCL.std\" "
|
||||||
"%result = OpExtInst %float %extcl sqrt %x");
|
"%result = OpExtInst %float %extcl sqrt %x");
|
||||||
EXPECT_HEADER(5).WillOnce(Return(SPV_SUCCESS));
|
EXPECT_HEADER(5).WillOnce(Return(SPV_SUCCESS));
|
||||||
|
@ -391,7 +391,7 @@ TEST_F(BinaryParseTest, ExtendedInstruction) {
|
||||||
3 /*result id*/, operands.data(),
|
3 /*result id*/, operands.data(),
|
||||||
static_cast<uint16_t>(operands.size())})))
|
static_cast<uint16_t>(operands.size())})))
|
||||||
.WillOnce(Return(SPV_SUCCESS));
|
.WillOnce(Return(SPV_SUCCESS));
|
||||||
Parse(binary, SPV_SUCCESS);
|
Parse(words, SPV_SUCCESS);
|
||||||
EXPECT_EQ(nullptr, diagnostic_);
|
EXPECT_EQ(nullptr, diagnostic_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,7 +407,6 @@ using BinaryParseWordsAndCountDiagnosticTest = spvtest::TextToBinaryTestBase<
|
||||||
::testing::TestWithParam<WordsAndCountDiagnosticCase>>;
|
::testing::TestWithParam<WordsAndCountDiagnosticCase>>;
|
||||||
|
|
||||||
TEST_P(BinaryParseWordsAndCountDiagnosticTest, WordAndCountCases) {
|
TEST_P(BinaryParseWordsAndCountDiagnosticTest, WordAndCountCases) {
|
||||||
spv_diagnostic diagnostic = nullptr;
|
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
SPV_ERROR_INVALID_BINARY,
|
SPV_ERROR_INVALID_BINARY,
|
||||||
spvBinaryParse(context, nullptr, GetParam().words, GetParam().num_words,
|
spvBinaryParse(context, nullptr, GetParam().words, GetParam().num_words,
|
||||||
|
@ -445,7 +444,6 @@ using BinaryParseWordVectorDiagnosticTest = spvtest::TextToBinaryTestBase<
|
||||||
::testing::TestWithParam<WordVectorDiagnosticCase>>;
|
::testing::TestWithParam<WordVectorDiagnosticCase>>;
|
||||||
|
|
||||||
TEST_P(BinaryParseWordVectorDiagnosticTest, WordVectorCases) {
|
TEST_P(BinaryParseWordVectorDiagnosticTest, WordVectorCases) {
|
||||||
spv_diagnostic diagnostic = nullptr;
|
|
||||||
const auto& words = GetParam().words;
|
const auto& words = GetParam().words;
|
||||||
EXPECT_THAT(spvBinaryParse(context, nullptr, words.data(), words.size(),
|
EXPECT_THAT(spvBinaryParse(context, nullptr, words.data(), words.size(),
|
||||||
nullptr, nullptr, &diagnostic),
|
nullptr, nullptr, &diagnostic),
|
||||||
|
@ -459,8 +457,10 @@ INSTANTIATE_TEST_CASE_P(
|
||||||
::testing::ValuesIn(std::vector<WordVectorDiagnosticCase>{
|
::testing::ValuesIn(std::vector<WordVectorDiagnosticCase>{
|
||||||
{Concatenate({ExpectedHeaderForBound(1), {spvOpcodeMake(0, SpvOpNop)}}),
|
{Concatenate({ExpectedHeaderForBound(1), {spvOpcodeMake(0, SpvOpNop)}}),
|
||||||
"Invalid instruction word count: 0"},
|
"Invalid instruction word count: 0"},
|
||||||
{Concatenate({ExpectedHeaderForBound(1),
|
{Concatenate(
|
||||||
{spvOpcodeMake(1, static_cast<SpvOp>(0xffff))}}),
|
{ExpectedHeaderForBound(1),
|
||||||
|
{spvOpcodeMake(1, static_cast<SpvOp>(
|
||||||
|
std::numeric_limits<uint16_t>::max()))}}),
|
||||||
"Invalid opcode: 65535"},
|
"Invalid opcode: 65535"},
|
||||||
{Concatenate({ExpectedHeaderForBound(1),
|
{Concatenate({ExpectedHeaderForBound(1),
|
||||||
MakeInstruction(SpvOpNop, {42})}),
|
MakeInstruction(SpvOpNop, {42})}),
|
||||||
|
@ -674,7 +674,6 @@ using BinaryParseAssemblyDiagnosticTest = spvtest::TextToBinaryTestBase<
|
||||||
::testing::TestWithParam<AssemblyDiagnosticCase>>;
|
::testing::TestWithParam<AssemblyDiagnosticCase>>;
|
||||||
|
|
||||||
TEST_P(BinaryParseAssemblyDiagnosticTest, AssemblyCases) {
|
TEST_P(BinaryParseAssemblyDiagnosticTest, AssemblyCases) {
|
||||||
spv_diagnostic diagnostic = nullptr;
|
|
||||||
auto words = CompileSuccessfully(GetParam().assembly);
|
auto words = CompileSuccessfully(GetParam().assembly);
|
||||||
EXPECT_THAT(spvBinaryParse(context, nullptr, words.data(), words.size(),
|
EXPECT_THAT(spvBinaryParse(context, nullptr, words.data(), words.size(),
|
||||||
nullptr, nullptr, &diagnostic),
|
nullptr, nullptr, &diagnostic),
|
||||||
|
|
|
@ -396,7 +396,6 @@ OpStore %2 %3 Aligned|Volatile 4 ; bogus, but not indented
|
||||||
TEST_F(TextToBinaryTest, VersionString) {
|
TEST_F(TextToBinaryTest, VersionString) {
|
||||||
auto words = CompileSuccessfully("");
|
auto words = CompileSuccessfully("");
|
||||||
spv_text decoded_text = nullptr;
|
spv_text decoded_text = nullptr;
|
||||||
spv_diagnostic diagnostic = nullptr;
|
|
||||||
EXPECT_THAT(spvBinaryToText(context, words.data(), words.size(),
|
EXPECT_THAT(spvBinaryToText(context, words.data(), words.size(),
|
||||||
SPV_BINARY_TO_TEXT_OPTION_NONE, &decoded_text,
|
SPV_BINARY_TO_TEXT_OPTION_NONE, &decoded_text,
|
||||||
&diagnostic),
|
&diagnostic),
|
||||||
|
@ -430,7 +429,6 @@ TEST_P(GeneratorStringTest, Sample) {
|
||||||
SPV_GENERATOR_WORD(GetParam().generator, GetParam().misc);
|
SPV_GENERATOR_WORD(GetParam().generator, GetParam().misc);
|
||||||
|
|
||||||
spv_text decoded_text = nullptr;
|
spv_text decoded_text = nullptr;
|
||||||
spv_diagnostic diagnostic = nullptr;
|
|
||||||
EXPECT_THAT(spvBinaryToText(context, words.data(), words.size(),
|
EXPECT_THAT(spvBinaryToText(context, words.data(), words.size(),
|
||||||
SPV_BINARY_TO_TEXT_OPTION_NONE, &decoded_text,
|
SPV_BINARY_TO_TEXT_OPTION_NONE, &decoded_text,
|
||||||
&diagnostic),
|
&diagnostic),
|
||||||
|
|
|
@ -592,7 +592,7 @@ TEST(HexFloatOperationTest, UnbiasedExponent) {
|
||||||
float float_fractions(const std::vector<uint32_t>& fractions) {
|
float float_fractions(const std::vector<uint32_t>& fractions) {
|
||||||
float f = 0;
|
float f = 0;
|
||||||
for(int32_t i: fractions) {
|
for(int32_t i: fractions) {
|
||||||
f += ldexp(1.0f, -i);
|
f += std::ldexp(1.0f, -i);
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
@ -626,7 +626,7 @@ uint16_t half_bits_set(const std::vector<uint32_t>& bits) {
|
||||||
for(uint32_t i: bits) {
|
for(uint32_t i: bits) {
|
||||||
val |= top_bit >> i;
|
val |= top_bit >> i;
|
||||||
}
|
}
|
||||||
return val;
|
return static_cast<uint16_t>(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(HexFloatOperationTest, NormalizedSignificand) {
|
TEST(HexFloatOperationTest, NormalizedSignificand) {
|
||||||
|
|
|
@ -184,7 +184,7 @@ TEST_F(ImmediateIntTest, StringFollowingImmediate) {
|
||||||
EXPECT_EQ(original,
|
EXPECT_EQ(original,
|
||||||
CompiledInstructions("OpMemberName !1 !4 \"" + name + "\""))
|
CompiledInstructions("OpMemberName !1 !4 \"" + name + "\""))
|
||||||
<< name;
|
<< name;
|
||||||
const uint32_t wordCount = 4 + name.size() / 4;
|
const uint16_t wordCount = static_cast<uint16_t>(4 + name.size() / 4);
|
||||||
const uint32_t firstWord = spvOpcodeMake(wordCount, SpvOpMemberName);
|
const uint32_t firstWord = spvOpcodeMake(wordCount, SpvOpMemberName);
|
||||||
EXPECT_EQ(original, CompiledInstructions("!" + std::to_string(firstWord) +
|
EXPECT_EQ(original, CompiledInstructions("!" + std::to_string(firstWord) +
|
||||||
" %10 !4 \"" + name + "\""))
|
" %10 !4 \"" + name + "\""))
|
||||||
|
|
|
@ -65,10 +65,10 @@ class TextToBinaryTestBase : public T {
|
||||||
|
|
||||||
// Compiles SPIR-V text in the given assembly syntax format, asserting
|
// Compiles SPIR-V text in the given assembly syntax format, asserting
|
||||||
// compilation success. Returns the compiled code.
|
// compilation success. Returns the compiled code.
|
||||||
SpirvVector CompileSuccessfully(const std::string& text) {
|
SpirvVector CompileSuccessfully(const std::string& txt) {
|
||||||
spv_result_t status = spvTextToBinary(context, text.c_str(), text.size(),
|
spv_result_t status = spvTextToBinary(context, txt.c_str(), txt.size(),
|
||||||
&binary, &diagnostic);
|
&binary, &diagnostic);
|
||||||
EXPECT_EQ(SPV_SUCCESS, status) << text;
|
EXPECT_EQ(SPV_SUCCESS, status) << txt;
|
||||||
SpirvVector code_copy;
|
SpirvVector code_copy;
|
||||||
if (status == SPV_SUCCESS) {
|
if (status == SPV_SUCCESS) {
|
||||||
code_copy = SpirvVector(binary->code, binary->code + binary->wordCount);
|
code_copy = SpirvVector(binary->code, binary->code + binary->wordCount);
|
||||||
|
@ -81,26 +81,26 @@ class TextToBinaryTestBase : public T {
|
||||||
|
|
||||||
// Compiles SPIR-V text with the given format, asserting compilation failure.
|
// Compiles SPIR-V text with the given format, asserting compilation failure.
|
||||||
// Returns the error message(s).
|
// Returns the error message(s).
|
||||||
std::string CompileFailure(const std::string& text) {
|
std::string CompileFailure(const std::string& txt) {
|
||||||
EXPECT_NE(SPV_SUCCESS, spvTextToBinary(context, text.c_str(), text.size(),
|
EXPECT_NE(SPV_SUCCESS, spvTextToBinary(context, txt.c_str(), txt.size(),
|
||||||
&binary, &diagnostic))
|
&binary, &diagnostic))
|
||||||
<< text;
|
<< txt;
|
||||||
DestroyBinary();
|
DestroyBinary();
|
||||||
return diagnostic->error;
|
return diagnostic->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encodes SPIR-V text into binary and then decodes the binary using
|
// Encodes SPIR-V text into binary and then decodes the binary using
|
||||||
// default options. Returns the decoded text.
|
// default options. Returns the decoded text.
|
||||||
std::string EncodeAndDecodeSuccessfully(const std::string& text) {
|
std::string EncodeAndDecodeSuccessfully(const std::string& txt) {
|
||||||
return EncodeAndDecodeSuccessfully(text, SPV_BINARY_TO_TEXT_OPTION_NONE);
|
return EncodeAndDecodeSuccessfully(txt, SPV_BINARY_TO_TEXT_OPTION_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encodes SPIR-V text into binary and then decodes the binary using
|
// Encodes SPIR-V text into binary and then decodes the binary using
|
||||||
// given options. Returns the decoded text.
|
// given options. Returns the decoded text.
|
||||||
std::string EncodeAndDecodeSuccessfully(const std::string& text,
|
std::string EncodeAndDecodeSuccessfully(const std::string& txt,
|
||||||
uint32_t disassemble_options) {
|
uint32_t disassemble_options) {
|
||||||
DestroyBinary();
|
DestroyBinary();
|
||||||
spv_result_t error = spvTextToBinary(context, text.c_str(), text.size(),
|
spv_result_t error = spvTextToBinary(context, txt.c_str(), txt.size(),
|
||||||
&binary, &diagnostic);
|
&binary, &diagnostic);
|
||||||
if (error) {
|
if (error) {
|
||||||
spvDiagnosticPrint(diagnostic);
|
spvDiagnosticPrint(diagnostic);
|
||||||
|
@ -116,7 +116,7 @@ class TextToBinaryTestBase : public T {
|
||||||
spvDiagnosticPrint(diagnostic);
|
spvDiagnosticPrint(diagnostic);
|
||||||
spvDiagnosticDestroy(diagnostic);
|
spvDiagnosticDestroy(diagnostic);
|
||||||
}
|
}
|
||||||
EXPECT_EQ(SPV_SUCCESS, error) << text;
|
EXPECT_EQ(SPV_SUCCESS, error) << txt;
|
||||||
|
|
||||||
const std::string decoded_string = decoded_text->str;
|
const std::string decoded_string = decoded_text->str;
|
||||||
spvTextDestroy(decoded_text);
|
spvTextDestroy(decoded_text);
|
||||||
|
@ -132,9 +132,9 @@ class TextToBinaryTestBase : public T {
|
||||||
// is then decoded. This is expected to fail.
|
// is then decoded. This is expected to fail.
|
||||||
// Returns the error message.
|
// Returns the error message.
|
||||||
std::string EncodeSuccessfullyDecodeFailed(
|
std::string EncodeSuccessfullyDecodeFailed(
|
||||||
const std::string& text, const SpirvVector& words_to_append) {
|
const std::string& txt, const SpirvVector& words_to_append) {
|
||||||
SpirvVector code =
|
SpirvVector code =
|
||||||
spvtest::Concatenate({CompileSuccessfully(text), words_to_append});
|
spvtest::Concatenate({CompileSuccessfully(txt), words_to_append});
|
||||||
|
|
||||||
spv_text decoded_text;
|
spv_text decoded_text;
|
||||||
EXPECT_NE(SPV_SUCCESS, spvBinaryToText(context, code.data(), code.size(),
|
EXPECT_NE(SPV_SUCCESS, spvBinaryToText(context, code.data(), code.size(),
|
||||||
|
@ -151,8 +151,8 @@ class TextToBinaryTestBase : public T {
|
||||||
|
|
||||||
// Compiles SPIR-V text, asserts success, and returns the words representing
|
// Compiles SPIR-V text, asserts success, and returns the words representing
|
||||||
// the instructions. In particular, skip the words in the SPIR-V header.
|
// the instructions. In particular, skip the words in the SPIR-V header.
|
||||||
SpirvVector CompiledInstructions(const std::string& text) {
|
SpirvVector CompiledInstructions(const std::string& txt) {
|
||||||
const SpirvVector code = CompileSuccessfully(text);
|
const SpirvVector code = CompileSuccessfully(txt);
|
||||||
SpirvVector result;
|
SpirvVector result;
|
||||||
// Extract just the instructions.
|
// Extract just the instructions.
|
||||||
// If the code fails to compile, then return the empty vector.
|
// If the code fails to compile, then return the empty vector.
|
||||||
|
|
|
@ -140,7 +140,6 @@ union char_word_t {
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(TextToBinaryTest, InvalidText) {
|
TEST_F(TextToBinaryTest, InvalidText) {
|
||||||
spv_binary binary;
|
|
||||||
ASSERT_EQ(SPV_ERROR_INVALID_TEXT,
|
ASSERT_EQ(SPV_ERROR_INVALID_TEXT,
|
||||||
spvTextToBinary(context, nullptr, 0, &binary, &diagnostic));
|
spvTextToBinary(context, nullptr, 0, &binary, &diagnostic));
|
||||||
EXPECT_NE(nullptr, diagnostic);
|
EXPECT_NE(nullptr, diagnostic);
|
||||||
|
@ -158,7 +157,6 @@ TEST_F(TextToBinaryTest, InvalidPointer) {
|
||||||
TEST_F(TextToBinaryTest, InvalidDiagnostic) {
|
TEST_F(TextToBinaryTest, InvalidDiagnostic) {
|
||||||
SetText(
|
SetText(
|
||||||
"OpEntryPoint Kernel 0 \"\"\nOpExecutionMode 0 LocalSizeHint 1 1 1\n");
|
"OpEntryPoint Kernel 0 \"\"\nOpExecutionMode 0 LocalSizeHint 1 1 1\n");
|
||||||
spv_binary binary;
|
|
||||||
ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC,
|
ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC,
|
||||||
spvTextToBinary(context, text.str, text.length, &binary, nullptr));
|
spvTextToBinary(context, text.str, text.length, &binary, nullptr));
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ void PrintTo(const WordVector& words, ::std::ostream* os);
|
||||||
// A proxy class to allow us to easily write out vectors of SPIR-V words.
|
// A proxy class to allow us to easily write out vectors of SPIR-V words.
|
||||||
class WordVector {
|
class WordVector {
|
||||||
public:
|
public:
|
||||||
explicit WordVector(const std::vector<uint32_t>& value) : value_(value) {}
|
explicit WordVector(const std::vector<uint32_t>& val) : value_(val) {}
|
||||||
explicit WordVector(const spv_binary_t& binary)
|
explicit WordVector(const spv_binary_t& binary)
|
||||||
: value_(binary.code, binary.code + binary.wordCount) {}
|
: value_(binary.code, binary.code + binary.wordCount) {}
|
||||||
|
|
||||||
|
@ -179,8 +179,8 @@ struct AutoText {
|
||||||
template <typename E>
|
template <typename E>
|
||||||
class EnumCase {
|
class EnumCase {
|
||||||
public:
|
public:
|
||||||
EnumCase(E value, std::string name, std::vector<uint32_t> operands = {})
|
EnumCase(E val, std::string enum_name, std::vector<uint32_t> ops = {})
|
||||||
: enum_value_(value), name_(name), operands_(operands) {}
|
: enum_value_(val), name_(enum_name), operands_(ops) {}
|
||||||
// Returns the enum value as a uint32_t.
|
// Returns the enum value as a uint32_t.
|
||||||
uint32_t value() const { return static_cast<uint32_t>(enum_value_); }
|
uint32_t value() const { return static_cast<uint32_t>(enum_value_); }
|
||||||
// Returns the name of the enumerant.
|
// Returns the name of the enumerant.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче