Have TableGen emit setSubgraphColor calls under control of a -gen-debug
[oota-llvm.git] / utils / TableGen / LLVMCConfigurationEmitter.cpp
index 77daf627a25f6a60bceaa8e879b641f17bee959d..43729033c39c4e0ca81189f94421050eb1e7a53e 100644 (file)
 #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 {
@@ -156,11 +155,18 @@ struct OptionDescription {
   std::string EscapeVariableName(const std::string& Var) const {
     std::string ret;
     for (unsigned i = 0; i != Var.size(); ++i) {
-      if (Var[i] == ',') {
+      char cur_char = Var[i];
+      if (cur_char == ',') {
+        ret += "_comma_";
+      }
+      else if (cur_char == '+') {
+        ret += "_plus_";
+      }
+      else if (cur_char == ',') {
         ret += "_comma_";
       }
       else {
-        ret.push_back(Var[i]);
+        ret.push_back(cur_char);
       }
     }
     return ret;
@@ -243,6 +249,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())
@@ -251,6 +258,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(); }
@@ -265,7 +286,7 @@ namespace ToolOptionDescriptionFlags {
                                     Forward = 0x2, UnpackValues = 0x4};
 }
 namespace OptionPropertyType {
-  enum OptionPropertyType { AppendCmd, OutputSuffix };
+  enum OptionPropertyType { AppendCmd, ForwardAs, OutputSuffix };
 }
 
 typedef std::pair<OptionPropertyType::OptionPropertyType, std::string>
@@ -337,8 +358,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) {}
 };
 
 
@@ -348,12 +369,237 @@ 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_["forward_as"] =
+        &CollectOptionProperties::onForwardAs;
+      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 onForwardAs (const DagInit* d) {
+    checkNumberOfArguments(d, 1);
+    checkToolProps(d);
+    const std::string& cmd = InitPtrToString(d->getArg(0));
+
+    toolProps_->OptDescs[optDesc_.Name].
+      AddProperty(OptionPropertyType::ForwardAs, cmd);
+  }
+
+  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
@@ -363,18 +609,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_;
 
 
@@ -392,34 +628,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;
-      propertyHandlers_["alias_option"] = &CollectProperties::onAlias;
-
-      // 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;
     }
@@ -501,149 +724,17 @@ private:
     toolProps_.setSink();
   }
 
-  void onAlias (const DagInit* d) {
+  // Just forwards to the AddOption function object. Somewhat
+  // non-optimal, but avoids code duplication.
+  void addOption (const DagInit* d) {
     checkNumberOfArguments(d, 2);
-    // We just need a GlobalOptionDescription for the aliases.
-    insertDescription
-      (GlobalOptionDescription(OptionType::Alias,
-                               InitPtrToString(d->getArg(0)),
-                               InitPtrToString(d->getArg(1))));
-  }
-
-  void onSwitch (const DagInit* d) {
-    addOption(d, OptionType::Switch);
+    AddOption(optDescs_, &toolProps_)(d);
   }
 
-  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) {
-    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);
-  }
-
-  // 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
-        = InitPtrToDag(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;
 
 
@@ -670,25 +761,50 @@ void CollectToolProperties (RecordVector::const_iterator B,
   }
 }
 
-/// CollectToolPropertiesFromOptionList - Gather information about
+
+/// CollectPropertiesFromOptionList - Gather information about
 /// *global* option properties from the OptionList.
-// TOFIX - This is kinda hacky, since it allows to use arbitrary tool
-// properties in the OptionList. CollectProperties function object
-// should be split into two parts that collect tool and option
-// properties, respectively.
 void CollectPropertiesFromOptionList (RecordVector::const_iterator B,
                                       RecordVector::const_iterator E,
                                       GlobalOptionDescriptions& OptDescs)
 {
   // Iterate over a properties list of every Tool definition
-  ToolProperties ToolProps("dummy");
   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(),
-                  CollectProperties(ToolProps, OptDescs));
+    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";
   }
 }
 
