Path: blob/21.2-virgl/src/microsoft/compiler/dxil_module.c
4564 views
/*1* Copyright © Microsoft Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "dxil_module.h"24#include "dxil_internal.h"2526#include "util/macros.h"27#include "util/u_math.h"28#include "util/u_memory.h"29#include "util/rb_tree.h"3031#include <assert.h>32#include <stdio.h>3334void35dxil_module_init(struct dxil_module *m, void *ralloc_ctx)36{37assert(ralloc_ctx);3839memset(m, 0, sizeof(struct dxil_module));40m->ralloc_ctx = ralloc_ctx;4142dxil_buffer_init(&m->buf, 2);43memset(&m->feats, 0, sizeof(m->feats));4445list_inithead(&m->type_list);46list_inithead(&m->func_list);47list_inithead(&m->attr_set_list);48list_inithead(&m->gvar_list);49list_inithead(&m->const_list);50list_inithead(&m->instr_list);51list_inithead(&m->mdnode_list);52list_inithead(&m->md_named_node_list);5354m->functions = rzalloc(ralloc_ctx, struct rb_tree);55rb_tree_init(m->functions);5657m->curr_block = 0;58}5960void61dxil_module_release(struct dxil_module *m)62{63dxil_buffer_finish(&m->buf);64}6566static bool67emit_bits64(struct dxil_buffer *b, uint64_t data, unsigned width)68{69if (data > UINT32_MAX) {70assert(width > 32);71return dxil_buffer_emit_bits(b, (uint32_t)(data & UINT32_MAX), width) &&72dxil_buffer_emit_bits(b, (uint32_t)(data >> 32), width - 32);73} else74return dxil_buffer_emit_bits(b, (uint32_t)data, width);75}7677/* See the LLVM documentation for details about what these are all about:78* https://www.llvm.org/docs/BitCodeFormat.html#abbreviation-ids79*/80enum dxil_fixed_abbrev {81DXIL_END_BLOCK = 0,82DXIL_ENTER_SUBBLOCK = 1,83DXIL_DEFINE_ABBREV = 2,84DXIL_UNABBREV_RECORD = 3,85DXIL_FIRST_APPLICATION_ABBREV = 486};8788static bool89enter_subblock(struct dxil_module *m, unsigned id, unsigned abbrev_width)90{91assert(m->num_blocks < ARRAY_SIZE(m->blocks));92m->blocks[m->num_blocks].abbrev_width = m->buf.abbrev_width;9394if (!dxil_buffer_emit_abbrev_id(&m->buf, DXIL_ENTER_SUBBLOCK) ||95!dxil_buffer_emit_vbr_bits(&m->buf, id, 8) ||96!dxil_buffer_emit_vbr_bits(&m->buf, abbrev_width, 4) ||97!dxil_buffer_align(&m->buf))98return false;99100m->buf.abbrev_width = abbrev_width;101m->blocks[m->num_blocks++].offset = blob_reserve_uint32(&m->buf.blob);102return true;103}104105static bool106exit_block(struct dxil_module *m)107{108assert(m->num_blocks > 0);109assert(m->num_blocks < ARRAY_SIZE(m->blocks));110111if (!dxil_buffer_emit_abbrev_id(&m->buf, DXIL_END_BLOCK) ||112!dxil_buffer_align(&m->buf))113return false;114115intptr_t size_offset = m->blocks[m->num_blocks - 1].offset;116uint32_t size = (m->buf.blob.size - size_offset - 1) / sizeof(uint32_t);117if (!blob_overwrite_uint32(&m->buf.blob, size_offset, size))118return false;119120m->num_blocks--;121m->buf.abbrev_width = m->blocks[m->num_blocks].abbrev_width;122return true;123}124125static bool126emit_record_no_abbrev(struct dxil_buffer *b, unsigned code,127const uint64_t *data, size_t size)128{129if (!dxil_buffer_emit_abbrev_id(b, DXIL_UNABBREV_RECORD) ||130!dxil_buffer_emit_vbr_bits(b, code, 6) ||131!dxil_buffer_emit_vbr_bits(b, size, 6))132return false;133134for (size_t i = 0; i < size; ++i)135if (!dxil_buffer_emit_vbr_bits(b, data[i], 6))136return false;137138return true;139}140141static bool142emit_record(struct dxil_module *m, unsigned code,143const uint64_t *data, size_t size)144{145return emit_record_no_abbrev(&m->buf, code, data, size);146}147148static bool149emit_record_int(struct dxil_module *m, unsigned code, int value)150{151uint64_t data = value;152return emit_record(m, code, &data, 1);153}154155static bool156is_char6(char ch)157{158if ((ch >= 'a' && ch <= 'z') ||159(ch >= 'A' && ch <= 'Z') ||160(ch >= '0' && ch <= '9'))161return true;162163switch (ch) {164case '.':165case '_':166return true;167168default:169return false;170}171}172173static bool174is_char6_string(const char *str)175{176while (*str != '\0') {177if (!is_char6(*str++))178return false;179}180return true;181}182183static bool184is_char7_string(const char *str)185{186while (*str != '\0') {187if (*str++ & 0x80)188return false;189}190return true;191}192193static unsigned194encode_char6(char ch)195{196const int letters = 'z' - 'a' + 1;197198if (ch >= 'a' && ch <= 'z')199return ch - 'a';200else if (ch >= 'A' && ch <= 'Z')201return letters + ch - 'A';202else if (ch >= '0' && ch <= '9')203return 2 * letters + ch - '0';204205switch (ch) {206case '.': return 62;207case '_': return 63;208default:209unreachable("invalid char6-character");210}211}212213static bool214emit_fixed(struct dxil_buffer *b, uint64_t data, unsigned width)215{216if (!width)217return true;218219return emit_bits64(b, data, width);220}221222static bool223emit_vbr(struct dxil_buffer *b, uint64_t data, unsigned width)224{225if (!width)226return true;227228return dxil_buffer_emit_vbr_bits(b, data, width);229}230231static bool232emit_char6(struct dxil_buffer *b, uint64_t data)233{234return dxil_buffer_emit_bits(b, encode_char6((char)data), 6);235}236237struct dxil_abbrev {238struct {239enum {240DXIL_OP_LITERAL = 0,241DXIL_OP_FIXED = 1,242DXIL_OP_VBR = 2,243DXIL_OP_ARRAY = 3,244DXIL_OP_CHAR6 = 4,245DXIL_OP_BLOB = 5246} type;247union {248uint64_t value;249uint64_t encoding_data;250};251} operands[7];252size_t num_operands;253};254255static bool256emit_record_abbrev(struct dxil_buffer *b,257unsigned abbrev, const struct dxil_abbrev *a,258const uint64_t *data, size_t size)259{260assert(abbrev >= DXIL_FIRST_APPLICATION_ABBREV);261262if (!dxil_buffer_emit_abbrev_id(b, abbrev))263return false;264265size_t curr_data = 0;266for (int i = 0; i < a->num_operands; ++i) {267switch (a->operands[i].type) {268case DXIL_OP_LITERAL:269assert(curr_data < size);270assert(data[curr_data] == a->operands[i].value);271curr_data++;272/* literals are no-ops, because their value is defined in the273abbrev-definition already */274break;275276case DXIL_OP_FIXED:277assert(curr_data < size);278if (!emit_fixed(b, data[curr_data++], a->operands[i].encoding_data))279return false;280break;281282case DXIL_OP_VBR:283assert(curr_data < size);284if (!emit_vbr(b, data[curr_data++], a->operands[i].encoding_data))285return false;286break;287288case DXIL_OP_ARRAY:289assert(i == a->num_operands - 2); /* arrays should always be second to last */290291if (!dxil_buffer_emit_vbr_bits(b, size - curr_data, 6))292return false;293294switch (a->operands[i + 1].type) {295case DXIL_OP_FIXED:296while (curr_data < size)297if (!emit_fixed(b, data[curr_data++], a->operands[i + 1].encoding_data))298return false;299break;300301case DXIL_OP_VBR:302while (curr_data < size)303if (!emit_vbr(b, data[curr_data++], a->operands[i + 1].encoding_data))304return false;305break;306307case DXIL_OP_CHAR6:308while (curr_data < size)309if (!emit_char6(b, data[curr_data++]))310return false;311break;312313default:314unreachable("unexpected operand type");315}316return true; /* we're done */317318case DXIL_OP_CHAR6:319assert(curr_data < size);320if (!emit_char6(b, data[curr_data++]))321return false;322break;323324case DXIL_OP_BLOB:325unreachable("HALP, unplement!");326327default:328unreachable("unexpected operand type");329}330}331332assert(curr_data == size);333return true;334}335336337static struct dxil_type *338create_type(struct dxil_module *m, enum type_type type)339{340struct dxil_type *ret = rzalloc_size(m->ralloc_ctx,341sizeof(struct dxil_type));342if (ret) {343ret->type = type;344ret->id = list_length(&m->type_list);345list_addtail(&ret->head, &m->type_list);346}347return ret;348}349350static bool351types_equal(const struct dxil_type *lhs, const struct dxil_type *rhs);352353static bool354type_list_equal(const struct dxil_type_list *lhs,355const struct dxil_type_list *rhs)356{357if (lhs->num_types != rhs->num_types)358return false;359for (unsigned i = 0; i < lhs->num_types; ++i)360if (!types_equal(lhs->types[i], rhs->types[i]))361return false;362return true;363}364365static bool366types_equal(const struct dxil_type *lhs, const struct dxil_type *rhs)367{368if (lhs == rhs)369return true;370371/* Below we only assert that different type pointers really define different types372* Since this function is only called in asserts, it is not needed to put the code373* into a #ifdef NDEBUG statement */374if (lhs->type != rhs->type)375return false;376377bool retval = false;378switch (lhs->type) {379case TYPE_VOID:380retval = true;381break;382case TYPE_FLOAT:383retval = lhs->float_bits == rhs->float_bits;384break;385case TYPE_INTEGER:386retval = lhs->int_bits == rhs->int_bits;387break;388case TYPE_POINTER:389retval = types_equal(lhs->ptr_target_type, rhs->ptr_target_type);390break;391case TYPE_ARRAY:392case TYPE_VECTOR:393retval = (lhs->array_or_vector_def.num_elems == rhs->array_or_vector_def.num_elems) &&394types_equal(lhs->array_or_vector_def.elem_type,395rhs->array_or_vector_def.elem_type);396break;397case TYPE_FUNCTION:398if (!types_equal(lhs->function_def.ret_type,399rhs->function_def.ret_type))400return false;401retval = type_list_equal(&lhs->function_def.args, &rhs->function_def.args);402break;403case TYPE_STRUCT:404retval = type_list_equal(&lhs->struct_def.elem, &rhs->struct_def.elem);405}406assert(!retval && "Types are equal in structure but not as pointers");407return retval;408}409410bool411dxil_value_type_equal_to(const struct dxil_value *value,412const struct dxil_type *rhs)413{414return types_equal(value->type, rhs);415}416417nir_alu_type418dxil_type_to_nir_type(const struct dxil_type *type)419{420assert(type);421switch (type->type) {422case TYPE_INTEGER:423return type->int_bits == 1 ? nir_type_bool : nir_type_int;424case TYPE_FLOAT:425return nir_type_float;426default:427unreachable("Unexpected type in dxil_type_to_nir_type");428}429}430431bool432dxil_value_type_bitsize_equal_to(const struct dxil_value *value, unsigned bitsize)433{434switch (value->type->type) {435case TYPE_INTEGER:436return value->type->int_bits == bitsize;437case TYPE_FLOAT:438return value->type->float_bits == bitsize;439default:440return false;441}442}443444const struct dxil_type *445dxil_value_get_type(const struct dxil_value *value)446{447return value->type;448}449450const struct dxil_type *451dxil_module_get_void_type(struct dxil_module *m)452{453if (!m->void_type)454m->void_type = create_type(m, TYPE_VOID);455return m->void_type;456}457458static const struct dxil_type *459create_int_type(struct dxil_module *m, unsigned bit_size)460{461struct dxil_type *type = create_type(m, TYPE_INTEGER);462if (type)463type->int_bits = bit_size;464return type;465}466467static const struct dxil_type *468get_int1_type(struct dxil_module *m)469{470if (!m->int1_type)471m->int1_type = create_int_type(m, 1);472return m->int1_type;473}474475static const struct dxil_type *476get_int8_type(struct dxil_module *m)477{478if (!m->int8_type)479m->int8_type = create_int_type(m, 8);480return m->int8_type;481}482483static const struct dxil_type *484get_int16_type(struct dxil_module *m)485{486if (!m->int16_type)487m->int16_type = create_int_type(m, 16);488return m->int16_type;489}490491static const struct dxil_type *492get_int32_type(struct dxil_module *m)493{494if (!m->int32_type)495m->int32_type = create_int_type(m, 32);496return m->int32_type;497}498499static const struct dxil_type *500get_int64_type(struct dxil_module *m)501{502if (!m->int64_type)503m->int64_type = create_int_type(m, 64);504return m->int64_type;505}506507static const struct dxil_type *508create_float_type(struct dxil_module *m, unsigned bit_size)509{510struct dxil_type *type = create_type(m, TYPE_FLOAT);511if (type)512type->float_bits = bit_size;513return type;514}515516const struct dxil_type *517dxil_module_get_int_type(struct dxil_module *m, unsigned bit_size)518{519switch (bit_size) {520case 1: return get_int1_type(m);521case 8: return get_int8_type(m);522case 16: return get_int16_type(m);523case 32: return get_int32_type(m);524case 64: return get_int64_type(m);525default:526unreachable("unsupported bit-width");527}528}529530static const struct dxil_type *531get_float16_type(struct dxil_module *m)532{533if (!m->float16_type)534m->float16_type = create_float_type(m, 16);535return m->float16_type;536}537538static const struct dxil_type *539get_float32_type(struct dxil_module *m)540{541if (!m->float32_type)542m->float32_type = create_float_type(m, 32);543return m->float32_type;544}545546static const struct dxil_type *547get_float64_type(struct dxil_module *m)548{549if (!m->float64_type)550m->float64_type = create_float_type(m, 64);551return m->float64_type;552}553554const struct dxil_type *555dxil_module_get_float_type(struct dxil_module *m, unsigned bit_size)556{557switch (bit_size) {558case 16: return get_float16_type(m);559case 32: return get_float32_type(m);560case 64: return get_float64_type(m);561default:562unreachable("unsupported bit-width");563}564return get_float32_type(m);565}566567const struct dxil_type *568dxil_module_get_pointer_type(struct dxil_module *m,569const struct dxil_type *target)570{571struct dxil_type *type;572LIST_FOR_EACH_ENTRY(type, &m->type_list, head) {573if (type->type == TYPE_POINTER &&574type->ptr_target_type == target)575return type;576}577578type = create_type(m, TYPE_POINTER);579if (type)580type->ptr_target_type = target;581return type;582}583584const struct dxil_type *585dxil_module_get_struct_type(struct dxil_module *m,586const char *name,587const struct dxil_type **elem_types,588size_t num_elem_types)589{590assert(!name || strlen(name) > 0);591592struct dxil_type *type;593LIST_FOR_EACH_ENTRY(type, &m->type_list, head) {594if (type->type != TYPE_STRUCT)595continue;596597if ((name == NULL) != (type->struct_def.name == NULL))598continue;599600if (name && strcmp(type->struct_def.name, name))601continue;602603if (type->struct_def.elem.num_types == num_elem_types &&604!memcmp(type->struct_def.elem.types, elem_types,605sizeof(struct dxil_type *) * num_elem_types))606return type;607}608609type = create_type(m, TYPE_STRUCT);610if (type) {611if (name) {612type->struct_def.name = ralloc_strdup(type, name);613if (!type->struct_def.name)614return NULL;615} else616type->struct_def.name = NULL;617618type->struct_def.elem.types = ralloc_array(type, struct dxil_type *,619num_elem_types);620if (!type->struct_def.elem.types)621return NULL;622623memcpy(type->struct_def.elem.types, elem_types,624sizeof(struct dxil_type *) * num_elem_types);625type->struct_def.elem.num_types = num_elem_types;626}627return type;628}629630const struct dxil_type *631dxil_module_get_array_type(struct dxil_module *m,632const struct dxil_type *elem_type,633size_t num_elems)634{635struct dxil_type *type;636LIST_FOR_EACH_ENTRY(type, &m->type_list, head) {637if (type->type != TYPE_ARRAY)638continue;639640if (type->array_or_vector_def.elem_type == elem_type &&641type->array_or_vector_def.num_elems == num_elems)642return type;643}644645type = create_type(m, TYPE_ARRAY);646if (type) {647type->array_or_vector_def.elem_type = elem_type;648type->array_or_vector_def.num_elems = num_elems;649}650return type;651}652653const struct dxil_type *654dxil_module_get_vector_type(struct dxil_module *m,655const struct dxil_type *elem_type,656size_t num_elems)657{658struct dxil_type *type;659LIST_FOR_EACH_ENTRY(type, &m->type_list, head) {660if (type->type == TYPE_VECTOR &&661type->array_or_vector_def.elem_type == elem_type &&662type->array_or_vector_def.num_elems == num_elems)663return type;664}665666type = create_type(m, TYPE_VECTOR);667if (!type)668return NULL;669670type->array_or_vector_def.elem_type = elem_type;671type->array_or_vector_def.num_elems = num_elems;672return type;673}674675const struct dxil_type *676dxil_get_overload_type(struct dxil_module *mod, enum overload_type overload)677{678switch (overload) {679case DXIL_I16: return get_int16_type(mod);680case DXIL_I32: return get_int32_type(mod);681case DXIL_I64: return get_int64_type(mod);682case DXIL_F16: return get_float16_type(mod);683case DXIL_F32: return get_float32_type(mod);684case DXIL_F64: return get_float64_type(mod);685default:686unreachable("unexpected overload type");687}688}689690const struct dxil_type *691dxil_module_get_handle_type(struct dxil_module *m)692{693const struct dxil_type *int8_type = get_int8_type(m);694if (!int8_type)695return NULL;696697const struct dxil_type *ptr_type = dxil_module_get_pointer_type(m, int8_type);698if (!ptr_type)699return NULL;700701return dxil_module_get_struct_type(m, "dx.types.Handle", &ptr_type, 1);702}703704const struct dxil_type *705dxil_module_get_cbuf_ret_type(struct dxil_module *mod, enum overload_type overload)706{707const struct dxil_type *overload_type = dxil_get_overload_type(mod, overload);708const struct dxil_type *fields[4] = { overload_type, overload_type, overload_type, overload_type };709unsigned num_fields;710711char name[64];712snprintf(name, sizeof(name), "dx.types.CBufRet.%s", dxil_overload_suffix(overload));713714switch (overload) {715case DXIL_I32:716case DXIL_F32:717num_fields = 4;718break;719case DXIL_I64:720case DXIL_F64:721num_fields = 2;722break;723default:724unreachable("unexpected overload type");725}726727return dxil_module_get_struct_type(mod, name, fields, num_fields);728}729730const struct dxil_type *731dxil_module_get_split_double_ret_type(struct dxil_module *mod)732{733const struct dxil_type *int32_type = dxil_module_get_int_type(mod, 32);734const struct dxil_type *fields[2] = { int32_type, int32_type };735736return dxil_module_get_struct_type(mod, "dx.types.splitDouble", fields, 2);737}738739static const struct dxil_type *740dxil_module_get_type_from_comp_type(struct dxil_module *m, enum dxil_component_type comp_type)741{742switch (comp_type) {743case DXIL_COMP_TYPE_U32: return get_int32_type(m);744case DXIL_COMP_TYPE_I32: return get_int32_type(m);745case DXIL_COMP_TYPE_F32: return get_float32_type(m);746case DXIL_COMP_TYPE_F64: return get_float64_type(m);747case DXIL_COMP_TYPE_U16: return get_int16_type(m);748case DXIL_COMP_TYPE_I16: return get_int16_type(m);749case DXIL_COMP_TYPE_U64: return get_int64_type(m);750case DXIL_COMP_TYPE_I64: return get_int64_type(m);751case DXIL_COMP_TYPE_I1: return get_int1_type(m);752753case DXIL_COMP_TYPE_F16:754default:755unreachable("unexpected component type");756}757}758759static const char *760get_res_comp_type_name(enum dxil_component_type comp_type)761{762switch (comp_type) {763case DXIL_COMP_TYPE_F64: return "double";764case DXIL_COMP_TYPE_F32: return "float";765case DXIL_COMP_TYPE_I32: return "int";766case DXIL_COMP_TYPE_U32: return "uint";767case DXIL_COMP_TYPE_I64: return "int64";768case DXIL_COMP_TYPE_U64: return "uint64";769default:770unreachable("unexpected resource component type");771}772}773774static const char *775get_res_dimension_type_name(enum dxil_resource_kind kind)776{777switch (kind) {778case DXIL_RESOURCE_KIND_TYPED_BUFFER: return "Buffer";779case DXIL_RESOURCE_KIND_TEXTURE1D: return "Texture1D";780case DXIL_RESOURCE_KIND_TEXTURE1D_ARRAY: return "Texture1DArray";781case DXIL_RESOURCE_KIND_TEXTURE2D: return "Texture2D";782case DXIL_RESOURCE_KIND_TEXTURE2DMS: return "Texture2DMS";783case DXIL_RESOURCE_KIND_TEXTURE2D_ARRAY: return "Texture2DArray";784case DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY: return "Texture2DMSArray";785case DXIL_RESOURCE_KIND_TEXTURE3D: return "Texture3D";786case DXIL_RESOURCE_KIND_TEXTURECUBE: return "TextureCube";787case DXIL_RESOURCE_KIND_TEXTURECUBE_ARRAY: return "TextureCubeArray";788default:789unreachable("unexpected resource kind");790}791}792793static const char *794get_res_ms_postfix(enum dxil_resource_kind kind)795{796switch (kind) {797case DXIL_RESOURCE_KIND_TEXTURE2DMS:798case DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY:799return ", 0";800801default:802return " ";803}804}805const struct dxil_type *806dxil_module_get_res_type(struct dxil_module *m, enum dxil_resource_kind kind,807enum dxil_component_type comp_type, bool readwrite)808{809switch (kind) {810case DXIL_RESOURCE_KIND_TYPED_BUFFER:811case DXIL_RESOURCE_KIND_TEXTURE1D:812case DXIL_RESOURCE_KIND_TEXTURE1D_ARRAY:813case DXIL_RESOURCE_KIND_TEXTURE2D:814case DXIL_RESOURCE_KIND_TEXTURE2D_ARRAY:815case DXIL_RESOURCE_KIND_TEXTURE2DMS:816case DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY:817case DXIL_RESOURCE_KIND_TEXTURE3D:818case DXIL_RESOURCE_KIND_TEXTURECUBE:819case DXIL_RESOURCE_KIND_TEXTURECUBE_ARRAY:820{821const struct dxil_type *component_type = dxil_module_get_type_from_comp_type(m, comp_type);822const struct dxil_type *vec_type = dxil_module_get_vector_type(m, component_type, 4);823char class_name[64] = { 0 };824snprintf(class_name, 64, "class.%s%s<vector<%s, 4>%s>",825readwrite ? "RW" : "",826get_res_dimension_type_name(kind),827get_res_comp_type_name(comp_type),828get_res_ms_postfix(kind));829return dxil_module_get_struct_type(m, class_name, &vec_type, 1);830}831832case DXIL_RESOURCE_KIND_RAW_BUFFER:833{834const struct dxil_type *component_type = dxil_module_get_int_type(m, 32);835char class_name[64] = { 0 };836snprintf(class_name, 64, "struct.%sByteAddressBuffer", readwrite ? "RW" : "");837return dxil_module_get_struct_type(m, class_name, &component_type, 1);838}839840default:841unreachable("resource type not supported");842}843}844845const struct dxil_type *846dxil_module_get_resret_type(struct dxil_module *m, enum overload_type overload)847{848const struct dxil_type *overload_type = dxil_get_overload_type(m, overload);849const struct dxil_type *int32_type = dxil_module_get_int_type(m, 32);850const char *name;851if (!overload_type)852return NULL;853854const struct dxil_type *resret[] =855{ overload_type, overload_type, overload_type, overload_type, int32_type };856857switch (overload) {858case DXIL_I32: name = "dx.types.ResRet.i32"; break;859case DXIL_I64: name = "dx.types.ResRet.i64"; break;860case DXIL_F32: name = "dx.types.ResRet.f32"; break;861case DXIL_F64: name = "dx.types.ResRet.f64"; break;862default:863unreachable("unexpected overload type");864}865866return dxil_module_get_struct_type(m, name, resret, 5);867}868869const struct dxil_type *870dxil_module_get_dimret_type(struct dxil_module *m)871{872const struct dxil_type *int32_type = dxil_module_get_int_type(m, 32);873874const struct dxil_type *dimret[] =875{ int32_type, int32_type, int32_type, int32_type };876877return dxil_module_get_struct_type(m, "dx.types.Dimensions", dimret, 4);878}879880const struct dxil_type *881dxil_module_add_function_type(struct dxil_module *m,882const struct dxil_type *ret_type,883const struct dxil_type **arg_types,884size_t num_arg_types)885{886struct dxil_type *type = create_type(m, TYPE_FUNCTION);887if (type) {888type->function_def.args.types = ralloc_array(type,889struct dxil_type *,890num_arg_types);891if (!type->function_def.args.types)892return NULL;893894memcpy(type->function_def.args.types, arg_types,895sizeof(struct dxil_type *) * num_arg_types);896type->function_def.args.num_types = num_arg_types;897type->function_def.ret_type = ret_type;898}899return type;900}901902903enum type_codes {904TYPE_CODE_NUMENTRY = 1,905TYPE_CODE_VOID = 2,906TYPE_CODE_FLOAT = 3,907TYPE_CODE_DOUBLE = 4,908TYPE_CODE_LABEL = 5,909TYPE_CODE_OPAQUE = 6,910TYPE_CODE_INTEGER = 7,911TYPE_CODE_POINTER = 8,912TYPE_CODE_FUNCTION_OLD = 9,913TYPE_CODE_HALF = 10,914TYPE_CODE_ARRAY = 11,915TYPE_CODE_VECTOR = 12,916TYPE_CODE_X86_FP80 = 13,917TYPE_CODE_FP128 = 14,918TYPE_CODE_PPC_FP128 = 15,919TYPE_CODE_METADATA = 16,920TYPE_CODE_X86_MMX = 17,921TYPE_CODE_STRUCT_ANON = 18,922TYPE_CODE_STRUCT_NAME = 19,923TYPE_CODE_STRUCT_NAMED = 20,924TYPE_CODE_FUNCTION = 21925};926927#define LITERAL(x) { DXIL_OP_LITERAL, { (x) } }928#define FIXED(x) { DXIL_OP_FIXED, { (x) } }929#define VBR(x) { DXIL_OP_VBR, { (x) } }930#define ARRAY { DXIL_OP_ARRAY, { 0 } }931#define CHAR6 { DXIL_OP_CHAR6, { 0 } }932#define BLOB { DXIL_OP_BLOB, { 0 } }933934#define TYPE_INDEX FIXED(32)935936enum type_table_abbrev_id {937TYPE_TABLE_ABBREV_POINTER,938TYPE_TABLE_ABBREV_FUNCTION,939TYPE_TABLE_ABBREV_STRUCT_ANON,940TYPE_TABLE_ABBREV_STRUCT_NAME,941TYPE_TABLE_ABBREV_STRUCT_NAMED,942TYPE_TABLE_ABBREV_ARRAY,943TYPE_TABLE_ABBREV_VECTOR,944};945946static const struct dxil_abbrev947type_table_abbrevs[] = {948[TYPE_TABLE_ABBREV_POINTER] = {949{ LITERAL(TYPE_CODE_POINTER), TYPE_INDEX, LITERAL(0) }, 3950},951[TYPE_TABLE_ABBREV_FUNCTION] = {952{ LITERAL(TYPE_CODE_FUNCTION), FIXED(1), ARRAY, TYPE_INDEX }, 4953},954[TYPE_TABLE_ABBREV_STRUCT_ANON] = {955{ LITERAL(TYPE_CODE_STRUCT_ANON), FIXED(1), ARRAY, TYPE_INDEX }, 4956},957[TYPE_TABLE_ABBREV_STRUCT_NAME] = {958{ LITERAL(TYPE_CODE_STRUCT_NAME), ARRAY, CHAR6 }, 3959},960[TYPE_TABLE_ABBREV_STRUCT_NAMED] = {961{ LITERAL(TYPE_CODE_STRUCT_NAMED), FIXED(1), ARRAY, TYPE_INDEX }, 4962},963[TYPE_TABLE_ABBREV_ARRAY] = {964{ LITERAL(TYPE_CODE_ARRAY), VBR(8), TYPE_INDEX }, 3965},966[TYPE_TABLE_ABBREV_VECTOR] = {967{ LITERAL(TYPE_CODE_VECTOR), VBR(8), TYPE_INDEX }, 3968},969};970971static bool972emit_type_table_abbrev_record(struct dxil_module *m,973enum type_table_abbrev_id abbrev,974const uint64_t *data, size_t size)975{976assert(abbrev < ARRAY_SIZE(type_table_abbrevs));977return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,978type_table_abbrevs + abbrev, data, size);979}980981enum constant_code {982CST_CODE_SETTYPE = 1,983CST_CODE_NULL = 2,984CST_CODE_UNDEF = 3,985CST_CODE_INTEGER = 4,986CST_CODE_WIDE_INTEGER = 5,987CST_CODE_FLOAT = 6,988CST_CODE_AGGREGATE = 7,989CST_CODE_STRING = 8,990CST_CODE_CSTRING = 9,991CST_CODE_CE_BINOP = 10,992CST_CODE_CE_CAST = 11,993CST_CODE_CE_GEP = 12,994CST_CODE_CE_SELECT = 13,995CST_CODE_CE_EXTRACTELT = 14,996CST_CODE_CE_INSERTELT = 15,997CST_CODE_CE_SHUFFLEVEC = 16,998CST_CODE_CE_CMP = 17,999CST_CODE_INLINEASM_OLD = 18,1000CST_CODE_CE_SHUFVEC_EX = 19,1001CST_CODE_CE_INBOUNDS_GEP = 20,1002CST_CODE_BLOCKADDRESS = 21,1003CST_CODE_DATA = 22,1004CST_CODE_INLINEASM = 231005};10061007enum const_abbrev_id {1008CONST_ABBREV_SETTYPE,1009CONST_ABBREV_INTEGER,1010CONST_ABBREV_CE_CAST,1011CONST_ABBREV_NULL,1012};10131014static const struct dxil_abbrev1015const_abbrevs[] = {1016[CONST_ABBREV_SETTYPE] = { { LITERAL(CST_CODE_SETTYPE), TYPE_INDEX }, 2 },1017[CONST_ABBREV_INTEGER] = { { LITERAL(CST_CODE_INTEGER), VBR(8) }, 2 },1018[CONST_ABBREV_CE_CAST] = {1019{ LITERAL(CST_CODE_CE_CAST), FIXED(4), TYPE_INDEX, VBR(8) }, 41020},1021[CONST_ABBREV_NULL] = { { LITERAL(CST_CODE_NULL) }, 1 },1022};10231024static bool1025emit_const_abbrev_record(struct dxil_module *m, enum const_abbrev_id abbrev,1026const uint64_t *data, size_t size)1027{1028assert(abbrev < ARRAY_SIZE(const_abbrevs));10291030return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,1031const_abbrevs + abbrev, data, size);1032}10331034enum function_code {1035FUNC_CODE_DECLAREBLOCKS = 1,1036FUNC_CODE_INST_BINOP = 2,1037FUNC_CODE_INST_CAST = 3,1038FUNC_CODE_INST_GEP_OLD = 4,1039FUNC_CODE_INST_SELECT = 5,1040FUNC_CODE_INST_EXTRACTELT = 6,1041FUNC_CODE_INST_INSERTELT = 7,1042FUNC_CODE_INST_SHUFFLEVEC = 8,1043FUNC_CODE_INST_CMP = 9,1044FUNC_CODE_INST_RET = 10,1045FUNC_CODE_INST_BR = 11,1046FUNC_CODE_INST_SWITCH = 12,1047FUNC_CODE_INST_INVOKE = 13,1048/* 14: unused */1049FUNC_CODE_INST_UNREACHABLE = 15,1050FUNC_CODE_INST_PHI = 16,1051/* 17-18: unused */1052FUNC_CODE_INST_ALLOCA = 19,1053FUNC_CODE_INST_LOAD = 20,1054/* 21-22: unused */1055FUNC_CODE_INST_VAARG = 23,1056FUNC_CODE_INST_STORE_OLD = 24,1057/* 25: unused */1058FUNC_CODE_INST_EXTRACTVAL = 26,1059FUNC_CODE_INST_INSERTVAL = 27,1060FUNC_CODE_INST_CMP2 = 28,1061FUNC_CODE_INST_VSELECT = 29,1062FUNC_CODE_INST_INBOUNDS_GEP_OLD = 30,1063FUNC_CODE_INST_INDIRECTBR = 31,1064/* 32: unused */1065FUNC_CODE_DEBUG_LOC_AGAIN = 33,1066FUNC_CODE_INST_CALL = 34,1067FUNC_CODE_DEBUG_LOC = 35,1068FUNC_CODE_INST_FENCE = 36,1069FUNC_CODE_INST_CMPXCHG_OLD = 37,1070FUNC_CODE_INST_ATOMICRMW = 38,1071FUNC_CODE_INST_RESUME = 39,1072FUNC_CODE_INST_LANDINGPAD_OLD = 40,1073FUNC_CODE_INST_LOADATOMIC = 41,1074FUNC_CODE_INST_STOREATOMIC_OLD = 42,1075FUNC_CODE_INST_GEP = 43,1076FUNC_CODE_INST_STORE = 44,1077FUNC_CODE_INST_STOREATOMIC = 45,1078FUNC_CODE_INST_CMPXCHG = 46,1079FUNC_CODE_INST_LANDINGPAD = 47,1080};10811082enum func_abbrev_id {1083FUNC_ABBREV_LOAD,1084FUNC_ABBREV_BINOP,1085FUNC_ABBREV_BINOP_FLAGS,1086FUNC_ABBREV_CAST,1087FUNC_ABBREV_RET_VOID,1088FUNC_ABBREV_RET_VAL,1089FUNC_ABBREV_UNREACHABLE,1090FUNC_ABBREV_GEP,1091};10921093static const struct dxil_abbrev1094func_abbrevs[] = {1095[FUNC_ABBREV_LOAD] = {1096{ LITERAL(FUNC_CODE_INST_LOAD), VBR(6), TYPE_INDEX, VBR(4),1097FIXED(1) }, 51098},1099[FUNC_ABBREV_BINOP] = {1100{ LITERAL(FUNC_CODE_INST_BINOP), VBR(6), VBR(6), FIXED(4) }, 41101},1102[FUNC_ABBREV_BINOP_FLAGS] = {1103{ LITERAL(FUNC_CODE_INST_BINOP), VBR(6), VBR(6), FIXED(4),1104FIXED(7) }, 51105},1106[FUNC_ABBREV_CAST] = {1107{ LITERAL(FUNC_CODE_INST_CAST), VBR(6), TYPE_INDEX, FIXED(4) }, 41108},1109[FUNC_ABBREV_RET_VOID] = { { LITERAL(FUNC_CODE_INST_RET) }, 1 },1110[FUNC_ABBREV_RET_VAL] = { { LITERAL(FUNC_CODE_INST_RET), VBR(6) }, 2 },1111[FUNC_ABBREV_UNREACHABLE] = {1112{ LITERAL(FUNC_CODE_INST_UNREACHABLE) }, 11113},1114[FUNC_ABBREV_GEP] = {1115{ LITERAL(FUNC_CODE_INST_GEP), FIXED(1), TYPE_INDEX, ARRAY,1116VBR(6) }, 51117},1118};11191120static bool1121emit_func_abbrev_record(struct dxil_module *m, enum func_abbrev_id abbrev,1122const uint64_t *data, size_t size)1123{1124assert(abbrev < ARRAY_SIZE(func_abbrevs));1125return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,1126func_abbrevs + abbrev, data, size);1127}11281129static bool1130define_abbrev(struct dxil_module *m, const struct dxil_abbrev *a)1131{1132if (!dxil_buffer_emit_abbrev_id(&m->buf, DXIL_DEFINE_ABBREV) ||1133!dxil_buffer_emit_vbr_bits(&m->buf, a->num_operands, 5))1134return false;11351136for (int i = 0; i < a->num_operands; ++i) {1137unsigned is_literal = a->operands[i].type == DXIL_OP_LITERAL;1138if (!dxil_buffer_emit_bits(&m->buf, is_literal, 1))1139return false;1140if (a->operands[i].type == DXIL_OP_LITERAL) {1141if (!dxil_buffer_emit_vbr_bits(&m->buf, a->operands[i].value, 8))1142return false;1143} else {1144if (!dxil_buffer_emit_bits(&m->buf, a->operands[i].type, 3))1145return false;1146if (a->operands[i].type == DXIL_OP_FIXED) {1147if (!dxil_buffer_emit_vbr_bits(&m->buf,1148a->operands[i].encoding_data, 5))1149return false;1150} else if (a->operands[i].type == DXIL_OP_VBR) {1151if (!dxil_buffer_emit_vbr_bits(&m->buf,1152a->operands[i].encoding_data, 5))1153return false;1154}1155}1156}11571158return true;1159}11601161enum dxil_blockinfo_code {1162DXIL_BLOCKINFO_CODE_SETBID = 1,1163DXIL_BLOCKINFO_CODE_BLOCKNAME = 2,1164DXIL_BLOCKINFO_CODE_SETRECORDNAME = 31165};11661167static bool1168switch_to_block(struct dxil_module *m, uint32_t block)1169{1170return emit_record_int(m, DXIL_BLOCKINFO_CODE_SETBID, block);1171}11721173enum dxil_standard_block {1174DXIL_BLOCKINFO = 0,1175DXIL_FIRST_APPLICATION_BLOCK = 81176};11771178enum dxil_llvm_block {1179DXIL_MODULE = DXIL_FIRST_APPLICATION_BLOCK,1180DXIL_PARAMATTR = DXIL_FIRST_APPLICATION_BLOCK + 1,1181DXIL_PARAMATTR_GROUP = DXIL_FIRST_APPLICATION_BLOCK + 2,1182DXIL_CONST_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 3,1183DXIL_FUNCTION_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 4,1184DXIL_VALUE_SYMTAB_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 6,1185DXIL_METADATA_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 7,1186DXIL_TYPE_BLOCK = DXIL_FIRST_APPLICATION_BLOCK + 9,1187};11881189enum value_symtab_code {1190VST_CODE_ENTRY = 1,1191VST_CODE_BBENTRY = 21192};11931194enum value_symtab_abbrev_id {1195VST_ABBREV_ENTRY_8,1196VST_ABBREV_ENTRY_7,1197VST_ABBREV_ENTRY_6,1198VST_ABBREV_BBENTRY_6,1199};12001201static struct dxil_abbrev value_symtab_abbrevs[] = {1202[VST_ABBREV_ENTRY_8] = { { FIXED(3), VBR(8), ARRAY, FIXED(8) }, 4 },1203[VST_ABBREV_ENTRY_7] = {1204{ LITERAL(VST_CODE_ENTRY), VBR(8), ARRAY, FIXED(7), }, 41205},1206[VST_ABBREV_ENTRY_6] = {1207{ LITERAL(VST_CODE_ENTRY), VBR(8), ARRAY, CHAR6, }, 41208},1209[VST_ABBREV_BBENTRY_6] = {1210{ LITERAL(VST_CODE_BBENTRY), VBR(8), ARRAY, CHAR6, }, 41211},1212};12131214static bool1215emit_value_symtab_abbrevs(struct dxil_module *m)1216{1217if (!switch_to_block(m, DXIL_VALUE_SYMTAB_BLOCK))1218return false;12191220for (int i = 0; i < ARRAY_SIZE(value_symtab_abbrevs); ++i) {1221if (!define_abbrev(m, value_symtab_abbrevs + i))1222return false;1223}12241225return true;1226}12271228static bool1229emit_const_abbrevs(struct dxil_module *m)1230{1231if (!switch_to_block(m, DXIL_CONST_BLOCK))1232return false;12331234for (int i = 0; i < ARRAY_SIZE(const_abbrevs); ++i) {1235if (!define_abbrev(m, const_abbrevs + i))1236return false;1237}12381239return true;1240}12411242static bool1243emit_function_abbrevs(struct dxil_module *m)1244{1245if (!switch_to_block(m, DXIL_FUNCTION_BLOCK))1246return false;12471248for (int i = 0; i < ARRAY_SIZE(func_abbrevs); ++i) {1249if (!define_abbrev(m, func_abbrevs + i))1250return false;1251}12521253return true;1254}12551256static bool1257emit_blockinfo(struct dxil_module *m)1258{1259return enter_subblock(m, DXIL_BLOCKINFO, 2) &&1260emit_value_symtab_abbrevs(m) &&1261emit_const_abbrevs(m) &&1262emit_function_abbrevs(m) &&1263exit_block(m);1264}12651266enum attribute_codes {1267PARAMATTR_GRP_CODE_ENTRY = 3,1268PARAMATTR_CODE_ENTRY = 21269};12701271static bool1272emit_attrib_group(struct dxil_module *m, int id, uint32_t slot,1273const struct dxil_attrib *attrs, size_t num_attrs)1274{1275uint64_t record[64];1276record[0] = id;1277record[1] = slot;1278size_t size = 2;12791280for (int i = 0; i < num_attrs; ++i) {1281switch (attrs[i].type) {1282case DXIL_ATTR_ENUM:1283assert(size < ARRAY_SIZE(record) - 2);1284record[size++] = 0;1285record[size++] = attrs[i].kind;1286break;12871288default:1289unreachable("unsupported attrib type");1290}1291}12921293return emit_record(m, PARAMATTR_GRP_CODE_ENTRY, record, size);1294}12951296static bool1297emit_attrib_group_table(struct dxil_module *m)1298{1299if (!enter_subblock(m, DXIL_PARAMATTR_GROUP, 3))1300return false;13011302struct attrib_set *as;1303int id = 1;1304LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) {1305if (!emit_attrib_group(m, id, UINT32_MAX, as->attrs, as->num_attrs))1306return false;1307id++;1308}13091310return exit_block(m);1311}13121313static bool1314emit_attribute_table(struct dxil_module *m)1315{1316if (!enter_subblock(m, DXIL_PARAMATTR, 3))1317return false;13181319struct attrib_set *as;1320int id = 1;1321LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) {1322if (!emit_record_int(m, PARAMATTR_CODE_ENTRY, id))1323return false;1324id++;1325}13261327return exit_block(m);1328}13291330static bool1331emit_type_table_abbrevs(struct dxil_module *m)1332{1333for (int i = 0; i < ARRAY_SIZE(type_table_abbrevs); ++i) {1334if (!define_abbrev(m, type_table_abbrevs + i))1335return false;1336}13371338return true;1339}13401341static bool1342emit_float_type(struct dxil_module *m, unsigned bit_size)1343{1344switch (bit_size) {1345case 16: return emit_record(m, TYPE_CODE_HALF, NULL, 0);1346case 32: return emit_record(m, TYPE_CODE_FLOAT, NULL, 0);1347case 64: return emit_record(m, TYPE_CODE_DOUBLE, NULL, 0);1348default:1349unreachable("unexpected bit_size for float type");1350}1351}13521353static bool1354emit_pointer_type(struct dxil_module *m, int type_index)1355{1356uint64_t data[] = { TYPE_CODE_POINTER, type_index, 0 };1357return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_POINTER,1358data, ARRAY_SIZE(data));1359}13601361static bool1362emit_struct_name(struct dxil_module *m, const char *name)1363{1364uint64_t temp[256];1365assert(strlen(name) < ARRAY_SIZE(temp));13661367for (int i = 0; i < strlen(name); ++i)1368temp[i] = name[i];13691370return emit_record(m, TYPE_CODE_STRUCT_NAME, temp, strlen(name));1371}13721373static bool1374emit_struct_name_char6(struct dxil_module *m, const char *name)1375{1376uint64_t temp[256];1377assert(strlen(name) < ARRAY_SIZE(temp) - 1);13781379temp[0] = TYPE_CODE_STRUCT_NAME;1380for (int i = 0; i < strlen(name); ++i)1381temp[i + 1] = name[i];13821383return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_STRUCT_NAME,1384temp, 1 + strlen(name));1385}13861387static bool1388emit_struct_type(struct dxil_module *m, const struct dxil_type *type)1389{1390enum type_table_abbrev_id abbrev = TYPE_TABLE_ABBREV_STRUCT_ANON;1391enum type_codes type_code = TYPE_CODE_STRUCT_ANON;1392if (type->struct_def.name) {1393abbrev = TYPE_TABLE_ABBREV_STRUCT_NAMED;1394type_code = TYPE_CODE_STRUCT_NAMED;1395if (is_char6_string(type->struct_def.name)) {1396if (!emit_struct_name_char6(m, type->struct_def.name))1397return false;1398} else {1399if (!emit_struct_name(m, type->struct_def.name))1400return false;1401}1402}14031404uint64_t temp[256];1405assert(type->struct_def.elem.num_types < ARRAY_SIZE(temp) - 2);1406temp[0] = type_code;1407temp[1] = 0; /* packed */1408for (int i = 0; i < type->struct_def.elem.num_types; ++i) {1409assert(type->struct_def.elem.types[i]->id >= 0);1410temp[2 + i] = type->struct_def.elem.types[i]->id;1411}14121413return emit_type_table_abbrev_record(m, abbrev, temp,14142 + type->struct_def.elem.num_types);1415}14161417static bool1418emit_array_type(struct dxil_module *m, const struct dxil_type *type)1419{1420assert(type->array_or_vector_def.elem_type->id >= 0);1421uint64_t data[] = {1422TYPE_CODE_ARRAY,1423type->array_or_vector_def.num_elems,1424type->array_or_vector_def.elem_type->id1425};1426return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_ARRAY, data,1427ARRAY_SIZE(data));1428}14291430static bool1431emit_function_type(struct dxil_module *m, const struct dxil_type *type)1432{1433uint64_t temp[256];1434assert(type->function_def.args.num_types < ARRAY_SIZE(temp) - 3);1435assert(type->function_def.ret_type->id >= 0);14361437temp[0] = TYPE_CODE_FUNCTION;1438temp[1] = 0; // vararg1439temp[2] = type->function_def.ret_type->id;1440for (int i = 0; i < type->function_def.args.num_types; ++i) {1441assert(type->function_def.args.types[i]->id >= 0);1442temp[3 + i] = type->function_def.args.types[i]->id;1443}14441445return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_FUNCTION,1446temp, 3 + type->function_def.args.num_types);1447}14481449static bool1450emit_vector_type(struct dxil_module *m, const struct dxil_type *type)1451{1452uint64_t temp[3];1453temp[0] = TYPE_CODE_VECTOR;1454temp[1] = type->array_or_vector_def.num_elems;1455temp[2] = type->array_or_vector_def.elem_type->id;14561457return emit_type_table_abbrev_record(m, TYPE_TABLE_ABBREV_VECTOR , temp, 3);1458}14591460static bool1461emit_metadata_type(struct dxil_module *m)1462{1463return emit_record(m, TYPE_CODE_METADATA, NULL, 0);1464}14651466static bool1467emit_type(struct dxil_module *m, struct dxil_type *type)1468{1469switch (type->type) {1470case TYPE_VOID:1471return emit_record(m, TYPE_CODE_VOID, NULL, 0);14721473case TYPE_INTEGER:1474return emit_record_int(m, TYPE_CODE_INTEGER, type->int_bits);14751476case TYPE_FLOAT:1477return emit_float_type(m, type->float_bits);14781479case TYPE_POINTER:1480return emit_pointer_type(m, type->ptr_target_type->id);14811482case TYPE_STRUCT:1483return emit_struct_type(m, type);14841485case TYPE_ARRAY:1486return emit_array_type(m, type);14871488case TYPE_FUNCTION:1489return emit_function_type(m, type);14901491case TYPE_VECTOR:1492return emit_vector_type(m, type);14931494default:1495unreachable("unexpected type->type");1496}1497}14981499static bool1500emit_type_table(struct dxil_module *m)1501{1502if (!enter_subblock(m, DXIL_TYPE_BLOCK, 4) ||1503!emit_type_table_abbrevs(m) ||1504!emit_record_int(m, 1, 1 + list_length(&m->type_list)))1505return false;15061507list_for_each_entry(struct dxil_type, type, &m->type_list, head) {1508if (!emit_type(m, type))1509return false;1510}15111512return emit_metadata_type(m) &&1513exit_block(m);1514}15151516static struct dxil_const *1517create_const(struct dxil_module *m, const struct dxil_type *type, bool undef)1518{1519struct dxil_const *ret = ralloc_size(m->ralloc_ctx,1520sizeof(struct dxil_const));1521if (ret) {1522ret->value.id = -1;1523ret->value.type = type;1524ret->undef = undef;1525list_addtail(&ret->head, &m->const_list);1526}1527return ret;1528}15291530static const struct dxil_value *1531get_int_const(struct dxil_module *m, const struct dxil_type *type,1532intmax_t value)1533{1534assert(type && type->type == TYPE_INTEGER);15351536struct dxil_const *c;1537LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {1538if (c->value.type != type || c->undef)1539continue;15401541if (c->int_value == value)1542return &c->value;1543}15441545c = create_const(m, type, false);1546if (!c)1547return NULL;15481549c->int_value = value;1550return &c->value;1551}15521553const struct dxil_value *1554dxil_module_get_int1_const(struct dxil_module *m, bool value)1555{1556const struct dxil_type *type = get_int1_type(m);1557if (!type)1558return NULL;15591560return get_int_const(m, type, value);1561}15621563const struct dxil_value *1564dxil_module_get_int8_const(struct dxil_module *m, int8_t value)1565{1566const struct dxil_type *type = get_int8_type(m);1567if (!type)1568return NULL;15691570return get_int_const(m, type, value);1571}15721573const struct dxil_value *1574dxil_module_get_int16_const(struct dxil_module *m, int16_t value)1575{1576const struct dxil_type *type = get_int16_type(m);1577if (!type)1578return NULL;15791580return get_int_const(m, type, value);1581}15821583const struct dxil_value *1584dxil_module_get_int32_const(struct dxil_module *m, int32_t value)1585{1586const struct dxil_type *type = get_int32_type(m);1587if (!type)1588return NULL;15891590return get_int_const(m, type, value);1591}15921593const struct dxil_value *1594dxil_module_get_int64_const(struct dxil_module *m, int64_t value)1595{1596const struct dxil_type *type = get_int64_type(m);1597if (!type)1598return NULL;15991600return get_int_const(m, type, value);1601}16021603const struct dxil_value *1604dxil_module_get_int_const(struct dxil_module *m, intmax_t value,1605unsigned bit_size)1606{1607switch (bit_size) {1608case 1:1609assert(value == 0 || value == 1);1610return dxil_module_get_int1_const(m, value);16111612case 8:1613assert(INT8_MIN <= value && value <= INT8_MAX);1614return dxil_module_get_int8_const(m, value);16151616case 16:1617assert(INT16_MIN <= value && value <= INT16_MAX);1618return dxil_module_get_int16_const(m, value);16191620case 32:1621assert(INT32_MIN <= value && value <= INT32_MAX);1622return dxil_module_get_int32_const(m, value);16231624case 64:1625assert(INT64_MIN <= value && value <= INT64_MAX);1626return dxil_module_get_int64_const(m, value);16271628default:1629unreachable("unsupported bit-width");1630}1631}16321633const struct dxil_value *1634dxil_module_get_float16_const(struct dxil_module *m, uint16_t value)1635{1636const struct dxil_type *type = get_float16_type(m);1637if (!type)1638return NULL;16391640struct dxil_const *c;1641LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {1642if (c->value.type != type || c->undef)1643continue;16441645if (c->int_value == (uintmax_t)value)1646return &c->value;1647}16481649c = create_const(m, type, false);1650if (!c)1651return NULL;16521653c->int_value = (uintmax_t)value;1654return &c->value;1655}16561657const struct dxil_value *1658dxil_module_get_float_const(struct dxil_module *m, float value)1659{1660const struct dxil_type *type = get_float32_type(m);1661if (!type)1662return NULL;16631664struct dxil_const *c;1665LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {1666if (c->value.type != type || c->undef)1667continue;16681669if (c->float_value == value)1670return &c->value;1671}16721673c = create_const(m, type, false);1674if (!c)1675return NULL;16761677c->float_value = value;1678return &c->value;1679}16801681const struct dxil_value *1682dxil_module_get_double_const(struct dxil_module *m, double value)1683{1684const struct dxil_type *type = get_float64_type(m);1685if (!type)1686return NULL;16871688struct dxil_const *c;1689LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {1690if (c->value.type != type || c->undef)1691continue;16921693if (c->float_value == value)1694return &c->value;1695}16961697c = create_const(m, type, false);1698if (!c)1699return NULL;17001701c->float_value = value;1702return &c->value;1703}17041705const struct dxil_value *1706dxil_module_get_array_const(struct dxil_module *m, const struct dxil_type *type,1707const struct dxil_value **values)1708{1709assert(type->type == TYPE_ARRAY);1710unsigned int num_values = type->array_or_vector_def.num_elems;17111712struct dxil_const *c;1713LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {1714if (c->value.type != type || c->undef)1715continue;17161717if (!memcmp(c->array_values, values, sizeof(*values) * num_values))1718return &c->value;1719}17201721c = create_const(m, type, false);1722if (!c)1723return NULL;1724void *tmp =1725ralloc_array(m->ralloc_ctx, struct dxil_value *, num_values);1726memcpy(tmp, values, sizeof(*values) * num_values);1727c->array_values = tmp;17281729return &c->value;1730}17311732const struct dxil_value *1733dxil_module_get_undef(struct dxil_module *m, const struct dxil_type *type)1734{1735assert(type != NULL);17361737struct dxil_const *c;1738LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {1739if (c->value.type != type)1740continue;17411742if (c->undef)1743return &c->value;1744}17451746c = create_const(m, type, true);1747return c ? &c->value : NULL;1748}17491750enum dxil_module_code {1751DXIL_MODULE_CODE_VERSION = 1,1752DXIL_MODULE_CODE_TRIPLE = 2,1753DXIL_MODULE_CODE_DATALAYOUT = 3,1754DXIL_MODULE_CODE_ASM = 4,1755DXIL_MODULE_CODE_SECTIONNAME = 5,1756DXIL_MODULE_CODE_DEPLIB = 6,1757DXIL_MODULE_CODE_GLOBALVAR = 7,1758DXIL_MODULE_CODE_FUNCTION = 8,1759DXIL_MODULE_CODE_ALIAS = 9,1760DXIL_MODULE_CODE_PURGEVALS = 10,1761DXIL_MODULE_CODE_GCNAME = 11,1762DXIL_MODULE_CODE_COMDAT = 12,1763};17641765static bool1766emit_target_triple(struct dxil_module *m, const char *triple)1767{1768uint64_t temp[256];1769assert(strlen(triple) < ARRAY_SIZE(temp));17701771for (int i = 0; i < strlen(triple); ++i)1772temp[i] = triple[i];17731774return emit_record(m, DXIL_MODULE_CODE_TRIPLE, temp, strlen(triple));1775}17761777static bool1778emit_datalayout(struct dxil_module *m, const char *datalayout)1779{1780uint64_t temp[256];1781assert(strlen(datalayout) < ARRAY_SIZE(temp));17821783for (int i = 0; i < strlen(datalayout); ++i)1784temp[i] = datalayout[i];17851786return emit_record(m, DXIL_MODULE_CODE_DATALAYOUT,1787temp, strlen(datalayout));1788}17891790static const struct dxil_value *1791add_gvar(struct dxil_module *m, const char *name,1792const struct dxil_type *type, const struct dxil_type *value_type,1793enum dxil_address_space as, int align, const struct dxil_value *value)1794{1795struct dxil_gvar *gvar = ralloc_size(m->ralloc_ctx,1796sizeof(struct dxil_gvar));1797if (!gvar)1798return NULL;17991800gvar->type = type;1801gvar->name = ralloc_strdup(m->ralloc_ctx, name);1802gvar->as = as;1803gvar->align = align;1804gvar->constant = !!value;1805gvar->initializer = value;18061807gvar->value.id = -1;1808gvar->value.type = value_type;18091810list_addtail(&gvar->head, &m->gvar_list);1811return &gvar->value;1812}18131814const struct dxil_value *1815dxil_add_global_var(struct dxil_module *m, const char *name,1816const struct dxil_type *type,1817enum dxil_address_space as, int align,1818const struct dxil_value *value)1819{1820return add_gvar(m, name, type, type, as, align, value);1821}18221823const struct dxil_value *1824dxil_add_global_ptr_var(struct dxil_module *m, const char *name,1825const struct dxil_type *type,1826enum dxil_address_space as, int align,1827const struct dxil_value *value)1828{1829return add_gvar(m, name, type, dxil_module_get_pointer_type(m, type),1830as, align, value);1831}18321833static struct dxil_func *1834add_function(struct dxil_module *m, const char *name,1835const struct dxil_type *type,1836bool decl, unsigned attr_set)1837{1838assert(type->type == TYPE_FUNCTION);18391840struct dxil_func *func = ralloc_size(m->ralloc_ctx,1841sizeof(struct dxil_func));1842if (!func)1843return NULL;18441845func->name = ralloc_strdup(func, name);1846if (!func->name) {1847return NULL;1848}18491850func->type = type;1851func->decl = decl;1852func->attr_set = attr_set;18531854func->value.id = -1;1855func->value.type = type->function_def.ret_type;1856list_addtail(&func->head, &m->func_list);1857return func;1858}18591860const struct dxil_func *1861dxil_add_function_def(struct dxil_module *m, const char *name,1862const struct dxil_type *type)1863{1864return add_function(m, name, type, false, 0);1865}18661867static unsigned1868get_attr_set(struct dxil_module *m, enum dxil_attr_kind attr)1869{1870struct dxil_attrib attrs[2] = {1871{ DXIL_ATTR_ENUM, { DXIL_ATTR_KIND_NO_UNWIND } },1872{ DXIL_ATTR_ENUM, { attr } }1873};18741875int index = 1;1876struct attrib_set *as;1877LIST_FOR_EACH_ENTRY(as, &m->attr_set_list, head) {1878if (!memcmp(as->attrs, attrs, sizeof(attrs)))1879return index;1880index++;1881}18821883as = ralloc_size(m->ralloc_ctx, sizeof(struct attrib_set));1884if (!as)1885return 0;18861887memcpy(as->attrs, attrs, sizeof(attrs));1888as->num_attrs = 1;1889if (attr != DXIL_ATTR_KIND_NONE)1890as->num_attrs++;18911892list_addtail(&as->head, &m->attr_set_list);1893assert(list_length(&m->attr_set_list) == index);1894return index;1895}18961897const struct dxil_func *1898dxil_add_function_decl(struct dxil_module *m, const char *name,1899const struct dxil_type *type,1900enum dxil_attr_kind attr)1901{1902unsigned attr_set = get_attr_set(m, attr);1903if (!attr_set)1904return NULL;19051906return add_function(m, name, type, true, attr_set);1907}19081909static bool1910emit_module_info_function(struct dxil_module *m, int type, bool declaration,1911int attr_set_index)1912{1913uint64_t data[] = {1914type, 0/* address space */, declaration, 0/* linkage */,1915attr_set_index, 0/* alignment */, 0 /* section */, 0 /* visibility */,19160 /* GC */, 0 /* unnamed addr */, 0 /* prologue data */,19170 /* storage class */, 0 /* comdat */, 0 /* prefix-data */,19180 /* personality */1919};1920return emit_record(m, DXIL_MODULE_CODE_FUNCTION, data, ARRAY_SIZE(data));1921}19221923enum gvar_var_flags {1924GVAR_FLAG_CONSTANT = (1 << 0),1925GVAR_FLAG_EXPLICIT_TYPE = (1 << 1),1926};19271928enum gvar_var_linkage {1929GVAR_LINKAGE_EXTERNAL = 0,1930GVAR_LINKAGE_APPENDING = 2,1931GVAR_LINKAGE_INTERNAL = 3,1932GVAR_LINKAGE_EXTERNAL_WEAK = 7,1933GVAR_LINKAGE_COMMON = 8,1934GVAR_LINKAGE_PRIVATE = 9,1935GVAR_LINKAGE_AVAILABLE_EXTERNALLY = 12,1936GVAR_LINKAGE_WEAK_ANY = 16,1937GVAR_LINKAGE_WEAK_ODR = 17,1938GVAR_LINKAGE_LINK_ONCE_ODR = 19,1939};19401941static bool1942emit_module_info_global(struct dxil_module *m, const struct dxil_gvar *gvar,1943const struct dxil_abbrev *simple_gvar_abbr)1944{1945uint64_t data[] = {1946DXIL_MODULE_CODE_GLOBALVAR,1947gvar->type->id,1948(gvar->as << 2) | GVAR_FLAG_EXPLICIT_TYPE |1949(gvar->constant ? GVAR_FLAG_CONSTANT : 0),1950gvar->initializer ? gvar->initializer->id + 1 : 0,1951(gvar->initializer ? GVAR_LINKAGE_INTERNAL : GVAR_LINKAGE_EXTERNAL),1952util_logbase2(gvar->align) + 1,195301954};1955return emit_record_abbrev(&m->buf, 4, simple_gvar_abbr,1956data, ARRAY_SIZE(data));1957}19581959static bool1960emit_module_info(struct dxil_module *m)1961{1962struct dxil_gvar *gvar;1963int max_global_type = 0;1964int max_alignment = 0;1965LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) {1966assert(gvar->type->id >= 0);1967max_global_type = MAX2(max_global_type, gvar->type->id);1968max_alignment = MAX2(max_alignment, gvar->align);1969}19701971struct dxil_abbrev simple_gvar_abbr = {1972{ LITERAL(DXIL_MODULE_CODE_GLOBALVAR),1973FIXED(util_logbase2(max_global_type) + 1),1974VBR(6), VBR(6), FIXED(5),1975FIXED(util_logbase2(max_alignment) + 1),1976LITERAL(0) }, 71977};19781979if (!emit_target_triple(m, "dxil-ms-dx") ||1980!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") ||1981!define_abbrev(m, &simple_gvar_abbr))1982return false;19831984LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) {1985assert(gvar->type->id >= 0);1986if (!emit_module_info_global(m, gvar, &simple_gvar_abbr))1987return false;1988}19891990struct dxil_func *func;1991LIST_FOR_EACH_ENTRY(func, &m->func_list, head) {1992assert(func->type->id >= 0);1993if (!emit_module_info_function(m, func->type->id, func->decl,1994func->attr_set))1995return false;1996}19971998return true;1999}20002001static bool2002emit_module_const_abbrevs(struct dxil_module *m)2003{2004/* these are unused for now, so let's not even record them */2005struct dxil_abbrev abbrevs[] = {2006{ { LITERAL(CST_CODE_AGGREGATE), ARRAY, FIXED(5) }, 3 },2007{ { LITERAL(CST_CODE_STRING), ARRAY, FIXED(8) }, 3 },2008{ { LITERAL(CST_CODE_CSTRING), ARRAY, FIXED(7) }, 3 },2009{ { LITERAL(CST_CODE_CSTRING), ARRAY, CHAR6 }, 3 },2010};20112012for (int i = 0; i < ARRAY_SIZE(abbrevs); ++i) {2013if (!define_abbrev(m, abbrevs + i))2014return false;2015}20162017return true;2018}20192020static bool2021emit_set_type(struct dxil_module *m, unsigned type_index)2022{2023uint64_t data[] = { CST_CODE_SETTYPE, type_index };2024return emit_const_abbrev_record(m, CONST_ABBREV_SETTYPE,2025data, ARRAY_SIZE(data));2026}20272028static bool2029emit_null_value(struct dxil_module *m)2030{2031return emit_record_no_abbrev(&m->buf, CST_CODE_NULL, NULL, 0);2032}20332034static bool2035emit_undef_value(struct dxil_module *m)2036{2037return emit_record_no_abbrev(&m->buf, CST_CODE_UNDEF, NULL, 0);2038}20392040static uint64_t2041encode_signed(int64_t value)2042{2043return value >= 0 ?2044(value << 1) :2045((-value << 1) | 1);2046}20472048static bool2049emit_int_value(struct dxil_module *m, int64_t value)2050{2051if (!value)2052return emit_null_value(m);20532054uint64_t data[] = { CST_CODE_INTEGER, encode_signed(value) };2055return emit_const_abbrev_record(m, CONST_ABBREV_INTEGER,2056data, ARRAY_SIZE(data));2057}20582059static bool2060emit_float16_value(struct dxil_module *m, uint16_t value)2061{2062if (!value)2063return emit_null_value(m);2064uint64_t data = value;2065return emit_record_no_abbrev(&m->buf, CST_CODE_FLOAT, &data, 1);2066}20672068static bool2069emit_float_value(struct dxil_module *m, float value)2070{2071uint64_t data = fui(value);2072if (data == UINT32_C(0))2073return emit_null_value(m);2074return emit_record_no_abbrev(&m->buf, CST_CODE_FLOAT, &data, 1);2075}20762077static bool2078emit_double_value(struct dxil_module *m, double value)2079{2080union di u;2081u.d = value;2082if (u.ui == UINT64_C(0))2083return emit_null_value(m);2084return emit_record_no_abbrev(&m->buf, CST_CODE_FLOAT, &u.ui, 1);2085}20862087static bool2088emit_aggregate_values(struct dxil_module *m, const struct dxil_value **values,2089int num_values)2090{2091uint64_t *value_ids = ralloc_array(m->ralloc_ctx, uint64_t, num_values);2092int i;20932094for (i = 0; i < num_values; i++)2095value_ids[i] = values[i]->id;20962097return emit_record_no_abbrev(&m->buf, CST_CODE_AGGREGATE, value_ids,2098num_values);2099}21002101static bool2102emit_consts(struct dxil_module *m)2103{2104const struct dxil_type *curr_type = NULL;2105struct dxil_const *c;2106LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {2107assert(c->value.id >= 0);2108assert(c->value.type != NULL);2109if (curr_type != c->value.type) {2110assert(c->value.type->id >= 0);2111if (!emit_set_type(m, c->value.type->id))2112return false;2113curr_type = c->value.type;2114}21152116if (c->undef) {2117if (!emit_undef_value(m))2118return false;2119continue;2120}21212122switch (curr_type->type) {2123case TYPE_INTEGER:2124if (!emit_int_value(m, c->int_value))2125return false;2126break;21272128case TYPE_FLOAT:2129switch (curr_type->float_bits) {2130case 16:2131if (!emit_float16_value(m, (uint16_t)(uintmax_t)c->int_value))2132return false;2133break;2134case 32:2135if (!emit_float_value(m, c->float_value))2136return false;2137break;2138case 64:2139if (!emit_double_value(m, c->float_value))2140return false;2141break;2142default:2143unreachable("unexpected float_bits");2144}2145break;21462147case TYPE_ARRAY:2148if (!emit_aggregate_values(m, c->array_values,2149c->value.type->array_or_vector_def.num_elems))2150return false;2151break;21522153default:2154unreachable("unsupported constant type");2155}2156}21572158return true;2159}21602161static bool2162emit_module_consts(struct dxil_module *m)2163{2164return enter_subblock(m, DXIL_CONST_BLOCK, 4) &&2165emit_module_const_abbrevs(m) &&2166emit_consts(m) &&2167exit_block(m);2168}21692170static bool2171emit_value_symtab_abbrev_record(struct dxil_module *m,2172enum value_symtab_abbrev_id abbrev,2173const uint64_t *data, size_t size)2174{2175assert(abbrev < ARRAY_SIZE(value_symtab_abbrevs));2176return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,2177value_symtab_abbrevs + abbrev, data, size);2178}21792180static bool2181emit_symtab_entry(struct dxil_module *m, unsigned value, const char *name)2182{2183uint64_t temp[256];2184assert(strlen(name) < ARRAY_SIZE(temp) - 2);21852186temp[0] = VST_CODE_ENTRY;2187temp[1] = value;2188for (int i = 0; i < strlen(name); ++i)2189temp[i + 2] = name[i];21902191enum value_symtab_abbrev_id abbrev = VST_ABBREV_ENTRY_8;2192if (is_char6_string(name))2193abbrev = VST_ABBREV_ENTRY_6;2194else if (is_char7_string(name))2195abbrev = VST_ABBREV_ENTRY_7;21962197return emit_value_symtab_abbrev_record(m, abbrev, temp, 2 + strlen(name));2198}21992200static bool2201emit_value_symbol_table(struct dxil_module *m)2202{2203if (!enter_subblock(m, DXIL_VALUE_SYMTAB_BLOCK, 4))2204return false;22052206struct dxil_func *func;2207LIST_FOR_EACH_ENTRY(func, &m->func_list, head) {2208if (!emit_symtab_entry(m, func->value.id, func->name))2209return false;2210}2211struct dxil_gvar *gvar;2212LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) {2213if (!emit_symtab_entry(m, gvar->value.id, gvar->name))2214return false;2215}2216return exit_block(m);2217}22182219enum metadata_codes {2220METADATA_STRING = 1,2221METADATA_VALUE = 2,2222METADATA_NODE = 3,2223METADATA_NAME = 4,2224METADATA_KIND = 6,2225METADATA_NAMED_NODE = 102226};22272228enum metadata_abbrev_id {2229METADATA_ABBREV_STRING,2230METADATA_ABBREV_NAME2231};22322233static const struct dxil_abbrev metadata_abbrevs[] = {2234[METADATA_ABBREV_STRING] = {2235{ LITERAL(METADATA_STRING), ARRAY, FIXED(8) }, 32236},2237[METADATA_ABBREV_NAME] = {2238{ LITERAL(METADATA_NAME), ARRAY, FIXED(8) }, 32239},2240};22412242static bool2243emit_metadata_abbrevs(struct dxil_module *m)2244{2245for (int i = 0; i < ARRAY_SIZE(metadata_abbrevs); ++i) {2246if (!define_abbrev(m, metadata_abbrevs + i))2247return false;2248}2249return true;2250}22512252static struct dxil_mdnode *2253create_mdnode(struct dxil_module *m, enum mdnode_type type)2254{2255struct dxil_mdnode *ret = rzalloc_size(m->ralloc_ctx,2256sizeof(struct dxil_mdnode));2257if (ret) {2258ret->type = type;2259ret->id = list_length(&m->mdnode_list) + 1; /* zero is reserved for NULL nodes */2260list_addtail(&ret->head, &m->mdnode_list);2261}2262return ret;2263}22642265const struct dxil_mdnode *2266dxil_get_metadata_string(struct dxil_module *m, const char *str)2267{2268assert(str);22692270struct dxil_mdnode *n;2271LIST_FOR_EACH_ENTRY(n, &m->mdnode_list, head) {2272if (n->type == MD_STRING &&2273!strcmp(n->string, str))2274return n;2275}22762277n = create_mdnode(m, MD_STRING);2278if (n) {2279n->string = ralloc_strdup(n, str);2280if (!n->string)2281return NULL;2282}2283return n;2284}22852286const struct dxil_mdnode *2287dxil_get_metadata_value(struct dxil_module *m, const struct dxil_type *type,2288const struct dxil_value *value)2289{2290struct dxil_mdnode *n;2291LIST_FOR_EACH_ENTRY(n, &m->mdnode_list, head) {2292if (n->type == MD_VALUE &&2293n->value.type == type &&2294n->value.value == value)2295return n;2296}22972298n = create_mdnode(m, MD_VALUE);2299if (n) {2300n->value.type = type;2301n->value.value = value;2302}2303return n;2304}23052306const struct dxil_mdnode *2307dxil_get_metadata_func(struct dxil_module *m, const struct dxil_func *func)2308{2309const struct dxil_type *ptr_type =2310dxil_module_get_pointer_type(m, func->type);2311return dxil_get_metadata_value(m, ptr_type, &func->value);2312}23132314const struct dxil_mdnode *2315dxil_get_metadata_node(struct dxil_module *m,2316const struct dxil_mdnode *subnodes[],2317size_t num_subnodes)2318{2319struct dxil_mdnode *n;2320LIST_FOR_EACH_ENTRY(n, &m->mdnode_list, head) {2321if (n->type == MD_NODE &&2322n->node.num_subnodes == num_subnodes &&2323!memcmp(n->node.subnodes, subnodes, sizeof(struct dxil_mdnode *) *2324num_subnodes))2325return n;2326}23272328n = create_mdnode(m, MD_NODE);2329if (n) {2330void *tmp = ralloc_array(n, struct dxil_mdnode *, num_subnodes);2331if (!tmp)2332return NULL;23332334memcpy(tmp, subnodes, sizeof(struct dxil_mdnode *) * num_subnodes);2335n->node.subnodes = tmp;2336n->node.num_subnodes = num_subnodes;2337}2338return n;2339}23402341const struct dxil_mdnode *2342dxil_get_metadata_int1(struct dxil_module *m, bool value)2343{2344const struct dxil_type *type = get_int1_type(m);2345if (!type)2346return NULL;23472348const struct dxil_value *const_value = get_int_const(m, type, value);2349if (!const_value)2350return NULL;23512352return dxil_get_metadata_value(m, type, const_value);2353}23542355const struct dxil_mdnode *2356dxil_get_metadata_int8(struct dxil_module *m, int8_t value)2357{2358const struct dxil_type *type = get_int8_type(m);2359if (!type)2360return NULL;23612362const struct dxil_value *const_value = get_int_const(m, type, value);2363if (!const_value)2364return NULL;23652366return dxil_get_metadata_value(m, type, const_value);2367}23682369const struct dxil_mdnode *2370dxil_get_metadata_int32(struct dxil_module *m, int32_t value)2371{2372const struct dxil_type *type = get_int32_type(m);2373if (!type)2374return NULL;23752376const struct dxil_value *const_value = get_int_const(m, type, value);2377if (!const_value)2378return NULL;23792380return dxil_get_metadata_value(m, type, const_value);2381}23822383const struct dxil_mdnode *2384dxil_get_metadata_int64(struct dxil_module *m, int64_t value)2385{2386const struct dxil_type *type = get_int64_type(m);2387if (!type)2388return NULL;23892390const struct dxil_value *const_value = get_int_const(m, type, value);2391if (!const_value)2392return NULL;23932394return dxil_get_metadata_value(m, type, const_value);2395}23962397bool2398dxil_add_metadata_named_node(struct dxil_module *m, const char *name,2399const struct dxil_mdnode *subnodes[],2400size_t num_subnodes)2401{2402struct dxil_named_node *n = ralloc_size(m->ralloc_ctx,2403sizeof(struct dxil_named_node));2404if (!n)2405return false;24062407n->name = ralloc_strdup(n, name);2408if (!n->name)2409return false;24102411void *tmp = ralloc_array(n, struct dxil_mdnode *, num_subnodes);2412if (!tmp)2413return false;24142415memcpy(tmp, subnodes, sizeof(struct dxil_mdnode *) * num_subnodes);2416n->subnodes = tmp;2417n->num_subnodes = num_subnodes;24182419list_addtail(&n->head, &m->md_named_node_list);2420return true;2421}24222423static bool2424emit_metadata_value(struct dxil_module *m, const struct dxil_type *type,2425const struct dxil_value *value)2426{2427assert(type->id >= 0 && value->id >= 0);2428uint64_t data[2] = { type->id, value->id };2429return emit_record(m, METADATA_VALUE, data, ARRAY_SIZE(data));2430}24312432static bool2433emit_metadata_abbrev_record(struct dxil_module *m,2434enum metadata_abbrev_id abbrev,2435const uint64_t *data, size_t size)2436{2437assert(abbrev < ARRAY_SIZE(metadata_abbrevs));2438return emit_record_abbrev(&m->buf, abbrev + DXIL_FIRST_APPLICATION_ABBREV,2439metadata_abbrevs + abbrev, data, size);2440}24412442static bool2443emit_metadata_string(struct dxil_module *m, const char *str)2444{2445uint64_t data[256];2446assert(strlen(str) < ARRAY_SIZE(data) - 1);2447data[0] = METADATA_STRING;2448for (size_t i = 0; i < strlen(str); ++i)2449data[i + 1] = str[i];24502451return emit_metadata_abbrev_record(m, METADATA_ABBREV_STRING,2452data, strlen(str) + 1);2453}24542455static bool2456emit_metadata_node(struct dxil_module *m,2457const struct dxil_mdnode *subnodes[],2458size_t num_subnodes)2459{2460uint64_t data[256];2461assert(num_subnodes < ARRAY_SIZE(data));2462for (size_t i = 0; i < num_subnodes; ++i)2463data[i] = subnodes[i] ? subnodes[i]->id : 0;24642465return emit_record(m, METADATA_NODE, data, num_subnodes);2466}24672468static bool2469emit_mdnode(struct dxil_module *m, struct dxil_mdnode *n)2470{2471switch (n->type) {2472case MD_STRING:2473return emit_metadata_string(m, n->string);24742475case MD_VALUE:2476return emit_metadata_value(m, n->value.type, n->value.value);24772478case MD_NODE:2479return emit_metadata_node(m, n->node.subnodes, n->node.num_subnodes);24802481default:2482unreachable("unexpected n->type");2483}2484}24852486static bool2487emit_metadata_nodes(struct dxil_module *m)2488{2489list_for_each_entry(struct dxil_mdnode, n, &m->mdnode_list, head) {2490if (!emit_mdnode(m, n))2491return false;2492}2493return true;2494}24952496static bool2497emit_metadata_name(struct dxil_module *m, const char *name)2498{2499uint64_t data[256];2500assert(strlen(name) < ARRAY_SIZE(data) - 1);2501data[0] = METADATA_NAME;2502for (size_t i = 0; i < strlen(name); ++i)2503data[i + 1] = name[i];25042505return emit_metadata_abbrev_record(m, METADATA_ABBREV_NAME,2506data, strlen(name) + 1);2507}25082509static bool2510emit_metadata_named_node(struct dxil_module *m, const char *name,2511const struct dxil_mdnode *subnodes[],2512size_t num_subnodes)2513{2514uint64_t data[256];2515assert(num_subnodes < ARRAY_SIZE(data));2516for (size_t i = 0; i < num_subnodes; ++i) {2517assert(subnodes[i]->id > 0); /* NULL nodes not allowed */2518data[i] = subnodes[i]->id - 1;2519}25202521return emit_metadata_name(m, name) &&2522emit_record(m, METADATA_NAMED_NODE, data, num_subnodes);2523}25242525static bool2526emit_metadata_named_nodes(struct dxil_module *m)2527{2528struct dxil_named_node *n;2529LIST_FOR_EACH_ENTRY(n, &m->md_named_node_list, head) {2530if (!emit_metadata_named_node(m, n->name, n->subnodes,2531n->num_subnodes))2532return false;2533}2534return true;2535}25362537static bool2538emit_metadata(struct dxil_module *m)2539{2540return enter_subblock(m, DXIL_METADATA_BLOCK, 3) &&2541emit_metadata_abbrevs(m) &&2542emit_metadata_nodes(m) &&2543emit_metadata_named_nodes(m) &&2544exit_block(m);2545}25462547static struct dxil_instr *2548create_instr(struct dxil_module *m, enum instr_type type,2549const struct dxil_type *ret_type)2550{2551struct dxil_instr *ret = ralloc_size(m->ralloc_ctx,2552sizeof(struct dxil_instr));2553if (ret) {2554ret->type = type;2555ret->value.id = -1;2556ret->value.type = ret_type;2557ret->has_value = false;2558list_addtail(&ret->head, &m->instr_list);2559}2560return ret;2561}25622563static inline bool2564legal_arith_type(const struct dxil_type *type)2565{2566switch (type->type) {2567case TYPE_INTEGER:2568return type->int_bits == 1 ||2569type->int_bits == 16 ||2570type->int_bits == 32 ||2571type->int_bits == 64;25722573case TYPE_FLOAT:2574return type->float_bits == 16 ||2575type->float_bits == 32 ||2576type->float_bits == 64;25772578default:2579return false;2580}2581}25822583const struct dxil_value *2584dxil_emit_binop(struct dxil_module *m, enum dxil_bin_opcode opcode,2585const struct dxil_value *op0, const struct dxil_value *op1,2586enum dxil_opt_flags flags)2587{2588assert(types_equal(op0->type, op1->type));2589assert(legal_arith_type(op0->type));2590struct dxil_instr *instr = create_instr(m, INSTR_BINOP, op0->type);2591if (!instr)2592return NULL;25932594instr->binop.opcode = opcode;2595instr->binop.operands[0] = op0;2596instr->binop.operands[1] = op1;2597instr->binop.flags = flags;2598instr->has_value = true;2599return &instr->value;2600}26012602const struct dxil_value *2603dxil_emit_cmp(struct dxil_module *m, enum dxil_cmp_pred pred,2604const struct dxil_value *op0, const struct dxil_value *op1)2605{2606assert(types_equal(op0->type, op1->type));2607assert(legal_arith_type(op0->type));2608struct dxil_instr *instr = create_instr(m, INSTR_CMP, get_int1_type(m));2609if (!instr)2610return NULL;26112612instr->cmp.pred = pred;2613instr->cmp.operands[0] = op0;2614instr->cmp.operands[1] = op1;2615instr->has_value = true;2616return &instr->value;2617}26182619const struct dxil_value *2620dxil_emit_select(struct dxil_module *m,2621const struct dxil_value *op0,2622const struct dxil_value *op1,2623const struct dxil_value *op2)2624{2625assert(types_equal(op0->type, get_int1_type(m)));2626assert(types_equal(op1->type, op2->type));2627assert(legal_arith_type(op1->type));26282629struct dxil_instr *instr = create_instr(m, INSTR_SELECT, op1->type);2630if (!instr)2631return NULL;26322633instr->select.operands[0] = op0;2634instr->select.operands[1] = op1;2635instr->select.operands[2] = op2;2636instr->has_value = true;2637return &instr->value;2638}26392640const struct dxil_value *2641dxil_emit_cast(struct dxil_module *m, enum dxil_cast_opcode opcode,2642const struct dxil_type *type,2643const struct dxil_value *value)2644{2645assert(legal_arith_type(value->type));2646assert(legal_arith_type(type));26472648struct dxil_instr *instr = create_instr(m, INSTR_CAST, type);2649if (!instr)2650return NULL;26512652instr->cast.opcode = opcode;2653instr->cast.type = type;2654instr->cast.value = value;2655instr->has_value = true;2656return &instr->value;2657}26582659bool2660dxil_emit_branch(struct dxil_module *m, const struct dxil_value *cond,2661unsigned true_block, unsigned false_block)2662{2663assert(!cond || types_equal(cond->type, get_int1_type(m)));26642665struct dxil_instr *instr = create_instr(m, INSTR_BR,2666dxil_module_get_void_type(m));2667if (!instr)2668return false;26692670instr->br.cond = cond;2671instr->br.succ[0] = true_block;2672instr->br.succ[1] = false_block;2673m->curr_block++;2674return true;2675}26762677const struct dxil_value *2678dxil_instr_get_return_value(struct dxil_instr *instr)2679{2680return instr->has_value ? &instr->value : NULL;2681}26822683struct dxil_instr *2684dxil_emit_phi(struct dxil_module *m, const struct dxil_type *type)2685{2686assert(legal_arith_type(type));26872688struct dxil_instr *instr = create_instr(m, INSTR_PHI, type);2689if (!instr)2690return NULL;26912692instr->phi.type = type;2693instr->phi.num_incoming = 0;2694instr->has_value = true;26952696return instr;2697}26982699void2700dxil_phi_set_incoming(struct dxil_instr *instr,2701const struct dxil_value *incoming_values[],2702const unsigned incoming_blocks[],2703size_t num_incoming)2704{2705assert(instr->type == INSTR_PHI);2706assert(num_incoming > 0);2707assert(num_incoming < ARRAY_SIZE(instr->phi.incoming));2708for (int i = 0; i < num_incoming; ++i) {2709assert(incoming_values[i]);2710assert(types_equal(incoming_values[i]->type, instr->phi.type));27112712instr->phi.incoming[i].value = incoming_values[i];2713instr->phi.incoming[i].block = incoming_blocks[i];2714}2715instr->phi.num_incoming = num_incoming;2716}27172718static struct dxil_instr *2719create_call_instr(struct dxil_module *m,2720const struct dxil_func *func,2721const struct dxil_value **args, size_t num_args)2722{2723assert(num_args == func->type->function_def.args.num_types);2724for (size_t i = 0; i < num_args; ++ i)2725assert(types_equal(func->type->function_def.args.types[i], args[i]->type));27262727struct dxil_instr *instr = create_instr(m, INSTR_CALL,2728func->type->function_def.ret_type);2729if (instr) {2730instr->call.func = func;2731instr->call.args = ralloc_array(instr, struct dxil_value *, num_args);2732if (!args)2733return false;2734memcpy(instr->call.args, args, sizeof(struct dxil_value *) * num_args);2735instr->call.num_args = num_args;2736}2737return instr;2738}27392740const struct dxil_value *2741dxil_emit_call(struct dxil_module *m,2742const struct dxil_func *func,2743const struct dxil_value **args, size_t num_args)2744{2745assert(func->type->function_def.ret_type->type != TYPE_VOID);27462747struct dxil_instr *instr = create_call_instr(m, func, args, num_args);2748if (!instr)2749return NULL;27502751instr->has_value = true;2752return &instr->value;2753}27542755bool2756dxil_emit_call_void(struct dxil_module *m,2757const struct dxil_func *func,2758const struct dxil_value **args, size_t num_args)2759{2760assert(func->type->function_def.ret_type->type == TYPE_VOID);27612762struct dxil_instr *instr = create_call_instr(m, func, args, num_args);2763if (!instr)2764return false;27652766return true;2767}27682769bool2770dxil_emit_ret_void(struct dxil_module *m)2771{2772struct dxil_instr *instr = create_instr(m, INSTR_RET,2773dxil_module_get_void_type(m));2774if (!instr)2775return false;27762777instr->ret.value = NULL;2778m->curr_block++;2779return true;2780}27812782const struct dxil_value *2783dxil_emit_extractval(struct dxil_module *m, const struct dxil_value *src,2784const unsigned int index)2785{2786assert(src->type->type == TYPE_STRUCT);2787assert(index < src->type->struct_def.elem.num_types);27882789struct dxil_instr *instr =2790create_instr(m, INSTR_EXTRACTVAL,2791src->type->struct_def.elem.types[index]);2792if (!instr)2793return NULL;27942795instr->extractval.src = src;2796instr->extractval.type = src->type;2797instr->extractval.idx = index;2798instr->has_value = true;27992800return &instr->value;2801}28022803const struct dxil_value *2804dxil_emit_alloca(struct dxil_module *m, const struct dxil_type *alloc_type,2805const struct dxil_type *size_type,2806const struct dxil_value *size,2807unsigned int align)2808{2809assert(size_type && size_type->type == TYPE_INTEGER);28102811const struct dxil_type *return_type =2812dxil_module_get_pointer_type(m, alloc_type);2813if (!return_type)2814return NULL;28152816struct dxil_instr *instr = create_instr(m, INSTR_ALLOCA, return_type);2817if (!instr)2818return NULL;28192820instr->alloca.alloc_type = alloc_type;2821instr->alloca.size_type = size_type;2822instr->alloca.size = size;2823instr->alloca.align = util_logbase2(align) + 1;2824assert(instr->alloca.align < (1 << 5));2825instr->alloca.align |= 1 << 6;28262827instr->has_value = true;2828return &instr->value;2829}28302831static const struct dxil_type *2832get_deref_type(const struct dxil_type *type)2833{2834switch (type->type) {2835case TYPE_POINTER: return type->ptr_target_type;2836case TYPE_ARRAY: return type->array_or_vector_def.elem_type;2837default: unreachable("unexpected type");2838}2839}28402841const struct dxil_value *2842dxil_emit_gep_inbounds(struct dxil_module *m,2843const struct dxil_value **operands,2844size_t num_operands)2845{2846assert(num_operands > 0);2847const struct dxil_type *source_elem_type =2848get_deref_type(operands[0]->type);28492850const struct dxil_type *type = operands[0]->type;2851for (int i = 1; i < num_operands; ++i) {2852assert(operands[i]->type == get_int32_type(m));2853type = get_deref_type(type);2854}28552856type = dxil_module_get_pointer_type(m, type);2857if (!type)2858return NULL;28592860struct dxil_instr *instr = create_instr(m, INSTR_GEP, type);2861if (!instr)2862return NULL;28632864instr->gep.operands = ralloc_array(instr, struct dxil_value *,2865num_operands);2866if (!instr->gep.operands)2867return NULL;28682869instr->gep.source_elem_type = source_elem_type;2870memcpy(instr->gep.operands, operands,2871sizeof(struct dxil_value *) * num_operands);2872instr->gep.num_operands = num_operands;2873instr->gep.inbounds = true;28742875instr->has_value = true;2876return &instr->value;2877}28782879const struct dxil_value *2880dxil_emit_load(struct dxil_module *m, const struct dxil_value *ptr,2881unsigned align,2882bool is_volatile)2883{2884assert(ptr->type->type == TYPE_POINTER ||2885ptr->type->type == TYPE_ARRAY);2886const struct dxil_type *type = ptr->type->type == TYPE_POINTER ?2887ptr->type->ptr_target_type :2888ptr->type->array_or_vector_def.elem_type;28892890struct dxil_instr *instr = create_instr(m, INSTR_LOAD, type);2891if (!instr)2892return false;28932894instr->load.ptr = ptr;2895instr->load.type = type;2896instr->load.align = util_logbase2(align) + 1;2897instr->load.is_volatile = is_volatile;28982899instr->has_value = true;2900return &instr->value;2901}29022903bool2904dxil_emit_store(struct dxil_module *m, const struct dxil_value *value,2905const struct dxil_value *ptr, unsigned align,2906bool is_volatile)2907{2908assert(legal_arith_type(value->type));29092910struct dxil_instr *instr = create_instr(m, INSTR_STORE,2911dxil_module_get_void_type(m));2912if (!instr)2913return false;29142915instr->store.value = value;2916instr->store.ptr = ptr;2917instr->store.align = util_logbase2(align) + 1;2918instr->store.is_volatile = is_volatile;2919return true;2920}29212922const struct dxil_value *2923dxil_emit_cmpxchg(struct dxil_module *m, const struct dxil_value *cmpval,2924const struct dxil_value *newval,2925const struct dxil_value *ptr, bool is_volatile,2926enum dxil_atomic_ordering ordering,2927enum dxil_sync_scope syncscope)2928{2929assert(ptr->type->type == TYPE_POINTER);29302931struct dxil_instr *instr = create_instr(m, INSTR_CMPXCHG,2932ptr->type->ptr_target_type);2933if (!instr)2934return false;29352936instr->cmpxchg.cmpval = cmpval;2937instr->cmpxchg.newval = newval;2938instr->cmpxchg.ptr = ptr;2939instr->cmpxchg.is_volatile = is_volatile;2940instr->cmpxchg.ordering = ordering;2941instr->cmpxchg.syncscope = syncscope;29422943instr->has_value = true;2944return &instr->value;2945}29462947const struct dxil_value *2948dxil_emit_atomicrmw(struct dxil_module *m, const struct dxil_value *value,2949const struct dxil_value *ptr, enum dxil_rmw_op op,2950bool is_volatile, enum dxil_atomic_ordering ordering,2951enum dxil_sync_scope syncscope)2952{2953assert(ptr->type->type == TYPE_POINTER);29542955struct dxil_instr *instr = create_instr(m, INSTR_ATOMICRMW,2956ptr->type->ptr_target_type);2957if (!instr)2958return false;29592960instr->atomicrmw.value = value;2961instr->atomicrmw.ptr = ptr;2962instr->atomicrmw.op = op;2963instr->atomicrmw.is_volatile = is_volatile;2964instr->atomicrmw.ordering = ordering;2965instr->atomicrmw.syncscope = syncscope;29662967instr->has_value = true;2968return &instr->value;2969}29702971static bool2972emit_binop(struct dxil_module *m, struct dxil_instr *instr)2973{2974assert(instr->type == INSTR_BINOP);2975assert(instr->value.id > instr->binop.operands[0]->id);2976assert(instr->value.id > instr->binop.operands[1]->id);29772978if (instr->binop.flags) {2979uint64_t data[] = {2980FUNC_CODE_INST_BINOP,2981instr->value.id - instr->binop.operands[0]->id,2982instr->value.id - instr->binop.operands[1]->id,2983instr->binop.opcode,2984instr->binop.flags2985};2986return emit_func_abbrev_record(m, FUNC_ABBREV_BINOP_FLAGS,2987data, ARRAY_SIZE(data));2988}2989uint64_t data[] = {2990FUNC_CODE_INST_BINOP,2991instr->value.id - instr->binop.operands[0]->id,2992instr->value.id - instr->binop.operands[1]->id,2993instr->binop.opcode2994};2995return emit_func_abbrev_record(m, FUNC_ABBREV_BINOP,2996data, ARRAY_SIZE(data));2997}29982999static bool3000emit_cmp(struct dxil_module *m, struct dxil_instr *instr)3001{3002assert(instr->type == INSTR_CMP);3003assert(instr->value.id > instr->cmp.operands[0]->id);3004assert(instr->value.id > instr->cmp.operands[1]->id);3005uint64_t data[] = {3006instr->value.id - instr->cmp.operands[0]->id,3007instr->value.id - instr->cmp.operands[1]->id,3008instr->cmp.pred3009};3010return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_CMP2,3011data, ARRAY_SIZE(data));3012}30133014static bool3015emit_select(struct dxil_module *m, struct dxil_instr *instr)3016{3017assert(instr->type == INSTR_SELECT);3018assert(instr->value.id > instr->select.operands[0]->id);3019assert(instr->value.id > instr->select.operands[1]->id);3020assert(instr->value.id > instr->select.operands[2]->id);3021uint64_t data[] = {3022instr->value.id - instr->select.operands[1]->id,3023instr->value.id - instr->select.operands[2]->id,3024instr->value.id - instr->select.operands[0]->id3025};3026return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_VSELECT,3027data, ARRAY_SIZE(data));3028}30293030static bool3031emit_cast(struct dxil_module *m, struct dxil_instr *instr)3032{3033assert(instr->type == INSTR_CAST);3034assert(instr->value.id > instr->cast.value->id);3035uint64_t data[] = {3036FUNC_CODE_INST_CAST,3037instr->value.id - instr->cast.value->id,3038instr->cast.type->id,3039instr->cast.opcode3040};3041return emit_func_abbrev_record(m, FUNC_ABBREV_CAST,3042data, ARRAY_SIZE(data));3043}30443045static bool3046emit_branch(struct dxil_module *m, struct dxil_instr *instr)3047{3048assert(instr->type == INSTR_BR);3049assert(instr->br.succ[0] < m->num_basic_block_ids);3050assert(m->basic_block_ids[instr->br.succ[0]] >= 0);30513052if (!instr->br.cond) {3053/* unconditional branch */3054uint64_t succ = m->basic_block_ids[instr->br.succ[0]];3055return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_BR, &succ, 1);3056}3057/* conditional branch */3058assert(instr->value.id > instr->br.cond->id);3059assert(instr->br.succ[1] < m->num_basic_block_ids);3060assert(m->basic_block_ids[instr->br.succ[1]] >= 0);30613062uint64_t data[] = {3063m->basic_block_ids[instr->br.succ[0]],3064m->basic_block_ids[instr->br.succ[1]],3065instr->value.id - instr->br.cond->id3066};3067return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_BR,3068data, ARRAY_SIZE(data));3069}30703071static bool3072emit_phi(struct dxil_module *m, struct dxil_instr *instr)3073{3074assert(instr->type == INSTR_PHI);3075uint64_t data[128];3076data[0] = instr->phi.type->id;3077assert(instr->phi.num_incoming > 0);3078for (int i = 0; i < instr->phi.num_incoming; ++i) {3079int64_t value_delta = instr->value.id - instr->phi.incoming[i].value->id;3080data[1 + i * 2] = encode_signed(value_delta);3081assert(instr->phi.incoming[i].block < m->num_basic_block_ids);3082assert(m->basic_block_ids[instr->phi.incoming[i].block] >= 0);3083data[1 + i * 2 + 1] = m->basic_block_ids[instr->phi.incoming[i].block];3084}3085return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_PHI,3086data, 1 + 2 * instr->phi.num_incoming);3087}30883089static bool3090emit_extractval(struct dxil_module *m, struct dxil_instr *instr)3091{3092assert(instr->type == INSTR_EXTRACTVAL);3093assert(instr->value.id > instr->extractval.src->id);3094assert(instr->value.id > instr->extractval.type->id);30953096/* relative value ID, followed by absolute type ID (only if3097* forward-declared), followed by n indices */3098uint64_t data[] = {3099instr->value.id - instr->extractval.src->id,3100instr->extractval.idx3101};3102return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_EXTRACTVAL,3103data, ARRAY_SIZE(data));3104}31053106static bool3107emit_call(struct dxil_module *m, struct dxil_instr *instr)3108{3109assert(instr->type == INSTR_CALL);3110assert(instr->call.func->value.id >= 0 && instr->value.id >= 0);3111assert(instr->call.func->type->id >= 0);3112assert(instr->call.func->value.id <= instr->value.id);3113int value_id_delta = instr->value.id - instr->call.func->value.id;31143115uint64_t data[256];3116data[0] = 0; // attribute id3117data[1] = 1 << 15; // calling convention etc3118data[2] = instr->call.func->type->id;3119data[3] = value_id_delta;31203121assert(instr->call.num_args < ARRAY_SIZE(data) - 4);3122for (size_t i = 0; i < instr->call.num_args; ++i) {3123assert(instr->call.args[i]->id >= 0);3124data[4 + i] = instr->value.id - instr->call.args[i]->id;3125}31263127return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_CALL,3128data, 4 + instr->call.num_args);3129}31303131static bool3132emit_ret(struct dxil_module *m, struct dxil_instr *instr)3133{3134assert(instr->type == INSTR_RET);31353136if (instr->ret.value) {3137assert(instr->ret.value->id >= 0);3138uint64_t data[] = { FUNC_CODE_INST_RET, instr->ret.value->id };3139return emit_func_abbrev_record(m, FUNC_ABBREV_RET_VAL,3140data, ARRAY_SIZE(data));3141}31423143uint64_t data[] = { FUNC_CODE_INST_RET };3144return emit_func_abbrev_record(m, FUNC_ABBREV_RET_VOID,3145data, ARRAY_SIZE(data));3146}31473148static bool3149emit_alloca(struct dxil_module *m, struct dxil_instr *instr)3150{3151assert(instr->type == INSTR_ALLOCA);3152assert(instr->alloca.alloc_type->id >= 0);3153assert(instr->alloca.size_type->id >= 0);3154assert(instr->alloca.size->id >= 0);31553156uint64_t data[] = {3157instr->alloca.alloc_type->id,3158instr->alloca.size_type->id,3159instr->alloca.size->id,3160instr->alloca.align,3161};3162return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_ALLOCA,3163data, ARRAY_SIZE(data));3164}31653166static bool3167emit_gep(struct dxil_module *m, struct dxil_instr *instr)3168{3169assert(instr->type == INSTR_GEP);3170assert(instr->gep.source_elem_type->id >= 0);31713172uint64_t data[256];3173data[0] = FUNC_CODE_INST_GEP;3174data[1] = instr->gep.inbounds;3175data[2] = instr->gep.source_elem_type->id;31763177assert(instr->gep.num_operands < ARRAY_SIZE(data) - 3);3178for (int i = 0; i < instr->gep.num_operands; ++i) {3179assert(instr->value.id > instr->gep.operands[i]->id);3180data[3 + i] = instr->value.id - instr->gep.operands[i]->id;3181}3182return emit_func_abbrev_record(m, FUNC_ABBREV_GEP,3183data, 3 + instr->gep.num_operands);3184}31853186static bool3187emit_load(struct dxil_module *m, struct dxil_instr *instr)3188{3189assert(instr->type == INSTR_LOAD);3190assert(instr->value.id > instr->load.ptr->id);3191assert(instr->load.type->id >= 0);31923193uint64_t data[] = {3194instr->value.id - instr->load.ptr->id,3195instr->load.type->id,3196instr->load.align,3197instr->load.is_volatile3198};3199return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_LOAD,3200data, ARRAY_SIZE(data));3201}3202static bool3203emit_store(struct dxil_module *m, struct dxil_instr *instr)3204{3205assert(instr->type == INSTR_STORE);3206assert(instr->value.id > instr->store.value->id);3207assert(instr->value.id > instr->store.ptr->id);32083209uint64_t data[] = {3210instr->value.id - instr->store.ptr->id,3211instr->value.id - instr->store.value->id,3212instr->store.align,3213instr->store.is_volatile3214};3215return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_STORE,3216data, ARRAY_SIZE(data));3217}32183219static bool3220emit_cmpxchg(struct dxil_module *m, struct dxil_instr *instr)3221{3222assert(instr->type == INSTR_CMPXCHG);3223assert(instr->value.id > instr->cmpxchg.cmpval->id);3224assert(instr->value.id > instr->cmpxchg.newval->id);3225assert(instr->value.id > instr->cmpxchg.ptr->id);3226uint64_t data[] = {3227instr->value.id - instr->cmpxchg.ptr->id,3228instr->value.id - instr->cmpxchg.cmpval->id,3229instr->value.id - instr->cmpxchg.newval->id,3230instr->cmpxchg.is_volatile,3231instr->cmpxchg.ordering,3232instr->cmpxchg.syncscope,3233};3234return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_CMPXCHG_OLD,3235data, ARRAY_SIZE(data));3236}32373238static bool3239emit_atomicrmw(struct dxil_module *m, struct dxil_instr *instr)3240{3241assert(instr->type == INSTR_ATOMICRMW);3242assert(instr->value.id > instr->atomicrmw.value->id);3243assert(instr->value.id > instr->atomicrmw.ptr->id);3244uint64_t data[] = {3245instr->value.id - instr->atomicrmw.ptr->id,3246instr->value.id - instr->atomicrmw.value->id,3247instr->atomicrmw.op,3248instr->atomicrmw.is_volatile,3249instr->atomicrmw.ordering,3250instr->atomicrmw.syncscope,3251};3252return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_ATOMICRMW,3253data, ARRAY_SIZE(data));3254}32553256static bool3257emit_instr(struct dxil_module *m, struct dxil_instr *instr)3258{3259switch (instr->type) {3260case INSTR_BINOP:3261return emit_binop(m, instr);32623263case INSTR_CMP:3264return emit_cmp(m, instr);32653266case INSTR_SELECT:3267return emit_select(m, instr);32683269case INSTR_CAST:3270return emit_cast(m, instr);32713272case INSTR_BR:3273return emit_branch(m, instr);32743275case INSTR_PHI:3276return emit_phi(m, instr);32773278case INSTR_CALL:3279return emit_call(m, instr);32803281case INSTR_RET:3282return emit_ret(m, instr);32833284case INSTR_EXTRACTVAL:3285return emit_extractval(m, instr);32863287case INSTR_ALLOCA:3288return emit_alloca(m, instr);32893290case INSTR_GEP:3291return emit_gep(m, instr);32923293case INSTR_LOAD:3294return emit_load(m, instr);32953296case INSTR_STORE:3297return emit_store(m, instr);32983299case INSTR_ATOMICRMW:3300return emit_atomicrmw(m, instr);33013302case INSTR_CMPXCHG:3303return emit_cmpxchg(m, instr);33043305default:3306unreachable("unexpected instruction type");3307}3308}33093310static bool3311emit_function(struct dxil_module *m)3312{3313if (!enter_subblock(m, DXIL_FUNCTION_BLOCK, 4) ||3314!emit_record_int(m, FUNC_CODE_DECLAREBLOCKS, m->curr_block))3315return false;33163317list_for_each_entry(struct dxil_instr, instr, &m->instr_list, head) {3318if (!emit_instr(m, instr))3319return false;3320}33213322return exit_block(m);3323}33243325static void3326assign_values(struct dxil_module *m)3327{3328int next_value_id = 0;33293330struct dxil_gvar *gvar;3331LIST_FOR_EACH_ENTRY(gvar, &m->gvar_list, head) {3332gvar->value.id = next_value_id++;3333}33343335struct dxil_func *func;3336LIST_FOR_EACH_ENTRY(func, &m->func_list, head) {3337func->value.id = next_value_id++;3338}33393340struct dxil_const *c;3341LIST_FOR_EACH_ENTRY(c, &m->const_list, head) {3342c->value.id = next_value_id++;3343}33443345struct dxil_instr *instr;3346LIST_FOR_EACH_ENTRY(instr, &m->instr_list, head) {3347instr->value.id = next_value_id;3348if (instr->has_value)3349next_value_id++;3350}3351}33523353bool3354dxil_emit_module(struct dxil_module *m)3355{3356assign_values(m);3357return dxil_buffer_emit_bits(&m->buf, 'B', 8) &&3358dxil_buffer_emit_bits(&m->buf, 'C', 8) &&3359dxil_buffer_emit_bits(&m->buf, 0xC0, 8) &&3360dxil_buffer_emit_bits(&m->buf, 0xDE, 8) &&3361enter_subblock(m, DXIL_MODULE, 3) &&3362emit_record_int(m, DXIL_MODULE_CODE_VERSION, 1) &&3363emit_blockinfo(m) &&3364emit_attrib_group_table(m) &&3365emit_attribute_table(m) &&3366emit_type_table(m) &&3367emit_module_info(m) &&3368emit_module_consts(m) &&3369emit_metadata(m) &&3370emit_value_symbol_table(m) &&3371emit_function(m) &&3372exit_block(m);3373}337433753376