Creating a new TableGen tool – The TableGen Language-4

  1. The keywords used for the filter are in the list named Tokens. To get access to that list, you first need to look up the Tokens field in the record. This returns a pointer to an instance of the RecordVal class, from which you can retrieve the Initializer instance via the calling method, getValue(). The Tokens field is defined as a list, so you cast the initializer instance to ListInit. If this fails, then exit the function: ListInit *TokenFilter = dyn_cast_or_null(
    AllTokenFilter[0]
    ->getValue(“Tokens”)
    ->getValue());
    if (!TokenFilter)
    return;
  2. Now, you are ready to construct a filter table. For each keyword stored in the TokenFilter, list, you need the name and the value of the Flag field. That field is again defined as a list, so you need to loop over those elements to calculate the final value. The resulting name/flag value pair is stored in a Table vector: using KeyFlag = std::pair;
    std::vector Table;
    for (size_t I = 0, E = TokenFilter->size(); I < E; ++I) { Record *CC = TokenFilter->getElementAsRecord(I);
    StringRef Name = CC->getValueAsString(“Name”);
    uint64_t Val = 0;
    ListInit *Flags = nullptr;
    if (RecordVal *F = CC->getValue(“Flags”))
    Flags = dyn_cast_or_null(F->getValue());
    if (Flags) {
    for (size_t I = 0, E = Flags->size(); I < E; ++I) { Val |= Flags->getElementAsRecord(I)->getValueAsInt(
    “Val”);
    }
    }
    Table.emplace_back(Name, Val);
    }
  3. To be able to perform a binary search, the table needs to be sorted. The comparison function is provided by a lambda function: llvm::sort(Table.begin(), Table.end(),
    [](const KeyFlag A, const KeyFlag B) {
    return A.first < B.first;
    });
  4. Now, you can emit the C++ source code. First, you emit the sorted table containing the name of the keyword and the associated flag value: OS << “ifdef GET_KEYWORD_FILTER\n”
    << “undef GET_KEYWORD_FILTER\n”;
    OS << “bool lookupKeyword(llvm::StringRef Keyword, “
    “unsigned &Value) {\n”;
    OS << ” struct Entry {\n”
    << ” unsigned Value;\n”
    << ” llvm::StringRef Keyword;\n”
    << ” };\n”
    << “static const Entry Table” << Table.size() << “ = {\n”;
    for (const auto &[Keyword, Value] : Table) {
    OS << ” { ” << Value << “, llvm::StringRef(\””
    << Keyword << “\”, ” << Keyword.size()
    << “) },\n”;
    }
    OS << ” };\n\n”;
  5. Next, you look up the keyword in the sorted table, using the std::lower_bound() standard C++ function. If the keyword is in the table, then the Value parameter receives the value of the flags associated with the keyword, and the function returns true. Otherwise, the function simply returns false: OS << ” const Entry *E = ” “std::lower_bound(&Table[0], ” “&Table” << Table.size() << “, Keyword, [](const Entry &A, const ” “StringRef ” “&B) {\n”; OS << ” return A.Keyword < B;\n”; OS << ” });\n”; OS << ” if (E != &Table” << Table.size() << “) {\n”; OS << ” Value = E->Value;\n”;
    OS << ” return true;\n”;
    OS << ” }\n”;
    OS << ” return false;\n”;
    OS << “}\n”;
    OS << “endif\n”;
    }