111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Copyright (c) 2015-2016 The Khronos Group Inc. 211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Permission is hereby granted, free of charge, to any person obtaining a 411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// copy of this software and/or associated documentation files (the 511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// "Materials"), to deal in the Materials without restriction, including 611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// without limitation the rights to use, copy, modify, merge, publish, 711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// distribute, sublicense, and/or sell copies of the Materials, and to 811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// permit persons to whom the Materials are furnished to do so, subject to 911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// the following conditions: 1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// The above copyright notice and this permission notice shall be included 1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// in all copies or substantial portions of the Materials. 1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS 1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS 1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT 1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// https://www.khronos.org/registry/ 1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "text_handler.h" 2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <cassert> 3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <cstdlib> 3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <cstring> 3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <tuple> 3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "assembly_grammar.h" 3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "binary.h" 3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "ext_inst.h" 3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "instruction.h" 3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "opcode.h" 3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "text.h" 4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "util/bitutils.h" 4111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "util/hex_float.h" 4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertnamespace { 4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertusing spvutils::BitwiseCast; 4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertusing spvutils::FloatProxy; 4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertusing spvutils::HexFloat; 4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Advances |text| to the start of the next line and writes the new position to 5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// |position|. 5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t advanceLine(spv_text text, spv_position position) { 5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (true) { 5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (position->index >= text->length) return SPV_END_OF_STREAM; 5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (text->str[position->index]) { 5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case '\0': 5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_END_OF_STREAM; 5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case '\n': 5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert position->column = 0; 5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert position->line++; 6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert position->index++; 6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_SUCCESS; 6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert position->column++; 6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert position->index++; 6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Advances |text| to first non white space character and writes the new 7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// position to |position|. 7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// If a null terminator is found during the text advance, SPV_END_OF_STREAM is 7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// returned, SPV_SUCCESS otherwise. No error checking is performed on the 7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// parameters, its the users responsibility to ensure these are non null. 7511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t advance(spv_text text, spv_position position) { 7611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // NOTE: Consume white space, otherwise don't advance. 7711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (position->index >= text->length) return SPV_END_OF_STREAM; 7811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (text->str[position->index]) { 7911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case '\0': 8011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_END_OF_STREAM; 8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case ';': 8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (spv_result_t error = advanceLine(text, position)) return error; 8311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return advance(text, position); 8411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case ' ': 8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case '\t': 8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case '\r': 8711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert position->column++; 8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert position->index++; 8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return advance(text, position); 9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case '\n': 9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert position->column = 0; 9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert position->line++; 9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert position->index++; 9411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return advance(text, position); 9511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 9811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_SUCCESS; 9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Fetches the next word from the given text stream starting from the given 10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// *position. On success, writes the decoded word into *word and updates 10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// *position to the location past the returned word. 10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// A word ends at the next comment or whitespace. However, double-quoted 10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// strings remain intact, and a backslash always escapes the next character. 10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t getWord(spv_text text, spv_position position, std::string* word) { 10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!text->str || !text->length) return SPV_ERROR_INVALID_TEXT; 10911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!position) return SPV_ERROR_INVALID_POINTER; 11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 11111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const size_t start_index = position->index; 11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool quoting = false; 11411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool escaping = false; 11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // NOTE: Assumes first character is not white space! 11711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (true) { 11811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (position->index >= text->length) { 11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert word->assign(text->str + start_index, text->str + position->index); 12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_SUCCESS; 12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char ch = text->str[position->index]; 12311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (ch == '\\') 12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert escaping = !escaping; 12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert else { 12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (ch) { 12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case '"': 12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!escaping) quoting = !quoting; 12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case ' ': 13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case ';': 13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case '\t': 13311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case '\n': 13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case '\r': 13511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (escaping || quoting) break; 13611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Fall through. 13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case '\0': { // NOTE: End of word found! 13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert word->assign(text->str + start_index, text->str + position->index); 13911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_SUCCESS; 14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 14411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert escaping = false; 14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert position->column++; 14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert position->index++; 14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Returns true if the characters in the text as position represent 15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// the start of an Opcode. 15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool startsWithOp(spv_text text, spv_position position) { 15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (text->length < position->index + 3) return false; 15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char ch0 = text->str[position->index]; 15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char ch1 = text->str[position->index + 1]; 15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char ch2 = text->str[position->index + 2]; 15911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return ('O' == ch0 && 'p' == ch1 && ('A' <= ch2 && ch2 <= 'Z')); 16011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 16111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 16211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} // anonymous namespace 16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertnamespace libspirv { 16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 16611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertconst IdType kUnknownType = {0, false, IdTypeClass::kBottom}; 16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 16811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TODO(dneto): Reorder AssemblyContext definitions to match declaration order. 16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This represents all of the data that is only valid for the duration of 17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// a single compilation. 17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertuint32_t AssemblyContext::spvNamedIdAssignOrGet(const char* textValue) { 17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (named_ids_.end() == named_ids_.find(textValue)) { 17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert named_ids_[std::string(textValue)] = bound_++; 17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return named_ids_[textValue]; 17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertuint32_t AssemblyContext::getBound() const { return bound_; } 17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t AssemblyContext::advance() { 18111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return ::advance(text_, ¤t_position_); 18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t AssemblyContext::getWord(std::string* word, 18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spv_position next_position) { 18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *next_position = current_position_; 18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return ::getWord(text_, next_position, word); 18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 18911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool AssemblyContext::startsWithOp() { 19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return ::startsWithOp(text_, ¤t_position_); 19211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 19311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 19411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool AssemblyContext::isStartOfNewInst() { 19511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spv_position_t pos = current_position_; 19611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (::advance(text_, &pos)) return false; 19711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (::startsWithOp(text_, &pos)) return true; 19811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 19911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string word; 20011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pos = current_position_; 20111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (::getWord(text_, &pos, &word)) return false; 20211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ('%' != word.front()) return false; 20311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 20411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (::advance(text_, &pos)) return false; 20511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (::getWord(text_, &pos, &word)) return false; 20611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ("=" != word) return false; 20711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 20811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (::advance(text_, &pos)) return false; 20911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (::startsWithOp(text_, &pos)) return true; 21011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 21111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 21211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 21311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertchar AssemblyContext::peek() const { 21411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return text_->str[current_position_.index]; 21511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 21611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 21711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool AssemblyContext::hasText() const { 21811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return text_->length > current_position_.index; 21911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 22011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 22111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid AssemblyContext::seekForward(uint32_t size) { 22211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert current_position_.index += size; 22311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert current_position_.column += size; 22411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 22511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 22611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t AssemblyContext::binaryEncodeU32(const uint32_t value, 22711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spv_instruction_t* pInst) { 22811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pInst->words.insert(pInst->words.end(), value); 22911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_SUCCESS; 23011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 23111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 23211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t AssemblyContext::binaryEncodeU64(const uint64_t value, 23311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spv_instruction_t* pInst) { 23411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t low = uint32_t(0x00000000ffffffff & value); 23511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t high = uint32_t((0xffffffff00000000 & value) >> 32); 23611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert binaryEncodeU32(low, pInst); 23711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert binaryEncodeU32(high, pInst); 23811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_SUCCESS; 23911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 24011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 24111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t AssemblyContext::binaryEncodeNumericLiteral( 24211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char* val, spv_result_t error_code, const IdType& type, 24311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spv_instruction_t* pInst) { 24411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const bool is_bottom = type.type_class == libspirv::IdTypeClass::kBottom; 24511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const bool is_floating = libspirv::isScalarFloating(type); 24611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const bool is_integer = libspirv::isScalarIntegral(type); 24711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 24811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!is_bottom && !is_floating && !is_integer) { 24911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return diagnostic(SPV_ERROR_INTERNAL) 25011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << "The expected type is not a scalar integer or float type"; 25111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 25211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 25311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If this is bottom, but looks like a float, we should treat it like a 25411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // float. 25511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const bool looks_like_float = is_bottom && strchr(val, '.'); 25611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 25711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If we explicitly expect a floating-point number, we should handle that 25811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // first. 25911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (is_floating || looks_like_float) 26011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return binaryEncodeFloatingPointLiteral(val, error_code, type, pInst); 26111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 26211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return binaryEncodeIntegerLiteral(val, error_code, type, pInst); 26311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 26411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 26511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t AssemblyContext::binaryEncodeString(const char* value, 26611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spv_instruction_t* pInst) { 26711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const size_t length = strlen(value); 26811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const size_t wordCount = (length / 4) + 1; 26911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const size_t oldWordCount = pInst->words.size(); 27011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const size_t newWordCount = oldWordCount + wordCount; 27111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 27211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO(dneto): We can just defer this check until later. 27311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (newWordCount > SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX) { 27411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return diagnostic() << "Instruction too long: more than " 27511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX << " words."; 27611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 27711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 27811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pInst->words.resize(newWordCount); 27911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 28011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Make sure all the bytes in the last word are 0, in case we only 28111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // write a partial word at the end. 28211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pInst->words.back() = 0; 28311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 28411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char* dest = (char*)&pInst->words[oldWordCount]; 28511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert strncpy(dest, value, length); 28611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 28711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_SUCCESS; 28811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 28911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 29011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t AssemblyContext::recordTypeDefinition( 29111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const spv_instruction_t* pInst) { 29211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t value = pInst->words[1]; 29311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (types_.find(value) != types_.end()) { 29411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return diagnostic() << "Value " << value 29511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << " has already been used to generate a type"; 29611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 29711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 29811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInst->opcode == SpvOpTypeInt) { 29911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInst->words.size() != 4) 30011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return diagnostic() << "Invalid OpTypeInt instruction"; 30111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert types_[value] = {pInst->words[2], pInst->words[3] != 0, 30211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert IdTypeClass::kScalarIntegerType}; 30311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pInst->opcode == SpvOpTypeFloat) { 30411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInst->words.size() != 3) 30511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return diagnostic() << "Invalid OpTypeFloat instruction"; 30611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert types_[value] = {pInst->words[2], false, IdTypeClass::kScalarFloatType}; 30711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 30811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert types_[value] = {0, false, IdTypeClass::kOtherType}; 30911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 31011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_SUCCESS; 31111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 31211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 31311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertIdType AssemblyContext::getTypeOfTypeGeneratingValue(uint32_t value) const { 31411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto type = types_.find(value); 31511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (type == types_.end()) { 31611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return kUnknownType; 31711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 31811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return std::get<1>(*type); 31911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 32011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 32111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertIdType AssemblyContext::getTypeOfValueInstruction(uint32_t value) const { 32211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto type_value = value_types_.find(value); 32311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (type_value == value_types_.end()) { 32411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return {0, false, IdTypeClass::kBottom}; 32511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 32611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return getTypeOfTypeGeneratingValue(std::get<1>(*type_value)); 32711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 32811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 32911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t AssemblyContext::recordTypeIdForValue(uint32_t value, 33011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t type) { 33111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool successfully_inserted = false; 33211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::tie(std::ignore, successfully_inserted) = 33311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert value_types_.insert(std::make_pair(value, type)); 33411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!successfully_inserted) 33511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return diagnostic() << "Value is being defined a second time"; 33611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_SUCCESS; 33711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 33811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 33911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t AssemblyContext::recordIdAsExtInstImport( 34011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t id, spv_ext_inst_type_t type) { 34111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool successfully_inserted = false; 34211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::tie(std::ignore, successfully_inserted) = 34311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert import_id_to_ext_inst_type_.insert(std::make_pair(id, type)); 34411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!successfully_inserted) 34511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return diagnostic() << "Import Id is being defined a second time"; 34611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_SUCCESS; 34711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 34811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 34911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_ext_inst_type_t AssemblyContext::getExtInstTypeForId(uint32_t id) const { 35011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto type = import_id_to_ext_inst_type_.find(id); 35111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (type == import_id_to_ext_inst_type_.end()) { 35211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_EXT_INST_TYPE_NONE; 35311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 35411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return std::get<1>(*type); 35511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 35611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 35711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t AssemblyContext::binaryEncodeFloatingPointLiteral( 35811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char* val, spv_result_t error_code, const IdType& type, 35911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spv_instruction_t* pInst) { 36011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const auto bit_width = assumedBitWidth(type); 36111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (bit_width) { 36211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case 16: { 36311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spvutils::HexFloat<FloatProxy<spvutils::Float16>> hVal(0); 36411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (auto error = parseNumber(val, error_code, &hVal, 36511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid 16-bit float literal: ")) 36611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return error; 36711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // getAsFloat will return the spvutils::Float16 value, and get_value 36811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // will return a uint16_t representing the bits of the float. 36911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // The encoding is therefore correct from the perspective of the SPIR-V 37011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // spec since the top 16 bits will be 0. 37111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return binaryEncodeU32( 37211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static_cast<uint32_t>(hVal.value().getAsFloat().get_value()), pInst); 37311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } break; 37411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case 32: { 37511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spvutils::HexFloat<FloatProxy<float>> fVal(0.0f); 37611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (auto error = parseNumber(val, error_code, &fVal, 37711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid 32-bit float literal: ")) 37811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return error; 37911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return binaryEncodeU32(BitwiseCast<uint32_t>(fVal), pInst); 38011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } break; 38111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case 64: { 38211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spvutils::HexFloat<FloatProxy<double>> dVal(0.0); 38311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (auto error = parseNumber(val, error_code, &dVal, 38411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid 64-bit float literal: ")) 38511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return error; 38611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return binaryEncodeU64(BitwiseCast<uint64_t>(dVal), pInst); 38711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } break; 38811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 38911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 39011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 39111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return diagnostic() << "Unsupported " << bit_width << "-bit float literals"; 39211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 39311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 39411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Returns SPV_SUCCESS if the given value fits within the target scalar 39511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// integral type. The target type may have an unusual bit width. 39611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// If the value was originally specified as a hexadecimal number, then 39711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// the overflow bits should be zero. If it was hex and the target type is 39811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// signed, then return the sign-extended value through the 39911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// updated_value_for_hex pointer argument. 40011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// On failure, return the given error code and emit a diagnostic if that error 40111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// code is not SPV_FAILED_MATCH. 40211cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename T> 40311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t checkRangeAndIfHexThenSignExtend(T value, spv_result_t error_code, 40411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const IdType& type, bool is_hex, 40511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert T* updated_value_for_hex) { 40611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // The encoded result has three regions of bits that are of interest, from 40711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // least to most significant: 40811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // - magnitude bits, where the magnitude of the number would be stored if 40911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // we were using a signed-magnitude representation. 41011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // - an optional sign bit 41111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // - overflow bits, up to bit 63 of a 64-bit number 41211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // For example: 41311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Type Overflow Sign Magnitude 41411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // --------------- -------- ---- --------- 41511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // unsigned 8 bit 8-63 n/a 0-7 41611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // signed 8 bit 8-63 7 0-6 41711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // unsigned 16 bit 16-63 n/a 0-15 41811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // signed 16 bit 16-63 15 0-14 41911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 42011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // We'll use masks to define the three regions. 42111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // At first we'll assume the number is unsigned. 42211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t bit_width = assumedBitWidth(type); 42311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint64_t magnitude_mask = 42411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (bit_width == 64) ? -1 : ((uint64_t(1) << bit_width) - 1); 42511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint64_t sign_mask = 0; 42611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint64_t overflow_mask = ~magnitude_mask; 42711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 42811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (value < 0 || type.isSigned) { 42911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Accommodate the sign bit. 43011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert magnitude_mask >>= 1; 43111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sign_mask = magnitude_mask + 1; 43211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 43311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 43411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool failed = false; 43511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (value < 0) { 43611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // The top bits must all be 1 for a negative signed value. 43711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert failed = ((value & overflow_mask) != overflow_mask) || 43811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ((value & sign_mask) != sign_mask); 43911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 44011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (is_hex) { 44111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Hex values are a bit special. They decode as unsigned values, but 44211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // may represent a negative number. In this case, the overflow bits 44311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // should be zero. 44411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert failed = (value & overflow_mask) != 0; 44511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 44611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint64_t value_as_u64 = static_cast<uint64_t>(value); 44711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Check overflow in the ordinary case. 44811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert failed = (value_as_u64 & magnitude_mask) != value_as_u64; 44911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 45011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 45111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 45211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (failed) { 45311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return error_code; 45411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 45511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 45611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Sign extend hex the number. 45711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (is_hex && (value & sign_mask)) 45811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *updated_value_for_hex = (value | overflow_mask); 45911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 46011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return SPV_SUCCESS; 46111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 46211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 46311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertspv_result_t AssemblyContext::binaryEncodeIntegerLiteral( 46411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char* val, spv_result_t error_code, const IdType& type, 46511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spv_instruction_t* pInst) { 46611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const bool is_bottom = type.type_class == libspirv::IdTypeClass::kBottom; 46711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t bit_width = assumedBitWidth(type); 46811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 46911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (bit_width > 64) 47011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return diagnostic(SPV_ERROR_INTERNAL) << "Unsupported " << bit_width 47111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << "-bit integer literals"; 47211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 47311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Either we are expecting anything or integer. 47411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool is_negative = val[0] == '-'; 47511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool can_be_signed = is_bottom || type.isSigned; 47611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 47711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (is_negative && !can_be_signed) { 47811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return diagnostic() 47911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << "Cannot put a negative number in an unsigned literal"; 48011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 48111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 48211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const bool is_hex = val[0] == '0' && (val[1] == 'x' || val[1] == 'X'); 48311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 48411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint64_t decoded_bits; 48511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (is_negative) { 48611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int64_t decoded_signed = 0; 48711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 48811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (auto error = parseNumber(val, error_code, &decoded_signed, 48911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid signed integer literal: ")) 49011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return error; 49111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (auto error = checkRangeAndIfHexThenSignExtend( 49211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert decoded_signed, error_code, type, is_hex, &decoded_signed)) { 49311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert diagnostic(error_code) 49411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << "Integer " << (is_hex ? std::hex : std::dec) << std::showbase 49511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << decoded_signed << " does not fit in a " << std::dec << bit_width 49611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << "-bit " << (type.isSigned ? "signed" : "unsigned") << " integer"; 49711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return error; 49811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 49911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert decoded_bits = decoded_signed; 50011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 50111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // There's no leading minus sign, so parse it as an unsigned integer. 50211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (auto error = parseNumber(val, error_code, &decoded_bits, 50311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid unsigned integer literal: ")) 50411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return error; 50511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (auto error = checkRangeAndIfHexThenSignExtend( 50611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert decoded_bits, error_code, type, is_hex, &decoded_bits)) { 50711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert diagnostic(error_code) 50811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << "Integer " << (is_hex ? std::hex : std::dec) << std::showbase 50911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << decoded_bits << " does not fit in a " << std::dec << bit_width 51011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << "-bit " << (type.isSigned ? "signed" : "unsigned") << " integer"; 51111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return error; 51211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 51311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 51411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (bit_width > 32) { 51511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return binaryEncodeU64(decoded_bits, pInst); 51611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 51711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return binaryEncodeU32(uint32_t(decoded_bits), pInst); 51811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 51911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 52011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} // namespace libspirv 521