aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-02-10 10:33:33 +0000
committerPhilip Herron <herron.philip@googlemail.com>2021-02-10 18:10:57 +0000
commitae273ffac99cb75d832a11a83fd63291bb74cbdc (patch)
treea3d9a44ebe75c96fac728c8f4ed3d0796664ed29 /gcc
parent016c40bedc7e3f53e2c413895f77c0d9f723eb3c (diff)
downloadgcc-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.h13
-rw-r--r--gcc/rust/ast/rust-expr.h13
-rw-r--r--gcc/rust/backend/rust-compile-expr.h30
-rw-r--r--gcc/rust/backend/rust-compile.cc37
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h37
-rw-r--r--gcc/rust/hir/rust-ast-lower-block.h4
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h25
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h30
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h3
-rw-r--r--gcc/rust/hir/tree/rust-hir-type.h2
-rw-r--r--gcc/rust/hir/tree/rust-hir.h26
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h51
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc2
-rw-r--r--gcc/rust/rust-backend.h6
-rw-r--r--gcc/rust/rust-gcc.cc23
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h10
-rw-r--r--gcc/testsuite/rust.test/compilable/loop2.rs14
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;
+ }
+}