Path: blob/21.2-virgl/src/microsoft/compiler/dxil_function.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_function.h"24#include "dxil_module.h"2526#define MAX_FUNC_PARAMS 172728struct predefined_func_descr {29const char *base_name;30const char *retval_descr;31const char *param_descr;32enum dxil_attr_kind attr;33};3435static struct predefined_func_descr predefined_funcs[] = {36{"dx.op.atomicBinOp", "O", "i@iiiii", DXIL_ATTR_KIND_READ_NONE},37{"dx.op.cbufferLoad", "O", "i@ii", DXIL_ATTR_KIND_READ_ONLY},38{"dx.op.cbufferLoadLegacy", "B", "i@i", DXIL_ATTR_KIND_READ_ONLY},39{"dx.op.createHandle", "@", "iciib", DXIL_ATTR_KIND_READ_ONLY},40{"dx.op.storeOutput", "v", "iiicO", DXIL_ATTR_KIND_NO_UNWIND},41{"dx.op.loadInput", "O", "iiici", DXIL_ATTR_KIND_READ_NONE},42{"dx.op.tertiary", "O", "iOOO", DXIL_ATTR_KIND_READ_NONE},43{"dx.op.threadId", "i", "ii", DXIL_ATTR_KIND_READ_NONE},44{"dx.op.threadIdInGroup", "i", "ii", DXIL_ATTR_KIND_READ_NONE},45{"dx.op.groupId", "i", "ii", DXIL_ATTR_KIND_READ_NONE},46{"dx.op.unary", "O", "iO", DXIL_ATTR_KIND_READ_NONE},47{"dx.op.unaryBits", "i", "iO", DXIL_ATTR_KIND_READ_NONE},48{"dx.op.isSpecialFloat", "b", "iO", DXIL_ATTR_KIND_READ_NONE},49{"dx.op.binary", "O", "iOO", DXIL_ATTR_KIND_READ_NONE},50{"dx.op.bufferStore", "v", "i@iiOOOOc", DXIL_ATTR_KIND_NONE},51{"dx.op.bufferLoad", "R", "i@ii", DXIL_ATTR_KIND_READ_ONLY},52{"dx.op.attributeAtVertex", "O", "iiicc", DXIL_ATTR_KIND_READ_NONE},53{"dx.op.sample", "R", "i@@ffffiiif", DXIL_ATTR_KIND_READ_ONLY},54{"dx.op.sampleBias", "R", "i@@ffffiiiff", DXIL_ATTR_KIND_READ_ONLY},55{"dx.op.sampleLevel", "R", "i@@ffffiiif", DXIL_ATTR_KIND_READ_ONLY},56{"dx.op.sampleGrad", "R", "i@@ffffiiifffffff", DXIL_ATTR_KIND_READ_ONLY},57{"dx.op.sampleCmp", "R", "i@@ffffiiiff", DXIL_ATTR_KIND_READ_ONLY},58{"dx.op.sampleCmpLevelZero", "R", "i@@ffffiiif", DXIL_ATTR_KIND_READ_ONLY},59{"dx.op.textureLoad", "R", "i@iiiiiii", DXIL_ATTR_KIND_READ_ONLY},60{"dx.op.discard", "v", "ib", DXIL_ATTR_KIND_READ_NONE},61{"dx.op.emitStream", "v", "ic", DXIL_ATTR_KIND_NONE},62{"dx.op.cutStream", "v", "ic", DXIL_ATTR_KIND_NONE},63{"dx.op.getDimensions", "D", "i@i", DXIL_ATTR_KIND_READ_ONLY},64{"dx.op.calculateLOD", "f", "i@@fffb", DXIL_ATTR_KIND_READ_ONLY},65{"dx.op.barrier", "v", "ii", DXIL_ATTR_KIND_NO_DUPLICATE},66{"dx.op.atomicCompareExchange", "O", "i@iiiii", DXIL_ATTR_KIND_READ_NONE},67{"dx.op.textureStore", "v", "i@iiiOOOOc", DXIL_ATTR_KIND_NONE},68{"dx.op.primitiveID", "i", "i", DXIL_ATTR_KIND_READ_NONE},69{"dx.op.legacyF16ToF32", "f", "ii", DXIL_ATTR_KIND_READ_ONLY},70{"dx.op.legacyF32ToF16", "i", "if", DXIL_ATTR_KIND_READ_ONLY},71{"dx.op.makeDouble", "g", "iii", DXIL_ATTR_KIND_READ_NONE},72{"dx.op.splitDouble", "G", "ig", DXIL_ATTR_KIND_READ_NONE},73};7475struct func_descr {76const char *name;77enum overload_type overload;78};7980struct func_rb_node {81struct rb_node node;82const struct dxil_func *func;83struct func_descr descr;84};8586static inline87const struct func_rb_node *88func_rb_node(const struct rb_node *n)89{90return (const struct func_rb_node *)n;91}9293static int94func_compare_to_name_and_overload(const struct rb_node *node, const void *data)95{96const struct func_descr *descr = (const struct func_descr *)data;97const struct func_rb_node *f = func_rb_node(node);98if (f->descr.overload < descr->overload)99return -1;100if (f->descr.overload > descr->overload)101return 1;102103return strcmp(f->descr.name, descr->name);104}105106static const struct dxil_func *107allocate_function_from_predefined(struct dxil_module *mod,108const char *name,109enum overload_type overload)110{111for (unsigned i = 0; i < ARRAY_SIZE(predefined_funcs); ++i) {112if (!strcmp(predefined_funcs[i].base_name, name)) {113return dxil_alloc_func(mod, name, overload,114predefined_funcs[i].retval_descr,115predefined_funcs[i].param_descr,116predefined_funcs[i].attr);117}118}119return false;120}121122const struct dxil_func *123dxil_get_function(struct dxil_module *mod,124const char *name, enum overload_type overload)125{126struct func_descr descr = { name, overload };127const struct rb_node *node = rb_tree_search(mod->functions, &descr,128func_compare_to_name_and_overload);129if (node)130return func_rb_node(node)->func;131132return allocate_function_from_predefined(mod, name, overload);133}134135static int func_compare_name(const struct rb_node *lhs, const struct rb_node *rhs)136{137const struct func_rb_node *node = func_rb_node(rhs);138return func_compare_to_name_and_overload(lhs, &node->descr);139}140141static void142dxil_add_function(struct rb_tree *functions, const struct dxil_func *func,143const char *name, enum overload_type overload)144{145struct func_rb_node *f = rzalloc(functions, struct func_rb_node);146f->func = func;147f->descr.name = name;148f->descr.overload = overload;149rb_tree_insert(functions, &f->node, func_compare_name);150}151152static const struct dxil_type *153get_type_from_string(struct dxil_module *mod, const char *param_descr,154enum overload_type overload, int *idx)155{156assert(param_descr);157char type_id = param_descr[(*idx)++];158assert(*idx <= (int)strlen(param_descr));159160switch (type_id) {161case DXIL_FUNC_PARAM_INT64: return dxil_module_get_int_type(mod, 64);162case DXIL_FUNC_PARAM_INT32: return dxil_module_get_int_type(mod, 32);163case DXIL_FUNC_PARAM_INT16: return dxil_module_get_int_type(mod, 16);164case DXIL_FUNC_PARAM_INT8: return dxil_module_get_int_type(mod, 8);165case DXIL_FUNC_PARAM_BOOL: return dxil_module_get_int_type(mod, 1);166case DXIL_FUNC_PARAM_FLOAT64: return dxil_module_get_float_type(mod, 64);167case DXIL_FUNC_PARAM_FLOAT32: return dxil_module_get_float_type(mod, 32);168case DXIL_FUNC_PARAM_FLOAT16: return dxil_module_get_float_type(mod, 16);169case DXIL_FUNC_PARAM_HANDLE: return dxil_module_get_handle_type(mod);170case DXIL_FUNC_PARAM_VOID: return dxil_module_get_void_type(mod);171case DXIL_FUNC_PARAM_FROM_OVERLOAD: return dxil_get_overload_type(mod, overload);172case DXIL_FUNC_PARAM_RESRET: return dxil_module_get_resret_type(mod, overload);173case DXIL_FUNC_PARAM_DIM: return dxil_module_get_dimret_type(mod);174case DXIL_FUNC_PARAM_CBUF_RET: return dxil_module_get_cbuf_ret_type(mod, overload);175case DXIL_FUNC_PARAM_SPLIT_DOUBLE: return dxil_module_get_split_double_ret_type(mod);176case DXIL_FUNC_PARAM_POINTER: {177const struct dxil_type *target = get_type_from_string(mod, param_descr, overload, idx);178return dxil_module_get_pointer_type(mod, target);179}180default:181assert(0 && "unknown type identifier");182}183return NULL;184}185186const struct dxil_func *187dxil_alloc_func_with_rettype(struct dxil_module *mod, const char *name,188enum overload_type overload,189const struct dxil_type *retval_type,190const char *param_descr,191enum dxil_attr_kind attr)192{193assert(param_descr);194const struct dxil_type *arg_types[MAX_FUNC_PARAMS];195196int index = 0;197unsigned num_params = 0;198199while (param_descr[num_params]) {200const struct dxil_type *t = get_type_from_string(mod, param_descr, overload, &index);201if (!t)202return false;203assert(num_params < MAX_FUNC_PARAMS);204arg_types[num_params++] = t;205}206207const struct dxil_type *func_type =208dxil_module_add_function_type(mod, retval_type,209arg_types, num_params);210if (!func_type) {211fprintf(stderr, "%s: Func type allocation failed\n", __func__);212return false;213}214215char full_name[100];216snprintf(full_name, sizeof (full_name), "%s%s%s", name,217overload == DXIL_NONE ? "" : ".", dxil_overload_suffix(overload));218const struct dxil_func *func = dxil_add_function_decl(mod, full_name, func_type, attr);219220if (func)221dxil_add_function(mod->functions, func, name, overload);222223return func;224}225226const struct dxil_func *227dxil_alloc_func(struct dxil_module *mod, const char *name, enum overload_type overload,228const char *retval_type_descr,229const char *param_descr, enum dxil_attr_kind attr)230{231232int index = 0;233const struct dxil_type *retval_type = get_type_from_string(mod, retval_type_descr, overload, &index);234assert(retval_type_descr[index] == 0);235236return dxil_alloc_func_with_rettype(mod, name, overload, retval_type,237param_descr, attr);238}239240241