//===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config ----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open
// Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting LLVMC configuration code.
//
//===----------------------------------------------------------------------===//

#include "LLVMCConfigurationEmitter.h"
#include "Record.h"

#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include <algorithm>
#include <cassert>
#include <functional>
#include <stdexcept>
#include <string>
#include <typeinfo>

using namespace llvm;

namespace {

//===----------------------------------------------------------------------===//
/// Typedefs

typedef std::vector<Record*> RecordVector;
typedef std::vector<std::string> StrVector;

//===----------------------------------------------------------------------===//
/// Constants

// Indentation strings.
const char * Indent1 = "    ";
const char * Indent2 = "        ";
const char * Indent3 = "            ";

// Default help string.
const char * DefaultHelpString = "NO HELP MESSAGE PROVIDED";

// Name for the "sink" option.
const char * SinkOptionName = "AutoGeneratedSinkOption";

//===----------------------------------------------------------------------===//
/// Helper functions

/// Id - An 'identity' function object.
struct Id {
  template<typename T>
  void operator()(const T&) const {
  }
};

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();
}

const ListInit& InitPtrToList(const Init* ptr) {
  const ListInit& val = dynamic_cast<const ListInit&>(*ptr);
  return val;
}

const DagInit& InitPtrToDag(const Init* ptr) {
  const DagInit& val = dynamic_cast<const DagInit&>(*ptr);
  return val;
}

// checkNumberOfArguments - Ensure that the number of args in d is
// greater than or equal to min_arguments, otherwise throw an exception.
void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) {
  if (!d || d->getNumArgs() < min_arguments)
    throw d->getOperator()->getAsString() + ": too few arguments!";
}

// isDagEmpty - is this DAG marked with an empty marker?
bool isDagEmpty (const DagInit* d) {
  return d->getOperator()->getAsString() == "empty";
}

// EscapeVariableName - Escape commas and other symbols not allowed
// in the C++ variable names. Makes it possible to use options named
// like "Wa," (useful for prefix options).
std::string EscapeVariableName(const std::string& Var) {
  std::string ret;
  for (unsigned i = 0; i != Var.size(); ++i) {
    char cur_char = Var[i];
    if (cur_char == ',') {
      ret += "_comma_";
    }
    else if (cur_char == '+') {
      ret += "_plus_";
    }
    else if (cur_char == '-') {
      ret += "_dash_";
    }
    else {
      ret.push_back(cur_char);
    }
  }
  return ret;
}

/// oneOf - Does the input string contain this character?
bool oneOf(const char* lst, char c) {
  while (*lst) {
    if (*lst++ == c)
      return true;
  }
  return false;
}

template <class I, class S>
void checkedIncrement(I& P, I E, S ErrorString) {
  ++P;
  if (P == E)
    throw ErrorString;
}

//===----------------------------------------------------------------------===//
/// Back-end specific code


/// OptionType - One of six different option types. See the
/// documentation for detailed description of differences.
namespace OptionType {

  enum OptionType { Alias, Switch, Parameter, ParameterList,
                    Prefix, PrefixList};

  bool IsList (OptionType t) {
    return (t == ParameterList || t == PrefixList);
  }

  bool IsSwitch (OptionType t) {
    return (t == Switch);
  }

  bool IsParameter (OptionType t) {
    return (t == Parameter || t == Prefix);
  }

}

OptionType::OptionType stringToOptionType(const std::string& T) {
  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 + '!';
}

namespace OptionDescriptionFlags {
  enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
                                ReallyHidden = 0x4, Extern = 0x8,
                                OneOrMore = 0x10, ZeroOrOne = 0x20 };
}

/// OptionDescription - Represents data contained in a single
/// OptionList entry.
struct OptionDescription {
  OptionType::OptionType Type;
  std::string Name;
  unsigned Flags;
  std::string Help;
  unsigned MultiVal;
  Init* InitVal;

  OptionDescription(OptionType::OptionType t = OptionType::Switch,
                    const std::string& n = "",
                    const std::string& h = DefaultHelpString)
    : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1), InitVal(0)
  {}

  /// GenTypeDeclaration - Returns the C++ variable type of this
  /// option.
  const char* GenTypeDeclaration() const;

  /// GenVariableName - Returns the variable name used in the
  /// generated C++ code.
  std::string GenVariableName() const;

  /// Merge - Merge two option descriptions.
  void Merge (const OptionDescription& other);

  // Misc convenient getters/setters.

  bool isAlias() const;

  bool isMultiVal() const;

  bool isExtern() const;
  void setExtern();

  bool isRequired() const;
  void setRequired();

  bool isOneOrMore() const;
  void setOneOrMore();

  bool isZeroOrOne() const;
  void setZeroOrOne();

  bool isHidden() const;
  void setHidden();

  bool isReallyHidden() const;
  void setReallyHidden();

  bool isParameter() const
  { return OptionType::IsParameter(this->Type); }

  bool isSwitch() const
  { return OptionType::IsSwitch(this->Type); }

  bool isList() const
  { return OptionType::IsList(this->Type); }

};

void OptionDescription::Merge (const OptionDescription& other)
{
  if (other.Type != Type)
    throw "Conflicting definitions for the option " + Name + "!";

  if (Help == other.Help || Help == DefaultHelpString)
    Help = other.Help;
  else if (other.Help != DefaultHelpString) {
    llvm::errs() << "Warning: several different help strings"
      " defined for option " + Name + "\n";
  }

  Flags |= other.Flags;
}

bool OptionDescription::isAlias() const {
  return Type == OptionType::Alias;
}

bool OptionDescription::isMultiVal() const {
  return MultiVal > 1;
}

bool OptionDescription::isExtern() const {
  return Flags & OptionDescriptionFlags::Extern;
}
void OptionDescription::setExtern() {
  Flags |= OptionDescriptionFlags::Extern;
}

bool OptionDescription::isRequired() const {
  return Flags & OptionDescriptionFlags::Required;
}
void OptionDescription::setRequired() {
  Flags |= OptionDescriptionFlags::Required;
}

bool OptionDescription::isOneOrMore() const {
  return Flags & OptionDescriptionFlags::OneOrMore;
}
void OptionDescription::setOneOrMore() {
  Flags |= OptionDescriptionFlags::OneOrMore;
}

bool OptionDescription::isZeroOrOne() const {
  return Flags & OptionDescriptionFlags::ZeroOrOne;
}
void OptionDescription::setZeroOrOne() {
  Flags |= OptionDescriptionFlags::ZeroOrOne;
}

bool OptionDescription::isHidden() const {
  return Flags & OptionDescriptionFlags::Hidden;
}
void OptionDescription::setHidden() {
  Flags |= OptionDescriptionFlags::Hidden;
}

bool OptionDescription::isReallyHidden() const {
  return Flags & OptionDescriptionFlags::ReallyHidden;
}
void OptionDescription::setReallyHidden() {
  Flags |= OptionDescriptionFlags::ReallyHidden;
}

const char* OptionDescription::GenTypeDeclaration() const {
  switch (Type) {
  case OptionType::Alias:
    return "cl::alias";
  case OptionType::PrefixList:
  case OptionType::ParameterList:
    return "cl::list<std::string>";
  case OptionType::Switch:
    return "cl::opt<bool>";
  case OptionType::Parameter:
  case OptionType::Prefix:
  default:
    return "cl::opt<std::string>";
  }
}

std::string OptionDescription::GenVariableName() const {
  const std::string& EscapedName = EscapeVariableName(Name);
  switch (Type) {
  case OptionType::Alias:
    return "AutoGeneratedAlias_" + EscapedName;
  case OptionType::PrefixList:
  case OptionType::ParameterList:
    return "AutoGeneratedList_" + EscapedName;
  case OptionType::Switch:
    return "AutoGeneratedSwitch_" + EscapedName;
  case OptionType::Prefix:
  case OptionType::Parameter:
  default:
    return "AutoGeneratedParameter_" + EscapedName;
  }
}

/// OptionDescriptions - An OptionDescription array plus some helper
/// functions.
class OptionDescriptions {
  typedef StringMap<OptionDescription> container_type;

  /// Descriptions - A list of OptionDescriptions.
  container_type Descriptions;

public:
  /// FindOption - exception-throwing wrapper for find().
  const OptionDescription& FindOption(const std::string& OptName) const;

