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