A small refactoring (extract method) + some comment fixes.
[oota-llvm.git] / utils / TableGen / LLVMCConfigurationEmitter.cpp
index aaa10992d99e357ab9a0d0e75c2954a4cad47459..7330dd3fc592737fa5d6d4fb5fb6e8e37390bc21 100644 (file)
@@ -38,16 +38,16 @@ typedef std::vector<std::string> StrVector;
 //===----------------------------------------------------------------------===//
 /// Constants
 
-// Indentation strings
+// Indentation strings.
 const char * Indent1 = "    ";
 const char * Indent2 = "        ";
 const char * Indent3 = "            ";
 const char * Indent4 = "                ";
 
-// Default help string
+// Default help string.
 const char * DefaultHelpString = "NO HELP MESSAGE PROVIDED";
 
-// Name for the "sink" option
+// Name for the "sink" option.
 const char * SinkOptionName = "AutoGeneratedSinkOption";
 
 //===----------------------------------------------------------------------===//
@@ -58,8 +58,19 @@ std::string InitPtrToString(Init* ptr) {
   return val.getValue();
 }
 
-// Ensure that the number of args in d is <= min_arguments,
-// throw exception otherwise
+int InitPtrToInt(Init* ptr) {
+  IntInit& val = dynamic_cast<IntInit&>(*ptr);
+  return val.getValue();
+}
+
+const DagInit& InitPtrToDagInitRef(Init* ptr) {
+  DagInit& val = dynamic_cast<DagInit&>(*ptr);
+  return val;
+}
+
+
+// checkNumberOfArguments - Ensure that the number of args in d is
+// less than or equal to min_arguments, otherwise throw an exception .
 void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) {
   if (d->getNumArgs() < min_arguments)
     throw "Property " + d->getOperator()->getAsString()
@@ -100,8 +111,7 @@ bool IsListOptionType (OptionType::OptionType t) {
 // the option registration code, while ToolOptionDescriptions are used
 // to generate tool-specific code.
 
-// Base class for option descriptions
-
+/// OptionDescription - Base class for option descriptions.
 struct OptionDescription {
   OptionType::OptionType Type;
   std::string Name;
@@ -143,7 +153,7 @@ struct OptionDescription {
 
 };
 
-// Global option description
+// Global option description.
 
 namespace GlobalOptionDescriptionFlags {
   enum GlobalOptionDescriptionFlags { Required = 0x1 };
@@ -153,8 +163,8 @@ struct GlobalOptionDescription : public OptionDescription {
   std::string Help;
   unsigned Flags;
 
-  // We need t provide a default constructor since
-  // StringMap can only store DefaultConstructible objects
+  // We need to provide a default constructor because
+  // StringMap can only store DefaultConstructible objects.
   GlobalOptionDescription() : OptionDescription(), Flags(0)
   {}
 
@@ -169,31 +179,33 @@ struct GlobalOptionDescription : public OptionDescription {
     Flags |= GlobalOptionDescriptionFlags::Required;
   }
 
-  // Merge two option descriptions
+  /// Merge - Merge two option descriptions.
   void Merge (const GlobalOptionDescription& other)
   {
     if (other.Type != Type)
       throw "Conflicting definitions for the option " + Name + "!";
 
-    if (Help.empty() && !other.Help.empty())
+    if (Help == DefaultHelpString)
       Help = other.Help;
-    else if (!Help.empty() && !other.Help.empty())
-      cerr << "Warning: more than one help string defined for option "
+    else if (other.Help != DefaultHelpString) {
+      llvm::cerr << "Warning: more than one help string defined for option "
         + Name + "\n";
+    }
 
     Flags |= other.Flags;
   }
 };
 
-// A GlobalOptionDescription array
-// + some flags affecting generation of option declarations
+/// GlobalOptionDescriptions - A GlobalOptionDescription array
+/// together with some flags affecting generation of option
+/// declarations.
 struct GlobalOptionDescriptions {
   typedef StringMap<GlobalOptionDescription> container_type;
   typedef container_type::const_iterator const_iterator;
 
-  // A list of GlobalOptionDescriptions
+  /// Descriptions - A list of GlobalOptionDescriptions.
   container_type Descriptions;
-  // Should the emitter generate a "cl::sink" option?
+  /// HasSink - Should the emitter generate a "cl::sink" option?
   bool HasSink;
 
   const GlobalOptionDescription& FindOption(const std::string& OptName) const {
@@ -210,9 +222,9 @@ struct GlobalOptionDescriptions {
 };
 
 
-// Tool-local option description
+// Tool-local option description.
 
-// Properties without arguments are implemented as flags
+// Properties without arguments are implemented as flags.
 namespace ToolOptionDescriptionFlags {
   enum ToolOptionDescriptionFlags { StopCompilation = 0x1,
                                     Forward = 0x2, UnpackValues = 0x4};
@@ -290,36 +302,39 @@ struct ToolProperties : public RefCountedBase<ToolProperties> {
 
   // Default ctor here is needed because StringMap can only store
   // DefaultConstructible objects
-  ToolProperties() {}
-  ToolProperties (const std::string& n) : Name(n) {}
+  ToolProperties() : Flags(0) {}
+  ToolProperties (const std::string& n) : Name(n), Flags(0) {}
 };
 
 
-// A list of Tool information records
-// IntrusiveRefCntPtrs are used because StringMap has no copy constructor
-// (and we want to avoid copying ToolProperties anyway)
+/// ToolPropertiesList - A list of Tool information records
+/// IntrusiveRefCntPtrs are used here because StringMap has no copy
+/// constructor (and we want to avoid copying ToolProperties anyway).
 typedef std::vector<IntrusiveRefCntPtr<ToolProperties> > ToolPropertiesList;
 
 
-// Function object for iterating over a list of tool property records
+/// CollectProperties - Function object for iterating over a list of
+/// tool property records.
 class CollectProperties {
 private:
 
   /// Implementation details
 
-  // "Property handler" - a function that extracts information
-  // about a given tool property from its DAG representation
-  typedef void (CollectProperties::*PropertyHandler)(DagInit*);
+  /// PropertyHandler - a function that extracts information
+  /// about a given tool property from its DAG representation
+  typedef void (CollectProperties::*PropertyHandler)(const DagInit*);
 
-  // Map from property names -> property handlers
+  /// PropertyHandlerMap - A map from property names to property
+  /// handlers.
   typedef StringMap<PropertyHandler> PropertyHandlerMap;
 
-  // "Option property handler" - a function that extracts information
-  // about a given option property from its DAG representation
-  typedef void (CollectProperties::*
-                OptionPropertyHandler)(DagInit*, GlobalOptionDescription &);
+  /// OptionPropertyHandler - a function that extracts information
+  /// about a given option property from its DAG representation.
+  typedef void (CollectProperties::* OptionPropertyHandler)
+  (const DagInit*, GlobalOptionDescription &);
 
-  // Map from option property names -> option property handlers
+  /// OptionPropertyHandlerMap - A map from option property names to
+  /// option property handlers
   typedef StringMap<OptionPropertyHandler> OptionPropertyHandlerMap;
 
   // Static maps from strings to CollectProperties methods("handlers")
@@ -330,9 +345,10 @@ private:
 
   /// This is where the information is stored
 
-  // Current Tool properties
+  /// toolProps_ -  Properties of the current Tool.
   ToolProperties& toolProps_;
-  // OptionDescriptions table(used to register options globally)
+  /// optDescs_ - OptionDescriptions table (used to register options
+  /// globally).
   GlobalOptionDescriptions& optDescs_;
 
 public:
@@ -371,10 +387,10 @@ public:
     }
   }
 
-  // Gets called for every tool property;
-  // Just forwards to the corresponding property handler.
+  /// operator() - Gets called for every tool property; Just forwards
+  /// to the corresponding property handler.
   void operator() (Init* i) {
-    DagInit& d = dynamic_cast<DagInit&>(*i);
+    const DagInit& d = InitPtrToDagInitRef(i);
     const std::string& property_name = d.getOperator()->getAsString();
     PropertyHandlerMap::iterator method
       = propertyHandlers_.find(property_name);
@@ -394,81 +410,95 @@ private:
   /// Functions that extract information about tool properties from
   /// DAG representation.
 
-  void onCmdLine (DagInit* d) {
+  void onCmdLine (const DagInit* d) {
     checkNumberOfArguments(d, 1);
     SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine);
     if (toolProps_.CmdLine.empty())
       throw "Tool " + toolProps_.Name + " has empty command line!";
   }
 
-  void onInLanguage (DagInit* d) {
+  void onInLanguage (const DagInit* d) {
     checkNumberOfArguments(d, 1);
     toolProps_.InLanguage = InitPtrToString(d->getArg(0));
   }
 
-  void onJoin (DagInit* d) {
+  void onJoin (const DagInit* d) {
     checkNumberOfArguments(d, 0);
     toolProps_.setJoin();
   }
 
-  void onOutLanguage (DagInit* d) {
+  void onOutLanguage (const DagInit* d) {
     checkNumberOfArguments(d, 1);
     toolProps_.OutLanguage = InitPtrToString(d->getArg(0));
   }
 
-  void onOutputSuffix (DagInit* d) {
+  void onOutputSuffix (const DagInit* d) {
     checkNumberOfArguments(d, 1);
     toolProps_.OutputSuffix = InitPtrToString(d->getArg(0));
   }
 
-  void onSink (DagInit* d) {
+  void onSink (const DagInit* d) {
     checkNumberOfArguments(d, 0);
     optDescs_.HasSink = true;
     toolProps_.setSink();
   }
 
-  void onSwitch (DagInit* d)        { addOption(d, OptionType::Switch); }
-  void onParameter (DagInit* d)     { addOption(d, OptionType::Parameter); }
-  void onParameterList (DagInit* d) { addOption(d, OptionType::ParameterList); }
-  void onPrefix (DagInit* d)        { addOption(d, OptionType::Prefix); }
-  void onPrefixList (DagInit* d)    { addOption(d, OptionType::PrefixList); }
+  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 (DagInit* d, GlobalOptionDescription& o) {
+  void onAppendCmd (const DagInit* d, GlobalOptionDescription& o) {
     checkNumberOfArguments(d, 1);
     std::string const& cmd = InitPtrToString(d->getArg(0));
 
     toolProps_.OptDescs[o.Name].AddProperty(OptionPropertyType::AppendCmd, cmd);
   }
 
-  void onForward (DagInit* d, GlobalOptionDescription& o) {
+  void onForward (const DagInit* d, GlobalOptionDescription& o) {
     checkNumberOfArguments(d, 0);
     toolProps_.OptDescs[o.Name].setForward();
   }
 
-  void onHelp (DagInit* d, GlobalOptionDescription& o) {
+  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 (DagInit* d, GlobalOptionDescription& o) {
+  void onRequired (const DagInit* d, GlobalOptionDescription& o) {
     checkNumberOfArguments(d, 0);
     o.setRequired();
   }
 
-  void onStopCompilation (DagInit* d, GlobalOptionDescription& o) {
+  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 (DagInit* d, GlobalOptionDescription& o) {
+  void onUnpackValues (const DagInit* d, GlobalOptionDescription& o) {
     checkNumberOfArguments(d, 0);
     toolProps_.OptDescs[o.Name].setUnpackValues();
   }
@@ -476,7 +506,7 @@ private:
   /// Helper functions
 
   // Add an option of type t
-  void addOption (DagInit* d, OptionType::OptionType t) {
+  void addOption (const DagInit* d, OptionType::OptionType t) {
     checkNumberOfArguments(d, 2);
     const std::string& name = InitPtrToString(d->getArg(0));
 
@@ -499,19 +529,19 @@ private:
     }
   }
 
-  // Go through the list of option properties and call a corresponding
-  // handler for each.
-  //
-  // Parameters:
-  // name - option name
-  // d - option property list
-  void processOptionProperties (DagInit* d, GlobalOptionDescription& 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) {
-      DagInit& option_property
-        = dynamic_cast<DagInit&>(*d->getArg(B));
+      const DagInit& option_property
+        = InitPtrToDagInitRef(d->getArg(B));
       const std::string& option_property_name
         = option_property.getOperator()->getAsString();
       OptionPropertyHandlerMap::iterator method
@@ -538,8 +568,9 @@ CollectProperties::optionPropertyHandlers_;
 bool CollectProperties::staticMembersInitialized_ = false;
 
 
-// Gather information from the parsed TableGen data
-// (Basically a wrapper for CollectProperties)
+/// CollectToolProperties - Gather information 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,
@@ -559,12 +590,50 @@ void CollectToolProperties (RecordVector::const_iterator B,
   }
 }
 
-// Used by EmitGenerateActionMethod
+/// EmitForwardOptionPropertyHandlingCode - Helper function used to
+/// implement EmitOptionPropertyHandlingCode(). Emits code for
+/// handling the (forward) option property.
+void EmitForwardOptionPropertyHandlingCode (const ToolOptionDescription& D,
+                                            std::ostream& O) {
+  switch (D.Type) {
+  case OptionType::Switch:
+    O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
+    break;
+  case OptionType::Parameter:
+    O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
+    O << Indent3 << "vec.push_back(" << D.GenVariableName() << ");\n";
+    break;
+  case OptionType::Prefix:
+    O << Indent3 << "vec.push_back(\"-" << D.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 << "\" + "
+      << "*B);\n";
+    break;
+  case OptionType::ParameterList:
+    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 << "\");\n"
+      << Indent4 << "vec.push_back(*B);\n"
+      << Indent3 << "}\n";
+    break;
+  }
+}
+
+/// EmitOptionPropertyHandlingCode - Helper function used by
+/// EmitGenerateActionMethod(). Emits code that handles option
+/// properties.
 void EmitOptionPropertyHandlingCode (const ToolProperties& P,
                                      const ToolOptionDescription& D,
                                      std::ostream& O)
 {
-  // if clause
+  // Start of the if-clause.
   O << Indent2 << "if (";
   if (D.Type == OptionType::Switch)
     O << D.GenVariableName();
@@ -573,7 +642,7 @@ void EmitOptionPropertyHandlingCode (const ToolProperties& P,
 
   O <<") {\n";
 
-  // Handle option properties that take an argument
+  // Handle option properties that take an argument.
   for (OptionPropertyList::const_iterator B = D.Props.begin(),
         E = D.Props.end(); B!=E; ++B) {
     const OptionProperty& val = *B;
@@ -592,37 +661,8 @@ void EmitOptionPropertyHandlingCode (const ToolProperties& P,
   // Handle flags
 
   // (forward) property
-  if (D.isForward()) {
-    switch (D.Type) {
-    case OptionType::Switch:
-      O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
-      break;
-    case OptionType::Parameter:
-      O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
-      O << Indent3 << "vec.push_back(" << D.GenVariableName() << ");\n";
-      break;
-    case OptionType::Prefix:
-      O << Indent3 << "vec.push_back(\"-" << D.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 << "\" + "
-        << "*B);\n";
-      break;
-    case OptionType::ParameterList:
-      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 << "\");\n"
-        << Indent4 << "vec.push_back(*B);\n"
-        << Indent3 << "}\n";
-      break;
-    }
-  }
+  if (D.isForward())
+    HandleForwardPropertyy(O);
 
   // (unpack_values) property
   if (D.isUnpackValues()) {
@@ -631,11 +671,11 @@ void EmitOptionPropertyHandlingCode (const ToolProperties& P,
         << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
         << Indent3 << "E = " << D.GenVariableName()
         << ".end(); B != E; ++B)\n"
-        << Indent4 << "Tool::UnpackValues(*B, vec);\n";
+        << Indent4 << "llvm::SplitString(*B, vec, \",\");\n";
     }
     else if (D.Type == OptionType::Prefix || D.Type == OptionType::Parameter){
-      O << Indent3 << "Tool::UnpackValues("
-        << D.GenVariableName() << ", vec);\n";
+      O << Indent3 << "llvm::SplitString("
+        << D.GenVariableName() << ", vec, \",\");\n";
     }
     else {
       // TOFIX: move this to the type-checking phase
@@ -643,15 +683,15 @@ void EmitOptionPropertyHandlingCode (const ToolProperties& P,
     }
   }
 
-  // close if clause
+  // End of the if-clause.
   O << Indent2 << "}\n";
 }
 
-// Emite one of two versions of GenerateAction method
-void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O)
+// EmitGenerateActionMethod - Emit one of two versions of the
+// Tool::GenerateAction() method.
+void EmitGenerateActionMethod (const ToolProperties& P, bool V, std::ostream& O)
 {
-  assert(V==1 || V==2);
-  if (V==1)
+  if (V)
     O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n";
   else
     O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n";
@@ -670,7 +710,7 @@ void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O)
     const std::string& cmd = *I;
     O << Indent2;
     if (cmd == "$INFILE") {
-      if (V==1)
+      if (V)
         O << "for (PathVector::const_iterator B = inFiles.begin()"
           << ", E = inFiles.end();\n"
           << Indent2 << "B != E; ++B)\n"
@@ -686,14 +726,14 @@ void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O)
     }
   }
 
-  // For every understood option, emit handling code
+  // For every understood option, emit handling code.
   for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(),
         E = P.OptDescs.end(); B != E; ++B) {
     const ToolOptionDescription& val = B->second;
     EmitOptionPropertyHandlingCode(P, val, O);
   }
 
-  // Handle Sink property
+  // Handle the Sink property.
   if (P.isSink()) {
     O << Indent2 << "if (!" << SinkOptionName << ".empty()) {\n"
       << Indent3 << "vec.insert(vec.end(), "
@@ -705,7 +745,8 @@ void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O)
     << Indent1 << "}\n\n";
 }
 
-// Emit GenerateAction methods for Tool classes
+/// EmitGenerateActionMethods - Emit two GenerateAction() methods for
+/// a given Tool class.
 void EmitGenerateActionMethods (const ToolProperties& P, std::ostream& O) {
 
   if (!P.isJoin())
@@ -721,7 +762,8 @@ void EmitGenerateActionMethods (const ToolProperties& P, std::ostream& O) {
   EmitGenerateActionMethod(P, 2, O);
 }
 
-// Emit IsLast() method for Tool classes
+/// EmitIsLastMethod - Emit the IsLast() method for a given Tool
+/// class.
 void EmitIsLastMethod (const ToolProperties& P, std::ostream& O) {
   O << Indent1 << "bool IsLast() const {\n"
     << Indent2 << "bool last = false;\n";
@@ -740,7 +782,8 @@ void EmitIsLastMethod (const ToolProperties& P, std::ostream& O) {
     << Indent1 <<  "}\n\n";
 }
 
-// Emit static [Input,Output]Language() methods for Tool classes
+/// 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"
@@ -751,21 +794,23 @@ void EmitInOutLanguageMethods (const ToolProperties& P, std::ostream& O) {
     << Indent1 << "}\n\n";
 }
 
-// Emit static [Input,Output]Language() methods for Tool classes
+/// EmitOutputSuffixMethod - Emit the OutputSuffix() method for a
+/// given Tool class.
 void EmitOutputSuffixMethod (const ToolProperties& P, std::ostream& O) {
   O << Indent1 << "const char* OutputSuffix() const {\n"
     << Indent2 << "return \"" << P.OutputSuffix << "\";\n"
     << Indent1 << "}\n\n";
 }
 
-// Emit static Name() method for Tool classes
+/// EmitNameMethod - Emit the Name() method for a given Tool class.
 void EmitNameMethod (const ToolProperties& P, std::ostream& O) {
   O << Indent1 << "const char* Name() const {\n"
     << Indent2 << "return \"" << P.Name << "\";\n"
     << Indent1 << "}\n\n";
 }
 
-// Emit static Name() method for Tool classes
+/// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
+/// class.
 void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) {
   O << Indent1 << "bool IsJoin() const {\n";
   if (P.isJoin())
@@ -775,7 +820,7 @@ void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) {
   O << Indent1 << "}\n\n";
 }
 
-// Emit a Tool class definition
+/// EmitToolClassDefinition - Emit a Tool class definition.
 void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) {
 
   if(P.Name == "root")
@@ -800,7 +845,8 @@ void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) {
   O << "};\n\n";
 }
 
-// Iterate over a list of option descriptions and emit registration code
+/// EmitOptionDescriptions - Iterate over a list of option
+/// descriptions and emit registration code.
 void EmitOptionDescriptions (const GlobalOptionDescriptions& descs,
                              std::ostream& O)
 {
@@ -836,6 +882,7 @@ void EmitOptionDescriptions (const GlobalOptionDescriptions& descs,
   O << '\n';
 }
 
+/// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function.
 void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
 {
   // Get the relevant field out of RecordKeeper
@@ -865,8 +912,8 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
   O << "}\n\n";
 }
 
-// Fills in two tables that map tool names to (input, output) languages.
-// Used by the typechecker.
+/// 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<std::string>& ToolToOutLang) {
@@ -878,7 +925,8 @@ void FillInToolToLang (const ToolPropertiesList& TPList,
   }
 }
 
-// Check that all output and input language names match.
+/// TypecheckGraph - Check that names for output and input languages
+/// on all edges do match.
 // TOFIX: check for cycles.
 // TOFIX: check for multiple default edges.
 void TypecheckGraph (Record* CompilationGraph,
@@ -909,20 +957,31 @@ void TypecheckGraph (Record* CompilationGraph,
   }
 }
 
-// Helper function used by EmitEdgePropertyTest.
-void EmitEdgePropertyTest1Arg(const DagInit& Prop,
+/// EmitEdgePropertyTest1Arg - Helper function used by
+/// EmitEdgePropertyTest.
+bool EmitEdgePropertyTest1Arg(const std::string& PropName,
+                              const DagInit& Prop,
                               const GlobalOptionDescriptions& OptDescs,
                               std::ostream& O) {
   checkNumberOfArguments(&Prop, 1);
   const std::string& OptName = InitPtrToString(Prop.getArg(0));
-  const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName);
-  if (OptDesc.Type != OptionType::Switch)
-    throw OptName + ": incorrect option type!";
-  O << OptDesc.GenVariableName();
+  if (PropName == "switch_on") {
+    const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName);
+    if (OptDesc.Type != OptionType::Switch)
+      throw OptName + ": incorrect option type!";
+    O << OptDesc.GenVariableName();
+    return true;
+  } else if (PropName == "if_input_languages_contain") {
+    O << "InLangs.count(\"" << OptName << "\") != 0";
+    return true;
+  }
+
+  return false;
 }
 
-// Helper function used by EmitEdgePropertyTest.
-void EmitEdgePropertyTest2Args(const std::string& PropName,
+/// EmitEdgePropertyTest2Args - Helper function used by
+/// EmitEdgePropertyTest.
+bool EmitEdgePropertyTest2Args(const std::string& PropName,
                                const DagInit& Prop,
                                const GlobalOptionDescriptions& OptDescs,
                                std::ostream& O) {
@@ -936,6 +995,7 @@ void EmitEdgePropertyTest2Args(const std::string& PropName,
         && OptDesc.Type != OptionType::Prefix)
       throw OptName + ": incorrect option type!";
     O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
+    return true;
   }
   else if (PropName == "element_in_list") {
     if (OptDesc.Type != OptionType::ParameterList
@@ -945,27 +1005,55 @@ void EmitEdgePropertyTest2Args(const std::string& PropName,
     O << "std::find(" << VarName << ".begin(),\n"
       << Indent3 << VarName << ".end(), \""
       << OptArg << "\") != " << VarName << ".end()";
+    return true;
   }
-  else
-    throw PropName + ": unknown edge property!";
+
+  return false;
 }
 
-// Helper function used by EmitEdgeClass.
-void EmitEdgePropertyTest(const std::string& PropName,
-                          const DagInit& Prop,
+// Forward declaration.
+void EmitEdgePropertyTest(const DagInit& Prop,
+                          const GlobalOptionDescriptions& OptDescs,
+                          std::ostream& O);
+
+/// EmitLogicalOperationTest - Helper function used by
+/// EmitEdgePropertyTest.
+void EmitLogicalOperationTest(const DagInit& Prop, const char* LogicOp,
+                              const GlobalOptionDescriptions& OptDescs,
+                              std::ostream& O) {
+  O << '(';
+  for (unsigned j = 0, NumArgs = Prop.getNumArgs(); j < NumArgs; ++j) {
+    const DagInit& InnerProp = InitPtrToDagInitRef(Prop.getArg(j));
+    EmitEdgePropertyTest(InnerProp, OptDescs, O);
+    if (j != NumArgs - 1)
+      O << ")\n" << Indent3 << ' ' << LogicOp << " (";
+    else
+      O << ')';
+  }
+}
+
+/// EmitEdgePropertyTest - Helper function used by EmitEdgeClass.
+void EmitEdgePropertyTest(const DagInit& Prop,
                           const GlobalOptionDescriptions& OptDescs,
                           std::ostream& O) {
-  if (PropName == "switch_on")
-    EmitEdgePropertyTest1Arg(Prop, OptDescs, O);
+  const std::string& PropName = Prop.getOperator()->getAsString();
+
+  if (PropName == "and")
+    EmitLogicalOperationTest(Prop, "&&", OptDescs, O);
+  else if (PropName == "or")
+    EmitLogicalOperationTest(Prop, "||", OptDescs, O);
+  else if (EmitEdgePropertyTest1Arg(PropName, Prop, OptDescs, O))
+    return;
+  else if (EmitEdgePropertyTest2Args(PropName, Prop, OptDescs, O))
+    return;
   else
-    EmitEdgePropertyTest2Args(PropName, Prop, OptDescs, O);
+    throw PropName + ": unknown edge property!";
 }
 
-// Emit a single Edge* class.
+/// EmitEdgeClass - Emit a single Edge# class.
 void EmitEdgeClass(unsigned N, const std::string& Target,
                    ListInit* Props, const GlobalOptionDescriptions& OptDescs,
                    std::ostream& O) {
-  bool IsDefault = false;
 
   // Class constructor.
   O << "class Edge" << N << ": public Edge {\n"
@@ -973,47 +1061,33 @@ void EmitEdgeClass(unsigned N, const std::string& Target,
     << Indent1 << "Edge" << N << "() : Edge(\"" << Target
     << "\") {}\n\n"
 
-    // Function isEnabled().
-    << Indent1 << "bool isEnabled() const {\n"
-    << Indent2 << "bool ret = false;\n";
+  // Function Weight().
+    << Indent1 << "unsigned Weight(const InputLanguagesSet& InLangs) const {\n"
+    << Indent2 << "unsigned ret = 0;\n";
 
+  // Emit tests for every edge property.
   for (size_t i = 0, PropsSize = Props->size(); i < PropsSize; ++i) {
-    const DagInit& Prop = dynamic_cast<DagInit&>(*Props->getElement(i));
+    const DagInit& Prop = InitPtrToDagInitRef(Props->getElement(i));
     const std::string& PropName = Prop.getOperator()->getAsString();
+    unsigned N = 2;
 
-    if (PropName == "default")
-      IsDefault = true;
-
-    O << Indent2 << "if (ret || (";
-    if (PropName == "and") {
-      O << '(';
-      for (unsigned j = 0, NumArgs = Prop.getNumArgs(); j < NumArgs; ++j) {
-        const DagInit& InnerProp = dynamic_cast<DagInit&>(*Prop.getArg(j));
-        const std::string& InnerPropName =
-          InnerProp.getOperator()->getAsString();
-        EmitEdgePropertyTest(InnerPropName, InnerProp, OptDescs, O);
-        if (j != NumArgs - 1)
-          O << ")\n" << Indent3 << " && (";
-        else
-          O << ')';
-      }
+    O << Indent2 << "if (";
+
+    if (PropName == "weight") {
+      checkNumberOfArguments(&Prop, 2);
+      N = InitPtrToInt(Prop.getArg(0));
+      const DagInit& InnerProp = InitPtrToDagInitRef(Prop.getArg(1));
+      EmitEdgePropertyTest(InnerProp, OptDescs, O);
     }
     else {
-      EmitEdgePropertyTest(PropName, Prop, OptDescs, O);
+      EmitEdgePropertyTest(Prop, OptDescs, O);
     }
-    O << "))\n" << Indent3 << "ret = true;\n";
+
+    O << ")\n" << Indent3 << "ret += " << N << ";\n";
   }
 
   O << Indent2 << "return ret;\n"
-    << Indent1 << "};\n\n"
-
-  // Function isDefault().
-    << Indent1 << "bool isDefault() const { return ";
-  if (IsDefault)
-    O << "true";
-  else
-    O << "false";
-  O <<"; }\n};\n\n";
+    << Indent1 << "};\n\n};\n\n";
 }
 
 // Emit Edge* classes that represent graph edges.
@@ -1034,6 +1108,8 @@ void EmitEdgeClasses (Record* CompilationGraph,
   }
 }
 
+/// EmitPopulateCompilationGraph - Emit the PopulateCompilationGraph()
+/// function.
 void EmitPopulateCompilationGraph (Record* CompilationGraph,
                                    std::ostream& O)
 {
@@ -1082,29 +1158,30 @@ void EmitPopulateCompilationGraph (Record* CompilationGraph,
 // End of anonymous namespace
 }
 
-// Back-end entry point
+/// run - The back-end entry point.
 void LLVMCConfigurationEmitter::run (std::ostream &O) {
-  // Emit file header
+
+  // Emit file header.
   EmitSourceFileHeader("LLVMC Configuration Library", O);
 
-  // Get a list of all defined Tools
+  // Get a list of all defined Tools.
   RecordVector Tools = Records.getAllDerivedDefinitions("Tool");
   if (Tools.empty())
     throw std::string("No tool definitions found!");
 
-  // Gather information from the Tool descriptions
+  // Gather information from the Tool description dags.
   ToolPropertiesList tool_props;
   GlobalOptionDescriptions opt_descs;
   CollectToolProperties(Tools.begin(), Tools.end(), tool_props, opt_descs);
 
-  // Emit global option registration code
+  // Emit global option registration code.
   EmitOptionDescriptions(opt_descs, O);
 
-  // Emit PopulateLanguageMap function
-  // (a language map maps from file extensions to language names)
+  // Emit PopulateLanguageMap() function
+  // (a language map maps from file extensions to language names).
   EmitPopulateLanguageMap(Records, O);
 
-  // Emit Tool classes
+  // Emit Tool classes.
   for (ToolPropertiesList::const_iterator B = tool_props.begin(),
          E = tool_props.end(); B!=E; ++B)
     EmitToolClassDefinition(*(*B), O);
@@ -1116,10 +1193,10 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) {
   // Typecheck the compilation graph.
   TypecheckGraph(CompilationGraphRecord, tool_props);
 
-  // Emit Edge* classes.
+  // Emit Edge# classes.
   EmitEdgeClasses(CompilationGraphRecord, opt_descs, O);
 
-  // Emit PopulateCompilationGraph function
+  // Emit PopulateCompilationGraph() function.
   EmitPopulateCompilationGraph(CompilationGraphRecord, O);
 
   // EOF