// Copyright (c) 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "name_mapper.h"

#include <algorithm>
#include <iterator>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>

#include "spirv-tools/libspirv.h"
#include "spirv/1.1/spirv.h"

namespace {

// Converts a uint32_t to its string decimal representation.
std::string to_string(uint32_t id) {
  // Use stringstream, since some versions of Android compilers lack
  // std::to_string.
  std::stringstream os;
  os << id;
  return os.str();
}

}  // anonymous namespace

namespace libspirv {

NameMapper GetTrivialNameMapper() { return to_string; }

FriendlyNameMapper::FriendlyNameMapper(const spv_const_context context,
                                       const uint32_t* code,
                                       const size_t wordCount)
    : grammar_(libspirv::AssemblyGrammar(context)) {
  spv_diagnostic diag = nullptr;
  // We don't care if the parse fails.
  spvBinaryParse(context, this, code, wordCount, nullptr,
                 ParseInstructionForwarder, &diag);
  spvDiagnosticDestroy(diag);
}

std::string FriendlyNameMapper::NameForId(uint32_t id) {
  auto iter = name_for_id_.find(id);
  if (iter == name_for_id_.end()) {
    // It must have been an invalid module, so just return a trivial mapping.
    // We don't care about uniqueness.
    return to_string(id);
  } else {
    return iter->second;
  }
}

std::string FriendlyNameMapper::Sanitize(const std::string& suggested_name) {
  if (suggested_name.empty()) return "_";
  // Otherwise, replace invalid characters by '_'.
  std::string result;
  std::string valid =
      "abcdefghijklmnopqrstuvwxyz"
      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      "_0123456789";
  std::transform(suggested_name.begin(), suggested_name.end(),
                 std::back_inserter(result), [&valid](const char c) {
                   return (std::string::npos == valid.find(c)) ? '_' : c;
                 });
  return result;
}

void FriendlyNameMapper::SaveName(uint32_t id,
                                  const std::string& suggested_name) {
  if (name_for_id_.find(id) != name_for_id_.end()) return;

  const std::string sanitized_suggested_name = Sanitize(suggested_name);
  std::string name = sanitized_suggested_name;
  auto inserted = used_names_.insert(name);
  if (!inserted.second) {
    const std::string base_name = sanitized_suggested_name + "_";
    for (uint32_t index = 0; !inserted.second; ++index) {
      name = base_name + to_string(index);
      inserted = used_names_.insert(name);
    }
  }
  name_for_id_[id] = name;
}

spv_result_t FriendlyNameMapper::ParseInstruction(
    const spv_parsed_instruction_t& inst) {
  const auto result_id = inst.result_id;
  switch (inst.opcode) {
    case SpvOpName:
      SaveName(inst.words[1], reinterpret_cast<const char*>(inst.words + 2));
      break;
    case SpvOpTypeVoid:
      SaveName(result_id, "void");
      break;
    case SpvOpTypeBool:
      SaveName(result_id, "bool");
      break;
    case SpvOpTypeInt: {
      std::string signedness;
      std::string root;
      const auto bit_width = inst.words[2];
      switch (bit_width) {
        case 8:
          root = "char";
          break;
        case 16:
          root = "short";
          break;
        case 32:
          root = "int";
          break;
        case 64:
          root = "long";
          break;
        default:
          root = to_string(bit_width);
          signedness = "i";
          break;
      }
      if (0 == inst.words[3]) signedness = "u";
      SaveName(result_id, signedness + root);
    } break;
    case SpvOpTypeFloat: {
      const auto bit_width = inst.words[2];
      switch (bit_width) {
        case 16:
          SaveName(result_id, "half");
          break;
        case 32:
          SaveName(result_id, "float");
          break;
        case 64:
          SaveName(result_id, "double");
          break;
        default:
          SaveName(result_id, std::string("fp") + to_string(bit_width));
          break;
      }
    } break;
    case SpvOpTypeVector:
      SaveName(result_id, std::string("v") + to_string(inst.words[3]) +
                              NameForId(inst.words[2]));
      break;
    case SpvOpTypeMatrix:
      SaveName(result_id, std::string("mat") + to_string(inst.words[3]) +
                              NameForId(inst.words[2]));
      break;
    case SpvOpTypeArray:
      SaveName(result_id, std::string("_arr_") + NameForId(inst.words[2]) +
                              "_" + NameForId(inst.words[3]));
      break;
    case SpvOpTypeRuntimeArray:
      SaveName(result_id,
               std::string("_runtimearr_") + NameForId(inst.words[2]));
      break;
    case SpvOpTypePointer:
      SaveName(result_id, std::string("_ptr_") +
                              NameForEnumOperand(SPV_OPERAND_TYPE_STORAGE_CLASS,
                                                 inst.words[2]) +
                              "_" + NameForId(inst.words[3]));
      break;
    case SpvOpTypePipe:
      SaveName(result_id,
               std::string("Pipe") +
                   NameForEnumOperand(SPV_OPERAND_TYPE_ACCESS_QUALIFIER,
                                      inst.words[2]));
      break;
    case SpvOpTypeEvent:
      SaveName(result_id, "Event");
      break;
    case SpvOpTypeDeviceEvent:
      SaveName(result_id, "DeviceEvent");
      break;
    case SpvOpTypeReserveId:
      SaveName(result_id, "ReserveId");
      break;
    case SpvOpTypeQueue:
      SaveName(result_id, "Queue");
      break;
    case SpvOpTypeOpaque:
      SaveName(result_id,
               std::string("Opaque_") +
                   Sanitize(reinterpret_cast<const char*>(inst.words + 2)));
      break;
    case SpvOpTypePipeStorage:
      SaveName(result_id, "PipeStorage");
      break;
    case SpvOpTypeNamedBarrier:
      SaveName(result_id, "NamedBarrier");
      break;
    case SpvOpTypeStruct:
      // Structs are mapped rather simplisitically. Just indicate that they
      // are a struct and then give the raw Id number.
      SaveName(result_id, std::string("_struct_") + to_string(result_id));
      break;
    default:
      // If this instruction otherwise defines an Id, then save a mapping for
      // it.  This is needed to ensure uniqueness in there is an OpName with
      // string something like "1" that might collide with this result_id.
      // We should only do this if a name hasn't already been registered by some
      // previous forward reference.
      if (result_id && name_for_id_.find(result_id) == name_for_id_.end())
        SaveName(result_id, to_string(result_id));
      break;
  }
  return SPV_SUCCESS;
}

std::string FriendlyNameMapper::NameForEnumOperand(spv_operand_type_t type,
                                                   uint32_t word) {
  spv_operand_desc desc = nullptr;
  if (SPV_SUCCESS == grammar_.lookupOperand(type, word, &desc)) {
    return desc->name;
  } else {
    // Invalid input.  Just give something sane.
    return std::string("StorageClass") + to_string(word);
  }
}

}  // namespace libspirv
