ptx_parser/unparser/
variable.rs

1use super::PtxUnparser;
2use crate::{
3    lexer::PtxToken,
4    r#type::{
5        common::{AddressSpace, AttributeDirective},
6        variable::{
7            GlobalInitializer, InitializerValue, ModuleVariableDirective, NumericLiteral,
8            VariableDirective, VariableModifier,
9        },
10    },
11    unparser::{push_decimal, push_directive, push_identifier},
12};
13
14fn push_numeric_literal(tokens: &mut Vec<PtxToken>, literal: &NumericLiteral) {
15    match literal {
16        NumericLiteral::Signed { value, .. } => {
17            if *value < 0 {
18                tokens.push(PtxToken::Minus);
19                let magnitude = (*value as i128).abs();
20                push_decimal(tokens, magnitude.to_string());
21            } else {
22                push_decimal(tokens, value.to_string());
23            }
24        }
25        NumericLiteral::Unsigned { value, .. } => {
26            push_decimal(tokens, value.to_string());
27        }
28        NumericLiteral::Float64 { value: bits, .. } => {
29            let text = format!("0d{:016x}", bits);
30            tokens.push(PtxToken::HexFloat(text));
31        }
32        NumericLiteral::Float32 { value: bits, .. } => {
33            let text = format!("0f{:08x}", bits);
34            tokens.push(PtxToken::HexFloat(text));
35        }
36    }
37}
38
39impl PtxUnparser for NumericLiteral {
40    fn unparse_tokens(&self, tokens: &mut Vec<PtxToken>) {
41        push_numeric_literal(tokens, self);
42    }
43}
44
45impl PtxUnparser for InitializerValue {
46    fn unparse_tokens(&self, tokens: &mut Vec<PtxToken>) {
47        match self {
48            InitializerValue::Numeric { value: literal, .. } => literal.unparse_tokens(tokens),
49            InitializerValue::Symbol { name: symbol, .. } => push_identifier(tokens, symbol),
50            InitializerValue::StringLiteral { value, .. } => {
51                tokens.push(PtxToken::StringLiteral(value.clone()));
52            }
53        }
54    }
55}
56
57impl PtxUnparser for GlobalInitializer {
58    fn unparse_tokens(&self, tokens: &mut Vec<PtxToken>) {
59        match self {
60            GlobalInitializer::Scalar { value, .. } => value.unparse_tokens(tokens),
61            GlobalInitializer::Aggregate { values: elements, .. } => {
62                tokens.push(PtxToken::LBrace);
63                for (index, element) in elements.iter().enumerate() {
64                    if index > 0 {
65                        tokens.push(PtxToken::Comma);
66                    }
67                    element.unparse_tokens(tokens);
68                }
69                tokens.push(PtxToken::RBrace);
70            }
71        }
72    }
73}
74
75impl PtxUnparser for VariableModifier {
76    fn unparse_tokens(&self, tokens: &mut Vec<PtxToken>) {
77        match self {
78            VariableModifier::Vector { value: width, .. } => {
79                push_directive(tokens, &format!("v{width}"));
80            }
81            VariableModifier::Alignment { value, .. } => {
82                push_directive(tokens, "align");
83                push_decimal(tokens, value.to_string());
84            }
85            VariableModifier::Linkage { linkage, .. } => linkage.unparse_tokens(tokens),
86            VariableModifier::Ptr { .. } => push_directive(tokens, "ptr"),
87        }
88    }
89}
90
91fn unparse_array_dimensions(tokens: &mut Vec<PtxToken>, extents: &[Option<u64>]) {
92    for extent in extents {
93        tokens.push(PtxToken::LBracket);
94        if let Some(value) = extent {
95            push_decimal(tokens, value.to_string());
96        }
97        tokens.push(PtxToken::RBracket);
98    }
99}
100
101fn unparse_initializer(tokens: &mut Vec<PtxToken>, initializer: &Option<GlobalInitializer>) {
102    if let Some(initializer) = initializer {
103        tokens.push(PtxToken::Equals);
104        initializer.unparse_tokens(tokens);
105    }
106}
107
108fn unparse_prefix(
109    tokens: &mut Vec<PtxToken>,
110    linkage_modifiers: &[VariableModifier],
111    other_modifiers: &[VariableModifier],
112    attributes: &[AttributeDirective],
113    address_space: &Option<AddressSpace>,
114) {
115    for attribute in attributes {
116        attribute.unparse_tokens(tokens);
117    }
118    for modifier in linkage_modifiers {
119        modifier.unparse_tokens(tokens);
120    }
121    if let Some(space) = address_space {
122        space.unparse_tokens(tokens);
123    }
124    for modifier in other_modifiers {
125        modifier.unparse_tokens(tokens);
126    }
127}
128
129fn split_modifiers(
130    modifiers: &[VariableModifier],
131) -> (Vec<VariableModifier>, Vec<VariableModifier>) {
132    let mut linkage = Vec::new();
133    let mut other = Vec::new();
134    for modifier in modifiers {
135        match modifier {
136            VariableModifier::Linkage { .. } => linkage.push(modifier.clone()),
137            _ => other.push(modifier.clone()),
138        }
139    }
140    (linkage, other)
141}
142
143impl PtxUnparser for VariableDirective {
144    fn unparse_tokens(&self, tokens: &mut Vec<PtxToken>) {
145        let (linkage_modifiers, other_modifiers) = split_modifiers(&self.modifiers);
146        unparse_prefix(
147            tokens,
148            &linkage_modifiers,
149            &other_modifiers,
150            &self.attributes,
151            &self.address_space,
152        );
153
154        if let Some(ty) = &self.ty {
155            ty.unparse_tokens(tokens);
156        }
157
158        push_identifier(tokens, &self.name);
159        unparse_array_dimensions(tokens, &self.array);
160        unparse_initializer(tokens, &self.initializer);
161        tokens.push(PtxToken::Semicolon);
162    }
163}
164
165impl PtxUnparser for ModuleVariableDirective {
166    fn unparse_tokens(&self, tokens: &mut Vec<PtxToken>) {
167        match self {
168            ModuleVariableDirective::Tex { directive, .. } => {
169                push_directive(tokens, "tex");
170                directive.unparse_tokens(tokens);
171            }
172            ModuleVariableDirective::Shared { directive, .. }
173            | ModuleVariableDirective::Global { directive, .. }
174            | ModuleVariableDirective::Const { directive, .. } => directive.unparse_tokens(tokens),
175        }
176    }
177}