Path: blob/21.2-virgl/src/compiler/nir/nir_clone.c
4545 views
/*1* Copyright © 2015 Red Hat2*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 "nir.h"24#include "nir_control_flow.h"2526/* Secret Decoder Ring:27* clone_foo():28* Allocate and clone a foo.29* __clone_foo():30* Clone body of foo (ie. parent class, embedded struct, etc)31*/3233typedef struct {34/* True if we are cloning an entire shader. */35bool global_clone;3637/* If true allows the clone operation to fall back to the original pointer38* if no clone pointer is found in the remap table. This allows us to39* clone a loop body without having to add srcs from outside the loop to40* the remap table. This is useful for loop unrolling.41*/42bool allow_remap_fallback;4344/* maps orig ptr -> cloned ptr: */45struct hash_table *remap_table;4647/* List of phi sources. */48struct list_head phi_srcs;4950/* new shader object, used as memctx for just about everything else: */51nir_shader *ns;52} clone_state;5354static void55init_clone_state(clone_state *state, struct hash_table *remap_table,56bool global, bool allow_remap_fallback)57{58state->global_clone = global;59state->allow_remap_fallback = allow_remap_fallback;6061if (remap_table) {62state->remap_table = remap_table;63} else {64state->remap_table = _mesa_pointer_hash_table_create(NULL);65}6667list_inithead(&state->phi_srcs);68}6970static void71free_clone_state(clone_state *state)72{73_mesa_hash_table_destroy(state->remap_table, NULL);74}7576static inline void *77_lookup_ptr(clone_state *state, const void *ptr, bool global)78{79struct hash_entry *entry;8081if (!ptr)82return NULL;8384if (!state->global_clone && global)85return (void *)ptr;8687if (unlikely(!state->remap_table)) {88assert(state->allow_remap_fallback);89return (void *)ptr;90}9192entry = _mesa_hash_table_search(state->remap_table, ptr);93if (!entry) {94assert(state->allow_remap_fallback);95return (void *)ptr;96}9798return entry->data;99}100101static void102add_remap(clone_state *state, void *nptr, const void *ptr)103{104_mesa_hash_table_insert(state->remap_table, ptr, nptr);105}106107static void *108remap_local(clone_state *state, const void *ptr)109{110return _lookup_ptr(state, ptr, false);111}112113static void *114remap_global(clone_state *state, const void *ptr)115{116return _lookup_ptr(state, ptr, true);117}118119static nir_register *120remap_reg(clone_state *state, const nir_register *reg)121{122return _lookup_ptr(state, reg, false);123}124125static nir_variable *126remap_var(clone_state *state, const nir_variable *var)127{128return _lookup_ptr(state, var, nir_variable_is_global(var));129}130131nir_constant *132nir_constant_clone(const nir_constant *c, nir_variable *nvar)133{134nir_constant *nc = ralloc(nvar, nir_constant);135136memcpy(nc->values, c->values, sizeof(nc->values));137nc->num_elements = c->num_elements;138nc->elements = ralloc_array(nvar, nir_constant *, c->num_elements);139for (unsigned i = 0; i < c->num_elements; i++) {140nc->elements[i] = nir_constant_clone(c->elements[i], nvar);141}142143return nc;144}145146/* NOTE: for cloning nir_variables, bypass nir_variable_create to avoid147* having to deal with locals and globals separately:148*/149nir_variable *150nir_variable_clone(const nir_variable *var, nir_shader *shader)151{152nir_variable *nvar = rzalloc(shader, nir_variable);153154nvar->type = var->type;155nvar->name = ralloc_strdup(nvar, var->name);156nvar->data = var->data;157nvar->num_state_slots = var->num_state_slots;158if (var->num_state_slots) {159nvar->state_slots = ralloc_array(nvar, nir_state_slot, var->num_state_slots);160memcpy(nvar->state_slots, var->state_slots,161var->num_state_slots * sizeof(nir_state_slot));162}163if (var->constant_initializer) {164nvar->constant_initializer =165nir_constant_clone(var->constant_initializer, nvar);166}167nvar->interface_type = var->interface_type;168169nvar->num_members = var->num_members;170if (var->num_members) {171nvar->members = ralloc_array(nvar, struct nir_variable_data,172var->num_members);173memcpy(nvar->members, var->members,174var->num_members * sizeof(*var->members));175}176177return nvar;178}179180static nir_variable *181clone_variable(clone_state *state, const nir_variable *var)182{183nir_variable *nvar = nir_variable_clone(var, state->ns);184add_remap(state, nvar, var);185186return nvar;187}188189/* clone list of nir_variable: */190static void191clone_var_list(clone_state *state, struct exec_list *dst,192const struct exec_list *list)193{194exec_list_make_empty(dst);195foreach_list_typed(nir_variable, var, node, list) {196nir_variable *nvar = clone_variable(state, var);197exec_list_push_tail(dst, &nvar->node);198}199}200201/* NOTE: for cloning nir_registers, bypass nir_global/local_reg_create()202* to avoid having to deal with locals and globals separately:203*/204static nir_register *205clone_register(clone_state *state, const nir_register *reg)206{207nir_register *nreg = rzalloc(state->ns, nir_register);208add_remap(state, nreg, reg);209210nreg->num_components = reg->num_components;211nreg->bit_size = reg->bit_size;212nreg->num_array_elems = reg->num_array_elems;213nreg->index = reg->index;214215/* reconstructing uses/defs/if_uses handled by nir_instr_insert() */216list_inithead(&nreg->uses);217list_inithead(&nreg->defs);218list_inithead(&nreg->if_uses);219220return nreg;221}222223/* clone list of nir_register: */224static void225clone_reg_list(clone_state *state, struct exec_list *dst,226const struct exec_list *list)227{228exec_list_make_empty(dst);229foreach_list_typed(nir_register, reg, node, list) {230nir_register *nreg = clone_register(state, reg);231exec_list_push_tail(dst, &nreg->node);232}233}234235static void236__clone_src(clone_state *state, void *ninstr_or_if,237nir_src *nsrc, const nir_src *src)238{239nsrc->is_ssa = src->is_ssa;240if (src->is_ssa) {241nsrc->ssa = remap_local(state, src->ssa);242} else {243nsrc->reg.reg = remap_reg(state, src->reg.reg);244if (src->reg.indirect) {245nsrc->reg.indirect = ralloc(ninstr_or_if, nir_src);246__clone_src(state, ninstr_or_if, nsrc->reg.indirect, src->reg.indirect);247}248nsrc->reg.base_offset = src->reg.base_offset;249}250}251252static void253__clone_dst(clone_state *state, nir_instr *ninstr,254nir_dest *ndst, const nir_dest *dst)255{256ndst->is_ssa = dst->is_ssa;257if (dst->is_ssa) {258nir_ssa_dest_init(ninstr, ndst, dst->ssa.num_components,259dst->ssa.bit_size, NULL);260if (likely(state->remap_table))261add_remap(state, &ndst->ssa, &dst->ssa);262} else {263ndst->reg.reg = remap_reg(state, dst->reg.reg);264if (dst->reg.indirect) {265ndst->reg.indirect = ralloc(ninstr, nir_src);266__clone_src(state, ninstr, ndst->reg.indirect, dst->reg.indirect);267}268ndst->reg.base_offset = dst->reg.base_offset;269}270}271272static nir_alu_instr *273clone_alu(clone_state *state, const nir_alu_instr *alu)274{275nir_alu_instr *nalu = nir_alu_instr_create(state->ns, alu->op);276nalu->exact = alu->exact;277nalu->no_signed_wrap = alu->no_signed_wrap;278nalu->no_unsigned_wrap = alu->no_unsigned_wrap;279280__clone_dst(state, &nalu->instr, &nalu->dest.dest, &alu->dest.dest);281nalu->dest.saturate = alu->dest.saturate;282nalu->dest.write_mask = alu->dest.write_mask;283284for (unsigned i = 0; i < nir_op_infos[alu->op].num_inputs; i++) {285__clone_src(state, &nalu->instr, &nalu->src[i].src, &alu->src[i].src);286nalu->src[i].negate = alu->src[i].negate;287nalu->src[i].abs = alu->src[i].abs;288memcpy(nalu->src[i].swizzle, alu->src[i].swizzle,289sizeof(nalu->src[i].swizzle));290}291292return nalu;293}294295nir_alu_instr *296nir_alu_instr_clone(nir_shader *shader, const nir_alu_instr *orig)297{298clone_state state = {299.allow_remap_fallback = true,300.ns = shader,301};302return clone_alu(&state, orig);303}304305static nir_deref_instr *306clone_deref_instr(clone_state *state, const nir_deref_instr *deref)307{308nir_deref_instr *nderef =309nir_deref_instr_create(state->ns, deref->deref_type);310311__clone_dst(state, &nderef->instr, &nderef->dest, &deref->dest);312313nderef->modes = deref->modes;314nderef->type = deref->type;315316if (deref->deref_type == nir_deref_type_var) {317nderef->var = remap_var(state, deref->var);318return nderef;319}320321__clone_src(state, &nderef->instr, &nderef->parent, &deref->parent);322323switch (deref->deref_type) {324case nir_deref_type_struct:325nderef->strct.index = deref->strct.index;326break;327328case nir_deref_type_array:329case nir_deref_type_ptr_as_array:330__clone_src(state, &nderef->instr,331&nderef->arr.index, &deref->arr.index);332break;333334case nir_deref_type_array_wildcard:335/* Nothing to do */336break;337338case nir_deref_type_cast:339nderef->cast.ptr_stride = deref->cast.ptr_stride;340nderef->cast.align_mul = deref->cast.align_mul;341nderef->cast.align_offset = deref->cast.align_offset;342break;343344default:345unreachable("Invalid instruction deref type");346}347348return nderef;349}350351static nir_intrinsic_instr *352clone_intrinsic(clone_state *state, const nir_intrinsic_instr *itr)353{354nir_intrinsic_instr *nitr =355nir_intrinsic_instr_create(state->ns, itr->intrinsic);356357unsigned num_srcs = nir_intrinsic_infos[itr->intrinsic].num_srcs;358359if (nir_intrinsic_infos[itr->intrinsic].has_dest)360__clone_dst(state, &nitr->instr, &nitr->dest, &itr->dest);361362nitr->num_components = itr->num_components;363memcpy(nitr->const_index, itr->const_index, sizeof(nitr->const_index));364365for (unsigned i = 0; i < num_srcs; i++)366__clone_src(state, &nitr->instr, &nitr->src[i], &itr->src[i]);367368return nitr;369}370371static nir_load_const_instr *372clone_load_const(clone_state *state, const nir_load_const_instr *lc)373{374nir_load_const_instr *nlc =375nir_load_const_instr_create(state->ns, lc->def.num_components,376lc->def.bit_size);377378memcpy(&nlc->value, &lc->value, sizeof(*nlc->value) * lc->def.num_components);379380add_remap(state, &nlc->def, &lc->def);381382return nlc;383}384385static nir_ssa_undef_instr *386clone_ssa_undef(clone_state *state, const nir_ssa_undef_instr *sa)387{388nir_ssa_undef_instr *nsa =389nir_ssa_undef_instr_create(state->ns, sa->def.num_components,390sa->def.bit_size);391392add_remap(state, &nsa->def, &sa->def);393394return nsa;395}396397static nir_tex_instr *398clone_tex(clone_state *state, const nir_tex_instr *tex)399{400nir_tex_instr *ntex = nir_tex_instr_create(state->ns, tex->num_srcs);401402ntex->sampler_dim = tex->sampler_dim;403ntex->dest_type = tex->dest_type;404ntex->op = tex->op;405__clone_dst(state, &ntex->instr, &ntex->dest, &tex->dest);406for (unsigned i = 0; i < ntex->num_srcs; i++) {407ntex->src[i].src_type = tex->src[i].src_type;408__clone_src(state, &ntex->instr, &ntex->src[i].src, &tex->src[i].src);409}410ntex->coord_components = tex->coord_components;411ntex->is_array = tex->is_array;412ntex->array_is_lowered_cube = tex->array_is_lowered_cube;413ntex->is_shadow = tex->is_shadow;414ntex->is_new_style_shadow = tex->is_new_style_shadow;415ntex->is_sparse = tex->is_sparse;416ntex->component = tex->component;417memcpy(ntex->tg4_offsets, tex->tg4_offsets, sizeof(tex->tg4_offsets));418419ntex->texture_index = tex->texture_index;420ntex->sampler_index = tex->sampler_index;421422ntex->texture_non_uniform = tex->texture_non_uniform;423ntex->sampler_non_uniform = tex->sampler_non_uniform;424425return ntex;426}427428static nir_phi_instr *429clone_phi(clone_state *state, const nir_phi_instr *phi, nir_block *nblk)430{431nir_phi_instr *nphi = nir_phi_instr_create(state->ns);432433__clone_dst(state, &nphi->instr, &nphi->dest, &phi->dest);434435/* Cloning a phi node is a bit different from other instructions. The436* sources of phi instructions are the only time where we can use an SSA437* def before it is defined. In order to handle this, we just copy over438* the sources from the old phi instruction directly and then fix them up439* in a second pass once all the instrutions in the function have been440* properly cloned.441*442* In order to ensure that the copied sources (which are the same as the443* old phi instruction's sources for now) don't get inserted into the old444* shader's use-def lists, we have to add the phi instruction *before* we445* set up its sources.446*/447nir_instr_insert_after_block(nblk, &nphi->instr);448449foreach_list_typed(nir_phi_src, src, node, &phi->srcs) {450nir_phi_src *nsrc = ralloc(nphi, nir_phi_src);451452/* Just copy the old source for now. */453memcpy(nsrc, src, sizeof(*src));454455/* Since we're not letting nir_insert_instr handle use/def stuff for us,456* we have to set the parent_instr manually. It doesn't really matter457* when we do it, so we might as well do it here.458*/459nsrc->src.parent_instr = &nphi->instr;460461/* Stash it in the list of phi sources. We'll walk this list and fix up462* sources at the very end of clone_function_impl.463*/464list_add(&nsrc->src.use_link, &state->phi_srcs);465466exec_list_push_tail(&nphi->srcs, &nsrc->node);467}468469return nphi;470}471472static nir_jump_instr *473clone_jump(clone_state *state, const nir_jump_instr *jmp)474{475/* These aren't handled because they require special block linking */476assert(jmp->type != nir_jump_goto && jmp->type != nir_jump_goto_if);477478nir_jump_instr *njmp = nir_jump_instr_create(state->ns, jmp->type);479480return njmp;481}482483static nir_call_instr *484clone_call(clone_state *state, const nir_call_instr *call)485{486nir_function *ncallee = remap_global(state, call->callee);487nir_call_instr *ncall = nir_call_instr_create(state->ns, ncallee);488489for (unsigned i = 0; i < ncall->num_params; i++)490__clone_src(state, ncall, &ncall->params[i], &call->params[i]);491492return ncall;493}494495static nir_instr *496clone_instr(clone_state *state, const nir_instr *instr)497{498switch (instr->type) {499case nir_instr_type_alu:500return &clone_alu(state, nir_instr_as_alu(instr))->instr;501case nir_instr_type_deref:502return &clone_deref_instr(state, nir_instr_as_deref(instr))->instr;503case nir_instr_type_intrinsic:504return &clone_intrinsic(state, nir_instr_as_intrinsic(instr))->instr;505case nir_instr_type_load_const:506return &clone_load_const(state, nir_instr_as_load_const(instr))->instr;507case nir_instr_type_ssa_undef:508return &clone_ssa_undef(state, nir_instr_as_ssa_undef(instr))->instr;509case nir_instr_type_tex:510return &clone_tex(state, nir_instr_as_tex(instr))->instr;511case nir_instr_type_phi:512unreachable("Cannot clone phis with clone_instr");513case nir_instr_type_jump:514return &clone_jump(state, nir_instr_as_jump(instr))->instr;515case nir_instr_type_call:516return &clone_call(state, nir_instr_as_call(instr))->instr;517case nir_instr_type_parallel_copy:518unreachable("Cannot clone parallel copies");519default:520unreachable("bad instr type");521return NULL;522}523}524525nir_instr *526nir_instr_clone(nir_shader *shader, const nir_instr *orig)527{528clone_state state = {529.allow_remap_fallback = true,530.ns = shader,531};532return clone_instr(&state, orig);533}534535static nir_block *536clone_block(clone_state *state, struct exec_list *cf_list, const nir_block *blk)537{538/* Don't actually create a new block. Just use the one from the tail of539* the list. NIR guarantees that the tail of the list is a block and that540* no two blocks are side-by-side in the IR; It should be empty.541*/542nir_block *nblk =543exec_node_data(nir_block, exec_list_get_tail(cf_list), cf_node.node);544assert(nblk->cf_node.type == nir_cf_node_block);545assert(exec_list_is_empty(&nblk->instr_list));546547/* We need this for phi sources */548add_remap(state, nblk, blk);549550nir_foreach_instr(instr, blk) {551if (instr->type == nir_instr_type_phi) {552/* Phi instructions are a bit of a special case when cloning because553* we don't want inserting the instruction to automatically handle554* use/defs for us. Instead, we need to wait until all the555* blocks/instructions are in so that we can set their sources up.556*/557clone_phi(state, nir_instr_as_phi(instr), nblk);558} else {559nir_instr *ninstr = clone_instr(state, instr);560nir_instr_insert_after_block(nblk, ninstr);561}562}563564return nblk;565}566567static void568clone_cf_list(clone_state *state, struct exec_list *dst,569const struct exec_list *list);570571static nir_if *572clone_if(clone_state *state, struct exec_list *cf_list, const nir_if *i)573{574nir_if *ni = nir_if_create(state->ns);575ni->control = i->control;576577__clone_src(state, ni, &ni->condition, &i->condition);578579nir_cf_node_insert_end(cf_list, &ni->cf_node);580581clone_cf_list(state, &ni->then_list, &i->then_list);582clone_cf_list(state, &ni->else_list, &i->else_list);583584return ni;585}586587static nir_loop *588clone_loop(clone_state *state, struct exec_list *cf_list, const nir_loop *loop)589{590nir_loop *nloop = nir_loop_create(state->ns);591nloop->control = loop->control;592nloop->partially_unrolled = loop->partially_unrolled;593594nir_cf_node_insert_end(cf_list, &nloop->cf_node);595596clone_cf_list(state, &nloop->body, &loop->body);597598return nloop;599}600601/* clone list of nir_cf_node: */602static void603clone_cf_list(clone_state *state, struct exec_list *dst,604const struct exec_list *list)605{606foreach_list_typed(nir_cf_node, cf, node, list) {607switch (cf->type) {608case nir_cf_node_block:609clone_block(state, dst, nir_cf_node_as_block(cf));610break;611case nir_cf_node_if:612clone_if(state, dst, nir_cf_node_as_if(cf));613break;614case nir_cf_node_loop:615clone_loop(state, dst, nir_cf_node_as_loop(cf));616break;617default:618unreachable("bad cf type");619}620}621}622623/* After we've cloned almost everything, we have to walk the list of phi624* sources and fix them up. Thanks to loops, the block and SSA value for a625* phi source may not be defined when we first encounter it. Instead, we626* add it to the phi_srcs list and we fix it up here.627*/628static void629fixup_phi_srcs(clone_state *state)630{631list_for_each_entry_safe(nir_phi_src, src, &state->phi_srcs, src.use_link) {632src->pred = remap_local(state, src->pred);633634/* Remove from this list */635list_del(&src->src.use_link);636637if (src->src.is_ssa) {638src->src.ssa = remap_local(state, src->src.ssa);639list_addtail(&src->src.use_link, &src->src.ssa->uses);640} else {641src->src.reg.reg = remap_reg(state, src->src.reg.reg);642list_addtail(&src->src.use_link, &src->src.reg.reg->uses);643}644}645assert(list_is_empty(&state->phi_srcs));646}647648void649nir_cf_list_clone(nir_cf_list *dst, nir_cf_list *src, nir_cf_node *parent,650struct hash_table *remap_table)651{652exec_list_make_empty(&dst->list);653dst->impl = src->impl;654655if (exec_list_is_empty(&src->list))656return;657658clone_state state;659init_clone_state(&state, remap_table, false, true);660661/* We use the same shader */662state.ns = src->impl->function->shader;663664/* The control-flow code assumes that the list of cf_nodes always starts665* and ends with a block. We start by adding an empty block.666*/667nir_block *nblk = nir_block_create(state.ns);668nblk->cf_node.parent = parent;669exec_list_push_tail(&dst->list, &nblk->cf_node.node);670671clone_cf_list(&state, &dst->list, &src->list);672673fixup_phi_srcs(&state);674675if (!remap_table)676free_clone_state(&state);677}678679static nir_function_impl *680clone_function_impl(clone_state *state, const nir_function_impl *fi)681{682nir_function_impl *nfi = nir_function_impl_create_bare(state->ns);683684clone_var_list(state, &nfi->locals, &fi->locals);685clone_reg_list(state, &nfi->registers, &fi->registers);686nfi->reg_alloc = fi->reg_alloc;687688assert(list_is_empty(&state->phi_srcs));689690clone_cf_list(state, &nfi->body, &fi->body);691692fixup_phi_srcs(state);693694/* All metadata is invalidated in the cloning process */695nfi->valid_metadata = 0;696697return nfi;698}699700nir_function_impl *701nir_function_impl_clone(nir_shader *shader, const nir_function_impl *fi)702{703clone_state state;704init_clone_state(&state, NULL, false, false);705706state.ns = shader;707708nir_function_impl *nfi = clone_function_impl(&state, fi);709710free_clone_state(&state);711712return nfi;713}714715static nir_function *716clone_function(clone_state *state, const nir_function *fxn, nir_shader *ns)717{718assert(ns == state->ns);719nir_function *nfxn = nir_function_create(ns, fxn->name);720721/* Needed for call instructions */722add_remap(state, nfxn, fxn);723724nfxn->num_params = fxn->num_params;725if (fxn->num_params) {726nfxn->params = ralloc_array(state->ns, nir_parameter, fxn->num_params);727memcpy(nfxn->params, fxn->params, sizeof(nir_parameter) * fxn->num_params);728}729nfxn->is_entrypoint = fxn->is_entrypoint;730731/* At first glance, it looks like we should clone the function_impl here.732* However, call instructions need to be able to reference at least the733* function and those will get processed as we clone the function_impls.734* We stop here and do function_impls as a second pass.735*/736737return nfxn;738}739740nir_shader *741nir_shader_clone(void *mem_ctx, const nir_shader *s)742{743clone_state state;744init_clone_state(&state, NULL, true, false);745746nir_shader *ns = nir_shader_create(mem_ctx, s->info.stage, s->options, NULL);747state.ns = ns;748749clone_var_list(&state, &ns->variables, &s->variables);750751/* Go through and clone functions */752foreach_list_typed(nir_function, fxn, node, &s->functions)753clone_function(&state, fxn, ns);754755/* Only after all functions are cloned can we clone the actual function756* implementations. This is because nir_call_instrs need to reference the757* functions of other functions and we don't know what order the functions758* will have in the list.759*/760nir_foreach_function(fxn, s) {761nir_function *nfxn = remap_global(&state, fxn);762nfxn->impl = clone_function_impl(&state, fxn->impl);763nfxn->impl->function = nfxn;764}765766ns->info = s->info;767ns->info.name = ralloc_strdup(ns, ns->info.name);768if (ns->info.label)769ns->info.label = ralloc_strdup(ns, ns->info.label);770771ns->num_inputs = s->num_inputs;772ns->num_uniforms = s->num_uniforms;773ns->num_outputs = s->num_outputs;774ns->scratch_size = s->scratch_size;775776ns->constant_data_size = s->constant_data_size;777if (s->constant_data_size > 0) {778ns->constant_data = ralloc_size(ns, s->constant_data_size);779memcpy(ns->constant_data, s->constant_data, s->constant_data_size);780}781782free_clone_state(&state);783784return ns;785}786787/** Overwrites dst and replaces its contents with src788*789* Everything ralloc parented to dst and src itself (but not its children)790* will be freed.791*792* This should only be used by test code which needs to swap out shaders with793* a cloned or deserialized version.794*/795void796nir_shader_replace(nir_shader *dst, nir_shader *src)797{798/* Delete all of dest's ralloc children */799void *dead_ctx = ralloc_context(NULL);800ralloc_adopt(dead_ctx, dst);801ralloc_free(dead_ctx);802803/* Re-parent all of src's ralloc children to dst */804ralloc_adopt(dst, src);805806memcpy(dst, src, sizeof(*dst));807808/* We have to move all the linked lists over separately because we need the809* pointers in the list elements to point to the lists in dst and not src.810*/811exec_list_move_nodes_to(&src->variables, &dst->variables);812813/* Now move the functions over. This takes a tiny bit more work */814exec_list_move_nodes_to(&src->functions, &dst->functions);815nir_foreach_function(function, dst)816function->shader = dst;817818ralloc_free(src);819}820821822