Skip to content
Snippets Groups Projects
Commit 6e04e69b authored by Arthur Cohen's avatar Arthur Cohen
Browse files

gccrs: libformat_parser: Send boxed values across FFI properly

gcc/rust/ChangeLog:

	* ast/rust-fmt.cc (Pieces::~Pieces): Call libformat_parser's release
	function in destructor.
	* ast/rust-fmt.h (struct PieceSlice): Add capacity.
	(destroy_pieces): New.
	(struct Pieces): Add destructor.

libgrust/ChangeLog:

	* libformat_parser/src/lib.rs: Leak Boxes properly for C++ to
	see them, add memory release function.
parent d6332141
No related branches found
No related tags found
No related merge requests found
...@@ -34,8 +34,10 @@ Pieces::collect (const std::string &to_parse) ...@@ -34,8 +34,10 @@ Pieces::collect (const std::string &to_parse)
// auto pieces = std::vector<Piece> (piece_slice.base_ptr, // auto pieces = std::vector<Piece> (piece_slice.base_ptr,
// piece_slice.base_ptr + piece_slice.len); // piece_slice.base_ptr + piece_slice.len);
return Pieces{}; return Pieces (piece_slice);
} }
Pieces::~Pieces () { destroy_pieces (slice); }
} // namespace Fmt } // namespace Fmt
} // namespace Rust } // namespace Rust
...@@ -237,6 +237,7 @@ struct PieceSlice ...@@ -237,6 +237,7 @@ struct PieceSlice
{ {
const Piece *base_ptr; const Piece *base_ptr;
size_t len; size_t len;
size_t cap;
}; };
extern "C" { extern "C" {
...@@ -244,11 +245,19 @@ extern "C" { ...@@ -244,11 +245,19 @@ extern "C" {
PieceSlice PieceSlice
collect_pieces (const char *input); collect_pieces (const char *input);
void destroy_pieces (PieceSlice);
} // extern "C" } // extern "C"
struct Pieces struct Pieces
{ {
static Pieces collect (const std::string &to_parse); static Pieces collect (const std::string &to_parse);
~Pieces ();
private:
Pieces (PieceSlice slice) : slice (slice) {}
PieceSlice slice;
}; };
} // namespace Fmt } // namespace Fmt
......
...@@ -3,21 +3,17 @@ ...@@ -3,21 +3,17 @@
// what's the plan? Have a function return something that can be constructed into a vector? // what's the plan? Have a function return something that can be constructed into a vector?
// or an iterator? // or an iterator?
use std::ffi::CStr; use std::{ffi::CStr, mem};
trait IntoFFI { trait IntoFFI<T> {
type Output; fn into_ffi(self) -> T;
fn into_ffi(&self) -> Self::Output;
} }
impl<T> IntoFFI for Option<T> impl<T> IntoFFI<*const T> for Option<T>
where where
T: Sized, T: Sized,
{ {
type Output = *const T; fn into_ffi(self) -> *const T {
fn into_ffi(&self) -> Self::Output {
match self.as_ref() { match self.as_ref() {
None => std::ptr::null(), None => std::ptr::null(),
Some(r) => r as *const T, Some(r) => r as *const T,
...@@ -40,12 +36,6 @@ mod ffi { ...@@ -40,12 +36,6 @@ mod ffi {
pub end: usize, pub end: usize,
} }
// impl InnerSpan {
// pub fn new(start: usize, end: usize) -> InnerSpan {
// InnerSpan { start, end }
// }
// }
/// The location and before/after width of a character whose width has changed from its source code /// The location and before/after width of a character whose width has changed from its source code
/// representation /// representation
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
...@@ -59,35 +49,27 @@ mod ffi { ...@@ -59,35 +49,27 @@ mod ffi {
pub after: usize, pub after: usize,
} }
// impl InnerWidthMapping { // TODO: Not needed for now?
// pub fn new(position: usize, before: usize, after: usize) -> InnerWidthMapping { // /// Whether the input string is a literal. If yes, it contains the inner width mappings.
// InnerWidthMapping { // #[derive(Clone, PartialEq, Eq)]
// position, // #[repr(C)]
// before, // enum InputStringKind {
// after, // NotALiteral,
// } // Literal {
// } // width_mappings: Vec<InnerWidthMapping>,
// },
// } // }
/// Whether the input string is a literal. If yes, it contains the inner width mappings. // TODO: Not needed for now?
#[derive(Clone, PartialEq, Eq)] // /// The type of format string that we are parsing.
#[repr(C)] // #[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum InputStringKind { // #[repr(C)]
NotALiteral, // pub enum ParseMode {
Literal { // /// A normal format string as per `format_args!`.
width_mappings: Vec<InnerWidthMapping>, // Format,
}, // /// An inline assembly template string for `asm!`.
} // InlineAsm,
// }
/// The type of format string that we are parsing.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(C)]
pub enum ParseMode {
/// A normal format string as per `format_args!`.
Format,
/// An inline assembly template string for `asm!`.
InlineAsm,
}
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[repr(C)] #[repr(C)]
...@@ -102,7 +84,13 @@ mod ffi { ...@@ -102,7 +84,13 @@ mod ffi {
String(&'a str), String(&'a str),
/// This describes that formatting should process the next argument (as /// This describes that formatting should process the next argument (as
/// specified inside) for emission. /// specified inside) for emission.
NextArgument(Box<Argument<'a>>), NextArgument(*const Argument<'a>),
}
impl<'a> Drop for Piece<'a> {
fn drop(&mut self) {
println!("dropping Piece: {:?}", self)
}
} }
/// Representation of an argument specification. /// Representation of an argument specification.
...@@ -225,7 +213,10 @@ mod ffi { ...@@ -225,7 +213,10 @@ mod ffi {
// a memory leak... should we resend the info back to the Rust lib afterwards to free it? // a memory leak... should we resend the info back to the Rust lib afterwards to free it?
// this is definitely the best way - store that pointer in the FFI piece and rebuild the box // this is definitely the best way - store that pointer in the FFI piece and rebuild the box
// in a Rust destructor // in a Rust destructor
Piece::NextArgument(Box::new(Into::<Argument>::into(*x))) let ptr = Box::leak(x);
let dst = Into::<Argument>::into(*ptr);
Piece::NextArgument(&dst as *const Argument)
} }
} }
} }
...@@ -331,17 +322,18 @@ pub mod rust { ...@@ -331,17 +322,18 @@ pub mod rust {
use generic_format_parser::{ParseMode, Parser, Piece}; use generic_format_parser::{ParseMode, Parser, Piece};
pub fn collect_pieces(input: &str) -> Vec<Piece<'_>> { pub fn collect_pieces(input: &str) -> Vec<Piece<'_>> {
// let parser = Parser::new();
let parser = Parser::new(input, None, None, true, ParseMode::Format); let parser = Parser::new(input, None, None, true, ParseMode::Format);
parser.into_iter().collect() parser.into_iter().collect()
} }
} }
// TODO: Should we instead make an FFIVector struct?
#[repr(C)] #[repr(C)]
pub struct PieceSlice { pub struct PieceSlice {
base_ptr: *const ffi::Piece<'static /* FIXME: That's wrong */>, base_ptr: *mut ffi::Piece<'static /* FIXME: That's wrong */>,
len: usize, len: usize,
cap: usize,
} }
#[no_mangle] #[no_mangle]
...@@ -355,10 +347,16 @@ pub extern "C" fn collect_pieces(input: *const libc::c_char) -> PieceSlice { ...@@ -355,10 +347,16 @@ pub extern "C" fn collect_pieces(input: *const libc::c_char) -> PieceSlice {
.map(Into::into) .map(Into::into)
.collect(); .collect();
println!("debug: {:?}, {:?}", pieces.as_ptr(), pieces.len()); println!("[ARTHUR]: debug: {:?}, {:?}", pieces.as_ptr(), pieces.len());
PieceSlice { PieceSlice {
base_ptr: pieces.as_ptr(),
len: pieces.len(), len: pieces.len(),
cap: pieces.capacity(),
base_ptr: pieces.leak().as_mut_ptr(),
} }
} }
#[no_mangle]
pub extern "C" fn destroy_pieces(PieceSlice { base_ptr, len, cap }: PieceSlice) {
let _ = unsafe { Vec::from_raw_parts(base_ptr, len, cap) };
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment