From: Kushal Pal <kushalpal...@gmail.com>

gcc/rust/ChangeLog:

        * Make-lang.in: Compile new file, rust-polonius.cc
        * checks/errors/borrowck/ffi-polonius/src/gccrs_ffi.rs: Opaque
        type to represent FFIVector from C++.
        * checks/errors/borrowck/ffi-polonius/src/gccrs_ffi_generated.rs:
        Change types of fields in Output.
        * checks/errors/borrowck/ffi-polonius/src/lib.rs: Added helper
        functions to contruct Polonius output on C++ side,
        used helpers to contruct Polonius output on C++ side.
        * checks/errors/borrowck/polonius/rust-polonius-ffi.h (make_vector):
        FFIVector is a wrapper around std::vector for transfering data
        from Rust to C++.
        (struct Output): Use pointers to FFIVector instead of bool to
        store Polonius output data.
        * checks/errors/borrowck/polonius/rust-polonius.h (FFIVector__new):
        Helper function.
        (FFIVector__new_vec_pair): Likewise.
        (FFIVector__new_vec_triple): Likewise.
        (FFIVector__push): Likewise.
        (FFIVector__push_vec_pair): Likewise.
        (FFIVector__push_vec_triple): Likewise.
        * checks/errors/borrowck/rust-borrow-checker.cc (BorrowChecker::go):
        Convert FFIVector to std::vector representation for easier
        navigation.
        * checks/errors/borrowck/polonius/rust-polonius.cc: New file,
        implementation of helper functions.

Signed-off-by: Kushal Pal <kushalpal...@gmail.com>
---
 gcc/rust/Make-lang.in                         |  7 ++
 .../borrowck/ffi-polonius/src/gccrs_ffi.rs    |  5 ++
 .../ffi-polonius/src/gccrs_ffi_generated.rs   |  6 +-
 .../errors/borrowck/ffi-polonius/src/lib.rs   | 76 ++++++++++++++++++-
 .../borrowck/polonius/rust-polonius-ffi.h     | 71 ++++++++++++++++-
 .../errors/borrowck/polonius/rust-polonius.cc | 66 ++++++++++++++++
 .../errors/borrowck/polonius/rust-polonius.h  | 24 ++++++
 .../errors/borrowck/rust-borrow-checker.cc    | 16 +++-
 8 files changed, 258 insertions(+), 13 deletions(-)
 create mode 100644 gcc/rust/checks/errors/borrowck/polonius/rust-polonius.cc

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 4f164c9753a..17f1feb6e46 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -171,6 +171,7 @@ GRS_OBJS = \
     rust/rust-borrow-checker.o \
     rust/rust-bir-builder-expr-stmt.o \
     rust/rust-bir-dump.o \
+    rust/rust-polonius.o\
     rust/rust-hir-dot-operator.o \
     rust/rust-hir-path-probe.o \
     rust/rust-type-util.o \
@@ -487,6 +488,12 @@ rust/%.o: rust/checks/errors/borrowck/%.cc
        $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
        $(POSTCOMPILE)
 
+
+# build borrow checking pass polonius files in rust folder
+rust/%.o: rust/checks/errors/borrowck/polonius/%.cc
+       $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+       $(POSTCOMPILE)
+
 # build rust/metadata files in rust folder
 rust/%.o: rust/metadata/%.cc
        $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
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
index 6d30d3c5cfb..0cb85078158 100644
--- a/gcc/rust/checks/errors/borrowck/ffi-polonius/src/gccrs_ffi.rs
+++ b/gcc/rust/checks/errors/borrowck/ffi-polonius/src/gccrs_ffi.rs
@@ -32,6 +32,11 @@ include!("gccrs_ffi_generated.rs");
 
 use crate::GccrsAtom;
 
+// Using opqaue types
+extern "C" {
+    pub type FFIVector;
+}
+
 impl<T1, T2> Into<(GccrsAtom, GccrsAtom)> for Pair<T1, T2>
 where
     GccrsAtom: From<T1> + From<T2>,
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
index db75a1d1509..b2c190d386a 100644
--- 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
@@ -52,7 +52,7 @@ pub struct FactsView {
 #[repr(C)]
 #[derive(Debug, Copy, Clone)]
 pub struct Output {
-    pub loan_errors: bool,
-    pub subset_errors: bool,
-    pub move_errors: bool,
+    pub loan_errors: *mut FFIVector,
+    pub move_errors: *mut FFIVector,
+    pub subset_errors: *mut FFIVector,
 }
diff --git a/gcc/rust/checks/errors/borrowck/ffi-polonius/src/lib.rs 
b/gcc/rust/checks/errors/borrowck/ffi-polonius/src/lib.rs
index b743be2e6be..782a63f8078 100644
--- a/gcc/rust/checks/errors/borrowck/ffi-polonius/src/lib.rs
+++ b/gcc/rust/checks/errors/borrowck/ffi-polonius/src/lib.rs
@@ -16,13 +16,30 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
+#![feature(extern_types)]
+
 mod gccrs_ffi;
-mod gccrs_ffi_generated;
 
+use gccrs_ffi::FFIVector;
 use polonius_engine::{AllFacts, Atom, FactTypes, Output};
 use std::fmt::Debug;
 use std::hash::Hash;
 
+extern "C" {
+    fn FFIVector__new() -> *mut FFIVector;
+    fn FFIVector__new_vec_pair() -> *mut FFIVector;
+    fn FFIVector__new_vec_triple() -> *mut FFIVector;
+    fn FFIVector__push(vector: *mut FFIVector, element: usize);
+    fn FFIVector__push_vec_pair(
+        vector: *mut FFIVector,
+        element: gccrs_ffi::Pair<usize, *mut FFIVector>,
+    );
+    fn FFIVector__push_vec_triple(
+        vector: *mut FFIVector,
+        element: gccrs_ffi::Triple<usize, usize, usize>,
+    );
+}
+
 /// A single fact value.
 /// For simplicity we use one type for all facts.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -46,6 +63,12 @@ impl From<GccrsAtom> for usize {
     }
 }
 
