gccrs: Added FFIVector to get Polonius output on C++ side
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 <kushalpal109@gmail.com>
This commit is contained in:
parent
e50983a756
commit
29f847e8b8
8 changed files with 259 additions and 14 deletions
|
@ -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) $<
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -16,13 +16,30 @@
|
|||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
mod gccrs_ffi;
|
||||
mod gccrs_ffi_generated;
|
||||
#![feature(extern_types)]
|
||||
|
||||
mod gccrs_ffi;
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
66
gcc/rust/checks/errors/borrowck/polonius/rust-polonius.cc
Normal file
66
gcc/rust/checks/errors/borrowck/polonius/rust-polonius.cc
Normal file
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ());
|
||||
|
|
Loading…
Add table
Reference in a new issue