ptx_parser/unparser/
variable.rs1use 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(bits) => {
29 let text = format!("0d{:016x}", bits);
30 tokens.push(PtxToken::HexFloat(text));
31 }
32 NumericLiteral::Float32(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(literal) => literal.unparse_tokens(tokens),
49 InitializerValue::Symbol(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(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(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}