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