spirv: Add better checks for SSA value types

Primarily, we check for two things:

 1. That we only ever add SSA values via vtn_push_ssa_value and
    vtn_copy_value.

 2. That the type of the SSA value matches the SPIR-V destination type.

Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5278>
This commit is contained in:
Jason Ekstrand
2020-05-29 16:10:28 -05:00
parent 47ebb50cab
commit d0be2fed4e
4 changed files with 31 additions and 6 deletions

View File

@@ -167,7 +167,7 @@ static struct vtn_ssa_value *
vtn_undef_ssa_value(struct vtn_builder *b, const struct glsl_type *type)
{
struct vtn_ssa_value *val = rzalloc(b, struct vtn_ssa_value);
val->type = type;
val->type = glsl_get_bare_type(type);
if (glsl_type_is_vector_or_scalar(type)) {
unsigned num_components = glsl_get_vector_elements(val->type);
@@ -202,7 +202,7 @@ vtn_const_ssa_value(struct vtn_builder *b, nir_constant *constant,
return entry->data;
struct vtn_ssa_value *val = rzalloc(b, struct vtn_ssa_value);
val->type = type;
val->type = glsl_get_bare_type(type);
if (glsl_type_is_vector_or_scalar(type)) {
unsigned num_components = glsl_get_vector_elements(val->type);
@@ -269,11 +269,17 @@ vtn_push_ssa_value(struct vtn_builder *b, uint32_t value_id,
{
struct vtn_type *type = vtn_get_value_type(b, value_id);
/* See vtn_create_ssa_value */
vtn_fail_if(ssa->type != glsl_get_bare_type(type->type),
"Type mismatch for SPIR-V SSA value");
struct vtn_value *val;
if (type->base_type == vtn_base_type_pointer) {
val = vtn_push_pointer(b, value_id, vtn_pointer_from_ssa(b, ssa->def, type));
} else {
val = vtn_push_value(b, value_id, vtn_value_type_ssa);
/* Don't trip the value_type_ssa check in vtn_push_value */
val = vtn_push_value(b, value_id, vtn_value_type_invalid);
val->value_type = vtn_value_type_ssa;
val->ssa = ssa;
}
@@ -2160,8 +2166,19 @@ vtn_emit_scoped_memory_barrier(struct vtn_builder *b, SpvScope scope,
struct vtn_ssa_value *
vtn_create_ssa_value(struct vtn_builder *b, const struct glsl_type *type)
{
/* Always use bare types for SSA values for a couple of reasons:
*
* 1. Code which emits deref chains should never listen to the explicit
* layout information on the SSA value if any exists. If we've
* accidentally been relying on this, we want to find those bugs.
*
* 2. We want to be able to quickly check that an SSA value being assigned
* to a SPIR-V value has the right type. Using bare types everywhere
* ensures that we can pointer-compare.
*/
struct vtn_ssa_value *val = rzalloc(b, struct vtn_ssa_value);
val->type = type;
val->type = glsl_get_bare_type(type);
if (!glsl_type_is_vector_or_scalar(type)) {
unsigned elems = glsl_get_length(val->type);

View File

@@ -43,7 +43,7 @@ wrap_matrix(struct vtn_builder *b, struct vtn_ssa_value *val)
return val;
struct vtn_ssa_value *dest = rzalloc(b, struct vtn_ssa_value);
dest->type = val->type;
dest->type = glsl_get_bare_type(val->type);
dest->elems = ralloc_array(b, struct vtn_ssa_value *, 1);
dest->elems[0] = val;

View File

@@ -710,6 +710,10 @@ vtn_push_value(struct vtn_builder *b, uint32_t value_id,
{
struct vtn_value *val = vtn_untyped_value(b, value_id);
vtn_fail_if(value_type == vtn_value_type_ssa,
"Do not call vtn_push_value for value_type_ssa. Use "
"vtn_push_ssa_value instead.");
vtn_fail_if(val->value_type != vtn_value_type_invalid,
"SPIR-V id %u has already been written by another instruction",
value_id);

View File

@@ -81,9 +81,13 @@ vtn_copy_value(struct vtn_builder *b, uint32_t src_value_id,
uint32_t dst_value_id)
{
struct vtn_value *src = vtn_untyped_value(b, src_value_id);
struct vtn_value *dst = vtn_push_value(b, dst_value_id, src->value_type);
struct vtn_value *dst = vtn_untyped_value(b, dst_value_id);
struct vtn_value src_copy = *src;
vtn_fail_if(dst->value_type != vtn_value_type_invalid,
"SPIR-V id %u has already been written by another instruction",
dst_value_id);
vtn_fail_if(dst->type->id != src->type->id,
"Result Type must equal Operand type");