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