diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index facdd43fd518..13745c184762 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -20,6 +20,7 @@
# This file provides the language dependent support in the main Makefile.
+
#RUST_EXES = rust
# Use strict warnings for this front end.
@@ -199,14 +200,19 @@ RUST_ALL_OBJS = $(GRS_OBJS) $(RUST_TARGET_OBJS)
rust_OBJS = $(RUST_ALL_OBJS) rust/rustspec.o
-RUST_LDFLAGS = $(LDFLAGS) -L./../libgrust/libproc_macro_internal
-RUST_LIBDEPS = $(LIBDEPS) ../libgrust/libproc_macro_internal/libproc_macro_internal.a
+# FIXME: Experiment - move to configure
+CLANG_TARGET := $(shell echo "$(host)" | sed 's/-pc-/-unknown-/')
+POLONIUS_LDFLAGS = $(shell cargo rustc --manifest-path $(srcdir)/rust/checks/errors/borrowck/ffi-polonius/Cargo.toml -q --message-format short -- --target $(CLANG_TARGET) --print=native-static-libs | grep "note: native-static-libs:" | sed 's/note: native-static-libs: //g')
+RUST_LDFLAGS = $(LDFLAGS) -L./../libgrust/libproc_macro_internal $(POLONIUS_LDFLAGS)
+RUST_LIBDEPS = $(LIBDEPS) ../libgrust/libproc_macro_internal/libproc_macro_internal.a rust/libffi_polonius.a
# The compiler itself is called crab1
crab1$(exeext): $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(RUST_LIBDEPS) $(rust.prev)
@$(call LINK_PROGRESS,$(INDEX.rust),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(RUST_LDFLAGS) -o $@ \
- $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) ../libgrust/libproc_macro_internal/libproc_macro_internal.a $(BACKENDLIBS)
+ $(RUST_ALL_OBJS) attribs.o $(BACKEND) \
+ $(LIBS) ../libgrust/libproc_macro_internal/libproc_macro_internal.a rust/libffi_polonius.a \
+ $(BACKENDLIBS)
@$(call LINK_PROGRESS,$(INDEX.rust),end)
# Build hooks.
@@ -240,6 +246,7 @@ rust.srcman:
# Clean hooks.
rust.mostlyclean:
+ rm -rf rust/ffi-polonius/release libffi_polonius.a
# cd $(srcdir)/rust; rm -f *.o y.tab.h y.tab.c lex.yy.c
rust.clean: rust.mostlyclean
@@ -461,3 +468,9 @@ rust/%.o: rust/checks/errors/borrowck/%.cc
rust/%.o: rust/metadata/%.cc
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
$(POSTCOMPILE)
+
+rust/libffi_polonius.a: \
+ rust/checks/errors/borrowck/ffi-polonius/Cargo.toml \
+ $(wildcard $(srcdir)/rust/checks/errors/borrowck/ffi-polonius/src/*)
+ cargo build --manifest-path $(srcdir)/rust/checks/errors/borrowck/ffi-polonius/Cargo.toml --release --target-dir rust/ffi-polonius
+ cp rust/ffi-polonius/release/libffi_polonius.a rust/libffi_polonius.a
\ No newline at end of file
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 000000000000..71315c3b635e
--- /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 000000000000..4720150f8b03
--- /dev/null
+++ b/gcc/rust/checks/errors/borrowck/ffi-polonius/src/gccrs_ffi.rs
@@ -0,0 +1,115 @@
+// Copyright (C) 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++
+// ```
+
+// GENERATED START ============================================================
+
+use crate::GccrsAtom;
+
+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: u64,
+ 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>,
+}
+
+// GENERATED END ==============================================================
+
+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/lib.rs b/gcc/rust/checks/errors/borrowck/ffi-polonius/src/lib.rs
new file mode 100644
index 000000000000..4d3f6b6d75b1
--- /dev/null
+++ b/gcc/rust/checks/errors/borrowck/ffi-polonius/src/lib.rs
@@ -0,0 +1,96 @@
+// Copyright (C) 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;
+
+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(),
+ }
+ }
+}
+
+/// 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);
+}
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 000000000000..75635804ccb8
--- /dev/null
+++ b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius-ffi.h
@@ -0,0 +1,98 @@
+// Copyright (C) 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
+
+// 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.
+
+#include
+
+namespace Rust {
+namespace Polonius {
+
+using Origin = size_t;
+using Loan = size_t;
+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)
+ {}
+};
+
+template struct Slice
+{
+ uint64_t len;
+ const T *const data;
+
+ template
+ Slice (const vector &v) : len (v.size ()), data (v.data ())
+ {}
+};
+
+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 000000000000..9959aeb99b61
--- /dev/null
+++ b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h
@@ -0,0 +1,92 @@
+// Copyright (C) 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_H
+#define RUST_POLONIUS_H
+
+// Interface to the Polonius borrow checker engine.
+// See (https://github.com/rust-lang/polonius/blob/master/polonius-engine/)
+
+#include "rust-polonius-ffi.h"
+
+namespace Rust {
+namespace Polonius {
+
+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};
+ }
+};
+
+/**
+ * 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 */
diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc
index 0c952ad32fa5..9a1865f3a252 100644
--- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc
@@ -20,6 +20,7 @@
#include "rust-function-collector.h"
#include "rust-bir-builder.h"
#include "rust-bir-dump.h"
+#include "polonius/rust-polonius.h"
namespace Rust {
namespace HIR {
@@ -86,6 +87,9 @@ BorrowChecker::go (HIR::Crate &crate)
dump_function_bir (filename, bir,
func->get_function_name ().as_string ());
}
+
+ Polonius::Facts facts; // Dummy facts for now.
+ Polonius::polonius_run (facts.freeze (), true);
}
for (auto closure ATTRIBUTE_UNUSED : collector.get_closures ())