+impl From<&GccrsAtom> for usize {
+    fn from(atom: &GccrsAtom) -> Self {
+        atom.index()
+    }
+}
+
 #[derive(Debug, Clone, Copy, Default)]
 struct GccrsFacts;
 
@@ -172,9 +195,54 @@ pub unsafe extern "C" fn polonius_run(
         }
     }
 
+    let loan_errors = FFIVector__new_vec_pair();
+    for (keys, values) in output.errors.iter() {
+        let loans_vec = FFIVector__new();
+        for loan in values.iter() {
+            let loan: usize = loan.into();
+            FFIVector__push(loans_vec, loan);
+        }
+        let point: usize = keys.into();
+        let pair = gccrs_ffi::Pair {
+            first: point,
+            second: loans_vec,
+        };
+        FFIVector__push_vec_pair(loan_errors, pair);
+    }
+
+    let move_errors = FFIVector__new_vec_pair();
+    for (keys, values) in output.move_errors.iter() {
+        let paths_vec = FFIVector__new();
+        for path in values.iter() {
+            let path: usize = path.into();
+            FFIVector__push(paths_vec, path);
+        }
+        let point: usize = keys.into();
+        let pair = gccrs_ffi::Pair {
+            first: point,
+            second: paths_vec,
+        };
+        FFIVector__push_vec_pair(move_errors, pair);
+    }
+
+    let subset_errors = FFIVector__new_vec_triple();
+    for (key, value) in output.subset_errors.iter() {
+        let point: usize = key.into();
+        for origin_pair in value.iter() {
+            let origin_1: usize = origin_pair.0.into();
+            let origin_2: usize = origin_pair.1.into();
+            let triple = gccrs_ffi::Triple {
+                first: point,
+                second: origin_1,
+                third: origin_2,
+            };
+            FFIVector__push_vec_triple(subset_errors, triple);
+        }
+    }
+
     return gccrs_ffi::Output {
-        loan_errors: output.errors.len() > 0,
-        subset_errors: output.subset_errors.len() > 0,
-        move_errors: output.move_errors.len() > 0,
+        loan_errors,
+        move_errors,
+        subset_errors,
     };
 }
diff --git a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius-ffi.h 
b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius-ffi.h
index af37e0f9fb4..e11ba55b1e4 100644
--- a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius-ffi.h
+++ b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius-ffi.h
@@ -102,11 +102,76 @@ struct FactsView
   Slice<Pair<Origin, Loan>> placeholder;
 };
 
+// Wrapper around std::vector to pass data from Rust to C++
+template <typename T> struct FFIVector
+{
+  std::vector<T> data;
+
+public:
+  void push (T new_element) { data.push_back (new_element); };
+
+  // allocates memory to a new instance and returns the pointer
+  static FFIVector *make_new () { return new FFIVector{}; }
+
+  // returns current size
+  size_t size () const { return data.size (); }
+
+  T at (size_t index) const
+  {
+    rust_assert (index < data.size ());
+    return data.at (index);
+  }
+};
+
+// Some useful type aliases
+using FFIVectorPair = FFIVector<Pair<size_t, FFIVector<size_t> *>>;
+using FFIVectorTriple = FFIVector<Triple<size_t, size_t, size_t>>;
+
+inline std::vector<size_t>
+make_vector (const FFIVector<size_t> *vec_sizet)
+{
+  std::vector<size_t> return_val (vec_sizet->size ());
+  for (size_t i = 0; i < vec_sizet->size (); ++i)
+    {
+      return_val[i] = vec_sizet->at (i);
+    }
+  return return_val;
+}
+
+inline std::vector<std::pair<size_t, std::vector<size_t>>>
+make_vector (const FFIVectorPair *vec_pair)
+{
+  std::vector<std::pair<size_t, std::vector<size_t>>> return_val (
+    vec_pair->size ());
+  for (size_t i = 0; i < vec_pair->size (); ++i)
+    {
+      std::pair<size_t, std::vector<size_t>> current_pair
+       = {vec_pair->at (i).first, make_vector (vec_pair->at (i).second)};
+      return_val[i] = current_pair;
+    }
+  return return_val;
+}
+
+inline std::vector<std::pair<size_t, std::pair<size_t, size_t>>>
+make_vector (const FFIVectorTriple *vec_triple)
+{
+  std::vector<std::pair<size_t, std::pair<size_t, size_t>>> return_val (
+    vec_triple->size ());
+  for (size_t i = 0; i < vec_triple->size (); ++i)
+    {
+      auto current_element = std::pair<size_t, std::pair<size_t, size_t>>{
+       vec_triple->at (i).first,
+       {vec_triple->at (i).second, vec_triple->at (i).third}};
+      return_val[i] = current_element;
+    }
+  return return_val;
+}
+
 struct Output
 {
-  bool loan_errors;
-  bool subset_errors;
-  bool move_errors;
+  FFIVectorPair *loan_errors;
+  FFIVectorPair *move_errors;
+  FFIVectorTriple *subset_errors;
 };
 
 } // namespace FFI
