llvm.org GIT mirror llvm / ecbdcf2
Rename LLVMCCConfigurationEmitter to LLVMCConfigurationEmitter git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50748 91177308-0d34-0410-b5e6-96231b3b80d8 Mikhail Glushenkov 11 years ago
5 changed file(s) with 1161 addition(s) and 1161 deletion(s). Raw diff Collapse all Expand all
+0
-1126
utils/TableGen/LLVMCCConfigurationEmitter.cpp less more
None //===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config --------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open
5 // Source License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend is responsible for emitting LLVMC configuration code.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "LLVMCCConfigurationEmitter.h"
14 #include "Record.h"
15
16 #include "llvm/ADT/IntrusiveRefCntPtr.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/Support/Streams.h"
21
22 #include
23 #include
24 #include
25 #include
26
27 using namespace llvm;
28
29 //namespace {
30
31 //===----------------------------------------------------------------------===//
32 /// Typedefs
33
34 typedef std::vector RecordVector;
35 typedef std::vector StrVector;
36
37 //===----------------------------------------------------------------------===//
38 /// Constants
39
40 // Indentation strings
41 const char * Indent1 = " ";
42 const char * Indent2 = " ";
43 const char * Indent3 = " ";
44 const char * Indent4 = " ";
45
46 // Default help string
47 const char * DefaultHelpString = "NO HELP MESSAGE PROVIDED";
48
49 // Name for the "sink" option
50 const char * SinkOptionName = "AutoGeneratedSinkOption";
51
52 //===----------------------------------------------------------------------===//
53 /// Helper functions
54
55 std::string InitPtrToString(Init* ptr) {
56 StringInit& val = dynamic_cast(*ptr);
57 return val.getValue();
58 }
59
60 // Ensure that the number of args in d is <= min_arguments,
61 // throw exception otherwise
62 void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) {
63 if (d->getNumArgs() < min_arguments)
64 throw "Property " + d->getOperator()->getAsString()
65 + " has too few arguments!";
66 }
67
68
69 //===----------------------------------------------------------------------===//
70 /// Back-end specific code
71
72 // A command-line option can have one of the following types:
73 //
74 // Switch - a simple switch w/o arguments, e.g. -O2
75 //
76 // Parameter - an option that takes one(and only one) argument, e.g. -o file,
77 // --output=file
78 //
79 // ParameterList - same as Parameter, but more than one occurence
80 // of the option is allowed, e.g. -lm -lpthread
81 //
82 // Prefix - argument is everything after the prefix,
83 // e.g. -Wa,-foo,-bar, -DNAME=VALUE
84 //
85 // PrefixList - same as Prefix, but more than one option occurence is
86 // allowed
87
88 namespace OptionType {
89 enum OptionType { Switch, Parameter, ParameterList, Prefix, PrefixList};
90 }
91
92 bool IsListOptionType (OptionType::OptionType t) {
93 return (t == OptionType::ParameterList || t == OptionType::PrefixList);
94 }
95
96 // Code duplication here is necessary because one option can affect
97 // several tools and those tools may have different actions associated
98 // with this option. GlobalOptionDescriptions are used to generate
99 // the option registration code, while ToolOptionDescriptions are used
100 // to generate tool-specific code.
101
102 // Base class for option descriptions
103
104 struct OptionDescription {
105 OptionType::OptionType Type;
106 std::string Name;
107
108 OptionDescription(OptionType::OptionType t = OptionType::Switch,
109 const std::string& n = "")
110 : Type(t), Name(n)
111 {}
112
113 const char* GenTypeDeclaration() const {
114 switch (Type) {
115 case OptionType::PrefixList:
116 case OptionType::ParameterList:
117 return "cl::list";
118 case OptionType::Switch:
119 return "cl::opt";
120 case OptionType::Parameter:
121 case OptionType::Prefix:
122 default:
123 return "cl::opt";
124 }
125 }
126
127 std::string GenVariableName() const {
128 switch (Type) {
129 case OptionType::Switch:
130 return "AutoGeneratedSwitch" + Name;
131 case OptionType::Prefix:
132 return "AutoGeneratedPrefix" + Name;
133 case OptionType::PrefixList:
134 return "AutoGeneratedPrefixList" + Name;
135 case OptionType::Parameter:
136 return "AutoGeneratedParameter" + Name;
137 case OptionType::ParameterList:
138 default:
139 return "AutoGeneratedParameterList" + Name;
140 }
141 }
142
143 };
144
145 // Global option description
146
147 namespace GlobalOptionDescriptionFlags {
148 enum GlobalOptionDescriptionFlags { Required = 0x1 };
149 }
150
151 struct GlobalOptionDescription : public OptionDescription {
152 std::string Help;
153 unsigned Flags;
154
155 // We need t provide a default constructor since
156 // StringMap can only store DefaultConstructible objects
157 GlobalOptionDescription() : OptionDescription(), Flags(0)
158 {}
159
160 GlobalOptionDescription (OptionType::OptionType t, const std::string& n)
161 : OptionDescription(t, n), Help(DefaultHelpString), Flags(0)
162 {}
163
164 bool isRequired() const {
165 return Flags & GlobalOptionDescriptionFlags::Required;
166 }
167 void setRequired() {
168 Flags |= GlobalOptionDescriptionFlags::Required;
169 }
170
171 // Merge two option descriptions
172 void Merge (const GlobalOptionDescription& other)
173 {
174 if (other.Type != Type)
175 throw "Conflicting definitions for the option " + Name + "!";
176
177 if (Help.empty() && !other.Help.empty())
178 Help = other.Help;
179 else if (!Help.empty() && !other.Help.empty())
180 cerr << "Warning: more than one help string defined for option "
181 + Name + "\n";
182
183 Flags |= other.Flags;
184 }
185 };
186
187 // A GlobalOptionDescription array
188 // + some flags affecting generation of option declarations
189 struct GlobalOptionDescriptions {
190 typedef StringMap container_type;
191 typedef container_type::const_iterator const_iterator;
192
193 // A list of GlobalOptionDescriptions
194 container_type Descriptions;
195 // Should the emitter generate a "cl::sink" option?
196 bool HasSink;
197
198 const GlobalOptionDescription& FindOption(const std::string& OptName) const {
199 const_iterator I = Descriptions.find(OptName);
200 if (I != Descriptions.end())
201 return I->second;
202 else
203 throw OptName + ": no such option!";
204 }
205
206 // Support for STL-style iteration
207 const_iterator begin() const { return Descriptions.begin(); }
208 const_iterator end() const { return Descriptions.end(); }
209 };
210
211
212 // Tool-local option description
213
214 // Properties without arguments are implemented as flags
215 namespace ToolOptionDescriptionFlags {
216 enum ToolOptionDescriptionFlags { StopCompilation = 0x1,
217 Forward = 0x2, UnpackValues = 0x4};
218 }
219 namespace OptionPropertyType {
220 enum OptionPropertyType { AppendCmd };
221 }
222
223 typedef std::pair
224 OptionProperty;
225 typedef SmallVector OptionPropertyList;
226
227 struct ToolOptionDescription : public OptionDescription {
228 unsigned Flags;
229 OptionPropertyList Props;
230
231 // StringMap can only store DefaultConstructible objects
232 ToolOptionDescription() : OptionDescription(), Flags(0) {}
233
234 ToolOptionDescription (OptionType::OptionType t, const std::string& n)
235 : OptionDescription(t, n)
236 {}
237
238 // Various boolean properties
239 bool isStopCompilation() const {
240 return Flags & ToolOptionDescriptionFlags::StopCompilation;
241 }
242 void setStopCompilation() {
243 Flags |= ToolOptionDescriptionFlags::StopCompilation;
244 }
245
246 bool isForward() const {
247 return Flags & ToolOptionDescriptionFlags::Forward;
248 }
249 void setForward() {
250 Flags |= ToolOptionDescriptionFlags::Forward;
251 }
252
253 bool isUnpackValues() const {
254 return Flags & ToolOptionDescriptionFlags::UnpackValues;
255 }
256 void setUnpackValues() {
257 Flags |= ToolOptionDescriptionFlags::UnpackValues;
258 }
259
260 void AddProperty (OptionPropertyType::OptionPropertyType t,
261 const std::string& val)
262 {
263 Props.push_back(std::make_pair(t, val));
264 }
265 };
266
267 typedef StringMap ToolOptionDescriptions;
268
269 // Tool information record
270
271 namespace ToolFlags {
272 enum ToolFlags { Join = 0x1, Sink = 0x2 };
273 }
274
275 struct ToolProperties : public RefCountedBase {
276 std::string Name;
277 StrVector CmdLine;
278 std::string InLanguage;
279 std::string OutLanguage;
280 std::string OutputSuffix;
281 unsigned Flags;
282 ToolOptionDescriptions OptDescs;
283
284 // Various boolean properties
285 void setSink() { Flags |= ToolFlags::Sink; }
286 bool isSink() const { return Flags & ToolFlags::Sink; }
287 void setJoin() { Flags |= ToolFlags::Join; }
288 bool isJoin() const { return Flags & ToolFlags::Join; }
289
290 // Default ctor here is needed because StringMap can only store
291 // DefaultConstructible objects
292 ToolProperties() {}
293 ToolProperties (const std::string& n) : Name(n) {}
294 };
295
296
297 // A list of Tool information records
298 // IntrusiveRefCntPtrs are used because StringMap has no copy constructor
299 // (and we want to avoid copying ToolProperties anyway)
300 typedef std::vector > ToolPropertiesList;
301
302
303 // Function object for iterating over a list of tool property records
304 class CollectProperties {
305 private:
306
307 /// Implementation details
308
309 // "Property handler" - a function that extracts information
310 // about a given tool property from its DAG representation
311 typedef void (CollectProperties::*PropertyHandler)(DagInit*);
312
313 // Map from property names -> property handlers
314 typedef StringMap PropertyHandlerMap;
315
316 // "Option property handler" - a function that extracts information
317 // about a given option property from its DAG representation
318 typedef void (CollectProperties::*
319 OptionPropertyHandler)(DagInit*, GlobalOptionDescription &);
320
321 // Map from option property names -> option property handlers
322 typedef StringMap OptionPropertyHandlerMap;
323
324 // Static maps from strings to CollectProperties methods("handlers")
325 static PropertyHandlerMap propertyHandlers_;
326 static OptionPropertyHandlerMap optionPropertyHandlers_;
327 static bool staticMembersInitialized_;
328
329
330 /// This is where the information is stored
331
332 // Current Tool properties
333 ToolProperties& toolProps_;
334 // OptionDescriptions table(used to register options globally)
335 GlobalOptionDescriptions& optDescs_;
336
337 public:
338
339 explicit CollectProperties (ToolProperties& p, GlobalOptionDescriptions& d)
340 : toolProps_(p), optDescs_(d)
341 {
342 if (!staticMembersInitialized_) {
343 // Init tool property handlers
344 propertyHandlers_["cmd_line"] = &CollectProperties::onCmdLine;
345 propertyHandlers_["in_language"] = &CollectProperties::onInLanguage;
346 propertyHandlers_["join"] = &CollectProperties::onJoin;
347 propertyHandlers_["out_language"] = &CollectProperties::onOutLanguage;
348 propertyHandlers_["output_suffix"] = &CollectProperties::onOutputSuffix;
349 propertyHandlers_["parameter_option"]
350 = &CollectProperties::onParameter;
351 propertyHandlers_["parameter_list_option"] =
352 &CollectProperties::onParameterList;
353 propertyHandlers_["prefix_option"] = &CollectProperties::onPrefix;
354 propertyHandlers_["prefix_list_option"] =
355 &CollectProperties::onPrefixList;
356 propertyHandlers_["sink"] = &CollectProperties::onSink;
357 propertyHandlers_["switch_option"] = &CollectProperties::onSwitch;
358
359 // Init option property handlers
360 optionPropertyHandlers_["append_cmd"] = &CollectProperties::onAppendCmd;
361 optionPropertyHandlers_["forward"] = &CollectProperties::onForward;
362 optionPropertyHandlers_["help"] = &CollectProperties::onHelp;
363 optionPropertyHandlers_["required"] = &CollectProperties::onRequired;
364 optionPropertyHandlers_["stop_compilation"] =
365 &CollectProperties::onStopCompilation;
366 optionPropertyHandlers_["unpack_values"] =
367 &CollectProperties::onUnpackValues;
368
369 staticMembersInitialized_ = true;
370 }
371 }
372
373 // Gets called for every tool property;
374 // Just forwards to the corresponding property handler.
375 void operator() (Init* i) {
376 DagInit& d = dynamic_cast(*i);
377 const std::string& property_name = d.getOperator()->getAsString();
378 PropertyHandlerMap::iterator method
379 = propertyHandlers_.find(property_name);
380
381 if (method != propertyHandlers_.end()) {
382 PropertyHandler h = method->second;
383 (this->*h)(&d);
384 }
385 else {
386 throw "Unknown tool property: " + property_name + "!";
387 }
388 }
389
390 private:
391
392 /// Property handlers --
393 /// Functions that extract information about tool properties from
394 /// DAG representation.
395
396 void onCmdLine (DagInit* d) {
397 checkNumberOfArguments(d, 1);
398 SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine);
399 if (toolProps_.CmdLine.empty())
400 throw "Tool " + toolProps_.Name + " has empty command line!";
401 }
402
403 void onInLanguage (DagInit* d) {
404 checkNumberOfArguments(d, 1);
405 toolProps_.InLanguage = InitPtrToString(d->getArg(0));
406 }
407
408 void onJoin (DagInit* d) {
409 checkNumberOfArguments(d, 0);
410 toolProps_.setJoin();
411 }
412
413 void onOutLanguage (DagInit* d) {
414 checkNumberOfArguments(d, 1);
415 toolProps_.OutLanguage = InitPtrToString(d->getArg(0));
416 }
417
418 void onOutputSuffix (DagInit* d) {
419 checkNumberOfArguments(d, 1);
420 toolProps_.OutputSuffix = InitPtrToString(d->getArg(0));
421 }
422
423 void onSink (DagInit* d) {
424 checkNumberOfArguments(d, 0);
425 optDescs_.HasSink = true;
426 toolProps_.setSink();
427 }
428
429 void onSwitch (DagInit* d) { addOption(d, OptionType::Switch); }
430 void onParameter (DagInit* d) { addOption(d, OptionType::Parameter); }
431 void onParameterList (DagInit* d) { addOption(d, OptionType::ParameterList); }
432 void onPrefix (DagInit* d) { addOption(d, OptionType::Prefix); }
433 void onPrefixList (DagInit* d) { addOption(d, OptionType::PrefixList); }
434
435 /// Option property handlers --
436 /// Methods that handle properties that are common for all types of
437 /// options (like append_cmd, stop_compilation)
438
439 void onAppendCmd (DagInit* d, GlobalOptionDescription& o) {
440 checkNumberOfArguments(d, 1);
441 std::string const& cmd = InitPtrToString(d->getArg(0));
442
443 toolProps_.OptDescs[o.Name].AddProperty(OptionPropertyType::AppendCmd, cmd);
444 }
445
446 void onForward (DagInit* d, GlobalOptionDescription& o) {
447 checkNumberOfArguments(d, 0);
448 toolProps_.OptDescs[o.Name].setForward();
449 }
450
451 void onHelp (DagInit* d, GlobalOptionDescription& o) {
452 checkNumberOfArguments(d, 1);
453 const std::string& help_message = InitPtrToString(d->getArg(0));
454
455 o.Help = help_message;
456 }
457
458 void onRequired (DagInit* d, GlobalOptionDescription& o) {
459 checkNumberOfArguments(d, 0);
460 o.setRequired();
461 }
462
463 void onStopCompilation (DagInit* d, GlobalOptionDescription& o) {
464 checkNumberOfArguments(d, 0);
465 if (o.Type != OptionType::Switch)
466 throw std::string("Only options of type Switch can stop compilation!");
467 toolProps_.OptDescs[o.Name].setStopCompilation();
468 }
469
470 void onUnpackValues (DagInit* d, GlobalOptionDescription& o) {
471 checkNumberOfArguments(d, 0);
472 toolProps_.OptDescs[o.Name].setUnpackValues();
473 }
474
475 /// Helper functions
476
477 // Add an option of type t
478 void addOption (DagInit* d, OptionType::OptionType t) {
479 checkNumberOfArguments(d, 2);
480 const std::string& name = InitPtrToString(d->getArg(0));
481
482 GlobalOptionDescription o(t, name);
483 toolProps_.OptDescs[name].Type = t;
484 toolProps_.OptDescs[name].Name = name;
485 processOptionProperties(d, o);
486 insertDescription(o);
487 }
488
489 // Insert new GlobalOptionDescription into GlobalOptionDescriptions list
490 void insertDescription (const GlobalOptionDescription& o)
491 {
492 if (optDescs_.Descriptions.count(o.Name)) {
493 GlobalOptionDescription& D = optDescs_.Descriptions[o.Name];
494 D.Merge(o);
495 }
496 else {
497 optDescs_.Descriptions[o.Name] = o;
498 }
499 }
500
501 // Go through the list of option properties and call a corresponding
502 // handler for each.
503 //
504 // Parameters:
505 // name - option name
506 // d - option property list
507 void processOptionProperties (DagInit* d, GlobalOptionDescription& o) {
508 // First argument is option name
509 checkNumberOfArguments(d, 2);
510
511 for (unsigned B = 1, E = d->getNumArgs(); B!=E; ++B) {
512 DagInit& option_property
513 = dynamic_cast(*d->getArg(B));
514 const std::string& option_property_name
515 = option_property.getOperator()->getAsString();
516 OptionPropertyHandlerMap::iterator method
517 = optionPropertyHandlers_.find(option_property_name);
518
519 if (method != optionPropertyHandlers_.end()) {
520 OptionPropertyHandler h = method->second;
521 (this->*h)(&option_property, o);
522 }
523 else {
524 throw "Unknown option property: " + option_property_name + "!";
525 }
526 }
527 }
528 };
529
530 // Static members of CollectProperties
531 CollectProperties::PropertyHandlerMap
532 CollectProperties::propertyHandlers_;
533
534 CollectProperties::OptionPropertyHandlerMap
535 CollectProperties::optionPropertyHandlers_;
536
537 bool CollectProperties::staticMembersInitialized_ = false;
538
539
540 // Gather information from the parsed TableGen data
541 // (Basically a wrapper for CollectProperties)
542 void CollectToolProperties (RecordVector::const_iterator B,
543 RecordVector::const_iterator E,
544 ToolPropertiesList& TPList,
545 GlobalOptionDescriptions& OptDescs)
546 {
547 // Iterate over a properties list of every Tool definition
548 for (;B!=E;++B) {
549 RecordVector::value_type T = *B;
550 ListInit* PropList = T->getValueAsListInit("properties");
551
552 IntrusiveRefCntPtr
553 ToolProps(new ToolProperties(T->getName()));
554
555 std::for_each(PropList->begin(), PropList->end(),
556 CollectProperties(*ToolProps, OptDescs));
557 TPList.push_back(ToolProps);
558 }
559 }
560
561 // Used by EmitGenerateActionMethod
562 void EmitOptionPropertyHandlingCode (const ToolProperties& P,
563 const ToolOptionDescription& D,
564 std::ostream& O)
565 {
566 // if clause
567 O << Indent2 << "if (";
568 if (D.Type == OptionType::Switch)
569 O << D.GenVariableName();
570 else
571 O << '!' << D.GenVariableName() << ".empty()";
572
573 O <<") {\n";
574
575 // Handle option properties that take an argument
576 for (OptionPropertyList::const_iterator B = D.Props.begin(),
577 E = D.Props.end(); B!=E; ++B) {
578 const OptionProperty& val = *B;
579
580 switch (val.first) {
581 // (append_cmd cmd) property
582 case OptionPropertyType::AppendCmd:
583 O << Indent3 << "vec.push_back(\"" << val.second << "\");\n";
584 break;
585 // Other properties with argument
586 default:
587 break;
588 }
589 }
590
591 // Handle flags
592
593 // (forward) property
594 if (D.isForward()) {
595 switch (D.Type) {
596 case OptionType::Switch:
597 O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
598 break;
599 case OptionType::Parameter:
600 O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
601 O << Indent3 << "vec.push_back(" << D.GenVariableName() << ");\n";
602 break;
603 case OptionType::Prefix:
604 O << Indent3 << "vec.push_back(\"-" << D.Name << "\" + "
605 << D.GenVariableName() << ");\n";
606 break;
607 case OptionType::PrefixList:
608 O << Indent3 << "for (" << D.GenTypeDeclaration()
609 << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
610 << Indent3 << "E = " << D.GenVariableName() << ".end(); B != E; ++B)\n"
611 << Indent4 << "vec.push_back(\"-" << D.Name << "\" + "
612 << "*B);\n";
613 break;
614 case OptionType::ParameterList:
615 O << Indent3 << "for (" << D.GenTypeDeclaration()
616 << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
617 << Indent3 << "E = " << D.GenVariableName()
618 << ".end() ; B != E; ++B) {\n"
619 << Indent4 << "vec.push_back(\"-" << D.Name << "\");\n"
620 << Indent4 << "vec.push_back(*B);\n"
621 << Indent3 << "}\n";
622 break;
623 }
624 }
625
626 // (unpack_values) property
627 if (D.isUnpackValues()) {
628 if (IsListOptionType(D.Type)) {
629 O << Indent3 << "for (" << D.GenTypeDeclaration()
630 << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
631 << Indent3 << "E = " << D.GenVariableName()
632 << ".end(); B != E; ++B)\n"
633 << Indent4 << "Tool::UnpackValues(*B, vec);\n";
634 }
635 else if (D.Type == OptionType::Prefix || D.Type == OptionType::Parameter){
636 O << Indent3 << "Tool::UnpackValues("
637 << D.GenVariableName() << ", vec);\n";
638 }
639 else {
640 // TOFIX: move this to the type-checking phase
641 throw std::string("Switches can't have unpack_values property!");
642 }
643 }
644
645 // close if clause
646 O << Indent2 << "}\n";
647 }
648
649 // Emite one of two versions of GenerateAction method
650 void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O)
651 {
652 assert(V==1 || V==2);
653 if (V==1)
654 O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n";
655 else
656 O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n";
657
658 O << Indent2 << "const sys::Path& outFile) const\n"
659 << Indent1 << "{\n"
660 << Indent2 << "std::vector vec;\n";
661
662 // Parse CmdLine tool property
663 if(P.CmdLine.empty())
664 throw "Tool " + P.Name + " has empty command line!";
665
666 StrVector::const_iterator I = P.CmdLine.begin();
667 ++I;
668 for (StrVector::const_iterator E = P.CmdLine.end(); I != E; ++I) {
669 const std::string& cmd = *I;
670 O << Indent2;
671 if (cmd == "$INFILE") {
672 if (V==1)
673 O << "for (PathVector::const_iterator B = inFiles.begin()"
674 << ", E = inFiles.end();\n"
675 << Indent2 << "B != E; ++B)\n"
676 << Indent3 << "vec.push_back(B->toString());\n";
677 else
678 O << "vec.push_back(inFile.toString());\n";
679 }
680 else if (cmd == "$OUTFILE") {
681 O << "vec.push_back(outFile.toString());\n";
682 }
683 else {
684 O << "vec.push_back(\"" << cmd << "\");\n";
685 }
686 }
687
688 // For every understood option, emit handling code
689 for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(),
690 E = P.OptDescs.end(); B != E; ++B) {
691 const ToolOptionDescription& val = B->second;
692 EmitOptionPropertyHandlingCode(P, val, O);
693 }
694
695 // Handle Sink property
696 if (P.isSink()) {
697 O << Indent2 << "if (!" << SinkOptionName << ".empty()) {\n"
698 << Indent3 << "vec.insert(vec.end(), "
699 << SinkOptionName << ".begin(), " << SinkOptionName << ".end());\n"
700 << Indent2 << "}\n";
701 }
702
703 O << Indent2 << "return Action(\"" << P.CmdLine.at(0) << "\", vec);\n"
704 << Indent1 << "}\n\n";
705 }
706
707 // Emit GenerateAction methods for Tool classes
708 void EmitGenerateActionMethods (const ToolProperties& P, std::ostream& O) {
709
710 if (!P.isJoin())
711 O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"
712 << Indent2 << "const llvm::sys::Path& outFile) const\n"
713 << Indent1 << "{\n"
714 << Indent2 << "throw std::runtime_error(\"" << P.Name
715 << " is not a Join tool!\");\n"
716 << Indent1 << "}\n\n";
717 else
718 EmitGenerateActionMethod(P, 1, O);
719
720 EmitGenerateActionMethod(P, 2, O);
721 }
722
723 // Emit IsLast() method for Tool classes
724 void EmitIsLastMethod (const ToolProperties& P, std::ostream& O) {
725 O << Indent1 << "bool IsLast() const {\n"
726 << Indent2 << "bool last = false;\n";
727
728 for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(),
729 E = P.OptDescs.end(); B != E; ++B) {
730 const ToolOptionDescription& val = B->second;
731
732 if (val.isStopCompilation())
733 O << Indent2
734 << "if (" << val.GenVariableName()
735 << ")\n" << Indent3 << "last = true;\n";
736 }
737
738 O << Indent2 << "return last;\n"
739 << Indent1 << "}\n\n";
740 }
741
742 // Emit static [Input,Output]Language() methods for Tool classes
743 void EmitInOutLanguageMethods (const ToolProperties& P, std::ostream& O) {
744 O << Indent1 << "const char* InputLanguage() const {\n"
745 << Indent2 << "return \"" << P.InLanguage << "\";\n"
746 << Indent1 << "}\n\n";
747
748 O << Indent1 << "const char* OutputLanguage() const {\n"
749 << Indent2 << "return \"" << P.OutLanguage << "\";\n"
750 << Indent1 << "}\n\n";
751 }
752
753 // Emit static [Input,Output]Language() methods for Tool classes
754 void EmitOutputSuffixMethod (const ToolProperties& P, std::ostream& O) {
755 O << Indent1 << "const char* OutputSuffix() const {\n"
756 << Indent2 << "return \"" << P.OutputSuffix << "\";\n"
757 << Indent1 << "}\n\n";
758 }
759
760 // Emit static Name() method for Tool classes
761 void EmitNameMethod (const ToolProperties& P, std::ostream& O) {
762 O << Indent1 << "const char* Name() const {\n"
763 << Indent2 << "return \"" << P.Name << "\";\n"
764 << Indent1 << "}\n\n";
765 }
766
767 // Emit static Name() method for Tool classes
768 void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) {
769 O << Indent1 << "bool IsJoin() const {\n";
770 if (P.isJoin())
771 O << Indent2 << "return true;\n";
772 else
773 O << Indent2 << "return false;\n";
774 O << Indent1 << "}\n\n";
775 }
776
777 // Emit a Tool class definition
778 void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) {
779
780 if(P.Name == "root")
781 return;
782
783 // Header
784 O << "class " << P.Name << " : public ";
785 if (P.isJoin())
786 O << "JoinTool";
787 else
788 O << "Tool";
789 O << " {\npublic:\n";
790
791 EmitNameMethod(P, O);
792 EmitInOutLanguageMethods(P, O);
793 EmitOutputSuffixMethod(P, O);
794 EmitIsJoinMethod(P, O);
795 EmitGenerateActionMethods(P, O);
796 EmitIsLastMethod(P, O);
797
798 // Close class definition
799 O << "};\n\n";
800 }
801
802 // Iterate over a list of option descriptions and emit registration code
803 void EmitOptionDescriptions (const GlobalOptionDescriptions& descs,
804 std::ostream& O)
805 {
806 // Emit static cl::Option variables
807 for (GlobalOptionDescriptions::const_iterator B = descs.begin(),
808 E = descs.end(); B!=E; ++B) {
809 const GlobalOptionDescription& val = B->second;
810
811 O << val.GenTypeDeclaration() << ' '
812 << val.GenVariableName()
813 << "(\"" << val.Name << '\"';
814
815 if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
816 O << ", cl::Prefix";
817
818 if (val.isRequired()) {
819 switch (val.Type) {
820 case OptionType::PrefixList:
821 case OptionType::ParameterList:
822 O << ", cl::OneOrMore";
823 break;
824 default:
825 O << ", cl::Required";
826 }
827 }
828
829 O << ", cl::desc(\"" << val.Help << "\"));\n";
830 }
831
832 if (descs.HasSink)
833 O << "cl::list " << SinkOptionName << "(cl::Sink);\n";
834
835 O << '\n';
836 }
837
838 void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
839 {
840 // Get the relevant field out of RecordKeeper
841 Record* LangMapRecord = Records.getDef("LanguageMap");
842 if (!LangMapRecord)
843 throw std::string("Language map definition not found!");
844
845 ListInit* LangsToSuffixesList = LangMapRecord->getValueAsListInit("map");
846 if (!LangsToSuffixesList)
847 throw std::string("Error in the language map definition!");
848
849 // Generate code
850 O << "void llvmc::PopulateLanguageMap(LanguageMap& language_map) {\n";
851
852 for (unsigned i = 0; i < LangsToSuffixesList->size(); ++i) {
853 Record* LangToSuffixes = LangsToSuffixesList->getElementAsRecord(i);
854
855 const std::string& Lang = LangToSuffixes->getValueAsString("lang");
856 const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes");
857
858 for (unsigned i = 0; i < Suffixes->size(); ++i)
859 O << Indent1 << "language_map[\""
860 << InitPtrToString(Suffixes->getElement(i))
861 << "\"] = \"" << Lang << "\";\n";
862 }
863
864 O << "}\n\n";
865 }
866
867 // Fills in two tables that map tool names to (input, output) languages.
868 // Used by the typechecker.
869 void FillInToolToLang (const ToolPropertiesList& TPList,
870 StringMap& ToolToInLang,
871 StringMap& ToolToOutLang) {
872 for (ToolPropertiesList::const_iterator B = TPList.begin(), E = TPList.end();
873 B != E; ++B) {
874 const ToolProperties& P = *(*B);
875 ToolToInLang[P.Name] = P.InLanguage;
876 ToolToOutLang[P.Name] = P.OutLanguage;
877 }
878 }
879
880 // Check that all output and input language names match.
881 // TOFIX: check for cycles.
882 // TOFIX: check for multiple default edges.
883 void TypecheckGraph (Record* CompilationGraph,
884 const ToolPropertiesList& TPList) {
885 StringMap ToolToInLang;
886 StringMap ToolToOutLang;
887
888 FillInToolToLang(TPList, ToolToInLang, ToolToOutLang);
889 ListInit* edges = CompilationGraph->getValueAsListInit("edges");
890 StringMap::iterator IAE = ToolToInLang.end();
891 StringMap::iterator IBE = ToolToOutLang.end();
892
893 for (unsigned i = 0; i < edges->size(); ++i) {
894 Record* Edge = edges->getElementAsRecord(i);
895 Record* A = Edge->getValueAsDef("a");
896 Record* B = Edge->getValueAsDef("b");
897 StringMap::iterator IA = ToolToOutLang.find(A->getName());
898 StringMap::iterator IB = ToolToInLang.find(B->getName());
899 if(IA == IAE)
900 throw A->getName() + ": no such tool!";
901 if(IB == IBE)
902 throw B->getName() + ": no such tool!";
903 if(A->getName() != "root" && IA->second != IB->second)
904 throw "Edge " + A->getName() + "->" + B->getName()
905 + ": output->input language mismatch";
906 if(B->getName() == "root")
907 throw std::string("Edges back to the root are not allowed!");
908 }
909 }
910
911 // Helper function used by EmitEdgePropertyTest.
912 void EmitEdgePropertyTest1Arg(const DagInit& Prop,
913 const GlobalOptionDescriptions& OptDescs,
914 std::ostream& O) {
915 checkNumberOfArguments(&Prop, 1);
916 const std::string& OptName = InitPtrToString(Prop.getArg(0));
917 const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName);
918 if (OptDesc.Type != OptionType::Switch)
919 throw OptName + ": incorrect option type!";
920 O << OptDesc.GenVariableName();
921 }
922
923 // Helper function used by EmitEdgePropertyTest.
924 void EmitEdgePropertyTest2Args(const std::string& PropName,
925 const DagInit& Prop,
926 const GlobalOptionDescriptions& OptDescs,
927 std::ostream& O) {
928 checkNumberOfArguments(&Prop, 2);
929 const std::string& OptName = InitPtrToString(Prop.getArg(0));
930 const std::string& OptArg = InitPtrToString(Prop.getArg(1));
931 const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName);
932
933 if (PropName == "parameter_equals") {
934 if (OptDesc.Type != OptionType::Parameter
935 && OptDesc.Type != OptionType::Prefix)
936 throw OptName + ": incorrect option type!";
937 O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
938 }
939 else if (PropName == "element_in_list") {
940 if (OptDesc.Type != OptionType::ParameterList
941 && OptDesc.Type != OptionType::PrefixList)
942 throw OptName + ": incorrect option type!";
943 const std::string& VarName = OptDesc.GenVariableName();
944 O << "std::find(" << VarName << ".begin(),\n"
945 << Indent3 << VarName << ".end(), \""
946 << OptArg << "\") != " << VarName << ".end()";
947 }
948 else
949 throw PropName + ": unknown edge property!";
950 }
951
952 // Helper function used by EmitEdgeClass.
953 void EmitEdgePropertyTest(const std::string& PropName,
954 const DagInit& Prop,
955 const GlobalOptionDescriptions& OptDescs,
956 std::ostream& O) {
957 if (PropName == "switch_on")
958 EmitEdgePropertyTest1Arg(Prop, OptDescs, O);
959 else
960 EmitEdgePropertyTest2Args(PropName, Prop, OptDescs, O);
961 }
962
963 // Emit a single Edge* class.
964 void EmitEdgeClass(unsigned N, const std::string& Target,
965 ListInit* Props, const GlobalOptionDescriptions& OptDescs,
966 std::ostream& O) {
967 bool IsDefault = false;
968
969 // Class constructor.
970 O << "class Edge" << N << ": public Edge {\n"
971 << "public:\n"
972 << Indent1 << "Edge" << N << "() : Edge(\"" << Target
973 << "\") {}\n\n"
974
975 // Function isEnabled().
976 << Indent1 << "bool isEnabled() const {\n"
977 << Indent2 << "bool ret = false;\n";
978
979 for (size_t i = 0, PropsSize = Props->size(); i < PropsSize; ++i) {
980 const DagInit& Prop = dynamic_cast(*Props->getElement(i));
981 const std::string& PropName = Prop.getOperator()->getAsString();
982
983 if (PropName == "default")
984 IsDefault = true;
985
986 O << Indent2 << "if (ret || (";
987 if (PropName == "and") {
988 O << '(';
989 for (unsigned j = 0, NumArgs = Prop.getNumArgs(); j < NumArgs; ++j) {
990 const DagInit& InnerProp = dynamic_cast(*Prop.getArg(j));
991 const std::string& InnerPropName =
992 InnerProp.getOperator()->getAsString();
993 EmitEdgePropertyTest(InnerPropName, InnerProp, OptDescs, O);
994 if (j != NumArgs - 1)
995 O << ")\n" << Indent3 << " && (";
996 else
997 O << ')';
998 }
999 }
1000 else {
1001 EmitEdgePropertyTest(PropName, Prop, OptDescs, O);
1002 }
1003 O << "))\n" << Indent3 << "ret = true;\n";
1004 }
1005
1006 O << Indent2 << "return ret;\n"
1007 << Indent1 << "};\n\n"
1008
1009 // Function isDefault().
1010 << Indent1 << "bool isDefault() const { return ";
1011 if (IsDefault)
1012 O << "true";
1013 else
1014 O << "false";
1015 O <<"; }\n};\n\n";
1016 }
1017
1018 // Emit Edge* classes that represent graph edges.
1019 void EmitEdgeClasses (Record* CompilationGraph,
1020 const GlobalOptionDescriptions& OptDescs,
1021 std::ostream& O) {
1022 ListInit* edges = CompilationGraph->getValueAsListInit("edges");
1023
1024 for (unsigned i = 0; i < edges->size(); ++i) {
1025 Record* Edge = edges->getElementAsRecord(i);
1026 Record* B = Edge->getValueAsDef("b");
1027 ListInit* Props = Edge->getValueAsListInit("props");
1028
1029 if (Props->empty())
1030 continue;
1031
1032 EmitEdgeClass(i, B->getName(), Props, OptDescs, O);
1033 }
1034 }
1035
1036 void EmitPopulateCompilationGraph (Record* CompilationGraph,
1037 std::ostream& O)
1038 {
1039 ListInit* edges = CompilationGraph->getValueAsListInit("edges");
1040
1041 // Generate code
1042 O << "void llvmc::PopulateCompilationGraph(CompilationGraph& G) {\n"
1043 << Indent1 << "PopulateLanguageMap(G.ExtsToLangs);\n\n";
1044
1045 // Insert vertices
1046
1047 RecordVector Tools = Records.getAllDerivedDefinitions("Tool");
1048 if (Tools.empty())
1049 throw std::string("No tool definitions found!");
1050
1051 for (RecordVector::iterator B = Tools.begin(), E = Tools.end(); B != E; ++B) {
1052 const std::string& Name = (*B)->getName();
1053 if(Name != "root")
1054 O << Indent1 << "G.insertNode(new "
1055 << Name << "());\n";
1056 }
1057
1058 O << '\n';
1059
1060 // Insert edges
1061 for (unsigned i = 0; i < edges->size(); ++i) {
1062 Record* Edge = edges->getElementAsRecord(i);
1063 Record* A = Edge->getValueAsDef("a");
1064 Record* B = Edge->getValueAsDef("b");
1065 ListInit* Props = Edge->getValueAsListInit("props");
1066
1067 O << Indent1 << "G.insertEdge(\"" << A->getName() << "\", ";
1068
1069 if (Props->empty())
1070 O << "new SimpleEdge(\"" << B->getName() << "\")";
1071 else
1072 O << "new Edge" << i << "()";
1073
1074 O << ");\n";
1075 }
1076
1077 O << "}\n\n";
1078 }
1079
1080
1081 // End of anonymous namespace
1082 //}
1083
1084 // Back-end entry point
1085 void LLVMCCConfigurationEmitter::run (std::ostream &O) {
1086 // Emit file header
1087 EmitSourceFileHeader("LLVMC Configuration Library", O);
1088
1089 // Get a list of all defined Tools
1090 RecordVector Tools = Records.getAllDerivedDefinitions("Tool");
1091 if (Tools.empty())
1092 throw std::string("No tool definitions found!");
1093
1094 // Gather information from the Tool descriptions
1095 ToolPropertiesList tool_props;
1096 GlobalOptionDescriptions opt_descs;
1097 CollectToolProperties(Tools.begin(), Tools.end(), tool_props, opt_descs);
1098
1099 // Emit global option registration code
1100 EmitOptionDescriptions(opt_descs, O);
1101
1102 // Emit PopulateLanguageMap function
1103 // (a language map maps from file extensions to language names)
1104 EmitPopulateLanguageMap(Records, O);
1105
1106 // Emit Tool classes
1107 for (ToolPropertiesList::const_iterator B = tool_props.begin(),
1108 E = tool_props.end(); B!=E; ++B)
1109 EmitToolClassDefinition(*(*B), O);
1110
1111 Record* CompilationGraphRecord = Records.getDef("CompilationGraph");
1112 if (!CompilationGraphRecord)
1113 throw std::string("Compilation graph description not found!");
1114
1115 // Typecheck the compilation graph.
1116 TypecheckGraph(CompilationGraphRecord, tool_props);
1117
1118 // Emit Edge* classes.
1119 EmitEdgeClasses(CompilationGraphRecord, opt_descs, O);
1120
1121 // Emit PopulateCompilationGraph function
1122 EmitPopulateCompilationGraph(CompilationGraphRecord, O);
1123
1124 // EOF
1125 }
+0
-30
utils/TableGen/LLVMCCConfigurationEmitter.h less more
None //===- LLVMCConfigurationEmitter.cpp - Generate LLVMCC config -------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open
5 // Source License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend is responsible for emitting LLVMCC configuration code.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVMCCCONF_EMITTER_H
14 #define LLVMCCCONF_EMITTER_H
15
16 #include "TableGenBackend.h"
17
18 namespace llvm {
19 class LLVMCCConfigurationEmitter : public TableGenBackend {
20 RecordKeeper &Records;
21 public:
22 explicit LLVMCCConfigurationEmitter(RecordKeeper &R) : Records(R) {}
23
24 // run - Output the asmwriter, returning true on failure.
25 void run(std::ostream &o);
26 };
27 }
28
29 #endif //LLVMCCCONF_EMITTER_H
0 //===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config --------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open
5 // Source License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend is responsible for emitting LLVMC configuration code.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "LLVMCConfigurationEmitter.h"
14 #include "Record.h"
15
16 #include "llvm/ADT/IntrusiveRefCntPtr.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/Support/Streams.h"
21
22 #include
23 #include
24 #include
25 #include
26
27 using namespace llvm;
28
29 //namespace {
30
31 //===----------------------------------------------------------------------===//
32 /// Typedefs
33
34 typedef std::vector RecordVector;
35 typedef std::vector StrVector;
36
37 //===----------------------------------------------------------------------===//
38 /// Constants
39
40 // Indentation strings
41 const char * Indent1 = " ";
42 const char * Indent2 = " ";
43 const char * Indent3 = " ";
44 const char * Indent4 = " ";
45
46 // Default help string
47 const char * DefaultHelpString = "NO HELP MESSAGE PROVIDED";
48
49 // Name for the "sink" option
50 const char * SinkOptionName = "AutoGeneratedSinkOption";
51
52 //===----------------------------------------------------------------------===//
53 /// Helper functions
54
55 std::string InitPtrToString(Init* ptr) {
56 StringInit& val = dynamic_cast(*ptr);
57 return val.getValue();
58 }
59
60 // Ensure that the number of args in d is <= min_arguments,
61 // throw exception otherwise
62 void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) {
63 if (d->getNumArgs() < min_arguments)
64 throw "Property " + d->getOperator()->getAsString()
65 + " has too few arguments!";
66 }
67
68
69 //===----------------------------------------------------------------------===//
70 /// Back-end specific code
71
72 // A command-line option can have one of the following types:
73 //
74 // Switch - a simple switch w/o arguments, e.g. -O2
75 //
76 // Parameter - an option that takes one(and only one) argument, e.g. -o file,
77 // --output=file
78 //
79 // ParameterList - same as Parameter, but more than one occurence
80 // of the option is allowed, e.g. -lm -lpthread
81 //
82 // Prefix - argument is everything after the prefix,
83 // e.g. -Wa,-foo,-bar, -DNAME=VALUE
84 //
85 // PrefixList - same as Prefix, but more than one option occurence is
86 // allowed
87
88 namespace OptionType {
89 enum OptionType { Switch, Parameter, ParameterList, Prefix, PrefixList};
90 }
91
92 bool IsListOptionType (OptionType::OptionType t) {
93 return (t == OptionType::ParameterList || t == OptionType::PrefixList);
94 }
95
96 // Code duplication here is necessary because one option can affect
97 // several tools and those tools may have different actions associated
98 // with this option. GlobalOptionDescriptions are used to generate
99 // the option registration code, while ToolOptionDescriptions are used
100 // to generate tool-specific code.
101
102 // Base class for option descriptions
103
104 struct OptionDescription {
105 OptionType::OptionType Type;
106 std::string Name;
107
108 OptionDescription(OptionType::OptionType t = OptionType::Switch,
109 const std::string& n = "")
110 : Type(t), Name(n)
111 {}
112
113 const char* GenTypeDeclaration() const {
114 switch (Type) {
115 case OptionType::PrefixList:
116 case OptionType::ParameterList:
117 return "cl::list";
118 case OptionType::Switch:
119 return "cl::opt";
120 case OptionType::Parameter:
121 case OptionType::Prefix:
122 default:
123 return "cl::opt";
124 }
125 }
126
127 std::string GenVariableName() const {
128 switch (Type) {
129 case OptionType::Switch:
130 return "AutoGeneratedSwitch" + Name;
131 case OptionType::Prefix:
132 return "AutoGeneratedPrefix" + Name;
133 case OptionType::PrefixList:
134 return "AutoGeneratedPrefixList" + Name;
135 case OptionType::Parameter:
136 return "AutoGeneratedParameter" + Name;
137 case OptionType::ParameterList:
138 default:
139 return "AutoGeneratedParameterList" + Name;
140 }
141 }
142
143 };
144
145 // Global option description
146
147 namespace GlobalOptionDescriptionFlags {
148 enum GlobalOptionDescriptionFlags { Required = 0x1 };
149 }
150
151 struct GlobalOptionDescription : public OptionDescription {
152 std::string Help;
153 unsigned Flags;
154
155 // We need t provide a default constructor since
156 // StringMap can only store DefaultConstructible objects
157 GlobalOptionDescription() : OptionDescription(), Flags(0)
158 {}
159
160 GlobalOptionDescription (OptionType::OptionType t, const std::string& n)
161 : OptionDescription(t, n), Help(DefaultHelpString), Flags(0)
162 {}
163
164 bool isRequired() const {
165 return Flags & GlobalOptionDescriptionFlags::Required;
166 }
167 void setRequired() {
168 Flags |= GlobalOptionDescriptionFlags::Required;
169 }
170
171 // Merge two option descriptions
172 void Merge (const GlobalOptionDescription& other)
173 {
174 if (other.Type != Type)
175 throw "Conflicting definitions for the option " + Name + "!";
176
177 if (Help.empty() && !other.Help.empty())
178 Help = other.Help;
179 else if (!Help.empty() && !other.Help.empty())
180 cerr << "Warning: more than one help string defined for option "
181 + Name + "\n";
182
183 Flags |= other.Flags;
184 }
185 };
186
187 // A GlobalOptionDescription array
188 // + some flags affecting generation of option declarations
189 struct GlobalOptionDescriptions {
190 typedef StringMap container_type;
191 typedef container_type::const_iterator const_iterator;
192
193 // A list of GlobalOptionDescriptions
194 container_type Descriptions;
195 // Should the emitter generate a "cl::sink" option?
196 bool HasSink;
197
198 const GlobalOptionDescription& FindOption(const std::string& OptName) const {
199 const_iterator I = Descriptions.find(OptName);
200 if (I != Descriptions.end())
201 return I->second;
202 else
203 throw OptName + ": no such option!";
204 }
205
206 // Support for STL-style iteration
207 const_iterator begin() const { return Descriptions.begin(); }
208 const_iterator end() const { return Descriptions.end(); }
209 };
210
211
212 // Tool-local option description
213
214 // Properties without arguments are implemented as flags
215 namespace ToolOptionDescriptionFlags {
216 enum ToolOptionDescriptionFlags { StopCompilation = 0x1,
217 Forward = 0x2, UnpackValues = 0x4};
218 }
219 namespace OptionPropertyType {
220 enum OptionPropertyType { AppendCmd };
221 }
222
223 typedef std::pair
224 OptionProperty;
225 typedef SmallVector OptionPropertyList;
226
227 struct ToolOptionDescription : public OptionDescription {
228 unsigned Flags;
229 OptionPropertyList Props;
230
231 // StringMap can only store DefaultConstructible objects
232 ToolOptionDescription() : OptionDescription(), Flags(0) {}
233
234 ToolOptionDescription (OptionType::OptionType t, const std::string& n)
235 : OptionDescription(t, n)
236 {}
237
238 // Various boolean properties
239 bool isStopCompilation() const {
240 return Flags & ToolOptionDescriptionFlags::StopCompilation;
241 }
242 void setStopCompilation() {
243 Flags |= ToolOptionDescriptionFlags::StopCompilation;
244 }
245
246 bool isForward() const {
247 return Flags & ToolOptionDescriptionFlags::Forward;
248 }
249 void setForward() {
250 Flags |= ToolOptionDescriptionFlags::Forward;
251 }
252
253 bool isUnpackValues() const {
254 return Flags & ToolOptionDescriptionFlags::UnpackValues;
255 }
256 void setUnpackValues() {
257 Flags |= ToolOptionDescriptionFlags::UnpackValues;
258 }
259
260 void AddProperty (OptionPropertyType::OptionPropertyType t,
261 const std::string& val)
262 {
263 Props.push_back(std::make_pair(t, val));
264 }
265 };
266
267 typedef StringMap ToolOptionDescriptions;
268
269 // Tool information record
270
271 namespace ToolFlags {
272 enum ToolFlags { Join = 0x1, Sink = 0x2 };
273 }
274
275 struct ToolProperties : public RefCountedBase {
276 std::string Name;
277 StrVector CmdLine;
278 std::string InLanguage;
279 std::string OutLanguage;
280 std::string OutputSuffix;
281 unsigned Flags;
282 ToolOptionDescriptions OptDescs;
283
284 // Various boolean properties
285 void setSink() { Flags |= ToolFlags::Sink; }
286 bool isSink() const { return Flags & ToolFlags::Sink; }
287 void setJoin() { Flags |= ToolFlags::Join; }
288 bool isJoin() const { return Flags & ToolFlags::Join; }
289
290 // Default ctor here is needed because StringMap can only store
291 // DefaultConstructible objects
292 ToolProperties() {}
293 ToolProperties (const std::string& n) : Name(n) {}
294 };
295
296
297 // A list of Tool information records
298 // IntrusiveRefCntPtrs are used because StringMap has no copy constructor
299 // (and we want to avoid copying ToolProperties anyway)
300 typedef std::vector > ToolPropertiesList;
301
302
303 // Function object for iterating over a list of tool property records
304 class CollectProperties {
305 private:
306
307 /// Implementation details
308
309 // "Property handler" - a function that extracts information
310 // about a given tool property from its DAG representation
311 typedef void (CollectProperties::*PropertyHandler)(DagInit*);
312
313 // Map from property names -> property handlers
314 typedef StringMap PropertyHandlerMap;
315
316 // "Option property handler" - a function that extracts information
317 // about a given option property from its DAG representation
318 typedef void (CollectProperties::*
319 OptionPropertyHandler)(DagInit*, GlobalOptionDescription &);
320
321 // Map from option property names -> option property handlers
322 typedef StringMap OptionPropertyHandlerMap;
323
324 // Static maps from strings to CollectProperties methods("handlers")
325 static PropertyHandlerMap propertyHandlers_;
326 static OptionPropertyHandlerMap optionPropertyHandlers_;
327 static bool staticMembersInitialized_;
328
329
330 /// This is where the information is stored
331
332 // Current Tool properties
333 ToolProperties& toolProps_;
334 // OptionDescriptions table(used to register options globally)
335 GlobalOptionDescriptions& optDescs_;
336
337 public:
338
339 explicit CollectProperties (ToolProperties& p, GlobalOptionDescriptions& d)
340 : toolProps_(p), optDescs_(d)
341 {
342 if (!staticMembersInitialized_) {
343 // Init tool property handlers
344 propertyHandlers_["cmd_line"] = &CollectProperties::onCmdLine;
345 propertyHandlers_["in_language"] = &CollectProperties::onInLanguage;
346 propertyHandlers_["join"] = &CollectProperties::onJoin;
347 propertyHandlers_["out_language"] = &CollectProperties::onOutLanguage;
348 propertyHandlers_["output_suffix"] = &CollectProperties::onOutputSuffix;
349 propertyHandlers_["parameter_option"]
350 = &CollectProperties::onParameter;
351 propertyHandlers_["parameter_list_option"] =
352 &CollectProperties::onParameterList;
353 propertyHandlers_["prefix_option"] = &CollectProperties::onPrefix;
354 propertyHandlers_["prefix_list_option"] =
355 &CollectProperties::onPrefixList;
356 propertyHandlers_["sink"] = &CollectProperties::onSink;
357 propertyHandlers_["switch_option"] = &CollectProperties::onSwitch;
358
359 // Init option property handlers
360 optionPropertyHandlers_["append_cmd"] = &CollectProperties::onAppendCmd;
361 optionPropertyHandlers_["forward"] = &CollectProperties::onForward;
362 optionPropertyHandlers_["help"] = &CollectProperties::onHelp;
363 optionPropertyHandlers_["required"] = &CollectProperties::onRequired;
364 optionPropertyHandlers_["stop_compilation"] =
365 &CollectProperties::onStopCompilation;
366 optionPropertyHandlers_["unpack_values"] =
367 &CollectProperties::onUnpackValues;
368
369 staticMembersInitialized_ = true;
370 }
371 }
372
373 // Gets called for every tool property;
374 // Just forwards to the corresponding property handler.
375 void operator() (Init* i) {
376 DagInit& d = dynamic_cast(*i);
377 const std::string& property_name = d.getOperator()->getAsString();
378 PropertyHandlerMap::iterator method
379 = propertyHandlers_.find(property_name);
380
381 if (method != propertyHandlers_.end()) {
382 PropertyHandler h = method->second;
383 (this->*h)(&d);
384 }
385 else {
386 throw "Unknown tool property: " + property_name + "!";
387 }
388 }
389
390 private:
391
392 /// Property handlers --
393 /// Functions that extract information about tool properties from
394 /// DAG representation.
395
396 void onCmdLine (DagInit* d) {
397 checkNumberOfArguments(d, 1);
398 SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine);
399 if (toolProps_.CmdLine.empty())
400 throw "Tool " + toolProps_.Name + " has empty command line!";
401 }
402
403 void onInLanguage (DagInit* d) {
404 checkNumberOfArguments(d, 1);
405 toolProps_.InLanguage = InitPtrToString(d->getArg(0));
406 }
407
408 void onJoin (DagInit* d) {
409 checkNumberOfArguments(d, 0);
410 toolProps_.setJoin();
411 }
412
413 void onOutLanguage (DagInit* d) {
414 checkNumberOfArguments(d, 1);
415 toolProps_.OutLanguage = InitPtrToString(d->getArg(0));
416 }
417
418 void onOutputSuffix (DagInit* d) {
419 checkNumberOfArguments(d, 1);
420 toolProps_.OutputSuffix = InitPtrToString(d->getArg(0));
421 }
422
423 void onSink (DagInit* d) {
424 checkNumberOfArguments(d, 0);
425 optDescs_.HasSink = true;
426 toolProps_.setSink();
427 }
428
429 void onSwitch (DagInit* d) { addOption(d, OptionType::Switch); }
430 void onParameter (DagInit* d) { addOption(d, OptionType::Parameter); }
431 void onParameterList (DagInit* d) { addOption(d, OptionType::ParameterList); }
432 void onPrefix (DagInit* d) { addOption(d, OptionType::Prefix); }
433 void onPrefixList (DagInit* d) { addOption(d, OptionType::PrefixList); }
434
435 /// Option property handlers --
436 /// Methods that handle properties that are common for all types of
437 /// options (like append_cmd, stop_compilation)
438
439 void onAppendCmd (DagInit* d, GlobalOptionDescription& o) {
440 checkNumberOfArguments(d, 1);
441 std::string const& cmd = InitPtrToString(d->getArg(0));
442
443 toolProps_.OptDescs[o.Name].AddProperty(OptionPropertyType::AppendCmd, cmd);
444 }
445
446 void onForward (DagInit* d, GlobalOptionDescription& o) {
447 checkNumberOfArguments(d, 0);
448 toolProps_.OptDescs[o.Name].setForward();
449 }
450
451 void onHelp (DagInit* d, GlobalOptionDescription& o) {
452 checkNumberOfArguments(d, 1);
453 const std::string& help_message = InitPtrToString(d->getArg(0));
454
455 o.Help = help_message;
456 }
457
458 void onRequired (DagInit* d, GlobalOptionDescription& o) {
459 checkNumberOfArguments(d, 0);
460 o.setRequired();
461 }
462
463 void onStopCompilation (DagInit* d, GlobalOptionDescription& o) {
464 checkNumberOfArguments(d, 0);
465 if (o.Type != OptionType::Switch)
466 throw std::string("Only options of type Switch can stop compilation!");
467 toolProps_.OptDescs[o.Name].setStopCompilation();
468 }
469
470 void onUnpackValues (DagInit* d, GlobalOptionDescription& o) {
471 checkNumberOfArguments(d, 0);
472 toolProps_.OptDescs[o.Name].setUnpackValues();
473 }
474
475 /// Helper functions
476
477 // Add an option of type t
478 void addOption (DagInit* d, OptionType::OptionType t) {
479 checkNumberOfArguments(d, 2);
480 const std::string& name = InitPtrToString(d->getArg(0));
481
482 GlobalOptionDescription o(t, name);
483 toolProps_.OptDescs[name].Type = t;
484 toolProps_.OptDescs[name].Name = name;
485 processOptionProperties(d, o);
486 insertDescription(o);
487 }
488
489 // Insert new GlobalOptionDescription into GlobalOptionDescriptions list
490 void insertDescription (const GlobalOptionDescription& o)
491 {
492 if (optDescs_.Descriptions.count(o.Name)) {
493 GlobalOptionDescription& D = optDescs_.Descriptions[o.Name];
494 D.Merge(o);
495 }
496 else {
497 optDescs_.Descriptions[o.Name] = o;
498 }
499 }
500
501 // Go through the list of option properties and call a corresponding
502 // handler for each.
503 //
504 // Parameters:
505 // name - option name
506 // d - option property list
507 void processOptionProperties (DagInit* d, GlobalOptionDescription& o) {
508 // First argument is option name
509 checkNumberOfArguments(d, 2);
510
511 for (unsigned B = 1, E = d->getNumArgs(); B!=E; ++B) {
512 DagInit& option_property
513 = dynamic_cast(*d->getArg(B));
514 const std::string& option_property_name
515 = option_property.getOperator()->getAsString();
516 OptionPropertyHandlerMap::iterator method
517 = optionPropertyHandlers_.find(option_property_name);
518
519 if (method != optionPropertyHandlers_.end()) {
520 OptionPropertyHandler h = method->second;
521 (this->*h)(&option_property, o);
522 }
523 else {
524 throw "Unknown option property: " + option_property_name + "!";
525 }
526 }
527 }
528 };
529
530 // Static members of CollectProperties
531 CollectProperties::PropertyHandlerMap
532 CollectProperties::propertyHandlers_;
533
534 CollectProperties::OptionPropertyHandlerMap
535 CollectProperties::optionPropertyHandlers_;
536
537 bool CollectProperties::staticMembersInitialized_ = false;
538
539
540 // Gather information from the parsed TableGen data
541 // (Basically a wrapper for CollectProperties)
542 void CollectToolProperties (RecordVector::const_iterator B,
543 RecordVector::const_iterator E,
544 ToolPropertiesList& TPList,
545 GlobalOptionDescriptions& OptDescs)
546 {
547 // Iterate over a properties list of every Tool definition
548 for (;B!=E;++B) {
549 RecordVector::value_type T = *B;
550 ListInit* PropList = T->getValueAsListInit("properties");
551
552 IntrusiveRefCntPtr
553 ToolProps(new ToolProperties(T->getName()));
554
555 std::for_each(PropList->begin(), PropList->end(),
556 CollectProperties(*ToolProps, OptDescs));
557 TPList.push_back(ToolProps);
558 }
559 }
560
561 // Used by EmitGenerateActionMethod
562 void EmitOptionPropertyHandlingCode (const ToolProperties& P,
563 const ToolOptionDescription& D,
564 std::ostream& O)
565 {
566 // if clause
567 O << Indent2 << "if (";
568 if (D.Type == OptionType::Switch)
569 O << D.GenVariableName();
570 else
571 O << '!' << D.GenVariableName() << ".empty()";
572
573 O <<") {\n";
574
575 // Handle option properties that take an argument
576 for (OptionPropertyList::const_iterator B = D.Props.begin(),
577 E = D.Props.end(); B!=E; ++B) {
578 const OptionProperty& val = *B;
579
580 switch (val.first) {
581 // (append_cmd cmd) property
582 case OptionPropertyType::AppendCmd:
583 O << Indent3 << "vec.push_back(\"" << val.second << "\");\n";
584 break;
585 // Other properties with argument
586 default:
587 break;
588 }
589 }
590
591 // Handle flags
592
593 // (forward) property
594 if (D.isForward()) {
595 switch (D.Type) {
596 case OptionType::Switch:
597 O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
598 break;
599 case OptionType::Parameter:
600 O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
601 O << Indent3 << "vec.push_back(" << D.GenVariableName() << ");\n";
602 break;
603 case OptionType::Prefix:
604 O << Indent3 << "vec.push_back(\"-" << D.Name << "\" + "
605 << D.GenVariableName() << ");\n";
606 break;
607 case OptionType::PrefixList:
608 O << Indent3 << "for (" << D.GenTypeDeclaration()
609 << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
610 << Indent3 << "E = " << D.GenVariableName() << ".end(); B != E; ++B)\n"
611 << Indent4 << "vec.push_back(\"-" << D.Name << "\" + "
612 << "*B);\n";
613 break;
614 case OptionType::ParameterList:
615 O << Indent3 << "for (" << D.GenTypeDeclaration()
616 << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
617 << Indent3 << "E = " << D.GenVariableName()
618 << ".end() ; B != E; ++B) {\n"
619 << Indent4 << "vec.push_back(\"-" << D.Name << "\");\n"
620 << Indent4 << "vec.push_back(*B);\n"
621 << Indent3 << "}\n";
622 break;
623 }
624 }
625
626 // (unpack_values) property
627 if (D.isUnpackValues()) {
628 if (IsListOptionType(D.Type)) {
629 O << Indent3 << "for (" << D.GenTypeDeclaration()
630 << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
631 << Indent3 << "E = " << D.GenVariableName()
632 << ".end(); B != E; ++B)\n"
633 << Indent4 << "Tool::UnpackValues(*B, vec);\n";
634 }
635 else if (D.Type == OptionType::Prefix || D.Type == OptionType::Parameter){
636 O << Indent3 << "Tool::UnpackValues("
637 << D.GenVariableName() << ", vec);\n";
638 }
639 else {
640 // TOFIX: move this to the type-checking phase
641 throw std::string("Switches can't have unpack_values property!");
642 }
643 }
644
645 // close if clause
646 O << Indent2 << "}\n";
647 }
648
649 // Emite one of two versions of GenerateAction method
650 void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O)
651 {
652 assert(V==1 || V==2);
653 if (V==1)
654 O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n";
655 else
656 O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n";
657
658 O << Indent2 << "const sys::Path& outFile) const\n"
659 << Indent1 << "{\n"
660 << Indent2 << "std::vector vec;\n";
661
662 // Parse CmdLine tool property
663 if(P.CmdLine.empty())
664 throw "Tool " + P.Name + " has empty command line!";
665
666 StrVector::const_iterator I = P.CmdLine.begin();
667 ++I;
668 for (StrVector::const_iterator E = P.CmdLine.end(); I != E; ++I) {
669 const std::string& cmd = *I;
670 O << Indent2;
671 if (cmd == "$INFILE") {
672 if (V==1)
673 O << "for (PathVector::const_iterator B = inFiles.begin()"
674 << ", E = inFiles.end();\n"
675 << Indent2 << "B != E; ++B)\n"
676 << Indent3 << "vec.push_back(B->toString());\n";
677 else
678 O << "vec.push_back(inFile.toString());\n";
679 }
680 else if (cmd == "$OUTFILE") {
681 O << "vec.push_back(outFile.toString());\n";
682 }
683 else {
684 O << "vec.push_back(\"" << cmd << "\");\n";
685 }
686 }
687
688 // For every understood option, emit handling code
689 for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(),
690 E = P.OptDescs.end(); B != E; ++B) {
691 const ToolOptionDescription& val = B->second;
692 EmitOptionPropertyHandlingCode(P, val, O);
693 }
694
695 // Handle Sink property
696 if (P.isSink()) {
697 O << Indent2 << "if (!" << SinkOptionName << ".empty()) {\n"
698 << Indent3 << "vec.insert(vec.end(), "
699 << SinkOptionName << ".begin(), " << SinkOptionName << ".end());\n"
700 << Indent2 << "}\n";
701 }
702
703 O << Indent2 << "return Action(\"" << P.CmdLine.at(0) << "\", vec);\n"
704 << Indent1 << "}\n\n";
705 }
706
707 // Emit GenerateAction methods for Tool classes
708 void EmitGenerateActionMethods (const ToolProperties& P, std::ostream& O) {
709
710 if (!P.isJoin())
711 O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"
712 << Indent2 << "const llvm::sys::Path& outFile) const\n"
713 << Indent1 << "{\n"
714 << Indent2 << "throw std::runtime_error(\"" << P.Name
715 << " is not a Join tool!\");\n"
716 << Indent1 << "}\n\n";
717 else
718 EmitGenerateActionMethod(P, 1, O);
719
720 EmitGenerateActionMethod(P, 2, O);
721 }
722
723 // Emit IsLast() method for Tool classes
724 void EmitIsLastMethod (const ToolProperties& P, std::ostream& O) {
725 O << Indent1 << "bool IsLast() const {\n"
726 << Indent2 << "bool last = false;\n";
727
728 for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(),
729 E = P.OptDescs.end(); B != E; ++B) {
730 const ToolOptionDescription& val = B->second;
731
732 if (val.isStopCompilation())
733 O << Indent2
734 << "if (" << val.GenVariableName()
735 << ")\n" << Indent3 << "last = true;\n";
736 }
737
738 O << Indent2 << "return last;\n"
739 << Indent1 << "}\n\n";
740 }
741
742 // Emit static [Input,Output]Language() methods for Tool classes
743 void EmitInOutLanguageMethods (const ToolProperties& P, std::ostream& O) {
744 O << Indent1 << "const char* InputLanguage() const {\n"
745 << Indent2 << "return \"" << P.InLanguage << "\";\n"
746 << Indent1 << "}\n\n";
747
748 O << Indent1 << "const char* OutputLanguage() const {\n"
749 << Indent2 << "return \"" << P.OutLanguage << "\";\n"
750 << Indent1 << "}\n\n";
751 }
752
753 // Emit static [Input,Output]Language() methods for Tool classes
754 void EmitOutputSuffixMethod (const ToolProperties& P, std::ostream& O) {
755 O << Indent1 << "const char* OutputSuffix() const {\n"
756 << Indent2 << "return \"" << P.OutputSuffix << "\";\n"
757 << Indent1 << "}\n\n";
758 }
759
760 // Emit static Name() method for Tool classes
761 void EmitNameMethod (const ToolProperties& P, std::ostream& O) {
762 O << Indent1 << "const char* Name() const {\n"
763 << Indent2 << "return \"" << P.Name << "\";\n"
764 << Indent1 << "}\n\n";
765 }
766
767 // Emit static Name() method for Tool classes
768 void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) {
769 O << Indent1 << "bool IsJoin() const {\n";
770 if (P.isJoin())
771 O << Indent2 << "return true;\n";
772 else
773 O << Indent2 << "return false;\n";
774 O << Indent1 << "}\n\n";
775 }
776
777 // Emit a Tool class definition
778 void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) {
779
780 if(P.Name == "root")
781 return;
782
783 // Header
784 O << "class " << P.Name << " : public ";
785 if (P.isJoin())
786 O << "JoinTool";
787 else
788 O << "Tool";
789 O << " {\npublic:\n";
790
791 EmitNameMethod(P, O);
792 EmitInOutLanguageMethods(P, O);
793 EmitOutputSuffixMethod(P, O);
794 EmitIsJoinMethod(P, O);
795 EmitGenerateActionMethods(P, O);
796 EmitIsLastMethod(P, O);
797
798 // Close class definition
799 O << "};\n\n";
800 }
801
802 // Iterate over a list of option descriptions and emit registration code
803 void EmitOptionDescriptions (const GlobalOptionDescriptions& descs,
804 std::ostream& O)
805 {
806 // Emit static cl::Option variables
807 for (GlobalOptionDescriptions::const_iterator B = descs.begin(),
808 E = descs.end(); B!=E; ++B) {
809 const GlobalOptionDescription& val = B->second;
810
811 O << val.GenTypeDeclaration() << ' '
812 << val.GenVariableName()
813 << "(\"" << val.Name << '\"';
814
815 if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
816 O << ", cl::Prefix";
817
818 if (val.isRequired()) {
819 switch (val.Type) {
820 case OptionType::PrefixList:
821 case OptionType::ParameterList:
822 O << ", cl::OneOrMore";
823 break;
824 default:
825 O << ", cl::Required";
826 }
827 }
828
829 O << ", cl::desc(\"" << val.Help << "\"));\n";
830 }
831
832 if (descs.HasSink)
833 O << "cl::list " << SinkOptionName << "(cl::Sink);\n";
834
835 O << '\n';
836 }
837
838 void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
839 {
840 // Get the relevant field out of RecordKeeper
841 Record* LangMapRecord = Records.getDef("LanguageMap");
842 if (!LangMapRecord)
843 throw std::string("Language map definition not found!");
844
845 ListInit* LangsToSuffixesList = LangMapRecord->getValueAsListInit("map");
846 if (!LangsToSuffixesList)
847 throw std::string("Error in the language map definition!");
848
849 // Generate code
850 O << "void llvmc::PopulateLanguageMap(LanguageMap& language_map) {\n";
851
852 for (unsigned i = 0; i < LangsToSuffixesList->size(); ++i) {
853 Record* LangToSuffixes = LangsToSuffixesList->getElementAsRecord(i);
854
855 const std::string& Lang = LangToSuffixes->getValueAsString("lang");
856 const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes");
857
858 for (unsigned i = 0; i < Suffixes->size(); ++i)
859 O << Indent1 << "language_map[\""
860 << InitPtrToString(Suffixes->getElement(i))
861 << "\"] = \"" << Lang << "\";\n";
862 }
863
864 O << "}\n\n";
865 }
866
867 // Fills in two tables that map tool names to (input, output) languages.
868 // Used by the typechecker.
869 void FillInToolToLang (const ToolPropertiesList& TPList,
870 StringMap& ToolToInLang,
871 StringMap& ToolToOutLang) {
872 for (ToolPropertiesList::const_iterator B = TPList.begin(), E = TPList.end();
873 B != E; ++B) {
874 const ToolProperties& P = *(*B);
875 ToolToInLang[P.Name] = P.InLanguage;
876 ToolToOutLang[P.Name] = P.OutLanguage;
877 }
878 }
879
880 // Check that all output and input language names match.
881 // TOFIX: check for cycles.
882 // TOFIX: check for multiple default edges.
883 void TypecheckGraph (Record* CompilationGraph,
884 const ToolPropertiesList& TPList) {
885 StringMap ToolToInLang;
886 StringMap ToolToOutLang;
887
888 FillInToolToLang(TPList, ToolToInLang, ToolToOutLang);
889 ListInit* edges = CompilationGraph->getValueAsListInit("edges");
890 StringMap::iterator IAE = ToolToInLang.end();
891 StringMap::iterator IBE = ToolToOutLang.end();
892
893 for (unsigned i = 0; i < edges->size(); ++i) {
894 Record* Edge = edges->getElementAsRecord(i);
895 Record* A = Edge->getValueAsDef("a");
896 Record* B = Edge->getValueAsDef("b");
897 StringMap::iterator IA = ToolToOutLang.find(A->getName());
898 StringMap::iterator IB = ToolToInLang.find(B->getName());
899 if(IA == IAE)
900 throw A->getName() + ": no such tool!";
901 if(IB == IBE)
902 throw B->getName() + ": no such tool!";
903 if(A->getName() != "root" && IA->second != IB->second)
904 throw "Edge " + A->getName() + "->" + B->getName()
905 + ": output->input language mismatch";
906 if(B->getName() == "root")
907 throw std::string("Edges back to the root are not allowed!");
908 }
909 }
910
911 // Helper function used by EmitEdgePropertyTest.
912 void EmitEdgePropertyTest1Arg(const DagInit& Prop,
913 const GlobalOptionDescriptions& OptDescs,
914 std::ostream& O) {
915 checkNumberOfArguments(&Prop, 1);
916 const std::string& OptName = InitPtrToString(Prop.getArg(0));
917 const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName);
918 if (OptDesc.Type != OptionType::Switch)
919 throw OptName + ": incorrect option type!";
920 O << OptDesc.GenVariableName();
921 }
922
923 // Helper function used by EmitEdgePropertyTest.
924 void EmitEdgePropertyTest2Args(const std::string& PropName,
925 const DagInit& Prop,
926 const GlobalOptionDescriptions& OptDescs,
927 std::ostream& O) {
928 checkNumberOfArguments(&Prop, 2);
929 const std::string& OptName = InitPtrToString(Prop.getArg(0));
930 const std::string& OptArg = InitPtrToString(Prop.getArg(1));
931 const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName);
932
933 if (PropName == "parameter_equals") {
934 if (OptDesc.Type != OptionType::Parameter
935 && OptDesc.Type != OptionType::Prefix)
936 throw OptName + ": incorrect option type!";
937 O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
938 }
939 else if (PropName == "element_in_list") {
940 if (OptDesc.Type != OptionType::ParameterList
941 && OptDesc.Type != OptionType::PrefixList)
942 throw OptName + ": incorrect option type!";
943 const std::string& VarName = OptDesc.GenVariableName();
944 O << "std::find(" << VarName << ".begin(),\n"
945 << Indent3 << VarName << ".end(), \""
946 << OptArg << "\") != " << VarName << ".end()";
947 }
948 else
949 throw PropName + ": unknown edge property!";
950 }
951
952 // Helper function used by EmitEdgeClass.
953 void EmitEdgePropertyTest(const std::string& PropName,
954 const DagInit& Prop,
955 const GlobalOptionDescriptions& OptDescs,
956 std::ostream& O) {
957 if (PropName == "switch_on")
958 EmitEdgePropertyTest1Arg(Prop, OptDescs, O);
959 else
960 EmitEdgePropertyTest2Args(PropName, Prop, OptDescs, O);
961 }
962
963 // Emit a single Edge* class.
964 void EmitEdgeClass(unsigned N, const std::string& Target,
965 ListInit* Props, const GlobalOptionDescriptions& OptDescs,
966 std::ostream& O) {
967 bool IsDefault = false;
968
969 // Class constructor.
970 O << "class Edge" << N << ": public Edge {\n"
971 << "public:\n"
972 << Indent1 << "Edge" << N << "() : Edge(\"" << Target
973 << "\") {}\n\n"
974
975 // Function isEnabled().
976 << Indent1 << "bool isEnabled() const {\n"
977 << Indent2 << "bool ret = false;\n";
978
979 for (size_t i = 0, PropsSize = Props->size(); i < PropsSize; ++i) {
980 const DagInit& Prop = dynamic_cast(*Props->getElement(i));
981 const std::string& PropName = Prop.getOperator()->getAsString();
982
983 if (PropName == "default")
984 IsDefault = true;
985
986 O << Indent2 << "if (ret || (";
987 if (PropName == "and") {
988 O << '(';
989 for (unsigned j = 0, NumArgs = Prop.getNumArgs(); j < NumArgs; ++j) {
990 const DagInit& InnerProp = dynamic_cast(*Prop.getArg(j));
991 const std::string& InnerPropName =
992 InnerProp.getOperator()->getAsString();
993 EmitEdgePropertyTest(InnerPropName, InnerProp, OptDescs, O);
994 if (j != NumArgs - 1)
995 O << ")\n" << Indent3 << " && (";
996 else
997 O << ')';
998 }
999 }
1000 else {
1001 EmitEdgePropertyTest(PropName, Prop, OptDescs, O);
1002 }
1003 O << "))\n" << Indent3 << "ret = true;\n";
1004 }
1005
1006 O << Indent2 << "return ret;\n"
1007 << Indent1 << "};\n\n"
1008
1009 // Function isDefault().
1010 << Indent1 << "bool isDefault() const { return ";
1011 if (IsDefault)
1012 O << "true";
1013 else
1014 O << "false";
1015 O <<"; }\n};\n\n";
1016 }
1017
1018 // Emit Edge* classes that represent graph edges.
1019 void EmitEdgeClasses (Record* CompilationGraph,
1020 const GlobalOptionDescriptions& OptDescs,
1021 std::ostream& O) {
1022 ListInit* edges = CompilationGraph->getValueAsListInit("edges");
1023
1024 for (unsigned i = 0; i < edges->size(); ++i) {
1025 Record* Edge = edges->getElementAsRecord(i);
1026 Record* B = Edge->getValueAsDef("b");
1027 ListInit* Props = Edge->getValueAsListInit("props");
1028
1029 if (Props->empty())
1030 continue;
1031
1032 EmitEdgeClass(i, B->getName(), Props, OptDescs, O);
1033 }
1034 }
1035
1036 void EmitPopulateCompilationGraph (Record* CompilationGraph,
1037 std::ostream& O)
1038 {
1039 ListInit* edges = CompilationGraph->getValueAsListInit("edges");
1040
1041 // Generate code
1042 O << "void llvmc::PopulateCompilationGraph(CompilationGraph& G) {\n"
1043 << Indent1 << "PopulateLanguageMap(G.ExtsToLangs);\n\n";
1044
1045 // Insert vertices
1046
1047 RecordVector Tools = Records.getAllDerivedDefinitions("Tool");
1048 if (Tools.empty())
1049 throw std::string("No tool definitions found!");
1050
1051 for (RecordVector::iterator B = Tools.begin(), E = Tools.end(); B != E; ++B) {
1052 const std::string& Name = (*B)->getName();
1053 if(Name != "root")
1054 O << Indent1 << "G.insertNode(new "
1055 << Name << "());\n";
1056 }
1057
1058 O << '\n';
1059
1060 // Insert edges
1061 for (unsigned i = 0; i < edges->size(); ++i) {
1062 Record* Edge = edges->getElementAsRecord(i);
1063 Record* A = Edge->getValueAsDef("a");
1064 Record* B = Edge->getValueAsDef("b");
1065 ListInit* Props = Edge->getValueAsListInit("props");
1066
1067 O << Indent1 << "G.insertEdge(\"" << A->getName() << "\", ";
1068
1069 if (Props->empty())
1070 O << "new SimpleEdge(\"" << B->getName() << "\")";
1071 else
1072 O << "new Edge" << i << "()";
1073
1074 O << ");\n";
1075 }
1076
1077 O << "}\n\n";
1078 }
1079
1080
1081 // End of anonymous namespace
1082 //}
1083
1084 // Back-end entry point
1085 void LLVMCCConfigurationEmitter::run (std::ostream &O) {
1086 // Emit file header
1087 EmitSourceFileHeader("LLVMC Configuration Library", O);
1088
1089 // Get a list of all defined Tools
1090 RecordVector Tools = Records.getAllDerivedDefinitions("Tool");
1091 if (Tools.empty())
1092 throw std::string("No tool definitions found!");
1093
1094 // Gather information from the Tool descriptions
1095 ToolPropertiesList tool_props;
1096 GlobalOptionDescriptions opt_descs;
1097 CollectToolProperties(Tools.begin(), Tools.end(), tool_props, opt_descs);
1098
1099 // Emit global option registration code
1100 EmitOptionDescriptions(opt_descs, O);
1101
1102 // Emit PopulateLanguageMap function
1103 // (a language map maps from file extensions to language names)
1104 EmitPopulateLanguageMap(Records, O);
1105
1106 // Emit Tool classes
1107 for (ToolPropertiesList::const_iterator B = tool_props.begin(),
1108 E = tool_props.end(); B!=E; ++B)
1109 EmitToolClassDefinition(*(*B), O);
1110
1111 Record* CompilationGraphRecord = Records.getDef("CompilationGraph");
1112 if (!CompilationGraphRecord)
1113 throw std::string("Compilation graph description not found!");
1114
1115 // Typecheck the compilation graph.
1116 TypecheckGraph(CompilationGraphRecord, tool_props);
1117
1118 // Emit Edge* classes.
1119 EmitEdgeClasses(CompilationGraphRecord, opt_descs, O);
1120
1121 // Emit PopulateCompilationGraph function
1122 EmitPopulateCompilationGraph(CompilationGraphRecord, O);
1123
1124 // EOF
1125 }
0 //===- LLVMCConfigurationEmitter.cpp - Generate LLVMCC config -------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open
5 // Source License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend is responsible for emitting LLVMCC configuration code.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVMCCCONF_EMITTER_H
14 #define LLVMCCCONF_EMITTER_H
15
16 #include "TableGenBackend.h"
17
18 namespace llvm {
19 class LLVMCCConfigurationEmitter : public TableGenBackend {
20 RecordKeeper &Records;
21 public:
22 explicit LLVMCCConfigurationEmitter(RecordKeeper &R) : Records(R) {}
23
24 // run - Output the asmwriter, returning true on failure.
25 void run(std::ostream &o);
26 };
27 }
28
29 #endif //LLVMCCCONF_EMITTER_H
3030 #include "DAGISelEmitter.h"
3131 #include "SubtargetEmitter.h"
3232 #include "IntrinsicEmitter.h"
33 #include "LLVMCCConfigurationEmitter.h"
33 #include "LLVMCConfigurationEmitter.h"
3434 #include
3535 #include
3636 #include
103103
104104 /// ParseFile - this function begins the parsing of the specified tablegen
105105 /// file.
106 static bool ParseFile(const std::string &Filename,
106 static bool ParseFile(const std::string &Filename,
107107 const std::vector &IncludeDirs) {
108108 std::string ErrorStr;
109109 MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr);
111111 cerr << "Could not open input file '" + Filename + "': " << ErrorStr <<"\n";
112112 return true;
113113 }
114
114
115115 TGParser Parser(F);
116
116
117117 // Record the location of the include directory so that the lexer can find
118118 // it later.
119119 Parser.setIncludeDirs(IncludeDirs);
120
120
121121 return Parser.ParseFile();
122122 }
123123