  /// insertDescription - Insert new OptionDescription into
  /// OptionDescriptions list
  void InsertDescription (const OptionDescription& o);

  // Support for STL-style iteration
  typedef container_type::const_iterator const_iterator;
  const_iterator begin() const { return Descriptions.begin(); }
  const_iterator end() const { return Descriptions.end(); }
};

const OptionDescription&
OptionDescriptions::FindOption(const std::string& OptName) const
{
  const_iterator I = Descriptions.find(OptName);
  if (I != Descriptions.end())
    return I->second;
  else
    throw OptName + ": no such option!";
}

void OptionDescriptions::InsertDescription (const OptionDescription& o)
{
  container_type::iterator I = Descriptions.find(o.Name);
  if (I != Descriptions.end()) {
    OptionDescription& D = I->second;
    D.Merge(o);
  }
  else {
    Descriptions[o.Name] = o;
  }
}

/// HandlerTable - A base class for function objects implemented as
/// 'tables of handlers'.
template <class T>
class HandlerTable {
protected:
  // Implementation details.

  /// Handler -
  typedef void (T::* Handler) (const DagInit*);
  /// HandlerMap - A map from property names to property handlers
  typedef StringMap<Handler> HandlerMap;

  static HandlerMap Handlers_;
  static bool staticMembersInitialized_;

  T* childPtr;
public:

  HandlerTable(T* cp) : childPtr(cp)
  {}

  /// operator() - Just forwards to the corresponding property
  /// handler.
  void operator() (Init* i) {
    const DagInit& property = InitPtrToDag(i);
    const std::string& property_name = property.getOperator()->getAsString();
    typename HandlerMap::iterator method = Handlers_.find(property_name);

    if (method != Handlers_.end()) {
      Handler h = method->second;
      (childPtr->*h)(&property);
    }
    else {
      throw "No handler found for property " + property_name + "!";
    }
  }

  void AddHandler(const char* Property, Handler Handl) {
    Handlers_[Property] = Handl;
  }
};

template <class T> typename HandlerTable<T>::HandlerMap
HandlerTable<T>::Handlers_;
template <class T> bool HandlerTable<T>::staticMembersInitialized_ = false;


/// CollectOptionProperties - Function object for iterating over an
/// option property list.
class CollectOptionProperties : public HandlerTable<CollectOptionProperties> {
private:

  /// optDescs_ - OptionDescriptions table. This is where the
  /// information is stored.
  OptionDescription& optDesc_;

public:

  explicit CollectOptionProperties(OptionDescription& OD)
    : HandlerTable<CollectOptionProperties>(this), optDesc_(OD)
  {
    if (!staticMembersInitialized_) {
      AddHandler("extern", &CollectOptionProperties::onExtern);
      AddHandler("help", &CollectOptionProperties::onHelp);
      AddHandler("hidden", &CollectOptionProperties::onHidden);
      AddHandler("init", &CollectOptionProperties::onInit);
      AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
      AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
      AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
      AddHandler("required", &CollectOptionProperties::onRequired);
      AddHandler("zero_or_one", &CollectOptionProperties::onZeroOrOne);

      staticMembersInitialized_ = true;
    }
  }

private:

  /// Option property handlers --
  /// Methods that handle option properties such as (help) or (hidden).

  void onExtern (const DagInit* d) {
    checkNumberOfArguments(d, 0);
    optDesc_.setExtern();
  }

  void onHelp (const DagInit* d) {
    checkNumberOfArguments(d, 1);
    optDesc_.Help = InitPtrToString(d->getArg(0));
  }

  void onHidden (const DagInit* d) {
    checkNumberOfArguments(d, 0);
    optDesc_.setHidden();
  }

  void onReallyHidden (const DagInit* d) {
    checkNumberOfArguments(d, 0);
    optDesc_.setReallyHidden();
  }

  void onRequired (const DagInit* d) {
    checkNumberOfArguments(d, 0);
    if (optDesc_.isOneOrMore())
      throw std::string("An option can't have both (required) "
                        "and (one_or_more) properties!");
    optDesc_.setRequired();
  }

  void onInit (const DagInit* d) {
    checkNumberOfArguments(d, 1);
    Init* i = d->getArg(0);
    const std::string& str = i->getAsString();

    bool correct = optDesc_.isParameter() && dynamic_cast<StringInit*>(i);
    correct |= (optDesc_.isSwitch() && (str == "true" || str == "false"));

    if (!correct)
      throw std::string("Incorrect usage of the 'init' option property!");

    optDesc_.InitVal = i;
  }

  void onOneOrMore (const DagInit* d) {
    checkNumberOfArguments(d, 0);
    if (optDesc_.isRequired() || optDesc_.isZeroOrOne())
      throw std::string("Only one of (required), (zero_or_one) or "
                        "(one_or_more) properties is allowed!");
    if (!OptionType::IsList(optDesc_.Type))
      llvm::errs() << "Warning: specifying the 'one_or_more' property "
        "on a non-list option will have no effect.\n";
    optDesc_.setOneOrMore();
  }

  void onZeroOrOne (const DagInit* d) {
    checkNumberOfArguments(d, 0);
    if (optDesc_.isRequired() || optDesc_.isOneOrMore())
      throw std::string("Only one of (required), (zero_or_one) or "
                        "(one_or_more) properties is allowed!");
    if (!OptionType::IsList(optDesc_.Type))
      llvm::errs() << "Warning: specifying the 'zero_or_one' property"
        "on a non-list option will have no effect.\n";
    optDesc_.setZeroOrOne();
  }

  void onMultiVal (const DagInit* d) {
    checkNumberOfArguments(d, 1);
    int val = InitPtrToInt(d->getArg(0));
    if (val < 2)
      throw std::string("Error in the 'multi_val' property: "
                        "the value must be greater than 1!");
    if (!OptionType::IsList(optDesc_.Type))
      throw std::string("The multi_val property is valid only "
                        "on list options!");
    optDesc_.MultiVal = val;
  }

};

/// AddOption - A function object that is applied to every option
/// description. Used by CollectOptionDescriptions.
class AddOption {
private:
  OptionDescriptions& OptDescs_;

public:
  explicit AddOption(OptionDescriptions& OD) : OptDescs_(OD)
  {}

  void operator()(const Init* i) {
    const DagInit& d = InitPtrToDag(i);
    checkNumberOfArguments(&d, 1);

    const OptionType::OptionType Type =
      stringToOptionType(d.getOperator()->getAsString());
    const std::string& Name = InitPtrToString(d.getArg(0));

    OptionDescription OD(Type, Name);

    if (!OD.isExtern())
      checkNumberOfArguments(&d, 2);

    if (OD.isAlias()) {
      // Aliases store the aliased option name in the 'Help' field.
      OD.Help = InitPtrToString(d.getArg(1));
    }
    else if (!OD.isExtern()) {
      processOptionProperties(&d, OD);
    }
    OptDescs_.InsertDescription(OD);
  }

private:
  /// processOptionProperties - Go through the list of option
  /// properties and call a corresponding handler for each.
  static void processOptionProperties (const DagInit* d, OptionDescription& 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(o));
  }

};

/// CollectOptionDescriptions - Collects option properties from all
/// OptionLists.
void CollectOptionDescriptions (RecordVector::const_iterator B,
                                RecordVector::const_iterator E,
                                OptionDescriptions& OptDescs)
{
  // For every OptionList:
  for (; B!=E; ++B) {
    RecordVector::value_type T = *B;
    // Throws an exception if the value does not exist.
    ListInit* PropList = T->getValueAsListInit("options");

    // For every option description in this list:
    // collect the information and
    std::for_each(PropList->begin(), PropList->end(), AddOption(OptDescs));
  }
}

// Tool information record

namespace ToolFlags {
  enum ToolFlags { Join = 0x1, Sink = 0x2 };
}

struct ToolDescription : public RefCountedBase<ToolDescription> {
  std::string Name;
  Init* CmdLine;
  Init* Actions;
  StrVector InLanguage;
  std::string OutLanguage;
  std::string OutputSuffix;
  unsigned Flags;

  // Various boolean properties
  void setSink()      { Flags |= ToolFlags::Sink; }
  bool isSink() const { return Flags & ToolFlags::Sink; }
  void setJoin()      { Flags |= ToolFlags::Join; }
  bool isJoin() const { return Flags & ToolFlags::Join; }

