[yaml2obj][obj2yaml] - Do not create a symbol table by default.
[llvm-complete.git] / lib / Analysis / VFABIDemangling.cpp
blob6fd8ae63f5f07b80920ba50da56fa6ec899b5ad8
1 //===- VFABIDemangling.cpp - Vector Function ABI demangling utilities. ---===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/VectorUtils.h"
11 using namespace llvm;
13 namespace {
14 /// Utilities for the Vector Function ABI name parser.
16 /// Return types for the parser functions.
17 enum class ParseRet {
18 OK, // Found.
19 None, // Not found.
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);
40 return ParseRet::OK;
43 /// Extracts the `<mask>` information from the mangled string, and
44 /// sets `IsMasked` accordingly. The input string `MangledName` is
45 /// left unmodified.
46 ParseRet tryParseMask(StringRef &MangledName, bool &IsMasked) {
47 if (MangledName.consume_front("M")) {
48 IsMasked = true;
49 return ParseRet::OK;
52 if (MangledName.consume_front("N")) {
53 IsMasked = false;
54 return ParseRet::OK;
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`.
64 ///
65 ParseRet tryParseVLEN(StringRef &ParseString, unsigned &VF, bool &IsScalable) {
66 if (ParseString.consume_front("x")) {
67 VF = 0;
68 IsScalable = true;
69 return ParseRet::OK;
72 if (ParseString.consumeInteger(10, VF))
73 return ParseRet::Error;
75 IsScalable = false;
76 return ParseRet::OK;
79 /// The function looks for the following strings at the beginning of
80 /// the input string `ParseString`:
81 ///
82 /// <token> <number>
83 ///
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.
88 ///
89 /// The function expects <token> to be one of "ls", "Rs", "Us" or
90 /// "Ls".
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;
98 return ParseRet::OK;
101 return ParseRet::None;
104 /// The function looks for the following stringt at the beginning of
105 /// the input string `ParseString`:
107 /// <token> <number>
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) {
117 ParseRet Ret;
119 // "ls" <RuntimeStepPos>
120 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "ls");
121 if (Ret != ParseRet::None)
122 return Ret;
124 // "Rs" <RuntimeStepPos>
125 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Rs");
126 if (Ret != ParseRet::None)
127 return Ret;
129 // "Ls" <RuntimeStepPos>
130 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Ls");
131 if (Ret != ParseRet::None)
132 return Ret;
134 // "Us" <RuntimeStepPos>
135 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Us");
136 if (Ret != ParseRet::None)
137 return Ret;
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
153 /// "L".
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))
161 LinearStep = 1;
162 if (Negate)
163 LinearStep *= -1;
164 return ParseRet::OK;
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") ==
183 ParseRet::OK)
184 return ParseRet::OK;
186 // "R" {"n"} <CompileTimeStep>
187 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "R") ==
188 ParseRet::OK)
189 return ParseRet::OK;
191 // "L" {"n"} <CompileTimeStep>
192 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "L") ==
193 ParseRet::OK)
194 return ParseRet::OK;
196 // "U" {"n"} <CompileTimeStep>
197 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "U") ==
198 ParseRet::OK)
199 return ParseRet::OK;
201 return ParseRet::None;
204 /// The function looks for the following strings at the beginning of
205 /// the input string `ParseString`:
207 /// "u" <number>
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) {
214 // "u" <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;
221 return ParseRet::OK;
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
228 /// `ParseString`.
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,
235 int &StepOrPos) {
236 if (ParseString.consume_front("v")) {
237 PKind = VFParamKind::Vector;
238 StepOrPos = 0;
239 return ParseRet::OK;
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)
254 return HasUniform;
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) {
268 uint64_t Val;
269 // "a" <number>
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);
279 return ParseRet::OK;
282 return ParseRet::None;
284 } // namespace
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"))
296 return None;
298 // Extract ISA. An unknow ISA is also supported, so we accept all
299 // values.
300 VFISAKind ISA;
301 if (tryParseISA(MangledName, ISA) != ParseRet::OK)
302 return None;
304 // Extract <mask>.
305 bool IsMasked;
306 if (tryParseMask(MangledName, IsMasked) != ParseRet::OK)
307 return None;
309 // Parse the variable size, starting from <vlen>.
310 unsigned VF;
311 bool IsScalable;
312 if (tryParseVLEN(MangledName, VF, IsScalable) != ParseRet::OK)
313 return None;
315 // Parse the <parameters>.
316 ParseRet ParamFound;
317 SmallVector<VFParameter, 8> Parameters;
318 do {
319 const unsigned ParameterPos = Parameters.size();
320 VFParamKind PKind;
321 int StepOrPos;
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)
326 return None;
328 if (ParamFound == ParseRet::OK) {
329 Align Alignment;
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)
334 return None;
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
342 // <parameters>.
343 if (Parameters.empty())
344 return None;
346 // Check for the <scalarname> and the optional <redirection>, which
347 // are separated from the prefix with "_"
348 if (!MangledName.consume_front("_"))
349 return None;
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())
357 return None;
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(")"))
364 return None;
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())
369 return None;
372 // When <mask> is "M", we need to add a parameter that is used as
373 // global predicate for the function.
374 if (IsMasked) {
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
381 // this parser:
382 // 1. Uniqueness.
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.");
389 if (NGlobalPreds)
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)
412 return ParamKind;
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");