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