  // Default ctor here is needed because StringMap can only store
  // DefaultConstructible objects
  ToolDescription() : CmdLine(0), Actions(0), Flags(0) {}
  ToolDescription (const std::string& n)
  : Name(n), CmdLine(0), Actions(0), Flags(0)
  {}
};

/// ToolDescriptions - A list of Tool information records.
typedef std::vector<IntrusiveRefCntPtr<ToolDescription> > ToolDescriptions;


/// CollectToolProperties - Function object for iterating over a list of
/// tool property records.
class CollectToolProperties : public HandlerTable<CollectToolProperties> {
private:

  /// toolDesc_ - Properties of the current Tool. This is where the
  /// information is stored.
  ToolDescription& toolDesc_;

public:

  explicit CollectToolProperties (ToolDescription& d)
    : HandlerTable<CollectToolProperties>(this) , toolDesc_(d)
  {
    if (!staticMembersInitialized_) {

      AddHandler("actions", &CollectToolProperties::onActions);
      AddHandler("cmd_line", &CollectToolProperties::onCmdLine);
      AddHandler("in_language", &CollectToolProperties::onInLanguage);
      AddHandler("join", &CollectToolProperties::onJoin);
      AddHandler("out_language", &CollectToolProperties::onOutLanguage);
      AddHandler("output_suffix", &CollectToolProperties::onOutputSuffix);
      AddHandler("sink", &CollectToolProperties::onSink);

      staticMembersInitialized_ = true;
    }
  }

private:

  /// Property handlers --
  /// Functions that extract information about tool properties from
  /// DAG representation.

  void onActions (const DagInit* d) {
    checkNumberOfArguments(d, 1);
    Init* Case = d->getArg(0);
    if (typeid(*Case) != typeid(DagInit) ||
        static_cast<DagInit*>(Case)->getOperator()->getAsString() != "case")
      throw
        std::string("The argument to (actions) should be a 'case' construct!");
    toolDesc_.Actions = Case;
  }

  void onCmdLine (const DagInit* d) {
    checkNumberOfArguments(d, 1);
    toolDesc_.CmdLine = d->getArg(0);
  }

  void onInLanguage (const DagInit* d) {
    checkNumberOfArguments(d, 1);
    Init* arg = d->getArg(0);

    // Find out the argument's type.
    if (typeid(*arg) == typeid(StringInit)) {
      // It's a string.
      toolDesc_.InLanguage.push_back(InitPtrToString(arg));
    }
    else {
      // It's a list.
      const ListInit& lst = InitPtrToList(arg);
      StrVector& out = toolDesc_.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) {
    checkNumberOfArguments(d, 0);
    toolDesc_.setJoin();
  }

  void onOutLanguage (const DagInit* d) {
    checkNumberOfArguments(d, 1);
    toolDesc_.OutLanguage = InitPtrToString(d->getArg(0));
  }

  void onOutputSuffix (const DagInit* d) {
    checkNumberOfArguments(d, 1);
    toolDesc_.OutputSuffix = InitPtrToString(d->getArg(0));
  }

  void onSink (const DagInit* d) {
    checkNumberOfArguments(d, 0);
    toolDesc_.setSink();
  }

};

/// CollectToolDescriptions - Gather information about tool properties
/// from the parsed TableGen data (basically a wrapper for the
/// CollectToolProperties function object).
void CollectToolDescriptions (RecordVector::const_iterator B,
                              RecordVector::const_iterator E,
                              ToolDescriptions& ToolDescs)
{
  // Iterate over a properties list of every Tool definition
  for (;B!=E;++B) {
    const Record* T = *B;
    // Throws an exception if the value does not exist.
    ListInit* PropList = T->getValueAsListInit("properties");

    IntrusiveRefCntPtr<ToolDescription>
      ToolDesc(new ToolDescription(T->getName()));

    std::for_each(PropList->begin(), PropList->end(),
                  CollectToolProperties(*ToolDesc));
    ToolDescs.push_back(ToolDesc);
  }
}

/// FillInEdgeVector - Merge all compilation graph definitions into
/// one single edge list.
void FillInEdgeVector(RecordVector::const_iterator B,
                      RecordVector::const_iterator E, RecordVector& Out) {
  for (; B != E; ++B) {
    const ListInit* edges = (*B)->getValueAsListInit("edges");

    for (unsigned i = 0; i < edges->size(); ++i)
      Out.push_back(edges->getElementAsRecord(i));
  }
}

/// CalculatePriority - Calculate the priority of this plugin.
int CalculatePriority(RecordVector::const_iterator B,
                      RecordVector::const_iterator E) {
  int total = 0;
  for (; B!=E; ++B) {
    total += static_cast<int>((*B)->getValueAsInt("priority"));
  }
  return total;
}

/// NotInGraph - Helper function object for FilterNotInGraph.
struct NotInGraph {
private:
  const llvm::StringSet<>& ToolsInGraph_;

public:
  NotInGraph(const llvm::StringSet<>& ToolsInGraph)
  : ToolsInGraph_(ToolsInGraph)
  {}

  bool operator()(const IntrusiveRefCntPtr<ToolDescription>& x) {
    return (ToolsInGraph_.count(x->Name) == 0);
  }
};

/// FilterNotInGraph - Filter out from ToolDescs all Tools not
/// mentioned in the compilation graph definition.
void FilterNotInGraph (const RecordVector& EdgeVector,
                       ToolDescriptions& ToolDescs) {

  // List all tools mentioned in the graph.
  llvm::StringSet<> ToolsInGraph;

  for (RecordVector::const_iterator B = EdgeVector.begin(),
         E = EdgeVector.end(); B != E; ++B) {

    const Record* Edge = *B;
    const std::string& NodeA = Edge->getValueAsString("a");
    const std::string& NodeB = Edge->getValueAsString("b");

    if (NodeA != "root")
      ToolsInGraph.insert(NodeA);
    ToolsInGraph.insert(NodeB);
  }

  // Filter ToolPropertiesList.
  ToolDescriptions::iterator new_end =
    std::remove_if(ToolDescs.begin(), ToolDescs.end(),
                   NotInGraph(ToolsInGraph));
  ToolDescs.erase(new_end, ToolDescs.end());
}

/// FillInToolToLang - Fills in two tables that map tool names to
/// (input, output) languages.  Helper function used by TypecheckGraph().
void FillInToolToLang (const ToolDescriptions& ToolDescs,
                       StringMap<StringSet<> >& ToolToInLang,
                       StringMap<std::string>& ToolToOutLang) {
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
         E = ToolDescs.end(); B != E; ++B) {
    const ToolDescription& D = *(*B);
    for (StrVector::const_iterator B = D.InLanguage.begin(),
           E = D.InLanguage.end(); B != E; ++B)
      ToolToInLang[D.Name].insert(*B);
    ToolToOutLang[D.Name] = D.OutLanguage;
  }
}

/// TypecheckGraph - Check that names for output and input languages
/// on all edges do match. This doesn't do much when the information
/// about the whole graph is not available (i.e. when compiling most
/// plugins).
void TypecheckGraph (const RecordVector& EdgeVector,
                     const ToolDescriptions& ToolDescs) {
  StringMap<StringSet<> > ToolToInLang;
  StringMap<std::string> ToolToOutLang;

  FillInToolToLang(ToolDescs, ToolToInLang, ToolToOutLang);
  StringMap<std::string>::iterator IAE = ToolToOutLang.end();
  StringMap<StringSet<> >::iterator IBE = ToolToInLang.end();

  for (RecordVector::const_iterator B = EdgeVector.begin(),
         E = EdgeVector.end(); B != E; ++B) {
    const Record* Edge = *B;
    const std::string& NodeA = Edge->getValueAsString("a");
    const std::string& NodeB = Edge->getValueAsString("b");
    StringMap<std::string>::iterator IA = ToolToOutLang.find(NodeA);
    StringMap<StringSet<> >::iterator IB = ToolToInLang.find(NodeB);

    if (NodeA != "root") {
      if (IA != IAE && IB != IBE && IB->second.count(IA->second) == 0)
        throw "Edge " + NodeA + "->" + NodeB
          + ": output->input language mismatch";
    }

    if (NodeB == "root")
      throw std::string("Edges back to the root are not allowed!");
  }
}

