| // Copyright (C) 2020-2025 Free Software Foundation, Inc. |
| |
| // This file is part of GCC. |
| |
| // GCC 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. |
| |
| // GCC 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. |
| |
| // You should have received a copy of the GNU General Public License |
| // along with GCC; see the file COPYING3. If not see |
| // <http://www.gnu.org/licenses/>. |
| |
| #ifndef RUST_MACRO_BUILTINS_H |
| #define RUST_MACRO_BUILTINS_H |
| |
| #include "optional.h" |
| #include "rust-ast.h" |
| #include "rust-builtin-ast-nodes.h" |
| #include "rust-ast-fragment.h" |
| #include "rust-location.h" |
| #include "bi-map.h" |
| |
| namespace Rust { |
| |
| // FIXME: Add a BuiltinMacro class which contains a name (or should it?), a |
| // transcriber and extra info if necessary |
| // then make a global map<string, BuiltinMacro> |
| |
| // |
| // All builtin macros possible |
| // |
| enum class BuiltinMacro |
| { |
| Assert, |
| File, |
| Line, |
| Column, |
| IncludeBytes, |
| IncludeStr, |
| Stringify, |
| CompileError, |
| Concat, |
| Env, |
| OptionEnv, |
| Cfg, |
| Include, |
| FormatArgs, |
| FormatArgsNl, |
| ConcatIdents, |
| ModulePath, |
| Asm, |
| LlvmAsm, |
| GlobalAsm, |
| LogSyntax, |
| TraceMacros, |
| Test, |
| Bench, |
| TestCase, |
| GlobalAllocator, |
| CfgAccessible, |
| RustcDecodable, |
| RustcEncodable, |
| Clone, |
| Copy, |
| Debug, |
| Default, |
| Eq, |
| PartialEq, |
| Ord, |
| PartialOrd, |
| Hash, |
| }; |
| |
| tl::optional<BuiltinMacro> |
| builtin_macro_from_string (const std::string &identifier); |
| |
| // |
| // This class provides a list of builtin macros implemented by the compiler. |
| // The functions defined are called "builtin transcribers" in that they |
| // replace the transcribing part of a macro definition. |
| // |
| // Like regular macro transcribers, they are responsible for building and |
| // returning an AST fragment: basically a vector of AST nodes put together. |
| // |
| // Unlike regular declarative macros where each match arm has its own |
| // associated transcriber, builtin transcribers are responsible for handling |
| // all match arms of the macro. This means that you should take extra care |
| // when implementing a builtin containing multiple match arms: You will |
| // probably need to do some lookahead in order to determine which match arm |
| // the user intended to use. |
| // |
| // An example of this is the `assert!()` macro: |
| // |
| // ``` |
| // macro_rules! assert { |
| // ($cond:expr $(,)?) => {{ ... }}; |
| // ($cond : expr, $ ($arg : tt) +) = > {{ ... }}; |
| // } |
| // ``` |
| // |
| // If more tokens exist beyond the optional comma, they need to be handled as |
| // a token-tree for a custom panic message. |
| // |
| // These builtin macros with empty transcribers are defined in the standard |
| // library. They are marked with a special attribute, |
| // `#[rustc_builtin_macro]`. When this attribute is present on a macro |
| // definition, the compiler should look for an associated transcriber in the |
| // mappings. Meaning that you must remember to insert your transcriber in the |
| // `builtin_macros` map of the `Mappings`. |
| // |
| // This map is built as a static variable in the `insert_macro_def()` method |
| // of the `Mappings` class. |
| |
| class MacroBuiltin |
| { |
| public: |
| static const BiMap<std::string, BuiltinMacro> builtins; |
| static std::unordered_map<std::string, AST::MacroTranscriberFunc> |
| builtin_transcribers; |
| |
| static tl::optional<AST::Fragment> assert_handler (location_t invoc_locus, |
| AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> file_handler (location_t invoc_locus, |
| AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> column_handler (location_t invoc_locus, |
| AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> |
| include_bytes_handler (location_t invoc_locus, AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> |
| include_str_handler (location_t invoc_locus, AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> |
| stringify_handler (location_t invoc_locus, AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> |
| compile_error_handler (location_t invoc_locus, AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> concat_handler (location_t invoc_locus, |
| AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> env_handler (location_t invoc_locus, |
| AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> |
| option_env_handler (location_t invoc_locus, AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> cfg_handler (location_t invoc_locus, |
| AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> |
| include_handler (location_t invoc_locus, AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> line_handler (location_t invoc_locus, |
| AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| static tl::optional<AST::Fragment> asm_handler (location_t invoc_locus, |
| AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon, |
| AST::AsmKind is_global_asm); |
| |
| static tl::optional<AST::Fragment> |
| llvm_asm_handler (location_t invoc_locus, AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon, AST::AsmKind is_global_asm); |
| |
| static tl::optional<AST::Fragment> |
| format_args_handler (location_t invoc_locus, AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon, AST::FormatArgs::Newline nl); |
| |
| static tl::optional<AST::Fragment> |
| offset_of_handler (location_t, AST::MacroInvocData &, AST::InvocKind); |
| |
| static tl::optional<AST::Fragment> sorry (location_t invoc_locus, |
| AST::MacroInvocData &invoc, |
| AST::InvocKind semicolon); |
| |
| /* Builtin procedural macros do not work directly on tokens, but still need a |
| * builtin transcriber to be considered proper builtin macros */ |
| static tl::optional<AST::Fragment> |
| proc_macro_builtin (location_t, AST::MacroInvocData &, AST::InvocKind); |
| }; |
| } // namespace Rust |
| |
| namespace std { |
| template <> struct hash<Rust::BuiltinMacro> |
| { |
| size_t operator() (const Rust::BuiltinMacro ¯o) const noexcept |
| { |
| return hash<std::underlying_type<Rust::BuiltinMacro>::type> () ( |
| static_cast<std::underlying_type<Rust::BuiltinMacro>::type> (macro)); |
| } |
| }; |
| } // namespace std |
| |
| #endif // RUST_MACRO_BUILTINS_H |