llvm.org GIT mirror llvm / 6d1409d
Remove the Clang tblgen backends from LLVM. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141293 91177308-0d34-0410-b5e6-96231b3b80d8 Peter Collingbourne 8 years ago
14 changed file(s) with 0 addition(s) and 4019 deletion(s). Raw diff Collapse all Expand all
66 AsmWriterEmitter.cpp
77 AsmWriterInst.cpp
88 CallingConvEmitter.cpp
9 ClangASTNodesEmitter.cpp
10 ClangAttrEmitter.cpp
11 ClangDiagnosticsEmitter.cpp
12 ClangSACheckersEmitter.cpp
139 CodeEmitterGen.cpp
1410 CodeGenDAGPatterns.cpp
1511 CodeGenInstruction.cpp
2723 InstrEnumEmitter.cpp
2824 InstrInfoEmitter.cpp
2925 IntrinsicEmitter.cpp
30 NeonEmitter.cpp
31 OptParserEmitter.cpp
3226 PseudoLoweringEmitter.cpp
3327 RegisterInfoEmitter.cpp
3428 SetTheory.cpp
+0
-168
utils/TableGen/ClangASTNodesEmitter.cpp less more
None //=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // These tablegen backends emit Clang AST node tables
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "ClangASTNodesEmitter.h"
14 #include
15 using namespace llvm;
16
17 //===----------------------------------------------------------------------===//
18 // Statement Node Tables (.inc file) generation.
19 //===----------------------------------------------------------------------===//
20
21 // Returns the first and last non-abstract subrecords
22 // Called recursively to ensure that nodes remain contiguous
23 std::pair ClangASTNodesEmitter::EmitNode(
24 const ChildMap &Tree,
25 raw_ostream &OS,
26 Record *Base) {
27 std::string BaseName = macroName(Base->getName());
28
29 ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base);
30
31 Record *First = 0, *Last = 0;
32 // This might be the pseudo-node for Stmt; don't assume it has an Abstract
33 // bit
34 if (Base->getValue("Abstract") && !Base->getValueAsBit("Abstract"))
35 First = Last = Base;
36
37 for (; i != e; ++i) {
38 Record *R = i->second;
39 bool Abstract = R->getValueAsBit("Abstract");
40 std::string NodeName = macroName(R->getName());
41
42 OS << "#ifndef " << NodeName << "\n";
43 OS << "# define " << NodeName << "(Type, Base) "
44 << BaseName << "(Type, Base)\n";
45 OS << "#endif\n";
46
47 if (Abstract)
48 OS << "ABSTRACT_" << macroName(Root.getName()) << "(" << NodeName << "("
49 << R->getName() << ", " << baseName(*Base) << "))\n";
50 else
51 OS << NodeName << "(" << R->getName() << ", "
52 << baseName(*Base) << ")\n";
53
54 if (Tree.find(R) != Tree.end()) {
55 const std::pair &Result
56 = EmitNode(Tree, OS, R);
57 if (!First && Result.first)
58 First = Result.first;
59 if (Result.second)
60 Last = Result.second;
61 } else {
62 if (!Abstract) {
63 Last = R;
64
65 if (!First)
66 First = R;
67 }
68 }
69
70 OS << "#undef " << NodeName << "\n\n";
71 }
72
73 if (First) {
74 assert (Last && "Got a first node but not a last node for a range!");
75 if (Base == &Root)
76 OS << "LAST_" << macroName(Root.getName()) << "_RANGE(";
77 else
78 OS << macroName(Root.getName()) << "_RANGE(";
79 OS << Base->getName() << ", " << First->getName() << ", "
80 << Last->getName() << ")\n\n";
81 }
82
83 return std::make_pair(First, Last);
84 }
85
86 void ClangASTNodesEmitter::run(raw_ostream &OS) {
87 // Write the preamble
88 OS << "#ifndef ABSTRACT_" << macroName(Root.getName()) << "\n";
89 OS << "# define ABSTRACT_" << macroName(Root.getName()) << "(Type) Type\n";
90 OS << "#endif\n";
91
92 OS << "#ifndef " << macroName(Root.getName()) << "_RANGE\n";
93 OS << "# define "
94 << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
95 OS << "#endif\n\n";
96
97 OS << "#ifndef LAST_" << macroName(Root.getName()) << "_RANGE\n";
98 OS << "# define LAST_"
99 << macroName(Root.getName()) << "_RANGE(Base, First, Last) "
100 << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
101 OS << "#endif\n\n";
102
103 // Emit statements
104 const std::vector Stmts
105 = Records.getAllDerivedDefinitions(Root.getName());
106
107 ChildMap Tree;
108
109 for (unsigned i = 0, e = Stmts.size(); i != e; ++i) {
110 Record *R = Stmts[i];
111
112 if (R->getValue("Base"))
113 Tree.insert(std::make_pair(R->getValueAsDef("Base"), R));
114 else
115 Tree.insert(std::make_pair(&Root, R));
116 }
117
118 EmitNode(Tree, OS, &Root);
119
120 OS << "#undef " << macroName(Root.getName()) << "\n";
121 OS << "#undef " << macroName(Root.getName()) << "_RANGE\n";
122 OS << "#undef LAST_" << macroName(Root.getName()) << "_RANGE\n";
123 OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n";
124 }
125
126 void ClangDeclContextEmitter::run(raw_ostream &OS) {
127 // FIXME: Find a .td file format to allow for this to be represented better.
128
129 OS << "#ifndef DECL_CONTEXT\n";
130 OS << "# define DECL_CONTEXT(DECL)\n";
131 OS << "#endif\n";
132
133 OS << "#ifndef DECL_CONTEXT_BASE\n";
134 OS << "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n";
135 OS << "#endif\n";
136
137 typedef std::set RecordSet;
138 typedef std::vector RecordVector;
139
140 RecordVector DeclContextsVector
141 = Records.getAllDerivedDefinitions("DeclContext");
142 RecordVector Decls = Records.getAllDerivedDefinitions("Decl");
143 RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end());
144
145 for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) {
146 Record *R = *i;
147
148 if (R->getValue("Base")) {
149 Record *B = R->getValueAsDef("Base");
150 if (DeclContexts.find(B) != DeclContexts.end()) {
151 OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n";
152 DeclContexts.erase(B);
153 }
154 }
155 }
156
157 // To keep identical order, RecordVector may be used
158 // instead of RecordSet.
159 for (RecordVector::iterator
160 i = DeclContextsVector.begin(), e = DeclContextsVector.end();
161 i != e; ++i)
162 if (DeclContexts.find(*i) != DeclContexts.end())
163 OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n";
164
165 OS << "#undef DECL_CONTEXT\n";
166 OS << "#undef DECL_CONTEXT_BASE\n";
167 }
+0
-84
utils/TableGen/ClangASTNodesEmitter.h less more
None //===- ClangASTNodesEmitter.h - Generate Clang AST node tables -*- C++ -*--===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // These tablegen backends emit Clang AST node tables
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef CLANGAST_EMITTER_H
14 #define CLANGAST_EMITTER_H
15
16 #include "llvm/TableGen/TableGenBackend.h"
17 #include "llvm/TableGen/Record.h"
18 #include
19 #include
20 #include
21
22 namespace llvm {
23
24 /// ClangASTNodesEmitter - The top-level class emits .inc files containing
25 /// declarations of Clang statements.
26 ///
27 class ClangASTNodesEmitter : public TableGenBackend {
28 // A map from a node to each of its derived nodes.
29 typedef std::multimap ChildMap;
30 typedef ChildMap::const_iterator ChildIterator;
31
32 RecordKeeper &Records;
33 Record Root;
34 const std::string &BaseSuffix;
35
36 // Create a macro-ized version of a name
37 static std::string macroName(std::string S) {
38 for (unsigned i = 0; i < S.size(); ++i)
39 S[i] = std::toupper(S[i]);
40
41 return S;
42 }
43
44 // Return the name to be printed in the base field. Normally this is
45 // the record's name plus the base suffix, but if it is the root node and
46 // the suffix is non-empty, it's just the suffix.
47 std::string baseName(Record &R) {
48 if (&R == &Root && !BaseSuffix.empty())
49 return BaseSuffix;
50
51 return R.getName() + BaseSuffix;
52 }
53
54 std::pair EmitNode (const ChildMap &Tree, raw_ostream& OS,
55 Record *Base);
56 public:
57 explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N,
58 const std::string &S)
59 : Records(R), Root(N, SMLoc(), R), BaseSuffix(S)
60 {}
61
62 // run - Output the .inc file contents
63 void run(raw_ostream &OS);
64 };
65
66 /// ClangDeclContextEmitter - Emits an addendum to a .inc file to enumerate the
67 /// clang declaration contexts.
68 ///
69 class ClangDeclContextEmitter : public TableGenBackend {
70 RecordKeeper &Records;
71
72 public:
73 explicit ClangDeclContextEmitter(RecordKeeper &R)
74 : Records(R)
75 {}
76
77 // run - Output the .inc file contents
78 void run(raw_ostream &OS);
79 };
80
81 } // End llvm namespace
82
83 #endif
+0
-788
utils/TableGen/ClangAttrEmitter.cpp less more
None //===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // These tablegen backends emit Clang attribute processing code
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "ClangAttrEmitter.h"
14 #include "llvm/ADT/StringSwitch.h"
15 #include "llvm/TableGen/Record.h"
16 #include
17 #include
18
19 using namespace llvm;
20
21 static const std::vector
22 getValueAsListOfStrings(Record &R, StringRef FieldName) {
23 ListInit *List = R.getValueAsListInit(FieldName);
24 assert (List && "Got a null ListInit");
25
26 std::vector Strings;
27 Strings.reserve(List->getSize());
28
29 for (ListInit::const_iterator i = List->begin(), e = List->end();
30 i != e;
31 ++i) {
32 assert(*i && "Got a null element in a ListInit");
33 if (StringInit *S = dynamic_cast(*i))
34 Strings.push_back(S->getValue());
35 else if (CodeInit *C = dynamic_cast(*i))
36 Strings.push_back(C->getValue());
37 else
38 assert(false && "Got a non-string, non-code element in a ListInit");
39 }
40
41 return Strings;
42 }
43
44 static std::string ReadPCHRecord(StringRef type) {
45 return StringSwitch(type)
46 .EndsWith("Decl *", "GetLocalDeclAs<"
47 + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
48 .Case("QualType", "getLocalType(F, Record[Idx++])")
49 .Case("Expr *", "ReadSubExpr()")
50 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
51 .Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)")
52 .Default("Record[Idx++]");
53 }
54
55 // Assumes that the way to get the value is SA->getname()
56 static std::string WritePCHRecord(StringRef type, StringRef name) {
57 return StringSwitch(type)
58 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
59 ", Record);\n")
60 .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
61 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
62 .Case("IdentifierInfo *",
63 "AddIdentifierRef(" + std::string(name) + ", Record);\n")
64 .Case("SourceLocation",
65 "AddSourceLocation(" + std::string(name) + ", Record);\n")
66 .Default("Record.push_back(" + std::string(name) + ");\n");
67 }
68
69 namespace {
70 class Argument {
71 std::string lowerName, upperName;
72 StringRef attrName;
73
74 public:
75 Argument(Record &Arg, StringRef Attr)
76 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
77 attrName(Attr) {
78 if (!lowerName.empty()) {
79 lowerName[0] = std::tolower(lowerName[0]);
80 upperName[0] = std::toupper(upperName[0]);
81 }
82 }
83 virtual ~Argument() {}
84
85 StringRef getLowerName() const { return lowerName; }
86 StringRef getUpperName() const { return upperName; }
87 StringRef getAttrName() const { return attrName; }
88
89 // These functions print the argument contents formatted in different ways.
90 virtual void writeAccessors(raw_ostream &OS) const = 0;
91 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
92 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
93 virtual void writeCtorBody(raw_ostream &OS) const {}
94 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
95 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
96 virtual void writeDeclarations(raw_ostream &OS) const = 0;
97 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
98 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
99 virtual void writePCHWrite(raw_ostream &OS) const = 0;
100 };
101
102 class SimpleArgument : public Argument {
103 std::string type;
104
105 public:
106 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
107 : Argument(Arg, Attr), type(T)
108 {}
109
110 void writeAccessors(raw_ostream &OS) const {
111 OS << " " << type << " get" << getUpperName() << "() const {\n";
112 OS << " return " << getLowerName() << ";\n";
113 OS << " }";
114 }
115 void writeCloneArgs(raw_ostream &OS) const {
116 OS << getLowerName();
117 }
118 void writeCtorInitializers(raw_ostream &OS) const {
119 OS << getLowerName() << "(" << getUpperName() << ")";
120 }
121 void writeCtorParameters(raw_ostream &OS) const {
122 OS << type << " " << getUpperName();
123 }
124 void writeDeclarations(raw_ostream &OS) const {
125 OS << type << " " << getLowerName() << ";";
126 }
127 void writePCHReadDecls(raw_ostream &OS) const {
128 std::string read = ReadPCHRecord(type);
129 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
130 }
131 void writePCHReadArgs(raw_ostream &OS) const {
132 OS << getLowerName();
133 }
134 void writePCHWrite(raw_ostream &OS) const {
135 OS << " " << WritePCHRecord(type, "SA->get" +
136 std::string(getUpperName()) + "()");
137 }
138 };
139
140 class StringArgument : public Argument {
141 public:
142 StringArgument(Record &Arg, StringRef Attr)
143 : Argument(Arg, Attr)
144 {}
145
146 void writeAccessors(raw_ostream &OS) const {
147 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
148 OS << " return llvm::StringRef(" << getLowerName() << ", "
149 << getLowerName() << "Length);\n";
150 OS << " }\n";
151 OS << " unsigned get" << getUpperName() << "Length() const {\n";
152 OS << " return " << getLowerName() << "Length;\n";
153 OS << " }\n";
154 OS << " void set" << getUpperName()
155 << "(ASTContext &C, llvm::StringRef S) {\n";
156 OS << " " << getLowerName() << "Length = S.size();\n";
157 OS << " this->" << getLowerName() << " = new (C, 1) char ["
158 << getLowerName() << "Length];\n";
159 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
160 << getLowerName() << "Length);\n";
161 OS << " }";
162 }
163 void writeCloneArgs(raw_ostream &OS) const {
164 OS << "get" << getUpperName() << "()";
165 }
166 void writeCtorBody(raw_ostream &OS) const {
167 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
168 << ".data(), " << getLowerName() << "Length);";
169 }
170 void writeCtorInitializers(raw_ostream &OS) const {
171 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
172 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
173 << "Length])";
174 }
175 void writeCtorParameters(raw_ostream &OS) const {
176 OS << "llvm::StringRef " << getUpperName();
177 }
178 void writeDeclarations(raw_ostream &OS) const {
179 OS << "unsigned " << getLowerName() << "Length;\n";
180 OS << "char *" << getLowerName() << ";";
181 }
182 void writePCHReadDecls(raw_ostream &OS) const {
183 OS << " std::string " << getLowerName()
184 << "= ReadString(Record, Idx);\n";
185 }
186 void writePCHReadArgs(raw_ostream &OS) const {
187 OS << getLowerName();
188 }
189 void writePCHWrite(raw_ostream &OS) const {
190 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
191 }
192 };
193
194 class AlignedArgument : public Argument {
195 public:
196 AlignedArgument(Record &Arg, StringRef Attr)
197 : Argument(Arg, Attr)
198 {}
199
200 void writeAccessors(raw_ostream &OS) const {
201 OS << " bool is" << getUpperName() << "Dependent() const;\n";
202
203 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
204
205 OS << " bool is" << getUpperName() << "Expr() const {\n";
206 OS << " return is" << getLowerName() << "Expr;\n";
207 OS << " }\n";
208
209 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
210 OS << " assert(is" << getLowerName() << "Expr);\n";
211 OS << " return " << getLowerName() << "Expr;\n";
212 OS << " }\n";
213
214 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
215 OS << " assert(!is" << getLowerName() << "Expr);\n";
216 OS << " return " << getLowerName() << "Type;\n";
217 OS << " }";
218 }
219 void writeAccessorDefinitions(raw_ostream &OS) const {
220 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
221 << "Dependent() const {\n";
222 OS << " if (is" << getLowerName() << "Expr)\n";
223 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
224 << "Expr->isValueDependent() || " << getLowerName()
225 << "Expr->isTypeDependent());\n";
226 OS << " else\n";
227 OS << " return " << getLowerName()
228 << "Type->getType()->isDependentType();\n";
229 OS << "}\n";
230
231 // FIXME: Do not do the calculation here
232 // FIXME: Handle types correctly
233 // A null pointer means maximum alignment
234 // FIXME: Load the platform-specific maximum alignment, rather than
235 // 16, the x86 max.
236 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
237 << "(ASTContext &Ctx) const {\n";
238 OS << " assert(!is" << getUpperName() << "Dependent());\n";
239 OS << " if (is" << getLowerName() << "Expr)\n";
240 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
241 << "Expr->EvaluateAsInt(Ctx).getZExtValue() : 16)"
242 << "* Ctx.getCharWidth();\n";
243 OS << " else\n";
244 OS << " return 0; // FIXME\n";
245 OS << "}\n";
246 }
247 void writeCloneArgs(raw_ostream &OS) const {
248 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
249 << "Expr ? static_cast(" << getLowerName()
250 << "Expr) : " << getLowerName()
251 << "Type";
252 }
253 void writeCtorBody(raw_ostream &OS) const {
254 OS << " if (is" << getLowerName() << "Expr)\n";
255 OS << " " << getLowerName() << "Expr = reinterpret_cast("
256 << getUpperName() << ");\n";
257 OS << " else\n";
258 OS << " " << getLowerName()
259 << "Type = reinterpret_cast(" << getUpperName()
260 << ");";
261 }
262 void writeCtorInitializers(raw_ostream &OS) const {
263 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
264 }
265 void writeCtorParameters(raw_ostream &OS) const {
266 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
267 }
268 void writeDeclarations(raw_ostream &OS) const {
269 OS << "bool is" << getLowerName() << "Expr;\n";
270 OS << "union {\n";
271 OS << "Expr *" << getLowerName() << "Expr;\n";
272 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
273 OS << "};";
274 }
275 void writePCHReadArgs(raw_ostream &OS) const {
276 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
277 }
278 void writePCHReadDecls(raw_ostream &OS) const {
279 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
280 OS << " void *" << getLowerName() << "Ptr;\n";
281 OS << " if (is" << getLowerName() << "Expr)\n";
282 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
283 OS << " else\n";
284 OS << " " << getLowerName()
285 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
286 }
287 void writePCHWrite(raw_ostream &OS) const {
288 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
289 OS << " if (SA->is" << getUpperName() << "Expr())\n";
290 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
291 OS << " else\n";
292 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
293 << "Type(), Record);\n";
294 }
295 };
296
297 class VariadicArgument : public Argument {
298 std::string type;
299
300 public:
301 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
302 : Argument(Arg, Attr), type(T)
303 {}
304
305 std::string getType() const { return type; }
306
307 void writeAccessors(raw_ostream &OS) const {
308 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
309 OS << " " << getLowerName() << "_iterator " << getLowerName()
310 << "_begin() const {\n";
311 OS << " return " << getLowerName() << ";\n";
312 OS << " }\n";
313 OS << " " << getLowerName() << "_iterator " << getLowerName()
314 << "_end() const {\n";
315 OS << " return " << getLowerName() << " + " << getLowerName()
316 << "Size;\n";
317 OS << " }\n";
318 OS << " unsigned " << getLowerName() << "_size() const {\n"
319 << " return " << getLowerName() << "Size;\n;";
320 OS << " }";
321 }
322 void writeCloneArgs(raw_ostream &OS) const {
323 OS << getLowerName() << ", " << getLowerName() << "Size";
324 }
325 void writeCtorBody(raw_ostream &OS) const {
326 // FIXME: memcpy is not safe on non-trivial types.
327 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
328 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
329 }
330 void writeCtorInitializers(raw_ostream &OS) const {
331 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
332 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
333 << getLowerName() << "Size])";
334 }
335 void writeCtorParameters(raw_ostream &OS) const {
336 OS << getType() << " *" << getUpperName() << ", unsigned "
337 << getUpperName() << "Size";
338 }
339 void writeDeclarations(raw_ostream &OS) const {
340 OS << " unsigned " << getLowerName() << "Size;\n";
341 OS << " " << getType() << " *" << getLowerName() << ";";
342 }
343 void writePCHReadDecls(raw_ostream &OS) const {
344 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
345 OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
346 << ";\n";
347 OS << " " << getLowerName() << ".reserve(" << getLowerName()
348 << "Size);\n";
349 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
350
351 std::string read = ReadPCHRecord(type);
352 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
353 }
354 void writePCHReadArgs(raw_ostream &OS) const {
355 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
356 }
357 void writePCHWrite(raw_ostream &OS) const{
358 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
359 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
360 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
361 << getLowerName() << "_end(); i != e; ++i)\n";
362 OS << " " << WritePCHRecord(type, "(*i)");
363 }
364 };
365
366 class EnumArgument : public Argument {
367 std::string type;
368 std::vector values, enums;
369 public:
370 EnumArgument(Record &Arg, StringRef Attr)
371 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
372 values(getValueAsListOfStrings(Arg, "Values")),
373 enums(getValueAsListOfStrings(Arg, "Enums"))
374 {}
375
376 void writeAccessors(raw_ostream &OS) const {
377 OS << " " << type << " get" << getUpperName() << "() const {\n";
378 OS << " return " << getLowerName() << ";\n";
379 OS << " }";
380 }
381 void writeCloneArgs(raw_ostream &OS) const {
382 OS << getLowerName();
383 }
384 void writeCtorInitializers(raw_ostream &OS) const {
385 OS << getLowerName() << "(" << getUpperName() << ")";
386 }
387 void writeCtorParameters(raw_ostream &OS) const {
388 OS << type << " " << getUpperName();
389 }
390 void writeDeclarations(raw_ostream &OS) const {
391 // Calculate the various enum values
392 std::vector uniques(enums);
393 std::sort(uniques.begin(), uniques.end());
394 uniques.erase(std::unique(uniques.begin(), uniques.end()),
395 uniques.end());
396 // FIXME: Emit a proper error
397 assert(!uniques.empty());
398
399 std::vector::iterator i = uniques.begin(),
400 e = uniques.end();
401 // The last one needs to not have a comma.
402 --e;
403
404 OS << "public:\n";
405 OS << " enum " << type << " {\n";
406 for (; i != e; ++i)
407 OS << " " << *i << ",\n";
408 OS << " " << *e << "\n";
409 OS << " };\n";
410 OS << "private:\n";
411 OS << " " << type << " " << getLowerName() << ";";
412 }
413 void writePCHReadDecls(raw_ostream &OS) const {
414 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
415 << "(static_cast<" << getAttrName() << "Attr::" << type
416 << ">(Record[Idx++]));\n";
417 }
418 void writePCHReadArgs(raw_ostream &OS) const {
419 OS << getLowerName();
420 }
421 void writePCHWrite(raw_ostream &OS) const {
422 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
423 }
424 };
425
426 class VersionArgument : public Argument {
427 public:
428 VersionArgument(Record &Arg, StringRef Attr)
429 : Argument(Arg, Attr)
430 {}
431
432 void writeAccessors(raw_ostream &OS) const {
433 OS << " VersionTuple get" << getUpperName() << "() const {\n";
434 OS << " return " << getLowerName() << ";\n";
435 OS << " }\n";
436 OS << " void set" << getUpperName()
437 << "(ASTContext &C, VersionTuple V) {\n";
438 OS << " " << getLowerName() << " = V;\n";
439 OS << " }";
440 }
441 void writeCloneArgs(raw_ostream &OS) const {
442 OS << "get" << getUpperName() << "()";
443 }
444 void writeCtorBody(raw_ostream &OS) const {
445 }
446 void writeCtorInitializers(raw_ostream &OS) const {
447 OS << getLowerName() << "(" << getUpperName() << ")";
448 }
449 void writeCtorParameters(raw_ostream &OS) const {
450 OS << "VersionTuple " << getUpperName();
451 }
452 void writeDeclarations(raw_ostream &OS) const {
453 OS << "VersionTuple " << getLowerName() << ";\n";
454 }
455 void writePCHReadDecls(raw_ostream &OS) const {
456 OS << " VersionTuple " << getLowerName()
457 << "= ReadVersionTuple(Record, Idx);\n";
458 }
459 void writePCHReadArgs(raw_ostream &OS) const {
460 OS << getLowerName();
461 }
462 void writePCHWrite(raw_ostream &OS) const {
463 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
464 }
465 };
466 }
467
468 static Argument *createArgument(Record &Arg, StringRef Attr,
469 Record *Search = 0) {
470 if (!Search)
471 Search = &Arg;
472
473 Argument *Ptr = 0;
474 llvm::StringRef ArgName = Search->getName();
475
476 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
477 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
478 else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
479 "Expr *");
480 else if (ArgName == "FunctionArgument")
481 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
482 else if (ArgName == "IdentifierArgument")
483 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
484 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
485 "bool");
486 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
487 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
488 else if (ArgName == "TypeArgument")
489 Ptr = new SimpleArgument(Arg, Attr, "QualType");
490 else if (ArgName == "UnsignedArgument")
491 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
492 else if (ArgName == "SourceLocArgument")
493 Ptr = new SimpleArgument(Arg, Attr, "SourceLocation");
494 else if (ArgName == "VariadicUnsignedArgument")
495 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
496 else if (ArgName == "VariadicExprArgument")
497 Ptr = new VariadicArgument(Arg, Attr, "Expr *");
498 else if (ArgName == "VersionArgument")
499 Ptr = new VersionArgument(Arg, Attr);
500
501 if (!Ptr) {
502 std::vector Bases = Search->getSuperClasses();
503 for (std::vector::iterator i = Bases.begin(), e = Bases.end();
504 i != e; ++i) {
505 Ptr = createArgument(Arg, Attr, *i);
506 if (Ptr)
507 break;
508 }
509 }
510 return Ptr;
511 }
512
513 void ClangAttrClassEmitter::run(raw_ostream &OS) {
514 OS << "// This file is generated by TableGen. Do not edit.\n\n";
515 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
516 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
517
518 std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
519
520 for (std::vector::iterator i = Attrs.begin(), e = Attrs.end();
521 i != e; ++i) {
522 Record &R = **i;
523 const std::string &SuperName = R.getSuperClasses().back()->getName();
524
525 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
526
527 std::vector ArgRecords = R.getValueAsListOfDefs("Args");
528 std::vector Args;
529 std::vector::iterator ai, ae;
530 Args.reserve(ArgRecords.size());
531
532 for (std::vector::iterator ri = ArgRecords.begin(),
533 re = ArgRecords.end();
534 ri != re; ++ri) {
535 Record &ArgRecord = **ri;
536 Argument *Arg = createArgument(ArgRecord, R.getName());
537 assert(Arg);
538 Args.push_back(Arg);
539
540 Arg->writeDeclarations(OS);
541 OS << "\n\n";
542 }
543
544 ae = Args.end();
545
546 OS << "\n public:\n";
547 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
548
549 for (ai = Args.begin(); ai != ae; ++ai) {
550 OS << " , ";
551 (*ai)->writeCtorParameters(OS);
552 OS << "\n";
553 }
554
555 OS << " )\n";
556 OS << " : " << SuperName << "(attr::" << R.getName() << ", R)\n";
557
558 for (ai = Args.begin(); ai != ae; ++ai) {
559 OS << " , ";
560 (*ai)->writeCtorInitializers(OS);
561 OS << "\n";
562 }
563
564 OS << " {\n";
565
566 for (ai = Args.begin(); ai != ae; ++ai) {
567 (*ai)->writeCtorBody(OS);
568 OS << "\n";
569 }
570 OS << " }\n\n";
571
572 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
573
574 for (ai = Args.begin(); ai != ae; ++ai) {
575 (*ai)->writeAccessors(OS);
576 OS << "\n\n";
577 }
578
579 OS << R.getValueAsCode("AdditionalMembers");
580 OS << "\n\n";
581
582 OS << " static bool classof(const Attr *A) { return A->getKind() == "
583 << "attr::" << R.getName() << "; }\n";
584 OS << " static bool classof(const " << R.getName()
585 << "Attr *) { return true; }\n";
586 OS << "};\n\n";
587 }
588
589 OS << "#endif\n";
590 }
591
592 void ClangAttrImplEmitter::run(raw_ostream &OS) {
593 OS << "// This file is generated by TableGen. Do not edit.\n\n";
594
595 std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
596 std::vector::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
597 std::vector::iterator ai, ae;
598
599 for (; i != e; ++i) {
600 Record &R = **i;
601 std::vector ArgRecords = R.getValueAsListOfDefs("Args");
602 std::vector Args;
603 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
604 Args.push_back(createArgument(**ri, R.getName()));
605
606 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
607 (*ai)->writeAccessorDefinitions(OS);
608
609 OS << R.getName() << "Attr *" << R.getName()
610 << "Attr::clone(ASTContext &C) const {\n";
611 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
612 for (ai = Args.begin(); ai != ae; ++ai) {
613 OS << ", ";
614 (*ai)->writeCloneArgs(OS);
615 }
616 OS << ");\n}\n\n";
617 }
618 }
619
620 static void EmitAttrList(raw_ostream &OS, StringRef Class,
621 const std::vector &AttrList) {
622 std::vector::const_iterator i = AttrList.begin(), e = AttrList.end();
623
624 if (i != e) {
625 // Move the end iterator back to emit the last attribute.
626 for(--e; i != e; ++i)
627 OS << Class << "(" << (*i)->getName() << ")\n";
628
629 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
630 }
631 }
632
633 void ClangAttrListEmitter::run(raw_ostream &OS) {
634 OS << "// This file is generated by TableGen. Do not edit.\n\n";
635
636 OS << "#ifndef LAST_ATTR\n";
637 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
638 OS << "#endif\n\n";
639
640 OS << "#ifndef INHERITABLE_ATTR\n";
641 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
642 OS << "#endif\n\n";
643
644 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
645 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
646 OS << "#endif\n\n";
647
648 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
649 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
650 OS << "#endif\n\n";
651
652 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
653 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
654 " INHERITABLE_PARAM_ATTR(NAME)\n";
655 OS << "#endif\n\n";
656
657 Record *InhClass = Records.getClass("InheritableAttr");
658 Record *InhParamClass = Records.getClass("InheritableParamAttr");
659 std::vector Attrs = Records.getAllDerivedDefinitions("Attr"),
660 NonInhAttrs, InhAttrs, InhParamAttrs;
661 for (std::vector::iterator i = Attrs.begin(), e = Attrs.end();
662 i != e; ++i) {
663 if ((*i)->isSubClassOf(InhParamClass))
664 InhParamAttrs.push_back(*i);
665 else if ((*i)->isSubClassOf(InhClass))
666 InhAttrs.push_back(*i);
667 else
668 NonInhAttrs.push_back(*i);
669 }
670
671 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
672 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
673 EmitAttrList(OS, "ATTR", NonInhAttrs);
674
675 OS << "#undef LAST_ATTR\n";
676 OS << "#undef INHERITABLE_ATTR\n";
677 OS << "#undef LAST_INHERITABLE_ATTR\n";
678 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
679 OS << "#undef ATTR\n";
680 }
681
682 void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
683 OS << "// This file is generated by TableGen. Do not edit.\n\n";
684
685 Record *InhClass = Records.getClass("InheritableAttr");
686 std::vector Attrs = Records.getAllDerivedDefinitions("Attr"),
687 ArgRecords;
688 std::vector::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
689 std::vector Args;
690 std::vector::iterator ri, re;
691
692 OS << " switch (Kind) {\n";
693 OS << " default:\n";
694 OS << " assert(0 && \"Unknown attribute!\");\n";
695 OS << " break;\n";
696 for (; i != e; ++i) {
697 Record &R = **i;
698 OS << " case attr::" << R.getName() << ": {\n";
699 if (R.isSubClassOf(InhClass))
700 OS << " bool isInherited = Record[Idx++];\n";
701 ArgRecords = R.getValueAsListOfDefs("Args");
702 Args.clear();
703 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
704 Argument *A = createArgument(**ai, R.getName());
705 Args.push_back(A);
706 A->writePCHReadDecls(OS);
707 }
708 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
709 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
710 OS << ", ";
711 (*ri)->writePCHReadArgs(OS);
712 }
713 OS << ");\n";
714 if (R.isSubClassOf(InhClass))
715 OS << " cast(New)->setInherited(isInherited);\n";
716 OS << " break;\n";
717 OS << " }\n";
718 }
719 OS << " }\n";
720 }
721
722 void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
723 Record *InhClass = Records.getClass("InheritableAttr");
724 std::vector Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
725 std::vector::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
726
727 OS << " switch (A->getKind()) {\n";
728 OS << " default:\n";
729 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
730 OS << " break;\n";
731 for (; i != e; ++i) {
732 Record &R = **i;
733 OS << " case attr::" << R.getName() << ": {\n";
734 Args = R.getValueAsListOfDefs("Args");
735 if (R.isSubClassOf(InhClass) || !Args.empty())
736 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
737 << "Attr>(A);\n";
738 if (R.isSubClassOf(InhClass))
739 OS << " Record.push_back(SA->isInherited());\n";
740 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
741 createArgument(**ai, R.getName())->writePCHWrite(OS);
742 OS << " break;\n";
743 OS << " }\n";
744 }
745 OS << " }\n";
746 }
747
748 void ClangAttrSpellingListEmitter::run(raw_ostream &OS) {
749 OS << "// This file is generated by TableGen. Do not edit.\n\n";
750
751 std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
752
753 for (std::vector::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
754 Record &Attr = **I;
755
756 std::vector Spellings = getValueAsListOfStrings(Attr, "Spellings");
757
758 for (std::vector::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
759 StringRef Spelling = *I;
760 OS << ".Case(\"" << Spelling << "\", true)\n";
761 }
762 }
763
764 }
765
766 void ClangAttrLateParsedListEmitter::run(raw_ostream &OS) {
767 OS << "// This file is generated by TableGen. Do not edit.\n\n";
768
769 std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
770
771 for (std::vector::iterator I = Attrs.begin(), E = Attrs.end();
772 I != E; ++I) {
773 Record &Attr = **I;
774
775 bool LateParsed = Attr.getValueAsBit("LateParsed");
776
777 if (LateParsed) {
778 std::vector Spellings =
779 getValueAsListOfStrings(Attr, "Spellings");
780
781 for (std::vector::const_iterator I = Spellings.begin(),
782 E = Spellings.end(); I != E; ++I) {
783 OS << ".Case(\"" << (*I) << "\", " << LateParsed << ")\n";
784 }
785 }
786 }
787 }
+0
-114
utils/TableGen/ClangAttrEmitter.h less more
None //===- ClangAttrEmitter.h - Generate Clang attribute handling =-*- C++ -*--===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // These tablegen backends emit Clang attribute processing code
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef CLANGATTR_EMITTER_H
14 #define CLANGATTR_EMITTER_H
15
16 #include "llvm/TableGen/TableGenBackend.h"
17
18 namespace llvm {
19
20 /// ClangAttrClassEmitter - class emits the class defintions for attributes for
21 /// clang.
22 class ClangAttrClassEmitter : public TableGenBackend {
23 RecordKeeper &Records;
24
25 public:
26 explicit ClangAttrClassEmitter(RecordKeeper &R)
27 : Records(R)
28 {}
29
30 void run(raw_ostream &OS);
31 };
32
33 /// ClangAttrImplEmitter - class emits the class method defintions for
34 /// attributes for clang.
35 class ClangAttrImplEmitter : public TableGenBackend {
36 RecordKeeper &Records;
37
38 public:
39 explicit ClangAttrImplEmitter(RecordKeeper &R)
40 : Records(R)
41 {}
42
43 void run(raw_ostream &OS);
44 };
45
46 /// ClangAttrListEmitter - class emits the enumeration list for attributes for
47 /// clang.
48 class ClangAttrListEmitter : public TableGenBackend {
49 RecordKeeper &Records;
50
51 public:
52 explicit ClangAttrListEmitter(RecordKeeper &R)
53 : Records(R)
54 {}
55
56 void run(raw_ostream &OS);
57 };
58
59 /// ClangAttrPCHReadEmitter - class emits the code to read an attribute from
60 /// a clang precompiled header.
61 class ClangAttrPCHReadEmitter : public TableGenBackend {
62 RecordKeeper &Records;
63
64 public:
65 explicit ClangAttrPCHReadEmitter(RecordKeeper &R)
66 : Records(R)
67 {}
68
69 void run(raw_ostream &OS);
70 };
71
72 /// ClangAttrPCHWriteEmitter - class emits the code to read an attribute from
73 /// a clang precompiled header.
74 class ClangAttrPCHWriteEmitter : public TableGenBackend {
75 RecordKeeper &Records;
76
77 public:
78 explicit ClangAttrPCHWriteEmitter(RecordKeeper &R)
79 : Records(R)
80 {}
81
82 void run(raw_ostream &OS);
83 };
84
85 /// ClangAttrSpellingListEmitter - class emits the list of spellings for attributes for
86 /// clang.
87 class ClangAttrSpellingListEmitter : public TableGenBackend {
88 RecordKeeper &Records;
89
90 public:
91 explicit ClangAttrSpellingListEmitter(RecordKeeper &R)
92 : Records(R)
93 {}
94
95 void run(raw_ostream &OS);
96 };
97
98 /// ClangAttrLateParsedListEmitter emits the LateParsed property for attributes
99 /// for clang.
100 class ClangAttrLateParsedListEmitter : public TableGenBackend {
101 RecordKeeper &Records;
102
103 public:
104 explicit ClangAttrLateParsedListEmitter(RecordKeeper &R)
105 : Records(R)
106 {}
107
108 void run(raw_ostream &OS);
109 };
110
111 }
112
113 #endif
+0
-378
utils/TableGen/ClangDiagnosticsEmitter.cpp less more
None //=- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables -*- C++ -*-
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // These tablegen backends emit Clang diagnostics tables.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "ClangDiagnosticsEmitter.h"
14 #include "llvm/TableGen/Record.h"
15 #include "llvm/Support/Debug.h"
16 #include "llvm/Support/Compiler.h"
17 #include "llvm/ADT/DenseSet.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/VectorExtras.h"
22 #include
23 #include
24 #include
25 using namespace llvm;
26
27 //===----------------------------------------------------------------------===//
28 // Diagnostic category computation code.
29 //===----------------------------------------------------------------------===//
30
31 namespace {
32 class DiagGroupParentMap {
33 RecordKeeper &Records;
34 std::map > Mapping;
35 public:
36 DiagGroupParentMap(RecordKeeper &records) : Records(records) {
37 std::vector DiagGroups
38 = Records.getAllDerivedDefinitions("DiagGroup");
39 for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
40 std::vector SubGroups =
41 DiagGroups[i]->getValueAsListOfDefs("SubGroups");
42 for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
43 Mapping[SubGroups[j]].push_back(DiagGroups[i]);
44 }
45 }
46
47 const std::vector &getParents(const Record *Group) {
48 return Mapping[Group];
49 }
50 };
51 } // end anonymous namespace.
52
53
54 static std::string
55 getCategoryFromDiagGroup(const Record *Group,
56 DiagGroupParentMap &DiagGroupParents) {
57 // If the DiagGroup has a category, return it.
58 std::string CatName = Group->getValueAsString("CategoryName");
59 if (!CatName.empty()) return CatName;
60
61 // The diag group may the subgroup of one or more other diagnostic groups,
62 // check these for a category as well.
63 const std::vector &Parents = DiagGroupParents.getParents(Group);
64 for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
65 CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
66 if (!CatName.empty()) return CatName;
67 }
68 return "";
69 }
70
71 /// getDiagnosticCategory - Return the category that the specified diagnostic
72 /// lives in.
73 static std::string getDiagnosticCategory(const Record *R,
74 DiagGroupParentMap &DiagGroupParents) {
75 // If the diagnostic is in a group, and that group has a category, use it.
76 if (DefInit *Group = dynamic_cast(R->getValueInit("Group"))) {
77 // Check the diagnostic's diag group for a category.
78 std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
79 DiagGroupParents);
80 if (!CatName.empty()) return CatName;
81 }
82
83 // If the diagnostic itself has a category, get it.
84 return R->getValueAsString("CategoryName");
85 }
86
87 namespace {
88 class DiagCategoryIDMap {
89 RecordKeeper &Records;
90 StringMap CategoryIDs;
91 std::vector CategoryStrings;
92 public:
93 DiagCategoryIDMap(RecordKeeper &records) : Records(records) {
94 DiagGroupParentMap ParentInfo(Records);
95
96 // The zero'th category is "".
97 CategoryStrings.push_back("");
98 CategoryIDs[""] = 0;
99
100 std::vector Diags =
101 Records.getAllDerivedDefinitions("Diagnostic");
102 for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
103 std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
104 if (Category.empty()) continue; // Skip diags with no category.
105
106 unsigned &ID = CategoryIDs[Category];
107 if (ID != 0) continue; // Already seen.
108
109 ID = CategoryStrings.size();
110 CategoryStrings.push_back(Category);
111 }
112 }
113
114 unsigned getID(StringRef CategoryString) {
115 return CategoryIDs[CategoryString];
116 }
117
118 typedef std::vector::iterator iterator;
119 iterator begin() { return CategoryStrings.begin(); }
120 iterator end() { return CategoryStrings.end(); }
121 };
122 } // end anonymous namespace.
123
124
125 //===----------------------------------------------------------------------===//
126 // Warning Tables (.inc file) generation.
127 //===----------------------------------------------------------------------===//
128
129 void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
130 // Write the #if guard
131 if (!Component.empty()) {
132 std::string ComponentName = UppercaseString(Component);
133 OS << "#ifdef " << ComponentName << "START\n";
134 OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
135 << ",\n";
136 OS << "#undef " << ComponentName << "START\n";
137 OS << "#endif\n\n";
138 }
139
140 const std::vector &Diags =
141 Records.getAllDerivedDefinitions("Diagnostic");
142
143 DiagCategoryIDMap CategoryIDs(Records);
144 DiagGroupParentMap DGParentMap(Records);
145
146 for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
147 const Record &R = *Diags[i];
148 // Filter by component.
149 if (!Component.empty() && Component != R.getValueAsString("Component"))
150 continue;
151
152 OS << "DIAG(" << R.getName() << ", ";
153 OS << R.getValueAsDef("Class")->getName();
154 OS << ", diag::" << R.getValueAsDef("DefaultMapping")->getName();
155
156 // Description string.
157 OS << ", \"";
158 OS.write_escaped(R.getValueAsString("Text")) << '"';
159
160 // Warning associated with the diagnostic.
161 if (DefInit *DI = dynamic_cast(R.getValueInit("Group"))) {
162 OS << ", \"";
163 OS.write_escaped(DI->getDef()->getValueAsString("GroupName")) << '"';
164 } else {
165 OS << ", \"\"";
166 }
167
168 // SFINAE bit
169 if (R.getValueAsBit("SFINAE"))
170 OS << ", true";
171 else
172 OS << ", false";
173
174 // Access control bit
175 if (R.getValueAsBit("AccessControl"))
176 OS << ", true";
177 else
178 OS << ", false";
179
180 // FIXME: This condition is just to avoid temporary revlock, it can be
181 // removed.
182 if (R.getValue("WarningNoWerror")) {
183 // Default warning has no Werror bit.
184 if (R.getValueAsBit("WarningNoWerror"))
185 OS << ", true";
186 else
187 OS << ", false";
188
189 // Default warning show in system header bit.
190 if (R.getValueAsBit("WarningShowInSystemHeader"))
191 OS << ", true";
192 else
193 OS << ", false";
194 }
195
196 // Category number.
197 OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
198
199 // Brief
200 OS << ", \"";
201 OS.write_escaped(R.getValueAsString("Brief")) << '"';
202
203 // Explanation
204 OS << ", \"";
205 OS.write_escaped(R.getValueAsString("Explanation")) << '"';
206 OS << ")\n";
207 }
208 }
209
210 //===----------------------------------------------------------------------===//
211 // Warning Group Tables generation
212 //===----------------------------------------------------------------------===//
213
214 static std::string getDiagCategoryEnum(llvm::StringRef name) {
215 if (name.empty())
216 return "DiagCat_None";
217 llvm::SmallString<256> enumName = llvm::StringRef("DiagCat_");
218 for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
219 enumName += isalnum(*I) ? *I : '_';
220 return enumName.str();
221 }
222
223 namespace {
224 struct GroupInfo {
225 std::vector DiagsInGroup;
226 std::vector SubGroups;
227 unsigned IDNo;
228 };
229 } // end anonymous namespace.
230
231 void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
232 // Compute a mapping from a DiagGroup to all of its parents.
233 DiagGroupParentMap DGParentMap(Records);
234
235 // Invert the 1-[0/1] mapping of diags to group into a one to many mapping of
236 // groups to diags in the group.
237 std::map DiagsInGroup;
238
239 std::vector Diags =
240 Records.getAllDerivedDefinitions("Diagnostic");
241 for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
242 const Record *R = Diags[i];
243 DefInit *DI = dynamic_cast(R->getValueInit("Group"));
244 if (DI == 0) continue;
245 std::string GroupName = DI->getDef()->getValueAsString("GroupName");
246 DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
247 }
248
249 // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
250 // groups (these are warnings that GCC supports that clang never produces).
251 std::vector DiagGroups
252 = Records.getAllDerivedDefinitions("DiagGroup");
253 for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
254 Record *Group = DiagGroups[i];
255 GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
256
257 std::vector SubGroups = Group->getValueAsListOfDefs("SubGroups");
258 for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
259 GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
260 }
261
262 // Assign unique ID numbers to the groups.
263 unsigned IDNo = 0;
264 for (std::map::iterator
265 I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
266 I->second.IDNo = IDNo;
267
268 // Walk through the groups emitting an array for each diagnostic of the diags
269 // that are mapped to.
270 OS << "\n#ifdef GET_DIAG_ARRAYS\n";
271 unsigned MaxLen = 0;
272 for (std::map::iterator
273 I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
274 MaxLen = std::max(MaxLen, (unsigned)I->first.size());
275
276 std::vector &V = I->second.DiagsInGroup;
277 if (!V.empty()) {
278 OS << "static const short DiagArray" << I->second.IDNo << "[] = { ";
279 for (unsigned i = 0, e = V.size(); i != e; ++i)
280 OS << "diag::" << V[i]->getName() << ", ";
281 OS << "-1 };\n";
282 }
283
284 const std::vector &SubGroups = I->second.SubGroups;
285 if (!SubGroups.empty()) {
286 OS << "static const short DiagSubGroup" << I->second.IDNo << "[] = { ";
287 for (unsigned i = 0, e = SubGroups.size(); i != e; ++i) {
288 std::map::iterator RI =
289 DiagsInGroup.find(SubGroups[i]);
290 assert(RI != DiagsInGroup.end() && "Referenced without existing?");
291 OS << RI->second.IDNo << ", ";
292 }
293 OS << "-1 };\n";
294 }
295 }
296 OS << "#endif // GET_DIAG_ARRAYS\n\n";
297
298 // Emit the table now.
299 OS << "\n#ifdef GET_DIAG_TABLE\n";
300 for (std::map::iterator
301 I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
302 // Group option string.
303 OS << " { ";
304 OS << I->first.size() << ", ";
305 OS << "\"";
306 OS.write_escaped(I->first) << "\","
307 << std::string(MaxLen-I->first.size()+1, ' ');
308
309 // Diagnostics in the group.
310 if (I->second.DiagsInGroup.empty())
311 OS << "0, ";
312 else
313 OS << "DiagArray" << I->second.IDNo << ", ";
314
315 // Subgroups.
316 if (I->second.SubGroups.empty())
317 OS << 0;
318 else
319 OS << "DiagSubGroup" << I->second.IDNo;
320 OS << " },\n";
321 }
322 OS << "#endif // GET_DIAG_TABLE\n\n";
323
324 // Emit the category table next.
325 DiagCategoryIDMap CategoriesByID(Records);
326 OS << "\n#ifdef GET_CATEGORY_TABLE\n";
327 for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(),
328 E = CategoriesByID.end(); I != E; ++I)
329 OS << "CATEGORY(\"" << *I << "\", " << getDiagCategoryEnum(*I) << ")\n";
330 OS << "#endif // GET_CATEGORY_TABLE\n\n";
331 }
332
333 //===----------------------------------------------------------------------===//
334 // Diagnostic name index generation
335 //===----------------------------------------------------------------------===//
336
337 namespace {
338 struct RecordIndexElement
339 {
340 RecordIndexElement() {}
341 explicit RecordIndexElement(Record const &R):
342 Name(R.getName()) {}
343
344 std::string Name;
345 };
346
347 struct RecordIndexElementSorter :
348 public std::binary_function {
349
350 bool operator()(RecordIndexElement const &Lhs,
351 RecordIndexElement const &Rhs) const {
352 return Lhs.Name < Rhs.Name;
353 }
354
355 };
356
357 } // end anonymous namespace.
358
359 void ClangDiagsIndexNameEmitter::run(raw_ostream &OS) {
360 const std::vector &Diags =
361 Records.getAllDerivedDefinitions("Diagnostic");
362
363 std::vector Index;
364 Index.reserve(Diags.size());
365 for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
366 const Record &R = *(Diags[i]);
367 Index.push_back(RecordIndexElement(R));
368 }
369
370 std::sort(Index.begin(), Index.end(), RecordIndexElementSorter());
371
372 for (unsigned i = 0, e = Index.size(); i != e; ++i) {
373 const RecordIndexElement &R = Index[i];
374
375 OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
376 }
377 }
+0
-54
utils/TableGen/ClangDiagnosticsEmitter.h less more
None //===- ClangDiagnosticsEmitter.h - Generate Clang diagnostics tables -*- C++ -*-
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // These tablegen backends emit Clang diagnostics tables.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef CLANGDIAGS_EMITTER_H
14 #define CLANGDIAGS_EMITTER_H
15
16 #include "llvm/TableGen/TableGenBackend.h"
17
18 namespace llvm {
19
20 /// ClangDiagsDefsEmitter - The top-level class emits .def files containing
21 /// declarations of Clang diagnostics.
22 ///
23 class ClangDiagsDefsEmitter : public TableGenBackend {
24 RecordKeeper &Records;
25 const std::string& Component;
26 public:
27 explicit ClangDiagsDefsEmitter(RecordKeeper &R, const std::string& component)
28 : Records(R), Component(component) {}
29
30 // run - Output the .def file contents
31 void run(raw_ostream &OS);
32 };
33
34 class ClangDiagGroupsEmitter : public TableGenBackend {
35 RecordKeeper &Records;
36 public:
37 explicit ClangDiagGroupsEmitter(RecordKeeper &R) : Records(R) {}
38
39 void run(raw_ostream &OS);
40 };
41
42 class ClangDiagsIndexNameEmitter : public TableGenBackend {
43 RecordKeeper &Records;
44 public:
45 explicit ClangDiagsIndexNameEmitter(RecordKeeper &R) : Records(R) {}
46
47 void run(raw_ostream &OS);
48 };
49
50
51 } // End llvm namespace
52
53 #endif
+0
-319
utils/TableGen/ClangSACheckersEmitter.cpp less more
None //=- ClangSACheckersEmitter.cpp - Generate Clang SA checkers tables -*- C++ -*-
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend emits Clang Static Analyzer checkers tables.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "ClangSACheckersEmitter.h"
14 #include "llvm/TableGen/Record.h"
15 #include "llvm/ADT/DenseSet.h"
16 #include
17 #include
18 using namespace llvm;
19
20 //===----------------------------------------------------------------------===//
21 // Static Analyzer Checkers Tables generation
22 //===----------------------------------------------------------------------===//
23
24 /// \brief True if it is specified hidden or a parent package is specified
25 /// as hidden, otherwise false.
26 static bool isHidden(const Record &R) {
27 if (R.getValueAsBit("Hidden"))
28 return true;
29 // Not declared as hidden, check the parent package if it is hidden.
30 if (DefInit *DI = dynamic_cast(R.getValueInit("ParentPackage")))
31 return isHidden(*DI->getDef());
32
33 return false;
34 }
35
36 static bool isCheckerNamed(const Record *R) {
37 return !R->getValueAsString("CheckerName").empty();
38 }
39
40 static std::string getPackageFullName(const Record *R);
41
42 static std::string getParentPackageFullName(const Record *R) {
43 std::string name;
44 if (DefInit *DI = dynamic_cast(R->getValueInit("ParentPackage")))
45 name = getPackageFullName(DI->getDef());
46 return name;
47 }
48
49 static std::string getPackageFullName(const Record *R) {
50 std::string name = getParentPackageFullName(R);
51 if (!name.empty()) name += ".";
52 return name + R->getValueAsString("PackageName");
53 }
54
55 static std::string getCheckerFullName(const Record *R) {
56 std::string name = getParentPackageFullName(R);
57 if (isCheckerNamed(R)) {
58 if (!name.empty()) name += ".";
59 name += R->getValueAsString("CheckerName");
60 }
61 return name;
62 }
63
64 static std::string getStringValue(const Record &R, StringRef field) {
65 if (StringInit *
66 SI = dynamic_cast(R.getValueInit(field)))
67 return SI->getValue();
68 return std::string();
69 }
70
71 namespace {
72 struct GroupInfo {
73 llvm::DenseSet Checkers;
74 llvm::DenseSet SubGroups;
75 bool Hidden;
76 unsigned Index;
77
78 GroupInfo() : Hidden(false) { }
79 };
80 }
81
82 static void addPackageToCheckerGroup(const Record *package, const Record *group,
83 llvm::DenseMap &recordGroupMap) {
84 llvm::DenseSet &checkers = recordGroupMap[package]->Checkers;
85 for (llvm::DenseSet::iterator
86 I = checkers.begin(), E = checkers.end(); I != E; ++I)
87 recordGroupMap[group]->Checkers.insert(*I);
88
89 llvm::DenseSet &subGroups = recordGroupMap[package]->SubGroups;
90 for (llvm::DenseSet::iterator
91 I = subGroups.begin(), E = subGroups.end(); I != E; ++I)
92 addPackageToCheckerGroup(*I, group, recordGroupMap);
93 }
94
95 void ClangSACheckersEmitter::run(raw_ostream &OS) {
96 std::vector checkers = Records.getAllDerivedDefinitions("Checker");
97 llvm::DenseMap checkerRecIndexMap;
98 for (unsigned i = 0, e = checkers.size(); i != e; ++i)
99 checkerRecIndexMap[checkers[i]] = i;
100
101 // Invert the mapping of checkers to package/group into a one to many
102 // mapping of packages/groups to checkers.
103 std::map groupInfoByName;
104 llvm::DenseMap recordGroupMap;
105
106 std::vector packages = Records.getAllDerivedDefinitions("Package");
107 for (unsigned i = 0, e = packages.size(); i != e; ++i) {
108 Record *R = packages[i];
109 std::string fullName = getPackageFullName(R);
110 if (!fullName.empty()) {
111 GroupInfo &info = groupInfoByName[fullName];
112 info.Hidden = isHidden(*R);
113 recordGroupMap[R] = &info;
114 }
115 }
116
117 std::vector
118 checkerGroups = Records.getAllDerivedDefinitions("CheckerGroup");
119 for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i) {
120 Record *R = checkerGroups[i];
121 std::string name = R->getValueAsString("GroupName");
122 if (!name.empty()) {
123 GroupInfo &info = groupInfoByName[name];
124 recordGroupMap[R] = &info;
125 }
126 }
127
128 for (unsigned i = 0, e = checkers.size(); i != e; ++i) {
129 Record *R = checkers[i];
130 Record *package = 0;
131 if (DefInit *
132 DI = dynamic_cast(R->getValueInit("ParentPackage")))
133 package = DI->getDef();
134 if (!isCheckerNamed(R) && !package)
135 throw "Checker '" + R->getName() + "' is neither named, nor in a package!";
136
137 if (isCheckerNamed(R)) {
138 // Create a pseudo-group to hold this checker.
139 std::string fullName = getCheckerFullName(R);
140 GroupInfo &info = groupInfoByName[fullName];
141 info.Hidden = R->getValueAsBit("Hidden");
142 recordGroupMap[R] = &info;
143 info.Checkers.insert(R);
144 } else {
145 recordGroupMap[package]->Checkers.insert(R);
146 }
147
148 Record *currR = isCheckerNamed(R) ? R : package;
149 // Insert the checker and its parent packages into the subgroups set of
150 // the corresponding parent package.
151 while (DefInit *DI
152 = dynamic_cast(currR->getValueInit("ParentPackage"))) {
153 Record *parentPackage = DI->getDef();
154 recordGroupMap[parentPackage]->SubGroups.insert(currR);
155 currR = parentPackage;
156 }
157 // Insert the checker into the set of its group.
158 if (DefInit *DI = dynamic_cast(R->getValueInit("Group")))
159 recordGroupMap[DI->getDef()]->Checkers.insert(R);
160 }
161
162 // If a package is in group, add all its checkers and its sub-packages
163 // checkers into the group.
164 for (unsigned i = 0, e = packages.size(); i != e; ++i)
165 if (DefInit *DI = dynamic_cast(packages[i]->getValueInit("Group")))
166 addPackageToCheckerGroup(packages[i], DI->getDef(), recordGroupMap);
167
168 typedef std::map SortedRecords;
169 typedef llvm::DenseMap RecToSortIndex;
170
171 SortedRecords sortedGroups;
172 RecToSortIndex groupToSortIndex;
173 OS << "\n#ifdef GET_GROUPS\n";
174 {
175 for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i)
176 sortedGroups[checkerGroups[i]->getValueAsString("GroupName")]
177 = checkerGroups[i];
178
179 unsigned sortIndex = 0;
180 for (SortedRecords::iterator
181 I = sortedGroups.begin(), E = sortedGroups.end(); I != E; ++I) {
182 const Record *R = I->second;
183
184 OS << "GROUP(" << "\"";
185 OS.write_escaped(R->getValueAsString("GroupName")) << "\"";
186 OS << ")\n";
187
188 groupToSortIndex[R] = sortIndex++;
189 }
190 }
191 OS << "#endif // GET_GROUPS\n\n";
192
193 OS << "\n#ifdef GET_PACKAGES\n";
194 {
195 SortedRecords sortedPackages;
196 for (unsigned i = 0, e = packages.size(); i != e; ++i)
197 sortedPackages[getPackageFullName(packages[i])] = packages[i];
198
199 for (SortedRecords::iterator
200 I = sortedPackages.begin(), E = sortedPackages.end(); I != E; ++I) {
201 const Record &R = *I->second;
202
203 OS << "PACKAGE(" << "\"";
204 OS.write_escaped(getPackageFullName(&R)) << "\", ";
205 // Group index
206 if (DefInit *DI = dynamic_cast(R.getValueInit("Group")))
207 OS << groupToSortIndex[DI->getDef()] << ", ";
208 else
209 OS << "-1, ";
210 // Hidden bit
211 if (isHidden(R))
212 OS << "true";
213 else
214 OS << "false";
215 OS << ")\n";
216 }
217 }
218 OS << "#endif // GET_PACKAGES\n\n";
219
220 OS << "\n#ifdef GET_CHECKERS\n";
221 for (unsigned i = 0, e = checkers.size(); i != e; ++i) {
222 const Record &R = *checkers[i];
223
224 OS << "CHECKER(" << "\"";
225 std::string name;
226 if (isCheckerNamed(&R))
227 name = getCheckerFullName(&R);
228 OS.write_escaped(name) << "\", ";
229 OS << R.getName() << ", ";
230 OS << getStringValue(R, "DescFile") << ", ";
231 OS << "\"";
232 OS.write_escaped(getStringValue(R, "HelpText")) << "\", ";
233 // Group index
234 if (DefInit *DI = dynamic_cast(R.getValueInit("Group")))
235 OS << groupToSortIndex[DI->getDef()] << ", ";
236 else
237 OS << "-1, ";
238 // Hidden bit
239 if (isHidden(R))
240 OS << "true";
241 else
242 OS << "false";
243 OS << ")\n";
244 }
245 OS << "#endif // GET_CHECKERS\n\n";
246
247 unsigned index = 0;
248 for (std::map::iterator
249 I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I)
250 I->second.Index = index++;
251
252 // Walk through the packages/groups/checkers emitting an array for each
253 // set of checkers and an array for each set of subpackages.
254
255 OS << "\n#ifdef GET_MEMBER_ARRAYS\n";
256 unsigned maxLen = 0;
257 for (std::map::iterator
258 I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) {
259 maxLen = std::max(maxLen, (unsigned)I->first.size());
260
261 llvm::DenseSet &checkers = I->second.Checkers;
262 if (!checkers.empty()) {
263 OS << "static const short CheckerArray" << I->second.Index << "[] = { ";
264 // Make the output order deterministic.
265 std::map sorted;
266 for (llvm::DenseSet::iterator
267 I = checkers.begin(), E = checkers.end(); I != E; ++I)
268 sorted[(*I)->getID()] = *I;
269
270 for (std::map::iterator
271 I = sorted.begin(), E = sorted.end(); I != E; ++I)
272 OS << checkerRecIndexMap[I->second] << ", ";
273 OS << "-1 };\n";
274 }
275
276 llvm::DenseSet &subGroups = I->second.SubGroups;
277 if (!subGroups.empty()) {
278 OS << "static const short SubPackageArray" << I->second.Index << "[] = { ";
279 // Make the output order deterministic.
280 std::map sorted;
281 for (llvm::DenseSet::iterator
282 I = subGroups.begin(), E = subGroups.end(); I != E; ++I)
283 sorted[(*I)->getID()] = *I;
284
285 for (std::map::iterator
286 I = sorted.begin(), E = sorted.end(); I != E; ++I) {
287 OS << recordGroupMap[I->second]->Index << ", ";
288 }
289 OS << "-1 };\n";
290 }
291 }
292 OS << "#endif // GET_MEMBER_ARRAYS\n\n";
293
294 OS << "\n#ifdef GET_CHECKNAME_TABLE\n";
295 for (std::map::iterator
296 I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) {
297 // Group option string.
298 OS << " { \"";
299 OS.write_escaped(I->first) << "\","
300 << std::string(maxLen-I->first.size()+1, ' ');
301
302 if (I->second.Checkers.empty())
303 OS << "0, ";
304 else
305 OS << "CheckerArray" << I->second.Index << ", ";
306
307 // Subgroups.
308 if (I->second.SubGroups.empty())
309 OS << "0, ";
310 else
311 OS << "SubPackageArray" << I->second.Index << ", ";
312
313 OS << (I->second.Hidden ? "true" : "false");
314
315 OS << " },\n";
316 }
317 OS << "#endif // GET_CHECKNAME_TABLE\n\n";
318 }
+0
-31
utils/TableGen/ClangSACheckersEmitter.h less more
None //===- ClangSACheckersEmitter.h - Generate Clang SA checkers tables -*- C++ -*-
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend emits Clang Static Analyzer checkers tables.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef CLANGSACHECKERS_EMITTER_H
14 #define CLANGSACHECKERS_EMITTER_H
15
16 #include "llvm/TableGen/TableGenBackend.h"
17
18 namespace llvm {
19
20 class ClangSACheckersEmitter : public TableGenBackend {
21 RecordKeeper &Records;
22 public:
23 explicit ClangSACheckersEmitter(RecordKeeper &R) : Records(R) {}
24
25 void run(raw_ostream &OS);
26 };
27
28 } // End llvm namespace
29
30 #endif
+0
-1551
utils/TableGen/NeonEmitter.cpp less more
None //===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend is responsible for emitting arm_neon.h, which includes
10 // a declaration and definition of each function specified by the ARM NEON
11 // compiler interface. See ARM document DUI0348B.
12 //
13 // Each NEON instruction is implemented in terms of 1 or more functions which
14 // are suffixed with the element type of the input vectors. Functions may be
15 // implemented in terms of generic vector operations such as +, *, -, etc. or
16 // by calling a __builtin_-prefixed function which will be handled by clang's
17 // CodeGen library.
18 //
19 // Additional validation code can be generated by this file when runHeader() is
20 // called, rather than the normal run() entry point. A complete set of tests
21 // for Neon intrinsics can be generated by calling the runTests() entry point.
22 //
23 //===----------------------------------------------------------------------===//
24
25 #include "NeonEmitter.h"
26 #include "llvm/TableGen/Error.h"
27 #include "llvm/ADT/SmallString.h"
28 #include "llvm/ADT/SmallVector.h"
29 #include "llvm/ADT/StringExtras.h"
30 #include
31
32 using namespace llvm;
33
34 /// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
35 /// which each StringRef representing a single type declared in the string.
36 /// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
37 /// 2xfloat and 4xfloat respectively.
38 static void ParseTypes(Record *r, std::string &s,
39 SmallVectorImpl &TV) {
40 const char *data = s.data();
41 int len = 0;
42
43 for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
44 if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
45 continue;
46
47 switch (data[len]) {
48 case 'c':
49 case 's':
50 case 'i':
51 case 'l':
52 case 'h':
53 case 'f':
54 break;
55 default:
56 throw TGError(r->getLoc(),
57 "Unexpected letter: " + std::string(data + len, 1));
58 break;
59 }
60 TV.push_back(StringRef(data, len + 1));
61 data += len + 1;
62 len = -1;
63 }
64 }
65
66 /// Widen - Convert a type code into the next wider type. char -> short,
67 /// short -> int, etc.
68 static char Widen(const char t) {
69 switch (t) {
70 case 'c':
71 return 's';
72 case 's':
73 return 'i';
74 case 'i':
75 return 'l';
76 case 'h':
77 return 'f';
78 default: throw "unhandled type in widen!";
79 }
80 return '\0';
81 }
82
83 /// Narrow - Convert a type code into the next smaller type. short -> char,
84 /// float -> half float, etc.
85 static char Narrow(const char t) {
86 switch (t) {
87 case 's':
88 return 'c';
89 case 'i':
90 return 's';
91 case 'l':
92 return 'i';
93 case 'f':
94 return 'h';
95 default: throw "unhandled type in narrow!";
96 }
97 return '\0';
98 }
99
100 /// For a particular StringRef, return the base type code, and whether it has
101 /// the quad-vector, polynomial, or unsigned modifiers set.
102 static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
103 unsigned off = 0;
104
105 // remember quad.
106 if (ty[off] == 'Q') {
107 quad = true;
108 ++off;
109 }
110
111 // remember poly.
112 if (ty[off] == 'P') {
113 poly = true;
114 ++off;
115 }
116
117 // remember unsigned.
118 if (ty[off] == 'U') {
119 usgn = true;
120 ++off;
121 }
122
123 // base type to get the type string for.
124 return ty[off];
125 }
126
127 /// ModType - Transform a type code and its modifiers based on a mod code. The
128 /// mod code definitions may be found at the top of arm_neon.td.
129 static char ModType(const char mod, char type, bool &quad, bool &poly,
130 bool &usgn, bool &scal, bool &cnst, bool &pntr) {
131 switch (mod) {
132 case 't':
133 if (poly) {
134 poly = false;
135 usgn = true;
136 }
137 break;
138 case 'u':
139 usgn = true;
140 poly = false;
141 if (type == 'f')
142 type = 'i';
143 break;
144 case 'x':
145 usgn = false;
146 poly = false;
147 if (type == 'f')
148 type = 'i';
149 break;
150 case 'f':
151 if (type == 'h')
152 quad = true;
153 type = 'f';
154 usgn = false;
155 break;
156 case 'g':
157 quad = false;
158 break;
159 case 'w':
160 type = Widen(type);
161 quad = true;
162 break;
163 case 'n':
164 type = Widen(type);
165 break;
166 case 'i':
167 type = 'i';
168 scal = true;
169 break;
170 case 'l':
171 type = 'l';
172 scal = true;
173 usgn = true;
174 break;
175 case 's':
176 case 'a':
177 scal = true;
178 break;
179 case 'k':
180 quad = true;
181 break;
182 case 'c':
183 cnst = true;
184 case 'p':
185 pntr = true;
186 scal = true;
187 break;
188 case 'h':
189 type = Narrow(type);
190 if (type == 'h')
191 quad = false;
192 break;
193 case 'e':
194 type = Narrow(type);
195 usgn = true;
196 break;
197 default:
198 break;
199 }
200 return type;
201 }
202
203 /// TypeString - for a modifier and type, generate the name of the typedef for
204 /// that type. QUc -> uint8x8_t.
205 static std::string TypeString(const char mod, StringRef typestr) {
206 bool quad = false;
207 bool poly = false;
208 bool usgn = false;
209 bool scal = false;
210 bool cnst = false;
211 bool pntr = false;
212
213 if (mod == 'v')
214 return "void";
215 if (mod == 'i')
216 return "int";
217
218 // base type to get the type string for.
219 char type = ClassifyType(typestr, quad, poly, usgn);
220
221 // Based on the modifying character, change the type and width if necessary.
222 type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
223
224 SmallString<128> s;
225
226 if (usgn)
227 s.push_back('u');
228
229 switch (type) {
230 case 'c':
231 s += poly ? "poly8" : "int8";
232 if (scal)
233 break;
234 s += quad ? "x16" : "x8";
235 break;
236 case 's':
237 s += poly ? "poly16" : "int16";
238 if (scal)
239 break;
240 s += quad ? "x8" : "x4";
241 break;
242 case 'i':
243 s += "int32";
244 if (scal)
245 break;
246 s += quad ? "x4" : "x2";
247 break;
248 case 'l':
249 s += "int64";
250 if (scal)
251 break;
252 s += quad ? "x2" : "x1";
253 break;
254 case 'h':
255 s += "float16";
256 if (scal)
257 break;
258 s += quad ? "x8" : "x4";
259 break;
260 case 'f':
261 s += "float32";
262 if (scal)
263 break;
264 s += quad ? "x4" : "x2";
265 break;
266 default:
267 throw "unhandled type!";
268 break;
269 }
270
271 if (mod == '2')
272 s += "x2";
273 if (mod == '3')
274 s += "x3";
275 if (mod == '4')
276 s += "x4";
277
278 // Append _t, finishing the type string typedef type.
279 s += "_t";
280
281 if (cnst)
282 s += " const";
283
284 if (pntr)
285 s += " *";
286
287 return s.str();
288 }
289
290 /// BuiltinTypeString - for a modifier and type, generate the clang
291 /// BuiltinsARM.def prototype code for the function. See the top of clang's
292 /// Builtins.def for a description of the type strings.
293 static std::string BuiltinTypeString(const char mod, StringRef typestr,
294 ClassKind ck, bool ret) {
295 bool quad = false;
296 bool poly = false;
297 bool usgn = false;
298 bool scal = false;
299 bool cnst = false;
300 bool pntr = false;
301
302 if (mod == 'v')
303 return "v"; // void
304 if (mod == 'i')
305 return "i"; // int
306
307 // base type to get the type string for.
308 char type = ClassifyType(typestr, quad, poly, usgn);
309
310 // Based on the modifying character, change the type and width if necessary.
311 type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
312
313 // All pointers are void* pointers. Change type to 'v' now.
314 if (pntr) {
315 usgn = false;
316 poly = false;
317 type = 'v';
318 }
319 // Treat half-float ('h') types as unsigned short ('s') types.
320 if (type == 'h') {
321 type = 's';
322 usgn = true;
323 }
324 usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
325
326 if (scal) {
327 SmallString<128> s;
328
329 if (usgn)
330 s.push_back('U');
331 else if (type == 'c')
332 s.push_back('S'); // make chars explicitly signed
333
334 if (type == 'l') // 64-bit long
335 s += "LLi";
336 else
337 s.push_back(type);
338
339 if (cnst)
340 s.push_back('C');
341 if (pntr)
342 s.push_back('*');
343 return s.str();
344 }
345
346 // Since the return value must be one type, return a vector type of the
347 // appropriate width which we will bitcast. An exception is made for
348 // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
349 // fashion, storing them to a pointer arg.
350 if (ret) {
351 if (mod >= '2' && mod <= '4')
352 return "vv*"; // void result with void* first argument
353 if (mod == 'f' || (ck != ClassB && type == 'f'))
354 return quad ? "V4f" : "V2f";
355 if (ck != ClassB && type == 's')
356 return quad ? "V8s" : "V4s";
357 if (ck != ClassB && type == 'i')
358 return quad ? "V4i" : "V2i";
359 if (ck != ClassB && type == 'l')
360 return quad ? "V2LLi" : "V1LLi";
361
362 return quad ? "V16Sc" : "V8Sc";
363 }
364
365 // Non-return array types are passed as individual vectors.
366 if (mod == '2')
367 return quad ? "V16ScV16Sc" : "V8ScV8Sc";
368 if (mod == '3')
369 return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc";
370 if (mod == '4')
371 return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc";
372
373 if (mod == 'f' || (ck != ClassB && type == 'f'))
374 return quad ? "V4f" : "V2f";
375 if (ck != ClassB && type == 's')
376 return quad ? "V8s" : "V4s";
377 if (ck != ClassB && type == 'i')
378 return quad ? "V4i" : "V2i";
379 if (ck != ClassB && type == 'l')
380 return quad ? "V2LLi" : "V1LLi";
381
382 return quad ? "V16Sc" : "V8Sc";
383 }
384
385 /// MangleName - Append a type or width suffix to a base neon function name,
386 /// and insert a 'q' in the appropriate location if the operation works on
387 /// 128b rather than 64b. E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
388 static std::string MangleName(const std::string &name, StringRef typestr,
389 ClassKind ck) {
390 if (name == "vcvt_f32_f16")
391 return name;
392
393 bool quad = false;
394 bool poly = false;
395 bool usgn = false;
396 char type = ClassifyType(typestr, quad, poly, usgn);
397
398 std::string s = name;
399
400 switch (type) {
401 case 'c':
402 switch (ck) {
403 case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
404 case ClassI: s += "_i8"; break;
405 case ClassW: s += "_8"; break;
406 default: break;
407 }
408 break;
409 case 's':
410 switch (ck) {
411 case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
412 case ClassI: s += "_i16"; break;
413 case ClassW: s += "_16"; break;
414 default: break;
415 }
416 break;
417 case 'i':
418 switch (ck) {
419 case ClassS: s += usgn ? "_u32" : "_s32"; break;
420 case ClassI: s += "_i32"; break;
421 case ClassW: s += "_32"; break;
422 default: break;
423 }
424 break;
425 case 'l':
426 switch (ck) {
427 case ClassS: s += usgn ? "_u64" : "_s64"; break;
428 case ClassI: s += "_i64"; break;
429 case ClassW: s += "_64"; break;
430 default: break;
431 }
432 break;
433 case 'h':
434 switch (ck) {
435 case ClassS:
436 case ClassI: s += "_f16"; break;
437 case ClassW: s += "_16"; break;
438 default: break;
439 }
440 break;
441 case 'f':
442 switch (ck) {
443 case ClassS:
444 case ClassI: s += "_f32"; break;
445 case ClassW: s += "_32"; break;
446 default: break;
447 }
448 break;
449 default:
450 throw "unhandled type!";
451 break;
452 }
453 if (ck == ClassB)
454 s += "_v";
455
456 // Insert a 'q' before the first '_' character so that it ends up before
457 // _lane or _n on vector-scalar operations.
458 if (quad) {
459 size_t pos = s.find('_');
460 s = s.insert(pos, "q");
461 }
462 return s;
463 }
464
465 /// UseMacro - Examine the prototype string to determine if the intrinsic
466 /// should be defined as a preprocessor macro instead of an inline function.
467 static bool UseMacro(const std::string &proto) {
468 // If this builtin takes an immediate argument, we need to #define it rather
469 // than use a standard declaration, so that SemaChecking can range check
470 // the immediate passed by the user.
471 if (proto.find('i') != std::string::npos)
472 return true;
473
474 // Pointer arguments need to use macros to avoid hiding aligned attributes
475 // from the pointer type.
476 if (proto.find('p') != std::string::npos ||
477 proto.find('c') != std::string::npos)
478 return true;
479
480 return false;
481 }
482
483 /// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is
484 /// defined as a macro should be accessed directly instead of being first
485 /// assigned to a local temporary.
486 static bool MacroArgUsedDirectly(const std::string &proto, unsigned i) {
487 // True for constant ints (i), pointers (p) and const pointers (c).
488 return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c');
489 }
490
491 // Generate the string "(argtype a, argtype b, ...)"
492 static std::string GenArgs(const std::string &proto, StringRef typestr) {
493 bool define = UseMacro(proto);
494 char arg = 'a';
495
496 std::string s;
497 s += "(";
498
499 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
500 if (define) {
501 // Some macro arguments are used directly instead of being assigned
502 // to local temporaries; prepend an underscore prefix to make their
503 // names consistent with the local temporaries.
504 if (MacroArgUsedDirectly(proto, i))
505 s += "__";
506 } else {
507 s += TypeString(proto[i], typestr) + " __";
508 }
509 s.push_back(arg);
510 if ((i + 1) < e)
511 s += ", ";
512 }
513
514 s += ")";
515 return s;
516 }
517
518 // Macro arguments are not type-checked like inline function arguments, so
519 // assign them to local temporaries to get the right type checking.
520 static std::string GenMacroLocals(const std::string &proto, StringRef typestr) {
521 char arg = 'a';
522 std::string s;
523 bool generatedLocal = false;
524
525 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
526 // Do not create a temporary for an immediate argument.
527 // That would defeat the whole point of using a macro!
528 // FIXME: For other (non-immediate) arguments that are used directly, a
529 // local temporary (or some other method) is still needed to get the
530 // correct type checking, even if that temporary is not used for anything.
531 // This is omitted for now because it turns out the the use of
532 // "__extension__" in the macro disables any warnings from the pointer
533 // assignment.
534 if (MacroArgUsedDirectly(proto, i))
535 continue;
536 generatedLocal = true;
537
538 s += TypeString(proto[i], typestr) + " __";
539 s.push_back(arg);
540 s += " = (";
541 s.push_back(arg);
542 s += "); ";
543 }
544
545 if (generatedLocal)
546 s += "\\\n ";
547 return s;
548 }
549
550 // Use the vmovl builtin to sign-extend or zero-extend a vector.
551 static std::string Extend(StringRef typestr, const std::string &a) {
552 std::string s;
553 s = MangleName("vmovl", typestr, ClassS);
554 s += "(" + a + ")";
555 return s;
556 }
557
558 static std::string Duplicate(unsigned nElts, StringRef typestr,
559 const std::string &a) {
560 std::string s;
561
562 s = "(" + TypeString('d', typestr) + "){ ";
563 for (unsigned i = 0; i != nElts; ++i) {
564 s += a;
565 if ((i + 1) < nElts)
566 s += ", ";
567 }
568 s += " }";
569
570 return s;
571 }
572
573 static std::string SplatLane(unsigned nElts, const std::string &vec,
574 const std::string &lane) {
575 std::string s = "__builtin_shufflevector(" + vec + ", " + vec;
576 for (unsigned i = 0; i < nElts; ++i)
577 s += ", " + lane;
578 s += ")";
579 return s;
580 }
581
582 static unsigned GetNumElements(StringRef typestr, bool &quad) {
583 quad = false;
584 bool dummy = false;
585 char type = ClassifyType(typestr, quad, dummy, dummy);
586 unsigned nElts = 0;
587 switch (type) {
588 case 'c': nElts = 8; break;
589 case 's': nElts = 4; break;
590 case 'i': nElts = 2; break;
591 case 'l': nElts = 1; break;
592 case 'h': nElts = 4; break;
593 case 'f': nElts = 2; break;
594 default:
595 throw "unhandled type!";
596 break;
597 }
598 if (quad) nElts <<= 1;
599 return nElts;
600 }
601
602 // Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
603 static std::string GenOpString(OpKind op, const std::string &proto,
604 StringRef typestr) {
605 bool quad;
606 unsigned nElts = GetNumElements(typestr, quad);
607 bool define = UseMacro(proto);
608
609 std::string ts = TypeString(proto[0], typestr);
610 std::string s;
611 if (!define) {
612 s = "return ";
613 }
614
615 switch(op) {
616 case OpAdd:
617 s += "__a + __b;";
618 break;
619 case OpAddl:
620 s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";";
621 break;
622 case OpAddw:
623 s += "__a + " + Extend(typestr, "__b") + ";";
624 break;
625 case OpSub:
626 s += "__a - __b;";
627 break;
628 case OpSubl:
629 s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";";
630 break;
631 case OpSubw:
632 s += "__a - " + Extend(typestr, "__b") + ";";
633 break;
634 case OpMulN:
635 s += "__a * " + Duplicate(nElts, typestr, "__b") + ";";
636 break;
637 case OpMulLane:
638 s += "__a * " + SplatLane(nElts, "__b", "__c") + ";";
639 break;
640 case OpMul:
641 s += "__a * __b;";
642 break;
643 case OpMullLane:
644 s += MangleName("vmull", typestr, ClassS) + "(__a, " +
645 SplatLane(nElts, "__b", "__c") + ");";
646 break;
647 case OpMlaN:
648 s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");";
649 break;
650 case OpMlaLane:
651 s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");";
652 break;
653 case OpMla:
654 s += "__a + (__b * __c);";
655 break;
656 case OpMlalN:
657 s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
658 Duplicate(nElts, typestr, "__c") + ");";
659 break;
660 case OpMlalLane:
661 s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
662 SplatLane(nElts, "__c", "__d") + ");";
663 break;
664 case OpMlal:
665 s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
666 break;
667 case OpMlsN:
668 s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");";
669 break;
670 case OpMlsLane:
671 s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");";
672 break;
673 case OpMls:
674 s += "__a - (__b * __c);";
675 break;
676 case OpMlslN:
677 s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
678 Duplicate(nElts, typestr, "__c") + ");";
679 break;
680 case OpMlslLane:
681 s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
682 SplatLane(nElts, "__c", "__d") + ");";
683 break;
684 case OpMlsl:
685 s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
686 break;
687 case OpQDMullLane:
688 s += MangleName("vqdmull", typestr, ClassS) + "(__a, " +
689 SplatLane(nElts, "__b", "__c") + ");";
690 break;
691 case OpQDMlalLane:
692 s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " +
693 SplatLane(nElts, "__c", "__d") + ");";
694 break;
695 case OpQDMlslLane:
696 s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " +
697 SplatLane(nElts, "__c", "__d") + ");";
698 break;
699 case OpQDMulhLane:
700 s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " +
701 SplatLane(nElts, "__b", "__c") + ");";
702 break;
703 case OpQRDMulhLane:
704 s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " +
705 SplatLane(nElts, "__b", "__c") + ");";
706 break;
707 case OpEq:
708 s += "(" + ts + ")(__a == __b);";
709 break;
710 case OpGe:
711 s += "(" + ts + ")(__a >= __b);";
712 break;
713 case OpLe:
714 s += "(" + ts + ")(__a <= __b);";
715 break;
716 case OpGt:
717 s += "(" + ts + ")(__a > __b);";
718 break;
719 case OpLt:
720 s += "(" + ts + ")(__a < __b);";
721 break;
722 case OpNeg:
723 s += " -__a;";
724 break;
725 case OpNot:
726 s += " ~__a;";
727 break;
728 case OpAnd:
729 s += "__a & __b;";
730 break;
731 case OpOr:
732 s += "__a | __b;";
733 break;
734 case OpXor:
735 s += "__a ^ __b;";
736 break;
737 case OpAndNot:
738 s += "__a & ~__b;";
739 break;
740 case OpOrNot:
741 s += "__a | ~__b;";
742 break;
743 case OpCast:
744 s += "(" + ts + ")__a;";
745 break;
746 case OpConcat:
747 s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a";
748 s += ", (int64x1_t)__b, 0, 1);";
749 break;
750 case OpHi:
751 s += "(" + ts +
752 ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 1);";
753 break;
754 case OpLo:
755 s += "(" + ts +
756 ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 0);";
757 break;
758 case OpDup:
759 s += Duplicate(nElts, typestr, "__a") + ";";
760 break;
761 case OpDupLane:
762 s += SplatLane(nElts, "__a", "__b") + ";";
763 break;
764 case OpSelect:
765 // ((0 & 1) | (~0 & 2))
766 s += "(" + ts + ")";
767 ts = TypeString(proto[1], typestr);
768 s += "((__a & (" + ts + ")__b) | ";
769 s += "(~__a & (" + ts + ")__c));";
770 break;
771 case OpRev16:
772 s += "__builtin_shufflevector(__a, __a";
773 for (unsigned i = 2; i <= nElts; i += 2)
774 for (unsigned j = 0; j != 2; ++j)
775 s += ", " + utostr(i - j - 1);
776 s += ");";
777 break;
778 case OpRev32: {
779 unsigned WordElts = nElts >> (1 + (int)quad);
780 s += "__builtin_shufflevector(__a, __a";
781 for (unsigned i = WordElts; i <= nElts; i += WordElts)
782 for (unsigned j = 0; j != WordElts; ++j)
783 s += ", " + utostr(i - j - 1);
784 s += ");";
785 break;
786 }
787 case OpRev64: {
788 unsigned DblWordElts = nElts >> (int)quad;
789 s += "__builtin_shufflevector(__a, __a";
790 for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts)
791 for (unsigned j = 0; j != DblWordElts; ++j)
792 s += ", " + utostr(i - j - 1);
793 s += ");";
794 break;
795 }
796 case OpAbdl: {
797 std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)";
798 if (typestr[0] != 'U') {
799 // vabd results are always unsigned and must be zero-extended.
800 std::string utype = "U" + typestr.str();
801 s += "(" + TypeString(proto[0], typestr) + ")";
802 abd = "(" + TypeString('d', utype) + ")" + abd;
803 s += Extend(utype, abd) + ";";
804 } else {
805 s += Extend(typestr, abd) + ";";
806 }
807 break;
808 }
809 case OpAba:
810 s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);";
811 break;
812 case OpAbal: {
813 s += "__a + ";
814 std::string abd = MangleName("vabd", typestr, ClassS) + "(__b, __c)";
815 if (typestr[0] != 'U') {
816 // vabd results are always unsigned and must be zero-extended.
817 std::string utype = "U" + typestr.str();
818 s += "(" + TypeString(proto[0], typestr) + ")";
819 abd = "(" + TypeString('d', utype) + ")" + abd;
820 s += Extend(utype, abd) + ";";
821 } else {
822 s += Extend(typestr, abd) + ";";
823 }
824 break;
825 }
826 default:
827 throw "unknown OpKind!";
828 break;
829 }
830 return s;
831 }
832
833 static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
834 unsigned mod = proto[0];
835 unsigned ret = 0;
836
837 if (mod == 'v' || mod == 'f')
838 mod = proto[1];
839
840 bool quad = false;
841 bool poly = false;
842 bool usgn = false;
843 bool scal = false;
844 bool cnst = false;
845 bool pntr = false;
846
847 // Base type to get the type string for.
848 char type = ClassifyType(typestr, quad, poly, usgn);
849
850 // Based on the modifying character, change the type and width if necessary.
851 type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
852
853 if (usgn)
854 ret |= 0x08;
855 if (quad && proto[1] != 'g')
856 ret |= 0x10;
857
858 switch (type) {
859 case 'c':
860 ret |= poly ? 5 : 0;
861 break;
862 case 's':
863 ret |= poly ? 6 : 1;
864 break;
865 case 'i':
866 ret |= 2;
867 break;
868 case 'l':
869 ret |= 3;
870 break;
871 case 'h':
872 ret |= 7;
873 break;
874 case 'f':
875 ret |= 4;
876 break;
877 default:
878 throw "unhandled type!";
879 break;
880 }
881 return ret;
882 }
883
884 // Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
885 static std::string GenBuiltin(const std::string &name, const std::string &proto,
886 StringRef typestr, ClassKind ck) {
887 std::string s;
888
889 // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
890 // sret-like argument.
891 bool sret = (proto[0] >= '2' && proto[0] <= '4');
892
893 bool define = UseMacro(proto);
894
895 // Check if the prototype has a scalar operand with the type of the vector
896 // elements. If not, bitcasting the args will take care of arg checking.
897 // The actual signedness etc. will be taken care of with special enums.
898 if (proto.find('s') == std::string::npos)
899 ck = ClassB;
900
901 if (proto[0] != 'v') {
902 std::string ts = TypeString(proto[0], typestr);
903
904 if (define) {
905 if (sret)
906 s += ts + " r; ";
907 else
908 s += "(" + ts + ")";
909 } else if (sret) {
910 s += ts + " r; ";
911 } else {
912 s += "return (" + ts + ")";
913 }
914 }
915
916 bool splat = proto.find('a') != std::string::npos;
917
918 s += "__builtin_neon_";
919 if (splat) {
920 // Call the non-splat builtin: chop off the "_n" suffix from the name.
921 std::string vname(name, 0, name.size()-2);
922 s += MangleName(vname, typestr, ck);
923 } else {
924 s += MangleName(name, typestr, ck);
925 }
926 s += "(";
927
928 // Pass the address of the return variable as the first argument to sret-like
929 // builtins.
930 if (sret)
931 s += "&r, ";
932
933 char arg = 'a';
934 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
935 std::string args = std::string(&arg, 1);
936
937 // Use the local temporaries instead of the macro arguments.
938 args = "__" + args;
939
940 bool argQuad = false;
941 bool argPoly = false;
942 bool argUsgn = false;
943 bool argScalar = false;
944 bool dummy = false;
945 char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn);
946 argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar,
947 dummy, dummy);
948
949 // Handle multiple-vector values specially, emitting each subvector as an
950 // argument to the __builtin.
951 if (proto[i] >= '2' && proto[i] <= '4') {
952 // Check if an explicit cast is needed.
953 if (argType != 'c' || argPoly || argUsgn)
954 args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args;
955
956 for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
957 s += args + ".val[" + utostr(vi) + "]";
958 if ((vi + 1) < ve)
959 s += ", ";
960 }
961 if ((i + 1) < e)
962 s += ", ";
963
964 continue;
965 }
966
967 if (splat && (i + 1) == e)
968 args = Duplicate(GetNumElements(typestr, argQuad), typestr, args);
969
970 // Check if an explicit cast is needed.
971 if ((splat || !argScalar) &&
972 ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) {
973 std::string argTypeStr = "c";
974 if (ck != ClassB)
975 argTypeStr = argType;
976 if (argQuad)
977 argTypeStr = "Q" + argTypeStr;
978 args = "(" + TypeString('d', argTypeStr) + ")" + args;
979 }
980
981 s += args;
982 if ((i + 1) < e)
983 s += ", ";
984 }
985
986 // Extra constant integer to hold type class enum for this function, e.g. s8
987 if (ck == ClassB)
988 s += ", " + utostr(GetNeonEnum(proto, typestr));
989
990 s += ");";
991
992 if (proto[0] != 'v' && sret) {
993 if (define)
994 s += " r;";
995 else
996 s += " return r;";
997 }
998 return s;
999 }
1000
1001 static std::string GenBuiltinDef(const std::string &name,
1002 const std::string &proto,
1003 StringRef typestr, ClassKind ck) {
1004 std::string s("BUILTIN(__builtin_neon_");
1005
1006 // If all types are the same size, bitcasting the args will take care
1007 // of arg checking. The actual signedness etc. will be taken care of with
1008 // special enums.
1009 if (proto.find('s') == std::string::npos)
1010 ck = ClassB;
1011
1012 s += MangleName(name, typestr, ck);
1013 s += ", \"";
1014
1015 for (unsigned i = 0, e = proto.size(); i != e; ++i)
1016 s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
1017
1018 // Extra constant integer to hold type class enum for this function, e.g. s8
1019 if (ck == ClassB)
1020 s += "i";
1021
1022 s += "\", \"n\")";
1023 return s;
1024 }
1025
1026 static std::string GenIntrinsic(const std::string &name,
1027 const std::string &proto,
1028 StringRef outTypeStr, StringRef inTypeStr,
1029 OpKind kind, ClassKind classKind) {
1030 assert(!proto.empty() && "");
1031 bool define = UseMacro(proto);
1032 std::string s;
1033
1034 // static always inline + return type
1035 if (define)
1036 s += "#define ";
1037 else
1038 s += "__ai " + TypeString(proto[0], outTypeStr) + " ";
1039
1040 // Function name with type suffix
1041 std::string mangledName = MangleName(name, outTypeStr, ClassS);
1042 if (outTypeStr != inTypeStr) {
1043 // If the input type is different (e.g., for vreinterpret), append a suffix
1044 // for the input type. String off a "Q" (quad) prefix so that MangleName
1045 // does not insert another "q" in the name.
1046 unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
1047 StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
1048 mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
1049 }
1050 s += mangledName;
1051
1052 // Function arguments
1053 s += GenArgs(proto, inTypeStr);
1054
1055 // Definition.
1056 if (define) {
1057 s += " __extension__ ({ \\\n ";
1058 s += GenMacroLocals(proto, inTypeStr);
1059 } else {
1060 s += " { \\\n ";
1061 }
1062
1063 if (kind != OpNone)
1064 s += GenOpString(kind, proto, outTypeStr);
1065 else
1066 s += GenBuiltin(name, proto, outTypeStr, classKind);
1067 if (define)
1068 s += " })";
1069 else
1070 s += " }";
1071 s += "\n";
1072 return s;
1073 }
1074
1075 /// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h
1076 /// is comprised of type definitions and function declarations.
1077 void NeonEmitter::run(raw_ostream &OS) {
1078 OS <<
1079 "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------"
1080 "---===\n"
1081 " *\n"
1082 " * Permission is hereby granted, free of charge, to any person obtaining "
1083 "a copy\n"
1084 " * of this software and associated documentation files (the \"Software\"),"
1085 " to deal\n"
1086 " * in the Software without restriction, including without limitation the "
1087 "rights\n"
1088 " * to use, copy, modify, merge, publish, distribute, sublicense, "
1089 "and/or sell\n"
1090 " * copies of the Software, and to permit persons to whom the Software is\n"
1091 " * furnished to do so, subject to the following conditions:\n"
1092 " *\n"
1093 " * The above copyright notice and this permission notice shall be "
1094 "included in\n"
1095 " * all copies or substantial portions of the Software.\n"
1096 " *\n"
1097 " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
1098 "EXPRESS OR\n"
1099 " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
1100 "MERCHANTABILITY,\n"
1101 " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
1102 "SHALL THE\n"
1103 " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
1104 "OTHER\n"
1105 " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
1106 "ARISING FROM,\n"
1107 " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
1108 "DEALINGS IN\n"
1109 " * THE SOFTWARE.\n"
1110 " *\n"
1111 " *===--------------------------------------------------------------------"
1112 "---===\n"
1113 " */\n\n";
1114
1115 OS << "#ifndef __ARM_NEON_H\n";
1116 OS << "#define __ARM_NEON_H\n\n";
1117
1118 OS << "#ifndef __ARM_NEON__\n";
1119 OS << "#error \"NEON support not enabled\"\n";
1120 OS << "#endif\n\n";
1121
1122 OS << "#include \n\n";
1123
1124 // Emit NEON-specific scalar typedefs.
1125 OS << "typedef float float32_t;\n";
1126 OS << "typedef int8_t poly8_t;\n";
1127 OS << "typedef int16_t poly16_t;\n";
1128 OS << "typedef uint16_t float16_t;\n";
1129
1130 // Emit Neon vector typedefs.
1131 std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
1132 SmallVector TDTypeVec;
1133 ParseTypes(0, TypedefTypes, TDTypeVec);
1134
1135 // Emit vector typedefs.
1136 for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
1137 bool dummy, quad = false, poly = false;
1138 (void) ClassifyType(TDTypeVec[i], quad, poly, dummy);
1139 if (poly)
1140 OS << "typedef __attribute__((neon_polyvector_type(";
1141 else
1142 OS << "typedef __attribute__((neon_vector_type(";
1143
1144 unsigned nElts = GetNumElements(TDTypeVec[i], quad);
1145 OS << utostr(nElts) << "))) ";
1146 if (nElts < 10)
1147 OS << " ";
1148
1149 OS << TypeString('s', TDTypeVec[i]);
1150 OS << " " << TypeString('d', TDTypeVec[i]) << ";\n";
1151 }
1152 OS << "\n";
1153
1154 // Emit struct typedefs.
1155 for (unsigned vi = 2; vi != 5; ++vi) {
1156 for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
1157 std::string ts = TypeString('d', TDTypeVec[i]);
1158 std::string vs = TypeString('0' + vi, TDTypeVec[i]);
1159 OS << "typedef struct " << vs << " {\n";
1160 OS << " " << ts << " val";
1161 OS << "[" << utostr(vi) << "]";
1162 OS << ";\n} ";
1163 OS << vs << ";\n\n";
1164 }
1165 }
1166
1167 OS << "#define __ai static __attribute__((__always_inline__))\n\n";
1168
1169 std::vector RV = Records.getAllDerivedDefinitions("Inst");
1170
1171 // Emit vmovl, vmull and vabd intrinsics first so they can be used by other
1172 // intrinsics. (Some of the saturating multiply instructions are also
1173 // used to implement the corresponding "_lane" variants, but tablegen
1174 // sorts the records into alphabetical order so that the "_lane" variants
1175 // come after the intrinsics they use.)
1176 emitIntrinsic(OS, Records.getDef("VMOVL"));
1177 emitIntrinsic(OS, Records.getDef("VMULL"));
1178 emitIntrinsic(OS, Records.getDef("VABD"));
1179
1180 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1181 Record *R = RV[i];
1182 if (R->getName() != "VMOVL" &&
1183 R->getName() != "VMULL" &&
1184 R->getName() != "VABD")
1185 emitIntrinsic(OS, R);
1186 }
1187
1188 OS << "#undef __ai\n\n";
1189 OS << "#endif /* __ARM_NEON_H */\n";
1190 }
1191
1192 /// emitIntrinsic - Write out the arm_neon.h header file definitions for the
1193 /// intrinsics specified by record R.
1194 void NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R) {
1195 std::string name = R->getValueAsString("Name");
1196 std::string Proto = R->getValueAsString("Prototype");
1197 std::string Types = R->getValueAsString("Types");
1198
1199 SmallVector TypeVec;
1200 ParseTypes(R, Types, TypeVec);
1201
1202 OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
1203
1204 ClassKind classKind = ClassNone;
1205 if (R->getSuperClasses().size() >= 2)
1206 classKind = ClassMap[R->getSuperClasses()[1]];
1207 if (classKind == ClassNone && kind == OpNone)
1208 throw TGError(R->getLoc(), "Builtin has no class kind");
1209
1210 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1211 if (kind == OpReinterpret) {
1212 bool outQuad = false;
1213 bool dummy = false;
1214 (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
1215 for (unsigned srcti = 0, srcte = TypeVec.size();
1216 srcti != srcte; ++srcti) {
1217 bool inQuad = false;
1218 (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
1219 if (srcti == ti || inQuad != outQuad)
1220 continue;
1221 OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti],
1222 OpCast, ClassS);
1223 }
1224 } else {
1225 OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti],
1226 kind, classKind);
1227 }
1228 }
1229 OS << "\n";
1230 }
1231
1232 static unsigned RangeFromType(const char mod, StringRef typestr) {
1233 // base type to get the type string for.
1234 bool quad = false, dummy = false;
1235 char type = ClassifyType(typestr, quad, dummy, dummy);
1236 type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy);
1237
1238 switch (type) {
1239 case 'c':
1240 return (8 << (int)quad) - 1;
1241 case 'h':
1242 case 's':
1243 return (4 << (int)quad) - 1;
1244 case 'f':
1245 case 'i':
1246 return (2 << (int)quad) - 1;
1247 case 'l':
1248 return (1 << (int)quad) - 1;
1249 default:
1250 throw "unhandled type!";
1251 break;
1252 }
1253 assert(0 && "unreachable");
1254 return 0;
1255 }
1256
1257 /// runHeader - Emit a file with sections defining:
1258 /// 1. the NEON section of BuiltinsARM.def.
1259 /// 2. the SemaChecking code for the type overload checking.
1260 /// 3. the SemaChecking code for validation of intrinsic immedate arguments.
1261 void NeonEmitter::runHeader(raw_ostream &OS) {
1262 std::vector RV = Records.getAllDerivedDefinitions("Inst");
1263
1264 StringMap EmittedMap;
1265
1266 // Generate BuiltinsARM.def for NEON
1267 OS << "#ifdef GET_NEON_BUILTINS\n";
1268 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1269 Record *R = RV[i];
1270 OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
1271 if (k != OpNone)
1272 continue;
1273
1274 std::string Proto = R->getValueAsString("Prototype");
1275
1276 // Functions with 'a' (the splat code) in the type prototype should not get
1277 // their own builtin as they use the non-splat variant.
1278 if (Proto.find('a') != std::string::npos)
1279 continue;
1280
1281 std::string Types = R->getValueAsString("Types");
1282 SmallVector TypeVec;
1283 ParseTypes(R, Types, TypeVec);
1284
1285 if (R->getSuperClasses().size() < 2)
1286 throw TGError(R->getLoc(), "Builtin has no class kind");
1287
1288 std::string name = R->getValueAsString("Name");
1289 ClassKind ck = ClassMap[R->getSuperClasses()[1]];
1290
1291 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1292 // Generate the BuiltinsARM.def declaration for this builtin, ensuring
1293 // that each unique BUILTIN() macro appears only once in the output
1294 // stream.
1295 std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
1296 if (EmittedMap.count(bd))
1297 continue;
1298
1299 EmittedMap[bd] = OpNone;
1300 OS << bd << "\n";
1301 }
1302 }
1303 OS << "#endif\n\n";
1304
1305 // Generate the overloaded type checking code for SemaChecking.cpp
1306 OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
1307 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1308 Record *R = RV[i];
1309 OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
1310 if (k != OpNone)
1311 continue;
1312
1313 std::string Proto = R->getValueAsString("Prototype");
1314 std::string Types = R->getValueAsString("Types");
1315 std::string name = R->getValueAsString("Name");
1316
1317 // Functions with 'a' (the splat code) in the type prototype should not get
1318 // their own builtin as they use the non-splat variant.
1319 if (Proto.find('a') != std::string::npos)
1320 continue;
1321
1322 // Functions which have a scalar argument cannot be overloaded, no need to
1323 // check them if we are emitting the type checking code.
1324 if (Proto.find('s') != std::string::npos)
1325 continue;
1326
1327 SmallVector TypeVec;
1328 ParseTypes(R, Types, TypeVec);
1329
1330 if (R->getSuperClasses().size() < 2)
1331 throw TGError(R->getLoc(), "Builtin has no class kind");
1332
1333 int si = -1, qi = -1;
1334 unsigned mask = 0, qmask = 0;
1335 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1336 // Generate the switch case(s) for this builtin for the type validation.
1337 bool quad = false, poly = false, usgn = false;
1338 (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
1339
1340 if (quad) {
1341 qi = ti;
1342 qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
1343 } else {
1344 si = ti;
1345 mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
1346 }
1347 }
1348 if (mask)
1349 OS << "case ARM::BI__builtin_neon_"
1350 << MangleName(name, TypeVec[si], ClassB)
1351 << ": mask = " << "0x" << utohexstr(mask) << "; break;\n";
1352 if (qmask)
1353 OS << "case ARM::BI__builtin_neon_"
1354 << MangleName(name, TypeVec[qi], ClassB)
1355 << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n";
1356 }
1357 OS << "#endif\n\n";
1358
1359 // Generate the intrinsic range checking code for shift/lane immediates.
1360 OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
1361 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1362 Record *R = RV[i];
1363
1364 OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
1365 if (k != OpNone)
1366 continue;
1367
1368 std::string name = R->getValueAsString("Name");
1369 std::string Proto = R->getValueAsString("Prototype");
1370 std::string Types = R->getValueAsString("Types");
1371
1372 // Functions with 'a' (the splat code) in the type prototype should not get
1373 // their own builtin as they use the non-splat variant.
1374 if (Proto.find('a') != std::string::npos)
1375 continue;
1376
1377 // Functions which do not have an immediate do not need to have range
1378 // checking code emitted.
1379 size_t immPos = Proto.find('i');
1380 if (immPos == std::string::npos)
1381 continue;
1382
1383 SmallVector TypeVec;
1384 ParseTypes(R, Types, TypeVec);
1385
1386 if (R->getSuperClasses().size() < 2)
1387 throw TGError(R->getLoc(), "Builtin has no class kind");
1388
1389 ClassKind ck = ClassMap[R->getSuperClasses()[1]];
1390
1391 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1392 std::string namestr, shiftstr, rangestr;
1393
1394 if (R->getValueAsBit("isVCVT_N")) {
1395 // VCVT between floating- and fixed-point values takes an immediate
1396 // in the range 1 to 32.
1397 ck = ClassB;
1398 rangestr = "l = 1; u = 31"; // upper bound = l + u
1399 } else if (Proto.find('s') == std::string::npos) {
1400 // Builtins which are overloaded by type will need to have their upper
1401 // bound computed at Sema time based on the type constant.
1402 ck = ClassB;
1403 if (R->getValueAsBit("isShift")) {
1404 shiftstr = ", true";
1405
1406 // Right shifts have an 'r' in the name, left shifts do not.
1407 if (name.find('r') != std::string::npos)
1408 rangestr = "l = 1; ";
1409 }
1410 rangestr += "u = RFT(TV" + shiftstr + ")";
1411 } else {
1412 // The immediate generally refers to a lane in the preceding argument.
1413 assert(immPos > 0 && "unexpected immediate operand");
1414 rangestr = "u = " + utostr(RangeFromType(Proto[immPos-1], TypeVec[ti]));
1415 }
1416 // Make sure cases appear only once by uniquing them in a string map.
1417 namestr = MangleName(name, TypeVec[ti], ck);
1418 if (EmittedMap.count(namestr))
1419 continue;
1420 EmittedMap[namestr] = OpNone;
1421
1422 // Calculate the index of the immediate that should be range checked.
1423 unsigned immidx = 0;
1424
1425 // Builtins that return a struct of multiple vectors have an extra
1426 // leading arg for the struct return.
1427 if (Proto[0] >= '2' && Proto[0] <= '4')
1428 ++immidx;
1429
1430 // Add one to the index for each argument until we reach the immediate
1431 // to be checked. Structs of vectors are passed as multiple arguments.
1432 for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
1433 switch (Proto[ii]) {
1434 default: immidx += 1; break;
1435 case '2': immidx += 2; break;
1436 case '3': immidx += 3; break;
1437 case '4': immidx += 4; break;
1438 case 'i': ie = ii + 1; break;
1439 }
1440 }
1441 OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck)
1442 << ": i = " << immidx << "; " << rangestr << "; break;\n";
1443 }
1444 }
1445 OS << "#endif\n\n";
1446 }
1447
1448 /// GenTest - Write out a test for the intrinsic specified by the name and
1449 /// type strings, including the embedded patterns for FileCheck to match.
1450 static std::string GenTest(const std::string &name,
1451 const std::string &proto,
1452 StringRef outTypeStr, StringRef inTypeStr,
1453 bool isShift) {
1454 assert(!proto.empty() && "");
1455 std::string s;
1456
1457 // Function name with type suffix
1458 std::string mangledName = MangleName(name, outTypeStr, ClassS);
1459 if (outTypeStr != inTypeStr) {
1460 // If the input type is different (e.g., for vreinterpret), append a suffix
1461 // for the input type. String off a "Q" (quad) prefix so that MangleName
1462 // does not insert another "q" in the name.
1463 unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
1464 StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
1465 mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
1466 }
1467
1468 // Emit the FileCheck patterns.
1469 s += "// CHECK: test_" + mangledName + "\n";
1470 // s += "// CHECK: \n"; // FIXME: + expected instruction opcode.
1471
1472 // Emit the start of the test function.
1473 s += TypeString(proto[0], outTypeStr) + " test_" + mangledName + "(";
1474 char arg = 'a';
1475 std::string comma;
1476 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
1477 // Do not create arguments for values that must be immediate constants.
1478 if (proto[i] == 'i')
1479 continue;
1480 s += comma + TypeString(proto[i], inTypeStr) + " ";
1481 s.push_back(arg);
1482 comma = ", ";
1483 }
1484 s += ") { \\\n ";
1485
1486 if (proto[0] != 'v')
1487 s += "return ";
1488 s += mangledName + "(";
1489 arg = 'a';
1490 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
1491 if (proto[i] == 'i') {
1492 // For immediate operands, test the maximum value.
1493 if (isShift)
1494 s += "1"; // FIXME
1495 else
1496 // The immediate generally refers to a lane in the preceding argument.
1497 s += utostr(RangeFromType(proto[i-1], inTypeStr));
1498 } else {
1499 s.push_back(arg);
1500 }
1501 if ((i + 1) < e)
1502 s += ", ";
1503 }
1504 s += ");\n}\n\n";
1505 return s;
1506 }
1507
1508 /// runTests - Write out a complete set of tests for all of the Neon
1509 /// intrinsics.
1510 void NeonEmitter::runTests(raw_ostream &OS) {
1511 OS <<
1512 "// RUN: %clang_cc1 -triple thumbv7-apple-darwin \\\n"
1513 "// RUN: -target-cpu cortex-a9 -ffreestanding -S -o - %s | FileCheck %s\n"
1514 "\n"
1515 "#include \n"
1516 "\n";
1517
1518 std::vector RV = Records.getAllDerivedDefinitions("Inst");
1519 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1520 Record *R = RV[i];
1521 std::string name = R->getValueAsString("Name");
1522 std::string Proto = R->getValueAsString("Prototype");
1523 std::string Types = R->getValueAsString("Types");
1524 bool isShift = R->getValueAsBit("isShift");
1525
1526 SmallVector TypeVec;
1527 ParseTypes(R, Types, TypeVec);
1528
1529 OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
1530 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1531 if (kind == OpReinterpret) {
1532 bool outQuad = false;
1533 bool dummy = false;
1534 (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
1535 for (unsigned srcti = 0, srcte = TypeVec.size();
1536 srcti != srcte; ++srcti) {
1537 bool inQuad = false;
1538 (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
1539 if (srcti == ti || inQuad != outQuad)
1540 continue;
1541 OS << GenTest(name, Proto, TypeVec[ti], TypeVec[srcti], isShift);
1542 }
1543 } else {
1544 OS << GenTest(name, Proto, TypeVec[ti], TypeVec[ti], isShift);
1545 }
1546 }
1547 OS << "\n";
1548 }
1549 }
1550
+0
-176
utils/TableGen/NeonEmitter.h less more
None //===- NeonEmitter.h - Generate arm_neon.h for use with clang ---*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend is responsible for emitting arm_neon.h, which includes
10 // a declaration and definition of each function specified by the ARM NEON
11 // compiler interface. See ARM document DUI0348B.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef NEON_EMITTER_H
16 #define NEON_EMITTER_H
17
18 #include "llvm/TableGen/Record.h"
19 #include "llvm/TableGen/TableGenBackend.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/StringMap.h"
22
23 enum OpKind {
24 OpNone,
25 OpAdd,
26 OpAddl,
27 OpAddw,
28 OpSub,
29 OpSubl,
30 OpSubw,
31 OpMul,
32 OpMla,
33 OpMlal,
34 OpMls,
35 OpMlsl,
36 OpMulN,
37 OpMlaN,
38 OpMlsN,
39 OpMlalN,
40 OpMlslN,
41 OpMulLane,
42 OpMullLane,
43 OpMlaLane,
44 OpMlsLane,
45 OpMlalLane,
46 OpMlslLane,
47 OpQDMullLane,
48 OpQDMlalLane,
49 OpQDMlslLane,
50 OpQDMulhLane,
51 OpQRDMulhLane,
52 OpEq,
53 OpGe,
54 OpLe,
55 OpGt,
56 OpLt,
57 OpNeg,
58 OpNot,
59 OpAnd,
60 OpOr,
61 OpXor,
62 OpAndNot,
63 OpOrNot,
64 OpCast,
65 OpConcat,
66 OpDup,
67 OpDupLane,
68 OpHi,
69 OpLo,
70 OpSelect,
71 OpRev16,
72 OpRev32,
73 OpRev64,
74 OpReinterpret,
75 OpAbdl,
76 OpAba,
77 OpAbal
78 };
79
80 enum ClassKind {
81 ClassNone,
82 ClassI, // generic integer instruction, e.g., "i8" suffix
83 ClassS, // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix
84 ClassW, // width-specific instruction, e.g., "8" suffix
85 ClassB // bitcast arguments with enum argument to specify type
86 };
87
88 namespace llvm {
89
90 class NeonEmitter : public TableGenBackend {
91 RecordKeeper &Records;
92 StringMap OpMap;
93 DenseMap ClassMap;
94
95 public:
96 NeonEmitter(RecordKeeper &R) : Records(R) {
97 OpMap["OP_NONE"] = OpNone;
98 OpMap["OP_ADD"] = OpAdd;
99 OpMap["OP_ADDL"] = OpAddl;
100 OpMap["OP_ADDW"] = OpAddw;
101 OpMap["OP_SUB"] = OpSub;
102 OpMap["OP_SUBL"] = OpSubl;
103 OpMap["OP_SUBW"] = OpSubw;
104 OpMap["OP_MUL"] = OpMul;
105 OpMap["OP_MLA"] = OpMla;
106 OpMap["OP_MLAL"] = OpMlal;
107 OpMap["OP_MLS"] = OpMls;
108 OpMap["OP_MLSL"] = OpMlsl;
109 OpMap["OP_MUL_N"] = OpMulN;
110 OpMap["OP_MLA_N"] = OpMlaN;
111 OpMap["OP_MLS_N"] = OpMlsN;
112 OpMap["OP_MLAL_N"] = OpMlalN;
113 OpMap["OP_MLSL_N"] = OpMlslN;
114 OpMap["OP_MUL_LN"]= OpMulLane;
115 OpMap["OP_MULL_LN"] = OpMullLane;
116 OpMap["OP_MLA_LN"]= OpMlaLane;
117 OpMap["OP_MLS_LN"]= OpMlsLane;
118 OpMap["OP_MLAL_LN"] = OpMlalLane;
119 OpMap["OP_MLSL_LN"] = OpMlslLane;
120 OpMap["OP_QDMULL_LN"] = OpQDMullLane;
121 OpMap["OP_QDMLAL_LN"] = OpQDMlalLane;
122 OpMap["OP_QDMLSL_LN"] = OpQDMlslLane;
123 OpMap["OP_QDMULH_LN"] = OpQDMulhLane;
124 OpMap["OP_QRDMULH_LN"] = OpQRDMulhLane;
125 OpMap["OP_EQ"] = OpEq;
126 OpMap["OP_GE"] = OpGe;
127 OpMap["OP_LE"] = OpLe;
128 OpMap["OP_GT"] = OpGt;
129 OpMap["OP_LT"] = OpLt;
130 OpMap["OP_NEG"] = OpNeg;
131 OpMap["OP_NOT"] = OpNot;
132 OpMap["OP_AND"] = OpAnd;
133 OpMap["OP_OR"] = OpOr;
134 OpMap["OP_XOR"] = OpXor;
135 OpMap["OP_ANDN"] = OpAndNot;
136 OpMap["OP_ORN"] = OpOrNot;
137 OpMap["OP_CAST"] = OpCast;
138 OpMap["OP_CONC"] = OpConcat;
139 OpMap["OP_HI"] = OpHi;
140 OpMap["OP_LO"] = OpLo;
141 OpMap["OP_DUP"] = OpDup;
142 OpMap["OP_DUP_LN"] = OpDupLane;
143 OpMap["OP_SEL"] = OpSelect;
144 OpMap["OP_REV16"] = OpRev16;
145 OpMap["OP_REV32"] = OpRev32;
146 OpMap["OP_REV64"] = OpRev64;
147 OpMap["OP_REINT"] = OpReinterpret;
148 OpMap["OP_ABDL"] = OpAbdl;
149 OpMap["OP_ABA"] = OpAba;
150 OpMap["OP_ABAL"] = OpAbal;
151
152 Record *SI = R.getClass("SInst");
153 Record *II = R.getClass("IInst");
154 Record *WI = R.getClass("WInst");
155 ClassMap[SI] = ClassS;
156 ClassMap[II] = ClassI;
157 ClassMap[WI] = ClassW;
158 }
159
160 // run - Emit arm_neon.h.inc
161 void run(raw_ostream &o);
162
163 // runHeader - Emit all the __builtin prototypes used in arm_neon.h
164 void runHeader(raw_ostream &o);
165
166 // runTests - Emit tests for all the Neon intrinsics.
167 void runTests(raw_ostream &o);
168
169 private:
170 void emitIntrinsic(raw_ostream &OS, Record *R);
171 };
172
173 } // End llvm namespace
174
175 #endif
+0
-194
utils/TableGen/OptParserEmitter.cpp less more
None //===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "OptParserEmitter.h"
10 #include "llvm/TableGen/Record.h"
11 #include "llvm/ADT/STLExtras.h"
12 using namespace llvm;
13
14 static int StrCmpOptionName(const char *A, const char *B) {
15 char a = *A, b = *B;
16 while (a == b) {
17 if (a == '\0')
18 return 0;
19
20 a = *++A;
21 b = *++B;
22 }
23
24 if (a == '\0') // A is a prefix of B.
25 return 1;
26 if (b == '\0') // B is a prefix of A.
27 return -1;
28
29 // Otherwise lexicographic.
30 return (a < b) ? -1 : 1;
31 }
32
33 static int CompareOptionRecords(const void *Av, const void *Bv) {
34 const Record *A = *(Record**) Av;
35 const Record *B = *(Record**) Bv;
36
37 // Sentinel options precede all others and are only ordered by precedence.
38 bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
39 bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
40 if (ASent != BSent)
41 return ASent ? -1 : 1;
42
43 // Compare options by name, unless they are sentinels.
44 if (!ASent)
45 if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
46 B->getValueAsString("Name").c_str()))
47 return Cmp;
48
49 // Then by the kind precedence;
50 int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
51 int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
52 assert(APrec != BPrec && "Options are equivalent!");
53 return APrec < BPrec ? -1 : 1;
54 }
55
56 static const std::string getOptionName(const Record &R) {
57 // Use the record name unless EnumName is defined.
58 if (dynamic_cast(R.getValueInit("EnumName")))
59 return R.getName();
60
61 return R.getValueAsString("EnumName");
62 }
63
64 static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
65 OS << '"';
66 OS.write_escaped(Str);
67 OS << '"';
68 return OS;
69 }
70
71