Change ScheduleDAG's SUnitMap from DenseMap<SDNode*, vector<SUnit*> >
[oota-llvm.git] / utils / TableGen / LLVMCConfigurationEmitter.cpp
index d3ad22c34a61b29425948ec1b1996648e1e3af0f..f30c6ee0a83bf4e78dc89eac1e09cf0f63091c73 100644 (file)
@@ -1,4 +1,4 @@
-//===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config --------------===//
+//===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config ----*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Streams.h"
-
 #include <algorithm>
 #include <cassert>
 #include <functional>
+#include <stdexcept>
 #include <string>
-
+#include <typeinfo>
 using namespace llvm;
 
 namespace {
@@ -53,17 +54,22 @@ const char * SinkOptionName = "AutoGeneratedSinkOption";
 //===----------------------------------------------------------------------===//
 /// Helper functions
 
+int InitPtrToInt(const Init* ptr) {
+  const IntInit& val = dynamic_cast<const IntInit&>(*ptr);
+  return val.getValue();
+}
+
 const std::string& InitPtrToString(const Init* ptr) {
   const StringInit& val = dynamic_cast<const StringInit&>(*ptr);
   return val.getValue();
 }
 
-int InitPtrToInt(const Init* ptr) {
-  const IntInit& val = dynamic_cast<const IntInit&>(*ptr);
-  return val.getValue();
+const ListInit& InitPtrToList(const Init* ptr) {
+  const ListInit& val = dynamic_cast<const ListInit&>(*ptr);
+  return val;
 }
 
-const DagInit& InitPtrToDagInitRef(const Init* ptr) {
+const DagInit& InitPtrToDag(const Init* ptr) {
   const DagInit& val = dynamic_cast<const DagInit&>(*ptr);
   return val;
 }
@@ -86,7 +92,9 @@ bool isDagEmpty (const DagInit* d) {
 
 // A command-line option can have one of the following types:
 //
-// Switch - a simple switch w/o arguments, e.g. -O2
+// Alias - an alias for another option.
+//
+// Switch - a simple switch without arguments, e.g. -O2
 //
 // Parameter - an option that takes one(and only one) argument, e.g. -o file,
 // --output=file
@@ -98,10 +106,11 @@ bool isDagEmpty (const DagInit* d) {
 // e.g. -Wa,-foo,-bar, -DNAME=VALUE
 //
 // PrefixList - same as Prefix, but more than one option occurence is
-// allowed
+// allowed.
 
 namespace OptionType {
-  enum OptionType { Switch, Parameter, ParameterList, Prefix, PrefixList};
+  enum OptionType { Alias, Switch,
+                    Parameter, ParameterList, Prefix, PrefixList};
 }
 
 bool IsListOptionType (OptionType::OptionType t) {
@@ -126,6 +135,8 @@ struct OptionDescription {
 
   const char* GenTypeDeclaration() const {
     switch (Type) {
+    case OptionType::Alias:
+      return "cl::alias";
     case OptionType::PrefixList:
     case OptionType::ParameterList:
       return "cl::list<std::string>";
@@ -157,18 +168,20 @@ struct OptionDescription {
   std::string GenVariableName() const {
     const std::string& EscapedName = EscapeVariableName(Name);
     switch (Type) {
+    case OptionType::Alias:
+     return "AutoGeneratedAlias" + EscapedName;
     case OptionType::Switch:
-     return "AutoGeneratedSwitch" + EscapedName;
-   case OptionType::Prefix:
-     return "AutoGeneratedPrefix" + EscapedName;
-   case OptionType::PrefixList:
-     return "AutoGeneratedPrefixList" + EscapedName;
-   case OptionType::Parameter:
-     return "AutoGeneratedParameter" + EscapedName;
-   case OptionType::ParameterList:
-   default:
-     return "AutoGeneratedParameterList" + EscapedName;
-   }
+      return "AutoGeneratedSwitch" + EscapedName;
+    case OptionType::Prefix:
+      return "AutoGeneratedPrefix" + EscapedName;
+    case OptionType::PrefixList:
+      return "AutoGeneratedPrefixList" + EscapedName;
+    case OptionType::Parameter:
+      return "AutoGeneratedParameter" + EscapedName;
+    case OptionType::ParameterList:
+    default:
+      return "AutoGeneratedParameterList" + EscapedName;
+    }
   }
 
 };
@@ -188,8 +201,9 @@ struct GlobalOptionDescription : public OptionDescription {
   GlobalOptionDescription() : OptionDescription(), Flags(0)
   {}
 
-  GlobalOptionDescription (OptionType::OptionType t, const std::string& n)
-    : OptionDescription(t, n), Help(DefaultHelpString), Flags(0)
+  GlobalOptionDescription (OptionType::OptionType t, const std::string& n,
+                           const std::string& h = DefaultHelpString)
+    : OptionDescription(t, n), Help(h), Flags(0)
   {}
 
   bool isRequired() const {
@@ -228,6 +242,7 @@ struct GlobalOptionDescriptions {
   /// HasSink - Should the emitter generate a "cl::sink" option?
   bool HasSink;
 
+  /// FindOption - exception-throwing wrapper for find().
   const GlobalOptionDescription& FindOption(const std::string& OptName) const {
     const_iterator I = Descriptions.find(OptName);
     if (I != Descriptions.end())
@@ -236,6 +251,20 @@ struct GlobalOptionDescriptions {
       throw OptName + ": no such option!";
   }
 
+  /// insertDescription - Insert new GlobalOptionDescription into
+  /// GlobalOptionDescriptions list
+  void insertDescription (const GlobalOptionDescription& o)
+  {
+    container_type::iterator I = Descriptions.find(o.Name);
+    if (I != Descriptions.end()) {
+      GlobalOptionDescription& D = I->second;
+      D.Merge(o);
+    }
+    else {
+      Descriptions[o.Name] = o;
+    }
+  }
+
   // Support for STL-style iteration
   const_iterator begin() const { return Descriptions.begin(); }
   const_iterator end() const { return Descriptions.end(); }
@@ -308,7 +337,7 @@ namespace ToolFlags {
 struct ToolProperties : public RefCountedBase<ToolProperties> {
   std::string Name;
   Init* CmdLine;
-  std::string InLanguage;
+  StrVector InLanguage;
   std::string OutLanguage;
   std::string OutputSuffix;
   unsigned Flags;
@@ -322,8 +351,8 @@ struct ToolProperties : public RefCountedBase<ToolProperties> {
 
   // Default ctor here is needed because StringMap can only store
   // DefaultConstructible objects
-  ToolProperties() : Flags(0) {}
-  ToolProperties (const std::string& n) : Name(n), Flags(0) {}
+  ToolProperties() : CmdLine(0), Flags(0) {}
+  ToolProperties (const std::string& n) : Name(n), CmdLine(0), Flags(0) {}
 };
 
 
@@ -333,12 +362,226 @@ struct ToolProperties : public RefCountedBase<ToolProperties> {
 typedef std::vector<IntrusiveRefCntPtr<ToolProperties> > ToolPropertiesList;
 
 
+/// CollectOptionProperties - Function object for iterating over a
+/// list (usually, a DAG) of option property records.
+class CollectOptionProperties {
+private:
+  // Implementation details.
+
+  /// OptionPropertyHandler - a function that extracts information
+  /// about a given option property from its DAG representation.
+  typedef void (CollectOptionProperties::* OptionPropertyHandler)
+  (const DagInit*);
+
+  /// OptionPropertyHandlerMap - A map from option property names to
+  /// option property handlers
+  typedef StringMap<OptionPropertyHandler> OptionPropertyHandlerMap;
+
+  static OptionPropertyHandlerMap optionPropertyHandlers_;
+  static bool staticMembersInitialized_;
+
+  /// This is where the information is stored
+
+  /// toolProps_ -  Properties of the current Tool.
+  ToolProperties* toolProps_;
+  /// optDescs_ - OptionDescriptions table (used to register options
+  /// globally).
+  GlobalOptionDescription& optDesc_;
+
+public:
+
+  explicit CollectOptionProperties(ToolProperties* TP,
+                                   GlobalOptionDescription& OD)
+    : toolProps_(TP), optDesc_(OD)
+  {
+    if (!staticMembersInitialized_) {
+      optionPropertyHandlers_["append_cmd"] =
+        &CollectOptionProperties::onAppendCmd;
+      optionPropertyHandlers_["forward"] =
+        &CollectOptionProperties::onForward;
+      optionPropertyHandlers_["help"] =
+        &CollectOptionProperties::onHelp;
+      optionPropertyHandlers_["output_suffix"] =
+        &CollectOptionProperties::onOutputSuffix;
+      optionPropertyHandlers_["required"] =
+        &CollectOptionProperties::onRequired;
+      optionPropertyHandlers_["stop_compilation"] =
+        &CollectOptionProperties::onStopCompilation;
+      optionPropertyHandlers_["unpack_values"] =
+        &CollectOptionProperties::onUnpackValues;
+
+      staticMembersInitialized_ = true;
+    }
+  }
+
+  /// operator() - Gets called for every option property; Just forwards
+  /// to the corresponding property handler.
+  void operator() (Init* i) {
+    const DagInit& option_property = InitPtrToDag(i);
+    const std::string& option_property_name
+      = option_property.getOperator()->getAsString();
+    OptionPropertyHandlerMap::iterator method
+      = optionPropertyHandlers_.find(option_property_name);
+
+    if (method != optionPropertyHandlers_.end()) {
+      OptionPropertyHandler h = method->second;
+      (this->*h)(&option_property);
+    }
+    else {
+      throw "Unknown option property: " + option_property_name + "!";
+    }
+  }
+
+private:
+
+  /// Option property handlers --
+  /// Methods that handle properties that are common for all types of
+  /// options (like append_cmd, stop_compilation)
+
+  void onAppendCmd (const DagInit* d) {
+    checkNumberOfArguments(d, 1);
+    checkToolProps(d);
+    const std::string& cmd = InitPtrToString(d->getArg(0));
+
+    toolProps_->OptDescs[optDesc_.Name].
+      AddProperty(OptionPropertyType::AppendCmd, cmd);
+  }
+
+  void onOutputSuffix (const DagInit* d) {
+    checkNumberOfArguments(d, 1);
+    checkToolProps(d);
+    const std::string& suf = InitPtrToString(d->getArg(0));
+
+    if (toolProps_->OptDescs[optDesc_.Name].Type != OptionType::Switch)
+      throw "Option " + optDesc_.Name
+        + " can't have 'output_suffix' property since it isn't a switch!";
+
+    toolProps_->OptDescs[optDesc_.Name].AddProperty
+      (OptionPropertyType::OutputSuffix, suf);
+  }
+
+  void onForward (const DagInit* d) {
+    checkNumberOfArguments(d, 0);
+    checkToolProps(d);
+    toolProps_->OptDescs[optDesc_.Name].setForward();
+  }
+
+  void onHelp (const DagInit* d) {
+    checkNumberOfArguments(d, 1);
+    const std::string& help_message = InitPtrToString(d->getArg(0));
+
+    optDesc_.Help = help_message;
+  }
+
+  void onRequired (const DagInit* d) {
+    checkNumberOfArguments(d, 0);
+    checkToolProps(d);
+    optDesc_.setRequired();
+  }
+
+  void onStopCompilation (const DagInit* d) {
+    checkNumberOfArguments(d, 0);
+    checkToolProps(d);
+    if (optDesc_.Type != OptionType::Switch)
+      throw std::string("Only options of type Switch can stop compilation!");
+    toolProps_->OptDescs[optDesc_.Name].setStopCompilation();
+  }
+
+  void onUnpackValues (const DagInit* d) {
+    checkNumberOfArguments(d, 0);
+    checkToolProps(d);
+    toolProps_->OptDescs[optDesc_.Name].setUnpackValues();
+  }
+
+  // Helper functions
+
+  /// checkToolProps - Throw an error if toolProps_ == 0.
+  void checkToolProps(const DagInit* d) {
+    if (!d)
+      throw "Option property " + d->getOperator()->getAsString()
+        + " can't be used in this context";
+  }
+
+};
+
+CollectOptionProperties::OptionPropertyHandlerMap
+CollectOptionProperties::optionPropertyHandlers_;
+
+bool CollectOptionProperties::staticMembersInitialized_ = false;
+
+
+/// processOptionProperties - Go through the list of option
+/// properties and call a corresponding handler for each.
+void processOptionProperties (const DagInit* d, ToolProperties* t,
+                              GlobalOptionDescription& o) {
+  checkNumberOfArguments(d, 2);
+  DagInit::const_arg_iterator B = d->arg_begin();
+  // Skip the first argument: it's always the option name.
+  ++B;
+  std::for_each(B, d->arg_end(), CollectOptionProperties(t, o));
+}
+
+/// AddOption - A function object wrapper for
+/// processOptionProperties. Used by CollectProperties and
+/// CollectPropertiesFromOptionList.
+class AddOption {
+private:
+  GlobalOptionDescriptions& OptDescs_;
+  ToolProperties* ToolProps_;
+
+public:
+  explicit AddOption(GlobalOptionDescriptions& OD, ToolProperties* TP = 0)
+    : OptDescs_(OD), ToolProps_(TP)
+  {}
+
+  void operator()(const Init* i) {
+    const DagInit& d = InitPtrToDag(i);
+    checkNumberOfArguments(&d, 2);
+
+    const OptionType::OptionType Type =
+      getOptionType(d.getOperator()->getAsString());
+    const std::string& Name = InitPtrToString(d.getArg(0));
+
+    GlobalOptionDescription OD(Type, Name);
+    if (Type != OptionType::Alias) {
+      processOptionProperties(&d, ToolProps_, OD);
+      if (ToolProps_) {
+        ToolProps_->OptDescs[Name].Type = Type;
+        ToolProps_->OptDescs[Name].Name = Name;
+      }
+    }
+    else {
+      OD.Help = InitPtrToString(d.getArg(1));
+    }
+    OptDescs_.insertDescription(OD);
+  }
+
+private:
+  OptionType::OptionType getOptionType(const std::string& T) const {
+    if (T == "alias_option")
+      return OptionType::Alias;
+    else if (T == "switch_option")
+      return OptionType::Switch;
+    else if (T == "parameter_option")
+      return OptionType::Parameter;
+    else if (T == "parameter_list_option")
+      return OptionType::ParameterList;
+    else if (T == "prefix_option")
+      return OptionType::Prefix;
+    else if (T == "prefix_list_option")
+      return OptionType::PrefixList;
+    else
+      throw "Unknown option type: " + T + '!';
+  }
+};
+
+
 /// CollectProperties - Function object for iterating over a list of
 /// tool property records.
 class CollectProperties {
 private:
 
-  /// Implementation details
+  // Implementation details
 
   /// PropertyHandler - a function that extracts information
   /// about a given tool property from its DAG representation
@@ -348,18 +591,8 @@ private:
   /// handlers.
   typedef StringMap<PropertyHandler> PropertyHandlerMap;
 
-  /// OptionPropertyHandler - a function that extracts information
-  /// about a given option property from its DAG representation.
-  typedef void (CollectProperties::* OptionPropertyHandler)
-  (const DagInit*, GlobalOptionDescription &);
-
-  /// OptionPropertyHandlerMap - A map from option property names to
-  /// option property handlers
-  typedef StringMap<OptionPropertyHandler> OptionPropertyHandlerMap;
-
   // Static maps from strings to CollectProperties methods("handlers")
   static PropertyHandlerMap propertyHandlers_;
-  static OptionPropertyHandlerMap optionPropertyHandlers_;
   static bool staticMembersInitialized_;
 
 
@@ -377,33 +610,21 @@ public:
     : toolProps_(p), optDescs_(d)
   {
     if (!staticMembersInitialized_) {
-      // Init tool property handlers
       propertyHandlers_["cmd_line"] = &CollectProperties::onCmdLine;
       propertyHandlers_["in_language"] = &CollectProperties::onInLanguage;
       propertyHandlers_["join"] = &CollectProperties::onJoin;
       propertyHandlers_["out_language"] = &CollectProperties::onOutLanguage;
       propertyHandlers_["output_suffix"] = &CollectProperties::onOutputSuffix;
       propertyHandlers_["parameter_option"]
-        = &CollectProperties::onParameter;
+        = &CollectProperties::addOption;
       propertyHandlers_["parameter_list_option"] =
-        &CollectProperties::onParameterList;
-      propertyHandlers_["prefix_option"] = &CollectProperties::onPrefix;
+        &CollectProperties::addOption;
+      propertyHandlers_["prefix_option"] = &CollectProperties::addOption;
       propertyHandlers_["prefix_list_option"] =
-        &CollectProperties::onPrefixList;
+        &CollectProperties::addOption;
       propertyHandlers_["sink"] = &CollectProperties::onSink;
-      propertyHandlers_["switch_option"] = &CollectProperties::onSwitch;
-
-      // Init option property handlers
-      optionPropertyHandlers_["append_cmd"] = &CollectProperties::onAppendCmd;
-      optionPropertyHandlers_["forward"] = &CollectProperties::onForward;
-      optionPropertyHandlers_["help"] = &CollectProperties::onHelp;
-      optionPropertyHandlers_["output_suffix"] =
-        &CollectProperties::onOutputSuffixOptionProp;
-      optionPropertyHandlers_["required"] = &CollectProperties::onRequired;
-      optionPropertyHandlers_["stop_compilation"] =
-        &CollectProperties::onStopCompilation;
-      optionPropertyHandlers_["unpack_values"] =
-        &CollectProperties::onUnpackValues;
+      propertyHandlers_["switch_option"] = &CollectProperties::addOption;
+      propertyHandlers_["alias_option"] = &CollectProperties::addOption;
 
       staticMembersInitialized_ = true;
     }
@@ -412,7 +633,7 @@ public:
   /// operator() - Gets called for every tool property; Just forwards
   /// to the corresponding property handler.
   void operator() (Init* i) {
-    const DagInit& d = InitPtrToDagInitRef(i);
+    const DagInit& d = InitPtrToDag(i);
     const std::string& property_name = d.getOperator()->getAsString();
     PropertyHandlerMap::iterator method
       = propertyHandlers_.find(property_name);
@@ -439,7 +660,29 @@ private:
 
   void onInLanguage (const DagInit* d) {
     checkNumberOfArguments(d, 1);
-    toolProps_.InLanguage = InitPtrToString(d->getArg(0));
+    Init* arg = d->getArg(0);
+
+    // Find out the argument's type.
+    if (typeid(*arg) == typeid(StringInit)) {
+      // It's a string.
+      toolProps_.InLanguage.push_back(InitPtrToString(arg));
+    }
+    else {
+      // It's a list.
+      const ListInit& lst = InitPtrToList(arg);
+      StrVector& out = toolProps_.InLanguage;
+
+      // Copy strings to the output vector.
+      for (ListInit::const_iterator B = lst.begin(), E = lst.end();
+           B != E; ++B) {
+        out.push_back(InitPtrToString(*B));
+      }
+
+      // Remove duplicates.
+      std::sort(out.begin(), out.end());
+      StrVector::iterator newE = std::unique(out.begin(), out.end());
+      out.erase(newE, out.end());
+    }
   }
 
   void onJoin (const DagInit* d) {
@@ -463,146 +706,23 @@ private:
     toolProps_.setSink();
   }
 
-  void onSwitch (const DagInit* d) {
-    addOption(d, OptionType::Switch);
-  }
-
-  void onParameter (const DagInit* d) {
-    addOption(d, OptionType::Parameter);
-  }
-
-  void onParameterList (const DagInit* d) {
-    addOption(d, OptionType::ParameterList);
-  }
-
-  void onPrefix (const DagInit* d) {
-    addOption(d, OptionType::Prefix);
-  }
-
-  void onPrefixList (const DagInit* d) {
-    addOption(d, OptionType::PrefixList);
-  }
-
-  /// Option property handlers --
-  /// Methods that handle properties that are common for all types of
-  /// options (like append_cmd, stop_compilation)
-
-  void onAppendCmd (const DagInit* d, GlobalOptionDescription& o) {
-    checkNumberOfArguments(d, 1);
-    const std::string& cmd = InitPtrToString(d->getArg(0));
-
-    toolProps_.OptDescs[o.Name].AddProperty(OptionPropertyType::AppendCmd, cmd);
-  }
-
-  void onOutputSuffixOptionProp (const DagInit* d, GlobalOptionDescription& o) {
-    checkNumberOfArguments(d, 1);
-    const std::string& suf = InitPtrToString(d->getArg(0));
-
-    if (toolProps_.OptDescs[o.Name].Type != OptionType::Switch)
-      throw "Option " + o.Name
-        + " can't have 'output_suffix' property since it isn't a switch!";
-
-    toolProps_.OptDescs[o.Name].AddProperty
-      (OptionPropertyType::OutputSuffix, suf);
-  }
-
-  void onForward (const DagInit* d, GlobalOptionDescription& o) {
-    checkNumberOfArguments(d, 0);
-    toolProps_.OptDescs[o.Name].setForward();
-  }
-
-  void onHelp (const DagInit* d, GlobalOptionDescription& o) {
-    checkNumberOfArguments(d, 1);
-    const std::string& help_message = InitPtrToString(d->getArg(0));
-
-    o.Help = help_message;
-  }
-
-  void onRequired (const DagInit* d, GlobalOptionDescription& o) {
-    checkNumberOfArguments(d, 0);
-    o.setRequired();
-  }
-
-  void onStopCompilation (const DagInit* d, GlobalOptionDescription& o) {
-    checkNumberOfArguments(d, 0);
-    if (o.Type != OptionType::Switch)
-      throw std::string("Only options of type Switch can stop compilation!");
-    toolProps_.OptDescs[o.Name].setStopCompilation();
-  }
-
-  void onUnpackValues (const DagInit* d, GlobalOptionDescription& o) {
-    checkNumberOfArguments(d, 0);
-    toolProps_.OptDescs[o.Name].setUnpackValues();
-  }
-
-  /// Helper functions
-
-  // Add an option of type t
-  void addOption (const DagInit* d, OptionType::OptionType t) {
+  // Just forwards to the AddOption function object. Somewhat
+  // non-optimal, but avoids code duplication.
+  void addOption (const DagInit* d) {
     checkNumberOfArguments(d, 2);
-    const std::string& name = InitPtrToString(d->getArg(0));
-
-    GlobalOptionDescription o(t, name);
-    toolProps_.OptDescs[name].Type = t;
-    toolProps_.OptDescs[name].Name = name;
-    processOptionProperties(d, o);
-    insertDescription(o);
+    AddOption(optDescs_, &toolProps_)(d);
   }
 
-  // Insert new GlobalOptionDescription into GlobalOptionDescriptions list
-  void insertDescription (const GlobalOptionDescription& o)
-  {
-    if (optDescs_.Descriptions.count(o.Name)) {
-      GlobalOptionDescription& D = optDescs_.Descriptions[o.Name];
-      D.Merge(o);
-    }
-    else {
-      optDescs_.Descriptions[o.Name] = o;
-    }
-  }
-
-  /// processOptionProperties - Go through the list of option
-  /// properties and call a corresponding handler for each.
-  ///
-  /// Parameters:
-  /// name - option name
-  /// d - option property list
-  void processOptionProperties (const DagInit* d, GlobalOptionDescription& o) {
-    // First argument is option name
-    checkNumberOfArguments(d, 2);
-
-    for (unsigned B = 1, E = d->getNumArgs(); B!=E; ++B) {
-      const DagInit& option_property
-        = InitPtrToDagInitRef(d->getArg(B));
-      const std::string& option_property_name
-        = option_property.getOperator()->getAsString();
-      OptionPropertyHandlerMap::iterator method
-        = optionPropertyHandlers_.find(option_property_name);
-
-      if (method != optionPropertyHandlers_.end()) {
-        OptionPropertyHandler h = method->second;
-        (this->*h)(&option_property, o);
-      }
-      else {
-        throw "Unknown option property: " + option_property_name + "!";
-      }
-    }
-  }
 };
 
-// Static members of CollectProperties
-CollectProperties::PropertyHandlerMap
-CollectProperties::propertyHandlers_;
-
-CollectProperties::OptionPropertyHandlerMap
-CollectProperties::optionPropertyHandlers_;
-
+// Defintions of static members of CollectProperties.
+CollectProperties::PropertyHandlerMap CollectProperties::propertyHandlers_;
 bool CollectProperties::staticMembersInitialized_ = false;
 
 
-/// CollectToolProperties - Gather information from the parsed
-/// TableGen data (basically a wrapper for the CollectProperties
-/// function object).
+/// CollectToolProperties - Gather information about tool properties
+/// from the parsed TableGen data (basically a wrapper for the
+/// CollectProperties function object).
 void CollectToolProperties (RecordVector::const_iterator B,
                             RecordVector::const_iterator E,
                             ToolPropertiesList& TPList,
@@ -610,7 +730,8 @@ void CollectToolProperties (RecordVector::const_iterator B,
 {
   // Iterate over a properties list of every Tool definition
   for (;B!=E;++B) {
-    RecordVector::value_type T = *B;
+    Record* T = *B;
+    // Throws an exception if the value does not exist.
     ListInit* PropList = T->getValueAsListInit("properties");
 
     IntrusiveRefCntPtr<ToolProperties>
@@ -622,12 +743,60 @@ void CollectToolProperties (RecordVector::const_iterator B,
   }
 }
 
+
+/// CollectPropertiesFromOptionList - Gather information about
+/// *global* option properties from the OptionList.
+void CollectPropertiesFromOptionList (RecordVector::const_iterator B,
+                                      RecordVector::const_iterator E,
+                                      GlobalOptionDescriptions& OptDescs)
+{
+  // Iterate over a properties list of every Tool definition
+  for (;B!=E;++B) {
+    RecordVector::value_type T = *B;
+    // Throws an exception if the value does not exist.
+    ListInit* PropList = T->getValueAsListInit("options");
+
+    std::for_each(PropList->begin(), PropList->end(), AddOption(OptDescs));
+  }
+}
+
+/// CheckForSuperfluousOptions - Check that there are no side
+/// effect-free options (specified only in the OptionList). Otherwise,
+/// output a warning.
+void CheckForSuperfluousOptions (const ToolPropertiesList& TPList,
+                                 const GlobalOptionDescriptions& OptDescs) {
+  llvm::StringSet<> nonSuperfluousOptions;
+
+  // Add all options mentioned in the TPList to the set of
+  // non-superfluous options.
+  for (ToolPropertiesList::const_iterator B = TPList.begin(),
+         E = TPList.end(); B != E; ++B) {
+    const ToolProperties& TP = *(*B);
+    for (ToolOptionDescriptions::const_iterator B = TP.OptDescs.begin(),
+           E = TP.OptDescs.end(); B != E; ++B) {
+      nonSuperfluousOptions.insert(B->first());
+    }
+  }
+
+  // Check that all options in OptDescs belong to the set of
+  // non-superfluous options.
+  for (GlobalOptionDescriptions::const_iterator B = OptDescs.begin(),
+         E = OptDescs.end(); B != E; ++B) {
+    const GlobalOptionDescription& Val = B->second;
+    if (!nonSuperfluousOptions.count(Val.Name)
+        && Val.Type != OptionType::Alias)
+      cerr << "Warning: option '-" << Val.Name << "' has no effect! "
+        "Probable cause: this option is specified only in the OptionList.\n";
+  }
+}
+
 /// EmitCaseTest1Arg - Helper function used by
 /// EmitCaseConstructHandler.
 bool EmitCaseTest1Arg(const std::string& TestName,
                       const DagInit& d,
                       const GlobalOptionDescriptions& OptDescs,
                       std::ostream& O) {
+  // TOFIX - Add a mechanism for OS detection.
   checkNumberOfArguments(&d, 1);
   const std::string& OptName = InitPtrToString(d.getArg(0));
   if (TestName == "switch_on") {
@@ -639,6 +808,22 @@ bool EmitCaseTest1Arg(const std::string& TestName,
   } else if (TestName == "input_languages_contain") {
     O << "InLangs.count(\"" << OptName << "\") != 0";
     return true;
+  } else if (TestName == "in_language") {
+    // Works only for cmd_line!
+    O << "GetLanguage(inFile) == \"" << OptName << '\"';
+    return true;
+  } else if (TestName == "not_empty") {
+    if (OptName == "o") {
+      O << "!OutputFilename.empty()";
+      return true;
+    }
+    else {
+      const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName);
+      if (OptDesc.Type == OptionType::Switch)
+        throw OptName + ": incorrect option type!";
+      O << '!' << OptDesc.GenVariableName() << ".empty()";
+      return true;
+    }
   }
 
   return false;
@@ -691,7 +876,7 @@ void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp,
                               std::ostream& O) {
   O << '(';
   for (unsigned j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) {
-    const DagInit& InnerTest = InitPtrToDagInitRef(d.getArg(j));
+    const DagInit& InnerTest = InitPtrToDag(d.getArg(j));
     EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
     if (j != NumArgs - 1)
       O << ")\n" << IndentLevel << Indent1 << ' ' << LogicOp << " (";
@@ -724,30 +909,28 @@ void EmitCaseTest(const DagInit& d, const char* IndentLevel,
 // void F(Init* Statement, const char* IndentLevel, std::ostream& O).
 template <typename F>
 void EmitCaseConstructHandler(const DagInit* d, const char* IndentLevel,
-                              const F& Callback, bool DefaultRequired,
+                              F Callback, bool EmitElseIf,
                               const GlobalOptionDescriptions& OptDescs,
                               std::ostream& O) {
   assert(d->getOperator()->getAsString() == "case");
 
-  bool DefaultProvided = false;
   unsigned numArgs = d->getNumArgs();
   if (d->getNumArgs() < 2)
     throw "There should be at least one clause in the 'case' expression:\n"
       + d->getAsString();
 
   for (unsigned i = 0; i != numArgs; ++i) {
-    const DagInit& Test = InitPtrToDagInitRef(d->getArg(i));
+    const DagInit& Test = InitPtrToDag(d->getArg(i));
 
     // Emit the test.
     if (Test.getOperator()->getAsString() == "default") {
-      DefaultProvided = true;
       if (i+2 != numArgs)
         throw std::string("The 'default' clause should be the last in the"
                           "'case' construct!");
       O << IndentLevel << "else {\n";
     }
     else {
-      O << IndentLevel << "if (";
+      O << IndentLevel << ((i != 0 && EmitElseIf) ? "else if (" : "if (");
       EmitCaseTest(Test, IndentLevel, OptDescs, O);
       O << ") {\n";
     }
@@ -758,13 +941,18 @@ void EmitCaseConstructHandler(const DagInit* d, const char* IndentLevel,
       throw "Case construct handler: no corresponding action "
         "found for the test " + Test.getAsString() + '!';
 
-    Callback(d->getArg(i), IndentLevel, O);
+    Init* arg = d->getArg(i);
+    if (dynamic_cast<DagInit*>(arg)
+        && static_cast<DagInit*>(arg)->getOperator()->getAsString() == "case") {
+      EmitCaseConstructHandler(static_cast<DagInit*>(arg),
+                               (std::string(IndentLevel) + Indent1).c_str(),
+                               Callback, EmitElseIf, OptDescs, O);
+    }
+    else {
+      Callback(arg, IndentLevel, O);
+    }
     O << IndentLevel << "}\n";
   }
-
-  if (DefaultRequired && !DefaultProvided)
-    throw "Case expression: the 'default' clause is required in this case:\n"
-      + d->getAsString();
 }
 
 /// EmitForwardOptionPropertyHandlingCode - Helper function used to
@@ -800,6 +988,9 @@ void EmitForwardOptionPropertyHandlingCode (const ToolOptionDescription& D,
       << Indent4 << "vec.push_back(*B);\n"
       << Indent3 << "}\n";
     break;
+  case OptionType::Alias:
+  default:
+    throw std::string("Aliases are not allowed in tool option descriptions!");
   }
 }
 
@@ -952,10 +1143,10 @@ void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
       O << "vec.push_back(\"" << cmd << "\");\n";
     }
   }
-  O << IndentLevel << "ret = Action("
+  O << IndentLevel << "cmd = "
     << ((StrVec[0][0] == '$') ? SubstituteSpecialCommands(StrVec[0])
         : "\"" + StrVec[0] + "\"")
-    << ", vec);\n";
+    << ";\n";
 }
 
 /// EmitCmdLineVecFillCallback - A function object wrapper around
@@ -989,14 +1180,14 @@ void EmitGenerateActionMethod (const ToolProperties& P,
   O << Indent2 << "const sys::Path& outFile,\n"
     << Indent2 << "const InputLanguagesSet& InLangs) const\n"
     << Indent1 << "{\n"
-    << Indent2 << "Action ret;\n"
+    << Indent2 << "const char* cmd;\n"
     << Indent2 << "std::vector<std::string> vec;\n";
 
   // cmd_line is either a string or a 'case' construct.
   if (typeid(*P.CmdLine) == typeid(StringInit))
     EmitCmdLineVecFill(P.CmdLine, P.Name, Version, Indent2, O);
   else
-    EmitCaseConstructHandler(&InitPtrToDagInitRef(P.CmdLine), Indent2,
+    EmitCaseConstructHandler(&InitPtrToDag(P.CmdLine), Indent2,
                              EmitCmdLineVecFillCallback(Version, P.Name),
                              true, OptDescs, O);
 
@@ -1015,7 +1206,7 @@ void EmitGenerateActionMethod (const ToolProperties& P,
       << Indent2 << "}\n";
   }
 
-  O << Indent2 << "return ret;\n"
+  O << Indent2 << "return Action(cmd, vec);\n"
     << Indent1 << "}\n\n";
 }
 
@@ -1061,8 +1252,8 @@ void EmitIsLastMethod (const ToolProperties& P, std::ostream& O) {
 /// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
 /// methods for a given Tool class.
 void EmitInOutLanguageMethods (const ToolProperties& P, std::ostream& O) {
-  O << Indent1 << "const char* InputLanguage() const {\n"
-    << Indent2 << "return \"" << P.InLanguage << "\";\n"
+  O << Indent1 << "const char** InputLanguages() const {\n"
+    << Indent2 << "return InputLanguages_;\n"
     << Indent1 << "}\n\n";
 
   O << Indent1 << "const char* OutputLanguage() const {\n"
@@ -1111,6 +1302,16 @@ void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) {
   O << Indent1 << "}\n\n";
 }
 
+/// EmitStaticMemberDefinitions - Emit static member definitions for a
+/// given Tool class.
+void EmitStaticMemberDefinitions(const ToolProperties& P, std::ostream& O) {
+  O << "const char* " << P.Name << "::InputLanguages_[] = {";
+  for (StrVector::const_iterator B = P.InLanguage.begin(),
+         E = P.InLanguage.end(); B != E; ++B)
+    O << '\"' << *B << "\", ";
+  O << "0};\n\n";
+}
+
 /// EmitToolClassDefinition - Emit a Tool class definition.
 void EmitToolClassDefinition (const ToolProperties& P,
                               const GlobalOptionDescriptions& OptDescs,
@@ -1124,8 +1325,11 @@ void EmitToolClassDefinition (const ToolProperties& P,
     O << "JoinTool";
   else
     O << "Tool";
-  O << " {\npublic:\n";
 
+  O << "{\nprivate:\n"
+    << Indent1 << "static const char* InputLanguages_[];\n\n";
+
+  O << "public:\n";
   EmitNameMethod(P, O);
   EmitInOutLanguageMethods(P, O);
   EmitOutputSuffixMethod(P, O);
@@ -1134,7 +1338,10 @@ void EmitToolClassDefinition (const ToolProperties& P,
   EmitIsLastMethod(P, O);
 
   // Close class definition
-  O << "};\n\n";
+  O << "};\n";
+
+  EmitStaticMemberDefinitions(P, O);
+
 }
 
 /// EmitOptionDescriptions - Iterate over a list of option
@@ -1142,11 +1349,18 @@ void EmitToolClassDefinition (const ToolProperties& P,
 void EmitOptionDescriptions (const GlobalOptionDescriptions& descs,
                              std::ostream& O)
 {
-  // Emit static cl::Option variables
+  std::vector<GlobalOptionDescription> Aliases;
+
+  // Emit static cl::Option variables.
   for (GlobalOptionDescriptions::const_iterator B = descs.begin(),
          E = descs.end(); B!=E; ++B) {
     const GlobalOptionDescription& val = B->second;
 
+    if (val.Type == OptionType::Alias) {
+      Aliases.push_back(val);
+      continue;
+    }
+
     O << val.GenTypeDeclaration() << ' '
       << val.GenVariableName()
       << "(\"" << val.Name << '\"';
@@ -1165,9 +1379,32 @@ void EmitOptionDescriptions (const GlobalOptionDescriptions& descs,
       }
     }
 
-    O << ", cl::desc(\"" << val.Help << "\"));\n";
+    if (!val.Help.empty())
+      O << ", cl::desc(\"" << val.Help << "\")";
+
+    O << ");\n";
+  }
+
+  // Emit the aliases (they should go after all the 'proper' options).
+  for (std::vector<GlobalOptionDescription>::const_iterator
+         B = Aliases.begin(), E = Aliases.end(); B != E; ++B) {
+    const GlobalOptionDescription& val = *B;
+
+    O << val.GenTypeDeclaration() << ' '
+      << val.GenVariableName()
+      << "(\"" << val.Name << '\"';
+
+    GlobalOptionDescriptions::container_type
+      ::const_iterator F = descs.Descriptions.find(val.Help);
+    if (F != descs.Descriptions.end())
+      O << ", cl::aliasopt(" << F->second.GenVariableName() << ")";
+    else
+      throw val.Name + ": alias to an unknown option!";
+
+    O << ", cl::desc(\"" << "An alias for -" + val.Help  << "\"));\n";
   }
 
+  // Emit the sink option.
   if (descs.HasSink)
     O << "cl::list<std::string> " << SinkOptionName << "(cl::Sink);\n";
 
@@ -1187,7 +1424,7 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
     throw std::string("Error in the language map definition!");
 
   // Generate code
-  O << "void llvmc::PopulateLanguageMap(LanguageMap& language_map) {\n";
+  O << "void llvmc::PopulateLanguageMap() {\n";
 
   for (unsigned i = 0; i < LangsToSuffixesList->size(); ++i) {
     Record* LangToSuffixes = LangsToSuffixesList->getElementAsRecord(i);
@@ -1196,7 +1433,7 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
     const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes");
 
     for (unsigned i = 0; i < Suffixes->size(); ++i)
-      O << Indent1 << "language_map[\""
+      O << Indent1 << "GlobalLanguageMap[\""
         << InitPtrToString(Suffixes->getElement(i))
         << "\"] = \"" << Lang << "\";\n";
   }
@@ -1207,41 +1444,47 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
 /// FillInToolToLang - Fills in two tables that map tool names to
 /// (input, output) languages.  Used by the typechecker.
 void FillInToolToLang (const ToolPropertiesList& TPList,
-                       StringMap<std::string>& ToolToInLang,
+                       StringMap<StringSet<> >& ToolToInLang,
                        StringMap<std::string>& ToolToOutLang) {
   for (ToolPropertiesList::const_iterator B = TPList.begin(), E = TPList.end();
        B != E; ++B) {
     const ToolProperties& P = *(*B);
-    ToolToInLang[P.Name] = P.InLanguage;
+    for (StrVector::const_iterator B = P.InLanguage.begin(),
+           E = P.InLanguage.end(); B != E; ++B)
+      ToolToInLang[P.Name].insert(*B);
     ToolToOutLang[P.Name] = P.OutLanguage;
   }
 }
 
 /// TypecheckGraph - Check that names for output and input languages
 /// on all edges do match.
-// TOFIX: check for cycles.
-// TOFIX: check for multiple default edges.
+// TOFIX: It would be nice if this function also checked for cycles
+// and multiple default edges in the graph (better error
+// reporting). Unfortunately, it is awkward to do right now because
+// our intermediate representation is not sufficiently
+// sofisticated. Algorithms like these should be run on a real graph
+// instead of AST.
 void TypecheckGraph (Record* CompilationGraph,
                      const ToolPropertiesList& TPList) {
-  StringMap<std::string> ToolToInLang;
+  StringMap<StringSet<> > ToolToInLang;
   StringMap<std::string> ToolToOutLang;
 
   FillInToolToLang(TPList, ToolToInLang, ToolToOutLang);
   ListInit* edges = CompilationGraph->getValueAsListInit("edges");
-  StringMap<std::string>::iterator IAE = ToolToInLang.end();
-  StringMap<std::string>::iterator IBE = ToolToOutLang.end();
+  StringMap<std::string>::iterator IAE = ToolToOutLang.end();
+  StringMap<StringSet<> >::iterator IBE = ToolToInLang.end();
 
   for (unsigned i = 0; i < edges->size(); ++i) {
     Record* Edge = edges->getElementAsRecord(i);
     Record* A = Edge->getValueAsDef("a");
     Record* B = Edge->getValueAsDef("b");
     StringMap<std::string>::iterator IA = ToolToOutLang.find(A->getName());
-    StringMap<std::string>::iterator IB = ToolToInLang.find(B->getName());
+    StringMap<StringSet<> >::iterator IB = ToolToInLang.find(B->getName());
     if (IA == IAE)
       throw A->getName() + ": no such tool!";
     if (IB == IBE)
       throw B->getName() + ": no such tool!";
-    if (A->getName() != "root" && IA->second != IB->second)
+    if (A->getName() != "root" && IB->second.count(IA->second) == 0)
       throw "Edge " + A->getName() + "->" + B->getName()
         + ": output->input language mismatch";
     if (B->getName() == "root")
@@ -1253,7 +1496,7 @@ void TypecheckGraph (Record* CompilationGraph,
 /// by EmitEdgeClass().
 void IncDecWeight (const Init* i, const char* IndentLevel,
                    std::ostream& O) {
-  const DagInit& d = InitPtrToDagInitRef(i);
+  const DagInit& d = InitPtrToDag(i);
   const std::string& OpName = d.getOperator()->getAsString();
 
   if (OpName == "inc_weight")
@@ -1319,7 +1562,7 @@ void EmitPopulateCompilationGraph (Record* CompilationGraph,
 
   // Generate code
   O << "void llvmc::PopulateCompilationGraph(CompilationGraph& G) {\n"
-    << Indent1 << "PopulateLanguageMap(G.ExtsToLangs);\n\n";
+    << Indent1 << "PopulateLanguageMap();\n\n";
 
   // Insert vertices
 
@@ -1374,30 +1617,40 @@ void ExtractHookNames(const Init* CmdLine, StrVector& HookNames) {
   }
 }
 
+/// ExtractHookNamesFromCaseConstruct - Extract hook names from the
+/// 'case' expression, handle nesting. Helper function used by
+/// FillInHookNames().
+void ExtractHookNamesFromCaseConstruct(Init* Case, StrVector& HookNames) {
+  const DagInit& d = InitPtrToDag(Case);
+  bool even = false;
+  for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
+       B != E; ++B) {
+    Init* arg = *B;
+    if (even && dynamic_cast<DagInit*>(arg)
+        && static_cast<DagInit*>(arg)->getOperator()->getAsString() == "case")
+      ExtractHookNamesFromCaseConstruct(arg, HookNames);
+    else if (even)
+      ExtractHookNames(arg, HookNames);
+    even = !even;
+  }
+}
+
 /// FillInHookNames - Actually extract the hook names from all command
 /// line strings. Helper function used by EmitHookDeclarations().
 void FillInHookNames(const ToolPropertiesList& TPList,
                      StrVector& HookNames) {
+  // For all command lines:
   for (ToolPropertiesList::const_iterator B = TPList.begin(),
          E = TPList.end(); B != E; ++B) {
     const ToolProperties& P = *(*B);
     if (!P.CmdLine)
       continue;
-    if (typeid(*P.CmdLine) == typeid(StringInit)) {
+    if (dynamic_cast<StringInit*>(P.CmdLine))
       // This is a string.
       ExtractHookNames(P.CmdLine, HookNames);
-    }
-    else {
+    else
       // This is a 'case' construct.
-      const DagInit& d = InitPtrToDagInitRef(P.CmdLine);
-      bool even = false;
-      for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
-           B != E; ++B) {
-        if (even)
-          ExtractHookNames(*B, HookNames);
-        even = !even;
-      }
-    }
+      ExtractHookNamesFromCaseConstruct(P.CmdLine, HookNames);
   }
 }
 
@@ -1425,6 +1678,7 @@ void EmitHookDeclarations(const ToolPropertiesList& ToolProps,
 
 /// run - The back-end entry point.
 void LLVMCConfigurationEmitter::run (std::ostream &O) {
+  try {
 
   // Emit file header.
   EmitSourceFileHeader("LLVMC Configuration Library", O);
@@ -1439,6 +1693,14 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) {
   GlobalOptionDescriptions opt_descs;
   CollectToolProperties(Tools.begin(), Tools.end(), tool_props, opt_descs);
 
+  RecordVector OptionLists = Records.getAllDerivedDefinitions("OptionList");
+  CollectPropertiesFromOptionList(OptionLists.begin(), OptionLists.end(),
+                                  opt_descs);
+
+  // Check that there are no options without side effects (specified
+  // only in the OptionList).
+  CheckForSuperfluousOptions(tool_props, opt_descs);
+
   // Emit global option registration code.
   EmitOptionDescriptions(opt_descs, O);
 
@@ -1468,4 +1730,7 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) {
   EmitPopulateCompilationGraph(CompilationGraphRecord, O);
 
   // EOF
+  } catch (std::exception& Error) {
+    throw Error.what() + std::string(" - usually this means a syntax error.");
+  }
 }