[gcc r14-7601] gccrs: libproc_macro: Change cpp literal representation

Arthur Cohen cohenarthur@gcc.gnu.org
Tue Jan 16 17:44:12 GMT 2024


https://gcc.gnu.org/g:10c9b9f0ccc340e53e1dfd3e8ca9125f280d8e66

commit r14-7601-g10c9b9f0ccc340e53e1dfd3e8ca9125f280d8e66
Author: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Date:   Wed May 10 15:17:46 2023 +0200

    gccrs: libproc_macro: Change cpp literal representation
    
    Change the literal representation on cpp side to match the new one in
    rust. This means FFIString had to be implemented on cpp side. A few
    helper functions has also been introduced.
    
    libgrust/ChangeLog:
    
            * libproc_macro/Makefile.am: Add ffistring unit to
            compiled objects list.
            * libproc_macro/Makefile.in: Regenerate.
            * libproc_macro/literal.cc (Literal::drop): Change with
            a call to ffistring drop function.
            (Literal::make_literal): Add new helper constructor
            (Literal__drop): Remove this function.
            (Literal__string): Likewise.
            (Literal__byte_string): Likewise.
            (Literal__from_string): Moved this function.
            (Literal::make_unsigned): Changed the constructor to match the
            new layout.
            (Literal::make_signed): Likewise.
            (Literal::clone): Reimplement th eclone function.
            (Literal::make_u8): Changed the constructor, make suffixed by
            default.
            (Literal::make_u16): Likewise.
            (Literal::make_u32): Likewise.
            (Literal::make_u64): Likewise.
            (Literal::make_i8): Likewise.
            (Literal::make_i16): Likewise.
            (Literal::make_i32): Likewise.
            (Literal::make_i64): Likewise.
            (Literal::make_string): Likewise.
            (Literal::make_byte_string): Likewise.
            (Literal::make_f32): Likewise.
            (Literal::make_f64): Likewise.
            (Literal::make_char): Likewise.
            (Literal::make_usize): Likewise.
            (Literal::make_isize): Likewise.
            (LitKind::make_byte): Add new helper constructor to avoid having
            to set the payload value.
            (LitKind::make_char): Likewise.
            (LitKind::make_integer): Likewise.
            (LitKind::make_float): Likewise.
            (LitKind::make_str): Likewise.
            (LitKind::make_str_raw): Add a new helper constructor which
            takes the payload value as an argument.
            (LitKind::make_byte_str): Add new helper constructor to avoid
            mistakes with payload value.
            (LitKind::make_byte_str_raw): Add a new helper constructor which
            takes the payload value as an argument.
            * libproc_macro/literal.h: Add new functions prototype.
            (enum UnsignedTag): Removed because it is now unused.
            (struct Payload128): Likewise.
            (union UnsignedPayload): Likewise.
            (struct Unsigned): Likewise.
            (enum SignedTag): Likewise.
            (union SignedPayload): Likewise.
            (struct Signed): Likewise.
            (enum LiteralTag): Likewise.
            (enum LitKindTag): Likewise.
            (struct StringPayload): Likewise.
            (struct ByteStringPayload): Likewise.
            (union LitKindPayload): Likewise.
            (struct UnsignedSuffixPayload): Likewise.
            (struct LitKind): Add new literal kind struct representation to
            match the enum on rust side.
            (struct SignedSuffixPayload): Removed because now unused.
            (struct UsizePayload): Likewise.
            (struct IsizePayload): Likewise.
            (struct Float32Payload): Likewise.
            (struct Float64Payload): Likewise.
            (union LiteralPayload): Likewise.
            (struct Literal): Changed the internals of the structure.
            (Literal__drop): Removed the drop function fom the c interface.
            (Literal__string): Removed unused function.
            (Literal__byte_string): Removed unused function.
            * libproc_macro/ffistring.cc: New file.
            * libproc_macro/ffistring.h: New file.
    
    gcc/rust/ChangeLog:
    
            * lex/rust-token.h: Implement hash for token id enumeration.
            * util/rust-token-converter.cc (dispatch_float_literals): Update
            to new internals.
            (dispatch_integer_literals): Likewise.
            (convert): Likewise.
            (string_literal): Remove function.
            (byte_string_literal): Likewise.
            (unsigned_literal): Likewise.
            (signed_literal): Likewise.
            (from_literal): Update with new internals.
    
    Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Diff:
---
 gcc/rust/lex/rust-token.h             |  12 ++
 gcc/rust/util/rust-token-converter.cc | 268 ++++++++------------------------
 libgrust/libproc_macro/Makefile.am    |   9 +-
 libgrust/libproc_macro/Makefile.in    |   9 +-
 libgrust/libproc_macro/ffistring.cc   |  62 ++++++++
 libgrust/libproc_macro/ffistring.h    |  55 +++++++
 libgrust/libproc_macro/literal.cc     | 282 ++++++++++++++--------------------
 libgrust/libproc_macro/literal.h      | 185 +++++-----------------
 8 files changed, 368 insertions(+), 514 deletions(-)

diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index c7ec753a123..716b3ce3686 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -456,4 +456,16 @@ return *str;
 };
 } // namespace Rust
 
+namespace std {
+template <> struct hash<Rust::PrimitiveCoreType>
+{
+  size_t operator() (const Rust::PrimitiveCoreType &coretype) const noexcept
+  {
+    return hash<std::underlying_type<Rust::PrimitiveCoreType>::type> () (
+      static_cast<std::underlying_type<Rust::PrimitiveCoreType>::type> (
+	coretype));
+  }
+};
+} // namespace std
+
 #endif
