blob: d398a7e7b58f40a0c33c06febbfa1986bd16de9a [file] [log] [blame]
//===- VTEmitter.cpp - Generate properties from ValueTypes.td -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <array>
#include <cassert>
#include <map>
using namespace llvm;
namespace {
class VTEmitter {
private:
RecordKeeper &Records;
public:
VTEmitter(RecordKeeper &R) : Records(R) {}
void run(raw_ostream &OS);
};
} // End anonymous namespace.
void VTEmitter::run(raw_ostream &OS) {
emitSourceFileHeader("ValueTypes Source Fragment", OS);
std::array<const Record *, 256> VTsByNumber = {};
auto ValueTypes = Records.getAllDerivedDefinitions("ValueType");
for (auto *VT : ValueTypes) {
auto Number = VT->getValueAsInt("Value");
assert(0 <= Number && Number < (int)VTsByNumber.size() &&
"ValueType should be uint8_t");
assert(!VTsByNumber[Number] && "Duplicate ValueType");
VTsByNumber[Number] = VT;
}
struct VTRange {
StringRef First;
StringRef Last;
bool Closed;
};
std::map<StringRef, VTRange> VTRanges;
auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name,
bool Valid) {
if (Valid) {
if (!VTRanges.count(Key))
VTRanges[Key].First = Name;
assert(!VTRanges[Key].Closed && "Gap detected!");
VTRanges[Key].Last = Name;
} else if (VTRanges.count(Key)) {
VTRanges[Key].Closed = true;
}
};
OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc)\n";
for (const auto *VT : VTsByNumber) {
if (!VT)
continue;
auto Name = VT->getValueAsString("LLVMName");
auto Value = VT->getValueAsInt("Value");
bool IsInteger = VT->getValueAsInt("isInteger");
bool IsFP = VT->getValueAsInt("isFP");
bool IsVector = VT->getValueAsInt("isVector");
bool IsScalable = VT->getValueAsInt("isScalable");
UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name,
IsInteger && IsVector && !IsScalable);
UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name,
IsInteger && IsScalable);
UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name,
IsFP && IsVector && !IsScalable);
UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable);
UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable);
UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable);
UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector);
UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector);
UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector);
UpdateVTRange("VALUETYPE", Name, Value < 224);
// clang-format off
OS << " GET_VT_ATTR("
<< Name << ", "
<< Value << ", "
<< VT->getValueAsInt("Size") << ", "
<< VT->getValueAsInt("isOverloaded") << ", "
<< (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", "
<< (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", "
<< IsVector << ", "
<< IsScalable << ")\n";
// clang-format on
}
OS << "#endif\n\n";
OS << "#ifdef GET_VT_RANGES\n";
for (const auto &KV : VTRanges) {
assert(KV.second.Closed);
OS << " FIRST_" << KV.first << " = " << KV.second.First << ",\n"
<< " LAST_" << KV.first << " = " << KV.second.Last << ",\n";
}
OS << "#endif\n\n";
OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, nElem, ElTy, ElSz)\n";
for (const auto *VT : VTsByNumber) {
if (!VT || !VT->getValueAsInt("isVector"))
continue;
const auto *ElTy = VT->getValueAsDef("ElementType");
assert(ElTy);
// clang-format off
OS << " GET_VT_VECATTR("
<< VT->getValueAsString("LLVMName") << ", "
<< VT->getValueAsInt("isScalable") << ", "
<< VT->getValueAsInt("nElem") << ", "
<< ElTy->getName() << ", "
<< ElTy->getValueAsInt("Size") << ")\n";
// clang-format on
}
OS << "#endif\n\n";
}
static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType");