Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
clang/utils/TableGen/ClangProgModelBuiltinEmitter.cpp
- This file was moved from clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp.
//===- ClangOpenCLBuiltinEmitter.cpp - Generate Clang OpenCL Builtin handling | //===- ClangProgModelBuiltinEmitter.cpp - Generate Clang Builtin handling | ||||
// | // | ||||
// The LLVM Compiler Infrastructure | // The LLVM Compiler Infrastructure | ||||
// | // | ||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||
// See https://llvm.org/LICENSE.txt for license information. | // See https://llvm.org/LICENSE.txt for license information. | ||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||
// | // | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
// | // | ||||
// These backends consume the definitions of OpenCL builtin functions in | // These backends consume the definitions of builtin functions in | ||||
// clang/lib/Sema/OpenCLBuiltins.td and produce builtin handling code for | // clang/lib/Sema/*Builtins.td and produce builtin handling code for | ||||
// inclusion in SemaLookup.cpp, or a test file that calls all declared builtins. | // inclusion in SemaLookup.cpp, or a test file that calls all declared builtins. | ||||
// | // | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
#include "TableGenBackends.h" | #include "TableGenBackends.h" | ||||
#include "llvm/ADT/MapVector.h" | #include "llvm/ADT/MapVector.h" | ||||
#include "llvm/ADT/STLExtras.h" | #include "llvm/ADT/STLExtras.h" | ||||
#include "llvm/ADT/SmallString.h" | #include "llvm/ADT/SmallString.h" | ||||
Show All 13 Lines | |||||
namespace { | namespace { | ||||
// A list of signatures that are shared by one or more builtin functions. | // A list of signatures that are shared by one or more builtin functions. | ||||
struct BuiltinTableEntries { | struct BuiltinTableEntries { | ||||
SmallVector<StringRef, 4> Names; | SmallVector<StringRef, 4> Names; | ||||
std::vector<std::pair<const Record *, unsigned>> Signatures; | std::vector<std::pair<const Record *, unsigned>> Signatures; | ||||
}; | }; | ||||
// This tablegen backend emits code for checking whether a function is an | // This tablegen backend emits code for checking whether a function is a | ||||
// OpenCL builtin function. If so, all overloads of this function are | // builtin function of a programming model. If so, all overloads of this | ||||
// added to the LookupResult. The generated include file is used by | // function are added to the LookupResult. The generated include file is | ||||
// SemaLookup.cpp | // used by SemaLookup.cpp | ||||
// | // | ||||
// For a successful lookup of e.g. the "cos" builtin, isOpenCLBuiltin("cos") | // For a successful lookup of e.g. the "cos" builtin, isBuiltin("cos") | ||||
// returns a pair <Index, Len>. | // returns a pair <Index, Len>. | ||||
// BuiltinTable[Index] to BuiltinTable[Index + Len] contains the pairs | // BuiltinTable[Index] to BuiltinTable[Index + Len] contains the pairs | ||||
// <SigIndex, SigLen> of the overloads of "cos". | // <SigIndex, SigLen> of the overloads of "cos". | ||||
// SignatureTable[SigIndex] to SignatureTable[SigIndex + SigLen] contains | // SignatureTable[SigIndex] to SignatureTable[SigIndex + SigLen] contains | ||||
// one of the signatures of "cos". The SignatureTable entry can be | // one of the signatures of "cos". The SignatureTable entry can be | ||||
// referenced by other functions, e.g. "sin", to exploit the fact that | // referenced by other functions, e.g. "sin", to exploit the fact that | ||||
// many OpenCL builtins share the same signature. | // many builtins may share the same signature. | ||||
// | // | ||||
// The file generated by this TableGen emitter contains the following: | // The file generated by this TableGen emitter contains the following: | ||||
// | // | ||||
// * Structs and enums to represent types and function signatures. | // * Structs and enums to represent types and function signatures. | ||||
// | // | ||||
// * const char *FunctionExtensionTable[] | // * const char *FunctionExtensionTable[] | ||||
// List of space-separated OpenCL extensions. A builtin references an | // List of space-separated OpenCL extensions. A builtin references an | ||||
// entry in this table when the builtin requires a particular (set of) | // entry in this table when the builtin requires a particular (set of) | ||||
// extension(s) to be enabled. | // extension(s) to be enabled. | ||||
// | // | ||||
// * OpenCLTypeStruct TypeTable[] | // * ProgModelTypeStruct TypeTable[] | ||||
// Type information for return types and arguments. | // Type information for return types and arguments. | ||||
// | // | ||||
// * unsigned SignatureTable[] | // * unsigned SignatureTable[] | ||||
// A list of types representing function signatures. Each entry is an index | // A list of types representing function signatures. Each entry is an index | ||||
// into the above TypeTable. Multiple entries following each other form a | // into the above TypeTable. Multiple entries following each other form a | ||||
// signature, where the first entry is the return type and subsequent | // signature, where the first entry is the return type and subsequent | ||||
// entries are the argument types. | // entries are the argument types. | ||||
// | // | ||||
// * OpenCLBuiltinStruct BuiltinTable[] | // * BuiltinStruct BuiltinTable[] | ||||
// Each entry represents one overload of an OpenCL builtin function and | // Each entry represents one overload of a builtin function and | ||||
// consists of an index into the SignatureTable and the number of arguments. | // consists of an index into the SignatureTable and the number of arguments. | ||||
// | // | ||||
// * std::pair<unsigned, unsigned> isOpenCLBuiltin(llvm::StringRef Name) | // * std::pair<unsigned, unsigned> isBuiltin(llvm::StringRef Name) | ||||
// Find out whether a string matches an existing OpenCL builtin function | // Find out whether a string matches an existing builtin function | ||||
// name and return an index into BuiltinTable and the number of overloads. | // name and return an index into BuiltinTable and the number of overloads. | ||||
// | // | ||||
// * void OCL2Qual(Sema&, OpenCLTypeStruct, std::vector<QualType>&) | // * void Bultin2Qual(Sema&, ProgModelTypeStruct, std::vector<QualType>&) | ||||
// Convert an OpenCLTypeStruct type to a list of QualType instances. | // Convert an ProgModelTypeStruct type to a list of QualType instances. | ||||
// One OpenCLTypeStruct can represent multiple types, primarily when using | // One ProgModelTypeStruct can represent multiple types, primarily when using | ||||
// GenTypes. | // GenTypes. | ||||
// | // | ||||
class BuiltinNameEmitter { | class BuiltinNameEmitter { | ||||
public: | public: | ||||
BuiltinNameEmitter(RecordKeeper &Records, raw_ostream &OS) | BuiltinNameEmitter(RecordKeeper &Records, raw_ostream &OS, | ||||
: Records(Records), OS(OS) {} | llvm::StringRef Family) | ||||
: Records(Records), OS(OS), Family(Family), | |||||
ClassName((Family + "Builtin").str()) {} | |||||
// Entrypoint to generate the functions and structures for checking | // Entrypoint to generate the functions and structures for checking | ||||
// whether a function is an OpenCL builtin function. | // whether a function is a builtin function. | ||||
void Emit(); | void Emit(); | ||||
private: | private: | ||||
// A list of indices into the builtin function table. | // A list of indices into the builtin function table. | ||||
using BuiltinIndexListTy = SmallVector<unsigned, 11>; | using BuiltinIndexListTy = SmallVector<unsigned, 11>; | ||||
// Contains OpenCL builtin functions and related information, stored as | // Contains builtin functions and related information, stored as | ||||
// Record instances. They are coming from the associated TableGen file. | // Record instances. They are coming from the associated TableGen file. | ||||
RecordKeeper &Records; | RecordKeeper &Records; | ||||
// The output file. | // The output file. | ||||
raw_ostream &OS; | raw_ostream &OS; | ||||
// Family for which the builtin are for. | |||||
llvm::StringRef Family; | |||||
// Class for which the builtin are for. | |||||
std::string ClassName; | |||||
// Helper function for BuiltinNameEmitter::EmitDeclarations. Generate enum | // Helper function for BuiltinNameEmitter::EmitDeclarations. Generate enum | ||||
// definitions in the Output string parameter, and save their Record instances | // definitions in the Output string parameter, and save their Record instances | ||||
// in the List parameter. | // in the List parameter. | ||||
// \param Types (in) List containing the Types to extract. | // \param Types (in) List containing the Types to extract. | ||||
// \param TypesSeen (inout) List containing the Types already extracted. | // \param TypesSeen (inout) List containing the Types already extracted. | ||||
// \param Output (out) String containing the enums to emit in the output file. | // \param Output (out) String containing the enums to emit in the output file. | ||||
// \param List (out) List containing the extracted Types, except the Types in | // \param List (out) List containing the extracted Types, except the Types in | ||||
// TypesSeen. | // TypesSeen. | ||||
void ExtractEnumTypes(std::vector<Record *> &Types, | void ExtractEnumTypes(std::vector<Record *> &Types, | ||||
StringMap<bool> &TypesSeen, std::string &Output, | StringMap<bool> &TypesSeen, std::string &Output, | ||||
std::vector<const Record *> &List); | std::vector<const Record *> &List); | ||||
// Emit the enum or struct used in the generated file. | // Emit the enum or struct used in the generated file. | ||||
// Populate the TypeList at the same time. | // Populate the TypeList at the same time. | ||||
void EmitDeclarations(); | void EmitDeclarations(); | ||||
// Parse the Records generated by TableGen to populate the SignaturesList, | // Parse the Records generated by TableGen to populate the SignaturesList, | ||||
// FctOverloadMap and TypeMap. | // FctOverloadMap and TypeMap. | ||||
void GetOverloads(); | void GetOverloads(); | ||||
// Compare two lists of signatures and check that e.g. the OpenCL version, | // Compare two lists of signatures and check that e.g. the version, | ||||
// function attributes, and extension are equal for each signature. | // function attributes, and extension are equal for each signature. | ||||
// \param Candidate (in) Entry in the SignatureListMap to check. | // \param Candidate (in) Entry in the SignatureListMap to check. | ||||
// \param SignatureList (in) List of signatures of the considered function. | // \param SignatureList (in) List of signatures of the considered function. | ||||
// \returns true if the two lists of signatures are identical. | // \returns true if the two lists of signatures are identical. | ||||
bool CanReuseSignature( | bool CanReuseSignature( | ||||
BuiltinIndexListTy *Candidate, | BuiltinIndexListTy *Candidate, | ||||
std::vector<std::pair<const Record *, unsigned>> &SignatureList); | std::vector<std::pair<const Record *, unsigned>> &SignatureList); | ||||
// Group functions with the same list of signatures by populating the | // Group functions with the same list of signatures by populating the | ||||
// SignatureListMap. | // SignatureListMap. | ||||
// Some builtin functions have the same list of signatures, for example the | // Some builtin functions have the same list of signatures, for example the | ||||
// "sin" and "cos" functions. To save space in the BuiltinTable, the | // "sin" and "cos" functions. To save space in the BuiltinTable, the | ||||
// "isOpenCLBuiltin" function will have the same output for these two | // "isBuiltin" function will have the same output for these two | ||||
// function names. | // function names. | ||||
void GroupBySignature(); | void GroupBySignature(); | ||||
// Emit the FunctionExtensionTable that lists all function extensions. | // Emit the FunctionExtensionTable that lists all function extensions. | ||||
void EmitExtensionTable(); | void EmitExtensionTable(); | ||||
// Emit the TypeTable containing all types used by OpenCL builtins. | // Emit the TypeTable containing all types used by the builtins. | ||||
void EmitTypeTable(); | void EmitTypeTable(); | ||||
// Emit the SignatureTable. This table contains all the possible signatures. | // Emit the SignatureTable. This table contains all the possible signatures. | ||||
// A signature is stored as a list of indexes of the TypeTable. | // A signature is stored as a list of indexes of the TypeTable. | ||||
// The first index references the return type (mandatory), and the followings | // The first index references the return type (mandatory), and the followings | ||||
// reference its arguments. | // reference its arguments. | ||||
// E.g.: | // E.g.: | ||||
// 15, 2, 15 can represent a function with the signature: | // 15, 2, 15 can represent a function with the signature: | ||||
// int func(float, int) | // int func(float, int) | ||||
// The "int" type being at the index 15 in the TypeTable. | // The "int" type being at the index 15 in the TypeTable. | ||||
void EmitSignatureTable(); | void EmitSignatureTable(); | ||||
// Emit the BuiltinTable table. This table contains all the overloads of | // Emit the BuiltinTable table. This table contains all the overloads of | ||||
// each function, and is a struct OpenCLBuiltinDecl. | // each function, and is a struct BuiltinDecl. | ||||
// E.g.: | // E.g.: | ||||
// // 891 convert_float2_rtn | // // 891 convert_float2_rtn | ||||
// { 58, 2, 3, 100, 0 }, | // { 58, 2, 3, 100, 0 }, | ||||
// This means that the signature of this convert_float2_rtn overload has | // This means that the signature of this convert_float2_rtn overload has | ||||
// 1 argument (+1 for the return type), stored at index 58 in | // 1 argument (+1 for the return type), stored at index 58 in | ||||
// the SignatureTable. This prototype requires extension "3" in the | // the SignatureTable. This prototype requires extension "3" in the | ||||
// FunctionExtensionTable. The last two values represent the minimum (1.0) | // FunctionExtensionTable. The last two values represent the minimum (1.0) | ||||
// and maximum (0, meaning no max version) OpenCL version in which this | // and maximum (0, meaning no max version) version in which this | ||||
// overload is supported. | // overload is supported. | ||||
void EmitBuiltinTable(); | void EmitBuiltinTable(); | ||||
// Emit a StringMatcher function to check whether a function name is an | // Emit a StringMatcher function to check whether a function name is a | ||||
// OpenCL builtin function name. | // builtin function name. | ||||
void EmitStringMatcher(); | void EmitStringMatcher(); | ||||
// Emit a function returning the clang QualType instance associated with | // Emit a function returning the clang QualType instance associated with | ||||
// the TableGen Record Type. | // the TableGen Record Type. | ||||
void EmitQualTypeFinder(); | void EmitQualTypeFinder(); | ||||
// Contains a list of the available signatures, without the name of the | // Contains a list of the available signatures, without the name of the | ||||
// function. Each pair consists of a signature and a cumulative index. | // function. Each pair consists of a signature and a cumulative index. | ||||
Show All 12 Lines | private: | ||||
// E.g.: The function cos: (float cos(float), double cos(double), ...) | // E.g.: The function cos: (float cos(float), double cos(double), ...) | ||||
// <"cos", <<ptrToPrototype0, 5>, | // <"cos", <<ptrToPrototype0, 5>, | ||||
// <ptrToPrototype1, 35>, | // <ptrToPrototype1, 35>, | ||||
// <ptrToPrototype2, 79>> | // <ptrToPrototype2, 79>> | ||||
// ptrToPrototype1 has the following signature: <double, double> | // ptrToPrototype1 has the following signature: <double, double> | ||||
MapVector<StringRef, std::vector<std::pair<const Record *, unsigned>>> | MapVector<StringRef, std::vector<std::pair<const Record *, unsigned>>> | ||||
FctOverloadMap; | FctOverloadMap; | ||||
// Contains the map of OpenCL types to their index in the TypeTable. | // Contains the map of types to their index in the TypeTable. | ||||
MapVector<const Record *, unsigned> TypeMap; | MapVector<const Record *, unsigned> TypeMap; | ||||
// List of OpenCL function extensions mapping extension strings to | // List of function extensions mapping extension strings to | ||||
// an index into the FunctionExtensionTable. | // an index into the FunctionExtensionTable. | ||||
StringMap<unsigned> FunctionExtensionIndex; | StringMap<unsigned> FunctionExtensionIndex; | ||||
// List of OpenCL type names in the same order as in enum OpenCLTypeID. | // List of type names in the same order as in enum TypeID. | ||||
// This list does not contain generic types. | // This list does not contain generic types. | ||||
std::vector<const Record *> TypeList; | std::vector<const Record *> TypeList; | ||||
// Same as TypeList, but for generic types only. | // Same as TypeList, but for generic types only. | ||||
std::vector<const Record *> GenTypeList; | std::vector<const Record *> GenTypeList; | ||||
// Map an ordered vector of signatures to their original Record instances, | // Map an ordered vector of signatures to their original Record instances, | ||||
// and to a list of function names that share these signatures. | // and to a list of function names that share these signatures. | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | public: | ||||
// Entrypoint to generate the functions for testing all OpenCL builtin | // Entrypoint to generate the functions for testing all OpenCL builtin | ||||
// functions. | // functions. | ||||
void emit() override; | void emit() override; | ||||
}; | }; | ||||
} // namespace | } // namespace | ||||
void BuiltinNameEmitter::Emit() { | void BuiltinNameEmitter::Emit() { | ||||
emitSourceFileHeader("OpenCL Builtin handling", OS); | std::string Banner = (Family + " Builtin handling").str(); | ||||
emitSourceFileHeader(Banner, OS); | |||||
OS << "#include \"llvm/ADT/StringRef.h\"\n"; | OS << "#include \"llvm/ADT/StringRef.h\"\n"; | ||||
OS << "using namespace clang;\n\n"; | OS << "using namespace clang;\n\n"; | ||||
// Emit enums and structs. | // Emit enums and structs. | ||||
EmitDeclarations(); | EmitDeclarations(); | ||||
// Parse the Records to populate the internal lists. | // Parse the Records to populate the internal lists. | ||||
Show All 14 Lines | |||||
void BuiltinNameEmitter::ExtractEnumTypes(std::vector<Record *> &Types, | void BuiltinNameEmitter::ExtractEnumTypes(std::vector<Record *> &Types, | ||||
StringMap<bool> &TypesSeen, | StringMap<bool> &TypesSeen, | ||||
std::string &Output, | std::string &Output, | ||||
std::vector<const Record *> &List) { | std::vector<const Record *> &List) { | ||||
raw_string_ostream SS(Output); | raw_string_ostream SS(Output); | ||||
for (const auto *T : Types) { | for (const auto *T : Types) { | ||||
if (TypesSeen.find(T->getValueAsString("Name")) == TypesSeen.end()) { | if (TypesSeen.find(T->getValueAsString("Name")) == TypesSeen.end()) { | ||||
SS << " OCLT_" + T->getValueAsString("Name") << ",\n"; | SS << " TID_" + T->getValueAsString("Name") << ",\n"; | ||||
// Save the type names in the same order as their enum value. Note that | // Save the type names in the same order as their enum value. Note that | ||||
// the Record can be a VectorType or something else, only the name is | // the Record can be a VectorType or something else, only the name is | ||||
// important. | // important. | ||||
List.push_back(T); | List.push_back(T); | ||||
TypesSeen.insert(std::make_pair(T->getValueAsString("Name"), true)); | TypesSeen.insert(std::make_pair(T->getValueAsString("Name"), true)); | ||||
} | } | ||||
} | } | ||||
SS.flush(); | SS.flush(); | ||||
} | } | ||||
void BuiltinNameEmitter::EmitDeclarations() { | void BuiltinNameEmitter::EmitDeclarations() { | ||||
OS << "class " << ClassName << " {\n\n" | |||||
<< "public:\n\n"; | |||||
// Enum of scalar type names (float, int, ...) and generic type sets. | // Enum of scalar type names (float, int, ...) and generic type sets. | ||||
OS << "enum OpenCLTypeID {\n"; | OS << "enum TypeID {\n"; | ||||
StringMap<bool> TypesSeen; | StringMap<bool> TypesSeen; | ||||
std::string GenTypeEnums; | std::string GenTypeEnums; | ||||
std::string TypeEnums; | std::string TypeEnums; | ||||
// Extract generic types and non-generic types separately, to keep | // Extract generic types and non-generic types separately, to keep | ||||
// gentypes at the end of the enum which simplifies the special handling | // gentypes at the end of the enum which simplifies the special handling | ||||
// for gentypes in SemaLookup. | // for gentypes in SemaLookup. | ||||
std::vector<Record *> GenTypes = | std::vector<Record *> GenTypes = | ||||
Records.getAllDerivedDefinitions("GenericType"); | Records.getAllDerivedDefinitions("GenericType"); | ||||
ExtractEnumTypes(GenTypes, TypesSeen, GenTypeEnums, GenTypeList); | ExtractEnumTypes(GenTypes, TypesSeen, GenTypeEnums, GenTypeList); | ||||
std::vector<Record *> Types = Records.getAllDerivedDefinitions("Type"); | std::vector<Record *> Types = Records.getAllDerivedDefinitions("Type"); | ||||
ExtractEnumTypes(Types, TypesSeen, TypeEnums, TypeList); | ExtractEnumTypes(Types, TypesSeen, TypeEnums, TypeList); | ||||
OS << TypeEnums; | OS << TypeEnums; | ||||
OS << GenTypeEnums; | OS << GenTypeEnums; | ||||
OS << "};\n"; | OS << "};\n"; | ||||
// Structure definitions. | // Structure definitions. | ||||
OS << R"( | OS << R"( | ||||
// Image access qualifier. | // Image access qualifier. | ||||
enum OpenCLAccessQual : unsigned char { | enum AccessQual : unsigned char { | ||||
OCLAQ_None, | AQ_None, | ||||
OCLAQ_ReadOnly, | AQ_ReadOnly, | ||||
OCLAQ_WriteOnly, | AQ_WriteOnly, | ||||
OCLAQ_ReadWrite | AQ_ReadWrite | ||||
}; | }; | ||||
// Represents a return type or argument type. | // Represents a return type or argument type. | ||||
struct OpenCLTypeStruct { | struct ProgModelTypeStruct { | ||||
// A type (e.g. float, int, ...). | // A type (e.g. float, int, ...). | ||||
const OpenCLTypeID ID; | const TypeID ID; | ||||
// Vector size (if applicable; 0 for scalars and generic types). | // Vector size (if applicable; 0 for scalars and generic types). | ||||
const unsigned VectorWidth; | const unsigned VectorWidth; | ||||
// 0 if the type is not a pointer. | // 0 if the type is not a pointer. | ||||
const bool IsPointer : 1; | const bool IsPointer : 1; | ||||
// 0 if the type is not const. | // 0 if the type is not const. | ||||
const bool IsConst : 1; | const bool IsConst : 1; | ||||
// 0 if the type is not volatile. | // 0 if the type is not volatile. | ||||
const bool IsVolatile : 1; | const bool IsVolatile : 1; | ||||
// Access qualifier. | // Access qualifier. | ||||
const OpenCLAccessQual AccessQualifier; | const AccessQual AccessQualifier; | ||||
// Address space of the pointer (if applicable). | // Address space of the pointer (if applicable). | ||||
const LangAS AS; | const LangAS AS; | ||||
}; | }; | ||||
// One overload of an OpenCL builtin function. | // One overload of a builtin function. | ||||
struct OpenCLBuiltinStruct { | struct BuiltinStruct { | ||||
// Index of the signature in the OpenCLTypeStruct table. | // Index of the signature in the ProgModelTypeStruct table. | ||||
const unsigned SigTableIndex; | const unsigned SigTableIndex; | ||||
// Entries between index SigTableIndex and (SigTableIndex + NumTypes - 1) in | // Entries between index SigTableIndex and (SigTableIndex + NumTypes - 1) in | ||||
// the SignatureTable represent the complete signature. The first type at | // the SignatureTable represent the complete signature. The first type at | ||||
// index SigTableIndex is the return type. | // index SigTableIndex is the return type. | ||||
const unsigned NumTypes; | const unsigned NumTypes; | ||||
// Function attribute __attribute__((pure)) | // Function attribute __attribute__((pure)) | ||||
const bool IsPure : 1; | const bool IsPure : 1; | ||||
// Function attribute __attribute__((const)) | // Function attribute __attribute__((const)) | ||||
const bool IsConst : 1; | const bool IsConst : 1; | ||||
// Function attribute __attribute__((convergent)) | // Function attribute __attribute__((convergent)) | ||||
const bool IsConv : 1; | const bool IsConv : 1; | ||||
// 0 if the function is not variadic. | |||||
const bool IsVariadic : 1; | |||||
// OpenCL extension(s) required for this overload. | // OpenCL extension(s) required for this overload. | ||||
const unsigned short Extension; | const unsigned short Extension; | ||||
// OpenCL versions in which this overload is available. | // OpenCL versions in which this overload is available. | ||||
const unsigned short Versions; | const unsigned short Versions; | ||||
}; | }; | ||||
static const char *FunctionExtensionTable[]; | |||||
static const ProgModelTypeStruct TypeTable[]; | |||||
static const unsigned short SignatureTable[]; | |||||
static const BuiltinStruct BuiltinTable[]; | |||||
static std::pair<unsigned, unsigned> isBuiltin(llvm::StringRef Name); | |||||
static void Bultin2Qual(Sema &Sema, const ProgModelTypeStruct &Ty, | |||||
llvm::SmallVectorImpl<QualType> &QT); | |||||
)"; | )"; | ||||
OS << "}; // class " << ClassName << "\n"; | |||||
} | } | ||||
// Verify that the combination of GenTypes in a signature is supported. | // Verify that the combination of GenTypes in a signature is supported. | ||||
// To simplify the logic for creating overloads in SemaLookup, only allow | // To simplify the logic for creating overloads in SemaLookup, only allow | ||||
// a signature to contain different GenTypes if these GenTypes represent | // a signature to contain different GenTypes if these GenTypes represent | ||||
// the same number of actual scalar or vector types. | // the same number of actual scalar or vector types. | ||||
// | // | ||||
// Exit with a fatal error if an unsupported construct is encountered. | // Exit with a fatal error if an unsupported construct is encountered. | ||||
static void VerifySignature(const std::vector<Record *> &Signature, | static void VerifySignature(const std::vector<Record *> &Signature, | ||||
const Record *BuiltinRec) { | const Record *BuiltinRec) { | ||||
unsigned GenTypeVecSizes = 1; | unsigned GenTypeVecSizes = 1; | ||||
unsigned GenTypeTypes = 1; | unsigned GenTypeTypes = 1; | ||||
for (const auto *T : Signature) { | for (const auto *T : Signature) { | ||||
// Check all GenericType arguments in this signature. | // Check all GenericType arguments in this signature. | ||||
if (T->isSubClassOf("GenericType")) { | if (T->isSubClassOf("GenericType")) { | ||||
// Check number of vector sizes. | // Check number of vector sizes. | ||||
unsigned NVecSizes = | unsigned NVecSizes = | ||||
T->getValueAsDef("VectorList")->getValueAsListOfInts("List").size(); | T->getValueAsDef("VectorList")->getValueAsListOfInts("List").size(); | ||||
if (NVecSizes != GenTypeVecSizes && NVecSizes != 1) { | if (NVecSizes != GenTypeVecSizes && NVecSizes != 1) { | ||||
if (GenTypeVecSizes > 1) { | if (GenTypeVecSizes > 1) { | ||||
// We already saw a gentype with a different number of vector sizes. | // We already saw a gentype with a different number of vector sizes. | ||||
PrintFatalError(BuiltinRec->getLoc(), | PrintFatalError( | ||||
BuiltinRec->getLoc(), | |||||
"number of vector sizes should be equal or 1 for all gentypes " | "number of vector sizes should be equal or 1 for all gentypes " | ||||
"in a declaration"); | "in a declaration"); | ||||
} | } | ||||
GenTypeVecSizes = NVecSizes; | GenTypeVecSizes = NVecSizes; | ||||
} | } | ||||
// Check number of data types. | // Check number of data types. | ||||
unsigned NTypes = | unsigned NTypes = | ||||
T->getValueAsDef("TypeList")->getValueAsListOfDefs("List").size(); | T->getValueAsDef("TypeList")->getValueAsListOfDefs("List").size(); | ||||
if (NTypes != GenTypeTypes && NTypes != 1) { | if (NTypes != GenTypeTypes && NTypes != 1) { | ||||
if (GenTypeTypes > 1) { | if (GenTypeTypes > 1) { | ||||
// We already saw a gentype with a different number of types. | // We already saw a gentype with a different number of types. | ||||
PrintFatalError(BuiltinRec->getLoc(), | PrintFatalError( | ||||
BuiltinRec->getLoc(), | |||||
"number of types should be equal or 1 for all gentypes " | "number of types should be equal or 1 for all gentypes " | ||||
"in a declaration"); | "in a declaration"); | ||||
} | } | ||||
GenTypeTypes = NTypes; | GenTypeTypes = NTypes; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
Show All 32 Lines | for (const auto *B : Builtins) { | ||||
} else { | } else { | ||||
SignIndex = it->second; | SignIndex = it->second; | ||||
} | } | ||||
FctOverloadMap[BName].push_back(std::make_pair(B, SignIndex)); | FctOverloadMap[BName].push_back(std::make_pair(B, SignIndex)); | ||||
} | } | ||||
} | } | ||||
void BuiltinNameEmitter::EmitExtensionTable() { | void BuiltinNameEmitter::EmitExtensionTable() { | ||||
OS << "static const char *FunctionExtensionTable[] = {\n"; | OS << "const char * " << ClassName << "::FunctionExtensionTable[] = {\n"; | ||||
unsigned Index = 0; | unsigned Index = 0; | ||||
std::vector<Record *> FuncExtensions = | std::vector<Record *> FuncExtensions = | ||||
Records.getAllDerivedDefinitions("FunctionExtension"); | Records.getAllDerivedDefinitions("FunctionExtension"); | ||||
for (const auto &FE : FuncExtensions) { | for (const auto &FE : FuncExtensions) { | ||||
// Emit OpenCL extension table entry. | // Emit OpenCL extension table entry. | ||||
OS << " // " << Index << ": " << FE->getName() << "\n" | OS << " // " << Index << ": " << FE->getName() << "\n" | ||||
<< " \"" << FE->getValueAsString("ExtName") << "\",\n"; | << " \"" << FE->getValueAsString("ExtName") << "\",\n"; | ||||
// Record index of this extension. | // Record index of this extension. | ||||
FunctionExtensionIndex[FE->getName()] = Index++; | FunctionExtensionIndex[FE->getName()] = Index++; | ||||
} | } | ||||
OS << "};\n\n"; | OS << "};\n\n"; | ||||
} | } | ||||
void BuiltinNameEmitter::EmitTypeTable() { | void BuiltinNameEmitter::EmitTypeTable() { | ||||
OS << "static const OpenCLTypeStruct TypeTable[] = {\n"; | OS << "const " << ClassName << "::ProgModelTypeStruct " << ClassName | ||||
<< "::TypeTable[] = {\n"; | |||||
for (const auto &T : TypeMap) { | for (const auto &T : TypeMap) { | ||||
const char *AccessQual = | const char *AccessQual = | ||||
StringSwitch<const char *>(T.first->getValueAsString("AccessQualifier")) | StringSwitch<const char *>(T.first->getValueAsString("AccessQualifier")) | ||||
.Case("RO", "OCLAQ_ReadOnly") | .Case("RO", "AQ_ReadOnly") | ||||
.Case("WO", "OCLAQ_WriteOnly") | .Case("WO", "AQ_WriteOnly") | ||||
.Case("RW", "OCLAQ_ReadWrite") | .Case("RW", "AQ_ReadWrite") | ||||
.Default("OCLAQ_None"); | .Default("AQ_None"); | ||||
OS << " // " << T.second << "\n" | OS << " // " << T.second << "\n" | ||||
<< " {OCLT_" << T.first->getValueAsString("Name") << ", " | << " {TID_" << T.first->getValueAsString("Name") << ", " | ||||
<< T.first->getValueAsInt("VecWidth") << ", " | << T.first->getValueAsInt("VecWidth") << ", " | ||||
<< T.first->getValueAsBit("IsPointer") << ", " | << T.first->getValueAsBit("IsPointer") << ", " | ||||
<< T.first->getValueAsBit("IsConst") << ", " | << T.first->getValueAsBit("IsConst") << ", " | ||||
<< T.first->getValueAsBit("IsVolatile") << ", " | << T.first->getValueAsBit("IsVolatile") << ", " << AccessQual << ", " | ||||
<< AccessQual << ", " | |||||
<< T.first->getValueAsString("AddrSpace") << "},\n"; | << T.first->getValueAsString("AddrSpace") << "},\n"; | ||||
} | } | ||||
OS << "};\n\n"; | OS << "};\n\n"; | ||||
} | } | ||||
void BuiltinNameEmitter::EmitSignatureTable() { | void BuiltinNameEmitter::EmitSignatureTable() { | ||||
// Store a type (e.g. int, float, int2, ...). The type is stored as an index | // Store a type (e.g. int, float, int2, ...). The type is stored as an index | ||||
// of a struct OpenCLType table. Multiple entries following each other form a | // of a struct ProgModelTypeStruct table. Multiple entries following each | ||||
// signature. | // other form a signature. | ||||
OS << "static const unsigned short SignatureTable[] = {\n"; | OS << "const unsigned short " << ClassName << "::SignatureTable[] = {\n"; | ||||
for (const auto &P : SignaturesList) { | for (const auto &P : SignaturesList) { | ||||
OS << " // " << P.second << "\n "; | OS << " // " << P.second << "\n "; | ||||
for (const Record *R : P.first) { | for (const Record *R : P.first) { | ||||
unsigned Entry = TypeMap.find(R)->second; | unsigned Entry = TypeMap.find(R)->second; | ||||
if (Entry > USHRT_MAX) { | if (Entry > USHRT_MAX) { | ||||
// Report an error when seeing an entry that is too large for the | // Report an error when seeing an entry that is too large for the | ||||
// current index type (unsigned short). When hitting this, the type | // current index type (unsigned short). When hitting this, the type | ||||
// of SignatureTable will need to be changed. | // of SignatureTable will need to be changed. | ||||
Show All 27 Lines | static unsigned short EncodeVersions(unsigned int MinVersion, | ||||
} | } | ||||
return Encoded; | return Encoded; | ||||
} | } | ||||
void BuiltinNameEmitter::EmitBuiltinTable() { | void BuiltinNameEmitter::EmitBuiltinTable() { | ||||
unsigned Index = 0; | unsigned Index = 0; | ||||
OS << "static const OpenCLBuiltinStruct BuiltinTable[] = {\n"; | OS << "const " << ClassName << "::BuiltinStruct " << ClassName | ||||
<< "::BuiltinTable[] = {\n"; | |||||
for (const auto &SLM : SignatureListMap) { | for (const auto &SLM : SignatureListMap) { | ||||
OS << " // " << (Index + 1) << ": "; | OS << " // " << (Index + 1) << ": "; | ||||
for (const auto &Name : SLM.second.Names) { | for (const auto &Name : SLM.second.Names) { | ||||
OS << Name << ", "; | OS << Name << ", "; | ||||
} | } | ||||
OS << "\n"; | OS << "\n"; | ||||
for (const auto &Overload : SLM.second.Signatures) { | for (const auto &Overload : SLM.second.Signatures) { | ||||
StringRef ExtName = Overload.first->getValueAsDef("Extension")->getName(); | StringRef ExtName = Overload.first->getValueAsDef("Extension")->getName(); | ||||
unsigned int MinVersion = | unsigned int MinVersion = | ||||
Overload.first->getValueAsDef("MinVersion")->getValueAsInt("ID"); | Overload.first->getValueAsDef("MinVersion")->getValueAsInt("ID"); | ||||
unsigned int MaxVersion = | unsigned int MaxVersion = | ||||
Overload.first->getValueAsDef("MaxVersion")->getValueAsInt("ID"); | Overload.first->getValueAsDef("MaxVersion")->getValueAsInt("ID"); | ||||
OS << " { " << Overload.second << ", " | OS << " { " << Overload.second << ", " | ||||
<< Overload.first->getValueAsListOfDefs("Signature").size() << ", " | << Overload.first->getValueAsListOfDefs("Signature").size() << ", " | ||||
<< (Overload.first->getValueAsBit("IsPure")) << ", " | << (Overload.first->getValueAsBit("IsPure")) << ", " | ||||
<< (Overload.first->getValueAsBit("IsConst")) << ", " | << (Overload.first->getValueAsBit("IsConst")) << ", " | ||||
<< (Overload.first->getValueAsBit("IsConv")) << ", " | << (Overload.first->getValueAsBit("IsConv")) << ", " | ||||
<< (Overload.first->getValueAsBit("IsVariadic")) << ", " | |||||
<< FunctionExtensionIndex[ExtName] << ", " | << FunctionExtensionIndex[ExtName] << ", " | ||||
<< EncodeVersions(MinVersion, MaxVersion) << " },\n"; | << EncodeVersions(MinVersion, MaxVersion) << " },\n"; | ||||
Index++; | Index++; | ||||
} | } | ||||
} | } | ||||
OS << "};\n\n"; | OS << "};\n\n"; | ||||
} | } | ||||
bool BuiltinNameEmitter::CanReuseSignature( | bool BuiltinNameEmitter::CanReuseSignature( | ||||
BuiltinIndexListTy *Candidate, | BuiltinIndexListTy *Candidate, | ||||
std::vector<std::pair<const Record *, unsigned>> &SignatureList) { | std::vector<std::pair<const Record *, unsigned>> &SignatureList) { | ||||
assert(Candidate->size() == SignatureList.size() && | assert(Candidate->size() == SignatureList.size() && | ||||
"signature lists should have the same size"); | "signature lists should have the same size"); | ||||
auto &CandidateSigs = | auto &CandidateSigs = SignatureListMap.find(Candidate)->second.Signatures; | ||||
SignatureListMap.find(Candidate)->second.Signatures; | |||||
for (unsigned Index = 0; Index < Candidate->size(); Index++) { | for (unsigned Index = 0; Index < Candidate->size(); Index++) { | ||||
const Record *Rec = SignatureList[Index].first; | const Record *Rec = SignatureList[Index].first; | ||||
const Record *Rec2 = CandidateSigs[Index].first; | const Record *Rec2 = CandidateSigs[Index].first; | ||||
if (Rec->getValueAsBit("IsPure") == Rec2->getValueAsBit("IsPure") && | if (Rec->getValueAsBit("IsPure") == Rec2->getValueAsBit("IsPure") && | ||||
Rec->getValueAsBit("IsConst") == Rec2->getValueAsBit("IsConst") && | Rec->getValueAsBit("IsConst") == Rec2->getValueAsBit("IsConst") && | ||||
Rec->getValueAsBit("IsConv") == Rec2->getValueAsBit("IsConv") && | Rec->getValueAsBit("IsConv") == Rec2->getValueAsBit("IsConv") && | ||||
Rec->getValueAsBit("IsVariadic") == Rec2->getValueAsBit("IsVariadic") && | |||||
Rec->getValueAsDef("MinVersion")->getValueAsInt("ID") == | Rec->getValueAsDef("MinVersion")->getValueAsInt("ID") == | ||||
Rec2->getValueAsDef("MinVersion")->getValueAsInt("ID") && | Rec2->getValueAsDef("MinVersion")->getValueAsInt("ID") && | ||||
Rec->getValueAsDef("MaxVersion")->getValueAsInt("ID") == | Rec->getValueAsDef("MaxVersion")->getValueAsInt("ID") == | ||||
Rec2->getValueAsDef("MaxVersion")->getValueAsInt("ID") && | Rec2->getValueAsDef("MaxVersion")->getValueAsInt("ID") && | ||||
Rec->getValueAsDef("Extension")->getName() == | Rec->getValueAsDef("Extension")->getName() == | ||||
Rec2->getValueAsDef("Extension")->getName()) { | Rec2->getValueAsDef("Extension")->getName()) { | ||||
return true; | return true; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | for (const auto &FctName : SLM.second.Names) { | ||||
SS.flush(); | SS.flush(); | ||||
ValidBuiltins.push_back( | ValidBuiltins.push_back( | ||||
StringMatcher::StringPair(std::string(FctName), RetStmt)); | StringMatcher::StringPair(std::string(FctName), RetStmt)); | ||||
} | } | ||||
CumulativeIndex += Ovl.size(); | CumulativeIndex += Ovl.size(); | ||||
} | } | ||||
OS << R"( | OS << R"( | ||||
// Find out whether a string matches an existing OpenCL builtin function name. | // Find out whether a string matches an existing builtin function name. | ||||
// Returns: A pair <0, 0> if no name matches. | // Returns: A pair <0, 0> if no name matches. | ||||
// A pair <Index, Len> indexing the BuiltinTable if the name is | // A pair <Index, Len> indexing the BuiltinTable if the name is | ||||
// matching an OpenCL builtin function. | // matching a builtin function. | ||||
static std::pair<unsigned, unsigned> isOpenCLBuiltin(llvm::StringRef Name) { | |||||
)"; | )"; | ||||
OS << "std::pair<unsigned, unsigned> " << ClassName | |||||
<< "::isBuiltin(llvm::StringRef Name) {\n\n"; | |||||
StringMatcher("Name", ValidBuiltins, OS).Emit(0, true); | StringMatcher("Name", ValidBuiltins, OS).Emit(0, true); | ||||
OS << " return std::make_pair(0, 0);\n"; | OS << " return std::make_pair(0, 0);\n"; | ||||
OS << "} // isOpenCLBuiltin\n"; | OS << "} // isBuiltin\n"; | ||||
} | } | ||||
void BuiltinNameEmitter::EmitQualTypeFinder() { | void BuiltinNameEmitter::EmitQualTypeFinder() { | ||||
OS << R"( | OS << R"( | ||||
// Convert an ProgModelTypeStruct type to a list of QualTypes. | |||||
static QualType getOpenCLEnumType(Sema &S, llvm::StringRef Name); | static QualType getOpenCLEnumType(Sema &S, llvm::StringRef Name); | ||||
static QualType getOpenCLTypedefType(Sema &S, llvm::StringRef Name); | static QualType getOpenCLTypedefType(Sema &S, llvm::StringRef Name); | ||||
// Convert an OpenCLTypeStruct type to a list of QualTypes. | // Convert an ProgModelTypeStruct type to a list of QualTypes. | ||||
// Generic types represent multiple types and vector sizes, thus a vector | // Generic types represent multiple types and vector sizes, thus a vector | ||||
// is returned. The conversion is done in two steps: | // is returned. The conversion is done in two steps: | ||||
// Step 1: A switch statement fills a vector with scalar base types for the | // Step 1: A switch statement fills a vector with scalar base types for the | ||||
// Cartesian product of (vector sizes) x (types) for generic types, | // Cartesian product of (vector sizes) x (types) for generic types, | ||||
// or a single scalar type for non generic types. | // or a single scalar type for non generic types. | ||||
// Step 2: Qualifiers and other type properties such as vector size are | // Step 2: Qualifiers and other type properties such as vector size are | ||||
// applied. | // applied. | ||||
static void OCL2Qual(Sema &S, const OpenCLTypeStruct &Ty, | )"; | ||||
llvm::SmallVectorImpl<QualType> &QT) { | |||||
OS << "void " << ClassName | |||||
<< "::Bultin2Qual(Sema &S, const ProgModelTypeStruct &Ty, " | |||||
"llvm::SmallVectorImpl<QualType> &QT) {\n"; | |||||
OS << R"( | |||||
ASTContext &Context = S.Context; | ASTContext &Context = S.Context; | ||||
// Number of scalar types in the GenType. | // Number of scalar types in the GenType. | ||||
unsigned GenTypeNumTypes; | unsigned GenTypeNumTypes; | ||||
// Pointer to the list of vector sizes for the GenType. | // Pointer to the list of vector sizes for the GenType. | ||||
llvm::ArrayRef<unsigned> GenVectorSizes; | llvm::ArrayRef<unsigned> GenVectorSizes; | ||||
)"; | )"; | ||||
// Generate list of vector sizes for each generic type. | // Generate list of vector sizes for each generic type. | ||||
for (const auto *VectList : Records.getAllDerivedDefinitions("IntList")) { | for (const auto *VectList : Records.getAllDerivedDefinitions("IntList")) { | ||||
OS << " constexpr unsigned List" | OS << " constexpr unsigned List" << VectList->getValueAsString("Name") | ||||
<< VectList->getValueAsString("Name") << "[] = {"; | << "[] = {"; | ||||
for (const auto V : VectList->getValueAsListOfInts("List")) { | for (const auto V : VectList->getValueAsListOfInts("List")) { | ||||
OS << V << ", "; | OS << V << ", "; | ||||
} | } | ||||
OS << "};\n"; | OS << "};\n"; | ||||
} | } | ||||
// Step 1. | // Step 1. | ||||
// Start of switch statement over all types. | // Start of switch statement over all types. | ||||
Show All 17 Lines | for (auto *IT : ImageTypes) { | ||||
} | } | ||||
} | } | ||||
// Emit the cases for the image types. For an image type name, there are 3 | // Emit the cases for the image types. For an image type name, there are 3 | ||||
// corresponding QualTypes ("RO", "WO", "RW"). The "AccessQualifier" field | // corresponding QualTypes ("RO", "WO", "RW"). The "AccessQualifier" field | ||||
// tells which one is needed. Emit a switch statement that puts the | // tells which one is needed. Emit a switch statement that puts the | ||||
// corresponding QualType into "QT". | // corresponding QualType into "QT". | ||||
for (const auto &ITE : ImageTypesMap) { | for (const auto &ITE : ImageTypesMap) { | ||||
OS << " case OCLT_" << ITE.getKey() << ":\n" | OS << " case TID_" << ITE.getKey() << ":\n" | ||||
<< " switch (Ty.AccessQualifier) {\n" | << " switch (Ty.AccessQualifier) {\n" | ||||
<< " case OCLAQ_None:\n" | << " case AQ_None:\n" | ||||
<< " llvm_unreachable(\"Image without access qualifier\");\n"; | << " llvm_unreachable(\"Image without access qualifier\");\n"; | ||||
for (const auto &Image : ITE.getValue()) { | for (const auto &Image : ITE.getValue()) { | ||||
OS << StringSwitch<const char *>( | OS << StringSwitch<const char *>( | ||||
Image->getValueAsString("AccessQualifier")) | Image->getValueAsString("AccessQualifier")) | ||||
.Case("RO", " case OCLAQ_ReadOnly:\n") | .Case("RO", " case AQ_ReadOnly:\n") | ||||
.Case("WO", " case OCLAQ_WriteOnly:\n") | .Case("WO", " case AQ_WriteOnly:\n") | ||||
.Case("RW", " case OCLAQ_ReadWrite:\n") | .Case("RW", " case AQ_ReadWrite:\n") | ||||
<< " QT.push_back(" | << " QT.push_back(" | ||||
<< Image->getValueAsDef("QTExpr")->getValueAsString("TypeExpr") | << Image->getValueAsDef("QTExpr")->getValueAsString("TypeExpr") | ||||
<< ");\n" | << ");\n" | ||||
<< " break;\n"; | << " break;\n"; | ||||
} | } | ||||
OS << " }\n" | OS << " }\n" | ||||
<< " break;\n"; | << " break;\n"; | ||||
} | } | ||||
// Switch cases for generic types. | // Switch cases for generic types. | ||||
for (const auto *GenType : Records.getAllDerivedDefinitions("GenericType")) { | for (const auto *GenType : Records.getAllDerivedDefinitions("GenericType")) { | ||||
OS << " case OCLT_" << GenType->getValueAsString("Name") << ": {\n"; | OS << " case TID_" << GenType->getValueAsString("Name") << ": {\n"; | ||||
// Build the Cartesian product of (vector sizes) x (types). Only insert | // Build the Cartesian product of (vector sizes) x (types). Only insert | ||||
// the plain scalar types for now; other type information such as vector | // the plain scalar types for now; other type information such as vector | ||||
// size and type qualifiers will be added after the switch statement. | // size and type qualifiers will be added after the switch statement. | ||||
std::vector<Record *> BaseTypes = | std::vector<Record *> BaseTypes = | ||||
GenType->getValueAsDef("TypeList")->getValueAsListOfDefs("List"); | GenType->getValueAsDef("TypeList")->getValueAsListOfDefs("List"); | ||||
// Collect all QualTypes for a single vector size into TypeList. | // Collect all QualTypes for a single vector size into TypeList. | ||||
OS << " SmallVector<QualType, " << BaseTypes.size() << "> TypeList;\n"; | OS << " SmallVector<QualType, " << BaseTypes.size() << "> TypeList;\n"; | ||||
for (const auto *T : BaseTypes) { | for (const auto *T : BaseTypes) { | ||||
StringRef Ext = | StringRef Ext = | ||||
T->getValueAsDef("Extension")->getValueAsString("ExtName"); | T->getValueAsDef("Extension")->getValueAsString("ExtName"); | ||||
if (!Ext.empty()) { | if (!Ext.empty()) { | ||||
OS << " if (S.getPreprocessor().isMacroDefined(\"" << Ext | OS << " if (S.getPreprocessor().isMacroDefined(\"" << Ext | ||||
<< "\")) {\n "; | << "\")) {\n "; | ||||
} | } | ||||
if (T->getValueAsDef("QTExpr")->isSubClassOf("QualTypeFromFunction")) | |||||
OS << " TypeList.push_back(" | OS << " TypeList.push_back(" | ||||
<< T->getValueAsDef("QTExpr")->getValueAsString("TypeExpr") << ");\n"; | << T->getValueAsDef("QTExpr")->getValueAsString("TypeExpr") | ||||
<< "(Context));\n"; | |||||
else | |||||
OS << " TypeList.push_back(" | |||||
<< T->getValueAsDef("QTExpr")->getValueAsString("TypeExpr") | |||||
<< ");\n"; | |||||
if (!Ext.empty()) { | if (!Ext.empty()) { | ||||
OS << " }\n"; | OS << " }\n"; | ||||
} | } | ||||
} | } | ||||
OS << " GenTypeNumTypes = TypeList.size();\n"; | OS << " GenTypeNumTypes = TypeList.size();\n"; | ||||
// Duplicate the TypeList for every vector size. | // Duplicate the TypeList for every vector size. | ||||
std::vector<int64_t> VectorList = | std::vector<int64_t> VectorList = | ||||
Show All 26 Lines | if (TypesSeen.find(T->getValueAsString("Name")) != TypesSeen.end()) | ||||
continue; | continue; | ||||
TypesSeen.insert(std::make_pair(T->getValueAsString("Name"), true)); | TypesSeen.insert(std::make_pair(T->getValueAsString("Name"), true)); | ||||
// Check the Type does not have an "abstract" QualType | // Check the Type does not have an "abstract" QualType | ||||
auto QT = T->getValueAsDef("QTExpr"); | auto QT = T->getValueAsDef("QTExpr"); | ||||
if (QT->getValueAsBit("IsAbstract") == 1) | if (QT->getValueAsBit("IsAbstract") == 1) | ||||
continue; | continue; | ||||
// Emit the cases for non generic, non image types. | // Emit the cases for non generic, non image types. | ||||
OS << " case OCLT_" << T->getValueAsString("Name") << ":\n"; | OS << " case TID_" << T->getValueAsString("Name") << ":\n"; | ||||
StringRef Ext = T->getValueAsDef("Extension")->getValueAsString("ExtName"); | StringRef Ext = T->getValueAsDef("Extension")->getValueAsString("ExtName"); | ||||
// If this type depends on an extension, ensure the extension macro is | // If this type depends on an extension, ensure the extension macro is | ||||
// defined. | // defined. | ||||
if (!Ext.empty()) { | if (!Ext.empty()) { | ||||
OS << " if (S.getPreprocessor().isMacroDefined(\"" << Ext | OS << " if (S.getPreprocessor().isMacroDefined(\"" << Ext | ||||
<< "\")) {\n "; | << "\")) {\n "; | ||||
} | } | ||||
if (QT->isSubClassOf("QualTypeFromFunction")) | |||||
OS << " QT.push_back(" << QT->getValueAsString("TypeExpr") | |||||
<< "(Context));\n"; | |||||
else | |||||
OS << " QT.push_back(" << QT->getValueAsString("TypeExpr") << ");\n"; | OS << " QT.push_back(" << QT->getValueAsString("TypeExpr") << ");\n"; | ||||
if (!Ext.empty()) { | if (!Ext.empty()) { | ||||
OS << " }\n"; | OS << " }\n"; | ||||
} | } | ||||
OS << " break;\n"; | OS << " break;\n"; | ||||
} | } | ||||
// End of switch statement. | // End of switch statement. | ||||
OS << " } // end of switch (Ty.ID)\n\n"; | OS << " } // end of switch (Ty.ID)\n\n"; | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | )"; | ||||
if (Ty.IsPointer != 0) { | if (Ty.IsPointer != 0) { | ||||
for (unsigned Index = 0; Index < QT.size(); Index++) { | for (unsigned Index = 0; Index < QT.size(); Index++) { | ||||
QT[Index] = Context.getAddrSpaceQualType(QT[Index], Ty.AS); | QT[Index] = Context.getAddrSpaceQualType(QT[Index], Ty.AS); | ||||
QT[Index] = Context.getPointerType(QT[Index]); | QT[Index] = Context.getPointerType(QT[Index]); | ||||
} | } | ||||
} | } | ||||
)"; | )"; | ||||
// End of the "OCL2Qual" function. | // End of the "Bultin2Qual" function. | ||||
OS << "\n} // OCL2Qual\n"; | OS << "\n} // Bultin2Qual\n"; | ||||
} | } | ||||
std::string OpenCLBuiltinFileEmitterBase::getTypeString(const Record *Type, | std::string OpenCLBuiltinFileEmitterBase::getTypeString(const Record *Type, | ||||
TypeFlags Flags, | TypeFlags Flags, | ||||
int VectorSize) const { | int VectorSize) const { | ||||
std::string S; | std::string S; | ||||
if (Type->getValueAsBit("IsConst") || Flags.IsConst) { | if (Type->getValueAsBit("IsConst") || Flags.IsConst) { | ||||
S += "const "; | S += "const "; | ||||
▲ Show 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | for (const auto *B : Builtins) { | ||||
} | } | ||||
OS << OptionalVersionEndif; | OS << OptionalVersionEndif; | ||||
OS << OptionalExtensionEndif; | OS << OptionalExtensionEndif; | ||||
} | } | ||||
} | } | ||||
void clang::EmitClangOpenCLBuiltins(RecordKeeper &Records, raw_ostream &OS) { | void clang::EmitClangOpenCLBuiltins(RecordKeeper &Records, raw_ostream &OS) { | ||||
BuiltinNameEmitter NameChecker(Records, OS); | BuiltinNameEmitter NameChecker(Records, OS, "OpenCL"); | ||||
NameChecker.Emit(); | |||||
} | |||||
void clang::EmitClangSPIRVBuiltins(RecordKeeper &Records, raw_ostream &OS) { | |||||
BuiltinNameEmitter NameChecker(Records, OS, "SPIRV"); | |||||
NameChecker.Emit(); | NameChecker.Emit(); | ||||
} | } | ||||
void clang::EmitClangOpenCLBuiltinTests(RecordKeeper &Records, | void clang::EmitClangOpenCLBuiltinTests(RecordKeeper &Records, | ||||
raw_ostream &OS) { | raw_ostream &OS) { | ||||
OpenCLBuiltinTestEmitter TestFileGenerator(Records, OS); | OpenCLBuiltinTestEmitter TestFileGenerator(Records, OS); | ||||
TestFileGenerator.emit(); | TestFileGenerator.emit(); | ||||
} | } |