1use crate::{
2 alt, err, func,
3 lexer::PtxToken,
4 mapc, ok,
5 parser::{
6 ParseErrorKind, PtxParseError, PtxParser, PtxTokenStream, Span,
7 util::{
8 comma_p, directive_exact_p, identifier_p, integer_p, many, optional, parse_u32_literal,
9 parse_u64_literal, sep_by, seq, skip_first, skip_semicolon, string_literal_p, try_map,
10 },
11 },
12 seq_n,
13 r#type::{
14 AliasFunctionDirective, CodeLinkage, DataLinkage, DwarfDirective, EntryFunctionDirective,
15 FuncFunctionDirective, SectionDirective, module::*, variable::ModuleVariableDirective,
16 },
17};
18
19impl PtxParser for Module {
20 fn parse() -> impl Fn(&mut PtxTokenStream) -> Result<(Self, Span), PtxParseError> {
21 mapc!(many(ModuleDirective::parse()), Module { directives })
22 }
23}
24
25impl PtxParser for ModuleDirective {
26 fn parse() -> impl Fn(&mut PtxTokenStream) -> Result<(Self, Span), PtxParseError> {
27 alt!(
28 parse_module_variable(),
29 parse_entry_function(),
30 parse_func_function(),
31 parse_alias_function(),
32 parse_module_info(),
33 parse_module_debug()
34 )
35 }
36}
37
38fn parse_module_variable()
39-> impl Fn(&mut PtxTokenStream) -> Result<(ModuleDirective, Span), PtxParseError> {
40 mapc!(
41 seq(
42 optional(DataLinkage::parse()),
43 ModuleVariableDirective::parse(),
44 ),
45 ModuleDirective::ModuleVariable { linkage, directive }
46 )
47}
48
49fn parse_entry_function()
50-> impl Fn(&mut PtxTokenStream) -> Result<(ModuleDirective, Span), PtxParseError> {
51 mapc!(
52 seq(
53 optional(CodeLinkage::parse()),
54 EntryFunctionDirective::parse(),
55 ),
56 ModuleDirective::EntryFunction { linkage, directive }
57 )
58}
59
60fn parse_func_function()
61-> impl Fn(&mut PtxTokenStream) -> Result<(ModuleDirective, Span), PtxParseError> {
62 mapc!(
63 seq(
64 optional(CodeLinkage::parse()),
65 FuncFunctionDirective::parse(),
66 ),
67 ModuleDirective::FuncFunction { linkage, directive }
68 )
69}
70
71fn parse_alias_function()
72-> impl Fn(&mut PtxTokenStream) -> Result<(ModuleDirective, Span), PtxParseError> {
73 mapc!(
74 AliasFunctionDirective::parse(),
75 ModuleDirective::AliasFunction { directive }
76 )
77}
78
79fn parse_module_info()
80-> impl Fn(&mut PtxTokenStream) -> Result<(ModuleDirective, Span), PtxParseError> {
81 mapc!(
82 ModuleInfoDirectiveKind::parse(),
83 ModuleDirective::ModuleInfo { directive }
84 )
85}
86
87fn parse_module_debug()
88-> impl Fn(&mut PtxTokenStream) -> Result<(ModuleDirective, Span), PtxParseError> {
89 mapc!(
90 ModuleDebugDirective::parse(),
91 ModuleDirective::Debug { directive }
92 )
93}
94
95impl PtxParser for ModuleInfoDirectiveKind {
96 fn parse() -> impl Fn(&mut PtxTokenStream) -> Result<(Self, Span), PtxParseError> {
97 alt!(
98 mapc!(
99 VersionDirective::parse(),
100 ModuleInfoDirectiveKind::Version { directive }
101 ),
102 mapc!(
103 TargetDirective::parse(),
104 ModuleInfoDirectiveKind::Target { directive }
105 ),
106 mapc!(
107 AddressSizeDirective::parse(),
108 ModuleInfoDirectiveKind::AddressSize { directive }
109 )
110 )
111 }
112}
113
114impl PtxParser for VersionDirective {
115 fn parse() -> impl Fn(&mut PtxTokenStream) -> Result<(Self, Span), PtxParseError> {
116 try_map(
117 skip_first(directive_exact_p("version"), version_number_p()),
118 func!(|(major, minor)| { ok!(VersionDirective { major, minor }) }),
119 )
120 }
121}
122
123impl PtxParser for TargetDirective {
124 fn parse() -> impl Fn(&mut PtxTokenStream) -> Result<(Self, Span), PtxParseError> {
125 mapc!(
126 skip_first(
127 directive_exact_p("target"),
128 sep_by(TargetString::parse(), comma_p()),
129 ),
130 TargetDirective { entries }
131 )
132 }
133}
134
135impl PtxParser for TargetString {
136 fn parse() -> impl Fn(&mut PtxTokenStream) -> Result<(Self, Span), PtxParseError> {
137 try_map(
139 identifier_p(),
140 func!(|name| match name.as_str() {
141 "sm_120a" => ok!(TargetString::Sm120a),
142 "sm_120f" => ok!(TargetString::Sm120f),
143 "sm_120" => ok!(TargetString::Sm120),
144 "sm_121a" => ok!(TargetString::Sm121a),
145 "sm_121f" => ok!(TargetString::Sm121f),
146 "sm_121" => ok!(TargetString::Sm121),
147 "sm_110a" => ok!(TargetString::Sm110a),
148 "sm_110f" => ok!(TargetString::Sm110f),
149 "sm_110" => ok!(TargetString::Sm110),
150 "sm_100a" => ok!(TargetString::Sm100a),
151 "sm_100f" => ok!(TargetString::Sm100f),
152 "sm_100" => ok!(TargetString::Sm100),
153 "sm_101a" => ok!(TargetString::Sm101a),
154 "sm_101f" => ok!(TargetString::Sm101f),
155 "sm_101" => ok!(TargetString::Sm101),
156 "sm_103a" => ok!(TargetString::Sm103a),
157 "sm_103f" => ok!(TargetString::Sm103f),
158 "sm_103" => ok!(TargetString::Sm103),
159 "sm_90a" => ok!(TargetString::Sm90a),
160 "sm_90" => ok!(TargetString::Sm90),
161 "sm_80" => ok!(TargetString::Sm80),
162 "sm_86" => ok!(TargetString::Sm86),
163 "sm_87" => ok!(TargetString::Sm87),
164 "sm_88" => ok!(TargetString::Sm88),
165 "sm_89" => ok!(TargetString::Sm89),
166 "sm_70" => ok!(TargetString::Sm70),
167 "sm_72" => ok!(TargetString::Sm72),
168 "sm_75" => ok!(TargetString::Sm75),
169 "sm_60" => ok!(TargetString::Sm60),
170 "sm_61" => ok!(TargetString::Sm61),
171 "sm_62" => ok!(TargetString::Sm62),
172 "sm_50" => ok!(TargetString::Sm50),
173 "sm_52" => ok!(TargetString::Sm52),
174 "sm_53" => ok!(TargetString::Sm53),
175 "sm_30" => ok!(TargetString::Sm30),
176 "sm_32" => ok!(TargetString::Sm32),
177 "sm_35" => ok!(TargetString::Sm35),
178 "sm_37" => ok!(TargetString::Sm37),
179 "sm_20" => ok!(TargetString::Sm20),
180 "sm_10" => ok!(TargetString::Sm10),
181 "sm_11" => ok!(TargetString::Sm11),
182 "sm_12" => ok!(TargetString::Sm12),
183 "sm_13" => ok!(TargetString::Sm13),
184 "texmode_unified" => ok!(TargetString::TexmodeUnified),
185 "texmode_independent" => ok!(TargetString::TexmodeIndependent),
186 "debug" => ok!(TargetString::Debug),
187 "map_f64_to_f32" => ok!(TargetString::MapF64ToF32),
188 _ => err!(ParseErrorKind::InvalidLiteral(format!(
189 "unknown target specifier: {}",
190 name
191 ))),
192 }),
193 )
194 }
195}
196
197impl PtxParser for AddressSizeDirective {
198 fn parse() -> impl Fn(&mut PtxTokenStream) -> Result<(Self, Span), PtxParseError> {
199 mapc!(
200 skip_first(directive_exact_p("address_size"), AddressSize::parse()),
201 AddressSizeDirective { size }
202 )
203 }
204}
205
206impl PtxParser for ModuleDebugDirective {
207 fn parse() -> impl Fn(&mut PtxTokenStream) -> Result<(Self, Span), PtxParseError> {
208 alt!(
209 mapc!(
210 FileDirective::parse(),
211 ModuleDebugDirective::File { directive }
212 ),
213 mapc!(
214 SectionDirective::parse(),
215 ModuleDebugDirective::Section { directive }
216 ),
217 mapc!(
218 skip_semicolon(DwarfDirective::parse()),
219 ModuleDebugDirective::Dwarf { directive }
220 )
221 )
222 }
223}
224
225impl PtxParser for FileDirective {
226 fn parse() -> impl Fn(&mut PtxTokenStream) -> Result<(Self, Span), PtxParseError> {
227 try_map(
228 skip_first(
229 directive_exact_p("file"),
230 seq_n!(
231 integer_p(),
232 string_literal_p(),
233 optional(skip_first(
234 comma_p(),
235 seq(integer_p(), skip_first(comma_p(), integer_p())),
236 )),
237 ),
238 ),
239 |(index_str, path, maybe_timestamps), span| {
240 let index = parse_u32_literal(&index_str, span)?;
241 let (timestamp, file_size) = if let Some((ts_str, size_str)) = maybe_timestamps {
242 let ts = parse_u64_literal(&ts_str, span)?;
243 let size = parse_u64_literal(&size_str, span)?;
244 (Some(ts), Some(size))
245 } else {
246 (None, None)
247 };
248 ok!(FileDirective {
249 index,
250 path,
251 timestamp,
252 file_size,
253 })
254 },
255 )
256 }
257}
258
259impl PtxParser for AddressSize {
260 fn parse() -> impl Fn(&mut PtxTokenStream) -> Result<(Self, Span), PtxParseError> {
261 try_map(
262 integer_p(),
263 func!(|value| match value.as_str() {
264 "32" => ok!(AddressSize::Size32),
265 "64" => ok!(AddressSize::Size64),
266 _ => err!(ParseErrorKind::InvalidLiteral(format!(
267 "invalid address size: {} (expected 32 or 64)",
268 value
269 ))),
270 }),
271 )
272 }
273}
274
275fn version_number_p() -> impl Fn(&mut PtxTokenStream) -> Result<((u32, u32), Span), PtxParseError> {
277 |stream| {
278 let start_pos = stream.position().0;
279
280 if let Ok((token, span)) = stream.peek() {
282 if let PtxToken::Float(f) = token {
283 let version_str = f.clone();
284 stream.consume()?;
285 let end_pos = stream.position().0;
286 let full_span = Span::new(start_pos, end_pos);
287 let parts: Vec<&str> = version_str.split('.').collect();
288 let span = span.clone();
289 if parts.len() != 2 {
290 return err!(ParseErrorKind::InvalidLiteral(format!(
291 "expected version in format X.Y, got {}",
292 version_str
293 )));
294 }
295 let major = parse_u32_literal(parts[0], span)?;
296 let minor = parse_u32_literal(parts[1], span)?;
297 return Ok(((major, minor), full_span));
298 }
299 }
300
301 let (major_str, major_span) = integer_p()(stream)?;
303 stream.expect(&PtxToken::Dot)?;
304 let (minor_str, minor_span) = integer_p()(stream)?;
305
306 let end_pos = stream.position().0;
307 let span = Span::new(start_pos, end_pos);
308 let major = parse_u32_literal(&major_str, major_span)?;
309 let minor = parse_u32_literal(&minor_str, minor_span)?;
310 Ok(((major, minor), span))
311 }
312}