diff options
author | M V V S Manoj Kumar <mvvsmanojkumar@gmail.com> | 2021-11-20 08:01:36 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-20 08:01:36 +0530 |
commit | 73a0903c156f86e1e59c30c542780fe2162438d4 (patch) | |
tree | d608a5ee3f316d63f259113ae7fed2da4149a6ce | |
parent | 9c4e3db7789dc32ae08a2302b13c2772f51d5bea (diff) | |
parent | fece068309e8a3cbeb81539fba14e1c970740a94 (diff) | |
download | gcc-73a0903c156f86e1e59c30c542780fe2162438d4.zip gcc-73a0903c156f86e1e59c30c542780fe2162438d4.tar.gz gcc-73a0903c156f86e1e59c30c542780fe2162438d4.tar.bz2 |
Merge branch 'Rust-GCC:master' into master
71 files changed, 2836 insertions, 2000 deletions
diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index d37247c..e1c81ad 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -13,6 +13,7 @@ jobs: runs-on: ubuntu-latest steps: + # If updating these steps, please also correspondingly update '../../CONTRIBUTING.md', "Running `clang-format` locally". - uses: actions/checkout@v2 - name: Copy .clang-format file run: cp contrib/clang-format .clang-format diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 360c0e2..c0d75d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,9 +40,81 @@ These will be imported into a GitHub PR to follow the normal review process, and * Where possible please add test cases to `gcc/testsuite/rust/` for all PRs. Some issues may not be testable via dejagnu/automation such as debug dump changes. -* PR's cannot be merged untill clang format and the build and tests pass. - -* Please take the time to create good git commit messages see the existing format of them in the git log or refer to something like: https://chris.beams.io/posts/git-commit/ +* Follow the [GCC coding style](https://gcc.gnu.org/codingconventions.html) (see `clang-format` below). + +* PRs won't be merged until the build and tests pass. + +* Please take the time to create good git commit messages. See the existing format of them in the git log or refer to something like: https://chris.beams.io/posts/git-commit/ + +#### Running `clang-format` locally + +* on all files using python scripts +... corresponding to what the _Clang Format Lint_ (`.github/workflows/clang-format.yml`) is doing, with `clang-format-10` being available locally, and avoiding the Docker overhead. + +```shell +$ wget 'https://github.com/DoozyX/clang-format-lint-action/raw/v0.11/run-clang-format.py' +$ cp contrib/clang-format .clang-format +$ python3 run-clang-format.py --clang-format-executable clang-format-10 --recursive --extensions h,cc gcc/rust/ +``` + +* on a given patch using python scripts +See the [clang-format documentation](https://clang.llvm.org/docs/ClangFormat.html#script-for-patch-reformatting) : + + $ git diff -U0 --no-color HEAD^ | clang-format-diff.py -i -p1 + +* using `git` interface + +At least on Debian and its derivative, each `clang-format` packages also comes +with `git-clang-format` command that can be used easily. It applies on staged +changes, and any modification can be seen as unstaged changes: + +```diff +$ git diff --cached +diff --git a/gcc/rust/rust-abi.h b/gcc/rust/rust-abi.h +index bd3043295ce..9559374ce60 100644 +--- a/gcc/rust/rust-abi.h ++++ b/gcc/rust/rust-abi.h +@@ -22,10 +22,10 @@ namespace Rust { + enum ABI + { + UNKNOWN, +- RUST, ++ RUST, + INTRINSIC, + C, +- CDECL, ++ CDECL, + STDCALL, + FASTCALL, + }; + +gccrs/gcc/rust on dkm/clang_format [$!+?] +❯ git clang-format +changed files: + gcc/rust/rust-abi.h + +gccrs/gcc/rust on dkm/clang_format [$!+?] +$ git diff rust-abi.h +diff --git a/gcc/rust/rust-abi.h b/gcc/rust/rust-abi.h +index 9559374ce60..bd3043295ce 100644 +--- a/gcc/rust/rust-abi.h ++++ b/gcc/rust/rust-abi.h +@@ -22,10 +22,10 @@ namespace Rust { + enum ABI + { + UNKNOWN, +- RUST, ++ RUST, + INTRINSIC, + C, +- CDECL, ++ CDECL, + STDCALL, + FASTCALL, + }; +``` + +Also note that you can use a given version of `clang-format` by using `git clang-format-10` if you have installed that particular version. Thanks! :heart: :heart: :heart: diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 15c0a8f..f0e9bc3 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -86,10 +86,12 @@ GRS_OBJS = \ rust/rust-hir-const-fold.o \ rust/rust-hir-type-check-type.o \ rust/rust-hir-type-check-struct.o \ + rust/rust-substitution-mapper.o \ rust/rust-lint-marklive.o \ rust/rust-hir-type-check-path.o \ rust/rust-compile-intrinsic.o \ rust/rust-base62.o \ + rust/rust-compile-expr.o \ $(END) # removed object files from here diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 72f2609..05779e7 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -542,6 +542,13 @@ protected: class AttrInput { public: + enum AttrInputType + { + LITERAL, + META_ITEM, + TOKEN_TREE, + }; + virtual ~AttrInput () {} // Unique pointer custom clone function @@ -564,6 +571,8 @@ public: // Returns whether attr input has been parsed to meta item syntax. virtual bool is_meta_item () const = 0; + virtual AttrInputType get_attr_input_type () const = 0; + protected: // pure virtual clone implementation virtual AttrInput *clone_attr_input_impl () const = 0; @@ -650,6 +659,11 @@ public: bool check_cfg_predicate (const Session &session) const override; + AttrInputType get_attr_input_type () const final override + { + return AttrInput::AttrInputType::META_ITEM; + } + // Clones this object. std::unique_ptr<AttrInputMetaItemContainer> clone_attr_input_meta_item_container () const @@ -767,6 +781,11 @@ public: } bool is_meta_item () const override { return false; } + + AttrInputType get_attr_input_type () const final override + { + return AttrInput::AttrInputType::TOKEN_TREE; + } }; /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 05c78b7..3463f5a 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -102,13 +102,7 @@ protected: // Literal expression attribute body (non-macro attribute) class AttrInputLiteral : public AttrInput { - // Literal expression WITHOUT SUFFIX - // std::unique_ptr<LiteralExpr> literal_expr; - LiteralExpr - literal_expr; // as not using polymorphic behaviour, doesn't require pointer - // TODO: will require pointer if LiteralExpr is changed to have subclassing - - // TODO: should this store location data? + LiteralExpr literal_expr; public: AttrInputLiteral (LiteralExpr lit_expr) : literal_expr (std::move (lit_expr)) @@ -127,6 +121,13 @@ public: bool is_meta_item () const override { return false; } + LiteralExpr &get_literal () { return literal_expr; } + + AttrInputType get_attr_input_type () const final override + { + return AttrInput::AttrInputType::LITERAL; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index 3184e27..af0ea40 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -193,23 +193,21 @@ protected: Context *get_context () { return ctx; } - void compile_function_body (Bfunction *fndecl, + void compile_function_body (tree fndecl, std::unique_ptr<HIR::BlockExpr> &function_body, bool has_return_type); - bool compile_locals_for_block (Resolver::Rib &rib, Bfunction *fndecl, + bool compile_locals_for_block (Resolver::Rib &rib, tree fndecl, std::vector<Bvariable *> &locals); - Bexpression *coercion_site (Bexpression *compiled_ref, TyTy::BaseType *actual, - TyTy::BaseType *expected, Location locus); + tree coercion_site (tree compiled_ref, TyTy::BaseType *actual, + TyTy::BaseType *expected, Location locus); - Bexpression *coerce_to_dyn_object (Bexpression *compiled_ref, - const TyTy::BaseType *actual, - const TyTy::BaseType *expected, - const TyTy::DynamicObjectType *ty, - Location locus); + tree coerce_to_dyn_object (tree compiled_ref, const TyTy::BaseType *actual, + const TyTy::BaseType *expected, + const TyTy::DynamicObjectType *ty, Location locus); - Bexpression *compute_address_for_trait_item ( + tree compute_address_for_trait_item ( const Resolver::TraitItemReference *ref, const TyTy::TypeBoundPredicate *predicate, std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>> diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h index 6876e8a..af90671 100644 --- a/gcc/rust/backend/rust-compile-block.h +++ b/gcc/rust/backend/rust-compile-block.h @@ -30,7 +30,7 @@ class CompileBlock : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static Bblock *compile (HIR::BlockExpr *expr, Context *ctx, Bvariable *result) + static tree compile (HIR::BlockExpr *expr, Context *ctx, Bvariable *result) { CompileBlock compiler (ctx, result); expr->accept_vis (compiler); @@ -44,7 +44,7 @@ private: : HIRCompileBase (ctx), translated (nullptr), result (result) {} - Bblock *translated; + tree translated; Bvariable *result; }; @@ -53,8 +53,7 @@ class CompileConditionalBlocks : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static Bstatement *compile (HIR::IfExpr *expr, Context *ctx, - Bvariable *result) + static tree compile (HIR::IfExpr *expr, Context *ctx, Bvariable *result) { CompileConditionalBlocks resolver (ctx, result); expr->accept_vis (resolver); @@ -72,7 +71,7 @@ private: : HIRCompileBase (ctx), translated (nullptr), result (result) {} - Bstatement *translated; + tree translated; Bvariable *result; }; @@ -81,8 +80,8 @@ class CompileExprWithBlock : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static Bstatement *compile (HIR::ExprWithBlock *expr, Context *ctx, - Bvariable *result) + static tree compile (HIR::ExprWithBlock *expr, Context *ctx, + Bvariable *result) { CompileExprWithBlock resolver (ctx, result); expr->accept_vis (resolver); @@ -109,7 +108,7 @@ private: : HIRCompileBase (ctx), translated (nullptr), result (result) {} - Bstatement *translated; + tree translated; Bvariable *result; }; diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 396cb10..668e8ba 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -35,7 +35,7 @@ namespace Compile { struct fncontext { - ::Bfunction *fndecl; + tree fndecl; ::Bvariable *ret_addr; }; @@ -60,20 +60,20 @@ public: ok = tyctx->lookup_type (ref, &lookup); rust_assert (ok); - Btype *compiled = TyTyCompile::compile (backend, lookup); - compiled_type_map.insert (std::pair<HirId, Btype *> (ref, compiled)); + tree compiled = TyTyCompile::compile (backend, lookup); + compiled_type_map.insert (std::pair<HirId, tree> (ref, compiled)); builtin_range.insert (ref); } } - bool lookup_compiled_types (HirId id, ::Btype **type, + bool lookup_compiled_types (HirId id, tree *type, const TyTy::BaseType *ref = nullptr) { if (ref != nullptr) { for (auto it = mono.begin (); it != mono.end (); it++) { - std::pair<HirId, ::Btype *> &val = it->second; + std::pair<HirId, tree> &val = it->second; const TyTy::BaseType *r = it->first; if (ref->is_equal (*r)) @@ -94,14 +94,14 @@ public: return true; } - void insert_compiled_type (HirId id, ::Btype *type, + void insert_compiled_type (HirId id, tree type, const TyTy::BaseType *ref = nullptr) { rust_assert (builtin_range.find (id) == builtin_range.end ()); - compiled_type_map.insert (std::pair<HirId, Btype *> (id, type)); + compiled_type_map.insert (std::pair<HirId, tree> (id, type)); if (ref != nullptr) { - std::pair<HirId, ::Btype *> elem (id, type); + std::pair<HirId, tree> elem (id, type); mono[ref] = std::move (elem); } } @@ -112,13 +112,13 @@ public: Analysis::Mappings *get_mappings () { return mappings; } ConstFold::Context *get_const_ctx () { return const_ctx; } - void push_block (Bblock *scope) + void push_block (tree scope) { scope_stack.push_back (scope); statements.push_back ({}); } - Bblock *pop_block () + tree pop_block () { auto block = scope_stack.back (); scope_stack.pop_back (); @@ -131,7 +131,7 @@ public: return block; } - Bblock *peek_enclosing_scope () + tree peek_enclosing_scope () { if (scope_stack.size () == 0) return nullptr; @@ -139,12 +139,12 @@ public: return scope_stack.back (); } - void add_statement_to_enclosing_scope (Bstatement *stmt) + void add_statement_to_enclosing_scope (tree stmt) { statements.at (statements.size () - 2).push_back (stmt); } - void add_statement (Bstatement *stmt) { statements.back ().push_back (stmt); } + void add_statement (tree stmt) { statements.back ().push_back (stmt); } void insert_var_decl (HirId id, ::Bvariable *decl) { @@ -161,7 +161,7 @@ public: return true; } - void insert_function_decl (const TyTy::FnType *ref, ::Bfunction *fn) + void insert_function_decl (const TyTy::FnType *ref, tree fn) { auto id = ref->get_ty_ref (); auto dId = ref->get_id (); @@ -176,8 +176,7 @@ public: mono_fns[dId].push_back ({ref, fn}); } - bool lookup_function_decl (HirId id, ::Bfunction **fn, - DefId dId = UNKNOWN_DEFID, + bool lookup_function_decl (HirId id, tree *fn, DefId dId = UNKNOWN_DEFID, const TyTy::BaseType *ref = nullptr) { // for for any monomorphized fns @@ -192,7 +191,7 @@ public: for (auto &e : mono_fns[dId]) { const TyTy::BaseType *r = e.first; - ::Bfunction *f = e.second; + tree f = e.second; if (ref->is_equal (*r)) { *fn = f; @@ -210,12 +209,9 @@ public: return true; } - void insert_const_decl (HirId id, ::Bexpression *expr) - { - compiled_consts[id] = expr; - } + void insert_const_decl (HirId id, tree expr) { compiled_consts[id] = expr; } - bool lookup_const_decl (HirId id, ::Bexpression **expr) + bool lookup_const_decl (HirId id, tree *expr) { auto it = compiled_consts.find (id); if (it == compiled_consts.end ()) @@ -225,12 +221,9 @@ public: return true; } - void insert_label_decl (HirId id, ::Blabel *label) - { - compiled_labels[id] = label; - } + void insert_label_decl (HirId id, tree label) { compiled_labels[id] = label; } - bool lookup_label_decl (HirId id, ::Blabel **label) + bool lookup_label_decl (HirId id, tree *label) { auto it = compiled_labels.find (id); if (it == compiled_labels.end ()) @@ -240,17 +233,17 @@ public: return true; } - void push_fn (::Bfunction *fn, ::Bvariable *ret_addr) + void push_fn (tree fn, ::Bvariable *ret_addr) { fn_stack.push_back (fncontext{fn, ret_addr}); } void pop_fn () { fn_stack.pop_back (); } fncontext peek_fn () { return fn_stack.back (); } - void push_type (::Btype *t) { type_decls.push_back (t); } + void push_type (tree t) { type_decls.push_back (t); } void push_var (::Bvariable *v) { var_decls.push_back (v); } - void push_const (::Bexpression *c) { const_decls.push_back (c); } - void push_function (::Bfunction *f) { func_decls.push_back (f); } + void push_const (tree c) { const_decls.push_back (c); } + void push_function (tree f) { func_decls.push_back (f); } void write_to_backend () { @@ -258,11 +251,11 @@ public: var_decls); } - bool function_completed (Bfunction *fn) + bool function_completed (tree fn) { for (auto it = func_decls.begin (); it != func_decls.end (); it++) { - Bfunction *i = (*it); + tree i = (*it); if (i == fn) { return true; @@ -282,16 +275,16 @@ public: return back; } - void push_loop_begin_label (Blabel *label) + void push_loop_begin_label (tree label) { loop_begin_labels.push_back (label); } - Blabel *peek_loop_begin_label () { return loop_begin_labels.back (); } + tree peek_loop_begin_label () { return loop_begin_labels.back (); } - Blabel *pop_loop_begin_label () + tree pop_loop_begin_label () { - Blabel *pop = loop_begin_labels.back (); + tree pop = loop_begin_labels.back (); loop_begin_labels.pop_back (); return pop; } @@ -322,30 +315,30 @@ private: // state std::vector<fncontext> fn_stack; std::map<HirId, ::Bvariable *> compiled_var_decls; - std::map<HirId, ::Btype *> compiled_type_map; - std::map<HirId, ::Bfunction *> compiled_fn_map; - std::map<HirId, ::Bexpression *> compiled_consts; - std::map<HirId, ::Blabel *> compiled_labels; - std::vector<::std::vector<Bstatement *>> statements; - std::vector<::Bblock *> scope_stack; + std::map<HirId, 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<::Blabel *> loop_begin_labels; - std::map<const TyTy::BaseType *, std::pair<HirId, ::Btype *>> mono; - std::map<DefId, std::vector<std::pair<const TyTy::BaseType *, ::Bfunction *>>> + std::vector<tree> loop_begin_labels; + std::map<const TyTy::BaseType *, std::pair<HirId, tree>> mono; + std::map<DefId, std::vector<std::pair<const TyTy::BaseType *, tree>>> mono_fns; // To GCC middle-end - std::vector<::Btype *> type_decls; + std::vector<tree> type_decls; std::vector<::Bvariable *> var_decls; - std::vector<::Bexpression *> const_decls; - std::vector<::Bfunction *> func_decls; + std::vector<tree> const_decls; + std::vector<tree> func_decls; }; class TyTyResolveCompile : public TyTy::TyConstVisitor { public: - static ::Btype *compile (Context *ctx, const TyTy::BaseType *ty, - bool trait_object_mode = false) + static tree compile (Context *ctx, const TyTy::BaseType *ty, + bool trait_object_mode = false) { TyTyResolveCompile compiler (ctx, trait_object_mode); ty->accept_vis (compiler); @@ -375,16 +368,16 @@ public: void visit (const TyTy::FnType &type) override { - Backend::Btyped_identifier receiver; - std::vector<Backend::Btyped_identifier> parameters; - std::vector<Backend::Btyped_identifier> results; + Backend::typed_identifier receiver; + std::vector<Backend::typed_identifier> parameters; + std::vector<Backend::typed_identifier> results; if (!type.get_return_type ()->is_unit ()) { auto hir_type = type.get_return_type (); auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode); - results.push_back (Backend::Btyped_identifier ( + results.push_back (Backend::typed_identifier ( "_", ret, ctx->get_mappings ()->lookup_location (hir_type->get_ref ()))); } @@ -395,7 +388,7 @@ public: auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode); - auto compiled_param = Backend::Btyped_identifier ( + auto compiled_param = Backend::typed_identifier ( param_pair.first->as_string (), compiled_param_type, ctx->get_mappings ()->lookup_location (param_tyty->get_ref ())); @@ -414,12 +407,12 @@ public: void visit (const TyTy::FnPtr &type) override { - Btype *result_type + tree result_type = TyTyResolveCompile::compile (ctx, type.get_return_type ()); - std::vector<Btype *> parameters; + std::vector<tree> parameters; type.iterate_params ([&] (TyTy::BaseType *p) mutable -> bool { - Btype *pty = TyTyResolveCompile::compile (ctx, p); + tree pty = TyTyResolveCompile::compile (ctx, p); parameters.push_back (pty); return true; }); @@ -439,25 +432,25 @@ public: rust_assert (type.number_of_variants () == 1); TyTy::VariantDef &variant = *type.get_variants ().at (0); - std::vector<Backend::Btyped_identifier> fields; + std::vector<Backend::typed_identifier> fields; for (size_t i = 0; i < variant.num_fields (); i++) { const TyTy::StructFieldType *field = variant.get_field_at_index (i); - Btype *compiled_field_ty + tree compiled_field_ty = TyTyResolveCompile::compile (ctx, field->get_field_type ()); - Backend::Btyped_identifier f (field->get_name (), compiled_field_ty, - ctx->get_mappings ()->lookup_location ( - type.get_ty_ref ())); + Backend::typed_identifier f (field->get_name (), compiled_field_ty, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); fields.push_back (std::move (f)); } - Btype *type_record; + tree type_record; if (type.is_union ()) type_record = ctx->get_backend ()->union_type (fields); else type_record = ctx->get_backend ()->struct_type (fields); - Btype *named_struct + tree named_struct = ctx->get_backend ()->named_type (type.get_name (), type_record, ctx->get_mappings ()->lookup_location ( type.get_ty_ref ())); @@ -482,11 +475,11 @@ public: return; // create implicit struct - std::vector<Backend::Btyped_identifier> fields; + std::vector<Backend::typed_identifier> fields; for (size_t i = 0; i < type.num_fields (); i++) { TyTy::BaseType *field = type.get_field (i); - Btype *compiled_field_ty = TyTyResolveCompile::compile (ctx, field); + tree compiled_field_ty = TyTyResolveCompile::compile (ctx, field); // rustc uses the convention __N, where N is an integer, to // name the fields of a tuple. We follow this as well, @@ -494,15 +487,15 @@ public: // this, rather than simply emitting the integer, is that this // approach makes it simpler to use a C-only debugger, or // GDB's C mode, when debugging Rust. - Backend::Btyped_identifier f ("__" + std::to_string (i), - compiled_field_ty, - ctx->get_mappings ()->lookup_location ( - type.get_ty_ref ())); + Backend::typed_identifier f ("__" + std::to_string (i), + compiled_field_ty, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); fields.push_back (std::move (f)); } - Btype *struct_type_record = ctx->get_backend ()->struct_type (fields); - Btype *named_struct + tree struct_type_record = ctx->get_backend ()->struct_type (fields); + tree named_struct = ctx->get_backend ()->named_type (type.as_string (), struct_type_record, ctx->get_mappings ()->lookup_location ( type.get_ty_ref ())); @@ -514,7 +507,7 @@ public: void visit (const TyTy::ArrayType &type) override { - Btype *element_type + tree element_type = TyTyResolveCompile::compile (ctx, type.get_element_type ()); translated = ctx->get_backend ()->array_type (element_type, type.get_capacity ()); @@ -522,7 +515,7 @@ public: void visit (const TyTy::BoolType &type) override { - ::Btype *compiled_type = nullptr; + tree compiled_type = nullptr; bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; @@ -530,7 +523,7 @@ public: void visit (const TyTy::IntType &type) override { - ::Btype *compiled_type = nullptr; + tree compiled_type = nullptr; bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; @@ -538,7 +531,7 @@ public: void visit (const TyTy::UintType &type) override { - ::Btype *compiled_type = nullptr; + tree compiled_type = nullptr; bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; @@ -546,7 +539,7 @@ public: void visit (const TyTy::FloatType &type) override { - ::Btype *compiled_type = nullptr; + tree compiled_type = nullptr; bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; @@ -554,7 +547,7 @@ public: void visit (const TyTy::USizeType &type) override { - ::Btype *compiled_type = nullptr; + tree compiled_type = nullptr; bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; @@ -562,7 +555,7 @@ public: void visit (const TyTy::ISizeType &type) override { - ::Btype *compiled_type = nullptr; + tree compiled_type = nullptr; bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; @@ -570,7 +563,7 @@ public: void visit (const TyTy::CharType &type) override { - ::Btype *compiled_type = nullptr; + tree compiled_type = nullptr; bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; @@ -578,7 +571,7 @@ public: void visit (const TyTy::ReferenceType &type) override { - Btype *base_compiled_type + tree base_compiled_type = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode); if (type.is_mutable ()) { @@ -593,7 +586,7 @@ public: void visit (const TyTy::PointerType &type) override { - Btype *base_compiled_type + tree base_compiled_type = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode); if (type.is_mutable ()) { @@ -608,7 +601,7 @@ public: void visit (const TyTy::StrType &type) override { - ::Btype *compiled_type = nullptr; + tree compiled_type = nullptr; bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; @@ -633,32 +626,32 @@ public: // create implicit struct auto items = type.get_object_items (); - std::vector<Backend::Btyped_identifier> fields; + std::vector<Backend::typed_identifier> fields; - Btype *uint = ctx->get_backend ()->integer_type ( + tree uint = ctx->get_backend ()->integer_type ( true, ctx->get_backend ()->get_pointer_size ()); - Btype *uintptr_ty = ctx->get_backend ()->pointer_type (uint); + tree uintptr_ty = ctx->get_backend ()->pointer_type (uint); - Backend::Btyped_identifier f ("__receiver_trait_obj_ptr", uintptr_ty, - ctx->get_mappings ()->lookup_location ( - type.get_ty_ref ())); + Backend::typed_identifier f ("__receiver_trait_obj_ptr", uintptr_ty, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); fields.push_back (std::move (f)); for (size_t i = 0; i < items.size (); i++) { // mrustc seems to make a vtable consisting of uintptr's - Btype *uint = ctx->get_backend ()->integer_type ( + tree uint = ctx->get_backend ()->integer_type ( true, ctx->get_backend ()->get_pointer_size ()); - Btype *uintptr_ty = ctx->get_backend ()->pointer_type (uint); + tree uintptr_ty = ctx->get_backend ()->pointer_type (uint); - Backend::Btyped_identifier f ("__" + std::to_string (i), uintptr_ty, - ctx->get_mappings ()->lookup_location ( - type.get_ty_ref ())); + Backend::typed_identifier f ("__" + std::to_string (i), uintptr_ty, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); fields.push_back (std::move (f)); } - Btype *type_record = ctx->get_backend ()->struct_type (fields); - Btype *named_struct + tree type_record = ctx->get_backend ()->struct_type (fields); + tree named_struct = ctx->get_backend ()->named_type (type.get_name (), type_record, ctx->get_mappings ()->lookup_location ( type.get_ty_ref ())); @@ -679,7 +672,7 @@ private: Context *ctx; bool trait_object_mode; - ::Btype *translated; + tree translated; size_t recursion_count; static const size_t kDefaultRecusionLimit = 5; diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc new file mode 100644 index 0000000..fb01d8d --- /dev/null +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -0,0 +1,393 @@ +// Copyright (C) 2020-2021 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/>. + +#include "rust-compile.h" +#include "rust-compile-item.h" +#include "rust-compile-expr.h" +#include "rust-compile-struct-field-expr.h" +#include "rust-hir-trait-resolve.h" +#include "rust-hir-path-probe.h" +#include "rust-hir-type-bounds.h" +#include "rust-hir-dot-operator.h" + +namespace Rust { +namespace Compile { + +void +CompileExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) +{ + auto op = expr.get_expr_type (); + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); + + // this might be an operator overload situation lets check + TyTy::FnType *fntype; + bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload ( + expr.get_mappings ().get_hirid (), &fntype); + if (is_op_overload) + { + auto lang_item_type + = Analysis::RustLangItem::OperatorToLangItem (expr.get_expr_type ()); + translated = resolve_operator_overload (lang_item_type, expr, lhs, rhs, + expr.get_lhs (), expr.get_rhs ()); + return; + } + + translated + = ctx->get_backend ()->arithmetic_or_logical_expression (op, lhs, rhs, + expr.get_locus ()); +} + +void +CompileExpr::visit (HIR::CompoundAssignmentExpr &expr) +{ + fncontext fn = ctx->peek_fn (); + + auto op = expr.get_expr_type (); + auto lhs = CompileExpr::Compile (expr.get_left_expr ().get (), ctx); + auto rhs = CompileExpr::Compile (expr.get_right_expr ().get (), ctx); + + // this might be an operator overload situation lets check + TyTy::FnType *fntype; + bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload ( + expr.get_mappings ().get_hirid (), &fntype); + if (is_op_overload) + { + auto lang_item_type + = Analysis::RustLangItem::CompoundAssignmentOperatorToLangItem ( + expr.get_expr_type ()); + auto compound_assignment + = resolve_operator_overload (lang_item_type, expr, lhs, rhs, + expr.get_left_expr ().get (), + expr.get_right_expr ().get ()); + auto assignment + = ctx->get_backend ()->expression_statement (fn.fndecl, + compound_assignment); + ctx->add_statement (assignment); + + return; + } + + auto operator_expr + = ctx->get_backend ()->arithmetic_or_logical_expression (op, lhs, rhs, + expr.get_locus ()); + tree assignment + = ctx->get_backend ()->assignment_statement (fn.fndecl, lhs, operator_expr, + expr.get_locus ()); + ctx->add_statement (assignment); +} + +void +CompileExpr::visit (HIR::NegationExpr &expr) +{ + auto op = expr.get_expr_type (); + auto negated_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); + auto location = expr.get_locus (); + + // this might be an operator overload situation lets check + TyTy::FnType *fntype; + bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload ( + expr.get_mappings ().get_hirid (), &fntype); + if (is_op_overload) + { + auto lang_item_type + = Analysis::RustLangItem::NegationOperatorToLangItem (op); + translated + = resolve_operator_overload (lang_item_type, expr, negated_expr, + nullptr, expr.get_expr ().get (), nullptr); + return; + } + + translated + = ctx->get_backend ()->negation_expression (op, negated_expr, location); +} + +tree +CompileExpr::compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn, + TyTy::BaseType *receiver, + TyTy::FnType *fntype, tree receiver_ref, + std::vector<HIR::Expr *> &arguments, + Location expr_locus) +{ + size_t offs = 0; + const Resolver::TraitItemReference *ref = nullptr; + for (auto &bound : dyn->get_object_items ()) + { + const Resolver::TraitItemReference *item = bound.first; + auto t = item->get_tyty (); + rust_assert (t->get_kind () == TyTy::TypeKind::FNDEF); + auto ft = static_cast<TyTy::FnType *> (t); + + if (ft->get_id () == fntype->get_id ()) + { + ref = item; + break; + } + offs++; + } + + if (ref == nullptr) + return ctx->get_backend ()->error_expression (); + + // get any indirection sorted out + if (receiver->get_kind () == TyTy::TypeKind::REF) + { + TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (receiver); + auto indirect_ty = r->get_base (); + tree indrect_compiled_tyty + = TyTyResolveCompile::compile (ctx, indirect_ty); + + tree indirect + = ctx->get_backend ()->indirect_expression (indrect_compiled_tyty, + receiver_ref, true, + expr_locus); + receiver_ref = indirect; + } + + // access the offs + 1 for the fnptr and offs=0 for the reciever obj + tree self_argument + = ctx->get_backend ()->struct_field_expression (receiver_ref, 0, + expr_locus); + + // access the vtable for the fn + tree fn_vtable_access + = ctx->get_backend ()->struct_field_expression (receiver_ref, offs + 1, + expr_locus); + + // cast it to the correct fntype + tree expected_fntype = TyTyResolveCompile::compile (ctx, fntype, true); + tree fn_convert_expr + = ctx->get_backend ()->convert_expression (expected_fntype, + fn_vtable_access, expr_locus); + + fncontext fnctx = ctx->peek_fn (); + tree enclosing_scope = ctx->peek_enclosing_scope (); + bool is_address_taken = false; + tree ret_var_stmt = NULL_TREE; + Bvariable *fn_convert_expr_tmp + = ctx->get_backend ()->temporary_variable (fnctx.fndecl, enclosing_scope, + expected_fntype, fn_convert_expr, + is_address_taken, expr_locus, + &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + + std::vector<tree> args; + args.push_back (self_argument); + for (auto &argument : arguments) + { + tree compiled_expr = CompileExpr::Compile (argument, ctx); + args.push_back (compiled_expr); + } + + tree fn_expr + = ctx->get_backend ()->var_expression (fn_convert_expr_tmp, expr_locus); + + return ctx->get_backend ()->call_expression (fnctx.fndecl, fn_expr, args, + nullptr, expr_locus); +} + +tree +CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref, + TyTy::BaseType *receiver, + HIR::PathIdentSegment &segment, + Analysis::NodeMapping expr_mappings, + Location expr_locus) +{ + // lookup compiled functions since it may have already been compiled + tree fn = NULL_TREE; + if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn)) + { + return ctx->get_backend ()->function_code_expression (fn, expr_locus); + } + + // Now we can try and resolve the address since this might be a forward + // declared function, generic function which has not be compiled yet or + // its an not yet trait bound function + HIR::ImplItem *resolved_item + = ctx->get_mappings ()->lookup_hir_implitem (expr_mappings.get_crate_num (), + ref, nullptr); + if (resolved_item != nullptr) + { + if (!fntype->has_subsititions_defined ()) + return CompileInherentImplItem::Compile (receiver, resolved_item, ctx, + true); + + return CompileInherentImplItem::Compile (receiver, resolved_item, ctx, + true, fntype); + } + + // it might be resolved to a trait item + HIR::TraitItem *trait_item = ctx->get_mappings ()->lookup_hir_trait_item ( + expr_mappings.get_crate_num (), ref); + HIR::Trait *trait = ctx->get_mappings ()->lookup_trait_item_mapping ( + trait_item->get_mappings ().get_hirid ()); + + Resolver::TraitReference *trait_ref + = &Resolver::TraitReference::error_node (); + bool ok = ctx->get_tyctx ()->lookup_trait_reference ( + trait->get_mappings ().get_defid (), &trait_ref); + rust_assert (ok); + + // the type resolver can only resolve type bounds to their trait + // item so its up to us to figure out if this path should resolve + // to an trait-impl-block-item or if it can be defaulted to the + // trait-impl-item's definition + + auto root = receiver->get_root (); + std::vector<Resolver::PathProbeCandidate> candidates + = Resolver::PathProbeType::Probe (root, segment, true, false, true); + + if (candidates.size () == 0) + { + // this means we are defaulting back to the trait_item if + // possible + Resolver::TraitItemReference *trait_item_ref = nullptr; + bool ok = trait_ref->lookup_hir_trait_item (*trait_item, &trait_item_ref); + rust_assert (ok); // found + rust_assert (trait_item_ref->is_optional ()); // has definition + + // FIXME Optional means it has a definition and an associated + // block which can be a default implementation, if it does not + // contain an implementation we should actually return + // error_mark_node + + return CompileTraitItem::Compile (receiver, + trait_item_ref->get_hir_trait_item (), + ctx, fntype, true, expr_locus); + } + else + { + std::vector<Resolver::Adjustment> adjustments; + Resolver::PathProbeCandidate *candidate + = Resolver::MethodResolution::Select (candidates, root, adjustments); + + // FIXME this will be a case to return error_mark_node, there is + // an error scenario where a Trait Foo has a method Bar, but this + // receiver does not implement this trait or has an incompatible + // implementation and we should just return error_mark_node + rust_assert (candidate != nullptr); + rust_assert (candidate->is_impl_candidate ()); + + HIR::ImplItem *impl_item = candidate->item.impl.impl_item; + if (!fntype->has_subsititions_defined ()) + return CompileInherentImplItem::Compile (receiver, impl_item, ctx, + true); + + return CompileInherentImplItem::Compile (receiver, impl_item, ctx, true, + fntype); + } +} + +tree +CompileExpr::resolve_operator_overload ( + Analysis::RustLangItem::ItemType lang_item_type, HIR::OperatorExpr &expr, + tree lhs, tree rhs, HIR::Expr *lhs_expr, HIR::Expr *rhs_expr) +{ + TyTy::FnType *fntype; + bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload ( + expr.get_mappings ().get_hirid (), &fntype); + rust_assert (is_op_overload); + + // lookup the resolved name + NodeId resolved_node_id = UNKNOWN_NODEID; + bool ok = ctx->get_resolver ()->lookup_resolved_name ( + expr.get_mappings ().get_nodeid (), &resolved_node_id); + rust_assert (ok); + + // reverse lookup + HirId ref; + ok = ctx->get_mappings ()->lookup_node_to_hir ( + expr.get_mappings ().get_crate_num (), resolved_node_id, &ref); + rust_assert (ok); + + TyTy::BaseType *receiver = nullptr; + ok = ctx->get_tyctx ()->lookup_receiver (expr.get_mappings ().get_hirid (), + &receiver); + rust_assert (ok); + + bool is_dyn_dispatch + = receiver->get_root ()->get_kind () == TyTy::TypeKind::DYNAMIC; + bool is_generic_receiver = receiver->get_kind () == TyTy::TypeKind::PARAM; + if (is_generic_receiver) + { + TyTy::ParamType *p = static_cast<TyTy::ParamType *> (receiver); + receiver = p->resolve (); + } + + if (is_dyn_dispatch) + { + const TyTy::DynamicObjectType *dyn + = static_cast<const TyTy::DynamicObjectType *> (receiver->get_root ()); + + std::vector<HIR::Expr *> arguments; + if (rhs_expr != nullptr) // can be null for negation_expr (unary ones) + arguments.push_back (rhs_expr); + + return compile_dyn_dispatch_call (dyn, receiver, fntype, lhs, arguments, + expr.get_locus ()); + } + + // lookup compiled functions since it may have already been compiled + HIR::PathIdentSegment segment_name ( + Analysis::RustLangItem::ToString (lang_item_type)); + tree fn_expr + = resolve_method_address (fntype, ref, receiver, segment_name, + expr.get_mappings (), expr.get_locus ()); + + // lookup the autoderef mappings + std::vector<Resolver::Adjustment> *adjustments = nullptr; + ok = ctx->get_tyctx ()->lookup_autoderef_mappings ( + expr.get_mappings ().get_hirid (), &adjustments); + rust_assert (ok); + + // FIXME refactor this out + tree self = lhs; + for (auto &adjustment : *adjustments) + { + switch (adjustment.get_type ()) + { + case Resolver::Adjustment::AdjustmentType::IMM_REF: + case Resolver::Adjustment::AdjustmentType::MUT_REF: + self + = ctx->get_backend ()->address_expression (self, + lhs_expr->get_locus ()); + break; + + case Resolver::Adjustment::AdjustmentType::DEREF_REF: + tree expected_type + = TyTyResolveCompile::compile (ctx, adjustment.get_expected ()); + self + = ctx->get_backend ()->indirect_expression (expected_type, self, + true, /* known_valid*/ + lhs_expr->get_locus ()); + break; + } + } + + std::vector<tree> args; + args.push_back (self); // adjusted self + if (rhs != nullptr) // can be null for negation_expr (unary ones) + args.push_back (rhs); + + auto fncontext = ctx->peek_fn (); + return ctx->get_backend ()->call_expression (fncontext.fndecl, fn_expr, args, + nullptr, expr.get_locus ()); +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index f43db50..2bf969b 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -33,7 +33,7 @@ class CompileExpr : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static Bexpression *Compile (HIR::Expr *expr, Context *ctx) + static tree Compile (HIR::Expr *expr, Context *ctx) { CompileExpr compiler (ctx); expr->accept_vis (compiler); @@ -45,7 +45,7 @@ public: HIR::Expr *tuple_expr = expr.get_tuple_expr ().get (); TupleIndex index = expr.get_tuple_index (); - Bexpression *receiver_ref = CompileExpr::Compile (tuple_expr, ctx); + tree receiver_ref = CompileExpr::Compile (tuple_expr, ctx); TyTy::BaseType *tuple_expr_ty = nullptr; bool ok = ctx->get_tyctx ()->lookup_type ( @@ -58,9 +58,9 @@ public: TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (tuple_expr_ty); TyTy::BaseType *tuple_type = r->get_base (); - Btype *tuple_tyty = TyTyResolveCompile::compile (ctx, tuple_type); + tree tuple_tyty = TyTyResolveCompile::compile (ctx, tuple_type); - Bexpression *indirect + tree indirect = ctx->get_backend ()->indirect_expression (tuple_tyty, receiver_ref, true, expr.get_locus ()); receiver_ref = indirect; @@ -88,11 +88,11 @@ public: return; } - Btype *tuple_type = TyTyResolveCompile::compile (ctx, tyty); + tree tuple_type = TyTyResolveCompile::compile (ctx, tyty); rust_assert (tuple_type != nullptr); // this assumes all fields are in order from type resolution - std::vector<Bexpression *> vals; + std::vector<tree> vals; for (auto &elem : expr.get_tuple_elems ()) { auto e = CompileExpr::Compile (elem.get (), ctx); @@ -108,10 +108,10 @@ public: { auto fncontext = ctx->peek_fn (); - std::vector<Bexpression *> retstmts; + std::vector<tree> retstmts; if (expr.has_return_expr ()) { - Bexpression *compiled_expr + tree compiled_expr = CompileExpr::Compile (expr.return_expr.get (), ctx); rust_assert (compiled_expr != nullptr); @@ -204,7 +204,7 @@ public: gcc_unreachable (); } - Bfunction *fn = nullptr; + tree fn = NULL_TREE; Bvariable *var = nullptr; if (ctx->lookup_const_decl (ref, &translated)) { @@ -259,7 +259,7 @@ public: return; } - Btype *type = TyTyResolveCompile::compile (ctx, tyty); + tree type = TyTyResolveCompile::compile (ctx, tyty); translated = ctx->get_backend ()->integer_constant_expression (type, ival); } @@ -285,7 +285,7 @@ public: return; } - Btype *type = TyTyResolveCompile::compile (ctx, tyty); + tree type = TyTyResolveCompile::compile (ctx, tyty); translated = ctx->get_backend ()->float_constant_expression (type, fval); } @@ -330,21 +330,19 @@ public: auto array_tyty = static_cast<TyTy::ArrayType *> (base_tyty); std::string value_str = expr.get_literal ()->as_string (); - std::vector<Bexpression *> vals; + std::vector<tree> vals; std::vector<unsigned long> indexes; for (size_t i = 0; i < value_str.size (); i++) { char b = value_str.at (i); - Bexpression *bb - = ctx->get_backend ()->char_constant_expression (b); + tree bb = ctx->get_backend ()->char_constant_expression (b); vals.push_back (bb); indexes.push_back (i); } - Btype *array_type = TyTyResolveCompile::compile (ctx, array_tyty); - Bexpression *constructed - = ctx->get_backend ()->array_constructor_expression ( - array_type, indexes, vals, expr.get_locus ()); + tree array_type = TyTyResolveCompile::compile (ctx, array_tyty); + tree constructed = ctx->get_backend ()->array_constructor_expression ( + array_type, indexes, vals, expr.get_locus ()); translated = ctx->get_backend ()->address_expression (constructed, @@ -381,17 +379,19 @@ public: rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ()); - Bstatement *assignment + tree assignment = ctx->get_backend ()->assignment_statement (fn.fndecl, lvalue, rvalue, expr.get_locus ()); ctx->add_statement (assignment); } + void visit (HIR::CompoundAssignmentExpr &expr) override; + void visit (HIR::ArrayIndexExpr &expr) override { - Bexpression *array = CompileExpr::Compile (expr.get_array_expr (), ctx); - Bexpression *index = CompileExpr::Compile (expr.get_index_expr (), ctx); + tree array = CompileExpr::Compile (expr.get_array_expr (), ctx); + tree index = CompileExpr::Compile (expr.get_index_expr (), ctx); translated = ctx->get_backend ()->array_index_expression (array, index, expr.get_locus ()); @@ -412,7 +412,7 @@ public: TyTy::ArrayType *array_tyty = static_cast<TyTy::ArrayType *> (tyty); capacity_expr = array_tyty->get_capacity (); - Btype *array_type = TyTyResolveCompile::compile (ctx, array_tyty); + tree array_type = TyTyResolveCompile::compile (ctx, array_tyty); rust_assert (array_type != nullptr); expr.get_internal_elements ()->accept_vis (*this); @@ -430,14 +430,14 @@ public: { for (auto &elem : elems.get_values ()) { - Bexpression *translated_expr = CompileExpr::Compile (elem.get (), ctx); + tree translated_expr = CompileExpr::Compile (elem.get (), ctx); constructor.push_back (translated_expr); } } void visit (HIR::ArrayElemsCopied &elems) override { - Bexpression *translated_expr + tree translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (), ctx); size_t capacity; @@ -448,17 +448,7 @@ public: constructor.push_back (translated_expr); } - void visit (HIR::ArithmeticOrLogicalExpr &expr) override - { - auto op = expr.get_expr_type (); - auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); - auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); - auto location = expr.get_locus (); - - translated - = ctx->get_backend ()->arithmetic_or_logical_expression (op, lhs, rhs, - location); - } + void visit (HIR::ArithmeticOrLogicalExpr &expr) override; void visit (HIR::ComparisonExpr &expr) override { @@ -482,15 +472,7 @@ public: = ctx->get_backend ()->lazy_boolean_expression (op, lhs, rhs, location); } - void visit (HIR::NegationExpr &expr) override - { - auto op = expr.get_expr_type (); - auto negated_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); - auto location = expr.get_locus (); - - translated - = ctx->get_backend ()->negation_expression (op, negated_expr, location); - } + void visit (HIR::NegationExpr &expr) override; void visit (HIR::TypeCastExpr &expr) override { @@ -532,11 +514,11 @@ public: if (needs_temp) { fncontext fnctx = ctx->peek_fn (); - Bblock *enclosing_scope = ctx->peek_enclosing_scope (); - Btype *block_type = TyTyResolveCompile::compile (ctx, if_type); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree block_type = TyTyResolveCompile::compile (ctx, if_type); bool is_address_taken = false; - Bstatement *ret_var_stmt = nullptr; + tree ret_var_stmt = nullptr; tmp = ctx->get_backend ()->temporary_variable ( fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, expr.get_locus (), &ret_var_stmt); @@ -569,11 +551,11 @@ public: if (needs_temp) { fncontext fnctx = ctx->peek_fn (); - Bblock *enclosing_scope = ctx->peek_enclosing_scope (); - Btype *block_type = TyTyResolveCompile::compile (ctx, if_type); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree block_type = TyTyResolveCompile::compile (ctx, if_type); bool is_address_taken = false; - Bstatement *ret_var_stmt = nullptr; + tree ret_var_stmt = nullptr; tmp = ctx->get_backend ()->temporary_variable ( fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, expr.get_locus (), &ret_var_stmt); @@ -605,11 +587,11 @@ public: if (needs_temp) { fncontext fnctx = ctx->peek_fn (); - Bblock *enclosing_scope = ctx->peek_enclosing_scope (); - Btype *block_type = TyTyResolveCompile::compile (ctx, block_tyty); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree block_type = TyTyResolveCompile::compile (ctx, block_tyty); bool is_address_taken = false; - Bstatement *ret_var_stmt = nullptr; + tree ret_var_stmt = nullptr; tmp = ctx->get_backend ()->temporary_variable ( fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, expr.get_locus (), &ret_var_stmt); @@ -656,15 +638,15 @@ public: return; } - Btype *type = TyTyResolveCompile::compile (ctx, tyty); + tree type = TyTyResolveCompile::compile (ctx, tyty); rust_assert (type != nullptr); // this assumes all fields are in order from type resolution and if a base // struct was specified those fields are filed via accesors - std::vector<Bexpression *> vals; + std::vector<tree> vals; for (auto &field : struct_expr.get_fields ()) { - Bexpression *expr = CompileStructExprField::Compile (field.get (), ctx); + tree expr = CompileStructExprField::Compile (field.get (), ctx); vals.push_back (expr); } @@ -681,7 +663,7 @@ public: void visit (HIR::FieldAccessExpr &expr) override { - Bexpression *receiver_ref + tree receiver_ref = CompileExpr::Compile (expr.get_receiver_expr ().get (), ctx); // resolve the receiver back to ADT type @@ -721,8 +703,8 @@ public: &field_index); rust_assert (ok); - Btype *adt_tyty = TyTyResolveCompile::compile (ctx, adt); - Bexpression *indirect + tree adt_tyty = TyTyResolveCompile::compile (ctx, adt); + tree indirect = ctx->get_backend ()->indirect_expression (adt_tyty, receiver_ref, true, expr.get_locus ()); receiver_ref = indirect; @@ -758,11 +740,11 @@ public: bool needs_temp = !block_tyty->is_unit (); if (needs_temp) { - Bblock *enclosing_scope = ctx->peek_enclosing_scope (); - Btype *block_type = TyTyResolveCompile::compile (ctx, block_tyty); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree block_type = TyTyResolveCompile::compile (ctx, block_tyty); bool is_address_taken = false; - Bstatement *ret_var_stmt = nullptr; + tree ret_var_stmt = NULL_TREE; tmp = ctx->get_backend ()->temporary_variable ( fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, expr.get_locus (), &ret_var_stmt); @@ -773,29 +755,29 @@ public: if (expr.has_loop_label ()) { HIR::LoopLabel &loop_label = expr.get_loop_label (); - Blabel *label + tree label = ctx->get_backend ()->label (fnctx.fndecl, loop_label.get_lifetime ().get_name (), loop_label.get_locus ()); - Bstatement *label_decl + tree label_decl = ctx->get_backend ()->label_definition_statement (label); ctx->add_statement (label_decl); ctx->insert_label_decl ( loop_label.get_lifetime ().get_mappings ().get_hirid (), label); } - Blabel *loop_begin_label + tree loop_begin_label = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); - Bstatement *loop_begin_label_decl + tree loop_begin_label_decl = ctx->get_backend ()->label_definition_statement (loop_begin_label); ctx->add_statement (loop_begin_label_decl); ctx->push_loop_begin_label (loop_begin_label); - Bblock *code_block + tree code_block = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); - Bexpression *loop_expr + tree loop_expr = ctx->get_backend ()->loop_expression (code_block, expr.get_locus ()); - Bstatement *loop_stmt + tree loop_stmt = ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr); ctx->add_statement (loop_stmt); @@ -814,11 +796,11 @@ public: if (expr.has_loop_label ()) { HIR::LoopLabel &loop_label = expr.get_loop_label (); - Blabel *label + tree label = ctx->get_backend ()->label (fnctx.fndecl, loop_label.get_lifetime ().get_name (), loop_label.get_locus ()); - Bstatement *label_decl + tree label_decl = ctx->get_backend ()->label_definition_statement (label); ctx->add_statement (label_decl); ctx->insert_label_decl ( @@ -829,39 +811,38 @@ public: Location start_location = expr.get_loop_block ()->get_locus (); Location end_location = expr.get_loop_block ()->get_locus (); // FIXME - Bblock *enclosing_scope = ctx->peek_enclosing_scope (); - Bblock *loop_block + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree loop_block = ctx->get_backend ()->block (fnctx.fndecl, enclosing_scope, locals, start_location, end_location); ctx->push_block (loop_block); - Blabel *loop_begin_label + tree loop_begin_label = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); - Bstatement *loop_begin_label_decl + tree loop_begin_label_decl = ctx->get_backend ()->label_definition_statement (loop_begin_label); ctx->add_statement (loop_begin_label_decl); ctx->push_loop_begin_label (loop_begin_label); - Bexpression *condition + tree condition = CompileExpr::Compile (expr.get_predicate_expr ().get (), ctx); - Bexpression *exit_expr + tree exit_expr = ctx->get_backend ()->exit_expression (condition, expr.get_locus ()); - Bstatement *break_stmt + tree break_stmt = ctx->get_backend ()->expression_statement (fnctx.fndecl, exit_expr); ctx->add_statement (break_stmt); - Bblock *code_block + tree code_block = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); - Bstatement *code_block_stmt - = ctx->get_backend ()->block_statement (code_block); + tree code_block_stmt = ctx->get_backend ()->block_statement (code_block); ctx->add_statement (code_block_stmt); ctx->pop_loop_begin_label (); ctx->pop_block (); - Bexpression *loop_expr + tree loop_expr = ctx->get_backend ()->loop_expression (loop_block, expr.get_locus ()); - Bstatement *loop_stmt + tree loop_stmt = ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr); ctx->add_statement (loop_stmt); } @@ -871,14 +852,14 @@ public: fncontext fnctx = ctx->peek_fn (); if (expr.has_break_expr ()) { - Bexpression *compiled_expr + tree compiled_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); Bvariable *loop_result_holder = ctx->peek_loop_context (); - Bexpression *result_reference = ctx->get_backend ()->var_expression ( + tree result_reference = ctx->get_backend ()->var_expression ( loop_result_holder, expr.get_expr ()->get_locus ()); - Bstatement *assignment = ctx->get_backend ()->assignment_statement ( + tree assignment = ctx->get_backend ()->assignment_statement ( fnctx.fndecl, result_reference, compiled_expr, expr.get_locus ()); ctx->add_statement (assignment); } @@ -906,7 +887,7 @@ public: return; } - Blabel *label = nullptr; + tree label = NULL_TREE; if (!ctx->lookup_label_decl (ref, &label)) { rust_error_at (expr.get_label ().get_locus (), @@ -914,16 +895,16 @@ public: return; } - Bstatement *goto_label + tree goto_label = ctx->get_backend ()->goto_statement (label, expr.get_locus ()); ctx->add_statement (goto_label); } else { - Bexpression *exit_expr = ctx->get_backend ()->exit_expression ( + tree exit_expr = ctx->get_backend ()->exit_expression ( ctx->get_backend ()->boolean_constant_expression (true), expr.get_locus ()); - Bstatement *break_stmt + tree break_stmt = ctx->get_backend ()->expression_statement (fnctx.fndecl, exit_expr); ctx->add_statement (break_stmt); } @@ -931,7 +912,7 @@ public: void visit (HIR::ContinueExpr &expr) override { - Blabel *label = ctx->peek_loop_begin_label (); + tree label = ctx->peek_loop_begin_label (); if (expr.has_label ()) { NodeId resolved_node_id = UNKNOWN_NODEID; @@ -963,15 +944,14 @@ public: } } - Bstatement *goto_label + tree goto_label = ctx->get_backend ()->goto_statement (label, expr.get_locus ()); ctx->add_statement (goto_label); } void visit (HIR::BorrowExpr &expr) override { - Bexpression *main_expr - = CompileExpr::Compile (expr.get_expr ().get (), ctx); + tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); translated = ctx->get_backend ()->address_expression (main_expr, expr.get_locus ()); @@ -979,8 +959,7 @@ public: void visit (HIR::DereferenceExpr &expr) override { - Bexpression *main_expr - = CompileExpr::Compile (expr.get_expr ().get (), ctx); + tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); TyTy::BaseType *tyty = nullptr; if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), @@ -991,7 +970,7 @@ public: return; } - Btype *expected_type = TyTyResolveCompile::compile (ctx, tyty); + tree expected_type = TyTyResolveCompile::compile (ctx, tyty); bool known_valid = true; translated = ctx->get_backend ()->indirect_expression (expected_type, main_expr, @@ -999,14 +978,32 @@ public: expr.get_locus ()); } +protected: + tree compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn, + TyTy::BaseType *receiver, + TyTy::FnType *fntype, tree receiver_ref, + std::vector<HIR::Expr *> &arguments, + Location expr_locus); + + tree resolve_method_address (TyTy::FnType *fntype, HirId ref, + TyTy::BaseType *receiver, + HIR::PathIdentSegment &segment, + Analysis::NodeMapping expr_mappings, + Location expr_locus); + + tree + resolve_operator_overload (Analysis::RustLangItem::ItemType lang_item_type, + HIR::OperatorExpr &expr, tree lhs, tree rhs, + HIR::Expr *lhs_expr, HIR::Expr *rhs_expr); + private: CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr), capacity_expr (nullptr) {} - Bexpression *translated; - Bexpression *capacity_expr; - std::vector<Bexpression *> constructor; + tree translated; + tree capacity_expr; + std::vector<tree> constructor; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h index 6e5a3fd..aa73509 100644 --- a/gcc/rust/backend/rust-compile-extern.h +++ b/gcc/rust/backend/rust-compile-extern.h @@ -55,7 +55,7 @@ public: // FIXME this is assuming C ABI std::string asm_name = name; - Btype *type = TyTyResolveCompile::compile (ctx, resolved_type); + tree type = TyTyResolveCompile::compile (ctx, resolved_type); bool is_external = true; bool is_hidden = false; bool in_unique_section = false; @@ -99,14 +99,14 @@ public: // items can be forward compiled which means we may not need to invoke this // code. We might also have already compiled this generic function as well. - Bfunction *lookup = nullptr; + tree lookup = NULL_TREE; if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, fntype->get_id (), fntype)) { // has this been added to the list then it must be finished if (ctx->function_completed (lookup)) { - Bfunction *dummy = nullptr; + tree dummy = NULL_TREE; if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) ctx->insert_function_decl (fntype, lookup); @@ -123,12 +123,12 @@ public: if (fntype->get_abi () == ABI::INTRINSIC) { Intrinsics compile (ctx); - Bfunction *fndecl = compile.compile (fntype); + tree fndecl = compile.compile (fntype); ctx->insert_function_decl (fntype, fndecl); return; } - ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); compiled_fn_type = ctx->get_backend ()->specify_abi_attribute (compiled_fn_type, fntype->get_abi ()); @@ -139,7 +139,7 @@ public: std::string ir_symbol_name = function.get_item_name (); std::string asm_name = function.get_item_name (); - Bfunction *fndecl + tree fndecl = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name, flags, function.get_locus ()); ctx->insert_function_decl (fntype, fndecl); diff --git a/gcc/rust/backend/rust-compile-fnparam.h b/gcc/rust/backend/rust-compile-fnparam.h index b246948..629f0f5 100644 --- a/gcc/rust/backend/rust-compile-fnparam.h +++ b/gcc/rust/backend/rust-compile-fnparam.h @@ -29,8 +29,8 @@ class CompileFnParam : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static Bvariable *compile (Context *ctx, Bfunction *fndecl, - HIR::FunctionParam *param, Btype *decl_type, + static Bvariable *compile (Context *ctx, tree fndecl, + HIR::FunctionParam *param, tree decl_type, Location locus) { CompileFnParam compiler (ctx, fndecl, decl_type, locus); @@ -51,14 +51,13 @@ public: } private: - CompileFnParam (Context *ctx, ::Bfunction *fndecl, ::Btype *decl_type, - Location locus) + CompileFnParam (Context *ctx, tree fndecl, tree decl_type, Location locus) : HIRCompileBase (ctx), fndecl (fndecl), decl_type (decl_type), locus (locus), translated (nullptr) {} - ::Bfunction *fndecl; - ::Btype *decl_type; + tree fndecl; + tree decl_type; Location locus; ::Bvariable *translated; }; @@ -66,9 +65,8 @@ private: class CompileSelfParam : public HIRCompileBase { public: - static Bvariable *compile (Context *ctx, Bfunction *fndecl, - HIR::SelfParam &self, Btype *decl_type, - Location locus) + static Bvariable *compile (Context *ctx, tree fndecl, HIR::SelfParam &self, + tree decl_type, Location locus) { bool is_immutable = self.get_self_kind () == HIR::SelfParam::ImplicitSelfKind::IMM diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h index 05c7910..7b41226 100644 --- a/gcc/rust/backend/rust-compile-implitem.h +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -34,11 +34,11 @@ class CompileInherentImplItem : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static Bexpression *Compile (const TyTy::BaseType *self, HIR::ImplItem *item, - Context *ctx, bool compile_fns, - TyTy::BaseType *concrete = nullptr, - bool is_query_mode = false, - Location ref_locus = Location ()) + static tree Compile (const TyTy::BaseType *self, HIR::ImplItem *item, + Context *ctx, bool compile_fns, + TyTy::BaseType *concrete = nullptr, + bool is_query_mode = false, + Location ref_locus = Location ()) { CompileInherentImplItem compiler (self, ctx, compile_fns, concrete, ref_locus); @@ -60,8 +60,8 @@ public: &resolved_type); rust_assert (ok); - ::Btype *type = TyTyResolveCompile::compile (ctx, resolved_type); - Bexpression *value = CompileExpr::Compile (constant.get_expr (), ctx); + tree type = TyTyResolveCompile::compile (ctx, resolved_type); + tree value = CompileExpr::Compile (constant.get_expr (), ctx); const Resolver::CanonicalPath *canonical_path = nullptr; ok = ctx->get_mappings ()->lookup_canonical_path ( @@ -70,7 +70,7 @@ public: rust_assert (ok); std::string ident = canonical_path->get (); - Bexpression *const_expr = ctx->get_backend ()->named_constant_expression ( + tree const_expr = ctx->get_backend ()->named_constant_expression ( type, constant.get_identifier (), value, constant.get_locus ()); ctx->push_const (const_expr); @@ -110,14 +110,14 @@ public: // items can be forward compiled which means we may not need to invoke this // code. We might also have already compiled this generic function as well. - Bfunction *lookup = nullptr; + tree lookup = NULL_TREE; if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, fntype->get_id (), fntype)) { // has this been added to the list then it must be finished if (ctx->function_completed (lookup)) { - Bfunction *dummy = nullptr; + tree dummy = NULL_TREE; if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) { ctx->insert_function_decl (fntype, lookup); @@ -136,7 +136,7 @@ public: } // convert to the actual function type - ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); unsigned int flags = 0; @@ -156,7 +156,7 @@ public: std::string asm_name = ctx->mangle_impl_item (self, fntype, function.get_function_name ()); - Bfunction *fndecl + tree fndecl = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name, flags, function.get_locus ()); ctx->insert_function_decl (fntype, fndecl); @@ -178,7 +178,7 @@ public: return; } - Btype *self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup); + tree self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup); if (self_type == nullptr) { rust_error_at (function.get_self_param ().get_locus (), @@ -262,12 +262,12 @@ public: ok = compile_locals_for_block (*rib, fndecl, locals); rust_assert (ok); - Bblock *enclosing_scope = NULL; + tree enclosing_scope = NULL_TREE; HIR::BlockExpr *function_body = function.get_definition ().get (); Location start_location = function_body->get_locus (); Location end_location = function_body->get_closing_locus (); - Bblock *code_block + tree code_block = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, start_location, end_location); ctx->push_block (code_block); @@ -275,10 +275,10 @@ public: Bvariable *return_address = nullptr; if (function.has_function_return_type ()) { - Btype *return_type = TyTyResolveCompile::compile (ctx, tyret); + tree return_type = TyTyResolveCompile::compile (ctx, tyret); bool address_is_taken = false; - Bstatement *ret_var_stmt = nullptr; + tree ret_var_stmt = NULL_TREE; return_address = ctx->get_backend ()->temporary_variable ( fndecl, code_block, return_type, NULL, address_is_taken, @@ -319,7 +319,7 @@ private: const TyTy::BaseType *self; bool compile_fns; TyTy::BaseType *concrete; - Bexpression *reference; + tree reference; Location ref_locus; }; @@ -328,10 +328,10 @@ class CompileTraitItem : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static Bexpression *Compile (const TyTy::BaseType *self, HIR::TraitItem *item, - Context *ctx, TyTy::BaseType *concrete, - bool is_query_mode = false, - Location ref_locus = Location ()) + static tree Compile (const TyTy::BaseType *self, HIR::TraitItem *item, + Context *ctx, TyTy::BaseType *concrete, + bool is_query_mode = false, + Location ref_locus = Location ()) { CompileTraitItem compiler (self, ctx, concrete, ref_locus); item->accept_vis (compiler); @@ -349,9 +349,8 @@ public: rust_assert (concrete != nullptr); TyTy::BaseType *resolved_type = concrete; - ::Btype *type = TyTyResolveCompile::compile (ctx, resolved_type); - Bexpression *value - = CompileExpr::Compile (constant.get_expr ().get (), ctx); + tree type = TyTyResolveCompile::compile (ctx, resolved_type); + tree value = CompileExpr::Compile (constant.get_expr ().get (), ctx); const Resolver::CanonicalPath *canonical_path = nullptr; bool ok = ctx->get_mappings ()->lookup_canonical_path ( @@ -360,7 +359,7 @@ public: rust_assert (ok); std::string ident = canonical_path->get (); - Bexpression *const_expr = ctx->get_backend ()->named_constant_expression ( + tree const_expr = ctx->get_backend ()->named_constant_expression ( type, constant.get_name (), value, constant.get_locus ()); ctx->push_const (const_expr); @@ -378,14 +377,14 @@ public: // items can be forward compiled which means we may not need to invoke this // code. We might also have already compiled this generic function as well. - Bfunction *lookup = nullptr; + tree lookup = NULL_TREE; if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, fntype->get_id (), fntype)) { // has this been added to the list then it must be finished if (ctx->function_completed (lookup)) { - Bfunction *dummy = nullptr; + tree dummy = NULL_TREE; if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) { ctx->insert_function_decl (fntype, lookup); @@ -404,7 +403,7 @@ public: } // convert to the actual function type - ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); HIR::TraitFunctionDecl &function = func.get_decl (); unsigned int flags = 0; @@ -418,7 +417,7 @@ public: std::string fn_identifier = canonical_path->get (); std::string asm_name = ctx->mangle_item (fntype, *canonical_path); - Bfunction *fndecl + tree fndecl = ctx->get_backend ()->function (compiled_fn_type, fn_identifier, asm_name, flags, func.get_locus ()); ctx->insert_function_decl (fntype, fndecl); @@ -440,7 +439,7 @@ public: return; } - Btype *self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup); + tree self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup); if (self_type == nullptr) { rust_error_at (function.get_self ().get_locus (), @@ -523,12 +522,12 @@ public: ok = compile_locals_for_block (*rib, fndecl, locals); rust_assert (ok); - Bblock *enclosing_scope = NULL; + tree enclosing_scope = NULL_TREE; HIR::BlockExpr *function_body = func.get_block_expr ().get (); Location start_location = function_body->get_locus (); Location end_location = function_body->get_closing_locus (); - Bblock *code_block + tree code_block = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, start_location, end_location); ctx->push_block (code_block); @@ -536,10 +535,10 @@ public: Bvariable *return_address = nullptr; if (function.has_return_type ()) { - Btype *return_type = TyTyResolveCompile::compile (ctx, tyret); + tree return_type = TyTyResolveCompile::compile (ctx, tyret); bool address_is_taken = false; - Bstatement *ret_var_stmt = nullptr; + tree ret_var_stmt = NULL_TREE; return_address = ctx->get_backend ()->temporary_variable ( fndecl, code_block, return_type, NULL, address_is_taken, @@ -578,7 +577,7 @@ private: const TyTy::BaseType *self; TyTy::BaseType *concrete; - Bexpression *reference; + tree reference; Location ref_locus; }; diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index 66d36e3..69626a9 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -21,7 +21,7 @@ namespace Compile { Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {} -Bfunction * +tree Intrinsics::compile (TyTy::FnType *fntype) { rust_assert (fntype->get_abi () == ABI::INTRINSIC); @@ -77,7 +77,7 @@ Intrinsics::compile (TyTy::FnType *fntype) // }; // Some(cx.get_intrinsic(&llvm_name)) - Bfunction *builtin = ctx->get_backend ()->lookup_builtin_by_rust_name ( + tree builtin = ctx->get_backend ()->lookup_builtin_by_rust_name ( fntype->get_identifier ()); if (builtin != nullptr) return builtin; diff --git a/gcc/rust/backend/rust-compile-intrinsic.h b/gcc/rust/backend/rust-compile-intrinsic.h index 25e298a..2d44baa 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.h +++ b/gcc/rust/backend/rust-compile-intrinsic.h @@ -27,7 +27,7 @@ class Intrinsics public: Intrinsics (Context *ctx); - Bfunction *compile (TyTy::FnType *fntype); + tree compile (TyTy::FnType *fntype); private: Context *ctx; diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 6691c2a..5af9ab3 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -37,11 +37,10 @@ protected: using Rust::Compile::HIRCompileBase::visit; public: - static Bexpression *compile (HIR::Item *item, Context *ctx, - bool compile_fns = true, - TyTy::BaseType *concrete = nullptr, - bool is_query_mode = false, - Location ref_locus = Location ()) + static tree compile (HIR::Item *item, Context *ctx, bool compile_fns = true, + TyTy::BaseType *concrete = nullptr, + bool is_query_mode = false, + Location ref_locus = Location ()) { CompileItem compiler (ctx, compile_fns, concrete, ref_locus); item->accept_vis (compiler); @@ -61,8 +60,8 @@ public: &resolved_type); rust_assert (ok); - Btype *type = TyTyResolveCompile::compile (ctx, resolved_type); - Bexpression *value = CompileExpr::Compile (var.get_expr (), ctx); + tree type = TyTyResolveCompile::compile (ctx, resolved_type); + tree value = CompileExpr::Compile (var.get_expr (), ctx); const Resolver::CanonicalPath *canonical_path = nullptr; ok = ctx->get_mappings ()->lookup_canonical_path ( @@ -97,8 +96,8 @@ public: &resolved_type); rust_assert (ok); - ::Btype *type = TyTyResolveCompile::compile (ctx, resolved_type); - Bexpression *value = CompileExpr::Compile (constant.get_expr (), ctx); + tree type = TyTyResolveCompile::compile (ctx, resolved_type); + tree value = CompileExpr::Compile (constant.get_expr (), ctx); const Resolver::CanonicalPath *canonical_path = nullptr; ok = ctx->get_mappings ()->lookup_canonical_path ( @@ -107,7 +106,7 @@ public: rust_assert (ok); std::string ident = canonical_path->get (); - Bexpression *const_expr + tree const_expr = ctx->get_backend ()->named_constant_expression (type, ident, value, constant.get_locus ()); @@ -148,14 +147,14 @@ public: // items can be forward compiled which means we may not need to invoke this // code. We might also have already compiled this generic function as well. - Bfunction *lookup = nullptr; + tree lookup = NULL_TREE; if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, fntype->get_id (), fntype)) { // has this been added to the list then it must be finished if (ctx->function_completed (lookup)) { - Bfunction *dummy = nullptr; + tree dummy = NULL_TREE; if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) { ctx->insert_function_decl (fntype, lookup); @@ -174,7 +173,7 @@ public: fntype->override_context (); } - ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); unsigned int flags = 0; bool is_main_fn = function.get_function_name ().compare ("main") == 0; @@ -202,7 +201,7 @@ public: asm_name = ctx->mangle_item (fntype, *canonical_path); } - Bfunction *fndecl + tree fndecl = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name, flags, function.get_locus ()); ctx->insert_function_decl (fntype, fndecl); @@ -262,12 +261,12 @@ public: ok = compile_locals_for_block (*rib, fndecl, locals); rust_assert (ok); - Bblock *enclosing_scope = NULL; + tree enclosing_scope = NULL_TREE; HIR::BlockExpr *function_body = function.get_definition ().get (); Location start_location = function_body->get_locus (); Location end_location = function_body->get_closing_locus (); - Bblock *code_block + tree code_block = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, start_location, end_location); ctx->push_block (code_block); @@ -275,10 +274,10 @@ public: Bvariable *return_address = nullptr; if (function.has_function_return_type ()) { - Btype *return_type = TyTyResolveCompile::compile (ctx, tyret); + tree return_type = TyTyResolveCompile::compile (ctx, tyret); bool address_is_taken = false; - Bstatement *ret_var_stmt = nullptr; + tree ret_var_stmt = NULL_TREE; return_address = ctx->get_backend ()->temporary_variable ( fndecl, code_block, return_type, NULL, address_is_taken, @@ -347,7 +346,7 @@ protected: bool compile_fns; TyTy::BaseType *concrete; - Bexpression *reference; + tree reference; Location ref_locus; }; diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index d571d4a..cb3f0df 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -40,7 +40,7 @@ ResolvePathRef::visit (HIR::PathInExpression &expr) expr.get_mappings (), expr.get_locus (), false); } -Bexpression * +tree ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, const Analysis::NodeMapping &mappings, Location expr_locus, bool is_qualified_path) @@ -76,7 +76,7 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, } // might be a constant - Bexpression *constant_expr; + tree constant_expr; if (ctx->lookup_const_decl (ref, &constant_expr)) return constant_expr; @@ -92,7 +92,7 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, if (lookup->get_kind () == TyTy::TypeKind::FNDEF) { TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup); - Bfunction *fn = nullptr; + tree fn = NULL_TREE; if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn)) { return ctx->get_backend ()->function_code_expression (fn, expr_locus); @@ -104,7 +104,7 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, is_qualified_path); } -Bexpression * +tree ResolvePathRef::query_compile (HirId ref, TyTy::BaseType *lookup, const HIR::PathIdentSegment &final_segment, const Analysis::NodeMapping &mappings, diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h index ecb89b3..56f82d1 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.h +++ b/gcc/rust/backend/rust-compile-resolve-path.h @@ -30,15 +30,14 @@ class ResolvePathRef : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static Bexpression *Compile (HIR::QualifiedPathInExpression &expr, - Context *ctx) + static tree Compile (HIR::QualifiedPathInExpression &expr, Context *ctx) { ResolvePathRef resolver (ctx); expr.accept_vis (resolver); return resolver.resolved; } - static Bexpression *Compile (HIR::PathInExpression &expr, Context *ctx) + static tree Compile (HIR::PathInExpression &expr, Context *ctx) { ResolvePathRef resolver (ctx); expr.accept_vis (resolver); @@ -54,16 +53,16 @@ private: : HIRCompileBase (ctx), resolved (ctx->get_backend ()->error_expression ()) {} - Bexpression *resolve (const HIR::PathIdentSegment &final_segment, - const Analysis::NodeMapping &mappings, Location locus, - bool is_qualified_path); + tree resolve (const HIR::PathIdentSegment &final_segment, + const Analysis::NodeMapping &mappings, Location locus, + bool is_qualified_path); - Bexpression *query_compile (HirId ref, TyTy::BaseType *lookup, - const HIR::PathIdentSegment &final_segment, - const Analysis::NodeMapping &mappings, - Location expr_locus, bool is_qualified_path); + tree query_compile (HirId ref, TyTy::BaseType *lookup, + const HIR::PathIdentSegment &final_segment, + const Analysis::NodeMapping &mappings, + Location expr_locus, bool is_qualified_path); - Bexpression *resolved; + tree resolved; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h index 754c5d2..f3ee69d 100644 --- a/gcc/rust/backend/rust-compile-stmt.h +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -31,7 +31,7 @@ class CompileStmt : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static Bexpression *Compile (HIR::Stmt *stmt, Context *ctx) + static tree Compile (HIR::Stmt *stmt, Context *ctx) { CompileStmt compiler (ctx); stmt->accept_vis (compiler); @@ -56,8 +56,8 @@ public: &resolved_type); rust_assert (ok); - ::Btype *type = TyTyResolveCompile::compile (ctx, resolved_type); - Bexpression *value = CompileExpr::Compile (constant.get_expr (), ctx); + tree type = TyTyResolveCompile::compile (ctx, resolved_type); + tree value = CompileExpr::Compile (constant.get_expr (), ctx); const Resolver::CanonicalPath *canonical_path = nullptr; ok = ctx->get_mappings ()->lookup_canonical_path ( @@ -66,7 +66,7 @@ public: rust_assert (ok); std::string ident = canonical_path->get (); - Bexpression *const_expr + tree const_expr = ctx->get_backend ()->named_constant_expression (type, ident, value, constant.get_locus ()); @@ -101,7 +101,7 @@ public: return; } - Bexpression *init = CompileExpr::Compile (stmt.get_init_expr (), ctx); + tree init = CompileExpr::Compile (stmt.get_init_expr (), ctx); // FIXME use error_mark_node, check that CompileExpr returns error_mark_node // on failure and make this an assertion if (init == nullptr) @@ -118,7 +118,7 @@ public: auto fnctx = ctx->peek_fn (); if (ty->is_unit ()) { - Bstatement *expr_stmt + tree expr_stmt = ctx->get_backend ()->expression_statement (fnctx.fndecl, init); ctx->add_statement (expr_stmt); } @@ -132,7 +132,7 @@ public: private: CompileStmt (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} - Bexpression *translated; + tree translated; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.h b/gcc/rust/backend/rust-compile-struct-field-expr.h index 553e870..6754e8c 100644 --- a/gcc/rust/backend/rust-compile-struct-field-expr.h +++ b/gcc/rust/backend/rust-compile-struct-field-expr.h @@ -30,7 +30,7 @@ class CompileStructExprField : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static Bexpression *Compile (HIR::StructExprField *field, Context *ctx) + static tree Compile (HIR::StructExprField *field, Context *ctx) { CompileStructExprField compiler (ctx); field->accept_vis (compiler); @@ -49,7 +49,7 @@ private: : HIRCompileBase (ctx), translated (nullptr) {} - Bexpression *translated; + tree translated; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index 180b971..04a3ecd 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -34,7 +34,7 @@ namespace Compile { class TyTyCompile : public TyTy::TyVisitor { public: - static ::Btype *compile (::Backend *backend, TyTy::BaseType *ty) + static tree compile (::Backend *backend, TyTy::BaseType *ty) { TyTyCompile compiler (backend); ty->accept_vis (compiler); @@ -72,15 +72,15 @@ public: void visit (TyTy::FnType &type) override { - Backend::Btyped_identifier receiver; - std::vector<Backend::Btyped_identifier> parameters; - std::vector<Backend::Btyped_identifier> results; + Backend::typed_identifier receiver; + std::vector<Backend::typed_identifier> parameters; + std::vector<Backend::typed_identifier> results; if (!type.get_return_type ()->is_unit ()) { auto hir_type = type.get_return_type (); auto ret = TyTyCompile::compile (backend, hir_type); - results.push_back (Backend::Btyped_identifier ( + results.push_back (Backend::typed_identifier ( "_", ret, mappings->lookup_location (hir_type->get_ref ()))); } @@ -90,7 +90,7 @@ public: auto param_tyty = params.second; auto compiled_param_type = TyTyCompile::compile (backend, param_tyty); - auto compiled_param = Backend::Btyped_identifier ( + auto compiled_param = Backend::typed_identifier ( param_pattern->as_string (), compiled_param_type, mappings->lookup_location (param_tyty->get_ref ())); @@ -227,7 +227,7 @@ public: void visit (TyTy::StrType &) override { - Btype *raw_str = backend->raw_str_type (); + tree raw_str = backend->raw_str_type (); translated = backend->named_type ("str", raw_str, Linemap::predeclared_location ()); } @@ -248,7 +248,7 @@ private: {} ::Backend *backend; - ::Btype *translated; + tree translated; Analysis::Mappings *mappings; }; diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index 7a86e15..a964fa2 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -29,8 +29,7 @@ class CompileVarDecl : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static ::Bvariable *compile (::Bfunction *fndecl, HIR::Stmt *stmt, - Context *ctx) + static ::Bvariable *compile (tree fndecl, HIR::Stmt *stmt, Context *ctx) { CompileVarDecl compiler (ctx, fndecl); stmt->accept_vis (compiler); @@ -64,13 +63,13 @@ public: } private: - CompileVarDecl (Context *ctx, ::Bfunction *fndecl) + CompileVarDecl (Context *ctx, tree fndecl) : HIRCompileBase (ctx), fndecl (fndecl), translated_type (nullptr), translated (nullptr) {} - ::Bfunction *fndecl; - ::Btype *translated_type; + tree fndecl; + tree translated_type; Location locus; ::Bvariable *translated; }; diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index e9aca2c..579b323 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -72,7 +72,7 @@ CompileExpr::visit (HIR::CallExpr &expr) { rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT); TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyty); - Btype *compiled_adt_type = TyTyResolveCompile::compile (ctx, tyty); + tree compiled_adt_type = TyTyResolveCompile::compile (ctx, tyty); rust_assert (!adt->is_enum ()); rust_assert (adt->number_of_variants () == 1); @@ -80,7 +80,7 @@ CompileExpr::visit (HIR::CallExpr &expr) // this assumes all fields are in order from type resolution and if a // base struct was specified those fields are filed via accesors - std::vector<Bexpression *> vals; + std::vector<tree> vals; for (size_t i = 0; i < expr.get_arguments ().size (); i++) { auto &argument = expr.get_arguments ().at (i); @@ -150,7 +150,7 @@ CompileExpr::visit (HIR::CallExpr &expr) required_num_args = fn->num_params (); } - std::vector<Bexpression *> args; + std::vector<tree> args; for (size_t i = 0; i < expr.get_arguments ().size (); i++) { auto &argument = expr.get_arguments ().at (i); @@ -195,7 +195,7 @@ void CompileExpr::visit (HIR::MethodCallExpr &expr) { // method receiver - Bexpression *self = CompileExpr::Compile (expr.get_receiver ().get (), ctx); + tree self = CompileExpr::Compile (expr.get_receiver ().get (), ctx); // lookup the resolved name NodeId resolved_node_id = UNKNOWN_NODEID; @@ -242,220 +242,21 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) const TyTy::DynamicObjectType *dyn = static_cast<const TyTy::DynamicObjectType *> (receiver->get_root ()); - size_t offs = 0; - const Resolver::TraitItemReference *ref = nullptr; - for (auto &bound : dyn->get_object_items ()) - { - const Resolver::TraitItemReference *item = bound.first; - auto t = item->get_tyty (); - rust_assert (t->get_kind () == TyTy::TypeKind::FNDEF); - auto ft = static_cast<TyTy::FnType *> (t); - - if (ft->get_id () == fntype->get_id ()) - { - ref = item; - break; - } - offs++; - } - - if (ref == nullptr) - { - translated = ctx->get_backend ()->error_expression (); - return; - } - - // get any indirection sorted out - auto receiver_ref = self; - if (receiver->get_kind () == TyTy::TypeKind::REF) - { - TyTy::ReferenceType *r - = static_cast<TyTy::ReferenceType *> (receiver); - auto indirect_ty = r->get_base (); - Btype *indrect_compiled_tyty - = TyTyResolveCompile::compile (ctx, indirect_ty); - - Bexpression *indirect - = ctx->get_backend ()->indirect_expression (indrect_compiled_tyty, - receiver_ref, true, - expr.get_locus ()); - receiver_ref = indirect; - } - - // access the offs + 1 for the fnptr and offs=0 for the reciever obj - Bexpression *self_argument - = ctx->get_backend ()->struct_field_expression (receiver_ref, 0, - expr.get_locus ()); - - // access the vtable for the fn - Bexpression *fn_vtable_access - = ctx->get_backend ()->struct_field_expression (receiver_ref, offs + 1, - expr.get_locus ()); - - // cast it to the correct fntype - Btype *expected_fntype = TyTyResolveCompile::compile (ctx, fntype, true); - Bexpression *fn_convert_expr - = ctx->get_backend ()->convert_expression (expected_fntype, - fn_vtable_access, - expr.get_locus ()); - - fncontext fnctx = ctx->peek_fn (); - Bblock *enclosing_scope = ctx->peek_enclosing_scope (); - bool is_address_taken = false; - Bstatement *ret_var_stmt = nullptr; - - Bvariable *fn_convert_expr_tmp = ctx->get_backend ()->temporary_variable ( - fnctx.fndecl, enclosing_scope, expected_fntype, fn_convert_expr, - is_address_taken, expr.get_locus (), &ret_var_stmt); - ctx->add_statement (ret_var_stmt); - - std::vector<Bexpression *> args; - args.push_back (self_argument); - for (auto &argument : expr.get_arguments ()) - { - Bexpression *compiled_expr - = CompileExpr::Compile (argument.get (), ctx); - args.push_back (compiled_expr); - } - - Bexpression *fn_expr - = ctx->get_backend ()->var_expression (fn_convert_expr_tmp, - expr.get_locus ()); + std::vector<HIR::Expr *> arguments; + for (auto &arg : expr.get_arguments ()) + arguments.push_back (arg.get ()); - translated - = ctx->get_backend ()->call_expression (fnctx.fndecl, fn_expr, args, - nullptr, expr.get_locus ()); + translated = compile_dyn_dispatch_call (dyn, receiver, fntype, self, + arguments, expr.get_locus ()); return; } - // address of compiled function - Bexpression *fn_expr = ctx->get_backend ()->error_expression (); - // lookup compiled functions since it may have already been compiled - Bfunction *fn = nullptr; - if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn)) - { - fn_expr - = ctx->get_backend ()->function_code_expression (fn, expr.get_locus ()); - } - else - { - // Now we can try and resolve the address since this might be a forward - // declared function, generic function which has not be compiled yet or - // its an not yet trait bound function - HIR::ImplItem *resolved_item = ctx->get_mappings ()->lookup_hir_implitem ( - expr.get_mappings ().get_crate_num (), ref, nullptr); - if (resolved_item == nullptr) - { - // it might be resolved to a trait item - HIR::TraitItem *trait_item - = ctx->get_mappings ()->lookup_hir_trait_item ( - expr.get_mappings ().get_crate_num (), ref); - HIR::Trait *trait = ctx->get_mappings ()->lookup_trait_item_mapping ( - trait_item->get_mappings ().get_hirid ()); - - Resolver::TraitReference *trait_ref - = &Resolver::TraitReference::error_node (); - bool ok = ctx->get_tyctx ()->lookup_trait_reference ( - trait->get_mappings ().get_defid (), &trait_ref); - rust_assert (ok); - - // the type resolver can only resolve type bounds to their trait - // item so its up to us to figure out if this path should resolve - // to an trait-impl-block-item or if it can be defaulted to the - // trait-impl-item's definition - - auto root = receiver->get_root (); - std::vector<Resolver::PathProbeCandidate> candidates - = Resolver::PathProbeType::Probe ( - root, expr.get_method_name ().get_segment (), true, false, true); - - if (candidates.size () == 0) - { - // this means we are defaulting back to the trait_item if - // possible - Resolver::TraitItemReference *trait_item_ref = nullptr; - bool ok = trait_ref->lookup_hir_trait_item (*trait_item, - &trait_item_ref); - rust_assert (ok); // found - rust_assert (trait_item_ref->is_optional ()); // has definition - - // FIXME Optional means it has a definition and an associated - // block which can be a default implementation, if it does not - // contain an implementation we should actually return - // error_mark_node - - TyTy::BaseType *self_type = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - expr.get_receiver ()->get_mappings ().get_hirid (), - &self_type)) - { - rust_error_at (expr.get_locus (), - "failed to resolve type for self param"); - return; - } - - fn_expr = CompileTraitItem::Compile ( - self_type, trait_item_ref->get_hir_trait_item (), ctx, fntype, - true, expr.get_locus ()); - } - else - { - std::vector<Resolver::Adjustment> adjustments; - Resolver::PathProbeCandidate *candidate - = Resolver::MethodResolution::Select (candidates, root, - adjustments); - - // FIXME this will be a case to return error_mark_node, there is - // an error scenario where a Trait Foo has a method Bar, but this - // receiver does not implement this trait or has an incompatible - // implementation and we should just return error_mark_node - rust_assert (candidate != nullptr); - rust_assert (candidate->is_impl_candidate ()); - - HIR::ImplItem *impl_item = candidate->item.impl.impl_item; - - TyTy::BaseType *self_type = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - expr.get_receiver ()->get_mappings ().get_hirid (), - &self_type)) - { - rust_error_at (expr.get_locus (), - "failed to resolve type for self param"); - return; - } - - if (!fntype->has_subsititions_defined ()) - fn_expr - = CompileInherentImplItem::Compile (self_type, impl_item, ctx, - true); - else - fn_expr - = CompileInherentImplItem::Compile (self_type, impl_item, ctx, - true, fntype); - } - } - else - { - TyTy::BaseType *self_type = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - expr.get_receiver ()->get_mappings ().get_hirid (), &self_type)) - { - rust_error_at (expr.get_locus (), - "failed to resolve type for self param"); - return; - } - - if (!fntype->has_subsititions_defined ()) - fn_expr - = CompileInherentImplItem::Compile (self_type, resolved_item, ctx, - true); - else - fn_expr - = CompileInherentImplItem::Compile (self_type, resolved_item, ctx, - true, fntype); - } - } + HIR::PathExprSegment method_name = expr.get_method_name (); + HIR::PathIdentSegment segment_name = method_name.get_segment (); + tree fn_expr + = resolve_method_address (fntype, ref, receiver, segment_name, + expr.get_mappings (), expr.get_locus ()); // lookup the autoderef mappings std::vector<Resolver::Adjustment> *adjustments = nullptr; @@ -474,7 +275,7 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) break; case Resolver::Adjustment::AdjustmentType::DEREF_REF: - Btype *expected_type + tree expected_type = TyTyResolveCompile::compile (ctx, adjustment.get_expected ()); self = ctx->get_backend ()->indirect_expression ( expected_type, self, true, /* known_valid*/ @@ -483,7 +284,7 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) } } - std::vector<Bexpression *> args; + std::vector<tree> args; args.push_back (self); // adjusted self // normal args @@ -521,7 +322,7 @@ void CompileBlock::visit (HIR::BlockExpr &expr) { fncontext fnctx = ctx->peek_fn (); - Bfunction *fndecl = fnctx.fndecl; + tree fndecl = fnctx.fndecl; Location start_location = expr.get_locus (); Location end_location = expr.get_closing_locus (); auto body_mappings = expr.get_mappings (); @@ -537,10 +338,9 @@ CompileBlock::visit (HIR::BlockExpr &expr) bool ok = compile_locals_for_block (*rib, fndecl, locals); rust_assert (ok); - Bblock *enclosing_scope = ctx->peek_enclosing_scope (); - Bblock *new_block - = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, - start_location, end_location); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree new_block = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, + start_location, end_location); ctx->push_block (new_block); for (auto &s : expr.get_statements ()) @@ -548,7 +348,7 @@ CompileBlock::visit (HIR::BlockExpr &expr) auto compiled_expr = CompileStmt::Compile (s.get (), ctx); if (compiled_expr != nullptr) { - Bstatement *compiled_stmt + tree compiled_stmt = ctx->get_backend ()->expression_statement (fnctx.fndecl, compiled_expr); ctx->add_statement (compiled_stmt); @@ -559,23 +359,22 @@ CompileBlock::visit (HIR::BlockExpr &expr) { // the previous passes will ensure this is a valid return or // a valid trailing expression - Bexpression *compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx); + tree compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx); if (compiled_expr != nullptr) { if (result == nullptr) { - Bstatement *final_stmt + tree final_stmt = ctx->get_backend ()->expression_statement (fnctx.fndecl, compiled_expr); ctx->add_statement (final_stmt); } else { - Bexpression *result_reference - = ctx->get_backend ()->var_expression ( - result, expr.get_final_expr ()->get_locus ()); + tree result_reference = ctx->get_backend ()->var_expression ( + result, expr.get_final_expr ()->get_locus ()); - Bstatement *assignment + tree assignment = ctx->get_backend ()->assignment_statement (fnctx.fndecl, result_reference, compiled_expr, @@ -593,11 +392,9 @@ void CompileConditionalBlocks::visit (HIR::IfExpr &expr) { fncontext fnctx = ctx->peek_fn (); - Bfunction *fndecl = fnctx.fndecl; - Bexpression *condition_expr - = CompileExpr::Compile (expr.get_if_condition (), ctx); - Bblock *then_block - = CompileBlock::compile (expr.get_if_block (), ctx, result); + tree fndecl = fnctx.fndecl; + tree condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx); + tree then_block = CompileBlock::compile (expr.get_if_block (), ctx, result); translated = ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block, @@ -608,13 +405,10 @@ void CompileConditionalBlocks::visit (HIR::IfExprConseqElse &expr) { fncontext fnctx = ctx->peek_fn (); - Bfunction *fndecl = fnctx.fndecl; - Bexpression *condition_expr - = CompileExpr::Compile (expr.get_if_condition (), ctx); - Bblock *then_block - = CompileBlock::compile (expr.get_if_block (), ctx, result); - Bblock *else_block - = CompileBlock::compile (expr.get_else_block (), ctx, result); + tree fndecl = fnctx.fndecl; + tree condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx); + tree then_block = CompileBlock::compile (expr.get_if_block (), ctx, result); + tree else_block = CompileBlock::compile (expr.get_else_block (), ctx, result); translated = ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block, @@ -625,23 +419,20 @@ void CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr) { fncontext fnctx = ctx->peek_fn (); - Bfunction *fndecl = fnctx.fndecl; - Bexpression *condition_expr - = CompileExpr::Compile (expr.get_if_condition (), ctx); - Bblock *then_block - = CompileBlock::compile (expr.get_if_block (), ctx, result); + tree fndecl = fnctx.fndecl; + tree condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx); + tree then_block = CompileBlock::compile (expr.get_if_block (), ctx, result); // else block std::vector<Bvariable *> locals; Location start_location = expr.get_conseq_if_expr ()->get_locus (); Location end_location = expr.get_conseq_if_expr ()->get_locus (); // FIXME - Bblock *enclosing_scope = ctx->peek_enclosing_scope (); - Bblock *else_block - = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, - start_location, end_location); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree else_block = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, + start_location, end_location); ctx->push_block (else_block); - Bstatement *else_stmt_decl + tree else_stmt_decl = CompileConditionalBlocks::compile (expr.get_conseq_if_expr (), ctx, result); ctx->add_statement (else_stmt_decl); @@ -681,7 +472,7 @@ CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field) void HIRCompileBase::compile_function_body ( - Bfunction *fndecl, std::unique_ptr<HIR::BlockExpr> &function_body, + tree fndecl, std::unique_ptr<HIR::BlockExpr> &function_body, bool has_return_type) { for (auto &s : function_body->get_statements ()) @@ -689,7 +480,7 @@ HIRCompileBase::compile_function_body ( auto compiled_expr = CompileStmt::Compile (s.get (), ctx); if (compiled_expr != nullptr) { - Bstatement *compiled_stmt + tree compiled_stmt = ctx->get_backend ()->expression_statement (fndecl, compiled_expr); ctx->add_statement (compiled_stmt); } @@ -699,14 +490,14 @@ HIRCompileBase::compile_function_body ( { // the previous passes will ensure this is a valid return // or a valid trailing expression - Bexpression *compiled_expr + tree compiled_expr = CompileExpr::Compile (function_body->expr.get (), ctx); if (compiled_expr != nullptr) { if (has_return_type) { - std::vector<Bexpression *> retstmts; + std::vector<tree> retstmts; retstmts.push_back (compiled_expr); auto ret = ctx->get_backend ()->return_statement ( @@ -716,7 +507,7 @@ HIRCompileBase::compile_function_body ( } else { - Bstatement *final_stmt + tree final_stmt = ctx->get_backend ()->expression_statement (fndecl, compiled_expr); ctx->add_statement (final_stmt); @@ -726,7 +517,7 @@ HIRCompileBase::compile_function_body ( } bool -HIRCompileBase::compile_locals_for_block (Resolver::Rib &rib, Bfunction *fndecl, +HIRCompileBase::compile_locals_for_block (Resolver::Rib &rib, tree fndecl, std::vector<Bvariable *> &locals) { rib.iterate_decls ([&] (NodeId n, Location) mutable -> bool { @@ -760,10 +551,9 @@ HIRCompileBase::compile_locals_for_block (Resolver::Rib &rib, Bfunction *fndecl, return true; } -Bexpression * -HIRCompileBase::coercion_site (Bexpression *compiled_ref, - TyTy::BaseType *actual, TyTy::BaseType *expected, - Location locus) +tree +HIRCompileBase::coercion_site (tree compiled_ref, TyTy::BaseType *actual, + TyTy::BaseType *expected, Location locus) { auto root_actual_kind = actual->get_root ()->get_kind (); auto root_expected_kind = expected->get_root ()->get_kind (); @@ -779,14 +569,14 @@ HIRCompileBase::coercion_site (Bexpression *compiled_ref, return compiled_ref; } -Bexpression * -HIRCompileBase::coerce_to_dyn_object (Bexpression *compiled_ref, +tree +HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, const TyTy::BaseType *actual, const TyTy::BaseType *expected, const TyTy::DynamicObjectType *ty, Location locus) { - Btype *dynamic_object = TyTyResolveCompile::compile (ctx, ty); + tree dynamic_object = TyTyResolveCompile::compile (ctx, ty); //' this assumes ordering and current the structure is // __trait_object_ptr @@ -796,7 +586,7 @@ HIRCompileBase::coerce_to_dyn_object (Bexpression *compiled_ref, std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>> probed_bounds_for_receiver = Resolver::TypeBoundsProbe::Probe (root); - std::vector<Bexpression *> vals; + std::vector<tree> vals; vals.push_back (compiled_ref); for (auto &bound : ty->get_object_items ()) { @@ -809,14 +599,14 @@ HIRCompileBase::coerce_to_dyn_object (Bexpression *compiled_ref, vals.push_back (address); } - Bexpression *constructed_trait_object + tree constructed_trait_object = ctx->get_backend ()->constructor_expression (dynamic_object, vals, -1, locus); fncontext fnctx = ctx->peek_fn (); - Bblock *enclosing_scope = ctx->peek_enclosing_scope (); + tree enclosing_scope = ctx->peek_enclosing_scope (); bool is_address_taken = false; - Bstatement *ret_var_stmt = nullptr; + tree ret_var_stmt = NULL_TREE; Bvariable *dyn_tmp = ctx->get_backend ()->temporary_variable ( fnctx.fndecl, enclosing_scope, dynamic_object, constructed_trait_object, @@ -858,7 +648,7 @@ HIRCompileBase::coerce_to_dyn_object (Bexpression *compiled_ref, return resulting_dyn_object_ref; } -Bexpression * +tree HIRCompileBase::compute_address_for_trait_item ( const Resolver::TraitItemReference *ref, const TyTy::TypeBoundPredicate *predicate, diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 54cb6113..f36096b 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -452,11 +452,8 @@ public: expr.get_locus ()); } - /* Compound assignment expression is compiled away. */ void visit (AST::CompoundAssignmentExpr &expr) override { - /* First we need to find the corresponding arithmetic or logical operator. - */ ArithmeticOrLogicalOperator op; switch (expr.get_expr_type ()) { @@ -503,15 +500,10 @@ public: Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - HIR::Expr *operator_expr - = new HIR::ArithmeticOrLogicalExpr (mapping, asignee_expr->clone_expr (), - std::unique_ptr<HIR::Expr> (value), - op, expr.get_locus ()); - translated - = new HIR::AssignmentExpr (mapping, - std::unique_ptr<HIR::Expr> (asignee_expr), - std::unique_ptr<HIR::Expr> (operator_expr), - expr.get_locus ()); + + translated = new HIR::CompoundAssignmentExpr ( + mapping, std::unique_ptr<HIR::Expr> (asignee_expr), + std::unique_ptr<HIR::Expr> (value), op, expr.get_locus ()); } void visit (AST::StructExprStruct &struct_expr) override diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index db0425f..65a4921 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -613,29 +613,6 @@ public: if (trait.has_generics ()) { generic_params = lower_generic_params (trait.get_generic_params ()); - - for (auto &generic_param : generic_params) - { - switch (generic_param->get_kind ()) - { - case HIR::GenericParam::GenericKind::TYPE: { - const HIR::TypeParam &t - = static_cast<const HIR::TypeParam &> (*generic_param); - - if (t.has_type ()) - { - // see https://github.com/rust-lang/rust/issues/36887 - rust_error_at ( - t.get_locus (), - "defaults for type parameters are not allowed here"); - } - } - break; - - default: - break; - } - } } std::vector<std::unique_ptr<HIR::TypeParamBound>> type_param_bounds; diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 575d1f6..901feda 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -666,6 +666,80 @@ protected: } }; +class CompoundAssignmentExpr : public OperatorExpr +{ +public: + using ExprType = ArithmeticOrLogicalOperator; + +private: + // Note: overloading trait specified in comments + ExprType expr_type; + std::unique_ptr<Expr> right_expr; + +public: + std::string as_string () const override; + + ExprType get_expr_type () const { return expr_type; } + + // Use pointers in constructor to enable polymorphism + CompoundAssignmentExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> value_to_assign_to, + std::unique_ptr<Expr> value_to_assign, + ExprType expr_kind, Location locus) + : OperatorExpr (std::move (mappings), std::move (value_to_assign_to), + AST::AttrVec (), locus), + expr_type (expr_kind), right_expr (std::move (value_to_assign)) + {} + // outer attributes not allowed + + // Have clone in copy constructor + CompoundAssignmentExpr (CompoundAssignmentExpr const &other) + : OperatorExpr (other), expr_type (other.expr_type), + right_expr (other.right_expr->clone_expr ()) + {} + + // Overload assignment operator to clone + CompoundAssignmentExpr &operator= (CompoundAssignmentExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr (); + expr_type = other.expr_type; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + CompoundAssignmentExpr (CompoundAssignmentExpr &&other) = default; + CompoundAssignmentExpr &operator= (CompoundAssignmentExpr &&other) = default; + + void accept_vis (HIRVisitor &vis) override; + + std::unique_ptr<Expr> &get_left_expr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + std::unique_ptr<Expr> &get_right_expr () + { + rust_assert (right_expr != nullptr); + return right_expr; + } + + void visit_lhs (HIRVisitor &vis) { main_or_left_expr->accept_vis (vis); } + void visit_rhs (HIRVisitor &vis) { right_expr->accept_vis (vis); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + CompoundAssignmentExpr *clone_expr_without_block_impl () const override + { + return new CompoundAssignmentExpr (*this); + } +}; + // Expression in parentheses (i.e. like literally just any 3 + (2 * 6)) class GroupedExpr : public ExprWithoutBlock { @@ -1635,7 +1709,6 @@ class MethodCallExpr : public ExprWithoutBlock { std::unique_ptr<Expr> receiver; PathExprSegment method_name; - // inlined form of CallParams std::vector<std::unique_ptr<Expr> > params; Location locus; @@ -1643,10 +1716,6 @@ class MethodCallExpr : public ExprWithoutBlock public: std::string as_string () const override; - /*inline std::vector<std::unique_ptr<Expr>> get_params() const { - return params; - }*/ - MethodCallExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> call_receiver, PathExprSegment method_path, diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc index bacef82..843e32c 100644 --- a/gcc/rust/hir/tree/rust-hir-full-test.cc +++ b/gcc/rust/hir/tree/rust-hir-full-test.cc @@ -1316,6 +1316,67 @@ AssignmentExpr::as_string () const } std::string +CompoundAssignmentExpr::as_string () const +{ + std::string operator_str; + operator_str.reserve (1); + + // get operator string + switch (expr_type) + { + case ArithmeticOrLogicalOperator::ADD: + operator_str = "+"; + break; + case ArithmeticOrLogicalOperator::SUBTRACT: + operator_str = "-"; + break; + case ArithmeticOrLogicalOperator::MULTIPLY: + operator_str = "*"; + break; + case ArithmeticOrLogicalOperator::DIVIDE: + operator_str = "/"; + break; + case ArithmeticOrLogicalOperator::MODULUS: + operator_str = "%"; + break; + case ArithmeticOrLogicalOperator::BITWISE_AND: + operator_str = "&"; + break; + case ArithmeticOrLogicalOperator::BITWISE_OR: + operator_str = "|"; + break; + case ArithmeticOrLogicalOperator::BITWISE_XOR: + operator_str = "^"; + break; + case ArithmeticOrLogicalOperator::LEFT_SHIFT: + operator_str = "<<"; + break; + case ArithmeticOrLogicalOperator::RIGHT_SHIFT: + operator_str = ">>"; + break; + default: + gcc_unreachable (); + break; + } + + operator_str += "="; + + std::string str ("CompoundAssignmentExpr: "); + if (main_or_left_expr == nullptr || right_expr == nullptr) + { + str += "error. this is probably a parsing failure."; + } + else + { + str += "\n left: " + main_or_left_expr->as_string (); + str += "\n right: " + right_expr->as_string (); + str += "\n operator: " + operator_str; + } + + return str; +} + +std::string AsyncBlockExpr::as_string () const { std::string str = "AsyncBlockExpr: "; @@ -3819,6 +3880,12 @@ AssignmentExpr::accept_vis (HIRVisitor &vis) } void +CompoundAssignmentExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void GroupedExpr::accept_vis (HIRVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h index 0487446..ea125d9 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.h +++ b/gcc/rust/hir/tree/rust-hir-visitor.h @@ -47,6 +47,7 @@ public: virtual void visit (LazyBooleanExpr &expr) = 0; virtual void visit (TypeCastExpr &expr) = 0; virtual void visit (AssignmentExpr &expr) = 0; + virtual void visit (CompoundAssignmentExpr &expr) = 0; virtual void visit (GroupedExpr &expr) = 0; virtual void visit (ArrayElemsValues &elems) = 0; virtual void visit (ArrayElemsCopied &elems) = 0; diff --git a/gcc/rust/lint/rust-lint-marklive-base.h b/gcc/rust/lint/rust-lint-marklive-base.h index b67705b..e0494d7 100644 --- a/gcc/rust/lint/rust-lint-marklive-base.h +++ b/gcc/rust/lint/rust-lint-marklive-base.h @@ -53,7 +53,7 @@ public: virtual void visit (HIR::LazyBooleanExpr &) override {} virtual void visit (HIR::TypeCastExpr &) override {} virtual void visit (HIR::AssignmentExpr &) override {} - + virtual void visit (HIR::CompoundAssignmentExpr &) override {} virtual void visit (HIR::GroupedExpr &) override {} virtual void visit (HIR::ArrayElemsValues &) override {} diff --git a/gcc/rust/lint/rust-lint-marklive.h b/gcc/rust/lint/rust-lint-marklive.h index ca5d894..bcf792b 100644 --- a/gcc/rust/lint/rust-lint-marklive.h +++ b/gcc/rust/lint/rust-lint-marklive.h @@ -186,6 +186,12 @@ public: expr.visit_rhs (*this); } + void visit (HIR::CompoundAssignmentExpr &expr) override + { + expr.visit_lhs (*this); + expr.visit_rhs (*this); + } + void visit (HIR::IfExpr &expr) override { expr.get_if_condition ()->accept_vis (*this); diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index 86c9934..f60732c 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -35,29 +35,14 @@ class ResolveTraitItems : public ResolverBase using Rust::Resolver::ResolverBase::visit; public: - static void go (AST::TraitItem *item, const CanonicalPath &self) + static void go (AST::TraitItem *item) { - ResolveTraitItems resolver (self); + ResolveTraitItems resolver; item->accept_vis (resolver); }; void visit (AST::TraitItemType &type) override { - // insert Self::type_alias for TypePath lookup - auto path - = self.append (ResolveTraitItemTypeToCanonicalPath::resolve (type)); - resolver->get_type_scope ().insert ( - path, type.get_node_id (), type.get_locus (), false, - [&] (const CanonicalPath &, NodeId, Location locus) -> void { - RichLocation r (type.get_locus ()); - r.add_range (locus); - rust_error_at (r, "redefined multiple times"); - }); - - // FIXME this stops the erronious unused decls which will be fixed later on - resolver->get_type_scope ().append_reference_for_def (type.get_node_id (), - type.get_node_id ()); - for (auto &bound : type.get_type_param_bounds ()) ResolveTypeBound::go (bound.get (), type.get_node_id ()); } @@ -189,11 +174,7 @@ public: } private: - ResolveTraitItems (const CanonicalPath &self) - : ResolverBase (UNKNOWN_NODEID), self (self) - {} - - const CanonicalPath &self; + ResolveTraitItems () : ResolverBase (UNKNOWN_NODEID) {} }; class ResolveItem : public ResolverBase @@ -649,7 +630,7 @@ public: for (auto &item : trait.get_trait_items ()) { - ResolveTraitItems::go (item.get (), Self); + ResolveTraitItems::go (item.get ()); } resolver->get_type_scope ().pop (); diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 838d173..2bcf79d 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -101,6 +101,7 @@ protected: using Rust::Resolver::ResolverBase::visit; public: + // FIXME this should really only take AST::TypeNoBounds& static CanonicalPath resolve (AST::Type &type, bool include_generic_args = true, bool type_resolve_generic_args = true) @@ -121,6 +122,8 @@ public: } } + void visit (AST::ReferenceType &ref) override; + void visit (AST::TypePathSegmentGeneric &seg) override; void visit (AST::TypePathSegment &seg) override; diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 921b77c..9a0d349 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -439,8 +439,10 @@ ResolveTypeToCanonicalPath::visit (AST::TypePathSegmentGeneric &seg) if (!seg.has_generic_args ()) { - result = CanonicalPath::new_seg (seg.get_node_id (), - seg.get_ident_segment ().as_string ()); + auto ident_segment + = CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string ()); + result = result.append (ident_segment); return; } @@ -454,14 +456,18 @@ ResolveTypeToCanonicalPath::visit (AST::TypePathSegmentGeneric &seg) { std::string generics = canonicalize_generic_args (seg.get_generic_args ()); - result = CanonicalPath::new_seg (seg.get_node_id (), - seg.get_ident_segment ().as_string () - + "::" + generics); + auto generic_segment + = CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string () + + "::" + generics); + result = result.append (generic_segment); return; } - result = CanonicalPath::new_seg (seg.get_node_id (), - seg.get_ident_segment ().as_string ()); + auto ident_segment + = CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string ()); + result = result.append (ident_segment); } void @@ -481,6 +487,24 @@ ResolveTypeToCanonicalPath::visit (AST::TypePathSegment &seg) result = result.append (ident_seg); } +void +ResolveTypeToCanonicalPath::visit (AST::ReferenceType &ref) +{ + auto inner_type + = ResolveTypeToCanonicalPath::resolve (*ref.get_type_referenced ().get (), + include_generic_args_flag, + type_resolve_generic_args_flag); + + std::string segment_string ("&"); + if (ref.get_has_mut ()) + segment_string += "mut "; + + segment_string += inner_type.get (); + + auto ident_seg = CanonicalPath::new_seg (ref.get_node_id (), segment_string); + result = result.append (ident_seg); +} + // rust-ast-resolve-expr.h void diff --git a/gcc/rust/resolve/rust-ast-verify-assignee.h b/gcc/rust/resolve/rust-ast-verify-assignee.h index 6fbf5fe..d362fe4 100644 --- a/gcc/rust/resolve/rust-ast-verify-assignee.h +++ b/gcc/rust/resolve/rust-ast-verify-assignee.h @@ -75,6 +75,13 @@ public: } } + void visit (AST::DereferenceExpr &expr) override + { + expr.get_dereferenced_expr ()->accept_vis (*this); + } + + void visit (AST::PathInExpression &expr) override { ok = true; } + private: VerifyAsignee (NodeId parent) : ResolverBase (parent), ok (false) {} diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 705f7dc..64144bc 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -29,6 +29,8 @@ #include "operator.h" #include "rust-abi.h" +#include "tree.h" + extern bool saw_errors (void); @@ -39,27 +41,9 @@ saw_errors (void); // frontend, and passed back to the backend. The types must be // defined by the backend using these names. -// The backend representation of a type. -class Btype; - -// The backend represention of an expression. -class Bexpression; - -// The backend representation of a statement. -class Bstatement; - -// The backend representation of a function definition or declaration. -class Bfunction; - -// The backend representation of a block. -class Bblock; - // The backend representation of a variable. class Bvariable; -// The backend representation of a label. -class Blabel; - // The backend interface. This is a pure abstract class that a // specific backend will implement. @@ -70,35 +54,30 @@ public: // Name/type/location. Used for function parameters, struct fields, // interface methods. - struct Btyped_identifier + struct typed_identifier { std::string name; - Btype *btype; + tree type; Location location; - Btyped_identifier () - : name (), btype (NULL), location (Linemap::unknown_location ()) + typed_identifier () + : name (), type (NULL_TREE), location (Linemap::unknown_location ()) {} - Btyped_identifier (const std::string &a_name, Btype *a_btype, - Location a_location) - : name (a_name), btype (a_btype), location (a_location) + typed_identifier (const std::string &a_name, tree a_type, + Location a_location) + : name (a_name), type (a_type), location (a_location) {} }; // debug - virtual void debug (Btype *) = 0; - virtual void debug (Bexpression *) = 0; - virtual void debug (Bstatement *) = 0; - virtual void debug (Bfunction *) = 0; - virtual void debug (Bblock *) = 0; + virtual void debug (tree) = 0; virtual void debug (Bvariable *) = 0; - virtual void debug (Blabel *) = 0; // const folder helpers - virtual bool const_size_cast (Bexpression *, size_t *) = 0; - virtual std::string const_size_val_to_string (Bexpression *) = 0; - virtual bool const_values_equal (Bexpression *, Bexpression *) = 0; + virtual bool const_size_cast (tree, size_t *) = 0; + virtual std::string const_size_val_to_string (tree) = 0; + virtual bool const_values_equal (tree, tree) = 0; static Rust::ABI get_abi_from_string (const std::string &abi, Location locus) { @@ -147,50 +126,50 @@ public: // Produce an error type. Actually the backend could probably just // crash if this is called. - virtual Btype *error_type () = 0; + virtual tree error_type () = 0; // Get a void type. This is used in (at least) two ways: 1) as the // return type of a function with no result parameters; 2) // unsafe.Pointer is represented as *void. - virtual Btype *void_type () = 0; + virtual tree void_type () = 0; // get unit-type - virtual Btype *unit_type () = 0; + virtual tree unit_type () = 0; // Get the unnamed boolean type. - virtual Btype *bool_type () = 0; + virtual tree bool_type () = 0; // Get the char type - virtual Btype *char_type () = 0; + virtual tree char_type () = 0; // Get the wchar type - virtual Btype *wchar_type () = 0; + virtual tree wchar_type () = 0; // Get the Host pointer size in bits virtual int get_pointer_size () = 0; // Get the raw str type const char* - virtual Btype *raw_str_type () = 0; + virtual tree raw_str_type () = 0; // Get an unnamed integer type with the given signedness and number // of bits. - virtual Btype *integer_type (bool is_unsigned, int bits) = 0; + virtual tree integer_type (bool is_unsigned, int bits) = 0; // Get an unnamed floating point type with the given number of bits // (32 or 64). - virtual Btype *float_type (int bits) = 0; + virtual tree float_type (int bits) = 0; // Get an unnamed complex type with the given number of bits (64 or 128). - virtual Btype *complex_type (int bits) = 0; + virtual tree complex_type (int bits) = 0; // Get a pointer type. - virtual Btype *pointer_type (Btype *to_type) = 0; + virtual tree pointer_type (tree to_type) = 0; // Get a reference type. - virtual Btype *reference_type (Btype *to_type) = 0; + virtual tree reference_type (tree to_type) = 0; // make type immutable - virtual Btype *immutable_type (Btype *base) = 0; + virtual tree immutable_type (tree base) = 0; // Get a function type. The receiver, parameter, and results are // generated from the types in the Function_type. The Function_type @@ -201,305 +180,201 @@ public: // one result, RESULT_STRUCT is a struct type to hold the results, // and RESULTS may be ignored; if there are zero or one results, // RESULT_STRUCT is NULL. - virtual Btype * - function_type (const Btyped_identifier &receiver, - const std::vector<Btyped_identifier> ¶meters, - const std::vector<Btyped_identifier> &results, - Btype *result_struct, Location location) + virtual tree function_type (const typed_identifier &receiver, + const std::vector<typed_identifier> ¶meters, + const std::vector<typed_identifier> &results, + tree result_struct, Location location) = 0; - virtual Btype * - function_type_varadic (const Btyped_identifier &receiver, - const std::vector<Btyped_identifier> ¶meters, - const std::vector<Btyped_identifier> &results, - Btype *result_struct, Location location) + virtual tree + function_type_varadic (const typed_identifier &receiver, + const std::vector<typed_identifier> ¶meters, + const std::vector<typed_identifier> &results, + tree result_struct, Location location) = 0; - virtual Btype *function_ptr_type (Btype *result, - const std::vector<Btype *> &praameters, - Location location) + virtual tree function_ptr_type (tree result, + const std::vector<tree> &praameters, + Location location) = 0; // Get a struct type. - virtual Btype *struct_type (const std::vector<Btyped_identifier> &fields) = 0; + virtual tree struct_type (const std::vector<typed_identifier> &fields) = 0; // Get a union type. - virtual Btype *union_type (const std::vector<Btyped_identifier> &fields) = 0; + virtual tree union_type (const std::vector<typed_identifier> &fields) = 0; // Get an array type. - virtual Btype *array_type (Btype *element_type, Bexpression *length) = 0; - - // Create a placeholder pointer type. This is used for a named - // pointer type, since in Go a pointer type may refer to itself. - // NAME is the name of the type, and the location is where the named - // type is defined. This function is also used for unnamed function - // types with multiple results, in which case the type has no name - // and NAME will be empty. FOR_FUNCTION is true if this is for a C - // pointer to function type. A Go func type is represented as a - // pointer to a struct, and the first field of the struct is a C - // pointer to function. The return value will later be passed as - // the first parameter to set_placeholder_pointer_type or - // set_placeholder_function_type. - virtual Btype *placeholder_pointer_type (const std::string &name, Location, - bool for_function) - = 0; - - // Fill in a placeholder pointer type as a pointer. This takes a - // type returned by placeholder_pointer_type and arranges for it to - // point to the type that TO_TYPE points to (that is, PLACEHOLDER - // becomes the same type as TO_TYPE). Returns true on success, - // false on failure. - virtual bool set_placeholder_pointer_type (Btype *placeholder, Btype *to_type) - = 0; - - // Fill in a placeholder pointer type as a function. This takes a - // type returned by placeholder_pointer_type and arranges for it to - // become a real Go function type (which corresponds to a C/C++ - // pointer to function type). FT will be something returned by the - // function_type method. Returns true on success, false on failure. - virtual bool set_placeholder_function_type (Btype *placeholder, Btype *ft) - = 0; - - // Create a placeholder struct type. This is used for a named - // struct type, as with placeholder_pointer_type. It is also used - // for interface types, in which case NAME will be the empty string. - virtual Btype *placeholder_struct_type (const std::string &name, Location) - = 0; - - // Fill in a placeholder struct type. This takes a type returned by - // placeholder_struct_type and arranges for it to become a real - // struct type. The parameter is as for struct_type. Returns true - // on success, false on failure. - virtual bool - set_placeholder_struct_type (Btype *placeholder, - const std::vector<Btyped_identifier> &fields) - = 0; - - // Create a placeholder array type. This is used for a named array - // type, as with placeholder_pointer_type, to handle cases like - // type A []*A. - virtual Btype *placeholder_array_type (const std::string &name, Location) = 0; - - // Fill in a placeholder array type. This takes a type returned by - // placeholder_array_type and arranges for it to become a real array - // type. The parameters are as for array_type. Returns true on - // success, false on failure. - virtual bool set_placeholder_array_type (Btype *placeholder, - Btype *element_type, - Bexpression *length) - = 0; + virtual tree array_type (tree element_type, tree length) = 0; // Return a named version of a type. The location is the location // of the type definition. This will not be called for a type // created via placeholder_pointer_type, placeholder_struct_type, or // placeholder_array_type.. (It may be called for a pointer, // struct, or array type in a case like "type P *byte; type Q P".) - virtual Btype *named_type (const std::string &name, Btype *, Location) = 0; - - // Create a marker for a circular pointer type. Go pointer and - // function types can refer to themselves in ways that are not - // permitted in C/C++. When a circular type is found, this function - // is called for the circular reference. This permits the backend - // to decide how to handle such a type. PLACEHOLDER is the - // placeholder type which has already been created; if the backend - // is prepared to handle a circular pointer type, it may simply - // return PLACEHOLDER. FOR_FUNCTION is true if this is for a - // function type. - // - // For "type P *P" the sequence of calls will be - // bt1 = placeholder_pointer_type(); - // bt2 = circular_pointer_type(bt1, false); - // set_placeholder_pointer_type(bt1, bt2); - virtual Btype *circular_pointer_type (Btype *placeholder, bool for_function) - = 0; - - // Return whether the argument could be a special type created by - // circular_pointer_type. This is used to introduce explicit type - // conversions where needed. If circular_pointer_type returns its - // PLACEHOLDER parameter, this may safely always return false. - virtual bool is_circular_pointer_type (Btype *) = 0; + virtual tree named_type (const std::string &name, tree, Location) = 0; // Return the size of a type. - virtual int64_t type_size (Btype *) = 0; + virtual int64_t type_size (tree) = 0; // Return the alignment of a type. - virtual int64_t type_alignment (Btype *) = 0; + virtual int64_t type_alignment (tree) = 0; // Return the alignment of a struct field of this type. This is // normally the same as type_alignment, but not always. - virtual int64_t type_field_alignment (Btype *) = 0; + virtual int64_t type_field_alignment (tree) = 0; // Return the offset of field INDEX in a struct type. INDEX is the // entry in the FIELDS std::vector parameter of struct_type or // set_placeholder_struct_type. - virtual int64_t type_field_offset (Btype *, size_t index) = 0; + virtual int64_t type_field_offset (tree, size_t index) = 0; // Expressions. // Return an expression for a zero value of the given type. This is // used for cases such as local variable initialization and // converting nil to other types. - virtual Bexpression *zero_expression (Btype *) = 0; + virtual tree zero_expression (tree) = 0; // Create an error expression. This is used for cases which should // not occur in a correct program, in order to keep the compilation // going without crashing. - virtual Bexpression *error_expression () = 0; + virtual tree error_expression () = 0; // return whether this is error_mark_node - virtual bool is_error_expression (Bexpression *) = 0; + virtual bool is_error_expression (tree) = 0; // Create a nil pointer expression. - virtual Bexpression *nil_pointer_expression () = 0; + virtual tree nil_pointer_expression () = 0; - virtual Bexpression *unit_expression () = 0; + virtual tree unit_expression () = 0; // Create a reference to a variable. - virtual Bexpression *var_expression (Bvariable *var, Location) = 0; + virtual tree var_expression (Bvariable *var, Location) = 0; // Create an expression that indirects through the pointer expression EXPR // (i.e., return the expression for *EXPR). KNOWN_VALID is true if the pointer // is known to point to a valid memory location. BTYPE is the expected type // of the indirected EXPR. - virtual Bexpression *indirect_expression (Btype *btype, Bexpression *expr, - bool known_valid, Location) + virtual tree indirect_expression (tree btype, tree expr, bool known_valid, + Location) = 0; // Return an expression that declares a constant named NAME with the // constant value VAL in BTYPE. - virtual Bexpression *named_constant_expression (Btype *btype, - const std::string &name, - Bexpression *val, Location) + virtual tree named_constant_expression (tree btype, const std::string &name, + tree val, Location) = 0; // Return an expression for the multi-precision integer VAL in BTYPE. - virtual Bexpression *integer_constant_expression (Btype *btype, mpz_t val) - = 0; + virtual tree integer_constant_expression (tree btype, mpz_t val) = 0; // Return an expression for the floating point value VAL in BTYPE. - virtual Bexpression *float_constant_expression (Btype *btype, mpfr_t val) = 0; + virtual tree float_constant_expression (tree btype, mpfr_t val) = 0; // Return an expression for the complex value VAL in BTYPE. - virtual Bexpression *complex_constant_expression (Btype *btype, mpc_t val) - = 0; + virtual tree complex_constant_expression (tree btype, mpc_t val) = 0; // Return an expression for the string value VAL. - virtual Bexpression *string_constant_expression (const std::string &val) = 0; + virtual tree string_constant_expression (const std::string &val) = 0; // Get a char literal - virtual Bexpression *char_constant_expression (char c) = 0; + virtual tree char_constant_expression (char c) = 0; // Get a char literal - virtual Bexpression *wchar_constant_expression (wchar_t c) = 0; + virtual tree wchar_constant_expression (wchar_t c) = 0; // Return an expression for the boolean value VAL. - virtual Bexpression *boolean_constant_expression (bool val) = 0; + virtual tree boolean_constant_expression (bool val) = 0; // Return an expression for the real part of BCOMPLEX. - virtual Bexpression *real_part_expression (Bexpression *bcomplex, Location) - = 0; + virtual tree real_part_expression (tree bcomplex, Location) = 0; // Return an expression for the imaginary part of BCOMPLEX. - virtual Bexpression *imag_part_expression (Bexpression *bcomplex, Location) - = 0; + virtual tree imag_part_expression (tree bcomplex, Location) = 0; // Return an expression for the complex number (BREAL, BIMAG). - virtual Bexpression *complex_expression (Bexpression *breal, - Bexpression *bimag, Location) - = 0; + virtual tree complex_expression (tree breal, tree bimag, Location) = 0; // Return an expression that converts EXPR to TYPE. - virtual Bexpression *convert_expression (Btype *type, Bexpression *expr, - Location) - = 0; + virtual tree convert_expression (tree type, tree expr, Location) = 0; // Create an expression for the address of a function. This is used to // get the address of the code for a function. - virtual Bexpression *function_code_expression (Bfunction *, Location) = 0; + virtual tree function_code_expression (tree, Location) = 0; // Create an expression that takes the address of an expression. - virtual Bexpression *address_expression (Bexpression *, Location) = 0; + virtual tree address_expression (tree, Location) = 0; // Return an expression for the field at INDEX in BSTRUCT. - virtual Bexpression *struct_field_expression (Bexpression *bstruct, - size_t index, Location) + virtual tree struct_field_expression (tree bstruct, size_t index, Location) = 0; // Create an expression that executes BSTAT before BEXPR. - virtual Bexpression *compound_expression (Bstatement *bstat, - Bexpression *bexpr, Location) - = 0; + virtual tree compound_expression (tree bstat, tree bexpr, Location) = 0; // Return an expression that executes THEN_EXPR if CONDITION is true, or // ELSE_EXPR otherwise and returns the result as type BTYPE, within the // specified function FUNCTION. ELSE_EXPR may be NULL. BTYPE may be NULL. - virtual Bexpression * - conditional_expression (Bfunction *function, Btype *btype, - Bexpression *condition, Bexpression *then_expr, - Bexpression *else_expr, Location) + virtual tree conditional_expression (tree function, tree btype, + tree condition, tree then_expr, + tree else_expr, Location) = 0; // Return an expression for the negation operation OP EXPR. // Supported values of OP are enumerated in NegationOperator. - virtual Bexpression *negation_expression (NegationOperator op, - Bexpression *expr, Location) + virtual tree negation_expression (NegationOperator op, tree expr, Location) = 0; // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in ArithmeticOrLogicalOperator. - virtual Bexpression * - arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, - Bexpression *left, Bexpression *right, - Location) + virtual tree arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, + tree left, tree right, + Location) = 0; // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in ComparisonOperator. - virtual Bexpression *comparison_expression (ComparisonOperator op, - Bexpression *left, - Bexpression *right, Location) + virtual tree comparison_expression (ComparisonOperator op, tree left, + tree right, Location) = 0; // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in LazyBooleanOperator. - virtual Bexpression *lazy_boolean_expression (LazyBooleanOperator op, - Bexpression *left, - Bexpression *right, Location) + virtual tree lazy_boolean_expression (LazyBooleanOperator op, tree left, + tree right, Location) = 0; // Return an expression that constructs BTYPE with VALS. BTYPE must be the // backend representation a of struct. VALS must be in the same order as the // corresponding fields in BTYPE. - virtual Bexpression * - constructor_expression (Btype *btype, const std::vector<Bexpression *> &vals, - int, Location) + virtual tree constructor_expression (tree btype, + const std::vector<tree> &vals, int, + Location) = 0; // Return an expression that constructs an array of BTYPE with INDEXES and // VALS. INDEXES and VALS must have the same amount of elements. Each index // in INDEXES must be in the same order as the corresponding value in VALS. - virtual Bexpression *array_constructor_expression ( - Btype *btype, const std::vector<unsigned long> &indexes, - const std::vector<Bexpression *> &vals, Location) + virtual tree + array_constructor_expression (tree btype, + const std::vector<unsigned long> &indexes, + const std::vector<tree> &vals, Location) = 0; // Return an expression for the address of BASE[INDEX]. // BASE has a pointer type. This is used for slice indexing. - virtual Bexpression *pointer_offset_expression (Bexpression *base, - Bexpression *index, Location) - = 0; + virtual tree pointer_offset_expression (tree base, tree index, Location) = 0; // Return an expression for ARRAY[INDEX] as an l-value. ARRAY is a valid // fixed-length array, not a slice. - virtual Bexpression *array_index_expression (Bexpression *array, - Bexpression *index, Location) - = 0; + virtual tree array_index_expression (tree array, tree index, Location) = 0; // Create an expression for a call to FN with ARGS, taking place within // caller CALLER. - virtual Bexpression *call_expression (Bfunction *caller, Bexpression *fn, - const std::vector<Bexpression *> &args, - Bexpression *static_chain, Location) + virtual tree call_expression (tree caller, tree fn, + const std::vector<tree> &args, + tree static_chain, Location) = 0; // Statements. @@ -507,40 +382,33 @@ public: // Create an error statement. This is used for cases which should // not occur in a correct program, in order to keep the compilation // going without crashing. - virtual Bstatement *error_statement () = 0; + virtual tree error_statement () = 0; // Create an expression statement within the specified function. - virtual Bstatement *expression_statement (Bfunction *, Bexpression *) = 0; + virtual tree expression_statement (tree, tree) = 0; // Create a variable initialization statement in the specified // function. This initializes a local variable at the point in the // program flow where it is declared. - virtual Bstatement *init_statement (Bfunction *, Bvariable *var, - Bexpression *init) - = 0; + virtual tree init_statement (tree, Bvariable *var, tree init) = 0; // Create an assignment statement within the specified function. - virtual Bstatement *assignment_statement (Bfunction *, Bexpression *lhs, - Bexpression *rhs, Location) - = 0; + virtual tree assignment_statement (tree, tree lhs, tree rhs, Location) = 0; // Create a return statement, passing the representation of the // function and the list of values to return. - virtual Bstatement * - return_statement (Bfunction *, const std::vector<Bexpression *> &, Location) - = 0; + virtual tree return_statement (tree, const std::vector<tree> &, Location) = 0; // Create an if statement within a function. ELSE_BLOCK may be NULL. - virtual Bstatement *if_statement (Bfunction *, Bexpression *condition, - Bblock *then_block, Bblock *else_block, - Location) + virtual tree if_statement (tree, tree condition, tree then_block, + tree else_block, Location) = 0; // infinite loop expressions - virtual Bexpression *loop_expression (Bblock *body, Location) = 0; + virtual tree loop_expression (tree body, Location) = 0; // exit expressions - virtual Bexpression *exit_expression (Bexpression *condition, Location) = 0; + virtual tree exit_expression (tree condition, Location) = 0; // Create a switch statement where the case values are constants. // CASES and STATEMENTS must have the same number of entries. If @@ -549,26 +417,24 @@ public: // either end with a goto statement or will fall through into // STATEMENTS[i + 1]. CASES[i] is empty for the default clause, // which need not be last. FUNCTION is the current function. - virtual Bstatement * - switch_statement (Bfunction *function, Bexpression *value, - const std::vector<std::vector<Bexpression *> > &cases, - const std::vector<Bstatement *> &statements, Location) + virtual tree switch_statement (tree function, tree value, + const std::vector<std::vector<tree> > &cases, + const std::vector<tree> &statements, Location) = 0; // Create a single statement from two statements. - virtual Bstatement *compound_statement (Bstatement *, Bstatement *) = 0; + virtual tree compound_statement (tree, tree) = 0; // Create a single statement from a list of statements. - virtual Bstatement *statement_list (const std::vector<Bstatement *> &) = 0; + virtual tree statement_list (const std::vector<tree> &) = 0; // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if // an exception occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and // if not NULL, it will always be executed. This is used for handling defers // in Go functions. In C++, the resulting code is of this form: // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; } - virtual Bstatement * - exception_handler_statement (Bstatement *bstat, Bstatement *except_stmt, - Bstatement *finally_stmt, Location) + virtual tree exception_handler_statement (tree bstat, tree except_stmt, + tree finally_stmt, Location) = 0; // Blocks. @@ -583,22 +449,20 @@ public: // the initial curly brace. END_LOCATION is the location of the end // of the block, more or less the location of the final curly brace. // The statements will be added after the block is created. - virtual Bblock *block (Bfunction *function, Bblock *enclosing, - const std::vector<Bvariable *> &vars, - Location start_location, Location end_location) + virtual tree block (tree function, tree enclosing, + const std::vector<Bvariable *> &vars, + Location start_location, Location end_location) = 0; // Add the statements to a block. The block is created first. Then // the statements are created. Then the statements are added to the // block. This will called exactly once per block. The vector may // be empty if there are no statements. - virtual void block_add_statements (Bblock *, - const std::vector<Bstatement *> &) - = 0; + virtual void block_add_statements (tree, const std::vector<tree> &) = 0; // Return the block as a statement. This is used to include a block // in a list of statements. - virtual Bstatement *block_statement (Bblock *) = 0; + virtual tree block_statement (tree) = 0; // Variables. @@ -618,7 +482,7 @@ public: // permit the linker to garbage collect the variable if it is not // referenced. LOCATION is where the variable was defined. virtual Bvariable *global_variable (const std::string &name, - const std::string &asm_name, Btype *btype, + const std::string &asm_name, tree btype, bool is_external, bool is_hidden, bool in_unique_section, Location location) = 0; @@ -629,7 +493,7 @@ public: // global_variable_set_init to set the initial value. If this is // not called, the backend should initialize a global variable to 0. // The init function may then assign a value to it. - virtual void global_variable_set_init (Bvariable *, Bexpression *) = 0; + virtual void global_variable_set_init (Bvariable *, tree) = 0; // Create a local variable. The frontend will create the local // variables first, and then create the block which contains them. @@ -643,23 +507,23 @@ public: // the function, as otherwise the variable would be on the heap). // LOCATION is where the variable is defined. For each local variable // the frontend will call init_statement to set the initial value. - virtual Bvariable * - local_variable (Bfunction *function, const std::string &name, Btype *type, - Bvariable *decl_var, bool is_address_taken, Location location) + virtual Bvariable *local_variable (tree function, const std::string &name, + tree type, Bvariable *decl_var, + bool is_address_taken, Location location) = 0; // Create a function parameter. This is an incoming parameter, not // a result parameter (result parameters are treated as local // variables). The arguments are as for local_variable. - virtual Bvariable * - parameter_variable (Bfunction *function, const std::string &name, Btype *type, - bool is_address_taken, Location location) + virtual Bvariable *parameter_variable (tree function, const std::string &name, + tree type, bool is_address_taken, + Location location) = 0; // Create a static chain parameter. This is the closure parameter. - virtual Bvariable *static_chain_variable (Bfunction *function, - const std::string &name, - Btype *type, Location location) + virtual Bvariable *static_chain_variable (tree function, + const std::string &name, tree type, + Location location) = 0; // Create a temporary variable. A temporary variable has no name, @@ -673,10 +537,9 @@ public: // variable, and may not be very useful. This function should // return a variable which can be referenced later and should set // *PSTATEMENT to a statement which initializes the variable. - virtual Bvariable * - temporary_variable (Bfunction *, Bblock *, Btype *, Bexpression *init, - bool address_is_taken, Location location, - Bstatement **pstatement) + virtual Bvariable *temporary_variable (tree, tree, tree, tree init, + bool address_is_taken, + Location location, tree *pstatement) = 0; // Create an implicit variable that is compiler-defined. This is @@ -705,10 +568,10 @@ public: // the zero value. IS_HIDDEN and IS_COMMON will never both be true. // // If ALIGNMENT is not zero, it is the desired alignment of the variable. - virtual Bvariable * - implicit_variable (const std::string &name, const std::string &asm_name, - Btype *type, bool is_hidden, bool is_constant, - bool is_common, int64_t alignment) + virtual Bvariable *implicit_variable (const std::string &name, + const std::string &asm_name, tree type, + bool is_hidden, bool is_constant, + bool is_common, int64_t alignment) = 0; // Set the initial value of a variable created by implicit_variable. @@ -722,9 +585,9 @@ public: // If IS_COMMON is true, INIT will be NULL, and the // variable should be initialized to all zeros. virtual void implicit_variable_set_init (Bvariable *, const std::string &name, - Btype *type, bool is_hidden, + tree type, bool is_hidden, bool is_constant, bool is_common, - Bexpression *init) + tree init) = 0; // Create a reference to a named implicit variable defined in some @@ -734,7 +597,7 @@ public: // variable in C. virtual Bvariable *implicit_variable_reference (const std::string &name, const std::string &asm_name, - Btype *type) + tree type) = 0; // Create a named immutable initialized data structure. This is @@ -767,7 +630,7 @@ public: // immutable_struct_set_init. virtual Bvariable * immutable_struct (const std::string &name, const std::string &asm_name, - bool is_hidden, bool is_common, Btype *type, Location) + bool is_hidden, bool is_common, tree type, Location) = 0; // Set the initial value of a variable created by immutable_struct. @@ -779,8 +642,7 @@ public: // immutable_struct. virtual void immutable_struct_set_init (Bvariable *, const std::string &name, bool is_hidden, bool is_common, - Btype *type, Location, - Bexpression *initializer) + tree type, Location, tree initializer) = 0; // Create a reference to a named immutable initialized data @@ -790,7 +652,7 @@ public: // corresponds to an extern const global variable in C. virtual Bvariable *immutable_struct_reference (const std::string &name, const std::string &asm_name, - Btype *type, Location) + tree type, Location) = 0; // Labels. @@ -798,27 +660,27 @@ public: // Create a new label. NAME will be empty if this is a label // created by the frontend for a loop construct. The location is // where the label is defined. - virtual Blabel *label (Bfunction *, const std::string &name, Location) = 0; + virtual tree label (tree, const std::string &name, Location) = 0; // Create a statement which defines a label. This statement will be // put into the codestream at the point where the label should be // defined. - virtual Bstatement *label_definition_statement (Blabel *) = 0; + virtual tree label_definition_statement (tree) = 0; // Create a goto statement to a label. - virtual Bstatement *goto_statement (Blabel *, Location) = 0; + virtual tree goto_statement (tree, Location) = 0; // Create an expression for the address of a label. This is used to // get the return address of a deferred function which may call // recover. - virtual Bexpression *label_address (Blabel *, Location) = 0; + virtual tree label_address (tree, Location) = 0; // Functions. // Create an error function. This is used for cases which should // not occur in a correct program, in order to keep the compilation // going without crashing. - virtual Bfunction *error_function () = 0; + virtual tree error_function () = 0; // Bit flags to pass to the function method. @@ -857,49 +719,47 @@ public: // string, is the name that should be used in the symbol table; this // will be non-empty if a magic extern comment is used. FLAGS is // bit flags described above. - virtual Bfunction *function (Btype *fntype, const std::string &name, - const std::string &asm_name, unsigned int flags, - Location) + virtual tree function (tree fntype, const std::string &name, + const std::string &asm_name, unsigned int flags, + Location) = 0; - virtual Btype *specify_abi_attribute (Btype *type, Rust::ABI abi) = 0; + virtual tree specify_abi_attribute (tree type, Rust::ABI abi) = 0; // Create a statement that runs all deferred calls for FUNCTION. This should // be a statement that looks like this in C++: // finish: // try { DEFER_RETURN; } catch { CHECK_DEFER; goto finish; } - virtual Bstatement * - function_defer_statement (Bfunction *function, Bexpression *undefer, - Bexpression *check_defer, Location) + virtual tree function_defer_statement (tree function, tree undefer, + tree check_defer, Location) = 0; // Record PARAM_VARS as the variables to use for the parameters of FUNCTION. // This will only be called for a function definition. Returns true on // success, false on failure. virtual bool - function_set_parameters (Bfunction *function, + function_set_parameters (tree function, const std::vector<Bvariable *> ¶m_vars) = 0; // Set the function body for FUNCTION using the code in CODE_STMT. Returns // true on success, false on failure. - virtual bool function_set_body (Bfunction *function, Bstatement *code_stmt) - = 0; + virtual bool function_set_body (tree function, tree code_stmt) = 0; // Look up a named built-in function in the current backend implementation. // Returns NULL if no built-in function by that name exists. - virtual Bfunction *lookup_gcc_builtin (const std::string &) = 0; + virtual tree lookup_gcc_builtin (const std::string &) = 0; - virtual Bfunction *lookup_builtin_by_rust_name (const std::string &) = 0; + virtual tree lookup_builtin_by_rust_name (const std::string &) = 0; // Utility. // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, // FUNCTION_DECLS, and VARIABLE_DECLS declared globally. virtual void - write_global_definitions (const std::vector<Btype *> &type_decls, - const std::vector<Bexpression *> &constant_decls, - const std::vector<Bfunction *> &function_decls, + write_global_definitions (const std::vector<tree> &type_decls, + const std::vector<tree> &constant_decls, + const std::vector<tree> &function_decls, const std::vector<Bvariable *> &variable_decls) = 0; diff --git a/gcc/rust/rust-diagnostics.h b/gcc/rust/rust-diagnostics.h index d9461f1..1c2ec84 100644 --- a/gcc/rust/rust-diagnostics.h +++ b/gcc/rust/rust-diagnostics.h @@ -48,6 +48,7 @@ // All other format specifiers are as defined by 'sprintf'. The final resulting // message is then sent to the back end via rust_be_error_at/rust_be_warning_at. +// clang-format off // simple location extern void rust_internal_error_at (const Location, const char *fmt, ...) @@ -71,6 +72,7 @@ rust_inform (const Location, const char *fmt, ...) extern void rust_error_at (const RichLocation &, const char *fmt, ...) RUST_ATTRIBUTE_GCC_DIAG (2, 3); +// clang-format on // These interfaces provide a way for the front end to ask for // the open/close quote characters it should use when formatting @@ -86,6 +88,7 @@ rust_close_quote (); // instead use the equivalent routines above. The back end is required to // implement these routines. +// clang-format off extern void rust_be_internal_error_at (const Location, const std::string &errmsg) RUST_ATTRIBUTE_NORETURN; @@ -104,6 +107,7 @@ extern void rust_be_get_quotechars (const char **open_quote, const char **close_quote); extern bool rust_be_debug_p (void); +// clang-format on namespace Rust { /* A structure used to represent an error. Useful for enabling diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index efc7823..12df769 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -53,58 +53,6 @@ // TODO: this will have to be significantly modified to work with Rust -// A class wrapping a tree. - -class Gcc_tree -{ -public: - Gcc_tree (tree t) : t_ (t) {} - - tree get_tree () const { return this->t_; } - - void set_tree (tree t) { this->t_ = t; } - -private: - tree t_; -}; - -// In gcc, types, expressions, and statements are all trees. -class Btype : public Gcc_tree -{ -public: - Btype (tree t) : Gcc_tree (t) {} -}; - -class Bexpression : public Gcc_tree -{ -public: - Bexpression (tree t) : Gcc_tree (t) {} -}; - -class Bstatement : public Gcc_tree -{ -public: - Bstatement (tree t) : Gcc_tree (t) {} -}; - -class Bfunction : public Gcc_tree -{ -public: - Bfunction (tree t) : Gcc_tree (t) {} -}; - -class Bblock : public Gcc_tree -{ -public: - Bblock (tree t) : Gcc_tree (t) {} -}; - -class Blabel : public Gcc_tree -{ -public: - Blabel (tree t) : Gcc_tree (t) {} -}; - // Bvariable is a bit more complicated, because of zero-sized types. // The GNU linker does not permit dynamic variables with zero size. // When we see such a variable, we generate a version of the type with @@ -159,22 +107,17 @@ class Gcc_backend : public Backend public: Gcc_backend (); - void debug (Btype *t) { debug_tree (t->get_tree ()); }; - void debug (Bexpression *t) { debug_tree (t->get_tree ()); }; - void debug (Bstatement *t) { debug_tree (t->get_tree ()); }; - void debug (Bfunction *t) { debug_tree (t->get_tree ()); }; - void debug (Bblock *t) { debug_tree (t->get_tree ()); }; + void debug (tree t) { debug_tree (t); }; void debug (Bvariable *t) { debug_tree (t->get_decl ()); }; - void debug (Blabel *t) { debug_tree (t->get_tree ()); }; // Types. - Btype *error_type () { return this->make_type (error_mark_node); } + tree error_type () { return error_mark_node; } - Btype *void_type () { return this->make_type (void_type_node); } + tree void_type () { return void_type_node; } - Btype *unit_type () + tree unit_type () { - static Btype *unit_type; + static tree unit_type; if (unit_type == nullptr) { auto unit_type_node = integer_type (true, 0); @@ -185,18 +128,18 @@ public: return unit_type; } - Btype *bool_type () { return this->make_type (boolean_type_node); } + tree bool_type () { return boolean_type_node; } - Btype *char_type () { return this->make_type (char_type_node); } + tree char_type () { return char_type_node; } - bool const_size_cast (Bexpression *expr, size_t *result) + bool const_size_cast (tree expr, size_t *result) { - rust_assert (TREE_CONSTANT (expr->get_tree ())); + rust_assert (TREE_CONSTANT (expr)); unsigned char buf[sizeof (size_t) + 1]; memset (buf, 0, sizeof (buf)); - int ret = native_encode_expr (expr->get_tree (), buf, sizeof (buf), 0); + int ret = native_encode_expr (expr, buf, sizeof (buf), 0); if (ret <= 0) return false; @@ -205,344 +148,276 @@ public: return true; } - std::string const_size_val_to_string (Bexpression *expr) + std::string const_size_val_to_string (tree expr) { - rust_assert (TREE_CONSTANT (expr->get_tree ())); + rust_assert (TREE_CONSTANT (expr)); unsigned char buf[sizeof (size_t) + 1]; memset (buf, 0, sizeof (buf)); - int ret = native_encode_expr (expr->get_tree (), buf, sizeof (buf), 0); + int ret = native_encode_expr (expr, buf, sizeof (buf), 0); rust_assert (ret > 0); size_t *ptr = (size_t *) buf; return std::to_string (*ptr); } - bool const_values_equal (Bexpression *a, Bexpression *b) + bool const_values_equal (tree a, tree b) { - return operand_equal_p (a->get_tree (), b->get_tree (), - OEP_ONLY_CONST | OEP_PURE_SAME); + return operand_equal_p (a, b, OEP_ONLY_CONST | OEP_PURE_SAME); // printf ("comparing!\n"); // debug_tree (a->get_tree ()); // debug_tree (b->get_tree ()); // printf ("ok = %s\n", ok ? "true" : "false"); } - Btype *wchar_type () + tree wchar_type () { tree wchar = make_unsigned_type (32); TYPE_STRING_FLAG (wchar) = 1; - return this->make_type (wchar); + return wchar; } int get_pointer_size (); - Btype *raw_str_type (); - - Btype *integer_type (bool, int); - - Btype *float_type (int); - - Btype *complex_type (int); - - Btype *pointer_type (Btype *); - - Btype *reference_type (Btype *); - - Btype *immutable_type (Btype *); - - Btype *specify_abi_attribute (Btype *, Rust::ABI); - - Btype *insert_type_attribute (Btype *, const std::string &); - - Btype *function_type (const Btyped_identifier &, - const std::vector<Btyped_identifier> &, - const std::vector<Btyped_identifier> &, Btype *, - const Location); + tree raw_str_type (); - Btype *function_type_varadic (const Btyped_identifier &, - const std::vector<Btyped_identifier> &, - const std::vector<Btyped_identifier> &, Btype *, - const Location); + tree integer_type (bool, int); - Btype *function_ptr_type (Btype *, const std::vector<Btype *> &, Location); + tree float_type (int); - Btype *struct_type (const std::vector<Btyped_identifier> &); + tree complex_type (int); - Btype *union_type (const std::vector<Btyped_identifier> &); + tree pointer_type (tree); - Btype *array_type (Btype *, Bexpression *); + tree reference_type (tree); - Btype *placeholder_pointer_type (const std::string &, Location, bool); + tree immutable_type (tree); - bool set_placeholder_pointer_type (Btype *, Btype *); + tree specify_abi_attribute (tree, Rust::ABI); - bool set_placeholder_function_type (Btype *, Btype *); + tree insert_type_attribute (tree, const std::string &); - Btype *placeholder_struct_type (const std::string &, Location); + tree function_type (const typed_identifier &, + const std::vector<typed_identifier> &, + const std::vector<typed_identifier> &, tree, + const Location); - bool set_placeholder_struct_type (Btype *placeholder, - const std::vector<Btyped_identifier> &); + tree function_type_varadic (const typed_identifier &, + const std::vector<typed_identifier> &, + const std::vector<typed_identifier> &, tree, + const Location); - Btype *placeholder_array_type (const std::string &, Location); + tree function_ptr_type (tree, const std::vector<tree> &, Location); - bool set_placeholder_array_type (Btype *, Btype *, Bexpression *); + tree struct_type (const std::vector<typed_identifier> &); - Btype *named_type (const std::string &, Btype *, Location); + tree union_type (const std::vector<typed_identifier> &); - Btype *circular_pointer_type (Btype *, bool); + tree array_type (tree, tree); - bool is_circular_pointer_type (Btype *); + tree named_type (const std::string &, tree, Location); - int64_t type_size (Btype *); + int64_t type_size (tree); - int64_t type_alignment (Btype *); + int64_t type_alignment (tree); - int64_t type_field_alignment (Btype *); + int64_t type_field_alignment (tree); - int64_t type_field_offset (Btype *, size_t index); + int64_t type_field_offset (tree, size_t index); // Expressions. - Bexpression *zero_expression (Btype *); + tree zero_expression (tree); - Bexpression *error_expression () - { - return this->make_expression (error_mark_node); - } + tree error_expression () { return error_mark_node; } - bool is_error_expression (Bexpression *expr) - { - return expr->get_tree () == error_mark_node; - } + bool is_error_expression (tree expr) { return expr == error_mark_node; } - Bexpression *nil_pointer_expression () - { - return this->make_expression (null_pointer_node); - } + tree nil_pointer_expression () { return null_pointer_node; } - Bexpression *unit_expression () - { - return this->make_expression (integer_zero_node); - } + tree unit_expression () { return integer_zero_node; } - Bexpression *var_expression (Bvariable *var, Location); + tree var_expression (Bvariable *var, Location); - Bexpression *indirect_expression (Btype *, Bexpression *expr, - bool known_valid, Location); + tree indirect_expression (tree, tree expr, bool known_valid, Location); - Bexpression *named_constant_expression (Btype *btype, const std::string &name, - Bexpression *val, Location); + tree named_constant_expression (tree type, const std::string &name, tree val, + Location); - Bexpression *integer_constant_expression (Btype *btype, mpz_t val); + tree integer_constant_expression (tree type, mpz_t val); - Bexpression *float_constant_expression (Btype *btype, mpfr_t val); + tree float_constant_expression (tree type, mpfr_t val); - Bexpression *complex_constant_expression (Btype *btype, mpc_t val); + tree complex_constant_expression (tree type, mpc_t val); - Bexpression *string_constant_expression (const std::string &val); + tree string_constant_expression (const std::string &val); - Bexpression *wchar_constant_expression (wchar_t c); + tree wchar_constant_expression (wchar_t c); - Bexpression *char_constant_expression (char c); + tree char_constant_expression (char c); - Bexpression *boolean_constant_expression (bool val); + tree boolean_constant_expression (bool val); - Bexpression *real_part_expression (Bexpression *bcomplex, Location); + tree real_part_expression (tree bcomplex, Location); - Bexpression *imag_part_expression (Bexpression *bcomplex, Location); + tree imag_part_expression (tree bcomplex, Location); - Bexpression *complex_expression (Bexpression *breal, Bexpression *bimag, - Location); + tree complex_expression (tree breal, tree bimag, Location); - Bexpression *convert_expression (Btype *type, Bexpression *expr, Location); + tree convert_expression (tree type, tree expr, Location); - Bexpression *function_code_expression (Bfunction *, Location); + tree function_code_expression (tree, Location); - Bexpression *address_expression (Bexpression *, Location); + tree address_expression (tree, Location); - Bexpression *struct_field_expression (Bexpression *, size_t, Location); + tree struct_field_expression (tree, size_t, Location); - Bexpression *compound_expression (Bstatement *, Bexpression *, Location); + tree compound_expression (tree, tree, Location); - Bexpression *conditional_expression (Bfunction *, Btype *, Bexpression *, - Bexpression *, Bexpression *, Location); + tree conditional_expression (tree, tree, tree, tree, tree, Location); - Bexpression *negation_expression (NegationOperator op, Bexpression *expr, - Location); + tree negation_expression (NegationOperator op, tree expr, Location); - Bexpression *arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, - Bexpression *left, - Bexpression *right, Location); + tree arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, + tree left, tree right, Location); - Bexpression *comparison_expression (ComparisonOperator op, Bexpression *left, - Bexpression *right, Location); + tree comparison_expression (ComparisonOperator op, tree left, tree right, + Location); - Bexpression *lazy_boolean_expression (LazyBooleanOperator op, - Bexpression *left, Bexpression *right, - Location); + tree lazy_boolean_expression (LazyBooleanOperator op, tree left, tree right, + Location); - Bexpression *constructor_expression (Btype *, - const std::vector<Bexpression *> &, int, - Location); + tree constructor_expression (tree, const std::vector<tree> &, int, Location); - Bexpression *array_constructor_expression (Btype *, - const std::vector<unsigned long> &, - const std::vector<Bexpression *> &, - Location); + tree array_constructor_expression (tree, const std::vector<unsigned long> &, + const std::vector<tree> &, Location); - Bexpression *pointer_offset_expression (Bexpression *base, - Bexpression *offset, Location); + tree pointer_offset_expression (tree base, tree offset, Location); - Bexpression *array_index_expression (Bexpression *array, Bexpression *index, - Location); + tree array_index_expression (tree array, tree index, Location); - Bexpression *call_expression (Bfunction *caller, Bexpression *fn, - const std::vector<Bexpression *> &args, - Bexpression *static_chain, Location); + tree call_expression (tree caller, tree fn, const std::vector<tree> &args, + tree static_chain, Location); // Statements. - Bstatement *error_statement () - { - return this->make_statement (error_mark_node); - } + tree error_statement () { return error_mark_node; } - Bstatement *expression_statement (Bfunction *, Bexpression *); + tree expression_statement (tree, tree); - Bstatement *init_statement (Bfunction *, Bvariable *var, Bexpression *init); + tree init_statement (tree, Bvariable *var, tree init); - Bstatement *assignment_statement (Bfunction *, Bexpression *lhs, - Bexpression *rhs, Location); + tree assignment_statement (tree, tree lhs, tree rhs, Location); - Bstatement *return_statement (Bfunction *, const std::vector<Bexpression *> &, - Location); + tree return_statement (tree, const std::vector<tree> &, Location); - Bstatement *if_statement (Bfunction *, Bexpression *condition, - Bblock *then_block, Bblock *else_block, Location); + tree if_statement (tree, tree condition, tree then_block, tree else_block, + Location); - Bstatement * - switch_statement (Bfunction *function, Bexpression *value, - const std::vector<std::vector<Bexpression *> > &cases, - const std::vector<Bstatement *> &statements, Location); + tree switch_statement (tree function, tree value, + const std::vector<std::vector<tree>> &cases, + const std::vector<tree> &statements, Location); - Bstatement *compound_statement (Bstatement *, Bstatement *); + tree compound_statement (tree, tree); - Bstatement *statement_list (const std::vector<Bstatement *> &); + tree statement_list (const std::vector<tree> &); - Bstatement *exception_handler_statement (Bstatement *bstat, - Bstatement *except_stmt, - Bstatement *finally_stmt, Location); + tree exception_handler_statement (tree bstat, tree except_stmt, + tree finally_stmt, Location); - Bexpression *loop_expression (Bblock *body, Location); + tree loop_expression (tree body, Location); - Bexpression *exit_expression (Bexpression *condition, Location); + tree exit_expression (tree condition, Location); // Blocks. - Bblock *block (Bfunction *, Bblock *, const std::vector<Bvariable *> &, - Location, Location); + tree block (tree, tree, const std::vector<Bvariable *> &, Location, Location); - void block_add_statements (Bblock *, const std::vector<Bstatement *> &); + void block_add_statements (tree, const std::vector<tree> &); - Bstatement *block_statement (Bblock *); + tree block_statement (tree); // Variables. Bvariable *error_variable () { return new Bvariable (error_mark_node); } Bvariable *global_variable (const std::string &var_name, - const std::string &asm_name, Btype *btype, + const std::string &asm_name, tree type, bool is_external, bool is_hidden, bool in_unique_section, Location location); - void global_variable_set_init (Bvariable *, Bexpression *); + void global_variable_set_init (Bvariable *, tree); - Bvariable *local_variable (Bfunction *, const std::string &, Btype *, - Bvariable *, bool, Location); + Bvariable *local_variable (tree, const std::string &, tree, Bvariable *, bool, + Location); - Bvariable *parameter_variable (Bfunction *, const std::string &, Btype *, - bool, Location); + Bvariable *parameter_variable (tree, const std::string &, tree, bool, + Location); - Bvariable *static_chain_variable (Bfunction *, const std::string &, Btype *, - Location); + Bvariable *static_chain_variable (tree, const std::string &, tree, Location); - Bvariable *temporary_variable (Bfunction *, Bblock *, Btype *, Bexpression *, - bool, Location, Bstatement **); + Bvariable *temporary_variable (tree, tree, tree, tree, bool, Location, + tree *); - Bvariable *implicit_variable (const std::string &, const std::string &, - Btype *, bool, bool, bool, int64_t); + Bvariable *implicit_variable (const std::string &, const std::string &, tree, + bool, bool, bool, int64_t); - void implicit_variable_set_init (Bvariable *, const std::string &, Btype *, - bool, bool, bool, Bexpression *); + void implicit_variable_set_init (Bvariable *, const std::string &, tree, bool, + bool, bool, tree); Bvariable *implicit_variable_reference (const std::string &, - const std::string &, Btype *); + const std::string &, tree); Bvariable *immutable_struct (const std::string &, const std::string &, bool, - bool, Btype *, Location); + bool, tree, Location); void immutable_struct_set_init (Bvariable *, const std::string &, bool, bool, - Btype *, Location, Bexpression *); + tree, Location, tree); Bvariable *immutable_struct_reference (const std::string &, - const std::string &, Btype *, - Location); + const std::string &, tree, Location); // Labels. - Blabel *label (Bfunction *, const std::string &name, Location); + tree label (tree, const std::string &name, Location); - Bstatement *label_definition_statement (Blabel *); + tree label_definition_statement (tree); - Bstatement *goto_statement (Blabel *, Location); + tree goto_statement (tree, Location); - Bexpression *label_address (Blabel *, Location); + tree label_address (tree, Location); // Functions. - Bfunction *error_function () { return this->make_function (error_mark_node); } + tree error_function () { return error_mark_node; } - Bfunction *function (Btype *fntype, const std::string &name, - const std::string &asm_name, unsigned int flags, - Location); + tree function (tree fntype, const std::string &name, + const std::string &asm_name, unsigned int flags, Location); - Bstatement *function_defer_statement (Bfunction *function, - Bexpression *undefer, - Bexpression *defer, Location); + tree function_defer_statement (tree function, tree undefer, tree defer, + Location); - bool function_set_parameters (Bfunction *function, + bool function_set_parameters (tree function, const std::vector<Bvariable *> &); - bool function_set_body (Bfunction *function, Bstatement *code_stmt); + bool function_set_body (tree function, tree code_stmt); - Bfunction *lookup_gcc_builtin (const std::string &); + tree lookup_gcc_builtin (const std::string &); - Bfunction *lookup_builtin_by_rust_name (const std::string &); + tree lookup_builtin_by_rust_name (const std::string &); - void write_global_definitions (const std::vector<Btype *> &, - const std::vector<Bexpression *> &, - const std::vector<Bfunction *> &, + void write_global_definitions (const std::vector<tree> &, + const std::vector<tree> &, + const std::vector<tree> &, const std::vector<Bvariable *> &); void write_export_data (const char *bytes, unsigned int size); private: - // Make a Bexpression from a tree. - Bexpression *make_expression (tree t) { return new Bexpression (t); } - - // Make a Bstatement from a tree. - Bstatement *make_statement (tree t) { return new Bstatement (t); } + tree fill_in_fields (tree, const std::vector<typed_identifier> &); - // Make a Btype from a tree. - Btype *make_type (tree t) { return new Btype (t); } - - Bfunction *make_function (tree t) { return new Bfunction (t); } - - Btype *fill_in_fields (Btype *, const std::vector<Btyped_identifier> &); - - Btype *fill_in_array (Btype *, Btype *, Bexpression *); + tree fill_in_array (tree, tree, tree); tree non_zero_size_type (tree); @@ -558,7 +433,7 @@ private: int flags); // A mapping of the GCC built-ins exposed to GCCRust. - std::map<std::string, Bfunction *> builtin_functions_; + std::map<std::string, tree> builtin_functions_; std::map<std::string, std::string> rust_intrinsic_to_gcc_builtin; }; @@ -810,15 +685,15 @@ Gcc_backend::get_pointer_size () return POINTER_SIZE; } -Btype * +tree Gcc_backend::raw_str_type () { tree char_ptr = build_pointer_type (char_type_node); tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST); - return this->make_type (const_char_type); + return const_char_type; } -Btype * +tree Gcc_backend::integer_type (bool is_unsigned, int bits) { tree type; @@ -848,12 +723,12 @@ Gcc_backend::integer_type (bool is_unsigned, int bits) else type = make_signed_type (bits); } - return this->make_type (type); + return type; } // Get an unnamed float type. -Btype * +tree Gcc_backend::float_type (int bits) { tree type; @@ -869,12 +744,12 @@ Gcc_backend::float_type (int bits) TYPE_PRECISION (type) = bits; layout_type (type); } - return this->make_type (type); + return type; } // Get an unnamed complex type. -Btype * +tree Gcc_backend::complex_type (int bits) { tree type; @@ -891,49 +766,46 @@ Gcc_backend::complex_type (int bits) layout_type (type); type = build_complex_type (type); } - return this->make_type (type); + return type; } // Get a pointer type. -Btype * -Gcc_backend::pointer_type (Btype *to_type) +tree +Gcc_backend::pointer_type (tree to_type) { - tree to_type_tree = to_type->get_tree (); - if (to_type_tree == error_mark_node) + if (to_type == error_mark_node) return this->error_type (); - tree type = build_pointer_type (to_type_tree); - return this->make_type (type); + tree type = build_pointer_type (to_type); + return type; } // Get a reference type. -Btype * -Gcc_backend::reference_type (Btype *to_type) +tree +Gcc_backend::reference_type (tree to_type) { - tree to_type_tree = to_type->get_tree (); - if (to_type_tree == error_mark_node) + if (to_type == error_mark_node) return this->error_type (); - tree type = build_reference_type (to_type_tree); - return this->make_type (type); + tree type = build_reference_type (to_type); + return type; } // Get immutable type -Btype * -Gcc_backend::immutable_type (Btype *base) +tree +Gcc_backend::immutable_type (tree base) { - tree type_tree = base->get_tree (); - if (type_tree == error_mark_node) + if (base == error_mark_node) return this->error_type (); - tree constified = build_qualified_type (type_tree, TYPE_QUAL_CONST); - return this->make_type (constified); + tree constified = build_qualified_type (base, TYPE_QUAL_CONST); + return constified; } // ABI -Btype * -Gcc_backend::specify_abi_attribute (Btype *type, Rust::ABI abi) +tree +Gcc_backend::specify_abi_attribute (tree type, Rust::ABI abi) { std::string abi_string; switch (abi) @@ -959,46 +831,46 @@ Gcc_backend::specify_abi_attribute (Btype *type, Rust::ABI abi) return insert_type_attribute (type, abi_string); } -Btype * -Gcc_backend::insert_type_attribute (Btype *type, const std::string &attrname) +tree +Gcc_backend::insert_type_attribute (tree type, const std::string &attrname) { tree ident = get_identifier (attrname.c_str ()); tree attribs = NULL_TREE; - tree old_attrs = TYPE_ATTRIBUTES (type->get_tree ()); + tree old_attrs = TYPE_ATTRIBUTES (type); if (old_attrs) attribs = merge_type_attributes (old_attrs, tree_cons (ident, NULL_TREE, NULL_TREE)); else attribs = tree_cons (ident, NULL_TREE, NULL_TREE); - tree res = build_type_attribute_variant (type->get_tree (), attribs); - return this->make_type (res); + tree res = build_type_attribute_variant (type, attribs); + return res; } // Make a function type. -Btype * -Gcc_backend::function_type (const Btyped_identifier &receiver, - const std::vector<Btyped_identifier> ¶meters, - const std::vector<Btyped_identifier> &results, - Btype *result_struct, Location) +tree +Gcc_backend::function_type (const typed_identifier &receiver, + const std::vector<typed_identifier> ¶meters, + const std::vector<typed_identifier> &results, + tree result_struct, Location) { tree args = NULL_TREE; tree *pp = &args; - if (receiver.btype != NULL) + if (receiver.type != NULL_TREE) { - tree t = receiver.btype->get_tree (); + tree t = receiver.type; if (t == error_mark_node) return this->error_type (); *pp = tree_cons (NULL_TREE, t, NULL_TREE); pp = &TREE_CHAIN (*pp); } - for (std::vector<Btyped_identifier>::const_iterator p = parameters.begin (); + for (std::vector<typed_identifier>::const_iterator p = parameters.begin (); p != parameters.end (); ++p) { - tree t = p->btype->get_tree (); + tree t = p->type; if (t == error_mark_node) return this->error_type (); *pp = tree_cons (NULL_TREE, t, NULL_TREE); @@ -1013,11 +885,11 @@ Gcc_backend::function_type (const Btyped_identifier &receiver, if (results.empty ()) result = void_type_node; else if (results.size () == 1) - result = results.front ().btype->get_tree (); + result = results.front ().type; else { gcc_assert (result_struct != NULL); - result = result_struct->get_tree (); + result = result_struct; } if (result == error_mark_node) return this->error_type (); @@ -1034,32 +906,32 @@ Gcc_backend::function_type (const Btyped_identifier &receiver, if (fntype == error_mark_node) return this->error_type (); - return this->make_type (build_pointer_type (fntype)); + return build_pointer_type (fntype); } -Btype * +tree Gcc_backend::function_type_varadic ( - const Btyped_identifier &receiver, - const std::vector<Btyped_identifier> ¶meters, - const std::vector<Btyped_identifier> &results, Btype *result_struct, Location) + const typed_identifier &receiver, + const std::vector<typed_identifier> ¶meters, + const std::vector<typed_identifier> &results, tree result_struct, Location) { - size_t n = parameters.size () + (receiver.btype != NULL ? 1 : 0); + size_t n = parameters.size () + (receiver.type != NULL_TREE ? 1 : 0); tree *args = XALLOCAVEC (tree, n); size_t offs = 0; - if (receiver.btype != NULL) + if (receiver.type != NULL_TREE) { - tree t = receiver.btype->get_tree (); + tree t = receiver.type; if (t == error_mark_node) return this->error_type (); args[offs++] = t; } - for (std::vector<Btyped_identifier>::const_iterator p = parameters.begin (); + for (std::vector<typed_identifier>::const_iterator p = parameters.begin (); p != parameters.end (); ++p) { - tree t = p->btype->get_tree (); + tree t = p->type; if (t == error_mark_node) return this->error_type (); args[offs++] = t; @@ -1069,11 +941,11 @@ Gcc_backend::function_type_varadic ( if (results.empty ()) result = void_type_node; else if (results.size () == 1) - result = results.front ().btype->get_tree (); + result = results.front ().type; else { - gcc_assert (result_struct != NULL); - result = result_struct->get_tree (); + gcc_assert (result_struct != NULL_TREE); + result = result_struct; } if (result == error_mark_node) return this->error_type (); @@ -1090,12 +962,12 @@ Gcc_backend::function_type_varadic ( if (fntype == error_mark_node) return this->error_type (); - return this->make_type (build_pointer_type (fntype)); + return build_pointer_type (fntype); } -Btype * -Gcc_backend::function_ptr_type (Btype *result_type, - const std::vector<Btype *> ¶meters, +tree +Gcc_backend::function_ptr_type (tree result_type, + const std::vector<tree> ¶meters, Location /* locus */) { tree args = NULL_TREE; @@ -1103,17 +975,16 @@ Gcc_backend::function_ptr_type (Btype *result_type, for (auto ¶m : parameters) { - tree t = param->get_tree (); - if (t == error_mark_node) + if (param == error_mark_node) return this->error_type (); - *pp = tree_cons (NULL_TREE, t, NULL_TREE); + *pp = tree_cons (NULL_TREE, param, NULL_TREE); pp = &TREE_CHAIN (*pp); } *pp = void_list_node; - tree result = result_type->get_tree (); + tree result = result_type; if (result != void_type_node && int_size_in_bytes (result) == 0) result = void_type_node; @@ -1121,82 +992,75 @@ Gcc_backend::function_ptr_type (Btype *result_type, if (fntype == error_mark_node) return this->error_type (); - return this->make_type (build_pointer_type (fntype)); + return build_pointer_type (fntype); } // Make a struct type. -Btype * -Gcc_backend::struct_type (const std::vector<Btyped_identifier> &fields) +tree +Gcc_backend::struct_type (const std::vector<typed_identifier> &fields) { - return this->fill_in_fields (this->make_type (make_node (RECORD_TYPE)), - fields); + return this->fill_in_fields (make_node (RECORD_TYPE), fields); } // Make a union type. -Btype * -Gcc_backend::union_type (const std::vector<Btyped_identifier> &fields) +tree +Gcc_backend::union_type (const std::vector<typed_identifier> &fields) { - return this->fill_in_fields (this->make_type (make_node (UNION_TYPE)), - fields); + return this->fill_in_fields (make_node (UNION_TYPE), fields); } // Fill in the fields of a struct or union type. -Btype * -Gcc_backend::fill_in_fields (Btype *fill, - const std::vector<Btyped_identifier> &fields) +tree +Gcc_backend::fill_in_fields (tree fill, + const std::vector<typed_identifier> &fields) { - tree fill_tree = fill->get_tree (); tree field_trees = NULL_TREE; tree *pp = &field_trees; - for (std::vector<Btyped_identifier>::const_iterator p = fields.begin (); + for (std::vector<typed_identifier>::const_iterator p = fields.begin (); p != fields.end (); ++p) { tree name_tree = get_identifier_from_string (p->name); - tree type_tree = p->btype->get_tree (); + tree type_tree = p->type; if (type_tree == error_mark_node) return this->error_type (); tree field = build_decl (p->location.gcc_location (), FIELD_DECL, name_tree, type_tree); - DECL_CONTEXT (field) = fill_tree; + DECL_CONTEXT (field) = fill; *pp = field; pp = &DECL_CHAIN (field); } - TYPE_FIELDS (fill_tree) = field_trees; - layout_type (fill_tree); + TYPE_FIELDS (fill) = field_trees; + layout_type (fill); // Because Rust permits converting between named struct types and // equivalent struct types, for which we use VIEW_CONVERT_EXPR, and // because we don't try to maintain TYPE_CANONICAL for struct types, // we need to tell the middle-end to use structural equality. - SET_TYPE_STRUCTURAL_EQUALITY (fill_tree); + SET_TYPE_STRUCTURAL_EQUALITY (fill); return fill; } // Make an array type. -Btype * -Gcc_backend::array_type (Btype *element_btype, Bexpression *length) +tree +Gcc_backend::array_type (tree element_type, tree length) { - return this->fill_in_array (this->make_type (make_node (ARRAY_TYPE)), - element_btype, length); + return this->fill_in_array (make_node (ARRAY_TYPE), element_type, length); } // Fill in an array type. -Btype * -Gcc_backend::fill_in_array (Btype *fill, Btype *element_type, - Bexpression *length) +tree +Gcc_backend::fill_in_array (tree fill, tree element_type, tree length_tree) { - tree element_type_tree = element_type->get_tree (); - tree length_tree = length->get_tree (); - if (element_type_tree == error_mark_node || length_tree == error_mark_node) + if (element_type == error_mark_node || length_tree == error_mark_node) return this->error_type (); - gcc_assert (TYPE_SIZE (element_type_tree) != NULL_TREE); + gcc_assert (TYPE_SIZE (element_type) != NULL_TREE); length_tree = fold_convert (sizetype, length_tree); @@ -1205,160 +1069,26 @@ Gcc_backend::fill_in_array (Btype *fill, Btype *element_type, tree index_type_tree = build_index_type ( fold_build2 (MINUS_EXPR, sizetype, length_tree, size_one_node)); - tree fill_tree = fill->get_tree (); - TREE_TYPE (fill_tree) = element_type_tree; - TYPE_DOMAIN (fill_tree) = index_type_tree; - TYPE_ADDR_SPACE (fill_tree) = TYPE_ADDR_SPACE (element_type_tree); - layout_type (fill_tree); + TREE_TYPE (fill) = element_type; + TYPE_DOMAIN (fill) = index_type_tree; + TYPE_ADDR_SPACE (fill) = TYPE_ADDR_SPACE (element_type); + layout_type (fill); - if (TYPE_STRUCTURAL_EQUALITY_P (element_type_tree)) - SET_TYPE_STRUCTURAL_EQUALITY (fill_tree); - else if (TYPE_CANONICAL (element_type_tree) != element_type_tree + if (TYPE_STRUCTURAL_EQUALITY_P (element_type)) + SET_TYPE_STRUCTURAL_EQUALITY (fill); + else if (TYPE_CANONICAL (element_type) != element_type || TYPE_CANONICAL (index_type_tree) != index_type_tree) - TYPE_CANONICAL (fill_tree) - = build_array_type (TYPE_CANONICAL (element_type_tree), - TYPE_CANONICAL (index_type_tree)); + TYPE_CANONICAL (fill) = build_array_type (TYPE_CANONICAL (element_type), + TYPE_CANONICAL (index_type_tree)); return fill; } -// Create a placeholder for a pointer type. - -Btype * -Gcc_backend::placeholder_pointer_type (const std::string &name, - Location location, bool) -{ - tree ret = build_distinct_type_copy (ptr_type_node); - if (!name.empty ()) - { - tree decl = build_decl (location.gcc_location (), TYPE_DECL, - get_identifier_from_string (name), ret); - TYPE_NAME (ret) = decl; - } - return this->make_type (ret); -} - -// Set the real target type for a placeholder pointer type. - -bool -Gcc_backend::set_placeholder_pointer_type (Btype *placeholder, Btype *to_type) -{ - tree pt = placeholder->get_tree (); - if (pt == error_mark_node) - return false; - gcc_assert (TREE_CODE (pt) == POINTER_TYPE); - tree tt = to_type->get_tree (); - if (tt == error_mark_node) - { - placeholder->set_tree (error_mark_node); - return false; - } - gcc_assert (TREE_CODE (tt) == POINTER_TYPE); - TREE_TYPE (pt) = TREE_TYPE (tt); - TYPE_CANONICAL (pt) = TYPE_CANONICAL (tt); - if (TYPE_NAME (pt) != NULL_TREE) - { - // Build the data structure gcc wants to see for a typedef. - tree copy = build_variant_type_copy (pt); - TYPE_NAME (copy) = NULL_TREE; - DECL_ORIGINAL_TYPE (TYPE_NAME (pt)) = copy; - } - return true; -} - -// Set the real values for a placeholder function type. - -bool -Gcc_backend::set_placeholder_function_type (Btype *placeholder, Btype *ft) -{ - return this->set_placeholder_pointer_type (placeholder, ft); -} - -// Create a placeholder for a struct type. - -Btype * -Gcc_backend::placeholder_struct_type (const std::string &name, - Location location) -{ - tree ret = make_node (RECORD_TYPE); - if (!name.empty ()) - { - tree decl = build_decl (location.gcc_location (), TYPE_DECL, - get_identifier_from_string (name), ret); - TYPE_NAME (ret) = decl; - - // The struct type that eventually replaces this placeholder will require - // structural equality. The placeholder must too, so that the requirement - // for structural equality propagates to references that are constructed - // before the replacement occurs. - SET_TYPE_STRUCTURAL_EQUALITY (ret); - } - return this->make_type (ret); -} - -// Fill in the fields of a placeholder struct type. - -bool -Gcc_backend::set_placeholder_struct_type ( - Btype *placeholder, const std::vector<Btyped_identifier> &fields) -{ - tree t = placeholder->get_tree (); - gcc_assert (TREE_CODE (t) == RECORD_TYPE && TYPE_FIELDS (t) == NULL_TREE); - Btype *r = this->fill_in_fields (placeholder, fields); - - if (TYPE_NAME (t) != NULL_TREE) - { - // Build the data structure gcc wants to see for a typedef. - tree copy = build_distinct_type_copy (t); - TYPE_NAME (copy) = NULL_TREE; - DECL_ORIGINAL_TYPE (TYPE_NAME (t)) = copy; - TYPE_SIZE (copy) = NULL_TREE; - Btype *bc = this->make_type (copy); - this->fill_in_fields (bc, fields); - delete bc; - } - - return r->get_tree () != error_mark_node; -} - -// Create a placeholder for an array type. - -Btype * -Gcc_backend::placeholder_array_type (const std::string &name, Location location) -{ - tree ret = make_node (ARRAY_TYPE); - tree decl = build_decl (location.gcc_location (), TYPE_DECL, - get_identifier_from_string (name), ret); - TYPE_NAME (ret) = decl; - return this->make_type (ret); -} - -// Fill in the fields of a placeholder array type. - -bool -Gcc_backend::set_placeholder_array_type (Btype *placeholder, - Btype *element_btype, - Bexpression *length) -{ - tree t = placeholder->get_tree (); - gcc_assert (TREE_CODE (t) == ARRAY_TYPE && TREE_TYPE (t) == NULL_TREE); - Btype *r = this->fill_in_array (placeholder, element_btype, length); - - // Build the data structure gcc wants to see for a typedef. - tree copy = build_distinct_type_copy (t); - TYPE_NAME (copy) = NULL_TREE; - DECL_ORIGINAL_TYPE (TYPE_NAME (t)) = copy; - - return r->get_tree () != error_mark_node; -} - // Return a named version of a type. -Btype * -Gcc_backend::named_type (const std::string &name, Btype *btype, - Location location) +tree +Gcc_backend::named_type (const std::string &name, tree type, Location location) { - tree type = btype->get_tree (); if (type == error_mark_node) return this->error_type (); @@ -1374,7 +1104,7 @@ Gcc_backend::named_type (const std::string &name, Btype *btype, tree decl = build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier_from_string (name), type); TYPE_NAME (type) = decl; - return this->make_type (type); + return type; } tree copy = build_variant_type_copy (type); @@ -1382,31 +1112,14 @@ Gcc_backend::named_type (const std::string &name, Btype *btype, get_identifier_from_string (name), copy); DECL_ORIGINAL_TYPE (decl) = type; TYPE_NAME (copy) = decl; - return this->make_type (copy); -} - -// Return a pointer type used as a marker for a circular type. - -Btype * -Gcc_backend::circular_pointer_type (Btype *, bool) -{ - return this->make_type (ptr_type_node); -} - -// Return whether we might be looking at a circular type. - -bool -Gcc_backend::is_circular_pointer_type (Btype *btype) -{ - return btype->get_tree () == ptr_type_node; + return copy; } // Return the size of a type. int64_t -Gcc_backend::type_size (Btype *btype) +Gcc_backend::type_size (tree t) { - tree t = btype->get_tree (); if (t == error_mark_node) return 1; if (t == void_type_node) @@ -1423,9 +1136,8 @@ Gcc_backend::type_size (Btype *btype) // Return the alignment of a type. int64_t -Gcc_backend::type_alignment (Btype *btype) +Gcc_backend::type_alignment (tree t) { - tree t = btype->get_tree (); if (t == error_mark_node) return 1; return TYPE_ALIGN_UNIT (t); @@ -1434,9 +1146,8 @@ Gcc_backend::type_alignment (Btype *btype) // Return the alignment of a struct field of type BTYPE. int64_t -Gcc_backend::type_field_alignment (Btype *btype) +Gcc_backend::type_field_alignment (tree t) { - tree t = btype->get_tree (); if (t == error_mark_node) return 1; return rust_field_alignment (t); @@ -1445,9 +1156,8 @@ Gcc_backend::type_field_alignment (Btype *btype) // Return the offset of a field in a struct. int64_t -Gcc_backend::type_field_offset (Btype *btype, size_t index) +Gcc_backend::type_field_offset (tree struct_tree, size_t index) { - tree struct_tree = btype->get_tree (); if (struct_tree == error_mark_node) return 0; gcc_assert (TREE_CODE (struct_tree) == RECORD_TYPE); @@ -1465,37 +1175,34 @@ Gcc_backend::type_field_offset (Btype *btype, size_t index) // Return the zero value for a type. -Bexpression * -Gcc_backend::zero_expression (Btype *btype) +tree +Gcc_backend::zero_expression (tree t) { - tree t = btype->get_tree (); tree ret; if (t == error_mark_node) ret = error_mark_node; else ret = build_zero_cst (t); - return this->make_expression (ret); + return ret; } // An expression that references a variable. -Bexpression * +tree Gcc_backend::var_expression (Bvariable *var, Location location) { tree ret = var->get_tree (location); if (ret == error_mark_node) return this->error_expression (); - return this->make_expression (ret); + return ret; } // An expression that indirectly references an expression. -Bexpression * -Gcc_backend::indirect_expression (Btype *btype, Bexpression *expr, +tree +Gcc_backend::indirect_expression (tree type_tree, tree expr_tree, bool known_valid, Location location) { - tree expr_tree = expr->get_tree (); - tree type_tree = btype->get_tree (); if (expr_tree == error_mark_node || type_tree == error_mark_node) return this->error_expression (); @@ -1509,18 +1216,16 @@ Gcc_backend::indirect_expression (Btype *btype, Bexpression *expr, tree ret = build_fold_indirect_ref_loc (location.gcc_location (), expr_tree); if (known_valid) TREE_THIS_NOTRAP (ret) = 1; - return this->make_expression (ret); + return ret; } // Return an expression that declares a constant named NAME with the // constant value VAL in BTYPE. -Bexpression * -Gcc_backend::named_constant_expression (Btype *btype, const std::string &name, - Bexpression *val, Location location) +tree +Gcc_backend::named_constant_expression (tree type_tree, const std::string &name, + tree const_val, Location location) { - tree type_tree = btype->get_tree (); - tree const_val = val->get_tree (); if (type_tree == error_mark_node || const_val == error_mark_node) return this->error_expression (); @@ -1532,28 +1237,26 @@ Gcc_backend::named_constant_expression (Btype *btype, const std::string &name, TREE_READONLY (decl) = 1; rust_preserve_from_gc (decl); - return this->make_expression (decl); + return decl; } // Return a typed value as a constant integer. -Bexpression * -Gcc_backend::integer_constant_expression (Btype *btype, mpz_t val) +tree +Gcc_backend::integer_constant_expression (tree t, mpz_t val) { - tree t = btype->get_tree (); if (t == error_mark_node) return this->error_expression (); tree ret = double_int_to_tree (t, mpz_get_double_int (t, val, true)); - return this->make_expression (ret); + return ret; } // Return a typed value as a constant floating-point number. -Bexpression * -Gcc_backend::float_constant_expression (Btype *btype, mpfr_t val) +tree +Gcc_backend::float_constant_expression (tree t, mpfr_t val) { - tree t = btype->get_tree (); tree ret; if (t == error_mark_node) return this->error_expression (); @@ -1563,15 +1266,14 @@ Gcc_backend::float_constant_expression (Btype *btype, mpfr_t val) REAL_VALUE_TYPE r2; real_convert (&r2, TYPE_MODE (t), &r1); ret = build_real (t, r2); - return this->make_expression (ret); + return ret; } // Return a typed real and imaginary value as a constant complex number. -Bexpression * -Gcc_backend::complex_constant_expression (Btype *btype, mpc_t val) +tree +Gcc_backend::complex_constant_expression (tree t, mpc_t val) { - tree t = btype->get_tree (); tree ret; if (t == error_mark_node) return this->error_expression (); @@ -1588,12 +1290,12 @@ Gcc_backend::complex_constant_expression (Btype *btype, mpc_t val) ret = build_complex (t, build_real (TREE_TYPE (t), r2), build_real (TREE_TYPE (t), r4)); - return this->make_expression (ret); + return ret; } // Make a constant string expression. -Bexpression * +tree Gcc_backend::string_constant_expression (const std::string &val) { tree index_type = build_index_type (size_int (val.length ())); @@ -1603,70 +1305,63 @@ Gcc_backend::string_constant_expression (const std::string &val) tree string_val = build_string (val.length (), val.data ()); TREE_TYPE (string_val) = string_type; - return this->make_expression (string_val); + return string_val; } -Bexpression * +tree Gcc_backend::wchar_constant_expression (wchar_t c) { - tree ret = build_int_cst (this->wchar_type ()->get_tree (), c); - return this->make_expression (ret); + return build_int_cst (this->wchar_type (), c); } -Bexpression * +tree Gcc_backend::char_constant_expression (char c) { - tree ret = build_int_cst (this->char_type ()->get_tree (), c); - return this->make_expression (ret); + return build_int_cst (this->char_type (), c); } // Make a constant boolean expression. -Bexpression * +tree Gcc_backend::boolean_constant_expression (bool val) { - tree bool_cst = val ? boolean_true_node : boolean_false_node; - return this->make_expression (bool_cst); + return val ? boolean_true_node : boolean_false_node; } // Return the real part of a complex expression. -Bexpression * -Gcc_backend::real_part_expression (Bexpression *bcomplex, Location location) +tree +Gcc_backend::real_part_expression (tree complex_tree, Location location) { - tree complex_tree = bcomplex->get_tree (); if (complex_tree == error_mark_node) return this->error_expression (); gcc_assert (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (complex_tree))); tree ret = fold_build1_loc (location.gcc_location (), REALPART_EXPR, TREE_TYPE (TREE_TYPE (complex_tree)), complex_tree); - return this->make_expression (ret); + return ret; } // Return the imaginary part of a complex expression. -Bexpression * -Gcc_backend::imag_part_expression (Bexpression *bcomplex, Location location) +tree +Gcc_backend::imag_part_expression (tree complex_tree, Location location) { - tree complex_tree = bcomplex->get_tree (); if (complex_tree == error_mark_node) return this->error_expression (); gcc_assert (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (complex_tree))); tree ret = fold_build1_loc (location.gcc_location (), IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (complex_tree)), complex_tree); - return this->make_expression (ret); + return ret; } // Make a complex expression given its real and imaginary parts. -Bexpression * -Gcc_backend::complex_expression (Bexpression *breal, Bexpression *bimag, +tree +Gcc_backend::complex_expression (tree real_tree, tree imag_tree, Location location) { - tree real_tree = breal->get_tree (); - tree imag_tree = bimag->get_tree (); if (real_tree == error_mark_node || imag_tree == error_mark_node) return this->error_expression (); gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (real_tree)) @@ -1675,23 +1370,22 @@ Gcc_backend::complex_expression (Bexpression *breal, Bexpression *bimag, tree ret = fold_build2_loc (location.gcc_location (), COMPLEX_EXPR, build_complex_type (TREE_TYPE (real_tree)), real_tree, imag_tree); - return this->make_expression (ret); + return ret; } // An expression that converts an expression to a different type. -Bexpression * -Gcc_backend::convert_expression (Btype *type, Bexpression *expr, +tree +Gcc_backend::convert_expression (tree type_tree, tree expr_tree, Location location) { - tree type_tree = type->get_tree (); - tree expr_tree = expr->get_tree (); if (type_tree == error_mark_node || expr_tree == error_mark_node || TREE_TYPE (expr_tree) == error_mark_node) return this->error_expression (); tree ret; - if (this->type_size (type) == 0 || TREE_TYPE (expr_tree) == void_type_node) + if (this->type_size (type_tree) == 0 + || TREE_TYPE (expr_tree) == void_type_node) { // Do not convert zero-sized types. ret = expr_tree; @@ -1712,42 +1406,38 @@ Gcc_backend::convert_expression (Btype *type, Bexpression *expr, else ret = fold_convert_loc (location.gcc_location (), type_tree, expr_tree); - return this->make_expression (ret); + return ret; } // Get the address of a function. -Bexpression * -Gcc_backend::function_code_expression (Bfunction *bfunc, Location location) +tree +Gcc_backend::function_code_expression (tree func, Location location) { - tree func = bfunc->get_tree (); if (func == error_mark_node) return this->error_expression (); tree ret = build_fold_addr_expr_loc (location.gcc_location (), func); - return this->make_expression (ret); + return ret; } // Get the address of an expression. -Bexpression * -Gcc_backend::address_expression (Bexpression *bexpr, Location location) +tree +Gcc_backend::address_expression (tree expr, Location location) { - tree expr = bexpr->get_tree (); if (expr == error_mark_node) return this->error_expression (); - tree ret = build_fold_addr_expr_loc (location.gcc_location (), expr); - return this->make_expression (ret); + return build_fold_addr_expr_loc (location.gcc_location (), expr); } // Return an expression for the field at INDEX in BSTRUCT. -Bexpression * -Gcc_backend::struct_field_expression (Bexpression *bstruct, size_t index, +tree +Gcc_backend::struct_field_expression (tree struct_tree, size_t index, Location location) { - tree struct_tree = bstruct->get_tree (); if (struct_tree == error_mark_node || TREE_TYPE (struct_tree) == error_mark_node) return this->error_expression (); @@ -1771,43 +1461,35 @@ Gcc_backend::struct_field_expression (Bexpression *bstruct, size_t index, TREE_TYPE (field), struct_tree, field, NULL_TREE); if (TREE_CONSTANT (struct_tree)) TREE_CONSTANT (ret) = 1; - return this->make_expression (ret); + return ret; } // Return an expression that executes BSTAT before BEXPR. -Bexpression * -Gcc_backend::compound_expression (Bstatement *bstat, Bexpression *bexpr, - Location location) +tree +Gcc_backend::compound_expression (tree stat, tree expr, Location location) { - tree stat = bstat->get_tree (); - tree expr = bexpr->get_tree (); if (stat == error_mark_node || expr == error_mark_node) return this->error_expression (); tree ret = fold_build2_loc (location.gcc_location (), COMPOUND_EXPR, TREE_TYPE (expr), stat, expr); - return this->make_expression (ret); + return ret; } // Return an expression that executes THEN_EXPR if CONDITION is true, or // ELSE_EXPR otherwise. -Bexpression * -Gcc_backend::conditional_expression (Bfunction *, Btype *btype, - Bexpression *condition, - Bexpression *then_expr, - Bexpression *else_expr, Location location) -{ - tree type_tree = btype == NULL ? void_type_node : btype->get_tree (); - tree cond_tree = condition->get_tree (); - tree then_tree = then_expr->get_tree (); - tree else_tree = else_expr == NULL ? NULL_TREE : else_expr->get_tree (); - if (type_tree == error_mark_node || cond_tree == error_mark_node - || then_tree == error_mark_node || else_tree == error_mark_node) +tree +Gcc_backend::conditional_expression (tree, tree type_tree, tree cond_expr, + tree then_expr, tree else_expr, + Location location) +{ + if (type_tree == error_mark_node || cond_expr == error_mark_node + || then_expr == error_mark_node || else_expr == error_mark_node) return this->error_expression (); tree ret = build3_loc (location.gcc_location (), COND_EXPR, type_tree, - cond_tree, then_tree, else_tree); - return this->make_expression (ret); + cond_expr, then_expr, else_expr); + return ret; } /* Helper function that converts rust operators to equivalent GCC tree_code. @@ -1909,13 +1591,12 @@ is_floating_point (tree t) } // Return an expression for the negation operation OP EXPR. -Bexpression * -Gcc_backend::negation_expression (NegationOperator op, Bexpression *expr, +tree +Gcc_backend::negation_expression (NegationOperator op, tree expr_tree, Location location) { /* Check if the expression is an error, in which case we return an error expression. */ - auto expr_tree = expr->get_tree (); if (expr_tree == error_mark_node || TREE_TYPE (expr_tree) == error_mark_node) return this->error_expression (); @@ -1944,20 +1625,17 @@ Gcc_backend::negation_expression (NegationOperator op, Bexpression *expr, tree_type, expr_tree); if (floating_point && extended_type != NULL_TREE) new_tree = convert (original_type, expr_tree); - return this->make_expression (new_tree); + return new_tree; } // Return an expression for the arithmetic or logical operation LEFT OP RIGHT. -Bexpression * +tree Gcc_backend::arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, - Bexpression *left, - Bexpression *right, + tree left_tree, tree right_tree, Location location) { /* Check if either expression is an error, in which case we return an error expression. */ - auto left_tree = left->get_tree (); - auto right_tree = right->get_tree (); if (left_tree == error_mark_node || right_tree == error_mark_node) return this->error_expression (); @@ -1990,18 +1668,16 @@ Gcc_backend::arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree_type, left_tree, right_tree); if (floating_point && extended_type != NULL_TREE) new_tree = convert (original_type, new_tree); - return this->make_expression (new_tree); + return new_tree; } // Return an expression for the comparison operation LEFT OP RIGHT. -Bexpression * -Gcc_backend::comparison_expression (ComparisonOperator op, Bexpression *left, - Bexpression *right, Location location) +tree +Gcc_backend::comparison_expression (ComparisonOperator op, tree left_tree, + tree right_tree, Location location) { /* Check if either expression is an error, in which case we return an error expression. */ - auto left_tree = left->get_tree (); - auto right_tree = right->get_tree (); if (left_tree == error_mark_node || right_tree == error_mark_node) return this->error_expression (); @@ -2012,18 +1688,16 @@ Gcc_backend::comparison_expression (ComparisonOperator op, Bexpression *left, /* Construct a new tree and build an expression from it. */ auto new_tree = fold_build2_loc (location.gcc_location (), tree_code, tree_type, left_tree, right_tree); - return this->make_expression (new_tree); + return new_tree; } // Return an expression for the lazy boolean operation LEFT OP RIGHT. -Bexpression * -Gcc_backend::lazy_boolean_expression (LazyBooleanOperator op, Bexpression *left, - Bexpression *right, Location location) +tree +Gcc_backend::lazy_boolean_expression (LazyBooleanOperator op, tree left_tree, + tree right_tree, Location location) { /* Check if either expression is an error, in which case we return an error expression. */ - auto left_tree = left->get_tree (); - auto right_tree = right->get_tree (); if (left_tree == error_mark_node || right_tree == error_mark_node) return this->error_expression (); @@ -2035,17 +1709,16 @@ Gcc_backend::lazy_boolean_expression (LazyBooleanOperator op, Bexpression *left, /* Construct a new tree and build an expression from it. */ auto new_tree = fold_build2_loc (location.gcc_location (), tree_code, tree_type, left_tree, right_tree); - return this->make_expression (new_tree); + return new_tree; } // Return an expression that constructs BTYPE with VALS. -Bexpression * -Gcc_backend::constructor_expression (Btype *btype, - const std::vector<Bexpression *> &vals, +tree +Gcc_backend::constructor_expression (tree type_tree, + const std::vector<tree> &vals, int union_index, Location location) { - tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) return this->error_expression (); @@ -2058,7 +1731,7 @@ Gcc_backend::constructor_expression (Btype *btype, if (union_index != -1) { gcc_assert (TREE_CODE (type_tree) == UNION_TYPE); - tree val = vals.front ()->get_tree (); + tree val = vals.front (); for (int i = 0; i < union_index; i++) { gcc_assert (field != NULL_TREE); @@ -2090,11 +1763,11 @@ Gcc_backend::constructor_expression (Btype *btype, else { gcc_assert (TREE_CODE (type_tree) == RECORD_TYPE); - for (std::vector<Bexpression *>::const_iterator p = vals.begin (); + for (std::vector<tree>::const_iterator p = vals.begin (); p != vals.end (); ++p, field = DECL_CHAIN (field)) { gcc_assert (field != NULL_TREE); - tree val = (*p)->get_tree (); + tree val = (*p); if (TREE_TYPE (field) == error_mark_node || val == error_mark_node || TREE_TYPE (val) == error_mark_node) return this->error_expression (); @@ -2125,15 +1798,14 @@ Gcc_backend::constructor_expression (Btype *btype, if (sink != NULL_TREE) ret = fold_build2_loc (location.gcc_location (), COMPOUND_EXPR, type_tree, sink, ret); - return this->make_expression (ret); + return ret; } -Bexpression * +tree Gcc_backend::array_constructor_expression ( - Btype *array_btype, const std::vector<unsigned long> &indexes, - const std::vector<Bexpression *> &vals, Location location) + tree type_tree, const std::vector<unsigned long> &indexes, + const std::vector<tree> &vals, Location location) { - tree type_tree = array_btype->get_tree (); if (type_tree == error_mark_node) return this->error_expression (); @@ -2149,7 +1821,7 @@ Gcc_backend::array_constructor_expression ( for (size_t i = 0; i < vals.size (); ++i) { tree index = size_int (indexes[i]); - tree val = (vals[i])->get_tree (); + tree val = vals[i]; if (index == error_mark_node || val == error_mark_node) return this->error_expression (); @@ -2179,17 +1851,15 @@ Gcc_backend::array_constructor_expression ( if (sink != NULL_TREE) ret = fold_build2_loc (location.gcc_location (), COMPOUND_EXPR, type_tree, sink, ret); - return this->make_expression (ret); + return ret; } // Return an expression for the address of BASE[INDEX]. -Bexpression * -Gcc_backend::pointer_offset_expression (Bexpression *base, Bexpression *index, +tree +Gcc_backend::pointer_offset_expression (tree base_tree, tree index_tree, Location location) { - tree base_tree = base->get_tree (); - tree index_tree = index->get_tree (); tree element_type_tree = TREE_TYPE (TREE_TYPE (base_tree)); if (base_tree == error_mark_node || TREE_TYPE (base_tree) == error_mark_node || index_tree == error_mark_node || element_type_tree == error_mark_node) @@ -2202,17 +1872,15 @@ Gcc_backend::pointer_offset_expression (Bexpression *base, Bexpression *index, index_tree, element_size); tree ptr = fold_build2_loc (location.gcc_location (), POINTER_PLUS_EXPR, TREE_TYPE (base_tree), base_tree, offset); - return this->make_expression (ptr); + return ptr; } // Return an expression representing ARRAY[INDEX] -Bexpression * -Gcc_backend::array_index_expression (Bexpression *array, Bexpression *index, +tree +Gcc_backend::array_index_expression (tree array_tree, tree index_tree, Location location) { - tree array_tree = array->get_tree (); - tree index_tree = index->get_tree (); if (array_tree == error_mark_node || TREE_TYPE (array_tree) == error_mark_node || index_tree == error_mark_node) return this->error_expression (); @@ -2229,17 +1897,15 @@ Gcc_backend::array_index_expression (Bexpression *array, Bexpression *index, ret = fold_build2_loc (location.gcc_location (), COMPOUND_EXPR, void_type_node, array_tree, index_tree); - return this->make_expression (ret); + return ret; } // Create an expression for a call to FN_EXPR with FN_ARGS. -Bexpression * -Gcc_backend::call_expression (Bfunction *, // containing fcn for call - Bexpression *fn_expr, - const std::vector<Bexpression *> &fn_args, - Bexpression *chain_expr, Location location) +tree +Gcc_backend::call_expression (tree, // containing fcn for call + tree fn, const std::vector<tree> &fn_args, + tree chain_expr, Location location) { - tree fn = fn_expr->get_tree (); if (fn == error_mark_node || TREE_TYPE (fn) == error_mark_node) return this->error_expression (); @@ -2250,7 +1916,7 @@ Gcc_backend::call_expression (Bfunction *, // containing fcn for call tree *args = nargs == 0 ? NULL : new tree[nargs]; for (size_t i = 0; i < nargs; ++i) { - args[i] = fn_args.at (i)->get_tree (); + args[i] = fn_args.at (i); if (args[i] == error_mark_node) return this->error_expression (); } @@ -2296,7 +1962,7 @@ Gcc_backend::call_expression (Bfunction *, // containing fcn for call fn, nargs, args); if (chain_expr) - CALL_EXPR_STATIC_CHAIN (ret) = chain_expr->get_tree (); + CALL_EXPR_STATIC_CHAIN (ret) = chain_expr; if (excess_type != NULL_TREE) { @@ -2306,24 +1972,23 @@ Gcc_backend::call_expression (Bfunction *, // containing fcn for call } delete[] args; - return this->make_expression (ret); + return ret; } // An expression as a statement. -Bstatement * -Gcc_backend::expression_statement (Bfunction *, Bexpression *expr) +tree +Gcc_backend::expression_statement (tree, tree expr) { - return this->make_statement (expr->get_tree ()); + return expr; } // Variable initialization. -Bstatement * -Gcc_backend::init_statement (Bfunction *, Bvariable *var, Bexpression *init) +tree +Gcc_backend::init_statement (tree, Bvariable *var, tree init_tree) { tree var_tree = var->get_decl (); - tree init_tree = init->get_tree (); if (var_tree == error_mark_node || init_tree == error_mark_node) return this->error_statement (); gcc_assert (TREE_CODE (var_tree) == VAR_DECL); @@ -2347,18 +2012,16 @@ Gcc_backend::init_statement (Bfunction *, Bvariable *var, Bexpression *init) ret = build2_loc (DECL_SOURCE_LOCATION (var_tree), COMPOUND_EXPR, void_type_node, init_tree, ret); - return this->make_statement (ret); + return ret; } // Assignment. -Bstatement * -Gcc_backend::assignment_statement (Bfunction *bfn, Bexpression *lhs, - Bexpression *rhs, Location location) +tree +Gcc_backend::assignment_statement (tree bfn, tree lhs, tree rhs, + Location location) { - tree lhs_tree = lhs->get_tree (); - tree rhs_tree = rhs->get_tree (); - if (lhs_tree == error_mark_node || rhs_tree == error_mark_node) + if (lhs == error_mark_node || rhs == error_mark_node) return this->error_statement (); // To avoid problems with GNU ld, we don't make zero-sized @@ -2367,28 +2030,25 @@ Gcc_backend::assignment_statement (Bfunction *bfn, Bexpression *lhs, // expression; avoid crashes here by avoiding assignments of // zero-sized expressions. Such assignments don't really mean // anything anyhow. - if (TREE_TYPE (lhs_tree) == void_type_node - || int_size_in_bytes (TREE_TYPE (lhs_tree)) == 0 - || TREE_TYPE (rhs_tree) == void_type_node - || int_size_in_bytes (TREE_TYPE (rhs_tree)) == 0) + if (TREE_TYPE (lhs) == void_type_node + || int_size_in_bytes (TREE_TYPE (lhs)) == 0 + || TREE_TYPE (rhs) == void_type_node + || int_size_in_bytes (TREE_TYPE (rhs)) == 0) return this->compound_statement (this->expression_statement (bfn, lhs), this->expression_statement (bfn, rhs)); - rhs_tree = this->convert_tree (TREE_TYPE (lhs_tree), rhs_tree, location); + rhs = this->convert_tree (TREE_TYPE (lhs), rhs, location); - return this->make_statement (fold_build2_loc (location.gcc_location (), - MODIFY_EXPR, void_type_node, - lhs_tree, rhs_tree)); + return fold_build2_loc (location.gcc_location (), MODIFY_EXPR, void_type_node, + lhs, rhs); } // Return. -Bstatement * -Gcc_backend::return_statement (Bfunction *bfunction, - const std::vector<Bexpression *> &vals, +tree +Gcc_backend::return_statement (tree fntree, const std::vector<tree> &vals, Location location) { - tree fntree = bfunction->get_tree (); if (fntree == error_mark_node) return this->error_statement (); tree result = DECL_RESULT (fntree); @@ -2402,10 +2062,10 @@ Gcc_backend::return_statement (Bfunction *bfunction, if (res_type == void_type_node || int_size_in_bytes (res_type) == 0) { tree stmt_list = NULL_TREE; - for (std::vector<Bexpression *>::const_iterator p = vals.begin (); + for (std::vector<tree>::const_iterator p = vals.begin (); p != vals.end (); p++) { - tree val = (*p)->get_tree (); + tree val = (*p); if (val == error_mark_node) return this->error_statement (); append_to_statement_list (val, &stmt_list); @@ -2413,7 +2073,7 @@ Gcc_backend::return_statement (Bfunction *bfunction, tree ret = fold_build1_loc (location.gcc_location (), RETURN_EXPR, void_type_node, NULL_TREE); append_to_statement_list (ret, &stmt_list); - return this->make_statement (stmt_list); + return stmt_list; } tree ret; @@ -2422,12 +2082,11 @@ Gcc_backend::return_statement (Bfunction *bfunction, void_type_node, NULL_TREE); else if (vals.size () == 1) { - tree val = vals.front ()->get_tree (); + tree val = vals.front (); if (val == error_mark_node) return this->error_statement (); - tree set - = fold_build2_loc (location.gcc_location (), MODIFY_EXPR, - void_type_node, result, vals.front ()->get_tree ()); + tree set = fold_build2_loc (location.gcc_location (), MODIFY_EXPR, + void_type_node, result, vals.front ()); ret = fold_build1_loc (location.gcc_location (), RETURN_EXPR, void_type_node, set); } @@ -2448,18 +2107,18 @@ Gcc_backend::return_statement (Bfunction *bfunction, pop_cfun (); tree field = TYPE_FIELDS (rettype); - for (std::vector<Bexpression *>::const_iterator p = vals.begin (); + for (std::vector<tree>::const_iterator p = vals.begin (); p != vals.end (); p++, field = DECL_CHAIN (field)) { gcc_assert (field != NULL_TREE); tree ref = fold_build3_loc (location.gcc_location (), COMPONENT_REF, TREE_TYPE (field), rettmp, field, NULL_TREE); - tree val = (*p)->get_tree (); + tree val = (*p); if (val == error_mark_node) return this->error_statement (); tree set = fold_build2_loc (location.gcc_location (), MODIFY_EXPR, - void_type_node, ref, (*p)->get_tree ()); + void_type_node, ref, (*p)); append_to_statement_list (set, &stmt_list); } gcc_assert (field == NULL_TREE); @@ -2470,7 +2129,7 @@ Gcc_backend::return_statement (Bfunction *bfunction, append_to_statement_list (ret_expr, &stmt_list); ret = stmt_list; } - return this->make_statement (ret); + return ret; } // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if an @@ -2479,116 +2138,101 @@ Gcc_backend::return_statement (Bfunction *bfunction, // functions. In C++, the resulting code is of this form: // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; } -Bstatement * -Gcc_backend::exception_handler_statement (Bstatement *bstat, - Bstatement *except_stmt, - Bstatement *finally_stmt, - Location location) +tree +Gcc_backend::exception_handler_statement (tree try_stmt, tree except_stmt, + tree finally_stmt, Location location) { - tree stat_tree = bstat->get_tree (); - tree except_tree = except_stmt == NULL ? NULL_TREE : except_stmt->get_tree (); - tree finally_tree - = finally_stmt == NULL ? NULL_TREE : finally_stmt->get_tree (); - - if (stat_tree == error_mark_node || except_tree == error_mark_node - || finally_tree == error_mark_node) + if (try_stmt == error_mark_node || except_stmt == error_mark_node + || finally_stmt == error_mark_node) return this->error_statement (); - if (except_tree != NULL_TREE) - stat_tree = build2_loc (location.gcc_location (), TRY_CATCH_EXPR, - void_type_node, stat_tree, - build2_loc (location.gcc_location (), CATCH_EXPR, - void_type_node, NULL, except_tree)); - if (finally_tree != NULL_TREE) - stat_tree = build2_loc (location.gcc_location (), TRY_FINALLY_EXPR, - void_type_node, stat_tree, finally_tree); - return this->make_statement (stat_tree); + if (except_stmt != NULL_TREE) + try_stmt = build2_loc (location.gcc_location (), TRY_CATCH_EXPR, + void_type_node, try_stmt, + build2_loc (location.gcc_location (), CATCH_EXPR, + void_type_node, NULL, except_stmt)); + if (finally_stmt != NULL_TREE) + try_stmt = build2_loc (location.gcc_location (), TRY_FINALLY_EXPR, + void_type_node, try_stmt, finally_stmt); + return try_stmt; } // If. -Bstatement * -Gcc_backend::if_statement (Bfunction *, Bexpression *condition, - Bblock *then_block, Bblock *else_block, +tree +Gcc_backend::if_statement (tree, tree cond_tree, tree then_tree, tree else_tree, Location location) { - tree cond_tree = condition->get_tree (); - tree then_tree = then_block->get_tree (); - tree else_tree = else_block == NULL ? NULL_TREE : else_block->get_tree (); if (cond_tree == error_mark_node || then_tree == error_mark_node || else_tree == error_mark_node) return this->error_statement (); tree ret = build3_loc (location.gcc_location (), COND_EXPR, void_type_node, cond_tree, then_tree, else_tree); - return this->make_statement (ret); + return ret; } // Loops -Bexpression * -Gcc_backend::loop_expression (Bblock *body, Location locus) +tree +Gcc_backend::loop_expression (tree body, Location locus) { - tree loop_expr_tree = fold_build1_loc (locus.gcc_location (), LOOP_EXPR, - void_type_node, body->get_tree ()); - return this->make_expression (loop_expr_tree); + return fold_build1_loc (locus.gcc_location (), LOOP_EXPR, void_type_node, + body); } -Bexpression * -Gcc_backend::exit_expression (Bexpression *condition, Location locus) +tree +Gcc_backend::exit_expression (tree cond_tree, Location locus) { - tree cond_tree = condition->get_tree (); - tree exit_expr_tree = fold_build1_loc (locus.gcc_location (), EXIT_EXPR, - void_type_node, cond_tree); - return this->make_expression (exit_expr_tree); + return fold_build1_loc (locus.gcc_location (), EXIT_EXPR, void_type_node, + cond_tree); } // Switch. -Bstatement * -Gcc_backend::switch_statement ( - Bfunction *function, Bexpression *value, - const std::vector<std::vector<Bexpression *> > &cases, - const std::vector<Bstatement *> &statements, Location switch_location) +tree +Gcc_backend::switch_statement (tree decl, tree value, + const std::vector<std::vector<tree>> &cases, + const std::vector<tree> &statements, + Location switch_location) { gcc_assert (cases.size () == statements.size ()); - tree decl = function->get_tree (); if (DECL_STRUCT_FUNCTION (decl) == NULL) push_struct_function (decl); else push_cfun (DECL_STRUCT_FUNCTION (decl)); tree stmt_list = NULL_TREE; - std::vector<std::vector<Bexpression *> >::const_iterator pc = cases.begin (); - for (std::vector<Bstatement *>::const_iterator ps = statements.begin (); + std::vector<std::vector<tree>>::const_iterator pc = cases.begin (); + for (std::vector<tree>::const_iterator ps = statements.begin (); ps != statements.end (); ++ps, ++pc) { if (pc->empty ()) { - location_t loc = (*ps != NULL ? EXPR_LOCATION ((*ps)->get_tree ()) - : UNKNOWN_LOCATION); + location_t loc + = (*ps != NULL ? EXPR_LOCATION (*ps) : UNKNOWN_LOCATION); tree label = create_artificial_label (loc); tree c = build_case_label (NULL_TREE, NULL_TREE, label); append_to_statement_list (c, &stmt_list); } else { - for (std::vector<Bexpression *>::const_iterator pcv = pc->begin (); + for (std::vector<tree>::const_iterator pcv = pc->begin (); pcv != pc->end (); ++pcv) { - tree t = (*pcv)->get_tree (); + tree t = (*pcv); if (t == error_mark_node) return this->error_statement (); location_t loc = EXPR_LOCATION (t); tree label = create_artificial_label (loc); - tree c = build_case_label ((*pcv)->get_tree (), NULL_TREE, label); + tree c = build_case_label ((*pcv), NULL_TREE, label); append_to_statement_list (c, &stmt_list); } } if (*ps != NULL) { - tree t = (*ps)->get_tree (); + tree t = (*ps); if (t == error_mark_node) return this->error_statement (); append_to_statement_list (t, &stmt_list); @@ -2596,25 +2240,25 @@ Gcc_backend::switch_statement ( } pop_cfun (); - tree tv = value->get_tree (); + tree tv = value; if (tv == error_mark_node) return this->error_statement (); tree t = build2_loc (switch_location.gcc_location (), SWITCH_EXPR, NULL_TREE, tv, stmt_list); - return this->make_statement (t); + return t; } // Pair of statements. -Bstatement * -Gcc_backend::compound_statement (Bstatement *s1, Bstatement *s2) +tree +Gcc_backend::compound_statement (tree s1, tree s2) { tree stmt_list = NULL_TREE; - tree t = s1->get_tree (); + tree t = s1; if (t == error_mark_node) return this->error_statement (); append_to_statement_list (t, &stmt_list); - t = s2->get_tree (); + t = s2; if (t == error_mark_node) return this->error_statement (); append_to_statement_list (t, &stmt_list); @@ -2624,24 +2268,24 @@ Gcc_backend::compound_statement (Bstatement *s1, Bstatement *s2) if (stmt_list == NULL_TREE) stmt_list = integer_zero_node; - return this->make_statement (stmt_list); + return stmt_list; } // List of statements. -Bstatement * -Gcc_backend::statement_list (const std::vector<Bstatement *> &statements) +tree +Gcc_backend::statement_list (const std::vector<tree> &statements) { tree stmt_list = NULL_TREE; - for (std::vector<Bstatement *>::const_iterator p = statements.begin (); + for (std::vector<tree>::const_iterator p = statements.begin (); p != statements.end (); ++p) { - tree t = (*p)->get_tree (); + tree t = (*p); if (t == error_mark_node) return this->error_statement (); append_to_statement_list (t, &stmt_list); } - return this->make_statement (stmt_list); + return stmt_list; } // Make a block. For some reason gcc uses a dual structure for @@ -2649,15 +2293,14 @@ Gcc_backend::statement_list (const std::vector<Bstatement *> &statements) // BIND_EXPR node points to the BLOCK node, we store the BIND_EXPR in // the Bblock. -Bblock * -Gcc_backend::block (Bfunction *function, Bblock *enclosing, +tree +Gcc_backend::block (tree fndecl, tree enclosing, const std::vector<Bvariable *> &vars, Location start_location, Location) { tree block_tree = make_node (BLOCK); if (enclosing == NULL) { - tree fndecl = function->get_tree (); gcc_assert (fndecl != NULL_TREE); // We may have already created a block for local variables when @@ -2680,8 +2323,7 @@ Gcc_backend::block (Bfunction *function, Bblock *enclosing, } else { - tree superbind_tree = enclosing->get_tree (); - tree superblock_tree = BIND_EXPR_BLOCK (superbind_tree); + tree superblock_tree = BIND_EXPR_BLOCK (enclosing); gcc_assert (TREE_CODE (superblock_tree) == BLOCK); BLOCK_SUPERCONTEXT (block_tree) = superblock_tree; @@ -2708,37 +2350,35 @@ Gcc_backend::block (Bfunction *function, Bblock *enclosing, = build3_loc (start_location.gcc_location (), BIND_EXPR, void_type_node, BLOCK_VARS (block_tree), NULL_TREE, block_tree); TREE_SIDE_EFFECTS (bind_tree) = 1; - return new Bblock (bind_tree); + return bind_tree; } // Add statements to a block. void -Gcc_backend::block_add_statements (Bblock *bblock, - const std::vector<Bstatement *> &statements) +Gcc_backend::block_add_statements (tree bind_tree, + const std::vector<tree> &statements) { tree stmt_list = NULL_TREE; - for (std::vector<Bstatement *>::const_iterator p = statements.begin (); + for (std::vector<tree>::const_iterator p = statements.begin (); p != statements.end (); ++p) { - tree s = (*p)->get_tree (); + tree s = (*p); if (s != error_mark_node) append_to_statement_list (s, &stmt_list); } - tree bind_tree = bblock->get_tree (); gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR); BIND_EXPR_BODY (bind_tree) = stmt_list; } // Return a block as a statement. -Bstatement * -Gcc_backend::block_statement (Bblock *bblock) +tree +Gcc_backend::block_statement (tree bind_tree) { - tree bind_tree = bblock->get_tree (); gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR); - return this->make_statement (bind_tree); + return bind_tree; } // This is not static because we declare it with GTY(()) in rust-c.h. @@ -2839,11 +2479,10 @@ Gcc_backend::convert_tree (tree type_tree, tree expr_tree, Location location) Bvariable * Gcc_backend::global_variable (const std::string &var_name, - const std::string &asm_name, Btype *btype, + const std::string &asm_name, tree type_tree, bool is_external, bool is_hidden, bool in_unique_section, Location location) { - tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) return this->error_variable (); @@ -2881,9 +2520,8 @@ Gcc_backend::global_variable (const std::string &var_name, // Set the initial value of a global variable. void -Gcc_backend::global_variable_set_init (Bvariable *var, Bexpression *expr) +Gcc_backend::global_variable_set_init (Bvariable *var, tree expr_tree) { - tree expr_tree = expr->get_tree (); if (expr_tree == error_mark_node) return; gcc_assert (TREE_CONSTANT (expr_tree)); @@ -2906,16 +2544,15 @@ Gcc_backend::global_variable_set_init (Bvariable *var, Bexpression *expr) // Make a local variable. Bvariable * -Gcc_backend::local_variable (Bfunction *function, const std::string &name, - Btype *btype, Bvariable *decl_var, +Gcc_backend::local_variable (tree function, const std::string &name, + tree type_tree, Bvariable *decl_var, bool is_address_taken, Location location) { - tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) return this->error_variable (); tree decl = build_decl (location.gcc_location (), VAR_DECL, get_identifier_from_string (name), type_tree); - DECL_CONTEXT (decl) = function->get_tree (); + DECL_CONTEXT (decl) = function; TREE_USED (decl) = 1; if (is_address_taken) TREE_ADDRESSABLE (decl) = 1; @@ -2931,16 +2568,15 @@ Gcc_backend::local_variable (Bfunction *function, const std::string &name, // Make a function parameter variable. Bvariable * -Gcc_backend::parameter_variable (Bfunction *function, const std::string &name, - Btype *btype, bool is_address_taken, +Gcc_backend::parameter_variable (tree function, const std::string &name, + tree type_tree, bool is_address_taken, Location location) { - tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) return this->error_variable (); tree decl = build_decl (location.gcc_location (), PARM_DECL, get_identifier_from_string (name), type_tree); - DECL_CONTEXT (decl) = function->get_tree (); + DECL_CONTEXT (decl) = function; DECL_ARG_TYPE (decl) = type_tree; TREE_USED (decl) = 1; if (is_address_taken) @@ -2952,16 +2588,13 @@ Gcc_backend::parameter_variable (Bfunction *function, const std::string &name, // Make a static chain variable. Bvariable * -Gcc_backend::static_chain_variable (Bfunction *function, - const std::string &name, Btype *btype, - Location location) +Gcc_backend::static_chain_variable (tree fndecl, const std::string &name, + tree type_tree, Location location) { - tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) return this->error_variable (); tree decl = build_decl (location.gcc_location (), PARM_DECL, get_identifier_from_string (name), type_tree); - tree fndecl = function->get_tree (); DECL_CONTEXT (decl) = fndecl; DECL_ARG_TYPE (decl) = type_tree; TREE_USED (decl) = 1; @@ -2987,17 +2620,13 @@ Gcc_backend::static_chain_variable (Bfunction *function, // Make a temporary variable. Bvariable * -Gcc_backend::temporary_variable (Bfunction *function, Bblock *bblock, - Btype *btype, Bexpression *binit, - bool is_address_taken, Location location, - Bstatement **pstatement) -{ - gcc_assert (function != NULL); - tree decl = function->get_tree (); - tree type_tree = btype->get_tree (); - tree init_tree = binit == NULL ? NULL_TREE : binit->get_tree (); +Gcc_backend::temporary_variable (tree fndecl, tree bind_tree, tree type_tree, + tree init_tree, bool is_address_taken, + Location location, tree *pstatement) +{ + gcc_assert (fndecl != NULL_TREE); if (type_tree == error_mark_node || init_tree == error_mark_node - || decl == error_mark_node) + || fndecl == error_mark_node) { *pstatement = this->error_statement (); return this->error_variable (); @@ -3007,26 +2636,25 @@ Gcc_backend::temporary_variable (Bfunction *function, Bblock *bblock, // We can only use create_tmp_var if the type is not addressable. if (!TREE_ADDRESSABLE (type_tree)) { - if (DECL_STRUCT_FUNCTION (decl) == NULL) - push_struct_function (decl); + if (DECL_STRUCT_FUNCTION (fndecl) == NULL) + push_struct_function (fndecl); else - push_cfun (DECL_STRUCT_FUNCTION (decl)); + push_cfun (DECL_STRUCT_FUNCTION (fndecl)); var = create_tmp_var (type_tree, "RUSTTMP"); pop_cfun (); } else { - gcc_assert (bblock != NULL); + gcc_assert (bind_tree != NULL_TREE); var = build_decl (location.gcc_location (), VAR_DECL, create_tmp_var_name ("RUSTTMP"), type_tree); DECL_ARTIFICIAL (var) = 1; DECL_IGNORED_P (var) = 1; TREE_USED (var) = 1; - DECL_CONTEXT (var) = decl; + DECL_CONTEXT (var) = fndecl; // We have to add this variable to the BLOCK and the BIND_EXPR. - tree bind_tree = bblock->get_tree (); gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR); tree block_tree = BIND_EXPR_BLOCK (bind_tree); gcc_assert (TREE_CODE (block_tree) == BLOCK); @@ -3035,24 +2663,23 @@ Gcc_backend::temporary_variable (Bfunction *function, Bblock *bblock, BIND_EXPR_VARS (bind_tree) = BLOCK_VARS (block_tree); } - if (this->type_size (btype) != 0 && init_tree != NULL_TREE + if (this->type_size (type_tree) != 0 && init_tree != NULL_TREE && TREE_TYPE (init_tree) != void_type_node) DECL_INITIAL (var) = this->convert_tree (type_tree, init_tree, location); if (is_address_taken) TREE_ADDRESSABLE (var) = 1; - *pstatement = this->make_statement ( - build1_loc (location.gcc_location (), DECL_EXPR, void_type_node, var)); + *pstatement + = build1_loc (location.gcc_location (), DECL_EXPR, void_type_node, var); // For a zero sized type, don't initialize VAR with BINIT, but still // evaluate BINIT for its side effects. if (init_tree != NULL_TREE - && (this->type_size (btype) == 0 + && (this->type_size (type_tree) == 0 || TREE_TYPE (init_tree) == void_type_node)) - *pstatement - = this->compound_statement (this->expression_statement (function, binit), - *pstatement); + *pstatement = this->compound_statement ( + this->expression_statement (fndecl, init_tree), *pstatement); return new Bvariable (var); } @@ -3062,11 +2689,10 @@ Gcc_backend::temporary_variable (Bfunction *function, Bblock *bblock, Bvariable * Gcc_backend::implicit_variable (const std::string &name, - const std::string &asm_name, Btype *type, + const std::string &asm_name, tree type_tree, bool is_hidden, bool is_constant, bool is_common, int64_t alignment) { - tree type_tree = type->get_tree (); if (type_tree == error_mark_node) return this->error_variable (); @@ -3117,15 +2743,10 @@ Gcc_backend::implicit_variable (const std::string &name, void Gcc_backend::implicit_variable_set_init (Bvariable *var, const std::string &, - Btype *, bool, bool, bool is_common, - Bexpression *init) + tree, bool, bool, bool is_common, + tree init_tree) { tree decl = var->get_decl (); - tree init_tree; - if (init == NULL) - init_tree = NULL_TREE; - else - init_tree = init->get_tree (); if (decl == error_mark_node || init_tree == error_mark_node) return; @@ -3149,9 +2770,8 @@ Gcc_backend::implicit_variable_set_init (Bvariable *var, const std::string &, Bvariable * Gcc_backend::implicit_variable_reference (const std::string &name, const std::string &asm_name, - Btype *btype) + tree type_tree) { - tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) return this->error_variable (); @@ -3172,9 +2792,9 @@ Gcc_backend::implicit_variable_reference (const std::string &name, Bvariable * Gcc_backend::immutable_struct (const std::string &name, const std::string &asm_name, bool is_hidden, - bool is_common, Btype *btype, Location location) + bool is_common, tree type_tree, + Location location) { - tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) return this->error_variable (); gcc_assert (TREE_CODE (type_tree) == RECORD_TYPE); @@ -3218,11 +2838,10 @@ Gcc_backend::immutable_struct (const std::string &name, void Gcc_backend::immutable_struct_set_init (Bvariable *var, const std::string &, - bool, bool is_common, Btype *, Location, - Bexpression *initializer) + bool, bool is_common, tree, Location, + tree init_tree) { tree decl = var->get_decl (); - tree init_tree = initializer->get_tree (); if (decl == error_mark_node || init_tree == error_mark_node) return; @@ -3249,9 +2868,8 @@ Gcc_backend::immutable_struct_set_init (Bvariable *var, const std::string &, Bvariable * Gcc_backend::immutable_struct_reference (const std::string &name, const std::string &asm_name, - Btype *btype, Location location) + tree type_tree, Location location) { - tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) return this->error_variable (); gcc_assert (TREE_CODE (type_tree) == RECORD_TYPE); @@ -3271,14 +2889,12 @@ Gcc_backend::immutable_struct_reference (const std::string &name, // Make a label. -Blabel * -Gcc_backend::label (Bfunction *function, const std::string &name, - Location location) +tree +Gcc_backend::label (tree func_tree, const std::string &name, Location location) { tree decl; if (name.empty ()) { - tree func_tree = function->get_tree (); if (DECL_STRUCT_FUNCTION (func_tree) == NULL) push_struct_function (func_tree); else @@ -3293,56 +2909,50 @@ Gcc_backend::label (Bfunction *function, const std::string &name, tree id = get_identifier_from_string (name); decl = build_decl (location.gcc_location (), LABEL_DECL, id, void_type_node); - DECL_CONTEXT (decl) = function->get_tree (); + DECL_CONTEXT (decl) = func_tree; } - return new Blabel (decl); + return decl; } // Make a statement which defines a label. -Bstatement * -Gcc_backend::label_definition_statement (Blabel *label) +tree +Gcc_backend::label_definition_statement (tree label) { - tree lab = label->get_tree (); - tree ret = fold_build1_loc (DECL_SOURCE_LOCATION (lab), LABEL_EXPR, - void_type_node, lab); - return this->make_statement (ret); + return fold_build1_loc (DECL_SOURCE_LOCATION (label), LABEL_EXPR, + void_type_node, label); } // Make a goto statement. -Bstatement * -Gcc_backend::goto_statement (Blabel *label, Location location) +tree +Gcc_backend::goto_statement (tree label, Location location) { - tree lab = label->get_tree (); - tree ret = fold_build1_loc (location.gcc_location (), GOTO_EXPR, - void_type_node, lab); - return this->make_statement (ret); + return fold_build1_loc (location.gcc_location (), GOTO_EXPR, void_type_node, + label); } // Get the address of a label. -Bexpression * -Gcc_backend::label_address (Blabel *label, Location location) +tree +Gcc_backend::label_address (tree label, Location location) { - tree lab = label->get_tree (); - TREE_USED (lab) = 1; - TREE_ADDRESSABLE (lab) = 1; + TREE_USED (label) = 1; + TREE_ADDRESSABLE (label) = 1; tree ret = fold_convert_loc (location.gcc_location (), ptr_type_node, build_fold_addr_expr_loc (location.gcc_location (), - lab)); - return this->make_expression (ret); + label)); + return ret; } // Declare or define a new function. -Bfunction * -Gcc_backend::function (Btype *fntype, const std::string &name, +tree +Gcc_backend::function (tree functype, const std::string &name, const std::string &asm_name, unsigned int flags, Location location) { - tree functype = fntype->get_tree (); if (functype != error_mark_node) { gcc_assert (FUNCTION_POINTER_TYPE_P (functype)); @@ -3386,7 +2996,7 @@ Gcc_backend::function (Btype *fntype, const std::string &name, TREE_READONLY (decl) = 1; rust_preserve_from_gc (decl); - return new Bfunction (decl); + return decl; } // Create a statement that runs all deferred calls for FUNCTION. This should @@ -3394,39 +3004,34 @@ Gcc_backend::function (Btype *fntype, const std::string &name, // finish: // try { UNDEFER; } catch { CHECK_DEFER; goto finish; } -Bstatement * -Gcc_backend::function_defer_statement (Bfunction *function, - Bexpression *undefer, Bexpression *defer, - Location location) +tree +Gcc_backend::function_defer_statement (tree function, tree undefer_tree, + tree defer_tree, Location location) { - tree undefer_tree = undefer->get_tree (); - tree defer_tree = defer->get_tree (); - tree fntree = function->get_tree (); - if (undefer_tree == error_mark_node || defer_tree == error_mark_node - || fntree == error_mark_node) + || function == error_mark_node) return this->error_statement (); - if (DECL_STRUCT_FUNCTION (fntree) == NULL) - push_struct_function (fntree); + if (DECL_STRUCT_FUNCTION (function) == NULL) + push_struct_function (function); else - push_cfun (DECL_STRUCT_FUNCTION (fntree)); + push_cfun (DECL_STRUCT_FUNCTION (function)); tree stmt_list = NULL; - Blabel *blabel = this->label (function, "", location); - Bstatement *label_def = this->label_definition_statement (blabel); - append_to_statement_list (label_def->get_tree (), &stmt_list); + tree label = this->label (function, "", location); + tree label_def = this->label_definition_statement (label); + append_to_statement_list (label_def, &stmt_list); - Bstatement *jump_stmt = this->goto_statement (blabel, location); - tree jump = jump_stmt->get_tree (); - tree catch_body = build2 (COMPOUND_EXPR, void_type_node, defer_tree, jump); + tree jump_stmt = this->goto_statement (label, location); + tree catch_body + = build2 (COMPOUND_EXPR, void_type_node, defer_tree, jump_stmt); catch_body = build2 (CATCH_EXPR, void_type_node, NULL, catch_body); tree try_catch = build2 (TRY_CATCH_EXPR, void_type_node, undefer_tree, catch_body); append_to_statement_list (try_catch, &stmt_list); pop_cfun (); - return this->make_statement (stmt_list); + return stmt_list; } // Record PARAM_VARS as the variables to use for the parameters of FUNCTION. @@ -3434,10 +3039,9 @@ Gcc_backend::function_defer_statement (Bfunction *function, bool Gcc_backend::function_set_parameters ( - Bfunction *function, const std::vector<Bvariable *> ¶m_vars) + tree function, const std::vector<Bvariable *> ¶m_vars) { - tree func_tree = function->get_tree (); - if (func_tree == error_mark_node) + if (function == error_mark_node) return false; tree params = NULL_TREE; @@ -3450,28 +3054,25 @@ Gcc_backend::function_set_parameters ( pp = &DECL_CHAIN (*pp); } *pp = NULL_TREE; - DECL_ARGUMENTS (func_tree) = params; + DECL_ARGUMENTS (function) = params; return true; } // Set the function body for FUNCTION using the code in CODE_BLOCK. bool -Gcc_backend::function_set_body (Bfunction *function, Bstatement *code_stmt) +Gcc_backend::function_set_body (tree function, tree code_stmt) { - tree func_tree = function->get_tree (); - tree code = code_stmt->get_tree (); - - if (func_tree == error_mark_node || code == error_mark_node) + if (function == error_mark_node || code_stmt == error_mark_node) return false; - DECL_SAVED_TREE (func_tree) = code; + DECL_SAVED_TREE (function) = code_stmt; return true; } // Look up a named built-in function in the current backend implementation. // Returns NULL if no built-in function by that name exists. -Bfunction * +tree Gcc_backend::lookup_gcc_builtin (const std::string &name) { if (this->builtin_functions_.count (name) != 0) @@ -3479,7 +3080,7 @@ Gcc_backend::lookup_gcc_builtin (const std::string &name) return NULL; } -Bfunction * +tree Gcc_backend::lookup_builtin_by_rust_name (const std::string &name) { auto it = rust_intrinsic_to_gcc_builtin.find (name); @@ -3495,9 +3096,8 @@ Gcc_backend::lookup_builtin_by_rust_name (const std::string &name) void Gcc_backend::write_global_definitions ( - const std::vector<Btype *> &type_decls, - const std::vector<Bexpression *> &constant_decls, - const std::vector<Bfunction *> &function_decls, + const std::vector<tree> &type_decls, const std::vector<tree> &constant_decls, + const std::vector<tree> &function_decls, const std::vector<Bvariable *> &variable_decls) { size_t count_definitions = type_decls.size () + constant_decls.size () @@ -3519,10 +3119,10 @@ Gcc_backend::write_global_definitions ( } } - for (std::vector<Btype *>::const_iterator p = type_decls.begin (); + for (std::vector<tree>::const_iterator p = type_decls.begin (); p != type_decls.end (); ++p) { - tree type_tree = (*p)->get_tree (); + tree type_tree = (*p); if (type_tree != error_mark_node && IS_TYPE_OR_DECL_P (type_tree)) { defs[i] = TYPE_NAME (type_tree); @@ -3531,20 +3131,20 @@ Gcc_backend::write_global_definitions ( ++i; } } - for (std::vector<Bexpression *>::const_iterator p = constant_decls.begin (); + for (std::vector<tree>::const_iterator p = constant_decls.begin (); p != constant_decls.end (); ++p) { - if ((*p)->get_tree () != error_mark_node) + if ((*p) != error_mark_node) { - defs[i] = (*p)->get_tree (); + defs[i] = (*p); rust_preserve_from_gc (defs[i]); ++i; } } - for (std::vector<Bfunction *>::const_iterator p = function_decls.begin (); + for (std::vector<tree>::const_iterator p = function_decls.begin (); p != function_decls.end (); ++p) { - tree decl = (*p)->get_tree (); + tree decl = (*p); if (decl != error_mark_node) { rust_preserve_from_gc (decl); @@ -3592,7 +3192,7 @@ Gcc_backend::define_builtin (const std::string rust_name, if ((flags & builtin_novops) != 0) DECL_IS_NOVOPS (decl) = 1; set_builtin_decl (bcode, decl, true); - this->builtin_functions_[name] = this->make_function (decl); + this->builtin_functions_[name] = decl; if (libname != NULL) { decl = add_builtin_function (libname, fntype, bcode, BUILT_IN_NORMAL, @@ -3603,7 +3203,7 @@ Gcc_backend::define_builtin (const std::string rust_name, TREE_THIS_VOLATILE (decl) = 1; if ((flags & builtin_novops) != 0) DECL_IS_NOVOPS (decl) = 1; - this->builtin_functions_[libname] = this->make_function (decl); + this->builtin_functions_[libname] = decl; } rust_intrinsic_to_gcc_builtin[rust_name] = name; diff --git a/gcc/rust/typecheck/rust-autoderef.h b/gcc/rust/typecheck/rust-autoderef.h index a4799ec..db34755 100644 --- a/gcc/rust/typecheck/rust-autoderef.h +++ b/gcc/rust/typecheck/rust-autoderef.h @@ -68,6 +68,47 @@ private: const TyTy::BaseType *expected; }; +class Adjuster +{ +public: + Adjuster (const TyTy::BaseType *ty) : base (ty) {} + + TyTy::BaseType *adjust_type (std::vector<Adjustment> adjustments) + { + TyTy::BaseType *ty = base->clone (); + for (auto &adjustment : adjustments) + { + switch (adjustment.get_type ()) + { + case Resolver::Adjustment::AdjustmentType::IMM_REF: + ty = new TyTy::ReferenceType (ty->get_ref (), + TyTy::TyVar (ty->get_ref ()), + Mutability::Imm); + break; + + case Resolver::Adjustment::AdjustmentType::MUT_REF: + ty = new TyTy::ReferenceType (ty->get_ref (), + TyTy::TyVar (ty->get_ref ()), + Mutability::Mut); + break; + + case Resolver::Adjustment::AdjustmentType::DEREF_REF: + // FIXME this really needs to support deref lang-item operator + // overloads + rust_assert (ty->get_kind () == TyTy::TypeKind::REF); + const TyTy::ReferenceType *rr + = static_cast<const TyTy::ReferenceType *> (ty); + ty = rr->get_base (); + break; + } + } + return ty; + } + +private: + const TyTy::BaseType *base; +}; + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-const-fold-base.h b/gcc/rust/typecheck/rust-hir-const-fold-base.h index 9cbf1ab..0b41053 100644 --- a/gcc/rust/typecheck/rust-hir-const-fold-base.h +++ b/gcc/rust/typecheck/rust-hir-const-fold-base.h @@ -56,7 +56,7 @@ public: virtual void visit (HIR::LazyBooleanExpr &) override {} virtual void visit (HIR::TypeCastExpr &) override {} virtual void visit (HIR::AssignmentExpr &) override {} - + virtual void visit (HIR::CompoundAssignmentExpr &) override {} virtual void visit (HIR::GroupedExpr &) override {} virtual void visit (HIR::ArrayElemsValues &) override {} diff --git a/gcc/rust/typecheck/rust-hir-const-fold-ctx.h b/gcc/rust/typecheck/rust-hir-const-fold-ctx.h index d330ac8..a3f5a16 100644 --- a/gcc/rust/typecheck/rust-hir-const-fold-ctx.h +++ b/gcc/rust/typecheck/rust-hir-const-fold-ctx.h @@ -36,15 +36,15 @@ public: ::Backend *get_backend () { return backend; } - bool lookup_const (HirId id, Bexpression **expr); + bool lookup_const (HirId id, tree *expr); - void insert_const (HirId, Bexpression *expr); + void insert_const (HirId, tree expr); private: Context (::Backend *backend); ::Backend *backend; - std::map<HirId, Bexpression *> ctx; + std::map<HirId, tree> ctx; }; } // namespace ConstFold diff --git a/gcc/rust/typecheck/rust-hir-const-fold.cc b/gcc/rust/typecheck/rust-hir-const-fold.cc index a2dd03f..6acedd1 100644 --- a/gcc/rust/typecheck/rust-hir-const-fold.cc +++ b/gcc/rust/typecheck/rust-hir-const-fold.cc @@ -41,7 +41,7 @@ Context::get () } bool -Context::lookup_const (HirId id, Bexpression **expr) +Context::lookup_const (HirId id, tree *expr) { auto it = ctx.find (id); if (it == ctx.end ()) @@ -52,7 +52,7 @@ Context::lookup_const (HirId id, Bexpression **expr) } void -Context::insert_const (HirId id, Bexpression *expr) +Context::insert_const (HirId id, tree expr) { rust_assert (ctx.find (id) == ctx.end ()); ctx[id] = expr; @@ -75,7 +75,7 @@ ConstFoldArrayElems::visit (HIR::ArrayElemsValues &elems) { unsigned long index = 0; std::vector<unsigned long> indices; - std::vector<Bexpression *> values; + std::vector<tree> values; TyTy::BaseType *tyty = nullptr; if (!tyctx->lookup_type (expr.get_mappings ().get_hirid (), &tyty)) @@ -85,7 +85,7 @@ ConstFoldArrayElems::visit (HIR::ArrayElemsValues &elems) return; } - Btype *btype = ConstFoldType::fold (tyty, ctx->get_backend ()); + tree type = ConstFoldType::fold (tyty, ctx->get_backend ()); for (auto &value : elems.get_values ()) { @@ -94,7 +94,7 @@ ConstFoldArrayElems::visit (HIR::ArrayElemsValues &elems) } folded - = ctx->get_backend ()->array_constructor_expression (btype, indices, values, + = ctx->get_backend ()->array_constructor_expression (type, indices, values, expr.get_locus ()); } @@ -102,7 +102,7 @@ void ConstFoldArrayElems::visit (HIR::ArrayElemsCopied &elems) { std::vector<unsigned long> indices; - std::vector<Bexpression *> values; + std::vector<tree> values; TyTy::BaseType *tyty = nullptr; if (!tyctx->lookup_type (expr.get_mappings ().get_hirid (), &tyty)) @@ -112,12 +112,12 @@ ConstFoldArrayElems::visit (HIR::ArrayElemsCopied &elems) return; } - Btype *btype = ConstFoldType::fold (tyty, ctx->get_backend ()); - Bexpression *elem = ConstFoldExpr::fold (elems.get_elem_to_copy ()); + tree type = ConstFoldType::fold (tyty, ctx->get_backend ()); + tree elem = ConstFoldExpr::fold (elems.get_elem_to_copy ()); // num copies expr was already folded in rust-hir-type-check-expr; lookup the // earlier result - Bexpression *num_copies_expr = ctx->get_backend ()->error_expression (); + tree num_copies_expr = ctx->get_backend ()->error_expression (); ctx->lookup_const (elems.get_num_copies_expr ()->get_mappings ().get_hirid (), &num_copies_expr); @@ -132,7 +132,7 @@ ConstFoldArrayElems::visit (HIR::ArrayElemsCopied &elems) } folded - = ctx->get_backend ()->array_constructor_expression (btype, indices, values, + = ctx->get_backend ()->array_constructor_expression (type, indices, values, expr.get_locus ()); } diff --git a/gcc/rust/typecheck/rust-hir-const-fold.h b/gcc/rust/typecheck/rust-hir-const-fold.h index 2bf0f2c..c965e25 100644 --- a/gcc/rust/typecheck/rust-hir-const-fold.h +++ b/gcc/rust/typecheck/rust-hir-const-fold.h @@ -28,7 +28,7 @@ namespace ConstFold { class ConstFoldType : public TyTy::TyVisitor { public: - static Btype *fold (TyTy::BaseType *type, ::Backend *backend) + static tree fold (TyTy::BaseType *type, ::Backend *backend) { ConstFoldType folder (backend); type->accept_vis (folder); @@ -43,13 +43,37 @@ public: void visit (TyTy::ArrayType &type) override { - Btype *element_ty = ConstFoldType::fold (type.get_element_type (), backend); + tree element_ty = ConstFoldType::fold (type.get_element_type (), backend); translated = backend->array_type (element_ty, type.get_capacity ()); } - void visit (TyTy::ReferenceType &) override { gcc_unreachable (); } + void visit (TyTy::ReferenceType &type) override + { + tree base_compiled_type = ConstFoldType::fold (type.get_base (), backend); + if (type.is_mutable ()) + { + translated = backend->reference_type (base_compiled_type); + } + else + { + auto base = backend->immutable_type (base_compiled_type); + translated = backend->reference_type (base); + } + } - void visit (TyTy::PointerType &) override { gcc_unreachable (); } + void visit (TyTy::PointerType &type) override + { + tree base_compiled_type = ConstFoldType::fold (type.get_base (), backend); + if (type.is_mutable ()) + { + translated = backend->pointer_type (base_compiled_type); + } + else + { + auto base = backend->immutable_type (base_compiled_type); + translated = backend->pointer_type (base); + } + } void visit (TyTy::ParamType &) override { gcc_unreachable (); } @@ -188,7 +212,7 @@ public: void visit (TyTy::StrType &) override { - Btype *raw_str = backend->raw_str_type (); + tree raw_str = backend->raw_str_type (); translated = backend->named_type ("str", raw_str, Linemap::predeclared_location ()); } @@ -205,7 +229,7 @@ private: {} ::Backend *backend; - ::Btype *translated; + ::tree translated; }; class ConstFoldItem : public ConstFoldBase @@ -213,7 +237,7 @@ class ConstFoldItem : public ConstFoldBase using ConstFoldBase::visit; public: - static Bexpression *fold (HIR::Item &item) + static tree fold (HIR::Item &item) { ConstFoldItem folder; item.accept_vis (folder); @@ -234,7 +258,7 @@ private: : ConstFoldBase (), folded (ctx->get_backend ()->error_expression ()) {} - Bexpression *folded; + tree folded; }; class ConstFoldArrayElems : public ConstFoldBase @@ -242,7 +266,7 @@ class ConstFoldArrayElems : public ConstFoldBase using ConstFoldBase::visit; public: - static Bexpression *fold (HIR::ArrayExpr &expr) + static tree fold (HIR::ArrayExpr &expr) { ConstFoldArrayElems folder (expr); HIR::ArrayElems *elems = expr.get_internal_elements (); @@ -259,7 +283,7 @@ private: expr (expr) {} - Bexpression *folded; + tree folded; HIR::ArrayExpr &expr; }; @@ -268,7 +292,7 @@ class ConstFoldExpr : public ConstFoldBase using ConstFoldBase::visit; public: - static Bexpression *fold (HIR::Expr *expr) + static tree fold (HIR::Expr *expr) { ConstFoldExpr folder; expr->accept_vis (folder); @@ -345,7 +369,7 @@ public: return; } - Btype *type = ConstFoldType::fold (tyty, ctx->get_backend ()); + tree type = ConstFoldType::fold (tyty, ctx->get_backend ()); folded = ctx->get_backend ()->integer_constant_expression (type, ival); } @@ -376,7 +400,7 @@ public: return; } - Btype *type = ConstFoldType::fold (tyty, ctx->get_backend ()); + tree type = ConstFoldType::fold (tyty, ctx->get_backend ()); folded = ctx->get_backend ()->float_constant_expression (type, fval); } return; @@ -429,19 +453,51 @@ public: void visit (HIR::ArrayIndexExpr &expr) override { - Bexpression *array = ConstFoldExpr::fold (expr.get_array_expr ()); - Bexpression *index = ConstFoldExpr::fold (expr.get_index_expr ()); + tree array = ConstFoldExpr::fold (expr.get_array_expr ()); + tree index = ConstFoldExpr::fold (expr.get_index_expr ()); folded = ctx->get_backend ()->array_index_expression (array, index, expr.get_locus ()); } + void visit (HIR::BorrowExpr &expr) override + { + tree main_expr = ConstFoldExpr::fold (expr.get_expr ().get ()); + + folded + = ctx->get_backend ()->address_expression (main_expr, expr.get_locus ()); + } + + void visit (HIR::DereferenceExpr &expr) override + { + tree main_expr = ConstFoldExpr::fold (expr.get_expr ().get ()); + + TyTy::BaseType *tyty = nullptr; + if (!tyctx->lookup_type (expr.get_mappings ().get_hirid (), &tyty)) + { + rust_fatal_error (expr.get_locus (), + "did not resolve type for this TupleExpr"); + return; + } + + tree expected_type = ConstFoldType::fold (tyty, ctx->get_backend ()); + bool known_valid = true; + folded = ctx->get_backend ()->indirect_expression (expected_type, main_expr, + known_valid, + expr.get_locus ()); + } + + void visit (HIR::GroupedExpr &expr) override + { + folded = ConstFoldExpr::fold (expr.get_expr_in_parens ().get ()); + } + private: ConstFoldExpr () : ConstFoldBase (), folded (ctx->get_backend ()->error_expression ()) {} - Bexpression *folded; + tree folded; }; } // namespace ConstFold diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h index d318b9c..0c618d3 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -119,9 +119,10 @@ public: static std::vector<PathProbeCandidate> Probe (const TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name, bool probe_impls, - bool probe_bounds, bool ignore_mandatory_trait_items) + bool probe_bounds, bool ignore_mandatory_trait_items, + DefId specific_trait_id = UNKNOWN_DEFID) { - PathProbeType probe (receiver, segment_name); + PathProbeType probe (receiver, segment_name, specific_trait_id); if (probe_impls) { if (receiver->get_kind () == TyTy::TypeKind::ADT) @@ -145,6 +146,13 @@ public: for (auto &candidate : probed_bounds) { const TraitReference *trait_ref = candidate.first; + if (specific_trait_id != UNKNOWN_DEFID) + { + if (trait_ref->get_mappings ().get_defid () + != specific_trait_id) + continue; + } + HIR::ImplBlock *impl = candidate.second; probe.process_associated_trait_for_candidates ( trait_ref, impl, ignore_mandatory_trait_items); @@ -154,6 +162,13 @@ public: for (const TyTy::TypeBoundPredicate &predicate : receiver->get_specified_bounds ()) { + const TraitReference *trait_ref = predicate.get (); + if (specific_trait_id != UNKNOWN_DEFID) + { + if (trait_ref->get_mappings ().get_defid () != specific_trait_id) + continue; + } + probe.process_predicate_for_candidates (predicate, ignore_mandatory_trait_items); } @@ -221,6 +236,9 @@ public: protected: void process_enum_item_for_candiates (const TyTy::ADTType *adt) { + if (specific_trait_id != UNKNOWN_DEFID) + return; + TyTy::VariantDef *v; if (!adt->lookup_variant (search.as_string (), &v)) return; @@ -385,9 +403,9 @@ protected: protected: PathProbeType (const TyTy::BaseType *receiver, - const HIR::PathIdentSegment &query) + const HIR::PathIdentSegment &query, DefId specific_trait_id) : TypeCheckBase (), receiver (receiver), search (query), - current_impl (nullptr) + current_impl (nullptr), specific_trait_id (specific_trait_id) {} std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> @@ -427,6 +445,7 @@ protected: const HIR::PathIdentSegment &search; std::vector<PathProbeCandidate> candidates; HIR::ImplBlock *current_impl; + DefId specific_trait_id; }; class ReportMultipleCandidateError : private TypeCheckBase @@ -507,7 +526,8 @@ private: PathProbeImplTrait (const TyTy::BaseType *receiver, const HIR::PathIdentSegment &query, const TraitReference *trait_reference) - : PathProbeType (receiver, query), trait_reference (trait_reference) + : PathProbeType (receiver, query, UNKNOWN_DEFID), + trait_reference (trait_reference) {} const TraitReference *trait_reference; diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index cee6999..b2deb91 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -116,7 +116,7 @@ TraitItemReference::resolve_item (HIR::TraitItemFunc &func) // need to get the return type from this TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (item_tyty); auto expected_ret_tyty = resolved_fn_type->get_return_type (); - context->push_return_type (expected_ret_tyty); + context->push_return_type (TypeCheckContextItem (&func), expected_ret_tyty); auto block_expr_ty = TypeCheckExpr::Resolve (func.get_block_expr ().get (), false); diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h index a32b4da..54591ce 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.h +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h @@ -24,6 +24,7 @@ #include "rust-tyty-visitor.h" #include "rust-hir-type-check-type.h" #include "rust-hir-trait-ref.h" +#include "rust-expr.h" namespace Rust { namespace Resolver { @@ -206,6 +207,31 @@ private: // loop of trying to resolve traits as required by the types tref->on_resolved (); + // does this have any lang-item attributes? + for (auto &attr : trait_reference->get_outer_attrs ()) + { + bool is_lang_item = attr.get_path ().as_string ().compare ("lang") == 0 + && attr.has_attr_input () + && attr.get_attr_input ().get_attr_input_type () + == AST::AttrInput::AttrInputType::LITERAL; + if (is_lang_item) + { + auto &literal + = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ()); + const auto &lang_item_type_str + = literal.get_literal ().as_string (); + auto lang_item_type + = Analysis::RustLangItem::Parse (lang_item_type_str); + if (lang_item_type == Analysis::RustLangItem::ItemType::UNKNOWN) + { + rust_error_at (attr.get_locus (), "unknown lang item"); + return tref; + } + mappings->insert_lang_item ( + lang_item_type, trait_reference->get_mappings ().get_defid ()); + } + } + return tref; } diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h index eb96fd1..52dea21 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.h +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -58,7 +58,7 @@ public: virtual void visit (HIR::LazyBooleanExpr &) override {} virtual void visit (HIR::TypeCastExpr &) override {} virtual void visit (HIR::AssignmentExpr &) override {} - + virtual void visit (HIR::CompoundAssignmentExpr &) override {} virtual void visit (HIR::GroupedExpr &) override {} virtual void visit (HIR::ArrayElemsValues &) override {} diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 2a6bae9..9eef755 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -265,15 +265,29 @@ public: bool probe_impls = !receiver_is_generic; bool ignore_mandatory_trait_items = !receiver_is_generic; + auto probe_type = probe_impls ? receiver_tyty : root; auto candidates - = PathProbeType::Probe (root, expr.get_method_name ().get_segment (), + = PathProbeType::Probe (probe_type, + expr.get_method_name ().get_segment (), probe_impls, probe_bounds, ignore_mandatory_trait_items); if (candidates.empty ()) { - rust_error_at (expr.get_locus (), - "failed to resolve the PathExprSegment to any item"); - return; + if (probe_impls) + { + candidates + = PathProbeType::Probe (root, + expr.get_method_name ().get_segment (), + probe_impls, probe_bounds, + ignore_mandatory_trait_items); + } + + if (candidates.empty ()) + { + rust_error_at (expr.get_locus (), + "failed to resolve the PathExprSegment to any item"); + return; + } } std::vector<Adjustment> adjustments; @@ -295,6 +309,10 @@ public: return; } + // Get the adjusted self + Adjuster adj (receiver_tyty); + TyTy::BaseType *adjusted_self = adj.adjust_type (adjustments); + // store the adjustments for code-generation to know what to do context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (), std::move (adjustments)); @@ -401,7 +419,8 @@ public: } TyTy::BaseType *function_ret_tyty - = TyTy::TypeCheckMethodCallExpr::go (lookup, expr, context); + = TyTy::TypeCheckMethodCallExpr::go (lookup, expr, adjusted_self, + context); if (function_ret_tyty == nullptr || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR) { @@ -470,6 +489,39 @@ public: result->clone ()); } + void visit (HIR::CompoundAssignmentExpr &expr) override + { + infered = new TyTy::TupleType (expr.get_mappings ().get_hirid ()); + + auto lhs = TypeCheckExpr::Resolve (expr.get_left_expr ().get (), false); + auto rhs = TypeCheckExpr::Resolve (expr.get_right_expr ().get (), false); + + // we dont care about the result of the unify from a compound assignment + // since this is a unit-type expr + auto result = lhs->unify (rhs); + if (result->get_kind () == TyTy::TypeKind::ERROR) + return; + + auto lang_item_type + = Analysis::RustLangItem::CompoundAssignmentOperatorToLangItem ( + expr.get_expr_type ()); + bool operator_overloaded + = resolve_operator_overload (lang_item_type, expr, lhs, rhs); + if (operator_overloaded) + return; + + bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ()); + bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ()); + bool valid = valid_lhs && valid_rhs; + if (!valid) + { + rust_error_at (expr.get_locus (), + "cannot apply this operator to types %s and %s", + lhs->as_string ().c_str (), rhs->as_string ().c_str ()); + return; + } + } + void visit (HIR::IdentifierExpr &expr) override { NodeId ast_node_id = expr.get_mappings ().get_nodeid (); @@ -654,7 +706,7 @@ public: UNKNOWN_LOCAL_DEFID); /* Capacity is the size of the string (number of chars). - It is a constant, but for fold it to get a Bexpression. */ + It is a constant, but for fold it to get a tree. */ std::string capacity_str = std::to_string (expr.get_literal ()->as_string ().size ()); HIR::LiteralExpr literal_capacity (capacity_mapping, capacity_str, @@ -667,8 +719,7 @@ public: new TyTy::USizeType ( capacity_mapping.get_hirid ())); - Bexpression *capacity - = ConstFold::ConstFoldExpr::fold (&literal_capacity); + tree capacity = ConstFold::ConstFoldExpr::fold (&literal_capacity); Analysis::NodeMapping array_mapping (crate_num, UNKNOWN_NODEID, mappings->get_next_hir_id ( @@ -699,6 +750,13 @@ public: auto lhs = TypeCheckExpr::Resolve (expr.get_lhs (), false); auto rhs = TypeCheckExpr::Resolve (expr.get_rhs (), false); + auto lang_item_type + = Analysis::RustLangItem::OperatorToLangItem (expr.get_expr_type ()); + bool operator_overloaded + = resolve_operator_overload (lang_item_type, expr, lhs, rhs); + if (operator_overloaded) + return; + bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ()); bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ()); bool valid = valid_lhs && valid_rhs; @@ -711,8 +769,6 @@ public: } infered = lhs->unify (rhs); - infered->append_reference (lhs->get_ref ()); - infered->append_reference (rhs->get_ref ()); } void visit (HIR::ComparisonExpr &expr) override @@ -736,17 +792,15 @@ public: // we expect the lhs and rhs must be bools at this point TyTy::BoolType elhs (expr.get_mappings ().get_hirid ()); lhs = elhs.unify (lhs); - if (lhs == nullptr || lhs->get_kind () == TyTy::TypeKind::ERROR) + if (lhs->get_kind () == TyTy::TypeKind::ERROR) return; TyTy::BoolType rlhs (expr.get_mappings ().get_hirid ()); rhs = elhs.unify (rhs); - if (lhs == nullptr || lhs->get_kind () == TyTy::TypeKind::ERROR) + if (lhs->get_kind () == TyTy::TypeKind::ERROR) return; infered = lhs->unify (rhs); - infered->append_reference (lhs->get_ref ()); - infered->append_reference (rhs->get_ref ()); } void visit (HIR::NegationExpr &expr) override @@ -754,6 +808,15 @@ public: auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr ().get (), false); + // check for operator overload + auto lang_item_type = Analysis::RustLangItem::NegationOperatorToLangItem ( + expr.get_expr_type ()); + bool operator_overloaded + = resolve_operator_overload (lang_item_type, expr, negated_expr_ty, + nullptr); + if (operator_overloaded) + return; + // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators switch (expr.get_expr_type ()) { @@ -1174,6 +1237,203 @@ public: infered = expr_to_convert->cast (tyty_to_convert_to); } +protected: + bool + resolve_operator_overload (Analysis::RustLangItem::ItemType lang_item_type, + HIR::OperatorExpr &expr, TyTy::BaseType *lhs, + TyTy::BaseType *rhs) + { + // in order to probe of the correct type paths we need the root type, which + // strips any references + const TyTy::BaseType *root = lhs->get_root (); + + // look up lang item for arithmetic type + std::vector<PathProbeCandidate> candidates; + std::string associated_item_name + = Analysis::RustLangItem::ToString (lang_item_type); + DefId respective_lang_item_id = UNKNOWN_DEFID; + bool lang_item_defined + = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id); + + // probe for the lang-item + if (lang_item_defined) + { + bool receiver_is_type_param + = root->get_kind () == TyTy::TypeKind::PARAM; + bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC; + + bool receiver_is_generic = receiver_is_type_param || receiver_is_dyn; + bool probe_bounds = true; + bool probe_impls = !receiver_is_generic; + bool ignore_mandatory_trait_items = !receiver_is_generic; + + candidates = PathProbeType::Probe ( + root, HIR::PathIdentSegment (associated_item_name), probe_impls, + probe_bounds, ignore_mandatory_trait_items, respective_lang_item_id); + } + + // autoderef + std::vector<Adjustment> adjustments; + PathProbeCandidate *resolved_candidate + = MethodResolution::Select (candidates, lhs, adjustments); + + // is this the case we are recursive + // handle the case where we are within the impl block for this lang_item + // otherwise we end up with a recursive operator overload such as the i32 + // operator overload trait + if (lang_item_defined && resolved_candidate != nullptr) + { + TypeCheckContextItem &fn_context = context->peek_context (); + if (fn_context.get_type () == TypeCheckContextItem::ItemType::IMPL_ITEM) + { + auto &impl_item = fn_context.get_impl_item (); + HIR::ImplBlock *parent = impl_item.first; + HIR::Function *fn = impl_item.second; + + if (parent->has_trait_ref () + && fn->get_function_name ().compare (associated_item_name) == 0) + { + TraitReference *trait_reference + = TraitResolver::Lookup (*parent->get_trait_ref ().get ()); + if (!trait_reference->is_error ()) + { + TyTy::BaseType *lookup = nullptr; + bool ok + = context->lookup_type (fn->get_mappings ().get_hirid (), + &lookup); + rust_assert (ok); + rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF); + + TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup); + rust_assert (fntype->is_method ()); + + Adjuster adj (lhs); + TyTy::BaseType *adjusted = adj.adjust_type (adjustments); + + bool is_lang_item_impl + = trait_reference->get_mappings ().get_defid () + == respective_lang_item_id; + bool self_is_lang_item_self + = fntype->get_self_type ()->is_equal (*adjusted); + bool recursive_operator_overload + = is_lang_item_impl && self_is_lang_item_self; + + lang_item_defined = !recursive_operator_overload; + } + } + } + } + + bool have_implementation_for_lang_item = resolved_candidate != nullptr; + if (!lang_item_defined || !have_implementation_for_lang_item) + { + // no operator overload exists for this + return false; + } + + // now its just like a method-call-expr + context->insert_receiver (expr.get_mappings ().get_hirid (), lhs); + + // store the adjustments for code-generation to know what to do + context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (), + std::move (adjustments)); + + TyTy::BaseType *lookup_tyty = resolved_candidate->ty; + NodeId resolved_node_id + = resolved_candidate->is_impl_candidate () + ? resolved_candidate->item.impl.impl_item->get_impl_mappings () + .get_nodeid () + : resolved_candidate->item.trait.item_ref->get_mappings () + .get_nodeid (); + + rust_assert (lookup_tyty->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::BaseType *lookup = lookup_tyty; + TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup); + rust_assert (fn->is_method ()); + + if (root->get_kind () == TyTy::TypeKind::ADT) + { + const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (root); + if (adt->has_substitutions () && fn->needs_substitution ()) + { + // consider the case where we have: + // + // struct Foo<X,Y>(X,Y); + // + // impl<T> Foo<T, i32> { + // fn test<X>(self, a:X) -> (T,X) { (self.0, a) } + // } + // + // In this case we end up with an fn type of: + // + // fn <T,X> test(self:Foo<T,i32>, a:X) -> (T,X) + // + // This means the instance or self we are calling this method for + // will be substituted such that we can get the inherited type + // arguments but then need to use the turbo fish if available or + // infer the remaining arguments. Luckily rust does not allow for + // default types GenericParams on impl blocks since these must + // always be at the end of the list + + auto s = fn->get_self_type ()->get_root (); + rust_assert (s->can_eq (adt, false, false)); + rust_assert (s->get_kind () == TyTy::TypeKind::ADT); + const TyTy::ADTType *self_adt + = static_cast<const TyTy::ADTType *> (s); + + // we need to grab the Self substitutions as the inherit type + // parameters for this + if (self_adt->needs_substitution ()) + { + rust_assert (adt->was_substituted ()); + + TyTy::SubstitutionArgumentMappings used_args_in_prev_segment + = GetUsedSubstArgs::From (adt); + + TyTy::SubstitutionArgumentMappings inherit_type_args + = self_adt->solve_mappings_from_receiver_for_self ( + used_args_in_prev_segment); + + // there may or may not be inherited type arguments + if (!inherit_type_args.is_error ()) + { + // need to apply the inherited type arguments to the + // function + lookup = fn->handle_substitions (inherit_type_args); + } + } + } + } + + // type check the arguments if required + TyTy::FnType *type = static_cast<TyTy::FnType *> (lookup); + if (rhs == nullptr) + { + rust_assert (type->num_params () == 1); + } + else + { + rust_assert (type->num_params () == 2); + auto fnparam = type->param_at (1); + fnparam.second->unify (rhs); // typecheck the rhs + } + + // get the return type + TyTy::BaseType *function_ret_tyty = fn->get_return_type ()->clone (); + + // store the expected fntype + context->insert_operator_overload (expr.get_mappings ().get_hirid (), type); + + // set up the resolved name on the path + resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (), + resolved_node_id); + + // return the result of the function back + infered = function_ret_tyty; + + return true; + } + private: TypeCheckExpr (bool inside_loop) : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr), @@ -1249,11 +1509,11 @@ private: /* The return value of visit(ArrayElemsValues&) and visit(ArrayElemsCopied&) Stores the type of array elements, if `expr` is ArrayExpr. */ TyTy::BaseType *infered_array_elems; - Bexpression *folded_array_capacity; + tree folded_array_capacity; Location root_array_expr_locus; bool inside_loop; -}; +}; // namespace Resolver } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index 062d60b..64853f5 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -310,9 +310,10 @@ class TypeCheckImplItem : public TypeCheckBase public: using Rust::Resolver::TypeCheckBase::visit; - static void Resolve (HIR::ImplItem *item, TyTy::BaseType *self) + static void Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item, + TyTy::BaseType *self) { - TypeCheckImplItem resolver (self); + TypeCheckImplItem resolver (parent, self); item->accept_vis (resolver); } @@ -336,7 +337,8 @@ public: // need to get the return type from this TyTy::FnType *resolve_fn_type = static_cast<TyTy::FnType *> (lookup); auto expected_ret_tyty = resolve_fn_type->get_return_type (); - context->push_return_type (expected_ret_tyty); + context->push_return_type (TypeCheckContextItem (parent, &function), + expected_ret_tyty); auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ().get (), false); @@ -346,8 +348,11 @@ public: } protected: - TypeCheckImplItem (TyTy::BaseType *self) : TypeCheckBase (), self (self) {} + TypeCheckImplItem (HIR::ImplBlock *parent, TyTy::BaseType *self) + : TypeCheckBase (), parent (parent), self (self) + {} + HIR::ImplBlock *parent; TyTy::BaseType *self; }; @@ -357,11 +362,12 @@ class TypeCheckImplItemWithTrait : public TypeCheckImplItem public: static const TraitItemReference & - Resolve (HIR::ImplItem *item, TyTy::BaseType *self, + Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self, TraitReference &trait_reference, std::vector<TyTy::SubstitutionParamMapping> substitutions) { - TypeCheckImplItemWithTrait resolver (self, trait_reference, substitutions); + TypeCheckImplItemWithTrait resolver (parent, self, trait_reference, + substitutions); item->accept_vis (resolver); return resolver.resolved_trait_item; } @@ -514,9 +520,10 @@ public: private: TypeCheckImplItemWithTrait ( - TyTy::BaseType *self, TraitReference &trait_reference, + HIR::ImplBlock *parent, TyTy::BaseType *self, + TraitReference &trait_reference, std::vector<TyTy::SubstitutionParamMapping> substitutions) - : TypeCheckImplItem (self), trait_reference (trait_reference), + : TypeCheckImplItem (parent, self), trait_reference (trait_reference), resolved_trait_item (TraitItemReference::error_node ()), substitutions (substitutions) { diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 706f649..cc102df 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -118,11 +118,12 @@ public: for (auto &impl_item : impl_block.get_impl_items ()) { if (!is_trait_impl_block) - TypeCheckImplItem::Resolve (impl_item.get (), self); + TypeCheckImplItem::Resolve (&impl_block, impl_item.get (), self); else { auto &trait_item_ref - = TypeCheckImplItemWithTrait::Resolve (impl_item.get (), self, + = TypeCheckImplItemWithTrait::Resolve (&impl_block, + impl_item.get (), self, *trait_reference, substitutions); trait_item_refs.push_back (trait_item_ref); @@ -210,7 +211,8 @@ public: // need to get the return type from this TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (lookup); auto expected_ret_tyty = resolved_fn_type->get_return_type (); - context->push_return_type (expected_ret_tyty); + context->push_return_type (TypeCheckContextItem (&function), + expected_ret_tyty); auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ().get (), false); diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index 8df43d9..fb0e047 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -424,7 +424,8 @@ public: TyTy::FnType *resolved_fn_type = fnType; auto expected_ret_tyty = resolved_fn_type->get_return_type (); - context->push_return_type (expected_ret_tyty); + context->push_return_type (TypeCheckContextItem (&function), + expected_ret_tyty); auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ().get (), false); diff --git a/gcc/rust/typecheck/rust-hir-type-check-util.h b/gcc/rust/typecheck/rust-hir-type-check-util.h index 4595ca3..f078df6 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-util.h +++ b/gcc/rust/typecheck/rust-hir-type-check-util.h @@ -51,7 +51,7 @@ public: virtual void visit (HIR::LazyBooleanExpr &) override {} virtual void visit (HIR::TypeCastExpr &) override {} virtual void visit (HIR::AssignmentExpr &) override {} - + virtual void visit (HIR::CompoundAssignmentExpr &) override {} virtual void visit (HIR::GroupedExpr &) override {} virtual void visit (HIR::ArrayElemsValues &) override {} diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index aa10f41..1add4fa 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -28,6 +28,68 @@ namespace Rust { namespace Resolver { +class TypeCheckContextItem +{ +public: + enum ItemType + { + ITEM, + IMPL_ITEM, + TRAIT_ITEM, + }; + + TypeCheckContextItem (HIR::Function *item) + : type (ItemType::ITEM), item (item) + {} + + TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item) + : type (ItemType::IMPL_ITEM), item (impl_block, item) + {} + + TypeCheckContextItem (HIR::TraitItemFunc *trait_item) + : type (ItemType::TRAIT_ITEM), item (trait_item) + {} + + ItemType get_type () const { return type; } + + HIR::Function *get_item () + { + rust_assert (get_type () == ItemType::ITEM); + return item.item; + } + + std::pair<HIR::ImplBlock *, HIR::Function *> &get_impl_item () + { + rust_assert (get_type () == ItemType::IMPL_ITEM); + return item.impl_item; + }; + + HIR::TraitItemFunc *get_trait_item () + { + rust_assert (get_type () == ItemType::TRAIT_ITEM); + return item.trait_item; + } + +private: + union Item + { + HIR::Function *item; + std::pair<HIR::ImplBlock *, HIR::Function *> impl_item; + HIR::TraitItemFunc *trait_item; + + Item (HIR::Function *item) : item (item) {} + + Item (HIR::ImplBlock *impl_block, HIR::Function *item) + : impl_item ({impl_block, item}) + {} + + Item (HIR::TraitItemFunc *trait_item) : trait_item (trait_item) {} + }; + + ItemType type; + Item item; +}; + class TypeCheckContext { public: @@ -49,7 +111,9 @@ public: bool lookup_type_by_node_id (NodeId ref, HirId *id); TyTy::BaseType *peek_return_type (); - void push_return_type (TyTy::BaseType *return_type); + TypeCheckContextItem &peek_context (); + void push_return_type (TypeCheckContextItem item, + TyTy::BaseType *return_type); void pop_return_type (); void iterate (std::function<bool (HirId, TyTy::BaseType *)> cb) @@ -232,13 +296,32 @@ public: return true; } + void insert_operator_overload (HirId id, TyTy::FnType *call_site) + { + auto it = operator_overloads.find (id); + rust_assert (it == operator_overloads.end ()); + + operator_overloads[id] = call_site; + } + + bool lookup_operator_overload (HirId id, TyTy::FnType **call) + { + auto it = operator_overloads.find (id); + if (it == operator_overloads.end ()) + return false; + + *call = it->second; + return true; + } + private: TypeCheckContext (); std::map<NodeId, HirId> node_id_refs; std::map<HirId, TyTy::BaseType *> resolved; std::vector<std::unique_ptr<TyTy::BaseType>> builtins; - std::vector<TyTy::BaseType *> return_type_stack; + std::vector<std::pair<TypeCheckContextItem, TyTy::BaseType *>> + return_type_stack; std::vector<TyTy::BaseType *> loop_type_stack; std::map<DefId, TraitReference> trait_context; std::map<HirId, TyTy::BaseType *> receiver_context; @@ -253,6 +336,9 @@ private: // adjustment mappings std::map<HirId, std::vector<Adjustment>> autoderef_mappings; + // operator overloads + std::map<HirId, TyTy::FnType *> operator_overloads; + // variants std::map<HirId, HirId> variants; }; diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc new file mode 100644 index 0000000..a439416 --- /dev/null +++ b/gcc/rust/typecheck/rust-substitution-mapper.cc @@ -0,0 +1,49 @@ +// Copyright (C) 2020-2021 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/>. + +#include "rust-substitution-mapper.h" +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Resolver { + +TyTy::BaseType * +SubstMapperInternal::Resolve (TyTy::BaseType *base, + TyTy::SubstitutionArgumentMappings &mappings) +{ + SubstMapperInternal mapper (base->get_ref (), mappings); + base->accept_vis (mapper); + rust_assert (mapper.resolved != nullptr); + + // insert these new implict types into the context + bool is_fn = mapper.resolved->get_kind () == TyTy::TypeKind::FNDEF; + bool is_adt = mapper.resolved->get_kind () == TyTy::TypeKind::ADT; + bool is_param = mapper.resolved->get_kind () == TyTy::TypeKind::PARAM; + if (!is_fn && !is_adt && !is_param) + { + auto context = TypeCheckContext::get (); + context->insert_type ( + Analysis::NodeMapping (0, 0, mapper.resolved->get_ty_ref (), 0), + mapper.resolved); + } + + return mapper.resolved; +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index 0b3ec3b..0932038 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -154,13 +154,7 @@ class SubstMapperInternal : public TyTy::TyVisitor { public: static TyTy::BaseType *Resolve (TyTy::BaseType *base, - TyTy::SubstitutionArgumentMappings &mappings) - { - SubstMapperInternal mapper (base->get_ref (), mappings); - base->accept_vis (mapper); - rust_assert (mapper.resolved != nullptr); - return mapper.resolved; - } + TyTy::SubstitutionArgumentMappings &mappings); void visit (TyTy::FnType &type) override { diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc index 02907d7..31f8ae5 100644 --- a/gcc/rust/typecheck/rust-tyctx.cc +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -122,13 +122,14 @@ TypeCheckContext::lookup_type_by_node_id (NodeId ref, HirId *id) TyTy::BaseType * TypeCheckContext::peek_return_type () { - return return_type_stack.back (); + return return_type_stack.back ().second; } void -TypeCheckContext::push_return_type (TyTy::BaseType *return_type) +TypeCheckContext::push_return_type (TypeCheckContextItem item, + TyTy::BaseType *return_type) { - return_type_stack.push_back (return_type); + return_type_stack.push_back ({std::move (item), return_type}); } void @@ -137,5 +138,11 @@ TypeCheckContext::pop_return_type () return_type_stack.pop_back (); } +TypeCheckContextItem & +TypeCheckContext::peek_context () +{ + return return_type_stack.back ().first; +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index c11fd4d..3080427 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -88,9 +88,10 @@ class TypeCheckMethodCallExpr : private TyVisitor public: // Resolve the Method parameters and return back the return type static BaseType *go (BaseType *ref, HIR::MethodCallExpr &call, + TyTy::BaseType *adjusted_self, Resolver::TypeCheckContext *context) { - TypeCheckMethodCallExpr checker (call, context); + TypeCheckMethodCallExpr checker (call, adjusted_self, context); ref->accept_vis (checker); return checker.resolved; } @@ -125,13 +126,15 @@ public: private: TypeCheckMethodCallExpr (HIR::MethodCallExpr &c, + TyTy::BaseType *adjusted_self, Resolver::TypeCheckContext *context) - : resolved (nullptr), call (c), context (context), - mappings (Analysis::Mappings::get ()) + : resolved (nullptr), call (c), adjusted_self (adjusted_self), + context (context), mappings (Analysis::Mappings::get ()) {} BaseType *resolved; HIR::MethodCallExpr &call; + TyTy::BaseType *adjusted_self; Resolver::TypeCheckContext *context; Analysis::Mappings *mappings; }; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 378416f..add4dbe 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -2786,6 +2786,8 @@ TypeCheckCallExpr::visit (FnPtr &type) void TypeCheckMethodCallExpr::visit (FnType &type) { + adjusted_self->unify (type.get_self_type ()); + // +1 for the receiver self size_t num_args_to_call = call.num_params () + 1; if (num_args_to_call != type.num_params ()) diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index ae9ff67..915aad9 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -1324,7 +1324,7 @@ public: params (std::move (params)), type (type), flags (flags), identifier (identifier), id (id), abi (abi) { - LocalDefId local_def_id = id & DEF_ID_LOCAL_DEF_MASK; + LocalDefId local_def_id = id.localDefId; rust_assert (local_def_id != UNKNOWN_LOCAL_DEFID); } @@ -1339,7 +1339,7 @@ public: params (params), type (type), flags (flags), identifier (identifier), id (id), abi (abi) { - LocalDefId local_def_id = id & DEF_ID_LOCAL_DEF_MASK; + LocalDefId local_def_id = id.localDefId; rust_assert (local_def_id != UNKNOWN_LOCAL_DEFID); } @@ -1519,7 +1519,7 @@ public: parameter_types (std::move (parameter_types)), result_type (std::move (result_type)), id (id) { - LocalDefId local_def_id = id & DEF_ID_LOCAL_DEF_MASK; + LocalDefId local_def_id = id.localDefId; rust_assert (local_def_id != UNKNOWN_LOCAL_DEFID); } @@ -1533,7 +1533,7 @@ public: parameter_types (std::move (parameter_types)), result_type (std::move (result_type)), id (id) { - LocalDefId local_def_id = id & DEF_ID_LOCAL_DEF_MASK; + LocalDefId local_def_id = id.localDefId; rust_assert (local_def_id != UNKNOWN_LOCAL_DEFID); } @@ -1588,13 +1588,13 @@ private: class ArrayType : public BaseType { public: - ArrayType (HirId ref, Bexpression *capacity, TyVar base, + ArrayType (HirId ref, tree capacity, TyVar base, std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ref, TypeKind::ARRAY, refs), capacity (capacity), element_type (base) {} - ArrayType (HirId ref, HirId ty_ref, Bexpression *capacity, TyVar base, + ArrayType (HirId ref, HirId ty_ref, tree capacity, TyVar base, std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ty_ref, TypeKind::ARRAY, refs), capacity (capacity), element_type (base) @@ -1615,7 +1615,7 @@ public: bool is_equal (const BaseType &other) const override; - Bexpression *get_capacity () const { return capacity; } + tree get_capacity () const { return capacity; } std::string capacity_string () const; BaseType *get_element_type () const; @@ -1628,7 +1628,7 @@ public: } private: - Bexpression *capacity; + tree capacity; TyVar element_type; }; diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index e965c23..9e5b509 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -63,7 +63,7 @@ NodeMapping::get_defid () const DefId NodeMapping::get_defid (CrateNum crate_num, LocalDefId local_defid) { - return ((uint64_t) crate_num << 32) | local_defid; + return DefId{crate_num, local_defid}; } std::string @@ -209,8 +209,8 @@ Mappings::insert_hir_crate (HIR::Crate *crate) void Mappings::insert_defid_mapping (DefId id, HIR::Item *item) { - CrateNum crate_num = (id & DEF_ID_CRATE_MASK) >> 32; - LocalDefId local_def_id = id & DEF_ID_LOCAL_DEF_MASK; + CrateNum crate_num = id.crateNum; + LocalDefId local_def_id = id.localDefId; rust_assert (lookup_defid (id) == nullptr); rust_assert (lookup_local_defid (crate_num, local_def_id) == nullptr); diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 4fe64d45..4f8c389 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -23,13 +23,185 @@ #include "rust-location.h" #include "rust-mapping-common.h" #include "rust-canonical-path.h" - #include "rust-ast-full-decls.h" #include "rust-hir-full-decls.h" +#include "operator.h" namespace Rust { namespace Analysis { +// https://github.com/rust-lang/rust/blob/master/library/core/src/ops/arith.rs +class RustLangItem +{ +public: + enum ItemType + { + ADD, + SUBTRACT, + MULTIPLY, + DIVIDE, + REMAINDER, + + NEGATION, + NOT, + + ADD_ASSIGN, + SUB_ASSIGN, + MUL_ASSIGN, + DIV_ASSIGN, + REM_ASSIGN, + + UNKNOWN, + }; + + static ItemType Parse (const std::string &item) + { + if (item.compare ("add") == 0) + { + return ItemType::ADD; + } + else if (item.compare ("sub") == 0) + { + return ItemType::SUBTRACT; + } + else if (item.compare ("mul") == 0) + { + return ItemType::MULTIPLY; + } + else if (item.compare ("div") == 0) + { + return ItemType::DIVIDE; + } + else if (item.compare ("rem") == 0) + { + return ItemType::REMAINDER; + } + else if (item.compare ("neg") == 0) + { + return ItemType::NEGATION; + } + else if (item.compare ("not") == 0) + { + return ItemType::NOT; + } + else if (item.compare ("add_assign") == 0) + { + return ItemType::ADD_ASSIGN; + } + else if (item.compare ("sub_assign") == 0) + { + return ItemType::SUB_ASSIGN; + } + else if (item.compare ("mul_assign") == 0) + { + return ItemType::MUL_ASSIGN; + } + else if (item.compare ("div_assign") == 0) + { + return ItemType::DIV_ASSIGN; + } + else if (item.compare ("rem_assign") == 0) + { + return ItemType::REM_ASSIGN; + } + + return ItemType::UNKNOWN; + } + + static std::string ToString (ItemType type) + { + switch (type) + { + case ADD: + return "add"; + case SUBTRACT: + return "sub"; + case MULTIPLY: + return "mul"; + case DIVIDE: + return "div"; + case REMAINDER: + return "rem"; + case NEGATION: + return "neg"; + case NOT: + return "not"; + case ADD_ASSIGN: + return "add_assign"; + case SUB_ASSIGN: + return "sub_assign"; + case MUL_ASSIGN: + return "mul_assign"; + case DIV_ASSIGN: + return "div_assign"; + case REM_ASSIGN: + return "rem_assign"; + + case UNKNOWN: + break; + } + return "<UNKNOWN>"; + } + + static ItemType OperatorToLangItem (ArithmeticOrLogicalOperator op) + { + switch (op) + { + case ArithmeticOrLogicalOperator::ADD: + return ItemType::ADD; + case ArithmeticOrLogicalOperator::SUBTRACT: + return ItemType::SUBTRACT; + case ArithmeticOrLogicalOperator::MULTIPLY: + return ItemType::MULTIPLY; + case ArithmeticOrLogicalOperator::DIVIDE: + return ItemType::DIVIDE; + case ArithmeticOrLogicalOperator::MODULUS: + return ItemType::REMAINDER; + + default: + return ItemType::UNKNOWN; + } + return ItemType::UNKNOWN; + } + + static ItemType + CompoundAssignmentOperatorToLangItem (ArithmeticOrLogicalOperator op) + { + switch (op) + { + case ArithmeticOrLogicalOperator::ADD: + return ItemType::ADD_ASSIGN; + case ArithmeticOrLogicalOperator::SUBTRACT: + return ItemType::SUB_ASSIGN; + case ArithmeticOrLogicalOperator::MULTIPLY: + return ItemType::MUL_ASSIGN; + case ArithmeticOrLogicalOperator::DIVIDE: + return ItemType::DIV_ASSIGN; + case ArithmeticOrLogicalOperator::MODULUS: + return ItemType::REM_ASSIGN; + + default: + return ItemType::UNKNOWN; + } + return ItemType::UNKNOWN; + } + + static ItemType NegationOperatorToLangItem (NegationOperator op) + { + switch (op) + { + case NegationOperator::NEGATE: + return ItemType::NEGATION; + case NegationOperator::NOT: + return ItemType::NOT; + + default: + return ItemType::UNKNOWN; + } + return ItemType::UNKNOWN; + } +}; + class NodeMapping { public: @@ -237,9 +409,9 @@ public: const Resolver::CanonicalPath *p = nullptr; if (lookup_canonical_path (crate, id, &p)) { - // if we have already stored a canonical path this is ok so long as this - // new path is equal or is smaller that the existing one but in that - // case we ignore it. + // if we have already stored a canonical path this is ok so long as + // this new path is equal or is smaller that the existing one but in + // that case we ignore it. if (p->is_equal (path)) return; else @@ -267,6 +439,24 @@ public: return true; } + void insert_lang_item (RustLangItem::ItemType item_type, DefId id) + { + auto it = lang_item_mappings.find (item_type); + rust_assert (it == lang_item_mappings.end ()); + + lang_item_mappings[item_type] = id; + } + + bool lookup_lang_item (RustLangItem::ItemType item_type, DefId *id) + { + auto it = lang_item_mappings.find (item_type); + if (it == lang_item_mappings.end ()) + return false; + + *id = it->second; + return true; + } + private: Mappings (); @@ -304,6 +494,9 @@ private: hirGenericParamMappings; std::map<HirId, HIR::Trait *> hirTraitItemsToTraitMappings; + // this maps the lang=<item_type> to DefId mappings + std::map<RustLangItem::ItemType, DefId> lang_item_mappings; + // canonical paths std::map<CrateNum, std::map<NodeId, const Resolver::CanonicalPath> > paths; diff --git a/gcc/rust/util/rust-mapping-common.h b/gcc/rust/util/rust-mapping-common.h index 1309a8d..0665779 100644 --- a/gcc/rust/util/rust-mapping-common.h +++ b/gcc/rust/util/rust-mapping-common.h @@ -31,17 +31,32 @@ typedef uint32_t NodeId; typedef uint32_t HirId; // refers to any top-level decl in HIR typedef uint32_t LocalDefId; -// refers to <Crate><DefId> -typedef uint64_t DefId; -#define DEF_ID_CRATE_MASK 0xFFFFFFFF00000000 -#define DEF_ID_LOCAL_DEF_MASK 0x00000000FFFFFFFF +struct DefId +{ + CrateNum crateNum; + LocalDefId localDefId; + + bool operator== (const DefId &other) const + { + return this->crateNum == other.crateNum + && this->localDefId == other.localDefId; + } + + bool operator!= (const DefId &other) const { return !(*this == other); } + + bool operator< (const DefId &other) const + { + return ((uint64_t) this->crateNum << 32 | this->localDefId) + < ((uint64_t) other.crateNum << 32 | other.localDefId); + } +}; #define UNKNOWN_CREATENUM ((uint32_t) (0)) #define UNKNOWN_NODEID ((uint32_t) (0)) #define UNKNOWN_HIRID ((uint32_t) (0)) #define UNKNOWN_LOCAL_DEFID ((uint32_t) (0)) -#define UNKNOWN_DEFID ((uint64_t) (0)) +#define UNKNOWN_DEFID (DefId{0, 0}) } // namespace Rust diff --git a/gcc/testsuite/rust/compile/torture/issue-808.rs b/gcc/testsuite/rust/compile/torture/issue-808.rs new file mode 100644 index 0000000..9aa00fe --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/issue-808.rs @@ -0,0 +1,22 @@ +pub trait Foo { + type Target; + + fn bar(&self) -> &Self::Target; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .Foo::bar." "" { target *-*-* } .-2 } +} + +impl<T> Foo for &T { + type Target = T; + + fn bar(&self) -> &T { + *self + } +} + +pub fn main() { + let a: i32 = 123; + let b: &i32 = &a; + + b.bar(); +} diff --git a/gcc/testsuite/rust/compile/torture/traits11.rs b/gcc/testsuite/rust/compile/torture/traits11.rs index b5fc023..41c82f0 100644 --- a/gcc/testsuite/rust/compile/torture/traits11.rs +++ b/gcc/testsuite/rust/compile/torture/traits11.rs @@ -1,6 +1,5 @@ trait Foo { type A; - // { dg-warning "unused name" "" { target *-*-* } .-1 } fn test(a: Self::A) -> Self::A { a diff --git a/gcc/testsuite/rust/compile/torture/traits4.rs b/gcc/testsuite/rust/compile/torture/traits4.rs index 1db5f32..10d9479 100644 --- a/gcc/testsuite/rust/compile/torture/traits4.rs +++ b/gcc/testsuite/rust/compile/torture/traits4.rs @@ -1,8 +1,6 @@ trait Foo { type A; - // { dg-warning "unused name" "" { target *-*-* } .-1 } type B; - // { dg-warning "unused name" "" { target *-*-* } .-1 } fn new(a: Self::A, b: Self::B) -> Self; // { dg-warning "unused name .a." "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/torture/traits5.rs b/gcc/testsuite/rust/compile/torture/traits5.rs index 87c0283..4a396a0 100644 --- a/gcc/testsuite/rust/compile/torture/traits5.rs +++ b/gcc/testsuite/rust/compile/torture/traits5.rs @@ -1,8 +1,6 @@ trait Foo { type A; - // { dg-warning "unused name" "" { target *-*-* } .-1 } type B; - // { dg-warning "unused name" "" { target *-*-* } .-1 } fn new(a: Self::A, b: Self::B) -> Self; // { dg-warning "unused name .a." "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/torture/traits6.rs b/gcc/testsuite/rust/compile/torture/traits6.rs index 5aae2e3..a69c6fd 100644 --- a/gcc/testsuite/rust/compile/torture/traits6.rs +++ b/gcc/testsuite/rust/compile/torture/traits6.rs @@ -1,6 +1,5 @@ trait Foo { type A; - // { dg-warning "unused name .Foo::A." "" { target *-*-* } .-1 } fn baz(a: Self::A) -> Self::A; // { dg-warning "unused name .a." "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_1.rs b/gcc/testsuite/rust/execute/torture/operator_overload_1.rs new file mode 100644 index 0000000..997ab04 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/operator_overload_1.rs @@ -0,0 +1,39 @@ +/* { dg-output "3\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "add"] +pub trait Add<Rhs = Self> { + type Output; + + fn add(self, rhs: Rhs) -> Self::Output; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .rhs." "" { target *-*-* } .-2 } + // { dg-warning "unused name .Add::add." "" { target *-*-* } .-3 } +} + +impl Add for i32 { + type Output = i32; + + fn add(self, other: i32) -> i32 { + let res = self + other; + + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, res); + } + + res + } +} + +fn main() -> i32 { + let a; + a = 1 + 2; + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_2.rs b/gcc/testsuite/rust/execute/torture/operator_overload_2.rs new file mode 100644 index 0000000..8d6a073 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/operator_overload_2.rs @@ -0,0 +1,41 @@ +/* { dg-output "3\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "add"] +pub trait Add<Rhs = Self> { + type Output; + + fn add(self, rhs: Rhs) -> Self::Output; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .rhs." "" { target *-*-* } .-2 } + // { dg-warning "unused name .Add::add." "" { target *-*-* } .-3 } +} + +struct Foo(i32); + +impl Add for Foo { + type Output = Foo; + + fn add(self, other: Foo) -> Foo { + let res = Foo(self.0 + other.0); + + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, res.0); + } + + res + } +} + +fn main() -> i32 { + let a; + a = Foo(1) + Foo(2); + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_3.rs b/gcc/testsuite/rust/execute/torture/operator_overload_3.rs new file mode 100644 index 0000000..50ff799 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/operator_overload_3.rs @@ -0,0 +1,58 @@ +/* { dg-output "3\n3\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "add"] +pub trait Add<Rhs = Self> { + type Output; + + fn add(self, rhs: Rhs) -> Self::Output; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .rhs." "" { target *-*-* } .-2 } + // { dg-warning "unused name .Add::add." "" { target *-*-* } .-3 } +} + +impl Add for i32 { + type Output = i32; + + fn add(self, other: i32) -> i32 { + let res = self + other; + + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, res); + } + + res + } +} + +struct Foo(i32); +impl Add for Foo { + type Output = Foo; + + fn add(self, other: Foo) -> Foo { + let res = Foo(self.0 + other.0); + + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, res.0); + } + + res + } +} + +fn main() -> i32 { + let a; + a = Foo(1) + Foo(2); + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_4.rs b/gcc/testsuite/rust/execute/torture/operator_overload_4.rs new file mode 100644 index 0000000..5ca5c7a --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/operator_overload_4.rs @@ -0,0 +1,35 @@ +/* { dg-output "neg\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "neg"] +pub trait Neg { + type Output; + + fn neg(self) -> Self::Output; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .Neg::neg." "" { target *-*-* } .-2 } +} + +impl Neg for i32 { + type Output = i32; + + fn neg(self) -> i32 { + unsafe { + let a = "neg\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + -self + } +} + +fn main() -> i32 { + let a: i32 = 1; + let _b = -a; + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_5.rs b/gcc/testsuite/rust/execute/torture/operator_overload_5.rs new file mode 100644 index 0000000..5aac3ad --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/operator_overload_5.rs @@ -0,0 +1,35 @@ +/* { dg-output "not\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "not"] +pub trait Not { + type Output; + + fn not(self) -> Self::Output; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .Not::not." "" { target *-*-* } .-2 } +} + +impl Not for i32 { + type Output = i32; + + fn not(self) -> i32 { + unsafe { + let a = "not\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + !self + } +} + +fn main() -> i32 { + let a: i32 = 1; + let _b = !a; + + 0 +} |