aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/buildHeaders/header.cpp57
-rw-r--r--tools/buildHeaders/jsonToSpirv.cpp31
-rw-r--r--tools/buildHeaders/jsonToSpirv.h34
-rw-r--r--tools/buildHeaders/main.cpp2
4 files changed, 103 insertions, 21 deletions
diff --git a/tools/buildHeaders/header.cpp b/tools/buildHeaders/header.cpp
index 7d5cd98..e1e05d0 100644
--- a/tools/buildHeaders/header.cpp
+++ b/tools/buildHeaders/header.cpp
@@ -42,6 +42,7 @@
#include <cctype>
#include <vector>
#include <utility>
+#include <set>
#include "jsoncpp/dist/json/json.h"
@@ -68,9 +69,9 @@ namespace {
TPrinter();
static const int DocMagicNumber = 0x07230203;
- static const int DocVersion = 0x00010300;
- static const int DocRevision = 6;
- #define DocRevisionString "6"
+ static const int DocVersion = 0x00010400;
+ static const int DocRevision = 1;
+ #define DocRevisionString "1"
static const std::string DocCopyright;
static const std::string DocComment1;
static const std::string DocComment2;
@@ -97,6 +98,7 @@ namespace {
virtual void printEpilogue(std::ostream&) const { }
virtual void printMeta(std::ostream&) const;
virtual void printTypes(std::ostream&) const { }
+ virtual void printHasResultType(std::ostream&) const { };
virtual std::string escapeComment(const std::string& s) const;
@@ -346,7 +348,7 @@ namespace {
bool printMax = (style != enumMask && maxEnum.size() > 0);
for (const auto& v : sorted)
- out << enumFmt(opPrefix, v, style, !printMax && v.first == sorted.back().first);
+ out << enumFmt(opPrefix, v, style, !printMax && v.second == sorted.back().second);
if (printMax)
out << maxEnum;
@@ -364,6 +366,7 @@ namespace {
printTypes(out);
printMeta(out);
printDefs(out);
+ printHasResultType(out);
printEpilogue(out);
}
@@ -478,7 +481,7 @@ namespace {
}
virtual void printEpilogue(std::ostream& out) const override {
- out << "#endif // #ifndef spirv_" << headerGuardSuffix() << std::endl;
+ out << "#endif" << std::endl;
}
virtual void printTypes(std::ostream& out) const override {
@@ -494,6 +497,45 @@ namespace {
virtual std::string pre() const { return ""; } // C name prefix
virtual std::string headerGuardSuffix() const = 0;
+
+ virtual std::string fmtEnumUse(const std::string& opPrefix, const std::string& name) const { return pre() + name; }
+
+ virtual void printHasResultType(std::ostream& out) const
+ {
+ const Json::Value& enums = spvRoot["spv"]["enum"];
+
+ std::set<unsigned> seenValues;
+
+ for (auto opClass = enums.begin(); opClass != enums.end(); ++opClass) {
+ const auto opName = (*opClass)["Name"].asString();
+ if (opName != "Op") {
+ continue;
+ }
+
+ out << "#ifdef SPV_ENABLE_UTILITY_CODE" << std::endl;
+ out << "inline void " << pre() << "HasResultAndType(" << pre() << opName << " opcode, bool *hasResult, bool *hasResultType) {" << std::endl;
+ out << " *hasResult = *hasResultType = false;" << std::endl;
+ out << " switch (opcode) {" << std::endl;
+ out << " default: /* unknown opcode */ break;" << std::endl;
+
+ for (auto& inst : spv::InstructionDesc) {
+
+ // Filter out duplicate enum values, which would break the switch statement.
+ // These are probably just extension enums promoted to core.
+ if (seenValues.find(inst.value) != seenValues.end()) {
+ continue;
+ }
+ seenValues.insert(inst.value);
+
+ std::string name = inst.name;
+ out << " case " << fmtEnumUse("Op", name) << ": *hasResult = " << (inst.hasResult() ? "true" : "false") << "; *hasResultType = " << (inst.hasType() ? "true" : "false") << "; break;" << std::endl;
+ }
+
+ out << " }" << std::endl;
+ out << "}" << std::endl;
+ out << "#endif /* SPV_ENABLE_UTILITY_CODE */" << std::endl << std::endl;
+ }
+ }
};
// C printer
@@ -552,7 +594,7 @@ namespace {
}
out << "\n} // end namespace spv\n\n";
- TPrinterCBase::printEpilogue(out);
+ out << "#endif // #ifndef spirv_" << headerGuardSuffix() << std::endl;
}
std::string commentBOL() const override { return "// "; }
@@ -600,6 +642,9 @@ namespace {
return enumFmt(s, v, style, true);
}
+ // Add type prefix for scoped enum
+ virtual std::string fmtEnumUse(const std::string& opPrefix, const std::string& name) const { return opPrefix + "::" + name; }
+
std::string headerGuardSuffix() const override { return "HPP"; }
};
diff --git a/tools/buildHeaders/jsonToSpirv.cpp b/tools/buildHeaders/jsonToSpirv.cpp
index 62b85a8..e6cab48 100644
--- a/tools/buildHeaders/jsonToSpirv.cpp
+++ b/tools/buildHeaders/jsonToSpirv.cpp
@@ -119,8 +119,7 @@ ClassOptionality ToOperandClassAndOptionality(const std::string& operandKind, co
else if (quantifier == "?")
return {OperandLiteralString, true};
else {
- assert(0 && "this case should not exist");
- return {OperandNone, false};
+ return {OperandOptionalLiteralStrings, false};
}
} else if (operandKind == "PairLiteralIntegerIdRef") {
// Used by OpSwitch in the grammar
@@ -198,7 +197,7 @@ ClassOptionality ToOperandClassAndOptionality(const std::string& operandKind, co
} else if (operandKind == "FunctionControl") {
type = OperandFunction;
} else if (operandKind == "MemoryAccess") {
- type = OperandMemoryAccess;
+ type = OperandMemoryOperands;
}
if (type == OperandNone) {
@@ -230,7 +229,21 @@ unsigned int NumberStringToBit(const std::string& str)
return bit;
}
-void jsonToSpirv(const std::string& jsonPath)
+bool ExcludeInstruction(unsigned op, bool buildingHeaders)
+{
+ // Some instructions in the grammar don't need to be reflected
+ // in the specification.
+
+ if (buildingHeaders)
+ return false;
+
+ if (op >= 5699 /* OpVmeImageINTEL */ && op <= 5816 /* OpSubgroupAvcSicGetInterRawSadsINTEL */)
+ return true;
+
+ return false;
+}
+
+void jsonToSpirv(const std::string& jsonPath, bool buildingHeaders)
{
// only do this once.
static bool initialized = false;
@@ -288,9 +301,12 @@ void jsonToSpirv(const std::string& jsonPath)
const Json::Value insts = root["instructions"];
for (const auto& inst : insts) {
const unsigned int opcode = inst["opcode"].asUInt();
+ if (ExcludeInstruction(opcode, buildingHeaders))
+ continue;
const std::string name = inst["opname"].asString();
EnumCaps caps = getCaps(inst);
std::string version = inst["version"].asString();
+ std::string lastVersion = inst["lastVersion"].asString();
Extensions exts = getExts(inst);
OperandParameters operands;
bool defResultId = false;
@@ -306,7 +322,7 @@ void jsonToSpirv(const std::string& jsonPath)
}
InstructionDesc.emplace_back(
std::move(EnumValue(opcode, name,
- std::move(caps), std::move(version), std::move(exts),
+ std::move(caps), std::move(version), std::move(lastVersion), std::move(exts),
std::move(operands))),
defTypeId, defResultId);
}
@@ -339,6 +355,7 @@ void jsonToSpirv(const std::string& jsonPath)
continue;
EnumCaps caps(getCaps(enumerant));
std::string version = enumerant["version"].asString();
+ std::string lastVersion = enumerant["lastVersion"].asString();
Extensions exts(getExts(enumerant));
OperandParameters params;
const Json::Value& paramsJson = enumerant["parameters"];
@@ -353,7 +370,7 @@ void jsonToSpirv(const std::string& jsonPath)
}
dest->emplace_back(
value, enumerant["enumerant"].asString(),
- std::move(caps), std::move(version), std::move(exts), std::move(params));
+ std::move(caps), std::move(version), std::move(lastVersion), std::move(exts), std::move(params));
}
};
@@ -421,7 +438,7 @@ void jsonToSpirv(const std::string& jsonPath)
} else if (enumName == "Dim") {
establishOperandClass(enumName, OperandDimensionality, &DimensionalityParams, operandEnum, category);
} else if (enumName == "MemoryAccess") {
- establishOperandClass(enumName, OperandMemoryAccess, &MemoryAccessParams, operandEnum, category);
+ establishOperandClass(enumName, OperandMemoryOperands, &MemoryAccessParams, operandEnum, category);
} else if (enumName == "Scope") {
establishOperandClass(enumName, OperandScope, &ScopeParams, operandEnum, category);
} else if (enumName == "GroupOperation") {
diff --git a/tools/buildHeaders/jsonToSpirv.h b/tools/buildHeaders/jsonToSpirv.h
index bc63a4d..beec01c 100644
--- a/tools/buildHeaders/jsonToSpirv.h
+++ b/tools/buildHeaders/jsonToSpirv.h
@@ -38,7 +38,7 @@ namespace spv {
std::pair<bool, std::string> ReadFile(const std::string& path);
// Fill in all the parameters
-void jsonToSpirv(const std::string& jsonPath);
+void jsonToSpirv(const std::string& jsonPath, bool buildingHeaders);
// For parameterizing operands.
enum OperandClass {
@@ -47,6 +47,7 @@ enum OperandClass {
OperandVariableIds,
OperandOptionalLiteral,
OperandOptionalLiteralString,
+ OperandOptionalLiteralStrings,
OperandVariableLiterals,
OperandVariableIdLiteral,
OperandVariableLiteralId,
@@ -76,7 +77,7 @@ enum OperandClass {
OperandLoop,
OperandFunction,
OperandMemorySemantics,
- OperandMemoryAccess,
+ OperandMemoryOperands,
OperandScope,
OperandGroupOperation,
OperandKernelEnqueueFlags,
@@ -145,6 +146,12 @@ public:
assert((where != end()) && "Could not find enum in the enum list");
return *where;
}
+ // gets *all* entries for the value, including the first one
+ void gatherAliases(unsigned value, std::vector<EValue*>& aliases) {
+ std::for_each(begin(), end(), [&](EValue& e) {
+ if (value == e.value)
+ aliases.push_back(&e);});
+ }
// Returns the EValue with the given name. We assume uniqueness
// by name.
EValue& at(std::string name) {
@@ -167,9 +174,11 @@ private:
class EnumValue {
public:
EnumValue() : value(0), desc(nullptr) {}
- EnumValue(unsigned int the_value, const std::string& the_name, EnumCaps&& the_caps, const 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)),
+ EnumValue(unsigned int the_value, const std::string& the_name, EnumCaps&& the_caps,
+ const std::string& the_firstVersion, const std::string& the_lastVersion,
+ Extensions&& the_extensions, OperandParameters&& the_operands) :
+ value(the_value), name(the_name), capabilities(std::move(the_caps)),
+ firstVersion(std::move(the_firstVersion)), lastVersion(std::move(the_lastVersion)),
extensions(std::move(the_extensions)), operands(std::move(the_operands)), desc(nullptr) { }
// For ValueEnum, the value from the JSON file.
@@ -178,7 +187,8 @@ public:
unsigned value;
std::string name;
EnumCaps capabilities;
- std::string version;
+ std::string firstVersion;
+ std::string lastVersion;
// 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,
@@ -233,10 +243,19 @@ public:
opDesc("TBD"),
opClass(0),
typePresent(has_type),
- resultPresent(has_result) {}
+ resultPresent(has_result),
+ alias(this) { }
+ InstructionValue(const InstructionValue& v)
+ {
+ *this = v;
+ alias = this;
+ }
bool hasResult() const { return resultPresent != 0; }
bool hasType() const { return typePresent != 0; }
+ void setAlias(const InstructionValue& a) { alias = &a; }
+ const InstructionValue& getAlias() const { return *alias; }
+ bool isAlias() const { return alias != this; }
const char* opDesc;
int opClass;
@@ -244,6 +263,7 @@ public:
protected:
int typePresent : 1;
int resultPresent : 1;
+ const InstructionValue* alias; // correct only after discovering the aliases; otherwise points to this
};
using InstructionValues = EnumValuesContainer<InstructionValue>;
diff --git a/tools/buildHeaders/main.cpp b/tools/buildHeaders/main.cpp
index 67d676c..7e5f7f8 100644
--- a/tools/buildHeaders/main.cpp
+++ b/tools/buildHeaders/main.cpp
@@ -119,7 +119,7 @@ int main(int argc, char* argv[])
return 1;
}
- spv::jsonToSpirv(jsonPath);
+ spv::jsonToSpirv(jsonPath, (Options & EOptionPrintHeader) != 0);
if (Options & EOptionPrintHeader)
spv::PrintHeader(Language, std::cout);