186 lines · cpp
1//===- TargetLibraryInfoEmitter.cpp - Properties from TargetLibraryInfo.td ===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "SequenceToOffsetTable.h"10#include "llvm/ADT/StringRef.h"11#include "llvm/Support/Debug.h"12#include "llvm/Support/raw_ostream.h"13#include "llvm/TableGen/Error.h"14#include "llvm/TableGen/Record.h"15#include "llvm/TableGen/SetTheory.h"16#include "llvm/TableGen/StringToOffsetTable.h"17#include "llvm/TableGen/TableGenBackend.h"18#include <cstddef>19 20#define DEBUG_TYPE "target-library-info-emitter"21 22using namespace llvm;23 24namespace {25class TargetLibraryInfoEmitter {26private:27 const RecordKeeper &Records;28 SmallVector<const Record *, 1024> AllTargetLibcalls;29 30private:31 void emitTargetLibraryInfoEnum(raw_ostream &OS) const;32 void emitTargetLibraryInfoStringTable(raw_ostream &OS) const;33 void emitTargetLibraryInfoSignatureTable(raw_ostream &OS) const;34 35public:36 TargetLibraryInfoEmitter(const RecordKeeper &R);37 38 void run(raw_ostream &OS);39};40 41} // End anonymous namespace.42 43TargetLibraryInfoEmitter::TargetLibraryInfoEmitter(const RecordKeeper &R)44 : Records(R) {45 ArrayRef<const Record *> All =46 Records.getAllDerivedDefinitions("TargetLibCall");47 AllTargetLibcalls.append(All.begin(), All.end());48 // Make sure that the records are in the same order as the input.49 // TODO Find a better sorting order when all is migrated.50 sort(AllTargetLibcalls, [](const Record *A, const Record *B) {51 return A->getID() < B->getID();52 });53}54 55// Emits the LibFunc enumeration, which is an abstract name for each library56// function.57void TargetLibraryInfoEmitter::emitTargetLibraryInfoEnum(58 raw_ostream &OS) const {59 OS << "#ifdef GET_TARGET_LIBRARY_INFO_ENUM\n";60 OS << "#undef GET_TARGET_LIBRARY_INFO_ENUM\n";61 OS << "enum LibFunc : unsigned {\n";62 OS.indent(2) << "NotLibFunc = 0,\n";63 for (const auto *R : AllTargetLibcalls) {64 OS.indent(2) << "LibFunc_" << R->getName() << ",\n";65 }66 OS.indent(2) << "NumLibFuncs,\n";67 OS.indent(2) << "End_LibFunc = NumLibFuncs,\n";68 if (AllTargetLibcalls.size()) {69 OS.indent(2) << "Begin_LibFunc = LibFunc_"70 << AllTargetLibcalls[0]->getName() << ",\n";71 } else {72 OS.indent(2) << "Begin_LibFunc = NotLibFunc,\n";73 }74 OS << "};\n";75 OS << "#endif\n\n";76}77 78// The names of the functions are stored in a long string, along with support79// tables for accessing the offsets of the function names from the beginning of80// the string.81void TargetLibraryInfoEmitter::emitTargetLibraryInfoStringTable(82 raw_ostream &OS) const {83 llvm::StringToOffsetTable Table(84 /*AppendZero=*/true,85 "TargetLibraryInfoImpl::", /*UsePrefixForStorageMember=*/false);86 for (const auto *R : AllTargetLibcalls)87 Table.GetOrAddStringOffset(R->getValueAsString("String"));88 89 OS << "#ifdef GET_TARGET_LIBRARY_INFO_STRING_TABLE\n";90 OS << "#undef GET_TARGET_LIBRARY_INFO_STRING_TABLE\n";91 Table.EmitStringTableDef(OS, "StandardNamesStrTable");92 OS << "\n";93 size_t NumEl = AllTargetLibcalls.size() + 1;94 OS << "const llvm::StringTable::Offset "95 "TargetLibraryInfoImpl::StandardNamesOffsets["96 << NumEl97 << "] = "98 "{\n";99 OS.indent(2) << "0, //\n";100 for (const auto *R : AllTargetLibcalls) {101 StringRef Str = R->getValueAsString("String");102 OS.indent(2) << Table.GetStringOffset(Str) << ", // " << Str << "\n";103 }104 OS << "};\n";105 OS << "const uint8_t TargetLibraryInfoImpl::StandardNamesSizeTable[" << NumEl106 << "] = {\n";107 OS << " 0,\n";108 for (const auto *R : AllTargetLibcalls)109 OS.indent(2) << R->getValueAsString("String").size() << ",\n";110 OS << "};\n";111 OS << "#endif\n\n";112 OS << "#ifdef GET_TARGET_LIBRARY_INFO_IMPL_DECL\n";113 OS << "#undef GET_TARGET_LIBRARY_INFO_IMPL_DECL\n";114 OS << "LLVM_ABI static const llvm::StringTable StandardNamesStrTable;\n";115 OS << "LLVM_ABI static const llvm::StringTable::Offset StandardNamesOffsets["116 << NumEl << "];\n";117 OS << "LLVM_ABI static const uint8_t StandardNamesSizeTable[" << NumEl118 << "];\n";119 OS << "#endif\n\n";120}121 122// Since there are much less type signatures then library functions, the type123// signatures are stored reusing existing entries. To access a table entry, an124// offset table is used.125void TargetLibraryInfoEmitter::emitTargetLibraryInfoSignatureTable(126 raw_ostream &OS) const {127 SmallVector<const Record *, 1024> FuncTypeArgs(128 Records.getAllDerivedDefinitions("FuncArgType"));129 130 // Sort the records by ID.131 sort(FuncTypeArgs, [](const Record *A, const Record *B) {132 return A->getID() < B->getID();133 });134 135 using Signature = std::vector<StringRef>;136 SequenceToOffsetTable<Signature> SignatureTable("NoFuncArgType");137 auto GetSignature = [](const Record *R) -> Signature {138 const auto *Tys = R->getValueAsListInit("ArgumentTypes");139 Signature Sig;140 Sig.reserve(Tys->size() + 1);141 const Record *RetType = R->getValueAsOptionalDef("ReturnType");142 if (RetType)143 Sig.push_back(RetType->getName());144 for (unsigned I = 0, E = Tys->size(); I < E; ++I) {145 Sig.push_back(Tys->getElementAsRecord(I)->getName());146 }147 return Sig;148 };149 Signature NoFuncSig({StringRef("Void")});150 SignatureTable.add(NoFuncSig);151 for (const auto *R : AllTargetLibcalls)152 SignatureTable.add(GetSignature(R));153 SignatureTable.layout();154 155 OS << "#ifdef GET_TARGET_LIBRARY_INFO_SIGNATURE_TABLE\n";156 OS << "#undef GET_TARGET_LIBRARY_INFO_SIGNATURE_TABLE\n";157 OS << "enum FuncArgTypeID : char {\n";158 OS.indent(2) << "NoFuncArgType = 0,\n";159 for (const auto *R : FuncTypeArgs) {160 OS.indent(2) << R->getName() << ",\n";161 }162 OS << "};\n";163 OS << "static const FuncArgTypeID SignatureTable[] = {\n";164 SignatureTable.emit(OS, [](raw_ostream &OS, StringRef E) { OS << E; });165 OS << "};\n";166 OS << "static const uint16_t SignatureOffset[] = {\n";167 OS.indent(2) << SignatureTable.get(NoFuncSig) << ", //\n";168 for (const auto *R : AllTargetLibcalls) {169 OS.indent(2) << SignatureTable.get(GetSignature(R)) << ", // "170 << R->getName() << "\n";171 }172 OS << "};\n";173 OS << "#endif\n\n";174}175 176void TargetLibraryInfoEmitter::run(raw_ostream &OS) {177 emitSourceFileHeader("Target Library Info Source Fragment", OS, Records);178 179 emitTargetLibraryInfoEnum(OS);180 emitTargetLibraryInfoStringTable(OS);181 emitTargetLibraryInfoSignatureTable(OS);182}183 184static TableGen::Emitter::OptClass<TargetLibraryInfoEmitter>185 X("gen-target-library-info", "Generate TargetLibraryInfo");186