diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2024-04-23 13:38:58 +0200 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2024-08-01 12:47:19 +0200 |
commit | 6fef4d6ffcab0fec8518adcb05458cba5dbeac25 (patch) | |
tree | bb3bdab1b69382086cc1bab294d79f60f75295c7 /gcc | |
parent | 473feb033d5ccb139f8af8e0e54193b176d1cd93 (diff) | |
download | gcc-6fef4d6ffcab0fec8518adcb05458cba5dbeac25.zip gcc-6fef4d6ffcab0fec8518adcb05458cba5dbeac25.tar.gz gcc-6fef4d6ffcab0fec8518adcb05458cba5dbeac25.tar.bz2 |
gccrs: libgrust: Add format_parser library
Compile libformat_parser and link to it.
gcc/rust/ChangeLog:
* Make-lang.in: Compile libformat_parser.
* ast/rust-fmt.cc: New FFI definitions.
* ast/rust-fmt.h: Likewise.
* expand/rust-macro-builtins.cc (MacroBuiltin::format_args_handler): Call
into libformat_parser.
* expand/rust-macro-builtins.h: Define format_args!() handler proper.
libgrust/ChangeLog:
* libformat_parser/Cargo.lock: New file.
* libformat_parser/Cargo.toml: New file.
* libformat_parser/generic_format_parser/Cargo.toml: New file.
* libformat_parser/generic_format_parser/src/lib.rs: New file.
* libformat_parser/src/bin.rs: New file.
* libformat_parser/src/lib.rs: New file.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/Make-lang.in | 11 | ||||
-rw-r--r-- | gcc/rust/ast/rust-fmt.cc | 77 | ||||
-rw-r--r-- | gcc/rust/ast/rust-fmt.h | 189 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-builtins.cc | 12 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-builtins.h | 3 |
5 files changed, 139 insertions, 153 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index c0df49a..8ac0d1d1 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -54,6 +54,8 @@ GCCRS_D_OBJS = \ rust/rustspec.o \ $(END) +LIBS += -ldl -lpthread + gccrs$(exeext): $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS) +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \ @@ -218,7 +220,7 @@ RUST_LIBDEPS = $(LIBDEPS) $(LIBPROC_MACRO_INTERNAL) crab1$(exeext): $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(RUST_LIBDEPS) $(rust.prev) @$(call LINK_PROGRESS,$(INDEX.rust),start) +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ - $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) $(LIBPROC_MACRO_INTERNAL) $(BACKENDLIBS) + $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) $(LIBPROC_MACRO_INTERNAL) rust/libformat_parser.a $(BACKENDLIBS) @$(call LINK_PROGRESS,$(INDEX.rust),end) # Build hooks. @@ -406,6 +408,13 @@ rust/%.o: rust/lex/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) +%.toml: + echo $@ + +rust/libformat_parser.a: $(srcdir)/../libgrust/libformat_parser/Cargo.toml $(wildcard $(srcdir)/../libgrust/libformat_parser/src/*.rs) + cargo build --manifest-path $(srcdir)/../libgrust/libformat_parser/Cargo.toml --release # FIXME: Not always release, right? + cp $(srcdir)/../libgrust/libformat_parser/target/release/liblibformat_parser.a $@ + # build all rust/parse files in rust folder, add cross-folder includes rust/%.o: rust/parse/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< diff --git a/gcc/rust/ast/rust-fmt.cc b/gcc/rust/ast/rust-fmt.cc index 9f9ba48..559b1c8 100644 --- a/gcc/rust/ast/rust-fmt.cc +++ b/gcc/rust/ast/rust-fmt.cc @@ -19,78 +19,23 @@ #include "rust-fmt.h" namespace Rust { -tl::expected<Fmt, Fmt::Error> -Fmt::parse_fmt_string (Fmt::Input input) -{ - return Fmt (); -} +namespace Fmt { -tl::expected<Fmt::Result<tl::optional<Fmt::Format>>, Fmt::Error> -Fmt::maybe_format (Fmt::Input input) +Pieces +Pieces::collect (const std::string &to_parse) { - tl::optional<Fmt::Format> none = tl::nullopt; + auto piece_slice = collect_pieces (to_parse.c_str ()); - return Fmt::Result (input, none); -} + rust_debug ("[ARTHUR] %p, %lu", (void *) piece_slice.ptr, piece_slice.len); -tl::expected<Fmt::Result<Fmt::Format>, Fmt::Error> -Fmt::format (Input input) -{ - return Fmt::Result (input, Format ()); -} + // this performs multiple copies, can we avoid them maybe? + auto pieces + = std::vector (piece_slice.ptr, piece_slice.ptr + piece_slice.len); -tl::expected<Fmt::Result<Fmt::Argument>, Fmt::Error> -Fmt::argument (Input input) -{ - return Fmt::Result (input, Argument ()); -} + rust_debug ("[ARTHUR] %p, %lu", (void *) pieces.data (), pieces.size ()); -tl::expected<Fmt::Result<Fmt::FormatSpec>, Fmt::Error> -Fmt::format_spec (Input input) -{ - return Fmt::Result (input, FormatSpec ()); -} - -tl::expected<Fmt::Result<Fmt::Fill>, Fmt::Error> -Fmt::fill (Input input) -{ - return Fmt::Result (input, Fill ()); -} - -tl::expected<Fmt::Result<Fmt::Align>, Fmt::Error> -Fmt::align (Input input) -{ - switch (input[0]) - { - case '<': - return Fmt::Result (input.substr (1), Align::Left); - case '^': - return Fmt::Result (input.substr (1), Align::Top); - case '>': - return Fmt::Result (input.substr (1), Align::Right); - default: - // TODO: Store the character here - // TODO: Can we have proper error locations? - // TODO: Maybe we should use a Rust::Literal string instead of a string - return tl::make_unexpected (Error::Align); - } -} - -tl::expected<Fmt::Result<Fmt::Sign>, Fmt::Error> -Fmt::sign (Input input) -{ - switch (input[0]) - { - case '+': - return Fmt::Result (input.substr (1), Sign::Plus); - case '-': - return Fmt::Result (input.substr (1), Sign::Minus); - default: - // TODO: Store the character here - // TODO: Can we have proper error locations? - // TODO: Maybe we should use a Rust::Literal string instead of a string - return tl::make_unexpected (Error::Sign); - } + return Pieces{}; } +} // namespace Fmt } // namespace Rust diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h index f3dd53d..0050977 100644 --- a/gcc/rust/ast/rust-fmt.h +++ b/gcc/rust/ast/rust-fmt.h @@ -19,115 +19,134 @@ #ifndef RUST_FMT_H #define RUST_FMT_H -#include "expected.h" -#include "optional.h" -#include "rust-ast.h" +#include "rust-diagnostics.h" #include "rust-system.h" namespace Rust { +namespace Fmt { -/** - * This class implements the parsing of Rust format strings according to the - * grammar here: https://doc.rust-lang.org/std/fmt/index.html#syntax - */ -// TODO: Are there features that are only present in specific Rust editions? -class Fmt +struct RustHamster { -public: - // TODO: Keep location information - // TODO: Switch to a Rust::AST::Literal here - using Input = std::string; + // hehe +}; - enum class Error - { - Align, - Sign, - }; +struct InnerSpan +{ +}; - template <typename T> class Result +struct Count +{ + enum class Kind + { + Is, + IsName, + IsParam, + IsStar, + Implied + } kind; + + union { - public: - explicit Result (Input remaining_input, T result) - : remaining_input (remaining_input), result (result) - {} + size_t is; + std::pair<RustHamster, InnerSpan> is_name; + size_t is_param; + size_t is_star; + } data; +}; - private: - Input remaining_input; - T result; - }; +struct DebugHex +{ +}; - // FIXME: Do not use an owned string here - static tl::expected<Fmt, Fmt::Error> parse_fmt_string (Input input); +struct Sign +{ +}; -private: - // the parse functions should return the remaining input as well as the - // expected node let's look at nom - // TODO: no string view :( use an owned string for now? +struct Alignment +{ +}; - template <typename T> struct ParseResult - { - tl::expected<Result<T>, Error> inner; +struct RustString +{ + // hehe +}; - ParseResult (tl::expected<Result<T>, Error> inner) : inner (inner) {} - ParseResult operator= (tl::expected<Result<T>, Error> inner) - { - return ParseResult (inner); - } +struct Position +{ +}; - Input remaining_input () { return inner->remaining_input; } - T value () { return inner->value; } - }; +struct FormatSpec +{ + /// Optionally specified character to fill alignment with. + tl::optional<char /* FIXME: This is a Rust char, not a C++ char - use an uint32_t instead? */> fill; + /// Span of the optionally specified fill character. + tl::optional<InnerSpan> fill_span; + /// Optionally specified alignment. + Alignment align; + /// The `+` or `-` flag. + tl::optional<Sign> sign; + /// The `#` flag. + bool alternate; + /// The `0` flag. + bool zero_pad; + /// The `x` or `X` flag. (Only for `Debug`.) + tl::optional<DebugHex> debug_hex; + /// The integer precision to use. + // Count <'a> precision; + /// The span of the precision formatting flag (for diagnostics). + tl::optional<InnerSpan> precision_span; + /// The string width requested for the resulting format. + // Count <'a> width; + /// The span of the width formatting flag (for diagnostics). + tl::optional<InnerSpan> width_span; + /// The descriptor string representing the name of the format desired for + /// this argument, this can be empty or any number of characters, although + /// it is required to be one word. + RustHamster ty; + // &'a str ty; + /// The span of the descriptor string (for diagnostics). + tl::optional<InnerSpan> ty_span; +}; - struct Format - { - }; +struct Argument +{ + Position position; + InnerSpan inner_span; + FormatSpec format; +}; - struct Argument +struct Piece +{ + enum class Kind { - enum struct Kind - { - Integer, - Identifier, - } kind; + String, + NextArgument + } kind; - int integer; - Identifier identifier; - }; - - struct FormatSpec + union { - }; + RustString string; + Argument *next_argument; + } data; +}; - struct Fill - { - char to_fill; - }; +struct PieceSlice +{ + Piece *ptr; + size_t len; +}; - enum class Align - { - Left, - Top, - Right - }; +extern "C" { +PieceSlice +collect_pieces (const char *); +} - enum class Sign - { - Plus, - Minus - }; - - // let's do one function per rule in the BNF - static tl::expected<Result<std::string>, Error> text (Input input); - static tl::expected<Result<tl::optional<Format>>, Error> - maybe_format (Input input); - static tl::expected<Result<Format>, Error> format (Input input); - static tl::expected<Result<Argument>, Error> argument (Input input); - static tl::expected<Result<FormatSpec>, Error> format_spec (Input input); - static tl::expected<Result<Fill>, Error> fill (Input input); - static tl::expected<Result<Align>, Error> align (Input input); - static tl::expected<Result<Sign>, Error> sign (Input input); +struct Pieces +{ + static Pieces collect (const std::string &to_parse); }; +} // namespace Fmt } // namespace Rust #endif // ! RUST_FMT_H diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc index 71da575..0e57406 100644 --- a/gcc/rust/expand/rust-macro-builtins.cc +++ b/gcc/rust/expand/rust-macro-builtins.cc @@ -30,6 +30,7 @@ #include "rust-parse.h" #include "rust-session-manager.h" #include "rust-attribute-values.h" +#include "rust-fmt.h" namespace Rust { @@ -89,8 +90,8 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc> {"env", MacroBuiltin::env_handler}, {"cfg", MacroBuiltin::cfg_handler}, {"include", MacroBuiltin::include_handler}, + {"format_args", MacroBuiltin::format_args_handler}, /* Unimplemented macro builtins */ - {"format_args", MacroBuiltin::sorry}, {"option_env", MacroBuiltin::sorry}, {"format_args_nl", MacroBuiltin::sorry}, {"concat_idents", MacroBuiltin::sorry}, @@ -943,6 +944,15 @@ MacroBuiltin::stringify_handler (location_t invoc_locus, } tl::optional<AST::Fragment> +MacroBuiltin::format_args_handler (location_t invoc_locus, + AST::MacroInvocData &invoc) +{ + Fmt::Pieces::collect ("heyo this {is} what I {} want to {3}, {parse}"); + + return AST::Fragment::create_empty (); +} + +tl::optional<AST::Fragment> MacroBuiltin::sorry (location_t invoc_locus, AST::MacroInvocData &invoc) { rust_sorry_at (invoc_locus, "unimplemented builtin macro: %qs", diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h index 6a84a8b..f9ab3fc 100644 --- a/gcc/rust/expand/rust-macro-builtins.h +++ b/gcc/rust/expand/rust-macro-builtins.h @@ -157,6 +157,9 @@ public: static tl::optional<AST::Fragment> line_handler (location_t invoc_locus, AST::MacroInvocData &invoc); + static tl::optional<AST::Fragment> + format_args_handler (location_t invoc_locus, AST::MacroInvocData &invoc); + static tl::optional<AST::Fragment> sorry (location_t invoc_locus, AST::MacroInvocData &invoc); |