Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions gcc/rust/backend/rust-compile-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,34 @@ class Context
return true;
}

void insert_break_label (HirId id, tree label)
{
compiled_break_labels[id] = label;
}

bool lookup_break_label (HirId id, tree *label)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if the old API uses an out pointer with a bool return value most of the new APIs try to use optional when available.

{
auto it = compiled_break_labels.find (id);
if (it == compiled_break_labels.end ())
return false;
*label = it->second;
return true;
}

void insert_continue_label (HirId id, tree label)
{
compiled_continue_labels[id] = label;
}

bool lookup_continue_label (HirId id, tree *label)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise.

{
auto it = compiled_continue_labels.find (id);
if (it == compiled_continue_labels.end ())
return false;
*label = it->second;
return true;
}

void insert_pattern_binding (HirId id, tree binding)
{
implicit_pattern_bindings[id] = binding;
Expand Down Expand Up @@ -355,6 +383,21 @@ class Context
return pop;
}

void push_loop_end_label (tree label) { loop_end_labels.push_back (label); }

tree peek_loop_end_label ()
{
rust_assert (!loop_end_labels.empty ());
return loop_end_labels.back ();
}

tree pop_loop_end_label ()
{
tree pop = loop_end_labels.back ();
loop_end_labels.pop_back ();
return pop;
}

void push_const_context (void) { const_context++; }
void pop_const_context (void)
{
Expand Down Expand Up @@ -417,10 +460,13 @@ class Context
std::map<HirId, tree> compiled_fn_map;
std::map<HirId, tree> compiled_consts;
std::map<HirId, tree> compiled_labels;
std::map<HirId, tree> compiled_break_labels;
std::map<HirId, tree> compiled_continue_labels;
std::vector<::std::vector<tree>> statements;
std::vector<tree> scope_stack;
std::vector<::Bvariable *> loop_value_stack;
std::vector<tree> loop_begin_labels;
std::vector<tree> loop_end_labels;
std::map<DefId, std::vector<std::pair<const TyTy::BaseType *, tree>>>
mono_fns;
std::map<DefId, std::vector<std::pair<const TyTy::ClosureType *, tree>>>
Expand Down
105 changes: 65 additions & 40 deletions gcc/rust/backend/rust-compile-expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
// <http://www.gnu.org/licenses/>.

#include "rust-compile-expr.h"
#include "line-map.h"
#include "optional.h"
#include "rust-backend.h"
#include "rust-compile-type.h"
#include "rust-compile-struct-field-expr.h"
Expand Down Expand Up @@ -758,24 +760,14 @@ CompileExpr::visit (HIR::LoopExpr &expr)
ctx->add_statement (ret_var_stmt);
ctx->push_loop_context (tmp);

tl::optional<HIR::LoopLabel> loop_label = tl::nullopt;
if (expr.has_loop_label ())
{
HIR::LoopLabel &loop_label = expr.get_loop_label ();
tree label
= Backend::label (fnctx.fndecl, loop_label.get_lifetime ().get_name (),
loop_label.get_locus ());
tree label_decl = Backend::label_definition_statement (label);
ctx->add_statement (label_decl);
ctx->insert_label_decl (
loop_label.get_lifetime ().get_mappings ().get_hirid (), label);
}
loop_label = tl::optional<HIR::LoopLabel> (expr.get_loop_label ());
std::pair<tree, tree> loop_labels = construct_loop_labels (loop_label);
tree loop_begin_label = loop_labels.first;
tree loop_end_label = loop_labels.second;

tree loop_begin_label
= Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ());
tree loop_begin_label_decl
= Backend::label_definition_statement (loop_begin_label);
ctx->add_statement (loop_begin_label_decl);
ctx->push_loop_begin_label (loop_begin_label);
ctx->add_statement (loop_begin_label);

tree code_block
= CompileBlock::compile (expr.get_loop_block (), ctx, nullptr);
Expand All @@ -784,41 +776,31 @@ CompileExpr::visit (HIR::LoopExpr &expr)

ctx->pop_loop_context ();
translated = Backend::var_expression (tmp, expr.get_locus ());

ctx->add_statement (loop_end_label);
ctx->pop_loop_begin_label ();
ctx->pop_loop_end_label ();
}

