1use std::borrow::Cow;
2
3use crate::{
4 lexer::PtxToken,
5 parser::{ParseErrorKind, PtxParseError, PtxParser, PtxTokenStream, Span},
6 r#type::common::*,
7};
8
9pub(crate) fn unexpected_value(
10 span: Span,
11 expected: &[&str],
12 found: impl Into<Cow<'static, str>>,
13) -> PtxParseError {
14 PtxParseError {
15 kind: ParseErrorKind::UnexpectedToken {
16 expected: expected.iter().map(|s| s.to_string()).collect(),
17 found: found.into().to_string(),
18 },
19 span,
20 }
21}
22
23pub(crate) fn invalid_literal(span: Span, literal: impl Into<Cow<'static, str>>) -> PtxParseError {
24 PtxParseError {
25 kind: ParseErrorKind::InvalidLiteral(literal.into().to_string()),
26 span,
27 }
28}
29
30pub(crate) fn parse_register_name(
31 stream: &mut PtxTokenStream,
32) -> Result<(String, Span), PtxParseError> {
33 let (mut name, mut span) = stream.expect_register()?;
34
35 loop {
36 let next = match stream.peek() {
38 Ok((token, _)) => token,
39 Err(_) => break,
40 };
41
42 match next {
43 PtxToken::Dot => {
44 if let Some((PtxToken::Identifier(component_name), _)) =
46 stream.tokens.get(stream.index + 1)
47 {
48 if matches!(component_name.as_str(), "x" | "y" | "z" | "w" | "r" | "g" | "b" | "a") {
51 stream.consume()?;
53 let (component, component_span) = stream.expect_identifier()?;
54
55 name.push('.');
56 name.push_str(&component);
57
58 span.end = component_span.end;
59 } else {
60 break;
62 }
63 } else {
64 break;
65 }
66 }
67 _ => break,
68 }
69 }
70
71 Ok((name, span))
72}
73
74pub(crate) fn numeric_literal(token: &PtxToken) -> Option<&String> {
75 match token {
76 PtxToken::DecimalInteger(value)
77 | PtxToken::HexInteger(value)
78 | PtxToken::BinaryInteger(value)
79 | PtxToken::OctalInteger(value)
80 | PtxToken::FloatExponent(value)
81 | PtxToken::Float(value)
82 | PtxToken::HexFloat(value) => Some(value),
83 _ => None,
84 }
85}
86
87pub(crate) fn is_numeric_token(token: &PtxToken) -> bool {
88 numeric_literal(token).is_some()
89}
90
91pub(crate) fn parse_u64_literal(stream: &mut PtxTokenStream) -> Result<(u64, Span), PtxParseError> {
92 let (token, span) = stream.consume()?;
93 let span = span.clone();
94
95 let value = match token {
96 PtxToken::DecimalInteger(text) => text
97 .parse::<u64>()
98 .map_err(|_| invalid_literal(span.clone(), text.clone()))?,
99 PtxToken::HexInteger(text) => {
100 let stripped = text
101 .strip_prefix("0x")
102 .or_else(|| text.strip_prefix("0X"))
103 .ok_or_else(|| invalid_literal(span.clone(), text.clone()))?;
104 u64::from_str_radix(stripped, 16)
105 .map_err(|_| invalid_literal(span.clone(), text.clone()))?
106 }
107 PtxToken::BinaryInteger(text) => {
108 let stripped = text
109 .strip_prefix("0b")
110 .or_else(|| text.strip_prefix("0B"))
111 .ok_or_else(|| invalid_literal(span.clone(), text.clone()))?;
112 u64::from_str_radix(stripped, 2)
113 .map_err(|_| invalid_literal(span.clone(), text.clone()))?
114 }
115 PtxToken::OctalInteger(text) => {
116 let stripped = &text[1..];
117 u64::from_str_radix(stripped, 8)
118 .map_err(|_| invalid_literal(span.clone(), text.clone()))?
119 }
120 _ => {
121 return Err(unexpected_value(
122 span,
123 &["unsigned integer literal"],
124 format!("{token:?}"),
125 ));
126 }
127 };
128
129 Ok((value, span))
130}
131
132impl PtxParser for CodeLinkage {
133 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
134 let (directive, span) = stream.expect_directive()?;
135 match directive.as_str() {
136 "visible" => Ok(CodeLinkage::Visible),
137 "extern" => Ok(CodeLinkage::Extern),
138 "weak" => Ok(CodeLinkage::Weak),
139 other => Err(unexpected_value(
140 span,
141 &[".visible", ".extern", ".weak"],
142 format!(".{other}"),
143 )),
144 }
145 }
146}
147
148impl PtxParser for DataLinkage {
149 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
150 let (directive, span) = stream.expect_directive()?;
151 match directive.as_str() {
152 "visible" => Ok(DataLinkage::Visible),
153 "extern" => Ok(DataLinkage::Extern),
154 "weak" => Ok(DataLinkage::Weak),
155 "common" => Ok(DataLinkage::Common),
156 other => Err(unexpected_value(
157 span,
158 &[".visible", ".extern", ".weak", ".common"],
159 format!(".{other}"),
160 )),
161 }
162 }
163}
164
165impl PtxParser for CodeOrDataLinkage {
166 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
167 let (directive, span) = stream.expect_directive()?;
168 match directive.as_str() {
169 "visible" => Ok(CodeOrDataLinkage::Visible),
170 "extern" => Ok(CodeOrDataLinkage::Extern),
171 "weak" => Ok(CodeOrDataLinkage::Weak),
172 "common" => Ok(CodeOrDataLinkage::Common),
173 other => Err(unexpected_value(
174 span,
175 &[".visible", ".extern", ".weak", ".common"],
176 format!(".{other}"),
177 )),
178 }
179 }
180}
181
182impl PtxParser for TexType {
183 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
184 let (directive, span) = stream.expect_directive()?;
185 match directive.as_str() {
186 "texref" => Ok(TexType::TexRef),
187 "samplerref" => Ok(TexType::SamplerRef),
188 "surfref" => Ok(TexType::SurfRef),
189 other => Err(unexpected_value(
190 span,
191 &[".texref", ".samplerref", ".surfref"],
192 format!(".{other}"),
193 )),
194 }
195 }
196}
197
198impl PtxParser for AddressSpace {
199 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
200 let (directive, span) = stream.expect_directive()?;
201 match directive.as_str() {
202 "global" => Ok(AddressSpace::Global),
203 "const" => Ok(AddressSpace::Const),
204 "shared" => Ok(AddressSpace::Shared),
205 "local" => Ok(AddressSpace::Local),
206 "param" => Ok(AddressSpace::Param),
207 "reg" => Ok(AddressSpace::Reg),
208 other => Err(unexpected_value(
209 span,
210 &[".global", ".const", ".shared", ".local", ".param", ".reg"],
211 format!(".{other}"),
212 )),
213 }
214 }
215}
216
217impl PtxParser for AttributeDirective {
218 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
219 let (directive, span) = stream.expect_directive()?;
220 match directive.as_str() {
221 "unified" => {
222 stream.expect(&PtxToken::LParen)?;
223 let (uuid1, _) = parse_u64_literal(stream)?;
224 stream.expect(&PtxToken::Comma)?;
225 let (uuid2, _) = parse_u64_literal(stream)?;
226 stream.expect(&PtxToken::RParen)?;
227 Ok(AttributeDirective::Unified(uuid1, uuid2))
228 }
229 "managed" => Ok(AttributeDirective::Managed),
230 other => Err(unexpected_value(
231 span,
232 &[".unified", ".managed"],
233 format!(".{other}"),
234 )),
235 }
236 }
237}
238
239impl PtxParser for DataType {
240 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
241 let (directive, span) = stream.expect_directive()?;
242 match directive.as_str() {
243 "u8" => Ok(DataType::U8),
244 "u16" => Ok(DataType::U16),
245 "u32" => Ok(DataType::U32),
246 "u64" => Ok(DataType::U64),
247 "s8" => Ok(DataType::S8),
248 "s16" => Ok(DataType::S16),
249 "s32" => Ok(DataType::S32),
250 "s64" => Ok(DataType::S64),
251 "f16" => Ok(DataType::F16),
252 "f16x2" => Ok(DataType::F16x2),
253 "f32" => Ok(DataType::F32),
254 "f64" => Ok(DataType::F64),
255 "b8" => Ok(DataType::B8),
256 "b16" => Ok(DataType::B16),
257 "b32" => Ok(DataType::B32),
258 "b64" => Ok(DataType::B64),
259 "b128" => Ok(DataType::B128),
260 "pred" => Ok(DataType::Pred),
261 other => Err(unexpected_value(
262 span,
263 &[
264 ".u8", ".u16", ".u32", ".u64", ".s8", ".s16", ".s32", ".s64", ".f16", ".f16x2",
265 ".f32", ".f64", ".b8", ".b16", ".b32", ".b64", ".b128", ".pred",
266 ],
267 format!(".{other}"),
268 )),
269 }
270 }
271}
272
273impl PtxParser for Sign {
274 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
275 if stream
276 .consume_if(|token| matches!(token, PtxToken::Plus))
277 .is_some()
278 {
279 return Ok(Sign::Positive);
280 }
281 if stream
282 .consume_if(|token| matches!(token, PtxToken::Minus))
283 .is_some()
284 {
285 return Ok(Sign::Negative);
286 }
287
288 let (token, span) = stream.peek()?;
289 Err(unexpected_value(
290 span.clone(),
291 &["+", "-"],
292 format!("{token:?}"),
293 ))
294 }
295}
296
297impl PtxParser for Immediate {
298 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
299 let has_minus = stream
301 .consume_if(|token| matches!(token, PtxToken::Minus))
302 .is_some();
303
304 let (token, span) = stream.peek()?;
305 let value = numeric_literal(token).cloned();
306 match value {
307 Some(value) => {
308 let literal = if has_minus {
309 format!("-{}", value)
310 } else {
311 value.clone()
312 };
313 stream.consume()?;
314 Ok(Immediate(literal))
315 }
316 None => {
317 if has_minus {
319 let mut current_pos = stream.position();
320 if current_pos.index > 0 {
321 current_pos.index -= 1;
322 current_pos.char_offset = 0;
323 stream.set_position(current_pos);
324 }
325 }
326 Err(unexpected_value(
327 span.clone(),
328 &["numeric literal"],
329 format!("{token:?}"),
330 ))
331 }
332 }
333 }
334}
335
336impl PtxParser for RegisterOperand {
337 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
338 if !stream.check(|token| matches!(token, PtxToken::Register(_))) {
339 let (token, span) = stream.peek()?;
340 return Err(unexpected_value(
341 span.clone(),
342 &["register"],
343 format!("{token:?}"),
344 ));
345 }
346 let (name, _) = parse_register_name(stream)?;
347 Ok(RegisterOperand(name))
348 }
349}
350
351impl PtxParser for PredicateRegister {
352 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
353 let (name, span) = parse_register_name(stream)?;
354 if name.starts_with("%p") {
355 Ok(PredicateRegister(name))
356 } else {
357 Err(invalid_literal(
358 span,
359 format!("expected predicate register starting with %p, found {name}"),
360 ))
361 }
362 }
363}
364
365impl PtxParser for Label {
366 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
367 let (name, _) = stream.expect_identifier()?;
368 Ok(Label(name))
369 }
370}
371
372impl PtxParser for SpecialRegister {
373 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
374 let (name, span) = parse_register_name(stream)?;
375 let name_str = name.as_str();
379 if let Some(rest) = name_str.strip_prefix("%cluster_ctaid") {
380 if rest.is_empty() {
381 return Ok(SpecialRegister::ClusterCtaid(Axis::None));
382 } else if rest == ".x" {
383 return Ok(SpecialRegister::ClusterCtaid(Axis::X));
384 } else if rest == ".y" {
385 return Ok(SpecialRegister::ClusterCtaid(Axis::Y));
386 } else if rest == ".z" {
387 return Ok(SpecialRegister::ClusterCtaid(Axis::Z));
388 }
389 }
390 if let Some(rest) = name_str.strip_prefix("%cluster_ctarank") {
391 if rest.is_empty() {
392 return Ok(SpecialRegister::ClusterCtarank(Axis::None));
393 } else if rest == ".x" {
394 return Ok(SpecialRegister::ClusterCtarank(Axis::X));
395 } else if rest == ".y" {
396 return Ok(SpecialRegister::ClusterCtarank(Axis::Y));
397 } else if rest == ".z" {
398 return Ok(SpecialRegister::ClusterCtarank(Axis::Z));
399 }
400 }
401 if let Some(rest) = name_str.strip_prefix("%nctaid") {
402 if rest.is_empty() {
403 return Ok(SpecialRegister::Nctaid(Axis::None));
404 } else if rest == ".x" {
405 return Ok(SpecialRegister::Nctaid(Axis::X));
406 } else if rest == ".y" {
407 return Ok(SpecialRegister::Nctaid(Axis::Y));
408 } else if rest == ".z" {
409 return Ok(SpecialRegister::Nctaid(Axis::Z));
410 }
411 }
412 if let Some(rest) = name_str.strip_prefix("%tid") {
413 if rest.is_empty() {
414 return Ok(SpecialRegister::Tid(Axis::None));
415 } else if rest == ".x" {
416 return Ok(SpecialRegister::Tid(Axis::X));
417 } else if rest == ".y" {
418 return Ok(SpecialRegister::Tid(Axis::Y));
419 } else if rest == ".z" {
420 return Ok(SpecialRegister::Tid(Axis::Z));
421 }
422 }
423 if let Some(rest) = name_str.strip_prefix("%cluster_nctaid") {
424 if rest.is_empty() {
425 return Ok(SpecialRegister::ClusterNctaid(Axis::None));
426 } else if rest == ".x" {
427 return Ok(SpecialRegister::ClusterNctaid(Axis::X));
428 } else if rest == ".y" {
429 return Ok(SpecialRegister::ClusterNctaid(Axis::Y));
430 } else if rest == ".z" {
431 return Ok(SpecialRegister::ClusterNctaid(Axis::Z));
432 }
433 }
434 if let Some(rest) = name_str.strip_prefix("%cluster_nctarank") {
435 if rest.is_empty() {
436 return Ok(SpecialRegister::ClusterNctarank(Axis::None));
437 } else if rest == ".x" {
438 return Ok(SpecialRegister::ClusterNctarank(Axis::X));
439 } else if rest == ".y" {
440 return Ok(SpecialRegister::ClusterNctarank(Axis::Y));
441 } else if rest == ".z" {
442 return Ok(SpecialRegister::ClusterNctarank(Axis::Z));
443 }
444 }
445 if let Some(rest) = name_str.strip_prefix("%ntid") {
446 if rest.is_empty() {
447 return Ok(SpecialRegister::Ntid(Axis::None));
448 } else if rest == ".x" {
449 return Ok(SpecialRegister::Ntid(Axis::X));
450 } else if rest == ".y" {
451 return Ok(SpecialRegister::Ntid(Axis::Y));
452 } else if rest == ".z" {
453 return Ok(SpecialRegister::Ntid(Axis::Z));
454 }
455 }
456 if let Some(rest) = name_str.strip_prefix("%ctaid") {
457 if rest.is_empty() {
458 return Ok(SpecialRegister::Ctaid(Axis::None));
459 } else if rest == ".x" {
460 return Ok(SpecialRegister::Ctaid(Axis::X));
461 } else if rest == ".y" {
462 return Ok(SpecialRegister::Ctaid(Axis::Y));
463 } else if rest == ".z" {
464 return Ok(SpecialRegister::Ctaid(Axis::Z));
465 }
466 }
467
468 match name.as_str() {
469 "%aggr_smem_size" => Ok(SpecialRegister::AggrSmemSize),
470 "%dynamic_smem_size" => Ok(SpecialRegister::DynamicSmemSize),
471 "%lanemask_gt" => Ok(SpecialRegister::LanemaskGt),
472 "%reserved_smem_offset_begin" => Ok(SpecialRegister::ReservedSmemOffsetBegin),
473 "%clock" => Ok(SpecialRegister::Clock),
474 "%lanemask_le" => Ok(SpecialRegister::LanemaskLe),
475 "%reserved_smem_offset_cap" => Ok(SpecialRegister::ReservedSmemOffsetCap),
476 "%clock64" => Ok(SpecialRegister::Clock64),
477 "%globaltimer" => Ok(SpecialRegister::Globaltimer),
478 "%lanemask_lt" => Ok(SpecialRegister::LanemaskLt),
479 "%reserved_smem_offset_end" => Ok(SpecialRegister::ReservedSmemOffsetEnd),
480 "%cluster_ctaid" | "%cluster_ctaid.x" | "%cluster_ctaid.y" | "%cluster_ctaid.z" => {
481 Ok(SpecialRegister::ClusterCtaid(Axis::None))
482 }
483 "%globaltimer_hi" => Ok(SpecialRegister::GlobaltimerHi),
484 "%nclusterid" => Ok(SpecialRegister::Nclusterid),
485 "%smid" => Ok(SpecialRegister::Smid),
486 "%cluster_ctarank" | "%cluster_ctarank.x" | "%cluster_ctarank.y"
487 | "%cluster_ctarank.z" => Ok(SpecialRegister::ClusterCtarank(Axis::None)),
488 "%globaltimer_lo" => Ok(SpecialRegister::GlobaltimerLo),
489 "%nctaid" | "%nctaid.x" | "%nctaid.y" | "%nctaid.z" => {
490 Ok(SpecialRegister::Nctaid(Axis::None))
491 }
492 "%tid" | "%tid.x" | "%tid.y" | "%tid.z" => Ok(SpecialRegister::Tid(Axis::None)),
493 "%cluster_nctaid" | "%cluster_nctaid.x" | "%cluster_nctaid.y" | "%cluster_nctaid.z" => {
494 Ok(SpecialRegister::ClusterNctaid(Axis::None))
495 }
496 "%gridid" => Ok(SpecialRegister::Gridid),
497 "%nsmid" => Ok(SpecialRegister::Nsmid),
498 "%total_smem_size" => Ok(SpecialRegister::TotalSmemSize),
499 "%cluster_nctarank"
500 | "%cluster_nctarank.x"
501 | "%cluster_nctarank.y"
502 | "%cluster_nctarank.z" => Ok(SpecialRegister::ClusterNctarank(Axis::None)),
503 "%is_explicit_cluster" => Ok(SpecialRegister::IsExplicitCluster),
504 "%ntid" | "%ntid.x" | "%ntid.y" | "%ntid.z" => Ok(SpecialRegister::Ntid(Axis::None)),
505 "%warpid" => Ok(SpecialRegister::Warpid),
506 "%clusterid" => Ok(SpecialRegister::Clusterid),
507 "%laneid" => Ok(SpecialRegister::Laneid),
508 "%nwarpid" => Ok(SpecialRegister::Nwarpid),
509 "%WARPSZ" => Ok(SpecialRegister::WARPSZ),
510 "%ctaid" | "%ctaid.x" | "%ctaid.y" | "%ctaid.z" => {
511 Ok(SpecialRegister::Ctaid(Axis::None))
512 }
513 "%lanemask_eq" => Ok(SpecialRegister::LanemaskEq),
514 "%current_graph_exec" => Ok(SpecialRegister::CurrentGraphExec),
515 "%lanemask_ge" => Ok(SpecialRegister::LanemaskGe),
516 other => {
517 if let Some(num) = other.strip_prefix("%envreg") {
518 let value = num
519 .parse::<u8>()
520 .map_err(|_| invalid_literal(span.clone(), name.clone()))?;
521 if value <= 31 {
522 return Ok(SpecialRegister::Envreg(value));
523 }
524 return Err(invalid_literal(
525 span,
526 format!("envreg index out of range: {value}"),
527 ));
528 }
529
530 if let Some(num) = other.strip_prefix("%pm") {
531 if let Some(rest) = num.strip_suffix("_64") {
532 let value = rest
533 .parse::<u8>()
534 .map_err(|_| invalid_literal(span.clone(), name.clone()))?;
535 if value <= 7 {
536 return Ok(SpecialRegister::Pm64(value));
537 }
538 return Err(invalid_literal(
539 span,
540 format!("pm index out of range: {value}"),
541 ));
542 }
543
544 let value = num
545 .parse::<u8>()
546 .map_err(|_| invalid_literal(span.clone(), name.clone()))?;
547 if value <= 7 {
548 return Ok(SpecialRegister::Pm(value));
549 }
550 return Err(invalid_literal(
551 span,
552 format!("pm index out of range: {value}"),
553 ));
554 }
555
556 if let Some(num) = other.strip_prefix("%reserved_smem_offset_") {
557 let value = num
558 .parse::<u8>()
559 .map_err(|_| invalid_literal(span.clone(), name.clone()))?;
560 if value <= 1 {
561 return Ok(SpecialRegister::ReservedSmemOffset(value));
562 }
563 return Err(invalid_literal(
564 span,
565 format!("reserved_smem_offset index out of range: {value}"),
566 ));
567 }
568
569 Err(invalid_literal(
570 span,
571 format!("unknown special register {name}"),
572 ))
573 }
574 }
575 }
576}
577
578impl PtxParser for Operand {
579 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
580 let saved_pos = stream.position();
581 if let Ok(immediate) = Immediate::parse(stream) {
582 return Ok(Operand::Immediate(immediate));
583 }
584 stream.set_position(saved_pos);
585
586 if stream.check(|token| matches!(token, PtxToken::Register(_))) {
587 return Ok(Operand::Register(RegisterOperand::parse(stream)?));
588 }
589
590 if stream.check(|token| matches!(token, PtxToken::Identifier(_))) {
591 let (identifier, _) = stream.expect_identifier()?;
592
593 let saved_pos_after_ident = stream.position();
595 if stream.expect(&PtxToken::Plus).is_ok() {
596 if let Ok(offset) = Immediate::parse(stream) {
597 return Ok(Operand::SymbolOffset(identifier, offset));
598 }
599 stream.set_position(saved_pos_after_ident);
601 }
602
603 return Ok(Operand::Symbol(identifier));
604 }
605
606 let (token, span) = stream.peek()?;
607 Err(unexpected_value(
608 span.clone(),
609 &["operand"],
610 format!("{token:?}"),
611 ))
612 }
613}
614
615impl PtxParser for VectorOperand {
616 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
617 let (_, brace_span) = stream.expect(&PtxToken::LBrace)?;
618 let mut operands = Vec::new();
619
620 loop {
621 operands.push(Operand::parse(stream)?);
622 if stream
623 .consume_if(|token| matches!(token, PtxToken::Comma))
624 .is_some()
625 {
626 continue;
627 }
628 break;
629 }
630
631 stream.expect(&PtxToken::RBrace)?;
632
633 match operands.len() {
634 1 => Ok(VectorOperand::Vector1(operands.remove(0))),
635 2 => Ok(VectorOperand::Vector2([
636 operands.remove(0),
637 operands.remove(0),
638 ])),
639 3 => Ok(VectorOperand::Vector3([
640 operands.remove(0),
641 operands.remove(0),
642 operands.remove(0),
643 ])),
644 4 => Ok(VectorOperand::Vector4([
645 operands.remove(0),
646 operands.remove(0),
647 operands.remove(0),
648 operands.remove(0),
649 ])),
650 8 => Ok(VectorOperand::Vector8([
651 operands.remove(0),
652 operands.remove(0),
653 operands.remove(0),
654 operands.remove(0),
655 operands.remove(0),
656 operands.remove(0),
657 operands.remove(0),
658 operands.remove(0),
659 ])),
660 other => Err(invalid_literal(
661 brace_span.clone(),
662 format!("expected operand vector of length 1..=4 or 8, found {other}"),
663 )),
664 }
665 }
666}
667
668impl PtxParser for GeneralOperand {
669 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
670 if stream.check(|token| matches!(token, PtxToken::LBrace)) {
671 Ok(GeneralOperand::Vec(VectorOperand::parse(stream)?))
672 } else {
673 Ok(GeneralOperand::Single(Operand::parse(stream)?))
674 }
675 }
676}
677
678impl PtxParser for TexHandler2 {
679 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
680 stream.expect(&PtxToken::LBracket)?;
681 let first = GeneralOperand::parse(stream)?;
682 stream.expect(&PtxToken::Comma)?;
683 let second = GeneralOperand::parse(stream)?;
684 stream.expect(&PtxToken::RBracket)?;
685 Ok(TexHandler2([first, second]))
686 }
687}
688
689impl PtxParser for TexHandler3 {
690 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
691 stream.expect(&PtxToken::LBracket)?;
692 let handle = GeneralOperand::parse(stream)?;
693 stream.expect(&PtxToken::Comma)?;
694 let sampler = GeneralOperand::parse(stream)?;
695 stream.expect(&PtxToken::Comma)?;
696 let coords = GeneralOperand::parse(stream)?;
697 stream.expect(&PtxToken::RBracket)?;
698
699 Ok(TexHandler3 {
700 handle,
701 sampler,
702 coords,
703 })
704 }
705}
706
707impl PtxParser for TexHandler3Optional {
708 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
709 stream.expect(&PtxToken::LBracket)?;
710 let handle = GeneralOperand::parse(stream)?;
711 stream.expect(&PtxToken::Comma)?;
712 let second = GeneralOperand::parse(stream)?;
713
714 let (sampler, coords) = if stream
715 .consume_if(|token| matches!(token, PtxToken::Comma))
716 .is_some()
717 {
718 let coords = GeneralOperand::parse(stream)?;
719 (Some(second), coords)
720 } else {
721 (None, second)
722 };
723
724 stream.expect(&PtxToken::RBracket)?;
725
726 Ok(TexHandler3Optional {
727 handle,
728 sampler,
729 coords,
730 })
731 }
732}
733
734impl PtxParser for AddressBase {
735 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
736 if stream.check(|token| matches!(token, PtxToken::Register(_))) {
737 Ok(AddressBase::Register(RegisterOperand::parse(stream)?))
738 } else if stream.check(|token| matches!(token, PtxToken::Identifier(_))) {
739 Ok(AddressBase::Variable(VariableSymbol::parse(stream)?))
740 } else {
741 let (token, span) = stream.peek()?;
742 Err(unexpected_value(
743 span.clone(),
744 &["register", "identifier"],
745 format!("{token:?}"),
746 ))
747 }
748 }
749}
750
751impl PtxParser for AddressOffset {
752 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
753 if stream
754 .consume_if(|token| matches!(token, PtxToken::Plus))
755 .is_some()
756 {
757 if stream.check(|token| matches!(token, PtxToken::Register(_))) {
758 Ok(AddressOffset::Register(RegisterOperand::parse(stream)?))
759 } else {
760 Ok(AddressOffset::Immediate(
761 Sign::Positive,
762 Immediate::parse(stream)?,
763 ))
764 }
765 } else if stream
766 .consume_if(|token| matches!(token, PtxToken::Minus))
767 .is_some()
768 {
769 Ok(AddressOffset::Immediate(
770 Sign::Negative,
771 Immediate::parse(stream)?,
772 ))
773 } else {
774 let (token, span) = stream.peek()?;
775 Err(unexpected_value(
776 span.clone(),
777 &["+", "-"],
778 format!("{token:?}"),
779 ))
780 }
781 }
782}
783
784impl PtxParser for AddressOperand {
785 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
786 if stream.check(|token| matches!(token, PtxToken::Identifier(_))) {
787 let saved = stream.position();
788 let (identifier, _) = stream.expect_identifier()?;
789 if stream
790 .consume_if(|token| matches!(token, PtxToken::LBracket))
791 .is_some()
792 {
793 let immediate = Immediate::parse(stream)?;
794 stream.expect(&PtxToken::RBracket)?;
795 return Ok(AddressOperand::Array(VariableSymbol(identifier), immediate));
796 } else {
797 stream.set_position(saved);
798 }
799 }
800
801 stream.expect(&PtxToken::LBracket)?;
802
803 if stream.check(|token| matches!(token, PtxToken::Minus)) {
804 let pos = stream.position();
805 stream.consume()?;
806 if stream.check(|token| is_numeric_token(token)) {
807 let mut immediate = Immediate::parse(stream)?;
808 immediate.0.insert(0, '-');
809 stream.expect(&PtxToken::RBracket)?;
810 return Ok(AddressOperand::ImmediateAddress(immediate));
811 } else {
812 stream.set_position(pos);
813 }
814 }
815
816 if stream.check(|token| is_numeric_token(token)) {
817 let immediate = Immediate::parse(stream)?;
818 stream.expect(&PtxToken::RBracket)?;
819 return Ok(AddressOperand::ImmediateAddress(immediate));
820 }
821
822 let base = AddressBase::parse(stream)?;
823 let offset = if stream.check(|token| matches!(token, PtxToken::Plus | PtxToken::Minus)) {
824 Some(AddressOffset::parse(stream)?)
825 } else {
826 None
827 };
828 stream.expect(&PtxToken::RBracket)?;
829
830 Ok(AddressOperand::Offset(base, offset))
831 }
832}
833
834impl PtxParser for FunctionSymbol {
835 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
836 let (name, _) = stream.expect_identifier()?;
837 Ok(FunctionSymbol(name))
838 }
839}
840
841impl PtxParser for VariableSymbol {
842 fn parse(stream: &mut PtxTokenStream) -> Result<Self, PtxParseError> {
843 let (name, _) = stream.expect_identifier()?;
844 Ok(VariableSymbol(name))
845 }
846}