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