//===- JSONBackend.cpp - Generate a JSON dump of all records. -*- C++ -*-=====//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This TableGen back end generates a machine-readable representation
// of all the classes and records defined by the input, in JSON format.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/JSON.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"

#define DEBUG_TYPE "json-emitter"

using namespace llvm;

namespace {

class JSONEmitter {
private:
  const RecordKeeper &Records;

  json::Value translateInit(const Init &I);

public:
  explicit JSONEmitter(const RecordKeeper &R) : Records(R) {}

  void run(raw_ostream &OS);
};

} // end anonymous namespace

json::Value JSONEmitter::translateInit(const Init &I) {
  // Init subclasses that we return as JSON primitive values of one
  // kind or another.

  if (isa<UnsetInit>(&I))
    return nullptr;
  if (const auto *Bit = dyn_cast<BitInit>(&I))
    return Bit->getValue() ? 1 : 0;
  if (const auto *Bits = dyn_cast<BitsInit>(&I)) {
    json::Array Array;
    for (unsigned Idx = 0, E = Bits->getNumBits(); Idx < E; ++Idx)
      Array.push_back(translateInit(*Bits->getBit(Idx)));
    return std::move(Array);
  }
  if (const auto *Int = dyn_cast<IntInit>(&I))
    return Int->getValue();
  if (const auto *Str = dyn_cast<StringInit>(&I))
    return Str->getValue();
  if (const auto *List = dyn_cast<ListInit>(&I)) {
    json::Array Array;
    for (const auto *Val : *List)
      Array.push_back(translateInit(*Val));
    return std::move(Array);
  }

  // Init subclasses that we return as JSON objects containing a
  // 'kind' discriminator. For these, we also provide the same
  // translation back into TableGen input syntax that -print-records
  // would give.

  json::Object Obj;
  Obj["printable"] = I.getAsString();

  if (const auto *Def = dyn_cast<DefInit>(&I)) {
    Obj["kind"] = "def";
    Obj["def"] = Def->getDef()->getName();
    return std::move(Obj);
  }
  if (const auto *Var = dyn_cast<VarInit>(&I)) {
    Obj["kind"] = "var";
    Obj["var"] = Var->getName();
    return std::move(Obj);
  }
  if (const auto *VarBit = dyn_cast<VarBitInit>(&I)) {
    if (const auto *Var = dyn_cast<VarInit>(VarBit->getBitVar())) {
      Obj["kind"] = "varbit";
      Obj["var"] = Var->getName();
      Obj["index"] = VarBit->getBitNum();
      return std::move(Obj);
    }
  }
  if (const auto *Dag = dyn_cast<DagInit>(&I)) {
    Obj["kind"] = "dag";
    Obj["operator"] = translateInit(*Dag->getOperator());
    if (auto name = Dag->getName())
      Obj["name"] = name->getAsUnquotedString();
    json::Array Args;
    for (unsigned Idx = 0, E = Dag->getNumArgs(); Idx < E; ++Idx) {
      json::Array Arg;
      Arg.push_back(translateInit(*Dag->getArg(Idx)));
      if (const auto ArgName = Dag->getArgName(Idx))
        Arg.push_back(ArgName->getAsUnquotedString());
      else
        Arg.push_back(nullptr);
      Args.push_back(std::move(Arg));
    }
    Obj["args"] = std::move(Args);
    return std::move(Obj);
  }

  // Final fallback: anything that gets past here is simply given a
  // kind field of 'complex', and the only other field is the standard
  // 'printable' representation.
  assert(!I.isConcrete());
  Obj["kind"] = "complex";
  return std::move(Obj);
}

void JSONEmitter::run(raw_ostream &OS) {
  json::Object Root;

  Root["!tablegen_json_version"] = 1;

  // Prepare the arrays that will list the instances of every class.
  // We mostly fill those in by iterating over the superclasses of
  // each def, but we also want to ensure we store an empty list for a
  // class with no instances at all, so we do a preliminary iteration
  // over the classes, invoking std::map::operator[] to default-
  // construct the array for each one.
  std::map<std::string, json::Array> InstanceLists;
  for (const auto &[ClassName, ClassRec] : Records.getClasses())
    InstanceLists.emplace(ClassRec->getNameInitAsString(), json::Array());

  // Main iteration over the defs.
  for (const auto &[DefName, Def] : Records.getDefs()) {
    const std::string Name = Def->getNameInitAsString();

    json::Object Obj;
    json::Array Fields;

    for (const RecordVal &RV : Def->getValues()) {
      if (!Def->isTemplateArg(RV.getNameInit())) {
        auto Name = RV.getNameInitAsString();
        if (RV.isNonconcreteOK())
          Fields.push_back(Name);
        Obj[Name] = translateInit(*RV.getValue());
      }
    }

    Obj["!fields"] = std::move(Fields);

    json::Array SuperClasses;
    // Add this def to the instance list for each of its superclasses.
    for (const Record *SuperClass : Def->getSuperClasses()) {
      std::string SuperName = SuperClass->getNameInitAsString();
      SuperClasses.push_back(SuperName);
      InstanceLists[SuperName].push_back(Name);
    }

    Obj["!superclasses"] = std::move(SuperClasses);

    Obj["!name"] = Name;
    Obj["!anonymous"] = Def->isAnonymous();

    json::Array Locs;
    for (const SMLoc Loc : Def->getLoc())
      Locs.push_back(SrcMgr.getFormattedLocationNoOffset(Loc));
    Obj["!locs"] = std::move(Locs);

    Root[Name] = std::move(Obj);
  }

  // Make a JSON object from the std::map of instance lists.
  json::Object InstanceOf;
  for (auto &[ClassName, Instances] : InstanceLists)
    InstanceOf[ClassName] = std::move(Instances);
  Root["!instanceof"] = std::move(InstanceOf);

  // Done. Write the output.
  OS << json::Value(std::move(Root)) << "\n";
}

void llvm::EmitJSON(const RecordKeeper &RK, raw_ostream &OS) {
  JSONEmitter(RK).run(OS);
}
