aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-compile-context.h
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2022-10-21 14:29:50 +0200
committerArthur Cohen <arthur.cohen@embecosm.com>2022-12-13 14:00:07 +0100
commitcfbda2f78baac4f329efe1838401b4ae2ed5b6a5 (patch)
tree63d04c0e9b01fe40f25380329f5801707583db1b /gcc/rust/backend/rust-compile-context.h
parent019b2f15581948806ee14a6d05b09ec94f04c966 (diff)
downloadgcc-cfbda2f78baac4f329efe1838401b4ae2ed5b6a5.zip
gcc-cfbda2f78baac4f329efe1838401b4ae2ed5b6a5.tar.gz
gcc-cfbda2f78baac4f329efe1838401b4ae2ed5b6a5.tar.bz2
gccrs: Add HIR to GCC GENERIC lowering entry point
This patch contains the entry point and utilities used for the lowering of HIR nodes to `tree`s. It also contains a constant evaluator, ported over from the C++ frontend. gcc/rust/ * backend/rust-compile-context.cc: New. * backend/rust-compile-context.h: New. * backend/rust-compile.cc: New. * backend/rust-compile.h: New. * backend/rust-constexpr.cc: New. * backend/rust-constexpr.h: New. Co-authored-by: David Faust <david.faust@oracle.com> Co-authored-by: Faisal Abbas <90.abbasfaisal@gmail.com> Signed-off-by: Faisal Abbas <90.abbasfaisal@gmail.com>
Diffstat (limited to 'gcc/rust/backend/rust-compile-context.h')
-rw-r--r--gcc/rust/backend/rust-compile-context.h343
1 files changed, 343 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
new file mode 100644
index 0000000..096b65f
--- /dev/null
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -0,0 +1,343 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// 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 RUST_COMPILE_CONTEXT
+#define RUST_COMPILE_CONTEXT
+
+#include "rust-system.h"
+#include "rust-hir-map.h"
+#include "rust-name-resolver.h"
+#include "rust-hir-type-check.h"
+#include "rust-backend.h"
+#include "rust-hir-full.h"
+#include "rust-mangle.h"
+#include "rust-tree.h"
+
+namespace Rust {
+namespace Compile {
+
+struct fncontext
+{
+ tree fndecl;
+ ::Bvariable *ret_addr;
+};
+
+class Context
+{
+public:
+ Context (::Backend *backend);
+
+ void setup_builtins ();
+
+ bool lookup_compiled_types (tree t, tree *type)
+ {
+ hashval_t h = type_hasher (t);
+ auto it = compiled_type_map.find (h);
+ if (it == compiled_type_map.end ())
+ return false;
+
+ *type = it->second;
+ return true;
+ }
+
+ tree insert_compiled_type (tree type)
+ {
+ hashval_t h = type_hasher (type);
+ auto it = compiled_type_map.find (h);
+ if (it != compiled_type_map.end ())
+ return it->second;
+
+ compiled_type_map.insert ({h, type});
+ push_type (type);
+ return type;
+ }
+
+ tree insert_main_variant (tree type)
+ {
+ hashval_t h = type_hasher (type);
+ auto it = main_variants.find (h);
+ if (it != main_variants.end ())
+ return it->second;
+
+ main_variants.insert ({h, type});
+ return type;
+ }
+
+ ::Backend *get_backend () { return backend; }
+ Resolver::Resolver *get_resolver () { return resolver; }
+ Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
+ Analysis::Mappings *get_mappings () { return mappings; }
+
+ void push_block (tree scope)
+ {
+ scope_stack.push_back (scope);
+ statements.push_back ({});
+ }
+
+ tree pop_block ()
+ {
+ auto block = scope_stack.back ();
+ scope_stack.pop_back ();
+
+ auto stmts = statements.back ();
+ statements.pop_back ();
+
+ backend->block_add_statements (block, stmts);
+
+ return block;
+ }
+
+ tree peek_enclosing_scope ()
+ {
+ if (scope_stack.size () == 0)
+ return nullptr;
+
+ return scope_stack.back ();
+ }
+
+ void add_statement_to_enclosing_scope (tree stmt)
+ {
+ statements.at (statements.size () - 2).push_back (stmt);
+ }
+
+ void add_statement (tree stmt) { statements.back ().push_back (stmt); }
+
+ void insert_var_decl (HirId id, ::Bvariable *decl)
+ {
+ compiled_var_decls[id] = decl;
+ }
+
+ bool lookup_var_decl (HirId id, ::Bvariable **decl)
+ {
+ auto it = compiled_var_decls.find (id);
+ if (it == compiled_var_decls.end ())
+ return false;
+
+ *decl = it->second;
+ return true;
+ }
+
+ void insert_function_decl (const TyTy::FnType *ref, tree fn)
+ {
+ auto id = ref->get_ty_ref ();
+ auto dId = ref->get_id ();
+
+ rust_assert (compiled_fn_map.find (id) == compiled_fn_map.end ());
+ compiled_fn_map[id] = fn;
+
+ auto it = mono_fns.find (dId);
+ if (it == mono_fns.end ())
+ mono_fns[dId] = {};
+
+ mono_fns[dId].push_back ({ref, fn});
+ }
+
+ bool lookup_function_decl (HirId id, tree *fn, DefId dId = UNKNOWN_DEFID,
+ const TyTy::BaseType *ref = nullptr)
+ {
+ // for for any monomorphized fns
+ if (ref != nullptr)
+ {
+ rust_assert (dId != UNKNOWN_DEFID);
+
+ auto it = mono_fns.find (dId);
+ if (it == mono_fns.end ())
+ return false;
+
+ for (auto &e : mono_fns[dId])
+ {
+ const TyTy::BaseType *r = e.first;
+ tree f = e.second;
+ if (ref->is_equal (*r))
+ {
+ *fn = f;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ auto it = compiled_fn_map.find (id);
+ if (it == compiled_fn_map.end ())
+ return false;
+
+ *fn = it->second;
+ return true;
+ }
+
+ void insert_const_decl (HirId id, tree expr) { compiled_consts[id] = expr; }
+
+ bool lookup_const_decl (HirId id, tree *expr)
+ {
+ auto it = compiled_consts.find (id);
+ if (it == compiled_consts.end ())
+ return false;
+
+ *expr = it->second;
+ return true;
+ }
+
+ void insert_label_decl (HirId id, tree label) { compiled_labels[id] = label; }
+
+ bool lookup_label_decl (HirId id, tree *label)
+ {
+ auto it = compiled_labels.find (id);
+ if (it == compiled_labels.end ())
+ return false;
+
+ *label = it->second;
+ return true;
+ }
+
+ void insert_pattern_binding (HirId id, tree binding)
+ {
+ implicit_pattern_bindings[id] = binding;
+ }
+
+ bool lookup_pattern_binding (HirId id, tree *binding)
+ {
+ auto it = implicit_pattern_bindings.find (id);
+ if (it == implicit_pattern_bindings.end ())
+ return false;
+
+ *binding = it->second;
+ return true;
+ }
+
+ void push_fn (tree fn, ::Bvariable *ret_addr)
+ {
+ fn_stack.push_back (fncontext{fn, ret_addr});
+ }
+ void pop_fn () { fn_stack.pop_back (); }
+
+ bool in_fn () { return fn_stack.size () != 0; }
+
+ // Note: it is undefined behavior to call peek_fn () if fn_stack is empty.
+ fncontext peek_fn ()
+ {
+ rust_assert (!fn_stack.empty ());
+ return fn_stack.back ();
+ }
+
+ void push_type (tree t) { type_decls.push_back (t); }
+ void push_var (::Bvariable *v) { var_decls.push_back (v); }
+ void push_const (tree c) { const_decls.push_back (c); }
+ void push_function (tree f) { func_decls.push_back (f); }
+
+ void write_to_backend ()
+ {
+ backend->write_global_definitions (type_decls, const_decls, func_decls,
+ var_decls);
+ }
+
+ bool function_completed (tree fn)
+ {
+ for (auto it = func_decls.begin (); it != func_decls.end (); it++)
+ {
+ tree i = (*it);
+ if (i == fn)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); }
+
+ Bvariable *peek_loop_context () { return loop_value_stack.back (); }
+
+ Bvariable *pop_loop_context ()
+ {
+ auto back = loop_value_stack.back ();
+ loop_value_stack.pop_back ();
+ return back;
+ }
+
+ void push_loop_begin_label (tree label)
+ {
+ loop_begin_labels.push_back (label);
+ }
+
+ tree peek_loop_begin_label () { return loop_begin_labels.back (); }
+
+ tree pop_loop_begin_label ()
+ {
+ tree pop = loop_begin_labels.back ();
+ loop_begin_labels.pop_back ();
+ return pop;
+ }
+
+ void push_const_context (void) { const_context++; }
+ void pop_const_context (void)
+ {
+ if (const_context > 0)
+ const_context--;
+ }
+ bool const_context_p (void) { return (const_context > 0); }
+
+ std::string mangle_item (const TyTy::BaseType *ty,
+ const Resolver::CanonicalPath &path) const
+ {
+ return mangler.mangle_item (ty, path);
+ }
+
+ std::vector<tree> &get_type_decls () { return type_decls; }
+ std::vector<::Bvariable *> &get_var_decls () { return var_decls; }
+ std::vector<tree> &get_const_decls () { return const_decls; }
+ std::vector<tree> &get_func_decls () { return func_decls; }
+
+ static hashval_t type_hasher (tree type);
+
+private:
+ ::Backend *backend;
+ Resolver::Resolver *resolver;
+ Resolver::TypeCheckContext *tyctx;
+ Analysis::Mappings *mappings;
+ Mangler mangler;
+
+ // state
+ std::vector<fncontext> fn_stack;
+ std::map<HirId, ::Bvariable *> compiled_var_decls;
+ std::map<hashval_t, tree> compiled_type_map;
+ std::map<HirId, tree> compiled_fn_map;
+ std::map<HirId, tree> compiled_consts;
+ std::map<HirId, tree> compiled_labels;
+ std::vector<::std::vector<tree>> statements;
+ std::vector<tree> scope_stack;
+ std::vector<::Bvariable *> loop_value_stack;
+ std::vector<tree> loop_begin_labels;
+ std::map<DefId, std::vector<std::pair<const TyTy::BaseType *, tree>>>
+ mono_fns;
+ std::map<HirId, tree> implicit_pattern_bindings;
+ std::map<hashval_t, tree> main_variants;
+
+ // To GCC middle-end
+ std::vector<tree> type_decls;
+ std::vector<::Bvariable *> var_decls;
+ std::vector<tree> const_decls;
+ std::vector<tree> func_decls;
+
+ // Nonzero iff we are currently compiling something inside a constant context.
+ unsigned int const_context = 0;
+};
+
+} // namespace Compile
+} // namespace Rust
+
+#endif // RUST_COMPILE_CONTEXT