/// WalkCase - Walks the 'case' expression DAG and invokes
/// TestCallback on every test, and StatementCallback on every
/// statement. Handles 'case' nesting, but not the 'and' and 'or'
/// combinators.
// TODO: Re-implement EmitCaseConstructHandler on top of this function?
template <typename F1, typename F2>
void WalkCase(Init* Case, F1 TestCallback, F2 StatementCallback) {
  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")
      WalkCase(arg, TestCallback, StatementCallback);
    else if (!even)
      TestCallback(arg);
    else
      StatementCallback(arg);
    even = !even;
  }
}

/// ExtractOptionNames - A helper function object used by
/// CheckForSuperfluousOptions() to walk the 'case' DAG.
class ExtractOptionNames {
  llvm::StringSet<>& OptionNames_;

  void processDag(const Init* Statement) {
    const DagInit& Stmt = InitPtrToDag(Statement);
    const std::string& ActionName = Stmt.getOperator()->getAsString();
    if (ActionName == "forward" || ActionName == "forward_as" ||
        ActionName == "unpack_values" || ActionName == "switch_on" ||
        ActionName == "parameter_equals" || ActionName == "element_in_list" ||
        ActionName == "not_empty" || ActionName == "empty") {
      checkNumberOfArguments(&Stmt, 1);
      const std::string& Name = InitPtrToString(Stmt.getArg(0));
      OptionNames_.insert(Name);
    }
    else if (ActionName == "and" || ActionName == "or") {
      for (unsigned i = 0, NumArgs = Stmt.getNumArgs(); i < NumArgs; ++i) {
        this->processDag(Stmt.getArg(i));
      }
    }
  }

public:
  ExtractOptionNames(llvm::StringSet<>& OptionNames) : OptionNames_(OptionNames)
  {}

  void operator()(const Init* Statement) {
    if (typeid(*Statement) == typeid(ListInit)) {
      const ListInit& DagList = *static_cast<const ListInit*>(Statement);
      for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
           B != E; ++B)
        this->processDag(*B);
    }
    else {
      this->processDag(Statement);
    }
  }
};

/// CheckForSuperfluousOptions - Check that there are no side
/// effect-free options (specified only in the OptionList). Otherwise,
/// output a warning.
void CheckForSuperfluousOptions (const RecordVector& Edges,
                                 const ToolDescriptions& ToolDescs,
                                 const OptionDescriptions& OptDescs) {
  llvm::StringSet<> nonSuperfluousOptions;

  // Add all options mentioned in the ToolDesc.Actions to the set of
  // non-superfluous options.
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
         E = ToolDescs.end(); B != E; ++B) {
    const ToolDescription& TD = *(*B);
    ExtractOptionNames Callback(nonSuperfluousOptions);
    if (TD.Actions)
      WalkCase(TD.Actions, Callback, Callback);
  }

  // Add all options mentioned in the 'case' clauses of the
  // OptionalEdges of the compilation graph to the set of
  // non-superfluous options.
  for (RecordVector::const_iterator B = Edges.begin(), E = Edges.end();
       B != E; ++B) {
    const Record* Edge = *B;
    DagInit* Weight = Edge->getValueAsDag("weight");

    if (!isDagEmpty(Weight))
      WalkCase(Weight, ExtractOptionNames(nonSuperfluousOptions), Id());
  }

  // Check that all options in OptDescs belong to the set of
  // non-superfluous options.
  for (OptionDescriptions::const_iterator B = OptDescs.begin(),
         E = OptDescs.end(); B != E; ++B) {
    const OptionDescription& Val = B->second;
    if (!nonSuperfluousOptions.count(Val.Name)
        && Val.Type != OptionType::Alias)
      llvm::errs() << "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 OptionDescriptions& OptDescs,
                      raw_ostream& O) {
  checkNumberOfArguments(&d, 1);
  const std::string& OptName = InitPtrToString(d.getArg(0));

  if (TestName == "switch_on") {
    const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
    if (!OptDesc.isSwitch())
      throw OptName + ": incorrect option type - should be a switch!";
    O << OptDesc.GenVariableName();
    return true;
  } else if (TestName == "input_languages_contain") {
    O << "InLangs.count(\"" << OptName << "\") != 0";
    return true;
  } else if (TestName == "in_language") {
    // 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" || TestName == "empty") {
    const char* Test = (TestName == "empty") ? "" : "!";

    if (OptName == "o") {
      O << Test << "OutputFilename.empty()";
      return true;
    }
    else {
      const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
      if (OptDesc.isSwitch())
        throw OptName
          + ": incorrect option type - should be a list or parameter!";
      O << Test << OptDesc.GenVariableName() << ".empty()";
      return true;
    }
  }

  return false;
}

/// EmitCaseTest2Args - Helper function used by
/// EmitCaseConstructHandler.
bool EmitCaseTest2Args(const std::string& TestName,
                       const DagInit& d,
                       const char* IndentLevel,
                       const OptionDescriptions& OptDescs,
                       raw_ostream& O) {
  checkNumberOfArguments(&d, 2);
  const std::string& OptName = InitPtrToString(d.getArg(0));
  const std::string& OptArg = InitPtrToString(d.getArg(1));
  const OptionDescription& OptDesc = OptDescs.FindOption(OptName);

  if (TestName == "parameter_equals") {
    if (!OptDesc.isParameter())
      throw OptName + ": incorrect option type - should be a parameter!";
    O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
    return true;
  }
  else if (TestName == "element_in_list") {
    if (!OptDesc.isList())
      throw OptName + ": incorrect option type - should be a list!";
    const std::string& VarName = OptDesc.GenVariableName();
    O << "std::find(" << VarName << ".begin(),\n"
      << IndentLevel << Indent1 << VarName << ".end(), \""
      << OptArg << "\") != " << VarName << ".end()";
    return true;
  }

  return false;
}

// Forward declaration.
// EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
void EmitCaseTest(const DagInit& d, const char* IndentLevel,
                  const OptionDescriptions& OptDescs,
                  raw_ostream& O);

/// EmitLogicalOperationTest - Helper function used by
/// EmitCaseConstructHandler.
void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp,
                              const char* IndentLevel,
                              const OptionDescriptions& OptDescs,
                              raw_ostream& O) {
  O << '(';
  for (unsigned j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) {
    const DagInit& InnerTest = InitPtrToDag(d.getArg(j));
    EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
    if (j != NumArgs - 1)
      O << ")\n" << IndentLevel << Indent1 << ' ' << LogicOp << " (";
    else
      O << ')';
  }
}

/// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
void EmitCaseTest(const DagInit& d, const char* IndentLevel,
                  const OptionDescriptions& OptDescs,
                  raw_ostream& O) {
  const std::string& TestName = d.getOperator()->getAsString();

  if (TestName == "and")
    EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);
  else if (TestName == "or")
    EmitLogicalOperationTest(d, "||", IndentLevel, OptDescs, O);
  else if (EmitCaseTest1Arg(TestName, d, OptDescs, O))
    return;
  else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O))
    return;
  else
    throw TestName + ": unknown edge property!";
}

// Emit code that handles the 'case' construct.
// Takes a function object that should emit code for every case clause.
// Callback's type is
// void F(Init* Statement, const char* IndentLevel, raw_ostream& O).
template <typename F>
void EmitCaseConstructHandler(const Init* Dag, const char* IndentLevel,
                              F Callback, bool EmitElseIf,
                              const OptionDescriptions& OptDescs,
                              raw_ostream& O) {
  const DagInit* d = &InitPtrToDag(Dag);
  if (d->getOperator()->getAsString() != "case")
    throw std::string("EmitCaseConstructHandler should be invoked"
                      " only on 'case' expressions!");

  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 = InitPtrToDag(d->getArg(i));

    // Emit the test.
    if (Test.getOperator()->getAsString() == "default") {
      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 << ((i != 0 && EmitElseIf) ? "else if (" : "if (");
      EmitCaseTest(Test, IndentLevel, OptDescs, O);
      O << ") {\n";
    }

    // Emit the corresponding statement.
    ++i;
    if (i == numArgs)
      throw "Case construct handler: no corresponding action "
        "found for the test " + Test.getAsString() + '!';

    Init* arg = d->getArg(i);
    const DagInit* nd = dynamic_cast<DagInit*>(arg);
    if (nd && (nd->getOperator()->getAsString() == "case")) {
      // Handle the nested 'case'.
      EmitCaseConstructHandler(nd, (std::string(IndentLevel) + Indent1).c_str(),
                               Callback, EmitElseIf, OptDescs, O);
    }
    else {
      Callback(arg, (std::string(IndentLevel) + Indent1).c_str(), O);
    }
    O << IndentLevel << "}\n";
  }
}

