~ubuntu-branches/ubuntu/saucy/clamav/saucy

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/utils/TableGen/NeonEmitter.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Leonel Nunez
  • Date: 2008-02-11 22:52:13 UTC
  • mfrom: (1.1.6 upstream)
  • mto: This revision was merged to the branch mainline in revision 38.
  • Revision ID: james.westby@ubuntu.com-20080211225213-p2uwj4czso1w2f8h
Tags: upstream-0.92~dfsg
ImportĀ upstreamĀ versionĀ 0.92~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//===- 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
21
 
// called, rather than the normal run() entry point.
22
 
//
23
 
//===----------------------------------------------------------------------===//
24
 
 
25
 
#include "NeonEmitter.h"
26
 
#include "llvm/ADT/SmallString.h"
27
 
#include "llvm/ADT/SmallVector.h"
28
 
#include "llvm/ADT/StringExtras.h"
29
 
#include <string>
30
 
 
31
 
using namespace llvm;
32
 
 
33
 
/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
34
 
/// which each StringRef representing a single type declared in the string.
35
 
/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
36
 
/// 2xfloat and 4xfloat respectively.
37
 
static void ParseTypes(Record *r, std::string &s,
38
 
                       SmallVectorImpl<StringRef> &TV) {
39
 
  const char *data = s.data();
40
 
  int len = 0;
41
 
  
42
 
  for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
43
 
    if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
44
 
      continue;
45
 
    
46
 
    switch (data[len]) {
47
 
      case 'c':
48
 
      case 's':
49
 
      case 'i':
50
 
      case 'l':
51
 
      case 'h':
52
 
      case 'f':
53
 
        break;
54
 
      default:
55
 
        throw TGError(r->getLoc(),
56
 
                      "Unexpected letter: " + std::string(data + len, 1));
57
 
        break;
58
 
    }
59
 
    TV.push_back(StringRef(data, len + 1));
60
 
    data += len + 1;
61
 
    len = -1;
62
 
  }
63
 
}
64
 
 
65
 
/// Widen - Convert a type code into the next wider type.  char -> short,
66
 
/// short -> int, etc.
67
 
static char Widen(const char t) {
68
 
  switch (t) {
69
 
    case 'c':
70
 
      return 's';
71
 
    case 's':
72
 
      return 'i';
73
 
    case 'i':
74
 
      return 'l';
75
 
    default: throw "unhandled type in widen!";
76
 
  }
77
 
  return '\0';
78
 
}
79
 
 
80
 
/// Narrow - Convert a type code into the next smaller type.  short -> char,
81
 
/// float -> half float, etc.
82
 
static char Narrow(const char t) {
83
 
  switch (t) {
84
 
    case 's':
85
 
      return 'c';
86
 
    case 'i':
87
 
      return 's';
88
 
    case 'l':
89
 
      return 'i';
90
 
    case 'f':
91
 
      return 'h';
92
 
    default: throw "unhandled type in widen!";
93
 
  }
94
 
  return '\0';
95
 
}
96
 
 
97
 
/// For a particular StringRef, return the base type code, and whether it has
98
 
/// the quad-vector, polynomial, or unsigned modifiers set.
99
 
static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
100
 
  unsigned off = 0;
101
 
  
102
 
  // remember quad.
103
 
  if (ty[off] == 'Q') {
104
 
    quad = true;
105
 
    ++off;
106
 
  }
107
 
  
108
 
  // remember poly.
109
 
  if (ty[off] == 'P') {
110
 
    poly = true;
111
 
    ++off;
112
 
  }
113
 
  
114
 
  // remember unsigned.
115
 
  if (ty[off] == 'U') {
116
 
    usgn = true;
117
 
    ++off;
118
 
  }
119
 
  
120
 
  // base type to get the type string for.
121
 
  return ty[off];
122
 
}
123
 
 
124
 
/// ModType - Transform a type code and its modifiers based on a mod code. The
125
 
/// mod code definitions may be found at the top of arm_neon.td.
126
 
static char ModType(const char mod, char type, bool &quad, bool &poly,
127
 
                    bool &usgn, bool &scal, bool &cnst, bool &pntr) {
128
 
  switch (mod) {
129
 
    case 't':
130
 
      if (poly) {
131
 
        poly = false;
132
 
        usgn = true;
133
 
      }
134
 
      break;
135
 
    case 'u':
136
 
      usgn = true;
137
 
    case 'x':
138
 
      poly = false;
139
 
      if (type == 'f')
140
 
        type = 'i';
141
 
      break;
142
 
    case 'f':
143
 
      if (type == 'h')
144
 
        quad = true;
145
 
      type = 'f';
146
 
      usgn = false;
147
 
      break;
148
 
    case 'g':
149
 
      quad = false;
150
 
      break;
151
 
    case 'w':
152
 
      type = Widen(type);
153
 
      quad = true;
154
 
      break;
155
 
    case 'n':
156
 
      type = Widen(type);
157
 
      break;
158
 
    case 'l':
159
 
      type = 'l';
160
 
      scal = true;
161
 
      usgn = true;
162
 
      break;
163
 
    case 's':
164
 
    case 'a':
165
 
      scal = true;
166
 
      break;
167
 
    case 'k':
168
 
      quad = true;
169
 
      break;
170
 
    case 'c':
171
 
      cnst = true;
172
 
    case 'p':
173
 
      pntr = true;
174
 
      scal = true;
175
 
      break;
176
 
    case 'h':
177
 
      type = Narrow(type);
178
 
      if (type == 'h')
179
 
        quad = false;
180
 
      break;
181
 
    case 'e':
182
 
      type = Narrow(type);
183
 
      usgn = true;
184
 
      break;
185
 
    default:
186
 
      break;
187
 
  }
188
 
  return type;
189
 
}
190
 
 
191
 
