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 +++++---- gcc/rust/typecheck/rust-hir-type-check-expr.h | 79 ++++------------------- gcc/rust/typecheck/rust-hir-type-check-implitem.h | 42 +++--------- gcc/rust/typecheck/rust-hir-type-check-item.h | 23 ++----- gcc/rust/typecheck/rust-hir-type-check-stmt.h | 18 ++---- gcc/rust/typecheck/rust-hir-type-check.cc | 16 +++-- 6 files changed, 67 insertions(+), 142 deletions(-) (limited to 'gcc/rust') 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) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index e6cca19..e7fa3b3 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -32,9 +32,9 @@ namespace Resolver { class TypeCheckExpr : public TypeCheckBase { public: - static TyTy::TyBase *Resolve (HIR::Expr *expr, bool is_final_expr = false) + static TyTy::TyBase *Resolve (HIR::Expr *expr) { - TypeCheckExpr resolver (is_final_expr); + TypeCheckExpr resolver; expr->accept_vis (resolver); if (resolver.infered == nullptr) @@ -277,11 +277,13 @@ public: void visit (HIR::AssignmentExpr &expr) { + infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); - infered = lhs->combine (rhs); - if (infered == nullptr) + auto result = lhs->combine (rhs); + if (result == nullptr) { rust_error_at (expr.get_locus (), "failure in TypeInference AssignmentExpr"); @@ -320,11 +322,10 @@ public: return; } - // FIXME free the old one context->insert_type ( Analysis::NodeMapping (expr.get_lhs ()->get_mappings ().get_crate_num (), ref_node_id, ref, UNKNOWN_LOCAL_DEFID), - infered->clone ()); + result->clone ()); } void visit (HIR::IdentifierExpr &expr) @@ -592,76 +593,25 @@ public: void visit (HIR::IfExpr &expr) { TypeCheckExpr::Resolve (expr.get_if_condition ()); - auto blk_expr = TypeCheckExpr::Resolve (expr.get_if_block ()); - - if (is_final_expr - && context->peek_return_type ()->get_kind () != TyTy::TypeKind::UNIT) - { - auto expected_ty = context->peek_return_type (); - infered = expected_ty->combine (blk_expr); - return; - } + TypeCheckExpr::Resolve (expr.get_if_block ()); infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } void visit (HIR::IfExprConseqElse &expr) { - // check and resolve all types in the conditional var TypeCheckExpr::Resolve (expr.get_if_condition ()); - auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ()); auto else_blk_resolved = TypeCheckExpr::Resolve (expr.get_else_block ()); - TyTy::TyBase *if_block_tyty = nullptr; - if (expr.get_if_block ()->has_expr ()) - if_block_tyty - = TypeCheckExpr::Resolve (expr.get_if_block ()->expr.get ()); - else - if_block_tyty = if_blk_resolved; - - TyTy::TyBase *else_block_tyty = nullptr; - if (expr.get_else_block ()->has_expr ()) - else_block_tyty - = TypeCheckExpr::Resolve (expr.get_else_block ()->expr.get ()); - else - else_block_tyty = else_blk_resolved; - - if (context->peek_return_type ()->get_kind () != TyTy::TypeKind::UNIT) - { - // this must combine to what the type is expected - // this might be a parameter or the last expr in an if + else in a - // BlockExpr then it must resolve to fn return type else its a unit-type - auto expected_ty - = is_final_expr - ? context->peek_return_type () - : new TyTy::UnitType (expr.get_mappings ().get_hirid ()); - - auto if_blk_combined = expected_ty->combine (if_block_tyty); - auto else_blk_combined = expected_ty->combine (else_block_tyty); - - infered = if_blk_combined->combine (else_blk_combined); - return; - } - - infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + infered = if_blk_resolved->combine (else_blk_resolved); } void visit (HIR::IfExprConseqIf &expr) { TypeCheckExpr::Resolve (expr.get_if_condition ()); - auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block ()); - auto elif_blk = TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); - - if (is_final_expr - && context->peek_return_type ()->get_kind () != TyTy::TypeKind::UNIT) - { - auto expected_ty = context->peek_return_type (); - - infered = expected_ty->combine (if_blk); - infered = infered->combine (elif_blk); - return; - } + TypeCheckExpr::Resolve (expr.get_if_block ()); + TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } @@ -817,9 +767,8 @@ public: } private: - TypeCheckExpr (bool is_final_expr) - : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr), - is_final_expr (is_final_expr) + TypeCheckExpr () + : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr) {} bool @@ -870,8 +819,6 @@ private: TyTy::TyBase *infered; TyTy::TyBase *infered_array_elems; - - bool is_final_expr; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index c8d161a..a0a4fda 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -170,23 +170,12 @@ public: auto expected_ret_tyty = resolve_fn_type->return_type (); context->push_return_type (expected_ret_tyty); - TypeCheckExpr::Resolve (function.function_body.get ()); - if (function.function_body->has_expr ()) - { - auto resolved - = TypeCheckExpr::Resolve (function.function_body->expr.get ()); + auto result = TypeCheckExpr::Resolve (function.function_body.get ()); + auto ret_resolved = expected_ret_tyty->combine (result); + if (ret_resolved == nullptr) + return; - auto ret_resolved = expected_ret_tyty->combine (resolved); - if (ret_resolved == nullptr) - { - rust_error_at (function.function_body->expr->get_locus_slow (), - "failed to resolve final expression"); - return; - } - - context->peek_return_type ()->append_reference ( - ret_resolved->get_ref ()); - } + context->peek_return_type ()->append_reference (ret_resolved->get_ref ()); context->pop_return_type (); } @@ -213,23 +202,12 @@ public: auto expected_ret_tyty = resolve_fn_type->return_type (); context->push_return_type (expected_ret_tyty); - TypeCheckExpr::Resolve (method.get_function_body ().get ()); - if (method.get_function_body ()->has_expr ()) - { - auto resolved - = TypeCheckExpr::Resolve (method.get_function_body ()->expr.get ()); + auto result = TypeCheckExpr::Resolve (method.get_function_body ().get ()); + auto ret_resolved = expected_ret_tyty->combine (result); + if (ret_resolved == nullptr) + return; - auto ret_resolved = expected_ret_tyty->combine (resolved); - if (ret_resolved == nullptr) - { - rust_error_at (method.get_function_body ()->expr->get_locus_slow (), - "failed to resolve final expression"); - return; - } - - context->peek_return_type ()->append_reference ( - ret_resolved->get_ref ()); - } + context->peek_return_type ()->append_reference (ret_resolved->get_ref ()); context->pop_return_type (); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 06be1ac..fbe2056 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -75,23 +75,12 @@ public: auto expected_ret_tyty = resolve_fn_type->return_type (); context->push_return_type (expected_ret_tyty); - TypeCheckExpr::Resolve (function.function_body.get ()); - if (function.function_body->has_expr ()) - { - auto resolved - = TypeCheckExpr::Resolve (function.function_body->expr.get ()); - - auto ret_resolved = expected_ret_tyty->combine (resolved); - if (ret_resolved == nullptr) - { - rust_error_at (function.function_body->expr->get_locus_slow (), - "failed to resolve final expression"); - return; - } - - context->peek_return_type ()->append_reference ( - ret_resolved->get_ref ()); - } + auto result = TypeCheckExpr::Resolve (function.function_body.get ()); + auto ret_resolved = expected_ret_tyty->combine (result); + if (ret_resolved == nullptr) + return; + + context->peek_return_type ()->append_reference (ret_resolved->get_ref ()); context->pop_return_type (); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index e04284e..83fdf11 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -30,21 +30,21 @@ namespace Resolver { class TypeCheckStmt : public TypeCheckBase { public: - static TyTy::TyBase *Resolve (HIR::Stmt *stmt, bool is_final_stmt) + static TyTy::TyBase *Resolve (HIR::Stmt *stmt) { - TypeCheckStmt resolver (is_final_stmt); + TypeCheckStmt resolver; stmt->accept_vis (resolver); return resolver.infered; } void visit (HIR::ExprStmtWithBlock &stmt) { - infered = TypeCheckExpr::Resolve (stmt.get_expr (), is_final_stmt); + infered = TypeCheckExpr::Resolve (stmt.get_expr ()); } void visit (HIR::ExprStmtWithoutBlock &stmt) { - infered = TypeCheckExpr::Resolve (stmt.get_expr (), is_final_stmt); + infered = TypeCheckExpr::Resolve (stmt.get_expr ()); } void visit (HIR::LetStmt &stmt) @@ -54,8 +54,7 @@ public: TyTy::TyBase *init_expr_ty = nullptr; if (stmt.has_init_expr ()) { - init_expr_ty - = TypeCheckExpr::Resolve (stmt.get_init_expr (), is_final_stmt); + init_expr_ty = TypeCheckExpr::Resolve (stmt.get_init_expr ()); if (init_expr_ty == nullptr) return; @@ -106,13 +105,10 @@ public: } private: - TypeCheckStmt (bool is_final_stmt) - : TypeCheckBase (), infered (nullptr), is_final_stmt (is_final_stmt) - {} + TypeCheckStmt () : TypeCheckBase (), infered (nullptr) {} TyTy::TyBase *infered; - bool is_final_stmt; -}; // namespace Resolver +}; } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 681d023..3044a6f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -109,10 +109,11 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { bool is_final_stmt = expr.is_final_stmt (s); - bool is_final_expr = is_final_stmt && !expr.has_expr (); + bool is_final_expr + = is_final_stmt && (!expr.has_expr () || !expr.tail_expr_reachable ()); - auto infered = TypeCheckStmt::Resolve (s, is_final_expr); - if (infered == nullptr) + auto resolved = TypeCheckStmt::Resolve (s); + if (resolved == nullptr) { rust_error_at (s->get_locus_slow (), "failure to resolve type"); return false; @@ -121,7 +122,12 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) if (is_final_expr) { delete block_tyty; - block_tyty = infered; + block_tyty = resolved; + } + else if (resolved->get_kind () != TyTy::TypeKind::UNIT) + { + rust_error_at (s->get_locus_slow (), "expected () got %s", + infered->as_string ().c_str ()); } return true; @@ -131,7 +137,7 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) { delete block_tyty; - block_tyty = TypeCheckExpr::Resolve (expr.get_final_expr ().get (), true); + block_tyty = TypeCheckExpr::Resolve (expr.get_final_expr ().get ()); } infered = block_tyty->clone (); -- 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 ++++++++++++++++++++++----- gcc/rust/typecheck/rust-hir-type-check-expr.h | 6 +-- 2 files changed, 54 insertions(+), 15 deletions(-) (limited to 'gcc/rust') 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) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index e7fa3b3..43e51c8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -610,10 +610,10 @@ public: void visit (HIR::IfExprConseqIf &expr) { TypeCheckExpr::Resolve (expr.get_if_condition ()); - TypeCheckExpr::Resolve (expr.get_if_block ()); - TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); + auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block ()); + auto else_blk = TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); - infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + infered = if_blk->combine (else_blk); } void visit (HIR::BlockExpr &expr); -- cgit v1.1 From 60cccd8e58f2a024676599cc00971a6e406e6d42 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 8 Feb 2021 13:26:07 +0000 Subject: Fixes parsing if expressions as part of an expression. This allows for rust style ternery expressions. Fixes #214 --- gcc/rust/parse/rust-parse-impl.h | 50 +++++++++++++++++++++++++++++++++------- gcc/rust/parse/rust-parse.h | 6 +++-- 2 files changed, 46 insertions(+), 10 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index ea468ca..906f6b1 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -7504,12 +7504,23 @@ Parser::parse_loop_label () template std::unique_ptr Parser::parse_if_expr ( - std::vector outer_attrs ATTRIBUTE_UNUSED) + std::vector outer_attrs ATTRIBUTE_UNUSED, bool pratt_parse) { // TODO: make having outer attributes an error? - - Location locus = lexer.peek_token ()->get_locus (); - skip_token (IF); + Location locus = Linemap::unknown_location (); + if (!pratt_parse) + { + locus = lexer.peek_token ()->get_locus (); + if (!skip_token (IF)) + { + skip_after_end_block (); + return nullptr; + } + } + else + { + locus = lexer.peek_token ()->get_locus () - 1; + } // detect accidental if let if (lexer.peek_token ()->get_id () == LET) @@ -7640,12 +7651,23 @@ Parser::parse_if_expr ( template std::unique_ptr Parser::parse_if_let_expr ( - std::vector outer_attrs ATTRIBUTE_UNUSED) + std::vector outer_attrs ATTRIBUTE_UNUSED, bool pratt_parse) { // TODO: make having outer attributes an error? - - Location locus = lexer.peek_token ()->get_locus (); - skip_token (IF); + Location locus = Linemap::unknown_location (); + if (!pratt_parse) + { + locus = lexer.peek_token ()->get_locus (); + if (!skip_token (IF)) + { + skip_after_end_block (); + return nullptr; + } + } + else + { + locus = lexer.peek_token ()->get_locus () - 1; + } // detect accidental if expr parsed as if let expr if (lexer.peek_token ()->get_id () != LET) @@ -12399,6 +12421,18 @@ Parser::null_denotation ( case LEFT_CURLY: // ok - this is an expression with block for once. return parse_block_expr (std::move (outer_attrs), true); + case IF: + // if or if let, so more lookahead to find out + if (lexer.peek_token (1)->get_id () == LET) + { + // if let expr + return parse_if_let_expr (std::move (outer_attrs), true); + } + else + { + // if expr + return parse_if_expr (std::move (outer_attrs), true); + } case MATCH_TOK: // also an expression with block return parse_match_expr (std::move (outer_attrs), true); diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 2778ec7..aeda82b 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -480,10 +480,12 @@ private: bool pratt_parse = false); std::unique_ptr parse_if_expr (std::vector outer_attrs - = std::vector ()); + = std::vector (), + bool pratt_parse = false); std::unique_ptr parse_if_let_expr (std::vector outer_attrs - = std::vector ()); + = std::vector (), + bool pratt_parse = false); std::unique_ptr parse_loop_expr (std::vector outer_attrs = std::vector (), -- 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 ++++++-------- gcc/rust/typecheck/rust-hir-type-check-expr.h | 87 ++++++++++----------------- 2 files changed, 51 insertions(+), 82 deletions(-) (limited to 'gcc/rust') 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 diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 43e51c8..cb92332 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -155,58 +155,11 @@ public: void visit (HIR::CallExpr &expr) { - auto fn = expr.get_fnexpr (); - auto fn_node_id = fn->get_mappings ().get_nodeid (); - - // then lookup the reference_node_id - NodeId ref_node_id = UNKNOWN_NODEID; - if (resolver->lookup_resolved_name (fn_node_id, &ref_node_id)) - { - Definition def; - if (!resolver->lookup_definition (ref_node_id, &def)) - { - rust_error_at (expr.get_locus (), - "unknown reference for resolved name"); - return; - } - ref_node_id = def.parent; - } - else if (!resolver->lookup_resolved_type (fn_node_id, &ref_node_id)) - { - rust_error_at (expr.get_locus (), - "Failed to lookup type reference for node: %s", - expr.as_string ().c_str ()); - return; - } - - if (ref_node_id == UNKNOWN_NODEID) - { - rust_error_at (expr.get_locus (), "unresolved node: %s", - expr.as_string ().c_str ()); - return; - } - - // node back to HIR - HirId ref; - if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), - ref_node_id, &ref)) - { - rust_error_at (expr.get_locus (), "reverse lookup failure for node %u", - ref_node_id); - return; - } - - // check if this has a type - TyTy::TyBase *lookup; - if (!context->lookup_type (ref, &lookup)) - { - rust_error_at (mappings->lookup_location (ref), - "failed to lookup type for CallExpr: %s", - expr.as_string ().c_str ()); - return; - } + TyTy::TyBase *function_tyty = TypeCheckExpr::Resolve (expr.get_fnexpr ()); + if (function_tyty == nullptr) + return; - infered = TyTy::TypeCheckCallExpr::go (lookup, expr, context); + infered = TyTy::TypeCheckCallExpr::go (function_tyty, expr, context); if (infered == nullptr) { rust_error_at (expr.get_locus (), "failed to lookup type to CallExpr"); @@ -703,6 +656,10 @@ public: void visit (HIR::GroupedExpr &expr) { + printf ("inside grouped expr: \n%s\n inside it is: \n%s\n", + expr.as_string ().c_str (), + expr.get_expr_in_parens ()->as_string ().c_str ()); + infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get ()); } @@ -738,16 +695,33 @@ public: NodeId ast_node_id = expr.get_mappings ().get_nodeid (); // then lookup the reference_node_id - NodeId ref_node_id; - if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + NodeId ref_node_id = UNKNOWN_NODEID; + if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) { - if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id)) + // these ref_node_ids will resolve to a pattern declaration but we are + // interested in the definition that this refers to get the parent id + Definition def; + if (!resolver->lookup_definition (ref_node_id, &def)) { rust_error_at (expr.get_locus (), - "Failed to lookup reference for node: %s", - expr.as_string ().c_str ()); + "unknown reference for resolved name"); return; } + ref_node_id = def.parent; + } + else if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id)) + { + rust_error_at (expr.get_locus (), + "Failed to lookup type reference for node: %s", + expr.as_string ().c_str ()); + return; + } + + if (ref_node_id == UNKNOWN_NODEID) + { + rust_error_at (expr.get_locus (), "unresolved node: %s", + expr.as_string ().c_str ()); + return; } // node back to HIR @@ -763,6 +737,7 @@ public: { rust_error_at (expr.get_locus (), "failed to resolve PathInExpression type"); + return; } } -- cgit v1.1 From c8b9c41bf248b952b0260c7b2f1e4c24cdaffae1 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 9 Feb 2021 11:48:12 +0000 Subject: Fix parsing |= as a compound assignment expression. Fixes #173 --- gcc/rust/parse/rust-parse-impl.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'gcc/rust') diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 906f6b1..be71231 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -386,6 +386,8 @@ Parser::left_binding_power (const_TokenPtr token) return LBP_MOD_ASSIG; case AMP_EQ: return LBP_AMP_ASSIG; + case PIPE_EQ: + return LBP_PIPE_ASSIG; case CARET_EQ: return LBP_CARET_ASSIG; case LEFT_SHIFT_EQ: -- cgit v1.1 From 9355fb29fc756807a775f9e8f71124071676c8e4 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 9 Feb 2021 14:06:02 +0000 Subject: Enable -frust-dump-all option for debugging We output each debug IR to file which makes it easier to debug larger test cases. Beaware not all dumps are complete such as name resolution is not implemented yet, HIR is badly formatted and type resolution dump is not finished. --- gcc/rust/parse/rust-parse-impl.h | 28 ++--- gcc/rust/parse/rust-parse.h | 58 ++++++---- gcc/rust/rust-session-manager.cc | 206 +++++++++++++++++++++++---------- gcc/rust/rust-session-manager.h | 40 +++++-- gcc/rust/typecheck/rust-tycheck-dump.h | 4 +- 5 files changed, 230 insertions(+), 106 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index be71231..277cd8b 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -14459,7 +14459,7 @@ Parser::done_end () // Dumps lexer output to stderr. template void -Parser::debug_dump_lex_output () +Parser::debug_dump_lex_output (std::ostream &out) { /* TODO: a better implementation of "lexer dump" (as in dump what was actually * tokenised) would actually be to "write" a token to a file every time @@ -14470,6 +14470,9 @@ Parser::debug_dump_lex_output () while (true) { + if (tok->get_id () == Rust::END_OF_FILE) + break; + bool has_text = tok->get_id () == Rust::IDENTIFIER || tok->get_id () == Rust::INT_LITERAL || tok->get_id () == Rust::FLOAT_LITERAL @@ -14480,16 +14483,13 @@ Parser::debug_dump_lex_output () Location loc = tok->get_locus (); - fprintf (stderr, "token_id_to_str (), - has_text ? (std::string (", text=") + tok->get_str () - + std::string (", typehint=") - + std::string (tok->get_type_hint_str ())) - .c_str () - : "", - lexer.get_line_map ()->to_string (loc).c_str ()); - - if (tok->get_id () == Rust::END_OF_FILE) - break; + out << "token_id_to_str (); + out << has_text ? (std::string (", text=") + tok->get_str () + + std::string (", typehint=") + + std::string (tok->get_type_hint_str ())) + : ""; + out << lexer.get_line_map ()->to_string (loc); lexer.skip_token (); tok = lexer.peek_token (); @@ -14499,9 +14499,9 @@ Parser::debug_dump_lex_output () // Parses crate and dumps AST to stderr, recursively. template void -Parser::debug_dump_ast_output (AST::Crate &crate) +Parser::debug_dump_ast_output (AST::Crate &crate, + std::ostream &out) { - // print crate "as string", which then calls each item as string, etc. - fprintf (stderr, "%s", crate.as_string ().c_str ()); + out << crate.as_string (); } } // namespace Rust diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index aeda82b..b811c77 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -166,22 +166,30 @@ private: parse_generic_params_in_angles (); std::vector > parse_generic_params (); template - std::vector > parse_generic_params (EndTokenPred is_end_token); + std::vector > + parse_generic_params (EndTokenPred is_end_token); std::vector > parse_lifetime_params (); template - std::vector > parse_lifetime_params (EndTokenPred is_end_token); + std::vector > + parse_lifetime_params (EndTokenPred is_end_token); std::vector parse_lifetime_params_objs (); template - std::vector parse_lifetime_params_objs (EndTokenPred is_end_token); + std::vector + parse_lifetime_params_objs (EndTokenPred is_end_token); template - auto parse_non_ptr_sequence (ParseFunction parsing_function, EndTokenPred is_end_token, std::string error_msg = "failed to parse generic param in generic params") -> std::vector; + auto parse_non_ptr_sequence ( + ParseFunction parsing_function, EndTokenPred is_end_token, + std::string error_msg = "failed to parse generic param in generic params") + -> std::vector; AST::LifetimeParam parse_lifetime_param (); std::vector > parse_type_params (); template - std::vector > parse_type_params (EndTokenPred is_end_token); + std::vector > + parse_type_params (EndTokenPred is_end_token); std::unique_ptr parse_type_param (); template - std::vector parse_function_params (EndTokenPred is_end_token); + std::vector + parse_function_params (EndTokenPred is_end_token); AST::FunctionParam parse_function_param (); std::unique_ptr parse_function_return_type (); AST::WhereClause parse_where_clause (); @@ -192,7 +200,8 @@ private: parse_type_bound_where_clause_item (); std::vector parse_for_lifetimes (); template - std::vector > parse_type_param_bounds (EndTokenPred is_end_token); + std::vector > + parse_type_param_bounds (EndTokenPred is_end_token); std::vector > parse_type_param_bounds (); std::unique_ptr parse_type_param_bound (); std::unique_ptr parse_trait_bound (); @@ -215,7 +224,8 @@ private: parse_enum (AST::Visibility vis, std::vector outer_attrs); std::vector > parse_enum_items (); template - std::vector > parse_enum_items (EndTokenPred is_end_token); + std::vector > + parse_enum_items (EndTokenPred is_end_token); std::unique_ptr parse_enum_item (); std::unique_ptr parse_union (AST::Visibility vis, std::vector outer_attrs); @@ -247,8 +257,9 @@ private: parse_extern_block (AST::Visibility vis, std::vector outer_attrs); std::unique_ptr parse_external_item (); - AST::NamedFunctionParam parse_named_function_param ( - std::vector outer_attrs = std::vector ()); + AST::NamedFunctionParam + parse_named_function_param (std::vector outer_attrs + = std::vector ()); AST::Method parse_method (); // Expression-related (Pratt parsed) @@ -272,9 +283,11 @@ private: = std::vector (), ParseRestrictions restrictions = ParseRestrictions ()); std::unique_ptr - parse_arithmetic_or_logical_expr (const_TokenPtr tok, std::unique_ptr left, - std::vector outer_attrs, AST::ArithmeticOrLogicalExpr::ExprType expr_type, - ParseRestrictions restrictions = ParseRestrictions ()); + parse_arithmetic_or_logical_expr ( + const_TokenPtr tok, std::unique_ptr left, + std::vector outer_attrs, + AST::ArithmeticOrLogicalExpr::ExprType expr_type, + ParseRestrictions restrictions = ParseRestrictions ()); std::unique_ptr parse_binary_plus_expr (const_TokenPtr tok, std::unique_ptr left, std::vector outer_attrs, @@ -368,10 +381,11 @@ private: parse_assig_expr (const_TokenPtr tok, std::unique_ptr left, std::vector outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr - parse_compound_assignment_expr (const_TokenPtr tok, std::unique_ptr left, - std::vector outer_attrs, AST::CompoundAssignmentExpr::ExprType expr_type, - ParseRestrictions restrictions = ParseRestrictions ()); + std::unique_ptr parse_compound_assignment_expr ( + const_TokenPtr tok, std::unique_ptr left, + std::vector outer_attrs, + AST::CompoundAssignmentExpr::ExprType expr_type, + ParseRestrictions restrictions = ParseRestrictions ()); std::unique_ptr parse_plus_assig_expr (const_TokenPtr tok, std::unique_ptr left, std::vector outer_attrs, @@ -563,7 +577,8 @@ private: std::unique_ptr parse_paren_prefixed_type (); std::unique_ptr parse_paren_prefixed_type_no_bounds (); std::unique_ptr parse_for_prefixed_type (); - AST::MaybeNamedParam parse_maybe_named_param (std::vector outer_attrs); + AST::MaybeNamedParam + parse_maybe_named_param (std::vector outer_attrs); // Statement-related std::unique_ptr parse_stmt (); @@ -593,7 +608,8 @@ private: std::unique_ptr parse_tuple_struct_items (); AST::StructPatternElements parse_struct_pattern_elems (); std::unique_ptr parse_struct_pattern_field (); - std::unique_ptr parse_struct_pattern_field_partial (std::vector outer_attrs); + std::unique_ptr + parse_struct_pattern_field_partial (std::vector outer_attrs); int left_binding_power (const_TokenPtr token); @@ -609,8 +625,8 @@ public: AST::Crate parse_crate (); // Dumps all lexer output. - void debug_dump_lex_output (); - void debug_dump_ast_output (AST::Crate &crate); + void debug_dump_lex_output (std::ostream &out); + void debug_dump_ast_output (AST::Crate &crate, std::ostream &out); private: // The token source (usually lexer) associated with the parser. diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index a2e5edd..6960556 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -21,6 +21,8 @@ #include "rust-diagnostics.h" #include "diagnostic.h" #include "input.h" +#include +#include #include "target.h" #include "tm.h" @@ -46,6 +48,13 @@ rust_get_backend (); namespace Rust { +const char *kLexDumpFile = "gccrs.lex.dump"; +const char *kASTDumpFile = "gccrs.ast.dump"; +const char *kASTExpandedDumpFile = "gccrs.ast-expanded.dump"; +const char *kHIRDumpFile = "gccrs.hir.dump"; +const char *kHIRTypeResolutionDumpFile = "gccrs.type-resolution.dump"; +const char *kTargetOptionsDumpFile = "gccrs.target-options.dump"; + // Implicitly enable a target_feature (and recursively enable dependencies). void Session::implicitly_enable_feature (std::string feature_name) @@ -309,9 +318,7 @@ Session::init () * itself. */ void Session::init_options () -{ - options.dump_option = CompileOptions::NO_DUMP; -} +{} // Handle option selection. bool @@ -357,39 +364,40 @@ Session::handle_option ( bool Session::enable_dump (std::string arg) { - /* FIXME: change dumping algorithm when new non-inhibiting dump system is - * created */ - if (arg == "all") + if (arg.empty ()) { - rust_error_at ( - Location (), - "dumping all is not supported as of now. choose %, %, " - "or %"); + rust_error_at (Location (), "dump option was not given a name. choose " + "%, %, or %"); return false; } + + if (arg == "all") + { + options.enable_all_dump_options (); + } else if (arg == "lex") { - options.dump_option = CompileOptions::LEXER_DUMP; + options.enable_dump_option (CompileOptions::LEXER_DUMP); } else if (arg == "parse") { - options.dump_option = CompileOptions::PARSER_AST_DUMP; + options.enable_dump_option (CompileOptions::PARSER_AST_DUMP); } else if (arg == "register_plugins") { - options.dump_option = CompileOptions::REGISTER_PLUGINS_DUMP; + options.enable_dump_option (CompileOptions::REGISTER_PLUGINS_DUMP); } else if (arg == "injection") { - options.dump_option = CompileOptions::INJECTION_DUMP; + options.enable_dump_option (CompileOptions::INJECTION_DUMP); } else if (arg == "expansion") { - options.dump_option = CompileOptions::EXPANSION_DUMP; + options.enable_dump_option (CompileOptions::EXPANSION_DUMP); } else if (arg == "resolution") { - options.dump_option = CompileOptions::RESOLUTION_DUMP; + options.enable_dump_option (CompileOptions::RESOLUTION_DUMP); } else if (arg == "target_options") { @@ -398,17 +406,11 @@ Session::enable_dump (std::string arg) // actual compile option // options.target_data.dump_target_options(); // return false; - options.dump_option = CompileOptions::TARGET_OPTION_DUMP; + options.enable_dump_option (CompileOptions::TARGET_OPTION_DUMP); } else if (arg == "hir") { - options.dump_option = CompileOptions::HIR_DUMP; - } - else if (arg == "") - { - rust_error_at (Location (), "dump option was not given a name. choose " - "%, %, or %"); - return false; + options.enable_dump_option (CompileOptions::HIR_DUMP); } else { @@ -460,24 +462,22 @@ Session::parse_file (const char *filename) auto mappings = Analysis::Mappings::get (); mappings->insert_ast_crate (&parsed_crate); - // give a chance to give some debug - switch (options.dump_option) + if (options.dump_option_enabled (CompileOptions::LEXER_DUMP)) + { + dump_lex (parser); + } + if (options.dump_option_enabled (CompileOptions::PARSER_AST_DUMP)) + { + dump_ast (parser, parsed_crate); + } + if (options.dump_option_enabled (CompileOptions::TARGET_OPTION_DUMP)) { - case CompileOptions::LEXER_DUMP: - parser.debug_dump_lex_output (); - // TODO: rewrite lexer dump or something so that it allows for the crate - // to already be parsed - break; - case CompileOptions::PARSER_AST_DUMP: - parser.debug_dump_ast_output (parsed_crate); - break; - case CompileOptions::TARGET_OPTION_DUMP: options.target_data.dump_target_options (); - return; - default: - break; } + if (saw_errors ()) + return; + /* basic pipeline: * - lex * - parse @@ -497,8 +497,7 @@ Session::parse_file (const char *filename) // register plugins pipeline stage register_plugins (parsed_crate); fprintf (stderr, "\033[0;31mSUCCESSFULLY REGISTERED PLUGINS \n\033[0m"); - - if (options.dump_option == CompileOptions::REGISTER_PLUGINS_DUMP) + if (options.dump_option_enabled (CompileOptions::REGISTER_PLUGINS_DUMP)) { // TODO: what do I dump here? } @@ -506,8 +505,7 @@ Session::parse_file (const char *filename) // injection pipeline stage injection (parsed_crate); fprintf (stderr, "\033[0;31mSUCCESSFULLY FINISHED INJECTION \n\033[0m"); - - if (options.dump_option == CompileOptions::INJECTION_DUMP) + if (options.dump_option_enabled (CompileOptions::INJECTION_DUMP)) { // TODO: what do I dump here? injected crate names? } @@ -515,18 +513,17 @@ Session::parse_file (const char *filename) // expansion pipeline stage expansion (parsed_crate); fprintf (stderr, "\033[0;31mSUCCESSFULLY FINISHED EXPANSION \n\033[0m"); - - if (options.dump_option == CompileOptions::EXPANSION_DUMP) + if (options.dump_option_enabled (CompileOptions::EXPANSION_DUMP)) { // dump AST with expanded stuff fprintf (stderr, "BEGIN POST-EXPANSION AST DUMP\n"); - parser.debug_dump_ast_output (parsed_crate); + dump_ast_expanded (parser, parsed_crate); fprintf (stderr, "END POST-EXPANSION AST DUMP\n"); } // resolution pipeline stage Resolver::NameResolution::Resolve (parsed_crate); - if (options.dump_option == CompileOptions::RESOLUTION_DUMP) + if (options.dump_option_enabled (CompileOptions::RESOLUTION_DUMP)) { // TODO: what do I dump here? resolved names? AST with resolved names? } @@ -536,10 +533,9 @@ Session::parse_file (const char *filename) // lower AST to HIR HIR::Crate hir = HIR::ASTLowering::Resolve (parsed_crate); - if (options.dump_option == CompileOptions::HIR_DUMP) + if (options.dump_option_enabled (CompileOptions::HIR_DUMP)) { - fprintf (stderr, "%s", hir.as_string ().c_str ()); - return; + dump_hir (hir); } if (saw_errors ()) @@ -547,11 +543,9 @@ Session::parse_file (const char *filename) // type resolve Resolver::TypeResolution::Resolve (hir); - if (options.dump_option == CompileOptions::TYPE_RESOLUTION_DUMP) + if (options.dump_option_enabled (CompileOptions::TYPE_RESOLUTION_DUMP)) { - auto buf = Resolver::TypeResolverDump::go (hir); - fprintf (stderr, "%s\n", buf.c_str ()); - return; + dump_type_resolution (hir); } // scan unused has to be done after type resolution since methods are resolved @@ -794,22 +788,114 @@ Session::expansion (AST::Crate &crate) } void +Session::dump_lex (Parser &parser) const +{ + std::ofstream out; + out.open (kLexDumpFile); + if (out.fail ()) + { + rust_error_at (Linemap::unknown_location (), "cannot open %s:%m; ignored", + kLexDumpFile); + return; + } + + // TODO: rewrite lexer dump or something so that it allows for the crate + // to already be parsed + parser.debug_dump_lex_output (out); + out.close (); +} + +void +Session::dump_ast (Parser &parser, AST::Crate &crate) const +{ + std::ofstream out; + out.open (kASTDumpFile); + if (out.fail ()) + { + rust_error_at (Linemap::unknown_location (), "cannot open %s:%m; ignored", + kASTDumpFile); + return; + } + + parser.debug_dump_ast_output (crate, out); + out.close (); +} + +void +Session::dump_ast_expanded (Parser &parser, AST::Crate &crate) const +{ + std::ofstream out; + out.open (kASTExpandedDumpFile); + if (out.fail ()) + { + rust_error_at (Linemap::unknown_location (), "cannot open %s:%m; ignored", + kASTExpandedDumpFile); + return; + } + + parser.debug_dump_ast_output (crate, out); + out.close (); +} + +void +Session::dump_hir (HIR::Crate &hir) const +{ + std::ofstream out; + out.open (kHIRDumpFile); + if (out.fail ()) + { + rust_error_at (Linemap::unknown_location (), "cannot open %s:%m; ignored", + kHIRDumpFile); + return; + } + + out << hir.as_string (); + out.close (); +} + +void +Session::dump_type_resolution (HIR::Crate &hir) const +{ + std::ofstream out; + out.open (kHIRTypeResolutionDumpFile); + if (out.fail ()) + { + rust_error_at (Linemap::unknown_location (), "cannot open %s:%m; ignored", + kHIRTypeResolutionDumpFile); + return; + } + + Resolver::TypeResolverDump::go (hir, out); + out.close (); +} + +void TargetOptions::dump_target_options () const { - fprintf (stderr, - "\033[0;31m--PREPARING TO DUMP ALL TARGET OPTIONS--\n\033[0m"); + std::ofstream out; + out.open (kTargetOptionsDumpFile); + if (out.fail ()) + { + rust_error_at (Linemap::unknown_location (), "cannot open %s:%m; ignored", + kTargetOptionsDumpFile); + return; + } + + if (features.empty ()) + { + out << "No target options available!\n"; + } + for (const auto &pairs : features) { for (const auto &value : pairs.second) - fprintf (stderr, "%s: \"%s\"\n", pairs.first.c_str (), value.c_str ()); + out << pairs.first + ": \"" + value + "\"\n"; if (pairs.second.empty ()) - fprintf (stderr, "%s\n", pairs.first.c_str ()); + out << pairs.first + "\n"; } - if (features.empty ()) - fprintf (stderr, "No target options available!\n"); - fprintf (stderr, "\033[0;31m--END OF TARGET OPTION DUMP--\n\033[0m"); + out.close (); } void diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index 07d5461..b7e081b 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -116,8 +116,8 @@ public: // Dump all target options to stderr. void dump_target_options () const; - /* Creates derived values and implicit enables after all target info is added - * (e.g. "unix"). */ + /* Creates derived values and implicit enables after all target info is + * added (e.g. "unix"). */ void init_derived_values (); /* Enables all requirements for the feature given, and will enable feature @@ -162,13 +162,8 @@ public: // Defines compiler options (e.g. dump, etc.). struct CompileOptions { - // TODO: use bitfield for smaller memory requirements? - - /* FIXME: this is set up for "instead of" dumping - in future, dumps should - * not inhibit compilation */ - enum DumpOptions + enum DumpOption { - NO_DUMP, LEXER_DUMP, PARSER_AST_DUMP, REGISTER_PLUGINS_DUMP, @@ -178,8 +173,9 @@ struct CompileOptions TARGET_OPTION_DUMP, HIR_DUMP, TYPE_RESOLUTION_DUMP, + }; - } dump_option; + std::set dump_options; /* configuration options - actually useful for conditional compilation and * whatever data related to target arch, features, os, family, env, endian, @@ -188,6 +184,26 @@ struct CompileOptions bool enable_test = false; bool debug_assertions = false; bool proc_macro = false; + + bool dump_option_enabled (DumpOption option) const + { + return dump_options.find (option) != dump_options.end (); + } + + void enable_dump_option (DumpOption option) { dump_options.insert (option); } + + void enable_all_dump_options () + { + enable_dump_option (DumpOption::LEXER_DUMP); + enable_dump_option (DumpOption::PARSER_AST_DUMP); + enable_dump_option (DumpOption::REGISTER_PLUGINS_DUMP); + enable_dump_option (DumpOption::INJECTION_DUMP); + enable_dump_option (DumpOption::EXPANSION_DUMP); + enable_dump_option (DumpOption::RESOLUTION_DUMP); + enable_dump_option (DumpOption::TARGET_OPTION_DUMP); + enable_dump_option (DumpOption::HIR_DUMP); + enable_dump_option (DumpOption::TYPE_RESOLUTION_DUMP); + } }; /* Defines a compiler session. This is for a single compiler invocation, so @@ -219,6 +235,12 @@ private: void parse_file (const char *filename); bool enable_dump (std::string arg); + void dump_lex (Parser &parser) const; + void dump_ast (Parser &parser, AST::Crate &crate) const; + void dump_ast_expanded (Parser &parser, AST::Crate &crate) const; + void dump_hir (HIR::Crate &crate) const; + void dump_type_resolution (HIR::Crate &crate) const; + void debug_dump_load_crates (Parser &parser); void implicitly_enable_feature (std::string feature_name); diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h index 9d882fb..17774a7 100644 --- a/gcc/rust/typecheck/rust-tycheck-dump.h +++ b/gcc/rust/typecheck/rust-tycheck-dump.h @@ -28,13 +28,13 @@ namespace Resolver { class TypeResolverDump : public TypeCheckBase { public: - static std::string go (HIR::Crate &crate) + static void go (HIR::Crate &crate, std::ofstream &out) { TypeResolverDump dumper; for (auto &item : crate.items) item->accept_vis (dumper); - return dumper.dump; + out << dumper.dump; } void visit (HIR::InherentImpl &impl_block) override -- cgit v1.1 From cb9998216d76ccc62b45fcf01b3a0928a026f7ed Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 9 Feb 2021 15:28:03 +0000 Subject: Fix parse of LoopExpr as part of a normal expression For example this fixes the form of: let x = loop { ... }; Fixes #219 --- gcc/rust/parse/rust-parse-impl.h | 29 ++++++++++++++++++++++++----- gcc/rust/parse/rust-parse.h | 7 +++---- 2 files changed, 27 insertions(+), 9 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 277cd8b..d391304 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -7827,14 +7827,30 @@ Parser::parse_if_let_expr ( template std::unique_ptr Parser::parse_loop_expr ( - std::vector outer_attrs, AST::LoopLabel label) + std::vector outer_attrs, AST::LoopLabel label, + bool pratt_parse) { Location locus = Linemap::unknown_location (); - if (label.is_error ()) - locus = lexer.peek_token ()->get_locus (); + if (!pratt_parse) + { + if (label.is_error ()) + locus = lexer.peek_token ()->get_locus (); + else + locus = label.get_locus (); + + if (!skip_token (LOOP)) + { + skip_after_end_block (); + return nullptr; + } + } else - locus = label.get_locus (); - skip_token (LOOP); + { + if (label.is_error ()) + locus = lexer.peek_token ()->get_locus () - 1; + else + locus = label.get_locus (); + } // parse loop body, which is required std::unique_ptr loop_body = parse_block_expr (); @@ -12435,6 +12451,9 @@ Parser::null_denotation ( // if expr return parse_if_expr (std::move (outer_attrs), true); } + case LOOP: + return parse_loop_expr (std::move (outer_attrs), AST::LoopLabel::error (), + true); case MATCH_TOK: // also an expression with block return parse_match_expr (std::move (outer_attrs), true); diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index b811c77..873b55e9 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -500,10 +500,9 @@ private: parse_if_let_expr (std::vector outer_attrs = std::vector (), bool pratt_parse = false); - std::unique_ptr - parse_loop_expr (std::vector outer_attrs - = std::vector (), - AST::LoopLabel label = AST::LoopLabel::error ()); + std::unique_ptr parse_loop_expr ( + std::vector outer_attrs = std::vector (), + AST::LoopLabel label = AST::LoopLabel::error (), bool pratt_parse = false); std::unique_ptr parse_while_loop_expr (std::vector outer_attrs = std::vector (), -- 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 +++++++++++++++++++ gcc/rust/hir/rust-ast-lower-block.h | 19 +++++++++++++++++++ gcc/rust/hir/rust-ast-lower-expr.h | 5 +++++ gcc/rust/hir/tree/rust-hir-expr.h | 2 ++ gcc/rust/resolve/rust-ast-resolve-expr.h | 5 +++++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 5 +++++ 6 files changed, 55 insertions(+) (limited to 'gcc/rust') 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) {} diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h index f81a242..d3c61df 100644 --- a/gcc/rust/hir/rust-ast-lower-block.h +++ b/gcc/rust/hir/rust-ast-lower-block.h @@ -134,6 +134,25 @@ public: translated = ASTLoweringBlock::translate (&expr, &terminated); } + void visit (AST::LoopExpr &expr) + { + std::vector outer_attribs; + HIR::BlockExpr *loop_block + = ASTLoweringBlock::translate (expr.get_loop_block ().get (), + &terminated); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::LoopExpr (mapping, + std::unique_ptr (loop_block), + expr.get_locus (), HIR::LoopLabel::error (), + std::move (outer_attribs)); + } + private: ASTLoweringExprWithBlock () : ASTLoweringBase (), translated (nullptr), terminated (false) diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index cd1863f..49ac7f1 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -697,6 +697,11 @@ public: std::move (outer_attribs), expr.get_locus ()); } + void visit (AST::LoopExpr &expr) + { + translated = ASTLoweringExprWithBlock::translate (&expr, &terminated); + } + private: ASTLoweringExpr () : translated (nullptr), translated_array_elems (nullptr), terminated (false) diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index d4af3c2..14b223a 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -3334,6 +3334,8 @@ public: Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } + + std::unique_ptr &get_loop_block () { return loop_block; }; }; // 'Loop' expression (i.e. the infinite loop) HIR node diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index d563f93..e8ee8b3 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -241,6 +241,11 @@ public: ResolveExpr::go (expr.get_receiver_expr ().get (), expr.get_node_id ()); } + void visit (AST::LoopExpr &expr) + { + ResolveExpr::go (expr.get_loop_block ().get (), expr.get_node_id ()); + } + private: ResolveExpr (NodeId parent) : ResolverBase (parent) {} }; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index cb92332..17e79d4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -741,6 +741,11 @@ public: } } + void visit (HIR::LoopExpr &expr) + { + infered = TypeCheckExpr::Resolve (expr.get_loop_block ().get ()); + } + private: TypeCheckExpr () : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr) -- cgit v1.1 From a3a343c8853cb0967b21e8da23a829665208b25d Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 10 Feb 2021 11:03:29 +0000 Subject: Give ParseRestriction option to allow for null parse_expr. The null_denotion function expects to find the beginning of an expression but breaks can be empty and the parser will fail with unexpected ';'. Fixes #225 --- gcc/rust/parse/rust-parse-impl.h | 12 ++++++++---- gcc/rust/parse/rust-parse.h | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index d391304..18e6983 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -7437,7 +7437,10 @@ Parser::parse_break_expr ( } // parse break return expression if it exists - std::unique_ptr return_expr = parse_expr (); + ParseRestrictions restrictions; + restrictions.expr_can_be_null = true; + std::unique_ptr return_expr + = parse_expr (std::vector (), restrictions); return std::unique_ptr ( new AST::BreakExpr (locus, std::move (label), std::move (return_expr), @@ -12461,9 +12464,10 @@ Parser::null_denotation ( // array definition expr (not indexing) return parse_array_expr (std::move (outer_attrs), true); default: - rust_error_at (tok->get_locus (), - "found unexpected token %qs in null denotation", - tok->get_token_description ()); + if (!restrictions.expr_can_be_null) + rust_error_at (tok->get_locus (), + "found unexpected token %qs in null denotation", + tok->get_token_description ()); return nullptr; } } diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 873b55e9..e691c9e 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -82,6 +82,7 @@ struct ParseRestrictions /* Whether the expression was entered from a unary expression - prevents stuff * like struct exprs being parsed from a dereference. */ bool entered_from_unary = false; + bool expr_can_be_null = false; }; // Parser implementation for gccrs. -- cgit v1.1 From 016c40bedc7e3f53e2c413895f77c0d9f723eb3c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 9 Feb 2021 18:26:13 +0000 Subject: Introduce new label namesapce for name resolution Labels are in their own namesapce so they do not affect types and normal values within a program. Addresses #107 --- gcc/rust/resolve/rust-ast-resolve-item.h | 3 +++ gcc/rust/resolve/rust-ast-resolve-unused.h | 1 + gcc/rust/resolve/rust-ast-resolve.cc | 37 +++++++++++++++++++++++++++++- gcc/rust/resolve/rust-name-resolver.h | 15 ++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) (limited to 'gcc/rust') diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index 8b6227e..f5dc579 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -88,8 +88,10 @@ public: NodeId scope_node_id = function.get_node_id (); resolver->get_name_scope ().push (scope_node_id); resolver->get_type_scope ().push (scope_node_id); + resolver->get_label_scope ().push (scope_node_id); resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); // we make a new scope so the names of parameters are resolved and shadowed // correctly @@ -111,6 +113,7 @@ public: resolver->get_name_scope ().pop (); resolver->get_type_scope ().pop (); + resolver->get_label_scope ().pop (); } void visit (AST::InherentImpl &impl_block) diff --git a/gcc/rust/resolve/rust-ast-resolve-unused.h b/gcc/rust/resolve/rust-ast-resolve-unused.h index 928cf11..748f972 100644 --- a/gcc/rust/resolve/rust-ast-resolve-unused.h +++ b/gcc/rust/resolve/rust-ast-resolve-unused.h @@ -43,6 +43,7 @@ public: auto resolver = Resolver::get (); resolver->iterate_name_ribs ([&] (Rib *r) -> void { ScanRib (r); }); resolver->iterate_type_ribs ([&] (Rib *r) -> void { ScanRib (r); }); + resolver->iterate_label_ribs ([&] (Rib *r) -> void { ScanRib (r); }); } }; diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 593a732..0ed2bfb 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -49,7 +49,8 @@ namespace Resolver { Resolver::Resolver () : mappings (Analysis::Mappings::get ()), tyctx (TypeCheckContext::get ()), name_scope (Scope (mappings->get_current_crate ())), - type_scope (Scope (mappings->get_current_crate ())) + type_scope (Scope (mappings->get_current_crate ())), + label_scope (Scope (mappings->get_current_crate ())) { generate_builtins (); } @@ -81,6 +82,13 @@ Resolver::push_new_type_rib (Rib *r) type_ribs[r->get_node_id ()] = r; } +void +Resolver::push_new_label_rib (Rib *r) +{ + rust_assert (label_ribs.find (r->get_node_id ()) == label_ribs.end ()); + label_ribs[r->get_node_id ()] = r; +} + bool Resolver::find_name_rib (NodeId id, Rib **rib) { @@ -238,6 +246,27 @@ Resolver::lookup_resolved_type (NodeId refId, NodeId *defId) return true; } +void +Resolver::insert_resolved_label (NodeId refId, NodeId defId) +{ + auto it = resolved_labels.find (refId); + rust_assert (it == resolved_labels.end ()); + + resolved_types[refId] = defId; + get_label_scope ().append_reference_for_def (refId, defId); +} + +bool +Resolver::lookup_resolved_label (NodeId refId, NodeId *defId) +{ + auto it = resolved_labels.find (refId); + if (it == resolved_labels.end ()) + return false; + + *defId = it->second; + return true; +} + // NameResolution NameResolution * @@ -275,6 +304,9 @@ NameResolution::go (AST::Crate &crate) // setup parent scoping for new types resolver->get_type_scope ().push (mappings->get_next_node_id ()); resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + // setup label scope + resolver->get_label_scope ().push (mappings->get_next_node_id ()); + resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); // first gather the top-level namespace names then we drill down for (auto it = crate.items.begin (); it != crate.items.end (); it++) @@ -293,8 +325,10 @@ ResolveExpr::visit (AST::BlockExpr &expr) NodeId scope_node_id = expr.get_node_id (); resolver->get_name_scope ().push (scope_node_id); resolver->get_type_scope ().push (scope_node_id); + resolver->get_label_scope ().push (scope_node_id); resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); expr.iterate_stmts ([&] (AST::Stmt *s) mutable -> bool { ResolveStmt::go (s, s->get_node_id ()); @@ -306,6 +340,7 @@ ResolveExpr::visit (AST::BlockExpr &expr) resolver->get_name_scope ().pop (); resolver->get_type_scope ().pop (); + resolver->get_label_scope ().pop (); } // rust-ast-resolve-struct-expr-field.h diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h index ea0e4f5..9c01d47 100644 --- a/gcc/rust/resolve/rust-name-resolver.h +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -250,9 +250,11 @@ public: void push_new_name_rib (Rib *r); void push_new_type_rib (Rib *r); + void push_new_label_rib (Rib *r); bool find_name_rib (NodeId id, Rib **rib); bool find_type_rib (NodeId id, Rib **rib); + bool find_label_rib (NodeId id, Rib **rib); void insert_new_definition (NodeId id, Definition def); bool lookup_definition (NodeId id, Definition *def); @@ -263,9 +265,13 @@ public: void insert_resolved_type (NodeId refId, NodeId defId); bool lookup_resolved_type (NodeId refId, NodeId *defId); + void insert_resolved_label (NodeId refId, NodeId defId); + bool lookup_resolved_label (NodeId refId, NodeId *defId); + // proxy for scoping Scope &get_name_scope () { return name_scope; } Scope &get_type_scope () { return type_scope; } + Scope &get_label_scope () { return label_scope; } NodeId get_global_type_node_id () { return global_type_node_id; } @@ -320,6 +326,12 @@ public: } } + void iterate_label_ribs (std::function cb) + { + for (auto it = label_ribs.begin (); it != label_ribs.end (); it++) + cb (it->second); + } + private: Resolver (); @@ -332,6 +344,7 @@ private: Scope name_scope; Scope type_scope; + Scope label_scope; NodeId global_type_node_id; NodeId unit_ty_node_id; @@ -339,6 +352,7 @@ private: // map a AST Node to a Rib std::map name_ribs; std::map type_ribs; + std::map label_ribs; // map any Node to its Definition // ie any name or type usage @@ -354,6 +368,7 @@ private: // we need two namespaces one for names and ones for types std::map resolved_names; std::map resolved_types; + std::map resolved_labels; // map of resolved names mutability flag std::map decl_mutability; -- 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/ast/rust-ast.h | 13 ++++++- gcc/rust/ast/rust-expr.h | 13 ++++++- gcc/rust/backend/rust-compile-expr.h | 30 +++++++++------- gcc/rust/backend/rust-compile.cc | 37 ++++++++++--------- gcc/rust/hir/rust-ast-lower-base.h | 37 +++++++++++++++++++ gcc/rust/hir/rust-ast-lower-block.h | 4 ++- gcc/rust/hir/rust-ast-lower-expr.h | 25 +++++++++++-- gcc/rust/hir/tree/rust-hir-expr.h | 30 +++++++++------- gcc/rust/hir/tree/rust-hir-item.h | 3 +- gcc/rust/hir/tree/rust-hir-type.h | 2 +- gcc/rust/hir/tree/rust-hir.h | 26 +++++++------- gcc/rust/resolve/rust-ast-resolve-expr.h | 51 +++++++++++++++++++++++++++ gcc/rust/resolve/rust-ast-resolve.cc | 2 +- gcc/rust/rust-backend.h | 6 ++++ gcc/rust/rust-gcc.cc | 23 ++++++++++++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 10 +++++- 16 files changed, 248 insertions(+), 64 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 392c36a..b61c8c3 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1139,11 +1139,14 @@ private: Location locus; + NodeId node_id; + public: // Constructor Lifetime (LifetimeType type, std::string name = std::string (), Location locus = Location ()) - : lifetime_type (type), lifetime_name (std::move (name)), locus (locus) + : lifetime_type (type), lifetime_name (std::move (name)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // Creates an "error" lifetime. @@ -1159,6 +1162,14 @@ public: void accept_vis (ASTVisitor &vis) override; + LifetimeType get_lifetime_type () { return lifetime_type; } + + Location get_locus () { return locus; } + + std::string get_lifetime_name () const { return lifetime_name; } + + NodeId get_node_id () const { return node_id; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 50006d1..52e3abc 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -3103,6 +3103,8 @@ public: return break_expr; } + Lifetime &get_label () { return label; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3670,11 +3672,14 @@ class LoopLabel /*: public Node*/ Lifetime label; // or type LIFETIME_OR_LABEL Location locus; + NodeId node_id; + public: std::string as_string () const; LoopLabel (Lifetime loop_label, Location locus = Location ()) - : label (std::move (loop_label)), locus (locus) + : label (std::move (loop_label)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // Returns whether the LoopLabel is in an error state. @@ -3684,6 +3689,10 @@ public: static LoopLabel error () { return LoopLabel (Lifetime::error ()); } Location get_locus () const { return locus; } + + Lifetime &get_lifetime () { return label; } + + NodeId get_node_id () const { return node_id; } }; // Base loop expression AST node - aka LoopExpr @@ -3743,6 +3752,8 @@ protected: public: bool has_loop_label () const { return !loop_label.is_error (); } + LoopLabel &get_loop_label () { return loop_label; } + Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } 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); + } } } diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index 093129e..95d93d0 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -243,6 +243,43 @@ protected: ASTLoweringBase () : mappings (Analysis::Mappings::get ()) {} Analysis::Mappings *mappings; + + HIR::Lifetime lower_lifetime (AST::Lifetime &lifetime) + { + HIR::Lifetime::LifetimeType type = HIR::Lifetime::LifetimeType::NAMED; + switch (lifetime.get_lifetime_type ()) + { + case AST::Lifetime::LifetimeType::NAMED: + type = HIR::Lifetime::LifetimeType::NAMED; + break; + case AST::Lifetime::LifetimeType::STATIC: + type = HIR::Lifetime::LifetimeType::STATIC; + break; + case AST::Lifetime::LifetimeType::WILDCARD: + type = HIR::Lifetime::LifetimeType::WILDCARD; + break; + } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, lifetime.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + return HIR::Lifetime (mapping, type, lifetime.get_lifetime_name (), + lifetime.get_locus ()); + } + + HIR::LoopLabel lower_loop_label (AST::LoopLabel &loop_label) + { + HIR::Lifetime life = lower_lifetime (loop_label.get_lifetime ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, loop_label.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + return HIR::LoopLabel (mapping, std::move (life), loop_label.get_locus ()); + } }; } // namespace HIR diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h index d3c61df..c945042 100644 --- a/gcc/rust/hir/rust-ast-lower-block.h +++ b/gcc/rust/hir/rust-ast-lower-block.h @@ -141,6 +141,8 @@ public: = ASTLoweringBlock::translate (expr.get_loop_block ().get (), &terminated); + HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ()); + auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), @@ -149,7 +151,7 @@ public: translated = new HIR::LoopExpr (mapping, std::unique_ptr (loop_block), - expr.get_locus (), HIR::LoopLabel::error (), + expr.get_locus (), std::move (loop_label), std::move (outer_attribs)); } diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 49ac7f1..e10448f 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -74,8 +74,6 @@ public: return compiler.translated; } - ~ASTLowerPathInExpression () {} - void visit (AST::PathInExpression &expr) { std::vector path_segments; @@ -702,9 +700,30 @@ public: translated = ASTLoweringExprWithBlock::translate (&expr, &terminated); } + void visit (AST::BreakExpr &expr) + { + std::vector outer_attribs; + HIR::Lifetime break_label = lower_lifetime (expr.get_label ()); + HIR::Expr *break_expr + = expr.has_break_expr () + ? ASTLoweringExpr::translate (expr.get_break_expr ().get ()) + : nullptr; + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::BreakExpr (mapping, expr.get_locus (), + std ::move (break_label), + std::unique_ptr (break_expr), + std::move (outer_attribs)); + } + private: ASTLoweringExpr () - : translated (nullptr), translated_array_elems (nullptr), terminated (false) + : ASTLoweringBase (), translated (nullptr), + translated_array_elems (nullptr), terminated (false) {} HIR::Expr *translated; diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 14b223a..fe884bb 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2712,8 +2712,7 @@ public: bool has_label () const { return !label.is_error (); } // Constructor for a ContinueExpr with a label. - ContinueExpr (Analysis::NodeMapping mappings, Location locus, - Lifetime label = Lifetime::error (), + ContinueExpr (Analysis::NodeMapping mappings, Location locus, Lifetime label, std::vector outer_attribs = std::vector ()) : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), @@ -2765,7 +2764,7 @@ public: // Constructor for a break expression BreakExpr (Analysis::NodeMapping mappings, Location locus, - Lifetime break_label = Lifetime::error (), + Lifetime break_label, std::unique_ptr expr_in_break = nullptr, std::vector outer_attribs = std::vector ()) : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), @@ -2803,6 +2802,10 @@ public: void accept_vis (HIRVisitor &vis) override; + Lifetime &get_label () { return label; } + + std::unique_ptr &get_expr () { return break_expr; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3266,20 +3269,21 @@ class LoopLabel /*: public Node*/ Location locus; + Analysis::NodeMapping mappings; + public: std::string as_string () const; - LoopLabel (Lifetime loop_label, Location locus = Location ()) - : label (std::move (loop_label)), locus (locus) + LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label, Location locus) + : label (std::move (loop_label)), locus (locus), mappings (mapping) {} // Returns whether the LoopLabel is in an error state. bool is_error () const { return label.is_error (); } - // Creates an error state LoopLabel. - static LoopLabel error () { return LoopLabel (Lifetime::error ()); } - Location get_locus () const { return locus; } + + Analysis::NodeMapping &get_mappings () { return mappings; } }; // Base loop expression HIR node - aka LoopExpr @@ -3299,7 +3303,7 @@ protected: // Constructor for BaseLoopExpr BaseLoopExpr (Analysis::NodeMapping mappings, std::unique_ptr loop_block, Location locus, - LoopLabel loop_label = LoopLabel::error (), + LoopLabel loop_label, std::vector outer_attribs = std::vector ()) : ExprWithBlock (std::move (mappings), std::move (outer_attribs)), @@ -3347,7 +3351,7 @@ public: // Constructor for LoopExpr LoopExpr (Analysis::NodeMapping mappings, std::unique_ptr loop_block, Location locus, - LoopLabel loop_label = LoopLabel::error (), + LoopLabel loop_label, std::vector outer_attribs = std::vector ()) : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, std::move (loop_label), std::move (outer_attribs)) @@ -3380,7 +3384,7 @@ public: WhileLoopExpr (Analysis::NodeMapping mappings, std::unique_ptr loop_condition, std::unique_ptr loop_block, Location locus, - LoopLabel loop_label = LoopLabel::error (), + LoopLabel loop_label, std::vector outer_attribs = std::vector ()) : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, @@ -3442,7 +3446,7 @@ public: std::vector > match_arm_patterns, std::unique_ptr condition, std::unique_ptr loop_block, Location locus, - LoopLabel loop_label = LoopLabel::error (), + LoopLabel loop_label, std::vector outer_attribs = std::vector ()) : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, @@ -3515,7 +3519,7 @@ public: std::unique_ptr loop_pattern, std::unique_ptr iterator_expr, std::unique_ptr loop_body, Location locus, - LoopLabel loop_label = LoopLabel::error (), + LoopLabel loop_label, std::vector outer_attribs = std::vector ()) : BaseLoopExpr (std::move (mappings), std::move (loop_body), locus, std::move (loop_label), std::move (outer_attribs)), diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 4ab23e1..c0d6d0f 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -324,7 +324,8 @@ public: // Type-based self parameter (not ref, no lifetime) SelfParam (Analysis::NodeMapping mappings, std::unique_ptr type, bool is_mut, Location locus) - : has_ref (false), is_mut (is_mut), lifetime (Lifetime::error ()), + : has_ref (false), is_mut (is_mut), + lifetime (Lifetime (mappings, Lifetime::LifetimeType::NAMED, "", locus)), type (std::move (type)), locus (locus), mappings (mappings) {} diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h index ebed119..746e3e2 100644 --- a/gcc/rust/hir/tree/rust-hir-type.h +++ b/gcc/rust/hir/tree/rust-hir-type.h @@ -531,7 +531,7 @@ public: // Constructor ReferenceType (Analysis::NodeMapping mappings, bool is_mut, std::unique_ptr type_no_bounds, Location locus, - Lifetime lifetime = Lifetime::error ()) + Lifetime lifetime) : TypeNoBounds (mappings), lifetime (std::move (lifetime)), has_mut (is_mut), type (std::move (type_no_bounds)), locus (locus) {} diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index 6fd6297..1567215 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -1060,16 +1060,16 @@ private: Location locus; + Analysis::NodeMapping mappings; + public: // Constructor - Lifetime (LifetimeType type, std::string name = std::string (), - Location locus = Location ()) - : lifetime_type (type), lifetime_name (std::move (name)), locus (locus) + Lifetime (Analysis::NodeMapping mapping, LifetimeType type, std::string name, + Location locus) + : lifetime_type (type), lifetime_name (std::move (name)), locus (locus), + mappings (mapping) {} - // Creates an "error" lifetime. - static Lifetime error () { return Lifetime (NAMED, std::string ("")); } - // Returns true if the lifetime is in an error state. bool is_error () const { @@ -1080,6 +1080,14 @@ public: void accept_vis (HIRVisitor &vis) override; + std::string get_name () const { return lifetime_name; } + + LifetimeType get_lifetime_type () const { return lifetime_type; } + + Location get_locus () const { return locus; } + + Analysis::NodeMapping get_mappings () const { return mappings; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1133,12 +1141,6 @@ public: // Returns whether the lifetime param has an outer attribute. bool has_outer_attribute () const { return !outer_attr.is_empty (); } - // Creates an error state lifetime param. - static LifetimeParam create_error () - { - return LifetimeParam (Lifetime::error ()); - } - // Returns whether the lifetime param is in an error state. bool is_error () const { return lifetime.is_error (); } diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index e8ee8b3..9cfa04d 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -243,9 +243,60 @@ public: void visit (AST::LoopExpr &expr) { + if (expr.has_loop_label ()) + { + auto label = expr.get_loop_label (); + if (label.get_lifetime ().get_lifetime_type () + != AST::Lifetime::LifetimeType::NAMED) + { + rust_error_at (label.get_locus (), + "Labels must be a named lifetime value"); + return; + } + + auto label_name = label.get_lifetime ().get_lifetime_name (); + auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); + resolver->get_label_scope ().insert ( + label_name, label_lifetime_node_id, label.get_locus (), false, + [&] (std::string, NodeId, Location locus) -> void { + rust_error_at (label.get_locus (), + "label redefined multiple times"); + rust_error_at (locus, "was defined here"); + }); + resolver->insert_new_definition (label_lifetime_node_id, + Definition{label_lifetime_node_id, + label.get_node_id ()}); + } ResolveExpr::go (expr.get_loop_block ().get (), expr.get_node_id ()); } + void visit (AST::BreakExpr &expr) + { + if (expr.has_label ()) + { + auto label = expr.get_label (); + if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED) + { + rust_error_at (label.get_locus (), + "Labels must be a named lifetime value"); + return; + } + + NodeId resolved_node = UNKNOWN_NODEID; + if (!resolver->get_label_scope ().lookup (label.get_lifetime_name (), + &resolved_node)) + { + rust_error_at (expr.get_label ().get_locus (), + "failed to resolve label"); + return; + } + resolver->insert_resolved_label (label.get_node_id (), resolved_node); + } + + if (expr.has_break_expr ()) + ResolveExpr::go (expr.get_break_expr ().get (), expr.get_node_id ()); + } + private: ResolveExpr (NodeId parent) : ResolverBase (parent) {} }; diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 0ed2bfb..213d141 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -252,7 +252,7 @@ Resolver::insert_resolved_label (NodeId refId, NodeId defId) auto it = resolved_labels.find (refId); rust_assert (it == resolved_labels.end ()); - resolved_types[refId] = defId; + resolved_labels[refId] = defId; get_label_scope ().append_reference_for_def (refId, defId); } diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 7b0ccf9..50e8728 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -425,6 +425,12 @@ public: Location) = 0; + // infinite loop expressions + virtual Bexpression *loop_expression (Bblock *body, Location); + + // exit expressions + virtual Bexpression *exit_expression (Bexpression *condition, Location); + // Create a switch statement where the case values are constants. // CASES and STATEMENTS must have the same number of entries. If // VALUE matches any of the list in CASES[i], which will all be diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 0729b1e..82ebb98 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -326,6 +326,10 @@ public: Bstatement *except_stmt, Bstatement *finally_stmt, Location); + Bexpression *loop_expression (Bblock *body, Location); + + Bexpression *exit_expression (Bexpression *condition, Location); + // Blocks. Bblock *block (Bfunction *, Bblock *, const std::vector &, @@ -2201,6 +2205,25 @@ Gcc_backend::if_statement (Bfunction *, Bexpression *condition, return this->make_statement (ret); } +// Loops + +Bexpression * +Gcc_backend::loop_expression (Bblock *body, Location locus) +{ + tree loop_expr_tree = fold_build1_loc (locus.gcc_location (), LOOP_EXPR, + void_type_node, body->get_tree ()); + return this->make_expression (loop_expr_tree); +} + +Bexpression * +Gcc_backend::exit_expression (Bexpression *condition, Location locus) +{ + tree cond_tree = condition->get_tree (); + tree exit_expr_tree = fold_build1_loc (locus.gcc_location (), EXIT_EXPR, + void_type_node, cond_tree); + return this->make_expression (exit_expr_tree); +} + // Switch. Bstatement * diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 17e79d4..9fe6e4f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -39,7 +39,8 @@ public: if (resolver.infered == nullptr) { - rust_error_at (expr->get_locus_slow (), "failed to resolve expression"); + rust_error_at (expr->get_locus_slow (), + "failed to type resolve expression"); return new TyTy::ErrorType (expr->get_mappings ().get_hirid ()); } @@ -746,6 +747,13 @@ public: infered = TypeCheckExpr::Resolve (expr.get_loop_block ().get ()); } + void visit (HIR::BreakExpr &expr) + { + infered = expr.has_break_expr () + ? TypeCheckExpr::Resolve (expr.get_expr ().get ()) + : new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + } + private: TypeCheckExpr () : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr) -- 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 +++++++++----- gcc/rust/parse/rust-parse-impl.h | 6 ++++-- gcc/rust/typecheck/rust-hir-type-check-expr.h | 6 ++++++ 3 files changed, 19 insertions(+), 7 deletions(-) (limited to 'gcc/rust') 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); diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 18e6983..fcb3d18 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -7400,8 +7400,10 @@ Parser::parse_return_expr ( } // parse expression to return, if it exists - std::unique_ptr returned_expr = parse_expr (); - // FIXME: ensure this doesn't ruin the middle of any expressions or anything + ParseRestrictions restrictions; + restrictions.expr_can_be_null = true; + std::unique_ptr returned_expr + = parse_expr (std::vector (), restrictions); return std::unique_ptr ( new AST::ReturnExpr (locus, std::move (returned_expr), diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 9fe6e4f..c8493f0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -137,6 +137,12 @@ public: void visit (HIR::ReturnExpr &expr) { + if (!expr.has_return_expr ()) + { + infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + return; + } + auto fn_return_tyty = context->peek_return_type (); rust_assert (fn_return_tyty != nullptr); -- 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 +++++++++++++++++++++++++++++---- gcc/rust/hir/rust-ast-lower-base.h | 4 ++ gcc/rust/hir/tree/rust-hir-expr.h | 4 ++ gcc/rust/util/rust-hir-map.cc | 6 +++ gcc/rust/util/rust-hir-map.h | 1 + 6 files changed, 90 insertions(+), 7 deletions(-) (limited to 'gcc/rust') 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: 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 &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 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); -- cgit v1.1 From d02ab5925b612678beb975d99951b1d2052958a1 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 10 Feb 2021 17:01:48 +0000 Subject: Add check for break outside of a loop. This will be needed to stop the compiler proceding to continue and break expressions without a loop context. --- gcc/rust/typecheck/rust-hir-type-check-expr.h | 84 ++++++++++++++--------- gcc/rust/typecheck/rust-hir-type-check-implitem.h | 8 ++- gcc/rust/typecheck/rust-hir-type-check-item.h | 2 +- gcc/rust/typecheck/rust-hir-type-check-stmt.h | 16 +++-- gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 5 +- gcc/rust/typecheck/rust-hir-type-check.cc | 14 ++-- gcc/rust/typecheck/rust-tyty.cc | 6 +- 7 files changed, 80 insertions(+), 55 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index c8493f0..6a45fef 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -32,9 +32,9 @@ namespace Resolver { class TypeCheckExpr : public TypeCheckBase { public: - static TyTy::TyBase *Resolve (HIR::Expr *expr) + static TyTy::TyBase *Resolve (HIR::Expr *expr, bool inside_loop) { - TypeCheckExpr resolver; + TypeCheckExpr resolver (inside_loop); expr->accept_vis (resolver); if (resolver.infered == nullptr) @@ -53,7 +53,8 @@ public: void visit (HIR::TupleIndexExpr &expr) { - auto resolved = TypeCheckExpr::Resolve (expr.get_tuple_expr ().get ()); + auto resolved + = TypeCheckExpr::Resolve (expr.get_tuple_expr ().get (), inside_loop); if (resolved == nullptr) { rust_error_at (expr.get_tuple_expr ()->get_locus_slow (), @@ -129,7 +130,7 @@ public: std::vector fields; for (auto &elem : expr.get_tuple_elems ()) { - auto field_ty = TypeCheckExpr::Resolve (elem.get ()); + auto field_ty = TypeCheckExpr::Resolve (elem.get (), false); fields.push_back (field_ty->get_ref ()); } infered = new TyTy::TupleType (expr.get_mappings ().get_hirid (), fields); @@ -146,7 +147,7 @@ public: auto fn_return_tyty = context->peek_return_type (); rust_assert (fn_return_tyty != nullptr); - auto expr_ty = TypeCheckExpr::Resolve (expr.get_expr ()); + auto expr_ty = TypeCheckExpr::Resolve (expr.get_expr (), false); if (expr_ty == nullptr) { rust_error_at (expr.get_locus (), @@ -162,7 +163,8 @@ public: void visit (HIR::CallExpr &expr) { - TyTy::TyBase *function_tyty = TypeCheckExpr::Resolve (expr.get_fnexpr ()); + TyTy::TyBase *function_tyty + = TypeCheckExpr::Resolve (expr.get_fnexpr (), false); if (function_tyty == nullptr) return; @@ -178,7 +180,8 @@ public: void visit (HIR::MethodCallExpr &expr) { - auto receiver_tyty = TypeCheckExpr::Resolve (expr.get_receiver ().get ()); + auto receiver_tyty + = TypeCheckExpr::Resolve (expr.get_receiver ().get (), false); if (receiver_tyty == nullptr) { rust_error_at (expr.get_receiver ()->get_locus_slow (), @@ -239,8 +242,8 @@ public: { infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); - auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs (), false); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs (), false); auto result = lhs->combine (rhs); if (result == nullptr) @@ -446,8 +449,8 @@ public: void visit (HIR::ArithmeticOrLogicalExpr &expr) { - auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs (), false); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs (), false); bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ()); bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ()); @@ -467,8 +470,8 @@ public: void visit (HIR::ComparisonExpr &expr) { - auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs (), false); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs (), false); auto result = lhs->combine (rhs); if (result == nullptr || result->get_kind () == TyTy::TypeKind::ERROR) @@ -482,8 +485,8 @@ public: void visit (HIR::LazyBooleanExpr &expr) { - auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs (), false); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs (), false); // we expect the lhs and rhs must be bools at this point TyTy::BoolType elhs (expr.get_mappings ().get_hirid ()); @@ -503,7 +506,7 @@ public: void visit (HIR::NegationExpr &expr) { - auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr ()); + auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr (), false); // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators switch (expr.get_negation_type ()) @@ -552,26 +555,29 @@ public: void visit (HIR::IfExpr &expr) { - TypeCheckExpr::Resolve (expr.get_if_condition ()); - TypeCheckExpr::Resolve (expr.get_if_block ()); + TypeCheckExpr::Resolve (expr.get_if_condition (), false); + TypeCheckExpr::Resolve (expr.get_if_block (), inside_loop); infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } void visit (HIR::IfExprConseqElse &expr) { - TypeCheckExpr::Resolve (expr.get_if_condition ()); - auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ()); - auto else_blk_resolved = TypeCheckExpr::Resolve (expr.get_else_block ()); + TypeCheckExpr::Resolve (expr.get_if_condition (), false); + auto if_blk_resolved + = TypeCheckExpr::Resolve (expr.get_if_block (), inside_loop); + auto else_blk_resolved + = TypeCheckExpr::Resolve (expr.get_else_block (), inside_loop); infered = if_blk_resolved->combine (else_blk_resolved); } void visit (HIR::IfExprConseqIf &expr) { - TypeCheckExpr::Resolve (expr.get_if_condition ()); - auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block ()); - auto else_blk = TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); + TypeCheckExpr::Resolve (expr.get_if_condition (), false); + auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block (), inside_loop); + auto else_blk + = TypeCheckExpr::Resolve (expr.get_conseq_if_expr (), inside_loop); infered = if_blk->combine (else_blk); } @@ -589,8 +595,8 @@ public: return; } - auto resolved_index_expr - = size_ty->combine (TypeCheckExpr::Resolve (expr.get_index_expr ())); + auto resolved_index_expr = size_ty->combine ( + TypeCheckExpr::Resolve (expr.get_index_expr (), false)); if (resolved_index_expr == nullptr) { rust_error_at (expr.get_index_expr ()->get_locus_slow (), @@ -637,7 +643,7 @@ public: { std::vector types; elems.iterate ([&] (HIR::Expr *e) mutable -> bool { - types.push_back (TypeCheckExpr::Resolve (e)); + types.push_back (TypeCheckExpr::Resolve (e, false)); return true; }); @@ -653,7 +659,8 @@ public: void visit (HIR::ArrayElemsCopied &elems) { - infered_array_elems = TypeCheckExpr::Resolve (elems.get_elem_to_copy ()); + infered_array_elems + = TypeCheckExpr::Resolve (elems.get_elem_to_copy (), false); } void visit (HIR::StructExprStructFields &struct_expr) @@ -667,13 +674,13 @@ public: expr.as_string ().c_str (), expr.get_expr_in_parens ()->as_string ().c_str ()); - infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get ()); + infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get (), false); } void visit (HIR::FieldAccessExpr &expr) { auto struct_base - = TypeCheckExpr::Resolve (expr.get_receiver_expr ().get ()); + = TypeCheckExpr::Resolve (expr.get_receiver_expr ().get (), false); bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT; if (!is_valid_type) @@ -750,19 +757,26 @@ public: void visit (HIR::LoopExpr &expr) { - infered = TypeCheckExpr::Resolve (expr.get_loop_block ().get ()); + infered = TypeCheckExpr::Resolve (expr.get_loop_block ().get (), true); } void visit (HIR::BreakExpr &expr) { + if (!inside_loop) + { + rust_error_at (expr.get_locus (), "cannot `break` outside of a loop"); + return; + } + infered = expr.has_break_expr () - ? TypeCheckExpr::Resolve (expr.get_expr ().get ()) + ? TypeCheckExpr::Resolve (expr.get_expr ().get (), false) : new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } private: - TypeCheckExpr () - : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr) + TypeCheckExpr (bool inside_loop) + : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr), + inside_loop (inside_loop) {} bool @@ -813,6 +827,8 @@ private: TyTy::TyBase *infered; TyTy::TyBase *infered_array_elems; + + bool inside_loop; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index a0a4fda..3e835b7 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -40,7 +40,8 @@ public: void visit (HIR::ConstantItem &constant) { TyTy::TyBase *type = TypeCheckType::Resolve (constant.get_type ()); - TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); + TyTy::TyBase *expr_type + = TypeCheckExpr::Resolve (constant.get_expr (), false); context->insert_type (constant.get_mappings (), type->combine (expr_type)); } @@ -170,7 +171,7 @@ public: auto expected_ret_tyty = resolve_fn_type->return_type (); context->push_return_type (expected_ret_tyty); - auto result = TypeCheckExpr::Resolve (function.function_body.get ()); + auto result = TypeCheckExpr::Resolve (function.function_body.get (), false); auto ret_resolved = expected_ret_tyty->combine (result); if (ret_resolved == nullptr) return; @@ -202,7 +203,8 @@ public: auto expected_ret_tyty = resolve_fn_type->return_type (); context->push_return_type (expected_ret_tyty); - auto result = TypeCheckExpr::Resolve (method.get_function_body ().get ()); + auto result + = TypeCheckExpr::Resolve (method.get_function_body ().get (), false); auto ret_resolved = expected_ret_tyty->combine (result); if (ret_resolved == nullptr) return; diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index fbe2056..f54956c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -75,7 +75,7 @@ public: auto expected_ret_tyty = resolve_fn_type->return_type (); context->push_return_type (expected_ret_tyty); - auto result = TypeCheckExpr::Resolve (function.function_body.get ()); + auto result = TypeCheckExpr::Resolve (function.function_body.get (), false); auto ret_resolved = expected_ret_tyty->combine (result); if (ret_resolved == nullptr) return; diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index 83fdf11..195e483 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -30,21 +30,21 @@ namespace Resolver { class TypeCheckStmt : public TypeCheckBase { public: - static TyTy::TyBase *Resolve (HIR::Stmt *stmt) + static TyTy::TyBase *Resolve (HIR::Stmt *stmt, bool inside_loop) { - TypeCheckStmt resolver; + TypeCheckStmt resolver (inside_loop); stmt->accept_vis (resolver); return resolver.infered; } void visit (HIR::ExprStmtWithBlock &stmt) { - infered = TypeCheckExpr::Resolve (stmt.get_expr ()); + infered = TypeCheckExpr::Resolve (stmt.get_expr (), inside_loop); } void visit (HIR::ExprStmtWithoutBlock &stmt) { - infered = TypeCheckExpr::Resolve (stmt.get_expr ()); + infered = TypeCheckExpr::Resolve (stmt.get_expr (), inside_loop); } void visit (HIR::LetStmt &stmt) @@ -54,7 +54,8 @@ public: TyTy::TyBase *init_expr_ty = nullptr; if (stmt.has_init_expr ()) { - init_expr_ty = TypeCheckExpr::Resolve (stmt.get_init_expr ()); + init_expr_ty + = TypeCheckExpr::Resolve (stmt.get_init_expr (), inside_loop); if (init_expr_ty == nullptr) return; @@ -105,9 +106,12 @@ public: } private: - TypeCheckStmt () : TypeCheckBase (), infered (nullptr) {} + TypeCheckStmt (bool inside_loop) + : TypeCheckBase (), infered (nullptr), inside_loop (inside_loop) + {} TyTy::TyBase *infered; + bool inside_loop; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 61823bf..6d4c876 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -86,7 +86,7 @@ public: void visit (HIR::StaticItem &var) { TyTy::TyBase *type = TypeCheckType::Resolve (var.get_type ()); - TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (var.get_expr ()); + TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (var.get_expr (), false); context->insert_type (var.get_mappings (), type->combine (expr_type)); } @@ -94,7 +94,8 @@ public: void visit (HIR::ConstantItem &constant) { TyTy::TyBase *type = TypeCheckType::Resolve (constant.get_type ()); - TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); + TyTy::TyBase *expr_type + = TypeCheckExpr::Resolve (constant.get_expr (), false); context->insert_type (constant.get_mappings (), type->combine (expr_type)); } diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 3044a6f..00a92b0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -112,7 +112,7 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) bool is_final_expr = is_final_stmt && (!expr.has_expr () || !expr.tail_expr_reachable ()); - auto resolved = TypeCheckStmt::Resolve (s); + auto resolved = TypeCheckStmt::Resolve (s, inside_loop); if (resolved == nullptr) { rust_error_at (s->get_locus_slow (), "failure to resolve type"); @@ -137,7 +137,8 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) { delete block_tyty; - block_tyty = TypeCheckExpr::Resolve (expr.get_final_expr ().get ()); + block_tyty + = TypeCheckExpr::Resolve (expr.get_final_expr ().get (), inside_loop); } infered = block_tyty->clone (); @@ -160,7 +161,8 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) if (struct_expr.has_struct_base ()) { TyTy::TyBase *base_resolved - = TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ()); + = TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get (), + false); resolved = struct_path_resolved->combine (base_resolved); if (resolved == nullptr) { @@ -326,7 +328,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) } size_t field_index; - TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ()); + TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value (), false); TyTy::StructFieldType *field_type = struct_path_resolved->get_field (field.field_name, &field_index); if (field_type == nullptr) @@ -355,7 +357,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) } size_t field_index; - TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ()); + TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value (), false); TyTy::StructFieldType *field_type = struct_path_resolved->get_field (field_name, &field_index); if (field_type == nullptr) @@ -395,7 +397,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) // existing code to figure out the type HIR::IdentifierExpr expr (field.get_mappings (), field.get_field_name (), field.get_locus ()); - TyTy::TyBase *value = TypeCheckExpr::Resolve (&expr); + TyTy::TyBase *value = TypeCheckExpr::Resolve (&expr, false); resolved_field = field_type->get_field_type ()->combine (value); if (resolved_field != nullptr) diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 8b04209..e12d5ff 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -501,7 +501,7 @@ TypeCheckCallExpr::visit (ADTType &type) StructFieldType *field = type.get_field (i); TyBase *field_tyty = field->get_field_type (); - TyBase *arg = Resolver::TypeCheckExpr::Resolve (p); + TyBase *arg = Resolver::TypeCheckExpr::Resolve (p, false); if (arg == nullptr) { rust_error_at (p->get_locus_slow (), "failed to resolve argument type"); @@ -542,7 +542,7 @@ TypeCheckCallExpr::visit (FnType &type) size_t i = 0; call.iterate_params ([&] (HIR::Expr *param) mutable -> bool { auto fnparam = type.param_at (i); - auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (param); + auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (param, false); if (argument_expr_tyty == nullptr) { rust_error_at (param->get_locus_slow (), @@ -593,7 +593,7 @@ TypeCheckMethodCallExpr::visit (FnType &type) size_t i = 1; call.iterate_params ([&] (HIR::Expr *param) mutable -> bool { auto fnparam = type.param_at (i); - auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (param); + auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (param, false); if (argument_expr_tyty == nullptr) { rust_error_at (param->get_locus_slow (), -- 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 +++++++++++++++++++++++++++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 28 +++++++++++++--- gcc/rust/typecheck/rust-hir-type-check.h | 23 ++++++++++++++ 4 files changed, 105 insertions(+), 4 deletions(-) (limited to 'gcc/rust') 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; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 6a45fef..87aeae6 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -757,7 +757,19 @@ public: void visit (HIR::LoopExpr &expr) { - infered = TypeCheckExpr::Resolve (expr.get_loop_block ().get (), true); + context->push_new_loop_context (expr.get_mappings ().get_hirid ()); + TypeCheckExpr::Resolve (expr.get_loop_block ().get (), true); + TyTy::TyBase *loop_context_type = context->pop_loop_context (); + + bool loop_context_type_infered + = (loop_context_type->get_kind () != TyTy::TypeKind::INFER) + || ((loop_context_type->get_kind () == TyTy::TypeKind::INFER) + && (((TyTy::InferType *) loop_context_type)->get_infer_kind () + != TyTy::InferType::GENERAL)); + + infered = loop_context_type_infered + ? loop_context_type + : new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } void visit (HIR::BreakExpr &expr) @@ -768,9 +780,17 @@ public: return; } - infered = expr.has_break_expr () - ? TypeCheckExpr::Resolve (expr.get_expr ().get (), false) - : new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + if (expr.has_break_expr ()) + { + TyTy::TyBase *break_expr_tyty + = TypeCheckExpr::Resolve (expr.get_expr ().get (), false); + + TyTy::TyBase *loop_context = context->peek_loop_context (); + TyTy::TyBase *combined = loop_context->combine (break_expr_tyty); + context->swap_head_loop_context (combined); + } + + infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } private: diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index d033878..531d241 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -56,6 +56,28 @@ public: } } + void push_new_loop_context (HirId id) + { + TyTy::TyBase *infer_var + = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL); + loop_type_stack.push_back (infer_var); + } + + TyTy::TyBase *peek_loop_context () { return loop_type_stack.back (); } + + TyTy::TyBase *pop_loop_context () + { + auto back = peek_loop_context (); + loop_type_stack.pop_back (); + return back; + } + + void swap_head_loop_context (TyTy::TyBase *val) + { + loop_type_stack.pop_back (); + loop_type_stack.push_back (val); + } + private: TypeCheckContext (); @@ -63,6 +85,7 @@ private: std::map resolved; std::vector > builtins; std::vector return_type_stack; + std::vector loop_type_stack; }; class TypeResolution -- cgit v1.1