Add asm, dis support for DebugInfo extended instruction set

Add grammar file for DebugInfo extended instruction set
- Each new operand enum kind in extinst.debuginfo.grammar.json maps
  to a new value in spv_operand_type_t.
- Add new concrete enum operand types for DebugInfo

Generate a C header for the DebugInfo extended instruction set

Add table lookup of DebugInfo extended instrutions

Handle the debug info operand types in binary parser,
disassembler, and assembler.

Add DebugInfo round trip tests for assembler, disassembler

Android.mk: Support DebugInfo extended instruction set

The extinst.debuginfo.grammar.json file is currently part of
SPIRV-Tools source.

It contributes operand type enums, so it has to be processed
along with the core grammar files.

We also generate a C header DebugInfo.h.

Add necessary grammar file processing to Android.mk.
This commit is contained in:
David Neto 2017-12-03 12:30:08 -05:00
parent a27d673cef
commit 59de6100b5
13 changed files with 1713 additions and 37 deletions

View File

@ -112,8 +112,11 @@ SPVTOOLS_OPT_SRC_FILES := \
SPV_CORE10_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.0/spirv.core.grammar.json 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_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_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_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 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 define gen_spvtools_grammar_tables
$(call generate-file-dir,$(1)/core.insts-1.0.inc) $(call generate-file-dir,$(1)/core.insts-1.0.inc)
@ -121,11 +124,13 @@ $(1)/core.insts-1.0.inc $(1)/operand.kinds-1.0.inc $(1)/glsl.std.450.insts.inc $
$(LOCAL_PATH)/utils/generate_grammar_tables.py \ $(LOCAL_PATH)/utils/generate_grammar_tables.py \
$(SPV_CORE10_GRAMMAR) \ $(SPV_CORE10_GRAMMAR) \
$(SPV_GLSL_GRAMMAR) \ $(SPV_GLSL_GRAMMAR) \
$(SPV_OPENCL_GRAMMAR) $(SPV_OPENCL_GRAMMAR) \
$(SPV_DEBUGINFO_GRAMMAR)
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \ @$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
--spirv-core-grammar=$(SPV_CORE10_GRAMMAR) \ --spirv-core-grammar=$(SPV_CORE10_GRAMMAR) \
--extinst-glsl-grammar=$(SPV_GLSL_GRAMMAR) \ --extinst-glsl-grammar=$(SPV_GLSL_GRAMMAR) \
--extinst-opencl-grammar=$(SPV_OPENCL_GRAMMAR) \ --extinst-opencl-grammar=$(SPV_OPENCL_GRAMMAR) \
--extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
--core-insts-output=$(1)/core.insts-1.0.inc \ --core-insts-output=$(1)/core.insts-1.0.inc \
--glsl-insts-output=$(1)/glsl.std.450.insts.inc \ --glsl-insts-output=$(1)/glsl.std.450.insts.inc \
--opencl-insts-output=$(1)/opencl.std.insts.inc \ --opencl-insts-output=$(1)/opencl.std.insts.inc \
@ -133,17 +138,21 @@ $(1)/core.insts-1.0.inc $(1)/operand.kinds-1.0.inc $(1)/glsl.std.450.insts.inc $
@echo "[$(TARGET_ARCH_ABI)] Grammar v1.0 : instructions & operands <= grammar JSON files" @echo "[$(TARGET_ARCH_ABI)] Grammar v1.0 : instructions & operands <= grammar JSON files"
$(1)/core.insts-1.1.inc $(1)/operand.kinds-1.1.inc: \ $(1)/core.insts-1.1.inc $(1)/operand.kinds-1.1.inc: \
$(LOCAL_PATH)/utils/generate_grammar_tables.py \ $(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 \ @$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
--spirv-core-grammar=$(SPV_CORE11_GRAMMAR) \ --spirv-core-grammar=$(SPV_CORE11_GRAMMAR) \
--extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
--core-insts-output=$(1)/core.insts-1.1.inc \ --core-insts-output=$(1)/core.insts-1.1.inc \
--operand-kinds-output=$(1)/operand.kinds-1.1.inc --operand-kinds-output=$(1)/operand.kinds-1.1.inc
@echo "[$(TARGET_ARCH_ABI)] Grammar v1.1 : instructions & operands <= grammar JSON files" @echo "[$(TARGET_ARCH_ABI)] Grammar v1.1 : instructions & operands <= grammar JSON files"
$(1)/core.insts-1.2.inc $(1)/operand.kinds-1.2.inc: \ $(1)/core.insts-1.2.inc $(1)/operand.kinds-1.2.inc: \
$(LOCAL_PATH)/utils/generate_grammar_tables.py \ $(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 \ @$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
--spirv-core-grammar=$(SPV_CORE12_GRAMMAR) \ --spirv-core-grammar=$(SPV_CORE12_GRAMMAR) \
--extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
--core-insts-output=$(1)/core.insts-1.2.inc \ --core-insts-output=$(1)/core.insts-1.2.inc \
--operand-kinds-output=$(1)/operand.kinds-1.2.inc --operand-kinds-output=$(1)/operand.kinds-1.2.inc
@echo "[$(TARGET_ARCH_ABI)] Grammar v1.2 : instructions & operands <= grammar JSON files" @echo "[$(TARGET_ARCH_ABI)] Grammar v1.2 : instructions & operands <= grammar JSON files"
@ -153,6 +162,27 @@ $(LOCAL_PATH)/source/ext_inst.cpp: $(1)/glsl.std.450.insts.inc $(1)/opencl.std.i
endef endef
$(eval $(call gen_spvtools_grammar_tables,$(SPVTOOLS_OUT_PATH))) $(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 define gen_spvtools_vendor_tables
$(call generate-file-dir,$(1)/$(2).insts.inc) $(call generate-file-dir,$(1)/$(2).insts.inc)
$(1)/$(2).insts.inc : \ $(1)/$(2).insts.inc : \
@ -172,9 +202,10 @@ define gen_spvtools_enum_string_mapping
$(call generate-file-dir,$(1)/extension_enum.inc.inc) $(call generate-file-dir,$(1)/extension_enum.inc.inc)
$(1)/extension_enum.inc $(1)/enum_string_mapping.inc: \ $(1)/extension_enum.inc $(1)/enum_string_mapping.inc: \
$(LOCAL_PATH)/utils/generate_grammar_tables.py \ $(LOCAL_PATH)/utils/generate_grammar_tables.py \
$(SPV_CORE11_GRAMMAR) $(SPV_CORELATEST_GRAMMAR)
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \ @$(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 \ --extension-enum-output=$(1)/extension_enum.inc \
--enum-string-mapping-output=$(1)/enum_string_mapping.inc --enum-string-mapping-output=$(1)/enum_string_mapping.inc
@echo "[$(TARGET_ARCH_ABI)] Generate enum<->string mapping <= grammar JSON files" @echo "[$(TARGET_ARCH_ABI)] Generate enum<->string mapping <= grammar JSON files"

View File

@ -206,6 +206,13 @@ typedef enum spv_operand_type_t {
// A sequence of zero or more pairs of (Id, Literal integer) // A sequence of zero or more pairs of (Id, Literal integer)
LAST_VARIABLE(SPV_OPERAND_TYPE_VARIABLE_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. // This is a sentinel value, and does not represent an operand type.
// It should come last. // It should come last.
SPV_OPERAND_TYPE_NUM_OPERAND_TYPES, SPV_OPERAND_TYPE_NUM_OPERAND_TYPES,
@ -221,6 +228,7 @@ typedef enum spv_ext_inst_type_t {
SPV_EXT_INST_TYPE_SPV_AMD_SHADER_TRINARY_MINMAX, SPV_EXT_INST_TYPE_SPV_AMD_SHADER_TRINARY_MINMAX,
SPV_EXT_INST_TYPE_SPV_AMD_GCN_SHADER, SPV_EXT_INST_TYPE_SPV_AMD_GCN_SHADER,
SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT, SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT,
SPV_EXT_INST_TYPE_DEBUGINFO,
SPV_FORCE_32_BIT_ENUM(spv_ext_inst_type_t) SPV_FORCE_32_BIT_ENUM(spv_ext_inst_type_t)
} spv_ext_inst_type_t; } spv_ext_inst_type_t;

View File

@ -15,6 +15,11 @@
set(GRAMMAR_PROCESSING_SCRIPT "${spirv-tools_SOURCE_DIR}/utils/generate_grammar_tables.py") 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(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(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 # 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 # file paths into some global lists (*_CPP_DEPENDS). And those global lists are
@ -27,9 +32,10 @@ macro(spvtools_core_tables VERSION)
add_custom_command(OUTPUT ${GRAMMAR_INSTS_INC_FILE} ${GRAMMAR_KINDS_INC_FILE} add_custom_command(OUTPUT ${GRAMMAR_INSTS_INC_FILE} ${GRAMMAR_KINDS_INC_FILE}
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT} COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
--spirv-core-grammar=${GRAMMAR_JSON_FILE} --spirv-core-grammar=${GRAMMAR_JSON_FILE}
--extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
--core-insts-output=${GRAMMAR_INSTS_INC_FILE} --core-insts-output=${GRAMMAR_INSTS_INC_FILE}
--operand-kinds-output=${GRAMMAR_KINDS_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.") COMMENT "Generate info tables for SPIR-V v${VERSION} core instructions and operands.")
list(APPEND OPCODE_CPP_DEPENDS ${GRAMMAR_INSTS_INC_FILE}) list(APPEND OPCODE_CPP_DEPENDS ${GRAMMAR_INSTS_INC_FILE})
list(APPEND OPERAND_CPP_DEPENDS ${GRAMMAR_KINDS_INC_FILE}) list(APPEND OPERAND_CPP_DEPENDS ${GRAMMAR_KINDS_INC_FILE})
@ -43,9 +49,10 @@ macro(spvtools_enum_string_mapping VERSION)
${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE} ${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT} COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
--spirv-core-grammar=${GRAMMAR_JSON_FILE} --spirv-core-grammar=${GRAMMAR_JSON_FILE}
--extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
--extension-enum-output=${GRAMMAR_EXTENSION_ENUM_INC_FILE} --extension-enum-output=${GRAMMAR_EXTENSION_ENUM_INC_FILE}
--enum-string-mapping-output=${GRAMMAR_ENUM_STRING_MAPPING_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}.") COMMENT "Generate enum-string mapping for SPIR-V v${VERSION}.")
list(APPEND EXTENSION_H_DEPENDS ${GRAMMAR_EXTENSION_ENUM_INC_FILE}) list(APPEND EXTENSION_H_DEPENDS ${GRAMMAR_EXTENSION_ENUM_INC_FILE})
list(APPEND ENUM_STRING_MAPPING_CPP_DEPENDS ${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}) list(APPEND ENUM_STRING_MAPPING_CPP_DEPENDS ${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE})
@ -59,11 +66,12 @@ macro(spvtools_vimsyntax VERSION CLVERSION)
add_custom_command(OUTPUT ${VIMSYNTAX_FILE} add_custom_command(OUTPUT ${VIMSYNTAX_FILE}
COMMAND ${PYTHON_EXECUTABLE} ${VIMSYNTAX_PROCESSING_SCRIPT} COMMAND ${PYTHON_EXECUTABLE} ${VIMSYNTAX_PROCESSING_SCRIPT}
--spirv-core-grammar=${GRAMMAR_JSON_FILE} --spirv-core-grammar=${GRAMMAR_JSON_FILE}
--exinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
--extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE} --extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE}
--extinst-opencl-grammar=${OPENCL_GRAMMAR_JSON_FILE} --extinst-opencl-grammar=${OPENCL_GRAMMAR_JSON_FILE}
>${VIMSYNTAX_FILE} >${VIMSYNTAX_FILE}
DEPENDS ${VIMSYNTAX_PROCESSING_SCRIPT} ${GRAMMAR_JSON_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.") COMMENT "Generate spvasm.vim: Vim syntax file for SPIR-V assembly.")
endmacro(spvtools_vimsyntax) endmacro(spvtools_vimsyntax)
@ -73,7 +81,6 @@ macro(spvtools_glsl_tables VERSION)
set(GRAMMAR_INC_FILE "${spirv-tools_BINARY_DIR}/glsl.std.450.insts.inc") set(GRAMMAR_INC_FILE "${spirv-tools_BINARY_DIR}/glsl.std.450.insts.inc")
add_custom_command(OUTPUT ${GRAMMAR_INC_FILE} add_custom_command(OUTPUT ${GRAMMAR_INC_FILE}
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT} COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
--spirv-core-grammar=${CORE_GRAMMAR_JSON_FILE}
--extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE} --extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE}
--glsl-insts-output=${GRAMMAR_INC_FILE} --glsl-insts-output=${GRAMMAR_INC_FILE}
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${GLSL_GRAMMAR_JSON_FILE} DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${GLSL_GRAMMAR_JSON_FILE}
@ -87,7 +94,6 @@ macro(spvtools_opencl_tables VERSION)
set(GRAMMAR_INC_FILE "${spirv-tools_BINARY_DIR}/opencl.std.insts.inc") set(GRAMMAR_INC_FILE "${spirv-tools_BINARY_DIR}/opencl.std.insts.inc")
add_custom_command(OUTPUT ${GRAMMAR_INC_FILE} add_custom_command(OUTPUT ${GRAMMAR_INC_FILE}
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT} COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
--spirv-core-grammar=${CORE_GRAMMAR_JSON_FILE}
--extinst-opencl-grammar=${OPENCL_GRAMMAR_JSON_FILE} --extinst-opencl-grammar=${OPENCL_GRAMMAR_JSON_FILE}
--opencl-insts-output=${GRAMMAR_INC_FILE} --opencl-insts-output=${GRAMMAR_INC_FILE}
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${OPENCL_GRAMMAR_JSON_FILE} DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${OPENCL_GRAMMAR_JSON_FILE}
@ -109,6 +115,22 @@ macro(spvtools_vendor_tables VENDOR_TABLE)
set_property(TARGET spirv-tools-${VENDOR_TABLE} PROPERTY FOLDER "SPIRV-Tools build") set_property(TARGET spirv-tools-${VENDOR_TABLE} PROPERTY FOLDER "SPIRV-Tools build")
endmacro(spvtools_vendor_tables) 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.0")
spvtools_core_tables("1.1") spvtools_core_tables("1.1")
spvtools_core_tables("1.2") spvtools_core_tables("1.2")
@ -119,6 +141,8 @@ spvtools_vendor_tables("spv-amd-shader-explicit-vertex-parameter")
spvtools_vendor_tables("spv-amd-shader-trinary-minmax") spvtools_vendor_tables("spv-amd-shader-trinary-minmax")
spvtools_vendor_tables("spv-amd-gcn-shader") spvtools_vendor_tables("spv-amd-gcn-shader")
spvtools_vendor_tables("spv-amd-shader-ballot") 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") spvtools_vimsyntax("1.2" "1.0")
add_custom_target(spirv-tools-vimsyntax DEPENDS ${VIMSYNTAX_FILE}) add_custom_target(spirv-tools-vimsyntax DEPENDS ${VIMSYNTAX_FILE})

View File

@ -613,7 +613,11 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
case SPV_OPERAND_TYPE_BUILT_IN: case SPV_OPERAND_TYPE_BUILT_IN:
case SPV_OPERAND_TYPE_GROUP_OPERATION: case SPV_OPERAND_TYPE_GROUP_OPERATION:
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS: 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. // A single word that is a plain enum value.
// Map an optional operand type to its corresponding concrete type. // Map an optional operand type to its corresponding concrete type.
@ -636,7 +640,8 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
case SPV_OPERAND_TYPE_IMAGE: case SPV_OPERAND_TYPE_IMAGE:
case SPV_OPERAND_TYPE_OPTIONAL_IMAGE: case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS: 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. // This operand is a mask.
// Map an optional operand type to its corresponding concrete type. // Map an optional operand type to its corresponding concrete type.

View File

@ -265,7 +265,11 @@ void Disassembler::EmitOperand(const spv_parsed_instruction_t& inst,
case SPV_OPERAND_TYPE_BUILT_IN: case SPV_OPERAND_TYPE_BUILT_IN:
case SPV_OPERAND_TYPE_GROUP_OPERATION: case SPV_OPERAND_TYPE_GROUP_OPERATION:
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS: 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; spv_operand_desc entry;
if (grammar_.lookupOperand(operand.type, word, &entry)) if (grammar_.lookupOperand(operand.type, word, &entry))
assert(false && "should have caught this earlier"); assert(false && "should have caught this earlier");
@ -277,6 +281,7 @@ void Disassembler::EmitOperand(const spv_parsed_instruction_t& inst,
case SPV_OPERAND_TYPE_IMAGE: case SPV_OPERAND_TYPE_IMAGE:
case SPV_OPERAND_TYPE_MEMORY_ACCESS: case SPV_OPERAND_TYPE_MEMORY_ACCESS:
case SPV_OPERAND_TYPE_SELECTION_CONTROL: case SPV_OPERAND_TYPE_SELECTION_CONTROL:
case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
EmitMaskOperand(operand.type, word); EmitMaskOperand(operand.type, word);
break; break;
default: default:

View File

@ -17,12 +17,17 @@
#include <cassert> #include <cassert>
#include <cstring> #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_glsl_std_450_header.h"
#include "latest_version_opencl_std_header.h" #include "latest_version_opencl_std_header.h"
#include "macro.h"
#include "spirv_definition.h" #include "spirv_definition.h"
#include "macro.h" #include "debuginfo.insts.inc" // defines opencl_entries
#include "glsl.std.450.insts.inc" // defines glsl_entries #include "glsl.std.450.insts.inc" // defines glsl_entries
#include "opencl.std.insts.inc" // defines opencl_entries #include "opencl.std.insts.inc" // defines opencl_entries
@ -44,6 +49,8 @@ static const spv_ext_inst_group_t kGroups_1_0[] = {
ARRAY_SIZE(spv_amd_gcn_shader_entries), spv_amd_gcn_shader_entries}, ARRAY_SIZE(spv_amd_gcn_shader_entries), spv_amd_gcn_shader_entries},
{SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT, {SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT,
ARRAY_SIZE(spv_amd_shader_ballot_entries), spv_amd_shader_ballot_entries}, 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), static const spv_ext_inst_table_t kTable_1_0 = {ARRAY_SIZE(kGroups_1_0),
@ -101,6 +108,9 @@ spv_ext_inst_type_t spvExtInstImportTypeGet(const char* name) {
if (!strcmp("SPV_AMD_shader_ballot", name)) { if (!strcmp("SPV_AMD_shader_ballot", name)) {
return SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT; 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; return SPV_EXT_INST_TYPE_NONE;
} }

View File

@ -0,0 +1,568 @@
{
"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" }
]
}
]
}
]
}

View File

@ -200,6 +200,16 @@ const char* spvOperandTypeStr(spv_operand_type_t type) {
return "image"; return "image";
case SPV_OPERAND_TYPE_OPTIONAL_CIV: case SPV_OPERAND_TYPE_OPTIONAL_CIV:
return "context-insensitive value"; 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 // 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 // an operand. So the specific strings don't matter. But let's add them
@ -278,6 +288,10 @@ bool spvOperandIsConcrete(spv_operand_type_t type) {
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS: 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_CAPABILITY: 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; return true;
default: default:
break; break;
@ -293,6 +307,7 @@ bool spvOperandIsConcreteMask(spv_operand_type_t type) {
case SPV_OPERAND_TYPE_LOOP_CONTROL: case SPV_OPERAND_TYPE_LOOP_CONTROL:
case SPV_OPERAND_TYPE_FUNCTION_CONTROL: case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
case SPV_OPERAND_TYPE_MEMORY_ACCESS: case SPV_OPERAND_TYPE_MEMORY_ACCESS:
case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
return true; return true;
default: default:
break; break;

View File

@ -366,13 +366,16 @@ spv_result_t spvTextEncodeOperand(const libspirv::AssemblyGrammar& grammar,
if (context->binaryEncodeString(literal.str.c_str(), pInst)) if (context->binaryEncodeString(literal.str.c_str(), pInst))
return SPV_ERROR_INVALID_TEXT; return SPV_ERROR_INVALID_TEXT;
} break; } break;
// Masks.
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE: case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
case SPV_OPERAND_TYPE_FUNCTION_CONTROL: case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
case SPV_OPERAND_TYPE_LOOP_CONTROL: case SPV_OPERAND_TYPE_LOOP_CONTROL:
case SPV_OPERAND_TYPE_IMAGE: case SPV_OPERAND_TYPE_IMAGE:
case SPV_OPERAND_TYPE_OPTIONAL_IMAGE: case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS: 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; uint32_t value;
if (grammar.parseMaskOperand(type, textValue, &value)) { if (grammar.parseMaskOperand(type, textValue, &value)) {
return context->diagnostic() << "Invalid " << spvOperandTypeStr(type) return context->diagnostic() << "Invalid " << spvOperandTypeStr(type)

View File

@ -92,6 +92,7 @@ set(TEST_SOURCES
comment_test.cpp comment_test.cpp
enum_string_mapping_test.cpp enum_string_mapping_test.cpp
enum_set_test.cpp enum_set_test.cpp
ext_inst.debuginfo_test.cpp
ext_inst.glsl_test.cpp ext_inst.glsl_test.cpp
ext_inst.opencl_test.cpp ext_inst.opencl_test.cpp
fix_word_test.cpp fix_word_test.cpp

View File

@ -0,0 +1,808 @@
// 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

View File

@ -612,6 +612,10 @@ def main():
type=str, required=False, type=str, required=False,
help='input JSON grammar file for core SPIR-V ' help='input JSON grammar file for core SPIR-V '
'instructions') '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>', parser.add_argument('--extinst-glsl-grammar', metavar='<path>',
type=str, required=False, default=None, type=str, required=False, default=None,
help='input JSON grammar file for GLSL extended ' help='input JSON grammar file for GLSL extended '
@ -650,9 +654,13 @@ def main():
if (args.core_insts_output is None) != \ if (args.core_insts_output is None) != \
(args.operand_kinds_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.') 'should be specified together.')
exit(1) 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) != \ if (args.glsl_insts_output is None) != \
(args.extinst_glsl_grammar is None): (args.extinst_glsl_grammar is None):
print('error: --glsl-insts-output and --extinst-glsl-grammar ' print('error: --glsl-insts-output and --extinst-glsl-grammar '
@ -680,26 +688,28 @@ def main():
if args.spirv_core_grammar is not None: if args.spirv_core_grammar is not None:
with open(args.spirv_core_grammar) as json_file: with open(args.spirv_core_grammar) as json_file:
grammar = json.loads(json_file.read()) grammar = json.loads(json_file.read())
if args.core_insts_output is not None: with open(args.extinst_debuginfo_grammar) as debuginfo_json_file:
make_path_to_file(args.core_insts_output) debuginfo_grammar = json.loads(debuginfo_json_file.read())
make_path_to_file(args.operand_kinds_output) operand_kinds = grammar['operand_kinds']
version = '{}_{}'.format(grammar['major_version'], operand_kinds.extend(debuginfo_grammar['operand_kinds'])
grammar['minor_version']) if args.core_insts_output is not None:
print(generate_instruction_table( make_path_to_file(args.core_insts_output)
grammar['instructions'], version), make_path_to_file(args.operand_kinds_output)
file=open(args.core_insts_output, 'w')) version = '{}_{}'.format(grammar['major_version'],
print(generate_operand_kind_table( grammar['minor_version'])
grammar['operand_kinds'], version), print(generate_instruction_table(
file=open(args.operand_kinds_output, 'w')) grammar['instructions'], version),
if args.extension_enum_output is not None: file=open(args.core_insts_output, 'w'))
make_path_to_file(args.extension_enum_output) print(generate_operand_kind_table(operand_kinds, version),
print(generate_extension_enum(grammar['operand_kinds']), file=open(args.operand_kinds_output, 'w'))
file=open(args.extension_enum_output, 'w')) if args.extension_enum_output is not None:
if args.enum_string_mapping_output is not None: make_path_to_file(args.extension_enum_output)
make_path_to_file(args.enum_string_mapping_output) print(generate_extension_enum(grammar['operand_kinds']),
print(generate_all_string_enum_mappings( file=open(args.extension_enum_output, 'w'))
grammar['operand_kinds']), if args.enum_string_mapping_output is not None:
file=open(args.enum_string_mapping_output, 'w')) 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: if args.extinst_glsl_grammar is not None:
with open(args.extinst_glsl_grammar) as json_file: with open(args.extinst_glsl_grammar) as json_file:

View File

@ -0,0 +1,188 @@
#!/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()