microsoft/compiler: Support emitting multiple functions into a DXIL module
The instruction and block lists are moved into a new "function definition" struct, and the DXIL module tracks one at a time for adding instructions into. The NIR side still only emits the main function here though. Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Bill Kristiansen <billkris@microsoft.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14399>
This commit is contained in:
@@ -97,7 +97,12 @@ dxil_dump_module(struct dxil_dumper *d, struct dxil_module *m)
|
||||
dump_funcs(d, &m->func_list);
|
||||
dump_attr_set_list(d, &m->attr_set_list);
|
||||
dump_constants(d, &m->const_list);
|
||||
dump_instrs(d, &m->instr_list);
|
||||
|
||||
struct dxil_func_def *func_def;
|
||||
LIST_FOR_EACH_ENTRY(func_def, &m->func_def_list, head) {
|
||||
dump_instrs(d, &func_def->instr_list);
|
||||
}
|
||||
|
||||
dump_mdnodes(d, &m->mdnode_list);
|
||||
dump_named_nodes(d, &m->md_named_node_list);
|
||||
dump_io_signatures(d->buf, m);
|
||||
|
||||
@@ -45,17 +45,15 @@ dxil_module_init(struct dxil_module *m, void *ralloc_ctx)
|
||||
|
||||
list_inithead(&m->type_list);
|
||||
list_inithead(&m->func_list);
|
||||
list_inithead(&m->func_def_list);
|
||||
list_inithead(&m->attr_set_list);
|
||||
list_inithead(&m->gvar_list);
|
||||
list_inithead(&m->const_list);
|
||||
list_inithead(&m->instr_list);
|
||||
list_inithead(&m->mdnode_list);
|
||||
list_inithead(&m->md_named_node_list);
|
||||
|
||||
m->functions = rzalloc(ralloc_ctx, struct rb_tree);
|
||||
rb_tree_init(m->functions);
|
||||
|
||||
m->curr_block = 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1842,7 +1840,7 @@ dxil_add_global_ptr_var(struct dxil_module *m, const char *name,
|
||||
as, align, value);
|
||||
}
|
||||
|
||||
static struct dxil_func *
|
||||
static const struct dxil_func *
|
||||
add_function(struct dxil_module *m, const char *name,
|
||||
const struct dxil_type *type,
|
||||
bool decl, unsigned attr_set)
|
||||
@@ -1869,11 +1867,33 @@ add_function(struct dxil_module *m, const char *name,
|
||||
return func;
|
||||
}
|
||||
|
||||
const struct dxil_func *
|
||||
struct dxil_func_def *
|
||||
dxil_add_function_def(struct dxil_module *m, const char *name,
|
||||
const struct dxil_type *type)
|
||||
const struct dxil_type *type, unsigned num_blocks)
|
||||
{
|
||||
return add_function(m, name, type, false, 0);
|
||||
struct dxil_func_def *def = ralloc_size(m->ralloc_ctx, sizeof(struct dxil_func_def));
|
||||
|
||||
def->func = add_function(m, name, type, false, 0);
|
||||
if (!def->func)
|
||||
return NULL;
|
||||
|
||||
list_inithead(&def->instr_list);
|
||||
def->curr_block = 0;
|
||||
|
||||
assert(num_blocks > 0);
|
||||
def->basic_block_ids = rzalloc_array(m->ralloc_ctx, int,
|
||||
num_blocks);
|
||||
if (!def->basic_block_ids)
|
||||
return NULL;
|
||||
|
||||
for (int i = 0; i < num_blocks; ++i)
|
||||
def->basic_block_ids[i] = -1;
|
||||
def->num_basic_block_ids = num_blocks;
|
||||
|
||||
list_addtail(&def->head, &m->func_def_list);
|
||||
m->cur_emitting_func = def;
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
@@ -2567,7 +2587,7 @@ create_instr(struct dxil_module *m, enum instr_type type,
|
||||
ret->value.id = -1;
|
||||
ret->value.type = ret_type;
|
||||
ret->has_value = false;
|
||||
list_addtail(&ret->head, &m->instr_list);
|
||||
list_addtail(&ret->head, &m->cur_emitting_func->instr_list);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -2682,7 +2702,7 @@ dxil_emit_branch(struct dxil_module *m, const struct dxil_value *cond,
|
||||
instr->br.cond = cond;
|
||||
instr->br.succ[0] = true_block;
|
||||
instr->br.succ[1] = false_block;
|
||||
m->curr_block++;
|
||||
m->cur_emitting_func->curr_block++;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2787,7 +2807,7 @@ dxil_emit_ret_void(struct dxil_module *m)
|
||||
return false;
|
||||
|
||||
instr->ret.value = NULL;
|
||||
m->curr_block++;
|
||||
m->cur_emitting_func->curr_block++;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3055,25 +3075,25 @@ emit_cast(struct dxil_module *m, struct dxil_instr *instr)
|
||||
}
|
||||
|
||||
static bool
|
||||
emit_branch(struct dxil_module *m, struct dxil_instr *instr)
|
||||
emit_branch(struct dxil_module *m, struct dxil_func_def *func, struct dxil_instr *instr)
|
||||
{
|
||||
assert(instr->type == INSTR_BR);
|
||||
assert(instr->br.succ[0] < m->num_basic_block_ids);
|
||||
assert(m->basic_block_ids[instr->br.succ[0]] >= 0);
|
||||
assert(instr->br.succ[0] < func->num_basic_block_ids);
|
||||
assert(func->basic_block_ids[instr->br.succ[0]] >= 0);
|
||||
|
||||
if (!instr->br.cond) {
|
||||
/* unconditional branch */
|
||||
uint64_t succ = m->basic_block_ids[instr->br.succ[0]];
|
||||
uint64_t succ = func->basic_block_ids[instr->br.succ[0]];
|
||||
return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_BR, &succ, 1);
|
||||
}
|
||||
/* conditional branch */
|
||||
assert(instr->value.id > instr->br.cond->id);
|
||||
assert(instr->br.succ[1] < m->num_basic_block_ids);
|
||||
assert(m->basic_block_ids[instr->br.succ[1]] >= 0);
|
||||
assert(instr->br.succ[1] < func->num_basic_block_ids);
|
||||
assert(func->basic_block_ids[instr->br.succ[1]] >= 0);
|
||||
|
||||
uint64_t data[] = {
|
||||
m->basic_block_ids[instr->br.succ[0]],
|
||||
m->basic_block_ids[instr->br.succ[1]],
|
||||
func->basic_block_ids[instr->br.succ[0]],
|
||||
func->basic_block_ids[instr->br.succ[1]],
|
||||
instr->value.id - instr->br.cond->id
|
||||
};
|
||||
return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_BR,
|
||||
@@ -3081,7 +3101,7 @@ emit_branch(struct dxil_module *m, struct dxil_instr *instr)
|
||||
}
|
||||
|
||||
static bool
|
||||
emit_phi(struct dxil_module *m, struct dxil_instr *instr)
|
||||
emit_phi(struct dxil_module *m, struct dxil_func_def *func, struct dxil_instr *instr)
|
||||
{
|
||||
assert(instr->type == INSTR_PHI);
|
||||
uint64_t data[128];
|
||||
@@ -3090,9 +3110,9 @@ emit_phi(struct dxil_module *m, struct dxil_instr *instr)
|
||||
for (int i = 0; i < instr->phi.num_incoming; ++i) {
|
||||
int64_t value_delta = instr->value.id - instr->phi.incoming[i].value->id;
|
||||
data[1 + i * 2] = encode_signed(value_delta);
|
||||
assert(instr->phi.incoming[i].block < m->num_basic_block_ids);
|
||||
assert(m->basic_block_ids[instr->phi.incoming[i].block] >= 0);
|
||||
data[1 + i * 2 + 1] = m->basic_block_ids[instr->phi.incoming[i].block];
|
||||
assert(instr->phi.incoming[i].block < func->num_basic_block_ids);
|
||||
assert(func->basic_block_ids[instr->phi.incoming[i].block] >= 0);
|
||||
data[1 + i * 2 + 1] = func->basic_block_ids[instr->phi.incoming[i].block];
|
||||
}
|
||||
return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_PHI,
|
||||
data, 1 + 2 * instr->phi.num_incoming);
|
||||
@@ -3266,7 +3286,7 @@ emit_atomicrmw(struct dxil_module *m, struct dxil_instr *instr)
|
||||
}
|
||||
|
||||
static bool
|
||||
emit_instr(struct dxil_module *m, struct dxil_instr *instr)
|
||||
emit_instr(struct dxil_module *m, struct dxil_func_def *func, struct dxil_instr *instr)
|
||||
{
|
||||
switch (instr->type) {
|
||||
case INSTR_BINOP:
|
||||
@@ -3282,10 +3302,10 @@ emit_instr(struct dxil_module *m, struct dxil_instr *instr)
|
||||
return emit_cast(m, instr);
|
||||
|
||||
case INSTR_BR:
|
||||
return emit_branch(m, instr);
|
||||
return emit_branch(m, func, instr);
|
||||
|
||||
case INSTR_PHI:
|
||||
return emit_phi(m, instr);
|
||||
return emit_phi(m, func, instr);
|
||||
|
||||
case INSTR_CALL:
|
||||
return emit_call(m, instr);
|
||||
@@ -3320,14 +3340,14 @@ emit_instr(struct dxil_module *m, struct dxil_instr *instr)
|
||||
}
|
||||
|
||||
static bool
|
||||
emit_function(struct dxil_module *m)
|
||||
emit_function(struct dxil_module *m, struct dxil_func_def *func)
|
||||
{
|
||||
if (!enter_subblock(m, DXIL_FUNCTION_BLOCK, 4) ||
|
||||
!emit_record_int(m, FUNC_CODE_DECLAREBLOCKS, m->curr_block))
|
||||
!emit_record_int(m, FUNC_CODE_DECLAREBLOCKS, func->curr_block))
|
||||
return false;
|
||||
|
||||
list_for_each_entry(struct dxil_instr, instr, &m->instr_list, head) {
|
||||
if (!emit_instr(m, instr))
|
||||
list_for_each_entry(struct dxil_instr, instr, &func->instr_list, head) {
|
||||
if (!emit_instr(m, func, instr))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3354,11 +3374,18 @@ assign_values(struct dxil_module *m)
|
||||
c->value.id = next_value_id++;
|
||||
}
|
||||
|
||||
struct dxil_instr *instr;
|
||||
LIST_FOR_EACH_ENTRY(instr, &m->instr_list, head) {
|
||||
instr->value.id = next_value_id;
|
||||
if (instr->has_value)
|
||||
next_value_id++;
|
||||
/* All functions start at this ID */
|
||||
unsigned value_id_at_functions_start = next_value_id;
|
||||
|
||||
struct dxil_func_def *func_def;
|
||||
LIST_FOR_EACH_ENTRY(func_def, &m->func_def_list, head) {
|
||||
struct dxil_instr *instr;
|
||||
next_value_id = value_id_at_functions_start;
|
||||
LIST_FOR_EACH_ENTRY(instr, &func_def->instr_list, head) {
|
||||
instr->value.id = next_value_id;
|
||||
if (instr->has_value)
|
||||
next_value_id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3366,20 +3393,27 @@ bool
|
||||
dxil_emit_module(struct dxil_module *m)
|
||||
{
|
||||
assign_values(m);
|
||||
return dxil_buffer_emit_bits(&m->buf, 'B', 8) &&
|
||||
dxil_buffer_emit_bits(&m->buf, 'C', 8) &&
|
||||
dxil_buffer_emit_bits(&m->buf, 0xC0, 8) &&
|
||||
dxil_buffer_emit_bits(&m->buf, 0xDE, 8) &&
|
||||
enter_subblock(m, DXIL_MODULE, 3) &&
|
||||
emit_record_int(m, DXIL_MODULE_CODE_VERSION, 1) &&
|
||||
emit_blockinfo(m) &&
|
||||
emit_attrib_group_table(m) &&
|
||||
emit_attribute_table(m) &&
|
||||
emit_type_table(m) &&
|
||||
emit_module_info(m) &&
|
||||
emit_module_consts(m) &&
|
||||
emit_metadata(m) &&
|
||||
emit_value_symbol_table(m) &&
|
||||
emit_function(m) &&
|
||||
exit_block(m);
|
||||
if (!(dxil_buffer_emit_bits(&m->buf, 'B', 8) &&
|
||||
dxil_buffer_emit_bits(&m->buf, 'C', 8) &&
|
||||
dxil_buffer_emit_bits(&m->buf, 0xC0, 8) &&
|
||||
dxil_buffer_emit_bits(&m->buf, 0xDE, 8) &&
|
||||
enter_subblock(m, DXIL_MODULE, 3) &&
|
||||
emit_record_int(m, DXIL_MODULE_CODE_VERSION, 1) &&
|
||||
emit_blockinfo(m) &&
|
||||
emit_attrib_group_table(m) &&
|
||||
emit_attribute_table(m) &&
|
||||
emit_type_table(m) &&
|
||||
emit_module_info(m) &&
|
||||
emit_module_consts(m) &&
|
||||
emit_metadata(m) &&
|
||||
emit_value_symbol_table(m)))
|
||||
return false;
|
||||
|
||||
struct dxil_func_def *func;
|
||||
LIST_FOR_EACH_ENTRY(func, &m->func_def_list, head) {
|
||||
if (!emit_function(m, func))
|
||||
return false;
|
||||
}
|
||||
|
||||
return exit_block(m);
|
||||
}
|
||||
|
||||
@@ -162,6 +162,16 @@ struct dxil_shader_info {
|
||||
unsigned has_per_sample_input:1;
|
||||
};
|
||||
|
||||
struct dxil_func_def {
|
||||
struct list_head head;
|
||||
const struct dxil_func *func;
|
||||
|
||||
struct list_head instr_list;
|
||||
int *basic_block_ids; /* maps from "user" ids to LLVM ids */
|
||||
size_t num_basic_block_ids;
|
||||
unsigned curr_block;
|
||||
};
|
||||
|
||||
struct dxil_module {
|
||||
void *ralloc_ctx;
|
||||
enum dxil_shader_kind shader_kind;
|
||||
@@ -195,8 +205,8 @@ struct dxil_module {
|
||||
struct list_head type_list;
|
||||
struct list_head gvar_list;
|
||||
struct list_head func_list;
|
||||
struct list_head func_def_list;
|
||||
struct list_head attr_set_list;
|
||||
struct list_head instr_list;
|
||||
struct list_head const_list;
|
||||
struct list_head mdnode_list;
|
||||
struct list_head md_named_node_list;
|
||||
@@ -207,9 +217,7 @@ struct dxil_module {
|
||||
|
||||
struct rb_tree *functions;
|
||||
|
||||
int *basic_block_ids; /* maps from "user" ids to LLVM ids */
|
||||
size_t num_basic_block_ids;
|
||||
unsigned curr_block;
|
||||
struct dxil_func_def *cur_emitting_func;
|
||||
};
|
||||
|
||||
struct dxil_instr;
|
||||
@@ -233,9 +241,9 @@ dxil_add_global_ptr_var(struct dxil_module *m, const char *name,
|
||||
enum dxil_address_space as, int align,
|
||||
const struct dxil_value *value);
|
||||
|
||||
const struct dxil_func *
|
||||
struct dxil_func_def *
|
||||
dxil_add_function_def(struct dxil_module *m, const char *name,
|
||||
const struct dxil_type *type);
|
||||
const struct dxil_type *type, unsigned num_blocks);
|
||||
|
||||
const struct dxil_func *
|
||||
dxil_add_function_decl(struct dxil_module *m, const char *name,
|
||||
|
||||
@@ -1432,11 +1432,10 @@ emit_metadata(struct ntd_context *ctx)
|
||||
!emit_dx_shader_model(&ctx->mod))
|
||||
return false;
|
||||
|
||||
const struct dxil_type *void_type = dxil_module_get_void_type(&ctx->mod);
|
||||
const struct dxil_type *main_func_type = dxil_module_add_function_type(&ctx->mod, void_type, NULL, 0);
|
||||
const struct dxil_func *main_func = dxil_add_function_def(&ctx->mod, "main", main_func_type);
|
||||
if (!main_func)
|
||||
const struct dxil_func_def *main_func_def = ctx->mod.cur_emitting_func;
|
||||
if (!main_func_def)
|
||||
return false;
|
||||
const struct dxil_func *main_func = main_func_def->func;
|
||||
|
||||
const struct dxil_mdnode *resources_node = emit_resources(ctx);
|
||||
|
||||
@@ -4612,8 +4611,8 @@ static bool emit_instr(struct ntd_context *ctx, struct nir_instr* instr)
|
||||
static bool
|
||||
emit_block(struct ntd_context *ctx, struct nir_block *block)
|
||||
{
|
||||
assert(block->index < ctx->mod.num_basic_block_ids);
|
||||
ctx->mod.basic_block_ids[block->index] = ctx->mod.curr_block;
|
||||
assert(block->index < ctx->mod.cur_emitting_func->num_basic_block_ids);
|
||||
ctx->mod.cur_emitting_func->basic_block_ids[block->index] = ctx->mod.cur_emitting_func->curr_block;
|
||||
|
||||
nir_foreach_instr(instr, block) {
|
||||
TRACE_CONVERSION(instr);
|
||||
@@ -4999,16 +4998,12 @@ emit_module(struct ntd_context *ctx, const struct nir_to_dxil_options *opts)
|
||||
nir_function_impl *entry = nir_shader_get_entrypoint(ctx->shader);
|
||||
nir_metadata_require(entry, nir_metadata_block_index);
|
||||
|
||||
assert(entry->num_blocks > 0);
|
||||
ctx->mod.basic_block_ids = rzalloc_array(ctx->ralloc_ctx, int,
|
||||
entry->num_blocks);
|
||||
if (!ctx->mod.basic_block_ids)
|
||||
const struct dxil_type *void_type = dxil_module_get_void_type(&ctx->mod);
|
||||
const struct dxil_type *main_func_type = dxil_module_add_function_type(&ctx->mod, void_type, NULL, 0);
|
||||
struct dxil_func_def *main_func = dxil_add_function_def(&ctx->mod, "main", main_func_type, entry->num_blocks);
|
||||
if (!main_func)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < entry->num_blocks; ++i)
|
||||
ctx->mod.basic_block_ids[i] = -1;
|
||||
ctx->mod.num_basic_block_ids = entry->num_blocks;
|
||||
|
||||
ctx->defs = rzalloc_array(ctx->ralloc_ctx, struct dxil_def,
|
||||
entry->ssa_alloc);
|
||||
if (!ctx->defs)
|
||||
|
||||
Reference in New Issue
Block a user