diff --git a/gcc/rust/util/rust-token-converter.cc b/gcc/rust/util/rust-token-converter.cc
index 2047ea72967..d56493f5411 100644
--- a/gcc/rust/util/rust-token-converter.cc
+++ b/gcc/rust/util/rust-token-converter.cc
@@ -17,9 +17,28 @@
 #include "rust-lex.h"
 #include "rust-token-converter.h"
 #include "libproc_macro/proc_macro.h"
+#include "bi-map.h"
+
+#include <string>
 
 namespace Rust {
 
+static const BiMap<PrimitiveCoreType, std::string> suffixes
+  = {{{CORETYPE_F32, "f32"},
+      {CORETYPE_F64, "f64"},
+      {CORETYPE_U8, "u8"},
+      {CORETYPE_U16, "u16"},
+      {CORETYPE_U32, "u32"},
+      {CORETYPE_U64, "u64"},
+      {CORETYPE_U128, "u128"},
+      {CORETYPE_I8, "i8"},
+      {CORETYPE_I16, "i16"},
+      {CORETYPE_I32, "i32"},
+      {CORETYPE_I64, "i64"},
+      {CORETYPE_I128, "i128"},
+      {CORETYPE_ISIZE, "isize"},
+      {CORETYPE_USIZE, "usize"}}};
+
 static void
 pop_group (std::vector<ProcMacro::TokenStream> &streams,
 	   ProcMacro::Delimiter delim)
@@ -35,93 +54,24 @@ static void
 dispatch_float_literals (ProcMacro::TokenStream &ts,
 			 const const_TokenPtr &token)
 {
-  std::string::size_type sz;
   auto str = token->as_string ();
-  switch (token->get_type_hint ())
-    {
-      case CORETYPE_F32: {
-	auto value = std::stof (str, &sz);
-	ts.push (ProcMacro::TokenTree::make_tokentree (
-	  ProcMacro::Literal::make_f32 (value, sz != str.length ())));
-      }
-      break;
-      case CORETYPE_F64: {
-	auto value = std::stod (str, &sz);
-	ts.push (ProcMacro::TokenTree::make_tokentree (
-	  ProcMacro::Literal::make_f64 (value, sz != str.length ())));
-      }
-      break;
-    default:
-      gcc_unreachable ();
-    }
+  auto kind = ProcMacro::LitKind::make_float ();
+  auto lookup = suffixes.lookup (token->get_type_hint ());
+  auto suffix = suffixes.is_iter_ok (lookup) ? lookup->second : "";
+  ts.push (ProcMacro::TokenTree::make_tokentree (
+    ProcMacro::Literal::make_literal (kind, str, suffix)));
 }
 
 static void
 dispatch_integer_literals (ProcMacro::TokenStream &ts,
 			   const const_TokenPtr &token)
 {
-  std::string::size_type sz;
   auto str = token->as_string ();
-  unsigned long long uvalue;
-  long long svalue;
-
-  switch (token->get_type_hint ())
-    {
-    case CORETYPE_U8:
-      uvalue = std::stoull (str, &sz);
-      ts.push (ProcMacro::TokenTree::make_tokentree (
-	ProcMacro::Literal::make_u8 (uvalue, sz != str.length ())));
-      break;
-    case CORETYPE_U16:
-      uvalue = std::stoull (str, &sz);
-      ts.push (ProcMacro::TokenTree::make_tokentree (
-	ProcMacro::Literal::make_u16 (uvalue, sz != str.length ())));
-      break;
-    case CORETYPE_U32:
-      uvalue = std::stoull (str, &sz);
-      ts.push (ProcMacro::TokenTree::make_tokentree (
-	ProcMacro::Literal::make_u32 (uvalue, sz != str.length ())));
-      break;
-    case CORETYPE_U64:
-      uvalue = std::stoull (str, &sz);
-      ts.push (ProcMacro::TokenTree::make_tokentree (
-	ProcMacro::Literal::make_u32 (uvalue, sz != str.length ())));
-      break;
-    case CORETYPE_I8:
-      svalue = std::stoll (str, &sz);
-      ts.push (ProcMacro::TokenTree::make_tokentree (
-	ProcMacro::Literal::make_i8 (svalue, sz != str.length ())));
-      break;
-    case CORETYPE_I16:
-      svalue = std::stoll (str, &sz);
-      ts.push (ProcMacro::TokenTree::make_tokentree (
-	ProcMacro::Literal::make_i16 (svalue, sz != str.length ())));
-      break;
-    case CORETYPE_I32:
-      svalue = std::stoll (str, &sz);
-      ts.push (ProcMacro::TokenTree::make_tokentree (
-	ProcMacro::Literal::make_i32 (svalue, sz != str.length ())));
-      break;
-    case CORETYPE_I64:
-      svalue = std::stoll (str, &sz);
-      ts.push (ProcMacro::TokenTree::make_tokentree (
-	ProcMacro::Literal::make_i32 (svalue, sz != str.length ())));
-      break;
-    case CORETYPE_INT:
-      svalue = std::stoll (str, &sz);
-      ts.push (ProcMacro::TokenTree::make_tokentree (
-	ProcMacro::Literal::make_isize (svalue, sz != str.length ())));
-      break;
-    case CORETYPE_UINT:
-      uvalue = std::stoull (str, &sz);
-      ts.push (ProcMacro::TokenTree::make_tokentree (
-	ProcMacro::Literal::make_usize (uvalue, sz != str.length ())));
-      break;
-    case CORETYPE_UNKNOWN:
-    default:
-      gcc_unreachable ();
-      break;
-    }
+  auto kind = ProcMacro::LitKind::make_integer ();
+  auto lookup = suffixes.lookup (token->get_type_hint ());
+  auto suffix = suffixes.is_iter_ok (lookup) ? lookup->second : "";
+  ts.push (ProcMacro::TokenTree::make_tokentree (
+    ProcMacro::Literal::make_literal (kind, str, suffix)));
 }
 
 ProcMacro::TokenStream
@@ -140,21 +90,25 @@ convert (const std::vector<const_TokenPtr> &tokens)
 	case INT_LITERAL:
 	  dispatch_integer_literals (trees.back (), token);
 	  break;
-	// FIXME: Why does BYTE_CHAR_LITERAL is not handled by rustc ?
-	case CHAR_LITERAL: // TODO: UTF-8 handling
+	case CHAR_LITERAL:
 	  trees.back ().push (ProcMacro::TokenTree::make_tokentree (
-	    ProcMacro::Literal::make_char (token->as_string ()[0])));
+	    ProcMacro::Literal::make_literal (ProcMacro::LitKind::make_char (),
+					      token->as_string ())));
 	  break;
 	case STRING_LITERAL:
 	  trees.back ().push (ProcMacro::TokenTree::make_tokentree (
-	    ProcMacro::Literal::make_string (token->as_string ())));
+	    ProcMacro::Literal::make_literal (ProcMacro::LitKind::make_str (),
+					      token->as_string ())));
 	  break;
