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