ClangOpenCLBuiltinEmitter.cpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  1. //===- ClangOpenCLBuiltinEmitter.cpp - Generate Clang OpenCL Builtin handling
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  6. // See https://llvm.org/LICENSE.txt for license information.
  7. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  8. //
  9. //===----------------------------------------------------------------------===//
  10. //
  11. // These backends consume the definitions of OpenCL builtin functions in
  12. // clang/lib/Sema/OpenCLBuiltins.td and produce builtin handling code for
  13. // inclusion in SemaLookup.cpp, or a test file that calls all declared builtins.
  14. //
  15. //===----------------------------------------------------------------------===//
  16. #include "TableGenBackends.h"
  17. #include "llvm/ADT/MapVector.h"
  18. #include "llvm/ADT/STLExtras.h"
  19. #include "llvm/ADT/SmallSet.h"
  20. #include "llvm/ADT/SmallString.h"
  21. #include "llvm/ADT/StringExtras.h"
  22. #include "llvm/ADT/StringMap.h"
  23. #include "llvm/ADT/StringRef.h"
  24. #include "llvm/ADT/StringSwitch.h"
  25. #include "llvm/Support/ErrorHandling.h"
  26. #include "llvm/Support/raw_ostream.h"
  27. #include "llvm/TableGen/Error.h"
  28. #include "llvm/TableGen/Record.h"
  29. #include "llvm/TableGen/StringMatcher.h"
  30. #include "llvm/TableGen/TableGenBackend.h"
  31. using namespace llvm;
  32. namespace {
  33. // A list of signatures that are shared by one or more builtin functions.
  34. struct BuiltinTableEntries {
  35. SmallVector<StringRef, 4> Names;
  36. std::vector<std::pair<const Record *, unsigned>> Signatures;
  37. };
  38. // This tablegen backend emits code for checking whether a function is an
  39. // OpenCL builtin function. If so, all overloads of this function are
  40. // added to the LookupResult. The generated include file is used by
  41. // SemaLookup.cpp
  42. //
  43. // For a successful lookup of e.g. the "cos" builtin, isOpenCLBuiltin("cos")
  44. // returns a pair <Index, Len>.
  45. // BuiltinTable[Index] to BuiltinTable[Index + Len] contains the pairs
  46. // <SigIndex, SigLen> of the overloads of "cos".
  47. // SignatureTable[SigIndex] to SignatureTable[SigIndex + SigLen] contains
  48. // one of the signatures of "cos". The SignatureTable entry can be
  49. // referenced by other functions, e.g. "sin", to exploit the fact that
  50. // many OpenCL builtins share the same signature.
  51. //
  52. // The file generated by this TableGen emitter contains the following:
  53. //
  54. // * Structs and enums to represent types and function signatures.
  55. //
  56. // * const char *FunctionExtensionTable[]
  57. // List of space-separated OpenCL extensions. A builtin references an
  58. // entry in this table when the builtin requires a particular (set of)
  59. // extension(s) to be enabled.
  60. //
  61. // * OpenCLTypeStruct TypeTable[]
  62. // Type information for return types and arguments.
  63. //
  64. // * unsigned SignatureTable[]
  65. // A list of types representing function signatures. Each entry is an index
  66. // into the above TypeTable. Multiple entries following each other form a
  67. // signature, where the first entry is the return type and subsequent
  68. // entries are the argument types.
  69. //
  70. // * OpenCLBuiltinStruct BuiltinTable[]
  71. // Each entry represents one overload of an OpenCL builtin function and
  72. // consists of an index into the SignatureTable and the number of arguments.
  73. //
  74. // * std::pair<unsigned, unsigned> isOpenCLBuiltin(llvm::StringRef Name)
  75. // Find out whether a string matches an existing OpenCL builtin function
  76. // name and return an index into BuiltinTable and the number of overloads.
  77. //
  78. // * void OCL2Qual(Sema&, OpenCLTypeStruct, std::vector<QualType>&)
  79. // Convert an OpenCLTypeStruct type to a list of QualType instances.
  80. // One OpenCLTypeStruct can represent multiple types, primarily when using
  81. // GenTypes.
  82. //
  83. class BuiltinNameEmitter {
  84. public:
  85. BuiltinNameEmitter(RecordKeeper &Records, raw_ostream &OS)
  86. : Records(Records), OS(OS) {}
  87. // Entrypoint to generate the functions and structures for checking
  88. // whether a function is an OpenCL builtin function.
  89. void Emit();
  90. private:
  91. // A list of indices into the builtin function table.
  92. using BuiltinIndexListTy = SmallVector<unsigned, 11>;
  93. // Contains OpenCL builtin functions and related information, stored as
  94. // Record instances. They are coming from the associated TableGen file.
  95. RecordKeeper &Records;
  96. // The output file.
  97. raw_ostream &OS;
  98. // Helper function for BuiltinNameEmitter::EmitDeclarations. Generate enum
  99. // definitions in the Output string parameter, and save their Record instances
  100. // in the List parameter.
  101. // \param Types (in) List containing the Types to extract.
  102. // \param TypesSeen (inout) List containing the Types already extracted.
  103. // \param Output (out) String containing the enums to emit in the output file.
  104. // \param List (out) List containing the extracted Types, except the Types in
  105. // TypesSeen.
  106. void ExtractEnumTypes(std::vector<Record *> &Types,
  107. StringMap<bool> &TypesSeen, std::string &Output,
  108. std::vector<const Record *> &List);
  109. // Emit the enum or struct used in the generated file.
  110. // Populate the TypeList at the same time.
  111. void EmitDeclarations();
  112. // Parse the Records generated by TableGen to populate the SignaturesList,
  113. // FctOverloadMap and TypeMap.
  114. void GetOverloads();
  115. // Compare two lists of signatures and check that e.g. the OpenCL version,
  116. // function attributes, and extension are equal for each signature.
  117. // \param Candidate (in) Entry in the SignatureListMap to check.
  118. // \param SignatureList (in) List of signatures of the considered function.
  119. // \returns true if the two lists of signatures are identical.
  120. bool CanReuseSignature(
  121. BuiltinIndexListTy *Candidate,
  122. std::vector<std::pair<const Record *, unsigned>> &SignatureList);
  123. // Group functions with the same list of signatures by populating the
  124. // SignatureListMap.
  125. // Some builtin functions have the same list of signatures, for example the
  126. // "sin" and "cos" functions. To save space in the BuiltinTable, the
  127. // "isOpenCLBuiltin" function will have the same output for these two
  128. // function names.
  129. void GroupBySignature();
  130. // Emit the FunctionExtensionTable that lists all function extensions.
  131. void EmitExtensionTable();
  132. // Emit the TypeTable containing all types used by OpenCL builtins.
  133. void EmitTypeTable();
  134. // Emit the SignatureTable. This table contains all the possible signatures.
  135. // A signature is stored as a list of indexes of the TypeTable.
  136. // The first index references the return type (mandatory), and the followings
  137. // reference its arguments.
  138. // E.g.:
  139. // 15, 2, 15 can represent a function with the signature:
  140. // int func(float, int)
  141. // The "int" type being at the index 15 in the TypeTable.
  142. void EmitSignatureTable();
  143. // Emit the BuiltinTable table. This table contains all the overloads of
  144. // each function, and is a struct OpenCLBuiltinDecl.
  145. // E.g.:
  146. // // 891 convert_float2_rtn
  147. // { 58, 2, 3, 100, 0 },
  148. // This means that the signature of this convert_float2_rtn overload has
  149. // 1 argument (+1 for the return type), stored at index 58 in
  150. // the SignatureTable. This prototype requires extension "3" in the
  151. // FunctionExtensionTable. The last two values represent the minimum (1.0)
  152. // and maximum (0, meaning no max version) OpenCL version in which this
  153. // overload is supported.
  154. void EmitBuiltinTable();
  155. // Emit a StringMatcher function to check whether a function name is an
  156. // OpenCL builtin function name.
  157. void EmitStringMatcher();
  158. // Emit a function returning the clang QualType instance associated with
  159. // the TableGen Record Type.
  160. void EmitQualTypeFinder();
  161. // Contains a list of the available signatures, without the name of the
  162. // function. Each pair consists of a signature and a cumulative index.
  163. // E.g.: <<float, float>, 0>,
  164. // <<float, int, int, 2>>,
  165. // <<float>, 5>,
  166. // ...
  167. // <<double, double>, 35>.
  168. std::vector<std::pair<std::vector<Record *>, unsigned>> SignaturesList;
  169. // Map the name of a builtin function to its prototypes (instances of the
  170. // TableGen "Builtin" class).
  171. // Each prototype is registered as a pair of:
  172. // <pointer to the "Builtin" instance,
  173. // cumulative index of the associated signature in the SignaturesList>
  174. // E.g.: The function cos: (float cos(float), double cos(double), ...)
  175. // <"cos", <<ptrToPrototype0, 5>,
  176. // <ptrToPrototype1, 35>,
  177. // <ptrToPrototype2, 79>>
  178. // ptrToPrototype1 has the following signature: <double, double>
  179. MapVector<StringRef, std::vector<std::pair<const Record *, unsigned>>>
  180. FctOverloadMap;
  181. // Contains the map of OpenCL types to their index in the TypeTable.
  182. MapVector<const Record *, unsigned> TypeMap;
  183. // List of OpenCL function extensions mapping extension strings to
  184. // an index into the FunctionExtensionTable.
  185. StringMap<unsigned> FunctionExtensionIndex;
  186. // List of OpenCL type names in the same order as in enum OpenCLTypeID.
  187. // This list does not contain generic types.
  188. std::vector<const Record *> TypeList;
  189. // Same as TypeList, but for generic types only.
  190. std::vector<const Record *> GenTypeList;
  191. // Map an ordered vector of signatures to their original Record instances,
  192. // and to a list of function names that share these signatures.
  193. //
  194. // For example, suppose the "cos" and "sin" functions have only three
  195. // signatures, and these signatures are at index Ix in the SignatureTable:
  196. // cos | sin | Signature | Index
  197. // float cos(float) | float sin(float) | Signature1 | I1
  198. // double cos(double) | double sin(double) | Signature2 | I2
  199. // half cos(half) | half sin(half) | Signature3 | I3
  200. //
  201. // Then we will create a mapping of the vector of signatures:
  202. // SignatureListMap[<I1, I2, I3>] = <
  203. // <"cos", "sin">,
  204. // <Signature1, Signature2, Signature3>>
  205. // The function "tan", having the same signatures, would be mapped to the
  206. // same entry (<I1, I2, I3>).
  207. MapVector<BuiltinIndexListTy *, BuiltinTableEntries> SignatureListMap;
  208. };
  209. /// Base class for emitting a file (e.g. header or test) from OpenCLBuiltins.td
  210. class OpenCLBuiltinFileEmitterBase {
  211. public:
  212. OpenCLBuiltinFileEmitterBase(RecordKeeper &Records, raw_ostream &OS)
  213. : Records(Records), OS(OS) {}
  214. virtual ~OpenCLBuiltinFileEmitterBase() = default;
  215. // Entrypoint to generate the functions for testing all OpenCL builtin
  216. // functions.
  217. virtual void emit() = 0;
  218. protected:
  219. struct TypeFlags {
  220. TypeFlags() : IsConst(false), IsVolatile(false), IsPointer(false) {}
  221. bool IsConst : 1;
  222. bool IsVolatile : 1;
  223. bool IsPointer : 1;
  224. StringRef AddrSpace;
  225. };
  226. // Return a string representation of the given type, such that it can be
  227. // used as a type in OpenCL C code.
  228. std::string getTypeString(const Record *Type, TypeFlags Flags,
  229. int VectorSize) const;
  230. // Return the type(s) and vector size(s) for the given type. For
  231. // non-GenericTypes, the resulting vectors will contain 1 element. For
  232. // GenericTypes, the resulting vectors typically contain multiple elements.
  233. void getTypeLists(Record *Type, TypeFlags &Flags,
  234. std::vector<Record *> &TypeList,
  235. std::vector<int64_t> &VectorList) const;
  236. // Expand the TableGen Records representing a builtin function signature into
  237. // one or more function signatures. Return them as a vector of a vector of
  238. // strings, with each string containing an OpenCL C type and optional
  239. // qualifiers.
  240. //
  241. // The Records may contain GenericTypes, which expand into multiple
  242. // signatures. Repeated occurrences of GenericType in a signature expand to
  243. // the same types. For example [char, FGenType, FGenType] expands to:
  244. // [char, float, float]
  245. // [char, float2, float2]
  246. // [char, float3, float3]
  247. // ...
  248. void
  249. expandTypesInSignature(const std::vector<Record *> &Signature,
  250. SmallVectorImpl<SmallVector<std::string, 2>> &Types);
  251. // Emit extension enabling pragmas.
  252. void emitExtensionSetup();
  253. // Emit an #if guard for a Builtin's extension. Return the corresponding
  254. // closing #endif, or an empty string if no extension #if guard was emitted.
  255. std::string emitExtensionGuard(const Record *Builtin);
  256. // Emit an #if guard for a Builtin's language version. Return the
  257. // corresponding closing #endif, or an empty string if no version #if guard
  258. // was emitted.
  259. std::string emitVersionGuard(const Record *Builtin);
  260. // Emit an #if guard for all type extensions required for the given type
  261. // strings. Return the corresponding closing #endif, or an empty string
  262. // if no extension #if guard was emitted.
  263. StringRef
  264. emitTypeExtensionGuards(const SmallVectorImpl<std::string> &Signature);
  265. // Map type strings to type extensions (e.g. "half2" -> "cl_khr_fp16").
  266. StringMap<StringRef> TypeExtMap;
  267. // Contains OpenCL builtin functions and related information, stored as
  268. // Record instances. They are coming from the associated TableGen file.
  269. RecordKeeper &Records;
  270. // The output file.
  271. raw_ostream &OS;
  272. };
  273. // OpenCL builtin test generator. This class processes the same TableGen input
  274. // as BuiltinNameEmitter, but generates a .cl file that contains a call to each
  275. // builtin function described in the .td input.
  276. class OpenCLBuiltinTestEmitter : public OpenCLBuiltinFileEmitterBase {
  277. public:
  278. OpenCLBuiltinTestEmitter(RecordKeeper &Records, raw_ostream &OS)
  279. : OpenCLBuiltinFileEmitterBase(Records, OS) {}
  280. // Entrypoint to generate the functions for testing all OpenCL builtin
  281. // functions.
  282. void emit() override;
  283. };
  284. } // namespace
  285. void BuiltinNameEmitter::Emit() {
  286. emitSourceFileHeader("OpenCL Builtin handling", OS);
  287. OS << "#include \"llvm/ADT/StringRef.h\"\n";
  288. OS << "using namespace clang;\n\n";
  289. // Emit enums and structs.
  290. EmitDeclarations();
  291. // Parse the Records to populate the internal lists.
  292. GetOverloads();
  293. GroupBySignature();
  294. // Emit tables.
  295. EmitExtensionTable();
  296. EmitTypeTable();
  297. EmitSignatureTable();
  298. EmitBuiltinTable();
  299. // Emit functions.
  300. EmitStringMatcher();
  301. EmitQualTypeFinder();
  302. }
  303. void BuiltinNameEmitter::ExtractEnumTypes(std::vector<Record *> &Types,
  304. StringMap<bool> &TypesSeen,
  305. std::string &Output,
  306. std::vector<const Record *> &List) {
  307. raw_string_ostream SS(Output);
  308. for (const auto *T : Types) {
  309. if (TypesSeen.find(T->getValueAsString("Name")) == TypesSeen.end()) {
  310. SS << " OCLT_" + T->getValueAsString("Name") << ",\n";
  311. // Save the type names in the same order as their enum value. Note that
  312. // the Record can be a VectorType or something else, only the name is
  313. // important.
  314. List.push_back(T);
  315. TypesSeen.insert(std::make_pair(T->getValueAsString("Name"), true));
  316. }
  317. }
  318. SS.flush();
  319. }
  320. void BuiltinNameEmitter::EmitDeclarations() {
  321. // Enum of scalar type names (float, int, ...) and generic type sets.
  322. OS << "enum OpenCLTypeID {\n";
  323. StringMap<bool> TypesSeen;
  324. std::string GenTypeEnums;
  325. std::string TypeEnums;
  326. // Extract generic types and non-generic types separately, to keep
  327. // gentypes at the end of the enum which simplifies the special handling
  328. // for gentypes in SemaLookup.
  329. std::vector<Record *> GenTypes =
  330. Records.getAllDerivedDefinitions("GenericType");
  331. ExtractEnumTypes(GenTypes, TypesSeen, GenTypeEnums, GenTypeList);
  332. std::vector<Record *> Types = Records.getAllDerivedDefinitions("Type");
  333. ExtractEnumTypes(Types, TypesSeen, TypeEnums, TypeList);
  334. OS << TypeEnums;
  335. OS << GenTypeEnums;
  336. OS << "};\n";
  337. // Structure definitions.
  338. OS << R"(
  339. // Image access qualifier.
  340. enum OpenCLAccessQual : unsigned char {
  341. OCLAQ_None,
  342. OCLAQ_ReadOnly,
  343. OCLAQ_WriteOnly,
  344. OCLAQ_ReadWrite
  345. };
  346. // Represents a return type or argument type.
  347. struct OpenCLTypeStruct {
  348. // A type (e.g. float, int, ...).
  349. const OpenCLTypeID ID;
  350. // Vector size (if applicable; 0 for scalars and generic types).
  351. const unsigned VectorWidth;
  352. // 0 if the type is not a pointer.
  353. const bool IsPointer : 1;
  354. // 0 if the type is not const.
  355. const bool IsConst : 1;
  356. // 0 if the type is not volatile.
  357. const bool IsVolatile : 1;
  358. // Access qualifier.
  359. const OpenCLAccessQual AccessQualifier;
  360. // Address space of the pointer (if applicable).
  361. const LangAS AS;
  362. };
  363. // One overload of an OpenCL builtin function.
  364. struct OpenCLBuiltinStruct {
  365. // Index of the signature in the OpenCLTypeStruct table.
  366. const unsigned SigTableIndex;
  367. // Entries between index SigTableIndex and (SigTableIndex + NumTypes - 1) in
  368. // the SignatureTable represent the complete signature. The first type at
  369. // index SigTableIndex is the return type.
  370. const unsigned NumTypes;
  371. // Function attribute __attribute__((pure))
  372. const bool IsPure : 1;
  373. // Function attribute __attribute__((const))
  374. const bool IsConst : 1;
  375. // Function attribute __attribute__((convergent))
  376. const bool IsConv : 1;
  377. // OpenCL extension(s) required for this overload.
  378. const unsigned short Extension;
  379. // OpenCL versions in which this overload is available.
  380. const unsigned short Versions;
  381. };
  382. )";
  383. }
  384. // Verify that the combination of GenTypes in a signature is supported.
  385. // To simplify the logic for creating overloads in SemaLookup, only allow
  386. // a signature to contain different GenTypes if these GenTypes represent
  387. // the same number of actual scalar or vector types.
  388. //
  389. // Exit with a fatal error if an unsupported construct is encountered.
  390. static void VerifySignature(const std::vector<Record *> &Signature,
  391. const Record *BuiltinRec) {
  392. unsigned GenTypeVecSizes = 1;
  393. unsigned GenTypeTypes = 1;
  394. for (const auto *T : Signature) {
  395. // Check all GenericType arguments in this signature.
  396. if (T->isSubClassOf("GenericType")) {
  397. // Check number of vector sizes.
  398. unsigned NVecSizes =
  399. T->getValueAsDef("VectorList")->getValueAsListOfInts("List").size();
  400. if (NVecSizes != GenTypeVecSizes && NVecSizes != 1) {
  401. if (GenTypeVecSizes > 1) {
  402. // We already saw a gentype with a different number of vector sizes.
  403. PrintFatalError(BuiltinRec->getLoc(),
  404. "number of vector sizes should be equal or 1 for all gentypes "
  405. "in a declaration");
  406. }
  407. GenTypeVecSizes = NVecSizes;
  408. }
  409. // Check number of data types.
  410. unsigned NTypes =
  411. T->getValueAsDef("TypeList")->getValueAsListOfDefs("List").size();
  412. if (NTypes != GenTypeTypes && NTypes != 1) {
  413. if (GenTypeTypes > 1) {
  414. // We already saw a gentype with a different number of types.
  415. PrintFatalError(BuiltinRec->getLoc(),
  416. "number of types should be equal or 1 for all gentypes "
  417. "in a declaration");
  418. }
  419. GenTypeTypes = NTypes;
  420. }
  421. }
  422. }
  423. }
  424. void BuiltinNameEmitter::GetOverloads() {
  425. // Populate the TypeMap.
  426. std::vector<Record *> Types = Records.getAllDerivedDefinitions("Type");
  427. unsigned I = 0;
  428. for (const auto &T : Types) {
  429. TypeMap.insert(std::make_pair(T, I++));
  430. }
  431. // Populate the SignaturesList and the FctOverloadMap.
  432. unsigned CumulativeSignIndex = 0;
  433. std::vector<Record *> Builtins = Records.getAllDerivedDefinitions("Builtin");
  434. for (const auto *B : Builtins) {
  435. StringRef BName = B->getValueAsString("Name");
  436. if (FctOverloadMap.find(BName) == FctOverloadMap.end()) {
  437. FctOverloadMap.insert(std::make_pair(
  438. BName, std::vector<std::pair<const Record *, unsigned>>{}));
  439. }
  440. auto Signature = B->getValueAsListOfDefs("Signature");
  441. // Reuse signatures to avoid unnecessary duplicates.
  442. auto it =
  443. llvm::find_if(SignaturesList,
  444. [&](const std::pair<std::vector<Record *>, unsigned> &a) {
  445. return a.first == Signature;
  446. });
  447. unsigned SignIndex;
  448. if (it == SignaturesList.end()) {
  449. VerifySignature(Signature, B);
  450. SignaturesList.push_back(std::make_pair(Signature, CumulativeSignIndex));
  451. SignIndex = CumulativeSignIndex;
  452. CumulativeSignIndex += Signature.size();
  453. } else {
  454. SignIndex = it->second;
  455. }
  456. FctOverloadMap[BName].push_back(std::make_pair(B, SignIndex));
  457. }
  458. }
  459. void BuiltinNameEmitter::EmitExtensionTable() {
  460. OS << "static const char *FunctionExtensionTable[] = {\n";
  461. unsigned Index = 0;
  462. std::vector<Record *> FuncExtensions =
  463. Records.getAllDerivedDefinitions("FunctionExtension");
  464. for (const auto &FE : FuncExtensions) {
  465. // Emit OpenCL extension table entry.
  466. OS << " // " << Index << ": " << FE->getName() << "\n"
  467. << " \"" << FE->getValueAsString("ExtName") << "\",\n";
  468. // Record index of this extension.
  469. FunctionExtensionIndex[FE->getName()] = Index++;
  470. }
  471. OS << "};\n\n";
  472. }
  473. void BuiltinNameEmitter::EmitTypeTable() {
  474. OS << "static const OpenCLTypeStruct TypeTable[] = {\n";
  475. for (const auto &T : TypeMap) {
  476. const char *AccessQual =
  477. StringSwitch<const char *>(T.first->getValueAsString("AccessQualifier"))
  478. .Case("RO", "OCLAQ_ReadOnly")
  479. .Case("WO", "OCLAQ_WriteOnly")
  480. .Case("RW", "OCLAQ_ReadWrite")
  481. .Default("OCLAQ_None");
  482. OS << " // " << T.second << "\n"
  483. << " {OCLT_" << T.first->getValueAsString("Name") << ", "
  484. << T.first->getValueAsInt("VecWidth") << ", "
  485. << T.first->getValueAsBit("IsPointer") << ", "
  486. << T.first->getValueAsBit("IsConst") << ", "
  487. << T.first->getValueAsBit("IsVolatile") << ", "
  488. << AccessQual << ", "
  489. << T.first->getValueAsString("AddrSpace") << "},\n";
  490. }
  491. OS << "};\n\n";
  492. }
  493. void BuiltinNameEmitter::EmitSignatureTable() {
  494. // Store a type (e.g. int, float, int2, ...). The type is stored as an index
  495. // of a struct OpenCLType table. Multiple entries following each other form a
  496. // signature.
  497. OS << "static const unsigned short SignatureTable[] = {\n";
  498. for (const auto &P : SignaturesList) {
  499. OS << " // " << P.second << "\n ";
  500. for (const Record *R : P.first) {
  501. unsigned Entry = TypeMap.find(R)->second;
  502. if (Entry > USHRT_MAX) {
  503. // Report an error when seeing an entry that is too large for the
  504. // current index type (unsigned short). When hitting this, the type
  505. // of SignatureTable will need to be changed.
  506. PrintFatalError("Entry in SignatureTable exceeds limit.");
  507. }
  508. OS << Entry << ", ";
  509. }
  510. OS << "\n";
  511. }
  512. OS << "};\n\n";
  513. }
  514. // Encode a range MinVersion..MaxVersion into a single bit mask that can be
  515. // checked against LangOpts using isOpenCLVersionContainedInMask().
  516. // This must be kept in sync with OpenCLVersionID in OpenCLOptions.h.
  517. // (Including OpenCLOptions.h here would be a layering violation.)
  518. static unsigned short EncodeVersions(unsigned int MinVersion,
  519. unsigned int MaxVersion) {
  520. unsigned short Encoded = 0;
  521. // A maximum version of 0 means available in all later versions.
  522. if (MaxVersion == 0) {
  523. MaxVersion = UINT_MAX;
  524. }
  525. unsigned VersionIDs[] = {100, 110, 120, 200, 300};
  526. for (unsigned I = 0; I < std::size(VersionIDs); I++) {
  527. if (VersionIDs[I] >= MinVersion && VersionIDs[I] < MaxVersion) {
  528. Encoded |= 1 << I;
  529. }
  530. }
  531. return Encoded;
  532. }
  533. void BuiltinNameEmitter::EmitBuiltinTable() {
  534. unsigned Index = 0;
  535. OS << "static const OpenCLBuiltinStruct BuiltinTable[] = {\n";
  536. for (const auto &SLM : SignatureListMap) {
  537. OS << " // " << (Index + 1) << ": ";
  538. for (const auto &Name : SLM.second.Names) {
  539. OS << Name << ", ";
  540. }
  541. OS << "\n";
  542. for (const auto &Overload : SLM.second.Signatures) {
  543. StringRef ExtName = Overload.first->getValueAsDef("Extension")->getName();
  544. unsigned int MinVersion =
  545. Overload.first->getValueAsDef("MinVersion")->getValueAsInt("ID");
  546. unsigned int MaxVersion =
  547. Overload.first->getValueAsDef("MaxVersion")->getValueAsInt("ID");
  548. OS << " { " << Overload.second << ", "
  549. << Overload.first->getValueAsListOfDefs("Signature").size() << ", "
  550. << (Overload.first->getValueAsBit("IsPure")) << ", "
  551. << (Overload.first->getValueAsBit("IsConst")) << ", "
  552. << (Overload.first->getValueAsBit("IsConv")) << ", "
  553. << FunctionExtensionIndex[ExtName] << ", "
  554. << EncodeVersions(MinVersion, MaxVersion) << " },\n";
  555. Index++;
  556. }
  557. }
  558. OS << "};\n\n";
  559. }
  560. bool BuiltinNameEmitter::CanReuseSignature(
  561. BuiltinIndexListTy *Candidate,
  562. std::vector<std::pair<const Record *, unsigned>> &SignatureList) {
  563. assert(Candidate->size() == SignatureList.size() &&
  564. "signature lists should have the same size");
  565. auto &CandidateSigs =
  566. SignatureListMap.find(Candidate)->second.Signatures;
  567. for (unsigned Index = 0; Index < Candidate->size(); Index++) {
  568. const Record *Rec = SignatureList[Index].first;
  569. const Record *Rec2 = CandidateSigs[Index].first;
  570. if (Rec->getValueAsBit("IsPure") == Rec2->getValueAsBit("IsPure") &&
  571. Rec->getValueAsBit("IsConst") == Rec2->getValueAsBit("IsConst") &&
  572. Rec->getValueAsBit("IsConv") == Rec2->getValueAsBit("IsConv") &&
  573. Rec->getValueAsDef("MinVersion")->getValueAsInt("ID") ==
  574. Rec2->getValueAsDef("MinVersion")->getValueAsInt("ID") &&
  575. Rec->getValueAsDef("MaxVersion")->getValueAsInt("ID") ==
  576. Rec2->getValueAsDef("MaxVersion")->getValueAsInt("ID") &&
  577. Rec->getValueAsDef("Extension")->getName() ==
  578. Rec2->getValueAsDef("Extension")->getName()) {
  579. return true;
  580. }
  581. }
  582. return false;
  583. }
  584. void BuiltinNameEmitter::GroupBySignature() {
  585. // List of signatures known to be emitted.
  586. std::vector<BuiltinIndexListTy *> KnownSignatures;
  587. for (auto &Fct : FctOverloadMap) {
  588. bool FoundReusableSig = false;
  589. // Gather all signatures for the current function.
  590. auto *CurSignatureList = new BuiltinIndexListTy();
  591. for (const auto &Signature : Fct.second) {
  592. CurSignatureList->push_back(Signature.second);
  593. }
  594. // Sort the list to facilitate future comparisons.
  595. llvm::sort(*CurSignatureList);
  596. // Check if we have already seen another function with the same list of
  597. // signatures. If so, just add the name of the function.
  598. for (auto *Candidate : KnownSignatures) {
  599. if (Candidate->size() == CurSignatureList->size() &&
  600. *Candidate == *CurSignatureList) {
  601. if (CanReuseSignature(Candidate, Fct.second)) {
  602. SignatureListMap.find(Candidate)->second.Names.push_back(Fct.first);
  603. FoundReusableSig = true;
  604. }
  605. }
  606. }
  607. if (FoundReusableSig) {
  608. delete CurSignatureList;
  609. } else {
  610. // Add a new entry.
  611. SignatureListMap[CurSignatureList] = {
  612. SmallVector<StringRef, 4>(1, Fct.first), Fct.second};
  613. KnownSignatures.push_back(CurSignatureList);
  614. }
  615. }
  616. for (auto *I : KnownSignatures) {
  617. delete I;
  618. }
  619. }
  620. void BuiltinNameEmitter::EmitStringMatcher() {
  621. std::vector<StringMatcher::StringPair> ValidBuiltins;
  622. unsigned CumulativeIndex = 1;
  623. for (const auto &SLM : SignatureListMap) {
  624. const auto &Ovl = SLM.second.Signatures;
  625. // A single signature list may be used by different builtins. Return the
  626. // same <index, length> pair for each of those builtins.
  627. for (const auto &FctName : SLM.second.Names) {
  628. std::string RetStmt;
  629. raw_string_ostream SS(RetStmt);
  630. SS << "return std::make_pair(" << CumulativeIndex << ", " << Ovl.size()
  631. << ");";
  632. SS.flush();
  633. ValidBuiltins.push_back(
  634. StringMatcher::StringPair(std::string(FctName), RetStmt));
  635. }
  636. CumulativeIndex += Ovl.size();
  637. }
  638. OS << R"(
  639. // Find out whether a string matches an existing OpenCL builtin function name.
  640. // Returns: A pair <0, 0> if no name matches.
  641. // A pair <Index, Len> indexing the BuiltinTable if the name is
  642. // matching an OpenCL builtin function.
  643. static std::pair<unsigned, unsigned> isOpenCLBuiltin(llvm::StringRef Name) {
  644. )";
  645. StringMatcher("Name", ValidBuiltins, OS).Emit(0, true);
  646. OS << " return std::make_pair(0, 0);\n";
  647. OS << "} // isOpenCLBuiltin\n";
  648. }
  649. // Emit an if-statement with an isMacroDefined call for each extension in
  650. // the space-separated list of extensions.
  651. static void EmitMacroChecks(raw_ostream &OS, StringRef Extensions) {
  652. SmallVector<StringRef, 2> ExtVec;
  653. Extensions.split(ExtVec, " ");
  654. OS << " if (";
  655. for (StringRef Ext : ExtVec) {
  656. if (Ext != ExtVec.front())
  657. OS << " && ";
  658. OS << "S.getPreprocessor().isMacroDefined(\"" << Ext << "\")";
  659. }
  660. OS << ") {\n ";
  661. }
  662. void BuiltinNameEmitter::EmitQualTypeFinder() {
  663. OS << R"(
  664. static QualType getOpenCLEnumType(Sema &S, llvm::StringRef Name);
  665. static QualType getOpenCLTypedefType(Sema &S, llvm::StringRef Name);
  666. // Convert an OpenCLTypeStruct type to a list of QualTypes.
  667. // Generic types represent multiple types and vector sizes, thus a vector
  668. // is returned. The conversion is done in two steps:
  669. // Step 1: A switch statement fills a vector with scalar base types for the
  670. // Cartesian product of (vector sizes) x (types) for generic types,
  671. // or a single scalar type for non generic types.
  672. // Step 2: Qualifiers and other type properties such as vector size are
  673. // applied.
  674. static void OCL2Qual(Sema &S, const OpenCLTypeStruct &Ty,
  675. llvm::SmallVectorImpl<QualType> &QT) {
  676. ASTContext &Context = S.Context;
  677. // Number of scalar types in the GenType.
  678. unsigned GenTypeNumTypes;
  679. // Pointer to the list of vector sizes for the GenType.
  680. llvm::ArrayRef<unsigned> GenVectorSizes;
  681. )";
  682. // Generate list of vector sizes for each generic type.
  683. for (const auto *VectList : Records.getAllDerivedDefinitions("IntList")) {
  684. OS << " constexpr unsigned List"
  685. << VectList->getValueAsString("Name") << "[] = {";
  686. for (const auto V : VectList->getValueAsListOfInts("List")) {
  687. OS << V << ", ";
  688. }
  689. OS << "};\n";
  690. }
  691. // Step 1.
  692. // Start of switch statement over all types.
  693. OS << "\n switch (Ty.ID) {\n";
  694. // Switch cases for image types (Image2d, Image3d, ...)
  695. std::vector<Record *> ImageTypes =
  696. Records.getAllDerivedDefinitions("ImageType");
  697. // Map an image type name to its 3 access-qualified types (RO, WO, RW).
  698. StringMap<SmallVector<Record *, 3>> ImageTypesMap;
  699. for (auto *IT : ImageTypes) {
  700. auto Entry = ImageTypesMap.find(IT->getValueAsString("Name"));
  701. if (Entry == ImageTypesMap.end()) {
  702. SmallVector<Record *, 3> ImageList;
  703. ImageList.push_back(IT);
  704. ImageTypesMap.insert(
  705. std::make_pair(IT->getValueAsString("Name"), ImageList));
  706. } else {
  707. Entry->second.push_back(IT);
  708. }
  709. }
  710. // Emit the cases for the image types. For an image type name, there are 3
  711. // corresponding QualTypes ("RO", "WO", "RW"). The "AccessQualifier" field
  712. // tells which one is needed. Emit a switch statement that puts the
  713. // corresponding QualType into "QT".
  714. for (const auto &ITE : ImageTypesMap) {
  715. OS << " case OCLT_" << ITE.getKey() << ":\n"
  716. << " switch (Ty.AccessQualifier) {\n"
  717. << " case OCLAQ_None:\n"
  718. << " llvm_unreachable(\"Image without access qualifier\");\n";
  719. for (const auto &Image : ITE.getValue()) {
  720. StringRef Exts =
  721. Image->getValueAsDef("Extension")->getValueAsString("ExtName");
  722. OS << StringSwitch<const char *>(
  723. Image->getValueAsString("AccessQualifier"))
  724. .Case("RO", " case OCLAQ_ReadOnly:\n")
  725. .Case("WO", " case OCLAQ_WriteOnly:\n")
  726. .Case("RW", " case OCLAQ_ReadWrite:\n");
  727. if (!Exts.empty()) {
  728. OS << " ";
  729. EmitMacroChecks(OS, Exts);
  730. }
  731. OS << " QT.push_back("
  732. << Image->getValueAsDef("QTExpr")->getValueAsString("TypeExpr")
  733. << ");\n";
  734. if (!Exts.empty()) {
  735. OS << " }\n";
  736. }
  737. OS << " break;\n";
  738. }
  739. OS << " }\n"
  740. << " break;\n";
  741. }
  742. // Switch cases for generic types.
  743. for (const auto *GenType : Records.getAllDerivedDefinitions("GenericType")) {
  744. OS << " case OCLT_" << GenType->getValueAsString("Name") << ": {\n";
  745. // Build the Cartesian product of (vector sizes) x (types). Only insert
  746. // the plain scalar types for now; other type information such as vector
  747. // size and type qualifiers will be added after the switch statement.
  748. std::vector<Record *> BaseTypes =
  749. GenType->getValueAsDef("TypeList")->getValueAsListOfDefs("List");
  750. // Collect all QualTypes for a single vector size into TypeList.
  751. OS << " SmallVector<QualType, " << BaseTypes.size() << "> TypeList;\n";
  752. for (const auto *T : BaseTypes) {
  753. StringRef Exts =
  754. T->getValueAsDef("Extension")->getValueAsString("ExtName");
  755. if (!Exts.empty()) {
  756. EmitMacroChecks(OS, Exts);
  757. }
  758. OS << " TypeList.push_back("
  759. << T->getValueAsDef("QTExpr")->getValueAsString("TypeExpr") << ");\n";
  760. if (!Exts.empty()) {
  761. OS << " }\n";
  762. }
  763. }
  764. OS << " GenTypeNumTypes = TypeList.size();\n";
  765. // Duplicate the TypeList for every vector size.
  766. std::vector<int64_t> VectorList =
  767. GenType->getValueAsDef("VectorList")->getValueAsListOfInts("List");
  768. OS << " QT.reserve(" << VectorList.size() * BaseTypes.size() << ");\n"
  769. << " for (unsigned I = 0; I < " << VectorList.size() << "; I++) {\n"
  770. << " QT.append(TypeList);\n"
  771. << " }\n";
  772. // GenVectorSizes is the list of vector sizes for this GenType.
  773. OS << " GenVectorSizes = List"
  774. << GenType->getValueAsDef("VectorList")->getValueAsString("Name")
  775. << ";\n"
  776. << " break;\n"
  777. << " }\n";
  778. }
  779. // Switch cases for non generic, non image types (int, int4, float, ...).
  780. // Only insert the plain scalar type; vector information and type qualifiers
  781. // are added in step 2.
  782. std::vector<Record *> Types = Records.getAllDerivedDefinitions("Type");
  783. StringMap<bool> TypesSeen;
  784. for (const auto *T : Types) {
  785. // Check this is not an image type
  786. if (ImageTypesMap.find(T->getValueAsString("Name")) != ImageTypesMap.end())
  787. continue;
  788. // Check we have not seen this Type
  789. if (TypesSeen.find(T->getValueAsString("Name")) != TypesSeen.end())
  790. continue;
  791. TypesSeen.insert(std::make_pair(T->getValueAsString("Name"), true));
  792. // Check the Type does not have an "abstract" QualType
  793. auto QT = T->getValueAsDef("QTExpr");
  794. if (QT->getValueAsBit("IsAbstract") == 1)
  795. continue;
  796. // Emit the cases for non generic, non image types.
  797. OS << " case OCLT_" << T->getValueAsString("Name") << ":\n";
  798. StringRef Exts = T->getValueAsDef("Extension")->getValueAsString("ExtName");
  799. // If this type depends on an extension, ensure the extension macros are
  800. // defined.
  801. if (!Exts.empty()) {
  802. EmitMacroChecks(OS, Exts);
  803. }
  804. OS << " QT.push_back(" << QT->getValueAsString("TypeExpr") << ");\n";
  805. if (!Exts.empty()) {
  806. OS << " }\n";
  807. }
  808. OS << " break;\n";
  809. }
  810. // End of switch statement.
  811. OS << " } // end of switch (Ty.ID)\n\n";
  812. // Step 2.
  813. // Add ExtVector types if this was a generic type, as the switch statement
  814. // above only populated the list with scalar types. This completes the
  815. // construction of the Cartesian product of (vector sizes) x (types).
  816. OS << " // Construct the different vector types for each generic type.\n";
  817. OS << " if (Ty.ID >= " << TypeList.size() << ") {";
  818. OS << R"(
  819. for (unsigned I = 0; I < QT.size(); I++) {
  820. // For scalars, size is 1.
  821. if (GenVectorSizes[I / GenTypeNumTypes] != 1) {
  822. QT[I] = Context.getExtVectorType(QT[I],
  823. GenVectorSizes[I / GenTypeNumTypes]);
  824. }
  825. }
  826. }
  827. )";
  828. // Assign the right attributes to the types (e.g. vector size).
  829. OS << R"(
  830. // Set vector size for non-generic vector types.
  831. if (Ty.VectorWidth > 1) {
  832. for (unsigned Index = 0; Index < QT.size(); Index++) {
  833. QT[Index] = Context.getExtVectorType(QT[Index], Ty.VectorWidth);
  834. }
  835. }
  836. if (Ty.IsVolatile != 0) {
  837. for (unsigned Index = 0; Index < QT.size(); Index++) {
  838. QT[Index] = Context.getVolatileType(QT[Index]);
  839. }
  840. }
  841. if (Ty.IsConst != 0) {
  842. for (unsigned Index = 0; Index < QT.size(); Index++) {
  843. QT[Index] = Context.getConstType(QT[Index]);
  844. }
  845. }
  846. // Transform the type to a pointer as the last step, if necessary.
  847. // Builtin functions only have pointers on [const|volatile], no
  848. // [const|volatile] pointers, so this is ok to do it as a last step.
  849. if (Ty.IsPointer != 0) {
  850. for (unsigned Index = 0; Index < QT.size(); Index++) {
  851. QT[Index] = Context.getAddrSpaceQualType(QT[Index], Ty.AS);
  852. QT[Index] = Context.getPointerType(QT[Index]);
  853. }
  854. }
  855. )";
  856. // End of the "OCL2Qual" function.
  857. OS << "\n} // OCL2Qual\n";
  858. }
  859. std::string OpenCLBuiltinFileEmitterBase::getTypeString(const Record *Type,
  860. TypeFlags Flags,
  861. int VectorSize) const {
  862. std::string S;
  863. if (Type->getValueAsBit("IsConst") || Flags.IsConst) {
  864. S += "const ";
  865. }
  866. if (Type->getValueAsBit("IsVolatile") || Flags.IsVolatile) {
  867. S += "volatile ";
  868. }
  869. auto PrintAddrSpace = [&S](StringRef AddrSpace) {
  870. S += StringSwitch<const char *>(AddrSpace)
  871. .Case("clang::LangAS::opencl_private", "__private")
  872. .Case("clang::LangAS::opencl_global", "__global")
  873. .Case("clang::LangAS::opencl_constant", "__constant")
  874. .Case("clang::LangAS::opencl_local", "__local")
  875. .Case("clang::LangAS::opencl_generic", "__generic")
  876. .Default("__private");
  877. S += " ";
  878. };
  879. if (Flags.IsPointer) {
  880. PrintAddrSpace(Flags.AddrSpace);
  881. } else if (Type->getValueAsBit("IsPointer")) {
  882. PrintAddrSpace(Type->getValueAsString("AddrSpace"));
  883. }
  884. StringRef Acc = Type->getValueAsString("AccessQualifier");
  885. if (Acc != "") {
  886. S += StringSwitch<const char *>(Acc)
  887. .Case("RO", "__read_only ")
  888. .Case("WO", "__write_only ")
  889. .Case("RW", "__read_write ");
  890. }
  891. S += Type->getValueAsString("Name").str();
  892. if (VectorSize > 1) {
  893. S += std::to_string(VectorSize);
  894. }
  895. if (Type->getValueAsBit("IsPointer") || Flags.IsPointer) {
  896. S += " *";
  897. }
  898. return S;
  899. }
  900. void OpenCLBuiltinFileEmitterBase::getTypeLists(
  901. Record *Type, TypeFlags &Flags, std::vector<Record *> &TypeList,
  902. std::vector<int64_t> &VectorList) const {
  903. bool isGenType = Type->isSubClassOf("GenericType");
  904. if (isGenType) {
  905. TypeList = Type->getValueAsDef("TypeList")->getValueAsListOfDefs("List");
  906. VectorList =
  907. Type->getValueAsDef("VectorList")->getValueAsListOfInts("List");
  908. return;
  909. }
  910. if (Type->isSubClassOf("PointerType") || Type->isSubClassOf("ConstType") ||
  911. Type->isSubClassOf("VolatileType")) {
  912. StringRef SubTypeName = Type->getValueAsString("Name");
  913. Record *PossibleGenType = Records.getDef(SubTypeName);
  914. if (PossibleGenType && PossibleGenType->isSubClassOf("GenericType")) {
  915. // When PointerType, ConstType, or VolatileType is applied to a
  916. // GenericType, the flags need to be taken from the subtype, not from the
  917. // GenericType.
  918. Flags.IsPointer = Type->getValueAsBit("IsPointer");
  919. Flags.IsConst = Type->getValueAsBit("IsConst");
  920. Flags.IsVolatile = Type->getValueAsBit("IsVolatile");
  921. Flags.AddrSpace = Type->getValueAsString("AddrSpace");
  922. getTypeLists(PossibleGenType, Flags, TypeList, VectorList);
  923. return;
  924. }
  925. }
  926. // Not a GenericType, so just insert the single type.
  927. TypeList.push_back(Type);
  928. VectorList.push_back(Type->getValueAsInt("VecWidth"));
  929. }
  930. void OpenCLBuiltinFileEmitterBase::expandTypesInSignature(
  931. const std::vector<Record *> &Signature,
  932. SmallVectorImpl<SmallVector<std::string, 2>> &Types) {
  933. // Find out if there are any GenTypes in this signature, and if so, calculate
  934. // into how many signatures they will expand.
  935. unsigned NumSignatures = 1;
  936. SmallVector<SmallVector<std::string, 4>, 4> ExpandedGenTypes;
  937. for (const auto &Arg : Signature) {
  938. SmallVector<std::string, 4> ExpandedArg;
  939. std::vector<Record *> TypeList;
  940. std::vector<int64_t> VectorList;
  941. TypeFlags Flags;
  942. getTypeLists(Arg, Flags, TypeList, VectorList);
  943. // Insert the Cartesian product of the types and vector sizes.
  944. for (const auto &Vector : VectorList) {
  945. for (const auto &Type : TypeList) {
  946. std::string FullType = getTypeString(Type, Flags, Vector);
  947. ExpandedArg.push_back(FullType);
  948. // If the type requires an extension, add a TypeExtMap entry mapping
  949. // the full type name to the extension.
  950. StringRef Ext =
  951. Type->getValueAsDef("Extension")->getValueAsString("ExtName");
  952. if (!Ext.empty() && TypeExtMap.find(FullType) == TypeExtMap.end()) {
  953. TypeExtMap.insert({FullType, Ext});
  954. }
  955. }
  956. }
  957. NumSignatures = std::max<unsigned>(NumSignatures, ExpandedArg.size());
  958. ExpandedGenTypes.push_back(ExpandedArg);
  959. }
  960. // Now the total number of signatures is known. Populate the return list with
  961. // all signatures.
  962. for (unsigned I = 0; I < NumSignatures; I++) {
  963. SmallVector<std::string, 2> Args;
  964. // Process a single signature.
  965. for (unsigned ArgNum = 0; ArgNum < Signature.size(); ArgNum++) {
  966. // For differently-sized GenTypes in a parameter list, the smaller
  967. // GenTypes just repeat, so index modulo the number of expanded types.
  968. size_t TypeIndex = I % ExpandedGenTypes[ArgNum].size();
  969. Args.push_back(ExpandedGenTypes[ArgNum][TypeIndex]);
  970. }
  971. Types.push_back(Args);
  972. }
  973. }
  974. void OpenCLBuiltinFileEmitterBase::emitExtensionSetup() {
  975. OS << R"(
  976. #pragma OPENCL EXTENSION cl_khr_fp16 : enable
  977. #pragma OPENCL EXTENSION cl_khr_fp64 : enable
  978. #pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable
  979. #pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : enable
  980. #pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable
  981. #pragma OPENCL EXTENSION cl_khr_mipmap_image_writes : enable
  982. #pragma OPENCL EXTENSION cl_khr_3d_image_writes : enable
  983. )";
  984. }
  985. std::string
  986. OpenCLBuiltinFileEmitterBase::emitExtensionGuard(const Record *Builtin) {
  987. StringRef Extensions =
  988. Builtin->getValueAsDef("Extension")->getValueAsString("ExtName");
  989. if (Extensions.empty())
  990. return "";
  991. OS << "#if";
  992. SmallVector<StringRef, 2> ExtVec;
  993. Extensions.split(ExtVec, " ");
  994. bool isFirst = true;
  995. for (StringRef Ext : ExtVec) {
  996. if (!isFirst) {
  997. OS << " &&";
  998. }
  999. OS << " defined(" << Ext << ")";
  1000. isFirst = false;
  1001. }
  1002. OS << "\n";
  1003. return "#endif // Extension\n";
  1004. }
  1005. std::string
  1006. OpenCLBuiltinFileEmitterBase::emitVersionGuard(const Record *Builtin) {
  1007. std::string OptionalEndif;
  1008. auto PrintOpenCLVersion = [this](int Version) {
  1009. OS << "CL_VERSION_" << (Version / 100) << "_" << ((Version % 100) / 10);
  1010. };
  1011. int MinVersion = Builtin->getValueAsDef("MinVersion")->getValueAsInt("ID");
  1012. if (MinVersion != 100) {
  1013. // OpenCL 1.0 is the default minimum version.
  1014. OS << "#if __OPENCL_C_VERSION__ >= ";
  1015. PrintOpenCLVersion(MinVersion);
  1016. OS << "\n";
  1017. OptionalEndif = "#endif // MinVersion\n" + OptionalEndif;
  1018. }
  1019. int MaxVersion = Builtin->getValueAsDef("MaxVersion")->getValueAsInt("ID");
  1020. if (MaxVersion) {
  1021. OS << "#if __OPENCL_C_VERSION__ < ";
  1022. PrintOpenCLVersion(MaxVersion);
  1023. OS << "\n";
  1024. OptionalEndif = "#endif // MaxVersion\n" + OptionalEndif;
  1025. }
  1026. return OptionalEndif;
  1027. }
  1028. StringRef OpenCLBuiltinFileEmitterBase::emitTypeExtensionGuards(
  1029. const SmallVectorImpl<std::string> &Signature) {
  1030. SmallSet<StringRef, 2> ExtSet;
  1031. // Iterate over all types to gather the set of required TypeExtensions.
  1032. for (const auto &Ty : Signature) {
  1033. StringRef TypeExt = TypeExtMap.lookup(Ty);
  1034. if (!TypeExt.empty()) {
  1035. // The TypeExtensions are space-separated in the .td file.
  1036. SmallVector<StringRef, 2> ExtVec;
  1037. TypeExt.split(ExtVec, " ");
  1038. for (const auto Ext : ExtVec) {
  1039. ExtSet.insert(Ext);
  1040. }
  1041. }
  1042. }
  1043. // Emit the #if only when at least one extension is required.
  1044. if (ExtSet.empty())
  1045. return "";
  1046. OS << "#if ";
  1047. bool isFirst = true;
  1048. for (const auto Ext : ExtSet) {
  1049. if (!isFirst)
  1050. OS << " && ";
  1051. OS << "defined(" << Ext << ")";
  1052. isFirst = false;
  1053. }
  1054. OS << "\n";
  1055. return "#endif // TypeExtension\n";
  1056. }
  1057. void OpenCLBuiltinTestEmitter::emit() {
  1058. emitSourceFileHeader("OpenCL Builtin exhaustive testing", OS);
  1059. emitExtensionSetup();
  1060. // Ensure each test has a unique name by numbering them.
  1061. unsigned TestID = 0;
  1062. // Iterate over all builtins.
  1063. std::vector<Record *> Builtins = Records.getAllDerivedDefinitions("Builtin");
  1064. for (const auto *B : Builtins) {
  1065. StringRef Name = B->getValueAsString("Name");
  1066. SmallVector<SmallVector<std::string, 2>, 4> FTypes;
  1067. expandTypesInSignature(B->getValueAsListOfDefs("Signature"), FTypes);
  1068. OS << "// Test " << Name << "\n";
  1069. std::string OptionalExtensionEndif = emitExtensionGuard(B);
  1070. std::string OptionalVersionEndif = emitVersionGuard(B);
  1071. for (const auto &Signature : FTypes) {
  1072. StringRef OptionalTypeExtEndif = emitTypeExtensionGuards(Signature);
  1073. // Emit function declaration.
  1074. OS << Signature[0] << " test" << TestID++ << "_" << Name << "(";
  1075. if (Signature.size() > 1) {
  1076. for (unsigned I = 1; I < Signature.size(); I++) {
  1077. if (I != 1)
  1078. OS << ", ";
  1079. OS << Signature[I] << " arg" << I;
  1080. }
  1081. }
  1082. OS << ") {\n";
  1083. // Emit function body.
  1084. OS << " ";
  1085. if (Signature[0] != "void") {
  1086. OS << "return ";
  1087. }
  1088. OS << Name << "(";
  1089. for (unsigned I = 1; I < Signature.size(); I++) {
  1090. if (I != 1)
  1091. OS << ", ";
  1092. OS << "arg" << I;
  1093. }
  1094. OS << ");\n";
  1095. // End of function body.
  1096. OS << "}\n";
  1097. OS << OptionalTypeExtEndif;
  1098. }
  1099. OS << OptionalVersionEndif;
  1100. OS << OptionalExtensionEndif;
  1101. }
  1102. }
  1103. void clang::EmitClangOpenCLBuiltins(RecordKeeper &Records, raw_ostream &OS) {
  1104. BuiltinNameEmitter NameChecker(Records, OS);
  1105. NameChecker.Emit();
  1106. }
  1107. void clang::EmitClangOpenCLBuiltinTests(RecordKeeper &Records,
  1108. raw_ostream &OS) {
  1109. OpenCLBuiltinTestEmitter TestFileGenerator(Records, OS);
  1110. TestFileGenerator.emit();
  1111. }