101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2015 Intel Corporation
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg *
2301e04c3fSmrg * Authors:
2401e04c3fSmrg *    Jason Ekstrand (jason@jlekstrand.net)
2501e04c3fSmrg *
2601e04c3fSmrg */
2701e04c3fSmrg
2801e04c3fSmrg#ifndef _VTN_PRIVATE_H_
2901e04c3fSmrg#define _VTN_PRIVATE_H_
3001e04c3fSmrg
3101e04c3fSmrg#include <setjmp.h>
3201e04c3fSmrg
3301e04c3fSmrg#include "nir/nir.h"
3401e04c3fSmrg#include "nir/nir_builder.h"
3501e04c3fSmrg#include "util/u_dynarray.h"
3601e04c3fSmrg#include "nir_spirv.h"
3701e04c3fSmrg#include "spirv.h"
387ec681f3Smrg#include "vtn_generator_ids.h"
3901e04c3fSmrg
4001e04c3fSmrgstruct vtn_builder;
4101e04c3fSmrgstruct vtn_decoration;
4201e04c3fSmrg
437ec681f3Smrg/* setjmp/longjmp is broken on MinGW: https://sourceforge.net/p/mingw-w64/bugs/406/ */
447ec681f3Smrg#ifdef __MINGW32__
457ec681f3Smrg  #define vtn_setjmp __builtin_setjmp
467ec681f3Smrg  #define vtn_longjmp __builtin_longjmp
477ec681f3Smrg#else
487ec681f3Smrg  #define vtn_setjmp setjmp
497ec681f3Smrg  #define vtn_longjmp longjmp
507ec681f3Smrg#endif
517ec681f3Smrg
5201e04c3fSmrgvoid vtn_log(struct vtn_builder *b, enum nir_spirv_debug_level level,
5301e04c3fSmrg             size_t spirv_offset, const char *message);
5401e04c3fSmrg
5501e04c3fSmrgvoid vtn_logf(struct vtn_builder *b, enum nir_spirv_debug_level level,
5601e04c3fSmrg              size_t spirv_offset, const char *fmt, ...) PRINTFLIKE(4, 5);
5701e04c3fSmrg
5801e04c3fSmrg#define vtn_info(...) vtn_logf(b, NIR_SPIRV_DEBUG_LEVEL_INFO, 0, __VA_ARGS__)
5901e04c3fSmrg
6001e04c3fSmrgvoid _vtn_warn(struct vtn_builder *b, const char *file, unsigned line,
6101e04c3fSmrg               const char *fmt, ...) PRINTFLIKE(4, 5);
6201e04c3fSmrg#define vtn_warn(...) _vtn_warn(b, __FILE__, __LINE__, __VA_ARGS__)
6301e04c3fSmrg
6401e04c3fSmrgvoid _vtn_err(struct vtn_builder *b, const char *file, unsigned line,
6501e04c3fSmrg               const char *fmt, ...) PRINTFLIKE(4, 5);
6601e04c3fSmrg#define vtn_err(...) _vtn_err(b, __FILE__, __LINE__, __VA_ARGS__)
6701e04c3fSmrg
6801e04c3fSmrg/** Fail SPIR-V parsing
6901e04c3fSmrg *
7001e04c3fSmrg * This function logs an error and then bails out of the shader compile using
7101e04c3fSmrg * longjmp.  This being safe relies on two things:
7201e04c3fSmrg *
7301e04c3fSmrg *  1) We must guarantee that setjmp is called after allocating the builder
7401e04c3fSmrg *     and setting up b->debug (so that logging works) but before before any
7501e04c3fSmrg *     errors have a chance to occur.
7601e04c3fSmrg *
7701e04c3fSmrg *  2) While doing the SPIR-V -> NIR conversion, we need to be careful to
7801e04c3fSmrg *     ensure that all heap allocations happen through ralloc and are parented
7901e04c3fSmrg *     to the builder.  This way they will get properly cleaned up on error.
8001e04c3fSmrg *
8101e04c3fSmrg *  3) We must ensure that _vtn_fail is never called while a mutex lock or a
8201e04c3fSmrg *     reference to any other resource is held with the exception of ralloc
8301e04c3fSmrg *     objects which are parented to the builder.
8401e04c3fSmrg *
8501e04c3fSmrg * So long as these two things continue to hold, we can easily longjmp back to
8601e04c3fSmrg * spirv_to_nir(), clean up the builder, and return NULL.
8701e04c3fSmrg */
8801e04c3fSmrgNORETURN void
8901e04c3fSmrg_vtn_fail(struct vtn_builder *b, const char *file, unsigned line,
9001e04c3fSmrg             const char *fmt, ...) PRINTFLIKE(4, 5);
9101e04c3fSmrg
9201e04c3fSmrg#define vtn_fail(...) _vtn_fail(b, __FILE__, __LINE__, __VA_ARGS__)
9301e04c3fSmrg
9401e04c3fSmrg/** Fail if the given expression evaluates to true */
9501e04c3fSmrg#define vtn_fail_if(expr, ...) \
9601e04c3fSmrg   do { \
9701e04c3fSmrg      if (unlikely(expr)) \
9801e04c3fSmrg         vtn_fail(__VA_ARGS__); \
9901e04c3fSmrg   } while (0)
10001e04c3fSmrg
1017e102996Smaya#define _vtn_fail_with(t, msg, v) \
1027e102996Smaya   vtn_fail("%s: %s (%u)\n", msg, spirv_ ## t ## _to_string(v), v)
1037e102996Smaya
1047e102996Smaya#define vtn_fail_with_decoration(msg, v) _vtn_fail_with(decoration, msg, v)
1057e102996Smaya#define vtn_fail_with_opcode(msg, v)     _vtn_fail_with(op, msg, v)
1067e102996Smaya
10701e04c3fSmrg/** Assert that a condition is true and, if it isn't, vtn_fail
10801e04c3fSmrg *
10901e04c3fSmrg * This macro is transitional only and should not be used in new code.  Use
11001e04c3fSmrg * vtn_fail_if and provide a real message instead.
11101e04c3fSmrg */
11201e04c3fSmrg#define vtn_assert(expr) \
11301e04c3fSmrg   do { \
11401e04c3fSmrg      if (!likely(expr)) \
11501e04c3fSmrg         vtn_fail("%s", #expr); \
11601e04c3fSmrg   } while (0)
11701e04c3fSmrg
11801e04c3fSmrgenum vtn_value_type {
11901e04c3fSmrg   vtn_value_type_invalid = 0,
12001e04c3fSmrg   vtn_value_type_undef,
12101e04c3fSmrg   vtn_value_type_string,
12201e04c3fSmrg   vtn_value_type_decoration_group,
12301e04c3fSmrg   vtn_value_type_type,
12401e04c3fSmrg   vtn_value_type_constant,
12501e04c3fSmrg   vtn_value_type_pointer,
12601e04c3fSmrg   vtn_value_type_function,
12701e04c3fSmrg   vtn_value_type_block,
12801e04c3fSmrg   vtn_value_type_ssa,
12901e04c3fSmrg   vtn_value_type_extension,
13001e04c3fSmrg   vtn_value_type_image_pointer,
13101e04c3fSmrg};
13201e04c3fSmrg
13301e04c3fSmrgenum vtn_branch_type {
13401e04c3fSmrg   vtn_branch_type_none,
1357ec681f3Smrg   vtn_branch_type_if_merge,
13601e04c3fSmrg   vtn_branch_type_switch_break,
13701e04c3fSmrg   vtn_branch_type_switch_fallthrough,
13801e04c3fSmrg   vtn_branch_type_loop_break,
13901e04c3fSmrg   vtn_branch_type_loop_continue,
1407ec681f3Smrg   vtn_branch_type_loop_back_edge,
14101e04c3fSmrg   vtn_branch_type_discard,
1427ec681f3Smrg   vtn_branch_type_terminate_invocation,
1437ec681f3Smrg   vtn_branch_type_ignore_intersection,
1447ec681f3Smrg   vtn_branch_type_terminate_ray,
14501e04c3fSmrg   vtn_branch_type_return,
14601e04c3fSmrg};
14701e04c3fSmrg
14801e04c3fSmrgenum vtn_cf_node_type {
14901e04c3fSmrg   vtn_cf_node_type_block,
15001e04c3fSmrg   vtn_cf_node_type_if,
15101e04c3fSmrg   vtn_cf_node_type_loop,
1527ec681f3Smrg   vtn_cf_node_type_case,
15301e04c3fSmrg   vtn_cf_node_type_switch,
1547ec681f3Smrg   vtn_cf_node_type_function,
15501e04c3fSmrg};
15601e04c3fSmrg
15701e04c3fSmrgstruct vtn_cf_node {
15801e04c3fSmrg   struct list_head link;
1597ec681f3Smrg   struct vtn_cf_node *parent;
16001e04c3fSmrg   enum vtn_cf_node_type type;
16101e04c3fSmrg};
16201e04c3fSmrg
16301e04c3fSmrgstruct vtn_loop {
16401e04c3fSmrg   struct vtn_cf_node node;
16501e04c3fSmrg
16601e04c3fSmrg   /* The main body of the loop */
16701e04c3fSmrg   struct list_head body;
16801e04c3fSmrg
16901e04c3fSmrg   /* The "continue" part of the loop.  This gets executed after the body
17001e04c3fSmrg    * and is where you go when you hit a continue.
17101e04c3fSmrg    */
17201e04c3fSmrg   struct list_head cont_body;
17301e04c3fSmrg
1747ec681f3Smrg   struct vtn_block *header_block;
1757ec681f3Smrg   struct vtn_block *cont_block;
1767ec681f3Smrg   struct vtn_block *break_block;
1777ec681f3Smrg
17801e04c3fSmrg   SpvLoopControlMask control;
17901e04c3fSmrg};
18001e04c3fSmrg
18101e04c3fSmrgstruct vtn_if {
18201e04c3fSmrg   struct vtn_cf_node node;
18301e04c3fSmrg
18401e04c3fSmrg   enum vtn_branch_type then_type;
18501e04c3fSmrg   struct list_head then_body;
18601e04c3fSmrg
18701e04c3fSmrg   enum vtn_branch_type else_type;
18801e04c3fSmrg   struct list_head else_body;
18901e04c3fSmrg
1907ec681f3Smrg   struct vtn_block *header_block;
1917ec681f3Smrg   struct vtn_block *merge_block;
1927ec681f3Smrg
19301e04c3fSmrg   SpvSelectionControlMask control;
19401e04c3fSmrg};
19501e04c3fSmrg
19601e04c3fSmrgstruct vtn_case {
1977ec681f3Smrg   struct vtn_cf_node node;
19801e04c3fSmrg
1997ec681f3Smrg   struct vtn_block *block;
20001e04c3fSmrg
2017ec681f3Smrg   enum vtn_branch_type type;
2027ec681f3Smrg   struct list_head body;
20301e04c3fSmrg
20401e04c3fSmrg   /* The fallthrough case, if any */
20501e04c3fSmrg   struct vtn_case *fallthrough;
20601e04c3fSmrg
20701e04c3fSmrg   /* The uint32_t values that map to this case */
20801e04c3fSmrg   struct util_dynarray values;
20901e04c3fSmrg
21001e04c3fSmrg   /* True if this is the default case */
21101e04c3fSmrg   bool is_default;
21201e04c3fSmrg
21301e04c3fSmrg   /* Initialized to false; used when sorting the list of cases */
21401e04c3fSmrg   bool visited;
21501e04c3fSmrg};
21601e04c3fSmrg
21701e04c3fSmrgstruct vtn_switch {
21801e04c3fSmrg   struct vtn_cf_node node;
21901e04c3fSmrg
22001e04c3fSmrg   uint32_t selector;
22101e04c3fSmrg
22201e04c3fSmrg   struct list_head cases;
2237ec681f3Smrg
2247ec681f3Smrg   struct vtn_block *break_block;
22501e04c3fSmrg};
22601e04c3fSmrg
22701e04c3fSmrgstruct vtn_block {
22801e04c3fSmrg   struct vtn_cf_node node;
22901e04c3fSmrg
23001e04c3fSmrg   /** A pointer to the label instruction */
23101e04c3fSmrg   const uint32_t *label;
23201e04c3fSmrg
23301e04c3fSmrg   /** A pointer to the merge instruction (or NULL if non exists) */
23401e04c3fSmrg   const uint32_t *merge;
23501e04c3fSmrg
23601e04c3fSmrg   /** A pointer to the branch instruction that ends this block */
23701e04c3fSmrg   const uint32_t *branch;
23801e04c3fSmrg
23901e04c3fSmrg   enum vtn_branch_type branch_type;
24001e04c3fSmrg
2417ec681f3Smrg   /* The CF node for which this is a merge target
2427ec681f3Smrg    *
2437ec681f3Smrg    * The SPIR-V spec requires that any given block can be the merge target
2447ec681f3Smrg    * for at most one merge instruction.  If this block is a merge target,
2457ec681f3Smrg    * this points back to the block containing that merge instruction.
2467ec681f3Smrg    */
2477ec681f3Smrg   struct vtn_cf_node *merge_cf_node;
2487ec681f3Smrg
24901e04c3fSmrg   /** Points to the loop that this block starts (if it starts a loop) */
25001e04c3fSmrg   struct vtn_loop *loop;
25101e04c3fSmrg
25201e04c3fSmrg   /** Points to the switch case started by this block (if any) */
25301e04c3fSmrg   struct vtn_case *switch_case;
25401e04c3fSmrg
25501e04c3fSmrg   /** Every block ends in a nop intrinsic so that we can find it again */
25601e04c3fSmrg   nir_intrinsic_instr *end_nop;
2577ec681f3Smrg
2587ec681f3Smrg   /** attached nir_block */
2597ec681f3Smrg   struct nir_block *block;
26001e04c3fSmrg};
26101e04c3fSmrg
26201e04c3fSmrgstruct vtn_function {
2637ec681f3Smrg   struct vtn_cf_node node;
26401e04c3fSmrg
26501e04c3fSmrg   struct vtn_type *type;
26601e04c3fSmrg
26701e04c3fSmrg   bool referenced;
26801e04c3fSmrg   bool emitted;
26901e04c3fSmrg
2707ec681f3Smrg   nir_function *nir_func;
27101e04c3fSmrg   struct vtn_block *start_block;
27201e04c3fSmrg
27301e04c3fSmrg   struct list_head body;
27401e04c3fSmrg
27501e04c3fSmrg   const uint32_t *end;
27601e04c3fSmrg
27701e04c3fSmrg   SpvFunctionControlMask control;
27801e04c3fSmrg};
27901e04c3fSmrg
2807ec681f3Smrg#define VTN_DECL_CF_NODE_CAST(_type)               \
2817ec681f3Smrgstatic inline struct vtn_##_type *                 \
2827ec681f3Smrgvtn_cf_node_as_##_type(struct vtn_cf_node *node)   \
2837ec681f3Smrg{                                                  \
2847ec681f3Smrg   assert(node->type == vtn_cf_node_type_##_type); \
2857ec681f3Smrg   return (struct vtn_##_type *)node;              \
2867ec681f3Smrg}
2877ec681f3Smrg
2887ec681f3SmrgVTN_DECL_CF_NODE_CAST(block)
2897ec681f3SmrgVTN_DECL_CF_NODE_CAST(loop)
2907ec681f3SmrgVTN_DECL_CF_NODE_CAST(if)
2917ec681f3SmrgVTN_DECL_CF_NODE_CAST(case)
2927ec681f3SmrgVTN_DECL_CF_NODE_CAST(switch)
2937ec681f3SmrgVTN_DECL_CF_NODE_CAST(function)
2947ec681f3Smrg
2957ec681f3Smrg#define vtn_foreach_cf_node(node, cf_list) \
2967ec681f3Smrg   list_for_each_entry(struct vtn_cf_node, node, cf_list, link)
2977ec681f3Smrg
29801e04c3fSmrgtypedef bool (*vtn_instruction_handler)(struct vtn_builder *, SpvOp,
29901e04c3fSmrg                                        const uint32_t *, unsigned);
30001e04c3fSmrg
30101e04c3fSmrgvoid vtn_build_cfg(struct vtn_builder *b, const uint32_t *words,
30201e04c3fSmrg                   const uint32_t *end);
30301e04c3fSmrgvoid vtn_function_emit(struct vtn_builder *b, struct vtn_function *func,
30401e04c3fSmrg                       vtn_instruction_handler instruction_handler);
30501e04c3fSmrgvoid vtn_handle_function_call(struct vtn_builder *b, SpvOp opcode,
30601e04c3fSmrg                              const uint32_t *w, unsigned count);
30701e04c3fSmrg
30801e04c3fSmrgconst uint32_t *
30901e04c3fSmrgvtn_foreach_instruction(struct vtn_builder *b, const uint32_t *start,
31001e04c3fSmrg                        const uint32_t *end, vtn_instruction_handler handler);
31101e04c3fSmrg
31201e04c3fSmrgstruct vtn_ssa_value {
31301e04c3fSmrg   union {
31401e04c3fSmrg      nir_ssa_def *def;
31501e04c3fSmrg      struct vtn_ssa_value **elems;
31601e04c3fSmrg   };
31701e04c3fSmrg
31801e04c3fSmrg   /* For matrices, if this is non-NULL, then this value is actually the
31901e04c3fSmrg    * transpose of some other value.  The value that `transposed` points to
32001e04c3fSmrg    * always dominates this value.
32101e04c3fSmrg    */
32201e04c3fSmrg   struct vtn_ssa_value *transposed;
32301e04c3fSmrg
32401e04c3fSmrg   const struct glsl_type *type;
32501e04c3fSmrg};
32601e04c3fSmrg
32701e04c3fSmrgenum vtn_base_type {
32801e04c3fSmrg   vtn_base_type_void,
32901e04c3fSmrg   vtn_base_type_scalar,
33001e04c3fSmrg   vtn_base_type_vector,
33101e04c3fSmrg   vtn_base_type_matrix,
33201e04c3fSmrg   vtn_base_type_array,
33301e04c3fSmrg   vtn_base_type_struct,
33401e04c3fSmrg   vtn_base_type_pointer,
33501e04c3fSmrg   vtn_base_type_image,
33601e04c3fSmrg   vtn_base_type_sampler,
33701e04c3fSmrg   vtn_base_type_sampled_image,
3387ec681f3Smrg   vtn_base_type_accel_struct,
33901e04c3fSmrg   vtn_base_type_function,
3407ec681f3Smrg   vtn_base_type_event,
34101e04c3fSmrg};
34201e04c3fSmrg
34301e04c3fSmrgstruct vtn_type {
34401e04c3fSmrg   enum vtn_base_type base_type;
34501e04c3fSmrg
34601e04c3fSmrg   const struct glsl_type *type;
34701e04c3fSmrg
34801e04c3fSmrg   /* The SPIR-V id of the given type. */
34901e04c3fSmrg   uint32_t id;
35001e04c3fSmrg
35101e04c3fSmrg   /* Specifies the length of complex types.
35201e04c3fSmrg    *
35301e04c3fSmrg    * For Workgroup pointers, this is the size of the referenced type.
35401e04c3fSmrg    */
35501e04c3fSmrg   unsigned length;
35601e04c3fSmrg
35701e04c3fSmrg   /* for arrays, matrices and pointers, the array stride */
35801e04c3fSmrg   unsigned stride;
35901e04c3fSmrg
36001e04c3fSmrg   /* Access qualifiers */
36101e04c3fSmrg   enum gl_access_qualifier access;
36201e04c3fSmrg
36301e04c3fSmrg   union {
36401e04c3fSmrg      /* Members for scalar, vector, and array-like types */
36501e04c3fSmrg      struct {
36601e04c3fSmrg         /* for arrays, the vtn_type for the elements of the array */
36701e04c3fSmrg         struct vtn_type *array_element;
36801e04c3fSmrg
36901e04c3fSmrg         /* for matrices, whether the matrix is stored row-major */
37001e04c3fSmrg         bool row_major:1;
37101e04c3fSmrg
37201e04c3fSmrg         /* Whether this type, or a parent type, has been decorated as a
37301e04c3fSmrg          * builtin
37401e04c3fSmrg          */
37501e04c3fSmrg         bool is_builtin:1;
37601e04c3fSmrg
37701e04c3fSmrg         /* Which built-in to use */
37801e04c3fSmrg         SpvBuiltIn builtin;
37901e04c3fSmrg      };
38001e04c3fSmrg
38101e04c3fSmrg      /* Members for struct types */
38201e04c3fSmrg      struct {
38301e04c3fSmrg         /* for structures, the vtn_type for each member */
38401e04c3fSmrg         struct vtn_type **members;
38501e04c3fSmrg
38601e04c3fSmrg         /* for structs, the offset of each member */
38701e04c3fSmrg         unsigned *offsets;
38801e04c3fSmrg
38901e04c3fSmrg         /* for structs, whether it was decorated as a "non-SSBO-like" block */
39001e04c3fSmrg         bool block:1;
39101e04c3fSmrg
39201e04c3fSmrg         /* for structs, whether it was decorated as an "SSBO-like" block */
39301e04c3fSmrg         bool buffer_block:1;
39401e04c3fSmrg
39501e04c3fSmrg         /* for structs with block == true, whether this is a builtin block
39601e04c3fSmrg          * (i.e. a block that contains only builtins).
39701e04c3fSmrg          */
39801e04c3fSmrg         bool builtin_block:1;
3997e102996Smaya
4007e102996Smaya         /* for structs and unions it specifies the minimum alignment of the
4017e102996Smaya          * members. 0 means packed.
4027e102996Smaya          *
4037e102996Smaya          * Set by CPacked and Alignment Decorations in kernels.
4047e102996Smaya          */
4057e102996Smaya         bool packed:1;
40601e04c3fSmrg      };
40701e04c3fSmrg
40801e04c3fSmrg      /* Members for pointer types */
40901e04c3fSmrg      struct {
41001e04c3fSmrg         /* For pointers, the vtn_type for dereferenced type */
41101e04c3fSmrg         struct vtn_type *deref;
41201e04c3fSmrg
41301e04c3fSmrg         /* Storage class for pointers */
41401e04c3fSmrg         SpvStorageClass storage_class;
41501e04c3fSmrg
41601e04c3fSmrg         /* Required alignment for pointers */
41701e04c3fSmrg         uint32_t align;
41801e04c3fSmrg      };
41901e04c3fSmrg
42001e04c3fSmrg      /* Members for image types */
42101e04c3fSmrg      struct {
4227ec681f3Smrg         /* GLSL image type for this type.  This is not to be confused with
4237ec681f3Smrg          * vtn_type::type which is actually going to be the GLSL type for a
4247ec681f3Smrg          * pointer to an image, likely a uint32_t.
4257ec681f3Smrg          */
4267ec681f3Smrg         const struct glsl_type *glsl_image;
42701e04c3fSmrg
42801e04c3fSmrg         /* Image format for image_load_store type images */
42901e04c3fSmrg         unsigned image_format;
43001e04c3fSmrg
43101e04c3fSmrg         /* Access qualifier for storage images */
43201e04c3fSmrg         SpvAccessQualifier access_qualifier;
43301e04c3fSmrg      };
43401e04c3fSmrg
43501e04c3fSmrg      /* Members for sampled image types */
43601e04c3fSmrg      struct {
43701e04c3fSmrg         /* For sampled images, the image type */
43801e04c3fSmrg         struct vtn_type *image;
43901e04c3fSmrg      };
44001e04c3fSmrg
44101e04c3fSmrg      /* Members for function types */
44201e04c3fSmrg      struct {
44301e04c3fSmrg         /* For functions, the vtn_type for each parameter */
44401e04c3fSmrg         struct vtn_type **params;
44501e04c3fSmrg
44601e04c3fSmrg         /* Return type for functions */
44701e04c3fSmrg         struct vtn_type *return_type;
44801e04c3fSmrg      };
44901e04c3fSmrg   };
45001e04c3fSmrg};
45101e04c3fSmrg
4527e102996Smayabool vtn_type_contains_block(struct vtn_builder *b, struct vtn_type *type);
4537e102996Smaya
45401e04c3fSmrgbool vtn_types_compatible(struct vtn_builder *b,
45501e04c3fSmrg                          struct vtn_type *t1, struct vtn_type *t2);
45601e04c3fSmrg
4577ec681f3Smrgstruct vtn_type *vtn_type_without_array(struct vtn_type *type);
4587ec681f3Smrg
45901e04c3fSmrgstruct vtn_variable;
46001e04c3fSmrg
46101e04c3fSmrgenum vtn_access_mode {
46201e04c3fSmrg   vtn_access_mode_id,
46301e04c3fSmrg   vtn_access_mode_literal,
46401e04c3fSmrg};
46501e04c3fSmrg
46601e04c3fSmrgstruct vtn_access_link {
46701e04c3fSmrg   enum vtn_access_mode mode;
4687e102996Smaya   int64_t id;
46901e04c3fSmrg};
47001e04c3fSmrg
47101e04c3fSmrgstruct vtn_access_chain {
47201e04c3fSmrg   uint32_t length;
47301e04c3fSmrg
47401e04c3fSmrg   /** Whether or not to treat the base pointer as an array.  This is only
47501e04c3fSmrg    * true if this access chain came from an OpPtrAccessChain.
47601e04c3fSmrg    */
47701e04c3fSmrg   bool ptr_as_array;
47801e04c3fSmrg
4797e102996Smaya   /* Access qualifiers */
4807e102996Smaya   enum gl_access_qualifier access;
4817e102996Smaya
48201e04c3fSmrg   /** Struct elements and array offsets.
48301e04c3fSmrg    *
48401e04c3fSmrg    * This is an array of 1 so that it can conveniently be created on the
48501e04c3fSmrg    * stack but the real length is given by the length field.
48601e04c3fSmrg    */
48701e04c3fSmrg   struct vtn_access_link link[1];
48801e04c3fSmrg};
48901e04c3fSmrg
49001e04c3fSmrgenum vtn_variable_mode {
4917e102996Smaya   vtn_variable_mode_function,
4927e102996Smaya   vtn_variable_mode_private,
49301e04c3fSmrg   vtn_variable_mode_uniform,
4947ec681f3Smrg   vtn_variable_mode_atomic_counter,
49501e04c3fSmrg   vtn_variable_mode_ubo,
49601e04c3fSmrg   vtn_variable_mode_ssbo,
4977e102996Smaya   vtn_variable_mode_phys_ssbo,
49801e04c3fSmrg   vtn_variable_mode_push_constant,
49901e04c3fSmrg   vtn_variable_mode_workgroup,
5007e102996Smaya   vtn_variable_mode_cross_workgroup,
5017ec681f3Smrg   vtn_variable_mode_generic,
5027ec681f3Smrg   vtn_variable_mode_constant,
50301e04c3fSmrg   vtn_variable_mode_input,
50401e04c3fSmrg   vtn_variable_mode_output,
5057ec681f3Smrg   vtn_variable_mode_image,
5067ec681f3Smrg   vtn_variable_mode_accel_struct,
5077ec681f3Smrg   vtn_variable_mode_call_data,
5087ec681f3Smrg   vtn_variable_mode_call_data_in,
5097ec681f3Smrg   vtn_variable_mode_ray_payload,
5107ec681f3Smrg   vtn_variable_mode_ray_payload_in,
5117ec681f3Smrg   vtn_variable_mode_hit_attrib,
5127ec681f3Smrg   vtn_variable_mode_shader_record,
51301e04c3fSmrg};
51401e04c3fSmrg
51501e04c3fSmrgstruct vtn_pointer {
51601e04c3fSmrg   /** The variable mode for the referenced data */
51701e04c3fSmrg   enum vtn_variable_mode mode;
51801e04c3fSmrg
51901e04c3fSmrg   /** The dereferenced type of this pointer */
52001e04c3fSmrg   struct vtn_type *type;
52101e04c3fSmrg
52201e04c3fSmrg   /** The pointer type of this pointer
52301e04c3fSmrg    *
52401e04c3fSmrg    * This may be NULL for some temporary pointers constructed as part of a
52501e04c3fSmrg    * large load, store, or copy.  It MUST be valid for all pointers which are
52601e04c3fSmrg    * stored as SPIR-V SSA values.
52701e04c3fSmrg    */
52801e04c3fSmrg   struct vtn_type *ptr_type;
52901e04c3fSmrg
53001e04c3fSmrg   /** The referenced variable, if known
53101e04c3fSmrg    *
53201e04c3fSmrg    * This field may be NULL if the pointer uses a (block_index, offset) pair
53301e04c3fSmrg    * instead of an access chain or if the access chain starts at a deref.
53401e04c3fSmrg    */
53501e04c3fSmrg   struct vtn_variable *var;
53601e04c3fSmrg
5377e102996Smaya   /** The NIR deref corresponding to this pointer */
53801e04c3fSmrg   nir_deref_instr *deref;
53901e04c3fSmrg
54001e04c3fSmrg   /** A (block_index, offset) pair representing a UBO or SSBO position. */
54101e04c3fSmrg   struct nir_ssa_def *block_index;
54201e04c3fSmrg   struct nir_ssa_def *offset;
54301e04c3fSmrg
54401e04c3fSmrg   /* Access qualifiers */
54501e04c3fSmrg   enum gl_access_qualifier access;
54601e04c3fSmrg};
54701e04c3fSmrg
54801e04c3fSmrgstruct vtn_variable {
54901e04c3fSmrg   enum vtn_variable_mode mode;
55001e04c3fSmrg
55101e04c3fSmrg   struct vtn_type *type;
55201e04c3fSmrg
55301e04c3fSmrg   unsigned descriptor_set;
55401e04c3fSmrg   unsigned binding;
55501e04c3fSmrg   bool explicit_binding;
55601e04c3fSmrg   unsigned offset;
55701e04c3fSmrg   unsigned input_attachment_index;
55801e04c3fSmrg
55901e04c3fSmrg   nir_variable *var;
56001e04c3fSmrg
5617e102996Smaya   /* If the variable is a struct with a location set on it then this will be
5627e102996Smaya    * stored here. This will be used to calculate locations for members that
5637e102996Smaya    * don’t have their own explicit location.
5647e102996Smaya    */
5657e102996Smaya   int base_location;
5667e102996Smaya
56701e04c3fSmrg   /**
56801e04c3fSmrg    * In some early released versions of GLSLang, it implemented all function
56901e04c3fSmrg    * calls by making copies of all parameters into temporary variables and
57001e04c3fSmrg    * passing those variables into the function.  It even did so for samplers
57101e04c3fSmrg    * and images which violates the SPIR-V spec.  Unfortunately, two games
57201e04c3fSmrg    * (Talos Principle and Doom) shipped with this old version of GLSLang and
57301e04c3fSmrg    * also happen to pass samplers into functions.  Talos Principle received
57401e04c3fSmrg    * an update fairly shortly after release with an updated GLSLang.  Doom,
57501e04c3fSmrg    * on the other hand, has never received an update so we need to work
57601e04c3fSmrg    * around this GLSLang issue in SPIR-V -> NIR.  Hopefully, we can drop this
57701e04c3fSmrg    * hack at some point in the future.
57801e04c3fSmrg    */
57901e04c3fSmrg   struct vtn_pointer *copy_prop_sampler;
58001e04c3fSmrg
58101e04c3fSmrg   /* Access qualifiers. */
58201e04c3fSmrg   enum gl_access_qualifier access;
58301e04c3fSmrg};
58401e04c3fSmrg
5857ec681f3Smrgconst struct glsl_type *
5867ec681f3Smrgvtn_type_get_nir_type(struct vtn_builder *b, struct vtn_type *type,
5877ec681f3Smrg                      enum vtn_variable_mode mode);
5887ec681f3Smrg
58901e04c3fSmrgstruct vtn_image_pointer {
5907ec681f3Smrg   nir_deref_instr *image;
59101e04c3fSmrg   nir_ssa_def *coord;
59201e04c3fSmrg   nir_ssa_def *sample;
5937ec681f3Smrg   nir_ssa_def *lod;
59401e04c3fSmrg};
59501e04c3fSmrg
59601e04c3fSmrgstruct vtn_value {
59701e04c3fSmrg   enum vtn_value_type value_type;
5987ec681f3Smrg
5997ec681f3Smrg   /* Workaround for https://gitlab.freedesktop.org/mesa/mesa/-/issues/3406
6007ec681f3Smrg    * Only set for OpImage / OpSampledImage. Note that this is in addition
6017ec681f3Smrg    * the existence of a NonUniform decoration on this value.*/
6027ec681f3Smrg   uint32_t propagated_non_uniform : 1;
6037ec681f3Smrg
6047ec681f3Smrg   /* Valid for vtn_value_type_constant to indicate the value is OpConstantNull. */
6057ec681f3Smrg   bool is_null_constant:1;
6067ec681f3Smrg
6077ec681f3Smrg   /* Valid when all the members of the value are undef. */
6087ec681f3Smrg   bool is_undef_constant:1;
6097ec681f3Smrg
61001e04c3fSmrg   const char *name;
61101e04c3fSmrg   struct vtn_decoration *decoration;
61201e04c3fSmrg   struct vtn_type *type;
61301e04c3fSmrg   union {
6147ec681f3Smrg      const char *str;
61501e04c3fSmrg      nir_constant *constant;
61601e04c3fSmrg      struct vtn_pointer *pointer;
61701e04c3fSmrg      struct vtn_image_pointer *image;
61801e04c3fSmrg      struct vtn_function *func;
61901e04c3fSmrg      struct vtn_block *block;
62001e04c3fSmrg      struct vtn_ssa_value *ssa;
62101e04c3fSmrg      vtn_instruction_handler ext_handler;
62201e04c3fSmrg   };
62301e04c3fSmrg};
62401e04c3fSmrg
62501e04c3fSmrg#define VTN_DEC_DECORATION -1
62601e04c3fSmrg#define VTN_DEC_EXECUTION_MODE -2
62701e04c3fSmrg#define VTN_DEC_STRUCT_MEMBER0 0
62801e04c3fSmrg
62901e04c3fSmrgstruct vtn_decoration {
63001e04c3fSmrg   struct vtn_decoration *next;
63101e04c3fSmrg
63201e04c3fSmrg   /* Specifies how to apply this decoration.  Negative values represent a
63301e04c3fSmrg    * decoration or execution mode. (See the VTN_DEC_ #defines above.)
63401e04c3fSmrg    * Non-negative values specify that it applies to a structure member.
63501e04c3fSmrg    */
63601e04c3fSmrg   int scope;
63701e04c3fSmrg
6387e102996Smaya   const uint32_t *operands;
63901e04c3fSmrg   struct vtn_value *group;
64001e04c3fSmrg
64101e04c3fSmrg   union {
64201e04c3fSmrg      SpvDecoration decoration;
64301e04c3fSmrg      SpvExecutionMode exec_mode;
64401e04c3fSmrg   };
64501e04c3fSmrg};
64601e04c3fSmrg
64701e04c3fSmrgstruct vtn_builder {
64801e04c3fSmrg   nir_builder nb;
64901e04c3fSmrg
65001e04c3fSmrg   /* Used by vtn_fail to jump back to the beginning of SPIR-V compilation */
65101e04c3fSmrg   jmp_buf fail_jump;
65201e04c3fSmrg
65301e04c3fSmrg   const uint32_t *spirv;
65401e04c3fSmrg   size_t spirv_word_count;
6557ec681f3Smrg   uint32_t version;
65601e04c3fSmrg
65701e04c3fSmrg   nir_shader *shader;
6587e102996Smaya   struct spirv_to_nir_options *options;
65901e04c3fSmrg   struct vtn_block *block;
66001e04c3fSmrg
66101e04c3fSmrg   /* Current offset, file, line, and column.  Useful for debugging.  Set
66201e04c3fSmrg    * automatically by vtn_foreach_instruction.
66301e04c3fSmrg    */
66401e04c3fSmrg   size_t spirv_offset;
6657ec681f3Smrg   const char *file;
66601e04c3fSmrg   int line, col;
66701e04c3fSmrg
66801e04c3fSmrg   /*
66901e04c3fSmrg    * In SPIR-V, constants are global, whereas in NIR, the load_const
67001e04c3fSmrg    * instruction we use is per-function. So while we parse each function, we
67101e04c3fSmrg    * keep a hash table of constants we've resolved to nir_ssa_value's so
67201e04c3fSmrg    * far, and we lazily resolve them when we see them used in a function.
67301e04c3fSmrg    */
67401e04c3fSmrg   struct hash_table *const_table;
67501e04c3fSmrg
67601e04c3fSmrg   /*
67701e04c3fSmrg    * Map from phi instructions (pointer to the start of the instruction)
67801e04c3fSmrg    * to the variable corresponding to it.
67901e04c3fSmrg    */
68001e04c3fSmrg   struct hash_table *phi_table;
68101e04c3fSmrg
6827ec681f3Smrg   /* In Vulkan, when lowering some modes variable access, the derefs of the
6837ec681f3Smrg    * variables are replaced with a resource index intrinsics, leaving the
6847ec681f3Smrg    * variable hanging.  This set keeps track of them so they can be filtered
6857ec681f3Smrg    * (and not removed) in nir_remove_dead_variables.
6867ec681f3Smrg    */
6877ec681f3Smrg   struct set *vars_used_indirectly;
6887ec681f3Smrg
68901e04c3fSmrg   unsigned num_specializations;
69001e04c3fSmrg   struct nir_spirv_specialization *specializations;
69101e04c3fSmrg
69201e04c3fSmrg   unsigned value_id_bound;
69301e04c3fSmrg   struct vtn_value *values;
69401e04c3fSmrg
6957ec681f3Smrg   /* Information on the origin of the SPIR-V */
6967ec681f3Smrg   enum vtn_generator generator_id;
6977ec681f3Smrg   SpvSourceLanguage source_lang;
6987ec681f3Smrg
6997ec681f3Smrg   /* True if we need to fix up CS OpControlBarrier */
7007ec681f3Smrg   bool wa_glslang_cs_barrier;
7017ec681f3Smrg
7027ec681f3Smrg   /* True if we need to ignore undef initializers */
7037ec681f3Smrg   bool wa_llvm_spirv_ignore_workgroup_initializer;
7047ec681f3Smrg
7057ec681f3Smrg   /* Workaround discard bugs in HLSL -> SPIR-V compilers */
7067ec681f3Smrg   bool uses_demote_to_helper_invocation;
7077ec681f3Smrg   bool convert_discard_to_demote;
7087e102996Smaya
70901e04c3fSmrg   gl_shader_stage entry_point_stage;
71001e04c3fSmrg   const char *entry_point_name;
71101e04c3fSmrg   struct vtn_value *entry_point;
7127e102996Smaya   struct vtn_value *workgroup_size_builtin;
7137e102996Smaya   bool variable_pointers;
71401e04c3fSmrg
7157ec681f3Smrg   uint32_t *interface_ids;
7167ec681f3Smrg   size_t interface_ids_count;
7177ec681f3Smrg
71801e04c3fSmrg   struct vtn_function *func;
7197ec681f3Smrg   struct list_head functions;
72001e04c3fSmrg
72101e04c3fSmrg   /* Current function parameter index */
72201e04c3fSmrg   unsigned func_param_idx;
72301e04c3fSmrg
7247e102996Smaya   /* false by default, set to true by the ContractionOff execution mode */
7257e102996Smaya   bool exact;
7267e102996Smaya
7277e102996Smaya   /* when a physical memory model is choosen */
7287e102996Smaya   bool physical_ptrs;
7297ec681f3Smrg
7307ec681f3Smrg   /* memory model specified by OpMemoryModel */
7317ec681f3Smrg   unsigned mem_model;
73201e04c3fSmrg};
73301e04c3fSmrg
73401e04c3fSmrgnir_ssa_def *
73501e04c3fSmrgvtn_pointer_to_ssa(struct vtn_builder *b, struct vtn_pointer *ptr);
73601e04c3fSmrgstruct vtn_pointer *
73701e04c3fSmrgvtn_pointer_from_ssa(struct vtn_builder *b, nir_ssa_def *ssa,
73801e04c3fSmrg                     struct vtn_type *ptr_type);
73901e04c3fSmrg
7407ec681f3Smrgstruct vtn_ssa_value *
7417ec681f3Smrgvtn_const_ssa_value(struct vtn_builder *b, nir_constant *constant,
7427ec681f3Smrg                    const struct glsl_type *type);
7437ec681f3Smrg
74401e04c3fSmrgstatic inline struct vtn_value *
74501e04c3fSmrgvtn_untyped_value(struct vtn_builder *b, uint32_t value_id)
74601e04c3fSmrg{
74701e04c3fSmrg   vtn_fail_if(value_id >= b->value_id_bound,
74801e04c3fSmrg               "SPIR-V id %u is out-of-bounds", value_id);
74901e04c3fSmrg   return &b->values[value_id];
75001e04c3fSmrg}
75101e04c3fSmrg
7527ec681f3Smrgstatic inline uint32_t
7537ec681f3Smrgvtn_id_for_value(struct vtn_builder *b, struct vtn_value *value)
7547ec681f3Smrg{
7557ec681f3Smrg   vtn_fail_if(value <= b->values, "vtn_value pointer outside the range of valid values");
7567ec681f3Smrg   uint32_t value_id = value - b->values;
7577ec681f3Smrg   vtn_fail_if(value_id >= b->value_id_bound, "vtn_value pointer outside the range of valid values");
7587ec681f3Smrg   return value_id;
7597ec681f3Smrg}
7607ec681f3Smrg
7617e102996Smaya/* Consider not using this function directly and instead use
7627ec681f3Smrg * vtn_push_ssa/vtn_push_pointer so that appropriate applying of
7637e102996Smaya * decorations is handled by common code.
7647e102996Smaya */
76501e04c3fSmrgstatic inline struct vtn_value *
76601e04c3fSmrgvtn_push_value(struct vtn_builder *b, uint32_t value_id,
76701e04c3fSmrg               enum vtn_value_type value_type)
76801e04c3fSmrg{
76901e04c3fSmrg   struct vtn_value *val = vtn_untyped_value(b, value_id);
77001e04c3fSmrg
7717ec681f3Smrg   vtn_fail_if(value_type == vtn_value_type_ssa,
7727ec681f3Smrg               "Do not call vtn_push_value for value_type_ssa.  Use "
7737ec681f3Smrg               "vtn_push_ssa_value instead.");
7747ec681f3Smrg
77501e04c3fSmrg   vtn_fail_if(val->value_type != vtn_value_type_invalid,
77601e04c3fSmrg               "SPIR-V id %u has already been written by another instruction",
77701e04c3fSmrg               value_id);
77801e04c3fSmrg
77901e04c3fSmrg   val->value_type = value_type;
78001e04c3fSmrg
7817e102996Smaya   return &b->values[value_id];
78201e04c3fSmrg}
78301e04c3fSmrg
78401e04c3fSmrgstatic inline struct vtn_value *
78501e04c3fSmrgvtn_value(struct vtn_builder *b, uint32_t value_id,
78601e04c3fSmrg          enum vtn_value_type value_type)
78701e04c3fSmrg{
78801e04c3fSmrg   struct vtn_value *val = vtn_untyped_value(b, value_id);
78901e04c3fSmrg   vtn_fail_if(val->value_type != value_type,
79001e04c3fSmrg               "SPIR-V id %u is the wrong kind of value", value_id);
79101e04c3fSmrg   return val;
79201e04c3fSmrg}
79301e04c3fSmrg
7947ec681f3Smrgstatic inline struct vtn_value *
7957ec681f3Smrgvtn_pointer_value(struct vtn_builder *b, uint32_t value_id)
7967ec681f3Smrg{
7977ec681f3Smrg   struct vtn_value *val = vtn_untyped_value(b, value_id);
7987ec681f3Smrg   vtn_fail_if(val->value_type != vtn_value_type_pointer &&
7997ec681f3Smrg               !val->is_null_constant,
8007ec681f3Smrg               "SPIR-V id %u is the wrong kind of value", value_id);
8017ec681f3Smrg   return val;
8027ec681f3Smrg}
8037ec681f3Smrg
8047ec681f3Smrgstatic inline struct vtn_pointer *
8057ec681f3Smrgvtn_value_to_pointer(struct vtn_builder *b, struct vtn_value *value)
8067ec681f3Smrg{
8077ec681f3Smrg   if (value->is_null_constant) {
8087ec681f3Smrg      vtn_assert(glsl_type_is_vector_or_scalar(value->type->type));
8097ec681f3Smrg      nir_ssa_def *const_ssa =
8107ec681f3Smrg         vtn_const_ssa_value(b, value->constant, value->type->type)->def;
8117ec681f3Smrg      return vtn_pointer_from_ssa(b, const_ssa, value->type);
8127ec681f3Smrg   }
8137ec681f3Smrg   vtn_assert(value->value_type == vtn_value_type_pointer);
8147ec681f3Smrg   return value->pointer;
8157ec681f3Smrg}
8167ec681f3Smrg
8177ec681f3Smrgstatic inline struct vtn_pointer *
8187ec681f3Smrgvtn_pointer(struct vtn_builder *b, uint32_t value_id)
8197ec681f3Smrg{
8207ec681f3Smrg   return vtn_value_to_pointer(b, vtn_pointer_value(b, value_id));
8217ec681f3Smrg}
8227ec681f3Smrg
82301e04c3fSmrgbool
82401e04c3fSmrgvtn_set_instruction_result_type(struct vtn_builder *b, SpvOp opcode,
82501e04c3fSmrg                                const uint32_t *w, unsigned count);
82601e04c3fSmrg
8277e102996Smayastatic inline uint64_t
8287e102996Smayavtn_constant_uint(struct vtn_builder *b, uint32_t value_id)
82901e04c3fSmrg{
8307e102996Smaya   struct vtn_value *val = vtn_value(b, value_id, vtn_value_type_constant);
8317e102996Smaya
8327e102996Smaya   vtn_fail_if(val->type->base_type != vtn_base_type_scalar ||
8337e102996Smaya               !glsl_type_is_integer(val->type->type),
8347e102996Smaya               "Expected id %u to be an integer constant", value_id);
8357e102996Smaya
8367e102996Smaya   switch (glsl_get_bit_size(val->type->type)) {
8377ec681f3Smrg   case 8:  return val->constant->values[0].u8;
8387ec681f3Smrg   case 16: return val->constant->values[0].u16;
8397ec681f3Smrg   case 32: return val->constant->values[0].u32;
8407ec681f3Smrg   case 64: return val->constant->values[0].u64;
8417e102996Smaya   default: unreachable("Invalid bit size");
8427e102996Smaya   }
8437e102996Smaya}
8447e102996Smaya
8457ec681f3Smrgstatic inline int64_t
8467ec681f3Smrgvtn_constant_int(struct vtn_builder *b, uint32_t value_id)
8477e102996Smaya{
8487ec681f3Smrg   struct vtn_value *val = vtn_value(b, value_id, vtn_value_type_constant);
8497ec681f3Smrg
8507ec681f3Smrg   vtn_fail_if(val->type->base_type != vtn_base_type_scalar ||
8517ec681f3Smrg               !glsl_type_is_integer(val->type->type),
8527ec681f3Smrg               "Expected id %u to be an integer constant", value_id);
8537ec681f3Smrg
8547ec681f3Smrg   switch (glsl_get_bit_size(val->type->type)) {
8557ec681f3Smrg   case 8:  return val->constant->values[0].i8;
8567ec681f3Smrg   case 16: return val->constant->values[0].i16;
8577ec681f3Smrg   case 32: return val->constant->values[0].i32;
8587ec681f3Smrg   case 64: return val->constant->values[0].i64;
8597ec681f3Smrg   default: unreachable("Invalid bit size");
8607e102996Smaya   }
8617ec681f3Smrg}
8627ec681f3Smrg
8637ec681f3Smrgstatic inline struct vtn_type *
8647ec681f3Smrgvtn_get_value_type(struct vtn_builder *b, uint32_t value_id)
8657ec681f3Smrg{
8667ec681f3Smrg   struct vtn_value *val = vtn_untyped_value(b, value_id);
8677ec681f3Smrg   vtn_fail_if(val->type == NULL, "Value %u does not have a type", value_id);
8687ec681f3Smrg   return val->type;
8697ec681f3Smrg}
8707e102996Smaya
8717ec681f3Smrgstatic inline struct vtn_type *
8727ec681f3Smrgvtn_get_type(struct vtn_builder *b, uint32_t value_id)
8737ec681f3Smrg{
8747ec681f3Smrg   return vtn_value(b, value_id, vtn_value_type_type)->type;
87501e04c3fSmrg}
87601e04c3fSmrg
87701e04c3fSmrgstruct vtn_ssa_value *vtn_ssa_value(struct vtn_builder *b, uint32_t value_id);
8787ec681f3Smrgstruct vtn_value *vtn_push_ssa_value(struct vtn_builder *b, uint32_t value_id,
8797ec681f3Smrg                                     struct vtn_ssa_value *ssa);
88001e04c3fSmrg
8817ec681f3Smrgnir_ssa_def *vtn_get_nir_ssa(struct vtn_builder *b, uint32_t value_id);
8827ec681f3Smrgstruct vtn_value *vtn_push_nir_ssa(struct vtn_builder *b, uint32_t value_id,
8837ec681f3Smrg                                   nir_ssa_def *def);
8847e102996Smaya
8857ec681f3Smrgstruct vtn_value *vtn_push_pointer(struct vtn_builder *b,
8867ec681f3Smrg                                   uint32_t value_id,
8877ec681f3Smrg                                   struct vtn_pointer *ptr);
8887ec681f3Smrg
8897ec681f3Smrgstruct vtn_sampled_image {
8907ec681f3Smrg   nir_deref_instr *image;
8917ec681f3Smrg   nir_deref_instr *sampler;
8927ec681f3Smrg};
8937ec681f3Smrg
8947ec681f3Smrgnir_ssa_def *vtn_sampled_image_to_nir_ssa(struct vtn_builder *b,
8957ec681f3Smrg                                          struct vtn_sampled_image si);
8967ec681f3Smrg
8977ec681f3Smrgvoid
8987ec681f3Smrgvtn_copy_value(struct vtn_builder *b, uint32_t src_value_id,
8997ec681f3Smrg               uint32_t dst_value_id);
9007e102996Smaya
90101e04c3fSmrgstruct vtn_ssa_value *vtn_create_ssa_value(struct vtn_builder *b,
90201e04c3fSmrg                                           const struct glsl_type *type);
90301e04c3fSmrg
90401e04c3fSmrgstruct vtn_ssa_value *vtn_ssa_transpose(struct vtn_builder *b,
90501e04c3fSmrg                                        struct vtn_ssa_value *src);
90601e04c3fSmrg
90701e04c3fSmrgnir_deref_instr *vtn_nir_deref(struct vtn_builder *b, uint32_t id);
90801e04c3fSmrg
90901e04c3fSmrgnir_deref_instr *vtn_pointer_to_deref(struct vtn_builder *b,
91001e04c3fSmrg                                      struct vtn_pointer *ptr);
91101e04c3fSmrgnir_ssa_def *
91201e04c3fSmrgvtn_pointer_to_offset(struct vtn_builder *b, struct vtn_pointer *ptr,
91301e04c3fSmrg                      nir_ssa_def **index_out);
91401e04c3fSmrg
9157ec681f3Smrgnir_deref_instr *
9167ec681f3Smrgvtn_get_call_payload_for_location(struct vtn_builder *b, uint32_t location_id);
9177ec681f3Smrg
91801e04c3fSmrgstruct vtn_ssa_value *
9197e102996Smayavtn_local_load(struct vtn_builder *b, nir_deref_instr *src,
9207e102996Smaya               enum gl_access_qualifier access);
92101e04c3fSmrg
92201e04c3fSmrgvoid vtn_local_store(struct vtn_builder *b, struct vtn_ssa_value *src,
9237e102996Smaya                     nir_deref_instr *dest,
9247e102996Smaya                     enum gl_access_qualifier access);
92501e04c3fSmrg
92601e04c3fSmrgstruct vtn_ssa_value *
9277ec681f3Smrgvtn_variable_load(struct vtn_builder *b, struct vtn_pointer *src,
9287ec681f3Smrg                  enum gl_access_qualifier access);
92901e04c3fSmrg
93001e04c3fSmrgvoid vtn_variable_store(struct vtn_builder *b, struct vtn_ssa_value *src,
9317ec681f3Smrg                        struct vtn_pointer *dest, enum gl_access_qualifier access);
93201e04c3fSmrg
93301e04c3fSmrgvoid vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
93401e04c3fSmrg                          const uint32_t *w, unsigned count);
93501e04c3fSmrg
93601e04c3fSmrg
93701e04c3fSmrgtypedef void (*vtn_decoration_foreach_cb)(struct vtn_builder *,
93801e04c3fSmrg                                          struct vtn_value *,
93901e04c3fSmrg                                          int member,
94001e04c3fSmrg                                          const struct vtn_decoration *,
94101e04c3fSmrg                                          void *);
94201e04c3fSmrg
94301e04c3fSmrgvoid vtn_foreach_decoration(struct vtn_builder *b, struct vtn_value *value,
94401e04c3fSmrg                            vtn_decoration_foreach_cb cb, void *data);
94501e04c3fSmrg
94601e04c3fSmrgtypedef void (*vtn_execution_mode_foreach_cb)(struct vtn_builder *,
94701e04c3fSmrg                                              struct vtn_value *,
94801e04c3fSmrg                                              const struct vtn_decoration *,
94901e04c3fSmrg                                              void *);
95001e04c3fSmrg
95101e04c3fSmrgvoid vtn_foreach_execution_mode(struct vtn_builder *b, struct vtn_value *value,
95201e04c3fSmrg                                vtn_execution_mode_foreach_cb cb, void *data);
95301e04c3fSmrg
95401e04c3fSmrgnir_op vtn_nir_alu_op_for_spirv_opcode(struct vtn_builder *b,
9557ec681f3Smrg                                       SpvOp opcode, bool *swap, bool *exact,
95601e04c3fSmrg                                       unsigned src_bit_size, unsigned dst_bit_size);
95701e04c3fSmrg
95801e04c3fSmrgvoid vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,
95901e04c3fSmrg                    const uint32_t *w, unsigned count);
96001e04c3fSmrg
9617ec681f3Smrgvoid vtn_handle_integer_dot(struct vtn_builder *b, SpvOp opcode,
9627ec681f3Smrg                            const uint32_t *w, unsigned count);
9637ec681f3Smrg
9647e102996Smayavoid vtn_handle_bitcast(struct vtn_builder *b, const uint32_t *w,
9657e102996Smaya                        unsigned count);
9667e102996Smaya
9677ec681f3Smrgvoid vtn_handle_no_contraction(struct vtn_builder *b, struct vtn_value *val);
9687ec681f3Smrg
96901e04c3fSmrgvoid vtn_handle_subgroup(struct vtn_builder *b, SpvOp opcode,
97001e04c3fSmrg                         const uint32_t *w, unsigned count);
97101e04c3fSmrg
97201e04c3fSmrgbool vtn_handle_glsl450_instruction(struct vtn_builder *b, SpvOp ext_opcode,
97301e04c3fSmrg                                    const uint32_t *words, unsigned count);
97401e04c3fSmrg
9757ec681f3Smrgbool vtn_handle_opencl_instruction(struct vtn_builder *b, SpvOp ext_opcode,
9767e102996Smaya                                   const uint32_t *words, unsigned count);
9777ec681f3Smrgbool vtn_handle_opencl_core_instruction(struct vtn_builder *b, SpvOp opcode,
9787ec681f3Smrg                                        const uint32_t *w, unsigned count);
9797e102996Smaya
98001e04c3fSmrgstruct vtn_builder* vtn_create_builder(const uint32_t *words, size_t word_count,
98101e04c3fSmrg                                       gl_shader_stage stage, const char *entry_point_name,
98201e04c3fSmrg                                       const struct spirv_to_nir_options *options);
98301e04c3fSmrg
98401e04c3fSmrgvoid vtn_handle_entry_point(struct vtn_builder *b, const uint32_t *w,
98501e04c3fSmrg                            unsigned count);
98601e04c3fSmrg
98701e04c3fSmrgvoid vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode,
98801e04c3fSmrg                           const uint32_t *w, unsigned count);
98901e04c3fSmrg
9907ec681f3Smrgenum vtn_variable_mode vtn_storage_class_to_mode(struct vtn_builder *b,
9917ec681f3Smrg                                                 SpvStorageClass class,
9927ec681f3Smrg                                                 struct vtn_type *interface_type,
9937ec681f3Smrg                                                 nir_variable_mode *nir_mode_out);
9947ec681f3Smrg
9957ec681f3Smrgnir_address_format vtn_mode_to_address_format(struct vtn_builder *b,
9967ec681f3Smrg                                              enum vtn_variable_mode);
9977ec681f3Smrg
9987ec681f3Smrgnir_rounding_mode vtn_rounding_mode_to_nir(struct vtn_builder *b,
9997ec681f3Smrg                                           SpvFPRoundingMode mode);
10007ec681f3Smrg
100101e04c3fSmrgstatic inline uint32_t
100201e04c3fSmrgvtn_align_u32(uint32_t v, uint32_t a)
100301e04c3fSmrg{
100401e04c3fSmrg   assert(a != 0 && a == (a & -((int32_t) a)));
100501e04c3fSmrg   return (v + a - 1) & ~(a - 1);
100601e04c3fSmrg}
100701e04c3fSmrg
100801e04c3fSmrgstatic inline uint64_t
100901e04c3fSmrgvtn_u64_literal(const uint32_t *w)
101001e04c3fSmrg{
101101e04c3fSmrg   return (uint64_t)w[1] << 32 | w[0];
101201e04c3fSmrg}
101301e04c3fSmrg
101401e04c3fSmrgbool vtn_handle_amd_gcn_shader_instruction(struct vtn_builder *b, SpvOp ext_opcode,
101501e04c3fSmrg                                           const uint32_t *words, unsigned count);
101601e04c3fSmrg
10177ec681f3Smrgbool vtn_handle_amd_shader_ballot_instruction(struct vtn_builder *b, SpvOp ext_opcode,
10187ec681f3Smrg                                              const uint32_t *w, unsigned count);
10197ec681f3Smrg
102001e04c3fSmrgbool vtn_handle_amd_shader_trinary_minmax_instruction(struct vtn_builder *b, SpvOp ext_opcode,
102101e04c3fSmrg						      const uint32_t *words, unsigned count);
10227ec681f3Smrg
10237ec681f3Smrgbool vtn_handle_amd_shader_explicit_vertex_parameter_instruction(struct vtn_builder *b,
10247ec681f3Smrg                                                                 SpvOp ext_opcode,
10257ec681f3Smrg                                                                 const uint32_t *words,
10267ec681f3Smrg                                                                 unsigned count);
10277ec681f3Smrg
10287ec681f3SmrgSpvMemorySemanticsMask vtn_mode_to_memory_semantics(enum vtn_variable_mode mode);
10297ec681f3Smrg
10307ec681f3Smrgvoid vtn_emit_memory_barrier(struct vtn_builder *b, SpvScope scope,
10317ec681f3Smrg                             SpvMemorySemanticsMask semantics);
10327ec681f3Smrg
10337ec681f3Smrgstatic inline int
10347ec681f3Smrgcmp_uint32_t(const void *pa, const void *pb)
10357ec681f3Smrg{
10367ec681f3Smrg   uint32_t a = *((const uint32_t *)pa);
10377ec681f3Smrg   uint32_t b = *((const uint32_t *)pb);
10387ec681f3Smrg   if (a < b)
10397ec681f3Smrg      return -1;
10407ec681f3Smrg   if (a > b)
10417ec681f3Smrg      return 1;
10427ec681f3Smrg   return 0;
10437ec681f3Smrg}
10447ec681f3Smrg
104501e04c3fSmrg#endif /* _VTN_PRIVATE_H_ */
1046