/// TypeString - for a modifier and type, generate the name of the typedef for
192
 
/// that type.  If generic is true, emit the generic vector type rather than
193
 
/// the public NEON type. QUc -> uint8x8_t / __neon_uint8x8_t.
194
 
static std::string TypeString(const char mod, StringRef typestr,
195
 
                              bool generic = false) {
196
 
  bool quad = false;
197
 
  bool poly = false;
198
 
  bool usgn = false;
199
 
  bool scal = false;
200
 
  bool cnst = false;
201
 
  bool pntr = false;
202
 
  
203
 
  if (mod == 'v')
204
 
    return "void";
205
 
  if (mod == 'i')
206
 
    return "int";
207
 
  
208
 
  // base type to get the type string for.
209
 
  char type = ClassifyType(typestr, quad, poly, usgn);
210
 
  
211
 
  // Based on the modifying character, change the type and width if necessary.
212
 
  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
213
 
  
214
 
  SmallString<128> s;
215
 
  
216
 
  if (generic)
217
 
    s += "__neon_";
218
 
  
219
 
  if (usgn)
220
 
    s.push_back('u');
221
 
  
222
 
  switch (type) {
223
 
    case 'c':
224
 
      s += poly ? "poly8" : "int8";
225
 
      if (scal)
226
 
        break;
227
 
      s += quad ? "x16" : "x8";
228
 
      break;
229
 
    case 's':
230
 
      s += poly ? "poly16" : "int16";
231
 
      if (scal)
232
 
        break;
233
 
      s += quad ? "x8" : "x4";
234
 
      break;
235
 
    case 'i':
236
 
      s += "int32";
237
 
      if (scal)
238
 
        break;
239
 
      s += quad ? "x4" : "x2";
240
 
      break;
241
 
    case 'l':
242
 
      s += "int64";
243
 
      if (scal)
244
 
        break;
245
 
      s += quad ? "x2" : "x1";
246
 
      break;
247
 
    case 'h':
248
 
      s += "float16";
249
 
      if (scal)
250
 
        break;
251
 
      s += quad ? "x8" : "x4";
252
 
      break;
253
 
    case 'f':
254
 
      s += "float32";
255
 
      if (scal)
256
 
        break;
257
 
      s += quad ? "x4" : "x2";
258
 
      break;
259
 
    default:
260
 
      throw "unhandled type!";
261
 
      break;
262
 
  }
263
 
 
264
 
  if (mod == '2')
265
 
    s += "x2";
266
 
  if (mod == '3')
267
 
    s += "x3";
268
 
  if (mod == '4')
269
 
    s += "x4";
270
 
  
271
 
  // Append _t, finishing the type string typedef type.
272
 
  s += "_t";
273
 
  
274
 
  if (cnst)
275
 
    s += " const";
276
 
  
277
 
  if (pntr)
278
 
    s += " *";
279
 
  
280
 
  return s.str();
281
 
}
282
 
 
283
 
/// BuiltinTypeString - for a modifier and type, generate the clang
284
 
/// BuiltinsARM.def prototype code for the function.  See the top of clang's
285
 
/// Builtins.def for a description of the type strings.
286
 
static std::string BuiltinTypeString(const char mod, StringRef typestr,
287
 
                                     ClassKind ck, bool ret) {
288
 
  bool quad = false;
289
 
  bool poly = false;
290
 
  bool usgn = false;
291
 
  bool scal = false;
292
 
  bool cnst = false;
293
 
  bool pntr = false;
294
 
  
295
 
  if (mod == 'v')
296
 
    return "v";
297
 
  if (mod == 'i')
298
 
    return "i";
299
 
  
300
 
  // base type to get the type string for.
301
 
  char type = ClassifyType(typestr, quad, poly, usgn);
302
 
  
303
 
  // Based on the modifying character, change the type and width if necessary.
304
 
  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
305
 
 
306
 
  if (pntr) {
307
 
    usgn = false;
308
 
    poly = false;
309
 
    type = 'v';
310
 
  }
311
 
  if (type == 'h') {
312
 
    type = 's';
313
 
    usgn = true;
314
 
  }
315
 
  usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
316
 
 
317
 
  if (scal) {
318
 
    SmallString<128> s;
319
 
 
320
 
    if (usgn)
321
 
      s.push_back('U');
322
 
    
323
 
    if (type == 'l')
324
 
      s += "LLi";
325
 
    else
326
 
      s.push_back(type);
327
 
 
328
 
    if (cnst)
329
 
      s.push_back('C');
330
 
    if (pntr)
331
 
      s.push_back('*');
332
 
    return s.str();
333
 
  }
334
 
 
335
 
  // Since the return value must be one type, return a vector type of the
336
 
  // appropriate width which we will bitcast.  An exception is made for
337
 
  // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
338
 
  // fashion, storing them to a pointer arg.
339
 
  if (ret) {
340
 
    if (mod == '2' || mod == '3' || mod == '4')
341
 
      return "vv*";
342
 
    if (mod == 'f' || (ck != ClassB && type == 'f'))
343
 
      return quad ? "V4f" : "V2f";
344
 
    if (ck != ClassB && type == 's')
345
 
      return quad ? "V8s" : "V4s";
346
 
    if (ck != ClassB && type == 'i')
347
 
      return quad ? "V4i" : "V2i";
348
 
    if (ck != ClassB && type == 'l')
349
 
      return quad ? "V2LLi" : "V1LLi";
350
 
    
351
 
    return quad ? "V16c" : "V8c";
352
 
  }    
353
 
 
354
 
  // Non-return array types are passed as individual vectors.
355
 
  if (mod == '2')
356
 
    return quad ? "V16cV16c" : "V8cV8c";
357
 
  if (mod == '3')
358
 
    return quad ? "V16cV16cV16c" : "V8cV8cV8c";
359
 
  if (mod == '4')
360
 
    return quad ? "V16cV16cV16cV16c" : "V8cV8cV8cV8c";
361
 
 
362
 
  if (mod == 'f' || (ck != ClassB && type == 'f'))
363
 
    return quad ? "V4f" : "V2f";
364
 
  if (ck != ClassB && type == 's')
365
 
    return quad ? "V8s" : "V4s";
366
 
  if (ck != ClassB && type == 'i')
367
 
    return quad ? "V4i" : "V2i";
368
 
  if (ck != ClassB && type == 'l')
369
 
    return quad ? "V2LLi" : "V1LLi";
370
 
  
371
 
  return quad ? "V16c" : "V8c";
372
 
}
373
 
 
374
 
