aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile-expr.h53
-rw-r--r--gcc/rust/hir/rust-ast-lower-block.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h5
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc27
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h30
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h40
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h6
-rw-r--r--gcc/testsuite/rust.test/compilable/loop6.rs11
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/break2.rs14
10 files changed, 183 insertions, 7 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 7b25c5e..1ca7631 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -641,11 +641,61 @@ public:
}
}
+ void visit (HIR::WhileLoopExpr &expr)
+ {
+ fncontext fnctx = ctx->peek_fn ();
+ if (expr.has_loop_label ())
+ {
+ HIR::LoopLabel &loop_label = expr.get_loop_label ();
+ Blabel *label
+ = ctx->get_backend ()->label (fnctx.fndecl,
+ loop_label.get_lifetime ().get_name (),
+ loop_label.get_locus ());
+ Bstatement *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
+
+ Bblock *enclosing_scope = ctx->peek_enclosing_scope ();
+ Bblock *loop_block
+ = ctx->get_backend ()->block (fnctx.fndecl, enclosing_scope, locals,
+ start_location, end_location);
+ ctx->push_block (loop_block);
+
+ Bexpression *condition
+ = CompileExpr::Compile (expr.get_predicate_expr ().get (), ctx);
+ Bexpression *exit_expr
+ = ctx->get_backend ()->exit_expression (condition, expr.get_locus ());
+ Bstatement *break_stmt
+ = ctx->get_backend ()->expression_statement (fnctx.fndecl, exit_expr);
+ ctx->add_statement (break_stmt);
+
+ Bblock *code_block
+ = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr);
+ Bstatement *code_block_stmt
+ = ctx->get_backend ()->block_statement (code_block);
+ ctx->add_statement (code_block_stmt);
+
+ ctx->pop_block ();
+
+ Bexpression *loop_expr
+ = ctx->get_backend ()->loop_expression (loop_block, expr.get_locus ());
+ Bstatement *loop_stmt
+ = ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr);
+ ctx->add_statement (loop_stmt);
+ }
+
void visit (HIR::BreakExpr &expr)
{
+ fncontext fnctx = ctx->peek_fn ();
if (expr.has_break_expr ())
{
- fncontext fnctx = ctx->peek_fn ();
Bexpression *compiled_expr
= CompileExpr::Compile (expr.get_expr ().get (), ctx);
@@ -695,7 +745,6 @@ public:
}
else
{
- fncontext fnctx = ctx->peek_fn ();
Bexpression *exit_expr = ctx->get_backend ()->exit_expression (
ctx->get_backend ()->boolean_constant_expression (true),
expr.get_locus ());
diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h
index c945042..ec0f895 100644
--- a/gcc/rust/hir/rust-ast-lower-block.h
+++ b/gcc/rust/hir/rust-ast-lower-block.h
@@ -155,6 +155,8 @@ public:
std::move (outer_attribs));
}
+ void visit (AST::WhileLoopExpr &expr);
+
private:
ASTLoweringExprWithBlock ()
: ASTLoweringBase (), translated (nullptr), terminated (false)
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h
index e10448f..8e80c7a 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -700,6 +700,11 @@ public:
translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
}
+ void visit (AST::WhileLoopExpr &expr)
+ {
+ translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
+ }
+
void visit (AST::BreakExpr &expr)
{
std::vector<HIR::Attribute> outer_attribs;
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index c1ea01a..230919a 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -242,5 +242,32 @@ ASTLowerStructExprField::visit (AST::StructExprFieldIdentifier &field)
field.get_locus ());
}
+// rust-ast-lower-block.h
+
+void
+ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr)
+{
+ std::vector<HIR::Attribute> outer_attribs;
+ HIR::BlockExpr *loop_block
+ = ASTLoweringBlock::translate (expr.get_loop_block ().get (), &terminated);
+
+ HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ());
+ HIR::Expr *loop_condition
+ = ASTLoweringExpr::translate (expr.get_predicate_expr ().get (),
+ &terminated);
+
+ 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::WhileLoopExpr (mapping,
+ std::unique_ptr<HIR::Expr> (loop_condition),
+ std::unique_ptr<HIR::BlockExpr> (loop_block),
+ expr.get_locus (), std::move (loop_label),
+ std::move (outer_attribs));
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index e92e059..3fd2ebc 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -3419,6 +3419,8 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ std::unique_ptr<Expr> &get_predicate_expr () { return condition; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index 9cfa04d..38a878c 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -297,6 +297,36 @@ public:
ResolveExpr::go (expr.get_break_expr ().get (), expr.get_node_id ());
}
+ void visit (AST::WhileLoopExpr &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_predicate_expr ().get (), expr.get_node_id ());
+ ResolveExpr::go (expr.get_loop_block ().get (), expr.get_node_id ());
+ }
+
private:
ResolveExpr (NodeId parent) : ResolverBase (parent) {}
};
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 87aeae6..7062f54 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -670,10 +670,6 @@ public:
void visit (HIR::GroupedExpr &expr)
{
- printf ("inside grouped expr: \n%s\n inside it is: \n%s\n",
- expr.as_string ().c_str (),
- expr.get_expr_in_parens ()->as_string ().c_str ());
-
infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get (), false);
}
@@ -758,7 +754,15 @@ public:
void visit (HIR::LoopExpr &expr)
{
context->push_new_loop_context (expr.get_mappings ().get_hirid ());
- TypeCheckExpr::Resolve (expr.get_loop_block ().get (), true);
+ TyTy::TyBase *block_expr
+ = TypeCheckExpr::Resolve (expr.get_loop_block ().get (), true);
+ if (block_expr->get_kind () != TyTy::TypeKind::UNIT)
+ {
+ rust_error_at (expr.get_loop_block ()->get_locus_slow (),
+ "expected () got %s", block_expr->as_string ().c_str ());
+ return;
+ }
+
TyTy::TyBase *loop_context_type = context->pop_loop_context ();
bool loop_context_type_infered
@@ -772,6 +776,25 @@ public:
: new TyTy::UnitType (expr.get_mappings ().get_hirid ());
}
+ void visit (HIR::WhileLoopExpr &expr)
+ {
+ context->push_new_while_loop_context (expr.get_mappings ().get_hirid ());
+
+ TypeCheckExpr::Resolve (expr.get_predicate_expr ().get (), false);
+ TyTy::TyBase *block_expr
+ = TypeCheckExpr::Resolve (expr.get_loop_block ().get (), true);
+
+ if (block_expr->get_kind () != TyTy::TypeKind::UNIT)
+ {
+ rust_error_at (expr.get_loop_block ()->get_locus_slow (),
+ "expected () got %s", block_expr->as_string ().c_str ());
+ return;
+ }
+
+ context->pop_loop_context ();
+ infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ());
+ }
+
void visit (HIR::BreakExpr &expr)
{
if (!inside_loop)
@@ -786,6 +809,13 @@ public:
= TypeCheckExpr::Resolve (expr.get_expr ().get (), false);
TyTy::TyBase *loop_context = context->peek_loop_context ();
+ if (loop_context->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (expr.get_locus (),
+ "can only break with a value inside `loop`");
+ return;
+ }
+
TyTy::TyBase *combined = loop_context->combine (break_expr_tyty);
context->swap_head_loop_context (combined);
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index 531d241..aa11b7e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -63,6 +63,12 @@ public:
loop_type_stack.push_back (infer_var);
}
+ void push_new_while_loop_context (HirId id)
+ {
+ TyTy::TyBase *infer_var = new TyTy::ErrorType (id);
+ loop_type_stack.push_back (infer_var);
+ }
+
TyTy::TyBase *peek_loop_context () { return loop_type_stack.back (); }
TyTy::TyBase *pop_loop_context ()
diff --git a/gcc/testsuite/rust.test/compilable/loop6.rs b/gcc/testsuite/rust.test/compilable/loop6.rs
new file mode 100644
index 0000000..ecd3ad4
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/loop6.rs
@@ -0,0 +1,11 @@
+fn main() {
+ let mut a = 1;
+ let mut b = 1;
+
+ let mut c;
+ while b > 10 {
+ c = a + b;
+ a = b;
+ b = c;
+ }
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/break2.rs b/gcc/testsuite/rust.test/fail_compilation/break2.rs
new file mode 100644
index 0000000..53cee9a
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/break2.rs
@@ -0,0 +1,14 @@
+fn main() {
+ let mut a = 1;
+ let mut b = 1;
+
+ let mut c;
+ while b > 10 {
+ if (b == 2) {
+ break b;
+ }
+ c = a + b;
+ a = b;
+ b = c;
+ }
+}