diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/Make-lang.in | 3 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-base.cc | 3 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-block.cc | 158 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-block.h | 71 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 746 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 769 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-fnparam.cc | 59 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-fnparam.h | 57 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-item.h | 2 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-pattern.cc | 3 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-resolve-path.cc | 1 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-stmt.cc | 115 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-stmt.h | 88 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-struct-field-expr.cc | 81 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-struct-field-expr.h | 75 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-type.h | 2 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 161 |
17 files changed, 1222 insertions, 1172 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 23dad26..49be3a1 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -137,8 +137,11 @@ GRS_OBJS = \ rust/rust-optional-test.o \ rust/rust-compile-item.o \ rust/rust-compile-implitem.o \ + rust/rust-compile-stmt.o \ rust/rust-compile-expr.o \ rust/rust-compile-type.o \ + rust/rust-compile-block.o \ + rust/rust-compile-struct-field-expr.o \ rust/rust-constexpr.o \ rust/rust-compile-base.o \ rust/rust-tree.o \ diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index a640a48..2b5c850 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -20,9 +20,10 @@ #include "rust-abi.h" #include "rust-compile-item.h" #include "rust-compile-stmt.h" +#include "rust-compile-expr.h" #include "rust-compile-fnparam.h" #include "rust-compile-var-decl.h" - +#include "rust-constexpr.h" #include "rust-diagnostics.h" #include "rust-expr.h" // for AST::AttrInputLiteral #include "rust-macro.h" // for AST::MetaNameValueStr diff --git a/gcc/rust/backend/rust-compile-block.cc b/gcc/rust/backend/rust-compile-block.cc new file mode 100644 index 0000000..99674e2 --- /dev/null +++ b/gcc/rust/backend/rust-compile-block.cc @@ -0,0 +1,158 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-compile-block.h" +#include "rust-compile-stmt.h" +#include "rust-compile-expr.h" + +namespace Rust { +namespace Compile { + +CompileBlock::CompileBlock (Context *ctx, Bvariable *result) + : HIRCompileBase (ctx), translated (nullptr), result (result) +{} + +tree +CompileBlock::compile (HIR::BlockExpr *expr, Context *ctx, Bvariable *result) +{ + CompileBlock compiler (ctx, result); + compiler.visit (*expr); + return compiler.translated; +} + +void +CompileBlock::visit (HIR::BlockExpr &expr) +{ + fncontext fnctx = ctx->peek_fn (); + tree fndecl = fnctx.fndecl; + Location start_location = expr.get_locus (); + Location end_location = expr.get_end_locus (); + auto body_mappings = expr.get_mappings (); + + Resolver::Rib *rib = nullptr; + if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), &rib)) + { + rust_fatal_error (expr.get_locus (), "failed to setup locals per block"); + return; + } + + std::vector<Bvariable *> locals + = compile_locals_for_block (ctx, *rib, fndecl); + + 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 ()) + { + auto compiled_expr = CompileStmt::Compile (s.get (), ctx); + if (compiled_expr != nullptr) + { + tree s = convert_to_void (compiled_expr, ICV_STATEMENT); + ctx->add_statement (s); + } + } + + if (expr.has_expr ()) + { + // the previous passes will ensure this is a valid return or + // a valid trailing expression + tree compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx); + if (compiled_expr != nullptr) + { + if (result == nullptr) + { + ctx->add_statement (compiled_expr); + } + else + { + tree result_reference = ctx->get_backend ()->var_expression ( + result, expr.get_final_expr ()->get_locus ()); + + tree assignment + = ctx->get_backend ()->assignment_statement (result_reference, + compiled_expr, + expr.get_locus ()); + ctx->add_statement (assignment); + } + } + } + + ctx->pop_block (); + translated = new_block; +} + +void +CompileConditionalBlocks::visit (HIR::IfExpr &expr) +{ + fncontext fnctx = ctx->peek_fn (); + 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, + NULL, expr.get_locus ()); +} + +void +CompileConditionalBlocks::visit (HIR::IfExprConseqElse &expr) +{ + fncontext fnctx = ctx->peek_fn (); + 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, + else_block, expr.get_locus ()); +} + +void +CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr) +{ + fncontext fnctx = ctx->peek_fn (); + 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 + 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); + + tree else_stmt_decl + = CompileConditionalBlocks::compile (expr.get_conseq_if_expr (), ctx, + result); + ctx->add_statement (else_stmt_decl); + + ctx->pop_block (); + + translated + = ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block, + else_block, expr.get_locus ()); +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h index e3c7399..cdd17f1 100644 --- a/gcc/rust/backend/rust-compile-block.h +++ b/gcc/rust/backend/rust-compile-block.h @@ -24,77 +24,16 @@ namespace Rust { namespace Compile { -class CompileBlock : public HIRCompileBase, public HIR::HIRExpressionVisitor +class CompileBlock : private HIRCompileBase { public: - static tree compile (HIR::BlockExpr *expr, Context *ctx, Bvariable *result) - { - CompileBlock compiler (ctx, result); - expr->accept_vis (compiler); - return compiler.translated; - } + static tree compile (HIR::BlockExpr *expr, Context *ctx, Bvariable *result); - void visit (HIR::BlockExpr &expr) override; - - // Empty visit for unused Expression HIR nodes. - void visit (HIR::PathInExpression &) override {} - void visit (HIR::QualifiedPathInExpression &) override {} - void visit (HIR::ClosureExprInner &) override {} - void visit (HIR::ClosureExprInnerTyped &) override {} - void visit (HIR::StructExprFieldIdentifier &) override {} - void visit (HIR::StructExprFieldIdentifierValue &) override {} - void visit (HIR::StructExprFieldIndexValue &) override {} - void visit (HIR::StructExprStruct &) override {} - void visit (HIR::StructExprStructFields &) override {} - void visit (HIR::LiteralExpr &) override {} - void visit (HIR::BorrowExpr &) override {} - void visit (HIR::DereferenceExpr &) override {} - void visit (HIR::ErrorPropagationExpr &) override {} - void visit (HIR::NegationExpr &) override {} - void visit (HIR::ArithmeticOrLogicalExpr &) override {} - void visit (HIR::ComparisonExpr &) override {} - void visit (HIR::LazyBooleanExpr &) override {} - void visit (HIR::TypeCastExpr &) override {} - void visit (HIR::AssignmentExpr &) override {} - void visit (HIR::CompoundAssignmentExpr &) override {} - void visit (HIR::GroupedExpr &) override {} - void visit (HIR::ArrayExpr &) override {} - void visit (HIR::ArrayIndexExpr &) override {} - void visit (HIR::TupleExpr &) override {} - void visit (HIR::TupleIndexExpr &) override {} - void visit (HIR::CallExpr &) override {} - void visit (HIR::MethodCallExpr &) override {} - void visit (HIR::FieldAccessExpr &) override {} - void visit (HIR::ContinueExpr &) override {} - void visit (HIR::BreakExpr &) override {} - void visit (HIR::RangeFromToExpr &) override {} - void visit (HIR::RangeFromExpr &) override {} - void visit (HIR::RangeToExpr &) override {} - void visit (HIR::RangeFullExpr &) override {} - void visit (HIR::RangeFromToInclExpr &) override {} - void visit (HIR::RangeToInclExpr &) override {} - void visit (HIR::ReturnExpr &) override {} - void visit (HIR::UnsafeBlockExpr &) override {} - void visit (HIR::LoopExpr &) override {} - void visit (HIR::WhileLoopExpr &) override {} - void visit (HIR::WhileLetLoopExpr &) override {} - void visit (HIR::ForLoopExpr &) override {} - void visit (HIR::IfExpr &) override {} - void visit (HIR::IfExprConseqElse &) override {} - void visit (HIR::IfExprConseqIf &) override {} - void visit (HIR::IfExprConseqIfLet &) override {} - void visit (HIR::IfLetExpr &) override {} - void visit (HIR::IfLetExprConseqElse &) override {} - void visit (HIR::IfLetExprConseqIf &) override {} - void visit (HIR::IfLetExprConseqIfLet &) override {} - void visit (HIR::MatchExpr &) override {} - void visit (HIR::AwaitExpr &) override {} - void visit (HIR::AsyncBlockExpr &) override {} +protected: + void visit (HIR::BlockExpr &expr); private: - CompileBlock (Context *ctx, Bvariable *result) - : HIRCompileBase (ctx), translated (nullptr), result (result) - {} + CompileBlock (Context *ctx, Bvariable *result); tree translated; Bvariable *result; diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index bfaa7fc..9a8b779 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -16,15 +16,15 @@ // 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-implitem.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-compile-pattern.h" +#include "rust-compile-resolve-path.h" +#include "rust-compile-block.h" +#include "rust-compile-implitem.h" #include "rust-constexpr.h" #include "fold-const.h" @@ -35,6 +35,97 @@ namespace Rust { namespace Compile { +CompileExpr::CompileExpr (Context *ctx) + : HIRCompileBase (ctx), translated (error_mark_node) +{} + +tree +CompileExpr::Compile (HIR::Expr *expr, Context *ctx) +{ + CompileExpr compiler (ctx); + expr->accept_vis (compiler); + return compiler.translated; +} + +void +CompileExpr::visit (HIR::TupleIndexExpr &expr) +{ + HIR::Expr *tuple_expr = expr.get_tuple_expr ().get (); + TupleIndex index = expr.get_tuple_index (); + + tree receiver_ref = CompileExpr::Compile (tuple_expr, ctx); + + TyTy::BaseType *tuple_expr_ty = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (tuple_expr->get_mappings ().get_hirid (), + &tuple_expr_ty); + rust_assert (ok); + + // do we need to add an indirect reference + if (tuple_expr_ty->get_kind () == TyTy::TypeKind::REF) + { + tree indirect = indirect_expression (receiver_ref, expr.get_locus ()); + receiver_ref = indirect; + } + + translated + = ctx->get_backend ()->struct_field_expression (receiver_ref, index, + expr.get_locus ()); +} + +void +CompileExpr::visit (HIR::TupleExpr &expr) +{ + if (expr.is_unit ()) + { + translated = ctx->get_backend ()->unit_expression (); + return; + } + + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &tyty)) + { + rust_fatal_error (expr.get_locus (), + "did not resolve type for this TupleExpr"); + return; + } + + tree tuple_type = TyTyResolveCompile::compile (ctx, tyty); + rust_assert (tuple_type != nullptr); + + // this assumes all fields are in order from type resolution + std::vector<tree> vals; + for (auto &elem : expr.get_tuple_elems ()) + { + auto e = CompileExpr::Compile (elem.get (), ctx); + vals.push_back (e); + } + + translated + = ctx->get_backend ()->constructor_expression (tuple_type, false, vals, -1, + expr.get_locus ()); +} + +void +CompileExpr::visit (HIR::ReturnExpr &expr) +{ + auto fncontext = ctx->peek_fn (); + + std::vector<tree> retstmts; + if (expr.has_return_expr ()) + { + tree compiled_expr = CompileExpr::Compile (expr.return_expr.get (), ctx); + rust_assert (compiled_expr != nullptr); + + retstmts.push_back (compiled_expr); + } + + auto s = ctx->get_backend ()->return_statement (fncontext.fndecl, retstmts, + expr.get_locus ()); + ctx->add_statement (s); +} + void CompileExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) { @@ -120,6 +211,585 @@ CompileExpr::visit (HIR::NegationExpr &expr) } void +CompileExpr::visit (HIR::ComparisonExpr &expr) +{ + 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 ()->comparison_expression (op, lhs, rhs, location); +} + +void +CompileExpr::visit (HIR::LazyBooleanExpr &expr) +{ + 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 ()->lazy_boolean_expression (op, lhs, rhs, location); +} + +void +CompileExpr::visit (HIR::TypeCastExpr &expr) +{ + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &tyty)) + { + translated = error_mark_node; + return; + } + + auto type_to_cast_to = TyTyResolveCompile::compile (ctx, tyty); + auto casted_expr = CompileExpr::Compile (expr.get_casted_expr ().get (), ctx); + translated + = type_cast_expression (type_to_cast_to, casted_expr, expr.get_locus ()); +} + +void +CompileExpr::visit (HIR::IfExpr &expr) +{ + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr); + ctx->add_statement (stmt); +} + +void +CompileExpr::visit (HIR::IfExprConseqElse &expr) +{ + TyTy::BaseType *if_type = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &if_type)) + { + rust_error_at (expr.get_locus (), + "failed to lookup type of IfExprConseqElse"); + return; + } + + Bvariable *tmp = NULL; + bool needs_temp = !if_type->is_unit (); + if (needs_temp) + { + fncontext fnctx = ctx->peek_fn (); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree block_type = TyTyResolveCompile::compile (ctx, if_type); + + bool is_address_taken = false; + 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); + ctx->add_statement (ret_var_stmt); + } + + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp); + ctx->add_statement (stmt); + + if (tmp != NULL) + { + translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + } +} + +void +CompileExpr::visit (HIR::IfExprConseqIf &expr) +{ + TyTy::BaseType *if_type = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &if_type)) + { + rust_error_at (expr.get_locus (), + "failed to lookup type of IfExprConseqElse"); + return; + } + + Bvariable *tmp = NULL; + bool needs_temp = !if_type->is_unit (); + if (needs_temp) + { + fncontext fnctx = ctx->peek_fn (); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree block_type = TyTyResolveCompile::compile (ctx, if_type); + + bool is_address_taken = false; + 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); + ctx->add_statement (ret_var_stmt); + } + + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp); + ctx->add_statement (stmt); + + if (tmp != NULL) + { + translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + } +} + +void +CompileExpr::visit (HIR::BlockExpr &expr) +{ + TyTy::BaseType *block_tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &block_tyty)) + { + rust_error_at (expr.get_locus (), "failed to lookup type of BlockExpr"); + return; + } + + Bvariable *tmp = NULL; + bool needs_temp = !block_tyty->is_unit (); + if (needs_temp) + { + fncontext fnctx = ctx->peek_fn (); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree block_type = TyTyResolveCompile::compile (ctx, block_tyty); + + bool is_address_taken = false; + 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); + ctx->add_statement (ret_var_stmt); + } + + auto block_stmt = CompileBlock::compile (&expr, ctx, tmp); + rust_assert (TREE_CODE (block_stmt) == BIND_EXPR); + ctx->add_statement (block_stmt); + + if (tmp != NULL) + { + translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + } +} + +void +CompileExpr::visit (HIR::UnsafeBlockExpr &expr) +{ + expr.get_block_expr ()->accept_vis (*this); +} + +void +CompileExpr::visit (HIR::StructExprStruct &struct_expr) +{ + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (struct_expr.get_mappings ().get_hirid (), + &tyty)) + { + rust_error_at (struct_expr.get_locus (), "unknown type"); + return; + } + + rust_assert (tyty->is_unit ()); + translated = ctx->get_backend ()->unit_expression (); +} + +void +CompileExpr::visit (HIR::StructExprStructFields &struct_expr) +{ + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (struct_expr.get_mappings ().get_hirid (), + &tyty)) + { + rust_error_at (struct_expr.get_locus (), "unknown type"); + return; + } + + // it must be an ADT + rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT); + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyty); + + // what variant is it? + int union_disriminator = struct_expr.union_index; + TyTy::VariantDef *variant = nullptr; + if (!adt->is_enum ()) + { + rust_assert (adt->number_of_variants () == 1); + variant = adt->get_variants ().at (0); + } + else + { + HirId variant_id; + bool ok = ctx->get_tyctx ()->lookup_variant_definition ( + struct_expr.get_struct_name ().get_mappings ().get_hirid (), + &variant_id); + rust_assert (ok); + + ok + = adt->lookup_variant_by_id (variant_id, &variant, &union_disriminator); + rust_assert (ok); + } + + // compile it + tree compiled_adt_type = TyTyResolveCompile::compile (ctx, tyty); + + std::vector<tree> arguments; + if (adt->is_union ()) + { + rust_assert (struct_expr.get_fields ().size () == 1); + + // assignments are coercion sites so lets convert the rvalue if + // necessary + auto respective_field = variant->get_field_at_index (union_disriminator); + auto expected = respective_field->get_field_type (); + + // process arguments + auto &argument = struct_expr.get_fields ().at (0); + auto lvalue_locus + = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + auto rvalue_locus = argument->get_locus (); + auto rvalue = CompileStructExprField::Compile (argument.get (), ctx); + + TyTy::BaseType *actual = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + argument->get_mappings ().get_hirid (), &actual); + + if (ok) + { + rvalue + = coercion_site (argument->get_mappings ().get_hirid (), rvalue, + actual, expected, lvalue_locus, rvalue_locus); + } + + // add it to the list + arguments.push_back (rvalue); + } + else + { + // this assumes all fields are in order from type resolution and if a + // base struct was specified those fields are filed via accesors + for (size_t i = 0; i < struct_expr.get_fields ().size (); i++) + { + // assignments are coercion sites so lets convert the rvalue if + // necessary + auto respective_field = variant->get_field_at_index (i); + auto expected = respective_field->get_field_type (); + + // process arguments + auto &argument = struct_expr.get_fields ().at (i); + auto lvalue_locus + = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + auto rvalue_locus = argument->get_locus (); + auto rvalue = CompileStructExprField::Compile (argument.get (), ctx); + + TyTy::BaseType *actual = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + argument->get_mappings ().get_hirid (), &actual); + + // coerce it if required/possible see + // compile/torture/struct_base_init_1.rs + if (ok) + { + rvalue + = coercion_site (argument->get_mappings ().get_hirid (), rvalue, + actual, expected, lvalue_locus, rvalue_locus); + } + + // add it to the list + arguments.push_back (rvalue); + } + } + + // the constructor depends on whether this is actually an enum or not if + // its an enum we need to setup the discriminator + std::vector<tree> ctor_arguments; + if (adt->is_enum ()) + { + HIR::Expr *discrim_expr = variant->get_discriminant (); + tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); + tree folded_discrim_expr = fold_expr (discrim_expr_node); + tree qualifier = folded_discrim_expr; + + ctor_arguments.push_back (qualifier); + } + for (auto &arg : arguments) + ctor_arguments.push_back (arg); + + translated = ctx->get_backend ()->constructor_expression ( + compiled_adt_type, adt->is_enum (), ctor_arguments, union_disriminator, + struct_expr.get_locus ()); +} + +void +CompileExpr::visit (HIR::GroupedExpr &expr) +{ + translated = CompileExpr::Compile (expr.get_expr_in_parens ().get (), ctx); +} + +void +CompileExpr::visit (HIR::FieldAccessExpr &expr) +{ + HIR::Expr *receiver_expr = expr.get_receiver_expr ().get (); + tree receiver_ref = CompileExpr::Compile (receiver_expr, ctx); + + // resolve the receiver back to ADT type + TyTy::BaseType *receiver = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + expr.get_receiver_expr ()->get_mappings ().get_hirid (), &receiver)) + { + rust_error_at (expr.get_receiver_expr ()->get_locus (), + "unresolved type for receiver"); + return; + } + + size_t field_index = 0; + if (receiver->get_kind () == TyTy::TypeKind::ADT) + { + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver); + rust_assert (!adt->is_enum ()); + rust_assert (adt->number_of_variants () == 1); + + TyTy::VariantDef *variant = adt->get_variants ().at (0); + bool ok + = variant->lookup_field (expr.get_field_name (), nullptr, &field_index); + rust_assert (ok); + } + else if (receiver->get_kind () == TyTy::TypeKind::REF) + { + TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (receiver); + TyTy::BaseType *b = r->get_base (); + rust_assert (b->get_kind () == TyTy::TypeKind::ADT); + + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (b); + rust_assert (!adt->is_enum ()); + rust_assert (adt->number_of_variants () == 1); + + TyTy::VariantDef *variant = adt->get_variants ().at (0); + bool ok + = variant->lookup_field (expr.get_field_name (), nullptr, &field_index); + rust_assert (ok); + + tree indirect = indirect_expression (receiver_ref, expr.get_locus ()); + receiver_ref = indirect; + } + + translated + = ctx->get_backend ()->struct_field_expression (receiver_ref, field_index, + expr.get_locus ()); +} + +void +CompileExpr::visit (HIR::QualifiedPathInExpression &expr) +{ + translated = ResolvePathRef::Compile (expr, ctx); +} + +void +CompileExpr::visit (HIR::PathInExpression &expr) +{ + translated = ResolvePathRef::Compile (expr, ctx); +} + +void +CompileExpr::visit (HIR::LoopExpr &expr) +{ + TyTy::BaseType *block_tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &block_tyty)) + { + rust_error_at (expr.get_locus (), "failed to lookup type of BlockExpr"); + return; + } + + fncontext fnctx = ctx->peek_fn (); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree block_type = TyTyResolveCompile::compile (ctx, block_tyty); + + bool is_address_taken = false; + tree ret_var_stmt = NULL_TREE; + Bvariable *tmp = ctx->get_backend ()->temporary_variable ( + fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, + expr.get_locus (), &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + ctx->push_loop_context (tmp); + + if (expr.has_loop_label ()) + { + HIR::LoopLabel &loop_label = expr.get_loop_label (); + tree label + = ctx->get_backend ()->label (fnctx.fndecl, + loop_label.get_lifetime ().get_name (), + loop_label.get_locus ()); + 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); + } + + tree loop_begin_label + = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); + 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); + + tree code_block + = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); + tree loop_expr + = ctx->get_backend ()->loop_expression (code_block, expr.get_locus ()); + ctx->add_statement (loop_expr); + + ctx->pop_loop_context (); + translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + + ctx->pop_loop_begin_label (); +} + +void +CompileExpr::visit (HIR::WhileLoopExpr &expr) +{ + fncontext fnctx = ctx->peek_fn (); + if (expr.has_loop_label ()) + { + HIR::LoopLabel &loop_label = expr.get_loop_label (); + tree label + = ctx->get_backend ()->label (fnctx.fndecl, + loop_label.get_lifetime ().get_name (), + loop_label.get_locus ()); + 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); + } + + std::vector<Bvariable *> locals; + Location start_location = expr.get_loop_block ()->get_locus (); + Location end_location = expr.get_loop_block ()->get_locus (); // FIXME + + 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); + + tree loop_begin_label + = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); + 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); + + tree condition + = CompileExpr::Compile (expr.get_predicate_expr ().get (), ctx); + tree exit_expr + = ctx->get_backend ()->exit_expression (condition, expr.get_locus ()); + ctx->add_statement (exit_expr); + + tree code_block_stmt + = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); + rust_assert (TREE_CODE (code_block_stmt) == BIND_EXPR); + ctx->add_statement (code_block_stmt); + + ctx->pop_loop_begin_label (); + ctx->pop_block (); + + tree loop_expr + = ctx->get_backend ()->loop_expression (loop_block, expr.get_locus ()); + ctx->add_statement (loop_expr); +} + +void +CompileExpr::visit (HIR::BreakExpr &expr) +{ + if (expr.has_break_expr ()) + { + tree compiled_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); + + Bvariable *loop_result_holder = ctx->peek_loop_context (); + tree result_reference + = ctx->get_backend ()->var_expression (loop_result_holder, + expr.get_expr ()->get_locus ()); + + tree assignment + = ctx->get_backend ()->assignment_statement (result_reference, + compiled_expr, + expr.get_locus ()); + ctx->add_statement (assignment); + } + + if (expr.has_label ()) + { + NodeId resolved_node_id = UNKNOWN_NODEID; + if (!ctx->get_resolver ()->lookup_resolved_label ( + expr.get_label ().get_mappings ().get_nodeid (), &resolved_node_id)) + { + rust_error_at ( + expr.get_label ().get_locus (), + "failed to resolve compiled label for label %s", + expr.get_label ().get_mappings ().as_string ().c_str ()); + return; + } + + HirId ref = UNKNOWN_HIRID; + if (!ctx->get_mappings ()->lookup_node_to_hir (resolved_node_id, &ref)) + { + rust_fatal_error (expr.get_locus (), "reverse lookup label failure"); + return; + } + + tree label = NULL_TREE; + if (!ctx->lookup_label_decl (ref, &label)) + { + rust_error_at (expr.get_label ().get_locus (), + "failed to lookup compiled label"); + return; + } + + tree goto_label + = ctx->get_backend ()->goto_statement (label, expr.get_locus ()); + ctx->add_statement (goto_label); + } + else + { + tree exit_expr = ctx->get_backend ()->exit_expression ( + ctx->get_backend ()->boolean_constant_expression (true), + expr.get_locus ()); + ctx->add_statement (exit_expr); + } +} + +void +CompileExpr::visit (HIR::ContinueExpr &expr) +{ + tree label = ctx->peek_loop_begin_label (); + if (expr.has_label ()) + { + NodeId resolved_node_id = UNKNOWN_NODEID; + if (!ctx->get_resolver ()->lookup_resolved_label ( + expr.get_label ().get_mappings ().get_nodeid (), &resolved_node_id)) + { + rust_error_at ( + expr.get_label ().get_locus (), + "failed to resolve compiled label for label %s", + expr.get_label ().get_mappings ().as_string ().c_str ()); + return; + } + + HirId ref = UNKNOWN_HIRID; + if (!ctx->get_mappings ()->lookup_node_to_hir (resolved_node_id, &ref)) + { + rust_fatal_error (expr.get_locus (), "reverse lookup label failure"); + return; + } + + if (!ctx->lookup_label_decl (ref, &label)) + { + rust_error_at (expr.get_label ().get_locus (), + "failed to lookup compiled label"); + return; + } + } + + translated = ctx->get_backend ()->goto_statement (label, expr.get_locus ()); +} + +void CompileExpr::visit (HIR::BorrowExpr &expr) { tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); @@ -177,6 +847,76 @@ CompileExpr::visit (HIR::DereferenceExpr &expr) translated = indirect_expression (main_expr, expr.get_locus ()); } +void +CompileExpr::visit (HIR::LiteralExpr &expr) +{ + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &tyty)) + return; + + switch (expr.get_lit_type ()) + { + case HIR::Literal::BOOL: + translated = compile_bool_literal (expr, tyty); + return; + + case HIR::Literal::INT: + translated = compile_integer_literal (expr, tyty); + return; + + case HIR::Literal::FLOAT: + translated = compile_float_literal (expr, tyty); + return; + + case HIR::Literal::CHAR: + translated = compile_char_literal (expr, tyty); + return; + + case HIR::Literal::BYTE: + translated = compile_byte_literal (expr, tyty); + return; + + case HIR::Literal::STRING: + translated = compile_string_literal (expr, tyty); + return; + + case HIR::Literal::BYTE_STRING: + translated = compile_byte_string_literal (expr, tyty); + return; + } +} + +void +CompileExpr::visit (HIR::AssignmentExpr &expr) +{ + auto lvalue = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rvalue = CompileExpr::Compile (expr.get_rhs (), ctx); + + // assignments are coercion sites so lets convert the rvalue if necessary + TyTy::BaseType *expected = nullptr; + TyTy::BaseType *actual = nullptr; + + bool ok; + ok = ctx->get_tyctx ()->lookup_type ( + expr.get_lhs ()->get_mappings ().get_hirid (), &expected); + rust_assert (ok); + + ok = ctx->get_tyctx ()->lookup_type ( + expr.get_rhs ()->get_mappings ().get_hirid (), &actual); + rust_assert (ok); + + rvalue = coercion_site (expr.get_mappings ().get_hirid (), rvalue, actual, + expected, expr.get_lhs ()->get_locus (), + expr.get_rhs ()->get_locus ()); + + tree assignment + = ctx->get_backend ()->assignment_statement (lvalue, rvalue, + expr.get_locus ()); + + ctx->add_statement (assignment); +} + // Helper for sort_tuple_patterns. // Determine whether Patterns a and b are really the same pattern. // FIXME: This is a nasty hack to avoid properly implementing a comparison diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 69f9492..4c1f95a 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -20,767 +20,52 @@ #define RUST_COMPILE_EXPR #include "rust-compile-base.h" -#include "rust-compile-resolve-path.h" -#include "rust-compile-block.h" -#include "rust-compile-struct-field-expr.h" -#include "rust-constexpr.h" namespace Rust { namespace Compile { -class CompileExpr : public HIRCompileBase, public HIR::HIRExpressionVisitor +class CompileExpr : private HIRCompileBase, protected HIR::HIRExpressionVisitor { public: - static tree Compile (HIR::Expr *expr, Context *ctx) - { - CompileExpr compiler (ctx); - expr->accept_vis (compiler); - return compiler.translated; - } - - void visit (HIR::TupleIndexExpr &expr) override - { - HIR::Expr *tuple_expr = expr.get_tuple_expr ().get (); - TupleIndex index = expr.get_tuple_index (); - - tree receiver_ref = CompileExpr::Compile (tuple_expr, ctx); - - TyTy::BaseType *tuple_expr_ty = nullptr; - bool ok = ctx->get_tyctx ()->lookup_type ( - tuple_expr->get_mappings ().get_hirid (), &tuple_expr_ty); - rust_assert (ok); - - // do we need to add an indirect reference - if (tuple_expr_ty->get_kind () == TyTy::TypeKind::REF) - { - tree indirect = indirect_expression (receiver_ref, expr.get_locus ()); - receiver_ref = indirect; - } - - translated - = ctx->get_backend ()->struct_field_expression (receiver_ref, index, - expr.get_locus ()); - } - - void visit (HIR::TupleExpr &expr) override - { - if (expr.is_unit ()) - { - translated = ctx->get_backend ()->unit_expression (); - return; - } - - TyTy::BaseType *tyty = nullptr; - if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), - &tyty)) - { - rust_fatal_error (expr.get_locus (), - "did not resolve type for this TupleExpr"); - return; - } - - tree tuple_type = TyTyResolveCompile::compile (ctx, tyty); - rust_assert (tuple_type != nullptr); - - // this assumes all fields are in order from type resolution - std::vector<tree> vals; - for (auto &elem : expr.get_tuple_elems ()) - { - auto e = CompileExpr::Compile (elem.get (), ctx); - vals.push_back (e); - } - - translated - = ctx->get_backend ()->constructor_expression (tuple_type, false, vals, - -1, expr.get_locus ()); - } - - void visit (HIR::ReturnExpr &expr) override - { - auto fncontext = ctx->peek_fn (); - - std::vector<tree> retstmts; - if (expr.has_return_expr ()) - { - tree compiled_expr - = CompileExpr::Compile (expr.return_expr.get (), ctx); - rust_assert (compiled_expr != nullptr); - - retstmts.push_back (compiled_expr); - } - - auto s = ctx->get_backend ()->return_statement (fncontext.fndecl, retstmts, - expr.get_locus ()); - ctx->add_statement (s); - } + static tree Compile (HIR::Expr *expr, Context *ctx); + void visit (HIR::TupleIndexExpr &expr) override; + void visit (HIR::TupleExpr &expr) override; + void visit (HIR::ReturnExpr &expr) override; void visit (HIR::CallExpr &expr) override; - void visit (HIR::MethodCallExpr &expr) override; - - void visit (HIR::LiteralExpr &expr) override - { - TyTy::BaseType *tyty = nullptr; - if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), - &tyty)) - return; - - switch (expr.get_lit_type ()) - { - case HIR::Literal::BOOL: - translated = compile_bool_literal (expr, tyty); - return; - - case HIR::Literal::INT: - translated = compile_integer_literal (expr, tyty); - return; - - case HIR::Literal::FLOAT: - translated = compile_float_literal (expr, tyty); - return; - - case HIR::Literal::CHAR: - translated = compile_char_literal (expr, tyty); - return; - - case HIR::Literal::BYTE: - translated = compile_byte_literal (expr, tyty); - return; - - case HIR::Literal::STRING: - translated = compile_string_literal (expr, tyty); - return; - - case HIR::Literal::BYTE_STRING: - translated = compile_byte_string_literal (expr, tyty); - return; - } - } - - void visit (HIR::AssignmentExpr &expr) override - { - auto lvalue = CompileExpr::Compile (expr.get_lhs (), ctx); - auto rvalue = CompileExpr::Compile (expr.get_rhs (), ctx); - - // assignments are coercion sites so lets convert the rvalue if necessary - TyTy::BaseType *expected = nullptr; - TyTy::BaseType *actual = nullptr; - - bool ok; - ok = ctx->get_tyctx ()->lookup_type ( - expr.get_lhs ()->get_mappings ().get_hirid (), &expected); - rust_assert (ok); - - ok = ctx->get_tyctx ()->lookup_type ( - expr.get_rhs ()->get_mappings ().get_hirid (), &actual); - rust_assert (ok); - - rvalue = coercion_site (expr.get_mappings ().get_hirid (), rvalue, actual, - expected, expr.get_lhs ()->get_locus (), - expr.get_rhs ()->get_locus ()); - - tree assignment - = ctx->get_backend ()->assignment_statement (lvalue, rvalue, - expr.get_locus ()); - - ctx->add_statement (assignment); - } - + void visit (HIR::LiteralExpr &expr) override; + void visit (HIR::AssignmentExpr &expr) override; void visit (HIR::CompoundAssignmentExpr &expr) override; - void visit (HIR::ArrayIndexExpr &expr) override; - void visit (HIR::ArrayExpr &expr) override; - void visit (HIR::ArithmeticOrLogicalExpr &expr) override; - - void visit (HIR::ComparisonExpr &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 ()->comparison_expression (op, lhs, rhs, location); - } - - void visit (HIR::LazyBooleanExpr &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 ()->lazy_boolean_expression (op, lhs, rhs, location); - } - + void visit (HIR::ComparisonExpr &expr) override; + void visit (HIR::LazyBooleanExpr &expr) override; void visit (HIR::NegationExpr &expr) override; - - void visit (HIR::TypeCastExpr &expr) override - { - TyTy::BaseType *tyty = nullptr; - if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), - &tyty)) - { - translated = error_mark_node; - return; - } - - auto type_to_cast_to = TyTyResolveCompile::compile (ctx, tyty); - auto casted_expr - = CompileExpr::Compile (expr.get_casted_expr ().get (), ctx); - translated - = type_cast_expression (type_to_cast_to, casted_expr, expr.get_locus ()); - } - - void visit (HIR::IfExpr &expr) override - { - auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr); - ctx->add_statement (stmt); - } - - void visit (HIR::IfExprConseqElse &expr) override - { - TyTy::BaseType *if_type = nullptr; - if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), - &if_type)) - { - rust_error_at (expr.get_locus (), - "failed to lookup type of IfExprConseqElse"); - return; - } - - Bvariable *tmp = NULL; - bool needs_temp = !if_type->is_unit (); - if (needs_temp) - { - fncontext fnctx = ctx->peek_fn (); - tree enclosing_scope = ctx->peek_enclosing_scope (); - tree block_type = TyTyResolveCompile::compile (ctx, if_type); - - bool is_address_taken = false; - 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); - ctx->add_statement (ret_var_stmt); - } - - auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp); - ctx->add_statement (stmt); - - if (tmp != NULL) - { - translated - = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); - } - } - - void visit (HIR::IfExprConseqIf &expr) override - { - TyTy::BaseType *if_type = nullptr; - if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), - &if_type)) - { - rust_error_at (expr.get_locus (), - "failed to lookup type of IfExprConseqElse"); - return; - } - - Bvariable *tmp = NULL; - bool needs_temp = !if_type->is_unit (); - if (needs_temp) - { - fncontext fnctx = ctx->peek_fn (); - tree enclosing_scope = ctx->peek_enclosing_scope (); - tree block_type = TyTyResolveCompile::compile (ctx, if_type); - - bool is_address_taken = false; - 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); - ctx->add_statement (ret_var_stmt); - } - - auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp); - ctx->add_statement (stmt); - - if (tmp != NULL) - { - translated - = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); - } - } - - void visit (HIR::BlockExpr &expr) override - { - TyTy::BaseType *block_tyty = nullptr; - if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), - &block_tyty)) - { - rust_error_at (expr.get_locus (), "failed to lookup type of BlockExpr"); - return; - } - - Bvariable *tmp = NULL; - bool needs_temp = !block_tyty->is_unit (); - if (needs_temp) - { - fncontext fnctx = ctx->peek_fn (); - tree enclosing_scope = ctx->peek_enclosing_scope (); - tree block_type = TyTyResolveCompile::compile (ctx, block_tyty); - - bool is_address_taken = false; - 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); - ctx->add_statement (ret_var_stmt); - } - - auto block_stmt = CompileBlock::compile (&expr, ctx, tmp); - rust_assert (TREE_CODE (block_stmt) == BIND_EXPR); - ctx->add_statement (block_stmt); - - if (tmp != NULL) - { - translated - = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); - } - } - - void visit (HIR::UnsafeBlockExpr &expr) override - { - expr.get_block_expr ()->accept_vis (*this); - } - - void visit (HIR::StructExprStruct &struct_expr) override - { - TyTy::BaseType *tyty = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - struct_expr.get_mappings ().get_hirid (), &tyty)) - { - rust_error_at (struct_expr.get_locus (), "unknown type"); - return; - } - - rust_assert (tyty->is_unit ()); - translated = ctx->get_backend ()->unit_expression (); - } - - void visit (HIR::StructExprStructFields &struct_expr) override - { - TyTy::BaseType *tyty = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - struct_expr.get_mappings ().get_hirid (), &tyty)) - { - rust_error_at (struct_expr.get_locus (), "unknown type"); - return; - } - - // it must be an ADT - rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT); - TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyty); - - // what variant is it? - int union_disriminator = struct_expr.union_index; - TyTy::VariantDef *variant = nullptr; - if (!adt->is_enum ()) - { - rust_assert (adt->number_of_variants () == 1); - variant = adt->get_variants ().at (0); - } - else - { - HirId variant_id; - bool ok = ctx->get_tyctx ()->lookup_variant_definition ( - struct_expr.get_struct_name ().get_mappings ().get_hirid (), - &variant_id); - rust_assert (ok); - - ok = adt->lookup_variant_by_id (variant_id, &variant, - &union_disriminator); - rust_assert (ok); - } - - // compile it - tree compiled_adt_type = TyTyResolveCompile::compile (ctx, tyty); - - std::vector<tree> arguments; - if (adt->is_union ()) - { - rust_assert (struct_expr.get_fields ().size () == 1); - - // assignments are coercion sites so lets convert the rvalue if - // necessary - auto respective_field - = variant->get_field_at_index (union_disriminator); - auto expected = respective_field->get_field_type (); - - // process arguments - auto &argument = struct_expr.get_fields ().at (0); - auto lvalue_locus - = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); - auto rvalue_locus = argument->get_locus (); - auto rvalue = CompileStructExprField::Compile (argument.get (), ctx); - - TyTy::BaseType *actual = nullptr; - bool ok = ctx->get_tyctx ()->lookup_type ( - argument->get_mappings ().get_hirid (), &actual); - - if (ok) - { - rvalue - = coercion_site (argument->get_mappings ().get_hirid (), rvalue, - actual, expected, lvalue_locus, rvalue_locus); - } - - // add it to the list - arguments.push_back (rvalue); - } - else - { - // this assumes all fields are in order from type resolution and if a - // base struct was specified those fields are filed via accesors - for (size_t i = 0; i < struct_expr.get_fields ().size (); i++) - { - // assignments are coercion sites so lets convert the rvalue if - // necessary - auto respective_field = variant->get_field_at_index (i); - auto expected = respective_field->get_field_type (); - - // process arguments - auto &argument = struct_expr.get_fields ().at (i); - auto lvalue_locus - = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); - auto rvalue_locus = argument->get_locus (); - auto rvalue - = CompileStructExprField::Compile (argument.get (), ctx); - - TyTy::BaseType *actual = nullptr; - bool ok = ctx->get_tyctx ()->lookup_type ( - argument->get_mappings ().get_hirid (), &actual); - - // coerce it if required/possible see - // compile/torture/struct_base_init_1.rs - if (ok) - { - rvalue = coercion_site (argument->get_mappings ().get_hirid (), - rvalue, actual, expected, lvalue_locus, - rvalue_locus); - } - - // add it to the list - arguments.push_back (rvalue); - } - } - - // the constructor depends on whether this is actually an enum or not if - // its an enum we need to setup the discriminator - std::vector<tree> ctor_arguments; - if (adt->is_enum ()) - { - HIR::Expr *discrim_expr = variant->get_discriminant (); - tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); - tree folded_discrim_expr = fold_expr (discrim_expr_node); - tree qualifier = folded_discrim_expr; - - ctor_arguments.push_back (qualifier); - } - for (auto &arg : arguments) - ctor_arguments.push_back (arg); - - translated = ctx->get_backend ()->constructor_expression ( - compiled_adt_type, adt->is_enum (), ctor_arguments, union_disriminator, - struct_expr.get_locus ()); - } - - void visit (HIR::GroupedExpr &expr) override - { - translated = CompileExpr::Compile (expr.get_expr_in_parens ().get (), ctx); - } - - void visit (HIR::FieldAccessExpr &expr) override - { - HIR::Expr *receiver_expr = expr.get_receiver_expr ().get (); - tree receiver_ref = CompileExpr::Compile (receiver_expr, ctx); - - // resolve the receiver back to ADT type - TyTy::BaseType *receiver = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - expr.get_receiver_expr ()->get_mappings ().get_hirid (), &receiver)) - { - rust_error_at (expr.get_receiver_expr ()->get_locus (), - "unresolved type for receiver"); - return; - } - - size_t field_index = 0; - if (receiver->get_kind () == TyTy::TypeKind::ADT) - { - TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver); - rust_assert (!adt->is_enum ()); - rust_assert (adt->number_of_variants () == 1); - - TyTy::VariantDef *variant = adt->get_variants ().at (0); - bool ok = variant->lookup_field (expr.get_field_name (), nullptr, - &field_index); - rust_assert (ok); - } - else if (receiver->get_kind () == TyTy::TypeKind::REF) - { - TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (receiver); - TyTy::BaseType *b = r->get_base (); - rust_assert (b->get_kind () == TyTy::TypeKind::ADT); - - TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (b); - rust_assert (!adt->is_enum ()); - rust_assert (adt->number_of_variants () == 1); - - TyTy::VariantDef *variant = adt->get_variants ().at (0); - bool ok = variant->lookup_field (expr.get_field_name (), nullptr, - &field_index); - rust_assert (ok); - - tree indirect = indirect_expression (receiver_ref, expr.get_locus ()); - receiver_ref = indirect; - } - - translated - = ctx->get_backend ()->struct_field_expression (receiver_ref, field_index, - expr.get_locus ()); - } - - void visit (HIR::QualifiedPathInExpression &expr) override - { - translated = ResolvePathRef::Compile (expr, ctx); - } - - void visit (HIR::PathInExpression &expr) override - { - translated = ResolvePathRef::Compile (expr, ctx); - } - - void visit (HIR::LoopExpr &expr) override - { - TyTy::BaseType *block_tyty = nullptr; - if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), - &block_tyty)) - { - rust_error_at (expr.get_locus (), "failed to lookup type of BlockExpr"); - return; - } - - fncontext fnctx = ctx->peek_fn (); - tree enclosing_scope = ctx->peek_enclosing_scope (); - tree block_type = TyTyResolveCompile::compile (ctx, block_tyty); - - bool is_address_taken = false; - tree ret_var_stmt = NULL_TREE; - Bvariable *tmp = ctx->get_backend ()->temporary_variable ( - fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, - expr.get_locus (), &ret_var_stmt); - ctx->add_statement (ret_var_stmt); - ctx->push_loop_context (tmp); - - if (expr.has_loop_label ()) - { - HIR::LoopLabel &loop_label = expr.get_loop_label (); - tree label - = ctx->get_backend ()->label (fnctx.fndecl, - loop_label.get_lifetime ().get_name (), - loop_label.get_locus ()); - 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); - } - - tree loop_begin_label - = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); - 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); - - tree code_block - = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); - tree loop_expr - = ctx->get_backend ()->loop_expression (code_block, expr.get_locus ()); - ctx->add_statement (loop_expr); - - ctx->pop_loop_context (); - translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); - - ctx->pop_loop_begin_label (); - } - - void visit (HIR::WhileLoopExpr &expr) override - { - fncontext fnctx = ctx->peek_fn (); - if (expr.has_loop_label ()) - { - HIR::LoopLabel &loop_label = expr.get_loop_label (); - tree label - = ctx->get_backend ()->label (fnctx.fndecl, - loop_label.get_lifetime ().get_name (), - loop_label.get_locus ()); - 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); - } - - std::vector<Bvariable *> locals; - Location start_location = expr.get_loop_block ()->get_locus (); - Location end_location = expr.get_loop_block ()->get_locus (); // FIXME - - 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); - - tree loop_begin_label - = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); - 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); - - tree condition - = CompileExpr::Compile (expr.get_predicate_expr ().get (), ctx); - tree exit_expr - = ctx->get_backend ()->exit_expression (condition, expr.get_locus ()); - ctx->add_statement (exit_expr); - - tree code_block_stmt - = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); - rust_assert (TREE_CODE (code_block_stmt) == BIND_EXPR); - ctx->add_statement (code_block_stmt); - - ctx->pop_loop_begin_label (); - ctx->pop_block (); - - tree loop_expr - = ctx->get_backend ()->loop_expression (loop_block, expr.get_locus ()); - ctx->add_statement (loop_expr); - } - - void visit (HIR::BreakExpr &expr) override - { - if (expr.has_break_expr ()) - { - tree compiled_expr - = CompileExpr::Compile (expr.get_expr ().get (), ctx); - - Bvariable *loop_result_holder = ctx->peek_loop_context (); - tree result_reference = ctx->get_backend ()->var_expression ( - loop_result_holder, expr.get_expr ()->get_locus ()); - - tree assignment - = ctx->get_backend ()->assignment_statement (result_reference, - compiled_expr, - expr.get_locus ()); - ctx->add_statement (assignment); - } - - if (expr.has_label ()) - { - NodeId resolved_node_id = UNKNOWN_NODEID; - if (!ctx->get_resolver ()->lookup_resolved_label ( - expr.get_label ().get_mappings ().get_nodeid (), - &resolved_node_id)) - { - rust_error_at ( - expr.get_label ().get_locus (), - "failed to resolve compiled label for label %s", - expr.get_label ().get_mappings ().as_string ().c_str ()); - return; - } - - HirId ref = UNKNOWN_HIRID; - if (!ctx->get_mappings ()->lookup_node_to_hir (resolved_node_id, &ref)) - { - rust_fatal_error (expr.get_locus (), - "reverse lookup label failure"); - return; - } - - tree label = NULL_TREE; - if (!ctx->lookup_label_decl (ref, &label)) - { - rust_error_at (expr.get_label ().get_locus (), - "failed to lookup compiled label"); - return; - } - - tree goto_label - = ctx->get_backend ()->goto_statement (label, expr.get_locus ()); - ctx->add_statement (goto_label); - } - else - { - tree exit_expr = ctx->get_backend ()->exit_expression ( - ctx->get_backend ()->boolean_constant_expression (true), - expr.get_locus ()); - ctx->add_statement (exit_expr); - } - } - - void visit (HIR::ContinueExpr &expr) override - { - tree label = ctx->peek_loop_begin_label (); - if (expr.has_label ()) - { - NodeId resolved_node_id = UNKNOWN_NODEID; - if (!ctx->get_resolver ()->lookup_resolved_label ( - expr.get_label ().get_mappings ().get_nodeid (), - &resolved_node_id)) - { - rust_error_at ( - expr.get_label ().get_locus (), - "failed to resolve compiled label for label %s", - expr.get_label ().get_mappings ().as_string ().c_str ()); - return; - } - - HirId ref = UNKNOWN_HIRID; - if (!ctx->get_mappings ()->lookup_node_to_hir (resolved_node_id, &ref)) - { - rust_fatal_error (expr.get_locus (), - "reverse lookup label failure"); - return; - } - - if (!ctx->lookup_label_decl (ref, &label)) - { - rust_error_at (expr.get_label ().get_locus (), - "failed to lookup compiled label"); - return; - } - } - - translated = ctx->get_backend ()->goto_statement (label, expr.get_locus ()); - } - + void visit (HIR::TypeCastExpr &expr) override; + void visit (HIR::IfExpr &expr) override; + void visit (HIR::IfExprConseqIf &expr) override; + void visit (HIR::IfExprConseqElse &expr) override; + void visit (HIR::BlockExpr &expr) override; + void visit (HIR::UnsafeBlockExpr &expr) override; + void visit (HIR::StructExprStruct &struct_expr) override; + void visit (HIR::StructExprStructFields &struct_expr) override; + void visit (HIR::GroupedExpr &expr) override; + void visit (HIR::FieldAccessExpr &expr) override; + void visit (HIR::QualifiedPathInExpression &expr) override; + void visit (HIR::PathInExpression &expr) override; + void visit (HIR::LoopExpr &expr) override; + void visit (HIR::WhileLoopExpr &expr) override; + void visit (HIR::BreakExpr &expr) override; + void visit (HIR::ContinueExpr &expr) override; void visit (HIR::BorrowExpr &expr) override; void visit (HIR::DereferenceExpr &expr) override; void visit (HIR::MatchExpr &expr) override; - void visit (HIR::RangeFromToExpr &expr) override; - void visit (HIR::RangeFromExpr &expr) override; - void visit (HIR::RangeToExpr &expr) override; - void visit (HIR::RangeFullExpr &expr) override; - void visit (HIR::RangeFromToInclExpr &expr) override; // Empty visit for unused Expression HIR nodes. @@ -852,9 +137,7 @@ protected: HIR::ArrayElemsCopied &elems); private: - CompileExpr (Context *ctx) - : HIRCompileBase (ctx), translated (error_mark_node) - {} + CompileExpr (Context *ctx); tree translated; }; diff --git a/gcc/rust/backend/rust-compile-fnparam.cc b/gcc/rust/backend/rust-compile-fnparam.cc index b1b5523..3f0ec82 100644 --- a/gcc/rust/backend/rust-compile-fnparam.cc +++ b/gcc/rust/backend/rust-compile-fnparam.cc @@ -24,6 +24,51 @@ namespace Rust { namespace Compile { +CompileFnParam::CompileFnParam (Context *ctx, tree fndecl, tree decl_type, + Location locus) + : HIRCompileBase (ctx), fndecl (fndecl), decl_type (decl_type), locus (locus), + compiled_param (ctx->get_backend ()->error_variable ()) +{} + +Bvariable * +CompileFnParam::compile (Context *ctx, tree fndecl, HIR::FunctionParam *param, + tree decl_type, Location locus) +{ + CompileFnParam compiler (ctx, fndecl, decl_type, locus); + param->get_param_name ()->accept_vis (compiler); + return compiler.compiled_param; +} + +Bvariable * +CompileFnParam::compile (Context *ctx, tree fndecl, HIR::Pattern *param, + tree decl_type, Location locus) +{ + CompileFnParam compiler (ctx, fndecl, decl_type, locus); + param->accept_vis (compiler); + return compiler.compiled_param; +} + +void +CompileFnParam::visit (HIR::IdentifierPattern &pattern) +{ + if (!pattern.is_mut ()) + decl_type = ctx->get_backend ()->immutable_type (decl_type); + + compiled_param + = ctx->get_backend ()->parameter_variable (fndecl, + pattern.get_identifier (), + decl_type, locus); +} + +void +CompileFnParam::visit (HIR::WildcardPattern &pattern) +{ + decl_type = ctx->get_backend ()->immutable_type (decl_type); + + compiled_param + = ctx->get_backend ()->parameter_variable (fndecl, "_", decl_type, locus); +} + void CompileFnParam::visit (HIR::StructPattern &pattern) { @@ -58,5 +103,19 @@ CompileFnParam::visit (HIR::TupleStructPattern &pattern) CompilePatternBindings::Compile (&pattern, anon_param, ctx); } +Bvariable * +CompileSelfParam::compile (Context *ctx, tree fndecl, HIR::SelfParam &self, + tree decl_type, Location locus) +{ + bool is_immutable + = self.get_self_kind () == HIR::SelfParam::ImplicitSelfKind::IMM + || self.get_self_kind () == HIR::SelfParam::ImplicitSelfKind::IMM_REF; + if (is_immutable) + decl_type = ctx->get_backend ()->immutable_type (decl_type); + + return ctx->get_backend ()->parameter_variable (fndecl, "self", decl_type, + locus); +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-fnparam.h b/gcc/rust/backend/rust-compile-fnparam.h index 7c4a43a..0dbbd99 100644 --- a/gcc/rust/backend/rust-compile-fnparam.h +++ b/gcc/rust/backend/rust-compile-fnparam.h @@ -24,45 +24,17 @@ namespace Rust { namespace Compile { -class CompileFnParam : public HIRCompileBase, public HIR::HIRPatternVisitor +class CompileFnParam : private HIRCompileBase, protected HIR::HIRPatternVisitor { public: static Bvariable *compile (Context *ctx, tree fndecl, HIR::FunctionParam *param, tree decl_type, - Location locus) - { - CompileFnParam compiler (ctx, fndecl, decl_type, locus); - param->get_param_name ()->accept_vis (compiler); - return compiler.compiled_param; - } - + Location locus); static Bvariable *compile (Context *ctx, tree fndecl, HIR::Pattern *param, - tree decl_type, Location locus) - { - CompileFnParam compiler (ctx, fndecl, decl_type, locus); - param->accept_vis (compiler); - return compiler.compiled_param; - } - - void visit (HIR::IdentifierPattern &pattern) override - { - if (!pattern.is_mut ()) - decl_type = ctx->get_backend ()->immutable_type (decl_type); - - compiled_param - = ctx->get_backend ()->parameter_variable (fndecl, - pattern.get_identifier (), - decl_type, locus); - } - - void visit (HIR::WildcardPattern &pattern) override - { - decl_type = ctx->get_backend ()->immutable_type (decl_type); - - compiled_param - = ctx->get_backend ()->parameter_variable (fndecl, "_", decl_type, locus); - } + tree decl_type, Location locus); + void visit (HIR::IdentifierPattern &pattern) override; + void visit (HIR::WildcardPattern &pattern) override; void visit (HIR::StructPattern &) override; void visit (HIR::TupleStructPattern &) override; @@ -77,10 +49,7 @@ public: void visit (HIR::TuplePattern &) override {} private: - CompileFnParam (Context *ctx, tree fndecl, tree decl_type, Location locus) - : HIRCompileBase (ctx), fndecl (fndecl), decl_type (decl_type), - locus (locus), compiled_param (ctx->get_backend ()->error_variable ()) - {} + CompileFnParam (Context *ctx, tree fndecl, tree decl_type, Location locus); tree fndecl; tree decl_type; @@ -88,21 +57,11 @@ private: Bvariable *compiled_param; }; -class CompileSelfParam : public HIRCompileBase, public HIR::HIRStmtVisitor +class CompileSelfParam : private HIRCompileBase { public: 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 - || self.get_self_kind () == HIR::SelfParam::ImplicitSelfKind::IMM_REF; - if (is_immutable) - decl_type = ctx->get_backend ()->immutable_type (decl_type); - - return ctx->get_backend ()->parameter_variable (fndecl, "self", decl_type, - locus); - } + tree decl_type, Location locus); }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 63316b9..3c12f10 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -24,7 +24,7 @@ namespace Rust { namespace Compile { -class CompileItem : public HIRCompileBase, public HIR::HIRStmtVisitor +class CompileItem : private HIRCompileBase, protected HIR::HIRStmtVisitor { protected: public: diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index 7e7fadd..1d8eda1 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -18,10 +18,9 @@ #include "rust-compile-pattern.h" #include "rust-compile-expr.h" +#include "rust-compile-resolve-path.h" #include "rust-constexpr.h" -#include "print-tree.h" - namespace Rust { namespace Compile { diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index f799445..4fb3d54 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -24,6 +24,7 @@ #include "rust-hir-trait-resolve.h" #include "rust-hir-path-probe.h" #include "rust-compile-extern.h" +#include "rust-constexpr.h" namespace Rust { namespace Compile { diff --git a/gcc/rust/backend/rust-compile-stmt.cc b/gcc/rust/backend/rust-compile-stmt.cc new file mode 100644 index 0000000..bfb25f1 --- /dev/null +++ b/gcc/rust/backend/rust-compile-stmt.cc @@ -0,0 +1,115 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-compile-stmt.h" +#include "rust-compile-expr.h" + +namespace Rust { +namespace Compile { + +CompileStmt::CompileStmt (Context *ctx) + : HIRCompileBase (ctx), translated (nullptr) +{} + +tree +CompileStmt::Compile (HIR::Stmt *stmt, Context *ctx) +{ + CompileStmt compiler (ctx); + stmt->accept_vis (compiler); + return compiler.translated; +} + +void +CompileStmt::visit (HIR::ExprStmtWithBlock &stmt) +{ + translated = CompileExpr::Compile (stmt.get_expr (), ctx); +} + +void +CompileStmt::visit (HIR::ExprStmtWithoutBlock &stmt) +{ + translated = CompileExpr::Compile (stmt.get_expr (), ctx); +} + +void +CompileStmt::visit (HIR::LetStmt &stmt) +{ + // nothing to do + if (!stmt.has_init_expr ()) + return; + + const HIR::Pattern &stmt_pattern = *stmt.get_pattern (); + HirId stmt_id = stmt_pattern.get_pattern_mappings ().get_hirid (); + + TyTy::BaseType *ty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (stmt_id, &ty)) + { + // FIXME this should be an assertion instead + rust_fatal_error (stmt.get_locus (), + "failed to lookup variable declaration type"); + return; + } + + Bvariable *var = nullptr; + if (!ctx->lookup_var_decl (stmt_id, &var)) + { + // FIXME this should be an assertion instead and use error mark node + rust_fatal_error (stmt.get_locus (), + "failed to lookup compiled variable declaration"); + return; + } + + 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) + return; + + TyTy::BaseType *actual = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + stmt.get_init_expr ()->get_mappings ().get_hirid (), &actual); + rust_assert (ok); + tree stmt_type = TyTyResolveCompile::compile (ctx, ty); + + Location lvalue_locus = stmt.get_pattern ()->get_locus (); + Location rvalue_locus = stmt.get_init_expr ()->get_locus (); + TyTy::BaseType *expected = ty; + init = coercion_site (stmt.get_mappings ().get_hirid (), init, actual, + expected, lvalue_locus, rvalue_locus); + + auto fnctx = ctx->peek_fn (); + if (ty->is_unit ()) + { + ctx->add_statement (init); + + auto unit_type_init_expr + = ctx->get_backend ()->constructor_expression (stmt_type, false, {}, -1, + rvalue_locus); + auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, + unit_type_init_expr); + ctx->add_statement (s); + } + else + { + auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init); + ctx->add_statement (s); + } +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h index 9bb4b7b..a0ec8b2 100644 --- a/gcc/rust/backend/rust-compile-stmt.h +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -20,94 +20,18 @@ #define RUST_COMPILE_STMT #include "rust-compile-base.h" -#include "rust-compile-expr.h" namespace Rust { namespace Compile { -class CompileStmt : public HIRCompileBase, public HIR::HIRStmtVisitor +class CompileStmt : private HIRCompileBase, protected HIR::HIRStmtVisitor { public: - static tree Compile (HIR::Stmt *stmt, Context *ctx) - { - CompileStmt compiler (ctx); - stmt->accept_vis (compiler); - return compiler.translated; - } + static tree Compile (HIR::Stmt *stmt, Context *ctx); - void visit (HIR::ExprStmtWithBlock &stmt) override - { - translated = CompileExpr::Compile (stmt.get_expr (), ctx); - } - - void visit (HIR::ExprStmtWithoutBlock &stmt) override - { - translated = CompileExpr::Compile (stmt.get_expr (), ctx); - } - - void visit (HIR::LetStmt &stmt) override - { - // nothing to do - if (!stmt.has_init_expr ()) - return; - - const HIR::Pattern &stmt_pattern = *stmt.get_pattern (); - HirId stmt_id = stmt_pattern.get_pattern_mappings ().get_hirid (); - - TyTy::BaseType *ty = nullptr; - if (!ctx->get_tyctx ()->lookup_type (stmt_id, &ty)) - { - // FIXME this should be an assertion instead - rust_fatal_error (stmt.get_locus (), - "failed to lookup variable declaration type"); - return; - } - - Bvariable *var = nullptr; - if (!ctx->lookup_var_decl (stmt_id, &var)) - { - // FIXME this should be an assertion instead and use error mark node - rust_fatal_error (stmt.get_locus (), - "failed to lookup compiled variable declaration"); - return; - } - - 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) - return; - - TyTy::BaseType *actual = nullptr; - bool ok = ctx->get_tyctx ()->lookup_type ( - stmt.get_init_expr ()->get_mappings ().get_hirid (), &actual); - rust_assert (ok); - tree stmt_type = TyTyResolveCompile::compile (ctx, ty); - - Location lvalue_locus = stmt.get_pattern ()->get_locus (); - Location rvalue_locus = stmt.get_init_expr ()->get_locus (); - TyTy::BaseType *expected = ty; - init = coercion_site (stmt.get_mappings ().get_hirid (), init, actual, - expected, lvalue_locus, rvalue_locus); - - auto fnctx = ctx->peek_fn (); - if (ty->is_unit ()) - { - ctx->add_statement (init); - - auto unit_type_init_expr - = ctx->get_backend ()->constructor_expression (stmt_type, false, {}, - -1, rvalue_locus); - auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, - unit_type_init_expr); - ctx->add_statement (s); - } - else - { - auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init); - ctx->add_statement (s); - } - } + void visit (HIR::ExprStmtWithBlock &stmt) override; + void visit (HIR::ExprStmtWithoutBlock &stmt) override; + void visit (HIR::LetStmt &stmt) override; // Empty visit for unused Stmt HIR nodes. void visit (HIR::TupleStruct &) override {} @@ -134,7 +58,7 @@ public: void visit (HIR::EmptyStmt &) override {} private: - CompileStmt (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} + CompileStmt (Context *ctx); tree translated; }; diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.cc b/gcc/rust/backend/rust-compile-struct-field-expr.cc new file mode 100644 index 0000000..c9a2811 --- /dev/null +++ b/gcc/rust/backend/rust-compile-struct-field-expr.cc @@ -0,0 +1,81 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-compile-struct-field-expr.h" +#include "rust-compile-expr.h" + +namespace Rust { +namespace Compile { + +CompileStructExprField::CompileStructExprField (Context *ctx) + : HIRCompileBase (ctx), translated (error_mark_node) +{} + +tree +CompileStructExprField::Compile (HIR::StructExprField *field, Context *ctx) +{ + CompileStructExprField compiler (ctx); + switch (field->get_kind ()) + { + case HIR::StructExprField::StructExprFieldKind::IDENTIFIER: + compiler.visit (static_cast<HIR::StructExprFieldIdentifier &> (*field)); + break; + + case HIR::StructExprField::StructExprFieldKind::IDENTIFIER_VALUE: + compiler.visit ( + static_cast<HIR::StructExprFieldIdentifierValue &> (*field)); + break; + + case HIR::StructExprField::StructExprFieldKind::INDEX_VALUE: + compiler.visit (static_cast<HIR::StructExprFieldIndexValue &> (*field)); + break; + } + return compiler.translated; +} + +void +CompileStructExprField::visit (HIR::StructExprFieldIdentifierValue &field) +{ + translated = CompileExpr::Compile (field.get_value (), ctx); +} + +void +CompileStructExprField::visit (HIR::StructExprFieldIndexValue &field) +{ + translated = CompileExpr::Compile (field.get_value (), ctx); +} + +void +CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field) +{ + // we can make the field look like a path expr to take advantage of existing + // code + + Analysis::NodeMapping mappings_copy1 = field.get_mappings (); + Analysis::NodeMapping mappings_copy2 = field.get_mappings (); + + HIR::PathIdentSegment ident_seg (field.get_field_name ()); + HIR::PathExprSegment seg (mappings_copy1, ident_seg, field.get_locus (), + HIR::GenericArgs::create_empty ()); + HIR::PathInExpression expr (mappings_copy2, {seg}, field.get_locus (), false, + {}); + translated = CompileExpr::Compile (&expr, ctx); +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.h b/gcc/rust/backend/rust-compile-struct-field-expr.h index 90c3140..bc5da08 100644 --- a/gcc/rust/backend/rust-compile-struct-field-expr.h +++ b/gcc/rust/backend/rust-compile-struct-field-expr.h @@ -24,79 +24,18 @@ namespace Rust { namespace Compile { -class CompileStructExprField : public HIRCompileBase, - public HIR::HIRExpressionVisitor +class CompileStructExprField : private HIRCompileBase { public: - static tree Compile (HIR::StructExprField *field, Context *ctx) - { - CompileStructExprField compiler (ctx); - field->accept_vis (compiler); - rust_assert (compiler.translated != nullptr); - return compiler.translated; - } + static tree Compile (HIR::StructExprField *field, Context *ctx); - void visit (HIR::StructExprFieldIdentifierValue &field) override; - void visit (HIR::StructExprFieldIndexValue &field) override; - void visit (HIR::StructExprFieldIdentifier &field) override; - - // Empty visit for unused Expression HIR nodes. - void visit (HIR::PathInExpression &) override {} - void visit (HIR::QualifiedPathInExpression &) override {} - void visit (HIR::ClosureExprInner &) override {} - void visit (HIR::ClosureExprInnerTyped &) override {} - void visit (HIR::StructExprStruct &) override {} - void visit (HIR::StructExprStructFields &) override {} - void visit (HIR::LiteralExpr &) override {} - void visit (HIR::BorrowExpr &) override {} - void visit (HIR::DereferenceExpr &) override {} - void visit (HIR::ErrorPropagationExpr &) override {} - void visit (HIR::NegationExpr &) override {} - void visit (HIR::ArithmeticOrLogicalExpr &) override {} - void visit (HIR::ComparisonExpr &) override {} - void visit (HIR::LazyBooleanExpr &) override {} - void visit (HIR::TypeCastExpr &) override {} - void visit (HIR::AssignmentExpr &) override {} - void visit (HIR::CompoundAssignmentExpr &) override {} - void visit (HIR::GroupedExpr &) override {} - void visit (HIR::ArrayExpr &) override {} - void visit (HIR::ArrayIndexExpr &) override {} - void visit (HIR::TupleExpr &) override {} - void visit (HIR::TupleIndexExpr &) override {} - void visit (HIR::CallExpr &) override {} - void visit (HIR::MethodCallExpr &) override {} - void visit (HIR::FieldAccessExpr &) override {} - void visit (HIR::BlockExpr &) override {} - void visit (HIR::ContinueExpr &) override {} - void visit (HIR::BreakExpr &) override {} - void visit (HIR::RangeFromToExpr &) override {} - void visit (HIR::RangeFromExpr &) override {} - void visit (HIR::RangeToExpr &) override {} - void visit (HIR::RangeFullExpr &) override {} - void visit (HIR::RangeFromToInclExpr &) override {} - void visit (HIR::RangeToInclExpr &) override {} - void visit (HIR::ReturnExpr &) override {} - void visit (HIR::UnsafeBlockExpr &) override {} - void visit (HIR::LoopExpr &) override {} - void visit (HIR::WhileLoopExpr &) override {} - void visit (HIR::WhileLetLoopExpr &) override {} - void visit (HIR::ForLoopExpr &) override {} - void visit (HIR::IfExpr &) override {} - void visit (HIR::IfExprConseqElse &) override {} - void visit (HIR::IfExprConseqIf &) override {} - void visit (HIR::IfExprConseqIfLet &) override {} - void visit (HIR::IfLetExpr &) override {} - void visit (HIR::IfLetExprConseqElse &) override {} - void visit (HIR::IfLetExprConseqIf &) override {} - void visit (HIR::IfLetExprConseqIfLet &) override {} - void visit (HIR::MatchExpr &) override {} - void visit (HIR::AwaitExpr &) override {} - void visit (HIR::AsyncBlockExpr &) override {} +protected: + void visit (HIR::StructExprFieldIdentifierValue &field); + void visit (HIR::StructExprFieldIndexValue &field); + void visit (HIR::StructExprFieldIdentifier &field); private: - CompileStructExprField (Context *ctx) - : HIRCompileBase (ctx), translated (nullptr) - {} + CompileStructExprField (Context *ctx); tree translated; }; diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h index c9b6b62..b52fd71 100644 --- a/gcc/rust/backend/rust-compile-type.h +++ b/gcc/rust/backend/rust-compile-type.h @@ -24,7 +24,7 @@ namespace Rust { namespace Compile { -class TyTyResolveCompile : public TyTy::TyConstVisitor +class TyTyResolveCompile : protected TyTy::TyConstVisitor { public: static tree compile (Context *ctx, const TyTy::BaseType *ty, diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index c4100c4..6913144 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -16,16 +16,17 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -#include "rust-hir-trait-resolve.h" -#include "rust-hir-path-probe.h" -#include "rust-hir-type-bounds.h" -#include "rust-hir-dot-operator.h" #include "rust-compile.h" #include "rust-compile-item.h" #include "rust-compile-implitem.h" #include "rust-compile-expr.h" #include "rust-compile-struct-field-expr.h" #include "rust-compile-stmt.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" +#include "rust-compile-block.h" namespace Rust { namespace Compile { @@ -50,158 +51,6 @@ CompileCrate::go () CompileItem::compile (item.get (), ctx); } -// rust-compile-block.h - -void -CompileBlock::visit (HIR::BlockExpr &expr) -{ - fncontext fnctx = ctx->peek_fn (); - tree fndecl = fnctx.fndecl; - Location start_location = expr.get_locus (); - Location end_location = expr.get_end_locus (); - auto body_mappings = expr.get_mappings (); - - Resolver::Rib *rib = nullptr; - if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), &rib)) - { - rust_fatal_error (expr.get_locus (), "failed to setup locals per block"); - return; - } - - std::vector<Bvariable *> locals - = compile_locals_for_block (ctx, *rib, fndecl); - - 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 ()) - { - auto compiled_expr = CompileStmt::Compile (s.get (), ctx); - if (compiled_expr != nullptr) - { - tree s = convert_to_void (compiled_expr, ICV_STATEMENT); - ctx->add_statement (s); - } - } - - if (expr.has_expr ()) - { - // the previous passes will ensure this is a valid return or - // a valid trailing expression - tree compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx); - if (compiled_expr != nullptr) - { - if (result == nullptr) - { - ctx->add_statement (compiled_expr); - } - else - { - tree result_reference = ctx->get_backend ()->var_expression ( - result, expr.get_final_expr ()->get_locus ()); - - tree assignment - = ctx->get_backend ()->assignment_statement (result_reference, - compiled_expr, - expr.get_locus ()); - ctx->add_statement (assignment); - } - } - } - - ctx->pop_block (); - translated = new_block; -} - -void -CompileConditionalBlocks::visit (HIR::IfExpr &expr) -{ - fncontext fnctx = ctx->peek_fn (); - 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, - NULL, expr.get_locus ()); -} - -void -CompileConditionalBlocks::visit (HIR::IfExprConseqElse &expr) -{ - fncontext fnctx = ctx->peek_fn (); - 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, - else_block, expr.get_locus ()); -} - -void -CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr) -{ - fncontext fnctx = ctx->peek_fn (); - 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 - 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); - - tree else_stmt_decl - = CompileConditionalBlocks::compile (expr.get_conseq_if_expr (), ctx, - result); - ctx->add_statement (else_stmt_decl); - - ctx->pop_block (); - - translated - = ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block, - else_block, expr.get_locus ()); -} - -// rust-compile-struct-field-expr.h - -void -CompileStructExprField::visit (HIR::StructExprFieldIdentifierValue &field) -{ - translated = CompileExpr::Compile (field.get_value (), ctx); -} - -void -CompileStructExprField::visit (HIR::StructExprFieldIndexValue &field) -{ - translated = CompileExpr::Compile (field.get_value (), ctx); -} - -void -CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field) -{ - // we can make the field look like a path expr to take advantage of existing - // code - - Analysis::NodeMapping mappings_copy1 = field.get_mappings (); - Analysis::NodeMapping mappings_copy2 = field.get_mappings (); - - HIR::PathIdentSegment ident_seg (field.get_field_name ()); - HIR::PathExprSegment seg (mappings_copy1, ident_seg, field.get_locus (), - HIR::GenericArgs::create_empty ()); - HIR::PathInExpression expr (mappings_copy2, {seg}, field.get_locus (), false, - {}); - translated = CompileExpr::Compile (&expr, ctx); -} - // Shared methods in compilation tree |