/// StructTag - generate the name of the struct tag for a type.
375
 
/// These names are mandated by ARM's ABI.
376
 
static std::string StructTag(StringRef typestr) {
377
 
  bool quad = false;
378
 
  bool poly = false;
379
 
  bool usgn = false;
380
 
  
381
 
  // base type to get the type string for.
382
 
  char type = ClassifyType(typestr, quad, poly, usgn);
383
 
  
384
 
  SmallString<128> s;
385
 
  s += "__simd";
386
 
  s += quad ? "128_" : "64_";
387
 
  if (usgn)
388
 
    s.push_back('u');
389
 
  
390
 
  switch (type) {
391
 
    case 'c':
392
 
      s += poly ? "poly8" : "int8";
393
 
      break;
394
 
    case 's':
395
 
      s += poly ? "poly16" : "int16";
396
 
      break;
397
 
    case 'i':
398
 
      s += "int32";
399
 
      break;
400
 
    case 'l':
401
 
      s += "int64";
402
 
      break;
403
 
    case 'h':
404
 
      s += "float16";
405
 
      break;
406
 
    case 'f':
407
 
      s += "float32";
408
 
      break;
409
 
    default:
410
 
      throw "unhandled type!";
411
 
      break;
412
 
  }
413
 
 
414
 
  // Append _t, finishing the struct tag name.
415
 
  s += "_t";
416
 
  
417
 
  return s.str();
418
 
}
419
 
 
420
 
/// MangleName - Append a type or width suffix to a base neon function name, 
421
 
/// and insert a 'q' in the appropriate location if the operation works on
422
 
/// 128b rather than 64b.   E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
423
 
static std::string MangleName(const std::string &name, StringRef typestr,
424
 
                              ClassKind ck) {
425
 
  if (name == "vcvt_f32_f16")
426
 
    return name;
427
 
  
428
 
  bool quad = false;
429
 
  bool poly = false;
430
 
  bool usgn = false;
431
 
  char type = ClassifyType(typestr, quad, poly, usgn);
432
 
 
433
 
  std::string s = name;
434
 
  
435
 
  switch (type) {
436
 
  case 'c':
437
 
    switch (ck) {
438
 
    case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
439
 
    case ClassI: s += "_i8"; break;
440
 
    case ClassW: s += "_8"; break;
441
 
    default: break;
442
 
    }
443
 
    break;
444
 
  case 's':
445
 
    switch (ck) {
446
 
    case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
447
 
    case ClassI: s += "_i16"; break;
448
 
    case ClassW: s += "_16"; break;
449
 
    default: break;
450
 
    }
451
 
    break;
452
 
  case 'i':
453
 
    switch (ck) {
454
 
    case ClassS: s += usgn ? "_u32" : "_s32"; break;
455
 
    case ClassI: s += "_i32"; break;
456
 
    case ClassW: s += "_32"; break;
457
 
    default: break;
458
 
    }
459
 
    break;
460
 
  case 'l':
461
 
    switch (ck) {
462
 
    case ClassS: s += usgn ? "_u64" : "_s64"; break;
463
 
    case ClassI: s += "_i64"; break;
464
 
    case ClassW: s += "_64"; break;
465
 
    default: break;
466
 
    }
467
 
    break;
468
 
  case 'h':
469
 
    switch (ck) {
470
 
    case ClassS:
471
 
    case ClassI: s += "_f16"; break;
472
 
    case ClassW: s += "_16"; break;
473
 
    default: break;
474
 
    }
475
 
    break;
476
 
  case 'f':
477
 
    switch (ck) {
478
 
    case ClassS:
479
 
    case ClassI: s += "_f32"; break;
480
 
    case ClassW: s += "_32"; break;
481
 
    default: break;
482
 
    }
483
 
    break;
484
 
  default:
485
 
    throw "unhandled type!";
486
 
    break;
487
 
  }
488
 
  if (ck == ClassB)
489
 
    s += "_v";
490
 
    
491
 
  // Insert a 'q' before the first '_' character so that it ends up before 
492
 
  // _lane or _n on vector-scalar operations.
493
 
  if (quad) {
494
 
    size_t pos = s.find('_');
495
 
    s = s.insert(pos, "q");
496
 
  }
497
 
  return s;
498
 
}
499
 
 
500
 
// Generate the string "(argtype a, argtype b, ...)"
501
 
static std::string GenArgs(const std::string &proto, StringRef typestr) {
502
 
  bool define = proto.find('i') != std::string::npos;
503
 
  char arg = 'a';
504
 
  
505
 
  std::string s;
506
 
  s += "(";
507
 
  
508
 
  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
509
 
    if (!define) {
510
 
      s += TypeString(proto[i], typestr);
511
 
      s.push_back(' ');
512
 
    }
513
 
    s.push_back(arg);
514
 
    if ((i + 1) < e)
515
 
      s += ", ";
516
 
  }
