10b57cec5SDimitry Andric //===--- CodeGenHwModes.cpp -----------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric // Classes to parse and store HW mode information for instruction selection
90b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric #include "CodeGenHwModes.h"
120b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
130b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
140b57cec5SDimitry Andric #include "llvm/TableGen/Error.h"
150b57cec5SDimitry Andric #include "llvm/TableGen/Record.h"
160b57cec5SDimitry Andric
170b57cec5SDimitry Andric using namespace llvm;
180b57cec5SDimitry Andric
190b57cec5SDimitry Andric StringRef CodeGenHwModes::DefaultModeName = "DefaultMode";
200b57cec5SDimitry Andric
HwMode(Record * R)210b57cec5SDimitry Andric HwMode::HwMode(Record *R) {
220b57cec5SDimitry Andric Name = R->getName();
235ffd83dbSDimitry Andric Features = std::string(R->getValueAsString("Features"));
24*fe013be4SDimitry Andric
25*fe013be4SDimitry Andric std::vector<Record *> PredicateRecs = R->getValueAsListOfDefs("Predicates");
26*fe013be4SDimitry Andric SmallString<128> PredicateCheck;
27*fe013be4SDimitry Andric raw_svector_ostream OS(PredicateCheck);
28*fe013be4SDimitry Andric ListSeparator LS(" && ");
29*fe013be4SDimitry Andric for (Record *Pred : PredicateRecs) {
30*fe013be4SDimitry Andric StringRef CondString = Pred->getValueAsString("CondString");
31*fe013be4SDimitry Andric if (CondString.empty())
32*fe013be4SDimitry Andric continue;
33*fe013be4SDimitry Andric OS << LS << '(' << CondString << ')';
34*fe013be4SDimitry Andric }
35*fe013be4SDimitry Andric
36*fe013be4SDimitry Andric Predicates = std::string(PredicateCheck);
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric LLVM_DUMP_METHOD
dump() const400b57cec5SDimitry Andric void HwMode::dump() const {
410b57cec5SDimitry Andric dbgs() << Name << ": " << Features << '\n';
420b57cec5SDimitry Andric }
430b57cec5SDimitry Andric
HwModeSelect(Record * R,CodeGenHwModes & CGH)440b57cec5SDimitry Andric HwModeSelect::HwModeSelect(Record *R, CodeGenHwModes &CGH) {
450b57cec5SDimitry Andric std::vector<Record*> Modes = R->getValueAsListOfDefs("Modes");
460b57cec5SDimitry Andric std::vector<Record*> Objects = R->getValueAsListOfDefs("Objects");
470b57cec5SDimitry Andric if (Modes.size() != Objects.size()) {
480b57cec5SDimitry Andric PrintError(R->getLoc(), "in record " + R->getName() +
490b57cec5SDimitry Andric " derived from HwModeSelect: the lists Modes and Objects should "
500b57cec5SDimitry Andric "have the same size");
510b57cec5SDimitry Andric report_fatal_error("error in target description.");
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric for (unsigned i = 0, e = Modes.size(); i != e; ++i) {
54*fe013be4SDimitry Andric unsigned ModeId = CGH.getHwModeId(Modes[i]);
550b57cec5SDimitry Andric Items.push_back(std::make_pair(ModeId, Objects[i]));
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric LLVM_DUMP_METHOD
dump() const600b57cec5SDimitry Andric void HwModeSelect::dump() const {
610b57cec5SDimitry Andric dbgs() << '{';
620b57cec5SDimitry Andric for (const PairType &P : Items)
630b57cec5SDimitry Andric dbgs() << " (" << P.first << ',' << P.second->getName() << ')';
640b57cec5SDimitry Andric dbgs() << " }\n";
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric
CodeGenHwModes(RecordKeeper & RK)670b57cec5SDimitry Andric CodeGenHwModes::CodeGenHwModes(RecordKeeper &RK) : Records(RK) {
68*fe013be4SDimitry Andric for (Record *R : Records.getAllDerivedDefinitions("HwMode")) {
690b57cec5SDimitry Andric // The default mode needs a definition in the .td sources for TableGen
700b57cec5SDimitry Andric // to accept references to it. We need to ignore the definition here.
71*fe013be4SDimitry Andric if (R->getName() == DefaultModeName)
720b57cec5SDimitry Andric continue;
730b57cec5SDimitry Andric Modes.emplace_back(R);
74*fe013be4SDimitry Andric ModeIds.insert(std::make_pair(R, Modes.size()));
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric
77*fe013be4SDimitry Andric for (Record *R : Records.getAllDerivedDefinitions("HwModeSelect")) {
780b57cec5SDimitry Andric auto P = ModeSelects.emplace(std::make_pair(R, HwModeSelect(R, *this)));
790b57cec5SDimitry Andric assert(P.second);
800b57cec5SDimitry Andric (void)P;
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric
getHwModeId(Record * R) const84*fe013be4SDimitry Andric unsigned CodeGenHwModes::getHwModeId(Record *R) const {
85*fe013be4SDimitry Andric if (R->getName() == DefaultModeName)
860b57cec5SDimitry Andric return DefaultMode;
87*fe013be4SDimitry Andric auto F = ModeIds.find(R);
880b57cec5SDimitry Andric assert(F != ModeIds.end() && "Unknown mode name");
890b57cec5SDimitry Andric return F->second;
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric
getHwModeSelect(Record * R) const920b57cec5SDimitry Andric const HwModeSelect &CodeGenHwModes::getHwModeSelect(Record *R) const {
930b57cec5SDimitry Andric auto F = ModeSelects.find(R);
940b57cec5SDimitry Andric assert(F != ModeSelects.end() && "Record is not a \"mode select\"");
950b57cec5SDimitry Andric return F->second;
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric LLVM_DUMP_METHOD
dump() const990b57cec5SDimitry Andric void CodeGenHwModes::dump() const {
1000b57cec5SDimitry Andric dbgs() << "Modes: {\n";
1010b57cec5SDimitry Andric for (const HwMode &M : Modes) {
1020b57cec5SDimitry Andric dbgs() << " ";
1030b57cec5SDimitry Andric M.dump();
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric dbgs() << "}\n";
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andric dbgs() << "ModeIds: {\n";
1080b57cec5SDimitry Andric for (const auto &P : ModeIds)
109*fe013be4SDimitry Andric dbgs() << " " << P.first->getName() << " -> " << P.second << '\n';
1100b57cec5SDimitry Andric dbgs() << "}\n";
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andric dbgs() << "ModeSelects: {\n";
1130b57cec5SDimitry Andric for (const auto &P : ModeSelects) {
1140b57cec5SDimitry Andric dbgs() << " " << P.first->getName() << " -> ";
1150b57cec5SDimitry Andric P.second.dump();
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric dbgs() << "}\n";
1180b57cec5SDimitry Andric }
119