1de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===- SearchableTableEmitter.cpp - Generate efficiently searchable tables -==//
2de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//
3de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//                     The LLVM Compiler Infrastructure
4de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//
5de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source
6de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// License. See LICENSE.TXT for details.
7de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//
8de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===----------------------------------------------------------------------===//
9de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//
10de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This tablegen backend emits a generic array initialized by specified fields,
11de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// together with companion index tables and lookup functions (binary search,
12de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// currently).
13de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//
14de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===----------------------------------------------------------------------===//
15de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
16de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/ADT/StringExtras.h"
17de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Support/Format.h"
18de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Support/MemoryBuffer.h"
19de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Support/SourceMgr.h"
20de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/TableGen/Error.h"
21de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/TableGen/Record.h"
22de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <algorithm>
23de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <sstream>
24de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <string>
25de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <vector>
26de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarusing namespace llvm;
27de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
28de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define DEBUG_TYPE "searchable-table-emitter"
29de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
30de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarnamespace {
31de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
32de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclass SearchableTableEmitter {
33de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  RecordKeeper &Records;
34de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
35de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarpublic:
36de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  SearchableTableEmitter(RecordKeeper &R) : Records(R) {}
37de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
38de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void run(raw_ostream &OS);
39de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
40de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarprivate:
41de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  typedef std::pair<Init *, int> SearchTableEntry;
42de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
43de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  int getAsInt(BitsInit *B) {
44de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    return cast<IntInit>(B->convertInitializerTo(IntRecTy::get()))->getValue();
45de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
46de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  int getInt(Record *R, StringRef Field) {
47de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    return getAsInt(R->getValueAsBitsInit(Field));
48de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
49de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
50de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::string primaryRepresentation(Init *I) {
51de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    if (StringInit *SI = dyn_cast<StringInit>(I))
52de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      return SI->getAsString();
53de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    else if (BitsInit *BI = dyn_cast<BitsInit>(I))
54de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      return "0x" + utohexstr(getAsInt(BI));
55de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    else if (BitInit *BI = dyn_cast<BitInit>(I))
56de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      return BI->getValue() ? "true" : "false";
57de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    else if (CodeInit *CI = dyn_cast<CodeInit>(I)) {
58de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      return CI->getValue();
59de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    }
60de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    PrintFatalError(SMLoc(),
61de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                    "invalid field type, expected: string, bits, bit or code");
62de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
63de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
64de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::string searchRepresentation(Init *I) {
65de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    std::string PrimaryRep = primaryRepresentation(I);
66de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    if (!isa<StringInit>(I))
67de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      return PrimaryRep;
68de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    return StringRef(PrimaryRep).upper();
69de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
70de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
71de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::string searchableFieldType(Init *I) {
72de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    if (isa<StringInit>(I))
73de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      return "const char *";
74de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    else if (BitsInit *BI = dyn_cast<BitsInit>(I)) {
75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      unsigned NumBits = BI->getNumBits();
76de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      if (NumBits <= 8)
77de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        NumBits = 8;
78de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      else if (NumBits <= 16)
79de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        NumBits = 16;
80de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      else if (NumBits <= 32)
81de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        NumBits = 32;
82de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      else if (NumBits <= 64)
83de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        NumBits = 64;
84de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      else
85de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        PrintFatalError(SMLoc(), "bitfield too large to search");
86de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      return "uint" + utostr(NumBits) + "_t";
87de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    }
88de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    PrintFatalError(SMLoc(), "Unknown type to search by");
89de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
90de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
91de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void emitMapping(Record *MappingDesc, raw_ostream &OS);
92de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void emitMappingEnum(std::vector<Record *> &Items, Record *InstanceClass,
93de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                       raw_ostream &OS);
94de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void
95de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  emitPrimaryTable(StringRef Name, std::vector<std::string> &FieldNames,
96de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                   std::vector<std::string> &SearchFieldNames,
97de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                   std::vector<std::vector<SearchTableEntry>> &SearchTables,
98de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                   std::vector<Record *> &Items, raw_ostream &OS);
99de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void emitSearchTable(StringRef Name, StringRef Field,
100de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                       std::vector<SearchTableEntry> &SearchTable,
101de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                       raw_ostream &OS);
102de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void emitLookupDeclaration(StringRef Name, StringRef Field, Init *I,
103de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                             raw_ostream &OS);
104de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void emitLookupFunction(StringRef Name, StringRef Field, Init *I,
105de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                          raw_ostream &OS);
106de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar};
107de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
108de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} // End anonymous namespace.
109de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
110de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar/// Emit an enum providing symbolic access to some preferred field from
111de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar/// C++.
112de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid SearchableTableEmitter::emitMappingEnum(std::vector<Record *> &Items,
113de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                             Record *InstanceClass,
114de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                             raw_ostream &OS) {
115de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::string EnumNameField = InstanceClass->getValueAsString("EnumNameField");
116de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::string EnumValueField;
117de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (!InstanceClass->isValueUnset("EnumValueField"))
118de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    EnumValueField = InstanceClass->getValueAsString("EnumValueField");
119de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
120de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "enum " << InstanceClass->getName() << "Values {\n";
121de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (auto Item : Items) {
122de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << "  " << Item->getValueAsString(EnumNameField);
123de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    if (EnumValueField != StringRef())
124de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      OS << " = " << getInt(Item, EnumValueField);
125de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << ",\n";
126de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
127de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "};\n\n";
128de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
129de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
130de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid SearchableTableEmitter::emitPrimaryTable(
131de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    StringRef Name, std::vector<std::string> &FieldNames,
132de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    std::vector<std::string> &SearchFieldNames,
133de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    std::vector<std::vector<SearchTableEntry>> &SearchTables,
134de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    std::vector<Record *> &Items, raw_ostream &OS) {
135de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "const " << Name << " " << Name << "sList[] = {\n";
136de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
137de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (auto Item : Items) {
138de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << "  { ";
139de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    for (unsigned i = 0; i < FieldNames.size(); ++i) {
140de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      OS << primaryRepresentation(Item->getValueInit(FieldNames[i]));
141de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      if (i != FieldNames.size() - 1)
142de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        OS << ", ";
143de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    }
144de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << "},\n";
145de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
146de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "};\n\n";
147de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
148de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
149de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid SearchableTableEmitter::emitSearchTable(
150de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    StringRef Name, StringRef Field, std::vector<SearchTableEntry> &SearchTable,
151de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    raw_ostream &OS) {
152de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "const std::pair<" << searchableFieldType(SearchTable[0].first)
153de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar     << ", int> " << Name << "sBy" << Field << "[] = {\n";
154de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
155de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (isa<BitsInit>(SearchTable[0].first)) {
156de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    std::stable_sort(SearchTable.begin(), SearchTable.end(),
157de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                     [this](const SearchTableEntry &LHS,
158de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                            const SearchTableEntry &RHS) {
159de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                       return getAsInt(cast<BitsInit>(LHS.first)) <
160de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                              getAsInt(cast<BitsInit>(RHS.first));
161de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                     });
162de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  } else {
163de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    std::stable_sort(SearchTable.begin(), SearchTable.end(),
164de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                     [this](const SearchTableEntry &LHS,
165de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                            const SearchTableEntry &RHS) {
166de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                       return searchRepresentation(LHS.first) <
167de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                              searchRepresentation(RHS.first);
168de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                     });
169de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
170de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
171de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (auto Entry : SearchTable) {
172de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << "  { " << searchRepresentation(Entry.first) << ", " << Entry.second
173de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar       << " },\n";
174de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
175de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "};\n\n";
176de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
177de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
178de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid SearchableTableEmitter::emitLookupFunction(StringRef Name, StringRef Field,
179de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                                Init *I, raw_ostream &OS) {
180de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  bool IsIntegral = isa<BitsInit>(I);
181de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::string FieldType = searchableFieldType(I);
182de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::string PairType = "std::pair<" + FieldType + ", int>";
183de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
184de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // const SysRegs *lookupSysRegByName(const char *Name) {
185de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "const " << Name << " *"
186de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar     << "lookup" << Name << "By" << Field;
187de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "(" << (IsIntegral ? FieldType : "StringRef") << " " << Field
188de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar     << ") {\n";
189de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
190de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (IsIntegral) {
191de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << "  auto CanonicalVal = " << Field << ";\n";
192de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << " " << PairType << " Val = {CanonicalVal, 0};\n";
193de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  } else {
194de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    // Make sure the result is null terminated because it's going via "char *".
195de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << "  std::string CanonicalVal = " << Field << ".upper();\n";
196de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << "  " << PairType << " Val = {CanonicalVal.data(), 0};\n";
197de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
198de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
199de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "  ArrayRef<" << PairType << "> Table(" << Name << "sBy" << Field
200de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar     << ");\n";
201de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "  auto Idx = std::lower_bound(Table.begin(), Table.end(), Val";
202de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
203de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (IsIntegral)
204de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << ");\n";
205de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  else {
206de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << ",\n                              ";
207de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << "[](const " << PairType << " &LHS, const " << PairType
208de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar       << " &RHS) {\n";
209de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << "    return StringRef(LHS.first) < StringRef(RHS.first);\n";
210de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << "  });\n\n";
211de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
212de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
213de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "  if (Idx == Table.end() || CanonicalVal != Idx->first)\n";
214de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "    return nullptr;\n";
215de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
216de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "  return &" << Name << "sList[Idx->second];\n";
217de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "}\n\n";
218de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
219de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
220de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid SearchableTableEmitter::emitLookupDeclaration(StringRef Name,
221de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                                   StringRef Field, Init *I,
222de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                                   raw_ostream &OS) {
223de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  bool IsIntegral = isa<BitsInit>(I);
224de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::string FieldType = searchableFieldType(I);
225de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "const " << Name << " *"
226de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar     << "lookup" << Name << "By" << Field;
227de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "(" << (IsIntegral ? FieldType : "StringRef") << " " << Field
228de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar     << ");\n\n";
229de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
230de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
231de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid SearchableTableEmitter::emitMapping(Record *InstanceClass,
232de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                         raw_ostream &OS) {
233de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  const std::string &TableName = InstanceClass->getName();
234de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::vector<Record *> Items = Records.getAllDerivedDefinitions(TableName);
235de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
236de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Gather all the records we're going to need for this particular mapping.
237de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::vector<std::vector<SearchTableEntry>> SearchTables;
238de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::vector<std::string> SearchFieldNames;
239de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
240de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::vector<std::string> FieldNames;
241de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (const RecordVal &Field : InstanceClass->getValues()) {
242de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    std::string FieldName = Field.getName();
243de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
244de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    // Skip uninteresting fields: either built-in, special to us, or injected
245de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    // template parameters (if they contain a ':').
246de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    if (FieldName.find(':') != std::string::npos || FieldName == "NAME" ||
247de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        FieldName == "SearchableFields" || FieldName == "EnumNameField" ||
248de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        FieldName == "EnumValueField")
249de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      continue;
250de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
251de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    FieldNames.push_back(FieldName);
252de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
253de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
254de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (auto *Field : *InstanceClass->getValueAsListInit("SearchableFields")) {
255de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    SearchTables.emplace_back();
256de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    SearchFieldNames.push_back(Field->getAsUnquotedString());
257de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
258de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
259de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  int Idx = 0;
260de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (Record *Item : Items) {
261de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    for (unsigned i = 0; i < SearchFieldNames.size(); ++i) {
262de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      Init *SearchVal = Item->getValueInit(SearchFieldNames[i]);
263de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      SearchTables[i].emplace_back(SearchVal, Idx);
264de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    }
265de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    ++Idx;
266de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
267de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
268de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "#ifdef GET_" << StringRef(TableName).upper() << "_DECL\n";
269de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "#undef GET_" << StringRef(TableName).upper() << "_DECL\n";
270de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
271de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Next emit the enum containing the top-level names for use in C++ code if
272de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // requested
273de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (!InstanceClass->isValueUnset("EnumNameField")) {
274de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    emitMappingEnum(Items, InstanceClass, OS);
275de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
276de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
277de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // And the declarations for the functions that will perform lookup.
278de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (unsigned i = 0; i < SearchFieldNames.size(); ++i)
279de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    emitLookupDeclaration(TableName, SearchFieldNames[i],
280de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                          SearchTables[i][0].first, OS);
281de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
282de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "#endif\n\n";
283de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
284de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "#ifdef GET_" << StringRef(TableName).upper() << "_IMPL\n";
285de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "#undef GET_" << StringRef(TableName).upper() << "_IMPL\n";
286de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
287de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // The primary data table contains all the fields defined for this map.
288de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  emitPrimaryTable(TableName, FieldNames, SearchFieldNames, SearchTables, Items,
289de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                   OS);
290de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
291de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Indexes are sorted "{ Thing, PrimaryIdx }" arrays, so that a binary
292de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // search can be performed by "Thing".
293de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (unsigned i = 0; i < SearchTables.size(); ++i) {
294de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    emitSearchTable(TableName, SearchFieldNames[i], SearchTables[i], OS);
295de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    emitLookupFunction(TableName, SearchFieldNames[i], SearchTables[i][0].first,
296de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                       OS);
297de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
298de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
299de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  OS << "#endif\n";
300de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
301de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
302de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid SearchableTableEmitter::run(raw_ostream &OS) {
303de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Tables are defined to be the direct descendents of "SearchableEntry".
304de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  Record *SearchableTable = Records.getClass("SearchableTable");
305de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (auto &NameRec : Records.getClasses()) {
306de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    Record *Class = NameRec.second.get();
307de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    if (Class->getSuperClasses().size() != 1 ||
308de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        !Class->isSubClassOf(SearchableTable))
309de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      continue;
310de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    emitMapping(Class, OS);
311de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
312de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
313de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
314de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarnamespace llvm {
315de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
316de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid EmitSearchableTables(RecordKeeper &RK, raw_ostream &OS) {
317de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  SearchableTableEmitter(RK).run(OS);
318de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
319de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
320de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} // End llvm namespace.
321