mirror of
https://gitee.com/openharmony/third_party_spirv-headers
synced 2025-02-17 05:58:00 +00:00
Add a header generator project.
This commit is contained in:
parent
6205884fb3
commit
7747a02cce
73
README.md
73
README.md
@ -1,40 +1,33 @@
|
||||
# SPIR-V Headers
|
||||
|
||||
This repository contains machine-readable files from the
|
||||
This repository contains machine-readable files for the
|
||||
[SPIR-V Registry](https://www.khronos.org/registry/spir-v/).
|
||||
This includes:
|
||||
|
||||
* Header files for various languages.
|
||||
* JSON files describing the grammar for the SPIR-V core instruction set,
|
||||
and for the GLSL.std.450 extended instruction set.
|
||||
* JSON files describing the grammar for the SPIR-V core instruction set
|
||||
and the extended instruction sets.
|
||||
* The XML registry file.
|
||||
* A tool to build the headers from the JSON grammar.
|
||||
|
||||
Under the [include](include) directory, header files are provided according to
|
||||
their own version. Only major and minor version numbers count.
|
||||
For example, the headers for SPIR-V 1.1 are in
|
||||
[include/spirv/1.1](include/spirv/1.1). Also, the headers for the 1.0 versions
|
||||
of the GLSL.std.450 and OpenCL extended instruction sets are in
|
||||
[include/spirv/1.0](include/spirv/1.0).
|
||||
Headers are provided in the [include](include) directory, with up-to-date
|
||||
headers in the `unified1` subdirectory. Older headers are provided according to
|
||||
their version.
|
||||
|
||||
In contrast, the XML registry file has a linear history, so it is
|
||||
not tied to SPIR-V specification versions.
|
||||
|
||||
## How is this repository updated?
|
||||
|
||||
When a new version or revision of the SPIR-V header files are published,
|
||||
the SPIR Working Group will push new commits onto master, updating
|
||||
When a new version or revision of the SPIR-V specification is published,
|
||||
the SPIR-V Working Group will push new commits onto master, updating
|
||||
the files under [include](include).
|
||||
A newer revision of a header file always replaces an older revision of
|
||||
the same version. For example, verison 1.0 Rev 4 of `spirv.h` is placed in
|
||||
`include/spirv/1.0/spirv.h` and if there is a Rev 5, then it will be placed
|
||||
in the same location.
|
||||
|
||||
The SPIR-V XML registry file is updated by the Khronos registrar whenever
|
||||
a new enum range is allocated.
|
||||
The SPIR-V XML registry file is updated by Khronos whenever a new enum range is allocated.
|
||||
|
||||
In particular, pull requests that update header files will not be accepted.
|
||||
Issues with the header files should be filed in the [issue
|
||||
tracker](https://github.com/KhronosGroup/SPIRV-Headers/issues).
|
||||
Pull requests can be made to
|
||||
- request allocation of new enum ranges in the XML registry file
|
||||
- reserve specific tokens in the JSON grammar
|
||||
|
||||
## How to install the headers
|
||||
|
||||
@ -48,7 +41,7 @@ cmake --build . --target install-headers
|
||||
cmake --build . --config Debug --target install-headers
|
||||
```
|
||||
|
||||
Then, for example, you will have `/usr/local/include/spirv/1.0/spirv.h`
|
||||
Then, for example, you will have `/usr/local/include/spirv/unified1/spirv.h`
|
||||
|
||||
If you want to install them somewhere else, then use
|
||||
`-DCMAKE_INSTALL_PREFIX=/other/path` on the first `cmake` command.
|
||||
@ -61,30 +54,40 @@ A CMake-based project can use the headers without installing, as follows:
|
||||
2. Use `${SPIRV-Headers_SOURCE_DIR}/include}` in a `target_include_directories`
|
||||
directive.
|
||||
3. In your C or C++ source code use `#include` directives that explicitly mention
|
||||
the `spirv` path component. For example the following uses SPIR-V 1.1
|
||||
core instructions, and the 1.0 versions of the GLSL.std.450 and OpenCL
|
||||
extended instructions.
|
||||
the `spirv` path component.
|
||||
```
|
||||
#include "spirv/1.0/GLSL.std.450.h"
|
||||
#include "spirv/1.0/OpenCL.std.h"
|
||||
#include "spirv/1.1/spirv.hpp"
|
||||
#include "spirv/unified1/GLSL.std.450.h"
|
||||
#include "spirv/unified1/OpenCL.std.h"
|
||||
#include "spirv/unified1/spirv.hpp"
|
||||
```
|
||||
|
||||
See also the [example](example/) subdirectory. But since that example is
|
||||
*inside* this repostory, it doesn't use and `add_subdirectory` directive.
|
||||
|
||||
## Generating the headers from the JSON grammar
|
||||
|
||||
This will generally be done by Khronos, for a change to the JSON grammar.
|
||||
However, the project for the tool to do this is included in this repository,
|
||||
and can be used to test a PR, or even to include the results in the PR.
|
||||
This is not required though.
|
||||
|
||||
The header-generation project is under the `buildHeaders` directory.
|
||||
Use CMake to build the project, in a `buildHeaders/build` subdirectory.
|
||||
There is a bash script at `buildHeaders/bin/makeHeaders` that shows how to use the built
|
||||
header-generator binary to generate the headers from the JSON grammar.
|
||||
|
||||
Notes:
|
||||
- this generator is used in a broader context within Khronos to generate the specification,
|
||||
and that influences the languages used, for legacy reasons
|
||||
- the C++ structures built may similarly include more than strictly necessary, for the same reason
|
||||
|
||||
## FAQ
|
||||
|
||||
* *How are different versions published?*
|
||||
|
||||
All versions are present in the master branch of the repository.
|
||||
They are located in different subdirectories under
|
||||
[include/spirv](include/spirv), where the subdirectory at that
|
||||
level encodes the major and minor version number of the relevant spec.
|
||||
|
||||
An application should consciously select the targeted spec version
|
||||
number, by naming the specific version in its `#include` directives,
|
||||
as above and in the examples.
|
||||
The multiple versions of the headers have been simplified into a
|
||||
single `unified1` view. The JSON grammar has a "version" field saying
|
||||
what version things first showed up in.
|
||||
|
||||
* *How do you handle the evolution of extended instruction sets?*
|
||||
|
||||
|
26
tools/buildHeaders/CMakeLists.txt
Executable file
26
tools/buildHeaders/CMakeLists.txt
Executable file
@ -0,0 +1,26 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(CMAKE_INSTALL_PREFIX "install" CACHE STRING "prefix" FORCE)
|
||||
|
||||
project(buildSpvHeaders)
|
||||
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
jsonToSpirv.cpp
|
||||
header.cpp
|
||||
jsoncpp/dist/jsoncpp.cpp)
|
||||
|
||||
set(HEADERS
|
||||
jsonToSpirv.h
|
||||
header.h
|
||||
jsoncpp/dist/json/json.h)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
add_definitions(-std=c++11)
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_definitions(-std=c++11)
|
||||
endif()
|
||||
|
||||
add_executable(buildSpvHeaders ${SOURCES} ${HEADERS})
|
||||
|
||||
install(TARGETS buildSpvHeaders RUNTIME DESTINATION bin)
|
5
tools/buildHeaders/bin/makeHeaders
Executable file
5
tools/buildHeaders/bin/makeHeaders
Executable file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
cd ../../include/spirv/unified1
|
||||
../../../tools/buildHeaders/build/install/bin/buildSpvHeaders -H spirv.core.grammar.json
|
||||
dos2unix spirv.*
|
713
tools/buildHeaders/header.cpp
Executable file
713
tools/buildHeaders/header.cpp
Executable file
@ -0,0 +1,713 @@
|
||||
// Copyright (c) 2014-2018 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and/or associated documentation files (the "Materials"),
|
||||
// to deal in the Materials without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Materials, and to permit persons to whom the
|
||||
// Materials are furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
// IN THE MATERIALS.
|
||||
|
||||
//
|
||||
// Print headers for SPIR-V in several languages.
|
||||
//
|
||||
// To change the header information, change the C++-built database in doc.*.
|
||||
//
|
||||
// Then, use "spriv -h <language>" - e.g, spriv.{h,hpp,lua,py,etc}:
|
||||
// replace the auto-generated header, or "spirv -H" to generate all
|
||||
// supported language headers to predefined names in the current directory.
|
||||
//
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <cctype>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "jsoncpp/dist/json/json.h"
|
||||
|
||||
#include "header.h"
|
||||
#include "jsonToSpirv.h"
|
||||
|
||||
// snprintf and _snprintf are not quite the same, but close enough
|
||||
// for our use.
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4996)
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
// This file converts SPIR-V definitions to an internal JSON
|
||||
// representation, and then generates language specific
|
||||
// data from that single internal form.
|
||||
|
||||
// Initially, the internal form is created from C++ data,
|
||||
// though this can be changed to a JSON master in time.
|
||||
|
||||
namespace {
|
||||
class TPrinter {
|
||||
protected:
|
||||
TPrinter();
|
||||
|
||||
static const int DocMagicNumber = 0x07230203;
|
||||
static const int DocVersion = 0x00010200;
|
||||
static const int DocRevision = 3;
|
||||
#define DocRevisionString "3"
|
||||
static const std::string DocCopyright;
|
||||
static const std::string DocComment1;
|
||||
static const std::string DocComment2;
|
||||
|
||||
enum enumStyle_t {
|
||||
enumNoMask,
|
||||
enumCount,
|
||||
enumShift,
|
||||
enumMask,
|
||||
enumHex,
|
||||
};
|
||||
|
||||
static std::string styleStr(enumStyle_t s) {
|
||||
return s == enumShift ? "Shift" :
|
||||
s == enumMask ? "Mask" : "";
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream&, const TPrinter&);
|
||||
|
||||
virtual void printAll(std::ostream&) const;
|
||||
virtual void printComments(std::ostream&) const;
|
||||
virtual void printPrologue(std::ostream&) const { }
|
||||
virtual void printDefs(std::ostream&) const;
|
||||
virtual void printEpilogue(std::ostream&) const { }
|
||||
virtual void printMeta(std::ostream&) const;
|
||||
virtual void printTypes(std::ostream&) const { }
|
||||
|
||||
virtual std::string escapeComment(const std::string& s) const;
|
||||
|
||||
// Default printComments() uses these comment strings
|
||||
virtual std::string commentBeg() const { return ""; }
|
||||
virtual std::string commentEnd(bool isLast) const { return ""; }
|
||||
virtual std::string commentBOL() const { return ""; }
|
||||
virtual std::string commentEOL(bool isLast) const { return ""; }
|
||||
|
||||
typedef std::pair<unsigned, std::string> valpair_t;
|
||||
|
||||
// for printing enum values
|
||||
virtual std::string enumBeg(const std::string&, enumStyle_t) const { return ""; }
|
||||
virtual std::string enumEnd(const std::string&, enumStyle_t, bool isLast = false) const {
|
||||
return "";
|
||||
}
|
||||
virtual std::string enumFmt(const std::string&, const valpair_t&,
|
||||
enumStyle_t, bool isLast = false) const {
|
||||
return "";
|
||||
}
|
||||
virtual std::string maxEnumFmt(const std::string&, const valpair_t&,
|
||||
enumStyle_t) const {
|
||||
return "";
|
||||
}
|
||||
|
||||
virtual std::string fmtConstInt(unsigned val, const std::string& name,
|
||||
const char* fmt, bool isLast = false) const {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::vector<valpair_t> getSortedVals(const Json::Value&) const;
|
||||
|
||||
virtual std::string indent(int count = 1) const {
|
||||
return std::string(count * 4, ' '); // default indent level = 4
|
||||
}
|
||||
|
||||
static std::string fmtNum(const char* fmt, unsigned val) {
|
||||
char buff[16]; // ample for 8 hex digits + 0x
|
||||
snprintf(buff, sizeof(buff), fmt, val);
|
||||
buff[sizeof(buff)-1] = '\0'; // MSVC doesn't promise null termination
|
||||
return buff;
|
||||
}
|
||||
|
||||
static std::string fmtStyleVal(unsigned v, enumStyle_t style);
|
||||
|
||||
// If the enum value name would start with a sigit, prepend the enum name.
|
||||
// E.g, "3D" -> "Dim3D".
|
||||
static std::string prependIfDigit(const std::string& ename, const std::string& vname) {
|
||||
return (std::isdigit(vname[0]) ? ename : std::string("")) + vname;
|
||||
}
|
||||
|
||||
void addComment(Json::Value& node, const std::string& str);
|
||||
|
||||
Json::Value spvRoot; // JSON SPIR-V data
|
||||
};
|
||||
|
||||
// Format value as mask or value
|
||||
std::string TPrinter::fmtStyleVal(unsigned v, enumStyle_t style)
|
||||
{
|
||||
switch (style) {
|
||||
case enumMask:
|
||||
return fmtNum("0x%08x", 1<<v);
|
||||
case enumHex:
|
||||
return fmtNum("0x%08x", v);
|
||||
default:
|
||||
return std::to_string(v);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string TPrinter::DocCopyright =
|
||||
"Copyright (c) 2014-2018 The Khronos Group Inc.\n"
|
||||
"\n"
|
||||
"Permission is hereby granted, free of charge, to any person obtaining a copy\n"
|
||||
"of this software and/or associated documentation files (the \"Materials\"),\n"
|
||||
"to deal in the Materials without restriction, including without limitation\n"
|
||||
"the rights to use, copy, modify, merge, publish, distribute, sublicense,\n"
|
||||
"and/or sell copies of the Materials, and to permit persons to whom the\n"
|
||||
"Materials are furnished to do so, subject to the following conditions:\n"
|
||||
"\n"
|
||||
"The above copyright notice and this permission notice shall be included in\n"
|
||||
"all copies or substantial portions of the Materials.\n"
|
||||
"\n"
|
||||
"MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS\n"
|
||||
"STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND\n"
|
||||
"HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ \n"
|
||||
"\n"
|
||||
"THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n"
|
||||
"OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
|
||||
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n"
|
||||
"THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"
|
||||
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n"
|
||||
"FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS\n"
|
||||
"IN THE MATERIALS.\n";
|
||||
|
||||
const std::string TPrinter::DocComment1 =
|
||||
"This header is automatically generated by the same tool that creates\n"
|
||||
"the Binary Section of the SPIR-V specification.\n";
|
||||
|
||||
const std::string TPrinter::DocComment2 =
|
||||
"Enumeration tokens for SPIR-V, in various styles:\n"
|
||||
" C, C++, C++11, JSON, Lua, Python\n"
|
||||
"\n"
|
||||
"- C will have tokens with a \"Spv\" prefix, e.g.: SpvSourceLanguageGLSL\n"
|
||||
"- C++ will have tokens in the \"spv\" name space, e.g.: spv::SourceLanguageGLSL\n"
|
||||
"- C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL\n"
|
||||
"- Lua will use tables, e.g.: spv.SourceLanguage.GLSL\n"
|
||||
"- Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']\n"
|
||||
"\n"
|
||||
"Some tokens act like mask values, which can be OR'd together,\n"
|
||||
"while others are mutually exclusive. The mask-like ones have\n"
|
||||
"\"Mask\" in their name, and a parallel enum that has the shift\n"
|
||||
"amount (1 << x) for each corresponding enumerant.\n";
|
||||
|
||||
// Construct
|
||||
TPrinter::TPrinter()
|
||||
{
|
||||
Json::Value& meta = spvRoot["spv"]["meta"];
|
||||
Json::Value& enums = spvRoot["spv"]["enum"];
|
||||
|
||||
meta["MagicNumber"] = DocMagicNumber;
|
||||
meta["Version"] = DocVersion;
|
||||
meta["Revision"] = DocRevision;
|
||||
meta["OpCodeMask"] = 0xffff;
|
||||
meta["WordCountShift"] = 16;
|
||||
|
||||
int commentId = 0;
|
||||
addComment(meta["Comment"][commentId++], DocCopyright);
|
||||
addComment(meta["Comment"][commentId++], DocComment1);
|
||||
addComment(meta["Comment"][commentId++], DocComment2);
|
||||
|
||||
for (int e = spv::OperandSource; e < spv::OperandOpcode; ++e) {
|
||||
auto& enumSet = spv::OperandClassParams[e];
|
||||
const bool mask = enumSet.bitmask;
|
||||
const std::string enumName = enumSet.codeName;
|
||||
|
||||
for (auto& enumRow : enumSet) {
|
||||
std::string name = enumRow.name;
|
||||
enums[e - spv::OperandSource]["Values"][name] = enumRow.value;
|
||||
}
|
||||
|
||||
enums[e - spv::OperandSource]["Type"] = mask ? "Bit" : "Value";
|
||||
enums[e - spv::OperandSource]["Name"] = enumName;
|
||||
}
|
||||
|
||||
// Instructions are in their own different table
|
||||
{
|
||||
auto& entry = enums[spv::OperandOpcode - spv::OperandSource];
|
||||
for (auto& enumRow : spv::InstructionDesc) {
|
||||
std::string name = enumRow.name;
|
||||
entry["Values"][name] = enumRow.value;
|
||||
}
|
||||
entry["Type"] = "Value";
|
||||
entry["Name"] = "Op";
|
||||
}
|
||||
}
|
||||
|
||||
// Create comment
|
||||
void TPrinter::addComment(Json::Value& node, const std::string& str)
|
||||
{
|
||||
std::istringstream cstream(str);
|
||||
std::string cline;
|
||||
|
||||
int line = 0;
|
||||
while (std::getline(cstream, cline)) // fmt each line
|
||||
node[line++] = cline;
|
||||
}
|
||||
|
||||
|
||||
// Return a list of values sorted by enum value. The std::vector
|
||||
// returned by value is okay in c++11 due to move semantics.
|
||||
std::vector<TPrinter::valpair_t>
|
||||
TPrinter::getSortedVals(const Json::Value& p) const
|
||||
{
|
||||
std::vector<valpair_t> values;
|
||||
|
||||
for (auto e = p.begin(); e != p.end(); ++e)
|
||||
values.push_back(valpair_t(e->asUInt(), e.name()));
|
||||
|
||||
// Use a stable sort because we might have aliases, e.g.
|
||||
// SubgropuBallot (might be in future core) vs. SubgroupBallotKHR.
|
||||
std::stable_sort(values.begin(), values.end());
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
// Escape comment characters if needed
|
||||
std::string TPrinter::escapeComment(const std::string& s) const { return s; }
|
||||
|
||||
// Format comments in language specific way
|
||||
void TPrinter::printComments(std::ostream& out) const
|
||||
{
|
||||
const int commentCount = spvRoot["spv"]["meta"]["Comment"].size();
|
||||
int commentNum = 0;
|
||||
|
||||
for (const auto& comment : spvRoot["spv"]["meta"]["Comment"]) {
|
||||
out << commentBeg();
|
||||
|
||||
for (int line = 0; line < int(comment.size()); ++line)
|
||||
out << commentBOL() << escapeComment(comment[line].asString()) <<
|
||||
commentEOL((line+1) == comment.size()) << std::endl;
|
||||
|
||||
out << commentEnd(++commentNum == commentCount) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Format header metadata
|
||||
void TPrinter::printMeta(std::ostream& out) const
|
||||
{
|
||||
const Json::Value& meta = spvRoot["spv"]["meta"];
|
||||
|
||||
const auto print = [&](const char* name, const char* fmt, bool isLast) {
|
||||
out << fmtConstInt(meta[name].asUInt(), name, fmt, isLast);
|
||||
};
|
||||
|
||||
print("MagicNumber", "0x%08lx", false);
|
||||
print("Version", "0x%08lx", false);
|
||||
print("Revision", "%d", false);
|
||||
print("OpCodeMask", "0x%04x", false);
|
||||
print("WordCountShift", "%d", true);
|
||||
}
|
||||
|
||||
// Format value definitions in language specific way
|
||||
void TPrinter::printDefs(std::ostream& out) const
|
||||
{
|
||||
const Json::Value& enums = spvRoot["spv"]["enum"];
|
||||
|
||||
for (auto opClass = enums.begin(); opClass != enums.end(); ++opClass) {
|
||||
const bool isMask = (*opClass)["Type"].asString() == "Bit";
|
||||
const auto opName = (*opClass)["Name"].asString();
|
||||
const auto opPrefix = opName == "Op" ? "" : opName;
|
||||
|
||||
for (enumStyle_t style = (isMask ? enumShift : enumCount);
|
||||
style <= (isMask ? enumMask : enumCount); style = enumStyle_t(int(style)+1)) {
|
||||
|
||||
out << enumBeg(opName, style);
|
||||
|
||||
if (style == enumMask)
|
||||
out << enumFmt(opPrefix, valpair_t(0, "MaskNone"), enumNoMask);
|
||||
|
||||
const auto sorted = getSortedVals((*opClass)["Values"]);
|
||||
|
||||
std::string maxEnum = maxEnumFmt(opName, valpair_t(0x7FFFFFFF, "Max"), enumHex);
|
||||
|
||||
bool printMax = (style != enumMask && maxEnum.size() > 0);
|
||||
|
||||
for (const auto& v : sorted)
|
||||
out << enumFmt(opPrefix, v, style, !printMax && v.first == sorted.back().first);
|
||||
|
||||
if (printMax)
|
||||
out << maxEnum;
|
||||
|
||||
auto nextOpClass = opClass;
|
||||
out << enumEnd(opName, style, ++nextOpClass == enums.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TPrinter::printAll(std::ostream& out) const
|
||||
{
|
||||
printComments(out);
|
||||
printPrologue(out);
|
||||
printTypes(out);
|
||||
printMeta(out);
|
||||
printDefs(out);
|
||||
printEpilogue(out);
|
||||
}
|
||||
|
||||
// Stream entire header to output
|
||||
std::ostream& operator<<(std::ostream& out, const TPrinter &p)
|
||||
{
|
||||
p.printAll(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// JSON printer. Rather than use the default printer, we supply our own so
|
||||
// we can control the printing order within various containers.
|
||||
class TPrinterJSON final : public TPrinter {
|
||||
private:
|
||||
void printPrologue(std::ostream& out) const override { out << "{\n" + indent() + "\"spv\":\n" + indent() + "{\n"; }
|
||||
void printEpilogue(std::ostream& out) const override { out << indent() + "}\n}\n"; }
|
||||
|
||||
std::string escapeComment(const std::string& s) const override {
|
||||
std::string newStr;
|
||||
for (auto c : s) {
|
||||
if (c == '"') {
|
||||
newStr += '\\';
|
||||
newStr += c;
|
||||
} else {
|
||||
newStr += c;
|
||||
}
|
||||
}
|
||||
return newStr;
|
||||
}
|
||||
|
||||
std::string fmtConstInt(unsigned val, const std::string& name,
|
||||
const char* fmt, bool isLast) const override {
|
||||
return indent(3) + '"' + name + "\": " + fmtNum("%d", val) + (isLast ? "\n" : ",\n");
|
||||
}
|
||||
|
||||
void printMeta(std::ostream& out) const override
|
||||
{
|
||||
out << indent(2) + "\"meta\":\n" + indent(2) + "{\n";
|
||||
printComments(out);
|
||||
TPrinter::printMeta(out);
|
||||
out << indent(2) + "},\n";
|
||||
}
|
||||
|
||||
std::string commentBeg() const override { return indent(4) + "[\n"; }
|
||||
std::string commentEnd(bool isLast) const override { return indent(4) + (isLast ? "]" : "],"); }
|
||||
std::string commentBOL() const override { return indent(5) + '"'; }
|
||||
std::string commentEOL(bool isLast) const override { return (isLast ? "\"" : "\","); }
|
||||
|
||||
void printComments(std::ostream& out) const override
|
||||
{
|
||||
out << indent(3) + "\"Comment\":\n" + indent(3) + "[\n";
|
||||
TPrinter::printComments(out);
|
||||
out << indent(3) + "],\n";
|
||||
}
|
||||
|
||||
void printDefs(std::ostream& out) const override
|
||||
{
|
||||
out << indent(2) + "\"enum\":\n" + indent(2) + "[\n";
|
||||
TPrinter::printDefs(out);
|
||||
out << indent(2) + "]\n";
|
||||
}
|
||||
|
||||
void printAll(std::ostream& out) const override
|
||||
{
|
||||
printPrologue(out);
|
||||
printMeta(out);
|
||||
printDefs(out);
|
||||
printEpilogue(out);
|
||||
}
|
||||
|
||||
std::string enumBeg(const std::string& s, enumStyle_t style) const override {
|
||||
if (style == enumMask)
|
||||
return "";
|
||||
return indent(3) + "{\n" +
|
||||
indent(4) + "\"Name\": \"" + s + "\",\n" +
|
||||
indent(4) + "\"Type\": " + (style == enumShift ? "\"Bit\"" : "\"Value\"") + ",\n" +
|
||||
indent(4) + "\"Values\":\n" +
|
||||
indent(4) + "{\n";
|
||||
}
|
||||
|
||||
std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override {
|
||||
if (style == enumMask)
|
||||
return "";
|
||||
return indent(4) + "}\n" +
|
||||
indent(3) + "}" + (isLast ? "" : ",") + "\n";
|
||||
}
|
||||
|
||||
std::string enumFmt(const std::string& s, const valpair_t& v,
|
||||
enumStyle_t style, bool isLast) const override {
|
||||
if (style == enumMask || style == enumNoMask)
|
||||
return "";
|
||||
return indent(5) + '"' + prependIfDigit(s, v.second) + "\": " + fmtNum("%d", v.first) +
|
||||
(isLast ? "\n" : ",\n");
|
||||
}
|
||||
};
|
||||
|
||||
// base for C and C++
|
||||
class TPrinterCBase : public TPrinter {
|
||||
protected:
|
||||
virtual void printPrologue(std::ostream& out) const override {
|
||||
out << "#ifndef spirv_" << headerGuardSuffix() << std::endl
|
||||
<< "#define spirv_" << headerGuardSuffix() << std::endl
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void printMeta(std::ostream& out) const override {
|
||||
out << "#define SPV_VERSION 0x" << std::hex << DocVersion << std::dec << "\n";
|
||||
out << "#define SPV_REVISION " << DocRevision << "\n";
|
||||
out << "\n";
|
||||
|
||||
return TPrinter::printMeta(out);
|
||||
}
|
||||
|
||||
virtual void printEpilogue(std::ostream& out) const override {
|
||||
out << "#endif // #ifndef spirv_" << headerGuardSuffix() << std::endl;
|
||||
}
|
||||
|
||||
virtual void printTypes(std::ostream& out) const override {
|
||||
out << "typedef unsigned int " << pre() << "Id;\n\n";
|
||||
}
|
||||
|
||||
virtual std::string fmtConstInt(unsigned val, const std::string& name,
|
||||
const char* fmt, bool isLast) const override
|
||||
{
|
||||
return std::string("static const unsigned int ") + pre() + name +
|
||||
" = " + fmtNum(fmt, val) + (isLast ? ";\n\n" : ";\n");
|
||||
}
|
||||
|
||||
virtual std::string pre() const { return ""; } // C name prefix
|
||||
virtual std::string headerGuardSuffix() const = 0;
|
||||
};
|
||||
|
||||
// C printer
|
||||
class TPrinterC final : public TPrinterCBase {
|
||||
private:
|
||||
std::string commentBeg() const override { return "/*\n"; }
|
||||
std::string commentEnd(bool isLast) const override { return "*/\n"; }
|
||||
std::string commentBOL() const override { return "** "; }
|
||||
|
||||
std::string enumBeg(const std::string& s, enumStyle_t style) const override {
|
||||
return std::string("typedef enum ") + pre() + s + styleStr(style) + "_ {\n";
|
||||
}
|
||||
|
||||
std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override {
|
||||
return "} " + pre() + s + styleStr(style) + ";\n\n";
|
||||
}
|
||||
|
||||
std::string enumFmt(const std::string& s, const valpair_t& v,
|
||||
enumStyle_t style, bool isLast) const override {
|
||||
return indent() + pre() + s + v.second + styleStr(style) + " = " + fmtStyleVal(v.first, style) + ",\n";
|
||||
}
|
||||
|
||||
std::string maxEnumFmt(const std::string& s, const valpair_t& v,
|
||||
enumStyle_t style) const override {
|
||||
return enumFmt(s, v, style, true);
|
||||
}
|
||||
|
||||
std::string pre() const override { return "Spv"; } // C name prefix
|
||||
std::string headerGuardSuffix() const override { return "H"; }
|
||||
};
|
||||
|
||||
// C++ printer
|
||||
class TPrinterCPP : public TPrinterCBase {
|
||||
private:
|
||||
void printPrologue(std::ostream& out) const override {
|
||||
TPrinterCBase::printPrologue(out);
|
||||
out << "namespace spv {\n\n";
|
||||
}
|
||||
|
||||
void printEpilogue(std::ostream& out) const override {
|
||||
const Json::Value& enums = spvRoot["spv"]["enum"];
|
||||
|
||||
// Create overloaded operator| for mask types
|
||||
out << "// Overload operator| for mask bit combining\n\n";
|
||||
|
||||
for (auto opClass = enums.begin(); opClass != enums.end(); ++opClass) {
|
||||
const bool isMask = (*opClass)["Type"].asString() == "Bit";
|
||||
const auto opName = (*opClass)["Name"].asString();
|
||||
|
||||
if (isMask) {
|
||||
const auto typeName = opName + styleStr(enumMask);
|
||||
|
||||
out << "inline " + typeName + " operator|(" + typeName + " a, " + typeName + " b) { return " +
|
||||
typeName + "(unsigned(a) | unsigned(b)); }\n";
|
||||
}
|
||||
}
|
||||
|
||||
out << "\n} // end namespace spv\n\n";
|
||||
TPrinterCBase::printEpilogue(out);
|
||||
}
|
||||
|
||||
std::string commentBOL() const override { return "// "; }
|
||||
|
||||
|
||||
virtual std::string enumBeg(const std::string& s, enumStyle_t style) const override {
|
||||
return std::string("enum ") + s + styleStr(style) + " {\n";
|
||||
}
|
||||
|
||||
std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override {
|
||||
return "};\n\n";
|
||||
}
|
||||
|
||||
virtual std::string enumFmt(const std::string& s, const valpair_t& v,
|
||||
enumStyle_t style, bool isLast) const override {
|
||||
return indent() + s + v.second + styleStr(style) + " = " + fmtStyleVal(v.first, style) + ",\n";
|
||||
}
|
||||
|
||||
virtual std::string maxEnumFmt(const std::string& s, const valpair_t& v,
|
||||
enumStyle_t style) const override {
|
||||
return enumFmt(s, v, style, true);
|
||||
}
|
||||
|
||||
// The C++ and C++11 headers define types with the same name. So they
|
||||
// should use the same header guard.
|
||||
std::string headerGuardSuffix() const override { return "HPP"; }
|
||||
|
||||
std::string operators;
|
||||
};
|
||||
|
||||
// C++11 printer (uses enum classes)
|
||||
class TPrinterCPP11 final : public TPrinterCPP {
|
||||
private:
|
||||
std::string enumBeg(const std::string& s, enumStyle_t style) const override {
|
||||
return std::string("enum class ") + s + styleStr(style) + " : unsigned {\n";
|
||||
}
|
||||
|
||||
std::string enumFmt(const std::string& s, const valpair_t& v,
|
||||
enumStyle_t style, bool isLast) const override {
|
||||
return indent() + prependIfDigit(s, v.second) + " = " + fmtStyleVal(v.first, style) + ",\n";
|
||||
}
|
||||
|
||||
std::string maxEnumFmt(const std::string& s, const valpair_t& v,
|
||||
enumStyle_t style) const override {
|
||||
return enumFmt(s, v, style, true);
|
||||
}
|
||||
|
||||
std::string headerGuardSuffix() const override { return "HPP"; }
|
||||
};
|
||||
|
||||
// LUA printer
|
||||
class TPrinterLua final : public TPrinter {
|
||||
private:
|
||||
void printPrologue(std::ostream& out) const override { out << "spv = {\n"; }
|
||||
|
||||
void printEpilogue(std::ostream& out) const override { out << "}\n"; }
|
||||
|
||||
std::string commentBOL() const override { return "-- "; }
|
||||
|
||||
std::string enumBeg(const std::string& s, enumStyle_t style) const override {
|
||||
return indent() + s + styleStr(style) + " = {\n";
|
||||
}
|
||||
|
||||
std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override {
|
||||
return indent() + "},\n\n";
|
||||
}
|
||||
|
||||
std::string enumFmt(const std::string& s, const valpair_t& v,
|
||||
enumStyle_t style, bool isLast) const override {
|
||||
return indent(2) + prependIfDigit(s, v.second) + " = " + fmtStyleVal(v.first, style) + ",\n";
|
||||
}
|
||||
|
||||
virtual std::string fmtConstInt(unsigned val, const std::string& name,
|
||||
const char* fmt, bool isLast) const override
|
||||
{
|
||||
return indent() + name + " = " + fmtNum(fmt, val) + (isLast ? ",\n\n" : ",\n");
|
||||
}
|
||||
};
|
||||
|
||||
// Python printer
|
||||
class TPrinterPython final : public TPrinter {
|
||||
private:
|
||||
void printPrologue(std::ostream& out) const override { out << "spv = {\n"; }
|
||||
|
||||
void printEpilogue(std::ostream& out) const override { out << "}\n"; }
|
||||
|
||||
std::string commentBOL() const override { return "# "; }
|
||||
|
||||
std::string enumBeg(const std::string& s, enumStyle_t style) const override {
|
||||
return indent() + "'" + s + styleStr(style) + "'" + " : {\n";
|
||||
}
|
||||
|
||||
std::string enumEnd(const std::string& s, enumStyle_t style, bool isLast) const override {
|
||||
return indent() + "},\n\n";
|
||||
}
|
||||
|
||||
std::string enumFmt(const std::string& s, const valpair_t& v,
|
||||
enumStyle_t style, bool isLast) const override {
|
||||
return indent(2) + "'" + prependIfDigit(s, v.second) + "'" + " : " + fmtStyleVal(v.first, style) + ",\n";
|
||||
}
|
||||
|
||||
std::string fmtConstInt(unsigned val, const std::string& name,
|
||||
const char* fmt, bool isLast) const override
|
||||
{
|
||||
return indent() + "'" + name + "'" + " : " + fmtNum(fmt, val) + (isLast ? ",\n\n" : ",\n");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace spv {
|
||||
void PrintAllHeaders()
|
||||
{
|
||||
// TODO: Once MSVC 2012 is no longer a factor, use brace initializers here
|
||||
std::vector<std::pair<TLanguage, std::string>> langInfo;
|
||||
|
||||
langInfo.push_back(std::make_pair(ELangC, "spirv.h"));
|
||||
langInfo.push_back(std::make_pair(ELangCPP, "spirv.hpp"));
|
||||
langInfo.push_back(std::make_pair(ELangCPP11, "spirv.hpp11"));
|
||||
langInfo.push_back(std::make_pair(ELangJSON, "spirv.json"));
|
||||
langInfo.push_back(std::make_pair(ELangLua, "spirv.lua"));
|
||||
langInfo.push_back(std::make_pair(ELangPython, "spirv.py"));
|
||||
|
||||
for (const auto& lang : langInfo) {
|
||||
std::ofstream out(lang.second, std::ios::out);
|
||||
|
||||
if ((out.rdstate() & std::ifstream::failbit)) {
|
||||
std::cerr << "Unable to open file: " << lang.second << std::endl;
|
||||
} else {
|
||||
PrintHeader(lang.first, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print header for given language to given output stream
|
||||
void PrintHeader(TLanguage lang, std::ostream& out)
|
||||
{
|
||||
typedef std::unique_ptr<TPrinter> TPrinterPtr;
|
||||
TPrinterPtr p;
|
||||
|
||||
switch (lang) {
|
||||
case ELangC: p = TPrinterPtr(new TPrinterC); break;
|
||||
case ELangCPP: p = TPrinterPtr(new TPrinterCPP); break;
|
||||
case ELangCPP11: p = TPrinterPtr(new TPrinterCPP11); break;
|
||||
case ELangJSON: p = TPrinterPtr(new TPrinterJSON); break;
|
||||
case ELangLua: p = TPrinterPtr(new TPrinterLua); break;
|
||||
case ELangPython: p = TPrinterPtr(new TPrinterPython); break;
|
||||
case ELangAll: PrintAllHeaders(); break;
|
||||
default:
|
||||
std::cerr << "Unknown language." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Print the data in the requested format
|
||||
if (p)
|
||||
out << *p << std::endl;
|
||||
|
||||
// object is auto-deleted
|
||||
}
|
||||
|
||||
} // namespace spv
|
52
tools/buildHeaders/header.h
Executable file
52
tools/buildHeaders/header.h
Executable file
@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2014-2018 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and/or associated documentation files (the "Materials"),
|
||||
// to deal in the Materials without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Materials, and to permit persons to whom the
|
||||
// Materials are furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
// IN THE MATERIALS.
|
||||
|
||||
//
|
||||
// Print headers for SPIR-V in several languages.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef header
|
||||
#define header
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace spv {
|
||||
// Languages supported
|
||||
enum TLanguage {
|
||||
ELangC, // C
|
||||
ELangCPP, // C++03
|
||||
ELangCPP11, // C++11
|
||||
ELangJSON, // JSON
|
||||
ELangLua, // Lua
|
||||
ELangPython, // Python
|
||||
|
||||
ELangAll, // print headers in all languages to files
|
||||
};
|
||||
|
||||
// Generate header for requested language
|
||||
void PrintHeader(TLanguage, std::ostream&);
|
||||
} // namespace spv
|
||||
|
||||
#endif // header
|
437
tools/buildHeaders/jsonToSpirv.cpp
Executable file
437
tools/buildHeaders/jsonToSpirv.cpp
Executable file
@ -0,0 +1,437 @@
|
||||
// Copyright (c) 2014-2018 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and/or associated documentation files (the "Materials"),
|
||||
// to deal in the Materials without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Materials, and to permit persons to whom the
|
||||
// Materials are furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
// IN THE MATERIALS.
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <fstream>
|
||||
|
||||
#include "jsoncpp/dist/json/json.h"
|
||||
|
||||
#include "jsonToSpirv.h"
|
||||
|
||||
namespace spv {
|
||||
|
||||
// The set of objects that hold all the instruction/operand
|
||||
// parameterization information.
|
||||
InstructionValues InstructionDesc;
|
||||
|
||||
// Note: There is no entry for OperandOpcode. Use InstructionDesc instead.
|
||||
EnumDefinition OperandClassParams[OperandOpcode];
|
||||
EnumValues SourceLanguageParams;
|
||||
EnumValues ExecutionModelParams;
|
||||
EnumValues AddressingParams;
|
||||
EnumValues MemoryParams;
|
||||
EnumValues ExecutionModeParams;
|
||||
EnumValues StorageParams;
|
||||
EnumValues SamplerAddressingModeParams;
|
||||
EnumValues SamplerFilterModeParams;
|
||||
EnumValues ImageFormatParams;
|
||||
EnumValues ImageChannelOrderParams;
|
||||
EnumValues ImageChannelDataTypeParams;
|
||||
EnumValues ImageOperandsParams;
|
||||
EnumValues FPFastMathParams;
|
||||
EnumValues FPRoundingModeParams;
|
||||
EnumValues LinkageTypeParams;
|
||||
EnumValues DecorationParams;
|
||||
EnumValues BuiltInParams;
|
||||
EnumValues DimensionalityParams;
|
||||
EnumValues FuncParamAttrParams;
|
||||
EnumValues AccessQualifierParams;
|
||||
EnumValues GroupOperationParams;
|
||||
EnumValues LoopControlParams;
|
||||
EnumValues SelectionControlParams;
|
||||
EnumValues FunctionControlParams;
|
||||
EnumValues MemorySemanticsParams;
|
||||
EnumValues MemoryAccessParams;
|
||||
EnumValues ScopeParams;
|
||||
EnumValues KernelEnqueueFlagsParams;
|
||||
EnumValues KernelProfilingInfoParams;
|
||||
EnumValues CapabilityParams;
|
||||
|
||||
std::pair<bool, std::string> ReadFile(const std::string& path)
|
||||
{
|
||||
std::ifstream fstream(path, std::ios::in);
|
||||
if (fstream) {
|
||||
std::string contents;
|
||||
fstream.seekg(0, std::ios::end);
|
||||
contents.reserve((unsigned int)fstream.tellg());
|
||||
fstream.seekg(0, std::ios::beg);
|
||||
contents.assign((std::istreambuf_iterator<char>(fstream)),
|
||||
std::istreambuf_iterator<char>());
|
||||
return std::make_pair(true, contents);
|
||||
}
|
||||
return std::make_pair(false, "");
|
||||
}
|
||||
|
||||
struct ClassOptionality {
|
||||
OperandClass type;
|
||||
bool optional;
|
||||
};
|
||||
|
||||
// Converts the |operandKind| and |quantifier| pair used to describe operands
|
||||
// in the JSON grammar to OperandClass and optionality used in this repo.
|
||||
ClassOptionality ToOperandClassAndOptionality(const std::string& operandKind, const std::string& quantifier)
|
||||
{
|
||||
assert(quantifier.empty() || quantifier == "?" || quantifier == "*");
|
||||
|
||||
if (operandKind == "IdRef") {
|
||||
if (quantifier.empty())
|
||||
return {OperandId, false};
|
||||
else if (quantifier == "?")
|
||||
return {OperandId, true};
|
||||
else
|
||||
return {OperandVariableIds, false};
|
||||
} else if (operandKind == "LiteralInteger") {
|
||||
if (quantifier.empty())
|
||||
return {OperandLiteralNumber, false};
|
||||
if (quantifier == "?")
|
||||
return {OperandOptionalLiteral, true};
|
||||
else
|
||||
return {OperandVariableLiterals, false};
|
||||
} else if (operandKind == "LiteralString") {
|
||||
if (quantifier.empty())
|
||||
return {OperandLiteralString, false};
|
||||
else if (quantifier == "?")
|
||||
return {OperandLiteralString, true};
|
||||
else {
|
||||
assert(0 && "this case should not exist");
|
||||
return {OperandNone, false};
|
||||
}
|
||||
} else if (operandKind == "PairLiteralIntegerIdRef") {
|
||||
// Used by OpSwitch in the grammar
|
||||
return {OperandVariableLiteralId, false};
|
||||
} else if (operandKind == "PairIdRefLiteralInteger") {
|
||||
// Used by OpGroupMemberDecorate in the grammar
|
||||
return {OperandVariableIdLiteral, false};
|
||||
} else if (operandKind == "PairIdRefIdRef") {
|
||||
// Used by OpPhi in the grammar
|
||||
return {OperandVariableIds, false};
|
||||
} else {
|
||||
OperandClass type = OperandNone;
|
||||
if (operandKind == "IdMemorySemantics" || operandKind == "MemorySemantics") {
|
||||
type = OperandMemorySemantics;
|
||||
} else if (operandKind == "IdScope" || operandKind == "Scope") {
|
||||
type = OperandScope;
|
||||
} else if (operandKind == "LiteralExtInstInteger") {
|
||||
type = OperandLiteralNumber;
|
||||
} else if (operandKind == "LiteralSpecConstantOpInteger") {
|
||||
type = OperandLiteralNumber;
|
||||
} else if (operandKind == "LiteralContextDependentNumber") {
|
||||
type = OperandVariableLiterals;
|
||||
} else if (operandKind == "SourceLanguage") {
|
||||
type = OperandSource;
|
||||
} else if (operandKind == "ExecutionModel") {
|
||||
type = OperandExecutionModel;
|
||||
} else if (operandKind == "AddressingModel") {
|
||||
type = OperandAddressing;
|
||||
} else if (operandKind == "MemoryModel") {
|
||||
type = OperandMemory;
|
||||
} else if (operandKind == "ExecutionMode") {
|
||||
type = OperandExecutionMode;
|
||||
} else if (operandKind == "StorageClass") {
|
||||
type = OperandStorage;
|
||||
} else if (operandKind == "Dim") {
|
||||
type = OperandDimensionality;
|
||||
} else if (operandKind == "SamplerAddressingMode") {
|
||||
type = OperandSamplerAddressingMode;
|
||||
} else if (operandKind == "SamplerFilterMode") {
|
||||
type = OperandSamplerFilterMode;
|
||||
} else if (operandKind == "ImageFormat") {
|
||||
type = OperandSamplerImageFormat;
|
||||
} else if (operandKind == "ImageChannelOrder") {
|
||||
type = OperandImageChannelOrder;
|
||||
} else if (operandKind == "ImageChannelDataType") {
|
||||
type = OperandImageChannelDataType;
|
||||
} else if (operandKind == "FPRoundingMode") {
|
||||
type = OperandFPRoundingMode;
|
||||
} else if (operandKind == "LinkageType") {
|
||||
type = OperandLinkageType;
|
||||
} else if (operandKind == "AccessQualifier") {
|
||||
type = OperandAccessQualifier;
|
||||
} else if (operandKind == "FunctionParameterAttribute") {
|
||||
type = OperandFuncParamAttr;
|
||||
} else if (operandKind == "Decoration") {
|
||||
type = OperandDecoration;
|
||||
} else if (operandKind == "BuiltIn") {
|
||||
type = OperandBuiltIn;
|
||||
} else if (operandKind == "GroupOperation") {
|
||||
type = OperandGroupOperation;
|
||||
} else if (operandKind == "KernelEnqueueFlags") {
|
||||
type = OperandKernelEnqueueFlags;
|
||||
} else if (operandKind == "KernelProfilingInfo") {
|
||||
type = OperandKernelProfilingInfo;
|
||||
} else if (operandKind == "Capability") {
|
||||
type = OperandCapability;
|
||||
} else if (operandKind == "ImageOperands") {
|
||||
type = OperandImageOperands;
|
||||
} else if (operandKind == "FPFastMathMode") {
|
||||
type = OperandFPFastMath;
|
||||
} else if (operandKind == "SelectionControl") {
|
||||
type = OperandSelect;
|
||||
} else if (operandKind == "LoopControl") {
|
||||
type = OperandLoop;
|
||||
} else if (operandKind == "FunctionControl") {
|
||||
type = OperandFunction;
|
||||
} else if (operandKind == "MemoryAccess") {
|
||||
type = OperandMemoryAccess;
|
||||
}
|
||||
|
||||
if (type == OperandNone) {
|
||||
std::cerr << "Unhandled operand kind found: " << operandKind << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
return {type, !quantifier.empty()};
|
||||
}
|
||||
}
|
||||
|
||||
bool IsTypeOrResultId(const std::string& str, bool* isType, bool* isResult)
|
||||
{
|
||||
if (str == "IdResultType")
|
||||
return *isType = true;
|
||||
if (str == "IdResult")
|
||||
return *isResult = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Given a number string, returns the position of the only bits set in the number.
|
||||
// So it requires the number is a power of two.
|
||||
unsigned int NumberStringToBit(const std::string& str)
|
||||
{
|
||||
char* parseEnd;
|
||||
unsigned int value = (unsigned int)std::strtol(str.c_str(), &parseEnd, 16);
|
||||
assert(!(value & (value - 1)) && "input number is not a power of 2");
|
||||
unsigned int bit = 0;
|
||||
for (; value; value >>= 1) ++bit;
|
||||
return bit;
|
||||
}
|
||||
|
||||
void jsonToSpirv(const std::string& jsonPath)
|
||||
{
|
||||
// only do this once.
|
||||
static bool initialized = false;
|
||||
if (initialized)
|
||||
return;
|
||||
initialized = true;
|
||||
|
||||
// Read the JSON grammar file.
|
||||
bool fileReadOk = false;
|
||||
std::string content;
|
||||
std::tie(fileReadOk, content) = ReadFile(jsonPath);
|
||||
if (!fileReadOk) {
|
||||
std::cerr << "Failed to read JSON grammar file: "
|
||||
<< jsonPath << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Decode the JSON grammar file.
|
||||
Json::Reader reader;
|
||||
Json::Value root;
|
||||
if (!reader.parse(content, root)) {
|
||||
std::cerr << "Failed to parse JSON grammar:\n"
|
||||
<< reader.getFormattedErrorMessages();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Layouts for all instructions.
|
||||
|
||||
// A lambda for returning capabilities from a JSON object as strings.
|
||||
const auto getCaps = [](const Json::Value& object) {
|
||||
EnumCaps result;
|
||||
const auto& caps = object["capabilities"];
|
||||
if (!caps.empty()) {
|
||||
assert(caps.isArray());
|
||||
for (const auto& cap : caps) {
|
||||
result.emplace_back(cap.asString());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// A lambda for returning extensions from a JSON object as strings.
|
||||
const auto getExts = [](const Json::Value& object) {
|
||||
Extensions result;
|
||||
const auto& exts = object["extensions"];
|
||||
if (!exts.empty()) {
|
||||
assert(exts.isArray());
|
||||
for (const auto& ext : exts) {
|
||||
result.emplace_back(ext.asString());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const Json::Value insts = root["instructions"];
|
||||
for (const auto& inst : insts) {
|
||||
const unsigned int opcode = inst["opcode"].asUInt();
|
||||
const std::string name = inst["opname"].asString();
|
||||
EnumCaps caps = getCaps(inst);
|
||||
std::string version = inst["version"].asString();
|
||||
Extensions exts = getExts(inst);
|
||||
OperandParameters operands;
|
||||
bool defResultId = false;
|
||||
bool defTypeId = false;
|
||||
for (const auto& operand : inst["operands"]) {
|
||||
const std::string kind = operand["kind"].asString();
|
||||
const std::string quantifier = operand.get("quantifier", "").asString();
|
||||
const std::string doc = operand.get("name", "").asString();
|
||||
if (!IsTypeOrResultId(kind, &defTypeId, &defResultId)) {
|
||||
const auto p = ToOperandClassAndOptionality(kind, quantifier);
|
||||
operands.push(p.type, doc, p.optional);
|
||||
}
|
||||
}
|
||||
InstructionDesc.emplace_back(
|
||||
std::move(EnumValue(opcode, name,
|
||||
std::move(caps), std::move(version), std::move(exts),
|
||||
std::move(operands))),
|
||||
defTypeId, defResultId);
|
||||
}
|
||||
|
||||
// Specific additional context-dependent operands
|
||||
|
||||
// Populate dest with EnumValue objects constructed from source.
|
||||
const auto populateEnumValues = [&getCaps,&getExts](EnumValues* dest, const Json::Value& source, bool bitEnum) {
|
||||
// A lambda for determining the numeric value to be used for a given
|
||||
// enumerant in JSON form, and whether that value is a 0 in a bitfield.
|
||||
auto getValue = [&bitEnum](const Json::Value& enumerant) {
|
||||
std::pair<unsigned, bool> result{0u,false};
|
||||
if (!bitEnum) {
|
||||
result.first = enumerant["value"].asUInt();
|
||||
} else {
|
||||
const unsigned int bit = NumberStringToBit(enumerant["value"].asString());
|
||||
if (bit == 0)
|
||||
result.second = true;
|
||||
else
|
||||
result.first = bit - 1; // This is the *shift* amount.
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
for (const auto& enumerant : source["enumerants"]) {
|
||||
unsigned value;
|
||||
bool skip_zero_in_bitfield;
|
||||
std::tie(value, skip_zero_in_bitfield) = getValue(enumerant);
|
||||
if (skip_zero_in_bitfield)
|
||||
continue;
|
||||
EnumCaps caps(getCaps(enumerant));
|
||||
std::string version = enumerant["version"].asString();
|
||||
Extensions exts(getExts(enumerant));
|
||||
OperandParameters params;
|
||||
const Json::Value& paramsJson = enumerant["parameters"];
|
||||
if (!paramsJson.empty()) { // This enumerant has parameters.
|
||||
assert(paramsJson.isArray());
|
||||
for (const auto& param : paramsJson) {
|
||||
const std::string kind = param["kind"].asString();
|
||||
const std::string doc = param.get("name", "").asString();
|
||||
const auto p = ToOperandClassAndOptionality(kind, ""); // All parameters are required!
|
||||
params.push(p.type, doc);
|
||||
}
|
||||
}
|
||||
dest->emplace_back(
|
||||
value, enumerant["enumerant"].asString(),
|
||||
std::move(caps), std::move(version), std::move(exts), std::move(params));
|
||||
}
|
||||
};
|
||||
|
||||
const auto establishOperandClass = [&populateEnumValues](
|
||||
const std::string& enumName, spv::OperandClass operandClass,
|
||||
spv::EnumValues* enumValues, const Json::Value& operandEnum, const std::string& category) {
|
||||
assert(category == "BitEnum" || category == "ValueEnum");
|
||||
bool bitEnum = (category == "BitEnum");
|
||||
populateEnumValues(enumValues, operandEnum, bitEnum);
|
||||
OperandClassParams[operandClass].set(enumName, enumValues, bitEnum);
|
||||
};
|
||||
|
||||
const Json::Value operandEnums = root["operand_kinds"];
|
||||
for (const auto& operandEnum : operandEnums) {
|
||||
const std::string enumName = operandEnum["kind"].asString();
|
||||
const std::string category = operandEnum["category"].asString();
|
||||
if (enumName == "SourceLanguage") {
|
||||
establishOperandClass(enumName, OperandSource, &SourceLanguageParams, operandEnum, category);
|
||||
} else if (enumName == "Decoration") {
|
||||
establishOperandClass(enumName, OperandDecoration, &DecorationParams, operandEnum, category);
|
||||
} else if (enumName == "ExecutionMode") {
|
||||
establishOperandClass(enumName, OperandExecutionMode, &ExecutionModeParams, operandEnum, category);
|
||||
} else if (enumName == "Capability") {
|
||||
establishOperandClass(enumName, OperandCapability, &CapabilityParams, operandEnum, category);
|
||||
} else if (enumName == "AddressingModel") {
|
||||
establishOperandClass(enumName, OperandAddressing, &AddressingParams, operandEnum, category);
|
||||
} else if (enumName == "MemoryModel") {
|
||||
establishOperandClass(enumName, OperandMemory, &MemoryParams, operandEnum, category);
|
||||
} else if (enumName == "MemorySemantics") {
|
||||
establishOperandClass(enumName, OperandMemorySemantics, &MemorySemanticsParams, operandEnum, category);
|
||||
} else if (enumName == "ExecutionModel") {
|
||||
establishOperandClass(enumName, OperandExecutionModel, &ExecutionModelParams, operandEnum, category);
|
||||
} else if (enumName == "StorageClass") {
|
||||
establishOperandClass(enumName, OperandStorage, &StorageParams, operandEnum, category);
|
||||
} else if (enumName == "SamplerAddressingMode") {
|
||||
establishOperandClass(enumName, OperandSamplerAddressingMode, &SamplerAddressingModeParams, operandEnum, category);
|
||||
} else if (enumName == "SamplerFilterMode") {
|
||||
establishOperandClass(enumName, OperandSamplerFilterMode, &SamplerFilterModeParams, operandEnum, category);
|
||||
} else if (enumName == "ImageFormat") {
|
||||
establishOperandClass(enumName, OperandSamplerImageFormat, &ImageFormatParams, operandEnum, category);
|
||||
} else if (enumName == "ImageChannelOrder") {
|
||||
establishOperandClass(enumName, OperandImageChannelOrder, &ImageChannelOrderParams, operandEnum, category);
|
||||
} else if (enumName == "ImageChannelDataType") {
|
||||
establishOperandClass(enumName, OperandImageChannelDataType, &ImageChannelDataTypeParams, operandEnum, category);
|
||||
} else if (enumName == "ImageOperands") {
|
||||
establishOperandClass(enumName, OperandImageOperands, &ImageOperandsParams, operandEnum, category);
|
||||
} else if (enumName == "FPFastMathMode") {
|
||||
establishOperandClass(enumName, OperandFPFastMath, &FPFastMathParams, operandEnum, category);
|
||||
} else if (enumName == "FPRoundingMode") {
|
||||
establishOperandClass(enumName, OperandFPRoundingMode, &FPRoundingModeParams, operandEnum, category);
|
||||
} else if (enumName == "LinkageType") {
|
||||
establishOperandClass(enumName, OperandLinkageType, &LinkageTypeParams, operandEnum, category);
|
||||
} else if (enumName == "FunctionParameterAttribute") {
|
||||
establishOperandClass(enumName, OperandFuncParamAttr, &FuncParamAttrParams, operandEnum, category);
|
||||
} else if (enumName == "AccessQualifier") {
|
||||
establishOperandClass(enumName, OperandAccessQualifier, &AccessQualifierParams, operandEnum, category);
|
||||
} else if (enumName == "BuiltIn") {
|
||||
establishOperandClass(enumName, OperandBuiltIn, &BuiltInParams, operandEnum, category);
|
||||
} else if (enumName == "SelectionControl") {
|
||||
establishOperandClass(enumName, OperandSelect, &SelectionControlParams, operandEnum, category);
|
||||
} else if (enumName == "LoopControl") {
|
||||
establishOperandClass(enumName, OperandLoop, &LoopControlParams, operandEnum, category);
|
||||
} else if (enumName == "FunctionControl") {
|
||||
establishOperandClass(enumName, OperandFunction, &FunctionControlParams, operandEnum, category);
|
||||
} else if (enumName == "Dim") {
|
||||
establishOperandClass(enumName, OperandDimensionality, &DimensionalityParams, operandEnum, category);
|
||||
} else if (enumName == "MemoryAccess") {
|
||||
establishOperandClass(enumName, OperandMemoryAccess, &MemoryAccessParams, operandEnum, category);
|
||||
} else if (enumName == "Scope") {
|
||||
establishOperandClass(enumName, OperandScope, &ScopeParams, operandEnum, category);
|
||||
} else if (enumName == "GroupOperation") {
|
||||
establishOperandClass(enumName, OperandGroupOperation, &GroupOperationParams, operandEnum, category);
|
||||
} else if (enumName == "KernelEnqueueFlags") {
|
||||
establishOperandClass(enumName, OperandKernelEnqueueFlags, &KernelEnqueueFlagsParams, operandEnum, category);
|
||||
} else if (enumName == "KernelProfilingInfo") {
|
||||
establishOperandClass(enumName, OperandKernelProfilingInfo, &KernelProfilingInfoParams, operandEnum, category);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}; // end namespace spv
|
259
tools/buildHeaders/jsonToSpirv.h
Executable file
259
tools/buildHeaders/jsonToSpirv.h
Executable file
@ -0,0 +1,259 @@
|
||||
// Copyright (c) 2014-2018 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and/or associated documentation files (the "Materials"),
|
||||
// to deal in the Materials without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Materials, and to permit persons to whom the
|
||||
// Materials are furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
// IN THE MATERIALS.
|
||||
|
||||
#pragma once
|
||||
#ifndef JSON_TO_SPIRV
|
||||
#define JSON_TO_SPIRV
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
|
||||
namespace spv {
|
||||
|
||||
// Reads the file in the given |path|. Returns true and the contents of the
|
||||
// file on success; otherwise, returns false and an empty string.
|
||||
std::pair<bool, std::string> ReadFile(const std::string& path);
|
||||
|
||||
// Fill in all the parameters
|
||||
void jsonToSpirv(const std::string& jsonPath);
|
||||
|
||||
// For parameterizing operands.
|
||||
enum OperandClass {
|
||||
OperandNone,
|
||||
OperandId,
|
||||
OperandVariableIds,
|
||||
OperandOptionalLiteral,
|
||||
OperandOptionalLiteralString,
|
||||
OperandVariableLiterals,
|
||||
OperandVariableIdLiteral,
|
||||
OperandVariableLiteralId,
|
||||
OperandLiteralNumber,
|
||||
OperandLiteralString,
|
||||
OperandSource,
|
||||
OperandExecutionModel,
|
||||
OperandAddressing,
|
||||
OperandMemory,
|
||||
OperandExecutionMode,
|
||||
OperandStorage,
|
||||
OperandDimensionality,
|
||||
OperandSamplerAddressingMode,
|
||||
OperandSamplerFilterMode,
|
||||
OperandSamplerImageFormat,
|
||||
OperandImageChannelOrder,
|
||||
OperandImageChannelDataType,
|
||||
OperandImageOperands,
|
||||
OperandFPFastMath,
|
||||
OperandFPRoundingMode,
|
||||
OperandLinkageType,
|
||||
OperandAccessQualifier,
|
||||
OperandFuncParamAttr,
|
||||
OperandDecoration,
|
||||
OperandBuiltIn,
|
||||
OperandSelect,
|
||||
OperandLoop,
|
||||
OperandFunction,
|
||||
OperandMemorySemantics,
|
||||
OperandMemoryAccess,
|
||||
OperandScope,
|
||||
OperandGroupOperation,
|
||||
OperandKernelEnqueueFlags,
|
||||
OperandKernelProfilingInfo,
|
||||
OperandCapability,
|
||||
|
||||
OperandOpcode,
|
||||
|
||||
OperandCount
|
||||
};
|
||||
|
||||
// Any specific enum can have a set of capabilities that allow it:
|
||||
typedef std::vector<std::string> EnumCaps;
|
||||
|
||||
// A set of extensions.
|
||||
typedef std::vector<std::string> Extensions;
|
||||
|
||||
// Parameterize a set of operands with their OperandClass(es) and descriptions.
|
||||
class OperandParameters {
|
||||
public:
|
||||
OperandParameters() { }
|
||||
void push(OperandClass oc, const std::string& d, bool opt = false)
|
||||
{
|
||||
opClass.push_back(oc);
|
||||
desc.push_back(d);
|
||||
optional.push_back(opt);
|
||||
}
|
||||
void setOptional();
|
||||
OperandClass getClass(int op) const { return opClass[op]; }
|
||||
const char* getDesc(int op) const { return desc[op].c_str(); }
|
||||
bool isOptional(int op) const { return optional[op]; }
|
||||
int getNum() const { return (int)opClass.size(); }
|
||||
|
||||
protected:
|
||||
std::vector<OperandClass> opClass;
|
||||
std::vector<std::string> desc;
|
||||
std::vector<bool> optional;
|
||||
};
|
||||
|
||||
// An ordered sequence of EValue. We'll preserve the order found in the
|
||||
// JSON file. You can look up a value by enum or by name. If there are
|
||||
// duplicate values, then take the first. We assume names are unique.
|
||||
// The EValue must have an unsigned |value| field and a string |name| field.
|
||||
template <typename EValue>
|
||||
class EnumValuesContainer {
|
||||
public:
|
||||
using ContainerType = std::vector<EValue>;
|
||||
using iterator = typename ContainerType::iterator;
|
||||
using const_iterator = typename ContainerType::const_iterator;
|
||||
|
||||
EnumValuesContainer() {}
|
||||
|
||||
// Constructs an EValue in place as a new element at the end of the
|
||||
// sequence.
|
||||
template <typename... Args>
|
||||
void emplace_back(Args&&... args) {
|
||||
values.emplace_back(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Returns the first EValue in the sequence with the given value.
|
||||
// More than one EValue might have the same value.
|
||||
EValue& operator[](unsigned value) {
|
||||
auto where = std::find_if(begin(), end(), [&value](const EValue& e) {
|
||||
return value == e.value;
|
||||
});
|
||||
assert((where != end()) && "Could not find enum in the enum list");
|
||||
return *where;
|
||||
}
|
||||
// Returns the EValue with the given name. We assume uniqueness
|
||||
// by name.
|
||||
EValue& at(std::string name) {
|
||||
auto where = std::find_if(begin(), end(), [&name](const EValue& e) {
|
||||
return name == e.name;
|
||||
});
|
||||
assert((where != end()) && "Could not find name in the enum list");
|
||||
return *where;
|
||||
}
|
||||
|
||||
iterator begin() { return values.begin(); }
|
||||
iterator end() { return values.end(); }
|
||||
|
||||
private:
|
||||
ContainerType values;
|
||||
};
|
||||
|
||||
// A single enumerant value. Corresponds to a row in an enumeration table
|
||||
// in the spec.
|
||||
class EnumValue {
|
||||
public:
|
||||
EnumValue() : value(0), desc(nullptr) {}
|
||||
EnumValue(unsigned int the_value, const std::string& the_name, EnumCaps&& the_caps, std::string& the_version,
|
||||
Extensions&& the_extensions, OperandParameters&& the_operands) :
|
||||
value(the_value), name(the_name), capabilities(std::move(the_caps)), version(std::move(the_version)),
|
||||
extensions(std::move(the_extensions)), operands(std::move(the_operands)), desc(nullptr) { }
|
||||
|
||||
// For ValueEnum, the value from the JSON file.
|
||||
// For BitEnum, the index of the bit position represented by this mask.
|
||||
// (That is, what you shift 1 by to get the mask.)
|
||||
unsigned value;
|
||||
std::string name;
|
||||
EnumCaps capabilities;
|
||||
std::string version;
|
||||
// A feature only be enabled by certain extensions.
|
||||
// An empty list means the feature does not require an extension.
|
||||
// Normally, only Capability enums are enabled by extension. In turn,
|
||||
// other enums and instructions are enabled by those capabilities.
|
||||
Extensions extensions;
|
||||
OperandParameters operands;
|
||||
const char* desc;
|
||||
};
|
||||
|
||||
using EnumValues = EnumValuesContainer<EnumValue>;
|
||||
|
||||
// Parameterize a set of enumerants that form an enum
|
||||
class EnumDefinition {
|
||||
public:
|
||||
EnumDefinition() :
|
||||
desc(0), bitmask(false), enumValues(nullptr) { }
|
||||
void set(const std::string& enumName, EnumValues* enumValuesArg, bool mask = false)
|
||||
{
|
||||
codeName = enumName;
|
||||
bitmask = mask;
|
||||
enumValues = enumValuesArg;
|
||||
}
|
||||
// Returns the first EnumValue in the sequence with the given value.
|
||||
// More than one EnumValue might have the same value. Only valid
|
||||
// if enumValues has been populated.
|
||||
EnumValue& operator[](unsigned value) {
|
||||
assert(enumValues != nullptr);
|
||||
return (*enumValues)[value];
|
||||
}
|
||||
// Returns the name of the first EnumValue with the given value.
|
||||
// Assumes enumValues has been populated.
|
||||
const char* getName(unsigned value) {
|
||||
return (*this)[value].name.c_str();
|
||||
}
|
||||
|
||||
using iterator = EnumValues::iterator;
|
||||
iterator begin() { return enumValues->begin(); }
|
||||
iterator end() { return enumValues->end(); }
|
||||
|
||||
std::string codeName; // name to use when declaring headers for code
|
||||
const char* desc;
|
||||
bool bitmask; // true if these enumerants combine into a bitmask
|
||||
EnumValues* enumValues; // parameters for each individual enumerant
|
||||
};
|
||||
|
||||
// Parameterize an instruction's logical format, including its known set of operands,
|
||||
// per OperandParameters above.
|
||||
class InstructionValue : public EnumValue {
|
||||
public:
|
||||
InstructionValue(EnumValue&& e, bool has_type, bool has_result)
|
||||
: EnumValue(std::move(e)),
|
||||
opDesc("TBD"),
|
||||
opClass(0),
|
||||
typePresent(has_type),
|
||||
resultPresent(has_result) {}
|
||||
|
||||
bool hasResult() const { return resultPresent != 0; }
|
||||
bool hasType() const { return typePresent != 0; }
|
||||
|
||||
const char* opDesc;
|
||||
int opClass;
|
||||
|
||||
protected:
|
||||
int typePresent : 1;
|
||||
int resultPresent : 1;
|
||||
};
|
||||
|
||||
using InstructionValues = EnumValuesContainer<InstructionValue>;
|
||||
|
||||
// Parameterization info for all instructions.
|
||||
extern InstructionValues InstructionDesc;
|
||||
|
||||
// These hold definitions of the enumerants used for operands.
|
||||
// This is indexed by OperandClass, but not including OperandOpcode.
|
||||
extern EnumDefinition OperandClassParams[];
|
||||
|
||||
}; // end namespace spv
|
||||
|
||||
#endif // JSON_TO_SPIRV
|
255
tools/buildHeaders/jsoncpp/dist/json/json-forwards.h
vendored
Normal file
255
tools/buildHeaders/jsoncpp/dist/json/json-forwards.h
vendored
Normal file
@ -0,0 +1,255 @@
|
||||
/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).
|
||||
/// It is intended to be used with #include "json/json-forwards.h"
|
||||
/// This header provides forward declaration for all JsonCpp types.
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// Beginning of content of file: LICENSE
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
The JsonCpp library's source code, including accompanying documentation,
|
||||
tests and demonstration applications, are licensed under the following
|
||||
conditions...
|
||||
|
||||
The author (Baptiste Lepilleur) explicitly disclaims copyright in all
|
||||
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||
this software is released into the Public Domain.
|
||||
|
||||
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
|
||||
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
|
||||
released under the terms of the MIT License (see below).
|
||||
|
||||
In jurisdictions which recognize Public Domain property, the user of this
|
||||
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||
conditions of the MIT License (see below), or 3) under the terms of dual
|
||||
Public Domain/MIT License conditions described here, as they choose.
|
||||
|
||||
The MIT License is about as close to Public Domain as a license can get, and is
|
||||
described in clear, concise terms at:
|
||||
|
||||
http://en.wikipedia.org/wiki/MIT_License
|
||||
|
||||
The full text of the MIT License follows:
|
||||
|
||||
========================================================================
|
||||
Copyright (c) 2007-2010 Baptiste Lepilleur
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
========================================================================
|
||||
(END LICENSE TEXT)
|
||||
|
||||
The MIT license is compatible with both the GPL and commercial
|
||||
software, affording one all of the rights of Public Domain with the
|
||||
minor nuisance of being required to keep the above copyright notice
|
||||
and license text in the source code. Note also that by accepting the
|
||||
Public Domain "license" you can re-license your copy using whatever
|
||||
license you like.
|
||||
|
||||
*/
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// End of content of file: LICENSE
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
|
||||
# define JSON_FORWARD_AMALGATED_H_INCLUDED
|
||||
/// If defined, indicates that the source file is amalgated
|
||||
/// to prevent private header inclusion.
|
||||
#define JSON_IS_AMALGAMATION
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// Beginning of content of file: include/json/config.h
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Copyright 2007-2010 Baptiste Lepilleur
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#ifndef JSON_CONFIG_H_INCLUDED
|
||||
#define JSON_CONFIG_H_INCLUDED
|
||||
|
||||
/// If defined, indicates that json library is embedded in CppTL library.
|
||||
//# define JSON_IN_CPPTL 1
|
||||
|
||||
/// If defined, indicates that json may leverage CppTL library
|
||||
//# define JSON_USE_CPPTL 1
|
||||
/// If defined, indicates that cpptl vector based map should be used instead of
|
||||
/// std::map
|
||||
/// as Value container.
|
||||
//# define JSON_USE_CPPTL_SMALLMAP 1
|
||||
|
||||
// If non-zero, the library uses exceptions to report bad input instead of C
|
||||
// assertion macros. The default is to use exceptions.
|
||||
#ifndef JSON_USE_EXCEPTION
|
||||
#define JSON_USE_EXCEPTION 1
|
||||
#endif
|
||||
|
||||
/// If defined, indicates that the source file is amalgated
|
||||
/// to prevent private header inclusion.
|
||||
/// Remarks: it is automatically defined in the generated amalgated header.
|
||||
// #define JSON_IS_AMALGAMATION
|
||||
|
||||
#ifdef JSON_IN_CPPTL
|
||||
#include <cpptl/config.h>
|
||||
#ifndef JSON_USE_CPPTL
|
||||
#define JSON_USE_CPPTL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JSON_IN_CPPTL
|
||||
#define JSON_API CPPTL_API
|
||||
#elif defined(JSON_DLL_BUILD)
|
||||
#if defined(_MSC_VER)
|
||||
#define JSON_API __declspec(dllexport)
|
||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||
#endif // if defined(_MSC_VER)
|
||||
#elif defined(JSON_DLL)
|
||||
#if defined(_MSC_VER)
|
||||
#define JSON_API __declspec(dllimport)
|
||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||
#endif // if defined(_MSC_VER)
|
||||
#endif // ifdef JSON_IN_CPPTL
|
||||
#if !defined(JSON_API)
|
||||
#define JSON_API
|
||||
#endif
|
||||
|
||||
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
|
||||
// integer
|
||||
// Storages, and 64 bits integer support is disabled.
|
||||
// #define JSON_NO_INT64 1
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6
|
||||
// Microsoft Visual Studio 6 only support conversion from __int64 to double
|
||||
// (no conversion from unsigned __int64).
|
||||
#define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
||||
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
|
||||
// characters in the debug information)
|
||||
// All projects I've ever seen with VS6 were using this globally (not bothering
|
||||
// with pragma push/pop).
|
||||
#pragma warning(disable : 4786)
|
||||
#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008
|
||||
/// Indicates that the following function is deprecated.
|
||||
#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
|
||||
#elif defined(__clang__) && defined(__has_feature)
|
||||
#if __has_feature(attribute_deprecated_with_message)
|
||||
#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
|
||||
#endif
|
||||
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
|
||||
#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
|
||||
#elif defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
|
||||
#endif
|
||||
|
||||
#if !defined(JSONCPP_DEPRECATED)
|
||||
#define JSONCPP_DEPRECATED(message)
|
||||
#endif // if !defined(JSONCPP_DEPRECATED)
|
||||
|
||||
namespace Json {
|
||||
typedef int Int;
|
||||
typedef unsigned int UInt;
|
||||
#if defined(JSON_NO_INT64)
|
||||
typedef int LargestInt;
|
||||
typedef unsigned int LargestUInt;
|
||||
#undef JSON_HAS_INT64
|
||||
#else // if defined(JSON_NO_INT64)
|
||||
// For Microsoft Visual use specific types as long long is not supported
|
||||
#if defined(_MSC_VER) // Microsoft Visual Studio
|
||||
typedef __int64 Int64;
|
||||
typedef unsigned __int64 UInt64;
|
||||
#else // if defined(_MSC_VER) // Other platforms, use long long
|
||||
typedef long long int Int64;
|
||||
typedef unsigned long long int UInt64;
|
||||
#endif // if defined(_MSC_VER)
|
||||
typedef Int64 LargestInt;
|
||||
typedef UInt64 LargestUInt;
|
||||
#define JSON_HAS_INT64
|
||||
#endif // if defined(JSON_NO_INT64)
|
||||
} // end namespace Json
|
||||
|
||||
#endif // JSON_CONFIG_H_INCLUDED
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// End of content of file: include/json/config.h
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// Beginning of content of file: include/json/forwards.h
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Copyright 2007-2010 Baptiste Lepilleur
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#ifndef JSON_FORWARDS_H_INCLUDED
|
||||
#define JSON_FORWARDS_H_INCLUDED
|
||||
|
||||
#if !defined(JSON_IS_AMALGAMATION)
|
||||
#include "config.h"
|
||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||
|
||||
namespace Json {
|
||||
|
||||
// writer.h
|
||||
class FastWriter;
|
||||
class StyledWriter;
|
||||
|
||||
// reader.h
|
||||
class Reader;
|
||||
|
||||
// features.h
|
||||
class Features;
|
||||
|
||||
// value.h
|
||||
typedef unsigned int ArrayIndex;
|
||||
class StaticString;
|
||||
class Path;
|
||||
class PathArgument;
|
||||
class Value;
|
||||
class ValueIteratorBase;
|
||||
class ValueIterator;
|
||||
class ValueConstIterator;
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#endif // JSON_FORWARDS_H_INCLUDED
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// End of content of file: include/json/forwards.h
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
|
2017
tools/buildHeaders/jsoncpp/dist/json/json.h
vendored
Normal file
2017
tools/buildHeaders/jsoncpp/dist/json/json.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5124
tools/buildHeaders/jsoncpp/dist/jsoncpp.cpp
vendored
Normal file
5124
tools/buildHeaders/jsoncpp/dist/jsoncpp.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
121
tools/buildHeaders/main.cpp
Executable file
121
tools/buildHeaders/main.cpp
Executable file
@ -0,0 +1,121 @@
|
||||
// Copyright (c) 2014-2018 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and/or associated documentation files (the "Materials"),
|
||||
// to deal in the Materials without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Materials, and to permit persons to whom the
|
||||
// Materials are furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
// IN THE MATERIALS.
|
||||
|
||||
//#include <fstream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "jsonToSpirv.h"
|
||||
#include "header.h"
|
||||
|
||||
// Command-line options
|
||||
enum TOptions {
|
||||
EOptionNone = 0x000,
|
||||
EOptionPrintHeader = 0x008,
|
||||
};
|
||||
|
||||
std::string jsonPath;
|
||||
int Options;
|
||||
spv::TLanguage Language;
|
||||
|
||||
void Usage()
|
||||
{
|
||||
printf("Usage: spirv option [file]\n"
|
||||
"\n"
|
||||
" -h <language> print header for given language to stdout, from one of:\n"
|
||||
" C - C99 header\n"
|
||||
" C++ - C++03 or greater header (also accepts C++03)\n"
|
||||
" C++11 - C++11 or greater header\n"
|
||||
" JSON - JSON format data\n"
|
||||
" Lua - Lua module\n"
|
||||
" Python - Python module (also accepts Py)\n"
|
||||
" -H print header in all supported languages to files in current directory\n"
|
||||
);
|
||||
}
|
||||
|
||||
std::string tolower_s(std::string s)
|
||||
{
|
||||
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
|
||||
return s;
|
||||
}
|
||||
|
||||
bool ProcessArguments(int argc, char* argv[])
|
||||
{
|
||||
argc--;
|
||||
argv++;
|
||||
for (; argc >= 1; argc--, argv++) {
|
||||
if (argv[0][0] == '-') {
|
||||
switch (argv[0][1]) {
|
||||
case 'H':
|
||||
Options |= EOptionPrintHeader;
|
||||
Language = spv::ELangAll;
|
||||
break;
|
||||
case 'h': {
|
||||
if (argc < 2)
|
||||
return false;
|
||||
|
||||
Options |= EOptionPrintHeader;
|
||||
const std::string language(tolower_s(argv[1]));
|
||||
|
||||
if (language == "c") {
|
||||
Language = spv::ELangC;
|
||||
} else if (language == "c++" || language == "c++03") {
|
||||
Language = spv::ELangCPP;
|
||||
} else if (language == "c++11") {
|
||||
Language = spv::ELangCPP11;
|
||||
} else if (language == "json") {
|
||||
Language = spv::ELangJSON;
|
||||
} else if (language == "lua") {
|
||||
Language = spv::ELangLua;
|
||||
} else if (language == "python" || language == "py") {
|
||||
Language = spv::ELangPython;
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
jsonPath = std::string(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 2 || ! ProcessArguments(argc, argv)) {
|
||||
Usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
spv::jsonToSpirv(jsonPath);
|
||||
if (Options & EOptionPrintHeader)
|
||||
spv::PrintHeader(Language, std::cout);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user