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