This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH 15/27] New file: gcc/jit/jit-playback.h
- From: David Malcolm <dmalcolm at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org, jit at gcc dot gnu dot org
- Cc: David Malcolm <dmalcolm at redhat dot com>
- Date: Fri, 31 Oct 2014 13:02:48 -0400
- Subject: [PATCH 15/27] New file: gcc/jit/jit-playback.h
- Authentication-results: sourceware.org; auth=none
- References: <1414774977-25605-1-git-send-email-dmalcolm at redhat dot com>
This files declares the gcc::jit::playback internal API, called by
the dummy "frontend" to replay the public API calls made to the
library. A thin wrapper around trees.
gcc/jit/
* jit-playback.h: New.
---
gcc/jit/jit-playback.h | 564 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 564 insertions(+)
create mode 100644 gcc/jit/jit-playback.h
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
new file mode 100644
index 0000000..dcb19bf
--- /dev/null
+++ b/gcc/jit/jit-playback.h
@@ -0,0 +1,564 @@
+/* Internals of libgccjit: classes for playing back recorded API calls.
+ Copyright (C) 2013-2014 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef JIT_PLAYBACK_H
+#define JIT_PLAYBACK_H
+
+#include <utility> // for std::pair
+
+#include "jit-recording.h"
+
+namespace gcc {
+
+namespace jit {
+
+/**********************************************************************
+ Playback.
+ **********************************************************************/
+
+namespace playback {
+
+class context
+{
+public:
+ context (::gcc::jit::recording::context *ctxt);
+ ~context ();
+
+ void gt_ggc_mx ();
+
+ void replay ();
+
+ location *
+ new_location (recording::location *rloc,
+ const char *filename,
+ int line,
+ int column);
+
+ type *
+ get_type (enum gcc_jit_types type);
+
+ type *
+ new_array_type (location *loc,
+ type *element_type,
+ int num_elements);
+
+ field *
+ new_field (location *loc,
+ type *type,
+ const char *name);
+
+ compound_type *
+ new_compound_type (location *loc,
+ const char *name,
+ bool is_struct); /* else is union */
+
+ type *
+ new_function_type (type *return_type,
+ vec<type *> *param_types,
+ int is_variadic);
+
+ param *
+ new_param (location *loc,
+ type *type,
+ const char *name);
+
+ function *
+ new_function (location *loc,
+ enum gcc_jit_function_kind kind,
+ type *return_type,
+ const char *name,
+ vec<param *> *params,
+ int is_variadic,
+ enum built_in_function builtin_id);
+
+ lvalue *
+ new_global (location *loc,
+ type *type,
+ const char *name);
+
+ rvalue *
+ new_rvalue_from_int (type *type,
+ int value);
+
+ rvalue *
+ new_rvalue_from_double (type *type,
+ double value);
+
+ rvalue *
+ new_rvalue_from_ptr (type *type,
+ void *value);
+
+ rvalue *
+ new_string_literal (const char *value);
+
+ rvalue *
+ new_unary_op (location *loc,
+ enum gcc_jit_unary_op op,
+ type *result_type,
+ rvalue *a);
+
+ rvalue *
+ new_binary_op (location *loc,
+ enum gcc_jit_binary_op op,
+ type *result_type,
+ rvalue *a, rvalue *b);
+
+ rvalue *
+ new_comparison (location *loc,
+ enum gcc_jit_comparison op,
+ rvalue *a, rvalue *b);
+
+ rvalue *
+ new_call (location *loc,
+ function *func,
+ vec<rvalue *> args);
+
+ rvalue *
+ new_call_through_ptr (location *loc,
+ rvalue *fn_ptr,
+ vec<rvalue *> args);
+
+ rvalue *
+ new_cast (location *loc,
+ rvalue *expr,
+ type *type_);
+
+ lvalue *
+ new_array_access (location *loc,
+ rvalue *ptr,
+ rvalue *index);
+
+ void
+ set_str_option (enum gcc_jit_str_option opt,
+ const char *value);
+
+ void
+ set_int_option (enum gcc_jit_int_option opt,
+ int value);
+
+ void
+ set_bool_option (enum gcc_jit_bool_option opt,
+ int value);
+
+ const char *
+ get_str_option (enum gcc_jit_str_option opt) const
+ {
+ return m_recording_ctxt->get_str_option (opt);
+ }
+
+ int
+ get_int_option (enum gcc_jit_int_option opt) const
+ {
+ return m_recording_ctxt->get_int_option (opt);
+ }
+
+ int
+ get_bool_option (enum gcc_jit_bool_option opt) const
+ {
+ return m_recording_ctxt->get_bool_option (opt);
+ }
+
+ result *
+ compile ();
+
+ void
+ add_error (location *loc, const char *fmt, ...)
+ GNU_PRINTF(3, 4);
+
+ void
+ add_error_va (location *loc, const char *fmt, va_list ap)
+ GNU_PRINTF(3, 0);
+
+ const char *
+ get_first_error () const;
+
+ void
+ set_tree_location (tree t, location *loc);
+
+ tree
+ new_field_access (location *loc,
+ tree datum,
+ field *field);
+
+ tree
+ new_dereference (tree ptr, location *loc);
+
+ tree
+ as_truth_value (tree expr, location *loc);
+
+ bool errors_occurred () const
+ {
+ return m_recording_ctxt->errors_occurred ();
+ }
+
+private:
+ void dump_generated_code ();
+
+ rvalue *
+ build_call (location *loc,
+ tree fn_ptr,
+ vec<rvalue *> args);
+
+ tree
+ build_cast (location *loc,
+ rvalue *expr,
+ type *type_);
+
+ source_file *
+ get_source_file (const char *filename);
+
+ void handle_locations ();
+
+private:
+ ::gcc::jit::recording::context *m_recording_ctxt;
+
+ /* Allocated using xmalloc (by xstrdup). */
+ char *m_path_template;
+
+ /* This either aliases m_path_template, or is NULL. */
+ char *m_path_tempdir;
+
+ /* The following are allocated using xmalloc. */
+ char *m_path_c_file;
+ char *m_path_s_file;
+ char *m_path_so_file;
+
+ vec<function *> m_functions;
+ tree m_char_array_type_node;
+ tree m_const_char_ptr;
+
+ /* Source location handling. */
+ vec<source_file *> m_source_files;
+
+ vec<std::pair<tree, location *> > m_cached_locations;
+};
+
+/* A temporary wrapper object.
+ These objects are (mostly) only valid during replay.
+ We allocate them on the GC heap, so that they will be cleaned
+ the next time the GC collects.
+ The exception is the "function" class, which is tracked and marked by
+ the jit::context, since it needs to stay alive during post-processing
+ (when the GC could run). */
+class wrapper
+{
+public:
+ /* Allocate in the GC heap. */
+ void *operator new (size_t sz);
+
+};
+
+class type : public wrapper
+{
+public:
+ type (tree inner)
+ : m_inner(inner)
+ {}
+
+ tree as_tree () const { return m_inner; }
+
+ type *get_pointer () const { return new type (build_pointer_type (m_inner)); }
+
+ type *get_const () const
+ {
+ return new type (build_qualified_type (m_inner, TYPE_QUAL_CONST));
+ }
+
+ type *get_volatile () const
+ {
+ return new type (build_qualified_type (m_inner, TYPE_QUAL_VOLATILE));
+ }
+
+private:
+ tree m_inner;
+};
+
+class compound_type : public type
+{
+public:
+ compound_type (tree inner)
+ : type (inner)
+ {}
+
+ void set_fields (const vec<field *> &fields);
+};
+
+class field : public wrapper
+{
+public:
+ field (tree inner)
+ : m_inner(inner)
+ {}
+
+ tree as_tree () const { return m_inner; }
+
+private:
+ tree m_inner;
+};
+
+class function : public wrapper
+{
+public:
+ function(context *ctxt, tree fndecl, enum gcc_jit_function_kind kind);
+
+ void gt_ggc_mx ();
+
+ tree get_return_type_as_tree () const;
+
+ tree as_fndecl () const { return m_inner_fndecl; }
+
+ enum gcc_jit_function_kind get_kind () const { return m_kind; }
+
+ lvalue *
+ new_local (location *loc,
+ type *type,
+ const char *name);
+
+ block*
+ new_block (const char *name);
+
+ void
+ build_stmt_list ();
+
+ void
+ postprocess ();
+
+public:
+ context *m_ctxt;
+
+public:
+ void
+ set_tree_location (tree t, location *loc)
+ {
+ m_ctxt->set_tree_location (t, loc);
+ }
+
+private:
+ tree m_inner_fndecl;
+ tree m_inner_block;
+ tree m_inner_bind_expr;
+ enum gcc_jit_function_kind m_kind;
+ tree m_stmt_list;
+ tree_stmt_iterator m_stmt_iter;
+ vec<block *> m_blocks;
+};
+
+class block : public wrapper
+{
+public:
+ block (function *func,
+ const char *name);
+
+ tree as_label_decl () const { return m_label_decl; }
+
+ void
+ add_eval (location *loc,
+ rvalue *rvalue);
+
+ void
+ add_assignment (location *loc,
+ lvalue *lvalue,
+ rvalue *rvalue);
+
+ void
+ add_comment (location *loc,
+ const char *text);
+
+ void
+ add_conditional (location *loc,
+ rvalue *boolval,
+ block *on_true,
+ block *on_false);
+
+ block *
+ add_block (location *loc,
+ const char *name);
+
+ void
+ add_jump (location *loc,
+ block *target);
+
+ void
+ add_return (location *loc,
+ rvalue *rvalue);
+
+private:
+ void
+ set_tree_location (tree t, location *loc)
+ {
+ m_func->set_tree_location (t, loc);
+ }
+
+ void add_stmt (tree stmt)
+ {
+ /* TODO: use one stmt_list per block. */
+ m_stmts.safe_push (stmt);
+ }
+
+private:
+ function *m_func;
+ tree m_label_decl;
+ vec<tree> m_stmts;
+
+public: // for now
+ tree m_label_expr;
+
+ friend class function;
+};
+
+class rvalue : public wrapper
+{
+public:
+ rvalue (context *ctxt, tree inner)
+ : m_ctxt (ctxt),
+ m_inner (inner)
+ {}
+
+ rvalue *
+ as_rvalue () { return this; }
+
+ tree as_tree () const { return m_inner; }
+
+ context *get_context () const { return m_ctxt; }
+
+ type *
+ get_type () { return new type (TREE_TYPE (m_inner)); }
+
+ rvalue *
+ access_field (location *loc,
+ field *field);
+
+ lvalue *
+ dereference_field (location *loc,
+ field *field);
+
+ lvalue *
+ dereference (location *loc);
+
+private:
+ context *m_ctxt;
+ tree m_inner;
+};
+
+class lvalue : public rvalue
+{
+public:
+ lvalue (context *ctxt, tree inner)
+ : rvalue(ctxt, inner)
+ {}
+
+ lvalue *
+ as_lvalue () { return this; }
+
+ lvalue *
+ access_field (location *loc,
+ field *field);
+
+ rvalue *
+ get_address (location *loc);
+
+};
+
+class param : public lvalue
+{
+public:
+ param (context *ctxt, tree inner)
+ : lvalue(ctxt, inner)
+ {}
+};
+
+/* Dealing with the linemap API.
+
+ It appears that libcpp requires locations to be created as if by
+ a tokenizer, creating them by filename, in ascending order of
+ line/column, whereas our API doesn't impose any such constraints:
+ we allow client code to create locations in arbitrary orders.
+
+ To square this circle, we need to cache all location creation,
+ grouping things up by filename/line, and then creating the linemap
+ entries in a post-processing phase. */
+
+/* A set of locations, all sharing a filename */
+class source_file : public wrapper
+{
+public:
+ source_file (tree filename);
+
+ source_line *
+ get_source_line (int line_num);
+
+ tree filename_as_tree () const { return m_filename; }
+
+ const char*
+ get_filename () const { return IDENTIFIER_POINTER (m_filename); }
+
+ vec<source_line *> m_source_lines;
+
+private:
+ tree m_filename;
+};
+
+/* A source line, with one or more locations of interest. */
+class source_line : public wrapper
+{
+public:
+ source_line (source_file *file, int line_num);
+
+ location *
+ get_location (recording::location *rloc, int column_num);
+
+ int get_line_num () const { return m_line_num; }
+
+ vec<location *> m_locations;
+
+private:
+ source_file *m_source_file;
+ int m_line_num;
+};
+
+/* A specific location on a source line. This is what we expose
+ to the client API. */
+class location : public wrapper
+{
+public:
+ location (recording::location *loc, source_line *line, int column_num);
+
+ int get_column_num () const { return m_column_num; }
+
+ recording::location *get_recording_loc () const { return m_recording_loc; }
+
+ source_location m_srcloc;
+
+private:
+ recording::location *m_recording_loc;
+ source_line *m_line;
+ int m_column_num;
+};
+
+} // namespace gcc::jit::playback
+
+extern playback::context *active_playback_ctxt;
+
+} // namespace gcc::jit
+
+} // namespace gcc
+
+#endif /* JIT_PLAYBACK_H */
+
--
1.8.5.3