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