181 lines
6.4 KiB
C++
181 lines
6.4 KiB
C++
//===- 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/CodeGenHelpers.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 {
|
|
IfDefEmitter IfDef(OS, "GET_TARGET_LIBRARY_INFO_ENUM");
|
|
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";
|
|
}
|
|
|
|
// 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"));
|
|
|
|
size_t NumEl = AllTargetLibcalls.size() + 1;
|
|
|
|
{
|
|
IfDefEmitter IfDef(OS, "GET_TARGET_LIBRARY_INFO_STRING_TABLE");
|
|
Table.EmitStringTableDef(OS, "StandardNamesStrTable");
|
|
OS << "\n";
|
|
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";
|
|
}
|
|
|
|
IfDefEmitter IfDef(OS, "GET_TARGET_LIBRARY_INFO_IMPL_DECL");
|
|
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";
|
|
}
|
|
|
|
// 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();
|
|
|
|
IfDefEmitter IfDef(OS, "GET_TARGET_LIBRARY_INFO_SIGNATURE_TABLE");
|
|
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";
|
|
}
|
|
|
|
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");
|