${CMAKE_CURRENT_SOURCE_DIR}/test/Comment.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/DiagnosticPrint.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/DiagnosticStream.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/ExtInst.OpenCL.std.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/ExtInstGLSLstd450.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/FixWord.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/ImmediateInt.cpp
typedef enum spv_ext_inst_type_t {
SPV_EXT_INST_TYPE_NONE,
SPV_EXT_INST_TYPE_GLSL_STD_450,
- SPV_EXT_INST_TYPE_OPENCL_STD_12,
- SPV_EXT_INST_TYPE_OPENCL_STD_20,
- SPV_EXT_INST_TYPE_OPENCL_STD_21,
+ SPV_EXT_INST_TYPE_OPENCL_STD,
SPV_FORCE_32_BIT_ENUM(spv_ext_inst_type_t)
} spv_ext_inst_type_t;
{GLSL450Inst2(InterpolateAtOffset)},
};
-static const spv_ext_inst_desc_t openclStd12Entries[] = {
- {"placeholder", 0, {}},
- // TODO: Add remaining OpenCL.std.12 instructions
-};
-
-static const spv_ext_inst_desc_t openclStd20Entries[] = {
- {"placeholder", 0, {}},
- // TODO: Add remaining OpenCL.std.20 instructions
-};
-
-static const spv_ext_inst_desc_t openclStd21Entries[] = {
- {"placeholder", 0, {}},
- // TODO: Add remaining OpenCL.std.21 instructions
+static const spv_ext_inst_desc_t openclEntries[] = {
+#define ExtInst(Name, Opcode, OperandList) {#Name, Opcode, OperandList},
+#define EmptyList \
+ {}
+#define List(...) \
+ { __VA_ARGS__ }
+#define OperandId SPV_OPERAND_TYPE_ID
+#define OperandLiteralNumber SPV_OPERAND_TYPE_LITERAL_NUMBER
+#define OperandFPRoundingMode SPV_OPERAND_TYPE_FP_ROUNDING_MODE
+#define OperandVariableIds SPV_OPERAND_TYPE_VARIABLE_ID
+#include "opencl_std_ext_inst.inc"
+#undef ExtList
+#undef EmptyList
+#undef List
+#undef OperandId
+#undef OperandLiteralNumber
+#undef OperandFPRoundingMode
+#undef OperandVariableIds
};
spv_result_t spvExtInstTableGet(spv_ext_inst_table *pExtInstTable) {
{SPV_EXT_INST_TYPE_GLSL_STD_450,
sizeof(glslStd450Entries) / sizeof(spv_ext_inst_desc_t),
glslStd450Entries},
- {SPV_EXT_INST_TYPE_OPENCL_STD_12,
- sizeof(openclStd12Entries) / sizeof(spv_ext_inst_desc_t),
- openclStd12Entries},
- {SPV_EXT_INST_TYPE_OPENCL_STD_20,
- sizeof(openclStd20Entries) / sizeof(spv_ext_inst_desc_t),
- openclStd20Entries},
- {SPV_EXT_INST_TYPE_OPENCL_STD_21,
- sizeof(openclStd21Entries) / sizeof(spv_ext_inst_desc_t),
- openclStd21Entries},
+ {SPV_EXT_INST_TYPE_OPENCL_STD,
+ sizeof(openclEntries) / sizeof(spv_ext_inst_desc_t),
+ openclEntries},
};
static const spv_ext_inst_table_t table = {
}
spv_ext_inst_type_t spvExtInstImportTypeGet(const char *name) {
+ // The names are specified by the respective extension instruction
+ // specifications.
if (!strcmp("GLSL.std.450", name)) {
return SPV_EXT_INST_TYPE_GLSL_STD_450;
}
- if (!strcmp("OpenCL.std.12", name)) {
- return SPV_EXT_INST_TYPE_OPENCL_STD_12;
- }
- if (!strcmp("OpenCL.std.20", name)) {
- return SPV_EXT_INST_TYPE_OPENCL_STD_20;
- }
- if (!strcmp("OpenCL.std.21", name)) {
- return SPV_EXT_INST_TYPE_OPENCL_STD_21;
+ if (!strcmp("OpenCL.std", name)) {
+ return SPV_EXT_INST_TYPE_OPENCL_STD;
}
return SPV_EXT_INST_TYPE_NONE;
}
--- /dev/null
+
+// OpenCL extended instructions table, one instruction per line.
+// All instructions have a result type and a result ID.
+// Fields in this file are:
+// - name
+// - extended instruction index
+// - EmptyList, or List of operand classes.
+ExtInst(acos, 0, List(OperandId))
+ExtInst(acosh, 1, List(OperandId))
+ExtInst(acospi, 2, List(OperandId))
+ExtInst(asin, 3, List(OperandId))
+ExtInst(asinh, 4, List(OperandId))
+ExtInst(asinpi, 5, List(OperandId))
+ExtInst(atan, 6, List(OperandId))
+ExtInst(atan2, 7, List(OperandId, OperandId))
+ExtInst(atanh, 8, List(OperandId))
+ExtInst(atanpi, 9, List(OperandId))
+ExtInst(atan2pi, 10, List(OperandId, OperandId))
+ExtInst(cbrt, 11, List(OperandId))
+ExtInst(ceil, 12, List(OperandId))
+ExtInst(copysign, 13, List(OperandId, OperandId))
+ExtInst(cos, 14, List(OperandId))
+ExtInst(cosh, 15, List(OperandId))
+ExtInst(cospi, 16, List(OperandId))
+ExtInst(erfc, 17, List(OperandId))
+ExtInst(erf, 18, List(OperandId))
+ExtInst(exp, 19, List(OperandId))
+ExtInst(exp2, 20, List(OperandId))
+ExtInst(exp10, 21, List(OperandId))
+ExtInst(expm1, 22, List(OperandId))
+ExtInst(fabs, 23, List(OperandId))
+ExtInst(fdim, 24, List(OperandId, OperandId))
+ExtInst(floor, 25, List(OperandId))
+ExtInst(fma, 26, List(OperandId, OperandId, OperandId))
+ExtInst(fmax, 27, List(OperandId, OperandId))
+ExtInst(fmin, 28, List(OperandId, OperandId))
+ExtInst(fmod, 29, List(OperandId, OperandId))
+ExtInst(fract, 30, List(OperandId, OperandId))
+ExtInst(frexp, 31, List(OperandId, OperandId))
+ExtInst(hypot, 32, List(OperandId, OperandId))
+ExtInst(ilogb, 33, List(OperandId))
+ExtInst(ldexp, 34, List(OperandId, OperandId))
+ExtInst(lgamma, 35, List(OperandId))
+ExtInst(lgamma_r, 36, List(OperandId, OperandId))
+ExtInst(log, 37, List(OperandId))
+ExtInst(log2, 38, List(OperandId))
+ExtInst(log10, 39, List(OperandId))
+ExtInst(log1p, 40, List(OperandId))
+ExtInst(logb, 41, List(OperandId))
+ExtInst(mad, 42, List(OperandId, OperandId, OperandId))
+ExtInst(maxmag, 43, List(OperandId, OperandId))
+ExtInst(minmag, 44, List(OperandId, OperandId))
+ExtInst(modf, 45, List(OperandId, OperandId))
+ExtInst(nan, 46, List(OperandId))
+ExtInst(nextafter, 47, List(OperandId, OperandId))
+ExtInst(pow, 48, List(OperandId, OperandId, OperandId))
+ExtInst(pown, 49, List(OperandId))
+ExtInst(powr, 50, List(OperandId, OperandId))
+ExtInst(remainder, 51, List(OperandId, OperandId))
+ExtInst(remquo, 52, List(OperandId, OperandId, OperandId))
+ExtInst(rint, 53, List(OperandId))
+ExtInst(rootn, 54, List(OperandId, OperandId))
+ExtInst(round, 55, List(OperandId))
+ExtInst(rsqrt, 56, List(OperandId))
+ExtInst(sin, 57, List(OperandId))
+ExtInst(sincos, 58, List(OperandId, OperandId))
+ExtInst(sinh, 59, List(OperandId))
+ExtInst(sinpi, 60, List(OperandId))
+ExtInst(sqrt, 61, List(OperandId))
+ExtInst(tan, 62, List(OperandId))
+ExtInst(tanh, 63, List(OperandId))
+ExtInst(tanpi, 64, List(OperandId))
+ExtInst(tgamma, 65, List(OperandId))
+ExtInst(trunc, 66, List(OperandId))
+ExtInst(half_cos, 67, List(OperandId))
+ExtInst(half_divide, 68, List(OperandId, OperandId))
+ExtInst(half_exp, 69, List(OperandId))
+ExtInst(half_exp2, 70, List(OperandId))
+ExtInst(half_exp10, 71, List(OperandId))
+ExtInst(half_log, 72, List(OperandId))
+ExtInst(half_log2, 73, List(OperandId))
+ExtInst(half_log10, 74, List(OperandId))
+ExtInst(half_powr, 75, List(OperandId, OperandId))
+ExtInst(half_recip, 76, List(OperandId))
+ExtInst(half_rsqrt, 77, List(OperandId))
+ExtInst(half_sin, 78, List(OperandId))
+ExtInst(half_sqrt, 79, List(OperandId))
+ExtInst(half_tan, 80, List(OperandId))
+ExtInst(native_cos, 81, List(OperandId))
+ExtInst(native_divide, 82, List(OperandId, OperandId))
+ExtInst(native_exp, 83, List(OperandId))
+ExtInst(native_exp2, 84, List(OperandId))
+ExtInst(native_exp10, 85, List(OperandId))
+ExtInst(native_log, 86, List(OperandId))
+ExtInst(native_log2, 87, List(OperandId))
+ExtInst(native_log10, 88, List(OperandId))
+ExtInst(native_powr, 89, List(OperandId, OperandId))
+ExtInst(native_recip, 90, List(OperandId))
+ExtInst(native_rsqrt, 91, List(OperandId))
+ExtInst(native_sin, 92, List(OperandId))
+ExtInst(native_sqrt, 93, List(OperandId))
+ExtInst(native_tan, 94, List(OperandId))
+ExtInst(fclamp, 95, List(OperandId, OperandId, OperandId))
+ExtInst(degrees, 96, List(OperandId))
+ExtInst(fmax_common, 97, List(OperandId, OperandId))
+ExtInst(fmin_common, 98, List(OperandId, OperandId))
+ExtInst(mix, 99, List(OperandId, OperandId, OperandId))
+ExtInst(radians, 100, List(OperandId))
+ExtInst(step, 101, List(OperandId, OperandId))
+ExtInst(smoothstep, 102, List(OperandId, OperandId, OperandId))
+ExtInst(sign, 103, List(OperandId))
+ExtInst(cross, 104, List(OperandId, OperandId))
+ExtInst(distance, 105, List(OperandId, OperandId))
+ExtInst(length, 106, List(OperandId))
+ExtInst(normalize, 107, List(OperandId))
+ExtInst(fast_distance, 108, List(OperandId, OperandId))
+ExtInst(fast_length, 109, List(OperandId))
+ExtInst(fast_normalize, 110, List(OperandId))
+ExtInst(read_imagef, 111, EmptyList)
+ExtInst(read_imagei, 112, EmptyList)
+ExtInst(read_imageui, 113, EmptyList)
+ExtInst(read_imageh, 114, EmptyList)
+ExtInst(read_imagef_samplerless, 115, EmptyList)
+ExtInst(read_imagei_samplerless, 116, EmptyList)
+ExtInst(read_imageui_samplerless, 117, EmptyList)
+ExtInst(read_imageh_samplerless, 118, EmptyList)
+ExtInst(write_imagef, 119, EmptyList)
+ExtInst(write_imagei, 120, EmptyList)
+ExtInst(write_imageui, 121, EmptyList)
+ExtInst(write_imageh, 122, EmptyList)
+ExtInst(read_imagef_mipmap_lod, 123, EmptyList)
+ExtInst(read_imagei_mipmap_lod, 124, EmptyList)
+ExtInst(read_imageui_mipmap_lod, 125, EmptyList)
+ExtInst(read_imagef_mipmap_gradient, 126, EmptyList)
+ExtInst(read_imagei_mipmap_gradient, 127, EmptyList)
+ExtInst(read_imageui_mipmap_gradient, 128, EmptyList)
+ExtInst(write_imagef_mipmap_lod, 129, List(OperandId, OperandId, OperandId, OperandId))
+ExtInst(write_imagei_mipmap_lod, 130, List(OperandId, OperandId, OperandId, OperandId))
+ExtInst(write_imageui_mipmap_lod, 131, List(OperandId, OperandId, OperandId, OperandId))
+ExtInst(get_image_width, 132, EmptyList)
+ExtInst(get_image_height, 133, EmptyList)
+ExtInst(get_image_depth, 134, EmptyList)
+ExtInst(get_image_channel_data_type, 135, EmptyList)
+ExtInst(get_image_channel_order, 136, EmptyList)
+ExtInst(get_image_dim, 137, EmptyList)
+ExtInst(get_image_array_size, 138, EmptyList)
+ExtInst(get_image_num_samples, 139, EmptyList)
+ExtInst(get_image_num_mip_levels, 140, EmptyList)
+ExtInst(s_abs, 141, List(OperandId))
+ExtInst(s_abs_diff, 142, List(OperandId, OperandId))
+ExtInst(s_add_sat, 143, List(OperandId, OperandId))
+ExtInst(u_add_sat, 144, List(OperandId, OperandId))
+ExtInst(s_hadd, 145, List(OperandId, OperandId))
+ExtInst(u_hadd, 146, List(OperandId, OperandId))
+ExtInst(s_rhadd, 147, List(OperandId, OperandId))
+ExtInst(u_rhadd, 148, List(OperandId, OperandId))
+ExtInst(s_clamp, 149, List(OperandId, OperandId, OperandId))
+ExtInst(u_clamp, 150, List(OperandId, OperandId, OperandId))
+ExtInst(clz, 151, List(OperandId))
+ExtInst(ctz, 152, List(OperandId))
+ExtInst(s_mad_hi, 153, List(OperandId, OperandId, OperandId))
+ExtInst(u_mad_sat, 154, List(OperandId, OperandId, OperandId))
+ExtInst(s_mad_sat, 155, List(OperandId, OperandId, OperandId))
+ExtInst(s_max, 156, List(OperandId, OperandId))
+ExtInst(u_max, 157, List(OperandId, OperandId))
+ExtInst(s_min, 158, List(OperandId, OperandId))
+ExtInst(u_min, 159, List(OperandId, OperandId))
+ExtInst(s_mul_hi, 160, List(OperandId, OperandId))
+ExtInst(rotate, 161, List(OperandId, OperandId))
+ExtInst(s_sub_sat, 162, List(OperandId, OperandId))
+ExtInst(u_sub_sat, 163, List(OperandId, OperandId))
+ExtInst(u_upsample, 164, List(OperandId, OperandId))
+ExtInst(s_upsample, 165, List(OperandId, OperandId))
+ExtInst(popcount, 166, List(OperandId))
+ExtInst(s_mad24, 167, List(OperandId, OperandId, OperandId))
+ExtInst(u_mad24, 168, List(OperandId, OperandId, OperandId))
+ExtInst(s_mul24, 169, List(OperandId, OperandId))
+ExtInst(u_mul24, 170, List(OperandId, OperandId))
+ExtInst(vloadn, 171, List(OperandId, OperandId, OperandLiteralNumber))
+ExtInst(vstoren, 172, List(OperandId, OperandId, OperandId))
+ExtInst(vload_half, 173, List(OperandId, OperandId))
+ExtInst(vload_halfn, 174, List(OperandId, OperandId, OperandLiteralNumber))
+ExtInst(vstore_half, 175, List(OperandId, OperandId, OperandId))
+ExtInst(vstore_half_r, 176, List(OperandId, OperandId, OperandId, OperandFPRoundingMode))
+ExtInst(vstore_halfn, 177, List(OperandId, OperandId, OperandId))
+ExtInst(vstore_halfn_r, 178, List(OperandId, OperandId, OperandId, OperandFPRoundingMode))
+ExtInst(vloada_halfn, 179, List(OperandId, OperandId, OperandLiteralNumber))
+ExtInst(vstorea_halfn, 180, List(OperandId, OperandId, OperandId))
+ExtInst(vstorea_halfn_r, 181, List(OperandId, OperandId, OperandId, OperandFPRoundingMode))
+ExtInst(shuffle, 182, List(OperandId, OperandId))
+ExtInst(shuffle2, 183, List(OperandId, OperandId, OperandId))
+ExtInst(printf, 184, List(OperandId, OperandVariableIds))
+ExtInst(prefetch, 185, List(OperandId, OperandId))
+ExtInst(bitselect, 186, List(OperandId, OperandId, OperandId))
+ExtInst(select, 187, List(OperandId, OperandId, OperandId))
+ExtInst(read_pipe, 188, EmptyList)
+ExtInst(write_pipe, 189, EmptyList)
+ExtInst(reserve_read_pipe, 190, EmptyList)
+ExtInst(reserve_write_pipe, 191, EmptyList)
+ExtInst(commit_read_pipe, 192, EmptyList)
+ExtInst(commit_write_pipe, 193, EmptyList)
+ExtInst(is_valid_reserve_id, 194, EmptyList)
+ExtInst(work_group_reserve_read_pipe, 195, EmptyList)
+ExtInst(work_group_reserve_write_pipe, 196, EmptyList)
+ExtInst(work_group_commit_read_pipe, 197, EmptyList)
+ExtInst(work_group_commit_write_pipe, 198, EmptyList)
+ExtInst(get_pipe_num_packets, 199, EmptyList)
+ExtInst(get_pipe_max_packets, 200, EmptyList)
+ExtInst(u_abs, 201, List(OperandId))
+ExtInst(u_abs_diff, 202, List(OperandId, OperandId))
+ExtInst(u_mul_hi, 203, List(OperandId, OperandId))
+ExtInst(u_mad_hi, 204, List(OperandId, OperandId, OperandId))
disassemble.cpp
header.cpp
doc.cpp
+diff --git a/tools/spirv/OclDoc.cpp b/tools/spirv/OclDoc.cpp
+index c94eae2..ea47d42 100644
+--- a/tools/spirv/OclDoc.cpp
++++ b/tools/spirv/OclDoc.cpp
+@@ -28,11 +28,14 @@
+ #include "headers/spirv.hpp"
+ #include "headers/OpenCL.std.h"
+
+-#include "doc.h"
+ #include "OclDoc.h"
+
++#include "assembler_table.h"
++#include "doc.h"
++
+ #include <stdio.h>
+ #include <string.h>
++#include <cassert>
+ #include <algorithm>
+ #include <map>
+
+@@ -2358,4 +2361,27 @@ void PrintOclCommonDoc()
+ PrintOclDoc(SPIROpenCLCommonVersion);
+ }
+
++void PrintOclInstructionsTable(std::ostream& out) {
++ ParameterizeBuiltins(SPIROpenCLCommonVersion);
++
++ out << R"(
++// OpenCL extended instructions table, one instruction per line.
++// All instructions have a result type and a result ID.
++// Fields in this file are:
++// - name
++// - extended instruction index
++// - EmptyList, or List of operand classes.
++)";
++ for (int i = 0; i < OclExtInstCeiling; ++i) {
++ const BuiltInFunctionParameters& inst = BuiltInDesc[i];
++ // Skip gaps in the enum space, if any.
++ if (0 == strcmp("unknown", inst.opName)) continue;
++ assert(inst.hasType());
++ assert(inst.hasResult());
++ out << "ExtInst(" << inst.opName << ", " << i << ", ";
++ PrintOperandClasses(inst.operands.classes(), out);
++ out << ")" << std::endl;
++ }
++}
++
+ }; // end namespace spv
+diff --git a/tools/spirv/OclDoc.h b/tools/spirv/OclDoc.h
+index 8568880..7cf8a31 100644
+--- a/tools/spirv/OclDoc.h
++++ b/tools/spirv/OclDoc.h
+@@ -35,6 +35,8 @@
+ #include <map>
+ #include "headers/spirv.hpp"
+
++#include "doc.h"
++
+ namespace spv {
+
+ void OclGetDebugNames(const char** names);
+@@ -189,6 +191,8 @@ public:
+ int getImageType(int op) { return Type[op]; }
+ AccessQualifier getAccessQualifier(int op) { return accessQualifier[op]; }
+
++ const std::vector<OperandClass>& classes() const { return opClass; }
++
+ protected:
+ std::vector<OperandClass> opClass;
+ std::vector<const char*> desc;
+@@ -307,4 +311,7 @@ protected:
+ // Print out the OpenCL common (all spec revisions) documentation.
+ void PrintOclCommonDoc();
+
++// Prints the OpenCL instructions table, for consumption by SPIR-V Tools.
++void PrintOclInstructionsTable(std::ostream& out);
++
+ }; // end namespace spv
diff --git a/tools/spirv/assembler_table.cpp b/tools/spirv/assembler_table.cpp
new file mode 100644
-index 0000000..5a68ade
+index 0000000..85bca89
--- /dev/null
+++ b/tools/spirv/assembler_table.cpp
-@@ -0,0 +1,200 @@
+@@ -0,0 +1,214 @@
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+namespace {
+
+// Returns true if the given instruction can vary in width.
-+bool isVariableLength(const InstructionParameters& inst) {
++bool IsVariableLength(const InstructionParameters& inst) {
+ const OperandParameters& operands = inst.operands;
+ for (int i = 0; i < operands.getNum() ; i++) {
+ switch (operands.getClass(i)) {
+ return false;
+}
+
-+// Returns a string for the given operand class, or nullptr if
-+// it's invalid.
-+const char* getOperandClassString(OperandClass operandClass) {
++// Returns a string for the given operand class, or nullptr if it's invalid.
++const char* GetOperandClassString(OperandClass operandClass) {
+ switch (operandClass) {
+#define CASE(X) case X: return #X;
+ CASE(OperandNone)
+ CASE(OperandOpcode)
+#undef CASE
+
-+// case OperandNone:
+ case OperandCount:
+ default:
+ break;
+ }
+ return nullptr;
+}
++} // anonymous namespace
+
+// Prints a listing of the operand kinds for the given instruction.
+// If the list is empty, then emit just "EmptyList",
+// otherwise the output looks like a call to the "List" macro.
-+void printOperandClasses(const InstructionParameters& inst, std::ostream& out) {
++void PrintOperandClasses(const std::vector<OperandClass>& classes, std::ostream& out) {
+ std::stringstream contents;
-+
-+ const OperandParameters& operands = inst.operands;
+ int numPrinted = 0;
-+ for (int i = 0; i < operands.getNum() ; i++) {
-+ if (const char* name = getOperandClassString(operands.getClass(i))) {
-+ if (numPrinted)
-+ contents << ", ";
++ for (auto operandClass : classes) {
++ if (const char* name = GetOperandClassString(operandClass)) {
++ if (numPrinted) contents << ", ";
+ contents << name;
+ numPrinted++;
+ }
+ else
+ out << "EmptyList";
+}
++} // namespace spv
++
++namespace spv {
++namespace {
++
++// Prints a listing of the operand kinds for the given instruction.
++// If the list is empty, then emit just "EmptyList",
++// otherwise the output looks like a call to the "List" macro.
++void PrintOperandClassesForInstruction(const InstructionParameters& inst,
++ std::ostream& out) {
++ std::vector<OperandClass> result;
++
++ const OperandParameters& operands = inst.operands;
++ for (int i = 0; i < operands.getNum(); i++) {
++ result.push_back(operands.getClass(i));
++ }
++ PrintOperandClasses(result, out);
++}
+
+// Prints the table entry for the given instruction with the given opcode.
-+void printInstructionDesc(int opcode, const InstructionParameters& inst, std::ostream& out) {
++void PrintInstructionDesc(int opcode, const InstructionParameters& inst, std::ostream& out) {
+ const char* name = OpcodeString(opcode);
+ // There can be gaps in the listing.
+ // All valid operations have a name beginning with "Op".
+ out << "Capability(None), ";
+ }
+
-+ out << (isVariableLength(inst) ? 1 : 0) << ", ";
-+ printOperandClasses(inst, out);
++ out << (IsVariableLength(inst) ? 1 : 0) << ", ";
++ PrintOperandClassesForInstruction(inst, out);
+ out << ")" << std::endl;
+ }
+}
+
-+}
++} // anonymous namespace
+
+void PrintAssemblerTable(std::ostream& out) {
+ out << "// Instruction fields are:\n"
+ << "// #define Instruction(Name,HasResult,HasType,NumLogicalOperands,CapabiltyRequired,IsVariable,LogicalArgsList)\n";
+
+ for (int i = 0; i < spv::OpcodeCeiling ; i++ ) {
-+ printInstructionDesc(i, InstructionDesc[i], out);
++ PrintInstructionDesc(i, InstructionDesc[i], out);
+ }
+}
+
+}
diff --git a/tools/spirv/assembler_table.h b/tools/spirv/assembler_table.h
new file mode 100644
-index 0000000..03ab769
+index 0000000..b98303a
--- /dev/null
+++ b/tools/spirv/assembler_table.h
-@@ -0,0 +1,41 @@
+@@ -0,0 +1,49 @@
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+#define ASSEMBLER_TABLE_H
+
+#include <iostream>
++#include <vector>
++
++#include "doc.h"
+
+namespace spv {
+
+ // Assumes that parameterization has already occurred
+ void PrintAssemblerTable(std::ostream& out);
+
++ // Prints a listing of the operand kinds.
++ // If the list is empty, then emit just "EmptyList",
++ // otherwise the output looks like a call to the "List" macro.
++ void PrintOperandClasses(const std::vector<OperandClass>& classes, std::ostream& out);
++
+}; // end namespace spv
+
+#endif // ASSEMBLER_TABLE_H
diff --git a/tools/spirv/doc.h b/tools/spirv/doc.h
-index 78b1031..5984835 100644
+index 78b1031..a182509 100644
--- a/tools/spirv/doc.h
+++ b/tools/spirv/doc.h
-@@ -81,6 +81,7 @@ const char* KernelEnqueueFlagsString(int);
+@@ -32,6 +32,9 @@
+ //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ //POSSIBILITY OF SUCH DAMAGE.
+
++#ifndef DOC_H_
++#define DOC_H_
++
+ //
+ // Author: John Kessenich, LunarG
+ //
+@@ -81,6 +84,7 @@ const char* KernelEnqueueFlagsString(int);
const char* KernelProfilingInfoString(int);
const char* CapabilityString(int);
const char* OpcodeString(int);
// For grouping opcodes into subsections
enum OpcodeClass {
-@@ -159,6 +160,10 @@ enum OperandClass {
+@@ -159,6 +163,10 @@ enum OperandClass {
OperandOpcode,
OperandCount
};
+@@ -257,3 +265,5 @@ const char* AccessQualifierString(int attr);
+ void PrintOperands(const OperandParameters& operands, int reservedOperands);
+
+ }; // end namespace spv
++
++#endif // DOC_H_
diff --git a/tools/spirv/main.cpp b/tools/spirv/main.cpp
-index d7312f9..c856271 100644
+index d7312f9..e1413bb 100644
--- a/tools/spirv/main.cpp
+++ b/tools/spirv/main.cpp
@@ -46,6 +46,7 @@ namespace spv {
#include "disassemble.h"
#include "header.h"
#include "doc.h"
-@@ -65,6 +66,7 @@ enum TOptions {
+@@ -65,6 +66,8 @@ enum TOptions {
EOptionDisassemble = 0x004,
EOptionPrintHeader = 0x008,
EOptionPrintOclBuiltinsAsciidoc = 0x010,
+ EOptionPrintAssemblerTable = 0x020,
++ EOptionPrintOclInstructionsTable = 0x040,
};
std::string Filename;
-@@ -89,6 +91,7 @@ void Usage()
- " 'CL12': OpenCL 1.2 extended instructions documentation\n"
- " 'CL20': OpenCL 2.0 extended instructions documentation\n"
- " 'CL21': OpenCL 2.1 extended instructions documentation\n"
+@@ -86,9 +89,11 @@ void Usage()
+ " -H print header in all supported languages to files in current directory\n"
+ " -p print documentation\n"
+ " -s [version] prints the SPIR-V extended instructions documentation\n"
+- " 'CL12': OpenCL 1.2 extended instructions documentation\n"
+- " 'CL20': OpenCL 2.0 extended instructions documentation\n"
+- " 'CL21': OpenCL 2.1 extended instructions documentation\n"
++ " 'OpenCL': OpenCL 1.2, 2.0, 2.1 extended instructions documentation\n"
++ " 'GLSL': GLSL extended instructions documentation\n"
+ " -a print table for the assembler\n"
++ " -C print OpenCL instructions for the assembler\n"
++ " This is incompatibile with -s OpenCL\n"
);
}
-@@ -155,6 +158,9 @@ bool ProcessArguments(int argc, char* argv[])
+@@ -155,6 +160,12 @@ bool ProcessArguments(int argc, char* argv[])
}
return true;
}
+ case 'a':
+ Options |= EOptionPrintAssemblerTable;
+ break;
++ case 'C':
++ Options |= EOptionPrintOclInstructionsTable;
++ break;
default:
return false;
}
-@@ -220,5 +226,8 @@ int main(int argc, char* argv[])
+@@ -162,6 +173,9 @@ bool ProcessArguments(int argc, char* argv[])
+ Filename = std::string(argv[0]);
+ }
+ }
++ if ((Options & EOptionPrintOclBuiltinsAsciidoc) &&
++ (Options & EOptionPrintOclInstructionsTable))
++ return false;
+
+ return true;
+ }
+@@ -220,5 +234,11 @@ int main(int argc, char* argv[])
if (Options & EOptionPrintHeader)
spv::PrintHeader(Language, std::cout);
+ if (Options & EOptionPrintAssemblerTable)
+ spv::PrintAssemblerTable(std::cout);
+
++ if (Options & EOptionPrintOclInstructionsTable)
++ spv::PrintOclInstructionsTable(std::cout);
++
return 0;
}
--- /dev/null
+// Copyright (c) 2015 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 "UnitSPIRV.h"
+
+#include <gmock/gmock.h>
+#include "TestFixture.h"
+
+namespace {
+
+using spvtest::Concatenate;
+using spvtest::MakeInstruction;
+using spvtest::MakeVector;
+using testing::Eq;
+
+struct InstructionCase {
+ uint32_t opcode;
+ std::string name;
+ std::string operands;
+ std::vector<uint32_t> expected_operands;
+};
+
+using ExtInstOpenCLStdRoundTripTest =
+ spvtest::TextToBinaryTestBase<::testing::TestWithParam<InstructionCase>>;
+
+TEST_P(ExtInstOpenCLStdRoundTripTest, ParameterizedExtInst) {
+ // This example should not validate.
+ const std::string input =
+ "%1 = OpExtInstImport \"OpenCL.std\"\n"
+ "%3 = OpExtInst %2 %1 " +
+ GetParam().name + " " + GetParam().operands + "\n";
+ // First make sure it assembles correctly.
+ EXPECT_THAT(
+ CompiledInstructions(input),
+ Eq(Concatenate(
+ {MakeInstruction(spv::OpExtInstImport, {1}, MakeVector("OpenCL.std")),
+ MakeInstruction(spv::OpExtInst, {2, 3, 1, GetParam().opcode},
+ GetParam().expected_operands)})))
+ << input;
+ // Now check the round trip through the disassembler.
+ EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input;
+}
+
+#define CASE1(Enum, Name) \
+ { \
+ uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4", { 4 } \
+ }
+#define CASE2(Enum, Name) \
+ { \
+ uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5", { 4, 5 } \
+ }
+#define CASE3(Enum, Name) \
+ { \
+ uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6", { 4, 5, 6 } \
+ }
+
+// clang-format off
+// OpenCL.std: 2.1 Math extended instructions
+INSTANTIATE_TEST_CASE_P(
+ OpenCLMath, ExtInstOpenCLStdRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ // We are only testing the correctness of encoding and decoding here.
+ // Semantic correctness should be the responsibility of validator.
+ CASE1(Acos, acos), // enum value 0
+ CASE1(Acosh, acosh),
+ CASE1(Acospi, acospi),
+ CASE1(Asin, asin),
+ CASE1(Asinh, asinh),
+ CASE1(Asinh, asinh),
+ CASE1(Asinpi, asinpi),
+ CASE1(Atan, atan),
+ CASE2(Atan2, atan2),
+ CASE1(Atanh, atanh),
+ CASE1(Atanpi, atanpi),
+ CASE2(Atan2pi, atan2pi),
+ CASE1(Cbrt, cbrt),
+ CASE1(Ceil, ceil),
+ CASE1(Ceil, ceil),
+ CASE2(Copysign, copysign),
+ CASE1(Cos, cos),
+ CASE1(Cosh, cosh),
+ CASE1(Cospi, cospi),
+ CASE1(Erfc, erfc),
+ CASE1(Erf, erf),
+ CASE1(Exp, exp),
+ CASE1(Exp2, exp2),
+ CASE1(Exp10, exp10),
+ CASE1(Expm1, expm1),
+ CASE1(Fabs, fabs),
+ CASE2(Fdim, fdim),
+ CASE1(Floor, floor),
+ CASE3(Fma, fma),
+ CASE2(Fmax, fmax),
+ CASE2(Fmin, fmin),
+ CASE2(Fmod, fmod),
+ CASE2(Fract, fract),
+ CASE2(Frexp, frexp),
+ CASE2(Hypot, hypot),
+ CASE1(Ilogb, ilogb),
+ CASE2(Ldexp, ldexp),
+ CASE1(Lgamma, lgamma),
+ CASE2(Lgamma_r, lgamma_r),
+ CASE1(Log, log),
+ CASE1(Log2, log2),
+ CASE1(Log10, log10),
+ CASE1(Log1p, log1p),
+ CASE3(Mad, mad),
+ CASE2(Maxmag, maxmag),
+ CASE2(Minmag, minmag),
+ CASE2(Modf, modf),
+ CASE1(Nan, nan),
+ CASE2(Nextafter, nextafter),
+ CASE3(Pow, pow),
+ CASE1(Pown, pown),
+ CASE2(Powr, powr),
+ CASE2(Remainder, remainder),
+ CASE3(Remquo, remquo),
+ CASE1(Rint, rint),
+ CASE2(Rootn, rootn),
+ CASE1(Round, round),
+ CASE1(Rsqrt, rsqrt),
+ CASE1(Sin, sin),
+ CASE2(Sincos, sincos),
+ CASE1(Sinh, sinh),
+ CASE1(Sinpi, sinpi),
+ CASE1(Sqrt, sqrt),
+ CASE1(Tan, tan),
+ CASE1(Tanh, tanh),
+ CASE1(Tanpi, tanpi),
+ CASE1(Tgamma, tgamma),
+ CASE1(Trunc, trunc),
+ CASE1(Half_cos, half_cos),
+ CASE2(Half_divide, half_divide),
+ CASE1(Half_exp, half_exp),
+ CASE1(Half_exp2, half_exp2),
+ CASE1(Half_exp10, half_exp10),
+ CASE1(Half_log, half_log),
+ CASE1(Half_log2, half_log2),
+ CASE1(Half_log10, half_log10),
+ CASE2(Half_powr, half_powr),
+ CASE1(Half_recip, half_recip),
+ CASE1(Half_rsqrt, half_rsqrt),
+ CASE1(Half_sin, half_sin),
+ CASE1(Half_sqrt, half_sqrt),
+ CASE1(Half_tan, half_tan),
+ CASE1(Native_cos, native_cos),
+ CASE2(Native_divide, native_divide),
+ CASE1(Native_exp, native_exp),
+ CASE1(Native_exp2, native_exp2),
+ CASE1(Native_exp10, native_exp10),
+ CASE1(Native_log, native_log),
+ CASE1(Native_log10, native_log10),
+ CASE2(Native_powr, native_powr),
+ CASE1(Native_recip, native_recip),
+ CASE1(Native_rsqrt, native_rsqrt),
+ CASE1(Native_sin, native_sin),
+ CASE1(Native_sqrt, native_sqrt),
+ CASE1(Native_tan, native_tan), // enum value 94
+ })));
+
+// TODO(dneto): OpenCL.std: 2.1 Integer instructions
+
+// OpenCL.std: 2.3 Common instrucitons
+INSTANTIATE_TEST_CASE_P(
+ OpenCLCommon, ExtInstOpenCLStdRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE3(FClamp, fclamp), // enum value 95
+ CASE1(Degrees, degrees),
+ CASE2(FMax_common, fmax_common),
+ CASE2(FMin_common, fmin_common),
+ CASE3(Mix, mix),
+ CASE1(Radians, radians),
+ CASE2(Step, step),
+ CASE3(Smoothstep, smoothstep),
+ CASE1(Sign, sign), // enum value 103
+ })));
+
+// TODO(dneto): OpenCL.std: 2.4 Geometric instructions
+// TODO(dneto): OpenCL.std: 2.5 Relational instructions
+// TODO(dneto): OpenCL.std: 2.6 Vector data load and store instructions
+// TODO(dneto): OpenCL.std: 2.7 Miscellaneous vector instructions
+// TODO(dneto): OpenCL.std: 2.8 Miscellaneous instructions
+// TODO(dneto): OpenCL.std: 2.9.1 Image encoding
+// TODO(dneto): OpenCL.std: 2.9.2 Sampler encoding
+// TODO(dneto): OpenCL.std: 2.9.3 Image read
+// TODO(dneto): OpenCL.std: 2.9.4 Image write
+
+// clang-format on
+
+#undef CASE1
+#undef CASE2
+#undef CASE3
+
+} // anonymous namespace