17ec681f3Smrg/*
27ec681f3Smrg * Copyright © Microsoft Corporation
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
217ec681f3Smrg * IN THE SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#include "dxil_module.h"
257ec681f3Smrg#include "dxil_internal.h"
267ec681f3Smrg
277ec681f3Smrg#include "util/macros.h"
287ec681f3Smrg#include "util/u_math.h"
297ec681f3Smrg#include "util/u_memory.h"
307ec681f3Smrg#include "util/rb_tree.h"
317ec681f3Smrg
327ec681f3Smrg#include <assert.h>
337ec681f3Smrg#include <stdio.h>
347ec681f3Smrg
357ec681f3Smrgvoid
367ec681f3Smrgdxil_module_init(struct dxil_module *m, void *ralloc_ctx)
377ec681f3Smrg{
387ec681f3Smrg   assert(ralloc_ctx);
397ec681f3Smrg
407ec681f3Smrg   memset(m, 0, sizeof(struct dxil_module));
417ec681f3Smrg   m->ralloc_ctx = ralloc_ctx;
427ec681f3Smrg
437ec681f3Smrg   dxil_buffer_init(&m->buf, 2);
447ec681f3Smrg   memset(&m->feats, 0, sizeof(m->feats));
457ec681f3Smrg
467ec681f3Smrg   list_inithead(&m->type_list);
477ec681f3Smrg   list_inithead(&m->func_list);
487ec681f3Smrg   list_inithead(&m->attr_set_list);
497ec681f3Smrg   list_inithead(&m->gvar_list);
507ec681f3Smrg   list_inithead(&m->const_list);
517ec681f3Smrg   list_inithead(&m->instr_list);
527ec681f3Smrg   list_inithead(&m->mdnode_list);
537ec681f3Smrg   list_inithead(&m->md_named_node_list);
547ec681f3Smrg
557ec681f3Smrg   m->functions = rzalloc(ralloc_ctx, struct rb_tree);
567ec681f3Smrg   rb_tree_init(m->functions);
577ec681f3Smrg
587ec681f3Smrg   m->curr_block = 0;
597ec681f3Smrg}
607ec681f3Smrg
617ec681f3Smrgvoid
627ec681f3Smrgdxil_module_release(struct dxil_module *m)
637ec681f3Smrg{
647ec681f3Smrg   dxil_buffer_finish(&m->buf);
657ec681f3Smrg}
667ec681f3Smrg
677ec681f3Smrgstatic bool
687ec681f3Smrgemit_bits64(struct dxil_buffer *b, uint64_t data, unsigned width)
697ec681f3Smrg{
707ec681f3Smrg   if (data > UINT32_MAX) {
717ec681f3Smrg      assert(width > 32);
727ec681f3Smrg      return dxil_buffer_emit_bits(b, (uint32_t)(data & UINT32_MAX), width) &&
737ec681f3Smrg             dxil_buffer_emit_bits(b, (uint32_t)(data >> 32), width - 32);
747ec681f3Smrg   } else
757ec681f3Smrg      return dxil_buffer_emit_bits(b, (uint32_t)data, width);
767ec681f3Smrg}
777ec681f3Smrg
787ec681f3Smrg/* See the LLVM documentation for details about what these are all about:
797ec681f3Smrg * https://www.llvm.org/docs/BitCodeFormat.html#abbreviation-ids
807ec681f3Smrg */
817ec681f3Smrgenum dxil_fixed_abbrev {
827ec681f3Smrg   DXIL_END_BLOCK = 0,
837ec681f3Smrg   DXIL_ENTER_SUBBLOCK = 1,
847ec681f3Smrg   DXIL_DEFINE_ABBREV = 2,
857ec681f3Smrg   DXIL_UNABBREV_RECORD = 3,
867ec681f3Smrg   DXIL_FIRST_APPLICATION_ABBREV = 4
877ec681f3Smrg};
887ec681f3Smrg
897ec681f3Smrgstatic bool
907ec681f3Smrgenter_subblock(struct dxil_module *m, unsigned id, unsigned abbrev_width)
917ec681f3Smrg{
927ec681f3Smrg   assert(m->num_blocks < ARRAY_SIZE(m->blocks));
937ec681f3Smrg   m->blocks[m->num_blocks].abbrev_width = m->buf.abbrev_width;
947ec681f3Smrg
957ec681f3Smrg   if (!dxil_buffer_emit_abbrev_id(&m->buf, DXIL_ENTER_SUBBLOCK) ||
967ec681f3Smrg       !dxil_buffer_emit_vbr_bits(&m->buf, id, 8) ||
977ec681f3Smrg       !dxil_buffer_emit_vbr_bits(&m->buf, abbrev_width, 4) ||
987ec681f3Smrg       !dxil_buffer_align(&m->buf))
997ec681f3Smrg      return false;
1007ec681f3Smrg
1017ec681f3Smrg   m->buf.abbrev_width = abbrev_width;
1027ec681f3Smrg   m->blocks[m->num_blocks++].offset = blob_reserve_uint32(&m->buf.blob);
1037ec681f3Smrg   return true;
1047ec681f3Smrg}
1057ec681f3Smrg
1067ec681f3Smrgstatic bool
1077ec681f3Smrgexit_block(struct dxil_module *m)
1087ec681f3Smrg{
1097ec681f3Smrg   assert(m->num_blocks > 0);
1107ec681f3Smrg   assert(m->num_blocks < ARRAY_SIZE(m->blocks));
1117ec681f3Smrg
1127ec681f3Smrg   if (!dxil_buffer_emit_abbrev_id(&m->buf, DXIL_END_BLOCK) ||
1137ec681f3Smrg       !dxil_buffer_align(&m->buf))
1147ec681f3Smrg      return false;
1157ec681f3Smrg
1167ec681f3Smrg   intptr_t size_offset = m->blocks[m->num_blocks - 1].offset;
1177ec681f3Smrg   uint32_t size = (m->buf.blob.size - size_offset - 1) / sizeof(uint32_t);
1187ec681f3Smrg   if (!blob_overwrite_uint32(&m->buf.blob, size_offset, size))
1197ec681f3Smrg      return false;
1207ec681f3Smrg
1217ec681f3Smrg   m->num_blocks--;
1227ec681f3Smrg   m->buf.abbrev_width = m->blocks[m->num_blocks].abbrev_width;
1237ec681f3Smrg   return true;
1247ec681f3Smrg}
1257ec681f3Smrg
1267ec681f3Smrgstatic bool
1277ec681f3Smrgemit_record_no_abbrev(struct dxil_buffer *b, unsigned code,
1287ec681f3Smrg                      const uint64_t *data, size_t size)
1297ec681f3Smrg{
1307ec681f3Smrg   if (!dxil_buffer_emit_abbrev_id(b, DXIL_UNABBREV_RECORD) ||
1317ec681f3Smrg       !dxil_buffer_emit_vbr_bits(b, code, 6) ||
1327ec681f3Smrg       !dxil_buffer_emit_vbr_bits(b, size, 6))
1337ec681f3Smrg      return false;
1347ec681f3Smrg
1357ec681f3Smrg   for (size_t i = 0; i < size; ++i)
1367ec681f3Smrg      if (!dxil_buffer_emit_vbr_bits(b, data[i], 6))
1377ec681f3Smrg         return false;
1387ec681f3Smrg
1397ec681f3Smrg   return true;
1407ec681f3Smrg}
1417ec681f3Smrg
1427ec681f3Smrgstatic bool
1437ec681f3Smrgemit_record(struct dxil_module *m, unsigned code,
1447ec681f3Smrg            const uint64_t *data, size_t size)
1457ec681f3Smrg{
1467ec681f3Smrg   return emit_record_no_abbrev(&m->buf, code, data, size);
1477ec681f3Smrg}
1487ec681f3Smrg
1497ec681f3Smrgstatic bool
1507ec681f3Smrgemit_record_int(struct dxil_module *m, unsigned code, int value)
1517ec681f3Smrg{
1527ec681f3Smrg   uint64_t data = value;
1537ec681f3Smrg   return emit_record(m, code, &data, 1);
1547ec681f3Smrg}
1557ec681f3Smrg
1567ec681f3Smrgstatic bool
1577ec681f3Smrgis_char6(char ch)
1587ec681f3Smrg{
1597ec681f3Smrg   if ((ch >= 'a' && ch <= 'z') ||
1607ec681f3Smrg       (ch >= 'A' && ch <= 'Z') ||
1617ec681f3Smrg       (ch >= '0' && ch <= '9'))
1627ec681f3Smrg     return true;
1637ec681f3Smrg
1647ec681f3Smrg   switch (ch) {
1657ec681f3Smrg   case '.':
1667ec681f3Smrg   case '_':
1677ec681f3Smrg      return true;
1687ec681f3Smrg
1697ec681f3Smrg   default:
1707ec681f3Smrg      return false;
1717ec681f3Smrg   }
1727ec681f3Smrg}
1737ec681f3Smrg
1747ec681f3Smrgstatic bool
1757ec681f3Smrgis_char6_string(const char *str)
1767ec681f3Smrg{
1777ec681f3Smrg   while (*str != '\0') {
1787ec681f3Smrg      if (!is_char6(*str++))
1797ec681f3Smrg         return false;
1807ec681f3Smrg   }
1817ec681f3Smrg   return true;
1827ec681f3Smrg}
1837ec681f3Smrg
1847ec681f3Smrgstatic bool
1857ec681f3Smrgis_char7_string(const char *str)
1867ec681f3Smrg{
1877ec681f3Smrg   while (*str != '\0') {
1887ec681f3Smrg      if (*str++ & 0x80)
1897ec681f3Smrg         return false;
1907ec681f3Smrg   }
1917ec681f3Smrg   return true;
1927ec681f3Smrg}
1937ec681f3Smrg
1947ec681f3Smrgstatic unsigned
1957ec681f3Smrgencode_char6(char ch)
1967ec681f3Smrg{
1977ec681f3Smrg   const int letters = 'z' - 'a' + 1;
1987ec681f3Smrg
1997ec681f3Smrg   if (ch >= 'a' && ch <= 'z')
2007ec681f3Smrg      return ch - 'a';
2017ec681f3Smrg   else if (ch >= 'A' && ch <= 'Z')
2027ec681f3Smrg      return letters + ch - 'A';
2037ec681f3Smrg   else if (ch >= '0' && ch <= '9')
2047ec681f3Smrg      return 2 * letters + ch - '0';
2057ec681f3Smrg
2067ec681f3Smrg   switch (ch) {
2077ec681f3Smrg   case '.': return 62;
2087ec681f3Smrg   case '_': return 63;
2097ec681f3Smrg   default:
2107ec681f3Smrg      unreachable("invalid char6-character");
2117ec681f3Smrg   }
2127ec681f3Smrg}
2137ec681f3Smrg
2147ec681f3Smrgstatic bool
2157ec681f3Smrgemit_fixed(struct dxil_buffer *b, uint64_t data, unsigned width)
2167ec681f3Smrg{
2177ec681f3Smrg   if (!width)
2187ec681f3Smrg      return true;
2197ec681f3Smrg
2207ec681f3Smrg   return emit_bits64(b, data, width);
2217ec681f3Smrg}
2227ec681f3Smrg
2237ec681f3Smrgstatic bool
2247ec681f3Smrgemit_vbr(struct dxil_buffer *b, uint64_t data, unsigned width)
2257ec681f3Smrg{
2267ec681f3Smrg   if (!width)
2277ec681f3Smrg      return true;
2287ec681f3Smrg
2297ec681f3Smrg   return dxil_buffer_emit_vbr_bits(b, data, width);
2307ec681f3Smrg}
2317ec681f3Smrg
2327ec681f3Smrgstatic bool
2337ec681f3Smrgemit_char6(struct dxil_buffer *b, uint64_t data)
2347ec681f3Smrg{
2357ec681f3Smrg   return dxil_buffer_emit_bits(b, encode_char6((char)data), 6);
2367ec681f3Smrg}
2377ec681f3Smrg
2387ec681f3Smrgstruct dxil_abbrev {
2397ec681f3Smrg   struct {
2407ec681f3Smrg      enum {
2417ec681f3Smrg         DXIL_OP_LITERAL = 0,
2427ec681f3Smrg         DXIL_OP_FIXED = 1,
2437ec681f3Smrg         DXIL_OP_VBR = 2,
2447ec681f3Smrg         DXIL_OP_ARRAY = 3,
2457ec681f3Smrg         DXIL_OP_CHAR6 = 4,
2467ec681f3Smrg         DXIL_OP_BLOB = 5
2477ec681f3Smrg      } type;
2487ec681f3Smrg      union {
2497ec681f3Smrg         uint64_t value;
2507ec681f3Smrg         uint64_t encoding_data;
2517ec681f3Smrg      };
2527ec681f3Smrg   } operands[7];
2537ec681f3Smrg   size_t num_operands;
2547ec681f3Smrg};
2557ec681f3Smrg
2567ec681f3Smrgstatic bool
2577ec681f3Smrgemit_record_abbrev(struct dxil_buffer *b,
2587ec681f3Smrg                   unsigned abbrev, const struct dxil_abbrev *a,
2597ec681f3Smrg                   const uint64_t *data, size_t size)
2607ec681f3Smrg{
2617ec681f3Smrg   assert(abbrev >= DXIL_FIRST_APPLICATION_ABBREV);
2627ec681f3Smrg
2637ec681f3Smrg   if (!dxil_buffer_emit_abbrev_id(b, abbrev))
2647ec681f3Smrg      return false;
2657ec681f3Smrg
2667ec681f3Smrg   size_t curr_data = 0;
2677ec681f3Smrg   for (int i = 0; i < a->num_operands; ++i) {
2687ec681f3Smrg      switch (a->operands[i].type) {
2697ec681f3Smrg      case DXIL_OP_LITERAL:
2707ec681f3Smrg         assert(curr_data < size);
2717ec681f3Smrg         assert(data[curr_data] == a->operands[i].value);
2727ec681f3Smrg         curr_data++;
2737ec681f3Smrg         /* literals are no-ops, because their value is defined in the
2747ec681f3Smrg            abbrev-definition already */
2757ec681f3Smrg         break;
2767ec681f3Smrg
2777ec681f3Smrg      case DXIL_OP_FIXED:
2787ec681f3Smrg         assert(curr_data < size);
2797ec681f3Smrg         if (!emit_fixed(b, data[curr_data++], a->operands[i].encoding_data))
2807ec681f3Smrg            return false;
2817ec681f3Smrg         break;
2827ec681f3Smrg
2837ec681f3Smrg      case DXIL_OP_VBR:
2847ec681f3Smrg         assert(curr_data < size);
2857ec681f3Smrg         if (!emit_vbr(b, data[curr_data++], a->operands[i].encoding_data))
2867ec681f3Smrg            return false;
2877ec681f3Smrg         break;
2887ec681f3Smrg
2897ec681f3Smrg      case DXIL_OP_ARRAY:
2907ec681f3Smrg         assert(i == a->num_operands - 2); /* arrays should always be second to last */
2917ec681f3Smrg
2927ec681f3Smrg         if (!dxil_buffer_emit_vbr_bits(b, size - curr_data, 6))
2937ec681f3Smrg            return false;
2947ec681f3Smrg
2957ec681f3Smrg         switch (a->operands[i + 1].type) {
2967ec681f3Smrg         case DXIL_OP_FIXED:
2977ec681f3Smrg            while (curr_data < size)
2987ec681f3Smrg               if (!emit_fixed(b, data[curr_data++], a->operands[i + 1].encoding_data))
2997ec681f3Smrg                  return false;
3007ec681f3Smrg            break;
3017ec681f3Smrg
3027ec681f3Smrg         case DXIL_OP_VBR:
3037ec681f3Smrg            while (curr_data < size)
3047ec681f3Smrg               if (!emit_vbr(b, data[curr_data++], a->operands[i + 1].encoding_data))
3057ec681f3Smrg                  return false;
3067ec681f3Smrg            break;
3077ec681f3Smrg
3087ec681f3Smrg         case DXIL_OP_CHAR6:
3097ec681f3Smrg            while (curr_data < size)
3107ec681f3Smrg               if (!emit_char6(b, data[curr_data++]))
3117ec681f3Smrg                  return false;
3127ec681f3Smrg            break;
3137ec681f3Smrg
3147ec681f3Smrg         default:
3157ec681f3Smrg            unreachable("unexpected operand type");
3167ec681f3Smrg         }
3177ec681f3Smrg         return true; /* we're done */
3187ec681f3Smrg
3197ec681f3Smrg      case DXIL_OP_CHAR6:
3207ec681f3Smrg         assert(curr_data < size);
3217ec681f3Smrg         if (!emit_char6(b, data[curr_data++]))
3227ec681f3Smrg            return false;
3237ec681f3Smrg         break;
3247ec681f3Smrg
3257ec681f3Smrg      case DXIL_OP_BLOB:
3267ec681f3Smrg         unreachable("HALP, unplement!");
3277ec681f3Smrg
3287ec681f3Smrg      default:
3297ec681f3Smrg         unreachable("unexpected operand type");
3307ec681f3Smrg      }
3317ec681f3Smrg   }
3327ec681f3Smrg
3337ec681f3Smrg   assert(curr_data == size);
3347ec681f3Smrg   return true;
3357ec681f3Smrg}
3367ec681f3Smrg
3377ec681f3Smrg
3387ec681f3Smrgstatic struct dxil_type *
3397ec681f3Smrgcreate_type(struct dxil_module *m, enum type_type type)
3407ec681f3Smrg{
3417ec681f3Smrg   struct dxil_type *ret = rzalloc_size(m->ralloc_ctx,
3427ec681f3Smrg                                        sizeof(struct dxil_type));
3437ec681f3Smrg   if (ret) {
3447ec681f3Smrg      ret->type = type;
3457ec681f3Smrg      ret->id = list_length(&m->type_list);
3467ec681f3Smrg      list_addtail(&ret->head, &m->type_list);
3477ec681f3Smrg   }
3487ec681f3Smrg   return ret;
3497ec681f3Smrg}
3507ec681f3Smrg
3517ec681f3Smrgstatic bool
3527ec681f3Smrgtypes_equal(const struct dxil_type *lhs, const struct dxil_type *rhs);
3537ec681f3Smrg
3547ec681f3Smrgstatic bool
3557ec681f3Smrgtype_list_equal(const struct dxil_type_list *lhs,
3567ec681f3Smrg                const struct dxil_type_list *rhs)
3577ec681f3Smrg{
3587ec681f3Smrg   if (lhs->num_types != rhs->num_types)
3597ec681f3Smrg      return false;
3607ec681f3Smrg   for (unsigned i = 0; i < lhs->num_types; ++i)
3617ec681f3Smrg      if (!types_equal(lhs->types[i],  rhs->types[i]))
3627ec681f3Smrg          return false;
3637ec681f3Smrg   return true;
3647ec681f3Smrg}
3657ec681f3Smrg
3667ec681f3Smrgstatic bool
3677ec681f3Smrgtypes_equal(const struct dxil_type *lhs, const struct dxil_type *rhs)
3687ec681f3Smrg{
3697ec681f3Smrg   if (lhs == rhs)
3707ec681f3Smrg      return true;
3717ec681f3Smrg
3727ec681f3Smrg   /* Below we only assert that different type pointers really define different types
3737ec681f3Smrg    * Since this function is only called in asserts, it is not needed to put the code
3747ec681f3Smrg    * into a #ifdef NDEBUG statement */
3757ec681f3Smrg   if (lhs->type != rhs->type)
3767ec681f3Smrg      return false;
3777ec681f3Smrg
3787ec681f3Smrg   bool retval = false;
3797ec681f3Smrg   switch (lhs->type) {
3807ec681f3Smrg   case TYPE_VOID:
3817ec681f3Smrg      retval = true;
3827ec681f3Smrg      break;
3837ec681f3Smrg   case TYPE_FLOAT:
3847ec681f3Smrg      retval = lhs->float_bits == rhs->float_bits;
3857ec681f3Smrg      break;
3867ec681f3Smrg   case TYPE_INTEGER:
3877ec681f3Smrg      retval = lhs->int_bits == rhs->int_bits;
3887ec681f3Smrg      break;
3897ec681f3Smrg   case TYPE_POINTER:
3907ec681f3Smrg      retval = types_equal(lhs->ptr_target_type, rhs->ptr_target_type);
3917ec681f3Smrg      break;
3927ec681f3Smrg   case TYPE_ARRAY:
3937ec681f3Smrg   case TYPE_VECTOR:
3947ec681f3Smrg      retval = (lhs->array_or_vector_def.num_elems == rhs->array_or_vector_def.num_elems) &&
3957ec681f3Smrg               types_equal(lhs->array_or_vector_def.elem_type,
3967ec681f3Smrg                           rhs->array_or_vector_def.elem_type);
3977ec681f3Smrg      break;
3987ec681f3Smrg   case TYPE_FUNCTION:
3997ec681f3Smrg      if (!types_equal(lhs->function_def.ret_type,
4007ec681f3Smrg                            rhs->function_def.ret_type))
4017ec681f3Smrg         return false;
4027ec681f3Smrg      retval = type_list_equal(&lhs->function_def.args, &rhs->function_def.args);
4037ec681f3Smrg      break;
4047ec681f3Smrg   case TYPE_STRUCT:
4057ec681f3Smrg      retval = type_list_equal(&lhs->struct_def.elem, &rhs->struct_def.elem);
4067ec681f3Smrg   }
4077ec681f3Smrg   assert(!retval && "Types are equal in structure but not as pointers");
4087ec681f3Smrg   return retval;
4097ec681f3Smrg}
4107ec681f3Smrg
4117ec681f3Smrgbool
4127ec681f3Smrgdxil_value_type_equal_to(const struct dxil_value *value,
4137ec681f3Smrg                         const struct dxil_type *rhs)
4147ec681f3Smrg{
4157ec681f3Smrg   return types_equal(value->type, rhs);
4167ec681f3Smrg}
4177ec681f3Smrg
4187ec681f3Smrgnir_alu_type
4197ec681f3Smrgdxil_type_to_nir_type(const struct dxil_type *type)
4207ec681f3Smrg{
4217ec681f3Smrg   assert(type);
4227ec681f3Smrg   switch (type->type) {
4237ec681f3Smrg   case TYPE_INTEGER:
4247ec681f3Smrg      return type->int_bits == 1 ? nir_type_bool : nir_type_int;
4257ec681f3Smrg   case TYPE_FLOAT:
4267ec681f3Smrg      return nir_type_float;
4277ec681f3Smrg   default:
4287ec681f3Smrg      unreachable("Unexpected type in dxil_type_to_nir_type");
4297ec681f3Smrg   }
4307ec681f3Smrg}
4317ec681f3Smrg
4327ec681f3Smrgbool
4337ec681f3Smrgdxil_value_type_bitsize_equal_to(const struct dxil_value *value, unsigned bitsize)
4347ec681f3Smrg{
4357ec681f3Smrg   switch (value->type->type) {
4367ec681f3Smrg   case TYPE_INTEGER:
4377ec681f3Smrg      return value->type->int_bits == bitsize;
4387ec681f3Smrg   case TYPE_FLOAT:
4397ec681f3Smrg      return value->type->float_bits == bitsize;
4407ec681f3Smrg   default:
4417ec681f3Smrg      return false;
4427ec681f3Smrg   }
4437ec681f3Smrg}
4447ec681f3Smrg
4457ec681f3Smrgconst struct dxil_type *
4467ec681f3Smrgdxil_value_get_type(const struct dxil_value *value)
4477ec681f3Smrg{
4487ec681f3Smrg   return value->type;
4497ec681f3Smrg}
4507ec681f3Smrg
4517ec681f3Smrgconst struct dxil_type *
4527ec681f3Smrgdxil_module_get_void_type(struct dxil_module *m)
4537ec681f3Smrg{
4547ec681f3Smrg   if (!m->void_type)
4557ec681f3Smrg      m->void_type = create_type(m, TYPE_VOID);
4567ec681f3Smrg   return m->void_type;
4577ec681f3Smrg}
4587ec681f3Smrg
4597ec681f3Smrgstatic const struct dxil_type *
4607ec681f3Smrgcreate_int_type(struct dxil_module *m, unsigned bit_size)
4617ec681f3Smrg{
4627ec681f3Smrg   struct dxil_type *type = create_type(m, TYPE_INTEGER);
4637ec681f3Smrg   if (type)
4647ec681f3Smrg      type->int_bits = bit_size;
4657ec681f3Smrg   return type;
4667ec681f3Smrg}
4677ec681f3Smrg
4687ec681f3Smrgstatic const struct dxil_type *
4697ec681f3Smrgget_int1_type(struct dxil_module *m)
4707ec681f3Smrg{
4717ec681f3Smrg   if (!m->int1_type)
4727ec681f3Smrg      m->int1_type = create_int_type(m, 1);
4737ec681f3Smrg   return m->int1_type;
4747ec681f3Smrg}
4757ec681f3Smrg
4767ec681f3Smrgstatic const struct dxil_type *
4777ec681f3Smrgget_int8_type(struct dxil_module *m)
4787ec681f3Smrg{
4797ec681f3Smrg   if (!m->int8_type)
4807ec681f3Smrg      m->int8_type = create_int_type(m, 8);
4817ec681f3Smrg   return m->int8_type;
4827ec681f3Smrg}
4837ec681f3Smrg
4847ec681f3Smrgstatic const struct dxil_type *
4857ec681f3Smrgget_int16_type(struct dxil_module *m)
4867ec681f3Smrg{
4877ec681f3Smrg   if (!m->int16_type)
4887ec681f3Smrg      m->int16_type = create_int_type(m, 16);
4897ec681f3Smrg   return m->int16_type;
4907ec681f3Smrg}
4917ec681f3Smrg
4927ec681f3Smrgstatic const struct dxil_type *
4937ec681f3Smrgget_int32_type(struct dxil_module *m)
4947ec681f3Smrg{
4957ec681f3Smrg   if (!m->int32_type)
4967ec681f3Smrg      m->int32_type = create_int_type(m, 32);
4977ec681f3Smrg   return m->int32_type;
4987ec681f3Smrg}
4997ec681f3Smrg
5007ec681f3Smrgstatic const struct dxil_type *
5017ec681f3Smrgget_int64_type(struct dxil_module *m)
5027ec681f3Smrg{
5037ec681f3Smrg   if (!m->int64_type)
5047ec681f3Smrg      m->int64_type = create_int_type(m, 64);
5057ec681f3Smrg   return m->int64_type;
5067ec681f3Smrg}
5077ec681f3Smrg
5087ec681f3Smrgstatic const struct dxil_type *
5097ec681f3Smrgcreate_float_type(struct dxil_module *m, unsigned bit_size)
5107ec681f3Smrg{
5117ec681f3Smrg   struct dxil_type *type = create_type(m, TYPE_FLOAT);
5127ec681f3Smrg   if (type)
5137ec681f3Smrg      type->float_bits = bit_size;
5147ec681f3Smrg   return type;
5157ec681f3Smrg}
5167ec681f3Smrg
5177ec681f3Smrgconst struct dxil_type *
5187ec681f3Smrgdxil_module_get_int_type(struct dxil_module *m, unsigned bit_size)
5197ec681f3Smrg{
5207ec681f3Smrg   switch (bit_size) {
5217ec681f3Smrg   case 1: return get_int1_type(m);
5227ec681f3Smrg   case 8: return get_int8_type(m);
5237ec681f3Smrg   case 16: return get_int16_type(m);
5247ec681f3Smrg   case 32: return get_int32_type(m);
5257ec681f3Smrg   case 64: return get_int64_type(m);
5267ec681f3Smrg   default:
5277ec681f3Smrg      unreachable("unsupported bit-width");
5287ec681f3Smrg   }
5297ec681f3Smrg}
5307ec681f3Smrg
5317ec681f3Smrgstatic const struct dxil_type *
5327ec681f3Smrgget_float16_type(struct dxil_module *m)
5337ec681f3Smrg{
5347ec681f3Smrg   if (!m->float16_type)
5357ec681f3Smrg      m->float16_type = create_float_type(m, 16);
5367ec681f3Smrg   return m->float16_type;
5377ec681f3Smrg}
5387ec681f3Smrg
5397ec681f3Smrgstatic const struct dxil_type *
5407ec681f3Smrgget_float32_type(struct dxil_module *m)
5417ec681f3Smrg{
5427ec681f3Smrg   if (!m->float32_type)
5437ec681f3Smrg      m->float32_type = create_float_type(m, 32);
5447ec681f3Smrg   return m->float32_type;
5457ec681f3Smrg}
5467ec681f3Smrg
5477ec681f3Smrgstatic const struct dxil_type *
5487ec681f3Smrgget_float64_type(struct dxil_module *m)
5497ec681f3Smrg{
5507ec681f3Smrg   if (!m->float64_type)
5517ec681f3Smrg      m->float64_type = create_float_type(m, 64);
5527ec681f3Smrg   return m->float64_type;
5537ec681f3Smrg}
5547ec681f3Smrg
5557ec681f3Smrgconst struct dxil_type *
5567ec681f3Smrgdxil_module_get_float_type(struct dxil_module *m, unsigned bit_size)
5577ec681f3Smrg{
5587ec681f3Smrg   switch (bit_size) {
5597ec681f3Smrg   case 16: return get_float16_type(m);
5607ec681f3Smrg   case 32: return get_float32_type(m);
5617ec681f3Smrg   case 64: return get_float64_type(m);
5627ec681f3Smrg   default:
5637ec681f3Smrg      unreachable("unsupported bit-width");
5647ec681f3Smrg   }
5657ec681f3Smrg   return get_float32_type(m);
5667ec681f3Smrg}
5677ec681f3Smrg
5687ec681f3Smrgconst struct dxil_type *
5697ec681f3Smrgdxil_module_get_pointer_type(struct dxil_module *m,
5707ec681f3Smrg                             const struct dxil_type *target)
5717ec681f3Smrg{
5727ec681f3Smrg   struct dxil_type *type;
5737ec681f3Smrg   LIST_FOR_EACH_ENTRY(type, &m->type_list, head) {
5747ec681f3Smrg      if (type->type == TYPE_POINTER &&
5757ec681f3Smrg          type->ptr_target_type == target)
5767ec681f3Smrg         return type;
5777ec681f3Smrg   }
5787ec681f3Smrg
5797ec681f3Smrg   type = create_type(m, TYPE_POINTER);
5807ec681f3Smrg   if (type)
5817ec681f3Smrg      type->ptr_target_type = target;
5827ec681f3Smrg   return type;
5837ec681f3Smrg}
5847ec681f3Smrg
5857ec681f3Smrgconst struct dxil_type *
5867ec681f3Smrgdxil_module_get_struct_type(struct dxil_module *m,
5877ec681f3Smrg                            const char *name,
5887ec681f3Smrg                            const struct dxil_type **elem_types,
5897ec681f3Smrg                            size_t num_elem_types)
5907ec681f3Smrg{
5917ec681f3Smrg   assert(!name || strlen(name) > 0);
5927ec681f3Smrg
5937ec681f3Smrg   struct dxil_type *type;
5947ec681f3Smrg   LIST_FOR_EACH_ENTRY(type, &m->type_list, head) {
5957ec681f3Smrg      if (type->type != TYPE_STRUCT)
5967ec681f3Smrg         continue;
5977ec681f3Smrg
5987ec681f3Smrg      if ((name == NULL) != (type->struct_def.name == NULL))
5997ec681f3Smrg         continue;
6007ec681f3Smrg
6017ec681f3Smrg      if (name && strcmp(type->struct_def.name, name))
6027ec681f3Smrg         continue;
6037ec681f3Smrg
6047ec681f3Smrg      if (type->struct_def.elem.num_types == num_elem_types &&
6057ec681f3Smrg          !memcmp(type->struct_def.elem.types, elem_types,
6067ec681f3Smrg                  sizeof(struct dxil_type *) * num_elem_types))
6077ec681f3Smrg         return type;
6087ec681f3Smrg   }
6097ec681f3Smrg
6107ec681f3Smrg   type = create_type(m, TYPE_STRUCT);
6117ec681f3Smrg   if (type) {
6127ec681f3Smrg      if (name) {
6137ec681f3Smrg         type->struct_def.name = ralloc_strdup(type, name);
6147ec681f3Smrg         if (!type->struct_def.name)
6157ec681f3Smrg            return NULL;
6167ec681f3Smrg      } else
6177ec681f3Smrg         type->struct_def.name = NULL;
6187ec681f3Smrg
6197ec681f3Smrg      type->struct_def.elem.types = ralloc_array(type, struct dxil_type *,
6207ec681f3Smrg                                                 num_elem_types);
6217ec681f3Smrg      if (!type->struct_def.elem.types)
6227ec681f3Smrg         return NULL;
6237ec681f3Smrg
6247ec681f3Smrg      memcpy(type->struct_def.elem.types, elem_types,
6257ec681f3Smrg             sizeof(struct dxil_type *) * num_elem_types);
6267ec681f3Smrg      type->struct_def.elem.num_types = num_elem_types;
6277ec681f3Smrg   }
6287ec681f3Smrg   return type;
6297ec681f3Smrg}
6307ec681f3Smrg
6317ec681f3Smrgconst struct dxil_type *
6327ec681f3Smrgdxil_module_get_array_type(struct dxil_module *m,
6337ec681f3Smrg                           const struct dxil_type *elem_type,
6347ec681f3Smrg                           size_t num_elems)
6357ec681f3Smrg{
6367ec681f3Smrg   struct dxil_type *type;
6377ec681f3Smrg   LIST_FOR_EACH_ENTRY(type, &m->type_list, head) {
6387ec681f3Smrg      if (type->type != TYPE_ARRAY)
6397ec681f3Smrg         continue;
6407ec681f3Smrg
6417ec681f3Smrg      if (type->array_or_vector_def.elem_type == elem_type &&
6427ec681f3Smrg          type->array_or_vector_def.num_elems == num_elems)
6437ec681f3Smrg         return type;
6447ec681f3Smrg   }
6457ec681f3Smrg
6467ec681f3Smrg   type = create_type(m, TYPE_ARRAY);
6477ec681f3Smrg   if (type) {
6487ec681f3Smrg      type->array_or_vector_def.elem_type = elem_type;
6497ec681f3Smrg      type->array_or_vector_def.num_elems = num_elems;
6507ec681f3Smrg   }
6517ec681f3Smrg   return type;
6527ec681f3Smrg}
6537ec681f3Smrg
6547ec681f3Smrgconst struct dxil_type *
6557ec681f3Smrgdxil_module_get_vector_type(struct dxil_module *m,
6567ec681f3Smrg                            const struct dxil_type *elem_type,
6577ec681f3Smrg                            size_t num_elems)
6587ec681f3Smrg{
6597ec681f3Smrg   struct dxil_type *type;
6607ec681f3Smrg   LIST_FOR_EACH_ENTRY(type, &m->type_list, head) {
6617ec681f3Smrg      if (type->type == TYPE_VECTOR &&
6627ec681f3Smrg          type->array_or_vector_def.elem_type == elem_type &&
6637ec681f3Smrg          type->array_or_vector_def.num_elems == num_elems)
6647ec681f3Smrg         return type;
6657ec681f3Smrg   }
6667ec681f3Smrg
6677ec681f3Smrg   type = create_type(m, TYPE_VECTOR);
6687ec681f3Smrg   if (!type)
6697ec681f3Smrg      return NULL;
6707ec681f3Smrg
6717ec681f3Smrg   type->array_or_vector_def.elem_type = elem_type;
6727ec681f3Smrg   type->array_or_vector_def.num_elems = num_elems;
6737ec681f3Smrg   return type;
6747ec681f3Smrg}
6757ec681f3Smrg
6767ec681f3Smrgconst struct dxil_type *
6777ec681f3Smrgdxil_get_overload_type(struct dxil_module *mod, enum overload_type overload)
6787ec681f3Smrg{
6797ec681f3Smrg   switch (overload) {
6807ec681f3Smrg   case DXIL_I16: return get_int16_type(mod);
6817ec681f3Smrg   case DXIL_I32: return get_int32_type(mod);
6827ec681f3Smrg   case DXIL_I64: return get_int64_type(mod);
6837ec681f3Smrg   case DXIL_F16: return get_float16_type(mod);
6847ec681f3Smrg   case DXIL_F32: return get_float32_type(mod);
6857ec681f3Smrg   case DXIL_F64: return get_float64_type(mod);
6867ec681f3Smrg   default:
6877ec681f3Smrg      unreachable("unexpected overload type");
6887ec681f3Smrg   }
6897ec681f3Smrg}
6907ec681f3Smrg
6917ec681f3Smrgconst struct dxil_type *
6927ec681f3Smrgdxil_module_get_handle_type(struct dxil_module *m)
6937ec681f3Smrg{
6947ec681f3Smrg   const struct dxil_type *int8_type = get_int8_type(m);
6957ec681f3Smrg   if (!int8_type)
6967ec681f3Smrg      return NULL;
6977ec681f3Smrg
6987ec681f3Smrg   const struct dxil_type *ptr_type = dxil_module_get_pointer_type(m, int8_type);
6997ec681f3Smrg   if (!ptr_type)
7007ec681f3Smrg      return NULL;
7017ec681f3Smrg
7027ec681f3Smrg   return dxil_module_get_struct_type(m, "dx.types.Handle", &ptr_type, 1);
7037ec681f3Smrg}
7047ec681f3Smrg
7057ec681f3Smrgconst struct dxil_type *
7067ec681f3Smrgdxil_module_get_cbuf_ret_type(struct dxil_module *mod, enum overload_type overload)
7077ec681f3Smrg{
7087ec681f3Smrg   const struct dxil_type *overload_type = dxil_get_overload_type(mod, overload);
7097ec681f3Smrg   const struct dxil_type *fields[4] = { overload_type, overload_type, overload_type, overload_type };
7107ec681f3Smrg   unsigned num_fields;
7117ec681f3Smrg
7127ec681f3Smrg   char name[64];
7137ec681f3Smrg   snprintf(name, sizeof(name), "dx.types.CBufRet.%s", dxil_overload_suffix(overload));
7147ec681f3Smrg
7157ec681f3Smrg   switch (overload) {
7167ec681f3Smrg   case DXIL_I32:
7177ec681f3Smrg   case DXIL_F32:
7187ec681f3Smrg      num_fields = 4;
7197ec681f3Smrg      break;
7207ec681f3Smrg   case DXIL_I64:
7217ec681f3Smrg   case DXIL_F64:
7227ec681f3Smrg      num_fields = 2;
7237ec681f3Smrg      break;
7247ec681f3Smrg   default:
7257ec681f3Smrg      unreachable("unexpected overload type");
7267ec681f3Smrg   }
7277ec681f3Smrg
7287ec681f3Smrg   return dxil_module_get_struct_type(mod, name, fields, num_fields);
7297ec681f3Smrg}
7307ec681f3Smrg
7317ec681f3Smrgconst struct dxil_type *
7327ec681f3Smrgdxil_module_get_split_double_ret_type(struct dxil_module *mod)
7337ec681f3Smrg{
7347ec681f3Smrg   const struct dxil_type *int32_type = dxil_module_get_int_type(mod, 32);
7357ec681f3Smrg   const struct dxil_type *fields[2] = { int32_type, int32_type };
7367ec681f3Smrg
7377ec681f3Smrg   return dxil_module_get_struct_type(mod, "dx.types.splitDouble", fields, 2);
7387ec681f3Smrg}
7397ec681f3Smrg
7407ec681f3Smrgstatic const struct dxil_type *
7417ec681f3Smrgdxil_module_get_type_from_comp_type(struct dxil_module *m, enum dxil_component_type comp_type)
7427ec681f3Smrg{
7437ec681f3Smrg   switch (comp_type) {
7447ec681f3Smrg   case DXIL_COMP_TYPE_U32: return get_int32_type(m);
7457ec681f3Smrg   case DXIL_COMP_TYPE_I32: return get_int32_type(m);
7467ec681f3Smrg   case DXIL_COMP_TYPE_F32: return get_float32_type(m);
7477ec681f3Smrg   case DXIL_COMP_TYPE_F64: return get_float64_type(m);
7487ec681f3Smrg   case DXIL_COMP_TYPE_U16: return get_int16_type(m);
7497ec681f3Smrg   case DXIL_COMP_TYPE_I16: return get_int16_type(m);
7507ec681f3Smrg   case DXIL_COMP_TYPE_U64: return get_int64_type(m);
7517ec681f3Smrg   case DXIL_COMP_TYPE_I64: return get_int64_type(m);
7527ec681f3Smrg   case DXIL_COMP_TYPE_I1: return get_int1_type(m);
7537ec681f3Smrg
7547ec681f3Smrg   case DXIL_COMP_TYPE_F16:
7557ec681f3Smrg   default:
7567ec681f3Smrg      unreachable("unexpected component type");
7577ec681f3Smrg   }
7587ec681f3Smrg}
7597ec681f3Smrg
7607ec681f3Smrgstatic const char *
7617ec681f3Smrgget_res_comp_type_name(enum dxil_component_type comp_type)
7627ec681f3Smrg{
7637ec681f3Smrg   switch (comp_type) {
7647ec681f3Smrg   case DXIL_COMP_TYPE_F64: return "double";
7657ec681f3Smrg   case DXIL_COMP_TYPE_F32: return "float";
7667ec681f3Smrg   case DXIL_COMP_TYPE_I32: return "int";
7677ec681f3Smrg   case DXIL_COMP_TYPE_U32: return "uint";
7687ec681f3Smrg   case DXIL_COMP_TYPE_I64: return "int64";
7697ec681f3Smrg   case DXIL_COMP_TYPE_U64: return "uint64";
7707ec681f3Smrg   default:
7717ec681f3Smrg      unreachable("unexpected resource component type");
7727ec681f3Smrg   }
7737ec681f3Smrg}
7747ec681f3Smrg
7757ec681f3Smrgstatic const char *
7767ec681f3Smrgget_res_dimension_type_name(enum dxil_resource_kind kind)
7777ec681f3Smrg{
7787ec681f3Smrg   switch (kind) {
7797ec681f3Smrg   case DXIL_RESOURCE_KIND_TYPED_BUFFER: return "Buffer";
7807ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE1D: return "Texture1D";
7817ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE1D_ARRAY: return "Texture1DArray";
7827ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE2D: return "Texture2D";
7837ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE2DMS: return "Texture2DMS";
7847ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE2D_ARRAY: return "Texture2DArray";
7857ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY: return "Texture2DMSArray";
7867ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE3D: return "Texture3D";
7877ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURECUBE: return "TextureCube";
7887ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURECUBE_ARRAY: return "TextureCubeArray";
7897ec681f3Smrg   default:
7907ec681f3Smrg      unreachable("unexpected resource kind");
7917ec681f3Smrg   }
7927ec681f3Smrg}
7937ec681f3Smrg
7947ec681f3Smrgstatic const char *
7957ec681f3Smrgget_res_ms_postfix(enum dxil_resource_kind kind)
7967ec681f3Smrg{
7977ec681f3Smrg   switch (kind) {
7987ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE2DMS:
7997ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY:
8007ec681f3Smrg      return ", 0";
8017ec681f3Smrg
8027ec681f3Smrg   default:
8037ec681f3Smrg      return " ";
8047ec681f3Smrg   }
8057ec681f3Smrg}
8067ec681f3Smrgconst struct dxil_type *
8077ec681f3Smrgdxil_module_get_res_type(struct dxil_module *m, enum dxil_resource_kind kind,
8087ec681f3Smrg                         enum dxil_component_type comp_type, bool readwrite)
8097ec681f3Smrg{
8107ec681f3Smrg   switch (kind) {
8117ec681f3Smrg   case DXIL_RESOURCE_KIND_TYPED_BUFFER:
8127ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE1D:
8137ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE1D_ARRAY:
8147ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE2D:
8157ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE2D_ARRAY:
8167ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE2DMS:
8177ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY:
8187ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURE3D:
8197ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURECUBE:
8207ec681f3Smrg   case DXIL_RESOURCE_KIND_TEXTURECUBE_ARRAY:
8217ec681f3Smrg   {
8227ec681f3Smrg      const struct dxil_type *component_type = dxil_module_get_type_from_comp_type(m, comp_type);
8237ec681f3Smrg      const struct dxil_type *vec_type = dxil_module_get_vector_type(m, component_type, 4);
8247ec681f3Smrg      char class_name[64] = { 0 };
8257ec681f3Smrg      snprintf(class_name, 64, "class.%s%s<vector<%s, 4>%s>",
8267ec681f3Smrg               readwrite ? "RW" : "",
8277ec681f3Smrg               get_res_dimension_type_name(kind),
8287ec681f3Smrg               get_res_comp_type_name(comp_type),
8297ec681f3Smrg               get_res_ms_postfix(kind));
8307ec681f3Smrg      return dxil_module_get_struct_type(m, class_name, &vec_type, 1);
8317ec681f3Smrg   }
8327ec681f3Smrg
8337ec681f3Smrg   case DXIL_RESOURCE_KIND_RAW_BUFFER:
8347ec681f3Smrg   {
8357ec681f3Smrg      const struct dxil_type *component_type = dxil_module_get_int_type(m, 32);
8367ec681f3Smrg      char class_name[64] = { 0 };
8377ec681f3Smrg      snprintf(class_name, 64, "struct.%sByteAddressBuffer", readwrite ? "RW" : "");
8387ec681f3Smrg      return dxil_module_get_struct_type(m, class_name, &component_type, 1);
8397ec681f3Smrg   }
8407ec681f3Smrg
8417ec681f3Smrg   default:
8427ec681f3Smrg      unreachable("resource type not supported");
8437ec681f3Smrg   }
8447ec681f3Smrg}
8457ec681f3Smrg
8467ec681f3Smrgconst struct dxil_type *
8477ec681f3Smrgdxil_module_get_resret_type(struct dxil_module *m, enum overload_type overload)
8487ec681f3Smrg{
8497ec681f3Smrg   const struct dxil_type *overload_type = dxil_get_overload_type(m, overload);
8507ec681f3Smrg   const struct dxil_type *int32_type = dxil_module_get_int_type(m, 32);
8517ec681f3Smrg   const char *name;
8527ec681f3Smrg   if (!overload_type)
8537ec681f3Smrg      return NULL;
8547ec681f3Smrg
8557ec681f3Smrg   const struct dxil_type *resret[] =
8567ec681f3Smrg      { overload_type, overload_type, overload_type, overload_type, int32_type };
8577ec681f3Smrg
8587ec681f3Smrg   switch (overload) {
8597ec681f3Smrg   case DXIL_I32: name = "dx.types.ResRet.i32"; break;
8607ec681f3Smrg   case DXIL_I64: name = "dx.types.ResRet.i64"; break;
8617ec681f3Smrg   case DXIL_F32: name = "dx.types.ResRet.f32"; break;
8627ec681f3Smrg   case DXIL_F64: name = "dx.types.ResRet.f64"; break;
8637ec681f3Smrg   default:
8647ec681f3Smrg      unreachable("unexpected overload type");
8657ec681f3Smrg   }
8667ec681f3Smrg
8677ec681f3Smrg   return dxil_module_get_struct_type(m, name, resret, 5);
8687ec681f3Smrg}
8697ec681f3Smrg
8707ec681f3Smrgconst struct dxil_type *
8717ec681f3Smrgdxil_module_get_dimret_type(struct dxil_module *m)
8727ec681f3Smrg{
8737ec681f3Smrg   const struct dxil_type *int32_type = dxil_module_get_int_type(m, 32);
8747ec681f3Smrg
8757ec681f3Smrg   const struct dxil_type *dimret[] =
8767ec681f3Smrg      { int32_type, int32_type, int32_type, int32_type };
8777ec681f3Smrg
8787ec681f3Smrg   return dxil_module_get_struct_type(m, "dx.types.Dimensions", dimret, 4);
8797ec681f3Smrg}
8807ec681f3Smrg
8817ec681f3Smrgconst struct dxil_type *
8827ec681f3Smrgdxil_module_add_function_type(struct dxil_module *m,
8837ec681f3Smrg                              const struct dxil_type *ret_type,
8847ec681f3Smrg                              const struct dxil_type **arg_types,
8857ec681f3Smrg                              size_t num_arg_types)
8867ec681f3Smrg{
8877ec681f3Smrg   struct dxil_type *type = create_type(m, TYPE_FUNCTION);
8887ec681f3Smrg   if (type) {
8897ec681f3Smrg      type->function_def.args.types = ralloc_array(type,
8907ec681f3Smrg                                                  struct dxil_type *,
8917ec681f3Smrg                                                  num_arg_types);
8927ec681f3Smrg      if (!type->function_def.args.types)
8937ec681f3Smrg         return NULL;
8947ec681f3Smrg
8957ec681f3Smrg      memcpy(type->function_def.args.types, arg_types,
8967ec681f3Smrg             sizeof(struct dxil_type *) * num_arg_types);
8977ec681f3Smrg      type->function_def.args.num_types = num_arg_types;
8987ec681f3Smrg      type->function_def.ret_type = ret_type;
8997ec681f3Smrg   }
9007ec681f3Smrg   return type;
9017ec681f3Smrg}
9027ec681f3Smrg
9037ec681f3Smrg
9047ec681f3Smrgenum type_codes {
9057ec681f3Smrg  TYPE_CODE_NUMENTRY = 1,
9067ec681f3Smrg  TYPE_CODE_VOID = 2,
9077ec681f3Smrg  TYPE_CODE_FLOAT = 3,
9087ec681f3Smrg  TYPE_CODE_DOUBLE = 4,
9097ec681f3Smrg  TYPE_CODE_LABEL = 5,
9107ec681f3Smrg  TYPE_CODE_OPAQUE = 6,
9117ec681f3Smrg  TYPE_CODE_INTEGER = 7,
9127ec681f3Smrg  TYPE_CODE_POINTER = 8,
9137ec681f3Smrg  TYPE_CODE_FUNCTION_OLD = 9,
9147ec681f3Smrg  TYPE_CODE_HALF = 10,
9157ec681f3Smrg  TYPE_CODE_ARRAY = 11,
9167ec681f3Smrg  TYPE_CODE_VECTOR = 12,
9177ec681f3Smrg  TYPE_CODE_X86_FP80 = 13,
9187ec681f3Smrg  TYPE_CODE_FP128 = 14,
9197ec681f3Smrg  TYPE_CODE_PPC_FP128 = 15,
9207ec681f3Smrg  TYPE_CODE_METADATA = 16,
9217ec681f3Smrg  TYPE_CODE_X86_MMX = 17,
9227ec681f3Smrg  TYPE_CODE_STRUCT_ANON = 18,
9237ec681f3Smrg  TYPE_CODE_STRUCT_NAME = 19,
9247ec681f3Smrg  TYPE_CODE_STRUCT_NAMED = 20,
9257ec681f3Smrg  TYPE_CODE_FUNCTION = 21
9267ec681f3Smrg};
9277ec681f3Smrg
9287ec681f3Smrg#define LITERAL(x) { DXIL_OP_LITERAL, { (x) } }
9297ec681f3Smrg#define FIXED(x) { DXIL_OP_FIXED, { (x) } }
9307ec681f3Smrg#define VBR(x) { DXIL_OP_VBR, { (x) } }
9317ec681f3Smrg#define ARRAY { DXIL_OP_ARRAY, { 0 } }
9327ec681f3Smrg#define CHAR6 { DXIL_OP_CHAR6, { 0 } }
9337ec681f3Smrg#define BLOB { DXIL_OP_BLOB, { 0 } }
9347ec681f3Smrg
9357ec681f3Smrg#define TYPE_INDEX FIXED(32)
9367ec681f3Smrg
9377ec681f3Smrgenum type_table_abbrev_id {
9387ec681f3Smrg   TYPE_TABLE_ABBREV_POINTER,
9397ec681f3Smrg   TYPE_TABLE_ABBREV_FUNCTION,
9407ec681f3Smrg   TYPE_TABLE_ABBREV_STRUCT_ANON,
9417ec681f3Smrg   TYPE_TABLE_ABBREV_STRUCT_NAME,
9427ec681f3Smrg   TYPE_TABLE_ABBREV_STRUCT_NAMED,
9437ec681f3Smrg   TYPE_TABLE_ABBREV_ARRAY,
9447ec681f3Smrg   TYPE_TABLE_ABBREV_VECTOR,
9457ec681f3Smrg};
9467ec681f3Smrg
9477ec681f3Smrgstatic const struct dxil_abbrev
9487ec681f3Smrgtype_table_abbrevs[] = {
9497ec681f3Smrg   [TYPE_TABLE_ABBREV_POINTER] = {
9507ec681f3Smrg      { LITERAL(TYPE_CODE_POINTER), TYPE_INDEX, LITERAL(0) }, 3
9517ec681f3Smrg   },
9527ec681f3Smrg   [TYPE_TABLE_ABBREV_FUNCTION] = {
9537ec681f3Smrg      { LITERAL(TYPE_CODE_FUNCTION), FIXED(1), ARRAY, TYPE_INDEX }, 4
9547ec681f3Smrg   },
9557ec681f3Smrg   [TYPE_TABLE_ABBREV_STRUCT_ANON] = {
9567ec681f3Smrg      { LITERAL(TYPE_CODE_STRUCT_ANON), FIXED(1), ARRAY, TYPE_INDEX }, 4
9577ec681f3Smrg   },
9587ec681f3Smrg   [TYPE_TABLE_ABBREV_STRUCT_NAME] = {
9597ec681f3Smrg      { LITERAL(TYPE_CODE_STRUCT_NAME), ARRAY, CHAR6 }, 3
9607ec681f3Smrg   },
9617ec681f3Smrg   [TYPE_TABLE_ABBREV_STRUCT_NAMED] = {
9627ec681f3Smrg      { LITERAL(TYPE_CODE_STRUCT_NAMED), FIXED(1), ARRAY, TYPE_INDEX }, 4
9637ec681f3Smrg   },
9647ec681f3Smrg   [TYPE_TABLE_ABBREV_ARRAY] = {
9657ec681f3Smrg      { LITERAL(TYPE_CODE_ARRAY), VBR(8), TYPE_INDEX }, 3
9667ec681f3Smrg   },
9677ec681f3Smrg   [TYPE_TABLE_ABBREV_VECTOR] = {
9687ec681f3Smrg      { LITERAL(TYPE_CODE_VECTOR), VBR(8), TYPE_INDEX }, 3
9697ec681f3Smrg   },
9707ec681f3Smrg};
9717ec681f3Smrg
9727ec681f3Smrgstatic bool
9737ec681f3Smrgemit_type_table_abbrev_record(struct dxil_module *m,
9747ec681f3Smrg                              enum type_table_abbrev_id abbrev,
9757ec681f3Smrg                              const uint64_t *data, size_t size)
9767ec681f3Smrg{
9777ec681f3Smrg   assert(abbrev < ARRAY_SIZE(type_table_abbrevs));
9787ec681f3Smrg   return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,
9797ec681f3Smrg                             type_table_abbrevs + abbrev, data, size);
9807ec681f3Smrg}
9817ec681f3Smrg
9827ec681f3Smrgenum constant_code {
9837ec681f3Smrg  CST_CODE_SETTYPE = 1,
9847ec681f3Smrg  CST_CODE_NULL = 2,
9857ec681f3Smrg  CST_CODE_UNDEF = 3,
9867ec681f3Smrg  CST_CODE_INTEGER = 4,
9877ec681f3Smrg  CST_CODE_WIDE_INTEGER = 5,
9887ec681f3Smrg  CST_CODE_FLOAT = 6,
9897ec681f3Smrg  CST_CODE_AGGREGATE = 7,
9907ec681f3Smrg  CST_CODE_STRING = 8,
9917ec681f3Smrg  CST_CODE_CSTRING = 9,
9927ec681f3Smrg  CST_CODE_CE_BINOP = 10,
9937ec681f3Smrg  CST_CODE_CE_CAST = 11,
9947ec681f3Smrg  CST_CODE_CE_GEP = 12,
9957ec681f3Smrg  CST_CODE_CE_SELECT = 13,
9967ec681f3Smrg  CST_CODE_CE_EXTRACTELT = 14,
9977ec681f3Smrg  CST_CODE_CE_INSERTELT = 15,
9987ec681f3Smrg  CST_CODE_CE_SHUFFLEVEC = 16,
9997ec681f3Smrg  CST_CODE_CE_CMP = 17,
10007ec681f3Smrg  CST_CODE_INLINEASM_OLD = 18,
10017ec681f3Smrg  CST_CODE_CE_SHUFVEC_EX = 19,
10027ec681f3Smrg  CST_CODE_CE_INBOUNDS_GEP = 20,
10037ec681f3Smrg  CST_CODE_BLOCKADDRESS = 21,
10047ec681f3Smrg  CST_CODE_DATA = 22,
10057ec681f3Smrg  CST_CODE_INLINEASM = 23
10067ec681f3Smrg};
10077ec681f3Smrg
10087ec681f3Smrgenum const_abbrev_id {
10097ec681f3Smrg   CONST_ABBREV_SETTYPE,
10107ec681f3Smrg   CONST_ABBREV_INTEGER,
10117ec681f3Smrg   CONST_ABBREV_CE_CAST,
10127ec681f3Smrg   CONST_ABBREV_NULL,
10137ec681f3Smrg};
10147ec681f3Smrg
10157ec681f3Smrgstatic const struct dxil_abbrev
10167ec681f3Smrgconst_abbrevs[] = {
10177ec681f3Smrg   [CONST_ABBREV_SETTYPE] = { { LITERAL(CST_CODE_SETTYPE), TYPE_INDEX }, 2 },
10187ec681f3Smrg   [CONST_ABBREV_INTEGER] = { { LITERAL(CST_CODE_INTEGER), VBR(8) }, 2 },
10197ec681f3Smrg   [CONST_ABBREV_CE_CAST] = {
10207ec681f3Smrg      { LITERAL(CST_CODE_CE_CAST), FIXED(4), TYPE_INDEX, VBR(8) }, 4
10217ec681f3Smrg   },
10227ec681f3Smrg   [CONST_ABBREV_NULL] = { { LITERAL(CST_CODE_NULL) }, 1 },
10237ec681f3Smrg};
10247ec681f3Smrg
10257ec681f3Smrgstatic bool
10267ec681f3Smrgemit_const_abbrev_record(struct dxil_module *m, enum const_abbrev_id abbrev,
10277ec681f3Smrg                         const uint64_t *data, size_t size)
10287ec681f3Smrg{
10297ec681f3Smrg   assert(abbrev < ARRAY_SIZE(const_abbrevs));
10307ec681f3Smrg
10317ec681f3Smrg   return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,
10327ec681f3Smrg                             const_abbrevs + abbrev, data, size);
10337ec681f3Smrg}
10347ec681f3Smrg
10357ec681f3Smrgenum function_code {
10367ec681f3Smrg  FUNC_CODE_DECLAREBLOCKS = 1,
10377ec681f3Smrg  FUNC_CODE_INST_BINOP = 2,
10387ec681f3Smrg  FUNC_CODE_INST_CAST = 3,
10397ec681f3Smrg  FUNC_CODE_INST_GEP_OLD = 4,
10407ec681f3Smrg  FUNC_CODE_INST_SELECT = 5,
10417ec681f3Smrg  FUNC_CODE_INST_EXTRACTELT = 6,
10427ec681f3Smrg  FUNC_CODE_INST_INSERTELT = 7,
10437ec681f3Smrg  FUNC_CODE_INST_SHUFFLEVEC = 8,
10447ec681f3Smrg  FUNC_CODE_INST_CMP = 9,
10457ec681f3Smrg  FUNC_CODE_INST_RET = 10,
10467ec681f3Smrg  FUNC_CODE_INST_BR = 11,
10477ec681f3Smrg  FUNC_CODE_INST_SWITCH = 12,
10487ec681f3Smrg  FUNC_CODE_INST_INVOKE = 13,
10497ec681f3Smrg  /* 14: unused */
10507ec681f3Smrg  FUNC_CODE_INST_UNREACHABLE = 15,
10517ec681f3Smrg  FUNC_CODE_INST_PHI = 16,
10527ec681f3Smrg  /* 17-18: unused */
10537ec681f3Smrg  FUNC_CODE_INST_ALLOCA = 19,
10547ec681f3Smrg  FUNC_CODE_INST_LOAD = 20,
10557ec681f3Smrg  /* 21-22: unused */
10567ec681f3Smrg  FUNC_CODE_INST_VAARG = 23,
10577ec681f3Smrg  FUNC_CODE_INST_STORE_OLD = 24,
10587ec681f3Smrg  /* 25: unused */
10597ec681f3Smrg  FUNC_CODE_INST_EXTRACTVAL = 26,
10607ec681f3Smrg  FUNC_CODE_INST_INSERTVAL = 27,
10617ec681f3Smrg  FUNC_CODE_INST_CMP2 = 28,
10627ec681f3Smrg  FUNC_CODE_INST_VSELECT = 29,
10637ec681f3Smrg  FUNC_CODE_INST_INBOUNDS_GEP_OLD = 30,
10647ec681f3Smrg  FUNC_CODE_INST_INDIRECTBR = 31,
10657ec681f3Smrg  /* 32: unused */
10667ec681f3Smrg  FUNC_CODE_DEBUG_LOC_AGAIN = 33,
10677ec681f3Smrg  FUNC_CODE_INST_CALL = 34,
10687ec681f3Smrg  FUNC_CODE_DEBUG_LOC = 35,
10697ec681f3Smrg  FUNC_CODE_INST_FENCE = 36,
10707ec681f3Smrg  FUNC_CODE_INST_CMPXCHG_OLD = 37,
10717ec681f3Smrg  FUNC_CODE_INST_ATOMICRMW = 38,
10727ec681f3Smrg  FUNC_CODE_INST_RESUME = 39,
10737ec681f3Smrg  FUNC_CODE_INST_LANDINGPAD_OLD = 40,
10747ec681f3Smrg  FUNC_CODE_INST_LOADATOMIC = 41,
10757ec681f3Smrg  FUNC_CODE_INST_STOREATOMIC_OLD = 42,
10767ec681f3Smrg  FUNC_CODE_INST_GEP = 43,
10777ec681f3Smrg  FUNC_CODE_INST_STORE = 44,
10787ec681f3Smrg  FUNC_CODE_INST_STOREATOMIC = 45,
10797ec681f3Smrg  FUNC_CODE_INST_CMPXCHG = 46,
10807ec681f3Smrg  FUNC_CODE_INST_LANDINGPAD = 47,
10817ec681f3Smrg};
10827ec681f3Smrg
10837ec681f3Smrgenum func_abbrev_id {
10847ec681f3Smrg   FUNC_ABBREV_LOAD,
10857ec681f3Smrg   FUNC_ABBREV_BINOP,
10867ec681f3Smrg   FUNC_ABBREV_BINOP_FLAGS,
10877ec681f3Smrg   FUNC_ABBREV_CAST,
10887ec681f3Smrg   FUNC_ABBREV_RET_VOID,
10897ec681f3Smrg   FUNC_ABBREV_RET_VAL,
10907ec681f3Smrg   FUNC_ABBREV_UNREACHABLE,
10917ec681f3Smrg   FUNC_ABBREV_GEP,
10927ec681f3Smrg};
10937ec681f3Smrg
10947ec681f3Smrgstatic const struct dxil_abbrev
10957ec681f3Smrgfunc_abbrevs[] = {
10967ec681f3Smrg   [FUNC_ABBREV_LOAD] = {
10977ec681f3Smrg      { LITERAL(FUNC_CODE_INST_LOAD), VBR(6), TYPE_INDEX, VBR(4),
10987ec681f3Smrg        FIXED(1) }, 5
10997ec681f3Smrg   },
11007ec681f3Smrg   [FUNC_ABBREV_BINOP] = {
11017ec681f3Smrg      { LITERAL(FUNC_CODE_INST_BINOP), VBR(6), VBR(6), FIXED(4) }, 4
11027ec681f3Smrg   },
11037ec681f3Smrg   [FUNC_ABBREV_BINOP_FLAGS] = {
11047ec681f3Smrg      { LITERAL(FUNC_CODE_INST_BINOP), VBR(6), VBR(6), FIXED(4),
11057ec681f3Smrg        FIXED(7) }, 5
11067ec681f3Smrg   },
11077ec681f3Smrg   [FUNC_ABBREV_CAST] = {
11087ec681f3Smrg      { LITERAL(FUNC_CODE_INST_CAST), VBR(6), TYPE_INDEX, FIXED(4) }, 4
11097ec681f3Smrg   },
11107ec681f3Smrg   [FUNC_ABBREV_RET_VOID] = { { LITERAL(FUNC_CODE_INST_RET) }, 1 },
11117ec681f3Smrg   [FUNC_ABBREV_RET_VAL] = { { LITERAL(FUNC_CODE_INST_RET), VBR(6) }, 2 },
11127ec681f3Smrg   [FUNC_ABBREV_UNREACHABLE] = {
11137ec681f3Smrg      { LITERAL(FUNC_CODE_INST_UNREACHABLE) }, 1
11147ec681f3Smrg   },
11157ec681f3Smrg   [FUNC_ABBREV_GEP] = {
11167ec681f3Smrg      { LITERAL(FUNC_CODE_INST_GEP), FIXED(1), TYPE_INDEX, ARRAY,
11177ec681f3Smrg        VBR(6) }, 5
11187ec681f3Smrg   },
11197ec681f3Smrg};
11207ec681f3Smrg
11217ec681f3Smrgstatic bool
11227ec681f3Smrgemit_func_abbrev_record(struct dxil_module *m, enum func_abbrev_id abbrev,
11237ec681f3Smrg                        const uint64_t *data, size_t size)
11247ec681f3Smrg{
11257ec681f3Smrg   assert(abbrev < ARRAY_SIZE(func_abbrevs));
11267ec681f3Smrg   return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,
11277ec681f3Smrg                             func_abbrevs + abbrev, data, size);
11287ec681f3Smrg}
11297ec681f3Smrg
11307ec681f3Smrgstatic bool
11317ec681f3Smrgdefine_abbrev(struct dxil_module *m, const struct dxil_abbrev *a)
11327ec681f3Smrg{
11337ec681f3Smrg   if (!dxil_buffer_emit_abbrev_id(&m->buf, DXIL_DEFINE_ABBREV) ||
11347ec681f3Smrg       !dxil_buffer_emit_vbr_bits(&m->buf, a->num_operands, 5))
11357ec681f3Smrg      return false;
11367ec681f3Smrg
11377ec681f3Smrg   for (int i = 0; i < a->num_operands; ++i) {
11387ec681f3Smrg      unsigned is_literal = a->operands[i].type == DXIL_OP_LITERAL;
11397ec681f3Smrg      if (!dxil_buffer_emit_bits(&m->buf, is_literal, 1))
11407ec681f3Smrg         return false;
11417ec681f3Smrg      if (a->operands[i].type == DXIL_OP_LITERAL) {
11427ec681f3Smrg         if (!dxil_buffer_emit_vbr_bits(&m->buf, a->operands[i].value, 8))
11437ec681f3Smrg            return false;
11447ec681f3Smrg      } else {
11457ec681f3Smrg         if (!dxil_buffer_emit_bits(&m->buf, a->operands[i].type, 3))
11467ec681f3Smrg            return false;
11477ec681f3Smrg         if (a->operands[i].type == DXIL_OP_FIXED) {
11487ec681f3Smrg            if (!dxil_buffer_emit_vbr_bits(&m->buf,
11497ec681f3Smrg                                           a->operands[i].encoding_data, 5))
11507ec681f3Smrg               return false;
11517ec681f3Smrg         } else if (a->operands[i].type == DXIL_OP_VBR) {
11527ec681f3Smrg            if (!dxil_buffer_emit_vbr_bits(&m->buf,
11537ec681f3Smrg                                           a->operands[i].encoding_data, 5))
11547ec681f3Smrg               return false;
11557ec681f3Smrg         }
11567ec681f3Smrg      }
11577ec681f3Smrg   }
11587ec681f3Smrg
11597ec681f3Smrg   return true;
11607ec681f3Smrg}
11617ec681f3Smrg
11627ec681f3Smrgenum dxil_blockinfo_code {
11637ec681f3Smrg   DXIL_BLOCKINFO_CODE_SETBID = 1,
11647ec681f3Smrg   DXIL_BLOCKINFO_CODE_BLOCKNAME = 2,
11657ec681f3Smrg   DXIL_BLOCKINFO_CODE_SETRECORDNAME = 3
11667ec681f3Smrg};
11677ec681f3Smrg
11687ec681f3Smrgstatic bool
11697ec681f3Smrgswitch_to_block(struct dxil_module *m, uint32_t block)
11707ec681f3Smrg{
11717ec681f3Smrg   return emit_record_int(m, DXIL_BLOCKINFO_CODE_SETBID, block);
11727ec681f3Smrg}
11737ec681f3Smrg
11747ec681f3Smrgenum dxil_standard_block {
11757ec681f3Smrg   DXIL_BLOCKINFO = 0,
11767ec681f3Smrg   DXIL_FIRST_APPLICATION_BLOCK = 8
11777ec681f3Smrg};
11787ec681f3Smrg
11797ec681f3Smrgenum dxil_llvm_block {
11807ec681f3Smrg   DXIL_MODULE = DXIL_FIRST_APPLICATION_BLOCK,
11817ec681f3Smrg   DXIL_PARAMATTR = DXIL_FIRST_APPLICATION_BLOCK + 1,
11827ec681f3Smrg   DXIL_PARAMATTR_GROUP = DXIL_FIRST_APPLICATION_BLOCK + 2,
11837ec681f3Smrg   DXIL_CONST_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 3,
11847ec681f3Smrg   DXIL_FUNCTION_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 4,
11857ec681f3Smrg   DXIL_VALUE_SYMTAB_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 6,
11867ec681f3Smrg   DXIL_METADATA_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 7,
11877ec681f3Smrg   DXIL_TYPE_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 9,
11887ec681f3Smrg};
11897ec681f3Smrg
11907ec681f3Smrgenum value_symtab_code {
11917ec681f3Smrg  VST_CODE_ENTRY = 1,
11927ec681f3Smrg  VST_CODE_BBENTRY = 2
11937ec681f3Smrg};
11947ec681f3Smrg
11957ec681f3Smrgenum value_symtab_abbrev_id {
11967ec681f3Smrg   VST_ABBREV_ENTRY_8,
11977ec681f3Smrg   VST_ABBREV_ENTRY_7,
11987ec681f3Smrg   VST_ABBREV_ENTRY_6,
11997ec681f3Smrg   VST_ABBREV_BBENTRY_6,
12007ec681f3Smrg};
12017ec681f3Smrg
12027ec681f3Smrgstatic struct dxil_abbrev value_symtab_abbrevs[] = {
12037ec681f3Smrg   [VST_ABBREV_ENTRY_8] = { { FIXED(3), VBR(8), ARRAY, FIXED(8) }, 4 },
12047ec681f3Smrg   [VST_ABBREV_ENTRY_7] = {
12057ec681f3Smrg      { LITERAL(VST_CODE_ENTRY), VBR(8), ARRAY, FIXED(7), }, 4
12067ec681f3Smrg   },
12077ec681f3Smrg   [VST_ABBREV_ENTRY_6] = {
12087ec681f3Smrg      { LITERAL(VST_CODE_ENTRY), VBR(8), ARRAY, CHAR6, }, 4
12097ec681f3Smrg   },
12107ec681f3Smrg   [VST_ABBREV_BBENTRY_6] = {
12117ec681f3Smrg      { LITERAL(VST_CODE_BBENTRY), VBR(8), ARRAY, CHAR6, }, 4
12127ec681f3Smrg   },
12137ec681f3Smrg};
12147ec681f3Smrg
12157ec681f3Smrgstatic bool
12167ec681f3Smrgemit_value_symtab_abbrevs(struct dxil_module *m)
12177ec681f3Smrg{
12187ec681f3Smrg   if (!switch_to_block(m, DXIL_VALUE_SYMTAB_BLOCK))
12197ec681f3Smrg      return false;
12207ec681f3Smrg
12217ec681f3Smrg   for (int i = 0; i < ARRAY_SIZE(value_symtab_abbrevs); ++i) {
12227ec681f3Smrg      if (!define_abbrev(m, value_symtab_abbrevs + i))
12237ec681f3Smrg         return false;
12247ec681f3Smrg   }
12257ec681f3Smrg
12267ec681f3Smrg   return true;
12277ec681f3Smrg}
12287ec681f3Smrg
12297ec681f3Smrgstatic bool
12307ec681f3Smrgemit_const_abbrevs(struct dxil_module *m)
12317ec681f3Smrg{
12327ec681f3Smrg   if (!switch_to_block(m, DXIL_CONST_BLOCK))
12337ec681f3Smrg      return false;
12347ec681f3Smrg
12357ec681f3Smrg   for (int i = 0; i < ARRAY_SIZE(const_abbrevs); ++i) {
12367ec681f3Smrg      if (!define_abbrev(m, const_abbrevs + i))
12377ec681f3Smrg         return false;
12387ec681f3Smrg   }
12397ec681f3Smrg
12407ec681f3Smrg   return true;
12417ec681f3Smrg}
12427ec681f3Smrg
12437ec681f3Smrgstatic bool
12447ec681f3Smrgemit_function_abbrevs(struct dxil_module *m)
12457ec681f3Smrg{
12467ec681f3Smrg   if (!switch_to_block(m, DXIL_FUNCTION_BLOCK))
12477ec681f3Smrg      return false;
12487ec681f3Smrg
12497ec681f3Smrg   for (int i = 0; i < ARRAY_SIZE(func_abbrevs); ++i) {
12507ec681f3Smrg      if (!define_abbrev(m, func_abbrevs + i))
12517ec681f3Smrg         return false;
12527ec681f3Smrg   }
12537ec681f3Smrg
12547ec681f3Smrg   return true;
12557ec681f3Smrg}
12567ec681f3Smrg
12577ec681f3Smrgstatic bool
12587ec681f3Smrgemit_blockinfo(struct dxil_module *m)
12597ec681f3Smrg{
12607ec681f3Smrg   return enter_subblock(m, DXIL_BLOCKINFO, 2) &&
12617ec681f3Smrg          emit_value_symtab_abbrevs(m) &&
12627ec681f3Smrg          emit_const_abbrevs(m) &&
12637ec681f3Smrg          emit_function_abbrevs(m) &&
12647ec681f3Smrg          exit_block(m);
12657ec681f3Smrg}
12667ec681f3Smrg
12677ec681f3Smrgenum attribute_codes {
12687ec681f3Smrg   PARAMATTR_GRP_CODE_ENTRY = 3,
12697ec681f3Smrg   PARAMATTR_CODE_ENTRY = 2
12707ec681f3Smrg};
12717ec681f3Smrg
12727ec681f3Smrgstatic bool
12737ec681f3Smrgemit_attrib_group(struct dxil_module *m, int id, uint32_t slot,
12747ec681f3Smrg                  const struct dxil_attrib *attrs, size_t num_attrs)
12757ec681f3Smrg{
12767ec681f3Smrg   uint64_t record[64];
12777ec681f3Smrg   record[0] = id;
12787ec681f3Smrg   record[1] = slot;
12797ec681f3Smrg   size_t size = 2;
12807ec681f3Smrg
12817ec681f3Smrg   for (int i = 0; i < num_attrs; ++i) {
12827ec681f3Smrg      switch (attrs[i].type) {
12837ec681f3Smrg      case DXIL_ATTR_ENUM:
12847ec681f3Smrg         assert(size < ARRAY_SIZE(record) - 2);
12857ec681f3Smrg         record[size++] = 0;
12867ec681f3Smrg         record[size++] = attrs[i].kind;
12877ec681f3Smrg         break;
12887ec681f3Smrg
12897ec681f3Smrg      default:
12907ec681f3Smrg         unreachable("unsupported attrib type");
12917ec681f3Smrg      }
12927ec681f3Smrg   }
12937ec681f3Smrg
12947ec681f3Smrg   return emit_record(m, PARAMATTR_GRP_CODE_ENTRY, record, size);
12957ec681f3Smrg}
12967ec681f3Smrg
12977ec681f3Smrgstatic bool
12987ec681f3Smrgemit_attrib_group_table(struct dxil_module *m)
12997ec681f3Smrg{
13007ec681f3Smrg   if (!enter_subblock(m, DXIL_PARAMATTR_GROUP, 3))
13017ec681f3Smrg      return false;
13027ec681f3Smrg
13037ec681f3Smrg   struct attrib_set *as;
13047ec681f3Smrg   int id = 1;
13057ec681f3Smrg   LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) {
13067ec681f3Smrg      if (!emit_attrib_group(m, id, UINT32_MAX, as->attrs, as->num_attrs))
13077ec681f3Smrg         return false;
13087ec681f3Smrg      id++;
13097ec681f3Smrg   }
13107ec681f3Smrg
13117ec681f3Smrg   return exit_block(m);
13127ec681f3Smrg}
13137ec681f3Smrg
13147ec681f3Smrgstatic bool
13157ec681f3Smrgemit_attribute_table(struct dxil_module *m)
13167ec681f3Smrg{
13177ec681f3Smrg   if (!enter_subblock(m, DXIL_PARAMATTR, 3))
13187ec681f3Smrg      return false;
13197ec681f3Smrg
13207ec681f3Smrg   struct attrib_set *as;
13217ec681f3Smrg   int id = 1;
13227ec681f3Smrg   LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) {
13237ec681f3Smrg      if (!emit_record_int(m, PARAMATTR_CODE_ENTRY, id))
13247ec681f3Smrg         return false;
13257ec681f3Smrg      id++;
13267ec681f3Smrg   }
13277ec681f3Smrg
13287ec681f3Smrg   return exit_block(m);
13297ec681f3Smrg}
13307ec681f3Smrg
13317ec681f3Smrgstatic bool
13327ec681f3Smrgemit_type_table_abbrevs(struct dxil_module *m)
13337ec681f3Smrg{
13347ec681f3Smrg   for (int i = 0; i < ARRAY_SIZE(type_table_abbrevs); ++i) {
13357ec681f3Smrg      if (!define_abbrev(m, type_table_abbrevs + i))
13367ec681f3Smrg         return false;
13377ec681f3Smrg   }
13387ec681f3Smrg
13397ec681f3Smrg   return true;
13407ec681f3Smrg}
13417ec681f3Smrg
13427ec681f3Smrgstatic bool
13437ec681f3Smrgemit_float_type(struct dxil_module *m, unsigned bit_size)
13447ec681f3Smrg{
13457ec681f3Smrg   switch (bit_size) {
13467ec681f3Smrg   case 16: return emit_record(m, TYPE_CODE_HALF, NULL, 0);
13477ec681f3Smrg   case 32: return emit_record(m, TYPE_CODE_FLOAT, NULL, 0);
13487ec681f3Smrg   case 64: return emit_record(m, TYPE_CODE_DOUBLE, NULL, 0);
13497ec681f3Smrg   default:
13507ec681f3Smrg      unreachable("unexpected bit_size for float type");
13517ec681f3Smrg   }
13527ec681f3Smrg}
13537ec681f3Smrg
13547ec681f3Smrgstatic bool
13557ec681f3Smrgemit_pointer_type(struct dxil_module *m, int type_index)
13567ec681f3Smrg{
13577ec681f3Smrg   uint64_t data[] = { TYPE_CODE_POINTER, type_index, 0 };
13587ec681f3Smrg   return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_POINTER,
13597ec681f3Smrg                                        data, ARRAY_SIZE(data));
13607ec681f3Smrg}
13617ec681f3Smrg
13627ec681f3Smrgstatic bool
13637ec681f3Smrgemit_struct_name(struct dxil_module *m, const char *name)
13647ec681f3Smrg{
13657ec681f3Smrg   uint64_t temp[256];
13667ec681f3Smrg   assert(strlen(name) < ARRAY_SIZE(temp));
13677ec681f3Smrg
13687ec681f3Smrg   for (int i = 0; i < strlen(name); ++i)
13697ec681f3Smrg      temp[i] = name[i];
13707ec681f3Smrg
13717ec681f3Smrg   return emit_record(m, TYPE_CODE_STRUCT_NAME, temp, strlen(name));
13727ec681f3Smrg}
13737ec681f3Smrg
13747ec681f3Smrgstatic bool
13757ec681f3Smrgemit_struct_name_char6(struct dxil_module *m, const char *name)
13767ec681f3Smrg{
13777ec681f3Smrg   uint64_t temp[256];
13787ec681f3Smrg   assert(strlen(name) < ARRAY_SIZE(temp) - 1);
13797ec681f3Smrg
13807ec681f3Smrg   temp[0] = TYPE_CODE_STRUCT_NAME;
13817ec681f3Smrg   for (int i = 0; i < strlen(name); ++i)
13827ec681f3Smrg      temp[i + 1] = name[i];
13837ec681f3Smrg
13847ec681f3Smrg   return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_STRUCT_NAME,
13857ec681f3Smrg                                        temp, 1 + strlen(name));
13867ec681f3Smrg}
13877ec681f3Smrg
13887ec681f3Smrgstatic bool
13897ec681f3Smrgemit_struct_type(struct dxil_module *m, const struct dxil_type *type)
13907ec681f3Smrg{
13917ec681f3Smrg   enum type_table_abbrev_id abbrev = TYPE_TABLE_ABBREV_STRUCT_ANON;
13927ec681f3Smrg   enum type_codes type_code = TYPE_CODE_STRUCT_ANON;
13937ec681f3Smrg   if (type->struct_def.name) {
13947ec681f3Smrg      abbrev = TYPE_TABLE_ABBREV_STRUCT_NAMED;
13957ec681f3Smrg      type_code = TYPE_CODE_STRUCT_NAMED;
13967ec681f3Smrg      if (is_char6_string(type->struct_def.name)) {
13977ec681f3Smrg         if (!emit_struct_name_char6(m, type->struct_def.name))
13987ec681f3Smrg            return false;
13997ec681f3Smrg      } else {
14007ec681f3Smrg         if (!emit_struct_name(m, type->struct_def.name))
14017ec681f3Smrg            return false;
14027ec681f3Smrg      }
14037ec681f3Smrg   }
14047ec681f3Smrg
14057ec681f3Smrg   uint64_t temp[256];
14067ec681f3Smrg   assert(type->struct_def.elem.num_types < ARRAY_SIZE(temp) - 2);
14077ec681f3Smrg   temp[0] = type_code;
14087ec681f3Smrg   temp[1] = 0; /* packed */
14097ec681f3Smrg   for (int i = 0; i < type->struct_def.elem.num_types; ++i) {
14107ec681f3Smrg      assert(type->struct_def.elem.types[i]->id >= 0);
14117ec681f3Smrg      temp[2 + i] = type->struct_def.elem.types[i]->id;
14127ec681f3Smrg   }
14137ec681f3Smrg
14147ec681f3Smrg   return emit_type_table_abbrev_record(m, abbrev, temp,
14157ec681f3Smrg                                        2 + type->struct_def.elem.num_types);
14167ec681f3Smrg}
14177ec681f3Smrg
14187ec681f3Smrgstatic bool
14197ec681f3Smrgemit_array_type(struct dxil_module *m, const struct dxil_type *type)
14207ec681f3Smrg{
14217ec681f3Smrg   assert(type->array_or_vector_def.elem_type->id >= 0);
14227ec681f3Smrg   uint64_t data[] = {
14237ec681f3Smrg      TYPE_CODE_ARRAY,
14247ec681f3Smrg      type->array_or_vector_def.num_elems,
14257ec681f3Smrg      type->array_or_vector_def.elem_type->id
14267ec681f3Smrg   };
14277ec681f3Smrg   return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_ARRAY, data,
14287ec681f3Smrg                                        ARRAY_SIZE(data));
14297ec681f3Smrg}
14307ec681f3Smrg
14317ec681f3Smrgstatic bool
14327ec681f3Smrgemit_function_type(struct dxil_module *m, const struct dxil_type *type)
14337ec681f3Smrg{
14347ec681f3Smrg   uint64_t temp[256];
14357ec681f3Smrg   assert(type->function_def.args.num_types < ARRAY_SIZE(temp) - 3);
14367ec681f3Smrg   assert(type->function_def.ret_type->id >= 0);
14377ec681f3Smrg
14387ec681f3Smrg   temp[0] = TYPE_CODE_FUNCTION;
14397ec681f3Smrg   temp[1] = 0; // vararg
14407ec681f3Smrg   temp[2] = type->function_def.ret_type->id;
14417ec681f3Smrg   for (int i = 0; i < type->function_def.args.num_types; ++i) {
14427ec681f3Smrg      assert(type->function_def.args.types[i]->id >= 0);
14437ec681f3Smrg      temp[3 + i] = type->function_def.args.types[i]->id;
14447ec681f3Smrg   }
14457ec681f3Smrg
14467ec681f3Smrg   return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_FUNCTION,
14477ec681f3Smrg                                        temp, 3 + type->function_def.args.num_types);
14487ec681f3Smrg}
14497ec681f3Smrg
14507ec681f3Smrgstatic bool
14517ec681f3Smrgemit_vector_type(struct dxil_module *m, const struct dxil_type *type)
14527ec681f3Smrg{
14537ec681f3Smrg   uint64_t temp[3];
14547ec681f3Smrg   temp[0] = TYPE_CODE_VECTOR;
14557ec681f3Smrg   temp[1] = type->array_or_vector_def.num_elems;
14567ec681f3Smrg   temp[2] = type->array_or_vector_def.elem_type->id;
14577ec681f3Smrg
14587ec681f3Smrg   return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_VECTOR , temp, 3);
14597ec681f3Smrg}
14607ec681f3Smrg
14617ec681f3Smrgstatic bool
14627ec681f3Smrgemit_metadata_type(struct dxil_module *m)
14637ec681f3Smrg{
14647ec681f3Smrg   return emit_record(m, TYPE_CODE_METADATA, NULL, 0);
14657ec681f3Smrg}
14667ec681f3Smrg
14677ec681f3Smrgstatic bool
14687ec681f3Smrgemit_type(struct dxil_module *m, struct dxil_type *type)
14697ec681f3Smrg{
14707ec681f3Smrg   switch (type->type) {
14717ec681f3Smrg   case TYPE_VOID:
14727ec681f3Smrg      return emit_record(m, TYPE_CODE_VOID, NULL, 0);
14737ec681f3Smrg
14747ec681f3Smrg   case TYPE_INTEGER:
14757ec681f3Smrg      return emit_record_int(m, TYPE_CODE_INTEGER, type->int_bits);
14767ec681f3Smrg
14777ec681f3Smrg   case TYPE_FLOAT:
14787ec681f3Smrg      return emit_float_type(m, type->float_bits);
14797ec681f3Smrg
14807ec681f3Smrg   case TYPE_POINTER:
14817ec681f3Smrg      return emit_pointer_type(m, type->ptr_target_type->id);
14827ec681f3Smrg
14837ec681f3Smrg   case TYPE_STRUCT:
14847ec681f3Smrg      return emit_struct_type(m, type);
14857ec681f3Smrg
14867ec681f3Smrg   case TYPE_ARRAY:
14877ec681f3Smrg      return emit_array_type(m, type);
14887ec681f3Smrg
14897ec681f3Smrg   case TYPE_FUNCTION:
14907ec681f3Smrg      return emit_function_type(m, type);
14917ec681f3Smrg
14927ec681f3Smrg   case TYPE_VECTOR:
14937ec681f3Smrg      return emit_vector_type(m, type);
14947ec681f3Smrg
14957ec681f3Smrg   default:
14967ec681f3Smrg      unreachable("unexpected type->type");
14977ec681f3Smrg   }
14987ec681f3Smrg}
14997ec681f3Smrg
15007ec681f3Smrgstatic bool
15017ec681f3Smrgemit_type_table(struct dxil_module *m)
15027ec681f3Smrg{
15037ec681f3Smrg   if (!enter_subblock(m, DXIL_TYPE_BLOCK, 4) ||
15047ec681f3Smrg       !emit_type_table_abbrevs(m) ||
15057ec681f3Smrg       !emit_record_int(m, 1, 1 + list_length(&m->type_list)))
15067ec681f3Smrg      return false;
15077ec681f3Smrg
15087ec681f3Smrg   list_for_each_entry(struct dxil_type, type, &m->type_list, head) {
15097ec681f3Smrg      if (!emit_type(m, type))
15107ec681f3Smrg         return false;
15117ec681f3Smrg   }
15127ec681f3Smrg
15137ec681f3Smrg   return emit_metadata_type(m) &&
15147ec681f3Smrg          exit_block(m);
15157ec681f3Smrg}
15167ec681f3Smrg
15177ec681f3Smrgstatic struct dxil_const *
15187ec681f3Smrgcreate_const(struct dxil_module *m, const struct dxil_type *type, bool undef)
15197ec681f3Smrg{
15207ec681f3Smrg   struct dxil_const *ret = ralloc_size(m->ralloc_ctx,
15217ec681f3Smrg                                        sizeof(struct dxil_const));
15227ec681f3Smrg   if (ret) {
15237ec681f3Smrg      ret->value.id = -1;
15247ec681f3Smrg      ret->value.type = type;
15257ec681f3Smrg      ret->undef = undef;
15267ec681f3Smrg      list_addtail(&ret->head, &m->const_list);
15277ec681f3Smrg   }
15287ec681f3Smrg   return ret;
15297ec681f3Smrg}
15307ec681f3Smrg
15317ec681f3Smrgstatic const struct dxil_value *
15327ec681f3Smrgget_int_const(struct dxil_module *m, const struct dxil_type *type,
15337ec681f3Smrg              intmax_t value)
15347ec681f3Smrg{
15357ec681f3Smrg   assert(type && type->type == TYPE_INTEGER);
15367ec681f3Smrg
15377ec681f3Smrg   struct dxil_const *c;
15387ec681f3Smrg   LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
15397ec681f3Smrg      if (c->value.type != type || c->undef)
15407ec681f3Smrg         continue;
15417ec681f3Smrg
15427ec681f3Smrg      if (c->int_value == value)
15437ec681f3Smrg         return &c->value;
15447ec681f3Smrg   }
15457ec681f3Smrg
15467ec681f3Smrg   c = create_const(m, type, false);
15477ec681f3Smrg   if (!c)
15487ec681f3Smrg      return NULL;
15497ec681f3Smrg
15507ec681f3Smrg   c->int_value = value;
15517ec681f3Smrg   return &c->value;
15527ec681f3Smrg}
15537ec681f3Smrg
15547ec681f3Smrgconst struct dxil_value *
15557ec681f3Smrgdxil_module_get_int1_const(struct dxil_module *m, bool value)
15567ec681f3Smrg{
15577ec681f3Smrg   const struct dxil_type *type = get_int1_type(m);
15587ec681f3Smrg   if (!type)
15597ec681f3Smrg      return NULL;
15607ec681f3Smrg
15617ec681f3Smrg   return get_int_const(m, type, value);
15627ec681f3Smrg}
15637ec681f3Smrg
15647ec681f3Smrgconst struct dxil_value *
15657ec681f3Smrgdxil_module_get_int8_const(struct dxil_module *m, int8_t value)
15667ec681f3Smrg{
15677ec681f3Smrg   const struct dxil_type *type = get_int8_type(m);
15687ec681f3Smrg   if (!type)
15697ec681f3Smrg      return NULL;
15707ec681f3Smrg
15717ec681f3Smrg   return get_int_const(m, type, value);
15727ec681f3Smrg}
15737ec681f3Smrg
15747ec681f3Smrgconst struct dxil_value *
15757ec681f3Smrgdxil_module_get_int16_const(struct dxil_module *m, int16_t value)
15767ec681f3Smrg{
15777ec681f3Smrg   const struct dxil_type *type = get_int16_type(m);
15787ec681f3Smrg   if (!type)
15797ec681f3Smrg      return NULL;
15807ec681f3Smrg
15817ec681f3Smrg   return get_int_const(m, type, value);
15827ec681f3Smrg}
15837ec681f3Smrg
15847ec681f3Smrgconst struct dxil_value *
15857ec681f3Smrgdxil_module_get_int32_const(struct dxil_module *m, int32_t value)
15867ec681f3Smrg{
15877ec681f3Smrg   const struct dxil_type *type = get_int32_type(m);
15887ec681f3Smrg   if (!type)
15897ec681f3Smrg      return NULL;
15907ec681f3Smrg
15917ec681f3Smrg   return get_int_const(m, type, value);
15927ec681f3Smrg}
15937ec681f3Smrg
15947ec681f3Smrgconst struct dxil_value *
15957ec681f3Smrgdxil_module_get_int64_const(struct dxil_module *m, int64_t value)
15967ec681f3Smrg{
15977ec681f3Smrg   const struct dxil_type *type = get_int64_type(m);
15987ec681f3Smrg   if (!type)
15997ec681f3Smrg      return NULL;
16007ec681f3Smrg
16017ec681f3Smrg   return get_int_const(m, type, value);
16027ec681f3Smrg}
16037ec681f3Smrg
16047ec681f3Smrgconst struct dxil_value *
16057ec681f3Smrgdxil_module_get_int_const(struct dxil_module *m, intmax_t value,
16067ec681f3Smrg                          unsigned bit_size)
16077ec681f3Smrg{
16087ec681f3Smrg   switch (bit_size) {
16097ec681f3Smrg   case 1:
16107ec681f3Smrg      assert(value == 0 || value == 1);
16117ec681f3Smrg      return dxil_module_get_int1_const(m, value);
16127ec681f3Smrg
16137ec681f3Smrg   case 8:
16147ec681f3Smrg      assert(INT8_MIN <= value && value <= INT8_MAX);
16157ec681f3Smrg      return dxil_module_get_int8_const(m, value);
16167ec681f3Smrg
16177ec681f3Smrg   case 16:
16187ec681f3Smrg      assert(INT16_MIN <= value && value <= INT16_MAX);
16197ec681f3Smrg      return dxil_module_get_int16_const(m, value);
16207ec681f3Smrg
16217ec681f3Smrg   case 32:
16227ec681f3Smrg      assert(INT32_MIN <= value && value <= INT32_MAX);
16237ec681f3Smrg      return dxil_module_get_int32_const(m, value);
16247ec681f3Smrg
16257ec681f3Smrg   case 64:
16267ec681f3Smrg      assert(INT64_MIN <= value && value <= INT64_MAX);
16277ec681f3Smrg      return dxil_module_get_int64_const(m, value);
16287ec681f3Smrg
16297ec681f3Smrg   default:
16307ec681f3Smrg      unreachable("unsupported bit-width");
16317ec681f3Smrg   }
16327ec681f3Smrg}
16337ec681f3Smrg
16347ec681f3Smrgconst struct dxil_value *
16357ec681f3Smrgdxil_module_get_float16_const(struct dxil_module *m, uint16_t value)
16367ec681f3Smrg{
16377ec681f3Smrg   const struct dxil_type *type = get_float16_type(m);
16387ec681f3Smrg   if (!type)
16397ec681f3Smrg      return NULL;
16407ec681f3Smrg
16417ec681f3Smrg   struct dxil_const *c;
16427ec681f3Smrg   LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
16437ec681f3Smrg      if (c->value.type != type || c->undef)
16447ec681f3Smrg         continue;
16457ec681f3Smrg
16467ec681f3Smrg      if (c->int_value == (uintmax_t)value)
16477ec681f3Smrg         return &c->value;
16487ec681f3Smrg   }
16497ec681f3Smrg
16507ec681f3Smrg   c = create_const(m, type, false);
16517ec681f3Smrg   if (!c)
16527ec681f3Smrg      return NULL;
16537ec681f3Smrg
16547ec681f3Smrg   c->int_value = (uintmax_t)value;
16557ec681f3Smrg   return &c->value;
16567ec681f3Smrg}
16577ec681f3Smrg
16587ec681f3Smrgconst struct dxil_value *
16597ec681f3Smrgdxil_module_get_float_const(struct dxil_module *m, float value)
16607ec681f3Smrg{
16617ec681f3Smrg   const struct dxil_type *type = get_float32_type(m);
16627ec681f3Smrg   if (!type)
16637ec681f3Smrg      return NULL;
16647ec681f3Smrg
16657ec681f3Smrg   struct dxil_const *c;
16667ec681f3Smrg   LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
16677ec681f3Smrg      if (c->value.type != type || c->undef)
16687ec681f3Smrg         continue;
16697ec681f3Smrg
16707ec681f3Smrg      if (c->float_value == value)
16717ec681f3Smrg         return &c->value;
16727ec681f3Smrg   }
16737ec681f3Smrg
16747ec681f3Smrg   c = create_const(m, type, false);
16757ec681f3Smrg   if (!c)
16767ec681f3Smrg      return NULL;
16777ec681f3Smrg
16787ec681f3Smrg   c->float_value = value;
16797ec681f3Smrg   return &c->value;
16807ec681f3Smrg}
16817ec681f3Smrg
16827ec681f3Smrgconst struct dxil_value *
16837ec681f3Smrgdxil_module_get_double_const(struct dxil_module *m, double value)
16847ec681f3Smrg{
16857ec681f3Smrg   const struct dxil_type *type = get_float64_type(m);
16867ec681f3Smrg   if (!type)
16877ec681f3Smrg      return NULL;
16887ec681f3Smrg
16897ec681f3Smrg   struct dxil_const *c;
16907ec681f3Smrg   LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
16917ec681f3Smrg      if (c->value.type != type || c->undef)
16927ec681f3Smrg         continue;
16937ec681f3Smrg
16947ec681f3Smrg      if (c->float_value == value)
16957ec681f3Smrg         return &c->value;
16967ec681f3Smrg   }
16977ec681f3Smrg
16987ec681f3Smrg   c = create_const(m, type, false);
16997ec681f3Smrg   if (!c)
17007ec681f3Smrg      return NULL;
17017ec681f3Smrg
17027ec681f3Smrg   c->float_value = value;
17037ec681f3Smrg   return &c->value;
17047ec681f3Smrg}
17057ec681f3Smrg
17067ec681f3Smrgconst struct dxil_value *
17077ec681f3Smrgdxil_module_get_array_const(struct dxil_module *m, const struct dxil_type *type,
17087ec681f3Smrg                            const struct dxil_value **values)
17097ec681f3Smrg{
17107ec681f3Smrg   assert(type->type == TYPE_ARRAY);
17117ec681f3Smrg   unsigned int num_values = type->array_or_vector_def.num_elems;
17127ec681f3Smrg
17137ec681f3Smrg   struct dxil_const *c;
17147ec681f3Smrg   LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
17157ec681f3Smrg      if (c->value.type != type || c->undef)
17167ec681f3Smrg         continue;
17177ec681f3Smrg
17187ec681f3Smrg      if (!memcmp(c->array_values, values, sizeof(*values) * num_values))
17197ec681f3Smrg         return &c->value;
17207ec681f3Smrg   }
17217ec681f3Smrg
17227ec681f3Smrg   c = create_const(m, type, false);
17237ec681f3Smrg   if (!c)
17247ec681f3Smrg      return NULL;
17257ec681f3Smrg   void *tmp =
17267ec681f3Smrg      ralloc_array(m->ralloc_ctx, struct dxil_value *, num_values);
17277ec681f3Smrg   memcpy(tmp, values, sizeof(*values) * num_values);
17287ec681f3Smrg   c->array_values = tmp;
17297ec681f3Smrg
17307ec681f3Smrg   return &c->value;
17317ec681f3Smrg}
17327ec681f3Smrg
17337ec681f3Smrgconst struct dxil_value *
17347ec681f3Smrgdxil_module_get_undef(struct dxil_module *m, const struct dxil_type *type)
17357ec681f3Smrg{
17367ec681f3Smrg   assert(type != NULL);
17377ec681f3Smrg
17387ec681f3Smrg   struct dxil_const *c;
17397ec681f3Smrg   LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
17407ec681f3Smrg      if (c->value.type != type)
17417ec681f3Smrg         continue;
17427ec681f3Smrg
17437ec681f3Smrg      if (c->undef)
17447ec681f3Smrg         return &c->value;
17457ec681f3Smrg   }
17467ec681f3Smrg
17477ec681f3Smrg   c = create_const(m, type, true);
17487ec681f3Smrg   return c ? &c->value : NULL;
17497ec681f3Smrg}
17507ec681f3Smrg
17517ec681f3Smrgenum dxil_module_code {
17527ec681f3Smrg   DXIL_MODULE_CODE_VERSION = 1,
17537ec681f3Smrg   DXIL_MODULE_CODE_TRIPLE = 2,
17547ec681f3Smrg   DXIL_MODULE_CODE_DATALAYOUT = 3,
17557ec681f3Smrg   DXIL_MODULE_CODE_ASM = 4,
17567ec681f3Smrg   DXIL_MODULE_CODE_SECTIONNAME = 5,
17577ec681f3Smrg   DXIL_MODULE_CODE_DEPLIB = 6,
17587ec681f3Smrg   DXIL_MODULE_CODE_GLOBALVAR = 7,
17597ec681f3Smrg   DXIL_MODULE_CODE_FUNCTION = 8,
17607ec681f3Smrg   DXIL_MODULE_CODE_ALIAS = 9,
17617ec681f3Smrg   DXIL_MODULE_CODE_PURGEVALS = 10,
17627ec681f3Smrg   DXIL_MODULE_CODE_GCNAME = 11,
17637ec681f3Smrg   DXIL_MODULE_CODE_COMDAT = 12,
17647ec681f3Smrg};
17657ec681f3Smrg
17667ec681f3Smrgstatic bool
17677ec681f3Smrgemit_target_triple(struct dxil_module *m, const char *triple)
17687ec681f3Smrg{
17697ec681f3Smrg   uint64_t temp[256];
17707ec681f3Smrg   assert(strlen(triple) < ARRAY_SIZE(temp));
17717ec681f3Smrg
17727ec681f3Smrg   for (int i = 0; i < strlen(triple); ++i)
17737ec681f3Smrg      temp[i] = triple[i];
17747ec681f3Smrg
17757ec681f3Smrg   return emit_record(m, DXIL_MODULE_CODE_TRIPLE, temp, strlen(triple));
17767ec681f3Smrg}
17777ec681f3Smrg
17787ec681f3Smrgstatic bool
17797ec681f3Smrgemit_datalayout(struct dxil_module *m, const char *datalayout)
17807ec681f3Smrg{
17817ec681f3Smrg   uint64_t temp[256];
17827ec681f3Smrg   assert(strlen(datalayout) < ARRAY_SIZE(temp));
17837ec681f3Smrg
17847ec681f3Smrg   for (int i = 0; i < strlen(datalayout); ++i)
17857ec681f3Smrg      temp[i] = datalayout[i];
17867ec681f3Smrg
17877ec681f3Smrg   return emit_record(m, DXIL_MODULE_CODE_DATALAYOUT,
17887ec681f3Smrg                      temp, strlen(datalayout));
17897ec681f3Smrg}
17907ec681f3Smrg
17917ec681f3Smrgstatic const struct dxil_value *
17927ec681f3Smrgadd_gvar(struct dxil_module *m, const char *name,
17937ec681f3Smrg         const struct dxil_type *type, const struct dxil_type *value_type,
17947ec681f3Smrg         enum dxil_address_space as, int align, const struct dxil_value *value)
17957ec681f3Smrg{
17967ec681f3Smrg   struct dxil_gvar *gvar = ralloc_size(m->ralloc_ctx,
17977ec681f3Smrg                                        sizeof(struct dxil_gvar));
17987ec681f3Smrg   if (!gvar)
17997ec681f3Smrg      return NULL;
18007ec681f3Smrg
18017ec681f3Smrg   gvar->type = type;
18027ec681f3Smrg   gvar->name = ralloc_strdup(m->ralloc_ctx, name);
18037ec681f3Smrg   gvar->as = as;
18047ec681f3Smrg   gvar->align = align;
18057ec681f3Smrg   gvar->constant = !!value;
18067ec681f3Smrg   gvar->initializer = value;
18077ec681f3Smrg
18087ec681f3Smrg   gvar->value.id = -1;
18097ec681f3Smrg   gvar->value.type = value_type;
18107ec681f3Smrg
18117ec681f3Smrg   list_addtail(&gvar->head, &m->gvar_list);
18127ec681f3Smrg   return &gvar->value;
18137ec681f3Smrg}
18147ec681f3Smrg
18157ec681f3Smrgconst struct dxil_value *
18167ec681f3Smrgdxil_add_global_var(struct dxil_module *m, const char *name,
18177ec681f3Smrg                    const struct dxil_type *type,
18187ec681f3Smrg                    enum dxil_address_space as, int align,
18197ec681f3Smrg                    const struct dxil_value *value)
18207ec681f3Smrg{
18217ec681f3Smrg   return add_gvar(m, name, type, type, as, align, value);
18227ec681f3Smrg}
18237ec681f3Smrg
18247ec681f3Smrgconst struct dxil_value *
18257ec681f3Smrgdxil_add_global_ptr_var(struct dxil_module *m, const char *name,
18267ec681f3Smrg                        const struct dxil_type *type,
18277ec681f3Smrg                        enum dxil_address_space as, int align,
18287ec681f3Smrg                        const struct dxil_value *value)
18297ec681f3Smrg{
18307ec681f3Smrg   return add_gvar(m, name, type, dxil_module_get_pointer_type(m, type),
18317ec681f3Smrg                   as, align, value);
18327ec681f3Smrg}
18337ec681f3Smrg
18347ec681f3Smrgstatic struct dxil_func *
18357ec681f3Smrgadd_function(struct dxil_module *m, const char *name,
18367ec681f3Smrg             const struct dxil_type *type,
18377ec681f3Smrg             bool decl, unsigned attr_set)
18387ec681f3Smrg{
18397ec681f3Smrg   assert(type->type == TYPE_FUNCTION);
18407ec681f3Smrg
18417ec681f3Smrg   struct dxil_func *func = ralloc_size(m->ralloc_ctx,
18427ec681f3Smrg                                        sizeof(struct dxil_func));
18437ec681f3Smrg   if (!func)
18447ec681f3Smrg      return NULL;
18457ec681f3Smrg
18467ec681f3Smrg   func->name = ralloc_strdup(func, name);
18477ec681f3Smrg   if (!func->name) {
18487ec681f3Smrg      return NULL;
18497ec681f3Smrg   }
18507ec681f3Smrg
18517ec681f3Smrg   func->type = type;
18527ec681f3Smrg   func->decl = decl;
18537ec681f3Smrg   func->attr_set = attr_set;
18547ec681f3Smrg
18557ec681f3Smrg   func->value.id = -1;
18567ec681f3Smrg   func->value.type  = type->function_def.ret_type;
18577ec681f3Smrg   list_addtail(&func->head, &m->func_list);
18587ec681f3Smrg   return func;
18597ec681f3Smrg}
18607ec681f3Smrg
18617ec681f3Smrgconst struct dxil_func *
18627ec681f3Smrgdxil_add_function_def(struct dxil_module *m, const char *name,
18637ec681f3Smrg                      const struct dxil_type *type)
18647ec681f3Smrg{
18657ec681f3Smrg   return add_function(m, name, type, false, 0);
18667ec681f3Smrg}
18677ec681f3Smrg
18687ec681f3Smrgstatic unsigned
18697ec681f3Smrgget_attr_set(struct dxil_module *m, enum dxil_attr_kind attr)
18707ec681f3Smrg{
18717ec681f3Smrg   struct dxil_attrib attrs[2] = {
18727ec681f3Smrg      { DXIL_ATTR_ENUM, { DXIL_ATTR_KIND_NO_UNWIND } },
18737ec681f3Smrg      { DXIL_ATTR_ENUM, { attr } }
18747ec681f3Smrg   };
18757ec681f3Smrg
18767ec681f3Smrg   int index = 1;
18777ec681f3Smrg   struct attrib_set *as;
18787ec681f3Smrg   LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) {
18797ec681f3Smrg      if (!memcmp(as->attrs, attrs, sizeof(attrs)))
18807ec681f3Smrg         return index;
18817ec681f3Smrg      index++;
18827ec681f3Smrg   }
18837ec681f3Smrg
18847ec681f3Smrg   as = ralloc_size(m->ralloc_ctx, sizeof(struct attrib_set));
18857ec681f3Smrg   if (!as)
18867ec681f3Smrg      return 0;
18877ec681f3Smrg
18887ec681f3Smrg   memcpy(as->attrs, attrs, sizeof(attrs));
18897ec681f3Smrg   as->num_attrs = 1;
18907ec681f3Smrg   if (attr != DXIL_ATTR_KIND_NONE)
18917ec681f3Smrg      as->num_attrs++;
18927ec681f3Smrg
18937ec681f3Smrg   list_addtail(&as->head, &m->attr_set_list);
18947ec681f3Smrg   assert(list_length(&m->attr_set_list) == index);
18957ec681f3Smrg   return index;
18967ec681f3Smrg}
18977ec681f3Smrg
18987ec681f3Smrgconst struct dxil_func *
18997ec681f3Smrgdxil_add_function_decl(struct dxil_module *m, const char *name,
19007ec681f3Smrg                       const struct dxil_type *type,
19017ec681f3Smrg                       enum dxil_attr_kind attr)
19027ec681f3Smrg{
19037ec681f3Smrg   unsigned attr_set = get_attr_set(m, attr);
19047ec681f3Smrg   if (!attr_set)
19057ec681f3Smrg      return NULL;
19067ec681f3Smrg
19077ec681f3Smrg   return add_function(m, name, type, true, attr_set);
19087ec681f3Smrg}
19097ec681f3Smrg
19107ec681f3Smrgstatic bool
19117ec681f3Smrgemit_module_info_function(struct dxil_module *m, int type, bool declaration,
19127ec681f3Smrg                          int attr_set_index)
19137ec681f3Smrg{
19147ec681f3Smrg   uint64_t data[] = {
19157ec681f3Smrg      type, 0/* address space */, declaration, 0/* linkage */,
19167ec681f3Smrg      attr_set_index, 0/* alignment */, 0 /* section */, 0 /* visibility */,
19177ec681f3Smrg      0 /* GC */, 0 /* unnamed addr */, 0 /* prologue data */,
19187ec681f3Smrg      0 /* storage class */, 0 /* comdat */, 0 /* prefix-data */,
19197ec681f3Smrg      0 /* personality */
19207ec681f3Smrg   };
19217ec681f3Smrg   return emit_record(m, DXIL_MODULE_CODE_FUNCTION, data, ARRAY_SIZE(data));
19227ec681f3Smrg}
19237ec681f3Smrg
19247ec681f3Smrgenum gvar_var_flags {
19257ec681f3Smrg   GVAR_FLAG_CONSTANT = (1 << 0),
19267ec681f3Smrg   GVAR_FLAG_EXPLICIT_TYPE = (1 << 1),
19277ec681f3Smrg};
19287ec681f3Smrg
19297ec681f3Smrgenum gvar_var_linkage {
19307ec681f3Smrg   GVAR_LINKAGE_EXTERNAL = 0,
19317ec681f3Smrg   GVAR_LINKAGE_APPENDING = 2,
19327ec681f3Smrg   GVAR_LINKAGE_INTERNAL = 3,
19337ec681f3Smrg   GVAR_LINKAGE_EXTERNAL_WEAK = 7,
19347ec681f3Smrg   GVAR_LINKAGE_COMMON = 8,
19357ec681f3Smrg   GVAR_LINKAGE_PRIVATE = 9,
19367ec681f3Smrg   GVAR_LINKAGE_AVAILABLE_EXTERNALLY = 12,
19377ec681f3Smrg   GVAR_LINKAGE_WEAK_ANY = 16,
19387ec681f3Smrg   GVAR_LINKAGE_WEAK_ODR = 17,
19397ec681f3Smrg   GVAR_LINKAGE_LINK_ONCE_ODR = 19,
19407ec681f3Smrg};
19417ec681f3Smrg
19427ec681f3Smrgstatic bool
19437ec681f3Smrgemit_module_info_global(struct dxil_module *m, const struct dxil_gvar *gvar,
19447ec681f3Smrg                        const struct dxil_abbrev *simple_gvar_abbr)
19457ec681f3Smrg{
19467ec681f3Smrg   uint64_t data[] = {
19477ec681f3Smrg      DXIL_MODULE_CODE_GLOBALVAR,
19487ec681f3Smrg      gvar->type->id,
19497ec681f3Smrg      (gvar->as << 2) | GVAR_FLAG_EXPLICIT_TYPE |
19507ec681f3Smrg      (gvar->constant ? GVAR_FLAG_CONSTANT : 0),
19517ec681f3Smrg      gvar->initializer ? gvar->initializer->id + 1 : 0,
19527ec681f3Smrg      (gvar->initializer ? GVAR_LINKAGE_INTERNAL : GVAR_LINKAGE_EXTERNAL),
19537ec681f3Smrg      util_logbase2(gvar->align) + 1,
19547ec681f3Smrg      0
19557ec681f3Smrg   };
19567ec681f3Smrg   return emit_record_abbrev(&m->buf, 4, simple_gvar_abbr,
19577ec681f3Smrg                             data, ARRAY_SIZE(data));
19587ec681f3Smrg}
19597ec681f3Smrg
19607ec681f3Smrgstatic bool
19617ec681f3Smrgemit_module_info(struct dxil_module *m)
19627ec681f3Smrg{
19637ec681f3Smrg   struct dxil_gvar *gvar;
19647ec681f3Smrg   int max_global_type = 0;
19657ec681f3Smrg   int max_alignment = 0;
19667ec681f3Smrg   LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) {
19677ec681f3Smrg      assert(gvar->type->id >= 0);
19687ec681f3Smrg      max_global_type = MAX2(max_global_type, gvar->type->id);
19697ec681f3Smrg      max_alignment = MAX2(max_alignment, gvar->align);
19707ec681f3Smrg   }
19717ec681f3Smrg
19727ec681f3Smrg   struct dxil_abbrev simple_gvar_abbr = {
19737ec681f3Smrg      { LITERAL(DXIL_MODULE_CODE_GLOBALVAR),
19747ec681f3Smrg        FIXED(util_logbase2(max_global_type) + 1),
19757ec681f3Smrg        VBR(6), VBR(6), FIXED(5),
19767ec681f3Smrg        FIXED(util_logbase2(max_alignment) + 1),
19777ec681f3Smrg        LITERAL(0) }, 7
19787ec681f3Smrg   };
19797ec681f3Smrg
19807ec681f3Smrg   if (!emit_target_triple(m, "dxil-ms-dx") ||
19817ec681f3Smrg       !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") ||
19827ec681f3Smrg       !define_abbrev(m, &simple_gvar_abbr))
19837ec681f3Smrg      return false;
19847ec681f3Smrg
19857ec681f3Smrg   LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) {
19867ec681f3Smrg      assert(gvar->type->id >= 0);
19877ec681f3Smrg      if (!emit_module_info_global(m, gvar, &simple_gvar_abbr))
19887ec681f3Smrg         return false;
19897ec681f3Smrg   }
19907ec681f3Smrg
19917ec681f3Smrg   struct dxil_func *func;
19927ec681f3Smrg   LIST_FOR_EACH_ENTRY(func, &m->func_list, head) {
19937ec681f3Smrg      assert(func->type->id >= 0);
19947ec681f3Smrg      if (!emit_module_info_function(m, func->type->id, func->decl,
19957ec681f3Smrg                                     func->attr_set))
19967ec681f3Smrg         return false;
19977ec681f3Smrg   }
19987ec681f3Smrg
19997ec681f3Smrg   return true;
20007ec681f3Smrg}
20017ec681f3Smrg
20027ec681f3Smrgstatic bool
20037ec681f3Smrgemit_module_const_abbrevs(struct dxil_module *m)
20047ec681f3Smrg{
20057ec681f3Smrg   /* these are unused for now, so let's not even record them */
20067ec681f3Smrg   struct dxil_abbrev abbrevs[] = {
20077ec681f3Smrg      { { LITERAL(CST_CODE_AGGREGATE), ARRAY, FIXED(5) }, 3 },
20087ec681f3Smrg      { { LITERAL(CST_CODE_STRING), ARRAY, FIXED(8) }, 3 },
20097ec681f3Smrg      { { LITERAL(CST_CODE_CSTRING), ARRAY, FIXED(7) }, 3 },
20107ec681f3Smrg      { { LITERAL(CST_CODE_CSTRING), ARRAY, CHAR6 }, 3 },
20117ec681f3Smrg   };
20127ec681f3Smrg
20137ec681f3Smrg   for (int i = 0; i < ARRAY_SIZE(abbrevs); ++i) {
20147ec681f3Smrg      if (!define_abbrev(m, abbrevs + i))
20157ec681f3Smrg         return false;
20167ec681f3Smrg   }
20177ec681f3Smrg
20187ec681f3Smrg   return true;
20197ec681f3Smrg}
20207ec681f3Smrg
20217ec681f3Smrgstatic bool
20227ec681f3Smrgemit_set_type(struct dxil_module *m, unsigned type_index)
20237ec681f3Smrg{
20247ec681f3Smrg   uint64_t data[] = { CST_CODE_SETTYPE, type_index };
20257ec681f3Smrg   return emit_const_abbrev_record(m, CONST_ABBREV_SETTYPE,
20267ec681f3Smrg                                   data, ARRAY_SIZE(data));
20277ec681f3Smrg}
20287ec681f3Smrg
20297ec681f3Smrgstatic bool
20307ec681f3Smrgemit_null_value(struct dxil_module *m)
20317ec681f3Smrg{
20327ec681f3Smrg   return emit_record_no_abbrev(&m->buf, CST_CODE_NULL, NULL, 0);
20337ec681f3Smrg}
20347ec681f3Smrg
20357ec681f3Smrgstatic bool
20367ec681f3Smrgemit_undef_value(struct dxil_module *m)
20377ec681f3Smrg{
20387ec681f3Smrg   return emit_record_no_abbrev(&m->buf, CST_CODE_UNDEF, NULL, 0);
20397ec681f3Smrg}
20407ec681f3Smrg
20417ec681f3Smrgstatic uint64_t
20427ec681f3Smrgencode_signed(int64_t value)
20437ec681f3Smrg{
20447ec681f3Smrg   return value >= 0 ?
20457ec681f3Smrg      (value << 1) :
20467ec681f3Smrg      ((-value << 1) | 1);
20477ec681f3Smrg}
20487ec681f3Smrg
20497ec681f3Smrgstatic bool
20507ec681f3Smrgemit_int_value(struct dxil_module *m, int64_t value)
20517ec681f3Smrg{
20527ec681f3Smrg   if (!value)
20537ec681f3Smrg      return emit_null_value(m);
20547ec681f3Smrg
20557ec681f3Smrg   uint64_t data[] = { CST_CODE_INTEGER, encode_signed(value) };
20567ec681f3Smrg   return emit_const_abbrev_record(m, CONST_ABBREV_INTEGER,
20577ec681f3Smrg                                   data, ARRAY_SIZE(data));
20587ec681f3Smrg}
20597ec681f3Smrg
20607ec681f3Smrgstatic bool
20617ec681f3Smrgemit_float16_value(struct dxil_module *m, uint16_t value)
20627ec681f3Smrg{
20637ec681f3Smrg   if (!value)
20647ec681f3Smrg      return emit_null_value(m);
20657ec681f3Smrg   uint64_t data = value;
20667ec681f3Smrg   return emit_record_no_abbrev(&m->buf, CST_CODE_FLOAT, &data, 1);
20677ec681f3Smrg}
20687ec681f3Smrg
20697ec681f3Smrgstatic bool
20707ec681f3Smrgemit_float_value(struct dxil_module *m, float value)
20717ec681f3Smrg{
20727ec681f3Smrg   uint64_t data = fui(value);
20737ec681f3Smrg   if (data == UINT32_C(0))
20747ec681f3Smrg      return emit_null_value(m);
20757ec681f3Smrg   return emit_record_no_abbrev(&m->buf, CST_CODE_FLOAT, &data, 1);
20767ec681f3Smrg}
20777ec681f3Smrg
20787ec681f3Smrgstatic bool
20797ec681f3Smrgemit_double_value(struct dxil_module *m, double value)
20807ec681f3Smrg{
20817ec681f3Smrg   union di u;
20827ec681f3Smrg   u.d = value;
20837ec681f3Smrg   if (u.ui == UINT64_C(0))
20847ec681f3Smrg      return emit_null_value(m);
20857ec681f3Smrg   return emit_record_no_abbrev(&m->buf, CST_CODE_FLOAT, &u.ui, 1);
20867ec681f3Smrg}
20877ec681f3Smrg
20887ec681f3Smrgstatic bool
20897ec681f3Smrgemit_aggregate_values(struct dxil_module *m, const struct dxil_value **values,
20907ec681f3Smrg                      int num_values)
20917ec681f3Smrg{
20927ec681f3Smrg   uint64_t *value_ids = ralloc_array(m->ralloc_ctx, uint64_t, num_values);
20937ec681f3Smrg   int i;
20947ec681f3Smrg
20957ec681f3Smrg   for (i = 0; i < num_values; i++)
20967ec681f3Smrg      value_ids[i] = values[i]->id;
20977ec681f3Smrg
20987ec681f3Smrg   return emit_record_no_abbrev(&m->buf, CST_CODE_AGGREGATE, value_ids,
20997ec681f3Smrg                                num_values);
21007ec681f3Smrg}
21017ec681f3Smrg
21027ec681f3Smrgstatic bool
21037ec681f3Smrgemit_consts(struct dxil_module *m)
21047ec681f3Smrg{
21057ec681f3Smrg   const struct dxil_type *curr_type = NULL;
21067ec681f3Smrg   struct dxil_const *c;
21077ec681f3Smrg   LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
21087ec681f3Smrg      assert(c->value.id >= 0);
21097ec681f3Smrg      assert(c->value.type != NULL);
21107ec681f3Smrg      if (curr_type != c->value.type) {
21117ec681f3Smrg         assert(c->value.type->id >= 0);
21127ec681f3Smrg         if (!emit_set_type(m, c->value.type->id))
21137ec681f3Smrg            return false;
21147ec681f3Smrg         curr_type = c->value.type;
21157ec681f3Smrg      }
21167ec681f3Smrg
21177ec681f3Smrg      if (c->undef) {
21187ec681f3Smrg         if (!emit_undef_value(m))
21197ec681f3Smrg            return false;
21207ec681f3Smrg         continue;
21217ec681f3Smrg      }
21227ec681f3Smrg
21237ec681f3Smrg      switch (curr_type->type) {
21247ec681f3Smrg      case TYPE_INTEGER:
21257ec681f3Smrg         if (!emit_int_value(m, c->int_value))
21267ec681f3Smrg            return false;
21277ec681f3Smrg         break;
21287ec681f3Smrg
21297ec681f3Smrg      case TYPE_FLOAT:
21307ec681f3Smrg         switch (curr_type->float_bits) {
21317ec681f3Smrg         case 16:
21327ec681f3Smrg            if (!emit_float16_value(m, (uint16_t)(uintmax_t)c->int_value))
21337ec681f3Smrg               return false;
21347ec681f3Smrg            break;
21357ec681f3Smrg         case 32:
21367ec681f3Smrg            if (!emit_float_value(m, c->float_value))
21377ec681f3Smrg               return false;
21387ec681f3Smrg            break;
21397ec681f3Smrg         case 64:
21407ec681f3Smrg            if (!emit_double_value(m, c->float_value))
21417ec681f3Smrg               return false;
21427ec681f3Smrg            break;
21437ec681f3Smrg         default:
21447ec681f3Smrg            unreachable("unexpected float_bits");
21457ec681f3Smrg         }
21467ec681f3Smrg         break;
21477ec681f3Smrg
21487ec681f3Smrg      case TYPE_ARRAY:
21497ec681f3Smrg         if (!emit_aggregate_values(m, c->array_values,
21507ec681f3Smrg                                    c->value.type->array_or_vector_def.num_elems))
21517ec681f3Smrg            return false;
21527ec681f3Smrg         break;
21537ec681f3Smrg
21547ec681f3Smrg      default:
21557ec681f3Smrg         unreachable("unsupported constant type");
21567ec681f3Smrg      }
21577ec681f3Smrg   }
21587ec681f3Smrg
21597ec681f3Smrg   return true;
21607ec681f3Smrg}
21617ec681f3Smrg
21627ec681f3Smrgstatic bool
21637ec681f3Smrgemit_module_consts(struct dxil_module *m)
21647ec681f3Smrg{
21657ec681f3Smrg   return enter_subblock(m, DXIL_CONST_BLOCK, 4) &&
21667ec681f3Smrg          emit_module_const_abbrevs(m) &&
21677ec681f3Smrg          emit_consts(m) &&
21687ec681f3Smrg          exit_block(m);
21697ec681f3Smrg}
21707ec681f3Smrg
21717ec681f3Smrgstatic bool
21727ec681f3Smrgemit_value_symtab_abbrev_record(struct dxil_module *m,
21737ec681f3Smrg                                enum value_symtab_abbrev_id abbrev,
21747ec681f3Smrg                                const uint64_t *data, size_t size)
21757ec681f3Smrg{
21767ec681f3Smrg   assert(abbrev < ARRAY_SIZE(value_symtab_abbrevs));
21777ec681f3Smrg   return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,
21787ec681f3Smrg                             value_symtab_abbrevs + abbrev, data, size);
21797ec681f3Smrg}
21807ec681f3Smrg
21817ec681f3Smrgstatic bool
21827ec681f3Smrgemit_symtab_entry(struct dxil_module *m, unsigned value, const char *name)
21837ec681f3Smrg{
21847ec681f3Smrg   uint64_t temp[256];
21857ec681f3Smrg   assert(strlen(name) < ARRAY_SIZE(temp) - 2);
21867ec681f3Smrg
21877ec681f3Smrg   temp[0] = VST_CODE_ENTRY;
21887ec681f3Smrg   temp[1] = value;
21897ec681f3Smrg   for (int i = 0; i < strlen(name); ++i)
21907ec681f3Smrg      temp[i + 2] = name[i];
21917ec681f3Smrg
21927ec681f3Smrg   enum value_symtab_abbrev_id abbrev = VST_ABBREV_ENTRY_8;
21937ec681f3Smrg   if (is_char6_string(name))
21947ec681f3Smrg      abbrev = VST_ABBREV_ENTRY_6;
21957ec681f3Smrg   else if (is_char7_string(name))
21967ec681f3Smrg      abbrev = VST_ABBREV_ENTRY_7;
21977ec681f3Smrg
21987ec681f3Smrg   return emit_value_symtab_abbrev_record(m, abbrev, temp, 2 + strlen(name));
21997ec681f3Smrg}
22007ec681f3Smrg
22017ec681f3Smrgstatic bool
22027ec681f3Smrgemit_value_symbol_table(struct dxil_module *m)
22037ec681f3Smrg{
22047ec681f3Smrg   if (!enter_subblock(m, DXIL_VALUE_SYMTAB_BLOCK, 4))
22057ec681f3Smrg      return false;
22067ec681f3Smrg
22077ec681f3Smrg   struct dxil_func *func;
22087ec681f3Smrg   LIST_FOR_EACH_ENTRY(func, &m->func_list, head) {
22097ec681f3Smrg      if (!emit_symtab_entry(m, func->value.id, func->name))
22107ec681f3Smrg         return false;
22117ec681f3Smrg   }
22127ec681f3Smrg   struct dxil_gvar *gvar;
22137ec681f3Smrg   LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) {
22147ec681f3Smrg      if (!emit_symtab_entry(m, gvar->value.id, gvar->name))
22157ec681f3Smrg         return false;
22167ec681f3Smrg   }
22177ec681f3Smrg   return exit_block(m);
22187ec681f3Smrg}
22197ec681f3Smrg
22207ec681f3Smrgenum metadata_codes {
22217ec681f3Smrg  METADATA_STRING = 1,
22227ec681f3Smrg  METADATA_VALUE = 2,
22237ec681f3Smrg  METADATA_NODE = 3,
22247ec681f3Smrg  METADATA_NAME = 4,
22257ec681f3Smrg  METADATA_KIND = 6,
22267ec681f3Smrg  METADATA_NAMED_NODE = 10
22277ec681f3Smrg};
22287ec681f3Smrg
22297ec681f3Smrgenum metadata_abbrev_id {
22307ec681f3Smrg   METADATA_ABBREV_STRING,
22317ec681f3Smrg   METADATA_ABBREV_NAME
22327ec681f3Smrg};
22337ec681f3Smrg
22347ec681f3Smrgstatic const struct dxil_abbrev metadata_abbrevs[] = {
22357ec681f3Smrg   [METADATA_ABBREV_STRING] = {
22367ec681f3Smrg      { LITERAL(METADATA_STRING), ARRAY, FIXED(8) }, 3
22377ec681f3Smrg   },
22387ec681f3Smrg   [METADATA_ABBREV_NAME] = {
22397ec681f3Smrg      { LITERAL(METADATA_NAME), ARRAY, FIXED(8) }, 3
22407ec681f3Smrg   },
22417ec681f3Smrg};
22427ec681f3Smrg
22437ec681f3Smrgstatic bool
22447ec681f3Smrgemit_metadata_abbrevs(struct dxil_module *m)
22457ec681f3Smrg{
22467ec681f3Smrg   for (int i = 0; i < ARRAY_SIZE(metadata_abbrevs); ++i) {
22477ec681f3Smrg      if (!define_abbrev(m, metadata_abbrevs + i))
22487ec681f3Smrg         return false;
22497ec681f3Smrg   }
22507ec681f3Smrg   return true;
22517ec681f3Smrg}
22527ec681f3Smrg
22537ec681f3Smrgstatic struct dxil_mdnode *
22547ec681f3Smrgcreate_mdnode(struct dxil_module *m, enum mdnode_type type)
22557ec681f3Smrg{
22567ec681f3Smrg   struct dxil_mdnode *ret = rzalloc_size(m->ralloc_ctx,
22577ec681f3Smrg                                          sizeof(struct dxil_mdnode));
22587ec681f3Smrg   if (ret) {
22597ec681f3Smrg      ret->type = type;
22607ec681f3Smrg      ret->id = list_length(&m->mdnode_list) + 1; /* zero is reserved for NULL nodes */
22617ec681f3Smrg      list_addtail(&ret->head, &m->mdnode_list);
22627ec681f3Smrg   }
22637ec681f3Smrg   return ret;
22647ec681f3Smrg}
22657ec681f3Smrg
22667ec681f3Smrgconst struct dxil_mdnode *
22677ec681f3Smrgdxil_get_metadata_string(struct dxil_module *m, const char *str)
22687ec681f3Smrg{
22697ec681f3Smrg   assert(str);
22707ec681f3Smrg
22717ec681f3Smrg   struct dxil_mdnode *n;
22727ec681f3Smrg   LIST_FOR_EACH_ENTRY(n, &m->mdnode_list, head) {
22737ec681f3Smrg      if (n->type == MD_STRING &&
22747ec681f3Smrg          !strcmp(n->string, str))
22757ec681f3Smrg         return n;
22767ec681f3Smrg   }
22777ec681f3Smrg
22787ec681f3Smrg   n = create_mdnode(m, MD_STRING);
22797ec681f3Smrg   if (n) {
22807ec681f3Smrg      n->string = ralloc_strdup(n, str);
22817ec681f3Smrg      if (!n->string)
22827ec681f3Smrg         return NULL;
22837ec681f3Smrg   }
22847ec681f3Smrg   return n;
22857ec681f3Smrg}
22867ec681f3Smrg
22877ec681f3Smrgconst struct dxil_mdnode *
22887ec681f3Smrgdxil_get_metadata_value(struct dxil_module *m, const struct dxil_type *type,
22897ec681f3Smrg                        const struct dxil_value *value)
22907ec681f3Smrg{
22917ec681f3Smrg   struct dxil_mdnode *n;
22927ec681f3Smrg   LIST_FOR_EACH_ENTRY(n, &m->mdnode_list, head) {
22937ec681f3Smrg      if (n->type == MD_VALUE &&
22947ec681f3Smrg          n->value.type == type &&
22957ec681f3Smrg          n->value.value == value)
22967ec681f3Smrg         return n;
22977ec681f3Smrg   }
22987ec681f3Smrg
22997ec681f3Smrg   n = create_mdnode(m, MD_VALUE);
23007ec681f3Smrg   if (n) {
23017ec681f3Smrg      n->value.type = type;
23027ec681f3Smrg      n->value.value = value;
23037ec681f3Smrg   }
23047ec681f3Smrg   return n;
23057ec681f3Smrg}
23067ec681f3Smrg
23077ec681f3Smrgconst struct dxil_mdnode *
23087ec681f3Smrgdxil_get_metadata_func(struct dxil_module *m, const struct dxil_func *func)
23097ec681f3Smrg{
23107ec681f3Smrg   const struct dxil_type *ptr_type =
23117ec681f3Smrg      dxil_module_get_pointer_type(m, func->type);
23127ec681f3Smrg   return dxil_get_metadata_value(m, ptr_type, &func->value);
23137ec681f3Smrg}
23147ec681f3Smrg
23157ec681f3Smrgconst struct dxil_mdnode *
23167ec681f3Smrgdxil_get_metadata_node(struct dxil_module *m,
23177ec681f3Smrg                       const struct dxil_mdnode *subnodes[],
23187ec681f3Smrg                       size_t num_subnodes)
23197ec681f3Smrg{
23207ec681f3Smrg   struct dxil_mdnode *n;
23217ec681f3Smrg   LIST_FOR_EACH_ENTRY(n, &m->mdnode_list, head) {
23227ec681f3Smrg      if (n->type == MD_NODE &&
23237ec681f3Smrg          n->node.num_subnodes == num_subnodes &&
23247ec681f3Smrg          !memcmp(n->node.subnodes, subnodes, sizeof(struct dxil_mdnode *) *
23257ec681f3Smrg                  num_subnodes))
23267ec681f3Smrg         return n;
23277ec681f3Smrg   }
23287ec681f3Smrg
23297ec681f3Smrg   n = create_mdnode(m, MD_NODE);
23307ec681f3Smrg   if (n) {
23317ec681f3Smrg      void *tmp = ralloc_array(n, struct dxil_mdnode *, num_subnodes);
23327ec681f3Smrg      if (!tmp)
23337ec681f3Smrg         return NULL;
23347ec681f3Smrg
23357ec681f3Smrg      memcpy(tmp, subnodes, sizeof(struct dxil_mdnode *) * num_subnodes);
23367ec681f3Smrg      n->node.subnodes = tmp;
23377ec681f3Smrg      n->node.num_subnodes = num_subnodes;
23387ec681f3Smrg   }
23397ec681f3Smrg   return n;
23407ec681f3Smrg}
23417ec681f3Smrg
23427ec681f3Smrgconst struct dxil_mdnode *
23437ec681f3Smrgdxil_get_metadata_int1(struct dxil_module *m, bool value)
23447ec681f3Smrg{
23457ec681f3Smrg   const struct dxil_type *type = get_int1_type(m);
23467ec681f3Smrg   if (!type)
23477ec681f3Smrg      return NULL;
23487ec681f3Smrg
23497ec681f3Smrg   const struct dxil_value *const_value = get_int_const(m, type, value);
23507ec681f3Smrg   if (!const_value)
23517ec681f3Smrg      return NULL;
23527ec681f3Smrg
23537ec681f3Smrg   return dxil_get_metadata_value(m, type, const_value);
23547ec681f3Smrg}
23557ec681f3Smrg
23567ec681f3Smrgconst struct dxil_mdnode *
23577ec681f3Smrgdxil_get_metadata_int8(struct dxil_module *m, int8_t value)
23587ec681f3Smrg{
23597ec681f3Smrg   const struct dxil_type *type = get_int8_type(m);
23607ec681f3Smrg   if (!type)
23617ec681f3Smrg      return NULL;
23627ec681f3Smrg
23637ec681f3Smrg   const struct dxil_value *const_value = get_int_const(m, type, value);
23647ec681f3Smrg   if (!const_value)
23657ec681f3Smrg      return NULL;
23667ec681f3Smrg
23677ec681f3Smrg   return dxil_get_metadata_value(m, type, const_value);
23687ec681f3Smrg}
23697ec681f3Smrg
23707ec681f3Smrgconst struct dxil_mdnode *
23717ec681f3Smrgdxil_get_metadata_int32(struct dxil_module *m, int32_t value)
23727ec681f3Smrg{
23737ec681f3Smrg   const struct dxil_type *type = get_int32_type(m);
23747ec681f3Smrg   if (!type)
23757ec681f3Smrg      return NULL;
23767ec681f3Smrg
23777ec681f3Smrg   const struct dxil_value *const_value = get_int_const(m, type, value);
23787ec681f3Smrg   if (!const_value)
23797ec681f3Smrg      return NULL;
23807ec681f3Smrg
23817ec681f3Smrg   return dxil_get_metadata_value(m, type, const_value);
23827ec681f3Smrg}
23837ec681f3Smrg
23847ec681f3Smrgconst struct dxil_mdnode *
23857ec681f3Smrgdxil_get_metadata_int64(struct dxil_module *m, int64_t value)
23867ec681f3Smrg{
23877ec681f3Smrg   const struct dxil_type *type = get_int64_type(m);
23887ec681f3Smrg   if (!type)
23897ec681f3Smrg      return NULL;
23907ec681f3Smrg
23917ec681f3Smrg   const struct dxil_value *const_value = get_int_const(m, type, value);
23927ec681f3Smrg   if (!const_value)
23937ec681f3Smrg      return NULL;
23947ec681f3Smrg
23957ec681f3Smrg   return dxil_get_metadata_value(m, type, const_value);
23967ec681f3Smrg}
23977ec681f3Smrg
23987ec681f3Smrgbool
23997ec681f3Smrgdxil_add_metadata_named_node(struct dxil_module *m, const char *name,
24007ec681f3Smrg                             const struct dxil_mdnode *subnodes[],
24017ec681f3Smrg                             size_t num_subnodes)
24027ec681f3Smrg{
24037ec681f3Smrg   struct dxil_named_node *n = ralloc_size(m->ralloc_ctx,
24047ec681f3Smrg                                           sizeof(struct dxil_named_node));
24057ec681f3Smrg   if (!n)
24067ec681f3Smrg      return false;
24077ec681f3Smrg
24087ec681f3Smrg   n->name = ralloc_strdup(n, name);
24097ec681f3Smrg   if (!n->name)
24107ec681f3Smrg      return false;
24117ec681f3Smrg
24127ec681f3Smrg   void *tmp = ralloc_array(n, struct dxil_mdnode *, num_subnodes);
24137ec681f3Smrg   if (!tmp)
24147ec681f3Smrg      return false;
24157ec681f3Smrg
24167ec681f3Smrg   memcpy(tmp, subnodes, sizeof(struct dxil_mdnode *) * num_subnodes);
24177ec681f3Smrg   n->subnodes = tmp;
24187ec681f3Smrg   n->num_subnodes = num_subnodes;
24197ec681f3Smrg
24207ec681f3Smrg   list_addtail(&n->head, &m->md_named_node_list);
24217ec681f3Smrg   return true;
24227ec681f3Smrg}
24237ec681f3Smrg
24247ec681f3Smrgstatic bool
24257ec681f3Smrgemit_metadata_value(struct dxil_module *m, const struct dxil_type *type,
24267ec681f3Smrg                    const struct dxil_value *value)
24277ec681f3Smrg{
24287ec681f3Smrg   assert(type->id >= 0 && value->id >= 0);
24297ec681f3Smrg   uint64_t data[2] = { type->id, value->id };
24307ec681f3Smrg   return emit_record(m, METADATA_VALUE, data, ARRAY_SIZE(data));
24317ec681f3Smrg}
24327ec681f3Smrg
24337ec681f3Smrgstatic bool
24347ec681f3Smrgemit_metadata_abbrev_record(struct dxil_module *m,
24357ec681f3Smrg                            enum metadata_abbrev_id abbrev,
24367ec681f3Smrg                            const uint64_t *data, size_t size)
24377ec681f3Smrg{
24387ec681f3Smrg   assert(abbrev < ARRAY_SIZE(metadata_abbrevs));
24397ec681f3Smrg   return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,
24407ec681f3Smrg                             metadata_abbrevs + abbrev, data, size);
24417ec681f3Smrg}
24427ec681f3Smrg
24437ec681f3Smrgstatic bool
24447ec681f3Smrgemit_metadata_string(struct dxil_module *m, const char *str)
24457ec681f3Smrg{
24467ec681f3Smrg   uint64_t data[256];
24477ec681f3Smrg   assert(strlen(str) < ARRAY_SIZE(data) - 1);
24487ec681f3Smrg   data[0] = METADATA_STRING;
24497ec681f3Smrg   for (size_t i = 0; i < strlen(str); ++i)
24507ec681f3Smrg      data[i + 1] = str[i];
24517ec681f3Smrg
24527ec681f3Smrg   return emit_metadata_abbrev_record(m, METADATA_ABBREV_STRING,
24537ec681f3Smrg                                      data, strlen(str) + 1);
24547ec681f3Smrg}
24557ec681f3Smrg
24567ec681f3Smrgstatic bool
24577ec681f3Smrgemit_metadata_node(struct dxil_module *m,
24587ec681f3Smrg                   const struct dxil_mdnode *subnodes[],
24597ec681f3Smrg                   size_t num_subnodes)
24607ec681f3Smrg{
24617ec681f3Smrg   uint64_t data[256];
24627ec681f3Smrg   assert(num_subnodes < ARRAY_SIZE(data));
24637ec681f3Smrg   for (size_t i = 0; i < num_subnodes; ++i)
24647ec681f3Smrg      data[i] = subnodes[i] ? subnodes[i]->id : 0;
24657ec681f3Smrg
24667ec681f3Smrg   return emit_record(m, METADATA_NODE, data, num_subnodes);
24677ec681f3Smrg}
24687ec681f3Smrg
24697ec681f3Smrgstatic bool
24707ec681f3Smrgemit_mdnode(struct dxil_module *m, struct dxil_mdnode *n)
24717ec681f3Smrg{
24727ec681f3Smrg   switch (n->type) {
24737ec681f3Smrg   case MD_STRING:
24747ec681f3Smrg      return emit_metadata_string(m, n->string);
24757ec681f3Smrg
24767ec681f3Smrg   case MD_VALUE:
24777ec681f3Smrg      return emit_metadata_value(m, n->value.type, n->value.value);
24787ec681f3Smrg
24797ec681f3Smrg   case MD_NODE:
24807ec681f3Smrg      return emit_metadata_node(m, n->node.subnodes, n->node.num_subnodes);
24817ec681f3Smrg
24827ec681f3Smrg   default:
24837ec681f3Smrg      unreachable("unexpected n->type");
24847ec681f3Smrg   }
24857ec681f3Smrg}
24867ec681f3Smrg
24877ec681f3Smrgstatic bool
24887ec681f3Smrgemit_metadata_nodes(struct dxil_module *m)
24897ec681f3Smrg{
24907ec681f3Smrg   list_for_each_entry(struct dxil_mdnode, n,  &m->mdnode_list, head) {
24917ec681f3Smrg      if (!emit_mdnode(m, n))
24927ec681f3Smrg         return false;
24937ec681f3Smrg   }
24947ec681f3Smrg   return true;
24957ec681f3Smrg}
24967ec681f3Smrg
24977ec681f3Smrgstatic bool
24987ec681f3Smrgemit_metadata_name(struct dxil_module *m, const char *name)
24997ec681f3Smrg{
25007ec681f3Smrg   uint64_t data[256];
25017ec681f3Smrg   assert(strlen(name) < ARRAY_SIZE(data) - 1);
25027ec681f3Smrg   data[0] = METADATA_NAME;
25037ec681f3Smrg   for (size_t i = 0; i < strlen(name); ++i)
25047ec681f3Smrg      data[i + 1] = name[i];
25057ec681f3Smrg
25067ec681f3Smrg   return emit_metadata_abbrev_record(m, METADATA_ABBREV_NAME,
25077ec681f3Smrg                                      data, strlen(name) + 1);
25087ec681f3Smrg}
25097ec681f3Smrg
25107ec681f3Smrgstatic bool
25117ec681f3Smrgemit_metadata_named_node(struct dxil_module *m, const char *name,
25127ec681f3Smrg                         const struct dxil_mdnode *subnodes[],
25137ec681f3Smrg                         size_t num_subnodes)
25147ec681f3Smrg{
25157ec681f3Smrg   uint64_t data[256];
25167ec681f3Smrg   assert(num_subnodes < ARRAY_SIZE(data));
25177ec681f3Smrg   for (size_t i = 0; i < num_subnodes; ++i) {
25187ec681f3Smrg      assert(subnodes[i]->id > 0); /* NULL nodes not allowed */
25197ec681f3Smrg      data[i] = subnodes[i]->id - 1;
25207ec681f3Smrg   }
25217ec681f3Smrg
25227ec681f3Smrg   return emit_metadata_name(m, name) &&
25237ec681f3Smrg          emit_record(m, METADATA_NAMED_NODE, data, num_subnodes);
25247ec681f3Smrg}
25257ec681f3Smrg
25267ec681f3Smrgstatic bool
25277ec681f3Smrgemit_metadata_named_nodes(struct dxil_module *m)
25287ec681f3Smrg{
25297ec681f3Smrg   struct dxil_named_node *n;
25307ec681f3Smrg   LIST_FOR_EACH_ENTRY(n, &m->md_named_node_list, head) {
25317ec681f3Smrg      if (!emit_metadata_named_node(m, n->name, n->subnodes,
25327ec681f3Smrg                                    n->num_subnodes))
25337ec681f3Smrg         return false;
25347ec681f3Smrg   }
25357ec681f3Smrg   return true;
25367ec681f3Smrg}
25377ec681f3Smrg
25387ec681f3Smrgstatic bool
25397ec681f3Smrgemit_metadata(struct dxil_module *m)
25407ec681f3Smrg{
25417ec681f3Smrg   return enter_subblock(m, DXIL_METADATA_BLOCK, 3) &&
25427ec681f3Smrg          emit_metadata_abbrevs(m) &&
25437ec681f3Smrg          emit_metadata_nodes(m) &&
25447ec681f3Smrg          emit_metadata_named_nodes(m) &&
25457ec681f3Smrg          exit_block(m);
25467ec681f3Smrg}
25477ec681f3Smrg
25487ec681f3Smrgstatic struct dxil_instr *
25497ec681f3Smrgcreate_instr(struct dxil_module *m, enum instr_type type,
25507ec681f3Smrg             const struct dxil_type *ret_type)
25517ec681f3Smrg{
25527ec681f3Smrg   struct dxil_instr *ret = ralloc_size(m->ralloc_ctx,
25537ec681f3Smrg                                        sizeof(struct dxil_instr));
25547ec681f3Smrg   if (ret) {
25557ec681f3Smrg      ret->type = type;
25567ec681f3Smrg      ret->value.id = -1;
25577ec681f3Smrg      ret->value.type = ret_type;
25587ec681f3Smrg      ret->has_value = false;
25597ec681f3Smrg      list_addtail(&ret->head, &m->instr_list);
25607ec681f3Smrg   }
25617ec681f3Smrg   return ret;
25627ec681f3Smrg}
25637ec681f3Smrg
25647ec681f3Smrgstatic inline bool
25657ec681f3Smrglegal_arith_type(const struct dxil_type *type)
25667ec681f3Smrg{
25677ec681f3Smrg   switch (type->type) {
25687ec681f3Smrg   case TYPE_INTEGER:
25697ec681f3Smrg      return type->int_bits == 1 ||
25707ec681f3Smrg             type->int_bits == 16 ||
25717ec681f3Smrg             type->int_bits == 32 ||
25727ec681f3Smrg             type->int_bits == 64;
25737ec681f3Smrg
25747ec681f3Smrg   case TYPE_FLOAT:
25757ec681f3Smrg      return type->float_bits == 16 ||
25767ec681f3Smrg             type->float_bits == 32 ||
25777ec681f3Smrg             type->float_bits == 64;
25787ec681f3Smrg
25797ec681f3Smrg   default:
25807ec681f3Smrg      return false;
25817ec681f3Smrg   }
25827ec681f3Smrg}
25837ec681f3Smrg
25847ec681f3Smrgconst struct dxil_value *
25857ec681f3Smrgdxil_emit_binop(struct dxil_module *m, enum dxil_bin_opcode opcode,
25867ec681f3Smrg                const struct dxil_value *op0, const struct dxil_value *op1,
25877ec681f3Smrg                enum dxil_opt_flags flags)
25887ec681f3Smrg{
25897ec681f3Smrg   assert(types_equal(op0->type, op1->type));
25907ec681f3Smrg   assert(legal_arith_type(op0->type));
25917ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_BINOP, op0->type);
25927ec681f3Smrg   if (!instr)
25937ec681f3Smrg      return NULL;
25947ec681f3Smrg
25957ec681f3Smrg   instr->binop.opcode = opcode;
25967ec681f3Smrg   instr->binop.operands[0] = op0;
25977ec681f3Smrg   instr->binop.operands[1] = op1;
25987ec681f3Smrg   instr->binop.flags = flags;
25997ec681f3Smrg   instr->has_value = true;
26007ec681f3Smrg   return &instr->value;
26017ec681f3Smrg}
26027ec681f3Smrg
26037ec681f3Smrgconst struct dxil_value *
26047ec681f3Smrgdxil_emit_cmp(struct dxil_module *m, enum dxil_cmp_pred pred,
26057ec681f3Smrg                const struct dxil_value *op0, const struct dxil_value *op1)
26067ec681f3Smrg{
26077ec681f3Smrg   assert(types_equal(op0->type, op1->type));
26087ec681f3Smrg   assert(legal_arith_type(op0->type));
26097ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_CMP, get_int1_type(m));
26107ec681f3Smrg   if (!instr)
26117ec681f3Smrg      return NULL;
26127ec681f3Smrg
26137ec681f3Smrg   instr->cmp.pred = pred;
26147ec681f3Smrg   instr->cmp.operands[0] = op0;
26157ec681f3Smrg   instr->cmp.operands[1] = op1;
26167ec681f3Smrg   instr->has_value = true;
26177ec681f3Smrg   return &instr->value;
26187ec681f3Smrg}
26197ec681f3Smrg
26207ec681f3Smrgconst struct dxil_value *
26217ec681f3Smrgdxil_emit_select(struct dxil_module *m,
26227ec681f3Smrg                const struct dxil_value *op0,
26237ec681f3Smrg                const struct dxil_value *op1,
26247ec681f3Smrg                const struct dxil_value *op2)
26257ec681f3Smrg{
26267ec681f3Smrg   assert(types_equal(op0->type, get_int1_type(m)));
26277ec681f3Smrg   assert(types_equal(op1->type, op2->type));
26287ec681f3Smrg   assert(legal_arith_type(op1->type));
26297ec681f3Smrg
26307ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_SELECT, op1->type);
26317ec681f3Smrg   if (!instr)
26327ec681f3Smrg      return NULL;
26337ec681f3Smrg
26347ec681f3Smrg   instr->select.operands[0] = op0;
26357ec681f3Smrg   instr->select.operands[1] = op1;
26367ec681f3Smrg   instr->select.operands[2] = op2;
26377ec681f3Smrg   instr->has_value = true;
26387ec681f3Smrg   return &instr->value;
26397ec681f3Smrg}
26407ec681f3Smrg
26417ec681f3Smrgconst struct dxil_value *
26427ec681f3Smrgdxil_emit_cast(struct dxil_module *m, enum dxil_cast_opcode opcode,
26437ec681f3Smrg               const struct dxil_type *type,
26447ec681f3Smrg               const struct dxil_value *value)
26457ec681f3Smrg{
26467ec681f3Smrg   assert(legal_arith_type(value->type));
26477ec681f3Smrg   assert(legal_arith_type(type));
26487ec681f3Smrg
26497ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_CAST, type);
26507ec681f3Smrg   if (!instr)
26517ec681f3Smrg      return NULL;
26527ec681f3Smrg
26537ec681f3Smrg   instr->cast.opcode = opcode;
26547ec681f3Smrg   instr->cast.type = type;
26557ec681f3Smrg   instr->cast.value = value;
26567ec681f3Smrg   instr->has_value = true;
26577ec681f3Smrg   return &instr->value;
26587ec681f3Smrg}
26597ec681f3Smrg
26607ec681f3Smrgbool
26617ec681f3Smrgdxil_emit_branch(struct dxil_module *m, const struct dxil_value *cond,
26627ec681f3Smrg                 unsigned true_block, unsigned false_block)
26637ec681f3Smrg{
26647ec681f3Smrg   assert(!cond || types_equal(cond->type, get_int1_type(m)));
26657ec681f3Smrg
26667ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_BR,
26677ec681f3Smrg                                           dxil_module_get_void_type(m));
26687ec681f3Smrg   if (!instr)
26697ec681f3Smrg      return false;
26707ec681f3Smrg
26717ec681f3Smrg   instr->br.cond = cond;
26727ec681f3Smrg   instr->br.succ[0] = true_block;
26737ec681f3Smrg   instr->br.succ[1] = false_block;
26747ec681f3Smrg   m->curr_block++;
26757ec681f3Smrg   return true;
26767ec681f3Smrg}
26777ec681f3Smrg
26787ec681f3Smrgconst struct dxil_value *
26797ec681f3Smrgdxil_instr_get_return_value(struct dxil_instr *instr)
26807ec681f3Smrg{
26817ec681f3Smrg   return instr->has_value ? &instr->value : NULL;
26827ec681f3Smrg}
26837ec681f3Smrg
26847ec681f3Smrgstruct dxil_instr *
26857ec681f3Smrgdxil_emit_phi(struct dxil_module *m, const struct dxil_type *type)
26867ec681f3Smrg{
26877ec681f3Smrg   assert(legal_arith_type(type));
26887ec681f3Smrg
26897ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_PHI, type);
26907ec681f3Smrg   if (!instr)
26917ec681f3Smrg      return NULL;
26927ec681f3Smrg
26937ec681f3Smrg   instr->phi.type = type;
26947ec681f3Smrg   instr->phi.num_incoming = 0;
26957ec681f3Smrg   instr->has_value = true;
26967ec681f3Smrg
26977ec681f3Smrg   return instr;
26987ec681f3Smrg}
26997ec681f3Smrg
27007ec681f3Smrgvoid
27017ec681f3Smrgdxil_phi_set_incoming(struct dxil_instr *instr,
27027ec681f3Smrg                      const struct dxil_value *incoming_values[],
27037ec681f3Smrg                      const unsigned incoming_blocks[],
27047ec681f3Smrg                      size_t num_incoming)
27057ec681f3Smrg{
27067ec681f3Smrg   assert(instr->type == INSTR_PHI);
27077ec681f3Smrg   assert(num_incoming > 0);
27087ec681f3Smrg   assert(num_incoming < ARRAY_SIZE(instr->phi.incoming));
27097ec681f3Smrg   for (int i = 0; i < num_incoming; ++i) {
27107ec681f3Smrg      assert(incoming_values[i]);
27117ec681f3Smrg      assert(types_equal(incoming_values[i]->type, instr->phi.type));
27127ec681f3Smrg
27137ec681f3Smrg      instr->phi.incoming[i].value = incoming_values[i];
27147ec681f3Smrg      instr->phi.incoming[i].block = incoming_blocks[i];
27157ec681f3Smrg   }
27167ec681f3Smrg   instr->phi.num_incoming = num_incoming;
27177ec681f3Smrg}
27187ec681f3Smrg
27197ec681f3Smrgstatic struct dxil_instr *
27207ec681f3Smrgcreate_call_instr(struct dxil_module *m,
27217ec681f3Smrg                  const struct dxil_func *func,
27227ec681f3Smrg                  const struct dxil_value **args, size_t num_args)
27237ec681f3Smrg{
27247ec681f3Smrg   assert(num_args == func->type->function_def.args.num_types);
27257ec681f3Smrg   for (size_t i = 0; i < num_args; ++ i)
27267ec681f3Smrg      assert(types_equal(func->type->function_def.args.types[i], args[i]->type));
27277ec681f3Smrg
27287ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_CALL,
27297ec681f3Smrg                                           func->type->function_def.ret_type);
27307ec681f3Smrg   if (instr) {
27317ec681f3Smrg      instr->call.func = func;
27327ec681f3Smrg      instr->call.args = ralloc_array(instr, struct dxil_value *, num_args);
27337ec681f3Smrg      if (!args)
27347ec681f3Smrg         return false;
27357ec681f3Smrg      memcpy(instr->call.args, args, sizeof(struct dxil_value *) * num_args);
27367ec681f3Smrg      instr->call.num_args = num_args;
27377ec681f3Smrg   }
27387ec681f3Smrg   return instr;
27397ec681f3Smrg}
27407ec681f3Smrg
27417ec681f3Smrgconst struct dxil_value *
27427ec681f3Smrgdxil_emit_call(struct dxil_module *m,
27437ec681f3Smrg               const struct dxil_func *func,
27447ec681f3Smrg               const struct dxil_value **args, size_t num_args)
27457ec681f3Smrg{
27467ec681f3Smrg   assert(func->type->function_def.ret_type->type != TYPE_VOID);
27477ec681f3Smrg
27487ec681f3Smrg   struct dxil_instr *instr = create_call_instr(m, func, args, num_args);
27497ec681f3Smrg   if (!instr)
27507ec681f3Smrg      return NULL;
27517ec681f3Smrg
27527ec681f3Smrg   instr->has_value = true;
27537ec681f3Smrg   return &instr->value;
27547ec681f3Smrg}
27557ec681f3Smrg
27567ec681f3Smrgbool
27577ec681f3Smrgdxil_emit_call_void(struct dxil_module *m,
27587ec681f3Smrg                    const struct dxil_func *func,
27597ec681f3Smrg                    const struct dxil_value **args, size_t num_args)
27607ec681f3Smrg{
27617ec681f3Smrg   assert(func->type->function_def.ret_type->type == TYPE_VOID);
27627ec681f3Smrg
27637ec681f3Smrg   struct dxil_instr *instr = create_call_instr(m, func, args, num_args);
27647ec681f3Smrg   if (!instr)
27657ec681f3Smrg      return false;
27667ec681f3Smrg
27677ec681f3Smrg   return true;
27687ec681f3Smrg}
27697ec681f3Smrg
27707ec681f3Smrgbool
27717ec681f3Smrgdxil_emit_ret_void(struct dxil_module *m)
27727ec681f3Smrg{
27737ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_RET,
27747ec681f3Smrg                                           dxil_module_get_void_type(m));
27757ec681f3Smrg   if (!instr)
27767ec681f3Smrg      return false;
27777ec681f3Smrg
27787ec681f3Smrg   instr->ret.value = NULL;
27797ec681f3Smrg   m->curr_block++;
27807ec681f3Smrg   return true;
27817ec681f3Smrg}
27827ec681f3Smrg
27837ec681f3Smrgconst struct dxil_value *
27847ec681f3Smrgdxil_emit_extractval(struct dxil_module *m, const struct dxil_value *src,
27857ec681f3Smrg                     const unsigned int index)
27867ec681f3Smrg{
27877ec681f3Smrg   assert(src->type->type == TYPE_STRUCT);
27887ec681f3Smrg   assert(index < src->type->struct_def.elem.num_types);
27897ec681f3Smrg
27907ec681f3Smrg   struct dxil_instr *instr =
27917ec681f3Smrg      create_instr(m, INSTR_EXTRACTVAL,
27927ec681f3Smrg                   src->type->struct_def.elem.types[index]);
27937ec681f3Smrg   if (!instr)
27947ec681f3Smrg      return NULL;
27957ec681f3Smrg
27967ec681f3Smrg   instr->extractval.src = src;
27977ec681f3Smrg   instr->extractval.type = src->type;
27987ec681f3Smrg   instr->extractval.idx = index;
27997ec681f3Smrg   instr->has_value = true;
28007ec681f3Smrg
28017ec681f3Smrg   return &instr->value;
28027ec681f3Smrg}
28037ec681f3Smrg
28047ec681f3Smrgconst struct dxil_value *
28057ec681f3Smrgdxil_emit_alloca(struct dxil_module *m, const struct dxil_type *alloc_type,
28067ec681f3Smrg                 const struct dxil_type *size_type,
28077ec681f3Smrg                 const struct dxil_value *size,
28087ec681f3Smrg                 unsigned int align)
28097ec681f3Smrg{
28107ec681f3Smrg   assert(size_type && size_type->type == TYPE_INTEGER);
28117ec681f3Smrg
28127ec681f3Smrg   const struct dxil_type *return_type =
28137ec681f3Smrg      dxil_module_get_pointer_type(m, alloc_type);
28147ec681f3Smrg   if (!return_type)
28157ec681f3Smrg      return NULL;
28167ec681f3Smrg
28177ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_ALLOCA, return_type);
28187ec681f3Smrg   if (!instr)
28197ec681f3Smrg      return NULL;
28207ec681f3Smrg
28217ec681f3Smrg   instr->alloca.alloc_type = alloc_type;
28227ec681f3Smrg   instr->alloca.size_type = size_type;
28237ec681f3Smrg   instr->alloca.size = size;
28247ec681f3Smrg   instr->alloca.align = util_logbase2(align) + 1;
28257ec681f3Smrg   assert(instr->alloca.align < (1 << 5));
28267ec681f3Smrg   instr->alloca.align |= 1 << 6;
28277ec681f3Smrg
28287ec681f3Smrg   instr->has_value = true;
28297ec681f3Smrg   return &instr->value;
28307ec681f3Smrg}
28317ec681f3Smrg
28327ec681f3Smrgstatic const struct dxil_type *
28337ec681f3Smrgget_deref_type(const struct dxil_type *type)
28347ec681f3Smrg{
28357ec681f3Smrg   switch (type->type) {
28367ec681f3Smrg   case TYPE_POINTER: return type->ptr_target_type;
28377ec681f3Smrg   case TYPE_ARRAY: return type->array_or_vector_def.elem_type;
28387ec681f3Smrg   default: unreachable("unexpected type");
28397ec681f3Smrg   }
28407ec681f3Smrg}
28417ec681f3Smrg
28427ec681f3Smrgconst struct dxil_value *
28437ec681f3Smrgdxil_emit_gep_inbounds(struct dxil_module *m,
28447ec681f3Smrg                       const struct dxil_value **operands,
28457ec681f3Smrg                       size_t num_operands)
28467ec681f3Smrg{
28477ec681f3Smrg   assert(num_operands > 0);
28487ec681f3Smrg   const struct dxil_type *source_elem_type =
28497ec681f3Smrg      get_deref_type(operands[0]->type);
28507ec681f3Smrg
28517ec681f3Smrg   const struct dxil_type *type = operands[0]->type;
28527ec681f3Smrg   for (int i = 1; i < num_operands; ++i) {
28537ec681f3Smrg      assert(operands[i]->type == get_int32_type(m));
28547ec681f3Smrg      type = get_deref_type(type);
28557ec681f3Smrg   }
28567ec681f3Smrg
28577ec681f3Smrg   type = dxil_module_get_pointer_type(m, type);
28587ec681f3Smrg   if (!type)
28597ec681f3Smrg      return NULL;
28607ec681f3Smrg
28617ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_GEP, type);
28627ec681f3Smrg   if (!instr)
28637ec681f3Smrg      return NULL;
28647ec681f3Smrg
28657ec681f3Smrg   instr->gep.operands = ralloc_array(instr, struct dxil_value *,
28667ec681f3Smrg                                      num_operands);
28677ec681f3Smrg   if (!instr->gep.operands)
28687ec681f3Smrg      return NULL;
28697ec681f3Smrg
28707ec681f3Smrg   instr->gep.source_elem_type = source_elem_type;
28717ec681f3Smrg   memcpy(instr->gep.operands, operands,
28727ec681f3Smrg          sizeof(struct dxil_value *) * num_operands);
28737ec681f3Smrg   instr->gep.num_operands = num_operands;
28747ec681f3Smrg   instr->gep.inbounds = true;
28757ec681f3Smrg
28767ec681f3Smrg   instr->has_value = true;
28777ec681f3Smrg   return &instr->value;
28787ec681f3Smrg}
28797ec681f3Smrg
28807ec681f3Smrgconst struct dxil_value *
28817ec681f3Smrgdxil_emit_load(struct dxil_module *m, const struct dxil_value *ptr,
28827ec681f3Smrg               unsigned align,
28837ec681f3Smrg               bool is_volatile)
28847ec681f3Smrg{
28857ec681f3Smrg   assert(ptr->type->type == TYPE_POINTER ||
28867ec681f3Smrg          ptr->type->type == TYPE_ARRAY);
28877ec681f3Smrg   const struct dxil_type *type = ptr->type->type == TYPE_POINTER ?
28887ec681f3Smrg      ptr->type->ptr_target_type :
28897ec681f3Smrg      ptr->type->array_or_vector_def.elem_type;
28907ec681f3Smrg
28917ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_LOAD, type);
28927ec681f3Smrg   if (!instr)
28937ec681f3Smrg      return false;
28947ec681f3Smrg
28957ec681f3Smrg   instr->load.ptr = ptr;
28967ec681f3Smrg   instr->load.type = type;
28977ec681f3Smrg   instr->load.align = util_logbase2(align) + 1;
28987ec681f3Smrg   instr->load.is_volatile = is_volatile;
28997ec681f3Smrg
29007ec681f3Smrg   instr->has_value = true;
29017ec681f3Smrg   return &instr->value;
29027ec681f3Smrg}
29037ec681f3Smrg
29047ec681f3Smrgbool
29057ec681f3Smrgdxil_emit_store(struct dxil_module *m, const struct dxil_value *value,
29067ec681f3Smrg                const struct dxil_value *ptr, unsigned align,
29077ec681f3Smrg                bool is_volatile)
29087ec681f3Smrg{
29097ec681f3Smrg   assert(legal_arith_type(value->type));
29107ec681f3Smrg
29117ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_STORE,
29127ec681f3Smrg                                           dxil_module_get_void_type(m));
29137ec681f3Smrg   if (!instr)
29147ec681f3Smrg      return false;
29157ec681f3Smrg
29167ec681f3Smrg   instr->store.value = value;
29177ec681f3Smrg   instr->store.ptr = ptr;
29187ec681f3Smrg   instr->store.align = util_logbase2(align) + 1;
29197ec681f3Smrg   instr->store.is_volatile = is_volatile;
29207ec681f3Smrg   return true;
29217ec681f3Smrg}
29227ec681f3Smrg
29237ec681f3Smrgconst struct dxil_value *
29247ec681f3Smrgdxil_emit_cmpxchg(struct dxil_module *m, const struct dxil_value *cmpval,
29257ec681f3Smrg                  const struct dxil_value *newval,
29267ec681f3Smrg                  const struct dxil_value *ptr, bool is_volatile,
29277ec681f3Smrg                  enum dxil_atomic_ordering ordering,
29287ec681f3Smrg                  enum dxil_sync_scope syncscope)
29297ec681f3Smrg{
29307ec681f3Smrg   assert(ptr->type->type == TYPE_POINTER);
29317ec681f3Smrg
29327ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_CMPXCHG,
29337ec681f3Smrg                                           ptr->type->ptr_target_type);
29347ec681f3Smrg   if (!instr)
29357ec681f3Smrg      return false;
29367ec681f3Smrg
29377ec681f3Smrg   instr->cmpxchg.cmpval = cmpval;
29387ec681f3Smrg   instr->cmpxchg.newval = newval;
29397ec681f3Smrg   instr->cmpxchg.ptr = ptr;
29407ec681f3Smrg   instr->cmpxchg.is_volatile = is_volatile;
29417ec681f3Smrg   instr->cmpxchg.ordering = ordering;
29427ec681f3Smrg   instr->cmpxchg.syncscope = syncscope;
29437ec681f3Smrg
29447ec681f3Smrg   instr->has_value = true;
29457ec681f3Smrg   return &instr->value;
29467ec681f3Smrg}
29477ec681f3Smrg
29487ec681f3Smrgconst struct dxil_value *
29497ec681f3Smrgdxil_emit_atomicrmw(struct dxil_module *m, const struct dxil_value *value,
29507ec681f3Smrg                    const struct dxil_value *ptr, enum dxil_rmw_op op,
29517ec681f3Smrg                    bool is_volatile, enum dxil_atomic_ordering ordering,
29527ec681f3Smrg                    enum dxil_sync_scope syncscope)
29537ec681f3Smrg{
29547ec681f3Smrg   assert(ptr->type->type == TYPE_POINTER);
29557ec681f3Smrg
29567ec681f3Smrg   struct dxil_instr *instr = create_instr(m, INSTR_ATOMICRMW,
29577ec681f3Smrg                                           ptr->type->ptr_target_type);
29587ec681f3Smrg   if (!instr)
29597ec681f3Smrg      return false;
29607ec681f3Smrg
29617ec681f3Smrg   instr->atomicrmw.value = value;
29627ec681f3Smrg   instr->atomicrmw.ptr = ptr;
29637ec681f3Smrg   instr->atomicrmw.op = op;
29647ec681f3Smrg   instr->atomicrmw.is_volatile = is_volatile;
29657ec681f3Smrg   instr->atomicrmw.ordering = ordering;
29667ec681f3Smrg   instr->atomicrmw.syncscope = syncscope;
29677ec681f3Smrg
29687ec681f3Smrg   instr->has_value = true;
29697ec681f3Smrg   return &instr->value;
29707ec681f3Smrg}
29717ec681f3Smrg
29727ec681f3Smrgstatic bool
29737ec681f3Smrgemit_binop(struct dxil_module *m, struct dxil_instr *instr)
29747ec681f3Smrg{
29757ec681f3Smrg   assert(instr->type == INSTR_BINOP);
29767ec681f3Smrg   assert(instr->value.id > instr->binop.operands[0]->id);
29777ec681f3Smrg   assert(instr->value.id > instr->binop.operands[1]->id);
29787ec681f3Smrg
29797ec681f3Smrg   if (instr->binop.flags) {
29807ec681f3Smrg      uint64_t data[] = {
29817ec681f3Smrg         FUNC_CODE_INST_BINOP,
29827ec681f3Smrg         instr->value.id - instr->binop.operands[0]->id,
29837ec681f3Smrg         instr->value.id - instr->binop.operands[1]->id,
29847ec681f3Smrg         instr->binop.opcode,
29857ec681f3Smrg         instr->binop.flags
29867ec681f3Smrg      };
29877ec681f3Smrg      return emit_func_abbrev_record(m, FUNC_ABBREV_BINOP_FLAGS,
29887ec681f3Smrg                                     data, ARRAY_SIZE(data));
29897ec681f3Smrg   }
29907ec681f3Smrg   uint64_t data[] = {
29917ec681f3Smrg      FUNC_CODE_INST_BINOP,
29927ec681f3Smrg      instr->value.id - instr->binop.operands[0]->id,
29937ec681f3Smrg      instr->value.id - instr->binop.operands[1]->id,
29947ec681f3Smrg      instr->binop.opcode
29957ec681f3Smrg   };
29967ec681f3Smrg   return emit_func_abbrev_record(m, FUNC_ABBREV_BINOP,
29977ec681f3Smrg                                  data, ARRAY_SIZE(data));
29987ec681f3Smrg}
29997ec681f3Smrg
30007ec681f3Smrgstatic bool
30017ec681f3Smrgemit_cmp(struct dxil_module *m, struct dxil_instr *instr)
30027ec681f3Smrg{
30037ec681f3Smrg   assert(instr->type == INSTR_CMP);
30047ec681f3Smrg   assert(instr->value.id > instr->cmp.operands[0]->id);
30057ec681f3Smrg   assert(instr->value.id > instr->cmp.operands[1]->id);
30067ec681f3Smrg   uint64_t data[] = {
30077ec681f3Smrg      instr->value.id - instr->cmp.operands[0]->id,
30087ec681f3Smrg      instr->value.id - instr->cmp.operands[1]->id,
30097ec681f3Smrg      instr->cmp.pred
30107ec681f3Smrg   };
30117ec681f3Smrg   return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_CMP2,
30127ec681f3Smrg                                data, ARRAY_SIZE(data));
30137ec681f3Smrg}
30147ec681f3Smrg
30157ec681f3Smrgstatic bool
30167ec681f3Smrgemit_select(struct dxil_module *m, struct dxil_instr *instr)
30177ec681f3Smrg{
30187ec681f3Smrg   assert(instr->type == INSTR_SELECT);
30197ec681f3Smrg   assert(instr->value.id > instr->select.operands[0]->id);
30207ec681f3Smrg   assert(instr->value.id > instr->select.operands[1]->id);
30217ec681f3Smrg   assert(instr->value.id > instr->select.operands[2]->id);
30227ec681f3Smrg   uint64_t data[] = {
30237ec681f3Smrg      instr->value.id - instr->select.operands[1]->id,
30247ec681f3Smrg      instr->value.id - instr->select.operands[2]->id,
30257ec681f3Smrg      instr->value.id - instr->select.operands[0]->id
30267ec681f3Smrg   };
30277ec681f3Smrg   return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_VSELECT,
30287ec681f3Smrg                                data, ARRAY_SIZE(data));
30297ec681f3Smrg}
30307ec681f3Smrg
30317ec681f3Smrgstatic bool
30327ec681f3Smrgemit_cast(struct dxil_module *m, struct dxil_instr *instr)
30337ec681f3Smrg{
30347ec681f3Smrg   assert(instr->type == INSTR_CAST);
30357ec681f3Smrg   assert(instr->value.id > instr->cast.value->id);
30367ec681f3Smrg   uint64_t data[] = {
30377ec681f3Smrg      FUNC_CODE_INST_CAST,
30387ec681f3Smrg      instr->value.id - instr->cast.value->id,
30397ec681f3Smrg      instr->cast.type->id,
30407ec681f3Smrg      instr->cast.opcode
30417ec681f3Smrg   };
30427ec681f3Smrg   return emit_func_abbrev_record(m, FUNC_ABBREV_CAST,
30437ec681f3Smrg                                  data, ARRAY_SIZE(data));
30447ec681f3Smrg}
30457ec681f3Smrg
30467ec681f3Smrgstatic bool
30477ec681f3Smrgemit_branch(struct dxil_module *m, struct dxil_instr *instr)
30487ec681f3Smrg{
30497ec681f3Smrg   assert(instr->type == INSTR_BR);
30507ec681f3Smrg   assert(instr->br.succ[0] < m->num_basic_block_ids);
30517ec681f3Smrg   assert(m->basic_block_ids[instr->br.succ[0]] >= 0);
30527ec681f3Smrg
30537ec681f3Smrg   if (!instr->br.cond) {
30547ec681f3Smrg      /* unconditional branch */
30557ec681f3Smrg      uint64_t succ = m->basic_block_ids[instr->br.succ[0]];
30567ec681f3Smrg      return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_BR, &succ, 1);
30577ec681f3Smrg   }
30587ec681f3Smrg   /* conditional branch */
30597ec681f3Smrg   assert(instr->value.id > instr->br.cond->id);
30607ec681f3Smrg   assert(instr->br.succ[1] < m->num_basic_block_ids);
30617ec681f3Smrg   assert(m->basic_block_ids[instr->br.succ[1]] >= 0);
30627ec681f3Smrg
30637ec681f3Smrg   uint64_t data[] = {
30647ec681f3Smrg      m->basic_block_ids[instr->br.succ[0]],
30657ec681f3Smrg      m->basic_block_ids[instr->br.succ[1]],
30667ec681f3Smrg      instr->value.id - instr->br.cond->id
30677ec681f3Smrg   };
30687ec681f3Smrg   return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_BR,
30697ec681f3Smrg                                data, ARRAY_SIZE(data));
30707ec681f3Smrg}
30717ec681f3Smrg
30727ec681f3Smrgstatic bool
30737ec681f3Smrgemit_phi(struct dxil_module *m, struct dxil_instr *instr)
30747ec681f3Smrg{
30757ec681f3Smrg   assert(instr->type == INSTR_PHI);
30767ec681f3Smrg   uint64_t data[128];
30777ec681f3Smrg   data[0] = instr->phi.type->id;
30787ec681f3Smrg   assert(instr->phi.num_incoming > 0);
30797ec681f3Smrg   for (int i = 0; i < instr->phi.num_incoming; ++i) {
30807ec681f3Smrg      int64_t value_delta = instr->value.id - instr->phi.incoming[i].value->id;
30817ec681f3Smrg      data[1 + i * 2] = encode_signed(value_delta);
30827ec681f3Smrg      assert(instr->phi.incoming[i].block < m->num_basic_block_ids);
30837ec681f3Smrg      assert(m->basic_block_ids[instr->phi.incoming[i].block] >= 0);
30847ec681f3Smrg      data[1 + i * 2 + 1] = m->basic_block_ids[instr->phi.incoming[i].block];
30857ec681f3Smrg   }
30867ec681f3Smrg   return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_PHI,
30877ec681f3Smrg                                data, 1 + 2 * instr->phi.num_incoming);
30887ec681f3Smrg}
30897ec681f3Smrg
30907ec681f3Smrgstatic bool
30917ec681f3Smrgemit_extractval(struct dxil_module *m, struct dxil_instr *instr)
30927ec681f3Smrg{
30937ec681f3Smrg   assert(instr->type == INSTR_EXTRACTVAL);
30947ec681f3Smrg   assert(instr->value.id > instr->extractval.src->id);
30957ec681f3Smrg   assert(instr->value.id > instr->extractval.type->id);
30967ec681f3Smrg
30977ec681f3Smrg   /* relative value ID, followed by absolute type ID (only if
30987ec681f3Smrg    * forward-declared), followed by n indices */
30997ec681f3Smrg   uint64_t data[] = {
31007ec681f3Smrg      instr->value.id - instr->extractval.src->id,
31017ec681f3Smrg      instr->extractval.idx
31027ec681f3Smrg   };
31037ec681f3Smrg   return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_EXTRACTVAL,
31047ec681f3Smrg                                data, ARRAY_SIZE(data));
31057ec681f3Smrg}
31067ec681f3Smrg
31077ec681f3Smrgstatic bool
31087ec681f3Smrgemit_call(struct dxil_module *m, struct dxil_instr *instr)
31097ec681f3Smrg{
31107ec681f3Smrg   assert(instr->type == INSTR_CALL);
31117ec681f3Smrg   assert(instr->call.func->value.id >= 0 && instr->value.id >= 0);
31127ec681f3Smrg   assert(instr->call.func->type->id >= 0);
31137ec681f3Smrg   assert(instr->call.func->value.id <= instr->value.id);
31147ec681f3Smrg   int value_id_delta = instr->value.id - instr->call.func->value.id;
31157ec681f3Smrg
31167ec681f3Smrg   uint64_t data[256];
31177ec681f3Smrg   data[0] = 0; // attribute id
31187ec681f3Smrg   data[1] = 1 << 15; // calling convention etc
31197ec681f3Smrg   data[2] = instr->call.func->type->id;
31207ec681f3Smrg   data[3] = value_id_delta;
31217ec681f3Smrg
31227ec681f3Smrg   assert(instr->call.num_args < ARRAY_SIZE(data) - 4);
31237ec681f3Smrg   for (size_t i = 0; i < instr->call.num_args; ++i) {
31247ec681f3Smrg      assert(instr->call.args[i]->id >= 0);
31257ec681f3Smrg      data[4 + i] = instr->value.id - instr->call.args[i]->id;
31267ec681f3Smrg   }
31277ec681f3Smrg
31287ec681f3Smrg   return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_CALL,
31297ec681f3Smrg                                data, 4 + instr->call.num_args);
31307ec681f3Smrg}
31317ec681f3Smrg
31327ec681f3Smrgstatic bool
31337ec681f3Smrgemit_ret(struct dxil_module *m, struct dxil_instr *instr)
31347ec681f3Smrg{
31357ec681f3Smrg   assert(instr->type == INSTR_RET);
31367ec681f3Smrg
31377ec681f3Smrg   if (instr->ret.value) {
31387ec681f3Smrg      assert(instr->ret.value->id >= 0);
31397ec681f3Smrg      uint64_t data[] = { FUNC_CODE_INST_RET, instr->ret.value->id };
31407ec681f3Smrg      return emit_func_abbrev_record(m, FUNC_ABBREV_RET_VAL,
31417ec681f3Smrg                                     data, ARRAY_SIZE(data));
31427ec681f3Smrg   }
31437ec681f3Smrg
31447ec681f3Smrg   uint64_t data[] = { FUNC_CODE_INST_RET };
31457ec681f3Smrg   return emit_func_abbrev_record(m, FUNC_ABBREV_RET_VOID,
31467ec681f3Smrg                                  data, ARRAY_SIZE(data));
31477ec681f3Smrg}
31487ec681f3Smrg
31497ec681f3Smrgstatic bool
31507ec681f3Smrgemit_alloca(struct dxil_module *m, struct dxil_instr *instr)
31517ec681f3Smrg{
31527ec681f3Smrg   assert(instr->type == INSTR_ALLOCA);
31537ec681f3Smrg   assert(instr->alloca.alloc_type->id >= 0);
31547ec681f3Smrg   assert(instr->alloca.size_type->id >= 0);
31557ec681f3Smrg   assert(instr->alloca.size->id >= 0);
31567ec681f3Smrg
31577ec681f3Smrg   uint64_t data[] = {
31587ec681f3Smrg      instr->alloca.alloc_type->id,
31597ec681f3Smrg      instr->alloca.size_type->id,
31607ec681f3Smrg      instr->alloca.size->id,
31617ec681f3Smrg      instr->alloca.align,
31627ec681f3Smrg   };
31637ec681f3Smrg   return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_ALLOCA,
31647ec681f3Smrg                                data, ARRAY_SIZE(data));
31657ec681f3Smrg}
31667ec681f3Smrg
31677ec681f3Smrgstatic bool
31687ec681f3Smrgemit_gep(struct dxil_module *m, struct dxil_instr *instr)
31697ec681f3Smrg{
31707ec681f3Smrg   assert(instr->type == INSTR_GEP);
31717ec681f3Smrg   assert(instr->gep.source_elem_type->id >= 0);
31727ec681f3Smrg
31737ec681f3Smrg   uint64_t data[256];
31747ec681f3Smrg   data[0] = FUNC_CODE_INST_GEP;
31757ec681f3Smrg   data[1] = instr->gep.inbounds;
31767ec681f3Smrg   data[2] = instr->gep.source_elem_type->id;
31777ec681f3Smrg
31787ec681f3Smrg   assert(instr->gep.num_operands < ARRAY_SIZE(data) - 3);
31797ec681f3Smrg   for (int i = 0; i < instr->gep.num_operands; ++i) {
31807ec681f3Smrg      assert(instr->value.id > instr->gep.operands[i]->id);
31817ec681f3Smrg      data[3 + i] = instr->value.id - instr->gep.operands[i]->id;
31827ec681f3Smrg   }
31837ec681f3Smrg   return emit_func_abbrev_record(m, FUNC_ABBREV_GEP,
31847ec681f3Smrg                                  data, 3 + instr->gep.num_operands);
31857ec681f3Smrg}
31867ec681f3Smrg
31877ec681f3Smrgstatic bool
31887ec681f3Smrgemit_load(struct dxil_module *m, struct dxil_instr *instr)
31897ec681f3Smrg{
31907ec681f3Smrg   assert(instr->type == INSTR_LOAD);
31917ec681f3Smrg   assert(instr->value.id > instr->load.ptr->id);
31927ec681f3Smrg   assert(instr->load.type->id >= 0);
31937ec681f3Smrg
31947ec681f3Smrg   uint64_t data[] = {
31957ec681f3Smrg      instr->value.id - instr->load.ptr->id,
31967ec681f3Smrg      instr->load.type->id,
31977ec681f3Smrg      instr->load.align,
31987ec681f3Smrg      instr->load.is_volatile
31997ec681f3Smrg   };
32007ec681f3Smrg   return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_LOAD,
32017ec681f3Smrg                                data, ARRAY_SIZE(data));
32027ec681f3Smrg}
32037ec681f3Smrgstatic bool
32047ec681f3Smrgemit_store(struct dxil_module *m, struct dxil_instr *instr)
32057ec681f3Smrg{
32067ec681f3Smrg   assert(instr->type == INSTR_STORE);
32077ec681f3Smrg   assert(instr->value.id > instr->store.value->id);
32087ec681f3Smrg   assert(instr->value.id > instr->store.ptr->id);
32097ec681f3Smrg
32107ec681f3Smrg   uint64_t data[] = {
32117ec681f3Smrg      instr->value.id - instr->store.ptr->id,
32127ec681f3Smrg      instr->value.id - instr->store.value->id,
32137ec681f3Smrg      instr->store.align,
32147ec681f3Smrg      instr->store.is_volatile
32157ec681f3Smrg   };
32167ec681f3Smrg   return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_STORE,
32177ec681f3Smrg                                data, ARRAY_SIZE(data));
32187ec681f3Smrg}
32197ec681f3Smrg
32207ec681f3Smrgstatic bool
32217ec681f3Smrgemit_cmpxchg(struct dxil_module *m, struct dxil_instr *instr)
32227ec681f3Smrg{
32237ec681f3Smrg   assert(instr->type == INSTR_CMPXCHG);
32247ec681f3Smrg   assert(instr->value.id > instr->cmpxchg.cmpval->id);
32257ec681f3Smrg   assert(instr->value.id > instr->cmpxchg.newval->id);
32267ec681f3Smrg   assert(instr->value.id > instr->cmpxchg.ptr->id);
32277ec681f3Smrg   uint64_t data[] = {
32287ec681f3Smrg      instr->value.id - instr->cmpxchg.ptr->id,
32297ec681f3Smrg      instr->value.id - instr->cmpxchg.cmpval->id,
32307ec681f3Smrg      instr->value.id - instr->cmpxchg.newval->id,
32317ec681f3Smrg      instr->cmpxchg.is_volatile,
32327ec681f3Smrg      instr->cmpxchg.ordering,
32337ec681f3Smrg      instr->cmpxchg.syncscope,
32347ec681f3Smrg   };
32357ec681f3Smrg   return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_CMPXCHG_OLD,
32367ec681f3Smrg                                data, ARRAY_SIZE(data));
32377ec681f3Smrg}
32387ec681f3Smrg
32397ec681f3Smrgstatic bool
32407ec681f3Smrgemit_atomicrmw(struct dxil_module *m, struct dxil_instr *instr)
32417ec681f3Smrg{
32427ec681f3Smrg   assert(instr->type == INSTR_ATOMICRMW);
32437ec681f3Smrg   assert(instr->value.id > instr->atomicrmw.value->id);
32447ec681f3Smrg   assert(instr->value.id > instr->atomicrmw.ptr->id);
32457ec681f3Smrg   uint64_t data[] = {
32467ec681f3Smrg      instr->value.id - instr->atomicrmw.ptr->id,
32477ec681f3Smrg      instr->value.id - instr->atomicrmw.value->id,
32487ec681f3Smrg      instr->atomicrmw.op,
32497ec681f3Smrg      instr->atomicrmw.is_volatile,
32507ec681f3Smrg      instr->atomicrmw.ordering,
32517ec681f3Smrg      instr->atomicrmw.syncscope,
32527ec681f3Smrg   };
32537ec681f3Smrg   return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_ATOMICRMW,
32547ec681f3Smrg                                data, ARRAY_SIZE(data));
32557ec681f3Smrg}
32567ec681f3Smrg
32577ec681f3Smrgstatic bool
32587ec681f3Smrgemit_instr(struct dxil_module *m, struct dxil_instr *instr)
32597ec681f3Smrg{
32607ec681f3Smrg   switch (instr->type) {
32617ec681f3Smrg   case INSTR_BINOP:
32627ec681f3Smrg      return emit_binop(m, instr);
32637ec681f3Smrg
32647ec681f3Smrg   case INSTR_CMP:
32657ec681f3Smrg      return emit_cmp(m, instr);
32667ec681f3Smrg
32677ec681f3Smrg   case INSTR_SELECT:
32687ec681f3Smrg      return emit_select(m, instr);
32697ec681f3Smrg
32707ec681f3Smrg   case INSTR_CAST:
32717ec681f3Smrg      return emit_cast(m, instr);
32727ec681f3Smrg
32737ec681f3Smrg   case INSTR_BR:
32747ec681f3Smrg      return emit_branch(m, instr);
32757ec681f3Smrg
32767ec681f3Smrg   case INSTR_PHI:
32777ec681f3Smrg      return emit_phi(m, instr);
32787ec681f3Smrg
32797ec681f3Smrg   case INSTR_CALL:
32807ec681f3Smrg      return emit_call(m, instr);
32817ec681f3Smrg
32827ec681f3Smrg   case INSTR_RET:
32837ec681f3Smrg      return emit_ret(m, instr);
32847ec681f3Smrg
32857ec681f3Smrg   case INSTR_EXTRACTVAL:
32867ec681f3Smrg      return emit_extractval(m, instr);
32877ec681f3Smrg
32887ec681f3Smrg   case INSTR_ALLOCA:
32897ec681f3Smrg      return emit_alloca(m, instr);
32907ec681f3Smrg
32917ec681f3Smrg   case INSTR_GEP:
32927ec681f3Smrg      return emit_gep(m, instr);
32937ec681f3Smrg
32947ec681f3Smrg   case INSTR_LOAD:
32957ec681f3Smrg      return emit_load(m, instr);
32967ec681f3Smrg
32977ec681f3Smrg   case INSTR_STORE:
32987ec681f3Smrg      return emit_store(m, instr);
32997ec681f3Smrg
33007ec681f3Smrg   case INSTR_ATOMICRMW:
33017ec681f3Smrg      return emit_atomicrmw(m, instr);
33027ec681f3Smrg
33037ec681f3Smrg   case INSTR_CMPXCHG:
33047ec681f3Smrg      return emit_cmpxchg(m, instr);
33057ec681f3Smrg
33067ec681f3Smrg   default:
33077ec681f3Smrg      unreachable("unexpected instruction type");
33087ec681f3Smrg   }
33097ec681f3Smrg}
33107ec681f3Smrg
33117ec681f3Smrgstatic bool
33127ec681f3Smrgemit_function(struct dxil_module *m)
33137ec681f3Smrg{
33147ec681f3Smrg   if (!enter_subblock(m, DXIL_FUNCTION_BLOCK, 4) ||
33157ec681f3Smrg       !emit_record_int(m, FUNC_CODE_DECLAREBLOCKS, m->curr_block))
33167ec681f3Smrg      return false;
33177ec681f3Smrg
33187ec681f3Smrg   list_for_each_entry(struct dxil_instr, instr, &m->instr_list, head) {
33197ec681f3Smrg      if (!emit_instr(m, instr))
33207ec681f3Smrg         return false;
33217ec681f3Smrg   }
33227ec681f3Smrg
33237ec681f3Smrg   return exit_block(m);
33247ec681f3Smrg}
33257ec681f3Smrg
33267ec681f3Smrgstatic void
33277ec681f3Smrgassign_values(struct dxil_module *m)
33287ec681f3Smrg{
33297ec681f3Smrg   int next_value_id = 0;
33307ec681f3Smrg
33317ec681f3Smrg   struct dxil_gvar *gvar;
33327ec681f3Smrg   LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) {
33337ec681f3Smrg      gvar->value.id = next_value_id++;
33347ec681f3Smrg   }
33357ec681f3Smrg
33367ec681f3Smrg   struct dxil_func *func;
33377ec681f3Smrg   LIST_FOR_EACH_ENTRY(func, &m->func_list, head) {
33387ec681f3Smrg      func->value.id = next_value_id++;
33397ec681f3Smrg   }
33407ec681f3Smrg
33417ec681f3Smrg   struct dxil_const *c;
33427ec681f3Smrg   LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {
33437ec681f3Smrg      c->value.id = next_value_id++;
33447ec681f3Smrg   }
33457ec681f3Smrg
33467ec681f3Smrg   struct dxil_instr *instr;
33477ec681f3Smrg   LIST_FOR_EACH_ENTRY(instr, &m->instr_list, head) {
33487ec681f3Smrg      instr->value.id = next_value_id;
33497ec681f3Smrg      if (instr->has_value)
33507ec681f3Smrg         next_value_id++;
33517ec681f3Smrg   }
33527ec681f3Smrg}
33537ec681f3Smrg
33547ec681f3Smrgbool
33557ec681f3Smrgdxil_emit_module(struct dxil_module *m)
33567ec681f3Smrg{
33577ec681f3Smrg   assign_values(m);
33587ec681f3Smrg   return dxil_buffer_emit_bits(&m->buf, 'B', 8) &&
33597ec681f3Smrg          dxil_buffer_emit_bits(&m->buf, 'C', 8) &&
33607ec681f3Smrg          dxil_buffer_emit_bits(&m->buf, 0xC0, 8) &&
33617ec681f3Smrg          dxil_buffer_emit_bits(&m->buf, 0xDE, 8) &&
33627ec681f3Smrg          enter_subblock(m, DXIL_MODULE, 3) &&
33637ec681f3Smrg          emit_record_int(m, DXIL_MODULE_CODE_VERSION, 1) &&
33647ec681f3Smrg          emit_blockinfo(m) &&
33657ec681f3Smrg          emit_attrib_group_table(m) &&
33667ec681f3Smrg          emit_attribute_table(m) &&
33677ec681f3Smrg          emit_type_table(m) &&
33687ec681f3Smrg          emit_module_info(m) &&
33697ec681f3Smrg          emit_module_consts(m) &&
33707ec681f3Smrg          emit_metadata(m) &&
33717ec681f3Smrg          emit_value_symbol_table(m) &&
33727ec681f3Smrg          emit_function(m) &&
33737ec681f3Smrg          exit_block(m);
33747ec681f3Smrg}
3375