xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/VTEmitter.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
106c3fb27SDimitry Andric //===- VTEmitter.cpp - Generate properties from ValueTypes.td -------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric 
906c3fb27SDimitry Andric #include "llvm/ADT/StringRef.h"
1006c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h"
1106c3fb27SDimitry Andric #include "llvm/TableGen/Record.h"
1206c3fb27SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
1306c3fb27SDimitry Andric #include <array>
1406c3fb27SDimitry Andric #include <cassert>
1506c3fb27SDimitry Andric #include <map>
1606c3fb27SDimitry Andric using namespace llvm;
1706c3fb27SDimitry Andric 
1806c3fb27SDimitry Andric namespace {
1906c3fb27SDimitry Andric 
2006c3fb27SDimitry Andric class VTEmitter {
2106c3fb27SDimitry Andric private:
2206c3fb27SDimitry Andric   RecordKeeper &Records;
2306c3fb27SDimitry Andric 
2406c3fb27SDimitry Andric public:
2506c3fb27SDimitry Andric   VTEmitter(RecordKeeper &R) : Records(R) {}
2606c3fb27SDimitry Andric 
2706c3fb27SDimitry Andric   void run(raw_ostream &OS);
2806c3fb27SDimitry Andric };
2906c3fb27SDimitry Andric 
3006c3fb27SDimitry Andric } // End anonymous namespace.
3106c3fb27SDimitry Andric 
3206c3fb27SDimitry Andric void VTEmitter::run(raw_ostream &OS) {
33*5f757f3fSDimitry Andric   emitSourceFileHeader("ValueTypes Source Fragment", OS, Records);
3406c3fb27SDimitry Andric 
3506c3fb27SDimitry Andric   std::array<const Record *, 256> VTsByNumber = {};
3606c3fb27SDimitry Andric   auto ValueTypes = Records.getAllDerivedDefinitions("ValueType");
3706c3fb27SDimitry Andric   for (auto *VT : ValueTypes) {
3806c3fb27SDimitry Andric     auto Number = VT->getValueAsInt("Value");
3906c3fb27SDimitry Andric     assert(0 <= Number && Number < (int)VTsByNumber.size() &&
4006c3fb27SDimitry Andric            "ValueType should be uint8_t");
4106c3fb27SDimitry Andric     assert(!VTsByNumber[Number] && "Duplicate ValueType");
4206c3fb27SDimitry Andric     VTsByNumber[Number] = VT;
4306c3fb27SDimitry Andric   }
4406c3fb27SDimitry Andric 
4506c3fb27SDimitry Andric   struct VTRange {
4606c3fb27SDimitry Andric     StringRef First;
4706c3fb27SDimitry Andric     StringRef Last;
4806c3fb27SDimitry Andric     bool Closed;
4906c3fb27SDimitry Andric   };
5006c3fb27SDimitry Andric 
5106c3fb27SDimitry Andric   std::map<StringRef, VTRange> VTRanges;
5206c3fb27SDimitry Andric 
5306c3fb27SDimitry Andric   auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name,
5406c3fb27SDimitry Andric                                    bool Valid) {
5506c3fb27SDimitry Andric     if (Valid) {
5606c3fb27SDimitry Andric       if (!VTRanges.count(Key))
5706c3fb27SDimitry Andric         VTRanges[Key].First = Name;
5806c3fb27SDimitry Andric       assert(!VTRanges[Key].Closed && "Gap detected!");
5906c3fb27SDimitry Andric       VTRanges[Key].Last = Name;
6006c3fb27SDimitry Andric     } else if (VTRanges.count(Key)) {
6106c3fb27SDimitry Andric       VTRanges[Key].Closed = true;
6206c3fb27SDimitry Andric     }
6306c3fb27SDimitry Andric   };
6406c3fb27SDimitry Andric 
6506c3fb27SDimitry Andric   OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc)\n";
6606c3fb27SDimitry Andric   for (const auto *VT : VTsByNumber) {
6706c3fb27SDimitry Andric     if (!VT)
6806c3fb27SDimitry Andric       continue;
6906c3fb27SDimitry Andric     auto Name = VT->getValueAsString("LLVMName");
7006c3fb27SDimitry Andric     auto Value = VT->getValueAsInt("Value");
7106c3fb27SDimitry Andric     bool IsInteger = VT->getValueAsInt("isInteger");
7206c3fb27SDimitry Andric     bool IsFP = VT->getValueAsInt("isFP");
7306c3fb27SDimitry Andric     bool IsVector = VT->getValueAsInt("isVector");
7406c3fb27SDimitry Andric     bool IsScalable = VT->getValueAsInt("isScalable");
7506c3fb27SDimitry Andric 
7606c3fb27SDimitry Andric     UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name,
7706c3fb27SDimitry Andric                   IsInteger && IsVector && !IsScalable);
7806c3fb27SDimitry Andric     UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name,
7906c3fb27SDimitry Andric                   IsInteger && IsScalable);
8006c3fb27SDimitry Andric     UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name,
8106c3fb27SDimitry Andric                   IsFP && IsVector && !IsScalable);
8206c3fb27SDimitry Andric     UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable);
8306c3fb27SDimitry Andric     UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable);
8406c3fb27SDimitry Andric     UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable);
8506c3fb27SDimitry Andric     UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector);
8606c3fb27SDimitry Andric     UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector);
8706c3fb27SDimitry Andric     UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector);
8806c3fb27SDimitry Andric     UpdateVTRange("VALUETYPE", Name, Value < 224);
8906c3fb27SDimitry Andric 
9006c3fb27SDimitry Andric     // clang-format off
9106c3fb27SDimitry Andric     OS << "  GET_VT_ATTR("
9206c3fb27SDimitry Andric        << Name << ", "
9306c3fb27SDimitry Andric        << Value << ", "
9406c3fb27SDimitry Andric        << VT->getValueAsInt("Size") << ", "
9506c3fb27SDimitry Andric        << VT->getValueAsInt("isOverloaded") << ", "
9606c3fb27SDimitry Andric        << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", "
9706c3fb27SDimitry Andric        << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", "
9806c3fb27SDimitry Andric        << IsVector << ", "
9906c3fb27SDimitry Andric        << IsScalable << ")\n";
10006c3fb27SDimitry Andric     // clang-format on
10106c3fb27SDimitry Andric   }
10206c3fb27SDimitry Andric   OS << "#endif\n\n";
10306c3fb27SDimitry Andric 
10406c3fb27SDimitry Andric   OS << "#ifdef GET_VT_RANGES\n";
10506c3fb27SDimitry Andric   for (const auto &KV : VTRanges) {
10606c3fb27SDimitry Andric     assert(KV.second.Closed);
10706c3fb27SDimitry Andric     OS << "  FIRST_" << KV.first << " = " << KV.second.First << ",\n"
10806c3fb27SDimitry Andric        << "  LAST_" << KV.first << " = " << KV.second.Last << ",\n";
10906c3fb27SDimitry Andric   }
11006c3fb27SDimitry Andric   OS << "#endif\n\n";
11106c3fb27SDimitry Andric 
11206c3fb27SDimitry Andric   OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, nElem, ElTy, ElSz)\n";
11306c3fb27SDimitry Andric   for (const auto *VT : VTsByNumber) {
11406c3fb27SDimitry Andric     if (!VT || !VT->getValueAsInt("isVector"))
11506c3fb27SDimitry Andric       continue;
11606c3fb27SDimitry Andric     const auto *ElTy = VT->getValueAsDef("ElementType");
11706c3fb27SDimitry Andric     assert(ElTy);
11806c3fb27SDimitry Andric     // clang-format off
11906c3fb27SDimitry Andric     OS << "  GET_VT_VECATTR("
12006c3fb27SDimitry Andric        << VT->getValueAsString("LLVMName") << ", "
12106c3fb27SDimitry Andric        << VT->getValueAsInt("isScalable") << ", "
12206c3fb27SDimitry Andric        << VT->getValueAsInt("nElem") << ", "
12306c3fb27SDimitry Andric        << ElTy->getName() << ", "
12406c3fb27SDimitry Andric        << ElTy->getValueAsInt("Size") << ")\n";
12506c3fb27SDimitry Andric     // clang-format on
12606c3fb27SDimitry Andric   }
12706c3fb27SDimitry Andric   OS << "#endif\n\n";
12806c3fb27SDimitry Andric }
12906c3fb27SDimitry Andric 
13006c3fb27SDimitry Andric static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType");
131