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:
VTEmitter(RecordKeeper & R)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
VTtoGetLLVMTyString(raw_ostream & OS,const Record * VT)32*0fca6ea1SDimitry Andric static void VTtoGetLLVMTyString(raw_ostream &OS, const Record *VT) {
33*0fca6ea1SDimitry Andric bool IsVector = VT->getValueAsBit("isVector");
34*0fca6ea1SDimitry Andric if (IsVector)
35*0fca6ea1SDimitry Andric OS << (VT->getValueAsBit("isScalable") ? "Scalable" : "Fixed")
36*0fca6ea1SDimitry Andric << "VectorType::get(";
37*0fca6ea1SDimitry Andric
38*0fca6ea1SDimitry Andric auto OutputVT = IsVector ? VT->getValueAsDef("ElementType") : VT;
39*0fca6ea1SDimitry Andric int64_t OutputVTSize = OutputVT->getValueAsInt("Size");
40*0fca6ea1SDimitry Andric
41*0fca6ea1SDimitry Andric if (OutputVT->getValueAsBit("isFP")) {
42*0fca6ea1SDimitry Andric StringRef FloatTy;
43*0fca6ea1SDimitry Andric auto OutputVTName = OutputVT->getValueAsString("LLVMName");
44*0fca6ea1SDimitry Andric switch (OutputVTSize) {
45*0fca6ea1SDimitry Andric default:
46*0fca6ea1SDimitry Andric llvm_unreachable("Unhandled case");
47*0fca6ea1SDimitry Andric case 16:
48*0fca6ea1SDimitry Andric FloatTy = (OutputVTName == "bf16") ? "BFloatTy" : "HalfTy";
49*0fca6ea1SDimitry Andric break;
50*0fca6ea1SDimitry Andric case 32:
51*0fca6ea1SDimitry Andric FloatTy = "FloatTy";
52*0fca6ea1SDimitry Andric break;
53*0fca6ea1SDimitry Andric case 64:
54*0fca6ea1SDimitry Andric FloatTy = "DoubleTy";
55*0fca6ea1SDimitry Andric break;
56*0fca6ea1SDimitry Andric case 80:
57*0fca6ea1SDimitry Andric FloatTy = "X86_FP80Ty";
58*0fca6ea1SDimitry Andric break;
59*0fca6ea1SDimitry Andric case 128:
60*0fca6ea1SDimitry Andric FloatTy = (OutputVTName == "ppcf128") ? "PPC_FP128Ty" : "FP128Ty";
61*0fca6ea1SDimitry Andric break;
62*0fca6ea1SDimitry Andric }
63*0fca6ea1SDimitry Andric OS << "Type::get" << FloatTy << "(Context)";
64*0fca6ea1SDimitry Andric } else if (OutputVT->getValueAsBit("isInteger")) {
65*0fca6ea1SDimitry Andric // We only have Type::getInt1Ty, Int8, Int16, Int32, Int64, and Int128
66*0fca6ea1SDimitry Andric if ((isPowerOf2_64(OutputVTSize) && OutputVTSize >= 8 &&
67*0fca6ea1SDimitry Andric OutputVTSize <= 128) ||
68*0fca6ea1SDimitry Andric OutputVTSize == 1)
69*0fca6ea1SDimitry Andric OS << "Type::getInt" << OutputVTSize << "Ty(Context)";
70*0fca6ea1SDimitry Andric else
71*0fca6ea1SDimitry Andric OS << "Type::getIntNTy(Context, " << OutputVTSize << ")";
72*0fca6ea1SDimitry Andric } else
73*0fca6ea1SDimitry Andric llvm_unreachable("Unhandled case");
74*0fca6ea1SDimitry Andric
75*0fca6ea1SDimitry Andric if (IsVector)
76*0fca6ea1SDimitry Andric OS << ", " << VT->getValueAsInt("nElem") << ")";
77*0fca6ea1SDimitry Andric }
78*0fca6ea1SDimitry Andric
run(raw_ostream & OS)7906c3fb27SDimitry Andric void VTEmitter::run(raw_ostream &OS) {
805f757f3fSDimitry Andric emitSourceFileHeader("ValueTypes Source Fragment", OS, Records);
8106c3fb27SDimitry Andric
8206c3fb27SDimitry Andric std::array<const Record *, 256> VTsByNumber = {};
8306c3fb27SDimitry Andric auto ValueTypes = Records.getAllDerivedDefinitions("ValueType");
8406c3fb27SDimitry Andric for (auto *VT : ValueTypes) {
8506c3fb27SDimitry Andric auto Number = VT->getValueAsInt("Value");
8606c3fb27SDimitry Andric assert(0 <= Number && Number < (int)VTsByNumber.size() &&
8706c3fb27SDimitry Andric "ValueType should be uint8_t");
8806c3fb27SDimitry Andric assert(!VTsByNumber[Number] && "Duplicate ValueType");
8906c3fb27SDimitry Andric VTsByNumber[Number] = VT;
9006c3fb27SDimitry Andric }
9106c3fb27SDimitry Andric
9206c3fb27SDimitry Andric struct VTRange {
9306c3fb27SDimitry Andric StringRef First;
9406c3fb27SDimitry Andric StringRef Last;
9506c3fb27SDimitry Andric bool Closed;
9606c3fb27SDimitry Andric };
9706c3fb27SDimitry Andric
9806c3fb27SDimitry Andric std::map<StringRef, VTRange> VTRanges;
9906c3fb27SDimitry Andric
10006c3fb27SDimitry Andric auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name,
10106c3fb27SDimitry Andric bool Valid) {
10206c3fb27SDimitry Andric if (Valid) {
10306c3fb27SDimitry Andric if (!VTRanges.count(Key))
10406c3fb27SDimitry Andric VTRanges[Key].First = Name;
10506c3fb27SDimitry Andric assert(!VTRanges[Key].Closed && "Gap detected!");
10606c3fb27SDimitry Andric VTRanges[Key].Last = Name;
10706c3fb27SDimitry Andric } else if (VTRanges.count(Key)) {
10806c3fb27SDimitry Andric VTRanges[Key].Closed = true;
10906c3fb27SDimitry Andric }
11006c3fb27SDimitry Andric };
11106c3fb27SDimitry Andric
11206c3fb27SDimitry Andric OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc)\n";
11306c3fb27SDimitry Andric for (const auto *VT : VTsByNumber) {
11406c3fb27SDimitry Andric if (!VT)
11506c3fb27SDimitry Andric continue;
11606c3fb27SDimitry Andric auto Name = VT->getValueAsString("LLVMName");
11706c3fb27SDimitry Andric auto Value = VT->getValueAsInt("Value");
118*0fca6ea1SDimitry Andric bool IsInteger = VT->getValueAsBit("isInteger");
119*0fca6ea1SDimitry Andric bool IsFP = VT->getValueAsBit("isFP");
120*0fca6ea1SDimitry Andric bool IsVector = VT->getValueAsBit("isVector");
121*0fca6ea1SDimitry Andric bool IsScalable = VT->getValueAsBit("isScalable");
122*0fca6ea1SDimitry Andric bool IsNormalValueType = VT->getValueAsBit("isNormalValueType");
123*0fca6ea1SDimitry Andric int64_t NElem = IsVector ? VT->getValueAsInt("nElem") : 0;
124*0fca6ea1SDimitry Andric StringRef EltName = IsVector ? VT->getValueAsDef("ElementType")->getName()
125*0fca6ea1SDimitry Andric : "INVALID_SIMPLE_VALUE_TYPE";
12606c3fb27SDimitry Andric
12706c3fb27SDimitry Andric UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name,
12806c3fb27SDimitry Andric IsInteger && IsVector && !IsScalable);
12906c3fb27SDimitry Andric UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name,
13006c3fb27SDimitry Andric IsInteger && IsScalable);
13106c3fb27SDimitry Andric UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name,
13206c3fb27SDimitry Andric IsFP && IsVector && !IsScalable);
13306c3fb27SDimitry Andric UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable);
13406c3fb27SDimitry Andric UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable);
13506c3fb27SDimitry Andric UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable);
13606c3fb27SDimitry Andric UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector);
13706c3fb27SDimitry Andric UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector);
13806c3fb27SDimitry Andric UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector);
139*0fca6ea1SDimitry Andric UpdateVTRange("VALUETYPE", Name, IsNormalValueType);
14006c3fb27SDimitry Andric
14106c3fb27SDimitry Andric // clang-format off
14206c3fb27SDimitry Andric OS << " GET_VT_ATTR("
14306c3fb27SDimitry Andric << Name << ", "
14406c3fb27SDimitry Andric << Value << ", "
14506c3fb27SDimitry Andric << VT->getValueAsInt("Size") << ", "
146*0fca6ea1SDimitry Andric << VT->getValueAsBit("isOverloaded") << ", "
14706c3fb27SDimitry Andric << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", "
14806c3fb27SDimitry Andric << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", "
14906c3fb27SDimitry Andric << IsVector << ", "
150*0fca6ea1SDimitry Andric << IsScalable << ", "
151*0fca6ea1SDimitry Andric << NElem << ", "
152*0fca6ea1SDimitry Andric << EltName << ")\n";
15306c3fb27SDimitry Andric // clang-format on
15406c3fb27SDimitry Andric }
15506c3fb27SDimitry Andric OS << "#endif\n\n";
15606c3fb27SDimitry Andric
15706c3fb27SDimitry Andric OS << "#ifdef GET_VT_RANGES\n";
15806c3fb27SDimitry Andric for (const auto &KV : VTRanges) {
15906c3fb27SDimitry Andric assert(KV.second.Closed);
16006c3fb27SDimitry Andric OS << " FIRST_" << KV.first << " = " << KV.second.First << ",\n"
16106c3fb27SDimitry Andric << " LAST_" << KV.first << " = " << KV.second.Last << ",\n";
16206c3fb27SDimitry Andric }
16306c3fb27SDimitry Andric OS << "#endif\n\n";
16406c3fb27SDimitry Andric
165*0fca6ea1SDimitry Andric OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, nElem, ElTy)\n";
16606c3fb27SDimitry Andric for (const auto *VT : VTsByNumber) {
167*0fca6ea1SDimitry Andric if (!VT || !VT->getValueAsBit("isVector"))
16806c3fb27SDimitry Andric continue;
16906c3fb27SDimitry Andric const auto *ElTy = VT->getValueAsDef("ElementType");
17006c3fb27SDimitry Andric assert(ElTy);
17106c3fb27SDimitry Andric // clang-format off
17206c3fb27SDimitry Andric OS << " GET_VT_VECATTR("
17306c3fb27SDimitry Andric << VT->getValueAsString("LLVMName") << ", "
174*0fca6ea1SDimitry Andric << VT->getValueAsBit("isScalable") << ", "
17506c3fb27SDimitry Andric << VT->getValueAsInt("nElem") << ", "
176*0fca6ea1SDimitry Andric << ElTy->getName() << ")\n";
17706c3fb27SDimitry Andric // clang-format on
17806c3fb27SDimitry Andric }
17906c3fb27SDimitry Andric OS << "#endif\n\n";
180*0fca6ea1SDimitry Andric
181*0fca6ea1SDimitry Andric OS << "#ifdef GET_VT_EVT\n";
182*0fca6ea1SDimitry Andric for (const auto *VT : VTsByNumber) {
183*0fca6ea1SDimitry Andric if (!VT)
184*0fca6ea1SDimitry Andric continue;
185*0fca6ea1SDimitry Andric bool IsInteger = VT->getValueAsBit("isInteger");
186*0fca6ea1SDimitry Andric bool IsVector = VT->getValueAsBit("isVector");
187*0fca6ea1SDimitry Andric bool IsFP = VT->getValueAsBit("isFP");
188*0fca6ea1SDimitry Andric
189*0fca6ea1SDimitry Andric if (!IsInteger && !IsVector && !IsFP)
190*0fca6ea1SDimitry Andric continue;
191*0fca6ea1SDimitry Andric
192*0fca6ea1SDimitry Andric OS << " GET_VT_EVT(" << VT->getValueAsString("LLVMName") << ", ";
193*0fca6ea1SDimitry Andric VTtoGetLLVMTyString(OS, VT);
194*0fca6ea1SDimitry Andric OS << ")\n";
195*0fca6ea1SDimitry Andric }
196*0fca6ea1SDimitry Andric OS << "#endif\n\n";
19706c3fb27SDimitry Andric }
19806c3fb27SDimitry Andric
19906c3fb27SDimitry Andric static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType");
200