-	  case BYTE_STRING_LITERAL: {
-	    auto str = token->as_string ();
-	    std::vector<uint8_t> data (str.begin (), str.end ());
-	    trees.back ().push (ProcMacro::TokenTree::make_tokentree (
-	      ProcMacro::Literal::make_byte_string (data)));
-	  }
+	case BYTE_CHAR_LITERAL:
+	  trees.back ().push (ProcMacro::TokenTree::make_tokentree (
+	    ProcMacro::Literal::make_literal (ProcMacro::LitKind::make_byte (),
+					      token->as_string ())));
+	  break;
+	case BYTE_STRING_LITERAL:
+	  trees.back ().push (ProcMacro::TokenTree::make_tokentree (
+	    ProcMacro::Literal::make_literal (
+	      ProcMacro::LitKind::make_byte_str (), token->as_string ())));
 	  break;
 	// Ident
 	case IDENTIFIER:
@@ -321,91 +275,6 @@ from_ident (const ProcMacro::Ident &ident, std::vector<const_TokenPtr> &result)
   result.push_back (lexer.peek_token ());
 }
 
-static void
-string_literal (const ProcMacro::StringPayload &payload,
-		std::vector<const_TokenPtr> &result)
-{
-  // TODO: UTF-8 string
-  result.push_back (Token::make_string (
-    Location (),
-    std::string (reinterpret_cast<const char *> (payload.data), payload.len)));
-}
-
-static void
-byte_string_literal (const ProcMacro::ByteStringPayload &payload,
-		     std::vector<const_TokenPtr> &result)
-{
-  result.push_back (Token::make_byte_string (
-    Location (),
-    std::string (reinterpret_cast<const char *> (payload.data), payload.size)));
-}
-
-static void
-unsigned_literal (const ProcMacro::Unsigned &lit,
-		  std::vector<const_TokenPtr> &result)
-{
-  switch (lit.tag)
-    {
-    case ProcMacro::UNSIGNED_8:
-      result.push_back (Token::make_int (Location (),
-					 std::to_string (lit.payload.unsigned8),
-					 CORETYPE_U8));
-      break;
-    case ProcMacro::UNSIGNED_16:
-      result.push_back (
-	Token::make_int (Location (), std::to_string (lit.payload.unsigned16),
-			 CORETYPE_U16));
-      break;
-    case ProcMacro::UNSIGNED_32:
-      result.push_back (
-	Token::make_int (Location (), std::to_string (lit.payload.unsigned32),
-			 CORETYPE_U32));
-      break;
-    case ProcMacro::UNSIGNED_64:
-      result.push_back (
-	Token::make_int (Location (), std::to_string (lit.payload.unsigned64),
-			 CORETYPE_U64));
-      break;
-    case ProcMacro::UNSIGNED_128:
-      // TODO: Handle 128 bits
-    default:
-      gcc_unreachable ();
-    }
-}
-
-static void
-signed_literal (const ProcMacro::Signed &lit,
-		std::vector<const_TokenPtr> &result)
-{
-  switch (lit.tag)
-    {
-    case ProcMacro::SIGNED_8:
-      result.push_back (Token::make_int (Location (),
-					 std::to_string (lit.payload.signed8),
-					 CORETYPE_I8));
-      break;
-    case ProcMacro::SIGNED_16:
-      result.push_back (Token::make_int (Location (),
-					 std::to_string (lit.payload.signed16),
-					 CORETYPE_I16));
-      break;
-    case ProcMacro::SIGNED_32:
-      result.push_back (Token::make_int (Location (),
-					 std::to_string (lit.payload.signed32),
-					 CORETYPE_I32));
-      break;
-    case ProcMacro::SIGNED_64:
-      result.push_back (Token::make_int (Location (),
-					 std::to_string (lit.payload.signed64),
-					 CORETYPE_I64));
-      break;
-    case ProcMacro::SIGNED_128:
-      // TODO: Handle 128 bits
-    default:
-      gcc_unreachable ();
-    }
-}
-
 /**
  * Append the token corresponding to a given Literal to a vector.
  *
@@ -416,46 +285,39 @@ static void
 from_literal (const ProcMacro::Literal &literal,
 	      std::vector<const_TokenPtr> &result)
 {
-  switch (literal.tag)
+  auto lookup = suffixes.lookup (literal.suffix.to_string ());
+  auto suffix
+    = suffixes.is_iter_ok (lookup) ? lookup->second : CORETYPE_UNKNOWN;
+  // FIXME: Add spans instead of empty locations
+  switch (literal.kind.tag)
     {
-    case ProcMacro::STRING:
-      string_literal (literal.payload.string_payload, result);
-      break;
-    case ProcMacro::BYTE_STRING:
-      byte_string_literal (literal.payload.byte_string_payload, result);
+    case ProcMacro::BYTE:
+      result.push_back (
+	Token::make_byte_char (Location (), literal.text.to_string ()[0]));
       break;
     case ProcMacro::CHAR:
       result.push_back (
-	Token::make_char (Location (), literal.payload.char_payload));
+	Token::make_char (Location (), literal.text.to_string ()[0]));
       break;
-    case ProcMacro::UNSIGNED:
-      unsigned_literal (literal.payload.unsigned_payload.value, result);
-      break;
-    case ProcMacro::SIGNED:
-      signed_literal (literal.payload.signed_payload.value, result);
-      break;
-    case ProcMacro::USIZE:
+    case ProcMacro::INTEGER:
       result.push_back (
-	Token::make_int (Location (),
-			 std::to_string (literal.payload.usize_payload.value),
-			 CORETYPE_USIZE));
+	Token::make_int (Location (), literal.text.to_string (), suffix));
       break;
-    case ProcMacro::ISIZE:
+    case ProcMacro::FLOAT:
       result.push_back (
-	Token::make_int (Location (),
-			 std::to_string (literal.payload.isize_payload.value),
-			 CORETYPE_ISIZE));
+	Token::make_float (Location (), literal.text.to_string (), suffix));
       break;
-    case ProcMacro::FLOAT32:
-      result.push_back (Token::make_float (
-	Location (), std::to_string (literal.payload.float32_payload.value),
-	CORETYPE_F32));
+    case ProcMacro::STR:
+      result.push_back (
+	Token::make_string (Location (), literal.text.to_string ()));
       break;
-    case ProcMacro::FLOAT64:
-      result.push_back (Token::make_float (
-	Location (), std::to_string (literal.payload.float64_payload.value),
-	CORETYPE_F64));
+    case ProcMacro::BYTE_STR:
+      result.push_back (
+	Token::make_byte_string (Location (), literal.text.to_string ()));
       break;
+    // FIXME: Handle raw string
+    case ProcMacro::STR_RAW:
+    case ProcMacro::BYTE_STR_RAW:
     default:
       gcc_unreachable ();
     }
diff --git a/libgrust/libproc_macro/Makefile.am b/libgrust/libproc_macro/Makefile.am
index 0fe22114248..493508cd9ee 100644
--- a/libgrust/libproc_macro/Makefile.am
+++ b/libgrust/libproc_macro/Makefile.am
@@ -52,7 +52,14 @@ LIBOBJS = @LIBOBJS@
 objext = @OBJEXT@
 
 REQUIRED_OFILES =							\
-	./proc_macro.$(objext) ./literal.$(objext) ./group.$(objext) ./ident.$(objext) ./punct.$(objext) ./tokenstream.$(objext) ./tokentree.$(objext)
+	./proc_macro.$(objext) \
+	./literal.$(objext) \
+	./group.$(objext) \
+	./ident.$(objext) \
+	./punct.$(objext) \
+	./tokenstream.$(objext) \
+	./tokentree.$(objext) \
+	./ffistring.$(objext)
 
 all: $(TARGETLIB)
 
diff --git a/libgrust/libproc_macro/Makefile.in b/libgrust/libproc_macro/Makefile.in
index 6eb5365d1ac..36031effcab 100644
--- a/libgrust/libproc_macro/Makefile.in
+++ b/libgrust/libproc_macro/Makefile.in
@@ -311,7 +311,14 @@ AM_MAKEFLAGS = \
 TARGETLIB = ./libproc_macro.a
 objext = @OBJEXT@
 REQUIRED_OFILES = \
-	./proc_macro.$(objext) ./literal.$(objext) ./group.$(objext) ./ident.$(objext) ./punct.$(objext) ./tokenstream.$(objext) ./tokentree.$(objext)
+	./proc_macro.$(objext) \
+	./literal.$(objext) \
+	./group.$(objext) \
+	./ident.$(objext) \
+	./punct.$(objext) \
+	./tokenstream.$(objext) \
+	./tokentree.$(objext) \
+	./ffistring.$(objext)
 
 all: all-am
 
diff --git a/libgrust/libproc_macro/ffistring.cc b/libgrust/libproc_macro/ffistring.cc
new file mode 100644
index 00000000000..1623bc9899e
--- /dev/null
+++ b/libgrust/libproc_macro/ffistring.cc
@@ -0,0 +1,62 @@
+// Copyright (C) 2023 Free Software Foundation, Inc.
+//
+// This file is part of the GNU Proc Macro Library.  This library 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.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#include <cstring>
+#include "ffistring.h"
+
+namespace ProcMacro {
+void
+FFIString::drop (FFIString *str)
+{
+  delete[] str->data;
+  str->len = 0;
+}
+
+FFIString
+FFIString::make_ffistring (const std::string &str)
+{
+  return make_ffistring (reinterpret_cast<const unsigned char *> (str.c_str ()),
+			 str.length ());
+}
+
+FFIString
+FFIString::make_ffistring (const unsigned char *data, std::uint64_t len)
+{
+  const unsigned char *inner = new unsigned char[len];
+  return {inner, len};
+}
+
+FFIString
+FFIString::clone () const
+{
+  unsigned char *inner = new unsigned char[this->len];
+  std::memcpy (inner, this->data, this->len);
+  return {inner, this->len};
+}
+
+std::string
+FFIString::to_string () const
+{
+  return std::string (reinterpret_cast<const char *> (this->data), this->len);
+}
+
+} // namespace ProcMacro
diff --git a/libgrust/libproc_macro/ffistring.h b/libgrust/libproc_macro/ffistring.h
new file mode 100644
index 00000000000..c151645ee5f
--- /dev/null
+++ b/libgrust/libproc_macro/ffistring.h
@@ -0,0 +1,55 @@
+// Copyright (C) 2023 Free Software Foundation, Inc.
+//
+// This file is part of the GNU Proc Macro Library.  This library 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.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef FFISTRING_H
+#define FFISTRING_H
+
+#include <cstdint>
+#include <string>
+
+namespace ProcMacro {
+
+struct FFIString
+{
+  const unsigned char *data;
+  std::uint64_t len;
+
+public:
+  FFIString clone () const;
+  std::string to_string () const;
+  static FFIString make_ffistring (const std::string &str);
+  static FFIString make_ffistring (const unsigned char *data,
+				   std::uint64_t len);
+  static void drop (FFIString *str);
+};
+
+extern "C" {
+FFIString
+FFIString__new (const unsigned char *data, std::uint64_t len);
+
+void
+FFIString__drop (FFIString *str);
+}
+
+} // namespace ProcMacro
+
+#endif /* ! FFISTRING_H */
diff --git a/libgrust/libproc_macro/literal.cc b/libgrust/libproc_macro/literal.cc
index 39474ce3120..e3d171f7268 100644
--- a/libgrust/libproc_macro/literal.cc
+++ b/libgrust/libproc_macro/literal.cc
@@ -26,266 +26,216 @@
 
 namespace ProcMacro {
 
-void
-Literal::drop (Literal *lit)
-{
-  switch (lit->tag)
-    {
-    case STRING:
-      delete[] lit->payload.string_payload.data;
-      lit->payload.string_payload.len = 0;
-      break;
-    case BYTE_STRING:
-      delete[] lit->payload.byte_string_payload.data;
-      lit->payload.byte_string_payload.size = 0;
-      break;
-    case CHAR:
-    case UNSIGNED:
-    case SIGNED:
-    case USIZE:
-    case ISIZE:
-    case FLOAT32:
-    case FLOAT64:
-      break;
-    }
-}
-
 extern "C" {
-
-void
-Literal__drop (Literal *lit)
-{
-  Literal::drop (lit);
-}
-
-Literal
-Literal__string (const unsigned char *str, std::uint64_t len)
-{
-  return Literal::make_string (str, len);
-}
-
-Literal
-Literal__byte_string (const std::uint8_t *bytes, std::uint64_t len)
-{
-  return Literal::make_byte_string (bytes, len);
-}
-
 bool
 Literal__from_string (const unsigned char *str, std::uint64_t len, Literal *lit)
 {
-  // FIXME: implement this function with parser
+  // FIXME: implement this function with lexer
   std::abort ();
   return false;
 }
 }
 
-Literal
-Literal::make_unsigned (UnsignedSuffixPayload p)
+void
+Literal::drop (Literal *lit)
 {
-  LiteralPayload payload;
-  payload.unsigned_payload = p;
-  return {UNSIGNED, payload};
+  FFIString::drop (&lit->text);
+  FFIString::drop (&lit->suffix);
 }
 
 Literal
-Literal::make_signed (SignedSuffixPayload p)
+Literal::clone () const
 {
-  LiteralPayload payload;
-  payload.signed_payload = p;
-  return {SIGNED, payload};
+  return {this->kind, this->text.clone (), this->has_suffix,
+	  this->suffix.clone ()};
 }
 
 Literal
-Literal::clone () const
+Literal::make_literal (LitKind kind, const std::string &text,
+		       const std::string &suffix)
 {
-  Literal lit = *this;
-  switch (this->tag)
-    {
-    case STRING:
-      lit.payload.string_payload.data
-	= new unsigned char[lit.payload.string_payload.len];
-      std::memcpy (lit.payload.string_payload.data,
-		   this->payload.string_payload.data,
-		   lit.payload.string_payload.len);
-      break;
-    case BYTE_STRING:
-      lit.payload.byte_string_payload.data
-	= new uint8_t[lit.payload.byte_string_payload.size];
-      std::memcpy (lit.payload.byte_string_payload.data,
-		   this->payload.byte_string_payload.data,
-		   lit.payload.byte_string_payload.size);
-      break;
-    default:
-      break;
-    }
-  return lit;
+  auto ffi_text = FFIString::make_ffistring (text);
+  auto ffi_suffix = FFIString::make_ffistring (suffix);
+  return {kind, ffi_text, suffix != "", ffi_suffix};
 }
 
 Literal
 Literal::make_u8 (std::uint8_t value, bool suffixed)
 {
-  UnsignedPayload unsigned_payload;
-  unsigned_payload.unsigned8 = value;
-  Unsigned val{UNSIGNED_8, unsigned_payload};
-  UnsignedSuffixPayload payload{val, suffixed};
-
-  return make_unsigned (payload);
+  auto text = FFIString::make_ffistring (std::to_string (value));
+  auto suffix = FFIString::make_ffistring (suffixed ? "u8" : "");
+  return {LitKind::make_integer (), text, suffixed, suffix};
 }
 
 Literal
 Literal::make_u16 (std::uint16_t value, bool suffixed)
 {
-  UnsignedPayload unsigned_payload;
-  unsigned_payload.unsigned16 = value;
-  Unsigned val{UNSIGNED_16, unsigned_payload};
-  UnsignedSuffixPayload payload{val, suffixed};
-
-  return make_unsigned (payload);
+  auto text = FFIString::make_ffistring (std::to_string (value));
+  auto suffix = FFIString::make_ffistring (suffixed ? "u16" : "");
+  return {LitKind::make_integer (), text, suffixed, suffix};
 }
 
 Literal
 Literal::make_u32 (std::uint32_t value, bool suffixed)
 {
-  UnsignedPayload unsigned_payload;
-  unsigned_payload.unsigned32 = value;
-  Unsigned val{UNSIGNED_32, unsigned_payload};
-  UnsignedSuffixPayload payload{val, suffixed};
-
-  return make_unsigned (payload);
+  auto text = FFIString::make_ffistring (std::to_string (value));
+  auto suffix = FFIString::make_ffistring (suffixed ? "u32" : "");
+  return {LitKind::make_integer (), text, suffixed, suffix};
 }
 
 Literal
 Literal::make_u64 (std::uint64_t value, bool suffixed)
 {
-  UnsignedPayload unsigned_payload;
-  unsigned_payload.unsigned64 = value;
-  Unsigned val{UNSIGNED_64, unsigned_payload};
-  UnsignedSuffixPayload payload{val, suffixed};
-
-  return make_unsigned (payload);
+  auto text = FFIString::make_ffistring (std::to_string (value));
+  auto suffix = FFIString::make_ffistring (suffixed ? "u64" : "");
+  return {LitKind::make_integer (), text, suffixed, suffix};
 }
 
 Literal
 Literal::make_i8 (std::int8_t value, bool suffixed)
 {
-  SignedPayload signed_payload;
-  signed_payload.signed8 = value;
-  Signed val{SIGNED_8, signed_payload};
-  SignedSuffixPayload payload{val, suffixed};
-
-  return make_signed (payload);
+  auto text = FFIString::make_ffistring (std::to_string (value));
+  auto suffix = FFIString::make_ffistring (suffixed ? "i8" : "");
+  return {LitKind::make_integer (), text, suffixed, suffix};
 }
 
 Literal
 Literal::make_i16 (std::int16_t value, bool suffixed)
 {
-  SignedPayload signed_payload;
-  signed_payload.signed16 = value;
-  Signed val{SIGNED_16, signed_payload};
-  SignedSuffixPayload payload{val, suffixed};
-
-  return make_signed (payload);
+  auto text = FFIString::make_ffistring (std::to_string (value));
+  auto suffix = FFIString::make_ffistring (suffixed ? "i16" : "");
+  return {LitKind::make_integer (), text, suffixed, suffix};
 }
 
 Literal
 Literal::make_i32 (std::int32_t value, bool suffixed)
 {
-  SignedPayload signed_payload;
-  signed_payload.signed32 = value;
-  Signed val{SIGNED_32, signed_payload};
-  SignedSuffixPayload payload = {val, suffixed};
-
-  return make_signed (payload);
+  auto text = FFIString::make_ffistring (std::to_string (value));
+  auto suffix = FFIString::make_ffistring (suffixed ? "i32" : "");
+  return {LitKind::make_integer (), text, suffixed, suffix};
 }
 
 Literal
 Literal::make_i64 (std::int64_t value, bool suffixed)
 {
-  SignedPayload signed_payload;
-  signed_payload.signed64 = value;
-  Signed val{SIGNED_64, signed_payload};
-  SignedSuffixPayload payload{val, suffixed};
-
-  return make_signed (payload);
+  auto text = FFIString::make_ffistring (std::to_string (value));
+  auto suffix = FFIString::make_ffistring (suffixed ? "i64" : "");
+  return {LitKind::make_integer (), text, suffixed, suffix};
 }
 
 Literal
 Literal::make_string (const std::string &str)
 {
-  return make_string (reinterpret_cast<const unsigned char *> (str.c_str ()),
-		      str.length ());
+  auto text = FFIString::make_ffistring (str);
+  auto suffix = FFIString::make_ffistring ("");
+  return {LitKind::make_str (), text, false, suffix};
 }
 
 Literal
-Literal::make_string (const unsigned char *str, std::uint64_t len)
+Literal::make_byte_string (const std::vector<std::uint8_t> &vec)
 {
-  unsigned char *data = new unsigned char[len];
-  StringPayload str_payload = {data, len};
-  std::memcpy (data, str, len);
-  LiteralPayload payload;
-  payload.string_payload = str_payload;
-  return {STRING, payload};
+  auto text
+    = FFIString::make_ffistring (std::string (vec.cbegin (), vec.cend ()));
+  auto suffix = FFIString::make_ffistring ("");
+  return {LitKind::make_byte_str (), text, false, suffix};
 }
 
 Literal
-Literal::make_byte_string (const std::vector<std::uint8_t> &vec)
+Literal::make_f32 (float value, bool suffixed)
 {
-  return make_byte_string (vec.data (), vec.size ());
+  auto text = FFIString::make_ffistring (std::to_string (value));
+  auto suffix = FFIString::make_ffistring (suffixed ? "f32" : "");
+  return {LitKind::make_float (), text, suffixed, suffix};
 }
 
 Literal
-Literal::make_byte_string (const std::uint8_t *bytes, std::uint64_t len)
+Literal::make_f64 (double value, bool suffixed)
 {
-  std::uint8_t *data = new std::uint8_t[len];
-  ByteStringPayload bstr_payload = {data, len};
-  std::memcpy (data, bytes, len);
-  LiteralPayload payload;
-  payload.byte_string_payload = bstr_payload;
-  return {BYTE_STRING, payload};
+  auto text = FFIString::make_ffistring (std::to_string (value));
+  auto suffix = FFIString::make_ffistring (suffixed ? "f64" : "");
+  return {LitKind::make_float (), text, suffixed, suffix};
 }
 
 Literal
-Literal::make_f32 (float value, bool suffixed)
+Literal::make_char (std::uint32_t ch)
 {
-  Float32Payload f{value, suffixed};
-  LiteralPayload payload;
-  payload.float32_payload = f;
-  return {FLOAT32, payload};
+  auto text = FFIString::make_ffistring (std::to_string ((char) ch));
+  auto suffix = FFIString::make_ffistring ("");
+  return {LitKind::make_char (), text, false, suffix};
 }
 
 Literal
-Literal::make_f64 (double value, bool suffixed)
+Literal::make_usize (std::uint64_t value, bool suffixed)
 {
-  Float64Payload f{value, suffixed};
-  LiteralPayload payload;
-  payload.float64_payload = f;
-  return {FLOAT64, payload};
+  auto text = FFIString::make_ffistring (std::to_string (value));
+  auto suffix = FFIString::make_ffistring (suffixed ? "usize" : "");
+  return {LitKind::make_integer (), text, suffixed, suffix};
 }
 
 Literal
-Literal::make_char (std::uint32_t ch)
+Literal::make_isize (std::int64_t value, bool suffixed)
+{
+  auto text = FFIString::make_ffistring (std::to_string (value));
+  auto suffix = FFIString::make_ffistring (suffixed ? "isize" : "");
+  return {LitKind::make_integer (), text, suffixed, suffix};
+}
+
+LitKind
+LitKind::make_byte ()
 {
-  LiteralPayload payload;
-  payload.char_payload = ch;
+  LitKindPayload payload;
+  return {BYTE, payload};
+}
+
+LitKind
+LitKind::make_char ()
+{
+  LitKindPayload payload;
   return {CHAR, payload};
 }
 
-Literal
-Literal::make_usize (std::uint64_t value, bool suffixed)
+LitKind
+LitKind::make_integer ()
 {
-  UsizePayload p{value, suffixed};
-  LiteralPayload payload;
-  payload.usize_payload = p;
-  return {USIZE, payload};
+  LitKindPayload payload;
+  return {INTEGER, payload};
 }
 
-Literal
-Literal::make_isize (std::int64_t value, bool suffixed)
+LitKind
+LitKind::make_float ()
+{
+  LitKindPayload payload;
+  return {FLOAT, payload};
+}
+
+LitKind
+LitKind::make_str ()
+{
+  LitKindPayload payload;
+  return {STR, payload};
+}
+
+LitKind
+LitKind::make_str_raw (std::uint8_t val)
+{
+  LitKindPayload payload;
+  payload.str_raw = val;
+  return {STR_RAW, payload};
+}
+
+LitKind
+LitKind::make_byte_str ()
+{
+  LitKindPayload payload;
+  return {BYTE_STR, payload};
+}
+
+LitKind
+LitKind::make_byte_str_raw (std::uint8_t val)
 {
-  IsizePayload p{value, suffixed};
-  LiteralPayload payload;
-  payload.isize_payload = p;
-  return {ISIZE, payload};
+  LitKindPayload payload;
+  payload.byte_str_raw = val;
+  return {BYTE_STR_RAW, payload};
 }
 
 } // namespace ProcMacro
