diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-02-10 15:47:14 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2021-02-10 18:10:57 +0000 |
commit | 06c9fd97bf3d86a08eadcadb1bc59cb392116d16 (patch) | |
tree | a74de9189504af72dff442103b5a323c7a74b48b /gcc | |
parent | f10e695fc508c472c77e968e644f710806f82f54 (diff) | |
download | gcc-06c9fd97bf3d86a08eadcadb1bc59cb392116d16.zip gcc-06c9fd97bf3d86a08eadcadb1bc59cb392116d16.tar.gz gcc-06c9fd97bf3d86a08eadcadb1bc59cb392116d16.tar.bz2 |
Support LoopLabels and break to label.
This allows for the Rust refernece example for loop labels to be compiled.
Fixes #107
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/backend/rust-compile-context.h | 16 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 66 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-base.h | 4 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-expr.h | 4 | ||||
-rw-r--r-- | gcc/rust/util/rust-hir-map.cc | 6 | ||||
-rw-r--r-- | gcc/rust/util/rust-hir-map.h | 1 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/loop4.rs | 7 |
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; + } + } +} |