From patchwork Thu Aug 1 14:57:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arthur Cohen X-Patchwork-Id: 1967864 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=embecosm.com header.i=@embecosm.com header.a=rsa-sha256 header.s=google header.b=EzrTr0bA; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WZY9m2Kn2z1ybV for ; Fri, 2 Aug 2024 01:42:04 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 852D1385C6C3 for ; Thu, 1 Aug 2024 15:42:02 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-ed1-x536.google.com (mail-ed1-x536.google.com [IPv6:2a00:1450:4864:20::536]) by sourceware.org (Postfix) with ESMTPS id 968CE3861022 for ; Thu, 1 Aug 2024 15:00:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 968CE3861022 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 968CE3861022 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::536 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722524490; cv=none; b=eKs77QYhAtuRvHpKTwYF8PTqbAMjH5keqqD4hEjiAOzf/c1Xgpzx3d3yzXSJ/l2RAyVjk1hmcUMYgauDwwYe5MRJHMQ9f5Wbl1a+JOcRLWaNGO1hBVSIFJEu27Yiuc9weVBxyC5KtXONf8u0k6shB61md+AlMXmslzW7L36+1r0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722524490; c=relaxed/simple; bh=6MXfC5FG8MvdzO9QRvdgRcPj/mxycGcX7/JDpCoD27E=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=YKwNlOHMGMfzKH4jgo5SfZCvrUjUwK+dfZ6wFearo3HpwquWBYZj8s9d0HQVrhKPuMLvsLolB5RYGcLRqmFdG++q0hjnSAIYkFNDQFIbxcvGcSeecJkUDwyl6Er9SYP1UeiFk1He56xfdaCrwK0wsEWmR5hhVLBgTHPeNBZp8qo= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-ed1-x536.google.com with SMTP id 4fb4d7f45d1cf-5b7b6a30454so856102a12.2 for ; Thu, 01 Aug 2024 08:00:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; t=1722524437; x=1723129237; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=aC0FYJNfhNlpSreBBc2EbEzBtuaYxIbU+3sMF5rpa3A=; b=EzrTr0bAmTrz/bR9lI+3G68El4ZsihWcNiRcoy0yrLIgzrlyR4i0fDV9nTSlYqytuZ 7YXMmFPt45iy8gSahMgnhP6wOfa6rj3ui82T1q8h+i3fIvTMwc43Q4ynXehO/ddVXKsG MSjlfhr2ob6pdQZqoskdVmGyIUt/3sXIQ6zFL7fOBNCcisfioX1i/h1W3GR9+uA99kdE x423tdq7Z15wBmzO0vCiVpIgSPzGYizOdctZL3TBX7ylklXnh3x7bf+BkcrioBptYfVc scV9zDyXZe7tNY6tCQUM5ZuQOU4UopyyP9/fkeAaljUWRzGFHTQEutBQAByG2QJgtnqX 5FXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722524437; x=1723129237; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=aC0FYJNfhNlpSreBBc2EbEzBtuaYxIbU+3sMF5rpa3A=; b=Yw5E8X6of+GF7Rgg2QPhj3MnKt+p3fa7kirk2x7NntMSCFzoqjxd8MYoH3iTeomkBD +6fJ5cf5ZV2s/bbxLL8WDcVCiIEF2xv0xlVN/DGwFt+DSiGRmgwCTVzTkcNbvfCIaaLp KRMMtibpN++i1di4TZBB6F9vLvIeyAI80J48wJHrj3mpk8za/zKLTc3lf8p7THf4NVFq A6svedweebiwDMkf2gddWelHgj1WuM3YWZHVMt3x80nlCucXrmED99AqpTJh1YSiL+iE BB2scXyDfsx9XfkbtLG+MWnXT9z1221kzb9zNUsU+yo7RYn54IXIXCysF5kH4ICzU3S8 wmBA== X-Gm-Message-State: AOJu0YzrfKS54pwLy0W2BCgtONiLI5aeMxBPlyD9j6seIymzaBFCVX9v p3OKTgIN1xXBJphNteeR0nA0uTFELigqEpTRFH/kuvb4feO82MS8BnwBMCwf/V4963vcuFR14Uc LzRnT X-Google-Smtp-Source: AGHT+IFV0aWF4x3Zxd/xS9ZHPq7zX1mxqZqMviY+PofGbgQh8KAeCp2Ciporjj8izbxBrTW33NSB3Q== X-Received: by 2002:aa7:d454:0:b0:5a3:5d3d:32fc with SMTP id 4fb4d7f45d1cf-5b7f38ebaeamr411824a12.10.1722524436907; Thu, 01 Aug 2024 08:00:36 -0700 (PDT) Received: from platypus.lan ([2a04:cec2:9:dc84:3622:6733:ff49:ee91]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5ac63590592sm10252456a12.25.2024.08.01.08.00.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Aug 2024 08:00:36 -0700 (PDT) From: Arthur Cohen To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org, Jakub Dupak Subject: [PATCH 115/125] gccrs: borrowck: BIR: emit moves Date: Thu, 1 Aug 2024 16:57:51 +0200 Message-ID: <20240801145809.366388-117-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240801145809.366388-2-arthur.cohen@embecosm.com> References: <20240801145809.366388-2-arthur.cohen@embecosm.com> MIME-Version: 1.0 X-Spam-Status: No, score=-14.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org From: Jakub Dupak gcc/rust/ChangeLog: * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Emit moves. * checks/errors/borrowck/rust-bir-builder-internal.h: Emit moves. * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Emit moves. * checks/errors/borrowck/rust-bir-dump.cc (Dump::visit_move_place): Emit moves. (Dump::visit): Emit moves. * checks/errors/borrowck/rust-bir-place.h (struct Place): Emit moves. * checks/errors/borrowck/rust-bir-visitor.h: Emit moves. * checks/errors/borrowck/rust-bir.h (enum class): Emit moves. (class AbstractExpr): Emit moves. (BasicBlock::is_terminated): Emit moves. Signed-off-by: Jakub Dupak --- .../borrowck/rust-bir-builder-expr-stmt.cc | 15 +++-- .../borrowck/rust-bir-builder-internal.h | 35 ++++------ .../borrowck/rust-bir-builder-lazyboolexpr.h | 2 +- .../checks/errors/borrowck/rust-bir-dump.cc | 11 +++- .../checks/errors/borrowck/rust-bir-place.h | 50 ++++++-------- .../checks/errors/borrowck/rust-bir-visitor.h | 4 ++ gcc/rust/checks/errors/borrowck/rust-bir.h | 66 +++++++++++++------ 7 files changed, 103 insertions(+), 80 deletions(-) diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc index 89352d84f6b..922894cc5d5 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc @@ -84,7 +84,7 @@ ExprStmtBuilder::visit (HIR::ClosureExpr &expr) { captures.push_back (ctx.place_db.lookup_variable (capture)); } - make_args (captures); + move_all (captures); // Note: Not a coercion site for captures. return_expr (new InitializerExpr (std::move (captures)), lookup_type (expr)); @@ -96,7 +96,7 @@ ExprStmtBuilder::visit (HIR::StructExprStructFields &fields) auto struct_ty = lookup_type (fields)->as ()->get_variants ().at (0); auto init_values = StructBuilder (ctx, struct_ty).build (fields); - make_args (init_values); + move_all (init_values); return_expr (new InitializerExpr (std::move (init_values)), lookup_type (fields)); } @@ -141,7 +141,7 @@ void ExprStmtBuilder::visit (HIR::NegationExpr &expr) { PlaceId operand = visit_expr (*expr.get_expr ()); - return_expr (new Operator<1> ({make_arg (operand)}), lookup_type (expr)); + return_expr (new Operator<1> ({move_place (operand)}), lookup_type (expr)); } void @@ -149,7 +149,7 @@ ExprStmtBuilder::visit (HIR::ArithmeticOrLogicalExpr &expr) { PlaceId lhs = visit_expr (*expr.get_lhs ()); PlaceId rhs = visit_expr (*expr.get_rhs ()); - return_expr (new Operator<2> ({make_arg (lhs), make_arg (rhs)}), + return_expr (new Operator<2> ({move_place (lhs), move_place (rhs)}), lookup_type (expr)); } @@ -158,7 +158,7 @@ ExprStmtBuilder::visit (HIR::ComparisonExpr &expr) { PlaceId lhs = visit_expr (*expr.get_lhs ()); PlaceId rhs = visit_expr (*expr.get_rhs ()); - return_expr (new Operator<2> ({make_arg (lhs), make_arg (rhs)}), + return_expr (new Operator<2> ({move_place (lhs), move_place (rhs)}), lookup_type (expr)); } @@ -208,7 +208,7 @@ ExprStmtBuilder::visit (HIR::ArrayExpr &expr) case HIR::ArrayElems::VALUES: { auto &elem_vals = (static_cast (*elems)); auto init_values = visit_list (elem_vals.get_values ()); - make_args (init_values); + move_all (init_values); return_expr (new InitializerExpr (std::move (init_values)), lookup_type (expr)); break; @@ -264,6 +264,7 @@ ExprStmtBuilder::visit (HIR::CallExpr &expr) coercion_site (arguments[i], fn_type->get_param_type_at (i)); } + move_all (arguments); return_expr (new CallExpr (fn, std::move (arguments)), lookup_type (expr), true); } @@ -502,7 +503,7 @@ ExprStmtBuilder::visit (HIR::IfExpr &expr) void ExprStmtBuilder::visit (HIR::IfExprConseqElse &expr) { - push_switch (make_arg (visit_expr (*expr.get_if_condition ()))); + push_switch (move_place (visit_expr (*expr.get_if_condition ()))); BasicBlockId if_end_bb = ctx.current_bb; PlaceId result = take_or_create_return_place (lookup_type (expr)); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h index 55f00aa50ac..b421ba43fba 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h @@ -230,10 +230,15 @@ protected: // Helpers to add BIR statements push_assignment (tmp, rhs); } + void push_tmp_assignment (PlaceId rhs) + { + push_tmp_assignment (new Assignment (rhs), ctx.place_db[rhs].tyty); + } + void push_switch (PlaceId switch_val, std::initializer_list destinations = {}) { - auto copy = make_arg (switch_val); + auto copy = move_place (switch_val); ctx.get_current_bb ().statements.emplace_back (Statement::Kind::SWITCH, copy); ctx.get_current_bb ().successors.insert ( @@ -259,33 +264,21 @@ protected: // Helpers to add BIR statements Statement::Kind::STORAGE_DEAD, place); } - PlaceId declare_rvalue (PlaceId place) + PlaceId move_place (PlaceId arg) { - ctx.place_db[place].is_rvalue = true; - return place; - } - - void declare_rvalues (std::vector &places) - { - for (auto &place : places) - declare_rvalue (place); - } - - PlaceId make_arg (PlaceId arg) - { - auto copy = ctx.place_db.into_rvalue (arg); - if (copy != arg) + if (ctx.place_db[arg].is_lvalue ()) { - push_storage_live (copy); - push_assignment (copy, arg); + push_tmp_assignment (arg); + arg = translated; } - return copy; + + return arg; } - void make_args (std::vector &args) + template void move_all (T &args) { std::transform (args.begin (), args.end (), args.begin (), - [this] (PlaceId arg) { return make_arg (arg); }); + [this] (PlaceId arg) { return move_place (arg); }); } protected: // CFG helpers diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h index fb0c75b4f72..1cc55569c7c 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h @@ -62,7 +62,7 @@ protected: void visit (HIR::LazyBooleanExpr &expr) override { auto lhs = visit_expr (*expr.get_lhs ()); - push_switch (make_arg (lhs), {short_circuit_bb}); + push_switch (move_place (lhs), {short_circuit_bb}); start_new_consecutive_bb (); return_place (visit_expr (*expr.get_rhs ())); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc index 4dea27e3038..320b653f830 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc @@ -241,7 +241,7 @@ void Dump::visit_move_place (PlaceId place_id) { const Place &place = func.place_db[place_id]; - if (place.is_rvalue || !place.is_copy) + if (!place.is_constant ()) stream << "move "; visit_place (place_id); } @@ -325,7 +325,14 @@ Dump::visit (Operator<2> &expr) void Dump::visit (Assignment &expr) { - visit_move_place (expr.get_rhs ()); + if (func.place_db[expr.get_rhs ()].is_rvalue ()) + { + visit_move_place (expr.get_rhs ()); + } + else + { + visit_place (expr.get_rhs ()); + } } std::ostream & diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h index 61e90d58d26..546890d797c 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h @@ -91,18 +91,26 @@ struct Place } path; /** Copy trait */ bool is_copy; - /** This place can be moved from safety. */ - bool is_rvalue; + bool has_drop = false; Lifetime lifetime; TyTy::BaseType *tyty; +public: Place (Kind kind, uint32_t variable_or_field_index, const Path &path, - bool is_copy, bool is_rvalue, const Lifetime &lifetime, - TyTy::BaseType *tyty) + bool is_copy, const Lifetime &lifetime, TyTy::BaseType *tyty) : kind (kind), variable_or_field_index (variable_or_field_index), - path (path), is_copy (is_copy), is_rvalue (is_rvalue), - lifetime (lifetime), tyty (tyty) + path (path), is_copy (is_copy), lifetime (lifetime), tyty (tyty) {} + +public: + [[nodiscard]] bool is_lvalue () const + { + return kind == VARIABLE || kind == FIELD || kind == INDEX || kind == DEREF; + } + + [[nodiscard]] bool is_rvalue () const { return kind == TEMPORARY; } + + bool is_constant () const { return kind == CONSTANT; } }; using ScopeId = uint32_t; @@ -134,8 +142,7 @@ public: PlaceDB () { // Reserved index for invalid place. - places.push_back ( - {Place::INVALID, 0, {}, false, false, NO_LIFETIME, nullptr}); + places.push_back ({Place::INVALID, 0, {}, false, NO_LIFETIME, nullptr}); scopes.emplace_back (); // Root scope. } @@ -193,8 +200,7 @@ public: PlaceId add_variable (NodeId id, TyTy::BaseType *tyty) { return add_place ( - {Place::VARIABLE, id, {}, is_type_copy (tyty), false, NO_LIFETIME, tyty}, - 0); + {Place::VARIABLE, id, {}, is_type_copy (tyty), NO_LIFETIME, tyty}, 0); } WARN_UNUSED_RESULT PlaceId lookup_or_add_path (Place::Kind kind, @@ -217,15 +223,14 @@ public: } } return add_place ({kind, id, Place::Path{parent, 0, 0}, is_type_copy (tyty), - false, NO_LIFETIME, tyty}, + NO_LIFETIME, tyty}, current); } PlaceId add_temporary (TyTy::BaseType *tyty) { return add_place ( - {Place::TEMPORARY, 0, {}, is_type_copy (tyty), false, NO_LIFETIME, tyty}, - 0); + {Place::TEMPORARY, 0, {}, is_type_copy (tyty), NO_LIFETIME, tyty}, 0); } PlaceId get_constant (TyTy::BaseType *tyty) @@ -235,8 +240,7 @@ public: return lookup->second; Lifetime lifetime = tyty->get_kind () == TyTy::REF ? STATIC_LIFETIME : NO_LIFETIME; - Place place - = {Place::CONSTANT, 0, {}, is_type_copy (tyty), false, lifetime, tyty}; + Place place = {Place::CONSTANT, 0, {}, is_type_copy (tyty), lifetime, tyty}; places.push_back (place); return places.size () - 1; } @@ -261,24 +265,10 @@ public: if (lookup != INVALID_PLACE) return lookup; add_place ( - {Place::VARIABLE, id, {}, is_type_copy (tyty), false, NO_LIFETIME, tyty}); + {Place::VARIABLE, id, {}, is_type_copy (tyty), NO_LIFETIME, tyty}); return places.size () - 1; }; - PlaceId into_rvalue (PlaceId place) - { - if (places[place].is_rvalue || places[place].kind == Place::CONSTANT - || places[place].tyty->get_kind () == TyTy::REF) - return place; - return add_place ({Place::TEMPORARY, - 0, - {}, - places[place].is_copy, - true, - NO_LIFETIME, - places[place].tyty}); - } - template void for_each_path_from_root (PlaceId var, FN fn) const { PlaceId current = var; diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h index 0b3a4bddbec..7ad62f700db 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h @@ -50,6 +50,10 @@ public: template class VisitableImpl : public BASE { public: + template + explicit VisitableImpl (Args &&... args) : BASE (std::forward (args)...) + {} + void accept_vis (Visitor &visitor) override { visitor.visit (static_cast (*this)); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir.h b/gcc/rust/checks/errors/borrowck/rust-bir.h index 746b2dc7e38..f8a2151aaf8 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir.h @@ -97,20 +97,7 @@ struct BasicBlock std::vector successors; public: - WARN_UNUSED_RESULT bool is_terminated () const - { - if (statements.empty ()) - return false; - switch (statements.back ().get_kind ()) - { - case Statement::Kind::GOTO: - case Statement::Kind::RETURN: - case Statement::Kind::SWITCH: - return true; - default: - return false; - } - } + WARN_UNUSED_RESULT bool is_terminated () const; WARN_UNUSED_RESULT bool is_goto_terminated () const { @@ -119,9 +106,23 @@ public: } }; +enum class ExprKind +{ + INITIALIZER, + OPERATOR, + BORROW, + ASSIGNMENT, + CALL, +}; + // Rhs expression of BIR assignment statements (abstract). class AbstractExpr : public Visitable { + ExprKind kind; + +public: + explicit AbstractExpr (ExprKind kind) : kind (kind) {} + [[nodiscard]] ExprKind get_kind () const { return kind; } }; class InitializerExpr : public VisitableImpl @@ -129,7 +130,10 @@ class InitializerExpr : public VisitableImpl std::vector values; public: - explicit InitializerExpr (std::vector &&values) : values (values) {} + explicit InitializerExpr (std::vector &&values) + : VisitableImpl (ExprKind::INITIALIZER), + values (values) + {} public: std::vector &get_values () { return values; } @@ -142,7 +146,8 @@ class Operator : public VisitableImpl> public: explicit Operator (std::array &&operands) - : operands (operands) + : VisitableImpl> (ExprKind::OPERATOR), + operands (operands) {} public: @@ -158,7 +163,9 @@ class BorrowExpr : public VisitableImpl PlaceId place; public: - explicit BorrowExpr (PlaceId place) : place (place) {} + explicit BorrowExpr (PlaceId place) + : VisitableImpl (ExprKind::BORROW), place (place) + {} WARN_UNUSED_RESULT PlaceId get_place () const { return place; } }; @@ -172,7 +179,9 @@ class Assignment : public VisitableImpl PlaceId rhs; public: - explicit Assignment (PlaceId rhs) : rhs (rhs) {} + explicit Assignment (PlaceId rhs) + : VisitableImpl (ExprKind::ASSIGNMENT), rhs (rhs) + {} public: WARN_UNUSED_RESULT PlaceId get_rhs () const { return rhs; } @@ -185,7 +194,8 @@ class CallExpr : public VisitableImpl public: explicit CallExpr (PlaceId callable, std::vector &&arguments) - : arguments (arguments), callable (callable) + : VisitableImpl (ExprKind::CALL), + arguments (arguments), callable (callable) {} public: @@ -193,6 +203,24 @@ public: WARN_UNUSED_RESULT PlaceId get_callable () const { return callable; } }; +inline bool +BasicBlock::is_terminated () const +{ + if (statements.empty ()) + return false; + switch (statements.back ().get_kind ()) + { + case Statement::Kind::GOTO: + case Statement::Kind::RETURN: + case Statement::Kind::SWITCH: + return true; + case Statement::Kind::ASSIGNMENT: + return statements.back ().get_expr ().get_kind () == ExprKind::CALL; + default: + return false; + } +} + } // namespace BIR } // namespace Rust