LCOV - code coverage report
Current view: top level - lib/TableGen - JSONBackend.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 57 58 98.3 %
Date: 2018-10-20 13:21:21 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- JSONBackend.cpp - Generate a JSON dump of all records. -*- C++ -*-=====//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This TableGen back end generates a machine-readable representation
      11             : // of all the classes and records defined by the input, in JSON format.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "llvm/ADT/BitVector.h"
      16             : #include "llvm/Support/Debug.h"
      17             : #include "llvm/TableGen/Error.h"
      18             : #include "llvm/TableGen/Record.h"
      19             : #include "llvm/TableGen/TableGenBackend.h"
      20             : #include "llvm/Support/JSON.h"
      21             : 
      22             : #define DEBUG_TYPE "json-emitter"
      23             : 
      24             : using namespace llvm;
      25             : 
      26             : namespace {
      27             : 
      28             : class JSONEmitter {
      29             : private:
      30             :   RecordKeeper &Records;
      31             : 
      32             :   json::Value translateInit(const Init &I);
      33             :   json::Array listSuperclasses(const Record &R);
      34             : 
      35             : public:
      36             :   JSONEmitter(RecordKeeper &R);
      37             : 
      38             :   void run(raw_ostream &OS);
      39             : };
      40             : 
      41             : } // end anonymous namespace
      42             : 
      43           1 : JSONEmitter::JSONEmitter(RecordKeeper &R) : Records(R) {}
      44             : 
      45          76 : json::Value JSONEmitter::translateInit(const Init &I) {
      46             : 
      47             :   // Init subclasses that we return as JSON primitive values of one
      48             :   // kind or another.
      49             : 
      50          76 :   if (isa<UnsetInit>(&I)) {
      51             :     return nullptr;
      52             :   } else if (auto *Bit = dyn_cast<BitInit>(&I)) {
      53          11 :     return Bit->getValue() ? 1 : 0;
      54             :   } else if (auto *Bits = dyn_cast<BitsInit>(&I)) {
      55             :     json::Array array;
      56          35 :     for (unsigned i = 0, limit = Bits->getNumBits(); i < limit; i++)
      57          60 :       array.push_back(translateInit(*Bits->getBit(i)));
      58             :     return std::move(array);
      59             :   } else if (auto *Int = dyn_cast<IntInit>(&I)) {
      60          14 :     return Int->getValue();
      61             :   } else if (auto *Str = dyn_cast<StringInit>(&I)) {
      62           2 :     return Str->getValue();
      63             :   } else if (auto *Code = dyn_cast<CodeInit>(&I)) {
      64           1 :     return Code->getValue();
      65             :   } else if (auto *List = dyn_cast<ListInit>(&I)) {
      66             :     json::Array array;
      67           5 :     for (auto val : *List)
      68           8 :       array.push_back(translateInit(*val));
      69             :     return std::move(array);
      70             :   }
      71             : 
      72             :   // Init subclasses that we return as JSON objects containing a
      73             :   // 'kind' discriminator. For these, we also provide the same
      74             :   // translation back into TableGen input syntax that -print-records
      75             :   // would give.
      76             : 
      77             :   json::Object obj;
      78          14 :   obj["printable"] = I.getAsString();
      79             : 
      80             :   if (auto *Def = dyn_cast<DefInit>(&I)) {
      81           4 :     obj["kind"] = "def";
      82           4 :     obj["def"] = Def->getDef()->getName();
      83             :     return std::move(obj);
      84             :   } else if (auto *Var = dyn_cast<VarInit>(&I)) {
      85           2 :     obj["kind"] = "var";
      86           2 :     obj["var"] = Var->getName();
      87             :     return std::move(obj);
      88             :   } else if (auto *VarBit = dyn_cast<VarBitInit>(&I)) {
      89           2 :     if (auto *Var = dyn_cast<VarInit>(VarBit->getBitVar())) {
      90           4 :       obj["kind"] = "varbit";
      91           4 :       obj["var"] = Var->getName();
      92           6 :       obj["index"] = VarBit->getBitNum();
      93             :       return std::move(obj);
      94             :     }
      95             :   } else if (auto *Dag = dyn_cast<DagInit>(&I)) {
      96           2 :     obj["kind"] = "dag";
      97           2 :     obj["operator"] = translateInit(*Dag->getOperator());
      98           1 :     if (auto name = Dag->getName())
      99           0 :       obj["name"] = name->getAsUnquotedString();
     100             :     json::Array args;
     101           3 :     for (unsigned i = 0, limit = Dag->getNumArgs(); i < limit; ++i) {
     102             :       json::Array arg;
     103           4 :       arg.push_back(translateInit(*Dag->getArg(i)));
     104           2 :       if (auto argname = Dag->getArgName(i))
     105           2 :         arg.push_back(argname->getAsUnquotedString());
     106             :       else
     107           1 :         arg.push_back(nullptr);
     108           2 :       args.push_back(std::move(arg));
     109             :     }
     110           2 :     obj["args"] = std::move(args);
     111             :     return std::move(obj);
     112             :   }
     113             : 
     114             :   // Final fallback: anything that gets past here is simply given a
     115             :   // kind field of 'complex', and the only other field is the standard
     116             :   // 'printable' representation.
     117             : 
     118             :   assert(!I.isConcrete());
     119           2 :   obj["kind"] = "complex";
     120             :   return std::move(obj);
     121             : }
     122             : 
     123           1 : void JSONEmitter::run(raw_ostream &OS) {
     124             :   json::Object root;
     125             : 
     126           2 :   root["!tablegen_json_version"] = 1;
     127             : 
     128             :   // Prepare the arrays that will list the instances of every class.
     129             :   // We mostly fill those in by iterating over the superclasses of
     130             :   // each def, but we also want to ensure we store an empty list for a
     131             :   // class with no instances at all, so we do a preliminary iteration
     132             :   // over the classes, invoking std::map::operator[] to default-
     133             :   // construct the array for each one.
     134             :   std::map<std::string, json::Array> instance_lists;
     135           5 :   for (const auto &C : Records.getClasses()) {
     136             :     auto &Name = C.second->getNameInitAsString();
     137           4 :     (void)instance_lists[Name];
     138             :   }
     139             : 
     140             :   // Main iteration over the defs.
     141          13 :   for (const auto &D : Records.getDefs()) {
     142             :     auto &Name = D.second->getNameInitAsString();
     143             :     auto &Def = *D.second;
     144             : 
     145             :     json::Object obj;
     146             :     json::Array fields;
     147             : 
     148          51 :     for (const RecordVal &RV : Def.getValues()) {
     149          78 :       if (!Def.isTemplateArg(RV.getNameInit())) {
     150             :         auto Name = RV.getNameInitAsString();
     151          39 :         if (RV.getPrefix())
     152           6 :           fields.push_back(Name);
     153         117 :         obj[Name] = translateInit(*RV.getValue());
     154             :       }
     155             :     }
     156             : 
     157          24 :     obj["!fields"] = std::move(fields);
     158             : 
     159             :     json::Array superclasses;
     160          17 :     for (const auto &SuperPair : Def.getSuperClasses())
     161          10 :       superclasses.push_back(SuperPair.first->getNameInitAsString());
     162          24 :     obj["!superclasses"] = std::move(superclasses);
     163             : 
     164          24 :     obj["!name"] = Name;
     165          36 :     obj["!anonymous"] = Def.isAnonymous();
     166             : 
     167          24 :     root[Name] = std::move(obj);
     168             : 
     169             :     // Add this def to the instance list for each of its superclasses.
     170          17 :     for (const auto &SuperPair : Def.getSuperClasses()) {
     171           5 :       auto SuperName = SuperPair.first->getNameInitAsString();
     172          15 :       instance_lists[SuperName].push_back(Name);
     173             :     }
     174             :   }
     175             : 
     176             :   // Make a JSON object from the std::map of instance lists.
     177             :   json::Object instanceof;
     178           5 :   for (auto kv: instance_lists)
     179           8 :     instanceof[kv.first] = std::move(kv.second);
     180           2 :   root["!instanceof"] = std::move(instanceof);
     181             : 
     182             :   // Done. Write the output.
     183           2 :   OS << json::Value(std::move(root)) << "\n";
     184           1 : }
     185             : 
     186             : namespace llvm {
     187             : 
     188           1 : void EmitJSON(RecordKeeper &RK, raw_ostream &OS) { JSONEmitter(RK).run(OS); }
     189             : } // end namespace llvm

Generated by: LCOV version 1.13