diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-02-08 10:12:43 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2021-02-09 09:46:54 +0000 |
commit | 9f3ddb35959606cbf7059362acfc27a9966ac3d4 (patch) | |
tree | 3cb0dd2a04c8d2166266a6bea55f285ba88a4625 /gcc/rust/backend/rust-compile-expr.h | |
parent | 0ccc245a06e434df2c98d7f9d6036c03e4038842 (diff) | |
download | gcc-9f3ddb35959606cbf7059362acfc27a9966ac3d4.zip gcc-9f3ddb35959606cbf7059362acfc27a9966ac3d4.tar.gz gcc-9f3ddb35959606cbf7059362acfc27a9966ac3d4.tar.bz2 |
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
Diffstat (limited to 'gcc/rust/backend/rust-compile-expr.h')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 63 |
1 files changed, 51 insertions, 12 deletions
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) |