blob: 253d9df44421a5cb20517f462ec39a408e4cdee9 [file] [log] [blame] [edit]
//===- 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 <cstddef>
#define DEBUG_TYPE "target-library-info-emitter"
using namespace llvm;
namespace {
class TargetLibraryInfoEmitter {
private:
const RecordKeeper &Records;
SmallVector<const Record *, 1024> 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<const Record *> 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<const Record *, 1024> 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<StringRef>;
SequenceToOffsetTable<Signature> 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<TargetLibraryInfoEmitter>
X("gen-target-library-info", "Generate TargetLibraryInfo");