SPV_CORE10_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.0/spirv.core.grammar.json
SPV_CORE11_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.1/spirv.core.grammar.json
SPV_CORE12_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.2/spirv.core.grammar.json
+SPV_CORELATEST_GRAMMAR=$(SPV_CORE12_GRAMMAR)
SPV_GLSL_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.2/extinst.glsl.std.450.grammar.json
SPV_OPENCL_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.2/extinst.opencl.std.100.grammar.json
+# TODO(dneto): I expect the DebugInfo grammar file to eventually migrate to SPIRV-Headers
+SPV_DEBUGINFO_GRAMMAR=$(LOCAL_PATH)/source/extinst.debuginfo.grammar.json
define gen_spvtools_grammar_tables
$(call generate-file-dir,$(1)/core.insts-1.0.inc)
$(LOCAL_PATH)/utils/generate_grammar_tables.py \
$(SPV_CORE10_GRAMMAR) \
$(SPV_GLSL_GRAMMAR) \
- $(SPV_OPENCL_GRAMMAR)
+ $(SPV_OPENCL_GRAMMAR) \
+ $(SPV_DEBUGINFO_GRAMMAR)
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
--spirv-core-grammar=$(SPV_CORE10_GRAMMAR) \
--extinst-glsl-grammar=$(SPV_GLSL_GRAMMAR) \
--extinst-opencl-grammar=$(SPV_OPENCL_GRAMMAR) \
+ --extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
--core-insts-output=$(1)/core.insts-1.0.inc \
--glsl-insts-output=$(1)/glsl.std.450.insts.inc \
--opencl-insts-output=$(1)/opencl.std.insts.inc \
@echo "[$(TARGET_ARCH_ABI)] Grammar v1.0 : instructions & operands <= grammar JSON files"
$(1)/core.insts-1.1.inc $(1)/operand.kinds-1.1.inc: \
$(LOCAL_PATH)/utils/generate_grammar_tables.py \
- $(SPV_CORE11_GRAMMAR)
+ $(SPV_CORE11_GRAMMAR) \
+ $(SPV_DEBUGINFO_GRAMMAR)
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
--spirv-core-grammar=$(SPV_CORE11_GRAMMAR) \
+ --extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
--core-insts-output=$(1)/core.insts-1.1.inc \
--operand-kinds-output=$(1)/operand.kinds-1.1.inc
@echo "[$(TARGET_ARCH_ABI)] Grammar v1.1 : instructions & operands <= grammar JSON files"
$(1)/core.insts-1.2.inc $(1)/operand.kinds-1.2.inc: \
$(LOCAL_PATH)/utils/generate_grammar_tables.py \
- $(SPV_CORE12_GRAMMAR)
+ $(SPV_CORE12_GRAMMAR) \
+ $(SPV_DEBUGINFO_GRAMMAR)
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
--spirv-core-grammar=$(SPV_CORE12_GRAMMAR) \
+ --extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
--core-insts-output=$(1)/core.insts-1.2.inc \
--operand-kinds-output=$(1)/operand.kinds-1.2.inc
@echo "[$(TARGET_ARCH_ABI)] Grammar v1.2 : instructions & operands <= grammar JSON files"
endef
$(eval $(call gen_spvtools_grammar_tables,$(SPVTOOLS_OUT_PATH)))
+
+define gen_spvtools_lang_headers
+# Generate language-specific headers. So far we only generate C headers
+# $1 is the output directory.
+# $2 is the base name of the header file, e.g. "DebugInfo".
+# $3 is the grammar file containing token definitions.
+$(call generate-file-dir,$(1)/$(2).h)
+$(1)/$(2).h : \
+ $(LOCAL_PATH)/utils/generate_language_headers.py \
+ $(3)
+ @$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_language_headers.py \
+ --extinst-name=$(2) \
+ --extinst-grammar=$(3) \
+ --extinst-output-base=$(1)/$(2)
+ @echo "[$(TARGET_ARCH_ABI)] Generate language specific header for $(2): headers <= grammar"
+$(LOCAL_PATH)/source/ext_inst.cpp: $(1)/$(2).h
+endef
+# We generate language-specific headers for DebugInfo
+$(eval $(call gen_spvtools_lang_headers,$(SPVTOOLS_OUT_PATH),DebugInfo,$(SPV_DEBUGINFO_GRAMMAR)))
+
+
define gen_spvtools_vendor_tables
$(call generate-file-dir,$(1)/$(2).insts.inc)
$(1)/$(2).insts.inc : \
$(call generate-file-dir,$(1)/extension_enum.inc.inc)
$(1)/extension_enum.inc $(1)/enum_string_mapping.inc: \
$(LOCAL_PATH)/utils/generate_grammar_tables.py \
- $(SPV_CORE11_GRAMMAR)
+ $(SPV_CORELATEST_GRAMMAR)
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
- --spirv-core-grammar=$(SPV_CORE11_GRAMMAR) \
+ --spirv-core-grammar=$(SPV_CORELATEST_GRAMMAR) \
+ --extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
--extension-enum-output=$(1)/extension_enum.inc \
--enum-string-mapping-output=$(1)/enum_string_mapping.inc
@echo "[$(TARGET_ARCH_ABI)] Generate enum<->string mapping <= grammar JSON files"
// A sequence of zero or more pairs of (Id, Literal integer)
LAST_VARIABLE(SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER),
+ // The following are concrete enum types.
+ SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, // DebugInfo Sec 3.2. A mask.
+ SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING, // DebugInfo Sec 3.3
+ SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE, // DebugInfo Sec 3.4
+ SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER, // DebugInfo Sec 3.5
+ SPV_OPERAND_TYPE_DEBUG_OPERATION, // DebugInfo Sec 3.6
+
// This is a sentinel value, and does not represent an operand type.
// It should come last.
SPV_OPERAND_TYPE_NUM_OPERAND_TYPES,
SPV_EXT_INST_TYPE_SPV_AMD_SHADER_TRINARY_MINMAX,
SPV_EXT_INST_TYPE_SPV_AMD_GCN_SHADER,
SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT,
+ SPV_EXT_INST_TYPE_DEBUGINFO,
SPV_FORCE_32_BIT_ENUM(spv_ext_inst_type_t)
} spv_ext_inst_type_t;
set(GRAMMAR_PROCESSING_SCRIPT "${spirv-tools_SOURCE_DIR}/utils/generate_grammar_tables.py")
set(VIMSYNTAX_PROCESSING_SCRIPT "${spirv-tools_SOURCE_DIR}/utils/generate_vim_syntax.py")
set(XML_REGISTRY_PROCESSING_SCRIPT "${spirv-tools_SOURCE_DIR}/utils/generate_registry_tables.py")
+set(LANG_HEADER_PROCESSING_SCRIPT "${spirv-tools_SOURCE_DIR}/utils/generate_language_headers.py")
+
+# For now, assume the DebugInfo grammar file is in the current directory.
+# It might migrate to SPIRV-Headers.
+set(DEBUGINFO_GRAMMAR_JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/extinst.debuginfo.grammar.json")
# macro() definitions are used in the following because we need to append .inc
# file paths into some global lists (*_CPP_DEPENDS). And those global lists are
add_custom_command(OUTPUT ${GRAMMAR_INSTS_INC_FILE} ${GRAMMAR_KINDS_INC_FILE}
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
--spirv-core-grammar=${GRAMMAR_JSON_FILE}
+ --extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
--core-insts-output=${GRAMMAR_INSTS_INC_FILE}
--operand-kinds-output=${GRAMMAR_KINDS_INC_FILE}
- DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${GRAMMAR_JSON_FILE}
+ DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${GRAMMAR_JSON_FILE} ${DEBUGINFO_GRAMMAR_JSON_FILE}
COMMENT "Generate info tables for SPIR-V v${VERSION} core instructions and operands.")
list(APPEND OPCODE_CPP_DEPENDS ${GRAMMAR_INSTS_INC_FILE})
list(APPEND OPERAND_CPP_DEPENDS ${GRAMMAR_KINDS_INC_FILE})
${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
--spirv-core-grammar=${GRAMMAR_JSON_FILE}
+ --extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
--extension-enum-output=${GRAMMAR_EXTENSION_ENUM_INC_FILE}
--enum-string-mapping-output=${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}
- DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${GRAMMAR_JSON_FILE}
+ DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${GRAMMAR_JSON_FILE} ${DEBUGINFO_GRAMMAR_JSON_FILE}
COMMENT "Generate enum-string mapping for SPIR-V v${VERSION}.")
list(APPEND EXTENSION_H_DEPENDS ${GRAMMAR_EXTENSION_ENUM_INC_FILE})
list(APPEND ENUM_STRING_MAPPING_CPP_DEPENDS ${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE})
add_custom_command(OUTPUT ${VIMSYNTAX_FILE}
COMMAND ${PYTHON_EXECUTABLE} ${VIMSYNTAX_PROCESSING_SCRIPT}
--spirv-core-grammar=${GRAMMAR_JSON_FILE}
+ --exinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
--extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE}
--extinst-opencl-grammar=${OPENCL_GRAMMAR_JSON_FILE}
>${VIMSYNTAX_FILE}
DEPENDS ${VIMSYNTAX_PROCESSING_SCRIPT} ${GRAMMAR_JSON_FILE}
- ${GLSL_GRAMMAR_JSON_FILE} ${OPENCL_GRAMMAR_JSON_FILE}
+ ${GLSL_GRAMMAR_JSON_FILE} ${OPENCL_GRAMMAR_JSON_FILE} ${DEBUGINFO_GRAMMAR_JSON_FILE}
COMMENT "Generate spvasm.vim: Vim syntax file for SPIR-V assembly.")
endmacro(spvtools_vimsyntax)
set(GRAMMAR_INC_FILE "${spirv-tools_BINARY_DIR}/glsl.std.450.insts.inc")
add_custom_command(OUTPUT ${GRAMMAR_INC_FILE}
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
- --spirv-core-grammar=${CORE_GRAMMAR_JSON_FILE}
--extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE}
--glsl-insts-output=${GRAMMAR_INC_FILE}
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${GLSL_GRAMMAR_JSON_FILE}
set(GRAMMAR_INC_FILE "${spirv-tools_BINARY_DIR}/opencl.std.insts.inc")
add_custom_command(OUTPUT ${GRAMMAR_INC_FILE}
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
- --spirv-core-grammar=${CORE_GRAMMAR_JSON_FILE}
--extinst-opencl-grammar=${OPENCL_GRAMMAR_JSON_FILE}
--opencl-insts-output=${GRAMMAR_INC_FILE}
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${OPENCL_GRAMMAR_JSON_FILE}
set_property(TARGET spirv-tools-${VENDOR_TABLE} PROPERTY FOLDER "SPIRV-Tools build")
endmacro(spvtools_vendor_tables)
+macro(spvtools_extinst_lang_headers NAME GRAMMAR_FILE)
+ set(OUTBASE ${spirv-tools_BINARY_DIR}/${NAME})
+ set(OUT_H ${OUTBASE}.h)
+ add_custom_command(OUTPUT ${OUT_H}
+ COMMAND ${PYTHON_EXECUTABLE} ${LANG_HEADER_PROCESSING_SCRIPT}
+ --extinst-name=${NAME}
+ --extinst-grammar=${GRAMMAR_FILE}
+ --extinst-output-base=${OUTBASE}
+ DEPENDS ${LANG_HEADER_PROCESSING_SCRIPT} ${GRAMMAR_FILE}
+ COMMENT "Generate language specific header for ${NAME}.")
+ list(APPEND EXTINST_CPP_DEPENDS ${OUT_H})
+ add_custom_target(spirv-tools-header-${NAME} DEPENDS ${OUT_H})
+ set_property(TARGET spirv-tools-header-${NAME} PROPERTY FOLDER "SPIRV-Tools build")
+endmacro(spvtools_extinst_lang_headers)
+
+
spvtools_core_tables("1.0")
spvtools_core_tables("1.1")
spvtools_core_tables("1.2")
spvtools_vendor_tables("spv-amd-shader-trinary-minmax")
spvtools_vendor_tables("spv-amd-gcn-shader")
spvtools_vendor_tables("spv-amd-shader-ballot")
+spvtools_vendor_tables("debuginfo")
+spvtools_extinst_lang_headers("DebugInfo" ${DEBUGINFO_GRAMMAR_JSON_FILE})
spvtools_vimsyntax("1.2" "1.0")
add_custom_target(spirv-tools-vimsyntax DEPENDS ${VIMSYNTAX_FILE})
case SPV_OPERAND_TYPE_BUILT_IN:
case SPV_OPERAND_TYPE_GROUP_OPERATION:
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
- case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO: {
+ case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
+ case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
+ case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
+ case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
+ case SPV_OPERAND_TYPE_DEBUG_OPERATION: {
// A single word that is a plain enum value.
// Map an optional operand type to its corresponding concrete type.
case SPV_OPERAND_TYPE_IMAGE:
case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
- case SPV_OPERAND_TYPE_SELECTION_CONTROL: {
+ case SPV_OPERAND_TYPE_SELECTION_CONTROL:
+ case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: {
// This operand is a mask.
// Map an optional operand type to its corresponding concrete type.
case SPV_OPERAND_TYPE_BUILT_IN:
case SPV_OPERAND_TYPE_GROUP_OPERATION:
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
- case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO: {
+ case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
+ case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
+ case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
+ case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
+ case SPV_OPERAND_TYPE_DEBUG_OPERATION: {
spv_operand_desc entry;
if (grammar_.lookupOperand(operand.type, word, &entry))
assert(false && "should have caught this earlier");
case SPV_OPERAND_TYPE_IMAGE:
case SPV_OPERAND_TYPE_MEMORY_ACCESS:
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
+ case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
EmitMaskOperand(operand.type, word);
break;
default:
#include <cassert>
#include <cstring>
+// DebugInfo extended instruction set.
+// See https://www.khronos.org/registry/spir-v/specs/1.0/DebugInfo.html
+// TODO(dneto): DebugInfo.h should probably move to SPIRV-Headers.
+#include "DebugInfo.h"
+
#include "latest_version_glsl_std_450_header.h"
#include "latest_version_opencl_std_header.h"
-#include "spirv_definition.h"
-
#include "macro.h"
+#include "spirv_definition.h"
+#include "debuginfo.insts.inc" // defines opencl_entries
#include "glsl.std.450.insts.inc" // defines glsl_entries
#include "opencl.std.insts.inc" // defines opencl_entries
ARRAY_SIZE(spv_amd_gcn_shader_entries), spv_amd_gcn_shader_entries},
{SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT,
ARRAY_SIZE(spv_amd_shader_ballot_entries), spv_amd_shader_ballot_entries},
+ {SPV_EXT_INST_TYPE_DEBUGINFO, ARRAY_SIZE(debuginfo_entries),
+ debuginfo_entries},
};
static const spv_ext_inst_table_t kTable_1_0 = {ARRAY_SIZE(kGroups_1_0),
if (!strcmp("SPV_AMD_shader_ballot", name)) {
return SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT;
}
+ if (!strcmp("DebugInfo", name)) {
+ return SPV_EXT_INST_TYPE_DEBUGINFO;
+ }
return SPV_EXT_INST_TYPE_NONE;
}
--- /dev/null
+{
+ "copyright" : [
+ "Copyright (c) 2017 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."
+ ],
+ "version" : 100,
+ "revision" : 1,
+ "instructions" : [
+ {
+ "opname" : "DebugInfoNone",
+ "opcode" : 0
+ },
+ {
+ "opname" : "DebugCompilationUnit",
+ "opcode" : 1,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Version'" },
+ { "kind" : "LiteralInteger", "name" : "'DWARF Version'" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeBasic",
+ "opcode" : 2,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "IdRef", "name" : "'Size'" },
+ { "kind" : "DebugBaseTypeAttributeEncoding", "name" : "'Encoding'" }
+ ]
+ },
+ {
+ "opname" : "DebugTypePointer",
+ "opcode" : 3,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Base Type'" },
+ { "kind" : "StorageClass", "name" : "'Storage Class'" },
+ { "kind" : "DebugInfoFlags", "name" : "'Literal Flags'" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeQualifier",
+ "opcode" : 4,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Base Type'" },
+ { "kind" : "DebugTypeQualifier", "name" : "'Type Qualifier'" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeArray",
+ "opcode" : 5,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Base Type'" },
+ { "kind" : "IdRef", "name" : "'Component Counts'", "quantifier" : "*" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeVector",
+ "opcode" : 6,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Base Type'" },
+ { "kind" : "LiteralInteger", "name" : "'Component Count'" }
+ ]
+ },
+ {
+ "opname" : "DebugTypedef",
+ "opcode" : 7,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "IdRef", "name" : "'Base Type'" },
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "LiteralInteger", "name" : "'Column'" },
+ { "kind" : "IdRef", "name" : "'Parent'" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeFunction",
+ "opcode" : 8,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Return Type'" },
+ { "kind" : "IdRef", "name" : "'Paramter Types'", "quantifier" : "*" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeEnum",
+ "opcode" : 9,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "IdRef", "name" : "'Underlying Type'" },
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "LiteralInteger", "name" : "'Column'" },
+ { "kind" : "IdRef", "name" : "'Parent'" },
+ { "kind" : "IdRef", "name" : "'Size'" },
+ { "kind" : "DebugInfoFlags", "name" : "'Flags'" },
+ { "kind" : "PairIdRefIdRef", "name" : "'Value, Name, Value, Name, ...'", "quantifier" : "*" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeComposite",
+ "opcode" : 10,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "DebugCompositeType", "name" : "'Tag'" },
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "LiteralInteger", "name" : "'Column'" },
+ { "kind" : "IdRef", "name" : "'Parent'" },
+ { "kind" : "IdRef", "name" : "'Size'" },
+ { "kind" : "DebugInfoFlags", "name" : "'Flags'" },
+ { "kind" : "IdRef", "name" : "'Members'", "quantifier" : "*" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeMember",
+ "opcode" : 11,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "IdRef", "name" : "'Type'" },
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "LiteralInteger", "name" : "'Column'" },
+ { "kind" : "IdRef", "name" : "'Parent'" },
+ { "kind" : "IdRef", "name" : "'Offset'" },
+ { "kind" : "IdRef", "name" : "'Size'" },
+ { "kind" : "DebugInfoFlags", "name" : "'Flags'" },
+ { "kind" : "IdRef", "name" : "'Value'", "quantifier" : "?" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeInheritance",
+ "opcode" : 12,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Child'" },
+ { "kind" : "IdRef", "name" : "'Parent'" },
+ { "kind" : "IdRef", "name" : "'Offset'" },
+ { "kind" : "IdRef", "name" : "'Size'" },
+ { "kind" : "DebugInfoFlags", "name" : "'Flags'" }
+ ]
+ },
+ {
+ "opname" : "DebugTypePtrToMember",
+ "opcode" : 13,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Member Type'" },
+ { "kind" : "IdRef", "name" : "'Parent'" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeTemplate",
+ "opcode" : 14,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Target'" },
+ { "kind" : "IdRef", "name" : "'Parameters'", "quantifier" : "*" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeTemplateParameter",
+ "opcode" : 15,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "IdRef", "name" : "'Actual Type'" },
+ { "kind" : "IdRef", "name" : "'Value'" },
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "LiteralInteger", "name" : "'Column'" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeTemplateTemplateParameter",
+ "opcode" : 16,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "IdRef", "name" : "'Template Name'" },
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "LiteralInteger", "name" : "'Column'" }
+ ]
+ },
+ {
+ "opname" : "DebugTypeTemplateParameterPack",
+ "opcode" : 17,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "LiteralInteger", "name" : "'Column'" },
+ { "kind" : "IdRef", "name" : "'Template Parameters'", "quantifier" : "*" }
+ ]
+ },
+ {
+ "opname" : "DebugGlobalVariable",
+ "opcode" : 18,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "IdRef", "name" : "'Type'" },
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "LiteralInteger", "name" : "'Column'" },
+ { "kind" : "IdRef", "name" : "'Parent'" },
+ { "kind" : "IdRef", "name" : "'Linkage Name'" },
+ { "kind" : "IdRef", "name" : "'Variable'" },
+ { "kind" : "DebugInfoFlags", "name" : "'Flags'" },
+ { "kind" : "IdRef", "name" : "'Static Member Declaration'", "quantifier" : "?" }
+ ]
+ },
+ {
+ "opname" : "DebugFunctionDeclaration",
+ "opcode" : 19,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "IdRef", "name" : "'Type'" },
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "LiteralInteger", "name" : "'Column'" },
+ { "kind" : "IdRef", "name" : "'Parent'" },
+ { "kind" : "IdRef", "name" : "'Linkage Name'" },
+ { "kind" : "DebugInfoFlags", "name" : "'Flags'" }
+ ]
+ },
+ {
+ "opname" : "DebugFunction",
+ "opcode" : 20,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "IdRef", "name" : "'Type'" },
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "LiteralInteger", "name" : "'Column'" },
+ { "kind" : "IdRef", "name" : "'Parent'" },
+ { "kind" : "IdRef", "name" : "'Linkage Name'" },
+ { "kind" : "DebugInfoFlags", "name" : "'Flags'" },
+ { "kind" : "LiteralInteger", "name" : "'Scope Line'" },
+ { "kind" : "IdRef", "name" : "'Function'" },
+ { "kind" : "IdRef", "name" : "'Declaration'", "quantifier" : "?" }
+ ]
+ },
+ {
+ "opname" : "DebugLexicalBlock",
+ "opcode" : 21,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "LiteralInteger", "name" : "'Column'" },
+ { "kind" : "IdRef", "name" : "'Parent'" },
+ { "kind" : "IdRef", "name" : "'Name'", "quantifier" : "?" }
+ ]
+ },
+ {
+ "opname" : "DebugLexicalBlockDiscriminator",
+ "opcode" : 22,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Scope'" },
+ { "kind" : "LiteralInteger", "name" : "'Discriminator'" },
+ { "kind" : "IdRef", "name" : "'Parent'" }
+ ]
+ },
+ {
+ "opname" : "DebugScope",
+ "opcode" : 23,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Scope'" },
+ { "kind" : "IdRef", "name" : "'Inlined At'", "quantifier" : "?" }
+ ]
+ },
+ {
+ "opname" : "DebugNoScope",
+ "opcode" : 24
+ },
+ {
+ "opname" : "DebugInlinedAt",
+ "opcode" : 25,
+ "operands" : [
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "IdRef", "name" : "'Scope'" },
+ { "kind" : "IdRef", "name" : "'Inlined'", "quantifier" : "?" }
+ ]
+ },
+ {
+ "opname" : "DebugLocalVariable",
+ "opcode" : 26,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "IdRef", "name" : "'Type'" },
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "LiteralInteger", "name" : "'Column'" },
+ { "kind" : "IdRef", "name" : "'Parent'" },
+ { "kind" : "LiteralInteger", "name" : "'Arg Number'", "quantifier" : "?" }
+ ]
+ },
+ {
+ "opname" : "DebugInlinedVariable",
+ "opcode" : 27,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Variable'" },
+ { "kind" : "IdRef", "name" : "'Inlined'" }
+ ]
+ },
+ {
+ "opname" : "DebugDeclare",
+ "opcode" : 28,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Local Variable'" },
+ { "kind" : "IdRef", "name" : "'Variable'" },
+ { "kind" : "IdRef", "name" : "'Expression'" }
+ ]
+ },
+ {
+ "opname" : "DebugValue",
+ "opcode" : 29,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Value'" },
+ { "kind" : "IdRef", "name" : "'Expression'" },
+ { "kind" : "IdRef", "name" : "'Indexes'", "quantifier" : "*" }
+ ]
+ },
+ {
+ "opname" : "DebugOperation",
+ "opcode" : 30,
+ "operands" : [
+ { "kind" : "DebugOperation", "name" : "'OpCode'" },
+ { "kind" : "LiteralInteger", "name" : "'Operands ...'", "quantifier" : "*" }
+ ]
+ },
+ {
+ "opname" : "DebugExpression",
+ "opcode" : 31,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Operands ...'", "quantifier" : "*" }
+ ]
+ },
+ {
+ "opname" : "DebugMacroDef",
+ "opcode" : 32,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "IdRef", "name" : "'Name'" },
+ { "kind" : "IdRef", "name" : "'Value'", "quantifier" : "?" }
+ ]
+ },
+ {
+ "opname" : "DebugMacroUndef",
+ "opcode" : 33,
+ "operands" : [
+ { "kind" : "IdRef", "name" : "'Source'" },
+ { "kind" : "LiteralInteger", "name" : "'Line'" },
+ { "kind" : "IdRef", "name" : "'Macro'" }
+ ]
+ }
+ ],
+ "operand_kinds" : [
+ {
+ "category" : "BitEnum",
+ "kind" : "DebugInfoFlags",
+ "enumerants" : [
+ {
+ "enumerant" : "FlagIsProtected",
+ "value" : "0x01"
+ },
+ {
+ "enumerant" : "FlagIsPrivate",
+ "value" : "0x02"
+ },
+ {
+ "enumerant" : "FlagIsPublic",
+ "value" : "0x03"
+ },
+ {
+ "enumerant" : "FlagIsLocal",
+ "value" : "0x04"
+ },
+ {
+ "enumerant" : "FlagIsDefinition",
+ "value" : "0x08"
+ },
+ {
+ "enumerant" : "FlagFwdDecl",
+ "value" : "0x10"
+ },
+ {
+ "enumerant" : "FlagArtificial",
+ "value" : "0x20"
+ },
+ {
+ "enumerant" : "FlagExplicit",
+ "value" : "0x40"
+ },
+ {
+ "enumerant" : "FlagPrototyped",
+ "value" : "0x80"
+ },
+ {
+ "enumerant" : "FlagObjectPointer",
+ "value" : "0x100"
+ },
+ {
+ "enumerant" : "FlagStaticMember",
+ "value" : "0x200"
+ },
+ {
+ "enumerant" : "FlagIndirectVariable",
+ "value" : "0x400"
+ },
+ {
+ "enumerant" : "FlagLValueReference",
+ "value" : "0x800"
+ },
+ {
+ "enumerant" : "FlagRValueReference",
+ "value" : "0x1000"
+ },
+ {
+ "enumerant" : "FlagIsOptimized",
+ "value" : "0x2000"
+ }
+ ]
+ },
+ {
+ "category" : "ValueEnum",
+ "kind" : "DebugBaseTypeAttributeEncoding",
+ "enumerants" : [
+ {
+ "enumerant" : "Unspecified",
+ "value" : "0"
+ },
+ {
+ "enumerant" : "Address",
+ "value" : "1"
+ },
+ {
+ "enumerant" : "Boolean",
+ "value" : "2"
+ },
+ {
+ "enumerant" : "Float",
+ "value" : "4"
+ },
+ {
+ "enumerant" : "Signed",
+ "value" : "5"
+ },
+ {
+ "enumerant" : "SignedChar",
+ "value" : "6"
+ },
+ {
+ "enumerant" : "Unsigned",
+ "value" : "7"
+ },
+ {
+ "enumerant" : "UnsignedChar",
+ "value" : "8"
+ }
+ ]
+ },
+ {
+ "category" : "ValueEnum",
+ "kind" : "DebugCompositeType",
+ "enumerants" : [
+ {
+ "enumerant" : "Class",
+ "value" : "0"
+ },
+ {
+ "enumerant" : "Structure",
+ "value" : "1"
+ },
+ {
+ "enumerant" : "Union",
+ "value" : "2"
+ }
+ ]
+ },
+ {
+ "category" : "ValueEnum",
+ "kind" : "DebugTypeQualifier",
+ "enumerants" : [
+ {
+ "enumerant" : "ConstType",
+ "value" : "0"
+ },
+ {
+ "enumerant" : "VolatileType",
+ "value" : "1"
+ },
+ {
+ "enumerant" : "RestrictType",
+ "value" : "2"
+ }
+ ]
+ },
+ {
+ "category" : "ValueEnum",
+ "kind" : "DebugOperation",
+ "enumerants" : [
+ {
+ "enumerant" : "Deref",
+ "value" : "0"
+ },
+ {
+ "enumerant" : "Plus",
+ "value" : "1"
+ },
+ {
+ "enumerant" : "Minus",
+ "value" : "2"
+ },
+ {
+ "enumerant" : "PlusUconst",
+ "value" : "3",
+ "parameters" : [
+ { "kind" : "LiteralInteger" }
+ ]
+ },
+ {
+ "enumerant" : "BitPiece",
+ "value" : "4",
+ "parameters" : [
+ { "kind" : "LiteralInteger" },
+ { "kind" : "LiteralInteger" }
+ ]
+ },
+ {
+ "enumerant" : "Swap",
+ "value" : "5"
+ },
+ {
+ "enumerant" : "Xderef",
+ "value" : "6"
+ },
+ {
+ "enumerant" : "StackValue",
+ "value" : "7"
+ },
+ {
+ "enumerant" : "Constu",
+ "value" : "8",
+ "parameters" : [
+ { "kind" : "LiteralInteger" }
+ ]
+ }
+ ]
+ }
+ ]
+}
return "image";
case SPV_OPERAND_TYPE_OPTIONAL_CIV:
return "context-insensitive value";
+ case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
+ return "debug info flags";
+ case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
+ return "debug base type encoding";
+ case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
+ return "debug composite type";
+ case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
+ return "debug type qualifier";
+ case SPV_OPERAND_TYPE_DEBUG_OPERATION:
+ return "debug operation";
// The next values are for values returned from an instruction, not actually
// an operand. So the specific strings don't matter. But let's add them
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
case SPV_OPERAND_TYPE_CAPABILITY:
+ case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
+ case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
+ case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
+ case SPV_OPERAND_TYPE_DEBUG_OPERATION:
return true;
default:
break;
case SPV_OPERAND_TYPE_LOOP_CONTROL:
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
case SPV_OPERAND_TYPE_MEMORY_ACCESS:
+ case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
return true;
default:
break;
if (context->binaryEncodeString(literal.str.c_str(), pInst))
return SPV_ERROR_INVALID_TEXT;
} break;
+
+ // Masks.
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
case SPV_OPERAND_TYPE_LOOP_CONTROL:
case SPV_OPERAND_TYPE_IMAGE:
case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
- case SPV_OPERAND_TYPE_SELECTION_CONTROL: {
+ case SPV_OPERAND_TYPE_SELECTION_CONTROL:
+ case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: {
uint32_t value;
if (grammar.parseMaskOperand(type, textValue, &value)) {
return context->diagnostic() << "Invalid " << spvOperandTypeStr(type)
comment_test.cpp
enum_string_mapping_test.cpp
enum_set_test.cpp
+ ext_inst.debuginfo_test.cpp
ext_inst.glsl_test.cpp
ext_inst.opencl_test.cpp
fix_word_test.cpp
--- /dev/null
+// Copyright (c) 2017 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "unit_spirv.h"
+
+#include <gmock/gmock.h>
+#include "DebugInfo.h"
+#include "test_fixture.h"
+
+// This file tests the correctness of encoding and decoding of instructions
+// involving the DebugInfo extended instruction set.
+// Semantic correctness should be the responsibility of validator.
+//
+// See https://www.khronos.org/registry/spir-v/specs/1.0/DebugInfo.html
+
+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 ExtInstDebugInfoRoundTripTest =
+ spvtest::TextToBinaryTestBase<::testing::TestWithParam<InstructionCase>>;
+using ExtInstDebugInfoRoundTripTestExplicit = spvtest::TextToBinaryTest;
+
+TEST_P(ExtInstDebugInfoRoundTripTest, ParameterizedExtInst) {
+ const std::string input =
+ "%1 = OpExtInstImport \"DebugInfo\"\n"
+ "%3 = OpExtInst %2 %1 " +
+ GetParam().name + GetParam().operands + "\n";
+ // First make sure it assembles correctly.
+ EXPECT_THAT(
+ CompiledInstructions(input),
+ Eq(Concatenate(
+ {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("DebugInfo")),
+ MakeInstruction(SpvOpExtInst, {2, 3, 1, GetParam().opcode},
+ GetParam().expected_operands)})))
+ << input;
+ // Now check the round trip through the disassembler.
+ EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input;
+}
+
+#define CASE_0(Enum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, "", {} \
+ }
+
+#define CASE_ILL(Enum, L0, L1) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #L0 " " #L1, { \
+ 4, L0, L1 \
+ } \
+ }
+
+#define CASE_IL(Enum, L0) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #L0, { 4, L0 } \
+ }
+
+#define CASE_I(Enum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4", { 4 } \
+ }
+
+#define CASE_II(Enum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5", { 4, 5 } \
+ }
+
+#define CASE_III(Enum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6", { 4, 5, 6 } \
+ }
+
+#define CASE_IIII(Enum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6 %7", { \
+ 4, 5, 6, 7 \
+ } \
+ }
+
+#define CASE_IIIII(Enum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6 %7 %8", { \
+ 4, 5, 6, 7, 8 \
+ } \
+ }
+
+#define CASE_IIIIII(Enum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6 %7 %8 %9", { \
+ 4, 5, 6, 7, 8, 9 \
+ } \
+ }
+
+#define CASE_IIIIIII(Enum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6 %7 %8 %9 %10", { \
+ 4, 5, 6, 7, 8, 9, 10 \
+ } \
+ }
+
+#define CASE_IIILLI(Enum, L0, L1) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 %6 " #L0 " " #L1 " %7", { \
+ 4, 5, 6, L0, L1, 7 \
+ } \
+ }
+
+#define CASE_IIILLIL(Enum, L0, L1, L2) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 %6 " #L0 " " #L1 " %7 " #L2, { \
+ 4, 5, 6, L0, L1, 7, L2 \
+ } \
+ }
+
+#define CASE_IE(Enum, E0) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #E0, { \
+ 4, uint32_t(DebugInfo##E0) \
+ } \
+ }
+
+#define CASE_IIE(Enum, E0) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 " #E0, { \
+ 4, 5, uint32_t(DebugInfo##E0) \
+ } \
+ }
+
+#define CASE_ISF(Enum, S0, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #S0 " " Fstr, { \
+ 4, uint32_t(SpvStorageClass##S0), Fnum \
+ } \
+ }
+
+#define CASE_LII(Enum, L0) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " " #L0 " %4 %5", { \
+ L0, 4, 5 \
+ } \
+ }
+
+#define CASE_ILI(Enum, L0) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #L0 " %5", { \
+ 4, L0, 5 \
+ } \
+ }
+
+#define CASE_ILII(Enum, L0) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #L0 " %5 %6", { \
+ 4, L0, 5, 6 \
+ } \
+ }
+
+#define CASE_ILLII(Enum, L0, L1) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 " #L0 " " #L1 " %5 %6", { \
+ 4, L0, L1, 5, 6 \
+ } \
+ }
+
+#define CASE_IIILLIIF(Enum, L0, L1, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 %6 " #L0 " " #L1 " %7 %8 " Fstr, { \
+ 4, 5, 6, L0, L1, 7, 8, Fnum \
+ } \
+ }
+
+#define CASE_IIILLIIFII(Enum, L0, L1, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 %6 " #L0 " " #L1 " %7 %8 " Fstr " %9 %10", { \
+ 4, 5, 6, L0, L1, 7, 8, Fnum, 9, 10 \
+ } \
+ }
+
+#define CASE_IIILLIIFIIII(Enum, L0, L1, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 %6 " #L0 " " #L1 " %7 %8 " Fstr " %9 %10 %11 %12", { \
+ 4, 5, 6, L0, L1, 7, 8, Fnum, 9, 10, 11, 12 \
+ } \
+ }
+
+#define CASE_IIILLIIFIIIIII(Enum, L0, L1, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 %6 " #L0 " " #L1 " %7 %8 " Fstr " %9 %10 %11 %12 %13 %14", { \
+ 4, 5, 6, L0, L1, 7, 8, Fnum, 9, 10, 11, 12, 13, 14 \
+ } \
+ }
+
+#define CASE_IEILLIIF(Enum, E0, L0, L1, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 " #E0 " %5 " #L0 " " #L1 " %6 %7 " Fstr, { \
+ 4, uint32_t(DebugInfo##E0), 5, L0, L1, 6, 7, Fnum \
+ } \
+ }
+
+#define CASE_IEILLIIFI(Enum, E0, L0, L1, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 " #E0 " %5 " #L0 " " #L1 " %6 %7 " Fstr " %8", { \
+ 4, uint32_t(DebugInfo##E0), 5, L0, L1, 6, 7, Fnum, 8 \
+ } \
+ }
+
+#define CASE_IEILLIIFII(Enum, E0, L0, L1, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 " #E0 " %5 " #L0 " " #L1 " %6 %7 " Fstr " %8 %9", { \
+ 4, uint32_t(DebugInfo##E0), 5, L0, L1, 6, 7, Fnum, 8, 9 \
+ } \
+ }
+
+#define CASE_IEILLIIFIII(Enum, E0, L0, L1, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 " #E0 " %5 " #L0 " " #L1 " %6 %7 " Fstr " %8 %9 %10", { \
+ 4, uint32_t(DebugInfo##E0), 5, L0, L1, 6, 7, Fnum, 8, 9, 10 \
+ } \
+ }
+
+#define CASE_IEILLIIFIIII(Enum, E0, L0, L1, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 " #E0 " %5 " #L0 " " #L1 " %6 %7 " Fstr " %8 %9 %10 %11", { \
+ 4, uint32_t(DebugInfo##E0), 5, L0, L1, 6, 7, Fnum, 8, 9, 10, 11 \
+ } \
+ }
+
+#define CASE_IIILLIIIF(Enum, L0, L1, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 %6 " #L0 " " #L1 " %7 %8 %9 " Fstr, { \
+ 4, 5, 6, L0, L1, 7, 8, 9, Fnum \
+ } \
+ }
+
+#define CASE_IIILLIIIFI(Enum, L0, L1, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 %6 " #L0 " " #L1 " %7 %8 %9 " Fstr " %10", { \
+ 4, 5, 6, L0, L1, 7, 8, 9, Fnum, 10 \
+ } \
+ }
+
+#define CASE_IIIIF(Enum, Fstr, Fnum) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6 %7 " Fstr, { \
+ 4, 5, 6, 7, Fnum \
+ } \
+ }
+
+#define CASE_IIILL(Enum, L0, L1) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6 " #L0 " " #L1, { \
+ 4, 5, 6, L0, L1 \
+ } \
+ }
+
+#define CASE_IIIILL(Enum, L0, L1) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 %6 %7 " #L0 " " #L1, { \
+ 4, 5, 6, 7, L0, L1 \
+ } \
+ }
+
+#define CASE_IILLI(Enum, L0, L1) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 " #L0 " " #L1 " %6", { \
+ 4, 5, L0, L1, 6 \
+ } \
+ }
+
+#define CASE_IILLII(Enum, L0, L1) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 " #L0 " " #L1 " %6 %7", { \
+ 4, 5, L0, L1, 6, 7 \
+ } \
+ }
+
+#define CASE_IILLIII(Enum, L0, L1) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 " #L0 " " #L1 " %6 %7 %8", { \
+ 4, 5, L0, L1, 6, 7, 8 \
+ } \
+ }
+
+#define CASE_IILLIIII(Enum, L0, L1) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 " #L0 " " #L1 " %6 %7 %8 %9", { \
+ 4, 5, L0, L1, 6, 7, 8, 9 \
+ } \
+ }
+
+#define CASE_IIILLIIFLI(Enum, L0, L1, Fstr, Fnum, L2) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 %6 " #L0 " " #L1 " %7 %8 " Fstr " " #L2 " %9", { \
+ 4, 5, 6, L0, L1, 7, 8, Fnum, L2, 9 \
+ } \
+ }
+
+#define CASE_IIILLIIFLII(Enum, L0, L1, Fstr, Fnum, L2) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \
+ " %4 %5 %6 " #L0 " " #L1 " %7 %8 " Fstr " " #L2 " %9 %10", { \
+ 4, 5, 6, L0, L1, 7, 8, Fnum, L2, 9, 10 \
+ } \
+ }
+
+#define CASE_E(Enum, E0) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " " #E0, { \
+ uint32_t(DebugInfo##E0) \
+ } \
+ }
+
+#define CASE_EL(Enum, E0, L0) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " " #E0 " " #L0, { \
+ uint32_t(DebugInfo##E0), L0 \
+ } \
+ }
+
+#define CASE_ELL(Enum, E0, L0, L1) \
+ { \
+ uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " " #E0 " " #L0 " " #L1, { \
+ uint32_t(DebugInfo##E0), L0, L1 \
+ } \
+ }
+
+// DebugInfo 4.1 Absent Debugging Information
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugInfoNone, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_0(InfoNone), // enum value 0
+ })), );
+
+// DebugInfo 4.2 Compilation Unit
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugCompilationUnit,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_ILL(CompilationUnit, 100, 42),
+ })), );
+
+// DebugInfo 4.3 Type instructions
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugTypeBasic, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IIE(TypeBasic, Unspecified),
+ CASE_IIE(TypeBasic, Address),
+ CASE_IIE(TypeBasic, Boolean),
+ CASE_IIE(TypeBasic, Float),
+ CASE_IIE(TypeBasic, Signed),
+ CASE_IIE(TypeBasic, SignedChar),
+ CASE_IIE(TypeBasic, Unsigned),
+ CASE_IIE(TypeBasic, UnsignedChar),
+ })), );
+
+// The FlagIsPublic is value is (1 << 0) | (1 << 2) which is the same
+// as the bitwise-OR of FlagIsProtected and FlagIsPrivate.
+// The disassembler will emit the compound expression instead.
+// There is no simple fix for this. This enum is not really a mask
+// for the bottom two bits.
+TEST_F(ExtInstDebugInfoRoundTripTestExplicit, FlagIsPublic) {
+ const std::string prefix =
+ "%1 = OpExtInstImport \"DebugInfo\"\n"
+ "%3 = OpExtInst %2 %1 DebugTypePointer %4 Private ";
+ const std::string input = prefix + "FlagIsPublic\n";
+ const std::string expected = prefix + "FlagIsProtected|FlagIsPrivate\n";
+ // First make sure it assembles correctly.
+ EXPECT_THAT(
+ CompiledInstructions(input),
+ Eq(Concatenate(
+ {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("DebugInfo")),
+ MakeInstruction(SpvOpExtInst, {2, 3, 1, DebugInfoDebugTypePointer, 4,
+ uint32_t(SpvStorageClassPrivate),
+ DebugInfoFlagIsPublic})})))
+ << input;
+ // Now check the round trip through the disassembler.
+ EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(expected)) << input;
+}
+
+INSTANTIATE_TEST_CASE_P(
+ DebugInfoDebugTypePointer, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+
+ //// Use each flag independently.
+ CASE_ISF(TypePointer, Private, "FlagIsProtected",
+ uint32_t(DebugInfoFlagIsProtected)),
+ CASE_ISF(TypePointer, Private, "FlagIsPrivate",
+ uint32_t(DebugInfoFlagIsPrivate)),
+
+ // FlagIsPublic is tested above.
+
+ CASE_ISF(TypePointer, Private, "FlagIsLocal",
+ uint32_t(DebugInfoFlagIsLocal)),
+ CASE_ISF(TypePointer, Private, "FlagIsDefinition",
+ uint32_t(DebugInfoFlagIsDefinition)),
+ CASE_ISF(TypePointer, Private, "FlagFwdDecl",
+ uint32_t(DebugInfoFlagFwdDecl)),
+ CASE_ISF(TypePointer, Private, "FlagArtificial",
+ uint32_t(DebugInfoFlagArtificial)),
+ CASE_ISF(TypePointer, Private, "FlagExplicit",
+ uint32_t(DebugInfoFlagExplicit)),
+ CASE_ISF(TypePointer, Private, "FlagPrototyped",
+ uint32_t(DebugInfoFlagPrototyped)),
+ CASE_ISF(TypePointer, Private, "FlagObjectPointer",
+ uint32_t(DebugInfoFlagObjectPointer)),
+ CASE_ISF(TypePointer, Private, "FlagStaticMember",
+ uint32_t(DebugInfoFlagStaticMember)),
+ CASE_ISF(TypePointer, Private, "FlagIndirectVariable",
+ uint32_t(DebugInfoFlagIndirectVariable)),
+ CASE_ISF(TypePointer, Private, "FlagLValueReference",
+ uint32_t(DebugInfoFlagLValueReference)),
+ CASE_ISF(TypePointer, Private, "FlagIsOptimized",
+ uint32_t(DebugInfoFlagIsOptimized)),
+
+ //// Use flags in combination, and try different storage classes.
+ CASE_ISF(TypePointer, Function, "FlagIsProtected|FlagIsPrivate",
+ uint32_t(DebugInfoFlagIsProtected) |
+ uint32_t(DebugInfoFlagIsPrivate)),
+ CASE_ISF(
+ TypePointer, Workgroup,
+ "FlagIsPrivate|FlagFwdDecl|FlagIndirectVariable|FlagIsOptimized",
+ uint32_t(DebugInfoFlagIsPrivate) | uint32_t(DebugInfoFlagFwdDecl) |
+ uint32_t(DebugInfoFlagIndirectVariable) |
+ uint32_t(DebugInfoFlagIsOptimized)),
+
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugTypeQualifier,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IE(TypeQualifier, ConstType),
+ CASE_IE(TypeQualifier, VolatileType),
+ CASE_IE(TypeQualifier, RestrictType),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugTypeArray, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_II(TypeArray),
+ CASE_III(TypeArray),
+ CASE_IIII(TypeArray),
+ CASE_IIIII(TypeArray),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugTypeVector, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IL(TypeVector, 2),
+ CASE_IL(TypeVector, 3),
+ CASE_IL(TypeVector, 4),
+ CASE_IL(TypeVector, 16),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugTypedef, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IIILLI(Typedef, 12, 13),
+ CASE_IIILLI(Typedef, 14, 99),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugTypeFunction,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_I(TypeFunction),
+ CASE_II(TypeFunction),
+ CASE_III(TypeFunction),
+ CASE_IIII(TypeFunction),
+ CASE_IIIII(TypeFunction),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(
+ DebugInfoDebugTypeEnum, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IIILLIIFII(
+ TypeEnum, 12, 13,
+ "FlagIsPrivate|FlagFwdDecl|FlagIndirectVariable|FlagIsOptimized",
+ uint32_t(DebugInfoFlagIsPrivate) | uint32_t(DebugInfoFlagFwdDecl) |
+ uint32_t(DebugInfoFlagIndirectVariable) |
+ uint32_t(DebugInfoFlagIsOptimized)),
+ CASE_IIILLIIFIIII(TypeEnum, 17, 18, "FlagStaticMember",
+ uint32_t(DebugInfoFlagStaticMember)),
+ CASE_IIILLIIFIIIIII(TypeEnum, 99, 1, "FlagStaticMember",
+ uint32_t(DebugInfoFlagStaticMember)),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(
+ DebugInfoDebugTypeComposite, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IEILLIIF(
+ TypeComposite, Class, 12, 13,
+ "FlagIsPrivate|FlagFwdDecl|FlagIndirectVariable|FlagIsOptimized",
+ uint32_t(DebugInfoFlagIsPrivate) | uint32_t(DebugInfoFlagFwdDecl) |
+ uint32_t(DebugInfoFlagIndirectVariable) |
+ uint32_t(DebugInfoFlagIsOptimized)),
+ // Cover all tag values: Class, Structure, Union
+ CASE_IEILLIIF(TypeComposite, Class, 12, 13, "FlagIsPrivate",
+ uint32_t(DebugInfoFlagIsPrivate)),
+ CASE_IEILLIIF(TypeComposite, Structure, 12, 13, "FlagIsPrivate",
+ uint32_t(DebugInfoFlagIsPrivate)),
+ CASE_IEILLIIF(TypeComposite, Union, 12, 13, "FlagIsPrivate",
+ uint32_t(DebugInfoFlagIsPrivate)),
+ // Now add members
+ CASE_IEILLIIFI(TypeComposite, Class, 9, 10, "FlagIsPrivate",
+ uint32_t(DebugInfoFlagIsPrivate)),
+ CASE_IEILLIIFII(TypeComposite, Class, 9, 10, "FlagIsPrivate",
+ uint32_t(DebugInfoFlagIsPrivate)),
+ CASE_IEILLIIFIII(TypeComposite, Class, 9, 10, "FlagIsPrivate",
+ uint32_t(DebugInfoFlagIsPrivate)),
+ CASE_IEILLIIFIIII(TypeComposite, Class, 9, 10, "FlagIsPrivate",
+ uint32_t(DebugInfoFlagIsPrivate)),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugTypeMember, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IIILLIIIF(TypeMember, 12, 13, "FlagIsPrivate",
+ uint32_t(DebugInfoFlagIsPrivate)),
+ CASE_IIILLIIIF(TypeMember, 99, 100,
+ "FlagIsPrivate|FlagFwdDecl",
+ uint32_t(DebugInfoFlagIsPrivate) |
+ uint32_t(DebugInfoFlagFwdDecl)),
+ // Add the optional Id argument.
+ CASE_IIILLIIIFI(TypeMember, 12, 13, "FlagIsPrivate",
+ uint32_t(DebugInfoFlagIsPrivate)),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(
+ DebugInfoDebugTypeInheritance, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IIIIF(TypeInheritance, "FlagIsPrivate",
+ uint32_t(DebugInfoFlagIsPrivate)),
+ CASE_IIIIF(TypeInheritance, "FlagIsPrivate|FlagFwdDecl",
+ uint32_t(DebugInfoFlagIsPrivate) |
+ uint32_t(DebugInfoFlagFwdDecl)),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugTypePtrToMember,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_II(TypePtrToMember),
+ })), );
+
+// DebugInfo 4.4 Templates
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugTypeTemplate,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_II(TypeTemplate),
+ CASE_III(TypeTemplate),
+ CASE_IIII(TypeTemplate),
+ CASE_IIIII(TypeTemplate),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugTypeTemplateParameter,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IIIILL(TypeTemplateParameter, 1, 2),
+ CASE_IIIILL(TypeTemplateParameter, 99, 102),
+ CASE_IIIILL(TypeTemplateParameter, 10, 7),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugTypeTemplateTemplateParameter,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IIILL(TypeTemplateTemplateParameter, 1, 2),
+ CASE_IIILL(TypeTemplateTemplateParameter, 99, 102),
+ CASE_IIILL(TypeTemplateTemplateParameter, 10, 7),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugTypeTemplateParameterPack,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IILLI(TypeTemplateParameterPack, 1, 2),
+ CASE_IILLII(TypeTemplateParameterPack, 99, 102),
+ CASE_IILLIII(TypeTemplateParameterPack, 10, 7),
+ CASE_IILLIIII(TypeTemplateParameterPack, 10, 7),
+ })), );
+
+// DebugInfo 4.5 Global Variables
+
+INSTANTIATE_TEST_CASE_P(
+ DebugInfoDebugGlobalVariable, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IIILLIIIF(GlobalVariable, 1, 2, "FlagIsOptimized",
+ uint32_t(DebugInfoFlagIsOptimized)),
+ CASE_IIILLIIIF(GlobalVariable, 42, 43, "FlagIsOptimized",
+ uint32_t(DebugInfoFlagIsOptimized)),
+ CASE_IIILLIIIFI(GlobalVariable, 1, 2, "FlagIsOptimized",
+ uint32_t(DebugInfoFlagIsOptimized)),
+ CASE_IIILLIIIFI(GlobalVariable, 42, 43, "FlagIsOptimized",
+ uint32_t(DebugInfoFlagIsOptimized)),
+ })), );
+
+// DebugInfo 4.6 Functions
+
+INSTANTIATE_TEST_CASE_P(
+ DebugInfoDebugFunctionDeclaration, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IIILLIIF(FunctionDeclaration, 1, 2, "FlagIsOptimized",
+ uint32_t(DebugInfoFlagIsOptimized)),
+ CASE_IIILLIIF(FunctionDeclaration, 42, 43, "FlagFwdDecl",
+ uint32_t(DebugInfoFlagFwdDecl)),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(
+ DebugInfoDebugFunction, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IIILLIIFLI(Function, 1, 2, "FlagIsOptimized",
+ uint32_t(DebugInfoFlagIsOptimized), 3),
+ CASE_IIILLIIFLI(Function, 42, 43, "FlagFwdDecl",
+ uint32_t(DebugInfoFlagFwdDecl), 44),
+ // Add the optional declaration Id.
+ CASE_IIILLIIFLII(Function, 1, 2, "FlagIsOptimized",
+ uint32_t(DebugInfoFlagIsOptimized), 3),
+ CASE_IIILLIIFLII(Function, 42, 43, "FlagFwdDecl",
+ uint32_t(DebugInfoFlagFwdDecl), 44),
+ })), );
+
+// DebugInfo 4.7 Local Information
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugLexicalBlock,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_ILLII(LexicalBlock, 1, 2),
+ CASE_ILLII(LexicalBlock, 42, 43),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugLexicalBlockDiscriminator,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_ILI(LexicalBlockDiscriminator, 1),
+ CASE_ILI(LexicalBlockDiscriminator, 42),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugScope, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_I(Scope),
+ CASE_II(Scope),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugNoScope, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_0(NoScope),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugInlinedAt, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_LII(InlinedAt, 1),
+ CASE_LII(InlinedAt, 42),
+ })), );
+
+// DebugInfo 4.8 Local Variables
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugLocalVariable,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_IIILLI(LocalVariable, 1, 2),
+ CASE_IIILLI(LocalVariable, 42, 43),
+ CASE_IIILLIL(LocalVariable, 1, 2, 3),
+ CASE_IIILLIL(LocalVariable, 42, 43, 44),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugInlinedVariable,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_II(InlinedVariable),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugDebugDeclare,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_III(Declare),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(
+ DebugInfoDebugDebugValue, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_III(Value),
+ CASE_IIII(Value),
+ CASE_IIIII(Value),
+ CASE_IIIIII(Value),
+ // Test up to 4 id parameters. We can always try more.
+ CASE_IIIIIII(Value),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugDebugOperation,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_E(Operation, Deref),
+ CASE_E(Operation, Plus),
+ CASE_E(Operation, Minus),
+ CASE_EL(Operation, PlusUconst, 1),
+ CASE_EL(Operation, PlusUconst, 42),
+ CASE_ELL(Operation, BitPiece, 1, 2),
+ CASE_ELL(Operation, BitPiece, 4, 5),
+ CASE_E(Operation, Swap),
+ CASE_E(Operation, Xderef),
+ CASE_E(Operation, StackValue),
+ CASE_EL(Operation, Constu, 1),
+ CASE_EL(Operation, Constu, 42),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugDebugExpression,
+ ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_0(Expression),
+ CASE_I(Expression),
+ CASE_II(Expression),
+ CASE_III(Expression),
+ CASE_IIII(Expression),
+ CASE_IIIII(Expression),
+ CASE_IIIIII(Expression),
+ CASE_IIIIIII(Expression),
+ })), );
+
+// DebugInfo 4.9 Macros
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugMacroDef, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_ILI(MacroDef, 1),
+ CASE_ILI(MacroDef, 42),
+ CASE_ILII(MacroDef, 1),
+ CASE_ILII(MacroDef, 42),
+ })), );
+
+INSTANTIATE_TEST_CASE_P(DebugInfoDebugMacroUndef, ExtInstDebugInfoRoundTripTest,
+ ::testing::ValuesIn(std::vector<InstructionCase>({
+ CASE_ILI(MacroUndef, 1),
+ CASE_ILI(MacroUndef, 42),
+ })), );
+
+#undef CASE_0
+#undef CASE_ILL
+#undef CASE_IL
+#undef CASE_I
+#undef CASE_II
+#undef CASE_III
+#undef CASE_IIII
+#undef CASE_IIIII
+#undef CASE_IIIIII
+#undef CASE_IIIIIII
+#undef CASE_IIILLI
+#undef CASE_IIILLIL
+#undef CASE_IE
+#undef CASE_IIE
+#undef CASE_ISF
+#undef CASE_LII
+#undef CASE_ILI
+#undef CASE_ILII
+#undef CASE_ILLII
+#undef CASE_IIILLIIF
+#undef CASE_IIILLIIFII
+#undef CASE_IIILLIIFIIII
+#undef CASE_IIILLIIFIIIIII
+#undef CASE_IEILLIIF
+#undef CASE_IEILLIIFI
+#undef CASE_IEILLIIFII
+#undef CASE_IEILLIIFIII
+#undef CASE_IEILLIIFIIII
+#undef CASE_IIILLIIIF
+#undef CASE_IIILLIIIFI
+#undef CASE_IIIIF
+#undef CASE_IIILL
+#undef CASE_IIIILL
+#undef CASE_IILLI
+#undef CASE_IILLII
+#undef CASE_IILLIII
+#undef CASE_IILLIIII
+#undef CASE_IIILLIIFLI
+#undef CASE_IIILLIIFLII
+#undef CASE_E
+#undef CASE_EL
+#undef CASE_ELL
+
+} // anonymous namespace
type=str, required=False,
help='input JSON grammar file for core SPIR-V '
'instructions')
+ parser.add_argument('--extinst-debuginfo-grammar', metavar='<path>',
+ type=str, required=False, default=None,
+ help='input JSON grammar file for DebugInfo extended '
+ 'instruction set')
parser.add_argument('--extinst-glsl-grammar', metavar='<path>',
type=str, required=False, default=None,
help='input JSON grammar file for GLSL extended '
if (args.core_insts_output is None) != \
(args.operand_kinds_output is None):
- print('error: --core-insts-output and --operand_kinds_output '
+ print('error: --core-insts-output and --operand-kinds-output '
'should be specified together.')
exit(1)
+ if args.operand_kinds_output and not (args.spirv_core_grammar and args.extinst_debuginfo_grammar):
+ print('error: --operand-kinds-output requires --spirv-core-grammar '
+ 'and --exinst-debuginfo-grammar')
+ exit(1)
if (args.glsl_insts_output is None) != \
(args.extinst_glsl_grammar is None):
print('error: --glsl-insts-output and --extinst-glsl-grammar '
if args.spirv_core_grammar is not None:
with open(args.spirv_core_grammar) as json_file:
grammar = json.loads(json_file.read())
- if args.core_insts_output is not None:
- make_path_to_file(args.core_insts_output)
- make_path_to_file(args.operand_kinds_output)
- version = '{}_{}'.format(grammar['major_version'],
- grammar['minor_version'])
- print(generate_instruction_table(
- grammar['instructions'], version),
- file=open(args.core_insts_output, 'w'))
- print(generate_operand_kind_table(
- grammar['operand_kinds'], version),
- file=open(args.operand_kinds_output, 'w'))
- if args.extension_enum_output is not None:
- make_path_to_file(args.extension_enum_output)
- print(generate_extension_enum(grammar['operand_kinds']),
- file=open(args.extension_enum_output, 'w'))
- if args.enum_string_mapping_output is not None:
- make_path_to_file(args.enum_string_mapping_output)
- print(generate_all_string_enum_mappings(
- grammar['operand_kinds']),
- file=open(args.enum_string_mapping_output, 'w'))
+ with open(args.extinst_debuginfo_grammar) as debuginfo_json_file:
+ debuginfo_grammar = json.loads(debuginfo_json_file.read())
+ operand_kinds = grammar['operand_kinds']
+ operand_kinds.extend(debuginfo_grammar['operand_kinds'])
+ if args.core_insts_output is not None:
+ make_path_to_file(args.core_insts_output)
+ make_path_to_file(args.operand_kinds_output)
+ version = '{}_{}'.format(grammar['major_version'],
+ grammar['minor_version'])
+ print(generate_instruction_table(
+ grammar['instructions'], version),
+ file=open(args.core_insts_output, 'w'))
+ print(generate_operand_kind_table(operand_kinds, version),
+ file=open(args.operand_kinds_output, 'w'))
+ if args.extension_enum_output is not None:
+ make_path_to_file(args.extension_enum_output)
+ print(generate_extension_enum(grammar['operand_kinds']),
+ file=open(args.extension_enum_output, 'w'))
+ if args.enum_string_mapping_output is not None:
+ make_path_to_file(args.enum_string_mapping_output)
+ print(generate_all_string_enum_mappings(operand_kinds),
+ file=open(args.enum_string_mapping_output, 'w'))
if args.extinst_glsl_grammar is not None:
with open(args.extinst_glsl_grammar) as json_file:
--- /dev/null
+#!/usr/bin/env python
+# Copyright (c) 2017 Google Inc.
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Generates language headers from a JSON grammar file"""
+
+from __future__ import print_function
+
+import errno
+import json
+import os.path
+import re
+
+
+def make_path_to_file(f):
+ """Makes all ancestor directories to the given file, if they
+ don't yet exist.
+
+ Arguments:
+ f: The file whose ancestor directories are to be created.
+ """
+ dir = os.path.dirname(os.path.abspath(f))
+ try:
+ os.makedirs(dir)
+ except OSError as e:
+ if e.errno == errno.EEXIST and os.path.isdir(dir):
+ pass
+ else:
+ raise
+
+class ExtInstGrammar:
+ """The grammar for an extended instruction set"""
+
+ def __init__(self, name, copyright, instructions, operand_kinds, version = None, revision = None):
+ self.name = name
+ self.copyright = copyright
+ self.instructions = instructions
+ self.operand_kinds = operand_kinds
+ self.version = version
+ self.revision = revision
+
+
+class LangGenerator:
+ """A language-specific generator"""
+
+ def __init__(self):
+ self.upper_case_initial = re.compile('^[A-Z]')
+ pass
+
+ def comment_prefix(self):
+ return ""
+
+ def namespace_prefix(self):
+ return ""
+
+ def uses_guards(self):
+ return False
+
+ def cpp_guard_preamble(self):
+ return ""
+
+ def cpp_guard_postamble(self):
+ return ""
+
+ def enum_value(self, prefix, name, value):
+ if self.upper_case_initial.match(name):
+ use_name = name
+ else:
+ use_name = '_' + name
+
+ return " {}{} = {},".format(prefix, use_name, value)
+
+ def generate(self, grammar):
+ """Returns a string that is the language-specific header for the given grammar"""
+
+ parts = []
+ if grammar.copyright:
+ parts.extend(["{}{}".format(self.comment_prefix(), f) for f in grammar.copyright])
+ parts.append('')
+
+ guard = 'SPIRV_EXTINST_{}_H_'.format(grammar.name)
+ if self.uses_guards:
+ parts.append('#ifndef {}'.format(guard))
+ parts.append('#define {}'.format(guard))
+ parts.append('')
+
+ parts.append(self.cpp_guard_preamble())
+
+ if grammar.version:
+ parts.append(self.const_definition(grammar.name, 'Version', grammar.version))
+
+ if grammar.revision is not None:
+ parts.append(self.const_definition(grammar.name, 'Revision', grammar.revision))
+
+ parts.append('')
+
+ if grammar.instructions:
+ parts.append(self.enum_prefix(grammar.name, 'Instructions'))
+ for inst in grammar.instructions:
+ parts.append(self.enum_value(grammar.name, inst['opname'], inst['opcode']))
+ parts.append(self.enum_end(grammar.name, 'Instructions'))
+ parts.append('')
+
+ if grammar.operand_kinds:
+ for kind in grammar.operand_kinds:
+ parts.append(self.enum_prefix(grammar.name, kind['kind']))
+ for e in kind['enumerants']:
+ parts.append(self.enum_value(grammar.name, e['enumerant'], e['value']))
+ parts.append(self.enum_end(grammar.name, kind['kind']))
+ parts.append('')
+
+ parts.append(self.cpp_guard_postamble())
+
+ if self.uses_guards:
+ parts.append('#endif // {}'.format(guard))
+
+ return '\n'.join(parts)
+
+
+class CLikeGenerator(LangGenerator):
+ def uses_guards(self):
+ return True
+
+ def comment_prefix(self):
+ return "// "
+
+ def const_definition(self, prefix, var, value):
+ # Use an anonymous enum. Don't use a static const int variable because
+ # that can bloat binary size.
+ return 'enum {0} {1}{2} = {3}, {1}{2}_BitWidthPadding = 0x7fffffff {4};'.format(
+ '{', prefix, var, value, '}')
+
+ def enum_prefix(self, prefix, name):
+ return 'enum {}{} {}'.format(prefix, name, '{')
+
+ def enum_end(self, prefix, enum):
+ return ' {}{}Max = 0x7ffffff\n{};\n'.format(prefix, enum, '}')
+
+ def cpp_guard_preamble(self):
+ return '#ifdef __cplusplus\nextern "C" {\n#endif\n'
+
+ def cpp_guard_postamble(self):
+ return '#ifdef __cplusplus\n}\n#endif\n'
+
+
+class CGenerator(CLikeGenerator):
+ pass
+
+
+def main():
+ import argparse
+ parser = argparse.ArgumentParser(description='Generate language headers from a JSON grammar')
+
+ parser.add_argument('--extinst-name',
+ type=str, required=True,
+ help='The name to use in tokens')
+ parser.add_argument('--extinst-grammar', metavar='<path>',
+ type=str, required=True,
+ help='input JSON grammar file for extended instruction set')
+ parser.add_argument('--extinst-output-base', metavar='<path>',
+ type=str, required=True,
+ help='Basename of the language-specific output file.')
+ args = parser.parse_args()
+
+ with open(args.extinst_grammar) as json_file:
+ grammar_json = json.loads(json_file.read())
+ grammar = ExtInstGrammar(name = args.extinst_name,
+ copyright = grammar_json['copyright'],
+ instructions = grammar_json['instructions'],
+ operand_kinds = grammar_json['operand_kinds'],
+ version = grammar_json['version'],
+ revision = grammar_json['revision'])
+ make_path_to_file(args.extinst_output_base)
+ print(CGenerator().generate(grammar), file=open(args.extinst_output_base + '.h', 'w'))
+
+
+if __name__ == '__main__':
+ main()