blob: eeb0bcc15047be51d4f38c3d87daaa9bff417ced [file] [log] [blame]
Nate Begeman5ddb0872010-05-28 01:08:32 +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//===----------------------------------------------------------------------===//
15
16#include "NeonEmitter.h"
17#include "Record.h"
Nate Begeman22237772010-06-02 00:34:55 +000018#include "llvm/ADT/SmallString.h"
19#include "llvm/ADT/SmallVector.h"
Nate Begeman5ddb0872010-05-28 01:08:32 +000020#include "llvm/ADT/StringExtras.h"
21#include "llvm/ADT/StringMap.h"
22#include <string>
23
24using namespace llvm;
25
Nate Begeman22237772010-06-02 00:34:55 +000026static void ParseTypes(Record *r, std::string &s,
27 SmallVectorImpl<StringRef> &TV) {
28 const char *data = s.data();
29 int len = 0;
30
31 for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
32 if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
33 continue;
34
35 switch (data[len]) {
36 case 'c':
37 case 's':
38 case 'i':
39 case 'l':
40 case 'h':
41 case 'f':
42 break;
43 default:
44 throw TGError(r->getLoc(),
45 "Unexpected letter: " + std::string(data + len, 1));
46 break;
47 }
48 TV.push_back(StringRef(data, len + 1));
49 data += len + 1;
50 len = -1;
51 }
52}
53
54static const char Widen(const char t) {
55 switch (t) {
56 case 'c':
57 return 's';
58 case 's':
59 return 'i';
60 case 'i':
61 return 'l';
62 default: throw "unhandled type in widen!";
63 }
64 return '\0';
65}
66
67static std::string TypeString(const char mod, StringRef typestr) {
68 unsigned off = 0;
69
70 bool quad = false;
71 bool poly = false;
72 bool usgn = false;
73 bool scal = false;
74 bool cnst = false;
75 bool pntr = false;
76
77 // remember quad.
78 if (typestr[off] == 'Q') {
79 quad = true;
80 ++off;
81 }
82
83 // remember poly.
84 if (typestr[off] == 'P') {
85 poly = true;
86 ++off;
87 }
88
89 // remember unsigned.
90 if (typestr[off] == 'U') {
91 usgn = true;
92 ++off;
93 }
94
95 // base type to get the type string for.
96 char type = typestr[off];
97
98 // Based on the modifying character, change the type and width if necessary.
99 switch (mod) {
100 case 'v':
101 type = 'v';
102 scal = true;
103 usgn = false;
104 break;
105 case 't':
106 if (poly) {
107 poly = false;
108 usgn = true;
109 }
110 break;
111 case 'x':
112 usgn = true;
113 if (type == 'f')
114 type = 'i';
115 break;
116 case 'f':
117 type = 'f';
118 break;
119 case 'w':
120 type = Widen(type);
121 quad = true;
122 break;
123 case 'n':
124 type = Widen(type);
125 break;
126 case 'i':
127 type = 'i';
128 scal = true;
129 usgn = false;
130 break;
131 case 'l':
132 type = 'l';
133 scal = true;
134 usgn = true;
135 break;
136 case 's':
137 scal = true;
138 break;
139 case 'k':
140 quad = true;
141 break;
142 case 'c':
143 cnst = true;
144 case 'p':
145 pntr = true;
146 scal = true;
147 break;
148 default:
149 break;
150 }
151
152 SmallString<128> s;
153
154 if (usgn)
155 s.push_back('u');
156
157 switch (type) {
158 case 'c':
159 s += poly ? "poly8" : "int8";
160 if (scal)
161 break;
162 s += quad ? "x16" : "x8";
163 break;
164 case 's':
165 s += poly ? "poly16" : "int16";
166 if (scal)
167 break;
168 s += quad ? "x8" : "x4";
169 break;
170 case 'i':
171 s += "int32";
172 if (scal)
173 break;
174 s += quad ? "x4" : "x2";
175 break;
176 case 'l':
177 s += "int64";
178 if (scal)
179 break;
180 s += quad ? "x2" : "x1";
181 break;
182 case 'h':
183 s += "float16";
184 if (scal)
185 break;
186 s += quad ? "x8" : "x4";
187 break;
188 case 'f':
189 s += "float32";
190 if (scal)
191 break;
192 s += quad ? "x4" : "x2";
193 break;
194 case 'v':
195 s += "void";
196 break;
197 default:
198 throw "unhandled type!";
199 break;
200 }
201
202 if (mod == '2')
203 s += "x2";
204 if (mod == '3')
205 s += "x3";
206 if (mod == '4')
207 s += "x4";
208
209 // Append _t, finishing the type string typedef type.
210 s += "_t";
211
212 if (cnst)
213 s += " const";
214
215 if (pntr)
216 s += " *";
217
218 return s.str();
219}
220
221// Turn "vst2_lane" into "vst2q_lane_f32", etc.
222static std::string MangleName(const std::string &name, StringRef typestr) {
223 return "";
224}
225
226//
227static std::string GenArgs(const std::string &proto, StringRef typestr) {
228 return "";
229}
230
Nate Begeman5ddb0872010-05-28 01:08:32 +0000231void NeonEmitter::run(raw_ostream &OS) {
232 EmitSourceFileHeader("ARM NEON Header", OS);
233
234 // FIXME: emit license into file?
235
236 OS << "#ifndef __ARM_NEON_H\n";
237 OS << "#define __ARM_NEON_H\n\n";
238
239 OS << "#ifndef __ARM_NEON__\n";
240 OS << "#error \"NEON support not enabled\"\n";
241 OS << "#endif\n\n";
242
243 OS << "#include <stdint.h>\n\n";
244
245 // EmitTypedefs(OS);
246
Nate Begeman5ddb0872010-05-28 01:08:32 +0000247 std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
248
Nate Begeman22237772010-06-02 00:34:55 +0000249 // Initialize Type Map
Nate Begeman5ddb0872010-05-28 01:08:32 +0000250
Nate Begeman22237772010-06-02 00:34:55 +0000251 // Unique the return+pattern types, and assign them.
Nate Begeman5ddb0872010-05-28 01:08:32 +0000252 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
253 Record *R = RV[i];
Nate Begeman22237772010-06-02 00:34:55 +0000254 std::string name = LowercaseString(R->getName());
255 std::string Proto = R->getValueAsString("Prototype");
Nate Begeman5ddb0872010-05-28 01:08:32 +0000256 std::string Types = R->getValueAsString("Types");
Nate Begeman22237772010-06-02 00:34:55 +0000257
258 SmallVector<StringRef, 16> TypeVec;
259 ParseTypes(R, Types, TypeVec);
260
261 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
262 assert(!Proto.empty() && "");
263
264 SmallString<128> Prototype;
265 Prototype += TypeString(Proto[0], TypeVec[ti]);
266 Prototype += " ";
267 Prototype += MangleName(name, TypeVec[ti]);
268 Prototype += GenArgs(Proto, TypeVec[ti]);
269
270 OS << Prototype << ";\n";
271
272 // gen definition
273
274 // if (opcode)
275
276 // gen opstring
277
278 // gen builtin (args)
279 }
280 OS << "\n";
Nate Begeman5ddb0872010-05-28 01:08:32 +0000281 }
Nate Begeman22237772010-06-02 00:34:55 +0000282
283 // TODO:
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.
Nate Begeman5ddb0872010-05-28 01:08:32 +0000287
Nate Begeman22237772010-06-02 00:34:55 +0000288 OS << "\n#endif /* __ARM_NEON_H */\n";
Nate Begeman5ddb0872010-05-28 01:08:32 +0000289}