/// TokenizeCmdline - converts from "$CALL(HookName, 'Arg1', 'Arg2')/path" to
/// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path"] .
/// Helper function used by EmitCmdLineVecFill and.
void TokenizeCmdline(const std::string& CmdLine, StrVector& Out) {
  const char* Delimiters = " \t\n\v\f\r";
  enum TokenizerState
  { Normal, SpecialCommand, InsideSpecialCommand, InsideQuotationMarks }
  cur_st  = Normal;

  if (CmdLine.empty())
    return;
  Out.push_back("");

  std::string::size_type B = CmdLine.find_first_not_of(Delimiters),
    E = CmdLine.size();

  for (; B != E; ++B) {
    char cur_ch = CmdLine[B];

    switch (cur_st) {
    case Normal:
      if (cur_ch == '$') {
        cur_st = SpecialCommand;
        break;
      }
      if (oneOf(Delimiters, cur_ch)) {
        // Skip whitespace
        B = CmdLine.find_first_not_of(Delimiters, B);
        if (B == std::string::npos) {
          B = E-1;
          continue;
        }
        --B;
        Out.push_back("");
        continue;
      }
      break;


    case SpecialCommand:
      if (oneOf(Delimiters, cur_ch)) {
        cur_st = Normal;
        Out.push_back("");
        continue;
      }
      if (cur_ch == '(') {
        Out.push_back("");
        cur_st = InsideSpecialCommand;
        continue;
      }
      break;

    case InsideSpecialCommand:
      if (oneOf(Delimiters, cur_ch)) {
        continue;
      }
      if (cur_ch == '\'') {
        cur_st = InsideQuotationMarks;
        Out.push_back("");
        continue;
      }
      if (cur_ch == ')') {
        cur_st = Normal;
        Out.push_back("");
      }
      if (cur_ch == ',') {
        continue;
      }

      break;

    case InsideQuotationMarks:
      if (cur_ch == '\'') {
        cur_st = InsideSpecialCommand;
        continue;
      }
      break;
    }

    Out.back().push_back(cur_ch);
  }
}

/// SubstituteSpecialCommands - Perform string substitution for $CALL
/// and $ENV. Helper function used by EmitCmdLineVecFill().
StrVector::const_iterator SubstituteSpecialCommands
(StrVector::const_iterator Pos, StrVector::const_iterator End, raw_ostream& O)
{

  const std::string& cmd = *Pos;

  if (cmd == "$CALL") {
    checkedIncrement(Pos, End, "Syntax error in $CALL invocation!");
    const std::string& CmdName = *Pos;

    if (CmdName == ")")
      throw std::string("$CALL invocation: empty argument list!");

    O << "hooks::";
    O << CmdName << "(";


    bool firstIteration = true;
    while (true) {
      checkedIncrement(Pos, End, "Syntax error in $CALL invocation!");
      const std::string& Arg = *Pos;
      assert(Arg.size() != 0);

      if (Arg[0] == ')')
        break;

      if (firstIteration)
        firstIteration = false;
      else
        O << ", ";

      O << '"' << Arg << '"';
    }

    O << ')';

  }
  else if (cmd == "$ENV") {
    checkedIncrement(Pos, End, "Syntax error in $ENV invocation!");
    const std::string& EnvName = *Pos;

    if (EnvName == ")")
      throw "$ENV invocation: empty argument list!";

    O << "checkCString(std::getenv(\"";
    O << EnvName;
    O << "\"))";

    checkedIncrement(Pos, End, "Syntax error in $ENV invocation!");
  }
  else {
    throw "Unknown special command: " + cmd;
  }

  const std::string& Leftover = *Pos;
  assert(Leftover.at(0) == ')');
  if (Leftover.size() != 1)
    O << " + std::string(\"" << (Leftover.c_str() + 1) << "\")";

  return Pos;
}

/// EmitCmdLineVecFill - Emit code that fills in the command line
/// vector. Helper function used by EmitGenerateActionMethod().
void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
                        bool IsJoin, const char* IndentLevel,
                        raw_ostream& O) {
  StrVector StrVec;
  TokenizeCmdline(InitPtrToString(CmdLine), StrVec);

  if (StrVec.empty())
    throw "Tool '" + ToolName + "' has empty command line!";

  StrVector::const_iterator I = StrVec.begin(), E = StrVec.end();

  // If there is a hook invocation on the place of the first command, skip it.
  assert(!StrVec[0].empty());
  if (StrVec[0][0] == '$') {
    while (I != E && (*I)[0] != ')' )
      ++I;

    // Skip the ')' symbol.
    ++I;
  }
  else {
    ++I;
  }

  for (; I != E; ++I) {
    const std::string& cmd = *I;
    assert(!cmd.empty());
    O << IndentLevel;
    if (cmd.at(0) == '$') {
      if (cmd == "$INFILE") {
        if (IsJoin)
          O << "for (PathVector::const_iterator B = inFiles.begin()"
            << ", E = inFiles.end();\n"
            << IndentLevel << "B != E; ++B)\n"
            << IndentLevel << Indent1 << "vec.push_back(B->toString());\n";
        else
          O << "vec.push_back(inFile.toString());\n";
      }
      else if (cmd == "$OUTFILE") {
        O << "vec.push_back(out_file);\n";
      }
      else {
        O << "vec.push_back(";
        I = SubstituteSpecialCommands(I, E, O);
        O << ");\n";
      }
    }
    else {
      O << "vec.push_back(\"" << cmd << "\");\n";
    }
  }
  O << IndentLevel << "cmd = ";

  if (StrVec[0][0] == '$')
    SubstituteSpecialCommands(StrVec.begin(), StrVec.end(), O);
  else
    O << '"' << StrVec[0] << '"';
  O << ";\n";
}

/// EmitCmdLineVecFillCallback - A function object wrapper around
/// EmitCmdLineVecFill(). Used by EmitGenerateActionMethod() as an
/// argument to EmitCaseConstructHandler().
class EmitCmdLineVecFillCallback {
  bool IsJoin;
  const std::string& ToolName;
 public:
  EmitCmdLineVecFillCallback(bool J, const std::string& TN)
    : IsJoin(J), ToolName(TN) {}

  void operator()(const Init* Statement, const char* IndentLevel,
                  raw_ostream& O) const
  {
    EmitCmdLineVecFill(Statement, ToolName, IsJoin,
                       IndentLevel, O);
  }
};

/// EmitForwardOptionPropertyHandlingCode - Helper function used to
/// implement EmitActionHandler. Emits code for
/// handling the (forward) and (forward_as) option properties.
void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
                                            const char* Indent,
                                            const std::string& NewName,
                                            raw_ostream& O) {
  const std::string& Name = NewName.empty()
    ? ("-" + D.Name)
    : NewName;

  switch (D.Type) {
  case OptionType::Switch:
    O << Indent << "vec.push_back(\"" << Name << "\");\n";
    break;
  case OptionType::Parameter:
    O << Indent << "vec.push_back(\"" << Name << "\");\n";
    O << Indent << "vec.push_back(" << D.GenVariableName() << ");\n";
    break;
  case OptionType::Prefix:
    O << Indent << "vec.push_back(\"" << Name << "\" + "
      << D.GenVariableName() << ");\n";
    break;
  case OptionType::PrefixList:
    O << Indent << "for (" << D.GenTypeDeclaration()
      << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
      << Indent << "E = " << D.GenVariableName() << ".end(); B != E;) {\n"
      << Indent << Indent1 << "vec.push_back(\"" << Name << "\" + "
      << "*B);\n"
      << Indent << Indent1 << "++B;\n";

    for (int i = 1, j = D.MultiVal; i < j; ++i) {
      O << Indent << Indent1 << "vec.push_back(*B);\n"
        << Indent << Indent1 << "++B;\n";
    }

    O << Indent << "}\n";
    break;
  case OptionType::ParameterList:
    O << Indent << "for (" << D.GenTypeDeclaration()
      << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
      << Indent << "E = " << D.GenVariableName()
      << ".end() ; B != E;) {\n"
      << Indent << Indent1 << "vec.push_back(\"" << Name << "\");\n";

    for (int i = 0, j = D.MultiVal; i < j; ++i) {
      O << Indent << Indent1 << "vec.push_back(*B);\n"
        << Indent << Indent1 << "++B;\n";
    }

    O << Indent << "}\n";
    break;
  case OptionType::Alias:
  default:
    throw std::string("Aliases are not allowed in tool option descriptions!");
  }
}

