llvm.org GIT mirror llvm / 3ae9cf5
Revert r141079: tblgen: add preprocessor as a separate mode git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141492 91177308-0d34-0410-b5e6-96231b3b80d8 Che-Liang Chiou 8 years ago
4 changed file(s) with 0 addition(s) and 680 deletion(s). Raw diff Collapse all Expand all
88 TableGenBackend.cpp
99 TGLexer.cpp
1010 TGParser.cpp
11 TGPreprocessor.cpp
1211 )
1312
1413 add_llvm_library_dependencies(LLVMTableGen
1515 //===----------------------------------------------------------------------===//
1616
1717 #include "TGParser.h"
18 #include "TGPreprocessor.h"
1918 #include "llvm/ADT/OwningPtr.h"
2019 #include "llvm/Support/CommandLine.h"
2120 #include "llvm/Support/MemoryBuffer.h"
4342 cl::list
4443 IncludeDirs("I", cl::desc("Directory of include files"),
4544 cl::value_desc("directory"), cl::Prefix);
46
47 cl::opt
48 PreprocessOnly("E",
49 cl::desc("Stop after the preprocessing stage; "
50 "This is work in progress and has no effect yet"),
51 cl::init(false));
5245 }
5346
5447 namespace llvm {
7265 // Record the location of the include directory so that the lexer can find
7366 // it later.
7467 SrcMgr.setIncludeDirs(IncludeDirs);
75
76 // TODO(clchiou): Integrate preprocessor into TGParser
77 if (PreprocessOnly) {
78 std::string Error;
79 tool_output_file Out(OutputFilename.c_str(), Error);
80 if (!Error.empty()) {
81 errs() << argv0 << ": error opening " << OutputFilename
82 << ":" << Error << "\n";
83 return 1;
84 }
85 TGPreprocessor Preprocessor(SrcMgr, Out);
86 if (Preprocessor.PreprocessFile())
87 return 1;
88 Out.keep();
89 return 0;
90 }
9168
9269 TGParser Parser(SrcMgr, Records);
9370
+0
-604
lib/TableGen/TGPreprocessor.cpp less more
None //===- TGPreprocessor.cpp - Preprocessor for TableGen ---------------------===//
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 // Implement the Preprocessor for TableGen.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "TGPreprocessor.h"
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/Support/MemoryBuffer.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "llvm/Support/ToolOutputFile.h"
18 #include "llvm/TableGen/Error.h"
19 #include
20 #include
21 #include
22 #include
23 #include
24 #include
25
26 namespace llvm {
27 typedef std::map TGPPEnvironment;
28
29 enum TGPPTokenKind {
30 tgpptoken_symbol,
31 tgpptoken_literal,
32 tgpptoken_newline,
33 tgpptoken_error,
34 tgpptoken_end
35 };
36
37 enum TGPPRecordKind {
38 tgpprecord_for,
39 tgpprecord_variable,
40 tgpprecord_literal
41 };
42
43 enum TGPPRangeKind {
44 tgpprange_list,
45 tgpprange_sequence
46 };
47
48 bool MatchSymbol(TGPPTokenKind Kind,
49 const char *BeginOfToken, const char *EndOfToken,
50 char Symbol);
51
52 bool MatchSymbol(TGPPTokenKind Kind,
53 const char *BeginOfToken, const char *EndOfToken,
54 const char *Symbol);
55
56 bool MatchIdNum(TGPPTokenKind Kind,
57 const char *BeginOfToken, const char *EndOfToken);
58
59 bool MatchIdentifier(TGPPTokenKind Kind,
60 const char *BeginOfToken, const char *EndOfToken);
61
62 bool MatchNumber(TGPPTokenKind Kind,
63 const char *BeginOfToken, const char *EndOfToken,
64 long int *Val);
65
66 class TGPPLexer {
67 const MemoryBuffer *CurBuf;
68 const char *CurPtr;
69 bool IsInsideMacroStatement, WasEndOfLine;
70
71 bool IsEndOfBuffer(const char *Ptr) const {
72 return (!*Ptr && Ptr == CurBuf->getBufferEnd());
73 }
74
75 bool IsNewLine() {
76 if (*CurPtr == '\r' || *CurPtr == '\n') {
77 if ((CurPtr[1] == '\r' || CurPtr[1] == '\n') && CurPtr[0] != CurPtr[1])
78 ++CurPtr;
79 return true;
80 }
81 return false;
82 }
83
84 bool MatchPrefix(const char *Prefix, const char *Ptr) const {
85 while (*Ptr == ' ' || *Ptr == '\t')
86 ++Ptr;
87 return !strncmp(Prefix, Ptr, strlen(Prefix));
88 }
89 public:
90 TGPPLexer(const SourceMgr &SM)
91 : CurBuf(SM.getMemoryBuffer(0)),
92 CurPtr(CurBuf->getBufferStart()),
93 IsInsideMacroStatement(false),
94 WasEndOfLine(true) {
95 }
96
97 TGPPTokenKind NextToken(const char **BeginOfToken, const char **EndOfToken);
98 };
99
100 // preprocessor records
101 class TGPPRecord {
102 TGPPRecordKind Kind;
103
104 // tgpprecord_for
105 std::vector IndexVars;
106 std::vector IndexRanges;
107 TGPPRecords LoopBody;
108
109 // tgpprecord_variable, tgpprecord_literal
110 std::string Str;
111
112 bool EvaluateFor(const TGPPEnvironment &Env, raw_fd_ostream &OS) const;
113
114 bool EvaluateVariable(const TGPPEnvironment &Env, raw_fd_ostream &OS) const {
115 TGPPEnvironment::const_iterator it_val = Env.find(Str);
116 if (it_val == Env.end()) {
117 PrintError("Var is not bound to any value: " + Str);
118 return true;
119 }
120 OS << it_val->second;
121 return false;
122 }
123
124 bool EvaluateLiteral(const TGPPEnvironment &Env, raw_fd_ostream &OS) const {
125 OS << Str;
126 return false;
127 }
128
129 public:
130 TGPPRecord(TGPPRecordKind K) : Kind(K) {}
131 TGPPRecord(TGPPRecordKind K, const std::string &S) : Kind(K), Str(S) {}
132
133 TGPPRecords *GetLoopBody() { return &LoopBody; }
134
135 void AppendIndex(const std::string &V, const TGPPRange &R) {
136 IndexVars.push_back(V);
137 IndexRanges.push_back(R);
138 }
139
140 bool Evaluate(const TGPPEnvironment &Env, raw_fd_ostream &OS) const;
141 };
142
143 class TGPPRange {
144 TGPPRangeKind Kind;
145
146 // tgpprange_list
147 std::vector Vals;
148
149 // tgpprange_sequence
150 long int From, To;
151
152 public:
153 TGPPRange() : Kind(tgpprange_list) {}
154 TGPPRange(long int F, long int T)
155 : Kind(tgpprange_sequence), From(F), To(T) {}
156
157 size_t size() const {
158 if (Kind == tgpprange_list)
159 return Vals.size();
160 else
161 return To - From + 1;
162 }
163
164 std::string at(size_t i) const {
165 if (Kind == tgpprange_list)
166 return Vals.at(i);
167 else {
168 std::string Result;
169 raw_string_ostream Tmp(Result);
170 Tmp << (From + (long int)i);
171 return Tmp.str();
172 }
173 }
174
175 void push_back(const std::string &S) {
176 if (Kind == tgpprange_list)
177 Vals.push_back(S);
178 }
179 };
180 } // namespace llvm
181
182 using namespace llvm;
183
184 bool llvm::MatchSymbol(TGPPTokenKind Kind,
185 const char *BeginOfToken, const char *EndOfToken,
186 char Symbol) {
187 return Kind == tgpptoken_symbol &&
188 BeginOfToken + 1 == EndOfToken &&
189 Symbol == *BeginOfToken;
190 }
191
192 bool llvm::MatchSymbol(TGPPTokenKind Kind,
193 const char *BeginOfToken, const char *EndOfToken,
194 const char *Symbol) {
195 return Kind == tgpptoken_symbol &&
196 BeginOfToken + strlen(Symbol) == EndOfToken &&
197 !strncmp(Symbol, BeginOfToken, EndOfToken - BeginOfToken);
198 }
199
200 bool llvm::MatchIdNum(TGPPTokenKind Kind,
201 const char *BeginOfToken, const char *EndOfToken) {
202 if (Kind != tgpptoken_symbol)
203 return false;
204 for (const char *i = BeginOfToken; i != EndOfToken; ++i)
205 if (*i != '_' && !isalnum(*i))
206 return false;
207 return true;
208 }
209
210 bool llvm::MatchIdentifier(TGPPTokenKind Kind,
211 const char *BeginOfToken, const char *EndOfToken) {
212 if (Kind != tgpptoken_symbol)
213 return false;
214
215 const char *i = BeginOfToken;
216 if (*i != '_' && !isalpha(*i))
217 return false;
218 for (++i; i != EndOfToken; ++i)
219 if (*i != '_' && !isalnum(*i))
220 return false;
221
222 return true;
223 }
224
225 bool llvm::MatchNumber(TGPPTokenKind Kind,
226 const char *BeginOfToken, const char *EndOfToken,
227 long int *Val) {
228 if (Kind != tgpptoken_symbol)
229 return false;
230 char *e;
231 *Val = strtol(BeginOfToken, &e, 10);
232 return e == EndOfToken;
233 }
234
235 TGPPTokenKind TGPPLexer::
236 NextToken(const char **BeginOfToken, const char **EndOfToken) {
237 bool IsBeginOfLine = WasEndOfLine;
238 WasEndOfLine = false;
239
240 if (IsEndOfBuffer(CurPtr))
241 return tgpptoken_end;
242
243 else if (IsInsideMacroStatement) {
244 while (*CurPtr == ' ' || *CurPtr == '\t') // trim space, if any
245 ++CurPtr;
246
247 const char *BeginOfSymbol = CurPtr;
248
249 if (IsNewLine()) {
250 ++CurPtr;
251 IsInsideMacroStatement = false;
252 WasEndOfLine = true;
253 return tgpptoken_newline;
254 }
255
256 else if (*CurPtr == '[' || *CurPtr == ']' ||
257 *CurPtr == '(' || *CurPtr == ')' ||
258 *CurPtr == ',' || *CurPtr == '=') {
259 *BeginOfToken = BeginOfSymbol;
260 *EndOfToken = ++CurPtr;
261 return tgpptoken_symbol;
262 }
263
264 else if (*CurPtr == '_' || isalpha(*CurPtr)) {
265 ++CurPtr;
266 while (*CurPtr == '_' || isalnum(*CurPtr))
267 ++CurPtr;
268 *BeginOfToken = BeginOfSymbol;
269 *EndOfToken = CurPtr;
270 return tgpptoken_symbol;
271 }
272
273 else if (*CurPtr == '+' || *CurPtr == '-' || isdigit(*CurPtr)) {
274 ++CurPtr;
275 while (isdigit(*CurPtr))
276 ++CurPtr;
277 *BeginOfToken = BeginOfSymbol;
278 *EndOfToken = CurPtr;
279 return tgpptoken_symbol;
280 }
281
282 else {
283 PrintError(BeginOfSymbol, "Unrecognizable token");
284 return tgpptoken_error;
285 }
286 }
287
288 else if (*CurPtr == '#') {
289 if (IsBeginOfLine &&
290 (MatchPrefix("for", CurPtr + 1) ||
291 MatchPrefix("end", CurPtr + 1))) {
292 ++CurPtr;
293 IsInsideMacroStatement = true;
294 return NextToken(BeginOfToken, EndOfToken);
295 }
296
297 // special token #"# is translate to literal "
298 else if (CurPtr[1] == '"' && CurPtr[2] == '#') {
299 *BeginOfToken = ++CurPtr;
300 *EndOfToken = ++CurPtr;
301 ++CurPtr;
302 return tgpptoken_literal;
303 }
304
305 else {
306 const char *BeginOfVar = ++CurPtr; // trim '#'
307 if (*CurPtr != '_' && !isalpha(*CurPtr)) {
308 PrintError(BeginOfVar, "Variable must start with [_A-Za-z]: ");
309 return tgpptoken_error;
310 }
311 while (*CurPtr == '_' || isalnum(*CurPtr))
312 ++CurPtr;
313 if (*CurPtr != '#') {
314 PrintError(BeginOfVar, "Variable must end with #");
315 return tgpptoken_error;
316 }
317 *BeginOfToken = BeginOfVar;
318 *EndOfToken = CurPtr++; // trim '#'
319 return tgpptoken_symbol;
320 }
321 }
322
323 const char *BeginOfLiteral = CurPtr;
324 int CCommentLevel = 0;
325 bool BCPLComment = false;
326 bool StringLiteral = false;
327 for (; !IsEndOfBuffer(CurPtr); ++CurPtr) {
328 if (CCommentLevel > 0) {
329 if (CurPtr[0] == '/' && CurPtr[1] == '*') {
330 ++CurPtr;
331 ++CCommentLevel;
332 } else if (CurPtr[0] == '*' && CurPtr[1] == '/') {
333 ++CurPtr;
334 --CCommentLevel;
335 } else if (IsNewLine())
336 WasEndOfLine = true;
337 }
338
339 else if (BCPLComment) {
340 if (IsNewLine()) {
341 WasEndOfLine = true;
342 BCPLComment = false;
343 }
344 }
345
346 else if (StringLiteral) {
347 // no string escape sequence in TableGen?
348 if (*CurPtr == '"')
349 StringLiteral = false;
350 }
351
352 else if (CurPtr[0] == '/' && CurPtr[1] == '*') {
353 ++CurPtr;
354 ++CCommentLevel;
355 }
356
357 else if (CurPtr[0] == '/' && CurPtr[1] == '/') {
358 ++CurPtr;
359 BCPLComment = true;
360 }
361
362 else if (*CurPtr == '"')
363 StringLiteral = true;
364
365 else if (IsNewLine()) {
366 ++CurPtr;
367 WasEndOfLine = true;
368 break;
369 }
370
371 else if (*CurPtr == '#')
372 break;
373 }
374
375 *BeginOfToken = BeginOfLiteral;
376 *EndOfToken = CurPtr;
377 return tgpptoken_literal;
378 }
379
380 bool TGPPRecord::
381 EvaluateFor(const TGPPEnvironment &Env, raw_fd_ostream &OS) const {
382 std::vector::const_iterator ri, re;
383
384 // calculate the min size
385 ri = IndexRanges.begin();
386 re = IndexRanges.begin();
387 size_t n = ri->size();
388 for (; ri != re; ++ri) {
389 size_t m = ri->size();
390 if (m < n)
391 n = m;
392 }
393
394 for (size_t which_val = 0; which_val < n; ++which_val) {
395 // construct nested environment
396 TGPPEnvironment NestedEnv(Env);
397 std::vector::const_iterator vi = IndexVars.begin();
398 for (ri = IndexRanges.begin(), re = IndexRanges.end();
399 ri != re; ++vi, ++ri) {
400 NestedEnv.insert(std::make_pair(*vi, ri->at(which_val)));
401 }
402 // evalute loop body
403 for (TGPPRecords::const_iterator i = LoopBody.begin(), e = LoopBody.end();
404 i != e; ++i)
405 if (i->Evaluate(NestedEnv, OS))
406 return true;
407 }
408
409 return false;
410 }
411
412 bool TGPPRecord::
413 Evaluate(const TGPPEnvironment &Env, raw_fd_ostream &OS) const {
414 switch (Kind) {
415 case tgpprecord_for:
416 return EvaluateFor(Env, OS);
417 case tgpprecord_variable:
418 return EvaluateVariable(Env, OS);
419 case tgpprecord_literal:
420 return EvaluateLiteral(Env, OS);
421 default:
422 PrintError("Unknown kind of record: " + Kind);
423 return true;
424 }
425 return false;
426 }
427
428 bool TGPreprocessor::ParseBlock(bool TopLevel) {
429 TGPPTokenKind Kind;
430 const char *BeginOfToken, *EndOfToken;
431 while ((Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken)) !=
432 tgpptoken_end) {
433 std::string Symbol(BeginOfToken, EndOfToken);
434 switch (Kind) {
435 case tgpptoken_symbol:
436 if (Symbol == "for") {
437 if (ParseForLoop())
438 return true;
439 } else if (Symbol == "end") {
440 if (TopLevel) {
441 PrintError(BeginOfToken, "No block to end here");
442 return true;
443 }
444 if ((Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken)) !=
445 tgpptoken_newline) {
446 PrintError(BeginOfToken, "Tokens after #end");
447 return true;
448 }
449 return false;
450 } else if (Symbol == "NAME") {
451 // treat '#NAME#' as a literal
452 CurRecords->push_back(
453 TGPPRecord(tgpprecord_literal,
454 std::string("#NAME#")));
455 } else {
456 CurRecords->push_back(
457 TGPPRecord(tgpprecord_variable,
458 std::string(BeginOfToken, EndOfToken)));
459 }
460 break;
461 case tgpptoken_literal:
462 CurRecords->push_back(
463 TGPPRecord(tgpprecord_literal,
464 std::string(BeginOfToken, EndOfToken)));
465 break;
466 default:
467 return true;
468 }
469 }
470 return false;
471 }
472
473 bool TGPreprocessor::ParseForLoop() {
474 TGPPRecord ForLoopRecord(tgpprecord_for);
475
476 for (;;) {
477 TGPPTokenKind Kind;
478 const char *BeginOfToken, *EndOfToken;
479
480 Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken);
481 if (!MatchIdentifier(Kind, BeginOfToken, EndOfToken)) {
482 PrintError(BeginOfToken, "Not an identifier");
483 return true;
484 }
485 std::string IndexVar(BeginOfToken, EndOfToken);
486
487 Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken);
488 if (!MatchSymbol(Kind, BeginOfToken, EndOfToken, '=')) {
489 PrintError(BeginOfToken, "Need a '=' here");
490 return true;
491 }
492
493 TGPPRange Range;
494 if (ParseRange(&Range))
495 return true;
496 ForLoopRecord.AppendIndex(IndexVar, Range);
497
498 Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken);
499 if (Kind == tgpptoken_newline)
500 break;
501 if (!MatchSymbol(Kind, BeginOfToken, EndOfToken, ',')) {
502 PrintError(BeginOfToken, "Need a ',' here");
503 return true;
504 }
505 }
506
507 // open a new level
508 TGPPRecords *LastCurRecords = CurRecords;
509 CurRecords = ForLoopRecord.GetLoopBody();
510
511 if (ParseBlock(false))
512 return true;
513
514 CurRecords = LastCurRecords;
515 CurRecords->push_back(ForLoopRecord);
516 return false;
517 }
518
519 bool TGPreprocessor::ParseRange(TGPPRange *Range) {
520 TGPPTokenKind Kind;
521 const char *BeginOfToken, *EndOfToken;
522
523 Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken);
524
525 if (MatchSymbol(Kind, BeginOfToken, EndOfToken, '[')) {
526 for (;;) {
527 Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken);
528 if (!MatchIdNum(Kind, BeginOfToken, EndOfToken)) {
529 PrintError(BeginOfToken, "Need a identifier or a number here");
530 return true;
531 }
532 Range->push_back(std::string(BeginOfToken, EndOfToken));
533
534 Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken);
535 if (MatchSymbol(Kind, BeginOfToken, EndOfToken, ']'))
536 break;
537 if (!MatchSymbol(Kind, BeginOfToken, EndOfToken, ',')) {
538 PrintError(BeginOfToken, "Need a comma here");
539 return true;
540 }
541 }
542 return false;
543 }
544
545 else if (MatchSymbol(Kind, BeginOfToken, EndOfToken, "sequence")) {
546 long int from, to;
547
548 Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken);
549 if (!MatchSymbol(Kind, BeginOfToken, EndOfToken, '(')) {
550 PrintError(BeginOfToken, "Need a left parentheses here");
551 return true;
552 }
553
554 Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken);
555 if (!MatchNumber(Kind, BeginOfToken, EndOfToken, &from)) {
556 PrintError(BeginOfToken, "Not a number");
557 return true;
558 }
559
560 Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken);
561 if (!MatchSymbol(Kind, BeginOfToken, EndOfToken, ',')) {
562 PrintError(BeginOfToken, "Need a comma here");
563 return true;
564 }
565
566 Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken);
567 if (!MatchNumber(Kind, BeginOfToken, EndOfToken, &to)) {
568 PrintError(BeginOfToken, "Not a number");
569 return true;
570 }
571
572 Kind = Lexer->NextToken(&BeginOfToken, &EndOfToken);
573 if (!MatchSymbol(Kind, BeginOfToken, EndOfToken, ')')) {
574 PrintError(BeginOfToken, "Need a right parentheses here");
575 return true;
576 }
577
578 *Range = TGPPRange(from, to);
579 return false;
580 }
581
582 PrintError(BeginOfToken, "illegal range of loop index");
583 return true;
584 }
585
586 bool TGPreprocessor::PreprocessFile() {
587 TGPPLexer TheLexer(SrcMgr);
588 TGPPRecords TopLevelRecords;
589
590 Lexer = &TheLexer;
591 CurRecords = &TopLevelRecords;
592 if (ParseBlock(true))
593 return true;
594
595 TGPPEnvironment Env;
596 for (TGPPRecords::const_iterator i = TopLevelRecords.begin(),
597 e = TopLevelRecords.end();
598 i != e; ++i)
599 if (i->Evaluate(Env, Out.os()))
600 return true;
601
602 return false;
603 }
+0
-52
lib/TableGen/TGPreprocessor.h less more
None //===- TGPreprocessor.h - Preprocessor for TableGen Files -------*- 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 class represents the Preprocessor for tablegen files.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef TGPREPROCESSOR_H
14 #define TGPREPROCESSOR_H
15
16 #include
17
18 namespace llvm {
19 class MemoryBuffer;
20 class SourceMgr;
21 class tool_output_file;
22
23 class TGPPLexer;
24 class TGPPRange;
25 class TGPPRecord;
26
27 typedef std::vector TGPPRecords;
28
29 class TGPreprocessor {
30 SourceMgr &SrcMgr;
31 tool_output_file &Out;
32
33 TGPPLexer *Lexer;
34 TGPPRecords *CurRecords;
35
36 bool ParseBlock(bool TopLevel);
37 bool ParseForLoop();
38 bool ParseRange(TGPPRange *Range);
39
40 public:
41 TGPreprocessor(SourceMgr &SM, tool_output_file &O)
42 : SrcMgr(SM), Out(O), Lexer(0), CurRecords(0) {
43 }
44
45 /// PreprocessFile - Main entrypoint for preprocess a tblgen file. These
46 /// preprocess routines return true on error, or false on success.
47 bool PreprocessFile();
48 };
49 } // namespace llvm
50
51 #endif /* TGPREPROCESSOR_H */