17ec681f3Smrg/* 27ec681f3Smrg * Copyright © Microsoft Corporation 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 217ec681f3Smrg * IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include "dxil_module.h" 257ec681f3Smrg#include "dxil_internal.h" 267ec681f3Smrg 277ec681f3Smrg#include "util/macros.h" 287ec681f3Smrg#include "util/u_math.h" 297ec681f3Smrg#include "util/u_memory.h" 307ec681f3Smrg#include "util/rb_tree.h" 317ec681f3Smrg 327ec681f3Smrg#include <assert.h> 337ec681f3Smrg#include <stdio.h> 347ec681f3Smrg 357ec681f3Smrgvoid 367ec681f3Smrgdxil_module_init(struct dxil_module *m, void *ralloc_ctx) 377ec681f3Smrg{ 387ec681f3Smrg assert(ralloc_ctx); 397ec681f3Smrg 407ec681f3Smrg memset(m, 0, sizeof(struct dxil_module)); 417ec681f3Smrg m->ralloc_ctx = ralloc_ctx; 427ec681f3Smrg 437ec681f3Smrg dxil_buffer_init(&m->buf, 2); 447ec681f3Smrg memset(&m->feats, 0, sizeof(m->feats)); 457ec681f3Smrg 467ec681f3Smrg list_inithead(&m->type_list); 477ec681f3Smrg list_inithead(&m->func_list); 487ec681f3Smrg list_inithead(&m->attr_set_list); 497ec681f3Smrg list_inithead(&m->gvar_list); 507ec681f3Smrg list_inithead(&m->const_list); 517ec681f3Smrg list_inithead(&m->instr_list); 527ec681f3Smrg list_inithead(&m->mdnode_list); 537ec681f3Smrg list_inithead(&m->md_named_node_list); 547ec681f3Smrg 557ec681f3Smrg m->functions = rzalloc(ralloc_ctx, struct rb_tree); 567ec681f3Smrg rb_tree_init(m->functions); 577ec681f3Smrg 587ec681f3Smrg m->curr_block = 0; 597ec681f3Smrg} 607ec681f3Smrg 617ec681f3Smrgvoid 627ec681f3Smrgdxil_module_release(struct dxil_module *m) 637ec681f3Smrg{ 647ec681f3Smrg dxil_buffer_finish(&m->buf); 657ec681f3Smrg} 667ec681f3Smrg 677ec681f3Smrgstatic bool 687ec681f3Smrgemit_bits64(struct dxil_buffer *b, uint64_t data, unsigned width) 697ec681f3Smrg{ 707ec681f3Smrg if (data > UINT32_MAX) { 717ec681f3Smrg assert(width > 32); 727ec681f3Smrg return dxil_buffer_emit_bits(b, (uint32_t)(data & UINT32_MAX), width) && 737ec681f3Smrg dxil_buffer_emit_bits(b, (uint32_t)(data >> 32), width - 32); 747ec681f3Smrg } else 757ec681f3Smrg return dxil_buffer_emit_bits(b, (uint32_t)data, width); 767ec681f3Smrg} 777ec681f3Smrg 787ec681f3Smrg/* See the LLVM documentation for details about what these are all about: 797ec681f3Smrg * https://www.llvm.org/docs/BitCodeFormat.html#abbreviation-ids 807ec681f3Smrg */ 817ec681f3Smrgenum dxil_fixed_abbrev { 827ec681f3Smrg DXIL_END_BLOCK = 0, 837ec681f3Smrg DXIL_ENTER_SUBBLOCK = 1, 847ec681f3Smrg DXIL_DEFINE_ABBREV = 2, 857ec681f3Smrg DXIL_UNABBREV_RECORD = 3, 867ec681f3Smrg DXIL_FIRST_APPLICATION_ABBREV = 4 877ec681f3Smrg}; 887ec681f3Smrg 897ec681f3Smrgstatic bool 907ec681f3Smrgenter_subblock(struct dxil_module *m, unsigned id, unsigned abbrev_width) 917ec681f3Smrg{ 927ec681f3Smrg assert(m->num_blocks < ARRAY_SIZE(m->blocks)); 937ec681f3Smrg m->blocks[m->num_blocks].abbrev_width = m->buf.abbrev_width; 947ec681f3Smrg 957ec681f3Smrg if (!dxil_buffer_emit_abbrev_id(&m->buf, DXIL_ENTER_SUBBLOCK) || 967ec681f3Smrg !dxil_buffer_emit_vbr_bits(&m->buf, id, 8) || 977ec681f3Smrg !dxil_buffer_emit_vbr_bits(&m->buf, abbrev_width, 4) || 987ec681f3Smrg !dxil_buffer_align(&m->buf)) 997ec681f3Smrg return false; 1007ec681f3Smrg 1017ec681f3Smrg m->buf.abbrev_width = abbrev_width; 1027ec681f3Smrg m->blocks[m->num_blocks++].offset = blob_reserve_uint32(&m->buf.blob); 1037ec681f3Smrg return true; 1047ec681f3Smrg} 1057ec681f3Smrg 1067ec681f3Smrgstatic bool 1077ec681f3Smrgexit_block(struct dxil_module *m) 1087ec681f3Smrg{ 1097ec681f3Smrg assert(m->num_blocks > 0); 1107ec681f3Smrg assert(m->num_blocks < ARRAY_SIZE(m->blocks)); 1117ec681f3Smrg 1127ec681f3Smrg if (!dxil_buffer_emit_abbrev_id(&m->buf, DXIL_END_BLOCK) || 1137ec681f3Smrg !dxil_buffer_align(&m->buf)) 1147ec681f3Smrg return false; 1157ec681f3Smrg 1167ec681f3Smrg intptr_t size_offset = m->blocks[m->num_blocks - 1].offset; 1177ec681f3Smrg uint32_t size = (m->buf.blob.size - size_offset - 1) / sizeof(uint32_t); 1187ec681f3Smrg if (!blob_overwrite_uint32(&m->buf.blob, size_offset, size)) 1197ec681f3Smrg return false; 1207ec681f3Smrg 1217ec681f3Smrg m->num_blocks--; 1227ec681f3Smrg m->buf.abbrev_width = m->blocks[m->num_blocks].abbrev_width; 1237ec681f3Smrg return true; 1247ec681f3Smrg} 1257ec681f3Smrg 1267ec681f3Smrgstatic bool 1277ec681f3Smrgemit_record_no_abbrev(struct dxil_buffer *b, unsigned code, 1287ec681f3Smrg const uint64_t *data, size_t size) 1297ec681f3Smrg{ 1307ec681f3Smrg if (!dxil_buffer_emit_abbrev_id(b, DXIL_UNABBREV_RECORD) || 1317ec681f3Smrg !dxil_buffer_emit_vbr_bits(b, code, 6) || 1327ec681f3Smrg !dxil_buffer_emit_vbr_bits(b, size, 6)) 1337ec681f3Smrg return false; 1347ec681f3Smrg 1357ec681f3Smrg for (size_t i = 0; i < size; ++i) 1367ec681f3Smrg if (!dxil_buffer_emit_vbr_bits(b, data[i], 6)) 1377ec681f3Smrg return false; 1387ec681f3Smrg 1397ec681f3Smrg return true; 1407ec681f3Smrg} 1417ec681f3Smrg 1427ec681f3Smrgstatic bool 1437ec681f3Smrgemit_record(struct dxil_module *m, unsigned code, 1447ec681f3Smrg const uint64_t *data, size_t size) 1457ec681f3Smrg{ 1467ec681f3Smrg return emit_record_no_abbrev(&m->buf, code, data, size); 1477ec681f3Smrg} 1487ec681f3Smrg 1497ec681f3Smrgstatic bool 1507ec681f3Smrgemit_record_int(struct dxil_module *m, unsigned code, int value) 1517ec681f3Smrg{ 1527ec681f3Smrg uint64_t data = value; 1537ec681f3Smrg return emit_record(m, code, &data, 1); 1547ec681f3Smrg} 1557ec681f3Smrg 1567ec681f3Smrgstatic bool 1577ec681f3Smrgis_char6(char ch) 1587ec681f3Smrg{ 1597ec681f3Smrg if ((ch >= 'a' && ch <= 'z') || 1607ec681f3Smrg (ch >= 'A' && ch <= 'Z') || 1617ec681f3Smrg (ch >= '0' && ch <= '9')) 1627ec681f3Smrg return true; 1637ec681f3Smrg 1647ec681f3Smrg switch (ch) { 1657ec681f3Smrg case '.': 1667ec681f3Smrg case '_': 1677ec681f3Smrg return true; 1687ec681f3Smrg 1697ec681f3Smrg default: 1707ec681f3Smrg return false; 1717ec681f3Smrg } 1727ec681f3Smrg} 1737ec681f3Smrg 1747ec681f3Smrgstatic bool 1757ec681f3Smrgis_char6_string(const char *str) 1767ec681f3Smrg{ 1777ec681f3Smrg while (*str != '\0') { 1787ec681f3Smrg if (!is_char6(*str++)) 1797ec681f3Smrg return false; 1807ec681f3Smrg } 1817ec681f3Smrg return true; 1827ec681f3Smrg} 1837ec681f3Smrg 1847ec681f3Smrgstatic bool 1857ec681f3Smrgis_char7_string(const char *str) 1867ec681f3Smrg{ 1877ec681f3Smrg while (*str != '\0') { 1887ec681f3Smrg if (*str++ & 0x80) 1897ec681f3Smrg return false; 1907ec681f3Smrg } 1917ec681f3Smrg return true; 1927ec681f3Smrg} 1937ec681f3Smrg 1947ec681f3Smrgstatic unsigned 1957ec681f3Smrgencode_char6(char ch) 1967ec681f3Smrg{ 1977ec681f3Smrg const int letters = 'z' - 'a' + 1; 1987ec681f3Smrg 1997ec681f3Smrg if (ch >= 'a' && ch <= 'z') 2007ec681f3Smrg return ch - 'a'; 2017ec681f3Smrg else if (ch >= 'A' && ch <= 'Z') 2027ec681f3Smrg return letters + ch - 'A'; 2037ec681f3Smrg else if (ch >= '0' && ch <= '9') 2047ec681f3Smrg return 2 * letters + ch - '0'; 2057ec681f3Smrg 2067ec681f3Smrg switch (ch) { 2077ec681f3Smrg case '.': return 62; 2087ec681f3Smrg case '_': return 63; 2097ec681f3Smrg default: 2107ec681f3Smrg unreachable("invalid char6-character"); 2117ec681f3Smrg } 2127ec681f3Smrg} 2137ec681f3Smrg 2147ec681f3Smrgstatic bool 2157ec681f3Smrgemit_fixed(struct dxil_buffer *b, uint64_t data, unsigned width) 2167ec681f3Smrg{ 2177ec681f3Smrg if (!width) 2187ec681f3Smrg return true; 2197ec681f3Smrg 2207ec681f3Smrg return emit_bits64(b, data, width); 2217ec681f3Smrg} 2227ec681f3Smrg 2237ec681f3Smrgstatic bool 2247ec681f3Smrgemit_vbr(struct dxil_buffer *b, uint64_t data, unsigned width) 2257ec681f3Smrg{ 2267ec681f3Smrg if (!width) 2277ec681f3Smrg return true; 2287ec681f3Smrg 2297ec681f3Smrg return dxil_buffer_emit_vbr_bits(b, data, width); 2307ec681f3Smrg} 2317ec681f3Smrg 2327ec681f3Smrgstatic bool 2337ec681f3Smrgemit_char6(struct dxil_buffer *b, uint64_t data) 2347ec681f3Smrg{ 2357ec681f3Smrg return dxil_buffer_emit_bits(b, encode_char6((char)data), 6); 2367ec681f3Smrg} 2377ec681f3Smrg 2387ec681f3Smrgstruct dxil_abbrev { 2397ec681f3Smrg struct { 2407ec681f3Smrg enum { 2417ec681f3Smrg DXIL_OP_LITERAL = 0, 2427ec681f3Smrg DXIL_OP_FIXED = 1, 2437ec681f3Smrg DXIL_OP_VBR = 2, 2447ec681f3Smrg DXIL_OP_ARRAY = 3, 2457ec681f3Smrg DXIL_OP_CHAR6 = 4, 2467ec681f3Smrg DXIL_OP_BLOB = 5 2477ec681f3Smrg } type; 2487ec681f3Smrg union { 2497ec681f3Smrg uint64_t value; 2507ec681f3Smrg uint64_t encoding_data; 2517ec681f3Smrg }; 2527ec681f3Smrg } operands[7]; 2537ec681f3Smrg size_t num_operands; 2547ec681f3Smrg}; 2557ec681f3Smrg 2567ec681f3Smrgstatic bool 2577ec681f3Smrgemit_record_abbrev(struct dxil_buffer *b, 2587ec681f3Smrg unsigned abbrev, const struct dxil_abbrev *a, 2597ec681f3Smrg const uint64_t *data, size_t size) 2607ec681f3Smrg{ 2617ec681f3Smrg assert(abbrev >= DXIL_FIRST_APPLICATION_ABBREV); 2627ec681f3Smrg 2637ec681f3Smrg if (!dxil_buffer_emit_abbrev_id(b, abbrev)) 2647ec681f3Smrg return false; 2657ec681f3Smrg 2667ec681f3Smrg size_t curr_data = 0; 2677ec681f3Smrg for (int i = 0; i < a->num_operands; ++i) { 2687ec681f3Smrg switch (a->operands[i].type) { 2697ec681f3Smrg case DXIL_OP_LITERAL: 2707ec681f3Smrg assert(curr_data < size); 2717ec681f3Smrg assert(data[curr_data] == a->operands[i].value); 2727ec681f3Smrg curr_data++; 2737ec681f3Smrg /* literals are no-ops, because their value is defined in the 2747ec681f3Smrg abbrev-definition already */ 2757ec681f3Smrg break; 2767ec681f3Smrg 2777ec681f3Smrg case DXIL_OP_FIXED: 2787ec681f3Smrg assert(curr_data < size); 2797ec681f3Smrg if (!emit_fixed(b, data[curr_data++], a->operands[i].encoding_data)) 2807ec681f3Smrg return false; 2817ec681f3Smrg break; 2827ec681f3Smrg 2837ec681f3Smrg case DXIL_OP_VBR: 2847ec681f3Smrg assert(curr_data < size); 2857ec681f3Smrg if (!emit_vbr(b, data[curr_data++], a->operands[i].encoding_data)) 2867ec681f3Smrg return false; 2877ec681f3Smrg break; 2887ec681f3Smrg 2897ec681f3Smrg case DXIL_OP_ARRAY: 2907ec681f3Smrg assert(i == a->num_operands - 2); /* arrays should always be second to last */ 2917ec681f3Smrg 2927ec681f3Smrg if (!dxil_buffer_emit_vbr_bits(b, size - curr_data, 6)) 2937ec681f3Smrg return false; 2947ec681f3Smrg 2957ec681f3Smrg switch (a->operands[i + 1].type) { 2967ec681f3Smrg case DXIL_OP_FIXED: 2977ec681f3Smrg while (curr_data < size) 2987ec681f3Smrg if (!emit_fixed(b, data[curr_data++], a->operands[i + 1].encoding_data)) 2997ec681f3Smrg return false; 3007ec681f3Smrg break; 3017ec681f3Smrg 3027ec681f3Smrg case DXIL_OP_VBR: 3037ec681f3Smrg while (curr_data < size) 3047ec681f3Smrg if (!emit_vbr(b, data[curr_data++], a->operands[i + 1].encoding_data)) 3057ec681f3Smrg return false; 3067ec681f3Smrg break; 3077ec681f3Smrg 3087ec681f3Smrg case DXIL_OP_CHAR6: 3097ec681f3Smrg while (curr_data < size) 3107ec681f3Smrg if (!emit_char6(b, data[curr_data++])) 3117ec681f3Smrg return false; 3127ec681f3Smrg break; 3137ec681f3Smrg 3147ec681f3Smrg default: 3157ec681f3Smrg unreachable("unexpected operand type"); 3167ec681f3Smrg } 3177ec681f3Smrg return true; /* we're done */ 3187ec681f3Smrg 3197ec681f3Smrg case DXIL_OP_CHAR6: 3207ec681f3Smrg assert(curr_data < size); 3217ec681f3Smrg if (!emit_char6(b, data[curr_data++])) 3227ec681f3Smrg return false; 3237ec681f3Smrg break; 3247ec681f3Smrg 3257ec681f3Smrg case DXIL_OP_BLOB: 3267ec681f3Smrg unreachable("HALP, unplement!"); 3277ec681f3Smrg 3287ec681f3Smrg default: 3297ec681f3Smrg unreachable("unexpected operand type"); 3307ec681f3Smrg } 3317ec681f3Smrg } 3327ec681f3Smrg 3337ec681f3Smrg assert(curr_data == size); 3347ec681f3Smrg return true; 3357ec681f3Smrg} 3367ec681f3Smrg 3377ec681f3Smrg 3387ec681f3Smrgstatic struct dxil_type * 3397ec681f3Smrgcreate_type(struct dxil_module *m, enum type_type type) 3407ec681f3Smrg{ 3417ec681f3Smrg struct dxil_type *ret = rzalloc_size(m->ralloc_ctx, 3427ec681f3Smrg sizeof(struct dxil_type)); 3437ec681f3Smrg if (ret) { 3447ec681f3Smrg ret->type = type; 3457ec681f3Smrg ret->id = list_length(&m->type_list); 3467ec681f3Smrg list_addtail(&ret->head, &m->type_list); 3477ec681f3Smrg } 3487ec681f3Smrg return ret; 3497ec681f3Smrg} 3507ec681f3Smrg 3517ec681f3Smrgstatic bool 3527ec681f3Smrgtypes_equal(const struct dxil_type *lhs, const struct dxil_type *rhs); 3537ec681f3Smrg 3547ec681f3Smrgstatic bool 3557ec681f3Smrgtype_list_equal(const struct dxil_type_list *lhs, 3567ec681f3Smrg const struct dxil_type_list *rhs) 3577ec681f3Smrg{ 3587ec681f3Smrg if (lhs->num_types != rhs->num_types) 3597ec681f3Smrg return false; 3607ec681f3Smrg for (unsigned i = 0; i < lhs->num_types; ++i) 3617ec681f3Smrg if (!types_equal(lhs->types[i], rhs->types[i])) 3627ec681f3Smrg return false; 3637ec681f3Smrg return true; 3647ec681f3Smrg} 3657ec681f3Smrg 3667ec681f3Smrgstatic bool 3677ec681f3Smrgtypes_equal(const struct dxil_type *lhs, const struct dxil_type *rhs) 3687ec681f3Smrg{ 3697ec681f3Smrg if (lhs == rhs) 3707ec681f3Smrg return true; 3717ec681f3Smrg 3727ec681f3Smrg /* Below we only assert that different type pointers really define different types 3737ec681f3Smrg * Since this function is only called in asserts, it is not needed to put the code 3747ec681f3Smrg * into a #ifdef NDEBUG statement */ 3757ec681f3Smrg if (lhs->type != rhs->type) 3767ec681f3Smrg return false; 3777ec681f3Smrg 3787ec681f3Smrg bool retval = false; 3797ec681f3Smrg switch (lhs->type) { 3807ec681f3Smrg case TYPE_VOID: 3817ec681f3Smrg retval = true; 3827ec681f3Smrg break; 3837ec681f3Smrg case TYPE_FLOAT: 3847ec681f3Smrg retval = lhs->float_bits == rhs->float_bits; 3857ec681f3Smrg break; 3867ec681f3Smrg case TYPE_INTEGER: 3877ec681f3Smrg retval = lhs->int_bits == rhs->int_bits; 3887ec681f3Smrg break; 3897ec681f3Smrg case TYPE_POINTER: 3907ec681f3Smrg retval = types_equal(lhs->ptr_target_type, rhs->ptr_target_type); 3917ec681f3Smrg break; 3927ec681f3Smrg case TYPE_ARRAY: 3937ec681f3Smrg case TYPE_VECTOR: 3947ec681f3Smrg retval = (lhs->array_or_vector_def.num_elems == rhs->array_or_vector_def.num_elems) && 3957ec681f3Smrg types_equal(lhs->array_or_vector_def.elem_type, 3967ec681f3Smrg rhs->array_or_vector_def.elem_type); 3977ec681f3Smrg break; 3987ec681f3Smrg case TYPE_FUNCTION: 3997ec681f3Smrg if (!types_equal(lhs->function_def.ret_type, 4007ec681f3Smrg rhs->function_def.ret_type)) 4017ec681f3Smrg return false; 4027ec681f3Smrg retval = type_list_equal(&lhs->function_def.args, &rhs->function_def.args); 4037ec681f3Smrg break; 4047ec681f3Smrg case TYPE_STRUCT: 4057ec681f3Smrg retval = type_list_equal(&lhs->struct_def.elem, &rhs->struct_def.elem); 4067ec681f3Smrg } 4077ec681f3Smrg assert(!retval && "Types are equal in structure but not as pointers"); 4087ec681f3Smrg return retval; 4097ec681f3Smrg} 4107ec681f3Smrg 4117ec681f3Smrgbool 4127ec681f3Smrgdxil_value_type_equal_to(const struct dxil_value *value, 4137ec681f3Smrg const struct dxil_type *rhs) 4147ec681f3Smrg{ 4157ec681f3Smrg return types_equal(value->type, rhs); 4167ec681f3Smrg} 4177ec681f3Smrg 4187ec681f3Smrgnir_alu_type 4197ec681f3Smrgdxil_type_to_nir_type(const struct dxil_type *type) 4207ec681f3Smrg{ 4217ec681f3Smrg assert(type); 4227ec681f3Smrg switch (type->type) { 4237ec681f3Smrg case TYPE_INTEGER: 4247ec681f3Smrg return type->int_bits == 1 ? nir_type_bool : nir_type_int; 4257ec681f3Smrg case TYPE_FLOAT: 4267ec681f3Smrg return nir_type_float; 4277ec681f3Smrg default: 4287ec681f3Smrg unreachable("Unexpected type in dxil_type_to_nir_type"); 4297ec681f3Smrg } 4307ec681f3Smrg} 4317ec681f3Smrg 4327ec681f3Smrgbool 4337ec681f3Smrgdxil_value_type_bitsize_equal_to(const struct dxil_value *value, unsigned bitsize) 4347ec681f3Smrg{ 4357ec681f3Smrg switch (value->type->type) { 4367ec681f3Smrg case TYPE_INTEGER: 4377ec681f3Smrg return value->type->int_bits == bitsize; 4387ec681f3Smrg case TYPE_FLOAT: 4397ec681f3Smrg return value->type->float_bits == bitsize; 4407ec681f3Smrg default: 4417ec681f3Smrg return false; 4427ec681f3Smrg } 4437ec681f3Smrg} 4447ec681f3Smrg 4457ec681f3Smrgconst struct dxil_type * 4467ec681f3Smrgdxil_value_get_type(const struct dxil_value *value) 4477ec681f3Smrg{ 4487ec681f3Smrg return value->type; 4497ec681f3Smrg} 4507ec681f3Smrg 4517ec681f3Smrgconst struct dxil_type * 4527ec681f3Smrgdxil_module_get_void_type(struct dxil_module *m) 4537ec681f3Smrg{ 4547ec681f3Smrg if (!m->void_type) 4557ec681f3Smrg m->void_type = create_type(m, TYPE_VOID); 4567ec681f3Smrg return m->void_type; 4577ec681f3Smrg} 4587ec681f3Smrg 4597ec681f3Smrgstatic const struct dxil_type * 4607ec681f3Smrgcreate_int_type(struct dxil_module *m, unsigned bit_size) 4617ec681f3Smrg{ 4627ec681f3Smrg struct dxil_type *type = create_type(m, TYPE_INTEGER); 4637ec681f3Smrg if (type) 4647ec681f3Smrg type->int_bits = bit_size; 4657ec681f3Smrg return type; 4667ec681f3Smrg} 4677ec681f3Smrg 4687ec681f3Smrgstatic const struct dxil_type * 4697ec681f3Smrgget_int1_type(struct dxil_module *m) 4707ec681f3Smrg{ 4717ec681f3Smrg if (!m->int1_type) 4727ec681f3Smrg m->int1_type = create_int_type(m, 1); 4737ec681f3Smrg return m->int1_type; 4747ec681f3Smrg} 4757ec681f3Smrg 4767ec681f3Smrgstatic const struct dxil_type * 4777ec681f3Smrgget_int8_type(struct dxil_module *m) 4787ec681f3Smrg{ 4797ec681f3Smrg if (!m->int8_type) 4807ec681f3Smrg m->int8_type = create_int_type(m, 8); 4817ec681f3Smrg return m->int8_type; 4827ec681f3Smrg} 4837ec681f3Smrg 4847ec681f3Smrgstatic const struct dxil_type * 4857ec681f3Smrgget_int16_type(struct dxil_module *m) 4867ec681f3Smrg{ 4877ec681f3Smrg if (!m->int16_type) 4887ec681f3Smrg m->int16_type = create_int_type(m, 16); 4897ec681f3Smrg return m->int16_type; 4907ec681f3Smrg} 4917ec681f3Smrg 4927ec681f3Smrgstatic const struct dxil_type * 4937ec681f3Smrgget_int32_type(struct dxil_module *m) 4947ec681f3Smrg{ 4957ec681f3Smrg if (!m->int32_type) 4967ec681f3Smrg m->int32_type = create_int_type(m, 32); 4977ec681f3Smrg return m->int32_type; 4987ec681f3Smrg} 4997ec681f3Smrg 5007ec681f3Smrgstatic const struct dxil_type * 5017ec681f3Smrgget_int64_type(struct dxil_module *m) 5027ec681f3Smrg{ 5037ec681f3Smrg if (!m->int64_type) 5047ec681f3Smrg m->int64_type = create_int_type(m, 64); 5057ec681f3Smrg return m->int64_type; 5067ec681f3Smrg} 5077ec681f3Smrg 5087ec681f3Smrgstatic const struct dxil_type * 5097ec681f3Smrgcreate_float_type(struct dxil_module *m, unsigned bit_size) 5107ec681f3Smrg{ 5117ec681f3Smrg struct dxil_type *type = create_type(m, TYPE_FLOAT); 5127ec681f3Smrg if (type) 5137ec681f3Smrg type->float_bits = bit_size; 5147ec681f3Smrg return type; 5157ec681f3Smrg} 5167ec681f3Smrg 5177ec681f3Smrgconst struct dxil_type * 5187ec681f3Smrgdxil_module_get_int_type(struct dxil_module *m, unsigned bit_size) 5197ec681f3Smrg{ 5207ec681f3Smrg switch (bit_size) { 5217ec681f3Smrg case 1: return get_int1_type(m); 5227ec681f3Smrg case 8: return get_int8_type(m); 5237ec681f3Smrg case 16: return get_int16_type(m); 5247ec681f3Smrg case 32: return get_int32_type(m); 5257ec681f3Smrg case 64: return get_int64_type(m); 5267ec681f3Smrg default: 5277ec681f3Smrg unreachable("unsupported bit-width"); 5287ec681f3Smrg } 5297ec681f3Smrg} 5307ec681f3Smrg 5317ec681f3Smrgstatic const struct dxil_type * 5327ec681f3Smrgget_float16_type(struct dxil_module *m) 5337ec681f3Smrg{ 5347ec681f3Smrg if (!m->float16_type) 5357ec681f3Smrg m->float16_type = create_float_type(m, 16); 5367ec681f3Smrg return m->float16_type; 5377ec681f3Smrg} 5387ec681f3Smrg 5397ec681f3Smrgstatic const struct dxil_type * 5407ec681f3Smrgget_float32_type(struct dxil_module *m) 5417ec681f3Smrg{ 5427ec681f3Smrg if (!m->float32_type) 5437ec681f3Smrg m->float32_type = create_float_type(m, 32); 5447ec681f3Smrg return m->float32_type; 5457ec681f3Smrg} 5467ec681f3Smrg 5477ec681f3Smrgstatic const struct dxil_type * 5487ec681f3Smrgget_float64_type(struct dxil_module *m) 5497ec681f3Smrg{ 5507ec681f3Smrg if (!m->float64_type) 5517ec681f3Smrg m->float64_type = create_float_type(m, 64); 5527ec681f3Smrg return m->float64_type; 5537ec681f3Smrg} 5547ec681f3Smrg 5557ec681f3Smrgconst struct dxil_type * 5567ec681f3Smrgdxil_module_get_float_type(struct dxil_module *m, unsigned bit_size) 5577ec681f3Smrg{ 5587ec681f3Smrg switch (bit_size) { 5597ec681f3Smrg case 16: return get_float16_type(m); 5607ec681f3Smrg case 32: return get_float32_type(m); 5617ec681f3Smrg case 64: return get_float64_type(m); 5627ec681f3Smrg default: 5637ec681f3Smrg unreachable("unsupported bit-width"); 5647ec681f3Smrg } 5657ec681f3Smrg return get_float32_type(m); 5667ec681f3Smrg} 5677ec681f3Smrg 5687ec681f3Smrgconst struct dxil_type * 5697ec681f3Smrgdxil_module_get_pointer_type(struct dxil_module *m, 5707ec681f3Smrg const struct dxil_type *target) 5717ec681f3Smrg{ 5727ec681f3Smrg struct dxil_type *type; 5737ec681f3Smrg LIST_FOR_EACH_ENTRY(type, &m->type_list, head) { 5747ec681f3Smrg if (type->type == TYPE_POINTER && 5757ec681f3Smrg type->ptr_target_type == target) 5767ec681f3Smrg return type; 5777ec681f3Smrg } 5787ec681f3Smrg 5797ec681f3Smrg type = create_type(m, TYPE_POINTER); 5807ec681f3Smrg if (type) 5817ec681f3Smrg type->ptr_target_type = target; 5827ec681f3Smrg return type; 5837ec681f3Smrg} 5847ec681f3Smrg 5857ec681f3Smrgconst struct dxil_type * 5867ec681f3Smrgdxil_module_get_struct_type(struct dxil_module *m, 5877ec681f3Smrg const char *name, 5887ec681f3Smrg const struct dxil_type **elem_types, 5897ec681f3Smrg size_t num_elem_types) 5907ec681f3Smrg{ 5917ec681f3Smrg assert(!name || strlen(name) > 0); 5927ec681f3Smrg 5937ec681f3Smrg struct dxil_type *type; 5947ec681f3Smrg LIST_FOR_EACH_ENTRY(type, &m->type_list, head) { 5957ec681f3Smrg if (type->type != TYPE_STRUCT) 5967ec681f3Smrg continue; 5977ec681f3Smrg 5987ec681f3Smrg if ((name == NULL) != (type->struct_def.name == NULL)) 5997ec681f3Smrg continue; 6007ec681f3Smrg 6017ec681f3Smrg if (name && strcmp(type->struct_def.name, name)) 6027ec681f3Smrg continue; 6037ec681f3Smrg 6047ec681f3Smrg if (type->struct_def.elem.num_types == num_elem_types && 6057ec681f3Smrg !memcmp(type->struct_def.elem.types, elem_types, 6067ec681f3Smrg sizeof(struct dxil_type *) * num_elem_types)) 6077ec681f3Smrg return type; 6087ec681f3Smrg } 6097ec681f3Smrg 6107ec681f3Smrg type = create_type(m, TYPE_STRUCT); 6117ec681f3Smrg if (type) { 6127ec681f3Smrg if (name) { 6137ec681f3Smrg type->struct_def.name = ralloc_strdup(type, name); 6147ec681f3Smrg if (!type->struct_def.name) 6157ec681f3Smrg return NULL; 6167ec681f3Smrg } else 6177ec681f3Smrg type->struct_def.name = NULL; 6187ec681f3Smrg 6197ec681f3Smrg type->struct_def.elem.types = ralloc_array(type, struct dxil_type *, 6207ec681f3Smrg num_elem_types); 6217ec681f3Smrg if (!type->struct_def.elem.types) 6227ec681f3Smrg return NULL; 6237ec681f3Smrg 6247ec681f3Smrg memcpy(type->struct_def.elem.types, elem_types, 6257ec681f3Smrg sizeof(struct dxil_type *) * num_elem_types); 6267ec681f3Smrg type->struct_def.elem.num_types = num_elem_types; 6277ec681f3Smrg } 6287ec681f3Smrg return type; 6297ec681f3Smrg} 6307ec681f3Smrg 6317ec681f3Smrgconst struct dxil_type * 6327ec681f3Smrgdxil_module_get_array_type(struct dxil_module *m, 6337ec681f3Smrg const struct dxil_type *elem_type, 6347ec681f3Smrg size_t num_elems) 6357ec681f3Smrg{ 6367ec681f3Smrg struct dxil_type *type; 6377ec681f3Smrg LIST_FOR_EACH_ENTRY(type, &m->type_list, head) { 6387ec681f3Smrg if (type->type != TYPE_ARRAY) 6397ec681f3Smrg continue; 6407ec681f3Smrg 6417ec681f3Smrg if (type->array_or_vector_def.elem_type == elem_type && 6427ec681f3Smrg type->array_or_vector_def.num_elems == num_elems) 6437ec681f3Smrg return type; 6447ec681f3Smrg } 6457ec681f3Smrg 6467ec681f3Smrg type = create_type(m, TYPE_ARRAY); 6477ec681f3Smrg if (type) { 6487ec681f3Smrg type->array_or_vector_def.elem_type = elem_type; 6497ec681f3Smrg type->array_or_vector_def.num_elems = num_elems; 6507ec681f3Smrg } 6517ec681f3Smrg return type; 6527ec681f3Smrg} 6537ec681f3Smrg 6547ec681f3Smrgconst struct dxil_type * 6557ec681f3Smrgdxil_module_get_vector_type(struct dxil_module *m, 6567ec681f3Smrg const struct dxil_type *elem_type, 6577ec681f3Smrg size_t num_elems) 6587ec681f3Smrg{ 6597ec681f3Smrg struct dxil_type *type; 6607ec681f3Smrg LIST_FOR_EACH_ENTRY(type, &m->type_list, head) { 6617ec681f3Smrg if (type->type == TYPE_VECTOR && 6627ec681f3Smrg type->array_or_vector_def.elem_type == elem_type && 6637ec681f3Smrg type->array_or_vector_def.num_elems == num_elems) 6647ec681f3Smrg return type; 6657ec681f3Smrg } 6667ec681f3Smrg 6677ec681f3Smrg type = create_type(m, TYPE_VECTOR); 6687ec681f3Smrg if (!type) 6697ec681f3Smrg return NULL; 6707ec681f3Smrg 6717ec681f3Smrg type->array_or_vector_def.elem_type = elem_type; 6727ec681f3Smrg type->array_or_vector_def.num_elems = num_elems; 6737ec681f3Smrg return type; 6747ec681f3Smrg} 6757ec681f3Smrg 6767ec681f3Smrgconst struct dxil_type * 6777ec681f3Smrgdxil_get_overload_type(struct dxil_module *mod, enum overload_type overload) 6787ec681f3Smrg{ 6797ec681f3Smrg switch (overload) { 6807ec681f3Smrg case DXIL_I16: return get_int16_type(mod); 6817ec681f3Smrg case DXIL_I32: return get_int32_type(mod); 6827ec681f3Smrg case DXIL_I64: return get_int64_type(mod); 6837ec681f3Smrg case DXIL_F16: return get_float16_type(mod); 6847ec681f3Smrg case DXIL_F32: return get_float32_type(mod); 6857ec681f3Smrg case DXIL_F64: return get_float64_type(mod); 6867ec681f3Smrg default: 6877ec681f3Smrg unreachable("unexpected overload type"); 6887ec681f3Smrg } 6897ec681f3Smrg} 6907ec681f3Smrg 6917ec681f3Smrgconst struct dxil_type * 6927ec681f3Smrgdxil_module_get_handle_type(struct dxil_module *m) 6937ec681f3Smrg{ 6947ec681f3Smrg const struct dxil_type *int8_type = get_int8_type(m); 6957ec681f3Smrg if (!int8_type) 6967ec681f3Smrg return NULL; 6977ec681f3Smrg 6987ec681f3Smrg const struct dxil_type *ptr_type = dxil_module_get_pointer_type(m, int8_type); 6997ec681f3Smrg if (!ptr_type) 7007ec681f3Smrg return NULL; 7017ec681f3Smrg 7027ec681f3Smrg return dxil_module_get_struct_type(m, "dx.types.Handle", &ptr_type, 1); 7037ec681f3Smrg} 7047ec681f3Smrg 7057ec681f3Smrgconst struct dxil_type * 7067ec681f3Smrgdxil_module_get_cbuf_ret_type(struct dxil_module *mod, enum overload_type overload) 7077ec681f3Smrg{ 7087ec681f3Smrg const struct dxil_type *overload_type = dxil_get_overload_type(mod, overload); 7097ec681f3Smrg const struct dxil_type *fields[4] = { overload_type, overload_type, overload_type, overload_type }; 7107ec681f3Smrg unsigned num_fields; 7117ec681f3Smrg 7127ec681f3Smrg char name[64]; 7137ec681f3Smrg snprintf(name, sizeof(name), "dx.types.CBufRet.%s", dxil_overload_suffix(overload)); 7147ec681f3Smrg 7157ec681f3Smrg switch (overload) { 7167ec681f3Smrg case DXIL_I32: 7177ec681f3Smrg case DXIL_F32: 7187ec681f3Smrg num_fields = 4; 7197ec681f3Smrg break; 7207ec681f3Smrg case DXIL_I64: 7217ec681f3Smrg case DXIL_F64: 7227ec681f3Smrg num_fields = 2; 7237ec681f3Smrg break; 7247ec681f3Smrg default: 7257ec681f3Smrg unreachable("unexpected overload type"); 7267ec681f3Smrg } 7277ec681f3Smrg 7287ec681f3Smrg return dxil_module_get_struct_type(mod, name, fields, num_fields); 7297ec681f3Smrg} 7307ec681f3Smrg 7317ec681f3Smrgconst struct dxil_type * 7327ec681f3Smrgdxil_module_get_split_double_ret_type(struct dxil_module *mod) 7337ec681f3Smrg{ 7347ec681f3Smrg const struct dxil_type *int32_type = dxil_module_get_int_type(mod, 32); 7357ec681f3Smrg const struct dxil_type *fields[2] = { int32_type, int32_type }; 7367ec681f3Smrg 7377ec681f3Smrg return dxil_module_get_struct_type(mod, "dx.types.splitDouble", fields, 2); 7387ec681f3Smrg} 7397ec681f3Smrg 7407ec681f3Smrgstatic const struct dxil_type * 7417ec681f3Smrgdxil_module_get_type_from_comp_type(struct dxil_module *m, enum dxil_component_type comp_type) 7427ec681f3Smrg{ 7437ec681f3Smrg switch (comp_type) { 7447ec681f3Smrg case DXIL_COMP_TYPE_U32: return get_int32_type(m); 7457ec681f3Smrg case DXIL_COMP_TYPE_I32: return get_int32_type(m); 7467ec681f3Smrg case DXIL_COMP_TYPE_F32: return get_float32_type(m); 7477ec681f3Smrg case DXIL_COMP_TYPE_F64: return get_float64_type(m); 7487ec681f3Smrg case DXIL_COMP_TYPE_U16: return get_int16_type(m); 7497ec681f3Smrg case DXIL_COMP_TYPE_I16: return get_int16_type(m); 7507ec681f3Smrg case DXIL_COMP_TYPE_U64: return get_int64_type(m); 7517ec681f3Smrg case DXIL_COMP_TYPE_I64: return get_int64_type(m); 7527ec681f3Smrg case DXIL_COMP_TYPE_I1: return get_int1_type(m); 7537ec681f3Smrg 7547ec681f3Smrg case DXIL_COMP_TYPE_F16: 7557ec681f3Smrg default: 7567ec681f3Smrg unreachable("unexpected component type"); 7577ec681f3Smrg } 7587ec681f3Smrg} 7597ec681f3Smrg 7607ec681f3Smrgstatic const char * 7617ec681f3Smrgget_res_comp_type_name(enum dxil_component_type comp_type) 7627ec681f3Smrg{ 7637ec681f3Smrg switch (comp_type) { 7647ec681f3Smrg case DXIL_COMP_TYPE_F64: return "double"; 7657ec681f3Smrg case DXIL_COMP_TYPE_F32: return "float"; 7667ec681f3Smrg case DXIL_COMP_TYPE_I32: return "int"; 7677ec681f3Smrg case DXIL_COMP_TYPE_U32: return "uint"; 7687ec681f3Smrg case DXIL_COMP_TYPE_I64: return "int64"; 7697ec681f3Smrg case DXIL_COMP_TYPE_U64: return "uint64"; 7707ec681f3Smrg default: 7717ec681f3Smrg unreachable("unexpected resource component type"); 7727ec681f3Smrg } 7737ec681f3Smrg} 7747ec681f3Smrg 7757ec681f3Smrgstatic const char * 7767ec681f3Smrgget_res_dimension_type_name(enum dxil_resource_kind kind) 7777ec681f3Smrg{ 7787ec681f3Smrg switch (kind) { 7797ec681f3Smrg case DXIL_RESOURCE_KIND_TYPED_BUFFER: return "Buffer"; 7807ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE1D: return "Texture1D"; 7817ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE1D_ARRAY: return "Texture1DArray"; 7827ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE2D: return "Texture2D"; 7837ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE2DMS: return "Texture2DMS"; 7847ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE2D_ARRAY: return "Texture2DArray"; 7857ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY: return "Texture2DMSArray"; 7867ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE3D: return "Texture3D"; 7877ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURECUBE: return "TextureCube"; 7887ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURECUBE_ARRAY: return "TextureCubeArray"; 7897ec681f3Smrg default: 7907ec681f3Smrg unreachable("unexpected resource kind"); 7917ec681f3Smrg } 7927ec681f3Smrg} 7937ec681f3Smrg 7947ec681f3Smrgstatic const char * 7957ec681f3Smrgget_res_ms_postfix(enum dxil_resource_kind kind) 7967ec681f3Smrg{ 7977ec681f3Smrg switch (kind) { 7987ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE2DMS: 7997ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY: 8007ec681f3Smrg return ", 0"; 8017ec681f3Smrg 8027ec681f3Smrg default: 8037ec681f3Smrg return " "; 8047ec681f3Smrg } 8057ec681f3Smrg} 8067ec681f3Smrgconst struct dxil_type * 8077ec681f3Smrgdxil_module_get_res_type(struct dxil_module *m, enum dxil_resource_kind kind, 8087ec681f3Smrg enum dxil_component_type comp_type, bool readwrite) 8097ec681f3Smrg{ 8107ec681f3Smrg switch (kind) { 8117ec681f3Smrg case DXIL_RESOURCE_KIND_TYPED_BUFFER: 8127ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE1D: 8137ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE1D_ARRAY: 8147ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE2D: 8157ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE2D_ARRAY: 8167ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE2DMS: 8177ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY: 8187ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURE3D: 8197ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURECUBE: 8207ec681f3Smrg case DXIL_RESOURCE_KIND_TEXTURECUBE_ARRAY: 8217ec681f3Smrg { 8227ec681f3Smrg const struct dxil_type *component_type = dxil_module_get_type_from_comp_type(m, comp_type); 8237ec681f3Smrg const struct dxil_type *vec_type = dxil_module_get_vector_type(m, component_type, 4); 8247ec681f3Smrg char class_name[64] = { 0 }; 8257ec681f3Smrg snprintf(class_name, 64, "class.%s%s<vector<%s, 4>%s>", 8267ec681f3Smrg readwrite ? "RW" : "", 8277ec681f3Smrg get_res_dimension_type_name(kind), 8287ec681f3Smrg get_res_comp_type_name(comp_type), 8297ec681f3Smrg get_res_ms_postfix(kind)); 8307ec681f3Smrg return dxil_module_get_struct_type(m, class_name, &vec_type, 1); 8317ec681f3Smrg } 8327ec681f3Smrg 8337ec681f3Smrg case DXIL_RESOURCE_KIND_RAW_BUFFER: 8347ec681f3Smrg { 8357ec681f3Smrg const struct dxil_type *component_type = dxil_module_get_int_type(m, 32); 8367ec681f3Smrg char class_name[64] = { 0 }; 8377ec681f3Smrg snprintf(class_name, 64, "struct.%sByteAddressBuffer", readwrite ? "RW" : ""); 8387ec681f3Smrg return dxil_module_get_struct_type(m, class_name, &component_type, 1); 8397ec681f3Smrg } 8407ec681f3Smrg 8417ec681f3Smrg default: 8427ec681f3Smrg unreachable("resource type not supported"); 8437ec681f3Smrg } 8447ec681f3Smrg} 8457ec681f3Smrg 8467ec681f3Smrgconst struct dxil_type * 8477ec681f3Smrgdxil_module_get_resret_type(struct dxil_module *m, enum overload_type overload) 8487ec681f3Smrg{ 8497ec681f3Smrg const struct dxil_type *overload_type = dxil_get_overload_type(m, overload); 8507ec681f3Smrg const struct dxil_type *int32_type = dxil_module_get_int_type(m, 32); 8517ec681f3Smrg const char *name; 8527ec681f3Smrg if (!overload_type) 8537ec681f3Smrg return NULL; 8547ec681f3Smrg 8557ec681f3Smrg const struct dxil_type *resret[] = 8567ec681f3Smrg { overload_type, overload_type, overload_type, overload_type, int32_type }; 8577ec681f3Smrg 8587ec681f3Smrg switch (overload) { 8597ec681f3Smrg case DXIL_I32: name = "dx.types.ResRet.i32"; break; 8607ec681f3Smrg case DXIL_I64: name = "dx.types.ResRet.i64"; break; 8617ec681f3Smrg case DXIL_F32: name = "dx.types.ResRet.f32"; break; 8627ec681f3Smrg case DXIL_F64: name = "dx.types.ResRet.f64"; break; 8637ec681f3Smrg default: 8647ec681f3Smrg unreachable("unexpected overload type"); 8657ec681f3Smrg } 8667ec681f3Smrg 8677ec681f3Smrg return dxil_module_get_struct_type(m, name, resret, 5); 8687ec681f3Smrg} 8697ec681f3Smrg 8707ec681f3Smrgconst struct dxil_type * 8717ec681f3Smrgdxil_module_get_dimret_type(struct dxil_module *m) 8727ec681f3Smrg{ 8737ec681f3Smrg const struct dxil_type *int32_type = dxil_module_get_int_type(m, 32); 8747ec681f3Smrg 8757ec681f3Smrg const struct dxil_type *dimret[] = 8767ec681f3Smrg { int32_type, int32_type, int32_type, int32_type }; 8777ec681f3Smrg 8787ec681f3Smrg return dxil_module_get_struct_type(m, "dx.types.Dimensions", dimret, 4); 8797ec681f3Smrg} 8807ec681f3Smrg 8817ec681f3Smrgconst struct dxil_type * 8827ec681f3Smrgdxil_module_add_function_type(struct dxil_module *m, 8837ec681f3Smrg const struct dxil_type *ret_type, 8847ec681f3Smrg const struct dxil_type **arg_types, 8857ec681f3Smrg size_t num_arg_types) 8867ec681f3Smrg{ 8877ec681f3Smrg struct dxil_type *type = create_type(m, TYPE_FUNCTION); 8887ec681f3Smrg if (type) { 8897ec681f3Smrg type->function_def.args.types = ralloc_array(type, 8907ec681f3Smrg struct dxil_type *, 8917ec681f3Smrg num_arg_types); 8927ec681f3Smrg if (!type->function_def.args.types) 8937ec681f3Smrg return NULL; 8947ec681f3Smrg 8957ec681f3Smrg memcpy(type->function_def.args.types, arg_types, 8967ec681f3Smrg sizeof(struct dxil_type *) * num_arg_types); 8977ec681f3Smrg type->function_def.args.num_types = num_arg_types; 8987ec681f3Smrg type->function_def.ret_type = ret_type; 8997ec681f3Smrg } 9007ec681f3Smrg return type; 9017ec681f3Smrg} 9027ec681f3Smrg 9037ec681f3Smrg 9047ec681f3Smrgenum type_codes { 9057ec681f3Smrg TYPE_CODE_NUMENTRY = 1, 9067ec681f3Smrg TYPE_CODE_VOID = 2, 9077ec681f3Smrg TYPE_CODE_FLOAT = 3, 9087ec681f3Smrg TYPE_CODE_DOUBLE = 4, 9097ec681f3Smrg TYPE_CODE_LABEL = 5, 9107ec681f3Smrg TYPE_CODE_OPAQUE = 6, 9117ec681f3Smrg TYPE_CODE_INTEGER = 7, 9127ec681f3Smrg TYPE_CODE_POINTER = 8, 9137ec681f3Smrg TYPE_CODE_FUNCTION_OLD = 9, 9147ec681f3Smrg TYPE_CODE_HALF = 10, 9157ec681f3Smrg TYPE_CODE_ARRAY = 11, 9167ec681f3Smrg TYPE_CODE_VECTOR = 12, 9177ec681f3Smrg TYPE_CODE_X86_FP80 = 13, 9187ec681f3Smrg TYPE_CODE_FP128 = 14, 9197ec681f3Smrg TYPE_CODE_PPC_FP128 = 15, 9207ec681f3Smrg TYPE_CODE_METADATA = 16, 9217ec681f3Smrg TYPE_CODE_X86_MMX = 17, 9227ec681f3Smrg TYPE_CODE_STRUCT_ANON = 18, 9237ec681f3Smrg TYPE_CODE_STRUCT_NAME = 19, 9247ec681f3Smrg TYPE_CODE_STRUCT_NAMED = 20, 9257ec681f3Smrg TYPE_CODE_FUNCTION = 21 9267ec681f3Smrg}; 9277ec681f3Smrg 9287ec681f3Smrg#define LITERAL(x) { DXIL_OP_LITERAL, { (x) } } 9297ec681f3Smrg#define FIXED(x) { DXIL_OP_FIXED, { (x) } } 9307ec681f3Smrg#define VBR(x) { DXIL_OP_VBR, { (x) } } 9317ec681f3Smrg#define ARRAY { DXIL_OP_ARRAY, { 0 } } 9327ec681f3Smrg#define CHAR6 { DXIL_OP_CHAR6, { 0 } } 9337ec681f3Smrg#define BLOB { DXIL_OP_BLOB, { 0 } } 9347ec681f3Smrg 9357ec681f3Smrg#define TYPE_INDEX FIXED(32) 9367ec681f3Smrg 9377ec681f3Smrgenum type_table_abbrev_id { 9387ec681f3Smrg TYPE_TABLE_ABBREV_POINTER, 9397ec681f3Smrg TYPE_TABLE_ABBREV_FUNCTION, 9407ec681f3Smrg TYPE_TABLE_ABBREV_STRUCT_ANON, 9417ec681f3Smrg TYPE_TABLE_ABBREV_STRUCT_NAME, 9427ec681f3Smrg TYPE_TABLE_ABBREV_STRUCT_NAMED, 9437ec681f3Smrg TYPE_TABLE_ABBREV_ARRAY, 9447ec681f3Smrg TYPE_TABLE_ABBREV_VECTOR, 9457ec681f3Smrg}; 9467ec681f3Smrg 9477ec681f3Smrgstatic const struct dxil_abbrev 9487ec681f3Smrgtype_table_abbrevs[] = { 9497ec681f3Smrg [TYPE_TABLE_ABBREV_POINTER] = { 9507ec681f3Smrg { LITERAL(TYPE_CODE_POINTER), TYPE_INDEX, LITERAL(0) }, 3 9517ec681f3Smrg }, 9527ec681f3Smrg [TYPE_TABLE_ABBREV_FUNCTION] = { 9537ec681f3Smrg { LITERAL(TYPE_CODE_FUNCTION), FIXED(1), ARRAY, TYPE_INDEX }, 4 9547ec681f3Smrg }, 9557ec681f3Smrg [TYPE_TABLE_ABBREV_STRUCT_ANON] = { 9567ec681f3Smrg { LITERAL(TYPE_CODE_STRUCT_ANON), FIXED(1), ARRAY, TYPE_INDEX }, 4 9577ec681f3Smrg }, 9587ec681f3Smrg [TYPE_TABLE_ABBREV_STRUCT_NAME] = { 9597ec681f3Smrg { LITERAL(TYPE_CODE_STRUCT_NAME), ARRAY, CHAR6 }, 3 9607ec681f3Smrg }, 9617ec681f3Smrg [TYPE_TABLE_ABBREV_STRUCT_NAMED] = { 9627ec681f3Smrg { LITERAL(TYPE_CODE_STRUCT_NAMED), FIXED(1), ARRAY, TYPE_INDEX }, 4 9637ec681f3Smrg }, 9647ec681f3Smrg [TYPE_TABLE_ABBREV_ARRAY] = { 9657ec681f3Smrg { LITERAL(TYPE_CODE_ARRAY), VBR(8), TYPE_INDEX }, 3 9667ec681f3Smrg }, 9677ec681f3Smrg [TYPE_TABLE_ABBREV_VECTOR] = { 9687ec681f3Smrg { LITERAL(TYPE_CODE_VECTOR), VBR(8), TYPE_INDEX }, 3 9697ec681f3Smrg }, 9707ec681f3Smrg}; 9717ec681f3Smrg 9727ec681f3Smrgstatic bool 9737ec681f3Smrgemit_type_table_abbrev_record(struct dxil_module *m, 9747ec681f3Smrg enum type_table_abbrev_id abbrev, 9757ec681f3Smrg const uint64_t *data, size_t size) 9767ec681f3Smrg{ 9777ec681f3Smrg assert(abbrev < ARRAY_SIZE(type_table_abbrevs)); 9787ec681f3Smrg return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV, 9797ec681f3Smrg type_table_abbrevs + abbrev, data, size); 9807ec681f3Smrg} 9817ec681f3Smrg 9827ec681f3Smrgenum constant_code { 9837ec681f3Smrg CST_CODE_SETTYPE = 1, 9847ec681f3Smrg CST_CODE_NULL = 2, 9857ec681f3Smrg CST_CODE_UNDEF = 3, 9867ec681f3Smrg CST_CODE_INTEGER = 4, 9877ec681f3Smrg CST_CODE_WIDE_INTEGER = 5, 9887ec681f3Smrg CST_CODE_FLOAT = 6, 9897ec681f3Smrg CST_CODE_AGGREGATE = 7, 9907ec681f3Smrg CST_CODE_STRING = 8, 9917ec681f3Smrg CST_CODE_CSTRING = 9, 9927ec681f3Smrg CST_CODE_CE_BINOP = 10, 9937ec681f3Smrg CST_CODE_CE_CAST = 11, 9947ec681f3Smrg CST_CODE_CE_GEP = 12, 9957ec681f3Smrg CST_CODE_CE_SELECT = 13, 9967ec681f3Smrg CST_CODE_CE_EXTRACTELT = 14, 9977ec681f3Smrg CST_CODE_CE_INSERTELT = 15, 9987ec681f3Smrg CST_CODE_CE_SHUFFLEVEC = 16, 9997ec681f3Smrg CST_CODE_CE_CMP = 17, 10007ec681f3Smrg CST_CODE_INLINEASM_OLD = 18, 10017ec681f3Smrg CST_CODE_CE_SHUFVEC_EX = 19, 10027ec681f3Smrg CST_CODE_CE_INBOUNDS_GEP = 20, 10037ec681f3Smrg CST_CODE_BLOCKADDRESS = 21, 10047ec681f3Smrg CST_CODE_DATA = 22, 10057ec681f3Smrg CST_CODE_INLINEASM = 23 10067ec681f3Smrg}; 10077ec681f3Smrg 10087ec681f3Smrgenum const_abbrev_id { 10097ec681f3Smrg CONST_ABBREV_SETTYPE, 10107ec681f3Smrg CONST_ABBREV_INTEGER, 10117ec681f3Smrg CONST_ABBREV_CE_CAST, 10127ec681f3Smrg CONST_ABBREV_NULL, 10137ec681f3Smrg}; 10147ec681f3Smrg 10157ec681f3Smrgstatic const struct dxil_abbrev 10167ec681f3Smrgconst_abbrevs[] = { 10177ec681f3Smrg [CONST_ABBREV_SETTYPE] = { { LITERAL(CST_CODE_SETTYPE), TYPE_INDEX }, 2 }, 10187ec681f3Smrg [CONST_ABBREV_INTEGER] = { { LITERAL(CST_CODE_INTEGER), VBR(8) }, 2 }, 10197ec681f3Smrg [CONST_ABBREV_CE_CAST] = { 10207ec681f3Smrg { LITERAL(CST_CODE_CE_CAST), FIXED(4), TYPE_INDEX, VBR(8) }, 4 10217ec681f3Smrg }, 10227ec681f3Smrg [CONST_ABBREV_NULL] = { { LITERAL(CST_CODE_NULL) }, 1 }, 10237ec681f3Smrg}; 10247ec681f3Smrg 10257ec681f3Smrgstatic bool 10267ec681f3Smrgemit_const_abbrev_record(struct dxil_module *m, enum const_abbrev_id abbrev, 10277ec681f3Smrg const uint64_t *data, size_t size) 10287ec681f3Smrg{ 10297ec681f3Smrg assert(abbrev < ARRAY_SIZE(const_abbrevs)); 10307ec681f3Smrg 10317ec681f3Smrg return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV, 10327ec681f3Smrg const_abbrevs + abbrev, data, size); 10337ec681f3Smrg} 10347ec681f3Smrg 10357ec681f3Smrgenum function_code { 10367ec681f3Smrg FUNC_CODE_DECLAREBLOCKS = 1, 10377ec681f3Smrg FUNC_CODE_INST_BINOP = 2, 10387ec681f3Smrg FUNC_CODE_INST_CAST = 3, 10397ec681f3Smrg FUNC_CODE_INST_GEP_OLD = 4, 10407ec681f3Smrg FUNC_CODE_INST_SELECT = 5, 10417ec681f3Smrg FUNC_CODE_INST_EXTRACTELT = 6, 10427ec681f3Smrg FUNC_CODE_INST_INSERTELT = 7, 10437ec681f3Smrg FUNC_CODE_INST_SHUFFLEVEC = 8, 10447ec681f3Smrg FUNC_CODE_INST_CMP = 9, 10457ec681f3Smrg FUNC_CODE_INST_RET = 10, 10467ec681f3Smrg FUNC_CODE_INST_BR = 11, 10477ec681f3Smrg FUNC_CODE_INST_SWITCH = 12, 10487ec681f3Smrg FUNC_CODE_INST_INVOKE = 13, 10497ec681f3Smrg /* 14: unused */ 10507ec681f3Smrg FUNC_CODE_INST_UNREACHABLE = 15, 10517ec681f3Smrg FUNC_CODE_INST_PHI = 16, 10527ec681f3Smrg /* 17-18: unused */ 10537ec681f3Smrg FUNC_CODE_INST_ALLOCA = 19, 10547ec681f3Smrg FUNC_CODE_INST_LOAD = 20, 10557ec681f3Smrg /* 21-22: unused */ 10567ec681f3Smrg FUNC_CODE_INST_VAARG = 23, 10577ec681f3Smrg FUNC_CODE_INST_STORE_OLD = 24, 10587ec681f3Smrg /* 25: unused */ 10597ec681f3Smrg FUNC_CODE_INST_EXTRACTVAL = 26, 10607ec681f3Smrg FUNC_CODE_INST_INSERTVAL = 27, 10617ec681f3Smrg FUNC_CODE_INST_CMP2 = 28, 10627ec681f3Smrg FUNC_CODE_INST_VSELECT = 29, 10637ec681f3Smrg FUNC_CODE_INST_INBOUNDS_GEP_OLD = 30, 10647ec681f3Smrg FUNC_CODE_INST_INDIRECTBR = 31, 10657ec681f3Smrg /* 32: unused */ 10667ec681f3Smrg FUNC_CODE_DEBUG_LOC_AGAIN = 33, 10677ec681f3Smrg FUNC_CODE_INST_CALL = 34, 10687ec681f3Smrg FUNC_CODE_DEBUG_LOC = 35, 10697ec681f3Smrg FUNC_CODE_INST_FENCE = 36, 10707ec681f3Smrg FUNC_CODE_INST_CMPXCHG_OLD = 37, 10717ec681f3Smrg FUNC_CODE_INST_ATOMICRMW = 38, 10727ec681f3Smrg FUNC_CODE_INST_RESUME = 39, 10737ec681f3Smrg FUNC_CODE_INST_LANDINGPAD_OLD = 40, 10747ec681f3Smrg FUNC_CODE_INST_LOADATOMIC = 41, 10757ec681f3Smrg FUNC_CODE_INST_STOREATOMIC_OLD = 42, 10767ec681f3Smrg FUNC_CODE_INST_GEP = 43, 10777ec681f3Smrg FUNC_CODE_INST_STORE = 44, 10787ec681f3Smrg FUNC_CODE_INST_STOREATOMIC = 45, 10797ec681f3Smrg FUNC_CODE_INST_CMPXCHG = 46, 10807ec681f3Smrg FUNC_CODE_INST_LANDINGPAD = 47, 10817ec681f3Smrg}; 10827ec681f3Smrg 10837ec681f3Smrgenum func_abbrev_id { 10847ec681f3Smrg FUNC_ABBREV_LOAD, 10857ec681f3Smrg FUNC_ABBREV_BINOP, 10867ec681f3Smrg FUNC_ABBREV_BINOP_FLAGS, 10877ec681f3Smrg FUNC_ABBREV_CAST, 10887ec681f3Smrg FUNC_ABBREV_RET_VOID, 10897ec681f3Smrg FUNC_ABBREV_RET_VAL, 10907ec681f3Smrg FUNC_ABBREV_UNREACHABLE, 10917ec681f3Smrg FUNC_ABBREV_GEP, 10927ec681f3Smrg}; 10937ec681f3Smrg 10947ec681f3Smrgstatic const struct dxil_abbrev 10957ec681f3Smrgfunc_abbrevs[] = { 10967ec681f3Smrg [FUNC_ABBREV_LOAD] = { 10977ec681f3Smrg { LITERAL(FUNC_CODE_INST_LOAD), VBR(6), TYPE_INDEX, VBR(4), 10987ec681f3Smrg FIXED(1) }, 5 10997ec681f3Smrg }, 11007ec681f3Smrg [FUNC_ABBREV_BINOP] = { 11017ec681f3Smrg { LITERAL(FUNC_CODE_INST_BINOP), VBR(6), VBR(6), FIXED(4) }, 4 11027ec681f3Smrg }, 11037ec681f3Smrg [FUNC_ABBREV_BINOP_FLAGS] = { 11047ec681f3Smrg { LITERAL(FUNC_CODE_INST_BINOP), VBR(6), VBR(6), FIXED(4), 11057ec681f3Smrg FIXED(7) }, 5 11067ec681f3Smrg }, 11077ec681f3Smrg [FUNC_ABBREV_CAST] = { 11087ec681f3Smrg { LITERAL(FUNC_CODE_INST_CAST), VBR(6), TYPE_INDEX, FIXED(4) }, 4 11097ec681f3Smrg }, 11107ec681f3Smrg [FUNC_ABBREV_RET_VOID] = { { LITERAL(FUNC_CODE_INST_RET) }, 1 }, 11117ec681f3Smrg [FUNC_ABBREV_RET_VAL] = { { LITERAL(FUNC_CODE_INST_RET), VBR(6) }, 2 }, 11127ec681f3Smrg [FUNC_ABBREV_UNREACHABLE] = { 11137ec681f3Smrg { LITERAL(FUNC_CODE_INST_UNREACHABLE) }, 1 11147ec681f3Smrg }, 11157ec681f3Smrg [FUNC_ABBREV_GEP] = { 11167ec681f3Smrg { LITERAL(FUNC_CODE_INST_GEP), FIXED(1), TYPE_INDEX, ARRAY, 11177ec681f3Smrg VBR(6) }, 5 11187ec681f3Smrg }, 11197ec681f3Smrg}; 11207ec681f3Smrg 11217ec681f3Smrgstatic bool 11227ec681f3Smrgemit_func_abbrev_record(struct dxil_module *m, enum func_abbrev_id abbrev, 11237ec681f3Smrg const uint64_t *data, size_t size) 11247ec681f3Smrg{ 11257ec681f3Smrg assert(abbrev < ARRAY_SIZE(func_abbrevs)); 11267ec681f3Smrg return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV, 11277ec681f3Smrg func_abbrevs + abbrev, data, size); 11287ec681f3Smrg} 11297ec681f3Smrg 11307ec681f3Smrgstatic bool 11317ec681f3Smrgdefine_abbrev(struct dxil_module *m, const struct dxil_abbrev *a) 11327ec681f3Smrg{ 11337ec681f3Smrg if (!dxil_buffer_emit_abbrev_id(&m->buf, DXIL_DEFINE_ABBREV) || 11347ec681f3Smrg !dxil_buffer_emit_vbr_bits(&m->buf, a->num_operands, 5)) 11357ec681f3Smrg return false; 11367ec681f3Smrg 11377ec681f3Smrg for (int i = 0; i < a->num_operands; ++i) { 11387ec681f3Smrg unsigned is_literal = a->operands[i].type == DXIL_OP_LITERAL; 11397ec681f3Smrg if (!dxil_buffer_emit_bits(&m->buf, is_literal, 1)) 11407ec681f3Smrg return false; 11417ec681f3Smrg if (a->operands[i].type == DXIL_OP_LITERAL) { 11427ec681f3Smrg if (!dxil_buffer_emit_vbr_bits(&m->buf, a->operands[i].value, 8)) 11437ec681f3Smrg return false; 11447ec681f3Smrg } else { 11457ec681f3Smrg if (!dxil_buffer_emit_bits(&m->buf, a->operands[i].type, 3)) 11467ec681f3Smrg return false; 11477ec681f3Smrg if (a->operands[i].type == DXIL_OP_FIXED) { 11487ec681f3Smrg if (!dxil_buffer_emit_vbr_bits(&m->buf, 11497ec681f3Smrg a->operands[i].encoding_data, 5)) 11507ec681f3Smrg return false; 11517ec681f3Smrg } else if (a->operands[i].type == DXIL_OP_VBR) { 11527ec681f3Smrg if (!dxil_buffer_emit_vbr_bits(&m->buf, 11537ec681f3Smrg a->operands[i].encoding_data, 5)) 11547ec681f3Smrg return false; 11557ec681f3Smrg } 11567ec681f3Smrg } 11577ec681f3Smrg } 11587ec681f3Smrg 11597ec681f3Smrg return true; 11607ec681f3Smrg} 11617ec681f3Smrg 11627ec681f3Smrgenum dxil_blockinfo_code { 11637ec681f3Smrg DXIL_BLOCKINFO_CODE_SETBID = 1, 11647ec681f3Smrg DXIL_BLOCKINFO_CODE_BLOCKNAME = 2, 11657ec681f3Smrg DXIL_BLOCKINFO_CODE_SETRECORDNAME = 3 11667ec681f3Smrg}; 11677ec681f3Smrg 11687ec681f3Smrgstatic bool 11697ec681f3Smrgswitch_to_block(struct dxil_module *m, uint32_t block) 11707ec681f3Smrg{ 11717ec681f3Smrg return emit_record_int(m, DXIL_BLOCKINFO_CODE_SETBID, block); 11727ec681f3Smrg} 11737ec681f3Smrg 11747ec681f3Smrgenum dxil_standard_block { 11757ec681f3Smrg DXIL_BLOCKINFO = 0, 11767ec681f3Smrg DXIL_FIRST_APPLICATION_BLOCK = 8 11777ec681f3Smrg}; 11787ec681f3Smrg 11797ec681f3Smrgenum dxil_llvm_block { 11807ec681f3Smrg DXIL_MODULE = DXIL_FIRST_APPLICATION_BLOCK, 11817ec681f3Smrg DXIL_PARAMATTR = DXIL_FIRST_APPLICATION_BLOCK + 1, 11827ec681f3Smrg DXIL_PARAMATTR_GROUP = DXIL_FIRST_APPLICATION_BLOCK + 2, 11837ec681f3Smrg DXIL_CONST_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 3, 11847ec681f3Smrg DXIL_FUNCTION_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 4, 11857ec681f3Smrg DXIL_VALUE_SYMTAB_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 6, 11867ec681f3Smrg DXIL_METADATA_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 7, 11877ec681f3Smrg DXIL_TYPE_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 9, 11887ec681f3Smrg}; 11897ec681f3Smrg 11907ec681f3Smrgenum value_symtab_code { 11917ec681f3Smrg VST_CODE_ENTRY = 1, 11927ec681f3Smrg VST_CODE_BBENTRY = 2 11937ec681f3Smrg}; 11947ec681f3Smrg 11957ec681f3Smrgenum value_symtab_abbrev_id { 11967ec681f3Smrg VST_ABBREV_ENTRY_8, 11977ec681f3Smrg VST_ABBREV_ENTRY_7, 11987ec681f3Smrg VST_ABBREV_ENTRY_6, 11997ec681f3Smrg VST_ABBREV_BBENTRY_6, 12007ec681f3Smrg}; 12017ec681f3Smrg 12027ec681f3Smrgstatic struct dxil_abbrev value_symtab_abbrevs[] = { 12037ec681f3Smrg [VST_ABBREV_ENTRY_8] = { { FIXED(3), VBR(8), ARRAY, FIXED(8) }, 4 }, 12047ec681f3Smrg [VST_ABBREV_ENTRY_7] = { 12057ec681f3Smrg { LITERAL(VST_CODE_ENTRY), VBR(8), ARRAY, FIXED(7), }, 4 12067ec681f3Smrg }, 12077ec681f3Smrg [VST_ABBREV_ENTRY_6] = { 12087ec681f3Smrg { LITERAL(VST_CODE_ENTRY), VBR(8), ARRAY, CHAR6, }, 4 12097ec681f3Smrg }, 12107ec681f3Smrg [VST_ABBREV_BBENTRY_6] = { 12117ec681f3Smrg { LITERAL(VST_CODE_BBENTRY), VBR(8), ARRAY, CHAR6, }, 4 12127ec681f3Smrg }, 12137ec681f3Smrg}; 12147ec681f3Smrg 12157ec681f3Smrgstatic bool 12167ec681f3Smrgemit_value_symtab_abbrevs(struct dxil_module *m) 12177ec681f3Smrg{ 12187ec681f3Smrg if (!switch_to_block(m, DXIL_VALUE_SYMTAB_BLOCK)) 12197ec681f3Smrg return false; 12207ec681f3Smrg 12217ec681f3Smrg for (int i = 0; i < ARRAY_SIZE(value_symtab_abbrevs); ++i) { 12227ec681f3Smrg if (!define_abbrev(m, value_symtab_abbrevs + i)) 12237ec681f3Smrg return false; 12247ec681f3Smrg } 12257ec681f3Smrg 12267ec681f3Smrg return true; 12277ec681f3Smrg} 12287ec681f3Smrg 12297ec681f3Smrgstatic bool 12307ec681f3Smrgemit_const_abbrevs(struct dxil_module *m) 12317ec681f3Smrg{ 12327ec681f3Smrg if (!switch_to_block(m, DXIL_CONST_BLOCK)) 12337ec681f3Smrg return false; 12347ec681f3Smrg 12357ec681f3Smrg for (int i = 0; i < ARRAY_SIZE(const_abbrevs); ++i) { 12367ec681f3Smrg if (!define_abbrev(m, const_abbrevs + i)) 12377ec681f3Smrg return false; 12387ec681f3Smrg } 12397ec681f3Smrg 12407ec681f3Smrg return true; 12417ec681f3Smrg} 12427ec681f3Smrg 12437ec681f3Smrgstatic bool 12447ec681f3Smrgemit_function_abbrevs(struct dxil_module *m) 12457ec681f3Smrg{ 12467ec681f3Smrg if (!switch_to_block(m, DXIL_FUNCTION_BLOCK)) 12477ec681f3Smrg return false; 12487ec681f3Smrg 12497ec681f3Smrg for (int i = 0; i < ARRAY_SIZE(func_abbrevs); ++i) { 12507ec681f3Smrg if (!define_abbrev(m, func_abbrevs + i)) 12517ec681f3Smrg return false; 12527ec681f3Smrg } 12537ec681f3Smrg 12547ec681f3Smrg return true; 12557ec681f3Smrg} 12567ec681f3Smrg 12577ec681f3Smrgstatic bool 12587ec681f3Smrgemit_blockinfo(struct dxil_module *m) 12597ec681f3Smrg{ 12607ec681f3Smrg return enter_subblock(m, DXIL_BLOCKINFO, 2) && 12617ec681f3Smrg emit_value_symtab_abbrevs(m) && 12627ec681f3Smrg emit_const_abbrevs(m) && 12637ec681f3Smrg emit_function_abbrevs(m) && 12647ec681f3Smrg exit_block(m); 12657ec681f3Smrg} 12667ec681f3Smrg 12677ec681f3Smrgenum attribute_codes { 12687ec681f3Smrg PARAMATTR_GRP_CODE_ENTRY = 3, 12697ec681f3Smrg PARAMATTR_CODE_ENTRY = 2 12707ec681f3Smrg}; 12717ec681f3Smrg 12727ec681f3Smrgstatic bool 12737ec681f3Smrgemit_attrib_group(struct dxil_module *m, int id, uint32_t slot, 12747ec681f3Smrg const struct dxil_attrib *attrs, size_t num_attrs) 12757ec681f3Smrg{ 12767ec681f3Smrg uint64_t record[64]; 12777ec681f3Smrg record[0] = id; 12787ec681f3Smrg record[1] = slot; 12797ec681f3Smrg size_t size = 2; 12807ec681f3Smrg 12817ec681f3Smrg for (int i = 0; i < num_attrs; ++i) { 12827ec681f3Smrg switch (attrs[i].type) { 12837ec681f3Smrg case DXIL_ATTR_ENUM: 12847ec681f3Smrg assert(size < ARRAY_SIZE(record) - 2); 12857ec681f3Smrg record[size++] = 0; 12867ec681f3Smrg record[size++] = attrs[i].kind; 12877ec681f3Smrg break; 12887ec681f3Smrg 12897ec681f3Smrg default: 12907ec681f3Smrg unreachable("unsupported attrib type"); 12917ec681f3Smrg } 12927ec681f3Smrg } 12937ec681f3Smrg 12947ec681f3Smrg return emit_record(m, PARAMATTR_GRP_CODE_ENTRY, record, size); 12957ec681f3Smrg} 12967ec681f3Smrg 12977ec681f3Smrgstatic bool 12987ec681f3Smrgemit_attrib_group_table(struct dxil_module *m) 12997ec681f3Smrg{ 13007ec681f3Smrg if (!enter_subblock(m, DXIL_PARAMATTR_GROUP, 3)) 13017ec681f3Smrg return false; 13027ec681f3Smrg 13037ec681f3Smrg struct attrib_set *as; 13047ec681f3Smrg int id = 1; 13057ec681f3Smrg LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) { 13067ec681f3Smrg if (!emit_attrib_group(m, id, UINT32_MAX, as->attrs, as->num_attrs)) 13077ec681f3Smrg return false; 13087ec681f3Smrg id++; 13097ec681f3Smrg } 13107ec681f3Smrg 13117ec681f3Smrg return exit_block(m); 13127ec681f3Smrg} 13137ec681f3Smrg 13147ec681f3Smrgstatic bool 13157ec681f3Smrgemit_attribute_table(struct dxil_module *m) 13167ec681f3Smrg{ 13177ec681f3Smrg if (!enter_subblock(m, DXIL_PARAMATTR, 3)) 13187ec681f3Smrg return false; 13197ec681f3Smrg 13207ec681f3Smrg struct attrib_set *as; 13217ec681f3Smrg int id = 1; 13227ec681f3Smrg LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) { 13237ec681f3Smrg if (!emit_record_int(m, PARAMATTR_CODE_ENTRY, id)) 13247ec681f3Smrg return false; 13257ec681f3Smrg id++; 13267ec681f3Smrg } 13277ec681f3Smrg 13287ec681f3Smrg return exit_block(m); 13297ec681f3Smrg} 13307ec681f3Smrg 13317ec681f3Smrgstatic bool 13327ec681f3Smrgemit_type_table_abbrevs(struct dxil_module *m) 13337ec681f3Smrg{ 13347ec681f3Smrg for (int i = 0; i < ARRAY_SIZE(type_table_abbrevs); ++i) { 13357ec681f3Smrg if (!define_abbrev(m, type_table_abbrevs + i)) 13367ec681f3Smrg return false; 13377ec681f3Smrg } 13387ec681f3Smrg 13397ec681f3Smrg return true; 13407ec681f3Smrg} 13417ec681f3Smrg 13427ec681f3Smrgstatic bool 13437ec681f3Smrgemit_float_type(struct dxil_module *m, unsigned bit_size) 13447ec681f3Smrg{ 13457ec681f3Smrg switch (bit_size) { 13467ec681f3Smrg case 16: return emit_record(m, TYPE_CODE_HALF, NULL, 0); 13477ec681f3Smrg case 32: return emit_record(m, TYPE_CODE_FLOAT, NULL, 0); 13487ec681f3Smrg case 64: return emit_record(m, TYPE_CODE_DOUBLE, NULL, 0); 13497ec681f3Smrg default: 13507ec681f3Smrg unreachable("unexpected bit_size for float type"); 13517ec681f3Smrg } 13527ec681f3Smrg} 13537ec681f3Smrg 13547ec681f3Smrgstatic bool 13557ec681f3Smrgemit_pointer_type(struct dxil_module *m, int type_index) 13567ec681f3Smrg{ 13577ec681f3Smrg uint64_t data[] = { TYPE_CODE_POINTER, type_index, 0 }; 13587ec681f3Smrg return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_POINTER, 13597ec681f3Smrg data, ARRAY_SIZE(data)); 13607ec681f3Smrg} 13617ec681f3Smrg 13627ec681f3Smrgstatic bool 13637ec681f3Smrgemit_struct_name(struct dxil_module *m, const char *name) 13647ec681f3Smrg{ 13657ec681f3Smrg uint64_t temp[256]; 13667ec681f3Smrg assert(strlen(name) < ARRAY_SIZE(temp)); 13677ec681f3Smrg 13687ec681f3Smrg for (int i = 0; i < strlen(name); ++i) 13697ec681f3Smrg temp[i] = name[i]; 13707ec681f3Smrg 13717ec681f3Smrg return emit_record(m, TYPE_CODE_STRUCT_NAME, temp, strlen(name)); 13727ec681f3Smrg} 13737ec681f3Smrg 13747ec681f3Smrgstatic bool 13757ec681f3Smrgemit_struct_name_char6(struct dxil_module *m, const char *name) 13767ec681f3Smrg{ 13777ec681f3Smrg uint64_t temp[256]; 13787ec681f3Smrg assert(strlen(name) < ARRAY_SIZE(temp) - 1); 13797ec681f3Smrg 13807ec681f3Smrg temp[0] = TYPE_CODE_STRUCT_NAME; 13817ec681f3Smrg for (int i = 0; i < strlen(name); ++i) 13827ec681f3Smrg temp[i + 1] = name[i]; 13837ec681f3Smrg 13847ec681f3Smrg return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_STRUCT_NAME, 13857ec681f3Smrg temp, 1 + strlen(name)); 13867ec681f3Smrg} 13877ec681f3Smrg 13887ec681f3Smrgstatic bool 13897ec681f3Smrgemit_struct_type(struct dxil_module *m, const struct dxil_type *type) 13907ec681f3Smrg{ 13917ec681f3Smrg enum type_table_abbrev_id abbrev = TYPE_TABLE_ABBREV_STRUCT_ANON; 13927ec681f3Smrg enum type_codes type_code = TYPE_CODE_STRUCT_ANON; 13937ec681f3Smrg if (type->struct_def.name) { 13947ec681f3Smrg abbrev = TYPE_TABLE_ABBREV_STRUCT_NAMED; 13957ec681f3Smrg type_code = TYPE_CODE_STRUCT_NAMED; 13967ec681f3Smrg if (is_char6_string(type->struct_def.name)) { 13977ec681f3Smrg if (!emit_struct_name_char6(m, type->struct_def.name)) 13987ec681f3Smrg return false; 13997ec681f3Smrg } else { 14007ec681f3Smrg if (!emit_struct_name(m, type->struct_def.name)) 14017ec681f3Smrg return false; 14027ec681f3Smrg } 14037ec681f3Smrg } 14047ec681f3Smrg 14057ec681f3Smrg uint64_t temp[256]; 14067ec681f3Smrg assert(type->struct_def.elem.num_types < ARRAY_SIZE(temp) - 2); 14077ec681f3Smrg temp[0] = type_code; 14087ec681f3Smrg temp[1] = 0; /* packed */ 14097ec681f3Smrg for (int i = 0; i < type->struct_def.elem.num_types; ++i) { 14107ec681f3Smrg assert(type->struct_def.elem.types[i]->id >= 0); 14117ec681f3Smrg temp[2 + i] = type->struct_def.elem.types[i]->id; 14127ec681f3Smrg } 14137ec681f3Smrg 14147ec681f3Smrg return emit_type_table_abbrev_record(m, abbrev, temp, 14157ec681f3Smrg 2 + type->struct_def.elem.num_types); 14167ec681f3Smrg} 14177ec681f3Smrg 14187ec681f3Smrgstatic bool 14197ec681f3Smrgemit_array_type(struct dxil_module *m, const struct dxil_type *type) 14207ec681f3Smrg{ 14217ec681f3Smrg assert(type->array_or_vector_def.elem_type->id >= 0); 14227ec681f3Smrg uint64_t data[] = { 14237ec681f3Smrg TYPE_CODE_ARRAY, 14247ec681f3Smrg type->array_or_vector_def.num_elems, 14257ec681f3Smrg type->array_or_vector_def.elem_type->id 14267ec681f3Smrg }; 14277ec681f3Smrg return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_ARRAY, data, 14287ec681f3Smrg ARRAY_SIZE(data)); 14297ec681f3Smrg} 14307ec681f3Smrg 14317ec681f3Smrgstatic bool 14327ec681f3Smrgemit_function_type(struct dxil_module *m, const struct dxil_type *type) 14337ec681f3Smrg{ 14347ec681f3Smrg uint64_t temp[256]; 14357ec681f3Smrg assert(type->function_def.args.num_types < ARRAY_SIZE(temp) - 3); 14367ec681f3Smrg assert(type->function_def.ret_type->id >= 0); 14377ec681f3Smrg 14387ec681f3Smrg temp[0] = TYPE_CODE_FUNCTION; 14397ec681f3Smrg temp[1] = 0; // vararg 14407ec681f3Smrg temp[2] = type->function_def.ret_type->id; 14417ec681f3Smrg for (int i = 0; i < type->function_def.args.num_types; ++i) { 14427ec681f3Smrg assert(type->function_def.args.types[i]->id >= 0); 14437ec681f3Smrg temp[3 + i] = type->function_def.args.types[i]->id; 14447ec681f3Smrg } 14457ec681f3Smrg 14467ec681f3Smrg return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_FUNCTION, 14477ec681f3Smrg temp, 3 + type->function_def.args.num_types); 14487ec681f3Smrg} 14497ec681f3Smrg 14507ec681f3Smrgstatic bool 14517ec681f3Smrgemit_vector_type(struct dxil_module *m, const struct dxil_type *type) 14527ec681f3Smrg{ 14537ec681f3Smrg uint64_t temp[3]; 14547ec681f3Smrg temp[0] = TYPE_CODE_VECTOR; 14557ec681f3Smrg temp[1] = type->array_or_vector_def.num_elems; 14567ec681f3Smrg temp[2] = type->array_or_vector_def.elem_type->id; 14577ec681f3Smrg 14587ec681f3Smrg return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_VECTOR , temp, 3); 14597ec681f3Smrg} 14607ec681f3Smrg 14617ec681f3Smrgstatic bool 14627ec681f3Smrgemit_metadata_type(struct dxil_module *m) 14637ec681f3Smrg{ 14647ec681f3Smrg return emit_record(m, TYPE_CODE_METADATA, NULL, 0); 14657ec681f3Smrg} 14667ec681f3Smrg 14677ec681f3Smrgstatic bool 14687ec681f3Smrgemit_type(struct dxil_module *m, struct dxil_type *type) 14697ec681f3Smrg{ 14707ec681f3Smrg switch (type->type) { 14717ec681f3Smrg case TYPE_VOID: 14727ec681f3Smrg return emit_record(m, TYPE_CODE_VOID, NULL, 0); 14737ec681f3Smrg 14747ec681f3Smrg case TYPE_INTEGER: 14757ec681f3Smrg return emit_record_int(m, TYPE_CODE_INTEGER, type->int_bits); 14767ec681f3Smrg 14777ec681f3Smrg case TYPE_FLOAT: 14787ec681f3Smrg return emit_float_type(m, type->float_bits); 14797ec681f3Smrg 14807ec681f3Smrg case TYPE_POINTER: 14817ec681f3Smrg return emit_pointer_type(m, type->ptr_target_type->id); 14827ec681f3Smrg 14837ec681f3Smrg case TYPE_STRUCT: 14847ec681f3Smrg return emit_struct_type(m, type); 14857ec681f3Smrg 14867ec681f3Smrg case TYPE_ARRAY: 14877ec681f3Smrg return emit_array_type(m, type); 14887ec681f3Smrg 14897ec681f3Smrg case TYPE_FUNCTION: 14907ec681f3Smrg return emit_function_type(m, type); 14917ec681f3Smrg 14927ec681f3Smrg case TYPE_VECTOR: 14937ec681f3Smrg return emit_vector_type(m, type); 14947ec681f3Smrg 14957ec681f3Smrg default: 14967ec681f3Smrg unreachable("unexpected type->type"); 14977ec681f3Smrg } 14987ec681f3Smrg} 14997ec681f3Smrg 15007ec681f3Smrgstatic bool 15017ec681f3Smrgemit_type_table(struct dxil_module *m) 15027ec681f3Smrg{ 15037ec681f3Smrg if (!enter_subblock(m, DXIL_TYPE_BLOCK, 4) || 15047ec681f3Smrg !emit_type_table_abbrevs(m) || 15057ec681f3Smrg !emit_record_int(m, 1, 1 + list_length(&m->type_list))) 15067ec681f3Smrg return false; 15077ec681f3Smrg 15087ec681f3Smrg list_for_each_entry(struct dxil_type, type, &m->type_list, head) { 15097ec681f3Smrg if (!emit_type(m, type)) 15107ec681f3Smrg return false; 15117ec681f3Smrg } 15127ec681f3Smrg 15137ec681f3Smrg return emit_metadata_type(m) && 15147ec681f3Smrg exit_block(m); 15157ec681f3Smrg} 15167ec681f3Smrg 15177ec681f3Smrgstatic struct dxil_const * 15187ec681f3Smrgcreate_const(struct dxil_module *m, const struct dxil_type *type, bool undef) 15197ec681f3Smrg{ 15207ec681f3Smrg struct dxil_const *ret = ralloc_size(m->ralloc_ctx, 15217ec681f3Smrg sizeof(struct dxil_const)); 15227ec681f3Smrg if (ret) { 15237ec681f3Smrg ret->value.id = -1; 15247ec681f3Smrg ret->value.type = type; 15257ec681f3Smrg ret->undef = undef; 15267ec681f3Smrg list_addtail(&ret->head, &m->const_list); 15277ec681f3Smrg } 15287ec681f3Smrg return ret; 15297ec681f3Smrg} 15307ec681f3Smrg 15317ec681f3Smrgstatic const struct dxil_value * 15327ec681f3Smrgget_int_const(struct dxil_module *m, const struct dxil_type *type, 15337ec681f3Smrg intmax_t value) 15347ec681f3Smrg{ 15357ec681f3Smrg assert(type && type->type == TYPE_INTEGER); 15367ec681f3Smrg 15377ec681f3Smrg struct dxil_const *c; 15387ec681f3Smrg LIST_FOR_EACH_ENTRY(c, &m->const_list, head) { 15397ec681f3Smrg if (c->value.type != type || c->undef) 15407ec681f3Smrg continue; 15417ec681f3Smrg 15427ec681f3Smrg if (c->int_value == value) 15437ec681f3Smrg return &c->value; 15447ec681f3Smrg } 15457ec681f3Smrg 15467ec681f3Smrg c = create_const(m, type, false); 15477ec681f3Smrg if (!c) 15487ec681f3Smrg return NULL; 15497ec681f3Smrg 15507ec681f3Smrg c->int_value = value; 15517ec681f3Smrg return &c->value; 15527ec681f3Smrg} 15537ec681f3Smrg 15547ec681f3Smrgconst struct dxil_value * 15557ec681f3Smrgdxil_module_get_int1_const(struct dxil_module *m, bool value) 15567ec681f3Smrg{ 15577ec681f3Smrg const struct dxil_type *type = get_int1_type(m); 15587ec681f3Smrg if (!type) 15597ec681f3Smrg return NULL; 15607ec681f3Smrg 15617ec681f3Smrg return get_int_const(m, type, value); 15627ec681f3Smrg} 15637ec681f3Smrg 15647ec681f3Smrgconst struct dxil_value * 15657ec681f3Smrgdxil_module_get_int8_const(struct dxil_module *m, int8_t value) 15667ec681f3Smrg{ 15677ec681f3Smrg const struct dxil_type *type = get_int8_type(m); 15687ec681f3Smrg if (!type) 15697ec681f3Smrg return NULL; 15707ec681f3Smrg 15717ec681f3Smrg return get_int_const(m, type, value); 15727ec681f3Smrg} 15737ec681f3Smrg 15747ec681f3Smrgconst struct dxil_value * 15757ec681f3Smrgdxil_module_get_int16_const(struct dxil_module *m, int16_t value) 15767ec681f3Smrg{ 15777ec681f3Smrg const struct dxil_type *type = get_int16_type(m); 15787ec681f3Smrg if (!type) 15797ec681f3Smrg return NULL; 15807ec681f3Smrg 15817ec681f3Smrg return get_int_const(m, type, value); 15827ec681f3Smrg} 15837ec681f3Smrg 15847ec681f3Smrgconst struct dxil_value * 15857ec681f3Smrgdxil_module_get_int32_const(struct dxil_module *m, int32_t value) 15867ec681f3Smrg{ 15877ec681f3Smrg const struct dxil_type *type = get_int32_type(m); 15887ec681f3Smrg if (!type) 15897ec681f3Smrg return NULL; 15907ec681f3Smrg 15917ec681f3Smrg return get_int_const(m, type, value); 15927ec681f3Smrg} 15937ec681f3Smrg 15947ec681f3Smrgconst struct dxil_value * 15957ec681f3Smrgdxil_module_get_int64_const(struct dxil_module *m, int64_t value) 15967ec681f3Smrg{ 15977ec681f3Smrg const struct dxil_type *type = get_int64_type(m); 15987ec681f3Smrg if (!type) 15997ec681f3Smrg return NULL; 16007ec681f3Smrg 16017ec681f3Smrg return get_int_const(m, type, value); 16027ec681f3Smrg} 16037ec681f3Smrg 16047ec681f3Smrgconst struct dxil_value * 16057ec681f3Smrgdxil_module_get_int_const(struct dxil_module *m, intmax_t value, 16067ec681f3Smrg unsigned bit_size) 16077ec681f3Smrg{ 16087ec681f3Smrg switch (bit_size) { 16097ec681f3Smrg case 1: 16107ec681f3Smrg assert(value == 0 || value == 1); 16117ec681f3Smrg return dxil_module_get_int1_const(m, value); 16127ec681f3Smrg 16137ec681f3Smrg case 8: 16147ec681f3Smrg assert(INT8_MIN <= value && value <= INT8_MAX); 16157ec681f3Smrg return dxil_module_get_int8_const(m, value); 16167ec681f3Smrg 16177ec681f3Smrg case 16: 16187ec681f3Smrg assert(INT16_MIN <= value && value <= INT16_MAX); 16197ec681f3Smrg return dxil_module_get_int16_const(m, value); 16207ec681f3Smrg 16217ec681f3Smrg case 32: 16227ec681f3Smrg assert(INT32_MIN <= value && value <= INT32_MAX); 16237ec681f3Smrg return dxil_module_get_int32_const(m, value); 16247ec681f3Smrg 16257ec681f3Smrg case 64: 16267ec681f3Smrg assert(INT64_MIN <= value && value <= INT64_MAX); 16277ec681f3Smrg return dxil_module_get_int64_const(m, value); 16287ec681f3Smrg 16297ec681f3Smrg default: 16307ec681f3Smrg unreachable("unsupported bit-width"); 16317ec681f3Smrg } 16327ec681f3Smrg} 16337ec681f3Smrg 16347ec681f3Smrgconst struct dxil_value * 16357ec681f3Smrgdxil_module_get_float16_const(struct dxil_module *m, uint16_t value) 16367ec681f3Smrg{ 16377ec681f3Smrg const struct dxil_type *type = get_float16_type(m); 16387ec681f3Smrg if (!type) 16397ec681f3Smrg return NULL; 16407ec681f3Smrg 16417ec681f3Smrg struct dxil_const *c; 16427ec681f3Smrg LIST_FOR_EACH_ENTRY(c, &m->const_list, head) { 16437ec681f3Smrg if (c->value.type != type || c->undef) 16447ec681f3Smrg continue; 16457ec681f3Smrg 16467ec681f3Smrg if (c->int_value == (uintmax_t)value) 16477ec681f3Smrg return &c->value; 16487ec681f3Smrg } 16497ec681f3Smrg 16507ec681f3Smrg c = create_const(m, type, false); 16517ec681f3Smrg if (!c) 16527ec681f3Smrg return NULL; 16537ec681f3Smrg 16547ec681f3Smrg c->int_value = (uintmax_t)value; 16557ec681f3Smrg return &c->value; 16567ec681f3Smrg} 16577ec681f3Smrg 16587ec681f3Smrgconst struct dxil_value * 16597ec681f3Smrgdxil_module_get_float_const(struct dxil_module *m, float value) 16607ec681f3Smrg{ 16617ec681f3Smrg const struct dxil_type *type = get_float32_type(m); 16627ec681f3Smrg if (!type) 16637ec681f3Smrg return NULL; 16647ec681f3Smrg 16657ec681f3Smrg struct dxil_const *c; 16667ec681f3Smrg LIST_FOR_EACH_ENTRY(c, &m->const_list, head) { 16677ec681f3Smrg if (c->value.type != type || c->undef) 16687ec681f3Smrg continue; 16697ec681f3Smrg 16707ec681f3Smrg if (c->float_value == value) 16717ec681f3Smrg return &c->value; 16727ec681f3Smrg } 16737ec681f3Smrg 16747ec681f3Smrg c = create_const(m, type, false); 16757ec681f3Smrg if (!c) 16767ec681f3Smrg return NULL; 16777ec681f3Smrg 16787ec681f3Smrg c->float_value = value; 16797ec681f3Smrg return &c->value; 16807ec681f3Smrg} 16817ec681f3Smrg 16827ec681f3Smrgconst struct dxil_value * 16837ec681f3Smrgdxil_module_get_double_const(struct dxil_module *m, double value) 16847ec681f3Smrg{ 16857ec681f3Smrg const struct dxil_type *type = get_float64_type(m); 16867ec681f3Smrg if (!type) 16877ec681f3Smrg return NULL; 16887ec681f3Smrg 16897ec681f3Smrg struct dxil_const *c; 16907ec681f3Smrg LIST_FOR_EACH_ENTRY(c, &m->const_list, head) { 16917ec681f3Smrg if (c->value.type != type || c->undef) 16927ec681f3Smrg continue; 16937ec681f3Smrg 16947ec681f3Smrg if (c->float_value == value) 16957ec681f3Smrg return &c->value; 16967ec681f3Smrg } 16977ec681f3Smrg 16987ec681f3Smrg c = create_const(m, type, false); 16997ec681f3Smrg if (!c) 17007ec681f3Smrg return NULL; 17017ec681f3Smrg 17027ec681f3Smrg c->float_value = value; 17037ec681f3Smrg return &c->value; 17047ec681f3Smrg} 17057ec681f3Smrg 17067ec681f3Smrgconst struct dxil_value * 17077ec681f3Smrgdxil_module_get_array_const(struct dxil_module *m, const struct dxil_type *type, 17087ec681f3Smrg const struct dxil_value **values) 17097ec681f3Smrg{ 17107ec681f3Smrg assert(type->type == TYPE_ARRAY); 17117ec681f3Smrg unsigned int num_values = type->array_or_vector_def.num_elems; 17127ec681f3Smrg 17137ec681f3Smrg struct dxil_const *c; 17147ec681f3Smrg LIST_FOR_EACH_ENTRY(c, &m->const_list, head) { 17157ec681f3Smrg if (c->value.type != type || c->undef) 17167ec681f3Smrg continue; 17177ec681f3Smrg 17187ec681f3Smrg if (!memcmp(c->array_values, values, sizeof(*values) * num_values)) 17197ec681f3Smrg return &c->value; 17207ec681f3Smrg } 17217ec681f3Smrg 17227ec681f3Smrg c = create_const(m, type, false); 17237ec681f3Smrg if (!c) 17247ec681f3Smrg return NULL; 17257ec681f3Smrg void *tmp = 17267ec681f3Smrg ralloc_array(m->ralloc_ctx, struct dxil_value *, num_values); 17277ec681f3Smrg memcpy(tmp, values, sizeof(*values) * num_values); 17287ec681f3Smrg c->array_values = tmp; 17297ec681f3Smrg 17307ec681f3Smrg return &c->value; 17317ec681f3Smrg} 17327ec681f3Smrg 17337ec681f3Smrgconst struct dxil_value * 17347ec681f3Smrgdxil_module_get_undef(struct dxil_module *m, const struct dxil_type *type) 17357ec681f3Smrg{ 17367ec681f3Smrg assert(type != NULL); 17377ec681f3Smrg 17387ec681f3Smrg struct dxil_const *c; 17397ec681f3Smrg LIST_FOR_EACH_ENTRY(c, &m->const_list, head) { 17407ec681f3Smrg if (c->value.type != type) 17417ec681f3Smrg continue; 17427ec681f3Smrg 17437ec681f3Smrg if (c->undef) 17447ec681f3Smrg return &c->value; 17457ec681f3Smrg } 17467ec681f3Smrg 17477ec681f3Smrg c = create_const(m, type, true); 17487ec681f3Smrg return c ? &c->value : NULL; 17497ec681f3Smrg} 17507ec681f3Smrg 17517ec681f3Smrgenum dxil_module_code { 17527ec681f3Smrg DXIL_MODULE_CODE_VERSION = 1, 17537ec681f3Smrg DXIL_MODULE_CODE_TRIPLE = 2, 17547ec681f3Smrg DXIL_MODULE_CODE_DATALAYOUT = 3, 17557ec681f3Smrg DXIL_MODULE_CODE_ASM = 4, 17567ec681f3Smrg DXIL_MODULE_CODE_SECTIONNAME = 5, 17577ec681f3Smrg DXIL_MODULE_CODE_DEPLIB = 6, 17587ec681f3Smrg DXIL_MODULE_CODE_GLOBALVAR = 7, 17597ec681f3Smrg DXIL_MODULE_CODE_FUNCTION = 8, 17607ec681f3Smrg DXIL_MODULE_CODE_ALIAS = 9, 17617ec681f3Smrg DXIL_MODULE_CODE_PURGEVALS = 10, 17627ec681f3Smrg DXIL_MODULE_CODE_GCNAME = 11, 17637ec681f3Smrg DXIL_MODULE_CODE_COMDAT = 12, 17647ec681f3Smrg}; 17657ec681f3Smrg 17667ec681f3Smrgstatic bool 17677ec681f3Smrgemit_target_triple(struct dxil_module *m, const char *triple) 17687ec681f3Smrg{ 17697ec681f3Smrg uint64_t temp[256]; 17707ec681f3Smrg assert(strlen(triple) < ARRAY_SIZE(temp)); 17717ec681f3Smrg 17727ec681f3Smrg for (int i = 0; i < strlen(triple); ++i) 17737ec681f3Smrg temp[i] = triple[i]; 17747ec681f3Smrg 17757ec681f3Smrg return emit_record(m, DXIL_MODULE_CODE_TRIPLE, temp, strlen(triple)); 17767ec681f3Smrg} 17777ec681f3Smrg 17787ec681f3Smrgstatic bool 17797ec681f3Smrgemit_datalayout(struct dxil_module *m, const char *datalayout) 17807ec681f3Smrg{ 17817ec681f3Smrg uint64_t temp[256]; 17827ec681f3Smrg assert(strlen(datalayout) < ARRAY_SIZE(temp)); 17837ec681f3Smrg 17847ec681f3Smrg for (int i = 0; i < strlen(datalayout); ++i) 17857ec681f3Smrg temp[i] = datalayout[i]; 17867ec681f3Smrg 17877ec681f3Smrg return emit_record(m, DXIL_MODULE_CODE_DATALAYOUT, 17887ec681f3Smrg temp, strlen(datalayout)); 17897ec681f3Smrg} 17907ec681f3Smrg 17917ec681f3Smrgstatic const struct dxil_value * 17927ec681f3Smrgadd_gvar(struct dxil_module *m, const char *name, 17937ec681f3Smrg const struct dxil_type *type, const struct dxil_type *value_type, 17947ec681f3Smrg enum dxil_address_space as, int align, const struct dxil_value *value) 17957ec681f3Smrg{ 17967ec681f3Smrg struct dxil_gvar *gvar = ralloc_size(m->ralloc_ctx, 17977ec681f3Smrg sizeof(struct dxil_gvar)); 17987ec681f3Smrg if (!gvar) 17997ec681f3Smrg return NULL; 18007ec681f3Smrg 18017ec681f3Smrg gvar->type = type; 18027ec681f3Smrg gvar->name = ralloc_strdup(m->ralloc_ctx, name); 18037ec681f3Smrg gvar->as = as; 18047ec681f3Smrg gvar->align = align; 18057ec681f3Smrg gvar->constant = !!value; 18067ec681f3Smrg gvar->initializer = value; 18077ec681f3Smrg 18087ec681f3Smrg gvar->value.id = -1; 18097ec681f3Smrg gvar->value.type = value_type; 18107ec681f3Smrg 18117ec681f3Smrg list_addtail(&gvar->head, &m->gvar_list); 18127ec681f3Smrg return &gvar->value; 18137ec681f3Smrg} 18147ec681f3Smrg 18157ec681f3Smrgconst struct dxil_value * 18167ec681f3Smrgdxil_add_global_var(struct dxil_module *m, const char *name, 18177ec681f3Smrg const struct dxil_type *type, 18187ec681f3Smrg enum dxil_address_space as, int align, 18197ec681f3Smrg const struct dxil_value *value) 18207ec681f3Smrg{ 18217ec681f3Smrg return add_gvar(m, name, type, type, as, align, value); 18227ec681f3Smrg} 18237ec681f3Smrg 18247ec681f3Smrgconst struct dxil_value * 18257ec681f3Smrgdxil_add_global_ptr_var(struct dxil_module *m, const char *name, 18267ec681f3Smrg const struct dxil_type *type, 18277ec681f3Smrg enum dxil_address_space as, int align, 18287ec681f3Smrg const struct dxil_value *value) 18297ec681f3Smrg{ 18307ec681f3Smrg return add_gvar(m, name, type, dxil_module_get_pointer_type(m, type), 18317ec681f3Smrg as, align, value); 18327ec681f3Smrg} 18337ec681f3Smrg 18347ec681f3Smrgstatic struct dxil_func * 18357ec681f3Smrgadd_function(struct dxil_module *m, const char *name, 18367ec681f3Smrg const struct dxil_type *type, 18377ec681f3Smrg bool decl, unsigned attr_set) 18387ec681f3Smrg{ 18397ec681f3Smrg assert(type->type == TYPE_FUNCTION); 18407ec681f3Smrg 18417ec681f3Smrg struct dxil_func *func = ralloc_size(m->ralloc_ctx, 18427ec681f3Smrg sizeof(struct dxil_func)); 18437ec681f3Smrg if (!func) 18447ec681f3Smrg return NULL; 18457ec681f3Smrg 18467ec681f3Smrg func->name = ralloc_strdup(func, name); 18477ec681f3Smrg if (!func->name) { 18487ec681f3Smrg return NULL; 18497ec681f3Smrg } 18507ec681f3Smrg 18517ec681f3Smrg func->type = type; 18527ec681f3Smrg func->decl = decl; 18537ec681f3Smrg func->attr_set = attr_set; 18547ec681f3Smrg 18557ec681f3Smrg func->value.id = -1; 18567ec681f3Smrg func->value.type = type->function_def.ret_type; 18577ec681f3Smrg list_addtail(&func->head, &m->func_list); 18587ec681f3Smrg return func; 18597ec681f3Smrg} 18607ec681f3Smrg 18617ec681f3Smrgconst struct dxil_func * 18627ec681f3Smrgdxil_add_function_def(struct dxil_module *m, const char *name, 18637ec681f3Smrg const struct dxil_type *type) 18647ec681f3Smrg{ 18657ec681f3Smrg return add_function(m, name, type, false, 0); 18667ec681f3Smrg} 18677ec681f3Smrg 18687ec681f3Smrgstatic unsigned 18697ec681f3Smrgget_attr_set(struct dxil_module *m, enum dxil_attr_kind attr) 18707ec681f3Smrg{ 18717ec681f3Smrg struct dxil_attrib attrs[2] = { 18727ec681f3Smrg { DXIL_ATTR_ENUM, { DXIL_ATTR_KIND_NO_UNWIND } }, 18737ec681f3Smrg { DXIL_ATTR_ENUM, { attr } } 18747ec681f3Smrg }; 18757ec681f3Smrg 18767ec681f3Smrg int index = 1; 18777ec681f3Smrg struct attrib_set *as; 18787ec681f3Smrg LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) { 18797ec681f3Smrg if (!memcmp(as->attrs, attrs, sizeof(attrs))) 18807ec681f3Smrg return index; 18817ec681f3Smrg index++; 18827ec681f3Smrg } 18837ec681f3Smrg 18847ec681f3Smrg as = ralloc_size(m->ralloc_ctx, sizeof(struct attrib_set)); 18857ec681f3Smrg if (!as) 18867ec681f3Smrg return 0; 18877ec681f3Smrg 18887ec681f3Smrg memcpy(as->attrs, attrs, sizeof(attrs)); 18897ec681f3Smrg as->num_attrs = 1; 18907ec681f3Smrg if (attr != DXIL_ATTR_KIND_NONE) 18917ec681f3Smrg as->num_attrs++; 18927ec681f3Smrg 18937ec681f3Smrg list_addtail(&as->head, &m->attr_set_list); 18947ec681f3Smrg assert(list_length(&m->attr_set_list) == index); 18957ec681f3Smrg return index; 18967ec681f3Smrg} 18977ec681f3Smrg 18987ec681f3Smrgconst struct dxil_func * 18997ec681f3Smrgdxil_add_function_decl(struct dxil_module *m, const char *name, 19007ec681f3Smrg const struct dxil_type *type, 19017ec681f3Smrg enum dxil_attr_kind attr) 19027ec681f3Smrg{ 19037ec681f3Smrg unsigned attr_set = get_attr_set(m, attr); 19047ec681f3Smrg if (!attr_set) 19057ec681f3Smrg return NULL; 19067ec681f3Smrg 19077ec681f3Smrg return add_function(m, name, type, true, attr_set); 19087ec681f3Smrg} 19097ec681f3Smrg 19107ec681f3Smrgstatic bool 19117ec681f3Smrgemit_module_info_function(struct dxil_module *m, int type, bool declaration, 19127ec681f3Smrg int attr_set_index) 19137ec681f3Smrg{ 19147ec681f3Smrg uint64_t data[] = { 19157ec681f3Smrg type, 0/* address space */, declaration, 0/* linkage */, 19167ec681f3Smrg attr_set_index, 0/* alignment */, 0 /* section */, 0 /* visibility */, 19177ec681f3Smrg 0 /* GC */, 0 /* unnamed addr */, 0 /* prologue data */, 19187ec681f3Smrg 0 /* storage class */, 0 /* comdat */, 0 /* prefix-data */, 19197ec681f3Smrg 0 /* personality */ 19207ec681f3Smrg }; 19217ec681f3Smrg return emit_record(m, DXIL_MODULE_CODE_FUNCTION, data, ARRAY_SIZE(data)); 19227ec681f3Smrg} 19237ec681f3Smrg 19247ec681f3Smrgenum gvar_var_flags { 19257ec681f3Smrg GVAR_FLAG_CONSTANT = (1 << 0), 19267ec681f3Smrg GVAR_FLAG_EXPLICIT_TYPE = (1 << 1), 19277ec681f3Smrg}; 19287ec681f3Smrg 19297ec681f3Smrgenum gvar_var_linkage { 19307ec681f3Smrg GVAR_LINKAGE_EXTERNAL = 0, 19317ec681f3Smrg GVAR_LINKAGE_APPENDING = 2, 19327ec681f3Smrg GVAR_LINKAGE_INTERNAL = 3, 19337ec681f3Smrg GVAR_LINKAGE_EXTERNAL_WEAK = 7, 19347ec681f3Smrg GVAR_LINKAGE_COMMON = 8, 19357ec681f3Smrg GVAR_LINKAGE_PRIVATE = 9, 19367ec681f3Smrg GVAR_LINKAGE_AVAILABLE_EXTERNALLY = 12, 19377ec681f3Smrg GVAR_LINKAGE_WEAK_ANY = 16, 19387ec681f3Smrg GVAR_LINKAGE_WEAK_ODR = 17, 19397ec681f3Smrg GVAR_LINKAGE_LINK_ONCE_ODR = 19, 19407ec681f3Smrg}; 19417ec681f3Smrg 19427ec681f3Smrgstatic bool 19437ec681f3Smrgemit_module_info_global(struct dxil_module *m, const struct dxil_gvar *gvar, 19447ec681f3Smrg const struct dxil_abbrev *simple_gvar_abbr) 19457ec681f3Smrg{ 19467ec681f3Smrg uint64_t data[] = { 19477ec681f3Smrg DXIL_MODULE_CODE_GLOBALVAR, 19487ec681f3Smrg gvar->type->id, 19497ec681f3Smrg (gvar->as << 2) | GVAR_FLAG_EXPLICIT_TYPE | 19507ec681f3Smrg (gvar->constant ? GVAR_FLAG_CONSTANT : 0), 19517ec681f3Smrg gvar->initializer ? gvar->initializer->id + 1 : 0, 19527ec681f3Smrg (gvar->initializer ? GVAR_LINKAGE_INTERNAL : GVAR_LINKAGE_EXTERNAL), 19537ec681f3Smrg util_logbase2(gvar->align) + 1, 19547ec681f3Smrg 0 19557ec681f3Smrg }; 19567ec681f3Smrg return emit_record_abbrev(&m->buf, 4, simple_gvar_abbr, 19577ec681f3Smrg data, ARRAY_SIZE(data)); 19587ec681f3Smrg} 19597ec681f3Smrg 19607ec681f3Smrgstatic bool 19617ec681f3Smrgemit_module_info(struct dxil_module *m) 19627ec681f3Smrg{ 19637ec681f3Smrg struct dxil_gvar *gvar; 19647ec681f3Smrg int max_global_type = 0; 19657ec681f3Smrg int max_alignment = 0; 19667ec681f3Smrg LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) { 19677ec681f3Smrg assert(gvar->type->id >= 0); 19687ec681f3Smrg max_global_type = MAX2(max_global_type, gvar->type->id); 19697ec681f3Smrg max_alignment = MAX2(max_alignment, gvar->align); 19707ec681f3Smrg } 19717ec681f3Smrg 19727ec681f3Smrg struct dxil_abbrev simple_gvar_abbr = { 19737ec681f3Smrg { LITERAL(DXIL_MODULE_CODE_GLOBALVAR), 19747ec681f3Smrg FIXED(util_logbase2(max_global_type) + 1), 19757ec681f3Smrg VBR(6), VBR(6), FIXED(5), 19767ec681f3Smrg FIXED(util_logbase2(max_alignment) + 1), 19777ec681f3Smrg LITERAL(0) }, 7 19787ec681f3Smrg }; 19797ec681f3Smrg 19807ec681f3Smrg if (!emit_target_triple(m, "dxil-ms-dx") || 19817ec681f3Smrg !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") || 19827ec681f3Smrg !define_abbrev(m, &simple_gvar_abbr)) 19837ec681f3Smrg return false; 19847ec681f3Smrg 19857ec681f3Smrg LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) { 19867ec681f3Smrg assert(gvar->type->id >= 0); 19877ec681f3Smrg if (!emit_module_info_global(m, gvar, &simple_gvar_abbr)) 19887ec681f3Smrg return false; 19897ec681f3Smrg } 19907ec681f3Smrg 19917ec681f3Smrg struct dxil_func *func; 19927ec681f3Smrg LIST_FOR_EACH_ENTRY(func, &m->func_list, head) { 19937ec681f3Smrg assert(func->type->id >= 0); 19947ec681f3Smrg if (!emit_module_info_function(m, func->type->id, func->decl, 19957ec681f3Smrg func->attr_set)) 19967ec681f3Smrg return false; 19977ec681f3Smrg } 19987ec681f3Smrg 19997ec681f3Smrg return true; 20007ec681f3Smrg} 20017ec681f3Smrg 20027ec681f3Smrgstatic bool 20037ec681f3Smrgemit_module_const_abbrevs(struct dxil_module *m) 20047ec681f3Smrg{ 20057ec681f3Smrg /* these are unused for now, so let's not even record them */ 20067ec681f3Smrg struct dxil_abbrev abbrevs[] = { 20077ec681f3Smrg { { LITERAL(CST_CODE_AGGREGATE), ARRAY, FIXED(5) }, 3 }, 20087ec681f3Smrg { { LITERAL(CST_CODE_STRING), ARRAY, FIXED(8) }, 3 }, 20097ec681f3Smrg { { LITERAL(CST_CODE_CSTRING), ARRAY, FIXED(7) }, 3 }, 20107ec681f3Smrg { { LITERAL(CST_CODE_CSTRING), ARRAY, CHAR6 }, 3 }, 20117ec681f3Smrg }; 20127ec681f3Smrg 20137ec681f3Smrg for (int i = 0; i < ARRAY_SIZE(abbrevs); ++i) { 20147ec681f3Smrg if (!define_abbrev(m, abbrevs + i)) 20157ec681f3Smrg return false; 20167ec681f3Smrg } 20177ec681f3Smrg 20187ec681f3Smrg return true; 20197ec681f3Smrg} 20207ec681f3Smrg 20217ec681f3Smrgstatic bool 20227ec681f3Smrgemit_set_type(struct dxil_module *m, unsigned type_index) 20237ec681f3Smrg{ 20247ec681f3Smrg uint64_t data[] = { CST_CODE_SETTYPE, type_index }; 20257ec681f3Smrg return emit_const_abbrev_record(m, CONST_ABBREV_SETTYPE, 20267ec681f3Smrg data, ARRAY_SIZE(data)); 20277ec681f3Smrg} 20287ec681f3Smrg 20297ec681f3Smrgstatic bool 20307ec681f3Smrgemit_null_value(struct dxil_module *m) 20317ec681f3Smrg{ 20327ec681f3Smrg return emit_record_no_abbrev(&m->buf, CST_CODE_NULL, NULL, 0); 20337ec681f3Smrg} 20347ec681f3Smrg 20357ec681f3Smrgstatic bool 20367ec681f3Smrgemit_undef_value(struct dxil_module *m) 20377ec681f3Smrg{ 20387ec681f3Smrg return emit_record_no_abbrev(&m->buf, CST_CODE_UNDEF, NULL, 0); 20397ec681f3Smrg} 20407ec681f3Smrg 20417ec681f3Smrgstatic uint64_t 20427ec681f3Smrgencode_signed(int64_t value) 20437ec681f3Smrg{ 20447ec681f3Smrg return value >= 0 ? 20457ec681f3Smrg (value << 1) : 20467ec681f3Smrg ((-value << 1) | 1); 20477ec681f3Smrg} 20487ec681f3Smrg 20497ec681f3Smrgstatic bool 20507ec681f3Smrgemit_int_value(struct dxil_module *m, int64_t value) 20517ec681f3Smrg{ 20527ec681f3Smrg if (!value) 20537ec681f3Smrg return emit_null_value(m); 20547ec681f3Smrg 20557ec681f3Smrg uint64_t data[] = { CST_CODE_INTEGER, encode_signed(value) }; 20567ec681f3Smrg return emit_const_abbrev_record(m, CONST_ABBREV_INTEGER, 20577ec681f3Smrg data, ARRAY_SIZE(data)); 20587ec681f3Smrg} 20597ec681f3Smrg 20607ec681f3Smrgstatic bool 20617ec681f3Smrgemit_float16_value(struct dxil_module *m, uint16_t value) 20627ec681f3Smrg{ 20637ec681f3Smrg if (!value) 20647ec681f3Smrg return emit_null_value(m); 20657ec681f3Smrg uint64_t data = value; 20667ec681f3Smrg return emit_record_no_abbrev(&m->buf, CST_CODE_FLOAT, &data, 1); 20677ec681f3Smrg} 20687ec681f3Smrg 20697ec681f3Smrgstatic bool 20707ec681f3Smrgemit_float_value(struct dxil_module *m, float value) 20717ec681f3Smrg{ 20727ec681f3Smrg uint64_t data = fui(value); 20737ec681f3Smrg if (data == UINT32_C(0)) 20747ec681f3Smrg return emit_null_value(m); 20757ec681f3Smrg return emit_record_no_abbrev(&m->buf, CST_CODE_FLOAT, &data, 1); 20767ec681f3Smrg} 20777ec681f3Smrg 20787ec681f3Smrgstatic bool 20797ec681f3Smrgemit_double_value(struct dxil_module *m, double value) 20807ec681f3Smrg{ 20817ec681f3Smrg union di u; 20827ec681f3Smrg u.d = value; 20837ec681f3Smrg if (u.ui == UINT64_C(0)) 20847ec681f3Smrg return emit_null_value(m); 20857ec681f3Smrg return emit_record_no_abbrev(&m->buf, CST_CODE_FLOAT, &u.ui, 1); 20867ec681f3Smrg} 20877ec681f3Smrg 20887ec681f3Smrgstatic bool 20897ec681f3Smrgemit_aggregate_values(struct dxil_module *m, const struct dxil_value **values, 20907ec681f3Smrg int num_values) 20917ec681f3Smrg{ 20927ec681f3Smrg uint64_t *value_ids = ralloc_array(m->ralloc_ctx, uint64_t, num_values); 20937ec681f3Smrg int i; 20947ec681f3Smrg 20957ec681f3Smrg for (i = 0; i < num_values; i++) 20967ec681f3Smrg value_ids[i] = values[i]->id; 20977ec681f3Smrg 20987ec681f3Smrg return emit_record_no_abbrev(&m->buf, CST_CODE_AGGREGATE, value_ids, 20997ec681f3Smrg num_values); 21007ec681f3Smrg} 21017ec681f3Smrg 21027ec681f3Smrgstatic bool 21037ec681f3Smrgemit_consts(struct dxil_module *m) 21047ec681f3Smrg{ 21057ec681f3Smrg const struct dxil_type *curr_type = NULL; 21067ec681f3Smrg struct dxil_const *c; 21077ec681f3Smrg LIST_FOR_EACH_ENTRY(c, &m->const_list, head) { 21087ec681f3Smrg assert(c->value.id >= 0); 21097ec681f3Smrg assert(c->value.type != NULL); 21107ec681f3Smrg if (curr_type != c->value.type) { 21117ec681f3Smrg assert(c->value.type->id >= 0); 21127ec681f3Smrg if (!emit_set_type(m, c->value.type->id)) 21137ec681f3Smrg return false; 21147ec681f3Smrg curr_type = c->value.type; 21157ec681f3Smrg } 21167ec681f3Smrg 21177ec681f3Smrg if (c->undef) { 21187ec681f3Smrg if (!emit_undef_value(m)) 21197ec681f3Smrg return false; 21207ec681f3Smrg continue; 21217ec681f3Smrg } 21227ec681f3Smrg 21237ec681f3Smrg switch (curr_type->type) { 21247ec681f3Smrg case TYPE_INTEGER: 21257ec681f3Smrg if (!emit_int_value(m, c->int_value)) 21267ec681f3Smrg return false; 21277ec681f3Smrg break; 21287ec681f3Smrg 21297ec681f3Smrg case TYPE_FLOAT: 21307ec681f3Smrg switch (curr_type->float_bits) { 21317ec681f3Smrg case 16: 21327ec681f3Smrg if (!emit_float16_value(m, (uint16_t)(uintmax_t)c->int_value)) 21337ec681f3Smrg return false; 21347ec681f3Smrg break; 21357ec681f3Smrg case 32: 21367ec681f3Smrg if (!emit_float_value(m, c->float_value)) 21377ec681f3Smrg return false; 21387ec681f3Smrg break; 21397ec681f3Smrg case 64: 21407ec681f3Smrg if (!emit_double_value(m, c->float_value)) 21417ec681f3Smrg return false; 21427ec681f3Smrg break; 21437ec681f3Smrg default: 21447ec681f3Smrg unreachable("unexpected float_bits"); 21457ec681f3Smrg } 21467ec681f3Smrg break; 21477ec681f3Smrg 21487ec681f3Smrg case TYPE_ARRAY: 21497ec681f3Smrg if (!emit_aggregate_values(m, c->array_values, 21507ec681f3Smrg c->value.type->array_or_vector_def.num_elems)) 21517ec681f3Smrg return false; 21527ec681f3Smrg break; 21537ec681f3Smrg 21547ec681f3Smrg default: 21557ec681f3Smrg unreachable("unsupported constant type"); 21567ec681f3Smrg } 21577ec681f3Smrg } 21587ec681f3Smrg 21597ec681f3Smrg return true; 21607ec681f3Smrg} 21617ec681f3Smrg 21627ec681f3Smrgstatic bool 21637ec681f3Smrgemit_module_consts(struct dxil_module *m) 21647ec681f3Smrg{ 21657ec681f3Smrg return enter_subblock(m, DXIL_CONST_BLOCK, 4) && 21667ec681f3Smrg emit_module_const_abbrevs(m) && 21677ec681f3Smrg emit_consts(m) && 21687ec681f3Smrg exit_block(m); 21697ec681f3Smrg} 21707ec681f3Smrg 21717ec681f3Smrgstatic bool 21727ec681f3Smrgemit_value_symtab_abbrev_record(struct dxil_module *m, 21737ec681f3Smrg enum value_symtab_abbrev_id abbrev, 21747ec681f3Smrg const uint64_t *data, size_t size) 21757ec681f3Smrg{ 21767ec681f3Smrg assert(abbrev < ARRAY_SIZE(value_symtab_abbrevs)); 21777ec681f3Smrg return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV, 21787ec681f3Smrg value_symtab_abbrevs + abbrev, data, size); 21797ec681f3Smrg} 21807ec681f3Smrg 21817ec681f3Smrgstatic bool 21827ec681f3Smrgemit_symtab_entry(struct dxil_module *m, unsigned value, const char *name) 21837ec681f3Smrg{ 21847ec681f3Smrg uint64_t temp[256]; 21857ec681f3Smrg assert(strlen(name) < ARRAY_SIZE(temp) - 2); 21867ec681f3Smrg 21877ec681f3Smrg temp[0] = VST_CODE_ENTRY; 21887ec681f3Smrg temp[1] = value; 21897ec681f3Smrg for (int i = 0; i < strlen(name); ++i) 21907ec681f3Smrg temp[i + 2] = name[i]; 21917ec681f3Smrg 21927ec681f3Smrg enum value_symtab_abbrev_id abbrev = VST_ABBREV_ENTRY_8; 21937ec681f3Smrg if (is_char6_string(name)) 21947ec681f3Smrg abbrev = VST_ABBREV_ENTRY_6; 21957ec681f3Smrg else if (is_char7_string(name)) 21967ec681f3Smrg abbrev = VST_ABBREV_ENTRY_7; 21977ec681f3Smrg 21987ec681f3Smrg return emit_value_symtab_abbrev_record(m, abbrev, temp, 2 + strlen(name)); 21997ec681f3Smrg} 22007ec681f3Smrg 22017ec681f3Smrgstatic bool 22027ec681f3Smrgemit_value_symbol_table(struct dxil_module *m) 22037ec681f3Smrg{ 22047ec681f3Smrg if (!enter_subblock(m, DXIL_VALUE_SYMTAB_BLOCK, 4)) 22057ec681f3Smrg return false; 22067ec681f3Smrg 22077ec681f3Smrg struct dxil_func *func; 22087ec681f3Smrg LIST_FOR_EACH_ENTRY(func, &m->func_list, head) { 22097ec681f3Smrg if (!emit_symtab_entry(m, func->value.id, func->name)) 22107ec681f3Smrg return false; 22117ec681f3Smrg } 22127ec681f3Smrg struct dxil_gvar *gvar; 22137ec681f3Smrg LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) { 22147ec681f3Smrg if (!emit_symtab_entry(m, gvar->value.id, gvar->name)) 22157ec681f3Smrg return false; 22167ec681f3Smrg } 22177ec681f3Smrg return exit_block(m); 22187ec681f3Smrg} 22197ec681f3Smrg 22207ec681f3Smrgenum metadata_codes { 22217ec681f3Smrg METADATA_STRING = 1, 22227ec681f3Smrg METADATA_VALUE = 2, 22237ec681f3Smrg METADATA_NODE = 3, 22247ec681f3Smrg METADATA_NAME = 4, 22257ec681f3Smrg METADATA_KIND = 6, 22267ec681f3Smrg METADATA_NAMED_NODE = 10 22277ec681f3Smrg}; 22287ec681f3Smrg 22297ec681f3Smrgenum metadata_abbrev_id { 22307ec681f3Smrg METADATA_ABBREV_STRING, 22317ec681f3Smrg METADATA_ABBREV_NAME 22327ec681f3Smrg}; 22337ec681f3Smrg 22347ec681f3Smrgstatic const struct dxil_abbrev metadata_abbrevs[] = { 22357ec681f3Smrg [METADATA_ABBREV_STRING] = { 22367ec681f3Smrg { LITERAL(METADATA_STRING), ARRAY, FIXED(8) }, 3 22377ec681f3Smrg }, 22387ec681f3Smrg [METADATA_ABBREV_NAME] = { 22397ec681f3Smrg { LITERAL(METADATA_NAME), ARRAY, FIXED(8) }, 3 22407ec681f3Smrg }, 22417ec681f3Smrg}; 22427ec681f3Smrg 22437ec681f3Smrgstatic bool 22447ec681f3Smrgemit_metadata_abbrevs(struct dxil_module *m) 22457ec681f3Smrg{ 22467ec681f3Smrg for (int i = 0; i < ARRAY_SIZE(metadata_abbrevs); ++i) { 22477ec681f3Smrg if (!define_abbrev(m, metadata_abbrevs + i)) 22487ec681f3Smrg return false; 22497ec681f3Smrg } 22507ec681f3Smrg return true; 22517ec681f3Smrg} 22527ec681f3Smrg 22537ec681f3Smrgstatic struct dxil_mdnode * 22547ec681f3Smrgcreate_mdnode(struct dxil_module *m, enum mdnode_type type) 22557ec681f3Smrg{ 22567ec681f3Smrg struct dxil_mdnode *ret = rzalloc_size(m->ralloc_ctx, 22577ec681f3Smrg sizeof(struct dxil_mdnode)); 22587ec681f3Smrg if (ret) { 22597ec681f3Smrg ret->type = type; 22607ec681f3Smrg ret->id = list_length(&m->mdnode_list) + 1; /* zero is reserved for NULL nodes */ 22617ec681f3Smrg list_addtail(&ret->head, &m->mdnode_list); 22627ec681f3Smrg } 22637ec681f3Smrg return ret; 22647ec681f3Smrg} 22657ec681f3Smrg 22667ec681f3Smrgconst struct dxil_mdnode * 22677ec681f3Smrgdxil_get_metadata_string(struct dxil_module *m, const char *str) 22687ec681f3Smrg{ 22697ec681f3Smrg assert(str); 22707ec681f3Smrg 22717ec681f3Smrg struct dxil_mdnode *n; 22727ec681f3Smrg LIST_FOR_EACH_ENTRY(n, &m->mdnode_list, head) { 22737ec681f3Smrg if (n->type == MD_STRING && 22747ec681f3Smrg !strcmp(n->string, str)) 22757ec681f3Smrg return n; 22767ec681f3Smrg } 22777ec681f3Smrg 22787ec681f3Smrg n = create_mdnode(m, MD_STRING); 22797ec681f3Smrg if (n) { 22807ec681f3Smrg n->string = ralloc_strdup(n, str); 22817ec681f3Smrg if (!n->string) 22827ec681f3Smrg return NULL; 22837ec681f3Smrg } 22847ec681f3Smrg return n; 22857ec681f3Smrg} 22867ec681f3Smrg 22877ec681f3Smrgconst struct dxil_mdnode * 22887ec681f3Smrgdxil_get_metadata_value(struct dxil_module *m, const struct dxil_type *type, 22897ec681f3Smrg const struct dxil_value *value) 22907ec681f3Smrg{ 22917ec681f3Smrg struct dxil_mdnode *n; 22927ec681f3Smrg LIST_FOR_EACH_ENTRY(n, &m->mdnode_list, head) { 22937ec681f3Smrg if (n->type == MD_VALUE && 22947ec681f3Smrg n->value.type == type && 22957ec681f3Smrg n->value.value == value) 22967ec681f3Smrg return n; 22977ec681f3Smrg } 22987ec681f3Smrg 22997ec681f3Smrg n = create_mdnode(m, MD_VALUE); 23007ec681f3Smrg if (n) { 23017ec681f3Smrg n->value.type = type; 23027ec681f3Smrg n->value.value = value; 23037ec681f3Smrg } 23047ec681f3Smrg return n; 23057ec681f3Smrg} 23067ec681f3Smrg 23077ec681f3Smrgconst struct dxil_mdnode * 23087ec681f3Smrgdxil_get_metadata_func(struct dxil_module *m, const struct dxil_func *func) 23097ec681f3Smrg{ 23107ec681f3Smrg const struct dxil_type *ptr_type = 23117ec681f3Smrg dxil_module_get_pointer_type(m, func->type); 23127ec681f3Smrg return dxil_get_metadata_value(m, ptr_type, &func->value); 23137ec681f3Smrg} 23147ec681f3Smrg 23157ec681f3Smrgconst struct dxil_mdnode * 23167ec681f3Smrgdxil_get_metadata_node(struct dxil_module *m, 23177ec681f3Smrg const struct dxil_mdnode *subnodes[], 23187ec681f3Smrg size_t num_subnodes) 23197ec681f3Smrg{ 23207ec681f3Smrg struct dxil_mdnode *n; 23217ec681f3Smrg LIST_FOR_EACH_ENTRY(n, &m->mdnode_list, head) { 23227ec681f3Smrg if (n->type == MD_NODE && 23237ec681f3Smrg n->node.num_subnodes == num_subnodes && 23247ec681f3Smrg !memcmp(n->node.subnodes, subnodes, sizeof(struct dxil_mdnode *) * 23257ec681f3Smrg num_subnodes)) 23267ec681f3Smrg return n; 23277ec681f3Smrg } 23287ec681f3Smrg 23297ec681f3Smrg n = create_mdnode(m, MD_NODE); 23307ec681f3Smrg if (n) { 23317ec681f3Smrg void *tmp = ralloc_array(n, struct dxil_mdnode *, num_subnodes); 23327ec681f3Smrg if (!tmp) 23337ec681f3Smrg return NULL; 23347ec681f3Smrg 23357ec681f3Smrg memcpy(tmp, subnodes, sizeof(struct dxil_mdnode *) * num_subnodes); 23367ec681f3Smrg n->node.subnodes = tmp; 23377ec681f3Smrg n->node.num_subnodes = num_subnodes; 23387ec681f3Smrg } 23397ec681f3Smrg return n; 23407ec681f3Smrg} 23417ec681f3Smrg 23427ec681f3Smrgconst struct dxil_mdnode * 23437ec681f3Smrgdxil_get_metadata_int1(struct dxil_module *m, bool value) 23447ec681f3Smrg{ 23457ec681f3Smrg const struct dxil_type *type = get_int1_type(m); 23467ec681f3Smrg if (!type) 23477ec681f3Smrg return NULL; 23487ec681f3Smrg 23497ec681f3Smrg const struct dxil_value *const_value = get_int_const(m, type, value); 23507ec681f3Smrg if (!const_value) 23517ec681f3Smrg return NULL; 23527ec681f3Smrg 23537ec681f3Smrg return dxil_get_metadata_value(m, type, const_value); 23547ec681f3Smrg} 23557ec681f3Smrg 23567ec681f3Smrgconst struct dxil_mdnode * 23577ec681f3Smrgdxil_get_metadata_int8(struct dxil_module *m, int8_t value) 23587ec681f3Smrg{ 23597ec681f3Smrg const struct dxil_type *type = get_int8_type(m); 23607ec681f3Smrg if (!type) 23617ec681f3Smrg return NULL; 23627ec681f3Smrg 23637ec681f3Smrg const struct dxil_value *const_value = get_int_const(m, type, value); 23647ec681f3Smrg if (!const_value) 23657ec681f3Smrg return NULL; 23667ec681f3Smrg 23677ec681f3Smrg return dxil_get_metadata_value(m, type, const_value); 23687ec681f3Smrg} 23697ec681f3Smrg 23707ec681f3Smrgconst struct dxil_mdnode * 23717ec681f3Smrgdxil_get_metadata_int32(struct dxil_module *m, int32_t value) 23727ec681f3Smrg{ 23737ec681f3Smrg const struct dxil_type *type = get_int32_type(m); 23747ec681f3Smrg if (!type) 23757ec681f3Smrg return NULL; 23767ec681f3Smrg 23777ec681f3Smrg const struct dxil_value *const_value = get_int_const(m, type, value); 23787ec681f3Smrg if (!const_value) 23797ec681f3Smrg return NULL; 23807ec681f3Smrg 23817ec681f3Smrg return dxil_get_metadata_value(m, type, const_value); 23827ec681f3Smrg} 23837ec681f3Smrg 23847ec681f3Smrgconst struct dxil_mdnode * 23857ec681f3Smrgdxil_get_metadata_int64(struct dxil_module *m, int64_t value) 23867ec681f3Smrg{ 23877ec681f3Smrg const struct dxil_type *type = get_int64_type(m); 23887ec681f3Smrg if (!type) 23897ec681f3Smrg return NULL; 23907ec681f3Smrg 23917ec681f3Smrg const struct dxil_value *const_value = get_int_const(m, type, value); 23927ec681f3Smrg if (!const_value) 23937ec681f3Smrg return NULL; 23947ec681f3Smrg 23957ec681f3Smrg return dxil_get_metadata_value(m, type, const_value); 23967ec681f3Smrg} 23977ec681f3Smrg 23987ec681f3Smrgbool 23997ec681f3Smrgdxil_add_metadata_named_node(struct dxil_module *m, const char *name, 24007ec681f3Smrg const struct dxil_mdnode *subnodes[], 24017ec681f3Smrg size_t num_subnodes) 24027ec681f3Smrg{ 24037ec681f3Smrg struct dxil_named_node *n = ralloc_size(m->ralloc_ctx, 24047ec681f3Smrg sizeof(struct dxil_named_node)); 24057ec681f3Smrg if (!n) 24067ec681f3Smrg return false; 24077ec681f3Smrg 24087ec681f3Smrg n->name = ralloc_strdup(n, name); 24097ec681f3Smrg if (!n->name) 24107ec681f3Smrg return false; 24117ec681f3Smrg 24127ec681f3Smrg void *tmp = ralloc_array(n, struct dxil_mdnode *, num_subnodes); 24137ec681f3Smrg if (!tmp) 24147ec681f3Smrg return false; 24157ec681f3Smrg 24167ec681f3Smrg memcpy(tmp, subnodes, sizeof(struct dxil_mdnode *) * num_subnodes); 24177ec681f3Smrg n->subnodes = tmp; 24187ec681f3Smrg n->num_subnodes = num_subnodes; 24197ec681f3Smrg 24207ec681f3Smrg list_addtail(&n->head, &m->md_named_node_list); 24217ec681f3Smrg return true; 24227ec681f3Smrg} 24237ec681f3Smrg 24247ec681f3Smrgstatic bool 24257ec681f3Smrgemit_metadata_value(struct dxil_module *m, const struct dxil_type *type, 24267ec681f3Smrg const struct dxil_value *value) 24277ec681f3Smrg{ 24287ec681f3Smrg assert(type->id >= 0 && value->id >= 0); 24297ec681f3Smrg uint64_t data[2] = { type->id, value->id }; 24307ec681f3Smrg return emit_record(m, METADATA_VALUE, data, ARRAY_SIZE(data)); 24317ec681f3Smrg} 24327ec681f3Smrg 24337ec681f3Smrgstatic bool 24347ec681f3Smrgemit_metadata_abbrev_record(struct dxil_module *m, 24357ec681f3Smrg enum metadata_abbrev_id abbrev, 24367ec681f3Smrg const uint64_t *data, size_t size) 24377ec681f3Smrg{ 24387ec681f3Smrg assert(abbrev < ARRAY_SIZE(metadata_abbrevs)); 24397ec681f3Smrg return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV, 24407ec681f3Smrg metadata_abbrevs + abbrev, data, size); 24417ec681f3Smrg} 24427ec681f3Smrg 24437ec681f3Smrgstatic bool 24447ec681f3Smrgemit_metadata_string(struct dxil_module *m, const char *str) 24457ec681f3Smrg{ 24467ec681f3Smrg uint64_t data[256]; 24477ec681f3Smrg assert(strlen(str) < ARRAY_SIZE(data) - 1); 24487ec681f3Smrg data[0] = METADATA_STRING; 24497ec681f3Smrg for (size_t i = 0; i < strlen(str); ++i) 24507ec681f3Smrg data[i + 1] = str[i]; 24517ec681f3Smrg 24527ec681f3Smrg return emit_metadata_abbrev_record(m, METADATA_ABBREV_STRING, 24537ec681f3Smrg data, strlen(str) + 1); 24547ec681f3Smrg} 24557ec681f3Smrg 24567ec681f3Smrgstatic bool 24577ec681f3Smrgemit_metadata_node(struct dxil_module *m, 24587ec681f3Smrg const struct dxil_mdnode *subnodes[], 24597ec681f3Smrg size_t num_subnodes) 24607ec681f3Smrg{ 24617ec681f3Smrg uint64_t data[256]; 24627ec681f3Smrg assert(num_subnodes < ARRAY_SIZE(data)); 24637ec681f3Smrg for (size_t i = 0; i < num_subnodes; ++i) 24647ec681f3Smrg data[i] = subnodes[i] ? subnodes[i]->id : 0; 24657ec681f3Smrg 24667ec681f3Smrg return emit_record(m, METADATA_NODE, data, num_subnodes); 24677ec681f3Smrg} 24687ec681f3Smrg 24697ec681f3Smrgstatic bool 24707ec681f3Smrgemit_mdnode(struct dxil_module *m, struct dxil_mdnode *n) 24717ec681f3Smrg{ 24727ec681f3Smrg switch (n->type) { 24737ec681f3Smrg case MD_STRING: 24747ec681f3Smrg return emit_metadata_string(m, n->string); 24757ec681f3Smrg 24767ec681f3Smrg case MD_VALUE: 24777ec681f3Smrg return emit_metadata_value(m, n->value.type, n->value.value); 24787ec681f3Smrg 24797ec681f3Smrg case MD_NODE: 24807ec681f3Smrg return emit_metadata_node(m, n->node.subnodes, n->node.num_subnodes); 24817ec681f3Smrg 24827ec681f3Smrg default: 24837ec681f3Smrg unreachable("unexpected n->type"); 24847ec681f3Smrg } 24857ec681f3Smrg} 24867ec681f3Smrg 24877ec681f3Smrgstatic bool 24887ec681f3Smrgemit_metadata_nodes(struct dxil_module *m) 24897ec681f3Smrg{ 24907ec681f3Smrg list_for_each_entry(struct dxil_mdnode, n, &m->mdnode_list, head) { 24917ec681f3Smrg if (!emit_mdnode(m, n)) 24927ec681f3Smrg return false; 24937ec681f3Smrg } 24947ec681f3Smrg return true; 24957ec681f3Smrg} 24967ec681f3Smrg 24977ec681f3Smrgstatic bool 24987ec681f3Smrgemit_metadata_name(struct dxil_module *m, const char *name) 24997ec681f3Smrg{ 25007ec681f3Smrg uint64_t data[256]; 25017ec681f3Smrg assert(strlen(name) < ARRAY_SIZE(data) - 1); 25027ec681f3Smrg data[0] = METADATA_NAME; 25037ec681f3Smrg for (size_t i = 0; i < strlen(name); ++i) 25047ec681f3Smrg data[i + 1] = name[i]; 25057ec681f3Smrg 25067ec681f3Smrg return emit_metadata_abbrev_record(m, METADATA_ABBREV_NAME, 25077ec681f3Smrg data, strlen(name) + 1); 25087ec681f3Smrg} 25097ec681f3Smrg 25107ec681f3Smrgstatic bool 25117ec681f3Smrgemit_metadata_named_node(struct dxil_module *m, const char *name, 25127ec681f3Smrg const struct dxil_mdnode *subnodes[], 25137ec681f3Smrg size_t num_subnodes) 25147ec681f3Smrg{ 25157ec681f3Smrg uint64_t data[256]; 25167ec681f3Smrg assert(num_subnodes < ARRAY_SIZE(data)); 25177ec681f3Smrg for (size_t i = 0; i < num_subnodes; ++i) { 25187ec681f3Smrg assert(subnodes[i]->id > 0); /* NULL nodes not allowed */ 25197ec681f3Smrg data[i] = subnodes[i]->id - 1; 25207ec681f3Smrg } 25217ec681f3Smrg 25227ec681f3Smrg return emit_metadata_name(m, name) && 25237ec681f3Smrg emit_record(m, METADATA_NAMED_NODE, data, num_subnodes); 25247ec681f3Smrg} 25257ec681f3Smrg 25267ec681f3Smrgstatic bool 25277ec681f3Smrgemit_metadata_named_nodes(struct dxil_module *m) 25287ec681f3Smrg{ 25297ec681f3Smrg struct dxil_named_node *n; 25307ec681f3Smrg LIST_FOR_EACH_ENTRY(n, &m->md_named_node_list, head) { 25317ec681f3Smrg if (!emit_metadata_named_node(m, n->name, n->subnodes, 25327ec681f3Smrg n->num_subnodes)) 25337ec681f3Smrg return false; 25347ec681f3Smrg } 25357ec681f3Smrg return true; 25367ec681f3Smrg} 25377ec681f3Smrg 25387ec681f3Smrgstatic bool 25397ec681f3Smrgemit_metadata(struct dxil_module *m) 25407ec681f3Smrg{ 25417ec681f3Smrg return enter_subblock(m, DXIL_METADATA_BLOCK, 3) && 25427ec681f3Smrg emit_metadata_abbrevs(m) && 25437ec681f3Smrg emit_metadata_nodes(m) && 25447ec681f3Smrg emit_metadata_named_nodes(m) && 25457ec681f3Smrg exit_block(m); 25467ec681f3Smrg} 25477ec681f3Smrg 25487ec681f3Smrgstatic struct dxil_instr * 25497ec681f3Smrgcreate_instr(struct dxil_module *m, enum instr_type type, 25507ec681f3Smrg const struct dxil_type *ret_type) 25517ec681f3Smrg{ 25527ec681f3Smrg struct dxil_instr *ret = ralloc_size(m->ralloc_ctx, 25537ec681f3Smrg sizeof(struct dxil_instr)); 25547ec681f3Smrg if (ret) { 25557ec681f3Smrg ret->type = type; 25567ec681f3Smrg ret->value.id = -1; 25577ec681f3Smrg ret->value.type = ret_type; 25587ec681f3Smrg ret->has_value = false; 25597ec681f3Smrg list_addtail(&ret->head, &m->instr_list); 25607ec681f3Smrg } 25617ec681f3Smrg return ret; 25627ec681f3Smrg} 25637ec681f3Smrg 25647ec681f3Smrgstatic inline bool 25657ec681f3Smrglegal_arith_type(const struct dxil_type *type) 25667ec681f3Smrg{ 25677ec681f3Smrg switch (type->type) { 25687ec681f3Smrg case TYPE_INTEGER: 25697ec681f3Smrg return type->int_bits == 1 || 25707ec681f3Smrg type->int_bits == 16 || 25717ec681f3Smrg type->int_bits == 32 || 25727ec681f3Smrg type->int_bits == 64; 25737ec681f3Smrg 25747ec681f3Smrg case TYPE_FLOAT: 25757ec681f3Smrg return type->float_bits == 16 || 25767ec681f3Smrg type->float_bits == 32 || 25777ec681f3Smrg type->float_bits == 64; 25787ec681f3Smrg 25797ec681f3Smrg default: 25807ec681f3Smrg return false; 25817ec681f3Smrg } 25827ec681f3Smrg} 25837ec681f3Smrg 25847ec681f3Smrgconst struct dxil_value * 25857ec681f3Smrgdxil_emit_binop(struct dxil_module *m, enum dxil_bin_opcode opcode, 25867ec681f3Smrg const struct dxil_value *op0, const struct dxil_value *op1, 25877ec681f3Smrg enum dxil_opt_flags flags) 25887ec681f3Smrg{ 25897ec681f3Smrg assert(types_equal(op0->type, op1->type)); 25907ec681f3Smrg assert(legal_arith_type(op0->type)); 25917ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_BINOP, op0->type); 25927ec681f3Smrg if (!instr) 25937ec681f3Smrg return NULL; 25947ec681f3Smrg 25957ec681f3Smrg instr->binop.opcode = opcode; 25967ec681f3Smrg instr->binop.operands[0] = op0; 25977ec681f3Smrg instr->binop.operands[1] = op1; 25987ec681f3Smrg instr->binop.flags = flags; 25997ec681f3Smrg instr->has_value = true; 26007ec681f3Smrg return &instr->value; 26017ec681f3Smrg} 26027ec681f3Smrg 26037ec681f3Smrgconst struct dxil_value * 26047ec681f3Smrgdxil_emit_cmp(struct dxil_module *m, enum dxil_cmp_pred pred, 26057ec681f3Smrg const struct dxil_value *op0, const struct dxil_value *op1) 26067ec681f3Smrg{ 26077ec681f3Smrg assert(types_equal(op0->type, op1->type)); 26087ec681f3Smrg assert(legal_arith_type(op0->type)); 26097ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_CMP, get_int1_type(m)); 26107ec681f3Smrg if (!instr) 26117ec681f3Smrg return NULL; 26127ec681f3Smrg 26137ec681f3Smrg instr->cmp.pred = pred; 26147ec681f3Smrg instr->cmp.operands[0] = op0; 26157ec681f3Smrg instr->cmp.operands[1] = op1; 26167ec681f3Smrg instr->has_value = true; 26177ec681f3Smrg return &instr->value; 26187ec681f3Smrg} 26197ec681f3Smrg 26207ec681f3Smrgconst struct dxil_value * 26217ec681f3Smrgdxil_emit_select(struct dxil_module *m, 26227ec681f3Smrg const struct dxil_value *op0, 26237ec681f3Smrg const struct dxil_value *op1, 26247ec681f3Smrg const struct dxil_value *op2) 26257ec681f3Smrg{ 26267ec681f3Smrg assert(types_equal(op0->type, get_int1_type(m))); 26277ec681f3Smrg assert(types_equal(op1->type, op2->type)); 26287ec681f3Smrg assert(legal_arith_type(op1->type)); 26297ec681f3Smrg 26307ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_SELECT, op1->type); 26317ec681f3Smrg if (!instr) 26327ec681f3Smrg return NULL; 26337ec681f3Smrg 26347ec681f3Smrg instr->select.operands[0] = op0; 26357ec681f3Smrg instr->select.operands[1] = op1; 26367ec681f3Smrg instr->select.operands[2] = op2; 26377ec681f3Smrg instr->has_value = true; 26387ec681f3Smrg return &instr->value; 26397ec681f3Smrg} 26407ec681f3Smrg 26417ec681f3Smrgconst struct dxil_value * 26427ec681f3Smrgdxil_emit_cast(struct dxil_module *m, enum dxil_cast_opcode opcode, 26437ec681f3Smrg const struct dxil_type *type, 26447ec681f3Smrg const struct dxil_value *value) 26457ec681f3Smrg{ 26467ec681f3Smrg assert(legal_arith_type(value->type)); 26477ec681f3Smrg assert(legal_arith_type(type)); 26487ec681f3Smrg 26497ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_CAST, type); 26507ec681f3Smrg if (!instr) 26517ec681f3Smrg return NULL; 26527ec681f3Smrg 26537ec681f3Smrg instr->cast.opcode = opcode; 26547ec681f3Smrg instr->cast.type = type; 26557ec681f3Smrg instr->cast.value = value; 26567ec681f3Smrg instr->has_value = true; 26577ec681f3Smrg return &instr->value; 26587ec681f3Smrg} 26597ec681f3Smrg 26607ec681f3Smrgbool 26617ec681f3Smrgdxil_emit_branch(struct dxil_module *m, const struct dxil_value *cond, 26627ec681f3Smrg unsigned true_block, unsigned false_block) 26637ec681f3Smrg{ 26647ec681f3Smrg assert(!cond || types_equal(cond->type, get_int1_type(m))); 26657ec681f3Smrg 26667ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_BR, 26677ec681f3Smrg dxil_module_get_void_type(m)); 26687ec681f3Smrg if (!instr) 26697ec681f3Smrg return false; 26707ec681f3Smrg 26717ec681f3Smrg instr->br.cond = cond; 26727ec681f3Smrg instr->br.succ[0] = true_block; 26737ec681f3Smrg instr->br.succ[1] = false_block; 26747ec681f3Smrg m->curr_block++; 26757ec681f3Smrg return true; 26767ec681f3Smrg} 26777ec681f3Smrg 26787ec681f3Smrgconst struct dxil_value * 26797ec681f3Smrgdxil_instr_get_return_value(struct dxil_instr *instr) 26807ec681f3Smrg{ 26817ec681f3Smrg return instr->has_value ? &instr->value : NULL; 26827ec681f3Smrg} 26837ec681f3Smrg 26847ec681f3Smrgstruct dxil_instr * 26857ec681f3Smrgdxil_emit_phi(struct dxil_module *m, const struct dxil_type *type) 26867ec681f3Smrg{ 26877ec681f3Smrg assert(legal_arith_type(type)); 26887ec681f3Smrg 26897ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_PHI, type); 26907ec681f3Smrg if (!instr) 26917ec681f3Smrg return NULL; 26927ec681f3Smrg 26937ec681f3Smrg instr->phi.type = type; 26947ec681f3Smrg instr->phi.num_incoming = 0; 26957ec681f3Smrg instr->has_value = true; 26967ec681f3Smrg 26977ec681f3Smrg return instr; 26987ec681f3Smrg} 26997ec681f3Smrg 27007ec681f3Smrgvoid 27017ec681f3Smrgdxil_phi_set_incoming(struct dxil_instr *instr, 27027ec681f3Smrg const struct dxil_value *incoming_values[], 27037ec681f3Smrg const unsigned incoming_blocks[], 27047ec681f3Smrg size_t num_incoming) 27057ec681f3Smrg{ 27067ec681f3Smrg assert(instr->type == INSTR_PHI); 27077ec681f3Smrg assert(num_incoming > 0); 27087ec681f3Smrg assert(num_incoming < ARRAY_SIZE(instr->phi.incoming)); 27097ec681f3Smrg for (int i = 0; i < num_incoming; ++i) { 27107ec681f3Smrg assert(incoming_values[i]); 27117ec681f3Smrg assert(types_equal(incoming_values[i]->type, instr->phi.type)); 27127ec681f3Smrg 27137ec681f3Smrg instr->phi.incoming[i].value = incoming_values[i]; 27147ec681f3Smrg instr->phi.incoming[i].block = incoming_blocks[i]; 27157ec681f3Smrg } 27167ec681f3Smrg instr->phi.num_incoming = num_incoming; 27177ec681f3Smrg} 27187ec681f3Smrg 27197ec681f3Smrgstatic struct dxil_instr * 27207ec681f3Smrgcreate_call_instr(struct dxil_module *m, 27217ec681f3Smrg const struct dxil_func *func, 27227ec681f3Smrg const struct dxil_value **args, size_t num_args) 27237ec681f3Smrg{ 27247ec681f3Smrg assert(num_args == func->type->function_def.args.num_types); 27257ec681f3Smrg for (size_t i = 0; i < num_args; ++ i) 27267ec681f3Smrg assert(types_equal(func->type->function_def.args.types[i], args[i]->type)); 27277ec681f3Smrg 27287ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_CALL, 27297ec681f3Smrg func->type->function_def.ret_type); 27307ec681f3Smrg if (instr) { 27317ec681f3Smrg instr->call.func = func; 27327ec681f3Smrg instr->call.args = ralloc_array(instr, struct dxil_value *, num_args); 27337ec681f3Smrg if (!args) 27347ec681f3Smrg return false; 27357ec681f3Smrg memcpy(instr->call.args, args, sizeof(struct dxil_value *) * num_args); 27367ec681f3Smrg instr->call.num_args = num_args; 27377ec681f3Smrg } 27387ec681f3Smrg return instr; 27397ec681f3Smrg} 27407ec681f3Smrg 27417ec681f3Smrgconst struct dxil_value * 27427ec681f3Smrgdxil_emit_call(struct dxil_module *m, 27437ec681f3Smrg const struct dxil_func *func, 27447ec681f3Smrg const struct dxil_value **args, size_t num_args) 27457ec681f3Smrg{ 27467ec681f3Smrg assert(func->type->function_def.ret_type->type != TYPE_VOID); 27477ec681f3Smrg 27487ec681f3Smrg struct dxil_instr *instr = create_call_instr(m, func, args, num_args); 27497ec681f3Smrg if (!instr) 27507ec681f3Smrg return NULL; 27517ec681f3Smrg 27527ec681f3Smrg instr->has_value = true; 27537ec681f3Smrg return &instr->value; 27547ec681f3Smrg} 27557ec681f3Smrg 27567ec681f3Smrgbool 27577ec681f3Smrgdxil_emit_call_void(struct dxil_module *m, 27587ec681f3Smrg const struct dxil_func *func, 27597ec681f3Smrg const struct dxil_value **args, size_t num_args) 27607ec681f3Smrg{ 27617ec681f3Smrg assert(func->type->function_def.ret_type->type == TYPE_VOID); 27627ec681f3Smrg 27637ec681f3Smrg struct dxil_instr *instr = create_call_instr(m, func, args, num_args); 27647ec681f3Smrg if (!instr) 27657ec681f3Smrg return false; 27667ec681f3Smrg 27677ec681f3Smrg return true; 27687ec681f3Smrg} 27697ec681f3Smrg 27707ec681f3Smrgbool 27717ec681f3Smrgdxil_emit_ret_void(struct dxil_module *m) 27727ec681f3Smrg{ 27737ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_RET, 27747ec681f3Smrg dxil_module_get_void_type(m)); 27757ec681f3Smrg if (!instr) 27767ec681f3Smrg return false; 27777ec681f3Smrg 27787ec681f3Smrg instr->ret.value = NULL; 27797ec681f3Smrg m->curr_block++; 27807ec681f3Smrg return true; 27817ec681f3Smrg} 27827ec681f3Smrg 27837ec681f3Smrgconst struct dxil_value * 27847ec681f3Smrgdxil_emit_extractval(struct dxil_module *m, const struct dxil_value *src, 27857ec681f3Smrg const unsigned int index) 27867ec681f3Smrg{ 27877ec681f3Smrg assert(src->type->type == TYPE_STRUCT); 27887ec681f3Smrg assert(index < src->type->struct_def.elem.num_types); 27897ec681f3Smrg 27907ec681f3Smrg struct dxil_instr *instr = 27917ec681f3Smrg create_instr(m, INSTR_EXTRACTVAL, 27927ec681f3Smrg src->type->struct_def.elem.types[index]); 27937ec681f3Smrg if (!instr) 27947ec681f3Smrg return NULL; 27957ec681f3Smrg 27967ec681f3Smrg instr->extractval.src = src; 27977ec681f3Smrg instr->extractval.type = src->type; 27987ec681f3Smrg instr->extractval.idx = index; 27997ec681f3Smrg instr->has_value = true; 28007ec681f3Smrg 28017ec681f3Smrg return &instr->value; 28027ec681f3Smrg} 28037ec681f3Smrg 28047ec681f3Smrgconst struct dxil_value * 28057ec681f3Smrgdxil_emit_alloca(struct dxil_module *m, const struct dxil_type *alloc_type, 28067ec681f3Smrg const struct dxil_type *size_type, 28077ec681f3Smrg const struct dxil_value *size, 28087ec681f3Smrg unsigned int align) 28097ec681f3Smrg{ 28107ec681f3Smrg assert(size_type && size_type->type == TYPE_INTEGER); 28117ec681f3Smrg 28127ec681f3Smrg const struct dxil_type *return_type = 28137ec681f3Smrg dxil_module_get_pointer_type(m, alloc_type); 28147ec681f3Smrg if (!return_type) 28157ec681f3Smrg return NULL; 28167ec681f3Smrg 28177ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_ALLOCA, return_type); 28187ec681f3Smrg if (!instr) 28197ec681f3Smrg return NULL; 28207ec681f3Smrg 28217ec681f3Smrg instr->alloca.alloc_type = alloc_type; 28227ec681f3Smrg instr->alloca.size_type = size_type; 28237ec681f3Smrg instr->alloca.size = size; 28247ec681f3Smrg instr->alloca.align = util_logbase2(align) + 1; 28257ec681f3Smrg assert(instr->alloca.align < (1 << 5)); 28267ec681f3Smrg instr->alloca.align |= 1 << 6; 28277ec681f3Smrg 28287ec681f3Smrg instr->has_value = true; 28297ec681f3Smrg return &instr->value; 28307ec681f3Smrg} 28317ec681f3Smrg 28327ec681f3Smrgstatic const struct dxil_type * 28337ec681f3Smrgget_deref_type(const struct dxil_type *type) 28347ec681f3Smrg{ 28357ec681f3Smrg switch (type->type) { 28367ec681f3Smrg case TYPE_POINTER: return type->ptr_target_type; 28377ec681f3Smrg case TYPE_ARRAY: return type->array_or_vector_def.elem_type; 28387ec681f3Smrg default: unreachable("unexpected type"); 28397ec681f3Smrg } 28407ec681f3Smrg} 28417ec681f3Smrg 28427ec681f3Smrgconst struct dxil_value * 28437ec681f3Smrgdxil_emit_gep_inbounds(struct dxil_module *m, 28447ec681f3Smrg const struct dxil_value **operands, 28457ec681f3Smrg size_t num_operands) 28467ec681f3Smrg{ 28477ec681f3Smrg assert(num_operands > 0); 28487ec681f3Smrg const struct dxil_type *source_elem_type = 28497ec681f3Smrg get_deref_type(operands[0]->type); 28507ec681f3Smrg 28517ec681f3Smrg const struct dxil_type *type = operands[0]->type; 28527ec681f3Smrg for (int i = 1; i < num_operands; ++i) { 28537ec681f3Smrg assert(operands[i]->type == get_int32_type(m)); 28547ec681f3Smrg type = get_deref_type(type); 28557ec681f3Smrg } 28567ec681f3Smrg 28577ec681f3Smrg type = dxil_module_get_pointer_type(m, type); 28587ec681f3Smrg if (!type) 28597ec681f3Smrg return NULL; 28607ec681f3Smrg 28617ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_GEP, type); 28627ec681f3Smrg if (!instr) 28637ec681f3Smrg return NULL; 28647ec681f3Smrg 28657ec681f3Smrg instr->gep.operands = ralloc_array(instr, struct dxil_value *, 28667ec681f3Smrg num_operands); 28677ec681f3Smrg if (!instr->gep.operands) 28687ec681f3Smrg return NULL; 28697ec681f3Smrg 28707ec681f3Smrg instr->gep.source_elem_type = source_elem_type; 28717ec681f3Smrg memcpy(instr->gep.operands, operands, 28727ec681f3Smrg sizeof(struct dxil_value *) * num_operands); 28737ec681f3Smrg instr->gep.num_operands = num_operands; 28747ec681f3Smrg instr->gep.inbounds = true; 28757ec681f3Smrg 28767ec681f3Smrg instr->has_value = true; 28777ec681f3Smrg return &instr->value; 28787ec681f3Smrg} 28797ec681f3Smrg 28807ec681f3Smrgconst struct dxil_value * 28817ec681f3Smrgdxil_emit_load(struct dxil_module *m, const struct dxil_value *ptr, 28827ec681f3Smrg unsigned align, 28837ec681f3Smrg bool is_volatile) 28847ec681f3Smrg{ 28857ec681f3Smrg assert(ptr->type->type == TYPE_POINTER || 28867ec681f3Smrg ptr->type->type == TYPE_ARRAY); 28877ec681f3Smrg const struct dxil_type *type = ptr->type->type == TYPE_POINTER ? 28887ec681f3Smrg ptr->type->ptr_target_type : 28897ec681f3Smrg ptr->type->array_or_vector_def.elem_type; 28907ec681f3Smrg 28917ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_LOAD, type); 28927ec681f3Smrg if (!instr) 28937ec681f3Smrg return false; 28947ec681f3Smrg 28957ec681f3Smrg instr->load.ptr = ptr; 28967ec681f3Smrg instr->load.type = type; 28977ec681f3Smrg instr->load.align = util_logbase2(align) + 1; 28987ec681f3Smrg instr->load.is_volatile = is_volatile; 28997ec681f3Smrg 29007ec681f3Smrg instr->has_value = true; 29017ec681f3Smrg return &instr->value; 29027ec681f3Smrg} 29037ec681f3Smrg 29047ec681f3Smrgbool 29057ec681f3Smrgdxil_emit_store(struct dxil_module *m, const struct dxil_value *value, 29067ec681f3Smrg const struct dxil_value *ptr, unsigned align, 29077ec681f3Smrg bool is_volatile) 29087ec681f3Smrg{ 29097ec681f3Smrg assert(legal_arith_type(value->type)); 29107ec681f3Smrg 29117ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_STORE, 29127ec681f3Smrg dxil_module_get_void_type(m)); 29137ec681f3Smrg if (!instr) 29147ec681f3Smrg return false; 29157ec681f3Smrg 29167ec681f3Smrg instr->store.value = value; 29177ec681f3Smrg instr->store.ptr = ptr; 29187ec681f3Smrg instr->store.align = util_logbase2(align) + 1; 29197ec681f3Smrg instr->store.is_volatile = is_volatile; 29207ec681f3Smrg return true; 29217ec681f3Smrg} 29227ec681f3Smrg 29237ec681f3Smrgconst struct dxil_value * 29247ec681f3Smrgdxil_emit_cmpxchg(struct dxil_module *m, const struct dxil_value *cmpval, 29257ec681f3Smrg const struct dxil_value *newval, 29267ec681f3Smrg const struct dxil_value *ptr, bool is_volatile, 29277ec681f3Smrg enum dxil_atomic_ordering ordering, 29287ec681f3Smrg enum dxil_sync_scope syncscope) 29297ec681f3Smrg{ 29307ec681f3Smrg assert(ptr->type->type == TYPE_POINTER); 29317ec681f3Smrg 29327ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_CMPXCHG, 29337ec681f3Smrg ptr->type->ptr_target_type); 29347ec681f3Smrg if (!instr) 29357ec681f3Smrg return false; 29367ec681f3Smrg 29377ec681f3Smrg instr->cmpxchg.cmpval = cmpval; 29387ec681f3Smrg instr->cmpxchg.newval = newval; 29397ec681f3Smrg instr->cmpxchg.ptr = ptr; 29407ec681f3Smrg instr->cmpxchg.is_volatile = is_volatile; 29417ec681f3Smrg instr->cmpxchg.ordering = ordering; 29427ec681f3Smrg instr->cmpxchg.syncscope = syncscope; 29437ec681f3Smrg 29447ec681f3Smrg instr->has_value = true; 29457ec681f3Smrg return &instr->value; 29467ec681f3Smrg} 29477ec681f3Smrg 29487ec681f3Smrgconst struct dxil_value * 29497ec681f3Smrgdxil_emit_atomicrmw(struct dxil_module *m, const struct dxil_value *value, 29507ec681f3Smrg const struct dxil_value *ptr, enum dxil_rmw_op op, 29517ec681f3Smrg bool is_volatile, enum dxil_atomic_ordering ordering, 29527ec681f3Smrg enum dxil_sync_scope syncscope) 29537ec681f3Smrg{ 29547ec681f3Smrg assert(ptr->type->type == TYPE_POINTER); 29557ec681f3Smrg 29567ec681f3Smrg struct dxil_instr *instr = create_instr(m, INSTR_ATOMICRMW, 29577ec681f3Smrg ptr->type->ptr_target_type); 29587ec681f3Smrg if (!instr) 29597ec681f3Smrg return false; 29607ec681f3Smrg 29617ec681f3Smrg instr->atomicrmw.value = value; 29627ec681f3Smrg instr->atomicrmw.ptr = ptr; 29637ec681f3Smrg instr->atomicrmw.op = op; 29647ec681f3Smrg instr->atomicrmw.is_volatile = is_volatile; 29657ec681f3Smrg instr->atomicrmw.ordering = ordering; 29667ec681f3Smrg instr->atomicrmw.syncscope = syncscope; 29677ec681f3Smrg 29687ec681f3Smrg instr->has_value = true; 29697ec681f3Smrg return &instr->value; 29707ec681f3Smrg} 29717ec681f3Smrg 29727ec681f3Smrgstatic bool 29737ec681f3Smrgemit_binop(struct dxil_module *m, struct dxil_instr *instr) 29747ec681f3Smrg{ 29757ec681f3Smrg assert(instr->type == INSTR_BINOP); 29767ec681f3Smrg assert(instr->value.id > instr->binop.operands[0]->id); 29777ec681f3Smrg assert(instr->value.id > instr->binop.operands[1]->id); 29787ec681f3Smrg 29797ec681f3Smrg if (instr->binop.flags) { 29807ec681f3Smrg uint64_t data[] = { 29817ec681f3Smrg FUNC_CODE_INST_BINOP, 29827ec681f3Smrg instr->value.id - instr->binop.operands[0]->id, 29837ec681f3Smrg instr->value.id - instr->binop.operands[1]->id, 29847ec681f3Smrg instr->binop.opcode, 29857ec681f3Smrg instr->binop.flags 29867ec681f3Smrg }; 29877ec681f3Smrg return emit_func_abbrev_record(m, FUNC_ABBREV_BINOP_FLAGS, 29887ec681f3Smrg data, ARRAY_SIZE(data)); 29897ec681f3Smrg } 29907ec681f3Smrg uint64_t data[] = { 29917ec681f3Smrg FUNC_CODE_INST_BINOP, 29927ec681f3Smrg instr->value.id - instr->binop.operands[0]->id, 29937ec681f3Smrg instr->value.id - instr->binop.operands[1]->id, 29947ec681f3Smrg instr->binop.opcode 29957ec681f3Smrg }; 29967ec681f3Smrg return emit_func_abbrev_record(m, FUNC_ABBREV_BINOP, 29977ec681f3Smrg data, ARRAY_SIZE(data)); 29987ec681f3Smrg} 29997ec681f3Smrg 30007ec681f3Smrgstatic bool 30017ec681f3Smrgemit_cmp(struct dxil_module *m, struct dxil_instr *instr) 30027ec681f3Smrg{ 30037ec681f3Smrg assert(instr->type == INSTR_CMP); 30047ec681f3Smrg assert(instr->value.id > instr->cmp.operands[0]->id); 30057ec681f3Smrg assert(instr->value.id > instr->cmp.operands[1]->id); 30067ec681f3Smrg uint64_t data[] = { 30077ec681f3Smrg instr->value.id - instr->cmp.operands[0]->id, 30087ec681f3Smrg instr->value.id - instr->cmp.operands[1]->id, 30097ec681f3Smrg instr->cmp.pred 30107ec681f3Smrg }; 30117ec681f3Smrg return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_CMP2, 30127ec681f3Smrg data, ARRAY_SIZE(data)); 30137ec681f3Smrg} 30147ec681f3Smrg 30157ec681f3Smrgstatic bool 30167ec681f3Smrgemit_select(struct dxil_module *m, struct dxil_instr *instr) 30177ec681f3Smrg{ 30187ec681f3Smrg assert(instr->type == INSTR_SELECT); 30197ec681f3Smrg assert(instr->value.id > instr->select.operands[0]->id); 30207ec681f3Smrg assert(instr->value.id > instr->select.operands[1]->id); 30217ec681f3Smrg assert(instr->value.id > instr->select.operands[2]->id); 30227ec681f3Smrg uint64_t data[] = { 30237ec681f3Smrg instr->value.id - instr->select.operands[1]->id, 30247ec681f3Smrg instr->value.id - instr->select.operands[2]->id, 30257ec681f3Smrg instr->value.id - instr->select.operands[0]->id 30267ec681f3Smrg }; 30277ec681f3Smrg return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_VSELECT, 30287ec681f3Smrg data, ARRAY_SIZE(data)); 30297ec681f3Smrg} 30307ec681f3Smrg 30317ec681f3Smrgstatic bool 30327ec681f3Smrgemit_cast(struct dxil_module *m, struct dxil_instr *instr) 30337ec681f3Smrg{ 30347ec681f3Smrg assert(instr->type == INSTR_CAST); 30357ec681f3Smrg assert(instr->value.id > instr->cast.value->id); 30367ec681f3Smrg uint64_t data[] = { 30377ec681f3Smrg FUNC_CODE_INST_CAST, 30387ec681f3Smrg instr->value.id - instr->cast.value->id, 30397ec681f3Smrg instr->cast.type->id, 30407ec681f3Smrg instr->cast.opcode 30417ec681f3Smrg }; 30427ec681f3Smrg return emit_func_abbrev_record(m, FUNC_ABBREV_CAST, 30437ec681f3Smrg data, ARRAY_SIZE(data)); 30447ec681f3Smrg} 30457ec681f3Smrg 30467ec681f3Smrgstatic bool 30477ec681f3Smrgemit_branch(struct dxil_module *m, struct dxil_instr *instr) 30487ec681f3Smrg{ 30497ec681f3Smrg assert(instr->type == INSTR_BR); 30507ec681f3Smrg assert(instr->br.succ[0] < m->num_basic_block_ids); 30517ec681f3Smrg assert(m->basic_block_ids[instr->br.succ[0]] >= 0); 30527ec681f3Smrg 30537ec681f3Smrg if (!instr->br.cond) { 30547ec681f3Smrg /* unconditional branch */ 30557ec681f3Smrg uint64_t succ = m->basic_block_ids[instr->br.succ[0]]; 30567ec681f3Smrg return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_BR, &succ, 1); 30577ec681f3Smrg } 30587ec681f3Smrg /* conditional branch */ 30597ec681f3Smrg assert(instr->value.id > instr->br.cond->id); 30607ec681f3Smrg assert(instr->br.succ[1] < m->num_basic_block_ids); 30617ec681f3Smrg assert(m->basic_block_ids[instr->br.succ[1]] >= 0); 30627ec681f3Smrg 30637ec681f3Smrg uint64_t data[] = { 30647ec681f3Smrg m->basic_block_ids[instr->br.succ[0]], 30657ec681f3Smrg m->basic_block_ids[instr->br.succ[1]], 30667ec681f3Smrg instr->value.id - instr->br.cond->id 30677ec681f3Smrg }; 30687ec681f3Smrg return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_BR, 30697ec681f3Smrg data, ARRAY_SIZE(data)); 30707ec681f3Smrg} 30717ec681f3Smrg 30727ec681f3Smrgstatic bool 30737ec681f3Smrgemit_phi(struct dxil_module *m, struct dxil_instr *instr) 30747ec681f3Smrg{ 30757ec681f3Smrg assert(instr->type == INSTR_PHI); 30767ec681f3Smrg uint64_t data[128]; 30777ec681f3Smrg data[0] = instr->phi.type->id; 30787ec681f3Smrg assert(instr->phi.num_incoming > 0); 30797ec681f3Smrg for (int i = 0; i < instr->phi.num_incoming; ++i) { 30807ec681f3Smrg int64_t value_delta = instr->value.id - instr->phi.incoming[i].value->id; 30817ec681f3Smrg data[1 + i * 2] = encode_signed(value_delta); 30827ec681f3Smrg assert(instr->phi.incoming[i].block < m->num_basic_block_ids); 30837ec681f3Smrg assert(m->basic_block_ids[instr->phi.incoming[i].block] >= 0); 30847ec681f3Smrg data[1 + i * 2 + 1] = m->basic_block_ids[instr->phi.incoming[i].block]; 30857ec681f3Smrg } 30867ec681f3Smrg return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_PHI, 30877ec681f3Smrg data, 1 + 2 * instr->phi.num_incoming); 30887ec681f3Smrg} 30897ec681f3Smrg 30907ec681f3Smrgstatic bool 30917ec681f3Smrgemit_extractval(struct dxil_module *m, struct dxil_instr *instr) 30927ec681f3Smrg{ 30937ec681f3Smrg assert(instr->type == INSTR_EXTRACTVAL); 30947ec681f3Smrg assert(instr->value.id > instr->extractval.src->id); 30957ec681f3Smrg assert(instr->value.id > instr->extractval.type->id); 30967ec681f3Smrg 30977ec681f3Smrg /* relative value ID, followed by absolute type ID (only if 30987ec681f3Smrg * forward-declared), followed by n indices */ 30997ec681f3Smrg uint64_t data[] = { 31007ec681f3Smrg instr->value.id - instr->extractval.src->id, 31017ec681f3Smrg instr->extractval.idx 31027ec681f3Smrg }; 31037ec681f3Smrg return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_EXTRACTVAL, 31047ec681f3Smrg data, ARRAY_SIZE(data)); 31057ec681f3Smrg} 31067ec681f3Smrg 31077ec681f3Smrgstatic bool 31087ec681f3Smrgemit_call(struct dxil_module *m, struct dxil_instr *instr) 31097ec681f3Smrg{ 31107ec681f3Smrg assert(instr->type == INSTR_CALL); 31117ec681f3Smrg assert(instr->call.func->value.id >= 0 && instr->value.id >= 0); 31127ec681f3Smrg assert(instr->call.func->type->id >= 0); 31137ec681f3Smrg assert(instr->call.func->value.id <= instr->value.id); 31147ec681f3Smrg int value_id_delta = instr->value.id - instr->call.func->value.id; 31157ec681f3Smrg 31167ec681f3Smrg uint64_t data[256]; 31177ec681f3Smrg data[0] = 0; // attribute id 31187ec681f3Smrg data[1] = 1 << 15; // calling convention etc 31197ec681f3Smrg data[2] = instr->call.func->type->id; 31207ec681f3Smrg data[3] = value_id_delta; 31217ec681f3Smrg 31227ec681f3Smrg assert(instr->call.num_args < ARRAY_SIZE(data) - 4); 31237ec681f3Smrg for (size_t i = 0; i < instr->call.num_args; ++i) { 31247ec681f3Smrg assert(instr->call.args[i]->id >= 0); 31257ec681f3Smrg data[4 + i] = instr->value.id - instr->call.args[i]->id; 31267ec681f3Smrg } 31277ec681f3Smrg 31287ec681f3Smrg return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_CALL, 31297ec681f3Smrg data, 4 + instr->call.num_args); 31307ec681f3Smrg} 31317ec681f3Smrg 31327ec681f3Smrgstatic bool 31337ec681f3Smrgemit_ret(struct dxil_module *m, struct dxil_instr *instr) 31347ec681f3Smrg{ 31357ec681f3Smrg assert(instr->type == INSTR_RET); 31367ec681f3Smrg 31377ec681f3Smrg if (instr->ret.value) { 31387ec681f3Smrg assert(instr->ret.value->id >= 0); 31397ec681f3Smrg uint64_t data[] = { FUNC_CODE_INST_RET, instr->ret.value->id }; 31407ec681f3Smrg return emit_func_abbrev_record(m, FUNC_ABBREV_RET_VAL, 31417ec681f3Smrg data, ARRAY_SIZE(data)); 31427ec681f3Smrg } 31437ec681f3Smrg 31447ec681f3Smrg uint64_t data[] = { FUNC_CODE_INST_RET }; 31457ec681f3Smrg return emit_func_abbrev_record(m, FUNC_ABBREV_RET_VOID, 31467ec681f3Smrg data, ARRAY_SIZE(data)); 31477ec681f3Smrg} 31487ec681f3Smrg 31497ec681f3Smrgstatic bool 31507ec681f3Smrgemit_alloca(struct dxil_module *m, struct dxil_instr *instr) 31517ec681f3Smrg{ 31527ec681f3Smrg assert(instr->type == INSTR_ALLOCA); 31537ec681f3Smrg assert(instr->alloca.alloc_type->id >= 0); 31547ec681f3Smrg assert(instr->alloca.size_type->id >= 0); 31557ec681f3Smrg assert(instr->alloca.size->id >= 0); 31567ec681f3Smrg 31577ec681f3Smrg uint64_t data[] = { 31587ec681f3Smrg instr->alloca.alloc_type->id, 31597ec681f3Smrg instr->alloca.size_type->id, 31607ec681f3Smrg instr->alloca.size->id, 31617ec681f3Smrg instr->alloca.align, 31627ec681f3Smrg }; 31637ec681f3Smrg return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_ALLOCA, 31647ec681f3Smrg data, ARRAY_SIZE(data)); 31657ec681f3Smrg} 31667ec681f3Smrg 31677ec681f3Smrgstatic bool 31687ec681f3Smrgemit_gep(struct dxil_module *m, struct dxil_instr *instr) 31697ec681f3Smrg{ 31707ec681f3Smrg assert(instr->type == INSTR_GEP); 31717ec681f3Smrg assert(instr->gep.source_elem_type->id >= 0); 31727ec681f3Smrg 31737ec681f3Smrg uint64_t data[256]; 31747ec681f3Smrg data[0] = FUNC_CODE_INST_GEP; 31757ec681f3Smrg data[1] = instr->gep.inbounds; 31767ec681f3Smrg data[2] = instr->gep.source_elem_type->id; 31777ec681f3Smrg 31787ec681f3Smrg assert(instr->gep.num_operands < ARRAY_SIZE(data) - 3); 31797ec681f3Smrg for (int i = 0; i < instr->gep.num_operands; ++i) { 31807ec681f3Smrg assert(instr->value.id > instr->gep.operands[i]->id); 31817ec681f3Smrg data[3 + i] = instr->value.id - instr->gep.operands[i]->id; 31827ec681f3Smrg } 31837ec681f3Smrg return emit_func_abbrev_record(m, FUNC_ABBREV_GEP, 31847ec681f3Smrg data, 3 + instr->gep.num_operands); 31857ec681f3Smrg} 31867ec681f3Smrg 31877ec681f3Smrgstatic bool 31887ec681f3Smrgemit_load(struct dxil_module *m, struct dxil_instr *instr) 31897ec681f3Smrg{ 31907ec681f3Smrg assert(instr->type == INSTR_LOAD); 31917ec681f3Smrg assert(instr->value.id > instr->load.ptr->id); 31927ec681f3Smrg assert(instr->load.type->id >= 0); 31937ec681f3Smrg 31947ec681f3Smrg uint64_t data[] = { 31957ec681f3Smrg instr->value.id - instr->load.ptr->id, 31967ec681f3Smrg instr->load.type->id, 31977ec681f3Smrg instr->load.align, 31987ec681f3Smrg instr->load.is_volatile 31997ec681f3Smrg }; 32007ec681f3Smrg return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_LOAD, 32017ec681f3Smrg data, ARRAY_SIZE(data)); 32027ec681f3Smrg} 32037ec681f3Smrgstatic bool 32047ec681f3Smrgemit_store(struct dxil_module *m, struct dxil_instr *instr) 32057ec681f3Smrg{ 32067ec681f3Smrg assert(instr->type == INSTR_STORE); 32077ec681f3Smrg assert(instr->value.id > instr->store.value->id); 32087ec681f3Smrg assert(instr->value.id > instr->store.ptr->id); 32097ec681f3Smrg 32107ec681f3Smrg uint64_t data[] = { 32117ec681f3Smrg instr->value.id - instr->store.ptr->id, 32127ec681f3Smrg instr->value.id - instr->store.value->id, 32137ec681f3Smrg instr->store.align, 32147ec681f3Smrg instr->store.is_volatile 32157ec681f3Smrg }; 32167ec681f3Smrg return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_STORE, 32177ec681f3Smrg data, ARRAY_SIZE(data)); 32187ec681f3Smrg} 32197ec681f3Smrg 32207ec681f3Smrgstatic bool 32217ec681f3Smrgemit_cmpxchg(struct dxil_module *m, struct dxil_instr *instr) 32227ec681f3Smrg{ 32237ec681f3Smrg assert(instr->type == INSTR_CMPXCHG); 32247ec681f3Smrg assert(instr->value.id > instr->cmpxchg.cmpval->id); 32257ec681f3Smrg assert(instr->value.id > instr->cmpxchg.newval->id); 32267ec681f3Smrg assert(instr->value.id > instr->cmpxchg.ptr->id); 32277ec681f3Smrg uint64_t data[] = { 32287ec681f3Smrg instr->value.id - instr->cmpxchg.ptr->id, 32297ec681f3Smrg instr->value.id - instr->cmpxchg.cmpval->id, 32307ec681f3Smrg instr->value.id - instr->cmpxchg.newval->id, 32317ec681f3Smrg instr->cmpxchg.is_volatile, 32327ec681f3Smrg instr->cmpxchg.ordering, 32337ec681f3Smrg instr->cmpxchg.syncscope, 32347ec681f3Smrg }; 32357ec681f3Smrg return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_CMPXCHG_OLD, 32367ec681f3Smrg data, ARRAY_SIZE(data)); 32377ec681f3Smrg} 32387ec681f3Smrg 32397ec681f3Smrgstatic bool 32407ec681f3Smrgemit_atomicrmw(struct dxil_module *m, struct dxil_instr *instr) 32417ec681f3Smrg{ 32427ec681f3Smrg assert(instr->type == INSTR_ATOMICRMW); 32437ec681f3Smrg assert(instr->value.id > instr->atomicrmw.value->id); 32447ec681f3Smrg assert(instr->value.id > instr->atomicrmw.ptr->id); 32457ec681f3Smrg uint64_t data[] = { 32467ec681f3Smrg instr->value.id - instr->atomicrmw.ptr->id, 32477ec681f3Smrg instr->value.id - instr->atomicrmw.value->id, 32487ec681f3Smrg instr->atomicrmw.op, 32497ec681f3Smrg instr->atomicrmw.is_volatile, 32507ec681f3Smrg instr->atomicrmw.ordering, 32517ec681f3Smrg instr->atomicrmw.syncscope, 32527ec681f3Smrg }; 32537ec681f3Smrg return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_ATOMICRMW, 32547ec681f3Smrg data, ARRAY_SIZE(data)); 32557ec681f3Smrg} 32567ec681f3Smrg 32577ec681f3Smrgstatic bool 32587ec681f3Smrgemit_instr(struct dxil_module *m, struct dxil_instr *instr) 32597ec681f3Smrg{ 32607ec681f3Smrg switch (instr->type) { 32617ec681f3Smrg case INSTR_BINOP: 32627ec681f3Smrg return emit_binop(m, instr); 32637ec681f3Smrg 32647ec681f3Smrg case INSTR_CMP: 32657ec681f3Smrg return emit_cmp(m, instr); 32667ec681f3Smrg 32677ec681f3Smrg case INSTR_SELECT: 32687ec681f3Smrg return emit_select(m, instr); 32697ec681f3Smrg 32707ec681f3Smrg case INSTR_CAST: 32717ec681f3Smrg return emit_cast(m, instr); 32727ec681f3Smrg 32737ec681f3Smrg case INSTR_BR: 32747ec681f3Smrg return emit_branch(m, instr); 32757ec681f3Smrg 32767ec681f3Smrg case INSTR_PHI: 32777ec681f3Smrg return emit_phi(m, instr); 32787ec681f3Smrg 32797ec681f3Smrg case INSTR_CALL: 32807ec681f3Smrg return emit_call(m, instr); 32817ec681f3Smrg 32827ec681f3Smrg case INSTR_RET: 32837ec681f3Smrg return emit_ret(m, instr); 32847ec681f3Smrg 32857ec681f3Smrg case INSTR_EXTRACTVAL: 32867ec681f3Smrg return emit_extractval(m, instr); 32877ec681f3Smrg 32887ec681f3Smrg case INSTR_ALLOCA: 32897ec681f3Smrg return emit_alloca(m, instr); 32907ec681f3Smrg 32917ec681f3Smrg case INSTR_GEP: 32927ec681f3Smrg return emit_gep(m, instr); 32937ec681f3Smrg 32947ec681f3Smrg case INSTR_LOAD: 32957ec681f3Smrg return emit_load(m, instr); 32967ec681f3Smrg 32977ec681f3Smrg case INSTR_STORE: 32987ec681f3Smrg return emit_store(m, instr); 32997ec681f3Smrg 33007ec681f3Smrg case INSTR_ATOMICRMW: 33017ec681f3Smrg return emit_atomicrmw(m, instr); 33027ec681f3Smrg 33037ec681f3Smrg case INSTR_CMPXCHG: 33047ec681f3Smrg return emit_cmpxchg(m, instr); 33057ec681f3Smrg 33067ec681f3Smrg default: 33077ec681f3Smrg unreachable("unexpected instruction type"); 33087ec681f3Smrg } 33097ec681f3Smrg} 33107ec681f3Smrg 33117ec681f3Smrgstatic bool 33127ec681f3Smrgemit_function(struct dxil_module *m) 33137ec681f3Smrg{ 33147ec681f3Smrg if (!enter_subblock(m, DXIL_FUNCTION_BLOCK, 4) || 33157ec681f3Smrg !emit_record_int(m, FUNC_CODE_DECLAREBLOCKS, m->curr_block)) 33167ec681f3Smrg return false; 33177ec681f3Smrg 33187ec681f3Smrg list_for_each_entry(struct dxil_instr, instr, &m->instr_list, head) { 33197ec681f3Smrg if (!emit_instr(m, instr)) 33207ec681f3Smrg return false; 33217ec681f3Smrg } 33227ec681f3Smrg 33237ec681f3Smrg return exit_block(m); 33247ec681f3Smrg} 33257ec681f3Smrg 33267ec681f3Smrgstatic void 33277ec681f3Smrgassign_values(struct dxil_module *m) 33287ec681f3Smrg{ 33297ec681f3Smrg int next_value_id = 0; 33307ec681f3Smrg 33317ec681f3Smrg struct dxil_gvar *gvar; 33327ec681f3Smrg LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) { 33337ec681f3Smrg gvar->value.id = next_value_id++; 33347ec681f3Smrg } 33357ec681f3Smrg 33367ec681f3Smrg struct dxil_func *func; 33377ec681f3Smrg LIST_FOR_EACH_ENTRY(func, &m->func_list, head) { 33387ec681f3Smrg func->value.id = next_value_id++; 33397ec681f3Smrg } 33407ec681f3Smrg 33417ec681f3Smrg struct dxil_const *c; 33427ec681f3Smrg LIST_FOR_EACH_ENTRY(c, &m->const_list, head) { 33437ec681f3Smrg c->value.id = next_value_id++; 33447ec681f3Smrg } 33457ec681f3Smrg 33467ec681f3Smrg struct dxil_instr *instr; 33477ec681f3Smrg LIST_FOR_EACH_ENTRY(instr, &m->instr_list, head) { 33487ec681f3Smrg instr->value.id = next_value_id; 33497ec681f3Smrg if (instr->has_value) 33507ec681f3Smrg next_value_id++; 33517ec681f3Smrg } 33527ec681f3Smrg} 33537ec681f3Smrg 33547ec681f3Smrgbool 33557ec681f3Smrgdxil_emit_module(struct dxil_module *m) 33567ec681f3Smrg{ 33577ec681f3Smrg assign_values(m); 33587ec681f3Smrg return dxil_buffer_emit_bits(&m->buf, 'B', 8) && 33597ec681f3Smrg dxil_buffer_emit_bits(&m->buf, 'C', 8) && 33607ec681f3Smrg dxil_buffer_emit_bits(&m->buf, 0xC0, 8) && 33617ec681f3Smrg dxil_buffer_emit_bits(&m->buf, 0xDE, 8) && 33627ec681f3Smrg enter_subblock(m, DXIL_MODULE, 3) && 33637ec681f3Smrg emit_record_int(m, DXIL_MODULE_CODE_VERSION, 1) && 33647ec681f3Smrg emit_blockinfo(m) && 33657ec681f3Smrg emit_attrib_group_table(m) && 33667ec681f3Smrg emit_attribute_table(m) && 33677ec681f3Smrg emit_type_table(m) && 33687ec681f3Smrg emit_module_info(m) && 33697ec681f3Smrg emit_module_consts(m) && 33707ec681f3Smrg emit_metadata(m) && 33717ec681f3Smrg emit_value_symbol_table(m) && 33727ec681f3Smrg emit_function(m) && 33737ec681f3Smrg exit_block(m); 33747ec681f3Smrg} 3375