]> gcc.gnu.org Git - gcc.git/commitdiff
gccrs: libproc_macro: Change rust literal internals
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Wed, 10 May 2023 09:34:45 +0000 (11:34 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:37:19 +0000 (18:37 +0100)
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>
libgrust/libproc_macro/rust/bridge.rs
libgrust/libproc_macro/rust/bridge/ffistring.rs [new file with mode: 0644]
libgrust/libproc_macro/rust/bridge/literal.rs

index eb7f854bd2bff9ef8faaed3e3234c01c08214fb0..3900ae1884b5dbd1a7afe68c921b0ab438cc7f18 100644 (file)
@@ -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 (file)
index 0000000..0cdbf13
--- /dev/null
@@ -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)?,
+        )
+    }
+}
index 740ed1fccac7dd9e9402c113f480e7a3b1bfb7e5..945311af88e515b586d5cd1ddc863d65a6d64529 100644 (file)
-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),
-        }
-    }
-}
This page took 0.0796249999999999 seconds and 5 git commands to generate.