aboutsummaryrefslogtreecommitdiff
path: root/gcc/jit/jit-playback.c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2020-11-12 17:28:17 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2020-11-12 17:30:01 -0500
commit421d0d0f54294a7bf2872b3b2ac521ce0fa9869e (patch)
tree750ae2f9567352ed7762d896424c2194c324f208 /gcc/jit/jit-playback.c
parentfec573408310139e1ffc42741fbe46b4f2947592 (diff)
downloadgcc-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.c125
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::