diff --git a/libgrust/libproc_macro/literal.h b/libgrust/libproc_macro/literal.h
index f48b534e3f0..fa2df3f62ea 100644
--- a/libgrust/libproc_macro/literal.h
+++ b/libgrust/libproc_macro/literal.h
@@ -26,183 +26,82 @@
 #include <cstdint>
 #include <string>
 #include <vector>
+#include "ffistring.h"
 
 namespace ProcMacro {
-enum UnsignedTag
-{
-  UNSIGNED_8,
-  UNSIGNED_16,
-  UNSIGNED_32,
-  UNSIGNED_64,
-  UNSIGNED_128
-};
-
-struct Payload128
-{
-  std::uint64_t low;
-  std::uint64_t high;
-};
-
-union UnsignedPayload
-{
-  std::uint8_t unsigned8;
-  std::uint16_t unsigned16;
-  std::uint32_t unsigned32;
-  std::uint64_t unsigned64;
-  Payload128 unsigned128;
-};
-
-struct Unsigned
-{
-  UnsignedTag tag;
-  UnsignedPayload payload;
-};
-
-enum SignedTag
-{
-  SIGNED_8,
-  SIGNED_16,
-  SIGNED_32,
-  SIGNED_64,
-  SIGNED_128
-};
-
-union SignedPayload
-{
-  std::int8_t signed8;
-  std::int16_t signed16;
-  std::int32_t signed32;
-  std::int64_t signed64;
-};
-
-struct Signed
-{
-  SignedTag tag;
-  SignedPayload payload;
-};
 
-enum LiteralTag
+enum LitKindTag
 {
-  STRING,
-  BYTE_STRING,
+  BYTE,
   CHAR,
-  UNSIGNED,
-  SIGNED,
-  USIZE,
-  ISIZE,
-  FLOAT32,
-  FLOAT64
-};
-
-struct StringPayload
-{
-  unsigned char *data;
-  std::uint64_t len;
+  INTEGER,
+  FLOAT,
+  STR,
+  STR_RAW,
+  BYTE_STR,
+  BYTE_STR_RAW,
 };
 
-struct ByteStringPayload
+union LitKindPayload
 {
-  std::uint8_t *data;
-  std::uint64_t size;
+  std::uint8_t str_raw;
+  std::uint8_t byte_str_raw;
 };
 
-struct UnsignedSuffixPayload
+struct LitKind
 {
-  Unsigned value;
-  bool suffix;
-};
+  LitKindTag tag;
+  LitKindPayload payload;
 
-struct SignedSuffixPayload
-{
-  Signed value;
-  bool suffix;
-};
-
-struct UsizePayload
-{
-  std::uint64_t value;
-  bool suffix;
-};
-
-struct IsizePayload
-{
-  std::int64_t value;
-  bool suffix;
-};
-
-struct Float32Payload
-{
-  float value;
-  bool suffix;
-};
-
-struct Float64Payload
-{
-  double value;
-  bool suffix;
-};
-
-union LiteralPayload
-{
-  StringPayload string_payload;
-  ByteStringPayload byte_string_payload;
-  std::uint32_t char_payload;
-  UnsignedSuffixPayload unsigned_payload;
-  SignedSuffixPayload signed_payload;
-  UsizePayload usize_payload;
-  IsizePayload isize_payload;
-  Float32Payload float32_payload;
-  Float64Payload float64_payload;
+private:
+public:
+  static LitKind make_byte ();
+  static LitKind make_char ();
+  static LitKind make_integer ();
+  static LitKind make_float ();
+  static LitKind make_str ();
+  static LitKind make_str_raw (std::uint8_t val);
+  static LitKind make_byte_str ();
+  static LitKind make_byte_str_raw (std::uint8_t val);
 };
 
 struct Literal
 {
-  LiteralTag tag;
-  LiteralPayload payload;
+  LitKind kind;
+  FFIString text;
+  bool has_suffix;
+  FFIString suffix;
+  // TODO: Add span once done in rust interface
 
 public:
   Literal clone () const;
 
-  static Literal make_u8 (std::uint8_t value, bool suffixed = false);
-  static Literal make_u16 (std::uint16_t value, bool suffixed = false);
-  static Literal make_u32 (std::uint32_t value, bool suffixed = false);
-  static Literal make_u64 (std::uint64_t value, bool suffixed = false);
+  static Literal make_literal (const LitKind kind, const std::string &text,
+			       const std::string &suffix = "");
+  static Literal make_u8 (std::uint8_t value, bool suffixed = true);
+  static Literal make_u16 (std::uint16_t value, bool suffixed = true);
+  static Literal make_u32 (std::uint32_t value, bool suffixed = true);
+  static Literal make_u64 (std::uint64_t value, bool suffixed = true);
 
-  static Literal make_i8 (std::int8_t value, bool suffixed = false);
-  static Literal make_i16 (std::int16_t value, bool suffixed = false);
-  static Literal make_i32 (std::int32_t value, bool suffixed = false);
-  static Literal make_i64 (std::int64_t value, bool suffixed = false);
+  static Literal make_i8 (std::int8_t value, bool suffixed = true);
+  static Literal make_i16 (std::int16_t value, bool suffixed = true);
+  static Literal make_i32 (std::int32_t value, bool suffixed = true);
+  static Literal make_i64 (std::int64_t value, bool suffixed = true);
 
   static Literal make_string (const std::string &str);
-  static Literal make_string (const unsigned char *str, std::uint64_t len);
   static Literal make_byte_string (const std::vector<std::uint8_t> &vec);
-  static Literal make_byte_string (const std::uint8_t *bytes,
-				   std::uint64_t len);
 
   static Literal make_f32 (float value, bool suffixed = false);
   static Literal make_f64 (double value, bool suffixed = false);
 
   static Literal make_char (std::uint32_t ch);
-  static Literal make_usize (std::uint64_t value, bool suffixed = false);
-  static Literal make_isize (std::int64_t value, bool suffixed = false);
+  static Literal make_usize (std::uint64_t value, bool suffixed = true);
+  static Literal make_isize (std::int64_t value, bool suffixed = true);
 
   static void drop (Literal *lit);
-
-private:
-  static Literal make_unsigned (UnsignedSuffixPayload p);
-  static Literal make_signed (SignedSuffixPayload p);
 };
 
 extern "C" {
-void
-Literal__drop (Literal *lit);
-
-Literal
-Literal__string (const unsigned char *str, std::uint64_t len);
-
-Literal
-Literal__byte_string (const std::uint8_t *bytes, std::uint64_t len);
-
 bool
 Literal__from_string (const unsigned char *str, std::uint64_t len,
 		      Literal *lit);


More information about the Gcc-cvs mailing list