517
 
  
518
 
  s += ")";
519
 
  return s;
520
 
}
521
 
 
522
 
static std::string Duplicate(unsigned nElts, StringRef typestr, 
523
 
                             const std::string &a) {
524
 
  std::string s;
525
 
  
526
 
  s = "(__neon_" + TypeString('d', typestr) + "){ ";
527
 
  for (unsigned i = 0; i != nElts; ++i) {
528
 
    s += a;
529
 
    if ((i + 1) < nElts)
530
 
      s += ", ";
531
 
  }
532
 
  s += " }";
533
 
  
534
 
  return s;
535
 
}
536
 
 
537
 
// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
538
 
// If structTypes is true, the NEON types are structs of vector types rather
539
 
// than vector types, and the call becomes "a.val + b.val"
540
 
static std::string GenOpString(OpKind op, const std::string &proto,
541
 
                               StringRef typestr, bool structTypes = true) {
542
 
  bool dummy, quad = false;
543
 
  char type = ClassifyType(typestr, quad, dummy, dummy);
544
 
  unsigned nElts = 0;
545
 
  switch (type) {
546
 
    case 'c': nElts = 8; break;
547
 
    case 's': nElts = 4; break;
548
 
    case 'i': nElts = 2; break;
549
 
    case 'l': nElts = 1; break;
550
 
    case 'h': nElts = 4; break;
551
 
    case 'f': nElts = 2; break;
552
 
  }
553
 
  
554
 
  std::string ts = TypeString(proto[0], typestr);
555
 
  std::string s = ts + " r; r";
556
 
  
557
 
  if (structTypes)
558
 
    s += ".val";
559
 
  
560
 
  s += " = ";
561
 
 
562
 
  std::string a, b, c;
563
 
  if (proto.size() > 1)
564
 
    a = (structTypes && proto[1] != 'l' && proto[1] != 's') ? "a.val" : "a";
565
 
  b = structTypes ? "b.val" : "b";
566
 
  c = structTypes ? "c.val" : "c";
567
 
  
568
 
  switch(op) {
569
 
  case OpAdd:
570
 
    s += a + " + " + b;
571
 
    break;
572
 
  case OpSub:
573
 
    s += a + " - " + b;
574
 
    break;
575
 
  case OpMulN:
576
 
    b = Duplicate(nElts << (int)quad, typestr, "b");
577
 
  case OpMul:
578
 
    s += a + " * " + b;
579
 
    break;
580
 
  case OpMlaN:
581
 
    c = Duplicate(nElts << (int)quad, typestr, "c");
582
 
  case OpMla:
583
 
    s += a + " + ( " + b + " * " + c + " )";
584
 
    break;
585
 
  case OpMlsN:
586
 
    c = Duplicate(nElts << (int)quad, typestr, "c");
587
 
  case OpMls:
588
 
    s += a + " - ( " + b + " * " + c + " )";
589
 
    break;
590
 
  case OpEq:
591
 
    s += "(__neon_" + ts + ")(" + a + " == " + b + ")";
592
 
    break;
593
 
  case OpGe:
594
 
    s += "(__neon_" + ts + ")(" + a + " >= " + b + ")";
595
 
    break;
596
 
  case OpLe:
597
 
    s += "(__neon_" + ts + ")(" + a + " <= " + b + ")";
598
 
    break;
599
 
  case OpGt:
600
 
    s += "(__neon_" + ts + ")(" + a + " > " + b + ")";
601
 
    break;
602
 
  case OpLt:
603
 
    s += "(__neon_" + ts + ")(" + a + " < " + b + ")";
604
 
    break;
605
 
  case OpNeg:
606
 
    s += " -" + a;
607
 
    break;
608
 
  case OpNot:
609
 
    s += " ~" + a;
610
 
    break;
611
 
  case OpAnd:
612
 
    s += a + " & " + b;
613
 
    break;
614
 
  case OpOr:
615
 
    s += a + " | " + b;
616
 
    break;
617
 
  case OpXor:
618
 
    s += a + " ^ " + b;
619
 
    break;
620
 
  case OpAndNot:
621
 
    s += a + " & ~" + b;
622
 
    break;
623
 
  case OpOrNot:
624
 
    s += a + " | ~" + b;
625
 
    break;
626
 
  case OpCast:
627
 
    s += "(__neon_" + ts + ")" + a;
628
 
    break;
629
 
  case OpConcat:
630
 
    s += "__builtin_shufflevector((__neon_int64x1_t)" + a;
631
 
    s += ", (__neon_int64x1_t)" + b + ", 0, 1)";
632
 
    break;
633
 
  case OpHi:
634
 
    s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[1])";
635
 
    break;
636
 
  case OpLo:
637
 
    s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[0])";
638
 
    break;
639
 
  case OpDup:
640
 
    s += Duplicate(nElts << (int)quad, typestr, a);
641
 
    break;
642
 
  case OpSelect:
643
 
    // ((0 & 1) | (~0 & 2))
644
 
    ts = TypeString(proto[1], typestr);
645
 
    s += "( " + a + " & (__neon_" + ts + ")" + b + ") | ";
646
 
    s += "(~" + a + " & (__neon_" + ts + ")" + c + ")";
647
 
    break;
648
 
  case OpRev16:
649
 
    s += "__builtin_shufflevector(" + a + ", " + a;
650
 
    for (unsigned i = 2; i <= nElts << (int)quad; i += 2)
