ptx_parser/type/function.rs
1use super::common::{Instruction, Label};
2use super::variable::{ParameterDirective, VariableDirective};
3use crate::Spanned;
4use crate::parser::Span;
5use crate::r#type::{AttributeDirective, DataType, FunctionSymbol, VariableSymbol};
6use serde::Serialize;
7
8/// Alias directive relating one function symbol to another.
9///
10/// Syntax:
11/// .alias fAlias, fAliasee;
12///
13/// Example:
14/// .alias foo, bar;
15#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
16pub struct AliasFunctionDirective {
17 pub alias: FunctionSymbol,
18 pub target: FunctionSymbol,
19 pub span: Span,
20}
21
22/// A PTX kernel declared with the `.entry` directive.
23#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
24pub struct FuncFunctionDirective {
25 /// Example:
26 /// .func .attribute(.unified(0xAB, 0xCD)) bar() { ... }
27 pub attributes: Vec<AttributeDirective>,
28 /// Optional return param.
29 ///
30 /// Example:
31 /// .func (.param .u32 rval) bar(.param .u32 N, .param .align 4 .b8 numbers[]) { ... }
32 pub return_param: Option<ParameterDirective>,
33 /// Function name.
34 pub name: FunctionSymbol,
35 /// Function parameters.
36 ///
37 /// Example:
38 /// .func (.param .u32 rval) bar(.param .u32 N, .param .align 4 .b8 numbers[])
39 pub params: Vec<ParameterDirective>,
40 /// Optional directives.
41 ///
42 /// Example:
43 /// .func foo (.reg .b32 N, .reg .f64 dbl) .noreturn { ... }
44 pub directives: Vec<FuncFunctionHeaderDirective>,
45 /// Optional function body. Without body represents a function prototype.
46 pub body: Option<FunctionBody>,
47 pub span: Span,
48}
49
50/// A PTX device function declared with the `.func` directive.
51#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
52pub struct EntryFunctionDirective {
53 /// Name of the entry function.
54 pub name: FunctionSymbol,
55 /// Function parameters.
56 pub params: Vec<ParameterDirective>,
57 /// Optional directives.
58 pub directives: Vec<EntryFunctionHeaderDirective>,
59 /// Optional function body. Without body represents a function prototype.
60 pub body: Option<FunctionBody>,
61 pub span: Span,
62}
63
64/// Directive tokens that may decorate a PTX function header.
65#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
66pub enum FuncFunctionHeaderDirective {
67 /// Syntax:
68 /// .noreturn
69 ///
70 /// Example:
71 /// .func foo .noreturn { ... }
72 NoReturn { span: Span },
73 /// Syntax:
74 /// .pragma list-of-strings ;
75 ///
76 /// Example:
77 ///.entry foo .pragma "nounroll"; { ... } // disable unrolling for current kernel
78 Pragma { args: Vec<String>, span: Span },
79 /// Syntax:
80 /// .abi_preserve N
81 ///
82 /// Example:
83 /// .entry foo .abi_preserve 8 { ... }
84 AbiPreserve { value: u32, span: Span },
85 /// Syntax:
86 /// .abi_preserve_control N
87 ///
88 /// Example:
89 /// .entry foo .abi_preserve_control 16 { ... }
90 AbiPreserveControl { value: u32, span: Span },
91}
92
93/// Directive tokens that may decorate a PTX function header.
94#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
95pub enum EntryFunctionHeaderDirective {
96 /// Syntax:
97 /// .maxnreg n
98 ///
99 /// Example:
100 /// .entry foo .maxnreg 16 { ... } // max regs per thread = 16
101 MaxNReg { value: u32, span: Span },
102 /// Syntax:
103 /// .maxntid nx
104 /// .maxntid nx, ny
105 /// .maxntid nx, ny, nz
106 ///
107 /// Example:
108 /// .entry foo .maxntid 256 { ... } // max threads = 256
109 /// .entry bar .maxntid 16,16,4 { ... } // max threads = 1024
110 MaxNTid { dim: FunctionDim, span: Span },
111 /// Syntax:
112 /// .reqntid nx
113 /// .reqntid nx, ny
114 /// .reqntid nx, ny, nz
115 ///
116 /// Example:
117 /// .entry foo .reqntid 256 { ... } // num threads = 256
118 /// .entry bar .reqntid 16,16,4 { ... } // num threads = 1024
119 ReqNTid { dim: FunctionDim, span: Span },
120 /// Syntax:
121 /// .minnctapersm ncta
122 ///
123 /// Example:
124 /// .entry foo .maxntid 256 .minnctapersm 4 { ... }
125 MinNCtaPerSm { value: u32, span: Span },
126 /// Syntax:
127 /// .maxnctapersm ncta
128 ///
129 /// Example:
130 /// .entry foo .maxntid 256 .maxnctapersm 4 { ... }
131 MaxNCtaPerSm { value: u32, span: Span },
132 /// Syntax:
133 /// .pragma list-of-strings ;
134 ///
135 /// Example:
136 ///.entry foo .pragma "nounroll"; { ... } // disable unrolling for current kernel
137 Pragma { args: Vec<String>, span: Span },
138 /// Syntax:
139 /// .reqnctapercluster nx
140 /// .reqnctapercluster nx, ny
141 /// .reqnctapercluster nx, ny, nz
142 ///
143 /// Example:
144 /// .entry foo .reqnctapercluster 2 { . . . }
145 /// .entry bar .reqnctapercluster 2, 2, 1 { . . . }
146 /// .entry ker .reqnctapercluster 3, 2 { . . . }
147 ReqNctaPerCluster { dim: FunctionDim, span: Span },
148 /// Syntax:
149 /// .explicitcluster
150 ///
151 /// Example:
152 /// .entry foo .explicitcluster { . . . }
153 ExplicitCluster { span: Span },
154 /// Syntax:
155 /// .maxclusterrank n
156 ///
157 /// Example:
158 /// .entry foo ..maxclusterrank 8 { . . . }
159 MaxClusterRank { value: u32, span: Span },
160 /// Syntax:
161 ///.blocksareclusters
162 ///
163 /// Example:
164 /// .entry foo .reqntid 32, 32, 1 .reqnctapercluster 32, 32, 1 .blocksareclusters { ... } // only allowed when with .reqnctapercluster and .reqntid
165 BlocksAreClusters { span: Span },
166}
167
168/// Statements contained within a PTX function body.
169#[derive(Debug, Clone, Default, PartialEq, Spanned, Serialize)]
170pub struct FunctionBody {
171 pub statements: Vec<FunctionStatement>,
172 pub span: Span,
173}
174
175/// Nested statement block enclosed in braces.
176/// Executable items that appear within a function body.
177#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
178pub enum FunctionStatement {
179 Label {
180 label: Label,
181 span: Span,
182 },
183 Directive {
184 directive: StatementDirective,
185 span: Span,
186 },
187 Instruction {
188 instruction: Instruction,
189 span: Span,
190 },
191 Block {
192 statements: Vec<FunctionStatement>,
193 span: Span,
194 },
195}
196
197/// Directive that declares a register variable inside a function body.
198///
199/// Syntax:
200/// .reg .ty name<range>
201#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
202pub struct RegisterDirective {
203 pub ty: DataType,
204 pub registers: Vec<RegisterTarget>,
205 pub span: Span,
206}
207
208#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
209pub struct RegisterTarget {
210 pub name: VariableSymbol,
211 pub range: Option<u32>,
212 pub span: Span,
213}
214
215/// Directive that applies to individual statements.
216#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
217pub enum StatementDirective {
218 Loc {
219 directive: LocationDirective,
220 span: Span,
221 },
222 Pragma {
223 directive: PragmaDirective,
224 span: Span,
225 },
226 Section {
227 directive: SectionDirective,
228 span: Span,
229 },
230 Reg {
231 directive: RegisterDirective,
232 span: Span,
233 },
234 Local {
235 directive: VariableDirective,
236 span: Span,
237 },
238 Param {
239 directive: VariableDirective,
240 span: Span,
241 },
242 Shared {
243 directive: VariableDirective,
244 span: Span,
245 },
246 Dwarf {
247 directive: DwarfDirective,
248 span: Span,
249 },
250 BranchTargets {
251 directive: BranchTargetsDirective,
252 span: Span,
253 },
254 CallTargets {
255 directive: CallTargetsDirective,
256 span: Span,
257 },
258 CallPrototype {
259 directive: CallPrototypeDirective,
260 span: Span,
261 },
262}
263
264/// Raw dwarf directive emitted by the compiler (e.g. `@@dwarf`).
265///
266/// Syntax:
267/// ```text
268/// @@DWARF dwarf-string
269///
270/// dwarf-string may have one of the
271/// .byte byte-list // comma-separated hexadecimal byte values
272/// .4byte int32-list // comma-separated hexadecimal integers in range [0..2^32-1]
273/// .quad int64-list // comma-separated hexadecimal integers in range [0..2^64-1]
274/// .4byte label
275/// .quad label
276/// ```
277#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
278pub struct DwarfDirective {
279 pub kind: DwarfDirectiveKind,
280 pub span: Span,
281}
282
283#[derive(Debug, Clone, PartialEq, Serialize)]
284pub enum DwarfDirectiveKind {
285 ByteValues(Vec<u8>),
286 FourByteValues(Vec<u32>),
287 QuadValues(Vec<u64>),
288 FourByteLabel(Label),
289 QuadLabel(Label),
290}
291
292/// Structured representation of a `.section` directive inside a function body.
293///
294/// Syntax:
295/// ```text
296/// .section section_name { dwarf-lines }
297///
298/// dwarf-lines have the following formats:
299/// .b8 byte-list // integers in [-128..255]
300/// .b16 int16-list // integers in [-2^15..2^16-1]
301/// .b32 int32-list // integers in [-2^31..2^32-1]
302/// label: // define label inside the debug section
303/// .b64 int64-list // integers in [-2^63..2^64-1]
304/// .b32 label
305/// .b64 label
306/// .b32 label+imm // label plus constant integer byte offset (32-bit)
307/// .b64 label+imm // label plus constant integer byte offset (64-bit)
308/// .b32 label1-label2 // difference between labels in same section (32-bit)
309/// .b64 label3-label4 // difference between labels in same section (64-bit)
310/// ```
311///
312/// Example:
313/// ```text
314/// .section .debug_str {
315/// info_string0:
316/// .b8 95 // _
317/// .b8 90 // z
318/// .b8 51 // 3
319/// .b8 102 // f
320/// .b8 111 // o
321/// .b8 111 // o
322/// .b8 118 // v
323/// .b8 0
324/// info_string1:
325/// .b8 95 // _
326/// .b8 90 // z
327/// .b8 51 // 3
328/// .b8 98 // b
329/// .b8 97 // a
330/// .b8 114 // r
331/// .b8 118 // v
332/// .b8 0
333/// .b8 95 // _
334/// .b8 90 // z
335/// .b8 51 // 3
336/// .b8 99 // c
337/// .b8 97 // a
338/// .b8 114 // r
339/// .b8 118 // v
340/// .b8 0
341/// }
342/// ```
343#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
344pub struct SectionDirective {
345 pub name: String,
346 pub entries: Vec<SectionEntry>,
347 pub span: Span,
348}
349
350#[derive(Debug, Clone, PartialEq, Serialize)]
351pub enum SectionEntry {
352 Label { label: Label, span: Span },
353 Directive(StatementSectionDirectiveLine),
354}
355
356#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
357pub enum StatementSectionDirectiveLine {
358 B8 { values: Vec<i16>, span: Span },
359 B16 { values: Vec<i32>, span: Span },
360 B32Immediate { values: Vec<i64>, span: Span },
361 B64Immediate { values: Vec<i128>, span: Span },
362 B32Label { labels: Label, span: Span },
363 B64Label { labels: Label, span: Span },
364 B32LabelPlusImm { entries: (Label, i32), span: Span },
365 B64LabelPlusImm { entries: (Label, i64), span: Span },
366 B32LabelDiff { entries: (Label, Label), span: Span },
367 B64LabelDiff { entries: (Label, Label), span: Span },
368}
369
370/// Structured representation of a `.loc` directive inside a PTX function.
371///
372/// Syntax:
373/// .loc file_index line_number column_position
374/// .loc file_index line_number column_position,function_name label {+ immediate }, inlined_at file_index2 line_number2 column_position2
375#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
376pub struct LocationDirective {
377 pub file_index: u32,
378 pub line: u32,
379 pub column: u32,
380 pub inlined_at: Option<LocationInlinedAt>,
381 pub span: Span,
382}
383
384#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
385pub struct LocationInlinedAt {
386 pub file_index: u32,
387 pub line: u32,
388 pub column: u32,
389 pub function_name: FunctionSymbol,
390 pub label: Label,
391 pub label_offset: Option<i64>,
392 pub span: Span,
393}
394
395/// Structured representation of a `.pragma` directive.
396///
397/// Syntax:
398/// .pragma "nounroll";
399/// .pragma "used_bytes_mask mask";
400/// .pragma "enable_smem_spilling";
401/// .pragma "frequency n";
402#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
403pub struct PragmaDirective {
404 pub kind: PragmaDirectiveKind,
405 pub span: Span,
406}
407
408#[derive(Debug, Clone, PartialEq, Serialize)]
409pub enum PragmaDirectiveKind {
410 Nounroll,
411 UsedBytesMask { mask: String },
412 EnableSmemSpilling,
413 Frequency { value: u32 },
414 Raw(String),
415}
416
417/// Structured representation of a `.branchtargets` directive.
418///
419/// Syntax:
420/// .branchtargets label1, label2, label3, ...;
421#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
422pub struct BranchTargetsDirective {
423 pub labels: Vec<Label>,
424 pub span: Span,
425}
426
427/// Structured representation of a `.calltargets` directive.
428///
429/// Syntax:
430/// .calltargets func1, func2, func3, ...;
431#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
432pub struct CallTargetsDirective {
433 pub targets: Vec<FunctionSymbol>,
434 pub span: Span,
435}
436
437/// Structured representation of a `.callprototype` directive.
438///
439/// Syntax:
440/// // no input or return parameters
441/// label: .callprototype _ .noreturn {.abi_preserve N} {.abi_preserve_control N};
442/// // input params, no return params
443/// label: .callprototype _ (param-list) .noreturn {.abi_preserve N} {.abi_preserve_control N};
444/// // no input params, // return params
445/// label: .callprototype (ret-param) _ {.abi_preserve N} {.abi_preserve_control N};
446/// // input, return parameters
447/// label: .callprototype (ret-param) _ (param-list) {.abi_preserve N} {.abi_preserve_control N};
448#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
449pub struct CallPrototypeDirective {
450 pub return_param: Option<ParameterDirective>,
451 pub params: Vec<ParameterDirective>,
452 pub noreturn: bool,
453 pub abi_preserve: Option<u32>,
454 pub abi_preserve_control: Option<u32>,
455 pub span: Span,
456}
457
458/// Dimension triplet used by several function header directives.
459#[derive(Debug, Clone, PartialEq, Spanned, Serialize)]
460pub enum FunctionDim {
461 X { x: u32, span: Span },
462 XY { x: u32, y: u32, span: Span },
463 XYZ { x: u32, y: u32, z: u32, span: Span },
464}