From 0ccc245a06e434df2c98d7f9d6036c03e4038842 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 6 Feb 2021 18:24:42 +0000 Subject: With the merge of BlockExprs Further testing found regressions with implicit returns and type resolution. This unifies the type resolution in block expressions to be more strict and ensure everything bar the final statement should be UnitType. --- gcc/rust/backend/rust-compile-expr.h | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index b823d29..686fb7f 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -460,22 +460,31 @@ public: return; } - fncontext fnctx = ctx->peek_fn (); - 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; - Bvariable *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); + Bvariable *tmp = NULL; + bool needs_temp = block_tyty->get_kind () != TyTy::TypeKind::UNIT; + if (needs_temp) + { + fncontext fnctx = ctx->peek_fn (); + 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); + } auto code_block = CompileBlock::compile (&expr, ctx, tmp); auto block_stmt = ctx->get_backend ()->block_statement (code_block); ctx->add_statement (block_stmt); - translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + if (tmp != NULL) + { + translated + = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + } } void visit (HIR::StructExprStructFields &struct_expr) -- cgit v1.1 From 9f3ddb35959606cbf7059362acfc27a9966ac3d4 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 8 Feb 2021 10:12:43 +0000 Subject: Conditional blocks with else can resolve into a non unit type expression. When we compile if blocks the else gives us a final branch that can resolve. Single IfExpr cannot resolve as there is no final branch. This also fixes a small regression in compiling elif blocks where the gimple body was empty. Fixes #213 --- gcc/rust/backend/rust-compile-expr.h | 63 +++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 12 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 686fb7f..2dabe01 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -417,7 +417,6 @@ public: void visit (HIR::IfExprConseqElse &expr) { - // this can be a return expression TyTy::TyBase *if_type = nullptr; if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &if_type)) @@ -427,27 +426,67 @@ public: return; } - fncontext fnctx = ctx->peek_fn (); - Bblock *enclosing_scope = ctx->peek_enclosing_scope (); - Btype *block_type = TyTyResolveCompile::compile (ctx, if_type); + Bvariable *tmp = NULL; + bool needs_temp = if_type->get_kind () != TyTy::TypeKind::UNIT; + if (needs_temp) + { + fncontext fnctx = ctx->peek_fn (); + Bblock *enclosing_scope = ctx->peek_enclosing_scope (); + Btype *block_type = TyTyResolveCompile::compile (ctx, if_type); - bool is_address_taken = false; - Bstatement *ret_var_stmt = nullptr; - Bvariable *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); + 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); + } auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp); ctx->add_statement (stmt); - translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + if (tmp != NULL) + { + translated + = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + } } void visit (HIR::IfExprConseqIf &expr) { - auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr); + TyTy::TyBase *if_type = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &if_type)) + { + rust_error_at (expr.get_locus (), + "failed to lookup type of IfExprConseqElse"); + return; + } + + Bvariable *tmp = NULL; + bool needs_temp = if_type->get_kind () != TyTy::TypeKind::UNIT; + if (needs_temp) + { + fncontext fnctx = ctx->peek_fn (); + Bblock *enclosing_scope = ctx->peek_enclosing_scope (); + Btype *block_type = TyTyResolveCompile::compile (ctx, if_type); + + 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); + } + + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp); ctx->add_statement (stmt); + + if (tmp != NULL) + { + translated + = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + } } void visit (HIR::BlockExpr &expr) -- cgit v1.1 From b96299b0b96b6714d5a7b03fa6d4f1ea7d09fc44 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 8 Feb 2021 15:51:54 +0000 Subject: Fix bad type resolution for CallExpr when fn is not simply PathInExpression When we have a function that is for example a FieldAccessExpression the compiler must resolve and compile that field into a reference which can be called. This is not simple direct call to a function in that senario. Fixes #217 --- gcc/rust/backend/rust-compile.cc | 46 +++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 26 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 0b83c72..600b2f9 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -53,33 +53,9 @@ CompileCrate::go () void CompileExpr::visit (HIR::CallExpr &expr) { - // this can be a function call or it can be a constructor for a tuple struct - Bexpression *fn = ResolvePathRef::Compile (expr.get_fnexpr (), ctx); - if (fn != nullptr) + Btype *type = ResolvePathType::Compile (expr.get_fnexpr (), ctx); + if (type != nullptr) { - std::vector args; - expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool { - Bexpression *compiled_expr = CompileExpr::Compile (p, ctx); - rust_assert (compiled_expr != nullptr); - args.push_back (compiled_expr); - return true; - }); - - auto fncontext = ctx->peek_fn (); - translated - = ctx->get_backend ()->call_expression (fncontext.fndecl, fn, args, - nullptr, expr.get_locus ()); - } - else - { - Btype *type = ResolvePathType::Compile (expr.get_fnexpr (), ctx); - if (type == nullptr) - { - rust_fatal_error (expr.get_locus (), - "failed to lookup type associated with call"); - return; - } - // this assumes all fields are in order from type resolution and if a base // struct was specified those fields are filed via accesors std::vector vals; @@ -93,6 +69,24 @@ CompileExpr::visit (HIR::CallExpr &expr) = ctx->get_backend ()->constructor_expression (type, vals, expr.get_locus ()); } + else + { + // must be a call to a function + Bexpression *fn = CompileExpr::Compile (expr.get_fnexpr (), ctx); + + std::vector args; + expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool { + Bexpression *compiled_expr = CompileExpr::Compile (p, ctx); + rust_assert (compiled_expr != nullptr); + args.push_back (compiled_expr); + return true; + }); + + auto fncontext = ctx->peek_fn (); + translated + = ctx->get_backend ()->call_expression (fncontext.fndecl, fn, args, + nullptr, expr.get_locus ()); + } } void -- cgit v1.1 From 1a2c0911f0e818328a8909b1f5ba0685b6eca351 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 9 Feb 2021 17:50:39 +0000 Subject: Support Simple LoopExpr This is the building block for the rest of loops where we have a basic infinite loop. Break/Continue reliest on the resolution of labels and breaks can also make a loop into a BlockExpr Fixes #106 --- gcc/rust/backend/rust-compile-expr.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 2dabe01..77b8888 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -580,6 +580,25 @@ public: translated = ResolvePathRef::Compile (&expr, ctx); } + void visit (HIR::LoopExpr &expr) + { + // loop_start: + // + // goto loop_start; + fncontext fnctx = ctx->peek_fn (); + Blabel *loop_start + = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); + Bstatement *label_decl_stmt + = ctx->get_backend ()->label_definition_statement (loop_start); + ctx->add_statement (label_decl_stmt); + + translated = CompileExpr::Compile (expr.get_loop_block ().get (), ctx); + + Bstatement *goto_loop_start_stmt + = ctx->get_backend ()->goto_statement (loop_start, Location ()); + ctx->add_statement (goto_loop_start_stmt); + } + private: CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} -- cgit v1.1 From ae273ffac99cb75d832a11a83fd63291bb74cbdc Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 10 Feb 2021 10:33:33 +0000 Subject: Support Break without label and expression This reuses GENERICS LOOP_EXPR and EXIT_EXPR to implement the infinite loop. Addresses: #106 #108 --- gcc/rust/backend/rust-compile-expr.h | 30 ++++++++++++++++------------- gcc/rust/backend/rust-compile.cc | 37 ++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 29 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 77b8888..92cb392 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -582,21 +582,25 @@ public: void visit (HIR::LoopExpr &expr) { - // loop_start: - // - // goto loop_start; fncontext fnctx = ctx->peek_fn (); - Blabel *loop_start - = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); - Bstatement *label_decl_stmt - = ctx->get_backend ()->label_definition_statement (loop_start); - ctx->add_statement (label_decl_stmt); - - translated = CompileExpr::Compile (expr.get_loop_block ().get (), ctx); + Bblock *code_block + = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); + Bexpression *loop_expr + = ctx->get_backend ()->loop_expression (code_block, expr.get_locus ()); + Bstatement *loop_stmt + = ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr); + ctx->add_statement (loop_stmt); + } - Bstatement *goto_loop_start_stmt - = ctx->get_backend ()->goto_statement (loop_start, Location ()); - ctx->add_statement (goto_loop_start_stmt); + 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); } private: diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 600b2f9..dd87d45 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -236,23 +236,28 @@ CompileBlock::visit (HIR::BlockExpr &expr) // the previous passes will ensure this is a valid return // dead code elimination should remove any bad trailing expressions Bexpression *compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx); - rust_assert (compiled_expr != nullptr); - - if (result == nullptr) - { - Bstatement *final_stmt - = ctx->get_backend ()->expression_statement (fnctx.fndecl, - compiled_expr); - ctx->add_statement (final_stmt); - } - else + if (compiled_expr != nullptr) { - Bexpression *result_reference = ctx->get_backend ()->var_expression ( - result, expr.get_final_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 (result == nullptr) + { + Bstatement *final_stmt + = ctx->get_backend ()->expression_statement (fnctx.fndecl, + compiled_expr); + ctx->add_statement (final_stmt); + } + else + { + Bexpression *result_reference + = ctx->get_backend ()->var_expression ( + result, expr.get_final_expr ()->get_locus_slow ()); + + Bstatement *assignment + = ctx->get_backend ()->assignment_statement (fnctx.fndecl, + result_reference, + compiled_expr, + expr.get_locus ()); + ctx->add_statement (assignment); + } } } -- cgit v1.1 From f10e695fc508c472c77e968e644f710806f82f54 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 10 Feb 2021 14:38:10 +0000 Subject: Return expressions can be empty which us unit-type The parser has the same bug as in #225 for break expressions. This tidies up the type resolver and GENERIC translation to handle the case where there is no return expression as well. Fixes #226 --- gcc/rust/backend/rust-compile-expr.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 92cb392..0c8d25a 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -84,14 +84,18 @@ public: void visit (HIR::ReturnExpr &expr) { - Bexpression *compiled_expr - = CompileExpr::Compile (expr.return_expr.get (), ctx); - rust_assert (compiled_expr != nullptr); - auto fncontext = ctx->peek_fn (); std::vector retstmts; - retstmts.push_back (compiled_expr); + if (expr.has_return_expr ()) + { + Bexpression *compiled_expr + = CompileExpr::Compile (expr.return_expr.get (), ctx); + rust_assert (compiled_expr != nullptr); + + retstmts.push_back (compiled_expr); + } + auto s = ctx->get_backend ()->return_statement (fncontext.fndecl, retstmts, expr.get_locus ()); ctx->add_statement (s); -- cgit v1.1 From 06c9fd97bf3d86a08eadcadb1bc59cb392116d16 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 10 Feb 2021 15:47:14 +0000 Subject: Support LoopLabels and break to label. This allows for the Rust refernece example for loop labels to be compiled. Fixes #107 --- gcc/rust/backend/rust-compile-context.h | 16 ++++++++ gcc/rust/backend/rust-compile-expr.h | 66 +++++++++++++++++++++++++++++---- 2 files changed, 75 insertions(+), 7 deletions(-) (limited to 'gcc/rust/backend') 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 compiled_type_map; std::map compiled_fn_map; std::map compiled_consts; + std::map compiled_labels; std::vector< ::std::vector > 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: -- cgit v1.1 From 0c7d0135663b6f0d94e0ffd931366ba2b32f8b2c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 10 Feb 2021 17:51:58 +0000 Subject: 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 --- gcc/rust/backend/rust-compile-context.h | 12 +++++++++ gcc/rust/backend/rust-compile-expr.h | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 8a74a05..288b917 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -208,6 +208,17 @@ public: return false; } + void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); } + + Bvariable *peek_loop_context () { return loop_value_stack.back (); } + + Bvariable *pop_loop_context () + { + auto back = loop_value_stack.back (); + loop_value_stack.pop_back (); + return back; + } + private: ::Backend *backend; Resolver::Resolver *resolver; @@ -223,6 +234,7 @@ private: std::map compiled_labels; std::vector< ::std::vector > statements; std::vector< ::Bblock *> scope_stack; + std::vector< ::Bvariable *> loop_value_stack; // To GCC middle-end std::vector< ::Btype *> type_decls; 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; -- cgit v1.1