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