651
 
      for (unsigned j = 0; j != 2; ++j)
652
 
        s += ", " + utostr(i - j - 1);
653
 
    s += ")";
654
 
    break;
655
 
  case OpRev32:
656
 
    nElts >>= 1;
657
 
    s += "__builtin_shufflevector(" + a + ", " + a;
658
 
    for (unsigned i = nElts; i <= nElts << (1 + (int)quad); i += nElts)
659
 
      for (unsigned j = 0; j != nElts; ++j)
660
 
        s += ", " + utostr(i - j - 1);
661
 
    s += ")";
662
 
    break;
663
 
  case OpRev64:
664
 
    s += "__builtin_shufflevector(" + a + ", " + a;
665
 
    for (unsigned i = nElts; i <= nElts << (int)quad; i += nElts)
666
 
      for (unsigned j = 0; j != nElts; ++j)
667
 
        s += ", " + utostr(i - j - 1);
668
 
    s += ")";
669
 
    break;
670
 
  default:
671
 
    throw "unknown OpKind!";
672
 
    break;
673
 
  }
674
 
  s += "; return r;";
675
 
  return s;
676
 
}
677
 
 
678
 
static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
679
 
  unsigned mod = proto[0];
680
 
  unsigned ret = 0;
681
 
 
682
 
  if (mod == 'v' || mod == 'f')
683
 
    mod = proto[1];
684
 
 
685
 
  bool quad = false;
686
 
  bool poly = false;
687
 
  bool usgn = false;
688
 
  bool scal = false;
689
 
  bool cnst = false;
690
 
  bool pntr = false;
691
 
  
692
 
  // Base type to get the type string for.
693
 
  char type = ClassifyType(typestr, quad, poly, usgn);
694
 
  
695
 
  // Based on the modifying character, change the type and width if necessary.
696
 
  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
697
 
 
698
 
  if (usgn)
699
 
    ret |= 0x08;
700
 
  if (quad && proto[1] != 'g')
701
 
    ret |= 0x10;
702
 
  
703
 
  switch (type) {
704
 
    case 'c': 
705
 
      ret |= poly ? 5 : 0;
706
 
      break;
707
 
    case 's':
708
 
      ret |= poly ? 6 : 1;
709
 
      break;
710
 
    case 'i':
711
 
      ret |= 2;
712
 
      break;
713
 
    case 'l':
714
 
      ret |= 3;
715
 
      break;
716
 
    case 'h':
717
 
      ret |= 7;
718
 
      break;
719
 
    case 'f':
720
 
      ret |= 4;
721
 
      break;
722
 
    default:
723
 
      throw "unhandled type!";
724
 
      break;
725
 
  }
726
 
  return ret;
727
 
}
728
 
 
729
 
// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
730
 
// If structTypes is true, the NEON types are structs of vector types rather
731
 
// than vector types, and the call becomes __builtin_neon_cls(a.val)
732
 
static std::string GenBuiltin(const std::string &name, const std::string &proto,
733
 
                              StringRef typestr, ClassKind ck,
734
 
                              bool structTypes = true) {
735
 
  bool dummy, quad = false;
736
 
  char type = ClassifyType(typestr, quad, dummy, dummy);
737
 
  unsigned nElts = 0;
738
 
  switch (type) {
739
 
    case 'c': nElts = 8; break;
740
 
    case 's': nElts = 4; break;
741
 
    case 'i': nElts = 2; break;
742
 
    case 'l': nElts = 1; break;
743
 
    case 'h': nElts = 4; break;
744
 
    case 'f': nElts = 2; break;
745
 
  }
746
 
  if (quad) nElts <<= 1;
747
 
 
748
 
  char arg = 'a';
749
 
  std::string s;
750
 
 
751
 
  // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
752
 
  // sret-like argument.
753
 
  bool sret = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4');
754
 
 
755
 
  // If this builtin takes an immediate argument, we need to #define it rather
756
 
  // than use a standard declaration, so that SemaChecking can range check
757
 
  // the immediate passed by the user.
758
 
  bool define = proto.find('i') != std::string::npos;
759
 
 
760
 
  // If all types are the same size, bitcasting the args will take care 
761
 
  // of arg checking.  The actual signedness etc. will be taken care of with
762
 
  // special enums.
763
 
  if (proto.find('s') == std::string::npos)
764
 
    ck = ClassB;
765
 
 
766
 
  if (proto[0] != 'v') {
767
 
    std::string ts = TypeString(proto[0], typestr);
768
 
    
769
 
    if (define) {
770
 
      if (sret)
771
 
        s += "({ " + ts + " r; ";
772
 
      else if (proto[0] != 's')
773
 
        s += "(" + ts + "){(__neon_" + ts + ")";
774
 
    } else if (sret) {
775
 
      s += ts + " r; ";
776
 
    } else {
777
 
      s += ts + " r; r";
778
 
      if (structTypes && proto[0] != 's' && proto[0] != 'i' && proto[0] != 'l')
779
 
        s += ".val";
780
 
      
781
 
      s += " = ";
782
 
    }
783
 
  }
784
 
  
785
 
  bool splat = proto.find('a') != std::string::npos;
786
 
  
787
 
  s += "__builtin_neon_";
788
 
  if (splat) {
789
 
    std::string vname(name, 0, name.size()-2);
790
 
    s += MangleName(vname, typestr, ck);
791
 
  } else {
792
 
    s += MangleName(name, typestr, ck);
793
 
  }
794
 
  s += "(";
795
 
 
796
 
  // Pass the address of the return variable as the first argument to sret-like
797
 
  // builtins.
798
 
  if (sret)
799
 
    s += "&r, ";
800
 
  
801
 
  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
802
 
    std::string args = std::string(&arg, 1);
803
 
    if (define)
804
 
      args = "(" + args + ")";
805
 
    
806
 
    // Handle multiple-vector values specially, emitting each subvector as an
807
 
    // argument to the __builtin.
808
 
    if (structTypes && (proto[i] == '2' || proto[i] == '3' || proto[i] == '4')){
809
 
      for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
810
 
        s += args + ".val[" + utostr(vi) + "].val";
811
 
        if ((vi + 1) < ve)
812
 
          s += ", ";
813
 
      }
814
 
      if ((i + 1) < e)
815
 
        s += ", ";
816
 
 
817
 
      continue;
818
 
    }
