//===-- InstrumentorConfigFile.cpp ----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// The implementation of the utilities for the Instrumentor JSON configuration
// file.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO/Instrumentor.h"

#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/VirtualFileSystem.h"

#include <string>

using namespace llvm;

static Expected<std::unique_ptr<MemoryBuffer>>
setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS) {
  auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN()
                                           : FS.getBufferForFile(Filename);
  if (std::error_code EC = BufferOrErr.getError())
    return errorCodeToError(EC);
  return std::move(BufferOrErr.get());
}

namespace llvm {
namespace instrumentor {

void writeConfigToJSON(InstrumentationConfig &IConf, StringRef OutputFile,
                       LLVMContext &Ctx) {
  if (OutputFile.empty())
    return;

  std::error_code EC;
  raw_fd_stream OS(OutputFile, EC);
  if (EC) {
    Ctx.diagnose(DiagnosticInfoInstrumentation(
        Twine("failed to open instrumentor configuration file for writing: ") +
            EC.message(),
        DS_Warning));
    return;
  }

  json::OStream J(OS, 2);
  J.objectBegin();

  J.attributeBegin("configuration");
  J.objectBegin();
  for (auto *BaseCO : IConf.BaseConfigurationOptions) {
    switch (BaseCO->Kind) {
    case BaseConfigurationOption::STRING:
      J.attribute(BaseCO->Name, BaseCO->getString());
      break;
    case BaseConfigurationOption::BOOLEAN:
      J.attribute(BaseCO->Name, BaseCO->getBool());
      break;
    case BaseConfigurationOption::STRING_LIST:
      J.attributeArray(BaseCO->Name, [&] {
        for (StringRef Value : BaseCO->getStringList())
          J.value(Value);
      });
      break;
    }
    if (!BaseCO->Description.empty())
      J.attribute(std::string(BaseCO->Name) + ".description",
                  BaseCO->Description);
  }
  J.objectEnd();
  J.attributeEnd();

  for (unsigned KindVal = 0; KindVal <= InstrumentationLocation::Last;
       ++KindVal) {
    auto Kind = InstrumentationLocation::KindTy(KindVal);

    auto &KindChoices = IConf.IChoices[Kind];
    if (KindChoices.empty())
      continue;

    J.attributeBegin(InstrumentationLocation::getKindStr(Kind));
    J.objectBegin();
    for (auto &[Name, Choice] : KindChoices) {
      J.attributeBegin(Name);
      J.objectBegin();
      J.attribute("enabled", Choice->Enabled);
      J.attribute("filter", Choice->Filter);
      J.attribute("filter.description",
                  "Static property filter to exclude instrumentation.");
      for (auto &ArgIt : Choice->IRTArgs) {
        J.attribute(ArgIt.Name, ArgIt.Enabled);
        if ((ArgIt.Flags & IRTArg::REPLACABLE) ||
            (ArgIt.Flags & IRTArg::REPLACABLE_CUSTOM))
          J.attribute(std::string(ArgIt.Name) + ".replace", true);
        if (!ArgIt.Description.empty())
          J.attribute(std::string(ArgIt.Name) + ".description",
                      ArgIt.Description);
      }
      J.objectEnd();
      J.attributeEnd();
    }
    J.objectEnd();
    J.attributeEnd();
  }

  J.objectEnd();
}

template <typename Map>
static StringRef closestOption(const Map &Options, StringRef Missing) {
  uint32_t MaxEdit = 5;
  StringRef Closest;
  for (const auto &Key : Options.keys()) {
    auto EditDist = Missing.edit_distance_insensitive(Key, true, MaxEdit);
    if (EditDist < MaxEdit) {
      Closest = Key;
      MaxEdit = EditDist;
    }
  }
  return Closest;
}

bool readConfigFromJSON(InstrumentationConfig &IConf, StringRef InputFile,
                        LLVMContext &Ctx, vfs::FileSystem &FS) {
  if (InputFile.empty())
    return true;

  auto BufferOrErr = setupMemoryBuffer(InputFile, FS);
  if (Error E = BufferOrErr.takeError()) {
    Ctx.diagnose(DiagnosticInfoInstrumentation(
        Twine("failed to open instrumentor configuration file for reading: ") +
            toString(std::move(E)),
        DS_Warning));
    return false;
  }
  auto Buffer = std::move(BufferOrErr.get());
  json::Path::Root NullRoot;
  auto Parsed = json::parse(Buffer->getBuffer());
  if (!Parsed) {
    Ctx.diagnose(DiagnosticInfoInstrumentation(
        Twine("failed to parse instrumentor configuration file: ") +
            toString(Parsed.takeError()),
        DS_Warning));
    return false;
  }
  auto *Config = Parsed->getAsObject();
  if (!Config) {
    Ctx.diagnose(DiagnosticInfoInstrumentation(
        "failed to parse instrumentor configuration file, expected an object "
        "'{ ... }'",
        DS_Warning));
    return false;
  }

  StringMap<BaseConfigurationOption *> BCOMap;
  for (auto *BO : IConf.BaseConfigurationOptions)
    BCOMap[BO->Name] = BO;

  SmallPtrSet<InstrumentationOpportunity *, 32> SeenIOs;
  for (auto &It : *Config) {
    auto *Obj = It.second.getAsObject();
    if (!Obj) {
      Ctx.diagnose(DiagnosticInfoInstrumentation(
          "malformed JSON configuration, expected an object", DS_Warning));
      continue;
    }
    if (It.first == "configuration") {
      for (auto &ObjIt : *Obj) {
        if (auto *BO = BCOMap.lookup(ObjIt.first)) {
          switch (BO->Kind) {
          case BaseConfigurationOption::STRING:
            if (auto V = ObjIt.second.getAsString()) {
              BO->setString(IConf.SS.save(*V));
            } else {
              Ctx.diagnose(DiagnosticInfoInstrumentation(
                  Twine("configuration key '") + StringRef(ObjIt.first) +
                      Twine("' expects a string, value ignored"),
                  DS_Warning));
            }
            break;
          case BaseConfigurationOption::BOOLEAN:
            if (auto V = ObjIt.second.getAsBoolean())
              BO->setBool(*V);
            else {
              Ctx.diagnose(DiagnosticInfoInstrumentation(
                  Twine("configuration key '") + StringRef(ObjIt.first) +
                      Twine("' expects a boolean, value ignored"),
                  DS_Warning));
            }
            break;
          case BaseConfigurationOption::STRING_LIST: {
            auto *Values = ObjIt.second.getAsArray();
            if (!Values) {
              Ctx.diagnose(DiagnosticInfoInstrumentation(
                  Twine("configuration key '") + StringRef(ObjIt.first) +
                      Twine("' expects an array of strings, value ignored"),
                  DS_Warning));
              break;
            }

            SmallVector<StringRef> Strings;
            bool AllStrings = true;
            for (const json::Value &Value : *Values) {
              auto String = Value.getAsString();
              if (!String) {
                AllStrings = false;
                break;
              }
              Strings.push_back(IConf.SS.save(*String));
            }
            if (AllStrings)
              BO->setStringList(Strings);
            else
              Ctx.diagnose(DiagnosticInfoInstrumentation(
                  Twine("configuration key '") + StringRef(ObjIt.first) +
                      Twine("' expects an array of strings, value ignored"),
                  DS_Warning));
            break;
          }
          }
        } else if (!StringRef(ObjIt.first).ends_with(".description")) {
          std::string Diag = "configuration key '" + ObjIt.first.str() +
                             "' not found and ignored";
          StringRef Closest = closestOption(BCOMap, ObjIt.first);
          if (!Closest.empty())
            Diag += "; did you mean '" + Closest.str() + "'?";
          Ctx.diagnose(DiagnosticInfoInstrumentation(Diag, DS_Warning));
        }
      }
      continue;
    }

    auto &IChoiceMap =
        IConf.IChoices[InstrumentationLocation::getKindFromStr(It.first)];
    for (auto &ObjIt : *Obj) {
      auto *InnerObj = ObjIt.second.getAsObject();
      if (!InnerObj) {
        Ctx.diagnose(DiagnosticInfoInstrumentation(
            "malformed JSON configuration, expected an object", DS_Warning));
        continue;
      }
      auto *IO = IChoiceMap.lookup(ObjIt.first);
      if (!IO) {
        std::string Diag =
            "malformed JSON configuration, expected an object matching "
            "an instrumentor choice, got '" +
            ObjIt.first.str() + "'";
        StringRef Closest = closestOption(IChoiceMap, ObjIt.first);
        if (!Closest.empty())
          Diag += "; did you mean '" + Closest.str() + "'?";
        Ctx.diagnose(DiagnosticInfoInstrumentation(Diag, DS_Warning));
        continue;
      }
      SeenIOs.insert(IO);
      StringMap<bool> ValueMap, ReplaceMap;
      StringRef FilterStr;
      StringSet<> IOOpts;
      IOOpts.insert("enabled");
      IOOpts.insert("filter");
      for (auto &IRArg : IO->IRTArgs)
        IOOpts.insert(IRArg.Name);
      for (auto &InnerObjIt : *InnerObj) {
        auto Name = StringRef(InnerObjIt.first);
        if (Name == "filter") {
          if (auto V = InnerObjIt.second.getAsString())
            FilterStr = IConf.SS.save(*V);
        } else if (Name.consume_back(".replace")) {
          ReplaceMap[Name] = InnerObjIt.second.getAsBoolean().value_or(false);
        } else {
          ValueMap[Name] = InnerObjIt.second.getAsBoolean().value_or(false);
        }
        if (!IOOpts.contains(Name) && !Name.ends_with(".description")) {
          std::string Diag = "unrecognized JSON property '" + Name.str() +
                             "' in configuration for '" + IO->getName().str() +
                             "'";
          StringRef Closest = closestOption(IOOpts, Name);
          if (!Closest.empty())
            Diag += "; did you mean '" + Closest.str() + "'?";
          Ctx.diagnose(DiagnosticInfoInstrumentation(Diag, DS_Warning));
        }
      }
      IO->Enabled = ValueMap["enabled"];
      IO->Filter = FilterStr;
      for (auto &IRArg : IO->IRTArgs) {
        IRArg.Enabled = ValueMap[IRArg.Name];
        if (!ReplaceMap.lookup(IRArg.Name)) {
          IRArg.Flags &= ~IRTArg::REPLACABLE;
          IRArg.Flags &= ~IRTArg::REPLACABLE_CUSTOM;
        }
      }
    }
  }

  for (auto &IChoiceMap : IConf.IChoices)
    for (auto &It : IChoiceMap)
      if (!SeenIOs.count(It.second))
        It.second->Enabled = false;

  return true;
}

bool readConfigPathsFile(StringRef InputFile, cl::list<std::string> &Configs,
                         LLVMContext &Ctx, vfs::FileSystem &FS) {
  if (InputFile.empty())
    return true;

  auto BufferOrErr = setupMemoryBuffer(InputFile, FS);
  if (Error E = BufferOrErr.takeError()) {
    Ctx.diagnose(DiagnosticInfoInstrumentation(
        Twine("failed to open instrumentor configuration paths file for "
              "reading: ") +
            toString(std::move(E)),
        DS_Warning));
    return false;
  }

  StringRef InputFilePath(sys::path::parent_path(InputFile));

  auto Buffer = std::move(BufferOrErr.get());
  StringRef Content = Buffer->getBuffer();
  StringRef EOL = Content.detectEOL();
  do {
    auto [LHS, RHS] = Content.split(EOL);
    std::string ConfigPath = LHS.trim().str();
    if (!sys::path::is_absolute(ConfigPath)) {
      SmallString<128> InputFilePathStringVec(InputFilePath);
      sys::path::append(InputFilePathStringVec, ConfigPath);
      ConfigPath = InputFilePathStringVec.c_str();
    }
    Configs.push_back(ConfigPath);
    Content = RHS.trim();
  } while (!Content.empty());

  return true;
}

} // end namespace instrumentor
} // end namespace llvm
