Fix comment for gen-clang-decl-nodes tblgen backend, from Michael Han
[oota-llvm.git] / utils / TableGen / LLVMCConfigurationEmitter.cpp
1 //===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config ----*- C++ -*-===//
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 LLVMC configuration code.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "LLVMCConfigurationEmitter.h"
15 #include "Record.h"
16
17 #include "llvm/ADT/IntrusiveRefCntPtr.h"
18 #include "llvm/ADT/StringMap.h"
19 #include "llvm/ADT/StringSet.h"
20
21 #include <algorithm>
22 #include <cassert>
23 #include <functional>
24 #include <stdexcept>
25 #include <string>
26 #include <typeinfo>
27
28
29 using namespace llvm;
30
31 namespace {
32
33 //===----------------------------------------------------------------------===//
34 /// Typedefs
35
36 typedef std::vector<Record*> RecordVector;
37 typedef std::vector<const DagInit*> DagVector;
38 typedef std::vector<std::string> StrVector;
39
40 //===----------------------------------------------------------------------===//
41 /// Constants
42
43 // Indentation.
44 const unsigned TabWidth = 4;
45 const unsigned Indent1  = TabWidth*1;
46 const unsigned Indent2  = TabWidth*2;
47 const unsigned Indent3  = TabWidth*3;
48 const unsigned Indent4  = TabWidth*4;
49
50 // Default help string.
51 const char * const DefaultHelpString = "NO HELP MESSAGE PROVIDED";
52
53 // Name for the "sink" option.
54 const char * const SinkOptionName = "SinkOption";
55
56 //===----------------------------------------------------------------------===//
57 /// Helper functions
58
59 /// Id - An 'identity' function object.
60 struct Id {
61   template<typename T0>
62   void operator()(const T0&) const {
63   }
64   template<typename T0, typename T1>
65   void operator()(const T0&, const T1&) const {
66   }
67   template<typename T0, typename T1, typename T2>
68   void operator()(const T0&, const T1&, const T2&) const {
69   }
70 };
71
72 int InitPtrToInt(const Init* ptr) {
73   const IntInit& val = dynamic_cast<const IntInit&>(*ptr);
74   return val.getValue();
75 }
76
77 const std::string& InitPtrToString(const Init* ptr) {
78   const StringInit& val = dynamic_cast<const StringInit&>(*ptr);
79   return val.getValue();
80 }
81
82 const ListInit& InitPtrToList(const Init* ptr) {
83   const ListInit& val = dynamic_cast<const ListInit&>(*ptr);
84   return val;
85 }
86
87 const DagInit& InitPtrToDag(const Init* ptr) {
88   const DagInit& val = dynamic_cast<const DagInit&>(*ptr);
89   return val;
90 }
91
92 const std::string GetOperatorName(const DagInit& D) {
93   return D.getOperator()->getAsString();
94 }
95
96 /// CheckBooleanConstant - Check that the provided value is a boolean constant.
97 void CheckBooleanConstant(const Init* I) {
98   const DefInit& val = dynamic_cast<const DefInit&>(*I);
99   const std::string& str = val.getAsString();
100
101   if (str != "true" && str != "false") {
102     throw "Incorrect boolean value: '" + str +
103       "': must be either 'true' or 'false'";
104   }
105 }
106
107 // CheckNumberOfArguments - Ensure that the number of args in d is
108 // greater than or equal to min_arguments, otherwise throw an exception.
109 void CheckNumberOfArguments (const DagInit& d, unsigned minArgs) {
110   if (d.getNumArgs() < minArgs)
111     throw GetOperatorName(d) + ": too few arguments!";
112 }
113
114 // EscapeVariableName - Escape commas and other symbols not allowed
115 // in the C++ variable names. Makes it possible to use options named
116 // like "Wa," (useful for prefix options).
117 std::string EscapeVariableName (const std::string& Var) {
118   std::string ret;
119   for (unsigned i = 0; i != Var.size(); ++i) {
120     char cur_char = Var[i];
121     if (cur_char == ',') {
122       ret += "_comma_";
123     }
124     else if (cur_char == '+') {
125       ret += "_plus_";
126     }
127     else if (cur_char == '-') {
128       ret += "_dash_";
129     }
130     else {
131       ret.push_back(cur_char);
132     }
133   }
134   return ret;
135 }
136
137 /// EscapeQuotes - Replace '"' with '\"'.
138 std::string EscapeQuotes (const std::string& Var) {
139   std::string ret;
140   for (unsigned i = 0; i != Var.size(); ++i) {
141     char cur_char = Var[i];
142     if (cur_char == '"') {
143       ret += "\\\"";
144     }
145     else {
146       ret.push_back(cur_char);
147     }
148   }
149   return ret;
150 }
151
152 /// OneOf - Does the input string contain this character?
153 bool OneOf(const char* lst, char c) {
154   while (*lst) {
155     if (*lst++ == c)
156       return true;
157   }
158   return false;
159 }
160
161 template <class I, class S>
162 void CheckedIncrement(I& P, I E, S ErrorString) {
163   ++P;
164   if (P == E)
165     throw ErrorString;
166 }
167
168 //===----------------------------------------------------------------------===//
169 /// Back-end specific code
170
171
172 /// OptionType - One of six different option types. See the
173 /// documentation for detailed description of differences.
174 namespace OptionType {
175
176   enum OptionType { Alias, Switch, SwitchList,
177                     Parameter, ParameterList, Prefix, PrefixList };
178
179   bool IsAlias(OptionType t) {
180     return (t == Alias);
181   }
182
183   bool IsList (OptionType t) {
184     return (t == SwitchList || t == ParameterList || t == PrefixList);
185   }
186
187   bool IsSwitch (OptionType t) {
188     return (t == Switch);
189   }
190
191   bool IsSwitchList (OptionType t) {
192     return (t == SwitchList);
193   }
194
195   bool IsParameter (OptionType t) {
196     return (t == Parameter || t == Prefix);
197   }
198
199 }
200
201 OptionType::OptionType stringToOptionType(const std::string& T) {
202   if (T == "alias_option")
203     return OptionType::Alias;
204   else if (T == "switch_option")
205     return OptionType::Switch;
206   else if (T == "switch_list_option")
207     return OptionType::SwitchList;
208   else if (T == "parameter_option")
209     return OptionType::Parameter;
210   else if (T == "parameter_list_option")
211     return OptionType::ParameterList;
212   else if (T == "prefix_option")
213     return OptionType::Prefix;
214   else if (T == "prefix_list_option")
215     return OptionType::PrefixList;
216   else
217     throw "Unknown option type: " + T + '!';
218 }
219
220 namespace OptionDescriptionFlags {
221   enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
222                                 ReallyHidden = 0x4, OneOrMore = 0x8,
223                                 Optional = 0x10, CommaSeparated = 0x20,
224                                 ForwardNotSplit = 0x40, ZeroOrMore = 0x80 };
225 }
226
227 /// OptionDescription - Represents data contained in a single
228 /// OptionList entry.
229 struct OptionDescription {
230   OptionType::OptionType Type;
231   std::string Name;
232   unsigned Flags;
233   std::string Help;
234   unsigned MultiVal;
235   Init* InitVal;
236
237   OptionDescription(OptionType::OptionType t = OptionType::Switch,
238                     const std::string& n = "",
239                     const std::string& h = DefaultHelpString)
240     : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1), InitVal(0)
241   {}
242
243   /// GenTypeDeclaration - Returns the C++ variable type of this
244   /// option.
245   const char* GenTypeDeclaration() const;
246
247   /// GenVariableName - Returns the variable name used in the
248   /// generated C++ code.
249   std::string GenVariableName() const
250   { return "autogenerated::" + GenOptionType() + EscapeVariableName(Name); }
251
252   /// GenPlainVariableName - Returns the variable name without the namespace
253   /// prefix.
254   std::string GenPlainVariableName() const
255   { return GenOptionType() + EscapeVariableName(Name); }
256
257   /// Merge - Merge two option descriptions.
258   void Merge (const OptionDescription& other);
259
260   /// CheckConsistency - Check that the flags are consistent.
261   void CheckConsistency() const;
262
263   // Misc convenient getters/setters.
264
265   bool isAlias() const;
266
267   bool isMultiVal() const;
268
269   bool isCommaSeparated() const;
270   void setCommaSeparated();
271
272   bool isForwardNotSplit() const;
273   void setForwardNotSplit();
274
275   bool isRequired() const;
276   void setRequired();
277
278   bool isOneOrMore() const;
279   void setOneOrMore();
280
281   bool isZeroOrMore() const;
282   void setZeroOrMore();
283
284   bool isOptional() const;
285   void setOptional();
286
287   bool isHidden() const;
288   void setHidden();
289
290   bool isReallyHidden() const;
291   void setReallyHidden();
292
293   bool isSwitch() const
294   { return OptionType::IsSwitch(this->Type); }
295
296   bool isSwitchList() const
297   { return OptionType::IsSwitchList(this->Type); }
298
299   bool isParameter() const
300   { return OptionType::IsParameter(this->Type); }
301
302   bool isList() const
303   { return OptionType::IsList(this->Type); }
304
305   bool isParameterList() const
306   { return (OptionType::IsList(this->Type)
307             && !OptionType::IsSwitchList(this->Type)); }
308
309 private:
310
311   // GenOptionType - Helper function used by GenVariableName().
312   std::string GenOptionType() const;
313 };
314
315 void OptionDescription::CheckConsistency() const {
316   unsigned i = 0;
317
318   i += this->isRequired();
319   i += this->isOptional();
320   i += this->isOneOrMore();
321   i += this->isZeroOrMore();
322
323   if (i > 1) {
324     throw "Only one of (required), (optional), (one_or_more) or "
325       "(zero_or_more) properties is allowed!";
326   }
327 }
328
329 void OptionDescription::Merge (const OptionDescription& other)
330 {
331   if (other.Type != Type)
332     throw "Conflicting definitions for the option " + Name + "!";
333
334   if (Help == other.Help || Help == DefaultHelpString)
335     Help = other.Help;
336   else if (other.Help != DefaultHelpString) {
337     llvm::errs() << "Warning: several different help strings"
338       " defined for option " + Name + "\n";
339   }
340
341   Flags |= other.Flags;
342 }
343
344 bool OptionDescription::isAlias() const {
345   return OptionType::IsAlias(this->Type);
346 }
347
348 bool OptionDescription::isMultiVal() const {
349   return MultiVal > 1;
350 }
351
352 bool OptionDescription::isCommaSeparated() const {
353   return Flags & OptionDescriptionFlags::CommaSeparated;
354 }
355 void OptionDescription::setCommaSeparated() {
356   Flags |= OptionDescriptionFlags::CommaSeparated;
357 }
358
359 bool OptionDescription::isForwardNotSplit() const {
360   return Flags & OptionDescriptionFlags::ForwardNotSplit;
361 }
362 void OptionDescription::setForwardNotSplit() {
363   Flags |= OptionDescriptionFlags::ForwardNotSplit;
364 }
365
366 bool OptionDescription::isRequired() const {
367   return Flags & OptionDescriptionFlags::Required;
368 }
369 void OptionDescription::setRequired() {
370   Flags |= OptionDescriptionFlags::Required;
371 }
372
373 bool OptionDescription::isOneOrMore() const {
374   return Flags & OptionDescriptionFlags::OneOrMore;
375 }
376 void OptionDescription::setOneOrMore() {
377   Flags |= OptionDescriptionFlags::OneOrMore;
378 }
379
380 bool OptionDescription::isZeroOrMore() const {
381   return Flags & OptionDescriptionFlags::ZeroOrMore;
382 }
383 void OptionDescription::setZeroOrMore() {
384   Flags |= OptionDescriptionFlags::ZeroOrMore;
385 }
386
387 bool OptionDescription::isOptional() const {
388   return Flags & OptionDescriptionFlags::Optional;
389 }
390 void OptionDescription::setOptional() {
391   Flags |= OptionDescriptionFlags::Optional;
392 }
393
394 bool OptionDescription::isHidden() const {
395   return Flags & OptionDescriptionFlags::Hidden;
396 }
397 void OptionDescription::setHidden() {
398   Flags |= OptionDescriptionFlags::Hidden;
399 }
400
401 bool OptionDescription::isReallyHidden() const {
402   return Flags & OptionDescriptionFlags::ReallyHidden;
403 }
404 void OptionDescription::setReallyHidden() {
405   Flags |= OptionDescriptionFlags::ReallyHidden;
406 }
407
408 const char* OptionDescription::GenTypeDeclaration() const {
409   switch (Type) {
410   case OptionType::Alias:
411     return "cl::alias";
412   case OptionType::PrefixList:
413   case OptionType::ParameterList:
414     return "cl::list<std::string>";
415   case OptionType::Switch:
416     return "cl::opt<bool>";
417   case OptionType::SwitchList:
418     return "cl::list<bool>";
419   case OptionType::Parameter:
420   case OptionType::Prefix:
421   default:
422     return "cl::opt<std::string>";
423   }
424 }
425
426 std::string OptionDescription::GenOptionType() const {
427   switch (Type) {
428   case OptionType::Alias:
429     return "Alias_";
430   case OptionType::PrefixList:
431   case OptionType::ParameterList:
432     return "List_";
433   case OptionType::Switch:
434     return "Switch_";
435   case OptionType::SwitchList:
436     return "SwitchList_";
437   case OptionType::Prefix:
438   case OptionType::Parameter:
439   default:
440     return "Parameter_";
441   }
442 }
443
444 /// OptionDescriptions - An OptionDescription array plus some helper
445 /// functions.
446 class OptionDescriptions {
447   typedef StringMap<OptionDescription> container_type;
448
449   /// Descriptions - A list of OptionDescriptions.
450   container_type Descriptions;
451
452 public:
453   /// FindOption - exception-throwing wrapper for find().
454   const OptionDescription& FindOption(const std::string& OptName) const;
455
456   // Wrappers for FindOption that throw an exception in case the option has a
457   // wrong type.
458   const OptionDescription& FindSwitch(const std::string& OptName) const;
459   const OptionDescription& FindParameter(const std::string& OptName) const;
460   const OptionDescription& FindParameterList(const std::string& OptName) const;
461   const OptionDescription&
462   FindListOrParameter(const std::string& OptName) const;
463   const OptionDescription&
464   FindParameterListOrParameter(const std::string& OptName) const;
465
466   /// insertDescription - Insert new OptionDescription into
467   /// OptionDescriptions list
468   void InsertDescription (const OptionDescription& o);
469
470   // Support for STL-style iteration
471   typedef container_type::const_iterator const_iterator;
472   const_iterator begin() const { return Descriptions.begin(); }
473   const_iterator end() const { return Descriptions.end(); }
474 };
475
476 const OptionDescription&
477 OptionDescriptions::FindOption(const std::string& OptName) const {
478   const_iterator I = Descriptions.find(OptName);
479   if (I != Descriptions.end())
480     return I->second;
481   else
482     throw OptName + ": no such option!";
483 }
484
485 const OptionDescription&
486 OptionDescriptions::FindSwitch(const std::string& OptName) const {
487   const OptionDescription& OptDesc = this->FindOption(OptName);
488   if (!OptDesc.isSwitch())
489     throw OptName + ": incorrect option type - should be a switch!";
490   return OptDesc;
491 }
492
493 const OptionDescription&
494 OptionDescriptions::FindParameterList(const std::string& OptName) const {
495   const OptionDescription& OptDesc = this->FindOption(OptName);
496   if (!OptDesc.isList() || OptDesc.isSwitchList())
497     throw OptName + ": incorrect option type - should be a parameter list!";
498   return OptDesc;
499 }
500
501 const OptionDescription&
502 OptionDescriptions::FindParameter(const std::string& OptName) const {
503   const OptionDescription& OptDesc = this->FindOption(OptName);
504   if (!OptDesc.isParameter())
505     throw OptName + ": incorrect option type - should be a parameter!";
506   return OptDesc;
507 }
508
509 const OptionDescription&
510 OptionDescriptions::FindListOrParameter(const std::string& OptName) const {
511   const OptionDescription& OptDesc = this->FindOption(OptName);
512   if (!OptDesc.isList() && !OptDesc.isParameter())
513     throw OptName
514       + ": incorrect option type - should be a list or parameter!";
515   return OptDesc;
516 }
517
518 const OptionDescription&
519 OptionDescriptions::FindParameterListOrParameter
520 (const std::string& OptName) const {
521   const OptionDescription& OptDesc = this->FindOption(OptName);
522   if ((!OptDesc.isList() && !OptDesc.isParameter()) || OptDesc.isSwitchList())
523     throw OptName
524       + ": incorrect option type - should be a parameter list or parameter!";
525   return OptDesc;
526 }
527
528 void OptionDescriptions::InsertDescription (const OptionDescription& o) {
529   container_type::iterator I = Descriptions.find(o.Name);
530   if (I != Descriptions.end()) {
531     OptionDescription& D = I->second;
532     D.Merge(o);
533   }
534   else {
535     Descriptions[o.Name] = o;
536   }
537 }
538
539 /// HandlerTable - A base class for function objects implemented as
540 /// 'tables of handlers'.
541 template <typename Handler>
542 class HandlerTable {
543 protected:
544   // Implementation details.
545
546   /// HandlerMap - A map from property names to property handlers
547   typedef StringMap<Handler> HandlerMap;
548
549   static HandlerMap Handlers_;
550   static bool staticMembersInitialized_;
551
552 public:
553
554   Handler GetHandler (const std::string& HandlerName) const {
555     typename HandlerMap::iterator method = Handlers_.find(HandlerName);
556
557     if (method != Handlers_.end()) {
558       Handler h = method->second;
559       return h;
560     }
561     else {
562       throw "No handler found for property " + HandlerName + "!";
563     }
564   }
565
566   void AddHandler(const char* Property, Handler H) {
567     Handlers_[Property] = H;
568   }
569
570 };
571
572 template <class Handler, class FunctionObject>
573 Handler GetHandler(FunctionObject* Obj, const DagInit& Dag) {
574   const std::string& HandlerName = GetOperatorName(Dag);
575   return Obj->GetHandler(HandlerName);
576 }
577
578 template <class FunctionObject>
579 void InvokeDagInitHandler(FunctionObject* Obj, Init* I) {
580   typedef void (FunctionObject::*Handler) (const DagInit&);
581
582   const DagInit& Dag = InitPtrToDag(I);
583   Handler h = GetHandler<Handler>(Obj, Dag);
584
585   ((Obj)->*(h))(Dag);
586 }
587
588 template <class FunctionObject>
589 void InvokeDagInitHandler(const FunctionObject* const Obj,
590                           const Init* I, unsigned IndentLevel, raw_ostream& O)
591 {
592   typedef void (FunctionObject::*Handler)
593     (const DagInit&, unsigned IndentLevel, raw_ostream& O) const;
594
595   const DagInit& Dag = InitPtrToDag(I);
596   Handler h = GetHandler<Handler>(Obj, Dag);
597
598   ((Obj)->*(h))(Dag, IndentLevel, O);
599 }
600
601 template <typename H>
602 typename HandlerTable<H>::HandlerMap HandlerTable<H>::Handlers_;
603
604 template <typename H>
605 bool HandlerTable<H>::staticMembersInitialized_ = false;
606
607
608 /// CollectOptionProperties - Function object for iterating over an
609 /// option property list.
610 class CollectOptionProperties;
611 typedef void (CollectOptionProperties::* CollectOptionPropertiesHandler)
612 (const DagInit&);
613
614 class CollectOptionProperties
615 : public HandlerTable<CollectOptionPropertiesHandler>
616 {
617 private:
618
619   /// optDescs_ - OptionDescriptions table. This is where the
620   /// information is stored.
621   OptionDescription& optDesc_;
622
623 public:
624
625   explicit CollectOptionProperties(OptionDescription& OD)
626     : optDesc_(OD)
627   {
628     if (!staticMembersInitialized_) {
629       AddHandler("help", &CollectOptionProperties::onHelp);
630       AddHandler("hidden", &CollectOptionProperties::onHidden);
631       AddHandler("init", &CollectOptionProperties::onInit);
632       AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
633       AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
634       AddHandler("zero_or_more", &CollectOptionProperties::onZeroOrMore);
635       AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
636       AddHandler("required", &CollectOptionProperties::onRequired);
637       AddHandler("optional", &CollectOptionProperties::onOptional);
638       AddHandler("comma_separated", &CollectOptionProperties::onCommaSeparated);
639       AddHandler("forward_not_split",
640                  &CollectOptionProperties::onForwardNotSplit);
641
642       staticMembersInitialized_ = true;
643     }
644   }
645
646   /// operator() - Just forwards to the corresponding property
647   /// handler.
648   void operator() (Init* I) {
649     InvokeDagInitHandler(this, I);
650   }
651
652 private:
653
654   /// Option property handlers --
655   /// Methods that handle option properties such as (help) or (hidden).
656
657   void onHelp (const DagInit& d) {
658     CheckNumberOfArguments(d, 1);
659     optDesc_.Help = EscapeQuotes(InitPtrToString(d.getArg(0)));
660   }
661
662   void onHidden (const DagInit& d) {
663     CheckNumberOfArguments(d, 0);
664     optDesc_.setHidden();
665   }
666
667   void onReallyHidden (const DagInit& d) {
668     CheckNumberOfArguments(d, 0);
669     optDesc_.setReallyHidden();
670   }
671
672   void onCommaSeparated (const DagInit& d) {
673     CheckNumberOfArguments(d, 0);
674     if (!optDesc_.isParameterList())
675       throw "'comma_separated' is valid only on parameter list options!";
676     optDesc_.setCommaSeparated();
677   }
678
679   void onForwardNotSplit (const DagInit& d) {
680     CheckNumberOfArguments(d, 0);
681     if (!optDesc_.isParameter())
682       throw "'forward_not_split' is valid only for parameter options!";
683     optDesc_.setForwardNotSplit();
684   }
685
686   void onRequired (const DagInit& d) {
687     CheckNumberOfArguments(d, 0);
688
689     optDesc_.setRequired();
690     optDesc_.CheckConsistency();
691   }
692
693   void onInit (const DagInit& d) {
694     CheckNumberOfArguments(d, 1);
695     Init* i = d.getArg(0);
696     const std::string& str = i->getAsString();
697
698     bool correct = optDesc_.isParameter() && dynamic_cast<StringInit*>(i);
699     correct |= (optDesc_.isSwitch() && (str == "true" || str == "false"));
700
701     if (!correct)
702       throw "Incorrect usage of the 'init' option property!";
703
704     optDesc_.InitVal = i;
705   }
706
707   void onOneOrMore (const DagInit& d) {
708     CheckNumberOfArguments(d, 0);
709
710     optDesc_.setOneOrMore();
711     optDesc_.CheckConsistency();
712   }
713
714   void onZeroOrMore (const DagInit& d) {
715     CheckNumberOfArguments(d, 0);
716
717     if (optDesc_.isList())
718       llvm::errs() << "Warning: specifying the 'zero_or_more' property "
719         "on a list option has no effect.\n";
720
721     optDesc_.setZeroOrMore();
722     optDesc_.CheckConsistency();
723   }
724
725   void onOptional (const DagInit& d) {
726     CheckNumberOfArguments(d, 0);
727
728     if (!optDesc_.isList())
729       llvm::errs() << "Warning: specifying the 'optional' property"
730         "on a non-list option has no effect.\n";
731
732     optDesc_.setOptional();
733     optDesc_.CheckConsistency();
734   }
735
736   void onMultiVal (const DagInit& d) {
737     CheckNumberOfArguments(d, 1);
738     int val = InitPtrToInt(d.getArg(0));
739     if (val < 2)
740       throw "Error in the 'multi_val' property: "
741         "the value must be greater than 1!";
742     if (!optDesc_.isParameterList())
743       throw "The multi_val property is valid only on list options!";
744     optDesc_.MultiVal = val;
745   }
746
747 };
748
749 /// AddOption - A function object that is applied to every option
750 /// description. Used by CollectOptionDescriptions.
751 class AddOption {
752 private:
753   OptionDescriptions& OptDescs_;
754
755 public:
756   explicit AddOption(OptionDescriptions& OD) : OptDescs_(OD)
757   {}
758
759   void operator()(const Init* i) {
760     const DagInit& d = InitPtrToDag(i);
761     CheckNumberOfArguments(d, 1);
762
763     const OptionType::OptionType Type =
764       stringToOptionType(GetOperatorName(d));
765     const std::string& Name = InitPtrToString(d.getArg(0));
766
767     OptionDescription OD(Type, Name);
768
769     CheckNumberOfArguments(d, 2);
770
771     // Alias option store the aliased option name in the 'Help' field and do not
772     // have any properties.
773     if (OD.isAlias()) {
774       OD.Help = InitPtrToString(d.getArg(1));
775     }
776     else {
777       processOptionProperties(d, OD);
778     }
779
780     // Switch options are ZeroOrMore by default.
781     if (OD.isSwitch()) {
782       if (!(OD.isOptional() || OD.isOneOrMore() || OD.isRequired()))
783         OD.setZeroOrMore();
784     }
785
786     OptDescs_.InsertDescription(OD);
787   }
788
789 private:
790   /// processOptionProperties - Go through the list of option
791   /// properties and call a corresponding handler for each.
792   static void processOptionProperties (const DagInit& d, OptionDescription& o) {
793     CheckNumberOfArguments(d, 2);
794     DagInit::const_arg_iterator B = d.arg_begin();
795     // Skip the first argument: it's always the option name.
796     ++B;
797     std::for_each(B, d.arg_end(), CollectOptionProperties(o));
798   }
799
800 };
801
802 /// CollectOptionDescriptions - Collects option properties from all
803 /// OptionLists.
804 void CollectOptionDescriptions (const RecordVector& V,
805                                 OptionDescriptions& OptDescs)
806 {
807   // For every OptionList:
808   for (RecordVector::const_iterator B = V.begin(), E = V.end(); B!=E; ++B)
809   {
810     // Throws an exception if the value does not exist.
811     ListInit* PropList = (*B)->getValueAsListInit("options");
812
813     // For every option description in this list: invoke AddOption.
814     std::for_each(PropList->begin(), PropList->end(), AddOption(OptDescs));
815   }
816 }
817
818 // Tool information record
819
820 namespace ToolFlags {
821   enum ToolFlags { Join = 0x1, Sink = 0x2 };
822 }
823
824 struct ToolDescription : public RefCountedBase<ToolDescription> {
825   std::string Name;
826   Init* CmdLine;
827   Init* Actions;
828   StrVector InLanguage;
829   std::string InFileOption;
830   std::string OutFileOption;
831   StrVector OutLanguage;
832   std::string OutputSuffix;
833   unsigned Flags;
834   const Init* OnEmpty;
835
836   // Various boolean properties
837   void setSink()      { Flags |= ToolFlags::Sink; }
838   bool isSink() const { return Flags & ToolFlags::Sink; }
839   void setJoin()      { Flags |= ToolFlags::Join; }
840   bool isJoin() const { return Flags & ToolFlags::Join; }
841
842   // Default ctor here is needed because StringMap can only store
843   // DefaultConstructible objects
844   ToolDescription (const std::string &n = "")
845     : Name(n), CmdLine(0), Actions(0), OutFileOption("-o"),
846       Flags(0), OnEmpty(0)
847   {}
848 };
849
850 /// ToolDescriptions - A list of Tool information records.
851 typedef std::vector<IntrusiveRefCntPtr<ToolDescription> > ToolDescriptions;
852
853
854 /// CollectToolProperties - Function object for iterating over a list of
855 /// tool property records.
856
857 class CollectToolProperties;
858 typedef void (CollectToolProperties::* CollectToolPropertiesHandler)
859 (const DagInit&);
860
861 class CollectToolProperties : public HandlerTable<CollectToolPropertiesHandler>
862 {
863 private:
864
865   /// toolDesc_ - Properties of the current Tool. This is where the
866   /// information is stored.
867   ToolDescription& toolDesc_;
868
869 public:
870
871   explicit CollectToolProperties (ToolDescription& d)
872     : toolDesc_(d)
873   {
874     if (!staticMembersInitialized_) {
875
876       AddHandler("actions", &CollectToolProperties::onActions);
877       AddHandler("command", &CollectToolProperties::onCommand);
878       AddHandler("in_language", &CollectToolProperties::onInLanguage);
879       AddHandler("join", &CollectToolProperties::onJoin);
880       AddHandler("out_language", &CollectToolProperties::onOutLanguage);
881
882       AddHandler("out_file_option", &CollectToolProperties::onOutFileOption);
883       AddHandler("in_file_option", &CollectToolProperties::onInFileOption);
884
885       AddHandler("output_suffix", &CollectToolProperties::onOutputSuffix);
886       AddHandler("sink", &CollectToolProperties::onSink);
887       AddHandler("works_on_empty", &CollectToolProperties::onWorksOnEmpty);
888
889       staticMembersInitialized_ = true;
890     }
891   }
892
893   void operator() (Init* I) {
894     InvokeDagInitHandler(this, I);
895   }
896
897 private:
898
899   /// Property handlers --
900   /// Functions that extract information about tool properties from
901   /// DAG representation.
902
903   void onActions (const DagInit& d) {
904     CheckNumberOfArguments(d, 1);
905     Init* Case = d.getArg(0);
906     if (typeid(*Case) != typeid(DagInit) ||
907         GetOperatorName(static_cast<DagInit&>(*Case)) != "case")
908       throw "The argument to (actions) should be a 'case' construct!";
909     toolDesc_.Actions = Case;
910   }
911
912   void onCommand (const DagInit& d) {
913     CheckNumberOfArguments(d, 1);
914     toolDesc_.CmdLine = d.getArg(0);
915   }
916
917   /// onInOutLanguage - Common implementation of on{In,Out}Language().
918   void onInOutLanguage (const DagInit& d, StrVector& OutVec) {
919     CheckNumberOfArguments(d, 1);
920
921     // Copy strings to the output vector.
922     for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) {
923       OutVec.push_back(InitPtrToString(d.getArg(i)));
924     }
925
926     // Remove duplicates.
927     std::sort(OutVec.begin(), OutVec.end());
928     StrVector::iterator newE = std::unique(OutVec.begin(), OutVec.end());
929     OutVec.erase(newE, OutVec.end());
930   }
931
932
933   void onInLanguage (const DagInit& d) {
934     this->onInOutLanguage(d, toolDesc_.InLanguage);
935   }
936
937   void onJoin (const DagInit& d) {
938     CheckNumberOfArguments(d, 0);
939     toolDesc_.setJoin();
940   }
941
942   void onOutLanguage (const DagInit& d) {
943     this->onInOutLanguage(d, toolDesc_.OutLanguage);
944   }
945
946   void onOutFileOption (const DagInit& d) {
947     CheckNumberOfArguments(d, 1);
948     toolDesc_.OutFileOption = InitPtrToString(d.getArg(0));
949   }
950
951   void onInFileOption (const DagInit& d) {
952     CheckNumberOfArguments(d, 1);
953     toolDesc_.InFileOption = InitPtrToString(d.getArg(0));
954   }
955
956   void onOutputSuffix (const DagInit& d) {
957     CheckNumberOfArguments(d, 1);
958     toolDesc_.OutputSuffix = InitPtrToString(d.getArg(0));
959   }
960
961   void onSink (const DagInit& d) {
962     CheckNumberOfArguments(d, 0);
963     toolDesc_.setSink();
964   }
965
966   void onWorksOnEmpty (const DagInit& d) {
967     toolDesc_.OnEmpty = d.getArg(0);
968   }
969
970 };
971
972 /// CollectToolDescriptions - Gather information about tool properties
973 /// from the parsed TableGen data (basically a wrapper for the
974 /// CollectToolProperties function object).
975 void CollectToolDescriptions (const RecordVector& Tools,
976                               ToolDescriptions& ToolDescs)
977 {
978   // Iterate over a properties list of every Tool definition
979   for (RecordVector::const_iterator B = Tools.begin(),
980          E = Tools.end(); B!=E; ++B) {
981     const Record* T = *B;
982     // Throws an exception if the value does not exist.
983     ListInit* PropList = T->getValueAsListInit("properties");
984
985     IntrusiveRefCntPtr<ToolDescription>
986       ToolDesc(new ToolDescription(T->getName()));
987
988     std::for_each(PropList->begin(), PropList->end(),
989                   CollectToolProperties(*ToolDesc));
990     ToolDescs.push_back(ToolDesc);
991   }
992 }
993
994 /// FillInEdgeVector - Merge all compilation graph definitions into
995 /// one single edge list.
996 void FillInEdgeVector(const RecordVector& CompilationGraphs,
997                       DagVector& Out) {
998   for (RecordVector::const_iterator B = CompilationGraphs.begin(),
999          E = CompilationGraphs.end(); B != E; ++B) {
1000     const ListInit* Edges = (*B)->getValueAsListInit("edges");
1001
1002     for (ListInit::const_iterator B = Edges->begin(),
1003            E = Edges->end(); B != E; ++B) {
1004       Out.push_back(&InitPtrToDag(*B));
1005     }
1006   }
1007 }
1008
1009 /// NotInGraph - Helper function object for FilterNotInGraph.
1010 struct NotInGraph {
1011 private:
1012   const llvm::StringSet<>& ToolsInGraph_;
1013
1014 public:
1015   NotInGraph(const llvm::StringSet<>& ToolsInGraph)
1016   : ToolsInGraph_(ToolsInGraph)
1017   {}
1018
1019   bool operator()(const IntrusiveRefCntPtr<ToolDescription>& x) {
1020     return (ToolsInGraph_.count(x->Name) == 0);
1021   }
1022 };
1023
1024 /// FilterNotInGraph - Filter out from ToolDescs all Tools not
1025 /// mentioned in the compilation graph definition.
1026 void FilterNotInGraph (const DagVector& EdgeVector,
1027                        ToolDescriptions& ToolDescs) {
1028
1029   // List all tools mentioned in the graph.
1030   llvm::StringSet<> ToolsInGraph;
1031
1032   for (DagVector::const_iterator B = EdgeVector.begin(),
1033          E = EdgeVector.end(); B != E; ++B) {
1034
1035     const DagInit* Edge = *B;
1036     const std::string& NodeA = InitPtrToString(Edge->getArg(0));
1037     const std::string& NodeB = InitPtrToString(Edge->getArg(1));
1038
1039     if (NodeA != "root")
1040       ToolsInGraph.insert(NodeA);
1041     ToolsInGraph.insert(NodeB);
1042   }
1043
1044   // Filter ToolPropertiesList.
1045   ToolDescriptions::iterator new_end =
1046     std::remove_if(ToolDescs.begin(), ToolDescs.end(),
1047                    NotInGraph(ToolsInGraph));
1048   ToolDescs.erase(new_end, ToolDescs.end());
1049 }
1050
1051 /// FillInToolToLang - Fills in two tables that map tool names to
1052 /// input & output language names.  Helper function used by TypecheckGraph().
1053 void FillInToolToLang (const ToolDescriptions& ToolDescs,
1054                        StringMap<StringSet<> >& ToolToInLang,
1055                        StringMap<StringSet<> >& ToolToOutLang) {
1056   for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
1057          E = ToolDescs.end(); B != E; ++B) {
1058     const ToolDescription& D = *(*B);
1059     for (StrVector::const_iterator B = D.InLanguage.begin(),
1060            E = D.InLanguage.end(); B != E; ++B)
1061       ToolToInLang[D.Name].insert(*B);
1062     for (StrVector::const_iterator B = D.OutLanguage.begin(),
1063            E = D.OutLanguage.end(); B != E; ++B)
1064       ToolToOutLang[D.Name].insert(*B);
1065   }
1066 }
1067
1068 /// Intersect - Is set intersection non-empty?
1069 bool Intersect (const StringSet<>& S1, const StringSet<>& S2) {
1070   for (StringSet<>::const_iterator B = S1.begin(), E = S1.end(); B != E; ++B) {
1071     if (S2.count(B->first()) != 0)
1072       return true;
1073   }
1074   return false;
1075 }
1076
1077 /// TypecheckGraph - Check that names for output and input languages
1078 /// on all edges do match.
1079 void TypecheckGraph (const DagVector& EdgeVector,
1080                      const ToolDescriptions& ToolDescs) {
1081   StringMap<StringSet<> > ToolToInLang;
1082   StringMap<StringSet<> > ToolToOutLang;
1083
1084   FillInToolToLang(ToolDescs, ToolToInLang, ToolToOutLang);
1085
1086   for (DagVector::const_iterator B = EdgeVector.begin(),
1087          E = EdgeVector.end(); B != E; ++B) {
1088     const DagInit* Edge = *B;
1089     const std::string& NodeA = InitPtrToString(Edge->getArg(0));
1090     const std::string& NodeB = InitPtrToString(Edge->getArg(1));
1091     StringMap<StringSet<> >::iterator IA = ToolToOutLang.find(NodeA);
1092     StringMap<StringSet<> >::iterator IB = ToolToInLang.find(NodeB);
1093
1094     if (NodeB == "root")
1095       throw "Edges back to the root are not allowed!";
1096
1097     if (NodeA != "root") {
1098       if (IA == ToolToOutLang.end())
1099         throw NodeA + ": no output language defined!";
1100       if (IB == ToolToInLang.end())
1101         throw NodeB + ": no input language defined!";
1102
1103       if (!Intersect(IA->second, IB->second)) {
1104         throw "Edge " + NodeA + "->" + NodeB
1105           + ": output->input language mismatch";
1106       }
1107     }
1108   }
1109 }
1110
1111 /// WalkCase - Walks the 'case' expression DAG and invokes
1112 /// TestCallback on every test, and StatementCallback on every
1113 /// statement. Handles 'case' nesting, but not the 'and' and 'or'
1114 /// combinators (that is, they are passed directly to TestCallback).
1115 /// TestCallback must have type 'void TestCallback(const DagInit*, unsigned
1116 /// IndentLevel, bool FirstTest)'.
1117 /// StatementCallback must have type 'void StatementCallback(const Init*,
1118 /// unsigned IndentLevel)'.
1119 template <typename F1, typename F2>
1120 void WalkCase(const Init* Case, F1 TestCallback, F2 StatementCallback,
1121               unsigned IndentLevel = 0)
1122 {
1123   const DagInit& d = InitPtrToDag(Case);
1124
1125   // Error checks.
1126   if (GetOperatorName(d) != "case")
1127     throw "WalkCase should be invoked only on 'case' expressions!";
1128
1129   if (d.getNumArgs() < 2)
1130     throw "There should be at least one clause in the 'case' expression:\n"
1131       + d.getAsString();
1132
1133   // Main loop.
1134   bool even = false;
1135   const unsigned numArgs = d.getNumArgs();
1136   unsigned i = 1;
1137   for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
1138        B != E; ++B) {
1139     Init* arg = *B;
1140
1141     if (!even)
1142     {
1143       // Handle test.
1144       const DagInit& Test = InitPtrToDag(arg);
1145
1146       if (GetOperatorName(Test) == "default" && (i+1 != numArgs))
1147         throw "The 'default' clause should be the last in the "
1148           "'case' construct!";
1149       if (i == numArgs)
1150         throw "Case construct handler: no corresponding action "
1151           "found for the test " + Test.getAsString() + '!';
1152
1153       TestCallback(Test, IndentLevel, (i == 1));
1154     }
1155     else
1156     {
1157       if (dynamic_cast<DagInit*>(arg)
1158           && GetOperatorName(static_cast<DagInit&>(*arg)) == "case") {
1159         // Nested 'case'.
1160         WalkCase(arg, TestCallback, StatementCallback, IndentLevel + Indent1);
1161       }
1162
1163       // Handle statement.
1164       StatementCallback(arg, IndentLevel);
1165     }
1166
1167     ++i;
1168     even = !even;
1169   }
1170 }
1171
1172 /// ExtractOptionNames - A helper function object used by
1173 /// CheckForSuperfluousOptions() to walk the 'case' DAG.
1174 class ExtractOptionNames {
1175   llvm::StringSet<>& OptionNames_;
1176
1177   void processDag(const Init* Statement) {
1178     const DagInit& Stmt = InitPtrToDag(Statement);
1179     const std::string& ActionName = GetOperatorName(Stmt);
1180     if (ActionName == "forward" || ActionName == "forward_as" ||
1181         ActionName == "forward_value" ||
1182         ActionName == "forward_transformed_value" ||
1183         ActionName == "parameter_equals" || ActionName == "element_in_list") {
1184       CheckNumberOfArguments(Stmt, 1);
1185
1186       Init* Arg = Stmt.getArg(0);
1187       if (typeid(*Arg) == typeid(StringInit))
1188         OptionNames_.insert(InitPtrToString(Arg));
1189     }
1190     else if (ActionName == "any_switch_on" || ActionName == "switch_on" ||
1191              ActionName == "any_not_empty" || ActionName == "any_empty" ||
1192              ActionName == "not_empty" || ActionName == "empty") {
1193       for (unsigned i = 0, NumArgs = Stmt.getNumArgs(); i < NumArgs; ++i) {
1194         Init* Arg = Stmt.getArg(i);
1195         if (typeid(*Arg) == typeid(StringInit))
1196           OptionNames_.insert(InitPtrToString(Arg));
1197       }
1198     }
1199     else if (ActionName == "and" || ActionName == "or" || ActionName == "not") {
1200       for (unsigned i = 0, NumArgs = Stmt.getNumArgs(); i < NumArgs; ++i) {
1201         this->processDag(Stmt.getArg(i));
1202       }
1203     }
1204   }
1205
1206 public:
1207   ExtractOptionNames(llvm::StringSet<>& OptionNames) : OptionNames_(OptionNames)
1208   {}
1209
1210   void operator()(const Init* Statement) {
1211     // Statement is either a dag, or a list of dags.
1212     if (typeid(*Statement) == typeid(ListInit)) {
1213       const ListInit& DagList = *static_cast<const ListInit*>(Statement);
1214       for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
1215            B != E; ++B)
1216         this->processDag(*B);
1217     }
1218     else {
1219       this->processDag(Statement);
1220     }
1221   }
1222
1223   void operator()(const DagInit& Test, unsigned, bool) {
1224     this->operator()(&Test);
1225   }
1226   void operator()(const Init* Statement, unsigned) {
1227     this->operator()(Statement);
1228   }
1229 };
1230
1231 /// IsOptionalEdge - Validate that the 'optional_edge' has proper structure.
1232 bool IsOptionalEdge (const DagInit& Edg) {
1233   return (GetOperatorName(Edg) == "optional_edge") && (Edg.getNumArgs() > 2);
1234 }
1235
1236 /// CheckForSuperfluousOptions - Check that there are no side
1237 /// effect-free options (specified only in the OptionList). Otherwise,
1238 /// output a warning.
1239 void CheckForSuperfluousOptions (const DagVector& EdgeVector,
1240                                  const ToolDescriptions& ToolDescs,
1241                                  const OptionDescriptions& OptDescs) {
1242   llvm::StringSet<> nonSuperfluousOptions;
1243
1244   // Add all options mentioned in the ToolDesc.Actions to the set of
1245   // non-superfluous options.
1246   for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
1247          E = ToolDescs.end(); B != E; ++B) {
1248     const ToolDescription& TD = *(*B);
1249     ExtractOptionNames Callback(nonSuperfluousOptions);
1250     if (TD.Actions)
1251       WalkCase(TD.Actions, Callback, Callback);
1252   }
1253
1254   // Add all options mentioned in the 'case' clauses of the
1255   // OptionalEdges of the compilation graph to the set of
1256   // non-superfluous options.
1257   for (DagVector::const_iterator B = EdgeVector.begin(),
1258          E = EdgeVector.end(); B != E; ++B) {
1259     const DagInit& Edge = **B;
1260     if (IsOptionalEdge(Edge)) {
1261       const DagInit& Weight = InitPtrToDag(Edge.getArg(2));
1262       WalkCase(&Weight, ExtractOptionNames(nonSuperfluousOptions), Id());
1263     }
1264   }
1265
1266   // Check that all options in OptDescs belong to the set of
1267   // non-superfluous options.
1268   for (OptionDescriptions::const_iterator B = OptDescs.begin(),
1269          E = OptDescs.end(); B != E; ++B) {
1270     const OptionDescription& Val = B->second;
1271     if (!nonSuperfluousOptions.count(Val.Name)
1272         && Val.Type != OptionType::Alias)
1273       llvm::errs() << "Warning: option '-" << Val.Name << "' has no effect! "
1274         "Probable cause: this option is specified only in the OptionList.\n";
1275   }
1276 }
1277
1278 /// EmitCaseTest0Args - Helper function used by EmitCaseConstructHandler().
1279 bool EmitCaseTest0Args(const std::string& TestName, raw_ostream& O) {
1280   if (TestName == "single_input_file") {
1281     O << "InputFilenames.size() == 1";
1282     return true;
1283   }
1284   else if (TestName == "multiple_input_files") {
1285     O << "InputFilenames.size() > 1";
1286     return true;
1287   }
1288
1289   return false;
1290 }
1291
1292 /// EmitMultipleArgumentTest - Helper function used by
1293 /// EmitCaseTestMultipleArgs()
1294 template <typename F>
1295 void EmitMultipleArgumentTest(const DagInit& D, const char* LogicOp,
1296                               F Callback, raw_ostream& O)
1297 {
1298   for (unsigned i = 0, NumArgs = D.getNumArgs(); i < NumArgs; ++i) {
1299     if (i != 0)
1300        O << ' ' << LogicOp << ' ';
1301     Callback(InitPtrToString(D.getArg(i)), O);
1302   }
1303 }
1304
1305 // Callbacks for use with EmitMultipleArgumentTest
1306
1307 class EmitSwitchOn {
1308   const OptionDescriptions& OptDescs_;
1309 public:
1310   EmitSwitchOn(const OptionDescriptions& OptDescs) : OptDescs_(OptDescs)
1311   {}
1312
1313   void operator()(const std::string& OptName, raw_ostream& O) const {
1314     const OptionDescription& OptDesc = OptDescs_.FindSwitch(OptName);
1315     O << OptDesc.GenVariableName();
1316   }
1317 };
1318
1319 class EmitEmptyTest {
1320   bool EmitNegate_;
1321   const OptionDescriptions& OptDescs_;
1322 public:
1323   EmitEmptyTest(bool EmitNegate, const OptionDescriptions& OptDescs)
1324     : EmitNegate_(EmitNegate), OptDescs_(OptDescs)
1325   {}
1326
1327   void operator()(const std::string& OptName, raw_ostream& O) const {
1328     const char* Neg = (EmitNegate_ ? "!" : "");
1329     if (OptName == "o") {
1330       O << Neg << "OutputFilename.empty()";
1331     }
1332     else if (OptName == "save-temps") {
1333       O << Neg << "(SaveTemps == SaveTempsEnum::Unset)";
1334     }
1335     else {
1336       const OptionDescription& OptDesc = OptDescs_.FindListOrParameter(OptName);
1337       O << Neg << OptDesc.GenVariableName() << ".empty()";
1338     }
1339   }
1340 };
1341
1342
1343 /// EmitCaseTestMultipleArgs - Helper function used by EmitCaseTest1Arg()
1344 bool EmitCaseTestMultipleArgs (const std::string& TestName,
1345                                const DagInit& d,
1346                                const OptionDescriptions& OptDescs,
1347                                raw_ostream& O) {
1348   if (TestName == "any_switch_on") {
1349     EmitMultipleArgumentTest(d, "||", EmitSwitchOn(OptDescs), O);
1350     return true;
1351   }
1352   else if (TestName == "switch_on") {
1353     EmitMultipleArgumentTest(d, "&&", EmitSwitchOn(OptDescs), O);
1354     return true;
1355   }
1356   else if (TestName == "any_not_empty") {
1357     EmitMultipleArgumentTest(d, "||", EmitEmptyTest(true, OptDescs), O);
1358     return true;
1359   }
1360   else if (TestName == "any_empty") {
1361     EmitMultipleArgumentTest(d, "||", EmitEmptyTest(false, OptDescs), O);
1362     return true;
1363   }
1364   else if (TestName == "not_empty") {
1365     EmitMultipleArgumentTest(d, "&&", EmitEmptyTest(true, OptDescs), O);
1366     return true;
1367   }
1368   else if (TestName == "empty") {
1369     EmitMultipleArgumentTest(d, "&&", EmitEmptyTest(false, OptDescs), O);
1370     return true;
1371   }
1372
1373   return false;
1374 }
1375
1376 /// EmitCaseTest1Arg - Helper function used by EmitCaseTest1OrMoreArgs()
1377 bool EmitCaseTest1Arg (const std::string& TestName,
1378                        const DagInit& d,
1379                        const OptionDescriptions& OptDescs,
1380                        raw_ostream& O) {
1381   const std::string& Arg = InitPtrToString(d.getArg(0));
1382
1383   if (TestName == "input_languages_contain") {
1384     O << "InLangs.count(\"" << Arg << "\") != 0";
1385     return true;
1386   }
1387   else if (TestName == "in_language") {
1388     // This works only for single-argument Tool::GenerateAction. Join
1389     // tools can process several files in different languages simultaneously.
1390
1391     // TODO: make this work with Edge::Weight (if possible).
1392     O << "LangMap.GetLanguage(inFile) == \"" << Arg << '\"';
1393     return true;
1394   }
1395
1396   return false;
1397 }
1398
1399 /// EmitCaseTest1OrMoreArgs - Helper function used by
1400 /// EmitCaseConstructHandler()
1401 bool EmitCaseTest1OrMoreArgs(const std::string& TestName,
1402                              const DagInit& d,
1403                              const OptionDescriptions& OptDescs,
1404                              raw_ostream& O) {
1405   CheckNumberOfArguments(d, 1);
1406   return EmitCaseTest1Arg(TestName, d, OptDescs, O) ||
1407     EmitCaseTestMultipleArgs(TestName, d, OptDescs, O);
1408 }
1409
1410 /// EmitCaseTest2Args - Helper function used by EmitCaseConstructHandler().
1411 bool EmitCaseTest2Args(const std::string& TestName,
1412                        const DagInit& d,
1413                        unsigned IndentLevel,
1414                        const OptionDescriptions& OptDescs,
1415                        raw_ostream& O) {
1416   CheckNumberOfArguments(d, 2);
1417   const std::string& OptName = InitPtrToString(d.getArg(0));
1418   const std::string& OptArg = InitPtrToString(d.getArg(1));
1419
1420   if (TestName == "parameter_equals") {
1421     const OptionDescription& OptDesc = OptDescs.FindParameter(OptName);
1422     O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
1423     return true;
1424   }
1425   else if (TestName == "element_in_list") {
1426     const OptionDescription& OptDesc = OptDescs.FindParameterList(OptName);
1427     const std::string& VarName = OptDesc.GenVariableName();
1428     O << "std::find(" << VarName << ".begin(),\n";
1429     O.indent(IndentLevel + Indent1)
1430       << VarName << ".end(), \""
1431       << OptArg << "\") != " << VarName << ".end()";
1432     return true;
1433   }
1434
1435   return false;
1436 }
1437
1438 // Forward declaration.
1439 // EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
1440 void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
1441                   const OptionDescriptions& OptDescs,
1442                   raw_ostream& O);
1443
1444 /// EmitLogicalOperationTest - Helper function used by
1445 /// EmitCaseConstructHandler.
1446 void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp,
1447                               unsigned IndentLevel,
1448                               const OptionDescriptions& OptDescs,
1449                               raw_ostream& O) {
1450   O << '(';
1451   for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) {
1452     const DagInit& InnerTest = InitPtrToDag(d.getArg(i));
1453     EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
1454     if (i != NumArgs - 1) {
1455       O << ")\n";
1456       O.indent(IndentLevel + Indent1) << ' ' << LogicOp << " (";
1457     }
1458     else {
1459       O << ')';
1460     }
1461   }
1462 }
1463
1464 void EmitLogicalNot(const DagInit& d, unsigned IndentLevel,
1465                     const OptionDescriptions& OptDescs, raw_ostream& O)
1466 {
1467   CheckNumberOfArguments(d, 1);
1468   const DagInit& InnerTest = InitPtrToDag(d.getArg(0));
1469   O << "! (";
1470   EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
1471   O << ")";
1472 }
1473
1474 /// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
1475 void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
1476                   const OptionDescriptions& OptDescs,
1477                   raw_ostream& O) {
1478   const std::string& TestName = GetOperatorName(d);
1479
1480   if (TestName == "and")
1481     EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);
1482   else if (TestName == "or")
1483     EmitLogicalOperationTest(d, "||", IndentLevel, OptDescs, O);
1484   else if (TestName == "not")
1485     EmitLogicalNot(d, IndentLevel, OptDescs, O);
1486   else if (EmitCaseTest0Args(TestName, O))
1487     return;
1488   else if (EmitCaseTest1OrMoreArgs(TestName, d, OptDescs, O))
1489     return;
1490   else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O))
1491     return;
1492   else
1493     throw "Unknown test '" + TestName + "' used in the 'case' construct!";
1494 }
1495
1496
1497 /// EmitCaseTestCallback - Callback used by EmitCaseConstructHandler.
1498 class EmitCaseTestCallback {
1499   bool EmitElseIf_;
1500   const OptionDescriptions& OptDescs_;
1501   raw_ostream& O_;
1502 public:
1503
1504   EmitCaseTestCallback(bool EmitElseIf,
1505                        const OptionDescriptions& OptDescs, raw_ostream& O)
1506     : EmitElseIf_(EmitElseIf), OptDescs_(OptDescs), O_(O)
1507   {}
1508
1509   void operator()(const DagInit& Test, unsigned IndentLevel, bool FirstTest)
1510   {
1511     if (GetOperatorName(Test) == "default") {
1512       O_.indent(IndentLevel) << "else {\n";
1513     }
1514     else {
1515       O_.indent(IndentLevel)
1516         << ((!FirstTest && EmitElseIf_) ? "else if (" : "if (");
1517       EmitCaseTest(Test, IndentLevel, OptDescs_, O_);
1518       O_ << ") {\n";
1519     }
1520   }
1521 };
1522
1523 /// EmitCaseStatementCallback - Callback used by EmitCaseConstructHandler.
1524 template <typename F>
1525 class EmitCaseStatementCallback {
1526   F Callback_;
1527   raw_ostream& O_;
1528 public:
1529
1530   EmitCaseStatementCallback(F Callback, raw_ostream& O)
1531     : Callback_(Callback), O_(O)
1532   {}
1533
1534   void operator() (const Init* Statement, unsigned IndentLevel) {
1535     // Is this a nested 'case'?
1536     bool IsCase = dynamic_cast<const DagInit*>(Statement) &&
1537       GetOperatorName(static_cast<const DagInit&>(*Statement)) == "case";
1538
1539     // If so, ignore it, it is handled by our caller, WalkCase.
1540     if (!IsCase) {
1541       if (typeid(*Statement) == typeid(ListInit)) {
1542         const ListInit& DagList = *static_cast<const ListInit*>(Statement);
1543         for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
1544              B != E; ++B)
1545           Callback_(*B, (IndentLevel + Indent1), O_);
1546       }
1547       else {
1548         Callback_(Statement, (IndentLevel + Indent1), O_);
1549       }
1550     }
1551     O_.indent(IndentLevel) << "}\n";
1552   }
1553
1554 };
1555
1556 /// EmitCaseConstructHandler - Emit code that handles the 'case'
1557 /// construct. Takes a function object that should emit code for every case
1558 /// clause. Implemented on top of WalkCase.
1559 /// Callback's type is void F(const Init* Statement, unsigned IndentLevel,
1560 /// raw_ostream& O).
1561 /// EmitElseIf parameter controls the type of condition that is emitted ('if
1562 /// (..) {..} else if (..) {} .. else {..}' vs. 'if (..) {..} if(..)  {..}
1563 /// .. else {..}').
1564 template <typename F>
1565 void EmitCaseConstructHandler(const Init* Case, unsigned IndentLevel,
1566                               F Callback, bool EmitElseIf,
1567                               const OptionDescriptions& OptDescs,
1568                               raw_ostream& O) {
1569   WalkCase(Case, EmitCaseTestCallback(EmitElseIf, OptDescs, O),
1570            EmitCaseStatementCallback<F>(Callback, O), IndentLevel);
1571 }
1572
1573 /// TokenizeCmdLine - converts from
1574 /// "$CALL(HookName, 'Arg1', 'Arg2')/path -arg1 -arg2" to
1575 /// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path", "-arg1", "-arg2"].
1576 void TokenizeCmdLine(const std::string& CmdLine, StrVector& Out) {
1577   const char* Delimiters = " \t\n\v\f\r";
1578   enum TokenizerState
1579   { Normal, SpecialCommand, InsideSpecialCommand, InsideQuotationMarks }
1580   cur_st  = Normal;
1581
1582   if (CmdLine.empty())
1583     return;
1584   Out.push_back("");
1585
1586   std::string::size_type B = CmdLine.find_first_not_of(Delimiters),
1587     E = CmdLine.size();
1588
1589   for (; B != E; ++B) {
1590     char cur_ch = CmdLine[B];
1591
1592     switch (cur_st) {
1593     case Normal:
1594       if (cur_ch == '$') {
1595         cur_st = SpecialCommand;
1596         break;
1597       }
1598       if (OneOf(Delimiters, cur_ch)) {
1599         // Skip whitespace
1600         B = CmdLine.find_first_not_of(Delimiters, B);
1601         if (B == std::string::npos) {
1602           B = E-1;
1603           continue;
1604         }
1605         --B;
1606         Out.push_back("");
1607         continue;
1608       }
1609       break;
1610
1611
1612     case SpecialCommand:
1613       if (OneOf(Delimiters, cur_ch)) {
1614         cur_st = Normal;
1615         Out.push_back("");
1616         continue;
1617       }
1618       if (cur_ch == '(') {
1619         Out.push_back("");
1620         cur_st = InsideSpecialCommand;
1621         continue;
1622       }
1623       break;
1624
1625     case InsideSpecialCommand:
1626       if (OneOf(Delimiters, cur_ch)) {
1627         continue;
1628       }
1629       if (cur_ch == '\'') {
1630         cur_st = InsideQuotationMarks;
1631         Out.push_back("");
1632         continue;
1633       }
1634       if (cur_ch == ')') {
1635         cur_st = Normal;
1636         Out.push_back("");
1637       }
1638       if (cur_ch == ',') {
1639         continue;
1640       }
1641
1642       break;
1643
1644     case InsideQuotationMarks:
1645       if (cur_ch == '\'') {
1646         cur_st = InsideSpecialCommand;
1647         continue;
1648       }
1649       break;
1650     }
1651
1652     Out.back().push_back(cur_ch);
1653   }
1654 }
1655
1656 /// SubstituteCall - Given "$CALL(HookName, [Arg1 [, Arg2 [...]]])", output
1657 /// "hooks::HookName([Arg1 [, Arg2 [, ...]]])". Helper function used by
1658 /// SubstituteSpecialCommands().
1659 StrVector::const_iterator
1660 SubstituteCall (StrVector::const_iterator Pos,
1661                 StrVector::const_iterator End,
1662                 bool IsJoin, raw_ostream& O)
1663 {
1664   const char* errorMessage = "Syntax error in $CALL invocation!";
1665   CheckedIncrement(Pos, End, errorMessage);
1666   const std::string& CmdName = *Pos;
1667
1668   if (CmdName == ")")
1669     throw "$CALL invocation: empty argument list!";
1670
1671   O << "hooks::";
1672   O << CmdName << "(";
1673
1674
1675   bool firstIteration = true;
1676   while (true) {
1677     CheckedIncrement(Pos, End, errorMessage);
1678     const std::string& Arg = *Pos;
1679     assert(Arg.size() != 0);
1680
1681     if (Arg[0] == ')')
1682       break;
1683
1684     if (firstIteration)
1685       firstIteration = false;
1686     else
1687       O << ", ";
1688
1689     if (Arg == "$INFILE") {
1690       if (IsJoin)
1691         throw "$CALL(Hook, $INFILE) can't be used with a Join tool!";
1692       else
1693         O << "inFile.c_str()";
1694     }
1695     else {
1696       O << '"' << Arg << '"';
1697     }
1698   }
1699
1700   O << ')';
1701
1702   return Pos;
1703 }
1704
1705 /// SubstituteEnv - Given '$ENV(VAR_NAME)', output 'getenv("VAR_NAME")'. Helper
1706 /// function used by SubstituteSpecialCommands().
1707 StrVector::const_iterator
1708 SubstituteEnv (StrVector::const_iterator Pos,
1709                StrVector::const_iterator End, raw_ostream& O)
1710 {
1711   const char* errorMessage = "Syntax error in $ENV invocation!";
1712   CheckedIncrement(Pos, End, errorMessage);
1713   const std::string& EnvName = *Pos;
1714
1715   if (EnvName == ")")
1716     throw "$ENV invocation: empty argument list!";
1717
1718   O << "checkCString(std::getenv(\"";
1719   O << EnvName;
1720   O << "\"))";
1721
1722   CheckedIncrement(Pos, End, errorMessage);
1723
1724   return Pos;
1725 }
1726
1727 /// SubstituteSpecialCommands - Given an invocation of $CALL or $ENV, output
1728 /// handler code. Helper function used by EmitCmdLineVecFill().
1729 StrVector::const_iterator
1730 SubstituteSpecialCommands (StrVector::const_iterator Pos,
1731                            StrVector::const_iterator End,
1732                            bool IsJoin, raw_ostream& O)
1733 {
1734
1735   const std::string& cmd = *Pos;
1736
1737   // Perform substitution.
1738   if (cmd == "$CALL") {
1739     Pos = SubstituteCall(Pos, End, IsJoin, O);
1740   }
1741   else if (cmd == "$ENV") {
1742     Pos = SubstituteEnv(Pos, End, O);
1743   }
1744   else {
1745     throw "Unknown special command: " + cmd;
1746   }
1747
1748   // Handle '$CMD(ARG)/additional/text'.
1749   const std::string& Leftover = *Pos;
1750   assert(Leftover.at(0) == ')');
1751   if (Leftover.size() != 1)
1752     O << " + std::string(\"" << (Leftover.c_str() + 1) << "\")";
1753
1754   return Pos;
1755 }
1756
1757 /// EmitCmdLineVecFill - Emit code that fills in the command line
1758 /// vector. Helper function used by EmitGenerateActionMethod().
1759 void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
1760                         bool IsJoin, unsigned IndentLevel,
1761                         raw_ostream& O) {
1762   StrVector StrVec;
1763   TokenizeCmdLine(InitPtrToString(CmdLine), StrVec);
1764
1765   if (StrVec.empty())
1766     throw "Tool '" + ToolName + "' has empty command line!";
1767
1768   StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();
1769
1770   // Emit the command itself.
1771   assert(!StrVec[0].empty());
1772   O.indent(IndentLevel) << "cmd = ";
1773   if (StrVec[0][0] == '$') {
1774     B = SubstituteSpecialCommands(B, E, IsJoin, O);
1775     ++B;
1776   }
1777   else {
1778     O << '"' << StrVec[0] << '"';
1779     ++B;
1780   }
1781   O << ";\n";
1782
1783   // Go through the command arguments.
1784   assert(B <= E);
1785   for (; B != E; ++B) {
1786     const std::string& cmd = *B;
1787
1788     assert(!cmd.empty());
1789     O.indent(IndentLevel);
1790
1791     if (cmd.at(0) == '$') {
1792       O << "vec.push_back(std::make_pair(0, ";
1793       B = SubstituteSpecialCommands(B, E, IsJoin, O);
1794       O << "));\n";
1795     }
1796     else {
1797       O << "vec.push_back(std::make_pair(0, \"" << cmd << "\"));\n";
1798     }
1799   }
1800
1801 }
1802
1803 /// EmitForEachListElementCycleHeader - Emit common code for iterating through
1804 /// all elements of a list. Helper function used by
1805 /// EmitForwardOptionPropertyHandlingCode.
1806 void EmitForEachListElementCycleHeader (const OptionDescription& D,
1807                                         unsigned IndentLevel,
1808                                         raw_ostream& O) {
1809   unsigned IndentLevel1 = IndentLevel + Indent1;
1810
1811   O.indent(IndentLevel)
1812     << "for (" << D.GenTypeDeclaration()
1813     << "::iterator B = " << D.GenVariableName() << ".begin(),\n";
1814   O.indent(IndentLevel)
1815     << "E = " << D.GenVariableName() << ".end(); B != E;) {\n";
1816   O.indent(IndentLevel1) << "unsigned pos = " << D.GenVariableName()
1817                          << ".getPosition(B - " << D.GenVariableName()
1818                          << ".begin());\n";
1819 }
1820
1821 /// EmitForwardOptionPropertyHandlingCode - Helper function used to
1822 /// implement EmitActionHandler. Emits code for
1823 /// handling the (forward) and (forward_as) option properties.
1824 void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
1825                                             unsigned IndentLevel,
1826                                             const std::string& NewName,
1827                                             raw_ostream& O) {
1828   const std::string& Name = NewName.empty()
1829     ? ("-" + D.Name)
1830     : NewName;
1831   unsigned IndentLevel1 = IndentLevel + Indent1;
1832
1833   switch (D.Type) {
1834   case OptionType::Switch:
1835     O.indent(IndentLevel)
1836       << "vec.push_back(std::make_pair(" << D.GenVariableName()
1837       << ".getPosition(), \"" << Name << "\"));\n";
1838     break;
1839   case OptionType::Parameter:
1840     O.indent(IndentLevel) << "vec.push_back(std::make_pair("
1841                           << D.GenVariableName()
1842                           <<".getPosition(), \"" << Name;
1843
1844     if (!D.isForwardNotSplit()) {
1845       O << "\"));\n";
1846       O.indent(IndentLevel) << "vec.push_back(std::make_pair("
1847                             << D.GenVariableName() << ".getPosition(), "
1848                             << D.GenVariableName() << "));\n";
1849     }
1850     else {
1851       O << "=\" + " << D.GenVariableName() << "));\n";
1852     }
1853     break;
1854   case OptionType::Prefix:
1855     O.indent(IndentLevel) << "vec.push_back(std::make_pair("
1856                           << D.GenVariableName() << ".getPosition(), \""
1857                           << Name << "\" + "
1858                           << D.GenVariableName() << "));\n";
1859     break;
1860   case OptionType::PrefixList:
1861     EmitForEachListElementCycleHeader(D, IndentLevel, O);
1862     O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
1863                            << Name << "\" + " << "*B));\n";
1864     O.indent(IndentLevel1) << "++B;\n";
1865
1866     for (int i = 1, j = D.MultiVal; i < j; ++i) {
1867       O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
1868       O.indent(IndentLevel1) << "++B;\n";
1869     }
1870
1871     O.indent(IndentLevel) << "}\n";
1872     break;
1873   case OptionType::ParameterList:
1874     EmitForEachListElementCycleHeader(D, IndentLevel, O);
1875     O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
1876                            << Name << "\"));\n";
1877
1878     for (int i = 0, j = D.MultiVal; i < j; ++i) {
1879       O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
1880       O.indent(IndentLevel1) << "++B;\n";
1881     }
1882
1883     O.indent(IndentLevel) << "}\n";
1884     break;
1885   case OptionType::SwitchList:
1886     EmitForEachListElementCycleHeader(D, IndentLevel, O);
1887     O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
1888                            << Name << "\"));\n";
1889     O.indent(IndentLevel1) << "++B;\n";
1890     O.indent(IndentLevel) << "}\n";
1891     break;
1892   case OptionType::Alias:
1893   default:
1894     throw "Aliases are not allowed in tool option descriptions!";
1895   }
1896 }
1897
1898 /// ActionHandlingCallbackBase - Base class of EmitActionHandlersCallback and
1899 /// EmitPreprocessOptionsCallback.
1900 struct ActionHandlingCallbackBase
1901 {
1902
1903   void onErrorDag(const DagInit& d,
1904                   unsigned IndentLevel, raw_ostream& O) const
1905   {
1906     O.indent(IndentLevel)
1907       << "PrintError(\""
1908       << (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0)) : "Unknown error!")
1909       << "\");\n";
1910     O.indent(IndentLevel) << "return 1;\n";
1911   }
1912
1913   void onWarningDag(const DagInit& d,
1914                     unsigned IndentLevel, raw_ostream& O) const
1915   {
1916     CheckNumberOfArguments(d, 1);
1917     O.indent(IndentLevel) << "llvm::errs() << \""
1918                           << InitPtrToString(d.getArg(0)) << "\";\n";
1919   }
1920
1921 };
1922
1923 /// EmitActionHandlersCallback - Emit code that handles actions. Used by
1924 /// EmitGenerateActionMethod() as an argument to EmitCaseConstructHandler().
1925 class EmitActionHandlersCallback;
1926
1927 typedef void (EmitActionHandlersCallback::* EmitActionHandlersCallbackHandler)
1928 (const DagInit&, unsigned, raw_ostream&) const;
1929
1930 class EmitActionHandlersCallback :
1931   public ActionHandlingCallbackBase,
1932   public HandlerTable<EmitActionHandlersCallbackHandler>
1933 {
1934   typedef EmitActionHandlersCallbackHandler Handler;
1935
1936   const OptionDescriptions& OptDescs;
1937
1938   /// EmitHookInvocation - Common code for hook invocation from actions. Used by
1939   /// onAppendCmd and onOutputSuffix.
1940   void EmitHookInvocation(const std::string& Str,
1941                           const char* BlockOpen, const char* BlockClose,
1942                           unsigned IndentLevel, raw_ostream& O) const
1943   {
1944     StrVector Out;
1945     TokenizeCmdLine(Str, Out);
1946
1947     for (StrVector::const_iterator B = Out.begin(), E = Out.end();
1948          B != E; ++B) {
1949       const std::string& cmd = *B;
1950
1951       O.indent(IndentLevel) << BlockOpen;
1952
1953       if (cmd.at(0) == '$')
1954         B = SubstituteSpecialCommands(B, E,  /* IsJoin = */ true, O);
1955       else
1956         O << '"' << cmd << '"';
1957
1958       O << BlockClose;
1959     }
1960   }
1961
1962   void onAppendCmd (const DagInit& Dag,
1963                     unsigned IndentLevel, raw_ostream& O) const
1964   {
1965     CheckNumberOfArguments(Dag, 1);
1966     this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
1967                              "vec.push_back(std::make_pair(65536, ", "));\n",
1968                              IndentLevel, O);
1969   }
1970
1971   void onForward (const DagInit& Dag,
1972                   unsigned IndentLevel, raw_ostream& O) const
1973   {
1974     CheckNumberOfArguments(Dag, 1);
1975     const std::string& Name = InitPtrToString(Dag.getArg(0));
1976     EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
1977                                           IndentLevel, "", O);
1978   }
1979
1980   void onForwardAs (const DagInit& Dag,
1981                     unsigned IndentLevel, raw_ostream& O) const
1982   {
1983     CheckNumberOfArguments(Dag, 2);
1984     const std::string& Name = InitPtrToString(Dag.getArg(0));
1985     const std::string& NewName = InitPtrToString(Dag.getArg(1));
1986     EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
1987                                           IndentLevel, NewName, O);
1988   }
1989
1990   void onForwardValue (const DagInit& Dag,
1991                        unsigned IndentLevel, raw_ostream& O) const
1992   {
1993     CheckNumberOfArguments(Dag, 1);
1994     const std::string& Name = InitPtrToString(Dag.getArg(0));
1995     const OptionDescription& D = OptDescs.FindParameterListOrParameter(Name);
1996
1997     if (D.isSwitchList()) {
1998       throw std::runtime_error
1999         ("forward_value is not allowed with switch_list");
2000     }
2001
2002     if (D.isParameter()) {
2003       O.indent(IndentLevel) << "vec.push_back(std::make_pair("
2004                             << D.GenVariableName() << ".getPosition(), "
2005                             << D.GenVariableName() << "));\n";
2006     }
2007     else {
2008       O.indent(IndentLevel) << "for (" << D.GenTypeDeclaration()
2009                             << "::iterator B = " << D.GenVariableName()
2010                             << ".begin(), \n";
2011       O.indent(IndentLevel + Indent1) << " E = " << D.GenVariableName()
2012                                       << ".end(); B != E; ++B)\n";
2013       O.indent(IndentLevel) << "{\n";
2014       O.indent(IndentLevel + Indent1)
2015         << "unsigned pos = " << D.GenVariableName()
2016         << ".getPosition(B - " << D.GenVariableName()
2017         << ".begin());\n";
2018       O.indent(IndentLevel + Indent1)
2019         << "vec.push_back(std::make_pair(pos, *B));\n";
2020       O.indent(IndentLevel) << "}\n";
2021     }
2022   }
2023
2024   void onForwardTransformedValue (const DagInit& Dag,
2025                                   unsigned IndentLevel, raw_ostream& O) const
2026   {
2027     CheckNumberOfArguments(Dag, 2);
2028     const std::string& Name = InitPtrToString(Dag.getArg(0));
2029     const std::string& Hook = InitPtrToString(Dag.getArg(1));
2030     const OptionDescription& D = OptDescs.FindParameterListOrParameter(Name);
2031
2032     O.indent(IndentLevel) << "vec.push_back(std::make_pair("
2033                           << D.GenVariableName() << ".getPosition("
2034                           << (D.isList() ? "0" : "") << "), "
2035                           << "hooks::" << Hook << "(" << D.GenVariableName()
2036                           << (D.isParameter() ? ".c_str()" : "") << ")));\n";
2037   }
2038
2039   void onNoOutFile (const DagInit& Dag,
2040                     unsigned IndentLevel, raw_ostream& O) const
2041   {
2042     CheckNumberOfArguments(Dag, 0);
2043     O.indent(IndentLevel) << "no_out_file = true;\n";
2044   }
2045
2046   void onOutputSuffix (const DagInit& Dag,
2047                        unsigned IndentLevel, raw_ostream& O) const
2048   {
2049     CheckNumberOfArguments(Dag, 1);
2050     this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
2051                              "output_suffix = ", ";\n", IndentLevel, O);
2052   }
2053
2054   void onStopCompilation (const DagInit& Dag,
2055                           unsigned IndentLevel, raw_ostream& O) const
2056   {
2057     O.indent(IndentLevel) << "stop_compilation = true;\n";
2058   }
2059
2060
2061   void onUnpackValues (const DagInit& Dag,
2062                        unsigned IndentLevel, raw_ostream& O) const
2063   {
2064     throw "'unpack_values' is deprecated. "
2065       "Use 'comma_separated' + 'forward_value' instead!";
2066   }
2067
2068  public:
2069
2070   explicit EmitActionHandlersCallback(const OptionDescriptions& OD)
2071     : OptDescs(OD)
2072   {
2073     if (!staticMembersInitialized_) {
2074       AddHandler("error", &EmitActionHandlersCallback::onErrorDag);
2075       AddHandler("warning", &EmitActionHandlersCallback::onWarningDag);
2076       AddHandler("append_cmd", &EmitActionHandlersCallback::onAppendCmd);
2077       AddHandler("forward", &EmitActionHandlersCallback::onForward);
2078       AddHandler("forward_as", &EmitActionHandlersCallback::onForwardAs);
2079       AddHandler("forward_value", &EmitActionHandlersCallback::onForwardValue);
2080       AddHandler("forward_transformed_value",
2081                  &EmitActionHandlersCallback::onForwardTransformedValue);
2082       AddHandler("no_out_file",
2083                  &EmitActionHandlersCallback::onNoOutFile);
2084       AddHandler("output_suffix", &EmitActionHandlersCallback::onOutputSuffix);
2085       AddHandler("stop_compilation",
2086                  &EmitActionHandlersCallback::onStopCompilation);
2087       AddHandler("unpack_values",
2088                  &EmitActionHandlersCallback::onUnpackValues);
2089
2090
2091       staticMembersInitialized_ = true;
2092     }
2093   }
2094
2095   void operator()(const Init* I,
2096                   unsigned IndentLevel, raw_ostream& O) const
2097   {
2098     InvokeDagInitHandler(this, I, IndentLevel, O);
2099   }
2100 };
2101
2102 void EmitGenerateActionMethodHeader(const ToolDescription& D,
2103                                     bool IsJoin, bool Naked,
2104                                     raw_ostream& O)
2105 {
2106   O.indent(Indent1) << "int GenerateAction(Action& Out,\n";
2107
2108   if (IsJoin)
2109     O.indent(Indent2) << "const PathVector& inFiles,\n";
2110   else
2111     O.indent(Indent2) << "const sys::Path& inFile,\n";
2112
2113   O.indent(Indent2) << "const bool HasChildren,\n";
2114   O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n";
2115   O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n";
2116   O.indent(Indent2) << "const LanguageMap& LangMap) const\n";
2117   O.indent(Indent1) << "{\n";
2118
2119   if (!Naked) {
2120     O.indent(Indent2) << "std::string cmd;\n";
2121     O.indent(Indent2) << "std::string out_file;\n";
2122     O.indent(Indent2)
2123       << "std::vector<std::pair<unsigned, std::string> > vec;\n";
2124     O.indent(Indent2) << "bool stop_compilation = !HasChildren;\n";
2125     O.indent(Indent2) << "bool no_out_file = false;\n";
2126     O.indent(Indent2) << "std::string output_suffix(\""
2127                       << D.OutputSuffix << "\");\n";
2128   }
2129 }
2130
2131 // EmitGenerateActionMethod - Emit either a normal or a "join" version of the
2132 // Tool::GenerateAction() method.
2133 void EmitGenerateActionMethod (const ToolDescription& D,
2134                                const OptionDescriptions& OptDescs,
2135                                bool IsJoin, raw_ostream& O) {
2136
2137   EmitGenerateActionMethodHeader(D, IsJoin, /* Naked = */ false, O);
2138
2139   if (!D.CmdLine)
2140     throw "Tool " + D.Name + " has no cmd_line property!";
2141
2142   // Process the 'command' property.
2143   O << '\n';
2144   EmitCmdLineVecFill(D.CmdLine, D.Name, IsJoin, Indent2, O);
2145   O << '\n';
2146
2147   // Process the 'actions' list of this tool.
2148   if (D.Actions)
2149     EmitCaseConstructHandler(D.Actions, Indent2,
2150                              EmitActionHandlersCallback(OptDescs),
2151                              false, OptDescs, O);
2152   O << '\n';
2153
2154   // Input file (s)
2155   if (!D.InFileOption.empty()) {
2156     O.indent(Indent2)
2157       << "vec.push_back(std::make_pair(InputFilenames.getPosition(0), \""
2158       << D.InFileOption << "\");\n";
2159   }
2160
2161   if (IsJoin) {
2162     O.indent(Indent2)
2163       << "for (PathVector::const_iterator B = inFiles.begin(),\n";
2164     O.indent(Indent3) << "E = inFiles.end(); B != E; ++B)\n";
2165     O.indent(Indent2) << "{\n";
2166     O.indent(Indent3) << "vec.push_back(std::make_pair("
2167                       << "InputFilenames.getPosition(B - inFiles.begin()), "
2168                       << "B->str()));\n";
2169     O.indent(Indent2) << "}\n";
2170   }
2171   else {
2172     O.indent(Indent2) << "vec.push_back(std::make_pair("
2173                       << "InputFilenames.getPosition(0), inFile.str()));\n";
2174   }
2175
2176   // Output file
2177   O.indent(Indent2) << "if (!no_out_file) {\n";
2178   if (!D.OutFileOption.empty())
2179     O.indent(Indent3) << "vec.push_back(std::make_pair(65536, \""
2180                       << D.OutFileOption << "\"));\n";
2181
2182   O.indent(Indent3) << "out_file = this->OutFilename("
2183                     << (IsJoin ? "sys::Path(),\n" : "inFile,\n");
2184   O.indent(Indent4) <<
2185     "TempDir, stop_compilation, output_suffix.c_str()).str();\n\n";
2186   O.indent(Indent3) << "vec.push_back(std::make_pair(65536, out_file));\n";
2187
2188   O.indent(Indent2) << "}\n\n";
2189
2190   // Handle the Sink property.
2191   std::string SinkOption("autogenerated::");
2192   SinkOption += SinkOptionName;
2193   if (D.isSink()) {
2194     O.indent(Indent2) << "if (!" << SinkOption << ".empty()) {\n";
2195     O.indent(Indent3) << "for (cl::list<std::string>::iterator B = "
2196                       << SinkOption << ".begin(), E = " << SinkOption
2197                       << ".end(); B != E; ++B)\n";
2198     O.indent(Indent4) << "vec.push_back(std::make_pair(" << SinkOption
2199                       << ".getPosition(B - " << SinkOption
2200                       <<  ".begin()), *B));\n";
2201     O.indent(Indent2) << "}\n";
2202   }
2203
2204   O.indent(Indent2) << "Out.Construct(cmd, this->SortArgs(vec), "
2205                     << "stop_compilation, out_file);\n";
2206   O.indent(Indent2) << "return 0;\n";
2207   O.indent(Indent1) << "}\n\n";
2208 }
2209
2210 /// EmitGenerateActionMethods - Emit two GenerateAction() methods for
2211 /// a given Tool class.
2212 void EmitGenerateActionMethods (const ToolDescription& ToolDesc,
2213                                 const OptionDescriptions& OptDescs,
2214                                 raw_ostream& O) {
2215   if (!ToolDesc.isJoin()) {
2216     EmitGenerateActionMethodHeader(ToolDesc, /* IsJoin = */ true,
2217                                    /* Naked = */ true, O);
2218     O.indent(Indent2) << "PrintError(\"" << ToolDesc.Name
2219                       << " is not a Join tool!\");\n";
2220     O.indent(Indent2) << "return -1;\n";
2221     O.indent(Indent1) << "}\n\n";
2222   }
2223   else {
2224     EmitGenerateActionMethod(ToolDesc, OptDescs, true, O);
2225   }
2226
2227   EmitGenerateActionMethod(ToolDesc, OptDescs, false, O);
2228 }
2229
2230 /// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
2231 /// methods for a given Tool class.
2232 void EmitInOutLanguageMethods (const ToolDescription& D, raw_ostream& O) {
2233   O.indent(Indent1) << "const char** InputLanguages() const {\n";
2234   O.indent(Indent2) << "return InputLanguages_;\n";
2235   O.indent(Indent1) << "}\n\n";
2236
2237   O.indent(Indent1) << "const char** OutputLanguages() const {\n";
2238   O.indent(Indent2) << "return OutputLanguages_;\n";
2239   O.indent(Indent1) << "}\n\n";
2240 }
2241
2242 /// EmitNameMethod - Emit the Name() method for a given Tool class.
2243 void EmitNameMethod (const ToolDescription& D, raw_ostream& O) {
2244   O.indent(Indent1) << "const char* Name() const {\n";
2245   O.indent(Indent2) << "return \"" << D.Name << "\";\n";
2246   O.indent(Indent1) << "}\n\n";
2247 }
2248
2249 /// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
2250 /// class.
2251 void EmitIsJoinMethod (const ToolDescription& D, raw_ostream& O) {
2252   O.indent(Indent1) << "bool IsJoin() const {\n";
2253   if (D.isJoin())
2254     O.indent(Indent2) << "return true;\n";
2255   else
2256     O.indent(Indent2) << "return false;\n";
2257   O.indent(Indent1) << "}\n\n";
2258 }
2259
2260 /// EmitWorksOnEmptyCallback - Callback used by EmitWorksOnEmptyMethod in
2261 /// conjunction with EmitCaseConstructHandler.
2262 void EmitWorksOnEmptyCallback (const Init* Value,
2263                                unsigned IndentLevel, raw_ostream& O) {
2264   CheckBooleanConstant(Value);
2265   O.indent(IndentLevel) << "return " << Value->getAsString() << ";\n";
2266 }
2267
2268 /// EmitWorksOnEmptyMethod - Emit the WorksOnEmpty() method for a given Tool
2269 /// class.
2270 void EmitWorksOnEmptyMethod (const ToolDescription& D,
2271                              const OptionDescriptions& OptDescs,
2272                              raw_ostream& O)
2273 {
2274   O.indent(Indent1) << "bool WorksOnEmpty() const {\n";
2275   if (D.OnEmpty == 0)
2276     O.indent(Indent2) << "return false;\n";
2277   else
2278     EmitCaseConstructHandler(D.OnEmpty, Indent2, EmitWorksOnEmptyCallback,
2279                              /*EmitElseIf = */ true, OptDescs, O);
2280   O.indent(Indent1) << "}\n\n";
2281 }
2282
2283 /// EmitStrArray - Emit definition of a 'const char**' static member
2284 /// variable. Helper used by EmitStaticMemberDefinitions();
2285 void EmitStrArray(const std::string& Name, const std::string& VarName,
2286                   const StrVector& StrVec, raw_ostream& O) {
2287   O << "const char* " << Name << "::" << VarName << "[] = {";
2288   for (StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();
2289        B != E; ++B)
2290     O << '\"' << *B << "\", ";
2291   O << "0};\n";
2292 }
2293
2294 /// EmitStaticMemberDefinitions - Emit static member definitions for a
2295 /// given Tool class.
2296 void EmitStaticMemberDefinitions(const ToolDescription& D, raw_ostream& O) {
2297   if (D.InLanguage.empty())
2298     throw "Tool " + D.Name + " has no 'in_language' property!";
2299   if (D.OutLanguage.empty())
2300     throw "Tool " + D.Name + " has no 'out_language' property!";
2301
2302   EmitStrArray(D.Name, "InputLanguages_", D.InLanguage, O);
2303   EmitStrArray(D.Name, "OutputLanguages_", D.OutLanguage, O);
2304   O << '\n';
2305 }
2306
2307 /// EmitToolClassDefinition - Emit a Tool class definition.
2308 void EmitToolClassDefinition (const ToolDescription& D,
2309                               const OptionDescriptions& OptDescs,
2310                               raw_ostream& O) {
2311   if (D.Name == "root")
2312     return;
2313
2314   // Header
2315   O << "class " << D.Name << " : public ";
2316   if (D.isJoin())
2317     O << "JoinTool";
2318   else
2319     O << "Tool";
2320
2321   O << " {\nprivate:\n";
2322   O.indent(Indent1) << "static const char* InputLanguages_[];\n";
2323   O.indent(Indent1) << "static const char* OutputLanguages_[];\n\n";
2324
2325   O << "public:\n";
2326   EmitNameMethod(D, O);
2327   EmitInOutLanguageMethods(D, O);
2328   EmitIsJoinMethod(D, O);
2329   EmitWorksOnEmptyMethod(D, OptDescs, O);
2330   EmitGenerateActionMethods(D, OptDescs, O);
2331
2332   // Close class definition
2333   O << "};\n";
2334
2335   EmitStaticMemberDefinitions(D, O);
2336
2337 }
2338
2339 /// EmitOptionDefinitions - Iterate over a list of option descriptions
2340 /// and emit registration code.
2341 void EmitOptionDefinitions (const OptionDescriptions& descs,
2342                             bool HasSink, raw_ostream& O)
2343 {
2344   std::vector<OptionDescription> Aliases;
2345
2346   // Emit static cl::Option variables.
2347   for (OptionDescriptions::const_iterator B = descs.begin(),
2348          E = descs.end(); B!=E; ++B) {
2349     const OptionDescription& val = B->second;
2350
2351     if (val.Type == OptionType::Alias) {
2352       Aliases.push_back(val);
2353       continue;
2354     }
2355
2356     O << val.GenTypeDeclaration() << ' '
2357       << val.GenPlainVariableName();
2358
2359     O << "(\"" << val.Name << "\"\n";
2360
2361     if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
2362       O << ", cl::Prefix";
2363
2364     if (val.isRequired()) {
2365       if (val.isList() && !val.isMultiVal())
2366         O << ", cl::OneOrMore";
2367       else
2368         O << ", cl::Required";
2369     }
2370
2371     if (val.isOptional())
2372         O << ", cl::Optional";
2373
2374     if (val.isOneOrMore())
2375         O << ", cl::OneOrMore";
2376
2377     if (val.isZeroOrMore())
2378         O << ", cl::ZeroOrMore";
2379
2380     if (val.isReallyHidden())
2381       O << ", cl::ReallyHidden";
2382     else if (val.isHidden())
2383       O << ", cl::Hidden";
2384
2385     if (val.isCommaSeparated())
2386       O << ", cl::CommaSeparated";
2387
2388     if (val.MultiVal > 1)
2389       O << ", cl::multi_val(" << val.MultiVal << ')';
2390
2391     if (val.InitVal) {
2392       const std::string& str = val.InitVal->getAsString();
2393       O << ", cl::init(" << str << ')';
2394     }
2395
2396     if (!val.Help.empty())
2397       O << ", cl::desc(\"" << val.Help << "\")";
2398
2399     O << ");\n\n";
2400   }
2401
2402   // Emit the aliases (they should go after all the 'proper' options).
2403   for (std::vector<OptionDescription>::const_iterator
2404          B = Aliases.begin(), E = Aliases.end(); B != E; ++B) {
2405     const OptionDescription& val = *B;
2406
2407     O << val.GenTypeDeclaration() << ' '
2408       << val.GenPlainVariableName()
2409       << "(\"" << val.Name << '\"';
2410
2411     const OptionDescription& D = descs.FindOption(val.Help);
2412     O << ", cl::aliasopt(" << D.GenVariableName() << ")";
2413
2414     O << ", cl::desc(\"" << "An alias for -" + val.Help  << "\"));\n";
2415   }
2416
2417   // Emit the sink option.
2418   if (HasSink)
2419     O << "cl::list<std::string> " << SinkOptionName << "(cl::Sink);\n";
2420
2421   O << '\n';
2422 }
2423
2424 /// EmitPreprocessOptionsCallback - Helper function passed to
2425 /// EmitCaseConstructHandler() by EmitPreprocessOptions().
2426
2427 class EmitPreprocessOptionsCallback;
2428
2429 typedef void
2430 (EmitPreprocessOptionsCallback::* EmitPreprocessOptionsCallbackHandler)
2431 (const DagInit&, unsigned, raw_ostream&) const;
2432
2433 class EmitPreprocessOptionsCallback :
2434   public ActionHandlingCallbackBase,
2435   public HandlerTable<EmitPreprocessOptionsCallbackHandler>
2436 {
2437   typedef EmitPreprocessOptionsCallbackHandler Handler;
2438   typedef void
2439   (EmitPreprocessOptionsCallback::* HandlerImpl)
2440   (const Init*, unsigned, raw_ostream&) const;
2441
2442   const OptionDescriptions& OptDescs_;
2443
2444   void onEachArgument(const DagInit& d, HandlerImpl h,
2445                       unsigned IndentLevel, raw_ostream& O) const
2446   {
2447     CheckNumberOfArguments(d, 1);
2448
2449     for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) {
2450       ((this)->*(h))(d.getArg(i), IndentLevel, O);
2451     }
2452   }
2453
2454   void onUnsetOptionImpl(const Init* I,
2455                          unsigned IndentLevel, raw_ostream& O) const
2456   {
2457     const std::string& OptName = InitPtrToString(I);
2458     const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
2459
2460     if (OptDesc.isSwitch()) {
2461       O.indent(IndentLevel) << OptDesc.GenVariableName() << " = false;\n";
2462     }
2463     else if (OptDesc.isParameter()) {
2464       O.indent(IndentLevel) << OptDesc.GenVariableName() << " = \"\";\n";
2465     }
2466     else if (OptDesc.isList()) {
2467       O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n";
2468     }
2469     else {
2470       throw "Can't apply 'unset_option' to alias option '" + OptName + "'!";
2471     }
2472   }
2473
2474   void onUnsetOption(const DagInit& d,
2475                      unsigned IndentLevel, raw_ostream& O) const
2476   {
2477     this->onEachArgument(d, &EmitPreprocessOptionsCallback::onUnsetOptionImpl,
2478                          IndentLevel, O);
2479   }
2480
2481   void onSetOptionImpl(const DagInit& D,
2482                        unsigned IndentLevel, raw_ostream& O) const {
2483     CheckNumberOfArguments(D, 2);
2484
2485     const std::string& OptName = InitPtrToString(D.getArg(0));
2486     const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
2487     const Init* Value = D.getArg(1);
2488
2489     if (OptDesc.isList()) {
2490       const ListInit& List = InitPtrToList(Value);
2491
2492       O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n";
2493       for (ListInit::const_iterator B = List.begin(), E = List.end();
2494            B != E; ++B) {
2495         const Init* CurElem = *B;
2496         if (OptDesc.isSwitchList())
2497           CheckBooleanConstant(CurElem);
2498
2499         O.indent(IndentLevel)
2500           << OptDesc.GenVariableName() << ".push_back(\""
2501           << (OptDesc.isSwitchList() ? CurElem->getAsString()
2502               : InitPtrToString(CurElem))
2503           << "\");\n";
2504       }
2505     }
2506     else if (OptDesc.isSwitch()) {
2507       CheckBooleanConstant(Value);
2508       O.indent(IndentLevel) << OptDesc.GenVariableName()
2509                             << " = " << Value->getAsString() << ";\n";
2510     }
2511     else if (OptDesc.isParameter()) {
2512       const std::string& Str = InitPtrToString(Value);
2513       O.indent(IndentLevel) << OptDesc.GenVariableName()
2514                             << " = \"" << Str << "\";\n";
2515     }
2516     else {
2517       throw "Can't apply 'set_option' to alias option '" + OptName + "'!";
2518     }
2519   }
2520
2521   void onSetSwitch(const Init* I,
2522                    unsigned IndentLevel, raw_ostream& O) const {
2523     const std::string& OptName = InitPtrToString(I);
2524     const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
2525
2526     if (OptDesc.isSwitch())
2527       O.indent(IndentLevel) << OptDesc.GenVariableName() << " = true;\n";
2528     else
2529       throw "set_option: -" + OptName + " is not a switch option!";
2530   }
2531
2532   void onSetOption(const DagInit& d,
2533                    unsigned IndentLevel, raw_ostream& O) const
2534   {
2535     CheckNumberOfArguments(d, 1);
2536
2537     // 2-argument form: (set_option "A", true), (set_option "B", "C"),
2538     // (set_option "D", ["E", "F"])
2539     if (d.getNumArgs() == 2) {
2540       const OptionDescription& OptDesc =
2541         OptDescs_.FindOption(InitPtrToString(d.getArg(0)));
2542       const Init* Opt2 = d.getArg(1);
2543
2544       if (!OptDesc.isSwitch() || typeid(*Opt2) != typeid(StringInit)) {
2545         this->onSetOptionImpl(d, IndentLevel, O);
2546         return;
2547       }
2548     }
2549
2550     // Multiple argument form: (set_option "A"), (set_option "B", "C", "D")
2551     this->onEachArgument(d, &EmitPreprocessOptionsCallback::onSetSwitch,
2552                          IndentLevel, O);
2553   }
2554
2555 public:
2556
2557   EmitPreprocessOptionsCallback(const OptionDescriptions& OptDescs)
2558   : OptDescs_(OptDescs)
2559   {
2560     if (!staticMembersInitialized_) {
2561       AddHandler("error", &EmitPreprocessOptionsCallback::onErrorDag);
2562       AddHandler("warning", &EmitPreprocessOptionsCallback::onWarningDag);
2563       AddHandler("unset_option", &EmitPreprocessOptionsCallback::onUnsetOption);
2564       AddHandler("set_option", &EmitPreprocessOptionsCallback::onSetOption);
2565
2566       staticMembersInitialized_ = true;
2567     }
2568   }
2569
2570   void operator()(const Init* I,
2571                   unsigned IndentLevel, raw_ostream& O) const
2572   {
2573     InvokeDagInitHandler(this, I, IndentLevel, O);
2574   }
2575
2576 };
2577
2578 /// EmitPreprocessOptions - Emit the PreprocessOptions() function.
2579 void EmitPreprocessOptions (const RecordKeeper& Records,
2580                             const OptionDescriptions& OptDecs, raw_ostream& O)
2581 {
2582   O << "int PreprocessOptions () {\n";
2583
2584   const RecordVector& OptionPreprocessors =
2585     Records.getAllDerivedDefinitions("OptionPreprocessor");
2586
2587   for (RecordVector::const_iterator B = OptionPreprocessors.begin(),
2588          E = OptionPreprocessors.end(); B!=E; ++B) {
2589     DagInit* Case = (*B)->getValueAsDag("preprocessor");
2590     EmitCaseConstructHandler(Case, Indent1,
2591                              EmitPreprocessOptionsCallback(OptDecs),
2592                              false, OptDecs, O);
2593   }
2594
2595   O << '\n';
2596   O.indent(Indent1) << "return 0;\n";
2597   O << "}\n\n";
2598 }
2599
2600 class DoEmitPopulateLanguageMap;
2601 typedef void (DoEmitPopulateLanguageMap::* DoEmitPopulateLanguageMapHandler)
2602 (const DagInit& D);
2603
2604 class DoEmitPopulateLanguageMap
2605 : public HandlerTable<DoEmitPopulateLanguageMapHandler>
2606 {
2607 private:
2608   raw_ostream& O_;
2609
2610 public:
2611
2612   explicit DoEmitPopulateLanguageMap (raw_ostream& O) : O_(O) {
2613     if (!staticMembersInitialized_) {
2614       AddHandler("lang_to_suffixes",
2615                  &DoEmitPopulateLanguageMap::onLangToSuffixes);
2616
2617       staticMembersInitialized_ = true;
2618     }
2619   }
2620
2621   void operator() (Init* I) {
2622     InvokeDagInitHandler(this, I);
2623   }
2624
2625 private:
2626
2627   void onLangToSuffixes (const DagInit& d) {
2628     CheckNumberOfArguments(d, 2);
2629
2630     const std::string& Lang = InitPtrToString(d.getArg(0));
2631     Init* Suffixes = d.getArg(1);
2632
2633     // Second argument to lang_to_suffixes is either a single string...
2634     if (typeid(*Suffixes) == typeid(StringInit)) {
2635       O_.indent(Indent1) << "langMap[\"" << InitPtrToString(Suffixes)
2636                          << "\"] = \"" << Lang << "\";\n";
2637     }
2638     // ...or a list of strings.
2639     else {
2640       const ListInit& Lst = InitPtrToList(Suffixes);
2641       assert(Lst.size() != 0);
2642       for (ListInit::const_iterator B = Lst.begin(), E = Lst.end();
2643            B != E; ++B) {
2644         O_.indent(Indent1) << "langMap[\"" << InitPtrToString(*B)
2645                            << "\"] = \"" << Lang << "\";\n";
2646       }
2647     }
2648   }
2649
2650 };
2651
2652 /// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function.
2653 void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)
2654 {
2655   O << "int PopulateLanguageMap (LanguageMap& langMap) {\n";
2656
2657   // For each LanguageMap:
2658   const RecordVector& LangMaps =
2659     Records.getAllDerivedDefinitions("LanguageMap");
2660
2661   // Call DoEmitPopulateLanguageMap.
2662   for (RecordVector::const_iterator B = LangMaps.begin(),
2663          E = LangMaps.end(); B!=E; ++B) {
2664     ListInit* LangMap = (*B)->getValueAsListInit("map");
2665     std::for_each(LangMap->begin(), LangMap->end(),
2666                   DoEmitPopulateLanguageMap(O));
2667   }
2668
2669   O << '\n';
2670   O.indent(Indent1) << "return 0;\n";
2671   O << "}\n\n";
2672 }
2673
2674 /// EmitEdgePropertyHandlerCallback - Emits code that handles edge
2675 /// properties. Helper function passed to EmitCaseConstructHandler() by
2676 /// EmitEdgeClass().
2677 void EmitEdgePropertyHandlerCallback (const Init* i, unsigned IndentLevel,
2678                                       raw_ostream& O) {
2679   const DagInit& d = InitPtrToDag(i);
2680   const std::string& OpName = GetOperatorName(d);
2681
2682   if (OpName == "inc_weight") {
2683     O.indent(IndentLevel) << "ret += ";
2684   }
2685   else if (OpName == "error") {
2686     CheckNumberOfArguments(d, 1);
2687     O.indent(IndentLevel) << "PrintError(\""
2688                           << InitPtrToString(d.getArg(0))
2689                           << "\");\n";
2690     O.indent(IndentLevel) << "return -1;\n";
2691     return;
2692   }
2693   else {
2694     throw "Unknown operator in edge properties list: '" + OpName + "'!"
2695       "\nOnly 'inc_weight', 'dec_weight' and 'error' are allowed.";
2696   }
2697
2698   if (d.getNumArgs() > 0)
2699     O << InitPtrToInt(d.getArg(0)) << ";\n";
2700   else
2701     O << "2;\n";
2702
2703 }
2704
2705 /// EmitEdgeClass - Emit a single Edge# class.
2706 void EmitEdgeClass (unsigned N, const std::string& Target,
2707                     const DagInit& Case, const OptionDescriptions& OptDescs,
2708                     raw_ostream& O) {
2709
2710   // Class constructor.
2711   O << "class Edge" << N << ": public Edge {\n"
2712     << "public:\n";
2713   O.indent(Indent1) << "Edge" << N << "() : Edge(\"" << Target
2714                     << "\") {}\n\n";
2715
2716   // Function Weight().
2717   O.indent(Indent1)
2718     << "int Weight(const InputLanguagesSet& InLangs) const {\n";
2719   O.indent(Indent2) << "unsigned ret = 0;\n";
2720
2721   // Handle the 'case' construct.
2722   EmitCaseConstructHandler(&Case, Indent2, EmitEdgePropertyHandlerCallback,
2723                            false, OptDescs, O);
2724
2725   O.indent(Indent2) << "return ret;\n";
2726   O.indent(Indent1) << "}\n\n};\n\n";
2727 }
2728
2729 /// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
2730 void EmitEdgeClasses (const DagVector& EdgeVector,
2731                       const OptionDescriptions& OptDescs,
2732                       raw_ostream& O) {
2733   int i = 0;
2734   for (DagVector::const_iterator B = EdgeVector.begin(),
2735          E = EdgeVector.end(); B != E; ++B) {
2736     const DagInit& Edge = **B;
2737     const std::string& Name = GetOperatorName(Edge);
2738
2739     if (Name == "optional_edge") {
2740       assert(IsOptionalEdge(Edge));
2741       const std::string& NodeB = InitPtrToString(Edge.getArg(1));
2742
2743       const DagInit& Weight = InitPtrToDag(Edge.getArg(2));
2744       EmitEdgeClass(i, NodeB, Weight, OptDescs, O);
2745     }
2746     else if (Name != "edge") {
2747       throw "Unknown edge class: '" + Name + "'!";
2748     }
2749
2750     ++i;
2751   }
2752 }
2753
2754 /// EmitPopulateCompilationGraph - Emit the PopulateCompilationGraph() function.
2755 void EmitPopulateCompilationGraph (const DagVector& EdgeVector,
2756                                    const ToolDescriptions& ToolDescs,
2757                                    raw_ostream& O)
2758 {
2759   O << "int PopulateCompilationGraph (CompilationGraph& G) {\n";
2760
2761   for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
2762          E = ToolDescs.end(); B != E; ++B)
2763     O.indent(Indent1) << "G.insertNode(new " << (*B)->Name << "());\n";
2764
2765   O << '\n';
2766
2767   // Insert edges.
2768
2769   int i = 0;
2770   for (DagVector::const_iterator B = EdgeVector.begin(),
2771          E = EdgeVector.end(); B != E; ++B) {
2772     const DagInit& Edge = **B;
2773     const std::string& NodeA = InitPtrToString(Edge.getArg(0));
2774     const std::string& NodeB = InitPtrToString(Edge.getArg(1));
2775
2776     O.indent(Indent1) << "if (int ret = G.insertEdge(\"" << NodeA << "\", ";
2777
2778     if (IsOptionalEdge(Edge))
2779       O << "new Edge" << i << "()";
2780     else
2781       O << "new SimpleEdge(\"" << NodeB << "\")";
2782
2783     O << "))\n";
2784     O.indent(Indent2) << "return ret;\n";
2785
2786     ++i;
2787   }
2788
2789   O << '\n';
2790   O.indent(Indent1) << "return 0;\n";
2791   O << "}\n\n";
2792 }
2793
2794 /// HookInfo - Information about the hook type and number of arguments.
2795 struct HookInfo {
2796
2797   // A hook can either have a single parameter of type std::vector<std::string>,
2798   // or NumArgs parameters of type const char*.
2799   enum HookType { ListHook, ArgHook };
2800
2801   HookType Type;
2802   unsigned NumArgs;
2803
2804   HookInfo() : Type(ArgHook), NumArgs(1)
2805   {}
2806
2807   HookInfo(HookType T) : Type(T), NumArgs(1)
2808   {}
2809
2810   HookInfo(unsigned N) : Type(ArgHook), NumArgs(N)
2811   {}
2812 };
2813
2814 typedef llvm::StringMap<HookInfo> HookInfoMap;
2815
2816 /// ExtractHookNames - Extract the hook names from all instances of
2817 /// $CALL(HookName) in the provided command line string/action. Helper
2818 /// function used by FillInHookNames().
2819 class ExtractHookNames {
2820   HookInfoMap& HookNames_;
2821   const OptionDescriptions& OptDescs_;
2822 public:
2823   ExtractHookNames(HookInfoMap& HookNames, const OptionDescriptions& OptDescs)
2824     : HookNames_(HookNames), OptDescs_(OptDescs)
2825   {}
2826
2827   void onAction (const DagInit& Dag) {
2828     const std::string& Name = GetOperatorName(Dag);
2829
2830     if (Name == "forward_transformed_value") {
2831       CheckNumberOfArguments(Dag, 2);
2832       const std::string& OptName = InitPtrToString(Dag.getArg(0));
2833       const std::string& HookName = InitPtrToString(Dag.getArg(1));
2834       const OptionDescription& D =
2835         OptDescs_.FindParameterListOrParameter(OptName);
2836
2837       HookNames_[HookName] = HookInfo(D.isList() ? HookInfo::ListHook
2838                                       : HookInfo::ArgHook);
2839     }
2840     else if (Name == "append_cmd" || Name == "output_suffix") {
2841       CheckNumberOfArguments(Dag, 1);
2842       this->onCmdLine(InitPtrToString(Dag.getArg(0)));
2843     }
2844   }
2845
2846   void onCmdLine(const std::string& Cmd) {
2847     StrVector cmds;
2848     TokenizeCmdLine(Cmd, cmds);
2849
2850     for (StrVector::const_iterator B = cmds.begin(), E = cmds.end();
2851          B != E; ++B) {
2852       const std::string& cmd = *B;
2853
2854       if (cmd == "$CALL") {
2855         unsigned NumArgs = 0;
2856         CheckedIncrement(B, E, "Syntax error in $CALL invocation!");
2857         const std::string& HookName = *B;
2858
2859         if (HookName.at(0) == ')')
2860           throw "$CALL invoked with no arguments!";
2861
2862         while (++B != E && B->at(0) != ')') {
2863           ++NumArgs;
2864         }
2865
2866         HookInfoMap::const_iterator H = HookNames_.find(HookName);
2867
2868         if (H != HookNames_.end() && H->second.NumArgs != NumArgs &&
2869             H->second.Type != HookInfo::ArgHook)
2870           throw "Overloading of hooks is not allowed. Overloaded hook: "
2871             + HookName;
2872         else
2873           HookNames_[HookName] = HookInfo(NumArgs);
2874       }
2875     }
2876   }
2877
2878   void operator()(const Init* Arg) {
2879
2880     // We're invoked on an action (either a dag or a dag list).
2881     if (typeid(*Arg) == typeid(DagInit)) {
2882       const DagInit& Dag = InitPtrToDag(Arg);
2883       this->onAction(Dag);
2884       return;
2885     }
2886     else if (typeid(*Arg) == typeid(ListInit)) {
2887       const ListInit& List = InitPtrToList(Arg);
2888       for (ListInit::const_iterator B = List.begin(), E = List.end(); B != E;
2889            ++B) {
2890         const DagInit& Dag = InitPtrToDag(*B);
2891         this->onAction(Dag);
2892       }
2893       return;
2894     }
2895
2896     // We're invoked on a command line string.
2897     this->onCmdLine(InitPtrToString(Arg));
2898   }
2899
2900   void operator()(const Init* Statement, unsigned) {
2901     this->operator()(Statement);
2902   }
2903 };
2904
2905 /// FillInHookNames - Actually extract the hook names from all command
2906 /// line strings. Helper function used by EmitHookDeclarations().
2907 void FillInHookNames(const ToolDescriptions& ToolDescs,
2908                      const OptionDescriptions& OptDescs,
2909                      HookInfoMap& HookNames)
2910 {
2911   // For all tool descriptions:
2912   for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
2913          E = ToolDescs.end(); B != E; ++B) {
2914     const ToolDescription& D = *(*B);
2915
2916     // Look for 'forward_transformed_value' in 'actions'.
2917     if (D.Actions)
2918       WalkCase(D.Actions, Id(), ExtractHookNames(HookNames, OptDescs));
2919
2920     // Look for hook invocations in 'cmd_line'.
2921     if (!D.CmdLine)
2922       continue;
2923     if (dynamic_cast<StringInit*>(D.CmdLine))
2924       // This is a string.
2925       ExtractHookNames(HookNames, OptDescs).operator()(D.CmdLine);
2926     else
2927       // This is a 'case' construct.
2928       WalkCase(D.CmdLine, Id(), ExtractHookNames(HookNames, OptDescs));
2929   }
2930 }
2931
2932 /// EmitHookDeclarations - Parse CmdLine fields of all the tool
2933 /// property records and emit hook function declaration for each
2934 /// instance of $CALL(HookName).
2935 void EmitHookDeclarations(const ToolDescriptions& ToolDescs,
2936                           const OptionDescriptions& OptDescs, raw_ostream& O) {
2937   HookInfoMap HookNames;
2938
2939   FillInHookNames(ToolDescs, OptDescs, HookNames);
2940   if (HookNames.empty())
2941     return;
2942
2943   for (HookInfoMap::const_iterator B = HookNames.begin(),
2944          E = HookNames.end(); B != E; ++B) {
2945     const char* HookName = B->first();
2946     const HookInfo& Info = B->second;
2947
2948     O.indent(Indent1) << "std::string " << HookName << "(";
2949
2950     if (Info.Type == HookInfo::ArgHook) {
2951       for (unsigned i = 0, j = Info.NumArgs; i < j; ++i) {
2952         O << "const char* Arg" << i << (i+1 == j ? "" : ", ");
2953       }
2954     }
2955     else {
2956       O << "const std::vector<std::string>& Arg";
2957     }
2958
2959     O <<");\n";
2960   }
2961 }
2962
2963 /// EmitIncludes - Emit necessary #include directives and some
2964 /// additional declarations.
2965 void EmitIncludes(raw_ostream& O) {
2966   O << "#include \"llvm/CompilerDriver/BuiltinOptions.h\"\n"
2967     << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
2968     << "#include \"llvm/CompilerDriver/Error.h\"\n"
2969     << "#include \"llvm/CompilerDriver/Tool.h\"\n\n"
2970
2971     << "#include \"llvm/Support/CommandLine.h\"\n"
2972     << "#include \"llvm/Support/raw_ostream.h\"\n\n"
2973
2974     << "#include <algorithm>\n"
2975     << "#include <cstdlib>\n"
2976     << "#include <iterator>\n"
2977     << "#include <stdexcept>\n\n"
2978
2979     << "using namespace llvm;\n"
2980     << "using namespace llvmc;\n\n"
2981
2982     << "inline const char* checkCString(const char* s)\n"
2983     << "{ return s == NULL ? \"\" : s; }\n\n";
2984 }
2985
2986
2987 /// DriverData - Holds all information about the driver.
2988 struct DriverData {
2989   OptionDescriptions OptDescs;
2990   ToolDescriptions ToolDescs;
2991   DagVector Edges;
2992   bool HasSink;
2993 };
2994
2995 /// HasSink - Go through the list of tool descriptions and check if
2996 /// there are any with the 'sink' property set.
2997 bool HasSink(const ToolDescriptions& ToolDescs) {
2998   for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
2999          E = ToolDescs.end(); B != E; ++B)
3000     if ((*B)->isSink())
3001       return true;
3002
3003   return false;
3004 }
3005
3006 /// CollectDriverData - Collect compilation graph edges, tool properties and
3007 /// option properties from the parse tree.
3008 void CollectDriverData (const RecordKeeper& Records, DriverData& Data) {
3009   // Collect option properties.
3010   const RecordVector& OptionLists =
3011     Records.getAllDerivedDefinitions("OptionList");
3012   CollectOptionDescriptions(OptionLists, Data.OptDescs);
3013
3014   // Collect tool properties.
3015   const RecordVector& Tools = Records.getAllDerivedDefinitions("Tool");
3016   CollectToolDescriptions(Tools, Data.ToolDescs);
3017   Data.HasSink = HasSink(Data.ToolDescs);
3018
3019   // Collect compilation graph edges.
3020   const RecordVector& CompilationGraphs =
3021     Records.getAllDerivedDefinitions("CompilationGraph");
3022   FillInEdgeVector(CompilationGraphs, Data.Edges);
3023 }
3024
3025 /// CheckDriverData - Perform some sanity checks on the collected data.
3026 void CheckDriverData(DriverData& Data) {
3027   // Filter out all tools not mentioned in the compilation graph.
3028   FilterNotInGraph(Data.Edges, Data.ToolDescs);
3029
3030   // Typecheck the compilation graph.
3031   TypecheckGraph(Data.Edges, Data.ToolDescs);
3032
3033   // Check that there are no options without side effects (specified
3034   // only in the OptionList).
3035   CheckForSuperfluousOptions(Data.Edges, Data.ToolDescs, Data.OptDescs);
3036 }
3037
3038 void EmitDriverCode(const DriverData& Data, 
3039                     raw_ostream& O, RecordKeeper &Records) {
3040   // Emit file header.
3041   EmitIncludes(O);
3042
3043   // Emit global option registration code.
3044   O << "namespace llvmc {\n"
3045     << "namespace autogenerated {\n\n";
3046   EmitOptionDefinitions(Data.OptDescs, Data.HasSink, O);
3047   O << "} // End namespace autogenerated.\n"
3048     << "} // End namespace llvmc.\n\n";
3049
3050   // Emit hook declarations.
3051   O << "namespace hooks {\n";
3052   EmitHookDeclarations(Data.ToolDescs, Data.OptDescs, O);
3053   O << "} // End namespace hooks.\n\n";
3054
3055   O << "namespace {\n\n";
3056   O << "using namespace llvmc::autogenerated;\n\n";
3057
3058   // Emit Tool classes.
3059   for (ToolDescriptions::const_iterator B = Data.ToolDescs.begin(),
3060          E = Data.ToolDescs.end(); B!=E; ++B)
3061     EmitToolClassDefinition(*(*B), Data.OptDescs, O);
3062
3063   // Emit Edge# classes.
3064   EmitEdgeClasses(Data.Edges, Data.OptDescs, O);
3065
3066   O << "} // End anonymous namespace.\n\n";
3067
3068   O << "namespace llvmc {\n";
3069   O << "namespace autogenerated {\n\n";
3070
3071   // Emit PreprocessOptions() function.
3072   EmitPreprocessOptions(Records, Data.OptDescs, O);
3073
3074   // Emit PopulateLanguageMap() function
3075   // (language map maps from file extensions to language names).
3076   EmitPopulateLanguageMap(Records, O);
3077
3078   // Emit PopulateCompilationGraph() function.
3079   EmitPopulateCompilationGraph(Data.Edges, Data.ToolDescs, O);
3080
3081   O << "} // End namespace autogenerated.\n";
3082   O << "} // End namespace llvmc.\n\n";
3083
3084   // EOF
3085 }
3086
3087
3088 // End of anonymous namespace
3089 }
3090
3091 /// run - The back-end entry point.
3092 void LLVMCConfigurationEmitter::run (raw_ostream &O) {
3093   try {
3094     DriverData Data;
3095
3096     CollectDriverData(Records, Data);
3097     CheckDriverData(Data);
3098
3099     this->EmitSourceFileHeader("llvmc-based driver: auto-generated code", O);
3100     EmitDriverCode(Data, O, Records);
3101
3102   } catch (std::exception& Error) {
3103     throw Error.what() + std::string(" - usually this means a syntax error.");
3104   }
3105 }