diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-02-10 17:51:58 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2021-02-10 18:10:57 +0000 |
commit | 0c7d0135663b6f0d94e0ffd931366ba2b32f8b2c (patch) | |
tree | 5955326e3e944c45de7a96eb989adb2cd7c4538a /gcc/rust/backend/rust-compile-expr.h | |
parent | d02ab5925b612678beb975d99951b1d2052958a1 (diff) | |
download | gcc-0c7d0135663b6f0d94e0ffd931366ba2b32f8b2c.zip gcc-0c7d0135663b6f0d94e0ffd931366ba2b32f8b2c.tar.gz gcc-0c7d0135663b6f0d94e0ffd931366ba2b32f8b2c.tar.bz2 |
Add support to break from loops with a value
This adds support to make the break value assignable such that the loop
now becomes akin to a BlockExpr
Fixes #108 #106
Diffstat (limited to 'gcc/rust/backend/rust-compile-expr.h')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 189118b..7b25c5e 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -586,7 +586,31 @@ public: void visit (HIR::LoopExpr &expr) { + TyTy::TyBase *block_tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &block_tyty)) + { + rust_error_at (expr.get_locus (), "failed to lookup type of BlockExpr"); + return; + } + fncontext fnctx = ctx->peek_fn (); + Bvariable *tmp = NULL; + bool needs_temp = block_tyty->get_kind () != TyTy::TypeKind::UNIT; + if (needs_temp) + { + Bblock *enclosing_scope = ctx->peek_enclosing_scope (); + Btype *block_type = TyTyResolveCompile::compile (ctx, block_tyty); + + bool is_address_taken = false; + Bstatement *ret_var_stmt = nullptr; + tmp = ctx->get_backend ()->temporary_variable ( + fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, + expr.get_locus (), &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + ctx->push_loop_context (tmp); + } + if (expr.has_loop_label ()) { HIR::LoopLabel &loop_label = expr.get_loop_label (); @@ -608,10 +632,32 @@ public: Bstatement *loop_stmt = ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr); ctx->add_statement (loop_stmt); + + if (tmp != NULL) + { + ctx->pop_loop_context (); + translated + = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + } } void visit (HIR::BreakExpr &expr) { + if (expr.has_break_expr ()) + { + fncontext fnctx = ctx->peek_fn (); + Bexpression *compiled_expr + = CompileExpr::Compile (expr.get_expr ().get (), ctx); + + Bvariable *loop_result_holder = ctx->peek_loop_context (); + Bexpression *result_reference = ctx->get_backend ()->var_expression ( + loop_result_holder, expr.get_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 (expr.has_label ()) { NodeId resolved_node_id = UNKNOWN_NODEID; |