819
 
    
820
 
    if (splat && (i + 1) == e) 
821
 
      s += Duplicate(nElts, typestr, args);
822
 
    else
823
 
      s += args;
824
 
    
825
 
    if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' &&
826
 
        proto[i] != 'p' && proto[i] != 'c' && proto[i] != 'a') {
827
 
      s += ".val";
828
 
    }
829
 
    if ((i + 1) < e)
830
 
      s += ", ";
831
 
  }
832
 
  
833
 
  // Extra constant integer to hold type class enum for this function, e.g. s8
834
 
  if (ck == ClassB)
835
 
    s += ", " + utostr(GetNeonEnum(proto, typestr));
836
 
  
837
 
  if (define)
838
 
    s += ")";
839
 
  else
840
 
    s += ");";
841
 
 
842
 
  if (proto[0] != 'v') {
843
 
    if (define) {
844
 
      if (sret)
845
 
        s += "; r; })";
846
 
      else if (proto[0] != 's')
847
 
        s += "}";
848
 
    } else {
849
 
      s += " return r;";
850
 
    }
851
 
  }
852
 
  return s;
853
 
}
854
 
 
855
 
static std::string GenBuiltinDef(const std::string &name, 
856
 
                                 const std::string &proto,
857
 
                                 StringRef typestr, ClassKind ck) {
858
 
  std::string s("BUILTIN(__builtin_neon_");
859
 
 
860
 
  // If all types are the same size, bitcasting the args will take care 
861
 
  // of arg checking.  The actual signedness etc. will be taken care of with
862
 
  // special enums.
863
 
  if (proto.find('s') == std::string::npos)
864
 
    ck = ClassB;
865
 
  
866
 
  s += MangleName(name, typestr, ck);
867
 
  s += ", \"";
868
 
  
869
 
  for (unsigned i = 0, e = proto.size(); i != e; ++i)
870
 
    s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
871
 
 
872
 
  // Extra constant integer to hold type class enum for this function, e.g. s8
873
 
  if (ck == ClassB)
874
 
    s += "i";
875
 
  
876
 
  s += "\", \"n\")";
877
 
  return s;
878
 
}
879
 
 
880
 
/// run - Read the records in arm_neon.td and output arm_neon.h.  arm_neon.h
881
 
/// is comprised of type definitions and function declarations.
882
 
void NeonEmitter::run(raw_ostream &OS) {
883
 
  EmitSourceFileHeader("ARM NEON Header", OS);
884
 
  
885
 
  // FIXME: emit license into file?
886
 
  
887
 
  OS << "#ifndef __ARM_NEON_H\n";
888
 
  OS << "#define __ARM_NEON_H\n\n";
889
 
  
890
 
  OS << "#ifndef __ARM_NEON__\n";
891
 
  OS << "#error \"NEON support not enabled\"\n";
892
 
  OS << "#endif\n\n";
893
 
 
894
 
  OS << "#include <stdint.h>\n\n";
895
 
 
896
 
  // Emit NEON-specific scalar typedefs.
897
 
  OS << "typedef float float32_t;\n";
898
 
  OS << "typedef uint8_t poly8_t;\n";
899
 
  OS << "typedef uint16_t poly16_t;\n";
900
 
  OS << "typedef uint16_t float16_t;\n";
901
 
 
902
 
  // Emit Neon vector typedefs.
903
 
  std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
904
 
  SmallVector<StringRef, 24> TDTypeVec;
905
 
  ParseTypes(0, TypedefTypes, TDTypeVec);
906
 
 
907
 
  // Emit vector typedefs.
908
 
  for (unsigned v = 1; v != 5; ++v) {
909
 
    for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
910
 
      bool dummy, quad = false;
911
 
      (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy);
912
 
      OS << "typedef __attribute__(( __vector_size__(";
913
 
      
914
 
      OS << utostr(8*v*(quad ? 2 : 1)) << ") )) ";
915
 
      if (!quad)
916
 
        OS << " ";
917
 
      
918
 
      OS << TypeString('s', TDTypeVec[i]);
919
 
      OS << " __neon_";
920
 
      
921
 
      char t = (v == 1) ? 'd' : '0' + v;
922
 
      OS << TypeString(t, TDTypeVec[i]) << ";\n";
923
 
    }
924
 
  }
925
 
  OS << "\n";
926
 
 
927
 
  // Emit struct typedefs.
928
 
  for (unsigned vi = 1; vi != 5; ++vi) {
929
 
    for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
930
 
      std::string ts = TypeString('d', TDTypeVec[i], vi == 1);
931
 
      std::string vs = TypeString((vi > 1) ? '0' + vi : 'd', TDTypeVec[i]);
932
 
      std::string tag = (vi > 1) ? vs : StructTag(TDTypeVec[i]);
933
 
      OS << "typedef struct " << tag << " {\n";
934
 
      OS << "  " << ts << " val";
935
 
      if (vi > 1)
936
 
        OS << "[" << utostr(vi) << "]";
937
 
      OS << ";\n} " << vs << ";\n\n";
938
 
    }
