aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/rust/backend/rust-compile-context.h16
-rw-r--r--gcc/rust/backend/rust-compile-expr.h66
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h4
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h4
-rw-r--r--gcc/rust/util/rust-hir-map.cc6
-rw-r--r--gcc/rust/util/rust-hir-map.h1
-rw-r--r--gcc/testsuite/rust.test/compilable/loop4.rs7
7 files changed, 97 insertions, 7 deletions
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index 25c9b89..8a74a05 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -162,6 +162,21 @@ public:
return true;
}
+ void insert_label_decl (HirId id, ::Blabel *label)
+ {
+ compiled_labels[id] = label;
+ }
+
+ bool lookup_label_decl (HirId id, ::Blabel **label)
+ {
+ auto it = compiled_labels.find (id);
+ if (it == compiled_labels.end ())
+ return false;
+
+ *label = it->second;
+ return true;
+ }
+
void push_fn (::Bfunction *fn, ::Bvariable *ret_addr)
{
fn_stack.push_back (fncontext{fn, ret_addr});
@@ -205,6 +220,7 @@ private:
std::map<HirId, ::Btype *> compiled_type_map;
std::map<HirId, ::Bfunction *> compiled_fn_map;
std::map<HirId, ::Bexpression *> compiled_consts;
+ std::map<HirId, ::Blabel *> compiled_labels;
std::vector< ::std::vector<Bstatement *> > statements;
std::vector< ::Bblock *> scope_stack;
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 0c8d25a..189118b 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -587,6 +587,20 @@ public:
void visit (HIR::LoopExpr &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);
+ }
+
Bblock *code_block
= CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr);
Bexpression *loop_expr
@@ -598,13 +612,51 @@ public:
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);
+ 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 (
+ expr.get_mappings ().get_crate_num (), resolved_node_id, &ref))
+ {
+ rust_fatal_error (expr.get_locus (),
+ "reverse lookup label failure");
+ return;
+ }
+
+ Blabel *label = nullptr;
+ if (!ctx->lookup_label_decl (ref, &label))
+ {
+ rust_error_at (expr.get_label ().get_locus (),
+ "failed to lookup compiled label");
+ return;
+ }
+
+ Bstatement *goto_label
+ = ctx->get_backend ()->goto_statement (label, expr.get_locus ());
+ ctx->add_statement (goto_label);
+ }
+ else
+ {
+ 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/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index 95d93d0..beeff87 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -264,6 +264,8 @@ protected:
Analysis::NodeMapping mapping (crate_num, lifetime.get_node_id (),
mappings->get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
+ mappings->insert_node_to_hir (mapping.get_crate_num (),
+ mapping.get_nodeid (), mapping.get_hirid ());
return HIR::Lifetime (mapping, type, lifetime.get_lifetime_name (),
lifetime.get_locus ());
@@ -277,6 +279,8 @@ protected:
Analysis::NodeMapping mapping (crate_num, loop_label.get_node_id (),
mappings->get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
+ mappings->insert_node_to_hir (mapping.get_crate_num (),
+ mapping.get_nodeid (), mapping.get_hirid ());
return HIR::LoopLabel (mapping, std::move (life), loop_label.get_locus ());
}
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index fe884bb..e92e059 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -3284,6 +3284,8 @@ public:
Location get_locus () const { return locus; }
Analysis::NodeMapping &get_mappings () { return mappings; }
+
+ Lifetime &get_lifetime () { return label; }
};
// Base loop expression HIR node - aka LoopExpr
@@ -3340,6 +3342,8 @@ public:
Location get_locus_slow () const override { return get_locus (); }
std::unique_ptr<HIR::BlockExpr> &get_loop_block () { return loop_block; };
+
+ LoopLabel &get_loop_label () { return loop_label; }
};
// 'Loop' expression (i.e. the infinite loop) HIR node
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 8a15631..4a1d4f7 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -460,6 +460,12 @@ Mappings::walk_local_defids_for_crate (CrateNum crateNum,
}
}
+void
+Mappings::insert_node_to_hir (CrateNum crate, NodeId id, HirId ref)
+{
+ nodeIdToHirMappings[crate][id] = ref;
+}
+
bool
Mappings::lookup_node_to_hir (CrateNum crate, NodeId id, HirId *ref)
{
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 0d625f6..b7dbd45 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -136,6 +136,7 @@ public:
void walk_local_defids_for_crate (CrateNum crateNum,
std::function<bool (HIR::Item *)> cb);
+ void insert_node_to_hir (CrateNum crate, NodeId id, HirId ref);
bool lookup_node_to_hir (CrateNum crate, NodeId id, HirId *ref);
void insert_location (CrateNum crate, HirId id, Location locus);
diff --git a/gcc/testsuite/rust.test/compilable/loop4.rs b/gcc/testsuite/rust.test/compilable/loop4.rs
new file mode 100644
index 0000000..f7b5935
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/loop4.rs
@@ -0,0 +1,7 @@
+fn main() {
+ 'outer: loop {
+ 'inner: loop {
+ break 'outer;
+ }
+ }
+}