LLVM  10.0.0svn
VFABIDemangling.cpp
Go to the documentation of this file.
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 //===----------------------------------------------------------------------===//
8 
10 
11 using namespace llvm;
12 
13 namespace {
14 /// Utilities for the Vector Function ABI name parser.
15 
16 /// Return types for the parser functions.
17 enum class ParseRet {
18  OK, // Found.
19  None, // Not found.
20  Error // Syntax error.
21 };
22 
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;
28 
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)
37 
38  MangledName = MangledName.drop_front(1);
39 
40  return ParseRet::OK;
41 }
42 
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;
50  }
51 
52  if (MangledName.consume_front("N")) {
53  IsMasked = false;
54  return ParseRet::OK;
55  }
56 
57  return ParseRet::Error;
58 }
59 
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;
70  }
71 
72  if (ParseString.consumeInteger(10, VF))
73  return ParseRet::Error;
74 
75  IsScalable = false;
76  return ParseRet::OK;
77 }
78 
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;
99  }
100 
101  return ParseRet::None;
102 }
103 
104 /// The function looks for the following stringt at the beginning of
105 /// the input string `ParseString`:
106 ///
107 /// <token> <number>
108 ///
109 /// <token> is one of "ls", "Rs", "Us" or "Ls".
110 ///
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;
118 
119  // "ls" <RuntimeStepPos>
120  Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "ls");
121  if (Ret != ParseRet::None)
122  return Ret;
123 
124  // "Rs" <RuntimeStepPos>
125  Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Rs");
126  if (Ret != ParseRet::None)
127  return Ret;
128 
129  // "Ls" <RuntimeStepPos>
130  Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Ls");
131  if (Ret != ParseRet::None)
132  return Ret;
133 
134  // "Us" <RuntimeStepPos>
135  Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Us");
136  if (Ret != ParseRet::None)
137  return Ret;
138 
139  return ParseRet::None;
140 }
141 
142 /// The function looks for the following strings at the beginning of
143 /// the input string `ParseString`:
144 ///
145 /// <token> {"n"} <number>
146 ///
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.
151 ///
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;
165  }
166 
167  return ParseRet::None;
168 }
169 
170 /// The function looks for the following strings at the beginning of
171 /// the input string `ParseString`:
172 ///
173 /// ["l" | "R" | "U" | "L"] {"n"} <number>
174 ///
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;
185 
186  // "R" {"n"} <CompileTimeStep>
187  if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "R") ==
188  ParseRet::OK)
189  return ParseRet::OK;
190 
191  // "L" {"n"} <CompileTimeStep>
192  if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "L") ==
193  ParseRet::OK)
194  return ParseRet::OK;
195 
196  // "U" {"n"} <CompileTimeStep>
197  if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "U") ==
198  ParseRet::OK)
199  return ParseRet::OK;
200 
201  return ParseRet::None;
202 }
203 
204 /// The function looks for the following strings at the beginning of
205 /// the input string `ParseString`:
206 ///
207 /// "u" <number>
208 ///
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;
220 
221  return ParseRet::OK;
222  }
223  return ParseRet::None;
224 }
225 
226 /// Looks into the <parameters> part of the mangled name in search
227 /// for valid paramaters at the beginning of the string
228 /// `ParseString`.
229 ///
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;
240  }
241 
242  const ParseRet HasLinearRuntime =
243  tryParseLinearWithRuntimeStep(ParseString, PKind, StepOrPos);
244  if (HasLinearRuntime != ParseRet::None)
245  return HasLinearRuntime;
246 
247  const ParseRet HasLinearCompileTime =
248  tryParseLinearWithCompileTimeStep(ParseString, PKind, StepOrPos);
249  if (HasLinearCompileTime != ParseRet::None)
250  return HasLinearCompileTime;
251 
252  const ParseRet HasUniform = tryParseUniform(ParseString, PKind, StepOrPos);
253  if (HasUniform != ParseRet::None)
254  return HasUniform;
255 
256  return ParseRet::None;
257 }
258 
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`.
262 ///
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;
273 
274  if (!isPowerOf2_64(Val))
275  return ParseRet::Error;
276 
277  Alignment = Align(Val);
278 
279  return ParseRet::OK;
280  }
281 
282  return ParseRet::None;
283 }
284 } // namespace
285 
286 // Format of the ABI name:
287 // _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)]
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;
293 
294  // Parse the fixed size part of the manled name
295  if (!MangledName.consume_front("_ZGV"))
296  return None;
297 
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;
303 
304  // Extract <mask>.
305  bool IsMasked;
306  if (tryParseMask(MangledName, IsMasked) != ParseRet::OK)
307  return None;
308 
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;
314 
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);
323 
324  // Bail off if there is a parsing error in the parsing of the parameter.
325  if (ParamFound == ParseRet::Error)
326  return None;
327 
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;
335 
336  // Add the parameter.
337  Parameters.push_back({ParameterPos, PKind, StepOrPos, Alignment});
338  }
339  } while (ParamFound == ParseRet::OK);
340 
341  // A valid MangledName mus have at least one valid entry in the
342  // <parameters>.
343  if (Parameters.empty())
344  return None;
345 
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;
350 
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 != '('; });
355 
356  if (ScalarName.empty())
357  return None;
358 
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;
370  }
371 
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});
377  }
378 
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;
387  });
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");
392 
393  const VFShape Shape({VF, IsScalable, ISA, Parameters});
394  return VFInfo({Shape, ScalarName, VectorName});
395 }
396 
398  const VFParamKind ParamKind = StringSwitch<VFParamKind>(Token)
399  .Case("v", VFParamKind::Vector)
410 
411  if (ParamKind != VFParamKind::Unknown)
412  return ParamKind;
413 
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");
418 }
LLVM_NODISCARD StringRef take_front(size_t N=1) const
Return a StringRef equal to &#39;this&#39; but with only the first N elements remaining.
Definition: StringRef.h:601
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
static bool IsMasked(Instruction *I)
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition: StringRef.h:663
auto count_if(R &&Range, UnaryPredicate P) -> typename std::iterator_traits< decltype(adl_begin(Range))>::difference_type
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
Definition: STLExtras.h:1239
Contains the information about the kind of vectorization available.
Definition: VectorUtils.h:79
LLVM_NODISCARD StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
Definition: StringRef.h:803
Holds the VFShape for a specific scalar to vector function mapping.
Definition: VectorUtils.h:92
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:67
LLVM_NODISCARD StringRef drop_front(size_t N=1) const
Return a StringRef equal to &#39;this&#39; but with the first N elements dropped.
Definition: StringRef.h:634
LLVM_NODISCARD R Default(T Value)
Definition: StringSwitch.h:181
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:140
LLVM_NODISCARD StringRef take_while(function_ref< bool(char)> F) const
Return the longest prefix of &#39;this&#39; such that every character in the prefix satisfies the given predi...
Definition: StringRef.h:620
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:526
VFISAKind
Describes the type of Instruction Set Architecture.
Definition: VectorUtils.h:43
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:42
Encapsulates information needed to describe a parameter.
Definition: VectorUtils.h:59
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition: MathExtras.h:470
Optional< VFInfo > tryDemangleForVFABI(StringRef MangledName)
Function to contruct a VFInfo out of a mangled names in the following format:
size_t size() const
Definition: SmallVector.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:40
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
VFParamKind
Describes the type of Parameters.
Definition: VectorUtils.h:24
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:55
ParseRet
Utilities for the Vector Function ABI name parser.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition: StringRef.h:673
VFParamKind getVFParamKindFromString(const StringRef Token)
Retrieve the VFParamKind from a string token.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48