939
 
  }
940
 
  
941
 
  OS << "#define __ai static __attribute__((__always_inline__))\n\n";
942
 
 
943
 
  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
944
 
  
945
 
  // Unique the return+pattern types, and assign them.
946
 
  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
947
 
    Record *R = RV[i];
948
 
    std::string name = LowercaseString(R->getName());
949
 
    std::string Proto = R->getValueAsString("Prototype");
950
 
    std::string Types = R->getValueAsString("Types");
951
 
    
952
 
    SmallVector<StringRef, 16> TypeVec;
953
 
    ParseTypes(R, Types, TypeVec);
954
 
    
955
 
    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
956
 
    
957
 
    bool define = Proto.find('i') != std::string::npos;
958
 
    
959
 
    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
960
 
      assert(!Proto.empty() && "");
961
 
      
962
 
      // static always inline + return type
963
 
      if (define)
964
 
        OS << "#define";
965
 
      else
966
 
        OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
967
 
      
968
 
      // Function name with type suffix
969
 
      OS << " " << MangleName(name, TypeVec[ti], ClassS);
970
 
      
971
 
      // Function arguments
972
 
      OS << GenArgs(Proto, TypeVec[ti]);
973
 
      
974
 
      // Definition.
975
 
      if (define)
976
 
        OS << " ";
977
 
      else
978
 
        OS << " { ";
979
 
      
980
 
      if (k != OpNone) {
981
 
        OS << GenOpString(k, Proto, TypeVec[ti]);
982
 
      } else {
983
 
        if (R->getSuperClasses().size() < 2)
984
 
          throw TGError(R->getLoc(), "Builtin has no class kind");
985
 
        
986
 
        ClassKind ck = ClassMap[R->getSuperClasses()[1]];
987
 
 
988
 
        if (ck == ClassNone)
989
 
          throw TGError(R->getLoc(), "Builtin has no class kind");
990
 
        OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
991
 
      }
992
 
      if (!define)
993
 
        OS << " }";
994
 
      OS << "\n";
995
 
    }
996
 
    OS << "\n";
997
 
  }
998
 
  OS << "#undef __ai\n\n";
999
 
  OS << "#endif /* __ARM_NEON_H */\n";
1000
 
}
1001
 
 
1002
 
static unsigned RangeFromType(StringRef typestr) {
1003
 
  // base type to get the type string for.
1004
 
  bool quad = false, dummy = false;
1005
 
  char type = ClassifyType(typestr, quad, dummy, dummy);
1006
 
  
1007
 
  switch (type) {
1008
 
    case 'c':
1009
 
      return (8 << (int)quad) - 1;
1010
 
    case 'h':
1011
 
    case 's':
1012
 
      return (4 << (int)quad) - 1;
1013
 
    case 'f':
1014
 
    case 'i':
1015
 
      return (2 << (int)quad) - 1;
1016
 
    case 'l':
1017
 
      return (1 << (int)quad) - 1;
1018
 
    default:
1019
 
      throw "unhandled type!";
1020
 
      break;
1021
 
  }
1022
 
  assert(0 && "unreachable");
1023
 
  return 0;
1024
 
}
1025
 
 
1026
 
/// runHeader - Emit a file with sections defining:
1027
 
/// 1. the NEON section of BuiltinsARM.def.
1028
 
/// 2. the SemaChecking code for the type overload checking.
1029
 
/// 3. the SemaChecking code for validation of intrinsic immedate arguments.
1030
 
void NeonEmitter::runHeader(raw_ostream &OS) {
1031
 
  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
1032
 
 
1033
 
  StringMap<OpKind> EmittedMap;
1034
 
  
1035
 
  // Generate BuiltinsARM.def for NEON
1036
 
  OS << "#ifdef GET_NEON_BUILTINS\n";
1037
 
  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1038
 
    Record *R = RV[i];
1039
 
    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
1040
 
    if (k != OpNone)
1041
 
      continue;
1042
 
 
1043
 
    std::string Proto = R->getValueAsString("Prototype");
1044
 
    
1045
 
    // Functions with 'a' (the splat code) in the type prototype should not get
1046
 
    // their own builtin as they use the non-splat variant.
1047
 
    if (Proto.find('a') != std::string::npos)
1048
 
      continue;
1049
 
    
1050
 
    std::string Types = R->getValueAsString("Types");
1051
 
    SmallVector<StringRef, 16> TypeVec;
1052
 
    ParseTypes(R, Types, TypeVec);
1053
 
    
1054
 
    if (R->getSuperClasses().size() < 2)
1055
 
      throw TGError(R->getLoc(), "Builtin has no class kind");
1056
 
    
1057
 
    std::string name = LowercaseString(R->getName());
1058
 
    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
1059
 
    
1060
 
    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1061
 
      // Generate the BuiltinsARM.def declaration for this builtin, ensuring
1062
 
      // that each unique BUILTIN() macro appears only once in the output
1063
 
      // stream.
1064
 
      std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
1065
 
      if (EmittedMap.count(bd))
1066
 
        continue;
1067
 
      
1068
 
      EmittedMap[bd] = OpNone;
1069
 
      OS << bd << "\n";
1070
 
    }
1071
 
  }
1072
 
  OS << "#endif\n\n";
1073
 
  
1074
 
  // Generate the overloaded type checking code for SemaChecking.cpp
1075
 
  OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
1076
 
  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1077
 
    Record *R = RV[i];
1078
 
    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
1079
 
    if (k != OpNone)
1080
 
      continue;
1081
 
    
1082
 
    std::string Proto = R->getValueAsString("Prototype");