void
CompileExpr::visit (HIR::WhileLoopExpr &expr)
{
fncontext fnctx = ctx->peek_fn ();
tree enclosing_scope = ctx->peek_enclosing_scope ();
ctx->push_loop_context (nullptr);
tl::optional<HIR::LoopLabel> loop_label = tl::nullopt;
if (expr.has_loop_label ())
{
HIR::LoopLabel &loop_label = expr.get_loop_label ();
tree label
= Backend::label (fnctx.fndecl, loop_label.get_lifetime ().get_name (),
loop_label.get_locus ());
tree label_decl = Backend::label_definition_statement (label);
ctx->add_statement (label_decl);
ctx->insert_label_decl (
loop_label.get_lifetime ().get_mappings ().get_hirid (), label);
}

loop_label = tl::optional<HIR::LoopLabel> (expr.get_loop_label ());
std::pair<tree, tree> loop_labels = construct_loop_labels (loop_label);
tree loop_begin_label = loop_labels.first;
tree loop_end_label = loop_labels.second;
std::vector<Bvariable *> locals;
location_t start_location = expr.get_loop_block ().get_locus ();
location_t end_location = expr.get_loop_block ().get_locus (); // FIXME

tree enclosing_scope = ctx->peek_enclosing_scope ();
tree loop_block = Backend::block (fnctx.fndecl, enclosing_scope, locals,
start_location, end_location);
ctx->push_block (loop_block);

tree loop_begin_label
= Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ());
tree loop_begin_label_decl
= Backend::label_definition_statement (loop_begin_label);
ctx->add_statement (loop_begin_label_decl);
ctx->push_loop_begin_label (loop_begin_label);
ctx->add_statement (loop_begin_label);

HIR::Expr &predicate = expr.get_predicate_expr ();
TyTy::BaseType *predicate_type = nullptr;
Expand Down Expand Up @@ -847,6 +829,9 @@ CompileExpr::visit (HIR::WhileLoopExpr &expr)

tree loop_expr = Backend::loop_expression (loop_block, expr.get_locus ());
ctx->add_statement (loop_expr);
ctx->add_statement (loop_end_label);
ctx->pop_loop_end_label ();

translated = unit_expression (expr.get_locus ());
}

Expand All @@ -862,6 +847,9 @@ CompileExpr::visit (HIR::BreakExpr &expr)
return;

Bvariable *loop_result_holder = ctx->peek_loop_context ();
if (loop_result_holder == nullptr)
return;

tree result_reference
= Backend::var_expression (loop_result_holder,
expr.get_expr ().get_locus ());
Expand Down Expand Up @@ -902,7 +890,7 @@ CompileExpr::visit (HIR::BreakExpr &expr)
auto ref = hid.value ();

tree label = NULL_TREE;
if (!ctx->lookup_label_decl (ref, &label))
if (!ctx->lookup_break_label (ref, &label))
{
rust_error_at (expr.get_label ().get_locus (),
"failed to lookup compiled label");
Expand All @@ -925,8 +913,7 @@ void
CompileExpr::visit (HIR::ContinueExpr &expr)
{
translated = error_mark_node;
if (!ctx->have_loop_context ())
return;
rust_assert (ctx->have_loop_context () && "continue is outside of loop");

tree label = ctx->peek_loop_begin_label ();
if (expr.has_label ())
Expand Down Expand Up @@ -958,7 +945,7 @@ CompileExpr::visit (HIR::ContinueExpr &expr)
}
auto ref = hid.value ();

if (!ctx->lookup_label_decl (ref, &label))
if (!ctx->lookup_continue_label (ref, &label))
{
rust_error_at (expr.get_label ().get_locus (),
"failed to lookup compiled label");
Expand Down Expand Up @@ -2758,5 +2745,43 @@ CompileExpr::generate_possible_fn_trait_call (HIR::CallExpr &expr,
return true;
}

std::pair<tree, tree>
CompileExpr::construct_loop_labels (tl::optional<HIR::LoopLabel> opt_loop_label)
{
fncontext fnctx = ctx->peek_fn ();
tree break_label_decl = NULL_TREE;
tree break_label_expr = NULL_TREE;
tree continue_label_decl = NULL_TREE;
tree continue_label_expr = NULL_TREE;
location_t label_locus = UNKNOWN_LOCATION;
tl::optional<std::string> continue_label_name = tl::nullopt;
tl::optional<std::string> break_label_name = tl::nullopt;
tl::optional<HirId> label_hirid = tl::nullopt;
if (opt_loop_label.has_value ())
{
label_locus = opt_loop_label.value ().get_locus ();
HIR::LoopLabel &loop_label = opt_loop_label.value ();
std::string label_name = loop_label.get_lifetime ().get_name ();
continue_label_name = label_name + "_continue";
break_label_name = label_name + "_break";
label_hirid = loop_label.get_lifetime ().get_mappings ().get_hirid ();
}
continue_label_decl
= Backend::label (fnctx.fndecl, continue_label_name, label_locus);
continue_label_expr
= Backend::label_definition_statement (continue_label_decl);
break_label_decl
= Backend::label (fnctx.fndecl, break_label_name, label_locus);
break_label_expr = Backend::label_definition_statement (break_label_decl);
if (label_hirid.has_value ())
{
ctx->insert_continue_label (label_hirid.value (), continue_label_decl);
ctx->insert_break_label (label_hirid.value (), break_label_decl);
}
ctx->push_loop_begin_label (continue_label_decl);
ctx->push_loop_end_label (break_label_decl);
return std::make_pair (continue_label_expr, break_label_expr);
}

} // namespace Compile
} // namespace Rust
4 changes: 4 additions & 0 deletions gcc/rust/backend/rust-compile-expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#ifndef RUST_COMPILE_EXPR
#define RUST_COMPILE_EXPR

