1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2017 Connor Abbott
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
9b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice (including the next
12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
13b8e80941Smrg * Software.
14b8e80941Smrg *
15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21b8e80941Smrg * IN THE SOFTWARE.
22b8e80941Smrg */
23b8e80941Smrg
24b8e80941Smrg#include "nir_serialize.h"
25b8e80941Smrg#include "nir_control_flow.h"
26b8e80941Smrg#include "util/u_dynarray.h"
27b8e80941Smrg
28b8e80941Smrgtypedef struct {
29b8e80941Smrg   size_t blob_offset;
30b8e80941Smrg   nir_ssa_def *src;
31b8e80941Smrg   nir_block *block;
32b8e80941Smrg} write_phi_fixup;
33b8e80941Smrg
34b8e80941Smrgtypedef struct {
35b8e80941Smrg   const nir_shader *nir;
36b8e80941Smrg
37b8e80941Smrg   struct blob *blob;
38b8e80941Smrg
39b8e80941Smrg   /* maps pointer to index */
40b8e80941Smrg   struct hash_table *remap_table;
41b8e80941Smrg
42b8e80941Smrg   /* the next index to assign to a NIR in-memory object */
43b8e80941Smrg   uintptr_t next_idx;
44b8e80941Smrg
45b8e80941Smrg   /* Array of write_phi_fixup structs representing phi sources that need to
46b8e80941Smrg    * be resolved in the second pass.
47b8e80941Smrg    */
48b8e80941Smrg   struct util_dynarray phi_fixups;
49b8e80941Smrg} write_ctx;
50b8e80941Smrg
51b8e80941Smrgtypedef struct {
52b8e80941Smrg   nir_shader *nir;
53b8e80941Smrg
54b8e80941Smrg   struct blob_reader *blob;
55b8e80941Smrg
56b8e80941Smrg   /* the next index to assign to a NIR in-memory object */
57b8e80941Smrg   uintptr_t next_idx;
58b8e80941Smrg
59b8e80941Smrg   /* The length of the index -> object table */
60b8e80941Smrg   uintptr_t idx_table_len;
61b8e80941Smrg
62b8e80941Smrg   /* map from index to deserialized pointer */
63b8e80941Smrg   void **idx_table;
64b8e80941Smrg
65b8e80941Smrg   /* List of phi sources. */
66b8e80941Smrg   struct list_head phi_srcs;
67b8e80941Smrg
68b8e80941Smrg} read_ctx;
69b8e80941Smrg
70b8e80941Smrgstatic void
71b8e80941Smrgwrite_add_object(write_ctx *ctx, const void *obj)
72b8e80941Smrg{
73b8e80941Smrg   uintptr_t index = ctx->next_idx++;
74b8e80941Smrg   _mesa_hash_table_insert(ctx->remap_table, obj, (void *) index);
75b8e80941Smrg}
76b8e80941Smrg
77b8e80941Smrgstatic uintptr_t
78b8e80941Smrgwrite_lookup_object(write_ctx *ctx, const void *obj)
79b8e80941Smrg{
80b8e80941Smrg   struct hash_entry *entry = _mesa_hash_table_search(ctx->remap_table, obj);
81b8e80941Smrg   assert(entry);
82b8e80941Smrg   return (uintptr_t) entry->data;
83b8e80941Smrg}
84b8e80941Smrg
85b8e80941Smrgstatic void
86b8e80941Smrgwrite_object(write_ctx *ctx, const void *obj)
87b8e80941Smrg{
88b8e80941Smrg   blob_write_intptr(ctx->blob, write_lookup_object(ctx, obj));
89b8e80941Smrg}
90b8e80941Smrg
91b8e80941Smrgstatic void
92b8e80941Smrgread_add_object(read_ctx *ctx, void *obj)
93b8e80941Smrg{
94b8e80941Smrg   assert(ctx->next_idx < ctx->idx_table_len);
95b8e80941Smrg   ctx->idx_table[ctx->next_idx++] = obj;
96b8e80941Smrg}
97b8e80941Smrg
98b8e80941Smrgstatic void *
99b8e80941Smrgread_lookup_object(read_ctx *ctx, uintptr_t idx)
100b8e80941Smrg{
101b8e80941Smrg   assert(idx < ctx->idx_table_len);
102b8e80941Smrg   return ctx->idx_table[idx];
103b8e80941Smrg}
104b8e80941Smrg
105b8e80941Smrgstatic void *
106b8e80941Smrgread_object(read_ctx *ctx)
107b8e80941Smrg{
108b8e80941Smrg   return read_lookup_object(ctx, blob_read_intptr(ctx->blob));
109b8e80941Smrg}
110b8e80941Smrg
111b8e80941Smrgstatic void
112b8e80941Smrgwrite_constant(write_ctx *ctx, const nir_constant *c)
113b8e80941Smrg{
114b8e80941Smrg   blob_write_bytes(ctx->blob, c->values, sizeof(c->values));
115b8e80941Smrg   blob_write_uint32(ctx->blob, c->num_elements);
116b8e80941Smrg   for (unsigned i = 0; i < c->num_elements; i++)
117b8e80941Smrg      write_constant(ctx, c->elements[i]);
118b8e80941Smrg}
119b8e80941Smrg
120b8e80941Smrgstatic nir_constant *
121b8e80941Smrgread_constant(read_ctx *ctx, nir_variable *nvar)
122b8e80941Smrg{
123b8e80941Smrg   nir_constant *c = ralloc(nvar, nir_constant);
124b8e80941Smrg
125b8e80941Smrg   blob_copy_bytes(ctx->blob, (uint8_t *)c->values, sizeof(c->values));
126b8e80941Smrg   c->num_elements = blob_read_uint32(ctx->blob);
127b8e80941Smrg   c->elements = ralloc_array(nvar, nir_constant *, c->num_elements);
128b8e80941Smrg   for (unsigned i = 0; i < c->num_elements; i++)
129b8e80941Smrg      c->elements[i] = read_constant(ctx, nvar);
130b8e80941Smrg
131b8e80941Smrg   return c;
132b8e80941Smrg}
133b8e80941Smrg
134b8e80941Smrgstatic void
135b8e80941Smrgwrite_variable(write_ctx *ctx, const nir_variable *var)
136b8e80941Smrg{
137b8e80941Smrg   write_add_object(ctx, var);
138b8e80941Smrg   encode_type_to_blob(ctx->blob, var->type);
139b8e80941Smrg   blob_write_uint32(ctx->blob, !!(var->name));
140b8e80941Smrg   if (var->name)
141b8e80941Smrg      blob_write_string(ctx->blob, var->name);
142b8e80941Smrg   blob_write_bytes(ctx->blob, (uint8_t *) &var->data, sizeof(var->data));
143b8e80941Smrg   blob_write_uint32(ctx->blob, var->num_state_slots);
144b8e80941Smrg   for (unsigned i = 0; i < var->num_state_slots; i++) {
145b8e80941Smrg      for (unsigned j = 0; j < STATE_LENGTH; j++)
146b8e80941Smrg         blob_write_uint32(ctx->blob, var->state_slots[i].tokens[j]);
147b8e80941Smrg      blob_write_uint32(ctx->blob, var->state_slots[i].swizzle);
148b8e80941Smrg   }
149b8e80941Smrg   blob_write_uint32(ctx->blob, !!(var->constant_initializer));
150b8e80941Smrg   if (var->constant_initializer)
151b8e80941Smrg      write_constant(ctx, var->constant_initializer);
152b8e80941Smrg   blob_write_uint32(ctx->blob, !!(var->interface_type));
153b8e80941Smrg   if (var->interface_type)
154b8e80941Smrg      encode_type_to_blob(ctx->blob, var->interface_type);
155b8e80941Smrg   blob_write_uint32(ctx->blob, var->num_members);
156b8e80941Smrg   if (var->num_members > 0) {
157b8e80941Smrg      blob_write_bytes(ctx->blob, (uint8_t *) var->members,
158b8e80941Smrg                       var->num_members * sizeof(*var->members));
159b8e80941Smrg   }
160b8e80941Smrg}
161b8e80941Smrg
162b8e80941Smrgstatic nir_variable *
163b8e80941Smrgread_variable(read_ctx *ctx)
164b8e80941Smrg{
165b8e80941Smrg   nir_variable *var = rzalloc(ctx->nir, nir_variable);
166b8e80941Smrg   read_add_object(ctx, var);
167b8e80941Smrg
168b8e80941Smrg   var->type = decode_type_from_blob(ctx->blob);
169b8e80941Smrg   bool has_name = blob_read_uint32(ctx->blob);
170b8e80941Smrg   if (has_name) {
171b8e80941Smrg      const char *name = blob_read_string(ctx->blob);
172b8e80941Smrg      var->name = ralloc_strdup(var, name);
173b8e80941Smrg   } else {
174b8e80941Smrg      var->name = NULL;
175b8e80941Smrg   }
176b8e80941Smrg   blob_copy_bytes(ctx->blob, (uint8_t *) &var->data, sizeof(var->data));
177b8e80941Smrg   var->num_state_slots = blob_read_uint32(ctx->blob);
178b8e80941Smrg   if (var->num_state_slots != 0) {
179b8e80941Smrg      var->state_slots = ralloc_array(var, nir_state_slot,
180b8e80941Smrg                                      var->num_state_slots);
181b8e80941Smrg      for (unsigned i = 0; i < var->num_state_slots; i++) {
182b8e80941Smrg         for (unsigned j = 0; j < STATE_LENGTH; j++)
183b8e80941Smrg            var->state_slots[i].tokens[j] = blob_read_uint32(ctx->blob);
184b8e80941Smrg         var->state_slots[i].swizzle = blob_read_uint32(ctx->blob);
185b8e80941Smrg      }
186b8e80941Smrg   }
187b8e80941Smrg   bool has_const_initializer = blob_read_uint32(ctx->blob);
188b8e80941Smrg   if (has_const_initializer)
189b8e80941Smrg      var->constant_initializer = read_constant(ctx, var);
190b8e80941Smrg   else
191b8e80941Smrg      var->constant_initializer = NULL;
192b8e80941Smrg   bool has_interface_type = blob_read_uint32(ctx->blob);
193b8e80941Smrg   if (has_interface_type)
194b8e80941Smrg      var->interface_type = decode_type_from_blob(ctx->blob);
195b8e80941Smrg   else
196b8e80941Smrg      var->interface_type = NULL;
197b8e80941Smrg   var->num_members = blob_read_uint32(ctx->blob);
198b8e80941Smrg   if (var->num_members > 0) {
199b8e80941Smrg      var->members = ralloc_array(var, struct nir_variable_data,
200b8e80941Smrg                                  var->num_members);
201b8e80941Smrg      blob_copy_bytes(ctx->blob, (uint8_t *) var->members,
202b8e80941Smrg                      var->num_members * sizeof(*var->members));
203b8e80941Smrg   }
204b8e80941Smrg
205b8e80941Smrg   return var;
206b8e80941Smrg}
207b8e80941Smrg
208b8e80941Smrgstatic void
209b8e80941Smrgwrite_var_list(write_ctx *ctx, const struct exec_list *src)
210b8e80941Smrg{
211b8e80941Smrg   blob_write_uint32(ctx->blob, exec_list_length(src));
212b8e80941Smrg   foreach_list_typed(nir_variable, var, node, src) {
213b8e80941Smrg      write_variable(ctx, var);
214b8e80941Smrg   }
215b8e80941Smrg}
216b8e80941Smrg
217b8e80941Smrgstatic void
218b8e80941Smrgread_var_list(read_ctx *ctx, struct exec_list *dst)
219b8e80941Smrg{
220b8e80941Smrg   exec_list_make_empty(dst);
221b8e80941Smrg   unsigned num_vars = blob_read_uint32(ctx->blob);
222b8e80941Smrg   for (unsigned i = 0; i < num_vars; i++) {
223b8e80941Smrg      nir_variable *var = read_variable(ctx);
224b8e80941Smrg      exec_list_push_tail(dst, &var->node);
225b8e80941Smrg   }
226b8e80941Smrg}
227b8e80941Smrg
228b8e80941Smrgstatic void
229b8e80941Smrgwrite_register(write_ctx *ctx, const nir_register *reg)
230b8e80941Smrg{
231b8e80941Smrg   write_add_object(ctx, reg);
232b8e80941Smrg   blob_write_uint32(ctx->blob, reg->num_components);
233b8e80941Smrg   blob_write_uint32(ctx->blob, reg->bit_size);
234b8e80941Smrg   blob_write_uint32(ctx->blob, reg->num_array_elems);
235b8e80941Smrg   blob_write_uint32(ctx->blob, reg->index);
236b8e80941Smrg   blob_write_uint32(ctx->blob, !!(reg->name));
237b8e80941Smrg   if (reg->name)
238b8e80941Smrg      blob_write_string(ctx->blob, reg->name);
239b8e80941Smrg}
240b8e80941Smrg
241b8e80941Smrgstatic nir_register *
242b8e80941Smrgread_register(read_ctx *ctx)
243b8e80941Smrg{
244b8e80941Smrg   nir_register *reg = ralloc(ctx->nir, nir_register);
245b8e80941Smrg   read_add_object(ctx, reg);
246b8e80941Smrg   reg->num_components = blob_read_uint32(ctx->blob);
247b8e80941Smrg   reg->bit_size = blob_read_uint32(ctx->blob);
248b8e80941Smrg   reg->num_array_elems = blob_read_uint32(ctx->blob);
249b8e80941Smrg   reg->index = blob_read_uint32(ctx->blob);
250b8e80941Smrg   bool has_name = blob_read_uint32(ctx->blob);
251b8e80941Smrg   if (has_name) {
252b8e80941Smrg      const char *name = blob_read_string(ctx->blob);
253b8e80941Smrg      reg->name = ralloc_strdup(reg, name);
254b8e80941Smrg   } else {
255b8e80941Smrg      reg->name = NULL;
256b8e80941Smrg   }
257b8e80941Smrg
258b8e80941Smrg   list_inithead(&reg->uses);
259b8e80941Smrg   list_inithead(&reg->defs);
260b8e80941Smrg   list_inithead(&reg->if_uses);
261b8e80941Smrg
262b8e80941Smrg   return reg;
263b8e80941Smrg}
264b8e80941Smrg
265b8e80941Smrgstatic void
266b8e80941Smrgwrite_reg_list(write_ctx *ctx, const struct exec_list *src)
267b8e80941Smrg{
268b8e80941Smrg   blob_write_uint32(ctx->blob, exec_list_length(src));
269b8e80941Smrg   foreach_list_typed(nir_register, reg, node, src)
270b8e80941Smrg      write_register(ctx, reg);
271b8e80941Smrg}
272b8e80941Smrg
273b8e80941Smrgstatic void
274b8e80941Smrgread_reg_list(read_ctx *ctx, struct exec_list *dst)
275b8e80941Smrg{
276b8e80941Smrg   exec_list_make_empty(dst);
277b8e80941Smrg   unsigned num_regs = blob_read_uint32(ctx->blob);
278b8e80941Smrg   for (unsigned i = 0; i < num_regs; i++) {
279b8e80941Smrg      nir_register *reg = read_register(ctx);
280b8e80941Smrg      exec_list_push_tail(dst, &reg->node);
281b8e80941Smrg   }
282b8e80941Smrg}
283b8e80941Smrg
284b8e80941Smrgstatic void
285b8e80941Smrgwrite_src(write_ctx *ctx, const nir_src *src)
286b8e80941Smrg{
287b8e80941Smrg   /* Since sources are very frequent, we try to save some space when storing
288b8e80941Smrg    * them. In particular, we store whether the source is a register and
289b8e80941Smrg    * whether the register has an indirect index in the low two bits. We can
290b8e80941Smrg    * assume that the high two bits of the index are zero, since otherwise our
291b8e80941Smrg    * address space would've been exhausted allocating the remap table!
292b8e80941Smrg    */
293b8e80941Smrg   if (src->is_ssa) {
294b8e80941Smrg      uintptr_t idx = write_lookup_object(ctx, src->ssa) << 2;
295b8e80941Smrg      idx |= 1;
296b8e80941Smrg      blob_write_intptr(ctx->blob, idx);
297b8e80941Smrg   } else {
298b8e80941Smrg      uintptr_t idx = write_lookup_object(ctx, src->reg.reg) << 2;
299b8e80941Smrg      if (src->reg.indirect)
300b8e80941Smrg         idx |= 2;
301b8e80941Smrg      blob_write_intptr(ctx->blob, idx);
302b8e80941Smrg      blob_write_uint32(ctx->blob, src->reg.base_offset);
303b8e80941Smrg      if (src->reg.indirect) {
304b8e80941Smrg         write_src(ctx, src->reg.indirect);
305b8e80941Smrg      }
306b8e80941Smrg   }
307b8e80941Smrg}
308b8e80941Smrg
309b8e80941Smrgstatic void
310b8e80941Smrgread_src(read_ctx *ctx, nir_src *src, void *mem_ctx)
311b8e80941Smrg{
312b8e80941Smrg   uintptr_t val = blob_read_intptr(ctx->blob);
313b8e80941Smrg   uintptr_t idx = val >> 2;
314b8e80941Smrg   src->is_ssa = val & 0x1;
315b8e80941Smrg   if (src->is_ssa) {
316b8e80941Smrg      src->ssa = read_lookup_object(ctx, idx);
317b8e80941Smrg   } else {
318b8e80941Smrg      bool is_indirect = val & 0x2;
319b8e80941Smrg      src->reg.reg = read_lookup_object(ctx, idx);
320b8e80941Smrg      src->reg.base_offset = blob_read_uint32(ctx->blob);
321b8e80941Smrg      if (is_indirect) {
322b8e80941Smrg         src->reg.indirect = ralloc(mem_ctx, nir_src);
323b8e80941Smrg         read_src(ctx, src->reg.indirect, mem_ctx);
324b8e80941Smrg      } else {
325b8e80941Smrg         src->reg.indirect = NULL;
326b8e80941Smrg      }
327b8e80941Smrg   }
328b8e80941Smrg}
329b8e80941Smrg
330b8e80941Smrgstatic void
331b8e80941Smrgwrite_dest(write_ctx *ctx, const nir_dest *dst)
332b8e80941Smrg{
333b8e80941Smrg   uint32_t val = dst->is_ssa;
334b8e80941Smrg   if (dst->is_ssa) {
335b8e80941Smrg      val |= !!(dst->ssa.name) << 1;
336b8e80941Smrg      val |= dst->ssa.num_components << 2;
337b8e80941Smrg      val |= dst->ssa.bit_size << 5;
338b8e80941Smrg   } else {
339b8e80941Smrg      val |= !!(dst->reg.indirect) << 1;
340b8e80941Smrg   }
341b8e80941Smrg   blob_write_uint32(ctx->blob, val);
342b8e80941Smrg   if (dst->is_ssa) {
343b8e80941Smrg      write_add_object(ctx, &dst->ssa);
344b8e80941Smrg      if (dst->ssa.name)
345b8e80941Smrg         blob_write_string(ctx->blob, dst->ssa.name);
346b8e80941Smrg   } else {
347b8e80941Smrg      blob_write_intptr(ctx->blob, write_lookup_object(ctx, dst->reg.reg));
348b8e80941Smrg      blob_write_uint32(ctx->blob, dst->reg.base_offset);
349b8e80941Smrg      if (dst->reg.indirect)
350b8e80941Smrg         write_src(ctx, dst->reg.indirect);
351b8e80941Smrg   }
352b8e80941Smrg}
353b8e80941Smrg
354b8e80941Smrgstatic void
355b8e80941Smrgread_dest(read_ctx *ctx, nir_dest *dst, nir_instr *instr)
356b8e80941Smrg{
357b8e80941Smrg   uint32_t val = blob_read_uint32(ctx->blob);
358b8e80941Smrg   bool is_ssa = val & 0x1;
359b8e80941Smrg   if (is_ssa) {
360b8e80941Smrg      bool has_name = val & 0x2;
361b8e80941Smrg      unsigned num_components = (val >> 2) & 0x7;
362b8e80941Smrg      unsigned bit_size = val >> 5;
363b8e80941Smrg      char *name = has_name ? blob_read_string(ctx->blob) : NULL;
364b8e80941Smrg      nir_ssa_dest_init(instr, dst, num_components, bit_size, name);
365b8e80941Smrg      read_add_object(ctx, &dst->ssa);
366b8e80941Smrg   } else {
367b8e80941Smrg      bool is_indirect = val & 0x2;
368b8e80941Smrg      dst->reg.reg = read_object(ctx);
369b8e80941Smrg      dst->reg.base_offset = blob_read_uint32(ctx->blob);
370b8e80941Smrg      if (is_indirect) {
371b8e80941Smrg         dst->reg.indirect = ralloc(instr, nir_src);
372b8e80941Smrg         read_src(ctx, dst->reg.indirect, instr);
373b8e80941Smrg      }
374b8e80941Smrg   }
375b8e80941Smrg}
376b8e80941Smrg
377b8e80941Smrgstatic void
378b8e80941Smrgwrite_alu(write_ctx *ctx, const nir_alu_instr *alu)
379b8e80941Smrg{
380b8e80941Smrg   blob_write_uint32(ctx->blob, alu->op);
381b8e80941Smrg   uint32_t flags = alu->exact;
382b8e80941Smrg   flags |= alu->dest.saturate << 1;
383b8e80941Smrg   flags |= alu->dest.write_mask << 2;
384b8e80941Smrg   blob_write_uint32(ctx->blob, flags);
385b8e80941Smrg
386b8e80941Smrg   write_dest(ctx, &alu->dest.dest);
387b8e80941Smrg
388b8e80941Smrg   for (unsigned i = 0; i < nir_op_infos[alu->op].num_inputs; i++) {
389b8e80941Smrg      write_src(ctx, &alu->src[i].src);
390b8e80941Smrg      flags = alu->src[i].negate;
391b8e80941Smrg      flags |= alu->src[i].abs << 1;
392b8e80941Smrg      for (unsigned j = 0; j < 4; j++)
393b8e80941Smrg         flags |= alu->src[i].swizzle[j] << (2 + 2 * j);
394b8e80941Smrg      blob_write_uint32(ctx->blob, flags);
395b8e80941Smrg   }
396b8e80941Smrg}
397b8e80941Smrg
398b8e80941Smrgstatic nir_alu_instr *
399b8e80941Smrgread_alu(read_ctx *ctx)
400b8e80941Smrg{
401b8e80941Smrg   nir_op op = blob_read_uint32(ctx->blob);
402b8e80941Smrg   nir_alu_instr *alu = nir_alu_instr_create(ctx->nir, op);
403b8e80941Smrg
404b8e80941Smrg   uint32_t flags = blob_read_uint32(ctx->blob);
405b8e80941Smrg   alu->exact = flags & 1;
406b8e80941Smrg   alu->dest.saturate = flags & 2;
407b8e80941Smrg   alu->dest.write_mask = flags >> 2;
408b8e80941Smrg
409b8e80941Smrg   read_dest(ctx, &alu->dest.dest, &alu->instr);
410b8e80941Smrg
411b8e80941Smrg   for (unsigned i = 0; i < nir_op_infos[op].num_inputs; i++) {
412b8e80941Smrg      read_src(ctx, &alu->src[i].src, &alu->instr);
413b8e80941Smrg      flags = blob_read_uint32(ctx->blob);
414b8e80941Smrg      alu->src[i].negate = flags & 1;
415b8e80941Smrg      alu->src[i].abs = flags & 2;
416b8e80941Smrg      for (unsigned j = 0; j < 4; j++)
417b8e80941Smrg         alu->src[i].swizzle[j] = (flags >> (2 * j + 2)) & 3;
418b8e80941Smrg   }
419b8e80941Smrg
420b8e80941Smrg   return alu;
421b8e80941Smrg}
422b8e80941Smrg
423b8e80941Smrgstatic void
424b8e80941Smrgwrite_deref(write_ctx *ctx, const nir_deref_instr *deref)
425b8e80941Smrg{
426b8e80941Smrg   blob_write_uint32(ctx->blob, deref->deref_type);
427b8e80941Smrg
428b8e80941Smrg   blob_write_uint32(ctx->blob, deref->mode);
429b8e80941Smrg   encode_type_to_blob(ctx->blob, deref->type);
430b8e80941Smrg
431b8e80941Smrg   write_dest(ctx, &deref->dest);
432b8e80941Smrg
433b8e80941Smrg   if (deref->deref_type == nir_deref_type_var) {
434b8e80941Smrg      write_object(ctx, deref->var);
435b8e80941Smrg      return;
436b8e80941Smrg   }
437b8e80941Smrg
438b8e80941Smrg   write_src(ctx, &deref->parent);
439b8e80941Smrg
440b8e80941Smrg   switch (deref->deref_type) {
441b8e80941Smrg   case nir_deref_type_struct:
442b8e80941Smrg      blob_write_uint32(ctx->blob, deref->strct.index);
443b8e80941Smrg      break;
444b8e80941Smrg
445b8e80941Smrg   case nir_deref_type_array:
446b8e80941Smrg   case nir_deref_type_ptr_as_array:
447b8e80941Smrg      write_src(ctx, &deref->arr.index);
448b8e80941Smrg      break;
449b8e80941Smrg
450b8e80941Smrg   case nir_deref_type_cast:
451b8e80941Smrg      blob_write_uint32(ctx->blob, deref->cast.ptr_stride);
452b8e80941Smrg      break;
453b8e80941Smrg
454b8e80941Smrg   case nir_deref_type_array_wildcard:
455b8e80941Smrg      /* Nothing to do */
456b8e80941Smrg      break;
457b8e80941Smrg
458b8e80941Smrg   default:
459b8e80941Smrg      unreachable("Invalid deref type");
460b8e80941Smrg   }
461b8e80941Smrg}
462b8e80941Smrg
463b8e80941Smrgstatic nir_deref_instr *
464b8e80941Smrgread_deref(read_ctx *ctx)
465b8e80941Smrg{
466b8e80941Smrg   nir_deref_type deref_type = blob_read_uint32(ctx->blob);
467b8e80941Smrg   nir_deref_instr *deref = nir_deref_instr_create(ctx->nir, deref_type);
468b8e80941Smrg
469b8e80941Smrg   deref->mode = blob_read_uint32(ctx->blob);
470b8e80941Smrg   deref->type = decode_type_from_blob(ctx->blob);
471b8e80941Smrg
472b8e80941Smrg   read_dest(ctx, &deref->dest, &deref->instr);
473b8e80941Smrg
474b8e80941Smrg   if (deref_type == nir_deref_type_var) {
475b8e80941Smrg      deref->var = read_object(ctx);
476b8e80941Smrg      return deref;
477b8e80941Smrg   }
478b8e80941Smrg
479b8e80941Smrg   read_src(ctx, &deref->parent, &deref->instr);
480b8e80941Smrg
481b8e80941Smrg   switch (deref->deref_type) {
482b8e80941Smrg   case nir_deref_type_struct:
483b8e80941Smrg      deref->strct.index = blob_read_uint32(ctx->blob);
484b8e80941Smrg      break;
485b8e80941Smrg
486b8e80941Smrg   case nir_deref_type_array:
487b8e80941Smrg   case nir_deref_type_ptr_as_array:
488b8e80941Smrg      read_src(ctx, &deref->arr.index, &deref->instr);
489b8e80941Smrg      break;
490b8e80941Smrg
491b8e80941Smrg   case nir_deref_type_cast:
492b8e80941Smrg      deref->cast.ptr_stride = blob_read_uint32(ctx->blob);
493b8e80941Smrg      break;
494b8e80941Smrg
495b8e80941Smrg   case nir_deref_type_array_wildcard:
496b8e80941Smrg      /* Nothing to do */
497b8e80941Smrg      break;
498b8e80941Smrg
499b8e80941Smrg   default:
500b8e80941Smrg      unreachable("Invalid deref type");
501b8e80941Smrg   }
502b8e80941Smrg
503b8e80941Smrg   return deref;
504b8e80941Smrg}
505b8e80941Smrg
506b8e80941Smrgstatic void
507b8e80941Smrgwrite_intrinsic(write_ctx *ctx, const nir_intrinsic_instr *intrin)
508b8e80941Smrg{
509b8e80941Smrg   blob_write_uint32(ctx->blob, intrin->intrinsic);
510b8e80941Smrg
511b8e80941Smrg   unsigned num_srcs = nir_intrinsic_infos[intrin->intrinsic].num_srcs;
512b8e80941Smrg   unsigned num_indices = nir_intrinsic_infos[intrin->intrinsic].num_indices;
513b8e80941Smrg
514b8e80941Smrg   blob_write_uint32(ctx->blob, intrin->num_components);
515b8e80941Smrg
516b8e80941Smrg   if (nir_intrinsic_infos[intrin->intrinsic].has_dest)
517b8e80941Smrg      write_dest(ctx, &intrin->dest);
518b8e80941Smrg
519b8e80941Smrg   for (unsigned i = 0; i < num_srcs; i++)
520b8e80941Smrg      write_src(ctx, &intrin->src[i]);
521b8e80941Smrg
522b8e80941Smrg   for (unsigned i = 0; i < num_indices; i++)
523b8e80941Smrg      blob_write_uint32(ctx->blob, intrin->const_index[i]);
524b8e80941Smrg}
525b8e80941Smrg
526b8e80941Smrgstatic nir_intrinsic_instr *
527b8e80941Smrgread_intrinsic(read_ctx *ctx)
528b8e80941Smrg{
529b8e80941Smrg   nir_intrinsic_op op = blob_read_uint32(ctx->blob);
530b8e80941Smrg
531b8e80941Smrg   nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(ctx->nir, op);
532b8e80941Smrg
533b8e80941Smrg   unsigned num_srcs = nir_intrinsic_infos[op].num_srcs;
534b8e80941Smrg   unsigned num_indices = nir_intrinsic_infos[op].num_indices;
535b8e80941Smrg
536b8e80941Smrg   intrin->num_components = blob_read_uint32(ctx->blob);
537b8e80941Smrg
538b8e80941Smrg   if (nir_intrinsic_infos[op].has_dest)
539b8e80941Smrg      read_dest(ctx, &intrin->dest, &intrin->instr);
540b8e80941Smrg
541b8e80941Smrg   for (unsigned i = 0; i < num_srcs; i++)
542b8e80941Smrg      read_src(ctx, &intrin->src[i], &intrin->instr);
543b8e80941Smrg
544b8e80941Smrg   for (unsigned i = 0; i < num_indices; i++)
545b8e80941Smrg      intrin->const_index[i] = blob_read_uint32(ctx->blob);
546b8e80941Smrg
547b8e80941Smrg   return intrin;
548b8e80941Smrg}
549b8e80941Smrg
550b8e80941Smrgstatic void
551b8e80941Smrgwrite_load_const(write_ctx *ctx, const nir_load_const_instr *lc)
552b8e80941Smrg{
553b8e80941Smrg   uint32_t val = lc->def.num_components;
554b8e80941Smrg   val |= lc->def.bit_size << 3;
555b8e80941Smrg   blob_write_uint32(ctx->blob, val);
556b8e80941Smrg   blob_write_bytes(ctx->blob, lc->value, sizeof(*lc->value) * lc->def.num_components);
557b8e80941Smrg   write_add_object(ctx, &lc->def);
558b8e80941Smrg}
559b8e80941Smrg
560b8e80941Smrgstatic nir_load_const_instr *
561b8e80941Smrgread_load_const(read_ctx *ctx)
562b8e80941Smrg{
563b8e80941Smrg   uint32_t val = blob_read_uint32(ctx->blob);
564b8e80941Smrg
565b8e80941Smrg   nir_load_const_instr *lc =
566b8e80941Smrg      nir_load_const_instr_create(ctx->nir, val & 0x7, val >> 3);
567b8e80941Smrg
568b8e80941Smrg   blob_copy_bytes(ctx->blob, lc->value, sizeof(*lc->value) * lc->def.num_components);
569b8e80941Smrg   read_add_object(ctx, &lc->def);
570b8e80941Smrg   return lc;
571b8e80941Smrg}
572b8e80941Smrg
573b8e80941Smrgstatic void
574b8e80941Smrgwrite_ssa_undef(write_ctx *ctx, const nir_ssa_undef_instr *undef)
575b8e80941Smrg{
576b8e80941Smrg   uint32_t val = undef->def.num_components;
577b8e80941Smrg   val |= undef->def.bit_size << 3;
578b8e80941Smrg   blob_write_uint32(ctx->blob, val);
579b8e80941Smrg   write_add_object(ctx, &undef->def);
580b8e80941Smrg}
581b8e80941Smrg
582b8e80941Smrgstatic nir_ssa_undef_instr *
583b8e80941Smrgread_ssa_undef(read_ctx *ctx)
584b8e80941Smrg{
585b8e80941Smrg   uint32_t val = blob_read_uint32(ctx->blob);
586b8e80941Smrg
587b8e80941Smrg   nir_ssa_undef_instr *undef =
588b8e80941Smrg      nir_ssa_undef_instr_create(ctx->nir, val & 0x7, val >> 3);
589b8e80941Smrg
590b8e80941Smrg   read_add_object(ctx, &undef->def);
591b8e80941Smrg   return undef;
592b8e80941Smrg}
593b8e80941Smrg
594b8e80941Smrgunion packed_tex_data {
595b8e80941Smrg   uint32_t u32;
596b8e80941Smrg   struct {
597b8e80941Smrg      enum glsl_sampler_dim sampler_dim:4;
598b8e80941Smrg      nir_alu_type dest_type:8;
599b8e80941Smrg      unsigned coord_components:3;
600b8e80941Smrg      unsigned is_array:1;
601b8e80941Smrg      unsigned is_shadow:1;
602b8e80941Smrg      unsigned is_new_style_shadow:1;
603b8e80941Smrg      unsigned component:2;
604b8e80941Smrg      unsigned unused:10; /* Mark unused for valgrind. */
605b8e80941Smrg   } u;
606b8e80941Smrg};
607b8e80941Smrg
608b8e80941Smrgstatic void
609b8e80941Smrgwrite_tex(write_ctx *ctx, const nir_tex_instr *tex)
610b8e80941Smrg{
611b8e80941Smrg   blob_write_uint32(ctx->blob, tex->num_srcs);
612b8e80941Smrg   blob_write_uint32(ctx->blob, tex->op);
613b8e80941Smrg   blob_write_uint32(ctx->blob, tex->texture_index);
614b8e80941Smrg   blob_write_uint32(ctx->blob, tex->texture_array_size);
615b8e80941Smrg   blob_write_uint32(ctx->blob, tex->sampler_index);
616b8e80941Smrg   blob_write_bytes(ctx->blob, tex->tg4_offsets, sizeof(tex->tg4_offsets));
617b8e80941Smrg
618b8e80941Smrg   STATIC_ASSERT(sizeof(union packed_tex_data) == sizeof(uint32_t));
619b8e80941Smrg   union packed_tex_data packed = {
620b8e80941Smrg      .u.sampler_dim = tex->sampler_dim,
621b8e80941Smrg      .u.dest_type = tex->dest_type,
622b8e80941Smrg      .u.coord_components = tex->coord_components,
623b8e80941Smrg      .u.is_array = tex->is_array,
624b8e80941Smrg      .u.is_shadow = tex->is_shadow,
625b8e80941Smrg      .u.is_new_style_shadow = tex->is_new_style_shadow,
626b8e80941Smrg      .u.component = tex->component,
627b8e80941Smrg   };
628b8e80941Smrg   blob_write_uint32(ctx->blob, packed.u32);
629b8e80941Smrg
630b8e80941Smrg   write_dest(ctx, &tex->dest);
631b8e80941Smrg   for (unsigned i = 0; i < tex->num_srcs; i++) {
632b8e80941Smrg      blob_write_uint32(ctx->blob, tex->src[i].src_type);
633b8e80941Smrg      write_src(ctx, &tex->src[i].src);
634b8e80941Smrg   }
635b8e80941Smrg}
636b8e80941Smrg
637b8e80941Smrgstatic nir_tex_instr *
638b8e80941Smrgread_tex(read_ctx *ctx)
639b8e80941Smrg{
640b8e80941Smrg   unsigned num_srcs = blob_read_uint32(ctx->blob);
641b8e80941Smrg   nir_tex_instr *tex = nir_tex_instr_create(ctx->nir, num_srcs);
642b8e80941Smrg
643b8e80941Smrg   tex->op = blob_read_uint32(ctx->blob);
644b8e80941Smrg   tex->texture_index = blob_read_uint32(ctx->blob);
645b8e80941Smrg   tex->texture_array_size = blob_read_uint32(ctx->blob);
646b8e80941Smrg   tex->sampler_index = blob_read_uint32(ctx->blob);
647b8e80941Smrg   blob_copy_bytes(ctx->blob, tex->tg4_offsets, sizeof(tex->tg4_offsets));
648b8e80941Smrg
649b8e80941Smrg   union packed_tex_data packed;
650b8e80941Smrg   packed.u32 = blob_read_uint32(ctx->blob);
651b8e80941Smrg   tex->sampler_dim = packed.u.sampler_dim;
652b8e80941Smrg   tex->dest_type = packed.u.dest_type;
653b8e80941Smrg   tex->coord_components = packed.u.coord_components;
654b8e80941Smrg   tex->is_array = packed.u.is_array;
655b8e80941Smrg   tex->is_shadow = packed.u.is_shadow;
656b8e80941Smrg   tex->is_new_style_shadow = packed.u.is_new_style_shadow;
657b8e80941Smrg   tex->component = packed.u.component;
658b8e80941Smrg
659b8e80941Smrg   read_dest(ctx, &tex->dest, &tex->instr);
660b8e80941Smrg   for (unsigned i = 0; i < tex->num_srcs; i++) {
661b8e80941Smrg      tex->src[i].src_type = blob_read_uint32(ctx->blob);
662b8e80941Smrg      read_src(ctx, &tex->src[i].src, &tex->instr);
663b8e80941Smrg   }
664b8e80941Smrg
665b8e80941Smrg   return tex;
666b8e80941Smrg}
667b8e80941Smrg
668b8e80941Smrgstatic void
669b8e80941Smrgwrite_phi(write_ctx *ctx, const nir_phi_instr *phi)
670b8e80941Smrg{
671b8e80941Smrg   /* Phi nodes are special, since they may reference SSA definitions and
672b8e80941Smrg    * basic blocks that don't exist yet. We leave two empty uintptr_t's here,
673b8e80941Smrg    * and then store enough information so that a later fixup pass can fill
674b8e80941Smrg    * them in correctly.
675b8e80941Smrg    */
676b8e80941Smrg   write_dest(ctx, &phi->dest);
677b8e80941Smrg
678b8e80941Smrg   blob_write_uint32(ctx->blob, exec_list_length(&phi->srcs));
679b8e80941Smrg
680b8e80941Smrg   nir_foreach_phi_src(src, phi) {
681b8e80941Smrg      assert(src->src.is_ssa);
682b8e80941Smrg      size_t blob_offset = blob_reserve_intptr(ctx->blob);
683b8e80941Smrg      MAYBE_UNUSED size_t blob_offset2 = blob_reserve_intptr(ctx->blob);
684b8e80941Smrg      assert(blob_offset + sizeof(uintptr_t) == blob_offset2);
685b8e80941Smrg      write_phi_fixup fixup = {
686b8e80941Smrg         .blob_offset = blob_offset,
687b8e80941Smrg         .src = src->src.ssa,
688b8e80941Smrg         .block = src->pred,
689b8e80941Smrg      };
690b8e80941Smrg      util_dynarray_append(&ctx->phi_fixups, write_phi_fixup, fixup);
691b8e80941Smrg   }
692b8e80941Smrg}
693b8e80941Smrg
694b8e80941Smrgstatic void
695b8e80941Smrgwrite_fixup_phis(write_ctx *ctx)
696b8e80941Smrg{
697b8e80941Smrg   util_dynarray_foreach(&ctx->phi_fixups, write_phi_fixup, fixup) {
698b8e80941Smrg      uintptr_t *blob_ptr = (uintptr_t *)(ctx->blob->data + fixup->blob_offset);
699b8e80941Smrg      blob_ptr[0] = write_lookup_object(ctx, fixup->src);
700b8e80941Smrg      blob_ptr[1] = write_lookup_object(ctx, fixup->block);
701b8e80941Smrg   }
702b8e80941Smrg
703b8e80941Smrg   util_dynarray_clear(&ctx->phi_fixups);
704b8e80941Smrg}
705b8e80941Smrg
706b8e80941Smrgstatic nir_phi_instr *
707b8e80941Smrgread_phi(read_ctx *ctx, nir_block *blk)
708b8e80941Smrg{
709b8e80941Smrg   nir_phi_instr *phi = nir_phi_instr_create(ctx->nir);
710b8e80941Smrg
711b8e80941Smrg   read_dest(ctx, &phi->dest, &phi->instr);
712b8e80941Smrg
713b8e80941Smrg   unsigned num_srcs = blob_read_uint32(ctx->blob);
714b8e80941Smrg
715b8e80941Smrg   /* For similar reasons as before, we just store the index directly into the
716b8e80941Smrg    * pointer, and let a later pass resolve the phi sources.
717b8e80941Smrg    *
718b8e80941Smrg    * In order to ensure that the copied sources (which are just the indices
719b8e80941Smrg    * from the blob for now) don't get inserted into the old shader's use-def
720b8e80941Smrg    * lists, we have to add the phi instruction *before* we set up its
721b8e80941Smrg    * sources.
722b8e80941Smrg    */
723b8e80941Smrg   nir_instr_insert_after_block(blk, &phi->instr);
724b8e80941Smrg
725b8e80941Smrg   for (unsigned i = 0; i < num_srcs; i++) {
726b8e80941Smrg      nir_phi_src *src = ralloc(phi, nir_phi_src);
727b8e80941Smrg
728b8e80941Smrg      src->src.is_ssa = true;
729b8e80941Smrg      src->src.ssa = (nir_ssa_def *) blob_read_intptr(ctx->blob);
730b8e80941Smrg      src->pred = (nir_block *) blob_read_intptr(ctx->blob);
731b8e80941Smrg
732b8e80941Smrg      /* Since we're not letting nir_insert_instr handle use/def stuff for us,
733b8e80941Smrg       * we have to set the parent_instr manually.  It doesn't really matter
734b8e80941Smrg       * when we do it, so we might as well do it here.
735b8e80941Smrg       */
736b8e80941Smrg      src->src.parent_instr = &phi->instr;
737b8e80941Smrg
738b8e80941Smrg      /* Stash it in the list of phi sources.  We'll walk this list and fix up
739b8e80941Smrg       * sources at the very end of read_function_impl.
740b8e80941Smrg       */
741b8e80941Smrg      list_add(&src->src.use_link, &ctx->phi_srcs);
742b8e80941Smrg
743b8e80941Smrg      exec_list_push_tail(&phi->srcs, &src->node);
744b8e80941Smrg   }
745b8e80941Smrg
746b8e80941Smrg   return phi;
747b8e80941Smrg}
748b8e80941Smrg
749b8e80941Smrgstatic void
750b8e80941Smrgread_fixup_phis(read_ctx *ctx)
751b8e80941Smrg{
752b8e80941Smrg   list_for_each_entry_safe(nir_phi_src, src, &ctx->phi_srcs, src.use_link) {
753b8e80941Smrg      src->pred = read_lookup_object(ctx, (uintptr_t)src->pred);
754b8e80941Smrg      src->src.ssa = read_lookup_object(ctx, (uintptr_t)src->src.ssa);
755b8e80941Smrg
756b8e80941Smrg      /* Remove from this list */
757b8e80941Smrg      list_del(&src->src.use_link);
758b8e80941Smrg
759b8e80941Smrg      list_addtail(&src->src.use_link, &src->src.ssa->uses);
760b8e80941Smrg   }
761b8e80941Smrg   assert(list_empty(&ctx->phi_srcs));
762b8e80941Smrg}
763b8e80941Smrg
764b8e80941Smrgstatic void
765b8e80941Smrgwrite_jump(write_ctx *ctx, const nir_jump_instr *jmp)
766b8e80941Smrg{
767b8e80941Smrg   blob_write_uint32(ctx->blob, jmp->type);
768b8e80941Smrg}
769b8e80941Smrg
770b8e80941Smrgstatic nir_jump_instr *
771b8e80941Smrgread_jump(read_ctx *ctx)
772b8e80941Smrg{
773b8e80941Smrg   nir_jump_type type = blob_read_uint32(ctx->blob);
774b8e80941Smrg   nir_jump_instr *jmp = nir_jump_instr_create(ctx->nir, type);
775b8e80941Smrg   return jmp;
776b8e80941Smrg}
777b8e80941Smrg
778b8e80941Smrgstatic void
779b8e80941Smrgwrite_call(write_ctx *ctx, const nir_call_instr *call)
780b8e80941Smrg{
781b8e80941Smrg   blob_write_intptr(ctx->blob, write_lookup_object(ctx, call->callee));
782b8e80941Smrg
783b8e80941Smrg   for (unsigned i = 0; i < call->num_params; i++)
784b8e80941Smrg      write_src(ctx, &call->params[i]);
785b8e80941Smrg}
786b8e80941Smrg
787b8e80941Smrgstatic nir_call_instr *
788b8e80941Smrgread_call(read_ctx *ctx)
789b8e80941Smrg{
790b8e80941Smrg   nir_function *callee = read_object(ctx);
791b8e80941Smrg   nir_call_instr *call = nir_call_instr_create(ctx->nir, callee);
792b8e80941Smrg
793b8e80941Smrg   for (unsigned i = 0; i < call->num_params; i++)
794b8e80941Smrg      read_src(ctx, &call->params[i], call);
795b8e80941Smrg
796b8e80941Smrg   return call;
797b8e80941Smrg}
798b8e80941Smrg
799b8e80941Smrgstatic void
800b8e80941Smrgwrite_instr(write_ctx *ctx, const nir_instr *instr)
801b8e80941Smrg{
802b8e80941Smrg   blob_write_uint32(ctx->blob, instr->type);
803b8e80941Smrg   switch (instr->type) {
804b8e80941Smrg   case nir_instr_type_alu:
805b8e80941Smrg      write_alu(ctx, nir_instr_as_alu(instr));
806b8e80941Smrg      break;
807b8e80941Smrg   case nir_instr_type_deref:
808b8e80941Smrg      write_deref(ctx, nir_instr_as_deref(instr));
809b8e80941Smrg      break;
810b8e80941Smrg   case nir_instr_type_intrinsic:
811b8e80941Smrg      write_intrinsic(ctx, nir_instr_as_intrinsic(instr));
812b8e80941Smrg      break;
813b8e80941Smrg   case nir_instr_type_load_const:
814b8e80941Smrg      write_load_const(ctx, nir_instr_as_load_const(instr));
815b8e80941Smrg      break;
816b8e80941Smrg   case nir_instr_type_ssa_undef:
817b8e80941Smrg      write_ssa_undef(ctx, nir_instr_as_ssa_undef(instr));
818b8e80941Smrg      break;
819b8e80941Smrg   case nir_instr_type_tex:
820b8e80941Smrg      write_tex(ctx, nir_instr_as_tex(instr));
821b8e80941Smrg      break;
822b8e80941Smrg   case nir_instr_type_phi:
823b8e80941Smrg      write_phi(ctx, nir_instr_as_phi(instr));
824b8e80941Smrg      break;
825b8e80941Smrg   case nir_instr_type_jump:
826b8e80941Smrg      write_jump(ctx, nir_instr_as_jump(instr));
827b8e80941Smrg      break;
828b8e80941Smrg   case nir_instr_type_call:
829b8e80941Smrg      write_call(ctx, nir_instr_as_call(instr));
830b8e80941Smrg      break;
831b8e80941Smrg   case nir_instr_type_parallel_copy:
832b8e80941Smrg      unreachable("Cannot write parallel copies");
833b8e80941Smrg   default:
834b8e80941Smrg      unreachable("bad instr type");
835b8e80941Smrg   }
836b8e80941Smrg}
837b8e80941Smrg
838b8e80941Smrgstatic void
839b8e80941Smrgread_instr(read_ctx *ctx, nir_block *block)
840b8e80941Smrg{
841b8e80941Smrg   nir_instr_type type = blob_read_uint32(ctx->blob);
842b8e80941Smrg   nir_instr *instr;
843b8e80941Smrg   switch (type) {
844b8e80941Smrg   case nir_instr_type_alu:
845b8e80941Smrg      instr = &read_alu(ctx)->instr;
846b8e80941Smrg      break;
847b8e80941Smrg   case nir_instr_type_deref:
848b8e80941Smrg      instr = &read_deref(ctx)->instr;
849b8e80941Smrg      break;
850b8e80941Smrg   case nir_instr_type_intrinsic:
851b8e80941Smrg      instr = &read_intrinsic(ctx)->instr;
852b8e80941Smrg      break;
853b8e80941Smrg   case nir_instr_type_load_const:
854b8e80941Smrg      instr = &read_load_const(ctx)->instr;
855b8e80941Smrg      break;
856b8e80941Smrg   case nir_instr_type_ssa_undef:
857b8e80941Smrg      instr = &read_ssa_undef(ctx)->instr;
858b8e80941Smrg      break;
859b8e80941Smrg   case nir_instr_type_tex:
860b8e80941Smrg      instr = &read_tex(ctx)->instr;
861b8e80941Smrg      break;
862b8e80941Smrg   case nir_instr_type_phi:
863b8e80941Smrg      /* Phi instructions are a bit of a special case when reading because we
864b8e80941Smrg       * don't want inserting the instruction to automatically handle use/defs
865b8e80941Smrg       * for us.  Instead, we need to wait until all the blocks/instructions
866b8e80941Smrg       * are read so that we can set their sources up.
867b8e80941Smrg       */
868b8e80941Smrg      read_phi(ctx, block);
869b8e80941Smrg      return;
870b8e80941Smrg   case nir_instr_type_jump:
871b8e80941Smrg      instr = &read_jump(ctx)->instr;
872b8e80941Smrg      break;
873b8e80941Smrg   case nir_instr_type_call:
874b8e80941Smrg      instr = &read_call(ctx)->instr;
875b8e80941Smrg      break;
876b8e80941Smrg   case nir_instr_type_parallel_copy:
877b8e80941Smrg      unreachable("Cannot read parallel copies");
878b8e80941Smrg   default:
879b8e80941Smrg      unreachable("bad instr type");
880b8e80941Smrg   }
881b8e80941Smrg
882b8e80941Smrg   nir_instr_insert_after_block(block, instr);
883b8e80941Smrg}
884b8e80941Smrg
885b8e80941Smrgstatic void
886b8e80941Smrgwrite_block(write_ctx *ctx, const nir_block *block)
887b8e80941Smrg{
888b8e80941Smrg   write_add_object(ctx, block);
889b8e80941Smrg   blob_write_uint32(ctx->blob, exec_list_length(&block->instr_list));
890b8e80941Smrg   nir_foreach_instr(instr, block)
891b8e80941Smrg      write_instr(ctx, instr);
892b8e80941Smrg}
893b8e80941Smrg
894b8e80941Smrgstatic void
895b8e80941Smrgread_block(read_ctx *ctx, struct exec_list *cf_list)
896b8e80941Smrg{
897b8e80941Smrg   /* Don't actually create a new block.  Just use the one from the tail of
898b8e80941Smrg    * the list.  NIR guarantees that the tail of the list is a block and that
899b8e80941Smrg    * no two blocks are side-by-side in the IR;  It should be empty.
900b8e80941Smrg    */
901b8e80941Smrg   nir_block *block =
902b8e80941Smrg      exec_node_data(nir_block, exec_list_get_tail(cf_list), cf_node.node);
903b8e80941Smrg
904b8e80941Smrg   read_add_object(ctx, block);
905b8e80941Smrg   unsigned num_instrs = blob_read_uint32(ctx->blob);
906b8e80941Smrg   for (unsigned i = 0; i < num_instrs; i++) {
907b8e80941Smrg      read_instr(ctx, block);
908b8e80941Smrg   }
909b8e80941Smrg}
910b8e80941Smrg
911b8e80941Smrgstatic void
912b8e80941Smrgwrite_cf_list(write_ctx *ctx, const struct exec_list *cf_list);
913b8e80941Smrg
914b8e80941Smrgstatic void
915b8e80941Smrgread_cf_list(read_ctx *ctx, struct exec_list *cf_list);
916b8e80941Smrg
917b8e80941Smrgstatic void
918b8e80941Smrgwrite_if(write_ctx *ctx, nir_if *nif)
919b8e80941Smrg{
920b8e80941Smrg   write_src(ctx, &nif->condition);
921b8e80941Smrg
922b8e80941Smrg   write_cf_list(ctx, &nif->then_list);
923b8e80941Smrg   write_cf_list(ctx, &nif->else_list);
924b8e80941Smrg}
925b8e80941Smrg
926b8e80941Smrgstatic void
927b8e80941Smrgread_if(read_ctx *ctx, struct exec_list *cf_list)
928b8e80941Smrg{
929b8e80941Smrg   nir_if *nif = nir_if_create(ctx->nir);
930b8e80941Smrg
931b8e80941Smrg   read_src(ctx, &nif->condition, nif);
932b8e80941Smrg
933b8e80941Smrg   nir_cf_node_insert_end(cf_list, &nif->cf_node);
934b8e80941Smrg
935b8e80941Smrg   read_cf_list(ctx, &nif->then_list);
936b8e80941Smrg   read_cf_list(ctx, &nif->else_list);
937b8e80941Smrg}
938b8e80941Smrg
939b8e80941Smrgstatic void
940b8e80941Smrgwrite_loop(write_ctx *ctx, nir_loop *loop)
941b8e80941Smrg{
942b8e80941Smrg   write_cf_list(ctx, &loop->body);
943b8e80941Smrg}
944b8e80941Smrg
945b8e80941Smrgstatic void
946b8e80941Smrgread_loop(read_ctx *ctx, struct exec_list *cf_list)
947b8e80941Smrg{
948b8e80941Smrg   nir_loop *loop = nir_loop_create(ctx->nir);
949b8e80941Smrg
950b8e80941Smrg   nir_cf_node_insert_end(cf_list, &loop->cf_node);
951b8e80941Smrg
952b8e80941Smrg   read_cf_list(ctx, &loop->body);
953b8e80941Smrg}
954b8e80941Smrg
955b8e80941Smrgstatic void
956b8e80941Smrgwrite_cf_node(write_ctx *ctx, nir_cf_node *cf)
957b8e80941Smrg{
958b8e80941Smrg   blob_write_uint32(ctx->blob, cf->type);
959b8e80941Smrg
960b8e80941Smrg   switch (cf->type) {
961b8e80941Smrg   case nir_cf_node_block:
962b8e80941Smrg      write_block(ctx, nir_cf_node_as_block(cf));
963b8e80941Smrg      break;
964b8e80941Smrg   case nir_cf_node_if:
965b8e80941Smrg      write_if(ctx, nir_cf_node_as_if(cf));
966b8e80941Smrg      break;
967b8e80941Smrg   case nir_cf_node_loop:
968b8e80941Smrg      write_loop(ctx, nir_cf_node_as_loop(cf));
969b8e80941Smrg      break;
970b8e80941Smrg   default:
971b8e80941Smrg      unreachable("bad cf type");
972b8e80941Smrg   }
973b8e80941Smrg}
974b8e80941Smrg
975b8e80941Smrgstatic void
976b8e80941Smrgread_cf_node(read_ctx *ctx, struct exec_list *list)
977b8e80941Smrg{
978b8e80941Smrg   nir_cf_node_type type = blob_read_uint32(ctx->blob);
979b8e80941Smrg
980b8e80941Smrg   switch (type) {
981b8e80941Smrg   case nir_cf_node_block:
982b8e80941Smrg      read_block(ctx, list);
983b8e80941Smrg      break;
984b8e80941Smrg   case nir_cf_node_if:
985b8e80941Smrg      read_if(ctx, list);
986b8e80941Smrg      break;
987b8e80941Smrg   case nir_cf_node_loop:
988b8e80941Smrg      read_loop(ctx, list);
989b8e80941Smrg      break;
990b8e80941Smrg   default:
991b8e80941Smrg      unreachable("bad cf type");
992b8e80941Smrg   }
993b8e80941Smrg}
994b8e80941Smrg
995b8e80941Smrgstatic void
996b8e80941Smrgwrite_cf_list(write_ctx *ctx, const struct exec_list *cf_list)
997b8e80941Smrg{
998b8e80941Smrg   blob_write_uint32(ctx->blob, exec_list_length(cf_list));
999b8e80941Smrg   foreach_list_typed(nir_cf_node, cf, node, cf_list) {
1000b8e80941Smrg      write_cf_node(ctx, cf);
1001b8e80941Smrg   }
1002b8e80941Smrg}
1003b8e80941Smrg
1004b8e80941Smrgstatic void
1005b8e80941Smrgread_cf_list(read_ctx *ctx, struct exec_list *cf_list)
1006b8e80941Smrg{
1007b8e80941Smrg   uint32_t num_cf_nodes = blob_read_uint32(ctx->blob);
1008b8e80941Smrg   for (unsigned i = 0; i < num_cf_nodes; i++)
1009b8e80941Smrg      read_cf_node(ctx, cf_list);
1010b8e80941Smrg}
1011b8e80941Smrg
1012b8e80941Smrgstatic void
1013b8e80941Smrgwrite_function_impl(write_ctx *ctx, const nir_function_impl *fi)
1014b8e80941Smrg{
1015b8e80941Smrg   write_var_list(ctx, &fi->locals);
1016b8e80941Smrg   write_reg_list(ctx, &fi->registers);
1017b8e80941Smrg   blob_write_uint32(ctx->blob, fi->reg_alloc);
1018b8e80941Smrg
1019b8e80941Smrg   write_cf_list(ctx, &fi->body);
1020b8e80941Smrg   write_fixup_phis(ctx);
1021b8e80941Smrg}
1022b8e80941Smrg
1023b8e80941Smrgstatic nir_function_impl *
1024b8e80941Smrgread_function_impl(read_ctx *ctx, nir_function *fxn)
1025b8e80941Smrg{
1026b8e80941Smrg   nir_function_impl *fi = nir_function_impl_create_bare(ctx->nir);
1027b8e80941Smrg   fi->function = fxn;
1028b8e80941Smrg
1029b8e80941Smrg   read_var_list(ctx, &fi->locals);
1030b8e80941Smrg   read_reg_list(ctx, &fi->registers);
1031b8e80941Smrg   fi->reg_alloc = blob_read_uint32(ctx->blob);
1032b8e80941Smrg
1033b8e80941Smrg   read_cf_list(ctx, &fi->body);
1034b8e80941Smrg   read_fixup_phis(ctx);
1035b8e80941Smrg
1036b8e80941Smrg   fi->valid_metadata = 0;
1037b8e80941Smrg
1038b8e80941Smrg   return fi;
1039b8e80941Smrg}
1040b8e80941Smrg
1041b8e80941Smrgstatic void
1042b8e80941Smrgwrite_function(write_ctx *ctx, const nir_function *fxn)
1043b8e80941Smrg{
1044b8e80941Smrg   blob_write_uint32(ctx->blob, !!(fxn->name));
1045b8e80941Smrg   if (fxn->name)
1046b8e80941Smrg      blob_write_string(ctx->blob, fxn->name);
1047b8e80941Smrg
1048b8e80941Smrg   write_add_object(ctx, fxn);
1049b8e80941Smrg
1050b8e80941Smrg   blob_write_uint32(ctx->blob, fxn->num_params);
1051b8e80941Smrg   for (unsigned i = 0; i < fxn->num_params; i++) {
1052b8e80941Smrg      uint32_t val =
1053b8e80941Smrg         ((uint32_t)fxn->params[i].num_components) |
1054b8e80941Smrg         ((uint32_t)fxn->params[i].bit_size) << 8;
1055b8e80941Smrg      blob_write_uint32(ctx->blob, val);
1056b8e80941Smrg   }
1057b8e80941Smrg
1058b8e80941Smrg   blob_write_uint32(ctx->blob, fxn->is_entrypoint);
1059b8e80941Smrg
1060b8e80941Smrg   /* At first glance, it looks like we should write the function_impl here.
1061b8e80941Smrg    * However, call instructions need to be able to reference at least the
1062b8e80941Smrg    * function and those will get processed as we write the function_impls.
1063b8e80941Smrg    * We stop here and write function_impls as a second pass.
1064b8e80941Smrg    */
1065b8e80941Smrg}
1066b8e80941Smrg
1067b8e80941Smrgstatic void
1068b8e80941Smrgread_function(read_ctx *ctx)
1069b8e80941Smrg{
1070b8e80941Smrg   bool has_name = blob_read_uint32(ctx->blob);
1071b8e80941Smrg   char *name = has_name ? blob_read_string(ctx->blob) : NULL;
1072b8e80941Smrg
1073b8e80941Smrg   nir_function *fxn = nir_function_create(ctx->nir, name);
1074b8e80941Smrg
1075b8e80941Smrg   read_add_object(ctx, fxn);
1076b8e80941Smrg
1077b8e80941Smrg   fxn->num_params = blob_read_uint32(ctx->blob);
1078b8e80941Smrg   fxn->params = ralloc_array(fxn, nir_parameter, fxn->num_params);
1079b8e80941Smrg   for (unsigned i = 0; i < fxn->num_params; i++) {
1080b8e80941Smrg      uint32_t val = blob_read_uint32(ctx->blob);
1081b8e80941Smrg      fxn->params[i].num_components = val & 0xff;
1082b8e80941Smrg      fxn->params[i].bit_size = (val >> 8) & 0xff;
1083b8e80941Smrg   }
1084b8e80941Smrg
1085b8e80941Smrg   fxn->is_entrypoint = blob_read_uint32(ctx->blob);
1086b8e80941Smrg}
1087b8e80941Smrg
1088b8e80941Smrgvoid
1089b8e80941Smrgnir_serialize(struct blob *blob, const nir_shader *nir)
1090b8e80941Smrg{
1091b8e80941Smrg   write_ctx ctx;
1092b8e80941Smrg   ctx.remap_table = _mesa_pointer_hash_table_create(NULL);
1093b8e80941Smrg   ctx.next_idx = 0;
1094b8e80941Smrg   ctx.blob = blob;
1095b8e80941Smrg   ctx.nir = nir;
1096b8e80941Smrg   util_dynarray_init(&ctx.phi_fixups, NULL);
1097b8e80941Smrg
1098b8e80941Smrg   size_t idx_size_offset = blob_reserve_intptr(blob);
1099b8e80941Smrg
1100b8e80941Smrg   struct shader_info info = nir->info;
1101b8e80941Smrg   uint32_t strings = 0;
1102b8e80941Smrg   if (info.name)
1103b8e80941Smrg      strings |= 0x1;
1104b8e80941Smrg   if (info.label)
1105b8e80941Smrg      strings |= 0x2;
1106b8e80941Smrg   blob_write_uint32(blob, strings);
1107b8e80941Smrg   if (info.name)
1108b8e80941Smrg      blob_write_string(blob, info.name);
1109b8e80941Smrg   if (info.label)
1110b8e80941Smrg      blob_write_string(blob, info.label);
1111b8e80941Smrg   info.name = info.label = NULL;
1112b8e80941Smrg   blob_write_bytes(blob, (uint8_t *) &info, sizeof(info));
1113b8e80941Smrg
1114b8e80941Smrg   write_var_list(&ctx, &nir->uniforms);
1115b8e80941Smrg   write_var_list(&ctx, &nir->inputs);
1116b8e80941Smrg   write_var_list(&ctx, &nir->outputs);
1117b8e80941Smrg   write_var_list(&ctx, &nir->shared);
1118b8e80941Smrg   write_var_list(&ctx, &nir->globals);
1119b8e80941Smrg   write_var_list(&ctx, &nir->system_values);
1120b8e80941Smrg
1121b8e80941Smrg   blob_write_uint32(blob, nir->num_inputs);
1122b8e80941Smrg   blob_write_uint32(blob, nir->num_uniforms);
1123b8e80941Smrg   blob_write_uint32(blob, nir->num_outputs);
1124b8e80941Smrg   blob_write_uint32(blob, nir->num_shared);
1125b8e80941Smrg   blob_write_uint32(blob, nir->scratch_size);
1126b8e80941Smrg
1127b8e80941Smrg   blob_write_uint32(blob, exec_list_length(&nir->functions));
1128b8e80941Smrg   nir_foreach_function(fxn, nir) {
1129b8e80941Smrg      write_function(&ctx, fxn);
1130b8e80941Smrg   }
1131b8e80941Smrg
1132b8e80941Smrg   nir_foreach_function(fxn, nir) {
1133b8e80941Smrg      write_function_impl(&ctx, fxn->impl);
1134b8e80941Smrg   }
1135b8e80941Smrg
1136b8e80941Smrg   blob_write_uint32(blob, nir->constant_data_size);
1137b8e80941Smrg   if (nir->constant_data_size > 0)
1138b8e80941Smrg      blob_write_bytes(blob, nir->constant_data, nir->constant_data_size);
1139b8e80941Smrg
1140b8e80941Smrg   *(uintptr_t *)(blob->data + idx_size_offset) = ctx.next_idx;
1141b8e80941Smrg
1142b8e80941Smrg   _mesa_hash_table_destroy(ctx.remap_table, NULL);
1143b8e80941Smrg   util_dynarray_fini(&ctx.phi_fixups);
1144b8e80941Smrg}
1145b8e80941Smrg
1146b8e80941Smrgnir_shader *
1147b8e80941Smrgnir_deserialize(void *mem_ctx,
1148b8e80941Smrg                const struct nir_shader_compiler_options *options,
1149b8e80941Smrg                struct blob_reader *blob)
1150b8e80941Smrg{
1151b8e80941Smrg   read_ctx ctx;
1152b8e80941Smrg   ctx.blob = blob;
1153b8e80941Smrg   list_inithead(&ctx.phi_srcs);
1154b8e80941Smrg   ctx.idx_table_len = blob_read_intptr(blob);
1155b8e80941Smrg   ctx.idx_table = calloc(ctx.idx_table_len, sizeof(uintptr_t));
1156b8e80941Smrg   ctx.next_idx = 0;
1157b8e80941Smrg
1158b8e80941Smrg   uint32_t strings = blob_read_uint32(blob);
1159b8e80941Smrg   char *name = (strings & 0x1) ? blob_read_string(blob) : NULL;
1160b8e80941Smrg   char *label = (strings & 0x2) ? blob_read_string(blob) : NULL;
1161b8e80941Smrg
1162b8e80941Smrg   struct shader_info info;
1163b8e80941Smrg   blob_copy_bytes(blob, (uint8_t *) &info, sizeof(info));
1164b8e80941Smrg
1165b8e80941Smrg   ctx.nir = nir_shader_create(mem_ctx, info.stage, options, NULL);
1166b8e80941Smrg
1167b8e80941Smrg   info.name = name ? ralloc_strdup(ctx.nir, name) : NULL;
1168b8e80941Smrg   info.label = label ? ralloc_strdup(ctx.nir, label) : NULL;
1169b8e80941Smrg
1170b8e80941Smrg   ctx.nir->info = info;
1171b8e80941Smrg
1172b8e80941Smrg   read_var_list(&ctx, &ctx.nir->uniforms);
1173b8e80941Smrg   read_var_list(&ctx, &ctx.nir->inputs);
1174b8e80941Smrg   read_var_list(&ctx, &ctx.nir->outputs);
1175b8e80941Smrg   read_var_list(&ctx, &ctx.nir->shared);
1176b8e80941Smrg   read_var_list(&ctx, &ctx.nir->globals);
1177b8e80941Smrg   read_var_list(&ctx, &ctx.nir->system_values);
1178b8e80941Smrg
1179b8e80941Smrg   ctx.nir->num_inputs = blob_read_uint32(blob);
1180b8e80941Smrg   ctx.nir->num_uniforms = blob_read_uint32(blob);
1181b8e80941Smrg   ctx.nir->num_outputs = blob_read_uint32(blob);
1182b8e80941Smrg   ctx.nir->num_shared = blob_read_uint32(blob);
1183b8e80941Smrg   ctx.nir->scratch_size = blob_read_uint32(blob);
1184b8e80941Smrg
1185b8e80941Smrg   unsigned num_functions = blob_read_uint32(blob);
1186b8e80941Smrg   for (unsigned i = 0; i < num_functions; i++)
1187b8e80941Smrg      read_function(&ctx);
1188b8e80941Smrg
1189b8e80941Smrg   nir_foreach_function(fxn, ctx.nir)
1190b8e80941Smrg      fxn->impl = read_function_impl(&ctx, fxn);
1191b8e80941Smrg
1192b8e80941Smrg   ctx.nir->constant_data_size = blob_read_uint32(blob);
1193b8e80941Smrg   if (ctx.nir->constant_data_size > 0) {
1194b8e80941Smrg      ctx.nir->constant_data =
1195b8e80941Smrg         ralloc_size(ctx.nir, ctx.nir->constant_data_size);
1196b8e80941Smrg      blob_copy_bytes(blob, ctx.nir->constant_data,
1197b8e80941Smrg                      ctx.nir->constant_data_size);
1198b8e80941Smrg   }
1199b8e80941Smrg
1200b8e80941Smrg   free(ctx.idx_table);
1201b8e80941Smrg
1202b8e80941Smrg   return ctx.nir;
1203b8e80941Smrg}
1204b8e80941Smrg
1205b8e80941Smrgnir_shader *
1206b8e80941Smrgnir_shader_serialize_deserialize(void *mem_ctx, nir_shader *s)
1207b8e80941Smrg{
1208b8e80941Smrg   const struct nir_shader_compiler_options *options = s->options;
1209b8e80941Smrg
1210b8e80941Smrg   struct blob writer;
1211b8e80941Smrg   blob_init(&writer);
1212b8e80941Smrg   nir_serialize(&writer, s);
1213b8e80941Smrg   ralloc_free(s);
1214b8e80941Smrg
1215b8e80941Smrg   struct blob_reader reader;
1216b8e80941Smrg   blob_reader_init(&reader, writer.data, writer.size);
1217b8e80941Smrg   nir_shader *ns = nir_deserialize(mem_ctx, options, &reader);
1218b8e80941Smrg
1219b8e80941Smrg   blob_finish(&writer);
1220b8e80941Smrg
1221b8e80941Smrg   return ns;
1222b8e80941Smrg}
1223