Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #ifndef RUST_MACRO_BUILTINS_H
20 : : #define RUST_MACRO_BUILTINS_H
21 : :
22 : : #include "optional.h"
23 : : #include "rust-ast.h"
24 : : #include "rust-builtin-ast-nodes.h"
25 : : #include "rust-ast-fragment.h"
26 : : #include "rust-location.h"
27 : : #include "bi-map.h"
28 : :
29 : : namespace Rust {
30 : :
31 : : // FIXME: Add a BuiltinMacro class which contains a name (or should it?), a
32 : : // transcriber and extra info if necessary
33 : : // then make a global map<string, BuiltinMacro>
34 : :
35 : : //
36 : : // All builtin macros possible
37 : : //
38 : : enum class BuiltinMacro
39 : : {
40 : : Assert,
41 : : File,
42 : : Line,
43 : : Column,
44 : : IncludeBytes,
45 : : IncludeStr,
46 : : Stringify,
47 : : CompileError,
48 : : Concat,
49 : : Env,
50 : : OptionEnv,
51 : : Cfg,
52 : : Include,
53 : : FormatArgs,
54 : : FormatArgsNl,
55 : : ConcatIdents,
56 : : ModulePath,
57 : : Asm,
58 : : LlvmAsm,
59 : : GlobalAsm,
60 : : LogSyntax,
61 : : TraceMacros,
62 : : Test,
63 : : Bench,
64 : : TestCase,
65 : : GlobalAllocator,
66 : : CfgAccessible,
67 : : RustcDecodable,
68 : : RustcEncodable,
69 : : Clone,
70 : : Copy,
71 : : Debug,
72 : : Default,
73 : : Eq,
74 : : PartialEq,
75 : : Ord,
76 : : PartialOrd,
77 : : Hash,
78 : : };
79 : :
80 : : tl::optional<BuiltinMacro>
81 : : builtin_macro_from_string (const std::string &identifier);
82 : :
83 : : //
84 : : // This class provides a list of builtin macros implemented by the compiler.
85 : : // The functions defined are called "builtin transcribers" in that they
86 : : // replace the transcribing part of a macro definition.
87 : : //
88 : : // Like regular macro transcribers, they are responsible for building and
89 : : // returning an AST fragment: basically a vector of AST nodes put together.
90 : : //
91 : : // Unlike regular declarative macros where each match arm has its own
92 : : // associated transcriber, builtin transcribers are responsible for handling
93 : : // all match arms of the macro. This means that you should take extra care
94 : : // when implementing a builtin containing multiple match arms: You will
95 : : // probably need to do some lookahead in order to determine which match arm
96 : : // the user intended to use.
97 : : //
98 : : // An example of this is the `assert!()` macro:
99 : : //
100 : : // ```
101 : : // macro_rules! assert {
102 : : // ($cond:expr $(,)?) => {{ ... }};
103 : : // ($cond : expr, $ ($arg : tt) +) = > {{ ... }};
104 : : // }
105 : : // ```
106 : : //
107 : : // If more tokens exist beyond the optional comma, they need to be handled as
108 : : // a token-tree for a custom panic message.
109 : : //
110 : : // These builtin macros with empty transcribers are defined in the standard
111 : : // library. They are marked with a special attribute,
112 : : // `#[rustc_builtin_macro]`. When this attribute is present on a macro
113 : : // definition, the compiler should look for an associated transcriber in the
114 : : // mappings. Meaning that you must remember to insert your transcriber in the
115 : : // `builtin_macros` map of the `Mappings`.
116 : : //
117 : : // This map is built as a static variable in the `insert_macro_def()` method
118 : : // of the `Mappings` class.
119 : :
120 : : class MacroBuiltin
121 : : {
122 : : public:
123 : : static const BiMap<std::string, BuiltinMacro> builtins;
124 : : static std::unordered_map<std::string, AST::MacroTranscriberFunc>
125 : : builtin_transcribers;
126 : :
127 : : static tl::optional<AST::Fragment> assert_handler (location_t invoc_locus,
128 : : AST::MacroInvocData &invoc,
129 : : AST::InvocKind semicolon);
130 : :
131 : : static tl::optional<AST::Fragment> file_handler (location_t invoc_locus,
132 : : AST::MacroInvocData &invoc,
133 : : AST::InvocKind semicolon);
134 : :
135 : : static tl::optional<AST::Fragment> column_handler (location_t invoc_locus,
136 : : AST::MacroInvocData &invoc,
137 : : AST::InvocKind semicolon);
138 : :
139 : : static tl::optional<AST::Fragment>
140 : : include_bytes_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
141 : : AST::InvocKind semicolon);
142 : :
143 : : static tl::optional<AST::Fragment>
144 : : include_str_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
145 : : AST::InvocKind semicolon);
146 : :
147 : : static tl::optional<AST::Fragment>
148 : : stringify_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
149 : : AST::InvocKind semicolon);
150 : :
151 : : static tl::optional<AST::Fragment>
152 : : compile_error_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
153 : : AST::InvocKind semicolon);
154 : :
155 : : static tl::optional<AST::Fragment> concat_handler (location_t invoc_locus,
156 : : AST::MacroInvocData &invoc,
157 : : AST::InvocKind semicolon);
158 : :
159 : : static tl::optional<AST::Fragment> env_handler (location_t invoc_locus,
160 : : AST::MacroInvocData &invoc,
161 : : AST::InvocKind semicolon);
162 : :
163 : : static tl::optional<AST::Fragment>
164 : : option_env_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
165 : : AST::InvocKind semicolon);
166 : :
167 : : static tl::optional<AST::Fragment> cfg_handler (location_t invoc_locus,
168 : : AST::MacroInvocData &invoc,
169 : : AST::InvocKind semicolon);
170 : :
171 : : static tl::optional<AST::Fragment>
172 : : include_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
173 : : AST::InvocKind semicolon);
174 : :
175 : : static tl::optional<AST::Fragment> line_handler (location_t invoc_locus,
176 : : AST::MacroInvocData &invoc,
177 : : AST::InvocKind semicolon);
178 : :
179 : : static tl::optional<AST::Fragment> asm_handler (location_t invoc_locus,
180 : : AST::MacroInvocData &invoc,
181 : : AST::InvocKind semicolon,
182 : : AST::AsmKind is_global_asm);
183 : :
184 : : static tl::optional<AST::Fragment>
185 : : llvm_asm_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
186 : : AST::InvocKind semicolon, AST::AsmKind is_global_asm);
187 : :
188 : : static tl::optional<AST::Fragment>
189 : : format_args_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
190 : : AST::InvocKind semicolon, AST::FormatArgs::Newline nl);
191 : :
192 : : static tl::optional<AST::Fragment>
193 : : offset_of_handler (location_t, AST::MacroInvocData &, AST::InvocKind);
194 : :
195 : : static tl::optional<AST::Fragment> sorry (location_t invoc_locus,
196 : : AST::MacroInvocData &invoc,
197 : : AST::InvocKind semicolon);
198 : :
199 : : /* Builtin procedural macros do not work directly on tokens, but still need a
200 : : * builtin transcriber to be considered proper builtin macros */
201 : : static tl::optional<AST::Fragment>
202 : : proc_macro_builtin (location_t, AST::MacroInvocData &, AST::InvocKind);
203 : : };
204 : : } // namespace Rust
205 : :
206 : : namespace std {
207 : : template <> struct hash<Rust::BuiltinMacro>
208 : : {
209 : 506510 : size_t operator() (const Rust::BuiltinMacro ¯o) const noexcept
210 : : {
211 : 506510 : return hash<std::underlying_type<Rust::BuiltinMacro>::type> () (
212 : : static_cast<std::underlying_type<Rust::BuiltinMacro>::type> (macro));
213 : : }
214 : : };
215 : : } // namespace std
216 : :
217 : : #endif // RUST_MACRO_BUILTINS_H
|