/// EmitActionHandler - Emit code that handles actions. Used by
/// EmitGenerateActionMethod() as an argument to
/// EmitCaseConstructHandler().
class EmitActionHandler {
  const OptionDescriptions& OptDescs;

  void processActionDag(const Init* Statement, const char* IndentLevel,
                        raw_ostream& O) const
  {
    const DagInit& Dag = InitPtrToDag(Statement);
    const std::string& ActionName = Dag.getOperator()->getAsString();

    if (ActionName == "append_cmd") {
      checkNumberOfArguments(&Dag, 1);
      const std::string& Cmd = InitPtrToString(Dag.getArg(0));
      StrVector Out;
      llvm::SplitString(Cmd, Out);

      for (StrVector::const_iterator B = Out.begin(), E = Out.end();
           B != E; ++B)
        O << IndentLevel << "vec.push_back(\"" << *B << "\");\n";
    }
    else if (ActionName == "error") {
      O << IndentLevel << "throw std::runtime_error(\"" <<
        (Dag.getNumArgs() >= 1 ? InitPtrToString(Dag.getArg(0))
         : "Unknown error!")
        << "\");\n";
    }
    else if (ActionName == "forward") {
      checkNumberOfArguments(&Dag, 1);
      const std::string& Name = InitPtrToString(Dag.getArg(0));
      EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
                                            IndentLevel, "", O);
    }
    else if (ActionName == "forward_as") {
      checkNumberOfArguments(&Dag, 2);
      const std::string& Name = InitPtrToString(Dag.getArg(0));
      const std::string& NewName = InitPtrToString(Dag.getArg(1));
      EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
                                            IndentLevel, NewName, O);
    }
    else if (ActionName == "output_suffix") {
      checkNumberOfArguments(&Dag, 1);
      const std::string& OutSuf = InitPtrToString(Dag.getArg(0));
      O << IndentLevel << "output_suffix = \"" << OutSuf << "\";\n";
    }
    else if (ActionName == "stop_compilation") {
      O << IndentLevel << "stop_compilation = true;\n";
    }
    else if (ActionName == "unpack_values") {
      checkNumberOfArguments(&Dag, 1);
      const std::string& Name = InitPtrToString(Dag.getArg(0));
      const OptionDescription& D = OptDescs.FindOption(Name);

      if (D.isMultiVal())
        throw std::string("Can't use unpack_values with multi-valued options!");

      if (D.isList()) {
        O << IndentLevel << "for (" << D.GenTypeDeclaration()
          << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
          << IndentLevel << "E = " << D.GenVariableName()
          << ".end(); B != E; ++B)\n"
          << IndentLevel << Indent1 << "llvm::SplitString(*B, vec, \",\");\n";
      }
      else if (D.isParameter()){
        O << Indent3 << "llvm::SplitString("
          << D.GenVariableName() << ", vec, \",\");\n";
      }
      else {
        throw "Option '" + D.Name +
          "': switches can't have the 'unpack_values' property!";
      }
    }
    else {
      throw "Unknown action name: " + ActionName + "!";
    }
  }
 public:
  EmitActionHandler(const OptionDescriptions& OD)
    : OptDescs(OD) {}

  void operator()(const Init* Statement, const char* IndentLevel,
                  raw_ostream& O) const
  {
    if (typeid(*Statement) == typeid(ListInit)) {
      const ListInit& DagList = *static_cast<const ListInit*>(Statement);
      for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
           B != E; ++B)
        this->processActionDag(*B, IndentLevel, O);
    }
    else {
      this->processActionDag(Statement, IndentLevel, O);
    }
  }
};

// EmitGenerateActionMethod - Emit one of two versions of the
// Tool::GenerateAction() method.
void EmitGenerateActionMethod (const ToolDescription& D,
                               const OptionDescriptions& OptDescs,
                               bool IsJoin, raw_ostream& O) {
  if (IsJoin)
    O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n";
  else
    O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n";

  O << Indent2 << "bool HasChildren,\n"
    << Indent2 << "const llvm::sys::Path& TempDir,\n"
    << Indent2 << "const InputLanguagesSet& InLangs,\n"
    << Indent2 << "const LanguageMap& LangMap) const\n"
    << Indent1 << "{\n"
    << Indent2 << "std::string cmd;\n"
    << Indent2 << "std::vector<std::string> vec;\n"
    << Indent2 << "bool stop_compilation = !HasChildren;\n"
    << Indent2 << "const char* output_suffix = \"" << D.OutputSuffix << "\";\n"
    << Indent2 << "std::string out_file;\n\n";

  // For every understood option, emit handling code.
  if (D.Actions)
    EmitCaseConstructHandler(D.Actions, Indent2, EmitActionHandler(OptDescs),
                             false, OptDescs, O);

  O << '\n' << Indent2
    << "out_file = OutFilename(" << (IsJoin ? "sys::Path(),\n" : "inFile,\n")
    << Indent3 << "TempDir, stop_compilation, output_suffix).toString();\n\n";

  // cmd_line is either a string or a 'case' construct.
  if (!D.CmdLine)
    throw "Tool " + D.Name + " has no cmd_line property!";
  else if (typeid(*D.CmdLine) == typeid(StringInit))
    EmitCmdLineVecFill(D.CmdLine, D.Name, IsJoin, Indent2, O);
  else
    EmitCaseConstructHandler(D.CmdLine, Indent2,
                             EmitCmdLineVecFillCallback(IsJoin, D.Name),
                             true, OptDescs, O);

  // Handle the Sink property.
  if (D.isSink()) {
    O << Indent2 << "if (!" << SinkOptionName << ".empty()) {\n"
      << Indent3 << "vec.insert(vec.end(), "
      << SinkOptionName << ".begin(), " << SinkOptionName << ".end());\n"
      << Indent2 << "}\n";
  }

  O << Indent2 << "return Action(cmd, vec, stop_compilation, out_file);\n"
    << Indent1 << "}\n\n";
}

/// EmitGenerateActionMethods - Emit two GenerateAction() methods for
/// a given Tool class.
void EmitGenerateActionMethods (const ToolDescription& ToolDesc,
                                const OptionDescriptions& OptDescs,
                                raw_ostream& O) {
  if (!ToolDesc.isJoin())
    O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"
      << Indent2 << "bool HasChildren,\n"
      << Indent2 << "const llvm::sys::Path& TempDir,\n"
      << Indent2 << "const InputLanguagesSet& InLangs,\n"
      << Indent2 << "const LanguageMap& LangMap) const\n"
      << Indent1 << "{\n"
      << Indent2 << "throw std::runtime_error(\"" << ToolDesc.Name
      << " is not a Join tool!\");\n"
      << Indent1 << "}\n\n";
  else
    EmitGenerateActionMethod(ToolDesc, OptDescs, true, O);

  EmitGenerateActionMethod(ToolDesc, OptDescs, false, O);
}

/// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
/// methods for a given Tool class.
void EmitInOutLanguageMethods (const ToolDescription& D, raw_ostream& O) {
  O << Indent1 << "const char** InputLanguages() const {\n"
    << Indent2 << "return InputLanguages_;\n"
    << Indent1 << "}\n\n";

  if (D.OutLanguage.empty())
    throw "Tool " + D.Name + " has no 'out_language' property!";

  O << Indent1 << "const char* OutputLanguage() const {\n"
    << Indent2 << "return \"" << D.OutLanguage << "\";\n"
    << Indent1 << "}\n\n";
}

/// EmitNameMethod - Emit the Name() method for a given Tool class.
void EmitNameMethod (const ToolDescription& D, raw_ostream& O) {
  O << Indent1 << "const char* Name() const {\n"
    << Indent2 << "return \"" << D.Name << "\";\n"
    << Indent1 << "}\n\n";
}

/// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
/// class.
void EmitIsJoinMethod (const ToolDescription& D, raw_ostream& O) {
  O << Indent1 << "bool IsJoin() const {\n";
  if (D.isJoin())
    O << Indent2 << "return true;\n";
  else
    O << Indent2 << "return false;\n";
  O << Indent1 << "}\n\n";
}

