1 //===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
16 #include "NeonEmitter.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/StringMap.h"
26 static void ParseTypes(Record *r, std::string &s,
27 SmallVectorImpl<StringRef> &TV) {
28 const char *data = s.data();
31 for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
32 if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
44 throw TGError(r->getLoc(),
45 "Unexpected letter: " + std::string(data + len, 1));
48 TV.push_back(StringRef(data, len + 1));
54 static const char Widen(const char t) {
62 default: throw "unhandled type in widen!";
67 static std::string TypeString(const char mod, StringRef typestr) {
78 if (typestr[off] == 'Q') {
84 if (typestr[off] == 'P') {
90 if (typestr[off] == 'U') {
95 // base type to get the type string for.
96 char type = typestr[off];
98 // Based on the modifying character, change the type and width if necessary.
159 s += poly ? "poly8" : "int8";
162 s += quad ? "x16" : "x8";
165 s += poly ? "poly16" : "int16";
168 s += quad ? "x8" : "x4";
174 s += quad ? "x4" : "x2";
180 s += quad ? "x2" : "x1";
186 s += quad ? "x8" : "x4";
192 s += quad ? "x4" : "x2";
198 throw "unhandled type!";
209 // Append _t, finishing the type string typedef type.
221 // Turn "vst2_lane" into "vst2q_lane_f32", etc.
222 static std::string MangleName(const std::string &name, StringRef typestr) {
227 static std::string GenArgs(const std::string &proto, StringRef typestr) {
231 void NeonEmitter::run(raw_ostream &OS) {
232 EmitSourceFileHeader("ARM NEON Header", OS);
234 // FIXME: emit license into file?
236 OS << "#ifndef __ARM_NEON_H\n";
237 OS << "#define __ARM_NEON_H\n\n";
239 OS << "#ifndef __ARM_NEON__\n";
240 OS << "#error \"NEON support not enabled\"\n";
243 OS << "#include <stdint.h>\n\n";
247 std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
249 // Initialize Type Map
251 // Unique the return+pattern types, and assign them.
252 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
254 std::string name = LowercaseString(R->getName());
255 std::string Proto = R->getValueAsString("Prototype");
256 std::string Types = R->getValueAsString("Types");
258 SmallVector<StringRef, 16> TypeVec;
259 ParseTypes(R, Types, TypeVec);
261 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
262 assert(!Proto.empty() && "");
264 SmallString<128> Prototype;
265 Prototype += TypeString(Proto[0], TypeVec[ti]);
267 Prototype += MangleName(name, TypeVec[ti]);
268 Prototype += GenArgs(Proto, TypeVec[ti]);
270 OS << Prototype << ";\n";
278 // gen builtin (args)
284 // Unique the return+pattern types, and assign them to each record
285 // Emit a #define for each unique "type" of intrinsic declaring all variants.
286 // Emit a #define for each intrinsic mapping it to a particular type.
288 OS << "\n#endif /* __ARM_NEON_H */\n";