From 4ddb431b16e7cba311e30cf79032ef00fe969d17 Mon Sep 17 00:00:00 2001 From: Andrew Woloszyn Date: Wed, 17 Feb 2016 13:00:23 -0500 Subject: [PATCH] Fixed internal compiler error in gcc-4.9. This showed up in mips and mips64 builds. A combination of templates and the error reporting were causing gcc to crash. This splits up the functionality in a way that now successfully compiles. --- CMakeLists.txt | 1 + source/instruction.cpp | 32 ++++++++++++ source/instruction.h | 4 +- source/text_handler.cpp | 126 +++++++++++++++++++++++++++--------------------- source/text_handler.h | 15 +----- 5 files changed, 106 insertions(+), 72 deletions(-) create mode 100644 source/instruction.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b49540..f200b09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,6 +127,7 @@ set(SPIRV_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/source/disassemble.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/diagnostic.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/ext_inst.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/source/instruction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/opcode.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/operand.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/print.cpp diff --git a/source/instruction.cpp b/source/instruction.cpp new file mode 100644 index 0000000..09ef98b --- /dev/null +++ b/source/instruction.cpp @@ -0,0 +1,32 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +#include "instruction.h" + +void spvInstructionAddWord(spv_instruction_t* inst, uint32_t value) { + inst->words.push_back(value); +} + diff --git a/source/instruction.h b/source/instruction.h index 9aca706..61549b6 100644 --- a/source/instruction.h +++ b/source/instruction.h @@ -55,8 +55,6 @@ struct spv_instruction_t { }; // Appends a word to an instruction, without checking for overflow. -inline void spvInstructionAddWord(spv_instruction_t* inst, uint32_t value) { - inst->words.push_back(value); -} +void spvInstructionAddWord(spv_instruction_t* inst, uint32_t value); #endif // LIBSPIRV_INSTRUCTION_H_ diff --git a/source/text_handler.cpp b/source/text_handler.cpp index adc492c..5cc1cc3 100644 --- a/source/text_handler.cpp +++ b/source/text_handler.cpp @@ -253,7 +253,7 @@ void AssemblyContext::seekForward(uint32_t size) { spv_result_t AssemblyContext::binaryEncodeU32(const uint32_t value, spv_instruction_t* pInst) { - spvInstructionAddWord(pInst, value); + pInst->words.insert(pInst->words.end(), value); return SPV_SUCCESS; } @@ -419,57 +419,18 @@ spv_result_t AssemblyContext::binaryEncodeFloatingPointLiteral( return diagnostic() << "Unsupported " << bit_width << "-bit float literals"; } -spv_result_t AssemblyContext::binaryEncodeIntegerLiteral( - const char* val, spv_result_t error_code, const IdType& type, - spv_instruction_t* pInst) { - const bool is_bottom = type.type_class == libspirv::IdTypeClass::kBottom; - const auto bit_width = assumedBitWidth(type); - - if (bit_width > 64) - return diagnostic(SPV_ERROR_INTERNAL) << "Unsupported " << bit_width - << "-bit integer literals"; - - // Either we are expecting anything or integer. - bool is_negative = val[0] == '-'; - bool can_be_signed = is_bottom || type.isSigned; - - if (is_negative && !can_be_signed) { - return diagnostic() - << "Cannot put a negative number in an unsigned literal"; - } - - const bool is_hex = val[0] == '0' && (val[1] == 'x' || val[1] == 'X'); - - uint64_t decoded_bits; - if (is_negative) { - int64_t decoded_signed = 0; - if (auto error = parseNumber(val, error_code, &decoded_signed, - "Invalid signed integer literal: ")) - return error; - if (auto error = checkRangeAndIfHexThenSignExtend( - decoded_signed, error_code, type, is_hex, &decoded_signed)) - return error; - decoded_bits = decoded_signed; - } else { - // There's no leading minus sign, so parse it as an unsigned integer. - if (auto error = parseNumber(val, error_code, &decoded_bits, - "Invalid unsigned integer literal: ")) - return error; - if (auto error = checkRangeAndIfHexThenSignExtend( - decoded_bits, error_code, type, is_hex, &decoded_bits)) - return error; - } - if (bit_width > 32) { - return binaryEncodeU64(decoded_bits, pInst); - } else { - return binaryEncodeU32(uint32_t(decoded_bits), pInst); - } -} - +// Returns SPV_SUCCESS if the given value fits within the target scalar +// integral type. The target type may have an unusual bit width. +// If the value was originally specified as a hexadecimal number, then +// the overflow bits should be zero. If it was hex and the target type is +// signed, then return the sign-extended value through the +// updated_value_for_hex pointer argument. +// On failure, return the given error code and emit a diagnostic if that error +// code is not SPV_FAILED_MATCH. template -spv_result_t AssemblyContext::checkRangeAndIfHexThenSignExtend( - T value, spv_result_t error_code, const IdType& type, bool is_hex, - T* updated_value_for_hex) { +spv_result_t checkRangeAndIfHexThenSignExtend(T value, spv_result_t error_code, + const IdType& type, bool is_hex, + T* updated_value_for_hex) { // The encoded result has three regions of bits that are of interest, from // least to most significant: // - magnitude bits, where the magnitude of the number would be stored if @@ -517,10 +478,7 @@ spv_result_t AssemblyContext::checkRangeAndIfHexThenSignExtend( } if (failed) { - return diagnostic(error_code) - << "Integer " << (is_hex ? std::hex : std::dec) << std::showbase - << value << " does not fit in a " << std::dec << bit_width << "-bit " - << (type.isSigned ? "signed" : "unsigned") << " integer"; + return error_code; } // Sign extend hex the number. @@ -529,4 +487,62 @@ spv_result_t AssemblyContext::checkRangeAndIfHexThenSignExtend( return SPV_SUCCESS; } + +spv_result_t AssemblyContext::binaryEncodeIntegerLiteral( + const char* val, spv_result_t error_code, const IdType& type, + spv_instruction_t* pInst) { + const bool is_bottom = type.type_class == libspirv::IdTypeClass::kBottom; + const uint32_t bit_width = assumedBitWidth(type); + + if (bit_width > 64) + return diagnostic(SPV_ERROR_INTERNAL) << "Unsupported " << bit_width + << "-bit integer literals"; + + // Either we are expecting anything or integer. + bool is_negative = val[0] == '-'; + bool can_be_signed = is_bottom || type.isSigned; + + if (is_negative && !can_be_signed) { + return diagnostic() + << "Cannot put a negative number in an unsigned literal"; + } + + const bool is_hex = val[0] == '0' && (val[1] == 'x' || val[1] == 'X'); + + uint64_t decoded_bits; + if (is_negative) { + int64_t decoded_signed = 0; + + if (auto error = parseNumber(val, error_code, &decoded_signed, + "Invalid signed integer literal: ")) + return error; + if (auto error = checkRangeAndIfHexThenSignExtend( + decoded_signed, error_code, type, is_hex, &decoded_signed)) { + diagnostic(error_code) + << "Integer " << (is_hex ? std::hex : std::dec) << std::showbase + << decoded_signed << " does not fit in a " << std::dec << bit_width + << "-bit " << (type.isSigned ? "signed" : "unsigned") << " integer"; + return error; + } + decoded_bits = decoded_signed; + } else { + // There's no leading minus sign, so parse it as an unsigned integer. + if (auto error = parseNumber(val, error_code, &decoded_bits, + "Invalid unsigned integer literal: ")) + return error; + if (auto error = checkRangeAndIfHexThenSignExtend( + decoded_bits, error_code, type, is_hex, &decoded_bits)) { + diagnostic(error_code) + << "Integer " << (is_hex ? std::hex : std::dec) << std::showbase + << decoded_bits << " does not fit in a " << std::dec << bit_width + << "-bit " << (type.isSigned ? "signed" : "unsigned") << " integer"; + return error; + } + } + if (bit_width > 32) { + return binaryEncodeU64(decoded_bits, pInst); + } else { + return binaryEncodeU32(uint32_t(decoded_bits), pInst); + } +} } // namespace libspirv diff --git a/source/text_handler.h b/source/text_handler.h index 7149e5f..1e96206 100644 --- a/source/text_handler.h +++ b/source/text_handler.h @@ -282,6 +282,7 @@ class AssemblyContext { } private: + // Appends the given floating point literal to the given instruction. // Returns SPV_SUCCESS if the value was correctly parsed. Otherwise // returns the given error code, and emits a diagnostic if that error @@ -302,20 +303,6 @@ class AssemblyContext { const IdType& type, spv_instruction_t* pInst); - // Returns SPV_SUCCESS if the given value fits within the target scalar - // integral type. The target type may have an unusual bit width. - // If the value was originally specified as a hexadecimal number, then - // the overflow bits should be zero. If it was hex and the target type is - // signed, then return the sign-extended value through the - // updated_value_for_hex pointer argument. - // On failure, return the given error code and emit a diagnostic if that error - // code is not SPV_FAILED_MATCH. - template - spv_result_t checkRangeAndIfHexThenSignExtend(T value, - spv_result_t error_code, - const IdType& type, bool is_hex, - T* updated_value_for_hex); - // Writes the given 64-bit literal value into the instruction. // return SPV_SUCCESS if the value could be written in the instruction. spv_result_t binaryEncodeU64(const uint64_t value, spv_instruction_t* pInst); -- 2.7.4