/// EmitStaticMemberDefinitions - Emit static member definitions for a
/// given Tool class.
void EmitStaticMemberDefinitions(const ToolDescription& D, raw_ostream& O) {
  if (D.InLanguage.empty())
    throw "Tool " + D.Name + " has no 'in_language' property!";

  O << "const char* " << D.Name << "::InputLanguages_[] = {";
  for (StrVector::const_iterator B = D.InLanguage.begin(),
         E = D.InLanguage.end(); B != E; ++B)
    O << '\"' << *B << "\", ";
  O << "0};\n\n";
}

/// EmitToolClassDefinition - Emit a Tool class definition.
void EmitToolClassDefinition (const ToolDescription& D,
                              const OptionDescriptions& OptDescs,
                              raw_ostream& O) {
  if (D.Name == "root")
    return;

  // Header
  O << "class " << D.Name << " : public ";
  if (D.isJoin())
    O << "JoinTool";
  else
    O << "Tool";

  O << "{\nprivate:\n"
    << Indent1 << "static const char* InputLanguages_[];\n\n";

  O << "public:\n";
  EmitNameMethod(D, O);
  EmitInOutLanguageMethods(D, O);
  EmitIsJoinMethod(D, O);
  EmitGenerateActionMethods(D, OptDescs, O);

  // Close class definition
  O << "};\n";

  EmitStaticMemberDefinitions(D, O);

}

/// EmitOptionDefinitions - Iterate over a list of option descriptions
/// and emit registration code.
void EmitOptionDefinitions (const OptionDescriptions& descs,
                            bool HasSink, bool HasExterns,
                            raw_ostream& O)
{
  std::vector<OptionDescription> Aliases;

  // Emit static cl::Option variables.
  for (OptionDescriptions::const_iterator B = descs.begin(),
         E = descs.end(); B!=E; ++B) {
    const OptionDescription& val = B->second;

    if (val.Type == OptionType::Alias) {
      Aliases.push_back(val);
      continue;
    }

    if (val.isExtern())
      O << "extern ";

    O << val.GenTypeDeclaration() << ' '
      << val.GenVariableName();

    if (val.isExtern()) {
      O << ";\n";
      continue;
    }

    O << "(\"" << val.Name << "\"\n";

    if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
      O << ", cl::Prefix";

    if (val.isRequired()) {
      if (val.isList() && !val.isMultiVal())
        O << ", cl::OneOrMore";
      else
        O << ", cl::Required";
    }
    else if (val.isOneOrMore() && val.isList()) {
        O << ", cl::OneOrMore";
    }
    else if (val.isZeroOrOne() && val.isList()) {
        O << ", cl::ZeroOrOne";
    }

    if (val.isReallyHidden()) {
      O << ", cl::ReallyHidden";
    }
    else if (val.isHidden()) {
      O << ", cl::Hidden";
    }

    if (val.MultiVal > 1)
      O << ", cl::multi_val(" << val.MultiVal << ')';

    if (val.InitVal) {
      const std::string& str = val.InitVal->getAsString();
      O << ", cl::init(" << str << ')';
    }

    if (!val.Help.empty())
      O << ", cl::desc(\"" << val.Help << "\")";

    O << ");\n\n";
  }

  // Emit the aliases (they should go after all the 'proper' options).
  for (std::vector<OptionDescription>::const_iterator
         B = Aliases.begin(), E = Aliases.end(); B != E; ++B) {
    const OptionDescription& val = *B;

    O << val.GenTypeDeclaration() << ' '
      << val.GenVariableName()
      << "(\"" << val.Name << '\"';

    const OptionDescription& D = descs.FindOption(val.Help);
    O << ", cl::aliasopt(" << D.GenVariableName() << ")";

    O << ", cl::desc(\"" << "An alias for -" + val.Help  << "\"));\n";
  }

  // Emit the sink option.
  if (HasSink)
    O << (HasExterns ? "extern cl" : "cl")
      << "::list<std::string> " << SinkOptionName
      << (HasExterns ? ";\n" : "(cl::Sink);\n");

  O << '\n';
}

/// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function.
void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)
{
  // Generate code
  O << "void PopulateLanguageMapLocal(LanguageMap& langMap) {\n";

  // Get the relevant field out of RecordKeeper
  const Record* LangMapRecord = Records.getDef("LanguageMap");

  // It is allowed for a plugin to have no language map.
  if (LangMapRecord) {

    ListInit* LangsToSuffixesList = LangMapRecord->getValueAsListInit("map");
    if (!LangsToSuffixesList)
      throw std::string("Error in the language map definition!");

    for (unsigned i = 0; i < LangsToSuffixesList->size(); ++i) {
      const Record* LangToSuffixes = LangsToSuffixesList->getElementAsRecord(i);

      const std::string& Lang = LangToSuffixes->getValueAsString("lang");
      const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes");

      for (unsigned i = 0; i < Suffixes->size(); ++i)
        O << Indent1 << "langMap[\""
          << InitPtrToString(Suffixes->getElement(i))
          << "\"] = \"" << Lang << "\";\n";
    }
  }

  O << "}\n\n";
}

/// IncDecWeight - Helper function passed to EmitCaseConstructHandler()
/// by EmitEdgeClass().
void IncDecWeight (const Init* i, const char* IndentLevel,
                   raw_ostream& O) {
  const DagInit& d = InitPtrToDag(i);
  const std::string& OpName = d.getOperator()->getAsString();

  if (OpName == "inc_weight") {
    O << IndentLevel << "ret += ";
  }
  else if (OpName == "dec_weight") {
    O << IndentLevel << "ret -= ";
  }
  else if (OpName == "error") {
    O << IndentLevel << "throw std::runtime_error(\"" <<
        (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0))
         : "Unknown error!")
      << "\");\n";
    return;
  }

  else
    throw "Unknown operator in edge properties list: " + OpName + '!' +
      "\nOnly 'inc_weight', 'dec_weight' and 'error' are allowed.";

  if (d.getNumArgs() > 0)
    O << InitPtrToInt(d.getArg(0)) << ";\n";
  else
    O << "2;\n";

}

/// EmitEdgeClass - Emit a single Edge# class.
void EmitEdgeClass (unsigned N, const std::string& Target,
                    DagInit* Case, const OptionDescriptions& OptDescs,
                    raw_ostream& O) {

  // Class constructor.
  O << "class Edge" << N << ": public Edge {\n"
    << "public:\n"
    << Indent1 << "Edge" << N << "() : Edge(\"" << Target
    << "\") {}\n\n"

  // Function Weight().
    << Indent1 << "unsigned Weight(const InputLanguagesSet& InLangs) const {\n"
    << Indent2 << "unsigned ret = 0;\n";

  // Handle the 'case' construct.
  EmitCaseConstructHandler(Case, Indent2, IncDecWeight, false, OptDescs, O);

  O << Indent2 << "return ret;\n"
    << Indent1 << "};\n\n};\n\n";
}

/// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
void EmitEdgeClasses (const RecordVector& EdgeVector,
                      const OptionDescriptions& OptDescs,
                      raw_ostream& O) {
  int i = 0;
  for (RecordVector::const_iterator B = EdgeVector.begin(),
         E = EdgeVector.end(); B != E; ++B) {
    const Record* Edge = *B;
    const std::string& NodeB = Edge->getValueAsString("b");
    DagInit* Weight = Edge->getValueAsDag("weight");

    if (!isDagEmpty(Weight))
      EmitEdgeClass(i, NodeB, Weight, OptDescs, O);
    ++i;
  }
}

/// EmitPopulateCompilationGraph - Emit the PopulateCompilationGraph()
/// function.
void EmitPopulateCompilationGraph (const RecordVector& EdgeVector,
                                   const ToolDescriptions& ToolDescs,
                                   raw_ostream& O)
{
  O << "void PopulateCompilationGraphLocal(CompilationGraph& G) {\n";

  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
         E = ToolDescs.end(); B != E; ++B)
    O << Indent1 << "G.insertNode(new " << (*B)->Name << "());\n";

  O << '\n';

  // Insert edges.

  int i = 0;
  for (RecordVector::const_iterator B = EdgeVector.begin(),
         E = EdgeVector.end(); B != E; ++B) {
    const Record* Edge = *B;
    const std::string& NodeA = Edge->getValueAsString("a");
    const std::string& NodeB = Edge->getValueAsString("b");
    DagInit* Weight = Edge->getValueAsDag("weight");

    O << Indent1 << "G.insertEdge(\"" << NodeA << "\", ";

    if (isDagEmpty(Weight))
      O << "new SimpleEdge(\"" << NodeB << "\")";
    else
      O << "new Edge" << i << "()";

    O << ");\n";
    ++i;
  }

  O << "}\n\n";
}

