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 : 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 533191 : size_t operator() (const Rust::BuiltinMacro ¯o) const noexcept
210 : {
211 533191 : 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
|