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