/// ExtractHookNames - Extract the hook names from all instances of
/// $CALL(HookName) in the provided command line string. Helper
/// function used by FillInHookNames().
class ExtractHookNames {
  llvm::StringMap<unsigned>& HookNames_;
public:
  ExtractHookNames(llvm::StringMap<unsigned>& HookNames)
  : HookNames_(HookNames) {}

  void operator()(const Init* CmdLine) {
    StrVector cmds;
    TokenizeCmdline(InitPtrToString(CmdLine), cmds);
    for (StrVector::const_iterator B = cmds.begin(), E = cmds.end();
         B != E; ++B) {
      const std::string& cmd = *B;

      if (cmd == "$CALL") {
        unsigned NumArgs = 0;
        checkedIncrement(B, E, "Syntax error in $CALL invocation!");
        const std::string& HookName = *B;


        if (HookName.at(0) == ')')
          throw "$CALL invoked with no arguments!";

        while (++B != E && B->at(0) != ')') {
          ++NumArgs;
        }

        StringMap<unsigned>::const_iterator H = HookNames_.find(HookName);

        if (H != HookNames_.end() && H->second != NumArgs)
          throw "Overloading of hooks is not allowed. Overloaded hook: "
            + HookName;
        else
          HookNames_[HookName] = NumArgs;

      }
    }
  }
};

/// FillInHookNames - Actually extract the hook names from all command
/// line strings. Helper function used by EmitHookDeclarations().
void FillInHookNames(const ToolDescriptions& ToolDescs,
                     llvm::StringMap<unsigned>& HookNames)
{
  // For all command lines:
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
         E = ToolDescs.end(); B != E; ++B) {
    const ToolDescription& D = *(*B);
    if (!D.CmdLine)
      continue;
    if (dynamic_cast<StringInit*>(D.CmdLine))
      // This is a string.
      ExtractHookNames(HookNames).operator()(D.CmdLine);
    else
      // This is a 'case' construct.
      WalkCase(D.CmdLine, Id(), ExtractHookNames(HookNames));
  }
}

/// EmitHookDeclarations - Parse CmdLine fields of all the tool
/// property records and emit hook function declaration for each
/// instance of $CALL(HookName).
void EmitHookDeclarations(const ToolDescriptions& ToolDescs, raw_ostream& O) {
  llvm::StringMap<unsigned> HookNames;

  FillInHookNames(ToolDescs, HookNames);
  if (HookNames.empty())
    return;

  O << "namespace hooks {\n";
  for (StringMap<unsigned>::const_iterator B = HookNames.begin(),
         E = HookNames.end(); B != E; ++B) {
    O << Indent1 << "std::string " << B->first() << "(";

    for (unsigned i = 0, j = B->second; i < j; ++i) {
      O << "const char* Arg" << i << (i+1 == j ? "" : ", ");
    }

    O <<");\n";
  }
  O << "}\n\n";
}

/// EmitRegisterPlugin - Emit code to register this plugin.
void EmitRegisterPlugin(int Priority, raw_ostream& O) {
  O << "struct Plugin : public llvmc::BasePlugin {\n\n"
    << Indent1 << "int Priority() const { return " << Priority << "; }\n\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";
}

/// EmitIncludes - Emit necessary #include directives and some
/// additional declarations.
void EmitIncludes(raw_ostream& O) {
  O << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
    << "#include \"llvm/CompilerDriver/ForceLinkageMacros.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"

    << "inline const char* checkCString(const char* s)\n"
    << "{ return s == NULL ? \"\" : s; }\n\n";
}


/// PluginData - Holds all information about a plugin.
struct PluginData {
  OptionDescriptions OptDescs;
  bool HasSink;
  bool HasExterns;
  ToolDescriptions ToolDescs;
  RecordVector Edges;
  int Priority;
};

/// HasSink - Go through the list of tool descriptions and check if
/// there are any with the 'sink' property set.
bool HasSink(const ToolDescriptions& ToolDescs) {
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
         E = ToolDescs.end(); B != E; ++B)
    if ((*B)->isSink())
      return true;

  return false;
}

/// HasExterns - Go through the list of option descriptions and check
/// if there are any external options.
bool HasExterns(const OptionDescriptions& OptDescs) {
 for (OptionDescriptions::const_iterator B = OptDescs.begin(),
         E = OptDescs.end(); B != E; ++B)
    if (B->second.isExtern())
      return true;

  return false;
}

/// CollectPluginData - Collect tool and option properties,
/// compilation graph edges and plugin priority from the parse tree.
void CollectPluginData (const RecordKeeper& Records, PluginData& Data) {
  // Collect option properties.
  const RecordVector& OptionLists =
    Records.getAllDerivedDefinitions("OptionList");
  CollectOptionDescriptions(OptionLists.begin(), OptionLists.end(),
                            Data.OptDescs);

  // Collect tool properties.
  const RecordVector& Tools = Records.getAllDerivedDefinitions("Tool");
  CollectToolDescriptions(Tools.begin(), Tools.end(), Data.ToolDescs);
  Data.HasSink = HasSink(Data.ToolDescs);
  Data.HasExterns = HasExterns(Data.OptDescs);

  // Collect compilation graph edges.
  const RecordVector& CompilationGraphs =
    Records.getAllDerivedDefinitions("CompilationGraph");
  FillInEdgeVector(CompilationGraphs.begin(), CompilationGraphs.end(),
                   Data.Edges);

  // Calculate the priority of this plugin.
  const RecordVector& Priorities =
    Records.getAllDerivedDefinitions("PluginPriority");
  Data.Priority = CalculatePriority(Priorities.begin(), Priorities.end());
}

/// CheckPluginData - Perform some sanity checks on the collected data.
void CheckPluginData(PluginData& Data) {
  // Filter out all tools not mentioned in the compilation graph.
  FilterNotInGraph(Data.Edges, Data.ToolDescs);

  // Typecheck the compilation graph.
  TypecheckGraph(Data.Edges, Data.ToolDescs);

  // Check that there are no options without side effects (specified
  // only in the OptionList).
  CheckForSuperfluousOptions(Data.Edges, Data.ToolDescs, Data.OptDescs);

}

void EmitPluginCode(const PluginData& Data, raw_ostream& O) {
  // Emit file header.
  EmitIncludes(O);

  // Emit global option registration code.
  EmitOptionDefinitions(Data.OptDescs, Data.HasSink, Data.HasExterns, O);

  // Emit hook declarations.
  EmitHookDeclarations(Data.ToolDescs, O);

  O << "namespace {\n\n";

  // Emit PopulateLanguageMap() function
  // (a language map maps from file extensions to language names).
  EmitPopulateLanguageMap(Records, O);

  // Emit Tool classes.
  for (ToolDescriptions::const_iterator B = Data.ToolDescs.begin(),
         E = Data.ToolDescs.end(); B!=E; ++B)
    EmitToolClassDefinition(*(*B), Data.OptDescs, O);

  // Emit Edge# classes.
  EmitEdgeClasses(Data.Edges, Data.OptDescs, O);

  // Emit PopulateCompilationGraph() function.
  EmitPopulateCompilationGraph(Data.Edges, Data.ToolDescs, O);

  // Emit code for plugin registration.
  EmitRegisterPlugin(Data.Priority, O);

  O << "} // End anonymous namespace.\n\n";

  // Force linkage magic.
  O << "namespace llvmc {\n";
  O << "LLVMC_FORCE_LINKAGE_DECL(LLVMC_PLUGIN_NAME) {}\n";
  O << "}\n";

  // EOF
}


// End of anonymous namespace
}

/// run - The back-end entry point.
void LLVMCConfigurationEmitter::run (raw_ostream &O) {
  try {
  PluginData Data;

  CollectPluginData(Records, Data);
  CheckPluginData(Data);

  EmitSourceFileHeader("LLVMC Configuration Library", O);
  EmitPluginCode(Data, O);

  } catch (std::exception& Error) {
    throw Error.what() + std::string(" - usually this means a syntax error.");
  }
}