@@ -710,8 +826,11 @@ bool EmitCaseTest1Arg(const std::string& TestName,
     O << "InLangs.count(\"" << OptName << "\") != 0";
     return true;
   } else if (TestName == "in_language") {
-    // Works only for cmd_line!
-    O << "GetLanguage(inFile) == \"" << OptName << '\"';
+    // This works only for single-argument Tool::GenerateAction. Join
+    // tools can process several files in different languages simultaneously.
+
+    // TODO: make this work with Edge::Weight (if possible).
+    O << "LangMap.GetLanguage(inFile) == \"" << OptName << '\"';
     return true;
   } else if (TestName == "not_empty") {
     if (OptName == "o") {
@@ -810,7 +929,7 @@ 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 EmitElseIf,
+                              F Callback, bool EmitElseIf,
                               const GlobalOptionDescriptions& OptDescs,
                               std::ostream& O) {
   assert(d->getOperator()->getAsString() == "case");
@@ -858,26 +977,31 @@ void EmitCaseConstructHandler(const DagInit* d, const char* IndentLevel,
 
 /// EmitForwardOptionPropertyHandlingCode - Helper function used to
 /// implement EmitOptionPropertyHandlingCode(). Emits code for
-/// handling the (forward) option property.
+/// handling the (forward) and (forward_as) option properties.
 void EmitForwardOptionPropertyHandlingCode (const ToolOptionDescription& D,
+                                            const std::string& NewName,
                                             std::ostream& O) {
+  const std::string& Name = NewName.empty()
+    ? ("-" + D.Name)
+    : NewName;
+
   switch (D.Type) {
   case OptionType::Switch:
-    O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
+    O << Indent3 << "vec.push_back(\"" << Name << "\");\n";
     break;
   case OptionType::Parameter:
-    O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
+    O << Indent3 << "vec.push_back(\"" << Name << "\");\n";
     O << Indent3 << "vec.push_back(" << D.GenVariableName() << ");\n";
     break;
   case OptionType::Prefix:
-    O << Indent3 << "vec.push_back(\"-" << D.Name << "\" + "
+    O << Indent3 << "vec.push_back(\"" << Name << "\" + "
       << D.GenVariableName() << ");\n";
     break;
   case OptionType::PrefixList:
     O << Indent3 << "for (" << D.GenTypeDeclaration()
       << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
       << Indent3 << "E = " << D.GenVariableName() << ".end(); B != E; ++B)\n"
-      << Indent4 << "vec.push_back(\"-" << D.Name << "\" + "
+      << Indent4 << "vec.push_back(\"" << Name << "\" + "
       << "*B);\n";
     break;
   case OptionType::ParameterList:
@@ -885,7 +1009,7 @@ void EmitForwardOptionPropertyHandlingCode (const ToolOptionDescription& D,
       << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
       << Indent3 << "E = " << D.GenVariableName()
       << ".end() ; B != E; ++B) {\n"
-      << Indent4 << "vec.push_back(\"-" << D.Name << "\");\n"
+      << Indent4 << "vec.push_back(\"" << Name << "\");\n"
       << Indent4 << "vec.push_back(*B);\n"
       << Indent3 << "}\n";
     break;
@@ -903,7 +1027,8 @@ bool ToolOptionHasInterestingProperties(const ToolOptionDescription& D) {
   for (OptionPropertyList::const_iterator B = D.Props.begin(),
          E = D.Props.end(); B != E; ++B) {
       const OptionProperty& OptProp = *B;
-      if (OptProp.first == OptionPropertyType::AppendCmd)
+      if (OptProp.first == OptionPropertyType::AppendCmd
+          || OptProp.first == OptionPropertyType::ForwardAs)
         ret = true;
     }
   if (D.isForward() || D.isUnpackValues())
@@ -938,6 +1063,10 @@ void EmitOptionPropertyHandlingCode (const ToolOptionDescription& D,
     case OptionPropertyType::AppendCmd:
       O << Indent3 << "vec.push_back(\"" << val.second << "\");\n";
       break;
+      // (forward_as) property
+    case OptionPropertyType::ForwardAs:
+      EmitForwardOptionPropertyHandlingCode(D, val.second, O);
+      break;
       // Other properties with argument
     default:
       break;
@@ -948,7 +1077,7 @@ void EmitOptionPropertyHandlingCode (const ToolOptionDescription& D,
 
   // (forward) property
   if (D.isForward())
-    EmitForwardOptionPropertyHandlingCode(D, O);
+    EmitForwardOptionPropertyHandlingCode(D, "", O);
 
   // (unpack_values) property
   if (D.isUnpackValues()) {
@@ -1079,7 +1208,8 @@ void EmitGenerateActionMethod (const ToolProperties& P,
     O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n";
 
   O << Indent2 << "const sys::Path& outFile,\n"
-    << Indent2 << "const InputLanguagesSet& InLangs) const\n"
+    << Indent2 << "const InputLanguagesSet& InLangs,\n"
+    << Indent2 << "const LanguageMap& LangMap) const\n"
     << Indent1 << "{\n"
     << Indent2 << "const char* cmd;\n"
     << Indent2 << "std::vector<std::string> vec;\n";
@@ -1119,7 +1249,8 @@ void EmitGenerateActionMethods (const ToolProperties& P,
   if (!P.isJoin())
     O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"
       << Indent2 << "const llvm::sys::Path& outFile,\n"
-      << Indent2 << "const InputLanguagesSet& InLangs) const\n"
+      << Indent2 << "const InputLanguagesSet& InLangs,\n"
+      << Indent2 << "const LanguageMap& LangMap) const\n"
       << Indent1 << "{\n"
       << Indent2 << "throw std::runtime_error(\"" << P.Name
       << " is not a Join tool!\");\n"
@@ -1325,7 +1456,8 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
     throw std::string("Error in the language map definition!");
 
   // Generate code
-  O << "void llvmc::PopulateLanguageMap() {\n";
+  O << "namespace {\n\n";
+  O << "void PopulateLanguageMapLocal(LanguageMap& langMap) {\n";
 
   for (unsigned i = 0; i < LangsToSuffixesList->size(); ++i) {
     Record* LangToSuffixes = LangsToSuffixesList->getElementAsRecord(i);
@@ -1334,12 +1466,12 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
     const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes");
 
     for (unsigned i = 0; i < Suffixes->size(); ++i)
-      O << Indent1 << "GlobalLanguageMap[\""
+      O << Indent1 << "langMap[\""
         << InitPtrToString(Suffixes->getElement(i))
         << "\"] = \"" << Lang << "\";\n";
   }
 
-  O << "}\n\n";
+  O << "}\n\n}\n\n";
 }
 
 /// FillInToolToLang - Fills in two tables that map tool names to
@@ -1363,8 +1495,8 @@ void FillInToolToLang (const ToolPropertiesList& TPList,
 // 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.
+// sophisticated. Algorithms like these require a real graph instead of
+// an AST.
 void TypecheckGraph (Record* CompilationGraph,
                      const ToolPropertiesList& TPList) {
   StringMap<StringSet<> > ToolToInLang;
@@ -1462,8 +1594,8 @@ void EmitPopulateCompilationGraph (Record* CompilationGraph,
   ListInit* edges = CompilationGraph->getValueAsListInit("edges");
 
   // Generate code
-  O << "void llvmc::PopulateCompilationGraph(CompilationGraph& G) {\n"
-    << Indent1 << "PopulateLanguageMap();\n\n";
+  O << "namespace {\n\n";
+  O << "void PopulateCompilationGraphLocal(CompilationGraph& G) {\n";
 
   // Insert vertices
 
@@ -1497,7 +1629,7 @@ void EmitPopulateCompilationGraph (Record* CompilationGraph,
     O << ");\n";
   }
 
-  O << "}\n\n";
+  O << "}\n\n}\n\n";
 }
 
 /// ExtractHookNames - Extract the hook names from all instances of
@@ -1574,6 +1706,38 @@ void EmitHookDeclarations(const ToolPropertiesList& ToolProps,
   O << "}\n\n";
 }
 
+/// EmitRegisterPlugin - Emit code to register this plugin.
+void EmitRegisterPlugin(std::ostream& O) {
+  O << "namespace {\n\n"
+    << "struct Plugin : public llvmc::BasePlugin {\n"
+    << Indent1 << "void PopulateLanguageMap(LanguageMap& langMap) const\n"
+    << Indent1 << "{ PopulateLanguageMapLocal(langMap); }\n\n"
+    << Indent1
+    << "void PopulateCompilationGraph(CompilationGraph& graph) const\n"
+    << Indent1 << "{ PopulateCompilationGraphLocal(graph); }\n"
+    << "};\n\n"
+
+    << "static llvmc::RegisterPlugin<Plugin> RP;\n\n}\n\n";
+}
+
+/// EmitInclude - Emit necessary #include directives.
+void EmitIncludes(std::ostream& O) {
+  O << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
+    << "#include \"llvm/CompilerDriver/Plugin.h\"\n"
+    << "#include \"llvm/CompilerDriver/Tool.h\"\n\n"
+
+    << "#include \"llvm/ADT/StringExtras.h\"\n"
+    << "#include \"llvm/Support/CommandLine.h\"\n\n"
+
+    << "#include <cstdlib>\n"
+    << "#include <stdexcept>\n\n"
+
+    << "using namespace llvm;\n"
+    << "using namespace llvmc;\n\n"
+
+    << "extern cl::opt<std::string> OutputFilename;\n\n";
+}
+
 // End of anonymous namespace
 }
 
@@ -1583,6 +1747,7 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) {
 
   // Emit file header.
   EmitSourceFileHeader("LLVMC Configuration Library", O);
+  EmitIncludes(O);
 
   // Get a list of all defined Tools.
   RecordVector Tools = Records.getAllDerivedDefinitions("Tool");
@@ -1598,6 +1763,10 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) {
   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);
 
@@ -1626,6 +1795,9 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) {
   // Emit PopulateCompilationGraph() function.
   EmitPopulateCompilationGraph(CompilationGraphRecord, O);
 
+  // Emit code for plugin registration.
+  EmitRegisterPlugin(O);
+
   // EOF
   } catch (std::exception& Error) {
     throw Error.what() + std::string(" - usually this means a syntax error.");