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