spirv: Add a prepass to set types on vtn_values
This autogenerated pass will automatically find and set the type field on all vtn_values. This way we always have the type and can use it for validation and other checks. Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
@@ -56,6 +56,10 @@ spirv/spirv_info.c: spirv/spirv_info_c.py spirv/spirv.core.grammar.json
|
|||||||
$(MKDIR_GEN)
|
$(MKDIR_GEN)
|
||||||
$(PYTHON_GEN) $(srcdir)/spirv/spirv_info_c.py $(srcdir)/spirv/spirv.core.grammar.json $@ || ($(RM) $@; false)
|
$(PYTHON_GEN) $(srcdir)/spirv/spirv_info_c.py $(srcdir)/spirv/spirv.core.grammar.json $@ || ($(RM) $@; false)
|
||||||
|
|
||||||
|
spirv/vtn_gather_types.c: spirv/vtn_gather_types_c.py spirv/spirv.core.grammar.json
|
||||||
|
$(MKDIR_GEN)
|
||||||
|
$(PYTHON_GEN) $(srcdir)/spirv/vtn_gather_types_c.py $(srcdir)/spirv/spirv.core.grammar.json $@ || ($(RM) $@; false)
|
||||||
|
|
||||||
noinst_PROGRAMS += spirv2nir
|
noinst_PROGRAMS += spirv2nir
|
||||||
|
|
||||||
spirv2nir_SOURCES = \
|
spirv2nir_SOURCES = \
|
||||||
|
@@ -290,7 +290,8 @@ NIR_FILES = \
|
|||||||
nir/nir_worklist.h
|
nir/nir_worklist.h
|
||||||
|
|
||||||
SPIRV_GENERATED_FILES = \
|
SPIRV_GENERATED_FILES = \
|
||||||
spirv/spirv_info.c
|
spirv/spirv_info.c \
|
||||||
|
spirv/vtn_gather_types.c
|
||||||
|
|
||||||
SPIRV_FILES = \
|
SPIRV_FILES = \
|
||||||
spirv/GLSL.std.450.h \
|
spirv/GLSL.std.450.h \
|
||||||
|
@@ -72,6 +72,14 @@ spirv_info_c = custom_target(
|
|||||||
command : [prog_python2, '@INPUT0@', '@INPUT1@', '@OUTPUT@'],
|
command : [prog_python2, '@INPUT0@', '@INPUT1@', '@OUTPUT@'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
vtn_gather_types_c = custom_target(
|
||||||
|
'vtn_gather_types.c',
|
||||||
|
input : files('../spirv/vtn_gather_types_c.py',
|
||||||
|
'../spirv/spirv.core.grammar.json'),
|
||||||
|
output : 'vtn_gather_types.c',
|
||||||
|
command : [prog_python2, '@INPUT0@', '@INPUT1@', '@OUTPUT@'],
|
||||||
|
)
|
||||||
|
|
||||||
files_libnir = files(
|
files_libnir = files(
|
||||||
'nir.c',
|
'nir.c',
|
||||||
'nir.h',
|
'nir.h',
|
||||||
@@ -189,7 +197,8 @@ files_libnir = files(
|
|||||||
libnir = static_library(
|
libnir = static_library(
|
||||||
'nir',
|
'nir',
|
||||||
[files_libnir, spirv_info_c, nir_opt_algebraic_c, nir_opcodes_c,
|
[files_libnir, spirv_info_c, nir_opt_algebraic_c, nir_opcodes_c,
|
||||||
nir_opcodes_h, nir_constant_expressions_c, nir_builder_opcodes_h],
|
nir_opcodes_h, nir_constant_expressions_c, nir_builder_opcodes_h,
|
||||||
|
vtn_gather_types_c],
|
||||||
include_directories : [inc_common, inc_compiler, include_directories('../spirv')],
|
include_directories : [inc_common, inc_compiler, include_directories('../spirv')],
|
||||||
c_args : [c_vis_args, c_msvc_compat_args, no_override_init_args],
|
c_args : [c_vis_args, c_msvc_compat_args, no_override_init_args],
|
||||||
link_with : libcompiler,
|
link_with : libcompiler,
|
||||||
|
@@ -1265,7 +1265,6 @@ vtn_handle_constant(struct vtn_builder *b, SpvOp opcode,
|
|||||||
const uint32_t *w, unsigned count)
|
const uint32_t *w, unsigned count)
|
||||||
{
|
{
|
||||||
struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_constant);
|
struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_constant);
|
||||||
val->type = vtn_value(b, w[1], vtn_value_type_type)->type;
|
|
||||||
val->constant = rzalloc(b, nir_constant);
|
val->constant = rzalloc(b, nir_constant);
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case SpvOpConstantTrue:
|
case SpvOpConstantTrue:
|
||||||
@@ -3287,6 +3286,8 @@ static bool
|
|||||||
vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode,
|
vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode,
|
||||||
const uint32_t *w, unsigned count)
|
const uint32_t *w, unsigned count)
|
||||||
{
|
{
|
||||||
|
vtn_set_instruction_result_type(b, opcode, w, count);
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case SpvOpSource:
|
case SpvOpSource:
|
||||||
case SpvOpSourceContinued:
|
case SpvOpSourceContinued:
|
||||||
@@ -3677,6 +3678,9 @@ spirv_to_nir(const uint32_t *words, size_t word_count,
|
|||||||
words = vtn_foreach_instruction(b, words, word_end,
|
words = vtn_foreach_instruction(b, words, word_end,
|
||||||
vtn_handle_variable_or_type_instruction);
|
vtn_handle_variable_or_type_instruction);
|
||||||
|
|
||||||
|
/* Set types on all vtn_values */
|
||||||
|
vtn_foreach_instruction(b, words, word_end, vtn_set_instruction_result_type);
|
||||||
|
|
||||||
vtn_build_cfg(b, words, word_end);
|
vtn_build_cfg(b, words, word_end);
|
||||||
|
|
||||||
assert(b->entry_point->value_type == vtn_value_type_function);
|
assert(b->entry_point->value_type == vtn_value_type_function);
|
||||||
|
124
src/compiler/spirv/vtn_gather_types_c.py
Normal file
124
src/compiler/spirv/vtn_gather_types_c.py
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
COPYRIGHT = """\
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Intel Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
from sys import stdout
|
||||||
|
from mako.template import Template
|
||||||
|
|
||||||
|
def find_result_types(spirv):
|
||||||
|
for inst in spirv['instructions']:
|
||||||
|
name = inst['opname']
|
||||||
|
|
||||||
|
if 'operands' not in inst:
|
||||||
|
continue
|
||||||
|
|
||||||
|
res_arg_idx = -1
|
||||||
|
res_type_arg_idx = -1
|
||||||
|
for idx, arg in enumerate(inst['operands']):
|
||||||
|
if arg['kind'] == 'IdResult':
|
||||||
|
res_arg_idx = idx
|
||||||
|
elif arg['kind'] == 'IdResultType':
|
||||||
|
res_type_arg_idx = idx
|
||||||
|
|
||||||
|
if res_type_arg_idx >= 0:
|
||||||
|
assert res_arg_idx >= 0
|
||||||
|
elif res_arg_idx >= 0:
|
||||||
|
untyped_insts = [
|
||||||
|
'OpString',
|
||||||
|
'OpExtInstImport',
|
||||||
|
'OpDecorationGroup',
|
||||||
|
'OpLabel',
|
||||||
|
]
|
||||||
|
assert name.startswith('OpType') or name in untyped_insts
|
||||||
|
|
||||||
|
if res_arg_idx >= 0 or res_type_arg_idx >= 0:
|
||||||
|
yield (name, res_arg_idx, res_type_arg_idx)
|
||||||
|
|
||||||
|
TEMPLATE = Template(COPYRIGHT + """\
|
||||||
|
|
||||||
|
/* DO NOT EDIT - This file is generated automatically by the
|
||||||
|
* vtn_gather_types_c.py script
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "vtn_private.h"
|
||||||
|
|
||||||
|
struct type_args {
|
||||||
|
int res_idx;
|
||||||
|
int res_type_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct type_args
|
||||||
|
result_type_args_for_opcode(SpvOp opcode)
|
||||||
|
{
|
||||||
|
switch (opcode) {
|
||||||
|
% for opcode in opcodes:
|
||||||
|
case Spv${opcode[0]}: return (struct type_args){ ${opcode[1]}, ${opcode[2]} };
|
||||||
|
% endfor
|
||||||
|
default: return (struct type_args){ -1, -1 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
vtn_set_instruction_result_type(struct vtn_builder *b, SpvOp opcode,
|
||||||
|
const uint32_t *w, unsigned count)
|
||||||
|
{
|
||||||
|
struct type_args args = result_type_args_for_opcode(opcode);
|
||||||
|
|
||||||
|
if (args.res_idx >= 0 && args.res_type_idx >= 0) {
|
||||||
|
struct vtn_value *val = vtn_untyped_value(b, w[1 + args.res_idx]);
|
||||||
|
val->type = vtn_value(b, w[1 + args.res_type_idx],
|
||||||
|
vtn_value_type_type)->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
""")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
p = argparse.ArgumentParser()
|
||||||
|
p.add_argument("json")
|
||||||
|
p.add_argument("out")
|
||||||
|
args = p.parse_args()
|
||||||
|
|
||||||
|
spirv_info = json.JSONDecoder().decode(open(args.json, "r").read())
|
||||||
|
|
||||||
|
opcodes = list(find_result_types(spirv_info))
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(args.out, 'w') as f:
|
||||||
|
f.write(TEMPLATE.render(opcodes=opcodes))
|
||||||
|
except Exception:
|
||||||
|
# In the even there's an error this imports some helpers from mako
|
||||||
|
# to print a useful stack trace and prints it, then exits with
|
||||||
|
# status 1, if python is run with debug; otherwise it just raises
|
||||||
|
# the exception
|
||||||
|
if __debug__:
|
||||||
|
import sys
|
||||||
|
from mako import exceptions
|
||||||
|
sys.stderr.write(exceptions.text_error_template().render() + '\n')
|
||||||
|
sys.exit(1)
|
||||||
|
raise
|
@@ -620,6 +620,10 @@ vtn_value(struct vtn_builder *b, uint32_t value_id,
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
vtn_set_instruction_result_type(struct vtn_builder *b, SpvOp opcode,
|
||||||
|
const uint32_t *w, unsigned count);
|
||||||
|
|
||||||
struct vtn_ssa_value *vtn_ssa_value(struct vtn_builder *b, uint32_t value_id);
|
struct vtn_ssa_value *vtn_ssa_value(struct vtn_builder *b, uint32_t value_id);
|
||||||
|
|
||||||
struct vtn_ssa_value *vtn_create_ssa_value(struct vtn_builder *b,
|
struct vtn_ssa_value *vtn_create_ssa_value(struct vtn_builder *b,
|
||||||
|
Reference in New Issue
Block a user