#include "optional.h"
#include "rust-compile-base.h"
#include "rust-hir-visitor.h"

Expand Down Expand Up @@ -151,6 +152,9 @@ class CompileExpr : private HIRCompileBase, protected HIR::HIRExpressionVisitor
bool generate_possible_fn_trait_call (HIR::CallExpr &expr, tree receiver,
tree *result);

std::pair<tree, tree>
construct_loop_labels (tl::optional<HIR::LoopLabel> loop_label);

private:
CompileExpr (Context *ctx);

Expand Down
20 changes: 20 additions & 0 deletions gcc/rust/resolve/rust-default-resolver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,26 @@ DefaultResolver::visit (AST::Function &function)
function.get_function_name ());
}

void
DefaultResolver::visit (AST::LoopExpr &expr)
{
ctx.scoped (Rib::Kind::Normal, expr.get_node_id (),
[this, &expr] () { AST::DefaultASTVisitor::visit (expr); });
}

void
DefaultResolver::visit (AST::WhileLoopExpr &expr)
{
ctx.scoped (Rib::Kind::Normal, expr.get_node_id (),
[this, &expr] () { AST::DefaultASTVisitor::visit (expr); });
}

void
DefaultResolver::visit (AST::WhileLetLoopExpr &expr)
{
ctx.scoped (Rib::Kind::Normal, expr.get_node_id (),
[this, &expr] () { AST::DefaultASTVisitor::visit (expr); });
}
void
DefaultResolver::visit (AST::ForLoopExpr &expr)
{
Expand Down
3 changes: 3 additions & 0 deletions gcc/rust/resolve/rust-default-resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class DefaultResolver : public AST::DefaultASTVisitor
void visit (AST::BlockExpr &) override;
void visit (AST::Module &) override;
void visit (AST::Function &) override;
void visit (AST::LoopExpr &expr) override;
void visit (AST::WhileLoopExpr &expr) override;
void visit (AST::WhileLetLoopExpr &expr) override;
void visit (AST::ForLoopExpr &expr) override;
virtual void visit_if_let_patterns (AST::IfLetExpr &expr);
void visit (AST::IfLetExpr &expr) override;
Expand Down
9 changes: 7 additions & 2 deletions gcc/rust/resolve/rust-late-name-resolver-2.0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,13 @@ void
Late::visit (AST::LoopLabel &label)
{
auto &lifetime = label.get_lifetime ();
ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()),
lifetime.get_node_id ());
auto resolved = ctx.lookup (lifetime.get_node_id ());
if (!resolved.has_value ())
{
ctx.labels.insert (Identifier (lifetime.as_string (),
lifetime.get_locus ()),
lifetime.get_node_id ());
}
}

void
Expand Down
14 changes: 9 additions & 5 deletions gcc/rust/resolve/rust-name-resolution-context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns)
return macros.insert (name, id);
case Namespace::Labels:
default:
// return labels.insert (name, id);
return labels.insert (name, id);
rust_unreachable ();
}
}
Expand Down Expand Up @@ -229,8 +229,8 @@ NameResolutionContext::insert_shadowable (Identifier name, NodeId id,
case Namespace::Macros:
return macros.insert_shadowable (name, id);
case Namespace::Labels:
return labels.insert (name, id);
default:
// return labels.insert (name, id);
rust_unreachable ();
}
}
Expand All @@ -247,8 +247,8 @@ NameResolutionContext::insert_globbed (Identifier name, NodeId id, Namespace ns)
case Namespace::Macros:
return macros.insert_globbed (name, id);
case Namespace::Labels:
return labels.insert (name, id);
default:
// return labels.insert (name, id);
rust_unreachable ();
}
}
Expand Down Expand Up @@ -282,14 +282,14 @@ NameResolutionContext::scoped (Rib::Kind rib_kind, NodeId id,
values.push (rib_kind, id, path);
types.push (rib_kind, id, path);
macros.push (rib_kind, id, path);
// labels.push (rib, id);
labels.push (rib_kind, id, path);

lambda ();

values.pop ();
types.pop ();
macros.pop ();
// labels.pop (rib);
labels.pop ();
}

void
Expand All @@ -310,6 +310,8 @@ NameResolutionContext::scoped (Rib::Kind rib_kind, Namespace ns,
types.push (rib_kind, scope_id, path);
break;
case Namespace::Labels:
labels.push (rib_kind, scope_id, path);
break;
case Namespace::Macros:
gcc_unreachable ();
}
Expand All @@ -325,6 +327,8 @@ NameResolutionContext::scoped (Rib::Kind rib_kind, Namespace ns,
types.pop ();
break;
case Namespace::Labels:
labels.pop ();
break;
case Namespace::Macros:
gcc_unreachable ();
}
Expand Down
Loading
Loading