Changeset View
Changeset View
Standalone View
Standalone View
utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
- This file was added.
//===- ClangOpenCLBuiltinEmitter.cpp - Generate Clang OpenCL Builtin handling | |||||
//=-*- C++ -*--=// | |||||
// | |||||
// The LLVM Compiler Infrastructure | |||||
// | |||||
// This file is distributed under the University of Illinois Open Source | |||||
// License. See LICENSE.TXT for details. | |||||
// | |||||
//===----------------------------------------------------------------------===// | |||||
// | |||||
// This tablegen backend emits Clang OpenCL Builtin checking code. | |||||
// | |||||
//===----------------------------------------------------------------------===// | |||||
#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) {} | |||||
void Emit(); | |||||
private: | |||||
RecordKeeper &Records; | |||||
raw_ostream &OS; | |||||
void EmitDeclarations(); | |||||
void EmitTable(); | |||||
void GetOverloads(); | |||||
MapVector<StringRef, std::vector<std::pair<const Record *, unsigned>>> | |||||
OverloadInfo; | |||||
std::vector<std::pair<std::vector<Record *>, unsigned>> ArgTypesSet; | |||||
}; | |||||
} // namespace | |||||
void BuiltinNameEmitter::GetOverloads() { | |||||
unsigned CumulativeArgIndex = 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 Args = B->getValueAsListOfDefs("args"); | |||||
auto it = | |||||
std::find_if(ArgTypesSet.begin(), ArgTypesSet.end(), | |||||
[&](const std::pair<std::vector<Record *>, unsigned> &a) { | |||||
return a.first == Args; | |||||
}); | |||||
unsigned ArgIndex; | |||||
if (it == ArgTypesSet.end()) { | |||||
ArgTypesSet.push_back(std::make_pair(Args, CumulativeArgIndex)); | |||||
ArgIndex = CumulativeArgIndex; | |||||
CumulativeArgIndex += Args.size(); | |||||
} else { | |||||
ArgIndex = it->second; | |||||
} | |||||
OverloadInfo[BName].push_back(std::make_pair(B, ArgIndex)); | |||||
} | |||||
} | |||||
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"( | |||||
struct OpenCLType { | |||||
OpenCLTypeID ID; | |||||
unsigned VectorWidth; | |||||
unsigned isPointer; | |||||
clang::LangAS AS; | |||||
}; | |||||
struct OpenCLBuiltinDecl { | |||||
unsigned NumArgs; | |||||
unsigned ArgTableIndex; | |||||
const char* Extension; | |||||
unsigned Version; | |||||
}; | |||||
)"; | |||||
} | |||||
void BuiltinNameEmitter::EmitTable() { | |||||
OS << "OpenCLBuiltinDecl OpenCLBuiltins[] = {\n"; | |||||
for (auto &i : OverloadInfo) { | |||||
StringRef Name = i.first; | |||||
OS << "// " << Name << "\n"; | |||||
for (auto &Overload : i.second) { | |||||
OS << " { " | |||||
<< Overload.first->getValueAsListOfDefs("args").size() << ", " | |||||
<< Overload.second << ", " << '"' | |||||
<< Overload.first->getValueAsString("extension") << "\", " | |||||
<< Overload.first->getValueAsDef("version")->getValueAsInt("version") | |||||
<< " },\n"; | |||||
} | |||||
} | |||||
OS << "};\n\n"; | |||||
} | |||||
void BuiltinNameEmitter::Emit() { | |||||
emitSourceFileHeader("OpenCL Builtin handling", OS); | |||||
OS << "#include \"llvm/ADT/StringRef.h\"\n\n"; | |||||
EmitDeclarations(); | |||||
GetOverloads(); | |||||
std::vector<std::vector<Record *>> ArgTypes; | |||||
OS << "OpenCLType OpenCLArgTypes[] = {\n"; | |||||
for (auto &P : ArgTypesSet) { | |||||
OS << "// " << P.second << "\n"; | |||||
for (Record *R : P.first) { | |||||
OS << "{ OCLT_" << R->getValueAsString("name") << ", " | |||||
<< R->getValueAsInt("vecWidth") << ", " | |||||
<< R->getValueAsInt("isPointer") << ", " << R->getValueAsString("as") | |||||
<< ", " | |||||
<< "}, "; | |||||
OS << "\n"; | |||||
} | |||||
} | |||||
OS << "};\n\n"; | |||||
EmitTable(); | |||||
// Construct a StringMatcher. | |||||
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 << "// Return 0 if name is not a recognized OpenCL builtin, or an index\n" | |||||
"// into a table of declarations if it is an OpenCL builtin.\n" | |||||
"std::pair<unsigned, unsigned> isOpenCLBuiltin(llvm::StringRef name) " | |||||
"{\n"; | |||||
StringMatcher("name", validBuiltins, OS).Emit(0, true); | |||||
OS << " return std::make_pair(0, 0);\n"; | |||||
OS << "}\n"; | |||||
} | |||||
namespace clang { | |||||
void EmitClangOpenCLBuiltins(RecordKeeper &Records, raw_ostream &OS) { | |||||
BuiltinNameEmitter NameChecker(Records, OS); | |||||
NameChecker.Emit(); | |||||
} | |||||
} // end namespace clang |