//===- TargetLibraryInfoEmitter.cpp - Properties from TargetLibraryInfo.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 "SequenceToOffsetTable.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/SetTheory.h" #include "llvm/TableGen/StringToOffsetTable.h" #include "llvm/TableGen/TableGenBackend.h" #include #define DEBUG_TYPE "target-library-info-emitter" using namespace llvm; namespace { class TargetLibraryInfoEmitter { private: const RecordKeeper &Records; SmallVector AllTargetLibcalls; private: void emitTargetLibraryInfoEnum(raw_ostream &OS) const; void emitTargetLibraryInfoStringTable(raw_ostream &OS) const; void emitTargetLibraryInfoSignatureTable(raw_ostream &OS) const; public: TargetLibraryInfoEmitter(const RecordKeeper &R); void run(raw_ostream &OS); }; } // End anonymous namespace. TargetLibraryInfoEmitter::TargetLibraryInfoEmitter(const RecordKeeper &R) : Records(R) { ArrayRef All = Records.getAllDerivedDefinitions("TargetLibCall"); AllTargetLibcalls.append(All.begin(), All.end()); // Make sure that the records are in the same order as the input. // TODO Find a better sorting order when all is migrated. sort(AllTargetLibcalls, [](const Record *A, const Record *B) { return A->getID() < B->getID(); }); } // Emits the LibFunc enumeration, which is an abstract name for each library // function. void TargetLibraryInfoEmitter::emitTargetLibraryInfoEnum( raw_ostream &OS) const { OS << "#ifdef GET_TARGET_LIBRARY_INFO_ENUM\n"; OS << "#undef GET_TARGET_LIBRARY_INFO_ENUM\n"; OS << "enum LibFunc : unsigned {\n"; OS.indent(2) << "NotLibFunc = 0,\n"; for (const auto *R : AllTargetLibcalls) { OS.indent(2) << "LibFunc_" << R->getName() << ",\n"; } OS.indent(2) << "NumLibFuncs,\n"; OS.indent(2) << "End_LibFunc = NumLibFuncs,\n"; if (AllTargetLibcalls.size()) { OS.indent(2) << "Begin_LibFunc = LibFunc_" << AllTargetLibcalls[0]->getName() << ",\n"; } else { OS.indent(2) << "Begin_LibFunc = NotLibFunc,\n"; } OS << "};\n"; OS << "#endif\n\n"; } // The names of the functions are stored in a long string, along with support // tables for accessing the offsets of the function names from the beginning of // the string. void TargetLibraryInfoEmitter::emitTargetLibraryInfoStringTable( raw_ostream &OS) const { llvm::StringToOffsetTable Table( /*AppendZero=*/true, "TargetLibraryInfoImpl::", /*UsePrefixForStorageMember=*/false); for (const auto *R : AllTargetLibcalls) Table.GetOrAddStringOffset(R->getValueAsString("String")); OS << "#ifdef GET_TARGET_LIBRARY_INFO_STRING_TABLE\n"; OS << "#undef GET_TARGET_LIBRARY_INFO_STRING_TABLE\n"; Table.EmitStringTableDef(OS, "StandardNamesStrTable"); OS << "\n"; size_t NumEl = AllTargetLibcalls.size() + 1; OS << "const llvm::StringTable::Offset " "TargetLibraryInfoImpl::StandardNamesOffsets[" << NumEl << "] = " "{\n"; OS.indent(2) << "0, //\n"; for (const auto *R : AllTargetLibcalls) { StringRef Str = R->getValueAsString("String"); OS.indent(2) << Table.GetStringOffset(Str) << ", // " << Str << "\n"; } OS << "};\n"; OS << "const uint8_t TargetLibraryInfoImpl::StandardNamesSizeTable[" << NumEl << "] = {\n"; OS << " 0,\n"; for (const auto *R : AllTargetLibcalls) OS.indent(2) << R->getValueAsString("String").size() << ",\n"; OS << "};\n"; OS << "#endif\n\n"; OS << "#ifdef GET_TARGET_LIBRARY_INFO_IMPL_DECL\n"; OS << "#undef GET_TARGET_LIBRARY_INFO_IMPL_DECL\n"; OS << "LLVM_ABI static const llvm::StringTable StandardNamesStrTable;\n"; OS << "LLVM_ABI static const llvm::StringTable::Offset StandardNamesOffsets[" << NumEl << "];\n"; OS << "LLVM_ABI static const uint8_t StandardNamesSizeTable[" << NumEl << "];\n"; OS << "#endif\n\n"; } // Since there are much less type signatures then library functions, the type // signatures are stored reusing existing entries. To access a table entry, an // offset table is used. void TargetLibraryInfoEmitter::emitTargetLibraryInfoSignatureTable( raw_ostream &OS) const { SmallVector FuncTypeArgs( Records.getAllDerivedDefinitions("FuncArgType")); // Sort the records by ID. sort(FuncTypeArgs, [](const Record *A, const Record *B) { return A->getID() < B->getID(); }); using Signature = std::vector; SequenceToOffsetTable SignatureTable("NoFuncArgType"); auto GetSignature = [](const Record *R) -> Signature { const auto *Tys = R->getValueAsListInit("ArgumentTypes"); Signature Sig; Sig.reserve(Tys->size() + 1); const Record *RetType = R->getValueAsOptionalDef("ReturnType"); if (RetType) Sig.push_back(RetType->getName()); for (unsigned I = 0, E = Tys->size(); I < E; ++I) { Sig.push_back(Tys->getElementAsRecord(I)->getName()); } return Sig; }; Signature NoFuncSig({StringRef("Void")}); SignatureTable.add(NoFuncSig); for (const auto *R : AllTargetLibcalls) SignatureTable.add(GetSignature(R)); SignatureTable.layout(); OS << "#ifdef GET_TARGET_LIBRARY_INFO_SIGNATURE_TABLE\n"; OS << "#undef GET_TARGET_LIBRARY_INFO_SIGNATURE_TABLE\n"; OS << "enum FuncArgTypeID : char {\n"; OS.indent(2) << "NoFuncArgType = 0,\n"; for (const auto *R : FuncTypeArgs) { OS.indent(2) << R->getName() << ",\n"; } OS << "};\n"; OS << "static const FuncArgTypeID SignatureTable[] = {\n"; SignatureTable.emit(OS, [](raw_ostream &OS, StringRef E) { OS << E; }); OS << "};\n"; OS << "static const uint16_t SignatureOffset[] = {\n"; OS.indent(2) << SignatureTable.get(NoFuncSig) << ", //\n"; for (const auto *R : AllTargetLibcalls) { OS.indent(2) << SignatureTable.get(GetSignature(R)) << ", // " << R->getName() << "\n"; } OS << "};\n"; OS << "#endif\n\n"; } void TargetLibraryInfoEmitter::run(raw_ostream &OS) { emitSourceFileHeader("Target Library Info Source Fragment", OS, Records); emitTargetLibraryInfoEnum(OS); emitTargetLibraryInfoStringTable(OS); emitTargetLibraryInfoSignatureTable(OS); } static TableGen::Emitter::OptClass X("gen-target-library-info", "Generate TargetLibraryInfo");