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_, &current_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_, &current_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