Line data Source code
1 : // Copyright (C) 2020-2026 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 : CfgSelect,
53 : Include,
54 : FormatArgs,
55 : FormatArgsNl,
56 : ConcatIdents,
57 : ModulePath,
58 : Asm,
59 : LlvmAsm,
60 : GlobalAsm,
61 : LogSyntax,
62 : TraceMacros,
63 : Test,
64 : Bench,
65 : TestCase,
66 : GlobalAllocator,
67 : CfgAccessible,
68 : RustcDecodable,
69 : RustcEncodable,
70 : Clone,
71 : Copy,
72 : Debug,
73 : Default,
74 : Eq,
75 : PartialEq,
76 : Ord,
77 : PartialOrd,
78 : Hash,
79 : CoercePointee,
80 : };
81 :
82 : tl::optional<BuiltinMacro>
83 : builtin_macro_from_string (const std::string &identifier);
84 :
85 : //
86 : // This class provides a list of builtin macros implemented by the compiler.
87 : // The functions defined are called "builtin transcribers" in that they
88 : // replace the transcribing part of a macro definition.
89 : //
90 : // Like regular macro transcribers, they are responsible for building and
91 : // returning an AST fragment: basically a vector of AST nodes put together.
92 : //
93 : // Unlike regular declarative macros where each match arm has its own
94 : // associated transcriber, builtin transcribers are responsible for handling
95 : // all match arms of the macro. This means that you should take extra care
96 : // when implementing a builtin containing multiple match arms: You will
97 : // probably need to do some lookahead in order to determine which match arm
98 : // the user intended to use.
99 : //
100 : // An example of this is the `assert!()` macro:
101 : //
102 : // ```
103 : // macro_rules! assert {
104 : // ($cond:expr $(,)?) => {{ ... }};
105 : // ($cond : expr, $ ($arg : tt) +) = > {{ ... }};
106 : // }
107 : // ```
108 : //
109 : // If more tokens exist beyond the optional comma, they need to be handled as
110 : // a token-tree for a custom panic message.
111 : //
112 : // These builtin macros with empty transcribers are defined in the standard
113 : // library. They are marked with a special attribute,
114 : // `#[rustc_builtin_macro]`. When this attribute is present on a macro
115 : // definition, the compiler should look for an associated transcriber in the
116 : // mappings. Meaning that you must remember to insert your transcriber in the
117 : // `builtin_macros` map of the `Mappings`.
118 : //
119 : // This map is built as a static variable in the `insert_macro_def()` method
120 : // of the `Mappings` class.
121 :
122 : class MacroBuiltin
123 : {
124 : public:
125 : static const BiMap<std::string, BuiltinMacro> builtins;
126 : static std::unordered_map<std::string, AST::MacroTranscriberFunc>
127 : builtin_transcribers;
128 :
129 : static tl::optional<AST::Fragment> assert_handler (location_t invoc_locus,
130 : AST::MacroInvocData &invoc,
131 : AST::InvocKind semicolon);
132 :
133 : static tl::optional<AST::Fragment> file_handler (location_t invoc_locus,
134 : AST::MacroInvocData &invoc,
135 : AST::InvocKind semicolon);
136 :
137 : static tl::optional<AST::Fragment> column_handler (location_t invoc_locus,
138 : AST::MacroInvocData &invoc,
139 : AST::InvocKind semicolon);
140 :
141 : static tl::optional<AST::Fragment>
142 : include_bytes_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
143 : AST::InvocKind semicolon);
144 :
145 : static tl::optional<AST::Fragment>
146 : include_str_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
147 : AST::InvocKind semicolon);
148 :
149 : static tl::optional<AST::Fragment>
150 : stringify_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
151 : AST::InvocKind semicolon);
152 :
153 : static tl::optional<AST::Fragment>
154 : compile_error_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
155 : AST::InvocKind semicolon);
156 :
157 : static tl::optional<AST::Fragment> concat_handler (location_t invoc_locus,
158 : AST::MacroInvocData &invoc,
159 : AST::InvocKind semicolon);
160 :
161 : static tl::optional<AST::Fragment> env_handler (location_t invoc_locus,
162 : AST::MacroInvocData &invoc,
163 : AST::InvocKind semicolon);
164 :
165 : static tl::optional<AST::Fragment>
166 : option_env_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
167 : AST::InvocKind semicolon);
168 :
169 : static tl::optional<AST::Fragment> cfg_handler (location_t invoc_locus,
170 : AST::MacroInvocData &invoc,
171 : AST::InvocKind semicolon);
172 :
173 : static tl::optional<AST::Fragment>
174 : cfg_select_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
175 : AST::InvocKind semicolon);
176 :
177 : static tl::optional<AST::Fragment>
178 : include_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
179 : AST::InvocKind semicolon);
180 :
181 : static tl::optional<AST::Fragment> line_handler (location_t invoc_locus,
182 : AST::MacroInvocData &invoc,
183 : AST::InvocKind semicolon);
184 :
185 : static tl::optional<AST::Fragment> asm_handler (location_t invoc_locus,
186 : AST::MacroInvocData &invoc,
187 : AST::InvocKind semicolon,
188 : AST::AsmKind is_global_asm);
189 :
190 : static tl::optional<AST::Fragment>
191 : llvm_asm_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
192 : AST::InvocKind semicolon, AST::AsmKind is_global_asm);
193 :
194 : static tl::optional<AST::Fragment>
195 : format_args_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
196 : AST::InvocKind semicolon, AST::FormatArgs::Newline nl);
197 :
198 : static tl::optional<AST::Fragment>
199 : offset_of_handler (location_t, AST::MacroInvocData &, AST::InvocKind);
200 :
201 : static tl::optional<AST::Fragment> sorry (location_t invoc_locus,
202 : AST::MacroInvocData &invoc,
203 : AST::InvocKind semicolon);
204 :
205 : /* Builtin procedural macros do not work directly on tokens, but still need a
206 : * builtin transcriber to be considered proper builtin macros */
207 : static tl::optional<AST::Fragment>
208 : proc_macro_builtin (location_t, AST::MacroInvocData &, AST::InvocKind);
209 : };
210 : } // namespace Rust
211 :
212 : namespace std {
213 : template <> struct hash<Rust::BuiltinMacro>
214 : {
215 619226 : size_t operator() (const Rust::BuiltinMacro ¯o) const noexcept
216 : {
217 619226 : return hash<std::underlying_type<Rust::BuiltinMacro>::type> () (
218 : static_cast<std::underlying_type<Rust::BuiltinMacro>::type> (macro));
219 : }
220 : };
221 : } // namespace std
222 :
223 : #endif // RUST_MACRO_BUILTINS_H
|