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