diff options
author | Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> | 2023-05-10 11:34:45 +0200 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2024-01-16 18:37:19 +0100 |
commit | 5605333c907883486f821088a1ceb22d2bb24aa3 (patch) | |
tree | e0a810e7dc38c92682ca3421d865736d20148fcc /libgrust | |
parent | 842a8307ca36858529de75ab0532749f2140f900 (diff) | |
download | gcc-5605333c907883486f821088a1ceb22d2bb24aa3.zip gcc-5605333c907883486f821088a1ceb22d2bb24aa3.tar.gz gcc-5605333c907883486f821088a1ceb22d2bb24aa3.tar.bz2 |
gccrs: libproc_macro: Change rust literal internals
Rust interface literal internals were taking a type and storing that
type. This lead to multiple problems such as various conversion from
string to int/float/other type as well as dead end on undetermined types
(type checker runs at a later stage).
libgrust/ChangeLog:
* libproc_macro/rust/bridge.rs: Add ffistring module.
* libproc_macro/rust/bridge/literal.rs: Rework type
internals.
* libproc_macro/rust/bridge/ffistring.rs: New file.
Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Diffstat (limited to 'libgrust')
-rw-r--r-- | libgrust/libproc_macro/rust/bridge.rs | 1 | ||||
-rw-r--r-- | libgrust/libproc_macro/rust/bridge/ffistring.rs | 48 | ||||
-rw-r--r-- | libgrust/libproc_macro/rust/bridge/literal.rs | 483 |
3 files changed, 216 insertions, 316 deletions
diff --git a/libgrust/libproc_macro/rust/bridge.rs b/libgrust/libproc_macro/rust/bridge.rs index eb7f854..3900ae1 100644 --- a/libgrust/libproc_macro/rust/bridge.rs +++ b/libgrust/libproc_macro/rust/bridge.rs @@ -1,3 +1,4 @@ +pub mod ffistring; pub mod group; pub mod ident; pub mod literal; diff --git a/libgrust/libproc_macro/rust/bridge/ffistring.rs b/libgrust/libproc_macro/rust/bridge/ffistring.rs new file mode 100644 index 0000000..0cdbf13 --- /dev/null +++ b/libgrust/libproc_macro/rust/bridge/ffistring.rs @@ -0,0 +1,48 @@ +use std::convert::TryInto; +use std::ffi::c_uchar; +use std::fmt; +use std::slice::from_raw_parts; +use std::str::from_utf8; + +extern "C" { + fn FFIString__new(data: *const c_uchar, len: u64) -> FFIString; + fn FFIString__drop(string: *mut FFIString); +} + +#[repr(C)] +#[derive(Debug)] +pub struct FFIString { + data: *const c_uchar, + len: u64, +} + +impl FFIString { + pub fn new(string: &str) -> FFIString { + unsafe { FFIString__new(string.as_ptr(), string.len() as u64) } + } +} + +impl Clone for FFIString { + fn clone(&self) -> Self { + FFIString::new(&self.to_string()) + } +} + +impl Drop for FFIString { + fn drop(&mut self) { + unsafe { + FFIString__drop(self as *mut FFIString); + } + } +} + +impl fmt::Display for FFIString { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str( + from_utf8(unsafe { + from_raw_parts(self.data, self.len.try_into().map_err(|_| fmt::Error)?) + }) + .map_err(|_| fmt::Error)?, + ) + } +} diff --git a/libgrust/libproc_macro/rust/bridge/literal.rs b/libgrust/libproc_macro/rust/bridge/literal.rs index 740ed1f..945311a 100644 --- a/libgrust/libproc_macro/rust/bridge/literal.rs +++ b/libgrust/libproc_macro/rust/bridge/literal.rs @@ -1,220 +1,166 @@ -use bridge::span::Span; -use std::convert::{TryFrom, TryInto}; +use bridge::{ffistring::FFIString, span::Span}; +use std::convert::TryInto; use std::ffi::c_uchar; use std::fmt; use std::str::FromStr; use LexError; extern "C" { - fn Literal__drop(literal: *mut Literal); - fn Literal__string(str: *const c_uchar, len: u64) -> Literal; - fn Literal__byte_string(bytes: *const u8, len: u64) -> Literal; fn Literal__from_string(str: *const c_uchar, len: u64, lit: *mut Literal) -> bool; } #[repr(C)] #[derive(Debug, Clone, Copy)] -pub enum Unsigned { - Unsigned8(u8), - Unsigned16(u16), - Unsigned32(u32), - Unsigned64(u64), - // u128 is not ffi safe, hence this representation - // https://github.com/rust-lang/rust/issues/54341 - Unsigned128(u64, u64), +pub enum LitKind { + Byte, + Char, + Integer, + Float, + Str, + StrRaw(u8), + ByteStr, + ByteStrRaw(u8), + Err, } #[repr(C)] -#[derive(Debug, Clone, Copy)] -pub enum Signed { - Signed8(i8), - Signed16(i16), - Signed32(i32), - Signed64(i64), - // i128 is not ffi safe, hence this representation - // https://github.com/rust-lang/rust/issues/54341 - Signed128(u64, u64), +#[derive(Debug, Clone)] +pub struct Literal { + kind: LitKind, + text: FFIString, + has_suffix: bool, + suffix: FFIString, + // FIXME: Add span, cannot add whilst Span remain an empty type } -#[repr(C)] -#[derive(Debug)] -pub enum Literal { - /// String literal internal representation - /// - /// # Note - /// This variant is constructed through FFI - #[allow(dead_code)] - String { - data: *const c_uchar, - len: u64, - }, - /// Bytestring literal internal representation - /// - /// # Note - /// This variant is constructed through FFI - #[allow(dead_code)] - ByteString { - data: *const u8, - size: u64, - }, - Char(u32), - Unsigned(Unsigned, bool), - Signed(Signed, bool), - Usize(u64, bool), - ISize(i64, bool), - Float32(f32, bool), - Float64(f64, bool), +macro_rules! suffixed_int_literals { + ($($name: ident => $kind: ident,)*) => ($( + pub fn $name(n : $kind) -> Literal { + Literal { + kind : LitKind::Integer, + text: FFIString::new(&n.to_string()), + has_suffix : true, + suffix: FFIString::new(stringify!($kind)) + } + } + )*) } -impl Literal { - pub fn u8_suffixed(n: u8) -> Self { - Literal::Unsigned(Unsigned::Unsigned8(n), true) - } - - pub fn u16_suffixed(n: u16) -> Self { - Literal::Unsigned(Unsigned::Unsigned16(n), true) - } - - pub fn u32_suffixed(n: u32) -> Self { - Literal::Unsigned(Unsigned::Unsigned32(n), true) - } - - pub fn u64_suffixed(n: u64) -> Self { - Literal::Unsigned(Unsigned::Unsigned64(n), true) - } - - pub fn u128_suffixed(n: u128) -> Self { - Literal::Unsigned( - Unsigned::Unsigned128( - (n >> 64).try_into().unwrap(), - (n & 0xFFFFFFFFFFFFFFFF).try_into().unwrap(), - ), - true, - ) - } - - pub fn usize_suffixed(n: usize) -> Self { - Literal::Usize(n.try_into().expect("Cannot convert usize to u64"), true) - } - - pub fn i8_suffixed(n: i8) -> Self { - Literal::Signed(Signed::Signed8(n), true) - } - - pub fn i16_suffixed(n: i16) -> Self { - Literal::Signed(Signed::Signed16(n), true) - } - - pub fn i32_suffixed(n: i32) -> Self { - Literal::Signed(Signed::Signed32(n), true) - } - - pub fn i64_suffixed(n: i64) -> Self { - Literal::Signed(Signed::Signed64(n), true) - } - - pub fn i128_suffixed(n: i128) -> Self { - Literal::Signed( - Signed::Signed128( - (n >> 64).try_into().unwrap(), - (n & 0xFFFFFFFFFFFFFFFF).try_into().unwrap(), - ), - true, - ) - } - - pub fn isize_suffixed(n: isize) -> Self { - Literal::ISize(n.try_into().expect("Cannot convert isize to i64"), true) - } - - // Unsuffixed - - pub fn u8_unsuffixed(n: u8) -> Self { - Literal::Unsigned(Unsigned::Unsigned8(n), false) - } - - pub fn u16_unsuffixed(n: u16) -> Self { - Literal::Unsigned(Unsigned::Unsigned16(n), false) - } - - pub fn u32_unsuffixed(n: u32) -> Self { - Literal::Unsigned(Unsigned::Unsigned32(n), false) - } - - pub fn u64_unsuffixed(n: u64) -> Self { - Literal::Unsigned(Unsigned::Unsigned64(n), false) - } - - pub fn u128_unsuffixed(n: u128) -> Self { - Literal::Unsigned( - Unsigned::Unsigned128( - (n >> 64).try_into().unwrap(), - (n & 0xFFFFFFFFFFFFFFFF).try_into().unwrap(), - ), - false, - ) - } - - pub fn usize_unsuffixed(n: usize) -> Self { - Literal::Usize(n.try_into().expect("Cannot convert usize to u64"), false) - } - - pub fn i8_unsuffixed(n: i8) -> Self { - Literal::Signed(Signed::Signed8(n), false) - } - - pub fn i16_unsuffixed(n: i16) -> Self { - Literal::Signed(Signed::Signed16(n), false) - } - - pub fn i32_unsuffixed(n: i32) -> Self { - Literal::Signed(Signed::Signed32(n), false) - } - - pub fn i64_unsuffixed(n: i64) -> Self { - Literal::Signed(Signed::Signed64(n), false) - } - - pub fn i128_unsuffixed(n: i128) -> Self { - Literal::Signed( - Signed::Signed128( - (n >> 64).try_into().unwrap(), - (n & 0xFFFFFFFFFFFFFFFF).try_into().unwrap(), - ), - false, - ) - } +macro_rules! unsuffixed_int_literals { + ($($name: ident => $kind: ident,)*) => ($( + pub fn $name(n : $kind) -> Literal { + Literal { + kind : LitKind::Integer, + text: FFIString::new(&n.to_string()), + has_suffix : false, + suffix: FFIString::new("") + } + } + )*) +} - pub fn isize_unsuffixed(n: isize) -> Self { - Literal::ISize(n.try_into().expect("Cannot convert isize to i64"), false) +impl Literal { + suffixed_int_literals! { + u8_suffixed => u8, + u16_suffixed => u16, + u32_suffixed => u32, + u64_suffixed => u64, + u128_suffixed => u128, + usize_suffixed => usize, + i8_suffixed => i8, + i16_suffixed => i16, + i32_suffixed => i32, + i64_suffixed => i64, + i128_suffixed => i128, + isize_suffixed => isize, + } + + unsuffixed_int_literals! { + u8_unsuffixed => u8, + u16_unsuffixed => u16, + u32_unsuffixed => u32, + u64_unsuffixed => u64, + u128_unsuffixed => u128, + usize_unsuffixed => usize, + i8_unsuffixed => i8, + i16_unsuffixed => i16, + i32_unsuffixed => i32, + i64_unsuffixed => i64, + i128_unsuffixed => i128, + isize_unsuffixed => isize, } pub fn f32_unsuffixed(n: f32) -> Self { - Literal::Float32(n, false) + let mut repr = n.to_string(); + if !repr.contains('.') { + repr.push_str(".0"); + } + + Literal { + kind: LitKind::Float, + text: FFIString::new(&repr), + has_suffix: false, + suffix: FFIString::new(""), + } } pub fn f32_suffixed(n: f32) -> Self { - Literal::Float32(n, true) + Literal { + kind: LitKind::Float, + text: FFIString::new(&n.to_string()), + has_suffix: true, + suffix: FFIString::new("f32"), + } } pub fn f64_unsuffixed(n: f64) -> Self { - Literal::Float64(n, false) + let mut repr = n.to_string(); + if !repr.contains('.') { + repr.push_str(".0"); + } + + Literal { + kind: LitKind::Float, + text: FFIString::new(&repr), + has_suffix: false, + suffix: FFIString::new(""), + } } pub fn f64_suffixed(n: f64) -> Self { - Literal::Float64(n, true) + Literal { + kind: LitKind::Float, + text: FFIString::new(&n.to_string()), + has_suffix: true, + suffix: FFIString::new("f64"), + } } pub fn string(string: &str) -> Self { - unsafe { Literal__string(string.as_ptr(), string.len().try_into().unwrap()) } + Literal { + kind: LitKind::Str, + text: FFIString::new(string), + has_suffix: false, + suffix: FFIString::new(""), + } } pub fn character(c: char) -> Self { - Literal::Char(c.into()) + Literal { + kind: LitKind::Char, + text: FFIString::new(&c.to_string()), + has_suffix: false, + suffix: FFIString::new(""), + } } pub fn byte_string(bytes: &[u8]) -> Self { - unsafe { Literal__byte_string(bytes.as_ptr(), bytes.len().try_into().unwrap()) } + Literal { + kind: LitKind::ByteStr, + text: FFIString::new(&bytes.escape_ascii().to_string()), + has_suffix: false, + suffix: FFIString::new(""), + } } pub fn span(&self) -> Span { @@ -226,138 +172,53 @@ impl Literal { } } -impl Drop for Literal { - fn drop(&mut self) { - match self { - Literal::String { .. } | Literal::ByteString { .. } => unsafe { - Literal__drop(self as *mut Literal) - }, - _ => (), - } - } -} - impl fmt::Display for Literal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Literal::String { data, len } => { - let slice = - unsafe { std::slice::from_raw_parts(*data, (*len).try_into().unwrap()) }; - f.write_str("\"")?; - f.write_str(std::str::from_utf8(slice).unwrap())?; - f.write_str("\"")?; + let text = &self.text.to_string(); + match self.kind { + LitKind::Byte => { + f.write_str("b'")?; + f.write_str(text)?; + f.write_str("'")?; } - Literal::ByteString { data, size } => { - f.write_str("b\"")?; - let slice = - unsafe { std::slice::from_raw_parts(*data, (*size).try_into().unwrap()) }; - for &byte in slice { - if byte != b'"' && (b' '..=b'z').contains(&byte) { - char::try_from(byte).unwrap().fmt(f)?; - } else { - write!(f, "\\x{:02x}", byte)?; - } - } - f.write_str("b\"")?; + LitKind::Char => { + f.write_str("'")?; + f.write_str(text)?; + f.write_str("'")?; } - Literal::Char(val) => { - let ch: char = (*val).try_into().unwrap(); - match ch { - '\'' => f.write_str("'\\''")?, - '\0' => f.write_str("'\\0'")?, - '\n' => f.write_str("'\\n'")?, - ' '..='z' => write!(f, "'{}'", ch)?, - _ => write!(f, "'\\u{:x}'", val)?, - } - } - Literal::Unsigned(val, suffixed) => match val { - Unsigned::Unsigned8(val) => { - val.fmt(f)?; - if *suffixed { - f.write_str("u8")?; - } - } - Unsigned::Unsigned16(val) => { - val.fmt(f)?; - if *suffixed { - f.write_str("u16")?; - } - } - Unsigned::Unsigned32(val) => { - val.fmt(f)?; - if *suffixed { - f.write_str("u32")?; - } - } - Unsigned::Unsigned64(val) => { - val.fmt(f)?; - if *suffixed { - f.write_str("u64")?; - } - } - Unsigned::Unsigned128(h, l) => { - ((u128::from(*h) << 64) & u128::from(*l)).fmt(f)?; - if *suffixed { - f.write_str("u128")?; - } - } - }, - Literal::Signed(val, suffixed) => match val { - Signed::Signed8(val) => { - val.fmt(f)?; - if *suffixed { - f.write_str("i8")?; - } - } - Signed::Signed16(val) => { - val.fmt(f)?; - if *suffixed { - f.write_str("i16")?; - } - } - Signed::Signed32(val) => { - val.fmt(f)?; - if *suffixed { - f.write_str("i32")?; - } - } - Signed::Signed64(val) => { - val.fmt(f)?; - if *suffixed { - f.write_str("i64")?; - } - } - Signed::Signed128(h, l) => { - ((i128::from(*h) << 64) & i128::from(*l)).fmt(f)?; - if *suffixed { - f.write_str("i128")?; - } - } - }, - Literal::Usize(val, suffixed) => { - val.fmt(f)?; - if *suffixed { - f.write_str("usize")?; - } + LitKind::Str => { + f.write_str("\"")?; + f.write_str(text)?; + f.write_str("\"")?; } - Literal::ISize(val, suffixed) => { - val.fmt(f)?; - if *suffixed { - f.write_str("isize")?; + LitKind::StrRaw(n) => { + f.write_str("r")?; + for _ in 0..n { + f.write_str("#")?; } + f.write_str("\"")?; + f.write_str(text)?; + f.write_str("\"")?; } - Literal::Float32(val, suffixed) => { - val.fmt(f)?; - if *suffixed { - f.write_str("f32")?; - } + LitKind::ByteStr => { + f.write_str("b\"")?; + f.write_str(text)?; + f.write_str("\"")?; } - Literal::Float64(val, suffixed) => { - val.fmt(f)?; - if *suffixed { - f.write_str("f64")?; + LitKind::ByteStrRaw(n) => { + f.write_str("br")?; + for _ in 0..n { + f.write_str("#")?; } + f.write_str("\"")?; + f.write_str(text)?; + f.write_str("\"")?; } + _ => f.write_str(text)?, + } + + if self.has_suffix { + f.write_str(&self.suffix.to_string())?; } Ok(()) } @@ -367,7 +228,13 @@ impl FromStr for Literal { type Err = LexError; fn from_str(string: &str) -> Result<Self, LexError> { - let mut lit = Literal::Char(0); + // Structure that will be filled in by the cpp + let mut lit = Literal { + kind: LitKind::Err, + text: FFIString::new(""), + has_suffix: false, + suffix: FFIString::new(""), + }; // TODO: We might want to pass a LexError by reference to retrieve // error information if unsafe { @@ -383,19 +250,3 @@ impl FromStr for Literal { } } } - -impl Clone for Literal { - fn clone(&self) -> Self { - match self { - Literal::String { data, len } => unsafe { Literal__string(*data, *len) }, - Literal::ByteString { data, size } => unsafe { Literal__byte_string(*data, *size) }, - Literal::Char(val) => Literal::Char(*val), - Literal::Unsigned(val, suffixed) => Literal::Unsigned(*val, *suffixed), - Literal::Signed(val, suffixed) => Literal::Signed(*val, *suffixed), - Literal::Usize(val, suffixed) => Literal::Usize(*val, *suffixed), - Literal::ISize(val, suffixed) => Literal::ISize(*val, *suffixed), - Literal::Float32(val, suffixed) => Literal::Float32(*val, *suffixed), - Literal::Float64(val, suffixed) => Literal::Float64(*val, *suffixed), - } - } -} |