diff --git a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.cc 
b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.cc
new file mode 100644
index 00000000000..61f431f6141
--- /dev/null
+++ b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.cc
@@ -0,0 +1,66 @@
+// Copyright (C) 2020-2024 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
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-polonius.h"
+
+namespace Rust {
+namespace Polonius {
+
+extern "C" {
+
+FFI::FFIVector<size_t> *
+FFIVector__new ()
+{
+  return FFI::FFIVector<size_t>::make_new ();
+}
+
+FFI::FFIVectorPair *
+FFIVector__new_vec_pair ()
+{
+  return FFI::FFIVectorPair::make_new ();
+}
+
+FFI::FFIVectorTriple *
+FFIVector__new_vec_triple ()
+{
+  return FFI::FFIVectorTriple::make_new ();
+}
+
+void
+FFIVector__push (FFI::FFIVector<size_t> *vector, size_t element)
+{
+  vector->push (element);
+}
+
+void
+FFIVector__push_vec_pair (FFI::FFIVectorPair *vector,
+                         FFI::Pair<size_t, FFI::FFIVector<size_t> *> element)
+{
+  vector->push (element);
+}
+
+void
+FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector,
+                           FFI::Triple<size_t, size_t, size_t> element)
+{
+  vector->push (element);
+}
+}
+
+} // namespace Polonius
+} // namespace Rust
diff --git a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h 
b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h
index bc145e707d3..b013a93671c 100644
--- a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h
+++ b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h
@@ -225,6 +225,30 @@ struct Facts
 extern "C" FFI::Output
 polonius_run (FFI::FactsView input, bool dump_enabled);
 
+// Helper functions for FFIVector to be used on Rust side
+extern "C" {
+
+FFI::FFIVector<size_t> *
+FFIVector__new ();
+
+FFI::FFIVectorPair *
+FFIVector__new_vec_pair ();
+
+FFI::FFIVectorTriple *
+FFIVector__new_vec_triple ();
+
+void
+FFIVector__push (FFI::FFIVector<size_t> *vector, size_t element);
+
+void
+FFIVector__push_vec_pair (FFI::FFIVectorPair *vector,
+                         FFI::Pair<size_t, FFI::FFIVector<size_t> *> element);
+
+void
+FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector,
+                           FFI::Triple<size_t, size_t, size_t> element);
+}
+
 } // namespace Polonius
 } // namespace Rust
 
diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc 
b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc
index 29a9f4d27bb..0ef4e5abf8c 100644
--- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc
@@ -142,19 +142,29 @@ BorrowChecker::go (HIR::Crate &crate)
       auto result
        = Polonius::polonius_run (facts.freeze (), rust_be_debug_p ());
 
-      if (result.loan_errors)
+      // convert to std::vector variation for easier navigation
+      auto loan_errors = make_vector (result.loan_errors);
+      auto move_errors = make_vector (result.move_errors);
+      auto subset_errors = make_vector (result.subset_errors);
+
+      // free allocated data
+      delete result.loan_errors;
+      delete result.move_errors;
+      delete result.subset_errors;
+
+      if (!loan_errors.empty ())
        {
          rust_error_at (func->get_locus (), "Found loan errors in function %s",
                         func->get_function_name ().as_string ().c_str ());
        }
-      if (result.subset_errors)
+      if (!subset_errors.empty ())
        {
          rust_error_at (func->get_locus (),
                         "Found subset errors in function %s. Some lifetime "
                         "constraints need to be added.",
                         func->get_function_name ().as_string ().c_str ());
        }
-      if (result.move_errors)
+      if (!move_errors.empty ())
        {
          rust_error_at (func->get_locus (), "Found move errors in function %s",
                         func->get_function_name ().as_string ().c_str ());
-- 
2.45.2

Reply via email to