aboutsummaryrefslogtreecommitdiff
path: root/libgrust
diff options
context:
space:
mode:
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>2023-05-10 11:34:45 +0200
committerArthur Cohen <arthur.cohen@embecosm.com>2024-01-16 18:37:19 +0100
commit5605333c907883486f821088a1ceb22d2bb24aa3 (patch)
treee0a810e7dc38c92682ca3421d865736d20148fcc /libgrust
parent842a8307ca36858529de75ab0532749f2140f900 (diff)
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.rs1
-rw-r--r--libgrust/libproc_macro/rust/bridge/ffistring.rs48
-rw-r--r--libgrust/libproc_macro/rust/bridge/literal.rs483
3 files changed, 216 insertions, 316 deletions
diff --git a/libgrust/libproc_macro/rust/bridge.rs b/libgrust/libproc_macro/rust/bridge.rs
index eb7f854bd2b..3900ae1884b 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 00000000000..0cdbf13851f
--- /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 740ed1fccac..945311af88e 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),
- }
- }
-}