• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © Microsoft Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "dxil_module.h"
25 #include "dxil_internal.h"
26 
27 #include "util/macros.h"
28 #include "util/u_math.h"
29 #include "util/u_memory.h"
30 #include "util/rb_tree.h"
31 
32 #include <assert.h>
33 #include <stdio.h>
34 
35 void
dxil_module_init(struct dxil_module * m,void * ralloc_ctx)36 dxil_module_init(struct dxil_module *m, void *ralloc_ctx)
37 {
38    assert(ralloc_ctx);
39 
40    memset(m, 0, sizeof(struct dxil_module));
41    m->ralloc_ctx = ralloc_ctx;
42 
43    dxil_buffer_init(&m->buf, 2);
44    memset(&m->feats, 0, sizeof(m->feats));
45 
46    list_inithead(&m->type_list);
47    list_inithead(&m->func_list);
48    list_inithead(&m->func_def_list);
49    list_inithead(&m->attr_set_list);
50    list_inithead(&m->gvar_list);
51    list_inithead(&m->const_list);
52    list_inithead(&m->mdnode_list);
53    list_inithead(&m->md_named_node_list);
54 
55    m->functions = rzalloc(ralloc_ctx, struct rb_tree);
56    rb_tree_init(m->functions);
57 }
58 
59 void
dxil_module_release(struct dxil_module * m)60 dxil_module_release(struct dxil_module *m)
61 {
62    dxil_buffer_finish(&m->buf);
63 }
64 
65 static bool
emit_bits64(struct dxil_buffer * b,uint64_t data,unsigned width)66 emit_bits64(struct dxil_buffer *b, uint64_t data, unsigned width)
67 {
68    if (data > UINT32_MAX) {
69       assert(width > 32);
70       return dxil_buffer_emit_bits(b, (uint32_t)(data & UINT32_MAX), width) &&
71              dxil_buffer_emit_bits(b, (uint32_t)(data >> 32), width - 32);
72    } else
73       return dxil_buffer_emit_bits(b, (uint32_t)data, width);
74 }
75 
76 /* See the LLVM documentation for details about what these are all about:
77  * https://www.llvm.org/docs/BitCodeFormat.html#abbreviation-ids
78  */
79 enum dxil_fixed_abbrev {
80    DXIL_END_BLOCK = 0,
81    DXIL_ENTER_SUBBLOCK = 1,
82    DXIL_DEFINE_ABBREV = 2,
83    DXIL_UNABBREV_RECORD = 3,
84    DXIL_FIRST_APPLICATION_ABBREV = 4
85 };
86 
87 static bool
enter_subblock(struct dxil_module * m,unsigned id,unsigned abbrev_width)88 enter_subblock(struct dxil_module *m, unsigned id, unsigned abbrev_width)
89 {
90    assert(m->num_blocks < ARRAY_SIZE(m->blocks));
91    m->blocks[m->num_blocks].abbrev_width = m->buf.abbrev_width;
92 
93    if (!dxil_buffer_emit_abbrev_id(&m->buf, DXIL_ENTER_SUBBLOCK) ||
94        !dxil_buffer_emit_vbr_bits(&m->buf, id, 8) ||
95        !dxil_buffer_emit_vbr_bits(&m->buf, abbrev_width, 4) ||
96        !dxil_buffer_align(&m->buf))
97       return false;
98 
99    m->buf.abbrev_width = abbrev_width;
100    m->blocks[m->num_blocks++].offset = blob_reserve_uint32(&m->buf.blob);
101    return true;
102 }
103 
104 static bool
exit_block(struct dxil_module * m)105 exit_block(struct dxil_module *m)
106 {
107    assert(m->num_blocks > 0);
108    assert(m->num_blocks < ARRAY_SIZE(m->blocks));
109 
110    if (!dxil_buffer_emit_abbrev_id(&m->buf, DXIL_END_BLOCK) ||
111        !dxil_buffer_align(&m->buf))
112       return false;
113 
114    intptr_t size_offset = m->blocks[m->num_blocks - 1].offset;
115    uint32_t size = (m->buf.blob.size - size_offset - 1) / sizeof(uint32_t);
116    if (!blob_overwrite_uint32(&m->buf.blob, size_offset, size))
117       return false;
118 
119    m->num_blocks--;
120    m->buf.abbrev_width = m->blocks[m->num_blocks].abbrev_width;
121    return true;
122 }
123 
124 static bool
emit_record_no_abbrev(struct dxil_buffer * b,unsigned code,const uint64_t * data,size_t size)125 emit_record_no_abbrev(struct dxil_buffer *b, unsigned code,
126                       const uint64_t *data, size_t size)
127 {
128    if (!dxil_buffer_emit_abbrev_id(b, DXIL_UNABBREV_RECORD) ||
129        !dxil_buffer_emit_vbr_bits(b, code, 6) ||
130        !dxil_buffer_emit_vbr_bits(b, size, 6))
131       return false;
132 
133    for (size_t i = 0; i < size; ++i)
134       if (!dxil_buffer_emit_vbr_bits(b, data[i], 6))
135          return false;
136 
137    return true;
138 }
139 
140 static bool
emit_record(struct dxil_module * m,unsigned code,const uint64_t * data,size_t size)141 emit_record(struct dxil_module *m, unsigned code,
142             const uint64_t *data, size_t size)
143 {
144    return emit_record_no_abbrev(&m->buf, code, data, size);
145 }
146 
147 static bool
emit_record_int(struct dxil_module * m,unsigned code,int value)148 emit_record_int(struct dxil_module *m, unsigned code, int value)
149 {
150    uint64_t data = value;
151    return emit_record(m, code, &data, 1);
152 }
153 
154 static bool
is_char6(char ch)155 is_char6(char ch)
156 {
157    if ((ch >= 'a' && ch <= 'z') ||
158        (ch >= 'A' && ch <= 'Z') ||
159        (ch >= '0' && ch <= '9'))
160      return true;
161 
162    switch (ch) {
163    case '.':
164    case '_':
165       return true;
166 
167    default:
168       return false;
169    }
170 }
171 
172 static bool
is_char6_string(const char * str)173 is_char6_string(const char *str)
174 {
175    while (*str != '\0') {
176       if (!is_char6(*str++))
177          return false;
178    }
179    return true;
180 }
181 
182 static bool
is_char7_string(const char * str)183 is_char7_string(const char *str)
184 {
185    while (*str != '\0') {
186       if (*str++ & 0x80)
187          return false;
188    }
189    return true;
190 }
191 
192 static unsigned
encode_char6(char ch)193 encode_char6(char ch)
194 {
195    const int letters = 'z' - 'a' + 1;
196 
197    if (ch >= 'a' && ch <= 'z')
198       return ch - 'a';
199    else if (ch >= 'A' && ch <= 'Z')
200       return letters + ch - 'A';
201    else if (ch >= '0' && ch <= '9')
202       return 2 * letters + ch - '0';
203 
204    switch (ch) {
205    case '.': return 62;
206    case '_': return 63;
207    default:
208       unreachable("invalid char6-character");
209    }
210 }
211 
212 static bool
emit_fixed(struct dxil_buffer * b,uint64_t data,unsigned width)213 emit_fixed(struct dxil_buffer *b, uint64_t data, unsigned width)
214 {
215    if (!width)
216       return true;
217 
218    return emit_bits64(b, data, width);
219 }
220 
221 static bool
emit_vbr(struct dxil_buffer * b,uint64_t data,unsigned width)222 emit_vbr(struct dxil_buffer *b, uint64_t data, unsigned width)
223 {
224    if (!width)
225       return true;
226 
227    return dxil_buffer_emit_vbr_bits(b, data, width);
228 }
229 
230 static bool
emit_char6(struct dxil_buffer * b,uint64_t data)231 emit_char6(struct dxil_buffer *b, uint64_t data)
232 {
233    return dxil_buffer_emit_bits(b, encode_char6((char)data), 6);
234 }
235 
236 struct dxil_abbrev {
237    struct {
238       enum {
239          DXIL_OP_LITERAL = 0,
240          DXIL_OP_FIXED = 1,
241          DXIL_OP_VBR = 2,
242          DXIL_OP_ARRAY = 3,
243          DXIL_OP_CHAR6 = 4,
244          DXIL_OP_BLOB = 5
245       } type;
246       union {
247          uint64_t value;
248          uint64_t encoding_data;
249       };
250    } operands[7];
251    size_t num_operands;
252 };
253 
254 static bool
emit_record_abbrev(struct dxil_buffer * b,unsigned abbrev,const struct dxil_abbrev * a,const uint64_t * data,size_t size)255 emit_record_abbrev(struct dxil_buffer *b,
256                    unsigned abbrev, const struct dxil_abbrev *a,
257                    const uint64_t *data, size_t size)
258 {
259    assert(abbrev >= DXIL_FIRST_APPLICATION_ABBREV);
260 
261    if (!dxil_buffer_emit_abbrev_id(b, abbrev))
262       return false;
263 
264    size_t curr_data = 0;
265    for (int i = 0; i < a->num_operands; ++i) {
266       switch (a->operands[i].type) {
267       case DXIL_OP_LITERAL:
268          assert(curr_data < size);
269          assert(data[curr_data] == a->operands[i].value);
270          curr_data++;
271          /* literals are no-ops, because their value is defined in the
272             abbrev-definition already */
273          break;
274 
275       case DXIL_OP_FIXED:
276          assert(curr_data < size);
277          if (!emit_fixed(b, data[curr_data++], a->operands[i].encoding_data))
278             return false;
279          break;
280 
281       case DXIL_OP_VBR:
282          assert(curr_data < size);
283          if (!emit_vbr(b, data[curr_data++], a->operands[i].encoding_data))
284             return false;
285          break;
286 
287       case DXIL_OP_ARRAY:
288          assert(i == a->num_operands - 2); /* arrays should always be second to last */
289 
290          if (!dxil_buffer_emit_vbr_bits(b, size - curr_data, 6))
291             return false;
292 
293          switch (a->operands[i + 1].type) {
294          case DXIL_OP_FIXED:
295             while (curr_data < size)
296                if (!emit_fixed(b, data[curr_data++], a->operands[i + 1].encoding_data))
297                   return false;
298             break;
299 
300          case DXIL_OP_VBR:
301             while (curr_data < size)
302                if (!emit_vbr(b, data[curr_data++], a->operands[i + 1].encoding_data))
303                   return false;
304             break;
305 
306          case DXIL_OP_CHAR6:
307             while (curr_data < size)
308                if (!emit_char6(b, data[curr_data++]))
309                   return false;
310             break;
311 
312          default:
313             unreachable("unexpected operand type");
314          }
315          return true; /* we're done */
316 
317       case DXIL_OP_CHAR6:
318          assert(curr_data < size);
319          if (!emit_char6(b, data[curr_data++]))
320             return false;
321          break;
322 
323       case DXIL_OP_BLOB:
324          unreachable("HALP, unplement!");
325 
326       default:
327          unreachable("unexpected operand type");
328       }
329    }
330 
331    assert(curr_data == size);
332    return true;
333 }
334 
335 
336 static struct dxil_type *
create_type(struct dxil_module * m,enum type_type type)337 create_type(struct dxil_module *m, enum type_type type)
338 {
339    struct dxil_type *ret = rzalloc_size(m->ralloc_ctx,
340                                         sizeof(struct dxil_type));
341    if (ret) {
342       ret->type = type;
343       ret->id = list_length(&m->type_list);
344       list_addtail(&ret->head, &m->type_list);
345    }
346    return ret;
347 }
348 
349 static bool
350 types_equal(const struct dxil_type *lhs, const struct dxil_type *rhs);
351 
352 static bool
type_list_equal(const struct dxil_type_list * lhs,const struct dxil_type_list * rhs)353 type_list_equal(const struct dxil_type_list *lhs,
354                 const struct dxil_type_list *rhs)
355 {
356    if (lhs->num_types != rhs->num_types)
357       return false;
358    for (unsigned i = 0; i < lhs->num_types; ++i)
359       if (!types_equal(lhs->types[i],  rhs->types[i]))
360           return false;
361    return true;
362 }
363 
364 static bool
types_equal(const struct dxil_type * lhs,const struct dxil_type * rhs)365 types_equal(const struct dxil_type *lhs, const struct dxil_type *rhs)
366 {
367    if (lhs == rhs)
368       return true;
369 
370    /* Below we only assert that different type pointers really define different types
371     * Since this function is only called in asserts, it is not needed to put the code
372     * into a #ifdef NDEBUG statement */
373    if (lhs->type != rhs->type)
374       return false;
375 
376    bool retval = false;
377    switch (lhs->type) {
378    case TYPE_VOID:
379       retval = true;
380       break;
381    case TYPE_FLOAT:
382       retval = lhs->float_bits == rhs->float_bits;
383       break;
384    case TYPE_INTEGER:
385       retval = lhs->int_bits == rhs->int_bits;
386       break;
387    case TYPE_POINTER:
388       retval = types_equal(lhs->ptr_target_type, rhs->ptr_target_type);
389       break;
390    case TYPE_ARRAY:
391    case TYPE_VECTOR:
392       retval = (lhs->array_or_vector_def.num_elems == rhs->array_or_vector_def.num_elems) &&
393                types_equal(lhs->array_or_vector_def.elem_type,
394                            rhs->array_or_vector_def.elem_type);
395       break;
396    case TYPE_FUNCTION:
397       if (!types_equal(lhs->function_def.ret_type,
398                             rhs->function_def.ret_type))
399          return false;
400       retval = type_list_equal(&lhs->function_def.args, &rhs->function_def.args);
401       break;
402    case TYPE_STRUCT:
403       retval = type_list_equal(&lhs->struct_def.elem, &rhs->struct_def.elem);
404    }
405    assert(!retval && "Types are equal in structure but not as pointers");
406    return retval;
407 }
408 
409 bool
dxil_value_type_equal_to(const struct dxil_value * value,const struct dxil_type * rhs)410 dxil_value_type_equal_to(const struct dxil_value *value,
411                          const struct dxil_type *rhs)
412 {
413    return types_equal(value->type, rhs);
414 }
415 
416 nir_alu_type
dxil_type_to_nir_type(const struct dxil_type * type)417 dxil_type_to_nir_type(const struct dxil_type *type)
418 {
419    assert(type);
420    switch (type->type) {
421    case TYPE_INTEGER:
422       return type->int_bits == 1 ? nir_type_bool : nir_type_int;
423    case TYPE_FLOAT:
424       return nir_type_float;
425    default:
426       unreachable("Unexpected type in dxil_type_to_nir_type");
427    }
428 }
429 
430 bool
dxil_value_type_bitsize_equal_to(const struct dxil_value * value,unsigned bitsize)431 dxil_value_type_bitsize_equal_to(const struct dxil_value *value, unsigned bitsize)
432 {
433    switch (value->type->type) {
434    case TYPE_INTEGER:
435       return value->type->int_bits == bitsize;
436    case TYPE_FLOAT:
437       return value->type->float_bits == bitsize;
438    default:
439       return false;
440    }
441 }
442 
443 const struct dxil_type *
dxil_value_get_type(const struct dxil_value * value)444 dxil_value_get_type(const struct dxil_value *value)
445 {
446    return value->type;
447 }
448 
449 const struct dxil_type *
dxil_module_get_void_type(struct dxil_module * m)450 dxil_module_get_void_type(struct dxil_module *m)
451 {
452    if (!m->void_type)
453       m->void_type = create_type(m, TYPE_VOID);
454    return m->void_type;
455 }
456 
457 static const struct dxil_type *
create_int_type(struct dxil_module * m,unsigned bit_size)458 create_int_type(struct dxil_module *m, unsigned bit_size)
459 {
460    struct dxil_type *type = create_type(m, TYPE_INTEGER);
461    if (type)
462       type->int_bits = bit_size;
463    return type;
464 }
465 
466 static const struct dxil_type *
get_int1_type(struct dxil_module * m)467 get_int1_type(struct dxil_module *m)
468 {
469    if (!m->int1_type)
470       m->int1_type = create_int_type(m, 1);
471    return m->int1_type;
472 }
473 
474 static const struct dxil_type *
get_int8_type(struct dxil_module * m)475 get_int8_type(struct dxil_module *m)
476 {
477    if (!m->int8_type)
478       m->int8_type = create_int_type(m, 8);
479    return m->int8_type;
480 }
481 
482 static const struct dxil_type *
get_int16_type(struct dxil_module * m)483 get_int16_type(struct dxil_module *m)
484 {
485    if (!m->int16_type)
486       m->int16_type = create_int_type(m, 16);
487    return m->int16_type;
488 }
489 
490 static const struct dxil_type *
get_int32_type(struct dxil_module * m)491 get_int32_type(struct dxil_module *m)
492 {
493    if (!m->int32_type)
494       m->int32_type = create_int_type(m, 32);
495    return m->int32_type;
496 }
497 
498 static const struct dxil_type *
get_int64_type(struct dxil_module * m)499 get_int64_type(struct dxil_module *m)
500 {
501    if (!m->int64_type)
502       m->int64_type = create_int_type(m, 64);
503    return m->int64_type;
504 }
505 
506 static const struct dxil_type *
create_float_type(struct dxil_module * m,unsigned bit_size)507 create_float_type(struct dxil_module *m, unsigned bit_size)
508 {
509    struct dxil_type *type = create_type(m, TYPE_FLOAT);
510    if (type)
511       type->float_bits = bit_size;
512    return type;
513 }
514 
515 const struct dxil_type *
dxil_module_get_int_type(struct dxil_module * m,unsigned bit_size)516 dxil_module_get_int_type(struct dxil_module *m, unsigned bit_size)
517 {
518    switch (bit_size) {
519    case 1: return get_int1_type(m);
520    case 8: return get_int8_type(m);
521    case 16: return get_int16_type(m);
522    case 32: return get_int32_type(m);
523    case 64: return get_int64_type(m);
524    default:
525       unreachable("unsupported bit-width");
526    }
527 }
528 
529 static const struct dxil_type *
get_float16_type(struct dxil_module * m)530 get_float16_type(struct dxil_module *m)
531 {
532    if (!m->float16_type)
533       m->float16_type = create_float_type(m, 16);
534    return m->float16_type;
535 }
536 
537 static const struct dxil_type *
get_float32_type(struct dxil_module * m)538 get_float32_type(struct dxil_module *m)
539 {
540    if (!m->float32_type)
541       m->float32_type = create_float_type(m, 32);
542    return m->float32_type;
543 }
544 
545 static const struct dxil_type *
get_float64_type(struct dxil_module * m)546 get_float64_type(struct dxil_module *m)
547 {
548    if (!m->float64_type)
549       m->float64_type = create_float_type(m, 64);
550    return m->float64_type;
551 }
552 
553 const struct dxil_type *
dxil_module_get_float_type(struct dxil_module * m,unsigned bit_size)554 dxil_module_get_float_type(struct dxil_module *m, unsigned bit_size)
555 {
556    switch (bit_size) {
557    case 16: return get_float16_type(m);
558    case 32: return get_float32_type(m);
559    case 64: return get_float64_type(m);
560    default:
561       unreachable("unsupported bit-width");
562    }
563    return get_float32_type(m);
564 }
565 
566 const struct dxil_type *
dxil_module_get_pointer_type(struct dxil_module * m,const struct dxil_type * target)567 dxil_module_get_pointer_type(struct dxil_module *m,
568                              const struct dxil_type *target)
569 {
570    struct dxil_type *type;
571    LIST_FOR_EACH_ENTRY(type, &m->type_list, head) {
572       if (type->type == TYPE_POINTER &&
573           type->ptr_target_type == target)
574          return type;
575    }
576 
577    type = create_type(m, TYPE_POINTER);
578    if (type)
579       type->ptr_target_type = target;
580    return type;
581 }
582 
583 const struct dxil_type *
dxil_module_get_struct_type(struct dxil_module * m,const char * name,const struct dxil_type ** elem_types,size_t num_elem_types)584 dxil_module_get_struct_type(struct dxil_module *m,
585                             const char *name,
586                             const struct dxil_type **elem_types,
587                             size_t num_elem_types)
588 {
589    assert(!name || strlen(name) > 0);
590 
591    struct dxil_type *type;
592    LIST_FOR_EACH_ENTRY(type, &m->type_list, head) {
593       if (type->type != TYPE_STRUCT)
594          continue;
595 
596       if ((name == NULL) != (type->struct_def.name == NULL))
597          continue;
598 
599       if (name && strcmp(type->struct_def.name, name))
600          continue;
601 
602       if (type->struct_def.elem.num_types == num_elem_types &&
603           !memcmp(type->struct_def.elem.types, elem_types,
604                   sizeof(struct dxil_type *) * num_elem_types))
605          return type;
606    }
607 
608    type = create_type(m, TYPE_STRUCT);
609    if (type) {
610       if (name) {
611          type->struct_def.name = ralloc_strdup(type, name);
612          if (!type->struct_def.name)
613             return NULL;
614       } else
615          type->struct_def.name = NULL;
616 
617       type->struct_def.elem.types = ralloc_array(type, struct dxil_type *,
618                                                  num_elem_types);
619       if (!type->struct_def.elem.types)
620          return NULL;
621 
622       memcpy(type->struct_def.elem.types, elem_types,
623              sizeof(struct dxil_type *) * num_elem_types);
624       type->struct_def.elem.num_types = num_elem_types;
625    }
626    return type;
627 }
628 
629 const struct dxil_type *
dxil_module_get_array_type(struct dxil_module * m,const struct dxil_type * elem_type,size_t num_elems)630 dxil_module_get_array_type(struct dxil_module *m,
631                            const struct dxil_type *elem_type,
632                            size_t num_elems)
633 {
634    struct dxil_type *type;
635    LIST_FOR_EACH_ENTRY(type, &m->type_list, head) {
636       if (type->type != TYPE_ARRAY)
637          continue;
638 
639       if (type->array_or_vector_def.elem_type == elem_type &&
640           type->array_or_vector_def.num_elems == num_elems)
641          return type;
642    }
643 
644    type = create_type(m, TYPE_ARRAY);
645    if (type) {
646       type->array_or_vector_def.elem_type = elem_type;
647       type->array_or_vector_def.num_elems = num_elems;
648    }
649    return type;
650 }
651 
652 const struct dxil_type *
dxil_module_get_vector_type(struct dxil_module * m,const struct dxil_type * elem_type,size_t num_elems)653 dxil_module_get_vector_type(struct dxil_module *m,
654                             const struct dxil_type *elem_type,
655                             size_t num_elems)
656 {
657    struct dxil_type *type;
658    LIST_FOR_EACH_ENTRY(type, &m->type_list, head) {
659       if (type->type == TYPE_VECTOR &&
660           type->array_or_vector_def.elem_type == elem_type &&
661           type->array_or_vector_def.num_elems == num_elems)
662          return type;
663    }
664 
665    type = create_type(m, TYPE_VECTOR);
666    if (!type)
667       return NULL;
668 
669    type->array_or_vector_def.elem_type = elem_type;
670    type->array_or_vector_def.num_elems = num_elems;
671    return type;
672 }
673 
674 const struct dxil_type *
dxil_get_overload_type(struct dxil_module * mod,enum overload_type overload)675 dxil_get_overload_type(struct dxil_module *mod, enum overload_type overload)
676 {
677    switch (overload) {
678    case DXIL_I1: return get_int1_type(mod);
679    case DXIL_I16: return get_int16_type(mod);
680    case DXIL_I32: return get_int32_type(mod);
681    case DXIL_I64: return get_int64_type(mod);
682    case DXIL_F16: return get_float16_type(mod);
683    case DXIL_F32: return get_float32_type(mod);
684    case DXIL_F64: return get_float64_type(mod);
685    default:
686       unreachable("unexpected overload type");
687    }
688 }
689 
690 const struct dxil_type *
dxil_module_get_handle_type(struct dxil_module * m)691 dxil_module_get_handle_type(struct dxil_module *m)
692 {
693    const struct dxil_type *int8_type = get_int8_type(m);
694    if (!int8_type)
695       return NULL;
696 
697    const struct dxil_type *ptr_type = dxil_module_get_pointer_type(m, int8_type);
698    if (!ptr_type)
699       return NULL;
700 
701    return dxil_module_get_struct_type(m, "dx.types.Handle", &ptr_type, 1);
702 }
703 
704 const struct dxil_type *
dxil_module_get_cbuf_ret_type(struct dxil_module * mod,enum overload_type overload)705 dxil_module_get_cbuf_ret_type(struct dxil_module *mod, enum overload_type overload)
706 {
707    const struct dxil_type *overload_type = dxil_get_overload_type(mod, overload);
708    const struct dxil_type *fields[8] = { overload_type, overload_type, overload_type, overload_type,
709                                          overload_type, overload_type, overload_type, overload_type };
710    unsigned num_fields;
711 
712    char name[64];
713    const char *additional = "";
714    switch (overload) {
715    case DXIL_I32:
716    case DXIL_F32:
717       num_fields = 4;
718       break;
719    case DXIL_I64:
720    case DXIL_F64:
721       num_fields = 2;
722       break;
723    case DXIL_I16:
724    case DXIL_F16:
725       num_fields = 8;
726       additional = ".8";
727       break;
728    default:
729       unreachable("unexpected overload type");
730    }
731    snprintf(name, sizeof(name), "dx.types.CBufRet.%s%s", dxil_overload_suffix(overload), additional);
732 
733    return dxil_module_get_struct_type(mod, name, fields, num_fields);
734 }
735 
736 const struct dxil_type *
dxil_module_get_split_double_ret_type(struct dxil_module * mod)737 dxil_module_get_split_double_ret_type(struct dxil_module *mod)
738 {
739    const struct dxil_type *int32_type = dxil_module_get_int_type(mod, 32);
740    const struct dxil_type *fields[2] = { int32_type, int32_type };
741 
742    return dxil_module_get_struct_type(mod, "dx.types.splitdouble", fields, 2);
743 }
744 
745 static const struct dxil_type *
dxil_module_get_type_from_comp_type(struct dxil_module * m,enum dxil_component_type comp_type)746 dxil_module_get_type_from_comp_type(struct dxil_module *m, enum dxil_component_type comp_type)
747 {
748    switch (comp_type) {
749    case DXIL_COMP_TYPE_U32: return get_int32_type(m);
750    case DXIL_COMP_TYPE_I32: return get_int32_type(m);
751    case DXIL_COMP_TYPE_F32: return get_float32_type(m);
752    case DXIL_COMP_TYPE_F64: return get_float64_type(m);
753    case DXIL_COMP_TYPE_U16: return get_int16_type(m);
754    case DXIL_COMP_TYPE_I16: return get_int16_type(m);
755    case DXIL_COMP_TYPE_U64: return get_int64_type(m);
756    case DXIL_COMP_TYPE_I64: return get_int64_type(m);
757    case DXIL_COMP_TYPE_I1: return get_int1_type(m);
758 
759    case DXIL_COMP_TYPE_F16:
760    default:
761       unreachable("unexpected component type");
762    }
763 }
764 
765 static const char *
get_res_comp_type_name(enum dxil_component_type comp_type)766 get_res_comp_type_name(enum dxil_component_type comp_type)
767 {
768    switch (comp_type) {
769    case DXIL_COMP_TYPE_F64: return "double";
770    case DXIL_COMP_TYPE_F32: return "float";
771    case DXIL_COMP_TYPE_I32: return "int";
772    case DXIL_COMP_TYPE_U32: return "uint";
773    case DXIL_COMP_TYPE_I64: return "int64";
774    case DXIL_COMP_TYPE_U64: return "uint64";
775    default:
776       unreachable("unexpected resource component type");
777    }
778 }
779 
780 static const char *
get_res_dimension_type_name(enum dxil_resource_kind kind)781 get_res_dimension_type_name(enum dxil_resource_kind kind)
782 {
783    switch (kind) {
784    case DXIL_RESOURCE_KIND_TYPED_BUFFER: return "Buffer";
785    case DXIL_RESOURCE_KIND_TEXTURE1D: return "Texture1D";
786    case DXIL_RESOURCE_KIND_TEXTURE1D_ARRAY: return "Texture1DArray";
787    case DXIL_RESOURCE_KIND_TEXTURE2D: return "Texture2D";
788    case DXIL_RESOURCE_KIND_TEXTURE2DMS: return "Texture2DMS";
789    case DXIL_RESOURCE_KIND_TEXTURE2D_ARRAY: return "Texture2DArray";
790    case DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY: return "Texture2DMSArray";
791    case DXIL_RESOURCE_KIND_TEXTURE3D: return "Texture3D";
792    case DXIL_RESOURCE_KIND_TEXTURECUBE: return "TextureCube";
793    case DXIL_RESOURCE_KIND_TEXTURECUBE_ARRAY: return "TextureCubeArray";
794    default:
795       unreachable("unexpected resource kind");
796    }
797 }
798 
799 static const char *
get_res_ms_postfix(enum dxil_resource_kind kind)800 get_res_ms_postfix(enum dxil_resource_kind kind)
801 {
802    switch (kind) {
803    case DXIL_RESOURCE_KIND_TEXTURE2DMS:
804    case DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY:
805       return ", 0";
806 
807    default:
808       return "";
809    }
810 }
811 const struct dxil_type *
dxil_module_get_res_type(struct dxil_module * m,enum dxil_resource_kind kind,enum dxil_component_type comp_type,unsigned num_comps,bool readwrite)812 dxil_module_get_res_type(struct dxil_module *m, enum dxil_resource_kind kind,
813                          enum dxil_component_type comp_type, unsigned num_comps,
814                          bool readwrite)
815 {
816    switch (kind) {
817    case DXIL_RESOURCE_KIND_TYPED_BUFFER:
818    case DXIL_RESOURCE_KIND_TEXTURE1D:
819    case DXIL_RESOURCE_KIND_TEXTURE1D_ARRAY:
820    case DXIL_RESOURCE_KIND_TEXTURE2D:
821    case DXIL_RESOURCE_KIND_TEXTURE2D_ARRAY:
822    case DXIL_RESOURCE_KIND_TEXTURE2DMS:
823    case DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY:
824    case DXIL_RESOURCE_KIND_TEXTURE3D:
825    case DXIL_RESOURCE_KIND_TEXTURECUBE:
826    case DXIL_RESOURCE_KIND_TEXTURECUBE_ARRAY:
827    {
828       const struct dxil_type *component_type = dxil_module_get_type_from_comp_type(m, comp_type);
829       const struct dxil_type *vec_type = num_comps == 1 ? component_type :
830          dxil_module_get_vector_type(m, component_type, num_comps);
831       char vector_name[64] = { 0 };
832       if (num_comps == 1)
833          snprintf(vector_name, 64, "%s", get_res_comp_type_name(comp_type));
834       else
835          snprintf(vector_name, 64, "vector<%s, %d>", get_res_comp_type_name(comp_type), num_comps);
836       char class_name[64] = { 0 };
837       snprintf(class_name, 64, "class.%s%s<%s%s>",
838                readwrite ? "RW" : "",
839                get_res_dimension_type_name(kind),
840                vector_name,
841                get_res_ms_postfix(kind));
842       return dxil_module_get_struct_type(m, class_name, &vec_type, 1);
843    }
844 
845    case DXIL_RESOURCE_KIND_RAW_BUFFER:
846    {
847       const struct dxil_type *component_type = dxil_module_get_int_type(m, 32);
848       char class_name[64] = { 0 };
849       snprintf(class_name, 64, "struct.%sByteAddressBuffer", readwrite ? "RW" : "");
850       return dxil_module_get_struct_type(m, class_name, &component_type, 1);
851    }
852 
853    default:
854       unreachable("resource type not supported");
855    }
856 }
857 
858 const struct dxil_type *
dxil_module_get_resret_type(struct dxil_module * m,enum overload_type overload)859 dxil_module_get_resret_type(struct dxil_module *m, enum overload_type overload)
860 {
861    const struct dxil_type *overload_type = dxil_get_overload_type(m, overload);
862    const struct dxil_type *int32_type = dxil_module_get_int_type(m, 32);
863    const char *name;
864    if (!overload_type)
865       return NULL;
866 
867    const struct dxil_type *resret[] =
868       { overload_type, overload_type, overload_type, overload_type, int32_type };
869 
870    switch (overload) {
871    case DXIL_I16: name = "dx.types.ResRet.i16"; break;
872    case DXIL_I32: name = "dx.types.ResRet.i32"; break;
873    case DXIL_I64: name = "dx.types.ResRet.i64"; break;
874    case DXIL_F16: name = "dx.types.ResRet.f16"; break;
875    case DXIL_F32: name = "dx.types.ResRet.f32"; break;
876    case DXIL_F64: name = "dx.types.ResRet.f64"; break;
877    default:
878       unreachable("unexpected overload type");
879    }
880 
881    return dxil_module_get_struct_type(m, name, resret, 5);
882 }
883 
884 const struct dxil_type *
dxil_module_get_dimret_type(struct dxil_module * m)885 dxil_module_get_dimret_type(struct dxil_module *m)
886 {
887    const struct dxil_type *int32_type = dxil_module_get_int_type(m, 32);
888 
889    const struct dxil_type *dimret[] =
890       { int32_type, int32_type, int32_type, int32_type };
891 
892    return dxil_module_get_struct_type(m, "dx.types.Dimensions", dimret, 4);
893 }
894 
895 const struct dxil_type *
dxil_module_get_samplepos_type(struct dxil_module * m)896 dxil_module_get_samplepos_type(struct dxil_module *m)
897 {
898    const struct dxil_type *float_type = dxil_module_get_float_type(m, 32);
899 
900    const struct dxil_type *samplepos[] =
901       { float_type, float_type };
902 
903    return dxil_module_get_struct_type(m, "dx.types.SamplePos", samplepos, 2);
904 }
905 
906 const struct dxil_type *
dxil_module_get_res_bind_type(struct dxil_module * mod)907 dxil_module_get_res_bind_type(struct dxil_module *mod)
908 {
909    /* %dx.types.ResBind = type { i32, i32, i32, i8 } */
910    const struct dxil_type *int32_type = dxil_module_get_int_type(mod, 32);
911    const struct dxil_type *int8_type = dxil_module_get_int_type(mod, 8);
912    const struct dxil_type *fields[4] = { int32_type, int32_type, int32_type, int8_type };
913 
914    return dxil_module_get_struct_type(mod, "dx.types.ResBind", fields, 4);
915 }
916 
917 const struct dxil_type *
dxil_module_get_res_props_type(struct dxil_module * mod)918 dxil_module_get_res_props_type(struct dxil_module *mod)
919 {
920    /* %dx.types.ResourceProperties = type { i32, i32 } */
921    const struct dxil_type *int32_type = dxil_module_get_int_type(mod, 32);
922    const struct dxil_type *fields[2] = { int32_type, int32_type };
923 
924    return dxil_module_get_struct_type(mod, "dx.types.ResourceProperties", fields, 2);
925 }
926 
927 const struct dxil_type *
dxil_module_get_fouri32_type(struct dxil_module * mod)928 dxil_module_get_fouri32_type(struct dxil_module *mod)
929 {
930    /* %dx.types.fouri32 = type { i32, i32, i32, i32 } */
931    const struct dxil_type *int32_type = dxil_module_get_int_type(mod, 32);
932    const struct dxil_type *fields[4] = { int32_type, int32_type, int32_type, int32_type };
933 
934    return dxil_module_get_struct_type(mod, "dx.types.fouri32", fields, 4);
935 }
936 
937 const struct dxil_type *
dxil_module_add_function_type(struct dxil_module * m,const struct dxil_type * ret_type,const struct dxil_type ** arg_types,size_t num_arg_types)938 dxil_module_add_function_type(struct dxil_module *m,
939                               const struct dxil_type *ret_type,
940                               const struct dxil_type **arg_types,
941                               size_t num_arg_types)
942 {
943    struct dxil_type *type = create_type(m, TYPE_FUNCTION);
944    if (type) {
945       type->function_def.args.types = ralloc_array(type,
946                                                   struct dxil_type *,
947                                                   num_arg_types);
948       if (!type->function_def.args.types)
949          return NULL;
950 
951       memcpy(type->function_def.args.types, arg_types,
952              sizeof(struct dxil_type *) * num_arg_types);
953       type->function_def.args.num_types = num_arg_types;
954       type->function_def.ret_type = ret_type;
955    }
956    return type;
957 }
958 
959 
960 enum type_codes {
961   TYPE_CODE_NUMENTRY = 1,
962   TYPE_CODE_VOID = 2,
963   TYPE_CODE_FLOAT = 3,
964   TYPE_CODE_DOUBLE = 4,
965   TYPE_CODE_LABEL = 5,
966   TYPE_CODE_OPAQUE = 6,
967   TYPE_CODE_INTEGER = 7,
968   TYPE_CODE_POINTER = 8,
969   TYPE_CODE_FUNCTION_OLD = 9,
970   TYPE_CODE_HALF = 10,
971   TYPE_CODE_ARRAY = 11,
972   TYPE_CODE_VECTOR = 12,
973   TYPE_CODE_X86_FP80 = 13,
974   TYPE_CODE_FP128 = 14,
975   TYPE_CODE_PPC_FP128 = 15,
976   TYPE_CODE_METADATA = 16,
977   TYPE_CODE_X86_MMX = 17,
978   TYPE_CODE_STRUCT_ANON = 18,
979   TYPE_CODE_STRUCT_NAME = 19,
980   TYPE_CODE_STRUCT_NAMED = 20,
981   TYPE_CODE_FUNCTION = 21
982 };
983 
984 #define LITERAL(x) { DXIL_OP_LITERAL, { (x) } }
985 #define FIXED(x) { DXIL_OP_FIXED, { (x) } }
986 #define VBR(x) { DXIL_OP_VBR, { (x) } }
987 #define ARRAY { DXIL_OP_ARRAY, { 0 } }
988 #define CHAR6 { DXIL_OP_CHAR6, { 0 } }
989 #define BLOB { DXIL_OP_BLOB, { 0 } }
990 
991 #define TYPE_INDEX FIXED(32)
992 
993 enum type_table_abbrev_id {
994    TYPE_TABLE_ABBREV_POINTER,
995    TYPE_TABLE_ABBREV_FUNCTION,
996    TYPE_TABLE_ABBREV_STRUCT_ANON,
997    TYPE_TABLE_ABBREV_STRUCT_NAME,
998    TYPE_TABLE_ABBREV_STRUCT_NAMED,
999    TYPE_TABLE_ABBREV_ARRAY,
1000    TYPE_TABLE_ABBREV_VECTOR,
1001 };
1002 
1003 static const struct dxil_abbrev
1004 type_table_abbrevs[] = {
1005    [TYPE_TABLE_ABBREV_POINTER] = {
1006       { LITERAL(TYPE_CODE_POINTER), TYPE_INDEX, LITERAL(0) }, 3
1007    },
1008    [TYPE_TABLE_ABBREV_FUNCTION] = {
1009       { LITERAL(TYPE_CODE_FUNCTION), FIXED(1), ARRAY, TYPE_INDEX }, 4
1010    },
1011    [TYPE_TABLE_ABBREV_STRUCT_ANON] = {
1012       { LITERAL(TYPE_CODE_STRUCT_ANON), FIXED(1), ARRAY, TYPE_INDEX }, 4
1013    },
1014    [TYPE_TABLE_ABBREV_STRUCT_NAME] = {
1015       { LITERAL(TYPE_CODE_STRUCT_NAME), ARRAY, CHAR6 }, 3
1016    },
1017    [TYPE_TABLE_ABBREV_STRUCT_NAMED] = {
1018       { LITERAL(TYPE_CODE_STRUCT_NAMED), FIXED(1), ARRAY, TYPE_INDEX }, 4
1019    },
1020    [TYPE_TABLE_ABBREV_ARRAY] = {
1021       { LITERAL(TYPE_CODE_ARRAY), VBR(8), TYPE_INDEX }, 3
1022    },
1023    [TYPE_TABLE_ABBREV_VECTOR] = {
1024       { LITERAL(TYPE_CODE_VECTOR), VBR(8), TYPE_INDEX }, 3
1025    },
1026 };
1027 
1028 static bool
emit_type_table_abbrev_record(struct dxil_module * m,enum type_table_abbrev_id abbrev,const uint64_t * data,size_t size)1029 emit_type_table_abbrev_record(struct dxil_module *m,
1030                               enum type_table_abbrev_id abbrev,
1031                               const uint64_t *data, size_t size)
1032 {
1033    assert(abbrev < ARRAY_SIZE(type_table_abbrevs));
1034    return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,
1035                              type_table_abbrevs + abbrev, data, size);
1036 }
1037 
1038 enum constant_code {
1039   CST_CODE_SETTYPE = 1,
1040   CST_CODE_NULL = 2,
1041   CST_CODE_UNDEF = 3,
1042   CST_CODE_INTEGER = 4,
1043   CST_CODE_WIDE_INTEGER = 5,
1044   CST_CODE_FLOAT = 6,
1045   CST_CODE_AGGREGATE = 7,
1046   CST_CODE_STRING = 8,
1047   CST_CODE_CSTRING = 9,
1048   CST_CODE_CE_BINOP = 10,
1049   CST_CODE_CE_CAST = 11,
1050   CST_CODE_CE_GEP = 12,
1051   CST_CODE_CE_SELECT = 13,
1052   CST_CODE_CE_EXTRACTELT = 14,
1053   CST_CODE_CE_INSERTELT = 15,
1054   CST_CODE_CE_SHUFFLEVEC = 16,
1055   CST_CODE_CE_CMP = 17,
1056   CST_CODE_INLINEASM_OLD = 18,
1057   CST_CODE_CE_SHUFVEC_EX = 19,
1058   CST_CODE_CE_INBOUNDS_GEP = 20,
1059   CST_CODE_BLOCKADDRESS = 21,
1060   CST_CODE_DATA = 22,
1061   CST_CODE_INLINEASM = 23
1062 };
1063 
1064 enum const_abbrev_id {
1065    CONST_ABBREV_SETTYPE,
1066    CONST_ABBREV_INTEGER,
1067    CONST_ABBREV_CE_CAST,
1068    CONST_ABBREV_NULL,
1069 };
1070 
1071 static const struct dxil_abbrev
1072 const_abbrevs[] = {
1073    [CONST_ABBREV_SETTYPE] = { { LITERAL(CST_CODE_SETTYPE), TYPE_INDEX }, 2 },
1074    [CONST_ABBREV_INTEGER] = { { LITERAL(CST_CODE_INTEGER), VBR(8) }, 2 },
1075    [CONST_ABBREV_CE_CAST] = {
1076       { LITERAL(CST_CODE_CE_CAST), FIXED(4), TYPE_INDEX, VBR(8) }, 4
1077    },
1078    [CONST_ABBREV_NULL] = { { LITERAL(CST_CODE_NULL) }, 1 },
1079 };
1080 
1081 static bool
emit_const_abbrev_record(struct dxil_module * m,enum const_abbrev_id abbrev,const uint64_t * data,size_t size)1082 emit_const_abbrev_record(struct dxil_module *m, enum const_abbrev_id abbrev,
1083                          const uint64_t *data, size_t size)
1084 {
1085    assert(abbrev < ARRAY_SIZE(const_abbrevs));
1086 
1087    return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,
1088                              const_abbrevs + abbrev, data, size);
1089 }
1090 
1091 enum function_code {
1092   FUNC_CODE_DECLAREBLOCKS = 1,
1093   FUNC_CODE_INST_BINOP = 2,
1094   FUNC_CODE_INST_CAST = 3,
1095   FUNC_CODE_INST_GEP_OLD = 4,
1096   FUNC_CODE_INST_SELECT = 5,
1097   FUNC_CODE_INST_EXTRACTELT = 6,
1098   FUNC_CODE_INST_INSERTELT = 7,
1099   FUNC_CODE_INST_SHUFFLEVEC = 8,
1100   FUNC_CODE_INST_CMP = 9,
1101   FUNC_CODE_INST_RET = 10,
1102   FUNC_CODE_INST_BR = 11,
1103   FUNC_CODE_INST_SWITCH = 12,
1104   FUNC_CODE_INST_INVOKE = 13,
1105   /* 14: unused */
1106   FUNC_CODE_INST_UNREACHABLE = 15,
1107   FUNC_CODE_INST_PHI = 16,
1108   /* 17-18: unused */
1109   FUNC_CODE_INST_ALLOCA = 19,
1110   FUNC_CODE_INST_LOAD = 20,
1111   /* 21-22: unused */
1112   FUNC_CODE_INST_VAARG = 23,
1113   FUNC_CODE_INST_STORE_OLD = 24,
1114   /* 25: unused */
1115   FUNC_CODE_INST_EXTRACTVAL = 26,
1116   FUNC_CODE_INST_INSERTVAL = 27,
1117   FUNC_CODE_INST_CMP2 = 28,
1118   FUNC_CODE_INST_VSELECT = 29,
1119   FUNC_CODE_INST_INBOUNDS_GEP_OLD = 30,
1120   FUNC_CODE_INST_INDIRECTBR = 31,
1121   /* 32: unused */
1122   FUNC_CODE_DEBUG_LOC_AGAIN = 33,
1123   FUNC_CODE_INST_CALL = 34,
1124   FUNC_CODE_DEBUG_LOC = 35,
1125   FUNC_CODE_INST_FENCE = 36,
1126   FUNC_CODE_INST_CMPXCHG_OLD = 37,
1127   FUNC_CODE_INST_ATOMICRMW = 38,
1128   FUNC_CODE_INST_RESUME = 39,
1129   FUNC_CODE_INST_LANDINGPAD_OLD = 40,
1130   FUNC_CODE_INST_LOADATOMIC = 41,
1131   FUNC_CODE_INST_STOREATOMIC_OLD = 42,
1132   FUNC_CODE_INST_GEP = 43,
1133   FUNC_CODE_INST_STORE = 44,
1134   FUNC_CODE_INST_STOREATOMIC = 45,
1135   FUNC_CODE_INST_CMPXCHG = 46,
1136   FUNC_CODE_INST_LANDINGPAD = 47,
1137 };
1138 
1139 enum func_abbrev_id {
1140    FUNC_ABBREV_LOAD,
1141    FUNC_ABBREV_BINOP,
1142    FUNC_ABBREV_BINOP_FLAGS,
1143    FUNC_ABBREV_CAST,
1144    FUNC_ABBREV_RET_VOID,
1145    FUNC_ABBREV_RET_VAL,
1146    FUNC_ABBREV_UNREACHABLE,
1147    FUNC_ABBREV_GEP,
1148 };
1149 
1150 static const struct dxil_abbrev
1151 func_abbrevs[] = {
1152    [FUNC_ABBREV_LOAD] = {
1153       { LITERAL(FUNC_CODE_INST_LOAD), VBR(6), TYPE_INDEX, VBR(4),
1154         FIXED(1) }, 5
1155    },
1156    [FUNC_ABBREV_BINOP] = {
1157       { LITERAL(FUNC_CODE_INST_BINOP), VBR(6), VBR(6), FIXED(4) }, 4
1158    },
1159    [FUNC_ABBREV_BINOP_FLAGS] = {
1160       { LITERAL(FUNC_CODE_INST_BINOP), VBR(6), VBR(6), FIXED(4),
1161         FIXED(7) }, 5
1162    },
1163    [FUNC_ABBREV_CAST] = {
1164       { LITERAL(FUNC_CODE_INST_CAST), VBR(6), TYPE_INDEX, FIXED(4) }, 4
1165    },
1166    [FUNC_ABBREV_RET_VOID] = { { LITERAL(FUNC_CODE_INST_RET) }, 1 },
1167    [FUNC_ABBREV_RET_VAL] = { { LITERAL(FUNC_CODE_INST_RET), VBR(6) }, 2 },
1168    [FUNC_ABBREV_UNREACHABLE] = {
1169       { LITERAL(FUNC_CODE_INST_UNREACHABLE) }, 1
1170    },
1171    [FUNC_ABBREV_GEP] = {
1172       { LITERAL(FUNC_CODE_INST_GEP), FIXED(1), TYPE_INDEX, ARRAY,
1173         VBR(6) }, 5
1174    },
1175 };
1176 
1177 static bool
emit_func_abbrev_record(struct dxil_module * m,enum func_abbrev_id abbrev,const uint64_t * data,size_t size)1178 emit_func_abbrev_record(struct dxil_module *m, enum func_abbrev_id abbrev,
1179                         const uint64_t *data, size_t size)
1180 {
1181    assert(abbrev < ARRAY_SIZE(func_abbrevs));
1182    return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,
1183                              func_abbrevs + abbrev, data, size);
1184 }
1185 
1186 static bool
define_abbrev(struct dxil_module * m,const struct dxil_abbrev * a)1187 define_abbrev(struct dxil_module *m, const struct dxil_abbrev *a)
1188 {
1189    if (!dxil_buffer_emit_abbrev_id(&m->buf, DXIL_DEFINE_ABBREV) ||
1190        !dxil_buffer_emit_vbr_bits(&m->buf, a->num_operands, 5))
1191       return false;
1192 
1193    for (int i = 0; i < a->num_operands; ++i) {
1194       unsigned is_literal = a->operands[i].type == DXIL_OP_LITERAL;
1195       if (!dxil_buffer_emit_bits(&m->buf, is_literal, 1))
1196          return false;
1197       if (a->operands[i].type == DXIL_OP_LITERAL) {
1198          if (!dxil_buffer_emit_vbr_bits(&m->buf, a->operands[i].value, 8))
1199             return false;
1200       } else {
1201          if (!dxil_buffer_emit_bits(&m->buf, a->operands[i].type, 3))
1202             return false;
1203          if (a->operands[i].type == DXIL_OP_FIXED) {
1204             if (!dxil_buffer_emit_vbr_bits(&m->buf,
1205                                            a->operands[i].encoding_data, 5))
1206                return false;
1207          } else if (a->operands[i].type == DXIL_OP_VBR) {
1208             if (!dxil_buffer_emit_vbr_bits(&m->buf,
1209                                            a->operands[i].encoding_data, 5))
1210                return false;
1211          }
1212       }
1213    }
1214 
1215    return true;
1216 }
1217 
1218 enum dxil_blockinfo_code {
1219    DXIL_BLOCKINFO_CODE_SETBID = 1,
1220    DXIL_BLOCKINFO_CODE_BLOCKNAME = 2,
1221    DXIL_BLOCKINFO_CODE_SETRECORDNAME = 3
1222 };
1223 
1224 static bool
switch_to_block(struct dxil_module * m,uint32_t block)1225 switch_to_block(struct dxil_module *m, uint32_t block)
1226 {
1227    return emit_record_int(m, DXIL_BLOCKINFO_CODE_SETBID, block);
1228 }
1229 
1230 enum dxil_standard_block {
1231    DXIL_BLOCKINFO = 0,
1232    DXIL_FIRST_APPLICATION_BLOCK = 8
1233 };
1234 
1235 enum dxil_llvm_block {
1236    DXIL_MODULE = DXIL_FIRST_APPLICATION_BLOCK,
1237    DXIL_PARAMATTR = DXIL_FIRST_APPLICATION_BLOCK + 1,
1238    DXIL_PARAMATTR_GROUP = DXIL_FIRST_APPLICATION_BLOCK + 2,
1239    DXIL_CONST_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 3,
1240    DXIL_FUNCTION_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 4,
1241    DXIL_VALUE_SYMTAB_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 6,
1242    DXIL_METADATA_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 7,
1243    DXIL_TYPE_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 9,
1244 };
1245 
1246 enum value_symtab_code {
1247   VST_CODE_ENTRY = 1,
1248   VST_CODE_BBENTRY = 2
1249 };
1250 
1251 enum value_symtab_abbrev_id {
1252    VST_ABBREV_ENTRY_8,
1253    VST_ABBREV_ENTRY_7,
1254    VST_ABBREV_ENTRY_6,
1255    VST_ABBREV_BBENTRY_6,
1256 };
1257 
1258 static struct dxil_abbrev value_symtab_abbrevs[] = {
1259    [VST_ABBREV_ENTRY_8] = { { FIXED(3), VBR(8), ARRAY, FIXED(8) }, 4 },
1260    [VST_ABBREV_ENTRY_7] = {
1261       { LITERAL(VST_CODE_ENTRY), VBR(8), ARRAY, FIXED(7), }, 4
1262    },
1263    [VST_ABBREV_ENTRY_6] = {
1264       { LITERAL(VST_CODE_ENTRY), VBR(8), ARRAY, CHAR6, }, 4
1265    },
1266    [VST_ABBREV_BBENTRY_6] = {
1267       { LITERAL(VST_CODE_BBENTRY), VBR(8), ARRAY, CHAR6, }, 4
1268    },
1269 };
1270 
1271 static bool
emit_value_symtab_abbrevs(struct dxil_module * m)1272 emit_value_symtab_abbrevs(struct dxil_module *m)
1273 {
1274    if (!switch_to_block(m, DXIL_VALUE_SYMTAB_BLOCK))
1275       return false;
1276 
1277    for (int i = 0; i < ARRAY_SIZE(value_symtab_abbrevs); ++i) {
1278       if (!define_abbrev(m, value_symtab_abbrevs + i))
1279          return false;
1280    }
1281 
1282    return true;
1283 }
1284 
1285 static bool
emit_const_abbrevs(struct dxil_module * m)1286 emit_const_abbrevs(struct dxil_module *m)
1287 {
1288    if (!switch_to_block(m, DXIL_CONST_BLOCK))
1289       return false;
1290 
1291    for (int i = 0; i < ARRAY_SIZE(const_abbrevs); ++i) {
1292       if (!define_abbrev(m, const_abbrevs + i))
1293          return false;
1294    }
1295 
1296    return true;
1297 }
1298 
1299 static bool
emit_function_abbrevs(struct dxil_module * m)1300 emit_function_abbrevs(struct dxil_module *m)
1301 {
1302    if (!switch_to_block(m, DXIL_FUNCTION_BLOCK))
1303       return false;
1304 
1305    for (int i = 0; i < ARRAY_SIZE(func_abbrevs); ++i) {
1306       if (!define_abbrev(m, func_abbrevs + i))
1307          return false;
1308    }
1309 
1310    return true;
1311 }
1312 
1313 static bool
emit_blockinfo(struct dxil_module * m)1314 emit_blockinfo(struct dxil_module *m)
1315 {
1316    return enter_subblock(m, DXIL_BLOCKINFO, 2) &&
1317           emit_value_symtab_abbrevs(m) &&
1318           emit_const_abbrevs(m) &&
1319           emit_function_abbrevs(m) &&
1320           exit_block(m);
1321 }
1322 
1323 enum attribute_codes {
1324    PARAMATTR_GRP_CODE_ENTRY = 3,
1325    PARAMATTR_CODE_ENTRY = 2
1326 };
1327 
1328 static bool
emit_attrib_group(struct dxil_module * m,int id,uint32_t slot,const struct dxil_attrib * attrs,size_t num_attrs)1329 emit_attrib_group(struct dxil_module *m, int id, uint32_t slot,
1330                   const struct dxil_attrib *attrs, size_t num_attrs)
1331 {
1332    uint64_t record[128];
1333    record[0] = id;
1334    record[1] = slot;
1335    size_t size = 2;
1336 
1337    for (int i = 0; i < num_attrs; ++i) {
1338       assert(size < ARRAY_SIZE(record) - 2);
1339       record[size++] = attrs[i].type;
1340       switch (attrs[i].type) {
1341       case DXIL_ATTR_ENUM:
1342          record[size++] = attrs[i].key.kind;
1343          break;
1344       case DXIL_ATTR_ENUM_VALUE:
1345          record[size++] = attrs[i].key.kind;
1346          record[size++] = attrs[i].value.integer;
1347          break;
1348       case DXIL_ATTR_STRING:
1349       case DXIL_ATTR_STRING_VALUE:
1350          assert(size < ARRAY_SIZE(record) - strlen(attrs[i].key.str));
1351          for (int j = 0; attrs[i].key.str[j]; ++j)
1352             record[size++] = attrs[i].key.str[j];
1353          record[size++] = 0;
1354 
1355          if (attrs[i].type == DXIL_ATTR_STRING)
1356             break;
1357 
1358          assert(size < ARRAY_SIZE(record) - strlen(attrs[i].value.str));
1359          for (int j = 0; attrs[i].value.str[j]; ++j)
1360             record[size++] = attrs[i].value.str[j];
1361          record[size++] = 0;
1362          break;
1363 
1364       default:
1365          unreachable("unsupported attrib type");
1366       }
1367    }
1368 
1369    return emit_record(m, PARAMATTR_GRP_CODE_ENTRY, record, size);
1370 }
1371 
1372 static bool
emit_attrib_group_table(struct dxil_module * m)1373 emit_attrib_group_table(struct dxil_module *m)
1374 {
1375    if (!enter_subblock(m, DXIL_PARAMATTR_GROUP, 3))
1376       return false;
1377 
1378    struct attrib_set *as;
1379    int id = 1;
1380    LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) {
1381       if (!emit_attrib_group(m, id, UINT32_MAX, as->attrs, as->num_attrs))
1382          return false;
1383       id++;
1384    }
1385 
1386    return exit_block(m);
1387 }
1388 
1389 static bool
emit_attribute_table(struct dxil_module * m)1390 emit_attribute_table(struct dxil_module *m)
1391 {
1392    if (!enter_subblock(m, DXIL_PARAMATTR, 3))
1393       return false;
1394 
1395    struct attrib_set *as;
1396    int id = 1;
1397    LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) {
1398       if (!emit_record_int(m, PARAMATTR_CODE_ENTRY, id))
1399          return false;
1400       id++;
1401    }
1402 
1403    return exit_block(m);
1404 }
1405 
1406 static bool
emit_type_table_abbrevs(struct dxil_module * m)1407 emit_type_table_abbrevs(struct dxil_module *m)
1408 {
1409    for (int i = 0; i < ARRAY_SIZE(type_table_abbrevs); ++i) {
1410       if (!define_abbrev(m, type_table_abbrevs + i))
1411          return false;
1412    }
1413 
1414    return true;
1415 }
1416 
1417 static bool
emit_float_type(struct dxil_module * m,unsigned bit_size)1418 emit_float_type(struct dxil_module *m, unsigned bit_size)
1419 {
1420    switch (bit_size) {
1421    case 16: return emit_record(m, TYPE_CODE_HALF, NULL, 0);
1422    case 32: return emit_record(m, TYPE_CODE_FLOAT, NULL, 0);
1423    case 64: return emit_record(m, TYPE_CODE_DOUBLE, NULL, 0);
1424    default:
1425       unreachable("unexpected bit_size for float type");
1426    }
1427 }
1428 
1429 static bool
emit_pointer_type(struct dxil_module * m,int type_index)1430 emit_pointer_type(struct dxil_module *m, int type_index)
1431 {
1432    uint64_t data[] = { TYPE_CODE_POINTER, type_index, 0 };
1433    return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_POINTER,
1434                                         data, ARRAY_SIZE(data));
1435 }
1436 
1437 static bool
emit_struct_name(struct dxil_module * m,const char * name)1438 emit_struct_name(struct dxil_module *m, const char *name)
1439 {
1440    uint64_t temp[256];
1441    assert(strlen(name) < ARRAY_SIZE(temp));
1442 
1443    for (int i = 0; i < strlen(name); ++i)
1444       temp[i] = name[i];
1445 
1446    return emit_record(m, TYPE_CODE_STRUCT_NAME, temp, strlen(name));
1447 }
1448 
1449 static bool
emit_struct_name_char6(struct dxil_module * m,const char * name)1450 emit_struct_name_char6(struct dxil_module *m, const char *name)
1451 {
1452    uint64_t temp[256];
1453    assert(strlen(name) < ARRAY_SIZE(temp) - 1);
1454 
1455    temp[0] = TYPE_CODE_STRUCT_NAME;
1456    for (int i = 0; i < strlen(name); ++i)
1457       temp[i + 1] = name[i];
1458 
1459    return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_STRUCT_NAME,
1460                                         temp, 1 + strlen(name));
1461 }
1462 
1463 static bool
emit_struct_type(struct dxil_module * m,const struct dxil_type * type)1464 emit_struct_type(struct dxil_module *m, const struct dxil_type *type)
1465 {
1466    enum type_table_abbrev_id abbrev = TYPE_TABLE_ABBREV_STRUCT_ANON;
1467    enum type_codes type_code = TYPE_CODE_STRUCT_ANON;
1468    if (type->struct_def.name) {
1469       abbrev = TYPE_TABLE_ABBREV_STRUCT_NAMED;
1470       type_code = TYPE_CODE_STRUCT_NAMED;
1471       if (is_char6_string(type->struct_def.name)) {
1472          if (!emit_struct_name_char6(m, type->struct_def.name))
1473             return false;
1474       } else {
1475          if (!emit_struct_name(m, type->struct_def.name))
1476             return false;
1477       }
1478    }
1479 
1480    uint64_t temp[256];
1481    assert(type->struct_def.elem.num_types < ARRAY_SIZE(temp) - 2);
1482    temp[0] = type_code;
1483    temp[1] = 0; /* packed */
1484    for (int i = 0; i < type->struct_def.elem.num_types; ++i) {
1485       assert(type->struct_def.elem.types[i]->id >= 0);
1486       temp[2 + i] = type->struct_def.elem.types[i]->id;
1487    }
1488 
1489    return emit_type_table_abbrev_record(m, abbrev, temp,
1490                                         2 + type->struct_def.elem.num_types);
1491 }
1492 
1493 static bool
emit_array_type(struct dxil_module * m,const struct dxil_type * type)1494 emit_array_type(struct dxil_module *m, const struct dxil_type *type)
1495 {
1496    assert(type->array_or_vector_def.elem_type->id >= 0);
1497    uint64_t data[] = {
1498       TYPE_CODE_ARRAY,
1499       type->array_or_vector_def.num_elems,
1500       type->array_or_vector_def.elem_type->id
1501    };
1502    return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_ARRAY, data,
1503                                         ARRAY_SIZE(data));
1504 }
1505 
1506 static bool
emit_function_type(struct dxil_module * m,const struct dxil_type * type)1507 emit_function_type(struct dxil_module *m, const struct dxil_type *type)
1508 {
1509    uint64_t temp[256];
1510    assert(type->function_def.args.num_types < ARRAY_SIZE(temp) - 3);
1511    assert(type->function_def.ret_type->id >= 0);
1512 
1513    temp[0] = TYPE_CODE_FUNCTION;
1514    temp[1] = 0; // vararg
1515    temp[2] = type->function_def.ret_type->id;
1516    for (int i = 0; i < type->function_def.args.num_types; ++i) {
1517       assert(type->function_def.args.types[i]->id >= 0);
1518       temp[3 + i] = type->function_def.args.types[i]->id;
1519    }
1520 
1521    return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_FUNCTION,
1522                                         temp, 3 + type->function_def.args.num_types);
1523 }
1524 
1525 static bool
emit_vector_type(struct dxil_module * m,const struct dxil_type * type)1526 emit_vector_type(struct dxil_module *m, const struct dxil_type *type)
1527 {
1528    uint64_t temp[3];
1529    temp[0] = TYPE_CODE_VECTOR;
1530    temp[1] = type->array_or_vector_def.num_elems;
1531    temp[2] = type->array_or_vector_def.elem_type->id;
1532 
1533    return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_VECTOR , temp, 3);
1534 }
1535 
1536 static bool
emit_metadata_type(struct dxil_module * m)1537 emit_metadata_type(struct dxil_module *m)
1538 {
1539    return emit_record(m, TYPE_CODE_METADATA, NULL, 0);
1540 }
1541 
1542 static bool
emit_type(struct dxil_module * m,struct dxil_type * type)1543 emit_type(struct dxil_module *m, struct dxil_type *type)
1544 {
1545    switch (type->type) {
1546    case TYPE_VOID:
1547       return emit_record(m, TYPE_CODE_VOID, NULL, 0);
1548 
1549    case TYPE_INTEGER:
1550       return emit_record_int(m, TYPE_CODE_INTEGER, type->int_bits);
1551 
1552    case TYPE_FLOAT:
1553       return emit_float_type(m, type->float_bits);
1554 
1555    case TYPE_POINTER:
1556       return emit_pointer_type(m, type->ptr_target_type->id);
1557 
1558    case TYPE_STRUCT:
1559       return emit_struct_type(m, type);
1560 
1561    case TYPE_ARRAY:
1562       return emit_array_type(m, type);
1563 
1564    case TYPE_FUNCTION:
1565       return emit_function_type(m, type);
1566 
1567    case TYPE_VECTOR:
1568       return emit_vector_type(m, type);
1569 
1570    default:
1571       unreachable("unexpected type->type");
1572    }
1573 }
1574 
1575 static bool
emit_type_table(struct dxil_module * m)1576 emit_type_table(struct dxil_module *m)
1577 {
1578    if (!enter_subblock(m, DXIL_TYPE_BLOCK, 4) ||
1579        !emit_type_table_abbrevs(m) ||
1580        !emit_record_int(m, 1, 1 + list_length(&m->type_list)))
1581       return false;
1582 
1583    list_for_each_entry(struct dxil_type, type, &m->type_list, head) {
1584       if (!emit_type(m, type))
1585          return false;
1586    }
1587 
1588    return emit_metadata_type(m) &&
1589           exit_block(m);
1590 }
1591 
1592 static struct dxil_const *
create_const(struct dxil_module * m,const struct dxil_type * type,bool undef)1593 create_const(struct dxil_module *m, const struct dxil_type *type, bool undef)
1594 {
1595    struct dxil_const *ret = ralloc_size(m->ralloc_ctx,
1596                                         sizeof(struct dxil_const));
1597    if (ret) {
1598       ret->value.id = -1;
1599       ret->value.type = type;
1600       ret->undef = undef;
1601       list_addtail(&ret->head, &m->const_list);
1602    }
1603    return ret;
1604 }
1605 
1606 static const struct dxil_value *
get_int_const(struct dxil_module * m,const struct dxil_type * type,intmax_t value)1607 get_int_const(struct dxil_module *m, const struct dxil_type *type,
1608               intmax_t value)
1609 {
1610    assert(type && type->type == TYPE_INTEGER);
1611 
1612    struct dxil_const *c;
1613    LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
1614       if (c->value.type != type || c->undef)
1615          continue;
1616 
1617       if (c->int_value == value)
1618          return &c->value;
1619    }
1620 
1621    c = create_const(m, type, false);
1622    if (!c)
1623       return NULL;
1624 
1625    c->int_value = value;
1626    return &c->value;
1627 }
1628 
1629 static intmax_t
get_int_from_const_value(const struct dxil_value * value)1630 get_int_from_const_value(const struct dxil_value *value)
1631 {
1632    assert(value->type->type == TYPE_INTEGER);
1633    const struct dxil_const *c = container_of(value, const struct dxil_const, value);
1634    return c->int_value;
1635 }
1636 
1637 const struct dxil_value *
dxil_module_get_int1_const(struct dxil_module * m,bool value)1638 dxil_module_get_int1_const(struct dxil_module *m, bool value)
1639 {
1640    const struct dxil_type *type = get_int1_type(m);
1641    if (!type)
1642       return NULL;
1643 
1644    return get_int_const(m, type, value);
1645 }
1646 
1647 const struct dxil_value *
dxil_module_get_int8_const(struct dxil_module * m,int8_t value)1648 dxil_module_get_int8_const(struct dxil_module *m, int8_t value)
1649 {
1650    const struct dxil_type *type = get_int8_type(m);
1651    if (!type)
1652       return NULL;
1653 
1654    return get_int_const(m, type, value);
1655 }
1656 
1657 const struct dxil_value *
dxil_module_get_int16_const(struct dxil_module * m,int16_t value)1658 dxil_module_get_int16_const(struct dxil_module *m, int16_t value)
1659 {
1660    const struct dxil_type *type = get_int16_type(m);
1661    if (!type)
1662       return NULL;
1663 
1664    return get_int_const(m, type, value);
1665 }
1666 
1667 const struct dxil_value *
dxil_module_get_int32_const(struct dxil_module * m,int32_t value)1668 dxil_module_get_int32_const(struct dxil_module *m, int32_t value)
1669 {
1670    const struct dxil_type *type = get_int32_type(m);
1671    if (!type)
1672       return NULL;
1673 
1674    return get_int_const(m, type, value);
1675 }
1676 
1677 const struct dxil_value *
dxil_module_get_int64_const(struct dxil_module * m,int64_t value)1678 dxil_module_get_int64_const(struct dxil_module *m, int64_t value)
1679 {
1680    const struct dxil_type *type = get_int64_type(m);
1681    if (!type)
1682       return NULL;
1683 
1684    return get_int_const(m, type, value);
1685 }
1686 
1687 const struct dxil_value *
dxil_module_get_int_const(struct dxil_module * m,intmax_t value,unsigned bit_size)1688 dxil_module_get_int_const(struct dxil_module *m, intmax_t value,
1689                           unsigned bit_size)
1690 {
1691    switch (bit_size) {
1692    case 1:
1693       assert(value == 0 || value == 1);
1694       return dxil_module_get_int1_const(m, value);
1695 
1696    case 8:
1697       assert(INT8_MIN <= value && value <= INT8_MAX);
1698       return dxil_module_get_int8_const(m, value);
1699 
1700    case 16:
1701       assert(INT16_MIN <= value && value <= INT16_MAX);
1702       return dxil_module_get_int16_const(m, value);
1703 
1704    case 32:
1705       assert(INT32_MIN <= value && value <= INT32_MAX);
1706       return dxil_module_get_int32_const(m, value);
1707 
1708    case 64:
1709       assert(INT64_MIN <= value && value <= INT64_MAX);
1710       return dxil_module_get_int64_const(m, value);
1711 
1712    default:
1713       unreachable("unsupported bit-width");
1714    }
1715 }
1716 
1717 const struct dxil_value *
dxil_module_get_float16_const(struct dxil_module * m,uint16_t value)1718 dxil_module_get_float16_const(struct dxil_module *m, uint16_t value)
1719 {
1720    const struct dxil_type *type = get_float16_type(m);
1721    if (!type)
1722       return NULL;
1723 
1724    struct dxil_const *c;
1725    LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
1726       if (c->value.type != type || c->undef)
1727          continue;
1728 
1729       if (c->int_value == (uintmax_t)value)
1730          return &c->value;
1731    }
1732 
1733    c = create_const(m, type, false);
1734    if (!c)
1735       return NULL;
1736 
1737    c->int_value = (uintmax_t)value;
1738    return &c->value;
1739 }
1740 
1741 const struct dxil_value *
dxil_module_get_float_const(struct dxil_module * m,float value)1742 dxil_module_get_float_const(struct dxil_module *m, float value)
1743 {
1744    const struct dxil_type *type = get_float32_type(m);
1745    if (!type)
1746       return NULL;
1747 
1748    struct dxil_const *c;
1749    LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
1750       if (c->value.type != type || c->undef)
1751          continue;
1752 
1753       if (c->float_value == value)
1754          return &c->value;
1755    }
1756 
1757    c = create_const(m, type, false);
1758    if (!c)
1759       return NULL;
1760 
1761    c->float_value = value;
1762    return &c->value;
1763 }
1764 
1765 const struct dxil_value *
dxil_module_get_double_const(struct dxil_module * m,double value)1766 dxil_module_get_double_const(struct dxil_module *m, double value)
1767 {
1768    const struct dxil_type *type = get_float64_type(m);
1769    if (!type)
1770       return NULL;
1771 
1772    struct dxil_const *c;
1773    LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
1774       if (c->value.type != type || c->undef)
1775          continue;
1776 
1777       if (c->float_value == value)
1778          return &c->value;
1779    }
1780 
1781    c = create_const(m, type, false);
1782    if (!c)
1783       return NULL;
1784 
1785    c->float_value = value;
1786    return &c->value;
1787 }
1788 
1789 const struct dxil_value *
dxil_module_get_array_const(struct dxil_module * m,const struct dxil_type * type,const struct dxil_value ** values)1790 dxil_module_get_array_const(struct dxil_module *m, const struct dxil_type *type,
1791                             const struct dxil_value **values)
1792 {
1793    assert(type->type == TYPE_ARRAY);
1794    unsigned int num_values = type->array_or_vector_def.num_elems;
1795 
1796    struct dxil_const *c;
1797    LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
1798       if (c->value.type != type || c->undef)
1799          continue;
1800 
1801       if (!memcmp(c->array_values, values, sizeof(*values) * num_values))
1802          return &c->value;
1803    }
1804 
1805    c = create_const(m, type, false);
1806    if (!c)
1807       return NULL;
1808    void *tmp =
1809       ralloc_array(m->ralloc_ctx, struct dxil_value *, num_values);
1810    memcpy(tmp, values, sizeof(*values) * num_values);
1811    c->array_values = tmp;
1812 
1813    return &c->value;
1814 }
1815 
1816 const struct dxil_value *
dxil_module_get_vector_const(struct dxil_module * m,const struct dxil_type * type,const struct dxil_value ** values)1817 dxil_module_get_vector_const(struct dxil_module *m, const struct dxil_type *type,
1818                             const struct dxil_value **values)
1819 {
1820    assert(type->type == TYPE_VECTOR);
1821    unsigned int num_values = type->array_or_vector_def.num_elems;
1822 
1823    struct dxil_const *c;
1824    LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
1825       if (c->value.type != type || c->undef)
1826          continue;
1827 
1828       if (!memcmp(c->vector_values, values, sizeof(*values) * num_values))
1829          return &c->value;
1830    }
1831 
1832    c = create_const(m, type, false);
1833    if (!c)
1834       return NULL;
1835    void *tmp =
1836       ralloc_array(m->ralloc_ctx, struct dxil_value *, num_values);
1837    memcpy(tmp, values, sizeof(*values) * num_values);
1838    c->vector_values = tmp;
1839 
1840    return &c->value;
1841 }
1842 
1843 const struct dxil_value *
dxil_module_get_undef(struct dxil_module * m,const struct dxil_type * type)1844 dxil_module_get_undef(struct dxil_module *m, const struct dxil_type *type)
1845 {
1846    assert(type != NULL);
1847 
1848    struct dxil_const *c;
1849    LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
1850       if (c->value.type != type)
1851          continue;
1852 
1853       if (c->undef)
1854          return &c->value;
1855    }
1856 
1857    c = create_const(m, type, true);
1858    return c ? &c->value : NULL;
1859 }
1860 
1861 const struct dxil_value *
dxil_module_get_struct_const(struct dxil_module * m,const struct dxil_type * type,const struct dxil_value ** values)1862 dxil_module_get_struct_const(struct dxil_module *m, const struct dxil_type *type,
1863                  const struct dxil_value **values)
1864 {
1865    assert(type->type == TYPE_STRUCT);
1866    unsigned int num_values = type->struct_def.elem.num_types;
1867 
1868    struct dxil_const *c;
1869    LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
1870       if (c->value.type != type || c->undef)
1871          continue;
1872 
1873       if (!memcmp(c->struct_values, values, sizeof(*values) * num_values))
1874          return &c->value;
1875    }
1876 
1877    c = create_const(m, type, false);
1878    if (!c)
1879       return NULL;
1880    void *tmp =
1881       ralloc_array(m->ralloc_ctx, struct dxil_value *, num_values);
1882    memcpy(tmp, values, sizeof(*values) * num_values);
1883    c->struct_values = tmp;
1884 
1885    return &c->value;
1886 }
1887 
1888 const struct dxil_value *
dxil_module_get_res_bind_const(struct dxil_module * m,uint32_t lower_bound,uint32_t upper_bound,uint32_t space,uint8_t class)1889 dxil_module_get_res_bind_const(struct dxil_module *m,
1890                                uint32_t lower_bound,
1891                                uint32_t upper_bound,
1892                                uint32_t space,
1893                                uint8_t class)
1894 {
1895    const struct dxil_type *type = dxil_module_get_res_bind_type(m);
1896    const struct dxil_type *int32_type = dxil_module_get_int_type(m, 32);
1897    const struct dxil_type *int8_type = dxil_module_get_int_type(m, 8);
1898    if (!type || !int32_type || !int8_type)
1899       return NULL;
1900 
1901    const struct dxil_value *values[4] = {
1902       get_int_const(m, int32_type, lower_bound),
1903       get_int_const(m, int32_type, upper_bound),
1904       get_int_const(m, int32_type, space),
1905       get_int_const(m, int8_type, class),
1906    };
1907    if (!values[0] || !values[1] || !values[2] || !values[3])
1908       return NULL;
1909 
1910    return dxil_module_get_struct_const(m, type, values);
1911 }
1912 
1913 static uint32_t
get_basic_srv_uav_res_props_dword(bool uav,bool rov,bool globally_coherent,bool has_counter,enum dxil_resource_kind kind)1914 get_basic_srv_uav_res_props_dword(bool uav,
1915                                   bool rov,
1916                                   bool globally_coherent,
1917                                   bool has_counter,
1918                                   enum dxil_resource_kind kind)
1919 {
1920    union {
1921       uint32_t raw;
1922       struct {
1923          uint8_t kind;
1924 
1925          uint8_t base_align_log2 : 4;
1926          uint8_t uav : 1;
1927          uint8_t rov : 1;
1928          uint8_t globally_coherent : 1;
1929          uint8_t has_counter : 1;
1930       };
1931    } basic;
1932    basic.raw = 0;
1933    basic.kind = kind;
1934    basic.uav = uav;
1935    basic.rov = rov;
1936    basic.globally_coherent = globally_coherent;
1937    basic.has_counter = has_counter;
1938    return basic.raw;
1939 }
1940 
1941 static uint32_t
get_typed_srv_uav_res_props_dword(enum dxil_component_type comp_type,uint8_t num_components,uint8_t sample_count)1942 get_typed_srv_uav_res_props_dword(enum dxil_component_type comp_type,
1943                                   uint8_t num_components,
1944                                   uint8_t sample_count)
1945 {
1946    union {
1947       uint32_t raw;
1948       struct {
1949          uint8_t comp_type;
1950          uint8_t num_components;
1951          uint8_t sample_count;
1952       };
1953    } type;
1954    type.raw = 0;
1955    type.comp_type = comp_type;
1956    type.num_components = num_components;
1957    type.sample_count = sample_count;
1958    return type.raw;
1959 }
1960 
1961 static uint32_t
get_sampler_res_props_dword(bool comparison)1962 get_sampler_res_props_dword(bool comparison)
1963 {
1964    union {
1965       uint32_t raw;
1966       struct {
1967          uint8_t kind;
1968 
1969          uint8_t padding : 7;
1970          uint8_t comparison : 1;
1971       };
1972    } basic;
1973    basic.raw = 0;
1974    basic.kind = DXIL_RESOURCE_KIND_SAMPLER;
1975    basic.comparison = comparison;
1976    return basic.raw;
1977 }
1978 
1979 static intmax_t
get_int_from_mdnode(const struct dxil_mdnode * mdnode,int subnode)1980 get_int_from_mdnode(const struct dxil_mdnode *mdnode, int subnode)
1981 {
1982    assert(mdnode->type == MD_NODE);
1983    assert(mdnode->node.subnodes[subnode]->type == MD_VALUE);
1984    return get_int_from_const_value(mdnode->node.subnodes[subnode]->value.value);
1985 }
1986 
1987 static void
fill_res_props_dwords(uint32_t dwords[2],enum dxil_resource_class class,const struct dxil_mdnode * mdnode)1988 fill_res_props_dwords(uint32_t dwords[2],
1989                       enum dxil_resource_class class,
1990                       const struct dxil_mdnode *mdnode)
1991 {
1992    enum dxil_resource_kind kind = DXIL_RESOURCE_KIND_INVALID;
1993    uint32_t sample_count = 0;
1994    switch (class) {
1995    case DXIL_RESOURCE_CLASS_SRV:
1996       kind = (enum dxil_resource_kind)get_int_from_mdnode(mdnode, 6);
1997       dwords[0] = get_basic_srv_uav_res_props_dword(false, false, false, false, kind);
1998       sample_count = get_int_from_mdnode(mdnode, 7);
1999       break;
2000    case DXIL_RESOURCE_CLASS_UAV:
2001       kind = (enum dxil_resource_kind)get_int_from_mdnode(mdnode, 6);
2002       dwords[0] = get_basic_srv_uav_res_props_dword(true,
2003          get_int_from_mdnode(mdnode, 9),
2004          get_int_from_mdnode(mdnode, 7),
2005          get_int_from_mdnode(mdnode, 8),
2006          kind);
2007       break;
2008    case DXIL_RESOURCE_CLASS_CBV:
2009       kind = DXIL_RESOURCE_KIND_CBUFFER;
2010       dwords[0] = kind;
2011       break;
2012    case DXIL_RESOURCE_CLASS_SAMPLER:
2013       kind = DXIL_RESOURCE_KIND_SAMPLER;
2014       dwords[0] = get_sampler_res_props_dword(get_int_from_mdnode(mdnode, 6) == DXIL_SAMPLER_KIND_COMPARISON);
2015       break;
2016    default:
2017       unreachable("Unexpected resource class");
2018    }
2019 
2020    switch (kind) {
2021    case DXIL_RESOURCE_KIND_STRUCTURED_BUFFER:
2022    case DXIL_RESOURCE_KIND_INVALID:
2023       unreachable("Unimplemented");
2024    case DXIL_RESOURCE_KIND_RAW_BUFFER:
2025    case DXIL_RESOURCE_KIND_SAMPLER:
2026       dwords[1] = 0;
2027       break;
2028    case DXIL_RESOURCE_KIND_CBUFFER:
2029       dwords[1] = get_int_from_mdnode(mdnode, 6);
2030       break;
2031    default: {
2032       unsigned tag_array_index = class == DXIL_RESOURCE_CLASS_SRV ? 8 : 10;
2033       const struct dxil_type *res_ptr_type = mdnode->node.subnodes[1]->value.type;
2034       const struct dxil_type *res_type = res_ptr_type->ptr_target_type->type == TYPE_ARRAY ?
2035          res_ptr_type->ptr_target_type->array_or_vector_def.elem_type : res_ptr_type->ptr_target_type;
2036       const struct dxil_type *vec_type = res_type->struct_def.elem.types[0];
2037       dwords[1] = get_typed_srv_uav_res_props_dword(
2038          (enum dxil_component_type)get_int_from_mdnode(
2039             mdnode->node.subnodes[tag_array_index], 1),
2040          vec_type->array_or_vector_def.num_elems,
2041          sample_count);
2042       break;
2043       }
2044    }
2045 }
2046 
2047 const struct dxil_value *
dxil_module_get_res_props_const(struct dxil_module * m,enum dxil_resource_class class,const struct dxil_mdnode * mdnode)2048 dxil_module_get_res_props_const(struct dxil_module *m,
2049                                 enum dxil_resource_class class,
2050                                 const struct dxil_mdnode *mdnode)
2051 {
2052    const struct dxil_type *type = dxil_module_get_res_props_type(m);
2053    if (!type)
2054       return NULL;
2055 
2056    uint32_t dwords[2];
2057    fill_res_props_dwords(dwords, class, mdnode);
2058 
2059    const struct dxil_value *values[2] = {
2060       dxil_module_get_int32_const(m, dwords[0]),
2061       dxil_module_get_int32_const(m, dwords[1])
2062    };
2063    if (!values[0] || !values[1])
2064       return NULL;
2065 
2066    return dxil_module_get_struct_const(m, type, values);
2067 }
2068 
2069 static enum dxil_component_type
comp_type_from_alu_type(nir_alu_type type)2070 comp_type_from_alu_type(nir_alu_type type)
2071 {
2072    switch (type & NIR_ALU_TYPE_BASE_TYPE_MASK)
2073    {
2074    case nir_type_int: return DXIL_COMP_TYPE_I32;
2075    case nir_type_uint: return DXIL_COMP_TYPE_U32;
2076    case nir_type_float: return DXIL_COMP_TYPE_F32;
2077    default: unreachable("Unexpected component type");
2078    }
2079 }
2080 
2081 const struct dxil_value *
dxil_module_get_srv_res_props_const(struct dxil_module * m,const nir_tex_instr * tex)2082 dxil_module_get_srv_res_props_const(struct dxil_module *m,
2083                                     const nir_tex_instr *tex)
2084 {
2085    const struct dxil_type *type = dxil_module_get_res_props_type(m);
2086    if (!type)
2087       return NULL;
2088 
2089    uint32_t dwords[2];
2090    dwords[0] = get_basic_srv_uav_res_props_dword(false, false, false, false,
2091                                                  dxil_sampler_dim_to_resource_kind(tex->sampler_dim, tex->is_array));
2092    dwords[1] = get_typed_srv_uav_res_props_dword(comp_type_from_alu_type(tex->dest_type),
2093                                                  nir_tex_instr_dest_size(tex),
2094                                                  0);
2095 
2096    const struct dxil_value *values[2] = {
2097       dxil_module_get_int32_const(m, dwords[0]),
2098       dxil_module_get_int32_const(m, dwords[1])
2099    };
2100    if (!values[0] || !values[1])
2101       return NULL;
2102 
2103    return dxil_module_get_struct_const(m, type, values);
2104 }
2105 
2106 const struct dxil_value *
dxil_module_get_sampler_res_props_const(struct dxil_module * m,bool is_shadow)2107 dxil_module_get_sampler_res_props_const(struct dxil_module *m,
2108                                         bool is_shadow)
2109 {
2110    const struct dxil_type *type = dxil_module_get_res_props_type(m);
2111    if (!type)
2112       return NULL;
2113 
2114    uint32_t dwords[2] = { get_sampler_res_props_dword(is_shadow), 0 };
2115 
2116    const struct dxil_value *values[2] = {
2117       dxil_module_get_int32_const(m, dwords[0]),
2118       dxil_module_get_int32_const(m, dwords[1])
2119    };
2120    if (!values[0] || !values[1])
2121       return NULL;
2122 
2123    return dxil_module_get_struct_const(m, type, values);
2124 }
2125 
2126 static nir_alu_type
alu_type_from_image_intr(nir_intrinsic_instr * intr)2127 alu_type_from_image_intr(nir_intrinsic_instr *intr)
2128 {
2129    switch (intr->intrinsic)
2130    {
2131    case nir_intrinsic_image_load:
2132    case nir_intrinsic_image_deref_load:
2133    case nir_intrinsic_bindless_image_load:
2134       return nir_intrinsic_dest_type(intr);
2135    case nir_intrinsic_image_store:
2136    case nir_intrinsic_image_deref_store:
2137    case nir_intrinsic_bindless_image_store:
2138       return nir_intrinsic_src_type(intr);
2139    default:
2140       if (nir_intrinsic_has_atomic_op(intr))
2141          return nir_atomic_op_type(nir_intrinsic_atomic_op(intr));
2142       return nir_type_uint;
2143    }
2144 }
2145 
2146 const struct dxil_value *
dxil_module_get_uav_res_props_const(struct dxil_module * m,nir_intrinsic_instr * intr)2147 dxil_module_get_uav_res_props_const(struct dxil_module *m,
2148                                     nir_intrinsic_instr *intr)
2149 {
2150    const struct dxil_type *type = dxil_module_get_res_props_type(m);
2151    if (!type)
2152       return NULL;
2153 
2154    uint32_t dwords[2];
2155    enum gl_access_qualifier access = nir_intrinsic_has_access(intr) ? nir_intrinsic_access(intr) : 0;
2156    dwords[0] = get_basic_srv_uav_res_props_dword(true, false, (access & ACCESS_COHERENT) != 0, false,
2157                                                  dxil_sampler_dim_to_resource_kind(nir_intrinsic_image_dim(intr),
2158                                                                                    nir_intrinsic_image_array(intr)));
2159    unsigned num_comps = intr->num_components ? intr->num_components : 1;
2160    if (nir_intrinsic_has_format(intr)) {
2161       enum pipe_format format = nir_intrinsic_format(intr);
2162       if (format != PIPE_FORMAT_NONE)
2163          num_comps = util_format_get_nr_components(format);
2164    }
2165    dwords[1] = get_typed_srv_uav_res_props_dword(comp_type_from_alu_type(alu_type_from_image_intr(intr)),
2166                                                  num_comps, 0);
2167 
2168    const struct dxil_value *values[2] = {
2169       dxil_module_get_int32_const(m, dwords[0]),
2170       dxil_module_get_int32_const(m, dwords[1])
2171    };
2172    if (!values[0] || !values[1])
2173       return NULL;
2174 
2175    return dxil_module_get_struct_const(m, type, values);
2176 }
2177 
2178 const struct dxil_value *
dxil_module_get_buffer_res_props_const(struct dxil_module * m,enum dxil_resource_class class,enum dxil_resource_kind kind)2179 dxil_module_get_buffer_res_props_const(struct dxil_module *m,
2180                                        enum dxil_resource_class class,
2181                                        enum dxil_resource_kind kind)
2182 {
2183    const struct dxil_type *type = dxil_module_get_res_props_type(m);
2184    if (!type)
2185       return NULL;
2186 
2187    uint32_t dwords[2];
2188    if (class == DXIL_RESOURCE_CLASS_CBV) {
2189       dwords[0] = kind;
2190       dwords[1] = 4096 /* vec4s */ * 4 /* components */ * 4 /* bytes */;
2191    } else {
2192       dwords[0] = get_basic_srv_uav_res_props_dword(class == DXIL_RESOURCE_CLASS_UAV,
2193                                                     false, false /*TODO*/, false,
2194                                                     kind);
2195       dwords[1] = 0;
2196    }
2197 
2198    const struct dxil_value *values[2] = {
2199       dxil_module_get_int32_const(m, dwords[0]),
2200       dxil_module_get_int32_const(m, dwords[1])
2201    };
2202    if (!values[0] || !values[1])
2203       return NULL;
2204 
2205    return dxil_module_get_struct_const(m, type, values);
2206 }
2207 
2208 enum dxil_module_code {
2209    DXIL_MODULE_CODE_VERSION = 1,
2210    DXIL_MODULE_CODE_TRIPLE = 2,
2211    DXIL_MODULE_CODE_DATALAYOUT = 3,
2212    DXIL_MODULE_CODE_ASM = 4,
2213    DXIL_MODULE_CODE_SECTIONNAME = 5,
2214    DXIL_MODULE_CODE_DEPLIB = 6,
2215    DXIL_MODULE_CODE_GLOBALVAR = 7,
2216    DXIL_MODULE_CODE_FUNCTION = 8,
2217    DXIL_MODULE_CODE_ALIAS = 9,
2218    DXIL_MODULE_CODE_PURGEVALS = 10,
2219    DXIL_MODULE_CODE_GCNAME = 11,
2220    DXIL_MODULE_CODE_COMDAT = 12,
2221 };
2222 
2223 static bool
emit_target_triple(struct dxil_module * m,const char * triple)2224 emit_target_triple(struct dxil_module *m, const char *triple)
2225 {
2226    uint64_t temp[256];
2227    assert(strlen(triple) < ARRAY_SIZE(temp));
2228 
2229    for (int i = 0; i < strlen(triple); ++i)
2230       temp[i] = triple[i];
2231 
2232    return emit_record(m, DXIL_MODULE_CODE_TRIPLE, temp, strlen(triple));
2233 }
2234 
2235 static bool
emit_datalayout(struct dxil_module * m,const char * datalayout)2236 emit_datalayout(struct dxil_module *m, const char *datalayout)
2237 {
2238    uint64_t temp[256];
2239    assert(strlen(datalayout) < ARRAY_SIZE(temp));
2240 
2241    for (int i = 0; i < strlen(datalayout); ++i)
2242       temp[i] = datalayout[i];
2243 
2244    return emit_record(m, DXIL_MODULE_CODE_DATALAYOUT,
2245                       temp, strlen(datalayout));
2246 }
2247 
2248 static const struct dxil_value *
add_gvar(struct dxil_module * m,const char * name,const struct dxil_type * type,const struct dxil_type * value_type,enum dxil_address_space as,int align,const struct dxil_value * value)2249 add_gvar(struct dxil_module *m, const char *name,
2250          const struct dxil_type *type, const struct dxil_type *value_type,
2251          enum dxil_address_space as, int align, const struct dxil_value *value)
2252 {
2253    struct dxil_gvar *gvar = ralloc_size(m->ralloc_ctx,
2254                                         sizeof(struct dxil_gvar));
2255    if (!gvar)
2256       return NULL;
2257 
2258    gvar->type = type;
2259    gvar->name = ralloc_strdup(m->ralloc_ctx, name);
2260    gvar->as = as;
2261    gvar->align = align;
2262    gvar->constant = !!value;
2263    gvar->initializer = value;
2264 
2265    gvar->value.id = -1;
2266    gvar->value.type = value_type;
2267 
2268    list_addtail(&gvar->head, &m->gvar_list);
2269    return &gvar->value;
2270 }
2271 
2272 const struct dxil_value *
dxil_add_global_var(struct dxil_module * m,const char * name,const struct dxil_type * type,enum dxil_address_space as,int align,const struct dxil_value * value)2273 dxil_add_global_var(struct dxil_module *m, const char *name,
2274                     const struct dxil_type *type,
2275                     enum dxil_address_space as, int align,
2276                     const struct dxil_value *value)
2277 {
2278    return add_gvar(m, name, type, type, as, align, value);
2279 }
2280 
2281 const struct dxil_value *
dxil_add_global_ptr_var(struct dxil_module * m,const char * name,const struct dxil_type * type,enum dxil_address_space as,int align,const struct dxil_value * value)2282 dxil_add_global_ptr_var(struct dxil_module *m, const char *name,
2283                         const struct dxil_type *type,
2284                         enum dxil_address_space as, int align,
2285                         const struct dxil_value *value)
2286 {
2287    return add_gvar(m, name, type, dxil_module_get_pointer_type(m, type),
2288                    as, align, value);
2289 }
2290 
2291 static const struct dxil_func *
add_function(struct dxil_module * m,const char * name,const struct dxil_type * type,bool decl,unsigned attr_set)2292 add_function(struct dxil_module *m, const char *name,
2293              const struct dxil_type *type,
2294              bool decl, unsigned attr_set)
2295 {
2296    assert(type->type == TYPE_FUNCTION);
2297 
2298    struct dxil_func *func = ralloc_size(m->ralloc_ctx,
2299                                         sizeof(struct dxil_func));
2300    if (!func)
2301       return NULL;
2302 
2303    /* Truncate function name to make emit_symtab_entry() happy. */
2304    func->name = ralloc_strndup(func, name, 253);
2305    if (!func->name) {
2306       return NULL;
2307    }
2308 
2309    func->type = type;
2310    func->decl = decl;
2311    func->attr_set = attr_set;
2312 
2313    func->value.id = -1;
2314    func->value.type  = type->function_def.ret_type;
2315    list_addtail(&func->head, &m->func_list);
2316    return func;
2317 }
2318 
attrs_equal(const struct dxil_attrib * a,const struct dxil_attrib * b)2319 static bool attrs_equal(const struct dxil_attrib *a, const struct dxil_attrib *b)
2320 {
2321    if (a->type != b->type)
2322       return false;
2323    switch (a->type) {
2324    case DXIL_ATTR_ENUM:
2325       return a->key.kind == b->key.kind;
2326    case DXIL_ATTR_ENUM_VALUE:
2327       return a->key.kind == b->key.kind && a->value.integer == b->value.integer;
2328    case DXIL_ATTR_STRING:
2329       return a->key.str == b->key.str || !strcmp(a->key.str, b->key.str);
2330    case DXIL_ATTR_STRING_VALUE:
2331       return (a->key.str == b->key.str || !strcmp(a->key.str, b->key.str)) &&
2332          (a->value.str == b->value.str || !strcmp(a->value.str, b->value.str));
2333    default:
2334       unreachable("Invalid attr type");
2335    }
2336 }
2337 
attr_sets_equal(unsigned num_attrs,const struct dxil_attrib * a,const struct dxil_attrib * b)2338 static bool attr_sets_equal(unsigned num_attrs, const struct dxil_attrib *a, const struct dxil_attrib *b)
2339 {
2340    for (unsigned i = 0; i < num_attrs; ++i) {
2341       if (!attrs_equal(&a[i], &b[i]))
2342          return false;
2343    }
2344    return true;
2345 }
2346 
2347 static unsigned
dxil_get_string_attr_set(struct dxil_module * m,const char * const * attr_keys,const char * const * attr_values)2348 dxil_get_string_attr_set(struct dxil_module *m,
2349                          const char *const *attr_keys, const char *const *attr_values)
2350 {
2351    if (!attr_keys)
2352       return 0;
2353 
2354    struct dxil_attrib attrs[2];
2355    unsigned num_attrs = 0;
2356    for (; num_attrs < ARRAY_SIZE(attrs) && attr_keys[num_attrs]; ++num_attrs) {
2357       if (attr_values && attr_values[num_attrs])
2358          attrs[num_attrs] = (struct dxil_attrib){ DXIL_ATTR_STRING_VALUE, {.str = attr_keys[num_attrs]}, {.str = attr_values[num_attrs]} };
2359       else
2360          attrs[num_attrs] = (struct dxil_attrib){ DXIL_ATTR_STRING, {.str = attr_keys[num_attrs]} };
2361    }
2362 
2363    if (num_attrs == 0)
2364       return 0;
2365 
2366    int index = 1;
2367    struct attrib_set *as;
2368    LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) {
2369       if (as->num_attrs == num_attrs && attr_sets_equal(num_attrs, as->attrs, attrs))
2370          return index;
2371       index++;
2372    }
2373 
2374    as = ralloc_size(m->ralloc_ctx, sizeof(struct attrib_set));
2375    if (!as)
2376       return 0;
2377 
2378    memcpy(as->attrs, attrs, sizeof(attrs));
2379    as->num_attrs = num_attrs;
2380 
2381    list_addtail(&as->head, &m->attr_set_list);
2382    assert(list_length(&m->attr_set_list) == index);
2383    return index;
2384 }
2385 
2386 struct dxil_func_def *
dxil_add_function_def(struct dxil_module * m,const char * name,const struct dxil_type * type,unsigned num_blocks,const char * const * attr_keys,const char * const * attr_values)2387 dxil_add_function_def(struct dxil_module *m, const char *name,
2388                       const struct dxil_type *type, unsigned num_blocks,
2389                       const char *const *attr_keys, const char *const *attr_values)
2390 {
2391    struct dxil_func_def *def = ralloc_size(m->ralloc_ctx, sizeof(struct dxil_func_def));
2392 
2393    unsigned attr_index = dxil_get_string_attr_set(m, attr_keys, attr_values);
2394    def->func = add_function(m, name, type, false, attr_index);
2395    if (!def->func)
2396       return NULL;
2397 
2398    list_inithead(&def->instr_list);
2399    def->curr_block = 0;
2400 
2401    assert(num_blocks > 0);
2402    def->basic_block_ids = rzalloc_array(m->ralloc_ctx, int,
2403                                         num_blocks);
2404    if (!def->basic_block_ids)
2405       return NULL;
2406 
2407    for (int i = 0; i < num_blocks; ++i)
2408       def->basic_block_ids[i] = -1;
2409    def->num_basic_block_ids = num_blocks;
2410 
2411    list_addtail(&def->head, &m->func_def_list);
2412    m->cur_emitting_func = def;
2413 
2414    return def;
2415 }
2416 
2417 static unsigned
get_attr_set(struct dxil_module * m,enum dxil_attr_kind attr)2418 get_attr_set(struct dxil_module *m, enum dxil_attr_kind attr)
2419 {
2420    struct dxil_attrib attrs[2] = {
2421       { DXIL_ATTR_ENUM, { DXIL_ATTR_KIND_NO_UNWIND } },
2422       { DXIL_ATTR_ENUM, { attr } }
2423    };
2424 
2425    unsigned num_attrs = attr == DXIL_ATTR_KIND_NONE ? 1 : 2;
2426    int index = 1;
2427    struct attrib_set *as;
2428    LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) {
2429       if (as->num_attrs == num_attrs && attr_sets_equal(num_attrs, as->attrs, attrs))
2430          return index;
2431       index++;
2432    }
2433 
2434    as = ralloc_size(m->ralloc_ctx, sizeof(struct attrib_set));
2435    if (!as)
2436       return 0;
2437 
2438    memcpy(as->attrs, attrs, sizeof(attrs));
2439    as->num_attrs = num_attrs;
2440 
2441    list_addtail(&as->head, &m->attr_set_list);
2442    assert(list_length(&m->attr_set_list) == index);
2443    return index;
2444 }
2445 
2446 const struct dxil_func *
dxil_add_function_decl(struct dxil_module * m,const char * name,const struct dxil_type * type,enum dxil_attr_kind attr)2447 dxil_add_function_decl(struct dxil_module *m, const char *name,
2448                        const struct dxil_type *type,
2449                        enum dxil_attr_kind attr)
2450 {
2451    unsigned attr_set = get_attr_set(m, attr);
2452    if (!attr_set)
2453       return NULL;
2454 
2455    return add_function(m, name, type, true, attr_set);
2456 }
2457 
2458 static bool
emit_module_info_function(struct dxil_module * m,int type,bool declaration,int attr_set_index)2459 emit_module_info_function(struct dxil_module *m, int type, bool declaration,
2460                           int attr_set_index)
2461 {
2462    uint64_t data[] = {
2463       type, 0/* address space */, declaration, 0/* linkage */,
2464       attr_set_index, 0/* alignment */, 0 /* section */, 0 /* visibility */,
2465       0 /* GC */, 0 /* unnamed addr */, 0 /* prologue data */,
2466       0 /* storage class */, 0 /* comdat */, 0 /* prefix-data */,
2467       0 /* personality */
2468    };
2469    return emit_record(m, DXIL_MODULE_CODE_FUNCTION, data, ARRAY_SIZE(data));
2470 }
2471 
2472 enum gvar_var_flags {
2473    GVAR_FLAG_CONSTANT = (1 << 0),
2474    GVAR_FLAG_EXPLICIT_TYPE = (1 << 1),
2475 };
2476 
2477 enum gvar_var_linkage {
2478    GVAR_LINKAGE_EXTERNAL = 0,
2479    GVAR_LINKAGE_APPENDING = 2,
2480    GVAR_LINKAGE_INTERNAL = 3,
2481    GVAR_LINKAGE_EXTERNAL_WEAK = 7,
2482    GVAR_LINKAGE_COMMON = 8,
2483    GVAR_LINKAGE_PRIVATE = 9,
2484    GVAR_LINKAGE_AVAILABLE_EXTERNALLY = 12,
2485    GVAR_LINKAGE_WEAK_ANY = 16,
2486    GVAR_LINKAGE_WEAK_ODR = 17,
2487    GVAR_LINKAGE_LINK_ONCE_ODR = 19,
2488 };
2489 
2490 static bool
emit_module_info_global(struct dxil_module * m,const struct dxil_gvar * gvar,const struct dxil_abbrev * simple_gvar_abbr)2491 emit_module_info_global(struct dxil_module *m, const struct dxil_gvar *gvar,
2492                         const struct dxil_abbrev *simple_gvar_abbr)
2493 {
2494    uint64_t data[] = {
2495       DXIL_MODULE_CODE_GLOBALVAR,
2496       gvar->type->id,
2497       (gvar->as << 2) | GVAR_FLAG_EXPLICIT_TYPE |
2498       (gvar->constant ? GVAR_FLAG_CONSTANT : 0),
2499       gvar->initializer ? gvar->initializer->id + 1 : 0,
2500       (gvar->initializer ? GVAR_LINKAGE_INTERNAL : GVAR_LINKAGE_EXTERNAL),
2501       util_logbase2(gvar->align) + 1,
2502       0
2503    };
2504    return emit_record_abbrev(&m->buf, 4, simple_gvar_abbr,
2505                              data, ARRAY_SIZE(data));
2506 }
2507 
2508 static bool
emit_module_info(struct dxil_module * m)2509 emit_module_info(struct dxil_module *m)
2510 {
2511    struct dxil_gvar *gvar;
2512    int max_global_type = 0;
2513    int max_alignment = 0;
2514    LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) {
2515       assert(gvar->type->id >= 0);
2516       max_global_type = MAX2(max_global_type, gvar->type->id);
2517       max_alignment = MAX2(max_alignment, gvar->align);
2518    }
2519 
2520    struct dxil_abbrev simple_gvar_abbr = {
2521       { LITERAL(DXIL_MODULE_CODE_GLOBALVAR),
2522         FIXED(util_logbase2(max_global_type) + 1),
2523         VBR(6), VBR(6), FIXED(5),
2524         FIXED(util_logbase2(max_alignment) + 1),
2525         LITERAL(0) }, 7
2526    };
2527 
2528    if (!emit_target_triple(m, "dxil-ms-dx") ||
2529        !emit_datalayout(m, "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64") ||
2530        !define_abbrev(m, &simple_gvar_abbr))
2531       return false;
2532 
2533    LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) {
2534       assert(gvar->type->id >= 0);
2535       if (!emit_module_info_global(m, gvar, &simple_gvar_abbr))
2536          return false;
2537    }
2538 
2539    struct dxil_func *func;
2540    LIST_FOR_EACH_ENTRY(func, &m->func_list, head) {
2541       assert(func->type->id >= 0);
2542       if (!emit_module_info_function(m, func->type->id, func->decl,
2543                                      func->attr_set))
2544          return false;
2545    }
2546 
2547    return true;
2548 }
2549 
2550 static bool
emit_module_const_abbrevs(struct dxil_module * m)2551 emit_module_const_abbrevs(struct dxil_module *m)
2552 {
2553    /* these are unused for now, so let's not even record them */
2554    struct dxil_abbrev abbrevs[] = {
2555       { { LITERAL(CST_CODE_AGGREGATE), ARRAY, FIXED(5) }, 3 },
2556       { { LITERAL(CST_CODE_STRING), ARRAY, FIXED(8) }, 3 },
2557       { { LITERAL(CST_CODE_CSTRING), ARRAY, FIXED(7) }, 3 },
2558       { { LITERAL(CST_CODE_CSTRING), ARRAY, CHAR6 }, 3 },
2559    };
2560 
2561    for (int i = 0; i < ARRAY_SIZE(abbrevs); ++i) {
2562       if (!define_abbrev(m, abbrevs + i))
2563          return false;
2564    }
2565 
2566    return true;
2567 }
2568 
2569 static bool
emit_set_type(struct dxil_module * m,unsigned type_index)2570 emit_set_type(struct dxil_module *m, unsigned type_index)
2571 {
2572    uint64_t data[] = { CST_CODE_SETTYPE, type_index };
2573    return emit_const_abbrev_record(m, CONST_ABBREV_SETTYPE,
2574                                    data, ARRAY_SIZE(data));
2575 }
2576 
2577 static bool
emit_null_value(struct dxil_module * m)2578 emit_null_value(struct dxil_module *m)
2579 {
2580    return emit_record_no_abbrev(&m->buf, CST_CODE_NULL, NULL, 0);
2581 }
2582 
2583 static bool
emit_undef_value(struct dxil_module * m)2584 emit_undef_value(struct dxil_module *m)
2585 {
2586    return emit_record_no_abbrev(&m->buf, CST_CODE_UNDEF, NULL, 0);
2587 }
2588 
2589 static uint64_t
encode_signed(int64_t value)2590 encode_signed(int64_t value)
2591 {
2592    return value >= 0 ?
2593       (value << 1) :
2594       ((-value << 1) | 1);
2595 }
2596 
2597 static bool
emit_int_value(struct dxil_module * m,int64_t value)2598 emit_int_value(struct dxil_module *m, int64_t value)
2599 {
2600    if (!value)
2601       return emit_null_value(m);
2602 
2603    uint64_t data[] = { CST_CODE_INTEGER, encode_signed(value) };
2604    return emit_const_abbrev_record(m, CONST_ABBREV_INTEGER,
2605                                    data, ARRAY_SIZE(data));
2606 }
2607 
2608 static bool
emit_float16_value(struct dxil_module * m,uint16_t value)2609 emit_float16_value(struct dxil_module *m, uint16_t value)
2610 {
2611    if (!value)
2612       return emit_null_value(m);
2613    uint64_t data = value;
2614    return emit_record_no_abbrev(&m->buf, CST_CODE_FLOAT, &data, 1);
2615 }
2616 
2617 static bool
emit_float_value(struct dxil_module * m,float value)2618 emit_float_value(struct dxil_module *m, float value)
2619 {
2620    uint64_t data = fui(value);
2621    if (data == UINT32_C(0))
2622       return emit_null_value(m);
2623    return emit_record_no_abbrev(&m->buf, CST_CODE_FLOAT, &data, 1);
2624 }
2625 
2626 static bool
emit_double_value(struct dxil_module * m,double value)2627 emit_double_value(struct dxil_module *m, double value)
2628 {
2629    union di u;
2630    u.d = value;
2631    if (u.ui == UINT64_C(0))
2632       return emit_null_value(m);
2633    return emit_record_no_abbrev(&m->buf, CST_CODE_FLOAT, &u.ui, 1);
2634 }
2635 
2636 static bool
emit_aggregate_values(struct dxil_module * m,const struct dxil_value ** values,int num_values)2637 emit_aggregate_values(struct dxil_module *m, const struct dxil_value **values,
2638                       int num_values)
2639 {
2640    uint64_t *value_ids = ralloc_array(m->ralloc_ctx, uint64_t, num_values);
2641    int i;
2642 
2643    for (i = 0; i < num_values; i++)
2644       value_ids[i] = values[i]->id;
2645 
2646    return emit_record_no_abbrev(&m->buf, CST_CODE_AGGREGATE, value_ids,
2647                                 num_values);
2648 }
2649 
2650 static bool
emit_consts(struct dxil_module * m)2651 emit_consts(struct dxil_module *m)
2652 {
2653    const struct dxil_type *curr_type = NULL;
2654    struct dxil_const *c;
2655    LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
2656       assert(c->value.id >= 0);
2657       assert(c->value.type != NULL);
2658       if (curr_type != c->value.type) {
2659          assert(c->value.type->id >= 0);
2660          if (!emit_set_type(m, c->value.type->id))
2661             return false;
2662          curr_type = c->value.type;
2663       }
2664 
2665       if (c->undef) {
2666          if (!emit_undef_value(m))
2667             return false;
2668          continue;
2669       }
2670 
2671       switch (curr_type->type) {
2672       case TYPE_INTEGER:
2673          if (!emit_int_value(m, c->int_value))
2674             return false;
2675          break;
2676 
2677       case TYPE_FLOAT:
2678          switch (curr_type->float_bits) {
2679          case 16:
2680             if (!emit_float16_value(m, (uint16_t)(uintmax_t)c->int_value))
2681                return false;
2682             break;
2683          case 32:
2684             if (!emit_float_value(m, c->float_value))
2685                return false;
2686             break;
2687          case 64:
2688             if (!emit_double_value(m, c->float_value))
2689                return false;
2690             break;
2691          default:
2692             unreachable("unexpected float_bits");
2693          }
2694          break;
2695 
2696       case TYPE_ARRAY:
2697          if (!emit_aggregate_values(m, c->array_values,
2698                                     c->value.type->array_or_vector_def.num_elems))
2699             return false;
2700          break;
2701 
2702       case TYPE_STRUCT:
2703          if (!emit_aggregate_values(m, c->struct_values,
2704                                     c->value.type->struct_def.elem.num_types))
2705             return false;
2706          break;
2707 
2708       default:
2709          unreachable("unsupported constant type");
2710       }
2711    }
2712 
2713    return true;
2714 }
2715 
2716 static bool
emit_module_consts(struct dxil_module * m)2717 emit_module_consts(struct dxil_module *m)
2718 {
2719    return enter_subblock(m, DXIL_CONST_BLOCK, 4) &&
2720           emit_module_const_abbrevs(m) &&
2721           emit_consts(m) &&
2722           exit_block(m);
2723 }
2724 
2725 static bool
emit_value_symtab_abbrev_record(struct dxil_module * m,enum value_symtab_abbrev_id abbrev,const uint64_t * data,size_t size)2726 emit_value_symtab_abbrev_record(struct dxil_module *m,
2727                                 enum value_symtab_abbrev_id abbrev,
2728                                 const uint64_t *data, size_t size)
2729 {
2730    assert(abbrev < ARRAY_SIZE(value_symtab_abbrevs));
2731    return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,
2732                              value_symtab_abbrevs + abbrev, data, size);
2733 }
2734 
2735 static bool
emit_symtab_entry(struct dxil_module * m,unsigned value,const char * name)2736 emit_symtab_entry(struct dxil_module *m, unsigned value, const char *name)
2737 {
2738    uint64_t temp[256];
2739    assert(strlen(name) < ARRAY_SIZE(temp) - 2);
2740 
2741    temp[0] = VST_CODE_ENTRY;
2742    temp[1] = value;
2743    for (int i = 0; i < strlen(name); ++i)
2744       temp[i + 2] = (uint8_t)(name[i]);
2745 
2746    enum value_symtab_abbrev_id abbrev = VST_ABBREV_ENTRY_8;
2747    if (is_char6_string(name))
2748       abbrev = VST_ABBREV_ENTRY_6;
2749    else if (is_char7_string(name))
2750       abbrev = VST_ABBREV_ENTRY_7;
2751 
2752    return emit_value_symtab_abbrev_record(m, abbrev, temp, 2 + strlen(name));
2753 }
2754 
2755 static bool
emit_value_symbol_table(struct dxil_module * m)2756 emit_value_symbol_table(struct dxil_module *m)
2757 {
2758    if (!enter_subblock(m, DXIL_VALUE_SYMTAB_BLOCK, 4))
2759       return false;
2760 
2761    struct dxil_func *func;
2762    LIST_FOR_EACH_ENTRY(func, &m->func_list, head) {
2763       if (!emit_symtab_entry(m, func->value.id, func->name))
2764          return false;
2765    }
2766    struct dxil_gvar *gvar;
2767    LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) {
2768       if (!emit_symtab_entry(m, gvar->value.id, gvar->name))
2769          return false;
2770    }
2771    return exit_block(m);
2772 }
2773 
2774 enum metadata_codes {
2775   METADATA_STRING = 1,
2776   METADATA_VALUE = 2,
2777   METADATA_NODE = 3,
2778   METADATA_NAME = 4,
2779   METADATA_KIND = 6,
2780   METADATA_NAMED_NODE = 10
2781 };
2782 
2783 enum metadata_abbrev_id {
2784    METADATA_ABBREV_STRING,
2785    METADATA_ABBREV_NAME
2786 };
2787 
2788 static const struct dxil_abbrev metadata_abbrevs[] = {
2789    [METADATA_ABBREV_STRING] = {
2790       { LITERAL(METADATA_STRING), ARRAY, FIXED(8) }, 3
2791    },
2792    [METADATA_ABBREV_NAME] = {
2793       { LITERAL(METADATA_NAME), ARRAY, FIXED(8) }, 3
2794    },
2795 };
2796 
2797 static bool
emit_metadata_abbrevs(struct dxil_module * m)2798 emit_metadata_abbrevs(struct dxil_module *m)
2799 {
2800    for (int i = 0; i < ARRAY_SIZE(metadata_abbrevs); ++i) {
2801       if (!define_abbrev(m, metadata_abbrevs + i))
2802          return false;
2803    }
2804    return true;
2805 }
2806 
2807 static struct dxil_mdnode *
create_mdnode(struct dxil_module * m,enum mdnode_type type)2808 create_mdnode(struct dxil_module *m, enum mdnode_type type)
2809 {
2810    struct dxil_mdnode *ret = rzalloc_size(m->ralloc_ctx,
2811                                           sizeof(struct dxil_mdnode));
2812    if (ret) {
2813       ret->type = type;
2814       ret->id = list_length(&m->mdnode_list) + 1; /* zero is reserved for NULL nodes */
2815       list_addtail(&ret->head, &m->mdnode_list);
2816    }
2817    return ret;
2818 }
2819 
2820 const struct dxil_mdnode *
dxil_get_metadata_string(struct dxil_module * m,const char * str)2821 dxil_get_metadata_string(struct dxil_module *m, const char *str)
2822 {
2823    assert(str);
2824 
2825    struct dxil_mdnode *n;
2826    LIST_FOR_EACH_ENTRY(n, &m->mdnode_list, head) {
2827       if (n->type == MD_STRING &&
2828           !strcmp(n->string, str))
2829          return n;
2830    }
2831 
2832    n = create_mdnode(m, MD_STRING);
2833    if (n) {
2834       n->string = ralloc_strdup(n, str);
2835       if (!n->string)
2836          return NULL;
2837    }
2838    return n;
2839 }
2840 
2841 const struct dxil_mdnode *
dxil_get_metadata_value(struct dxil_module * m,const struct dxil_type * type,const struct dxil_value * value)2842 dxil_get_metadata_value(struct dxil_module *m, const struct dxil_type *type,
2843                         const struct dxil_value *value)
2844 {
2845    struct dxil_mdnode *n;
2846    LIST_FOR_EACH_ENTRY(n, &m->mdnode_list, head) {
2847       if (n->type == MD_VALUE &&
2848           n->value.type == type &&
2849           n->value.value == value)
2850          return n;
2851    }
2852 
2853    n = create_mdnode(m, MD_VALUE);
2854    if (n) {
2855       n->value.type = type;
2856       n->value.value = value;
2857    }
2858    return n;
2859 }
2860 
2861 const struct dxil_mdnode *
dxil_get_metadata_func(struct dxil_module * m,const struct dxil_func * func)2862 dxil_get_metadata_func(struct dxil_module *m, const struct dxil_func *func)
2863 {
2864    const struct dxil_type *ptr_type =
2865       dxil_module_get_pointer_type(m, func->type);
2866    return dxil_get_metadata_value(m, ptr_type, &func->value);
2867 }
2868 
2869 const struct dxil_mdnode *
dxil_get_metadata_node(struct dxil_module * m,const struct dxil_mdnode * subnodes[],size_t num_subnodes)2870 dxil_get_metadata_node(struct dxil_module *m,
2871                        const struct dxil_mdnode *subnodes[],
2872                        size_t num_subnodes)
2873 {
2874    struct dxil_mdnode *n;
2875    LIST_FOR_EACH_ENTRY(n, &m->mdnode_list, head) {
2876       if (n->type == MD_NODE &&
2877           n->node.num_subnodes == num_subnodes &&
2878           !memcmp(n->node.subnodes, subnodes, sizeof(struct dxil_mdnode *) *
2879                   num_subnodes))
2880          return n;
2881    }
2882 
2883    n = create_mdnode(m, MD_NODE);
2884    if (n) {
2885       void *tmp = ralloc_array(n, struct dxil_mdnode *, num_subnodes);
2886       if (!tmp)
2887          return NULL;
2888 
2889       memcpy(tmp, subnodes, sizeof(struct dxil_mdnode *) * num_subnodes);
2890       n->node.subnodes = tmp;
2891       n->node.num_subnodes = num_subnodes;
2892    }
2893    return n;
2894 }
2895 
2896 const struct dxil_mdnode *
dxil_get_metadata_int1(struct dxil_module * m,bool value)2897 dxil_get_metadata_int1(struct dxil_module *m, bool value)
2898 {
2899    const struct dxil_type *type = get_int1_type(m);
2900    if (!type)
2901       return NULL;
2902 
2903    const struct dxil_value *const_value = get_int_const(m, type, value);
2904    if (!const_value)
2905       return NULL;
2906 
2907    return dxil_get_metadata_value(m, type, const_value);
2908 }
2909 
2910 const struct dxil_mdnode *
dxil_get_metadata_int8(struct dxil_module * m,int8_t value)2911 dxil_get_metadata_int8(struct dxil_module *m, int8_t value)
2912 {
2913    const struct dxil_type *type = get_int8_type(m);
2914    if (!type)
2915       return NULL;
2916 
2917    const struct dxil_value *const_value = get_int_const(m, type, value);
2918    if (!const_value)
2919       return NULL;
2920 
2921    return dxil_get_metadata_value(m, type, const_value);
2922 }
2923 
2924 const struct dxil_mdnode *
dxil_get_metadata_int32(struct dxil_module * m,int32_t value)2925 dxil_get_metadata_int32(struct dxil_module *m, int32_t value)
2926 {
2927    const struct dxil_type *type = get_int32_type(m);
2928    if (!type)
2929       return NULL;
2930 
2931    const struct dxil_value *const_value = get_int_const(m, type, value);
2932    if (!const_value)
2933       return NULL;
2934 
2935    return dxil_get_metadata_value(m, type, const_value);
2936 }
2937 
2938 const struct dxil_mdnode *
dxil_get_metadata_int64(struct dxil_module * m,int64_t value)2939 dxil_get_metadata_int64(struct dxil_module *m, int64_t value)
2940 {
2941    const struct dxil_type *type = get_int64_type(m);
2942    if (!type)
2943       return NULL;
2944 
2945    const struct dxil_value *const_value = get_int_const(m, type, value);
2946    if (!const_value)
2947       return NULL;
2948 
2949    return dxil_get_metadata_value(m, type, const_value);
2950 }
2951 
2952 const struct dxil_mdnode *
dxil_get_metadata_float32(struct dxil_module * m,float value)2953 dxil_get_metadata_float32(struct dxil_module *m, float value)
2954 {
2955    const struct dxil_type *type = get_float32_type(m);
2956    if (!type)
2957       return NULL;
2958 
2959    const struct dxil_value *const_value = dxil_module_get_float_const(m, value);
2960    if (!const_value)
2961       return NULL;
2962 
2963    return dxil_get_metadata_value(m, type, const_value);
2964 }
2965 
2966 bool
dxil_add_metadata_named_node(struct dxil_module * m,const char * name,const struct dxil_mdnode * subnodes[],size_t num_subnodes)2967 dxil_add_metadata_named_node(struct dxil_module *m, const char *name,
2968                              const struct dxil_mdnode *subnodes[],
2969                              size_t num_subnodes)
2970 {
2971    struct dxil_named_node *n = ralloc_size(m->ralloc_ctx,
2972                                            sizeof(struct dxil_named_node));
2973    if (!n)
2974       return false;
2975 
2976    n->name = ralloc_strdup(n, name);
2977    if (!n->name)
2978       return false;
2979 
2980    void *tmp = ralloc_array(n, struct dxil_mdnode *, num_subnodes);
2981    if (!tmp)
2982       return false;
2983 
2984    memcpy(tmp, subnodes, sizeof(struct dxil_mdnode *) * num_subnodes);
2985    n->subnodes = tmp;
2986    n->num_subnodes = num_subnodes;
2987 
2988    list_addtail(&n->head, &m->md_named_node_list);
2989    return true;
2990 }
2991 
2992 static bool
emit_metadata_value(struct dxil_module * m,const struct dxil_type * type,const struct dxil_value * value)2993 emit_metadata_value(struct dxil_module *m, const struct dxil_type *type,
2994                     const struct dxil_value *value)
2995 {
2996    assert(type->id >= 0 && value->id >= 0);
2997    uint64_t data[2] = { type->id, value->id };
2998    return emit_record(m, METADATA_VALUE, data, ARRAY_SIZE(data));
2999 }
3000 
3001 static bool
emit_metadata_abbrev_record(struct dxil_module * m,enum metadata_abbrev_id abbrev,const uint64_t * data,size_t size)3002 emit_metadata_abbrev_record(struct dxil_module *m,
3003                             enum metadata_abbrev_id abbrev,
3004                             const uint64_t *data, size_t size)
3005 {
3006    assert(abbrev < ARRAY_SIZE(metadata_abbrevs));
3007    return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,
3008                              metadata_abbrevs + abbrev, data, size);
3009 }
3010 
3011 static bool
emit_metadata_string(struct dxil_module * m,const char * str)3012 emit_metadata_string(struct dxil_module *m, const char *str)
3013 {
3014    uint64_t data[256];
3015    assert(strlen(str) < ARRAY_SIZE(data) - 1);
3016    data[0] = METADATA_STRING;
3017    for (size_t i = 0; i < strlen(str); ++i)
3018       data[i + 1] = (uint8_t)(str[i]);
3019 
3020    return emit_metadata_abbrev_record(m, METADATA_ABBREV_STRING,
3021                                       data, strlen(str) + 1);
3022 }
3023 
3024 static bool
emit_metadata_node(struct dxil_module * m,const struct dxil_mdnode * subnodes[],size_t num_subnodes)3025 emit_metadata_node(struct dxil_module *m,
3026                    const struct dxil_mdnode *subnodes[],
3027                    size_t num_subnodes)
3028 {
3029    uint64_t data[256];
3030    assert(num_subnodes < ARRAY_SIZE(data));
3031    for (size_t i = 0; i < num_subnodes; ++i)
3032       data[i] = subnodes[i] ? subnodes[i]->id : 0;
3033 
3034    return emit_record(m, METADATA_NODE, data, num_subnodes);
3035 }
3036 
3037 static bool
emit_mdnode(struct dxil_module * m,struct dxil_mdnode * n)3038 emit_mdnode(struct dxil_module *m, struct dxil_mdnode *n)
3039 {
3040    switch (n->type) {
3041    case MD_STRING:
3042       return emit_metadata_string(m, n->string);
3043 
3044    case MD_VALUE:
3045       return emit_metadata_value(m, n->value.type, n->value.value);
3046 
3047    case MD_NODE:
3048       return emit_metadata_node(m, n->node.subnodes, n->node.num_subnodes);
3049 
3050    default:
3051       unreachable("unexpected n->type");
3052    }
3053 }
3054 
3055 static bool
emit_metadata_nodes(struct dxil_module * m)3056 emit_metadata_nodes(struct dxil_module *m)
3057 {
3058    list_for_each_entry(struct dxil_mdnode, n,  &m->mdnode_list, head) {
3059       if (!emit_mdnode(m, n))
3060          return false;
3061    }
3062    return true;
3063 }
3064 
3065 static bool
emit_metadata_name(struct dxil_module * m,const char * name)3066 emit_metadata_name(struct dxil_module *m, const char *name)
3067 {
3068    uint64_t data[256];
3069    assert(strlen(name) < ARRAY_SIZE(data) - 1);
3070    data[0] = METADATA_NAME;
3071    for (size_t i = 0; i < strlen(name); ++i)
3072       data[i + 1] = name[i];
3073 
3074    return emit_metadata_abbrev_record(m, METADATA_ABBREV_NAME,
3075                                       data, strlen(name) + 1);
3076 }
3077 
3078 static bool
emit_metadata_named_node(struct dxil_module * m,const char * name,const struct dxil_mdnode * subnodes[],size_t num_subnodes)3079 emit_metadata_named_node(struct dxil_module *m, const char *name,
3080                          const struct dxil_mdnode *subnodes[],
3081                          size_t num_subnodes)
3082 {
3083    uint64_t data[256];
3084    assert(num_subnodes < ARRAY_SIZE(data));
3085    for (size_t i = 0; i < num_subnodes; ++i) {
3086       assert(subnodes[i]->id > 0); /* NULL nodes not allowed */
3087       data[i] = subnodes[i]->id - 1;
3088    }
3089 
3090    return emit_metadata_name(m, name) &&
3091           emit_record(m, METADATA_NAMED_NODE, data, num_subnodes);
3092 }
3093 
3094 static bool
emit_metadata_named_nodes(struct dxil_module * m)3095 emit_metadata_named_nodes(struct dxil_module *m)
3096 {
3097    struct dxil_named_node *n;
3098    LIST_FOR_EACH_ENTRY(n, &m->md_named_node_list, head) {
3099       if (!emit_metadata_named_node(m, n->name, n->subnodes,
3100                                     n->num_subnodes))
3101          return false;
3102    }
3103    return true;
3104 }
3105 
3106 static bool
emit_metadata(struct dxil_module * m)3107 emit_metadata(struct dxil_module *m)
3108 {
3109    return enter_subblock(m, DXIL_METADATA_BLOCK, 3) &&
3110           emit_metadata_abbrevs(m) &&
3111           emit_metadata_nodes(m) &&
3112           emit_metadata_named_nodes(m) &&
3113           exit_block(m);
3114 }
3115 
3116 static struct dxil_instr *
create_instr(struct dxil_module * m,enum instr_type type,const struct dxil_type * ret_type)3117 create_instr(struct dxil_module *m, enum instr_type type,
3118              const struct dxil_type *ret_type)
3119 {
3120    struct dxil_instr *ret = ralloc_size(m->ralloc_ctx,
3121                                         sizeof(struct dxil_instr));
3122    if (ret) {
3123       ret->type = type;
3124       ret->value.id = -1;
3125       ret->value.type = ret_type;
3126       ret->has_value = false;
3127       list_addtail(&ret->head, &m->cur_emitting_func->instr_list);
3128    }
3129    return ret;
3130 }
3131 
3132 static inline bool
legal_arith_type(const struct dxil_type * type)3133 legal_arith_type(const struct dxil_type *type)
3134 {
3135    switch (type->type) {
3136    case TYPE_INTEGER:
3137       return type->int_bits == 1 ||
3138              type->int_bits == 16 ||
3139              type->int_bits == 32 ||
3140              type->int_bits == 64;
3141 
3142    case TYPE_FLOAT:
3143       return type->float_bits == 16 ||
3144              type->float_bits == 32 ||
3145              type->float_bits == 64;
3146 
3147    default:
3148       return false;
3149    }
3150 }
3151 
3152 const struct dxil_value *
dxil_emit_binop(struct dxil_module * m,enum dxil_bin_opcode opcode,const struct dxil_value * op0,const struct dxil_value * op1,enum dxil_opt_flags flags)3153 dxil_emit_binop(struct dxil_module *m, enum dxil_bin_opcode opcode,
3154                 const struct dxil_value *op0, const struct dxil_value *op1,
3155                 enum dxil_opt_flags flags)
3156 {
3157    assert(types_equal(op0->type, op1->type));
3158    assert(legal_arith_type(op0->type));
3159    struct dxil_instr *instr = create_instr(m, INSTR_BINOP, op0->type);
3160    if (!instr)
3161       return NULL;
3162 
3163    instr->binop.opcode = opcode;
3164    instr->binop.operands[0] = op0;
3165    instr->binop.operands[1] = op1;
3166    instr->binop.flags = flags;
3167    instr->has_value = true;
3168    return &instr->value;
3169 }
3170 
3171 const struct dxil_value *
dxil_emit_cmp(struct dxil_module * m,enum dxil_cmp_pred pred,const struct dxil_value * op0,const struct dxil_value * op1)3172 dxil_emit_cmp(struct dxil_module *m, enum dxil_cmp_pred pred,
3173                 const struct dxil_value *op0, const struct dxil_value *op1)
3174 {
3175    assert(types_equal(op0->type, op1->type));
3176    assert(legal_arith_type(op0->type));
3177    struct dxil_instr *instr = create_instr(m, INSTR_CMP, get_int1_type(m));
3178    if (!instr)
3179       return NULL;
3180 
3181    instr->cmp.pred = pred;
3182    instr->cmp.operands[0] = op0;
3183    instr->cmp.operands[1] = op1;
3184    instr->has_value = true;
3185    return &instr->value;
3186 }
3187 
3188 const struct dxil_value *
dxil_emit_select(struct dxil_module * m,const struct dxil_value * op0,const struct dxil_value * op1,const struct dxil_value * op2)3189 dxil_emit_select(struct dxil_module *m,
3190                 const struct dxil_value *op0,
3191                 const struct dxil_value *op1,
3192                 const struct dxil_value *op2)
3193 {
3194    assert(types_equal(op0->type, get_int1_type(m)));
3195    assert(types_equal(op1->type, op2->type));
3196    assert(legal_arith_type(op1->type));
3197 
3198    struct dxil_instr *instr = create_instr(m, INSTR_SELECT, op1->type);
3199    if (!instr)
3200       return NULL;
3201 
3202    instr->select.operands[0] = op0;
3203    instr->select.operands[1] = op1;
3204    instr->select.operands[2] = op2;
3205    instr->has_value = true;
3206    return &instr->value;
3207 }
3208 
3209 const struct dxil_value *
dxil_emit_cast(struct dxil_module * m,enum dxil_cast_opcode opcode,const struct dxil_type * type,const struct dxil_value * value)3210 dxil_emit_cast(struct dxil_module *m, enum dxil_cast_opcode opcode,
3211                const struct dxil_type *type,
3212                const struct dxil_value *value)
3213 {
3214    assert(legal_arith_type(value->type));
3215    assert(legal_arith_type(type));
3216 
3217    struct dxil_instr *instr = create_instr(m, INSTR_CAST, type);
3218    if (!instr)
3219       return NULL;
3220 
3221    instr->cast.opcode = opcode;
3222    instr->cast.type = type;
3223    instr->cast.value = value;
3224    instr->has_value = true;
3225    return &instr->value;
3226 }
3227 
3228 bool
dxil_emit_branch(struct dxil_module * m,const struct dxil_value * cond,unsigned true_block,unsigned false_block)3229 dxil_emit_branch(struct dxil_module *m, const struct dxil_value *cond,
3230                  unsigned true_block, unsigned false_block)
3231 {
3232    assert(!cond || types_equal(cond->type, get_int1_type(m)));
3233 
3234    struct dxil_instr *instr = create_instr(m, INSTR_BR,
3235                                            dxil_module_get_void_type(m));
3236    if (!instr)
3237       return false;
3238 
3239    instr->br.cond = cond;
3240    instr->br.succ[0] = true_block;
3241    instr->br.succ[1] = false_block;
3242    m->cur_emitting_func->curr_block++;
3243    return true;
3244 }
3245 
3246 const struct dxil_value *
dxil_instr_get_return_value(struct dxil_instr * instr)3247 dxil_instr_get_return_value(struct dxil_instr *instr)
3248 {
3249    return instr->has_value ? &instr->value : NULL;
3250 }
3251 
3252 struct dxil_instr *
dxil_emit_phi(struct dxil_module * m,const struct dxil_type * type)3253 dxil_emit_phi(struct dxil_module *m, const struct dxil_type *type)
3254 {
3255    assert(legal_arith_type(type));
3256 
3257    struct dxil_instr *instr = create_instr(m, INSTR_PHI, type);
3258    if (!instr)
3259       return NULL;
3260 
3261    instr->phi.type = type;
3262    instr->phi.incoming = NULL;
3263    instr->phi.num_incoming = 0;
3264    instr->has_value = true;
3265 
3266    return instr;
3267 }
3268 
3269 bool
dxil_phi_add_incoming(struct dxil_instr * instr,const struct dxil_value * incoming_values[],const unsigned incoming_blocks[],size_t num_incoming)3270 dxil_phi_add_incoming(struct dxil_instr *instr,
3271                       const struct dxil_value *incoming_values[],
3272                       const unsigned incoming_blocks[],
3273                       size_t num_incoming)
3274 {
3275    assert(instr->type == INSTR_PHI);
3276    assert(num_incoming > 0);
3277 
3278    instr->phi.incoming = reralloc(instr, instr->phi.incoming,
3279                                   struct dxil_phi_src,
3280                                   instr->phi.num_incoming + num_incoming);
3281    if (!instr->phi.incoming)
3282       return false;
3283 
3284    for (int i = 0; i < num_incoming; ++i) {
3285       assert(incoming_values[i]);
3286       assert(types_equal(incoming_values[i]->type, instr->phi.type));
3287       int dst = instr->phi.num_incoming + i;
3288       instr->phi.incoming[dst].value = incoming_values[i];
3289       instr->phi.incoming[dst].block = incoming_blocks[i];
3290    }
3291    instr->phi.num_incoming += num_incoming;
3292    return true;
3293 }
3294 
3295 static struct dxil_instr *
create_call_instr(struct dxil_module * m,const struct dxil_func * func,const struct dxil_value ** args,size_t num_args)3296 create_call_instr(struct dxil_module *m,
3297                   const struct dxil_func *func,
3298                   const struct dxil_value **args, size_t num_args)
3299 {
3300    assert(num_args == func->type->function_def.args.num_types);
3301    for (size_t i = 0; i < num_args; ++ i)
3302       assert(types_equal(func->type->function_def.args.types[i], args[i]->type));
3303 
3304    struct dxil_instr *instr = create_instr(m, INSTR_CALL,
3305                                            func->type->function_def.ret_type);
3306    if (instr) {
3307       instr->call.func = func;
3308       instr->call.args = ralloc_array(instr, struct dxil_value *, num_args);
3309       if (!args)
3310          return false;
3311       memcpy(instr->call.args, args, sizeof(struct dxil_value *) * num_args);
3312       instr->call.num_args = num_args;
3313    }
3314    return instr;
3315 }
3316 
3317 const struct dxil_value *
dxil_emit_call(struct dxil_module * m,const struct dxil_func * func,const struct dxil_value ** args,size_t num_args)3318 dxil_emit_call(struct dxil_module *m,
3319                const struct dxil_func *func,
3320                const struct dxil_value **args, size_t num_args)
3321 {
3322    assert(func->type->function_def.ret_type->type != TYPE_VOID);
3323 
3324    struct dxil_instr *instr = create_call_instr(m, func, args, num_args);
3325    if (!instr)
3326       return NULL;
3327 
3328    instr->has_value = true;
3329    return &instr->value;
3330 }
3331 
3332 bool
dxil_emit_call_void(struct dxil_module * m,const struct dxil_func * func,const struct dxil_value ** args,size_t num_args)3333 dxil_emit_call_void(struct dxil_module *m,
3334                     const struct dxil_func *func,
3335                     const struct dxil_value **args, size_t num_args)
3336 {
3337    assert(func->type->function_def.ret_type->type == TYPE_VOID);
3338 
3339    struct dxil_instr *instr = create_call_instr(m, func, args, num_args);
3340    if (!instr)
3341       return false;
3342 
3343    return true;
3344 }
3345 
3346 bool
dxil_emit_ret_void(struct dxil_module * m)3347 dxil_emit_ret_void(struct dxil_module *m)
3348 {
3349    struct dxil_instr *instr = create_instr(m, INSTR_RET,
3350                                            dxil_module_get_void_type(m));
3351    if (!instr)
3352       return false;
3353 
3354    instr->ret.value = NULL;
3355    m->cur_emitting_func->curr_block++;
3356    return true;
3357 }
3358 
3359 const struct dxil_value *
dxil_emit_extractval(struct dxil_module * m,const struct dxil_value * src,const unsigned int index)3360 dxil_emit_extractval(struct dxil_module *m, const struct dxil_value *src,
3361                      const unsigned int index)
3362 {
3363    assert(src->type->type == TYPE_STRUCT);
3364    assert(index < src->type->struct_def.elem.num_types);
3365 
3366    struct dxil_instr *instr =
3367       create_instr(m, INSTR_EXTRACTVAL,
3368                    src->type->struct_def.elem.types[index]);
3369    if (!instr)
3370       return NULL;
3371 
3372    instr->extractval.src = src;
3373    instr->extractval.type = src->type;
3374    instr->extractval.idx = index;
3375    instr->has_value = true;
3376 
3377    return &instr->value;
3378 }
3379 
3380 const struct dxil_value *
dxil_emit_alloca(struct dxil_module * m,const struct dxil_type * alloc_type,const struct dxil_value * size,unsigned int align)3381 dxil_emit_alloca(struct dxil_module *m, const struct dxil_type *alloc_type,
3382                  const struct dxil_value *size,
3383                  unsigned int align)
3384 {
3385    assert(size->type->type == TYPE_INTEGER);
3386 
3387    const struct dxil_type *return_type =
3388       dxil_module_get_pointer_type(m, alloc_type);
3389    if (!return_type)
3390       return NULL;
3391 
3392    struct dxil_instr *instr = create_instr(m, INSTR_ALLOCA, return_type);
3393    if (!instr)
3394       return NULL;
3395 
3396    instr->alloca.alloc_type = alloc_type;
3397    instr->alloca.size_type = size->type;
3398    instr->alloca.size = size;
3399    instr->alloca.align = util_logbase2(align) + 1;
3400    assert(instr->alloca.align < (1 << 5));
3401    instr->alloca.align |= 1 << 6;
3402 
3403    instr->has_value = true;
3404    return &instr->value;
3405 }
3406 
3407 static const struct dxil_type *
get_deref_type(const struct dxil_type * type)3408 get_deref_type(const struct dxil_type *type)
3409 {
3410    switch (type->type) {
3411    case TYPE_POINTER: return type->ptr_target_type;
3412    case TYPE_ARRAY: return type->array_or_vector_def.elem_type;
3413    default: unreachable("unexpected type");
3414    }
3415 }
3416 
3417 const struct dxil_value *
dxil_emit_gep_inbounds(struct dxil_module * m,const struct dxil_value ** operands,size_t num_operands)3418 dxil_emit_gep_inbounds(struct dxil_module *m,
3419                        const struct dxil_value **operands,
3420                        size_t num_operands)
3421 {
3422    assert(num_operands > 0);
3423    const struct dxil_type *source_elem_type =
3424       get_deref_type(operands[0]->type);
3425 
3426    const struct dxil_type *type = operands[0]->type;
3427    for (int i = 1; i < num_operands; ++i) {
3428       assert(operands[i]->type == get_int32_type(m));
3429       type = get_deref_type(type);
3430    }
3431 
3432    type = dxil_module_get_pointer_type(m, type);
3433    if (!type)
3434       return NULL;
3435 
3436    struct dxil_instr *instr = create_instr(m, INSTR_GEP, type);
3437    if (!instr)
3438       return NULL;
3439 
3440    instr->gep.operands = ralloc_array(instr, struct dxil_value *,
3441                                       num_operands);
3442    if (!instr->gep.operands)
3443       return NULL;
3444 
3445    instr->gep.source_elem_type = source_elem_type;
3446    memcpy(instr->gep.operands, operands,
3447           sizeof(struct dxil_value *) * num_operands);
3448    instr->gep.num_operands = num_operands;
3449    instr->gep.inbounds = true;
3450 
3451    instr->has_value = true;
3452    return &instr->value;
3453 }
3454 
3455 const struct dxil_value *
dxil_emit_load(struct dxil_module * m,const struct dxil_value * ptr,unsigned align,bool is_volatile)3456 dxil_emit_load(struct dxil_module *m, const struct dxil_value *ptr,
3457                unsigned align,
3458                bool is_volatile)
3459 {
3460    assert(ptr->type->type == TYPE_POINTER ||
3461           ptr->type->type == TYPE_ARRAY);
3462    const struct dxil_type *type = ptr->type->type == TYPE_POINTER ?
3463       ptr->type->ptr_target_type :
3464       ptr->type->array_or_vector_def.elem_type;
3465 
3466    struct dxil_instr *instr = create_instr(m, INSTR_LOAD, type);
3467    if (!instr)
3468       return false;
3469 
3470    instr->load.ptr = ptr;
3471    instr->load.type = type;
3472    instr->load.align = util_logbase2(align) + 1;
3473    instr->load.is_volatile = is_volatile;
3474 
3475    instr->has_value = true;
3476    return &instr->value;
3477 }
3478 
3479 bool
dxil_emit_store(struct dxil_module * m,const struct dxil_value * value,const struct dxil_value * ptr,unsigned align,bool is_volatile)3480 dxil_emit_store(struct dxil_module *m, const struct dxil_value *value,
3481                 const struct dxil_value *ptr, unsigned align,
3482                 bool is_volatile)
3483 {
3484    assert(legal_arith_type(value->type));
3485 
3486    struct dxil_instr *instr = create_instr(m, INSTR_STORE,
3487                                            dxil_module_get_void_type(m));
3488    if (!instr)
3489       return false;
3490 
3491    instr->store.value = value;
3492    instr->store.ptr = ptr;
3493    instr->store.align = util_logbase2(align) + 1;
3494    instr->store.is_volatile = is_volatile;
3495    return true;
3496 }
3497 
3498 const struct dxil_value *
dxil_emit_cmpxchg(struct dxil_module * m,const struct dxil_value * cmpval,const struct dxil_value * newval,const struct dxil_value * ptr,bool is_volatile,enum dxil_atomic_ordering ordering,enum dxil_sync_scope syncscope)3499 dxil_emit_cmpxchg(struct dxil_module *m, const struct dxil_value *cmpval,
3500                   const struct dxil_value *newval,
3501                   const struct dxil_value *ptr, bool is_volatile,
3502                   enum dxil_atomic_ordering ordering,
3503                   enum dxil_sync_scope syncscope)
3504 {
3505    assert(ptr->type->type == TYPE_POINTER);
3506 
3507    struct dxil_instr *instr = create_instr(m, INSTR_CMPXCHG,
3508                                            ptr->type->ptr_target_type);
3509    if (!instr)
3510       return false;
3511 
3512    instr->cmpxchg.cmpval = cmpval;
3513    instr->cmpxchg.newval = newval;
3514    instr->cmpxchg.ptr = ptr;
3515    instr->cmpxchg.is_volatile = is_volatile;
3516    instr->cmpxchg.ordering = ordering;
3517    instr->cmpxchg.syncscope = syncscope;
3518 
3519    instr->has_value = true;
3520    return &instr->value;
3521 }
3522 
3523 const struct dxil_value *
dxil_emit_atomicrmw(struct dxil_module * m,const struct dxil_value * value,const struct dxil_value * ptr,enum dxil_rmw_op op,bool is_volatile,enum dxil_atomic_ordering ordering,enum dxil_sync_scope syncscope)3524 dxil_emit_atomicrmw(struct dxil_module *m, const struct dxil_value *value,
3525                     const struct dxil_value *ptr, enum dxil_rmw_op op,
3526                     bool is_volatile, enum dxil_atomic_ordering ordering,
3527                     enum dxil_sync_scope syncscope)
3528 {
3529    assert(ptr->type->type == TYPE_POINTER);
3530 
3531    struct dxil_instr *instr = create_instr(m, INSTR_ATOMICRMW,
3532                                            ptr->type->ptr_target_type);
3533    if (!instr)
3534       return false;
3535 
3536    instr->atomicrmw.value = value;
3537    instr->atomicrmw.ptr = ptr;
3538    instr->atomicrmw.op = op;
3539    instr->atomicrmw.is_volatile = is_volatile;
3540    instr->atomicrmw.ordering = ordering;
3541    instr->atomicrmw.syncscope = syncscope;
3542 
3543    instr->has_value = true;
3544    return &instr->value;
3545 }
3546 
3547 static bool
emit_binop(struct dxil_module * m,struct dxil_instr * instr)3548 emit_binop(struct dxil_module *m, struct dxil_instr *instr)
3549 {
3550    assert(instr->type == INSTR_BINOP);
3551    assert(instr->value.id > instr->binop.operands[0]->id);
3552    assert(instr->value.id > instr->binop.operands[1]->id);
3553 
3554    if (instr->binop.flags) {
3555       uint64_t data[] = {
3556          FUNC_CODE_INST_BINOP,
3557          instr->value.id - instr->binop.operands[0]->id,
3558          instr->value.id - instr->binop.operands[1]->id,
3559          instr->binop.opcode,
3560          instr->binop.flags
3561       };
3562       return emit_func_abbrev_record(m, FUNC_ABBREV_BINOP_FLAGS,
3563                                      data, ARRAY_SIZE(data));
3564    }
3565    uint64_t data[] = {
3566       FUNC_CODE_INST_BINOP,
3567       instr->value.id - instr->binop.operands[0]->id,
3568       instr->value.id - instr->binop.operands[1]->id,
3569       instr->binop.opcode
3570    };
3571    return emit_func_abbrev_record(m, FUNC_ABBREV_BINOP,
3572                                   data, ARRAY_SIZE(data));
3573 }
3574 
3575 static bool
emit_cmp(struct dxil_module * m,struct dxil_instr * instr)3576 emit_cmp(struct dxil_module *m, struct dxil_instr *instr)
3577 {
3578    assert(instr->type == INSTR_CMP);
3579    assert(instr->value.id > instr->cmp.operands[0]->id);
3580    assert(instr->value.id > instr->cmp.operands[1]->id);
3581    uint64_t data[] = {
3582       instr->value.id - instr->cmp.operands[0]->id,
3583       instr->value.id - instr->cmp.operands[1]->id,
3584       instr->cmp.pred
3585    };
3586    return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_CMP2,
3587                                 data, ARRAY_SIZE(data));
3588 }
3589 
3590 static bool
emit_select(struct dxil_module * m,struct dxil_instr * instr)3591 emit_select(struct dxil_module *m, struct dxil_instr *instr)
3592 {
3593    assert(instr->type == INSTR_SELECT);
3594    assert(instr->value.id > instr->select.operands[0]->id);
3595    assert(instr->value.id > instr->select.operands[1]->id);
3596    assert(instr->value.id > instr->select.operands[2]->id);
3597    uint64_t data[] = {
3598       instr->value.id - instr->select.operands[1]->id,
3599       instr->value.id - instr->select.operands[2]->id,
3600       instr->value.id - instr->select.operands[0]->id
3601    };
3602    return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_VSELECT,
3603                                 data, ARRAY_SIZE(data));
3604 }
3605 
3606 static bool
emit_cast(struct dxil_module * m,struct dxil_instr * instr)3607 emit_cast(struct dxil_module *m, struct dxil_instr *instr)
3608 {
3609    assert(instr->type == INSTR_CAST);
3610    assert(instr->value.id > instr->cast.value->id);
3611    uint64_t data[] = {
3612       FUNC_CODE_INST_CAST,
3613       instr->value.id - instr->cast.value->id,
3614       instr->cast.type->id,
3615       instr->cast.opcode
3616    };
3617    return emit_func_abbrev_record(m, FUNC_ABBREV_CAST,
3618                                   data, ARRAY_SIZE(data));
3619 }
3620 
3621 static bool
emit_branch(struct dxil_module * m,struct dxil_func_def * func,struct dxil_instr * instr)3622 emit_branch(struct dxil_module *m, struct dxil_func_def *func, struct dxil_instr *instr)
3623 {
3624    assert(instr->type == INSTR_BR);
3625    assert(instr->br.succ[0] < func->num_basic_block_ids);
3626    assert(func->basic_block_ids[instr->br.succ[0]] >= 0);
3627 
3628    if (!instr->br.cond) {
3629       /* unconditional branch */
3630       uint64_t succ = func->basic_block_ids[instr->br.succ[0]];
3631       return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_BR, &succ, 1);
3632    }
3633    /* conditional branch */
3634    assert(instr->value.id > instr->br.cond->id);
3635    assert(instr->br.succ[1] < func->num_basic_block_ids);
3636    assert(func->basic_block_ids[instr->br.succ[1]] >= 0);
3637 
3638    uint64_t data[] = {
3639       func->basic_block_ids[instr->br.succ[0]],
3640       func->basic_block_ids[instr->br.succ[1]],
3641       instr->value.id - instr->br.cond->id
3642    };
3643    return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_BR,
3644                                 data, ARRAY_SIZE(data));
3645 }
3646 
3647 static bool
emit_phi(struct dxil_module * m,struct dxil_func_def * func,struct dxil_instr * instr)3648 emit_phi(struct dxil_module *m, struct dxil_func_def *func, struct dxil_instr *instr)
3649 {
3650    assert(instr->type == INSTR_PHI);
3651    uint64_t data[128];
3652    data[0] = instr->phi.type->id;
3653    assert(instr->phi.num_incoming > 0);
3654    for (int i = 0; i < instr->phi.num_incoming; ++i) {
3655       int64_t value_delta = instr->value.id - instr->phi.incoming[i].value->id;
3656       data[1 + i * 2] = encode_signed(value_delta);
3657       assert(instr->phi.incoming[i].block < func->num_basic_block_ids);
3658       assert(func->basic_block_ids[instr->phi.incoming[i].block] >= 0);
3659       data[1 + i * 2 + 1] = func->basic_block_ids[instr->phi.incoming[i].block];
3660    }
3661    return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_PHI,
3662                                 data, 1 + 2 * instr->phi.num_incoming);
3663 }
3664 
3665 static bool
emit_extractval(struct dxil_module * m,struct dxil_instr * instr)3666 emit_extractval(struct dxil_module *m, struct dxil_instr *instr)
3667 {
3668    assert(instr->type == INSTR_EXTRACTVAL);
3669    assert(instr->value.id > instr->extractval.src->id);
3670    assert(instr->value.id > instr->extractval.type->id);
3671 
3672    /* relative value ID, followed by absolute type ID (only if
3673     * forward-declared), followed by n indices */
3674    uint64_t data[] = {
3675       instr->value.id - instr->extractval.src->id,
3676       instr->extractval.idx
3677    };
3678    return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_EXTRACTVAL,
3679                                 data, ARRAY_SIZE(data));
3680 }
3681 
3682 static bool
emit_call(struct dxil_module * m,struct dxil_instr * instr)3683 emit_call(struct dxil_module *m, struct dxil_instr *instr)
3684 {
3685    assert(instr->type == INSTR_CALL);
3686    assert(instr->call.func->value.id >= 0 && instr->value.id >= 0);
3687    assert(instr->call.func->type->id >= 0);
3688    assert(instr->call.func->value.id <= instr->value.id);
3689    int value_id_delta = instr->value.id - instr->call.func->value.id;
3690 
3691    uint64_t data[256];
3692    data[0] = 0; // attribute id
3693    data[1] = 1 << 15; // calling convention etc
3694    data[2] = instr->call.func->type->id;
3695    data[3] = value_id_delta;
3696 
3697    assert(instr->call.num_args < ARRAY_SIZE(data) - 4);
3698    for (size_t i = 0; i < instr->call.num_args; ++i) {
3699       assert(instr->call.args[i]->id >= 0);
3700       data[4 + i] = instr->value.id - instr->call.args[i]->id;
3701    }
3702 
3703    return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_CALL,
3704                                 data, 4 + instr->call.num_args);
3705 }
3706 
3707 static bool
emit_ret(struct dxil_module * m,struct dxil_instr * instr)3708 emit_ret(struct dxil_module *m, struct dxil_instr *instr)
3709 {
3710    assert(instr->type == INSTR_RET);
3711 
3712    if (instr->ret.value) {
3713       assert(instr->ret.value->id >= 0);
3714       uint64_t data[] = { FUNC_CODE_INST_RET, instr->ret.value->id };
3715       return emit_func_abbrev_record(m, FUNC_ABBREV_RET_VAL,
3716                                      data, ARRAY_SIZE(data));
3717    }
3718 
3719    uint64_t data[] = { FUNC_CODE_INST_RET };
3720    return emit_func_abbrev_record(m, FUNC_ABBREV_RET_VOID,
3721                                   data, ARRAY_SIZE(data));
3722 }
3723 
3724 static bool
emit_alloca(struct dxil_module * m,struct dxil_instr * instr)3725 emit_alloca(struct dxil_module *m, struct dxil_instr *instr)
3726 {
3727    assert(instr->type == INSTR_ALLOCA);
3728    assert(instr->alloca.alloc_type->id >= 0);
3729    assert(instr->alloca.size_type->id >= 0);
3730    assert(instr->alloca.size->id >= 0);
3731 
3732    uint64_t data[] = {
3733       instr->alloca.alloc_type->id,
3734       instr->alloca.size_type->id,
3735       instr->alloca.size->id,
3736       instr->alloca.align,
3737    };
3738    return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_ALLOCA,
3739                                 data, ARRAY_SIZE(data));
3740 }
3741 
3742 static bool
emit_gep(struct dxil_module * m,struct dxil_instr * instr)3743 emit_gep(struct dxil_module *m, struct dxil_instr *instr)
3744 {
3745    assert(instr->type == INSTR_GEP);
3746    assert(instr->gep.source_elem_type->id >= 0);
3747 
3748    uint64_t data[256];
3749    data[0] = FUNC_CODE_INST_GEP;
3750    data[1] = instr->gep.inbounds;
3751    data[2] = instr->gep.source_elem_type->id;
3752 
3753    assert(instr->gep.num_operands < ARRAY_SIZE(data) - 3);
3754    for (int i = 0; i < instr->gep.num_operands; ++i) {
3755       assert(instr->value.id > instr->gep.operands[i]->id);
3756       data[3 + i] = instr->value.id - instr->gep.operands[i]->id;
3757    }
3758    return emit_func_abbrev_record(m, FUNC_ABBREV_GEP,
3759                                   data, 3 + instr->gep.num_operands);
3760 }
3761 
3762 static bool
emit_load(struct dxil_module * m,struct dxil_instr * instr)3763 emit_load(struct dxil_module *m, struct dxil_instr *instr)
3764 {
3765    assert(instr->type == INSTR_LOAD);
3766    assert(instr->value.id > instr->load.ptr->id);
3767    assert(instr->load.type->id >= 0);
3768 
3769    uint64_t data[] = {
3770       instr->value.id - instr->load.ptr->id,
3771       instr->load.type->id,
3772       instr->load.align,
3773       instr->load.is_volatile
3774    };
3775    return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_LOAD,
3776                                 data, ARRAY_SIZE(data));
3777 }
3778 static bool
emit_store(struct dxil_module * m,struct dxil_instr * instr)3779 emit_store(struct dxil_module *m, struct dxil_instr *instr)
3780 {
3781    assert(instr->type == INSTR_STORE);
3782    assert(instr->value.id > instr->store.value->id);
3783    assert(instr->value.id > instr->store.ptr->id);
3784 
3785    uint64_t data[] = {
3786       instr->value.id - instr->store.ptr->id,
3787       instr->value.id - instr->store.value->id,
3788       instr->store.align,
3789       instr->store.is_volatile
3790    };
3791    return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_STORE,
3792                                 data, ARRAY_SIZE(data));
3793 }
3794 
3795 static bool
emit_cmpxchg(struct dxil_module * m,struct dxil_instr * instr)3796 emit_cmpxchg(struct dxil_module *m, struct dxil_instr *instr)
3797 {
3798    assert(instr->type == INSTR_CMPXCHG);
3799    assert(instr->value.id > instr->cmpxchg.cmpval->id);
3800    assert(instr->value.id > instr->cmpxchg.newval->id);
3801    assert(instr->value.id > instr->cmpxchg.ptr->id);
3802    uint64_t data[] = {
3803       instr->value.id - instr->cmpxchg.ptr->id,
3804       instr->value.id - instr->cmpxchg.cmpval->id,
3805       instr->value.id - instr->cmpxchg.newval->id,
3806       instr->cmpxchg.is_volatile,
3807       instr->cmpxchg.ordering,
3808       instr->cmpxchg.syncscope,
3809    };
3810    return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_CMPXCHG_OLD,
3811                                 data, ARRAY_SIZE(data));
3812 }
3813 
3814 static bool
emit_atomicrmw(struct dxil_module * m,struct dxil_instr * instr)3815 emit_atomicrmw(struct dxil_module *m, struct dxil_instr *instr)
3816 {
3817    assert(instr->type == INSTR_ATOMICRMW);
3818    assert(instr->value.id > instr->atomicrmw.value->id);
3819    assert(instr->value.id > instr->atomicrmw.ptr->id);
3820    uint64_t data[] = {
3821       instr->value.id - instr->atomicrmw.ptr->id,
3822       instr->value.id - instr->atomicrmw.value->id,
3823       instr->atomicrmw.op,
3824       instr->atomicrmw.is_volatile,
3825       instr->atomicrmw.ordering,
3826       instr->atomicrmw.syncscope,
3827    };
3828    return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_ATOMICRMW,
3829                                 data, ARRAY_SIZE(data));
3830 }
3831 
3832 static bool
emit_instr(struct dxil_module * m,struct dxil_func_def * func,struct dxil_instr * instr)3833 emit_instr(struct dxil_module *m, struct dxil_func_def *func, struct dxil_instr *instr)
3834 {
3835    switch (instr->type) {
3836    case INSTR_BINOP:
3837       return emit_binop(m, instr);
3838 
3839    case INSTR_CMP:
3840       return emit_cmp(m, instr);
3841 
3842    case INSTR_SELECT:
3843       return emit_select(m, instr);
3844 
3845    case INSTR_CAST:
3846       return emit_cast(m, instr);
3847 
3848    case INSTR_BR:
3849       return emit_branch(m, func, instr);
3850 
3851    case INSTR_PHI:
3852       return emit_phi(m, func, instr);
3853 
3854    case INSTR_CALL:
3855       return emit_call(m, instr);
3856 
3857    case INSTR_RET:
3858       return emit_ret(m, instr);
3859 
3860    case INSTR_EXTRACTVAL:
3861       return emit_extractval(m, instr);
3862 
3863    case INSTR_ALLOCA:
3864       return emit_alloca(m, instr);
3865 
3866    case INSTR_GEP:
3867       return emit_gep(m, instr);
3868 
3869    case INSTR_LOAD:
3870       return emit_load(m, instr);
3871 
3872    case INSTR_STORE:
3873       return emit_store(m, instr);
3874 
3875    case INSTR_ATOMICRMW:
3876       return emit_atomicrmw(m, instr);
3877 
3878    case INSTR_CMPXCHG:
3879       return emit_cmpxchg(m, instr);
3880 
3881    default:
3882       unreachable("unexpected instruction type");
3883    }
3884 }
3885 
3886 static bool
emit_function(struct dxil_module * m,struct dxil_func_def * func)3887 emit_function(struct dxil_module *m, struct dxil_func_def *func)
3888 {
3889    if (!enter_subblock(m, DXIL_FUNCTION_BLOCK, 4) ||
3890        !emit_record_int(m, FUNC_CODE_DECLAREBLOCKS, func->curr_block))
3891       return false;
3892 
3893    list_for_each_entry(struct dxil_instr, instr, &func->instr_list, head) {
3894       if (!emit_instr(m, func, instr))
3895          return false;
3896    }
3897 
3898    return exit_block(m);
3899 }
3900 
3901 static void
assign_values(struct dxil_module * m)3902 assign_values(struct dxil_module *m)
3903 {
3904    int next_value_id = 0;
3905 
3906    struct dxil_gvar *gvar;
3907    LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) {
3908       gvar->value.id = next_value_id++;
3909    }
3910 
3911    struct dxil_func *func;
3912    LIST_FOR_EACH_ENTRY(func, &m->func_list, head) {
3913       func->value.id = next_value_id++;
3914    }
3915 
3916    struct dxil_const *c;
3917    LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
3918       c->value.id = next_value_id++;
3919    }
3920 
3921    /* All functions start at this ID */
3922    unsigned value_id_at_functions_start = next_value_id;
3923 
3924    struct dxil_func_def *func_def;
3925    LIST_FOR_EACH_ENTRY(func_def, &m->func_def_list, head) {
3926       struct dxil_instr *instr;
3927       next_value_id = value_id_at_functions_start;
3928       LIST_FOR_EACH_ENTRY(instr, &func_def->instr_list, head) {
3929          instr->value.id = next_value_id;
3930          if (instr->has_value)
3931             next_value_id++;
3932       }
3933    }
3934 }
3935 
3936 bool
dxil_emit_module(struct dxil_module * m)3937 dxil_emit_module(struct dxil_module *m)
3938 {
3939    assign_values(m);
3940    if (!(dxil_buffer_emit_bits(&m->buf, 'B', 8) &&
3941          dxil_buffer_emit_bits(&m->buf, 'C', 8) &&
3942          dxil_buffer_emit_bits(&m->buf, 0xC0, 8) &&
3943          dxil_buffer_emit_bits(&m->buf, 0xDE, 8) &&
3944          enter_subblock(m, DXIL_MODULE, 3) &&
3945          emit_record_int(m, DXIL_MODULE_CODE_VERSION, 1) &&
3946          emit_blockinfo(m) &&
3947          emit_attrib_group_table(m) &&
3948          emit_attribute_table(m) &&
3949          emit_type_table(m) &&
3950          emit_module_info(m) &&
3951          emit_module_consts(m) &&
3952          emit_metadata(m) &&
3953          emit_value_symbol_table(m)))
3954       return false;
3955 
3956    struct dxil_func_def *func;
3957    LIST_FOR_EACH_ENTRY(func, &m->func_def_list, head) {
3958       if (!emit_function(m, func))
3959          return false;
3960    }
3961 
3962    return exit_block(m);
3963 }
3964