diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2023-11-30 14:11:41 +0100 |
---|---|---|
committer | CohenArthur <arthur.cohen@embecosm.com> | 2024-02-26 17:32:38 +0000 |
commit | 7b25f53a416868059299661ddf769ec4c9c2516d (patch) | |
tree | 78fb5b2af443b15fcd5dbc97a5bb73d6faae7288 /gcc/rust | |
parent | 486b2043a08ff49605ea7d52fc2c3f5403d72079 (diff) | |
download | gcc-7b25f53a416868059299661ddf769ec4c9c2516d.zip gcc-7b25f53a416868059299661ddf769ec4c9c2516d.tar.gz gcc-7b25f53a416868059299661ddf769ec4c9c2516d.tar.bz2 |
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/rust')
-rw-r--r-- | gcc/rust/Make-lang.in | 15 | ||||
-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, 141 insertions, 155 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 6696b47..7c8ab6e 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 \ @@ -209,14 +211,14 @@ RUST_ALL_OBJS = $(GRS_OBJS) $(RUST_TARGET_OBJS) rust_OBJS = $(RUST_ALL_OBJS) rust/rustspec.o -RUST_LDFLAGS = $(LDFLAGS) -L./../libgrust/libproc_macro_internal -RUST_LIBDEPS = $(LIBDEPS) ../libgrust/libproc_macro_internal/libproc_macro_internal.a +RUST_LDFLAGS = $(LDFLAGS) -L./../libgrust/libproc_macro_internal -L./../libgrust/librustc_format_parser/ +RUST_LIBDEPS = $(LIBDEPS) ../libgrust/libproc_macro_internal/libproc_macro_internal.a rust/libformat_parser.a # The compiler itself is called crab1 crab1$(exeext): $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(RUST_LIBDEPS) $(rust.prev) @$(call LINK_PROGRESS,$(INDEX.rust),start) +$(LLINKER) $(ALL_LINKERFLAGS) $(RUST_LDFLAGS) -o $@ \ - $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) ../libgrust/libproc_macro_internal/libproc_macro_internal.a $(BACKENDLIBS) + $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) ../libgrust/libproc_macro_internal/libproc_macro_internal.a rust/libformat_parser.a $(BACKENDLIBS) @$(call LINK_PROGRESS,$(INDEX.rust),end) # Build hooks. @@ -402,6 +404,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); |