aboutsummaryrefslogtreecommitdiff
path: root/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
commit2298981669bf3bd63335a4be179bc0f96823a8f4 (patch)
tree1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
parent9a83721404652cea39e9f02ae3e3b5c964602a5c (diff)
downloadsrc-2298981669bf3bd63335a4be179bc0f96823a8f4.tar.gz
src-2298981669bf3bd63335a4be179bc0f96823a8f4.zip
Vendor import of stripped clang trunk r366426 (just before thevendor/clang/clang-trunk-r366426
Notes
Notes: svn path=/vendor/clang/dist/; revision=351280 svn path=/vendor/clang/clang-trunk-r366426/; revision=351281; tag=vendor/clang/clang-trunk-r366426
Diffstat (limited to 'utils/TableGen/ClangOpenCLBuiltinEmitter.cpp')
-rw-r--r--utils/TableGen/ClangOpenCLBuiltinEmitter.cpp318
1 files changed, 318 insertions, 0 deletions
diff --git a/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp b/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
new file mode 100644
index 000000000000..8d83b1c7fa6b
--- /dev/null
+++ b/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
@@ -0,0 +1,318 @@
+//===- ClangOpenCLBuiltinEmitter.cpp - Generate Clang OpenCL Builtin handling
+//
+// The LLVM Compiler Infrastructure
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits code for checking whether a function is an
+// OpenCL builtin function. If so, all overloads of this function are
+// added to the LookupResult. The generated include file is used by
+// SemaLookup.cpp
+//
+// For a successful lookup of e.g. the "cos" builtin, isOpenCLBuiltin("cos")
+// returns a pair <Index, Len>.
+// OpenCLBuiltins[Index] to OpenCLBuiltins[Index + Len] contains the pairs
+// <SigIndex, SigLen> of the overloads of "cos".
+// OpenCLSignature[SigIndex] to OpenCLSignature[SigIndex + SigLen] contains
+// one of the signatures of "cos". The OpenCLSignature entry can be
+// referenced by other functions, i.e. "sin", since multiple OpenCL builtins
+// share the same signature.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringMatcher.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <set>
+
+using namespace llvm;
+
+namespace {
+class BuiltinNameEmitter {
+public:
+ BuiltinNameEmitter(RecordKeeper &Records, raw_ostream &OS)
+ : Records(Records), OS(OS) {}
+
+ // Entrypoint to generate the functions and structures for checking
+ // whether a function is an OpenCL builtin function.
+ void Emit();
+
+private:
+ // Contains OpenCL builtin functions and related information, stored as
+ // Record instances. They are coming from the associated TableGen file.
+ RecordKeeper &Records;
+
+ // The output file.
+ raw_ostream &OS;
+
+ // Emit the enums and structs.
+ void EmitDeclarations();
+
+ // Parse the Records generated by TableGen and populate OverloadInfo and
+ // SignatureSet.
+ void GetOverloads();
+
+ // Emit the OpenCLSignature table. This table contains all possible
+ // signatures, and is a struct OpenCLType. A signature is composed of a
+ // return type (mandatory), followed by zero or more argument types.
+ // E.g.:
+ // // 12
+ // { OCLT_uchar, 4, clang::LangAS::Default, false },
+ // { OCLT_float, 4, clang::LangAS::Default, false },
+ // This means that index 12 represents a signature
+ // - returning a uchar vector of 4 elements, and
+ // - taking as first argument a float vector of 4 elements.
+ void EmitSignatureTable();
+
+ // Emit the OpenCLBuiltins table. This table contains all overloads of
+ // each function, and is a struct OpenCLBuiltinDecl.
+ // E.g.:
+ // // acos
+ // { 2, 0, "", 100 },
+ // This means that the signature of this acos overload is defined in OpenCL
+ // version 1.0 (100) and does not belong to any extension (""). It has a
+ // 1 argument (+1 for the return type), stored at index 0 in the
+ // OpenCLSignature table.
+ void EmitBuiltinTable();
+
+ // Emit a StringMatcher function to check whether a function name is an
+ // OpenCL builtin function name.
+ void EmitStringMatcher();
+
+ // Emit a function returning the clang QualType instance associated with
+ // the TableGen Record Type.
+ void EmitQualTypeFinder();
+
+ // Contains a list of the available signatures, without the name of the
+ // function. Each pair consists of a signature and a cumulative index.
+ // E.g.: <<float, float>, 0>,
+ // <<float, int, int, 2>>,
+ // <<float>, 5>,
+ // ...
+ // <<double, double>, 35>.
+ std::vector<std::pair<std::vector<Record *>, unsigned>> SignatureSet;
+
+ // Map the name of a builtin function to its prototypes (instances of the
+ // TableGen "Builtin" class).
+ // Each prototype is registered as a pair of:
+ // <pointer to the "Builtin" instance,
+ // cumulative index of the associated signature in the SignatureSet>
+ // E.g.: The function cos: (float cos(float), double cos(double), ...)
+ // <"cos", <<ptrToPrototype0, 5>,
+ // <ptrToPrototype1, 35>>
+ // <ptrToPrototype2, 79>>
+ // ptrToPrototype1 has the following signature: <double, double>
+ MapVector<StringRef, std::vector<std::pair<const Record *, unsigned>>>
+ OverloadInfo;
+};
+} // namespace
+
+void BuiltinNameEmitter::Emit() {
+ emitSourceFileHeader("OpenCL Builtin handling", OS);
+
+ OS << "#include \"llvm/ADT/StringRef.h\"\n";
+ OS << "using namespace clang;\n\n";
+
+ EmitDeclarations();
+
+ GetOverloads();
+
+ EmitSignatureTable();
+
+ EmitBuiltinTable();
+
+ EmitStringMatcher();
+
+ EmitQualTypeFinder();
+}
+
+void BuiltinNameEmitter::EmitDeclarations() {
+ OS << "enum OpenCLTypeID {\n";
+ std::vector<Record *> Types = Records.getAllDerivedDefinitions("Type");
+ StringMap<bool> TypesSeen;
+ for (const auto *T : Types) {
+ if (TypesSeen.find(T->getValueAsString("Name")) == TypesSeen.end())
+ OS << " OCLT_" + T->getValueAsString("Name") << ",\n";
+ TypesSeen.insert(std::make_pair(T->getValueAsString("Name"), true));
+ }
+ OS << "};\n";
+
+ OS << R"(
+
+// Type used in a prototype of an OpenCL builtin function.
+struct OpenCLType {
+ // A type (e.g.: float, int, ...)
+ OpenCLTypeID ID;
+ // Size of vector (if applicable)
+ unsigned VectorWidth;
+ // Address space of the pointer (if applicable)
+ LangAS AS;
+ // Whether the type is a pointer
+ bool isPointer;
+};
+
+// One overload of an OpenCL builtin function.
+struct OpenCLBuiltinDecl {
+ // Number of arguments for the signature
+ unsigned NumArgs;
+ // Index in the OpenCLSignature table to get the required types
+ unsigned ArgTableIndex;
+ // Extension to which it belongs (e.g. cl_khr_subgroups)
+ const char *Extension;
+ // Version in which it was introduced (e.g. CL20)
+ unsigned Version;
+};
+
+)";
+}
+
+void BuiltinNameEmitter::GetOverloads() {
+ unsigned CumulativeSignIndex = 0;
+ std::vector<Record *> Builtins = Records.getAllDerivedDefinitions("Builtin");
+ for (const auto *B : Builtins) {
+ StringRef BName = B->getValueAsString("Name");
+ if (OverloadInfo.find(BName) == OverloadInfo.end()) {
+ OverloadInfo.insert(std::make_pair(
+ BName, std::vector<std::pair<const Record *, unsigned>>{}));
+ }
+
+ auto Signature = B->getValueAsListOfDefs("Signature");
+ auto it =
+ std::find_if(SignatureSet.begin(), SignatureSet.end(),
+ [&](const std::pair<std::vector<Record *>, unsigned> &a) {
+ return a.first == Signature;
+ });
+ unsigned SignIndex;
+ if (it == SignatureSet.end()) {
+ SignatureSet.push_back(std::make_pair(Signature, CumulativeSignIndex));
+ SignIndex = CumulativeSignIndex;
+ CumulativeSignIndex += Signature.size();
+ } else {
+ SignIndex = it->second;
+ }
+ OverloadInfo[BName].push_back(std::make_pair(B, SignIndex));
+ }
+}
+
+void BuiltinNameEmitter::EmitSignatureTable() {
+ OS << "static const OpenCLType OpenCLSignature[] = {\n";
+ for (auto &P : SignatureSet) {
+ OS << "// " << P.second << "\n";
+ for (Record *R : P.first) {
+ OS << "{ OCLT_" << R->getValueAsString("Name") << ", "
+ << R->getValueAsInt("VecWidth") << ", "
+ << R->getValueAsString("AddrSpace") << ", "
+ << R->getValueAsBit("IsPointer") << "},";
+ OS << "\n";
+ }
+ }
+ OS << "};\n\n";
+}
+
+void BuiltinNameEmitter::EmitBuiltinTable() {
+ OS << "static const OpenCLBuiltinDecl OpenCLBuiltins[] = {\n";
+ for (auto &i : OverloadInfo) {
+ StringRef Name = i.first;
+ OS << "// " << Name << "\n";
+ for (auto &Overload : i.second) {
+ OS << " { " << Overload.first->getValueAsListOfDefs("Signature").size()
+ << ", " << Overload.second << ", " << '"'
+ << Overload.first->getValueAsString("Extension") << "\", "
+ << Overload.first->getValueAsDef("Version")->getValueAsInt("Version")
+ << " },\n";
+ }
+ }
+ OS << "};\n\n";
+}
+
+void BuiltinNameEmitter::EmitStringMatcher() {
+ std::vector<StringMatcher::StringPair> ValidBuiltins;
+ unsigned CumulativeIndex = 1;
+ for (auto &i : OverloadInfo) {
+ auto &Ov = i.second;
+ std::string RetStmt;
+ raw_string_ostream SS(RetStmt);
+ SS << "return std::make_pair(" << CumulativeIndex << ", " << Ov.size()
+ << ");";
+ SS.flush();
+ CumulativeIndex += Ov.size();
+
+ ValidBuiltins.push_back(StringMatcher::StringPair(i.first, RetStmt));
+ }
+
+ OS << R"(
+// Return 0 if name is not a recognized OpenCL builtin, or an index
+// into a table of declarations if it is an OpenCL builtin.
+static std::pair<unsigned, unsigned> isOpenCLBuiltin(llvm::StringRef name) {
+
+)";
+
+ StringMatcher("name", ValidBuiltins, OS).Emit(0, true);
+
+ OS << " return std::make_pair(0, 0);\n";
+ OS << "}\n";
+}
+
+void BuiltinNameEmitter::EmitQualTypeFinder() {
+ OS << R"(
+
+static QualType OCL2Qual(ASTContext &Context, OpenCLType Ty) {
+ QualType RT = Context.VoidTy;
+ switch (Ty.ID) {
+)";
+
+ std::vector<Record *> Types = Records.getAllDerivedDefinitions("Type");
+ StringMap<bool> TypesSeen;
+
+ for (const auto *T : Types) {
+ // Check we have not seen this Type
+ if (TypesSeen.find(T->getValueAsString("Name")) != TypesSeen.end())
+ continue;
+ TypesSeen.insert(std::make_pair(T->getValueAsString("Name"), true));
+
+ // Check the Type does not have an "abstract" QualType
+ auto QT = T->getValueAsDef("QTName");
+ if (QT->getValueAsString("Name") == "null")
+ continue;
+
+ OS << " case OCLT_" << T->getValueAsString("Name") << ":\n";
+ OS << " RT = Context." << QT->getValueAsString("Name") << ";\n";
+ OS << " break;\n";
+ }
+ OS << " }\n";
+
+ // Special cases
+ OS << R"(
+ if (Ty.VectorWidth > 0)
+ RT = Context.getExtVectorType(RT, Ty.VectorWidth);
+
+ if (Ty.isPointer) {
+ RT = Context.getAddrSpaceQualType(RT, Ty.AS);
+ RT = Context.getPointerType(RT);
+ }
+
+ return RT;
+}
+)";
+}
+
+namespace clang {
+
+void EmitClangOpenCLBuiltins(RecordKeeper &Records, raw_ostream &OS) {
+ BuiltinNameEmitter NameChecker(Records, OS);
+ NameChecker.Emit();
+}
+
+} // end namespace clang