From patchwork Thu Aug 1 14:57:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arthur Cohen X-Patchwork-Id: 1967826 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=Ha7UrBRp; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; 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 [IPv6:2620:52:3:1:0:246e:9693:128c]) (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 4WZXzP74bqz1yZv for ; Fri, 2 Aug 2024 01:33:05 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 378BB3861810 for ; Thu, 1 Aug 2024 15:33:04 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-lf1-x133.google.com (mail-lf1-x133.google.com [IPv6:2a00:1450:4864:20::133]) by sourceware.org (Postfix) with ESMTPS id 9AE61386101C for ; Thu, 1 Aug 2024 15:00:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9AE61386101C 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 9AE61386101C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::133 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722524495; cv=none; b=IUTxarxezX/H+Us1J96XPT7hmojuH32ytegFp01A+d/V/OELJWZ0kt2948tk4OrRqXnlhXZSd2Q62AG2CYeL4kuM0BhRdzodlqCiSJixwpQdzHGei3OFolPTnF3D0m+GGVeab8Vp0gEiSRmCv2yCUQ+dqNy1T4vg3PJW+EwPhag= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722524495; c=relaxed/simple; bh=GNUOfNFdDfCklXOU0aUpwMNfo+z0KKOgsxigNuiiUMo=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=nkS9t3QnA34YDFMEfOMCEY+bqRvjhp9yNIh37MLvv75LB976+Jt28Wld8O7cudzu4YRMOYXsQcaT0g7OEECzLhmJoar6LVMj79rs2LFf9MXKnRePToBR7Fm4WAO4k4afuLylZLwBTao42ML1xOlo1NpVUR009juZXnYGIZJ30X4= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-lf1-x133.google.com with SMTP id 2adb3069b0e04-52efd08e6d9so10388970e87.1 for ; Thu, 01 Aug 2024 08:00:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; t=1722524440; x=1723129240; 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=OGtUQg1f0fnLQv+sUYKrOQQ6Qz7jU9ghu9Jt9PRTU7Q=; b=Ha7UrBRpeAXG1xGxq7r0z90Y82SAADTiSGICNffHo4mfUMRxemnTsBll0Eb9AcfmhJ WWp7+SSXv5jUgxZ8ATxakXI9LM7UlfKBH3RgrluefMgyFSby6JtOB/M+n9kEFmlNUcE/ LRhscF/urkyVlflJOYBhS37l5wxMtH6e63Bo6k2DsfV3kvhxNh+DX6yhSOy2ng++DRlt gXKQV3Wm6No0DuSikHoBYsNpMOCC7694nYesUfhojJUUy1RbQbyRecP4BE5K/mo26Pdd CS7mY3LVnUQs+pOob6Hlh86OA1VOCALfhFNhy56Jwu5KxBGVD61e4hWtusAhDxzgONEn UIbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722524440; x=1723129240; 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=OGtUQg1f0fnLQv+sUYKrOQQ6Qz7jU9ghu9Jt9PRTU7Q=; b=P3xBMANGdjlVuyfq2PVTauGqukL05Ifb1NPZabJvX07/HVdMa0c1n/M8qUu/mt1m4X QOzIP5Ynda8M/iOQVIlzrLkg91gQhUtM8kMJ7OJHb37zY8+BatGoM85H+N/ZGcZfrWBS MhclLDU70Ixo4uMPSDmg9A5FQ+ZtX7lR5Q+svU/LWr9o86jMMwyjQgG8uUD62rbf07EY A7QTYRlcPoCyUr4tD1K12JuSjlfbUmvwIeDWbt79hdqqaF3eXfZHi+e9O0EKwDhgbujW 3Qots0IEoW07IDm6uDcwoNRS0BmnSIIHxWrxEi0evpoM9TjtVceqhL3756lg/HZ5ySNn 0SWA== X-Gm-Message-State: AOJu0YwHzrLEL0Q8sOf+mFnp1AWzWoJOBjaBEaJ87Gtz26XFe8cLf/Rr vPxdqxTzPW/1+E00ZloY9SIdkYEpIn1nsaw1wQY2h/0qv3acZ7Sb5Dx14Ij1Y499hgiU3jDh3J/ XGpbV X-Google-Smtp-Source: AGHT+IGA6xPuOWlmxIfE4P2EeSSAX8Sw2RVLl1RPR1Z0YsmvXE6r9moer5AEoP8OwufpWsQyc+kDuA== X-Received: by 2002:a05:6512:1189:b0:52c:daa7:8975 with SMTP id 2adb3069b0e04-530bb39788fmr110108e87.18.1722524439539; Thu, 01 Aug 2024 08:00:39 -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.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Aug 2024 08:00:38 -0700 (PDT) From: Arthur Cohen To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org, Jakub Dupak Subject: [PATCH 117/125] gccrs: borrowck: Polonius FFI Date: Thu, 1 Aug 2024 16:57:53 +0200 Message-ID: <20240801145809.366388-119-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.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham 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 Rust part is not build and not invoked at this point. gcc/rust/ChangeLog: * checks/errors/borrowck/ffi-polonius/Cargo.toml: New file. * checks/errors/borrowck/ffi-polonius/src/gccrs_ffi.rs: New file. * checks/errors/borrowck/ffi-polonius/src/gccrs_ffi_generated.rs: New file. * checks/errors/borrowck/ffi-polonius/src/lib.rs: New file. * checks/errors/borrowck/polonius/rust-polonius-ffi.h: New file. * checks/errors/borrowck/polonius/rust-polonius.h: New file. Signed-off-by: Jakub Dupak --- .../errors/borrowck/ffi-polonius/Cargo.toml | 11 + .../borrowck/ffi-polonius/src/gccrs_ffi.rs | 61 +++++ .../ffi-polonius/src/gccrs_ffi_generated.rs | 50 ++++ .../errors/borrowck/ffi-polonius/src/lib.rs | 133 ++++++++++ .../borrowck/polonius/rust-polonius-ffi.h | 109 ++++++++ .../errors/borrowck/polonius/rust-polonius.h | 232 ++++++++++++++++++ 6 files changed, 596 insertions(+) create mode 100644 gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.toml create mode 100644 gcc/rust/checks/errors/borrowck/ffi-polonius/src/gccrs_ffi.rs create mode 100644 gcc/rust/checks/errors/borrowck/ffi-polonius/src/gccrs_ffi_generated.rs create mode 100644 gcc/rust/checks/errors/borrowck/ffi-polonius/src/lib.rs create mode 100644 gcc/rust/checks/errors/borrowck/polonius/rust-polonius-ffi.h create mode 100644 gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h diff --git a/gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.toml b/gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.toml new file mode 100644 index 00000000000..71315c3b635 --- /dev/null +++ b/gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "ffi-polonius" +version = "0.1.0" +edition = "2021" +license = "GPL-3" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +polonius-engine = "0.13.0" \ No newline at end of file diff --git a/gcc/rust/checks/errors/borrowck/ffi-polonius/src/gccrs_ffi.rs b/gcc/rust/checks/errors/borrowck/ffi-polonius/src/gccrs_ffi.rs new file mode 100644 index 00000000000..3a849444bbc --- /dev/null +++ b/gcc/rust/checks/errors/borrowck/ffi-polonius/src/gccrs_ffi.rs @@ -0,0 +1,61 @@ +// Copyright (C) 2020-2023 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +// This is an FFI interface to gccrs (c++). +// It is a counterpart to `rust-polonius-ffi.h`. + +// Generated by rust-bindgen, remove unsafe phantoms and add Into impls. +// ```shell +// bindgen \ +// --generate types \ +// --allowlist-file rust-polonius-facts-ffi.h +// --no-layout-tests +// rust-polonius-ffi.h +// -- -x c++ +// ``` +include!("gccrs_ffi_generated.rs"); + +use crate::GccrsAtom; + +impl Into<(GccrsAtom, GccrsAtom)> for Pair +where + GccrsAtom: From + From, +{ + fn into(self) -> (GccrsAtom, GccrsAtom) { + (self.first.into(), self.second.into()) + } +} + +impl Into<(GccrsAtom, GccrsAtom, GccrsAtom)> for Triple +where + GccrsAtom: From + From + From, +{ + fn into(self) -> (GccrsAtom, GccrsAtom, GccrsAtom) { + (self.first.into(), self.second.into(), self.third.into()) + } +} + +impl Into> for Slice +where + IN: Into + Copy, +{ + fn into(self) -> Vec { + let slice = unsafe { std::slice::from_raw_parts(self.data, self.len as usize) }; + slice.iter().map(|&e| e.into()).collect() + } +} diff --git a/gcc/rust/checks/errors/borrowck/ffi-polonius/src/gccrs_ffi_generated.rs b/gcc/rust/checks/errors/borrowck/ffi-polonius/src/gccrs_ffi_generated.rs new file mode 100644 index 00000000000..20908179528 --- /dev/null +++ b/gcc/rust/checks/errors/borrowck/ffi-polonius/src/gccrs_ffi_generated.rs @@ -0,0 +1,50 @@ +pub type Origin = usize; +pub type Loan = usize; +pub type Point = usize; +pub type Variable = usize; +pub type Path = usize; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Pair { + pub first: T1, + pub second: T2, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Triple { + pub first: T1, + pub second: T2, + pub third: T3, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Slice { + pub len: usize, + pub data: *const T, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct FactsView { + pub loan_issued_at: Slice>, + pub universal_region: Slice, + pub cfg_edge: Slice>, + pub loan_killed_at: Slice>, + pub subset_base: Slice>, + pub loan_invalidated_at: Slice>, + pub var_used_at: Slice>, + pub var_defined_at: Slice>, + pub var_dropped_at: Slice>, + pub use_of_var_derefs_origin: Slice>, + pub drop_of_var_derefs_origin: Slice>, + pub child_path: Slice>, + pub path_is_var: Slice>, + pub path_assigned_at_base: Slice>, + pub path_moved_at_base: Slice>, + pub path_accessed_at_base: Slice>, + pub known_placeholder_subset: Slice>, + pub placeholder: Slice>, +} diff --git a/gcc/rust/checks/errors/borrowck/ffi-polonius/src/lib.rs b/gcc/rust/checks/errors/borrowck/ffi-polonius/src/lib.rs new file mode 100644 index 00000000000..a9aa8106b69 --- /dev/null +++ b/gcc/rust/checks/errors/borrowck/ffi-polonius/src/lib.rs @@ -0,0 +1,133 @@ +// Copyright (C) 2020-2023 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +mod gccrs_ffi; +mod gccrs_ffi_generated; + +use polonius_engine::{AllFacts, Atom, FactTypes, Output}; +use std::fmt::Debug; +use std::hash::Hash; + +/// A single fact value. +/// For simplicity we use one type for all facts. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +struct GccrsAtom(usize); + +impl Atom for GccrsAtom { + fn index(self) -> usize { + self.0 + } +} + +impl From for GccrsAtom { + fn from(inner: usize) -> GccrsAtom { + GccrsAtom(inner) + } +} + +impl From for usize { + fn from(atom: GccrsAtom) -> Self { + atom.index() + } +} + +#[derive(Debug, Clone, Copy, Default)] +struct GccrsFacts; + +impl FactTypes for GccrsFacts { + type Origin = GccrsAtom; + type Loan = GccrsAtom; + type Point = GccrsAtom; + type Variable = GccrsAtom; + type Path = GccrsAtom; +} + +impl From for AllFacts { + fn from(input: gccrs_ffi::FactsView) -> Self { + AllFacts:: { + loan_issued_at: input.loan_issued_at.into(), + universal_region: input.universal_region.into(), + cfg_edge: input.cfg_edge.into(), + loan_killed_at: input.loan_killed_at.into(), + subset_base: input.subset_base.into(), + loan_invalidated_at: input.loan_invalidated_at.into(), + var_used_at: input.var_used_at.into(), + var_defined_at: input.var_defined_at.into(), + var_dropped_at: input.var_dropped_at.into(), + use_of_var_derefs_origin: input.use_of_var_derefs_origin.into(), + drop_of_var_derefs_origin: input.drop_of_var_derefs_origin.into(), + child_path: input.child_path.into(), + path_is_var: input.path_is_var.into(), + path_assigned_at_base: input.path_assigned_at_base.into(), + path_moved_at_base: input.path_moved_at_base.into(), + path_accessed_at_base: input.path_accessed_at_base.into(), + known_placeholder_subset: input.known_placeholder_subset.into(), + placeholder: input.placeholder.into(), + } + } +} + +fn print_point(point: GccrsAtom) { + let val: usize = point.into(); + let mid = val % 2 == 1; + let bb = val >> 16; + let stmt = (val >> 1) & 0xFFFF; + print!("{}(bb{}[{}])", if mid { "Mid" } else { "Start" }, bb, stmt); +} + +/// Run the polonius analysis on the given facts (for a single function). +/// Right now, results are only printed and not propagated back to the gccrs. +#[no_mangle] +pub unsafe extern "C" fn polonius_run(input: gccrs_ffi::FactsView, dump_enabled: bool) { + let facts = AllFacts::::from(input); + let output = Output::compute(&facts, polonius_engine::Algorithm::Naive, dump_enabled); + + // FIXME: Temporary output + println!("Polonius analysis completed. Results:"); + println!("Errors: {:#?}", output.errors); + println!("Subset error: {:#?}", output.subset_errors); + println!("Move error: {:#?}", output.move_errors); + + println!("Subsets:"); + let mut subset_vec: Vec<_> = output.subset.iter().collect(); + subset_vec.sort_by_key(|&(point, _)| point); + for (point, subsets) in subset_vec { + print_point(*point); + println!(": {{"); + for (&lhs, rhss) in subsets { + for &rhs in rhss { + println!(" {} <= {}", usize::from(lhs), usize::from(rhs)); + } + } + println!("}}"); + } + println!("Subset anywhere: {:#?}", output.subset_anywhere); + + // Print origin live on entry + println!("Origin live on entry:"); + let mut origin_vec: Vec<_> = output.origin_live_on_entry.iter().collect(); + origin_vec.sort_by_key(|&(point, _)| point); + for (point, origins) in origin_vec { + print_point(*point); + println!(": {{"); + for &origin in origins { + println!(" {}", usize::from(origin)); + } + println!("}}"); + } +} diff --git a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius-ffi.h b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius-ffi.h new file mode 100644 index 00000000000..500d25a3222 --- /dev/null +++ b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius-ffi.h @@ -0,0 +1,109 @@ +// Copyright (C) 2020-2023 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_POLONIUS_FACTS_FFI_H +#define RUST_POLONIUS_FACTS_FFI_H + +#include "rust-system.h" + +// This file defines the C++ side of the FFI interface to Polonius. +// The corresponding Rust side is in `gccrs-ffi.rs`. + +// IMPORTANT: +// This file intentionally does not include any C++ headers +// to allow seamless binding generation on the Rust side. + +namespace Rust { +namespace Polonius { + +using Origin = size_t; +using Loan = size_t; +/** + * Compressed CFG point + * Encoding: + * - (bit size - 16) bits: basic block index + * - 15 bits: stmt index inside basic block + * - 1bit: start or mid + * + * Note: Polonius requires the holding type to be `size_t`/`usize`. + */ +using Point = size_t; +using Variable = size_t; +using Path = size_t; + +namespace FFI { + +// NOTE: std::pair and std::tuple are complicating the bindings' generation. +template struct Pair +{ + T1 first; + T2 second; + + Pair (T1 first, T2 second) : first (first), second (second) {} +}; + +template struct Triple +{ + T1 first; + T2 second; + T3 third; + + Triple (T1 first, T2 second, T3 third) + : first (first), second (second), third (third) + {} +}; + +/** Frozen variant to vector for FFI */ +template struct Slice +{ + size_t len; + const T *const data; + + template + Slice (const vector &v) : len (v.size ()), data (v.data ()) + {} +}; + +/** Frozen variant of the facts with C ABI and no methods. */ +struct FactsView +{ + Slice> loan_issued_at; + Slice universal_region; + Slice> cfg_edge; + Slice> loan_killed_at; + Slice> subset_base; + Slice> loan_invalidated_at; + Slice> var_used_at; + Slice> var_defined_at; + Slice> var_dropped_at; + Slice> use_of_var_derefs_origin; + Slice> drop_of_var_derefs_origin; + Slice> child_path; + Slice> path_is_var; + Slice> path_assigned_at_base; + Slice> path_moved_at_base; + Slice> path_accessed_at_base; + Slice> known_placeholder_subset; + Slice> placeholder; +}; + +} // namespace FFI +} // namespace Polonius +} // namespace Rust + +#endif // RUST_POLONIUS_FACTS_FFI_H diff --git a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h new file mode 100644 index 00000000000..df746dd0c76 --- /dev/null +++ b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h @@ -0,0 +1,232 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_POLONIUS_H +#define RUST_POLONIUS_H + +// Interface to the Polonius borrow checker engine. +// See (https://github.com/rust-lang/polonius/blob/master/polonius-engine/) + +#include +#include "rust-polonius-ffi.h" + +namespace Rust { +namespace Polonius { + +/** A point in the control flow graph. */ +struct FullPoint +{ + uint32_t bb; + uint32_t stmt; + bool mid; + + /** Expands a compressed `Point` into its components. + * See `Point` docs for encoding details. + */ + explicit FullPoint (Point point) + : bb (extract_bb (point)), stmt (extract_stmt (point)), + mid (extract_mid (point)) + {} + + static uint32_t extract_bb (Point point) { return point >> 16; } + static uint32_t extract_stmt (Point point) + { + return (point & ~(1 << 16)) >> 1; + } + static bool extract_mid (Point point) { return point & 1; } + + friend std::ostream &operator<< (std::ostream &os, const FullPoint &point) + { + return os << ((point.mid) ? "Mid" : "Start") << "(bb" << point.bb << "[" + << point.stmt << "])"; + } +}; + +struct Facts +{ + // See (https://rust-lang.github.io/polonius/rules/relations.html) + std::vector> loan_issued_at; + std::vector universal_region; + std::vector> cfg_edge; + std::vector> loan_killed_at; + std::vector> subset_base; + std::vector> loan_invalidated_at; + std::vector> var_used_at; + std::vector> var_defined_at; + std::vector> var_dropped_at; + std::vector> use_of_var_derefs_origin; + std::vector> drop_of_var_derefs_origin; + std::vector> child_path; + std::vector> path_is_var; + std::vector> path_assigned_at_base; + std::vector> path_moved_at_base; + std::vector> path_accessed_at_base; + std::vector> known_placeholder_subset; + std::vector> placeholder; + + /** + * Create a const view for the struct for FFI. + * + * This view uses the original vector storage. + * Therefore any resizing operation of Facts member may invalidate the view. + */ + FFI::FactsView freeze () + { + return FFI::FactsView{loan_issued_at, + universal_region, + cfg_edge, + loan_killed_at, + subset_base, + loan_invalidated_at, + var_used_at, + var_defined_at, + var_dropped_at, + use_of_var_derefs_origin, + drop_of_var_derefs_origin, + child_path, + path_is_var, + path_assigned_at_base, + path_moved_at_base, + path_accessed_at_base, + known_placeholder_subset, + placeholder}; + } + + void dump_loan_issued_at (std::ostream &os) const + { + for (auto &e : loan_issued_at) + os << "\"'?" << e.first << "\"\t\"bw" << e.second << "\"\t\"" + << FullPoint (e.third) << "\"\n"; + } + + void dump_universal_region (std::ostream &os) const + { + for (auto &e : universal_region) + os << e << "\n"; + } + + void dump_cfg_edge (std::ostream &os) const + { + for (auto &e : cfg_edge) + os << FullPoint (e.first) << " " << FullPoint (e.second) << "\n"; + } + + void dump_loan_killed_at (std::ostream &os) const + { + for (auto &e : loan_killed_at) + os << e.first << " " << FullPoint (e.second) << "\n"; + } + + void dump_subset_base (std::ostream &os) const + { + for (auto &e : subset_base) + os << "\"'?" << e.first << "\"\t\"'?" << e.second << "\"\t\"" + << FullPoint (e.third) << "\"\n"; + } + + void dump_loan_invalidated_at (std::ostream &os) const + { + for (auto &e : loan_invalidated_at) + os << FullPoint (e.first) << " " << e.second << "\n"; + } + + void dump_var_used_at (std::ostream &os) const + { + for (auto &e : var_used_at) + os << e.first - 1 << " " << FullPoint (e.second) << "\n"; + } + + void dump_var_defined_at (std::ostream &os) const + { + for (auto &e : var_defined_at) + os << e.first << " " << FullPoint (e.second) << "\n"; + } + + void dump_var_dropped_at (std::ostream &os) const + { + for (auto &e : var_dropped_at) + os << e.first << " " << FullPoint (e.second) << "\n"; + } + + void dump_use_of_var_derefs_origin (std::ostream &os) const + { + for (auto &e : use_of_var_derefs_origin) + os << e.first << " " << e.second << "\n"; + } + + void dump_drop_of_var_derefs_origin (std::ostream &os) const + { + for (auto &e : drop_of_var_derefs_origin) + os << e.first << " " << e.second << "\n"; + } + + void dump_child_path (std::ostream &os) const + { + for (auto &e : child_path) + os << e.first << " " << e.second << "\n"; + } + + void dump_path_is_var (std::ostream &os) const + { + for (auto &e : path_is_var) + os << e.first << " " << e.second << "\n"; + } + + void dump_path_assigned_at_base (std::ostream &os) const + { + for (auto &e : path_assigned_at_base) + os << e.first << " " << FullPoint (e.second) << "\n"; + } + + void dump_path_moved_at_base (std::ostream &os) const + { + for (auto &e : path_moved_at_base) + os << e.first << " " << FullPoint (e.second) << "\n"; + } + + void dump_path_accessed_at_base (std::ostream &os) const + { + for (auto &e : path_accessed_at_base) + os << e.first << " " << FullPoint (e.second) << "\n"; + } + + void dump_known_placeholder_subset (std::ostream &os) const + { + for (auto &e : known_placeholder_subset) + os << e.first << " " << e.second << "\n"; + } + + void dump_placeholder (std::ostream &os) const + { + for (auto &e : placeholder) + os << e.first << " " << e.second << "\n"; + } +}; + +/** + * Check a single function for borrow errors. + * + * Output is not yet implemented and is only dumped to stdout. + */ +extern "C" void +polonius_run (FFI::FactsView input, bool dump_enabled); + +} // namespace Polonius +} // namespace Rust + +#endif /* !RUST_POLONIUS_H */