1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "dxil_function.h" 25bf215546Sopenharmony_ci#include "dxil_module.h" 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#define MAX_FUNC_PARAMS 17 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_cistruct predefined_func_descr { 30bf215546Sopenharmony_ci const char *base_name; 31bf215546Sopenharmony_ci const char *retval_descr; 32bf215546Sopenharmony_ci const char *param_descr; 33bf215546Sopenharmony_ci enum dxil_attr_kind attr; 34bf215546Sopenharmony_ci}; 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_cistatic struct predefined_func_descr predefined_funcs[] = { 37bf215546Sopenharmony_ci{"dx.op.atomicBinOp", "O", "i@iiiii", DXIL_ATTR_KIND_READ_NONE}, 38bf215546Sopenharmony_ci{"dx.op.cbufferLoad", "O", "i@ii", DXIL_ATTR_KIND_READ_ONLY}, 39bf215546Sopenharmony_ci{"dx.op.cbufferLoadLegacy", "B", "i@i", DXIL_ATTR_KIND_READ_ONLY}, 40bf215546Sopenharmony_ci{"dx.op.createHandle", "@", "iciib", DXIL_ATTR_KIND_READ_ONLY}, 41bf215546Sopenharmony_ci{"dx.op.storeOutput", "v", "iiicO", DXIL_ATTR_KIND_NO_UNWIND}, 42bf215546Sopenharmony_ci{"dx.op.loadInput", "O", "iiici", DXIL_ATTR_KIND_READ_NONE}, 43bf215546Sopenharmony_ci{"dx.op.tertiary", "O", "iOOO", DXIL_ATTR_KIND_READ_NONE}, 44bf215546Sopenharmony_ci{"dx.op.quaternary", "O", "iOOOO", DXIL_ATTR_KIND_READ_NONE}, 45bf215546Sopenharmony_ci{"dx.op.threadId", "i", "ii", DXIL_ATTR_KIND_READ_NONE}, 46bf215546Sopenharmony_ci{"dx.op.threadIdInGroup", "i", "ii", DXIL_ATTR_KIND_READ_NONE}, 47bf215546Sopenharmony_ci{"dx.op.flattenedThreadIdInGroup", "i", "i", DXIL_ATTR_KIND_READ_NONE}, 48bf215546Sopenharmony_ci{"dx.op.groupId", "i", "ii", DXIL_ATTR_KIND_READ_NONE}, 49bf215546Sopenharmony_ci{"dx.op.unary", "O", "iO", DXIL_ATTR_KIND_READ_NONE}, 50bf215546Sopenharmony_ci{"dx.op.unaryBits", "i", "iO", DXIL_ATTR_KIND_READ_NONE}, 51bf215546Sopenharmony_ci{"dx.op.isSpecialFloat", "b", "iO", DXIL_ATTR_KIND_READ_NONE}, 52bf215546Sopenharmony_ci{"dx.op.binary", "O", "iOO", DXIL_ATTR_KIND_READ_NONE}, 53bf215546Sopenharmony_ci{"dx.op.bufferStore", "v", "i@iiOOOOc", DXIL_ATTR_KIND_NONE}, 54bf215546Sopenharmony_ci{"dx.op.bufferLoad", "R", "i@ii", DXIL_ATTR_KIND_READ_ONLY}, 55bf215546Sopenharmony_ci{"dx.op.attributeAtVertex", "O", "iiicc", DXIL_ATTR_KIND_READ_NONE}, 56bf215546Sopenharmony_ci{"dx.op.sample", "R", "i@@ffffiiif", DXIL_ATTR_KIND_READ_ONLY}, 57bf215546Sopenharmony_ci{"dx.op.sampleBias", "R", "i@@ffffiiiff", DXIL_ATTR_KIND_READ_ONLY}, 58bf215546Sopenharmony_ci{"dx.op.sampleLevel", "R", "i@@ffffiiif", DXIL_ATTR_KIND_READ_ONLY}, 59bf215546Sopenharmony_ci{"dx.op.sampleGrad", "R", "i@@ffffiiifffffff", DXIL_ATTR_KIND_READ_ONLY}, 60bf215546Sopenharmony_ci{"dx.op.sampleCmp", "R", "i@@ffffiiiff", DXIL_ATTR_KIND_READ_ONLY}, 61bf215546Sopenharmony_ci{"dx.op.sampleCmpLevelZero", "R", "i@@ffffiiif", DXIL_ATTR_KIND_READ_ONLY}, 62bf215546Sopenharmony_ci{"dx.op.textureLoad", "R", "i@iiiiiii", DXIL_ATTR_KIND_READ_ONLY}, 63bf215546Sopenharmony_ci{"dx.op.textureGather", "R", "i@@ffffiii", DXIL_ATTR_KIND_READ_ONLY}, 64bf215546Sopenharmony_ci{"dx.op.textureGatherCmp", "R", "i@@ffffiiif", DXIL_ATTR_KIND_READ_ONLY}, 65bf215546Sopenharmony_ci{"dx.op.discard", "v", "ib", DXIL_ATTR_KIND_NO_UNWIND}, 66bf215546Sopenharmony_ci{"dx.op.sampleIndex", "i", "i", DXIL_ATTR_KIND_READ_NONE}, 67bf215546Sopenharmony_ci{"dx.op.emitStream", "v", "ic", DXIL_ATTR_KIND_NONE}, 68bf215546Sopenharmony_ci{"dx.op.cutStream", "v", "ic", DXIL_ATTR_KIND_NONE}, 69bf215546Sopenharmony_ci{"dx.op.getDimensions", "D", "i@i", DXIL_ATTR_KIND_READ_ONLY}, 70bf215546Sopenharmony_ci{"dx.op.calculateLOD", "f", "i@@fffb", DXIL_ATTR_KIND_READ_ONLY}, 71bf215546Sopenharmony_ci{"dx.op.barrier", "v", "ii", DXIL_ATTR_KIND_NO_DUPLICATE}, 72bf215546Sopenharmony_ci{"dx.op.atomicCompareExchange", "O", "i@iiiii", DXIL_ATTR_KIND_READ_NONE}, 73bf215546Sopenharmony_ci{"dx.op.textureStore", "v", "i@iiiOOOOc", DXIL_ATTR_KIND_NONE}, 74bf215546Sopenharmony_ci{"dx.op.primitiveID", "i", "i", DXIL_ATTR_KIND_READ_NONE}, 75bf215546Sopenharmony_ci{"dx.op.outputControlPointID", "i", "i", DXIL_ATTR_KIND_READ_NONE}, 76bf215546Sopenharmony_ci{"dx.op.gsInstanceID", "i", "i", DXIL_ATTR_KIND_READ_NONE}, 77bf215546Sopenharmony_ci{"dx.op.domainLocation", "f", "ii", DXIL_ATTR_KIND_READ_NONE}, 78bf215546Sopenharmony_ci{"dx.op.legacyF16ToF32", "f", "ii", DXIL_ATTR_KIND_READ_ONLY}, 79bf215546Sopenharmony_ci{"dx.op.legacyF32ToF16", "i", "if", DXIL_ATTR_KIND_READ_ONLY}, 80bf215546Sopenharmony_ci{"dx.op.makeDouble", "g", "iii", DXIL_ATTR_KIND_READ_NONE}, 81bf215546Sopenharmony_ci{"dx.op.splitDouble", "G", "ig", DXIL_ATTR_KIND_READ_NONE}, 82bf215546Sopenharmony_ci{"dx.op.texture2DMSGetSamplePosition", "S", "i@i", DXIL_ATTR_KIND_READ_ONLY}, 83bf215546Sopenharmony_ci{"dx.op.renderTargetGetSamplePosition", "S", "ii", DXIL_ATTR_KIND_READ_ONLY}, 84bf215546Sopenharmony_ci{"dx.op.evalSnapped", "O", "iiicii", DXIL_ATTR_KIND_READ_NONE}, 85bf215546Sopenharmony_ci{"dx.op.evalCentroid", "O", "iiic", DXIL_ATTR_KIND_READ_NONE}, 86bf215546Sopenharmony_ci{"dx.op.evalSampleIndex", "O", "iiici", DXIL_ATTR_KIND_READ_NONE}, 87bf215546Sopenharmony_ci{"dx.op.coverage", "i", "i", DXIL_ATTR_KIND_READ_NONE}, 88bf215546Sopenharmony_ci{"dx.op.storePatchConstant", "v", "iiicO", DXIL_ATTR_KIND_NO_UNWIND}, 89bf215546Sopenharmony_ci{"dx.op.loadPatchConstant", "O", "iiic", DXIL_ATTR_KIND_READ_NONE}, 90bf215546Sopenharmony_ci{"dx.op.loadOutputControlPoint", "O", "iiici", DXIL_ATTR_KIND_READ_NONE}, 91bf215546Sopenharmony_ci}; 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_cistruct func_descr { 94bf215546Sopenharmony_ci const char *name; 95bf215546Sopenharmony_ci enum overload_type overload; 96bf215546Sopenharmony_ci}; 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_cistruct func_rb_node { 99bf215546Sopenharmony_ci struct rb_node node; 100bf215546Sopenharmony_ci const struct dxil_func *func; 101bf215546Sopenharmony_ci struct func_descr descr; 102bf215546Sopenharmony_ci}; 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_cistatic inline 105bf215546Sopenharmony_ciconst struct func_rb_node * 106bf215546Sopenharmony_cifunc_rb_node(const struct rb_node *n) 107bf215546Sopenharmony_ci{ 108bf215546Sopenharmony_ci return (const struct func_rb_node *)n; 109bf215546Sopenharmony_ci} 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_cistatic int 112bf215546Sopenharmony_cifunc_compare_to_name_and_overload(const struct rb_node *node, const void *data) 113bf215546Sopenharmony_ci{ 114bf215546Sopenharmony_ci const struct func_descr *descr = (const struct func_descr *)data; 115bf215546Sopenharmony_ci const struct func_rb_node *f = func_rb_node(node); 116bf215546Sopenharmony_ci if (f->descr.overload < descr->overload) 117bf215546Sopenharmony_ci return -1; 118bf215546Sopenharmony_ci if (f->descr.overload > descr->overload) 119bf215546Sopenharmony_ci return 1; 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci return strcmp(f->descr.name, descr->name); 122bf215546Sopenharmony_ci} 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_cistatic const struct dxil_func * 125bf215546Sopenharmony_ciallocate_function_from_predefined(struct dxil_module *mod, 126bf215546Sopenharmony_ci const char *name, 127bf215546Sopenharmony_ci enum overload_type overload) 128bf215546Sopenharmony_ci{ 129bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(predefined_funcs); ++i) { 130bf215546Sopenharmony_ci if (!strcmp(predefined_funcs[i].base_name, name)) { 131bf215546Sopenharmony_ci return dxil_alloc_func(mod, name, overload, 132bf215546Sopenharmony_ci predefined_funcs[i].retval_descr, 133bf215546Sopenharmony_ci predefined_funcs[i].param_descr, 134bf215546Sopenharmony_ci predefined_funcs[i].attr); 135bf215546Sopenharmony_ci } 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci unreachable("Invalid function name"); 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ciconst struct dxil_func * 141bf215546Sopenharmony_cidxil_get_function(struct dxil_module *mod, 142bf215546Sopenharmony_ci const char *name, enum overload_type overload) 143bf215546Sopenharmony_ci{ 144bf215546Sopenharmony_ci struct func_descr descr = { name, overload }; 145bf215546Sopenharmony_ci const struct rb_node *node = rb_tree_search(mod->functions, &descr, 146bf215546Sopenharmony_ci func_compare_to_name_and_overload); 147bf215546Sopenharmony_ci if (node) 148bf215546Sopenharmony_ci return func_rb_node(node)->func; 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci return allocate_function_from_predefined(mod, name, overload); 151bf215546Sopenharmony_ci} 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_cistatic int func_compare_name(const struct rb_node *lhs, const struct rb_node *rhs) 154bf215546Sopenharmony_ci{ 155bf215546Sopenharmony_ci const struct func_rb_node *node = func_rb_node(rhs); 156bf215546Sopenharmony_ci return func_compare_to_name_and_overload(lhs, &node->descr); 157bf215546Sopenharmony_ci} 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_cistatic void 160bf215546Sopenharmony_cidxil_add_function(struct rb_tree *functions, const struct dxil_func *func, 161bf215546Sopenharmony_ci const char *name, enum overload_type overload) 162bf215546Sopenharmony_ci{ 163bf215546Sopenharmony_ci struct func_rb_node *f = rzalloc(functions, struct func_rb_node); 164bf215546Sopenharmony_ci f->func = func; 165bf215546Sopenharmony_ci f->descr.name = name; 166bf215546Sopenharmony_ci f->descr.overload = overload; 167bf215546Sopenharmony_ci rb_tree_insert(functions, &f->node, func_compare_name); 168bf215546Sopenharmony_ci} 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_cistatic const struct dxil_type * 171bf215546Sopenharmony_ciget_type_from_string(struct dxil_module *mod, const char *param_descr, 172bf215546Sopenharmony_ci enum overload_type overload, int *idx) 173bf215546Sopenharmony_ci{ 174bf215546Sopenharmony_ci assert(param_descr); 175bf215546Sopenharmony_ci char type_id = param_descr[(*idx)++]; 176bf215546Sopenharmony_ci assert(*idx <= (int)strlen(param_descr)); 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci switch (type_id) { 179bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_INT64: return dxil_module_get_int_type(mod, 64); 180bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_INT32: return dxil_module_get_int_type(mod, 32); 181bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_INT16: return dxil_module_get_int_type(mod, 16); 182bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_INT8: return dxil_module_get_int_type(mod, 8); 183bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_BOOL: return dxil_module_get_int_type(mod, 1); 184bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_FLOAT64: return dxil_module_get_float_type(mod, 64); 185bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_FLOAT32: return dxil_module_get_float_type(mod, 32); 186bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_FLOAT16: return dxil_module_get_float_type(mod, 16); 187bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_HANDLE: return dxil_module_get_handle_type(mod); 188bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_VOID: return dxil_module_get_void_type(mod); 189bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_FROM_OVERLOAD: return dxil_get_overload_type(mod, overload); 190bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_RESRET: return dxil_module_get_resret_type(mod, overload); 191bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_DIM: return dxil_module_get_dimret_type(mod); 192bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_SAMPLE_POS: return dxil_module_get_samplepos_type(mod); 193bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_CBUF_RET: return dxil_module_get_cbuf_ret_type(mod, overload); 194bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_SPLIT_DOUBLE: return dxil_module_get_split_double_ret_type(mod); 195bf215546Sopenharmony_ci case DXIL_FUNC_PARAM_POINTER: { 196bf215546Sopenharmony_ci const struct dxil_type *target = get_type_from_string(mod, param_descr, overload, idx); 197bf215546Sopenharmony_ci return dxil_module_get_pointer_type(mod, target); 198bf215546Sopenharmony_ci } 199bf215546Sopenharmony_ci default: 200bf215546Sopenharmony_ci assert(0 && "unknown type identifier"); 201bf215546Sopenharmony_ci } 202bf215546Sopenharmony_ci return NULL; 203bf215546Sopenharmony_ci} 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ciconst struct dxil_func * 206bf215546Sopenharmony_cidxil_alloc_func_with_rettype(struct dxil_module *mod, const char *name, 207bf215546Sopenharmony_ci enum overload_type overload, 208bf215546Sopenharmony_ci const struct dxil_type *retval_type, 209bf215546Sopenharmony_ci const char *param_descr, 210bf215546Sopenharmony_ci enum dxil_attr_kind attr) 211bf215546Sopenharmony_ci{ 212bf215546Sopenharmony_ci assert(param_descr); 213bf215546Sopenharmony_ci const struct dxil_type *arg_types[MAX_FUNC_PARAMS]; 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci int index = 0; 216bf215546Sopenharmony_ci unsigned num_params = 0; 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci while (param_descr[num_params]) { 219bf215546Sopenharmony_ci const struct dxil_type *t = get_type_from_string(mod, param_descr, overload, &index); 220bf215546Sopenharmony_ci if (!t) 221bf215546Sopenharmony_ci return false; 222bf215546Sopenharmony_ci assert(num_params < MAX_FUNC_PARAMS); 223bf215546Sopenharmony_ci arg_types[num_params++] = t; 224bf215546Sopenharmony_ci } 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci const struct dxil_type *func_type = 227bf215546Sopenharmony_ci dxil_module_add_function_type(mod, retval_type, 228bf215546Sopenharmony_ci arg_types, num_params); 229bf215546Sopenharmony_ci if (!func_type) { 230bf215546Sopenharmony_ci fprintf(stderr, "%s: Func type allocation failed\n", __func__); 231bf215546Sopenharmony_ci return false; 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci char full_name[100]; 235bf215546Sopenharmony_ci snprintf(full_name, sizeof (full_name), "%s%s%s", name, 236bf215546Sopenharmony_ci overload == DXIL_NONE ? "" : ".", dxil_overload_suffix(overload)); 237bf215546Sopenharmony_ci const struct dxil_func *func = dxil_add_function_decl(mod, full_name, func_type, attr); 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci if (func) 240bf215546Sopenharmony_ci dxil_add_function(mod->functions, func, name, overload); 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci return func; 243bf215546Sopenharmony_ci} 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ciconst struct dxil_func * 246bf215546Sopenharmony_cidxil_alloc_func(struct dxil_module *mod, const char *name, enum overload_type overload, 247bf215546Sopenharmony_ci const char *retval_type_descr, 248bf215546Sopenharmony_ci const char *param_descr, enum dxil_attr_kind attr) 249bf215546Sopenharmony_ci{ 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci int index = 0; 252bf215546Sopenharmony_ci const struct dxil_type *retval_type = get_type_from_string(mod, retval_type_descr, overload, &index); 253bf215546Sopenharmony_ci assert(retval_type_descr[index] == 0); 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci return dxil_alloc_func_with_rettype(mod, name, overload, retval_type, 256bf215546Sopenharmony_ci param_descr, attr); 257bf215546Sopenharmony_ci} 258