1083
 
    std::string Types = R->getValueAsString("Types");
1084
 
    std::string name = LowercaseString(R->getName());
1085
 
    
1086
 
    // Functions with 'a' (the splat code) in the type prototype should not get
1087
 
    // their own builtin as they use the non-splat variant.
1088
 
    if (Proto.find('a') != std::string::npos)
1089
 
      continue;
1090
 
    
1091
 
    // Functions which have a scalar argument cannot be overloaded, no need to
1092
 
    // check them if we are emitting the type checking code.
1093
 
    if (Proto.find('s') != std::string::npos)
1094
 
      continue;
1095
 
    
1096
 
    SmallVector<StringRef, 16> TypeVec;
1097
 
    ParseTypes(R, Types, TypeVec);
1098
 
    
1099
 
    if (R->getSuperClasses().size() < 2)
1100
 
      throw TGError(R->getLoc(), "Builtin has no class kind");
1101
 
    
1102
 
    int si = -1, qi = -1;
1103
 
    unsigned mask = 0, qmask = 0;
1104
 
    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1105
 
      // Generate the switch case(s) for this builtin for the type validation.
1106
 
      bool quad = false, poly = false, usgn = false;
1107
 
      (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
1108
 
      
1109
 
      if (quad) {
1110
 
        qi = ti;
1111
 
        qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
1112
 
      } else {
1113
 
        si = ti;
1114
 
        mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
1115
 
      }
1116
 
    }
1117
 
    if (mask)
1118
 
      OS << "case ARM::BI__builtin_neon_" 
1119
 
      << MangleName(name, TypeVec[si], ClassB)
1120
 
      << ": mask = " << "0x" << utohexstr(mask) << "; break;\n";
1121
 
    if (qmask)
1122
 
      OS << "case ARM::BI__builtin_neon_" 
1123
 
      << MangleName(name, TypeVec[qi], ClassB)
1124
 
      << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n";
1125
 
  }
1126
 
  OS << "#endif\n\n";
1127
 
  
1128
 
  // Generate the intrinsic range checking code for shift/lane immediates.
1129
 
  OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
1130
 
  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1131
 
    Record *R = RV[i];
1132
 
    
1133
 
    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
1134
 
    if (k != OpNone)
1135
 
      continue;
1136
 
    
1137
 
    std::string name = LowercaseString(R->getName());
1138
 
    std::string Proto = R->getValueAsString("Prototype");
1139
 
    std::string Types = R->getValueAsString("Types");
1140
 
    
1141
 
    // Functions with 'a' (the splat code) in the type prototype should not get
1142
 
    // their own builtin as they use the non-splat variant.
1143
 
    if (Proto.find('a') != std::string::npos)
1144
 
      continue;
1145
 
    
1146
 
    // Functions which do not have an immediate do not need to have range
1147
 
    // checking code emitted.
1148
 
    if (Proto.find('i') == std::string::npos)
1149
 
      continue;
1150
 
    
1151
 
    SmallVector<StringRef, 16> TypeVec;
1152
 
    ParseTypes(R, Types, TypeVec);
1153
 
    
1154
 
    if (R->getSuperClasses().size() < 2)
1155
 
      throw TGError(R->getLoc(), "Builtin has no class kind");
1156
 
    
1157
 
    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
1158
 
    
1159
 
    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1160
 
      std::string namestr, shiftstr, rangestr;
1161
 
      
1162
 
      // Builtins which are overloaded by type will need to have their upper
1163
 
      // bound computed at Sema time based on the type constant.
1164
 
      if (Proto.find('s') == std::string::npos) {
1165
 
        ck = ClassB;
1166
 
        if (R->getValueAsBit("isShift")) {
1167
 
          shiftstr = ", true";
1168
 
          
1169
 
          // Right shifts have an 'r' in the name, left shifts do not.
1170
 
          if (name.find('r') != std::string::npos)
1171
 
            rangestr = "l = 1; ";
1172
 
        }
1173
 
        rangestr += "u = RFT(TV" + shiftstr + ")";
1174
 
      } else {
1175
 
        rangestr = "u = " + utostr(RangeFromType(TypeVec[ti]));
1176
 
      }
1177
 
      // Make sure cases appear only once by uniquing them in a string map.
1178
 
      namestr = MangleName(name, TypeVec[ti], ck);
1179
 
      if (EmittedMap.count(namestr))
1180
 
        continue;
1181
 
      EmittedMap[namestr] = OpNone;
1182
 
 
1183
 
      // Calculate the index of the immediate that should be range checked.
1184
 
      unsigned immidx = 0;
1185
 
      
1186
 
      // Builtins that return a struct of multiple vectors have an extra
1187
 
      // leading arg for the struct return.
1188
 
      if (Proto[0] == '2' || Proto[0] == '3' || Proto[0] == '4')
1189
 
        ++immidx;
1190
 
      
1191
 
      // Add one to the index for each argument until we reach the immediate 
1192
 
      // to be checked.  Structs of vectors are passed as multiple arguments.
1193
 
      for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
1194
 
        switch (Proto[ii]) {
1195
 
          default:  immidx += 1; break;
1196
 
          case '2': immidx += 2; break;
1197
 
          case '3': immidx += 3; break;
1198
 
          case '4': immidx += 4; break;
1199
 
          case 'i': ie = ii + 1; break;
1200
 
        }
1201
 
      }
1202
 
      OS << "case ARM::BI__builtin_neon_"  << MangleName(name, TypeVec[ti], ck)
1203
 
         << ": i = " << immidx << "; " << rangestr << "; break;\n";
1204
 
    }
1205
 
  }
1206
 
  OS << "#endif\n\n";
1207
 
}