blob: 83c3c048e41d6fea81978e6717f14caf87aa0845 [file] [log] [blame]
Peter Collingbournebee583f2011-10-06 13:03:08 +00001//===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This tablegen backend is responsible for emitting arm_neon.h, which includes
11// a declaration and definition of each function specified by the ARM NEON
12// compiler interface. See ARM document DUI0348B.
13//
14// Each NEON instruction is implemented in terms of 1 or more functions which
15// are suffixed with the element type of the input vectors. Functions may be
16// implemented in terms of generic vector operations such as +, *, -, etc. or
17// by calling a __builtin_-prefixed function which will be handled by clang's
18// CodeGen library.
19//
20// Additional validation code can be generated by this file when runHeader() is
James Molloydee4ab02014-06-17 13:11:27 +000021// called, rather than the normal run() entry point.
22//
23// See also the documentation in include/clang/Basic/arm_neon.td.
Peter Collingbournebee583f2011-10-06 13:03:08 +000024//
25//===----------------------------------------------------------------------===//
26
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +000027#include "llvm/ADT/DenseMap.h"
Peter Collingbournebee583f2011-10-06 13:03:08 +000028#include "llvm/ADT/SmallString.h"
29#include "llvm/ADT/SmallVector.h"
30#include "llvm/ADT/StringExtras.h"
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +000031#include "llvm/ADT/StringMap.h"
David Blaikie8a40f702012-01-17 06:56:22 +000032#include "llvm/Support/ErrorHandling.h"
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +000033#include "llvm/TableGen/Error.h"
34#include "llvm/TableGen/Record.h"
James Molloydee4ab02014-06-17 13:11:27 +000035#include "llvm/TableGen/SetTheory.h"
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +000036#include "llvm/TableGen/TableGenBackend.h"
Peter Collingbournebee583f2011-10-06 13:03:08 +000037#include <string>
James Molloydee4ab02014-06-17 13:11:27 +000038#include <sstream>
39#include <vector>
40#include <map>
41#include <algorithm>
Peter Collingbournebee583f2011-10-06 13:03:08 +000042using namespace llvm;
43
James Molloydee4ab02014-06-17 13:11:27 +000044namespace {
45
46// While globals are generally bad, this one allows us to perform assertions
47// liberally and somehow still trace them back to the def they indirectly
48// came from.
49static Record *CurrentRecord = nullptr;
50static void assert_with_loc(bool Assertion, const std::string &Str) {
51 if (!Assertion) {
52 if (CurrentRecord)
53 PrintFatalError(CurrentRecord->getLoc(), Str);
54 else
55 PrintFatalError(Str);
56 }
57}
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +000058
59enum ClassKind {
60 ClassNone,
James Molloydee4ab02014-06-17 13:11:27 +000061 ClassI, // generic integer instruction, e.g., "i8" suffix
62 ClassS, // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix
63 ClassW, // width-specific instruction, e.g., "8" suffix
64 ClassB, // bitcast arguments with enum argument to specify type
65 ClassL, // Logical instructions which are op instructions
66 // but we need to not emit any suffix for in our
67 // tests.
68 ClassNoTest // Instructions which we do not test since they are
69 // not TRUE instructions.
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +000070};
71
72/// NeonTypeFlags - Flags to identify the types for overloaded Neon
73/// builtins. These must be kept in sync with the flags in
74/// include/clang/Basic/TargetBuiltins.h.
James Molloydee4ab02014-06-17 13:11:27 +000075namespace NeonTypeFlags {
76enum { EltTypeMask = 0xf, UnsignedFlag = 0x10, QuadFlag = 0x20 };
77
78enum EltType {
79 Int8,
80 Int16,
81 Int32,
82 Int64,
83 Poly8,
84 Poly16,
85 Poly64,
86 Poly128,
87 Float16,
88 Float32,
89 Float64
90};
91}
92
93class Intrinsic;
94class NeonEmitter;
95class Type;
96class Variable;
97
98//===----------------------------------------------------------------------===//
99// TypeSpec
100//===----------------------------------------------------------------------===//
101
102/// A TypeSpec is just a simple wrapper around a string, but gets its own type
103/// for strong typing purposes.
104///
105/// A TypeSpec can be used to create a type.
106class TypeSpec : public std::string {
107public:
108 static std::vector<TypeSpec> fromTypeSpecs(StringRef Str) {
109 std::vector<TypeSpec> Ret;
110 TypeSpec Acc;
111 for (char I : Str.str()) {
112 if (islower(I)) {
113 Acc.push_back(I);
114 Ret.push_back(TypeSpec(Acc));
115 Acc.clear();
116 } else {
117 Acc.push_back(I);
118 }
119 }
120 return Ret;
121 }
122};
123
124//===----------------------------------------------------------------------===//
125// Type
126//===----------------------------------------------------------------------===//
127
128/// A Type. Not much more to say here.
129class Type {
130private:
131 TypeSpec TS;
132
133 bool Float, Signed, Void, Poly, Constant, Pointer;
134 // ScalarForMangling and NoManglingQ are really not suited to live here as
135 // they are not related to the type. But they live in the TypeSpec (not the
136 // prototype), so this is really the only place to store them.
137 bool ScalarForMangling, NoManglingQ;
138 unsigned Bitwidth, ElementBitwidth, NumVectors;
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +0000139
140public:
James Molloydee4ab02014-06-17 13:11:27 +0000141 Type()
142 : Float(false), Signed(false), Void(true), Poly(false), Constant(false),
143 Pointer(false), ScalarForMangling(false), NoManglingQ(false),
144 Bitwidth(0), ElementBitwidth(0), NumVectors(0) {}
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +0000145
James Molloydee4ab02014-06-17 13:11:27 +0000146 Type(TypeSpec TS, char CharMod)
147 : TS(TS), Float(false), Signed(false), Void(false), Poly(false),
148 Constant(false), Pointer(false), ScalarForMangling(false),
149 NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) {
150 applyModifier(CharMod);
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +0000151 }
152
James Molloydee4ab02014-06-17 13:11:27 +0000153 /// Returns a type representing "void".
154 static Type getVoid() { return Type(); }
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +0000155
James Molloydee4ab02014-06-17 13:11:27 +0000156 bool operator==(const Type &Other) const { return str() == Other.str(); }
157 bool operator!=(const Type &Other) const { return !operator==(Other); }
158
159 //
160 // Query functions
161 //
162 bool isScalarForMangling() const { return ScalarForMangling; }
163 bool noManglingQ() const { return NoManglingQ; }
164
165 bool isPointer() const { return Pointer; }
166 bool isFloating() const { return Float; }
167 bool isInteger() const { return !Float && !Poly; }
168 bool isSigned() const { return Signed; }
169 bool isScalar() const { return NumVectors == 0; }
170 bool isVector() const { return NumVectors > 0; }
171 bool isFloat() const { return Float && ElementBitwidth == 32; }
172 bool isDouble() const { return Float && ElementBitwidth == 64; }
173 bool isHalf() const { return Float && ElementBitwidth == 16; }
174 bool isPoly() const { return Poly; }
175 bool isChar() const { return ElementBitwidth == 8; }
176 bool isShort() const { return !Float && ElementBitwidth == 16; }
177 bool isInt() const { return !Float && ElementBitwidth == 32; }
178 bool isLong() const { return !Float && ElementBitwidth == 64; }
179 bool isVoid() const { return Void; }
180 unsigned getNumElements() const { return Bitwidth / ElementBitwidth; }
181 unsigned getSizeInBits() const { return Bitwidth; }
182 unsigned getElementSizeInBits() const { return ElementBitwidth; }
183 unsigned getNumVectors() const { return NumVectors; }
184
185 //
186 // Mutator functions
187 //
188 void makeUnsigned() { Signed = false; }
189 void makeSigned() { Signed = true; }
190 void makeInteger(unsigned ElemWidth, bool Sign) {
191 Float = false;
192 Poly = false;
193 Signed = Sign;
194 ElementBitwidth = ElemWidth;
195 }
196 void makeScalar() {
197 Bitwidth = ElementBitwidth;
198 NumVectors = 0;
199 }
200 void makeOneVector() {
201 assert(isVector());
202 NumVectors = 1;
203 }
204 void doubleLanes() {
205 assert_with_loc(Bitwidth != 128, "Can't get bigger than 128!");
206 Bitwidth = 128;
207 }
208 void halveLanes() {
209 assert_with_loc(Bitwidth != 64, "Can't get smaller than 64!");
210 Bitwidth = 64;
211 }
212
213 /// Return the C string representation of a type, which is the typename
214 /// defined in stdint.h or arm_neon.h.
215 std::string str() const;
216
217 /// Return the string representation of a type, which is an encoded
218 /// string for passing to the BUILTIN() macro in Builtins.def.
219 std::string builtin_str() const;
220
221 /// Return the value in NeonTypeFlags for this type.
222 unsigned getNeonEnum() const;
223
224 /// Parse a type from a stdint.h or arm_neon.h typedef name,
225 /// for example uint32x2_t or int64_t.
226 static Type fromTypedefName(StringRef Name);
227
228private:
229 /// Creates the type based on the typespec string in TS.
230 /// Sets "Quad" to true if the "Q" or "H" modifiers were
231 /// seen. This is needed by applyModifier as some modifiers
232 /// only take effect if the type size was changed by "Q" or "H".
233 void applyTypespec(bool &Quad);
234 /// Applies a prototype modifier to the type.
235 void applyModifier(char Mod);
236};
237
238//===----------------------------------------------------------------------===//
239// Variable
240//===----------------------------------------------------------------------===//
241
242/// A variable is a simple class that just has a type and a name.
243class Variable {
244 Type T;
245 std::string N;
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +0000246
247public:
James Molloydee4ab02014-06-17 13:11:27 +0000248 Variable() : T(Type::getVoid()), N("") {}
249 Variable(Type T, std::string N) : T(T), N(N) {}
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +0000250
James Molloydee4ab02014-06-17 13:11:27 +0000251 Type getType() const { return T; }
252 std::string getName() const { return "__" + N; }
253};
254
255//===----------------------------------------------------------------------===//
256// Intrinsic
257//===----------------------------------------------------------------------===//
258
259/// The main grunt class. This represents an instantiation of an intrinsic with
260/// a particular typespec and prototype.
261class Intrinsic {
262 /// The Record this intrinsic was created from.
263 Record *R;
264 /// The unmangled name and prototype.
265 std::string Name, Proto;
266 /// The input and output typespecs. InTS == OutTS except when
267 /// CartesianProductOfTypes is 1 - this is the case for vreinterpret.
268 TypeSpec OutTS, InTS;
269 /// The base class kind. Most intrinsics use ClassS, which has full type
270 /// info for integers (s32/u32). Some use ClassI, which doesn't care about
271 /// signedness (i32), while some (ClassB) have no type at all, only a width
272 /// (32).
273 ClassKind CK;
274 /// The list of DAGs for the body. May be empty, in which case we should
275 /// emit a builtin call.
276 ListInit *Body;
277 /// The architectural #ifdef guard.
278 std::string Guard;
279 /// Set if the Unvailable bit is 1. This means we don't generate a body,
280 /// just an "unavailable" attribute on a declaration.
281 bool IsUnavailable;
282
283 /// The types of return value [0] and parameters [1..].
284 std::vector<Type> Types;
285 /// The local variables defined.
286 std::map<std::string, Variable> Variables;
287 /// NeededEarly - set if any other intrinsic depends on this intrinsic.
288 bool NeededEarly;
289 /// UseMacro - set if we should implement using a macro or unset for a
290 /// function.
291 bool UseMacro;
292 /// The set of intrinsics that this intrinsic uses/requires.
293 std::set<Intrinsic *> Dependencies;
294 /// The "base type", which is Type('d', OutTS). InBaseType is only
295 /// different if CartesianProductOfTypes = 1 (for vreinterpret).
296 Type BaseType, InBaseType;
297 /// The return variable.
298 Variable RetVar;
299 /// A postfix to apply to every variable. Defaults to "".
300 std::string VariablePostfix;
301
302 NeonEmitter &Emitter;
303 std::stringstream OS;
304
305public:
306 Intrinsic(Record *R, StringRef Name, StringRef Proto, TypeSpec OutTS,
307 TypeSpec InTS, ClassKind CK, ListInit *Body, NeonEmitter &Emitter,
308 StringRef Guard, bool IsUnavailable)
309 : R(R), Name(Name.str()), Proto(Proto.str()), OutTS(OutTS), InTS(InTS),
310 CK(CK), Body(Body), Guard(Guard.str()), IsUnavailable(IsUnavailable),
311 NeededEarly(false), UseMacro(false), BaseType(OutTS, 'd'),
312 InBaseType(InTS, 'd'), Emitter(Emitter) {
313 // If this builtin takes an immediate argument, we need to #define it rather
314 // than use a standard declaration, so that SemaChecking can range check
315 // the immediate passed by the user.
316 if (Proto.find('i') != std::string::npos)
317 UseMacro = true;
318
319 // Pointer arguments need to use macros to avoid hiding aligned attributes
320 // from the pointer type.
321 if (Proto.find('p') != std::string::npos ||
322 Proto.find('c') != std::string::npos)
323 UseMacro = true;
324
325 // It is not permitted to pass or return an __fp16 by value, so intrinsics
326 // taking a scalar float16_t must be implemented as macros.
327 if (OutTS.find('h') != std::string::npos &&
328 Proto.find('s') != std::string::npos)
329 UseMacro = true;
330
331 // Modify the TypeSpec per-argument to get a concrete Type, and create
332 // known variables for each.
333 // Types[0] is the return value.
334 Types.push_back(Type(OutTS, Proto[0]));
335 for (unsigned I = 1; I < Proto.size(); ++I)
336 Types.push_back(Type(InTS, Proto[I]));
337 }
338
339 /// Get the Record that this intrinsic is based off.
340 Record *getRecord() const { return R; }
341 /// Get the set of Intrinsics that this intrinsic calls.
342 /// this is the set of immediate dependencies, NOT the
343 /// transitive closure.
344 const std::set<Intrinsic *> &getDependencies() const { return Dependencies; }
345 /// Get the architectural guard string (#ifdef).
346 std::string getGuard() const { return Guard; }
347 /// Get the non-mangled name.
348 std::string getName() const { return Name; }
349
350 /// Return true if the intrinsic takes an immediate operand.
351 bool hasImmediate() const {
352 return Proto.find('i') != std::string::npos;
353 }
354 /// Return the parameter index of the immediate operand.
355 unsigned getImmediateIdx() const {
356 assert(hasImmediate());
357 unsigned Idx = Proto.find('i');
358 assert(Idx > 0 && "Can't return an immediate!");
359 return Idx - 1;
360 }
361
362 /// Return true if the intrinsic takes an splat operand.
363 bool hasSplat() const { return Proto.find('a') != std::string::npos; }
364 /// Return the parameter index of the splat operand.
365 unsigned getSplatIdx() const {
366 assert(hasSplat());
367 unsigned Idx = Proto.find('a');
368 assert(Idx > 0 && "Can't return a splat!");
369 return Idx - 1;
370 }
371
372 unsigned getNumParams() const { return Proto.size() - 1; }
373 Type getReturnType() const { return Types[0]; }
374 Type getParamType(unsigned I) const { return Types[I + 1]; }
375 Type getBaseType() const { return BaseType; }
376 /// Return the raw prototype string.
377 std::string getProto() const { return Proto; }
378
379 /// Return true if the prototype has a scalar argument.
380 /// This does not return true for the "splat" code ('a').
381 bool protoHasScalar();
382
383 /// Return the index that parameter PIndex will sit at
384 /// in a generated function call. This is often just PIndex,
385 /// but may not be as things such as multiple-vector operands
386 /// and sret parameters need to be taken into accont.
387 unsigned getGeneratedParamIdx(unsigned PIndex) {
388 unsigned Idx = 0;
389 if (getReturnType().getNumVectors() > 1)
390 // Multiple vectors are passed as sret.
391 ++Idx;
392
393 for (unsigned I = 0; I < PIndex; ++I)
394 Idx += std::max(1U, getParamType(I).getNumVectors());
395
396 return Idx;
397 }
398
399 bool hasBody() const { return Body && Body->getValues().size() > 0; }
400
401 void setNeededEarly() { NeededEarly = true; }
402
403 bool operator<(const Intrinsic &Other) const {
404 // Sort lexicographically on a two-tuple (Guard, Name)
405 if (Guard != Other.Guard)
406 return Guard < Other.Guard;
407 return Name < Other.Name;
408 }
409
410 ClassKind getClassKind(bool UseClassBIfScalar = false) {
411 if (UseClassBIfScalar && !protoHasScalar())
412 return ClassB;
413 return CK;
414 }
415
416 /// Return the name, mangled with type information.
417 /// If ForceClassS is true, use ClassS (u32/s32) instead
418 /// of the intrinsic's own type class.
419 std::string getMangledName(bool ForceClassS = false);
420 /// Return the type code for a builtin function call.
421 std::string getInstTypeCode(Type T, ClassKind CK);
422 /// Return the type string for a BUILTIN() macro in Builtins.def.
423 std::string getBuiltinTypeStr();
424
425 /// Generate the intrinsic, returning code.
426 std::string generate();
427 /// Perform type checking and populate the dependency graph, but
428 /// don't generate code yet.
429 void indexBody();
430
431private:
432 std::string mangleName(std::string Name, ClassKind CK);
433
434 void initVariables();
435 std::string replaceParamsIn(std::string S);
436
437 void emitBodyAsBuiltinCall();
438 std::pair<Type, std::string> emitDagArg(Init *Arg, std::string ArgName);
439 std::pair<Type, std::string> emitDagSaveTemp(DagInit *DI);
440 std::pair<Type, std::string> emitDagSplat(DagInit *DI);
441 std::pair<Type, std::string> emitDagDup(DagInit *DI);
442 std::pair<Type, std::string> emitDagShuffle(DagInit *DI);
443 std::pair<Type, std::string> emitDagCast(DagInit *DI, bool IsBitCast);
444 std::pair<Type, std::string> emitDagCall(DagInit *DI);
445 std::pair<Type, std::string> emitDagNameReplace(DagInit *DI);
446 std::pair<Type, std::string> emitDagLiteral(DagInit *DI);
447 std::pair<Type, std::string> emitDagOp(DagInit *DI);
448 std::pair<Type, std::string> emitDag(DagInit *DI);
449
450 void emitReturn();
451 void emitBody();
452 void emitShadowedArgs();
453 void emitNewLine();
454 void emitClosingBrace();
455 void emitOpeningBrace();
456 void emitPrototype();
457};
458
459//===----------------------------------------------------------------------===//
460// NeonEmitter
461//===----------------------------------------------------------------------===//
462
463class NeonEmitter {
464 RecordKeeper &Records;
465 DenseMap<Record *, ClassKind> ClassMap;
466 std::map<std::string, std::vector<Intrinsic *>> IntrinsicMap;
467 unsigned UniqueNumber;
468
469 void createIntrinsic(Record *R, SmallVectorImpl<Intrinsic *> &Out);
470 void genBuiltinsDef(raw_ostream &OS, SmallVectorImpl<Intrinsic *> &Defs);
471 void genOverloadTypeCheckCode(raw_ostream &OS,
472 SmallVectorImpl<Intrinsic *> &Defs);
473 void genIntrinsicRangeCheckCode(raw_ostream &OS,
474 SmallVectorImpl<Intrinsic *> &Defs);
475
476public:
477 /// Called by Intrinsic - this attempts to get an intrinsic that takes
478 /// the given types as arguments.
479 Intrinsic *getIntrinsic(StringRef Name, ArrayRef<Type> Types);
480
481 /// Called by Intrinsic - returns a globally-unique number.
482 unsigned getUniqueNumber() { return UniqueNumber++; }
483
484 NeonEmitter(RecordKeeper &R) : Records(R), UniqueNumber(0) {
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +0000485 Record *SI = R.getClass("SInst");
486 Record *II = R.getClass("IInst");
487 Record *WI = R.getClass("WInst");
Michael Gottesmanfc89cc22013-04-16 21:18:42 +0000488 Record *SOpI = R.getClass("SOpInst");
489 Record *IOpI = R.getClass("IOpInst");
490 Record *WOpI = R.getClass("WOpInst");
491 Record *LOpI = R.getClass("LOpInst");
492 Record *NoTestOpI = R.getClass("NoTestOpInst");
493
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +0000494 ClassMap[SI] = ClassS;
495 ClassMap[II] = ClassI;
496 ClassMap[WI] = ClassW;
Michael Gottesmanfc89cc22013-04-16 21:18:42 +0000497 ClassMap[SOpI] = ClassS;
498 ClassMap[IOpI] = ClassI;
499 ClassMap[WOpI] = ClassW;
500 ClassMap[LOpI] = ClassL;
501 ClassMap[NoTestOpI] = ClassNoTest;
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +0000502 }
503
504 // run - Emit arm_neon.h.inc
505 void run(raw_ostream &o);
506
507 // runHeader - Emit all the __builtin prototypes used in arm_neon.h
508 void runHeader(raw_ostream &o);
509
510 // runTests - Emit tests for all the Neon intrinsics.
511 void runTests(raw_ostream &o);
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +0000512};
James Molloydee4ab02014-06-17 13:11:27 +0000513
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +0000514} // end anonymous namespace
515
James Molloydee4ab02014-06-17 13:11:27 +0000516//===----------------------------------------------------------------------===//
517// Type implementation
518//===----------------------------------------------------------------------===//
Peter Collingbournebee583f2011-10-06 13:03:08 +0000519
James Molloydee4ab02014-06-17 13:11:27 +0000520std::string Type::str() const {
521 if (Void)
Peter Collingbournebee583f2011-10-06 13:03:08 +0000522 return "void";
James Molloydee4ab02014-06-17 13:11:27 +0000523 std::string S;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000524
James Molloydee4ab02014-06-17 13:11:27 +0000525 if (!Signed && isInteger())
526 S += "u";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000527
James Molloydee4ab02014-06-17 13:11:27 +0000528 if (Poly)
529 S += "poly";
530 else if (Float)
531 S += "float";
532 else
533 S += "int";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000534
James Molloydee4ab02014-06-17 13:11:27 +0000535 S += utostr(ElementBitwidth);
536 if (isVector())
537 S += "x" + utostr(getNumElements());
538 if (NumVectors > 1)
539 S += "x" + utostr(NumVectors);
540 S += "_t";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000541
James Molloydee4ab02014-06-17 13:11:27 +0000542 if (Constant)
543 S += " const";
544 if (Pointer)
545 S += " *";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000546
James Molloydee4ab02014-06-17 13:11:27 +0000547 return S;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000548}
549
James Molloydee4ab02014-06-17 13:11:27 +0000550std::string Type::builtin_str() const {
551 std::string S;
552 if (isVoid())
553 return "v";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000554
James Molloydee4ab02014-06-17 13:11:27 +0000555 if (Pointer)
556 // All pointers are void pointers.
557 S += "v";
558 else if (isInteger())
559 switch (ElementBitwidth) {
560 case 8: S += "c"; break;
561 case 16: S += "s"; break;
562 case 32: S += "i"; break;
563 case 64: S += "Wi"; break;
564 case 128: S += "LLLi"; break;
565 default: assert(0 && "Unhandled case!");
566 }
567 else
568 switch (ElementBitwidth) {
569 case 16: S += "h"; break;
570 case 32: S += "f"; break;
571 case 64: S += "d"; break;
572 default: assert(0 && "Unhandled case!");
573 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000574
James Molloydee4ab02014-06-17 13:11:27 +0000575 if (isChar() && !Pointer)
576 // Make chars explicitly signed.
577 S = "S" + S;
578 else if (isInteger() && !Pointer && !Signed)
579 S = "U" + S;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000580
James Molloydee4ab02014-06-17 13:11:27 +0000581 if (isScalar()) {
582 if (Constant) S += "C";
583 if (Pointer) S += "*";
584 return S;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000585 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000586
James Molloydee4ab02014-06-17 13:11:27 +0000587 std::string Ret;
588 for (unsigned I = 0; I < NumVectors; ++I)
589 Ret += "V" + utostr(getNumElements()) + S;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000590
James Molloydee4ab02014-06-17 13:11:27 +0000591 return Ret;
592}
Peter Collingbournebee583f2011-10-06 13:03:08 +0000593
James Molloydee4ab02014-06-17 13:11:27 +0000594unsigned Type::getNeonEnum() const {
595 unsigned Addend;
596 switch (ElementBitwidth) {
597 case 8: Addend = 0; break;
598 case 16: Addend = 1; break;
599 case 32: Addend = 2; break;
600 case 64: Addend = 3; break;
601 case 128: Addend = 4; break;
Craig Topperc7193c42014-06-18 03:13:41 +0000602 default: llvm_unreachable("Unhandled element bitwidth!");
Peter Collingbournebee583f2011-10-06 13:03:08 +0000603 }
604
James Molloydee4ab02014-06-17 13:11:27 +0000605 unsigned Base = (unsigned)NeonTypeFlags::Int8 + Addend;
606 if (Poly) {
607 // Adjustment needed because Poly32 doesn't exist.
608 if (Addend >= 2)
609 --Addend;
610 Base = (unsigned)NeonTypeFlags::Poly8 + Addend;
611 }
612 if (Float) {
613 assert(Addend != 0 && "Float8 doesn't exist!");
614 Base = (unsigned)NeonTypeFlags::Float16 + (Addend - 1);
615 }
616
617 if (Bitwidth == 128)
618 Base |= (unsigned)NeonTypeFlags::QuadFlag;
619 if (isInteger() && !Signed)
620 Base |= (unsigned)NeonTypeFlags::UnsignedFlag;
621
622 return Base;
623}
624
625Type Type::fromTypedefName(StringRef Name) {
626 Type T;
627 T.Void = false;
628 T.Float = false;
629 T.Poly = false;
630
631 if (Name.front() == 'u') {
632 T.Signed = false;
633 Name = Name.drop_front();
634 } else {
635 T.Signed = true;
636 }
637
638 if (Name.startswith("float")) {
639 T.Float = true;
640 Name = Name.drop_front(5);
641 } else if (Name.startswith("poly")) {
642 T.Poly = true;
643 Name = Name.drop_front(4);
644 } else {
645 assert(Name.startswith("int"));
646 Name = Name.drop_front(3);
647 }
648
649 unsigned I = 0;
650 for (I = 0; I < Name.size(); ++I) {
651 if (!isdigit(Name[I]))
652 break;
653 }
654 Name.substr(0, I).getAsInteger(10, T.ElementBitwidth);
655 Name = Name.drop_front(I);
656
657 T.Bitwidth = T.ElementBitwidth;
658 T.NumVectors = 1;
659
660 if (Name.front() == 'x') {
661 Name = Name.drop_front();
662 unsigned I = 0;
663 for (I = 0; I < Name.size(); ++I) {
664 if (!isdigit(Name[I]))
665 break;
666 }
667 unsigned NumLanes;
668 Name.substr(0, I).getAsInteger(10, NumLanes);
669 Name = Name.drop_front(I);
670 T.Bitwidth = T.ElementBitwidth * NumLanes;
671 } else {
672 // Was scalar.
673 T.NumVectors = 0;
674 }
675 if (Name.front() == 'x') {
676 Name = Name.drop_front();
677 unsigned I = 0;
678 for (I = 0; I < Name.size(); ++I) {
679 if (!isdigit(Name[I]))
680 break;
681 }
682 Name.substr(0, I).getAsInteger(10, T.NumVectors);
683 Name = Name.drop_front(I);
684 }
685
686 assert(Name.startswith("_t") && "Malformed typedef!");
687 return T;
688}
689
690void Type::applyTypespec(bool &Quad) {
691 std::string S = TS;
692 ScalarForMangling = false;
693 Void = false;
694 Poly = Float = false;
695 ElementBitwidth = ~0U;
696 Signed = true;
697 NumVectors = 1;
698
699 for (char I : S) {
700 switch (I) {
701 case 'S':
702 ScalarForMangling = true;
703 break;
704 case 'H':
705 NoManglingQ = true;
706 Quad = true;
707 break;
708 case 'Q':
709 Quad = true;
710 break;
711 case 'P':
712 Poly = true;
713 break;
714 case 'U':
715 Signed = false;
716 break;
717 case 'c':
718 ElementBitwidth = 8;
719 break;
720 case 'h':
721 Float = true;
722 // Fall through
723 case 's':
724 ElementBitwidth = 16;
725 break;
726 case 'f':
727 Float = true;
728 // Fall through
729 case 'i':
730 ElementBitwidth = 32;
731 break;
732 case 'd':
733 Float = true;
734 // Fall through
735 case 'l':
736 ElementBitwidth = 64;
737 break;
738 case 'k':
739 ElementBitwidth = 128;
740 // Poly doesn't have a 128x1 type.
741 if (Poly)
742 NumVectors = 0;
743 break;
744 default:
745 assert(0 && "Unhandled type code!");
746 }
747 }
748 assert(ElementBitwidth != ~0U && "Bad element bitwidth!");
749
750 Bitwidth = Quad ? 128 : 64;
751}
752
753void Type::applyModifier(char Mod) {
754 bool AppliedQuad = false;
755 applyTypespec(AppliedQuad);
756
757 switch (Mod) {
758 case 'v':
759 Void = true;
760 break;
761 case 't':
762 if (Poly) {
763 Poly = false;
764 Signed = false;
765 }
766 break;
767 case 'b':
768 Signed = false;
769 Float = false;
770 Poly = false;
771 NumVectors = 0;
772 Bitwidth = ElementBitwidth;
773 break;
774 case '$':
775 Signed = true;
776 Float = false;
777 Poly = false;
778 NumVectors = 0;
779 Bitwidth = ElementBitwidth;
780 break;
781 case 'u':
782 Signed = false;
783 Poly = false;
784 Float = false;
785 break;
786 case 'x':
787 Signed = true;
788 assert(!Poly && "'u' can't be used with poly types!");
789 Float = false;
790 break;
791 case 'o':
792 Bitwidth = ElementBitwidth = 64;
793 NumVectors = 0;
794 Float = true;
795 break;
796 case 'y':
797 Bitwidth = ElementBitwidth = 32;
798 NumVectors = 0;
799 Float = true;
800 break;
801 case 'f':
802 // Special case - if we're half-precision, a floating
803 // point argument needs to be 128-bits (double size).
804 if (isHalf())
805 Bitwidth = 128;
806 Float = true;
807 ElementBitwidth = 32;
808 break;
809 case 'F':
810 Float = true;
811 ElementBitwidth = 64;
812 break;
813 case 'g':
814 if (AppliedQuad)
815 Bitwidth /= 2;
816 break;
817 case 'j':
818 if (!AppliedQuad)
819 Bitwidth *= 2;
820 break;
821 case 'w':
822 ElementBitwidth *= 2;
823 Bitwidth *= 2;
824 break;
825 case 'n':
826 ElementBitwidth *= 2;
827 break;
828 case 'i':
829 Float = false;
830 Poly = false;
831 ElementBitwidth = Bitwidth = 32;
832 NumVectors = 0;
833 Signed = true;
834 break;
835 case 'l':
836 Float = false;
837 Poly = false;
838 ElementBitwidth = Bitwidth = 64;
839 NumVectors = 0;
840 Signed = false;
841 break;
842 case 'z':
843 ElementBitwidth /= 2;
844 Bitwidth = ElementBitwidth;
845 NumVectors = 0;
846 break;
847 case 'r':
848 ElementBitwidth *= 2;
849 Bitwidth = ElementBitwidth;
850 NumVectors = 0;
851 break;
852 case 's':
853 case 'a':
854 Bitwidth = ElementBitwidth;
855 NumVectors = 0;
856 break;
857 case 'k':
858 Bitwidth *= 2;
859 break;
860 case 'c':
861 Constant = true;
862 // Fall through
863 case 'p':
864 Pointer = true;
865 Bitwidth = ElementBitwidth;
866 NumVectors = 0;
867 break;
868 case 'h':
869 ElementBitwidth /= 2;
870 break;
871 case 'q':
872 ElementBitwidth /= 2;
873 Bitwidth *= 2;
874 break;
875 case 'e':
876 ElementBitwidth /= 2;
877 Signed = false;
878 break;
879 case 'm':
880 ElementBitwidth /= 2;
881 Bitwidth /= 2;
882 break;
883 case 'd':
884 break;
885 case '2':
886 NumVectors = 2;
887 break;
888 case '3':
889 NumVectors = 3;
890 break;
891 case '4':
892 NumVectors = 4;
893 break;
894 case 'B':
895 NumVectors = 2;
896 if (!AppliedQuad)
897 Bitwidth *= 2;
898 break;
899 case 'C':
900 NumVectors = 3;
901 if (!AppliedQuad)
902 Bitwidth *= 2;
903 break;
904 case 'D':
905 NumVectors = 4;
906 if (!AppliedQuad)
907 Bitwidth *= 2;
908 break;
909 default:
910 assert(0 && "Unhandled character!");
911 }
912}
913
914//===----------------------------------------------------------------------===//
915// Intrinsic implementation
916//===----------------------------------------------------------------------===//
917
918std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) {
919 char typeCode = '\0';
920 bool printNumber = true;
921
922 if (CK == ClassB)
923 return "";
924
925 if (T.isPoly())
926 typeCode = 'p';
927 else if (T.isInteger())
928 typeCode = T.isSigned() ? 's' : 'u';
929 else
930 typeCode = 'f';
931
932 if (CK == ClassI) {
933 switch (typeCode) {
934 default:
935 break;
936 case 's':
937 case 'u':
938 case 'p':
939 typeCode = 'i';
940 break;
941 }
942 }
943 if (CK == ClassB) {
944 typeCode = '\0';
945 }
946
947 std::string S;
948 if (typeCode != '\0')
949 S.push_back(typeCode);
950 if (printNumber)
951 S += utostr(T.getElementSizeInBits());
952
953 return S;
954}
955
956std::string Intrinsic::getBuiltinTypeStr() {
957 ClassKind LocalCK = getClassKind(true);
958 std::string S;
959
960 Type RetT = getReturnType();
961 if ((LocalCK == ClassI || LocalCK == ClassW) && RetT.isScalar() &&
962 !RetT.isFloating())
963 RetT.makeInteger(RetT.getElementSizeInBits(), false);
964
Peter Collingbournebee583f2011-10-06 13:03:08 +0000965 // Since the return value must be one type, return a vector type of the
966 // appropriate width which we will bitcast. An exception is made for
967 // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
968 // fashion, storing them to a pointer arg.
James Molloydee4ab02014-06-17 13:11:27 +0000969 if (RetT.getNumVectors() > 1) {
970 S += "vv*"; // void result with void* first argument
971 } else {
972 if (RetT.isPoly())
973 RetT.makeInteger(RetT.getElementSizeInBits(), false);
974 if (!RetT.isScalar() && !RetT.isSigned())
975 RetT.makeSigned();
Peter Collingbournebee583f2011-10-06 13:03:08 +0000976
James Molloydee4ab02014-06-17 13:11:27 +0000977 bool ForcedVectorFloatingType = Proto[0] == 'F' || Proto[0] == 'f';
978 if (LocalCK == ClassB && !RetT.isScalar() && !ForcedVectorFloatingType)
979 // Cast to vector of 8-bit elements.
980 RetT.makeInteger(8, true);
981
982 S += RetT.builtin_str();
Peter Collingbournebee583f2011-10-06 13:03:08 +0000983 }
984
James Molloydee4ab02014-06-17 13:11:27 +0000985 for (unsigned I = 0; I < getNumParams(); ++I) {
986 Type T = getParamType(I);
987 if (T.isPoly())
988 T.makeInteger(T.getElementSizeInBits(), false);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000989
James Molloydee4ab02014-06-17 13:11:27 +0000990 bool ForcedFloatingType = Proto[I + 1] == 'F' || Proto[I + 1] == 'f';
991 if (LocalCK == ClassB && !T.isScalar() && !ForcedFloatingType)
992 T.makeInteger(8, true);
993 // Halves always get converted to 8-bit elements.
994 if (T.isHalf() && T.isVector() && !T.isScalarForMangling())
995 T.makeInteger(8, true);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000996
James Molloydee4ab02014-06-17 13:11:27 +0000997 if (LocalCK == ClassI)
998 T.makeSigned();
Peter Collingbournebee583f2011-10-06 13:03:08 +0000999
James Molloydee4ab02014-06-17 13:11:27 +00001000 // Constant indices are always just "int".
1001 if (hasImmediate() && getImmediateIdx() == I)
1002 T.makeInteger(32, true);
Michael Gottesman095c58f2013-04-16 22:07:30 +00001003
James Molloydee4ab02014-06-17 13:11:27 +00001004 S += T.builtin_str();
Michael Gottesman095c58f2013-04-16 22:07:30 +00001005 }
James Molloydee4ab02014-06-17 13:11:27 +00001006
1007 // Extra constant integer to hold type class enum for this function, e.g. s8
1008 if (LocalCK == ClassB)
1009 S += "i";
1010
1011 return S;
Michael Gottesman095c58f2013-04-16 22:07:30 +00001012}
1013
James Molloydee4ab02014-06-17 13:11:27 +00001014std::string Intrinsic::getMangledName(bool ForceClassS) {
1015 // Check if the prototype has a scalar operand with the type of the vector
1016 // elements. If not, bitcasting the args will take care of arg checking.
1017 // The actual signedness etc. will be taken care of with special enums.
1018 ClassKind LocalCK = CK;
1019 if (!protoHasScalar())
1020 LocalCK = ClassB;
1021
1022 return mangleName(Name, ForceClassS ? ClassS : LocalCK);
Kevin Qinc076d062013-08-29 07:55:15 +00001023}
1024
James Molloydee4ab02014-06-17 13:11:27 +00001025std::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) {
1026 std::string typeCode = getInstTypeCode(BaseType, LocalCK);
1027 std::string S = Name;
Hao Liu5e4ce1a2013-11-18 06:33:43 +00001028
James Molloydee4ab02014-06-17 13:11:27 +00001029 if (Name == "vcvt_f32_f16" || Name == "vcvt_f32_f64" ||
1030 Name == "vcvt_f64_f32")
1031 return Name;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001032
Michael Gottesman095c58f2013-04-16 22:07:30 +00001033 if (typeCode.size() > 0) {
James Molloydee4ab02014-06-17 13:11:27 +00001034 // If the name ends with _xN (N = 2,3,4), insert the typeCode before _xN.
1035 if (Name.size() >= 3 && isdigit(Name.back()) &&
1036 Name[Name.length() - 2] == 'x' && Name[Name.length() - 3] == '_')
1037 S.insert(S.length() - 3, "_" + typeCode);
Hao Liu5e4ce1a2013-11-18 06:33:43 +00001038 else
James Molloydee4ab02014-06-17 13:11:27 +00001039 S += "_" + typeCode;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001040 }
Michael Gottesman095c58f2013-04-16 22:07:30 +00001041
James Molloydee4ab02014-06-17 13:11:27 +00001042 if (BaseType != InBaseType) {
1043 // A reinterpret - out the input base type at the end.
1044 S += "_" + getInstTypeCode(InBaseType, LocalCK);
1045 }
1046
1047 if (LocalCK == ClassB)
1048 S += "_v";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001049
1050 // Insert a 'q' before the first '_' character so that it ends up before
1051 // _lane or _n on vector-scalar operations.
James Molloydee4ab02014-06-17 13:11:27 +00001052 if (BaseType.getSizeInBits() == 128 && !BaseType.noManglingQ()) {
1053 size_t Pos = S.find('_');
1054 S.insert(Pos, "q");
Kevin Qinc076d062013-08-29 07:55:15 +00001055 }
Michael Gottesman6cd3e562013-04-16 23:00:26 +00001056
James Molloydee4ab02014-06-17 13:11:27 +00001057 char Suffix = '\0';
1058 if (BaseType.isScalarForMangling()) {
1059 switch (BaseType.getElementSizeInBits()) {
1060 case 8: Suffix = 'b'; break;
1061 case 16: Suffix = 'h'; break;
1062 case 32: Suffix = 's'; break;
1063 case 64: Suffix = 'd'; break;
1064 default: assert(0 && "Bad suffix!");
Michael Gottesman6cd3e562013-04-16 23:00:26 +00001065 }
1066 }
James Molloydee4ab02014-06-17 13:11:27 +00001067 if (Suffix != '\0') {
1068 size_t Pos = S.find('_');
1069 S.insert(Pos, &Suffix, 1);
Michael Gottesman6cd3e562013-04-16 23:00:26 +00001070 }
James Molloydee4ab02014-06-17 13:11:27 +00001071
1072 return S;
Michael Gottesman6cd3e562013-04-16 23:00:26 +00001073}
1074
James Molloydee4ab02014-06-17 13:11:27 +00001075std::string Intrinsic::replaceParamsIn(std::string S) {
1076 while (S.find('$') != std::string::npos) {
1077 size_t Pos = S.find('$');
1078 size_t End = Pos + 1;
1079 while (isalpha(S[End]))
1080 ++End;
Michael Gottesman6cd3e562013-04-16 23:00:26 +00001081
James Molloydee4ab02014-06-17 13:11:27 +00001082 std::string VarName = S.substr(Pos + 1, End - Pos - 1);
1083 assert_with_loc(Variables.find(VarName) != Variables.end(),
1084 "Variable not defined!");
1085 S.replace(Pos, End - Pos, Variables.find(VarName)->second.getName());
Michael Gottesman6cd3e562013-04-16 23:00:26 +00001086 }
1087
James Molloydee4ab02014-06-17 13:11:27 +00001088 return S;
Michael Gottesman6cd3e562013-04-16 23:00:26 +00001089}
1090
James Molloydee4ab02014-06-17 13:11:27 +00001091void Intrinsic::initVariables() {
1092 Variables.clear();
Michael Gottesman6cd3e562013-04-16 23:00:26 +00001093
James Molloydee4ab02014-06-17 13:11:27 +00001094 // Modify the TypeSpec per-argument to get a concrete Type, and create
1095 // known variables for each.
1096 for (unsigned I = 1; I < Proto.size(); ++I) {
1097 char NameC = '0' + (I - 1);
1098 std::string Name = "p";
1099 Name.push_back(NameC);
1100
1101 Variables[Name] = Variable(Types[I], Name + VariablePostfix);
1102 }
1103 RetVar = Variable(Types[0], "ret" + VariablePostfix);
1104}
1105
1106void Intrinsic::emitPrototype() {
1107 if (UseMacro)
1108 OS << "#define ";
1109 else
1110 OS << "__ai " << Types[0].str() << " ";
1111
1112 OS << mangleName(Name, ClassS) << "(";
1113
1114 for (unsigned I = 0; I < getNumParams(); ++I) {
1115 if (I != 0)
1116 OS << ", ";
1117
1118 char NameC = '0' + I;
1119 std::string Name = "p";
1120 Name.push_back(NameC);
1121 assert(Variables.find(Name) != Variables.end());
1122 Variable &V = Variables[Name];
1123
1124 if (!UseMacro)
1125 OS << V.getType().str() << " ";
1126 OS << V.getName();
1127 }
1128
1129 OS << ")";
1130}
1131
1132void Intrinsic::emitOpeningBrace() {
1133 if (UseMacro)
1134 OS << " __extension__ ({";
1135 else
1136 OS << " {";
1137 emitNewLine();
1138}
1139
1140void Intrinsic::emitClosingBrace() {
1141 if (UseMacro)
1142 OS << "})";
1143 else
1144 OS << "}";
1145}
1146
1147void Intrinsic::emitNewLine() {
1148 if (UseMacro)
1149 OS << " \\\n";
1150 else
1151 OS << "\n";
1152}
1153
1154void Intrinsic::emitShadowedArgs() {
1155 // Macro arguments are not type-checked like inline function arguments,
1156 // so assign them to local temporaries to get the right type checking.
1157 if (!UseMacro)
Michael Gottesman6cd3e562013-04-16 23:00:26 +00001158 return;
1159
James Molloydee4ab02014-06-17 13:11:27 +00001160 for (unsigned I = 0; I < getNumParams(); ++I) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001161 // Do not create a temporary for an immediate argument.
1162 // That would defeat the whole point of using a macro!
James Molloydee4ab02014-06-17 13:11:27 +00001163 if (hasImmediate() && Proto[I+1] == 'i')
Peter Collingbournebee583f2011-10-06 13:03:08 +00001164 continue;
James Molloydee4ab02014-06-17 13:11:27 +00001165 // Do not create a temporary for pointer arguments. The input
1166 // pointer may have an alignment hint.
1167 if (getParamType(I).isPointer())
1168 continue;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001169
James Molloydee4ab02014-06-17 13:11:27 +00001170 char NameC = '0' + I;
1171 std::string Name = "p";
1172 Name.push_back(NameC);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001173
James Molloydee4ab02014-06-17 13:11:27 +00001174 assert(Variables.find(Name) != Variables.end());
1175 Variable &V = Variables[Name];
Peter Collingbournebee583f2011-10-06 13:03:08 +00001176
James Molloydee4ab02014-06-17 13:11:27 +00001177 std::string NewName = "s" + utostr(I);
1178 Variable V2(V.getType(), NewName + VariablePostfix);
Jiangning Liu1bda93a2013-09-09 02:21:08 +00001179
James Molloydee4ab02014-06-17 13:11:27 +00001180 OS << " " << V2.getType().str() << " " << V2.getName() << " = "
1181 << V.getName() << ";";
1182 emitNewLine();
Jiangning Liu1bda93a2013-09-09 02:21:08 +00001183
James Molloydee4ab02014-06-17 13:11:27 +00001184 V = V2;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001185 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001186}
1187
Jiangning Liuee3e0872013-11-27 14:02:55 +00001188// We don't check 'a' in this function, because for builtin function the
1189// argument matching to 'a' uses a vector type splatted from a scalar type.
James Molloydee4ab02014-06-17 13:11:27 +00001190bool Intrinsic::protoHasScalar() {
1191 return (Proto.find('s') != std::string::npos ||
1192 Proto.find('z') != std::string::npos ||
1193 Proto.find('r') != std::string::npos ||
1194 Proto.find('b') != std::string::npos ||
1195 Proto.find('$') != std::string::npos ||
1196 Proto.find('y') != std::string::npos ||
1197 Proto.find('o') != std::string::npos);
Jiangning Liub96ebac2013-10-05 08:22:55 +00001198}
1199
James Molloydee4ab02014-06-17 13:11:27 +00001200void Intrinsic::emitBodyAsBuiltinCall() {
1201 std::string S;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001202
1203 // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
1204 // sret-like argument.
James Molloydee4ab02014-06-17 13:11:27 +00001205 bool SRet = getReturnType().getNumVectors() >= 2;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001206
James Molloydee4ab02014-06-17 13:11:27 +00001207 StringRef N = Name;
1208 if (hasSplat()) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001209 // Call the non-splat builtin: chop off the "_n" suffix from the name.
James Molloydee4ab02014-06-17 13:11:27 +00001210 assert(N.endswith("_n"));
1211 N = N.drop_back(2);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001212 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001213
James Molloydee4ab02014-06-17 13:11:27 +00001214 ClassKind LocalCK = CK;
1215 if (!protoHasScalar())
1216 LocalCK = ClassB;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001217
James Molloydee4ab02014-06-17 13:11:27 +00001218 if (!getReturnType().isVoid() && !SRet)
1219 S += "(" + RetVar.getType().str() + ") ";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001220
James Molloydee4ab02014-06-17 13:11:27 +00001221 S += "__builtin_neon_" + mangleName(N, LocalCK) + "(";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001222
James Molloydee4ab02014-06-17 13:11:27 +00001223 if (SRet)
1224 S += "&" + RetVar.getName() + ", ";
1225
1226 for (unsigned I = 0; I < getNumParams(); ++I) {
1227 Variable &V = Variables["p" + utostr(I)];
1228 Type T = V.getType();
Peter Collingbournebee583f2011-10-06 13:03:08 +00001229
1230 // Handle multiple-vector values specially, emitting each subvector as an
James Molloydee4ab02014-06-17 13:11:27 +00001231 // argument to the builtin.
1232 if (T.getNumVectors() > 1) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001233 // Check if an explicit cast is needed.
James Molloydee4ab02014-06-17 13:11:27 +00001234 std::string Cast;
1235 if (T.isChar() || T.isPoly() || !T.isSigned()) {
1236 Type T2 = T;
1237 T2.makeOneVector();
1238 T2.makeInteger(8, /*Signed=*/true);
1239 Cast = "(" + T2.str() + ")";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001240 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001241
James Molloydee4ab02014-06-17 13:11:27 +00001242 for (unsigned J = 0; J < T.getNumVectors(); ++J)
1243 S += Cast + V.getName() + ".val[" + utostr(J) + "], ";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001244 continue;
1245 }
1246
James Molloydee4ab02014-06-17 13:11:27 +00001247 std::string Arg;
1248 Type CastToType = T;
1249 if (hasSplat() && I == getSplatIdx()) {
1250 Arg = "(" + BaseType.str() + ") {";
1251 for (unsigned J = 0; J < BaseType.getNumElements(); ++J) {
1252 if (J != 0)
1253 Arg += ", ";
1254 Arg += V.getName();
1255 }
1256 Arg += "}";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001257
James Molloydee4ab02014-06-17 13:11:27 +00001258 CastToType = BaseType;
1259 } else {
1260 Arg = V.getName();
Peter Collingbournebee583f2011-10-06 13:03:08 +00001261 }
1262
James Molloydee4ab02014-06-17 13:11:27 +00001263 // Check if an explicit cast is needed.
1264 if (CastToType.isVector()) {
1265 CastToType.makeInteger(8, true);
1266 Arg = "(" + CastToType.str() + ")" + Arg;
1267 }
1268
1269 S += Arg + ", ";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001270 }
1271
1272 // Extra constant integer to hold type class enum for this function, e.g. s8
James Molloydee4ab02014-06-17 13:11:27 +00001273 if (getClassKind(true) == ClassB) {
1274 Type ThisTy = getReturnType();
1275 if (Proto[0] == 'v' || Proto[0] == 'f' || Proto[0] == 'F')
1276 ThisTy = getParamType(0);
1277 if (ThisTy.isPointer())
1278 ThisTy = getParamType(1);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001279
James Molloydee4ab02014-06-17 13:11:27 +00001280 S += utostr(ThisTy.getNeonEnum());
1281 } else {
1282 // Remove extraneous ", ".
1283 S.pop_back();
1284 S.pop_back();
Peter Collingbournebee583f2011-10-06 13:03:08 +00001285 }
James Molloydee4ab02014-06-17 13:11:27 +00001286 S += ");";
1287
1288 std::string RetExpr;
1289 if (!SRet && !RetVar.getType().isVoid())
1290 RetExpr = RetVar.getName() + " = ";
1291
1292 OS << " " << RetExpr << S;
1293 emitNewLine();
Peter Collingbournebee583f2011-10-06 13:03:08 +00001294}
1295
James Molloydee4ab02014-06-17 13:11:27 +00001296void Intrinsic::emitBody() {
1297 std::vector<std::string> Lines;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001298
James Molloydee4ab02014-06-17 13:11:27 +00001299 assert(RetVar.getType() == Types[0]);
1300 // Create a return variable, if we're not void.
1301 if (!RetVar.getType().isVoid()) {
1302 OS << " " << RetVar.getType().str() << " " << RetVar.getName() << ";";
1303 emitNewLine();
1304 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001305
James Molloydee4ab02014-06-17 13:11:27 +00001306 if (!Body || Body->getValues().size() == 0) {
1307 // Nothing specific to output - must output a builtin.
1308 emitBodyAsBuiltinCall();
1309 return;
1310 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001311
James Molloydee4ab02014-06-17 13:11:27 +00001312 // We have a list of "things to output". The last should be returned.
1313 for (auto *I : Body->getValues()) {
1314 if (StringInit *SI = dyn_cast<StringInit>(I)) {
1315 Lines.push_back(replaceParamsIn(SI->getAsString()));
1316 } else if (DagInit *DI = dyn_cast<DagInit>(I)) {
1317 Lines.push_back(emitDag(DI).second + ";");
1318 }
1319 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001320
James Molloydee4ab02014-06-17 13:11:27 +00001321 assert(Lines.size() && "Empty def?");
1322 if (!RetVar.getType().isVoid())
1323 Lines.back().insert(0, RetVar.getName() + " = ");
Peter Collingbournebee583f2011-10-06 13:03:08 +00001324
James Molloydee4ab02014-06-17 13:11:27 +00001325 for (auto &L : Lines) {
1326 OS << " " << L;
1327 emitNewLine();
1328 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001329}
1330
James Molloydee4ab02014-06-17 13:11:27 +00001331void Intrinsic::emitReturn() {
1332 if (RetVar.getType().isVoid())
1333 return;
1334 if (UseMacro)
1335 OS << " " << RetVar.getName() << ";";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001336 else
James Molloydee4ab02014-06-17 13:11:27 +00001337 OS << " return " << RetVar.getName() << ";";
1338 emitNewLine();
1339}
Peter Collingbournebee583f2011-10-06 13:03:08 +00001340
James Molloydee4ab02014-06-17 13:11:27 +00001341std::pair<Type, std::string> Intrinsic::emitDag(DagInit *DI) {
1342 // At this point we should only be seeing a def.
1343 DefInit *DefI = cast<DefInit>(DI->getOperator());
1344 std::string Op = DefI->getAsString();
1345
1346 if (Op == "cast" || Op == "bitcast")
1347 return emitDagCast(DI, Op == "bitcast");
1348 if (Op == "shuffle")
1349 return emitDagShuffle(DI);
1350 if (Op == "dup")
1351 return emitDagDup(DI);
1352 if (Op == "splat")
1353 return emitDagSplat(DI);
1354 if (Op == "save_temp")
1355 return emitDagSaveTemp(DI);
1356 if (Op == "op")
1357 return emitDagOp(DI);
1358 if (Op == "call")
1359 return emitDagCall(DI);
1360 if (Op == "name_replace")
1361 return emitDagNameReplace(DI);
1362 if (Op == "literal")
1363 return emitDagLiteral(DI);
1364 assert_with_loc(false, "Unknown operation!");
1365 return std::make_pair(Type::getVoid(), "");
1366}
1367
1368std::pair<Type, std::string> Intrinsic::emitDagOp(DagInit *DI) {
1369 std::string Op = cast<StringInit>(DI->getArg(0))->getAsUnquotedString();
1370 if (DI->getNumArgs() == 2) {
1371 // Unary op.
1372 std::pair<Type, std::string> R =
1373 emitDagArg(DI->getArg(1), DI->getArgName(1));
1374 return std::make_pair(R.first, Op + R.second);
1375 } else {
1376 assert(DI->getNumArgs() == 3 && "Can only handle unary and binary ops!");
1377 std::pair<Type, std::string> R1 =
1378 emitDagArg(DI->getArg(1), DI->getArgName(1));
1379 std::pair<Type, std::string> R2 =
1380 emitDagArg(DI->getArg(2), DI->getArgName(2));
1381 assert_with_loc(R1.first == R2.first, "Argument type mismatch!");
1382 return std::make_pair(R1.first, R1.second + " " + Op + " " + R2.second);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001383 }
James Molloydee4ab02014-06-17 13:11:27 +00001384}
Peter Collingbournebee583f2011-10-06 13:03:08 +00001385
James Molloydee4ab02014-06-17 13:11:27 +00001386std::pair<Type, std::string> Intrinsic::emitDagCall(DagInit *DI) {
1387 std::vector<Type> Types;
1388 std::vector<std::string> Values;
1389 for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) {
1390 std::pair<Type, std::string> R =
1391 emitDagArg(DI->getArg(I + 1), DI->getArgName(I + 1));
1392 Types.push_back(R.first);
1393 Values.push_back(R.second);
1394 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001395
James Molloydee4ab02014-06-17 13:11:27 +00001396 // Look up the called intrinsic.
1397 std::string N;
1398 if (StringInit *SI = dyn_cast<StringInit>(DI->getArg(0)))
1399 N = SI->getAsUnquotedString();
Peter Collingbournebee583f2011-10-06 13:03:08 +00001400 else
James Molloydee4ab02014-06-17 13:11:27 +00001401 N = emitDagArg(DI->getArg(0), "").second;
1402 Intrinsic *Callee = Emitter.getIntrinsic(N, Types);
1403 assert(Callee && "getIntrinsic should not return us nullptr!");
1404
1405 // Make sure the callee is known as an early def.
1406 Callee->setNeededEarly();
1407 Dependencies.insert(Callee);
1408
1409 // Now create the call itself.
1410 std::string S = Callee->getMangledName(true) + "(";
1411 for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) {
1412 if (I != 0)
1413 S += ", ";
1414 S += Values[I];
1415 }
1416 S += ")";
1417
1418 return std::make_pair(Callee->getReturnType(), S);
1419}
1420
1421std::pair<Type, std::string> Intrinsic::emitDagCast(DagInit *DI,
1422 bool IsBitCast) {
1423 // (cast MOD* VAL) -> cast VAL to type given by MOD.
1424 std::pair<Type, std::string> R = emitDagArg(
1425 DI->getArg(DI->getNumArgs() - 1), DI->getArgName(DI->getNumArgs() - 1));
1426 Type castToType = R.first;
1427 for (unsigned ArgIdx = 0; ArgIdx < DI->getNumArgs() - 1; ++ArgIdx) {
1428
1429 // MOD can take several forms:
1430 // 1. $X - take the type of parameter / variable X.
1431 // 2. The value "R" - take the type of the return type.
1432 // 3. a type string
1433 // 4. The value "U" or "S" to switch the signedness.
1434 // 5. The value "H" or "D" to half or double the bitwidth.
1435 // 6. The value "8" to convert to 8-bit (signed) integer lanes.
1436 if (DI->getArgName(ArgIdx).size()) {
1437 assert_with_loc(Variables.find(DI->getArgName(ArgIdx)) != Variables.end(),
1438 "Variable not found");
1439 castToType = Variables[DI->getArgName(ArgIdx)].getType();
1440 } else {
1441 StringInit *SI = dyn_cast<StringInit>(DI->getArg(ArgIdx));
1442 assert_with_loc(SI, "Expected string type or $Name for cast type");
1443
1444 if (SI->getAsUnquotedString() == "R") {
1445 castToType = getReturnType();
1446 } else if (SI->getAsUnquotedString() == "U") {
1447 castToType.makeUnsigned();
1448 } else if (SI->getAsUnquotedString() == "S") {
1449 castToType.makeSigned();
1450 } else if (SI->getAsUnquotedString() == "H") {
1451 castToType.halveLanes();
1452 } else if (SI->getAsUnquotedString() == "D") {
1453 castToType.doubleLanes();
1454 } else if (SI->getAsUnquotedString() == "8") {
1455 castToType.makeInteger(8, true);
1456 } else {
1457 castToType = Type::fromTypedefName(SI->getAsUnquotedString());
1458 assert_with_loc(!castToType.isVoid(), "Unknown typedef");
1459 }
1460 }
1461 }
1462
1463 std::string S;
1464 if (IsBitCast) {
1465 // Emit a reinterpret cast. The second operand must be an lvalue, so create
1466 // a temporary.
1467 std::string N = "reint";
1468 unsigned I = 0;
1469 while (Variables.find(N) != Variables.end())
1470 N = "reint" + utostr(++I);
1471 Variables[N] = Variable(R.first, N + VariablePostfix);
1472
1473 OS << R.first.str() << " " << Variables[N].getName() << " = " << R.second
1474 << ";";
1475 emitNewLine();
1476
1477 S = "*(" + castToType.str() + " *) &" + Variables[N].getName() + "";
1478 } else {
1479 // Emit a normal (static) cast.
1480 S = "(" + castToType.str() + ")(" + R.second + ")";
1481 }
1482
1483 return std::make_pair(castToType, S);
1484}
1485
1486std::pair<Type, std::string> Intrinsic::emitDagShuffle(DagInit *DI) {
1487 // See the documentation in arm_neon.td for a description of these operators.
1488 class LowHalf : public SetTheory::Operator {
1489 public:
1490 virtual void anchor() {}
1491 virtual ~LowHalf() {}
1492 virtual void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
1493 ArrayRef<SMLoc> Loc) {
1494 SetTheory::RecSet Elts2;
1495 ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts2, Loc);
1496 Elts.insert(Elts2.begin(), Elts2.begin() + (Elts2.size() / 2));
1497 }
1498 };
1499 class HighHalf : public SetTheory::Operator {
1500 public:
1501 virtual void anchor() {}
1502 virtual ~HighHalf() {}
1503 virtual void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
1504 ArrayRef<SMLoc> Loc) {
1505 SetTheory::RecSet Elts2;
1506 ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts2, Loc);
1507 Elts.insert(Elts2.begin() + (Elts2.size() / 2), Elts2.end());
1508 }
1509 };
1510 class Rev : public SetTheory::Operator {
1511 unsigned ElementSize;
1512
1513 public:
1514 Rev(unsigned ElementSize) : ElementSize(ElementSize) {}
1515 virtual void anchor() {}
1516 virtual ~Rev() {}
1517 virtual void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
1518 ArrayRef<SMLoc> Loc) {
1519 SetTheory::RecSet Elts2;
1520 ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Elts2, Loc);
1521
1522 int64_t VectorSize = cast<IntInit>(Expr->getArg(0))->getValue();
1523 VectorSize /= ElementSize;
1524
1525 std::vector<Record *> Revved;
1526 for (unsigned VI = 0; VI < Elts2.size(); VI += VectorSize) {
1527 for (int LI = VectorSize - 1; LI >= 0; --LI) {
1528 Revved.push_back(Elts2[VI + LI]);
1529 }
1530 }
1531
1532 Elts.insert(Revved.begin(), Revved.end());
1533 }
1534 };
1535 class MaskExpander : public SetTheory::Expander {
1536 unsigned N;
1537
1538 public:
1539 MaskExpander(unsigned N) : N(N) {}
1540 virtual void anchor() {}
1541 virtual ~MaskExpander() {}
1542 virtual void expand(SetTheory &ST, Record *R, SetTheory::RecSet &Elts) {
1543 unsigned Addend = 0;
1544 if (R->getName() == "mask0")
1545 Addend = 0;
1546 else if (R->getName() == "mask1")
1547 Addend = N;
1548 else
1549 return;
1550 for (unsigned I = 0; I < N; ++I)
1551 Elts.insert(R->getRecords().getDef("sv" + utostr(I + Addend)));
1552 }
1553 };
1554
1555 // (shuffle arg1, arg2, sequence)
1556 std::pair<Type, std::string> Arg1 =
1557 emitDagArg(DI->getArg(0), DI->getArgName(0));
1558 std::pair<Type, std::string> Arg2 =
1559 emitDagArg(DI->getArg(1), DI->getArgName(1));
1560 assert_with_loc(Arg1.first == Arg2.first,
1561 "Different types in arguments to shuffle!");
1562
1563 SetTheory ST;
1564 LowHalf LH;
1565 HighHalf HH;
1566 MaskExpander ME(Arg1.first.getNumElements());
1567 Rev R(Arg1.first.getElementSizeInBits());
1568 SetTheory::RecSet Elts;
1569 ST.addOperator("lowhalf", &LH);
1570 ST.addOperator("highhalf", &HH);
1571 ST.addOperator("rev", &R);
1572 ST.addExpander("MaskExpand", &ME);
1573 ST.evaluate(DI->getArg(2), Elts, ArrayRef<SMLoc>());
1574
1575 std::string S = "__builtin_shufflevector(" + Arg1.second + ", " + Arg2.second;
1576 for (auto &E : Elts) {
1577 StringRef Name = E->getName();
1578 assert_with_loc(Name.startswith("sv"),
1579 "Incorrect element kind in shuffle mask!");
1580 S += ", " + Name.drop_front(2).str();
1581 }
1582 S += ")";
1583
1584 // Recalculate the return type - the shuffle may have halved or doubled it.
1585 Type T(Arg1.first);
1586 if (Elts.size() > T.getNumElements()) {
1587 assert_with_loc(
1588 Elts.size() == T.getNumElements() * 2,
1589 "Can only double or half the number of elements in a shuffle!");
1590 T.doubleLanes();
1591 } else if (Elts.size() < T.getNumElements()) {
1592 assert_with_loc(
1593 Elts.size() == T.getNumElements() / 2,
1594 "Can only double or half the number of elements in a shuffle!");
1595 T.halveLanes();
1596 }
1597
1598 return std::make_pair(T, S);
1599}
1600
1601std::pair<Type, std::string> Intrinsic::emitDagDup(DagInit *DI) {
1602 assert_with_loc(DI->getNumArgs() == 1, "dup() expects one argument");
1603 std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), DI->getArgName(0));
1604 assert_with_loc(A.first.isScalar(), "dup() expects a scalar argument");
1605
1606 Type T = getBaseType();
1607 assert_with_loc(T.isVector(), "dup() used but default type is scalar!");
1608 std::string S = "(" + T.str() + ") {";
1609 for (unsigned I = 0; I < T.getNumElements(); ++I) {
1610 if (I != 0)
1611 S += ", ";
1612 S += A.second;
1613 }
1614 S += "}";
1615
1616 return std::make_pair(T, S);
1617}
1618
1619std::pair<Type, std::string> Intrinsic::emitDagSplat(DagInit *DI) {
1620 assert_with_loc(DI->getNumArgs() == 2, "splat() expects two arguments");
1621 std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), DI->getArgName(0));
1622 std::pair<Type, std::string> B = emitDagArg(DI->getArg(1), DI->getArgName(1));
1623
1624 assert_with_loc(B.first.isScalar(),
1625 "splat() requires a scalar int as the second argument");
1626
1627 std::string S = "__builtin_shufflevector(" + A.second + ", " + A.second;
1628 for (unsigned I = 0; I < BaseType.getNumElements(); ++I) {
1629 S += ", " + B.second;
1630 }
1631 S += ")";
1632
1633 return std::make_pair(BaseType, S);
1634}
1635
1636std::pair<Type, std::string> Intrinsic::emitDagSaveTemp(DagInit *DI) {
1637 assert_with_loc(DI->getNumArgs() == 2, "save_temp() expects two arguments");
1638 std::pair<Type, std::string> A = emitDagArg(DI->getArg(1), DI->getArgName(1));
1639
1640 assert_with_loc(!A.first.isVoid(),
1641 "Argument to save_temp() must have non-void type!");
1642
1643 std::string N = DI->getArgName(0);
1644 assert_with_loc(N.size(), "save_temp() expects a name as the first argument");
1645
1646 assert_with_loc(Variables.find(N) == Variables.end(),
1647 "Variable already defined!");
1648 Variables[N] = Variable(A.first, N + VariablePostfix);
1649
1650 std::string S =
1651 A.first.str() + " " + Variables[N].getName() + " = " + A.second;
1652
1653 return std::make_pair(Type::getVoid(), S);
1654}
1655
1656std::pair<Type, std::string> Intrinsic::emitDagNameReplace(DagInit *DI) {
1657 std::string S = Name;
1658
1659 assert_with_loc(DI->getNumArgs() == 2, "name_replace requires 2 arguments!");
1660 std::string ToReplace = cast<StringInit>(DI->getArg(0))->getAsUnquotedString();
1661 std::string ReplaceWith = cast<StringInit>(DI->getArg(1))->getAsUnquotedString();
1662
1663 size_t Idx = S.find(ToReplace);
1664
1665 assert_with_loc(Idx != std::string::npos, "name should contain '" + ToReplace + "'!");
1666 S.replace(Idx, ToReplace.size(), ReplaceWith);
1667
1668 return std::make_pair(Type::getVoid(), S);
1669}
1670
1671std::pair<Type, std::string> Intrinsic::emitDagLiteral(DagInit *DI) {
1672 std::string Ty = cast<StringInit>(DI->getArg(0))->getAsUnquotedString();
1673 std::string Value = cast<StringInit>(DI->getArg(1))->getAsUnquotedString();
1674 return std::make_pair(Type::fromTypedefName(Ty), Value);
1675}
1676
1677std::pair<Type, std::string> Intrinsic::emitDagArg(Init *Arg,
1678 std::string ArgName) {
1679 if (ArgName.size()) {
1680 assert_with_loc(!Arg->isComplete(),
1681 "Arguments must either be DAGs or names, not both!");
1682 assert_with_loc(Variables.find(ArgName) != Variables.end(),
1683 "Variable not defined!");
1684 Variable &V = Variables[ArgName];
1685 return std::make_pair(V.getType(), V.getName());
1686 }
1687
1688 assert(Arg && "Neither ArgName nor Arg?!");
1689 DagInit *DI = dyn_cast<DagInit>(Arg);
1690 assert_with_loc(DI, "Arguments must either be DAGs or names!");
1691
1692 return emitDag(DI);
1693}
1694
1695std::string Intrinsic::generate() {
1696 CurrentRecord = R;
1697
1698 // If we call a macro, our local variables may be corrupted due to
1699 // lack of proper lexical scoping. So, add a globally unique postfix
1700 // to every variable.
1701 //
1702 // indexBody() should have set up the Dependencies set by now.
1703 for (auto *I : Dependencies)
1704 if (I->UseMacro) {
1705 VariablePostfix = "_" + utostr(Emitter.getUniqueNumber());
1706 break;
1707 }
1708
1709 initVariables();
1710
1711 emitPrototype();
1712
1713 if (IsUnavailable) {
1714 OS << " __attribute__((unavailable));";
1715 } else {
1716 emitOpeningBrace();
1717 emitShadowedArgs();
1718 emitBody();
1719 emitReturn();
1720 emitClosingBrace();
1721 }
1722 OS << "\n";
1723
1724 CurrentRecord = nullptr;
1725 return OS.str();
1726}
1727
1728void Intrinsic::indexBody() {
1729 CurrentRecord = R;
1730
1731 initVariables();
1732 emitBody();
1733 OS.str("");
1734
1735 CurrentRecord = nullptr;
1736}
1737
1738//===----------------------------------------------------------------------===//
1739// NeonEmitter implementation
1740//===----------------------------------------------------------------------===//
1741
1742Intrinsic *NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) {
1743 // First, look up the name in the intrinsic map.
1744 assert_with_loc(IntrinsicMap.find(Name.str()) != IntrinsicMap.end(),
1745 ("Intrinsic '" + Name + "' not found!").str());
1746 std::vector<Intrinsic *> &V = IntrinsicMap[Name.str()];
1747 std::vector<Intrinsic *> GoodVec;
1748
1749 // Create a string to print if we end up failing.
1750 std::string ErrMsg = "looking up intrinsic '" + Name.str() + "(";
1751 for (unsigned I = 0; I < Types.size(); ++I) {
1752 if (I != 0)
1753 ErrMsg += ", ";
1754 ErrMsg += Types[I].str();
1755 }
1756 ErrMsg += ")'\n";
1757 ErrMsg += "Available overloads:\n";
1758
1759 // Now, look through each intrinsic implementation and see if the types are
1760 // compatible.
1761 for (auto *I : V) {
1762 ErrMsg += " - " + I->getReturnType().str() + " " + I->getMangledName();
1763 ErrMsg += "(";
1764 for (unsigned A = 0; A < I->getNumParams(); ++A) {
1765 if (A != 0)
1766 ErrMsg += ", ";
1767 ErrMsg += I->getParamType(A).str();
1768 }
1769 ErrMsg += ")\n";
1770
1771 if (I->getNumParams() != Types.size())
1772 continue;
1773
1774 bool Good = true;
1775 for (unsigned Arg = 0; Arg < Types.size(); ++Arg) {
1776 if (I->getParamType(Arg) != Types[Arg]) {
1777 Good = false;
1778 break;
1779 }
1780 }
1781 if (Good)
1782 GoodVec.push_back(I);
1783 }
1784
1785 assert_with_loc(GoodVec.size() > 0,
1786 "No compatible intrinsic found - " + ErrMsg);
1787 assert_with_loc(GoodVec.size() == 1, "Multiple overloads found - " + ErrMsg);
1788
1789 return GoodVec.front();
1790}
1791
1792void NeonEmitter::createIntrinsic(Record *R,
1793 SmallVectorImpl<Intrinsic *> &Out) {
1794 std::string Name = R->getValueAsString("Name");
1795 std::string Proto = R->getValueAsString("Prototype");
1796 std::string Types = R->getValueAsString("Types");
1797 Record *OperationRec = R->getValueAsDef("Operation");
1798 bool CartesianProductOfTypes = R->getValueAsBit("CartesianProductOfTypes");
1799 std::string Guard = R->getValueAsString("ArchGuard");
1800 bool IsUnavailable = OperationRec->getValueAsBit("Unavailable");
1801
1802 // Set the global current record. This allows assert_with_loc to produce
1803 // decent location information even when highly nested.
1804 CurrentRecord = R;
1805
1806 ListInit *Body = OperationRec->getValueAsListInit("Ops");
1807
1808 std::vector<TypeSpec> TypeSpecs = TypeSpec::fromTypeSpecs(Types);
1809
1810 ClassKind CK = ClassNone;
1811 if (R->getSuperClasses().size() >= 2)
1812 CK = ClassMap[R->getSuperClasses()[1]];
1813
1814 std::vector<std::pair<TypeSpec, TypeSpec>> NewTypeSpecs;
1815 for (auto TS : TypeSpecs) {
1816 if (CartesianProductOfTypes) {
1817 Type DefaultT(TS, 'd');
1818 for (auto SrcTS : TypeSpecs) {
1819 Type DefaultSrcT(SrcTS, 'd');
1820 if (TS == SrcTS ||
1821 DefaultSrcT.getSizeInBits() != DefaultT.getSizeInBits())
1822 continue;
1823 NewTypeSpecs.push_back(std::make_pair(TS, SrcTS));
1824 }
1825 } else {
1826 NewTypeSpecs.push_back(std::make_pair(TS, TS));
1827 }
1828 }
1829
1830 std::sort(NewTypeSpecs.begin(), NewTypeSpecs.end());
1831 std::unique(NewTypeSpecs.begin(), NewTypeSpecs.end());
1832
1833 for (auto &I : NewTypeSpecs) {
1834 Intrinsic *IT = new Intrinsic(R, Name, Proto, I.first, I.second, CK, Body,
1835 *this, Guard, IsUnavailable);
1836
1837 IntrinsicMap[Name].push_back(IT);
1838 Out.push_back(IT);
1839 }
1840
1841 CurrentRecord = nullptr;
1842}
1843
1844/// genBuiltinsDef: Generate the BuiltinsARM.def and BuiltinsAArch64.def
1845/// declaration of builtins, checking for unique builtin declarations.
1846void NeonEmitter::genBuiltinsDef(raw_ostream &OS,
1847 SmallVectorImpl<Intrinsic *> &Defs) {
1848 OS << "#ifdef GET_NEON_BUILTINS\n";
1849
1850 // We only want to emit a builtin once, and we want to emit them in
1851 // alphabetical order, so use a std::set.
1852 std::set<std::string> Builtins;
1853
1854 for (auto *Def : Defs) {
1855 if (Def->hasBody())
1856 continue;
1857 // Functions with 'a' (the splat code) in the type prototype should not get
1858 // their own builtin as they use the non-splat variant.
1859 if (Def->hasSplat())
1860 continue;
1861
1862 std::string S = "BUILTIN(__builtin_neon_" + Def->getMangledName() + ", \"";
1863
1864 S += Def->getBuiltinTypeStr();
1865 S += "\", \"n\")";
1866
1867 Builtins.insert(S);
1868 }
1869
1870 for (auto &S : Builtins)
1871 OS << S << "\n";
1872 OS << "#endif\n\n";
1873}
1874
1875/// Generate the ARM and AArch64 overloaded type checking code for
1876/// SemaChecking.cpp, checking for unique builtin declarations.
1877void NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS,
1878 SmallVectorImpl<Intrinsic *> &Defs) {
1879 OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
1880
1881 // We record each overload check line before emitting because subsequent Inst
1882 // definitions may extend the number of permitted types (i.e. augment the
1883 // Mask). Use std::map to avoid sorting the table by hash number.
1884 struct OverloadInfo {
1885 uint64_t Mask;
1886 int PtrArgNum;
1887 bool HasConstPtr;
1888 OverloadInfo() : Mask(0ULL), PtrArgNum(0), HasConstPtr(false) {}
1889 };
1890 std::map<std::string, OverloadInfo> OverloadMap;
1891
1892 for (auto *Def : Defs) {
1893 // If the def has a body (that is, it has Operation DAGs), it won't call
1894 // __builtin_neon_* so we don't need to generate a definition for it.
1895 if (Def->hasBody())
1896 continue;
1897 // Functions with 'a' (the splat code) in the type prototype should not get
1898 // their own builtin as they use the non-splat variant.
1899 if (Def->hasSplat())
1900 continue;
1901 // Functions which have a scalar argument cannot be overloaded, no need to
1902 // check them if we are emitting the type checking code.
1903 if (Def->protoHasScalar())
1904 continue;
1905
1906 uint64_t Mask = 0ULL;
1907 Type Ty = Def->getReturnType();
1908 if (Def->getProto()[0] == 'v' || Def->getProto()[0] == 'f' ||
1909 Def->getProto()[0] == 'F')
1910 Ty = Def->getParamType(0);
1911 if (Ty.isPointer())
1912 Ty = Def->getParamType(1);
1913
1914 Mask |= 1ULL << Ty.getNeonEnum();
1915
1916 // Check if the function has a pointer or const pointer argument.
1917 std::string Proto = Def->getProto();
1918 int PtrArgNum = -1;
1919 bool HasConstPtr = false;
1920 for (unsigned I = 0; I < Def->getNumParams(); ++I) {
1921 char ArgType = Proto[I + 1];
1922 if (ArgType == 'c') {
1923 HasConstPtr = true;
1924 PtrArgNum = I;
1925 break;
1926 }
1927 if (ArgType == 'p') {
1928 PtrArgNum = I;
1929 break;
1930 }
1931 }
1932 // For sret builtins, adjust the pointer argument index.
1933 if (PtrArgNum >= 0 && Def->getReturnType().getNumVectors() > 1)
1934 PtrArgNum += 1;
1935
1936 std::string Name = Def->getName();
1937 // Omit type checking for the pointer arguments of vld1_lane, vld1_dup,
1938 // and vst1_lane intrinsics. Using a pointer to the vector element
1939 // type with one of those operations causes codegen to select an aligned
1940 // load/store instruction. If you want an unaligned operation,
1941 // the pointer argument needs to have less alignment than element type,
1942 // so just accept any pointer type.
1943 if (Name == "vld1_lane" || Name == "vld1_dup" || Name == "vst1_lane") {
1944 PtrArgNum = -1;
1945 HasConstPtr = false;
1946 }
1947
1948 if (Mask) {
1949 std::string Name = Def->getMangledName();
1950 OverloadMap.insert(std::make_pair(Name, OverloadInfo()));
1951 OverloadInfo &OI = OverloadMap[Name];
1952 OI.Mask |= Mask;
1953 OI.PtrArgNum |= PtrArgNum;
1954 OI.HasConstPtr = HasConstPtr;
1955 }
1956 }
1957
1958 for (auto &I : OverloadMap) {
1959 OverloadInfo &OI = I.second;
1960
1961 OS << "case NEON::BI__builtin_neon_" << I.first << ": ";
1962 OS << "mask = 0x" << utohexstr(OI.Mask) << "ULL";
1963 if (OI.PtrArgNum >= 0)
1964 OS << "; PtrArgNum = " << OI.PtrArgNum;
1965 if (OI.HasConstPtr)
1966 OS << "; HasConstPtr = true";
1967 OS << "; break;\n";
1968 }
1969 OS << "#endif\n\n";
1970}
1971
1972void
1973NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS,
1974 SmallVectorImpl<Intrinsic *> &Defs) {
1975 OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
1976
1977 std::set<std::string> Emitted;
1978
1979 for (auto *Def : Defs) {
1980 if (Def->hasBody())
1981 continue;
1982 // Functions with 'a' (the splat code) in the type prototype should not get
1983 // their own builtin as they use the non-splat variant.
1984 if (Def->hasSplat())
1985 continue;
1986 // Functions which do not have an immediate do not ned to have range
1987 // checking
1988 // code emitted.
1989 if (!Def->hasImmediate())
1990 continue;
1991 if (Emitted.find(Def->getMangledName()) != Emitted.end())
1992 continue;
1993
1994 std::string LowerBound, UpperBound;
1995
1996 Record *R = Def->getRecord();
1997 if (R->getValueAsBit("isVCVT_N")) {
1998 // VCVT between floating- and fixed-point values takes an immediate
1999 // in the range [1, 32) for f32 or [1, 64) for f64.
2000 LowerBound = "1";
2001 if (Def->getBaseType().getElementSizeInBits() == 32)
2002 UpperBound = "31";
2003 else
2004 UpperBound = "63";
2005 } else if (R->getValueAsBit("isScalarShift")) {
2006 // Right shifts have an 'r' in the name, left shifts do not. Convert
2007 // instructions have the same bounds and right shifts.
2008 if (Def->getName().find('r') != std::string::npos ||
2009 Def->getName().find("cvt") != std::string::npos)
2010 LowerBound = "1";
2011
2012 UpperBound = utostr(Def->getReturnType().getElementSizeInBits() - 1);
2013 } else if (R->getValueAsBit("isShift")) {
2014 // Builtins which are overloaded by type will need to have thier upper
2015 // bound computed at Sema time based on the type constant.
2016
2017 // Right shifts have an 'r' in the name, left shifts do not.
2018 if (Def->getName().find('r') != std::string::npos)
2019 LowerBound = "1";
2020 UpperBound = "RFT(TV, true)";
2021 } else if (Def->getClassKind(true) == ClassB) {
2022 // ClassB intrinsics have a type (and hence lane number) that is only
2023 // known at runtime.
2024 if (R->getValueAsBit("isLaneQ"))
2025 UpperBound = "RFT(TV, false, true)";
2026 else
2027 UpperBound = "RFT(TV, false, false)";
2028 } else {
2029 // The immediate generally refers to a lane in the preceding argument.
2030 assert(Def->getImmediateIdx() > 0);
2031 Type T = Def->getParamType(Def->getImmediateIdx() - 1);
2032 UpperBound = utostr(T.getNumElements() - 1);
2033 }
2034
2035 // Calculate the index of the immediate that should be range checked.
2036 unsigned Idx = Def->getNumParams();
2037 if (Def->hasImmediate())
2038 Idx = Def->getGeneratedParamIdx(Def->getImmediateIdx());
2039
2040 OS << "case NEON::BI__builtin_neon_" << Def->getMangledName() << ": "
2041 << "i = " << Idx << ";";
2042 if (LowerBound.size())
2043 OS << " l = " << LowerBound << ";";
2044 if (UpperBound.size())
2045 OS << " u = " << UpperBound << ";";
2046 OS << " break;\n";
2047
2048 Emitted.insert(Def->getMangledName());
2049 }
2050
2051 OS << "#endif\n\n";
2052}
2053
2054/// runHeader - Emit a file with sections defining:
2055/// 1. the NEON section of BuiltinsARM.def and BuiltinsAArch64.def.
2056/// 2. the SemaChecking code for the type overload checking.
2057/// 3. the SemaChecking code for validation of intrinsic immediate arguments.
2058void NeonEmitter::runHeader(raw_ostream &OS) {
2059 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
2060
2061 SmallVector<Intrinsic *, 128> Defs;
2062 for (auto *R : RV)
2063 createIntrinsic(R, Defs);
2064
2065 // Generate shared BuiltinsXXX.def
2066 genBuiltinsDef(OS, Defs);
2067
2068 // Generate ARM overloaded type checking code for SemaChecking.cpp
2069 genOverloadTypeCheckCode(OS, Defs);
2070
2071 // Generate ARM range checking code for shift/lane immediates.
2072 genIntrinsicRangeCheckCode(OS, Defs);
Peter Collingbournebee583f2011-10-06 13:03:08 +00002073}
2074
2075/// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h
2076/// is comprised of type definitions and function declarations.
2077void NeonEmitter::run(raw_ostream &OS) {
James Molloydee4ab02014-06-17 13:11:27 +00002078 OS << "/*===---- arm_neon.h - ARM Neon intrinsics "
2079 "------------------------------"
2080 "---===\n"
2081 " *\n"
2082 " * Permission is hereby granted, free of charge, to any person "
2083 "obtaining "
2084 "a copy\n"
2085 " * of this software and associated documentation files (the "
2086 "\"Software\"),"
2087 " to deal\n"
2088 " * in the Software without restriction, including without limitation "
2089 "the "
2090 "rights\n"
2091 " * to use, copy, modify, merge, publish, distribute, sublicense, "
2092 "and/or sell\n"
2093 " * copies of the Software, and to permit persons to whom the Software "
2094 "is\n"
2095 " * furnished to do so, subject to the following conditions:\n"
2096 " *\n"
2097 " * The above copyright notice and this permission notice shall be "
2098 "included in\n"
2099 " * all copies or substantial portions of the Software.\n"
2100 " *\n"
2101 " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
2102 "EXPRESS OR\n"
2103 " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
2104 "MERCHANTABILITY,\n"
2105 " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
2106 "SHALL THE\n"
2107 " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
2108 "OTHER\n"
2109 " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
2110 "ARISING FROM,\n"
2111 " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
2112 "DEALINGS IN\n"
2113 " * THE SOFTWARE.\n"
2114 " *\n"
2115 " *===-----------------------------------------------------------------"
2116 "---"
2117 "---===\n"
2118 " */\n\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00002119
2120 OS << "#ifndef __ARM_NEON_H\n";
2121 OS << "#define __ARM_NEON_H\n\n";
2122
Tim Northover5bb34ca2013-11-21 12:36:34 +00002123 OS << "#if !defined(__ARM_NEON)\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00002124 OS << "#error \"NEON support not enabled\"\n";
2125 OS << "#endif\n\n";
2126
2127 OS << "#include <stdint.h>\n\n";
2128
2129 // Emit NEON-specific scalar typedefs.
2130 OS << "typedef float float32_t;\n";
Tim Northover2fe823a2013-08-01 09:23:19 +00002131 OS << "typedef __fp16 float16_t;\n";
2132
2133 OS << "#ifdef __aarch64__\n";
2134 OS << "typedef double float64_t;\n";
2135 OS << "#endif\n\n";
2136
2137 // For now, signedness of polynomial types depends on target
2138 OS << "#ifdef __aarch64__\n";
2139 OS << "typedef uint8_t poly8_t;\n";
2140 OS << "typedef uint16_t poly16_t;\n";
Kevin Qincaac85e2013-11-14 03:29:16 +00002141 OS << "typedef uint64_t poly64_t;\n";
Kevin Qinfb79d7f2013-12-10 06:49:01 +00002142 OS << "typedef __uint128_t poly128_t;\n";
Tim Northover2fe823a2013-08-01 09:23:19 +00002143 OS << "#else\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00002144 OS << "typedef int8_t poly8_t;\n";
2145 OS << "typedef int16_t poly16_t;\n";
Tim Northover2fe823a2013-08-01 09:23:19 +00002146 OS << "#endif\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00002147
2148 // Emit Neon vector typedefs.
Tim Northover2fe823a2013-08-01 09:23:19 +00002149 std::string TypedefTypes(
Kevin Qincaac85e2013-11-14 03:29:16 +00002150 "cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfdQdPcQPcPsQPsPlQPl");
James Molloydee4ab02014-06-17 13:11:27 +00002151 std::vector<TypeSpec> TDTypeVec = TypeSpec::fromTypeSpecs(TypedefTypes);
Peter Collingbournebee583f2011-10-06 13:03:08 +00002152
2153 // Emit vector typedefs.
James Molloydee4ab02014-06-17 13:11:27 +00002154 bool InIfdef = false;
2155 for (auto &TS : TDTypeVec) {
2156 bool IsA64 = false;
2157 Type T(TS, 'd');
2158 if (T.isDouble() || (T.isPoly() && T.isLong()))
2159 IsA64 = true;
Tim Northover2fe823a2013-08-01 09:23:19 +00002160
James Molloydee4ab02014-06-17 13:11:27 +00002161 if (InIfdef && !IsA64) {
Jiangning Liu4617e9d2013-10-04 09:21:17 +00002162 OS << "#endif\n";
James Molloydee4ab02014-06-17 13:11:27 +00002163 InIfdef = false;
2164 }
2165 if (!InIfdef && IsA64) {
Tim Northover2fe823a2013-08-01 09:23:19 +00002166 OS << "#ifdef __aarch64__\n";
James Molloydee4ab02014-06-17 13:11:27 +00002167 InIfdef = true;
2168 }
Tim Northover2fe823a2013-08-01 09:23:19 +00002169
James Molloydee4ab02014-06-17 13:11:27 +00002170 if (T.isPoly())
Peter Collingbournebee583f2011-10-06 13:03:08 +00002171 OS << "typedef __attribute__((neon_polyvector_type(";
2172 else
2173 OS << "typedef __attribute__((neon_vector_type(";
2174
James Molloydee4ab02014-06-17 13:11:27 +00002175 Type T2 = T;
2176 T2.makeScalar();
2177 OS << utostr(T.getNumElements()) << "))) ";
2178 OS << T2.str();
2179 OS << " " << T.str() << ";\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00002180 }
James Molloydee4ab02014-06-17 13:11:27 +00002181 if (InIfdef)
Kevin Qincaac85e2013-11-14 03:29:16 +00002182 OS << "#endif\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00002183 OS << "\n";
2184
2185 // Emit struct typedefs.
James Molloydee4ab02014-06-17 13:11:27 +00002186 InIfdef = false;
2187 for (unsigned NumMembers = 2; NumMembers <= 4; ++NumMembers) {
2188 for (auto &TS : TDTypeVec) {
2189 bool IsA64 = false;
2190 Type T(TS, 'd');
2191 if (T.isDouble() || (T.isPoly() && T.isLong()))
2192 IsA64 = true;
Tim Northover2fe823a2013-08-01 09:23:19 +00002193
James Molloydee4ab02014-06-17 13:11:27 +00002194 if (InIfdef && !IsA64) {
Jiangning Liu4617e9d2013-10-04 09:21:17 +00002195 OS << "#endif\n";
James Molloydee4ab02014-06-17 13:11:27 +00002196 InIfdef = false;
2197 }
2198 if (!InIfdef && IsA64) {
Tim Northover2fe823a2013-08-01 09:23:19 +00002199 OS << "#ifdef __aarch64__\n";
James Molloydee4ab02014-06-17 13:11:27 +00002200 InIfdef = true;
2201 }
Tim Northover2fe823a2013-08-01 09:23:19 +00002202
James Molloydee4ab02014-06-17 13:11:27 +00002203 char M = '2' + (NumMembers - 2);
2204 Type VT(TS, M);
2205 OS << "typedef struct " << VT.str() << " {\n";
2206 OS << " " << T.str() << " val";
2207 OS << "[" << utostr(NumMembers) << "]";
Peter Collingbournebee583f2011-10-06 13:03:08 +00002208 OS << ";\n} ";
James Molloydee4ab02014-06-17 13:11:27 +00002209 OS << VT.str() << ";\n";
Tim Northover2fe823a2013-08-01 09:23:19 +00002210 OS << "\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00002211 }
2212 }
James Molloydee4ab02014-06-17 13:11:27 +00002213 if (InIfdef)
Kevin Qincaac85e2013-11-14 03:29:16 +00002214 OS << "#endif\n";
2215 OS << "\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00002216
James Molloydee4ab02014-06-17 13:11:27 +00002217 OS << "#define __ai static inline __attribute__((__always_inline__, "
2218 "__nodebug__))\n\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00002219
James Molloydee4ab02014-06-17 13:11:27 +00002220 SmallVector<Intrinsic *, 128> Defs;
2221 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
2222 for (auto *R : RV)
2223 createIntrinsic(R, Defs);
Peter Collingbournebee583f2011-10-06 13:03:08 +00002224
James Molloydee4ab02014-06-17 13:11:27 +00002225 for (auto *I : Defs)
2226 I->indexBody();
Tim Northover2fe823a2013-08-01 09:23:19 +00002227
James Molloydee4ab02014-06-17 13:11:27 +00002228 std::stable_sort(
2229 Defs.begin(), Defs.end(),
2230 [](const Intrinsic *A, const Intrinsic *B) { return *A < *B; });
Tim Northover2fe823a2013-08-01 09:23:19 +00002231
James Molloydee4ab02014-06-17 13:11:27 +00002232 // Only emit a def when its requirements have been met.
2233 // FIXME: This loop could be made faster, but it's fast enough for now.
2234 bool MadeProgress = true;
2235 std::string InGuard = "";
2236 while (!Defs.empty() && MadeProgress) {
2237 MadeProgress = false;
2238
2239 for (SmallVector<Intrinsic *, 128>::iterator I = Defs.begin();
2240 I != Defs.end(); /*No step*/) {
2241 bool DependenciesSatisfied = true;
2242 for (auto *II : (*I)->getDependencies()) {
2243 if (std::find(Defs.begin(), Defs.end(), II) != Defs.end())
2244 DependenciesSatisfied = false;
2245 }
2246 if (!DependenciesSatisfied) {
2247 // Try the next one.
2248 ++I;
2249 continue;
2250 }
2251
2252 // Emit #endif/#if pair if needed.
2253 if ((*I)->getGuard() != InGuard) {
2254 if (!InGuard.empty())
2255 OS << "#endif\n";
2256 InGuard = (*I)->getGuard();
2257 if (!InGuard.empty())
2258 OS << "#if " << InGuard << "\n";
2259 }
2260
2261 // Actually generate the intrinsic code.
2262 OS << (*I)->generate();
2263
2264 MadeProgress = true;
2265 I = Defs.erase(I);
2266 }
Tim Northover2fe823a2013-08-01 09:23:19 +00002267 }
James Molloydee4ab02014-06-17 13:11:27 +00002268 assert(Defs.empty() && "Some requirements were not satisfied!");
2269 if (!InGuard.empty())
2270 OS << "#endif\n";
Tim Northover2fe823a2013-08-01 09:23:19 +00002271
James Molloydee4ab02014-06-17 13:11:27 +00002272 OS << "\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00002273 OS << "#undef __ai\n\n";
2274 OS << "#endif /* __ARM_NEON_H */\n";
2275}
2276
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00002277namespace clang {
2278void EmitNeon(RecordKeeper &Records, raw_ostream &OS) {
2279 NeonEmitter(Records).run(OS);
2280}
2281void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
2282 NeonEmitter(Records).runHeader(OS);
2283}
2284void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
James Molloydee4ab02014-06-17 13:11:27 +00002285 assert(0 && "Neon test generation no longer implemented!");
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00002286}
2287} // End namespace clang