1 //===- VFABIDemangling.cpp - Vector Function ABI demangling utilities. ---===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/VectorUtils.h"
14 /// Utilities for the Vector Function ABI name parser.
16 /// Return types for the parser functions.
20 Error
// Syntax error.
23 /// Extracts the `<isa>` information from the mangled string, and
24 /// sets the `ISA` accordingly.
25 ParseRet
tryParseISA(StringRef
&MangledName
, VFISAKind
&ISA
) {
26 if (MangledName
.empty())
27 return ParseRet::Error
;
29 ISA
= StringSwitch
<VFISAKind
>(MangledName
.take_front(1))
30 .Case("n", VFISAKind::AdvancedSIMD
)
31 .Case("s", VFISAKind::SVE
)
32 .Case("b", VFISAKind::SSE
)
33 .Case("c", VFISAKind::AVX
)
34 .Case("d", VFISAKind::AVX2
)
35 .Case("e", VFISAKind::AVX512
)
36 .Default(VFISAKind::Unknown
);
38 MangledName
= MangledName
.drop_front(1);
43 /// Extracts the `<mask>` information from the mangled string, and
44 /// sets `IsMasked` accordingly. The input string `MangledName` is
46 ParseRet
tryParseMask(StringRef
&MangledName
, bool &IsMasked
) {
47 if (MangledName
.consume_front("M")) {
52 if (MangledName
.consume_front("N")) {
57 return ParseRet::Error
;
60 /// Extract the `<vlen>` information from the mangled string, and
61 /// sets `VF` accordingly. A `<vlen> == "x"` token is interpreted as a scalable
62 /// vector length. On success, the `<vlen>` token is removed from
63 /// the input string `ParseString`.
65 ParseRet
tryParseVLEN(StringRef
&ParseString
, unsigned &VF
, bool &IsScalable
) {
66 if (ParseString
.consume_front("x")) {
72 if (ParseString
.consumeInteger(10, VF
))
73 return ParseRet::Error
;
79 /// The function looks for the following strings at the beginning of
80 /// the input string `ParseString`:
84 /// On success, it removes the parsed parameter from `ParseString`,
85 /// sets `PKind` to the correspondent enum value, sets `Pos` to
86 /// <number>, and return success. On a syntax error, it return a
87 /// parsing error. If nothing is parsed, it returns None.
89 /// The function expects <token> to be one of "ls", "Rs", "Us" or
91 ParseRet
tryParseLinearTokenWithRuntimeStep(StringRef
&ParseString
,
92 VFParamKind
&PKind
, int &Pos
,
93 const StringRef Token
) {
94 if (ParseString
.consume_front(Token
)) {
95 PKind
= VFABI::getVFParamKindFromString(Token
);
96 if (ParseString
.consumeInteger(10, Pos
))
97 return ParseRet::Error
;
101 return ParseRet::None
;
104 /// The function looks for the following stringt at the beginning of
105 /// the input string `ParseString`:
109 /// <token> is one of "ls", "Rs", "Us" or "Ls".
111 /// On success, it removes the parsed parameter from `ParseString`,
112 /// sets `PKind` to the correspondent enum value, sets `StepOrPos` to
113 /// <number>, and return success. On a syntax error, it return a
114 /// parsing error. If nothing is parsed, it returns None.
115 ParseRet
tryParseLinearWithRuntimeStep(StringRef
&ParseString
,
116 VFParamKind
&PKind
, int &StepOrPos
) {
119 // "ls" <RuntimeStepPos>
120 Ret
= tryParseLinearTokenWithRuntimeStep(ParseString
, PKind
, StepOrPos
, "ls");
121 if (Ret
!= ParseRet::None
)
124 // "Rs" <RuntimeStepPos>
125 Ret
= tryParseLinearTokenWithRuntimeStep(ParseString
, PKind
, StepOrPos
, "Rs");
126 if (Ret
!= ParseRet::None
)
129 // "Ls" <RuntimeStepPos>
130 Ret
= tryParseLinearTokenWithRuntimeStep(ParseString
, PKind
, StepOrPos
, "Ls");
131 if (Ret
!= ParseRet::None
)
134 // "Us" <RuntimeStepPos>
135 Ret
= tryParseLinearTokenWithRuntimeStep(ParseString
, PKind
, StepOrPos
, "Us");
136 if (Ret
!= ParseRet::None
)
139 return ParseRet::None
;
142 /// The function looks for the following strings at the beginning of
143 /// the input string `ParseString`:
145 /// <token> {"n"} <number>
147 /// On success, it removes the parsed parameter from `ParseString`,
148 /// sets `PKind` to the correspondent enum value, sets `LinearStep` to
149 /// <number>, and return success. On a syntax error, it return a
150 /// parsing error. If nothing is parsed, it returns None.
152 /// The function expects <token> to be one of "l", "R", "U" or
154 ParseRet
tryParseCompileTimeLinearToken(StringRef
&ParseString
,
155 VFParamKind
&PKind
, int &LinearStep
,
156 const StringRef Token
) {
157 if (ParseString
.consume_front(Token
)) {
158 PKind
= VFABI::getVFParamKindFromString(Token
);
159 const bool Negate
= ParseString
.consume_front("n");
160 if (ParseString
.consumeInteger(10, LinearStep
))
167 return ParseRet::None
;
170 /// The function looks for the following strings at the beginning of
171 /// the input string `ParseString`:
173 /// ["l" | "R" | "U" | "L"] {"n"} <number>
175 /// On success, it removes the parsed parameter from `ParseString`,
176 /// sets `PKind` to the correspondent enum value, sets `LinearStep` to
177 /// <number>, and return success. On a syntax error, it return a
178 /// parsing error. If nothing is parsed, it returns None.
179 ParseRet
tryParseLinearWithCompileTimeStep(StringRef
&ParseString
,
180 VFParamKind
&PKind
, int &StepOrPos
) {
181 // "l" {"n"} <CompileTimeStep>
182 if (tryParseCompileTimeLinearToken(ParseString
, PKind
, StepOrPos
, "l") ==
186 // "R" {"n"} <CompileTimeStep>
187 if (tryParseCompileTimeLinearToken(ParseString
, PKind
, StepOrPos
, "R") ==
191 // "L" {"n"} <CompileTimeStep>
192 if (tryParseCompileTimeLinearToken(ParseString
, PKind
, StepOrPos
, "L") ==
196 // "U" {"n"} <CompileTimeStep>
197 if (tryParseCompileTimeLinearToken(ParseString
, PKind
, StepOrPos
, "U") ==
201 return ParseRet::None
;
204 /// The function looks for the following strings at the beginning of
205 /// the input string `ParseString`:
209 /// On success, it removes the parsed parameter from `ParseString`,
210 /// sets `PKind` to the correspondent enum value, sets `Pos` to
211 /// <number>, and return success. On a syntax error, it return a
212 /// parsing error. If nothing is parsed, it returns None.
213 ParseRet
tryParseUniform(StringRef
&ParseString
, VFParamKind
&PKind
, int &Pos
) {
215 const char *UniformToken
= "u";
216 if (ParseString
.consume_front(UniformToken
)) {
217 PKind
= VFABI::getVFParamKindFromString(UniformToken
);
218 if (ParseString
.consumeInteger(10, Pos
))
219 return ParseRet::Error
;
223 return ParseRet::None
;
226 /// Looks into the <parameters> part of the mangled name in search
227 /// for valid paramaters at the beginning of the string
230 /// On success, it removes the parsed parameter from `ParseString`,
231 /// sets `PKind` to the correspondent enum value, sets `StepOrPos`
232 /// accordingly, and return success. On a syntax error, it return a
233 /// parsing error. If nothing is parsed, it returns None.
234 ParseRet
tryParseParameter(StringRef
&ParseString
, VFParamKind
&PKind
,
236 if (ParseString
.consume_front("v")) {
237 PKind
= VFParamKind::Vector
;
242 const ParseRet HasLinearRuntime
=
243 tryParseLinearWithRuntimeStep(ParseString
, PKind
, StepOrPos
);
244 if (HasLinearRuntime
!= ParseRet::None
)
245 return HasLinearRuntime
;
247 const ParseRet HasLinearCompileTime
=
248 tryParseLinearWithCompileTimeStep(ParseString
, PKind
, StepOrPos
);
249 if (HasLinearCompileTime
!= ParseRet::None
)
250 return HasLinearCompileTime
;
252 const ParseRet HasUniform
= tryParseUniform(ParseString
, PKind
, StepOrPos
);
253 if (HasUniform
!= ParseRet::None
)
256 return ParseRet::None
;
259 /// Looks into the <parameters> part of the mangled name in search
260 /// of a valid 'aligned' clause. The function should be invoked
261 /// after parsing a parameter via `tryParseParameter`.
263 /// On success, it removes the parsed parameter from `ParseString`,
264 /// sets `PKind` to the correspondent enum value, sets `StepOrPos`
265 /// accordingly, and return success. On a syntax error, it return a
266 /// parsing error. If nothing is parsed, it returns None.
267 ParseRet
tryParseAlign(StringRef
&ParseString
, Align
&Alignment
) {
270 if (ParseString
.consume_front("a")) {
271 if (ParseString
.consumeInteger(10, Val
))
272 return ParseRet::Error
;
274 if (!isPowerOf2_64(Val
))
275 return ParseRet::Error
;
277 Alignment
= Align(Val
);
282 return ParseRet::None
;
286 // Format of the ABI name:
287 // _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)]
288 Optional
<VFInfo
> VFABI::tryDemangleForVFABI(StringRef MangledName
) {
289 // Assume there is no custom name <redirection>, and therefore the
290 // vector name consists of
291 // _ZGV<isa><mask><vlen><parameters>_<scalarname>.
292 StringRef VectorName
= MangledName
;
294 // Parse the fixed size part of the manled name
295 if (!MangledName
.consume_front("_ZGV"))
298 // Extract ISA. An unknow ISA is also supported, so we accept all
301 if (tryParseISA(MangledName
, ISA
) != ParseRet::OK
)
306 if (tryParseMask(MangledName
, IsMasked
) != ParseRet::OK
)
309 // Parse the variable size, starting from <vlen>.
312 if (tryParseVLEN(MangledName
, VF
, IsScalable
) != ParseRet::OK
)
315 // Parse the <parameters>.
317 SmallVector
<VFParameter
, 8> Parameters
;
319 const unsigned ParameterPos
= Parameters
.size();
322 ParamFound
= tryParseParameter(MangledName
, PKind
, StepOrPos
);
324 // Bail off if there is a parsing error in the parsing of the parameter.
325 if (ParamFound
== ParseRet::Error
)
328 if (ParamFound
== ParseRet::OK
) {
330 // Look for the alignment token "a <number>".
331 const ParseRet AlignFound
= tryParseAlign(MangledName
, Alignment
);
332 // Bail off if there is a syntax error in the align token.
333 if (AlignFound
== ParseRet::Error
)
336 // Add the parameter.
337 Parameters
.push_back({ParameterPos
, PKind
, StepOrPos
, Alignment
});
339 } while (ParamFound
== ParseRet::OK
);
341 // A valid MangledName mus have at least one valid entry in the
343 if (Parameters
.empty())
346 // Check for the <scalarname> and the optional <redirection>, which
347 // are separated from the prefix with "_"
348 if (!MangledName
.consume_front("_"))
351 // The rest of the string must be in the format:
352 // <scalarname>[(<redirection>)]
353 const StringRef ScalarName
=
354 MangledName
.take_while([](char In
) { return In
!= '('; });
356 if (ScalarName
.empty())
359 // Reduce MangledName to [(<redirection>)].
360 MangledName
= MangledName
.ltrim(ScalarName
);
361 // Find the optional custom name redirection.
362 if (MangledName
.consume_front("(")) {
363 if (!MangledName
.consume_back(")"))
365 // Update the vector variant with the one specified by the user.
366 VectorName
= MangledName
;
367 // If the vector name is missing, bail out.
368 if (VectorName
.empty())
372 // When <mask> is "M", we need to add a parameter that is used as
373 // global predicate for the function.
375 const unsigned Pos
= Parameters
.size();
376 Parameters
.push_back({Pos
, VFParamKind::GlobalPredicate
});
379 // Asserts for parameters of type `VFParamKind::GlobalPredicate`, as
380 // prescribed by the Vector Function ABI specifications supported by
383 // 2. Must be the last in the parameter list.
384 const auto NGlobalPreds
= std::count_if(
385 Parameters
.begin(), Parameters
.end(), [](const VFParameter PK
) {
386 return PK
.ParamKind
== VFParamKind::GlobalPredicate
;
388 assert(NGlobalPreds
< 2 && "Cannot have more than one global predicate.");
390 assert(Parameters
.back().ParamKind
== VFParamKind::GlobalPredicate
&&
391 "The global predicate must be the last parameter");
393 const VFShape
Shape({VF
, IsScalable
, ISA
, Parameters
});
394 return VFInfo({Shape
, ScalarName
, VectorName
});
397 VFParamKind
VFABI::getVFParamKindFromString(const StringRef Token
) {
398 const VFParamKind ParamKind
= StringSwitch
<VFParamKind
>(Token
)
399 .Case("v", VFParamKind::Vector
)
400 .Case("l", VFParamKind::OMP_Linear
)
401 .Case("R", VFParamKind::OMP_LinearRef
)
402 .Case("L", VFParamKind::OMP_LinearVal
)
403 .Case("U", VFParamKind::OMP_LinearUVal
)
404 .Case("ls", VFParamKind::OMP_LinearPos
)
405 .Case("Ls", VFParamKind::OMP_LinearValPos
)
406 .Case("Rs", VFParamKind::OMP_LinearRefPos
)
407 .Case("Us", VFParamKind::OMP_LinearUValPos
)
408 .Case("u", VFParamKind::OMP_Uniform
)
409 .Default(VFParamKind::Unknown
);
411 if (ParamKind
!= VFParamKind::Unknown
)
414 // This function should never be invoked with an invalid input.
415 llvm_unreachable("This fuction should be invoken only on parameters"
416 " that have a textual representation in the mangled name"
417 " of the Vector Function ABI");