blob: b296c86ffd111d01392ace52a42a0678600cba31 [file] [edit]
//===------------------------------------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_UTILS_TABLEGEN_COMMON_RUNTIMELIBCALLS_H
#define LLVM_UTILS_TABLEGEN_COMMON_RUNTIMELIBCALLS_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/SetTheory.h"
namespace llvm {
class AvailabilityPredicate {
const Record *TheDef;
std::string PredicateString;
public:
AvailabilityPredicate(const Record *Def) : TheDef(Def) {
if (!TheDef)
return;
// An unset CondDag means the libcall is always available.
if (const RecordVal *RV = TheDef->getValue("CondDag")) {
if (const auto *Dag = dyn_cast_or_null<DagInit>(RV->getValue());
Dag && !isa<UnsetInit>(Dag->getOperator()))
PredicateString = lowerCondDag(TheDef, Dag);
}
}
const Record *getDef() const { return TheDef; }
bool isAlwaysAvailable() const { return PredicateString.empty(); }
void emitIf(raw_ostream &OS) const {
OS << "if (" << PredicateString << ") {\n";
}
void emitEndIf(raw_ostream &OS) const { OS << "}\n"; }
void emitTableVariableNameSuffix(raw_ostream &OS) const {
if (TheDef)
OS << '_' << TheDef->getName();
}
private:
// Lower a (all_of/any_of/not <LibcallPredicate>...) dag to a C++ boolean
// expression.
static std::string lowerCondDag(const Record *Owner, const Init *Val,
bool ParenIfBinOp = false);
};
class RuntimeLibcalls;
class RuntimeLibcallImpl;
/// Used to apply predicates to nested sets of libcalls.
struct LibcallPredicateExpander : SetTheory::Expander {
const RuntimeLibcalls &Libcalls;
DenseMap<const RuntimeLibcallImpl *,
std::pair<std::vector<const Record *>, const Record *>> &Func2Preds;
LibcallPredicateExpander(
const RuntimeLibcalls &Libcalls,
DenseMap<const RuntimeLibcallImpl *,
std::pair<std::vector<const Record *>, const Record *>>
&Func2Preds)
: Libcalls(Libcalls), Func2Preds(Func2Preds) {}
void expand(SetTheory &ST, const Record *Def,
SetTheory::RecSet &Elts) override;
};
class RuntimeLibcall {
const Record *TheDef = nullptr;
const size_t EnumVal;
public:
RuntimeLibcall() = delete;
RuntimeLibcall(const Record *Def, size_t EnumVal)
: TheDef(Def), EnumVal(EnumVal) {
assert(Def);
}
~RuntimeLibcall() { assert(TheDef); }
const Record *getDef() const { return TheDef; }
StringRef getName() const { return TheDef->getName(); }
size_t getEnumVal() const { return EnumVal; }
void emitEnumEntry(raw_ostream &OS) const {
OS << "RTLIB::" << TheDef->getValueAsString("Name");
}
};
class RuntimeLibcallImpl {
const Record *TheDef;
const RuntimeLibcall *Provides = nullptr;
const size_t EnumVal;
public:
RuntimeLibcallImpl(
const Record *Def,
const DenseMap<const Record *, const RuntimeLibcall *> &ProvideMap,
size_t EnumVal)
: TheDef(Def), EnumVal(EnumVal) {
if (const Record *ProvidesDef = Def->getValueAsDef("Provides"))
Provides = ProvideMap.lookup(ProvidesDef);
}
~RuntimeLibcallImpl() = default;
const Record *getDef() const { return TheDef; }
StringRef getName() const { return TheDef->getName(); }
size_t getEnumVal() const { return EnumVal; }
const RuntimeLibcall *getProvides() const { return Provides; }
StringRef getLibcallFuncName() const {
return TheDef->getValueAsString("LibCallFuncName");
}
const Record *getCallingConv() const {
return TheDef->getValueAsOptionalDef("CallingConv");
}
void emitQuotedLibcallFuncName(raw_ostream &OS) const {
OS << '\"' << getLibcallFuncName() << '\"';
}
void emitEnumEntry(raw_ostream &OS) const {
OS << "RTLIB::impl_" << this->getName();
}
void emitSetImplCall(raw_ostream &OS) const {
OS << "setLibcallImpl(";
Provides->emitEnumEntry(OS);
OS << ", ";
emitEnumEntry(OS);
OS << "); // " << getLibcallFuncName() << '\n';
}
void emitTableEntry(raw_ostream &OS) const {
OS << '{';
Provides->emitEnumEntry(OS);
OS << ", ";
emitEnumEntry(OS);
OS << "}, // " << getLibcallFuncName() << '\n';
}
void emitSetCallingConv(raw_ostream &OS) const {}
};
struct LibcallsWithCC {
std::vector<const RuntimeLibcallImpl *> LibcallImpls;
const Record *CallingConv = nullptr;
};
class RuntimeLibcalls {
private:
DenseMap<const Record *, const RuntimeLibcall *> Def2RuntimeLibcall;
DenseMap<const Record *, const RuntimeLibcallImpl *> Def2RuntimeLibcallImpl;
std::vector<RuntimeLibcall> RuntimeLibcallDefList;
std::vector<RuntimeLibcallImpl> RuntimeLibcallImplDefList;
public:
RuntimeLibcalls(const RecordKeeper &Records);
ArrayRef<RuntimeLibcall> getRuntimeLibcallDefList() const {
return RuntimeLibcallDefList;
}
ArrayRef<RuntimeLibcallImpl> getRuntimeLibcallImplDefList() const {
return RuntimeLibcallImplDefList;
}
const RuntimeLibcall *getRuntimeLibcall(const Record *Def) const {
return Def2RuntimeLibcall.lookup(Def);
}
const RuntimeLibcallImpl *getRuntimeLibcallImpl(const Record *Def) const {
return Def2RuntimeLibcallImpl.lookup(Def);
}
};
} // namespace llvm
#endif // LLVM_UTILS_TABLEGEN_COMMON_RUNTIMELIBCALLS_H