1b2a28edaSopenharmony_ci// Copyright (c) 2014-2020 The Khronos Group Inc. 2b2a28edaSopenharmony_ci// 3b2a28edaSopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a copy 4b2a28edaSopenharmony_ci// of this software and/or associated documentation files (the "Materials"), 5b2a28edaSopenharmony_ci// to deal in the Materials without restriction, including without limitation 6b2a28edaSopenharmony_ci// the rights to use, copy, modify, merge, publish, distribute, sublicense, 7b2a28edaSopenharmony_ci// and/or sell copies of the Materials, and to permit persons to whom the 8b2a28edaSopenharmony_ci// Materials are furnished to do so, subject to the following conditions: 9b2a28edaSopenharmony_ci// 10b2a28edaSopenharmony_ci// The above copyright notice and this permission notice shall be included in 11b2a28edaSopenharmony_ci// all copies or substantial portions of the Materials. 12b2a28edaSopenharmony_ci// 13b2a28edaSopenharmony_ci// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS 14b2a28edaSopenharmony_ci// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND 15b2a28edaSopenharmony_ci// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ 16b2a28edaSopenharmony_ci// 17b2a28edaSopenharmony_ci// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18b2a28edaSopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19b2a28edaSopenharmony_ci// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20b2a28edaSopenharmony_ci// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21b2a28edaSopenharmony_ci// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22b2a28edaSopenharmony_ci// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS 23b2a28edaSopenharmony_ci// IN THE MATERIALS. 24b2a28edaSopenharmony_ci 25b2a28edaSopenharmony_ci// 26b2a28edaSopenharmony_ci// Print headers for SPIR-V in several languages. 27b2a28edaSopenharmony_ci// 28b2a28edaSopenharmony_ci// To change the header information, change the C++-built database in doc.*. 29b2a28edaSopenharmony_ci// 30b2a28edaSopenharmony_ci// Then, use "spriv -h <language>" - e.g, spriv.{h,hpp,lua,py,etc}: 31b2a28edaSopenharmony_ci// replace the auto-generated header, or "spirv -H" to generate all 32b2a28edaSopenharmony_ci// supported language headers to predefined names in the current directory. 33b2a28edaSopenharmony_ci// 34b2a28edaSopenharmony_ci 35b2a28edaSopenharmony_ci#include <string> 36b2a28edaSopenharmony_ci#include <sstream> 37b2a28edaSopenharmony_ci#include <fstream> 38b2a28edaSopenharmony_ci#include <cstring> 39b2a28edaSopenharmony_ci#include <cstdio> 40b2a28edaSopenharmony_ci#include <algorithm> 41b2a28edaSopenharmony_ci#include <memory> 42b2a28edaSopenharmony_ci#include <cctype> 43b2a28edaSopenharmony_ci#include <vector> 44b2a28edaSopenharmony_ci#include <utility> 45b2a28edaSopenharmony_ci#include <set> 46b2a28edaSopenharmony_ci 47b2a28edaSopenharmony_ci#include "jsoncpp/dist/json/json.h" 48b2a28edaSopenharmony_ci 49b2a28edaSopenharmony_ci#include "header.h" 50b2a28edaSopenharmony_ci#include "jsonToSpirv.h" 51b2a28edaSopenharmony_ci 52b2a28edaSopenharmony_ci// snprintf and _snprintf are not quite the same, but close enough 53b2a28edaSopenharmony_ci// for our use. 54b2a28edaSopenharmony_ci#ifdef _MSC_VER 55b2a28edaSopenharmony_ci#pragma warning(disable:4996) 56b2a28edaSopenharmony_ci#define snprintf _snprintf 57b2a28edaSopenharmony_ci#endif 58b2a28edaSopenharmony_ci 59b2a28edaSopenharmony_ci// This file converts SPIR-V definitions to an internal JSON 60b2a28edaSopenharmony_ci// representation, and then generates language specific 61b2a28edaSopenharmony_ci// data from that single internal form. 62b2a28edaSopenharmony_ci 63b2a28edaSopenharmony_ci// Initially, the internal form is created from C++ data, 64b2a28edaSopenharmony_ci// though this can be changed to a JSON master in time. 65b2a28edaSopenharmony_ci 66b2a28edaSopenharmony_cinamespace { 67b2a28edaSopenharmony_ci class TPrinter { 68b2a28edaSopenharmony_ci protected: 69b2a28edaSopenharmony_ci TPrinter(); 70b2a28edaSopenharmony_ci 71b2a28edaSopenharmony_ci static const int DocMagicNumber = 0x07230203; 72b2a28edaSopenharmony_ci static const int DocVersion = 0x00010600; 73b2a28edaSopenharmony_ci static const int DocRevision = 1; 74b2a28edaSopenharmony_ci #define DocRevisionString "1" 75b2a28edaSopenharmony_ci static const std::string DocCopyright; 76b2a28edaSopenharmony_ci static const std::string DocComment1; 77b2a28edaSopenharmony_ci static const std::string DocComment2; 78b2a28edaSopenharmony_ci 79b2a28edaSopenharmony_ci enum enumStyle_t { 80b2a28edaSopenharmony_ci enumNoMask, 81b2a28edaSopenharmony_ci enumCount, 82b2a28edaSopenharmony_ci enumShift, 83b2a28edaSopenharmony_ci enumMask, 84b2a28edaSopenharmony_ci enumHex, 85b2a28edaSopenharmony_ci }; 86b2a28edaSopenharmony_ci 87b2a28edaSopenharmony_ci static std::string styleStr(enumStyle_t s) { 88b2a28edaSopenharmony_ci return s == enumShift ? "Shift" : 89b2a28edaSopenharmony_ci s == enumMask ? "Mask" : ""; 90b2a28edaSopenharmony_ci } 91b2a28edaSopenharmony_ci 92b2a28edaSopenharmony_ci friend std::ostream& operator<<(std::ostream&, const TPrinter&); 93b2a28edaSopenharmony_ci 94b2a28edaSopenharmony_ci virtual void printAll(std::ostream&) const; 95b2a28edaSopenharmony_ci virtual void printComments(std::ostream&) const; 96b2a28edaSopenharmony_ci virtual void printPrologue(std::ostream&) const { } 97b2a28edaSopenharmony_ci virtual void printDefs(std::ostream&) const; 98b2a28edaSopenharmony_ci virtual void printEpilogue(std::ostream&) const { } 99b2a28edaSopenharmony_ci virtual void printMeta(std::ostream&) const; 100b2a28edaSopenharmony_ci virtual void printTypes(std::ostream&) const { } 101b2a28edaSopenharmony_ci virtual void printHasResultType(std::ostream&) const { }; 102b2a28edaSopenharmony_ci 103b2a28edaSopenharmony_ci virtual std::string escapeComment(const std::string& s) const; 104b2a28edaSopenharmony_ci 105b2a28edaSopenharmony_ci // Default printComments() uses these comment strings 106b2a28edaSopenharmony_ci virtual std::string commentBeg() const { return ""; } 107b2a28edaSopenharmony_ci virtual std::string commentEnd(bool isLast) const { return ""; } 108b2a28edaSopenharmony_ci virtual std::string commentBOL() const { return ""; } 109b2a28edaSopenharmony_ci virtual std::string commentEOL(bool isLast) const { return ""; } 110b2a28edaSopenharmony_ci 111b2a28edaSopenharmony_ci typedef std::pair<unsigned, std::string> valpair_t; 112b2a28edaSopenharmony_ci 113b2a28edaSopenharmony_ci // for printing enum values 114b2a28edaSopenharmony_ci virtual std::string enumBeg(const std::string&, enumStyle_t) const { return ""; } 115b2a28edaSopenharmony_ci virtual std::string enumEnd(const std::string&, enumStyle_t, bool isLast = false) const { 116b2a28edaSopenharmony_ci return ""; 117b2a28edaSopenharmony_ci } 118b2a28edaSopenharmony_ci virtual std::string enumFmt(const std::string&, const valpair_t&, 119b2a28edaSopenharmony_ci enumStyle_t, bool isLast = false) const { 120b2a28edaSopenharmony_ci return ""; 121b2a28edaSopenharmony_ci } 122b2a28edaSopenharmony_ci virtual std::string maxEnumFmt(const std::string&, const valpair_t&, 123b2a28edaSopenharmony_ci enumStyle_t) const { 124b2a28edaSopenharmony_ci return ""; 125b2a28edaSopenharmony_ci } 126b2a28edaSopenharmony_ci 127b2a28edaSopenharmony_ci virtual std::string fmtConstInt(unsigned val, const std::string& name, 128b2a28edaSopenharmony_ci const char* fmt, bool isLast = false) const { 129b2a28edaSopenharmony_ci return ""; 130b2a28edaSopenharmony_ci } 131b2a28edaSopenharmony_ci 132b2a28edaSopenharmony_ci std::vector<valpair_t> getSortedVals(const Json::Value&) const; 133b2a28edaSopenharmony_ci 134b2a28edaSopenharmony_ci virtual std::string indent(int count = 1) const { 135b2a28edaSopenharmony_ci return std::string(count * 4, ' '); // default indent level = 4 136b2a28edaSopenharmony_ci } 137b2a28edaSopenharmony_ci 138b2a28edaSopenharmony_ci static std::string fmtNum(const char* fmt, unsigned val) { 139b2a28edaSopenharmony_ci char buff[16]; // ample for 8 hex digits + 0x 140b2a28edaSopenharmony_ci snprintf(buff, sizeof(buff), fmt, val); 141b2a28edaSopenharmony_ci buff[sizeof(buff)-1] = '\0'; // MSVC doesn't promise null termination 142b2a28edaSopenharmony_ci return buff; 143b2a28edaSopenharmony_ci } 144b2a28edaSopenharmony_ci 145b2a28edaSopenharmony_ci static std::string fmtStyleVal(unsigned v, enumStyle_t style); 146b2a28edaSopenharmony_ci 147b2a28edaSopenharmony_ci // If the enum value name would start with a sigit, prepend the enum name. 148b2a28edaSopenharmony_ci // E.g, "3D" -> "Dim3D". 149b2a28edaSopenharmony_ci static std::string prependIfDigit(const std::string& ename, const std::string& vname) { 150b2a28edaSopenharmony_ci return (std::isdigit(vname[0]) ? ename : std::string("")) + vname; 151b2a28edaSopenharmony_ci } 152b2a28edaSopenharmony_ci 153b2a28edaSopenharmony_ci void addComment(Json::Value& node, const std::string& str); 154b2a28edaSopenharmony_ci 155b2a28edaSopenharmony_ci Json::Value spvRoot; // JSON SPIR-V data 156b2a28edaSopenharmony_ci }; 157b2a28edaSopenharmony_ci 158b2a28edaSopenharmony_ci // Format value as mask or value 159b2a28edaSopenharmony_ci std::string TPrinter::fmtStyleVal(unsigned v, enumStyle_t style) 160b2a28edaSopenharmony_ci { 161b2a28edaSopenharmony_ci switch (style) { 162b2a28edaSopenharmony_ci case enumMask: 163b2a28edaSopenharmony_ci return fmtNum("0x%08x", 1<<v); 164b2a28edaSopenharmony_ci case enumHex: 165b2a28edaSopenharmony_ci return fmtNum("0x%08x", v); 166b2a28edaSopenharmony_ci default: 167b2a28edaSopenharmony_ci return std::to_string(v); 168b2a28edaSopenharmony_ci } 169b2a28edaSopenharmony_ci } 170b2a28edaSopenharmony_ci 171b2a28edaSopenharmony_ci const std::string TPrinter::DocCopyright = 172b2a28edaSopenharmony_ci "Copyright (c) 2014-2020 The Khronos Group Inc.\n" 173b2a28edaSopenharmony_ci "\n" 174b2a28edaSopenharmony_ci "Permission is hereby granted, free of charge, to any person obtaining a copy\n" 175b2a28edaSopenharmony_ci "of this software and/or associated documentation files (the \"Materials\"),\n" 176b2a28edaSopenharmony_ci "to deal in the Materials without restriction, including without limitation\n" 177b2a28edaSopenharmony_ci "the rights to use, copy, modify, merge, publish, distribute, sublicense,\n" 178b2a28edaSopenharmony_ci "and/or sell copies of the Materials, and to permit persons to whom the\n" 179b2a28edaSopenharmony_ci "Materials are furnished to do so, subject to the following conditions:\n" 180b2a28edaSopenharmony_ci "\n" 181b2a28edaSopenharmony_ci "The above copyright notice and this permission notice shall be included in\n" 182b2a28edaSopenharmony_ci "all copies or substantial portions of the Materials.\n" 183b2a28edaSopenharmony_ci "\n" 184b2a28edaSopenharmony_ci "MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS\n" 185b2a28edaSopenharmony_ci "STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND\n" 186b2a28edaSopenharmony_ci "HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ \n" 187b2a28edaSopenharmony_ci "\n" 188b2a28edaSopenharmony_ci "THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n" 189b2a28edaSopenharmony_ci "OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n" 190b2a28edaSopenharmony_ci "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n" 191b2a28edaSopenharmony_ci "THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n" 192b2a28edaSopenharmony_ci "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n" 193b2a28edaSopenharmony_ci "FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS\n" 194b2a28edaSopenharmony_ci "IN THE MATERIALS.\n"; 195b2a28edaSopenharmony_ci 196b2a28edaSopenharmony_ci const std::string TPrinter::DocComment1 = 197b2a28edaSopenharmony_ci "This header is automatically generated by the same tool that creates\n" 198b2a28edaSopenharmony_ci "the Binary Section of the SPIR-V specification.\n"; 199b2a28edaSopenharmony_ci 200b2a28edaSopenharmony_ci const std::string TPrinter::DocComment2 = 201b2a28edaSopenharmony_ci "Enumeration tokens for SPIR-V, in various styles:\n" 202b2a28edaSopenharmony_ci " C, C++, C++11, JSON, Lua, Python, C#, D, Beef\n" 203b2a28edaSopenharmony_ci "\n" 204b2a28edaSopenharmony_ci "- C will have tokens with a \"Spv\" prefix, e.g.: SpvSourceLanguageGLSL\n" 205b2a28edaSopenharmony_ci "- C++ will have tokens in the \"spv\" name space, e.g.: spv::SourceLanguageGLSL\n" 206b2a28edaSopenharmony_ci "- C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL\n" 207b2a28edaSopenharmony_ci "- Lua will use tables, e.g.: spv.SourceLanguage.GLSL\n" 208b2a28edaSopenharmony_ci "- Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']\n" 209b2a28edaSopenharmony_ci "- C# will use enum classes in the Specification class located in the \"Spv\" namespace,\n" 210b2a28edaSopenharmony_ci " e.g.: Spv.Specification.SourceLanguage.GLSL\n" 211b2a28edaSopenharmony_ci "- D will have tokens under the \"spv\" module, e.g: spv.SourceLanguage.GLSL\n" 212b2a28edaSopenharmony_ci "- Beef will use enum classes in the Specification class located in the \"Spv\" namespace,\n" 213b2a28edaSopenharmony_ci " e.g.: Spv.Specification.SourceLanguage.GLSL\n" 214b2a28edaSopenharmony_ci "\n" 215b2a28edaSopenharmony_ci "Some tokens act like mask values, which can be OR'd together,\n" 216b2a28edaSopenharmony_ci "while others are mutually exclusive. The mask-like ones have\n" 217b2a28edaSopenharmony_ci "\"Mask\" in their name, and a parallel enum that has the shift\n" 218b2a28edaSopenharmony_ci "amount (1 << x) for each corresponding enumerant.\n"; 219b2a28edaSopenharmony_ci 220b2a28edaSopenharmony_ci // Construct 221b2a28edaSopenharmony_ci TPrinter::TPrinter() 222b2a28edaSopenharmony_ci { 223b2a28edaSopenharmony_ci Json::Value& meta = spvRoot["spv"]["meta"]; 224b2a28edaSopenharmony_ci Json::Value& enums = spvRoot["spv"]["enum"]; 225b2a28edaSopenharmony_ci 226b2a28edaSopenharmony_ci meta["MagicNumber"] = DocMagicNumber; 227b2a28edaSopenharmony_ci meta["Version"] = DocVersion; 228b2a28edaSopenharmony_ci meta["Revision"] = DocRevision; 229b2a28edaSopenharmony_ci meta["OpCodeMask"] = 0xffff; 230b2a28edaSopenharmony_ci meta["WordCountShift"] = 16; 231b2a28edaSopenharmony_ci 232b2a28edaSopenharmony_ci int commentId = 0; 233b2a28edaSopenharmony_ci addComment(meta["Comment"][commentId++], DocCopyright); 234b2a28edaSopenharmony_ci addComment(meta["Comment"][commentId++], DocComment1); 235b2a28edaSopenharmony_ci addComment(meta["Comment"][commentId++], DocComment2); 236b2a28edaSopenharmony_ci 237b2a28edaSopenharmony_ci for (int e = spv::OperandSource; e < spv::OperandOpcode; ++e) { 238b2a28edaSopenharmony_ci auto& enumSet = spv::OperandClassParams[e]; 239b2a28edaSopenharmony_ci const bool mask = enumSet.bitmask; 240b2a28edaSopenharmony_ci const std::string enumName = enumSet.codeName; 241b2a28edaSopenharmony_ci 242b2a28edaSopenharmony_ci for (auto& enumRow : enumSet) { 243b2a28edaSopenharmony_ci std::string name = enumRow.name; 244b2a28edaSopenharmony_ci enums[e - spv::OperandSource]["Values"][name] = enumRow.value; 245b2a28edaSopenharmony_ci } 246b2a28edaSopenharmony_ci 247b2a28edaSopenharmony_ci enums[e - spv::OperandSource]["Type"] = mask ? "Bit" : "Value"; 248b2a28edaSopenharmony_ci enums[e - spv::OperandSource]["Name"] = enumName; 249b2a28edaSopenharmony_ci } 250b2a28edaSopenharmony_ci 251b2a28edaSopenharmony_ci // Instructions are in their own different table 252b2a28edaSopenharmony_ci { 253b2a28edaSopenharmony_ci auto& entry = enums[spv::OperandOpcode - spv::OperandSource]; 254b2a28edaSopenharmony_ci for (auto& enumRow : spv::InstructionDesc) { 255b2a28edaSopenharmony_ci std::string name = enumRow.name; 256b2a28edaSopenharmony_ci entry["Values"][name] = enumRow.value; 257b2a28edaSopenharmony_ci } 258b2a28edaSopenharmony_ci entry["Type"] = "Value"; 259b2a28edaSopenharmony_ci entry["Name"] = "Op"; 260b2a28edaSopenharmony_ci } 261b2a28edaSopenharmony_ci } 262b2a28edaSopenharmony_ci 263b2a28edaSopenharmony_ci // Create comment 264b2a28edaSopenharmony_ci void TPrinter::addComment(Json::Value& node, const std::string& str) 265b2a28edaSopenharmony_ci { 266b2a28edaSopenharmony_ci std::istringstream cstream(str); 267b2a28edaSopenharmony_ci std::string cline; 268b2a28edaSopenharmony_ci 269b2a28edaSopenharmony_ci int line = 0; 270b2a28edaSopenharmony_ci while (std::getline(cstream, cline)) // fmt each line 271b2a28edaSopenharmony_ci node[line++] = cline; 272b2a28edaSopenharmony_ci } 273b2a28edaSopenharmony_ci 274b2a28edaSopenharmony_ci 275b2a28edaSopenharmony_ci // Return a list of values sorted by enum value. The std::vector 276b2a28edaSopenharmony_ci // returned by value is okay in c++11 due to move semantics. 277b2a28edaSopenharmony_ci std::vector<TPrinter::valpair_t> 278b2a28edaSopenharmony_ci TPrinter::getSortedVals(const Json::Value& p) const 279b2a28edaSopenharmony_ci { 280b2a28edaSopenharmony_ci std::vector<valpair_t> values; 281b2a28edaSopenharmony_ci 282b2a28edaSopenharmony_ci for (auto e = p.begin(); e != p.end(); ++e) 283b2a28edaSopenharmony_ci values.push_back(valpair_t(e->asUInt(), e.name())); 284b2a28edaSopenharmony_ci 285b2a28edaSopenharmony_ci // Use a stable sort because we might have aliases, e.g. 286b2a28edaSopenharmony_ci // SubgropuBallot (might be in future core) vs. SubgroupBallotKHR. 287b2a28edaSopenharmony_ci std::stable_sort(values.begin(), values.end()); 288b2a28edaSopenharmony_ci 289b2a28edaSopenharmony_ci return values; 290b2a28edaSopenharmony_ci } 291b2a28edaSopenharmony_ci 292b2a28edaSopenharmony_ci // Escape comment characters if needed 293b2a28edaSopenharmony_ci std::string TPrinter::escapeComment(const std::string& s) const { return s; } 294b2a28edaSopenharmony_ci 295b2a28edaSopenharmony_ci // Format comments in language specific way 296b2a28edaSopenharmony_ci void TPrinter::printComments(std::ostream& out) const 297b2a28edaSopenharmony_ci { 298b2a28edaSopenharmony_ci const int commentCount = spvRoot["spv"]["meta"]["Comment"].size(); 299b2a28edaSopenharmony_ci int commentNum = 0; 300b2a28edaSopenharmony_ci 301b2a28edaSopenharmony_ci for (const auto& comment : spvRoot["spv"]["meta"]["Comment"]) { 302b2a28edaSopenharmony_ci out << commentBeg(); 303b2a28edaSopenharmony_ci 304b2a28edaSopenharmony_ci for (int line = 0; line < int(comment.size()); ++line) 305b2a28edaSopenharmony_ci out << commentBOL() << escapeComment(comment[line].asString()) << 306b2a28edaSopenharmony_ci commentEOL((line+1) == comment.size()) << std::endl; 307b2a28edaSopenharmony_ci 308b2a28edaSopenharmony_ci out << commentEnd(++commentNum == commentCount) << std::endl; 309b2a28edaSopenharmony_ci } 310b2a28edaSopenharmony_ci } 311b2a28edaSopenharmony_ci 312b2a28edaSopenharmony_ci // Format header metadata 313b2a28edaSopenharmony_ci void TPrinter::printMeta(std::ostream& out) const 314b2a28edaSopenharmony_ci { 315b2a28edaSopenharmony_ci const Json::Value& meta = spvRoot["spv"]["meta"]; 316b2a28edaSopenharmony_ci 317b2a28edaSopenharmony_ci const auto print = [&](const char* name, const char* fmt, bool isLast) { 318b2a28edaSopenharmony_ci out << fmtConstInt(meta[name].asUInt(), name, fmt, isLast); 319b2a28edaSopenharmony_ci }; 320b2a28edaSopenharmony_ci 321b2a28edaSopenharmony_ci print("MagicNumber", "0x%08lx", false); 322b2a28edaSopenharmony_ci print("Version", "0x%08lx", false); 323b2a28edaSopenharmony_ci print("Revision", "%d", false); 324b2a28edaSopenharmony_ci print("OpCodeMask", "0x%04x", false); 325b2a28edaSopenharmony_ci print("WordCountShift", "%d", true); 326b2a28edaSopenharmony_ci } 327b2a28edaSopenharmony_ci 328b2a28edaSopenharmony_ci // Format value definitions in language specific way 329b2a28edaSopenharmony_ci void TPrinter::printDefs(std::ostream& out) const 330b2a28edaSopenharmony_ci { 331b2a28edaSopenharmony_ci const Json::Value& enums = spvRoot["spv"]["enum"]; 332b2a28edaSopenharmony_ci 333b2a28edaSopenharmony_ci for (auto opClass = enums.begin(); opClass != enums.end(); ++opClass) { 334b2a28edaSopenharmony_ci const bool isMask = (*opClass)["Type"].asString() == "Bit"; 335b2a28edaSopenharmony_ci const auto opName = (*opClass)["Name"].asString(); 336b2a28edaSopenharmony_ci const auto opPrefix = opName == "Op" ? "" : opName; 337b2a28edaSopenharmony_ci 338b2a28edaSopenharmony_ci for (enumStyle_t style = (isMask ? enumShift : enumCount); 339b2a28edaSopenharmony_ci style <= (isMask ? enumMask : enumCount); style = enumStyle_t(int(style)+1)) { 340b2a28edaSopenharmony_ci 341b2a28edaSopenharmony_ci out << enumBeg(opName, style); 342b2a28edaSopenharmony_ci 343b2a28edaSopenharmony_ci if (style == enumMask) 344b2a28edaSopenharmony_ci out << enumFmt(opPrefix, valpair_t(0, "MaskNone"), enumNoMask); 345b2a28edaSopenharmony_ci 346b2a28edaSopenharmony_ci const auto sorted = getSortedVals((*opClass)["Values"]); 347b2a28edaSopenharmony_ci 348b2a28edaSopenharmony_ci std::string maxEnum = maxEnumFmt(opName, valpair_t(0x7FFFFFFF, "Max"), enumHex); 349b2a28edaSopenharmony_ci 350b2a28edaSopenharmony_ci bool printMax = (style != enumMask && maxEnum.size() > 0); 351b2a28edaSopenharmony_ci 352b2a28edaSopenharmony_ci for (const auto& v : sorted) 353b2a28edaSopenharmony_ci out << enumFmt(opPrefix, v, style, !printMax && v.second == sorted.back().second); 354b2a28edaSopenharmony_ci 355b2a28edaSopenharmony_ci if (printMax) 356b2a28edaSopenharmony_ci out << maxEnum; 357b2a28edaSopenharmony_ci 358b2a28edaSopenharmony_ci auto nextOpClass = opClass; 359b2a28edaSopenharmony_ci out << enumEnd(opName, style, ++nextOpClass == enums.end()); 360b2a28edaSopenharmony_ci } 361b2a28edaSopenharmony_ci } 362b2a28edaSopenharmony_ci } 363b2a28edaSopenharmony_ci 364b2a28edaSopenharmony_ci void TPrinter::printAll(std::ostream& out) const 365b2a28edaSopenharmony_ci { 366b2a28edaSopenharmony_ci printComments(out); 367b2a28edaSopenharmony_ci printPrologue(out); 368b2a28edaSopenharmony_ci printTypes(out); 369b2a28edaSopenharmony_ci printMeta(out); 370b2a28edaSopenharmony_ci printDefs(out); 371b2a28edaSopenharmony_ci printHasResultType(out); 372b2a28edaSopenharmony_ci printEpilogue(out); 373b2a28edaSopenharmony_ci } 374b2a28edaSopenharmony_ci 375b2a28edaSopenharmony_ci // Stream entire header to output 376b2a28edaSopenharmony_ci std::ostream& operator<<(std::ostream& out, const TPrinter &p) 377b2a28edaSopenharmony_ci { 378b2a28edaSopenharmony_ci p.printAll(out); 379b2a28edaSopenharmony_ci return out; 380b2a28edaSopenharmony_ci } 381b2a28edaSopenharmony_ci 382b2a28edaSopenharmony_ci // JSON printer. Rather than use the default printer, we supply our own so 383b2a28edaSopenharmony_ci // we can control the printing order within various containers. 384b2a28edaSopenharmony_ci class TPrinterJSON final : public TPrinter { 385b2a28edaSopenharmony_ci private: 386b2a28edaSopenharmony_ci void printPrologue(std::ostream& out) const override { out << "{\n" + indent() + "\"spv\":\n" + indent() + "{\n"; } 387b2a28edaSopenharmony_ci void printEpilogue(std::ostream& out) const override { out << indent() + "}\n}\n"; } 388b2a28edaSopenharmony_ci 389b2a28edaSopenharmony_ci std::string escapeComment(const std::string& s) const override { 390b2a28edaSopenharmony_ci std::string newStr; 391b2a28edaSopenharmony_ci for (auto c : s) { 392b2a28edaSopenharmony_ci if (c == '"') { 393b2a28edaSopenharmony_ci newStr += '\\'; 394b2a28edaSopenharmony_ci newStr += c; 395b2a28edaSopenharmony_ci } else { 396b2a28edaSopenharmony_ci newStr += c; 397b2a28edaSopenharmony_ci } 398b2a28edaSopenharmony_ci } 399b2a28edaSopenharmony_ci return newStr; 400b2a28edaSopenharmony_ci } 401b2a28edaSopenharmony_ci 402b2a28edaSopenharmony_ci std::string fmtConstInt(unsigned val, const std::string& name, 403b2a28edaSopenharmony_ci const char* fmt, bool isLast) const override { 404b2a28edaSopenharmony_ci return indent(3) + '"' + name + "\": " + fmtNum("%d", val) + (isLast ? "\n" : ",\n"); 405b2a28edaSopenharmony_ci } 406b2a28edaSopenharmony_ci 407b2a28edaSopenharmony_ci void printMeta(std::ostream& out) const override 408b2a28edaSopenharmony_ci { 409b2a28edaSopenharmony_ci out << indent(2) + "\"meta\":\n" + indent(2) + "{\n"; 410b2a28edaSopenharmony_ci printComments(out); 411b2a28edaSopenharmony_ci TPrinter::printMeta(out); 412b2a28edaSopenharmony_ci out << indent(2) + "},\n"; 413b2a28edaSopenharmony_ci } 414b2a28edaSopenharmony_ci 415b2a28edaSopenharmony_ci std::string commentBeg() const override { return indent(4) + "[\n"; } 416b2a28edaSopenharmony_ci std::string commentEnd(bool isLast) const override { return indent(4) + (isLast ? "]" : "],"); } 417b2a28edaSopenharmony_ci std::string commentBOL() const override { return indent(5) + '"'; } 418b2a28edaSopenharmony_ci std::string commentEOL(bool isLast) const override { return (isLast ? "\"" : "\","); } 419b2a28edaSopenharmony_ci 420b2a28edaSopenharmony_ci void printComments(std::ostream& out) const override 421b2a28edaSopenharmony_ci { 422b2a28edaSopenharmony_ci out << indent(3) + "\"Comment\":\n" + indent(3) + "[\n"; 423b2a28edaSopenharmony_ci TPrinter::printComments(out); 424b2a28edaSopenharmony_ci out << indent(3) + "],\n"; 425b2a28edaSopenharmony_ci } 426b2a28edaSopenharmony_ci 427b2a28edaSopenharmony_ci void printDefs(std::ostream& out) const override 428b2a28edaSopenharmony_ci { 429b2a28edaSopenharmony_ci out << indent(2) + "\"enum\":\n" + indent(2) + "[\n"; 430b2a28edaSopenharmony_ci TPrinter::printDefs(out); 431b2a28edaSopenharmony_ci out << indent(2) + "]\n"; 432b2a28edaSopenharmony_ci } 433b2a28edaSopenharmony_ci 434b2a28edaSopenharmony_ci void printAll(std::ostream& out) const override 435b2a28edaSopenharmony_ci { 436b2a28edaSopenharmony_ci printPrologue(out); 437b2a28edaSopenharmony_ci printMeta(out); 438b2a28edaSopenharmony_ci printDefs(out); 439b2a28edaSopenharmony_ci printEpilogue(out); 440b2a28edaSopenharmony_ci } 441b2a28edaSopenharmony_ci 442b2a28edaSopenharmony_ci std::string enumBeg(const std::string& s, enumStyle_t style) const override { 443b2a28edaSopenharmony_ci if (style == enumMask) 444b2a28edaSopenharmony_ci return ""; 445b2a28edaSopenharmony_ci return indent(3) + "{\n" + 446b2a28edaSopenharmony_ci indent(4) + "\"Name\": \"" + s + "\",\n" + 447b2a28edaSopenharmony_ci indent(4) + "\"Type\": " + (style == enumShift ? "\"Bit\"" : "\"Value\"") + ",\n" + 448b2a28edaSopenharmony_ci indent(4) + "\"Values\":\n" + 449b2a28edaSopenharmony_ci indent(4) + "{\n"; 450b2a28edaSopenharmony_ci } 451b2a28edaSopenharmony_ci 452b2a28edaSopenharmony_ci std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override { 453b2a28edaSopenharmony_ci if (style == enumMask) 454b2a28edaSopenharmony_ci return ""; 455b2a28edaSopenharmony_ci return indent(4) + "}\n" + 456b2a28edaSopenharmony_ci indent(3) + "}" + (isLast ? "" : ",") + "\n"; 457b2a28edaSopenharmony_ci } 458b2a28edaSopenharmony_ci 459b2a28edaSopenharmony_ci std::string enumFmt(const std::string& s, const valpair_t& v, 460b2a28edaSopenharmony_ci enumStyle_t style, bool isLast) const override { 461b2a28edaSopenharmony_ci if (style == enumMask || style == enumNoMask) 462b2a28edaSopenharmony_ci return ""; 463b2a28edaSopenharmony_ci return indent(5) + '"' + prependIfDigit(s, v.second) + "\": " + fmtNum("%d", v.first) + 464b2a28edaSopenharmony_ci (isLast ? "\n" : ",\n"); 465b2a28edaSopenharmony_ci } 466b2a28edaSopenharmony_ci }; 467b2a28edaSopenharmony_ci 468b2a28edaSopenharmony_ci // base for C and C++ 469b2a28edaSopenharmony_ci class TPrinterCBase : public TPrinter { 470b2a28edaSopenharmony_ci protected: 471b2a28edaSopenharmony_ci virtual void printPrologue(std::ostream& out) const override { 472b2a28edaSopenharmony_ci out << "#ifndef spirv_" << headerGuardSuffix() << std::endl 473b2a28edaSopenharmony_ci << "#define spirv_" << headerGuardSuffix() << std::endl 474b2a28edaSopenharmony_ci << std::endl; 475b2a28edaSopenharmony_ci } 476b2a28edaSopenharmony_ci 477b2a28edaSopenharmony_ci void printMeta(std::ostream& out) const override { 478b2a28edaSopenharmony_ci out << "#define SPV_VERSION 0x" << std::hex << DocVersion << std::dec << "\n"; 479b2a28edaSopenharmony_ci out << "#define SPV_REVISION " << DocRevision << "\n"; 480b2a28edaSopenharmony_ci out << "\n"; 481b2a28edaSopenharmony_ci 482b2a28edaSopenharmony_ci return TPrinter::printMeta(out); 483b2a28edaSopenharmony_ci } 484b2a28edaSopenharmony_ci 485b2a28edaSopenharmony_ci virtual void printEpilogue(std::ostream& out) const override { 486b2a28edaSopenharmony_ci out << "#endif" << std::endl; 487b2a28edaSopenharmony_ci } 488b2a28edaSopenharmony_ci 489b2a28edaSopenharmony_ci virtual void printTypes(std::ostream& out) const override { 490b2a28edaSopenharmony_ci out << "typedef unsigned int " << pre() << "Id;\n\n"; 491b2a28edaSopenharmony_ci } 492b2a28edaSopenharmony_ci 493b2a28edaSopenharmony_ci virtual std::string fmtConstInt(unsigned val, const std::string& name, 494b2a28edaSopenharmony_ci const char* fmt, bool isLast) const override 495b2a28edaSopenharmony_ci { 496b2a28edaSopenharmony_ci return std::string("static const unsigned int ") + pre() + name + 497b2a28edaSopenharmony_ci " = " + fmtNum(fmt, val) + (isLast ? ";\n\n" : ";\n"); 498b2a28edaSopenharmony_ci } 499b2a28edaSopenharmony_ci 500b2a28edaSopenharmony_ci virtual std::string pre() const { return ""; } // C name prefix 501b2a28edaSopenharmony_ci virtual std::string headerGuardSuffix() const = 0; 502b2a28edaSopenharmony_ci 503b2a28edaSopenharmony_ci virtual std::string fmtEnumUse(const std::string& opPrefix, const std::string& name) const { return pre() + name; } 504b2a28edaSopenharmony_ci 505b2a28edaSopenharmony_ci virtual void printHasResultType(std::ostream& out) const override 506b2a28edaSopenharmony_ci { 507b2a28edaSopenharmony_ci const Json::Value& enums = spvRoot["spv"]["enum"]; 508b2a28edaSopenharmony_ci 509b2a28edaSopenharmony_ci std::set<unsigned> seenValues; 510b2a28edaSopenharmony_ci 511b2a28edaSopenharmony_ci for (auto opClass = enums.begin(); opClass != enums.end(); ++opClass) { 512b2a28edaSopenharmony_ci const auto opName = (*opClass)["Name"].asString(); 513b2a28edaSopenharmony_ci if (opName != "Op") { 514b2a28edaSopenharmony_ci continue; 515b2a28edaSopenharmony_ci } 516b2a28edaSopenharmony_ci 517b2a28edaSopenharmony_ci out << "#ifdef SPV_ENABLE_UTILITY_CODE" << std::endl; 518b2a28edaSopenharmony_ci out << "#ifndef __cplusplus" << std::endl; 519b2a28edaSopenharmony_ci out << "#include <stdbool.h>" << std::endl; 520b2a28edaSopenharmony_ci out << "#endif" << std::endl; 521b2a28edaSopenharmony_ci out << "inline void " << pre() << "HasResultAndType(" << pre() << opName << " opcode, bool *hasResult, bool *hasResultType) {" << std::endl; 522b2a28edaSopenharmony_ci out << " *hasResult = *hasResultType = false;" << std::endl; 523b2a28edaSopenharmony_ci out << " switch (opcode) {" << std::endl; 524b2a28edaSopenharmony_ci out << " default: /* unknown opcode */ break;" << std::endl; 525b2a28edaSopenharmony_ci 526b2a28edaSopenharmony_ci for (auto& inst : spv::InstructionDesc) { 527b2a28edaSopenharmony_ci 528b2a28edaSopenharmony_ci // Filter out duplicate enum values, which would break the switch statement. 529b2a28edaSopenharmony_ci // These are probably just extension enums promoted to core. 530b2a28edaSopenharmony_ci if (seenValues.find(inst.value) != seenValues.end()) { 531b2a28edaSopenharmony_ci continue; 532b2a28edaSopenharmony_ci } 533b2a28edaSopenharmony_ci seenValues.insert(inst.value); 534b2a28edaSopenharmony_ci 535b2a28edaSopenharmony_ci std::string name = inst.name; 536b2a28edaSopenharmony_ci out << " case " << fmtEnumUse("Op", name) << ": *hasResult = " << (inst.hasResult() ? "true" : "false") << "; *hasResultType = " << (inst.hasType() ? "true" : "false") << "; break;" << std::endl; 537b2a28edaSopenharmony_ci } 538b2a28edaSopenharmony_ci 539b2a28edaSopenharmony_ci out << " }" << std::endl; 540b2a28edaSopenharmony_ci out << "}" << std::endl; 541b2a28edaSopenharmony_ci out << "#endif /* SPV_ENABLE_UTILITY_CODE */" << std::endl << std::endl; 542b2a28edaSopenharmony_ci } 543b2a28edaSopenharmony_ci } 544b2a28edaSopenharmony_ci }; 545b2a28edaSopenharmony_ci 546b2a28edaSopenharmony_ci // C printer 547b2a28edaSopenharmony_ci class TPrinterC final : public TPrinterCBase { 548b2a28edaSopenharmony_ci private: 549b2a28edaSopenharmony_ci std::string commentBeg() const override { return "/*\n"; } 550b2a28edaSopenharmony_ci std::string commentEnd(bool isLast) const override { return "*/\n"; } 551b2a28edaSopenharmony_ci std::string commentBOL() const override { return "** "; } 552b2a28edaSopenharmony_ci 553b2a28edaSopenharmony_ci std::string enumBeg(const std::string& s, enumStyle_t style) const override { 554b2a28edaSopenharmony_ci return std::string("typedef enum ") + pre() + s + styleStr(style) + "_ {\n"; 555b2a28edaSopenharmony_ci } 556b2a28edaSopenharmony_ci 557b2a28edaSopenharmony_ci std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override { 558b2a28edaSopenharmony_ci return "} " + pre() + s + styleStr(style) + ";\n\n"; 559b2a28edaSopenharmony_ci } 560b2a28edaSopenharmony_ci 561b2a28edaSopenharmony_ci std::string enumFmt(const std::string& s, const valpair_t& v, 562b2a28edaSopenharmony_ci enumStyle_t style, bool isLast) const override { 563b2a28edaSopenharmony_ci return indent() + pre() + s + v.second + styleStr(style) + " = " + fmtStyleVal(v.first, style) + ",\n"; 564b2a28edaSopenharmony_ci } 565b2a28edaSopenharmony_ci 566b2a28edaSopenharmony_ci std::string maxEnumFmt(const std::string& s, const valpair_t& v, 567b2a28edaSopenharmony_ci enumStyle_t style) const override { 568b2a28edaSopenharmony_ci return enumFmt(s, v, style, true); 569b2a28edaSopenharmony_ci } 570b2a28edaSopenharmony_ci 571b2a28edaSopenharmony_ci std::string pre() const override { return "Spv"; } // C name prefix 572b2a28edaSopenharmony_ci std::string headerGuardSuffix() const override { return "H"; } 573b2a28edaSopenharmony_ci }; 574b2a28edaSopenharmony_ci 575b2a28edaSopenharmony_ci // C++ printer 576b2a28edaSopenharmony_ci class TPrinterCPP : public TPrinterCBase { 577b2a28edaSopenharmony_ci protected: 578b2a28edaSopenharmony_ci void printMaskOperators(std::ostream& out, const std::string& specifiers) const { 579b2a28edaSopenharmony_ci const Json::Value& enums = spvRoot["spv"]["enum"]; 580b2a28edaSopenharmony_ci 581b2a28edaSopenharmony_ci out << "// Overload bitwise operators for mask bit combining\n\n"; 582b2a28edaSopenharmony_ci 583b2a28edaSopenharmony_ci for (auto opClass = enums.begin(); opClass != enums.end(); ++opClass) { 584b2a28edaSopenharmony_ci const bool isMask = (*opClass)["Type"].asString() == "Bit"; 585b2a28edaSopenharmony_ci const auto opName = (*opClass)["Name"].asString(); 586b2a28edaSopenharmony_ci 587b2a28edaSopenharmony_ci if (isMask) { 588b2a28edaSopenharmony_ci const auto typeName = opName + styleStr(enumMask); 589b2a28edaSopenharmony_ci 590b2a28edaSopenharmony_ci // Overload operator| 591b2a28edaSopenharmony_ci out << specifiers << " " << typeName << " operator|(" << typeName << " a, " << typeName << " b) { return " << 592b2a28edaSopenharmony_ci typeName << "(unsigned(a) | unsigned(b)); }\n"; 593b2a28edaSopenharmony_ci // Overload operator& 594b2a28edaSopenharmony_ci out << specifiers << " " << typeName << " operator&(" << typeName << " a, " << typeName << " b) { return " << 595b2a28edaSopenharmony_ci typeName << "(unsigned(a) & unsigned(b)); }\n"; 596b2a28edaSopenharmony_ci // Overload operator^ 597b2a28edaSopenharmony_ci out << specifiers << " " << typeName << " operator^(" << typeName << " a, " << typeName << " b) { return " << 598b2a28edaSopenharmony_ci typeName << "(unsigned(a) ^ unsigned(b)); }\n"; 599b2a28edaSopenharmony_ci // Overload operator~ 600b2a28edaSopenharmony_ci out << specifiers << " " << typeName << " operator~(" << typeName << " a) { return " << 601b2a28edaSopenharmony_ci typeName << "(~unsigned(a)); }\n"; 602b2a28edaSopenharmony_ci } 603b2a28edaSopenharmony_ci } 604b2a28edaSopenharmony_ci } 605b2a28edaSopenharmony_ci private: 606b2a28edaSopenharmony_ci void printPrologue(std::ostream& out) const override { 607b2a28edaSopenharmony_ci TPrinterCBase::printPrologue(out); 608b2a28edaSopenharmony_ci out << "namespace spv {\n\n"; 609b2a28edaSopenharmony_ci } 610b2a28edaSopenharmony_ci 611b2a28edaSopenharmony_ci void printEpilogue(std::ostream& out) const override { 612b2a28edaSopenharmony_ci printMaskOperators(out, "inline"); 613b2a28edaSopenharmony_ci out << "\n} // end namespace spv\n\n"; 614b2a28edaSopenharmony_ci out << "#endif // #ifndef spirv_" << headerGuardSuffix() << std::endl; 615b2a28edaSopenharmony_ci } 616b2a28edaSopenharmony_ci 617b2a28edaSopenharmony_ci std::string commentBOL() const override { return "// "; } 618b2a28edaSopenharmony_ci 619b2a28edaSopenharmony_ci 620b2a28edaSopenharmony_ci virtual std::string enumBeg(const std::string& s, enumStyle_t style) const override { 621b2a28edaSopenharmony_ci return std::string("enum ") + s + styleStr(style) + " {\n"; 622b2a28edaSopenharmony_ci } 623b2a28edaSopenharmony_ci 624b2a28edaSopenharmony_ci std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override { 625b2a28edaSopenharmony_ci return "};\n\n"; 626b2a28edaSopenharmony_ci } 627b2a28edaSopenharmony_ci 628b2a28edaSopenharmony_ci virtual std::string enumFmt(const std::string& s, const valpair_t& v, 629b2a28edaSopenharmony_ci enumStyle_t style, bool isLast) const override { 630b2a28edaSopenharmony_ci return indent() + s + v.second + styleStr(style) + " = " + fmtStyleVal(v.first, style) + ",\n"; 631b2a28edaSopenharmony_ci } 632b2a28edaSopenharmony_ci 633b2a28edaSopenharmony_ci virtual std::string maxEnumFmt(const std::string& s, const valpair_t& v, 634b2a28edaSopenharmony_ci enumStyle_t style) const override { 635b2a28edaSopenharmony_ci return enumFmt(s, v, style, true); 636b2a28edaSopenharmony_ci } 637b2a28edaSopenharmony_ci 638b2a28edaSopenharmony_ci // The C++ and C++11 headers define types with the same name. So they 639b2a28edaSopenharmony_ci // should use the same header guard. 640b2a28edaSopenharmony_ci std::string headerGuardSuffix() const override { return "HPP"; } 641b2a28edaSopenharmony_ci 642b2a28edaSopenharmony_ci std::string operators; 643b2a28edaSopenharmony_ci }; 644b2a28edaSopenharmony_ci 645b2a28edaSopenharmony_ci // C++11 printer (uses enum classes) 646b2a28edaSopenharmony_ci class TPrinterCPP11 final : public TPrinterCPP { 647b2a28edaSopenharmony_ci private: 648b2a28edaSopenharmony_ci void printEpilogue(std::ostream& out) const override { 649b2a28edaSopenharmony_ci printMaskOperators(out, "constexpr"); 650b2a28edaSopenharmony_ci out << "\n} // end namespace spv\n\n"; 651b2a28edaSopenharmony_ci out << "#endif // #ifndef spirv_" << headerGuardSuffix() << std::endl; 652b2a28edaSopenharmony_ci } 653b2a28edaSopenharmony_ci std::string enumBeg(const std::string& s, enumStyle_t style) const override { 654b2a28edaSopenharmony_ci return std::string("enum class ") + s + styleStr(style) + " : unsigned {\n"; 655b2a28edaSopenharmony_ci } 656b2a28edaSopenharmony_ci 657b2a28edaSopenharmony_ci std::string enumFmt(const std::string& s, const valpair_t& v, 658b2a28edaSopenharmony_ci enumStyle_t style, bool isLast) const override { 659b2a28edaSopenharmony_ci return indent() + prependIfDigit(s, v.second) + " = " + fmtStyleVal(v.first, style) + ",\n"; 660b2a28edaSopenharmony_ci } 661b2a28edaSopenharmony_ci 662b2a28edaSopenharmony_ci std::string maxEnumFmt(const std::string& s, const valpair_t& v, 663b2a28edaSopenharmony_ci enumStyle_t style) const override { 664b2a28edaSopenharmony_ci return enumFmt(s, v, style, true); 665b2a28edaSopenharmony_ci } 666b2a28edaSopenharmony_ci 667b2a28edaSopenharmony_ci // Add type prefix for scoped enum 668b2a28edaSopenharmony_ci virtual std::string fmtEnumUse(const std::string& opPrefix, const std::string& name) const override { return opPrefix + "::" + name; } 669b2a28edaSopenharmony_ci 670b2a28edaSopenharmony_ci std::string headerGuardSuffix() const override { return "HPP"; } 671b2a28edaSopenharmony_ci }; 672b2a28edaSopenharmony_ci 673b2a28edaSopenharmony_ci // LUA printer 674b2a28edaSopenharmony_ci class TPrinterLua final : public TPrinter { 675b2a28edaSopenharmony_ci private: 676b2a28edaSopenharmony_ci void printPrologue(std::ostream& out) const override { out << "spv = {\n"; } 677b2a28edaSopenharmony_ci 678b2a28edaSopenharmony_ci void printEpilogue(std::ostream& out) const override { out << "}\n"; } 679b2a28edaSopenharmony_ci 680b2a28edaSopenharmony_ci std::string commentBOL() const override { return "-- "; } 681b2a28edaSopenharmony_ci 682b2a28edaSopenharmony_ci std::string enumBeg(const std::string& s, enumStyle_t style) const override { 683b2a28edaSopenharmony_ci return indent() + s + styleStr(style) + " = {\n"; 684b2a28edaSopenharmony_ci } 685b2a28edaSopenharmony_ci 686b2a28edaSopenharmony_ci std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override { 687b2a28edaSopenharmony_ci return indent() + "},\n\n"; 688b2a28edaSopenharmony_ci } 689b2a28edaSopenharmony_ci 690b2a28edaSopenharmony_ci std::string enumFmt(const std::string& s, const valpair_t& v, 691b2a28edaSopenharmony_ci enumStyle_t style, bool isLast) const override { 692b2a28edaSopenharmony_ci return indent(2) + prependIfDigit(s, v.second) + " = " + fmtStyleVal(v.first, style) + ",\n"; 693b2a28edaSopenharmony_ci } 694b2a28edaSopenharmony_ci 695b2a28edaSopenharmony_ci virtual std::string fmtConstInt(unsigned val, const std::string& name, 696b2a28edaSopenharmony_ci const char* fmt, bool isLast) const override 697b2a28edaSopenharmony_ci { 698b2a28edaSopenharmony_ci return indent() + name + " = " + fmtNum(fmt, val) + (isLast ? ",\n\n" : ",\n"); 699b2a28edaSopenharmony_ci } 700b2a28edaSopenharmony_ci }; 701b2a28edaSopenharmony_ci 702b2a28edaSopenharmony_ci // Python printer 703b2a28edaSopenharmony_ci class TPrinterPython final : public TPrinter { 704b2a28edaSopenharmony_ci private: 705b2a28edaSopenharmony_ci void printPrologue(std::ostream& out) const override { out << "spv = {\n"; } 706b2a28edaSopenharmony_ci 707b2a28edaSopenharmony_ci void printEpilogue(std::ostream& out) const override { out << "}\n"; } 708b2a28edaSopenharmony_ci 709b2a28edaSopenharmony_ci std::string commentBOL() const override { return "# "; } 710b2a28edaSopenharmony_ci 711b2a28edaSopenharmony_ci std::string enumBeg(const std::string& s, enumStyle_t style) const override { 712b2a28edaSopenharmony_ci return indent() + "'" + s + styleStr(style) + "'" + " : {\n"; 713b2a28edaSopenharmony_ci } 714b2a28edaSopenharmony_ci 715b2a28edaSopenharmony_ci std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override { 716b2a28edaSopenharmony_ci return indent() + "},\n\n"; 717b2a28edaSopenharmony_ci } 718b2a28edaSopenharmony_ci 719b2a28edaSopenharmony_ci std::string enumFmt(const std::string& s, const valpair_t& v, 720b2a28edaSopenharmony_ci enumStyle_t style, bool isLast) const override { 721b2a28edaSopenharmony_ci return indent(2) + "'" + prependIfDigit(s, v.second) + "'" + " : " + fmtStyleVal(v.first, style) + ",\n"; 722b2a28edaSopenharmony_ci } 723b2a28edaSopenharmony_ci 724b2a28edaSopenharmony_ci std::string fmtConstInt(unsigned val, const std::string& name, 725b2a28edaSopenharmony_ci const char* fmt, bool isLast) const override 726b2a28edaSopenharmony_ci { 727b2a28edaSopenharmony_ci return indent() + "'" + name + "'" + " : " + fmtNum(fmt, val) + (isLast ? ",\n\n" : ",\n"); 728b2a28edaSopenharmony_ci } 729b2a28edaSopenharmony_ci }; 730b2a28edaSopenharmony_ci 731b2a28edaSopenharmony_ci // C# printer 732b2a28edaSopenharmony_ci class TPrinterCSharp final : public TPrinter { 733b2a28edaSopenharmony_ci private: 734b2a28edaSopenharmony_ci std::string commentBOL() const override { return "// "; } 735b2a28edaSopenharmony_ci 736b2a28edaSopenharmony_ci void printPrologue(std::ostream& out) const override { 737b2a28edaSopenharmony_ci out << "namespace Spv\n{\n\n"; 738b2a28edaSopenharmony_ci out << indent() << "public static class Specification\n"; 739b2a28edaSopenharmony_ci out << indent() << "{\n"; 740b2a28edaSopenharmony_ci } 741b2a28edaSopenharmony_ci 742b2a28edaSopenharmony_ci void printEpilogue(std::ostream& out) const override { 743b2a28edaSopenharmony_ci out << indent() << "}\n"; 744b2a28edaSopenharmony_ci out << "}\n"; 745b2a28edaSopenharmony_ci } 746b2a28edaSopenharmony_ci 747b2a28edaSopenharmony_ci std::string enumBeg(const std::string& s, enumStyle_t style) const override { 748b2a28edaSopenharmony_ci return indent(2) + "public enum " + s + styleStr(style) + "\n" + indent(2) + "{\n"; 749b2a28edaSopenharmony_ci } 750b2a28edaSopenharmony_ci 751b2a28edaSopenharmony_ci std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override { 752b2a28edaSopenharmony_ci return indent(2) + "}" + + (isLast ? "\n" : "\n\n"); 753b2a28edaSopenharmony_ci } 754b2a28edaSopenharmony_ci 755b2a28edaSopenharmony_ci std::string enumFmt(const std::string& s, const valpair_t& v, 756b2a28edaSopenharmony_ci enumStyle_t style, bool isLast) const override { 757b2a28edaSopenharmony_ci return indent(3) + prependIfDigit(s, v.second) + " = " + fmtStyleVal(v.first, style) + ",\n"; 758b2a28edaSopenharmony_ci } 759b2a28edaSopenharmony_ci 760b2a28edaSopenharmony_ci std::string fmtConstInt(unsigned val, const std::string& name, 761b2a28edaSopenharmony_ci const char* fmt, bool isLast) const override { 762b2a28edaSopenharmony_ci return indent(2) + std::string("public const uint ") + name + 763b2a28edaSopenharmony_ci " = " + fmtNum(fmt, val) + (isLast ? ";\n\n" : ";\n"); 764b2a28edaSopenharmony_ci } 765b2a28edaSopenharmony_ci }; 766b2a28edaSopenharmony_ci 767b2a28edaSopenharmony_ci // D printer 768b2a28edaSopenharmony_ci class TPrinterD final : public TPrinter { 769b2a28edaSopenharmony_ci private: 770b2a28edaSopenharmony_ci std::string commentBeg() const override { return "/+\n"; } 771b2a28edaSopenharmony_ci std::string commentBOL() const override { return " + "; } 772b2a28edaSopenharmony_ci std::string commentEnd(bool isLast) const override { return " +/\n"; } 773b2a28edaSopenharmony_ci 774b2a28edaSopenharmony_ci void printPrologue(std::ostream& out) const override { 775b2a28edaSopenharmony_ci out << "module spv;\n\n"; 776b2a28edaSopenharmony_ci } 777b2a28edaSopenharmony_ci 778b2a28edaSopenharmony_ci void printEpilogue(std::ostream& out) const override { 779b2a28edaSopenharmony_ci } 780b2a28edaSopenharmony_ci 781b2a28edaSopenharmony_ci std::string enumBeg(const std::string& s, enumStyle_t style) const override { 782b2a28edaSopenharmony_ci return "enum " + s + styleStr(style) + " : uint\n{\n"; 783b2a28edaSopenharmony_ci } 784b2a28edaSopenharmony_ci 785b2a28edaSopenharmony_ci std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override { 786b2a28edaSopenharmony_ci return std::string("}\n\n"); 787b2a28edaSopenharmony_ci } 788b2a28edaSopenharmony_ci 789b2a28edaSopenharmony_ci std::string enumFmt(const std::string& s, const valpair_t& v, 790b2a28edaSopenharmony_ci enumStyle_t style, bool isLast) const override { 791b2a28edaSopenharmony_ci return indent() + prependIfDigit("_", v.second) + " = " + fmtStyleVal(v.first, style) + ",\n"; 792b2a28edaSopenharmony_ci } 793b2a28edaSopenharmony_ci 794b2a28edaSopenharmony_ci std::string fmtConstInt(unsigned val, const std::string& name, 795b2a28edaSopenharmony_ci const char* fmt, bool isLast) const override { 796b2a28edaSopenharmony_ci return std::string("enum uint ") + name + 797b2a28edaSopenharmony_ci " = " + fmtNum(fmt, val) + (isLast ? ";\n\n" : ";\n"); 798b2a28edaSopenharmony_ci } 799b2a28edaSopenharmony_ci }; 800b2a28edaSopenharmony_ci 801b2a28edaSopenharmony_ci // Beef printer 802b2a28edaSopenharmony_ci class TPrinterBeef final : public TPrinter { 803b2a28edaSopenharmony_ci private: 804b2a28edaSopenharmony_ci std::string commentBOL() const override { return "// "; } 805b2a28edaSopenharmony_ci 806b2a28edaSopenharmony_ci void printPrologue(std::ostream& out) const override { 807b2a28edaSopenharmony_ci out << "namespace Spv\n{\n"; 808b2a28edaSopenharmony_ci out << indent() << "using System;\n\n"; 809b2a28edaSopenharmony_ci out << indent() << "public static class Specification\n"; 810b2a28edaSopenharmony_ci out << indent() << "{\n"; 811b2a28edaSopenharmony_ci } 812b2a28edaSopenharmony_ci 813b2a28edaSopenharmony_ci void printEpilogue(std::ostream& out) const override { 814b2a28edaSopenharmony_ci out << indent() << "}\n"; 815b2a28edaSopenharmony_ci out << "}\n"; 816b2a28edaSopenharmony_ci } 817b2a28edaSopenharmony_ci 818b2a28edaSopenharmony_ci std::string enumBeg(const std::string& s, enumStyle_t style) const override { 819b2a28edaSopenharmony_ci return indent(2) + "[AllowDuplicates, CRepr] public enum " + s + styleStr(style) + "\n" + indent(2) + "{\n"; 820b2a28edaSopenharmony_ci } 821b2a28edaSopenharmony_ci 822b2a28edaSopenharmony_ci std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override { 823b2a28edaSopenharmony_ci return indent(2) + "}" + +(isLast ? "\n" : "\n\n"); 824b2a28edaSopenharmony_ci } 825b2a28edaSopenharmony_ci 826b2a28edaSopenharmony_ci std::string enumFmt(const std::string& s, const valpair_t& v, 827b2a28edaSopenharmony_ci enumStyle_t style, bool isLast) const override { 828b2a28edaSopenharmony_ci return indent(3) + prependIfDigit(s, v.second) + " = " + fmtStyleVal(v.first, style) + ",\n"; 829b2a28edaSopenharmony_ci } 830b2a28edaSopenharmony_ci 831b2a28edaSopenharmony_ci std::string fmtConstInt(unsigned val, const std::string& name, 832b2a28edaSopenharmony_ci const char* fmt, bool isLast) const override { 833b2a28edaSopenharmony_ci return indent(2) + std::string("public const uint32 ") + name + 834b2a28edaSopenharmony_ci " = " + fmtNum(fmt, val) + (isLast ? ";\n\n" : ";\n"); 835b2a28edaSopenharmony_ci } 836b2a28edaSopenharmony_ci }; 837b2a28edaSopenharmony_ci 838b2a28edaSopenharmony_ci} // namespace 839b2a28edaSopenharmony_ci 840b2a28edaSopenharmony_cinamespace spv { 841b2a28edaSopenharmony_ci void PrintAllHeaders() 842b2a28edaSopenharmony_ci { 843b2a28edaSopenharmony_ci // TODO: Once MSVC 2012 is no longer a factor, use brace initializers here 844b2a28edaSopenharmony_ci std::vector<std::pair<TLanguage, std::string>> langInfo; 845b2a28edaSopenharmony_ci 846b2a28edaSopenharmony_ci langInfo.push_back(std::make_pair(ELangC, "spirv.h")); 847b2a28edaSopenharmony_ci langInfo.push_back(std::make_pair(ELangCPP, "spirv.hpp")); 848b2a28edaSopenharmony_ci langInfo.push_back(std::make_pair(ELangCPP11, "spirv.hpp11")); 849b2a28edaSopenharmony_ci langInfo.push_back(std::make_pair(ELangJSON, "spirv.json")); 850b2a28edaSopenharmony_ci langInfo.push_back(std::make_pair(ELangLua, "spirv.lua")); 851b2a28edaSopenharmony_ci langInfo.push_back(std::make_pair(ELangPython, "spirv.py")); 852b2a28edaSopenharmony_ci langInfo.push_back(std::make_pair(ELangCSharp, "spirv.cs")); 853b2a28edaSopenharmony_ci langInfo.push_back(std::make_pair(ELangD, "spv.d")); 854b2a28edaSopenharmony_ci langInfo.push_back(std::make_pair(ELangBeef, "spirv.bf")); 855b2a28edaSopenharmony_ci 856b2a28edaSopenharmony_ci for (const auto& lang : langInfo) { 857b2a28edaSopenharmony_ci std::ofstream out(lang.second, std::ios::out); 858b2a28edaSopenharmony_ci 859b2a28edaSopenharmony_ci if ((out.rdstate() & std::ifstream::failbit)) { 860b2a28edaSopenharmony_ci std::cerr << "Unable to open file: " << lang.second << std::endl; 861b2a28edaSopenharmony_ci } else { 862b2a28edaSopenharmony_ci PrintHeader(lang.first, out); 863b2a28edaSopenharmony_ci } 864b2a28edaSopenharmony_ci } 865b2a28edaSopenharmony_ci } 866b2a28edaSopenharmony_ci 867b2a28edaSopenharmony_ci // Print header for given language to given output stream 868b2a28edaSopenharmony_ci void PrintHeader(TLanguage lang, std::ostream& out) 869b2a28edaSopenharmony_ci { 870b2a28edaSopenharmony_ci typedef std::unique_ptr<TPrinter> TPrinterPtr; 871b2a28edaSopenharmony_ci TPrinterPtr p; 872b2a28edaSopenharmony_ci 873b2a28edaSopenharmony_ci switch (lang) { 874b2a28edaSopenharmony_ci case ELangC: p = TPrinterPtr(new TPrinterC); break; 875b2a28edaSopenharmony_ci case ELangCPP: p = TPrinterPtr(new TPrinterCPP); break; 876b2a28edaSopenharmony_ci case ELangCPP11: p = TPrinterPtr(new TPrinterCPP11); break; 877b2a28edaSopenharmony_ci case ELangJSON: p = TPrinterPtr(new TPrinterJSON); break; 878b2a28edaSopenharmony_ci case ELangLua: p = TPrinterPtr(new TPrinterLua); break; 879b2a28edaSopenharmony_ci case ELangPython: p = TPrinterPtr(new TPrinterPython); break; 880b2a28edaSopenharmony_ci case ELangCSharp: p = TPrinterPtr(new TPrinterCSharp); break; 881b2a28edaSopenharmony_ci case ELangD: p = TPrinterPtr(new TPrinterD); break; 882b2a28edaSopenharmony_ci case ELangBeef: p = TPrinterPtr(new TPrinterBeef); break; 883b2a28edaSopenharmony_ci case ELangAll: PrintAllHeaders(); break; 884b2a28edaSopenharmony_ci default: 885b2a28edaSopenharmony_ci std::cerr << "Unknown language." << std::endl; 886b2a28edaSopenharmony_ci return; 887b2a28edaSopenharmony_ci } 888b2a28edaSopenharmony_ci 889b2a28edaSopenharmony_ci // Print the data in the requested format 890b2a28edaSopenharmony_ci if (p) 891b2a28edaSopenharmony_ci out << *p << std::endl; 892b2a28edaSopenharmony_ci 893b2a28edaSopenharmony_ci // object is auto-deleted 894b2a28edaSopenharmony_ci } 895b2a28edaSopenharmony_ci 896b2a28edaSopenharmony_ci} // namespace spv 897