diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-02-10 10:33:33 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2021-02-10 18:10:57 +0000 |
commit | ae273ffac99cb75d832a11a83fd63291bb74cbdc (patch) | |
tree | a3d9a44ebe75c96fac728c8f4ed3d0796664ed29 /gcc | |
parent | 016c40bedc7e3f53e2c413895f77c0d9f723eb3c (diff) | |
download | gcc-ae273ffac99cb75d832a11a83fd63291bb74cbdc.zip gcc-ae273ffac99cb75d832a11a83fd63291bb74cbdc.tar.gz gcc-ae273ffac99cb75d832a11a83fd63291bb74cbdc.tar.bz2 |
Support Break without label and expression
This reuses GENERICS LOOP_EXPR and EXIT_EXPR to implement the infinite
loop.
Addresses: #106 #108
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 13 | ||||
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 13 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 30 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 37 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-base.h | 37 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-block.h | 4 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-expr.h | 25 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-expr.h | 30 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-item.h | 3 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-type.h | 2 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir.h | 26 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.h | 51 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.cc | 2 | ||||
-rw-r--r-- | gcc/rust/rust-backend.h | 6 | ||||
-rw-r--r-- | gcc/rust/rust-gcc.cc | 23 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 10 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/loop2.rs | 14 |
17 files changed, 262 insertions, 64 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 392c36a..b61c8c3 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1139,11 +1139,14 @@ private: Location locus; + NodeId node_id; + public: // Constructor Lifetime (LifetimeType type, std::string name = std::string (), Location locus = Location ()) - : lifetime_type (type), lifetime_name (std::move (name)), locus (locus) + : lifetime_type (type), lifetime_name (std::move (name)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // Creates an "error" lifetime. @@ -1159,6 +1162,14 @@ public: void accept_vis (ASTVisitor &vis) override; + LifetimeType get_lifetime_type () { return lifetime_type; } + + Location get_locus () { return locus; } + + std::string get_lifetime_name () const { return lifetime_name; } + + NodeId get_node_id () const { return node_id; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 50006d1..52e3abc 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -3103,6 +3103,8 @@ public: return break_expr; } + Lifetime &get_label () { return label; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3670,11 +3672,14 @@ class LoopLabel /*: public Node*/ Lifetime label; // or type LIFETIME_OR_LABEL Location locus; + NodeId node_id; + public: std::string as_string () const; LoopLabel (Lifetime loop_label, Location locus = Location ()) - : label (std::move (loop_label)), locus (locus) + : label (std::move (loop_label)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // Returns whether the LoopLabel is in an error state. @@ -3684,6 +3689,10 @@ public: static LoopLabel error () { return LoopLabel (Lifetime::error ()); } Location get_locus () const { return locus; } + + Lifetime &get_lifetime () { return label; } + + NodeId get_node_id () const { return node_id; } }; // Base loop expression AST node - aka LoopExpr @@ -3743,6 +3752,8 @@ protected: public: bool has_loop_label () const { return !loop_label.is_error (); } + LoopLabel &get_loop_label () { return loop_label; } + Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 77b8888..92cb392 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -582,21 +582,25 @@ public: void visit (HIR::LoopExpr &expr) { - // loop_start: - // <loop_body> - // goto loop_start; fncontext fnctx = ctx->peek_fn (); - Blabel *loop_start - = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); - Bstatement *label_decl_stmt - = ctx->get_backend ()->label_definition_statement (loop_start); - ctx->add_statement (label_decl_stmt); - - translated = CompileExpr::Compile (expr.get_loop_block ().get (), ctx); + Bblock *code_block + = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); + Bexpression *loop_expr + = ctx->get_backend ()->loop_expression (code_block, expr.get_locus ()); + Bstatement *loop_stmt + = ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr); + ctx->add_statement (loop_stmt); + } - Bstatement *goto_loop_start_stmt - = ctx->get_backend ()->goto_statement (loop_start, Location ()); - ctx->add_statement (goto_loop_start_stmt); + void visit (HIR::BreakExpr &expr) + { + fncontext fnctx = ctx->peek_fn (); + Bexpression *exit_expr = ctx->get_backend ()->exit_expression ( + ctx->get_backend ()->boolean_constant_expression (true), + expr.get_locus ()); + Bstatement *break_stmt + = ctx->get_backend ()->expression_statement (fnctx.fndecl, exit_expr); + ctx->add_statement (break_stmt); } private: diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 600b2f9..dd87d45 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -236,23 +236,28 @@ CompileBlock::visit (HIR::BlockExpr &expr) // the previous passes will ensure this is a valid return // dead code elimination should remove any bad trailing expressions Bexpression *compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx); - rust_assert (compiled_expr != nullptr); - - if (result == nullptr) - { - Bstatement *final_stmt - = ctx->get_backend ()->expression_statement (fnctx.fndecl, - compiled_expr); - ctx->add_statement (final_stmt); - } - else + if (compiled_expr != nullptr) { - Bexpression *result_reference = ctx->get_backend ()->var_expression ( - result, expr.get_final_expr ()->get_locus_slow ()); - - Bstatement *assignment = ctx->get_backend ()->assignment_statement ( - fnctx.fndecl, result_reference, compiled_expr, expr.get_locus ()); - ctx->add_statement (assignment); + if (result == nullptr) + { + Bstatement *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_slow ()); + + Bstatement *assignment + = ctx->get_backend ()->assignment_statement (fnctx.fndecl, + result_reference, + compiled_expr, + expr.get_locus ()); + ctx->add_statement (assignment); + } } } diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index 093129e..95d93d0 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -243,6 +243,43 @@ protected: ASTLoweringBase () : mappings (Analysis::Mappings::get ()) {} Analysis::Mappings *mappings; + + HIR::Lifetime lower_lifetime (AST::Lifetime &lifetime) + { + HIR::Lifetime::LifetimeType type = HIR::Lifetime::LifetimeType::NAMED; + switch (lifetime.get_lifetime_type ()) + { + case AST::Lifetime::LifetimeType::NAMED: + type = HIR::Lifetime::LifetimeType::NAMED; + break; + case AST::Lifetime::LifetimeType::STATIC: + type = HIR::Lifetime::LifetimeType::STATIC; + break; + case AST::Lifetime::LifetimeType::WILDCARD: + type = HIR::Lifetime::LifetimeType::WILDCARD; + break; + } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, lifetime.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + return HIR::Lifetime (mapping, type, lifetime.get_lifetime_name (), + lifetime.get_locus ()); + } + + HIR::LoopLabel lower_loop_label (AST::LoopLabel &loop_label) + { + HIR::Lifetime life = lower_lifetime (loop_label.get_lifetime ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, loop_label.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + return HIR::LoopLabel (mapping, std::move (life), loop_label.get_locus ()); + } }; } // namespace HIR diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h index d3c61df..c945042 100644 --- a/gcc/rust/hir/rust-ast-lower-block.h +++ b/gcc/rust/hir/rust-ast-lower-block.h @@ -141,6 +141,8 @@ public: = ASTLoweringBlock::translate (expr.get_loop_block ().get (), &terminated); + HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ()); + auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), @@ -149,7 +151,7 @@ public: translated = new HIR::LoopExpr (mapping, std::unique_ptr<HIR::BlockExpr> (loop_block), - expr.get_locus (), HIR::LoopLabel::error (), + expr.get_locus (), std::move (loop_label), std::move (outer_attribs)); } diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 49ac7f1..e10448f 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -74,8 +74,6 @@ public: return compiler.translated; } - ~ASTLowerPathInExpression () {} - void visit (AST::PathInExpression &expr) { std::vector<HIR::PathExprSegment> path_segments; @@ -702,9 +700,30 @@ public: translated = ASTLoweringExprWithBlock::translate (&expr, &terminated); } + void visit (AST::BreakExpr &expr) + { + std::vector<HIR::Attribute> outer_attribs; + HIR::Lifetime break_label = lower_lifetime (expr.get_label ()); + HIR::Expr *break_expr + = expr.has_break_expr () + ? ASTLoweringExpr::translate (expr.get_break_expr ().get ()) + : nullptr; + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::BreakExpr (mapping, expr.get_locus (), + std ::move (break_label), + std::unique_ptr<HIR::Expr> (break_expr), + std::move (outer_attribs)); + } + private: ASTLoweringExpr () - : translated (nullptr), translated_array_elems (nullptr), terminated (false) + : ASTLoweringBase (), translated (nullptr), + translated_array_elems (nullptr), terminated (false) {} HIR::Expr *translated; diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 14b223a..fe884bb 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2712,8 +2712,7 @@ public: bool has_label () const { return !label.is_error (); } // Constructor for a ContinueExpr with a label. - ContinueExpr (Analysis::NodeMapping mappings, Location locus, - Lifetime label = Lifetime::error (), + ContinueExpr (Analysis::NodeMapping mappings, Location locus, Lifetime label, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), @@ -2765,7 +2764,7 @@ public: // Constructor for a break expression BreakExpr (Analysis::NodeMapping mappings, Location locus, - Lifetime break_label = Lifetime::error (), + Lifetime break_label, std::unique_ptr<Expr> expr_in_break = nullptr, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), @@ -2803,6 +2802,10 @@ public: void accept_vis (HIRVisitor &vis) override; + Lifetime &get_label () { return label; } + + std::unique_ptr<Expr> &get_expr () { return break_expr; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3266,20 +3269,21 @@ class LoopLabel /*: public Node*/ Location locus; + Analysis::NodeMapping mappings; + public: std::string as_string () const; - LoopLabel (Lifetime loop_label, Location locus = Location ()) - : label (std::move (loop_label)), locus (locus) + LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label, Location locus) + : label (std::move (loop_label)), locus (locus), mappings (mapping) {} // Returns whether the LoopLabel is in an error state. bool is_error () const { return label.is_error (); } - // Creates an error state LoopLabel. - static LoopLabel error () { return LoopLabel (Lifetime::error ()); } - Location get_locus () const { return locus; } + + Analysis::NodeMapping &get_mappings () { return mappings; } }; // Base loop expression HIR node - aka LoopExpr @@ -3299,7 +3303,7 @@ protected: // Constructor for BaseLoopExpr BaseLoopExpr (Analysis::NodeMapping mappings, std::unique_ptr<BlockExpr> loop_block, Location locus, - LoopLabel loop_label = LoopLabel::error (), + LoopLabel loop_label, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : ExprWithBlock (std::move (mappings), std::move (outer_attribs)), @@ -3347,7 +3351,7 @@ public: // Constructor for LoopExpr LoopExpr (Analysis::NodeMapping mappings, std::unique_ptr<BlockExpr> loop_block, Location locus, - LoopLabel loop_label = LoopLabel::error (), + LoopLabel loop_label, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, std::move (loop_label), std::move (outer_attribs)) @@ -3380,7 +3384,7 @@ public: WhileLoopExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> loop_condition, std::unique_ptr<BlockExpr> loop_block, Location locus, - LoopLabel loop_label = LoopLabel::error (), + LoopLabel loop_label, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, @@ -3442,7 +3446,7 @@ public: std::vector<std::unique_ptr<Pattern> > match_arm_patterns, std::unique_ptr<Expr> condition, std::unique_ptr<BlockExpr> loop_block, Location locus, - LoopLabel loop_label = LoopLabel::error (), + LoopLabel loop_label, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, @@ -3515,7 +3519,7 @@ public: std::unique_ptr<Pattern> loop_pattern, std::unique_ptr<Expr> iterator_expr, std::unique_ptr<BlockExpr> loop_body, Location locus, - LoopLabel loop_label = LoopLabel::error (), + LoopLabel loop_label, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : BaseLoopExpr (std::move (mappings), std::move (loop_body), locus, std::move (loop_label), std::move (outer_attribs)), diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 4ab23e1..c0d6d0f 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -324,7 +324,8 @@ public: // Type-based self parameter (not ref, no lifetime) SelfParam (Analysis::NodeMapping mappings, std::unique_ptr<Type> type, bool is_mut, Location locus) - : has_ref (false), is_mut (is_mut), lifetime (Lifetime::error ()), + : has_ref (false), is_mut (is_mut), + lifetime (Lifetime (mappings, Lifetime::LifetimeType::NAMED, "", locus)), type (std::move (type)), locus (locus), mappings (mappings) {} diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h index ebed119..746e3e2 100644 --- a/gcc/rust/hir/tree/rust-hir-type.h +++ b/gcc/rust/hir/tree/rust-hir-type.h @@ -531,7 +531,7 @@ public: // Constructor ReferenceType (Analysis::NodeMapping mappings, bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds, Location locus, - Lifetime lifetime = Lifetime::error ()) + Lifetime lifetime) : TypeNoBounds (mappings), lifetime (std::move (lifetime)), has_mut (is_mut), type (std::move (type_no_bounds)), locus (locus) {} diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index 6fd6297..1567215 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -1060,16 +1060,16 @@ private: Location locus; + Analysis::NodeMapping mappings; + public: // Constructor - Lifetime (LifetimeType type, std::string name = std::string (), - Location locus = Location ()) - : lifetime_type (type), lifetime_name (std::move (name)), locus (locus) + Lifetime (Analysis::NodeMapping mapping, LifetimeType type, std::string name, + Location locus) + : lifetime_type (type), lifetime_name (std::move (name)), locus (locus), + mappings (mapping) {} - // Creates an "error" lifetime. - static Lifetime error () { return Lifetime (NAMED, std::string ("")); } - // Returns true if the lifetime is in an error state. bool is_error () const { @@ -1080,6 +1080,14 @@ public: void accept_vis (HIRVisitor &vis) override; + std::string get_name () const { return lifetime_name; } + + LifetimeType get_lifetime_type () const { return lifetime_type; } + + Location get_locus () const { return locus; } + + Analysis::NodeMapping get_mappings () const { return mappings; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1133,12 +1141,6 @@ public: // Returns whether the lifetime param has an outer attribute. bool has_outer_attribute () const { return !outer_attr.is_empty (); } - // Creates an error state lifetime param. - static LifetimeParam create_error () - { - return LifetimeParam (Lifetime::error ()); - } - // Returns whether the lifetime param is in an error state. bool is_error () const { return lifetime.is_error (); } diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index e8ee8b3..9cfa04d 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -243,9 +243,60 @@ public: void visit (AST::LoopExpr &expr) { + if (expr.has_loop_label ()) + { + auto label = expr.get_loop_label (); + if (label.get_lifetime ().get_lifetime_type () + != AST::Lifetime::LifetimeType::NAMED) + { + rust_error_at (label.get_locus (), + "Labels must be a named lifetime value"); + return; + } + + auto label_name = label.get_lifetime ().get_lifetime_name (); + auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); + resolver->get_label_scope ().insert ( + label_name, label_lifetime_node_id, label.get_locus (), false, + [&] (std::string, NodeId, Location locus) -> void { + rust_error_at (label.get_locus (), + "label redefined multiple times"); + rust_error_at (locus, "was defined here"); + }); + resolver->insert_new_definition (label_lifetime_node_id, + Definition{label_lifetime_node_id, + label.get_node_id ()}); + } ResolveExpr::go (expr.get_loop_block ().get (), expr.get_node_id ()); } + void visit (AST::BreakExpr &expr) + { + if (expr.has_label ()) + { + auto label = expr.get_label (); + if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED) + { + rust_error_at (label.get_locus (), + "Labels must be a named lifetime value"); + return; + } + + NodeId resolved_node = UNKNOWN_NODEID; + if (!resolver->get_label_scope ().lookup (label.get_lifetime_name (), + &resolved_node)) + { + rust_error_at (expr.get_label ().get_locus (), + "failed to resolve label"); + return; + } + resolver->insert_resolved_label (label.get_node_id (), resolved_node); + } + + if (expr.has_break_expr ()) + ResolveExpr::go (expr.get_break_expr ().get (), expr.get_node_id ()); + } + private: ResolveExpr (NodeId parent) : ResolverBase (parent) {} }; diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 0ed2bfb..213d141 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -252,7 +252,7 @@ Resolver::insert_resolved_label (NodeId refId, NodeId defId) auto it = resolved_labels.find (refId); rust_assert (it == resolved_labels.end ()); - resolved_types[refId] = defId; + resolved_labels[refId] = defId; get_label_scope ().append_reference_for_def (refId, defId); } diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 7b0ccf9..50e8728 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -425,6 +425,12 @@ public: Location) = 0; + // infinite loop expressions + virtual Bexpression *loop_expression (Bblock *body, Location); + + // exit expressions + virtual Bexpression *exit_expression (Bexpression *condition, Location); + // Create a switch statement where the case values are constants. // CASES and STATEMENTS must have the same number of entries. If // VALUE matches any of the list in CASES[i], which will all be diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 0729b1e..82ebb98 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -326,6 +326,10 @@ public: Bstatement *except_stmt, Bstatement *finally_stmt, Location); + Bexpression *loop_expression (Bblock *body, Location); + + Bexpression *exit_expression (Bexpression *condition, Location); + // Blocks. Bblock *block (Bfunction *, Bblock *, const std::vector<Bvariable *> &, @@ -2201,6 +2205,25 @@ Gcc_backend::if_statement (Bfunction *, Bexpression *condition, return this->make_statement (ret); } +// Loops + +Bexpression * +Gcc_backend::loop_expression (Bblock *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); +} + +Bexpression * +Gcc_backend::exit_expression (Bexpression *condition, 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); +} + // Switch. Bstatement * diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 17e79d4..9fe6e4f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -39,7 +39,8 @@ public: if (resolver.infered == nullptr) { - rust_error_at (expr->get_locus_slow (), "failed to resolve expression"); + rust_error_at (expr->get_locus_slow (), + "failed to type resolve expression"); return new TyTy::ErrorType (expr->get_mappings ().get_hirid ()); } @@ -746,6 +747,13 @@ public: infered = TypeCheckExpr::Resolve (expr.get_loop_block ().get ()); } + void visit (HIR::BreakExpr &expr) + { + infered = expr.has_break_expr () + ? TypeCheckExpr::Resolve (expr.get_expr ().get ()) + : new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + } + private: TypeCheckExpr () : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr) diff --git a/gcc/testsuite/rust.test/compilable/loop2.rs b/gcc/testsuite/rust.test/compilable/loop2.rs new file mode 100644 index 0000000..3de3ea8 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/loop2.rs @@ -0,0 +1,14 @@ +fn main() { + let mut a = 1; + let mut b = 1; + + // first number in Fibonacci sequence over 10: + loop { + if b > 10 { + break; + } + let c = a + b; + a = b; + b = c; + } +} |