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