// Copyright 2019 Google LLC
//
// 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
//
//      https://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 "compiler/Serialization/VMSourceMapBuilder.h"

#include "flatbuffers/flatbuffers.h"
#include "schemas/source_map_def_generated.h"
#include "llvm/Support/raw_ostream.h"
#include "mlir/IR/Identifier.h"
#include "mlir/IR/Location.h"

namespace mlir {
namespace iree_compiler {

VMSourceMapBuilder::VMSourceMapBuilder(::flatbuffers::FlatBufferBuilder *fbb)
    : fbb_(fbb) {}

int VMSourceMapBuilder::GetUniqueString(std::string value) {
  auto it = stringTableMap_.find(value);
  if (it != stringTableMap_.end()) {
    return it->second;
  }
  int stringIndex = stringTable_.size();
  stringTableMap_.insert({value, stringIndex});
  stringTable_.push_back(std::move(value));
  return stringIndex;
}

LogicalResult VMSourceMapBuilder::AddFunction(
    int functionOrdinal, VMFunctionSourceMap functionSourceMap) {
  if (functionMaps_.size() <= functionOrdinal) {
    functionMaps_.resize(functionOrdinal + 1);
  }
  functionMaps_[functionOrdinal] = std::move(functionSourceMap);
  return success();
}

::flatbuffers::Offset<iree::SourceMapDef> VMSourceMapBuilder::Finish(
    int maxFunctionOrdinal) {
  // NOTE: we always ensure the source map table is the same size as the
  // function table so that lookups at runtime can be validated once at load
  // time (ensuring the tables match up) instead of on each lookup.
  if (maxFunctionOrdinal < functionMaps_.size()) {
    llvm::errs() << "Max function ordinal defined as " << maxFunctionOrdinal
                 << " but there are " << functionMaps_.size()
                 << " function source maps present";
    return {};
  }
  functionMaps_.resize(maxFunctionOrdinal);

  std::vector<::flatbuffers::Offset<iree::FunctionSourceMapDef>> functionDefs;
  functionDefs.resize(maxFunctionOrdinal);
  for (int i = 0; i < functionMaps_.size(); ++i) {
    const auto &functionMap = functionMaps_[i];
    functionDefs[i] = SerializeVMFunctionSourceMap(functionMap);
    if (functionDefs[i].IsNull()) return {};
  }

  auto functionTableOffset = fbb_->CreateVector(functionDefs);
  auto stringTableOffset = fbb_->CreateVectorOfStrings(stringTable_);
  iree::SourceMapDefBuilder smdb(*fbb_);
  smdb.add_function_table(functionTableOffset);
  smdb.add_string_table(stringTableOffset);
  return smdb.Finish();
}

::flatbuffers::Offset<iree::FunctionSourceMapDef>
VMSourceMapBuilder::SerializeVMFunctionSourceMap(
    const VMFunctionSourceMap &functionMap) {
  if (functionMap.locations.empty()) {
    // Empty table. This ensures that we still have a non-null value in the
    // function table but doesn't waste much space.
    iree::FunctionSourceMapDefBuilder fsmdb(*fbb_);
    return fsmdb.Finish();
  }

  LocationOffsetTable locationOffsetTable;
  std::vector<iree::BytecodeSourceLocation> bytecodeMap;
  for (const auto &offset_location : functionMap.locations) {
    int locationIndex =
        SerializeLocation(offset_location.second, &locationOffsetTable);
    bytecodeMap.push_back({offset_location.first, locationIndex});
  }
  auto locationTableOffset =
      fbb_->CreateVector(locationOffsetTable.locationDefs);
  auto bytecodeMapOffset = fbb_->CreateVectorOfStructs(bytecodeMap);

  iree::FunctionSourceMapDefBuilder fsmdb(*fbb_);
  fsmdb.add_location_table(locationTableOffset);
  fsmdb.add_bytecode_map(bytecodeMapOffset);
  return fsmdb.Finish();
}

int VMSourceMapBuilder::SerializeLocation(
    const Location &location, LocationOffsetTable *locationOffsetTable) {
  auto existingIt = locationOffsetTable->locationMap.find(location);
  if (existingIt != locationOffsetTable->locationMap.end()) {
    return existingIt->getSecond();
  }

  iree::LocationDefUnion locationUnionType;
  ::flatbuffers::Offset<void> locationUnionOffset;
  if (auto fileLoc = location.dyn_cast<FileLineColLoc>()) {
    locationUnionType = iree::LocationDefUnion::FileLocationDef;
    int filenameIndex = GetUniqueString(fileLoc.getFilename().str());
    iree::FileLocationDefBuilder lb(*fbb_);
    lb.add_filename(filenameIndex);
    lb.add_line(fileLoc.getLine());
    lb.add_column(fileLoc.getColumn());
    locationUnionOffset = lb.Finish().Union();
  } else if (auto nameLoc = location.dyn_cast<NameLoc>()) {
    locationUnionType = iree::LocationDefUnion::NameLocationDef;
    int nameIndex = GetUniqueString(nameLoc.getName().str());
    iree::NameLocationDefBuilder lb(*fbb_);
    lb.add_name(nameIndex);
    locationUnionOffset = lb.Finish().Union();
  } else if (auto callSiteLoc = location.dyn_cast<CallSiteLoc>()) {
    locationUnionType = iree::LocationDefUnion::CallSiteLocationDef;
    int calleeIndex =
        SerializeLocation(callSiteLoc.getCallee(), locationOffsetTable);
    int callerIndex =
        SerializeLocation(callSiteLoc.getCaller(), locationOffsetTable);
    iree::CallSiteLocationDefBuilder lb(*fbb_);
    lb.add_callee_location(calleeIndex);
    lb.add_caller_location(callerIndex);
    locationUnionOffset = lb.Finish().Union();
  } else if (auto fusedLoc = location.dyn_cast<FusedLoc>()) {
    locationUnionType = iree::LocationDefUnion::FusedLocationDef;
    std::vector<int> locationIndices;
    locationIndices.reserve(fusedLoc.getLocations().size());
    for (const auto &child_loc : fusedLoc.getLocations()) {
      int child_index = SerializeLocation(child_loc, locationOffsetTable);
      locationIndices.push_back(child_index);
    }
    auto locationIndicesOffset = fbb_->CreateVector(locationIndices);
    iree::FusedLocationDefBuilder lb(*fbb_);
    lb.add_locations(locationIndicesOffset);
    locationUnionOffset = lb.Finish().Union();
  } else {
    llvm_unreachable("Unimplemented location kind");
  }

  iree::LocationDefBuilder ldb(*fbb_);
  ldb.add_location_union_type(locationUnionType);
  ldb.add_location_union(locationUnionOffset);
  int locationIndex = locationOffsetTable->locationDefs.size();
  locationOffsetTable->locationDefs.push_back(ldb.Finish());
  locationOffsetTable->locationMap.insert({location, locationIndex});
  return locationIndex;
}

}  // namespace iree_compiler
}  // namespace mlir
