Implement statement::clone_into for asm statements
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc index 84ccc6d..4e83d7b 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc
@@ -4805,7 +4805,13 @@ { if (block **existing = m_map.get (orig)) return *existing; - block *clone = m_func->new_block (NULL); + /* Give the clone the original's name. Block names need not be unique + (blocks are identified by pointer, and only dumps and error messages + use the name), and reusing it keeps the label's identifier, so an + "asm goto" template referring to a label symbolically ("%l[name]") + still resolves in the clone. */ + block *clone + = m_func->new_block (orig->m_name ? orig->m_name->c_str () : NULL); clone->m_is_reachable = orig->m_is_reachable; m_map.put (orig, clone); m_all.safe_push (orig); @@ -7994,23 +8000,12 @@ m_loc = d.make_location (); } -/* Default implementation of recording::statement::clone_into: reject - statement kinds that carry state which cannot be safely duplicated (e.g. - extended asm). The kinds that appear in cleanup bodies override this. */ - -void -recording::statement::clone_into (block_cloner &, block *) const -{ - m_ctxt->add_error (get_loc (), - "cloning this kind of statement is not supported"); -} - /* clone_into / get_inlined_blocks implementations for the concrete - statement kinds that a cleanup body may contain. Each re-emits itself - into DEST via the normal recording API (so all bookkeeping -- context - recording, termination flags, reachability -- is reused), remapping block - references through CLONER. References to blocks inside the cloned set - become the clones; references outside it are preserved. */ + statement kinds. Each re-emits itself into DEST via the normal recording + API (so all bookkeeping -- context recording, termination flags, + reachability -- is reused), remapping block references through CLONER. + References to blocks inside the cloned set become the clones; references + outside it are preserved. */ void recording::eval::clone_into (block_cloner &cloner, block *dest) const @@ -8114,6 +8109,66 @@ out.safe_push (b); } +/* Copy the flags, operands and clobbers of this extended asm into DEST, a + freshly-created clone of it. The asm template and the operands' symbolic + names and constraints are immutable strings, so they are simply re-added; + the operands' lvalues/rvalues are cloned through CLONER. */ + +void +recording::extended_asm::clone_contents_into (block_cloner &cloner, + extended_asm *dest) const +{ + dest->set_volatile_flag (m_is_volatile); + dest->set_inline_flag (m_is_inline); + + unsigned i; + output_asm_operand *output_op; + FOR_EACH_VEC_ELT (m_output_ops, i, output_op) + dest->add_output_operand (output_op->get_symbolic_name (), + output_op->get_constraint (), + cloner.clone_lvalue (output_op->get_lvalue ())); + + input_asm_operand *input_op; + FOR_EACH_VEC_ELT (m_input_ops, i, input_op) + dest->add_input_operand (input_op->get_symbolic_name (), + input_op->get_constraint (), + cloner.clone_rvalue (input_op->get_rvalue ())); + + string *clobber; + FOR_EACH_VEC_ELT (m_clobbers, i, clobber) + dest->add_clobber (clobber->c_str ()); +} + +void +recording::extended_asm_simple::clone_into (block_cloner &cloner, + block *dest) const +{ + extended_asm *clone + = dest->add_extended_asm (get_loc (), m_asm_template->c_str ()); + clone_contents_into (cloner, clone); +} + +void +recording::extended_asm_goto::clone_into (block_cloner &cloner, + block *dest) const +{ + auto_vec<block *> goto_blocks (m_goto_blocks.length ()); + unsigned i; + block *b; + FOR_EACH_VEC_ELT (m_goto_blocks, i, b) + goto_blocks.quick_push (cloner.remap (b)); + + extended_asm *clone + = dest->end_with_extended_asm_goto (get_loc (), + m_asm_template->c_str (), + goto_blocks.length (), + goto_blocks.address (), + (m_fallthrough_block + ? cloner.remap (m_fallthrough_block) + : NULL)); + clone_contents_into (cloner, clone); +} + /* The implementation of class gcc::jit::recording::memento_of_set_personality_function. */ /* Implementation of pure virtual hook recording::memento::replay_into
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 0f65997..acb70d0 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h
@@ -3011,10 +3011,10 @@ /* Re-emit this statement into DEST (a clone block), remapping any block references through CLONER so a duplicated subgraph is self-contained. - The base implementation reports an error for statement kinds that carry - state which cannot be safely duplicated (e.g. extended asm); the kinds - that appear in cleanup bodies override it. See block_cloner. */ - virtual void clone_into (block_cloner &cloner, block *dest) const; + Pure so every concrete statement kind must provide a clone -- + gcc_jit_blocks_clone stays fully generic, and adding a new statement + kind forces a clone at compile time. See block_cloner. */ + virtual void clone_into (block_cloner &cloner, block *dest) const = 0; /* Append to OUT the blocks whose statements this statement *inlines* (rather than merely branching to): a try/catch's try and handler blocks, @@ -3465,6 +3465,11 @@ void write_flags (reproducer &r); void write_clobbers (reproducer &r); + /* Copy the flags, operands and clobbers of this extended asm into DEST + (a freshly-created clone of it), cloning the operands' rvalues through + CLONER. Used by the clone_into of both concrete subclasses. */ + void clone_contents_into (block_cloner &cloner, extended_asm *dest) const; + private: string * make_debug_string () final override; virtual void maybe_populate_playback_blocks @@ -3495,6 +3500,8 @@ bool is_goto () const final override { return false; } void maybe_print_gotos (pretty_printer *) const final override {} + void clone_into (block_cloner &cloner, block *dest) const final override; + private: void maybe_populate_playback_blocks (auto_vec <playback::block *> *) final override @@ -3522,6 +3529,8 @@ bool is_goto () const final override { return true; } void maybe_print_gotos (pretty_printer *) const final override; + void clone_into (block_cloner &cloner, block *dest) const final override; + private: void maybe_populate_playback_blocks (auto_vec <playback::block *> *out) final override;