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