aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen/Basic
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/TableGen/Basic')
-rw-r--r--llvm/utils/TableGen/Basic/ARMTargetDefEmitter.cpp11
-rw-r--r--llvm/utils/TableGen/Basic/CMakeLists.txt2
-rw-r--r--llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp69
-rw-r--r--llvm/utils/TableGen/Basic/CodeGenIntrinsics.h21
-rw-r--r--llvm/utils/TableGen/Basic/DirectiveEmitter.cpp197
-rw-r--r--llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp117
-rw-r--r--llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp93
-rw-r--r--llvm/utils/TableGen/Basic/RuntimeLibcalls.h189
-rw-r--r--llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp294
-rw-r--r--llvm/utils/TableGen/Basic/SequenceToOffsetTable.h7
-rw-r--r--llvm/utils/TableGen/Basic/TableGen.cpp7
-rw-r--r--llvm/utils/TableGen/Basic/TargetLibraryInfoEmitter.cpp185
-rw-r--r--llvm/utils/TableGen/Basic/VTEmitter.cpp17
13 files changed, 798 insertions, 411 deletions
diff --git a/llvm/utils/TableGen/Basic/ARMTargetDefEmitter.cpp b/llvm/utils/TableGen/Basic/ARMTargetDefEmitter.cpp
index 3f284ee..a18fed0 100644
--- a/llvm/utils/TableGen/Basic/ARMTargetDefEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/ARMTargetDefEmitter.cpp
@@ -159,12 +159,15 @@ static void emitARMTargetDef(const RecordKeeper &RK, raw_ostream &OS) {
<< " if(I.size()) return I;\n"
<< " I.reserve(" << FMVExts.size() << ");\n";
for (const Record *Rec : FMVExts) {
+ auto FeatName = Rec->getValueAsString("BackendFeature");
+ const Record *FeatRec = ExtensionMap[FeatName];
OS << " I.emplace_back(";
OS << "\"" << Rec->getValueAsString("Name") << "\"";
- OS << ", " << Rec->getValueAsString("FeatureBit");
+ if (FeatRec)
+ OS << ", " << Rec->getValueAsString("FeatureBit");
+ else
+ OS << ", std::nullopt";
OS << ", " << Rec->getValueAsString("PriorityBit");
- auto FeatName = Rec->getValueAsString("BackendFeature");
- const Record *FeatRec = ExtensionMap[FeatName];
if (FeatRec)
OS << ", " << FeatRec->getValueAsString("ArchExtKindSpelling").upper();
else
@@ -220,7 +223,7 @@ static void emitARMTargetDef(const RecordKeeper &RK, raw_ostream &OS) {
ProfileLower + "'");
// Name of the object in C++
- const std::string CppSpelling = ArchInfoName(Major, Minor, ProfileUpper);
+ std::string CppSpelling = ArchInfoName(Major, Minor, ProfileUpper);
OS << "inline constexpr ArchInfo " << CppSpelling << " = {\n";
CppSpellings.push_back(std::move(CppSpelling));
diff --git a/llvm/utils/TableGen/Basic/CMakeLists.txt b/llvm/utils/TableGen/Basic/CMakeLists.txt
index b4a66ec..01ab8a0 100644
--- a/llvm/utils/TableGen/Basic/CMakeLists.txt
+++ b/llvm/utils/TableGen/Basic/CMakeLists.txt
@@ -16,9 +16,11 @@ add_llvm_library(LLVMTableGenBasic OBJECT EXCLUDE_FROM_ALL DISABLE_LLVM_LINK_LLV
IntrinsicEmitter.cpp
RISCVTargetDefEmitter.cpp
RuntimeLibcallsEmitter.cpp
+ RuntimeLibcalls.cpp
SDNodeProperties.cpp
TableGen.cpp
TargetFeaturesEmitter.cpp
+ TargetLibraryInfoEmitter.cpp
VTEmitter.cpp
)
diff --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
index cd86646..d90fcc2 100644
--- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
+++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
@@ -13,6 +13,7 @@
#include "CodeGenIntrinsics.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/TableGen/Error.h"
@@ -377,7 +378,19 @@ void CodeGenIntrinsic::setProperty(const Record *R) {
ME &= MemoryEffects::argMemOnly();
else if (R->getName() == "IntrInaccessibleMemOnly")
ME &= MemoryEffects::inaccessibleMemOnly();
- else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")
+ else if (R->isSubClassOf("IntrRead")) {
+ MemoryEffects ReadMask = MemoryEffects::writeOnly();
+ for (const Record *RLoc : R->getValueAsListOfDefs("MemLoc"))
+ ReadMask = ReadMask.getWithModRef(getValueAsIRMemLocation(RLoc),
+ ModRefInfo::ModRef);
+ ME &= ReadMask;
+ } else if (R->isSubClassOf("IntrWrite")) {
+ MemoryEffects WriteMask = MemoryEffects::readOnly();
+ for (const Record *WLoc : R->getValueAsListOfDefs("MemLoc"))
+ WriteMask = WriteMask.getWithModRef(getValueAsIRMemLocation(WLoc),
+ ModRefInfo::ModRef);
+ ME &= WriteMask;
+ } else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")
ME &= MemoryEffects::inaccessibleOrArgMemOnly();
else if (R->getName() == "Commutative")
isCommutative = true;
@@ -407,6 +420,8 @@ void CodeGenIntrinsic::setProperty(const Record *R) {
hasSideEffects = true;
else if (R->getName() == "IntrStrictFP")
isStrictFP = true;
+ else if (R->getName() == "IntrNoCreateUndefOrPoison")
+ isNoCreateUndefOrPoison = true;
else if (R->isSubClassOf("NoCapture")) {
unsigned ArgNo = R->getValueAsInt("ArgNo");
addArgAttribute(ArgNo, NoCapture);
@@ -447,11 +462,50 @@ void CodeGenIntrinsic::setProperty(const Record *R) {
int64_t Lower = R->getValueAsInt("Lower");
int64_t Upper = R->getValueAsInt("Upper");
addArgAttribute(ArgNo, Range, Lower, Upper);
+ } else if (R->isSubClassOf("ArgInfo")) {
+ unsigned ArgNo = R->getValueAsInt("ArgNo");
+ if (ArgNo < 1)
+ PrintFatalError(R->getLoc(),
+ "ArgInfo requires ArgNo >= 1 (0 is return value)");
+ const ListInit *Properties = R->getValueAsListInit("Properties");
+ StringRef ArgName;
+ StringRef FuncName;
+
+ for (const Init *PropInit : Properties->getElements()) {
+ if (const auto *PropDef = dyn_cast<DefInit>(PropInit)) {
+ const Record *PropRec = PropDef->getDef();
+
+ if (PropRec->isSubClassOf("ArgName"))
+ ArgName = PropRec->getValueAsString("Name");
+ else if (PropRec->isSubClassOf("ImmArgPrinter"))
+ FuncName = PropRec->getValueAsString("FuncName");
+ else
+ PrintFatalError(PropRec->getLoc(),
+ "Unknown ArgProperty type: " + PropRec->getName());
+ }
+ }
+ addPrettyPrintFunction(ArgNo - 1, ArgName, FuncName);
} else {
llvm_unreachable("Unknown property!");
}
}
+llvm::IRMemLocation
+CodeGenIntrinsic::getValueAsIRMemLocation(const Record *R) const {
+ StringRef Name = R->getName();
+ IRMemLocation Loc =
+ StringSwitch<IRMemLocation>(Name)
+ .Case("TargetMem0", IRMemLocation::TargetMem0)
+ .Case("TargetMem1", IRMemLocation::TargetMem1)
+ .Case("InaccessibleMem", IRMemLocation::InaccessibleMem)
+ .Default(IRMemLocation::Other); // fallback enum
+
+ if (Loc == IRMemLocation::Other)
+ PrintFatalError(R->getLoc(), "unknown IRMemLocation: " + Name);
+
+ return Loc;
+}
+
bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const {
if (ParamIdx >= IS.ParamTys.size())
return false;
@@ -474,3 +528,16 @@ void CodeGenIntrinsic::addArgAttribute(unsigned Idx, ArgAttrKind AK, uint64_t V,
ArgumentAttributes.resize(Idx + 1);
ArgumentAttributes[Idx].emplace_back(AK, V, V2);
}
+
+void CodeGenIntrinsic::addPrettyPrintFunction(unsigned ArgIdx,
+ StringRef ArgName,
+ StringRef FuncName) {
+ auto It = llvm::find_if(PrettyPrintFunctions, [ArgIdx](const auto &Info) {
+ return Info.ArgIdx == ArgIdx;
+ });
+ if (It != PrettyPrintFunctions.end())
+ PrintFatalError(TheDef->getLoc(), "ArgInfo for argument " + Twine(ArgIdx) +
+ " is already defined as '" +
+ It->FuncName + "'");
+ PrettyPrintFunctions.emplace_back(ArgIdx, ArgName, FuncName);
+}
diff --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
index 2e86149..305260a 100644
--- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
+++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
@@ -114,6 +114,9 @@ struct CodeGenIntrinsic {
// True if the intrinsic is marked as strictfp.
bool isStrictFP = false;
+ // True if the intrinsic is marked as IntrNoCreateUndefOrPoison.
+ bool isNoCreateUndefOrPoison = false;
+
enum ArgAttrKind {
NoCapture,
NoAlias,
@@ -149,6 +152,22 @@ struct CodeGenIntrinsic {
void addArgAttribute(unsigned Idx, ArgAttrKind AK, uint64_t V = 0,
uint64_t V2 = 0);
+ /// Structure to store pretty print and argument information.
+ struct PrettyPrintArgInfo {
+ unsigned ArgIdx;
+ StringRef ArgName;
+ StringRef FuncName;
+
+ PrettyPrintArgInfo(unsigned Idx, StringRef Name, StringRef Func)
+ : ArgIdx(Idx), ArgName(Name), FuncName(Func) {}
+ };
+
+ /// Vector that stores ArgInfo (ArgIndex, ArgName, FunctionName).
+ SmallVector<PrettyPrintArgInfo> PrettyPrintFunctions;
+
+ void addPrettyPrintFunction(unsigned ArgIdx, StringRef ArgName,
+ StringRef FuncName);
+
bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
/// Goes through all IntrProperties that have IsDefault value set and sets
@@ -167,6 +186,8 @@ struct CodeGenIntrinsic {
bool isParamImmArg(unsigned ParamIdx) const;
+ llvm::IRMemLocation getValueAsIRMemLocation(const Record *R) const;
+
CodeGenIntrinsic(const Record *R, const CodeGenIntrinsicContext &Ctx);
};
diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
index 3c6ff11..1126c83 100644
--- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
@@ -81,6 +81,7 @@ static void generateEnumExports(ArrayRef<const Record *> Records,
std::string N = getIdentifierName(R, Prefix);
OS << "constexpr auto " << N << " = " << Enum << "::" << N << ";\n";
}
+ OS << "\n";
}
// Generate enum class. Entries are emitted in the order in which they appear
@@ -88,7 +89,6 @@ static void generateEnumExports(ArrayRef<const Record *> Records,
static void generateEnumClass(ArrayRef<const Record *> Records, raw_ostream &OS,
StringRef Enum, StringRef Prefix,
bool ExportEnums) {
- OS << "\n";
OS << "enum class " << Enum << " {\n";
if (!Records.empty()) {
std::string N;
@@ -104,17 +104,15 @@ static void generateEnumClass(ArrayRef<const Record *> Records, raw_ostream &OS,
OS << "};\n";
OS << "\n";
OS << "static constexpr std::size_t " << Enum
- << "_enumSize = " << Records.size() << ";\n";
+ << "_enumSize = " << Records.size() << ";\n\n";
// Make the enum values available in the defined namespace. This allows us to
// write something like Enum_X if we have a `using namespace <CppNamespace>`.
// At the same time we do not loose the strong type guarantees of the enum
// class, that is we cannot pass an unsigned as Directive without an explicit
// cast.
- if (ExportEnums) {
- OS << "\n";
+ if (ExportEnums)
generateEnumExports(Records, OS, Enum, Prefix);
- }
}
// Generate enum class with values corresponding to different bit positions.
@@ -127,7 +125,6 @@ static void generateEnumBitmask(ArrayRef<const Record *> Records,
StringRef Type = Records.size() <= 32 ? "uint32_t" : "uint64_t";
StringRef TypeSuffix = Records.size() <= 32 ? "U" : "ULL";
- OS << "\n";
OS << "enum class " << Enum << " : " << Type << " {\n";
std::string LastName;
for (auto [I, R] : llvm::enumerate(Records)) {
@@ -138,17 +135,15 @@ static void generateEnumBitmask(ArrayRef<const Record *> Records,
OS << "};\n";
OS << "\n";
OS << "static constexpr std::size_t " << Enum
- << "_enumSize = " << Records.size() << ";\n";
+ << "_enumSize = " << Records.size() << ";\n\n";
// Make the enum values available in the defined namespace. This allows us to
// write something like Enum_X if we have a `using namespace <CppNamespace>`.
// At the same time we do not loose the strong type guarantees of the enum
// class, that is we cannot pass an unsigned as Directive without an explicit
// cast.
- if (ExportEnums) {
- OS << "\n";
+ if (ExportEnums)
generateEnumExports(Records, OS, Enum, Prefix);
- }
}
// Generate enums for values that clauses can take.
@@ -170,7 +165,6 @@ static void generateClauseEnumVal(ArrayRef<const Record *> Records,
return;
}
- OS << "\n";
OS << "enum class " << Enum << " {\n";
for (const EnumVal Val : ClauseVals)
OS << " " << Val.getRecordName() << "=" << Val.getValue() << ",\n";
@@ -182,6 +176,7 @@ static void generateClauseEnumVal(ArrayRef<const Record *> Records,
OS << "constexpr auto " << CV->getName() << " = " << Enum
<< "::" << CV->getName() << ";\n";
}
+ OS << "\n";
EnumHelperFuncs += (Twine("LLVM_ABI ") + Twine(Enum) + Twine(" get") +
Twine(Enum) + Twine("(StringRef Str);\n"))
.str();
@@ -281,84 +276,81 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << "#include <utility>\n"; // for std::pair
OS << "\n";
NamespaceEmitter LlvmNS(OS, "llvm");
- NamespaceEmitter DirLangNS(OS, DirLang.getCppNamespace());
-
- if (DirLang.hasEnableBitmaskEnumInNamespace())
- OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n";
-
- // Emit Directive associations
- std::vector<const Record *> Associations;
- copy_if(DirLang.getAssociations(), std::back_inserter(Associations),
- // Skip the "special" value
- [](const Record *Def) { return Def->getName() != "AS_FromLeaves"; });
- generateEnumClass(Associations, OS, "Association",
- /*Prefix=*/"", /*ExportEnums=*/false);
-
- generateEnumClass(DirLang.getCategories(), OS, "Category", /*Prefix=*/"",
- /*ExportEnums=*/false);
-
- generateEnumBitmask(DirLang.getSourceLanguages(), OS, "SourceLanguage",
+ {
+ NamespaceEmitter DirLangNS(OS, DirLang.getCppNamespace());
+
+ if (DirLang.hasEnableBitmaskEnumInNamespace())
+ OS << "LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n\n";
+
+ // Emit Directive associations
+ std::vector<const Record *> Associations;
+ copy_if(
+ DirLang.getAssociations(), std::back_inserter(Associations),
+ // Skip the "special" value
+ [](const Record *Def) { return Def->getName() != "AS_FromLeaves"; });
+ generateEnumClass(Associations, OS, "Association",
/*Prefix=*/"", /*ExportEnums=*/false);
- // Emit Directive enumeration
- generateEnumClass(DirLang.getDirectives(), OS, "Directive",
- DirLang.getDirectivePrefix(),
- DirLang.hasMakeEnumAvailableInNamespace());
+ generateEnumClass(DirLang.getCategories(), OS, "Category", /*Prefix=*/"",
+ /*ExportEnums=*/false);
- // Emit Clause enumeration
- generateEnumClass(DirLang.getClauses(), OS, "Clause",
- DirLang.getClausePrefix(),
- DirLang.hasMakeEnumAvailableInNamespace());
+ generateEnumBitmask(DirLang.getSourceLanguages(), OS, "SourceLanguage",
+ /*Prefix=*/"", /*ExportEnums=*/false);
- // Emit ClauseVals enumeration
- std::string EnumHelperFuncs;
- generateClauseEnumVal(DirLang.getClauses(), OS, DirLang, EnumHelperFuncs);
+ // Emit Directive enumeration
+ generateEnumClass(DirLang.getDirectives(), OS, "Directive",
+ DirLang.getDirectivePrefix(),
+ DirLang.hasMakeEnumAvailableInNamespace());
- // Generic function signatures
- OS << "\n";
- OS << "// Enumeration helper functions\n";
+ // Emit Clause enumeration
+ generateEnumClass(DirLang.getClauses(), OS, "Clause",
+ DirLang.getClausePrefix(),
+ DirLang.hasMakeEnumAvailableInNamespace());
- OS << "LLVM_ABI std::pair<Directive, directive::VersionRange> get" << Lang
- << "DirectiveKindAndVersions(StringRef Str);\n";
+ // Emit ClauseVals enumeration
+ std::string EnumHelperFuncs;
+ generateClauseEnumVal(DirLang.getClauses(), OS, DirLang, EnumHelperFuncs);
- OS << "inline Directive get" << Lang << "DirectiveKind(StringRef Str) {\n";
- OS << " return get" << Lang << "DirectiveKindAndVersions(Str).first;\n";
- OS << "}\n";
- OS << "\n";
+ // Generic function signatures
+ OS << "// Enumeration helper functions\n";
- OS << "LLVM_ABI StringRef get" << Lang
- << "DirectiveName(Directive D, unsigned Ver = 0);\n";
- OS << "\n";
+ OS << "LLVM_ABI std::pair<Directive, directive::VersionRange> get" << Lang
+ << "DirectiveKindAndVersions(StringRef Str);\n";
- OS << "LLVM_ABI std::pair<Clause, directive::VersionRange> get" << Lang
- << "ClauseKindAndVersions(StringRef Str);\n";
- OS << "\n";
+ OS << "inline Directive get" << Lang << "DirectiveKind(StringRef Str) {\n";
+ OS << " return get" << Lang << "DirectiveKindAndVersions(Str).first;\n";
+ OS << "}\n";
+ OS << "\n";
- OS << "inline Clause get" << Lang << "ClauseKind(StringRef Str) {\n";
- OS << " return get" << Lang << "ClauseKindAndVersions(Str).first;\n";
- OS << "}\n";
- OS << "\n";
+ OS << "LLVM_ABI StringRef get" << Lang
+ << "DirectiveName(Directive D, unsigned Ver = 0);\n";
+ OS << "\n";
- OS << "LLVM_ABI StringRef get" << Lang
- << "ClauseName(Clause C, unsigned Ver = 0);\n";
- OS << "\n";
+ OS << "LLVM_ABI std::pair<Clause, directive::VersionRange> get" << Lang
+ << "ClauseKindAndVersions(StringRef Str);\n";
+ OS << "\n";
- OS << "/// Return true if \\p C is a valid clause for \\p D in version \\p "
- << "Version.\n";
- OS << "LLVM_ABI bool isAllowedClauseForDirective(Directive D, "
- << "Clause C, unsigned Version);\n";
- OS << "\n";
- OS << "constexpr std::size_t getMaxLeafCount() { return "
- << getMaxLeafCount(DirLang) << "; }\n";
- OS << "LLVM_ABI Association getDirectiveAssociation(Directive D);\n";
- OS << "LLVM_ABI Category getDirectiveCategory(Directive D);\n";
- OS << "LLVM_ABI SourceLanguage getDirectiveLanguages(Directive D);\n";
- if (EnumHelperFuncs.length() > 0) {
- OS << EnumHelperFuncs;
+ OS << "inline Clause get" << Lang << "ClauseKind(StringRef Str) {\n";
+ OS << " return get" << Lang << "ClauseKindAndVersions(Str).first;\n";
+ OS << "}\n";
OS << "\n";
- }
- DirLangNS.close();
+ OS << "LLVM_ABI StringRef get" << Lang
+ << "ClauseName(Clause C, unsigned Ver = 0);\n";
+ OS << "\n";
+
+ OS << "/// Return true if \\p C is a valid clause for \\p D in version \\p "
+ << "Version.\n";
+ OS << "LLVM_ABI bool isAllowedClauseForDirective(Directive D, "
+ << "Clause C, unsigned Version);\n";
+ OS << "\n";
+ OS << "constexpr std::size_t getMaxLeafCount() { return "
+ << getMaxLeafCount(DirLang) << "; }\n";
+ OS << "LLVM_ABI Association getDirectiveAssociation(Directive D);\n";
+ OS << "LLVM_ABI Category getDirectiveCategory(Directive D);\n";
+ OS << "LLVM_ABI SourceLanguage getDirectiveLanguages(Directive D);\n";
+ OS << EnumHelperFuncs;
+ } // close DirLangNS
// These specializations need to be in ::llvm.
for (StringRef Enum : {"Association", "Category", "Directive", "Clause"}) {
@@ -368,7 +360,6 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << " static constexpr bool is_iterable = true;\n";
OS << "};\n";
}
- LlvmNS.close();
}
// Given a list of spellings (for a given clause/directive), order them
@@ -738,11 +729,12 @@ static void emitLeafTable(const DirectiveLanguage &DirLang, raw_ostream &OS,
static void generateGetDirectiveAssociation(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
enum struct Association {
- None = 0, // None should be the smallest value.
- Block, // The values of the rest don't matter.
- Declaration,
+ None = 0, // None should be the smallest value.
+ Block, // If the order of the rest of these changes, update the
+ Declaration, // 'Reduce' function below.
Delimited,
- Loop,
+ LoopNest,
+ LoopSeq,
Separating,
FromLeaves,
Invalid,
@@ -755,7 +747,8 @@ static void generateGetDirectiveAssociation(const DirectiveLanguage &DirLang,
.Case("AS_Block", Association::Block)
.Case("AS_Declaration", Association::Declaration)
.Case("AS_Delimited", Association::Delimited)
- .Case("AS_Loop", Association::Loop)
+ .Case("AS_LoopNest", Association::LoopNest)
+ .Case("AS_LoopSeq", Association::LoopSeq)
.Case("AS_None", Association::None)
.Case("AS_Separating", Association::Separating)
.Case("AS_FromLeaves", Association::FromLeaves)
@@ -786,13 +779,12 @@ static void generateGetDirectiveAssociation(const DirectiveLanguage &DirLang,
// Calculate the result using the following rules:
// x + x = x
// AS_None + x = x
- // AS_Block + AS_Loop = AS_Loop
+ // AS_Block + AS_Loop{Nest|Seq} = AS_Loop{Nest|Seq}
if (A == Association::None || A == B)
return B;
- if (A == Association::Block && B == Association::Loop)
+ if (A == Association::Block &&
+ (B == Association::LoopNest || B == Association::LoopSeq))
return B;
- if (A == Association::Loop && B == Association::Block)
- return A;
return Association::Invalid;
};
@@ -940,27 +932,20 @@ static void generateClauseSet(ArrayRef<const Record *> VerClauses,
// Generate an enum set for the 4 kinds of clauses linked to a directive.
static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
Frontend FE, raw_ostream &OS) {
+ IfDefEmitter Scope(OS, "GEN_" + getFESpelling(FE).upper() +
+ "_DIRECTIVE_CLAUSE_SETS");
- std::string IfDefName{"GEN_"};
- IfDefName += getFESpelling(FE).upper();
- IfDefName += "_DIRECTIVE_CLAUSE_SETS";
- IfDefEmitter Scope(OS, IfDefName);
-
- StringRef Namespace =
- getFESpelling(FE == Frontend::Flang ? Frontend::LLVM : FE);
+ std::string Namespace =
+ getFESpelling(FE == Frontend::Flang ? Frontend::LLVM : FE).str();
// The namespace has to be different for clang vs flang, as 2 structs with the
// same name but different layout is UB. So just put the 'clang' on in the
// clang namespace.
- OS << "namespace " << Namespace << " {\n";
-
- // Open namespaces defined in the directive language.
- SmallVector<StringRef, 2> Namespaces;
- SplitString(DirLang.getCppNamespace(), Namespaces, "::");
- for (auto Ns : Namespaces)
- OS << "namespace " << Ns << " {\n";
+ // Additionally, open namespaces defined in the directive language.
+ if (!DirLang.getCppNamespace().empty())
+ Namespace += "::" + DirLang.getCppNamespace().str();
+ NamespaceEmitter NS(OS, Namespace);
for (const Directive Dir : DirLang.getDirectives()) {
- OS << "\n";
OS << "// Sets for " << Dir.getSpellingForIdentifier() << "\n";
generateClauseSet(Dir.getAllowedClauses(), OS, "allowedClauses_", Dir,
@@ -972,12 +957,6 @@ static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
generateClauseSet(Dir.getRequiredClauses(), OS, "requiredClauses_", Dir,
DirLang, FE);
}
-
- // Closing namespaces
- for (auto Ns : reverse(Namespaces))
- OS << "} // namespace " << Ns << "\n";
-
- OS << "} // namespace " << Namespace << "\n";
}
// Generate a map of directive (key) with DirectiveClauses struct as values.
@@ -985,10 +964,8 @@ static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
// allowances (allowed, allowed once, allowed exclusive and required).
static void generateDirectiveClauseMap(const DirectiveLanguage &DirLang,
Frontend FE, raw_ostream &OS) {
- std::string IfDefName{"GEN_"};
- IfDefName += getFESpelling(FE).upper();
- IfDefName += "_DIRECTIVE_CLAUSE_MAP";
- IfDefEmitter Scope(OS, IfDefName);
+ IfDefEmitter Scope(OS, "GEN_" + getFESpelling(FE).upper() +
+ "_DIRECTIVE_CLAUSE_MAP");
OS << "{\n";
diff --git a/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp b/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
index 75dffb1..9fed592 100644
--- a/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
@@ -60,8 +60,16 @@ public:
raw_ostream &OS);
void EmitIntrinsicToOverloadTable(const CodeGenIntrinsicTable &Ints,
raw_ostream &OS);
+ void EmitIntrinsicToPrettyPrintTable(const CodeGenIntrinsicTable &Ints,
+ raw_ostream &OS);
+ void EmitIntrinsicBitTable(
+ const CodeGenIntrinsicTable &Ints, raw_ostream &OS, StringRef Guard,
+ StringRef TableName, StringRef Comment,
+ function_ref<bool(const CodeGenIntrinsic &Int)> GetProperty);
void EmitGenerator(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
void EmitAttributes(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
+ void EmitPrettyPrintArguments(const CodeGenIntrinsicTable &Ints,
+ raw_ostream &OS);
void EmitIntrinsicToBuiltinMap(const CodeGenIntrinsicTable &Ints,
bool IsClang, raw_ostream &OS);
};
@@ -109,6 +117,12 @@ void IntrinsicEmitter::run(raw_ostream &OS, bool Enums) {
// Emit the intrinsic parameter attributes.
EmitAttributes(Ints, OS);
+ // Emit the intrinsic ID -> pretty print table.
+ EmitIntrinsicToPrettyPrintTable(Ints, OS);
+
+ // Emit Pretty Print attribute.
+ EmitPrettyPrintArguments(Ints, OS);
+
// Emit code to translate Clang builtins into LLVM intrinsics.
EmitIntrinsicToBuiltinMap(Ints, true, OS);
@@ -240,6 +254,29 @@ static constexpr IntrinsicTargetInfo TargetInfos[] = {
)";
}
+/// Helper function to emit a bit table for intrinsic properties.
+/// This is used for both overload and pretty print bit tables.
+void IntrinsicEmitter::EmitIntrinsicBitTable(
+ const CodeGenIntrinsicTable &Ints, raw_ostream &OS, StringRef Guard,
+ StringRef TableName, StringRef Comment,
+ function_ref<bool(const CodeGenIntrinsic &Int)> GetProperty) {
+ OS << formatv("// {}\n", Comment);
+ OS << formatv("#ifdef {}\n", Guard);
+ OS << formatv("static constexpr uint8_t {}[] = {{\n", TableName);
+ OS << " 0\n ";
+ for (auto [I, Int] : enumerate(Ints)) {
+ // Add one to the index so we emit a null bit for the invalid #0 intrinsic.
+ size_t Idx = I + 1;
+ if (Idx % 8 == 0)
+ OS << ",\n 0";
+ if (GetProperty(Int))
+ OS << " | (1<<" << Idx % 8 << ')';
+ }
+ OS << "\n};\n\n";
+ OS << formatv("return ({}[id/8] & (1 << (id%8))) != 0;\n", TableName);
+ OS << formatv("#endif // {}\n\n", Guard);
+}
+
void IntrinsicEmitter::EmitIntrinsicToNameTable(
const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
// Built up a table of the intrinsic names.
@@ -276,24 +313,10 @@ static constexpr unsigned IntrinsicNameOffsetTable[] = {
void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
- OS << R"(// Intrinsic ID to overload bitset.
-#ifdef GET_INTRINSIC_OVERLOAD_TABLE
-static constexpr uint8_t OTable[] = {
- 0
- )";
- for (auto [I, Int] : enumerate(Ints)) {
- // Add one to the index so we emit a null bit for the invalid #0 intrinsic.
- size_t Idx = I + 1;
-
- if (Idx % 8 == 0)
- OS << ",\n 0";
- if (Int.isOverloaded)
- OS << " | (1<<" << Idx % 8 << ')';
- }
- OS << "\n};\n\n";
- // OTable contains a true bit at the position if the intrinsic is overloaded.
- OS << "return (OTable[id/8] & (1 << (id%8))) != 0;\n";
- OS << "#endif\n\n";
+ EmitIntrinsicBitTable(
+ Ints, OS, "GET_INTRINSIC_OVERLOAD_TABLE", "OTable",
+ "Intrinsic ID to overload bitset.",
+ [](const CodeGenIntrinsic &Int) { return Int.isOverloaded; });
}
using TypeSigTy = SmallVector<unsigned char>;
@@ -421,7 +444,8 @@ static bool compareFnAttributes(const CodeGenIntrinsic *L,
return std::tie(I->canThrow, I->isNoDuplicate, I->isNoMerge, I->isNoReturn,
I->isNoCallback, I->isNoSync, I->isNoFree, I->isWillReturn,
I->isCold, I->isConvergent, I->isSpeculatable,
- I->hasSideEffects, I->isStrictFP);
+ I->hasSideEffects, I->isStrictFP,
+ I->isNoCreateUndefOrPoison);
};
auto TieL = TieBoolAttributes(L);
@@ -446,7 +470,8 @@ static bool hasFnAttributes(const CodeGenIntrinsic &Int) {
return !Int.canThrow || Int.isNoReturn || Int.isNoCallback || Int.isNoSync ||
Int.isNoFree || Int.isWillReturn || Int.isCold || Int.isNoDuplicate ||
Int.isNoMerge || Int.isConvergent || Int.isSpeculatable ||
- Int.isStrictFP || getEffectiveME(Int) != MemoryEffects::unknown();
+ Int.isStrictFP || Int.isNoCreateUndefOrPoison ||
+ getEffectiveME(Int) != MemoryEffects::unknown();
}
namespace {
@@ -574,10 +599,10 @@ static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
if (!UniqFnAttributes.try_emplace(&Int, ID).second)
continue;
OS << formatv(R"(
- case {}:
+ case {}: // {}
return AttributeSet::get(C, {{
)",
- ID);
+ ID, Int.Name);
auto addAttribute = [&OS](StringRef Attr) {
OS << formatv(" Attribute::get(C, Attribute::{}),\n", Attr);
};
@@ -605,6 +630,8 @@ static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
addAttribute("Speculatable");
if (Int.isStrictFP)
addAttribute("StrictFP");
+ if (Int.isNoCreateUndefOrPoison)
+ addAttribute("NoCreateUndefOrPoison");
const MemoryEffects ME = getEffectiveME(Int);
if (ME != MemoryEffects::unknown()) {
@@ -805,6 +832,52 @@ AttributeSet Intrinsic::getFnAttributes(LLVMContext &C, ID id) {{
NoFunctionAttrsID);
}
+void IntrinsicEmitter::EmitIntrinsicToPrettyPrintTable(
+ const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
+ EmitIntrinsicBitTable(Ints, OS, "GET_INTRINSIC_PRETTY_PRINT_TABLE", "PPTable",
+ "Intrinsic ID to pretty print bitset.",
+ [](const CodeGenIntrinsic &Int) {
+ return !Int.PrettyPrintFunctions.empty();
+ });
+}
+
+void IntrinsicEmitter::EmitPrettyPrintArguments(
+ const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
+ OS << R"(
+#ifdef GET_INTRINSIC_PRETTY_PRINT_ARGUMENTS
+void Intrinsic::printImmArg(ID IID, unsigned ArgIdx, raw_ostream &OS, const Constant *ImmArgVal) {
+ using namespace Intrinsic;
+ switch (IID) {
+)";
+
+ for (const CodeGenIntrinsic &Int : Ints) {
+ if (Int.PrettyPrintFunctions.empty())
+ continue;
+
+ OS << " case " << Int.EnumName << ":\n";
+ OS << " switch (ArgIdx) {\n";
+ for (const auto [ArgIdx, ArgName, FuncName] : Int.PrettyPrintFunctions) {
+ OS << " case " << ArgIdx << ":\n";
+ OS << " OS << \"" << ArgName << "=\";\n";
+ if (!FuncName.empty()) {
+ OS << " ";
+ if (!Int.TargetPrefix.empty())
+ OS << Int.TargetPrefix << "::";
+ OS << FuncName << "(OS, ImmArgVal);\n";
+ }
+ OS << " return;\n";
+ }
+ OS << " }\n";
+ OS << " break;\n";
+ }
+ OS << R"( default:
+ break;
+ }
+}
+#endif // GET_INTRINSIC_PRETTY_PRINT_ARGUMENTS
+)";
+}
+
void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
const CodeGenIntrinsicTable &Ints, bool IsClang, raw_ostream &OS) {
StringRef CompilerName = IsClang ? "Clang" : "MS";
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp
new file mode 100644
index 0000000..1e609a2
--- /dev/null
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp
@@ -0,0 +1,93 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "RuntimeLibcalls.h"
+#include "llvm/TableGen/Error.h"
+
+using namespace llvm;
+
+RuntimeLibcalls::RuntimeLibcalls(const RecordKeeper &Records) {
+ ArrayRef<const Record *> AllRuntimeLibcalls =
+ Records.getAllDerivedDefinitions("RuntimeLibcall");
+
+ RuntimeLibcallDefList.reserve(AllRuntimeLibcalls.size());
+
+ size_t CallTypeEnumVal = 0;
+ for (const Record *RuntimeLibcallDef : AllRuntimeLibcalls) {
+ RuntimeLibcallDefList.emplace_back(RuntimeLibcallDef, CallTypeEnumVal++);
+ Def2RuntimeLibcall[RuntimeLibcallDef] = &RuntimeLibcallDefList.back();
+ }
+
+ for (RuntimeLibcall &LibCall : RuntimeLibcallDefList)
+ Def2RuntimeLibcall[LibCall.getDef()] = &LibCall;
+
+ ArrayRef<const Record *> AllRuntimeLibcallImplsRaw =
+ Records.getAllDerivedDefinitions("RuntimeLibcallImpl");
+
+ SmallVector<const Record *, 1024> AllRuntimeLibcallImpls(
+ AllRuntimeLibcallImplsRaw);
+
+ // Sort by libcall impl name and secondarily by the enum name.
+ sort(AllRuntimeLibcallImpls, [](const Record *A, const Record *B) {
+ return std::pair(A->getValueAsString("LibCallFuncName"), A->getName()) <
+ std::pair(B->getValueAsString("LibCallFuncName"), B->getName());
+ });
+
+ RuntimeLibcallImplDefList.reserve(AllRuntimeLibcallImpls.size());
+
+ size_t LibCallImplEnumVal = 1;
+ for (const Record *LibCallImplDef : AllRuntimeLibcallImpls) {
+ RuntimeLibcallImplDefList.emplace_back(LibCallImplDef, Def2RuntimeLibcall,
+ LibCallImplEnumVal++);
+
+ const RuntimeLibcallImpl &LibCallImpl = RuntimeLibcallImplDefList.back();
+ Def2RuntimeLibcallImpl[LibCallImplDef] = &LibCallImpl;
+
+ if (LibCallImpl.isDefault()) {
+ const RuntimeLibcall *Provides = LibCallImpl.getProvides();
+ if (!Provides)
+ PrintFatalError(LibCallImplDef->getLoc(),
+ "default implementations must provide a libcall");
+ LibCallToDefaultImpl[Provides] = &LibCallImpl;
+ }
+ }
+}
+
+void LibcallPredicateExpander::expand(SetTheory &ST, const Record *Def,
+ SetTheory::RecSet &Elts) {
+ assert(Def->isSubClassOf("LibcallImpls"));
+
+ SetTheory::RecSet TmpElts;
+
+ ST.evaluate(Def->getValueInit("MemberList"), TmpElts, Def->getLoc());
+
+ Elts.insert(TmpElts.begin(), TmpElts.end());
+
+ AvailabilityPredicate AP(Def->getValueAsDef("AvailabilityPredicate"));
+ const Record *CCClass = Def->getValueAsOptionalDef("CallingConv");
+
+ // This is assuming we aren't conditionally applying a calling convention to
+ // some subsets, and not another, but this doesn't appear to be used.
+
+ for (const Record *LibcallImplDef : TmpElts) {
+ const RuntimeLibcallImpl *LibcallImpl =
+ Libcalls.getRuntimeLibcallImpl(LibcallImplDef);
+ if (!AP.isAlwaysAvailable() || CCClass) {
+ auto [It, Inserted] = Func2Preds.insert({LibcallImpl, {{}, CCClass}});
+ if (!Inserted) {
+ PrintError(
+ Def,
+ "combining nested libcall set predicates currently unhandled: '" +
+ LibcallImpl->getLibcallFuncName() + "'");
+ }
+
+ It->second.first.push_back(AP.getDef());
+ It->second.second = CCClass;
+ }
+ }
+}
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcalls.h b/llvm/utils/TableGen/Basic/RuntimeLibcalls.h
new file mode 100644
index 0000000..6c98976
--- /dev/null
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcalls.h
@@ -0,0 +1,189 @@
+//===------------------------------------------------------------*- 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;
+ StringRef PredicateString;
+
+public:
+ AvailabilityPredicate(const Record *Def) : TheDef(Def) {
+ if (TheDef)
+ PredicateString = TheDef->getValueAsString("Cond");
+ }
+
+ 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();
+ }
+};
+
+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() << '\"';
+ }
+
+ bool isDefault() const { return TheDef->getValueAsBit("IsDefault"); }
+
+ 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;
+
+ DenseMap<const RuntimeLibcall *, const RuntimeLibcallImpl *>
+ LibCallToDefaultImpl;
+
+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
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index 6a36f47..7aca87a6 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -8,6 +8,8 @@
#define DEBUG_TYPE "runtime-libcall-emitter"
+#include "RuntimeLibcalls.h"
+
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h"
@@ -65,160 +67,12 @@ template <> struct DenseMapInfo<PredicateWithCC, void> {
return LHS == RHS;
}
};
-} // namespace llvm
-
-namespace {
-
-class AvailabilityPredicate {
- const Record *TheDef;
- StringRef PredicateString;
-
-public:
- AvailabilityPredicate(const Record *Def) : TheDef(Def) {
- if (TheDef)
- PredicateString = TheDef->getValueAsString("Cond");
- }
-
- 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();
- }
-};
-
-class RuntimeLibcallEmitter;
-class RuntimeLibcallImpl;
-
-/// Used to apply predicates to nested sets of libcalls.
-struct LibcallPredicateExpander : SetTheory::Expander {
- const RuntimeLibcallEmitter &LibcallEmitter;
- DenseMap<const RuntimeLibcallImpl *,
- std::pair<std::vector<const Record *>, const Record *>> &Func2Preds;
-
- LibcallPredicateExpander(
- const RuntimeLibcallEmitter &LibcallEmitter,
- DenseMap<const RuntimeLibcallImpl *,
- std::pair<std::vector<const Record *>, const Record *>>
- &Func2Preds)
- : LibcallEmitter(LibcallEmitter), 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() << '\"';
- }
-
- bool isDefault() const { return TheDef->getValueAsBit("IsDefault"); }
-
- 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 RuntimeLibcallEmitter {
private:
const RecordKeeper &Records;
- DenseMap<const Record *, const RuntimeLibcall *> Def2RuntimeLibcall;
- DenseMap<const Record *, const RuntimeLibcallImpl *> Def2RuntimeLibcallImpl;
+ RuntimeLibcalls Libcalls;
- std::vector<RuntimeLibcall> RuntimeLibcallDefList;
- std::vector<RuntimeLibcallImpl> RuntimeLibcallImplDefList;
-
- DenseMap<const RuntimeLibcall *, const RuntimeLibcallImpl *>
- LibCallToDefaultImpl;
-
-private:
void emitGetRuntimeLibcallEnum(raw_ostream &OS) const;
void emitNameMatchHashTable(raw_ostream &OS,
@@ -229,61 +83,7 @@ private:
void emitSystemRuntimeLibrarySetCalls(raw_ostream &OS) const;
public:
- RuntimeLibcallEmitter(const RecordKeeper &R) : Records(R) {
-
- ArrayRef<const Record *> AllRuntimeLibcalls =
- Records.getAllDerivedDefinitions("RuntimeLibcall");
-
- RuntimeLibcallDefList.reserve(AllRuntimeLibcalls.size());
-
- size_t CallTypeEnumVal = 0;
- for (const Record *RuntimeLibcallDef : AllRuntimeLibcalls) {
- RuntimeLibcallDefList.emplace_back(RuntimeLibcallDef, CallTypeEnumVal++);
- Def2RuntimeLibcall[RuntimeLibcallDef] = &RuntimeLibcallDefList.back();
- }
-
- for (RuntimeLibcall &LibCall : RuntimeLibcallDefList)
- Def2RuntimeLibcall[LibCall.getDef()] = &LibCall;
-
- ArrayRef<const Record *> AllRuntimeLibcallImplsRaw =
- Records.getAllDerivedDefinitions("RuntimeLibcallImpl");
-
- SmallVector<const Record *, 1024> AllRuntimeLibcallImpls(
- AllRuntimeLibcallImplsRaw);
-
- // Sort by libcall impl name and secondarily by the enum name.
- sort(AllRuntimeLibcallImpls, [](const Record *A, const Record *B) {
- return std::pair(A->getValueAsString("LibCallFuncName"), A->getName()) <
- std::pair(B->getValueAsString("LibCallFuncName"), B->getName());
- });
-
- RuntimeLibcallImplDefList.reserve(AllRuntimeLibcallImpls.size());
-
- size_t LibCallImplEnumVal = 1;
- for (const Record *LibCallImplDef : AllRuntimeLibcallImpls) {
- RuntimeLibcallImplDefList.emplace_back(LibCallImplDef, Def2RuntimeLibcall,
- LibCallImplEnumVal++);
-
- const RuntimeLibcallImpl &LibCallImpl = RuntimeLibcallImplDefList.back();
- Def2RuntimeLibcallImpl[LibCallImplDef] = &LibCallImpl;
-
- if (LibCallImpl.isDefault()) {
- const RuntimeLibcall *Provides = LibCallImpl.getProvides();
- if (!Provides)
- PrintFatalError(LibCallImplDef->getLoc(),
- "default implementations must provide a libcall");
- LibCallToDefaultImpl[Provides] = &LibCallImpl;
- }
- }
- }
-
- const RuntimeLibcall *getRuntimeLibcall(const Record *Def) const {
- return Def2RuntimeLibcall.lookup(Def);
- }
-
- const RuntimeLibcallImpl *getRuntimeLibcallImpl(const Record *Def) const {
- return Def2RuntimeLibcallImpl.lookup(Def);
- }
+ RuntimeLibcallEmitter(const RecordKeeper &R) : Records(R), Libcalls(R) {}
void run(raw_ostream &OS);
};
@@ -297,24 +97,25 @@ void RuntimeLibcallEmitter::emitGetRuntimeLibcallEnum(raw_ostream &OS) const {
"namespace RTLIB {\n"
"enum Libcall : unsigned short {\n";
- for (const RuntimeLibcall &LibCall : RuntimeLibcallDefList) {
+ for (const RuntimeLibcall &LibCall : Libcalls.getRuntimeLibcallDefList()) {
StringRef Name = LibCall.getName();
OS << " " << Name << " = " << LibCall.getEnumVal() << ",\n";
}
- OS << " UNKNOWN_LIBCALL = " << RuntimeLibcallDefList.size()
+ OS << " UNKNOWN_LIBCALL = " << Libcalls.getRuntimeLibcallDefList().size()
<< "\n};\n\n"
"enum LibcallImpl : unsigned short {\n"
" Unsupported = 0,\n";
- for (const RuntimeLibcallImpl &LibCall : RuntimeLibcallImplDefList) {
+ for (const RuntimeLibcallImpl &LibCall :
+ Libcalls.getRuntimeLibcallImplDefList()) {
OS << " impl_" << LibCall.getName() << " = " << LibCall.getEnumVal()
<< ", // " << LibCall.getLibcallFuncName() << '\n';
}
OS << "};\n"
<< "constexpr size_t NumLibcallImpls = "
- << RuntimeLibcallImplDefList.size() + 1
+ << Libcalls.getRuntimeLibcallImplDefList().size() + 1
<< ";\n"
"} // End namespace RTLIB\n"
"} // End namespace llvm\n";
@@ -394,6 +195,8 @@ constructPerfectHashTable(ArrayRef<RuntimeLibcallImpl> Keywords,
/// Generate hash table based lookup by name.
void RuntimeLibcallEmitter::emitNameMatchHashTable(
raw_ostream &OS, StringToOffsetTable &OffsetTable) const {
+ ArrayRef<RuntimeLibcallImpl> RuntimeLibcallImplDefList =
+ Libcalls.getRuntimeLibcallImplDefList();
std::vector<uint64_t> Hashes(RuntimeLibcallImplDefList.size());
std::vector<unsigned> TableValues(RuntimeLibcallImplDefList.size());
DenseSet<StringRef> SeenFuncNames;
@@ -495,7 +298,8 @@ void RuntimeLibcallEmitter::emitGetInitRuntimeLibcallNames(
{
IfDefEmitter IfDef(OS, "GET_INIT_RUNTIME_LIBCALL_NAMES");
- for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList)
+ for (const RuntimeLibcallImpl &LibCallImpl :
+ Libcalls.getRuntimeLibcallImplDefList())
Table.GetOrAddStringOffset(LibCallImpl.getLibcallFuncName());
Table.EmitStringTableDef(OS, "RuntimeLibcallImplNameTable");
@@ -505,7 +309,8 @@ const uint16_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameOffsetTable[] = {
OS << formatv(" {}, // {}\n", Table.GetStringOffset(""),
""); // Unsupported entry
- for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList) {
+ for (const RuntimeLibcallImpl &LibCallImpl :
+ Libcalls.getRuntimeLibcallImplDefList()) {
StringRef ImplName = LibCallImpl.getLibcallFuncName();
OS << formatv(" {}, // {}\n", Table.GetStringOffset(ImplName), ImplName);
}
@@ -516,7 +321,8 @@ const uint8_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameSizeTable[] = {
)";
OS << " 0,\n";
- for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList)
+ for (const RuntimeLibcallImpl &LibCallImpl :
+ Libcalls.getRuntimeLibcallImplDefList())
OS << " " << LibCallImpl.getLibcallFuncName().size() << ",\n";
OS << "};\n\n";
@@ -525,7 +331,8 @@ const uint8_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameSizeTable[] = {
"ImplToLibcall[RTLIB::NumLibcallImpls] = {\n"
" RTLIB::UNKNOWN_LIBCALL, // RTLIB::Unsupported\n";
- for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList) {
+ for (const RuntimeLibcallImpl &LibCallImpl :
+ Libcalls.getRuntimeLibcallImplDefList()) {
const RuntimeLibcall *Provides = LibCallImpl.getProvides();
OS << " ";
Provides->emitEnumEntry(OS);
@@ -533,6 +340,7 @@ const uint8_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameSizeTable[] = {
LibCallImpl.emitEnumEntry(OS);
OS << '\n';
}
+
OS << "};\n\n";
}
@@ -544,11 +352,8 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
OS << "void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets("
"const llvm::Triple &TT, ExceptionHandling ExceptionModel, "
"FloatABI::ABIType FloatABI, EABI EABIVersion, "
- "StringRef ABIName) {\n"
- " struct LibcallImplPair {\n"
- " RTLIB::Libcall Func;\n"
- " RTLIB::LibcallImpl Impl;\n"
- " };\n";
+ "StringRef ABIName) {\n";
+
ArrayRef<const Record *> AllLibs =
Records.getAllDerivedDefinitions("SystemRuntimeLibrary");
@@ -579,7 +384,7 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
std::pair<std::vector<const Record *>, const Record *>>
Func2Preds;
Sets.addExpander("LibcallImpls", std::make_unique<LibcallPredicateExpander>(
- *this, Func2Preds));
+ Libcalls, Func2Preds));
const SetTheory::RecVec *Elements =
Sets.expand(R->getValueAsDef("MemberList"));
@@ -592,11 +397,12 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
constexpr unsigned BitsPerStorageElt = 64;
DenseMap<PredicateWithCC, LibcallsWithCC> Pred2Funcs;
- SmallVector<uint64_t, 32> BitsetValues(
- divideCeil(RuntimeLibcallImplDefList.size() + 1, BitsPerStorageElt));
+ SmallVector<uint64_t, 32> BitsetValues(divideCeil(
+ Libcalls.getRuntimeLibcallImplDefList().size() + 1, BitsPerStorageElt));
for (const Record *Elt : *Elements) {
- const RuntimeLibcallImpl *LibCallImpl = getRuntimeLibcallImpl(Elt);
+ const RuntimeLibcallImpl *LibCallImpl =
+ Libcalls.getRuntimeLibcallImpl(Elt);
if (!LibCallImpl) {
PrintError(R, "entry for SystemLibrary is not a RuntimeLibcallImpl");
PrintNote(Elt->getLoc(), "invalid entry `" + Elt->getName() + "`");
@@ -703,7 +509,7 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
Funcs.erase(UniqueI, Funcs.end());
OS << indent(IndentDepth + 2)
- << "static const LibcallImplPair LibraryCalls";
+ << "static const RTLIB::LibcallImpl LibraryCalls";
SubsetPredicate.emitTableVariableNameSuffix(OS);
if (FuncsWithCC.CallingConv)
OS << '_' << FuncsWithCC.CallingConv->getName();
@@ -711,18 +517,18 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
OS << "[] = {\n";
for (const RuntimeLibcallImpl *LibCallImpl : Funcs) {
OS << indent(IndentDepth + 6);
- LibCallImpl->emitTableEntry(OS);
+ LibCallImpl->emitEnumEntry(OS);
+ OS << ", // " << LibCallImpl->getLibcallFuncName() << '\n';
}
OS << indent(IndentDepth + 2) << "};\n\n"
<< indent(IndentDepth + 2)
- << "for (const auto [Func, Impl] : LibraryCalls";
+ << "for (const RTLIB::LibcallImpl Impl : LibraryCalls";
SubsetPredicate.emitTableVariableNameSuffix(OS);
if (FuncsWithCC.CallingConv)
OS << '_' << FuncsWithCC.CallingConv->getName();
- OS << ") {\n"
- << indent(IndentDepth + 4) << "setLibcallImpl(Func, Impl);\n";
+ OS << ") {\n" << indent(IndentDepth + 4) << "setAvailable(Impl);\n";
if (FuncsWithCC.CallingConv) {
StringRef CCEnum =
@@ -759,44 +565,10 @@ void RuntimeLibcallEmitter::run(raw_ostream &OS) {
emitGetInitRuntimeLibcallNames(OS);
{
- IfDefEmitter IfDef(OS, "GET_SET_TARGET_RUNTIME_LIBCALL_SETS");
+ IfDefEmitter IfDef(OS, "GET_RUNTIME_LIBCALLS_INFO");
emitSystemRuntimeLibrarySetCalls(OS);
}
}
-void LibcallPredicateExpander::expand(SetTheory &ST, const Record *Def,
- SetTheory::RecSet &Elts) {
- assert(Def->isSubClassOf("LibcallImpls"));
-
- SetTheory::RecSet TmpElts;
-
- ST.evaluate(Def->getValueInit("MemberList"), TmpElts, Def->getLoc());
-
- Elts.insert(TmpElts.begin(), TmpElts.end());
-
- AvailabilityPredicate AP(Def->getValueAsDef("AvailabilityPredicate"));
- const Record *CCClass = Def->getValueAsOptionalDef("CallingConv");
-
- // This is assuming we aren't conditionally applying a calling convention to
- // some subsets, and not another, but this doesn't appear to be used.
-
- for (const Record *LibcallImplDef : TmpElts) {
- const RuntimeLibcallImpl *LibcallImpl =
- LibcallEmitter.getRuntimeLibcallImpl(LibcallImplDef);
- if (!AP.isAlwaysAvailable() || CCClass) {
- auto [It, Inserted] = Func2Preds.insert({LibcallImpl, {{}, CCClass}});
- if (!Inserted) {
- PrintError(
- Def,
- "combining nested libcall set predicates currently unhandled: '" +
- LibcallImpl->getLibcallFuncName() + "'");
- }
-
- It->second.first.push_back(AP.getDef());
- It->second.second = CCClass;
- }
- }
-}
-
static TableGen::Emitter::OptClass<RuntimeLibcallEmitter>
X("gen-runtime-libcalls", "Generate RuntimeLibcalls");
diff --git a/llvm/utils/TableGen/Basic/SequenceToOffsetTable.h b/llvm/utils/TableGen/Basic/SequenceToOffsetTable.h
index 8da6fbe..1cd18b7 100644
--- a/llvm/utils/TableGen/Basic/SequenceToOffsetTable.h
+++ b/llvm/utils/TableGen/Basic/SequenceToOffsetTable.h
@@ -44,7 +44,7 @@ inline void printChar(raw_ostream &OS, char C) {
/// @tparam Less A stable comparator for SeqT elements.
template <typename SeqT, typename Less = std::less<typename SeqT::value_type>>
class SequenceToOffsetTable {
- typedef typename SeqT::value_type ElemT;
+ using ElemT = typename SeqT::value_type;
// Define a comparator for SeqT that sorts a suffix immediately before a
// sequence with that suffix.
@@ -58,7 +58,7 @@ class SequenceToOffsetTable {
// Keep sequences ordered according to SeqLess so suffixes are easy to find.
// Map each sequence to its offset in the table.
- typedef std::map<SeqT, unsigned, SeqLess> SeqMap;
+ using SeqMap = std::map<SeqT, unsigned, SeqLess>;
// Sequences added so far, with suffixes removed.
SeqMap Seqs;
@@ -162,7 +162,8 @@ public:
/// emit - Print out the table as the body of an array initializer.
/// Use the Print function to print elements.
- void emit(raw_ostream &OS, void (*Print)(raw_ostream &, ElemT)) const {
+ void emit(raw_ostream &OS,
+ function_ref<void(raw_ostream &, ElemT)> Print) const {
assert(IsLaidOut && "Call layout() before emit()");
for (const auto &[Seq, Offset] : Seqs) {
OS << " /* " << Offset << " */ ";
diff --git a/llvm/utils/TableGen/Basic/TableGen.cpp b/llvm/utils/TableGen/Basic/TableGen.cpp
index edb7791..a655cbb 100644
--- a/llvm/utils/TableGen/Basic/TableGen.cpp
+++ b/llvm/utils/TableGen/Basic/TableGen.cpp
@@ -60,7 +60,9 @@ static TableGen::Emitter::Opt X[] = {
true},
{"print-detailed-records", EmitDetailedRecords,
"Print full details of all records to stdout"},
- {"null-backend", [](const RecordKeeper &Records, raw_ostream &OS) {},
+ {"null-backend",
+ TableGen::Emitter::FnT(
+ [](const RecordKeeper &Records, raw_ostream &OS) {}),
"Do nothing after parsing (useful for timing)"},
{"dump-json", EmitJSON, "Dump all records as machine-readable JSON"},
{"print-enums", printEnums, "Print enum values for a class"},
@@ -71,7 +73,8 @@ int tblgen_main(int argc, char **argv) {
InitLLVM X(argc, argv);
cl::ParseCommandLineOptions(argc, argv);
- return TableGenMain(argv[0]);
+ MultiFileTableGenMainFn MainFn = nullptr;
+ return TableGenMain(argv[0], MainFn);
}
#ifndef __has_feature
diff --git a/llvm/utils/TableGen/Basic/TargetLibraryInfoEmitter.cpp b/llvm/utils/TableGen/Basic/TargetLibraryInfoEmitter.cpp
new file mode 100644
index 0000000..253d9df
--- /dev/null
+++ b/llvm/utils/TableGen/Basic/TargetLibraryInfoEmitter.cpp
@@ -0,0 +1,185 @@
+//===- 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");
diff --git a/llvm/utils/TableGen/Basic/VTEmitter.cpp b/llvm/utils/TableGen/Basic/VTEmitter.cpp
index 301b27d..87f5f4b 100644
--- a/llvm/utils/TableGen/Basic/VTEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/VTEmitter.cpp
@@ -91,11 +91,14 @@ void VTEmitter::run(raw_ostream &OS) {
emitSourceFileHeader("ValueTypes Source Fragment", OS, Records);
std::vector<const Record *> VTsByNumber{512};
- for (auto *VT : Records.getAllDerivedDefinitions("ValueType")) {
- auto Number = VT->getValueAsInt("Value");
- assert(0 <= Number && Number < (int)VTsByNumber.size() &&
- "ValueType should be uint16_t");
- assert(!VTsByNumber[Number] && "Duplicate ValueType");
+ unsigned Number = 0;
+ std::vector<const Record *> Defs(
+ Records.getAllDerivedDefinitions("ValueType"));
+ // Emit VTs in the order they were declared so that VTRanges stay contiguous.
+ llvm::sort(Defs, LessRecordByID());
+ for (auto *VT : Defs) {
+ ++Number;
+ assert(Number < VTsByNumber.size() && "ValueType should be uint16_t");
VTsByNumber[Number] = VT;
}
@@ -120,13 +123,12 @@ void VTEmitter::run(raw_ostream &OS) {
}
};
- OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc, Tup, NF, "
+ OS << "#ifdef GET_VT_ATTR // (Ty, sz, Any, Int, FP, Vec, Sc, Tup, NF, "
"NElem, EltTy)\n";
for (const auto *VT : VTsByNumber) {
if (!VT)
continue;
auto Name = VT->getValueAsString("LLVMName");
- auto Value = VT->getValueAsInt("Value");
bool IsInteger = VT->getValueAsBit("isInteger");
bool IsFP = VT->getValueAsBit("isFP");
bool IsVector = VT->getValueAsBit("isVector");
@@ -158,7 +160,6 @@ void VTEmitter::run(raw_ostream &OS) {
// clang-format off
OS << " GET_VT_ATTR("
<< Name << ", "
- << Value << ", "
<< VT->getValueAsInt("Size") << ", "
<< VT->getValueAsBit("isOverloaded") << ", "
<< (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", "