diff options
author | David Malcolm <dmalcolm@redhat.com> | 2020-11-12 17:28:17 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2020-11-12 17:30:01 -0500 |
commit | 421d0d0f54294a7bf2872b3b2ac521ce0fa9869e (patch) | |
tree | 750ae2f9567352ed7762d896424c2194c324f208 /gcc/jit/jit-playback.c | |
parent | fec573408310139e1ffc42741fbe46b4f2947592 (diff) | |
download | gcc-421d0d0f54294a7bf2872b3b2ac521ce0fa9869e.zip gcc-421d0d0f54294a7bf2872b3b2ac521ce0fa9869e.tar.gz gcc-421d0d0f54294a7bf2872b3b2ac521ce0fa9869e.tar.bz2 |
jit: add support for inline asm [PR87291]
This patch adds various entrypoints to libgccjit for directly embedding
asm statements into a compile, analogous to inline asm in the C frontend:
gcc_jit_block_add_extended_asm
gcc_jit_block_end_with_extended_asm_goto
gcc_jit_extended_asm_as_object
gcc_jit_extended_asm_set_volatile_flag
gcc_jit_extended_asm_set_inline_flag
gcc_jit_extended_asm_add_output_operand
gcc_jit_extended_asm_add_input_operand
gcc_jit_extended_asm_add_clobber
gcc_jit_context_add_top_level_asm
gcc/jit/ChangeLog:
PR jit/87291
* docs/cp/topics/asm.rst: New file.
* docs/cp/topics/index.rst (Topic Reference): Add it.
* docs/topics/asm.rst: New file.
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_15): New.
* docs/topics/functions.rst (Statements): Add link to extended
asm.
* docs/topics/index.rst (Topic Reference): Add asm.rst.
* docs/topics/objects.rst: Add gcc_jit_extended_asm to ASCII art.
* docs/_build/texinfo/Makefile: Regenerate.
* docs/_build/texinfo/libgccjit.texi: Regenerate.
* jit-common.h (gcc::jit::recording::extended_asm): New forward
decl.
(gcc::jit::recording::top_level_asm): Likewise.
* jit-playback.c: Include "stmt.h".
(build_string): New.
(gcc::jit::playback::context::new_string_literal): Disambiguate
build_string call.
(gcc::jit::playback::context::add_top_level_asm): New.
(build_operand_chain): New.
(build_clobbers): New.
(build_goto_operands): New.
(gcc::jit::playback::block::add_extended_asm): New.
* jit-playback.h (gcc::jit::playback::context::add_top_level_asm):
New decl.
(struct gcc::jit::playback::asm_operand): New struct.
(gcc::jit::playback::block::add_extended_asm): New decl.
* jit-recording.c (gcc::jit::recording::context::dump_to_file):
Dump top-level asms.
(gcc::jit::recording::context::add_top_level_asm): New.
(gcc::jit::recording::block::add_extended_asm): New.
(gcc::jit::recording::block::end_with_extended_asm_goto): New.
(gcc::jit::recording::asm_operand::asm_operand): New.
(gcc::jit::recording::asm_operand::print): New.
(gcc::jit::recording::asm_operand::make_debug_string): New.
(gcc::jit::recording::output_asm_operand::write_reproducer): New.
(gcc::jit::recording::output_asm_operand::print): New.
(gcc::jit::recording::input_asm_operand::write_reproducer): New.
(gcc::jit::recording::input_asm_operand::print): New.
(gcc::jit::recording::extended_asm::add_output_operand): New.
(gcc::jit::recording::extended_asm::add_input_operand): New.
(gcc::jit::recording::extended_asm::add_clobber): New.
(gcc::jit::recording::extended_asm::replay_into): New.
(gcc::jit::recording::extended_asm::make_debug_string): New.
(gcc::jit::recording::extended_asm::write_flags): New.
(gcc::jit::recording::extended_asm::write_clobbers): New.
(gcc::jit::recording::extended_asm_simple::write_reproducer): New.
(gcc::jit::recording::extended_asm::maybe_populate_playback_blocks):
New.
(gcc::jit::recording::extended_asm_goto::extended_asm_goto): New.
(gcc::jit::recording::extended_asm_goto::replay_into): New.
(gcc::jit::recording::extended_asm_goto::write_reproducer): New.
(gcc::jit::recording::extended_asm_goto::get_successor_blocks):
New.
(gcc::jit::recording::extended_asm_goto::maybe_print_gotos): New.
(gcc::jit::recording::extended_asm_goto::maybe_populate_playback_blocks):
New.
(gcc::jit::recording::top_level_asm::top_level_asm): New.
(gcc::jit::recording::top_level_asm::replay_into): New.
(gcc::jit::recording::top_level_asm::make_debug_string): New.
(gcc::jit::recording::top_level_asm::write_to_dump): New.
(gcc::jit::recording::top_level_asm::write_reproducer): New.
* jit-recording.h
(gcc::jit::recording::context::add_top_level_asm): New decl.
(gcc::jit::recording::context::m_top_level_asms): New field.
(gcc::jit::recording::block::add_extended_asm): New decl.
(gcc::jit::recording::block::end_with_extended_asm_goto): New
decl.
(gcc::jit::recording::asm_operand): New class.
(gcc::jit::recording::output_asm_operand): New class.
(gcc::jit::recording::input_asm_operand): New class.
(gcc::jit::recording::extended_asm): New class.
(gcc::jit::recording::extended_asm_simple): New class.
(gcc::jit::recording::extended_asm_goto): New class.
(gcc::jit::recording::top_level_asm): New class.
* libgccjit++.h (gccjit::extended_asm): New forward decl.
(gccjit::context::add_top_level_asm): New.
(gccjit::block::add_extended_asm): New.
(gccjit::block::end_with_extended_asm_goto): New.
(gccjit::extended_asm): New class.
(gccjit::extended_asm::extended_asm): New ctors.
(gccjit::extended_asm::set_volatile_flag): New.
(gccjit::extended_asm::set_inline_flag): New.
(gccjit::extended_asm::add_output_operand): New.
(gccjit::extended_asm::add_input_operand): New.
(gccjit::extended_asm::add_clobber): New.
(gccjit::extended_asm::get_inner_extended_asm): New.
* libgccjit.c (struct gcc_jit_extended_asm): New.
(jit_error): Make "loc" param take a gcc::jit::recording::location *
rather than a gcc_jit_location *.
(gcc_jit_block_add_extended_asm): New entrypoint.
(gcc_jit_block_end_with_extended_asm_goto): New entrypoint.
(gcc_jit_extended_asm_as_object): New entrypoint.
(gcc_jit_extended_asm_set_volatile_flag): New entrypoint.
(gcc_jit_extended_asm_set_inline_flag): New entrypoint.
(gcc_jit_extended_asm_add_output_operand): New entrypoint.
(gcc_jit_extended_asm_add_clobber): New entrypoint.
(gcc_jit_context_add_top_level_asm): New entrypoint.
* libgccjit.h: Add gcc_jit_extended_asm to ASCII art.
(gcc_jit_extended_asm): New typedef.
(LIBGCCJIT_HAVE_ASM_STATEMENTS): New define.
(gcc_jit_block_add_extended_asm): New entrypoint.
(gcc_jit_block_end_with_extended_asm_goto): New entrypoint.
(gcc_jit_extended_asm_as_object): New entrypoint.
(gcc_jit_extended_asm_set_volatile_flag): New entrypoint.
(gcc_jit_extended_asm_set_inline_flag): New entrypoint.
(gcc_jit_extended_asm_add_output_operand): New entrypoint.
(gcc_jit_extended_asm_add_input_operand): New entrypoint.
(gcc_jit_extended_asm_add_clobber): New entrypoint.
(gcc_jit_context_add_top_level_asm): New entrypoint.
* libgccjit.map (LIBGCCJIT_ABI_15): New.
gcc/testsuite/ChangeLog:
PR jit/87291
* jit.dg/jit.exp: Load target-supports-dg.exp.
Set dg-do-what-default.
(jit-dg-test): Set dg-do-what and call dg-get-options, skipping
the test if it's not supported on the given target.
* jit.dg/test-asm.c: New test.
* jit.dg/test-asm.cc: New test.
Diffstat (limited to 'gcc/jit/jit-playback.c')
-rw-r--r-- | gcc/jit/jit-playback.c | 125 |
1 files changed, 124 insertions, 1 deletions
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index 4fac64d..5bccf59 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see #include "opt-suggestions.h" #include "gcc.h" #include "diagnostic.h" +#include "stmt.h" #include <pthread.h> @@ -86,6 +87,18 @@ namespace jit { Playback. **********************************************************************/ +/* Build a STRING_CST tree for STR, or return NULL if it is NULL. + The TREE_TYPE is not initialized. */ + +static tree +build_string (const char *str) +{ + if (str) + return ::build_string (strlen (str), str); + else + return NULL_TREE; +} + /* The constructor for gcc::jit::playback::context. */ playback::context::context (recording::context *ctxt) @@ -774,7 +787,7 @@ new_string_literal (const char *value) tree a_type = build_array_type (char_type_node, i_type); /* build_string len parameter must include NUL terminator when building C strings. */ - tree t_str = build_string (len + 1, value); + tree t_str = ::build_string (len + 1, value); TREE_TYPE (t_str) = a_type; /* Convert to (const char*), loosely based on @@ -821,6 +834,18 @@ as_truth_value (tree expr, location *loc) return expr; } +/* Add a "top-level" basic asm statement (i.e. one outside of any functions) + containing ASM_STMTS. + + Compare with c_parser_asm_definition. */ + +void +playback::context::add_top_level_asm (const char *asm_stmts) +{ + tree asm_str = build_string (asm_stmts); + symtab->finalize_toplevel_asm (asm_str); +} + /* Construct a playback::rvalue instance (wrapping a tree) for a unary op. */ @@ -1897,6 +1922,104 @@ add_switch (location *loc, add_stmt (switch_stmt); } +/* Convert OPERANDS to a tree-based chain suitable for creating an + extended asm stmt. + Compare with c_parser_asm_operands. */ + +static tree +build_operand_chain (const auto_vec <playback::asm_operand> *operands) +{ + tree result = NULL_TREE; + unsigned i; + playback::asm_operand *asm_op; + FOR_EACH_VEC_ELT (*operands, i, asm_op) + { + tree name = build_string (asm_op->m_asm_symbolic_name); + tree str = build_string (asm_op->m_constraint); + tree value = asm_op->m_expr; + result = chainon (result, + build_tree_list (build_tree_list (name, str), + value)); + } + return result; +} + +/* Convert CLOBBERS to a tree-based list suitable for creating an + extended asm stmt. + Compare with c_parser_asm_clobbers. */ + +static tree +build_clobbers (const auto_vec <const char *> *clobbers) +{ + tree list = NULL_TREE; + unsigned i; + const char *clobber; + FOR_EACH_VEC_ELT (*clobbers, i, clobber) + { + tree str = build_string (clobber); + list = tree_cons (NULL_TREE, str, list); + } + return list; +} + +/* Convert BLOCKS to a tree-based list suitable for creating an + extended asm stmt. + Compare with c_parser_asm_goto_operands. */ + +static tree +build_goto_operands (const auto_vec <playback::block *> *blocks) +{ + tree list = NULL_TREE; + unsigned i; + playback::block *b; + FOR_EACH_VEC_ELT (*blocks, i, b) + { + tree label = b->as_label_decl (); + tree name = build_string (IDENTIFIER_POINTER (DECL_NAME (label))); + TREE_USED (label) = 1; + list = tree_cons (name, label, list); + } + return nreverse (list); +} + +/* Add an extended asm statement to this block. + + Compare with c_parser_asm_statement (in c/c-parser.c) + and build_asm_expr (in c/c-typeck.c). */ + +void +playback::block::add_extended_asm (location *loc, + const char *asm_template, + bool is_volatile, + bool is_inline, + const auto_vec <asm_operand> *outputs, + const auto_vec <asm_operand> *inputs, + const auto_vec <const char *> *clobbers, + const auto_vec <block *> *goto_blocks) +{ + tree t_string = build_string (asm_template); + tree t_outputs = build_operand_chain (outputs); + tree t_inputs = build_operand_chain (inputs); + tree t_clobbers = build_clobbers (clobbers); + tree t_labels = build_goto_operands (goto_blocks); + t_string + = resolve_asm_operand_names (t_string, t_outputs, t_inputs, t_labels); + tree asm_stmt + = build5 (ASM_EXPR, void_type_node, + t_string, t_outputs, t_inputs, t_clobbers, t_labels); + + /* asm statements without outputs, including simple ones, are treated + as volatile. */ + ASM_VOLATILE_P (asm_stmt) = (outputs->length () == 0); + ASM_INPUT_P (asm_stmt) = 0; /* extended asm stmts are not "simple". */ + ASM_INLINE_P (asm_stmt) = is_inline; + if (is_volatile) + ASM_VOLATILE_P (asm_stmt) = 1; + if (loc) + set_tree_location (asm_stmt, loc); + add_stmt (asm_stmt); +} + /* Constructor for gcc::jit::playback::block. */ playback::block:: |